stardis-solver

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

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

Add and test sdis_solve_probe_boundary_green_function

Diffstat:
Msrc/sdis.h | 16++++++++++++++--
Msrc/sdis_green.c | 21+++++++++++++++++++++
Msrc/sdis_green.h | 6++++++
Msrc/sdis_realisation.h | 2++
Msrc/sdis_realisation_Xd.h | 2++
Msrc/sdis_solve.c | 32++++++++++++++++++++++++++------
Msrc/sdis_solve_boundary_Xd.h | 2+-
Msrc/sdis_solve_medium_Xd.h | 11+++++++----
Msrc/sdis_solve_probe_Xd.h | 10++++------
Msrc/sdis_solve_probe_boundary_Xd.h | 89+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------
Msrc/test_sdis_solve_boundary.c | 29++++++++++++++++++++++++++++-
11 files changed, 185 insertions(+), 35 deletions(-)

diff --git a/src/sdis.h b/src/sdis.h @@ -793,7 +793,7 @@ sdis_green_function_for_each_path /* Retrieve the spatio-temporal end point of a path used to estimate the green * function. Note that this point went back in time from the relative - * observation time 0. Its time is thus negative ; its absolute value + * observation time 0. Its time is thus negative; its absolute value * represents the time spent by the path into the system. */ SDIS_API res_T sdis_green_path_get_limit_point @@ -950,7 +950,7 @@ sdis_solve_medium * 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 invocations : others interfaces/media are + * sdis_green_function_solve invocations: others interfaces/media are * definitely registered against the green function as interfaces/media with no * flux/volumic power. * @@ -968,6 +968,18 @@ sdis_solve_probe_green_function struct sdis_green_function** green); SDIS_API res_T +sdis_solve_probe_boundary_green_function + (struct sdis_scene* scn, + const size_t nrealisations, /* #realisations */ + const size_t iprim, /* Identifier of the primitive on which the probe lies */ + const double uv[2], /* Parametric coordinates of the probe onto the primitve */ + const enum sdis_side side, /* Side of iprim on which the probe lies */ + 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_green.c b/src/sdis_green.c @@ -774,6 +774,27 @@ error: } res_T +green_function_redux_and_clear + (struct sdis_green_function* dst, + struct sdis_green_function* greens[], + const size_t ngreens) +{ + size_t i; + res_T res = RES_OK; + ASSERT(dst && greens && ngreens); + + FOR_EACH(i, 0, ngreens) { + res = green_function_merge_and_clear(dst, greens[i]); + if(res != RES_OK) goto error; + } + +exit: + return res; +error: + goto exit; +} + +res_T green_function_finalize (struct sdis_green_function* green, struct ssp_rng_proxy* proxy) diff --git a/src/sdis_green.h b/src/sdis_green.h @@ -42,6 +42,12 @@ green_function_merge_and_clear (struct sdis_green_function* dst, struct sdis_green_function* src); +extern LOCAL_SYM res_T +green_function_redux_and_clear + (struct sdis_green_function* dst, + struct sdis_green_function* greens[], + const size_t ngreens); + /* Finalize the green function state (e.g.: computes the #paths & #failures, * save the rng state, etc.) */ extern LOCAL_SYM res_T 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 green_path_handle* green_path, struct sdis_heat_path* heat_path, double* weight); @@ -93,6 +94,7 @@ boundary_realisation_3d const double fp_to_meter, const double ambient_radiative_temperature, const double reference_temperature, + struct green_path_handle* green_path, struct sdis_heat_path* heat_path, double* weight); diff --git a/src/sdis_realisation_Xd.h b/src/sdis_realisation_Xd.h @@ -213,6 +213,7 @@ XD(boundary_realisation) const double fp_to_meter, const double Tarad, const double Tref, + struct green_path_handle* green_path, struct sdis_heat_path* heat_path, double* weight) { @@ -262,6 +263,7 @@ XD(boundary_realisation) SDIS_HEAT_VERTEX_CONDUCTION); if(res != RES_OK) goto error; + ctx.green_path = green_path; ctx.heat_path = heat_path; ctx.Tarad = Tarad; ctx.Tref3 = Tref*Tref*Tref; diff --git a/src/sdis_solve.c b/src/sdis_solve.c @@ -235,10 +235,32 @@ sdis_solve_probe_boundary 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, register_paths, out_estimator); + side, fp_to_meter, Tarad, Tref, register_paths, NULL, out_estimator); } else { return solve_probe_boundary_3d(scn, nrealisations, iprim, uv, time_range, - side, fp_to_meter, Tarad, Tref, register_paths, out_estimator); + side, fp_to_meter, Tarad, Tref, register_paths, NULL, out_estimator); + } +} + +res_T +sdis_solve_probe_boundary_green_function + (struct sdis_scene* scn, + const size_t nrealisations, /* #realisations */ + const size_t iprim, /* Identifier of the primitive on which the probe lies */ + const double uv[2], /* Parametric coordinates of the probe onto the primitve */ + const enum sdis_side side, /* Side of iprim on which the probe lies */ + 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_probe_boundary_2d(scn, nrealisations, iprim, uv, NULL, + side, fp_to_meter, Tarad, Tref, SDIS_HEAT_PATH_NONE, green, NULL); + } else { + return solve_probe_boundary_3d(scn, nrealisations, iprim, uv, NULL, + side, fp_to_meter, Tarad, Tref, SDIS_HEAT_PATH_NONE, green, NULL); } } @@ -300,16 +322,14 @@ sdis_solve_boundary_flux const double Tref, /* In Kelvin */ struct sdis_estimator** out_estimator) { - res_T res = RES_OK; if(!scn) return RES_BAD_ARG; if(scene_is_2d(scn)) { - res = solve_boundary_flux_2d(scn, nrealisations, primitives, nprimitives, + return solve_boundary_flux_2d(scn, nrealisations, primitives, nprimitives, time_range, fp_to_meter, Tarad, Tref, out_estimator); } else { - res = solve_boundary_flux_3d(scn, nrealisations, primitives, nprimitives, + return solve_boundary_flux_3d(scn, nrealisations, primitives, nprimitives, time_range, fp_to_meter, Tarad, Tref, out_estimator); } - return res; } res_T diff --git a/src/sdis_solve_boundary_Xd.h b/src/sdis_solve_boundary_Xd.h @@ -234,7 +234,7 @@ XD(solve_boundary) /* Invoke the boundary realisation */ res_local = XD(boundary_realisation)(scn, rng, iprim, uv, time, side, - fp_to_meter, Tarad, Tref, pheat_path, &w); + fp_to_meter, Tarad, Tref, NULL, pheat_path, &w); /* Update the MC accumulators */ if(res_local == RES_OK) { diff --git a/src/sdis_solve_medium_Xd.h b/src/sdis_solve_medium_Xd.h @@ -367,12 +367,11 @@ XD(solve_medium) } 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*/ - FOR_EACH(i, 1, scn->dev->nthreads) { /* Merge the per thread green */ - res = green_function_merge_and_clear(green, greens[i]); - if(res != RES_OK) goto error; - } + 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); @@ -399,6 +398,10 @@ exit: if(out_green) *out_green = green; return (res_T)res; error: + if(green) { + SDIS(green_function_ref_put(green)); + green = NULL; + } if(estimator) { SDIS(estimator_ref_put(estimator)); estimator = NULL; diff --git a/src/sdis_solve_probe_Xd.h b/src/sdis_solve_probe_Xd.h @@ -96,15 +96,14 @@ XD(solve_probe) res = scene_get_medium(scn, position, NULL, &medium); if(res != RES_OK) goto error; + /* Create the per thread green function */ if(out_green) { - /* Create the per thread green function */ 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 */ @@ -182,12 +181,11 @@ XD(solve_probe) } 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*/ - FOR_EACH(i, 1, scn->dev->nthreads) { /* Merge the per thread green */ - res = green_function_merge_and_clear(green, greens[i]); - if(res != RES_OK) goto error; - } + 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); diff --git a/src/sdis_solve_probe_boundary_Xd.h b/src/sdis_solve_probe_boundary_Xd.h @@ -40,9 +40,12 @@ XD(solve_probe_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 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; @@ -51,13 +54,21 @@ XD(solve_probe_boundary) ATOMIC res = RES_OK; if(!scn || !nrealisations || nrealisations > INT64_MAX || !uv - || !time_range || time_range[0] < 0 || time_range[1] < time_range[0] - || (time_range[1] > DBL_MAX && time_range[0] != time_range[1]) - || fp_to_meter <= 0 || Tref < 0 || (side != SDIS_FRONT && side != SDIS_BACK) - || !out_estimator) { + || fp_to_meter <= 0 || Tref < 0 || (side != SDIS_FRONT && side != SDIS_BACK)) { + 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; } @@ -123,9 +134,21 @@ XD(solve_probe_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; + } /* Here we go! Launch the Monte Carlo estimation */ omp_set_num_threads((int)scn->dev->nthreads); @@ -134,6 +157,8 @@ XD(solve_probe_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; double w = NaN; @@ -142,15 +167,23 @@ XD(solve_probe_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; } res_local = XD(boundary_realisation)(scn, rng, iprim, uv, time, side, - fp_to_meter, Tarad, Tref, pheat_path, &w); + fp_to_meter, Tarad, Tref, pgreen_path, pheat_path, &w); if(res_local == RES_OK) { accum->sum += w; accum->sum2 += w*w; @@ -177,9 +210,24 @@ XD(solve_probe_boundary) if(res != RES_OK) goto error; /* Setup the estimated temperature */ - sum_accums(accums, scn->dev->nthreads, &accums[0]); - 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); + } + + 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) { @@ -188,11 +236,22 @@ exit: } 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(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: + if(green) { + SDIS(green_function_ref_put(green)); + green = NULL; + } if(estimator) { SDIS(estimator_ref_put(estimator)); estimator = NULL; diff --git a/src/test_sdis_solve_boundary.c b/src/test_sdis_solve_boundary.c @@ -181,6 +181,8 @@ main(int argc, char** argv) struct sdis_scene* box_scn = NULL; struct sdis_scene* square_scn = NULL; struct sdis_estimator* estimator = NULL; + struct sdis_estimator* estimator2 = NULL; + struct sdis_green_function* green = 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; @@ -199,7 +201,7 @@ main(int argc, char** argv) (void)argc, (void)argv; OK(mem_init_proxy_allocator(&allocator, &mem_default_allocator)); - OK(sdis_device_create(NULL, &allocator, SDIS_NTHREADS_DEFAULT, 1, &dev)); + OK(sdis_device_create(NULL, &allocator, SDIS_NTHREADS_DEFAULT, 0, &dev)); /* Temporary file used to dump heat paths */ CHK(fp = tmpfile()); @@ -291,6 +293,7 @@ main(int argc, char** argv) ref = (H*Tf + LAMBDA * Tb) / (H + LAMBDA); #define SOLVE sdis_solve_probe_boundary + #define GREEN sdis_solve_probe_boundary_green_function #define F SDIS_FRONT uv[0] = 0.3; uv[1] = 0.3; @@ -314,7 +317,23 @@ main(int argc, char** argv) 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); + + BA(GREEN(NULL, N, iprim, uv, F, 1, 0, 0, &green)); + BA(GREEN(box_scn, 0, iprim, uv, F, 1, 0, 0, &green)); + BA(GREEN(box_scn, N, 12, uv, F, 1, 0, 0, &green)); + BA(GREEN(box_scn, N, iprim, NULL, F, 1, 0, 0, &green)); + BA(GREEN(box_scn, N, iprim, uv, -1, 1, 0, 0, &green)); + BA(GREEN(box_scn, N, iprim, uv, F, 0, 0, 0, &green)); + BA(GREEN(box_scn, N, iprim, uv, F, 1, 0, 0, NULL)); + + 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); + + OK(sdis_green_function_ref_put(green)); OK(sdis_estimator_ref_put(estimator)); + OK(sdis_estimator_ref_put(estimator2)); /* Dump paths */ OK(SOLVE(box_scn, N_dump, iprim, uv, time_range, F, 1.0, 0, 0, @@ -334,7 +353,15 @@ main(int argc, char** argv) 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); + + 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); + OK(sdis_estimator_ref_put(estimator)); + OK(sdis_estimator_ref_put(estimator2)); + OK(sdis_green_function_ref_put(green)); /* The external fluid cannot have an unknown temperature */ fluid_param->temperature = UNKNOWN_TEMPERATURE;