solstice-solver

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

commit 4fbdeeef584c135ac392029ece4f3a18bba06364
parent 0ee3b390d45d05c990c2d53406df787cd9a1f933
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Fri, 17 Feb 2017 12:15:41 +0100

Make consistent the MC estimations implementation

Rename the 'primary MC' in 'sampled MC'

Diffstat:
Msrc/ssol.h | 2+-
Msrc/ssol_estimator.c | 83++++++++++++++++++++++++++++++++++++++++++++-----------------------------------
Msrc/ssol_estimator_c.h | 221+++++++++++++++++++++++++++++++++++++++++++++----------------------------------
Msrc/ssol_mc_receiver.c | 15+++++++++++----
Msrc/ssol_solver.c | 172++++++++++++++++++++++++++++++++++++++++++-------------------------------------
Msrc/test_ssol_by_receiver_integration.c | 12++++++------
6 files changed, 281 insertions(+), 224 deletions(-)

diff --git a/src/ssol.h b/src/ssol.h @@ -792,7 +792,7 @@ ssol_estimator_get_mc_global struct ssol_mc_global* mc_global); SSOL_API res_T -ssol_estimator_get_primary_entity_x_receiver_status +ssol_estimator_get_mc_sampled_x_receiver (struct ssol_estimator* estimator, const struct ssol_instance* prim_instance, const struct ssol_instance* recv_instance, diff --git a/src/ssol_estimator.c b/src/ssol_estimator.c @@ -36,7 +36,7 @@ create_mc_receivers { struct htable_instance_iterator it, end; struct mc_receiver mc_rcv_null; - struct mc_per_primary_data mc_samp_null; + struct mc_sampled mc_samp_null; res_T res = RES_OK; ASSERT(scene && estimator); @@ -44,7 +44,7 @@ create_mc_receivers htable_instance_end(&scene->instances_rt, &end); mc_receiver_init(estimator->dev->allocator, &mc_rcv_null); - init_mc_per_prim_data(estimator->dev->allocator, &mc_samp_null); + mc_sampled_init(estimator->dev->allocator, &mc_samp_null); while(!htable_instance_iterator_eq(&it, &end)) { const struct ssol_instance* inst = *htable_instance_iterator_data_get(&it); @@ -55,17 +55,17 @@ create_mc_receivers if(res != RES_OK) goto error; } if(inst->sample) { - res = htable_primary_set(&estimator->global_primaries, &inst, &mc_samp_null); + res = htable_sampled_set(&estimator->mc_sampled, &inst, &mc_samp_null); if(res != RES_OK) goto error; } } exit: mc_receiver_release(&mc_rcv_null); - release_mc_per_prim_data(&mc_samp_null); + mc_sampled_release(&mc_samp_null); return res; error: htable_receiver_clear(&estimator->mc_receivers); - htable_primary_clear(&estimator->global_primaries); + htable_sampled_clear(&estimator->mc_sampled); goto exit; } @@ -78,7 +78,7 @@ estimator_release(ref_T* ref) ASSERT(ref); dev = estimator->dev; htable_receiver_release(&estimator->mc_receivers); - htable_primary_release(&estimator->global_primaries); + htable_sampled_release(&estimator->mc_sampled); ASSERT(dev && dev->allocator); MEM_RM(dev->allocator, estimator); SSOL(device_ref_put(dev)); @@ -88,10 +88,9 @@ estimator_release(ref_T* ref) * Exported function ******************************************************************************/ res_T -ssol_estimator_ref_get - (struct ssol_estimator* estimator) +ssol_estimator_ref_get(struct ssol_estimator* estimator) { - if (!estimator) return RES_BAD_ARG; + if(!estimator) return RES_BAD_ARG; ref_get(&estimator->ref); return RES_OK; } @@ -125,44 +124,54 @@ ssol_estimator_get_mc_global } res_T -ssol_estimator_get_primary_entity_x_receiver_status +ssol_estimator_get_mc_sampled_x_receiver (struct ssol_estimator* estimator, - const struct ssol_instance* prim_instance, + const struct ssol_instance* samp_instance, const struct ssol_instance* recv_instance, const enum ssol_side_flag side, struct ssol_mc_receiver* rcv) { - struct mc_per_primary_data* prim_data = NULL; + struct mc_sampled* mc_samp = NULL; + struct mc_receiver* mc_rcv = NULL; struct mc_receiver_1side* mc_rcv1 = NULL; - if(!estimator || !prim_instance || !recv_instance || !rcv + + if(!estimator || !samp_instance || !recv_instance || !rcv || (side != SSOL_BACK && side != SSOL_FRONT) - || !prim_instance->sample + || !samp_instance->sample || !(recv_instance->receiver_mask & (int)side)) return RES_BAD_ARG; - /* Check if prim_instance is a primary entity */ - prim_data = estimator_get_primary_entity_data - (&estimator->global_primaries, prim_instance); - if(prim_data == NULL) return RES_BAD_ARG; - - /* realisation count for this primary */ - mc_rcv1 = estimator_get_prim_recv_data(prim_data, recv_instance, side); - if(!prim_data->nb_samples || !mc_rcv1) { - memset(rcv, 0, sizeof(rcv[0])); - } else { - #define SETUP_MC_RESULT(Name) { \ - const double N = (double)prim_data->nb_samples; \ - const struct mc_data* data = &mc_rcv1->Name; \ - rcv->Name.E = data->weight / N; \ - rcv->Name.V = data->sqr_weight / N - rcv->Name.E*rcv->Name.E; \ - rcv->Name.SE = rcv->Name.V > 0 ? sqrt(rcv->Name.V / N) : 0; \ - } (void)0 - SETUP_MC_RESULT(integrated_irradiance); - SETUP_MC_RESULT(absorptivity_loss); - SETUP_MC_RESULT(reflectivity_loss); - SETUP_MC_RESULT(cos_loss); - #undef SETUP_MC_RESULT + memset(rcv, 0, sizeof(rcv[0])); + + + mc_samp = htable_sampled_find(&estimator->mc_sampled, &samp_instance); + if(!mc_samp || !mc_samp->nb_samples) { + /* The sampled instance has no MC estimation */ + return RES_BAD_ARG; + } + + mc_rcv = htable_receiver_find(&mc_samp->mc_rcvs, &recv_instance); + if(!mc_rcv) { + /* No radiative path starting from the sampled instance reaches the receiver + * instance. */ + return RES_OK; } + + mc_rcv1 = side == SSOL_FRONT ? &mc_rcv->front : &mc_rcv->back; + #define SETUP_MC_RESULT(Name) { \ + const double N = (double)mc_samp->nb_samples; \ + const struct mc_data* data = &mc_rcv1->Name; \ + rcv->Name.E = data->weight / N; \ + rcv->Name.V = data->sqr_weight / N - rcv->Name.E*rcv->Name.E; \ + rcv->Name.SE = rcv->Name.V > 0 ? sqrt(rcv->Name.V / N) : 0; \ + } (void)0 + SETUP_MC_RESULT(integrated_irradiance); + SETUP_MC_RESULT(absorptivity_loss); + SETUP_MC_RESULT(reflectivity_loss); + SETUP_MC_RESULT(cos_loss); + #undef SETUP_MC_RESULT + rcv->mc__ = mc_rcv1; + rcv->N__ = mc_samp->nb_samples; return RES_OK; } @@ -208,7 +217,7 @@ estimator_create } htable_receiver_init(dev->allocator, &estimator->mc_receivers); - htable_primary_init(dev->allocator, &estimator->global_primaries); + htable_sampled_init(dev->allocator, &estimator->mc_sampled); SSOL(device_ref_get(dev)); estimator->dev = dev; ref_init(&estimator->ref); diff --git a/src/ssol_estimator_c.h b/src/ssol_estimator_c.h @@ -133,39 +133,38 @@ mc_receiver_1side_copy_and_release return RES_OK; } -static INLINE struct mc_primitive_1side* +static INLINE res_T mc_receiver_1side_get_mc_primitive - (struct mc_receiver_1side* mc_rcv, const unsigned iprim) + (struct mc_receiver_1side* mc_rcv, + const unsigned iprim, + struct mc_primitive_1side** out_mc_prim1) { unsigned* pui = NULL; - struct mc_primitive_1side* mc_prim = NULL; + struct mc_primitive_1side* mc_prim1 = NULL; + res_T res = RES_OK; ASSERT(mc_rcv); pui = htable_prim2mc_find(&mc_rcv->prim2mc, &iprim); if(pui) { - mc_prim = darray_mc_prim_data_get(&mc_rcv->mc_prims) + *pui; + mc_prim1 = darray_mc_prim_data_get(&mc_rcv->mc_prims) + *pui; ASSERT(*pui < darray_mc_prim_size_get(&mc_rcv->mc_prims)); - ASSERT(mc_prim->index == *pui); + ASSERT(mc_prim1->index == *pui); } else { unsigned ui = (unsigned)darray_mc_prim_size_get(&mc_rcv->mc_prims); - res_T res; res = darray_mc_prim_push_back(&mc_rcv->mc_prims, &MC_PRIMITIVE_1SIDE_NULL); if(res != RES_OK) goto error; - mc_prim = darray_mc_prim_data_get(&mc_rcv->mc_prims) + ui; - mc_prim->index = ui; + mc_prim1 = darray_mc_prim_data_get(&mc_rcv->mc_prims) + ui; + mc_prim1->index = ui; res = htable_prim2mc_set(&mc_rcv->prim2mc, &iprim, &ui); if(res != RES_OK) goto error; } exit: - return mc_prim; + *out_mc_prim1 = mc_prim1; + return res; error: - if(pui && mc_prim) { - darray_mc_prim_pop_back(&mc_rcv->mc_prims); - } - mc_prim = NULL; goto exit; } @@ -229,108 +228,93 @@ mc_receiver_copy_and_release #include <rsys/hash_table.h> /******************************************************************************* - * Per primitive MC data + * Per sampled instance MC data ******************************************************************************/ -struct mc_per_primary_data { - /* global data for this entity */ +struct mc_sampled { + /* Global data for this entity */ struct mc_data cos_loss; - struct mc_data shadow_loss; + struct mc_data shadowed; double area; double sun_cos; size_t nb_samples; - size_t nb_failed; - /* by-receptor data for this entity */ - struct htable_receiver by_receiver; + + /* By-receptor data for this entity */ + struct htable_receiver mc_rcvs; }; static INLINE void -init_mc_per_prim_data - (struct mem_allocator* alloc, - struct mc_per_primary_data* data) +mc_sampled_init + (struct mem_allocator* allocator, + struct mc_sampled* samp) { - ASSERT(alloc && data); - data->area = 0; - data->sun_cos = 0; - data->cos_loss = MC_DATA_NULL; - data->shadow_loss = MC_DATA_NULL; - data->nb_samples = 0; - data->nb_failed = 0; - htable_receiver_init(alloc, &data->by_receiver); + ASSERT(samp); + samp->cos_loss = MC_DATA_NULL; + samp->shadowed = MC_DATA_NULL; + samp->area = 0; + samp->sun_cos = 0; + samp->nb_samples = 0; + htable_receiver_init(allocator, &samp->mc_rcvs); } static INLINE void -release_mc_per_prim_data(struct mc_per_primary_data* data) +mc_sampled_release(struct mc_sampled* samp) { - ASSERT(data); - htable_receiver_release(&data->by_receiver); + ASSERT(samp); + htable_receiver_release(&samp->mc_rcvs); } -#define PRIM_COPY(Dst, Src) {\ - Dst->area = Src->area;\ - Dst->sun_cos = Src->sun_cos;\ - Dst->nb_failed = Src->nb_failed;\ - Dst->nb_samples = Src->nb_samples;\ - Dst->shadow_loss = Src->shadow_loss;\ - Dst->cos_loss = Src->cos_loss;\ -} (void)0 - static INLINE res_T -copy_mc_per_prim_data - (struct mc_per_primary_data* dst, - const struct mc_per_primary_data* src) +mc_sampled_copy(struct mc_sampled* dst, const struct mc_sampled* src) { ASSERT(dst && src); - PRIM_COPY(dst, src); - return htable_receiver_copy(&dst->by_receiver, &src->by_receiver); + dst->cos_loss = src->cos_loss; + dst->shadowed = src->shadowed; + dst->area = src->area; + dst->sun_cos = src->sun_cos; + dst->nb_samples = src->nb_samples; + return htable_receiver_copy(&dst->mc_rcvs, &src->mc_rcvs); } static INLINE res_T -copy_and_release_mc_per_prim_data - (struct mc_per_primary_data* dst, - struct mc_per_primary_data* src) +mc_sampled_copy_and_release(struct mc_sampled* dst, struct mc_sampled* src) { ASSERT(dst && src); - PRIM_COPY(dst, src); - return htable_receiver_copy_and_release(&dst->by_receiver, &src->by_receiver); + dst->cos_loss = src->cos_loss; + dst->shadowed = src->shadowed; + dst->area = src->area; + dst->sun_cos = src->sun_cos; + dst->nb_samples = src->nb_samples; + return htable_receiver_copy_and_release(&dst->mc_rcvs, &src->mc_rcvs); } static INLINE res_T -copy_and_clear_mc_per_prim_data - (struct mc_per_primary_data* dst, - struct mc_per_primary_data* src) -{ - ASSERT(dst && src); - PRIM_COPY(dst, src); - return htable_receiver_copy_and_clear(&dst->by_receiver, &src->by_receiver); -} - - -static INLINE struct mc_receiver_1side* -mc_per_primary_get_mc_receiver - (struct mc_per_primary_data* primary, - const struct ssol_instance* instance, - const enum ssol_side_flag side) +mc_sampled_get_mc_receiver_1side + (struct mc_sampled* mc_samp, + const struct ssol_instance* inst, + const enum ssol_side_flag side, + struct mc_receiver_1side** out_mc_rcv1) { struct mc_receiver* mc_rcv = NULL; struct mc_receiver_1side* mc_rcv1 = NULL; struct mc_receiver mc_rcv_null; res_T res = RES_OK; - ASSERT(primary && instance); - ASSERT(instance->receiver_mask & (int)side); - - mc_receiver_init(instance->dev->allocator, &mc_rcv_null); + ASSERT(mc_samp && inst); + ASSERT(inst->receiver_mask & (int)side); - mc_rcv = htable_receiver_find(&primary->by_receiver, &instance); + mc_receiver_init(inst->dev->allocator, &mc_rcv_null); + + mc_rcv = htable_receiver_find(&mc_samp->mc_rcvs, &inst); if(!mc_rcv) { - res = htable_receiver_set(&primary->by_receiver, &instance, &mc_rcv_null); + res = htable_receiver_set(&mc_samp->mc_rcvs, &inst, &mc_rcv_null); if(res != RES_OK) goto error; - mc_rcv = htable_receiver_find(&primary->by_receiver, &instance); + mc_rcv = htable_receiver_find(&mc_samp->mc_rcvs, &inst); } mc_rcv1 = side == SSOL_FRONT ? &mc_rcv->front : &mc_rcv->back; exit: mc_receiver_release(&mc_rcv_null); - return mc_rcv1; + *out_mc_rcv1 = mc_rcv1; + return res; error: mc_rcv1 = NULL; goto exit; @@ -339,14 +323,13 @@ error: #undef PRIM_COPY /* Define the htable_primary data structure */ -#define HTABLE_NAME primary +#define HTABLE_NAME sampled #define HTABLE_KEY const struct ssol_instance* -#define HTABLE_DATA struct mc_per_primary_data -#define HTABLE_DATA_FUNCTOR_INIT init_mc_per_prim_data -#define HTABLE_DATA_FUNCTOR_RELEASE release_mc_per_prim_data -#define HTABLE_DATA_FUNCTOR_COPY copy_mc_per_prim_data -#define HTABLE_DATA_FUNCTOR_COPY_AND_RELEASE copy_and_release_mc_per_prim_data -#define HTABLE_DATA_FUNCTOR_COPY_AND_CLEAR copy_and_clear_mc_per_prim_data +#define HTABLE_DATA struct mc_sampled +#define HTABLE_DATA_FUNCTOR_INIT mc_sampled_init +#define HTABLE_DATA_FUNCTOR_RELEASE mc_sampled_release +#define HTABLE_DATA_FUNCTOR_COPY mc_sampled_copy +#define HTABLE_DATA_FUNCTOR_COPY_AND_RELEASE mc_sampled_copy_and_release #include <rsys/hash_table.h> /******************************************************************************* @@ -362,9 +345,9 @@ struct ssol_estimator { struct mc_data cos_loss; /* TODO compute it */ struct htable_receiver mc_receivers; /* Per receiver MC */ - struct htable_primary global_primaries; /* Per sampled MC */ + struct htable_sampled mc_sampled; /* Per sampled instance MC */ - double primary_area; + double sampled_area; struct ssol_device* dev; ref_T ref; @@ -376,20 +359,67 @@ estimator_create struct ssol_scene* scene, struct ssol_estimator** estimator); -static FINLINE struct mc_receiver_1side* -estimator_get_mc_receiver +static FINLINE res_T +get_mc_receiver_1side (struct htable_receiver* receivers, - const struct ssol_instance* instance, - const enum ssol_side_flag side) + const struct ssol_instance* inst, + const enum ssol_side_flag side, + struct mc_receiver_1side** out_mc_rcv1) +{ + struct mc_receiver* mc_rcv = NULL; + struct mc_receiver_1side* mc_rcv1 = NULL; + struct mc_receiver mc_rcv_null; + res_T res = RES_OK; + ASSERT(receivers && inst && out_mc_rcv1); + ASSERT(inst->receiver_mask & (int)side); + + mc_receiver_init(inst->dev->allocator, &mc_rcv_null); + + mc_rcv = htable_receiver_find(receivers, &inst); + if(!mc_rcv) { + res = htable_receiver_set(receivers, &inst, &mc_rcv_null); + if(res != RES_OK) goto error; + mc_rcv = htable_receiver_find(receivers, &inst); + } + + mc_rcv1 = side == SSOL_FRONT ? &mc_rcv->front : &mc_rcv->back; +exit: + mc_receiver_release(&mc_rcv_null); + *out_mc_rcv1 = mc_rcv1; + return res; +error: + goto exit; +} + +static FINLINE res_T +get_mc_sampled + (struct htable_sampled* sampled, + const struct ssol_instance* inst, + struct mc_sampled** out_mc_samp) { - struct mc_receiver* mc_rcv; - ASSERT(receivers && instance); - if(!(instance->receiver_mask & (int)side)) return NULL; - mc_rcv = htable_receiver_find(receivers, &instance); - if(!mc_rcv) return NULL; - return side == SSOL_FRONT ? &mc_rcv->front : &mc_rcv->back; + struct mc_sampled* mc_samp = NULL; + struct mc_sampled mc_samp_null; + res_T res = RES_OK; + ASSERT(sampled && inst && out_mc_samp); + + mc_sampled_init(inst->dev->allocator, &mc_samp_null); + + mc_samp = htable_sampled_find(sampled, &inst); + if(!mc_samp) { + res = htable_sampled_set(sampled, &inst, &mc_samp_null); + if(res != RES_OK) goto error; + mc_samp = htable_sampled_find(sampled, &inst); + } + +exit: + mc_sampled_release(&mc_samp_null); + *out_mc_samp = mc_samp; + return res; +error: + goto exit; } +#if 0 static FINLINE struct mc_per_primary_data* estimator_get_primary_entity_data (struct htable_primary* primaries, @@ -411,6 +441,7 @@ estimator_get_prim_recv_data ASSERT(primary_data && instance); return estimator_get_mc_receiver(&primary_data->by_receiver, instance, side); } +#endif #endif /* SSOL_ESTIMATOR_C_H */ diff --git a/src/ssol_mc_receiver.c b/src/ssol_mc_receiver.c @@ -26,15 +26,22 @@ ssol_estimator_get_mc_receiver const enum ssol_side_flag side, struct ssol_mc_receiver* rcv) { + const struct mc_receiver* mc_rcv = NULL; const struct mc_receiver_1side* mc_rcv1 = NULL; + if(!estimator || !instance || !rcv - || (side != SSOL_BACK && side != SSOL_FRONT)) + || !(instance->receiver_mask & (int)side)) return RES_BAD_ARG; - /* Check if a receiver is defined for this instance/side */ - mc_rcv1 = estimator_get_mc_receiver(&estimator->mc_receivers, instance, side); - if(mc_rcv1 == NULL) return RES_BAD_ARG; + memset(rcv, 0, sizeof(rcv[0])); + + mc_rcv = htable_receiver_find(&estimator->mc_receivers, &instance); + if(!mc_rcv) { + /* The receiver has no MC estimation */ + return RES_OK; + } + mc_rcv1 = side == SSOL_FRONT ? &mc_rcv->front : &mc_rcv->back; #define SETUP_MC_RESULT(Name) { \ const double N = (double)estimator->realisation_count; \ const struct mc_data* data = &mc_rcv1->Name; \ diff --git a/src/ssol_solver.c b/src/ssol_solver.c @@ -47,7 +47,7 @@ struct point { const struct ssol_instance* inst; const struct shaded_shape* sshape; - struct mc_per_primary_data* primary; + struct mc_sampled* mc_samp; struct s3d_primitive prim; double N[3]; double pos[3]; @@ -79,18 +79,17 @@ static const struct point POINT_NULL = POINT_NULL__; /******************************************************************************* * Helper functions ******************************************************************************/ -/* Return 1 if the returned point is lit by the sun and 0 otherwise */ -static int +static res_T point_init (struct point* pt, struct ssol_scene* scn, - struct htable_primary* prim_data, - struct ssol_estimator* estimator, + struct htable_sampled* sampled, struct s3d_scene_view* view_samp, struct s3d_scene_view* view_rt, struct ranst_sun_dir* ran_sun_dir, struct ranst_sun_wl* ran_sun_wl, - struct ssp_rng* rng) + struct ssp_rng* rng, + int* is_lit) { struct s3d_attrib attr; struct s3d_hit hit; @@ -98,6 +97,9 @@ point_init float dir[3], pos[3], range[2] = { 0, FLT_MAX }; double cos_sun; size_t id; + res_T res = RES_OK; + ASSERT(pt && scn && sampled && view_samp && view_rt); + ASSERT(ran_sun_dir && ran_sun_wl && rng && is_lit); /* Sample a point into the scene view */ S3D(scene_view_sample @@ -132,18 +134,12 @@ point_init pt->sshape = darray_shaded_shape_cdata_get (&pt->inst->object->shaded_shapes) + id; - /* store primary entity related weights */ - pt->primary = estimator_get_primary_entity_data(prim_data, pt->inst); - if (!pt->primary) { - struct mc_per_primary_data data; - init_mc_per_prim_data(estimator->dev->allocator, &data); - htable_primary_set(prim_data, &pt->inst, &data); - pt->primary = estimator_get_primary_entity_data(prim_data, pt->inst); - ASSERT(pt->primary); - } - pt->primary->cos_loss.weight += pt->cos_loss; - pt->primary->cos_loss.sqr_weight += pt->cos_loss * pt->cos_loss; - pt->primary->nb_samples++; + /* Store sampled entity related weights */ + res = get_mc_sampled(sampled, pt->inst, &pt->mc_samp); + if(res != RES_OK) goto error; + pt->mc_samp->cos_loss.weight += pt->cos_loss; + pt->mc_samp->cos_loss.sqr_weight += pt->cos_loss * pt->cos_loss; + pt->mc_samp->nb_samples++; /* For punched surface, retrieve the sampled position and normal onto the * quadric surface */ @@ -172,11 +168,15 @@ point_init f3_minus(dir, f3_set_d3(dir, pt->dir)); f3_set_d3(pos, pt->pos); S3D(scene_view_trace_ray(view_rt, pos, dir, range, &ray_data, &hit)); - if(!S3D_HIT_NONE(&hit)) return 0; + *is_lit = S3D_HIT_NONE(&hit); + if(*is_lit) { + pt->wl = ranst_sun_wl_get(ran_sun_wl, rng); /* Sample a wavelength */ + } - /* Sample a wavelength */ - pt->wl = ranst_sun_wl_get(ran_sun_wl, rng); - return 1; +exit: + return res; +error: + goto exit; } static FINLINE void @@ -368,8 +368,9 @@ accum_mc_receivers_1side /* Merge the per primitive MC of the integrated irradiance */ FOR_EACH(i, 0, darray_mc_prim_size_get(&src->mc_prims)) { src_mc_prim = darray_mc_prim_cdata_get(&src->mc_prims) + i; - dst_mc_prim = mc_receiver_1side_get_mc_primitive(dst, src_mc_prim->index); - if(!dst_mc_prim) goto error; + res = mc_receiver_1side_get_mc_primitive + (dst, src_mc_prim->index, &dst_mc_prim); + if(res != RES_OK) goto error; #define ACCUM_WEIGHT(Name) { \ dst_mc_prim->Name.weight += src_mc_prim->Name.weight; \ dst_mc_prim->Name.sqr_weight += src_mc_prim->Name.sqr_weight; \ @@ -387,9 +388,7 @@ error: } static res_T -accum_mc_per_primary_data - (struct mc_per_primary_data* dst, - struct mc_per_primary_data* src) +accum_mc_sampled(struct mc_sampled* dst, struct mc_sampled* src) { struct htable_receiver_iterator it, end; struct mc_receiver mc_rcv_null; @@ -403,25 +402,24 @@ accum_mc_per_primary_data dst->Name.sqr_weight += src->Name.sqr_weight; \ } (void)0 ACCUM_WEIGHT(cos_loss); - ACCUM_WEIGHT(shadow_loss); + ACCUM_WEIGHT(shadowed); #undef ACCUM_WEIGHT dst->nb_samples += src->nb_samples; - dst->nb_failed += src->nb_failed; /* dst->by_receiver += src->by_receiver; */ - htable_receiver_begin(&src->by_receiver, &it); - htable_receiver_end(&src->by_receiver, &end); + htable_receiver_begin(&src->mc_rcvs, &it); + htable_receiver_end(&src->mc_rcvs, &end); while(!htable_receiver_iterator_eq(&it, &end)) { struct mc_receiver* src_mc_rcv = htable_receiver_iterator_data_get(&it); const struct ssol_instance* inst = *htable_receiver_iterator_key_get(&it); - struct mc_receiver* dst_mc_rcv = htable_receiver_find(&dst->by_receiver, &inst); + struct mc_receiver* dst_mc_rcv = htable_receiver_find(&dst->mc_rcvs, &inst); htable_receiver_iterator_next(&it); if(!dst_mc_rcv) { - res = htable_receiver_set(&dst->by_receiver, &inst, &mc_rcv_null); + res = htable_receiver_set(&dst->mc_rcvs, &inst, &mc_rcv_null); if(res != RES_OK) goto error; - dst_mc_rcv = htable_receiver_find(&dst->by_receiver, &inst); + dst_mc_rcv = htable_receiver_find(&dst->mc_rcvs, &inst); } if(inst->receiver_mask & (int)SSOL_FRONT) { @@ -452,7 +450,7 @@ ssol_solve struct ssol_estimator** out_estimator) { struct htable_receiver_iterator r_it, r_end; - struct htable_primary_iterator p_it, p_end; + struct htable_sampled_iterator s_it, s_end; struct s3d_scene_view* view_rt = NULL; struct s3d_scene_view* view_samp = NULL; struct ranst_sun_dir* ran_sun_dir = NULL; @@ -465,7 +463,7 @@ ssol_solve struct mc_data* mc_cos_losses = NULL; /* TODO compute it */ size_t* failed_counts = NULL; /* TODO compute it */ struct htable_receiver* mc_rcvs = NULL; - struct htable_primary* mc_prims = NULL; + struct htable_sampled* mc_sampled = NULL; struct ssol_estimator* estimator = NULL; int nthreads = 0; int64_t nrealisations = 0; @@ -521,7 +519,7 @@ ssol_solve CREATE(mc_missings); CREATE(mc_cos_losses); CREATE(mc_rcvs); - CREATE(mc_prims); + CREATE(mc_sampled); CREATE(failed_counts); #undef CREATE @@ -534,8 +532,8 @@ ssol_solve htable_receiver_init(scn->dev->allocator, mc_rcvs + i); res = htable_receiver_copy(mc_rcvs + i, &estimator->mc_receivers); if(res != RES_OK) goto error; - htable_primary_init(scn->dev->allocator, mc_prims + i); - res = htable_primary_copy(mc_prims + i, &estimator->global_primaries); + htable_sampled_init(scn->dev->allocator, mc_sampled + i); + res = htable_sampled_copy(mc_sampled + i, &estimator->mc_sampled); if(res != RES_OK) goto error; } @@ -550,12 +548,13 @@ ssol_solve struct mc_data* cos_loss; size_t* nfails; struct htable_receiver* receiver; - struct htable_primary* primary; + struct htable_sampled* sampled; float org[3], dir[3], range[2] = { 0, FLT_MAX }; const int ithread = omp_get_thread_num(); size_t depth = 0; int is_lit; int hit_a_receiver = 0; + res_T res_local; if(ATOMIC_GET(&res) != RES_OK) continue; /* An error occurs */ @@ -566,23 +565,27 @@ ssol_solve cos_loss = mc_cos_losses + ithread; missing = mc_missings + ithread; receiver = mc_rcvs + ithread; - primary = mc_prims + ithread; + sampled = mc_sampled + ithread; nfails = failed_counts + ithread; /* Find a new starting point of the radiative random walk */ - is_lit = point_init(&pt, scn, primary, estimator, view_samp, view_rt, - ran_sun_dir, ran_sun_wl, rng); + res_local = point_init(&pt, scn, sampled, view_samp, view_rt, ran_sun_dir, + ran_sun_wl, rng, &is_lit); + if(res_local != RES_OK) { + ATOMIC_SET(&res, res_local); + continue; + } if(!is_lit) { /* The starting point is not lit */ - pt.primary->shadow_loss.weight += pt.weight; - pt.primary->shadow_loss.sqr_weight += pt.weight; + pt.mc_samp->shadowed.weight += pt.weight; + pt.mc_samp->shadowed.sqr_weight += pt.weight; shadow->weight += pt.weight; shadow->sqr_weight += pt.weight * pt.weight; continue; } - /* Setup the ray as if it starts from the current point position in order to handle - * the points that start from a virtual material */ + /* Setup the ray as if it starts from the current point position in order + * to handle the points that start from a virtual material */ f3_set_d3(org, pt.pos); f3_set_d3(dir, pt.dir); hit.distance = 0; @@ -592,15 +595,21 @@ ssol_solve struct ssol_material* mtl; if(point_is_receiver(&pt)) { - const res_T res_local = point_dump(&pt, (size_t)i, depth, output); struct mc_receiver_1side* mc_rcv1 = NULL; + struct mc_receiver_1side* mc_samp_x_rcv1 = NULL; + + res_local = point_dump(&pt, (size_t)i, depth, output); if(res_local != RES_OK) { ATOMIC_SET(&res, res_local); break; } /* Per receiver MC accumulation */ - mc_rcv1 = estimator_get_mc_receiver(receiver, pt.inst, pt.side); + res_local = get_mc_receiver_1side(receiver, pt.inst, pt.side, &mc_rcv1); + if(res_local != RES_OK) { + ATOMIC_SET(&res, res_local); + break; + } #define ACCUM_WEIGHT(Name, W) { \ mc_rcv1->Name.weight += (W); \ mc_rcv1->Name.sqr_weight += (W)*(W); \ @@ -611,12 +620,30 @@ ssol_solve ACCUM_WEIGHT(cos_loss, pt.cos_loss); #undef ACCUM_WEIGHT + /* Per-primary/receiver MC accumulation */ + res_local = mc_sampled_get_mc_receiver_1side + (pt.mc_samp, pt.inst, pt.side, &mc_samp_x_rcv1); + if(res_local != RES_OK) { + ATOMIC_SET(&res, res_local); + break; + } + #define ACCUM_WEIGHT(Name, W) { \ + mc_samp_x_rcv1->Name.weight += (W); \ + mc_samp_x_rcv1->Name.sqr_weight += (W)*(W); \ + } (void)0 + ACCUM_WEIGHT(integrated_irradiance, pt.weight); + ACCUM_WEIGHT(absorptivity_loss, pt.absorptivity_loss); + ACCUM_WEIGHT(reflectivity_loss, pt.reflectivity_loss); + ACCUM_WEIGHT(cos_loss, pt.cos_loss); + #undef ACCUM_WEIGHT + /* Per primitive receiver MC accumulation */ if(pt.inst->receiver_per_primitive) { struct mc_primitive_1side* mc_prim; - mc_prim = mc_receiver_1side_get_mc_primitive(mc_rcv1, pt.prim.prim_id); - if(!mc_prim) { - ATOMIC_SET(&res, RES_MEM_ERR); + res_local = mc_receiver_1side_get_mc_primitive + (mc_rcv1, pt.prim.prim_id, &mc_prim); + if(res_local) { + ATOMIC_SET(&res, res_local); break; } #define ACCUM_WEIGHT(Name, W) { \ @@ -629,23 +656,6 @@ ssol_solve ACCUM_WEIGHT(cos_loss, pt.cos_loss); #undef ACCUM_WEIGHT } - - /* Per-primary/receiver MC accumulation */ - mc_rcv1 = mc_per_primary_get_mc_receiver(pt.primary, pt.inst, pt.side); - #define ACCUM_WEIGHT(Name, W) { \ - mc_rcv1->Name.weight += (W); \ - mc_rcv1->Name.sqr_weight += (W)*(W); \ - } (void)0 - if(!mc_rcv1) { - ATOMIC_SET(&res, RES_MEM_ERR); - break; - } - ACCUM_WEIGHT(integrated_irradiance, pt.weight); - ACCUM_WEIGHT(absorptivity_loss, pt.absorptivity_loss); - ACCUM_WEIGHT(reflectivity_loss, pt.reflectivity_loss); - ACCUM_WEIGHT(cos_loss, pt.cos_loss); - #undef ACCUM_WEIGHT - hit_a_receiver = 1; } @@ -659,7 +669,7 @@ ssol_solve } else { /* Modulate the point weight wrt to its scattering functions and * generate an outgoing direction */ - res_T res_local = point_shade(&pt, bsdf, rng, pt.dir); + res_local = point_shade(&pt, bsdf, rng, pt.dir); if(res_local != RES_OK) { ATOMIC_SET(&res, res_local); break; @@ -739,16 +749,16 @@ ssol_solve } /* Merge per thread sampled instance MC estimations */ - htable_primary_begin(&estimator->global_primaries, &p_it); - htable_primary_end(&estimator->global_primaries, &p_end); - while(!htable_primary_iterator_eq(&p_it, &p_end)) { - struct mc_per_primary_data* pri_data = htable_primary_iterator_data_get(&p_it); - const struct ssol_instance* key = *htable_primary_iterator_key_get(&p_it); - htable_primary_iterator_next(&p_it); + htable_sampled_begin(&estimator->mc_sampled, &s_it); + htable_sampled_end(&estimator->mc_sampled, &s_end); + while(!htable_sampled_iterator_eq(&s_it, &s_end)) { + struct mc_sampled* mc_samp = htable_sampled_iterator_data_get(&s_it); + const struct ssol_instance* inst = *htable_sampled_iterator_key_get(&s_it); + htable_sampled_iterator_next(&s_it); FOR_EACH(i, 0, nthreads) { - struct mc_per_primary_data* th_data = htable_primary_find(mc_prims + i, &key); - res = accum_mc_per_primary_data(pri_data, th_data); + struct mc_sampled* mc_samp_thread = htable_sampled_find(mc_sampled + i, &inst); + res = accum_mc_sampled(mc_samp, mc_samp_thread); if(res != RES_OK) goto error; } } @@ -773,9 +783,9 @@ exit: FOR_EACH(i, 0, nthreads) htable_receiver_release(mc_rcvs + i); sa_release(mc_rcvs); } - if (mc_prims) { - FOR_EACH(i, 0, nthreads) htable_primary_release(mc_prims + i); - sa_release(mc_prims); + if(mc_sampled) { + FOR_EACH(i, 0, nthreads) htable_sampled_release(mc_sampled + i); + sa_release(mc_sampled); } sa_release(mc_shadows); sa_release(mc_missings); diff --git a/src/test_ssol_by_receiver_integration.c b/src/test_ssol_by_receiver_integration.c @@ -132,26 +132,26 @@ main(int argc, char** argv) #define N__ 10000 #define S_DNI_cos (4 * 1000 * cos(PI / 4)) -#define GET_RCV_STATUS ssol_estimator_get_mc_receiver -#define GET_PRIM_X_RCV_STATUS ssol_estimator_get_primary_entity_x_receiver_status +#define GET_MC_RCV ssol_estimator_get_mc_receiver +#define GET_MC_SAMP_X_RCV ssol_estimator_get_mc_sampled_x_receiver CHECK(ssol_solve(scene, rng, N__, NULL, &estimator1), RES_OK); - CHECK(GET_RCV_STATUS(estimator1, target, SSOL_FRONT, &mc_rcv), RES_OK); + CHECK(GET_MC_RCV(estimator1, target, SSOL_FRONT, &mc_rcv), RES_OK); printf("Ir(target) = %g +/- %g\n", mc_rcv.integrated_irradiance.E, mc_rcv.integrated_irradiance.SE); CHECK(ssol_instance_set_receiver(heliostat, SSOL_FRONT, 0), RES_OK); CHECK(eq_eps(mc_rcv.integrated_irradiance.E, S_DNI_cos, S_DNI_cos * 2e-1), 1); CHECK(ssol_solve(scene, rng, 8 * N__, NULL, &estimator2), RES_OK); - CHECK(GET_RCV_STATUS(estimator2, target, SSOL_FRONT, &mc_rcv), RES_OK); + CHECK(GET_MC_RCV(estimator2, target, SSOL_FRONT, &mc_rcv), RES_OK); printf("Ir(target) = %g +/- %g\n", mc_rcv.integrated_irradiance.E, mc_rcv.integrated_irradiance.SE); CHECK(eq_eps(mc_rcv.integrated_irradiance.E, S_DNI_cos, S_DNI_cos * 5e-2), 1); CHECK(ssol_estimator_ref_put(estimator1), RES_OK); CHECK(ssol_solve(scene, rng, 3 * N__, NULL, &estimator1), RES_OK); - CHECK(GET_RCV_STATUS(estimator1, target, SSOL_FRONT, &mc_rcv), RES_OK); + CHECK(GET_MC_RCV(estimator1, target, SSOL_FRONT, &mc_rcv), RES_OK); printf("Ir(target) = %g +/- %g\n", mc_rcv.integrated_irradiance.E, mc_rcv.integrated_irradiance.SE); CHECK(eq_eps(mc_rcv.integrated_irradiance.E, S_DNI_cos, S_DNI_cos * 1e-1), 1); - CHECK(GET_PRIM_X_RCV_STATUS(estimator1, heliostat, target, SSOL_FRONT, &mc_rcv), RES_OK); + CHECK(GET_MC_SAMP_X_RCV(estimator1, heliostat, target, SSOL_FRONT, &mc_rcv), RES_OK); printf("Ir(heliostat=>target) = %g +/- %g", mc_rcv.integrated_irradiance.E, mc_rcv.integrated_irradiance.SE); CHECK(eq_eps(mc_rcv.integrated_irradiance.E, S_DNI_cos, S_DNI_cos * 1e-1), 1);