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:
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);