solstice-solver

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

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:
Msrc/ssol_estimator.c | 112++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------
Msrc/ssol_estimator_c.h | 60++++++++++++++++++++++++++++++++++++++++++++++++------------
Msrc/ssol_instance.c | 2--
Msrc/ssol_instance_c.h | 10----------
Msrc/ssol_scene.c | 36+-----------------------------------
Msrc/ssol_scene_c.h | 2--
Msrc/ssol_solver.c | 75+++++++++++++++++++++++++++++++++++++--------------------------------------
Msrc/test_ssol_solver1.c | 44++++++++++++++++++++++++++++++++++----------
Msrc/test_ssol_solver2.c | 12++++++------
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++++++++++--
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);