solstice-solver

Solver library of the solstice app
git clone git://git.meso-star.com/solstice-solver.git
Log | Files | Refs | README | LICENSE

commit 6548e67fcbe947a8b9aef797bcccb7429e4243ff
parent 643459fb2dc5ebe4ef4f3223ad5fff49b8599828
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Tue, 14 Mar 2017 08:10:53 +0100

Fix the per receiver primitive integration and accessors

The per primitive integration was wrong if the receiver was composed by
several shapes. To handle this issue, this commit adds a per
instantiated shape indirection to access the per receiver primitives.

Diffstat:
Msrc/ssol.h | 21++++++++++++++-------
Msrc/ssol_estimator_c.h | 148++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------------
Msrc/ssol_mc_receiver.c | 74+++++++++++++++++++++++++++++++++++++++++++-------------------------------
Msrc/ssol_solver.c | 73+++++++++++++++++++++++++++++++++++++++++++++++++++----------------------
Msrc/test_ssol_solver1.c | 39++++++++++++++++++++++++---------------
5 files changed, 229 insertions(+), 126 deletions(-)

diff --git a/src/ssol.h b/src/ssol.h @@ -313,7 +313,13 @@ struct ssol_mc_receiver { /* Internal data */ size_t N__; - const void* mc__; + void* mc__; +}; + +struct ssol_mc_shape { + /* Internal data */ + size_t N__; + void* mc__; }; struct ssol_mc_primitive { @@ -940,14 +946,15 @@ ssol_estimator_get_mc_receiver struct ssol_mc_receiver* rcv); SSOL_API res_T -ssol_mc_receiver_get_mc_primitives_count - (const struct ssol_mc_receiver* rcv, - size_t* count); +ssol_mc_receiver_get_mc_shape + (struct ssol_mc_receiver* rcv, + const struct ssol_shape* shape, + struct ssol_mc_shape* mc); SSOL_API res_T -ssol_mc_receiver_get_mc_primitive - (const struct ssol_mc_receiver* rcv, - const size_t i, +ssol_mc_shape_get_mc_primitive + (struct ssol_mc_shape* shape, + const unsigned i, /* In [0, ssol_shape_get_triangles_count[ */ struct ssol_mc_primitive* prim); /******************************************************************************* diff --git a/src/ssol_estimator_c.h b/src/ssol_estimator_c.h @@ -18,8 +18,7 @@ #include "ssol_device_c.h" #include "ssol_instance_c.h" - -#include <limits.h> +#include "ssol_shape_c.h" #include <rsys/ref_count.h> #include <rsys/hash_table.h> @@ -36,9 +35,6 @@ struct mc_data { #define MC_DATA_NULL__ { 0, 0 } static const struct mc_data MC_DATA_NULL = MC_DATA_NULL__; -/******************************************************************************* - * One sided Per receiver MC data - ******************************************************************************/ #define MC_RECEIVER_DATA \ struct mc_data integrated_irradiance; /* In W */ \ struct mc_data absorptivity_loss; /* In W */ \ @@ -51,31 +47,99 @@ static const struct mc_data MC_DATA_NULL = MC_DATA_NULL__; MC_DATA_NULL__, \ MC_DATA_NULL__ +/******************************************************************************* + * One sided per shape MC data + ******************************************************************************/ struct mc_primitive_1side { MC_RECEIVER_DATA - unsigned index; }; -#define MC_PRIMITIVE_1SIDE_NULL__ { MC_RECEIVER_DATA_NULL__, UINT_MAX } +#define MC_PRIMITIVE_1SIDE_NULL__ { MC_RECEIVER_DATA_NULL__ } static const struct mc_primitive_1side MC_PRIMITIVE_1SIDE_NULL = MC_PRIMITIVE_1SIDE_NULL__; -/* Declare the hash table that maps a primitive index to its corresponding - * entry into an array of Monte-Carlo estimations */ +/* Map an unsigned to a struct mc_primitive_1side */ #define HTABLE_NAME prim2mc #define HTABLE_KEY unsigned -#define HTABLE_DATA unsigned +#define HTABLE_DATA struct mc_primitive_1side #include <rsys/hash_table.h> -/* Declare the list of per primitive MC estimations */ -#define DARRAY_NAME mc_prim -#define DARRAY_DATA struct mc_primitive_1side -#include <rsys/dynamic_array.h> +struct mc_shape_1side { + struct htable_prim2mc prim2mc; +}; + +static INLINE void +mc_shape_1side_init + (struct mem_allocator* allocator, struct mc_shape_1side* mc) +{ + ASSERT(mc); + htable_prim2mc_init(allocator, &mc->prim2mc); +} + +static INLINE void +mc_shape_1side_release(struct mc_shape_1side* mc) +{ + ASSERT(mc); + htable_prim2mc_release(&mc->prim2mc); +} + +static INLINE res_T +mc_shape_1side_copy + (struct mc_shape_1side* dst, const struct mc_shape_1side* src) +{ + ASSERT(dst && src); + return htable_prim2mc_copy(&dst->prim2mc, &src->prim2mc); +} + +static INLINE res_T +mc_shape_1side_copy_and_release + (struct mc_shape_1side* dst, struct mc_shape_1side* src) +{ + ASSERT(dst && src); + return htable_prim2mc_copy_and_release(&dst->prim2mc, &src->prim2mc); +} + +static INLINE res_T +mc_shape_1side_get_mc_primitive + (struct mc_shape_1side* mc_shape1, + const unsigned iprim, + struct mc_primitive_1side** out_mc_prim1) +{ + struct mc_primitive_1side* mc_prim1 = NULL; + res_T res = RES_OK; + ASSERT(mc_shape1 && out_mc_prim1); + + mc_prim1 = htable_prim2mc_find(&mc_shape1->prim2mc, &iprim); + if(!mc_prim1) { + res = htable_prim2mc_set(&mc_shape1->prim2mc, &iprim, &MC_PRIMITIVE_1SIDE_NULL); + if(res != RES_OK) goto error; + + mc_prim1 = htable_prim2mc_find(&mc_shape1->prim2mc, &iprim); + } + +exit: + *out_mc_prim1 = mc_prim1; + return res; +error: + goto exit; +} + +/******************************************************************************* + * One sided per receiver MC data + ******************************************************************************/ +/* Map a ssol shape to a struct mc_shape_1side */ +#define HTABLE_NAME shape2mc +#define HTABLE_KEY const struct ssol_shape* +#define HTABLE_DATA struct mc_shape_1side +#define HTABLE_DATA_FUNCTOR_INIT mc_shape_1side_init +#define HTABLE_DATA_FUNCTOR_RELEASE mc_shape_1side_release +#define HTABLE_DATA_FUNCTOR_COPY mc_shape_1side_copy +#define HTABLE_DATA_FUNCTOR_COPY_AND_RELEASE mc_shape_1side_copy_and_release +#include <rsys/hash_table.h> struct mc_receiver_1side { MC_RECEIVER_DATA - struct htable_prim2mc prim2mc; - struct darray_mc_prim mc_prims; + struct htable_shape2mc shape2mc; }; static INLINE void @@ -87,82 +151,64 @@ mc_receiver_1side_init mc->absorptivity_loss = MC_DATA_NULL; mc->reflectivity_loss = MC_DATA_NULL; mc->cos_loss = MC_DATA_NULL; - htable_prim2mc_init(allocator, &mc->prim2mc); - darray_mc_prim_init(allocator, &mc->mc_prims); + htable_shape2mc_init(allocator, &mc->shape2mc); } static INLINE void mc_receiver_1side_release(struct mc_receiver_1side* mc) { ASSERT(mc); - htable_prim2mc_release(&mc->prim2mc); - darray_mc_prim_release(&mc->mc_prims); + htable_shape2mc_release(&mc->shape2mc); } static INLINE res_T mc_receiver_1side_copy (struct mc_receiver_1side* dst, const struct mc_receiver_1side* src) { - res_T res = RES_OK; ASSERT(dst && src); dst->integrated_irradiance = src->integrated_irradiance; dst->absorptivity_loss = src->absorptivity_loss; dst->reflectivity_loss = src->reflectivity_loss; dst->cos_loss = src->cos_loss; - res = htable_prim2mc_copy(&dst->prim2mc, &src->prim2mc); - if(res != RES_OK) return res; - res = darray_mc_prim_copy(&dst->mc_prims, &src->mc_prims); - if(res != RES_OK) return res; - return RES_OK; + return htable_shape2mc_copy(&dst->shape2mc, &src->shape2mc); } static INLINE res_T mc_receiver_1side_copy_and_release (struct mc_receiver_1side* dst, struct mc_receiver_1side* src) { - res_T res = RES_OK; ASSERT(dst && src); dst->integrated_irradiance = src->integrated_irradiance; dst->absorptivity_loss = src->absorptivity_loss; dst->reflectivity_loss = src->reflectivity_loss; dst->cos_loss = src->cos_loss; - res = htable_prim2mc_copy(&dst->prim2mc, &src->prim2mc); - if(res != RES_OK) return res; - res = darray_mc_prim_copy(&dst->mc_prims, &src->mc_prims); - if(res != RES_OK) return res; - return RES_OK; + return htable_shape2mc_copy_and_release(&dst->shape2mc, &src->shape2mc); } static INLINE res_T -mc_receiver_1side_get_mc_primitive +mc_receiver_1side_get_mc_shape (struct mc_receiver_1side* mc_rcv, - const unsigned iprim, - struct mc_primitive_1side** out_mc_prim1) + const struct ssol_shape* shape, + struct mc_shape_1side** out_mc_shape1) { - unsigned* pui = NULL; - struct mc_primitive_1side* mc_prim1 = NULL; + struct mc_shape_1side* mc_shape1 = NULL; + struct mc_shape_1side mc_shape1_null; res_T res = RES_OK; - ASSERT(mc_rcv); + ASSERT(mc_rcv && shape && out_mc_prim1); - pui = htable_prim2mc_find(&mc_rcv->prim2mc, &iprim); - if(pui) { - mc_prim1 = darray_mc_prim_data_get(&mc_rcv->mc_prims) + *pui; - ASSERT(*pui < darray_mc_prim_size_get(&mc_rcv->mc_prims)); - ASSERT(mc_prim1->index == *pui); - } else { - unsigned ui = (unsigned)darray_mc_prim_size_get(&mc_rcv->mc_prims); + mc_shape_1side_init(shape->dev->allocator, &mc_shape1_null); - res = darray_mc_prim_push_back(&mc_rcv->mc_prims, &MC_PRIMITIVE_1SIDE_NULL); + mc_shape1 = htable_shape2mc_find(&mc_rcv->shape2mc, &shape); + if(!mc_shape1) { + res = htable_shape2mc_set(&mc_rcv->shape2mc, &shape, &mc_shape1_null); if(res != RES_OK) goto error; - mc_prim1 = darray_mc_prim_data_get(&mc_rcv->mc_prims) + ui; - mc_prim1->index = ui; - res = htable_prim2mc_set(&mc_rcv->prim2mc, &iprim, &ui); - if(res != RES_OK) goto error; + mc_shape1 = htable_shape2mc_find(&mc_rcv->shape2mc, &shape); } exit: - *out_mc_prim1 = mc_prim1; + mc_shape_1side_release(&mc_shape1_null); + *out_mc_shape1 = mc_shape1; return res; error: goto exit; diff --git a/src/ssol_mc_receiver.c b/src/ssol_mc_receiver.c @@ -26,8 +26,8 @@ ssol_estimator_get_mc_receiver const enum ssol_side_flag side, struct ssol_mc_receiver* rcv) { - const struct mc_receiver* mc_rcv = NULL; - const struct mc_receiver_1side* mc_rcv1 = NULL; + struct mc_receiver* mc_rcv = NULL; + struct mc_receiver_1side* mc_rcv1 = NULL; if(!estimator || !instance || !rcv || !(instance->receiver_mask & (int)side)) @@ -60,45 +60,57 @@ ssol_estimator_get_mc_receiver } res_T -ssol_mc_receiver_get_mc_primitives_count - (const struct ssol_mc_receiver* rcv, size_t* count) +ssol_mc_receiver_get_mc_shape + (struct ssol_mc_receiver* rcv, + const struct ssol_shape* shape, + struct ssol_mc_shape* mc) { - const struct mc_receiver_1side* mc_rcv1; - if(!rcv || !count) return RES_BAD_ARG; + struct mc_receiver_1side* mc_rcv1; + + if(!rcv || !shape || !mc) return RES_BAD_ARG; mc_rcv1 = rcv->mc__; - *count = darray_mc_prim_size_get(&mc_rcv1->mc_prims); + mc->N__ = rcv->N__; + mc->mc__ = htable_shape2mc_find(&mc_rcv1->shape2mc, &shape); return RES_OK; } res_T -ssol_mc_receiver_get_mc_primitive - (const struct ssol_mc_receiver* rcv, - const size_t i, +ssol_mc_shape_get_mc_primitive + (struct ssol_mc_shape* shape, + const unsigned i, struct ssol_mc_primitive* prim) { - const struct mc_primitive_1side* mc_prim1; - const struct mc_receiver_1side* mc_rcv1; - - if(!rcv || !prim) return RES_BAD_ARG; + struct mc_shape_1side* mc_shape1; + struct mc_primitive_1side* mc_prim1; - mc_rcv1 = rcv->mc__; - if(i >= darray_mc_prim_size_get(&mc_rcv1->mc_prims)) - return RES_BAD_ARG; + if(!shape || !prim) return RES_BAD_ARG; - mc_prim1 = darray_mc_prim_cdata_get(&mc_rcv1->mc_prims) + i; - #define SETUP_MC_RESULT(Name) { \ - const double N = (double)rcv->N__; \ - const struct mc_data* data = &mc_prim1->Name; \ - prim->Name.E = data->weight / N; \ - prim->Name.V = data->sqr_weight/N - prim->Name.E*prim->Name.E; \ - prim->Name.SE = prim->Name.V > 0 ? sqrt(prim->Name.V / N) : 0; \ - } (void)0 - SETUP_MC_RESULT(integrated_irradiance); - SETUP_MC_RESULT(absorptivity_loss); - SETUP_MC_RESULT(reflectivity_loss); - SETUP_MC_RESULT(cos_loss); - #undef SETUP_MC_RESULT - prim->index = i; + mc_shape1 = shape->mc__; + if(!mc_shape1 || !(mc_prim1 = htable_prim2mc_find(&mc_shape1->prim2mc, &i))) { + #define SETUP_MC_RESULT(Name) { \ + prim->Name.E = 0; \ + prim->Name.V = 0; \ + prim->Name.SE = 0; \ + } (void)0 + SETUP_MC_RESULT(integrated_irradiance); + SETUP_MC_RESULT(absorptivity_loss); + SETUP_MC_RESULT(reflectivity_loss); + SETUP_MC_RESULT(cos_loss); + #undef SETUP_MC_RESULT + } else { + #define SETUP_MC_RESULT(Name) { \ + const double N = (double)shape->N__; \ + const struct mc_data* data = &mc_prim1->Name; \ + prim->Name.E = data->weight / N; \ + prim->Name.V = data->sqr_weight/N - prim->Name.E*prim->Name.E; \ + prim->Name.SE = prim->Name.V > 0 ? sqrt(prim->Name.V / N) : 0; \ + } (void)0 + SETUP_MC_RESULT(integrated_irradiance); + SETUP_MC_RESULT(absorptivity_loss); + SETUP_MC_RESULT(reflectivity_loss); + SETUP_MC_RESULT(cos_loss); + #undef SETUP_MC_RESULT + } return RES_OK; } diff --git a/src/ssol_solver.c b/src/ssol_solver.c @@ -452,9 +452,7 @@ accum_mc_receivers_1side (struct mc_receiver_1side* dst, struct mc_receiver_1side* src) { - const struct mc_primitive_1side* src_mc_prim; - struct mc_primitive_1side* dst_mc_prim; - size_t i; + struct htable_shape2mc_iterator it_shape, end_shape; res_T res = RES_OK; ASSERT(dst && src); @@ -468,22 +466,48 @@ accum_mc_receivers_1side ACCUM_WEIGHT(cos_loss); #undef ACCUM_WEIGHT - /* Merge the per primitive MC of the integrated irradiance */ - FOR_EACH(i, 0, darray_mc_prim_size_get(&src->mc_prims)) { - src_mc_prim = darray_mc_prim_cdata_get(&src->mc_prims) + i; - res = mc_receiver_1side_get_mc_primitive - (dst, src_mc_prim->index, &dst_mc_prim); + /* Merge the per shape MC */ + htable_shape2mc_begin(&src->shape2mc, &it_shape); + htable_shape2mc_end(&src->shape2mc, &end_shape); + while(!htable_shape2mc_iterator_eq(&it_shape, &end_shape)) { + struct htable_prim2mc_iterator it_prim, end_prim; + const struct ssol_shape* shape = *htable_shape2mc_iterator_key_get(&it_shape); + struct mc_shape_1side* mc_shape1_src; + struct mc_shape_1side* mc_shape1_dst; + + mc_shape1_src = htable_shape2mc_iterator_data_get(&it_shape); + + res = mc_receiver_1side_get_mc_shape(dst, shape, &mc_shape1_dst); if(res != RES_OK) goto error; - #define ACCUM_WEIGHT(Name) { \ - dst_mc_prim->Name.weight += src_mc_prim->Name.weight; \ - dst_mc_prim->Name.sqr_weight += src_mc_prim->Name.sqr_weight; \ - } (void)0 - ACCUM_WEIGHT(integrated_irradiance); - ACCUM_WEIGHT(absorptivity_loss); - ACCUM_WEIGHT(reflectivity_loss); - ACCUM_WEIGHT(cos_loss); - #undef ACCUM_WEIGHT + + /* Merge the per primitive MC */ + htable_prim2mc_begin(&mc_shape1_src->prim2mc, &it_prim); + htable_prim2mc_end(&mc_shape1_src->prim2mc, &end_prim); + while(!htable_prim2mc_iterator_eq(&it_prim, &end_prim)) { + const unsigned iprim = *htable_prim2mc_iterator_key_get(&it_prim); + struct mc_primitive_1side* mc_prim1_src; + struct mc_primitive_1side* mc_prim1_dst; + + mc_prim1_src = htable_prim2mc_iterator_data_get(&it_prim); + + res = mc_shape_1side_get_mc_primitive(mc_shape1_dst, iprim, &mc_prim1_dst); + if(res != RES_OK) goto error; + + #define ACCUM_WEIGHT(Name) { \ + mc_prim1_dst->Name.weight += mc_prim1_src->Name.weight; \ + mc_prim1_dst->Name.sqr_weight += mc_prim1_src->Name.sqr_weight; \ + } (void)0 + ACCUM_WEIGHT(integrated_irradiance); + ACCUM_WEIGHT(absorptivity_loss); + ACCUM_WEIGHT(reflectivity_loss); + ACCUM_WEIGHT(cos_loss); + #undef ACCUM_WEIGHT + + htable_prim2mc_iterator_next(&it_prim); + } + htable_shape2mc_iterator_next(&it_shape); } + exit: return res; error: @@ -587,13 +611,18 @@ update_mc /* Per primitive receiver MC accumulation */ if(pt->inst->receiver_per_primitive) { - struct mc_primitive_1side* mc_prim; - res = mc_receiver_1side_get_mc_primitive - (mc_rcv1, pt->prim.prim_id, &mc_prim); + struct mc_shape_1side* mc_shape1; + struct mc_primitive_1side* mc_prim1; + + res = mc_receiver_1side_get_mc_shape(mc_rcv1, pt->sshape->shape, &mc_shape1); + if(res != RES_OK) goto error; + + res = mc_shape_1side_get_mc_primitive(mc_shape1, pt->prim.prim_id, &mc_prim1); if(res != RES_OK) goto error; + #define ACCUM_WEIGHT(Name, W) { \ - mc_prim->Name.weight += (W); \ - mc_prim->Name.sqr_weight += (W)*(W); \ + mc_prim1->Name.weight += (W); \ + mc_prim1->Name.sqr_weight += (W)*(W); \ } (void)0 ACCUM_WEIGHT(integrated_irradiance, pt->weight); ACCUM_WEIGHT(absorptivity_loss, pt->absorptivity_loss); diff --git a/src/test_ssol_solver1.c b/src/test_ssol_solver1.c @@ -70,6 +70,7 @@ main(int argc, char** argv) struct ssol_estimator* estimator; struct ssol_mc_global mc_global; struct ssol_mc_receiver mc_rcv; + struct ssol_mc_shape mc_shape; struct ssol_mc_primitive mc_prim; double dir[3]; double wavelengths[3] = { 1, 2, 3 }; @@ -85,6 +86,7 @@ main(int argc, char** argv) double m, std; double a_m, a_std; uint32_t r_id; + unsigned ntris; (void) argc, (void) argv; @@ -426,22 +428,29 @@ main(int argc, char** argv) + mc_rcv.cos_loss.E, 4 * DNI, 1e-8), 1); CHECK(eq_eps(mc_rcv.cos_loss.E / (4 * DNI), 1 - COS, 1e-8), 1); - CHECK(ssol_mc_receiver_get_mc_primitives_count(NULL, NULL), RES_BAD_ARG); - CHECK(ssol_mc_receiver_get_mc_primitives_count(&mc_rcv, NULL), RES_BAD_ARG); - CHECK(ssol_mc_receiver_get_mc_primitives_count(NULL, &count), RES_BAD_ARG); - CHECK(ssol_mc_receiver_get_mc_primitives_count(&mc_rcv, &count), RES_OK); - NCHECK(count, 0); - - CHECK(ssol_mc_receiver_get_mc_primitive(NULL, count, NULL), RES_BAD_ARG); - CHECK(ssol_mc_receiver_get_mc_primitive(&mc_rcv, count, NULL), RES_BAD_ARG); - CHECK(ssol_mc_receiver_get_mc_primitive(NULL, 0, NULL), RES_BAD_ARG); - CHECK(ssol_mc_receiver_get_mc_primitive(&mc_rcv, 0, NULL), RES_BAD_ARG); - CHECK(ssol_mc_receiver_get_mc_primitive(NULL, count, &mc_prim), RES_BAD_ARG); - CHECK(ssol_mc_receiver_get_mc_primitive(&mc_rcv, count, &mc_prim), RES_BAD_ARG); - CHECK(ssol_mc_receiver_get_mc_primitive(NULL, 0, &mc_prim), RES_BAD_ARG); + CHECK(ssol_mc_receiver_get_mc_shape(NULL, NULL, NULL), RES_BAD_ARG); + CHECK(ssol_mc_receiver_get_mc_shape(&mc_rcv, NULL, NULL), RES_BAD_ARG); + CHECK(ssol_mc_receiver_get_mc_shape(NULL, square, NULL), RES_BAD_ARG); + CHECK(ssol_mc_receiver_get_mc_shape(&mc_rcv, square, NULL), RES_BAD_ARG); + CHECK(ssol_mc_receiver_get_mc_shape(NULL, NULL, &mc_shape), RES_BAD_ARG); + CHECK(ssol_mc_receiver_get_mc_shape(&mc_rcv, NULL, &mc_shape), RES_BAD_ARG); + CHECK(ssol_mc_receiver_get_mc_shape(NULL, square, &mc_shape), RES_BAD_ARG); + CHECK(ssol_mc_receiver_get_mc_shape(&mc_rcv, square, &mc_shape), RES_OK); + + CHECK(ssol_shape_get_triangles_count(square, &ntris), RES_OK); + NCHECK(ntris, 0); + + CHECK(ssol_mc_shape_get_mc_primitive(NULL, ntris, NULL), RES_BAD_ARG); + CHECK(ssol_mc_shape_get_mc_primitive(&mc_shape, ntris, NULL), RES_BAD_ARG); + CHECK(ssol_mc_shape_get_mc_primitive(NULL, 0, NULL), RES_BAD_ARG); + CHECK(ssol_mc_shape_get_mc_primitive(&mc_shape, 0, NULL), RES_BAD_ARG); + CHECK(ssol_mc_shape_get_mc_primitive(NULL, ntris, &mc_prim), RES_BAD_ARG); + CHECK(ssol_mc_shape_get_mc_primitive(&mc_shape, ntris, &mc_prim), RES_BAD_ARG); + CHECK(ssol_mc_shape_get_mc_primitive(NULL, 0, &mc_prim), RES_BAD_ARG); + dbl = 0; - FOR_EACH(i, 0, count) { - CHECK(ssol_mc_receiver_get_mc_primitive(&mc_rcv, i, &mc_prim), RES_OK); + FOR_EACH(i, 0, ntris) { + CHECK(ssol_mc_shape_get_mc_primitive(&mc_shape, (unsigned)i, &mc_prim), RES_OK); dbl += mc_prim.integrated_irradiance.E; } CHECK(eq_eps(dbl, a_m, 1.e-6), 1);