stardis-solver

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

commit 29f02068eb7805f0e4793c2046ab06cd58f5a99c
parent 6fdf0552279f3b1d8e296dda218ce00f4b1e4226
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Wed, 17 Jan 2018 10:15:28 +0100

Add support of 2D scenes in the sdis_solve_probe function

Diffstat:
Mcmake/CMakeLists.txt | 2+-
Msrc/sdis_interface.c | 18+++++++++++++++++-
Msrc/sdis_interface_c.h | 9++++++++-
Msrc/sdis_scene.c | 155+++++++++++++++++++++++++++++++++++++++----------------------------------------
Msrc/sdis_solve_probe.c | 36+++++++++++++-----------------------
Msrc/sdis_solve_probe_Xd.h | 52+++++++++++++++++++++++++++++++++++++++++++++++++---
Msrc/test_sdis_utils.h | 21++++++++++++++++++++-
7 files changed, 185 insertions(+), 108 deletions(-)

diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt @@ -26,7 +26,7 @@ option(NO_TEST "Do not build tests" OFF) find_package(RCMake 0.3 REQUIRED) find_package(Star2D 0.1 REQUIRED) find_package(Star3D 0.4 REQUIRED) -find_package(StarSP 0.5 REQUIRED) +find_package(StarSP 0.7 REQUIRED) find_package(RSys 0.6 REQUIRED) find_package(OpenMP 1.2 REQUIRED) diff --git a/src/sdis_interface.c b/src/sdis_interface.c @@ -21,6 +21,7 @@ #include <rsys/double3.h> #include <rsys/mem_allocator.h> +#include <star/s2d.h> #include <star/s3d.h> /******************************************************************************* @@ -176,7 +177,22 @@ interface_get_id(const struct sdis_interface* interf) } void -setup_interface_fragment +setup_interface_fragment_2d + (struct sdis_interface_fragment* frag, + const struct sdis_rwalk_vertex* vertex, + const struct s2d_hit* hit) +{ + ASSERT(frag && vertex && hit && !S2D_HIT_NONE(hit)); + d2_set(frag->P, vertex->P); + frag->P[2] = 0; + d2_normalize(frag->Ng, d2_set_f2(frag->Ng, hit->normal)); + frag->Ng[2] = 0; + frag->uv[0] = hit->u; + frag->time = vertex->time; +} + +void +setup_interface_fragment_3d (struct sdis_interface_fragment* frag, const struct sdis_rwalk_vertex* vertex, const struct s3d_hit* hit) diff --git a/src/sdis_interface_c.h b/src/sdis_interface_c.h @@ -22,6 +22,7 @@ #include <float.h> /* Forward declaration of external type */ +struct s2d_hit; struct s3d_hit; struct sdis_interface { @@ -45,7 +46,13 @@ interface_get_id (const struct sdis_interface* interf); extern LOCAL_SYM void -setup_interface_fragment +setup_interface_fragment_2d + (struct sdis_interface_fragment* frag, + const struct sdis_rwalk_vertex* vertex, + const struct s2d_hit* hit); + +extern LOCAL_SYM void +setup_interface_fragment_3d (struct sdis_interface_fragment* frag, const struct sdis_rwalk_vertex* vertex, const struct s3d_hit* hit); diff --git a/src/sdis_scene.c b/src/sdis_scene.c @@ -39,6 +39,22 @@ struct geometry_context { /******************************************************************************* * Helper function ******************************************************************************/ +/* Check that `hit' roughly lies on a vertex. For segments, a simple but + * approximative way is to test that its position have at least one barycentric + * coordinate roughly equal to 0 or 1. */ +static FINLINE int +hit_on_vertex(const struct s2d_hit* hit) +{ + const float on_vertex_eps = 1.e-4f; + float v; + ASSERT(hit && !S2D_HIT_NONE(hit)); + v = 1.f - hit->u; + return eq_epsf(hit->u, 0.f, on_vertex_eps) + || eq_epsf(hit->u, 1.f, on_vertex_eps) + || eq_epsf(v, 0.f, on_vertex_eps) + || eq_epsf(v, 1.f, on_vertex_eps); +} + /* Check that `hit' roughly lies on an edge. For triangular primitives, a * simple but approximative way is to test that its position have at least one * barycentric coordinate roughly equal to 0 or 1. */ @@ -58,7 +74,7 @@ hit_on_edge(const struct s3d_hit* hit) } static int -hit_filter_function +hit_filter_function_3d (const struct s3d_hit* hit, const float org[3], const float dir[3], @@ -81,22 +97,6 @@ hit_filter_function return 0; } -/* Check that `hit' roughly lies on a vertex. For segments, a simple but - * approximative way is to test that its position have at least one barycentric - * coordinate roughly equal to 0 or 1. */ -static FINLINE int -hit_on_vertex(const struct s2d_hit* hit) -{ - const float on_vertex_eps = 1.e-4f; - float v; - ASSERT(hit && !S2D_HIT_NONE(hit)); - v = 1.f - hit->u; - return eq_epsf(hit->u, 0.f, on_vertex_eps) - || eq_epsf(hit->u, 1.f, on_vertex_eps) - || eq_epsf(v, 0.f, on_vertex_eps) - || eq_epsf(v, 1.f, on_vertex_eps); -} - static int hit_filter_function_2d (const struct s2d_hit* hit, @@ -122,49 +122,49 @@ hit_filter_function_2d } static void -get_indices(const unsigned itri, unsigned out_ids[3], void* data) +get_indices_2d(const unsigned iseg, unsigned out_ids[2], void* data) { struct geometry_context* ctx = data; - size_t ids[3]; + size_t ids[2]; ASSERT(ctx); - ctx->indices(itri, ids, ctx->data); + ctx->indices(iseg, ids, ctx->data); out_ids[0] = (unsigned)ids[0]; out_ids[1] = (unsigned)ids[1]; - out_ids[2] = (unsigned)ids[2]; } static void -get_indices_2d(const unsigned iseg, unsigned out_ids[2], void* data) +get_indices_3d(const unsigned itri, unsigned out_ids[3], void* data) { struct geometry_context* ctx = data; - size_t ids[2]; + size_t ids[3]; ASSERT(ctx); - ctx->indices(iseg, ids, ctx->data); + ctx->indices(itri, ids, ctx->data); out_ids[0] = (unsigned)ids[0]; out_ids[1] = (unsigned)ids[1]; + out_ids[2] = (unsigned)ids[2]; } static void -get_position(const unsigned ivert, float out_pos[3], void* data) +get_position_2d(const unsigned ivert, float out_pos[2], void* data) { struct geometry_context* ctx = data; - double pos[3]; + double pos[2]; ASSERT(ctx); ctx->position(ivert, pos, ctx->data); out_pos[0] = (float)pos[0]; out_pos[1] = (float)pos[1]; - out_pos[2] = (float)pos[2]; } static void -get_position_2d(const unsigned ivert, float out_pos[2], void* data) +get_position_3d(const unsigned ivert, float out_pos[3], void* data) { struct geometry_context* ctx = data; - double pos[2]; + double pos[3]; ASSERT(ctx); ctx->position(ivert, pos, ctx->data); out_pos[0] = (float)pos[0]; out_pos[1] = (float)pos[1]; + out_pos[2] = (float)pos[2]; } static void @@ -229,20 +229,20 @@ error: } static res_T -setup_geometry +setup_geometry_2d (struct sdis_scene* scn, - const size_t ntris, /* #triangles */ - void (*indices)(const size_t itri, size_t ids[3], void*), + const size_t nsegs, /* #segments */ + void (*indices)(const size_t itri, size_t ids[2], void*), const size_t nverts, /* #vertices */ - void (*position)(const size_t ivert, double pos[3], void* ctx), + void (*position)(const size_t ivert, double pos[2], void* ctx), void* ctx) { struct geometry_context context; - struct s3d_shape* s3d_msh = NULL; - struct s3d_scene* s3d_scn = NULL; - struct s3d_vertex_data vdata = S3D_VERTEX_DATA_NULL; + struct s2d_shape* s2d_msh = NULL; + struct s2d_scene* s2d_scn = NULL; + struct s2d_vertex_data vdata = S2D_VERTEX_DATA_NULL; res_T res = RES_OK; - ASSERT(scn && ntris && indices && nverts && position); + ASSERT(scn && nsegs && indices && nverts && position); /* Setup the intermediary geometry context */ context.indices = indices; @@ -250,50 +250,51 @@ setup_geometry context.data = ctx; /* Setup the vertex data */ - vdata.usage = S3D_POSITION; - vdata.type = S3D_FLOAT3; - vdata.get = get_position; + vdata.usage = S2D_POSITION; + vdata.type = S2D_FLOAT2; + vdata.get = get_position_2d; - /* Create the Star-3D geometry */ - res = s3d_scene_create(scn->dev->s3d, &s3d_scn); + /* Create the Star-2D geometry */ + res = s2d_scene_create(scn->dev->s2d, &s2d_scn); if(res != RES_OK) goto error; - res = s3d_shape_create_mesh(scn->dev->s3d, &s3d_msh); + res = s2d_shape_create_line_segments(scn->dev->s2d, &s2d_msh); if(res != RES_OK) goto error; - res = s3d_mesh_set_hit_filter_function(s3d_msh, hit_filter_function, NULL); + res = s2d_line_segments_set_hit_filter_function + (s2d_msh, hit_filter_function_2d, NULL); if(res != RES_OK) goto error; - res = s3d_scene_attach_shape(s3d_scn, s3d_msh); + res = s2d_scene_attach_shape(s2d_scn, s2d_msh); if(res != RES_OK) goto error; - res = s3d_mesh_setup_indexed_vertices(s3d_msh, (unsigned)ntris, get_indices, - (unsigned)nverts, &vdata, 1, &context); + res = s2d_line_segments_setup_indexed_vertices(s2d_msh, (unsigned)nsegs, + get_indices_2d, (unsigned)nverts, &vdata, 1, &context); if(res != RES_OK) goto error; - res = s3d_scene_view_create(s3d_scn, S3D_SAMPLE|S3D_TRACE|S3D_GET_PRIMITIVE, - &scn->s3d_view); + res = s2d_scene_view_create(s2d_scn, S2D_SAMPLE|S2D_TRACE|S2D_GET_PRIMITIVE, + &scn->s2d_view); if(res != RES_OK) goto error; exit: - if(s3d_msh) S3D(shape_ref_put(s3d_msh)); - if(s3d_scn) S3D(scene_ref_put(s3d_scn)); + if(s2d_msh) S2D(shape_ref_put(s2d_msh)); + if(s2d_scn) S2D(scene_ref_put(s2d_scn)); return res; error: - if(scn->s3d_view) S3D(scene_view_ref_put(scn->s3d_view)); + if(scn->s2d_view) S2D(scene_view_ref_put(scn->s2d_view)); goto exit; } static res_T -setup_geometry_2d +setup_geometry_3d (struct sdis_scene* scn, - const size_t nsegs, /* #segments */ - void (*indices)(const size_t itri, size_t ids[2], void*), + const size_t ntris, /* #triangles */ + void (*indices)(const size_t itri, size_t ids[3], void*), const size_t nverts, /* #vertices */ - void (*position)(const size_t ivert, double pos[2], void* ctx), + void (*position)(const size_t ivert, double pos[3], void* ctx), void* ctx) { struct geometry_context context; - struct s2d_shape* s2d_msh = NULL; - struct s2d_scene* s2d_scn = NULL; - struct s2d_vertex_data vdata = S2D_VERTEX_DATA_NULL; + struct s3d_shape* s3d_msh = NULL; + struct s3d_scene* s3d_scn = NULL; + struct s3d_vertex_data vdata = S3D_VERTEX_DATA_NULL; res_T res = RES_OK; - ASSERT(scn && nsegs && indices && nverts && position); + ASSERT(scn && ntris && indices && nverts && position); /* Setup the intermediary geometry context */ context.indices = indices; @@ -301,33 +302,32 @@ setup_geometry_2d context.data = ctx; /* Setup the vertex data */ - vdata.usage = S2D_POSITION; - vdata.type = S2D_FLOAT2; - vdata.get = get_position_2d; + vdata.usage = S3D_POSITION; + vdata.type = S3D_FLOAT3; + vdata.get = get_position_3d; - /* Create the Star-2D geometry */ - res = s2d_scene_create(scn->dev->s2d, &s2d_scn); + /* Create the Star-3D geometry */ + res = s3d_scene_create(scn->dev->s3d, &s3d_scn); if(res != RES_OK) goto error; - res = s2d_shape_create_line_segments(scn->dev->s2d, &s2d_msh); + res = s3d_shape_create_mesh(scn->dev->s3d, &s3d_msh); if(res != RES_OK) goto error; - res = s2d_line_segments_set_hit_filter_function - (s2d_msh, hit_filter_function_2d, NULL); + res = s3d_mesh_set_hit_filter_function(s3d_msh, hit_filter_function_3d, NULL); if(res != RES_OK) goto error; - res = s2d_scene_attach_shape(s2d_scn, s2d_msh); + res = s3d_scene_attach_shape(s3d_scn, s3d_msh); if(res != RES_OK) goto error; - res = s2d_line_segments_setup_indexed_vertices(s2d_msh, (unsigned)nsegs, - get_indices_2d, (unsigned)nverts, &vdata, 1, &context); + res = s3d_mesh_setup_indexed_vertices(s3d_msh, (unsigned)ntris, + get_indices_3d, (unsigned)nverts, &vdata, 1, &context); if(res != RES_OK) goto error; - res = s2d_scene_view_create(s2d_scn, S2D_SAMPLE|S2D_TRACE|S2D_GET_PRIMITIVE, - &scn->s2d_view); + res = s3d_scene_view_create(s3d_scn, S3D_SAMPLE|S3D_TRACE|S3D_GET_PRIMITIVE, + &scn->s3d_view); if(res != RES_OK) goto error; exit: - if(s2d_msh) S2D(shape_ref_put(s2d_msh)); - if(s2d_scn) S2D(scene_ref_put(s2d_scn)); + if(s3d_msh) S3D(shape_ref_put(s3d_msh)); + if(s3d_scn) S3D(scene_ref_put(s3d_scn)); return res; error: - if(scn->s2d_view) S2D(scene_view_ref_put(scn->s2d_view)); + if(scn->s3d_view) S3D(scene_view_ref_put(scn->s3d_view)); goto exit; } @@ -373,7 +373,7 @@ scene_create if(is_2d) { res = setup_geometry_2d(scn, nprims, indices, nverts, position, ctx); } else { - res = setup_geometry(scn, nprims, indices, nverts, position, ctx); + res = setup_geometry_3d(scn, nprims, indices, nverts, position, ctx); } if(res != RES_OK) { log_err(dev, "%s: could not setup the scene geometry.\n", FUNC_NAME); @@ -623,7 +623,6 @@ scene_get_medium const double pos[], const struct sdis_medium** out_medium) { - return scene_is_2d(scn) ? scene_get_medium_2d(scn, pos, out_medium) : scene_get_medium_3d(scn, pos, out_medium); diff --git a/src/sdis_solve_probe.c b/src/sdis_solve_probe.c @@ -18,6 +18,10 @@ #include "sdis_estimator_c.h" #include "sdis_solve_probe_Xd.h" +/* Generate the 2D solver */ +#define SDIS_SOLVE_PROBE_DIMENSION 2 +#include "sdis_solve_probe_Xd.h" + /* Generate the 3D solver */ #define SDIS_SOLVE_PROBE_DIMENSION 3 #include "sdis_solve_probe_Xd.h" @@ -47,12 +51,6 @@ sdis_solve_probe goto error; } - if(scene_is_2d(scn)) { - log_err(scn->dev, "%s: 2D scene are not supported yet.\n", FUNC_NAME); - res = RES_BAD_ARG; - goto error; - } - res = scene_get_medium(scn, position, &medium); if(res != RES_OK) goto error; @@ -62,23 +60,15 @@ sdis_solve_probe if(res != RES_OK) goto error; FOR_EACH(irealisation, 0, nrealisations) { - struct rwalk_3d rwalk = RWALK_NULL_3d; - struct temperature_3d T = TEMPERATURE_NULL_3d; + double w; - switch(medium->type) { - case SDIS_MEDIUM_FLUID: T.func = fluid_temperature_3d; break; - case SDIS_MEDIUM_SOLID: T.func = solid_temperature_3d; break; - default: FATAL("Unreachable code\n"); break; + if(scene_is_2d(scn)) { + res = probe_realisation_2d + (scn, rng, medium, position, time, fp_to_meter, &w); + } else { + res = probe_realisation_3d + (scn, rng, medium, position, time, fp_to_meter, &w); } - - rwalk.vtx.P[0] = position[0]; - rwalk.vtx.P[1] = position[1]; - rwalk.vtx.P[2] = position[2]; - rwalk.vtx.time = time; - rwalk.hit = S3D_HIT_NULL; - rwalk.mdm = medium; - - res = compute_temperature_3d(scn, fp_to_meter, &rwalk, rng, &T); if(res != RES_OK) { if(res == RES_BAD_OP) { ++estimator->nfailures; @@ -86,8 +76,8 @@ sdis_solve_probe goto error; } } else { - weight += T.value; - sqr_weight += T.value*T.value; + weight += w; + sqr_weight += w*w; ++estimator->nrealisations; } } diff --git a/src/sdis_solve_probe_Xd.h b/src/sdis_solve_probe_Xd.h @@ -46,16 +46,23 @@ #error "Invalid dimension "STR(SDIS_SOLVE_PROBE_DIMENSION) #endif +/* Syntactic sugar */ #define DIM SDIS_SOLVE_PROBE_DIMENSION + +/* Star-XD macros generic to SDIS_SOLVE_PROBE_DIMENSION */ #define sXd(Name) CONCAT(CONCAT(CONCAT(s, DIM), d_), Name) #define SXD_HIT_NONE CONCAT(CONCAT(S,DIM), D_HIT_NONE) #define SXD_HIT_NULL CONCAT(CONCAT(S,DIM), D_HIT_NULL) #define SXD_HIT_NULL__ CONCAT(CONCAT(S, DIM), D_HIT_NULL__) #define SXD CONCAT(CONCAT(S, DIM), D) + +/* Vector macros generic to SDIS_SOLVE_PROBE_DIMENSION */ #define dX(Func) CONCAT(CONCAT(CONCAT(d, DIM), _), Func) #define fX(Func) CONCAT(CONCAT(CONCAT(f, DIM), _), Func) #define fX_set_dX CONCAT(CONCAT(CONCAT(f, DIM), _set_d), DIM) #define dX_set_fX CONCAT(CONCAT(CONCAT(d, DIM), _set_f), DIM) + +/* Macro making generic its subimitted name to SDIS_SOLVE_PROBE_DIMENSION */ #define XD(Name) CONCAT(CONCAT(CONCAT(Name, _), DIM), d) /* Current state of the random walk */ @@ -322,7 +329,7 @@ XD(boundary_temperature) ASSERT(scn && fp_to_meter > 0 && rwalk && rng && T); ASSERT(!SXD_HIT_NONE(&rwalk->hit)); - setup_interface_fragment(&frag, &rwalk->vtx, &rwalk->hit); + XD(setup_interface_fragment)(&frag, &rwalk->vtx, &rwalk->hit); /* Retrieve the current interface */ interf = scene_get_interface(scn, rwalk->hit.prim.prim_id); @@ -396,14 +403,19 @@ XD(solid_temperature) rho = solid_get_volumic_mass(mdm, &rwalk->vtx); cp = solid_get_calorific_capacity(mdm, &rwalk->vtx); +#if (SDIS_SOLVE_PROBE_DIMENSION == 2) + /* Sample a direction around 2PI */ + ssp_ran_circle_uniform_float(rng, dir0, NULL); +#else /* Sample a direction around 4PI */ ssp_ran_sphere_uniform_float(rng, dir0, NULL); +#endif /* Trace a ray along the sampled direction and its opposite to check if a * surface is hit in [0, delta_solid]. */ fX_set_dX(org, rwalk->vtx.P); fX(minus)(dir1, dir0); - hit0 = hit1 = S3D_HIT_NULL; + hit0 = hit1 = SXD_HIT_NULL; range[0] = 0.f, range[1] = delta_solid*RAY_RANGE_MAX_SCALE; SXD(scene_view_trace_ray(scn->sXd(view), org, dir0, range, NULL, &hit0)); SXD(scene_view_trace_ray(scn->sXd(view), org, dir1, range, NULL, &hit1)); @@ -417,7 +429,7 @@ XD(solid_temperature) } /* Sample the time */ - mu = (2 * DIM * lambda) / (rho * cp * delta * fp_to_meter * delta * fp_to_meter); + mu = (2*DIM*lambda) / (rho*cp*delta*fp_to_meter*delta*fp_to_meter); tau = ssp_ran_exp(rng, mu); rwalk->vtx.time -= tau; @@ -503,6 +515,40 @@ error: goto exit; } +static res_T +XD(probe_realisation) + (struct sdis_scene* scn, + struct ssp_rng* rng, + const struct sdis_medium* medium, + const double position[], + const double time, + const double fp_to_meter,/* Scale factor from floating point unit to meter */ + double* weight) +{ + struct XD(rwalk) rwalk = XD(RWALK_NULL); + struct XD(temperature) T = XD(TEMPERATURE_NULL); + res_T res = RES_OK; + ASSERT(medium && position && fp_to_meter > 0 && weight && time >= 0); + + switch(medium->type) { + case SDIS_MEDIUM_FLUID: T.func = XD(fluid_temperature); break; + case SDIS_MEDIUM_SOLID: T.func = XD(solid_temperature); break; + default: FATAL("Unreachable code\n"); break; + } + + dX(set)(rwalk.vtx.P, position); + rwalk.vtx.time = time; + rwalk.hit = SXD_HIT_NULL; + rwalk.mdm = medium; + + res = XD(compute_temperature)(scn, fp_to_meter, &rwalk, rng, &T); + if(res != RES_OK) return res; + + *weight = T.value; + return RES_OK; +} + + #undef SDIS_SOLVE_PROBE_DIMENSION #undef DIM #undef sXd diff --git a/src/test_sdis_utils.h b/src/test_sdis_utils.h @@ -20,7 +20,7 @@ #include <stdio.h> /******************************************************************************* - * Geometry + * Box geometry ******************************************************************************/ static const double box_vertices[8/*#vertices*/*3/*#coords per vertex*/] = { 0.0, 0.0, 0.0, @@ -55,6 +55,25 @@ static const size_t box_indices[12/*#triangles*/*3/*#indices per triangle*/] = { static const size_t box_ntriangles = sizeof(box_indices) / sizeof(size_t[3]); /******************************************************************************* + * Square geometry + ******************************************************************************/ +static const double square_vertices[4/*#vertices*/*2/*#coords per vertex*/] = { + 1.0, 0.0, + 0.0, 0.0, + 0.0, 1.0, + 1.0, 1.0 +}; +static const size_t square_nvertices = sizeof(square_vertices)/sizeof(double[2]); + +static const size_t square_indices[4/*#triangles*/*2/*#indices per segment*/]= { + 0, 1, /* Bottom */ + 1, 2, /* Left */ + 2, 3, /* Top */ + 3, 0 /* Right */ +}; +static const size_t square_nsegments = sizeof(square_indices)/sizeof(size_t[2]); + +/******************************************************************************* * Medium & interface ******************************************************************************/ static INLINE double