stardis-solver

Solve coupled heat transfers
git clone git://git.meso-star.fr/stardis-solver.git
Log | Files | Refs | README | LICENSE

test_sdis_draw_external_flux.c (13831B)


      1 /* Copyright (C) 2016-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 "sdis.h"
     17 #include "test_sdis_mesh.h"
     18 #include "test_sdis_utils.h"
     19 
     20 #include <star/s3dut.h>
     21 
     22 #define IMG_WIDTH 320
     23 #define IMG_HEIGHT 240
     24 #define IMG_SPP 64
     25 #define SOURCE_POWER 30e6 /* W */
     26 #define EMISSIVITY 0.5
     27 #define T_RAD 300 /* [K] */
     28 #define T_REF 300 /* [K] */
     29 
     30 /*
     31  * The system consists of a floor (i.e. a parallelepiped), a super-form floating
     32  * above it and a spherical external source. The test attempts to render the
     33  * scene and thus verify the entire sampling of conductive-radiative paths
     34  * coupled to an external flux from the external source.
     35  */
     36 
     37 /*******************************************************************************
     38  * Geometries
     39  ******************************************************************************/
     40 static void
     41 mesh_add_super_shape(struct mesh* mesh)
     42 {
     43   struct s3dut_mesh* sshape = NULL;
     44   struct s3dut_mesh_data sshape_data;
     45   struct s3dut_super_formula f0 = S3DUT_SUPER_FORMULA_NULL;
     46   struct s3dut_super_formula f1 = S3DUT_SUPER_FORMULA_NULL;
     47   const double radius = 1;
     48   const unsigned nslices = 256;
     49 
     50   f0.A = 1.5; f0.B = 1; f0.M = 11.0; f0.N0 = 1; f0.N1 = 1; f0.N2 = 2.0;
     51   f1.A = 1.0; f1.B = 2; f1.M =  3.6; f1.N0 = 1; f1.N1 = 2; f1.N2 = 0.7;
     52   OK(s3dut_create_super_shape(NULL, &f0, &f1, radius, nslices, nslices/2, &sshape));
     53   OK(s3dut_mesh_get_data(sshape, &sshape_data));
     54   mesh_append(mesh, sshape_data.positions, sshape_data.nvertices,
     55     sshape_data.indices, sshape_data.nprimitives, NULL);
     56   OK(s3dut_mesh_ref_put(sshape));
     57 }
     58 
     59 static void
     60 mesh_add_ground(struct mesh* mesh)
     61 {
     62   #define DEPTH 2.0
     63   const double translate[3] = {0, 0, -DEPTH-1};
     64 
     65   struct s3dut_mesh* ground = NULL;
     66   struct s3dut_mesh_data ground_data;
     67 
     68   OK(s3dut_create_cuboid(NULL, 20, 20, DEPTH, &ground));
     69   OK(s3dut_mesh_get_data(ground, &ground_data));
     70   mesh_append(mesh, ground_data.positions, ground_data.nvertices,
     71     ground_data.indices, ground_data.nprimitives, translate);
     72   OK(s3dut_mesh_ref_put(ground));
     73   #undef DEPTH
     74 }
     75 
     76 /*******************************************************************************
     77  * Media & interface
     78  ******************************************************************************/
     79 #define MEDIUM_PROP(Type, Prop, Val)                                           \
     80   static double                                                                \
     81   Type##_get_##Prop                                                            \
     82     (const struct sdis_rwalk_vertex* vtx,                                      \
     83      struct sdis_data* data)                                                   \
     84   {                                                                            \
     85     (void)vtx, (void)data; /* Avoid the "unused variable" warning */           \
     86     return Val;                                                                \
     87   }
     88 MEDIUM_PROP(solid, calorific_capacity, 500.0) /* [J/K/Kg] */
     89 MEDIUM_PROP(solid, thermal_conductivity, 25.0) /* [W/m/K] */
     90 MEDIUM_PROP(solid, volumic_mass, 7500.0) /* [kg/m^3] */
     91 MEDIUM_PROP(solid, temperature, 310) /* [K] */
     92 MEDIUM_PROP(solid, delta, 1.0/20.0) /* [m] */
     93 MEDIUM_PROP(fluid, calorific_capacity, 2.0) /* [J/K/Kg] */
     94 MEDIUM_PROP(fluid, volumic_mass, 25.0) /* |kg/m^3] */
     95 MEDIUM_PROP(fluid, temperature, SDIS_TEMPERATURE_NONE) /* [K] */
     96 #undef MEDIUM_PROP
     97 
     98 static struct sdis_medium*
     99 create_solid(struct sdis_device* sdis)
    100 {
    101   struct sdis_solid_shader shader = SDIS_SOLID_SHADER_NULL;
    102   struct sdis_medium* solid = NULL;
    103 
    104   shader.calorific_capacity = solid_get_calorific_capacity;
    105   shader.thermal_conductivity = solid_get_thermal_conductivity;
    106   shader.volumic_mass = solid_get_volumic_mass;
    107   shader.delta = solid_get_delta;
    108   shader.temperature = solid_get_temperature;
    109   OK(sdis_solid_create(sdis, &shader, NULL, &solid));
    110   return solid;
    111 }
    112 
    113 static struct sdis_medium*
    114 create_fluid(struct sdis_device* sdis)
    115 {
    116   struct sdis_fluid_shader shader = SDIS_FLUID_SHADER_NULL;
    117   struct sdis_medium* fluid = NULL;
    118 
    119   shader.calorific_capacity = fluid_get_calorific_capacity;
    120   shader.volumic_mass = fluid_get_volumic_mass;
    121   shader.temperature = fluid_get_temperature;
    122   OK(sdis_fluid_create(sdis, &shader, NULL, &fluid));
    123   return fluid;
    124 }
    125 
    126 static double
    127 interface_get_reference_temperature
    128   (const struct sdis_interface_fragment* frag,
    129    struct sdis_data* data)
    130 {
    131   (void)frag, (void)data; /* Avoid the "unused variable" warning */
    132   return T_REF;
    133 }
    134 
    135 static double
    136 interface_get_temperature
    137   (const struct sdis_interface_fragment* frag,
    138    struct sdis_data* data)
    139 {
    140   (void)frag, (void)data;/* Avoid the "unused variable" warning */
    141   return SDIS_TEMPERATURE_NONE;
    142 }
    143 
    144 static double
    145 interface_get_emissivity
    146   (const struct sdis_interface_fragment* frag,
    147    const unsigned source_id,
    148    struct sdis_data* data)
    149 {
    150   /* Avoid the "unused variable" warning */
    151   (void)frag, (void)source_id, (void)data;
    152   return EMISSIVITY;
    153 }
    154 
    155 static struct sdis_interface*
    156 create_interface
    157   (struct sdis_device* sdis,
    158    struct sdis_medium* front,
    159    struct sdis_medium* back)
    160 {
    161   struct sdis_interface* interf = NULL;
    162   struct sdis_interface_shader shader = SDIS_INTERFACE_SHADER_NULL;
    163 
    164   shader.front.temperature = interface_get_temperature;
    165   shader.front.reference_temperature = interface_get_reference_temperature;
    166   shader.front.emissivity = interface_get_emissivity;
    167   shader.back.temperature = interface_get_temperature;
    168   OK(sdis_interface_create(sdis, front, back, &shader, NULL, &interf));
    169   return interf;
    170 }
    171 
    172 /*******************************************************************************
    173  * External source
    174  ******************************************************************************/
    175 static void
    176 source_get_position
    177   (const double time,
    178    double pos[3],
    179    struct sdis_data* data)
    180 {
    181   (void)time, (void)data; /* Avoid the "unusued variable" warning */
    182   pos[0] = 5.0;
    183   pos[1] = 5.0;
    184   pos[2] = 5.0;
    185 }
    186 
    187 static double
    188 source_get_power(const double time, struct sdis_data* data)
    189 {
    190   (void)time, (void)data; /* Avoid the "unusued variable" warning */
    191   return SOURCE_POWER; /* [W] */
    192 }
    193 
    194 static double
    195 source_get_diffuse_radiance
    196   (const double time,
    197    const double dir[3],
    198    struct sdis_data* data)
    199 {
    200   (void)time, (void)data; /* Avoid the "unusued variable" warning */
    201   CHK(d3_is_normalized(dir));
    202   return 50;
    203 }
    204 
    205 static struct sdis_source*
    206 create_source(struct sdis_device* sdis)
    207 {
    208   struct sdis_spherical_source_shader shader = SDIS_SPHERICAL_SOURCE_SHADER_NULL;
    209   struct sdis_source* source = NULL;
    210 
    211   shader.position = source_get_position;
    212   shader.power = source_get_power;
    213   shader.diffuse_radiance = source_get_diffuse_radiance;
    214   shader.radius = 3e-1; /* [m] */
    215   OK(sdis_spherical_source_create(sdis, &shader, NULL, &source));
    216   return source;
    217 }
    218 
    219 /*******************************************************************************
    220  * Radiative environment
    221  ******************************************************************************/
    222 static double
    223 radenv_get_temperature
    224   (const struct sdis_radiative_ray* ray,
    225    struct sdis_data* data)
    226 {
    227   (void)ray, (void)data;
    228   return T_RAD;
    229 }
    230 
    231 static double
    232 radenv_get_reference_temperature
    233   (const struct sdis_radiative_ray* ray,
    234    struct sdis_data* data)
    235 {
    236   (void)ray, (void)data;
    237   return T_REF;
    238 }
    239 
    240 static struct sdis_radiative_env*
    241 create_radenv(struct sdis_device* sdis)
    242 {
    243   struct sdis_radiative_env_shader shader = SDIS_RADIATIVE_ENV_SHADER_NULL;
    244   struct sdis_radiative_env* radenv = NULL;
    245 
    246   shader.temperature = radenv_get_temperature;
    247   shader.reference_temperature = radenv_get_reference_temperature;
    248   OK(sdis_radiative_env_create(sdis, &shader, NULL, &radenv));
    249   return radenv;
    250 }
    251 
    252 /*******************************************************************************
    253  * Scene, i.e. the system to simulate
    254  ******************************************************************************/
    255 struct scene_context {
    256   const struct mesh* mesh;
    257   struct sdis_interface* interf;
    258 };
    259 static const struct scene_context SCENE_CONTEXT_NULL = {NULL, NULL};
    260 
    261 static void
    262 scene_get_indices(const size_t itri, size_t ids[3], void* ctx)
    263 {
    264   struct scene_context* context = ctx;
    265   CHK(ids && context && itri < mesh_ntriangles(context->mesh));
    266   ids[0] = (unsigned)context->mesh->indices[itri*3+0];
    267   ids[1] = (unsigned)context->mesh->indices[itri*3+1];
    268   ids[2] = (unsigned)context->mesh->indices[itri*3+2];
    269 }
    270 
    271 static void
    272 scene_get_interface(const size_t itri, struct sdis_interface** interf, void* ctx)
    273 {
    274   struct scene_context* context = ctx;
    275   CHK(interf && context && itri < mesh_ntriangles(context->mesh));
    276   *interf = context->interf;
    277 }
    278 
    279 static void
    280 scene_get_position(const size_t ivert, double pos[3], void* ctx)
    281 {
    282   struct scene_context* context = ctx;
    283   CHK(pos && context && ivert < mesh_nvertices(context->mesh));
    284   pos[0] = context->mesh->positions[ivert*3+0];
    285   pos[1] = context->mesh->positions[ivert*3+1];
    286   pos[2] = context->mesh->positions[ivert*3+2];
    287 }
    288 
    289 static struct sdis_scene*
    290 create_scene
    291   (struct sdis_device* sdis,
    292    const struct mesh* mesh,
    293    struct sdis_interface* interf,
    294    struct sdis_source* source,
    295    struct sdis_radiative_env* radenv)
    296 {
    297   struct sdis_scene* scn = NULL;
    298   struct sdis_scene_create_args scn_args = SDIS_SCENE_CREATE_ARGS_DEFAULT;
    299   struct scene_context context = SCENE_CONTEXT_NULL;
    300 
    301   context.mesh = mesh;
    302   context.interf = interf;
    303 
    304   scn_args.get_indices = scene_get_indices;
    305   scn_args.get_interface = scene_get_interface;
    306   scn_args.get_position = scene_get_position;
    307   scn_args.nprimitives = mesh_ntriangles(mesh);
    308   scn_args.nvertices = mesh_nvertices(mesh);
    309   scn_args.t_range[0] = MMIN(T_RAD, T_REF);
    310   scn_args.t_range[1] = MMAX(T_RAD, T_REF);
    311   scn_args.source = source;
    312   scn_args.radenv = radenv;
    313   scn_args.context = &context;
    314   OK(sdis_scene_create(sdis, &scn_args, &scn));
    315   return scn;
    316 }
    317 
    318 /*******************************************************************************
    319  * Rendering point of view
    320  ******************************************************************************/
    321 static struct sdis_camera*
    322 create_camera(struct sdis_device* sdis)
    323 {
    324   const double pos[3] = {-3.81, 11.23, 5.29};
    325   const double tgt[3] = {-0.46, 0, -0.32};
    326   const double up[3] = {0, 0, 1};
    327   struct sdis_camera* cam = NULL;
    328 
    329   OK(sdis_camera_create(sdis, &cam));
    330   OK(sdis_camera_set_proj_ratio(cam, (double)IMG_WIDTH/(double)IMG_HEIGHT));
    331   OK(sdis_camera_set_fov(cam, MDEG2RAD(30)));
    332   OK(sdis_camera_look_at(cam, pos, tgt, up));
    333   return cam;
    334 }
    335 
    336 /*******************************************************************************
    337  * Draw the submitted scene
    338  ******************************************************************************/
    339 /* Write an image in htrdr-image(5) format */
    340 static void
    341 write_image(FILE* stream, struct sdis_estimator_buffer* image)
    342 {
    343   size_t x, y;
    344 
    345   /* Header */
    346   fprintf(stream, "%d %d\n", IMG_WIDTH, IMG_HEIGHT);
    347 
    348   /* Pixels ordered by row */
    349   FOR_EACH(y, 0, IMG_HEIGHT) {
    350     FOR_EACH(x, 0, IMG_WIDTH) {
    351       const struct sdis_estimator* pixel = NULL;
    352       struct sdis_mc temperature = SDIS_MC_NULL;
    353 
    354       OK(sdis_estimator_buffer_at(image, x, y, &pixel));
    355       OK(sdis_estimator_get_temperature(pixel, &temperature));
    356       fprintf(stream, "%g %g 0 0 0 0 0 0\n", temperature.E, temperature.SE);
    357     }
    358   }
    359 }
    360 
    361 static void
    362 draw(struct sdis_scene* scn, struct sdis_camera* cam)
    363 {
    364   struct sdis_solve_camera_args args = SDIS_SOLVE_CAMERA_ARGS_DEFAULT;
    365   struct sdis_estimator_buffer* image = NULL;
    366 
    367   args.cam = cam;
    368   args.image_definition[0] = IMG_WIDTH;
    369   args.image_definition[1] = IMG_HEIGHT;
    370   args.spp = IMG_SPP;
    371 
    372   OK(sdis_solve_camera(scn, &args, &image));
    373   write_image(stdout, image);
    374   OK(sdis_estimator_buffer_ref_put(image));
    375 }
    376 
    377 /*******************************************************************************
    378  * The test
    379  ******************************************************************************/
    380 int
    381 main(int argc, char** argv)
    382 {
    383   /* Stardis */
    384   struct sdis_camera* cam = NULL;
    385   struct sdis_device* dev = NULL;
    386   struct sdis_interface* interf = NULL;
    387   struct sdis_medium* fluid = NULL;
    388   struct sdis_medium* solid = NULL;
    389   struct sdis_scene* scn = NULL;
    390   struct sdis_source* source = NULL;
    391   struct sdis_radiative_env* radenv = NULL;
    392 
    393   /* Miscellaneous */
    394   struct mesh mesh = MESH_NULL;
    395   (void)argc, (void)argv;
    396 
    397   OK(sdis_device_create(&SDIS_DEVICE_CREATE_ARGS_DEFAULT, &dev));
    398 
    399   mesh_init(&mesh);
    400   mesh_add_super_shape(&mesh);
    401   mesh_add_ground(&mesh);
    402 
    403   solid = create_solid(dev);
    404   fluid = create_fluid(dev);
    405   interf = create_interface(dev, fluid, solid);
    406   source = create_source(dev);
    407   radenv = create_radenv(dev);
    408   scn = create_scene(dev, &mesh, interf, source, radenv);
    409   cam = create_camera(dev);
    410 
    411   draw(scn, cam);
    412 
    413   /* For debug of scene geometry */
    414   /*dump_mesh(stdout,
    415     mesh.positions, mesh_nvertices(&mesh),
    416     mesh.indices, mesh_ntriangles(&mesh));*/
    417 
    418   mesh_release(&mesh);
    419   OK(sdis_camera_ref_put(cam));
    420   OK(sdis_device_ref_put(dev));
    421   OK(sdis_interface_ref_put(interf));
    422   OK(sdis_medium_ref_put(fluid));
    423   OK(sdis_medium_ref_put(solid));
    424   OK(sdis_scene_ref_put(scn));
    425   OK(sdis_source_ref_put(source));
    426   OK(sdis_radiative_env_ref_put(radenv));
    427   CHK(mem_allocated_size() == 0);
    428   return 0;
    429 }