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:
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 */
+