stardis

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

commit 76363a31b24196e7a5030073d48b3a865ee9a289
parent 236d08acb439485acf02812a6cbaf56820f7245a
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date:   Thu, 24 Sep 2020 16:11:28 +0200

Merge branch 'develop' into feature_unsteady_green

Diffstat:
Mcmake/CMakeLists.txt | 4++--
Mdoc/stardis.1.txt.in | 79+++++++++++++++++++++++++++++++++++++++++++++++--------------------------------
Msrc/stardis-app.c | 102+++++++++++++++++++++++++++++++++++++++++--------------------------------------
Msrc/stardis-app.h | 8+++++---
Msrc/stardis-compute.c | 6+++---
Msrc/stardis-output.c | 112++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------------------
Msrc/stardis-parsing.c | 186++++++++++++++++++++++++++++++++++++++++++-------------------------------------
Msrc/stardis-parsing.h | 7++++---
8 files changed, 294 insertions(+), 210 deletions(-)

diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt @@ -36,14 +36,14 @@ set_property(CACHE STARDIS_DOC PROPERTY STRINGS # Generate files ############################################################################### set(STARDIS_ARGS_DEFAULT_AMBIENT_TEMP "300") -set(STARDIS_ARGS_DEFAULT_COMPUTE_TIME "INF") +set(STARDIS_ARGS_DEFAULT_COMPUTE_TIME "INF, INF") set(STARDIS_ARGS_DEFAULT_RENDERING_FOV "70") # degrees set(STARDIS_ARGS_DEFAULT_RENDERING_IMG_HEIGHT "480") set(STARDIS_ARGS_DEFAULT_RENDERING_IMG_WIDTH "640") set(STARDIS_ARGS_DEFAULT_RENDERING_POS "1, 1, 1") set(STARDIS_ARGS_DEFAULT_RENDERING_SPP "4") set(STARDIS_ARGS_DEFAULT_RENDERING_TGT "0, 0, 0") -set(STARDIS_ARGS_DEFAULT_RENDERING_TIME "INF") +set(STARDIS_ARGS_DEFAULT_RENDERING_TIME "INF, INF") set(STARDIS_ARGS_DEFAULT_RENDERING_UP "0, 0, 1") set(STARDIS_ARGS_DEFAULT_REFERENCE_TEMP "300") set(STARDIS_ARGS_DEFAULT_SAMPLES_COUNT "10000") diff --git a/doc/stardis.1.txt.in b/doc/stardis.1.txt.in @@ -39,9 +39,11 @@ relative to the characteristic time of the system. The provided system description should comply with the *stardis-input*(5) format. *stardis* can compute a thermal observable, like temperature or flux, at a -probe point and date or the mean value of an observable over a given surface -or volume, and time period. In addition, *stardis* gives access to the -evaluation of the propagator (a.k.a the *Green function*). +probe point and date or the mean value of an observable over a given surface, +volume, or time range. When a time range *t1, t2* is provided, the computed +value is the mean value over the time range. To compute the value at a given +time, simply provide a single value *t*. In addition, *stardis* gives access to +the evaluation of the propagator (a.k.a the *Green function*). The propagator is of great value for thermicist engineers as it gives some crucial information to analyse heat transfers in the system. It helps engineers @@ -89,43 +91,45 @@ MANDATORY OPTIONS EXCLUSIVE OPTIONS ----------------- -*-p* _x,y,z[,time]_:: - Compute the temperature at the given probe at a given time. By default - compute time is @STARDIS_ARGS_DEFAULT_COMPUTE_TIME@. The probe must be in a - medium. The probe coordinates must be in the same system as the geometry. +*-p* _x,y,z[,time-range]_:: + Compute the temperature at the given probe at a given time. By default the + compute time range is @STARDIS_ARGS_DEFAULT_COMPUTE_TIME@. The probe must + be in a medium. The probe coordinates must be in the same system as the + geometry. -*-P* _x,y,z[,time]_:: +*-P* _x,y,z[,time-range]_:: Compute the temperature at the given probe on an interface at a given time. - By default 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 must - be in the same system as the geometry. + By default the compute time range 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 + must be in the same system as the geometry. -*-m* _medium_name[,time]_:: +*-m* _medium_name[,time-range]_:: Compute the mean temperature in a given medium at a given time. The medium - name must be part of the system description. By default compute time is - @STARDIS_ARGS_DEFAULT_COMPUTE_TIME@. The medium does not need to be connex. - -*-s* _file[,time]_:: - Compute the mean temperature on a given 2D region at a given time, the - region being defined as the front sides of the triangles in the provided - *STL* file. By default compute time is @STARDIS_ARGS_DEFAULT_COMPUTE_TIME@. + name must be part of the system description. By default the compute time + range is @STARDIS_ARGS_DEFAULT_COMPUTE_TIME@. The medium does not need to be + connex. + +*-s* _file[,time-range]_:: + Compute the mean temperature on a given 2D region at a given time, the region + being defined as the front sides of the triangles in the provided *STL* file. + By default the compute time range is @STARDIS_ARGS_DEFAULT_COMPUTE_TIME@. These triangles are not added to the geometry, but must be part of it. The region does not need to be connex. -*-S* _file[,time]_:: +*-S* _file[,time-range]_:: Compute the by-triangle mean temperature on a given 2D region at a given time, the region being defined as the front sides of the triangles in the provided *VTK* file. These triangles are not added to the geometry, but must - be part of it. By default compute time is + be part of it. By default the compute time range is @STARDIS_ARGS_DEFAULT_COMPUTE_TIME@. The region does not need to be connex. -*-F* _file[,time]_:: +*-F* _file[,time-range]_:: Compute the mean flux on a given 2D region at a given time, the region being defined as the front sides of the triangles in the provided *VTK* file. These triangles are not added to the geometry, but must be part of it. Flux is accounted positive when going from the front side to the back side, at a - single-triangle level. By default compute time is + single-triangle level. By default the compute time range is @STARDIS_ARGS_DEFAULT_COMPUTE_TIME@.The region does not need to be connex. *-R* [__sub-option__:...]:: @@ -153,8 +157,9 @@ EXCLUSIVE OPTIONS Number of samples per pixel. By default, use @STARDIS_ARGS_DEFAULT_RENDERING_SPP@ samples per pixel. - **t=**_time_;; - Rendering time. By default _time_ is @STARDIS_ARGS_DEFAULT_RENDERING_TIME@. + **t=**_time-range_;; + Rendering time range. By default _time-range_ is + @STARDIS_ARGS_DEFAULT_RENDERING_TIME@. **tgt=**_x_**,**_y_**,**_z_;; Position targeted by the camera. By default, it is set to @@ -249,16 +254,26 @@ in the file *scene.vtk*. Verbosity level is set to *3*: $ stardis -M "scene 5.txt" -F edge.stl -d -V 3 > scene.vtk Compute the temperature at the probe point *0, 0.5, 0* at steady state. The -system is read from the 2 files *media.txt* and *bounds.txt* and the number of -samples is set to *1000000*: +system is read from the file *model.txt* and the number of samples is set to +*1000000*: - $ stardis -M media.txt -M bounds.txt -p 0,0.5,0 -n 1000000 + $ stardis -M model.txt -p 0,0.5,0 -n 1000000 Compute the mean temperature in the medium *med05* at *t=100* s. The system is -read from the 2 files *media.txt* and *bounds.txt* and the result is output -with extended format: +read from the file *model.txt* and the result is output with extended format: + + $ stardis -M model.txt -m med05,100 -e + +Compute the temperature at the probe point *0, 0, 0* at *t=2500*. The system is +read from the 2 files *media.txt* and *bounds.txt* and the number of samples is +set to *1000000*: + + $ stardis -M media.txt -M bounds.txt -p 0,0,0,2500 -n 1000000 + +Compute the mean temperature at the probe point *1, 2.5, 0* over the *50, 5000* +time range. The system is read from the file *model.txt*: - $ stardis -M media.txt -M bounds.txt -m med05,100 -e + $ stardis -M model.txt -p 1,2.5,0,50,5000 Render the system as described in *scene.txt* with default settings: diff --git a/src/stardis-app.c b/src/stardis-app.c @@ -27,6 +27,8 @@ #include <rsys/str.h> #include <rsys/text_reader.h> #include <rsys/logger.h> +#include <rsys/double2.h> +#include <rsys/double3.h> #include <string.h> @@ -121,55 +123,59 @@ check_delta_and_create_solid /* The enclosures where created using description ids */ ERR(senc3d_scene_get_enclosure_count_by_medium(stardis->senc3d_scn, desc_id, &ecount)); - CHK(ecount != 0); /* This solid cannot be unused */ - /* Can be unused if conflicts; in this case, avoid delta warnings */ - int external = 0; - FOR_EACH(e, 0, ecount) { - ERR(senc3d_scene_get_enclosure_by_medium(stardis->senc3d_scn, desc_id, - e, &enc)); - ERR(senc3d_enclosure_get_header(enc, &header)); - if(header.is_infinite) { - /* External solid, volume is negative and no delta walk expected */ - external = 1; - } else { - double d = header.volume / (header.area * 6); - ASSERT(d >= 0); - delta_range[0] = MMIN(delta_range[0], d); - delta_range[1] = MMAX(delta_range[1], d); + if(ecount == 0) { + unsigned ccount; + ERR(sg3d_geometry_get_unique_triangles_with_properties_conflict_count( + stardis->geometry.sg3d, &ccount)); + CHK(ccount == 0); /* This solid can only be unused if in conflict*/ + } else { + int external = 0; + FOR_EACH(e, 0, ecount) { + ERR(senc3d_scene_get_enclosure_by_medium(stardis->senc3d_scn, desc_id, + e, &enc)); + ERR(senc3d_enclosure_get_header(enc, &header)); + if(header.is_infinite) { + /* External solid, volume is negative and no delta walk expected */ + external = 1; + } else { + double d = header.volume / (header.area * 6); + ASSERT(d >= 0); + delta_range[0] = MMIN(delta_range[0], d); + delta_range[1] = MMAX(delta_range[1], d); + } + ERR(senc3d_enclosure_ref_put(enc)); + enc = NULL; } - ERR(senc3d_enclosure_ref_put(enc)); - enc = NULL; - } - if(ecount > 1 || !external) { - ASSERT(0 < delta_range[0] && delta_range[0] <= delta_range[1]); - ratio = delta_range[1] / delta_range[0]; - if(ratio > acceptance_ratio) - logger_print(stardis->logger, LOG_WARNING, - "Solid %s is used in %u different enclosures that have different " - "delta requirements.\n", - str_cget(&description->d.solid.name), ecount); - /* Delta needs to be substituted with actual value */ - if(description->d.solid.delta == DELTA_AUTO) { - description->d.solid.delta = delta_range[0]; - logger_print(stardis->logger, LOG_OUTPUT, - "Auto delta for solid %s set to %g\n", - str_cget(&description->d.solid.name), description->d.solid.delta); - } else { - int too_small - = (delta_range[0] > description->d.solid.delta * acceptance_ratio); - int too_big - = (delta_range[0] * acceptance_ratio < description->d.solid.delta); - /* Check if user delta is OK */ - if(too_small || too_big) { + if(ecount > 1 || !external) { + ASSERT(0 < delta_range[0] && delta_range[0] <= delta_range[1]); + ratio = delta_range[1] / delta_range[0]; + if(ratio > acceptance_ratio) logger_print(stardis->logger, LOG_WARNING, - "User delta for solid %s seems too %s: %g; " - "auto delta would have set it to %g.\n", - str_cget(&description->d.solid.name), (too_big ? "big" : "small"), - description->d.solid.delta, delta_range[0]); + "Solid %s is used in %u different enclosures that have different " + "delta requirements.\n", + str_cget(&description->d.solid.name), ecount); + /* Delta needs to be substituted with actual value */ + if(description->d.solid.delta == DELTA_AUTO) { + description->d.solid.delta = delta_range[0]; + logger_print(stardis->logger, LOG_OUTPUT, + "Auto delta for solid %s set to %g\n", + str_cget(&description->d.solid.name), description->d.solid.delta); + } else { + int too_small + = (delta_range[0] > description->d.solid.delta * acceptance_ratio); + int too_big + = (delta_range[0] * acceptance_ratio < description->d.solid.delta); + /* Check if user delta is OK */ + if(too_small || too_big) { + logger_print(stardis->logger, LOG_WARNING, + "User delta for solid %s seems too %s: %g; " + "auto delta would have set it to %g.\n", + str_cget(&description->d.solid.name), (too_big ? "big" : "small"), + description->d.solid.delta, delta_range[0]); + } } } } - } ERR(create_solver_solid(stardis, &description->d.solid)); @@ -207,10 +213,8 @@ stardis_init 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]; + d3_set(stardis->probe, args->pos_and_time); + d2_set(stardis->time_range, args->pos_and_time + 3); stardis->dev = NULL; stardis->sdis_scn = NULL; stardis->senc3d_scn = NULL; @@ -250,7 +254,7 @@ stardis_init &stardis->geometry)); if(args->mode & MODE_IR_COMPUTE) { - ERR(parse_camera(stardis->logger, args->camera, &stardis->camera)); + ERR(parse_camera(stardis->logger, args->camera, stardis)); } else if(args->mode & MODE_MEDIUM_COMPUTE) { ERR(str_set(&stardis->solve_name, args->medium_name)); diff --git a/src/stardis-app.h b/src/stardis-app.h @@ -26,6 +26,7 @@ #include <rsys/rsys.h> #include <rsys/float3.h> +#include <rsys/double2.h> #include <rsys/double3.h> #include <rsys/dynamic_array_size_t.h> #include <rsys/dynamic_array.h> @@ -615,7 +616,7 @@ struct camera { double tgt[3]; double up[3]; double fov; - double time; + double time_range[2]; unsigned spp; unsigned img_width, img_height; int auto_look_at; @@ -630,7 +631,7 @@ init_camera(struct camera* cam) { cam->spp = STARDIS_DEFAULT_RENDERING_SPP; cam->img_width = STARDIS_DEFAULT_RENDERING_IMG_WIDTH; cam->img_height = STARDIS_DEFAULT_RENDERING_IMG_HEIGHT; - cam->time = STARDIS_DEFAULT_RENDERING_TIME; + d2(cam->time_range, STARDIS_DEFAULT_RENDERING_TIME); cam->auto_look_at = 1; } @@ -704,7 +705,8 @@ struct stardis { struct senc3d_scene* senc3d_scn; struct counts counts; - double probe[4]; /* x,y,z,t of probe when mode is PROBE_COMPUTE */ + double probe[3]; /* x,y,z of probe when mode is PROBE_COMPUTE */ + double time_range[2]; /* compute time */ 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 diff --git a/src/stardis-compute.c b/src/stardis-compute.c @@ -598,7 +598,7 @@ compute_camera(struct stardis* stardis) stardis->camera.up)); args.cam = cam; - d2_splat(args.time_range, stardis->camera.time); + d2_set(args.time_range, stardis->camera.time_range); args.fp_to_meter = stardis->scale_factor; args.ambient_radiative_temperature = stardis->ambient_temp; args.reference_temperature = stardis->ref_temp; @@ -819,7 +819,7 @@ compute_flux_boundary(struct stardis* stardis) = darray_size_t_cdata_get(&stardis->compute_surface.primitives); args.nprimitives = darray_size_t_size_get(&stardis->compute_surface.primitives); - d2_splat(args.time_range, stardis->probe[3]); + d2_set(args.time_range, stardis->time_range); args.fp_to_meter = stardis->scale_factor; args.ambient_radiative_temperature = stardis->ambient_temp; args.reference_temperature = stardis->ref_temp; @@ -869,7 +869,7 @@ compute_map(struct stardis* stardis) args.sides = darray_sides_cdata_get(&stardis->compute_surface.sides); args.nprimitives = darray_size_t_size_get(&stardis->compute_surface.primitives); - d2_splat(args.time_range, stardis->probe[3]); + d2_set(args.time_range, stardis->time_range); args.fp_to_meter = stardis->scale_factor; args.ambient_radiative_temperature = stardis->ambient_temp; args.reference_temperature = stardis->ref_temp; diff --git a/src/stardis-output.c b/src/stardis-output.c @@ -1170,40 +1170,64 @@ print_single_MC_result switch (stardis->mode & COMPUTE_MODES) { case MODE_PROBE_COMPUTE: if(stardis->mode & MODE_EXTENDED_RESULTS) { - fprintf(stream, "Temperature at [%g, %g, %g] at t=%g = %g +/- %g\n", - SPLIT4(stardis->probe), - result.E, /* Expected value */ - result.SE); /* Standard error */ + if(stardis->time_range[0] == stardis->time_range[1]) + fprintf(stream, "Temperature at [%g, %g, %g] at t=%g = %g +/- %g\n", + SPLIT3(stardis->probe), stardis->time_range[0], + result.E, /* Expected value */ + result.SE); /* Standard error */ + else + fprintf(stream, "Temperature at [%g, %g, %g] with t in [%g %g] = %g +/- %g\n", + SPLIT3(stardis->probe), SPLIT2(stardis->time_range), + result.E, /* Expected value */ + result.SE); /* Standard error */ } else fprintf(stream, "%g %g %zu %zu\n", result.E, result.SE, nfailures, stardis->samples); break; case MODE_PROBE_COMPUTE_ON_INTERFACE: if(stardis->mode & MODE_EXTENDED_RESULTS) { - fprintf(stream, "Boundary temperature at [%g, %g, %g] at t=%g = %g +/- %g\n", - SPLIT4(stardis->probe), - result.E, /* Expected value */ - result.SE); /* Standard error */ + if(stardis->time_range[0] == stardis->time_range[1]) + fprintf(stream, "Boundary temperature at [%g, %g, %g] at t=%g = %g +/- %g\n", + SPLIT3(stardis->probe), stardis->time_range[0], + result.E, /* Expected value */ + result.SE); /* Standard error */ + else + fprintf(stream, "Boundary temperature at [%g, %g, %g] with t in [%g %g] = %g +/- %g\n", + SPLIT3(stardis->probe), SPLIT2(stardis->time_range), + result.E, /* Expected value */ + result.SE); /* Standard error */ } else fprintf(stream, "%g %g %zu %zu\n", result.E, result.SE, nfailures, stardis->samples); break; case MODE_MEDIUM_COMPUTE: if(stardis->mode & MODE_EXTENDED_RESULTS) { - 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 */ + if(stardis->time_range[0] == stardis->time_range[1]) + fprintf(stream, "Temperature in medium '%s' at t=%g = %g +/- %g\n", + str_cget(&stardis->solve_name), stardis->time_range[0], + result.E, /* Expected value */ + result.SE); /* Standard error */ + else + fprintf(stream, "Temperature in medium '%s' with t in [%g %g] = %g +/- %g\n", + str_cget(&stardis->solve_name), SPLIT2(stardis->time_range), + result.E, /* Expected value */ + result.SE); /* Standard error */ } else fprintf(stream, "%g %g %zu %zu\n", result.E, result.SE, nfailures, stardis->samples); break; case MODE_BOUNDARY_COMPUTE: if(stardis->mode & MODE_EXTENDED_RESULTS) { - 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 */ + if(stardis->time_range[0] == stardis->time_range[1]) + fprintf(stream, "Temperature at boundary %s at t=%g = %g +/- %g\n", + str_cget(&stardis->solve_name), stardis->time_range[0], + result.E, /* Expected value */ + result.SE); /* Standard error */ + else + fprintf(stream, "Temperature at boundary %s with t in [%g %g] = %g +/- %g\n", + str_cget(&stardis->solve_name), SPLIT2(stardis->time_range), + result.E, /* Expected value */ + result.SE); /* Standard error */ } else fprintf(stream, "%g %g %zu %zu\n", result.E, result.SE, nfailures, stardis->samples); @@ -1214,25 +1238,49 @@ print_single_MC_result ASSERT(type == SDIS_ESTIMATOR_FLUX); if(stardis->mode & MODE_EXTENDED_RESULTS) { - 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 */ + if(stardis->time_range[0] == stardis->time_range[1]) + fprintf(stream, "Temperature at boundary %s at t=%g = %g +/- %g\n", + str_cget(&stardis->solve_name), stardis->time_range[0], + result.E, /* Expected value */ + result.SE); /* Standard error */ + else + fprintf(stream, "Temperature at boundary %s with t in [%g %g] = %g +/- %g\n", + str_cget(&stardis->solve_name), SPLIT2(stardis->time_range), + result.E, /* Expected value */ + result.SE); /* Standard error */ ERR(sdis_estimator_get_convective_flux(estimator, &result)); - 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 */ + if(stardis->time_range[0] == stardis->time_range[1]) + fprintf(stream, "Convective flux at boundary %s at t=%g = %g +/- %g\n", + str_cget(&stardis->solve_name), stardis->time_range[0], + result.E, /* Expected value */ + result.SE); /* Standard error */ + else + fprintf(stream, "Convective flux at boundary %s with t in [%g %g] = %g +/- %g\n", + str_cget(&stardis->solve_name), SPLIT2(stardis->time_range), + result.E, /* Expected value */ + result.SE); /* Standard error */ ERR(sdis_estimator_get_radiative_flux(estimator, &result)); - 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 */ + if(stardis->time_range[0] == stardis->time_range[1]) + fprintf(stream, "Radiative flux at boundary %s at t=%g = %g +/- %g\n", + str_cget(&stardis->solve_name), stardis->time_range[0], + result.E, /* Expected value */ + result.SE); /* Standard error */ + else + fprintf(stream, "Radiative flux at boundary %s with t in [%g %g] = %g +/- %g\n", + str_cget(&stardis->solve_name), SPLIT2(stardis->time_range), + result.E, /* Expected value */ + result.SE); /* Standard error */ ERR(sdis_estimator_get_total_flux(estimator, &result)); - 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 */ + if(stardis->time_range[0] == stardis->time_range[1]) + fprintf(stream, "Total flux Flux at boundary %s at t=%g = %g +/- %g\n", + str_cget(&stardis->solve_name), stardis->time_range[0], + result.E, /* Expected value */ + result.SE); /* Standard error */ + else + fprintf(stream, "Total flux Flux at boundary %s with t in [%g %g] = %g +/- %g\n", + str_cget(&stardis->solve_name), SPLIT2(stardis->time_range), + result.E, /* Expected value */ + result.SE); /* Standard error */ } else { fprintf(stream, "%g %g ", result.E, result.SE); ERR(sdis_estimator_get_convective_flux(estimator, &result)); diff --git a/src/stardis-parsing.c b/src/stardis-parsing.c @@ -20,6 +20,7 @@ #include "stardis-version.h" #include <rsys/cstr.h> +#include <rsys/double2.h> #include <rsys/double3.h> #include <sdis_version.h> #include <rsys/logger.h> @@ -343,7 +344,7 @@ init_args /* Set default values */ args->samples = STARDIS_DEFAULT_SAMPLES_COUNT; args->nthreads = SDIS_NTHREADS_DEFAULT; - args->probe[3] = STARDIS_DEFAULT_COMPUTE_TIME; + d2(args->pos_and_time+3, STARDIS_DEFAULT_COMPUTE_TIME); args->ambient_temp = STARDIS_DEFAULT_AMBIENT_TEMP; args->ref_temp = STARDIS_DEFAULT_REFERENCE_TEMP; args->verbose = STARDIS_DEFAULT_VERBOSE_LEVEL; @@ -438,37 +439,37 @@ short_help name); print_version(stream); - fprintf(stream, "\nMandatory arguments\n"); + fprintf(stream, "\nMandatory options\n"); fprintf(stream, "-------------------\n"); fprintf(stream, "\n -M <FILE>\n"); fprintf(stream, " Read a text file that contains (partial) description of the model.\n"); - fprintf(stream, "\nExclusive arguments\n"); + fprintf(stream, "\nExclusive options\n"); fprintf(stream, "-------------------\n"); - fprintf(stream, "\n -F STL_FILE[,TIME]\n"); + fprintf(stream, "\n -F STL_FILE[,TIME-RANGE]\n"); fprintf(stream, " Compute the mean flux on a given 2D region at a given time.\n"); - fprintf(stream, "\n -m MEDIUM_NAME[,TIME]\n"); + fprintf(stream, "\n -m MEDIUM_NAME[,TIME-RANGE]\n"); fprintf(stream, " Compute the mean temperature in a given medium at a given time.\n"); - fprintf(stream, "\n -p X,Y,Z[,TIME]\n"); + fprintf(stream, "\n -p X,Y,Z[,TIME-RANGE]\n"); fprintf(stream, " Compute the temperature at the given probe.\n"); - fprintf(stream, "\n -P X,Y,Z[,TIME]\n"); + fprintf(stream, "\n -P X,Y,Z[,TIME-RANGE]\n"); fprintf(stream, " Compute the temperature at the given probe on an interface.\n"); fprintf(stream, "\n -R [RENDERING_OPTIONS]\n"); fprintf(stream, " Compute an infra-red image of the model.\n"); - fprintf(stream, "\n -s STL_FILE[,TIME]\n"); + fprintf(stream, "\n -s STL_FILE[,TIME-RANGE]\n"); fprintf(stream, " Compute the mean temperature on a given 2D region.\n"); - fprintf(stream, "\n -S STL_FILE[,TIME]\n"); + fprintf(stream, "\n -S STL_FILE[,TIME-RANGE]\n"); fprintf(stream, " Compute the by-triangle mean temperature on a given 2D region.\n"); - fprintf(stream, "\nOptionnal arguments\n"); + fprintf(stream, "\nOther options\n"); fprintf(stream, "-------------------\n"); fprintf(stream, "\n -a AMBIENT_TEMP\n"); @@ -511,6 +512,39 @@ short_help fprintf(stream, " Set the verbosity level.\n"); } +/* 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) \ + res = cstr_to_list_double((Src), ',', (Dst), &len, (Rank)+2); \ + if(res != RES_OK \ + || (len < (Rank)) \ + || (len == (Rank)+1 && (Dst)[(Rank)] < 0) \ + || (len == (Rank)+2 && ((Dst)[0] < 0 || (Dst)[(Rank)] > (Dst)[(Rank)+1])) \ + || len > (Rank)+2) \ + { \ + if(res == RES_OK) res = RES_BAD_ARG; \ + logger_print((Logger), LOG_ERROR, \ + "Invalid argument for option "OptionString": %s\n", \ + (Option), (Src)); \ + goto error; \ + } else { \ + if(len == (Rank)+1) (Dst)[(Rank)+1] = (Dst)[(Rank)];\ + } + + /* Get a string followed by an optional time range */ +#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); \ + *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); + res_T parse_args (const int argc, @@ -581,10 +615,6 @@ parse_args args->mode |= MODE_DUMP_VTK; break; - case 'e': - args->mode |= MODE_EXTENDED_RESULTS; - break; - case 'D': { char* ptr = strrchr(optarg, ','); if(!ptr || ptr != strchr(optarg, ',')) @@ -615,13 +645,36 @@ parse_args break; } + case 'e': + args->mode |= MODE_EXTENDED_RESULTS; + break; + /*case 'F': see 's' */ case 'g': + if(args->mode & MODE_BIN_GREEN) { + res = RES_BAD_ARG; + logger_print(args->logger, LOG_ERROR, + "Options -%c and -%c are exclusive.\n", + (char)opt, mode_option(MODE_BIN_GREEN)); + goto error; + } args->mode |= MODE_GREEN; break; case 'G': + if(args->mode & (MODE_BIN_GREEN | MODE_GREEN)) { + res = RES_BAD_ARG; + if(args->mode & MODE_BIN_GREEN) + logger_print(args->logger, LOG_ERROR, + "Option -%c cannot be used twice.\n", + (char)opt); + else + logger_print(args->logger, LOG_ERROR, + "Options -%c and -%c are exclusive.\n", + (char)opt, mode_option(MODE_GREEN)); + goto error; + } args->mode |= MODE_BIN_GREEN; args->bin_green_filename = optarg; break; @@ -643,28 +696,12 @@ parse_args if(args->mode & EXCLUSIVE_MODES) { res = RES_BAD_ARG; logger_print(args->logger, LOG_ERROR, - "Modes -%c and -%c are exclusive.\n", + "Options -%c and -%c are exclusive.\n", (char)opt, mode_option(args->mode)); goto error; } args->mode |= MODE_MEDIUM_COMPUTE; - ptr = strrchr(optarg, ','); - if(ptr) { - if(ptr != strchr(optarg, ',')) - res = RES_BAD_ARG; /* Single ',' allowed */ - else { - res = cstr_to_double(ptr + 1, args->probe + 3); - if(res == RES_OK && args->probe[3] < 0) res = RES_BAD_ARG; - } - *ptr = '\0'; - } - if(res != RES_OK) { - logger_print(args->logger, LOG_ERROR, - "Invalid argument for option -%c: %s\n", - opt, optarg); - goto error; - } - args->medium_name = optarg; + GET_STR_AND_OPTIONAL_TIME_RANGE(args->medium_name, args->pos_and_time + 3); break; } @@ -697,46 +734,24 @@ parse_args if(args->mode & EXCLUSIVE_MODES) { res = RES_BAD_ARG; logger_print(args->logger, LOG_ERROR, - "Modes -%c and -%c are exclusive.\n", + "Options -%c and -%c are exclusive.\n", (char)opt, mode_option(args->mode)); goto error; } args->mode |= MODE_PROBE_COMPUTE; - res = cstr_to_list_double(optarg, ',', args->probe, &len, 4); - if(res != RES_OK - || len < 3 - || (len == 4 && args->probe[3] < 0) - || len > 4) - { - 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; - } + GET_POS_AND_OPTIONAL_TIME_RANGE(args->pos_and_time); break; case 'P': if(args->mode & EXCLUSIVE_MODES) { res = RES_BAD_ARG; logger_print(args->logger, LOG_ERROR, - "Modes -%c and -%c are exclusive.\n", + "Options -%c and -%c are exclusive.\n", (char)opt, mode_option(args->mode)); goto error; } args->mode |= MODE_PROBE_COMPUTE_ON_INTERFACE; - res = cstr_to_list_double(optarg, ',', args->probe, &len, 4); - if(res != RES_OK - || len < 3 - || (len == 4 && args->probe[3] < 0) - || len > 4) - { - 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; - } + GET_POS_AND_OPTIONAL_TIME_RANGE(args->pos_and_time); break; case 'r': @@ -756,7 +771,7 @@ parse_args if(args->mode & EXCLUSIVE_MODES) { res = RES_BAD_ARG; logger_print(args->logger, LOG_ERROR, - "Modes -%c and -%c are exclusive.\n", + "Options -%c and -%c are exclusive.\n", (char)opt, mode_option(args->mode)); goto error; } @@ -771,7 +786,7 @@ parse_args if(args->mode & EXCLUSIVE_MODES) { res = RES_BAD_ARG; logger_print(args->logger, LOG_ERROR, - "Modes -%c and -%c are exclusive.\n", + "Options -%c and -%c are exclusive.\n", (char)opt, mode_option(args->mode)); goto error; } @@ -786,24 +801,7 @@ parse_args args->mode |= MODE_FLUX_BOUNDARY_COMPUTE; break; } - ptr = strrchr(optarg, ','); - if(ptr) { - if(ptr != strchr(optarg, ',')) - res = RES_BAD_ARG; /* Single ',' allowed */ - else { - res = cstr_to_double(ptr + 1, args->probe + 3); - if(res == RES_OK && args->probe[3] < 0) - res = RES_BAD_ARG; - } - *ptr = '\0'; - } - args->solve_filename = optarg; - if(res != RES_OK) { - logger_print(args->logger, LOG_ERROR, - "Invalid argument for option -%c: %s\n", - opt, optarg); - goto error; - } + GET_STR_AND_OPTIONAL_TIME_RANGE(args->solve_filename, args->pos_and_time + 3); break; } @@ -879,8 +877,8 @@ parse_args { 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\n", - buf); + "Option -%c can only be used in conjunction with: %s\n", + mode_option(args->mode & (MODE_BIN_GREEN | MODE_GREEN)), buf); res = RES_BAD_ARG; goto error; } @@ -914,7 +912,7 @@ parse_args } if(args->mode & MODE_EXTENDED_RESULTS) { - if(!(args->mode & COMPUTE_MODES)) { + if(!(args->mode & EXT_COMPATIBLE_MODES)) { res = RES_BAD_ARG; print_multiple_modes(buf, sizeof(buf), EXT_COMPATIBLE_MODES, 0); logger_print(args->logger, LOG_ERROR, @@ -944,25 +942,36 @@ res_T parse_camera (struct logger* logger, char* cam_param, - struct camera* cam) + struct stardis* stardis) { char** line = NULL; char** opt = NULL; + struct camera* cam; res_T res = RES_OK; - ASSERT(cam_param && cam); - + ASSERT(cam_param && stardis); + cam = &stardis->camera; line = split_line(cam_param, ':'); if(line) { + struct str keep; int i = 0; + str_init(stardis->allocator, &keep); for(i = 0; *(line + i); i++) { size_t len = 0; + str_set(&keep, line[i]); opt = split_line(line[i], '='); - ASSERT(opt[0] && opt[1] && !opt[2]); + if(!opt[0] || ! opt[1] || opt[2]) { + if(res == RES_OK) res = RES_BAD_ARG; + logger_print((logger), LOG_ERROR, + "Invalid option syntax: %s\n", str_cget(&keep)); + goto error; + } + str_set(&keep, opt[0]); _strupr(opt[0]); if(strcmp(opt[0], "T") == 0) { - ERR(cstr_to_double(opt[1], &cam->time)); + GET_OPTIONAL_TIME_RANGE(opt[1], 0, cam->time_range, logger, "%s", + str_cget(&keep)); } else if(strcmp(opt[0], "FOV") == 0) { ERR(cstr_to_double(opt[1], &cam->fov)); @@ -994,6 +1003,7 @@ parse_camera goto error; } } + str_release(&keep); } end: @@ -1015,6 +1025,10 @@ error: goto end; } +#undef GET_STR_AND_OPTIONAL_TIME_RANGE +#undef GET_POS_AND_OPTIONAL_TIME_RANGE +#undef GET_OPTIONAL_TIME_RANGE + static struct description* find_description_by_name (struct stardis* stardis, diff --git a/src/stardis-parsing.h b/src/stardis-parsing.h @@ -68,7 +68,8 @@ enum stardis_mode { SURFACE_COMPUTE_MODES = MODE_BOUNDARY_COMPUTE | MODE_FLUX_BOUNDARY_COMPUTE | MODE_MAP_COMPUTE, - EXT_COMPATIBLE_MODES = GREEN_COMPATIBLE_MODES | MODE_MEDIUM_COMPUTE, + EXT_COMPATIBLE_MODES + = GREEN_COMPATIBLE_MODES | MODE_MEDIUM_COMPUTE | MODE_FLUX_BOUNDARY_COMPUTE, REGION_COMPUTE_MODES = SURFACE_COMPUTE_MODES | MODE_MEDIUM_COMPUTE, @@ -104,7 +105,7 @@ struct args { char* chunks_prefix; size_t samples; unsigned nthreads; - double probe[4]; + double pos_and_time[5]; enum stardis_mode mode; double ambient_temp, ref_temp; char* camera; @@ -179,7 +180,7 @@ extern res_T parse_camera (struct logger* logger, char* cam_param, - struct camera* cam); + struct stardis* stardis); extern LOCAL_SYM res_T process_model_line