stardis-test

Test Stardis behaviors
git clone git://git.meso-star.fr/stardis-test.git
Log | Files | Refs | README | LICENSE

sadist_lib_solid_sphere.c (11049B)


      1 /* Copyright (C) 2024 |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/stardis-prog-properties.h>
     17 
     18 #include <star/s3d.h>
     19 #include <star/ssp.h>
     20 #include <star/sstl.h>
     21 
     22 #include <rsys/cstr.h>
     23 #include <rsys/double3.h>
     24 #include <rsys/mem_allocator.h>
     25 
     26 #include <getopt.h>
     27 
     28 struct args {
     29   const char* stl;
     30   double lambda; /* [W/m/K] */
     31   double rho; /* [kg/m^3] */
     32   double cp; /* [J/K/kg] */
     33   double radius; /* [m/fp_to_meter] */
     34 };
     35 #define ARGS_DEFAULT__ {NULL,1,1,1,1}
     36 static const struct args ARGS_DEFAULT = ARGS_DEFAULT__;
     37 
     38 /* Define a solid sphere */
     39 struct solid_sphere {
     40   struct s3d_scene_view* view;
     41   double lambda; /* [W/m/K] */
     42   double rho; /* [kg/m^3] */
     43   double cp; /* [J/K/kg] */
     44   double radius; /* [m/fp_to_meter] */
     45 };
     46 #define SOLID_SPHERE_NULL__ {NULL,0,0,0,0}
     47 static const struct solid_sphere SOLID_SPHERE_NULL = SOLID_SPHERE_NULL__;
     48 
     49 /*******************************************************************************
     50  * Helper functions
     51  ******************************************************************************/
     52 static void
     53 get_indices(const unsigned itri, unsigned ids[3], void* ctx)
     54 {
     55   const struct sstl_desc* desc = ctx;
     56   ASSERT(desc && itri < desc->triangles_count);
     57   ids[0] = desc->indices[itri*3+0];
     58   ids[1] = desc->indices[itri*3+1];
     59   ids[2] = desc->indices[itri*3+2];
     60 }
     61 
     62 static void
     63 get_position(const unsigned ivert, float pos[3], void* ctx)
     64 {
     65   const struct sstl_desc* desc = ctx;
     66   ASSERT(desc && ivert < desc->vertices_count);
     67   pos[0] = desc->vertices[ivert*3+0];
     68   pos[1] = desc->vertices[ivert*3+1];
     69   pos[2] = desc->vertices[ivert*3+2];
     70 }
     71 
     72 static struct s3d_scene_view*
     73 create_scene_view(const char* filename)
     74 {
     75   /* Star-STL */
     76   struct sstl_desc desc;
     77   struct sstl* sstl = NULL;
     78 
     79   /* Star3D */
     80   struct s3d_vertex_data vdata = S3D_VERTEX_DATA_NULL;
     81   struct s3d_device* dev = NULL;
     82   struct s3d_scene* scn = NULL;
     83   struct s3d_shape* shape = NULL;
     84   struct s3d_scene_view* view = NULL;
     85 
     86   res_T res = RES_OK;
     87   ASSERT(filename);
     88 
     89   if((res = sstl_create(NULL, NULL, 1, &sstl)) != RES_OK) goto error;
     90   if((res = sstl_load(sstl, filename)) != RES_OK) goto error;
     91   if((res = sstl_get_desc(sstl, &desc)) != RES_OK) goto error;
     92 
     93   if((res = s3d_device_create(NULL, NULL, 0, &dev)) != RES_OK) goto error;
     94   if((res = s3d_scene_create(dev, &scn)) != RES_OK) goto error;
     95   if((res = s3d_shape_create_mesh(dev, &shape)) != RES_OK) goto error;
     96   if((res = s3d_scene_attach_shape(scn, shape)) != RES_OK) goto error;
     97 
     98   vdata.usage = S3D_POSITION;
     99   vdata.type = S3D_FLOAT3;
    100   vdata.get = get_position;
    101   res = s3d_mesh_setup_indexed_vertices(shape,
    102     (unsigned int)desc.triangles_count, get_indices,
    103     (unsigned int)desc.vertices_count, &vdata, 1, &desc);
    104   if(res != RES_OK) goto error;
    105 
    106   res = s3d_scene_view_create(scn, S3D_TRACE|S3D_GET_PRIMITIVE, &view);
    107   if(res != RES_OK) goto error;
    108 
    109 exit:
    110   if(sstl) SSTL(ref_put(sstl));
    111   if(dev) S3D(device_ref_put(dev));
    112   if(scn) S3D(scene_ref_put(scn));
    113   if(shape) S3D(shape_ref_put(shape));
    114   return view;
    115 error:
    116   if(view) { S3D(scene_view_ref_put(view)); view = NULL; }
    117   goto exit;
    118 }
    119 
    120 static void
    121 print_usage(FILE* stream, const char* name)
    122 {
    123   ASSERT(name);
    124   fprintf(stream,
    125     "usage: %s -m mesh [-c capa] [-h] [-l lambda] [-R radius] [-r rho]\n",
    126     name);
    127 }
    128 
    129 static res_T
    130 parse_args
    131   (const struct stardis_description_create_context* ctx,
    132    struct args* args,
    133    const int argc,
    134    char* argv[])
    135 {
    136   int opt = 0;
    137   res_T res = RES_OK;
    138 
    139   /* Check pre-conditions */
    140   ASSERT(ctx && args);
    141   *args = ARGS_DEFAULT;
    142 
    143   optind = 1;
    144   while((opt = getopt(argc, argv, "c:hl:m:R:r:")) != -1) {
    145     switch(opt) {
    146       case 'c':
    147         res = cstr_to_double(optarg, &args->cp);
    148         if(res == RES_OK && args->cp <= 0) res = RES_BAD_ARG;
    149         break;
    150       case 'h':
    151         print_usage(stdout, argv[0]);
    152         break;
    153       case 'l':
    154         res = cstr_to_double(optarg, &args->lambda);
    155         if(res == RES_OK && args->lambda <= 0) res = RES_BAD_ARG;
    156         break;
    157       case 'm':
    158         args->stl = optarg;
    159         break;
    160       case 'R':
    161         res = cstr_to_double(optarg, &args->radius);
    162         if(res == RES_OK && args->radius <= 0) res = RES_BAD_ARG;
    163         break;
    164       case 'r':
    165         res = cstr_to_double(optarg, &args->rho);
    166         if(res == RES_OK && args->rho <= 0) res = RES_BAD_ARG;
    167         break;
    168       default: res = RES_BAD_ARG; break;
    169     }
    170     if(res != RES_OK) {
    171       if(optarg) {
    172         fprintf(stderr, "%s: invalid option argument '%s' -- '%c'\n",
    173           ctx->name, optarg, opt);
    174       }
    175       goto error;
    176     }
    177   }
    178 
    179   if(!args->stl) {
    180     fprintf(stderr, "%s: missing mesh -- option '-m'\n", argv[0]);
    181     res = RES_BAD_ARG;
    182     goto error;
    183   }
    184 
    185 exit:
    186   return res;
    187 error:
    188   goto exit;
    189 }
    190 
    191 /*******************************************************************************
    192  * Create data
    193  ******************************************************************************/
    194 void*
    195 stardis_create_data
    196   (const struct stardis_description_create_context *ctx,
    197    void* libdata,
    198    size_t argc,
    199    char* argv[])
    200 {
    201   struct args args = ARGS_DEFAULT__;
    202   struct solid_sphere* solid = NULL;
    203   res_T res = RES_OK;
    204   (void)libdata;
    205 
    206   solid = mem_alloc(sizeof(*solid));
    207   if(!solid) {
    208     fprintf(stderr, "%s:%d: error allocating the solid sphere.\n",
    209       __FILE__, __LINE__);
    210     goto error;
    211   }
    212   *solid = SOLID_SPHERE_NULL;
    213 
    214   res = parse_args(ctx, &args, (int)argc, argv);
    215   if(res != RES_OK) goto error;
    216 
    217   solid->lambda = args.lambda;
    218   solid->rho = args.rho;
    219   solid->cp = args.cp;
    220   solid->radius = args.radius;
    221 
    222   if(!(solid->view = create_scene_view(args.stl))) goto error;
    223 
    224 exit:
    225   return solid;
    226 error:
    227   if(solid) {
    228     stardis_release_data(solid);
    229     solid = NULL;
    230   }
    231   goto exit;
    232 }
    233 
    234 void
    235 stardis_release_data(void* data)
    236 {
    237   struct solid_sphere* solid = data;
    238   ASSERT(solid);
    239   if(solid->view) S3D(scene_view_ref_put(solid->view));
    240   mem_rm(solid);
    241 }
    242 
    243 /*******************************************************************************
    244  * Solid properties
    245  ******************************************************************************/
    246 double
    247 stardis_calorific_capacity(const struct stardis_vertex* vtx, void* data)
    248 {
    249   const struct solid_sphere* sphere = data;
    250   (void)vtx;
    251   return sphere->cp;
    252 }
    253 
    254 double
    255 stardis_volumic_mass(const struct stardis_vertex* vtx, void* data)
    256 {
    257   const struct solid_sphere* sphere = data;
    258   (void)vtx;
    259   return sphere->rho;
    260 }
    261 
    262 double
    263 stardis_conductivity(const struct stardis_vertex* vtx, void* data)
    264 {
    265   const struct solid_sphere* sphere = data;
    266   (void)vtx;
    267   return sphere->lambda;
    268 }
    269 
    270 double
    271 stardis_delta_solid(const struct stardis_vertex* vtx, void* data)
    272 {
    273   const struct solid_sphere* sphere = data;
    274   (void)vtx;
    275   return sphere->radius/20.0;
    276 }
    277 
    278 double
    279 stardis_volumic_power(const struct stardis_vertex* vtx, void* data)
    280 {
    281   (void)vtx, (void)data;
    282   return STARDIS_VOLUMIC_POWER_NONE;
    283 }
    284 
    285 double
    286 stardis_medium_temperature(const struct stardis_vertex* vtx, void* data)
    287 {
    288   (void)vtx, (void)data;
    289   return STARDIS_TEMPERATURE_NONE;
    290 }
    291 
    292 int
    293 stardis_sample_conductive_path
    294   (struct sdis_scene* scn,
    295    struct ssp_rng* rng,
    296    struct stardis_path* path,
    297    void* data)
    298 {
    299   const struct solid_sphere* sphere = data;
    300   struct s3d_hit hit = S3D_HIT_NULL;
    301   struct s3d_attrib attr0, attr1, attr2;
    302 
    303   double pos[3];
    304   double epsilon = 0;
    305   ASSERT(scn && rng && path && data);
    306   (void)scn;
    307 
    308   epsilon = sphere->radius * 1.e-6; /* Epsilon shell */
    309 
    310   d3_set(pos, path->vtx.P);
    311 
    312   do {
    313     /* Distance from the geometry center to the current position */
    314     const double dst = d3_len(pos);
    315 
    316     double dir[3] = {0,0,0};
    317     double r = 0; /* Radius */
    318 
    319     r = sphere->radius - dst;
    320     CHK(dst > 0);
    321 
    322     if(r > epsilon) {
    323       /* Uniformly sample a new position on the surrounding sphere */
    324       ssp_ran_sphere_uniform(rng, dir, NULL);
    325 
    326       /* Move to the new position */
    327       d3_muld(dir, dir, r);
    328       d3_add(pos, pos, dir);
    329 
    330     /* The current position is in the epsilon shell:
    331      * move it to the nearest interface position */
    332     } else {
    333       float posf[3];
    334 
    335       d3_set(dir, pos);
    336       d3_normalize(dir, dir);
    337       d3_muld(pos, dir, sphere->radius);
    338 
    339       /* Map the position to the sphere geometry */
    340       f3_set_d3(posf, pos);
    341       S3D(scene_view_closest_point(sphere->view, posf, (float)INF, NULL, &hit));
    342     }
    343 
    344   /* The calculation is performed in steady state, so the path necessarily stops
    345    * at a boundary */
    346   } while(S3D_HIT_NONE(&hit));
    347 
    348   /* Setup the path state */
    349   d3_set(path->vtx.P, pos);
    350   path->weight = 0;
    351   path->at_limit = 0;
    352 
    353   /* Configure the intersecting primitive. The vertices must be exactly the same
    354    * (i.e. bit-compatible) as those used internally by Stardis, as they are used
    355    * as the key to retrieve the corresponding Stardis triangle. Note that
    356    * Stardis also uses Star-STL internally to load its geometry. As a result,
    357    * the in-memory representation of the loaded data is the same between Stardis
    358    * and the current code, i.e. single-precision floating point. And Star-3D
    359    * also uses the same representation. We can therefore use Star-3D data
    360    * directly to define the coordinates of the vertices of the intersecting
    361    * primitive */
    362   S3D(triangle_get_vertex_attrib(&hit.prim, 0, S3D_POSITION, &attr0));
    363   S3D(triangle_get_vertex_attrib(&hit.prim, 1, S3D_POSITION, &attr1));
    364   S3D(triangle_get_vertex_attrib(&hit.prim, 2, S3D_POSITION, &attr2));
    365   d3_set_f3(path->tri.vtx0, attr0.value);
    366   d3_set_f3(path->tri.vtx1, attr1.value);
    367   d3_set_f3(path->tri.vtx2, attr2.value);
    368 
    369   return RES_OK;
    370 }
    371 
    372 /*******************************************************************************
    373  * Legal notices
    374  ******************************************************************************/
    375 const char*
    376 get_copyright_notice(void* data)
    377 {
    378   (void)data; /* Avoid "unused variable" warnings */
    379   return "Copyright (C) 2024 |Méso|Star> (contact@meso-star.com)";
    380 }
    381 
    382 const char*
    383 get_license_short(void* data)
    384 {
    385   (void)data; /* Avoid "unused variable" warnings */
    386   return "GNU GPL version 3 or later <http://www.gnu.org/licenses/>";
    387 }
    388 
    389 const char*
    390 get_license_text(void* data)
    391 {
    392   (void)data; /* Avoid "unused variable" warnings */
    393   return
    394     "This is free software released under the GPL v3+ license: GNU GPL\n"
    395     "version 3 or later. You are welcome to redistribute it under certain\n"
    396     "conditions; refer to <http://www.gnu.org/licenses/> for details.";
    397 }