stardis-solver

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

commit 7db538678420d047796cd092b306de31f860ac4c
parent dcf75a5fddbafcfe70339375f9fc874e0519623a
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Tue, 12 Mar 2019 14:56:11 +0100

Add and test sdis_solve_boundary_green_function

Diffstat:
Msrc/sdis.h | 12++++++++++++
Msrc/sdis_solve.c | 28++++++++++++++++++++++++++--
Msrc/sdis_solve_boundary_Xd.h | 95+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------
Msrc/test_sdis_solve_boundary.c | 47+++++++++++++++++++++++++++++++++++++++++++++--
4 files changed, 161 insertions(+), 21 deletions(-)

diff --git a/src/sdis.h b/src/sdis.h @@ -980,6 +980,18 @@ sdis_solve_probe_boundary_green_function struct sdis_green_function** green); SDIS_API res_T +sdis_solve_boundary_green_function + (struct sdis_scene* scn, + const size_t nrealisations, /* #realisations */ + const size_t primitives[], /* List of boundary primitives to handle */ + const enum sdis_side sides[], /* Per primitive side to consider */ + const size_t nprimitives, /* #primitives */ + 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 */ + struct sdis_green_function** green); + +SDIS_API res_T sdis_solve_medium_green_function (struct sdis_scene* scn, const size_t nrealisations, /* #realisations */ diff --git a/src/sdis_solve.c b/src/sdis_solve.c @@ -281,10 +281,34 @@ sdis_solve_boundary 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, register_paths, out_estimator); + time_range, fp_to_meter, Tarad, Tref, register_paths, NULL, out_estimator); } else { return solve_boundary_3d(scn, nrealisations, primitives, sides, nprimitives, - time_range, fp_to_meter, Tarad, Tref, register_paths, out_estimator); + time_range, fp_to_meter, Tarad, Tref, register_paths, NULL, out_estimator); + } +} + +res_T +sdis_solve_boundary_green_function + (struct sdis_scene* scn, + const size_t nrealisations, /* #realisations */ + const size_t primitives[], /* List of boundary primitives to handle */ + const enum sdis_side sides[], /* Per primitive side to consider */ + const size_t nprimitives, /* #primitives */ + const double fp_to_meter, /* Scale from floating point units to meters */ + const double Tarad, /* In Kelvin */ + const double Tref, /* In Kelvin */ + struct sdis_green_function** green) +{ + if(!scn) return RES_BAD_ARG; + if(scene_is_2d(scn)) { + return solve_boundary_2d(scn, nrealisations, primitives, sides, + nprimitives, NULL, fp_to_meter, Tarad, Tref, SDIS_HEAT_PATH_NONE, green, + NULL); + } else { + return solve_boundary_3d(scn, nrealisations, primitives, sides, + nprimitives, NULL, fp_to_meter, Tarad, Tref, SDIS_HEAT_PATH_NONE, green, + NULL); } } diff --git a/src/sdis_solve_boundary_Xd.h b/src/sdis_solve_boundary_Xd.h @@ -84,6 +84,7 @@ XD(solve_boundary) const double Tarad, /* In Kelvin */ const double Tref, /* In Kelvin */ const int register_paths, /* Combination of enum sdis_heat_path_flag */ + struct sdis_green_function** out_green, struct sdis_estimator** out_estimator) { struct XD(boundary_context) ctx = XD(BOUNDARY_CONTEXT_NULL); @@ -92,6 +93,8 @@ XD(solve_boundary) struct sXd(shape)* shape = NULL; struct sXd(scene_view)* view = NULL; struct sdis_estimator* estimator = NULL; + struct sdis_green_function* green = NULL; + struct sdis_green_function** greens = NULL; struct ssp_rng_proxy* rng_proxy = NULL; struct ssp_rng** rngs = NULL; struct accum* accums = NULL; @@ -101,13 +104,21 @@ XD(solve_boundary) ATOMIC res = RES_OK; if(!scn || !nrealisations || nrealisations > INT64_MAX || !primitives - || !time_range || time_range[0] < 0 || time_range[1] < time_range[0] - || (time_range[1] > DBL_MAX && time_range[0] != time_range[1]) - || !sides || !nprimitives || fp_to_meter < 0 || Tref < 0 - || !out_estimator) { + || !sides || !nprimitives || fp_to_meter <= 0 || Tref < 0) { + res = RES_BAD_ARG; + goto error; + } + if(!out_estimator && !out_green) { res = RES_BAD_ARG; goto error; } + if(out_estimator) { + if(!time_range || time_range[0] < 0 || time_range[1] < time_range[0] + || (time_range[1] > DBL_MAX && time_range[0] != time_range[1])) { + res = RES_BAD_ARG; + goto error; + } + } #if SDIS_XD_DIMENSION == 2 if(scene_is_2d(scn) == 0) { res = RES_BAD_ARG; goto error; } @@ -178,9 +189,21 @@ XD(solve_boundary) accums = MEM_CALLOC(scn->dev->allocator, scn->dev->nthreads, sizeof(*accums)); if(!accums) { res = RES_MEM_ERR; goto error; } + /* Create the per thread green function */ + if(out_green) { + greens = MEM_CALLOC(scn->dev->allocator, scn->dev->nthreads, sizeof(*greens)); + if(!greens) { res = RES_MEM_ERR; goto error; } + FOR_EACH(i, 0, scn->dev->nthreads) { + res = green_function_create(scn->dev, &greens[i]); + if(res != RES_OK) goto error; + } + } + /* Create the estimator */ - res = estimator_create(scn->dev, SDIS_ESTIMATOR_TEMPERATURE, &estimator); - if(res != RES_OK) goto error; + if(out_estimator) { + res = estimator_create(scn->dev, SDIS_ESTIMATOR_TEMPERATURE, &estimator); + if(res != RES_OK) goto error; + } omp_set_num_threads((int)scn->dev->nthreads); #pragma omp parallel for schedule(static) @@ -188,6 +211,8 @@ XD(solve_boundary) const int ithread = omp_get_thread_num(); struct ssp_rng* rng = rngs[ithread]; struct accum* accum = &accums[ithread]; + struct green_path_handle* pgreen_path = NULL; + struct green_path_handle green_path = GREEN_PATH_HANDLE_NULL; struct sdis_heat_path* pheat_path = NULL; struct sdis_heat_path heat_path; struct sXd(primitive) prim; @@ -201,11 +226,19 @@ XD(solve_boundary) if(ATOMIC_GET(&res) != RES_OK) continue; /* An error occurred */ - time = sample_time(rng, time_range); - - if(register_paths) { - heat_path_init(scn->dev->allocator, &heat_path); - pheat_path = &heat_path; + if(!out_green) { + time = sample_time(rng, time_range); + if(register_paths) { + heat_path_init(scn->dev->allocator, &heat_path); + pheat_path = &heat_path; + } + } else { + /* Do not take care of the submitted time when registering the green + * function. Simply takes 0 as relative time */ + time = 0; + res_local = green_function_create_path(greens[ithread], &green_path); + if(res_local != RES_OK) { ATOMIC_SET(&res, res_local); continue; } + pgreen_path = &green_path; } /* Sample a position onto the boundary */ @@ -234,7 +267,7 @@ XD(solve_boundary) /* Invoke the boundary realisation */ res_local = XD(boundary_realisation)(scn, rng, iprim, uv, time, side, - fp_to_meter, Tarad, Tref, NULL, pheat_path, &w); + fp_to_meter, Tarad, Tref, pgreen_path, pheat_path, &w); /* Update the MC accumulators */ if(res_local == RES_OK) { @@ -261,22 +294,46 @@ XD(solve_boundary) } } - sum_accums(accums, scn->dev->nthreads, &accums[0]); - /* Setup the estimated temperature */ - estimator_setup_realisations_count(estimator, nrealisations, accums[0].count); - estimator_setup_temperature(estimator, accums[0].sum, accums[0].sum2); + if(out_estimator) { + struct accum acc; + sum_accums(accums, scn->dev->nthreads, &acc); + estimator_setup_realisations_count(estimator, nrealisations, acc.count); + estimator_setup_temperature(estimator, acc.sum, acc.sum2); + } + + /* Setup the green function */ + if(out_green) { + /* Redux the per thread green function into the green of the 1st thread */ + green = greens[0]; /* Return the green of the 1st thread */ + greens[0] = NULL; /* Make invalid the 1st green for 'on exit' clean up*/ + res = green_function_redux_and_clear(green, greens+1, scn->dev->nthreads-1); + if(res != RES_OK) goto error; + + /* Finalize the estimated green */ + res = green_function_finalize(green, 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]));} + FOR_EACH(i, 0, scn->dev->nthreads) { + if(rngs[i]) SSP(rng_ref_put(rngs[i])); + } MEM_RM(scn->dev->allocator, rngs); } + if(greens) { + FOR_EACH(i, 0, scn->dev->nthreads) { + if(greens[i]) SDIS(green_function_ref_put(greens[i])); + } + MEM_RM(scn->dev->allocator, greens); + } if(accums) MEM_RM(scn->dev->allocator, accums); if(scene) SXD(scene_ref_put(scene)); if(shape) SXD(shape_ref_put(shape)); if(view) SXD(scene_view_ref_put(view)); if(rng_proxy) SSP(rng_proxy_ref_put(rng_proxy)); + if(out_green) *out_green = green; if(out_estimator) *out_estimator = estimator; return (res_T)res; error: @@ -284,6 +341,10 @@ error: SDIS(estimator_ref_put(estimator)); estimator = NULL; } + if(green) { + SDIS(green_function_ref_put(green)); + green = NULL; + } goto exit; } diff --git a/src/test_sdis_solve_boundary.c b/src/test_sdis_solve_boundary.c @@ -329,7 +329,7 @@ main(int argc, char** argv) OK(GREEN(box_scn, N, iprim, uv, F, 1, 0, 0, &green)); check_green_function(green); OK(sdis_green_function_solve(green, time_range, &estimator2)); - check_estimator_eq(estimator, estimator2); + check_estimator(estimator2, N, ref); OK(sdis_green_function_ref_put(green)); OK(sdis_estimator_ref_put(estimator)); @@ -357,7 +357,7 @@ main(int argc, char** argv) OK(GREEN(square_scn, N, iprim, uv, F, 1, 0, 0, &green)); check_green_function(green); OK(sdis_green_function_solve(green, time_range, &estimator2)); - check_estimator_eq(estimator, estimator2); + check_estimator(estimator2, N, ref); OK(sdis_estimator_ref_put(estimator)); OK(sdis_estimator_ref_put(estimator2)); @@ -370,6 +370,7 @@ main(int argc, char** argv) #undef F #undef SOLVE + #undef GREEN sides[0] = SDIS_FRONT; sides[1] = SDIS_FRONT; @@ -377,6 +378,7 @@ main(int argc, char** argv) sides[3] = SDIS_FRONT; #define SOLVE sdis_solve_boundary + #define GREEN sdis_solve_boundary_green_function prims[0] = 6; prims[1] = 7; BA(SOLVE(NULL, N, prims, sides, 2, time_range, 1.0, 0, 0, 0, &estimator)); @@ -397,7 +399,23 @@ main(int argc, char** argv) 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); + + BA(GREEN(NULL, N, prims, sides, 2, 1.0, 0, 0, &green)); + BA(GREEN(box_scn, 0, prims, sides, 2, 1.0, 0, 0, &green)); + BA(GREEN(box_scn, N, NULL, sides, 2, 1.0, 0, 0, &green)); + BA(GREEN(box_scn, N, prims, NULL, 2, 1.0, 0, 0, &green)); + BA(GREEN(box_scn, N, prims, sides, 0, 1.0, 0, 0, &green)); + BA(GREEN(box_scn, N, prims, sides, 2, 0.0, 0, 0, &green)); + BA(GREEN(box_scn, N, prims, sides, 2, 1.0, 0, 0, NULL)); + + OK(GREEN(box_scn, N, prims, sides, 2, 1.0, 0, 0, &green)); + check_green_function(green); + OK(sdis_green_function_solve(green, time_range, &estimator2)); + check_estimator(estimator2, N, ref); + + OK(sdis_green_function_ref_put(green)); OK(sdis_estimator_ref_put(estimator)); + OK(sdis_estimator_ref_put(estimator2)); /* Dump path */ OK(SOLVE(box_scn, N_dump, prims, sides, 2, time_range, 1.0, 0, 0, @@ -411,7 +429,15 @@ main(int argc, char** argv) 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(GREEN(square_scn, N, prims, sides, 1, 1.0, 0, 0, &green)); + check_green_function(green); + OK(sdis_green_function_solve(green, time_range, &estimator2)); + check_estimator(estimator2, N, ref); + + OK(sdis_green_function_ref_put(green)); OK(sdis_estimator_ref_put(estimator)); + OK(sdis_estimator_ref_put(estimator2)); /* Dump path */ OK(SOLVE(square_scn, N_dump, prims, sides, 1, time_range, 1.0, 0, 0, @@ -436,7 +462,15 @@ main(int argc, char** argv) 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(GREEN(box_scn, N, prims, sides, 4, 1.0, 0, 0, &green)); + check_green_function(green); + OK(sdis_green_function_solve(green, time_range, &estimator2)); + check_estimator(estimator2, N, ref); + + OK(sdis_green_function_ref_put(green)); OK(sdis_estimator_ref_put(estimator)); + OK(sdis_estimator_ref_put(estimator2)); /* Average temperature on the left+right sides of the square */ prims[0] = 1; @@ -444,8 +478,17 @@ main(int argc, char** argv) 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(GREEN(square_scn, N, prims, sides, 2, 1.0, 0, 0, &green)); + check_green_function(green); + OK(sdis_green_function_solve(green, time_range, &estimator2)); + check_estimator(estimator2, N, ref); + + OK(sdis_green_function_ref_put(green)); OK(sdis_estimator_ref_put(estimator)); + OK(sdis_estimator_ref_put(estimator2)); #undef SOLVE + #undef GREEN OK(sdis_scene_ref_put(box_scn)); OK(sdis_scene_ref_put(square_scn));