commit 62d0ba10b65920ecc3a3fa0410a7dea3189a1823
parent 4cfe9d034554a7a198dd4b46c0eb4dfe630394b3
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Mon, 23 Jan 2017 15:12:40 +0100
Merge branch 'receiver'
Diffstat:
15 files changed, 329 insertions(+), 59 deletions(-)
diff --git a/src/ssol.h b/src/ssol.h
@@ -762,6 +762,13 @@ ssol_estimator_get_status
struct ssol_estimator_status* status);
SSOL_API res_T
+ssol_estimator_get_receiver_status
+ (struct ssol_estimator* estimator,
+ const struct ssol_instance* instance,
+ const enum ssol_side_flag side,
+ struct ssol_estimator_status* status);
+
+SSOL_API res_T
ssol_estimator_get_count
(const struct ssol_estimator* estimator,
size_t* count);
diff --git a/src/ssol_estimator.c b/src/ssol_estimator.c
@@ -14,8 +14,11 @@
* 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"
#include <rsys/rsys.h>
#include <rsys/mem_allocator.h>
@@ -34,12 +37,58 @@ estimator_release(ref_T* ref)
CONTAINER_OF(ref, struct ssol_estimator, ref);
ASSERT(ref);
dev = estimator->dev;
+ htable_receiver_release(&estimator->global_receivers);
ASSERT(dev && dev->allocator);
MEM_RM(dev->allocator, estimator);
SSOL(device_ref_put(dev));
}
/*******************************************************************************
+ * 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)) {
+ const struct ssol_instance* inst = *htable_instance_iterator_data_get(&it);
+ htable_instance_iterator_next(&it);
+
+ if (inst->receiver_mask) {
+ res_T res = htable_receiver_set
+ (&estimator->global_receivers, &inst, &MC_DATA2_NULL);
+ 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;
+}
+
+/*******************************************************************************
* Exported ssol_estimator functions
******************************************************************************/
res_T
@@ -61,6 +110,8 @@ ssol_estimator_create
goto error;
}
+ htable_receiver_init(dev->allocator, &estimator->global_receivers);
+
SSOL(device_ref_get(dev));
estimator->dev = dev;
ref_init(&estimator->ref);
@@ -94,6 +145,7 @@ ssol_estimator_ref_put
ref_put(&estimator->ref, estimator_release);
return RES_OK;
}
+
res_T
ssol_estimator_get_status
(const struct ssol_estimator* estimator,
@@ -118,9 +170,33 @@ ssol_estimator_get_status
}
res_T
+ssol_estimator_get_receiver_status
+ (struct ssol_estimator* estimator,
+ const struct ssol_instance* instance,
+ const enum ssol_side_flag side,
+ struct ssol_estimator_status* status)
+{
+ 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 */
+ rcv_data = estimator_get_receiver_data
+ (&estimator->global_receivers, instance, side);
+ if(rcv_data == NULL) return RES_BAD_ARG;
+
+ status->N = estimator->realisation_count;
+ status->Nf = estimator->failed_count;
+ 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;
+}
+
+res_T
ssol_estimator_get_count
-(const struct ssol_estimator* estimator,
- size_t* count)
+ (const struct ssol_estimator* estimator, size_t* count)
{
if (!estimator || !count) return RES_BAD_ARG;
*count = estimator->realisation_count;
@@ -129,8 +205,7 @@ ssol_estimator_get_count
res_T
ssol_estimator_get_failed_count
-(const struct ssol_estimator* estimator,
- size_t* count)
+ (const struct ssol_estimator* estimator, size_t* count)
{
if (!estimator || !count) return RES_BAD_ARG;
*count = estimator->failed_count;
@@ -138,16 +213,23 @@ ssol_estimator_get_failed_count
}
res_T
-ssol_estimator_clear
-(struct ssol_estimator* estimator)
+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);
+ estimator->shadow = MC_DATA_NULL;
+ estimator->missing = MC_DATA_NULL;
+
+ 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);
+ htable_receiver_iterator_next(&it);
+ *estimator_data = MC_DATA2_NULL;
+ }
return RES_OK;
}
-
diff --git a/src/ssol_estimator_c.h b/src/ssol_estimator_c.h
@@ -17,6 +17,16 @@
#define SSOL_ESTIMATOR_C_H
#include <rsys/ref_count.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 {
@@ -24,21 +34,65 @@ struct mc_data {
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__;
+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__;
+
+static INLINE void
+init_mc_data2
+ (struct mem_allocator* alloc,
+ struct mc_data_2* data)
+{
+ (void)alloc;
+ ASSERT(data);
+ *data = MC_DATA2_NULL;
+}
+
+/* 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;
size_t failed_count;
/* the implicit MC computations */
struct mc_data shadow;
struct mc_data missing;
- /* 2 global MC per receiver: one for P, one for cos effect losses */
+ /* 1 global MC per 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);
+
+static FINLINE struct mc_data*
+estimator_get_receiver_data
+ (struct htable_receiver* receivers,
+ const struct ssol_instance* instance,
+ const enum ssol_side_flag side)
+{
+ struct mc_data_2* data2;
+ ASSERT(receivers && instance);
+ if(!(instance->receiver_mask & (int)side)) return NULL;
+ data2 = htable_receiver_find(receivers, &instance);
+ if(!data2) return NULL;
+ return side == SSOL_FRONT ? &data2->front : &data2->back;
+}
+
#endif /* SSOL_ESTIMATOR_C_H */
diff --git a/src/ssol_instance_c.h b/src/ssol_instance_c.h
@@ -26,7 +26,7 @@ struct ssol_instance {
struct s3d_shape* shape_samp; /* Instantiated Star-3D shape to sample */
double transform[12]; /* Column major 4x3 affine transformation */
int receiver_mask; /* Combination of ssol_face_flag */
- int sample; /* Define whether or not the instance is sampled or not */
+ int sample; /* Define whether or not the instance should be sampled */
struct fid id; /* Unique identifier */
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 has_receiver = 0;
res_T res = RES_OK;
ASSERT(scn && out_view_rt && out_view_samp);
@@ -297,16 +295,8 @@ scene_create_s3d_views
unsigned id;
htable_instance_iterator_next(&it);
- if(inst->receiver_mask) {
- has_receiver = 1;
- }
-
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;
@@ -321,16 +311,6 @@ 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(!has_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);
diff --git a/src/ssol_scene_c.h b/src/ssol_scene_c.h
@@ -36,7 +36,7 @@ struct ssol_scene;
struct ssol_sun;
struct ssol_scene {
- /* Map the instantiated RT/Samp S3D shape id to its SSOL intrance */
+ /* Map the instantiated RT/Samp S3D shape id to its SSOL instance */
struct htable_instance instances_rt;
struct htable_instance instances_samp;
diff --git a/src/ssol_solver.c b/src/ssol_solver.c
@@ -312,6 +312,7 @@ ssol_solve
FILE* output,
struct ssol_estimator* estimator)
{
+ struct htable_receiver_iterator it, end;
struct s3d_scene_view* view_rt = NULL;
struct s3d_scene_view* view_samp = NULL;
struct ranst_sun_dir* ran_sun_dir = NULL;
@@ -321,6 +322,7 @@ ssol_solve
struct ssp_rng_proxy* rng_proxy = NULL;
struct mc_data* mc_shadows = NULL;
struct mc_data* mc_missings = NULL;
+ struct htable_receiver* mc_rcvs = NULL;
float sampled_area = 0;
int nthreads = 0;
int nrealisations = 0;
@@ -335,12 +337,13 @@ ssol_solve
/* CL compiler supports OpenMP parallel loop whose indices are signed. The
* following line ensures that the unsigned number of realisations does not
- * overflow the realisation index */
+ * overflow the realisation index. */
if(realisations_count > INT_MAX) {
res = RES_BAD_ARG;
goto error;
}
nrealisations = (int)realisations_count;
+ nthreads = (int) scn->dev->nthreads;
res = check_scene(scn, FUNC_NAME);
if(res != RES_OK) goto error;
@@ -352,6 +355,10 @@ ssol_solve
if(res != RES_OK) goto error;
S3D(scene_view_compute_area(view_samp, &sampled_area));
+ /* 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 */
res = ssp_rng_proxy_create_from_rng
(scn->dev->allocator, rng_state, scn->dev->nthreads, &rng_proxy);
@@ -370,15 +377,18 @@ ssol_solve
CREATE(bsdfs);
CREATE(mc_shadows);
CREATE(mc_missings);
+ CREATE(mc_rcvs);
#undef CREATE
/* Setup per thread data structures */
- nthreads = (int)scn->dev->nthreads;
FOR_EACH(i, 0, nthreads) {
res = ssf_bsdf_create(scn->dev->allocator, bsdfs+i);
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_rcvs + i);
+ res = htable_receiver_copy(mc_rcvs + i, &estimator->global_receivers);
+ if(res != RES_OK) goto error;
}
#pragma omp parallel for schedule(static)
@@ -389,6 +399,7 @@ ssol_solve
struct ssf_bsdf* bsdf;
struct mc_data* shadow;
struct mc_data* missing;
+ struct htable_receiver* receiver;
float org[3], dir[3], range[2] = { 0, FLT_MAX };
const int ithread = omp_get_thread_num();
size_t depth = 0;
@@ -402,6 +413,7 @@ ssol_solve
bsdf = bsdfs[ithread];
shadow = mc_shadows + ithread;
missing = mc_missings + ithread;
+ receiver = mc_rcvs + ithread;
/* Find a new starting point of the radiative random walk */
is_lit = point_init(&pt, scn, sampled_area, view_samp, view_rt,
@@ -425,10 +437,15 @@ ssol_solve
if(point_is_receiver(&pt)) {
const res_T res_local = point_dump(&pt, (size_t)i, depth, output);
+ struct mc_data* mc_rcv = NULL;
if(res_local != RES_OK) {
ATOMIC_SET(&res, res_local);
break;
}
+ mc_rcv = estimator_get_receiver_data(receiver, pt.inst, pt.side);
+ ASSERT(mc_rcv);
+ mc_rcv->weight += pt.weight;
+ mc_rcv->sqr_weight += pt.weight*pt.weight;
hit_a_receiver = 1;
}
@@ -490,6 +507,23 @@ ssol_solve
estimator->missing.weight += mc_missings[i].weight;
estimator->missing.sqr_weight += mc_missings[i].sqr_weight;
}
+
+ /* Merge per thread estimations */
+ 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) {
+ /* Sum both sides, even if no receiver is defined to avoid tests */
+ struct mc_data_2* thread_data = htable_receiver_find(mc_rcvs + i, &key);
+ 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;
exit:
@@ -506,6 +540,10 @@ exit:
FOR_EACH(i, 0, nthreads) if(rngs[i]) SSP(rng_ref_put(rngs[i]));
sa_release(rngs);
}
+ if(mc_rcvs) {
+ FOR_EACH(i, 0, nthreads) htable_receiver_release(mc_rcvs + i);
+ sa_release(mc_rcvs);
+ }
sa_release(mc_shadows);
sa_release(mc_missings);
return (res_T)res;
diff --git a/src/test_ssol_estimator.c b/src/test_ssol_estimator.c
@@ -38,6 +38,10 @@ main(int argc, char** argv)
struct ssol_device* dev;
struct ssp_rng* rng;
struct ssol_estimator* estimator;
+ struct ssol_instance* inst;
+ struct ssol_material* v_mtl;
+ struct ssol_shape* shape;
+ struct ssol_object* object;
struct ssol_estimator_status status;
size_t count;
@@ -71,6 +75,22 @@ main(int argc, char** argv)
CHECK(GET_STATUS(estimator, SSOL_STATUS_MISSING, &status), RES_OK);
#undef GET_STATUS
+ #define GET_RCV_STATUS ssol_estimator_get_receiver_status
+ CHECK(ssol_material_create_virtual(dev, &v_mtl), RES_OK);
+ CHECK(ssol_object_create(dev, &object), RES_OK);
+ CHECK(ssol_shape_create_punched_surface(dev, &shape), RES_OK);
+ CHECK(ssol_object_add_shaded_shape(object, shape, v_mtl, v_mtl), RES_OK);
+ CHECK(ssol_object_instantiate(object, &inst), RES_OK);
+ CHECK(ssol_instance_set_receiver(inst, SSOL_FRONT), RES_OK);
+ CHECK(GET_RCV_STATUS(NULL, inst, SSOL_BACK, &status), RES_BAD_ARG);
+ CHECK(GET_RCV_STATUS(estimator, NULL, SSOL_BACK, &status), RES_BAD_ARG);
+ CHECK(GET_RCV_STATUS(estimator, inst, 0, &status), RES_BAD_ARG);
+ CHECK(GET_RCV_STATUS(estimator, inst, SSOL_BACK, NULL), RES_BAD_ARG);
+ /* we cannot get a status before solve has been succesfully called */
+ CHECK(GET_RCV_STATUS(estimator, inst, SSOL_BACK, &status), RES_BAD_ARG);
+ CHECK(GET_RCV_STATUS(estimator, inst, SSOL_FRONT, &status), RES_BAD_ARG);
+ #undef GET_RCV_STATUS
+
CHECK(ssol_estimator_get_count(NULL, &count), RES_BAD_ARG);
CHECK(ssol_estimator_get_count(estimator, NULL), RES_BAD_ARG);
CHECK(ssol_estimator_get_count(estimator, &count), RES_OK);
@@ -79,6 +99,10 @@ main(int argc, char** argv)
CHECK(ssol_estimator_get_failed_count(estimator, NULL), RES_BAD_ARG);
CHECK(ssol_estimator_get_failed_count(estimator, &count), RES_OK);
+ CHECK(ssol_material_ref_put(v_mtl), RES_OK);
+ CHECK(ssol_object_ref_put(object), RES_OK);
+ CHECK(ssol_shape_ref_put(shape), RES_OK);
+ CHECK(ssol_instance_ref_put(inst), RES_OK);
CHECK(ssol_estimator_ref_put(estimator), RES_OK);
CHECK(ssol_device_ref_put(dev), RES_OK);
diff --git a/src/test_ssol_solver1.c b/src/test_ssol_solver1.c
@@ -222,6 +222,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);
@@ -239,16 +241,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);
@@ -264,12 +270,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 */
desc.wavelengths = wavelengths;
@@ -294,12 +304,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;
@@ -320,12 +334,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 */
desc.wavelengths = &mono;
@@ -354,12 +372,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
@@ -186,6 +186,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);
@@ -197,12 +201,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);
- 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, 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_FRONT, &status), RES_OK);
+ logger_print(&logger, LOG_OUTPUT, "P(heliostat2) = %g +/- %g", status.E, status.SE);
+ 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_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
@@ -191,6 +191,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);
@@ -203,13 +205,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
@@ -145,6 +145,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);
@@ -157,13 +159,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
@@ -212,6 +212,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);
@@ -221,13 +223,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
@@ -152,6 +152,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);
@@ -166,13 +168,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
@@ -145,6 +145,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);
@@ -155,13 +157,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);