stardis-solver

Solve coupled heat transfers
git clone git://git.meso-star.fr/stardis-solver.git
Log | Files | Refs | README | LICENSE

commit 1d6c1d47a62c5b6ccdf2a275339df7948652a123
parent 81dc3fd6a23f9e5541590932cc286d191bc5ad74
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Fri, 15 Feb 2019 14:57:15 +0100

Test the probe green function with flux and volumic power

Diffstat:
Msrc/sdis.h | 19+++++++++++++++----
Msrc/sdis_green.c | 2+-
Msrc/sdis_heat_path_conductive_Xd.h | 34++++++++++++++++++++++++++++------
Msrc/test_sdis_flux.c | 126+++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------------
Msrc/test_sdis_utils.h | 9---------
Msrc/test_sdis_volumic_power.c | 130+++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------------
6 files changed, 230 insertions(+), 90 deletions(-)

diff --git a/src/sdis.h b/src/sdis.h @@ -686,10 +686,21 @@ sdis_solve_camera * * The caller should ensure that green solvers are invoked on scenes whose data * do not depend on time. Indeed, on green estimation, the time parameter along - * the random walks registers the relative time spent in the system, not an - * absolute time. As a consequence, on green estimation, the media/interfaces - * parameters cannot use this parameter to vary in time. If these data vary in - * time, the behavior of the estimated green function is undefined. + * the random walks registers the relative time spent in the system rather than + * an absolute time. As a consequence, the media/interfaces parameters cannot + * vary in time with respect to an absolute time value. + * + * In addition, the green solvers assumes that the interface fluxes are + * constants in time and space. In the same way the volumic power of the solid + * media must be constant in time and space too. Furthermore, note that only + * the interfaces/media that had a flux/volumic power during green estimation + * can update their flux/volumic power value for subsequent + * sdis_green_function_solve invokations : other interfaces/media are + * definitely registered against the green function as interfaces/media with no + * flux/volumic power. + * + * If the aforementionned assumptions are not ensured by the caller, the + * behavior of the estimated green function is undefined. ******************************************************************************/ SDIS_API res_T sdis_solve_probe_green_function diff --git a/src/sdis_green.c b/src/sdis_green.c @@ -642,7 +642,7 @@ green_path_add_power_term size_t iterm; unsigned id; res_T res = RES_OK; - ASSERT(handle && mdm && vtx && val >= 0); + ASSERT(handle && mdm && vtx); /* Unused position and time: the current implementation of the green function * assumes that the power is constant in space and time per medium. */ diff --git a/src/sdis_heat_path_conductive_Xd.h b/src/sdis_heat_path_conductive_Xd.h @@ -34,6 +34,8 @@ XD(conductive_path) struct XD(temperature)* T) { double position_start[DIM]; + double green_power_factor = 0; + double power_ref = SDIS_VOLUMIC_POWER_NONE; struct sdis_medium* mdm; res_T res = RES_OK; ASSERT(scn && fp_to_meter > 0 && rwalk && rng && T); @@ -51,6 +53,12 @@ XD(conductive_path) /* Save the submitted position */ dX(set)(position_start, rwalk->vtx.P); + if(ctx->green_path) { + /* Retrieve the power of the medium. Use it to check that it is effectively + * constant along the random walk */ + power_ref = solid_get_volumic_power(mdm, &rwalk->vtx); + } + do { /* Solid random walk */ struct get_medium_info info = GET_MEDIUM_INFO_NULL; struct sXd(hit) hit0, hit1; @@ -75,7 +83,7 @@ XD(conductive_path) res = green_path_set_limit_vertex(ctx->green_path, rwalk->mdm, &rwalk->vtx); if(res != RES_OK) goto error; } - goto exit; + break; } /* Fetch solid properties */ @@ -85,6 +93,15 @@ XD(conductive_path) cp = solid_get_calorific_capacity(mdm, &rwalk->vtx); power = solid_get_volumic_power(mdm, &rwalk->vtx); + if(ctx->green_path && power_ref != power) { + log_err(scn->dev, + "%s: invalid non constant volumic power term. Expecting a constant " + "volumic power in time and space on green function estimation.\n", + FUNC_NAME); + res = RES_BAD_ARG; + goto error; + } + #if DIM == 2 /* Sample a direction around 2PI */ ssp_ran_circle_uniform_float(rng, dir0, NULL); @@ -159,11 +176,9 @@ XD(conductive_path) } } - /* Register the power term against the green function */ + /* Register the power term for the green function */ if(ctx->green_path && power != SDIS_VOLUMIC_POWER_NONE) { - res = green_path_add_power_term - (ctx->green_path, mdm, &rwalk->vtx, power_factor); - if(res != RES_OK) goto error; + green_power_factor += power_factor; } /* Sample the time */ @@ -179,7 +194,7 @@ XD(conductive_path) if(tmp >= 0) { T->value += tmp; T->done = 1; - goto exit; + break; } /* The initial condition should have been reached */ log_err(scn->dev, @@ -245,6 +260,13 @@ XD(conductive_path) /* Keep going while the solid random walk does not hit an interface */ } while(SXD_HIT_NONE(&rwalk->hit)); + /* Register the power term for the green function */ + if(ctx->green_path && power_ref != SDIS_VOLUMIC_POWER_NONE) { + res = green_path_add_power_term + (ctx->green_path, mdm, &rwalk->vtx, green_power_factor); + if(res != RES_OK) goto error; + } + T->func = XD(boundary_path); rwalk->mdm = NULL; /* The random walk is at an interface between 2 media */ diff --git a/src/test_sdis_flux.c b/src/test_sdis_flux.c @@ -16,6 +16,7 @@ #include "sdis.h" #include "test_sdis_utils.h" +#include <rsys/clock_time.h> #include <rsys/double3.h> /* @@ -123,13 +124,98 @@ interface_get_flux } /******************************************************************************* + * Helper functions + ******************************************************************************/ +static void +solve(struct sdis_scene* scn, const double pos[]) +{ + char dump[128]; + struct time t0, t1, t2; + struct sdis_estimator* estimator; + struct sdis_estimator* estimator2; + struct sdis_green_function* green; + struct sdis_mc T; + size_t nreals; + size_t nfails; + double ref; + const double time_range[2] = {INF, INF}; + enum sdis_scene_dimension dim; + ASSERT(scn && pos); + + ref = T0 + (1 - pos[0]) * PHI/LAMBDA; + + time_current(&t0); + OK(sdis_solve_probe(scn, N, pos, time_range, 1.0, 0, 0, &estimator)); + time_sub(&t0, time_current(&t1), &t0); + time_dump(&t0, TIME_ALL, NULL, dump, sizeof(dump)); + + OK(sdis_estimator_get_realisation_count(estimator, &nreals)); + OK(sdis_estimator_get_failure_count(estimator, &nfails)); + OK(sdis_estimator_get_temperature(estimator, &T)); + + OK(sdis_scene_get_dimension(scn, &dim)); + + switch(dim) { + case SDIS_SCENE_2D: + printf("Temperature at (%g %g) = %g ~ %g +/- %g\n", + SPLIT2(pos), ref, T.E, T.SE); + break; + case SDIS_SCENE_3D: + printf("Temperature at (%g %g %g) = %g ~ %g +/- %g\n", + SPLIT3(pos), ref, T.E, T.SE); + break; + default: FATAL("Unreachable code.\n"); break; + } + printf("#failures = %lu/%lu\n", (unsigned long)nfails, (unsigned long)N); + printf("Elapsed time = %s\n\n", dump); + + CHK(nfails + nreals == N); + CHK(nfails < N/1000); + CHK(eq_eps(T.E, ref, T.SE*3)); + + time_current(&t0); + OK(sdis_solve_probe_green_function(scn, N, pos, 1.0, 0, 0, &green)); + time_current(&t1); + OK(sdis_green_function_solve(green, time_range, &estimator2)); + time_current(&t2); + + OK(sdis_estimator_get_realisation_count(estimator2, &nreals)); + OK(sdis_estimator_get_failure_count(estimator2, &nfails)); + OK(sdis_estimator_get_temperature(estimator2, &T)); + + switch(dim) { + case SDIS_SCENE_2D: + printf("Green temperature at (%g %g) = %g ~ %g +/- %g\n", + SPLIT2(pos), ref, T.E, T.SE); + break; + case SDIS_SCENE_3D: + printf("Green temperature at (%g %g %g) = %g ~ %g +/- %g\n", + SPLIT3(pos), ref, T.E, T.SE); + break; + default: FATAL("Unreachable code.\n"); break; + } + printf("#failures = %lu/%lu\n", (unsigned long)nfails, (unsigned long)N); + time_sub(&t0, &t1, &t0); + time_dump(&t0, TIME_ALL, NULL, dump, sizeof(dump)); + printf("Green estimation time = %s\n", dump); + time_sub(&t1, &t2, &t1); + time_dump(&t1, TIME_ALL, NULL, dump, sizeof(dump)); + printf("Green solve time = %s\n\n", dump); + + check_estimator_eq(estimator, estimator2); + + OK(sdis_estimator_ref_put(estimator)); + OK(sdis_estimator_ref_put(estimator2)); + OK(sdis_green_function_ref_put(green)); +} + +/******************************************************************************* * Test ******************************************************************************/ int main(int argc, char** argv) { struct mem_allocator allocator; - struct sdis_mc T = SDIS_MC_NULL; struct sdis_data* data = NULL; struct sdis_device* dev = NULL; struct sdis_medium* fluid = NULL; @@ -139,7 +225,6 @@ main(int argc, char** argv) struct sdis_interface* interf_phi = NULL; struct sdis_scene* box_scn = NULL; struct sdis_scene* square_scn = NULL; - struct sdis_estimator* estimator = NULL; struct sdis_fluid_shader fluid_shader = DUMMY_FLUID_SHADER; struct sdis_solid_shader solid_shader = DUMMY_SOLID_SHADER; struct sdis_interface_shader interf_shader = SDIS_INTERFACE_SHADER_NULL; @@ -147,10 +232,6 @@ main(int argc, char** argv) struct sdis_interface* square_interfaces[4/*#segments*/]; struct interf* interf_props = NULL; double pos[3]; - double time_range[2] = { INF, INF }; - double ref; - size_t nreals; - size_t nfails; (void)argc, (void)argv; OK(mem_init_proxy_allocator(&allocator, &mem_default_allocator)); @@ -230,34 +311,12 @@ main(int argc, char** argv) OK(sdis_interface_ref_put(interf_T0)); OK(sdis_interface_ref_put(interf_phi)); + /* Solve */ d3_splat(pos, 0.25); - ref = T0 + (1 - pos[0]) * PHI/LAMBDA; - - /* Solve in 3D */ - OK(sdis_solve_probe(box_scn, N, pos, time_range, 1.0, 0, 0, &estimator)); - OK(sdis_estimator_get_realisation_count(estimator, &nreals)); - OK(sdis_estimator_get_failure_count(estimator, &nfails)); - OK(sdis_estimator_get_temperature(estimator, &T)); - OK(sdis_estimator_ref_put(estimator)); - printf("Temperature of the box at (%g %g %g) = %g ~ %g +/- %g\n", - SPLIT3(pos), ref, T.E, T.SE); - printf("#failures = %lu/%lu\n", (unsigned long)nfails, (unsigned long)N); - CHK(nfails + nreals == N); - CHK(nfails < N/1000); - CHK(eq_eps(T.E, ref, T.SE*3)); - - /* Solve in 2D */ - OK(sdis_solve_probe(square_scn, N, pos, time_range, 1.0, 0, 0, &estimator)); - OK(sdis_estimator_get_realisation_count(estimator, &nreals)); - OK(sdis_estimator_get_failure_count(estimator, &nfails)); - OK(sdis_estimator_get_temperature(estimator, &T)); - OK(sdis_estimator_ref_put(estimator)); - printf("Temperature of the square at (%g %g) = %g ~ %g +/- %g\n", - SPLIT2(pos), ref, T.E, T.SE); - printf("#failures = %lu/%lu\n", (unsigned long)nfails, (unsigned long)N); - CHK(nfails + nreals == N); - CHK(nfails < N/1000); - CHK(eq_eps(T.E, ref, T.SE*3)); + printf(">> Box scene\n"); + solve(box_scn, pos); + printf(">> Square Scene\n"); + solve(square_scn, pos); OK(sdis_scene_ref_put(box_scn)); OK(sdis_scene_ref_put(square_scn)); @@ -267,5 +326,4 @@ main(int argc, char** argv) mem_shutdown_proxy_allocator(&allocator); CHK(mem_allocated_size() == 0); return 0; - } diff --git a/src/test_sdis_utils.h b/src/test_sdis_utils.h @@ -244,7 +244,6 @@ check_estimator_eq (const struct sdis_estimator* e1, const struct sdis_estimator* e2) { struct sdis_mc mc1, mc2; - size_t n1, n2; enum sdis_estimator_type type1, type2; ASSERT(e1 && e2); @@ -252,14 +251,6 @@ check_estimator_eq OK(sdis_estimator_get_type(e2, &type2)); CHK(type1 == type2); - OK(sdis_estimator_get_realisation_count(e1, &n1)); - OK(sdis_estimator_get_realisation_count(e2, &n2)); - CHK(n1 == n2); - - OK(sdis_estimator_get_failure_count(e1, &n1)); - OK(sdis_estimator_get_failure_count(e2, &n2)); - CHK(n1 == n2); - OK(sdis_estimator_get_temperature(e1, &mc1)); OK(sdis_estimator_get_temperature(e2, &mc2)); CHK(mc1.E + mc1.SE >= mc2.E - mc2.SE); diff --git a/src/test_sdis_volumic_power.c b/src/test_sdis_volumic_power.c @@ -16,6 +16,7 @@ #include "sdis.h" #include "test_sdis_utils.h" +#include <rsys/clock_time.h> #include <rsys/double3.h> #include <rsys/math.h> @@ -145,13 +146,100 @@ interface_get_convection_coef } /******************************************************************************* + * Helper functions + ******************************************************************************/ +static void +solve(struct sdis_scene* scn, const double pos[]) +{ + char dump[128]; + struct time t0, t1, t2; + struct sdis_estimator* estimator; + struct sdis_estimator* estimator2; + struct sdis_green_function* green; + struct sdis_mc T; + size_t nreals; + size_t nfails; + double x; + double ref; + const double time_range[2] = {INF, INF}; + enum sdis_scene_dimension dim; + ASSERT(scn && pos); + + x = pos[0] - 0.5; + ref = P0 / (2*LAMBDA) * (1.0/4.0 - x*x) + T0; + + time_current(&t0); + OK(sdis_solve_probe(scn, N, pos, time_range, 1.0, 0, 0, &estimator)); + time_sub(&t0, time_current(&t1), &t0); + time_dump(&t0, TIME_ALL, NULL, dump, sizeof(dump)); + + OK(sdis_estimator_get_realisation_count(estimator, &nreals)); + OK(sdis_estimator_get_failure_count(estimator, &nfails)); + OK(sdis_estimator_get_temperature(estimator, &T)); + + OK(sdis_scene_get_dimension(scn, &dim)); + + switch(dim) { + case SDIS_SCENE_2D: + printf("Temperature at (%g %g) = %g ~ %g +/- %g\n", + SPLIT2(pos), ref, T.E, T.SE); + break; + case SDIS_SCENE_3D: + printf("Temperature at (%g %g %g) = %g ~ %g +/- %g\n", + SPLIT3(pos), ref, T.E, T.SE); + break; + default: FATAL("Unreachable code.\n"); break; + } + printf("#failures = %lu/%lu\n", (unsigned long)nfails, (unsigned long)N); + printf("Elapsed time = %s\n\n", dump); + + CHK(nfails + nreals == N); + CHK(nfails < N/1000); + CHK(eq_eps(T.E, ref, T.SE*3)); + + time_current(&t0); + OK(sdis_solve_probe_green_function(scn, N, pos, 1.0, 0, 0, &green)); + time_current(&t1); + OK(sdis_green_function_solve(green, time_range, &estimator2)); + time_current(&t2); + + OK(sdis_estimator_get_realisation_count(estimator2, &nreals)); + OK(sdis_estimator_get_failure_count(estimator2, &nfails)); + OK(sdis_estimator_get_temperature(estimator2, &T)); + + switch(dim) { + case SDIS_SCENE_2D: + printf("Green temperature at (%g %g) = %g ~ %g +/- %g\n", + SPLIT2(pos), ref, T.E, T.SE); + break; + case SDIS_SCENE_3D: + printf("Green temperature at (%g %g %g) = %g ~ %g +/- %g\n", + SPLIT3(pos), ref, T.E, T.SE); + break; + default: FATAL("Unreachable code.\n"); break; + } + printf("#failures = %lu/%lu\n", (unsigned long)nfails, (unsigned long)N); + time_sub(&t0, &t1, &t0); + time_dump(&t0, TIME_ALL, NULL, dump, sizeof(dump)); + printf("Green estimation time = %s\n", dump); + time_sub(&t1, &t2, &t1); + time_dump(&t1, TIME_ALL, NULL, dump, sizeof(dump)); + printf("Green solve time = %s\n\n", dump); + + check_estimator_eq(estimator, estimator2); + + OK(sdis_estimator_ref_put(estimator)); + OK(sdis_estimator_ref_put(estimator2)); + OK(sdis_green_function_ref_put(green)); +} + +/******************************************************************************* * Test ******************************************************************************/ int main(int argc, char** argv) { struct mem_allocator allocator; - struct sdis_mc T = SDIS_MC_NULL; struct sdis_data* data = NULL; struct sdis_device* dev = NULL; struct sdis_medium* fluid = NULL; @@ -161,7 +249,6 @@ main(int argc, char** argv) struct sdis_interface* interf_T0 = NULL; struct sdis_scene* box_scn = NULL; struct sdis_scene* square_scn = NULL; - struct sdis_estimator* estimator = NULL; struct sdis_fluid_shader fluid_shader = DUMMY_FLUID_SHADER; struct sdis_solid_shader solid_shader = DUMMY_SOLID_SHADER; struct sdis_interface_shader interf_shader = SDIS_INTERFACE_SHADER_NULL; @@ -170,11 +257,6 @@ main(int argc, char** argv) struct interf* interf_props = NULL; struct solid* solid_props = NULL; double pos[3]; - double time_range[2] = { INF, INF }; - double x; - double ref; - size_t nreals; - size_t nfails; (void)argc, (void)argv; OK(mem_init_proxy_allocator(&allocator, &mem_default_allocator)); @@ -263,36 +345,12 @@ main(int argc, char** argv) OK(sdis_interface_ref_put(interf_adiabatic)); OK(sdis_interface_ref_put(interf_T0)); + /* Solve */ d3_splat(pos, 0.25); - x = pos[0] - 0.5; - ref = P0 / (2*LAMBDA) * (1.0/4.0 - x*x) + T0; - - /* Solve in 3D */ - OK(sdis_solve_probe(box_scn, N, pos, time_range, 1.0, 0, 0, &estimator)); - OK(sdis_estimator_get_realisation_count(estimator, &nreals)); - OK(sdis_estimator_get_failure_count(estimator, &nfails)); - CHK(nfails + nreals == N); - OK(sdis_estimator_get_temperature(estimator, &T)); - OK(sdis_estimator_ref_put(estimator)); - printf("Temperature of the box at (%g %g %g) = %g ~ %g +/- %g\n", - SPLIT3(pos), ref, T.E, T.SE); - printf("#failures = %lu/%lu\n", (unsigned long)nfails, (unsigned long)N); - CHK(nfails + nreals == N); - CHK(nfails < N/1000); - CHK(eq_eps(T.E, ref, 3*T.SE)); - - /* Solve in 2D */ - OK(sdis_solve_probe(square_scn, N, pos, time_range, 1.0, 0, 0, &estimator)); - OK(sdis_estimator_get_realisation_count(estimator, &nreals)); - OK(sdis_estimator_get_failure_count(estimator, &nfails)); - OK(sdis_estimator_get_temperature(estimator, &T)); - OK(sdis_estimator_ref_put(estimator)); - printf("Temperature of the square at (%g %g) = %g ~ %g +/- %g\n", - SPLIT2(pos), ref, T.E, T.SE); - printf("#failures = %lu/%lu\n", (unsigned long)nfails, (unsigned long)N); - CHK(nfails + nreals == N); - CHK(nfails < N/1000); - CHK(eq_eps(T.E, ref, 3*T.SE)); + printf(">> Box scene\n"); + solve(box_scn, pos); + printf(">> Square scene\n"); + solve(square_scn, pos); OK(sdis_scene_ref_put(box_scn)); OK(sdis_scene_ref_put(square_scn));