star-gs

Literate program for a geometric sensitivity calculation
git clone git://git.meso-star.fr/star-gs.git
Log | Files | Refs | README | LICENSE

commit 52687f24428cca216e2031bbe473e648e0e96c89
parent 66cb2687eda5448174d0af13f3ccd3a20cf4eb3d
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Wed, 15 Sep 2021 11:17:27 +0200

Upd the way the compute_trans_sensib process is written

Diffstat:
Msrc/sgs_compute_trans_sensib.c | 196+++++++++++++++++++++++++++++++++++++++++++++++--------------------------------
1 file changed, 117 insertions(+), 79 deletions(-)

diff --git a/src/sgs_compute_trans_sensib.c b/src/sgs_compute_trans_sensib.c @@ -26,16 +26,18 @@ #include <star/smc.h> #include <star/ssp.h> +/* Sugar syntax */ enum {X, Y, Z}; +enum {WEIGHT, SENSIB, WEIGHTS_COUNT__}; +/* FIXME this should be variables */ static const double RECV_MIN[2] = {0.5, 1.5}; static const double RECV_MAX[2] = {1.5, 2.5}; -static const double EMIT_THRESHOLD = 2; -static const double V[3] = {0, 0, 1}; - -/* FIXME this should be a variable */ -static const double EMIT_SZ[3] = {4, 4, 0}; +static const double EMIT_E_THRESHOLD = 2; static const double EMIT_E_SZ[3] = {0, 4, 2}; +static const double EMIT_S_SZ[3] = {4, 4, 0}; + +static const double V[3] = {0, 0, 1}; #if 0 static const double RECV_MIN[2] = {0.125, 0.375}; @@ -48,36 +50,43 @@ static const double V[3] = {0, 0, 1}; * Helper functions ******************************************************************************/ static res_T -realisation(void* weight, struct ssp_rng* rng, const unsigned ithread, void* ctx) +realisation + (void* weights, + struct ssp_rng* rng, + const unsigned ithread, + void* ctx) { + struct smc_doubleN_context* dblN_ctx = ctx; + struct sgs* sgs = dblN_ctx->integrand_data; struct sgs_hit hit = SGS_HIT_NULL; - struct sgs_fragment frag = SGS_FRAGMENT_NULL; - struct sgs* sgs = ctx; - double dir_emit[3] = {0, 0, 0}; - double dir_spec[3] = {0, 0, 0}; - double pos_emit[3] = {0, 0, 0}; - double pos_recv[3] = {0, 0, 0}; - double pos_emit_e[3] = {0, 0, 0}; - double dir_spec_e[3] = {0, 0, 0}; + double normal_e[3]; + double normal_s[3]; - double range[2] = {0, DBL_MAX}; + double dir_emit_s[3]; + double dir_spec_e[3]; + double dir_spec_s[3]; + double pos_emit_e[3]; + double pos_emit_s[3]; + double pos_recv[3]; - double u_emit[3]; - double u_spec[3]; + double range[2]; + + double u_emit_s[3]; + double u_spec_s[3]; double u_emit_e[3]; double u_spec_e[3]; - double tmp[3]; - double beta_emit; - double beta_spec; - double alpha_emit; - double alpha_spec; - double beta_emit_e; - double beta_spec_e; + double alpha_emit_e; double alpha_spec_e; - + double alpha_emit_s; + double alpha_spec_s; + double beta_emit_e; + double beta_spec_e; + double beta_emit_s; + double beta_spec_s; + double rho; double grad_rho[3]; double I; @@ -86,81 +95,103 @@ realisation(void* weight, struct ssp_rng* rng, const unsigned ithread, void* ctx double S; double w = 0; + double s = 0; - enum sgs_surface_type surf_emit = SGS_SURFACE_NONE; + enum sgs_surface_type surf_emit_e; + enum sgs_surface_type surf_emit_s; res_T res = RES_OK; (void)ithread; + range[0] = 0, range[1] = INF; + /* Sample the sensitivity emissive surface */ sgs_geometry_sample(sgs->geom, rng, &frag); - surf_emit = frag.surface; + pos_emit_s[X] = frag.position[X]; + pos_emit_s[Y] = frag.position[Y]; + pos_emit_s[Z] = frag.position[Z]; + normal_s[X] = frag.normal[X]; + normal_s[Y] = frag.normal[Y]; + normal_s[Z] = frag.normal[Z]; + surf_emit_s = frag.surface; /* Sample the cosine weighted sampling of the emissive direction */ - ssp_ran_hemisphere_cos(rng, frag.normal, dir_emit, NULL); + ssp_ran_hemisphere_cos(rng, frag.normal, dir_emit_s, NULL); - pos_emit[X] = frag.position[X]; - pos_emit[Y] = frag.position[Y]; - pos_emit[Z] = frag.position[Z]; - - range[0] = 0; - range[1] = INF; - - sgs_geometry_trace_ray(sgs->geom, pos_emit, dir_emit, range, surf_emit, &hit); + /* Trace the ray from the sensitivity emissive surface */ + sgs_geometry_trace_ray + (sgs->geom, pos_emit_s, dir_emit_s, range, surf_emit_s, &hit); if(SGS_HIT_NONE(&hit)) { res = RES_OK; goto error; } - pos_recv[X] = pos_emit[X] + hit.distance*dir_emit[X]; - pos_recv[Y] = pos_emit[Y] + hit.distance*dir_emit[Y]; - pos_recv[Z] = pos_emit[Z] + hit.distance*dir_emit[Z]; + pos_recv[X] = pos_emit_s[X] + hit.distance*dir_emit_s[X]; + pos_recv[Y] = pos_emit_s[Y] + hit.distance*dir_emit_s[Y]; + pos_recv[Z] = pos_emit_s[Z] + hit.distance*dir_emit_s[Z]; - /* Does not reach the receiver */ + /* The ray does not reach the receiver, the MC weight is NULL */ if(hit.surface != SGS_SURFACE_Z_NEG - || RECV_MIN[X] > pos_recv[X] || pos_recv[X] > RECV_MAX[X] - || RECV_MIN[Y] > pos_recv[Y] || pos_recv[Y] > RECV_MAX[Y]) { + || pos_recv[X] < RECV_MIN[X] || RECV_MAX[X] < pos_recv[X] + || pos_recv[Y] < RECV_MIN[Y] || RECV_MAX[Y] < pos_recv[Y]) { goto exit; } - reflect(dir_spec, dir_emit, frag.normal); - sgs_geometry_trace_ray(sgs->geom, pos_emit, dir_spec, range, surf_emit, &hit); + /* Find the reflected position */ + reflect(dir_spec_s, dir_emit_s, frag.normal); + sgs_geometry_trace_ray + (sgs->geom, pos_emit_s, dir_spec_s, range, surf_emit_s, &hit); if(SGS_HIT_NONE(&hit)) { res = RES_OK; goto error; } - pos_emit_e[X] = pos_emit[X] + hit.distance*dir_spec[X]; - pos_emit_e[Y] = pos_emit[Y] + hit.distance*dir_spec[Y]; - pos_emit_e[Z] = pos_emit[Z] + hit.distance*dir_spec[Z]; - - if(hit.surface != SGS_SURFACE_X_POS || pos_emit_e[Z] > EMIT_THRESHOLD) { + pos_emit_e[X] = pos_emit_s[X] + hit.distance*dir_spec_s[X]; + pos_emit_e[Y] = pos_emit_s[Y] + hit.distance*dir_spec_s[Y]; + pos_emit_e[Z] = pos_emit_s[Z] + hit.distance*dir_spec_s[Z]; + normal_e[X] = hit.normal[X]; + normal_e[Y] = hit.normal[Y]; + normal_e[Z] = hit.normal[Z]; + surf_emit_e = hit.surface; + + /* The reflected position is not an the emitter, the MC weight is null */ + if(surf_emit_e != SGS_SURFACE_X_POS || pos_emit_e[Z] > EMIT_E_THRESHOLD) { goto exit; } - alpha_emit = d3_dot(V, frag.normal) / d3_dot(dir_emit, frag.normal); - alpha_spec = d3_dot(V, frag.normal) / d3_dot(dir_spec, frag.normal); - d3_sub(u_emit, V, d3_muld(tmp, dir_emit, alpha_emit)); - d3_sub(u_spec, V, d3_muld(tmp, dir_spec, alpha_spec)); - beta_emit = d3_normalize(u_emit, u_emit); - beta_spec = d3_normalize(u_spec, u_spec); - - d3_minus(dir_spec_e, dir_spec); - - alpha_emit_e = d3_dot(u_emit, hit.normal) / d3_dot(dir_spec_e, hit.normal); - alpha_spec_e = d3_dot(u_spec, hit.normal) / d3_dot(dir_spec_e, hit.normal); - d3_sub(u_emit_e, u_emit, d3_muld(tmp, dir_spec_e, alpha_emit_e)); - d3_sub(u_spec_e, u_spec, d3_muld(tmp, dir_spec_e, alpha_spec_e)); + alpha_emit_s = d3_dot(V, normal_s) / d3_dot(dir_emit_s, normal_s); + alpha_spec_s = d3_dot(V, normal_s) / d3_dot(dir_spec_s, normal_s); + u_emit_s[X] = V[X] - alpha_emit_s*dir_emit_s[X]; + u_emit_s[Y] = V[Y] - alpha_emit_s*dir_emit_s[Y]; + u_emit_s[Z] = V[Z] - alpha_emit_s*dir_emit_s[Z]; + u_spec_s[X] = V[X] - alpha_spec_s*dir_spec_s[X]; + u_spec_s[Y] = V[Y] - alpha_spec_s*dir_spec_s[Y]; + u_spec_s[Z] = V[Z] - alpha_spec_s*dir_spec_s[Z]; + beta_emit_s = d3_normalize(u_emit_s, u_emit_s); + beta_spec_s = d3_normalize(u_spec_s, u_spec_s); + + dir_spec_e[X] = -dir_spec_s[X]; + dir_spec_e[Y] = -dir_spec_s[Y]; + dir_spec_e[Z] = -dir_spec_s[Z]; + + alpha_emit_e = d3_dot(u_emit_s, normal_e) / d3_dot(dir_spec_e, normal_e); + alpha_spec_e = d3_dot(u_spec_s, normal_e) / d3_dot(dir_spec_e, normal_e); + u_emit_e[X] = u_emit_s[X] - alpha_emit_e*dir_spec_e[X]; + u_emit_e[Y] = u_emit_s[Y] - alpha_emit_e*dir_spec_e[Y]; + u_emit_e[Z] = u_emit_s[Z] - alpha_emit_e*dir_spec_e[Z]; + u_spec_e[X] = u_spec_s[X] - alpha_spec_e*dir_spec_e[X]; + u_spec_e[Y] = u_spec_s[Y] - alpha_spec_e*dir_spec_e[Y]; + u_spec_e[Z] = u_spec_s[Z] - alpha_spec_e*dir_spec_e[Z]; beta_emit_e = d3_normalize(u_emit_e, u_emit_e); beta_spec_e = d3_normalize(u_spec_e, u_spec_e); rho = 0.25 - * (1 - cos(2*PI*pos_emit[X]/EMIT_SZ[X])) - * (1 - cos(2*PI*pos_emit[Y]/EMIT_SZ[Y])); + * (1 - cos(2*PI*pos_emit_s[X]/EMIT_S_SZ[X])) + * (1 - cos(2*PI*pos_emit_s[Y]/EMIT_S_SZ[Y])); grad_rho[X] = 0.25 - * (((2*PI)/EMIT_SZ[X])*sin(2*PI*pos_emit[X]/EMIT_SZ[X])) - * (1 - cos(2*PI*pos_emit[Y]/EMIT_SZ[Y])); + * (((2*PI)/EMIT_S_SZ[X])*sin(2*PI*pos_emit_s[X]/EMIT_S_SZ[X])) + * (1 - cos(2*PI*pos_emit_s[Y]/EMIT_S_SZ[Y])); grad_rho[Y] = 0.25 - * (((2*PI)/EMIT_SZ[Y])*sin(2*PI*pos_emit[Y]/EMIT_SZ[Y])) - * (1 - cos(2*PI*pos_emit[X]/EMIT_SZ[X])); + * (((2*PI)/EMIT_S_SZ[Y])*sin(2*PI*pos_emit_s[Y]/EMIT_S_SZ[Y])) + * (1 - cos(2*PI*pos_emit_s[X]/EMIT_S_SZ[X])); grad_rho[Z] = 0; I = @@ -175,15 +206,16 @@ realisation(void* weight, struct ssp_rng* rng, const unsigned ithread, void* ctx * (1 - cos(2*PI*pos_emit_e[Y]/EMIT_E_SZ[Y])); S = - - beta_emit * d3_dot(grad_rho, u_emit) * I - - rho * beta_emit * beta_emit_e * d3_dot(grad_I, u_emit_e) - + rho * beta_spec * beta_spec_e * d3_dot(grad_I, u_spec_e); + - beta_emit_s * d3_dot(grad_rho, u_emit_s) * I + - rho * beta_emit_s * beta_emit_e * d3_dot(grad_I, u_emit_e) + + rho * beta_spec_s * beta_spec_e * d3_dot(grad_I, u_spec_e); - /* w = I*EMIT_SZ[X]*EMIT_SZ[Y]*PI;*/ /* Weight */ - w = S*EMIT_SZ[X]*EMIT_SZ[Y]*PI; /* Sensib */ + w = I*EMIT_S_SZ[X]*EMIT_S_SZ[Y]*PI; /* Weight */ + s = S*EMIT_S_SZ[X]*EMIT_S_SZ[Y]*PI; /* Sensib */ exit: - SMC_DOUBLE(weight) = w; + SMC_DOUBLEN(weights)[WEIGHT] = w; + SMC_DOUBLEN(weights)[SENSIB] = s; return res; error: goto exit; @@ -199,6 +231,7 @@ compute_trans_sensib(struct sgs* sgs) struct smc_estimator_status status; struct smc_device* smc = NULL; struct smc_estimator* estimator = NULL; + struct smc_doubleN_context ctx; res_T res = RES_OK; ASSERT(sgs); @@ -213,12 +246,14 @@ compute_trans_sensib(struct sgs* sgs) /* Setup the integrator */ integrator.integrand = realisation; - integrator.type = &smc_double; + integrator.type = &smc_doubleN; integrator.max_realisations = sgs->nrealisations; integrator.max_failures = (size_t)((double)sgs->nrealisations*0.01); + ctx.count = WEIGHTS_COUNT__; + ctx.integrand_data = sgs; /* Run Monte-Carlo integration */ - res = smc_solve(smc, &integrator, sgs, &estimator); + res = smc_solve(smc, &integrator, &ctx, &estimator); if(res != RES_OK) { sgs_log_err(sgs, "Error while solving 4V/S -- %s.\n", res_to_cstr(res)); @@ -234,9 +269,12 @@ compute_trans_sensib(struct sgs* sgs) } /* Print the result */ - sgs_log(sgs, "%g +/- %g; #failures = %lu/%lu\n", - SMC_DOUBLE(status.E), - SMC_DOUBLE(status.SE), + sgs_log(sgs, "estim ~ %g +/- %g; sensib ~ %g +/- %g\n", + SMC_DOUBLEN(status.E)[WEIGHT], + SMC_DOUBLEN(status.SE)[WEIGHT], + SMC_DOUBLEN(status.E)[SENSIB], + SMC_DOUBLEN(status.SE)[SENSIB]); + sgs_log(sgs, "#failures = %lu/%lu\n", (unsigned long)status.NF, (unsigned long)sgs->nrealisations);