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 }