stardis

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

commit 277f8240fbe4849ba98646d5ca56c097554d5698
parent 143456ff49b2448b19af52e4c26c0f2c7f54f47c
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date:   Wed, 10 Mar 2021 16:51:49 +0100

Merge branch 'feature_thermal_contact_resistance' into develop

Diffstat:
Mdoc/stardis-input.5.txt | 9++++++++-
Mdoc/stardis.1.txt.in | 7+++++--
Msrc/stardis-app.c | 13++++++++++---
Msrc/stardis-app.h | 76+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
Msrc/stardis-compute.c | 152+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/stardis-intface.c | 31+++++++++++++++++++++++++++++--
Msrc/stardis-intface.h | 3+++
Msrc/stardis-main.c | 2+-
Msrc/stardis-parsing.c | 167+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------
Msrc/stardis-parsing.h | 3++-
10 files changed, 413 insertions(+), 50 deletions(-)

diff --git a/doc/stardis-input.5.txt b/doc/stardis-input.5.txt @@ -99,6 +99,7 @@ _______ | <f-bound-for-solid> <media-connection> ::= <solid-fluid-connect> + | <solid-solid-connect> <comment> ::= "#" Any text introduced by the # character @@ -132,9 +133,13 @@ _______ <solid-fluid-connect> ::= "SOLID_FLUID_CONNECTION" <bound-name> <emissivity> \ <specular-fraction> <hc> <triangles> +<solid-solid-connect> ::= "SOLID_SOLID_CONNECTION" <bound-name> \ + <contact-resistance> <triangles> + ------------------------------------- -<medium-name> ::= STRING # no space allowed +<medium-name> ::= STRING # no space allowed, must not be parsable as a + # number, including INF and others <lambda> ::= REAL # conductivity in W/(m.K); in ]0, INF) @@ -167,6 +172,8 @@ _______ <hc> ::= REAL # in W/(m2.K); in [0, INF) +<contact-resistance> ::= REAL # in m2.K/W in [0, INF) + <flux> ::= REAL # in W/m2; in (-INF , INF) <triangles> ::= <file-name> [ <triangles> ] diff --git a/doc/stardis.1.txt.in b/doc/stardis.1.txt.in @@ -95,11 +95,14 @@ EXCLUSIVE OPTIONS be in a medium. The probe coordinates must be in the same system as the geometry. -*-P* _x,y,z[,time[,time]]_:: +*-P* _x,y,z[,time[,time]][:side_indicator]_:: Compute the temperature at the given probe on an interface at a given time. + If the probe is on an interface where a thermal contact resistance is + defined, it is mandatory to provide a side indicator (either FRONT, BACK, or + a medium name), as the temperature differs between the two sides. By default the compute time is @STARDIS_ARGS_DEFAULT_COMPUTE_TIME@. The probe is supposed to be on an interface and is moved to the closest point of - the closest interface before the computation start. The probe coordinates + the closest interface before the computation starts. The probe coordinates must be in the same system as the geometry. *-m* _medium_name[,time[,time]]_:: diff --git a/src/stardis-app.c b/src/stardis-app.c @@ -261,6 +261,9 @@ stardis_init else if(args->mode & MODE_MEDIUM_COMPUTE) { ERR(str_set(&stardis->solve_name, args->medium_name)); } + else if(args->mode & MODE_PROBE_COMPUTE_ON_INTERFACE && args->medium_name) { + ERR(str_set(&stardis->solve_name, args->medium_name)); + } else if(args->mode & SURFACE_COMPUTE_MODES) { ERR(str_set(&stardis->solve_name, args->solve_filename)); } @@ -375,9 +378,6 @@ stardis_init struct sdis_scene_create_args scn_args = SDIS_SCENE_CREATE_ARGS_DEFAULT; ASSERT(darray_interface_ptrs_size_get(&stardis->geometry.interf_bytrg) == tcount); - /* Can release enclosures as they are no longer needed if compute */ - SENC3D(scene_ref_put(stardis->senc3d_scn)); - stardis->senc3d_scn = NULL; scn_args.get_indices = sg3d_sdisXd_geometry_get_indices; scn_args.get_interface = sg3d_sdisXd_geometry_get_interface; scn_args.get_position = sg3d_sdisXd_geometry_get_position; @@ -576,6 +576,13 @@ validate_properties goto end; } break; + case DESC_SOLID_SOLID_CONNECT: + if(solid_count != 2) { + /*if(soli_count == 1 && fluid_count == 1)*/ + /**properties_conflict_status = SSCONNECT_BETWEEN_SOLID_AND_FLUID;*/ + goto end; + } + break; default: FATAL("error:" STR(__FILE__) ":" STR(__LINE__)": Invalid type.\n"); } diff --git a/src/stardis-app.h b/src/stardis-app.h @@ -106,6 +106,7 @@ enum description_type { DESC_BOUND_T_FOR_SOLID, DESC_BOUND_F_FOR_SOLID, DESC_SOLID_FLUID_CONNECT, + DESC_SOLID_SOLID_CONNECT, DESCRIPTION_TYPE_COUNT__, DESC_OUTSIDE }; @@ -415,6 +416,58 @@ cp_release_sf_connect return cp_sf_connect(dst, src); } +struct solid_solid_connect { + struct str name; + double tcr; + unsigned connection_id; +}; + +static FINLINE void +release_ss_connect(struct solid_solid_connect* connect) +{ + str_release(&connect->name); +} + +static FINLINE void +init_ss(struct mem_allocator* allocator, struct solid_solid_connect* dst) +{ + str_init(allocator, &dst->name); + dst->tcr = 0; + dst->connection_id = UINT_MAX; +} + +static res_T +str_print_ss_connect + (struct str* str, + const struct solid_solid_connect* c) +{ + res_T res = RES_OK; + ASSERT(str && c); + STR_APPEND_PRINTF(str, "Solid-Solid connection '%s':", ARG1( str_cget(&c->name) ) ); + STR_APPEND_PRINTF(str, " contact resistance=%g", ARG1( c->tcr ) ); +end: + return res; +error: + goto end; +} + +static FINLINE res_T +cp_ss_connect + (struct solid_solid_connect* dst, const struct solid_solid_connect* src) +{ + dst->connection_id = src->connection_id; + dst->tcr = src->tcr; + return str_copy(&dst->name, &src->name); +} + +static FINLINE res_T +cp_release_ss_connect + (struct solid_solid_connect* dst, struct solid_solid_connect* src) +{ + return cp_ss_connect(dst, src); +} + + struct description { enum description_type type; union { @@ -424,6 +477,7 @@ struct description { struct f_boundary f_boundary; struct h_boundary h_boundary; struct solid_fluid_connect sf_connect; + struct solid_solid_connect ss_connect; } d; }; @@ -460,6 +514,9 @@ release_description(struct description* desc) case DESC_SOLID_FLUID_CONNECT: release_sf_connect(&desc->d.sf_connect); break; + case DESC_SOLID_SOLID_CONNECT: + release_ss_connect(&desc->d.ss_connect); + break; default: FATAL("error:" STR(__FILE__) ":" STR(__LINE__)": Invalid type.\n"); } @@ -496,6 +553,9 @@ str_print_description case DESC_SOLID_FLUID_CONNECT: ERR(str_print_sf_connect(str, &desc->d.sf_connect)); break; + case DESC_SOLID_SOLID_CONNECT: + ERR(str_print_ss_connect(str, &desc->d.ss_connect)); + break; default: FATAL("error:" STR(__FILE__) ":" STR(__LINE__)": Invalid type.\n"); } @@ -525,6 +585,8 @@ get_description_name return &desc->d.f_boundary.name; case DESC_SOLID_FLUID_CONNECT: return &desc->d.sf_connect.name; + case DESC_SOLID_SOLID_CONNECT: + return &desc->d.ss_connect.name; default: FATAL("error:" STR(__FILE__) ":" STR(__LINE__)": Invalid type.\n"); } @@ -582,7 +644,14 @@ cp_description } ERR(cp_sf_connect(&dst->d.sf_connect, &src->d.sf_connect)); break; - default: + case DESC_SOLID_SOLID_CONNECT: + if(dst->type == DESCRIPTION_TYPE_COUNT__) { + dst->type = src->type; + init_ss(src->d.ss_connect.name.allocator, &dst->d.ss_connect); + } + ERR(cp_ss_connect(&dst->d.ss_connect, &src->d.ss_connect)); + break; + default: FATAL("error:" STR(__FILE__) ":" STR(__LINE__)": Invalid type.\n"); } end: @@ -616,6 +685,7 @@ description_get_medium_id *id = desc->d.f_boundary.mat_id; return; case DESC_SOLID_FLUID_CONNECT: /* No medium linked to SF */ + case DESC_SOLID_SOLID_CONNECT: /* No medium linked to SS */ default: FATAL("error:" STR(__FILE__) ":" STR(__LINE__)": Invalid type.\n"); } @@ -699,10 +769,10 @@ log_prt_fn(const char* msg, void* ctx) struct counts { unsigned smed_count, fmed_count, tbound_count, hbound_count, - fbound_count, sfconnect_count; + fbound_count, sfconnect_count, ssconnect_count; }; #define COUNTS_NULL__ {\ - 0, 0, 0, 0, 0, 0\ + 0, 0, 0, 0, 0, 0, 0\ } /* Type to store the primitives of a compute region */ diff --git a/src/stardis-compute.c b/src/stardis-compute.c @@ -31,10 +31,18 @@ #include <rsys/image.h> #include <rsys/clock_time.h> +#ifdef COMPILER_GCC +#include <strings.h> /* strcasecmp */ +#else +#include <string.h> +#define strcasecmp(s1, s2) _stricmp((s1), (s2)) +#endif + /******************************************************************************* * Local Functions ******************************************************************************/ + struct filter_ctx { const struct stardis* stardis; unsigned prim; @@ -456,11 +464,155 @@ compute_probe_on_interface(struct stardis* stardis, struct time* start) = SDIS_SOLVE_PROBE_BOUNDARY_ARGS_DEFAULT; FILE* stream = NULL; struct time compute_start, compute_end; + enum sdis_side compute_side; + unsigned prop[3]; + const size_t dcount = darray_descriptions_size_get(&stardis->descriptions); + const struct description* descriptions + = darray_descriptions_cdata_get(&stardis->descriptions); + double tcr = 0; + const char* solve_name; + const char* compute_side_name = NULL; + const char* medium_name = NULL; + const struct description* intface_desc; ASSERT(stardis && start && (stardis->mode & MODE_PROBE_COMPUTE_ON_INTERFACE)); ERR(check_probe_conform_to_type(stardis, 1, stardis->probe, &iprim, uv)); ASSERT(iprim != UINT_MAX); + ERR(sg3d_geometry_get_unique_triangle_properties(stardis->geometry.sg3d, + (unsigned)iprim, prop)); + + ASSERT(prop[SG3D_INTFACE] != SG3D_UNSPECIFIED_PROPERTY + && prop[SG3D_INTFACE] < dcount); + intface_desc = descriptions + prop[SG3D_INTFACE]; + if(intface_desc->type == DESC_SOLID_SOLID_CONNECT) + tcr = intface_desc->d.ss_connect.tcr; + + solve_name = str_is_empty(&stardis->solve_name) + ? NULL : str_cget(&stardis->solve_name); + if(!solve_name) { + compute_side = SDIS_SIDE_NULL__; /* Side is let unspecified */ + } + else if(0 == strcasecmp(solve_name, "FRONT")) { + const struct description* d; + ASSERT(prop[SG3D_FRONT] < dcount); + d = descriptions + prop[SG3D_FRONT]; + ASSERT(d->type == DESC_MAT_SOLID || d->type == DESC_MAT_FLUID); + medium_name = str_cget(get_description_name(d)); + compute_side = SDIS_FRONT; + compute_side_name = "FRONT"; + } + else if(0 == strcasecmp(solve_name, "BACK")) { + const struct description* d; + ASSERT(prop[SG3D_BACK] < dcount); + d = descriptions + prop[SG3D_BACK]; + ASSERT(d->type == DESC_MAT_SOLID || d->type == DESC_MAT_FLUID); + medium_name = str_cget(get_description_name(d)); + compute_side = SDIS_BACK; + compute_side_name = "BACK"; + } else { /* solve_name must be a medium name */ + unsigned med_id, fmat_id, bmat_id; + const struct description* fd; + const struct description* bd; + struct sdis_medium* medium + = find_medium_by_name(stardis, &stardis->solve_name, &med_id); + if(medium == NULL) { /* Not found */ + logger_print(stardis->logger, LOG_ERROR, + "Cannot locate side from medium name '%s' (unknown medium)\n", + solve_name); + res = RES_BAD_ARG; + goto error; + } + + fd = descriptions + prop[SG3D_FRONT]; + bd = descriptions + prop[SG3D_BACK]; + ASSERT(fd->type == DESC_MAT_SOLID || fd->type == DESC_MAT_FLUID); + fmat_id = (fd->type == DESC_MAT_SOLID) + ? fd->d.solid.solid_id : fd->d.fluid.fluid_id; + ASSERT(bd->type == DESC_MAT_SOLID || bd->type == DESC_MAT_FLUID); + bmat_id = (bd->type == DESC_MAT_SOLID) + ? bd->d.solid.solid_id : bd->d.fluid.fluid_id; + + if(med_id != fmat_id && med_id != bmat_id) { /* Not here */ + logger_print(stardis->logger, LOG_ERROR, + "Medium '%s' is not used at this interface (prim id=%u)\n", + solve_name, iprim); + res = RES_BAD_ARG; + goto error; + } + if(fmat_id == bmat_id) { /* Cannot differentiate */ + unsigned encs[2]; + ERR(senc3d_scene_get_triangle_enclosures(stardis->senc3d_scn, iprim, + encs)); + logger_print(stardis->logger, LOG_ERROR, + "Medium '%s' is used on both sides of this interface (prim id=%u)\n", + solve_name,iprim); + logger_print(stardis->logger, LOG_ERROR, + "Side must be defined using either FRONT or BACK.\n"); + logger_print(stardis->logger, LOG_ERROR, + "FRONT side is related to enclosure %u, BACK side to enclosure %u.\n", + encs[SENC3D_FRONT], encs[SENC3D_BACK]); + res = RES_BAD_ARG; + goto error; + } + medium_name = solve_name; + if(med_id == fmat_id) { + compute_side = SDIS_FRONT; + compute_side_name = "FRONT"; + } else { + compute_side = SDIS_BACK; + compute_side_name = "BACK"; + } + } + + if(compute_side == SDIS_SIDE_NULL__) { + /* Cannot have defined a contact resistance here */ + if(tcr != 0) { + const struct description* fdesc = NULL; + const struct description* bdesc = NULL; + if(prop[SG3D_FRONT] != SG3D_UNSPECIFIED_PROPERTY) { + ASSERT(prop[SG3D_FRONT] < dcount); + fdesc = descriptions + prop[SG3D_FRONT]; + } + if(prop[SG3D_BACK] != SG3D_UNSPECIFIED_PROPERTY) { + ASSERT(prop[SG3D_BACK] < dcount); + bdesc = descriptions + prop[SG3D_BACK]; + } + ASSERT(fdesc || bdesc); + logger_print(stardis->logger, LOG_ERROR, + "Cannot let probe computation side unspecified on an interface with a " + "non-nul thermal resistance.\n"); + logger_print(stardis->logger, LOG_ERROR, + "Interface '%s',%s%s%s%s%s%s%s, resistance=%g K.m^2/W.\n", + str_cget(get_description_name(intface_desc)), + (fdesc ? " FRONT:'" : ""), + (fdesc ? str_cget(get_description_name(fdesc)) : ""), + (fdesc ? "'" : ""), + (fdesc && bdesc ? "," : ""), + (bdesc ? " BACK:'" : ""), + (bdesc ? str_cget(get_description_name(bdesc)) : ""), + (bdesc ? "'" : ""), + tcr); + res = RES_BAD_ARG; + goto error; + } + /* Any side is OK as temperature is the same */ + compute_side = SDIS_FRONT; + } else if (tcr == 0) { + /* Warn if side defined and no resistance defined */ + logger_print(stardis->logger, LOG_WARNING, + "Specifying a compute side at an interface with no contact resistance " + "is meaningless.\n"); + } + + if(tcr > 0) { + ASSERT(compute_side_name && medium_name); + logger_print(stardis->logger, LOG_OUTPUT, + "Probe computation on an interface with a thermal resistance = %g K.m^2/W " + "on %s side (medium is '%s').\n", + tcr, compute_side_name, medium_name); + } + args.nrealisations = stardis->samples; args.iprim = iprim; d3_set(args.uv, uv); diff --git a/src/stardis-intface.c b/src/stardis-intface.c @@ -75,6 +75,17 @@ interface_get_alpha return interface_props->alpha; } +static double +interface_get_tcr + (const struct sdis_interface_fragment* frag, + struct sdis_data* data) +{ + const struct intface* interface_props = sdis_data_cget(data); + (void)frag; + return interface_props->tcr; +} + + /******************************************************************************* * Public Functions ******************************************************************************/ @@ -94,7 +105,8 @@ create_intface struct sdis_data* data = NULL; unsigned fd, bd, cd, descr[SG3D_PROP_TYPES_COUNT__]; int fluid_count = 0, solid_count = 0; - int solid_fluid_connection_count = 0, connection_count = 0, boundary_count = 0; + int solid_fluid_connection_count = 0, solid_solid_connection_count = 0; + int connection_count = 0, boundary_count = 0; const struct description* descriptions; struct sdis_medium** media; res_T res = RES_OK; @@ -185,7 +197,8 @@ create_intface struct sdis_medium* def_medium = NULL; unsigned ext_id; if(connect->type != DESC_SOLID_FLUID_CONNECT - && front_defined == back_defined) + && connect->type != DESC_SOLID_SOLID_CONNECT + && front_defined == back_defined) { /* 1 and only 1 defined */ res = RES_BAD_ARG; @@ -335,6 +348,20 @@ create_intface fluid_side_shader->specular_fraction = interface_get_alpha; } break; + case DESC_SOLID_SOLID_CONNECT: + /* Both front and back should be defined */ + if(solid_count != 2 || fluid_count != 0) { + res = RES_BAD_ARG; + goto error; + } + ASSERT(front_defined && back_defined); + connection_count++; + solid_solid_connection_count++; + interface_props->tcr = connect->d.ss_connect.tcr; + if(connect->d.ss_connect.tcr > 0) { + interface_shader.thermal_contact_resistance = interface_get_tcr; + } + break; default: FATAL("error:" STR(__FILE__) ":" STR(__LINE__)": Invalid type.\n"); } diff --git a/src/stardis-intface.h b/src/stardis-intface.h @@ -27,9 +27,12 @@ struct dummies; * Interface data ******************************************************************************/ struct intface { + /* fluid - solid */ double hc; double emissivity; double alpha; + /* solid - solid */ + double tcr; /* Imposed compute temperature & flux */ double imposed_temperature; double imposed_flux; diff --git a/src/stardis-main.c b/src/stardis-main.c @@ -56,7 +56,7 @@ main ERR(init_args(&logger, &allocator, &args)); args_initialized = 1; - ERR(parse_args(argc, argv, args)); + ERR(parse_args(argc, argv, args, &allocator)); mode = args->mode; if(mode & MODE_DUMP_HELP) { diff --git a/src/stardis-parsing.c b/src/stardis-parsing.c @@ -31,17 +31,15 @@ #include <ctype.h> #include <string.h> #ifdef COMPILER_GCC -#include <strings.h> +#include <strings.h> /* strcasecmp */ +#else +#define strcasecmp(s1, s2) _stricmp((s1), (s2)) #endif /******************************************************************************* * Local Functions ******************************************************************************/ -#ifdef COMPILER_CL -#define strcasecmp(s1, s2) _stricmp((s1), (s2)) -#endif - static char** split_line (char* a_str, @@ -506,13 +504,23 @@ short_help fprintf(stream, " Set the verbosity level.\n"); } +#define FREE_AARRAY(ARRAY) \ +if(ARRAY) {\ + int i__ = 0; \ + for(i__=0; *((ARRAY)+i__);i__++){\ + free((ARRAY)[i__]);\ + }\ + free(ARRAY);\ + (ARRAY) = NULL;\ +} + /* Workaround for a gcc warning when GET_OPTIONAL_TIME_RANGE used with Rank=0 */ FINLINE int is_less(size_t a, size_t b) { return a < b; } /* Get a time range from a coma-separated list of doubles * The first Rank values are mandatory, followed by an optional time range * that can be a single time */ -#define GET_OPTIONAL_TIME_RANGE(Src, Rank, Dst, Logger, OptionString, Option) \ +#define GET_OPTIONAL_TIME_RANGE(Src, Rank, Dst, Logger, OptionString, Option, FullSrc) \ res = cstr_to_list_double((Src), ',', (Dst), &len, (Rank)+2); \ if(res != RES_OK \ || is_less(len, (Rank)) \ @@ -523,7 +531,7 @@ FINLINE int is_less(size_t a, size_t b) { return a < b; } if(res == RES_OK) res = RES_BAD_ARG; \ logger_print((Logger), LOG_ERROR, \ "Invalid argument for option "OptionString": %s\n", \ - (Option), (Src)); \ + (Option), (FullSrc)); \ goto error; \ } else { \ if(len == (Rank)+1) (Dst)[(Rank)+1] = (Dst)[(Rank)];\ @@ -533,29 +541,33 @@ FINLINE int is_less(size_t a, size_t b) { return a < b; } #define GET_STR_AND_OPTIONAL_TIME_RANGE(Str, Time) \ ptr = strchr(optarg, ','); /* First ',' */ \ if(ptr) { /* Time range provided */ \ - GET_OPTIONAL_TIME_RANGE(ptr+1, 0, (Time), args->logger, "-%c", opt); \ + GET_OPTIONAL_TIME_RANGE(ptr+1, 0, (Time), args->logger, "-%c", opt, optarg); \ *ptr = '\0'; \ } \ (Str) = optarg; /* Get a position followed by an optional time range */ -#define GET_POS_AND_OPTIONAL_TIME_RANGE(Dst) \ - GET_OPTIONAL_TIME_RANGE(optarg, 3, (Dst), args->logger, "-%c", opt); +#define GET_POS_AND_OPTIONAL_TIME_RANGE(Src, Dst, FullSrc) \ + GET_OPTIONAL_TIME_RANGE((Src), 3, (Dst), args->logger, "-%c", opt, (FullSrc)); res_T parse_args (const int argc, char** argv, - struct args* args) + struct args* args, + struct mem_allocator* allocator) { int opt = 0, n_used = 0; size_t len = 0; const char option_list[] = "a:c:dD:eF:gG:hm:M:n:p:P:r:R:s:S:t:vV:"; char buf[128]; + struct str keep; + char** line = NULL; res_T res = RES_OK; ASSERT(argv && args); + str_init(allocator, &keep); opterr = 0; /* No default error messages */ while((opt = getopt(argc, argv, option_list)) != -1) { switch (opt) { @@ -744,20 +756,44 @@ parse_args goto error; } args->mode |= MODE_PROBE_COMPUTE; - GET_POS_AND_OPTIONAL_TIME_RANGE(args->pos_and_time); + GET_POS_AND_OPTIONAL_TIME_RANGE(optarg, args->pos_and_time, optarg); break; case 'P': - if(args->mode & EXCLUSIVE_MODES) { - res = RES_BAD_ARG; - logger_print(args->logger, LOG_ERROR, - "Options -%c and -%c are exclusive.\n", - (char)opt, mode_option(args->mode)); - goto error; - } - args->mode |= MODE_PROBE_COMPUTE_ON_INTERFACE; - GET_POS_AND_OPTIONAL_TIME_RANGE(args->pos_and_time); - break; + if(args->mode & EXCLUSIVE_MODES) { + res = RES_BAD_ARG; + logger_print(args->logger, LOG_ERROR, + "Options -%c and -%c are exclusive.\n", + (char)opt, mode_option(args->mode)); + goto error; + } + args->mode |= MODE_PROBE_COMPUTE_ON_INTERFACE; + + ERR(str_set(&keep, optarg)); + line = split_line(optarg, ':'); + if(!line) { + res = RES_MEM_ERR; + str_release(&keep); + goto error; + } + + /* We expect 1 or 2 parts in line */ + if(!line[0] || (line[1] && line[2])) { + logger_print((args->logger), LOG_ERROR, + "Invalid argument for option ""-%c"": %s\n", + opt, str_cget(&keep)); + str_release(&keep); + res = RES_BAD_ARG; + goto error; + } + + /* First part is pos and optional time, optional second part is a + * medium name (OK if NULL) */ + GET_POS_AND_OPTIONAL_TIME_RANGE(line[0], args->pos_and_time, + str_cget(&keep)); + args->medium_name = optarg + strlen(line[0]) + 1; + + break; case 'r': res = cstr_to_double(optarg, &args->ref_temp); @@ -937,12 +973,15 @@ parse_args } end: + FREE_AARRAY(line); + str_release(&keep); return res; error: logger_print(args->logger, LOG_ERROR, "Use option -h to print help.\n"); goto end; } + res_T parse_camera (struct logger* logger, @@ -976,7 +1015,8 @@ parse_camera goto error; } if(strcasecmp(opt[0], "T") == 0) { - GET_OPTIONAL_TIME_RANGE(opt[1], 0, cam->time_range, logger, "%s", opt[0]); + GET_OPTIONAL_TIME_RANGE(opt[1], 0, cam->time_range, logger, "%s", opt[0], + str_cget(&keep)); } else if(strcasecmp(opt[0], "FILE") == 0) { ERR(str_set(&cam->file_name, opt[1])); @@ -1023,23 +1063,12 @@ parse_camera res = RES_BAD_ARG; goto error; } - -#define FREE_AARRAY(ARRAY) \ -if(ARRAY) {\ - int i__ = 0; \ - for(i__=0; *((ARRAY)+i__);i__++){\ - free((ARRAY)[i__]);\ - }\ - free(ARRAY);\ - (ARRAY) = NULL;\ -} - - FREE_AARRAY(opt) + FREE_AARRAY(opt); } end: - FREE_AARRAY(line) - FREE_AARRAY(opt) + FREE_AARRAY(line); + FREE_AARRAY(opt); #undef FREE_AARRAY str_release(&keep); @@ -1439,6 +1468,68 @@ error: goto end; } +/* SOLID_SOLID_CONNECTION Name contact-resitance STL_filenames */ +static res_T +process_ssc + (struct stardis* stardis, + char** tok_ctx) +{ + char* tk = NULL; + struct description* desc; + size_t sz; + res_T res = RES_OK; + + ASSERT(stardis && tok_ctx); + + stardis->counts.ssconnect_count++; + + sz = darray_descriptions_size_get(&stardis->descriptions); + ERR(darray_descriptions_resize(&stardis->descriptions, sz + 1)); + desc = darray_descriptions_data_get(&stardis->descriptions) + sz; + init_ss(stardis->allocator, &desc->d.ss_connect); + + /* Use a medium ID even if there is no medium here + * As other cases use media IDs as unique IDs for read_sides_and_files calls + * we continue the trend to ensure connection ID is OK */ + desc->type = DESC_SOLID_SOLID_CONNECT; + desc->d.ss_connect.connection_id = allocate_stardis_medium_id(stardis); + + CHK_TOK(strtok_r(NULL, " \t", tok_ctx), "solid solid connection name"); + ERR(description_set_name(stardis, &desc->d.ss_connect.name, tk)); + if(find_description_by_name(stardis, &desc->d.ss_connect.name, NULL) + != desc) + { + logger_print(stardis->logger, LOG_ERROR, + "Name already used: %s\n", tk); + if(res == RES_OK) res = RES_BAD_ARG; + goto end; + } + + CHK_TOK(strtok_r(NULL, " \t", tok_ctx), "contact resistance"); + res = cstr_to_double(tk, &desc->d.ss_connect.tcr); + if(res != RES_OK + || desc->d.ss_connect.tcr < 0) + { + logger_print(stardis->logger, LOG_ERROR, + "Invalid contact resistance: %s\n", tk); + if(res == RES_OK) res = RES_BAD_ARG; + goto end; + } + else if(desc->d.ss_connect.tcr == 0) { + logger_print(stardis->logger, LOG_WARNING, + "Solid-solid connection %s: defining a contact resistance to 0 has " + "no effect\n", str_cget(&desc->d.ss_connect.name)); + } + + ASSERT(sz <= UINT_MAX); + ERR(read_sides_and_files(stardis, 1, (unsigned)sz, tok_ctx)); + +end: + return res; +error: + goto end; +} + static res_T read_imposed_temperature (struct stardis* stardis, @@ -1787,6 +1878,8 @@ process_model_line ERR(process_flx(stardis, dummies, &tok_ctx)); else if(0 == strcasecmp(tk, "SOLID_FLUID_CONNECTION")) ERR(process_sfc(stardis, &tok_ctx)); + else if(0 == strcasecmp(tk, "SOLID_SOLID_CONNECTION")) + ERR(process_ssc(stardis, &tok_ctx)); else if(0 == strcasecmp(tk, "SOLID")) ERR(process_solid(stardis, &tok_ctx)); else if(0 == strcasecmp(tk, "FLUID")) diff --git a/src/stardis-parsing.h b/src/stardis-parsing.h @@ -175,7 +175,8 @@ extern res_T parse_args (const int argc, char** argv, - struct args* args); + struct args* args, + struct mem_allocator* allocator); extern res_T parse_camera