solstice-solver

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

commit 95440d240d759b8b4ab38bb3f9ef82bf37cc288f
parent 643459fb2dc5ebe4ef4f3223ad5fff49b8599828
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date:   Fri, 10 Mar 2017 16:03:49 +0100

Add absorbed irradiance computations.

Diffstat:
Msrc/ssol.h | 2++
Msrc/ssol_estimator.c | 1+
Msrc/ssol_estimator_c.h | 5+++++
Msrc/ssol_mc_receiver.c | 2++
Msrc/ssol_solver.c | 87++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------------
Msrc/test_ssol_solver7.c | 6+++++-
6 files changed, 72 insertions(+), 31 deletions(-)

diff --git a/src/ssol.h b/src/ssol.h @@ -307,6 +307,7 @@ struct ssol_mc_global { struct ssol_mc_receiver { struct ssol_mc_result integrated_irradiance; /* In W */ + struct ssol_mc_result integrated_absorbed_irradiance; /* In W */ struct ssol_mc_result absorptivity_loss; /* In W */ struct ssol_mc_result reflectivity_loss; /* In W */ struct ssol_mc_result cos_loss; /* In W TODO remove this */ @@ -318,6 +319,7 @@ struct ssol_mc_receiver { struct ssol_mc_primitive { struct ssol_mc_result integrated_irradiance; /* In W */ + struct ssol_mc_result integrated_absorbed_irradiance; /* In W */ struct ssol_mc_result absorptivity_loss; /* In W */ struct ssol_mc_result reflectivity_loss; /* In W */ struct ssol_mc_result cos_loss; /* In W TODO remove this */ diff --git a/src/ssol_estimator.c b/src/ssol_estimator.c @@ -166,6 +166,7 @@ ssol_estimator_get_mc_sampled_x_receiver rcv->Name.SE = rcv->Name.V > 0 ? sqrt(rcv->Name.V / N) : 0; \ } (void)0 SETUP_MC_RESULT(integrated_irradiance); + SETUP_MC_RESULT(integrated_absorbed_irradiance); SETUP_MC_RESULT(absorptivity_loss); SETUP_MC_RESULT(reflectivity_loss); SETUP_MC_RESULT(cos_loss); diff --git a/src/ssol_estimator_c.h b/src/ssol_estimator_c.h @@ -41,6 +41,7 @@ static const struct mc_data MC_DATA_NULL = MC_DATA_NULL__; ******************************************************************************/ #define MC_RECEIVER_DATA \ struct mc_data integrated_irradiance; /* In W */ \ + struct mc_data integrated_absorbed_irradiance; /* In W */ \ struct mc_data absorptivity_loss; /* In W */ \ struct mc_data reflectivity_loss; /* In W */ \ struct mc_data cos_loss; /* In W */ @@ -49,6 +50,7 @@ static const struct mc_data MC_DATA_NULL = MC_DATA_NULL__; MC_DATA_NULL__, \ MC_DATA_NULL__, \ MC_DATA_NULL__, \ + MC_DATA_NULL__, \ MC_DATA_NULL__ struct mc_primitive_1side { @@ -84,6 +86,7 @@ mc_receiver_1side_init { ASSERT(mc); mc->integrated_irradiance = MC_DATA_NULL; + mc->integrated_absorbed_irradiance = MC_DATA_NULL; mc->absorptivity_loss = MC_DATA_NULL; mc->reflectivity_loss = MC_DATA_NULL; mc->cos_loss = MC_DATA_NULL; @@ -106,6 +109,7 @@ mc_receiver_1side_copy res_T res = RES_OK; ASSERT(dst && src); dst->integrated_irradiance = src->integrated_irradiance; + dst->integrated_absorbed_irradiance = src->integrated_absorbed_irradiance; dst->absorptivity_loss = src->absorptivity_loss; dst->reflectivity_loss = src->reflectivity_loss; dst->cos_loss = src->cos_loss; @@ -123,6 +127,7 @@ mc_receiver_1side_copy_and_release res_T res = RES_OK; ASSERT(dst && src); dst->integrated_irradiance = src->integrated_irradiance; + dst->integrated_absorbed_irradiance = src->integrated_absorbed_irradiance; dst->absorptivity_loss = src->absorptivity_loss; dst->reflectivity_loss = src->reflectivity_loss; dst->cos_loss = src->cos_loss; diff --git a/src/ssol_mc_receiver.c b/src/ssol_mc_receiver.c @@ -50,6 +50,7 @@ ssol_estimator_get_mc_receiver rcv->Name.SE = rcv->Name.V > 0 ? sqrt(rcv->Name.V / N) : 0; \ } (void)0 SETUP_MC_RESULT(integrated_irradiance); + SETUP_MC_RESULT(integrated_absorbed_irradiance); SETUP_MC_RESULT(absorptivity_loss); SETUP_MC_RESULT(reflectivity_loss); SETUP_MC_RESULT(cos_loss); @@ -94,6 +95,7 @@ ssol_mc_receiver_get_mc_primitive prim->Name.SE = prim->Name.V > 0 ? sqrt(prim->Name.V / N) : 0; \ } (void)0 SETUP_MC_RESULT(integrated_irradiance); + SETUP_MC_RESULT(integrated_absorbed_irradiance); SETUP_MC_RESULT(absorptivity_loss); SETUP_MC_RESULT(reflectivity_loss); SETUP_MC_RESULT(cos_loss); diff --git a/src/ssol_solver.c b/src/ssol_solver.c @@ -155,10 +155,12 @@ struct point { double dir[3]; float uv[2]; double wl; /* Sampled wavelength */ - double weight; /* actual weight */ - double absorptivity_loss; - double reflectivity_loss; - double cos_loss; + /* MC weights, before and after hit */ + double incoming_weight, weight; + double absorbed_irradiance; /* current hit only */ + double absorptivity_loss_before, absorptivity_loss; + double reflectivity_loss_before, reflectivity_loss; + double cos_loss_before, cos_loss; enum ssol_side_flag side; }; @@ -172,7 +174,7 @@ struct point { {0, 0, 0}, /* Direction */ \ {0, 0}, /* UV */ \ 0, /* Wavelength */ \ - 0, 0, 0, 0, /* MC weights */ \ + 0, 0, 0, 0, 0, 0, 0, 0, 0, /* MC weights */ \ SSOL_FRONT /* Side */ \ } static const struct point POINT_NULL = POINT_NULL__; @@ -365,12 +367,27 @@ point_shade r = ssf_bsdf_sample(bsdf, rng, wi, frag.Ns, dir, &pdf); ASSERT(0 <= r && r <= 1); - pt->reflectivity_loss += (1 - r) * pt->weight; - pt->weight *= r; + pt->incoming_weight = pt->weight; + pt->absorptivity_loss_before = pt->absorptivity_loss; + pt->reflectivity_loss_before = pt->reflectivity_loss; + pt->cos_loss_before = pt->cos_loss; + pt->absorbed_irradiance = (1 - r) * pt->weight; + pt->reflectivity_loss += pt->absorbed_irradiance; + pt->weight = pt->incoming_weight - pt->absorbed_irradiance; return RES_OK; } +static FINLINE void +point_hit_virtual(struct point* pt) +{ + pt->absorbed_irradiance = 0; + pt->incoming_weight = pt->weight; + pt->absorptivity_loss_before = pt->absorptivity_loss; + pt->reflectivity_loss_before = pt->reflectivity_loss; + pt->cos_loss_before = pt->cos_loss; +} + static FINLINE int point_is_receiver(const struct point* pt) { @@ -463,6 +480,7 @@ accum_mc_receivers_1side dst->Name.sqr_weight += src->Name.sqr_weight; \ } (void)0 ACCUM_WEIGHT(integrated_irradiance); + ACCUM_WEIGHT(integrated_absorbed_irradiance); ACCUM_WEIGHT(absorptivity_loss); ACCUM_WEIGHT(reflectivity_loss); ACCUM_WEIGHT(cos_loss); @@ -479,6 +497,7 @@ accum_mc_receivers_1side dst_mc_prim->Name.sqr_weight += src_mc_prim->Name.sqr_weight; \ } (void)0 ACCUM_WEIGHT(integrated_irradiance); + ACCUM_WEIGHT(integrated_absorbed_irradiance); ACCUM_WEIGHT(absorptivity_loss); ACCUM_WEIGHT(reflectivity_loss); ACCUM_WEIGHT(cos_loss); @@ -565,10 +584,11 @@ update_mc mc_rcv1->Name.weight += (W); \ mc_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); + ACCUM_WEIGHT(integrated_irradiance, pt->incoming_weight); + ACCUM_WEIGHT(integrated_absorbed_irradiance, pt->absorbed_irradiance); + ACCUM_WEIGHT(absorptivity_loss, pt->absorptivity_loss_before); + ACCUM_WEIGHT(reflectivity_loss, pt->reflectivity_loss_before); + ACCUM_WEIGHT(cos_loss, pt->cos_loss_before); #undef ACCUM_WEIGHT /* Per-sampled/receiver MC accumulation */ @@ -579,10 +599,11 @@ update_mc 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); + ACCUM_WEIGHT(integrated_irradiance, pt->incoming_weight); + ACCUM_WEIGHT(integrated_absorbed_irradiance, pt->absorbed_irradiance); + ACCUM_WEIGHT(absorptivity_loss, pt->absorptivity_loss_before); + ACCUM_WEIGHT(reflectivity_loss, pt->reflectivity_loss_before); + ACCUM_WEIGHT(cos_loss, pt->cos_loss_before); #undef ACCUM_WEIGHT /* Per primitive receiver MC accumulation */ @@ -595,10 +616,11 @@ update_mc mc_prim->Name.weight += (W); \ mc_prim->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); + ACCUM_WEIGHT(integrated_irradiance, pt->incoming_weight); + ACCUM_WEIGHT(integrated_absorbed_irradiance, pt->absorbed_irradiance); + ACCUM_WEIGHT(absorptivity_loss, pt->absorptivity_loss_before); + ACCUM_WEIGHT(reflectivity_loss, pt->reflectivity_loss_before); + ACCUM_WEIGHT(cos_loss, pt->cos_loss_before); #undef ACCUM_WEIGHT } @@ -651,13 +673,28 @@ trace_radiative_path struct ray_data ray_data = RAY_DATA_NULL; struct ssol_material* mtl; + /* Compute interaction with material */ + mtl = point_get_material(&pt); + if(mtl->type == SSOL_MATERIAL_VIRTUAL) { + point_hit_virtual(&pt); + } + else { + /* Modulate the point weight wrt to its scattering functions and + * generate an outgoing direction */ + res = point_shade(&pt, thread_ctx->bsdf, thread_ctx->rng, pt.dir); + if(res != RES_OK) goto error; + } + if(point_is_receiver(&pt)) { hit_a_receiver = 1; res = update_mc(&pt, path_id, depth, &thread_ctx->mc_rcvs, output); if(res != RES_OK) goto error; } - mtl = point_get_material(&pt); + /* Stop the radiative random walk */ + if(pt.weight == 0) break; + + /* Setup new ray parameters */ if(mtl->type == SSOL_MATERIAL_VIRTUAL) { /* Note that for Virtual materials, the ray parameters 'org' & 'dir' * are not updated to ensure that it pursues its traversal without any @@ -665,16 +702,6 @@ trace_radiative_path range[0] = nextafterf(hit.distance, FLT_MAX); range[1] = FLT_MAX; } else { - - /* Modulate the point weight wrt to its scattering functions and - * generate an outgoing direction */ - res = point_shade(&pt, thread_ctx->bsdf, thread_ctx->rng, pt.dir); - if(res != RES_OK) goto error; - - /* Stop the radiative random walk */ - if(pt.weight == 0) break; - - /* Setup new ray parameters */ f2(range, 0, FLT_MAX); f3_set_d3(org, pt.pos); f3_set_d3(dir, pt.dir); diff --git a/src/test_ssol_solver7.c b/src/test_ssol_solver7.c @@ -24,7 +24,7 @@ #define HEIGHT 480 #define PROJ_RATIO (double)WIDTH/(double)HEIGHT -#define REFLECTIVITY 0 +#define REFLECTIVITY 0.1 #include "test_ssol_materials.h" #define TARGET_SZ 2 @@ -211,9 +211,13 @@ main(int argc, char** argv) CHECK(eq_eps(mc_global.missing.E, 0, 1e-4), 1); CHECK(GET_MC_RCV(estimator, target, SSOL_FRONT, &mc_rcv), RES_OK); + printf("Abs(target1) = %g +/- %g\n", + mc_rcv.integrated_absorbed_irradiance.E, mc_rcv.integrated_absorbed_irradiance.SE); printf("Ir(target1) = %g +/- %g\n", mc_rcv.integrated_irradiance.E, mc_rcv.integrated_irradiance.SE); CHECK(eq_eps(mc_rcv.integrated_irradiance.E, TOTAL, TOTAL * 1e-4), 1); + CHECK(eq_eps(mc_rcv.integrated_absorbed_irradiance.E, + (1 - REFLECTIVITY) * TOTAL, (1 - REFLECTIVITY) *TOTAL * 1e-4), 1); CHECK(eq_eps(mc_rcv.integrated_irradiance.SE, 0, 1e-4), 1); /* Free data */