stardis

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

commit 03ea5f7ca645f39ec62d7a0dca6032061911777f
parent 8a56fd6a51ea677858b227a09cf2e0fed20712df
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date:   Wed, 17 Feb 2021 16:51:29 +0100

Finished parsing probe interface

Diffstat:
Mdoc/stardis.1.txt.in | 6+++---
Msrc/stardis-compute.c | 152++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
Msrc/stardis-main.c | 2+-
Msrc/stardis-parsing.c | 98++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------------
Msrc/stardis-parsing.h | 3++-
5 files changed, 215 insertions(+), 46 deletions(-)

diff --git a/doc/stardis.1.txt.in b/doc/stardis.1.txt.in @@ -95,11 +95,11 @@ EXCLUSIVE OPTIONS be in a medium. The probe coordinates must be in the same system as the geometry. -*-P* _x,y,z[,time[,time]][,medium_name]_:: +*-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 medium name, as the temperature differs - between the two sides. + 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 starts. The probe coordinates 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,19 +464,147 @@ 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); - /* Find medium */ - medium = find_medium_by_name(stardis, &stardis->solve_name, NULL); - if(medium == NULL) { /* Not found */ - logger_print(stardis->logger, LOG_ERROR, - "Cannot solve on this side '%s' (unknown medium)\n", - str_cget(&stardis->solve_name)); - res = RES_BAD_ARG; - goto error; + 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=%lu)\n", + solve_name, (unsigned long)iprim); + res = RES_BAD_ARG; + goto error; + } + if(fmat_id == bmat_id) { /* Cannot differentiate */ + logger_print(stardis->logger, LOG_ERROR, + "Medium '%s' is used on both sides of this interface (prim id=%lu)\n", + solve_name, (unsigned long)iprim); + logger_print(stardis->logger, LOG_ERROR, + "Side must be defined using either FRONT or BACK.\n"); + 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; 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,12 +756,10 @@ 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': - { - static const char toto[] = "toto"; if(args->mode & EXCLUSIVE_MODES) { res = RES_BAD_ARG; logger_print(args->logger, LOG_ERROR, @@ -758,10 +768,33 @@ parse_args goto error; } args->mode |= MODE_PROBE_COMPUTE_ON_INTERFACE; - GET_POS_AND_OPTIONAL_TIME_RANGE_AND_OPTIONAL_MEDIUM(args->pos_and_time); - args->medium_name = toto; + + 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); if(res != RES_OK @@ -940,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, @@ -979,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])); @@ -1026,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); @@ -1484,10 +1510,16 @@ process_ssc if(res != RES_OK || desc->d.ss_connect.tcr < 0) { - logger_print(stardis->logger, LOG_ERROR, "Invalid contact resistance: %s\n", tk); + 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)); 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