stardis

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

commit d08ffec02dc3feb65f17dca8094c34eda2b742c3
parent 8f577c6286759d0405e81e3eb9217d5ebd36c155
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date:   Thu, 26 Mar 2020 18:03:35 +0100

Still refactoring. Add a logger.

Diffstat:
Msrc/main.c | 75++++++++++++++++++++++++++++++++++++++++++++++++++-------------------------
Msrc/stardis-app.c | 589+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------
Msrc/stardis-app.h | 364+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------
Msrc/stardis-compute.c | 575++++++++++++++++++++++++++-----------------------------------------------------
Msrc/stardis-compute.h | 32++++++++++----------------------
Msrc/stardis-fluid.c | 28++++++++++++----------------
Msrc/stardis-fluid.h | 9+++------
Msrc/stardis-intface.c | 185+++++++++++++++++++++++++++++++++----------------------------------------------
Msrc/stardis-intface.h | 23++++-------------------
Msrc/stardis-output.c | 373+++++++++++++++++++++++++++++++++++++++++++------------------------------------
Msrc/stardis-output.h | 25+++++++++++--------------
Msrc/stardis-parsing.c | 578+++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------------
Msrc/stardis-parsing.h | 58+++++++++++++++++++++++++++++++++++++++++-----------------
Msrc/stardis-solid.c | 25++++++++++++-------------
Msrc/stardis-solid.h | 9+++------
15 files changed, 1769 insertions(+), 1179 deletions(-)

diff --git a/src/main.c b/src/main.c @@ -3,9 +3,11 @@ #include "stardis-app.h" #include "stardis-parsing.h" #include "stardis-output.h" +#include "stardis-compute.h" #include <rsys/rsys.h> #include <rsys/mem_allocator.h> +#include <rsys/logger.h> #include <stdio.h> @@ -16,48 +18,71 @@ main { struct args* args = NULL; struct stardis stardis; - int allocator_initialized = 0, stardis_initialized = 0; - int err = 0; + int logger_initialized = 0, allocator_initialized = 0, + args_initialized = 0, stardis_initialized = 0; + int err = EXIT_SUCCESS; struct mem_allocator allocator; + struct logger logger; res_T res = RES_OK; ERR(mem_init_proxy_allocator(&allocator, &mem_default_allocator)); allocator_initialized = 1; - ERR(init_args(&allocator, &args)); + + ERR(logger_init(&allocator, &logger)); + logger_initialized = 1; + /* Active loggin for args pasing */ + logger_set_stream(&logger, LOG_OUTPUT, log_prt, NULL); + logger_set_stream(&logger, LOG_ERROR, log_err, NULL); + logger_set_stream(&logger, LOG_WARNING, log_warn, NULL); + + ERR(init_args(&logger, &allocator, &args)); + args_initialized = 1; ERR(parse_args(argc, argv, args)); - if(args->just_help) goto exit; - if(args->mode == UNDEF_MODE) { - fprintf(stderr, "Nothing to do.\n" - "One of the following options should be used:"); - print_multiple_modes(stderr, EXCLUSIVE_MODES); - fprintf(stderr, "\n" - "Use the -h option to get help.\n"); + if(args->mode & DUMP_HELP) { + print_help(stdout, argv[0]); + goto exit; + } + else if(args->mode & DUMP_VERSION) { + print_version(stdout); goto exit; } - ERR(stardis_init(args, &stardis)); + /* Deactivate some loggin according to the -V arg */ + if(args->verbose < 1) + logger_set_stream(&logger, LOG_ERROR, NULL, NULL); + if(args->verbose < 2) + logger_set_stream(&logger, LOG_WARNING, NULL, NULL); + if(args->verbose < 3) + logger_set_stream(&logger, LOG_OUTPUT, NULL, NULL); + + ERR(stardis_init(args, &logger, &allocator, &stardis)); stardis_initialized = 1; + release_args(args); + args_initialized = 0; - if(args->mode & DUMP_VTK) { + if(stardis.mode & DUMP_VTK) { + /* Dump all the app-independent information */ ERR(sg3d_geometry_dump_as_vtk(stardis.geometry.sg3d, stdout)); - /* If it applies dump the compute region */ - if(args->mode & REGION_COMPUTE_MODES) + /* Dump the compute region if any */ + if(stardis.mode & REGION_COMPUTE_MODES) ERR(dump_compute_region_at_the_end_of_vtk(&stardis, stdout)); - /* If it applies dump holes */ - if(has_holes(&stardis)) - ERR(dump_holes_at_the_end_of_vtk(&stardis, stdout)); - goto exit; /* If dump flag set, then dump and exit */ - } - else if(args->mode & COMPUTE_MODES) { - ERR(stardis_compute(&stardis, args->mode)); - } else { - fprintf(stderr, "Unknown mode: %c.\n", mode_option(args->mode)); + /* Dump possible holes + * TODO: as this extracts enclosures, it could dump front/back + * enclosure IDs too */ + ERR(dump_enclosure_related_stuff_at_the_end_of_vtk(&stardis, stdout)); + + /* If dump flag set, then dump and exit */ + goto exit; } + ASSERT(stardis.mode & COMPUTE_MODES); + ERR(stardis_compute(&stardis)); + exit: - release_args(args); + if(args_initialized) release_args(args); if(stardis_initialized) stardis_release(&stardis); + if(logger_initialized) logger_release(&logger); if(allocator_initialized) { if(MEM_ALLOCATED_SIZE(&allocator) != 0) { char dump[4096] = { '\0' }; @@ -70,6 +95,6 @@ exit: } return err; error: - err = -1; + err = EXIT_FAILURE; goto exit; } diff --git a/src/stardis-app.c b/src/stardis-app.c @@ -3,11 +3,52 @@ #include "stardis-app.h" #include "stardis-output.h" #include "stardis-compute.h" +#include "stardis-intface.h" +#include "stardis-fluid.h" +#include "stardis-solid.h" + +#include <star/sg3d_sdisXd_helper.h> #include <rsys/text_reader.h> +#include <rsys/logger.h> #include <string.h> +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_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, + NO_BOUND_BETWEEN_FLUIDS, + TRG_WITH_NO_PROPERTY, + NO_BOUND_BETWEEN_FLUID_AND_UNDEF, + NO_BOUND_BETWEEN_SOLID_AND_UNDEF, + PROPERTIES_CONFLICT_COUNT__ +}; + /******************************************************************************* * Local Functions ******************************************************************************/ @@ -29,7 +70,9 @@ read_model const char* name = str_cget(files + i); f = fopen(name, "r"); if(!f) { - fprintf(stderr, "Cannot open model file '%s'\n", name); + logger_print(stardis->logger, LOG_ERROR, + "Cannot open model file '%s'\n", + name); res = RES_IO_ERR; goto error; } @@ -39,7 +82,7 @@ read_model ERR(txtrdr_read_line(txtrdr)); line = txtrdr_get_line(txtrdr); if(!line) break; - ERR(process_model_line(line, stardis)); + ERR(process_model_line(name, line, stardis)); } txtrdr_ref_put(txtrdr); txtrdr = NULL; @@ -57,14 +100,48 @@ error: } #define COUNT_SIDE(Rank) {\ - if(properties[(Rank)] == SG3D_UNSPECIFIED_PROPERTY) u_count++;\ + if(properties[(Rank)] == SG3D_UNSPECIFIED_PROPERTY) undef_count++;\ else {\ - ASSERT(properties[(Rank)] < darray_descriptions_size_get(descriptions));\ + 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) s_count++;\ - else f_count++;\ + if(descs[properties[(Rank)]].type == DESC_MAT_SOLID) solid_count++;\ + else fluid_count++;\ + }\ +} + +#define PRT_INCOHERENT_TRG() {\ + struct str str;\ + str_init(stardis->allocator, &str);\ + ERR(logger_print(stardis->logger, LOG_WARNING,\ + "Incoherent triangle description (%u)\n", itri));\ + if(!front_defined)\ + ERR(logger_print(stardis->logger, LOG_OUTPUT, "Front: undefined\n"));\ + else {\ + ERR(str_printf(&str, "Front: "));\ + ERR(print_description(&str, descs + properties[SG3D_FRONT]));\ + ERR(str_printf(&str, "\n"));\ + ERR(logger_print(stardis->logger, LOG_OUTPUT, str_cget(&str))); \ }\ + str_clear(&str);\ + if(!back_defined)\ + ERR(logger_print(stardis->logger, LOG_OUTPUT, "Back: undefined\n"));\ + else {\ + ERR(str_printf(&str, "Back: "));\ + ERR(print_description(&str, descs + properties[SG3D_BACK]));\ + ERR(str_printf(&str, "\n"));\ + ERR(logger_print(stardis->logger, LOG_OUTPUT, str_cget(&str))); \ + }\ + str_clear(&str);\ + if(!connect_defined)\ + ERR(logger_print(stardis->logger, LOG_OUTPUT, "Connection: undefined\n"));\ + else {\ + ERR(str_printf(&str, "Connection: "));\ + ERR(print_description(&str, descs + properties[SG3D_INTFACE]));\ + ERR(str_printf(&str, "\n"));\ + ERR(logger_print(stardis->logger, LOG_OUTPUT, str_cget(&str))); \ + }\ + str_release(&str);\ } static res_T @@ -74,57 +151,303 @@ validate_properties void* context, int* properties_conflict_status) { - struct darray_descriptions* descriptions = context; - unsigned u_count, s_count, f_count, i_count; - const struct description* descs, * d = NULL; + 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; + int front_defined, back_defined, connect_defined; (void)itri; - ASSERT(descriptions && properties_conflict_status); - descs = darray_descriptions_cdata_get(descriptions); - u_count = s_count = f_count = i_count = 0; + 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) - u_count++; - else i_count++; + undef_count++; + else intface_count++; - ASSERT(u_count + s_count + f_count + i_count == 3); - if(i_count) { - ASSERT(properties[SG3D_INTFACE] < darray_descriptions_size_get(descriptions)); - d = descs + properties[SG3D_INTFACE]; - } - if(f_count > 1) { - /* Cannot have 2 fluids */ - *properties_conflict_status = 1; - } - else if(u_count > 1) { - /* Cannot have undefined interface if 1 side is undefined */ - *properties_conflict_status = 1; - } - else if(u_count == 1) { - if(!(s_count == 2 && !d) - && !(s_count == 1 && d - && (d->type == DESC_BOUND_H_FOR_SOLID || d->type == DESC_BOUND_H_FOR_SOLID))) - { - /* The only valid configurations are Solid / Undef / Solid - * and Solid / Solid_bound / Undef */ - *properties_conflict_status = 1; + front_defined = (properties[SG3D_FRONT] != SG3D_UNSPECIFIED_PROPERTY); + back_defined = (properties[SG3D_BACK] != SG3D_UNSPECIFIED_PROPERTY); + connect_defined = (properties[SG3D_INTFACE] != SG3D_UNSPECIFIED_PROPERTY); + + 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)) { + PRT_INCOHERENT_TRG(); + logger_print(stardis->logger, LOG_ERROR, + "Can only define a DESC_BOUND_H_FOR_FLUID boundary for a fluid region\n"); + 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)) { + PRT_INCOHERENT_TRG(); + logger_print(stardis->logger, LOG_ERROR, + "Can only define a DESC_BOUND_H_FOR_SOLID boundary for a solid region\n"); + 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)) { + PRT_INCOHERENT_TRG(); + logger_print(stardis->logger, LOG_ERROR, + "Can only define a DESC_BOUND_T_FOR_FLUID boundary for a fluid region\n"); + 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)) { + PRT_INCOHERENT_TRG(); + logger_print(stardis->logger, LOG_ERROR, + "Can only define a DESC_BOUND_T_FOR_SOLID boundary for a solid region\n"); + 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)) { + PRT_INCOHERENT_TRG(); + logger_print(stardis->logger, LOG_ERROR, + "Can only define a DESC_BOUND_F_FOR_SOLID boundary for a solid region\n"); + 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) { + PRT_INCOHERENT_TRG(); + logger_print(stardis->logger, LOG_ERROR, + "Can only define a DESC_SOLID_FLUID_CONNECT between a fluid and a solid\n"); + 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 < 2) + *properties_conflict_status = SFCONNECT_USED_AS_BOUNDARY; + else FATAL("error:" STR(__FILE__) ":" STR(__LINE__)"\n"); + goto end; + } + break; + default: + FATAL("error:" STR(__FILE__) ":" STR(__LINE__)": Invalid type.\n"); } } else { - ASSERT(u_count == 0 && d); - if(s_count != 1 || f_count != 1 || d->type != DESC_SOLID_FLUID_CONNECT) { - /* The only valid configuration is Solid / Solid_Fluid_bound / Fluid */ - *properties_conflict_status = 1; + /* No interface defined */ + ASSERT(intface_count == 0 && undef_count >= 1); + if(fluid_count == 2) { + *properties_conflict_status = NO_BOUND_BETWEEN_FLUIDS; + goto end; + } + if(undef_count == 3) { + *properties_conflict_status = TRG_WITH_NO_PROPERTY; + 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; + } + /* Undef interface between solids is OK */ + if(undef_count == 1) CHK(solid_count == 2); } - - /* No conflict found */ - *properties_conflict_status = 0; - return RES_OK; + +end: + return res; +error: + goto end; } #undef COUNT_SIDE +#undef PRT_INCOHERENT_TRG + +static struct sdis_interface* +geometry_get_interface + (const size_t itri, void* ctx) +{ + struct darray_interface_ptrs* app_interface_data = ctx; + ASSERT(app_interface_data + && itri < darray_interface_ptrs_size_get(app_interface_data)); + return darray_interface_ptrs_cdata_get(app_interface_data)[itri]; +} + +static res_T +create_holder + (struct stardis* stardis, + struct dummies* dummies, + const unsigned idx, + const int is_green) +{ + res_T res = RES_OK; + struct description* description; + + ASSERT(stardis && dummies + && idx < darray_descriptions_size_get(&stardis->descriptions)); + + description = darray_descriptions_data_get(&stardis->descriptions) + idx; + switch (description->type) { + case DESC_BOUND_H_FOR_SOLID: + stardis->counts.hbound_count++; + /* Create an external fluid with imposed temperature */ + 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); + break; + case DESC_BOUND_H_FOR_FLUID: + stardis->counts.hbound_count++; + 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); + 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; + logger_print(stardis->logger, LOG_OUTPUT, + "Dummy solid (id=%u): lambda=1 rho=1 cp=1\n", + dummies->dummy_solid_id); + } + break; + case DESC_BOUND_T_FOR_SOLID: + stardis->counts.tbound_count++; + 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); + 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; + logger_print(stardis->logger, LOG_OUTPUT, + "Dummy fluid (id=%u): rho=1 cp=1\n", dummies->dummy_fluid_id); + } + break; + case DESC_BOUND_T_FOR_FLUID: + stardis->counts.tbound_count++; + 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); + 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; + logger_print(stardis->logger, LOG_OUTPUT, + "Dummy solid (id=%u): lambda=1 rho=1 cp=1\n", + dummies->dummy_solid_id); + } + break; + case DESC_BOUND_F_FOR_SOLID: + stardis->counts.fbound_count++; + 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); + 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; + logger_print(stardis->logger, LOG_OUTPUT, + "Dummy fluid (id=%u): rho=1 cp=1\n", dummies->dummy_fluid_id); + } + break; + case DESC_SOLID_FLUID_CONNECT: + stardis->counts.sfconnect_count++; + ASSERT(description->d.sf_connect.specular_fraction >= 0 + && description->d.sf_connect.specular_fraction <= 1); + ASSERT(description->d.sf_connect.emissivity >= 0); + ASSERT(description->d.sf_connect.hc >= 0); + break; + case DESC_MAT_SOLID: + stardis->counts.smed_count++; + ERR(create_stardis_solid(stardis, + &description->d.solid.name, + description->d.solid.lambda, + description->d.solid.rho, + description->d.solid.cp, + description->d.solid.delta, + is_green, + 0, + description->d.solid.tinit, + description->d.solid.imposed_temperature, + description->d.solid.vpower, + &description->d.solid.solid_id)); + break; + case DESC_MAT_FLUID: + stardis->counts.fmed_count++; + ERR(create_stardis_fluid(stardis, + &description->d.fluid.name, + description->d.fluid.rho, + description->d.fluid.cp, + is_green, + 0, + description->d.fluid.tinit, + description->d.fluid.imposed_temperature, + &description->d.fluid.fluid_id)); + break; + default: + FATAL("error:" STR(__FILE__) ":" STR(__LINE__)": Invalid type.\n"); + } + +end: + return res; +error: + goto end; +} /******************************************************************************* * Public Functions @@ -133,26 +456,38 @@ validate_properties res_T stardis_init (const struct args* args, + struct logger* logger, + struct mem_allocator* allocator, struct stardis* stardis) { res_T res = RES_OK; - int geom_initialized = 0; - unsigned count; - int run = 1; + struct sg3d_sdisXd_scene_create_context create_context; + struct dummies dummies = DUMMIES_NULL; + struct htable_intface htable_interfaces; + struct str str; + unsigned i, vcount, tcount, count; + int is_for_compute; - ASSERT(args && stardis && args->allocator); + ASSERT(args && logger && allocator && stardis); - stardis->allocator = args->allocator; + /* Init everithing that cannot fail */ + stardis->logger = logger; + stardis->allocator = allocator; + htable_intface_init(stardis->allocator, &htable_interfaces); darray_descriptions_init(stardis->allocator, &stardis->descriptions); stardis->probe[0] = args->probe[0]; stardis->probe[1] = args->probe[1]; stardis->probe[2] = args->probe[2]; stardis->probe[3] = args->probe[3]; + stardis->dev = NULL; + stardis->sdis_scn = NULL; + stardis->mode = args->mode; + stardis->counts = COUNTS_NULL; init_camera(&stardis->camera); str_init(stardis->allocator, &stardis->solve_name); - darray_size_t_init(stardis->allocator, &stardis->compute_region.primitives); - darray_sides_init(stardis->allocator, &stardis->compute_region.sides); - darray_uint_init(stardis->allocator, &stardis->compute_region.err_triangles); + darray_size_t_init(stardis->allocator, &stardis->compute_surface.primitives); + darray_sides_init(stardis->allocator, &stardis->compute_surface.sides); + darray_uint_init(stardis->allocator, &stardis->compute_surface.err_triangles); stardis->samples = args->samples; stardis->nthreads = args->nthreads; stardis->scale_factor = args->scale_factor; @@ -164,90 +499,144 @@ stardis_init if(args->dump_paths & DUMP_SUCCESS) stardis->dump_paths |= SDIS_HEAT_PATH_SUCCESS; stardis->verbose = args->verbose; - ERR(init_geometry(stardis->allocator, stardis->verbose, &stardis->geometry)); - geom_initialized = 1; + darray_media_ptr_init(stardis->allocator, &stardis->media); + + is_for_compute = (stardis->mode & COMPUTE_MODES); + ERR(init_geometry(stardis->logger, stardis->allocator, stardis->verbose, + &stardis->geometry)); - if(args->mode & IR_COMPUTE) - ERR(parse_camera(args->camera, &stardis->camera)); - else if(args->mode & MEDIUM_COMPUTE) + if(args->mode & IR_COMPUTE) { + ERR(parse_camera(stardis->logger, args->camera, &stardis->camera)); + } + else if(args->mode & MEDIUM_COMPUTE) { ERR(str_set(&stardis->solve_name, args->medium_name)); - else if(args->mode & (BOUNDARY_COMPUTE | MAP_COMPUTE)) - ERR(str_set(&stardis->solve_name, args->solve_boundary_filename)); - + } + else if(args->mode & SURFACE_COMPUTE_MODES) { + ERR(str_set(&stardis->solve_name, args->solve_filename)); + } ERR(read_model(&args->model_files, stardis)); - /* If computation is on a compute region, read it */ - if(args->mode & REGION_COMPUTE_MODES) { - ASSERT(!str_is_empty(&stardis->solve_name)); - ERR(read_compute_region(stardis)); - } + ERR(sdis_device_create(stardis->logger, stardis->allocator, args->nthreads, + args->verbose, &stardis->dev)); - /* Check conflicts */ - ERR(sg3d_geometry_get_unique_triangles_with_merge_conflict_count( - stardis->geometry.sg3d, &count)); - if(count) { - fprintf(stderr, - "Merge conflicts found in the the model (%u triangles).\n", count); - run = 0; - res = RES_BAD_ARG; - /* Don't goto error to allow further checking */ + /* Create media and property holders for those found in descriptions */ + str_init(stardis->allocator, &str); + for(i = 0; i < darray_descriptions_size_get(&stardis->descriptions); i++) { + ERR(create_holder(stardis, &dummies, i, stardis->mode & GREEN_MODE)); + str_clear(&str); + str_printf(&str, "Description %d: ", i); + ERR(print_description(&str, + darray_descriptions_cdata_get(&stardis->descriptions) + i)); + ERR(str_printf(&str, "\n")); + logger_print(stardis->logger, LOG_OUTPUT, str_cget(&str)); } + str_release(&str); + + create_context.geometry = stardis->geometry.sg3d; + create_context.app_interface_getter = geometry_get_interface; + create_context.app_interface_data = &stardis->geometry.interf_bytrg; + 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->descriptions)); + validate_properties, stardis)); ERR(sg3d_geometry_get_unique_triangles_with_properties_conflict_count( stardis->geometry.sg3d, &count)); if(count) { - fprintf(stderr, + logger_print(stardis->logger, (is_for_compute ? LOG_ERROR : LOG_WARNING), "Properties conflicts found in the the model (%u triangles).\n", count); - run = 0; - res = RES_BAD_ARG; - /* Don't goto error to allow further checking */ + if(is_for_compute) { + res = RES_BAD_ARG; + goto error; + } + } + + for(i = 0; i < tcount; ++i) { + ERR(create_intface(stardis, i, &htable_interfaces)); } - if(args->mode & REGION_COMPUTE_MODES) { + + /* If computation is on a compute surface, read it */ + if(args->mode & SURFACE_COMPUTE_MODES) { + ASSERT(!str_is_empty(&stardis->solve_name)); + ERR(read_compute_surface(stardis)); + /* Check compute surface */ ERR(sg3d_geometry_validate_properties(stardis->geometry.sg3d, - validate_properties, &stardis->descriptions)); + validate_properties, stardis)); ERR(sg3d_geometry_get_unique_triangles_with_properties_conflict_count( stardis->geometry.sg3d, &count)); if(count) { - fprintf(stderr, "Invalid compute region defined by file '%s'.\n", + logger_print(stardis->logger, (is_for_compute ? LOG_ERROR : LOG_WARNING), + "Invalid compute region defined by file '%s'.\n", str_cget(&stardis->solve_name)); - fprintf(stderr, + logger_print(stardis->logger, (is_for_compute ? LOG_ERROR : LOG_WARNING), "The file contains %u triangles not in the model.\n", count); - run = 0; + if(is_for_compute) { + res = RES_BAD_ARG; + goto error; + } + } + } + /* If computation is on a volume, check medium is known */ + if(args->mode & MEDIUM_COMPUTE) { + if(!find_medium_by_name(stardis, &stardis->solve_name, NULL)) { + logger_print(stardis->logger, (is_for_compute ? LOG_ERROR : LOG_WARNING), + "Cannot find medium '%s'\n", str_cget(&stardis->solve_name)); res = RES_BAD_ARG; + goto error; } } - if(!run) { - fprintf(stderr, "Cannot run the solver.\n"); - goto error; + + /* Check conflicts */ + ERR(sg3d_geometry_get_unique_triangles_with_merge_conflict_count( + stardis->geometry.sg3d, &count)); + if(count) { + logger_print(stardis->logger, (is_for_compute ? LOG_ERROR : LOG_WARNING), + "Merge conflicts found in the the model (%u triangles).\n", count); + if(is_for_compute) { + res = RES_BAD_ARG; + goto error; + } } + if(is_for_compute) { + ASSERT(darray_interface_ptrs_size_get(&stardis->geometry.interf_bytrg) + == tcount); + res = sdis_scene_create(stardis->dev, tcount, + sg3d_sdisXd_geometry_get_indices, + sg3d_sdisXd_geometry_get_interface, + vcount, sg3d_sdisXd_geometry_get_position, + &create_context, &stardis->sdis_scn); + if(res != RES_OK) { + logger_print(stardis->logger, LOG_ERROR, + "Cannot create the stardis solver scene, no computation possible.\n"); + goto error; + } + } + exit: + htable_intface_release(&htable_interfaces); return res; error: - if(geom_initialized) release_geometry(&stardis->geometry); - darray_descriptions_release(&stardis->descriptions); - str_release(&stardis->solve_name); - darray_size_t_release(&stardis->compute_region.primitives); - darray_sides_release(&stardis->compute_region.sides); - darray_uint_release(&stardis->compute_region.err_triangles); + stardis_release(stardis); goto exit; } void stardis_release(struct stardis* stardis) { - struct sdis_interface** itf; - struct description* dsc; + size_t i; - if(!stardis) return; + ASSERT(stardis); - itf = darray_interface_ptrs_data_get(&stardis->geometry.interfaces); - dsc = darray_descriptions_data_get(&stardis->descriptions); + if(stardis->dev) SDIS(device_ref_put(stardis->dev)); + if(stardis->sdis_scn) SDIS(scene_ref_put(stardis->sdis_scn)); str_release(&stardis->solve_name); darray_descriptions_release(&stardis->descriptions); release_geometry(&stardis->geometry); - darray_size_t_release(&stardis->compute_region.primitives); - darray_sides_release(&stardis->compute_region.sides); - darray_uint_release(&stardis->compute_region.err_triangles); + darray_size_t_release(&stardis->compute_surface.primitives); + darray_sides_release(&stardis->compute_surface.sides); + darray_uint_release(&stardis->compute_surface.err_triangles); + FOR_EACH(i, 0, darray_media_ptr_size_get(&stardis->media)) + SDIS(medium_ref_put(darray_media_ptr_data_get(&stardis->media)[i])); + darray_media_ptr_release(&stardis->media); } diff --git a/src/stardis-app.h b/src/stardis-app.h @@ -19,6 +19,11 @@ #include <limits.h> +/* Forward declarations */ +struct logger; +struct mem_allocator; +struct sdis_medium; + /* Utility macros */ #define ERR(Expr) if((res = (Expr)) != RES_OK) goto error; else (void)0 @@ -40,53 +45,137 @@ enum description_type { #define DARRAY_DATA struct sdis_interface* #include <rsys/dynamic_array.h> +struct dummies { + struct sdis_medium* dummy_fluid; + unsigned dummy_fluid_id; + struct sdis_medium* dummy_solid; + unsigned dummy_solid_id; +}; +#define DUMMIES_NULL__ {\ + NULL, UINT_MAX, NULL, UINT_MAX\ +} + +#define DARRAY_NAME media_ptr +#define DARRAY_DATA struct sdis_medium* +#include <rsys/dynamic_array.h> + struct geometry { struct sg3d_geometry* sg3d; - struct sdis_scene* sdis_scn; struct darray_interface_ptrs interf_bytrg; struct darray_interface_ptrs interfaces; }; +static INLINE void +release_geometry(struct geometry* geom) +{ + size_t i; + struct sdis_interface + ** intf = darray_interface_ptrs_data_get(&geom->interfaces); + if(geom->sg3d) SG3D(geometry_ref_put(geom->sg3d)); + for(i = 0; i < darray_interface_ptrs_size_get(&geom->interfaces); ++i) + SDIS(interface_ref_put(intf[i])); + darray_interface_ptrs_release(&geom->interfaces); + darray_interface_ptrs_release(&geom->interf_bytrg); +} + static INLINE res_T init_geometry - (struct mem_allocator* allocator, + (struct logger* logger, + struct mem_allocator* allocator, const int verbose, struct geometry* geom) { res_T res = RES_OK; struct sg3d_device* sg3d_dev = NULL; - struct sg3d_geometry* sg3d = NULL; - ASSERT(allocator && geom); - ERR(sg3d_device_create(NULL, allocator, verbose, &sg3d_dev)); - ERR(sg3d_geometry_create(sg3d_dev, &sg3d)); + ASSERT(allocator && geom); + + geom->sg3d = NULL; darray_interface_ptrs_init(allocator, &geom->interfaces); darray_interface_ptrs_init(allocator, &geom->interf_bytrg); + ERR(sg3d_device_create(logger, allocator, verbose, &sg3d_dev)); + ERR(sg3d_geometry_create(sg3d_dev, &geom->sg3d)); exit: - geom->sg3d = sg3d; - geom->sdis_scn = NULL; if(sg3d_dev) SG3D(device_ref_put(sg3d_dev)); return res; error: - if(sg3d) SG3D(geometry_ref_put(sg3d)); - sg3d = NULL; + release_geometry(geom); goto exit; } -static INLINE void -release_geometry(struct geometry* geom) +/******************************************************************************* + * rsys/str additions + ******************************************************************************/ +static res_T +ensure_allocated(struct str* str, const size_t len, const char keep_old) { - size_t i; - struct sdis_interface - **intf = darray_interface_ptrs_data_get(&geom->interfaces); - if(geom->sg3d) SG3D(geometry_ref_put(geom->sg3d)); - if(geom->sdis_scn) SDIS(scene_ref_put(geom->sdis_scn)); - for(i = 0; i < darray_interface_ptrs_size_get(&geom->interfaces); ++i) - SDIS(interface_ref_put(intf[i])); - darray_interface_ptrs_release(&geom->interfaces); - darray_interface_ptrs_release(&geom->interf_bytrg); + char* buf = NULL; + const size_t alloc_granularity = 32; + size_t mod = 0; + size_t new_len = 0; + size_t new_size = 0; + ASSERT(str); + + if(len * sizeof(char) <= str->allocated) + return RES_OK; + + mod = len % alloc_granularity; + new_len = !mod ? len : len - mod + alloc_granularity; + new_size = new_len * sizeof(char); + buf = MEM_ALLOC(str->allocator, new_size); + if(!buf) + return RES_MEM_ERR; + + if(keep_old) { + strncpy(buf, str->cstr, new_len - 1); + buf[new_len - 1] = '\0'; + } + + str->allocated = new_len * sizeof(char); + if(str->cstr != str->buffer) + MEM_RM(str->allocator, str->cstr); + + str->cstr = buf; + return RES_OK; +} + +static res_T +str_printf +(struct str* str, + const char* fmt, ...) +#ifdef COMPILER_GCC + __attribute((format(printf, 3, 4))) +#endif +{ + res_T res = RES_OK; + size_t initial_len, left; + va_list args_cp; + int needed = 0; + va_list args; + ASSERT(str && fmt); + va_start(args, fmt); + + initial_len = str_len(str); + left = str->allocated - initial_len; + ASSERT(left >= 0); + if(left) { + VA_COPY(args_cp, args); + needed = vsnprintf(str->cstr+ initial_len, left, fmt, args_cp); + } + if(needed >= left) { + ERR(ensure_allocated(str, initial_len + needed + 1, 1)); + left = str->allocated - initial_len; + needed = vsnprintf(str->cstr+ initial_len, left, fmt, args); + CHK(needed < left); + } + va_end(args); +end: + return res; +error: + goto end; } +/******************************************************************************/ struct mat_fluid { struct str name; @@ -115,16 +204,23 @@ release_fluid(struct mat_fluid* fluid) str_release(&fluid->name); } -static void -print_fluid(FILE* stream, const struct mat_fluid* f) +static res_T +print_fluid + (struct str* str, + const struct mat_fluid* f) { - ASSERT(stream && f); - fprintf(stream, "Fluid '%s': rho=%g cp=%g", - str_cget(&f->name), f->rho, f->cp); - if(f->tinit >= 0) fprintf(stream, " Tinit=%g", f->tinit); + res_T res = RES_OK; + ASSERT(str && f); + ERR(str_printf(str, "Fluid '%s': rho=%g cp=%g", + str_cget(&f->name), f->rho, f->cp)); + if(f->tinit >= 0) + ERR(str_printf(str, " Tinit=%g", f->tinit)); if(f->imposed_temperature >= 0) - fprintf(stream, " Temp=%g", f->imposed_temperature); - fprintf(stream, "\n"); + ERR(str_printf(str, " Temp=%g", f->imposed_temperature)); +end: + return res; +error: + goto end; } static FINLINE res_T @@ -172,18 +268,25 @@ release_solid(struct mat_solid* solid) str_release(&solid->name); } -static void -print_solid(FILE* stream, const struct mat_solid* s) -{ - ASSERT(stream && s); - fprintf(stream, - "Solid '%s': lambda=%g rho=%g cp=%g delta=%g", - str_cget(&s->name), s->lambda, s->rho, s->cp, s->delta); - if(s->vpower != 0) fprintf(stream, " VPower=%g", s->vpower); - if(s->tinit >= 0) fprintf(stream, " Tinit=%g", s->tinit); +static res_T +print_solid + (struct str* str, + const struct mat_solid* s) +{ + res_T res = RES_OK; + ASSERT(str && s); + ERR(str_printf(str, "Solid '%s': lambda=%g rho=%g cp=%g delta=%g", + str_cget(&s->name), s->lambda, s->rho, s->cp, s->delta)); + if(s->vpower != 0) + ERR(str_printf(str, " VPower=%g", s->vpower)); + if(s->tinit >= 0) + ERR(str_printf(str, " Tinit=%g", s->tinit)); if(s->imposed_temperature >= 0) - fprintf(stream, " Temp=%g", s->imposed_temperature); - fprintf(stream, "\n"); + ERR(str_printf(str, " Temp=%g", s->imposed_temperature)); +end: + return res; +error: + goto end; } static FINLINE res_T @@ -228,20 +331,24 @@ release_h_boundary(struct h_boundary* bound) str_release(&bound->name); } -static void +static res_T print_h_boundary - (FILE* stream, + (struct str* str, const struct h_boundary* b, const enum description_type type) { - ASSERT(stream && b + res_T res = RES_OK; + ASSERT(str && b && (type == DESC_BOUND_H_FOR_SOLID || type == DESC_BOUND_H_FOR_FLUID)); - fprintf(stream, - "H boundary for %s '%s': emissivity=%g specular_fraction=%g hc=%g T=%g\n", - (type == DESC_BOUND_H_FOR_SOLID ? "solid" : "fluid"), - str_cget(&b->name), - b->emissivity, b->specular_fraction, b->hc, - b->imposed_temperature); + ERR(str_printf(str, + "H boundary for %s '%s': emissivity=%g specular_fraction=%g hc=%g T=%g " + "(using medium %u as external medium)", + (type == DESC_BOUND_H_FOR_SOLID ? "solid" : "fluid"), str_cget(&b->name), + b->emissivity, b->specular_fraction, b->hc, b->imposed_temperature, b->mat_id)); +end: + return res; +error: + goto end; } static FINLINE res_T @@ -259,6 +366,8 @@ cp_h_boundary(struct h_boundary* dst, const struct h_boundary* src) struct t_boundary { struct str name; unsigned mat_id; + double emissivity; + double specular_fraction; double hc; double imposed_temperature; }; @@ -268,6 +377,8 @@ init_t(struct mem_allocator* allocator, struct t_boundary* dst) { str_init(allocator, &dst->name); dst->mat_id = UINT_MAX; + dst->emissivity = 0; + dst->specular_fraction = 0; dst->hc = 0; dst->imposed_temperature = -1; return RES_OK; @@ -279,19 +390,28 @@ release_t_boundary(struct t_boundary* bound) str_release(&bound->name); } -static void +static res_T print_t_boundary - (FILE* stream, + (struct str* str, const struct t_boundary* b, const enum description_type type) { - ASSERT(stream && b + res_T res = RES_OK; + ASSERT(str && b && (type == DESC_BOUND_T_FOR_SOLID || type == DESC_BOUND_T_FOR_FLUID)); - fprintf(stream, - "T boundary for %s' %s': hc=%g T=%f\n", + ERR(str_printf(str, "T boundary for %s' %s': T=%g ", (type == DESC_BOUND_T_FOR_SOLID ? "solid" : "fluid"), - str_cget(&b->name), - b->hc, b->imposed_temperature); + str_cget(&b->name), b->imposed_temperature)); + + if(type == DESC_BOUND_T_FOR_FLUID) + ERR(str_printf(str, "emissivity=%g, specular_fraction=%g hc=%g ", + b->emissivity, b->specular_fraction, b->hc)); + + ERR(str_printf(str, "(using medium %u as external medium)", b->mat_id)); +end: + return res; +error: + goto end; } static FINLINE res_T @@ -299,8 +419,10 @@ cp_t_boundary(struct t_boundary* dst, const struct t_boundary* src) { str_copy(&dst->name, &src->name); dst->mat_id = src->mat_id; - dst->imposed_temperature = src->imposed_temperature; + dst->emissivity = src->emissivity; + dst->specular_fraction = src->specular_fraction; dst->hc = src->hc; + dst->imposed_temperature = src->imposed_temperature; return RES_OK; } @@ -325,16 +447,20 @@ release_f_boundary(struct f_boundary* bound) str_release(&bound->name); } -static void +static res_T print_f_boundary - (FILE* stream, + (struct str* str, const struct f_boundary* b) { - ASSERT(stream && b); - fprintf(stream, - "F boundary for SOLID '%s': flux=%f\n", - str_cget(&b->name), - b->imposed_flux); + res_T res = RES_OK; + ASSERT(str && b); + ERR(str_printf(str, + "F boundary for SOLID '%s': flux=%g (using medium %u as external medium)", + str_cget(&b->name), b->imposed_flux, b->mat_id)); +end: + return res; +error: + goto end; } static FINLINE res_T @@ -369,17 +495,20 @@ init_sf(struct mem_allocator* allocator, struct solid_fluid_connect* dst) return RES_OK; } -static void +static res_T print_sf_connect - (FILE* stream, + (struct str* str, const struct solid_fluid_connect* c) { - ASSERT(stream && c); - fprintf(stream, "Solid-Fluid connection '%s':", str_cget(&c->name)); - fprintf(stream, " emissivity=%f, specular_fraction=%f", - c->emissivity, c->specular_fraction); - fprintf(stream, " hc=%f", c->hc); - fprintf(stream, "\n"); + res_T res = RES_OK; + ASSERT(str && c); + ERR(str_printf(str, "Solid-Fluid connection '%s':", str_cget(&c->name))); + ERR(str_printf(str, " emissivity=%g, specular_fraction=%g hc=%g", + c->emissivity, c->specular_fraction, c->hc)); +end: + return res; +error: + goto end; } static FINLINE res_T @@ -448,40 +577,47 @@ release_description(struct description* desc) } } -static INLINE void +static INLINE res_T print_description - (FILE* stream, + (struct str* str, const struct description* desc) { - ASSERT(stream && desc); + res_T res = RES_OK; + ASSERT(str && desc); switch (desc->type) { case DESC_MAT_SOLID: - print_solid(stream, &desc->d.solid); + ERR(print_solid(str, &desc->d.solid)); break; case DESC_MAT_FLUID: - print_fluid(stream, &desc->d.fluid); + ERR(print_fluid(str, &desc->d.fluid)); break; case DESC_BOUND_T_FOR_SOLID: case DESC_BOUND_T_FOR_FLUID: - print_t_boundary(stream, &desc->d.t_boundary, desc->type); + ERR(print_t_boundary(str, &desc->d.t_boundary, desc->type)); break; case DESC_BOUND_H_FOR_SOLID: case DESC_BOUND_H_FOR_FLUID: - print_h_boundary(stream, &desc->d.h_boundary, desc->type); + ERR(print_h_boundary(str, &desc->d.h_boundary, desc->type)); break; case DESC_BOUND_F_FOR_SOLID: - print_f_boundary(stream, &desc->d.f_boundary); + ERR(print_f_boundary(str, &desc->d.f_boundary)); break; case DESC_SOLID_FLUID_CONNECT: - print_sf_connect(stream, &desc->d.sf_connect); + ERR(print_sf_connect(str, &desc->d.sf_connect)); break; default: FATAL("error:" STR(__FILE__) ":" STR(__LINE__)": Invalid type.\n"); } +end: + return res; +error: + goto end; } static FINLINE res_T -cp_description(struct description* dst, const struct description* src) +cp_description + (struct description* dst, + const struct description* src) { res_T res = RES_OK; ASSERT(src && dst); @@ -560,6 +696,50 @@ init_camera(struct camera* cam) { cam->time = INF; } +static void +log_err(const char* msg, void* ctx) +{ + ASSERT(msg); + (void)ctx; +#ifdef OS_WINDOWS + fprintf(stderr, "error: %s", msg); +#else + fprintf(stderr, "\x1b[31merror:\x1b[0m %s", msg); +#endif +} + +static void +log_warn(const char* msg, void* ctx) +{ + ASSERT(msg); + (void)ctx; +#ifdef OS_WINDOWS + fprintf(stderr, "warning: %s", msg); +#else + fprintf(stderr, "\x1b[33mwarning:\x1b[0m %s", msg); +#endif +} + +static void +log_prt(const char* msg, void* ctx) +{ + ASSERT(msg); + (void)ctx; +#ifdef OS_WINDOWS + fprintf(stderr, "message: %s", msg); +#else + fprintf(stderr, "\x1b[32moutput:\x1b[0m %s", msg); +#endif +} + +struct counts { + size_t smed_count, fmed_count, tbound_count, hbound_count, + fbound_count, sfconnect_count; +}; +#define COUNTS_NULL__ {\ + 0, 0, 0, 0, 0, 0\ + } + /* Type to store the primitives of a compute region */ #define DARRAY_NAME sides #define DARRAY_DATA enum sdis_side @@ -572,7 +752,7 @@ init_camera(struct camera* cam) { #define DARRAY_FUNCTOR_RELEASE release_description #include <rsys/dynamic_array.h> -struct compute_region { +struct compute_surface { struct darray_size_t primitives; struct darray_sides sides; struct darray_uint err_triangles; @@ -580,20 +760,27 @@ struct compute_region { struct stardis { struct geometry geometry; + struct sdis_scene* sdis_scn; /* The solver scene */ struct darray_descriptions descriptions; /* Materials and boundaries */ + struct darray_media_ptr media; + struct counts counts; double probe[4]; /* x,y,z,t of probe when mode is PROBE_COMPUTE */ struct camera camera; /* camera when mode is IR_COMPUTE */ struct str solve_name; /* medium name when mode is MEDIUM_COMPUTE, boundary file name when [FLUX_]BOUNDARY_COMPUTE map file name when MAP_COMPUTE */ - struct compute_region compute_region; /* Compute region when mode is - BOUNDARY_COMPUTE or BOUNDARY_COMPUTE */ + struct compute_surface compute_surface; /* 2D compute region when mode is + [FLUX_]BOUNDARY_COMPUTE + or MAP_COMPUTE */ + int mode; size_t samples; unsigned nthreads; double scale_factor; double radiative_temp[2]; struct mem_allocator* allocator; + struct logger* logger; + struct sdis_device* dev; enum sdis_heat_path_flag dump_paths; int verbose; }; @@ -601,13 +788,10 @@ struct stardis { extern LOCAL_SYM res_T stardis_init (const struct args* args, + struct logger* logger, + struct mem_allocator* allocator, struct stardis* stardis); -extern LOCAL_SYM res_T -stardis_compute - (struct stardis* stardis, - const int mode); - extern LOCAL_SYM void stardis_release (struct stardis* stardis); diff --git a/src/stardis-compute.c b/src/stardis-compute.c @@ -5,7 +5,6 @@ #include "stardis-compute.h" #include "stardis-fluid.h" #include "stardis-solid.h" -#include "stardis-intface.h" #include <sdis.h> #include <sdis_version.h> @@ -14,19 +13,9 @@ #include <rsys/double3.h> #include <rsys/double2.h> +#include <rsys/logger.h> #include <rsys/image.h> -struct dummies { - struct sdis_medium* dummy_fluid; - unsigned dummy_fluid_id; - struct sdis_medium* dummy_solid; - unsigned dummy_solid_id; -}; -#define DUMMIES_NULL__ {\ - NULL, UINT_MAX, NULL, UINT_MAX\ -} -static const struct dummies DUMMIES_NULL = DUMMIES_NULL__; - /******************************************************************************* * Local Functions ******************************************************************************/ @@ -35,8 +24,7 @@ static const struct dummies DUMMIES_NULL = DUMMIES_NULL__; * if on_interface is set */ static res_T select_probe_type - (const struct sdis_scene* scn, - const struct stardis* stardis, + (const struct stardis* stardis, const int on_interface, double pos[3], size_t* iprim, @@ -50,7 +38,7 @@ select_probe_type const struct description* descriptions; unsigned i, tcount; - ASSERT(scn && stardis && pos && iprim && uv); + ASSERT(stardis && pos && iprim && uv); descriptions = darray_descriptions_cdata_get(&stardis->descriptions); ERR(sg3d_geometry_get_unique_triangles_count(stardis->geometry.sg3d, &tcount)); for(i = 0; i < tcount; ++i) { @@ -63,15 +51,15 @@ select_probe_type ERR(sg3d_geometry_get_unique_triangle_vertices(stardis->geometry.sg3d, i, indices)); - ERR(sdis_scene_boundary_project_position(scn, i, pos, tmp_uv)); - ERR(sdis_scene_get_boundary_position(scn, i, tmp_uv, projected_pos)); + ERR(sdis_scene_boundary_project_position(stardis->sdis_scn, i, pos, tmp_uv)); + ERR(sdis_scene_get_boundary_position(stardis->sdis_scn, i, tmp_uv, projected_pos)); d3_sub(dp, projected_pos, pos); d = d3_len(dp); if(d == 0) { /* Best possible match */ found = i; - fprintf(stderr, + logger_print(stardis->logger, LOG_OUTPUT, "The probe is on the primitive %llu.\n", (long long int)*iprim); break; } @@ -119,29 +107,31 @@ select_probe_type if(!min_desc) { /* Doesn't handle the case where pos is outside the model * but very close and could be considered on the boundary */ - fprintf(stderr, "The probe is outside the model.\n"); + logger_print(stardis->logger, LOG_ERROR, "The probe is outside the model.\n"); return RES_BAD_ARG; } if(on_interface) { *iprim = found; if(min_type == DESC_MAT_FLUID) - fprintf(stderr, "Probe was on a fluid.\n"); - fprintf(stderr, "The probe is moved to %g,%g,%g (primitive %llu)\n", + logger_print(stardis->logger, LOG_OUTPUT, "Probe was on a fluid.\n"); + logger_print(stardis->logger, LOG_OUTPUT, + "The probe is moved to %g,%g,%g (primitive %llu)\n", SPLIT3(new_pos), (long long int)*iprim); if(min_type == DESC_MAT_SOLID && min_d > min_delta) - fprintf(stderr, "WARNING: The probe move is %.1f delta long.\n", min_d / min_delta); + logger_print(stardis->logger, LOG_WARNING, + "The probe move is %.1f delta long.\n", min_d / min_delta); d3_set(pos, new_pos); d2_set(uv, min_uv); } else { if(min_type == DESC_MAT_FLUID) - fprintf(stderr, + logger_print(stardis->logger, LOG_WARNING, "The probe is in a fluid: computing fluid temperature, not using a specific position.\n"); if(min_type == DESC_MAT_SOLID && min_d < min_delta) { - fprintf(stderr, - "WARNING: The probe is very close to the primitive %llu (%.1f delta).\n", + logger_print(stardis->logger, LOG_WARNING, + "The probe is very close to the primitive %llu (%.1f delta).\n", (long long int)found, min_d / min_delta); - fprintf(stderr, + logger_print(stardis->logger, LOG_WARNING, "To have this probe moved on the closest interface use -P instead of -p\n"); } } @@ -153,131 +143,7 @@ error: } static res_T -create_holder - (struct mem_allocator* allocator, - struct counts* counts, - struct dummies* dummies, - struct description* description, - struct sdis_device* dev, - struct darray_media_ptr* media_ptr, - const int is_green) -{ - res_T res = RES_OK; - - ASSERT(allocator && counts && dummies && description && dev && media_ptr); - - switch (description->type) { - case DESC_BOUND_H_FOR_SOLID: - counts->hbound_count++; - /* Create an external fluid with bound temp as fluid temp */ - ERR(create_fluid(dev, allocator, NULL, 1, 1, is_green, 1, -1, - description->d.h_boundary.imposed_temperature, media_ptr, - &description->d.h_boundary.mat_id)); - break; - case DESC_BOUND_H_FOR_FLUID: - /* Create an external solid with bound temp as solid temp */ - counts->hbound_count++; - ERR(create_solid(dev, allocator, NULL, INF, 1, 1, 1, is_green, 1, -1, - description->d.h_boundary.imposed_temperature, 0, media_ptr, - &description->d.h_boundary.mat_id)); - break; - case DESC_BOUND_T_FOR_SOLID: - counts->tbound_count++; - 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(media_ptr); - ERR(create_fluid(dev, allocator, NULL, 1, 1, is_green, 1, -1, - -1, media_ptr, &description->d.t_boundary.mat_id)); - dummies->dummy_fluid = darray_media_ptr_data_get(media_ptr)[sz]; - dummies->dummy_fluid_id = description->d.t_boundary.mat_id; - } - break; - case DESC_BOUND_T_FOR_FLUID: - counts->tbound_count++; - 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(media_ptr); - ERR(create_solid(dev, allocator, NULL, 1, 1, 1, 1, is_green, 1, -1, - -1, 0, media_ptr, &description->d.t_boundary.mat_id)); - dummies->dummy_solid = darray_media_ptr_data_get(media_ptr)[sz]; - dummies->dummy_solid_id = description->d.t_boundary.mat_id; - } - break; - case DESC_BOUND_F_FOR_SOLID: - counts->fbound_count++; - 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(media_ptr); - ERR(create_fluid(dev, allocator, NULL, 1, 1, is_green, 1, -1, -1, - media_ptr, &description->d.f_boundary.mat_id)); - dummies->dummy_fluid = darray_media_ptr_data_get(media_ptr)[sz]; - dummies->dummy_fluid_id = description->d.f_boundary.mat_id; - } - break; - case DESC_SOLID_FLUID_CONNECT: - counts->sfconnect_count++; - ASSERT(description->d.sf_connect.specular_fraction >= 0 - && description->d.sf_connect.specular_fraction <= 1); - ASSERT(description->d.sf_connect.emissivity >= 0); - ASSERT(description->d.sf_connect.hc >= 0); - break; - case DESC_MAT_SOLID: - counts->smed_count++; - ERR(create_solid(dev, - allocator, - &description->d.solid.name, - description->d.solid.lambda, - description->d.solid.rho, - description->d.solid.cp, - description->d.solid.delta, - is_green, - 0, - description->d.solid.tinit, - description->d.solid.imposed_temperature, - description->d.solid.vpower, - media_ptr, - &description->d.solid.solid_id)); - break; - case DESC_MAT_FLUID: - counts->fmed_count++; - ERR(create_fluid(dev, - allocator, - &description->d.fluid.name, - description->d.fluid.rho, - description->d.fluid.cp, - is_green, - 0, - description->d.fluid.tinit, - description->d.fluid.imposed_temperature, - media_ptr, - &description->d.fluid.fluid_id)); - - break; - default: - FATAL("error:" STR(__FILE__) ":" STR(__LINE__)": Invalid type.\n"); - } - -end: - return res; -error: - goto end; -} - -static res_T -compute_probe - (struct sdis_scene* scn, - const struct counts* counts, - struct stardis* stardis, - enum stardis_mode mode) +compute_probe(struct stardis* stardis) { res_T res = RES_OK; double time[2], pos[3], uv[2] = { 0,0 }; @@ -285,25 +151,25 @@ compute_probe struct sdis_green_function* green = NULL; struct sdis_estimator* estimator = NULL; - ASSERT(scn && counts && stardis && (mode & PROBE_COMPUTE)); + ASSERT(stardis && (stardis->mode & PROBE_COMPUTE)); d3_set(pos, stardis->probe); - ERR(select_probe_type(scn, stardis, 0, pos, &iprim, uv)); + ERR(select_probe_type(stardis, 0, pos, &iprim, uv)); - if(mode & GREEN_MODE) { + if(stardis->mode & GREEN_MODE) { ASSERT(iprim == SIZE_MAX); - ERR(sdis_solve_probe_green_function(scn, + ERR(sdis_solve_probe_green_function(stardis->sdis_scn, stardis->samples, pos, stardis->scale_factor, stardis->radiative_temp[0], stardis->radiative_temp[1], &green)); - ERR(dump_green(green, counts, &stardis->descriptions, stardis->radiative_temp)); + ERR(dump_green(green, stardis, stdout)); } else { ASSERT(iprim == SIZE_MAX); d2_splat(time, stardis->probe[3]); - ERR(sdis_solve_probe(scn, + ERR(sdis_solve_probe(stardis->sdis_scn, stardis->samples, pos, time, @@ -312,7 +178,7 @@ compute_probe stardis->radiative_temp[1], stardis->dump_paths, &estimator)); - ERR(print_single_MC_result(mode, estimator, stardis)); + ERR(print_single_MC_result(estimator, stardis, stdout)); } end: if(estimator) SDIS(estimator_ref_put(estimator)); @@ -323,11 +189,7 @@ error: } static res_T -compute_probe_on_interface - (struct sdis_scene* scn, - const struct counts* counts, - struct stardis* stardis, - const int mode) +compute_probe_on_interface(struct stardis* stardis) { res_T res = RES_OK; double time[2], pos[3], uv[2] = { 0,0 }; @@ -335,13 +197,13 @@ compute_probe_on_interface struct sdis_estimator* estimator = NULL; struct sdis_green_function* green = NULL; - ASSERT(scn && counts && stardis && (mode & PROBE_COMPUTE_ON_INTERFACE)); + ASSERT(stardis && (stardis->mode & PROBE_COMPUTE_ON_INTERFACE)); d3_set(pos, stardis->probe); - ERR(select_probe_type(scn, stardis, 1, pos, &iprim, uv)); + ERR(select_probe_type(stardis, 1, pos, &iprim, uv)); - if(mode & GREEN_MODE) { + if(stardis->mode & GREEN_MODE) { ASSERT(iprim == SIZE_MAX); - ERR(sdis_solve_probe_boundary_green_function(scn, + ERR(sdis_solve_probe_boundary_green_function(stardis->sdis_scn, stardis->samples, iprim, uv, @@ -350,22 +212,22 @@ compute_probe_on_interface stardis->radiative_temp[0], stardis->radiative_temp[1], &green)); - ERR(dump_green(green, counts, &stardis->descriptions, stardis->radiative_temp)); + ERR(dump_green(green, stardis, stdout)); } else { ASSERT(iprim == SIZE_MAX); d2_splat(time, stardis->probe[3]); - ERR(sdis_solve_probe_boundary(scn, + ERR(sdis_solve_probe_boundary(stardis->sdis_scn, stardis->samples, iprim, uv, time, - SDIS_FRONT, /* FIXME!!!!!!! */ + SDIS_FRONT, stardis->scale_factor, stardis->radiative_temp[0], stardis->radiative_temp[1], stardis->dump_paths, &estimator)); - ERR(print_single_MC_result(mode, estimator, stardis)); + ERR(print_single_MC_result(estimator, stardis, stdout)); } end: if(estimator) SDIS(estimator_ref_put(estimator)); @@ -376,11 +238,7 @@ error: } static res_T -compute_camera - (struct sdis_device* dev, - struct sdis_scene* scn, - const struct stardis* stardis, - const int mode) +compute_camera(const struct stardis* stardis) { res_T res = RES_OK; double time[2]; @@ -388,13 +246,13 @@ compute_camera struct sdis_estimator_buffer* buf = NULL; struct sdis_camera* cam = NULL; - ASSERT(!(mode & GREEN_MODE) && (mode & IR_COMPUTE) && scn && stardis); - (void)mode; + ASSERT(stardis + && !(stardis->mode & GREEN_MODE) && (stardis->mode & IR_COMPUTE)); width = (size_t)stardis->camera.img[0]; height = (size_t)stardis->camera.img[1]; /* Setup the camera */ - ERR(sdis_camera_create(dev, &cam)); + ERR(sdis_camera_create(stardis->dev, &cam)); ERR(sdis_camera_set_proj_ratio(cam, (double)width / (double)height)); ERR(sdis_camera_set_fov(cam, MDEG2RAD(stardis->camera.fov))); ERR(sdis_camera_look_at(cam, @@ -404,7 +262,7 @@ compute_camera /* Launch the simulation */ time[0] = time[1] = stardis->camera.time; - ERR(sdis_solve_camera(scn, + ERR(sdis_solve_camera(stardis->sdis_scn, cam, time, stardis->scale_factor, @@ -413,11 +271,11 @@ compute_camera width, height, (size_t)stardis->camera.spp, - stardis->dump_paths, + 0, &buf)); /* Write the image */ - ERR(dump_image(buf)); + ERR(dump_image(buf, stdout)); end: if(cam) SDIS(camera_ref_put(cam)); @@ -428,60 +286,39 @@ error: } static res_T -compute_medium - (struct sdis_scene* scn, - struct darray_media_ptr* media_ptr, - struct stardis* stardis, - const int mode) +compute_medium(struct stardis* stardis) { res_T res = RES_OK; double time[2]; - size_t sz, ii; struct sdis_medium* medium = NULL; struct sdis_estimator* estimator = NULL; struct sdis_green_function* green = NULL; - ASSERT(scn && media_ptr && stardis && (mode & MEDIUM_COMPUTE)); + ASSERT(stardis && (stardis->mode & MEDIUM_COMPUTE)); /* Find medium */ - sz = darray_descriptions_size_get(&stardis->descriptions); - FOR_EACH(ii, 0, sz) { - struct description* - desc = darray_descriptions_data_get(&stardis->descriptions) + ii; - if(desc->type == DESC_MAT_SOLID) { - if(str_eq(&stardis->solve_name, &desc->d.solid.name)) { - ASSERT(darray_media_ptr_size_get(media_ptr) > ii); - medium = darray_media_ptr_data_get(media_ptr)[ii]; - break; - } - } - else if(desc->type == DESC_MAT_FLUID) { - if(str_eq(&stardis->solve_name, &desc->d.fluid.name) ){ - ASSERT(darray_media_ptr_size_get(media_ptr) > ii); - medium = darray_media_ptr_data_get(media_ptr)[ii]; - break; - } - } - } + medium = find_medium_by_name(stardis, &stardis->solve_name, NULL); if(medium == NULL) { /* Not found */ - fprintf(stderr, "Cannot solve medium %s (unknown medium)\n", + logger_print(stardis->logger, LOG_ERROR, + "Cannot solve medium '%s' (unknown medium)\n", str_cget(&stardis->solve_name)); res = RES_BAD_ARG; goto error; } - if(mode & GREEN_MODE) { - ERR(sdis_solve_medium_green_function(scn, + if(stardis->mode & GREEN_MODE) { + ERR(sdis_solve_medium_green_function(stardis->sdis_scn, stardis->samples, medium, stardis->scale_factor, stardis->radiative_temp[0], stardis->radiative_temp[1], &green)); + ERR(dump_green(green, stardis, stdout)); } else { d2_splat(time, stardis->probe[3]); time[0] = time[1] = stardis->probe[3]; - ERR(sdis_solve_medium(scn, + ERR(sdis_solve_medium(stardis->sdis_scn, stardis->samples, medium, time, @@ -490,7 +327,7 @@ compute_medium stardis->radiative_temp[1], stardis->dump_paths, &estimator)); - ERR(print_single_MC_result(mode, estimator, stardis)); + ERR(print_single_MC_result(estimator, stardis, stdout)); } end: if(estimator) SDIS(estimator_ref_put(estimator)); @@ -501,12 +338,12 @@ error: } static res_T -add_compute_region_triangle +add_compute_surface_triangle (const unsigned unique_id, const unsigned itri, void* context) { res_T res = RES_OK; const struct add_geom_ctx* ctx = context; - struct compute_region* region; + struct compute_surface* region; ASSERT(ctx); (void)itri; region = ctx->custom; /* The triangle should be already in the model, but is not @@ -520,7 +357,7 @@ error: } static res_T -merge_compute_region_triangle +merge_compute_surface_triangle (const unsigned unique_id, const unsigned itri, const int reversed_triangle, @@ -531,7 +368,7 @@ merge_compute_region_triangle { res_T res = RES_OK; const struct add_geom_ctx* ctx = context; - struct compute_region* region; + struct compute_surface* region; size_t uid; enum sdis_side side = reversed_triangle ? SDIS_BACK : SDIS_FRONT; ASSERT(ctx); @@ -548,100 +385,43 @@ error: goto end; } -/* Process an STL file describing a compute region * - * Triangles must be members of the geometry already - * TODO: what if same triangle appears more than once (same side or not)? - */ -res_T -read_compute_region(struct stardis* stardis) -{ - res_T res = RES_OK; - struct sstl* sstl = NULL; - struct add_geom_ctx add_geom_ctx; - struct sg3d_geometry_add_callbacks callbacks = SG3D_ADD_CALLBACKS_NULL__; - int new_triangles_initialized = 0; - const char* file; - - ASSERT(stardis); - - file = str_cget(&stardis->solve_name); - callbacks.get_indices = add_geom_ctx_indices; - callbacks.get_position = add_geom_ctx_position; - callbacks.add_triangle = add_compute_region_triangle; - callbacks.merge_triangle = merge_compute_region_triangle; - - ERR(sstl_create(NULL, stardis->allocator, 0, &sstl)); - res = sstl_load(sstl, file); - if(res != RES_OK) { - fprintf(stderr, "Cannot read STL file: %s\n", file); - goto error; - } - ERR(sstl_get_desc(sstl, &add_geom_ctx.stl_desc)); - ASSERT(add_geom_ctx.stl_desc.vertices_count <= UINT_MAX - && add_geom_ctx.stl_desc.triangles_count <= UINT_MAX); - - new_triangles_initialized = 1; - add_geom_ctx.custom = &stardis->compute_region; - - res = sg3d_geometry_add( - stardis->geometry.sg3d, - (unsigned)add_geom_ctx.stl_desc.vertices_count, - (unsigned)add_geom_ctx.stl_desc.triangles_count, - &callbacks, - &add_geom_ctx); - if(res != RES_OK) { - fprintf(stderr, "Cannot add file content: %s\n", file); - goto error; - } - -end: - if(sstl) SSTL(ref_put(sstl)); - return res; -error: - goto end; -} - static res_T -compute_boundary - (struct sdis_scene* scn, - const struct counts* counts, - struct stardis* stardis, - const int mode) +compute_boundary(struct stardis* stardis) { res_T res = RES_OK; double time[2], pos[3]; struct sdis_green_function* green = NULL; struct sdis_estimator* estimator = NULL; - ASSERT(scn && counts && stardis && (mode & BOUNDARY_COMPUTE)); + ASSERT(stardis && (stardis->mode & BOUNDARY_COMPUTE)); d3_set(pos, stardis->probe); - if(mode & GREEN_MODE) { - ERR(sdis_solve_boundary_green_function(scn, + if(stardis->mode & GREEN_MODE) { + ERR(sdis_solve_boundary_green_function(stardis->sdis_scn, stardis->samples, - darray_size_t_cdata_get(&stardis->compute_region.primitives), - darray_sides_cdata_get(&stardis->compute_region.sides), - darray_size_t_size_get(&stardis->compute_region.primitives), + darray_size_t_cdata_get(&stardis->compute_surface.primitives), + darray_sides_cdata_get(&stardis->compute_surface.sides), + darray_size_t_size_get(&stardis->compute_surface.primitives), stardis->scale_factor, stardis->radiative_temp[0], stardis->radiative_temp[1], &green)); - ERR(dump_green(green, counts, &stardis->descriptions, stardis->radiative_temp)); + ERR(dump_green(green, stardis, stdout)); } else { d2_splat(time, stardis->probe[3]); - ERR(sdis_solve_boundary(scn, + ERR(sdis_solve_boundary(stardis->sdis_scn, stardis->samples, - darray_size_t_cdata_get(&stardis->compute_region.primitives), - darray_sides_cdata_get(&stardis->compute_region.sides), - darray_size_t_size_get(&stardis->compute_region.primitives), + darray_size_t_cdata_get(&stardis->compute_surface.primitives), + darray_sides_cdata_get(&stardis->compute_surface.sides), + darray_size_t_size_get(&stardis->compute_surface.primitives), time, stardis->scale_factor, stardis->radiative_temp[0], stardis->radiative_temp[1], stardis->dump_paths, &estimator)); - ERR(print_single_MC_result(mode, estimator, stardis)); + ERR(print_single_MC_result(estimator, stardis, stdout)); } end: if(estimator) SDIS(estimator_ref_put(estimator)); @@ -652,30 +432,27 @@ error: } static res_T -compute_flux_boundary - (struct sdis_scene* scn, - struct stardis* stardis, - const int mode) +compute_flux_boundary(struct stardis* stardis) { res_T res = RES_OK; double time[2], pos[3]; struct sdis_green_function* green = NULL; struct sdis_estimator* estimator = NULL; - ASSERT(scn && stardis && (mode & FLUX_BOUNDARY_COMPUTE)); + ASSERT(stardis && (stardis->mode & FLUX_BOUNDARY_COMPUTE)); d3_set(pos, stardis->probe); d2_splat(time, stardis->probe[3]); - ERR(sdis_solve_boundary_flux(scn, + ERR(sdis_solve_boundary_flux(stardis->sdis_scn, stardis->samples, - darray_size_t_cdata_get(&stardis->compute_region.primitives), - darray_size_t_size_get(&stardis->compute_region.primitives), + darray_size_t_cdata_get(&stardis->compute_surface.primitives), + darray_size_t_size_get(&stardis->compute_surface.primitives), time, stardis->scale_factor, stardis->radiative_temp[0], stardis->radiative_temp[1], &estimator)); - ERR(print_single_MC_result(mode, estimator, stardis)); + ERR(print_single_MC_result(estimator, stardis, stdout)); end: if(estimator) SDIS(estimator_ref_put(estimator)); if(green) SDIS(green_function_ref_put(green)); @@ -685,10 +462,7 @@ error: } static res_T -compute_map - (struct sdis_scene* scn, - struct stardis* stardis, - const int mode) +compute_map(struct stardis* stardis) { res_T res = RES_OK; double time[2], pos[3]; @@ -697,9 +471,8 @@ compute_map int estimators_initialized = 0; size_t p; - ASSERT(scn && stardis && (mode & MAP_COMPUTE) - && !(mode & GREEN_MODE)); - (void)mode; + ASSERT(stardis + && (stardis->mode & MAP_COMPUTE) && !(stardis->mode & GREEN_MODE)); darray_estimators_init(stardis->allocator, &estimators); estimators_initialized = 1; @@ -708,13 +481,13 @@ compute_map ERR(darray_estimators_resize(&estimators, darray_estimators_size_get(&estimators) + - darray_size_t_size_get(&stardis->compute_region.primitives))); + darray_size_t_size_get(&stardis->compute_surface.primitives))); - FOR_EACH(p, 0, darray_size_t_size_get(&stardis->compute_region.primitives)) { - ERR(sdis_solve_boundary(scn, + FOR_EACH(p, 0, darray_size_t_size_get(&stardis->compute_surface.primitives)) { + ERR(sdis_solve_boundary(stardis->sdis_scn, stardis->samples, - darray_size_t_cdata_get(&stardis->compute_region.primitives) + p, - darray_sides_cdata_get(&stardis->compute_region.sides) + p, + darray_size_t_cdata_get(&stardis->compute_surface.primitives) + p, + darray_sides_cdata_get(&stardis->compute_surface.sides) + p, 1, time, stardis->scale_factor, @@ -723,12 +496,12 @@ compute_map stardis->dump_paths, darray_estimators_data_get(&estimators) + p)); } - dump_map(stardis, &estimators); + dump_map(stardis, &estimators, stdout); end: if(estimators_initialized) { struct sdis_estimator** est = darray_estimators_data_get(&estimators); - FOR_EACH(p, 0, darray_size_t_size_get(&stardis->compute_region.primitives)) { + FOR_EACH(p, 0, darray_size_t_size_get(&stardis->compute_surface.primitives)) { SDIS(estimator_ref_put(est[p])); } darray_estimators_release(&estimators); @@ -739,101 +512,129 @@ error: goto end; } -static struct sdis_interface* -geometry_get_interface - (const size_t itri, void* ctx) -{ - struct darray_interface_ptrs* app_interface_data = ctx; - ASSERT(app_interface_data - && itri < darray_interface_ptrs_size_get(app_interface_data)); - return darray_interface_ptrs_cdata_get(app_interface_data)[itri]; -} - /******************************************************************************* * Public Functions ******************************************************************************/ -res_T -stardis_compute +struct sdis_medium* +find_medium_by_name (struct stardis* stardis, - const int mode) + const struct str* name, + unsigned* out_id) +{ + struct sdis_medium* medium = NULL; + size_t i; + + ASSERT(stardis && name); + + FOR_EACH(i, 0, darray_descriptions_size_get(&stardis->descriptions)) { + struct description* + desc = darray_descriptions_data_get(&stardis->descriptions) + i; + if(desc->type == DESC_MAT_SOLID) { + if(str_eq(name, &desc->d.solid.name)) { + unsigned id = desc->d.solid.solid_id; + ASSERT(darray_media_ptr_size_get(&stardis->media) > id); + medium = darray_media_ptr_data_get(&stardis->media)[id]; + if(out_id) *out_id = id; + break; + } + } + else if(desc->type == DESC_MAT_FLUID) { + if(str_eq(name, &desc->d.fluid.name)) { + unsigned id = desc->d.fluid.fluid_id; + ASSERT(darray_media_ptr_size_get(&stardis->media) > id); + medium = darray_media_ptr_data_get(&stardis->media)[id]; + if(out_id) *out_id = id; + break; + } + } + } + return medium; +} + +/* Process an STL file describing a compute region + * Triangles must be members of the geometry already */ +res_T +read_compute_surface + (struct stardis* stardis) { res_T res = RES_OK; - struct sdis_device* dev = NULL; - struct darray_media_ptr media; - struct sg3d_sdisXd_scene_create_context create_context; - struct dummies dummies = DUMMIES_NULL; - struct htable_intface htable_interfaces; - int struct_initialised = 0; - struct counts counts = COUNTS_NULL; - int try_compute = 0, try_scene = 0; - unsigned i, vcount, tcount; - - ASSERT(stardis && (mode & COMPUTE_MODES)); - - ERR(sdis_device_create(NULL, stardis->allocator, stardis->nthreads, - stardis->verbose, &dev)); - - htable_intface_init(stardis->allocator, &htable_interfaces); - darray_media_ptr_init(stardis->allocator, &media); - struct_initialised = 1; - - /* Create media and property holders found in descriptions */ - for(i = 0; i < darray_descriptions_size_get(&stardis->descriptions); ++i) { - ERR(create_holder(stardis->allocator, &counts, &dummies, - darray_descriptions_data_get(&stardis->descriptions) + i, dev, - &media, mode & GREEN_MODE)); + struct sstl* sstl = NULL; + struct add_geom_ctx add_geom_ctx; + struct sg3d_geometry_add_callbacks callbacks = SG3D_ADD_CALLBACKS_NULL__; + int new_triangles_initialized = 0; + const char* file; + + ASSERT(stardis); + + file = str_cget(&stardis->solve_name); + callbacks.get_indices = add_geom_ctx_indices; + callbacks.get_position = add_geom_ctx_position; + callbacks.add_triangle = add_compute_surface_triangle; + callbacks.merge_triangle = merge_compute_surface_triangle; + + ERR(sstl_create(stardis->logger, stardis->allocator, 0, &sstl)); + res = sstl_load(sstl, file); + if(res != RES_OK) { + logger_print(stardis->logger, LOG_ERROR, + "Cannot read STL file: '%s'\n", file); + goto error; } + ERR(sstl_get_desc(sstl, &add_geom_ctx.stl_desc)); + ASSERT(add_geom_ctx.stl_desc.vertices_count <= UINT_MAX + && add_geom_ctx.stl_desc.triangles_count <= UINT_MAX); - /* Create interfaces */ - ERR(sg3d_geometry_get_unique_vertices_count(stardis->geometry.sg3d, &vcount)); - ERR(sg3d_geometry_get_unique_triangles_count(stardis->geometry.sg3d, &tcount)); + new_triangles_initialized = 1; + add_geom_ctx.custom = &stardis->compute_surface; - for(i = 0; i < tcount; ++i) { - ERR(create_intface(dev, i, &htable_interfaces, &stardis->geometry, - &stardis->descriptions, &media)); + res = sg3d_geometry_add( + stardis->geometry.sg3d, + (unsigned)add_geom_ctx.stl_desc.vertices_count, + (unsigned)add_geom_ctx.stl_desc.triangles_count, + &callbacks, + &add_geom_ctx); + if(res != RES_OK) { + logger_print(stardis->logger, LOG_ERROR, + "Cannot add file content: '%s'\n", file); + goto error; } - /* Create scene */ - try_scene = 1; - create_context.geometry = stardis->geometry.sg3d; - create_context.app_interface_getter = geometry_get_interface; - create_context.app_interface_data = &stardis->geometry.interf_bytrg; - ERR(sdis_scene_create(dev, tcount, sg3d_sdisXd_geometry_get_indices, - sg3d_sdisXd_geometry_get_interface, vcount, sg3d_sdisXd_geometry_get_position, - &create_context, &stardis->geometry.sdis_scn)); +end: + if(sstl) SSTL(ref_put(sstl)); + return res; +error: + goto end; +} + +res_T +stardis_compute + (struct stardis* stardis) +{ + res_T res = RES_OK; + + ASSERT(stardis && (stardis->mode & COMPUTE_MODES)); /* Compute */ - try_compute = 1; - if(mode & PROBE_COMPUTE) - ERR(compute_probe(stardis->geometry.sdis_scn, &counts, stardis, mode)); - else if(mode & PROBE_COMPUTE_ON_INTERFACE) - ERR(compute_probe_on_interface(stardis->geometry.sdis_scn, - &counts, stardis, mode)); - else if(mode & IR_COMPUTE) - ERR(compute_camera(dev, stardis->geometry.sdis_scn, stardis, mode)); - else if(mode & MEDIUM_COMPUTE) - ERR(compute_medium(stardis->geometry.sdis_scn, &media, stardis, mode)); - else if(mode & BOUNDARY_COMPUTE) - ERR(compute_boundary(stardis->geometry.sdis_scn, &counts, stardis, mode)); - else if(mode & FLUX_BOUNDARY_COMPUTE) - ERR(compute_flux_boundary(stardis->geometry.sdis_scn, stardis, mode)); - else if(mode & MAP_COMPUTE) - ERR(compute_map(stardis->geometry.sdis_scn, stardis, mode)); + if(stardis->mode & PROBE_COMPUTE) + ERR(compute_probe(stardis)); + else if(stardis->mode & PROBE_COMPUTE_ON_INTERFACE) + ERR(compute_probe_on_interface(stardis)); + else if(stardis->mode & IR_COMPUTE) + ERR(compute_camera(stardis)); + else if(stardis->mode & MEDIUM_COMPUTE) + ERR(compute_medium(stardis)); + else if(stardis->mode & BOUNDARY_COMPUTE) + ERR(compute_boundary(stardis)); + else if(stardis->mode & FLUX_BOUNDARY_COMPUTE) + ERR(compute_flux_boundary(stardis)); + else if(stardis->mode & MAP_COMPUTE) + ERR(compute_map(stardis)); else FATAL("Unknown mode.\n"); end: - if(struct_initialised) { - htable_intface_release(&htable_interfaces); - FOR_EACH(i, 0, darray_media_ptr_size_get(&media)) - SDIS(medium_ref_put(darray_media_ptr_data_get(&media)[i])); - darray_media_ptr_release(&media); - } - if(dev) SDIS(device_ref_put(dev)); - return res; error: - if(try_compute) fprintf(stderr, "%s: computation failed!\n", FUNC_NAME); - else if(try_scene) fprintf(stderr, "%s: could not setup the scene!\n", FUNC_NAME); + logger_print(stardis->logger, LOG_ERROR, + "%s: computation failed!\n", FUNC_NAME); goto end; } diff --git a/src/stardis-compute.h b/src/stardis-compute.h @@ -4,39 +4,27 @@ #define SDIS_COMPUTE_H #include <rsys/rsys.h> -#include <rsys/hash_table.h> - -#define HTABLE_NAME weigth -#define HTABLE_DATA double -#define HTABLE_KEY unsigned -#include <rsys/hash_table.h> +#include <rsys/dynamic_array.h> struct stardis; -struct sdis_medium; - -#define DARRAY_NAME media_ptr -#define DARRAY_DATA struct sdis_medium* -#include <rsys/dynamic_array.h> +struct str; #define DARRAY_NAME estimators #define DARRAY_DATA struct sdis_estimator* #include <rsys/dynamic_array.h> -struct counts { - size_t smed_count, fmed_count, tbound_count, hbound_count, - fbound_count, sfconnect_count; -}; -#define COUNTS_NULL__ {\ - 0, 0, 0, 0, 0, 0\ - } -static const struct counts COUNTS_NULL = COUNTS_NULL__; +struct sdis_medium* +find_medium_by_name + (struct stardis* stardis, + const struct str* name, + unsigned* id); /* Can be NULL */ extern LOCAL_SYM res_T stardis_compute - (struct stardis* stardis, - const int mode); + (struct stardis* stardis); extern LOCAL_SYM res_T -read_compute_region(struct stardis* stardis); +read_compute_surface + (struct stardis* stardis); #endif \ No newline at end of file diff --git a/src/stardis-fluid.c b/src/stardis-fluid.c @@ -38,9 +38,7 @@ fluid_get_temperature const struct fluid* fluid_props = sdis_data_cget(data); if(fluid_props->is_green || vtx->time > fluid_props->t0) { /* Always use temp for Green mode, regardless of time */ - if(fluid_props->imposed_temperature >= 0) - return fluid_props->imposed_temperature; - else return -1; + return fluid_props->imposed_temperature; } /* Time is <= 0: use tinit */ if(fluid_props->tinit >= 0) return fluid_props->tinit; @@ -61,17 +59,15 @@ fluid_get_temperature ******************************************************************************/ res_T -create_fluid - (struct sdis_device* dev, - struct mem_allocator* allocator, - const struct str* name, +create_stardis_fluid + (struct stardis* stardis, + const struct str* name, /* Can be NULL */ const double rho, const double cp, const int is_green, const int is_outside, const double tinit, const double imposed_temperature, - struct darray_media_ptr* media_ptr, unsigned* out_id) { res_T res = RES_OK; @@ -80,19 +76,19 @@ create_fluid struct fluid* fluid_props; size_t sz; - ASSERT(dev && rho >= 0 && cp >= 0 && media_ptr && out_id); - ASSERT(tinit >= 0 || imposed_temperature >= 0); + ASSERT(stardis && rho >= 0 && cp >= 0 && out_id); fluid_shader.calorific_capacity = fluid_get_calorific_capacity; fluid_shader.volumic_mass = fluid_get_volumic_mass; fluid_shader.temperature = fluid_get_temperature; - ERR(sdis_data_create(dev, sizeof(struct fluid), ALIGNOF(struct fluid), + ERR(sdis_data_create(stardis->dev, sizeof(struct fluid), ALIGNOF(struct fluid), NULL, &data)); - sz = darray_media_ptr_size_get(media_ptr); + sz = darray_media_ptr_size_get(&stardis->media); ASSERT(sz < INT_MAX); fluid_props = sdis_data_get(data); /* Fetch the allocated memory space */ - str_init(allocator, &fluid_props->name); + str_init(stardis->allocator, &fluid_props->name); if(name) str_copy(&fluid_props->name, name); + fluid_props->t0 = 0; fluid_props->cp = cp; fluid_props->rho = rho; fluid_props->tinit = tinit; @@ -101,9 +97,9 @@ create_fluid fluid_props->is_outside = is_outside; fluid_props->id = (unsigned)sz; - ERR(darray_media_ptr_resize(media_ptr, sz+1)); - ERR(sdis_fluid_create(dev, &fluid_shader, data, - darray_media_ptr_data_get(media_ptr) + sz)); + ERR(darray_media_ptr_resize(&stardis->media, sz+1)); + ERR(sdis_fluid_create(stardis->dev, &fluid_shader, data, + darray_media_ptr_data_get(&stardis->media) + sz)); *out_id = fluid_props->id; end: diff --git a/src/stardis-fluid.h b/src/stardis-fluid.h @@ -8,8 +8,7 @@ #include <rsys/rsys.h> #include <rsys/str.h> -struct sdis_device; -struct darray_media_ptr; +struct stardis; /******************************************************************************* * Fluid data @@ -28,9 +27,8 @@ struct fluid { }; extern res_T -create_fluid - (struct sdis_device* dev, - struct mem_allocator* allocator, +create_stardis_fluid + (struct stardis* stardis, const struct str* name, const double rho, const double cp, @@ -38,7 +36,6 @@ create_fluid const int is_outside, const double tinit, const double imposed_temperature, - struct darray_media_ptr* media_ptr, unsigned* out_id); #endif diff --git a/src/stardis-intface.c b/src/stardis-intface.c @@ -2,6 +2,7 @@ #include "stardis-app.h" #include "stardis-compute.h" #include "stardis-output.h" +#include "stardis-solid.h" #include <sdis.h> @@ -65,12 +66,9 @@ interface_get_alpha res_T create_intface - (struct sdis_device* dev, - unsigned tr_idx, - struct htable_intface* htable_interfaces, - struct geometry* geometry, - const struct darray_descriptions* desc_array, - struct darray_media_ptr* med_array) + (struct stardis* stardis, + unsigned itri, + struct htable_intface* htable_interfaces) { struct int_descs int_descs = INT_DESCS_NULL; struct sdis_interface** p_intface; @@ -86,13 +84,13 @@ create_intface struct sdis_medium** media; res_T res = RES_OK; - ASSERT(dev && htable_interfaces && geometry && desc_array && med_array); + ASSERT(stardis && htable_interfaces); - SG3D(geometry_get_unique_triangle_properties(geometry->sg3d, tr_idx, - properties)); + ERR(sg3d_geometry_get_unique_triangle_properties(stardis->geometry.sg3d, + itri, properties)); - descriptions = darray_descriptions_cdata_get(desc_array); - media = darray_media_ptr_data_get(med_array); + descriptions = darray_descriptions_cdata_get(&stardis->descriptions); + media = darray_media_ptr_data_get(&stardis->media); /* Create key */ int_descs.front = fd = properties[SG3D_FRONT]; @@ -108,12 +106,12 @@ create_intface struct sdis_interface_shader interface_shader = SDIS_INTERFACE_SHADER_NULL; struct intface* interface_props = NULL; unsigned id; - int front_defined = (fd != UINT_MAX); - int back_defined = (bd != UINT_MAX); - int connect_defined = (cd != UINT_MAX); + int front_defined = (fd != SG3D_UNSPECIFIED_PROPERTY); + int back_defined = (bd != SG3D_UNSPECIFIED_PROPERTY); + int connect_defined = (cd != SG3D_UNSPECIFIED_PROPERTY); - SDIS(data_create(dev, sizeof(struct intface), ALIGNOF(struct intface), - NULL, &data)); + ERR(sdis_data_create(stardis->dev, sizeof(struct intface), + ALIGNOF(struct intface), NULL, &data)); interface_props = sdis_data_get(data); interface_props->imposed_temperature = -1; interface_props->imposed_flux = SDIS_FLUX_NONE; @@ -160,85 +158,85 @@ create_intface struct sdis_medium* def_medium = NULL; unsigned ext_id; if(connect->type == DESC_SOLID_FLUID_CONNECT) { - if(solid_count != 1 || fluid_count != 1) { - ASSERT(front_defined && back_defined); - fprintf(stderr, - "Can only define a DESC_SOLID_FLUID_CONNECT between a fluid and a solid\n"); - res = RES_BAD_ARG; - goto error; - } + ASSERT(front_defined && back_defined); + fluid_side_shader = (descriptions[fd].type == DESC_MAT_SOLID) + ? &interface_shader.back : &interface_shader.front; + if(solid_count != 1 || fluid_count != 1) goto error; } else { - if(front_defined == back_defined) { - fprintf(stderr, - "Cannot define a boundary between 2 %s regions\n", - front_defined ? "defined" : "undefined"); - res = RES_BAD_ARG; - goto error; - } + if(front_defined == back_defined) goto error; def_medium = front_defined ? front_med : back_med; - if(front_defined) + if(front_defined) { + ASSERT(descriptions[fd].type == DESC_MAT_SOLID + || descriptions[fd].type == DESC_MAT_FLUID); + fluid_side_shader = (descriptions[fd].type == DESC_MAT_SOLID) + ? &interface_shader.back : &interface_shader.front; interface_props->front_boundary_id = cd; - else interface_props->back_boundary_id = cd; + } else { + ASSERT(back_defined); + ASSERT(descriptions[bd].type == DESC_MAT_SOLID + || descriptions[bd].type == DESC_MAT_FLUID); + fluid_side_shader = (descriptions[bd].type == DESC_MAT_SOLID) + ? &interface_shader.back : &interface_shader.front; + interface_props->back_boundary_id = cd; + } } - switch (connect->type) { + switch(connect->type) { case DESC_BOUND_H_FOR_FLUID: - if(sdis_medium_get_type(def_medium) != SDIS_FLUID) { - fprintf(stderr, - "Can only define a DESC_BOUND_H_FOR_FLUID boundary for a fluid region\n"); - res = RES_BAD_ARG; - goto error; - } + if(sdis_medium_get_type(def_medium) != SDIS_FLUID) goto error; type_checked = 1; + ASSERT(connect->d.h_boundary.imposed_temperature >= 0); + interface_props->imposed_temperature + = connect->d.h_boundary.imposed_temperature; + fluid_side_shader->temperature = interface_get_temperature; /* fall through */ case DESC_BOUND_H_FOR_SOLID: if(!type_checked - && sdis_medium_get_type(def_medium) != SDIS_SOLID) { - fprintf(stderr, - "Can only define a DESC_BOUND_H_FOR_SOLID boundary for a solid region\n"); - res = RES_BAD_ARG; - goto error; - } + && sdis_medium_get_type(def_medium) != SDIS_SOLID) goto error; ext_id = connect->d.h_boundary.mat_id; /* External material id */ - ASSERT(ext_id < darray_media_ptr_size_get(med_array)); + ASSERT(ext_id < darray_media_ptr_size_get(&stardis->media)); ASSERT(sdis_medium_get_type(media[ext_id]) == (connect->type == DESC_BOUND_H_FOR_SOLID ? SDIS_FLUID : SDIS_SOLID)); connection_count++; boundary_count++; if(front_defined) back_med = media[ext_id]; else front_med = media[ext_id]; - interface_shader.convection_coef = interface_get_convection_coef; interface_shader.convection_coef_upper_bound = connect->d.h_boundary.hc; interface_props->hc = connect->d.h_boundary.hc; - ASSERT(!fluid_side_shader); /* Cause defined medium is solid */ + interface_props->emissivity = connect->d.h_boundary.emissivity; + interface_props->alpha = connect->d.h_boundary.specular_fraction; if(connect->d.h_boundary.hc > 0) { - fluid_side_shader = - front_defined ? &interface_shader.back : &interface_shader.front; + interface_shader.convection_coef = interface_get_convection_coef; + } + if(connect->d.h_boundary.emissivity > 0) { + ASSERT(fluid_side_shader); fluid_side_shader->emissivity = interface_get_emissivity; fluid_side_shader->specular_fraction = interface_get_alpha; - interface_props->emissivity = connect->d.h_boundary.emissivity; - interface_props->alpha = connect->d.h_boundary.specular_fraction; } break; case DESC_BOUND_T_FOR_FLUID: - if(sdis_medium_get_type(def_medium) != SDIS_FLUID) { - fprintf(stderr, - "Can only define a DESC_BOUND_T_FOR_FLUID boundary for a fluid region\n"); - res = RES_BAD_ARG; - goto error; - } + if(sdis_medium_get_type(def_medium) != SDIS_FLUID) goto error; type_checked = 1; + interface_shader.convection_coef_upper_bound = connect->d.t_boundary.hc; + interface_props->hc = connect->d.t_boundary.hc; + if(connect->d.t_boundary.hc > 0) { + ASSERT(connect->type == DESC_BOUND_T_FOR_FLUID); + interface_shader.convection_coef = interface_get_convection_coef; + } + interface_props->emissivity = connect->d.t_boundary.emissivity; + interface_props->alpha = connect->d.t_boundary.specular_fraction; + if(connect->d.t_boundary.emissivity > 0) { + ASSERT(fluid_side_shader); + fluid_side_shader->emissivity = interface_get_emissivity; + fluid_side_shader->specular_fraction = interface_get_alpha; + } /* fall through */ case DESC_BOUND_T_FOR_SOLID: if(!type_checked - && sdis_medium_get_type(def_medium) != SDIS_SOLID) { - fprintf(stderr, - "Can only define a DESC_BOUND_T_FOR_SOLID boundary for a solid region\n"); - res = RES_BAD_ARG; - goto error; - } + && sdis_medium_get_type(def_medium) != SDIS_SOLID) goto error; ext_id = connect->d.t_boundary.mat_id; /* External material id */ - ASSERT(ext_id < darray_media_ptr_size_get(med_array)); - ASSERT(sdis_medium_get_type(media[ext_id]) == SDIS_FLUID); + ASSERT(ext_id < darray_media_ptr_size_get(&stardis->media)); + ASSERT(sdis_medium_get_type(media[ext_id]) + == (connect->type == DESC_BOUND_T_FOR_FLUID ? SDIS_SOLID: SDIS_FLUID)); connection_count++; boundary_count++; if(front_defined) { @@ -255,20 +253,9 @@ create_intface ASSERT(connect->d.t_boundary.imposed_temperature >= 0); interface_props->imposed_temperature = connect->d.t_boundary.imposed_temperature; - if(connect->d.t_boundary.hc > 0) { - ASSERT(connect->type == DESC_BOUND_T_FOR_FLUID); - interface_shader.convection_coef = interface_get_convection_coef; - interface_shader.convection_coef_upper_bound = connect->d.t_boundary.hc; - interface_props->hc = connect->d.t_boundary.hc; - } break; case DESC_BOUND_F_FOR_SOLID: - if(sdis_medium_get_type(def_medium) != SDIS_SOLID) { - fprintf(stderr, - "Can only define a DESC_BOUND_F_FOR_SOLID boundary for a solid region\n"); - res = RES_BAD_ARG; - goto error; - } + if(sdis_medium_get_type(def_medium) != SDIS_SOLID) goto error; connection_count++; boundary_count++; if(front_defined) { @@ -286,17 +273,17 @@ create_intface * if not will raise an error below */ connection_count++; solid_fluid_connection_count++; - ASSERT(fluid_side_shader); + interface_shader.convection_coef_upper_bound = connect->d.sf_connect.hc; + interface_props->hc = connect->d.sf_connect.hc; + interface_props->emissivity = connect->d.sf_connect.emissivity; + interface_props->alpha = connect->d.sf_connect.specular_fraction; if(connect->d.sf_connect.hc > 0) { interface_shader.convection_coef = interface_get_convection_coef; - interface_shader.convection_coef_upper_bound = connect->d.sf_connect.hc; - interface_props->hc = connect->d.sf_connect.hc; } if(connect->d.sf_connect.emissivity > 0) { + ASSERT(fluid_side_shader); fluid_side_shader->emissivity = interface_get_emissivity; fluid_side_shader->specular_fraction = interface_get_alpha; - interface_props->emissivity = connect->d.sf_connect.emissivity; - interface_props->alpha = connect->d.sf_connect.specular_fraction; } break; default: @@ -309,37 +296,20 @@ create_intface || (boundary_count ? (fluid_count + solid_count != 1) : (fluid_count + solid_count != 2)) || (solid_fluid_connection_count && (fluid_count != 1 || solid_count != 1))) - { - /* Incoherent triangle description */ - fprintf(stderr, "Incoherent triangle description (%u)\n", tr_idx); - fprintf(stderr, "Front: "); - if(!front_defined) fprintf(stderr, "undefined\n"); - else print_description(stderr, descriptions + fd); - fprintf(stderr, "Back: "); - if(!back_defined) fprintf(stderr, "undefined\n"); - else print_description(stderr, descriptions + bd); - fprintf(stderr, "Connection: "); - if(!connect_defined) fprintf(stderr, "undefined\n"); - else print_description(stderr, descriptions + cd); - res = RES_BAD_ARG; goto error; - } - res = sdis_interface_create(dev, front_med, back_med, - &interface_shader, data, &intface); + ERR(sdis_interface_create(stardis->dev, front_med, back_med, + &interface_shader, data, &intface)); SDIS(data_ref_put(data)); data = NULL; - if(res != RES_OK) { - fprintf(stderr, - "Cannot create interface associated to triangle %u\n", tr_idx); - goto error; - } - ERR(darray_interface_ptrs_push_back(&geometry->interfaces, &intface)); + ERR(darray_interface_ptrs_push_back(&stardis->geometry.interfaces, &intface)); ERR(htable_intface_set(htable_interfaces, &int_descs, &intface)); } - ERR(darray_interface_ptrs_push_back(&geometry->interf_bytrg, &intface)); + ERR(darray_interface_ptrs_push_back(&stardis->geometry.interf_bytrg, &intface)); end: + if(data) SDIS(data_ref_put(data)); return res; error: goto end; -} -\ No newline at end of file +} + diff --git a/src/stardis-intface.h b/src/stardis-intface.h @@ -7,13 +7,8 @@ #include <limits.h> -struct sdis_data; -struct sdis_device; -struct geometry; -struct description; -struct sdis_medium; -struct darray_descriptions; -struct darray_media_ptr; +struct stardis; +struct dummies; /******************************************************************************* * Interface data @@ -43,26 +38,16 @@ eq_desc(const struct int_descs* a, const struct int_descs* b) && a->connect == b->connect); } -static INLINE size_t -hash_desc(struct int_descs const* key) -{ - return (size_t)hash_fnv64(key, 3 * sizeof(unsigned)); -} - #define HTABLE_NAME intface #define HTABLE_DATA struct sdis_interface* #define HTABLE_KEY struct int_descs #define HTABLE_KEY_FUNCTOR_EQ eq_desc -#define HTABLE_KEY_FUNCTOR_HASH hash_desc #include <rsys/hash_table.h> extern res_T create_intface - (struct sdis_device* dev, + (struct stardis* stardis, unsigned tr_idx, - struct htable_intface* htable_interfaces, - struct geometry* geometry, - const struct darray_descriptions* descriptions, - struct darray_media_ptr* media); + struct htable_intface* htable_interfaces); #endif diff --git a/src/stardis-output.c b/src/stardis-output.c @@ -8,24 +8,27 @@ #include <sdis.h> #include<star/senc3d.h> +#include<star/sg3d_sencXd_helper.h> #include <rsys/math.h> #include <rsys/mem_allocator.h> #include <rsys/dynamic_array_uint.h> +#include <rsys/hash_table.h> +#include <rsys/logger.h> #include <stdio.h> +#define HTABLE_NAME weigth +#define HTABLE_DATA double +#define HTABLE_KEY unsigned +#include <rsys/hash_table.h> + struct w_ctx { const struct darray_descriptions* desc; struct htable_weigth weigths; + FILE* stream; }; -#include <rsys/hash_table.h> -#define HTABLE_NAME vrtx_rank -#define HTABLE_DATA unsigned -#define HTABLE_KEY unsigned -#include <rsys/hash_table.h> - /******************************************************************************* * Local Functions ******************************************************************************/ @@ -56,7 +59,7 @@ print_power_term const struct description* descs = darray_descriptions_cdata_get(w_ctx->desc); id = d__->id; ASSERT(id == descs[id].d.solid.solid_id); (void)descs; - printf("\tS\t%u\t%g", id, power_term); + fprintf(w_ctx->stream, "\tS\t%u\t%g", id, power_term); break; } default: FATAL("Unreachable code.\n"); break; @@ -132,7 +135,7 @@ dump_path fprintf(stream, "%g %g %g\n", SPLIT3(vtx.P)); } /* Write the segment of the path */ - fprintf(stream, "LINES %u %zu\n", 1u, 1 + vcount); + fprintf(stream, "LINES %d %zu\n", 1, 1 + vcount); fprintf(stream, "%zu", vcount); FOR_EACH(i, 0, vcount) fprintf(stream, " %zu", i); fprintf(stream, "\n"); @@ -171,7 +174,7 @@ dump_path fprintf(stream, "%g\n", IS_INF(vtx.time) ? FLT_MAX : vtx.time); } /* Write path type */ - fprintf(stream, "CELL_DATA %u\n", 1u); + fprintf(stream, "CELL_DATA %d\n", 1); fprintf(stream, "SCALARS Path_Type float 1\n"); fprintf(stream, "LOOKUP_TABLE path_type\n"); ERR(sdis_heat_path_get_status(path, &status)); @@ -233,16 +236,16 @@ print_sample case DESC_BOUND_T_FOR_SOLID: case DESC_BOUND_T_FOR_FLUID: ASSERT(id == descs[id].d.t_boundary.mat_id); - printf("T\t%u", id); + fprintf(w_ctx->stream, "T\t%u", id); break; case DESC_BOUND_H_FOR_SOLID: case DESC_BOUND_H_FOR_FLUID: ASSERT(id == descs[id].d.h_boundary.mat_id); - printf("H\t%u", id); + fprintf(w_ctx->stream, "H\t%u", id); break; case DESC_BOUND_F_FOR_SOLID: ASSERT(id == descs[id].d.f_boundary.mat_id); - printf("X\t%u", id); + fprintf(w_ctx->stream, "X\t%u", id); break; default: FATAL("Unreachable code.\n"); break; } @@ -255,7 +258,7 @@ print_sample /* Radiative output */ size_t sz = darray_descriptions_size_get(w_ctx->desc); ASSERT(sz <= UINT_MAX); - printf("R\t%u", (unsigned)sz); + fprintf(w_ctx->stream, "R\t%u", (unsigned)sz); } else if(type == SDIS_FLUID) { struct fluid* d__ = sdis_data_get(data); @@ -264,16 +267,16 @@ print_sample if(d__->is_outside) /* If outside the model and in a fluid with known temperature, * its a fluid attached to a H boundary */ - printf("H\t%u", id); + fprintf(w_ctx->stream, "H\t%u", id); /* In a standard fluid with known temperature */ - else printf("F\t%u", id); + else fprintf(w_ctx->stream, "F\t%u", id); } else { struct solid* d__ = sdis_data_get(data); ASSERT(type == SDIS_SOLID); id = d__->id; ASSERT(id == descs[id].d.solid.solid_id); ASSERT(!d__->is_outside); /* FIXME: what if in external solid? */ - printf("S\t%u", id); + fprintf(w_ctx->stream, "S\t%u", id); } break; default: FATAL("Unreachable code.\n"); break; @@ -285,19 +288,19 @@ print_sample ERR(sdis_green_path_for_each_flux_term(path, get_flux_terms, w_ctx)); fcount = htable_weigth_size_get(&w_ctx->weigths); - printf("\t%zu\t%zu", pcount, fcount); + fprintf(w_ctx->stream, "\t%zu\t%zu", pcount, fcount); ERR(sdis_green_path_for_each_power_term(path, print_power_term, ctx)); htable_weigth_begin(&w_ctx->weigths, &it); htable_weigth_end(&w_ctx->weigths, &end); - while (!htable_weigth_iterator_eq(&it, &end)) { + while(!htable_weigth_iterator_eq(&it, &end)) { double* w = htable_weigth_iterator_data_get(&it); unsigned* k = htable_weigth_iterator_key_get(&it); - printf("\t%u\t%g", *k, *w); + fprintf(w_ctx->stream, "\t%u\t%g", *k, *w); htable_weigth_iterator_next(&it); } - printf("\n"); + fprintf(w_ctx->stream, "\n"); end: return res; @@ -307,14 +310,15 @@ error: res_T dump_image - (const struct sdis_estimator_buffer* buf) + (const struct sdis_estimator_buffer* buf, + FILE* stream) { res_T res = RES_OK; size_t definition[2]; double* temps = NULL; size_t ix, iy; - CHK(buf != NULL); + ASSERT(buf && stream); ERR(sdis_estimator_buffer_get_definition(buf, definition)); temps = mem_alloc(definition[0] * definition[1] * sizeof(double)); @@ -324,64 +328,65 @@ dump_image } /* Compute the per pixel temperature */ - fprintf(stdout, "# vtk DataFile Version 2.0\nvtk output\nASCII\nDATASET STRUCTURED_POINTS\n"); - fprintf(stdout, "DIMENSIONS %zu %zu 1\n", definition[0], definition[1]); - fprintf(stdout, "ORIGIN 0 0 0\n"); - fprintf(stdout, "SPACING 1 1 1\n"); - fprintf(stdout, "POINT_DATA %zu\n", definition[0] * definition[1]); - fprintf(stdout, "SCALARS temperature_estimate float 1\n"); - fprintf(stdout, "LOOKUP_TABLE default\n"); + fprintf(stream, + "# vtk DataFile Version 2.0\nvtk output\nASCII\nDATASET STRUCTURED_POINTS\n"); + fprintf(stream, "DIMENSIONS %zu %zu 1\n", definition[0], definition[1]); + fprintf(stream, "ORIGIN 0 0 0\n"); + fprintf(stream, "SPACING 1 1 1\n"); + fprintf(stream, "POINT_DATA %zu\n", definition[0] * definition[1]); + fprintf(stream, "SCALARS temperature_estimate float 1\n"); + fprintf(stream, "LOOKUP_TABLE default\n"); FOR_EACH(iy, 0, definition[1]) { FOR_EACH(ix, 0, definition[0]) { const struct sdis_estimator* estimator; struct sdis_mc T; ERR(sdis_estimator_buffer_at(buf, ix, iy, &estimator)); ERR(sdis_estimator_get_temperature(estimator, &T)); - fprintf(stdout, "%f\n", T.E); + fprintf(stream, "%f\n", T.E); } } - fprintf(stdout, "SCALARS temperature_std_dev float 1\n"); - fprintf(stdout, "LOOKUP_TABLE default\n"); + fprintf(stream, "SCALARS temperature_std_dev float 1\n"); + fprintf(stream, "LOOKUP_TABLE default\n"); FOR_EACH(iy, 0, definition[1]) { FOR_EACH(ix, 0, definition[0]) { const struct sdis_estimator* estimator; struct sdis_mc T; ERR(sdis_estimator_buffer_at(buf, ix, iy, &estimator)); ERR(sdis_estimator_get_temperature(estimator, &T)); - fprintf(stdout, "%f\n", T.SE); + fprintf(stream, "%f\n", T.SE); } } - fprintf(stdout, "SCALARS computation_time float 1\n"); - fprintf(stdout, "LOOKUP_TABLE default\n"); + fprintf(stream, "SCALARS computation_time float 1\n"); + fprintf(stream, "LOOKUP_TABLE default\n"); FOR_EACH(iy, 0, definition[1]) { FOR_EACH(ix, 0, definition[0]) { const struct sdis_estimator* estimator; struct sdis_mc time; ERR(sdis_estimator_buffer_at(buf, ix, iy, &estimator)); ERR(sdis_estimator_get_realisation_time(estimator, &time)); - fprintf(stdout, "%f\n", time.E); + fprintf(stream, "%f\n", time.E); } } - fprintf(stdout, "SCALARS computation_time_std_dev float 1\n"); - fprintf(stdout, "LOOKUP_TABLE default\n"); + fprintf(stream, "SCALARS computation_time_std_dev float 1\n"); + fprintf(stream, "LOOKUP_TABLE default\n"); FOR_EACH(iy, 0, definition[1]) { FOR_EACH(ix, 0, definition[0]) { const struct sdis_estimator* estimator; struct sdis_mc time; ERR(sdis_estimator_buffer_at(buf, ix, iy, &estimator)); ERR(sdis_estimator_get_realisation_time(estimator, &time)); - fprintf(stdout, "%f\n", time.SE); + fprintf(stream, "%f\n", time.SE); } } - fprintf(stdout, "SCALARS temperature_failures_count unsigned_long_long 1\n"); - fprintf(stdout, "LOOKUP_TABLE default\n"); + fprintf(stream, "SCALARS temperature_failures_count unsigned_long_long 1\n"); + fprintf(stream, "LOOKUP_TABLE default\n"); FOR_EACH(iy, 0, definition[1]) { FOR_EACH(ix, 0, definition[0]) { const struct sdis_estimator* estimator; size_t nfails; ERR(sdis_estimator_buffer_at(buf, ix, iy, &estimator)); ERR(sdis_estimator_get_failure_count(estimator, &nfails)); - fprintf(stdout, "%zu\n", nfails); + fprintf(stream, "%zu\n", nfails); } } mem_rm(temps); @@ -395,9 +400,8 @@ error: res_T dump_green (struct sdis_green_function* green, - const struct counts* counts, - const struct darray_descriptions* descriptions, - const double radiative_temps[2]) + const struct stardis* stardis, + FILE* stream) { res_T res = RES_OK; size_t ok_count, failed_count, sz; @@ -406,105 +410,110 @@ dump_green unsigned i, szd; const struct description* descs; - ASSERT(green && counts && descriptions && radiative_temps); + ASSERT(green && stardis && stream); ERR(sdis_green_function_get_invalid_paths_count(green, &failed_count)); ERR(sdis_green_function_get_paths_count(green, &ok_count)); - sz = darray_descriptions_size_get(descriptions); + sz = darray_descriptions_size_get(&stardis->descriptions); ASSERT(sz <= UINT_MAX); szd = (unsigned)sz; - descs = darray_descriptions_cdata_get(descriptions); + descs = darray_descriptions_cdata_get(&stardis->descriptions); /* Output counts */ - printf("---BEGIN GREEN---\n"); - printf("# #solids #fluids #t_boundaries #h_boundaries #f_boundaries #ok #failures\n"); - printf("%zu %zu %zu %zu %zu %zu %zu\n", - counts->smed_count, counts->fmed_count, - counts->tbound_count, counts->hbound_count, counts->fbound_count, - ok_count, failed_count); + fprintf(stream, "---BEGIN GREEN---\n"); + fprintf(stream, + "# #solids #fluids #t_boundaries #h_boundaries #f_boundaries #ok #failures\n"); + fprintf(stream, "%zu %zu %zu %zu %zu %zu %zu\n", + stardis->counts.smed_count, stardis->counts.fmed_count, + stardis->counts.tbound_count, stardis->counts.hbound_count, + stardis->counts.fbound_count, ok_count, failed_count); /* List Media */ - if(counts->smed_count) { - printf("# Solids\n"); - printf("# ID Name lambda rho cp power\n"); + if(stardis->counts.smed_count) { + fprintf(stream, "# Solids\n"); + fprintf(stream, "# ID Name lambda rho cp power\n"); FOR_EACH(i, 0, szd) { const struct description* desc = descs + i; const struct mat_solid* sl; if(desc->type != DESC_MAT_SOLID) continue; sl = &desc->d.solid; - printf("%u\t%s\t%g\t%g\t%g\t%g\n", + fprintf(stream, "%u\t%s\t%g\t%g\t%g\t%g\n", i, str_cget(&sl->name), sl->lambda, sl->rho, sl->cp, sl->vpower); } } - if(counts->fmed_count) { - printf("# Fluids\n"); - printf("# ID Name rho cp\n"); + if(stardis->counts.fmed_count) { + fprintf(stream, "# Fluids\n"); + fprintf(stream, "# ID Name rho cp\n"); FOR_EACH(i, 0, szd) { const struct description* desc = descs + i; const struct mat_fluid* fl; fl = &desc->d.fluid; - printf("%u\t%s\t%g\t%g\n", i, str_cget(&fl->name), fl->rho, fl->cp); + fprintf(stream, "%u\t%s\t%g\t%g\n", + i, str_cget(&fl->name), fl->rho, fl->cp); } } /* List Boundaries */ - if(counts->tbound_count) { - printf("# T Boundaries\n"); - printf("# ID Name temperature\n"); + if(stardis->counts.tbound_count) { + fprintf(stream, "# T Boundaries\n"); + fprintf(stream, "# ID Name temperature\n"); FOR_EACH(i, 0, szd) { const struct description* desc = descs + i; const struct t_boundary* bd; if(desc->type != DESC_BOUND_T_FOR_SOLID && desc->type != DESC_BOUND_T_FOR_FLUID) continue; bd = &desc->d.t_boundary; - printf("%u\t%s\t%g\n", i, str_cget(&bd->name), bd->imposed_temperature); + fprintf(stream, "%u\t%s\t%g\n", + i, str_cget(&bd->name), bd->imposed_temperature); } } - if(counts->hbound_count) { - printf("# H Boundaries\n"); - printf("# ID Name emissivity specular_fraction hc hc_max T_env\n"); + if(stardis->counts.hbound_count) { + fprintf(stream, "# H Boundaries\n"); + fprintf(stream, "# ID Name emissivity specular_fraction hc hc_max T_env\n"); FOR_EACH(i, 0, szd) { const struct description* desc = descs + i; const struct h_boundary* bd; if(desc->type != DESC_BOUND_H_FOR_SOLID && desc->type != DESC_BOUND_H_FOR_FLUID) continue; bd = &desc->d.h_boundary; - printf("%u\t%s\t%g\t%g\t%g\t%g\n", + fprintf(stream, "%u\t%s\t%g\t%g\t%g\t%g\n", i, str_cget(&bd->name), bd->emissivity, bd->specular_fraction, bd->hc, bd->imposed_temperature); } } - if(counts->fbound_count) { - printf("# F Boundaries\n"); - printf("# ID Name flux\n"); + if(stardis->counts.fbound_count) { + fprintf(stream, "# F Boundaries\n"); + fprintf(stream, "# ID Name flux\n"); FOR_EACH(i, 0, szd) { const struct description* desc = descs + i; const struct f_boundary* bd; if(desc->type != DESC_BOUND_F_FOR_SOLID) continue; bd = &desc->d.f_boundary; - printf("%u\t%s\t%g\n", + fprintf(stream, "%u\t%s\t%g\n", i, str_cget(&bd->name), bd->imposed_flux); } } /* Radiative Temperatures */ - printf("# Radiative Temperatures\n"); - printf("# ID Rad_Temp Lin_Temp\n"); - printf("%u\t%g\t%g\n", szd, radiative_temps[0], radiative_temps[1]); - - printf("# Samples\n"); - printf("# end #power_terms #flux_terms power_term_1 ... power_term_n flux_term_1 ... flux_term_n\n"); - printf("# end = end_type end_id; end_type = T | H | X | R | F | S\n"); - printf("# power_term_i = power_type_i power_id_i factor_i\n"); - printf("# flux_term_i = flux_id_i factor_i\n"); - - w_ctx.desc = descriptions; + fprintf(stream, "# Radiative Temperatures\n"); + fprintf(stream, "# ID Rad_Temp Lin_Temp\n"); + fprintf(stream, "%u\t%g\t%g\n", + szd, stardis->radiative_temp[0], stardis->radiative_temp[1]); + + fprintf(stream, "# Samples\n"); + fprintf(stream, + "# end #power_terms #flux_terms power_term_1 ... power_term_n flux_term_1 ... flux_term_n\n"); + fprintf(stream, "# end = end_type end_id; end_type = T | H | X | R | F | S\n"); + fprintf(stream, "# power_term_i = power_type_i power_id_i factor_i\n"); + fprintf(stream, "# flux_term_i = flux_id_i factor_i\n"); + + w_ctx.desc = &stardis->descriptions; htable_weigth_init(NULL, &w_ctx.weigths); table_initialized = 1; ERR(sdis_green_function_for_each_path(green, print_sample, &w_ctx)); - printf("---END GREEN---\n"); + fprintf(stream, "---END GREEN---\n"); ERR(sdis_green_function_ref_put(green)); @@ -515,52 +524,54 @@ error: goto end; } -int -has_holes(const struct stardis* stardis) -{ - struct senc3d_scene* senc3d_scn; - unsigned count; - SDIS(scene_get_senc3d_scene(stardis->geometry.sdis_scn, &senc3d_scn)); - SENC3D(scene_get_frontier_segments_count(senc3d_scn, &count)); - return count != 0; -} - res_T -dump_holes_at_the_end_of_vtk +dump_enclosure_related_stuff_at_the_end_of_vtk (const struct stardis* stardis, FILE* stream) { res_T res = RES_OK; unsigned* trgs = NULL; struct senc3d_scene* senc3d_scn = NULL; - unsigned tsz, scount, i; + struct senc3d_device* senc_dev = NULL; + unsigned tsz, vsz, scount, i; ASSERT(stardis && stream); - ASSERT(stardis); ERR(sg3d_geometry_get_unique_triangles_count(stardis->geometry.sg3d, &tsz)); - /* Store frontier triangles */ - trgs = MEM_CALLOC(stardis->allocator, tsz, sizeof(*trgs)); - if(!trgs) { - res = RES_MEM_ERR; - goto error; - } + ERR(sg3d_geometry_get_unique_vertices_count(stardis->geometry.sg3d, &vsz)); + + /* Create enclosures to have holes information */ + ERR(senc3d_device_create(stardis->logger, stardis->allocator, stardis->nthreads, + stardis->verbose, &senc_dev)); + 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, + vsz, sg3d_sencXd_geometry_get_position, stardis->geometry.sg3d, + &senc3d_scn)); /* Keep the involved segments (not the vertices) */ - ERR(sdis_scene_get_senc3d_scene(stardis->geometry.sdis_scn, &senc3d_scn)); ERR(senc3d_scene_get_frontier_segments_count(senc3d_scn, &scount)); - FOR_EACH(i, 0, scount) { - unsigned vrtc[2], trid; - ERR(senc3d_scene_get_frontier_segment(senc3d_scn, i, vrtc, &trid)); - trgs[trid] = 1; - } + if(scount) { + /* Room to store frontier triangles */ + trgs = MEM_CALLOC(stardis->allocator, tsz, sizeof(*trgs)); + if(!trgs) { + res = RES_MEM_ERR; + goto error; + } + FOR_EACH(i, 0, scount) { + unsigned vrtc[2], trid; + ERR(senc3d_scene_get_frontier_segment(senc3d_scn, i, vrtc, &trid)); + trgs[trid] = 1; + } - fprintf(stream, "SCALARS Holes_frontiers int\n"); - fprintf(stream, "LOOKUP_TABLE default\n"); - FOR_EACH(i, 0, tsz) fprintf(stream, "%d\n", trgs[i]); + fprintf(stream, "SCALARS Hole_frontiers int\n"); + fprintf(stream, "LOOKUP_TABLE default\n"); + FOR_EACH(i, 0, tsz) fprintf(stream, "%d\n", trgs[i]); + } exit: if(trgs) MEM_RM(stardis->allocator, trgs); if(senc3d_scn) senc3d_scene_ref_put(senc3d_scn); + if(senc_dev) senc3d_device_ref_put(senc_dev); return res; error: goto exit; @@ -568,37 +579,37 @@ error: res_T print_single_MC_result - (const int mode, - struct sdis_estimator* estimator, - struct stardis* stardis) + (struct sdis_estimator* estimator, + struct stardis* stardis, + FILE* stream) { res_T res = RES_OK; struct sdis_mc result; size_t nfailures; - ASSERT(estimator && stardis); + ASSERT(estimator && stardis && stream); /* Fetch the estimation data */ ERR(sdis_estimator_get_temperature(estimator, &result)); ERR(sdis_estimator_get_failure_count(estimator, &nfailures)); /* Print the results */ - switch (mode & COMPUTE_MODES) { + switch (stardis->mode & COMPUTE_MODES) { case PROBE_COMPUTE: case PROBE_COMPUTE_ON_INTERFACE: - printf("Temperature at [%g, %g, %g], t=%g = %g +/- %g\n", + fprintf(stream, "Temperature at [%g, %g, %g] at t=%g = %g +/- %g\n", SPLIT4(stardis->probe), result.E, /* Expected value */ result.SE); /* Standard error */ break; case MEDIUM_COMPUTE: - printf("Temperature in medium %s at t=%g = %g +/- %g\n", + fprintf(stream, "Temperature in medium %s at t=%g = %g +/- %g\n", str_cget(&stardis->solve_name), stardis->probe[3], result.E, /* Expected value */ result.SE); /* Standard error */ break; case BOUNDARY_COMPUTE: - printf("Temperature at boundary %s at t=%g = %g +/- %g\n", + fprintf(stream, "Temperature at boundary %s at t=%g = %g +/- %g\n", str_cget(&stardis->solve_name), stardis->probe[3], result.E, /* Expected value */ result.SE); /* Standard error */ @@ -608,22 +619,22 @@ print_single_MC_result ERR(sdis_estimator_get_type(estimator, &type)); ASSERT(type == SDIS_ESTIMATOR_FLUX); - printf("Temperature at boundary %s at t=%g = %g +/- %g\n", + fprintf(stream, "Temperature at boundary %s at t=%g = %g +/- %g\n", str_cget(&stardis->solve_name), stardis->probe[3], result.E, /* Expected value */ result.SE); /* Standard error */ ERR(sdis_estimator_get_convective_flux(estimator, &result)); - printf("Convective flux at boundary %s at t=%g = %g +/- %g\n", + fprintf(stream, "Convective flux at boundary %s at t=%g = %g +/- %g\n", str_cget(&stardis->solve_name), stardis->probe[3], result.E, /* Expected value */ result.SE); /* Standard error */ ERR(sdis_estimator_get_radiative_flux(estimator, &result)); - printf("Radiative flux at boundary %s at t=%g = %g +/- %g\n", + fprintf(stream, "Radiative flux at boundary %s at t=%g = %g +/- %g\n", str_cget(&stardis->solve_name), stardis->probe[3], result.E, /* Expected value */ result.SE); /* Standard error */ ERR(sdis_estimator_get_total_flux(estimator, &result)); - printf("Total flux Flux at boundary %s at t=%g = %g +/- %g\n", + fprintf(stream, "Total flux Flux at boundary %s at t=%g = %g +/- %g\n", str_cget(&stardis->solve_name), stardis->probe[3], result.E, /* Expected value */ result.SE); /* Standard error */ @@ -631,9 +642,10 @@ print_single_MC_result } default: FATAL("Invalid mode."); } - printf("#failures: %zu/%zu\n", nfailures, stardis->samples); + fprintf(stream, "#failures: %zu/%zu\n", nfailures, stardis->samples); if(nfailures) - fprintf(stderr, "#failures: %zu/%zu\n", nfailures, stardis->samples); + logger_print(stardis->logger, LOG_ERROR, + "#failures: %zu/%zu\n", nfailures, stardis->samples); /* Dump paths according to user settings */ ERR(sdis_estimator_for_each_path(estimator, dump_path, stdout)); @@ -646,7 +658,8 @@ error: void dump_map (const struct stardis* stardis, - const struct darray_estimators* estimators) + const struct darray_estimators* estimators, + FILE* stream) { unsigned i, vcount, tcount, last_v = 0; const size_t* idx; @@ -654,11 +667,11 @@ dump_map unsigned szp; const struct sdis_estimator* const* est; - ASSERT(stardis && estimators); + ASSERT(stardis && estimators && stream); est = darray_estimators_cdata_get(estimators); - idx = darray_size_t_cdata_get(&stardis->compute_region.primitives); - sz = darray_size_t_size_get(&stardis->compute_region.primitives); + idx = darray_size_t_cdata_get(&stardis->compute_surface.primitives); + sz = darray_size_t_size_get(&stardis->compute_surface.primitives); ASSERT(sz <= UINT_MAX); szp = (unsigned)sz; SG3D(geometry_get_unique_vertices_count(stardis->geometry.sg3d, &vcount)); @@ -676,15 +689,16 @@ dump_map } /* Dump vertices up to last_v, even unused ones, to avoid reindexing */ - printf("# vtk DataFile Version 2.0\nvtk output\nASCII\nDATASET POLYDATA\n"); - printf("POINTS %u float\n\n", last_v + 1); + fprintf(stream, + "# vtk DataFile Version 2.0\nvtk output\nASCII\nDATASET POLYDATA\n"); + fprintf(stream, "POINTS %u float\n\n", last_v + 1); for(i = 0; i <= last_v; ++i) { double coord[3]; SG3D(geometry_get_unique_vertex(stardis->geometry.sg3d, i, coord)); - printf("%f %f %f\n", SPLIT3(coord)); + fprintf(stream, "%f %f %f\n", SPLIT3(coord)); } /* Dump only primitives in boundary */ - printf("\nPOLYGONS %u %u\n", szp, 4 * szp); + fprintf(stream, "\nPOLYGONS %u %u\n", szp, 4 * szp); for(i = 0; i < szp; ++i) { unsigned t; unsigned indices[3]; @@ -692,50 +706,50 @@ dump_map t = (unsigned)idx[i]; SG3D(geometry_get_unique_triangle_vertices(stardis->geometry.sg3d, t, indices)); - printf("3 %u %u %u\n", SPLIT3(indices)); + fprintf(stream, "3 %u %u %u\n", SPLIT3(indices)); } - printf("\nCELL_DATA %u\n", szp); - printf("SCALARS temperature_estimate float 1\n"); - printf("LOOKUP_TABLE default\n"); + fprintf(stream, "\nCELL_DATA %u\n", szp); + fprintf(stream, "SCALARS temperature_estimate float 1\n"); + fprintf(stream, "LOOKUP_TABLE default\n"); for(i = 0; i < szp; ++i) { struct sdis_mc T; SDIS(estimator_get_temperature(est[i], &T)); - printf("%f\n", T.E); + fprintf(stream, "%f\n", T.E); } - printf("SCALARS temperature_std_dev float 1\n"); - printf("LOOKUP_TABLE default\n"); + fprintf(stream, "SCALARS temperature_std_dev float 1\n"); + fprintf(stream, "LOOKUP_TABLE default\n"); for(i = 0; i < szp; ++i) { struct sdis_mc T; SDIS(estimator_get_temperature(est[i], &T)); - printf("%f\n", T.SE); + fprintf(stream, "%f\n", T.SE); } - printf("SCALARS temperature_failures_count unsigned_long_long 1\n"); - printf("LOOKUP_TABLE default\n"); + fprintf(stream, "SCALARS temperature_failures_count unsigned_long_long 1\n"); + fprintf(stream, "LOOKUP_TABLE default\n"); for(i = 0; i < szp; ++i) { size_t nfails; SDIS(estimator_get_failure_count(est[i], &nfails)); ASSERT(nfails <= UINT_MAX); - printf("%u\n", (unsigned)nfails); + fprintf(stream, "%u\n", (unsigned)nfails); } - printf("SCALARS computation_time_estimate float 1\n"); - printf("LOOKUP_TABLE default\n"); + fprintf(stream, "SCALARS computation_time_estimate float 1\n"); + fprintf(stream, "LOOKUP_TABLE default\n"); for(i = 0; i < szp; ++i) { struct sdis_mc time; SDIS(estimator_get_realisation_time(est[i], &time)); - printf("%f\n", time.E); + fprintf(stream, "%f\n", time.E); } - printf("SCALARS computation_time_std_dev float 1\n"); - printf("LOOKUP_TABLE default\n"); + fprintf(stream, "SCALARS computation_time_std_dev float 1\n"); + fprintf(stream, "LOOKUP_TABLE default\n"); for(i = 0; i < szp; ++i) { struct sdis_mc time; SDIS(estimator_get_realisation_time(est[i], &time)); - printf("%f\n", time.SE); + fprintf(stream, "%f\n", time.SE); } } res_T dump_compute_region_at_the_end_of_vtk - (const struct stardis* stardis, + (struct stardis* stardis, FILE* stream) { res_T res = RES_OK; @@ -743,8 +757,8 @@ dump_compute_region_at_the_end_of_vtk unsigned tsz, i; size_t j; ASSERT(stardis && stream); - ASSERT(darray_size_t_size_get(&stardis->compute_region.primitives) - == darray_sides_size_get(&stardis->compute_region.sides)); + ASSERT(darray_size_t_size_get(&stardis->compute_surface.primitives) + == 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 */ @@ -754,21 +768,40 @@ dump_compute_region_at_the_end_of_vtk goto error; } - /* For triangles in compute region, v==1 if FRONT or v==2 for BACK */ - FOR_EACH(j, 0, darray_size_t_size_get(&stardis->compute_region.primitives)) { - size_t prim = darray_size_t_cdata_get(&stardis->compute_region.primitives)[j]; - enum sdis_side side = darray_sides_cdata_get(&stardis->compute_region.sides)[j]; - ASSERT(prim <= tsz); - ASSERT(v[(unsigned)prim] == 0); /* Not the same triangle twice */ - v[(unsigned)prim] = (side == SDIS_FRONT) ? 1 : 2; - } + 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]; + ASSERT(prim <= tsz); + v[(unsigned)prim] |= (side == SDIS_FRONT ? 1 : 2); + } - /* For triangles in compute region with error v==MAX */ - FOR_EACH(j, 0, darray_uint_size_get(&stardis->compute_region.err_triangles)) { - unsigned prim = darray_uint_cdata_get(&stardis->compute_region.err_triangles)[j]; - ASSERT(prim <= tsz); - ASSERT(v[prim] == 0); /* Not the same triangle twice */ - v[(unsigned)prim] = UCHAR_MAX; + /* 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]; + ASSERT(prim <= tsz); + v[(unsigned)prim] = UCHAR_MAX; + } + } else { + unsigned prop[SG3D_PROP_TYPES_COUNT__]; + struct sdis_medium* medium; + unsigned medium_id; + ASSERT(stardis->mode & MEDIUM_COMPUTE); + medium = find_medium_by_name(stardis, &stardis->solve_name, &medium_id); + ASSERT(medium != NULL); (void)medium; + FOR_EACH(i, 0, tsz) { + ERR(sg3d_geometry_get_unique_triangle_properties(stardis->geometry.sg3d, + i, prop)); + /* For triangles in compute volume, + * v==1 if FRONT, v==2 for BACK, v==3 for BOTH */ + if(prop[SG3D_FRONT] == medium_id && prop[SG3D_BACK] == medium_id) + ; /* Keep v==0, not really a boundary */ + else if(prop[SG3D_FRONT] == medium_id) + v[i] = 1; + else if(prop[SG3D_BACK] == medium_id) + v[i] = 2; + } } fprintf(stream, "SCALARS Compute_region int\n"); diff --git a/src/stardis-output.h b/src/stardis-output.h @@ -17,7 +17,6 @@ struct sdis_estimator; struct stardis; struct geometry; struct vertex; -struct darray_descriptions; struct darray_estimators; extern res_T @@ -27,37 +26,35 @@ print_sample extern res_T dump_image - (const struct sdis_estimator_buffer* buf); + (const struct sdis_estimator_buffer* buf, + FILE* stream); extern res_T dump_green (struct sdis_green_function* green, - const struct counts* counts, - const struct darray_descriptions* descriptions, - const double radiative_temps[2]); - -extern int -has_holes(const struct stardis* stardis); + const struct stardis* stardis, + FILE* stream); extern res_T -dump_holes_at_the_end_of_vtk +dump_enclosure_related_stuff_at_the_end_of_vtk (const struct stardis* stardis, FILE* stream); extern res_T print_single_MC_result - (const int mode, - struct sdis_estimator* estimator, - struct stardis* stardis); + (struct sdis_estimator* estimator, + struct stardis* stardis, + FILE* stream); extern void dump_map (const struct stardis* stardis, - const struct darray_estimators* estimators); + const struct darray_estimators* estimators, + FILE* stream); extern res_T dump_compute_region_at_the_end_of_vtk - (const struct stardis* stardis, + (struct stardis* stardis, FILE* stream); #endif diff --git a/src/stardis-parsing.c b/src/stardis-parsing.c @@ -6,6 +6,7 @@ #include <rsys/cstr.h> #include <rsys/double3.h> #include <sdis_version.h> +#include <rsys/logger.h> #include <getopt.h> #include <stdlib.h> @@ -48,7 +49,7 @@ split_line ASSERT(a_str); /* Count how many elements will be extracted. */ - while (*tmp) + while(*tmp) { if(a_delim == *tmp) { @@ -72,7 +73,7 @@ split_line size_t idx = 0; char* token = strtok(a_str, delim); - while (token) + while(token) { ASSERT(idx < count); #ifdef COMPILER_CL @@ -89,11 +90,13 @@ split_line return result; } -static void +void print_version - () + (FILE* stream) { - printf("Stardis version %i.%i.%i built on stardis solver version %i.%i.%i\n", + ASSERT(stream); + fprintf(stream, + "Stardis version %i.%i.%i built on stardis solver version %i.%i.%i\n", StardisApp_VERSION_MAJOR, StardisApp_VERSION_MINOR, StardisApp_VERSION_PATCH, Stardis_VERSION_MAJOR, Stardis_VERSION_MINOR, Stardis_VERSION_PATCH); } @@ -162,7 +165,7 @@ read_sides_and_files callbacks.get_position = add_geom_ctx_position; /* At least one side+name, no side without name */ - ERR(sstl_create(NULL, stardis->allocator, 0, &sstl)); + ERR(sstl_create(stardis->logger, stardis->allocator, 0, &sstl)); for(;;) { struct str name; if(side_is_intface) { @@ -174,7 +177,8 @@ read_sides_and_files if(!tk) { if(file_count == 0) { /* At least 1 side */ - fprintf(stderr, "Invalid data (missing token 'side')\n"); + logger_print(stardis->logger, LOG_ERROR, + "Invalid data (missing token 'side')\n"); res = RES_BAD_ARG; goto error; } @@ -195,7 +199,8 @@ read_sides_and_files add_geom_ctx.properties[SG3D_BACK] = id; } else { - fprintf(stderr, "Invalid side specifier: %s\n", tk); + logger_print(stardis->logger, LOG_ERROR, + "Invalid side specifier: %s\n", tk); res = RES_BAD_ARG; goto error; } @@ -205,7 +210,8 @@ read_sides_and_files if(!side_is_intface /* Has read a side */ || !file_count) /* Need at least 1 file */ { - fprintf(stderr, "Invalid data (missing token 'file name')\n"); + logger_print(stardis->logger, LOG_ERROR, + "Invalid data (missing token 'file name')\n"); res = RES_BAD_ARG; goto error; } @@ -214,7 +220,8 @@ read_sides_and_files file_count++; res = sstl_load(sstl, tk); if(res != RES_OK) { - fprintf(stderr, "Cannot read STL file: %s\n", tk); + logger_print(stardis->logger, LOG_ERROR, + "Cannot read STL file: '%s'\n", tk); goto error; } ERR(sstl_get_desc(sstl, &add_geom_ctx.stl_desc)); @@ -233,7 +240,8 @@ read_sides_and_files &add_geom_ctx); if(res != RES_OK) { - fprintf(stderr, "Cannot add file content: %s\n", tk); + logger_print(stardis->logger, LOG_ERROR, + "Cannot add file content: '%s'\n", tk); goto error; } } @@ -250,11 +258,14 @@ error: ******************************************************************************/ res_T -init_args(struct mem_allocator* alloc, struct args** out_args) +init_args + (struct logger* logger, + struct mem_allocator* allocator, + struct args** out_args) { res_T res = RES_OK; struct args* args = NULL; - ASSERT(alloc && out_args); + ASSERT(logger && allocator && out_args); args = calloc(sizeof(struct args), 1); if(!args) { @@ -262,14 +273,16 @@ init_args(struct mem_allocator* alloc, struct args** out_args) goto error; } - args->allocator = alloc; - darray_str_init(alloc, &args->model_files); + args->logger = logger; + args->allocator = allocator; + darray_str_init(allocator, &args->model_files); /* Some fields have non-zero default values */ args->samples = 10000; args->nthreads = DEFAULT_NTHREADS; args->probe[3] = INF; /* Probe time */ args->scale_factor = 1; args->radiative_temp[0] = args->radiative_temp[1] = 300; + args->verbose = 1; end: *out_args = args; @@ -283,8 +296,7 @@ error: void release_args(struct args* args) { - ASSERT(args && args->allocator); - args->allocator = NULL; + ASSERT(args); darray_str_release(&args->model_files); } @@ -298,125 +310,183 @@ mode_option if(m & PROBE_COMPUTE_ON_INTERFACE) { found++; res = 'P'; } if(m & MEDIUM_COMPUTE) { found++; res = 'm'; } if(m & BOUNDARY_COMPUTE) { found++; res = 's'; } + if(m & FLUX_BOUNDARY_COMPUTE) { found++; res = 'F'; } if(m & IR_COMPUTE) { found++; res = 'R'; } if(m & MAP_COMPUTE) { found++; res = 'S'; } - if (m & DUMP_VTK) { found++; res = 'd'; } - if (m & FLUX_BOUNDARY_COMPUTE) { found++; res = 'F'; } + if(m & DUMP_VTK) { found++; res = 'd'; } + if(m & DUMP_PATHS) { found++; res = 'D'; } + if(m & DUMP_HELP) { found++; res = 'h'; } + if(m & DUMP_VERSION) { found++; res = 'v'; } + if(m & GREEN_MODE) { found++; res = 'g'; } ASSERT(found == 1); return res; } -void print_multiple_modes - (FILE* stream, - const int modes) +void +print_multiple_modes + (char* buf, + const size_t sz, + const int modes, + const int dont) /* Modes in dont are not printed */ { int b = 0, fst = 1; int m = UNDEF_MODE; - ASSERT(stream); + size_t left = sz; + ASSERT(buf); do { m = BIT(b++); + if(m & dont) continue; if(m & modes) { - fprintf(stream, (fst ? " -%c" : ", -%c"), mode_option(m)); + int n = snprintf(buf, left, (fst ? "-%c" : ", -%c"), mode_option(m)); + if(n < 0 || n >= left) FATAL("Buffer is too small."); + left -= n; + buf += n; fst = 0; } - } while (m <= modes); + } while(m < modes); } void print_help - (const char* prog) + (FILE* stream, + const char* prog) { char* name; + char buf[128]; + ASSERT(stream && prog); + #ifdef COMPILER_GCC name = 1 + strrchr(prog, '/'); #else name = 1 + strrchr(prog, '\\'); #endif - ASSERT(prog); - print_version(); - printf("\nUsage: \n"); - printf("------\n"); - printf("\n%s {-M MODEL_FILE_NAME}+\n", name); - printf(" [ -p X,Y,Z,TIME | -P X,Y,Z,TIME | -m MEDIUM_NAME,TIME\n"); - printf(" | -s STL_FILE_NAME,TIME | -S STL_FILE_NAME,TIME | -F STL_FILE_NAME,TIME\n"); - printf(" | -R t=TIME:spp=SPP:fov=FOV:up=XUP,YUP,ZUP:pos=X,Y,Z:tgt=XT,YT,ZT:img=WxH ]\n"); - printf(" [-d] [-g] [-f SCALE_FACTOR] [-D {all|error|success}] [-n REALIZATIONS_COUNT]\n"); - printf(" [-t NUM_OF_THREADS] [-r AMBIENT_RAD_TEMP:REFERENCE_TEMP]\n"); - printf("\n%s -h: print this help.\n", name); - printf("\n%s -v: print stardis-app version.\n", name); - printf("\nMandatory arguments:\n"); - printf("--------------------\n"); - printf("\n -M <MODEL_FILE_NAME>:\n"); - printf(" Add a text file that contains (partial) description of the model.\n"); - printf(" Can include both media and boundary conditions, in any order.\n"); - printf(" Can be used more than once if description is split across different files.\n"); - printf("\nExclusive arguments:\n"); - printf("--------------------\n"); - printf("\n -p X,Y,Z:TIME:\n"); - printf(" Compute the temperature at the given probe.\n"); - printf(" The probe must be in a medium.\n"); - printf("\n -P X,Y,Z:TIME:\n"); - printf(" Compute the temperature at the given probe on an interface.\n"); - printf(" The probe is suposed to be on an interface and is adjusted to the\n"); - printf(" closest point of the closest interface.\n"); - printf("\n -m MEDIUM_NAME,TIME:\n"); - printf(" Compute the mean temperature in a given medium at a given time. The medium\n"); - printf(" doesn't need to be connex.\n"); - printf("\n -s STL_FILE_NAME,TIME:\n"); - printf(" Compute the mean temperature on a given 2D region at a given time, the\n"); - printf(" region being defined as the front sides of the triangles in the provided\n"); - printf(" file. These triangles are not added to the geometry, but must be already\n"); - printf(" part of it. The region doesn't need to be connex.\n"); - printf("\n -S STL_FILE_NAME,TIME:\n"); - printf(" Compute the by-triangle mean temperature on a given 2D region at a given\n"); - printf(" time, the region being defined as the front sides of the triangles in the\n"); - printf(" provided file. These triangles are not added to the geometry, but must be\n"); - printf(" already part of it. The region doesn't need to be connex.\n"); - printf("\n -F STL_FILE_NAME,TIME:\n"); - printf(" Compute the mean flux on a given 2D region at a given time, the region\n"); - printf(" being defined as the front sides of the triangles in the provided file.\n"); - printf(" Flux is accounted positive when going from the front side to the back side,\n"); - printf(" at a single-triangle scale. These triangles are not added to the geometry,\n"); - printf(" but must be already part of it. The region doesn't need to be connex.\n"); - printf("\n -R t=TIME:spp=SPP:fov=FOV:up=XUP,YUP,ZUP:pos=X,Y,Z:tgt=XT,YT,ZT:img=WxH:\n"); - printf(" The infra-red rendering mode.\n"); - printf(" t is the rendering time (default: INF).\n"); - printf(" spp is the number of samples per pixel (default: 4).\n"); - printf(" fov is the field of view (default: 70 degrees).\n"); - printf(" up is the up direction (default: 0,0,1).\n"); - printf(" pos is the position of the camera (default: 1,1,1).\n"); - printf(" tgt is the target of the camera (default: 0,0,0).\n"); - printf(" img is the image resolution (default: 640x480).\n"); - printf("\nOptionnal arguments:\n"); - printf("--------------------\n"); - printf("\n -d:\n"); - printf(" Dump the geometry in VTK format with various properties, including possible\n"); - printf(" errors. If this option is used, no computation occurs. Including both this\n"); - printf(" option and one of the options specifying a compute region ("); - print_multiple_modes(stdout, REGION_COMPUTE_MODES); printf(") has\n"); - printf(" the effect to include the region in the dump.\n"); - printf("\n -g:\n"); - printf(" Compute the green function at t=INF.\n"); - printf(" Can only be used in conjonction with one these options:"); - print_multiple_modes(stdout, GREEN_COMPATIBLE_MODES); printf("\n"); - printf(" Provided TIME is silently ignored.\n"); - printf("\n -f SCALE_FACTOR.\n"); - printf(" Default value: 1.0.\n"); - printf("\n -D { all|error|success }:\n"); - printf(" Dump paths in VTK format.\n"); - printf("\n -n NUM_OF_REALIZATIONS:\n"); - printf(" Number of Monte-Carlo realizations.\n"); - printf(" Default value: 10000.\n"); - printf("\n -t NUM_OF_THREADS:\n"); - printf(" Number of threads; default value is all threads available.\n"); - printf("\n -r AMBIENT_RAD_TEMP,REFERENCE_TEMP:\n"); - printf(" Parameters for the radiative transfer.\n"); - printf(" AMBIENT_RAD_TEMP is the ambient radiative temperature .\n"); - printf(" REFERENCE_TEMP is the temperature used for the linearization\n"); - printf(" of the radiative transfer.\n"); - printf(" Default values: 300 and 300.\n"); - printf("\n -V:\n"); - printf(" Verbose mode.\n"); + + print_version(stream); + fprintf(stream, "\nUsage: \n"); + fprintf(stream, "------\n"); + + fprintf(stream, "\n%s {-M MODEL_FILE_NAME}+\n", name); + fprintf(stream, " [ -p X,Y,Z,TIME | -P X,Y,Z,TIME | -m MEDIUM_NAME,TIME\n"); + fprintf(stream, " | -s STL_FILE_NAME,TIME | -S STL_FILE_NAME,TIME | -F STL_FILE_NAME,TIME\n"); + fprintf(stream, " | -R t=TIME:spp=SPP:fov=FOV:up=XUP,YUP,ZUP:pos=X,Y,Z:tgt=XT,YT,ZT:img=WxH ]\n"); + fprintf(stream, " [-d] [-D {all|error|success}] [-g] [-f SCALE_FACTOR] [-n REALIZATIONS_COUNT]\n"); + fprintf(stream, " [-t NUM_OF_THREADS] [-r AMBIENT_RAD_TEMP:REFERENCE_TEMP]\n"); + + fprintf(stream, "\n%s -h: print this help.\n", name); + + fprintf(stream, "\n%s -v: print stardis-app version.\n", name); + + fprintf(stream, "\nMandatory arguments:\n"); + fprintf(stream, "--------------------\n"); + + fprintf(stream, "\n -M <MODEL_FILE_NAME>:\n"); + fprintf(stream, " Add a text file that contains (partial) description of the model.\n"); + fprintf(stream, " Can include both media and boundary conditions, in any order.\n"); + fprintf(stream, " Can be used more than once if description is split across different files.\n"); + + fprintf(stream, "\nExclusive arguments:\n"); + fprintf(stream, "--------------------\n"); + + fprintf(stream, "\n -p X,Y,Z,TIME:\n"); + fprintf(stream, " Compute the temperature at the given probe.\n"); + fprintf(stream, " The probe must be in a medium.\n"); + + fprintf(stream, "\n -P X,Y,Z,TIME:\n"); + fprintf(stream, " Compute the temperature at the given probe on an interface.\n"); + fprintf(stream, " The probe is suposed to be on an interface and is adjusted to the\n"); + fprintf(stream, " closest point of the closest interface.\n"); + + fprintf(stream, "\n -m MEDIUM_NAME,TIME:\n"); + fprintf(stream, " Compute the mean temperature in a given medium at a given time. The medium\n"); + fprintf(stream, " doesn't need to be connex.\n"); + + fprintf(stream, "\n -s STL_FILE_NAME,TIME:\n"); + fprintf(stream, " Compute the mean temperature on a given 2D region at a given time, the\n"); + fprintf(stream, " region being defined as the front sides of the triangles in the provided\n"); + fprintf(stream, " file. These triangles are not added to the geometry, but must be already\n"); + fprintf(stream, " part of it. The region doesn't need to be connex.\n"); + + fprintf(stream, "\n -S STL_FILE_NAME,TIME:\n"); + fprintf(stream, " Compute the by-triangle mean temperature on a given 2D region at a given\n"); + fprintf(stream, " time, the region being defined as the front sides of the triangles in the\n"); + fprintf(stream, " provided file. These triangles are not added to the geometry, but must be\n"); + fprintf(stream, " already part of it. The region doesn't need to be connex.\n"); + + fprintf(stream, "\n -F STL_FILE_NAME,TIME:\n"); + fprintf(stream, " Compute the mean flux on a given 2D region at a given time, the region\n"); + fprintf(stream, " being defined as the front sides of the triangles in the provided file.\n"); + fprintf(stream, " Flux is accounted positive when going from the front side to the back side,\n"); + fprintf(stream, " at a single-triangle scale. These triangles are not added to the geometry,\n"); + fprintf(stream, " but must be already part of it. The region doesn't need to be connex.\n"); + + fprintf(stream, "\n -R t=TIME:spp=SPP:fov=FOV:up=XUP,YUP,ZUP:pos=X,Y,Z:tgt=XT,YT,ZT:img=WxH:\n"); + fprintf(stream, " Compute an infra-red image of the model and dump it to stdout in VTK format.\n"); + fprintf(stream, " t is the rendering time (default: INF).\n"); + fprintf(stream, " spp is the number of samples per pixel (default: 4).\n"); + fprintf(stream, " fov is the field of view (default: 70 degrees).\n"); + fprintf(stream, " up is the up direction (default: 0,0,1).\n"); + fprintf(stream, " pos is the position of the camera (default: 1,1,1).\n"); + fprintf(stream, " tgt is the target of the camera (default: 0,0,0).\n"); + fprintf(stream, " img is the image resolution (default: 640x480).\n"); + + fprintf(stream, "\nOptionnal arguments:\n"); + fprintf(stream, "--------------------\n"); + + fprintf(stream, "\n -d:\n"); + fprintf(stream, " Dump the geometry to stdout in VTK format along with various properties,\n"); + fprintf(stream, " including possible errors. If this option is used, no computation occurs.\n"); + fprintf(stream, " Using this option in conjunction with an options that specifies a compute\n"); + print_multiple_modes(buf, sizeof(buf), SURFACE_COMPUTE_MODES, 0); + fprintf(stream, " region (%s) has the effect to include the region in the dump.\n", buf); + fprintf(stream, " This option cannot be used in conjunction with other dump options.\n"); + print_multiple_modes(buf, sizeof(buf), USE_STDOUT_MODES, DUMP_VTK); + fprintf(stream, " (%s).\n", buf); + + fprintf(stream, "\n -D TYPE:\n"); + fprintf(stream, " Dump thermal paths of type TYPE to stdout in VTK format.\n"); + fprintf(stream, " Type can be:\n"); + fprintf(stream, " - error (paths ending in error),\n"); + fprintf(stream, " - success (successful paths)\n"); + fprintf(stream, " - all (all paths).\n"); + + fprintf(stream, " This option can only be used in conjuction with an option that runs a\n"); + print_multiple_modes(buf, sizeof(buf), COMPUTE_MODES, 0); + fprintf(stream, " computation (%s) and cannot be used in conjunction\n", buf); + print_multiple_modes(buf, sizeof(buf), USE_STDOUT_MODES, DUMP_PATHS); + fprintf(stream, " with other dump options (%s).\n", buf); + + fprintf(stream, "\n -g:\n"); + fprintf(stream, " Change the required computation to produce the green function at t=INF\n"); + fprintf(stream, " and dump it to stdout.\n"); + print_multiple_modes(buf, sizeof(buf), GREEN_COMPATIBLE_MODES, 0); + fprintf(stream, " Can only be used in conjonction with one these options: %s\n", buf); + fprintf(stream, " The provided TIME is silently ignored.\n"); + + fprintf(stream, "\n -f SCALE_FACTOR.\n"); + fprintf(stream, " Rescale the geometry before sending it to the solver.\n"); + + fprintf(stream, "\n -n NUM_OF_REALIZATIONS:\n"); + fprintf(stream, " Set the number of Monte-Carlo realizations.\n"); + fprintf(stream, " Default value: 10000.\n"); + + fprintf(stream, "\n -t NUM_OF_THREADS:\n"); + fprintf(stream, " Set the number of threads.\n"); + fprintf(stream, " Default is to use all threads available.\n"); + + fprintf(stream, "\n -r AMBIENT_RAD_TEMP,REFERENCE_TEMP:\n"); + fprintf(stream, " Set the parameters for the radiative transfer.\n"); + fprintf(stream, " AMBIENT_RAD_TEMP is the ambient radiative temperature .\n"); + fprintf(stream, " REFERENCE_TEMP is the temperature used for the linearization of the\n"); + fprintf(stream, " radiative transfer.\n"); + fprintf(stream, " Default values: 300 and 300.\n"); + + fprintf(stream, "\n -V LEVEL:\n"); + fprintf(stream, " Set the verbosity level.\n"); + fprintf(stream, " Level can be:\n"); + fprintf(stream, " - 0 (non-verbose),\n"); + fprintf(stream, " - 1 (errors only, default),\n"); + fprintf(stream, " - 2 (errors and warnings),\n"); + fprintf(stream, " - 3 (errors, warnings and messages).\n"); } res_T @@ -427,33 +497,52 @@ parse_args { int opt = 0, n_used = 0; size_t len = 0; + const char option_list[] = "hvgn:t:B:M:m:p:P:dD:s:S:F:f:r:R:V:"; + char buf[128]; res_T res = RES_OK; ASSERT(argv && args); - if(argc == 1) { - print_help(argv[0]); - res = RES_BAD_ARG; - goto error; - } - opterr = 0; /* No default error messages */ - while ((opt = getopt(argc, argv, "hvgn:t:B:M:m:p:P:dD:s:S:F:f:r:R:V")) != -1) { + while((opt = getopt(argc, argv, option_list)) != -1) { switch (opt) { case '?': /* Unreconised option */ + { + char* ptr = strchr(option_list, optopt); res = RES_BAD_ARG; - fprintf(stderr, "Invalid option -%c\n", optopt); + if(ptr && ptr[1] == ':') { + logger_print(args->logger, LOG_ERROR, + "Missing argument for option -%c\n", + optopt); + } else { + logger_print(args->logger, LOG_ERROR, "Invalid option -%c\n", optopt); + } goto error; + } case 'h': - print_help(argv[0]); - args->just_help = 1; - goto end; + if(args->mode & USE_STDOUT_MODES) { + res = RES_BAD_ARG; + print_multiple_modes(buf, sizeof(buf), USE_STDOUT_MODES, DUMP_HELP); + logger_print(args->logger, LOG_ERROR, + "Option -%c cannot be used in conjunction with other dump options (%s).\n", + (char)opt, buf); + goto error; + } + args->mode |= DUMP_HELP; + break; case 'v': - print_version(); - args->just_help = 1; - goto end; + if(args->mode & USE_STDOUT_MODES) { + res = RES_BAD_ARG; + print_multiple_modes(buf, sizeof(buf), USE_STDOUT_MODES, DUMP_VERSION); + logger_print(args->logger, LOG_ERROR, + "Option -%c cannot be used in conjunction with other dump options (%s).\n", + (char)opt, buf); + goto error; + } + args->mode |= DUMP_VERSION; + break; case 'g': args->mode |= GREEN_MODE; @@ -466,7 +555,9 @@ parse_args || n == 0) { if(res == RES_OK) res = RES_BAD_ARG; - fprintf(stderr, "Invalid argument for option -%c: %s\n", opt, optarg); + logger_print(args->logger, LOG_ERROR, + "Invalid argument for option -%c: %s\n", + opt, optarg); goto error; } args->samples = n; @@ -489,7 +580,9 @@ parse_args || args->nthreads <= 0) { if(res == RES_OK) res = RES_BAD_ARG; - fprintf(stderr, "Invalid argument for option -%c: %s\n", opt, optarg); + logger_print(args->logger, LOG_ERROR, + "Invalid argument for option -%c: %s\n", + opt, optarg); goto error; } break; @@ -497,18 +590,21 @@ parse_args case 'p': if(args->mode & EXCLUSIVE_MODES) { res = RES_BAD_ARG; - fprintf(stderr, "Modes -%c and -%c are exclusive.\n", + logger_print(args->logger, LOG_ERROR, + "Modes -%c and -%c are exclusive.\n", (char)opt, mode_option(args->mode)); goto error; } args->mode |= PROBE_COMPUTE; - cstr_to_list_double(optarg, ',', args->probe, &len, 4); + res = cstr_to_list_double(optarg, ',', args->probe, &len, 4); if(len != 4 || res != RES_OK || args->probe[3] < 0) { if(res == RES_OK) res = RES_BAD_ARG; - fprintf(stderr, "Invalid argument for option -%c: %s\n", opt, optarg); + logger_print(args->logger, LOG_ERROR, + "Invalid argument for option -%c: %s\n", + opt, optarg); goto error; } break; @@ -516,18 +612,21 @@ parse_args case 'P': if(args->mode & EXCLUSIVE_MODES) { res = RES_BAD_ARG; - fprintf(stderr, "Modes -%c and -%c are exclusive.\n", + logger_print(args->logger, LOG_ERROR, + "Modes -%c and -%c are exclusive.\n", (char)opt, mode_option(args->mode)); goto error; } args->mode |= PROBE_COMPUTE_ON_INTERFACE; - cstr_to_list_double(optarg, ',', args->probe, &len, 4); + res = cstr_to_list_double(optarg, ',', args->probe, &len, 4); if(len != 4 || res != RES_OK || args->probe[3] < 0) { if(res == RES_OK) res = RES_BAD_ARG; - fprintf(stderr, "Invalid argument for option -%c: %s\n", opt, optarg); + logger_print(args->logger, LOG_ERROR, + "Invalid argument for option -%c: %s\n", + opt, optarg); goto error; } break; @@ -539,7 +638,8 @@ parse_args char *ptr; if(args->mode & EXCLUSIVE_MODES) { res = RES_BAD_ARG; - fprintf(stderr, "Modes -%c and -%c are exclusive.\n", + logger_print(args->logger, LOG_ERROR, + "Modes -%c and -%c are exclusive.\n", (char)opt, mode_option(args->mode)); goto error; } @@ -555,18 +655,21 @@ parse_args break; } ptr = strrchr(optarg, ','); - /* Single ',' allowed */ + /* Single ',' expected */ if(!ptr || ptr != strchr(optarg, ',')) err = 1; else { *ptr = '\0'; ptr++; - args->solve_boundary_filename = optarg; - err = (RES_OK != cstr_to_double(ptr, args->probe + 3) || args->probe[3] < 0); + args->solve_filename = optarg; + err = (RES_OK != cstr_to_double(ptr, args->probe + 3) + || args->probe[3] < 0); } if(err) { res = RES_BAD_ARG; - fprintf(stderr, "Invalid argument for option -%c: %s\n", opt, optarg); + logger_print(args->logger, LOG_ERROR, + "Invalid argument for option -%c: %s\n", + opt, optarg); goto error; } break; @@ -576,7 +679,8 @@ parse_args char* ptr; if(args->mode & EXCLUSIVE_MODES) { res = RES_BAD_ARG; - fprintf(stderr, "Modes -%c and -%c are exclusive.\n", + logger_print(args->logger, LOG_ERROR, + "Modes -%c and -%c are exclusive.\n", (char)opt, mode_option(args->mode)); goto error; } @@ -586,7 +690,9 @@ parse_args res = RES_BAD_ARG; else res = cstr_to_double(ptr + 1, args->probe + 3); if(res != RES_OK) { - fprintf(stderr, "Invalid argument for option -%c: %s\n", opt, optarg); + logger_print(args->logger, LOG_ERROR, + "Invalid argument for option -%c: %s\n", + opt, optarg); goto error; } *ptr = '\0'; @@ -595,6 +701,14 @@ parse_args } case 'd': + if(args->mode & USE_STDOUT_MODES) { + res = RES_BAD_ARG; + print_multiple_modes(buf, sizeof(buf), USE_STDOUT_MODES, DUMP_VTK); + logger_print(args->logger, LOG_ERROR, + "Option -%c cannot be used in conjunction with other dump options (%s).\n", + (char)opt, buf); + goto error; + } args->mode |= DUMP_VTK; break; @@ -609,31 +723,54 @@ parse_args args->dump_paths = DUMP_SUCCESS; } else { res = RES_BAD_ARG; - fprintf(stderr, "Invalid argument for option -%c: %s\n", opt, optarg); + logger_print(args->logger, LOG_ERROR, + "Invalid argument for option -%c: %s\n", + opt, optarg); + goto error; + } + if(args->mode & USE_STDOUT_MODES) { + res = RES_BAD_ARG; + print_multiple_modes(buf, sizeof(buf), USE_STDOUT_MODES, DUMP_PATHS); + logger_print(args->logger, LOG_ERROR, + "Option -%c cannot be used in conjunction with other dump options\n(%s).\n", + (char)opt, buf); goto error; } + if(!(args->mode & COMPUTE_MODES)) { + res = RES_BAD_ARG; + print_multiple_modes(buf, sizeof(buf), COMPUTE_MODES, 0); + logger_print(args->logger, LOG_ERROR, + "Option -%c can only be used in conjunction with a compute option\n(%s).\n", + (char)opt, buf); + goto error; + } + args->mode |= DUMP_PATHS; break; case 'f': - cstr_to_double(optarg, &args->scale_factor); + res = cstr_to_double(optarg, &args->scale_factor); if(res != RES_OK || args->scale_factor <= 0) { if(res == RES_OK) res = RES_BAD_ARG; - fprintf(stderr, "Invalid argument for option -%c: %s\n", opt, optarg); + logger_print(args->logger, LOG_ERROR, + "Invalid argument for option -%c: %s\n", + opt, optarg); goto error; } break; case 'r': - cstr_to_list_double(optarg, ',', args->radiative_temp, &len, 2); + res = cstr_to_list_double(optarg, ',', args->radiative_temp, &len, 2); if(res != RES_OK || len != 2 - || args->radiative_temp[0] <= 0 - || args->radiative_temp[1] <= 0) + || args->radiative_temp[0] < 0 + || args->radiative_temp[1] < 0) { if(res == RES_OK) res = RES_BAD_ARG; - fprintf(stderr, "Invalid argument for option -%c: %s\n", opt, optarg); + logger_print(args->logger, LOG_ERROR, + "Invalid argument for option -%c: %s\n", + opt, optarg); goto error; } break; @@ -641,7 +778,8 @@ parse_args case 'R': if(args->mode & EXCLUSIVE_MODES) { res = RES_BAD_ARG; - fprintf(stderr, "Modes -%c and -%c are exclusive.\n", + logger_print(args->logger, LOG_ERROR, + "Modes -%c and -%c are exclusive.\n", (char)opt, mode_option(args->mode)); goto error; } @@ -650,29 +788,62 @@ parse_args break; case 'V': - args->verbose = 1; + res = cstr_to_int(optarg, &args->verbose); + if(res != RES_OK + || args->verbose < 0 + || args->verbose > 3) + { + if(res == RES_OK) res = RES_BAD_ARG; + logger_print(args->logger, LOG_ERROR, + "Invalid argument for option -%c: %s\n", + opt, optarg); + goto error; + } break; } } - - if(args->mode & GREEN_MODE - && (args->mode != (args->mode & (GREEN_MODE | GREEN_COMPATIBLE_MODES)))) - { - fprintf(stderr, "Option -g can only be used in conjunction with:"); - print_multiple_modes(stderr, GREEN_COMPATIBLE_MODES); - fprintf(stderr, "\n"); + + if(argc > optind) { + int i; + for(i = optind; i < argc; i++) { + logger_print(args->logger, LOG_ERROR, "Unexpected argument: %s.\n", argv[i]); + } + res = RES_BAD_ARG; + goto error; + } + + if(!darray_str_size_get(&args->model_files) + && !(args->mode & SHORT_EXIT_MODES)) { + logger_print(args->logger, LOG_ERROR, + "Missing mandatory argument: -M <model_file_name>\n"); res = RES_BAD_ARG; goto error; } - if(!darray_str_size_get(&args->model_files)) { - fprintf(stderr, "Missing mandatory argument: -M <model_file_name>\n"); + if(args->mode == UNDEF_MODE) { + print_multiple_modes(buf, sizeof(buf), EXCLUSIVE_MODES | USE_STDOUT_MODES, 0); + logger_print(args->logger, LOG_WARNING, + "Nothing to do. One of the following options should be used: %s", + buf); + res = RES_BAD_ARG; + goto error; + } + + if(args->mode & GREEN_MODE + && (args->mode != (args->mode & (GREEN_MODE | GREEN_COMPATIBLE_MODES)))) + { + print_multiple_modes(buf, sizeof(buf), GREEN_COMPATIBLE_MODES, 0); + logger_print(args->logger, LOG_ERROR, + "Option -g can only be used in conjunction with: %s", + buf); + logger_print(args->logger, LOG_ERROR, "\n"); res = RES_BAD_ARG; goto error; } if(args->mode & IR_COMPUTE && n_used) { - fprintf(stderr, "The -n option has no effect in rendering mode;" + logger_print(args->logger, LOG_ERROR, + "The -n option has no effect in rendering mode;" " use rendering's SPP suboption instead.\n"); res = RES_BAD_ARG; goto error; @@ -681,13 +852,14 @@ parse_args end: return res; error: - fprintf(stderr, "Use the -h option to get help.\n"); + logger_print(args->logger, LOG_ERROR, "Use option -h to print help.\n"); goto end; } res_T parse_camera - (char* cam_param, + (struct logger* logger, + char* cam_param, struct camera* cam) { char** line = NULL; @@ -725,7 +897,8 @@ parse_camera else if(strcmp(opt[0], "SPP") == 0) { ERR(cstr_to_uint(opt[1], &cam->spp)); } else { - fprintf(stderr, "Warning: unexpected option for rendering mode: %s.\n", + logger_print(logger, LOG_ERROR, + "Unexpected option for rendering mode: %s.\n", opt[0]); res = RES_BAD_ARG; goto error; @@ -747,7 +920,8 @@ end: return res; error: - fprintf(stderr, "Use the -h option to get help.\n"); + logger_print(logger, LOG_ERROR, "Error parsing camera options.\n"); + logger_print(logger, LOG_ERROR, "Use the -h option to get help.\n"); goto end; } @@ -784,7 +958,7 @@ process_h || desc->d.h_boundary.emissivity < 0 || desc->d.h_boundary.emissivity > 1) { - fprintf(stderr, "Invalid emissivity: %s\n", tk); + logger_print(stardis->logger, LOG_ERROR, "Invalid emissivity: %s\n", tk); if(res == RES_OK) res = RES_BAD_ARG; goto end; } @@ -794,7 +968,8 @@ process_h || desc->d.h_boundary.specular_fraction < 0 || desc->d.h_boundary.specular_fraction > 1) { - fprintf(stderr, "Invalid specular fraction: %s\n", tk); + logger_print(stardis->logger, LOG_ERROR, + "Invalid specular fraction: %s\n", tk); if(res == RES_OK) res = RES_BAD_ARG; goto end; } @@ -803,7 +978,7 @@ process_h if(res != RES_OK || desc->d.h_boundary.hc < 0) { - fprintf(stderr, "Invalid hc: %s\n", tk); + logger_print(stardis->logger, LOG_ERROR, "Invalid hc: %s\n", tk); if(res == RES_OK) res = RES_BAD_ARG; goto end; } @@ -812,7 +987,7 @@ process_h if(res != RES_OK || desc->d.h_boundary.imposed_temperature < 0) { - fprintf(stderr, "Invalid temperature: %s\n", tk); + logger_print(stardis->logger, LOG_ERROR, "Invalid temperature: %s\n", tk); if(res == RES_OK) res = RES_BAD_ARG; goto end; } @@ -826,7 +1001,7 @@ error: } /* T_BOUNDARY_FOR_SOLID Name T STL_filenames - * T_BOUNDARY_FOR_FLUID Name T hc STL_filenames */ + * T_BOUNDARY_FOR_FLUID Name T emissivity specular_fraction hc STL_filenames */ static res_T process_t (struct stardis* stardis, @@ -857,17 +1032,38 @@ process_t if(res != RES_OK || desc->d.t_boundary.imposed_temperature < 0) { - fprintf(stderr, "Invalid temperature: %s\n", tk); + logger_print(stardis->logger, LOG_ERROR, "Invalid temperature: %s\n", tk); if(res == RES_OK) res = RES_BAD_ARG; goto end; } if(type == DESC_BOUND_T_FOR_FLUID) { + CHK_TOK(strtok_r(NULL, " ", tok_ctx), "emissivity"); + res = cstr_to_double(tk, &desc->d.t_boundary.emissivity); + if(res != RES_OK + || desc->d.t_boundary.emissivity < 0 + || desc->d.t_boundary.emissivity > 1) + { + logger_print(stardis->logger, LOG_ERROR, "Invalid emissivity: %s\n", tk); + if(res == RES_OK) res = RES_BAD_ARG; + goto end; + } + CHK_TOK(strtok_r(NULL, " ", tok_ctx), "specular fraction"); + res = cstr_to_double(tk, &desc->d.t_boundary.specular_fraction); + if(res != RES_OK + || desc->d.t_boundary.specular_fraction < 0 + || desc->d.t_boundary.specular_fraction > 1) + { + logger_print(stardis->logger, LOG_ERROR, + "Invalid specular fraction: %s\n", tk); + if(res == RES_OK) res = RES_BAD_ARG; + goto end; + } CHK_TOK(strtok_r(NULL, " ", tok_ctx), "hc"); res = cstr_to_double(tk, &desc->d.t_boundary.hc); if(res != RES_OK || desc->d.t_boundary.hc < 0) { - fprintf(stderr, "Invalid hc: %s\n", tk); + logger_print(stardis->logger, LOG_ERROR, "Invalid hc: %s\n", tk); if(res == RES_OK) res = RES_BAD_ARG; goto end; } @@ -910,7 +1106,7 @@ process_flx res = cstr_to_double(tk, &desc->d.f_boundary.imposed_flux); if(res != RES_OK) { /* Flux can be < 0 */ - fprintf(stderr, "Invalid flux: %s\n", tk); + logger_print(stardis->logger, LOG_ERROR, "Invalid flux: %s\n", tk); goto end; } @@ -954,7 +1150,7 @@ process_sfc || desc->d.sf_connect.emissivity < 0 || desc->d.h_boundary.emissivity > 1) { - fprintf(stderr, "Invalid emissivity: %s\n", tk); + logger_print(stardis->logger, LOG_ERROR, "Invalid emissivity: %s\n", tk); if(res == RES_OK) res = RES_BAD_ARG; goto end; } @@ -964,16 +1160,17 @@ process_sfc || desc->d.sf_connect.specular_fraction < 0 || desc->d.sf_connect.specular_fraction > 1) { - fprintf(stderr, "Invalid specular fraction: %s\n", tk); + logger_print(stardis->logger, LOG_ERROR, + "Invalid specular fraction: %s\n", tk); if(res == RES_OK) res = RES_BAD_ARG; goto end; } CHK_TOK(strtok_r(NULL, " ", tok_ctx), "hc"); res = cstr_to_double(tk, &desc->d.sf_connect.hc); if(res != RES_OK - || desc->d.sf_connect.hc <= 0) + || desc->d.sf_connect.hc < 0) { - fprintf(stderr, "Invalid hc: %s\n", tk); + logger_print(stardis->logger, LOG_ERROR, "Invalid hc: %s\n", tk); if(res == RES_OK) res = RES_BAD_ARG; goto end; } @@ -1016,7 +1213,7 @@ process_solid if(res != RES_OK || desc->d.solid.lambda <= 0) { - fprintf(stderr, "Invalid lambda: %s\n", tk); + logger_print(stardis->logger, LOG_ERROR, "Invalid lambda: %s\n", tk); if(res == RES_OK) res = RES_BAD_ARG; goto end; } @@ -1025,7 +1222,7 @@ process_solid if(res != RES_OK || desc->d.solid.rho <= 0) { - fprintf(stderr, "Invalid rho: %s\n", tk); + logger_print(stardis->logger, LOG_ERROR, "Invalid rho: %s\n", tk); if(res == RES_OK) res = RES_BAD_ARG; goto end; } @@ -1034,7 +1231,7 @@ process_solid if(res != RES_OK || desc->d.solid.cp <= 0) { - fprintf(stderr, "Invalid cp: %s\n", tk); + logger_print(stardis->logger, LOG_ERROR, "Invalid cp: %s\n", tk); if(res == RES_OK) res = RES_BAD_ARG; goto end; } @@ -1043,7 +1240,7 @@ process_solid if(res != RES_OK || desc->d.solid.delta <= 0) { - fprintf(stderr, "Invalid delta: %s\n", tk); + logger_print(stardis->logger, LOG_ERROR, "Invalid delta: %s\n", tk); if(res == RES_OK) res = RES_BAD_ARG; goto end; } @@ -1052,7 +1249,7 @@ process_solid if(res != RES_OK || desc->d.solid.tinit < 0) { - fprintf(stderr, "Invalid Tinit: %s\n", tk); + logger_print(stardis->logger, LOG_ERROR, "Invalid Tinit: %s\n", tk); if(res == RES_OK) res = RES_BAD_ARG; goto end; } @@ -1060,7 +1257,7 @@ process_solid res = cstr_to_double(tk, &desc->d.solid.vpower); if(res != RES_OK) { /* VPower can be < 0 */ - fprintf(stderr, "Invalid volumic power: %s\n", tk); + logger_print(stardis->logger, LOG_ERROR, "Invalid volumic power: %s\n", tk); goto end; } @@ -1102,7 +1299,7 @@ process_fluid if(res != RES_OK || desc->d.fluid.rho <= 0) { - fprintf(stderr, "Invalid rho: %s\n", tk); + logger_print(stardis->logger, LOG_ERROR, "Invalid rho: %s\n", tk); if(res == RES_OK) res = RES_BAD_ARG; goto end; } @@ -1111,7 +1308,7 @@ process_fluid if(res != RES_OK || desc->d.fluid.cp <= 0) { - fprintf(stderr, "Invalid cp: %s\n", tk); + logger_print(stardis->logger, LOG_ERROR, "Invalid cp: %s\n", tk); if(res == RES_OK) res = RES_BAD_ARG; goto end; } @@ -1120,7 +1317,7 @@ process_fluid if(res != RES_OK || desc->d.fluid.tinit < 0) { - fprintf(stderr, "Invalid Tinit: %s\n", tk); + logger_print(stardis->logger, LOG_ERROR, "Invalid Tinit: %s\n", tk); if(res == RES_OK) res = RES_BAD_ARG; goto end; } @@ -1147,14 +1344,18 @@ error: */ res_T process_model_line - (char* line, + (const char* file_name, + char* line, struct stardis* stardis) { res_T res = RES_OK; + struct str keep; char* tk = NULL, * tok_ctx = NULL; ASSERT(line && stardis); + str_init(stardis->allocator, &keep); + ERR(str_set(&keep, line)); CHK_TOK(strtok_r(line, " ", &tok_ctx), "model line type"); _strupr(tk); @@ -1175,13 +1376,18 @@ process_model_line else if(0 == strcmp(tk, "FLUID")) ERR(process_fluid(stardis, &tok_ctx)); else { - fprintf(stderr, "Unknown description type: %s\n", tk); + logger_print(stardis->logger, LOG_ERROR, + "Unknown description type: %s\n", tk); res = RES_BAD_ARG; goto error; } end: + str_release(&keep); return res; error: + logger_print(stardis->logger, LOG_ERROR, + "Invalid description line in model file '%s':\n", file_name); + logger_print(stardis->logger, LOG_ERROR, "%s\n", str_cget(&keep)); goto end; } \ No newline at end of file diff --git a/src/stardis-parsing.h b/src/stardis-parsing.h @@ -11,13 +11,15 @@ #include <star/sstl.h> struct camera; -struct description; +struct logger; +enum log_type; struct mem_allocator; struct stardis; /* Utility macros */ #define CHK_TOK(x, Name) if((tk = (x)) == NULL) {\ - fprintf(stderr, "Invalid data (missing token '" Name "')\n");\ + logger_print(stardis->logger, LOG_ERROR,\ + "Invalid data (missing token '" Name "')\n");\ res = RES_BAD_ARG;\ goto error;\ } (void)0 @@ -37,17 +39,26 @@ enum stardis_mode { DUMP_VTK = BIT(6), GREEN_MODE = BIT(7), FLUX_BOUNDARY_COMPUTE = BIT(8), + DUMP_PATHS = BIT(9), + DUMP_HELP = BIT(10), + DUMP_VERSION = BIT(11), - GREEN_COMPATIBLE_MODES = PROBE_COMPUTE | PROBE_COMPUTE_ON_INTERFACE | MEDIUM_COMPUTE - | BOUNDARY_COMPUTE, + GREEN_COMPATIBLE_MODES + = PROBE_COMPUTE | PROBE_COMPUTE_ON_INTERFACE | MEDIUM_COMPUTE | BOUNDARY_COMPUTE, - REGION_COMPUTE_MODES = BOUNDARY_COMPUTE | FLUX_BOUNDARY_COMPUTE | MAP_COMPUTE, + SURFACE_COMPUTE_MODES + = BOUNDARY_COMPUTE | FLUX_BOUNDARY_COMPUTE | MAP_COMPUTE, - COMPUTE_MODES = GREEN_COMPATIBLE_MODES | IR_COMPUTE | REGION_COMPUTE_MODES, + REGION_COMPUTE_MODES = SURFACE_COMPUTE_MODES | MEDIUM_COMPUTE, - NON_COMPUTE_MODES = UNDEF_MODE | DUMP_VTK | GREEN_MODE, + COMPUTE_MODES = GREEN_COMPATIBLE_MODES | IR_COMPUTE | SURFACE_COMPUTE_MODES, - EXCLUSIVE_MODES = COMPUTE_MODES | FLUX_BOUNDARY_COMPUTE + EXCLUSIVE_MODES = COMPUTE_MODES, + + SHORT_EXIT_MODES = DUMP_HELP | DUMP_VERSION, + + USE_STDOUT_MODES + = DUMP_VTK | DUMP_PATHS | DUMP_HELP | DUMP_VERSION | IR_COMPUTE | GREEN_MODE }; STATIC_ASSERT(GREEN_COMPATIBLE_MODES == (COMPUTE_MODES & GREEN_COMPATIBLE_MODES), @@ -61,10 +72,11 @@ enum dump_path_type { }; struct args { + struct logger* logger; struct mem_allocator* allocator; struct darray_str model_files; char* medium_name; - char* solve_boundary_filename; + char* solve_filename; size_t samples; unsigned nthreads; double probe[4]; @@ -73,7 +85,6 @@ struct args { double radiative_temp[2]; char* camera; enum dump_path_type dump_paths; - int just_help; int verbose; }; @@ -111,10 +122,14 @@ add_geom_ctx_position #endif extern LOCAL_SYM res_T -init_args(struct mem_allocator* mem, struct args** args); +init_args + (struct logger* logger, + struct mem_allocator* mem, + struct args** args); extern LOCAL_SYM void -release_args(struct args* args); +release_args + (struct args* args); extern char mode_option @@ -122,12 +137,19 @@ mode_option extern void print_multiple_modes - (FILE* stream, - const int modes); + (char* buf, + const size_t sz, + const int modes, + const int dont); + +extern void +print_version + (FILE* stream); extern void print_help - (const char* prog); + (FILE* stream, + const char* prog); extern res_T parse_args @@ -137,12 +159,14 @@ parse_args extern res_T parse_camera - (char* cam_param, + (struct logger* logger, + char* cam_param, struct camera* cam); extern LOCAL_SYM res_T process_model_line - (char* line, + (const char* file_name, + char* line, struct stardis* stardis); #endif /*ARGS_H*/ diff --git a/src/stardis-solid.c b/src/stardis-solid.c @@ -102,10 +102,9 @@ solid_get_power ******************************************************************************/ res_T -create_solid - (struct sdis_device* dev, - struct mem_allocator* allocator, - const struct str* name, +create_stardis_solid + (struct stardis* stardis, + const struct str* name, /* Can be NULL */ const double lambda, const double rho, const double cp, @@ -115,7 +114,6 @@ create_solid const double tinit, const double imposed_temperature, const double vpower, - struct darray_media_ptr* media_ptr, unsigned* out_id) { res_T res = RES_OK; @@ -125,8 +123,8 @@ create_solid size_t sz; /* Could be less restrictive if green output included positions/dates */ - ASSERT(dev && lambda >= 0 && rho >= 0 && cp >= 0 && delta > 0 - && media_ptr && out_id); + ASSERT(stardis && lambda >= 0 && rho >= 0 && cp >= 0 && delta > 0 + && out_id); solid_shader.calorific_capacity = solid_get_calorific_capacity; solid_shader.thermal_conductivity = solid_get_thermal_conductivity; solid_shader.volumic_mass = solid_get_volumic_mass; @@ -135,14 +133,15 @@ create_solid solid_shader.delta_boundary = solid_get_delta_boundary; #endif solid_shader.temperature = solid_get_temperature; - ERR(sdis_data_create(dev, sizeof(struct solid), ALIGNOF(struct solid), + ERR(sdis_data_create(stardis->dev, sizeof(struct solid), ALIGNOF(struct solid), NULL, &data)); - sz = darray_media_ptr_size_get(media_ptr); + sz = darray_media_ptr_size_get(&stardis->media); ASSERT(sz < INT_MAX); solid_props = sdis_data_get(data); /* Fetch the allocated memory space */ - str_init(allocator, &solid_props->name); + str_init(stardis->allocator, &solid_props->name); if(name) str_copy(&solid_props->name, name); + solid_props->t0 = 0; solid_props->lambda = lambda; solid_props->rho = rho; solid_props->cp = cp; @@ -154,9 +153,9 @@ create_solid solid_props->is_outside = is_outside; solid_props->id = (unsigned)sz; if(vpower != 0) solid_shader.volumic_power = solid_get_power; - ERR(darray_media_ptr_resize(media_ptr, sz + 1)); - ERR(sdis_solid_create(dev, &solid_shader, data, - darray_media_ptr_data_get(media_ptr) + sz)); + ERR(darray_media_ptr_resize(&stardis->media, sz + 1)); + ERR(sdis_solid_create(stardis->dev, &solid_shader, data, + darray_media_ptr_data_get(&stardis->media) + sz)); *out_id = solid_props->id; end: diff --git a/src/stardis-solid.h b/src/stardis-solid.h @@ -6,8 +6,7 @@ #include <rsys/rsys.h> #include <rsys/str.h> -struct sdis_device; -struct darray_media_ptr; +struct stardis; /******************************************************************************* * Solid data @@ -29,9 +28,8 @@ struct solid { }; extern res_T -create_solid - (struct sdis_device* dev, - struct mem_allocator* allocator, +create_stardis_solid + (struct stardis* stardis, const struct str* name, const double lambda, const double rho, @@ -42,7 +40,6 @@ create_solid const double tinit, const double imposed_temperature, const double vpower, - struct darray_media_ptr* media_ptr, unsigned* out_id); #endif