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:
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;