stardis

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

commit 44931a8d300c6702cde26a8add3b0a7bc5ece140
parent 4c760ea5b258354d7305b510b044460336d5d21d
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date:   Wed, 30 Jun 2021 14:48:17 +0200

Merge branch 'feature_randomstate_rw' into develop

Diffstat:
Mcmake/CMakeLists.txt | 8+++++---
Mdoc/stardis.1.txt.in | 24++++++++++++++++++++----
Msrc/stardis-app.c | 10++++++++++
Msrc/stardis-app.h | 2++
Msrc/stardis-compute.c | 77+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/stardis-output.c | 21+++++++++++++++++++++
Msrc/stardis-output.h | 11+++++++++++
Msrc/stardis-parsing.c | 52+++++++++++++++++++++++++++++++++++++++++++++++++++-
Msrc/stardis-parsing.h | 8+++++++-
9 files changed, 204 insertions(+), 9 deletions(-)

diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt @@ -75,6 +75,7 @@ find_package(Star3D 0.8 REQUIRED) find_package(StarEnc3D 0.5.3 REQUIRED) find_package(Stardis 0.12 REQUIRED) find_package(StarSTL 0.3.3 REQUIRED) +find_package(StarSP 0.8.1 REQUIRED) if(MSVC) find_package(MuslGetopt REQUIRED) endif() @@ -86,6 +87,7 @@ include_directories( ${StarEnc3D_INCLUDE_DIR} ${Stardis_INCLUDE_DIR} ${StarSTL_INCLUDE_DIR} + ${StarSP_INCLUDE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) if(MSVC) include_directories(${MuslGetopt_INCLUDE_DIR}) @@ -97,11 +99,11 @@ include(rcmake_runtime) if(CMAKE_COMPILER_IS_GNUCC) rcmake_append_runtime_dirs(_runtime_dirs - RSys Stardis Star3D StarGeom3D StarEnc3D StarSTL) + RSys Stardis Star3D StarGeom3D StarEnc3D StarSTL StarSP) endif() if(MSVC) rcmake_append_runtime_dirs(_runtime_dirs - RSys MuslGetopt Stardis Star3D StarGeom3D StarEnc3D StarSTL) + RSys MuslGetopt Stardis Star3D StarGeom3D StarEnc3D StarSTL StarSP) endif() ############################################################################### @@ -156,7 +158,7 @@ set_target_properties(stardis PROPERTIES VERSION ${SDIS_VERSION}) target_link_libraries(stardis - Stardis Star3D StarGeom3D StarEnc3D StarSTL RSys ${GETOPT_LIB} ${MATH_LIB}) + Stardis Star3D StarGeom3D StarEnc3D StarSTL StarSP RSys ${GETOPT_LIB} ${MATH_LIB}) ############################################################################### # Define output & install directories diff --git a/doc/stardis.1.txt.in b/doc/stardis.1.txt.in @@ -48,7 +48,7 @@ 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 answer questions like _"Where from does the heat come at this location?"_. -Propagators seamlessly agregate all the provided geometrical and physical +Propagators seamlessly aggregate all the provided geometrical and physical information on the system in an unbiased and very-fast statistical model. *stardis*(1) also provides two additional functionalities: converting the @@ -63,7 +63,7 @@ cinema industry (FX and animated movies), this theoretical framework can now be practically used on the most geometrically complex systems. Everytime the linear assumption is relevant, this theoretical framework allows -to encompass all the heat transfer mecanisms (conductive-convective-radiative) +to encompass all the heat transfer mechanisms (conductive-convective-radiative) in an unified statistical model. Such systems can be solved by a Monte-Carlo approach just by sampling heat paths. This can be seen as an extension of Monte-Carlo algorithms that solve radiative transfer by sampling optical paths. @@ -207,7 +207,7 @@ options that write to _standard output_ (-g, -h, -R, -v). rank starting at index 00000000, and possibly followed by *_err* for failure paths: prefix00000000.vtk, prefix00000001_err.vtk, ... + -This option can only be used in conjuction with options that compute a +This option can only be used in conjunction with options that compute a result (-F, -m, -P, -p, -R, -S, -s) and cannot be used in conjunction with options -g or -G. @@ -259,6 +259,16 @@ different temperature, flux or volumic power values. and informative messages). All the messages are written to _standard error_. Default verbosity *level* is @STARDIS_ARGS_DEFAULT_VERBOSE_LEVEL@. +*-x* _file_name_:: + Read the provided file and use its content to initialize the random + generator's internal state. Used in conjunction with the *-X* option, this + can be used to ensure statistical independence between subsequent + computations. + +*-X* _file_name_:: + Write the random generator's internal state, as it is at the end of the + computation, to the provided file. + EXAMPLES -------- Preprocess the system as described in *scene 5.txt* when intending to compute @@ -289,6 +299,12 @@ time range. The system is read from the file *model.txt*: $ stardis -M model.txt -p 1,2.5,0,50,5000 +Compute 3 probe temperatures, ensuring statistical independence: + + $ stardis -M model.txt -p 1,1.5,0,50,5000 -Xstate1 + $ stardis -M model.txt -p 1,2.5,0,50,5000 -xstate1 -Xstate2 + $ stardis -M model.txt -p 1,3.5,0,50,5000 -xstate2 + Render the system as described in *scene.txt* with default settings: $ stardis -M scene.txt -R : @@ -304,7 +320,7 @@ post-processed using *htpp*(1) with default settings to obtain a png file. -D error,err_path_ > img.ht $ htpp -o img.pgn -v -m default img.ht -Compute the Green fonction that computes the temperature at the probe point +Compute the Green function that computes the temperature at the probe point *0, 0, 0* at steady state. The system is read from the file *model.txt* and the Green function is written to the *probe.green file* and the heat paths' ends are written to the *probe_ends.csv* file: diff --git a/src/stardis-app.c b/src/stardis-app.c @@ -225,6 +225,8 @@ stardis_init str_init(stardis->allocator, &stardis->paths_filename); str_init(stardis->allocator, &stardis->bin_green_filename); str_init(stardis->allocator, &stardis->end_paths_filename); + str_init(stardis->allocator, &stardis->rndgen_state_in_filename); + str_init(stardis->allocator, &stardis->rndgen_state_out_filename); str_init(stardis->allocator, &stardis->chunks_prefix); darray_size_t_init(stardis->allocator, &stardis->compute_surface.primitives); darray_sides_init(stardis->allocator, &stardis->compute_surface.sides); @@ -362,6 +364,14 @@ stardis_init if(args->end_paths_filename) { ERR(str_set(&stardis->end_paths_filename, args->end_paths_filename)); } + if(args->rndgen_state_in_filename) { + ERR(str_set(&stardis->rndgen_state_in_filename, + args->rndgen_state_in_filename)); + } + if(args->rndgen_state_out_filename) { + ERR(str_set(&stardis->rndgen_state_out_filename, + args->rndgen_state_out_filename)); + } } /* If computation is on a volume, check medium is known */ diff --git a/src/stardis-app.h b/src/stardis-app.h @@ -814,6 +814,8 @@ struct stardis { struct str paths_filename; struct str bin_green_filename; struct str end_paths_filename; + struct str rndgen_state_in_filename; + struct str rndgen_state_out_filename; struct str chunks_prefix; int mode; size_t samples; diff --git a/src/stardis-compute.c b/src/stardis-compute.c @@ -24,6 +24,7 @@ #include <star/s3d.h> #include <star/sg3d_sXd_helper.h> +#include <star/ssp.h> #include <rsys/double3.h> #include <rsys/double2.h> @@ -373,6 +374,43 @@ error: goto end; } +#define READ_RANDOM_STATE(Name) \ + if(!str_is_empty(Name)) { \ + const char* name = str_cget(Name); \ + stream = fopen(name, "r"); \ + if(!stream) { \ + res = RES_IO_ERR; \ + logger_print(stardis->logger, LOG_ERROR, \ + "Could not open generator's state file ('%s').\n", \ + name); \ + goto error; \ + } \ + ERR(ssp_rng_create(stardis->allocator, &ssp_rng_mt19937_64, &args.rng_state)); \ + res = read_random_generator_state(args.rng_state, stream); \ + if(res != RES_OK) { \ + logger_print(stardis->logger, LOG_ERROR, \ + "Could not read random generator's state ('%s').\n", \ + name); \ + goto error; \ + } \ + fclose(stream); stream = NULL; \ + } + +#define WRITE_RANDOM_STATE(Name) \ + if(!str_is_empty(Name)) { \ + const char* name = str_cget(Name); \ + stream = fopen(name, "wb"); \ + if(!stream) { \ + res = RES_IO_ERR; \ + logger_print(stardis->logger, LOG_ERROR, \ + "Could not write random generator's state ('%s').\n", \ + name); \ + goto error; \ + } \ + ERR(write_random_generator_state(estimator, stream)); \ + fclose(stream); stream = NULL; \ + } + static res_T compute_probe(struct stardis* stardis, struct time* start) { @@ -394,6 +432,9 @@ compute_probe(struct stardis* stardis, struct time* start) d3_set(args.position, stardis->probe); d2_set(args.time_range, stardis->time_range); + /* Input random state? */ + READ_RANDOM_STATE(&stardis->rndgen_state_in_filename); + if(stardis->mode & (MODE_BIN_GREEN | MODE_GREEN)) { time_current(&compute_start); ERR(sdis_solve_probe_green_function(stardis->sdis_scn, &args, &green)); @@ -441,10 +482,14 @@ compute_probe(struct stardis* stardis, struct time* start) ERR(sdis_estimator_for_each_path(estimator, dump_path, &dump_ctx)); } + /* Output random state? */ + WRITE_RANDOM_STATE(&stardis->rndgen_state_out_filename); + end: if(stream) fclose(stream); if(estimator) SDIS(estimator_ref_put(estimator)); if(green) SDIS(green_function_ref_put(green)); + if(args.rng_state) SSP(rng_ref_put(args.rng_state)); return res; error: goto end; @@ -622,6 +667,9 @@ compute_probe_on_interface(struct stardis* stardis, struct time* start) args.side = compute_side; d2_set(args.time_range, stardis->time_range); + /* Input random state? */ + READ_RANDOM_STATE(&stardis->rndgen_state_in_filename); + if(stardis->mode & (MODE_BIN_GREEN | MODE_GREEN)) { time_current(&compute_start); ERR(sdis_solve_probe_boundary_green_function(stardis->sdis_scn, &args, @@ -670,10 +718,14 @@ compute_probe_on_interface(struct stardis* stardis, struct time* start) ERR(sdis_estimator_for_each_path(estimator, dump_path, &dump_ctx)); } + /* Output random state? */ + WRITE_RANDOM_STATE(&stardis->rndgen_state_out_filename); + end: if(stream) fclose(stream); if(estimator) SDIS(estimator_ref_put(estimator)); if(green) SDIS(green_function_ref_put(green)); + if(args.rng_state) SSP(rng_ref_put(args.rng_state)); return res; error: goto end; @@ -876,6 +928,9 @@ compute_medium(struct stardis* stardis, struct time* start) args.medium = medium; d2_set(args.time_range, stardis->time_range); + /* Input random state? */ + READ_RANDOM_STATE(&stardis->rndgen_state_in_filename); + if(stardis->mode & (MODE_BIN_GREEN | MODE_GREEN)) { time_current(&compute_start); ERR(sdis_solve_medium_green_function(stardis->sdis_scn, &args, &green)); @@ -922,10 +977,14 @@ compute_medium(struct stardis* stardis, struct time* start) ERR(sdis_estimator_for_each_path(estimator, dump_path, &dump_ctx)); } + /* Output random state? */ + WRITE_RANDOM_STATE(&stardis->rndgen_state_out_filename); + end: if(stream) fclose(stream); if(estimator) SDIS(estimator_ref_put(estimator)); if(green) SDIS(green_function_ref_put(green)); + if(args.rng_state) SSP(rng_ref_put(args.rng_state)); return res; error: goto end; @@ -1000,6 +1059,9 @@ compute_boundary(struct stardis* stardis, struct time* start) = darray_size_t_size_get(&stardis->compute_surface.primitives); d2_set(args.time_range, stardis->time_range); + /* Input random state? */ + READ_RANDOM_STATE(&stardis->rndgen_state_in_filename); + if(stardis->mode & (MODE_BIN_GREEN | MODE_GREEN)) { time_current(&compute_start); ERR(sdis_solve_boundary_green_function(stardis->sdis_scn, &args, &green)); @@ -1046,10 +1108,14 @@ compute_boundary(struct stardis* stardis, struct time* start) ERR(sdis_estimator_for_each_path(estimator, dump_path, &dump_ctx)); } + /* Output random state? */ + WRITE_RANDOM_STATE(&stardis->rndgen_state_out_filename); + end: if(stream) fclose(stream); if(estimator) SDIS(estimator_ref_put(estimator)); if(green) SDIS(green_function_ref_put(green)); + if(args.rng_state) SSP(rng_ref_put(args.rng_state)); return res; error: goto end; @@ -1064,6 +1130,7 @@ compute_flux_boundary(struct stardis* stardis, struct time* start) struct sdis_solve_boundary_flux_args args = SDIS_SOLVE_BOUNDARY_FLUX_ARGS_DEFAULT; struct dump_path_context dump_ctx; + FILE* stream = NULL; struct time compute_start, compute_end; ASSERT(stardis && start && (stardis->mode & MODE_FLUX_BOUNDARY_COMPUTE)); @@ -1075,6 +1142,9 @@ compute_flux_boundary(struct stardis* stardis, struct time* start) = darray_size_t_size_get(&stardis->compute_surface.primitives); d2_set(args.time_range, stardis->time_range); + /* Input random state? */ + READ_RANDOM_STATE(&stardis->rndgen_state_in_filename); + time_current(&compute_start); ERR(sdis_solve_boundary_flux(stardis->sdis_scn, &args, &estimator)); time_current(&compute_end); @@ -1087,9 +1157,13 @@ compute_flux_boundary(struct stardis* stardis, struct time* start) dump_ctx.rank = 0; ERR(sdis_estimator_for_each_path(estimator, dump_path, &dump_ctx)); + /* Output random state? */ + WRITE_RANDOM_STATE(&stardis->rndgen_state_out_filename); + end: if(estimator) SDIS(estimator_ref_put(estimator)); if(green) SDIS(green_function_ref_put(green)); + if(args.rng_state) SSP(rng_ref_put(args.rng_state)); return res; error: goto end; @@ -1147,6 +1221,9 @@ error: goto end; } +#undef READ_RANDOM_STATE +#undef WRITE_RANDOM_STATE + /******************************************************************************* * Public Functions ******************************************************************************/ diff --git a/src/stardis-output.c b/src/stardis-output.c @@ -25,6 +25,7 @@ #include<star/senc3d.h> #include<star/sg3d.h> +#include<star/ssp.h> #include <rsys/math.h> #include <rsys/mem_allocator.h> @@ -1823,3 +1824,23 @@ exit: error: goto exit; } + +res_T +write_random_generator_state + (struct sdis_estimator* estimator, + FILE* stream) +{ + res_T res; + struct ssp_rng* state; + res = sdis_estimator_get_rng_state(estimator, &state); + if(res != RES_OK) return res; + return ssp_rng_write(state, stream); +} + +res_T +read_random_generator_state + (struct ssp_rng* state, + FILE* stream) +{ + return ssp_rng_read(state, stream); +} diff --git a/src/stardis-output.h b/src/stardis-output.h @@ -32,6 +32,7 @@ struct geometry; struct vertex; struct darray_estimators; struct time; +struct ssp_rng; struct dump_path_context { unsigned long rank; @@ -117,4 +118,14 @@ dump_model_as_c_chunks (struct stardis* stardis, FILE* stream); +extern res_T +write_random_generator_state + (struct sdis_estimator* estimator, + FILE* stream); + +extern res_T +read_random_generator_state + (struct ssp_rng* state, + FILE* stream); + #endif diff --git a/src/stardis-parsing.c b/src/stardis-parsing.c @@ -502,6 +502,12 @@ short_help fprintf(stream, "\n -V LEVEL\n"); fprintf(stream, " Set the verbosity level.\n"); + + fprintf(stream, "\n -x <FILE>\n"); + fprintf(stream, " Use a random generator's state read from a file.\n"); + + fprintf(stream, "\n -X <FILE>\n"); + fprintf(stream, " Save the final random generator's state in a file.\n"); } #define FREE_AARRAY(ARRAY) \ @@ -559,7 +565,7 @@ parse_args { 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:"; + const char option_list[] = "a:c:dD:eF:gG:hm:M:n:p:P:r:R:s:S:t:vV:x:X:"; char buf[128]; struct str keep; char** line = NULL; @@ -885,6 +891,30 @@ parse_args goto error; } break; + + case 'x': + if(!(args->mode & RANDOM_RW_MODES)) { + res = RES_BAD_ARG; + print_multiple_modes(buf, sizeof(buf), RANDOM_RW_MODES, 0); + logger_print(args->logger, LOG_ERROR, + "Option -%c can only be used in conjunction with one of the following options: %s.\n", + (char)opt, buf); + goto error; + } + args->rndgen_state_in_filename = optarg; + break; + + case 'X': + if(!(args->mode & RANDOM_RW_MODES)) { + res = RES_BAD_ARG; + print_multiple_modes(buf, sizeof(buf), RANDOM_RW_MODES, 0); + logger_print(args->logger, LOG_ERROR, + "Option -%c can only be used in conjunction with one of the following options: %s.\n", + (char)opt, buf); + goto error; + } + args->rndgen_state_out_filename = optarg; + break; } } @@ -973,6 +1003,26 @@ parse_args } } + if(args->rndgen_state_in_filename && !(args->mode & COMPUTE_MODES)) { + res = RES_BAD_ARG; + print_multiple_modes(buf, sizeof(buf), COMPUTE_MODES, 0); + logger_print(args->logger, LOG_ERROR, + "Option -x can only be used in conjunction with an option" + " that launch a MC computation (%s).\n", + buf); + goto error; + } + + if(args->rndgen_state_out_filename && !(args->mode & COMPUTE_MODES)) { + res = RES_BAD_ARG; + print_multiple_modes(buf, sizeof(buf), COMPUTE_MODES, 0); + logger_print(args->logger, LOG_ERROR, + "Option -X can only be used in conjunction with an option" + " that launch a MC computation (%s).\n", + buf); + goto error; + } + end: FREE_AARRAY(line); str_release(&keep); diff --git a/src/stardis-parsing.h b/src/stardis-parsing.h @@ -81,7 +81,11 @@ enum stardis_mode { USE_STDOUT_MODES = MODE_DUMP_C_CHUNKS | MODE_DUMP_VTK | MODE_DUMP_HELP | MODE_DUMP_VERSION - | MODE_IR_COMPUTE | MODE_GREEN + | MODE_IR_COMPUTE | MODE_GREEN, + + RANDOM_RW_MODES + = MODE_PROBE_COMPUTE | MODE_PROBE_COMPUTE_ON_INTERFACE | MODE_MEDIUM_COMPUTE + | MODE_BOUNDARY_COMPUTE | MODE_FLUX_BOUNDARY_COMPUTE }; STATIC_ASSERT(GREEN_COMPATIBLE_MODES == (COMPUTE_MODES & GREEN_COMPATIBLE_MODES), @@ -103,6 +107,8 @@ struct args { char* bin_green_filename; char* end_paths_filename; char* paths_filename; + char* rndgen_state_in_filename; + char* rndgen_state_out_filename; char* chunks_prefix; size_t samples; unsigned nthreads;