commit 0b10594c55e221bb8cdd18e4eec51512f4869bc9
parent dfe2ae42870c4b1023a78f8ff0814e7f128826e4
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Thu, 21 Dec 2017 16:00:52 +0100
Test the sdis_solve_probe function
Diffstat:
6 files changed, 295 insertions(+), 12 deletions(-)
diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt
@@ -113,6 +113,7 @@ if(NOT NO_TEST)
new_test(test_sdis_interface)
new_test(test_sdis_medium)
new_test(test_sdis_scene)
+ new_test(test_sdis_solve_probe)
endif()
################################################################################
diff --git a/src/sdis.h b/src/sdis.h
@@ -96,13 +96,15 @@ struct sdis_mc {
double V; /* Variance */
double SE; /* Standard error */
};
+#define SDIS_MC_NULL__ {0, 0, 0}
+static const struct sdis_mc SDIS_MC_NULL = SDIS_MC_NULL__;
/* Functor type to retrieve the medium properties. */
typedef double
(*sdis_medium_getter_T)
(const struct sdis_rwalk_vertex* vert,
struct sdis_data* data);
-
+
/* Functor type to retrieve the interface properties. */
typedef double
@@ -304,7 +306,7 @@ sdis_estimator_get_temperature
* Miscellaneous functions
******************************************************************************/
SDIS_API res_T
-sdis_solve_probe_temperature
+sdis_solve_probe
(struct sdis_scene* scn,
const size_t nrealisations,
const double position[3],
diff --git a/src/sdis_estimator.c b/src/sdis_estimator.c
@@ -102,6 +102,7 @@ estimator_create(struct sdis_device* dev, struct sdis_estimator** out_estimator)
estimator->dev = dev;
exit:
+ if(out_estimator) *out_estimator = estimator;
return res;
error:
if(estimator) {
diff --git a/src/sdis_scene.c b/src/sdis_scene.c
@@ -152,7 +152,8 @@ setup_geometry
res = s3d_mesh_setup_indexed_vertices(s3d_msh, (unsigned)ntris, get_indices,
(unsigned)nverts, &vdata, 1, &context);
if(res != RES_OK) goto error;
- res = s3d_scene_view_create(s3d_scn, S3D_SAMPLE|S3D_TRACE, &scn->s3d_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:
diff --git a/src/sdis_solve_probe.c b/src/sdis_solve_probe.c
@@ -50,8 +50,9 @@ struct temperature {
struct ssp_rng* rng,
struct temperature* temp);
double value; /* Current value of the temperature */
+ int done;
};
-static const struct temperature TEMPERATURE_NULL = { NULL, -1 };
+static const struct temperature TEMPERATURE_NULL = { NULL, 0, 0 };
static res_T
boundary_temperature
@@ -103,9 +104,10 @@ check_rwalk_fragment_consistency
d2_set_f2(uv, rwalk->hit.uv);
return !S3D_HIT_NONE(&rwalk->hit)
&& d3_eq_eps(rwalk->vtx.P, frag->P, 1.e-6)
- && eq_eps(rwalk->vtx.time, frag->time, 1.e-6)
&& d3_eq_eps(N, frag->Ng, 1.e-6)
- && d2_eq_eps(uv, frag->uv, 1.e-6);
+ && d2_eq_eps(uv, frag->uv, 1.e-6)
+ && ( (IS_INF(rwalk->vtx.time) && IS_INF(frag->time))
+ || eq_eps(rwalk->vtx.time, frag->time, 1.e-6));
}
res_T
@@ -128,6 +130,7 @@ fluid_temperature
return RES_BAD_OP;
}
T->value += tmp;
+ T->done = 1;
return RES_OK;
}
@@ -292,6 +295,7 @@ boundary_temperature
tmp = interface_get_temperature(interface, &frag);
if(tmp >= 0) {
T->value += tmp;
+ T->done = 1;
return RES_OK;
}
@@ -346,6 +350,7 @@ solid_temperature
tmp = solid_get_temperature(mdm, &rwalk->vtx);
if(tmp >= 0) {
T->value += tmp;
+ T->done = 1;
return RES_OK;
}
@@ -384,6 +389,7 @@ solid_temperature
tmp = solid_get_temperature(mdm, &rwalk->vtx);
if(tmp >= 0) {
T->value += tmp;
+ T->done = 1;
return RES_OK;
}
@@ -433,13 +439,13 @@ compute_temperature
res_T res = RES_OK;
ASSERT(scn && fp_to_meter && rwalk && rng && T);
- while(T->value) { /* Unknown temperature */
+ do {
res = T->func(scn, fp_to_meter, rwalk, rng, T);
if(res != RES_OK) goto error;
sa_push(stack, *T);
++istack;
- }
+ } while(!T->done);
exit:
sa_release(stack);
@@ -452,7 +458,7 @@ error:
* Exported functions
******************************************************************************/
res_T
-sdis_solve_probe_temperature
+sdis_solve_probe
(struct sdis_scene* scn,
const size_t nrealisations,
const double position[3],
@@ -468,7 +474,8 @@ sdis_solve_probe_temperature
size_t irealisation = 0;
res_T res = RES_OK;
- if(!scn || !position || time < 0 || fp_to_meter < 0 || !out_estimator) {
+ if(!scn || !nrealisations || !position || time < 0 || fp_to_meter <= 0
+ || !out_estimator) {
res = RES_BAD_ARG;
goto error;
}
@@ -486,8 +493,8 @@ sdis_solve_probe_temperature
struct temperature T = TEMPERATURE_NULL;
switch(medium->type) {
- case SDIS_MEDIUM_FLUID: T.func = solid_temperature; break;
- case SDIS_MEDIUM_SOLID: T.func = fluid_temperature; break;
+ case SDIS_MEDIUM_FLUID: T.func = fluid_temperature; break;
+ case SDIS_MEDIUM_SOLID: T.func = solid_temperature; break;
default: FATAL("Unreachable code\n"); break;
}
diff --git a/src/test_sdis_solve_probe.c b/src/test_sdis_solve_probe.c
@@ -0,0 +1,271 @@
+/* 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 "test_sdis_utils.h"
+
+#include <rsys/math.h>
+
+/*******************************************************************************
+ * Geometry
+ ******************************************************************************/
+struct context {
+ const double* positions;
+ const size_t* indices;
+ struct sdis_interface* interface;
+};
+
+static void
+get_indices(const size_t itri, size_t ids[3], void* context)
+{
+ struct context* ctx = context;
+ ids[0] = ctx->indices[itri*3+0];
+ ids[1] = ctx->indices[itri*3+1];
+ ids[2] = ctx->indices[itri*3+2];
+}
+
+static void
+get_position(const size_t ivert, double pos[3], void* context)
+{
+ struct context* ctx = context;
+ pos[0] = ctx->positions[ivert*3+0];
+ pos[1] = ctx->positions[ivert*3+1];
+ pos[2] = ctx->positions[ivert*3+2];
+}
+
+static void
+get_interface(const size_t itri, struct sdis_interface** bound, void* context)
+{
+ struct context* ctx = context;
+ (void)itri;
+ *bound = ctx->interface;
+}
+
+/*******************************************************************************
+ * Fluid medium
+ ******************************************************************************/
+struct fluid {
+ double temperature;
+};
+
+static double
+fluid_get_temperature
+ (const struct sdis_rwalk_vertex* vtx, struct sdis_data* data)
+{
+ CHK(data != NULL && vtx != NULL);
+ return ((const struct fluid*)sdis_data_cget(data))->temperature;
+}
+
+/*******************************************************************************
+ * Solid medium
+ ******************************************************************************/
+struct solid {
+ double cp;
+ double lambda;
+ double rho;
+ double delta;
+ double temperature;
+};
+
+static double
+solid_get_calorific_capacity
+ (const struct sdis_rwalk_vertex* vtx, struct sdis_data* data)
+{
+ CHK(data != NULL && vtx != NULL);
+ return ((const struct solid*)sdis_data_cget(data))->cp;
+}
+
+static double
+solid_get_thermal_conductivity
+ (const struct sdis_rwalk_vertex* vtx, struct sdis_data* data)
+{
+ CHK(data != NULL && vtx != NULL);
+ return ((const struct solid*)sdis_data_cget(data))->lambda;
+}
+
+static double
+solid_get_volumic_mass
+ (const struct sdis_rwalk_vertex* vtx, struct sdis_data* data)
+{
+ CHK(data != NULL && vtx != NULL);
+ return ((const struct solid*)sdis_data_cget(data))->rho;
+}
+
+static double
+solid_get_delta
+ (const struct sdis_rwalk_vertex* vtx, struct sdis_data* data)
+{
+ CHK(data != NULL && vtx != NULL);
+ return ((const struct solid*)sdis_data_cget(data))->delta;
+}
+
+static double
+solid_get_delta_boundary
+ (const struct sdis_rwalk_vertex* vtx, struct sdis_data* data)
+{
+ CHK(data != NULL && vtx != NULL);
+ return ((const struct solid*)sdis_data_cget(data))->delta * 2.1;
+}
+
+static double
+solid_get_temperature
+ (const struct sdis_rwalk_vertex* vtx, struct sdis_data* data)
+{
+ CHK(data != NULL && vtx != NULL);
+ return ((const struct solid*)sdis_data_cget(data))->temperature;
+}
+
+/*******************************************************************************
+ * Interface
+ ******************************************************************************/
+struct interface {
+ double hc;
+};
+
+static double
+interface_get_convection_coef
+ (const struct sdis_interface_fragment* frag, struct sdis_data* data)
+{
+ CHK(data != NULL && frag != NULL);
+ return ((const struct interface*)sdis_data_cget(data))->hc;
+}
+
+/*******************************************************************************
+ * Test
+ ******************************************************************************/
+int
+main(int argc, char** argv)
+{
+ struct mem_allocator allocator;
+ struct sdis_mc T = SDIS_MC_NULL;
+ struct sdis_device* dev = NULL;
+ struct sdis_medium* solid = NULL;
+ struct sdis_medium* fluid = NULL;
+ struct sdis_interface* interface = NULL;
+ struct sdis_scene* scn = NULL;
+ struct sdis_data* data = NULL;
+ struct sdis_estimator* estimator = NULL;
+ struct sdis_fluid_shader fluid_shader = DUMMY_FLUID_SHADER;
+ struct sdis_solid_shader solid_shader = DUMMY_SOLID_SHADER;
+ struct sdis_interface_shader interface_shader = DUMMY_INTERFACE_SHADER;
+ struct context ctx;
+ struct fluid* fluid_param;
+ struct solid* solid_param;
+ struct interface* interface_param;
+ double pos[3];
+ double time;
+ const size_t N = 1000;
+ size_t nreals;
+ size_t nfails;
+ (void)argc, (void)argv;
+
+ CHK(mem_init_proxy_allocator(&allocator, &mem_default_allocator) == RES_OK);
+ CHK(sdis_device_create
+ (NULL, &allocator, SDIS_NTHREADS_DEFAULT, 0, &dev) == RES_OK);
+
+ /* Create the fluid medium */
+ CHK(sdis_data_create
+ (dev, sizeof(struct fluid), ALIGNOF(struct fluid), NULL, &data) == RES_OK);
+ fluid_param = sdis_data_get(data);
+ fluid_param->temperature = 300;
+ fluid_shader.temperature = fluid_get_temperature;
+ CHK(sdis_fluid_create(dev, &fluid_shader, data, &fluid) == RES_OK);
+ CHK(sdis_data_ref_put(data) == RES_OK);
+
+ /* Create the solid medium */
+ CHK(sdis_data_create
+ (dev, sizeof(struct solid), ALIGNOF(struct solid), NULL, &data) == RES_OK);
+ solid_param = sdis_data_get(data);
+ solid_param->cp = 1.0;
+ solid_param->lambda = 0.1;
+ solid_param->rho = 1.0;
+ solid_param->delta = 1.0/20.0;
+ solid_param->temperature = -1;
+ solid_shader.calorific_capacity = solid_get_calorific_capacity;
+ solid_shader.thermal_conductivity = solid_get_thermal_conductivity;
+ solid_shader.volumic_mass = solid_get_volumic_mass;
+ solid_shader.delta_solid = solid_get_delta;
+ solid_shader.delta_boundary = solid_get_delta_boundary;
+ solid_shader.temperature = solid_get_temperature;
+ CHK(sdis_solid_create(dev, &solid_shader, data, &solid) == RES_OK);
+ CHK(sdis_data_ref_put(data) == RES_OK);
+
+ /* Create the solid/fluid interface */
+ CHK(sdis_data_create(dev, sizeof(struct interface),
+ ALIGNOF(struct interface), NULL, &data) == RES_OK);
+ interface_param = sdis_data_get(data);
+ interface_param->hc = 0.5;
+ interface_shader.convection_coef = interface_get_convection_coef;
+ interface_shader.temperature = NULL;
+ CHK(sdis_interface_create
+ (dev, solid, fluid, &interface_shader, data, &interface) == RES_OK);
+ CHK(sdis_data_ref_put(data) == RES_OK);
+
+ /* Release the media */
+ CHK(sdis_medium_ref_put(solid) == RES_OK);
+ CHK(sdis_medium_ref_put(fluid) == RES_OK);
+
+ /* Create the scene */
+ ctx.positions = box_vertices;
+ ctx.indices = box_indices;
+ ctx.interface = interface;
+ CHK(sdis_scene_create(dev, box_ntriangles, get_indices, get_interface,
+ box_nvertices, get_position, &ctx, &scn) == RES_OK);
+
+ CHK(sdis_interface_ref_put(interface) == RES_OK);
+
+ /* Test the solver */
+ pos[0] = 0.5;
+ pos[1] = 0.5;
+ pos[2] = 0.5;
+ time = INF;
+ CHK(sdis_solve_probe(NULL, N, pos, time, 1.0, &estimator) == RES_BAD_ARG);
+ CHK(sdis_solve_probe(scn, 0, pos, time, 1.0, &estimator) == RES_BAD_ARG);
+ CHK(sdis_solve_probe(scn, N, NULL, time, 1.0, &estimator) == RES_BAD_ARG);
+ CHK(sdis_solve_probe(scn, N, pos, time, 0, &estimator) == RES_BAD_ARG);
+ CHK(sdis_solve_probe(scn, N, pos, time, 1.0, NULL) == RES_BAD_ARG);
+ CHK(sdis_solve_probe(scn, N, pos, time, 1.0, &estimator) == RES_OK);
+
+ CHK(sdis_estimator_get_realisation_count(estimator, NULL) == RES_BAD_ARG);
+ CHK(sdis_estimator_get_realisation_count(NULL, &nreals) == RES_BAD_ARG);
+ CHK(sdis_estimator_get_realisation_count(estimator, &nreals) == RES_OK);
+
+ CHK(sdis_estimator_get_failure_count(estimator, NULL) == RES_BAD_ARG);
+ CHK(sdis_estimator_get_failure_count(NULL, &nfails) == RES_BAD_ARG);
+ CHK(sdis_estimator_get_failure_count(estimator, &nfails) == RES_OK);
+
+ CHK(nfails + nreals == N);
+
+ CHK(sdis_estimator_get_temperature(estimator, NULL) == RES_BAD_ARG);
+ CHK(sdis_estimator_get_temperature(NULL, &T) == RES_BAD_ARG);
+ CHK(sdis_estimator_get_temperature(estimator, &T) == RES_OK);
+
+ CHK(eq_eps(T.E, 300, T.SE));
+
+ CHK(sdis_estimator_ref_get(NULL) == RES_BAD_ARG);
+ CHK(sdis_estimator_ref_get(estimator) == RES_OK);
+ CHK(sdis_estimator_ref_put(NULL) == RES_BAD_ARG);
+ CHK(sdis_estimator_ref_put(estimator) == RES_OK);
+ CHK(sdis_estimator_ref_put(estimator) == RES_OK);
+
+ CHK(sdis_scene_ref_put(scn) == RES_OK);
+ CHK(sdis_device_ref_put(dev) == RES_OK);
+
+ check_memory_allocator(&allocator);
+ mem_shutdown_proxy_allocator(&allocator);
+ CHK(mem_allocated_size() == 0);
+ return 0;
+}
+