stardis-solver

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

commit fa403f13a85230402ffb965f0968bb4821aa937c
parent 38603e8f489d1e9c3398a682d0d7979ddc5170c0
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Thu, 12 Apr 2018 15:38:20 +0200

Implement the computation of unknown fluid temperature

The computation actually assumes that the convection coefficient of a
fluid enclosure is constant for the whole enclosure.

Diffstat:
Msrc/sdis_scene_Xd.h | 23++++++++++++++++++-----
Msrc/sdis_scene_c.h | 26++++++++++++++++++++++++++
Msrc/sdis_solve_Xd.h | 144+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------
3 files changed, 174 insertions(+), 19 deletions(-)

diff --git a/src/sdis_scene_Xd.h b/src/sdis_scene_Xd.h @@ -518,6 +518,7 @@ XD(setup_enclosure_geometry)(struct sdis_scene* scn, struct sencXd(enclosure)* e struct sXd(vertex_data) vdata = SXD_VERTEX_DATA_NULL; struct enclosure enc_dummy; struct enclosure* enc_data; + float S, V; unsigned iprim, nprims, nverts; #if DIM == 2 const struct enclosure2d_header* header; @@ -571,10 +572,22 @@ XD(setup_enclosure_geometry)(struct sdis_scene* scn, struct sencXd(enclosure)* e CALL(sXd(mesh_setup_indexed_vertices)(sXd_shape, nprims, XD(enclosure_indices), nverts, &vdata, 1, enc)); #endif - CALL(sXd(scene_create)(sXd_dev, &sXd_scn)); CALL(sXd(scene_attach_shape)(sXd_scn, sXd_shape)); CALL(sXd(scene_view_create)(sXd_scn, SXD_SAMPLE, &enc_data->sXd(view))); + + /* Compute the S/V ratio */ +#if DIM == 2 + CALL(sXd(scene_view_compute_contour_length)(enc_data->sXd(view), &S)); + CALL(sXd(scene_view_compute_area)(enc_data->sXd(view), &V)); +#else + CALL(sXd(scene_view_compute_area)(enc_data->sXd(view), &S)); + CALL(sXd(scene_view_compute_volume)(enc_data->sXd(view), &V)); +#endif + /* The volume of the enclosure is actually negative since Star-Enc ensures + * that the normal of its primitives point outward the enclosure. Take its + * absolute value in order to ensure a postive value. */ + enc_data->S_over_V = S/absf(V); #undef CALL /* Define the identifier of the enclosure primitives in the whole scene */ @@ -600,8 +613,8 @@ error: goto exit; } -/* Build the Star-XD scene view and define its associated data of the fluid - * enclosures */ +/* Build the Star-XD scene view and define its associated data of the finite + * fluid enclosures */ static res_T XD(setup_enclosures)(struct sdis_scene* scn, struct sencXd(descriptor)* desc) { @@ -626,8 +639,8 @@ XD(setup_enclosures)(struct sdis_scene* scn, struct sencXd(descriptor)* desc) mdm = darray_medium_cdata_get(&scn->media)[header->enclosed_medium]; ASSERT(mdm); - /* Silently discard the solid enclosures */ - if(mdm->type == SDIS_MEDIUM_FLUID) { + /* Silently discard the solid and infinite enclosures */ + if(mdm->type == SDIS_MEDIUM_FLUID && !header->is_infinite) { res = XD(setup_enclosure_geometry)(scn, enc); if(res != RES_OK) goto error; } diff --git a/src/sdis_scene_c.h b/src/sdis_scene_c.h @@ -60,6 +60,8 @@ struct enclosure { /* Map the id of the enclosure primitives to their primitive id into the * whole scene */ struct darray_uint local2global; + + double S_over_V; /* in 3D = surface/volume; in 2D = perimeter/area */ }; static INLINE void @@ -69,6 +71,7 @@ enclosure_init(struct mem_allocator* allocator, struct enclosure* enc) enc->s2d_view = NULL; enc->s3d_view = NULL; darray_uint_init(allocator, &enc->local2global); + enc->S_over_V = 0; } static INLINE void @@ -90,6 +93,7 @@ enclosure_copy(struct enclosure* dst, const struct enclosure* src) S2D(scene_view_ref_get(src->s2d_view)); dst->s2d_view = src->s2d_view; } + dst->S_over_V = src->S_over_V; return darray_uint_copy(&dst->local2global, &src->local2global); } @@ -109,6 +113,7 @@ enclosure_copy_and_release(struct enclosure* dst, struct enclosure* src) dst->s2d_view = src->s2d_view; src->s2d_view = NULL; } + dst->S_over_V = src->S_over_V; return RES_OK; } @@ -173,6 +178,27 @@ scene_get_medium const double position[], const struct sdis_medium** medium); +static INLINE void +scene_get_enclosure_ids + (const struct sdis_scene* scn, + const unsigned iprim, + unsigned encs[2]) /* Front and Back enclosure identifiers */ +{ + ASSERT(scn && iprim < darray_prim_prop_size_get(&scn->prim_props)); + ASSERT(encs); + encs[0] = darray_prim_prop_cdata_get(&scn->prim_props)[iprim].front_enclosure; + encs[1] = darray_prim_prop_cdata_get(&scn->prim_props)[iprim].back_enclosure; +} + +static INLINE const struct enclosure* +scene_get_enclosure(struct sdis_scene* scn, const unsigned ienc) +{ + const struct enclosure* enc = NULL; + ASSERT(scn); + enc = htable_enclosure_find(&scn->enclosures, &ienc); + return enc; +} + static FINLINE int scene_is_2d(const struct sdis_scene* scn) { diff --git a/src/sdis_solve_Xd.h b/src/sdis_solve_Xd.h @@ -101,7 +101,7 @@ static const struct XD(rwalk) XD(RWALK_NULL) = { struct XD(temperature) { res_T (*func)/* Next function to invoke in order to compute the temperature */ - (const struct sdis_scene* scn, + (struct sdis_scene* scn, const double fp_to_meter, const struct rwalk_context* ctx, struct XD(rwalk)* rwalk, @@ -114,7 +114,7 @@ static const struct XD(temperature) XD(TEMPERATURE_NULL) = { NULL, 0, 0 }; static res_T XD(boundary_temperature) - (const struct sdis_scene* scn, + (struct sdis_scene* scn, const double fp_to_meter, const struct rwalk_context* ctx, struct XD(rwalk)* rwalk, @@ -123,7 +123,7 @@ XD(boundary_temperature) static res_T XD(solid_temperature) - (const struct sdis_scene* scn, + (struct sdis_scene* scn, const double fp_to_meter, const struct rwalk_context* ctx, struct XD(rwalk)* rwalk, @@ -132,7 +132,7 @@ XD(solid_temperature) static res_T XD(fluid_temperature) - (const struct sdis_scene* scn, + (struct sdis_scene* scn, const double fp_to_meter, const struct rwalk_context* ctx, struct XD(rwalk)* rwalk, @@ -141,7 +141,7 @@ XD(fluid_temperature) static res_T XD(radiative_temperature) - (const struct sdis_scene* scn, + (struct sdis_scene* scn, const double fp_to_meter, const struct rwalk_context* ctx, struct XD(rwalk)* rwalk, @@ -190,7 +190,7 @@ XD(check_rwalk_fragment_consistency) static res_T XD(trace_radiative_path) - (const struct sdis_scene* scn, + (struct sdis_scene* scn, const float ray_dir[3], const double fp_to_meter, const struct rwalk_context* ctx, @@ -308,7 +308,7 @@ error: res_T XD(radiative_temperature) - (const struct sdis_scene* scn, + (struct sdis_scene* scn, const double fp_to_meter, const struct rwalk_context* ctx, struct XD(rwalk)* rwalk, @@ -352,26 +352,142 @@ error: res_T XD(fluid_temperature) - (const struct sdis_scene* scn, + (struct sdis_scene* scn, const double fp_to_meter, const struct rwalk_context* ctx, struct XD(rwalk)* rwalk, struct ssp_rng* rng, struct XD(temperature)* T) { + struct sXd(attrib) attr_P, attr_N; + struct sdis_interface_fragment frag; + const struct sdis_interface* interf; + const struct enclosure* enc; + unsigned enc_ids[2]; + unsigned enc_id; + double rho; /* Volumic mass */ + double hc; /* Convection coef */ + double cp; /* Calorific capacity */ + double mu; + double tau; double tmp; +#if DIM == 2 + float st; +#else + float st[2]; +#endif (void)rng, (void)fp_to_meter, (void)ctx; ASSERT(scn && fp_to_meter > 0 && ctx && rwalk && rng && T); ASSERT(rwalk->mdm->type == SDIS_MEDIUM_FLUID); tmp = fluid_get_temperature(rwalk->mdm, &rwalk->vtx); - if(tmp < 0) { - log_err(scn->dev, "%s: unknown fluid temperature is not supported.\n", + if(tmp >= 0) { + T->value += tmp; + T->done = 1; + return RES_OK; + } + + if(SXD_HIT_NONE(&rwalk->hit)) { /* The path begins in the fluid */ + const float range[2] = {0, FLT_MAX}; + float dir[DIM] = {0}; + float org[DIM]; + + dir[DIM-1] = 1; + fX_set_dX(org, rwalk->vtx.P); + + /* Init the path hit field required to define the current enclosure and + * fetch the interface data */ + SXD(scene_view_trace_ray(scn->sXd(view), org, dir, range, NULL, &rwalk->hit)); + + if(SXD_HIT_NONE(&rwalk->hit)) { + log_err(scn->dev, +"%s: the position %g %g %g lise in the surrounding fluid whose temperature must \n" +"be known.\n", + FUNC_NAME, SPLIT3(rwalk->vtx.P)); + return RES_BAD_OP; + } + } + + /* Setup the fragment of the interface */ + XD(setup_interface_fragment)(&frag, &rwalk->vtx, &rwalk->hit); + + /* Fetch the current interface and its associated enclosures */ + interf = scene_get_interface(scn, rwalk->hit.prim.prim_id); + scene_get_enclosure_ids(scn, rwalk->hit.prim.prim_id, enc_ids); + + /* Define the enclosure identifier of the current medium */ + ASSERT(interf->medium_front != interf->medium_back); + if(rwalk->mdm == interf->medium_front) { + enc_id = enc_ids[0]; + } else { + ASSERT(rwalk->mdm == interf->medium_back); + enc_id = enc_ids[1]; + } + + /* Fetch the enclosure data */ + enc = scene_get_enclosure(scn, enc_id); + if(!enc) { + log_err(scn->dev, +"%s: invalid enclosure. The position %g %g %g may lie in the surrounding fluid.\n", + FUNC_NAME, SPLIT3(rwalk->vtx.P)); + return RES_BAD_OP; + } + + /* Fetch the physical properties */ + hc = interface_get_convection_coef(interf, &frag); + cp = fluid_get_calorific_capacity(rwalk->mdm, &rwalk->vtx); + rho = fluid_get_volumic_mass(rwalk->mdm, &rwalk->vtx); + + /* Sample the time. + * FIXME we assume that hc is constant for the whole enclosure */ + mu = hc / (rho * cp) * enc->S_over_V; + tau = ssp_ran_exp(rng, mu); + rwalk->vtx.time = MMIN(rwalk->vtx.time - tau, 0); + + /* Check the initial condition */ + tmp = fluid_get_temperature(rwalk->mdm, &rwalk->vtx); + if(tmp >= 0) { + T->value += tmp; + T->done = 1; + return RES_OK; + } + + /* The initial condition should be reached */ + if(rwalk->vtx.time <=0) { + log_err(scn->dev, + "%s: undefined initial condition. " + "The time is null but the temperature remains unknown.\n", FUNC_NAME); return RES_BAD_OP; } - T->value += tmp; - T->done = 1; + + /* Uniformly sample the enclosure */ +#if DIM == 2 + SXD(scene_view_sample + (enc->sXd(view), + ssp_rng_canonical_float(rng), + ssp_rng_canonical_float(rng), + &rwalk->hit.prim, + &rwalk->hit.u)); + st = rwalk->hit.u; +#else + SXD(scene_view_sample + (enc->sXd(view), + ssp_rng_canonical_float(rng), + ssp_rng_canonical_float(rng), + ssp_rng_canonical_float(rng), + &rwalk->hit.prim, + rwalk->hit.uv)); + f2_set(st, rwalk->hit.uv); +#endif + rwalk->hit.distance = 0; + SXD(primitive_get_attrib(&rwalk->hit.prim, SXD_POSITION, st, &attr_P)); + SXD(primitive_get_attrib(&rwalk->hit.prim, SXD_GEOMETRY_NORMAL, st, &attr_N)); + dX_set_fX(rwalk->vtx.P, attr_P.value); + fX(set)(rwalk->hit.normal, attr_N.value); + + T->func = XD(boundary_temperature); + rwalk->mdm = NULL; /* The random walk is at an interface between 2 media */ return RES_OK; } @@ -530,7 +646,7 @@ XD(solid_fluid_boundary_temperature) res_T XD(boundary_temperature) - (const struct sdis_scene* scn, + (struct sdis_scene* scn, const double fp_to_meter, const struct rwalk_context* ctx, struct XD(rwalk)* rwalk, @@ -574,7 +690,7 @@ XD(boundary_temperature) res_T XD(solid_temperature) - (const struct sdis_scene* scn, + (struct sdis_scene* scn, const double fp_to_meter, const struct rwalk_context* ctx, struct XD(rwalk)* rwalk,