stardis-solver

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

commit 2f14e21128dcc9abf777292619c8ab45afbe191d
parent a7f6b5a129924c0e6e598402cbb8a1d83ebd04e4
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Wed, 22 Jun 2022 14:03:02 +0200

Merge remote-tracking branch 'origin/feature_flux_with_conv_and_rad' into develop

Diffstat:
Mcmake/CMakeLists.txt | 1+
Msrc/sdis.h | 4++--
Msrc/sdis_heat_path_boundary_Xd.h | 15---------------
Msrc/sdis_heat_path_boundary_Xd_c.h | 44++++++++++++++++++++++++++++++++++++++++++++
Msrc/sdis_heat_path_boundary_Xd_solid_fluid_picard1.h | 20++++++++++++++++++--
Msrc/sdis_heat_path_boundary_Xd_solid_fluid_picardN.h | 41+++++++++++++++++++++++++++++++++++++++++
Msrc/sdis_heat_path_boundary_c.h | 31++++++++++++++++++++++++++++++-
Msrc/sdis_interface.c | 9+--------
Msrc/sdis_medium_c.h | 2+-
Asrc/test_sdis_flux2.c | 542+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/test_sdis_volumic_power.c | 2+-
11 files changed, 681 insertions(+), 30 deletions(-)

diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt @@ -212,6 +212,7 @@ if(NOT NO_TEST) new_test(test_sdis_data) new_test(test_sdis_device) new_test(test_sdis_flux) + new_test(test_sdis_flux2) new_test(test_sdis_interface) new_test(test_sdis_medium) new_test(test_sdis_picard) diff --git a/src/sdis.h b/src/sdis.h @@ -279,7 +279,7 @@ enum sdis_heat_path_flag { SDIS_HEAT_PATH_NONE = 0 }; -/* Vertex of heat path v*/ +/* Vertex of heat path */ struct sdis_heat_vertex { double P[3]; double time; @@ -407,7 +407,7 @@ struct sdis_scene_create_args { size_t nprimitives; /* #primitives, i.e. #segments or #triangles */ size_t nvertices; /* #vertices */ - double fp_to_meter; /* Scale factor used to convert 1.0 in 1 meter */ + double fp_to_meter; /* Scale factor used to convert a float in meter */ struct sdis_ambient_radiative_temperature trad; /* Ambient radiative temp */ /* Min/max temperature used to linearise the radiative temperature */ diff --git a/src/sdis_heat_path_boundary_Xd.h b/src/sdis_heat_path_boundary_Xd.h @@ -39,7 +39,6 @@ XD(boundary_path) struct sdis_interface* interf = NULL; struct sdis_medium* mdm_front = NULL; struct sdis_medium* mdm_back = NULL; - struct sdis_medium* mdm = NULL; double tmp; res_T res = RES_OK; ASSERT(scn && ctx && rwalk && rng && T); @@ -70,20 +69,6 @@ XD(boundary_path) goto exit; } - /* Check if the boundary flux is known. Note that currently, 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) { - const double phi = interface_side_get_flux(interf, &frag); - if(phi != SDIS_FLUX_NONE) { - res = XD(solid_boundary_with_flux_path) - (scn, ctx, &frag, phi, rwalk, rng, T); - if(res != RES_OK) goto error; - - goto exit; - } - } - mdm_front = interface_get_medium(interf, SDIS_FRONT); mdm_back = interface_get_medium(interf, SDIS_BACK); diff --git a/src/sdis_heat_path_boundary_Xd_c.h b/src/sdis_heat_path_boundary_Xd_c.h @@ -872,4 +872,48 @@ error: goto exit; } +res_T +XD(handle_net_flux) + (const struct sdis_scene* scn, + const struct handle_net_flux_args* args, + struct XD(temperature)* T) +{ + double flux_term; + double phi; + res_T res = RES_OK; + CHK(scn && T); + CHK(args->interf && args->frag); + CHK(args->h_cond >= 0); + CHK(args->h_conv >= 0); + CHK(args->h_radi >= 0); + CHK(args->h_cond + args->h_conv + args->h_radi > 0); + + phi = interface_side_get_flux(args->interf, args->frag); + if(phi == SDIS_FLUX_NONE) goto exit; /* No flux. Do nothig */ + + if(args->picard_order > 1 && phi != 0) { + log_err(scn->dev, + "%s: invalid flux '%g' W/m^2. Could not manage a flux != 0 when the " + "picard order is not equal to 1; Picard order is currently set to %lu.\n", + FUNC_NAME, phi, (unsigned long)args->picard_order); + res = RES_BAD_ARG; + goto error; + } + + flux_term = 1.0 / (args->h_cond + args->h_conv + args->h_radi); + T->value += phi * flux_term; + + /* Register the net flux term */ + if(args->green_path) { + res = green_path_add_flux_term + (args->green_path, args->interf, args->frag, flux_term); + if(res != RES_OK) goto error; + } + +exit: + return res; +error: + goto exit; +} + #include "sdis_Xd_end.h" diff --git a/src/sdis_heat_path_boundary_Xd_solid_fluid_picard1.h b/src/sdis_heat_path_boundary_Xd_solid_fluid_picard1.h @@ -51,7 +51,7 @@ XD(check_Tref) } if(Tref > scn->tmax) { log_err(scn->dev, - "%s: invalid maximum temperature `%gK'. The reference temperature `%gK'" + "%s: invalid maximum temperature `%gK'. The reference temperature `%gK' " "at the position `"STR_VECX"' is greater than this temperature.\n", func_name, scn->tmax, Tref, SPLITX(pos)); return RES_BAD_OP_IRRECOVERABLE; @@ -119,6 +119,9 @@ XD(solid_fluid_boundary_picard1_path) struct ssp_rng* rng, struct XD(temperature)* T) { + /* Input argument used to handle the net flux */ + struct handle_net_flux_args handle_net_flux_args = HANDLE_NET_FLUX_ARGS_NULL; + /* 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); @@ -150,6 +153,7 @@ XD(solid_fluid_boundary_picard1_path) double lambda; /* Solid conductivity */ double delta_boundary; /* Orthogonal reinjection dst at the boundary */ double delta; /* Orthogonal fitted reinjection dst at the boundary */ + double delta_m; /* delta in meter */ double r; struct sdis_heat_vertex hvtx = SDIS_HEAT_VERTEX_NULL; @@ -209,10 +213,11 @@ XD(solid_fluid_boundary_picard1_path) /* Define the orthogonal dst from the reinjection pos to the interface */ delta = reinject_step.distance / sqrt(DIM); + delta_m = delta * scn->fp_to_meter; /* 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_cond = lambda / delta_m; h_radi_hat = 4.0 * BOLTZMANN_CONSTANT * ctx->That3 * epsilon; /* Compute a global upper bound coefficient */ @@ -222,6 +227,17 @@ XD(solid_fluid_boundary_picard1_path) p_conv = h_conv / h_hat; p_cond = h_cond / h_hat; + /* Handle the net flux if any */ + handle_net_flux_args.interf = interf; + handle_net_flux_args.frag = frag; + handle_net_flux_args.green_path = ctx->green_path; + handle_net_flux_args.picard_order = get_picard_order(ctx); + handle_net_flux_args.h_cond = h_cond; + handle_net_flux_args.h_conv = h_conv; + handle_net_flux_args.h_radi = h_radi_hat; + res = XD(handle_net_flux)(scn, &handle_net_flux_args, T); + if(res != RES_OK) goto error; + /* Fetch the last registered heat path vertex */ if(ctx->heat_path) hvtx = *heat_path_get_last_vertex(ctx->heat_path); diff --git a/src/sdis_heat_path_boundary_Xd_solid_fluid_picardN.h b/src/sdis_heat_path_boundary_Xd_solid_fluid_picardN.h @@ -26,6 +26,41 @@ #include "sdis_Xd_begin.h" /******************************************************************************* + * Non generic helper functions + ******************************************************************************/ +#ifndef SDIS_HEAT_PATH_BOUNDARY_XD_SOLID_FLUID_PICARD_N_H +#define SDIS_HEAT_PATH_BOUNDARY_XD_SOLID_FLUID_PICARD_N_H + +static INLINE res_T +check_net_flux + (struct sdis_scene* scn, + const struct sdis_interface* interf, + const struct sdis_interface_fragment* frag, + const size_t picard_order) +{ + double phi; + res_T res = RES_OK; + ASSERT(scn && interf && frag && picard_order > 1); + + phi = interface_side_get_flux(interf, frag); + if(phi != SDIS_FLUX_NONE && phi != 0) { + log_err(scn->dev, + "%s: invalid flux '%g' W/m^2. Could not manage a flux != 0 when the " + "picard order is not equal to 1; Picard order is currently set to %lu.\n", + FUNC_NAME, phi, (unsigned long)picard_order); + res = RES_BAD_ARG; + goto error; + } + +exit: + return res; +error: + goto exit; +} + +#endif /* SDIS_HEAT_PATH_BOUNDARY_XD_SOLID_FLUID_PICARD_N_H */ + +/******************************************************************************* * Generic helper functions ******************************************************************************/ static INLINE res_T @@ -139,6 +174,7 @@ XD(solid_fluid_boundary_picardN_path) ASSERT(scn && rwalk && rng && T && ctx); ASSERT(XD(check_rwalk_fragment_consistency)(rwalk, frag)); + /* Fetch the Min/max temperature */ Tmin = ctx->Tmin; Tmin2 = ctx->Tmin2; @@ -159,6 +195,11 @@ XD(solid_fluid_boundary_picardN_path) ASSERT(fluid->type == SDIS_FLUID); } + /* Check that no net flux is set for this interface since the provided + * picardN algorithm does not handle it */ + res = check_net_flux(scn, interf, frag, get_picard_order(ctx)); + if(res != RES_OK) goto error; + /* Setup a fragment for the fluid side */ frag_fluid = *frag; frag_fluid.side = fluid_side; diff --git a/src/sdis_heat_path_boundary_c.h b/src/sdis_heat_path_boundary_c.h @@ -68,7 +68,7 @@ SAMPLE_REINJECTION_STEP_ARGS_NULL_3d = SAMPLE_REINJECTION_STEP_ARGS_NULL___3d; #define REINJECTION_STEP_NULL___2d {S2D_HIT_NULL__, {0,0}, 0} #define REINJECTION_STEP_NULL___3d {S3D_HIT_NULL__, {0,0,0}, 0} -static const struct reinjection_step_2d +static const struct reinjection_step_2d REINJECTION_STEP_NULL_2d = REINJECTION_STEP_NULL___2d; static const struct reinjection_step_3d REINJECTION_STEP_NULL_3d = REINJECTION_STEP_NULL___3d; @@ -140,6 +140,35 @@ solid_reinjection_3d struct solid_reinjection_args_3d* args); /******************************************************************************* + * Handle net flux + ******************************************************************************/ +struct handle_net_flux_args { + struct sdis_interface* interf; + const struct sdis_interface_fragment* frag; + struct green_path_handle* green_path; + + size_t picard_order; + double h_cond; /* Convective coefficient, i.e. lambda/delta */ + double h_conv; /* Condutive coefficient */ + double h_radi; /* Radiative coefficient */ +}; +#define HANDLE_NET_FLUX_ARGS_NULL__ {NULL,NULL,NULL,0,0,0,0} +static const struct handle_net_flux_args HANDLE_NET_FLUX_ARGS_NULL = + HANDLE_NET_FLUX_ARGS_NULL__; + +extern LOCAL_SYM res_T +handle_net_flux_2d + (const struct sdis_scene* scn, + const struct handle_net_flux_args* args, + struct temperature_2d* T); + +extern LOCAL_SYM res_T +handle_net_flux_3d + (const struct sdis_scene* scn, + const struct handle_net_flux_args* args, + struct temperature_3d* T); + +/******************************************************************************* * Boundary sub-paths ******************************************************************************/ extern LOCAL_SYM res_T diff --git a/src/sdis_interface.c b/src/sdis_interface.c @@ -73,6 +73,7 @@ check_interface_shader FOR_EACH(i, 0, 2) { switch(type[i]) { + case SDIS_FLUID: /* No constraint */ break; case SDIS_SOLID: if(shaders[i]->emissivity || shaders[i]->specular_fraction @@ -84,14 +85,6 @@ check_interface_shader caller_name); } break; - case SDIS_FLUID: - if(shaders[i]->flux) { - log_warn(dev, - "%s: the interface side toward a fluid can't have a flux property. " - "The shader's pointer function for this attribute should be NULL.\n", - caller_name); - } - break; default: FATAL("Unreachable code.\n"); break; } } diff --git a/src/sdis_medium_c.h b/src/sdis_medium_c.h @@ -176,7 +176,7 @@ fluid_get_properties /******************************************************************************* * Solid local functions ******************************************************************************/ -DEFINE_MDM_CHK_PROP_FUNC(solid, calorific_capacity,0, INF, 0, 1) +DEFINE_MDM_CHK_PROP_FUNC(solid, calorific_capacity, 0, INF, 0, 1) DEFINE_MDM_CHK_PROP_FUNC(solid, thermal_conductivity, 0, INF, 0, 1) DEFINE_MDM_CHK_PROP_FUNC(solid, volumic_mass, 0, INF, 0, 1) DEFINE_MDM_CHK_PROP_FUNC(solid, delta, 0, INF, 0, 1) diff --git a/src/test_sdis_flux2.c b/src/test_sdis_flux2.c @@ -0,0 +1,542 @@ +/* Copyright (C) 2016-2022 |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.h" +#include "test_sdis_utils.h" + +#define UNKNOWN_TEMPERATURE -1 + +/* This test consists in solving the temperature profile in a solid slab + * surrounded by two different convective and radiative temperatures. The + * conductivity of the solid material is known, as well as its thickness. A net + * flux is fixed on the left side of the slab. + * + * + * Y ////(0.1,1,1) 280K + * | +----------+-------+ (1.1,1,1) + * o--- X /##########/'E=1 /| + * / +----------+-------+ | + * Z /_ |##########|*' _\ | | + * ---> \ \ E=1|##########|*'/ / |280K + * 320K-> \__/ |##########|*'\__/ | | + * ---> 330K |##########|*'290K | | + * --\|##########|*+.... |.+ + * 10000W.m^-2 --/|##########|/ |/ + * (-1,-1,-1) +----------+-------+ + * (0,-1,-1)/////// 280K + * + */ + +enum interface_type { + ADIABATIC, + FIXED_TEMPERATURE, + SOLID_FLUID_WITH_FLUX, + SOLID_FLUID, + INTERFACES_COUNT__ +}; + +struct probe { + double x; + double time; + double ref; /* Analytically computed temperature */ +}; + +/******************************************************************************* + * Geometry + ******************************************************************************/ +struct geometry { + const double* positions; + const size_t* indices; + struct sdis_interface** interfaces; +}; + +static const double vertices_3d[12/*#vertices*/*3/*#coords per vertex*/] = { + 0.0,-1.0,-1.0, + 0.1,-1.0,-1.0, + 0.0, 1.0,-1.0, + 0.1, 1.0,-1.0, + 0.0,-1.0, 1.0, + 0.1,-1.0, 1.0, + 0.0, 1.0, 1.0, + 0.1, 1.0, 1.0, + 1.1,-1.0,-1.0, + 1.1, 1.0,-1.0, + 1.1,-1.0, 1.0, + 1.1, 1.0, 1.0 +}; +static const size_t nvertices_3d = sizeof(vertices_3d) / (sizeof(double)*3); + +static const size_t indices_3d[22/*#triangles*/*3/*#indices per triangle*/] = { + 0, 2, 1, 1, 2, 3, /* Solid -Z */ + 0, 4, 2, 2, 4, 6, /* Solid -X */ + 4, 5, 6, 6, 5, 7, /* Solid +Z */ + 3, 7, 1, 1, 7, 5, /* Solid +X */ + 2, 6, 3, 3, 6, 7, /* Solid +Y */ + 0, 1, 4, 4, 1, 5, /* Solid -Y */ + + 1, 3, 8, 8, 3, 9, /* Right fluid -Z */ + 5, 10, 7, 7, 10, 11, /* Right fluid +Z */ + 9, 11, 8, 8, 11, 10, /* Right fluid +X */ + 3, 7, 9, 9, 7, 11, /* Right fluid +Y */ + 1, 8, 5, 5, 8, 10 /* Right fluid -Y */ +}; +static const size_t nprimitives_3d = sizeof(indices_3d) / (sizeof(size_t)*3); + +static void +get_indices_3d(const size_t itri, size_t ids[3], void* ctx) +{ + struct geometry* geom = ctx; + CHK(ctx != NULL); + ids[0] = geom->indices[itri*3+0]; + ids[1] = geom->indices[itri*3+1]; + ids[2] = geom->indices[itri*3+2]; +} + +static void +get_position_3d(const size_t ivert, double pos[3], void* ctx) +{ + struct geometry* geom = ctx; + CHK(ctx != NULL); + pos[0] = geom->positions[ivert*3+0]; + pos[1] = geom->positions[ivert*3+1]; + pos[2] = geom->positions[ivert*3+2]; +} + +static void +get_interface(const size_t iprim, struct sdis_interface** bound, void* ctx) +{ + struct geometry* geom = ctx; + CHK(ctx != NULL); + *bound = geom->interfaces[iprim]; +} + +/******************************************************************************* + * Solid media + ******************************************************************************/ +struct solid { + double lambda; + double rho; + double cp; + double volumic_power; +}; + +static double +solid_get_calorific_capacity + (const struct sdis_rwalk_vertex* vtx, struct sdis_data* data) +{ + const struct solid* solid = sdis_data_cget(data); + CHK(vtx && solid); + return solid->cp; +} + +static double +solid_get_thermal_conductivity + (const struct sdis_rwalk_vertex* vtx, struct sdis_data* data) +{ + const struct solid* solid = sdis_data_cget(data); + CHK(vtx && solid); + return solid->lambda; +} + +static double +solid_get_volumic_mass + (const struct sdis_rwalk_vertex* vtx, struct sdis_data* data) +{ + const struct solid* solid = sdis_data_cget(data); + CHK(vtx && solid); + return solid->rho; +} + +static double +solid_get_delta + (const struct sdis_rwalk_vertex* vtx, struct sdis_data* data) +{ + CHK(vtx && data); + return 0.005; +} + +static double +solid_get_temperature + (const struct sdis_rwalk_vertex* vtx, struct sdis_data* data) +{ + const struct solid* solid = sdis_data_cget(data); + CHK(vtx && solid); + + if(vtx->time > 0) { + return UNKNOWN_TEMPERATURE; + } else { + /* The initial temperature is a linear profile between T1 and T2, where T1 + * and T2 are the temperature on the left and right slab boundary, + * respectively. */ + const double T1 = 306.334; + const double T2 = 294.941; + const double u = CLAMP(vtx->P[0] / 0.1, 0.0, 1.0); + return u*(T2 - T1) + T1; + } +} + +static void +create_solid + (struct sdis_device* dev, + const struct solid* solid_props, + struct sdis_medium** solid) +{ + struct sdis_data* data = NULL; + struct sdis_solid_shader shader = SDIS_SOLID_SHADER_NULL; + CHK(dev && solid_props && solid); + + OK(sdis_data_create + (dev, sizeof(struct solid), ALIGNOF(struct solid), NULL, &data)); + memcpy(sdis_data_get(data), solid_props, sizeof(struct solid)); + shader.calorific_capacity = solid_get_calorific_capacity; + shader.thermal_conductivity = solid_get_thermal_conductivity; + shader.volumic_mass = solid_get_volumic_mass; + shader.delta = solid_get_delta; + shader.temperature = solid_get_temperature; + OK(sdis_solid_create(dev, &shader, data, solid)); + OK(sdis_data_ref_put(data)); +} + +/******************************************************************************* + * Fluid media + ******************************************************************************/ +struct fluid { + double temperature; +}; + +static double +fluid_get_temperature + (const struct sdis_rwalk_vertex* vtx, struct sdis_data* data) +{ + const struct fluid* fluid = sdis_data_cget(data); + CHK(vtx && fluid); + return fluid->temperature; +} + +static void +create_fluid + (struct sdis_device* dev, + const struct fluid* fluid_props, + struct sdis_medium** fluid) +{ + struct sdis_data* data = NULL; + struct sdis_fluid_shader shader = DUMMY_FLUID_SHADER; + CHK(dev && fluid_props && fluid); + + OK(sdis_data_create + (dev, sizeof(struct fluid), ALIGNOF(struct fluid), NULL, &data)); + memcpy(sdis_data_get(data), fluid_props, sizeof(struct fluid)); + shader.temperature = fluid_get_temperature; + OK(sdis_fluid_create(dev, &shader, data, fluid)); + OK(sdis_data_ref_put(data)); +} + +/******************************************************************************* + * Interface + ******************************************************************************/ +struct interf { + double h; + double emissivity; + double phi; + double temperature; + double Tref; +}; + +static double +interface_get_temperature + (const struct sdis_interface_fragment* frag, struct sdis_data* data) +{ + const struct interf* interf = sdis_data_cget(data); + CHK(frag && data); + return interf->temperature; +} + +static double +interface_get_reference_temperature + (const struct sdis_interface_fragment* frag, struct sdis_data* data) +{ + const struct interf* interf = sdis_data_cget(data); + CHK(frag && interf); + return interf->Tref; +} + +static double +interface_get_convection_coef + (const struct sdis_interface_fragment* frag, struct sdis_data* data) +{ + const struct interf* interf = sdis_data_cget(data); + CHK(frag && interf); + return interf->h; +} + +static double +interface_get_emissivity + (const struct sdis_interface_fragment* frag, struct sdis_data* data) +{ + const struct interf* interf = sdis_data_cget(data); + CHK(frag && interf); + return interf->emissivity; +} + +static double +interface_get_specular_fraction + (const struct sdis_interface_fragment* frag, struct sdis_data* data) +{ + CHK(frag && data); + return 0; /* Unused */ +} + +static double +interface_get_flux + (const struct sdis_interface_fragment* frag, struct sdis_data* data) +{ + const struct interf* interf = sdis_data_cget(data); + CHK(frag && interf); + return interf->phi; +} + +static void +create_interface + (struct sdis_device* dev, + struct sdis_medium* front, + struct sdis_medium* back, + const struct interf* interf, + struct sdis_interface** out_interf) +{ + struct sdis_interface_shader shader = SDIS_INTERFACE_SHADER_NULL; + struct sdis_data* data = NULL; + + CHK(interf != NULL); + + shader.front.temperature = interface_get_temperature; + shader.back.temperature = interface_get_temperature; + shader.front.flux = interface_get_flux; + shader.back.flux = interface_get_flux; + + if(sdis_medium_get_type(front) != sdis_medium_get_type(back)) { + shader.convection_coef = interface_get_convection_coef; + } + if(sdis_medium_get_type(front) == SDIS_FLUID) { + shader.front.emissivity = interface_get_emissivity; + shader.front.specular_fraction = interface_get_specular_fraction; + shader.front.reference_temperature = interface_get_reference_temperature; + } + if(sdis_medium_get_type(back) == SDIS_FLUID) { + shader.back.emissivity = interface_get_emissivity; + shader.back.specular_fraction = interface_get_specular_fraction; + shader.back.reference_temperature = interface_get_reference_temperature; + } + shader.convection_coef_upper_bound = MMAX(0, interf->h); + + OK(sdis_data_create + (dev, sizeof(struct interf), ALIGNOF(struct interf), NULL, &data)); + memcpy(sdis_data_get(data), interf, sizeof(*interf)); + + OK(sdis_interface_create(dev, front, back, &shader, data, out_interf)); + OK(sdis_data_ref_put(data)); +} + +/******************************************************************************* + * Create scene + ******************************************************************************/ +static void +create_scene_3d + (struct sdis_device* dev, + struct sdis_interface* interfaces[INTERFACES_COUNT__], + struct sdis_scene** scn) +{ + struct geometry geom; + struct sdis_interface* prim_interfaces[32]; + struct sdis_scene_create_args scn_args = SDIS_SCENE_CREATE_ARGS_DEFAULT; + + CHK(dev && interfaces && scn); + + /* Setup the per primitive interface of the solid medium */ + prim_interfaces[0] = prim_interfaces[1] = interfaces[ADIABATIC]; + prim_interfaces[2] = prim_interfaces[3] = interfaces[SOLID_FLUID_WITH_FLUX]; + prim_interfaces[4] = prim_interfaces[5] = interfaces[ADIABATIC]; + prim_interfaces[6] = prim_interfaces[7] = interfaces[SOLID_FLUID]; + prim_interfaces[8] = prim_interfaces[9] = interfaces[ADIABATIC]; + prim_interfaces[10] = prim_interfaces[11] = interfaces[ADIABATIC]; + + /* Setup the per primitive interface for the right fluid */ + prim_interfaces[12] = prim_interfaces[13] = interfaces[FIXED_TEMPERATURE]; + prim_interfaces[14] = prim_interfaces[15] = interfaces[FIXED_TEMPERATURE]; + prim_interfaces[16] = prim_interfaces[17] = interfaces[FIXED_TEMPERATURE]; + prim_interfaces[18] = prim_interfaces[19] = interfaces[FIXED_TEMPERATURE]; + prim_interfaces[20] = prim_interfaces[21] = interfaces[FIXED_TEMPERATURE]; + + /* Create the scene */ + geom.positions = vertices_3d; + geom.indices = indices_3d; + geom.interfaces = prim_interfaces; + scn_args.get_indices = get_indices_3d; + scn_args.get_interface = get_interface; + scn_args.get_position = get_position_3d; + scn_args.nprimitives = nprimitives_3d; + scn_args.nvertices = nvertices_3d; + scn_args.t_range[0] = 300; + scn_args.t_range[1] = 300; + scn_args.context = &geom; + scn_args.trad.temperature = 320; + scn_args.trad.reference = 300; + OK(sdis_scene_create(dev, &scn_args, scn)); +} + +/******************************************************************************* + * Helper functions + ******************************************************************************/ +static void +check(struct sdis_scene* scn, const struct probe* probe) +{ + struct sdis_solve_probe_args args = SDIS_SOLVE_PROBE_ARGS_DEFAULT; + struct sdis_estimator* estimator = NULL; + struct sdis_mc T = SDIS_MC_NULL; + + CHK(scn && probe); + + args.nrealisations = 10000; + args.picard_order = 1; + args.position[0] = probe->x; + args.position[1] = 0; + args.position[2] = 0; + args.time_range[0] = probe->time; + args.time_range[1] = probe->time; + + OK(sdis_solve_probe(scn, &args, &estimator)); + OK(sdis_estimator_get_temperature(estimator, &T)); + OK(sdis_estimator_ref_put(estimator)); + + printf("Temperature at x=%g, t=%g: %g ~ %g +/- %g\n", + probe->x, probe->time, probe->ref, T.E, T.SE); + + CHK(eq_eps(probe->ref, T.E, T.SE*3)); +} + +/******************************************************************************* + * Test + ******************************************************************************/ +int +main(int argc, char** argv) +{ + struct sdis_device* dev = NULL; + struct sdis_scene* scn_3d = NULL; + struct sdis_medium* solid = NULL; + struct sdis_medium* dummy = NULL; + struct sdis_medium* fluid1 = NULL; + struct sdis_medium* fluid2 = NULL; + struct sdis_interface* interfaces[INTERFACES_COUNT__]; + + struct solid solid_props; + struct fluid fluid_props; + struct interf interf_props; + + const struct probe probes[] = { + {0.01, 1000.0, 481.72005748728628}, + {0.05, 1000.0, 335.19469995601020}, + {0.09, 1000.0, 299.94436943411478}, + {0.01, 2000.0, 563.21759568607558}, + {0.05, 2000.0, 392.79827670626440}, + {0.09, 2000.0, 324.89742556243448}, + {0.01, 3000.0, 620.25242712533577}, + {0.05, 3000.0, 444.73414407361213}, + {0.09, 3000.0, 359.44045704073852}, + {0.01, 4000.0, 665.65935222224493}, + {0.05, 4000.0, 490.32470982110840}, + {0.09, 4000.0, 393.89924931902408}, + {0.01, 10000.0, 830.44439052891505}, + {0.05, 10000.0, 664.82771620162805}, + {0.09, 10000.0, 533.92442748613928} + }; + const size_t nprobes = sizeof(probes)/sizeof(*probes); + size_t iprobe; + + (void)argc, (void)argv; + + OK(sdis_device_create(&SDIS_DEVICE_CREATE_ARGS_DEFAULT, &dev)); + + /* Solid medium */ + solid_props.lambda = 1.15; + solid_props.rho = 1700; + solid_props.cp = 800; + create_solid(dev, &solid_props, &solid); + + /* Dummy solid medium */ + solid_props.lambda = 0; + solid_props.rho = 1700; + solid_props.cp = 800; + create_solid(dev, &solid_props, &dummy); + + /* Fluid media */ + fluid_props.temperature = 330; + create_fluid(dev, &fluid_props, &fluid1); + fluid_props.temperature = 290; + create_fluid(dev, &fluid_props, &fluid2); + + /* Adiabatic interfaces */ + interf_props.h = 0; + interf_props.emissivity = 0; + interf_props.phi = SDIS_FLUX_NONE; + interf_props.temperature = UNKNOWN_TEMPERATURE; + interf_props.Tref = UNKNOWN_TEMPERATURE; + create_interface(dev, solid, dummy, &interf_props, &interfaces[ADIABATIC]); + + /* Interfaces with a fixed temperature */ + interf_props.h = 1; + interf_props.emissivity = 1; + interf_props.phi = SDIS_FLUX_NONE; + interf_props.temperature = 280; + interf_props.Tref = 300; + create_interface + (dev, fluid2, dummy, &interf_props, &interfaces[FIXED_TEMPERATURE]); + + /* Interfaces with a fixed flux */ + interf_props.h = 2; + interf_props.emissivity = 1; + interf_props.phi = 10000; + interf_props.temperature = UNKNOWN_TEMPERATURE; + interf_props.Tref = 300; + create_interface + (dev, solid, fluid1, &interf_props, &interfaces[SOLID_FLUID_WITH_FLUX]); + + interf_props.h = 8; + interf_props.emissivity = 1; + interf_props.phi = SDIS_FLUX_NONE; + interf_props.temperature = UNKNOWN_TEMPERATURE; + interf_props.Tref = 300; + create_interface + (dev, solid, fluid2, &interf_props, &interfaces[SOLID_FLUID]); + + create_scene_3d(dev, interfaces, &scn_3d); + + FOR_EACH(iprobe, 0, nprobes) { + check(scn_3d, &probes[iprobe]); + } + + /* Release memory */ + OK(sdis_scene_ref_put(scn_3d)); + OK(sdis_medium_ref_put(solid)); + OK(sdis_medium_ref_put(dummy)); + OK(sdis_medium_ref_put(fluid1)); + OK(sdis_medium_ref_put(fluid2)); + OK(sdis_interface_ref_put(interfaces[ADIABATIC])); + OK(sdis_interface_ref_put(interfaces[FIXED_TEMPERATURE])); + OK(sdis_interface_ref_put(interfaces[SOLID_FLUID_WITH_FLUX])); + OK(sdis_interface_ref_put(interfaces[SOLID_FLUID])); + OK(sdis_device_ref_put(dev)); + + CHK(mem_allocated_size() == 0); + return 0; +} diff --git a/src/test_sdis_volumic_power.c b/src/test_sdis_volumic_power.c @@ -51,7 +51,7 @@ #define T0 320 #define LAMBDA 0.1 #define P0 10 -#define DELTA 1.0/50.0 +#define DELTA 1.0/55.0 /******************************************************************************* * Media