stardis-solver

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

commit cbf8ac9885f6dd1683d2400943a234dd1c35292e
parent b0c47badfb9912de9b30acad133ffff213eab30a
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Mon, 25 Oct 2021 17:27:53 +0200

Add the picard1 boundary sub path

Diffstat:
Mcmake/CMakeLists.txt | 1+
Msrc/sdis_heat_path.h | 18++++++++++++++++++
Msrc/sdis_heat_path_boundary.c | 4++++
Msrc/sdis_heat_path_boundary_Xd_fixed_flux.h | 2+-
Msrc/sdis_heat_path_boundary_Xd_solid_fluid.h | 3++-
Asrc/sdis_heat_path_boundary_Xd_solid_fluid_picard1.h | 268+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/sdis_heat_path_boundary_Xd_solid_solid.h | 2+-
Msrc/sdis_heat_path_boundary_c.h | 30++++++++++++++++++++++++------
8 files changed, 319 insertions(+), 9 deletions(-)

diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt @@ -90,6 +90,7 @@ set(SDIS_FILES_INC sdis_heat_path_boundary_Xd.h sdis_heat_path_boundary_Xd_fixed_flux.h sdis_heat_path_boundary_Xd_solid_fluid.h + sdis_heat_path_boundary_Xd_solid_fluid_picard1.h sdis_heat_path_boundary_Xd_solid_solid.h sdis_heat_path_conductive_Xd.h sdis_heat_path_convective_Xd.h diff --git a/src/sdis_heat_path.h b/src/sdis_heat_path.h @@ -19,6 +19,7 @@ #include "sdis.h" #include <rsys/dynamic_array.h> +#include <rsys/dynamic_array_size_t.h> #include <rsys/rsys.h> /* Forward declarations */ @@ -39,7 +40,12 @@ struct temperature_3d; * Heat path data structure ******************************************************************************/ struct sdis_heat_path { + /* List of the path vertices */ struct darray_heat_vertex vertices; + + /* Indices of the vertices that mark a break in the path */ + struct darray_size_t breaks; + enum sdis_heat_path_flag status; }; @@ -99,6 +105,18 @@ heat_path_get_last_vertex(struct sdis_heat_path* path) return darray_heat_vertex_data_get(&path->vertices) + (sz-1); } +static INLINE res_T +heat_path_add_break(struct sdis_heat_path* path) +{ + size_t id; + size_t sz; + ASSERT(path); + sz = darray_heat_vertex_size_get(&path->vertices); + if(sz == 0) return RES_OK; /* Nothing to do */ + id = sz-1; + return darray_size_t_push_back(&path->breaks, &id); +} + /* Generate the dynamic array of heat paths */ #define DARRAY_NAME heat_path #define DARRAY_DATA struct sdis_heat_path diff --git a/src/sdis_heat_path_boundary.c b/src/sdis_heat_path_boundary.c @@ -32,6 +32,10 @@ #define SDIS_XD_DIMENSION 3 #include "sdis_heat_path_boundary_Xd_solid_fluid.h" #define SDIS_XD_DIMENSION 2 +#include "sdis_heat_path_boundary_Xd_solid_fluid_picard1.h" +#define SDIS_XD_DIMENSION 3 +#include "sdis_heat_path_boundary_Xd_solid_fluid_picard1.h" +#define SDIS_XD_DIMENSION 2 #include "sdis_heat_path_boundary_Xd_solid_solid.h" #define SDIS_XD_DIMENSION 3 #include "sdis_heat_path_boundary_Xd_solid_solid.h" diff --git a/src/sdis_heat_path_boundary_Xd_fixed_flux.h b/src/sdis_heat_path_boundary_Xd_fixed_flux.h @@ -30,7 +30,7 @@ ******************************************************************************/ res_T XD(solid_boundary_with_flux_path) - (const struct sdis_scene* scn, + (struct sdis_scene* scn, const struct rwalk_context* ctx, const struct sdis_interface_fragment* frag, const double phi, diff --git a/src/sdis_heat_path_boundary_Xd_solid_fluid.h b/src/sdis_heat_path_boundary_Xd_solid_fluid.h @@ -29,7 +29,7 @@ ******************************************************************************/ res_T XD(solid_fluid_boundary_path) - (const struct sdis_scene* scn, + (struct sdis_scene* scn, const struct rwalk_context* ctx, const struct sdis_interface_fragment* frag, struct XD(rwalk)* rwalk, @@ -79,6 +79,7 @@ XD(solid_fluid_boundary_path) if(solid->type != SDIS_SOLID) { SWAP(struct sdis_medium*, solid, fluid); SWAP(enum sdis_side, solid_side, fluid_side); + ASSERT(fluid->type == SDIS_FLUID); } /* Setup a fragment for the fluid side */ diff --git a/src/sdis_heat_path_boundary_Xd_solid_fluid_picard1.h b/src/sdis_heat_path_boundary_Xd_solid_fluid_picard1.h @@ -0,0 +1,268 @@ +/* Copyright (C) 2016-2021 |Meso|Star> (contact@meso-star.com) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include "sdis_green.h" +#include "sdis_heat_path_boundary_c.h" +#include "sdis_interface_c.h" +#include "sdis_medium_c.h" +#include "sdis_misc.h" +#include "sdis_scene_c.h" + +#include <star/ssp.h> + +#include "sdis_Xd_begin.h" + +/******************************************************************************* + * Helper functions + ******************************************************************************/ +static INLINE res_T +XD(rwalk_get_Tref) + (const struct sdis_scene* scn, + const struct XD(rwalk)* rwalk, + const struct XD(temperature)* T, + double* out_Tref) +{ + double Tref = -1; + res_T res = RES_OK; + ASSERT(rwalk && T && out_Tref); + + if(T->done) { + Tref = T->value; + } else { + struct sdis_interface_fragment frag; + struct sdis_interface* interf = NULL; + ASSERT(!SXD_HIT_NONE(&rwalk->hit)); + + /* Fetch the interface where the random walk ends */ + interf = scene_get_interface(scn, rwalk->hit.prim.prim_id); + ASSERT(rwalk->hit_side!=SDIS_FRONT || interf->medium_front->type==SDIS_FLUID); + ASSERT(rwalk->hit_side!=SDIS_BACK || interf->medium_back->type==SDIS_FLUID); + + /* Fragment on the fluid side of the boundary onto which the rwalk ends */ + XD(setup_interface_fragment) + (&frag, &rwalk->vtx, &rwalk->hit, rwalk->hit_side); + + Tref = interface_side_get_reference_temperature(interf, &frag); + } + + if(Tref < 0) { +#if DIM == 2 + log_err(scn->dev, + "%s: invalid reference temperature `%gK' at the position `%g %g'.\n", + FUNC_NAME, Tref, SPLIT2(rwalk->vtx.P)); +#else + log_err(scn->dev, + "%s: invalid reference temperature `%gK' at the position `%g %g %g'.\n", + FUNC_NAME, Tref, SPLIT3(rwalk->vtx.P)); +#endif + res = RES_BAD_OP_IRRECOVERABLE; + goto error; + } + +exit: + *out_Tref = Tref; + return res; +error: + Tref = -1; + goto exit; +} + +/******************************************************************************* + * Boundary path between a solid and a fluid + ******************************************************************************/ +res_T +XD(solid_fluid_boundary_picard1_path) + (struct sdis_scene* scn, + const struct rwalk_context* ctx, + const struct sdis_interface_fragment* frag, + struct XD(rwalk)* rwalk, + struct ssp_rng* rng, + struct XD(temperature)* T) +{ + /* Input/output arguments of the function used to sample a reinjection */ + struct XD(sample_reinjection_step_args) samp_reinject_step_args = + XD(SAMPLE_REINJECTION_STEP_ARGS_NULL); + struct XD(reinjection_step) reinject_step = + XD(REINJECTION_STEP_NULL); + + /* Temperature and random walk state of the sampled radiative path */ + struct XD(temperature) T_s; + struct XD(rwalk) rwalk_s; + + /* Fragment on the fluid side of the boundary */ + struct sdis_interface_fragment frag_fluid; + + /* Data attached to the boundary */ + struct sdis_interface* interf = NULL; + struct sdis_medium* solid = NULL; + struct sdis_medium* fluid = NULL; + + double h_cond; /* Conductive coefficient */ + double h_conv; /* Convective coefficient */ + double h_radi_hat; /* Radiative coefficient with That */ + double h_hat; /* Sum of h_<conv|cond|rad_hat> */ + double p_conv; /* Convective proba */ + double p_cond; /* Conductive proba */ + + double epsilon; /* Interface emissivity */ + double Tref; /* Reference temperature */ + double Tref_s; /* Reference temperature of the sampled radiative path */ + double lambda; /* Solid conductivity */ + double delta_boundary; /* Orthogonal reinjection dst at the boundary */ + double delta; /* Orthogonal fitted reinjection dst at the boundary */ + + double r; + enum sdis_heat_vertex_type current_vertex_type; + enum sdis_side solid_side = SDIS_SIDE_NULL__; + enum sdis_side fluid_side = SDIS_SIDE_NULL__; + res_T res = RES_OK; + + ASSERT(scn && rwalk && rng && T && ctx); + ASSERT(XD(check_rwalk_fragment_consistency)(rwalk, frag)); + + /* Retrieve the solid and the fluid split by the boundary */ + interf = scene_get_interface(scn, rwalk->hit.prim.prim_id); + solid = interface_get_medium(interf, SDIS_FRONT); + fluid = interface_get_medium(interf, SDIS_BACK); + solid_side = SDIS_FRONT; + fluid_side = SDIS_BACK; + if(solid->type != SDIS_SOLID) { + SWAP(struct sdis_medium*, solid, fluid); + SWAP(enum sdis_side, solid_side, fluid_side); + ASSERT(fluid->type == SDIS_FLUID); + } + + /* Fetch the solid properties */ + lambda = solid_get_thermal_conductivity(solid, &rwalk->vtx); + delta = solid_get_delta(solid, &rwalk->vtx); + + /* Fetch the boundary properties */ + epsilon = interface_side_get_emissivity(interf, &frag_fluid); + Tref = interface_side_get_reference_temperature(interf, &frag_fluid); + + /* Note that the reinjection distance is *FIXED*. It MUST ensure that the + * orthogonal distance from the boundary to the reinjection point is at most + * equal to delta. */ + delta_boundary = sqrt(DIM) * delta; + + /* Sample a reinjection step */ + samp_reinject_step_args.rng = rng; + samp_reinject_step_args.solid = solid; + samp_reinject_step_args.rwalk = rwalk; + samp_reinject_step_args.distance = delta_boundary; + samp_reinject_step_args.side = solid_side; + res = XD(sample_reinjection_step_solid_fluid) + (scn, &samp_reinject_step_args, &reinject_step); + if(res != RES_OK) goto error; + + /* Define the orthogonal dst from the reinjection pos to the interface */ + delta = reinject_step.distance / sqrt(DIM); + + /* Compute the convective, conductive and the upper bound radiative coef */ + h_conv = interface_get_convection_coef(interf, frag); + h_cond = lambda / (delta * scn->fp_to_meter); + h_radi_hat = 4.0 * BOLTZMANN_CONSTANT * ctx->That3 * epsilon; + + /* Compute a global upper bound coefficient */ + h_hat = h_conv + h_cond + h_radi_hat; + + /* Compute the probas to switch in solid, fluid or radiative random walk */ + p_conv = h_conv / h_hat; + p_cond = h_cond / h_hat; + + /* Fetch the current heat vertex type. This will be used below to restart the + * registration of the heat path geometry after a null collision */ + if(ctx->heat_path) { + current_vertex_type = heat_path_get_last_vertex(ctx->heat_path)->type; + } + + /* Null collision */ + for(;;) { + double h_radi; /* Radiative coefficient */ + double p_radi; /* Radiative proba */ + + r = ssp_rng_canonical(rng); + + /* Switch in convective path */ + if(r < p_conv) { + T->func = XD(convective_path); + rwalk->mdm = fluid; + rwalk->hit_side = fluid_side; + break; + } + + /* Switch in conductive path */ + if(r < p_conv + p_cond) { + struct XD(solid_reinjection_args) solid_reinject_args = + XD(SOLID_REINJECTION_ARGS_NULL); + + /* Perform the reinjection into the solid */ + solid_reinject_args.reinjection = &reinject_step; + solid_reinject_args.rwalk_ctx = ctx; + solid_reinject_args.rwalk = rwalk; + solid_reinject_args.rng = rng; + solid_reinject_args.T = T; + solid_reinject_args.fp_to_meter = scn->fp_to_meter; + res = XD(solid_reinjection)(solid, &solid_reinject_args); + if(res != RES_OK) goto error; + break; + } + + /* From there, we know the path is either a radiative path or a + * null-collision */ + + /* Sample a radiative path and get the Tref at its end. + * TODO handle the registration of the path geometry */ + T_s = *T; rwalk_s = *rwalk; + res = XD(radiative_path)(scn, ctx, &rwalk_s, rng, &T_s); + if(res != RES_OK) goto error; + + /* Get the Tref at the end of the candidate radiative path */ + res = XD(rwalk_get_Tref)(scn, &rwalk_s, &T_s, &Tref_s); + if(res != RES_OK) goto error; + + h_radi = BOLTZMANN_CONSTANT * epsilon * + ( Tref*Tref*Tref + + Tref*Tref * Tref_s + + Tref * Tref_s*Tref_s + + Tref_s*Tref_s*Tref_s); + + p_radi = h_radi / h_hat; + if(r < p_conv + p_cond + p_radi) { /* Radiative path */ + *rwalk = rwalk_s; + *T = T_s; + break; + } else if(ctx->heat_path) { + /* Null-collision: the sampled path is rejected. Add a break into the + * heat path geometry and restart it from the current position */ + res = heat_path_add_break(ctx->heat_path); + if(res != RES_OK) goto error; + + res = register_heat_vertex + (ctx->heat_path, &rwalk->vtx, T->value, current_vertex_type); + if(res != RES_OK) goto error; + } + + /* Null-collision, looping at the beginning */ + } + + +exit: + return res; +error: + goto exit; +} + +#include "sdis_Xd_end.h" diff --git a/src/sdis_heat_path_boundary_Xd_solid_solid.h b/src/sdis_heat_path_boundary_Xd_solid_solid.h @@ -30,7 +30,7 @@ ******************************************************************************/ res_T XD(solid_solid_boundary_path) - (const struct sdis_scene* scn, + (struct sdis_scene* scn, const struct rwalk_context* ctx, const struct sdis_interface_fragment* frag, struct XD(rwalk)* rwalk, diff --git a/src/sdis_heat_path_boundary_c.h b/src/sdis_heat_path_boundary_c.h @@ -144,7 +144,7 @@ solid_reinjection_3d ******************************************************************************/ extern LOCAL_SYM res_T solid_boundary_with_flux_path_2d - (const struct sdis_scene* scn, + (struct sdis_scene* scn, const struct rwalk_context* ctx, const struct sdis_interface_fragment* frag, const double phi, @@ -154,7 +154,7 @@ solid_boundary_with_flux_path_2d extern LOCAL_SYM res_T solid_boundary_with_flux_path_3d - (const struct sdis_scene* scn, + (struct sdis_scene* scn, const struct rwalk_context* ctx, const struct sdis_interface_fragment* frag, const double phi, @@ -164,7 +164,7 @@ solid_boundary_with_flux_path_3d extern LOCAL_SYM res_T solid_fluid_boundary_path_2d - (const struct sdis_scene* scn, + (struct sdis_scene* scn, const struct rwalk_context* ctx, const struct sdis_interface_fragment* frag, struct rwalk_2d* rwalk, @@ -173,7 +173,25 @@ solid_fluid_boundary_path_2d extern LOCAL_SYM res_T solid_fluid_boundary_path_3d - (const struct sdis_scene* scn, + (struct sdis_scene* scn, + const struct rwalk_context* ctx, + const struct sdis_interface_fragment* frag, + struct rwalk_3d* rwalk, + struct ssp_rng* rng, + struct temperature_3d* T); + +extern LOCAL_SYM res_T +solid_fluid_boundary_picard1_path_2d + (struct sdis_scene* scn, + const struct rwalk_context* ctx, + const struct sdis_interface_fragment* frag, + struct rwalk_2d* rwalk, + struct ssp_rng* rng, + struct temperature_2d* T); + +extern LOCAL_SYM res_T +solid_fluid_boundary_picard1_path_3d + (struct sdis_scene* scn, const struct rwalk_context* ctx, const struct sdis_interface_fragment* frag, struct rwalk_3d* rwalk, @@ -182,7 +200,7 @@ solid_fluid_boundary_path_3d extern LOCAL_SYM res_T solid_solid_boundary_path_2d - (const struct sdis_scene* scn, + (struct sdis_scene* scn, const struct rwalk_context* ctx, const struct sdis_interface_fragment* frag, struct rwalk_2d* rwalk, @@ -191,7 +209,7 @@ solid_solid_boundary_path_2d extern LOCAL_SYM res_T solid_solid_boundary_path_3d - (const struct sdis_scene* scn, + (struct sdis_scene* scn, const struct rwalk_context* ctx, const struct sdis_interface_fragment* frag, struct rwalk_3d* rwalk,