stardis-solver

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

test_sdis_primkey.c (10285B)


      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_utils.h"
     18 
     19 #include <star/s3dut.h>
     20 #include <rsys/float3.h>
     21 
     22 /*
     23  * The system is a solid supershape whose boundary temperature is set to a
     24  * constant. The temperature of the solid is therefore this same temperature.
     25  * This simplistic test case is not used to verify a Monte Carlo estimate, but
     26  * to ensure that the caller can recover the internal representation of the
     27  * geometric primitives from his own data.
     28  *
     29  *             /\
     30  *         ___/  \___
     31  *         \        /
     32  *         /_  __  _\
     33  *           \/  \/
     34  *
     35  */
     36 
     37 /*******************************************************************************
     38  * Super shape
     39  ******************************************************************************/
     40 static struct s3dut_mesh*
     41 create_super_shape(void)
     42 {
     43   struct s3dut_mesh* mesh = NULL;
     44   struct s3dut_super_formula f0 = S3DUT_SUPER_FORMULA_NULL;
     45   struct s3dut_super_formula f1 = S3DUT_SUPER_FORMULA_NULL;
     46   const double radius = 1;
     47   const unsigned nslices = 256;
     48 
     49   f0.A = 1.5; f0.B = 1; f0.M = 11.0; f0.N0 = 1; f0.N1 = 1; f0.N2 = 2.0;
     50   f1.A = 1.0; f1.B = 2; f1.M =  3.6; f1.N0 = 1; f1.N1 = 2; f1.N2 = 0.7;
     51   OK(s3dut_create_super_shape(NULL, &f0, &f1, radius, nslices, nslices/2, &mesh));
     52 
     53   return mesh;
     54 }
     55 
     56 /*******************************************************************************
     57  * Solid, i.e. medium of the super shape
     58  ******************************************************************************/
     59 #define SOLID_PROP(Prop, Val)                                                  \
     60   static double                                                                \
     61   solid_get_##Prop                                                             \
     62     (const struct sdis_rwalk_vertex* vtx,                                      \
     63      struct sdis_data* data)                                                   \
     64   {                                                                            \
     65     (void)vtx, (void)data; /* Avoid the "unused variable" warning */           \
     66     return Val;                                                                \
     67   }
     68 SOLID_PROP(calorific_capacity, 1) /* [J/K/Kg] */
     69 SOLID_PROP(thermal_conductivity, 1) /* [W/m/K] */
     70 SOLID_PROP(volumic_mass, 1) /* [kg/m^3] */
     71 SOLID_PROP(temperature, SDIS_TEMPERATURE_NONE) /* [K] */
     72 SOLID_PROP(delta, 1.0/20.0) /* [m/fp_to_meter] */
     73 #undef SOLID_PROP
     74 
     75 static struct sdis_medium*
     76 create_solid(struct sdis_device* sdis)
     77 {
     78   struct sdis_solid_shader shader = SDIS_SOLID_SHADER_NULL;
     79   struct sdis_medium* solid = NULL;
     80 
     81   shader.calorific_capacity = solid_get_calorific_capacity;
     82   shader.thermal_conductivity = solid_get_thermal_conductivity;
     83   shader.volumic_mass = solid_get_volumic_mass;
     84   shader.delta = solid_get_delta;
     85   shader.temperature = solid_get_temperature;
     86   OK(sdis_solid_create(sdis, &shader, NULL, &solid));
     87   return solid;
     88 }
     89 
     90 /*******************************************************************************
     91  * Dummy environment, i.e. environment surrounding the super shape. It is
     92  * defined only for Stardis compliance: in Stardis, an interface must divide 2
     93  * media.
     94  ******************************************************************************/
     95 static struct sdis_medium*
     96 create_dummy(struct sdis_device* sdis)
     97 {
     98   struct sdis_fluid_shader shader = SDIS_FLUID_SHADER_NULL;
     99   struct sdis_medium* dummy = NULL;
    100 
    101   shader.calorific_capacity = dummy_medium_getter;
    102   shader.volumic_mass = dummy_medium_getter;
    103   shader.temperature = dummy_medium_getter;
    104   OK(sdis_fluid_create(sdis, &shader, NULL, &dummy));
    105   return dummy;
    106 }
    107 
    108 /*******************************************************************************
    109  * Interface
    110  ******************************************************************************/
    111 static double
    112 interface_get_temperature
    113   (const struct sdis_interface_fragment* frag,
    114    struct sdis_data* data)
    115 {
    116   (void)frag, (void)data; /* Avoid the "unused variable" warning */
    117   return 300; /* [K] */
    118 }
    119 
    120 static struct sdis_interface*
    121 create_interface
    122   (struct sdis_device* sdis,
    123    struct sdis_medium* front,
    124    struct sdis_medium* back)
    125 {
    126   struct sdis_interface* interf = NULL;
    127   struct sdis_interface_shader shader = SDIS_INTERFACE_SHADER_NULL;
    128 
    129   shader.front.temperature = interface_get_temperature;
    130   shader.back.temperature = interface_get_temperature;
    131   OK(sdis_interface_create(sdis, front, back, &shader, NULL, &interf));
    132   return interf;
    133 }
    134 
    135 /*******************************************************************************
    136  * Scene, i.e. the system to simulate
    137  ******************************************************************************/
    138 struct scene_context {
    139   struct s3dut_mesh_data mesh_data;
    140   struct sdis_interface* interf;
    141 };
    142 static const struct scene_context SCENE_CONTEXT_NULL = {{0}, NULL};
    143 
    144 static void
    145 scene_get_indices(const size_t itri, size_t ids[3], void* ctx)
    146 {
    147   struct scene_context* context = ctx;
    148   CHK(ids && context && itri < context->mesh_data.nprimitives);
    149   /* Flip the indices to ensure that the normal points into the super shape */
    150   ids[0] = (unsigned)context->mesh_data.indices[itri*3+0];
    151   ids[1] = (unsigned)context->mesh_data.indices[itri*3+2];
    152   ids[2] = (unsigned)context->mesh_data.indices[itri*3+1];
    153 }
    154 
    155 static void
    156 scene_get_interface(const size_t itri, struct sdis_interface** interf, void* ctx)
    157 {
    158   struct scene_context* context = ctx;
    159   CHK(interf && context && itri < context->mesh_data.nprimitives);
    160   *interf = context->interf;
    161 }
    162 
    163 static void
    164 scene_get_position(const size_t ivert, double pos[3], void* ctx)
    165 {
    166   struct scene_context* context = ctx;
    167   CHK(pos && context && ivert < context->mesh_data.nvertices);
    168   pos[0] = context->mesh_data.positions[ivert*3+0];
    169   pos[1] = context->mesh_data.positions[ivert*3+1];
    170   pos[2] = context->mesh_data.positions[ivert*3+2];
    171 }
    172 
    173 static struct sdis_scene*
    174 create_scene
    175   (struct sdis_device* sdis,
    176    const struct s3dut_mesh* mesh,
    177    struct sdis_interface* interf)
    178 {
    179   struct sdis_scene* scn = NULL;
    180   struct sdis_scene_create_args scn_args = SDIS_SCENE_CREATE_ARGS_DEFAULT;
    181   struct scene_context context = SCENE_CONTEXT_NULL;
    182 
    183   OK(s3dut_mesh_get_data(mesh, &context.mesh_data));
    184   context.interf = interf;
    185 
    186   scn_args.get_indices = scene_get_indices;
    187   scn_args.get_interface = scene_get_interface;
    188   scn_args.get_position = scene_get_position;
    189   scn_args.nprimitives = context.mesh_data.nprimitives;
    190   scn_args.nvertices = context.mesh_data.nvertices;
    191   scn_args.context = &context;
    192   OK(sdis_scene_create(sdis, &scn_args, &scn));
    193   return scn;
    194 }
    195 
    196 /*******************************************************************************
    197  * Validation
    198  ******************************************************************************/
    199 static void
    200 check(struct sdis_scene* scn, const struct s3dut_mesh* mesh)
    201 {
    202   struct s3d_primitive prim = S3D_PRIMITIVE_NULL;
    203   struct s3dut_mesh_data mesh_data;
    204   struct sdis_primkey key = SDIS_PRIMKEY_NULL;
    205   size_t iprim = 0;
    206 
    207   OK(s3dut_mesh_get_data(mesh, &mesh_data));
    208 
    209   BA(sdis_scene_get_s3d_primitive(NULL, &key, &prim));
    210   BA(sdis_scene_get_s3d_primitive(scn, NULL, &prim));
    211   BA(sdis_scene_get_s3d_primitive(scn, &key, NULL));
    212   BA(sdis_scene_get_s3d_primitive(scn, &key, &prim));
    213 
    214   FOR_EACH(iprim, 0, mesh_data.nprimitives) {
    215     const double *v0, *v1, *v2;
    216     float v0f[3], v1f[3], v2f[3];
    217     struct s3d_attrib attr0, attr1, attr2;
    218 
    219     /* Check that a primitive can be obtained from the key constructed on the
    220      * user side */
    221     v0 = mesh_data.positions + mesh_data.indices[iprim*3 + 0]*3;
    222     v1 = mesh_data.positions + mesh_data.indices[iprim*3 + 1]*3;
    223     v2 = mesh_data.positions + mesh_data.indices[iprim*3 + 2]*3;
    224     sdis_primkey_setup(&key, v0, v1, v2);
    225     OK(sdis_scene_get_s3d_primitive(scn, &key, &prim));
    226 
    227     /* Check that the primitive on the solver side is the same as that on the
    228      * user side. On the solver side, vertices are stored in simple precision in
    229      * Star-3D view. We therefore need to take care of this conversion to check
    230      * that the vertices are the same */
    231     OK(s3d_triangle_get_vertex_attrib(&prim, 0, S3D_POSITION, &attr0));
    232     OK(s3d_triangle_get_vertex_attrib(&prim, 1, S3D_POSITION, &attr1));
    233     OK(s3d_triangle_get_vertex_attrib(&prim, 2, S3D_POSITION, &attr2));
    234     f3_set_d3(v0f, v0);
    235     f3_set_d3(v1f, v1);
    236     f3_set_d3(v2f, v2);
    237 
    238     /* The vertices have been inverted on the user's side to reverse the normal
    239      * orientation. Below it is taken into account */
    240     CHK(f3_eq(v0f, attr0.value));
    241     CHK(f3_eq(v1f, attr2.value));
    242     CHK(f3_eq(v2f, attr1.value));
    243   }
    244 }
    245 
    246 /*******************************************************************************
    247  * The test
    248  ******************************************************************************/
    249 int
    250 main(int argc, char** argv)
    251 {
    252   /* Stardis variables */
    253   struct sdis_device* sdis = NULL;
    254   struct sdis_interface* interf = NULL;
    255   struct sdis_medium* solid = NULL;
    256   struct sdis_medium* dummy = NULL;
    257   struct sdis_scene* scn = NULL;
    258 
    259   struct s3dut_mesh* super_shape = NULL;
    260   (void)argc, (void)argv;
    261 
    262   OK(sdis_device_create(&SDIS_DEVICE_CREATE_ARGS_DEFAULT, &sdis));
    263 
    264   super_shape = create_super_shape();
    265   solid = create_solid(sdis);
    266   dummy = create_dummy(sdis);
    267   interf = create_interface(sdis, solid, dummy);
    268   scn = create_scene(sdis, super_shape, interf);
    269 
    270   check(scn, super_shape);
    271 
    272   OK(s3dut_mesh_ref_put(super_shape));
    273   OK(sdis_device_ref_put(sdis));
    274   OK(sdis_interface_ref_put(interf));
    275   OK(sdis_medium_ref_put(solid));
    276   OK(sdis_medium_ref_put(dummy));
    277   OK(sdis_scene_ref_put(scn));
    278 
    279   CHK(mem_allocated_size() == 0);
    280   return 0;
    281 }