stardis

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

commit 3c8d91d5b8021a655bcff307a1aae645d5248a78
parent 21fae3ba4f4bde64a1554c1cecb4d909e596ba4c
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date:   Mon, 24 Feb 2025 17:19:32 +0100

Add the -f option to compute flux density probes

Diffstat:
Mdoc/stardis-output.5 | 16++++++++++++++++
Mdoc/stardis.1.in | 9+++++++++
Msrc/stardis-app.c | 1+
Msrc/stardis-args.c | 30+++++++++++++++++++++++++-----
Msrc/stardis-args.h.in | 31+++++++++++++++++--------------
Msrc/stardis-compute-probe-boundary.c | 119+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------
Msrc/stardis-compute.c | 49++-----------------------------------------------
Msrc/stardis-compute.h | 49+++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/stardis-output.c | 97++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
9 files changed, 320 insertions(+), 81 deletions(-)

diff --git a/doc/stardis-output.5 b/doc/stardis-output.5 @@ -112,6 +112,7 @@ or an extended format that mixes numbers and their descriptions .It Ta \& \& | Ta Ao Va medium-temp Ac # Option Fl m .It Ta \& \& | Ta Ao Va mean-temp Ac # Option Fl s .It Ta \& \& | Ta Ao Va mean-flux Ac # Option Fl F +.It Ta \& \& | Ta Ao Va flux-density Ac # Option Fl f .It \ Ta Ta .\" Probe temperature .It Ao Va probe-temp Ac Ta ::= Ta Ao Va probe-temp-raw Ac | Ao Va probe-temp-ext Ac @@ -133,8 +134,11 @@ or an extended format that mixes numbers and their descriptions .It \ Ta Ta .\" Mean flux .It Ao Va mean-flux Ac Ta ::= Ta Ao Va mean-flux-raw Ac | Ao Va mean-flux-ext Ac +.It Ao Va flux-density Ac Ta ::= Ta Ao Va flux-density-raw Ac | Ao Va flux-density-ext Ac .It Ao Va mean-flux-raw Ac Ta ::= Ta Ao Va estimate Ac Ao Va estimate Ac Ao Va estimate Ac \e .It Ta Ta Ao Va estimate Ac Ao Va estimate Ac Ao Va failures Ac +.It Ao Va flux-density-raw Ac Ta ::= Ta Ao Va estimate Ac Ao Va estimate Ac Ao Va estimate Ac \e +.It Ta Ta Ao Va estimate Ac Ao Va estimate Ac Ao Va failures Ac .It Ao Va mean-flux-ext Ac Ta ::= Ta Li Temperature at boundary Ao Va stl-path Ac \e .It Ta Ta Ao Va time Ac Ao Va estimate-temp-ext Ac .It Ta Ta Li Convective flux at boundary Ao Va stl-path Ac \e @@ -146,11 +150,23 @@ or an extended format that mixes numbers and their descriptions .It Ta Ta Li Total flux at boundary Ao Va stl-path Ac \e .It Ta Ta Ao Va time Ac Ao Va estimate-flux-ext Ac .It Ta Ta Ao Va failures-ext Ac +.It Ao Va flux-density-ext Ac Ta ::= Ta Li Temperature at Ao Va position Ac Ao Va time Ac \e +.It Ta Ta Ao Va estimate-temp-ext Ac +.It Ta Ta Li Convective flux density at Ao Va position Ac Ao Va time Ac \e +.It Ta Ta Ao Va estimate-f-dsity-ext Ac +.It Ta Ta Li Radiative flux density at Ao Va position Ac Ao Va time Ac \e +.It Ta Ta Ao Va estimate-f-dsity-ext Ac +.It Ta Ta Li Imposed flux density at Ao Va position Ac Ao Va time Ac \e +.It Ta Ta Ao Va estimate-f-dsity-ext Ac +.It Ta Ta Li Total flux density at Ao Va position Ac Ao Va time Ac \e +.It Ta Ta Ao Va estimate-f-dsity-ext Ac +.It Ta Ta Ao Va failures-ext Ac .It \ Ta Ta .\" Miscellaneous .It Ao Va estimate Ac Ta ::= Ta Ao Va expected-value Ac Ao Va standard-error Ac .It Ao Va estimate-temp-ext Ac Ta ::= Ta Ao Va expected-value Ac Li K +/- Ao Va standard-error Ac .It Ao Va estimate-flux-ext Ac Ta ::= Ta Ao Va expected-value Ac Li W +/- Ao Va standard-error Ac +.It Ao Va estimate-f-dsity-ext Ac Ta ::= Ta Ao Va expected-value Ac Li W/m² +/- Ao Va standard-error Ac .It Ao Va expected-value Ac Ta ::= Ta Vt real .It Ao Va standard-error Ac Ta ::= Ta Vt real .It \ Ta Ta diff --git a/doc/stardis.1.in b/doc/stardis.1.in @@ -27,6 +27,7 @@ .Op Fl D Ar path_type , Ns Ar files_name_prefix .Op Fl d Ar file_base_name .Op Fl F Pa surface Ns Op , Ns Ar time Ns Op , Ns Ar time +.Op Fl f Ar x , Ns Ar y , Ns Ar z Ns Op , Ns Ar time Ns Op , Ns Ar time .Op Fl G Pa green_bin Ns Op , Ns Pa green_ascii .Op Fl I Ar initial_time .Op Fl L Pa interface_probes @@ -209,6 +210,14 @@ positive from the solid to the fluid. These triangles are not added to the geometry, but must be part of it. By default the compute time is @STARDIS_ARGS_DEFAULT_COMPUTE_TIME@. The surface does not need to be connex. +.It Fl f Ar x , Ns Ar y , Ns Ar z Ns Op , Ns Ar time Ns Op , Ns Ar time +Compute the flux density at a given probe on an interface at a given 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 flux density can only be computed on a solid-fluid interface and is +accounted positive from the solid to the fluid. +The probe coordinates must be in the same system as the geometry. +By default the compute time is @STARDIS_ARGS_DEFAULT_COMPUTE_TIME@. .It Fl G Pa green_bin Ns Op , Ns Pa green_ascii Compute the Green function at the specified time and write it to a binary file. If a diff --git a/src/stardis-app.c b/src/stardis-app.c @@ -328,6 +328,7 @@ stardis_init ERR(str_set(&stardis->solve_name, args->medium_name)); } else if((args->mode & MODE_PROBE_COMPUTE_ON_INTERFACE) + || (args->mode & MODE_PROBE_COMPUTE_FLUX_ON_INTERFACE) || (args->mode & MODE_PROBE_LIST_COMPUTE_ON_INTERFACE)) { ERR(darray_probe_boundary_copy (&stardis->probe_boundary_list, &args->probe_boundary_list)); diff --git a/src/stardis-args.c b/src/stardis-args.c @@ -113,6 +113,7 @@ mode_option(const int m) if(m & MODE_DUMP_PATHS) { found++; res = 'D'; } if(m & MODE_EXTENDED_RESULTS) { found++; res = 'e'; } if(m & MODE_FLUX_BOUNDARY_COMPUTE) { found++; res = 'F'; } + if(m & MODE_PROBE_COMPUTE_FLUX_ON_INTERFACE) { found++; res = 'f'; } if(m & MODE_GREEN) { found++; res = 'g'; } if(m & MODE_BIN_GREEN) { found++; res = 'G'; } if(m & MODE_DUMP_HELP) { found++; res = 'h'; } @@ -459,10 +460,10 @@ usage(FILE* stream) #define PRINT(Msg) fprintf(stream, Msg) PRINT("stardis [-eghiv] [-a diff_algo] [-D path_type,files_name_prefix]\n"); PRINT(" [-d file_base_name] [-F surface[,time[,time]]]\n"); - PRINT(" [-G green_bin[,green_ascii]] [-I initial_time]\n"); - PRINT(" [-L interface_probes] [-m medium_name[,time[,time]]]\n"); - PRINT(" [-n samples_count] [-o picard_order]\n"); - PRINT(" [-P x,y,z[,time[,time]][:side_indicator]]\n"); + PRINT(" [-f x,y,z[,time[,time]]] [-G green_bin[,green_ascii]]\n"); + PRINT(" [-I initial_time] [-L interface_probes]\n"); + PRINT(" [-m medium_name[,time[,time]]] [-n samples_count]\n"); + PRINT(" [-o picard_order] [-P x,y,z[,time[,time]][:side_indicator]]\n"); PRINT(" [-p x,y,z[,time[,time]]] [-R rendering_opt[:rendering_opt ...]]\n"); PRINT(" [-S surface[,time[,time]]] [-s surface[,time[,time]]]\n"); PRINT(" [-t threads_count] [-V verbosity_level] [-X output_rng]\n"); @@ -525,7 +526,7 @@ parse_args { int opt = 0, n_used = 0, o_used = 0; size_t len = 0; - const char option_list[] = "a:c:d:D:eF:gG:hiI:L:m:M:n:o:p:P:R:s:S:t:vV:x:X:"; + const char option_list[] = "a:c:d:D:ef:F:gG:hiI:L:m:M:n:o:p:P:R:s:S:t:vV:x:X:"; char buf[128]; struct str keep; char** line = NULL; @@ -609,6 +610,25 @@ parse_args args->mode |= MODE_EXTENDED_RESULTS; break; + case 'f': + { + struct stardis_probe_boundary* probe = NULL; + + if(args->mode & EXCLUSIVE_MODES) { + logger_print(args->logger, LOG_ERROR, + "Options -%c and -%c are exclusive.\n", + (char)opt, mode_option(args->mode)); + res = RES_BAD_ARG; + goto error; + } + args->mode |= MODE_PROBE_COMPUTE_FLUX_ON_INTERFACE; + res = allocate_probe_boundary(args, &probe); + if(res != RES_OK) goto error; + res = parse_position_and_time(optarg, probe->position, probe->time); + if(res != RES_OK) goto error; + break; + } + /*case 'F': see 's' */ case 'g': diff --git a/src/stardis-args.h.in b/src/stardis-args.h.in @@ -50,18 +50,19 @@ enum stardis_mode { MODE_DUMP_MODEL = BIT(2), /* -d */ MODE_EXTENDED_RESULTS = BIT(3), /* -e */ MODE_FLUX_BOUNDARY_COMPUTE = BIT(4), /* -F */ - MODE_BIN_GREEN = BIT(5), /* -G */ - MODE_GREEN = BIT(6), /* -g */ - MODE_DUMP_HELP = BIT(7), /* -h */ - MODE_PROBE_LIST_COMPUTE_ON_INTERFACE = BIT(8), /* -L */ - MODE_MEDIUM_COMPUTE = BIT(9), /* -m */ - MODE_PROBE_COMPUTE_ON_INTERFACE = BIT(10), /* -P */ - MODE_PROBE_COMPUTE = BIT(11), /* -p */ - MODE_IR_COMPUTE = BIT(12), /* -R */ - MODE_MAP_COMPUTE = BIT(13), /* -S */ - MODE_BOUNDARY_COMPUTE = BIT(14), /* -s */ - MODE_VERBOSITY = BIT(15), /* -V */ - MODE_DUMP_VERSION = BIT(16), /* -v */ + MODE_PROBE_COMPUTE_FLUX_ON_INTERFACE = BIT(5), /* -f */ + MODE_BIN_GREEN = BIT(6), /* -G */ + MODE_GREEN = BIT(7), /* -g */ + MODE_DUMP_HELP = BIT(8), /* -h */ + MODE_PROBE_LIST_COMPUTE_ON_INTERFACE = BIT(9), /* -L */ + MODE_MEDIUM_COMPUTE = BIT(10), /* -m */ + MODE_PROBE_COMPUTE_ON_INTERFACE = BIT(11), /* -P */ + MODE_PROBE_COMPUTE = BIT(12), /* -p */ + MODE_IR_COMPUTE = BIT(13), /* -R */ + MODE_MAP_COMPUTE = BIT(14), /* -S */ + MODE_BOUNDARY_COMPUTE = BIT(15), /* -s */ + MODE_VERBOSITY = BIT(16), /* -V */ + MODE_DUMP_VERSION = BIT(17), /* -v */ GREEN_COMPATIBLE_MODES = MODE_PROBE_COMPUTE @@ -77,7 +78,8 @@ enum stardis_mode { EXT_COMPATIBLE_MODES = GREEN_COMPATIBLE_MODES | MODE_MEDIUM_COMPUTE - | MODE_FLUX_BOUNDARY_COMPUTE, + | MODE_FLUX_BOUNDARY_COMPUTE + | MODE_PROBE_COMPUTE_FLUX_ON_INTERFACE, REGION_COMPUTE_MODES = SURFACE_COMPUTE_MODES @@ -87,7 +89,8 @@ enum stardis_mode { GREEN_COMPATIBLE_MODES | MODE_IR_COMPUTE | SURFACE_COMPUTE_MODES - | MODE_PROBE_LIST_COMPUTE_ON_INTERFACE, + | MODE_PROBE_LIST_COMPUTE_ON_INTERFACE + | MODE_PROBE_COMPUTE_FLUX_ON_INTERFACE, EXCLUSIVE_MODES = COMPUTE_MODES, diff --git a/src/stardis-compute-probe-boundary.c b/src/stardis-compute-probe-boundary.c @@ -235,7 +235,8 @@ check_move_to_solid_boundary const struct description* desc, /* Solid medium in which pos lies */ const size_t iprim, /* Triangle index to which to move */ const double uv[2], /* Triangle coordinates to which to move */ - const double distance) /* Move distance */ + const double distance, /* Move distance */ + const int advice) { struct stardis_vertex vtx = STARDIS_VERTEX_NULL; const char* prefix = ""; @@ -261,7 +262,7 @@ check_move_to_solid_boundary vtx.P[2] = pos[2]; vtx.time = time; delta = desc->d.solid_prog->delta(&vtx, desc->d.solid_prog->prog_data); - prefix = "programmed"; + prefix = "programmed "; break; default: FATAL("Unreachable code.\n"); @@ -271,7 +272,7 @@ check_move_to_solid_boundary logger_print(stardis->logger, LOG_OUTPUT, "Probe was in %ssolid '%s'.\n", prefix, solid_name); - /* The position is closed from the triangle */ + /* The position is close from the triangle */ if(distance < 0.5*delta) { logger_print(stardis->logger, LOG_OUTPUT, "Probe was %g delta from closest boundary.\n", @@ -280,9 +281,9 @@ check_move_to_solid_boundary /* Notice that the position is a little far from the triangle */ } else if(distance < 2*delta) { logger_print(stardis->logger, LOG_WARNING, - "Probe was %g delta from closest boundary. " - "Consider using -p instead of -P.\n", - distance/delta); + "Probe was %g delta from closest boundary.%s\n", + distance/delta, + (advice ? " Consider using -p instead of -P.\n" : "")); /* The position is too far from the triangle */ } else { @@ -316,7 +317,7 @@ check_move_to_fluid_boundary switch(desc->type) { case DESC_MAT_FLUID: prefix = ""; break; - case DESC_MAT_FLUID_PROG: prefix = "programmed"; break; + case DESC_MAT_FLUID_PROG: prefix = "programmed "; break; default: FATAL("Unreachable code.\n"); } @@ -334,6 +335,7 @@ move_to_boundary (struct stardis* stardis, const double pos[3], const double time, /* [s] */ + const int is_probe_temp_computation, size_t* out_iprim, double uv[2]) { @@ -342,7 +344,6 @@ move_to_boundary double proj_pos[3] = {0,0,0}; size_t iprim = 0; - /* Miscellaneous */ size_t nvertices_close = 0; res_T res = RES_OK; @@ -376,7 +377,8 @@ move_to_boundary case DESC_MAT_SOLID: case DESC_MAT_SOLID_PROG: ERR(check_move_to_solid_boundary - (stardis, pos, time, desc, iprim, uv, filter_ctx.distance)); + (stardis, pos, time, desc, iprim, uv, filter_ctx.distance, + is_probe_temp_computation)); break; case DESC_MAT_FLUID: case DESC_MAT_FLUID_PROG: @@ -826,6 +828,91 @@ error: } static res_T +setup_solve_probe_boundary_flux_args + (struct stardis* stardis, + const struct stardis_probe_boundary* probe, + struct sdis_solve_probe_boundary_flux_args* args) +{ + double uv[2] = {0, 0}; + size_t iprim = SIZE_MAX; + unsigned desc_ids[SG3D_PROP_TYPES_COUNT__]; + res_T res = RES_OK; + ASSERT(stardis && probe && args); + + /* Calculate the probe position on the boundary */ + ERR(move_to_boundary(stardis, probe->position, probe->time[0], 0, &iprim, uv)); + + ERR(sg3d_geometry_get_unique_triangle_properties(stardis->geometry.sg3d, + (unsigned)iprim, desc_ids)); + + d3_set(stardis->probe, probe->position); + /* Setup of solve input parameters */ + + args->nrealisations = stardis->samples; + args->iprim = iprim; + d2_set(args->uv, uv); + args->picard_order = stardis->picard_order; + d2_set(args->time_range, stardis->time_range); + args->diff_algo = stardis->diff_algo; + +exit: + return res; +error: + goto exit; +} + +static res_T +compute_single_flux_probe_on_interface + (struct stardis* stardis, + struct time* start, + const struct stardis_probe_boundary* probe) +{ + res_T res = RES_OK; + struct sdis_green_function* green = NULL; + struct sdis_estimator* estimator = NULL; + struct sdis_solve_probe_boundary_flux_args args + = SDIS_SOLVE_PROBE_BOUNDARY_FLUX_ARGS_DEFAULT; + struct dump_path_context dump_ctx; + FILE* stream_r = NULL; + struct time compute_start, compute_end; + + ASSERT(stardis && start && probe); + + ERR(setup_solve_probe_boundary_flux_args(stardis, probe, &args)); + + /* Input random state? */ + READ_RANDOM_STATE(&stardis->rndgen_state_in_filename); + + if(stardis->mpi_initialized && stardis->mpi_rank != 0) { + ERR(sdis_solve_probe_boundary_flux(stardis->sdis_scn, &args, &estimator)); + } else { + struct sdis_mc time = SDIS_MC_NULL; + time_current(&compute_start); + ERR(sdis_solve_probe_boundary_flux(stardis->sdis_scn, &args, &estimator)); + time_current(&compute_end); + ERR(sdis_estimator_get_realisation_time(estimator, &time)); + ERR(print_computation_time + (&time, stardis, start, &compute_start, &compute_end, NULL)); + + ERR(print_single_MC_result(estimator, stardis, stdout)); + + /* TODO: warning if dump paths requested */ + + } + + /* 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; +} + +static res_T setup_solve_probe_boundary_args (struct stardis* stardis, const struct stardis_probe_boundary* probe, @@ -836,10 +923,10 @@ setup_solve_probe_boundary_args size_t iprim = SIZE_MAX; unsigned desc_ids[SG3D_PROP_TYPES_COUNT__]; res_T res = RES_OK; - ASSERT(stardis && probe && args); + ASSERT(stardis && probe && args && (stardis->mode && MODE_MAP_COMPUTE)); /* Calculate the probe position on the boundary */ - ERR(move_to_boundary(stardis, probe->position, probe->time[0], &iprim, uv)); + ERR(move_to_boundary(stardis, probe->position, probe->time[0], 1, &iprim, uv)); ERR(sg3d_geometry_get_unique_triangle_properties(stardis->geometry.sg3d, (unsigned)iprim, desc_ids)); @@ -962,7 +1049,8 @@ compute_probe_on_interface(struct stardis* stardis, struct time* start) res_T res = RES_OK; ASSERT(stardis && start); ASSERT((stardis->mode & MODE_PROBE_COMPUTE_ON_INTERFACE) - || (stardis->mode & MODE_PROBE_LIST_COMPUTE_ON_INTERFACE)); + || (stardis->mode & MODE_PROBE_LIST_COMPUTE_ON_INTERFACE) + || (stardis->mode & MODE_PROBE_COMPUTE_FLUX_ON_INTERFACE)); /* Multiple probes */ if(stardis->mode & MODE_PROBE_LIST_COMPUTE_ON_INTERFACE) { @@ -979,6 +1067,13 @@ compute_probe_on_interface(struct stardis* stardis, struct time* start) probe = darray_probe_boundary_cdata_get(&stardis->probe_boundary_list); res = compute_single_probe_on_interface(stardis, start, probe); if(res != RES_OK) goto error; + } else if(stardis->mode & MODE_PROBE_COMPUTE_FLUX_ON_INTERFACE) { + const struct stardis_probe_boundary* probe = NULL; + ASSERT(darray_probe_boundary_size_get(&stardis->probe_boundary_list) == 1); + + probe = darray_probe_boundary_cdata_get(&stardis->probe_boundary_list); + res = compute_single_flux_probe_on_interface(stardis, start, probe); + if(res != RES_OK) goto error; } exit: diff --git a/src/stardis-compute.c b/src/stardis-compute.c @@ -333,50 +333,6 @@ error: goto end; } -#define READ_RANDOM_STATE(Name) \ - if(!stardis->mpi_initialized || stardis->mpi_rank == 0) { \ - if(str_is_empty(Name)) { \ - /* Force using threefry independently of the default RNG type */ \ - args.rng_type = SSP_RNG_THREEFRY; \ - } else { \ - const char* name = str_cget(Name); \ - stream_r = fopen(name, "r"); \ - if(!stream_r) { \ - res = RES_IO_ERR; \ - logger_print(stardis->logger, LOG_ERROR, \ - "Cannot open generator's state file ('%s').\n", \ - name); \ - goto error; \ - } \ - ERR(ssp_rng_create(stardis->allocator, SSP_RNG_THREEFRY, &args.rng_state)); \ - res = read_random_generator_state(args.rng_state, stream_r); \ - if(res != RES_OK) { \ - logger_print(stardis->logger, LOG_ERROR, \ - "Cannot read random generator's state ('%s').\n", \ - name); \ - goto error; \ - } \ - fclose(stream_r); stream_r = NULL; \ - } \ - } - -#define WRITE_RANDOM_STATE(Name) \ - if(!stardis->mpi_initialized || stardis->mpi_rank == 0) { \ - if(!str_is_empty(Name)) { \ - const char* name = str_cget(Name); \ - stream_r = fopen(name, "wb"); \ - if(!stream_r) { \ - res = RES_IO_ERR; \ - logger_print(stardis->logger, LOG_ERROR, \ - "Cannot write random generator's state ('%s').\n", \ - name); \ - goto error; \ - } \ - ERR(write_random_generator_state(estimator, stream_r)); \ - fclose(stream_r); stream_r = NULL; \ - } \ - } - static res_T compute_probe(struct stardis* stardis, struct time* start) { @@ -1065,9 +1021,6 @@ error: goto end; } -#undef READ_RANDOM_STATE -#undef WRITE_RANDOM_STATE - /******************************************************************************* * Public Functions ******************************************************************************/ @@ -1188,6 +1141,8 @@ stardis_compute ERR(compute_probe_on_interface(stardis, start)); else if(stardis->mode & MODE_PROBE_LIST_COMPUTE_ON_INTERFACE) ERR(compute_probe_on_interface(stardis, start)); + else if(stardis->mode & MODE_PROBE_COMPUTE_FLUX_ON_INTERFACE) + ERR(compute_probe_on_interface(stardis, start)); else if(stardis->mode & MODE_IR_COMPUTE) ERR(compute_camera(stardis, start)); else if(stardis->mode & MODE_MEDIUM_COMPUTE) diff --git a/src/stardis-compute.h b/src/stardis-compute.h @@ -27,6 +27,50 @@ struct str; #define DARRAY_DATA struct sdis_estimator* #include <rsys/dynamic_array.h> +#define READ_RANDOM_STATE(Name) \ + if(!stardis->mpi_initialized || stardis->mpi_rank == 0) { \ + if(str_is_empty(Name)) { \ + /* Force using threefry independently of the default RNG type */ \ + args.rng_type = SSP_RNG_THREEFRY; \ + } else { \ + const char* name = str_cget(Name); \ + stream_r = fopen(name, "r"); \ + if(!stream_r) { \ + res = RES_IO_ERR; \ + logger_print(stardis->logger, LOG_ERROR, \ + "Cannot open generator's state file ('%s').\n", \ + name); \ + goto error; \ + } \ + ERR(ssp_rng_create(stardis->allocator, SSP_RNG_THREEFRY, &args.rng_state)); \ + res = read_random_generator_state(args.rng_state, stream_r); \ + if(res != RES_OK) { \ + logger_print(stardis->logger, LOG_ERROR, \ + "Cannot read random generator's state ('%s').\n", \ + name); \ + goto error; \ + } \ + fclose(stream_r); stream_r = NULL; \ + } \ + } + +#define WRITE_RANDOM_STATE(Name) \ + if(!stardis->mpi_initialized || stardis->mpi_rank == 0) { \ + if(!str_is_empty(Name)) { \ + const char* name = str_cget(Name); \ + stream_r = fopen(name, "wb"); \ + if(!stream_r) { \ + res = RES_IO_ERR; \ + logger_print(stardis->logger, LOG_ERROR, \ + "Cannot write random generator's state ('%s').\n", \ + name); \ + goto error; \ + } \ + ERR(write_random_generator_state(estimator, stream_r)); \ + fclose(stream_r); stream_r = NULL; \ + } \ + } + extern LOCAL_SYM struct sdis_medium* find_medium_by_name (struct stardis* stardis, @@ -47,4 +91,9 @@ compute_probe_on_interface (struct stardis* stardis, struct time* start); +extern LOCAL_SYM res_T +compute_flux_density_boundary + (struct stardis* stardis, + struct time* start); + #endif diff --git a/src/stardis-output.c b/src/stardis-output.c @@ -1690,7 +1690,98 @@ print_single_MC_result else fprintf(stream, "%g %g %lu %lu\n", result.E, result.SE, nfailures, nsamples); break; - case MODE_FLUX_BOUNDARY_COMPUTE: { + + case MODE_PROBE_COMPUTE_FLUX_ON_INTERFACE: + { + enum sdis_estimator_type type; + ERR(sdis_estimator_get_type(estimator, &type)); + ASSERT(type == SDIS_ESTIMATOR_FLUX); + + if(stardis->mode & MODE_EXTENDED_RESULTS) { + if(stardis->time_range[0] == stardis->time_range[1]) + fprintf(stream, "Temperature at [%g, %g, %g] at t=%g = %g K +/- %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 K +/- %g\n", + SPLIT3(stardis->probe), SPLIT2(stardis->time_range), + result.E, /* Expected value */ + result.SE); /* Standard error */ + ERR(sdis_estimator_get_convective_flux(estimator, &result)); + if(stardis->time_range[0] == stardis->time_range[1]) + fprintf(stream, "Convective flux density at [%g, %g, %g] at t=%g = %g W/m² +/- %g\n", + SPLIT3(stardis->probe), stardis->time_range[0], + result.E, /* Expected value */ + result.SE); /* Standard error */ + else + fprintf(stream, + "Convective flux density at [%g, %g, %g] with t in [%g %g] = %g W/m² +/- %g\n", + SPLIT3(stardis->probe), SPLIT2(stardis->time_range), + result.E, /* Expected value */ + result.SE); /* Standard error */ + ERR(sdis_estimator_get_radiative_flux(estimator, &result)); + if(stardis->time_range[0] == stardis->time_range[1]) + fprintf(stream, "Radiative flux density at [%g, %g, %g] at t=%g = %g W/m² +/- %g\n", + SPLIT3(stardis->probe), stardis->time_range[0], + result.E, /* Expected value */ + result.SE); /* Standard error */ + else + fprintf(stream, + "Radiative flux density at [%g, %g, %g] with t in [%g %g] = %g W/m² +/- %g\n", + SPLIT3(stardis->probe), SPLIT2(stardis->time_range), + result.E, /* Expected value */ + result.SE); /* Standard error */ + ERR(sdis_estimator_get_imposed_flux(estimator, &result)); + if(stardis->time_range[0] == stardis->time_range[1]) + fprintf(stream, "Imposed flux density at [%g, %g, %g] at t=%g = %g W/m² +/- %g\n", + SPLIT3(stardis->probe), stardis->time_range[0], + result.E, /* Expected value */ + result.SE); /* Standard error */ + else + fprintf(stream, + "Imposed flux density at [%g, %g, %g] with t in [%g %g] = %g W/m² +/- %g\n", + SPLIT3(stardis->probe), SPLIT2(stardis->time_range), + result.E, /* Expected value */ + result.SE); /* Standard error */ + ERR(sdis_estimator_get_total_flux(estimator, &result)); + if(stardis->time_range[0] == stardis->time_range[1]) + fprintf(stream, "Total flux density at [%g, %g, %g] at t=%g = %g W/m² +/- %g\n", + SPLIT3(stardis->probe), stardis->time_range[0], + result.E, /* Expected value */ + result.SE); /* Standard error */ + else + fprintf(stream, + "Total flux density at [%g, %g, %g] with t in [%g %g] = %g W/m² +/- %g\n", + SPLIT3(stardis->probe), SPLIT2(stardis->time_range), + result.E, /* Expected value */ + result.SE); /* Standard error */ + } else { + fprintf(stream, "%g %g ", result.E, result.SE); /* Temperature */ + ERR(sdis_estimator_get_convective_flux(estimator, &result)); + fprintf(stream, "%g %g ", + result.E, + result.SE); + ERR(sdis_estimator_get_radiative_flux(estimator, &result)); + fprintf(stream, "%g %g ", + result.E, + result.SE); + ERR(sdis_estimator_get_imposed_flux(estimator, &result)); + fprintf(stream, "%g %g ", + result.E, + result.SE); + ERR(sdis_estimator_get_total_flux(estimator, &result)); + fprintf(stream, "%g %g ", + result.E, + result.SE); + fprintf(stream, "%lu %lu\n", nfailures, nsamples); + } + break; + } + + case MODE_FLUX_BOUNDARY_COMPUTE: + { enum sdis_estimator_type type; ERR(sdis_estimator_get_type(estimator, &type)); ASSERT(type == SDIS_ESTIMATOR_FLUX); @@ -1745,13 +1836,13 @@ print_single_MC_result stardis->compute_surface.area * result.SE); /* Standard error */ ERR(sdis_estimator_get_total_flux(estimator, &result)); if(stardis->time_range[0] == stardis->time_range[1]) - fprintf(stream, "Total flux Flux at boundary '%s' at t=%g = %g W +/- %g\n", + fprintf(stream, "Total flux at boundary '%s' at t=%g = %g W +/- %g\n", str_cget(&stardis->solve_name), stardis->time_range[0], stardis->compute_surface.area * result.E, /* Expected value */ stardis->compute_surface.area * result.SE); /* Standard error */ else fprintf(stream, - "Total flux Flux at boundary '%s' with t in [%g %g] = %g W +/- %g\n", + "Total flux at boundary '%s' with t in [%g %g] = %g W +/- %g\n", str_cget(&stardis->solve_name), SPLIT2(stardis->time_range), stardis->compute_surface.area * result.E, /* Expected value */ stardis->compute_surface.area * result.SE); /* Standard error */