stardis-solver

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

commit dade59464e632ada0b90f7b87cb01b13ba8da8ca
parent ef35ef9c486e8bfe3a7b2d46d48153264f032a1d
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Wed, 30 May 2018 12:35:41 +0200

Handle the 2D reinjection pattern for solid boundaries with fixed flux

Diffstat:
Msrc/sdis_solve_Xd.h | 126+++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------------
Msrc/test_sdis_flux.c | 4++--
Msrc/test_sdis_volumic_power3_2d.c | 1+
Msrc/test_sdis_volumic_power4_2d.c | 1+
4 files changed, 95 insertions(+), 37 deletions(-)

diff --git a/src/sdis_solve_Xd.h b/src/sdis_solve_Xd.h @@ -636,7 +636,6 @@ XD(solid_fluid_boundary_temperature) /* Sample a reinjection direction */ XD(sample_reinjection_dir)(rwalk, rng, dir); - fX(normalize)(dir, dir); if(solid == mdm_back) fX(minus)(dir, dir); /* Trace dir to adjust the reinjection distance */ @@ -644,7 +643,7 @@ XD(solid_fluid_boundary_temperature) f2(range, 0, (float)delta_boundary*RAY_RANGE_MAX_SCALE); SXD(scene_view_trace_ray(scn->sXd(view), pos, dir, range, &rwalk->hit, &hit)); - /* Adjuste the deltab boundary to the hit distance */ + /* Adjust the delta boundary to the hit distance */ delta_boundary = MMIN(delta_boundary, hit.distance); /* Define the orthogonal distance from the reinjection pos to the interface */ delta = delta_boundary / sqrt(2.0); @@ -696,6 +695,91 @@ XD(solid_fluid_boundary_temperature) } } +static void +XD(solid_boundary_with_flux_temperature) + (const struct sdis_scene* scn, + const double fp_to_meter, + const struct rwalk_context* ctx, + const struct sdis_interface_fragment* frag, + const double phi, + struct XD(rwalk)* rwalk, + struct ssp_rng* rng, + struct XD(temperature)* T) +{ + const struct sdis_interface* interf = NULL; + const struct sdis_medium* mdm = NULL; + double lambda; + double delta; + double delta_boundary; + double delta_in_meter; + double power; + struct sXd(hit) hit; + float pos[DIM]; + float dir[DIM]; + float range[2]; + ASSERT(frag && phi != SDIS_FLUX_NONE); + ASSERT(XD(check_rwalk_fragment_consistency)(rwalk, frag)); + (void)ctx; + + /* Fetch current interface */ + interf = scene_get_interface(scn, rwalk->hit.prim.prim_id); + ASSERT(phi == interface_side_get_flux(interf, frag)); + + /* Fetch incoming solid */ + mdm = interface_get_medium(interf, frag->side); + ASSERT(mdm->type == SDIS_SOLID); + + /* Fetch medium properties */ + lambda = solid_get_thermal_conductivity(mdm, &rwalk->vtx); + delta = solid_get_delta(mdm, &rwalk->vtx); + + /* Compute the reinjection distance. It MUST ensure that the orthogonal + * distance from the boundary to the point to chalenge is equal to delta. */ + delta_boundary = delta * sqrt(2.0); + + /* Sample a reinjection direction */ + XD(sample_reinjection_dir)(rwalk, rng, dir); + if(frag->side == SDIS_BACK) fX(minus)(dir, dir); + + /* Trace dir to adjust the reinjection distance wrt to the geometry */ + fX_set_dX(pos, rwalk->vtx.P); + f2(range, 0, (float)delta_boundary*RAY_RANGE_MAX_SCALE); + SXD(scene_view_trace_ray(scn->sXd(view), pos, dir, range, &rwalk->hit, &hit)); + + /* Adjust the delta boundary to the hit distance */ + delta_boundary = MMIN(delta_boundary, hit.distance); + + /* Define the orthogonal distance from the reinjection pos to the interface */ + delta = delta_boundary / sqrt(2.0); + + /* Update the temperature. Note that we use delta and not delta_boundary */ + delta_in_meter = delta*fp_to_meter; + T->value += phi * delta_in_meter / lambda; + + /* Handle the volumic power */ + power = solid_get_volumic_power(mdm, &rwalk->vtx); + if(power != SDIS_VOLUMIC_POWER_NONE) { + double tmp; + delta_in_meter = delta_boundary * fp_to_meter; + tmp = power * delta_in_meter * delta_in_meter / (2.0 * DIM * lambda); + T->value += tmp; + } + + /* Reinject into the solid */ + XD(move_pos)(rwalk->vtx.P, dir, (float)delta_boundary); + if(hit.distance == delta_boundary) { + T->func = XD(boundary_temperature); + rwalk->mdm = NULL; + rwalk->hit = hit; + rwalk->hit_side = fX(dot)(hit.normal, dir) < 0 ? SDIS_FRONT : SDIS_BACK; + } else { + T->func = XD(solid_temperature); + rwalk->mdm = mdm; + rwalk->hit = SXD_HIT_NULL; + rwalk->hit_side = SDIS_SIDE_NULL__; + } +} + res_T XD(boundary_temperature) (const struct sdis_scene* scn, @@ -731,43 +815,15 @@ XD(boundary_temperature) /* Check if the boundary flux is known. Note that actually, only solid media * can have a flux as limit condition */ mdm = interface_get_medium(interf, frag.side); - if(sdis_medium_get_type(mdm) == SDIS_SOLID) { + if(sdis_medium_get_type(mdm) == SDIS_SOLID ) { const double phi = interface_side_get_flux(interf, &frag); - if(phi != SDIS_FLUX_NONE) { /* FIXME */ -#if 1 - FATAL("Not implemented yet\n"); -#else - double lambda = solid_get_thermal_conductivity(mdm, &rwalk->vtx); - double delta_b = solid_get_delta_boundary(mdm, &rwalk->vtx); - double delta_b_in_meter = delta_b * fp_to_meter; - float pos[3]; - float range[2]; - float dir[3]; - - /* Update the temperature */ - T->value += phi * delta_b_in_meter / lambda; - - /* Ensure that the normal points toward the solid */ - fX(normalize)(dir, rwalk->hit.normal); - if(frag.side == SDIS_BACK) fX(minus)(dir, dir); - - /* "Reinject" the random walk into the solid */ - fX_set_dX(pos, rwalk->vtx.P); - range[0] = 0, range[1] = (float)delta_b*RAY_RANGE_MAX_SCALE; - SXD(scene_view_trace_ray - (scn->sXd(view), pos, dir, range, &rwalk->hit, &rwalk->hit)); - if(!SXD_HIT_NONE(&rwalk->hit)) delta_b = rwalk->hit.distance * 0.5; - XD(move_pos)(rwalk->vtx.P, dir, (float)delta_b); - - /* Switch in solid random walk */ - T->func = XD(solid_temperature); - rwalk->hit = SXD_HIT_NULL; - rwalk->hit_side = SDIS_SIDE_NULL__; - rwalk->mdm = mdm; + if(phi != SDIS_FLUX_NONE) { + XD(solid_boundary_with_flux_temperature) + (scn, fp_to_meter, ctx, &frag, phi, rwalk, rng, T); return RES_OK; -#endif } } + mdm_front = interface_get_medium(interf, SDIS_FRONT); mdm_back = interface_get_medium(interf, SDIS_BACK); diff --git a/src/test_sdis_flux.c b/src/test_sdis_flux.c @@ -306,7 +306,7 @@ main(int argc, char** argv) 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(eq_eps(T.E, ref, T.SE*2)); + CHK(eq_eps(T.E, ref, T.SE*3)); /* Solve in 2D */ CHK(sdis_solve_probe(square_scn, N, pos, INF, 1.0, 0, 0, &estimator) == RES_OK); @@ -318,7 +318,7 @@ main(int argc, char** argv) 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(eq_eps(T.E, ref, T.SE*2.0)); + CHK(eq_eps(T.E, ref, T.SE*3)); CHK(sdis_scene_ref_put(box_scn) == RES_OK); CHK(sdis_scene_ref_put(square_scn) == RES_OK); diff --git a/src/test_sdis_volumic_power3_2d.c b/src/test_sdis_volumic_power3_2d.c @@ -449,6 +449,7 @@ main(int argc, char** argv) CHK(sdis_estimator_get_temperature(estimator, &T) == RES_OK); printf("Temperature at (%g %g) = %g ~ %g +/- %g [%g, %g]\n", SPLIT2(pos), Tref, T.E, T.SE, T.E-3*T.SE, T.E+3*T.SE); + CHK(eq_eps(T.E, Tref, T.SE*3)); CHK(sdis_estimator_ref_put(estimator) == RES_OK); CHK(sdis_scene_ref_put(scn) == RES_OK); diff --git a/src/test_sdis_volumic_power4_2d.c b/src/test_sdis_volumic_power4_2d.c @@ -323,6 +323,7 @@ main(int argc, char** argv) CHK(sdis_estimator_get_temperature(estimator, &T) == RES_OK); printf("Temperature at (%g %g) = %g ~ %g +/- %g\n", SPLIT2(pos), Tref, T.E, T.SE); + CHK(eq_eps(T.E, Tref, T.SE*3)); CHK(sdis_estimator_ref_put(estimator) == RES_OK); CHK(sdis_scene_ref_put(scn) == RES_OK);