stardis-solver

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

commit 43034a6741317a99a565b894a59f499d7a60c184
parent 221ea417664665c9d3411d6c5cdb168c4f8bc687
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Fri,  5 Nov 2021 16:50:15 +0100

Test the picardN algorithm

Diffstat:
Mcmake/CMakeLists.txt | 2+-
Asrc/test_sdis_picard.c | 774+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Dsrc/test_sdis_picard1.c | 739-------------------------------------------------------------------------------
3 files changed, 775 insertions(+), 740 deletions(-)

diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt @@ -192,7 +192,7 @@ if(NOT NO_TEST) new_test(test_sdis_flux) new_test(test_sdis_interface) new_test(test_sdis_medium) - new_test(test_sdis_picard1) + new_test(test_sdis_picard) new_test(test_sdis_scene) new_test(test_sdis_solid_random_walk_robustness) new_test(test_sdis_solve_camera) diff --git a/src/test_sdis_picard.c b/src/test_sdis_picard.c @@ -0,0 +1,774 @@ +/* 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.h" +#include "test_sdis_utils.h" + +#include <string.h> + +#define UNKNOWN_TEMPERATURE -1 +#define N 10000 + +/* This test consists in solving the stationary temperature profile in a solid + * slab surrounded by two different radiative temperatures (left / right). The + * conductivity of the solid material is known, as well as its thickness and + * the source term (volumic power density). + * + * The purpose is to test the Picard-1 radiative transfer algorithm, that can + * be compared with analytic results. This algorithm can use a possibly + * non-uniform reference temperature field. When the reference temperature + * field is uniform, results should be identical to the classical Monte-Carlo + * algorithm (using a linearized radiative transfer scheme). + * + * Y + * | (0.1,1) + * o--- X +------+----------+------+ (1.1,1) + * | |##########| | + * | |##########| | + * 280K | E=1 |##########| E=1 | 350K + * | |##########| | + * | |##########| | + * (-1,-1) +------+----------+------+ + * (0,-1) + * + * + * + * Y (0.1, 1, 1) + * | +------+----------+------+ (1.1,1,1) + * o--- X /' /##########/' /| + * / +------+----------+------+ | + * Z | ' |##########|*' | | 350K + * | ' |##########|*' | | + * 280K | ' E=1|##########|*'E=1 | | + * | +....|##########|*+....|.+ + * |/ |##########|/ |/ + * (-1,-1,-1) +------+----------+------+ + * (0,-1,-1) + * + * lambda = 1.15 W/(m.K) + * rho = 1000 kg.m^-3 + * cp = 800 J/(kg.K) + * emissivity = 1 + * + * Basic Tref = 300 K + * probe = 0.05 0 0 m + * (power = 1000 W.m^-3) */ + +enum interface_type { + ADIABATIC, + SOLID_FLUID_mX, + SOLID_FLUID_pX, + BOUNDARY_mX, + BOUNDARY_pX, + INTERFACES_COUNT__ +}; + +/******************************************************************************* + * Geometry + ******************************************************************************/ +struct geometry { + const double* positions; + const size_t* indices; + struct sdis_interface** interfaces; +}; + +static const double vertices_2d[8/*#vertices*/*2/*#coords par vertex*/] = { + 0.1, -1.0, + 0.0, -1.0, + 0.0, 1.0, + 0.1, 1.0, + 1.1, -1.0, + -1.0, -1.0, + -1.0, 1.0, + 1.1, 1.0 +}; +static const size_t nvertices_2d = sizeof(vertices_2d) / (sizeof(double)*2); + +static const size_t indices_2d[10/*#segments*/*2/*#indices per segment*/] = { + 0, 1, /* Solid -Y */ + 1, 2, /* Solid -X */ + 2, 3, /* Solid +Y */ + 3, 0, /* Solid +X */ + + 1, 5, /* Left fluid -Y */ + 5, 6, /* Left fluid -X */ + 6, 2, /* Left fluid +Y */ + + 4, 0, /* Right fluid -Y */ + 3, 7, /* Right fluid +Y */ + 7, 4 /* Right fluid +X */ +}; +static const size_t nprimitives_2d = sizeof(indices_2d) / (sizeof(size_t)*2); + +static const double vertices_3d[16/*#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.0,-1.0,-1.0, + 1.1,-1.0,-1.0, + -1.0, 1.0,-1.0, + 1.1, 1.0,-1.0, + -1.0,-1.0, 1.0, + 1.1,-1.0, 1.0, + -1.0, 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[32/*#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 */ + + 8, 10, 0, 0, 10, 2, /* Left fluid -Z */ + 8, 12, 10, 10, 12, 14, /* Left fluid -X */ + 12, 4, 14, 14, 4, 6, /* Left fluid +Z */ + 10, 14, 2, 2, 14, 6, /* Left fluid +Y */ + 8, 0, 12, 12, 0, 4, /* Left fluid -Y */ + + 1, 3, 9, 9, 3, 11, /* Right fluid -Z */ + 5, 13, 7, 7, 13, 15, /* Right fluid +Z */ + 11, 15, 9, 9, 15, 13, /* Right fluid +X */ + 3, 7, 11, 11, 7, 15, /* Right fluid +Y */ + 1, 9, 5, 5, 9, 13 /* Right fluid -Y */ +}; +static const size_t nprimitives_3d = sizeof(indices_3d) / (sizeof(size_t)*3); + +static void +get_indices_2d(const size_t iseg, size_t ids[2], void* ctx) +{ + struct geometry* geom = ctx; + CHK(ctx != NULL); + ids[0] = geom->indices[iseg*2+0]; + ids[1] = geom->indices[iseg*2+1]; +} + +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_2d(const size_t ivert, double pos[2], void* ctx) +{ + struct geometry* geom = ctx; + CHK(ctx != NULL); + pos[0] = geom->positions[ivert*2+0]; + pos[1] = geom->positions[ivert*2+1]; +} + +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]; +} + +/******************************************************************************* + * 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) +{ + CHK(vtx && data); + return UNKNOWN_TEMPERATURE; +} + +static double +solid_get_volumic_power + (const struct sdis_rwalk_vertex* vtx, struct sdis_data* data) +{ + const struct solid* solid = sdis_data_cget(data); + CHK(vtx && solid); + return solid->volumic_power; +} + +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 = solid_get_delta; + shader.temperature = solid_get_temperature; + shader.volumic_power = solid_get_volumic_power; + OK(sdis_solid_create(dev, &shader, data, solid)); + OK(sdis_data_ref_put(data)); +} + +static void +create_fluid(struct sdis_device* dev, struct sdis_medium** fluid) +{ + struct sdis_fluid_shader shader = DUMMY_FLUID_SHADER; + OK(sdis_fluid_create(dev, &shader, NULL, fluid)); +} + +/******************************************************************************* + * Interface + ******************************************************************************/ +struct interf { + double temperature; + double h; + double emissivity; + double specular_fraction; + 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 && interf); + return interf->temperature; +} + +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) +{ + const struct interf* interf = sdis_data_cget(data); + CHK(frag && interf); + return interf->specular_fraction; +} + +static double +interface_get_Tref + (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 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; + 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_Tref; + } + 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_Tref; + } + 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)); +} + +/******************************************************************************* + * Helper functions + ******************************************************************************/ +struct reference_result { + double T; /* Temperature at the center of the solid [K] */ + double T1; /* Temperature on the left boundary of the solid [K] */ + double T2; /* Temperature on the right boundary of the solid [K] */ +}; +static const struct reference_result REFERENCE_RESULT_NULL = {0,0,0}; + +static void +test_picard1(struct sdis_scene* scn, const struct reference_result* ref) +{ + struct sdis_solve_probe_args probe_args = SDIS_SOLVE_PROBE_ARGS_DEFAULT; + struct sdis_solve_boundary_args bound_args = SDIS_SOLVE_BOUNDARY_ARGS_DEFAULT; + struct sdis_mc mc = SDIS_MC_NULL; + struct sdis_estimator* estimator = NULL; + enum sdis_scene_dimension dim; + size_t prims[2]; + enum sdis_side sides[2]; + CHK(scn); + + OK(sdis_scene_get_dimension(scn, &dim)); + switch(dim) { + case SDIS_SCENE_2D: printf(">>> 2D\n"); break; + case SDIS_SCENE_3D: printf(">>> 3D\n"); break; + default: FATAL("Unreachable code.\n"); break; + } + + probe_args.nrealisations = N; + probe_args.position[0] = 0.05; + probe_args.position[1] = 0; + probe_args.position[2] = 0; + OK(sdis_solve_probe(scn, &probe_args, &estimator)); + OK(sdis_estimator_get_temperature(estimator, &mc)); + printf("Temperature at `%g %g %g' = %g ~ %g +/- %g\n", + SPLIT3(probe_args.position), ref->T, mc.E, mc.SE); + CHK(eq_eps(ref->T, mc.E, mc.SE*3)); + OK(sdis_estimator_ref_put(estimator)); + + switch(dim) { + case SDIS_SCENE_2D: + prims[0] = 1; sides[0] = SDIS_BACK; + bound_args.nprimitives = 1; + break; + case SDIS_SCENE_3D: + prims[0] = 2; sides[0] = SDIS_BACK; + prims[1] = 3; sides[1] = SDIS_BACK; + bound_args.nprimitives = 2; + break; + default: FATAL("Unreachable code.\n"); break; + } + bound_args.nrealisations = N; + bound_args.primitives = prims; + bound_args.sides = sides; + OK(sdis_solve_boundary(scn, &bound_args, &estimator)); + OK(sdis_estimator_get_temperature(estimator, &mc)); + printf("T1 = %g ~ %g +/- %g\n", ref->T1, mc.E, mc.SE); + CHK(eq_eps(ref->T1, mc.E, mc.SE*3)); + OK(sdis_estimator_ref_put(estimator)); + + switch(dim) { + case SDIS_SCENE_2D: + prims[0] = 3; sides[0] = SDIS_BACK; + bound_args.nprimitives = 1; + break; + case SDIS_SCENE_3D: + prims[0] = 6; sides[0] = SDIS_BACK; + prims[1] = 7; sides[1] = SDIS_BACK; + bound_args.nprimitives = 2; + break; + default: FATAL("Unreachable code.\n"); break; + } + bound_args.nrealisations = N; + bound_args.primitives = prims; + bound_args.sides = sides; + OK(sdis_solve_boundary(scn, &bound_args, &estimator)); + OK(sdis_estimator_get_temperature(estimator, &mc)); + printf("T2 = %g ~ %g +/- %g\n", ref->T2, mc.E, mc.SE); + CHK(eq_eps(ref->T2, mc.E, mc.SE*3)); + OK(sdis_estimator_ref_put(estimator)); +} + +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_mX]; + prim_interfaces[4] = prim_interfaces[5] = interfaces[ADIABATIC]; + prim_interfaces[6] = prim_interfaces[7] = interfaces[SOLID_FLUID_pX]; + prim_interfaces[8] = prim_interfaces[9] = interfaces[ADIABATIC]; + prim_interfaces[10] = prim_interfaces[11] = interfaces[ADIABATIC]; + + /* Setup the per primitive interface for the left fluid */ + prim_interfaces[12] = prim_interfaces[13] = interfaces[BOUNDARY_mX]; + prim_interfaces[14] = prim_interfaces[15] = interfaces[BOUNDARY_mX]; + prim_interfaces[16] = prim_interfaces[17] = interfaces[BOUNDARY_mX]; + prim_interfaces[18] = prim_interfaces[19] = interfaces[BOUNDARY_mX]; + prim_interfaces[20] = prim_interfaces[21] = interfaces[BOUNDARY_mX]; + + /* Setup the per primitive interface for the right fluid */ + prim_interfaces[22] = prim_interfaces[23] = interfaces[BOUNDARY_pX]; + prim_interfaces[24] = prim_interfaces[25] = interfaces[BOUNDARY_pX]; + prim_interfaces[26] = prim_interfaces[27] = interfaces[BOUNDARY_pX]; + prim_interfaces[28] = prim_interfaces[29] = interfaces[BOUNDARY_pX]; + prim_interfaces[30] = prim_interfaces[31] = interfaces[BOUNDARY_pX]; + + /* 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] = 280; + scn_args.t_range[1] = 350; + scn_args.context = &geom; + OK(sdis_scene_create(dev, &scn_args, scn)); +} + +static void +create_scene_2d + (struct sdis_device* dev, + struct sdis_interface* interfaces[INTERFACES_COUNT__], + struct sdis_scene** scn) +{ + struct geometry geom; + struct sdis_interface* prim_interfaces[10/*#segment*/]; + 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] = interfaces[ADIABATIC]; + prim_interfaces[1] = interfaces[SOLID_FLUID_mX]; + prim_interfaces[2] = interfaces[ADIABATIC]; + prim_interfaces[3] = interfaces[SOLID_FLUID_pX]; + + /* Setup the per primitive interface of the fluid on the left of the medium */ + prim_interfaces[4] = interfaces[BOUNDARY_mX]; + prim_interfaces[5] = interfaces[BOUNDARY_mX]; + prim_interfaces[6] = interfaces[BOUNDARY_mX]; + + /* Setup the per primitive interface of the fluid on the right of the medium */ + prim_interfaces[7] = interfaces[BOUNDARY_pX]; + prim_interfaces[8] = interfaces[BOUNDARY_pX]; + prim_interfaces[9] = interfaces[BOUNDARY_pX]; + + /* Create the scene */ + geom.positions = vertices_2d; + geom.indices = indices_2d; + geom.interfaces = prim_interfaces; + scn_args.get_indices = get_indices_2d; + scn_args.get_interface = get_interface; + scn_args.get_position = get_position_2d; + scn_args.nprimitives = nprimitives_2d; + scn_args.nvertices = nvertices_2d; + scn_args.t_range[0] = 280; + scn_args.t_range[1] = 350; + scn_args.context = &geom; + OK(sdis_scene_2d_create(dev, &scn_args, scn)); +} + +/******************************************************************************* + * Test + ******************************************************************************/ +int +main(int argc, char** argv) +{ + struct mem_allocator allocator; + + struct sdis_device* dev = NULL; + struct sdis_scene* scn_2d = NULL; + struct sdis_scene* scn_3d = NULL; + struct sdis_medium* solid = NULL; + struct sdis_medium* fluid = NULL; + struct sdis_medium* dummy = NULL; + struct sdis_interface* interfaces[INTERFACES_COUNT__]; + + struct solid solid_props; + struct solid* psolid_props; + struct reference_result ref = REFERENCE_RESULT_NULL; + struct interf interf_props; + struct interf* pinterf_props[INTERFACES_COUNT__]; + + double t_range[2]; + + size_t i; + (void)argc, (void)argv; + + OK(mem_init_proxy_allocator(&allocator, &mem_default_allocator)); + OK(sdis_device_create(NULL, &allocator, SDIS_NTHREADS_DEFAULT, 1, &dev)); + + /* Solid medium */ + solid_props.lambda = 1.15; + solid_props.rho = 1000; + solid_props.cp = 800; + create_solid(dev, &solid_props, &solid); + + /* Dummy solid medium */ + solid_props.lambda = 0; + solid_props.rho = 1000; + solid_props.cp = 800; + solid_props.volumic_power = SDIS_VOLUMIC_POWER_NONE; + create_solid(dev, &solid_props, &dummy); + + /* Fluid medium */ + create_fluid(dev, &fluid); + + /* Create the adiabatic interface for the solid */ + interf_props.temperature = UNKNOWN_TEMPERATURE; + interf_props.h = -1; + interf_props.emissivity = -1; + interf_props.specular_fraction = -1; + interf_props.Tref = UNKNOWN_TEMPERATURE; + create_interface(dev, solid, dummy, &interf_props, interfaces+ADIABATIC); + + /* Create the interface between the solid and the fluid */ + interf_props.temperature = UNKNOWN_TEMPERATURE; + interf_props.h = 0; + interf_props.emissivity = 1; + interf_props.specular_fraction = 0; + interf_props.Tref = 280; + create_interface(dev, solid, fluid, &interf_props, interfaces+SOLID_FLUID_mX); + interf_props.Tref = 350; + create_interface(dev, solid, fluid, &interf_props, interfaces+SOLID_FLUID_pX); + + /* Create the interface for the fluid on the left */ + interf_props.temperature = 280; + interf_props.h = -1; + interf_props.emissivity = 1; + interf_props.specular_fraction = -1; + interf_props.Tref = 280; + create_interface(dev, fluid, dummy, &interf_props, interfaces+BOUNDARY_mX); + + /* Create the interface for the fluid on the right */ + interf_props.temperature = 350; + interf_props.h = -1; + interf_props.emissivity = 1; + interf_props.specular_fraction = -1; + interf_props.Tref = 350; + create_interface(dev, fluid, dummy, &interf_props, interfaces+BOUNDARY_pX); + + /* Fetch pointers toward the solid and the interfaces */ + psolid_props = sdis_data_get(sdis_medium_get_data(solid)); + FOR_EACH(i, 0, INTERFACES_COUNT__) { + pinterf_props[i] = sdis_data_get(sdis_interface_get_data(interfaces[i])); + } + + create_scene_2d(dev, interfaces, &scn_2d); + create_scene_3d(dev, interfaces, &scn_3d); + + /* Test picard1 with a constant Tref <=> regular linearisation */ + printf("Test Picard1 with a constant Tref of 300 K\n"); + ref.T = 314.99999999999989; + ref.T1 = 307.64122364709766; + ref.T2 = 322.35877635290217; + pinterf_props[SOLID_FLUID_mX]->Tref = 300; + pinterf_props[SOLID_FLUID_pX]->Tref = 300; + pinterf_props[BOUNDARY_mX]->Tref = 300; + pinterf_props[BOUNDARY_pX]->Tref = 300; + test_picard1(scn_2d, &ref); + test_picard1(scn_3d, &ref); + printf("\n"); + + /* Test picard1 using T4 as a reference */ + printf("Test Picard1 using T4 as a reference\n"); + ref.T = 320.37126474482994; + ref.T1 = 312.12650299072266; + ref.T2 = 328.61602649893723; + pinterf_props[SOLID_FLUID_mX]->Tref = ref.T1; + pinterf_props[SOLID_FLUID_pX]->Tref = ref.T2; + pinterf_props[BOUNDARY_mX]->Tref = 280; + pinterf_props[BOUNDARY_pX]->Tref = 350; + test_picard1(scn_2d, &ref); + test_picard1(scn_3d, &ref); + printf("\n"); + + /* Test picard2 */ + printf("Test Picard2 with a constant Tref of 300K\n"); + ref.T = 320.37126474482994; + ref.T1 = 312.12650299072266; + ref.T2 = 328.61602649893723; + pinterf_props[SOLID_FLUID_mX]->Tref = 300; + pinterf_props[SOLID_FLUID_pX]->Tref = 300; + pinterf_props[BOUNDARY_mX]->Tref = 300; + pinterf_props[BOUNDARY_pX]->Tref = 300; + OK(sdis_scene_set_picard_order(scn_2d, 2)); + OK(sdis_scene_set_picard_order(scn_3d, 2)); + test_picard1(scn_2d, &ref); + test_picard1(scn_3d, &ref); + OK(sdis_scene_set_picard_order(scn_2d, 1)); + OK(sdis_scene_set_picard_order(scn_3d, 1)); + printf("\n"); + + t_range[0] = 200; + t_range[1] = 500; + OK(sdis_scene_set_temperature_range(scn_2d, t_range)); + OK(sdis_scene_set_temperature_range(scn_3d, t_range)); + OK(sdis_scene_set_picard_order(scn_2d, 3)); + OK(sdis_scene_set_picard_order(scn_3d, 3)); + + /* Test picard2 */ + printf("Test Picard3 with a delta T of 300K\n"); + ref.T = 416.4023; + ref.T1 = 372.7557; + ref.T2 = 460.0489; + pinterf_props[BOUNDARY_mX]->temperature = t_range[0]; + pinterf_props[BOUNDARY_pX]->temperature = t_range[1]; + pinterf_props[SOLID_FLUID_mX]->Tref = 350; + pinterf_props[SOLID_FLUID_pX]->Tref = 450; + pinterf_props[BOUNDARY_mX]->Tref = pinterf_props[BOUNDARY_mX]->temperature; + pinterf_props[BOUNDARY_pX]->Tref = pinterf_props[BOUNDARY_pX]->temperature; + test_picard1(scn_2d, &ref); + test_picard1(scn_3d, &ref); + printf("\n"); + + t_range[0] = 280; + t_range[1] = 350; + OK(sdis_scene_set_temperature_range(scn_2d, t_range)); + OK(sdis_scene_set_temperature_range(scn_3d, t_range)); + OK(sdis_scene_set_picard_order(scn_2d, 1)); + OK(sdis_scene_set_picard_order(scn_3d, 1)); + pinterf_props[BOUNDARY_mX]->temperature = t_range[0]; + pinterf_props[BOUNDARY_pX]->temperature = t_range[1]; + + /* Add volumic power */ + psolid_props->volumic_power = 1000; + + /* Test picard1 with a volumic power and constant Tref */ + printf("Test Picard1 with a volumic power of 1000 W/m^3 and a constant Tref " + "of 300 K\n"); + ref.T = 324.25266420769509; + ref.T1 = 315.80693133305368; + ref.T2 = 330.52448403885825; + pinterf_props[SOLID_FLUID_mX]->Tref = 300; + pinterf_props[SOLID_FLUID_pX]->Tref = 300; + pinterf_props[BOUNDARY_mX]->Tref = 300; + pinterf_props[BOUNDARY_pX]->Tref = 300; + test_picard1(scn_2d, &ref); + test_picard1(scn_3d, &ref); + printf("\n"); + + /* Test picard1 with a volumic power and T4 a the reference */ + printf("Test Picard1 with a volumic power of 1000 W/m^3 and T4 as a reference\n"); + ref.T = 327.95981050850446; + ref.T1 = 318.75148773193359; + ref.T2 = 334.99422024159708; + pinterf_props[SOLID_FLUID_mX]->Tref = ref.T1; + pinterf_props[SOLID_FLUID_pX]->Tref = ref.T2; + pinterf_props[BOUNDARY_mX]->Tref = 280; + pinterf_props[BOUNDARY_pX]->Tref = 350; + test_picard1(scn_2d, &ref); + test_picard1(scn_3d, &ref); + printf("\n"); + + /* Release memory */ + OK(sdis_scene_ref_put(scn_2d)); + OK(sdis_scene_ref_put(scn_3d)); + OK(sdis_interface_ref_put(interfaces[ADIABATIC])); + OK(sdis_interface_ref_put(interfaces[SOLID_FLUID_mX])); + OK(sdis_interface_ref_put(interfaces[SOLID_FLUID_pX])); + OK(sdis_interface_ref_put(interfaces[BOUNDARY_mX])); + OK(sdis_interface_ref_put(interfaces[BOUNDARY_pX])); + OK(sdis_medium_ref_put(fluid)); + OK(sdis_medium_ref_put(solid)); + OK(sdis_medium_ref_put(dummy)); + OK(sdis_device_ref_put(dev)); + + check_memory_allocator(&allocator); + mem_shutdown_proxy_allocator(&allocator); + CHK(mem_allocated_size() == 0); + return 0; +} diff --git a/src/test_sdis_picard1.c b/src/test_sdis_picard1.c @@ -1,739 +0,0 @@ -/* 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.h" -#include "test_sdis_utils.h" - -#include <string.h> - -#define UNKNOWN_TEMPERATURE -1 -#define N 10000 - -/* This test consists in solving the stationary temperature profile in a solid - * slab surrounded by two different radiative temperatures (left / right). The - * conductivity of the solid material is known, as well as its thickness and - * the source term (volumic power density). - * - * The purpose is to test the Picard-1 radiative transfer algorithm, that can - * be compared with analytic results. This algorithm can use a possibly - * non-uniform reference temperature field. When the reference temperature - * field is uniform, results should be identical to the classical Monte-Carlo - * algorithm (using a linearized radiative transfer scheme). - * - * Y - * | (0.1,1) - * o--- X +------+----------+------+ (1.1,1) - * | |##########| | - * | |##########| | - * 280K | E=1 |##########| E=1 | 350K - * | |##########| | - * | |##########| | - * (-1,-1) +------+----------+------+ - * (0,-1) - * - * - * - * Y (0.1, 1, 1) - * | +------+----------+------+ (1.1,1,1) - * o--- X /' /##########/' /| - * / +------+----------+------+ | - * Z | ' |##########|*' | | 350K - * | ' |##########|*' | | - * 280K | ' E=1|##########|*'E=1 | | - * | +....|##########|*+....|.+ - * |/ |##########|/ |/ - * (-1,-1,-1) +------+----------+------+ - * (0,-1,-1) - * - * lambda = 1.15 W/(m.K) - * rho = 1000 kg.m^-3 - * cp = 800 J/(kg.K) - * emissivity = 1 - * - * Basic Tref = 300 K - * probe = 0.05 0 0 m - * (power = 1000 W.m^-3) */ - -enum interface_type { - ADIABATIC, - SOLID_FLUID_mX, - SOLID_FLUID_pX, - BOUNDARY_mX, - BOUNDARY_pX, - INTERFACES_COUNT__ -}; - -/******************************************************************************* - * Geometry - ******************************************************************************/ -struct geometry { - const double* positions; - const size_t* indices; - struct sdis_interface** interfaces; -}; - -static const double vertices_2d[8/*#vertices*/*2/*#coords par vertex*/] = { - 0.1, -1.0, - 0.0, -1.0, - 0.0, 1.0, - 0.1, 1.0, - 1.1, -1.0, - -1.0, -1.0, - -1.0, 1.0, - 1.1, 1.0 -}; -static const size_t nvertices_2d = sizeof(vertices_2d) / (sizeof(double)*2); - -static const size_t indices_2d[10/*#segments*/*2/*#indices per segment*/] = { - 0, 1, /* Solid -Y */ - 1, 2, /* Solid -X */ - 2, 3, /* Solid +Y */ - 3, 0, /* Solid +X */ - - 1, 5, /* Left fluid -Y */ - 5, 6, /* Left fluid -X */ - 6, 2, /* Left fluid +Y */ - - 4, 0, /* Right fluid -Y */ - 3, 7, /* Right fluid +Y */ - 7, 4 /* Right fluid +X */ -}; -static const size_t nprimitives_2d = sizeof(indices_2d) / (sizeof(size_t)*2); - -static const double vertices_3d[16/*#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.0,-1.0,-1.0, - 1.1,-1.0,-1.0, - -1.0, 1.0,-1.0, - 1.1, 1.0,-1.0, - -1.0,-1.0, 1.0, - 1.1,-1.0, 1.0, - -1.0, 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[32/*#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 */ - - 8, 10, 0, 0, 10, 2, /* Left fluid -Z */ - 8, 12, 10, 10, 12, 14, /* Left fluid -X */ - 12, 4, 14, 14, 4, 6, /* Left fluid +Z */ - 10, 14, 2, 2, 14, 6, /* Left fluid +Y */ - 8, 0, 12, 12, 0, 4, /* Left fluid -Y */ - - 1, 3, 9, 9, 3, 11, /* Right fluid -Z */ - 5, 13, 7, 7, 13, 15, /* Right fluid +Z */ - 11, 15, 9, 9, 15, 13, /* Right fluid +X */ - 3, 7, 11, 11, 7, 15, /* Right fluid +Y */ - 1, 9, 5, 5, 9, 13 /* Right fluid -Y */ -}; -static const size_t nprimitives_3d = sizeof(indices_3d) / (sizeof(size_t)*3); - -static void -get_indices_2d(const size_t iseg, size_t ids[2], void* ctx) -{ - struct geometry* geom = ctx; - CHK(ctx != NULL); - ids[0] = geom->indices[iseg*2+0]; - ids[1] = geom->indices[iseg*2+1]; -} - -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_2d(const size_t ivert, double pos[2], void* ctx) -{ - struct geometry* geom = ctx; - CHK(ctx != NULL); - pos[0] = geom->positions[ivert*2+0]; - pos[1] = geom->positions[ivert*2+1]; -} - -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]; -} - -/******************************************************************************* - * 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) -{ - CHK(vtx && data); - return UNKNOWN_TEMPERATURE; -} - -static double -solid_get_volumic_power - (const struct sdis_rwalk_vertex* vtx, struct sdis_data* data) -{ - const struct solid* solid = sdis_data_cget(data); - CHK(vtx && solid); - return solid->volumic_power; -} - -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 = solid_get_delta; - shader.temperature = solid_get_temperature; - shader.volumic_power = solid_get_volumic_power; - OK(sdis_solid_create(dev, &shader, data, solid)); - OK(sdis_data_ref_put(data)); -} - -static void -create_fluid(struct sdis_device* dev, struct sdis_medium** fluid) -{ - struct sdis_fluid_shader shader = DUMMY_FLUID_SHADER; - OK(sdis_fluid_create(dev, &shader, NULL, fluid)); -} - -/******************************************************************************* - * Interface - ******************************************************************************/ -struct interf { - double temperature; - double h; - double emissivity; - double specular_fraction; - 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 && interf); - return interf->temperature; -} - -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) -{ - const struct interf* interf = sdis_data_cget(data); - CHK(frag && interf); - return interf->specular_fraction; -} - -static double -interface_get_Tref - (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 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; - 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_Tref; - } - 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_Tref; - } - 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)); -} - -/******************************************************************************* - * Helper functions - ******************************************************************************/ -struct reference_result { - double T; /* Temperature at the center of the solid [K] */ - double T1; /* Temperature on the left boundary of the solid [K] */ - double T2; /* Temperature on the right boundary of the solid [K] */ -}; -static const struct reference_result REFERENCE_RESULT_NULL = {0,0,0}; - -static void -test_picard1(struct sdis_scene* scn, const struct reference_result* ref) -{ - struct sdis_solve_probe_args probe_args = SDIS_SOLVE_PROBE_ARGS_DEFAULT; - struct sdis_solve_boundary_args bound_args = SDIS_SOLVE_BOUNDARY_ARGS_DEFAULT; - struct sdis_mc mc = SDIS_MC_NULL; - struct sdis_estimator* estimator = NULL; - enum sdis_scene_dimension dim; - size_t prims[2]; - enum sdis_side sides[2]; - CHK(scn); - - OK(sdis_scene_get_dimension(scn, &dim)); - switch(dim) { - case SDIS_SCENE_2D: printf(">>> 2D\n"); break; - case SDIS_SCENE_3D: printf(">>> 3D\n"); break; - default: FATAL("Unreachable code.\n"); break; - } - - probe_args.nrealisations = N; - probe_args.position[0] = 0.05; - probe_args.position[1] = 0; - probe_args.position[2] = 0; - OK(sdis_solve_probe(scn, &probe_args, &estimator)); - OK(sdis_estimator_get_temperature(estimator, &mc)); - printf("Temperature at `%g %g %g' = %g ~ %g +/- %g\n", - SPLIT3(probe_args.position), ref->T, mc.E, mc.SE); - CHK(eq_eps(ref->T, mc.E, mc.SE*3)); - OK(sdis_estimator_ref_put(estimator)); - - switch(dim) { - case SDIS_SCENE_2D: - prims[0] = 1; sides[0] = SDIS_BACK; - bound_args.nprimitives = 1; - break; - case SDIS_SCENE_3D: - prims[0] = 2; sides[0] = SDIS_BACK; - prims[1] = 3; sides[1] = SDIS_BACK; - bound_args.nprimitives = 2; - break; - default: FATAL("Unreachable code.\n"); break; - } - bound_args.nrealisations = N; - bound_args.primitives = prims; - bound_args.sides = sides; - OK(sdis_solve_boundary(scn, &bound_args, &estimator)); - OK(sdis_estimator_get_temperature(estimator, &mc)); - printf("T1 = %g ~ %g +/- %g\n", ref->T1, mc.E, mc.SE); - CHK(eq_eps(ref->T1, mc.E, mc.SE*3)); - OK(sdis_estimator_ref_put(estimator)); - - switch(dim) { - case SDIS_SCENE_2D: - prims[0] = 3; sides[0] = SDIS_BACK; - bound_args.nprimitives = 1; - break; - case SDIS_SCENE_3D: - prims[0] = 6; sides[0] = SDIS_BACK; - prims[1] = 7; sides[1] = SDIS_BACK; - bound_args.nprimitives = 2; - break; - default: FATAL("Unreachable code.\n"); break; - } - bound_args.nrealisations = N; - bound_args.primitives = prims; - bound_args.sides = sides; - OK(sdis_solve_boundary(scn, &bound_args, &estimator)); - OK(sdis_estimator_get_temperature(estimator, &mc)); - printf("T2 = %g ~ %g +/- %g\n", ref->T2, mc.E, mc.SE); - CHK(eq_eps(ref->T2, mc.E, mc.SE*3)); - OK(sdis_estimator_ref_put(estimator)); -} - -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_mX]; - prim_interfaces[4] = prim_interfaces[5] = interfaces[ADIABATIC]; - prim_interfaces[6] = prim_interfaces[7] = interfaces[SOLID_FLUID_pX]; - prim_interfaces[8] = prim_interfaces[9] = interfaces[ADIABATIC]; - prim_interfaces[10] = prim_interfaces[11] = interfaces[ADIABATIC]; - - /* Setup the per primitive interface for the left fluid */ - prim_interfaces[12] = prim_interfaces[13] = interfaces[BOUNDARY_mX]; - prim_interfaces[14] = prim_interfaces[15] = interfaces[BOUNDARY_mX]; - prim_interfaces[16] = prim_interfaces[17] = interfaces[BOUNDARY_mX]; - prim_interfaces[18] = prim_interfaces[19] = interfaces[BOUNDARY_mX]; - prim_interfaces[20] = prim_interfaces[21] = interfaces[BOUNDARY_mX]; - - /* Setup the per primitive interface for the right fluid */ - prim_interfaces[22] = prim_interfaces[23] = interfaces[BOUNDARY_pX]; - prim_interfaces[24] = prim_interfaces[25] = interfaces[BOUNDARY_pX]; - prim_interfaces[26] = prim_interfaces[27] = interfaces[BOUNDARY_pX]; - prim_interfaces[28] = prim_interfaces[29] = interfaces[BOUNDARY_pX]; - prim_interfaces[30] = prim_interfaces[31] = interfaces[BOUNDARY_pX]; - - /* 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] = 280; - scn_args.t_range[1] = 350; - scn_args.context = &geom; - OK(sdis_scene_create(dev, &scn_args, scn)); -} - -static void -create_scene_2d - (struct sdis_device* dev, - struct sdis_interface* interfaces[INTERFACES_COUNT__], - struct sdis_scene** scn) -{ - struct geometry geom; - struct sdis_interface* prim_interfaces[10/*#segment*/]; - 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] = interfaces[ADIABATIC]; - prim_interfaces[1] = interfaces[SOLID_FLUID_mX]; - prim_interfaces[2] = interfaces[ADIABATIC]; - prim_interfaces[3] = interfaces[SOLID_FLUID_pX]; - - /* Setup the per primitive interface of the fluid on the left of the medium */ - prim_interfaces[4] = interfaces[BOUNDARY_mX]; - prim_interfaces[5] = interfaces[BOUNDARY_mX]; - prim_interfaces[6] = interfaces[BOUNDARY_mX]; - - /* Setup the per primitive interface of the fluid on the right of the medium */ - prim_interfaces[7] = interfaces[BOUNDARY_pX]; - prim_interfaces[8] = interfaces[BOUNDARY_pX]; - prim_interfaces[9] = interfaces[BOUNDARY_pX]; - - /* Create the scene */ - geom.positions = vertices_2d; - geom.indices = indices_2d; - geom.interfaces = prim_interfaces; - scn_args.get_indices = get_indices_2d; - scn_args.get_interface = get_interface; - scn_args.get_position = get_position_2d; - scn_args.nprimitives = nprimitives_2d; - scn_args.nvertices = nvertices_2d; - scn_args.t_range[0] = 280; - scn_args.t_range[1] = 350; - scn_args.context = &geom; - OK(sdis_scene_2d_create(dev, &scn_args, scn)); -} - -/******************************************************************************* - * Test - ******************************************************************************/ -int -main(int argc, char** argv) -{ - struct mem_allocator allocator; - - struct sdis_device* dev = NULL; - struct sdis_scene* scn_2d = NULL; - struct sdis_scene* scn_3d = NULL; - struct sdis_medium* solid = NULL; - struct sdis_medium* fluid = NULL; - struct sdis_medium* dummy = NULL; - struct sdis_interface* interfaces[INTERFACES_COUNT__]; - - struct solid solid_props; - struct solid* psolid_props; - struct reference_result ref = REFERENCE_RESULT_NULL; - struct interf interf_props; - struct interf* pinterf_props[INTERFACES_COUNT__]; - - size_t i; - (void)argc, (void)argv; - - OK(mem_init_proxy_allocator(&allocator, &mem_default_allocator)); - OK(sdis_device_create(NULL, &allocator, SDIS_NTHREADS_DEFAULT, 1, &dev)); - - /* Solid medium */ - solid_props.lambda = 1.15; - solid_props.rho = 1000; - solid_props.cp = 800; - create_solid(dev, &solid_props, &solid); - - /* Dummy solid medium */ - solid_props.lambda = 0; - solid_props.rho = 1000; - solid_props.cp = 800; - solid_props.volumic_power = SDIS_VOLUMIC_POWER_NONE; - create_solid(dev, &solid_props, &dummy); - - /* Fluid medium */ - create_fluid(dev, &fluid); - - /* Create the adiabatic interface for the solid */ - interf_props.temperature = UNKNOWN_TEMPERATURE; - interf_props.h = -1; - interf_props.emissivity = -1; - interf_props.specular_fraction = -1; - interf_props.Tref = UNKNOWN_TEMPERATURE; - create_interface(dev, solid, dummy, &interf_props, interfaces+ADIABATIC); - - /* Create the interface between the solid and the fluid */ - interf_props.temperature = UNKNOWN_TEMPERATURE; - interf_props.h = 0; - interf_props.emissivity = 1; - interf_props.specular_fraction = 0; - interf_props.Tref = 280; - create_interface(dev, solid, fluid, &interf_props, interfaces+SOLID_FLUID_mX); - interf_props.Tref = 350; - create_interface(dev, solid, fluid, &interf_props, interfaces+SOLID_FLUID_pX); - - /* Create the interface for the fluid on the left */ - interf_props.temperature = 280; - interf_props.h = -1; - interf_props.emissivity = 1; - interf_props.specular_fraction = -1; - interf_props.Tref = 280; - create_interface(dev, fluid, dummy, &interf_props, interfaces+BOUNDARY_mX); - - /* Create the interface for the fluid on the right */ - interf_props.temperature = 350; - interf_props.h = -1; - interf_props.emissivity = 1; - interf_props.specular_fraction = -1; - interf_props.Tref = 350; - create_interface(dev, fluid, dummy, &interf_props, interfaces+BOUNDARY_pX); - - /* Fetch pointers toward the solid and the interfaces */ - psolid_props = sdis_data_get(sdis_medium_get_data(solid)); - FOR_EACH(i, 0, INTERFACES_COUNT__) { - pinterf_props[i] = sdis_data_get(sdis_interface_get_data(interfaces[i])); - } - - create_scene_2d(dev, interfaces, &scn_2d); - create_scene_3d(dev, interfaces, &scn_3d); - - /* Test picard1 with a constant Tref <=> regular linearisation */ - printf("Test Picard1 with a constant Tref of 300 K\n"); - ref.T = 314.99999999999989; - ref.T1 = 307.64122364709766; - ref.T2 = 322.35877635290217; - pinterf_props[SOLID_FLUID_mX]->Tref = 300; - pinterf_props[SOLID_FLUID_pX]->Tref = 300; - pinterf_props[BOUNDARY_mX]->Tref = 300; - pinterf_props[BOUNDARY_pX]->Tref = 300; - test_picard1(scn_2d, &ref); - test_picard1(scn_3d, &ref); - printf("\n"); - - /* Test picard1 using T4 as a reference */ - printf("Test Picard1 using T4 as a reference\n"); - ref.T = 320.37126474482994; - ref.T1 = 312.12650299072266; - ref.T2 = 328.61602649893723; - pinterf_props[SOLID_FLUID_mX]->Tref = ref.T1; - pinterf_props[SOLID_FLUID_pX]->Tref = ref.T2; - pinterf_props[BOUNDARY_mX]->Tref = 280; - pinterf_props[BOUNDARY_pX]->Tref = 350; - test_picard1(scn_2d, &ref); - test_picard1(scn_3d, &ref); - printf("\n"); - -#if 0 - /* Test picardN */ - printf("Test Picard1 using T4 as a reference\n"); - ref.T = 320.37126474482994; - ref.T1 = 312.12650299072266; - ref.T2 = 328.61602649893723; - pinterf_props[SOLID_FLUID_mX]->Tref = 300; - pinterf_props[SOLID_FLUID_pX]->Tref = 300; - pinterf_props[BOUNDARY_mX]->Tref = 280; - pinterf_props[BOUNDARY_pX]->Tref = 350; - test_picard1(scn_2d, &ref); - test_picard1(scn_3d, &ref); - printf("\n"); -#endif - - /* Add volumic power */ - psolid_props->volumic_power = 1000; - - /* Test picard1 with a volumic power and constant Tref */ - printf("Test Picard1 with a volumic power of 1000 W/m^3 and a constant Tref " - "of 300 K\n"); - ref.T = 324.25266420769509; - ref.T1 = 315.80693133305368; - ref.T2 = 330.52448403885825; - pinterf_props[SOLID_FLUID_mX]->Tref = 300; - pinterf_props[SOLID_FLUID_pX]->Tref = 300; - pinterf_props[BOUNDARY_mX]->Tref = 300; - pinterf_props[BOUNDARY_pX]->Tref = 300; - test_picard1(scn_2d, &ref); - test_picard1(scn_3d, &ref); - printf("\n"); - - /* Test picard1 with a volumic power and T4 a the reference */ - printf("Test Picard1 with a volumic power of 1000 W/m^3 and T4 as a reference\n"); - ref.T = 327.95981050850446; - ref.T1 = 318.75148773193359; - ref.T2 = 334.99422024159708; - pinterf_props[SOLID_FLUID_mX]->Tref = ref.T1; - pinterf_props[SOLID_FLUID_pX]->Tref = ref.T2; - pinterf_props[BOUNDARY_mX]->Tref = 280; - pinterf_props[BOUNDARY_pX]->Tref = 350; - test_picard1(scn_2d, &ref); - test_picard1(scn_3d, &ref); - printf("\n"); - - /* Release memory */ - OK(sdis_scene_ref_put(scn_2d)); - OK(sdis_scene_ref_put(scn_3d)); - OK(sdis_interface_ref_put(interfaces[ADIABATIC])); - OK(sdis_interface_ref_put(interfaces[SOLID_FLUID_mX])); - OK(sdis_interface_ref_put(interfaces[SOLID_FLUID_pX])); - OK(sdis_interface_ref_put(interfaces[BOUNDARY_mX])); - OK(sdis_interface_ref_put(interfaces[BOUNDARY_pX])); - OK(sdis_medium_ref_put(fluid)); - OK(sdis_medium_ref_put(solid)); - OK(sdis_medium_ref_put(dummy)); - OK(sdis_device_ref_put(dev)); - - check_memory_allocator(&allocator); - mem_shutdown_proxy_allocator(&allocator); - CHK(mem_allocated_size() == 0); - return 0; -}