stardis-solver

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

commit 5cd8799035ee1985539e17f10c612deb994b6576
parent 1c08c544493d3fd94dae13ef1fd10a84e97049e8
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Mon, 11 Mar 2019 15:56:01 +0100

Add the register_paths flag to the boundary temperature solvers

Diffstat:
Msrc/sdis.h | 6++++--
Msrc/sdis_realisation.h | 2++
Msrc/sdis_realisation_Xd.h | 40+++++++++++++++++++++++++++++++++++++---
Msrc/sdis_solve.c | 10++++++----
Msrc/sdis_solve_boundary_Xd.h | 26++++++++++++++++++++++++--
Msrc/sdis_solve_probe_boundary_Xd.h | 26++++++++++++++++++++++++--
Msrc/test_sdis_solve_boundary.c | 88+++++++++++++++++++++++++++++++++++++++++++++++++++----------------------------
7 files changed, 154 insertions(+), 44 deletions(-)

diff --git a/src/sdis.h b/src/sdis.h @@ -855,7 +855,7 @@ sdis_solve_probe const double fp_to_meter, /* Scale from floating point units to meters */ const double ambient_radiative_temperature, /* In Kelvin */ const double reference_temperature, /* In Kelvin */ - const int register_path, /* Combination of enum sdis_heat_path_flag */ + const int register_paths, /* Combination of enum sdis_heat_path_flag */ struct sdis_estimator** estimator); SDIS_API res_T @@ -869,6 +869,7 @@ sdis_solve_probe_boundary const double fp_to_meter, /* Scale from floating point units to meters */ const double ambient_radiative_temperature, /* In Kelvin */ const double reference_temperature, /* In Kelvin */ + const int register_paths, /* Combination of enum sdis_heat_path_flag */ struct sdis_estimator** estimator); SDIS_API res_T @@ -882,6 +883,7 @@ sdis_solve_boundary const double fp_to_meter, /* Scale from floating point units to meters */ const double ambient_radiative_temperature, /* In Kelvin */ const double reference_temperature, /* In Kelvin */ + const int register_paths, /* Combination of enum sdis_heat_path_flag */ struct sdis_estimator** estimator); SDIS_API res_T @@ -931,7 +933,7 @@ sdis_solve_medium const double fp_to_meter, /* Scale from floating point units to meters */ const double ambient_radiative_temperature, /* In Kelvin */ const double reference_temperature, /* In Kelvin */ - const int register_path, /* Combination of enum sdis_heat_path_flag */ + const int register_paths, /* Combination of enum sdis_heat_path_flag */ struct sdis_estimator** estimator); /******************************************************************************* diff --git a/src/sdis_realisation.h b/src/sdis_realisation.h @@ -79,6 +79,7 @@ boundary_realisation_2d const double fp_to_meter, const double ambient_radiative_temperature, const double reference_temperature, + struct sdis_heat_path* heat_path, double* weight); extern LOCAL_SYM res_T @@ -92,6 +93,7 @@ boundary_realisation_3d const double fp_to_meter, const double ambient_radiative_temperature, const double reference_temperature, + struct sdis_heat_path* heat_path, double* weight); extern LOCAL_SYM res_T diff --git a/src/sdis_realisation_Xd.h b/src/sdis_realisation_Xd.h @@ -46,10 +46,15 @@ XD(compute_temperature) size_t istack = 0; #endif /* Maximum accepted #failures before stopping the realisation */ + struct sdis_heat_vertex* heat_vtx = NULL; const size_t MAX_FAILS = 10; res_T res = RES_OK; ASSERT(scn && fp_to_meter > 0 && ctx && rwalk && rng && T); + if(ctx->heat_path && T->func == XD(boundary_path)) { + heat_vtx = heat_path_get_last_vertex(ctx->heat_path); + } + do { /* Save the current random walk state */ const struct XD(rwalk) rwalk_bkp = *rwalk; @@ -71,6 +76,25 @@ XD(compute_temperature) } while(res == RES_BAD_OP && ++nfails < MAX_FAILS); if(res != RES_OK) goto error; + /* Update the type of the first vertex of the random walks that begin on a + * boundary. Indeed, one knows the "right" type of the first vertex only + * after the boundary_path execution that defines the sub path to resolve + * from the submitted boundary position. Note that if the boundary + * temperature is know, the type is let as it. */ + if(heat_vtx && !T->done) { + if(heat_path_get_last_vertex(ctx->heat_path) != heat_vtx) { + /* Path was reinjected into a solid */ + heat_vtx->type = SDIS_HEAT_VERTEX_CONDUCTION; + } else if(T->func == XD(convective_path)) { + heat_vtx->type = SDIS_HEAT_VERTEX_CONVECTION; + } else if(T->func == XD(radiative_path)) { + heat_vtx->type = SDIS_HEAT_VERTEX_RADIATIVE; + } else { + FATAL("Unreachable code.\n"); + } + heat_vtx = NULL; /* Notify that the first vertex is finalized */ + } + } while(!T->done); exit: @@ -131,7 +155,7 @@ XD(probe_realisation) rwalk.vtx.time = time; /* Register the starting position against the heat path */ - type = medium->type == SDIS_SOLID + type = medium->type == SDIS_SOLID ? SDIS_HEAT_VERTEX_CONDUCTION : SDIS_HEAT_VERTEX_CONVECTION; res = register_heat_vertex(heat_path, &rwalk.vtx, 0, type); @@ -189,6 +213,7 @@ XD(boundary_realisation) const double fp_to_meter, const double Tarad, const double Tref, + struct sdis_heat_path* heat_path, double* weight) { struct rwalk_context ctx = RWALK_CONTEXT_NULL; @@ -233,14 +258,23 @@ XD(boundary_realisation) f2_set(rwalk.hit.uv, st); #endif + res = register_heat_vertex(heat_path, &rwalk.vtx, 0/*weight*/, + SDIS_HEAT_VERTEX_CONDUCTION); + if(res != RES_OK) goto error; + + ctx.heat_path = heat_path; ctx.Tarad = Tarad; ctx.Tref3 = Tref*Tref*Tref; res = XD(compute_temperature)(scn, fp_to_meter, &ctx, &rwalk, rng, &T); - if(res != RES_OK) return res; + if(res != RES_OK) goto error; *weight = T.value; - return RES_OK; + +exit: + return res; +error: + goto exit; } res_T diff --git a/src/sdis_solve.c b/src/sdis_solve.c @@ -229,15 +229,16 @@ sdis_solve_probe_boundary const double fp_to_meter, /* Scale from floating point units to meters */ const double Tarad, /* In Kelvin */ const double Tref, /* In Kelvin */ + const int register_paths, /* Combination of enum sdis_heat_path_flag */ struct sdis_estimator** out_estimator) { if(!scn) return RES_BAD_ARG; if(scene_is_2d(scn)) { return solve_probe_boundary_2d(scn, nrealisations, iprim, uv, time_range, - side, fp_to_meter, Tarad, Tref, out_estimator); + side, fp_to_meter, Tarad, Tref, register_paths, out_estimator); } else { return solve_probe_boundary_3d(scn, nrealisations, iprim, uv, time_range, - side, fp_to_meter, Tarad, Tref, out_estimator); + side, fp_to_meter, Tarad, Tref, register_paths, out_estimator); } } @@ -252,15 +253,16 @@ sdis_solve_boundary const double fp_to_meter, /* Scale from floating point units to meters */ const double Tarad, /* In Kelvin */ const double Tref, /* In Kelvin */ + const int register_paths, /* Combination of enum sdis_heat_path_flag */ struct sdis_estimator** out_estimator) { if(!scn) return RES_BAD_ARG; if(scene_is_2d(scn)) { return solve_boundary_2d(scn, nrealisations, primitives, sides, nprimitives, - time_range, fp_to_meter, Tarad, Tref, out_estimator); + time_range, fp_to_meter, Tarad, Tref, register_paths, out_estimator); } else { return solve_boundary_3d(scn, nrealisations, primitives, sides, nprimitives, - time_range, fp_to_meter, Tarad, Tref, out_estimator); + time_range, fp_to_meter, Tarad, Tref, register_paths, out_estimator); } } diff --git a/src/sdis_solve_boundary_Xd.h b/src/sdis_solve_boundary_Xd.h @@ -83,6 +83,7 @@ XD(solve_boundary) const double fp_to_meter, /* Scale from floating point units to meters */ const double Tarad, /* In Kelvin */ const double Tref, /* In Kelvin */ + const int register_paths, /* Combination of enum sdis_heat_path_flag */ struct sdis_estimator** out_estimator) { struct XD(boundary_context) ctx = XD(BOUNDARY_CONTEXT_NULL); @@ -187,6 +188,8 @@ XD(solve_boundary) const int ithread = omp_get_thread_num(); struct ssp_rng* rng = rngs[ithread]; struct accum* accum = &accums[ithread]; + struct sdis_heat_path* pheat_path = NULL; + struct sdis_heat_path heat_path; struct sXd(primitive) prim; enum sdis_side side; size_t iprim; @@ -200,6 +203,11 @@ XD(solve_boundary) time = sample_time(rng, time_range); + if(register_paths) { + heat_path_init(scn->dev->allocator, &heat_path); + pheat_path = &heat_path; + } + /* Sample a position onto the boundary */ #if SDIS_XD_DIMENSION == 2 res_local = s2d_scene_view_sample @@ -225,8 +233,8 @@ XD(solve_boundary) side = sides[prim.prim_id]; /* Invoke the boundary realisation */ - res_local = XD(boundary_realisation) - (scn, rng, iprim, uv, time, side, fp_to_meter, Tarad, Tref, &w); + res_local = XD(boundary_realisation)(scn, rng, iprim, uv, time, side, + fp_to_meter, Tarad, Tref, pheat_path, &w); /* Update the MC accumulators */ if(res_local == RES_OK) { @@ -237,6 +245,20 @@ XD(solve_boundary) ATOMIC_SET(&res, res_local); continue; } + + if(pheat_path) { + pheat_path->status = res_local == RES_OK + ? SDIS_HEAT_PATH_SUCCEED + : SDIS_HEAT_PATH_FAILED; + + /* Check if the path must be saved regarding the register_paths mask */ + if(!(register_paths & (int)pheat_path->status)) { + heat_path_release(pheat_path); + } else { /* Register the sampled path */ + res_local = estimator_add_and_release_heat_path(estimator, pheat_path); + if(res_local != RES_OK) { ATOMIC_SET(&res, res_local); continue; } + } + } } sum_accums(accums, scn->dev->nthreads, &accums[0]); diff --git a/src/sdis_solve_probe_boundary_Xd.h b/src/sdis_solve_probe_boundary_Xd.h @@ -39,6 +39,7 @@ XD(solve_probe_boundary) const double fp_to_meter, /* Scale from floating point units to meters */ const double Tarad, /* In Kelvin */ const double Tref, /* In Kelvin */ + const int register_paths, /* Combination of enum sdis_heat_path_flag */ struct sdis_estimator** out_estimator) { struct sdis_estimator* estimator = NULL; @@ -133,6 +134,8 @@ XD(solve_probe_boundary) const int ithread = omp_get_thread_num(); struct ssp_rng* rng = rngs[ithread]; struct accum* accum = &accums[ithread]; + struct sdis_heat_path* pheat_path = NULL; + struct sdis_heat_path heat_path; double w = NaN; double time; res_T res_local; @@ -141,8 +144,13 @@ XD(solve_probe_boundary) time = sample_time(rng, time_range); - res_local = XD(boundary_realisation) - (scn, rng, iprim, uv, time, side, fp_to_meter, Tarad, Tref, &w); + if(register_paths) { + heat_path_init(scn->dev->allocator, &heat_path); + pheat_path = &heat_path; + } + + res_local = XD(boundary_realisation)(scn, rng, iprim, uv, time, side, + fp_to_meter, Tarad, Tref, pheat_path, &w); if(res_local == RES_OK) { accum->sum += w; accum->sum2 += w*w; @@ -151,6 +159,20 @@ XD(solve_probe_boundary) ATOMIC_SET(&res, res_local); continue; } + + if(pheat_path) { + pheat_path->status = res_local == RES_OK + ? SDIS_HEAT_PATH_SUCCEED + : SDIS_HEAT_PATH_FAILED; + + /* Check if the path must be saved regarding the register_paths mask */ + if(!(register_paths & (int)pheat_path->status)) { + heat_path_release(pheat_path); + } else { /* Register the sampled path */ + res_local = estimator_add_and_release_heat_path(estimator, pheat_path); + if(res_local != RES_OK) { ATOMIC_SET(&res, res_local); continue; } + } + } } if(res != RES_OK) goto error; diff --git a/src/test_sdis_solve_boundary.c b/src/test_sdis_solve_boundary.c @@ -44,6 +44,7 @@ #define UNKNOWN_TEMPERATURE -1 #define N 10000 /* #realisations */ +#define N_dump 10 /* #dumped paths */ #define Tf 310.0 #define Tb 300.0 @@ -168,6 +169,7 @@ check_estimator int main(int argc, char** argv) { + FILE* fp = NULL; struct mem_allocator allocator; struct sdis_data* data = NULL; struct sdis_device* dev = NULL; @@ -199,6 +201,9 @@ main(int argc, char** argv) OK(mem_init_proxy_allocator(&allocator, &mem_default_allocator)); OK(sdis_device_create(NULL, &allocator, SDIS_NTHREADS_DEFAULT, 1, &dev)); + /* Temporary file used to dump heat paths */ + CHK(fp = tmpfile()); + /* Create the fluid medium */ OK(sdis_data_create (dev, sizeof(struct fluid), ALIGNOF(struct fluid), NULL, &data)); @@ -291,35 +296,41 @@ main(int argc, char** argv) uv[1] = 0.3; iprim = 6; - BA(SOLVE(NULL, N, iprim, uv, time_range, F, 1.0, 0, 0, &estimator)); - BA(SOLVE(box_scn, 0, iprim, uv, time_range, F, 1.0, 0, 0, &estimator)); - BA(SOLVE(box_scn, N, 12, uv, time_range, F, 1.0, 0, 0, &estimator)); - BA(SOLVE(box_scn, N, iprim, NULL, time_range, F, 1.0, 0, 0, &estimator)); - BA(SOLVE(box_scn, N, iprim, uv, NULL, F, 1.0, 0, 0, &estimator)); - BA(SOLVE(box_scn, N, iprim, uv, time_range, -1, 1.0, 0, 0, &estimator)); - BA(SOLVE(box_scn, N, iprim, uv, time_range, F, 1.0, 0, 0, NULL)); + BA(SOLVE(NULL, N, iprim, uv, time_range, F, 1.0, 0, 0, 0, &estimator)); + BA(SOLVE(box_scn, 0, iprim, uv, time_range, F, 1.0, 0, 0, 0, &estimator)); + BA(SOLVE(box_scn, N, 12, uv, time_range, F, 1.0, 0, 0, 0, &estimator)); + BA(SOLVE(box_scn, N, iprim, NULL, time_range, F, 1.0, 0, 0, 0, &estimator)); + BA(SOLVE(box_scn, N, iprim, uv, NULL, F, 1.0, 0, 0, 0, &estimator)); + BA(SOLVE(box_scn, N, iprim, uv, time_range, -1, 1.0, 0, 0, 0, &estimator)); + BA(SOLVE(box_scn, N, iprim, uv, time_range, F, 1.0, 0, 0, 0, NULL)); tr[0] = tr[1] = -1; - BA(SOLVE(box_scn, N, iprim, uv, tr, F, 1.0, 0, 0, NULL)); + BA(SOLVE(box_scn, N, iprim, uv, tr, F, 1.0, 0, 0, 0, NULL)); tr[0] = 1; - BA(SOLVE(box_scn, N, iprim, uv, tr, F, 1.0, 0, 0, NULL)); + BA(SOLVE(box_scn, N, iprim, uv, tr, F, 1.0, 0, 0, 0, NULL)); tr[1] = 0; - BA(SOLVE(box_scn, N, iprim, uv, tr, F, 1.0, 0, 0, NULL)); + BA(SOLVE(box_scn, N, iprim, uv, tr, F, 1.0, 0, 0, 0, NULL)); - OK(SOLVE(box_scn, N, iprim, uv, time_range, F, 1.0, 0, 0, &estimator)); + OK(SOLVE(box_scn, N, iprim, uv, time_range, F, 1.0, 0, 0, 0, &estimator)); OK(sdis_scene_get_boundary_position(box_scn, iprim, uv, pos)); printf("Boundary temperature of the box at (%g %g %g) = ", SPLIT3(pos)); check_estimator(estimator, N, ref); OK(sdis_estimator_ref_put(estimator)); + /* Dump paths */ + OK(SOLVE(box_scn, N_dump, iprim, uv, time_range, F, 1.0, 0, 0, + SDIS_HEAT_PATH_ALL, &estimator)); + dump_heat_paths(fp, estimator); + OK(sdis_estimator_ref_put(estimator)); + /* The external fluid cannot have an unknown temperature */ fluid_param->temperature = UNKNOWN_TEMPERATURE; - BA(SOLVE(box_scn, N, iprim, uv, time_range, F, 1.0, 0, 0, &estimator)); + BA(SOLVE(box_scn, N, iprim, uv, time_range, F, 1.0, 0, 0, 0, &estimator)); fluid_param->temperature = Tf; uv[0] = 0.5; iprim = 3; - BA(SOLVE(square_scn, N, 4, uv, time_range, F, 1.0, 0, 0, &estimator)); - OK(SOLVE(square_scn, N, iprim, uv, time_range, F, 1.0, 0, 0, &estimator)); + BA(SOLVE(square_scn, N, 4, uv, time_range, F, 1.0, 0, 0, 0, &estimator)); + OK(SOLVE(square_scn, N, iprim, uv, time_range, F, 1.0, 0, 0, 0, &estimator)); OK(sdis_scene_get_boundary_position(square_scn, iprim, uv, pos)); printf("Boundary temperature of the square at (%g %g) = ", SPLIT2(pos)); check_estimator(estimator, N, ref); @@ -327,8 +338,9 @@ main(int argc, char** argv) /* The external fluid cannot have an unknown temperature */ fluid_param->temperature = UNKNOWN_TEMPERATURE; - BA(SOLVE(square_scn, N, iprim, uv, time_range, F, 1.0, 0, 0, &estimator)); + BA(SOLVE(square_scn, N, iprim, uv, time_range, F, 1.0, 0, 0, 0, &estimator)); fluid_param->temperature = Tf; + #undef F #undef SOLVE @@ -340,39 +352,51 @@ main(int argc, char** argv) #define SOLVE sdis_solve_boundary prims[0] = 6; prims[1] = 7; - BA(SOLVE(NULL, N, prims, sides, 2, time_range, 1.0, 0, 0, &estimator)); - BA(SOLVE(box_scn, 0, prims, sides, 2, time_range, 1.0, 0, 0, &estimator)); - BA(SOLVE(box_scn, N, NULL, sides, 2, time_range, 1.0, 0, 0, &estimator)); - BA(SOLVE(box_scn, N, prims, NULL, 2, time_range, 1.0, 0, 0, &estimator)); - BA(SOLVE(box_scn, N, prims, sides, 0, time_range, 1.0, 0, 0, &estimator)); - BA(SOLVE(box_scn, N, prims, sides, 2, NULL, 1.0, 0, 0, &estimator)); - BA(SOLVE(box_scn, N, prims, sides, 2, time_range, 1.0, 0, 0, NULL)); + BA(SOLVE(NULL, N, prims, sides, 2, time_range, 1.0, 0, 0, 0, &estimator)); + BA(SOLVE(box_scn, 0, prims, sides, 2, time_range, 1.0, 0, 0, 0, &estimator)); + BA(SOLVE(box_scn, N, NULL, sides, 2, time_range, 1.0, 0, 0, 0, &estimator)); + BA(SOLVE(box_scn, N, prims, NULL, 2, time_range, 1.0, 0, 0, 0, &estimator)); + BA(SOLVE(box_scn, N, prims, sides, 0, time_range, 1.0, 0, 0, 0, &estimator)); + BA(SOLVE(box_scn, N, prims, sides, 2, NULL, 1.0, 0, 0, 0, &estimator)); + BA(SOLVE(box_scn, N, prims, sides, 2, time_range, 1.0, 0, 0, 0, NULL)); tr[0] = tr[1] = -1; - BA(SOLVE(box_scn, N, prims, sides, 2, tr, 1.0, 0, 0, NULL)); + BA(SOLVE(box_scn, N, prims, sides, 2, tr, 1.0, 0, 0, 0, NULL)); tr[0] = 1; - BA(SOLVE(box_scn, N, prims, sides, 2, tr, 1.0, 0, 0, NULL)); + BA(SOLVE(box_scn, N, prims, sides, 2, tr, 1.0, 0, 0, 0, NULL)); tr[1] = 0; - BA(SOLVE(box_scn, N, prims, sides, 2, tr, 1.0, 0, 0, NULL)); + BA(SOLVE(box_scn, N, prims, sides, 2, tr, 1.0, 0, 0, 0, NULL)); /* Average temperature on the right side of the box */ - OK(SOLVE(box_scn, N, prims, sides, 2, time_range, 1.0, 0, 0, &estimator)); + OK(SOLVE(box_scn, N, prims, sides, 2, time_range, 1.0, 0, 0, 0, &estimator)); printf("Average temperature of the right side of the box = "); check_estimator(estimator, N, ref); OK(sdis_estimator_ref_put(estimator)); + /* Dump path */ + OK(SOLVE(box_scn, N_dump, prims, sides, 2, time_range, 1.0, 0, 0, + SDIS_HEAT_PATH_ALL, &estimator)); + dump_heat_paths(fp, estimator); + OK(sdis_estimator_ref_put(estimator)); + /* Average temperature on the right side of the square */ prims[0] = 3; sides[0] = SDIS_FRONT; - OK(SOLVE(square_scn, N, prims, sides, 1, time_range, 1.0, 0, 0, &estimator)); + OK(SOLVE(square_scn, N, prims, sides, 1, time_range, 1.0, 0, 0, 0, &estimator)); printf("Average temperature of the right side of the square = "); check_estimator(estimator, N, ref); OK(sdis_estimator_ref_put(estimator)); + /* Dump path */ + OK(SOLVE(square_scn, N_dump, prims, sides, 1, time_range, 1.0, 0, 0, + SDIS_HEAT_PATH_ALL, &estimator)); + dump_heat_paths(fp, estimator); + OK(sdis_estimator_ref_put(estimator)); + /* Check out of bound prims */ prims[0] = 12; - BA(SOLVE(box_scn, N, prims, sides, 2, time_range, 1.0, 0, 0, &estimator)); + BA(SOLVE(box_scn, N, prims, sides, 2, time_range, 1.0, 0, 0, 0, &estimator)); prims[0] = 4; - BA(SOLVE(square_scn, N, prims, sides, 1, time_range, 1.0, 0, 0, &estimator)); + BA(SOLVE(square_scn, N, prims, sides, 1, time_range, 1.0, 0, 0, 0, &estimator)); /* Average temperature on the left+right sides of the box */ prims[0] = 2; @@ -382,7 +406,7 @@ main(int argc, char** argv) ref = (ref + Tb) / 2; - OK(SOLVE(box_scn, N, prims, sides, 4, time_range, 1.0, 0, 0, &estimator)); + OK(SOLVE(box_scn, N, prims, sides, 4, time_range, 1.0, 0, 0, 0, &estimator)); printf("Average temperature of the left+right sides of the box = "); check_estimator(estimator, N, ref); OK(sdis_estimator_ref_put(estimator)); @@ -390,7 +414,7 @@ main(int argc, char** argv) /* Average temperature on the left+right sides of the square */ prims[0] = 1; prims[1] = 3; - OK(SOLVE(square_scn, N, prims, sides, 2, time_range, 1.0, 0, 0, &estimator)); + OK(SOLVE(square_scn, N, prims, sides, 2, time_range, 1.0, 0, 0, 0, &estimator)); printf("Average temperature of the left+right sides of the square = "); check_estimator(estimator, N, ref); OK(sdis_estimator_ref_put(estimator)); @@ -400,6 +424,8 @@ main(int argc, char** argv) OK(sdis_scene_ref_put(square_scn)); OK(sdis_device_ref_put(dev)); + CHK(fclose(fp) == 0); + check_memory_allocator(&allocator); mem_shutdown_proxy_allocator(&allocator); CHK(mem_allocated_size() == 0);