solstice-solver

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

commit f58429641da44af14ad004d3ee8d020ac083159d
parent e4f68d2113fed14e012d2936ddb8047e41376e86
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Wed, 15 Feb 2017 16:11:32 +0100

Add an accessor to the per receiver primitive MC

Diffstat:
Mcmake/CMakeLists.txt | 1+
Msrc/ssol.h | 40+++++++++++++++++++++++++++++++++-------
Msrc/ssol_estimator.c | 31-------------------------------
Msrc/ssol_estimator_c.h | 114+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------
Asrc/ssol_mc_receiver.c | 96+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/ssol_solver.c | 32+++++++++++++-------------------
6 files changed, 228 insertions(+), 86 deletions(-)

diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt @@ -60,6 +60,7 @@ set(SSOL_FILES_SRC ssol_estimator.c ssol_image.c ssol_material.c + ssol_mc_receiver.c ssol_object.c ssol_instance.c ssol_param_buffer.c diff --git a/src/ssol.h b/src/ssol.h @@ -264,6 +264,18 @@ struct ssol_mc_receiver { struct ssol_mc_result absorptivity_loss; /* In W */ struct ssol_mc_result reflectivity_loss; /* In W */ struct ssol_mc_result cos_loss; /* In W TODO remove this */ + + /* Internal data */ + size_t N__; + const void* mc__; +}; + +struct ssol_mc_primitive { + struct ssol_mc_result integrated_irradiance; /* In W */ + struct ssol_mc_result absorptivity_loss; /* In W */ + struct ssol_mc_result reflectivity_loss; /* In W */ + struct ssol_mc_result cos_loss; /* In W TODO remove this */ + size_t index; /* Index of the primitive */ }; typedef res_T @@ -768,13 +780,6 @@ ssol_estimator_get_mc_global struct ssol_mc_global* mc_global); SSOL_API res_T -ssol_estimator_get_mc_receiver - (struct ssol_estimator* estimator, - const struct ssol_instance* instance, - const enum ssol_side_flag side, - struct ssol_mc_receiver* status); - -SSOL_API res_T ssol_estimator_get_count (const struct ssol_estimator* estimator, size_t* count); @@ -795,6 +800,27 @@ ssol_estimator_get_primary_area double* area); /******************************************************************************* + * Per receiver MC estimations + ******************************************************************************/ +SSOL_API res_T +ssol_estimator_get_mc_receiver + (struct ssol_estimator* estimator, + const struct ssol_instance* instance, + const enum ssol_side_flag side, + 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_API res_T +ssol_mc_receiver_get_mc_primitive + (const struct ssol_mc_receiver* rcv, + const size_t i, + struct ssol_mc_primitive* prim); + +/******************************************************************************* * Miscellaneous functions ******************************************************************************/ SSOL_API res_T diff --git a/src/ssol_estimator.c b/src/ssol_estimator.c @@ -116,37 +116,6 @@ ssol_estimator_get_mc_global } res_T -ssol_estimator_get_mc_receiver - (struct ssol_estimator* estimator, - const struct ssol_instance* instance, - const enum ssol_side_flag side, - struct ssol_mc_receiver* rcv) -{ - const struct mc_receiver_1side* mc_rcv1 = NULL; - if(!estimator || !instance || !rcv - || (side != SSOL_BACK && side != SSOL_FRONT)) - return RES_BAD_ARG; - - /* Check if a receiver is defined for this instance/side */ - mc_rcv1 = estimator_get_mc_receiver(&estimator->mc_receivers, instance, side); - if(mc_rcv1 == NULL) return RES_BAD_ARG; - - #define SETUP_MC_RESULT(Name) { \ - const double N = (double)estimator->realisation_count; \ - const struct mc_data* data = &mc_rcv1->data.Name; \ - rcv->Name.E = data->weight / N; \ - rcv->Name.V = data->sqr_weight/N - rcv->Name.E*rcv->Name.E; \ - rcv->Name.SE = rcv->Name.V > 0 ? sqrt(rcv->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; -} - -res_T ssol_estimator_get_count (const struct ssol_estimator* estimator, size_t* count) { diff --git a/src/ssol_estimator_c.h b/src/ssol_estimator_c.h @@ -16,6 +16,10 @@ #ifndef SSOL_ESTIMATOR_C_H #define SSOL_ESTIMATOR_C_H +#include "ssol_instance_c.h" + +#include <limits.h> + #include <rsys/ref_count.h> #include <rsys/hash_table.h> @@ -34,26 +38,43 @@ static const struct mc_data MC_DATA_NULL = MC_DATA_NULL__; /******************************************************************************* * One sided Per receiver MC data ******************************************************************************/ -struct mc_receiver_data { - struct mc_data integrated_irradiance; /* In W */ - struct mc_data absorptivity_loss; /* In W */ - struct mc_data reflectivity_loss; /* In W */ +#define MC_RECEIVER_DATA \ + struct mc_data integrated_irradiance; /* In W */ \ + struct mc_data absorptivity_loss; /* In W */ \ + struct mc_data reflectivity_loss; /* In W */ \ struct mc_data cos_loss; /* In W */ + +#define MC_RECEIVER_DATA_NULL__ \ + MC_DATA_NULL__, \ + MC_DATA_NULL__, \ + MC_DATA_NULL__, \ + MC_DATA_NULL__ + +struct mc_primitive_1side { + MC_RECEIVER_DATA + unsigned index; }; -#define MC_RECEIVER_DATA_NULL__ \ - { MC_DATA_NULL__, MC_DATA_NULL__, MC_DATA_NULL__, MC_DATA_NULL__ } -static const struct mc_receiver_data MC_RECEIVER_DATA_NULL = - MC_RECEIVER_DATA_NULL__; -/* Declare the Per primitive receiver hash table */ -#define HTABLE_NAME rcvprim +#define MC_PRIMITIVE_1SIDE_NULL__ { MC_RECEIVER_DATA_NULL__, UINT_MAX } +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 */ +#define HTABLE_NAME prim2mc #define HTABLE_KEY unsigned -#define HTABLE_DATA struct mc_receiver_data +#define HTABLE_DATA unsigned #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_receiver_1side { - struct mc_receiver_data data; - struct htable_rcvprim prims; /* Per primitive MC */ + MC_RECEIVER_DATA + struct htable_prim2mc prim2mc; + struct darray_mc_prim mc_prims; }; static INLINE void @@ -61,54 +82,89 @@ mc_receiver_1side_init (struct mem_allocator* allocator, struct mc_receiver_1side* mc) { ASSERT(mc); - mc->data = MC_RECEIVER_DATA_NULL; - htable_rcvprim_init(allocator, &mc->prims); + mc->integrated_irradiance = MC_DATA_NULL; + 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); } static INLINE void mc_receiver_1side_release(struct mc_receiver_1side* mc) { ASSERT(mc); - htable_rcvprim_release(&mc->prims); + htable_prim2mc_release(&mc->prim2mc); + darray_mc_prim_release(&mc->mc_prims); } 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->data = src->data; - return htable_rcvprim_copy(&dst->prims, &src->prims); + 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; } 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->data = src->data; - return htable_rcvprim_copy_and_release(&dst->prims, &src->prims); + 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; } -static INLINE struct mc_receiver_data* +static INLINE struct mc_primitive_1side* mc_receiver_1side_get_mc_primitive (struct mc_receiver_1side* mc_rcv, const unsigned iprim) { - struct mc_receiver_data* pmc = NULL; + unsigned* pui = NULL; + struct mc_primitive_1side* mc_prim = NULL; ASSERT(mc_rcv); - pmc = htable_rcvprim_find(&mc_rcv->prims, &iprim); - if(!pmc) { - const res_T res = htable_rcvprim_set - (&mc_rcv->prims, &iprim, &MC_RECEIVER_DATA_NULL); + pui = htable_prim2mc_find(&mc_rcv->prim2mc, &iprim); + if(pui) { + mc_prim = darray_mc_prim_data_get(&mc_rcv->mc_prims) + *pui; + ASSERT(*pui < darray_mc_prim_size_get(&mc_rcv->mc_prims)); + ASSERT(mc_prim->index == *pui); + } else { + unsigned ui = (unsigned)darray_mc_prim_size_get(&mc_rcv->mc_prims); + res_T res; + + res = darray_mc_prim_push_back(&mc_rcv->mc_prims, &MC_PRIMITIVE_1SIDE_NULL); + if(res != RES_OK) goto error; + mc_prim = darray_mc_prim_data_get(&mc_rcv->mc_prims) + ui; + mc_prim->index = ui; + + res = htable_prim2mc_set(&mc_rcv->prim2mc, &iprim, &ui); if(res != RES_OK) goto error; - pmc = htable_rcvprim_find(&mc_rcv->prims, &iprim); } exit: - return pmc; + return mc_prim; error: - pmc = NULL; + if(pui && mc_prim) { + darray_mc_prim_pop_back(&mc_rcv->mc_prims); + } + mc_prim = NULL; goto exit; } diff --git a/src/ssol_mc_receiver.c b/src/ssol_mc_receiver.c @@ -0,0 +1,96 @@ +/* Copyright (C) CNRS 2016-2017 + * + * 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 "ssol.h" +#include "ssol_estimator_c.h" + +/******************************************************************************* + * Exported functions + ******************************************************************************/ +res_T +ssol_estimator_get_mc_receiver + (struct ssol_estimator* estimator, + const struct ssol_instance* instance, + const enum ssol_side_flag side, + struct ssol_mc_receiver* rcv) +{ + const struct mc_receiver_1side* mc_rcv1 = NULL; + if(!estimator || !instance || !rcv + || (side != SSOL_BACK && side != SSOL_FRONT)) + return RES_BAD_ARG; + + /* Check if a receiver is defined for this instance/side */ + mc_rcv1 = estimator_get_mc_receiver(&estimator->mc_receivers, instance, side); + if(mc_rcv1 == NULL) return RES_BAD_ARG; + + #define SETUP_MC_RESULT(Name) { \ + const double N = (double)estimator->realisation_count; \ + const struct mc_data* data = &mc_rcv1->Name; \ + rcv->Name.E = data->weight / N; \ + rcv->Name.V = data->sqr_weight/N - rcv->Name.E*rcv->Name.E; \ + rcv->Name.SE = rcv->Name.V > 0 ? sqrt(rcv->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 + rcv->mc__ = mc_rcv1; + return RES_OK; +} + +res_T +ssol_mc_receiver_get_mc_primitives_count + (const struct ssol_mc_receiver* rcv, size_t* count) +{ + const struct mc_receiver_1side* mc_rcv1; + if(!rcv || !count) return RES_BAD_ARG; + mc_rcv1 = rcv->mc__; + *count = darray_mc_prim_size_get(&mc_rcv1->mc_prims); + return RES_OK; +} + +res_T +ssol_mc_receiver_get_mc_primitive + (const struct ssol_mc_receiver* rcv, + const size_t 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; + + mc_rcv1 = rcv->mc__; + if(i >= darray_mc_prim_size_get(&mc_rcv1->mc_prims)) + return RES_BAD_ARG; + + mc_prim1 = darray_mc_prim_cdata_get(&mc_rcv1->mc_prims); + #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 - rcv->Name.E*rcv->Name.E; \ + prim->Name.SE = rcv->Name.V > 0 ? sqrt(rcv->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; + return RES_OK; +} + diff --git a/src/ssol_solver.c b/src/ssol_solver.c @@ -333,15 +333,14 @@ accum_mc_receivers_1side (struct mc_receiver_1side* dst, struct mc_receiver_1side* src) { - struct htable_rcvprim_iterator it, end; - const struct mc_receiver_data* mc_src; - struct mc_receiver_data* mc_dst; - unsigned iprim; + const struct mc_primitive_1side* src_mc_prim; + struct mc_primitive_1side* dst_mc_prim; + size_t i; ASSERT(dst && src); #define ACCUM_WEIGHT(Name) { \ - dst->data.Name.weight += src->data.Name.weight; \ - dst->data.Name.sqr_weight += src->data.Name.sqr_weight; \ + dst->Name.weight += src->Name.weight; \ + dst->Name.sqr_weight += src->Name.sqr_weight; \ } (void)0 ACCUM_WEIGHT(integrated_irradiance); ACCUM_WEIGHT(absorptivity_loss); @@ -350,23 +349,18 @@ accum_mc_receivers_1side #undef ACCUM_WEIGHT /* Merge the per primitive MC of the integrated irradiance */ - htable_rcvprim_begin(&src->prims, &it); - htable_rcvprim_end(&src->prims, &end); - while(!htable_rcvprim_iterator_eq(&it, &end)) { - iprim = *htable_rcvprim_iterator_key_get(&it); - mc_src = htable_rcvprim_iterator_data_get(&it); - mc_dst = mc_receiver_1side_get_mc_primitive(dst, iprim); - + FOR_EACH(i, 0, darray_mc_prim_size_get(&src->mc_prims)) { + src_mc_prim = darray_mc_prim_cdata_get(&src->mc_prims) + i; + dst_mc_prim = mc_receiver_1side_get_mc_primitive(dst, src_mc_prim->index); #define ACCUM_WEIGHT(Name) { \ - mc_dst->Name.weight += mc_src->Name.weight; \ - mc_dst->Name.sqr_weight += mc_src->Name.sqr_weight; \ + 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 - htable_rcvprim_iterator_next(&it); } } @@ -522,8 +516,8 @@ ssol_solve } mc_rcv1 = estimator_get_mc_receiver(receiver, pt.inst, pt.side); #define ACCUM_WEIGHT(Name, W) { \ - mc_rcv1->data.Name.weight += (W); \ - mc_rcv1->data.Name.sqr_weight += (W)*(W); \ + mc_rcv1->Name.weight += (W); \ + mc_rcv1->Name.sqr_weight += (W)*(W); \ } (void)0 ACCUM_WEIGHT(integrated_irradiance, pt.weight); ACCUM_WEIGHT(absorptivity_loss, pt.absorptivity_loss); @@ -533,7 +527,7 @@ ssol_solve hit_a_receiver = 1; if(pt.inst->receiver_per_primitive) { - struct mc_receiver_data* mc_prim; + struct mc_primitive_1side* mc_prim; mc_prim = mc_receiver_1side_get_mc_primitive(mc_rcv1, pt.prim.prim_id); if(!mc_prim) { ATOMIC_SET(&res, RES_MEM_ERR);