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 }