stardis-solver

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

commit c18be649d7ac8fda4d2ca2cc16989901179c7a5a
parent 8f8576520edacb95e9e174a06efc1ead45583251
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Thu, 21 Dec 2017 10:23:43 +0100

Implement the estimator API

Diffstat:
Mcmake/CMakeLists.txt | 13+++++++++----
Msrc/sdis.h | 57++++++++++++++++++++++++++++++++++++++++++++++++++++-----
Asrc/sdis_estimator.c | 113+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/sdis_estimator_c.h | 43+++++++++++++++++++++++++++++++++++++++++++
Msrc/sdis_interface.c | 40++++++++++++++++++++++++++++++----------
Msrc/sdis_interface_c.h | 53+++++++++++++++++++++++++++++++++++++++++++++++++++--
Msrc/sdis_medium.c | 18+++---------------
Asrc/sdis_medium_c.h | 131+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/sdis_scene.c | 154++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------------
Asrc/sdis_scene_c.h | 76++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/test_sdis_medium.c | 8++++----
Msrc/test_sdis_scene.c | 1+
Msrc/test_sdis_utils.h | 1+
13 files changed, 635 insertions(+), 73 deletions(-)

diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt @@ -45,6 +45,7 @@ set(VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}) set(SDIS_FILES_SRC sdis_data.c sdis_device.c + sdis_estimator.c sdis_interface.c sdis_medium.c sdis_scene.c) @@ -53,7 +54,11 @@ set(SDIS_FILES_INC_API sdis.h) set(SDIS_FILES_INC - sdis_device_c.h) + sdis_device_c.h + sdis_estimator_c.h + sdis_interface_c.h + sdis_medium_c.h + sdis_scene_c.h) set(SDIS_FILES_DOC COPYING README.md) @@ -63,8 +68,8 @@ rcmake_prepend_path(SDIS_FILES_INC ${SDIS_SOURCE_DIR}) rcmake_prepend_path(SDIS_FILES_INC_API ${SDIS_SOURCE_DIR}) rcmake_prepend_path(SDIS_FILES_DOC ${PROJECT_SOURCE_DIR}/../) -add_library(sdis SHARED - ${SDIS_FILES_SRC} +add_library(sdis SHARED + ${SDIS_FILES_SRC} ${SDIS_FILES_INC} ${SDIS_FILES_INC_API}) target_link_libraries(sdis RSys Star3D) @@ -77,7 +82,7 @@ set_target_properties(sdis PROPERTIES rcmake_copy_runtime_libraries(sdis) if(CMAKE_COMPILER_IS_GNUCC) - set_target_properties(sdis PROPERTIES LINK_FLAGS ${OpenMP_C_FLAGS}) + set_target_properties(sdis PROPERTIES LINK_FLAGS "${OpenMP_C_FLAGS} -lm") endif() rcmake_setup_devel(sdis Stardis ${VERSION} sdis_version.h) diff --git a/src/sdis.h b/src/sdis.h @@ -52,6 +52,7 @@ struct mem_allocator; * counter, respectively. When this counter reach 0 the object is silently * destroyed and cannot be used anymore. */ struct sdis_device; +struct sdis_estimator; struct sdis_interface; struct sdis_medium; struct sdis_data; @@ -89,6 +90,13 @@ struct sdis_interface_fragment { static const struct sdis_interface_fragment SDIS_INTERFACE_FRAGMENT_NULL = SDIS_INTERFACE_FRAGMENT_NULL__; +/* Monte-Carlo estimation */ +struct sdis_mc { + double E; /* Expected value */ + double V; /* Variance */ + double SE; /* Standard error */ +}; + /* Functor type to retrieve the medium properties. */ typedef void (*sdis_medium_getter_T) @@ -113,8 +121,9 @@ struct sdis_solid_shader { sdis_medium_getter_T delta_solid; sdis_medium_getter_T delta_boundary; - /* Initial condition */ - sdis_medium_getter_T initial_temperature; + /* Initial/limit condition. A temperature < 0 means that the temperature is + * unknown for the submitted random walk vertex. */ + sdis_medium_getter_T temperature; }; #define SDIS_SOLID_SHADER_NULL__ {NULL} static const struct sdis_solid_shader SDIS_SOLID_SHADER_NULL = @@ -125,15 +134,16 @@ struct sdis_fluid_shader { sdis_medium_getter_T calorific_capacity; sdis_medium_getter_T volumic_mass; - /* Initial condition */ - sdis_medium_getter_T initial_temperature; + /* Initial/limit condition. A temperature < 0 means that the temperature is + * unknown for the submitted position and time. */ + sdis_medium_getter_T temperature; }; #define SDIS_FLUID_SHADER_NULL__ {NULL} static const struct sdis_fluid_shader SDIS_FLUID_SHADER_NULL = SDIS_FLUID_SHADER_NULL__; struct sdis_interface_shader { - sdis_interface_getter_T temperature; /* NULL <=> Unknown temperature */ + sdis_interface_getter_T temperature; /* Limit condition. NULL <=> Unknown */ sdis_interface_getter_T convection_coef; /* NULL <=> Solid/Solid interface */ }; #define SDIS_INTERFACE_SHADER_NULL__ {NULL} @@ -267,6 +277,43 @@ sdis_scene_get_aabb double lower[3], double upper[3]); +/******************************************************************************* + * An estimator stores the state of a simulation + ******************************************************************************/ +SDIS_API res_T +sdis_estimator_ref_get + (struct sdis_estimator* estimator); + +SDIS_API res_T +sdis_estimator_ref_put + (struct sdis_estimator* estimator); + +SDIS_API res_T +sdis_estimator_get_realisation_count + (const struct sdis_estimator* estimator, + size_t* nrealisations); + +SDIS_API res_T +sdis_estimator_get_failure_count + (const struct sdis_estimator* estimator, + size_t* nfailures); + +SDIS_API res_T +sdis_estimator_get_temperature + (const struct sdis_estimator* estimator, + struct sdis_mc* temperature); + +/******************************************************************************* + * Miscellaneous functions + ******************************************************************************/ +SDIS_API res_T +sdis_solve_probe_temperature + (struct sdis_scene* scn, + const double position[3], + const double time, + const double fp_to_meter,/* Scale factor from floating point unit to meter */ + struct sdis_estimator** estimator); + END_DECLS #endif /* SDIS_H */ diff --git a/src/sdis_estimator.c b/src/sdis_estimator.c @@ -0,0 +1,113 @@ +/* Copyright (C) |Meso|Star> 2016-2017 (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 "sdis_device_c.h" +#include "sdis_estimator_c.h" + +/******************************************************************************* + * Helper functions + ******************************************************************************/ +static void +estimator_release(ref_T* ref) +{ + struct sdis_estimator* estimator = NULL; + struct sdis_device* dev = NULL; + ASSERT(ref); + estimator = CONTAINER_OF(ref, struct sdis_estimator, ref); + dev = estimator->dev; + MEM_RM(dev->allocator, estimator); + SDIS(device_ref_put(dev)); +} + +/******************************************************************************* + * Exported functions + ******************************************************************************/ +res_T +sdis_estimator_ref_get(struct sdis_estimator* estimator) +{ + if(!estimator) return RES_BAD_ARG; + ref_get(&estimator->ref); + return RES_OK; +} + +res_T +sdis_estimator_ref_put(struct sdis_estimator* estimator) +{ + if(!estimator) return RES_BAD_ARG; + ref_put(&estimator->ref, estimator_release); + return RES_OK; +} + +res_T +sdis_estimator_get_realisation_count + (const struct sdis_estimator* estimator, size_t* nrealisations) +{ + if(!estimator || !nrealisations) return RES_BAD_ARG; + *nrealisations = estimator->nrealisations; + return RES_OK; +} + +res_T +sdis_estimator_get_failure_count + (const struct sdis_estimator* estimator, size_t* nfailures) +{ + if(!estimator || !nfailures) return RES_BAD_ARG; + *nfailures = estimator->nfailures; + return RES_OK; +} + +res_T +sdis_estimator_get_temperature + (const struct sdis_estimator* estimator, struct sdis_mc* mc) +{ + if(!estimator || !mc) return RES_BAD_ARG; + *mc = estimator->temperature; + return RES_OK; +} + +/******************************************************************************* + * Local functions + ******************************************************************************/ +res_T +estimator_create(struct sdis_device* dev, struct sdis_estimator** out_estimator) +{ + struct sdis_estimator* estimator = NULL; + res_T res = RES_OK; + + if(!dev || !out_estimator) { + res = RES_BAD_ARG; + goto error; + } + + estimator = MEM_CALLOC(dev->allocator, 1, sizeof(struct sdis_estimator)); + if(!estimator) { + res = RES_MEM_ERR; + goto error; + } + ref_init(&estimator->ref); + SDIS(device_ref_get(dev)); + estimator->dev = dev; + +exit: + return res; +error: + if(estimator) { + SDIS(estimator_ref_put(estimator)); + estimator = NULL; + } + goto exit; +} + diff --git a/src/sdis_estimator_c.h b/src/sdis_estimator_c.h @@ -0,0 +1,43 @@ +/* Copyright (C) |Meso|Star> 2016-2017 (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/>. */ + +#ifndef SDIS_ESTIMATOR_C_H +#define SDIS_ESTIMATOR_C_H + +#include <rsys/ref_count.h> + +/* Forward declarations */ +struct sdis_device; +struct sdis_estimator; + +struct sdis_estimator { + struct sdis_mc temperature; + size_t nrealisations; + size_t nfailures; + + ref_T ref; + struct sdis_device* dev; +}; + +/******************************************************************************* + * Estmator data structure + ******************************************************************************/ +extern LOCAL_SYM res_T +estimator_create + (struct sdis_device* dev, + struct sdis_estimator** estimator); + +#endif /* SDIS_PROBE_ESTIMATOR_C_H */ + diff --git a/src/sdis_interface.c b/src/sdis_interface.c @@ -17,18 +17,11 @@ #include "sdis_device_c.h" #include "sdis_interface_c.h" +#include <rsys/double2.h> +#include <rsys/double3.h> #include <rsys/mem_allocator.h> -struct sdis_interface { - struct sdis_medium* medium_front; - struct sdis_medium* medium_back; - struct sdis_interface_shader shader; - struct sdis_data* data; - struct fid id; /* Unique identifier of the interface */ - - ref_T ref; - struct sdis_device* dev; -}; +#include <star/s3d.h> /******************************************************************************* * Helper functions @@ -161,6 +154,20 @@ sdis_interface_ref_put(struct sdis_interface* interface) /******************************************************************************* * Local function ******************************************************************************/ +const struct sdis_medium* +interface_get_medium + (const struct sdis_interface* interface, const enum sdis_side_flag side) +{ + struct sdis_medium* mdm = NULL; + ASSERT(interface); + switch(side) { + case SDIS_FRONT: mdm = interface->medium_front; break; + case SDIS_BACK: mdm = interface->medium_back; break; + default: FATAL("Unreachable code.\n"); break; + } + return mdm; +} + unsigned interface_get_id(const struct sdis_interface* interface) { @@ -168,3 +175,16 @@ interface_get_id(const struct sdis_interface* interface) return interface->id.index; } +void +setup_interface_fragment + (struct sdis_interface_fragment* frag, + const struct sdis_rwalk_vertex* vertex, + const struct s3d_hit* hit) +{ + ASSERT(frag && vertex && hit && !S3D_HIT_NONE(hit)); + d3_set(frag->P, vertex->P); + d3_normalize(frag->Ng, d3_set_f3(frag->Ng, hit->normal)); + d2_set_f2(frag->uv, hit->uv); + frag->time = vertex->time; +} + diff --git a/src/sdis_interface_c.h b/src/sdis_interface_c.h @@ -16,13 +16,62 @@ #ifndef SDIS_INTERFACE_C_H #define SDIS_INTERFACE_C_H -#include <rsys/rsys.h> +#include "sdis.h" +#include <rsys/free_list.h> +#include <rsys/ref_count.h> +#include <float.h> -struct sdis_interface; +/* Forward declaration of external type */ +struct s3d_hit; + +struct sdis_interface { + struct sdis_medium* medium_front; + struct sdis_medium* medium_back; + struct sdis_interface_shader shader; + struct sdis_data* data; + struct fid id; /* Unique identifier of the interface */ + + ref_T ref; + struct sdis_device* dev; +}; + +extern LOCAL_SYM const struct sdis_medium* +interface_get_medium + (const struct sdis_interface* interface, + const enum sdis_side_flag side); extern LOCAL_SYM unsigned interface_get_id (const struct sdis_interface* interface); +extern LOCAL_SYM void +setup_interface_fragment + (struct sdis_interface_fragment* frag, + const struct sdis_rwalk_vertex* vertex, + const struct s3d_hit* hit); + +static INLINE double +interface_get_temperature + (const struct sdis_interface* interface, + const struct sdis_interface_fragment* frag) +{ + double T = -1; + ASSERT(interface && frag); + if(!interface->shader.temperature) return -DBL_MAX; + interface->shader.temperature(interface->dev, interface->data, frag, &T); + return T; +} + +static INLINE double +interface_get_convection_coef + (const struct sdis_interface* interface, + const struct sdis_interface_fragment* frag) +{ + double hc = -1; + ASSERT(interface && frag); + interface->shader.convection_coef(interface->dev, interface->data, frag, &hc); + return hc; +} + #endif /* SDIS_INTERFACE_C_H */ diff --git a/src/sdis_medium.c b/src/sdis_medium.c @@ -15,22 +15,10 @@ #include "sdis.h" #include "sdis_device_c.h" +#include "sdis_medium_c.h" #include <rsys/mem_allocator.h> -struct sdis_medium { - enum sdis_medium_type type; - union { - struct sdis_solid_shader solid; - struct sdis_fluid_shader fluid; - } shader; - - struct sdis_data* data; - - ref_T ref; - struct sdis_device* dev; -}; - /******************************************************************************* * Helper functions ******************************************************************************/ @@ -40,7 +28,7 @@ check_fluid_shader(const struct sdis_fluid_shader* shader) ASSERT(shader); return shader->calorific_capacity && shader->volumic_mass - && shader->initial_temperature; + && shader->temperature; } static int @@ -52,7 +40,7 @@ check_solid_shader(const struct sdis_solid_shader* shader) && shader->volumic_mass && shader->delta_solid && shader->delta_boundary - && shader->initial_temperature; + && shader->temperature; } static res_T diff --git a/src/sdis_medium_c.h b/src/sdis_medium_c.h @@ -0,0 +1,131 @@ +/* Copyright (C) |Meso|Star> 2016-2017 (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/>. */ + +#ifndef SDIS_MEDIUM_C_H +#define SDIS_MEDIUM_C_H + +#include "sdis.h" + +struct sdis_medium { + enum sdis_medium_type type; + union { + struct sdis_solid_shader solid; + struct sdis_fluid_shader fluid; + } shader; + + struct sdis_data* data; + + ref_T ref; + struct sdis_device* dev; +}; + +/******************************************************************************* + * Fluid local functions + ******************************************************************************/ +static INLINE double +fluid_get_calorific_capacity + (struct sdis_medium* mdm, const struct sdis_rwalk_vertex* vtx) +{ + double cp = -1; + ASSERT(mdm && mdm->type == SDIS_MEDIUM_FLUID); + mdm->shader.fluid.calorific_capacity(mdm->dev, mdm->data, vtx, &cp); + return cp; +} + +static INLINE double +fluid_get_volumic_mass + (struct sdis_medium* mdm, const struct sdis_rwalk_vertex* vtx) +{ + double rho = -1; + ASSERT(mdm && mdm->type == SDIS_MEDIUM_FLUID); + mdm->shader.fluid.volumic_mass(mdm->dev, mdm->data, vtx, &rho); + return rho; +} + +static INLINE double +fluid_get_temperature + (struct sdis_medium* mdm, const struct sdis_rwalk_vertex* vtx) +{ + double T = -1; + ASSERT(mdm && mdm->type == SDIS_MEDIUM_FLUID); + mdm->shader.fluid.temperature(mdm->dev, mdm->data, vtx, &T); + return T; +} + +/******************************************************************************* + * Solid local functions + ******************************************************************************/ +static INLINE double +solid_get_calorific_capacity + (struct sdis_medium* mdm, const struct sdis_rwalk_vertex* vtx) +{ + double cp = -1; + ASSERT(mdm && mdm->type == SDIS_MEDIUM_SOLID); + mdm->shader.solid.calorific_capacity(mdm->dev, mdm->data, vtx, &cp); + return cp; +} + +static INLINE double +solid_get_thermal_conductivity + (struct sdis_medium* mdm, const struct sdis_rwalk_vertex* vtx) +{ + double lambda = -1; + ASSERT(mdm && mdm->type == SDIS_MEDIUM_SOLID); + mdm->shader.solid.thermal_conductivity(mdm->dev, mdm->data, vtx, &lambda); + return lambda; +} + +static INLINE double +solid_get_volumic_mass + (struct sdis_medium* mdm, const struct sdis_rwalk_vertex* vtx) +{ + double rho = -1; + ASSERT(mdm && mdm->type == SDIS_MEDIUM_SOLID); + mdm->shader.solid.volumic_mass(mdm->dev, mdm->data, vtx, &rho); + return rho; +} + +static INLINE double +solid_get_delta + (struct sdis_medium* mdm, const struct sdis_rwalk_vertex* vtx) +{ + double delta = -1; + ASSERT(mdm && mdm->type == SDIS_MEDIUM_SOLID); + mdm->shader.solid.delta_solid(mdm->dev, mdm->data, vtx, &delta); + return delta; +} + +static INLINE double +solid_get_delta_boundary + (struct sdis_medium* mdm, const struct sdis_rwalk_vertex* vtx) +{ + double delta_bound = -1; + ASSERT(mdm && mdm->type == SDIS_MEDIUM_SOLID); + mdm->shader.solid.delta_boundary(mdm->dev, mdm->data, vtx, &delta_bound); + return delta_bound; +} + +static INLINE double +solid_get_temperature + (struct sdis_medium* mdm, const struct sdis_rwalk_vertex* vtx) +{ + double T = -1; + ASSERT(mdm && mdm->type == SDIS_MEDIUM_SOLID); + mdm->shader.solid.temperature(mdm->dev, mdm->data, vtx, &T); + return T; +} + +#endif /* SDIS_MEDIUM_C_H */ + diff --git a/src/sdis_scene.c b/src/sdis_scene.c @@ -16,45 +16,16 @@ #include "sdis.h" #include "sdis_device_c.h" #include "sdis_interface_c.h" +#include "sdis_scene_c.h" +#include <rsys/float3.h> #include <rsys/double3.h> -#include <rsys/dynamic_array.h> #include <rsys/mem_allocator.h> + #include <star/s3d.h> #include <limits.h> -/* Context used to wrap the user geometry to Star-3D. */ -struct geometry_context { - void (*indices)(const size_t itri, size_t ids[3], void*); - void (*position)(const size_t ivert, double pos[3], void*); - void* data; -}; - -static INLINE void -interface_init - (struct mem_allocator* allocator, - struct sdis_interface** interface) -{ - (void)allocator; - *interface = NULL; -} - -/* Declare the array of interfaces */ -#define DARRAY_NAME interface -#define DARRAY_DATA struct sdis_interface* -#define DARRAY_FUNCTOR_INIT interface_init -#include <rsys/dynamic_array.h> - -struct sdis_scene { - struct darray_interface interfaces; /* List of interfaces own by the scene */ - struct darray_interface prim_interfaces; /* Per primitive interface */ - struct s3d_scene_view* s3d_view; - - ref_T ref; - struct sdis_device* dev; -}; - /******************************************************************************* * Helper function ******************************************************************************/ @@ -174,6 +145,8 @@ setup_geometry if(res != RES_OK) goto error; res = s3d_shape_create_mesh(scn->dev->s3d, &s3d_msh); if(res != RES_OK) goto error; + res = s3d_mesh_set_hit_filter_function(s3d_msh, hit_filter_function, NULL); + if(res != RES_OK) goto error; res = s3d_scene_attach_shape(s3d_scn, s3d_msh); if(res != RES_OK) goto error; res = s3d_mesh_setup_indexed_vertices(s3d_msh, (unsigned)ntris, get_indices, @@ -191,6 +164,24 @@ error: goto exit; } +/* 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. */ +static FINLINE int +hit_on_edge(const struct s3d_hit* hit) +{ + const float on_edge_eps = 1.e-4f; + float w; + ASSERT(hit && !S3D_HIT_NONE(hit)); + w = 1.f - hit->uv[0] - hit->uv[1]; + return eq_epsf(hit->uv[0], 0.f, on_edge_eps) + || eq_epsf(hit->uv[0], 1.f, on_edge_eps) + || eq_epsf(hit->uv[1], 0.f, on_edge_eps) + || eq_epsf(hit->uv[1], 1.f, on_edge_eps) + || eq_epsf(w, 0.f, on_edge_eps) + || eq_epsf(w, 1.f, on_edge_eps); +} + static void scene_release(ref_T * ref) { @@ -224,7 +215,7 @@ sdis_scene_create struct sdis_scene* scn = NULL; res_T res = RES_OK; - if(!dev || !out_scn || !ntris || !indices || !interface || !nverts + if(!dev || !out_scn || !ntris || !indices || !interface || !nverts || !position || ntris > UINT_MAX || nverts > UINT_MAX) { res = RES_BAD_ARG; goto error; @@ -295,3 +286,100 @@ sdis_scene_get_aabb return RES_OK; } +/******************************************************************************* + * Local miscellaneous function + ******************************************************************************/ +const struct sdis_interface* +scene_get_interface(const struct sdis_scene* scn, const unsigned iprim) +{ + ASSERT(scn && iprim < darray_interface_size_get(&scn->prim_interfaces)); + return darray_interface_cdata_get(&scn->prim_interfaces)[iprim]; +} + +res_T +scene_get_medium + (const struct sdis_scene* scn, + const double pos[3], + const struct sdis_medium** out_medium) +{ + const struct sdis_medium* medium = NULL; + size_t iprim, nprims; + size_t nfailures = 0; + const size_t max_failures = 10; + res_T res = RES_OK; + ASSERT(scn && pos); + + S3D(scene_view_primitives_count(scn->s3d_view, &nprims)); + FOR_EACH(iprim, 0, nprims) { + struct s3d_hit hit; + struct s3d_attrib attr; + struct s3d_primitive prim; + const float st[2] = { 1.f/3.f, 1.f/3.f }; + const float range[2] = {0.f, FLT_MAX}; + float N[3], P[3], dir[3], cos_N_dir; + + /* Retrieve a position onto the primitive */ + S3D(scene_view_get_primitive(scn->s3d_view, (unsigned)iprim, &prim)); + S3D(primitive_get_attrib(&prim, S3D_POSITION, st, &attr)); + + /* Trace a ray from the randomw walk vertex toward the retrieved primitive + * position */ + f3_normalize(dir, f3_sub(dir, attr.value, f3_set_d3(P, pos))); + S3D(scene_view_trace_ray(scn->s3d_view, P, dir, range, NULL, &hit)); + + f3_normalize(N, hit.normal); + cos_N_dir = f3_dot(N, dir); + + /* Unforeseen error. One has to intersect a primitive ! */ + if(S3D_HIT_NONE(&hit)) { + ++nfailures; + if(nfailures < max_failures) { + continue; + } else { + res = RES_BAD_ARG; + goto error; + } + } + + if(absf(cos_N_dir) > 1.e-1f) { /* Not roughly orthognonal */ + const struct sdis_interface* interface; + interface = scene_get_interface(scn, hit.prim.prim_id); + medium = interface_get_medium + (interface, cos_N_dir < 0 ? SDIS_FRONT : SDIS_BACK); + break; + } + } + +exit: + *out_medium = medium; + return res; +error: + log_err(scn->dev, "%s: could not retrieve the medium at {%g, %g, %g}.\n", + FUNC_NAME, SPLIT3(pos)); + goto exit; +} + +int +hit_filter_function + (const struct s3d_hit* hit, + const float org[3], + const float dir[3], + void* ray_data, + void* filter_data) +{ + const struct s3d_hit* hit_from = ray_data; + (void)org, (void)dir, (void)filter_data; + + if(!hit_from || S3D_HIT_NONE(hit_from)) return 0; /* No filtering */ + + if(S3D_PRIMITIVE_EQ(&hit_from->prim, &hit->prim)) return 1; + + if(eq_epsf(hit->distance, 0, 1.e-6f)) { + /* If the targeted point is near of the origin, check that it lies on an + * edge shared by the 2 primitives. */ + return hit_on_edge(hit_from) && hit_on_edge(hit); + } + + return 0; +} + diff --git a/src/sdis_scene_c.h b/src/sdis_scene_c.h @@ -0,0 +1,76 @@ +/* Copyright (C) |Meso|Star> 2016-2017 (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/>. */ + +#ifndef SDIS_SCENE_C_H +#define SDIS_SCENE_C_H + +#include <rsys/dynamic_array.h> +#include <rsys/ref_count.h> + +/* Forward declaration of external types */ +struct s3d_hit; + +/* Context used to wrap the user geometry to Star-3D. */ +struct geometry_context { + void (*indices)(const size_t itri, size_t ids[3], void*); + void (*position)(const size_t ivert, double pos[3], void*); + void* data; +}; + +static INLINE void +interface_init + (struct mem_allocator* allocator, + struct sdis_interface** interface) +{ + (void)allocator; + *interface = NULL; +} + +/* Declare the array of interfaces */ +#define DARRAY_NAME interface +#define DARRAY_DATA struct sdis_interface* +#define DARRAY_FUNCTOR_INIT interface_init +#include <rsys/dynamic_array.h> + +struct sdis_scene { + struct darray_interface interfaces; /* List of interfaces own by the scene */ + struct darray_interface prim_interfaces; /* Per primitive interface */ + struct s3d_scene_view* s3d_view; + + ref_T ref; + struct sdis_device* dev; +}; + +extern LOCAL_SYM const struct sdis_interface* +scene_get_interface + (const struct sdis_scene* scene, + const unsigned iprim); + +extern LOCAL_SYM res_T +scene_get_medium + (const struct sdis_scene* scene, + const double position[3], + const struct sdis_medium** medium); + +extern LOCAL_SYM int +hit_filter_function + (const struct s3d_hit* hit, + const float ray_org[3], + const float ray_dir[3], + void* ray_data, /* struct s3d_hit* */ + void* filter_data); /* NULL */ + +#endif /* SDIS_SCENE_C_H */ + diff --git a/src/test_sdis_medium.c b/src/test_sdis_medium.c @@ -54,9 +54,9 @@ main(int argc, char** argv) CHK(sdis_fluid_create(dev, &fluid_shader, NULL, &fluid) == RES_BAD_ARG); fluid_shader.volumic_mass = DUMMY_FLUID_SHADER.volumic_mass; - fluid_shader.initial_temperature = NULL; + fluid_shader.temperature = NULL; CHK(sdis_fluid_create(dev, &fluid_shader, NULL, &fluid) == RES_BAD_ARG); - fluid_shader.initial_temperature = DUMMY_FLUID_SHADER.initial_temperature; + fluid_shader.temperature = DUMMY_FLUID_SHADER.temperature; CHK(sdis_fluid_create (dev, &SDIS_FLUID_SHADER_NULL, NULL, &fluid) == RES_BAD_ARG); @@ -91,9 +91,9 @@ main(int argc, char** argv) CHK(sdis_solid_create(dev, &solid_shader, NULL, &solid) == RES_BAD_ARG); solid_shader.delta_boundary = DUMMY_SOLID_SHADER.delta_boundary; - solid_shader.initial_temperature = NULL; + solid_shader.temperature = NULL; CHK(sdis_solid_create(dev, &solid_shader, NULL, &solid) == RES_BAD_ARG); - solid_shader.initial_temperature = DUMMY_SOLID_SHADER.initial_temperature; + solid_shader.temperature = DUMMY_SOLID_SHADER.temperature; CHK(sdis_device_ref_put(dev) == RES_OK); diff --git a/src/test_sdis_scene.c b/src/test_sdis_scene.c @@ -131,3 +131,4 @@ main(int argc, char** argv) CHK(mem_allocated_size() == 0); return 0; } + diff --git a/src/test_sdis_utils.h b/src/test_sdis_utils.h @@ -116,3 +116,4 @@ check_memory_allocator(struct mem_allocator* allocator) } #endif /* TEST_SDIS_UTILS_H */ +