commit 19564c2076e440929fdcd517dea481db7de3fbad
parent fa96756ead94e2a036c3b9b21d6852fddf0fd039
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Mon, 22 Jun 2020 11:51:24 +0200
Save the RNG state of the simulation in the estimator
Diffstat:
9 files changed, 114 insertions(+), 3 deletions(-)
diff --git a/src/sdis.h b/src/sdis.h
@@ -49,6 +49,7 @@ struct logger;
struct mem_allocator;
struct senc2d_scene;
struct senc3d_scene;
+struct ssp_rng;
/* Forward declaration of the Stardis opaque data types. These data types are
* ref counted. Once created the caller implicitly owns the created data, i.e.
@@ -730,6 +731,12 @@ sdis_estimator_for_each_path
sdis_process_heat_path_T func,
void* context);
+/* Retrieve the RNG state at the end of the simulation. */
+SDIS_API res_T
+sdis_estimator_get_rng_state
+ (const struct sdis_estimator* estimator,
+ struct ssp_rng** rng_state);
+
/*******************************************************************************
* The green function saves the estimation of the propagator
******************************************************************************/
diff --git a/src/sdis_estimator.c b/src/sdis_estimator.c
@@ -16,7 +16,11 @@
#include "sdis.h"
#include "sdis_device_c.h"
#include "sdis_estimator_c.h"
+#include "sdis_log.h"
+#include <star/ssp.h>
+
+#include <rsys/cstr.h>
#include <rsys/mutex.h>
/*******************************************************************************
@@ -32,6 +36,7 @@ estimator_release(ref_T* ref)
dev = estimator->dev;
darray_heat_path_release(&estimator->paths);
if(estimator->mutex) mutex_destroy(estimator->mutex);
+ if(estimator->rng) SSP(rng_ref_put(estimator->rng));
MEM_RM(dev->allocator, estimator);
SDIS(device_ref_put(dev));
}
@@ -192,6 +197,16 @@ error:
goto exit;
}
+res_T
+sdis_estimator_get_rng_state
+ (const struct sdis_estimator* estimator,
+ struct ssp_rng** rng_state)
+{
+ if(!estimator || !rng_state) return RES_BAD_ARG;
+ *rng_state = estimator->rng;
+ return RES_OK;
+}
+
/*******************************************************************************
* Local functions
******************************************************************************/
@@ -268,3 +283,65 @@ error:
goto exit;
}
+res_T
+estimator_save_rng_state
+ (struct sdis_estimator* estimator,
+ const struct ssp_rng_proxy* proxy)
+{
+ struct ssp_rng_type rng_type;
+ FILE* stream = NULL;
+ res_T res = RES_OK;
+ ASSERT(estimator && proxy);
+
+ /* Release the previous RNG state if any */
+ if(estimator->rng) {
+ SSP(rng_ref_put(estimator->rng));
+ estimator->rng = NULL;
+ }
+
+ stream = tmpfile();
+ if(!stream) {
+ log_err(estimator->dev,
+ "Could not open a temporary stream to store "
+ "the RNG state of the estimation.\n");
+ res = RES_IO_ERR;
+ goto error;
+ }
+
+ SSP(rng_proxy_get_type(proxy, &rng_type));
+ res = ssp_rng_create(estimator->dev->allocator, &rng_type, &estimator->rng);
+ if(res != RES_OK) {
+ log_err(estimator->dev,
+ "Could not create the RNG to save the RNG state of the estimation "
+ "-- %s\n", res_to_cstr(res));
+ goto error;
+ }
+
+ res = ssp_rng_proxy_write(proxy, stream);
+ if(res != RES_OK) {
+ log_err(estimator->dev,
+ "Could not serialize the RNG state of the estimation -- %s\n",
+ res_to_cstr(res));
+ goto error;
+ }
+
+ rewind(stream);
+ res = ssp_rng_read(estimator->rng, stream);
+ if(res != RES_OK) {
+ log_err(estimator->dev,
+ "Could not save the RNG state of the estimation -- %s\n",
+ res_to_cstr(res));
+ goto error;
+ }
+
+exit:
+ if(stream) fclose(stream);
+ return res;
+error:
+ if(estimator->rng) {
+ SSP(rng_ref_put(estimator->rng));
+ estimator->rng = NULL;
+ }
+ goto exit;
+}
+
diff --git a/src/sdis_estimator_c.h b/src/sdis_estimator_c.h
@@ -23,6 +23,7 @@
#include <rsys/ref_count.h>
/* Forward declarations */
+struct ssp_rng;
struct sdis_device;
struct sdis_estimator;
enum sdis_estimator_type;
@@ -44,13 +45,14 @@ struct sdis_estimator {
struct mutex* mutex;
struct darray_heat_path paths; /* Tracked paths */
+ /* State of the RNG after the simulation */
+ struct ssp_rng* rng;
+
enum sdis_estimator_type type;
ref_T ref;
struct sdis_device* dev;
};
-struct sdis_estimator_handle;
-
/*******************************************************************************
* Estimator local API
******************************************************************************/
@@ -66,6 +68,11 @@ estimator_add_and_release_heat_path
(struct sdis_estimator* estimator,
struct sdis_heat_path* path);
+extern LOCAL_SYM res_T
+estimator_save_rng_state
+ (struct sdis_estimator* estimator,
+ const struct ssp_rng_proxy* proxy);
+
/* Must be invoked before any others "estimator_setup" functions */
static INLINE void
estimator_setup_realisations_count
diff --git a/src/sdis_solve_boundary_Xd.h b/src/sdis_solve_boundary_Xd.h
@@ -342,6 +342,8 @@ XD(solve_boundary)
estimator_setup_realisations_count(estimator, nrealisations, acc_temp.count);
estimator_setup_temperature(estimator, acc_temp.sum, acc_temp.sum2);
estimator_setup_realisation_time(estimator, acc_time.sum, acc_time.sum2);
+ res = estimator_save_rng_state(estimator, rng_proxy);
+ if(res != RES_OK) goto error;
}
/* Setup the green function */
@@ -676,6 +678,9 @@ XD(solve_boundary_flux)
estimator_setup_flux(estimator, FLUX_RADIATIVE, acc_fr[0].sum, acc_fr[0].sum2);
estimator_setup_flux(estimator, FLUX_TOTAL, acc_fl[0].sum, acc_fl[0].sum2);
+ res = estimator_save_rng_state(estimator, rng_proxy);
+ if(res != RES_OK) goto error;
+
exit:
if(rngs) {
FOR_EACH(i, 0, scn->dev->nthreads) { if(rngs[i]) SSP(rng_ref_put(rngs[i])); }
diff --git a/src/sdis_solve_medium_Xd.h b/src/sdis_solve_medium_Xd.h
@@ -405,6 +405,8 @@ XD(solve_medium)
estimator_setup_realisations_count(estimator, nrealisations, acc_temp.count);
estimator_setup_temperature(estimator, acc_temp.sum, acc_temp.sum2);
estimator_setup_realisation_time(estimator, acc_time.sum, acc_time.sum2);
+ res = estimator_save_rng_state(estimator, rng_proxy);
+ if(res != RES_OK) goto error;
}
if(out_green) {
diff --git a/src/sdis_solve_probe_Xd.h b/src/sdis_solve_probe_Xd.h
@@ -221,6 +221,8 @@ XD(solve_probe)
estimator_setup_realisations_count(estimator, nrealisations, acc_temp.count);
estimator_setup_temperature(estimator, acc_temp.sum, acc_temp.sum2);
estimator_setup_realisation_time(estimator, acc_time.sum, acc_time.sum2);
+ res = estimator_save_rng_state(estimator, rng_proxy);
+ if(res != RES_OK) goto error;
}
if(out_green) {
diff --git a/src/sdis_solve_probe_boundary_Xd.h b/src/sdis_solve_probe_boundary_Xd.h
@@ -258,6 +258,8 @@ XD(solve_probe_boundary)
estimator_setup_realisations_count(estimator, nrealisations, acc_temp.count);
estimator_setup_temperature(estimator, acc_temp.sum, acc_temp.sum2);
estimator_setup_realisation_time(estimator, acc_time.sum, acc_time.sum2);
+ res = estimator_save_rng_state(estimator, rng_proxy);
+ if(res != RES_OK) goto error;
}
if(out_green) {
@@ -542,6 +544,9 @@ XD(solve_probe_boundary_flux)
estimator_setup_flux(estimator, FLUX_RADIATIVE, acc_fr[0].sum, acc_fr[0].sum2);
estimator_setup_flux(estimator, FLUX_TOTAL, acc_fl[0].sum, acc_fl[0].sum2);
+ res = estimator_save_rng_state(estimator, rng_proxy);
+ if(res != RES_OK) goto error;
+
exit:
if(rngs) {
FOR_EACH(i, 0, scn->dev->nthreads) {if(rngs[i]) SSP(rng_ref_put(rngs[i]));}
diff --git a/src/test_sdis_solve_camera.c b/src/test_sdis_solve_camera.c
@@ -30,7 +30,7 @@
#define UNKOWN_TEMPERATURE -1
#define IMG_WIDTH 640
#define IMG_HEIGHT 480
-#define SPP 1024 /* #Samples per pixel, i.e. #realisations per pixel */
+#define SPP 4 /* #Samples per pixel, i.e. #realisations per pixel */
/*
* The scene is composed of a solid cube whose temperature is unknown. The
diff --git a/src/test_sdis_solve_probe.c b/src/test_sdis_solve_probe.c
@@ -16,6 +16,7 @@
#include "sdis.h"
#include "test_sdis_utils.h"
+#include <star/ssp.h>
#include <rsys/math.h>
/*
@@ -268,6 +269,7 @@ main(int argc, char** argv)
struct fluid* fluid_param;
struct solid* solid_param;
struct interf* interface_param;
+ struct ssp_rng* rng_state = NULL;
enum sdis_estimator_type type;
double pos[3];
double time_range[2];
@@ -454,6 +456,10 @@ main(int argc, char** argv)
BA(sdis_estimator_for_each_path(estimator, NULL, &dump_ctx));
OK(sdis_estimator_for_each_path(estimator, process_heat_path, &dump_ctx));
+ BA(sdis_estimator_get_rng_state(NULL, &rng_state));
+ BA(sdis_estimator_get_rng_state(estimator, NULL));
+ OK(sdis_estimator_get_rng_state(estimator, &rng_state));
+
OK(sdis_estimator_ref_put(estimator));
OK(sdis_scene_ref_put(scn));
OK(sdis_device_ref_put(dev));