stardis

Perform coupled heat transfer calculations
git clone git://git.meso-star.fr/stardis.git
Log | Files | Refs | README | LICENSE

stardis-solid-prog.c (7911B)


      1 /* Copyright (C) 2018-2025 |Méso|Star> (contact@meso-star.com)
      2  *
      3  * This program is free software: you can redistribute it and/or modify
      4  * it under the terms of the GNU General Public License as published by
      5  * the Free Software Foundation, either version 3 of the License, or
      6  * (at your option) any later version.
      7  *
      8  * This program is distributed in the hope that it will be useful,
      9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
     11  * GNU General Public License for more details.
     12  *
     13  * You should have received a copy of the GNU General Public License
     14  * along with this program. If not, see <http://www.gnu.org/licenses/>. */
     15 
     16 #include "stardis-solid-prog.h"
     17 #include "stardis-prog-properties.h"
     18 #include "stardis-app.h"
     19 
     20 #include <rsys/mem_allocator.h>
     21 
     22 #include <sdis.h>
     23 
     24 #include <limits.h>
     25 
     26 /*******************************************************************************
     27  * Local Functions
     28  ******************************************************************************/
     29 
     30 static double
     31 solid_prog_get_thermal_conductivity
     32   (const struct sdis_rwalk_vertex* vtx,
     33    struct sdis_data* data)
     34 {
     35   const struct solid_prog* const* solid_props = sdis_data_cget(data);
     36   struct stardis_vertex v;
     37   d3_set(v.P, vtx->P);
     38   v.time = vtx->time;
     39   return (*solid_props)->lambda(&v, (*solid_props)->prog_data);
     40 }
     41 
     42 static double
     43 solid_prog_get_volumic_mass
     44   (const struct sdis_rwalk_vertex* vtx,
     45    struct sdis_data* data)
     46 {
     47   const struct solid_prog* const* solid_props = sdis_data_cget(data);
     48   struct stardis_vertex v;
     49   d3_set(v.P, vtx->P);
     50   v.time = vtx->time;
     51   return (*solid_props)->rho(&v, (*solid_props)->prog_data);
     52 }
     53 
     54 static double
     55 solid_prog_get_calorific_capacity
     56   (const struct sdis_rwalk_vertex* vtx,
     57    struct sdis_data* data)
     58 {
     59   const struct solid_prog* const* solid_props = sdis_data_cget(data);
     60   struct stardis_vertex v;
     61   d3_set(v.P, vtx->P);
     62   v.time = vtx->time;
     63   return (*solid_props)->cp(&v, (*solid_props)->prog_data);
     64 }
     65 
     66 static double
     67 solid_prog_get_delta
     68   (const struct sdis_rwalk_vertex* vtx,
     69    struct sdis_data* data)
     70 {
     71   const struct solid_prog* const* solid_props = sdis_data_cget(data);
     72   struct stardis_vertex v;
     73   d3_set(v.P, vtx->P);
     74   v.time = vtx->time;
     75   return (*solid_props)->delta(&v, (*solid_props)->prog_data);
     76 }
     77 
     78 static double
     79 solid_prog_get_volumic_power
     80   (const struct sdis_rwalk_vertex* vtx,
     81    struct sdis_data* data)
     82 {
     83   const struct solid_prog* const* solid_props = sdis_data_cget(data);
     84   struct stardis_vertex v;
     85   double power;
     86   d3_set(v.P, vtx->P);
     87   v.time = vtx->time;
     88   power = (*solid_props)->vpower(&v, (*solid_props)->prog_data);
     89   return power != STARDIS_VOLUMIC_POWER_NONE ? power : SDIS_VOLUMIC_POWER_NONE;
     90 }
     91 
     92 static double
     93 solid_prog_get_temperature
     94   (const struct sdis_rwalk_vertex* vtx,
     95    struct sdis_data* data)
     96 {
     97   const struct solid_prog* const* solid_props = sdis_data_cget(data);
     98   struct stardis_vertex v;
     99   double temp;
    100   d3_set(v.P, vtx->P);
    101   v.time = vtx->time;
    102   temp = (*solid_props)->temp(&v, (*solid_props)->prog_data);
    103   return STARDIS_TEMPERATURE_IS_KNOWN(temp) ? temp : SDIS_TEMPERATURE_NONE;
    104 }
    105 
    106 static res_T
    107 solid_prog_sample_path
    108   (struct sdis_scene* scn,
    109    struct ssp_rng* rng,
    110    struct sdis_path* path,
    111    struct sdis_data* data)
    112 {
    113   const struct solid_prog* const* solid_props = sdis_data_cget(data);
    114   struct stardis_path p = STARDIS_PATH_NULL;
    115   int err = 0;
    116   res_T res = RES_OK;
    117 
    118   d3_set(p.vtx.P, path->vtx.P);
    119   p.vtx.time = path->vtx.time;
    120 
    121   err = (*solid_props)->sample_path(scn, rng, &p, (*solid_props)->prog_data);
    122   if(err) { res = RES_UNKNOWN_ERR; goto error; }
    123 
    124   d3_set(path->vtx.P, p.vtx.P);
    125   path->vtx.time = p.vtx.time;
    126   path->weight = p.weight;
    127   path->at_limit = p.at_limit;
    128 
    129   if(!STARDIS_TRIANGLE_NONE(&p.tri)) {
    130     struct sdis_primkey key = SDIS_PRIMKEY_NULL;
    131 
    132     sdis_primkey_setup(&key, p.tri.vtx0, p.tri.vtx1, p.tri.vtx2);
    133     res = sdis_scene_get_s3d_primitive(scn, &key, &path->prim_3d);
    134 
    135     /* In fact, we'd like to log an error notifying us that the returned
    136      * triangle doesn't exist in Stardis. But there's no easy way to retrieve
    137      * the logger since the program has no reference to Stardis. This lack stems
    138      * from design choices where internal data structures are not managed by
    139      * reference and don't take a reference on the Stardis structure. In any
    140      * case, until stardis' internal data structures have been thoroughly
    141      * redesigned, we're only returning an error */
    142     if(res != RES_OK) goto error;
    143   }
    144 
    145 exit:
    146   return res;
    147 error:
    148   goto exit;
    149 }
    150 
    151 /*******************************************************************************
    152  * Public Functions
    153  ******************************************************************************/
    154 
    155 res_T
    156 create_solver_solid_prog
    157   (struct stardis* stardis,
    158    const struct solid_prog* solid_props)
    159 {
    160   res_T res = RES_OK;
    161   struct sdis_solid_shader solid_shader = SDIS_SOLID_SHADER_NULL;
    162   struct sdis_data* data = NULL;
    163   const struct solid_prog** props;
    164 
    165   ASSERT(stardis && solid_props);
    166   solid_shader.calorific_capacity = solid_prog_get_calorific_capacity;
    167   solid_shader.thermal_conductivity = solid_prog_get_thermal_conductivity;
    168   solid_shader.volumic_mass = solid_prog_get_volumic_mass;
    169   solid_shader.delta = solid_prog_get_delta;
    170   solid_shader.volumic_power = solid_prog_get_volumic_power;
    171   solid_shader.temperature = solid_prog_get_temperature;
    172   solid_shader.t0 = stardis->initial_time;
    173   if(solid_props->sample_path) {
    174     solid_shader.sample_path = solid_prog_sample_path;
    175   }
    176   ERR(sdis_data_create(stardis->dev, sizeof(struct solid_prog*),
    177     ALIGNOF(struct solid_prog*), NULL, &data));
    178 
    179   props = sdis_data_get(data); /* Fetch the allocated memory space */
    180   *props = solid_props;
    181   if(solid_props->solid_id >= darray_media_ptr_size_get(&stardis->media)) {
    182     ERR(darray_media_ptr_resize(&stardis->media, solid_props->solid_id + 1));
    183   }
    184   ASSERT(!darray_media_ptr_data_get(&stardis->media)[solid_props->solid_id]);
    185   ERR(sdis_solid_create(stardis->dev, &solid_shader, data,
    186     darray_media_ptr_data_get(&stardis->media) + solid_props->solid_id));
    187 
    188 end:
    189   if(data) SDIS(data_ref_put(data));
    190   return res;
    191 error:
    192   goto end;
    193 }
    194 
    195 res_T
    196 init_solid_prog(struct mem_allocator* allocator, struct solid_prog** dst)
    197 {
    198   res_T res = RES_OK;
    199   int str_initialized = 0;
    200   ASSERT(allocator && dst && *dst == NULL);
    201   *dst = MEM_CALLOC(allocator, 1, sizeof(**dst));
    202   if(! *dst) {
    203     res = RES_MEM_ERR;
    204     goto error;
    205   }
    206   str_init(allocator, &(*dst)->name);
    207   str_init(allocator, &(*dst)->prog_name);
    208   str_initialized = 1;
    209   (*dst)->desc_id = UINT_MAX;
    210   (*dst)->solid_id = UINT_MAX;
    211 end:
    212   return res;
    213 error:
    214   if(str_initialized) {
    215     str_release(&(*dst)->name);
    216     str_release(&(*dst)->prog_name);
    217   }
    218   if(*dst) MEM_RM(allocator, *dst);
    219   goto end;
    220 }
    221 
    222 void
    223 release_solid_prog
    224   (struct solid_prog* solid,
    225    struct mem_allocator* allocator)
    226 {
    227   size_t i;
    228   ASSERT(solid && allocator);
    229   str_release(&solid->name);
    230   str_release(&solid->prog_name);
    231   if(solid->prog_data)
    232     solid->release(solid->prog_data);
    233   for(i = 0; i < solid->argc; i++) MEM_RM(allocator, solid->argv[i]);
    234   MEM_RM(allocator, solid->argv);
    235   /* library_close call is managed at lib_data level */
    236   MEM_RM(allocator, solid);
    237 }
    238 
    239 res_T
    240 str_print_solid_prog(struct str* str, const struct solid_prog* f)
    241 {
    242   res_T res = RES_OK;
    243   ASSERT(str && f);
    244   ASSERT(f->argc >= 1); /* At least one argument which is the program name */
    245 
    246   ERR(str_append_printf(str,
    247     "programmed solid '%s': lib='%s', it is medium %u)",
    248     str_cget(&f->name), str_cget(&f->prog_name), f->solid_id));
    249   if(f->argc > 1) {
    250     size_t i;
    251     ERR(str_append_printf(str, ", provided arguments:\n"));
    252     for(i = 1; i < f->argc; i++) {
    253       ERR(str_append_printf(str, (i+1 == f->argc ? "\t%s" : "\t%s\n"), f->argv[i]));
    254     }
    255   }
    256 end:
    257   return res;
    258 error:
    259   goto end;
    260 }