solstice-solver

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

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:
Msrc/ssol.h | 7+++++++
Msrc/ssol_estimator.c | 100+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------
Msrc/ssol_estimator_c.h | 60+++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
Msrc/ssol_instance_c.h | 2+-
Msrc/ssol_scene.c | 22+---------------------
Msrc/ssol_scene_c.h | 2+-
Msrc/ssol_solver.c | 42++++++++++++++++++++++++++++++++++++++++--
Msrc/test_ssol_estimator.c | 24++++++++++++++++++++++++
Msrc/test_ssol_solver1.c | 44++++++++++++++++++++++++++++++++++----------
Msrc/test_ssol_solver2.c | 21+++++++++++++++++++--
Msrc/test_ssol_solver2b.c | 12++++++++++--
Msrc/test_ssol_solver3.c | 12++++++++++--
Msrc/test_ssol_solver3N.c | 12++++++++++--
Msrc/test_ssol_solver4.c | 16++++++++++++++--
Msrc/test_ssol_solver5.c | 12++++++++++--
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);