commit 90d0d20e67868275d1b8c3edeb128441ccad2cfc
parent 82db14daa6c11b8734553b6c68be13fcb246c66b
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date: Fri, 20 Jan 2017 12:27:28 +0100
Major rework on global MC result by receiver.
Diffstat:
14 files changed, 282 insertions(+), 135 deletions(-)
diff --git a/src/ssol_estimator.c b/src/ssol_estimator.c
@@ -14,6 +14,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include "ssol.h"
+#include "ssol_c.h"
+#include "ssol_scene_c.h"
#include "ssol_estimator_c.h"
#include "ssol_device_c.h"
#include "ssol_instance_c.h"
@@ -35,12 +37,94 @@ estimator_release(ref_T* ref)
CONTAINER_OF(ref, struct ssol_estimator, ref);
ASSERT(ref);
dev = estimator->dev;
- darray_receiver_release(&estimator->global_receiver);
+ htable_receiver_release(&estimator->global_receivers);
ASSERT(dev && dev->allocator);
MEM_RM(dev->allocator, estimator);
SSOL(device_ref_put(dev));
}
+static res_T
+register_receiver
+ (struct ssol_estimator* estimator,
+ const struct ssol_instance* instance)
+{
+ const struct mc_data_2 d = MC_DATA2_NULL__;
+ if (htable_receiver_find(&estimator->global_receivers, &instance))
+ return RES_OK;
+ return htable_receiver_set(&estimator->global_receivers, &instance, &d);
+}
+
+/*******************************************************************************
+ * Local functions
+ ******************************************************************************/
+res_T
+estimator_create_global_receivers
+ (struct ssol_estimator* estimator,
+ struct ssol_scene* scene)
+{
+ struct htable_instance_iterator it, end;
+ int has_sampled = 0;
+ int has_receiver = 0;
+ ASSERT(scene && estimator);
+
+ htable_instance_begin(&scene->instances_rt, &it);
+ htable_instance_end(&scene->instances_rt, &end);
+
+ while (!htable_instance_iterator_eq(&it, &end)) {
+ struct ssol_instance* inst = *htable_instance_iterator_data_get(&it);
+ htable_instance_iterator_next(&it);
+
+ if (inst->receiver_mask) {
+ res_T res = register_receiver(estimator, inst);
+ if (res != RES_OK) return res;
+ has_receiver = 1;
+ }
+
+ /* FIXME: should not sample virtual (material) instance
+ as material is used to compute output dir */
+ if (inst->sample)
+ has_sampled = 1;
+ }
+
+ if(!has_sampled) {
+ log_error(scene->dev, "No solstice instance to sample.\n");
+ return RES_BAD_ARG;
+ }
+
+ if(!has_receiver) {
+ log_warning(scene->dev, "No receiver is defined.\n");
+ }
+
+ return RES_OK;
+}
+
+#define GET_RCV_DTA(r, i, s) \
+ struct mc_data_2* d___;\
+ if (!(i->receiver_mask & s)) return NULL;\
+ d___ = htable_receiver_find(r, &i);\
+ if (!d___) return NULL;\
+ return s == SSOL_FRONT ? &d___->front : &d___->back
+
+const struct mc_data*
+get_receiver_cdata
+ (const struct htable_receiver* receivers,
+ const struct ssol_instance* instance,
+ const enum ssol_side_flag side)
+{
+ const GET_RCV_DTA((struct htable_receiver*)receivers, instance, side);
+}
+
+struct mc_data*
+get_receiver_data
+ (struct htable_receiver* receivers,
+ const struct ssol_instance* instance,
+ const enum ssol_side_flag side)
+{
+ GET_RCV_DTA(receivers, instance, side);
+}
+
+#undef GET_RCV_DTA
+
/*******************************************************************************
* Exported ssol_estimator functions
******************************************************************************/
@@ -63,7 +147,7 @@ ssol_estimator_create
goto error;
}
- darray_receiver_init(dev->allocator, &estimator->global_receiver);
+ htable_receiver_init(dev->allocator, &estimator->global_receivers);
SSOL(device_ref_get(dev));
estimator->dev = dev;
@@ -129,23 +213,20 @@ ssol_estimator_get_receiver_status
const enum ssol_side_flag side,
struct ssol_estimator_status* status)
{
- const struct mc_data* data;
- uint32_t idx = 0;
+ const struct mc_data* rcv_data = NULL;
if (!estimator || !instance || !status
|| (side != SSOL_BACK && side != SSOL_FRONT))
return RES_BAD_ARG;
/* check if a receiver is defined for this instance/side */
- idx = instance->mc_result_idx[side_idx(side)];
- if (idx == MC_RESULT_IDX_NONE)
+ rcv_data = get_receiver_cdata(&estimator->global_receivers, instance, side);
+ if (rcv_data == NULL)
return RES_BAD_ARG;
- ASSERT(idx < estimator->global_receiver.size);
- data = estimator->global_receiver.data + idx;
status->N = estimator->realisation_count;
status->Nf = estimator->failed_count;
- status->E = data->weight / (double) status->N;
- status->V = data->sqr_weight / (double) status->N - status->E * status->E;
+ status->E = rcv_data->weight / (double) status->N;
+ status->V = rcv_data->sqr_weight / (double) status->N - status->E * status->E;
status->SE = (status->V > 0) ? sqrt(status->V / (double) status->N) : 0;
return RES_OK;
}
@@ -174,12 +255,23 @@ res_T
ssol_estimator_clear
(struct ssol_estimator* estimator)
{
+ struct htable_receiver_iterator it, end;
if (!estimator)
return RES_BAD_ARG;
estimator->realisation_count = 0;
CLEAR_MC_DATA(estimator->shadow);
CLEAR_MC_DATA(estimator->missing);
+
+ htable_receiver_begin(&estimator->global_receivers, &it);
+ htable_receiver_end(&estimator->global_receivers, &end);
+ while (!htable_receiver_iterator_eq(&it, &end)) {
+ struct mc_data_2* estimator_data = htable_receiver_iterator_data_get(&it);
+ ASSERT(estimator_data);
+ htable_receiver_iterator_next(&it);
+ CLEAR_MC_DATA2(*estimator_data);
+ }
+
return RES_OK;
}
diff --git a/src/ssol_estimator_c.h b/src/ssol_estimator_c.h
@@ -17,36 +17,55 @@
#define SSOL_ESTIMATOR_C_H
#include <rsys/ref_count.h>
-#include <rsys/dynamic_array.h>
+#include <rsys/hash_table.h>
struct mem_allocator;
+static FINLINE int
+side_idx(const enum ssol_side_flag side)
+{
+ ASSERT(side == SSOL_FRONT || side == SSOL_BACK);
+ return side == SSOL_FRONT ? 0 : 1;
+}
+
/* Monte carlo data */
struct mc_data {
double weight;
double sqr_weight;
};
-#define CLEAR_MC_DATA(d) ((d).weight=0,(d).sqr_weight=0)
-
#define MC_DATA_NULL__ { 0, 0 }
static const struct mc_data MC_DATA_NULL = MC_DATA_NULL__;
+#define CLEAR_MC_DATA(d) ((d).weight=0,(d).sqr_weight=0)
+
+struct mc_data_2 {
+ struct mc_data front;
+ struct mc_data back;
+};
+
+#define MC_DATA2_NULL__ { MC_DATA_NULL__, MC_DATA_NULL__ }
+static const struct mc_data_2 MC_DATA2_NULL = MC_DATA2_NULL__;
+
+#define CLEAR_MC_DATA2(d) (CLEAR_MC_DATA((d).front),CLEAR_MC_DATA((d).back))
+
static INLINE void
-init_mc_data
+init_mc_data2
(struct mem_allocator* alloc,
- struct mc_data* data)
+ struct mc_data_2* data)
{
(void)alloc;
ASSERT(data);
- CLEAR_MC_DATA(*data);
+ CLEAR_MC_DATA2(*data);
}
-/* Define the darray_receiver data structure */
-#define DARRAY_NAME receiver
-#define DARRAY_DATA struct mc_data
-#define DARRAY_FUNCTOR_INIT init_mc_data
-#include <rsys/dynamic_array.h>
+/* Define the htable_receiver data structure */
+struct ssol_instance;
+#define HTABLE_NAME receiver
+#define HTABLE_KEY const struct ssol_instance*
+#define HTABLE_DATA struct mc_data_2
+#define HTABLE_FUNCTOR_INIT init_mc_data2
+#include <rsys/hash_table.h>
struct ssol_estimator {
size_t realisation_count;
@@ -55,10 +74,27 @@ struct ssol_estimator {
struct mc_data shadow;
struct mc_data missing;
/* 1 global MC per receiver */
- struct darray_receiver global_receiver;
+ struct htable_receiver global_receivers;
struct ssol_device* dev;
ref_T ref;
};
+res_T
+estimator_create_global_receivers
+ (struct ssol_estimator* estimator,
+ struct ssol_scene* scene);
+
+const struct mc_data*
+get_receiver_cdata
+ (const struct htable_receiver* receivers,
+ const struct ssol_instance* instance,
+ const enum ssol_side_flag side);
+
+struct mc_data*
+ get_receiver_data
+ (struct htable_receiver* receivers,
+ const struct ssol_instance* instance,
+ const enum ssol_side_flag side);
+
#endif /* SSOL_ESTIMATOR_C_H */
diff --git a/src/ssol_instance.c b/src/ssol_instance.c
@@ -78,8 +78,6 @@ ssol_object_instantiate
instance->dev = dev;
instance->object = object;
instance->sample = 1;
- instance->mc_result_idx[side_idx(SSOL_FRONT)] = MC_RESULT_IDX_NONE;
- instance->mc_result_idx[side_idx(SSOL_BACK)] = MC_RESULT_IDX_NONE;
d33_set_identity(instance->transform);
d3_splat(instance->transform + 9, 0);
diff --git a/src/ssol_instance_c.h b/src/ssol_instance_c.h
@@ -20,21 +20,11 @@
#include <rsys/list.h>
#include <rsys/ref_count.h>
-#define MC_RESULT_IDX_NONE -1
-
-static FINLINE int
-side_idx(const enum ssol_side_flag side)
-{
- ASSERT(side == SSOL_FRONT || side == SSOL_BACK);
- return side == SSOL_FRONT ? 0 : 1;
-}
-
struct ssol_instance {
struct ssol_object* object; /* Instantiated object */
struct s3d_shape* shape_rt; /* Instantiated Star-3D shape to ray-trace */
struct s3d_shape* shape_samp; /* Instantiated Star-3D shape to sample */
double transform[12]; /* Column major 4x3 affine transformation */
- int mc_result_idx[2]; /* index of the global MC results for possible receptors */
int receiver_mask; /* Combination of ssol_face_flag */
int sample; /* Define whether or not the instance should be sampled */
diff --git a/src/ssol_scene.c b/src/ssol_scene.c
@@ -281,8 +281,6 @@ scene_create_s3d_views
struct htable_instance_iterator it, end;
struct s3d_scene_view* view_rt = NULL;
struct s3d_scene_view* view_samp = NULL;
- int has_sampled = 0;
- int cpt_receiver = 0;
res_T res = RES_OK;
ASSERT(scn && out_view_rt && out_view_samp);
@@ -297,29 +295,8 @@ scene_create_s3d_views
unsigned id;
htable_instance_iterator_next(&it);
- if (inst->receiver_mask & SSOL_FRONT) {
- ASSERT(SSOL_FRONT == 1 || SSOL_FRONT == 2);
- if (cpt_receiver == INT_MAX) {
- res = RES_BAD_ARG;
- goto error;
- }
- inst->mc_result_idx[side_idx(SSOL_FRONT)] = cpt_receiver++;
- }
- if (inst->receiver_mask & SSOL_BACK) {
- ASSERT(SSOL_BACK == 1 || SSOL_BACK == 2);
- if (cpt_receiver == INT_MAX) {
- res = RES_BAD_ARG;
- goto error;
- }
- inst->mc_result_idx[side_idx(SSOL_BACK)] = cpt_receiver++;
- }
-
if(!inst->sample) continue;
-
- /* FIXME: should not sample virtual (material) instance
- as material is used to compute output dir */
- has_sampled = 1;
-
+
/* Attach the instantiated s3d sampling shape to the s3d sampling scene */
res = s3d_scene_attach_shape(scn->scn_samp, inst->shape_samp);
if(res != RES_OK) goto error;
@@ -334,23 +311,12 @@ scene_create_s3d_views
* by the scene on its attachment */
}
- if(!has_sampled) {
- log_error(scn->dev, "No solstice instance to sample.\n");
- res = RES_BAD_ARG;
- goto error;
- }
-
- if(!cpt_receiver) {
- log_warning(scn->dev, "No receiver is defined.\n");
- }
-
res = s3d_scene_view_create(scn->scn_rt, S3D_TRACE, &view_rt);
if(res != RES_OK) goto error;
res = s3d_scene_view_create(scn->scn_samp, S3D_SAMPLE, &view_samp);
if(res != RES_OK) goto error;
exit:
- scn->nb_receivers = cpt_receiver;
*out_view_rt = view_rt;
*out_view_samp = view_samp;
return res;
diff --git a/src/ssol_scene_c.h b/src/ssol_scene_c.h
@@ -46,8 +46,6 @@ struct ssol_scene {
struct ssol_sun* sun; /* Sun of the scene */
struct ssol_atmosphere* atmosphere; /* Atmosphere of the scene */
- int nb_receivers;
-
struct ssol_device* dev;
ref_T ref;
};
diff --git a/src/ssol_solver.c b/src/ssol_solver.c
@@ -301,15 +301,6 @@ check_scene(const struct ssol_scene* scene, const char* caller)
return RES_OK;
}
-static FINLINE int
-get_rcv_idx(const struct point* pt)
-{
- ASSERT(pt);
- if (pt->inst->receiver_mask & pt->side)
- return pt->inst->mc_result_idx[side_idx(pt->side)];
- return MC_RESULT_IDX_NONE;
-}
-
/*******************************************************************************
* Exported functions
******************************************************************************/
@@ -330,12 +321,11 @@ ssol_solve
struct ssp_rng_proxy* rng_proxy = NULL;
struct mc_data* mc_shadows = NULL;
struct mc_data* mc_missings = NULL;
- struct mc_data* mc_global_receivers = NULL;
+ struct htable_receiver* mc_global_receivers = NULL;
float sampled_area = 0;
int nthreads = 0;
int nrealisations = 0;
- int nb_receivers = 0;
- int i = 0, j =0;
+ int i = 0;
ATOMIC res = RES_OK;
ASSERT(nrealisations <= INT_MAX);
@@ -364,9 +354,8 @@ ssol_solve
if(res != RES_OK) goto error;
S3D(scene_view_compute_area(view_samp, &sampled_area));
- /* allocate room for per-receiver global MC data */
- nb_receivers = scn->nb_receivers;
- res = darray_receiver_resize(&estimator->global_receiver, nb_receivers);
+ /* create per-receiver global MC data */
+ res = estimator_create_global_receivers(estimator, scn);
if (res != RES_OK) goto error;
/* Create a RNG proxy from the submitted RNG state */
@@ -375,22 +364,20 @@ ssol_solve
if(res != RES_OK) goto error;
/* Create per thread data structures */
- #define CREATEN(Data,N) { \
+ #define CREATE(Data) { \
ASSERT(!(Data)); \
if(!sa_add((Data), nthreads)) { \
res = RES_BAD_ARG; \
goto error; \
} \
- memset((Data), 0, sizeof((Data)[0])*N*nthreads); \
+ memset((Data), 0, sizeof((Data)[0])*nthreads); \
} (void)0
- #define CREATE(Data) CREATEN(Data,1)
CREATE(rngs);
CREATE(bsdfs);
CREATE(mc_shadows);
CREATE(mc_missings);
- CREATEN(mc_global_receivers, nb_receivers);
+ CREATE(mc_global_receivers);
#undef CREATE
- #undef CREATEN
/* Setup per thread data structures */
FOR_EACH(i, 0, nthreads) {
@@ -398,6 +385,9 @@ ssol_solve
if(res != RES_OK) goto error;
res = ssp_rng_proxy_create_rng(rng_proxy, (size_t)i, rngs + i);
if(res != RES_OK) goto error;
+ htable_receiver_init(scn->dev->allocator, mc_global_receivers + i);
+ res = htable_receiver_copy(mc_global_receivers + i, &estimator->global_receivers);
+ if (res != RES_OK) goto error;
}
#pragma omp parallel for schedule(static)
@@ -408,7 +398,7 @@ ssol_solve
struct ssf_bsdf* bsdf;
struct mc_data* shadow;
struct mc_data* missing;
- struct mc_data* global_receiver;
+ struct htable_receiver* global_receiver;
float org[3], dir[3], range[2] = { 0, FLT_MAX };
const int ithread = omp_get_thread_num();
size_t depth = 0;
@@ -422,7 +412,7 @@ ssol_solve
bsdf = bsdfs[ithread];
shadow = mc_shadows + ithread;
missing = mc_missings + ithread;
- global_receiver = mc_global_receivers + ithread * nb_receivers;
+ global_receiver = mc_global_receivers + ithread;
/* Find a new starting point of the radiative random walk */
is_lit = point_init(&pt, scn, sampled_area, view_samp, view_rt,
@@ -446,19 +436,13 @@ ssol_solve
if(point_is_receiver(&pt)) {
const res_T res_local = point_dump(&pt, (size_t)i, depth, output);
- int rcv_idx = MC_RESULT_IDX_NONE;
struct mc_data* global_recv = NULL;
if(res_local != RES_OK) {
ATOMIC_SET(&res, res_local);
break;
}
- rcv_idx = get_rcv_idx(&pt);
- if (rcv_idx == MC_RESULT_IDX_NONE) {
- ATOMIC_SET(&res, res_local);
- break;
- }
- ASSERT(rcv_idx < nb_receivers);
- global_recv = &global_receiver[rcv_idx];
+ global_recv = get_receiver_data(global_receiver, pt.inst, pt.side);
+ ASSERT(global_recv != NULL);
global_recv->weight += pt.weight;
global_recv->sqr_weight += pt.weight*pt.weight;
hit_a_receiver = 1;
@@ -516,18 +500,30 @@ ssol_solve
}
/* Merge per thread estimations */
- ASSERT(estimator->global_receiver.size <= nb_receivers);
FOR_EACH(i, 0, nthreads) {
estimator->shadow.weight += mc_shadows[i].weight;
estimator->shadow.sqr_weight += mc_shadows[i].sqr_weight;
estimator->missing.weight += mc_missings[i].weight;
estimator->missing.sqr_weight += mc_missings[i].sqr_weight;
- FOR_EACH(j, 0, nb_receivers) {
- const int idx = i * nb_receivers + j;
- estimator->global_receiver.data[j].weight
- += mc_global_receivers[idx].weight;
- estimator->global_receiver.data[j].sqr_weight
- += mc_global_receivers[idx].sqr_weight;
+ }
+ {
+ struct htable_receiver_iterator it, end;
+ htable_receiver_begin(&estimator->global_receivers, &it);
+ htable_receiver_end(&estimator->global_receivers, &end);
+ while (!htable_receiver_iterator_eq(&it, &end)) {
+ struct mc_data_2* estimator_data = htable_receiver_iterator_data_get(&it);
+ const struct ssol_instance* key = *htable_receiver_iterator_key_get(&it);
+ htable_receiver_iterator_next(&it);
+ FOR_EACH(i, 0, nthreads) {
+ const struct mc_data_2* thread_data
+ = htable_receiver_find(mc_global_receivers + i, &key);
+ ASSERT(estimator_data && thread_data);
+ /* sum both sides, even if no receiver defined to avoid tests */
+ estimator_data->front.weight += thread_data->front.weight;
+ estimator_data->front.sqr_weight += thread_data->front.sqr_weight;
+ estimator_data->back.weight += thread_data->back.weight;
+ estimator_data->back.sqr_weight += thread_data->back.sqr_weight;
+ }
}
}
estimator->realisation_count += realisations_count;
@@ -546,9 +542,12 @@ exit:
FOR_EACH(i, 0, nthreads) if(rngs[i]) SSP(rng_ref_put(rngs[i]));
sa_release(rngs);
}
+ if (mc_global_receivers) {
+ FOR_EACH(i, 0, nthreads) htable_receiver_release(mc_global_receivers + i);
+ sa_release(mc_global_receivers);
+ }
sa_release(mc_shadows);
sa_release(mc_missings);
- sa_release(mc_global_receivers);
return (res_T)res;
error:
goto exit;
diff --git a/src/test_ssol_solver1.c b/src/test_ssol_solver1.c
@@ -202,6 +202,8 @@ main(int argc, char** argv)
/* Can sample any geometry; variance is high */
NCHECK(tmp = tmpfile(), 0);
#define N__ 10000
+#define GET_STATUS ssol_estimator_get_status
+#define GET_RCV_STATUS ssol_estimator_get_receiver_status
CHECK(ssol_estimator_clear(estimator), RES_OK);
CHECK(ssol_solve(scene, rng, N__, tmp, estimator), RES_OK);
CHECK(ssol_instance_get_id(target, &r_id), RES_OK);
@@ -219,16 +221,20 @@ main(int argc, char** argv)
dbl = sqrt((SQR(12 * DNI_cos) / 3 - SQR(4 * DNI_cos)) / (double)count);
CHECK(eq_eps(std, dbl, dbl*1e-2), 1);
/* Target was sampled but shadowed by secondary */
- CHECK(ssol_estimator_get_status(estimator, SSOL_STATUS_SHADOW, &status), RES_OK);
+ CHECK(GET_STATUS(estimator, SSOL_STATUS_SHADOW, &status), RES_OK);
logger_print(&logger, LOG_OUTPUT, "Shadows = %g +/- %g", status.E, status.SE);
CHECK(eq_eps(status.E, m, 2 * dbl), 1);
CHECK(status.N, count);
CHECK(status.Nf, fcount);
- CHECK(ssol_estimator_get_status(estimator, SSOL_STATUS_MISSING, &status), RES_OK);
+ CHECK(GET_STATUS(estimator, SSOL_STATUS_MISSING, &status), RES_OK);
logger_print(&logger, LOG_OUTPUT, "Missing = %g +/- %g", status.E, status.SE);
CHECK(eq_eps(status.E, m, 2*status.SE), 1);
CHECK(status.N, count);
CHECK(status.Nf, fcount);
+ CHECK(GET_RCV_STATUS(estimator, target, SSOL_FRONT, &status), RES_OK);
+ logger_print(&logger, LOG_OUTPUT, "P(target) = %g +/- %g", status.E, status.SE);
+ CHECK(eq_eps(status.E, m, 1e-8), 1);
+ CHECK(eq_eps(status.SE, std, 1e-4), 1);
/* Sample primary mirror only; variance is low */
CHECK(ssol_instance_sample(target, 0), RES_OK);
@@ -244,12 +250,16 @@ main(int argc, char** argv)
logger_print(&logger, LOG_OUTPUT, "\nP = %g +/- %g", m, std);
CHECK(eq_eps(m, 4 * DNI_cos, MMAX(4 * DNI_cos * 1e-2, std)), 1);
CHECK(eq_eps(std, 0, 1e-4), 1);
- CHECK(ssol_estimator_get_status(estimator, SSOL_STATUS_SHADOW, &status), RES_OK);
+ CHECK(GET_STATUS(estimator, SSOL_STATUS_SHADOW, &status), RES_OK);
logger_print(&logger, LOG_OUTPUT, "Shadows = %g +/- %g", status.E, status.SE);
CHECK(eq_eps(status.E, 0, 1e-4), 1);
- CHECK(ssol_estimator_get_status(estimator, SSOL_STATUS_MISSING, &status), RES_OK);
+ CHECK(GET_STATUS(estimator, SSOL_STATUS_MISSING, &status), RES_OK);
logger_print(&logger, LOG_OUTPUT, "Missing = %g +/- %g", status.E, status.SE);
CHECK(eq_eps(status.E, 0, 1e-4), 1);
+ CHECK(GET_RCV_STATUS(estimator, target, SSOL_FRONT, &status), RES_OK);
+ logger_print(&logger, LOG_OUTPUT, "P(target) = %g +/- %g", status.E, status.SE);
+ CHECK(eq_eps(status.E, m, 1e-8), 1);
+ CHECK(eq_eps(status.SE, std, 1e-4), 1);
/* Check atmosphere model; with no absorption result is unchanged */
CHECK(ssol_spectrum_create(dev, &abs), RES_OK);
@@ -271,12 +281,16 @@ main(int argc, char** argv)
CHECK(ssol_scene_detach_atmosphere(scene, atm), RES_OK);
CHECK(ssol_spectrum_ref_put(abs), RES_OK);
CHECK(ssol_atmosphere_ref_put(atm), RES_OK);
- CHECK(ssol_estimator_get_status(estimator, SSOL_STATUS_SHADOW, &status), RES_OK);
+ CHECK(GET_STATUS(estimator, SSOL_STATUS_SHADOW, &status), RES_OK);
logger_print(&logger, LOG_OUTPUT, "Shadows = %g +/- %g", status.E, status.SE);
CHECK(eq_eps(status.E, 0, 1e-4), 1);
- CHECK(ssol_estimator_get_status(estimator, SSOL_STATUS_MISSING, &status), RES_OK);
+ CHECK(GET_STATUS(estimator, SSOL_STATUS_MISSING, &status), RES_OK);
logger_print(&logger, LOG_OUTPUT, "Missing = %g +/- %g", status.E, status.SE);
CHECK(eq_eps(status.E, 0, 1e-4), 1);
+ CHECK(GET_RCV_STATUS(estimator, target, SSOL_FRONT, &status), RES_OK);
+ logger_print(&logger, LOG_OUTPUT, "P(target) = %g +/- %g", status.E, status.SE);
+ CHECK(eq_eps(status.E, m, 1e-8), 1);
+ CHECK(eq_eps(status.SE, std, 1e-4), 1);
/* Check atmosphere model; with absorption power decreases */
ka[0] = ka[1] = ka[2] = 0.1;
@@ -297,12 +311,16 @@ main(int argc, char** argv)
#define K (exp(-0.1 * 4 * sqrt(2)))
CHECK(eq_eps(m, 4 * K * DNI_cos, MMAX(4 * K * DNI_cos * 1e-1, std)), 1);
CHECK(eq_eps(std, 0, 1e-4), 1);
- CHECK(ssol_estimator_get_status(estimator, SSOL_STATUS_SHADOW, &status), RES_OK);
+ CHECK(GET_STATUS(estimator, SSOL_STATUS_SHADOW, &status), RES_OK);
logger_print(&logger, LOG_OUTPUT, "Shadows = %g +/- %g", status.E, status.SE);
CHECK(eq_eps(status.E, 0, 1e-4), 1);
- CHECK(ssol_estimator_get_status(estimator, SSOL_STATUS_MISSING, &status), RES_OK);
+ CHECK(GET_STATUS(estimator, SSOL_STATUS_MISSING, &status), RES_OK);
logger_print(&logger, LOG_OUTPUT, "Missing = %g +/- %g", status.E, status.SE);
CHECK(eq_eps(status.E, 0, 1e-4), 1);
+ CHECK(GET_RCV_STATUS(estimator, target, SSOL_FRONT, &status), RES_OK);
+ logger_print(&logger, LOG_OUTPUT, "P(target) = %g +/- %g", status.E, status.SE);
+ CHECK(eq_eps(status.E, m, 1e-8), 1);
+ CHECK(eq_eps(status.SE, std, 1e-4), 1);
/* Check a monochromatic sun */
CHECK(ssol_spectrum_setup(spectrum, &mono, intensities, 1), RES_OK);
@@ -325,12 +343,18 @@ main(int argc, char** argv)
#define K2 (exp(-0.121 * 4 * sqrt(2)))
CHECK(eq_eps(m, 4 * K2 * DNI_cos, MMAX(4 * K2 * DNI_cos * 1e-4, std)), 1);
CHECK(eq_eps(std, 0, 1e-4), 1);
- CHECK(ssol_estimator_get_status(estimator, SSOL_STATUS_SHADOW, &status), RES_OK);
+ CHECK(GET_STATUS(estimator, SSOL_STATUS_SHADOW, &status), RES_OK);
logger_print(&logger, LOG_OUTPUT, "Shadows = %g +/- %g", status.E, status.SE);
CHECK(eq_eps(status.E, 0, 1e-4), 1);
- CHECK(ssol_estimator_get_status(estimator, SSOL_STATUS_MISSING, &status), RES_OK);
+ CHECK(GET_STATUS(estimator, SSOL_STATUS_MISSING, &status), RES_OK);
logger_print(&logger, LOG_OUTPUT, "Missing = %g +/- %g", status.E, status.SE);
CHECK(eq_eps(status.E, 0, 1e-4), 1);
+ CHECK(GET_RCV_STATUS(estimator, target, SSOL_FRONT, &status), RES_OK);
+ logger_print(&logger, LOG_OUTPUT, "P(target) = %g +/- %g", status.E, status.SE);
+ CHECK(eq_eps(status.E, m, 1e-8), 1);
+ CHECK(eq_eps(status.SE, std, 1e-4), 1);
+#undef GET_STATUS
+#undef GET_RCV_STATUS
/* Free data */
CHECK(ssol_instance_ref_put(heliostat), RES_OK);
diff --git a/src/test_ssol_solver2.c b/src/test_ssol_solver2.c
@@ -180,6 +180,10 @@ main(int argc, char** argv)
NCHECK(tmp = tmpfile(), 0);
#define N__ 10000
+#define GET_STATUS ssol_estimator_get_status
+#define GET_RCV_STATUS ssol_estimator_get_receiver_status
+ CHECK(GET_RCV_STATUS(estimator, heliostat2, SSOL_BACK, &status), RES_BAD_ARG);
+ CHECK(GET_RCV_STATUS(estimator, heliostat2, SSOL_FRONT, &status), RES_BAD_ARG);
CHECK(ssol_solve(scene, rng, N__, tmp, estimator), RES_OK);
CHECK(ssol_instance_get_id(target, &r_id), RES_OK);
CHECK(ssol_estimator_get_count(estimator, &count), RES_OK);
@@ -191,29 +195,25 @@ main(int argc, char** argv)
CHECK(eq_eps(m, 4 * DNI_cos, 4 * DNI_cos * 1e-4), 1);
#define SQR(x) ((x)*(x))
CHECK(eq_eps(std, 0, 1e-4), 1);
-#define GET_STATUS ssol_estimator_get_status
CHECK(GET_STATUS(estimator, SSOL_STATUS_SHADOW, &status), RES_OK);
logger_print(&logger, LOG_OUTPUT, "Shadows = %g +/- %g", status.E, status.SE);
CHECK(eq_eps(status.E, 0, 1e-4), 1);
CHECK(GET_STATUS(estimator, SSOL_STATUS_MISSING, &status), RES_OK);
logger_print(&logger, LOG_OUTPUT, "Missing = %g +/- %g", status.E, status.SE);
CHECK(eq_eps(status.E, 0, 1e-4), 1);
-
-#define GET_RCV_STATUS ssol_estimator_get_receiver_status
CHECK(GET_RCV_STATUS(estimator, heliostat1, SSOL_BACK, &status), RES_BAD_ARG);
CHECK(GET_RCV_STATUS(estimator, heliostat1, SSOL_FRONT, &status), RES_OK);
logger_print(&logger, LOG_OUTPUT, "P(heliostat1) = %g +/- %g", status.E, status.SE);
- CHECK(GET_RCV_STATUS(estimator, heliostat2, SSOL_BACK, &status), RES_BAD_ARG);
CHECK(GET_RCV_STATUS(estimator, heliostat2, SSOL_FRONT, &status), RES_OK);
logger_print(&logger, LOG_OUTPUT, "P(heliostat2) = %g +/- %g", status.E, status.SE);
- CHECK(GET_RCV_STATUS(estimator, secondary, SSOL_BACK, &status), RES_BAD_ARG);
CHECK(GET_RCV_STATUS(estimator, secondary, SSOL_FRONT, &status), RES_OK);
logger_print(&logger, LOG_OUTPUT, "P(secondary) = %g +/- %g", status.E, status.SE);
- CHECK(GET_RCV_STATUS(estimator, target, SSOL_BACK, &status), RES_BAD_ARG);
CHECK(GET_RCV_STATUS(estimator, target, SSOL_FRONT, &status), RES_OK);
logger_print(&logger, LOG_OUTPUT, "P(target) = %g +/- %g", status.E, status.SE);
CHECK(eq_eps(status.E, m, 1e-8), 1);
CHECK(eq_eps(status.SE, std, 1e-4), 1);
+#undef GET_STATUS
+#undef GET_RCV_STATUS
/* Free data */
CHECK(ssol_instance_ref_put(heliostat1), RES_OK);
diff --git a/src/test_ssol_solver2b.c b/src/test_ssol_solver2b.c
@@ -185,6 +185,8 @@ main(int argc, char** argv)
NCHECK(tmp = tmpfile(), 0);
#define N__ 50000
+#define GET_STATUS ssol_estimator_get_status
+#define GET_RCV_STATUS ssol_estimator_get_receiver_status
CHECK(ssol_solve(scene, rng, N__, tmp, estimator), RES_OK);
CHECK(ssol_instance_get_id(target, &r_id), RES_OK);
CHECK(ssol_estimator_get_count(estimator, &count), RES_OK);
@@ -197,13 +199,19 @@ main(int argc, char** argv)
#define SQR(x) ((x)*(x))
CHECK(eq_eps(std,
sqrt((SQR(4 * DNI_cos) / 2 - SQR(2 * DNI_cos)) / (double)count), 1e-3), 1);
- CHECK(ssol_estimator_get_status(estimator, SSOL_STATUS_SHADOW, &status), RES_OK);
+ CHECK(GET_STATUS(estimator, SSOL_STATUS_SHADOW, &status), RES_OK);
logger_print(&logger, LOG_OUTPUT, "Shadows = %g +/- %g", status.E, status.SE);
CHECK(eq_eps(status.E, 0, 1e-4), 1);
- CHECK(ssol_estimator_get_status(estimator, SSOL_STATUS_MISSING, &status), RES_OK);
+ CHECK(GET_STATUS(estimator, SSOL_STATUS_MISSING, &status), RES_OK);
logger_print(&logger, LOG_OUTPUT, "Missing = %g +/- %g", status.E, status.SE);
CHECK(eq_eps(status.E, 0, 1e-4), 1);
CHECK(status.Nf, 0);
+ CHECK(GET_RCV_STATUS(estimator, target, SSOL_FRONT, &status), RES_OK);
+ logger_print(&logger, LOG_OUTPUT, "P(target) = %g +/- %g", status.E, status.SE);
+ CHECK(eq_eps(status.E, m, 1e-8), 1);
+ CHECK(eq_eps(status.SE, std, 1e-4), 1);
+#undef GET_STATUS
+#undef GET_RCV_STATUS
/* Free data */
CHECK(ssol_instance_ref_put(heliostat1), RES_OK);
diff --git a/src/test_ssol_solver3.c b/src/test_ssol_solver3.c
@@ -139,6 +139,8 @@ main(int argc, char** argv)
NCHECK(tmp = tmpfile(), 0);
#define N__ 20000
+#define GET_STATUS ssol_estimator_get_status
+#define GET_RCV_STATUS ssol_estimator_get_receiver_status
CHECK(ssol_solve(scene, rng, N__, tmp, estimator), RES_OK);
CHECK(ssol_instance_get_id(target, &r_id), RES_OK);
CHECK(ssol_estimator_get_count(estimator, &count), RES_OK);
@@ -151,13 +153,19 @@ main(int argc, char** argv)
#define SQR(x) ((x)*(x))
CHECK(eq_eps(std,
sqrt((SQR(400*DNI_cos) / 100 - SQR(4*DNI_cos)) / (double)count), 20), 1);
- CHECK(ssol_estimator_get_status(estimator, SSOL_STATUS_SHADOW, &status), RES_OK);
+ CHECK(GET_STATUS(estimator, SSOL_STATUS_SHADOW, &status), RES_OK);
logger_print(&logger, LOG_OUTPUT, "Shadows = %g +/- %g", status.E, status.SE);
CHECK(eq_eps(status.E, 0, 1e-4), 1);
- CHECK(ssol_estimator_get_status(estimator, SSOL_STATUS_MISSING, &status), RES_OK);
+ CHECK(GET_STATUS(estimator, SSOL_STATUS_MISSING, &status), RES_OK);
logger_print(&logger, LOG_OUTPUT, "Missing = %g +/- %g", status.E, status.SE);
CHECK(eq_eps(status.E, 0, 1e-4), 1);
CHECK(status.Nf, 0);
+ CHECK(GET_RCV_STATUS(estimator, target, SSOL_FRONT, &status), RES_OK);
+ logger_print(&logger, LOG_OUTPUT, "P(target) = %g +/- %g", status.E, status.SE);
+ CHECK(eq_eps(status.E, m, 1e-8), 1);
+ CHECK(eq_eps(status.SE, std, 1e-4), 1);
+#undef GET_STATUS
+#undef GET_RCV_STATUS
/* Free data */
CHECK(ssol_instance_ref_put(heliostat), RES_OK);
diff --git a/src/test_ssol_solver3N.c b/src/test_ssol_solver3N.c
@@ -203,6 +203,8 @@ main(int argc, char** argv)
NCHECK(tmp = tmpfile(), 0);
#define N__ 10000
+#define GET_STATUS ssol_estimator_get_status
+#define GET_RCV_STATUS ssol_estimator_get_receiver_status
CHECK(ssol_solve(scene, rng, N__, tmp, estimator), RES_OK);
CHECK(ssol_instance_get_id(target, &r_id), RES_OK);
CHECK(ssol_estimator_get_count(estimator, &count), RES_OK);
@@ -212,13 +214,19 @@ main(int argc, char** argv)
logger_print(&logger, LOG_OUTPUT, "\nP = %g +/- %g\n", m, std);
#define DNI_cos (1000 * cos(PI / 8))
CHECK(eq_eps(m, 4 * NX * NY * NZ * DNI_cos, 4 * NX * NY * NZ * DNI_cos * 2e-1), 1);
- CHECK(ssol_estimator_get_status(estimator, SSOL_STATUS_SHADOW, &status), RES_OK);
+ CHECK(GET_STATUS(estimator, SSOL_STATUS_SHADOW, &status), RES_OK);
logger_print(&logger, LOG_OUTPUT, "Shadows = %g +/- %g", status.E, status.SE);
CHECK(eq_eps(status.E, 0, 1e-4), 1);
- CHECK(ssol_estimator_get_status(estimator, SSOL_STATUS_MISSING, &status), RES_OK);
+ CHECK(GET_STATUS(estimator, SSOL_STATUS_MISSING, &status), RES_OK);
logger_print(&logger, LOG_OUTPUT, "Missing = %g +/- %g", status.E, status.SE);
CHECK(eq_eps(status.E, 0, 1e-4), 1);
CHECK(status.Nf, 0);
+ CHECK(GET_RCV_STATUS(estimator, target, SSOL_FRONT, &status), RES_OK);
+ logger_print(&logger, LOG_OUTPUT, "P(target) = %g +/- %g", status.E, status.SE);
+ CHECK(eq_eps(status.E, m, 1e-6), 1);
+ CHECK(eq_eps(status.SE, std, 1e-3), 1);
+#undef GET_STATUS
+#undef GET_RCV_STATUS
/* Free data */
CHECK(ssol_instance_ref_put(target), RES_OK);
diff --git a/src/test_ssol_solver4.c b/src/test_ssol_solver4.c
@@ -146,6 +146,8 @@ main(int argc, char** argv)
NCHECK(tmp = tmpfile(), 0);
#define N__ 10000
+#define GET_STATUS ssol_estimator_get_status
+#define GET_RCV_STATUS ssol_estimator_get_receiver_status
CHECK(ssol_solve(scene, rng, N__, tmp, estimator), RES_OK);
CHECK(ssol_instance_get_id(target1, &r_id1), RES_OK);
CHECK(ssol_instance_get_id(target2, &r_id2), RES_OK);
@@ -160,13 +162,23 @@ main(int argc, char** argv)
CHECK(eq_eps(std1, 0, 1), 1);
CHECK(m1, m2);
CHECK(std1, std2);
- CHECK(ssol_estimator_get_status(estimator, SSOL_STATUS_SHADOW, &status), RES_OK);
+ CHECK(GET_STATUS(estimator, SSOL_STATUS_SHADOW, &status), RES_OK);
logger_print(&logger, LOG_OUTPUT, "Shadows = %g +/- %g", status.E, status.SE);
CHECK(eq_eps(status.E, 0, 1e-4), 1);
- CHECK(ssol_estimator_get_status(estimator, SSOL_STATUS_MISSING, &status), RES_OK);
+ CHECK(GET_STATUS(estimator, SSOL_STATUS_MISSING, &status), RES_OK);
logger_print(&logger, LOG_OUTPUT, "Missing = %g +/- %g", status.E, status.SE);
CHECK(eq_eps(status.E, 0, 1e-4), 1);
CHECK(status.Nf, 0);
+ CHECK(GET_RCV_STATUS(estimator, target1, SSOL_FRONT, &status), RES_OK);
+ logger_print(&logger, LOG_OUTPUT, "P(target1) = %g +/- %g", status.E, status.SE);
+ CHECK(eq_eps(status.E, m1, 1e-8), 1);
+ CHECK(eq_eps(status.SE, std1, 1e-4), 1);
+ CHECK(GET_RCV_STATUS(estimator, target2, SSOL_FRONT, &status), RES_OK);
+ logger_print(&logger, LOG_OUTPUT, "P(target2) = %g +/- %g", status.E, status.SE);
+ CHECK(eq_eps(status.E, m2, 1e-8), 1);
+ CHECK(eq_eps(status.SE, std2, 1e-4), 1);
+#undef GET_STATUS
+#undef GET_RCV_STATUS
/* Free data */
CHECK(ssol_instance_ref_put(heliostat), RES_OK);
diff --git a/src/test_ssol_solver5.c b/src/test_ssol_solver5.c
@@ -139,6 +139,8 @@ main(int argc, char** argv)
NCHECK(tmp = tmpfile(), 0);
#define N__ 10000
+#define GET_STATUS ssol_estimator_get_status
+#define GET_RCV_STATUS ssol_estimator_get_receiver_status
CHECK(ssol_solve(scene, rng, N__, tmp, estimator), RES_OK);
CHECK(ssol_instance_get_id(target, &r_id), RES_OK);
CHECK(ssol_estimator_get_count(estimator, &count), RES_OK);
@@ -149,13 +151,19 @@ main(int argc, char** argv)
#define DNI_cos (1000 * cos(0))
CHECK(eq_eps(m, 400 * DNI_cos, 20), 1);
CHECK(eq_eps(std, 0, 1), 1);
- CHECK(ssol_estimator_get_status(estimator, SSOL_STATUS_SHADOW, &status), RES_OK);
+ CHECK(GET_STATUS(estimator, SSOL_STATUS_SHADOW, &status), RES_OK);
logger_print(&logger, LOG_OUTPUT, "Shadows = %g +/- %g", status.E, status.SE);
CHECK(eq_eps(status.E, 0, 1e-4), 1);
- CHECK(ssol_estimator_get_status(estimator, SSOL_STATUS_MISSING, &status), RES_OK);
+ CHECK(GET_STATUS(estimator, SSOL_STATUS_MISSING, &status), RES_OK);
logger_print(&logger, LOG_OUTPUT, "Missing = %g +/- %g", status.E, status.SE);
CHECK(eq_eps(status.E, 0, 1e-4), 1);
CHECK(status.Nf, 0);
+ CHECK(GET_RCV_STATUS(estimator, target, SSOL_FRONT, &status), RES_OK);
+ logger_print(&logger, LOG_OUTPUT, "P(target) = %g +/- %g", status.E, status.SE);
+ CHECK(eq_eps(status.E, m, 1e-8), 1);
+ CHECK(eq_eps(status.SE, std, 1e-4), 1);
+#undef GET_STATUS
+#undef GET_RCV_STATUS
/* Free data */
CHECK(ssol_instance_ref_put(heliostat), RES_OK);