stardis

Perform coupled heat transfer calculations
git clone git://git.meso-star.fr/stardis.git
Log | Files | Refs | README | LICENSE

commit f1a2e903680a1feb3818f21a670b4165cfebe590
parent 65376959565a048141c19b5b6c35e974d243fac3
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date:   Wed, 19 Aug 2020 14:31:30 +0200

Improve information on geometry dumps

Diffstat:
Mdoc/stardis-output.5.txt | 55++++++++++++++++++++++++++++++++++++++++++++-----------
Msrc/stardis-app.c | 420+++++++++++++++++++++++++++++++++++++------------------------------------------
Msrc/stardis-app.h | 78++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/stardis-compute.c | 18++++++++++--------
Msrc/stardis-intface.c | 13+++++++------
Msrc/stardis-main.c | 3+++
Msrc/stardis-output.c | 261+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------
Msrc/stardis-output.h | 7++++++-
Msrc/stardis-parsing.c | 100+++++++++++++++++++++++++++++++++++++++++++++++++++----------------------------
Msrc/stardis-parsing.h | 16+++-------------
10 files changed, 642 insertions(+), 329 deletions(-)

diff --git a/doc/stardis-output.5.txt b/doc/stardis-output.5.txt @@ -477,6 +477,15 @@ defined by its frontier that is a collection of triangles surrounding the hole. Such triangles are detected as having their 2 sides in the same enclosure, but with a different medium on each side. +Media information is provided in two different flavours. First the medium on +front and back sides of triangles can be found through the Front_medium and +Back_medium fields. These fields use the special value 4294967295 (INT_MAX) for +sides with no defined medium, as one can expect on boundary triangles. On the +other hand, medium information provided by the Enclosures_internal_media +field displays the id of the medium created to hold boundary information for +boundary triangles. In either case, media numbering information can be found +in log messages if option -V 3 is used in conjunction with the -d dump option. + [verse] _______ <geometry-file> ::= "# vtk DataFile Version 2.0" @@ -493,7 +502,8 @@ _______ <user-ids> [ <merge-conflicts> ] # if some merge conflict occured [ <property-conflicts> ] # if some property conflict occured - <file-ranks> + <file-ids> + <boundaries> [ <compute-region> ] # if defined <encl-or-overlaps> @@ -535,6 +545,10 @@ _______ "LOOKUP_TABLE default" <file-ranks> +<boundaries> ::= "SCALARS Boundaries unsigned_int 1" + "LOOKUP_TABLE default" + <boundary-ids> + <compute-region> ::= "SCALARS Compute_region unsigned_int 1" "LOOKUP_TABLE default" <region-membership> @@ -542,14 +556,6 @@ _______ <encl-or-overlaps> ::= <encl-information> # if enclosure extraction was possible | <overlaps> # if overlapping triangles where detected -<holes> ::= "SCALARS Hole_frontiers unsigned_int 1" - "LOOKUP_TABLE default" - <hole-memberships> - -<enclosures> ::= "FIELD FieldData 1" - "Enclosure_ID" #enclosures #triangles "unsigned_char" - <encl-memberships> - ----------------- <vertex-list> ::= "3" <vertice_id> <vertice_id> <vertice_id> @@ -611,6 +617,9 @@ _______ <file-ranks> ::= INTEGER # in [0 #submitted files[ <file-ranks> # #triangles ranks +<boundary-ids> ::= INTEGER # in [0 #submitted descriptions[ + <boundary-ids> # #triangles ids + <region-membership> ::= <reg-not-member> # triangle not part of the compute region | <reg-member> # triangle is part of the compute region <region-membership> # #triangles membership status @@ -622,6 +631,18 @@ _______ "LOOKUP_TABLE default" <overlapping-status> +<holes> ::= "SCALARS Hole_frontiers unsigned_int 1" + "LOOKUP_TABLE default" + <hole-memberships> + +<enclosures> ::= "FIELD FieldData 2" + "Enclosures" #enclosures #triangles "unsigned_char" + <encl-memberships> + "Enclosures_internal_media" #enclosures #triangles "unsigned_int" + <encl-media> + +----------------- + <hole-memberships> ::= "0" # triangle not surrounding a hole | "1" # triangle surrounding a hole <hole-memberships> # #triangles hole memberships @@ -629,16 +650,18 @@ _______ <encl-memberships> ::= <enclosure-status 0> ... <enclosure-status #enclosures-1> <encl-memberships> # #triangles enclosure memberships +<encl-media> ::= <enclosure 0 medium> ... <enclosure #enclosures-1 medium> + <encl-media> # #triangles enclosure media + <medium-id> ::= INTEGER # in [0, #medium[ <undef-medium> ::= "4294967295" ------------------ - <reg-not-member> ::= "0" <reg-member> ::= "1" # the FRONT side is member of the region | "2" # the BACK side is member of the region + | "3" # both sides are member of the region | "4294967295" # the triangle is an invalid part of the region <overlapping-status> ::= "0" # triangle not overlapping another triangle @@ -648,6 +671,16 @@ _______ <enclosure-status i> ::= <encl-not-member> # the triangle is not part of the ith enclosure | <encl-member> # the triangle is part of the ith enclosure +<enclosure i medium> ::= <medium-id> # the triangle is part of the ith enclosure and + # has this medium in the involved side(s) + | "4294967293" # the triangle is part of the ith enclosure and + # has no defined medium in the involved side(s) + | "4294967294" # the 2 sides of the triangle are part of the ith + # enclosure, but have 2 different media + | "4294967295" # the triangle is not part of the ith enclosure + +----------------- + <encl-not-member> ::= "0" <encl-member> ::= "1" # valid enclosure diff --git a/src/stardis-app.c b/src/stardis-app.c @@ -34,52 +34,13 @@ static const struct dummies DUMMIES_NULL = DUMMIES_NULL__; static const struct counts COUNTS_NULL = COUNTS_NULL__; /******************************************************************************* - * Local Type; for documentation purpose - * These values are used in dumps - ******************************************************************************/ -enum properties_conflict_t { - NO_PROPERTY_CONFLICT, - BOUND_H_FOR_FLUID_BETWEEN_2_DEFS, - BOUND_H_FOR_FLUID_BETWEEN_2_UNDEFS, - BOUND_H_FOR_FLUID_ENCLOSING_SOLID, - BOUND_H_FOR_SOLID_BETWEEN_2_DEFS, - BOUND_H_FOR_SOLID_BETWEEN_2_UNDEFS, - BOUND_H_FOR_SOLID_ENCLOSING_FLUID, - BOUND_T_FOR_FLUID_BETWEEN_2_DEFS, - BOUND_T_FOR_FLUID_BETWEEN_2_UNDEFS, - BOUND_T_FOR_FLUID_ENCLOSING_SOLID, - BOUND_T_FOR_SOLID_BETWEEN_2_DEFS, - BOUND_T_FOR_SOLID_BETWEEN_2_UNDEFS, - BOUND_T_FOR_SOLID_ENCLOSING_FLUID, - BOUND_F_FOR_SOLID_BETWEEN_2_DEFS, - BOUND_F_FOR_SOLID_BETWEEN_2_UNDEFS, - BOUND_F_FOR_SOLID_ENCLOSING_FLUID, - SFCONNECT_BETWEEN_2_SOLIDS, - SFCONNECT_BETWEEN_2_FLUIDS, - SFCONNECT_USED_AS_BOUNDARY, - SFCONNECT_BETWEEN_2_UNDEFS, - NO_CONNECTION_BETWEEN_2_FLUIDS, - NO_CONNECTION_BETWEEN_SOLID_AND_FLUID, - NO_BOUND_BETWEEN_FLUID_AND_UNDEF, - NO_BOUND_BETWEEN_SOLID_AND_UNDEF, - TRG_WITH_NO_PROPERTY, - PROPERTIES_CONFLICT_COUNT__ -}; - -enum enclosure_errors_t { - NO_ENCLOSURE_ERROR, - INTERNAL_ENCLOSURE_WITH_N_MEDIA, - ENCLOSURE_ERRORS_COUNT__ -}; - -/******************************************************************************* * Local Functions ******************************************************************************/ - static res_T read_model (const struct darray_str* model_files, - struct stardis* stardis) + struct stardis* stardis, + struct dummies* dummies) { res_T res = RES_OK; const struct str* files = NULL; @@ -105,7 +66,7 @@ read_model ERR(txtrdr_read_line(txtrdr)); line = txtrdr_get_line(txtrdr); if(!line) break; - ERR(process_model_line(name, line, stardis)); + ERR(process_model_line(name, line, stardis, dummies)); } txtrdr_ref_put(txtrdr); txtrdr = NULL; @@ -126,155 +87,6 @@ error: goto exit; } -#define COUNT_SIDE(Rank) {\ - if(properties[(Rank)] == SG3D_UNSPECIFIED_PROPERTY) undef_count++;\ - else {\ - ASSERT(properties[(Rank)] < darray_descriptions_size_get(&stardis->descriptions));\ - ASSERT(descs[properties[(Rank)]].type == DESC_MAT_SOLID\ - || descs[properties[(Rank)]].type == DESC_MAT_FLUID);\ - if(descs[properties[(Rank)]].type == DESC_MAT_SOLID) solid_count++;\ - else fluid_count++;\ - }\ -} -static res_T -validate_properties - (const unsigned itri, - const unsigned properties[SG3D_PROP_TYPES_COUNT__], - void* context, - int* properties_conflict_status) -{ - res_T res = RES_OK; - struct stardis* stardis = context; - unsigned undef_count, solid_count, fluid_count, intface_count; - const struct description* descs; - const struct description* intface = NULL; - - (void)itri; - ASSERT(stardis && properties_conflict_status); - descs = darray_descriptions_cdata_get(&stardis->descriptions); - undef_count = solid_count = fluid_count = intface_count = 0; - - COUNT_SIDE(SG3D_FRONT); - COUNT_SIDE(SG3D_BACK); - if(properties[SG3D_INTFACE] == SG3D_UNSPECIFIED_PROPERTY) - undef_count++; - else intface_count++; - - ASSERT(solid_count <= 2 && fluid_count <= 2 && intface_count <= 1); - ASSERT(undef_count + solid_count + fluid_count + intface_count == 3); - if(intface_count) { - ASSERT(properties[SG3D_INTFACE] < darray_descriptions_size_get(&stardis->descriptions)); - intface = descs + properties[SG3D_INTFACE]; - switch (intface->type) { - case DESC_BOUND_H_FOR_FLUID: - if(!(solid_count == 0 && fluid_count == 1)) { - if(solid_count + fluid_count == 2) - *properties_conflict_status = BOUND_H_FOR_FLUID_BETWEEN_2_DEFS; - else if(solid_count + fluid_count == 0) - *properties_conflict_status = BOUND_H_FOR_FLUID_BETWEEN_2_UNDEFS; - else if(solid_count == 1) - *properties_conflict_status = BOUND_H_FOR_FLUID_ENCLOSING_SOLID; - else FATAL("error:" STR(__FILE__) ":" STR(__LINE__)"\n"); - goto end; - } - break; - case DESC_BOUND_H_FOR_SOLID: - if(!(solid_count == 1 && fluid_count == 0)) { - if(solid_count + fluid_count == 2) - *properties_conflict_status = BOUND_H_FOR_SOLID_BETWEEN_2_DEFS; - else if(solid_count + fluid_count == 0) - *properties_conflict_status = BOUND_H_FOR_SOLID_BETWEEN_2_UNDEFS; - else if(fluid_count == 1) - *properties_conflict_status = BOUND_H_FOR_SOLID_ENCLOSING_FLUID; - else FATAL("error:" STR(__FILE__) ":" STR(__LINE__)"\n"); - goto end; - } - break; - case DESC_BOUND_T_FOR_FLUID: - if(!(solid_count == 0 && fluid_count == 1)) { - if(solid_count + fluid_count == 2) - *properties_conflict_status = BOUND_T_FOR_FLUID_BETWEEN_2_DEFS; - else if(solid_count + fluid_count == 0) - *properties_conflict_status = BOUND_T_FOR_FLUID_BETWEEN_2_UNDEFS; - else if(solid_count == 1) - *properties_conflict_status = BOUND_T_FOR_FLUID_ENCLOSING_SOLID; - else FATAL("error:" STR(__FILE__) ":" STR(__LINE__)"\n"); - goto end; - } - break; - case DESC_BOUND_T_FOR_SOLID: - if(!(solid_count == 1 && fluid_count == 0)) { - if(solid_count + fluid_count == 2) - *properties_conflict_status = BOUND_T_FOR_SOLID_BETWEEN_2_DEFS; - else if(solid_count + fluid_count == 0) - *properties_conflict_status = BOUND_T_FOR_SOLID_BETWEEN_2_UNDEFS; - else if(fluid_count == 1) - *properties_conflict_status = BOUND_T_FOR_SOLID_ENCLOSING_FLUID; - else FATAL("error:" STR(__FILE__) ":" STR(__LINE__)"\n"); - goto end; - } - break; - case DESC_BOUND_F_FOR_SOLID: - if(!(solid_count == 1 && fluid_count == 0)) { - if(solid_count + fluid_count == 2) - *properties_conflict_status = BOUND_F_FOR_SOLID_BETWEEN_2_DEFS; - else if(solid_count + fluid_count == 0) - *properties_conflict_status = BOUND_F_FOR_SOLID_BETWEEN_2_UNDEFS; - else if(fluid_count == 1) - *properties_conflict_status = BOUND_F_FOR_SOLID_ENCLOSING_FLUID; - else FATAL("error:" STR(__FILE__) ":" STR(__LINE__)"\n"); - goto end; - } - break; - case DESC_SOLID_FLUID_CONNECT: - if(solid_count != 1 || fluid_count != 1) { - if(solid_count == 2) - *properties_conflict_status = SFCONNECT_BETWEEN_2_SOLIDS; - else if(fluid_count == 2) - *properties_conflict_status = SFCONNECT_BETWEEN_2_FLUIDS; - else if(solid_count + fluid_count == 1) - *properties_conflict_status = SFCONNECT_USED_AS_BOUNDARY; - else if(solid_count + fluid_count == 0) - *properties_conflict_status = SFCONNECT_BETWEEN_2_UNDEFS; - else FATAL("error:" STR(__FILE__) ":" STR(__LINE__)"\n"); - goto end; - } - break; - default: - FATAL("error:" STR(__FILE__) ":" STR(__LINE__)": Invalid type.\n"); - } - } else { - /* No interface defined */ - ASSERT(intface_count == 0 && undef_count >= 1); - if(undef_count == 3) { - *properties_conflict_status = TRG_WITH_NO_PROPERTY; - goto end; - } - if(fluid_count == 2) { - *properties_conflict_status = NO_CONNECTION_BETWEEN_2_FLUIDS; - goto end; - } - if(undef_count == 2) { - ASSERT(fluid_count + solid_count == 1); - if(fluid_count) - *properties_conflict_status = NO_BOUND_BETWEEN_FLUID_AND_UNDEF; - else *properties_conflict_status = NO_BOUND_BETWEEN_SOLID_AND_UNDEF; - goto end; - } - if(undef_count == 1 && solid_count == 1 && fluid_count == 1) { - *properties_conflict_status = NO_CONNECTION_BETWEEN_SOLID_AND_FLUID; - goto end; - } - /* Undef interface between solids is OK */ - CHK(solid_count == 2); - } - -end: - return res; -} - -#undef COUNT_SIDE - static struct sdis_interface* geometry_get_interface (const size_t itri, void* ctx) @@ -304,87 +116,89 @@ create_holder case DESC_BOUND_H_FOR_SOLID: stardis->counts.hbound_count++; /* Create an external fluid with imposed temperature */ - allocate_stardis_medium_id(stardis, &description->d.h_boundary.mat_id); + ASSERT(description->d.h_boundary.mat_id != UINT_MAX); ERR(create_stardis_fluid(stardis, NULL, 1, 1, is_green, 1, -1, description->d.h_boundary.imposed_temperature, description->d.h_boundary.mat_id)); logger_print(stardis->logger, LOG_OUTPUT, - "External fluid (id=%u): rho=1 cp=1 T=%g\n", - description->d.h_boundary.mat_id, - description->d.h_boundary.imposed_temperature); + "External fluid: rho=1 cp=1 T=%g (it is medium %u)\n", + description->d.h_boundary.imposed_temperature, + description->d.h_boundary.mat_id); break; case DESC_BOUND_H_FOR_FLUID: stardis->counts.hbound_count++; + ASSERT(dummies->dummy_solid_id != UINT_MAX); if(dummies->dummy_solid) { /* Reuse external dummy solid */ description->d.h_boundary.mat_id = dummies->dummy_solid_id; } else { /* Create dummy solid */ - size_t sz = darray_media_ptr_size_get(&stardis->media); - allocate_stardis_medium_id(stardis, &description->d.h_boundary.mat_id); + description->d.h_boundary.mat_id = dummies->dummy_solid_id; ERR(create_stardis_solid(stardis, NULL, 1, 1, 1, 1, is_green, 1, -1, -1, 0, description->d.h_boundary.mat_id)); - dummies->dummy_solid = darray_media_ptr_data_get(&stardis->media)[sz]; - dummies->dummy_solid_id = description->d.h_boundary.mat_id; + dummies->dummy_solid + = darray_media_ptr_data_get(&stardis->media)[dummies->dummy_solid_id]; logger_print(stardis->logger, LOG_OUTPUT, - "Dummy solid (id=%u): lambda=1 rho=1 cp=1\n", + "Dummy solid: lambda=1 rho=1 cp=1 (it is medium %u)\n", dummies->dummy_solid_id); } break; case DESC_BOUND_T_FOR_SOLID: stardis->counts.tbound_count++; + ASSERT(dummies->dummy_fluid_id != UINT_MAX); if(dummies->dummy_fluid) { /* Reuse external dummy fluid */ description->d.t_boundary.mat_id = dummies->dummy_fluid_id; } else { /* Create dummy fluid */ - size_t sz = darray_media_ptr_size_get(&stardis->media); - allocate_stardis_medium_id(stardis, &description->d.t_boundary.mat_id); + description->d.t_boundary.mat_id = dummies->dummy_fluid_id; ERR(create_stardis_fluid(stardis, NULL, 1, 1, is_green, 1, -1, -1, description->d.t_boundary.mat_id)); - dummies->dummy_fluid = darray_media_ptr_data_get(&stardis->media)[sz]; - dummies->dummy_fluid_id = description->d.t_boundary.mat_id; + dummies->dummy_fluid + = darray_media_ptr_data_get(&stardis->media)[dummies->dummy_fluid_id]; logger_print(stardis->logger, LOG_OUTPUT, - "Dummy fluid (id=%u): rho=1 cp=1\n", dummies->dummy_fluid_id); + "Dummy fluid: rho=1 cp=1 (it is medium %u)\n", + dummies->dummy_fluid_id); } break; case DESC_BOUND_T_FOR_FLUID: stardis->counts.tbound_count++; + ASSERT(dummies->dummy_solid_id != UINT_MAX); if(dummies->dummy_solid) { /* Reuse external dummy solid */ description->d.t_boundary.mat_id = dummies->dummy_solid_id; } else { /* Create dummy solid */ - size_t sz = darray_media_ptr_size_get(&stardis->media); - allocate_stardis_medium_id(stardis, &description->d.t_boundary.mat_id); + description->d.t_boundary.mat_id = dummies->dummy_solid_id; ERR(create_stardis_solid(stardis, NULL, 1, 1, 1, 1, is_green, 1, -1, -1, 0, description->d.t_boundary.mat_id)); - dummies->dummy_solid = darray_media_ptr_data_get(&stardis->media)[sz]; - dummies->dummy_solid_id = description->d.t_boundary.mat_id; + dummies->dummy_solid + = darray_media_ptr_data_get(&stardis->media)[dummies->dummy_solid_id]; logger_print(stardis->logger, LOG_OUTPUT, - "Dummy solid (id=%u): lambda=1 rho=1 cp=1\n", + "Dummy solid: lambda=1 rho=1 cp=1 (it is medium %u)\n", dummies->dummy_solid_id); } break; case DESC_BOUND_F_FOR_SOLID: stardis->counts.fbound_count++; + ASSERT(dummies->dummy_fluid_id != UINT_MAX); if(dummies->dummy_fluid) { /* Reuse external dummy fluid */ description->d.f_boundary.mat_id = dummies->dummy_fluid_id; } else { /* Create dummy fluid */ - size_t sz = darray_media_ptr_size_get(&stardis->media); - allocate_stardis_medium_id(stardis, &description->d.f_boundary.mat_id); + description->d.f_boundary.mat_id = dummies->dummy_fluid_id; ERR(create_stardis_fluid(stardis, NULL, 1, 1, is_green, 1, -1, -1, description->d.f_boundary.mat_id)); - dummies->dummy_fluid = darray_media_ptr_data_get(&stardis->media)[sz]; - dummies->dummy_fluid_id = description->d.f_boundary.mat_id; + dummies->dummy_fluid + = darray_media_ptr_data_get(&stardis->media)[dummies->dummy_fluid_id]; logger_print(stardis->logger, LOG_OUTPUT, - "Dummy fluid (id=%u): rho=1 cp=1\n", dummies->dummy_fluid_id); + "Dummy fluid: rho=1 cp=1 (it is medium %u)\n", dummies->dummy_fluid_id); } break; case DESC_SOLID_FLUID_CONNECT: stardis->counts.sfconnect_count++; + ASSERT(description->d.sf_connect.connection_id != UINT_MAX); ASSERT(description->d.sf_connect.specular_fraction >= 0 && description->d.sf_connect.specular_fraction <= 1); ASSERT(description->d.sf_connect.emissivity >= 0); @@ -396,19 +210,23 @@ create_holder struct senc3d_enclosure_header header; /* Create solid to have ID informed */ stardis->counts.smed_count++; - allocate_stardis_medium_id(stardis, &description->d.solid.solid_id); + ASSERT(description->d.solid.solid_id != UINT_MAX); /* Check if delta can fit possible multiple enclosures */ if(stardis->senc3d_scn) { /* Due to previous errors, senc3d_scn can be unavailable */ unsigned e, ecount = 0; - ERR(senc3d_scene_get_enclosure_count_by_medium(stardis->senc3d_scn, - description->d.solid.solid_id, &ecount)); + + /* At this stage we use a geometry that was created using description ids + * as media ids. As a consequence we thereafter use description ids in + * APIs calls requiring a medium id */ + ERR(senc3d_scene_get_enclosure_count_by_medium(stardis->senc3d_scn, idx, + &ecount)); if(ecount != 0) { /* Can be unused if conflicts; in this case, avoid delta warnings */ int external = 0; FOR_EACH(e, 0, ecount) { - ERR(senc3d_scene_get_enclosure_by_medium(stardis->senc3d_scn, - description->d.solid.solid_id, e, &enc)); + ERR(senc3d_scene_get_enclosure_by_medium(stardis->senc3d_scn, idx, e, + &enc)); ERR(senc3d_enclosure_get_header(enc, &header)); if(header.is_infinite) { /* External solid, volume is negative and no delta walk expected */ @@ -468,7 +286,7 @@ create_holder } case DESC_MAT_FLUID: stardis->counts.fmed_count++; - allocate_stardis_medium_id(stardis, &description->d.fluid.fluid_id); + ASSERT(description->d.fluid.fluid_id != UINT_MAX); ERR(create_stardis_fluid(stardis, &description->d.fluid.name, description->d.fluid.rho, @@ -544,6 +362,7 @@ stardis_init if(args->dump_paths & DUMP_SUCCESS) stardis->dump_paths |= SDIS_HEAT_PATH_SUCCESS; stardis->next_medium_id = 0; + stardis->undefined_medium_behind_boundary_id = SENC3D_UNSPECIFIED_MEDIUM; stardis->verbose = args->verbose; darray_media_ptr_init(stardis->allocator, &stardis->media); @@ -563,7 +382,7 @@ stardis_init else if(args->mode & SURFACE_COMPUTE_MODES) { ERR(str_set(&stardis->solve_name, args->solve_filename)); } - ERR(read_model(&args->model_files, stardis)); + ERR(read_model(&args->model_files, stardis, &dummies)); ERR(sdis_device_create(stardis->logger, stardis->allocator, stardis->nthreads, args->verbose, &stardis->dev)); @@ -574,13 +393,14 @@ stardis_init ERR(sg3d_geometry_get_unique_vertices_count(stardis->geometry.sg3d, &vcount)); ERR(sg3d_geometry_get_unique_triangles_count(stardis->geometry.sg3d, &tcount)); + ERR(sg3d_geometry_validate_properties(stardis->geometry.sg3d, validate_properties, stardis)); ERR(sg3d_geometry_get_unique_triangles_with_properties_conflict_count( stardis->geometry.sg3d, &count)); if(count) { logger_print(stardis->logger, (is_for_compute ? LOG_ERROR : LOG_WARNING), - "Properties conflicts found in the model (%u triangles).\n", count); + "Property conflicts found in the model (%u triangles).\n", count); if(is_for_compute) { res = RES_BAD_ARG; goto error; @@ -730,6 +550,8 @@ init_enclosures ERR(sg3d_geometry_get_unique_vertices_count(stardis->geometry.sg3d, &vsz)); ERR(senc3d_device_create(stardis->logger, stardis->allocator, stardis->nthreads, stardis->verbose, &senc_dev)); + allocate_stardis_medium_id(stardis, + &stardis->undefined_medium_behind_boundary_id); ERR(senc3d_scene_create(senc_dev, SENC3D_CONVENTION_NORMAL_BACK | SENC3D_CONVENTION_NORMAL_OUTSIDE, tsz, sg3d_sencXd_geometry_get_indices, sg3d_sencXd_geometry_get_media, @@ -742,6 +564,158 @@ error: goto exit; } +#define COUNT_SIDE(Rank) {\ + if(properties[(Rank)] == SG3D_UNSPECIFIED_PROPERTY) undef_count++;\ + else {\ + ASSERT(properties[(Rank)] < darray_descriptions_size_get(&stardis->descriptions));\ + ASSERT(descs[properties[(Rank)]].type == DESC_MAT_SOLID\ + || descs[properties[(Rank)]].type == DESC_MAT_FLUID);\ + if(descs[properties[(Rank)]].type == DESC_MAT_SOLID) solid_count++;\ + else fluid_count++;\ + }\ +} + +res_T +validate_properties + (const unsigned itri, + const unsigned properties[SG3D_PROP_TYPES_COUNT__], + void* context, + int* properties_conflict_status) +{ + res_T res = RES_OK; + struct stardis* stardis = context; + unsigned undef_count, solid_count, fluid_count, intface_count; + const struct description* descs; + const struct description* intface = NULL; + + (void)itri; + ASSERT(stardis && properties_conflict_status); + descs = darray_descriptions_cdata_get(&stardis->descriptions); + *properties_conflict_status = NO_PROPERTY_CONFLICT; + undef_count = solid_count = fluid_count = intface_count = 0; + + COUNT_SIDE(SG3D_FRONT); + COUNT_SIDE(SG3D_BACK); + if(properties[SG3D_INTFACE] == SG3D_UNSPECIFIED_PROPERTY) + undef_count++; + else intface_count++; + + ASSERT(solid_count <= 2 && fluid_count <= 2 && intface_count <= 1); + ASSERT(undef_count + solid_count + fluid_count + intface_count == 3); + if(intface_count) { + ASSERT(properties[SG3D_INTFACE] + < darray_descriptions_size_get(&stardis->descriptions)); + intface = descs + properties[SG3D_INTFACE]; + switch (intface->type) { + case DESC_BOUND_H_FOR_FLUID: + if(!(solid_count == 0 && fluid_count == 1)) { + if(solid_count + fluid_count == 2) + *properties_conflict_status = BOUND_H_FOR_FLUID_BETWEEN_2_DEFS; + else if(solid_count + fluid_count == 0) + *properties_conflict_status = BOUND_H_FOR_FLUID_BETWEEN_2_UNDEFS; + else if(solid_count == 1) + *properties_conflict_status = BOUND_H_FOR_FLUID_ENCLOSING_SOLID; + else FATAL("error:" STR(__FILE__) ":" STR(__LINE__)"\n"); + goto end; + } + break; + case DESC_BOUND_H_FOR_SOLID: + if(!(solid_count == 1 && fluid_count == 0)) { + if(solid_count + fluid_count == 2) + *properties_conflict_status = BOUND_H_FOR_SOLID_BETWEEN_2_DEFS; + else if(solid_count + fluid_count == 0) + *properties_conflict_status = BOUND_H_FOR_SOLID_BETWEEN_2_UNDEFS; + else if(fluid_count == 1) + *properties_conflict_status = BOUND_H_FOR_SOLID_ENCLOSING_FLUID; + else FATAL("error:" STR(__FILE__) ":" STR(__LINE__)"\n"); + goto end; + } + break; + case DESC_BOUND_T_FOR_FLUID: + if(!(solid_count == 0 && fluid_count == 1)) { + if(solid_count + fluid_count == 2) + *properties_conflict_status = BOUND_T_FOR_FLUID_BETWEEN_2_DEFS; + else if(solid_count + fluid_count == 0) + *properties_conflict_status = BOUND_T_FOR_FLUID_BETWEEN_2_UNDEFS; + else if(solid_count == 1) + *properties_conflict_status = BOUND_T_FOR_FLUID_ENCLOSING_SOLID; + else FATAL("error:" STR(__FILE__) ":" STR(__LINE__)"\n"); + goto end; + } + break; + case DESC_BOUND_T_FOR_SOLID: + if(!(solid_count == 1 && fluid_count == 0)) { + if(solid_count + fluid_count == 2) + *properties_conflict_status = BOUND_T_FOR_SOLID_BETWEEN_2_DEFS; + else if(solid_count + fluid_count == 0) + *properties_conflict_status = BOUND_T_FOR_SOLID_BETWEEN_2_UNDEFS; + else if(fluid_count == 1) + *properties_conflict_status = BOUND_T_FOR_SOLID_ENCLOSING_FLUID; + else FATAL("error:" STR(__FILE__) ":" STR(__LINE__)"\n"); + goto end; + } + break; + case DESC_BOUND_F_FOR_SOLID: + if(!(solid_count == 1 && fluid_count == 0)) { + if(solid_count + fluid_count == 2) + *properties_conflict_status = BOUND_F_FOR_SOLID_BETWEEN_2_DEFS; + else if(solid_count + fluid_count == 0) + *properties_conflict_status = BOUND_F_FOR_SOLID_BETWEEN_2_UNDEFS; + else if(fluid_count == 1) + *properties_conflict_status = BOUND_F_FOR_SOLID_ENCLOSING_FLUID; + else FATAL("error:" STR(__FILE__) ":" STR(__LINE__)"\n"); + goto end; + } + break; + case DESC_SOLID_FLUID_CONNECT: + if(solid_count != 1 || fluid_count != 1) { + if(solid_count == 2) + *properties_conflict_status = SFCONNECT_BETWEEN_2_SOLIDS; + else if(fluid_count == 2) + *properties_conflict_status = SFCONNECT_BETWEEN_2_FLUIDS; + else if(solid_count + fluid_count == 1) + *properties_conflict_status = SFCONNECT_USED_AS_BOUNDARY; + else if(solid_count + fluid_count == 0) + *properties_conflict_status = SFCONNECT_BETWEEN_2_UNDEFS; + else FATAL("error:" STR(__FILE__) ":" STR(__LINE__)"\n"); + goto end; + } + break; + default: + FATAL("error:" STR(__FILE__) ":" STR(__LINE__)": Invalid type.\n"); + } + } else { + /* No interface defined */ + ASSERT(intface_count == 0 && undef_count >= 1); + if(undef_count == 3) { + *properties_conflict_status = TRG_WITH_NO_PROPERTY; + goto end; + } + if(fluid_count == 2) { + *properties_conflict_status = NO_CONNECTION_BETWEEN_2_FLUIDS; + goto end; + } + if(undef_count == 2) { + ASSERT(fluid_count + solid_count == 1); + if(fluid_count) + *properties_conflict_status = NO_BOUND_BETWEEN_FLUID_AND_UNDEF; + else *properties_conflict_status = NO_BOUND_BETWEEN_SOLID_AND_UNDEF; + goto end; + } + if(undef_count == 1 && solid_count == 1 && fluid_count == 1) { + *properties_conflict_status = NO_CONNECTION_BETWEEN_SOLID_AND_FLUID; + goto end; + } + /* Undef interface between solids is OK */ + CHK(solid_count == 2); + } + +end: + return res; +} + +#undef COUNT_SIDE + /******************************************************************************* * rsys/str additions ******************************************************************************/ diff --git a/src/stardis-app.h b/src/stardis-app.h @@ -45,6 +45,35 @@ struct sdis_medium; #define DELTA_AUTO INF /* Placeholder until actual value is substituted */ #define UNKNOWN_MEDIUM_TEMPERATURE -1 /* Unknown for stadis solver is -1 */ +enum properties_conflict_t { + NO_PROPERTY_CONFLICT, + BOUND_H_FOR_FLUID_BETWEEN_2_DEFS, + BOUND_H_FOR_FLUID_BETWEEN_2_UNDEFS, + BOUND_H_FOR_FLUID_ENCLOSING_SOLID, + BOUND_H_FOR_SOLID_BETWEEN_2_DEFS, + BOUND_H_FOR_SOLID_BETWEEN_2_UNDEFS, + BOUND_H_FOR_SOLID_ENCLOSING_FLUID, + BOUND_T_FOR_FLUID_BETWEEN_2_DEFS, + BOUND_T_FOR_FLUID_BETWEEN_2_UNDEFS, + BOUND_T_FOR_FLUID_ENCLOSING_SOLID, + BOUND_T_FOR_SOLID_BETWEEN_2_DEFS, + BOUND_T_FOR_SOLID_BETWEEN_2_UNDEFS, + BOUND_T_FOR_SOLID_ENCLOSING_FLUID, + BOUND_F_FOR_SOLID_BETWEEN_2_DEFS, + BOUND_F_FOR_SOLID_BETWEEN_2_UNDEFS, + BOUND_F_FOR_SOLID_ENCLOSING_FLUID, + SFCONNECT_BETWEEN_2_SOLIDS, + SFCONNECT_BETWEEN_2_FLUIDS, + SFCONNECT_USED_AS_BOUNDARY, + SFCONNECT_BETWEEN_2_UNDEFS, + NO_CONNECTION_BETWEEN_2_FLUIDS, + NO_CONNECTION_BETWEEN_SOLID_AND_FLUID, + NO_BOUND_BETWEEN_FLUID_AND_UNDEF, + NO_BOUND_BETWEEN_SOLID_AND_UNDEF, + TRG_WITH_NO_PROPERTY, + PROPERTIES_CONFLICT_COUNT__ +}; + /* Different types of descriptions */ enum description_type { DESC_MAT_SOLID, @@ -63,6 +92,12 @@ enum description_type { ((D) == DESC_BOUND_H_FOR_SOLID || (D) == DESC_BOUND_H_FOR_FLUID) #define DESC_IS_T(D) \ ((D) == DESC_BOUND_T_FOR_SOLID || (D) == DESC_BOUND_T_FOR_FLUID) +#define DESC_IS_F(D) \ + ((D) == DESC_BOUND_F_FOR_SOLID) +#define DESC_IS_MEDIUM(D) \ + ((D) == DESC_MAT_SOLID || (D) == DESC_MAT_FLUID) +#define DESC_IS_BOUNDARY(D) \ + (DESC_IS_H(D) || DESC_IS_T(D) || DESC_IS_F(D)) #define DARRAY_NAME interface_ptrs #define DARRAY_DATA struct sdis_interface* @@ -192,6 +227,7 @@ str_print_fluid if(f->imposed_temperature >= 0) { ERR(str_printf(str, " Temp=%g", f->imposed_temperature)); } + ERR(str_printf(str, " (it is medium %u)", f->fluid_id)); end: return res; error: @@ -261,6 +297,7 @@ str_print_solid if(s->imposed_temperature >= 0) { ERR(str_printf(str, " Temp=%g", s->imposed_temperature)); } + ERR(str_printf(str, " (it is medium %u)", s->solid_id)); end: return res; error: @@ -450,6 +487,7 @@ cp_f_boundary(struct f_boundary* dst, const struct f_boundary* src) struct solid_fluid_connect { struct str name; + unsigned connection_id; double emissivity; double specular_fraction; double hc; @@ -465,6 +503,7 @@ static FINLINE res_T init_sf(struct mem_allocator* allocator, struct solid_fluid_connect* dst) { str_init(allocator, &dst->name); + dst->connection_id = UINT_MAX; dst->emissivity = 0; dst->specular_fraction = 0; dst->hc = 0; @@ -491,6 +530,7 @@ static FINLINE res_T cp_sf_connect(struct solid_fluid_connect* dst, const struct solid_fluid_connect* src) { str_copy(&dst->name, &src->name); + dst->connection_id = src->connection_id; dst->specular_fraction = src->specular_fraction; dst->emissivity = src->emissivity; dst->hc = src->hc; @@ -676,6 +716,36 @@ error: goto end; } +static FINLINE void +description_get_medium_id + (const struct description* desc, + unsigned* id) +{ + ASSERT(desc && id); + switch (desc->type) { + case DESC_MAT_SOLID: + *id = desc->d.solid.solid_id; + return; + case DESC_MAT_FLUID: + *id = desc->d.fluid.fluid_id; + return; + case DESC_BOUND_H_FOR_SOLID: + case DESC_BOUND_H_FOR_FLUID: + *id = desc->d.h_boundary.mat_id; + return; + case DESC_BOUND_T_FOR_SOLID: + case DESC_BOUND_T_FOR_FLUID: + *id = desc->d.t_boundary.mat_id; + return; + case DESC_BOUND_F_FOR_SOLID: + *id = desc->d.f_boundary.mat_id; + return; + case DESC_SOLID_FLUID_CONNECT: /* No medium linked to SF */ + default: + FATAL("error:" STR(__FILE__) ":" STR(__LINE__)": Invalid type.\n"); + } +} + struct camera { double pos[3]; double tgt[3]; @@ -789,6 +859,7 @@ struct stardis { struct logger* logger; struct sdis_device* dev; unsigned next_medium_id; + unsigned undefined_medium_behind_boundary_id; int dump_paths; int verbose; }; @@ -817,4 +888,11 @@ extern LOCAL_SYM res_T init_enclosures (struct stardis* stardis); +extern LOCAL_SYM res_T +validate_properties + (const unsigned itri, + const unsigned properties[SG3D_PROP_TYPES_COUNT__], + void* context, + int* properties_conflict_status); + #endif /*STARDIS-APP_H*/ diff --git a/src/stardis-compute.c b/src/stardis-compute.c @@ -85,7 +85,7 @@ hit_filter enum senc3d_side hit_side; struct s3d_attrib interf_pos; const struct description* descriptions; - unsigned properties[3]; + unsigned descr[SG3D_PROP_TYPES_COUNT__]; const struct stardis* stardis; (void)ray_org; (void)invalid_; (void)filter_data; @@ -115,17 +115,18 @@ hit_filter return 0; /* Keep */ } + /* Get the description IDs for this triangle */ CHK(sg3d_geometry_get_unique_triangle_properties(stardis->geometry.sg3d, - hit->prim.prim_id, properties) == RES_OK); + hit->prim.prim_id, descr) == RES_OK); - if(properties[SDIS_FRONT] == properties[SG3D_BACK]) { + if(descr[SG3D_FRONT] == descr[SG3D_BACK]) { /* Don't need to bother with sides */ filter_ctx->prim = hit->prim.prim_id; - filter_ctx->desc = (properties[SDIS_FRONT] == SG3D_UNSPECIFIED_PROPERTY) - ? NULL : descriptions + properties[SG3D_FRONT]; + filter_ctx->desc = (descr[SG3D_FRONT] == SG3D_UNSPECIFIED_PROPERTY) + ? NULL : descriptions + descr[SG3D_FRONT]; f3_set(filter_ctx->pos, interf_pos.value); filter_ctx->dist = hit->distance; - filter_ctx->outside = (properties[SG3D_FRONT] == SG3D_UNSPECIFIED_PROPERTY); + filter_ctx->outside = (descr[SG3D_FRONT] == SG3D_UNSPECIFIED_PROPERTY); filter_ctx->probe_on_boundary = 0; return 0; /* Keep */ } @@ -146,7 +147,7 @@ hit_filter * Warning: following Embree 2 convention for geometrical normals, * the Star3D hit normals are left-handed */ hit_side = (s > 0) ? SG3D_BACK : SG3D_FRONT; - if(properties[hit_side] == SG3D_UNSPECIFIED_PROPERTY) { + if(descr[hit_side] == SG3D_UNSPECIFIED_PROPERTY) { filter_ctx->prim = hit->prim.prim_id; filter_ctx->desc = NULL; f3_set(filter_ctx->pos, interf_pos.value); @@ -155,7 +156,7 @@ hit_filter filter_ctx->probe_on_boundary = 0; } else { filter_ctx->prim = hit->prim.prim_id; - filter_ctx->desc = descriptions + properties[hit_side]; + filter_ctx->desc = descriptions + descr[hit_side]; f3_set(filter_ctx->pos, interf_pos.value); filter_ctx->dist = hit->distance; filter_ctx->outside = 0; @@ -237,6 +238,7 @@ check_probe_conform_to_type } else { if(filter_ctx.desc->type == DESC_MAT_SOLID) { double delta = filter_ctx.desc->d.solid.delta; + ASSERT(delta < INF); logger_print(stardis->logger, LOG_OUTPUT, "Probe was in solid '%s'.\n", str_cget(&filter_ctx.desc->d.solid.name)); if(filter_ctx.dist > 2 * delta) { diff --git a/src/stardis-intface.c b/src/stardis-intface.c @@ -92,7 +92,7 @@ create_intface struct sdis_medium* back_med = NULL; struct sdis_interface_side_shader* fluid_side_shader = NULL; struct sdis_data* data = NULL; - unsigned fd, bd, cd, properties[3]; + unsigned fd, bd, cd, descr[SG3D_PROP_TYPES_COUNT__]; int fluid_count = 0, solid_count = 0; int solid_fluid_connection_count = 0, connection_count = 0, boundary_count = 0; const struct description* descriptions; @@ -100,17 +100,18 @@ create_intface res_T res = RES_OK; ASSERT(stardis && htable_interfaces); - + + /* Get the description IDs for this triangle */ ERR(sg3d_geometry_get_unique_triangle_properties(stardis->geometry.sg3d, - itri, properties)); + itri, descr)); descriptions = darray_descriptions_cdata_get(&stardis->descriptions); media = darray_media_ptr_data_get(&stardis->media); /* Create key */ - int_descs.front = fd = properties[SG3D_FRONT]; - int_descs.back = bd = properties[SG3D_BACK]; - int_descs.connect = cd = properties[SG3D_INTFACE]; + int_descs.front = fd = descr[SG3D_FRONT]; + int_descs.back = bd = descr[SG3D_BACK]; + int_descs.connect = cd = descr[SG3D_INTFACE]; /* Search if interface already exists, or create it */ p_intface = htable_intface_find(htable_interfaces, &int_descs); diff --git a/src/stardis-main.c b/src/stardis-main.c @@ -80,6 +80,9 @@ main if(mode & MODE_DUMP_VTK) { /* Dump all the app-independent information */ ERR(sg3d_geometry_dump_as_vtk(stardis.geometry.sg3d, stdout)); + /* Dump boundaries + * Should we dump connections too? */ + ERR(dump_boundaries_at_the_end_of_vtk(&stardis, stdout)); /* Dump the compute region if any */ if(mode & REGION_COMPUTE_MODES) { ERR(dump_compute_region_at_the_end_of_vtk(&stardis, stdout)); diff --git a/src/stardis-output.c b/src/stardis-output.c @@ -23,6 +23,7 @@ #include <sdis.h> #include<star/senc3d.h> +#include<star/sg3d.h> #include <rsys/math.h> #include <rsys/mem_allocator.h> @@ -54,8 +55,8 @@ struct w_ctx { ******************************************************************************/ enum enclosure_errors_t { NO_ENCLOSURE_ERROR = BIT(0), - INTERNAL_ENCLOSURE_WITH_N_MEDIA = BIT(1), - INTERNAL_ENCLOSURE_WITH_UNDEF_MEDIUM = BIT(2) + ENCLOSURE_WITH_N_MEDIA = BIT(1), + ENCLOSURE_WITH_UNDEF_MEDIUM = BIT(2) }; /******************************************************************************* @@ -814,18 +815,52 @@ error: } res_T -dump_enclosure_related_stuff_at_the_end_of_vtk +dump_boundaries_at_the_end_of_vtk (const struct stardis* stardis, FILE* stream) { res_T res = RES_OK; + const struct description* descriptions; + unsigned tsz, t; + ASSERT(stardis && stream); + + ERR(sg3d_geometry_get_unique_triangles_count(stardis->geometry.sg3d, &tsz)); + descriptions = darray_descriptions_cdata_get(&stardis->descriptions); + + fprintf(stream, "SCALARS Boundaries unsigned_int 1\n"); + fprintf(stream, "LOOKUP_TABLE default\n"); + FOR_EACH(t, 0, tsz) { + unsigned descr[SG3D_PROP_TYPES_COUNT__]; + ERR(sg3d_geometry_get_unique_triangle_properties(stardis->geometry.sg3d, t, + descr)); + if(descr[SG3D_INTFACE] != SG3D_UNSPECIFIED_PROPERTY + && DESC_IS_BOUNDARY(descriptions[descr[SG3D_INTFACE]].type)) + /* Descriptions are numbered from 1 in the log (so the 1+ below) */ + fprintf(stream, "%u\n", 1 + descr[SG3D_INTFACE]); + else fprintf(stream, "%u\n", SG3D_UNSPECIFIED_PROPERTY); + } + +exit: + return res; +error: + goto exit; +} + +res_T +dump_enclosure_related_stuff_at_the_end_of_vtk + (struct stardis* stardis, + FILE* stream) +{ + res_T res = RES_OK; unsigned* trgs = NULL; struct senc3d_enclosure* enc = NULL; unsigned tsz, e, s, t, scount, ecount, ocount; int* enc_status = NULL; + const struct description* descriptions; int invalid_enclosures_count = 0; ASSERT(stardis && stream); + descriptions = darray_descriptions_cdata_get(&stardis->descriptions); ERR(sg3d_geometry_get_unique_triangles_count(stardis->geometry.sg3d, &tsz)); trgs = MEM_CALLOC(stardis->allocator, tsz, sizeof(*trgs)); if(!trgs) { @@ -870,43 +905,191 @@ dump_enclosure_related_stuff_at_the_end_of_vtk res = RES_MEM_ERR; goto error; } + ASSERT(stardis->undefined_medium_behind_boundary_id != SENC3D_UNSPECIFIED_MEDIUM); FOR_EACH(e, 0, ecount) { struct senc3d_enclosure_header header; + unsigned tid, med, enc_fst_med = SENC3D_UNSPECIFIED_MEDIUM; + int is_fst_med = 1, is_err_cs = 0; enc_status[e] = NO_ENCLOSURE_ERROR; ERR(senc3d_scene_get_enclosure(stardis->senc3d_scn, e, &enc)); ERR(senc3d_enclosure_get_header(enc, &header)); - /* Check if anclosure is invalid regarding stardis solver requirements */ - if(!header.is_infinite) { - unsigned m, med; - if(header.enclosed_media_count != 1) - enc_status[e] |= INTERNAL_ENCLOSURE_WITH_N_MEDIA; - FOR_EACH(m, 0, header.enclosed_media_count) { - ERR(senc3d_enclosure_get_medium(enc, m, &med)); - if(med==SENC3D_UNSPECIFIED_MEDIUM) - enc_status[e] |= INTERNAL_ENCLOSURE_WITH_UNDEF_MEDIUM; + + FOR_EACH(t, 0, header.unique_primitives_count) { + unsigned prop[SG3D_PROP_TYPES_COUNT__]; + enum senc3d_side side; + size_t j; + ERR(senc3d_enclosure_get_triangle_id(enc, t, &tid, &side)); + FOR_EACH(j, 0, darray_uint_size_get(&stardis->compute_surface.err_triangles)) + { + unsigned prim + = darray_uint_cdata_get(&stardis->compute_surface.err_triangles)[j]; + if (prim == tid) { + is_err_cs = 1; + break; + } + } + if(is_err_cs) + /* Don't flag an enclosure invalid because of a triangle that is + * considered not member of it */ + continue; + + ERR(sg3d_geometry_get_unique_triangle_properties(stardis->geometry.sg3d, + tid, prop)); + + if(prop[side] != SG3D_UNSPECIFIED_PROPERTY) { + ASSERT(prop[side] < darray_descriptions_size_get(&stardis->descriptions)); + description_get_medium_id(descriptions + prop[side], &med); + } else { + /* If unspecified behind a boundary, use a specific ID to avoid to flag + * using different boundaries for a given enclosure as invalid */ + int properties_conflict_status; + validate_properties(t, prop, stardis, &properties_conflict_status); + if(properties_conflict_status == NO_PROPERTY_CONFLICT) + med = stardis->undefined_medium_behind_boundary_id; + else { + enc_status[e] |= ENCLOSURE_WITH_UNDEF_MEDIUM; + continue; /* Don't flag N_MEDIA at the same time */ + } + } + if(is_fst_med) { + is_fst_med = 0; + enc_fst_med = med; + } else { + if(enc_fst_med != med) + enc_status[e] |= ENCLOSURE_WITH_N_MEDIA; } - if(enc_status[e] != NO_ENCLOSURE_ERROR) invalid_enclosures_count++; } + /* The external (infinite) enclosure is always valid */ + if(enc_status[e] != NO_ENCLOSURE_ERROR && !header.is_infinite) + invalid_enclosures_count++; ERR(senc3d_enclosure_ref_put(enc)); } if(invalid_enclosures_count) { logger_print(stardis->logger, LOG_WARNING, "Found %d invalid enclosure(s).\n", invalid_enclosures_count); } - fprintf(stream, "FIELD FieldData 1\n"); - fprintf(stream, "Enclosure_ID %d %d unsigned_char\n", ecount, tsz); + fprintf(stream, "FIELD EnclosuresData 2\n"); + fprintf(stream, "Enclosures %d %d unsigned_char\n", ecount, tsz); FOR_EACH(t, 0, tsz) { + unsigned encs[2], is_err_cs = 0; + size_t j; + FOR_EACH(j, 0, darray_uint_size_get(&stardis->compute_surface.err_triangles)) + { + unsigned prim + = darray_uint_cdata_get(&stardis->compute_surface.err_triangles)[j]; + if(prim == t) { + is_err_cs = 1; + break; + } + } + if(is_err_cs) { + /* Triangles in compute surface with error are considered member of no + * enclosure */ + FOR_EACH(e, 1, ecount) fprintf(stream, "0 "); + fprintf(stream, "0\n"); + continue; + } + ERR(senc3d_scene_get_triangle_enclosures(stardis->senc3d_scn, t, encs)); + FOR_EACH(e, 0, ecount) { + unsigned c = (e == encs[SENC3D_FRONT] || e == encs[SENC3D_BACK]) + ? (unsigned char)enc_status[e] : 0; + if(e == ecount - 1) + fprintf(stream, "%u\n", c); + else fprintf(stream, "%u ", c); + } + } + +#define ENC_NOT_MEMBER SENC3D_UNSPECIFIED_MEDIUM +#define ENC_MEMBER_2_DISTINT_MEDIA (ENC_NOT_MEMBER - 1) +#define ENC_MEMBER_NO_MEDIUM (ENC_NOT_MEMBER - 2) + + fprintf(stream, "Enclosures_internal_media %d %d unsigned_int\n", ecount, tsz); + FOR_EACH(t, 0, tsz) { + unsigned descr[SG3D_PROP_TYPES_COUNT__]; unsigned encs[2]; + unsigned is_err_cs = 0; + size_t j; ERR(senc3d_scene_get_triangle_enclosures(stardis->senc3d_scn, t, encs)); + ERR(sg3d_geometry_get_unique_triangle_properties(stardis->geometry.sg3d, t, + descr)); + + /* Special value for triangles in compute surface with error */ + FOR_EACH(j, 0, darray_uint_size_get(&stardis->compute_surface.err_triangles)) + { + unsigned prim + = darray_uint_cdata_get(&stardis->compute_surface.err_triangles)[j]; + if(prim == t) { + is_err_cs = 1; + break; + } + } + if(is_err_cs) { + /* Triangles in compute surface with error are considered member of no + * enclosure */ + FOR_EACH(e, 1, ecount) fprintf(stream, "%u ", ENC_NOT_MEMBER); + fprintf(stream, "%u\n", ENC_NOT_MEMBER); + continue; + } FOR_EACH(e, 0, ecount) { - if(e == encs[SENC3D_FRONT] || e == encs[SENC3D_BACK]) - fprintf(stream, "%d ", (char)enc_status[e]); - else fprintf(stream, "0 "); + unsigned mid; + if(e == encs[SENC3D_FRONT] && e == encs[SENC3D_BACK]) { + /* Both sides of this triangle are in enclosure #e */ + unsigned fmid, bmid; + if(descr[SG3D_FRONT] != SG3D_UNSPECIFIED_PROPERTY) + description_get_medium_id(descriptions + descr[SG3D_FRONT], &fmid); + else if(descr[SG3D_INTFACE] != SG3D_UNSPECIFIED_PROPERTY + && DESC_IS_BOUNDARY(descriptions[descr[SG3D_INTFACE]].type)) + { + description_get_medium_id(descriptions + descr[SG3D_INTFACE], &fmid); + } + else fmid = ENC_MEMBER_NO_MEDIUM; + if(descr[SENC3D_BACK] != SG3D_UNSPECIFIED_PROPERTY) + description_get_medium_id(descriptions + descr[SENC3D_BACK], &bmid); + else if(descr[SG3D_INTFACE] != SG3D_UNSPECIFIED_PROPERTY + && DESC_IS_BOUNDARY(descriptions[descr[SG3D_INTFACE]].type)) + { + description_get_medium_id(descriptions + descr[SG3D_INTFACE], &bmid); + } + else bmid = ENC_MEMBER_NO_MEDIUM; + mid = (fmid == bmid) ? fmid : ENC_MEMBER_2_DISTINT_MEDIA; + } + else if(e == encs[SENC3D_FRONT]) { + /* Member of enclosure #e (front side only) */ + if(descr[SG3D_FRONT] != SG3D_UNSPECIFIED_PROPERTY) + description_get_medium_id(descriptions + descr[SG3D_FRONT], &mid); + else if(descr[SG3D_INTFACE] != SG3D_UNSPECIFIED_PROPERTY + && DESC_IS_BOUNDARY(descriptions[descr[SG3D_INTFACE]].type)) + { + description_get_medium_id(descriptions + descr[SG3D_INTFACE], &mid); + } + else mid = ENC_MEMBER_NO_MEDIUM; + } + else if(e == encs[SENC3D_BACK]) { + /* Member of enclosure #e (back side only) */ + if(descr[SENC3D_BACK] != SG3D_UNSPECIFIED_PROPERTY) + description_get_medium_id(descriptions + descr[SENC3D_BACK], &mid); + else if(descr[SG3D_INTFACE] != SG3D_UNSPECIFIED_PROPERTY + && DESC_IS_BOUNDARY(descriptions[descr[SG3D_INTFACE]].type)) + { + description_get_medium_id(descriptions + descr[SG3D_INTFACE], &mid); + } + else mid = ENC_MEMBER_NO_MEDIUM; + } else { + /* Not member of enclosure #e */ + mid = ENC_NOT_MEMBER; + } + if(e == ecount - 1) + fprintf(stream, "%u\n", mid); + else fprintf(stream, "%u ", mid); } - fprintf(stream, "\n"); } +#undef ENC_NOT_MEMBER +#undef ENC_ERR_COMPUTE_SURFACE +#undef ENC_MEMBER_2_DISTINT_MEDIA +#undef ENC_MEMBER_NO_MEDIUM + exit: MEM_RM(stardis->allocator, trgs); MEM_RM(stardis->allocator, enc_status); @@ -1132,10 +1315,10 @@ dump_compute_region_at_the_end_of_vtk res_T res = RES_OK; unsigned char* v = NULL; unsigned tsz, i; - size_t j; + size_t j, psz; ASSERT(stardis && stream); - ASSERT(darray_size_t_size_get(&stardis->compute_surface.primitives) - == darray_sides_size_get(&stardis->compute_surface.sides)); + psz = darray_size_t_size_get(&stardis->compute_surface.primitives); + ASSERT(psz == darray_sides_size_get(&stardis->compute_surface.sides)); ERR(sg3d_geometry_get_unique_triangles_count(stardis->geometry.sg3d, &tsz)); /* For triangles not in compute region v==0 */ @@ -1147,37 +1330,51 @@ dump_compute_region_at_the_end_of_vtk if(stardis->mode & SURFACE_COMPUTE_MODES) { /* For triangles in compute surface, v==1 if FRONT or v==2 for BACK */ - FOR_EACH(j, 0, darray_size_t_size_get(&stardis->compute_surface.primitives)) { - size_t prim = darray_size_t_cdata_get(&stardis->compute_surface.primitives)[j]; - enum sdis_side side = darray_sides_cdata_get(&stardis->compute_surface.sides)[j]; + FOR_EACH(j, 0, psz) { + size_t prim + = darray_size_t_cdata_get(&stardis->compute_surface.primitives)[j]; + enum sdis_side side + = darray_sides_cdata_get(&stardis->compute_surface.sides)[j]; ASSERT(prim <= tsz); v[(unsigned)prim] = (unsigned char)(v[(unsigned)prim] | (side == SDIS_FRONT ? 1 : 2)); } /* For triangles in compute surface with error v==MAX */ - FOR_EACH(j, 0, darray_uint_size_get(&stardis->compute_surface.err_triangles)) { - unsigned prim = darray_uint_cdata_get(&stardis->compute_surface.err_triangles)[j]; + FOR_EACH(j, 0, darray_uint_size_get(&stardis->compute_surface.err_triangles)) + { + unsigned prim + = darray_uint_cdata_get(&stardis->compute_surface.err_triangles)[j]; ASSERT(prim <= tsz); v[(unsigned)prim] = UCHAR_MAX; } } else { - unsigned prop[SG3D_PROP_TYPES_COUNT__]; + unsigned descr[SG3D_PROP_TYPES_COUNT__]; struct sdis_medium* medium; + const struct description* descriptions; unsigned medium_id; ASSERT(stardis->mode & MODE_MEDIUM_COMPUTE); medium = find_medium_by_name(stardis, &stardis->solve_name, &medium_id); ASSERT(medium != NULL); (void)medium; + descriptions = darray_descriptions_cdata_get(&stardis->descriptions); FOR_EACH(i, 0, tsz) { + unsigned f_mid, b_mid; + /* Get the description IDs for this triangle */ ERR(sg3d_geometry_get_unique_triangle_properties(stardis->geometry.sg3d, - i, prop)); + i, descr)); /* For triangles in compute volume, * v==1 if FRONT, v==2 for BACK */ - if(prop[SG3D_FRONT] == medium_id && prop[SG3D_BACK] == medium_id) + if(descr[SG3D_FRONT] == SG3D_UNSPECIFIED_PROPERTY) + f_mid = UINT_MAX; + else description_get_medium_id(descriptions + descr[SG3D_FRONT], &f_mid); + if(descr[SG3D_BACK] == SG3D_UNSPECIFIED_PROPERTY) + b_mid = UINT_MAX; + else description_get_medium_id(descriptions + descr[SG3D_BACK], &b_mid); + if(f_mid == medium_id && b_mid == medium_id) ; /* Keep v==0, not really a boundary */ - else if(prop[SG3D_FRONT] == medium_id) + else if(f_mid == medium_id) v[i] = 1; - else if(prop[SG3D_BACK] == medium_id) + else if(b_mid == medium_id) v[i] = 2; } } diff --git a/src/stardis-output.h b/src/stardis-output.h @@ -66,7 +66,7 @@ dump_green_bin extern res_T dump_enclosure_related_stuff_at_the_end_of_vtk - (const struct stardis* stardis, + (struct stardis* stardis, FILE* stream); extern res_T @@ -82,6 +82,11 @@ dump_map FILE* stream); extern res_T +dump_boundaries_at_the_end_of_vtk + (const struct stardis* stardis, + FILE* stream); + +extern res_T dump_compute_region_at_the_end_of_vtk (struct stardis* stardis, FILE* stream); diff --git a/src/stardis-parsing.c b/src/stardis-parsing.c @@ -177,8 +177,8 @@ add_geom_keep_degenerated static res_T read_sides_and_files (struct stardis* stardis, - const int side_is_intface, /* if 1, don't read side */ - const unsigned id, + const int descr_is_intface, /* if 1, don't read side */ + const unsigned description_id, char** tok_ctx) { char* tk = NULL; @@ -208,10 +208,10 @@ read_sides_and_files ERR(sstl_create(stardis->logger, stardis->allocator, 1, &sstl)); for(;;) { unsigned merge_errors; - if(side_is_intface) { + if(descr_is_intface) { add_geom_ctx.properties[SG3D_FRONT] = SG3D_UNSPECIFIED_PROPERTY; add_geom_ctx.properties[SG3D_BACK] = SG3D_UNSPECIFIED_PROPERTY; - add_geom_ctx.properties[SG3D_INTFACE] = id; + add_geom_ctx.properties[SG3D_INTFACE] = description_id; } else { tk = strtok_r(NULL, " \t", tok_ctx); if(!tk) { @@ -227,16 +227,16 @@ read_sides_and_files _strupr(tk); add_geom_ctx.properties[SG3D_INTFACE] = SG3D_UNSPECIFIED_PROPERTY; if(0 == strcmp(tk, "FRONT")) { - add_geom_ctx.properties[SG3D_FRONT] = id; + add_geom_ctx.properties[SG3D_FRONT] = description_id; add_geom_ctx.properties[SG3D_BACK] = SG3D_UNSPECIFIED_PROPERTY; } else if(0 == strcmp(tk, "BACK")) { add_geom_ctx.properties[SG3D_FRONT] = SG3D_UNSPECIFIED_PROPERTY; - add_geom_ctx.properties[SG3D_BACK] = id; + add_geom_ctx.properties[SG3D_BACK] = description_id; } else if(0 == strcmp(tk, "BOTH")) { - add_geom_ctx.properties[SG3D_FRONT] = id; - add_geom_ctx.properties[SG3D_BACK] = id; + add_geom_ctx.properties[SG3D_FRONT] = description_id; + add_geom_ctx.properties[SG3D_BACK] = description_id; } else { logger_print(stardis->logger, LOG_ERROR, @@ -247,7 +247,7 @@ read_sides_and_files } tk = strtok_r(NULL, " \t", tok_ctx); if(!tk) { - if(!side_is_intface /* Has read a side */ + if(!descr_is_intface /* Has read a side */ || !file_count) /* Need at least 1 file */ { logger_print(stardis->logger, LOG_ERROR, @@ -342,7 +342,7 @@ init_args darray_str_init(allocator, &args->model_files); /* Set default values */ args->samples = STARDIS_DEFAULT_SAMPLES_COUNT; - args->nthreads = DEFAULT_NTHREADS; + args->nthreads = SDIS_NTHREADS_DEFAULT; args->probe[3] = STARDIS_DEFAULT_COMPUTE_TIME; args->ambient_temp = STARDIS_DEFAULT_AMBIENT_TEMP; args->ref_temp = STARDIS_DEFAULT_REFERENCE_TEMP; @@ -1023,6 +1023,7 @@ find_description_by_name static res_T process_h (struct stardis* stardis, + struct dummies* dummies, const enum description_type type, char** tok_ctx) { @@ -1034,12 +1035,21 @@ process_h ASSERT(stardis && tok_ctx); sz = darray_descriptions_size_get(&stardis->descriptions); - ASSERT(sz <= UINT_MAX); ERR(darray_descriptions_resize(&stardis->descriptions, sz+1)); desc = darray_descriptions_data_get(&stardis->descriptions) + sz; init_h(stardis->allocator, &desc->d.h_boundary); - desc->d.h_boundary.mat_id = (unsigned)sz; + if(type == DESC_BOUND_H_FOR_SOLID) { + /* Need a dedicated fluid */ + allocate_stardis_medium_id(stardis, &desc->d.h_boundary.mat_id); + } else { + /* Can use dummy solid */ + if(dummies->dummy_solid_id == UINT_MAX) { + /* Allocate an ID for dummy solid */ + allocate_stardis_medium_id(stardis, &dummies->dummy_solid_id); + } + desc->d.h_boundary.mat_id = dummies->dummy_solid_id; + } desc->type = type; CHK_TOK(strtok_r(NULL, " \t", tok_ctx), "h boundary name"); @@ -1093,7 +1103,8 @@ process_h goto end; } - ERR(read_sides_and_files(stardis, 1, desc->d.h_boundary.mat_id, tok_ctx)); + ASSERT(sz <= UINT_MAX); + ERR(read_sides_and_files(stardis, 1, (unsigned)sz, tok_ctx)); end: return res; @@ -1106,6 +1117,7 @@ error: static res_T process_t (struct stardis* stardis, + struct dummies* dummies, const enum description_type type, char** tok_ctx) { @@ -1117,12 +1129,10 @@ process_t ASSERT(stardis && tok_ctx); sz = darray_descriptions_size_get(&stardis->descriptions); - ASSERT(sz <= UINT_MAX); ERR(darray_descriptions_resize(&stardis->descriptions, sz + 1)); desc = darray_descriptions_data_get(&stardis->descriptions) + sz; init_t(stardis->allocator, &desc->d.t_boundary); - desc->d.t_boundary.mat_id = (unsigned)sz; desc->type = type; CHK_TOK(strtok_r(NULL, " \t", tok_ctx), "temperature boundary name"); @@ -1146,6 +1156,11 @@ process_t goto end; } if(type == DESC_BOUND_T_FOR_FLUID) { + if(dummies->dummy_solid_id == UINT_MAX) { + /* Allocate an ID for dummy solid */ + allocate_stardis_medium_id(stardis, &dummies->dummy_solid_id); + } + desc->d.t_boundary.mat_id = dummies->dummy_solid_id; CHK_TOK(strtok_r(NULL, " \t", tok_ctx), "emissivity"); res = cstr_to_double(tk, &desc->d.t_boundary.emissivity); if(res != RES_OK @@ -1176,9 +1191,16 @@ process_t if(res == RES_OK) res = RES_BAD_ARG; goto end; } + } else { + if(dummies->dummy_fluid_id == UINT_MAX) { + /* Allocate an ID for dummy fluid */ + allocate_stardis_medium_id(stardis, &dummies->dummy_fluid_id); + } + desc->d.t_boundary.mat_id = dummies->dummy_fluid_id; } - ERR(read_sides_and_files(stardis, 1, desc->d.t_boundary.mat_id, tok_ctx)); + ASSERT(sz <= UINT_MAX); + ERR(read_sides_and_files(stardis, 1, (unsigned)sz, tok_ctx)); end: return res; @@ -1190,6 +1212,7 @@ error: static res_T process_flx (struct stardis* stardis, + struct dummies* dummies, char** tok_ctx) { char* tk = NULL; @@ -1200,12 +1223,15 @@ process_flx ASSERT(stardis && tok_ctx); sz = darray_descriptions_size_get(&stardis->descriptions); - ASSERT(sz <= UINT_MAX); ERR(darray_descriptions_resize(&stardis->descriptions, sz + 1)); desc = darray_descriptions_data_get(&stardis->descriptions) + sz; init_f(stardis->allocator, &desc->d.f_boundary); - desc->d.f_boundary.mat_id = (unsigned)sz; + if(dummies->dummy_fluid_id == UINT_MAX) { + /* Allocate an ID for dummy fluid */ + allocate_stardis_medium_id(stardis, &dummies->dummy_fluid_id); + } + desc->d.f_boundary.mat_id = dummies->dummy_fluid_id; desc->type = DESC_BOUND_F_FOR_SOLID; CHK_TOK(strtok_r(NULL, " \t", tok_ctx), "flux boundary name"); @@ -1229,7 +1255,8 @@ process_flx goto end; } - ERR(read_sides_and_files(stardis, 1, desc->d.f_boundary.mat_id, tok_ctx)); + ASSERT(sz <= UINT_MAX); + ERR(read_sides_and_files(stardis, 1, (unsigned)sz, tok_ctx)); end: return res; @@ -1246,18 +1273,19 @@ process_sfc char* tk = NULL; struct description* desc; size_t sz; - unsigned connection_id; res_T res = RES_OK; ASSERT(stardis && tok_ctx); sz = darray_descriptions_size_get(&stardis->descriptions); - ASSERT(sz <= UINT_MAX); ERR(darray_descriptions_resize(&stardis->descriptions, sz + 1)); desc = darray_descriptions_data_get(&stardis->descriptions) + sz; init_sf(stardis->allocator, &desc->d.sf_connect); - connection_id = (unsigned)sz; + /* Use a medium ID even if there is no medium here + * As other cases use media IDs as unique IDs for read_sides_and_files calls + * we continue the trend to ensure connection ID is OK */ + allocate_stardis_medium_id(stardis, &desc->d.sf_connect.connection_id); desc->type = DESC_SOLID_FLUID_CONNECT; CHK_TOK(strtok_r(NULL, " \t", tok_ctx), "solid fluid connection name"); @@ -1302,7 +1330,8 @@ process_sfc goto end; } - ERR(read_sides_and_files(stardis, 1, connection_id, tok_ctx)); + ASSERT(sz <= UINT_MAX); + ERR(read_sides_and_files(stardis, 1, (unsigned)sz, tok_ctx)); end: return res; @@ -1403,12 +1432,11 @@ process_solid ASSERT(stardis && tok_ctx); sz = darray_descriptions_size_get(&stardis->descriptions); - ASSERT(sz <= UINT_MAX); ERR(darray_descriptions_resize(&stardis->descriptions, sz + 1)); desc = darray_descriptions_data_get(&stardis->descriptions) + sz; init_solid(stardis->allocator, &desc->d.solid); - desc->d.solid.solid_id = (unsigned)sz; + allocate_stardis_medium_id(stardis, &desc->d.solid.solid_id); desc->type = DESC_MAT_SOLID; CHK_TOK(strtok_r(NULL, " \t", tok_ctx), "solid name"); @@ -1469,7 +1497,8 @@ process_solid goto end; } - ERR(read_sides_and_files(stardis, 0, desc->d.solid.solid_id, tok_ctx)); + ASSERT(sz <= UINT_MAX); + ERR(read_sides_and_files(stardis, 0, (unsigned)sz, tok_ctx)); end: return res; @@ -1491,12 +1520,11 @@ process_fluid ASSERT(stardis && tok_ctx); sz = darray_descriptions_size_get(&stardis->descriptions); - ASSERT(sz <= UINT_MAX); ERR(darray_descriptions_resize(&stardis->descriptions, sz + 1)); desc = darray_descriptions_data_get(&stardis->descriptions) + sz; init_fluid(stardis->allocator, &desc->d.fluid); - desc->d.fluid.fluid_id = (unsigned)sz; + allocate_stardis_medium_id(stardis, &desc->d.fluid.fluid_id); desc->type = DESC_MAT_FLUID; CHK_TOK(strtok_r(NULL, " \t", tok_ctx), "fluid name"); @@ -1541,7 +1569,8 @@ process_fluid ERR(read_imposed_temperature(stardis, &desc->d.fluid.imposed_temperature, tok_ctx)); - ERR(read_sides_and_files(stardis, 0, desc->d.fluid.fluid_id, tok_ctx)); + ASSERT(sz <= UINT_MAX); + ERR(read_sides_and_files(stardis, 0, (unsigned)sz, tok_ctx)); end: return res; @@ -1600,7 +1629,8 @@ res_T process_model_line (const char* file_name, char* line, - struct stardis* stardis) + struct stardis* stardis, + struct dummies* dummies) { res_T res = RES_OK; struct str keep; @@ -1614,15 +1644,15 @@ process_model_line _strupr(tk); if(0 == strcmp(tk, "H_BOUNDARY_FOR_SOLID")) - ERR(process_h(stardis, DESC_BOUND_H_FOR_SOLID, &tok_ctx)); + ERR(process_h(stardis, dummies, DESC_BOUND_H_FOR_SOLID, &tok_ctx)); else if(0 == strcmp(tk, "H_BOUNDARY_FOR_FLUID")) - ERR(process_h(stardis, DESC_BOUND_H_FOR_FLUID, &tok_ctx)); + ERR(process_h(stardis, dummies, DESC_BOUND_H_FOR_FLUID, &tok_ctx)); else if(0 == strcmp(tk, "T_BOUNDARY_FOR_SOLID")) - ERR(process_t(stardis, DESC_BOUND_T_FOR_SOLID, &tok_ctx)); + ERR(process_t(stardis, dummies, DESC_BOUND_T_FOR_SOLID, &tok_ctx)); else if(0 == strcmp(tk, "T_BOUNDARY_FOR_FLUID")) - ERR(process_t(stardis, DESC_BOUND_T_FOR_FLUID, &tok_ctx)); + ERR(process_t(stardis, dummies, DESC_BOUND_T_FOR_FLUID, &tok_ctx)); else if(0 == strcmp(tk, "F_BOUNDARY_FOR_SOLID")) - ERR(process_flx(stardis, &tok_ctx)); + ERR(process_flx(stardis, dummies, &tok_ctx)); else if(0 == strcmp(tk, "SOLID_FLUID_CONNECTION")) ERR(process_sfc(stardis, &tok_ctx)); else if(0 == strcmp(tk, "SOLID")) diff --git a/src/stardis-parsing.h b/src/stardis-parsing.h @@ -27,6 +27,7 @@ struct camera; struct logger; struct mem_allocator; struct stardis; +struct dummies; /* Utility macros */ #define CHK_TOK(x, Name) if((tk = (x)) == NULL) {\ @@ -136,18 +137,6 @@ add_geom_ctx_position void* context); extern LOCAL_SYM res_T -add_geom_count_degenerate -(const unsigned itri, - void* context, - int* abort); - -#ifdef NDEBUG -#define DEFAULT_NTHREADS SDIS_NTHREADS_DEFAULT -#else -#define DEFAULT_NTHREADS 1 -#endif - -extern LOCAL_SYM res_T init_args (struct logger* logger, struct mem_allocator* mem, @@ -193,6 +182,7 @@ extern LOCAL_SYM res_T process_model_line (const char* file_name, char* line, - struct stardis* stardis); + struct stardis* stardis, + struct dummies* dummies); #endif /*ARGS_H*/