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 a3377a8c8c785b7d1f5cebb286956bea98f380ca
parent d97612754c9ccd7592792a5d1d502b805778b7e2
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Wed,  1 Feb 2023 18:32:58 +0100

Remplace les sources C par leur version Noweb

Diffstat:
MMakefile | 20+++++++++++++-------
Mconfig.mk | 2+-
Dsrc/sgs_compute_sensitivity_translation.c | 417-------------------------------------------------------------------------------
3 files changed, 14 insertions(+), 425 deletions(-)

diff --git a/Makefile b/Makefile @@ -24,16 +24,19 @@ include config.mk +DOC = sgs_compute_sensitivity_translation + +TMPC =\ + src/sgs_compute_sensitivity_translation.c + SRC =\ src/sgs_args.c\ src/sgs.c\ - src/sgs_compute_sensitivity_translation.c\ src/sgs_geometry_box.c\ src/sgs_geometry.c\ src/sgs_log.c\ - src/sgs_main.c - -DOC = sgs_compute_sensitivity_translation + src/sgs_main.c\ + $(TMPC) NOWEB=\ src/$(DOC).nw @@ -58,9 +61,12 @@ sgs: $(OBJ) @echo "configure $(MAKE)" @$(SHELL) configure.sh program && echo "config done" > $@ || exit 1 +$(TMPC): $(NOWEB) config.mk + @$(TANGLE) $(TANGLE_OPTS)\ + -R$$(c="$@" && echo "$${c##*/}" | sed 's/_/\\_/g') $(NOWEB) | cpif $@ + .SUFFIXES: .c .d .o .c.d: - @#echo "DEP $@" @$(CC) $(CFLAGS) -MM -MT "$(@:.d=.o) $@" $< -MF $@ .c.o: @@ -102,8 +108,8 @@ uninstall: rm -f $(DESTDIR)$(PREFIX)/share/doc/star-gs/README.md clean: - @rm -f $(OBJ) $(TEX) sgs .config_program .config_document ./*.aux ./*.bbl\ - ./*.idx ./*.log ./*.dvi ./*.glo ./*.lof ./*.toc ./*.out ./*.blg\ + @rm -f $(OBJ) $(TEX) $(TMPC) sgs .config_program .config_document ./*.aux\ + ./*.bbl ./*.idx ./*.log ./*.dvi ./*.glo ./*.lof ./*.toc ./*.out ./*.blg\ ./*.nav ./*.snm ./*.vrb weave* $(DOC).pdf distclean: clean diff --git a/config.mk b/config.mk @@ -33,7 +33,7 @@ LATEX = pdflatex TANGLE = notangle WEAVE = noweave -TANGLE_OPTS = #-L +TANGLE_OPTS = -L WEAVE_OPTS = -index -delay -v ################################################################################ diff --git a/src/sgs_compute_sensitivity_translation.c b/src/sgs_compute_sensitivity_translation.c @@ -1,417 +0,0 @@ -/* Copyright (C) 2021-2023 Centre National de la Recherche Scientifique - * Copyright (C) 2021-2023 Institut Mines Télécom Albi-Carmaux - * Copyright (C) 2021-2023 |Méso|Star> (contact@meso-star.com) - * Copyright (C) 2021-2023 Université Clermont Auvergne - * Copyright (C) 2021-2023 Université de Lorraine - * Copyright (C) 2021-2023 Université de Lyon - * Copyright (C) 2021-2023 Université de Toulouse - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. */ - -#include "sgs_c.h" -#include "sgs_geometry.h" -#include "sgs_log.h" - -#include <rsys/cstr.h> - -#include <star/smc.h> -#include <star/ssp.h> - -/* Sugar syntax */ -enum {X, Y, Z}; -enum {WEIGHT, SENSIB, WEIGHTS_COUNT__}; - -/* FIXME this should be variables */ -#if 0 -/* Il semblerait que le cube soit de taille {4, 4, 3} */ -static const double RECV_MIN[2] = {0.5, 1.5}; -static const double RECV_MAX[2] = {1.5, 2.5}; -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}; -#else -static const double RECV_MIN[2] = {0.125/*<=>1/8*/, 0.375/*<=>3/8*/}; -static const double RECV_MAX[2] = {0.375/*<=>3/8*/, 0.625/*<=>5/8*/}; -static const double EMIT_E_THRESHOLD = 2.0/3.0; -static const double EMIT_E_SZ[3] = {0, 1, 2.0/3.0}; -static const double EMIT_S_SZ[3] = {1, 1, 0}; -#endif - -/* Vecteur de déformation (à renommer en gamma ?) */ -static const double V[3] = {0, 0, 1}; - -struct deformation_2d { - double alpha; - double beta; - double u[3]; -}; - -struct scene { - /* Upper and lower limit of the scene */ - double box_low[3]; - double box_upp[3]; - - double box_sz[3]; /* Size of the scene */ - - /* Geometry of the receiver on the box bottom plane */ - double recv_min[3]; - double recv_max[3]; - - double emit_e_threshold; /* Geometric upper bound of the radiative source */ - double emit_e_sz[3]; /* Size of the radiative source */ - double emit_s_sz[3]; /* Size of the specular surface */ -}; - -/******************************************************************************* - * Helper functions - ******************************************************************************/ -static void -setup_scene(const struct sgs_geometry* geometry, struct scene* scn) -{ - ASSERT(geometry && scn); - - /* Compute the size of the geometry */ - sgs_geometry_get_aabb(geometry, scn->box_low, scn->box_upp); - d3_sub(scn->box_sz, scn->box_upp, scn->box_low); - - /* Setup the geometry of the receiver */ - scn->recv_min[X] = RECV_MIN[X]*scn->box_sz[X] + scn->box_low[X]; - scn->recv_min[Y] = RECV_MIN[Y]*scn->box_sz[Y] + scn->box_low[Y]; - scn->recv_min[Z] = 0; - scn->recv_max[X] = RECV_MAX[X]*scn->box_sz[X] + scn->box_low[X]; - scn->recv_max[Y] = RECV_MAX[Y]*scn->box_sz[Y] + scn->box_low[Y]; - scn->recv_max[Z] = 0; - - /* Setup the geometry of the radiative source */ - scn->emit_e_threshold = EMIT_E_THRESHOLD*scn->box_sz[Z] + scn->box_low[Z]; - - /* Compute the size of the radiative source/specular surface */ - scn->emit_e_sz[X] = EMIT_E_SZ[X]*scn->box_sz[X] + scn->box_low[X]; - scn->emit_e_sz[Y] = EMIT_E_SZ[Y]*scn->box_sz[Y] + scn->box_low[Y]; - scn->emit_e_sz[Z] = EMIT_E_SZ[Z]*scn->box_sz[Z] + scn->box_low[Z]; - scn->emit_s_sz[X] = EMIT_S_SZ[X]*scn->box_sz[X] + scn->box_low[X]; - scn->emit_s_sz[Y] = EMIT_S_SZ[Y]*scn->box_sz[Y] + scn->box_low[Y]; - scn->emit_s_sz[Z] = EMIT_S_SZ[Z]*scn->box_sz[Z] + scn->box_low[Z]; -} - -/* Return 1 if the `hit' lies on the receiver and 0 otherwise */ -static int -hit_receiver - (const struct scene* scn, - const double ray_org[3], - const double ray_dir[3], - const struct sgs_hit* hit, - double pos_recv[3]) -{ - ASSERT(scn && ray_org && ray_dir && hit && pos_recv); - - pos_recv[X] = ray_org[X] + hit->distance*ray_dir[X]; - pos_recv[Y] = ray_org[Y] + hit->distance*ray_dir[Y]; - pos_recv[Z] = ray_org[Z] + hit->distance*ray_dir[Z]; - - if(hit->surface != SGS_SURFACE_Z_MIN - || pos_recv[X] < scn->recv_min[X] || scn->recv_max[X] < pos_recv[X] - || pos_recv[Y] < scn->recv_min[Y] || scn->recv_max[Y] < pos_recv[Y]) { - return 0; /* The ray does not intersect the receiver */ - } else { - return 1; - } -} - -/* Return 1 if the `hit' lies on the source and 0 otherwise */ -static int -hit_source - (const struct scene* scn, - const double ray_org[3], - const double ray_dir[3], - const struct sgs_hit* hit, - double pos_emit_e[3]) -{ - pos_emit_e[X] = ray_org[X] + hit->distance*ray_dir[X]; - pos_emit_e[Y] = ray_org[Y] + hit->distance*ray_dir[Y]; - pos_emit_e[Z] = ray_org[Z] + hit->distance*ray_dir[Z]; - - if(hit->surface != SGS_SURFACE_X_MAX - || pos_emit_e[Z] > scn->emit_e_threshold) { - return 0; /* The ray does not intersect the emitter */ - } else { - return 1; - } -} - -static double -compute_rho - (const double position[2], /* Position sur la surface réfléchissante */ - const double size[2]) /* Taille de la surface réfléchissante */ -{ - ASSERT(position && size); - return 0.25 - * (1 - cos(2*PI*position[X]/size[X])) - * (1 - cos(2*PI*position[Y]/size[Y])); -} - -static void -compute_grad_rho - (const double position[2], /* Position sur la surface réfléchissante */ - const double size[2], /* Taille de la surface réfléchissante */ - double out_gradient[2]) -{ - ASSERT(position && size && out_gradient); - out_gradient[X] = 0.25 - * (((2*PI)/size[X])*sin(2*PI*position[X]/size[X])) - * (1 - cos(2*PI*position[Y]/size[Y])); - out_gradient[Y] = 0.25 - * (((2*PI)/size[Y])*sin(2*PI*position[Y]/size[Y])) - * (1 - cos(2*PI*position[X]/size[X])); -} - -static double -compute_I - (const double position[2], /* Position sur la surface émettrice */ - const double size[2]) /* Taille de la surface émettrice */ -{ - ASSERT(position && size); - return - (1 - cos(2*PI*position[X]/size[X])) - * (1 - cos(2*PI*position[Y]/size[Y])); -} - -static void -compute_grad_I - (const double position[2], /* Position sur la surface réfléchissante */ - const double size[2], /* Taille de la surface réfléchissante */ - double out_gradient[2]) -{ - ASSERT(position && size && out_gradient); - out_gradient[X] = - (((2*PI)/size[X])*sin(2*PI*position[X]/size[X])) - * (1 - cos(2*PI*position[Y]/size[Y])); - out_gradient[Y] = - (((2*PI)/size[Y])*sin(2*PI*position[Y]/size[Y])) - * (1 - cos(2*PI*position[X]/size[X])); -} - -static void -decomposition - (const double chi[3], - const double normal[3], - const double omega[3], - struct deformation_2d* out_vector) -{ - ASSERT(chi && normal && omega && out_vector); - ASSERT(d3_is_normalized(normal)); - ASSERT(d3_is_normalized(omega)); - - out_vector->alpha = d3_dot(chi, normal) / d3_dot(omega, normal); - out_vector->u[X] = chi[X] - out_vector->alpha*omega[X]; - out_vector->u[Y] = chi[Y] - out_vector->alpha*omega[Y]; - out_vector->u[Z] = chi[Z] - out_vector->alpha*omega[Z]; - out_vector->beta = d3_normalize(out_vector->u, out_vector->u); -} - -static res_T -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 deformation_2d proj_u_e; - struct deformation_2d proj_V_e; - struct deformation_2d proj_V_s; - - struct scene scn; - double emit_e_sz_2d[2]; - double emit_s_sz_2d[2]; - - double normal_e[3]; - double normal_s[3]; - - double dir_emit_s[3]; - double dir_spec_e[3]; - double dir_spec_s[3]; - double pos_emit_e[3], pos_emit_e_2d[2]; - double pos_emit_s[3], pos_emit_s_2d[2]; - double pos_recv[3]; - - double rho; - double grad_rho[3], grad_rho_2d[2]; - double I; - double grad_I[3], grad_I_2d[2]; - - double S; - - double w = 0; - double s = 0; - - enum sgs_surface_type surf_emit_s; - - res_T res = RES_OK; - (void)ithread; - - setup_scene(sgs->scene.geom, &scn); - - /* Sample the sensitivity emissive surface */ - sgs_geometry_sample(sgs->scene.geom, rng, &frag); - d3_set(pos_emit_s, frag.position); - d3_set(normal_s, frag.normal); - surf_emit_s = frag.surface; - - /* Sample the cosine weighted sampling of the emissive direction */ - ssp_ran_hemisphere_cos(rng, normal_s, dir_emit_s, NULL); - - /* Helper macro used as syntactic sugar */ - #define TRACE_RAY(Org, Dir, StartFrom, Hit) { \ - const double range[2] = {0, DBL_MAX}; \ - sgs_geometry_trace_ray(sgs->scene.geom, (Org), (Dir), range, (StartFrom), (Hit));\ - if(SGS_HIT_NONE(&hit)) { res = RES_BAD_ARG; goto error; } \ - } (void)0 - - /* Trace the sampled ray and check that if reaches the receiver? */ - TRACE_RAY(pos_emit_s, dir_emit_s, surf_emit_s, &hit); - if(!hit_receiver(&scn, pos_emit_s, dir_emit_s, &hit, pos_recv)) goto exit; - - /* Trace the reflected ray and check that if reaches the source? */ - reflect(dir_spec_s, dir_emit_s, normal_s); - TRACE_RAY(pos_emit_s, dir_spec_s, surf_emit_s, &hit); - if(!hit_source(&scn, pos_emit_s, dir_spec_s, &hit, pos_emit_e)) goto exit; - - #undef TRACE_RAY - - /* Calcul du poids */ - - d3_set(normal_e, hit.normal); - d3_minus(dir_spec_e, dir_spec_s); - - decomposition(V, normal_e, dir_spec_e, &proj_V_e); - decomposition(V, normal_s, dir_emit_s, &proj_V_s); - decomposition(proj_V_s.u, normal_e, dir_spec_e, &proj_u_e); - - pos_emit_s_2d[X] = pos_emit_s[X]; - pos_emit_s_2d[Y] = pos_emit_s[Y]; - emit_s_sz_2d[X] = scn.emit_s_sz[X]; - emit_s_sz_2d[Y] = scn.emit_s_sz[Y]; - rho = compute_rho(pos_emit_s_2d, emit_s_sz_2d); - compute_grad_rho(pos_emit_s_2d, emit_s_sz_2d, grad_rho_2d); - grad_rho[X] = grad_rho_2d[X]; - grad_rho[Y] = grad_rho_2d[Y]; - grad_rho[Z] = 0; - - pos_emit_e_2d[X] = pos_emit_e[Y]; - pos_emit_e_2d[Y] = pos_emit_e[Z]; - emit_e_sz_2d[X] = scn.emit_e_sz[Y]; - emit_e_sz_2d[Y] = scn.emit_e_sz[Z]; - I = compute_I(pos_emit_e_2d, emit_e_sz_2d); - compute_grad_I(pos_emit_e_2d, emit_e_sz_2d, grad_I_2d); - grad_I[X] = 0; - grad_I[Y] = grad_I_2d[X]; - grad_I[Z] = grad_I_2d[Y]; - - S = - - proj_V_s.beta * d3_dot(grad_rho, proj_V_s.u) * I - - rho * proj_V_s.beta * proj_u_e.beta * d3_dot(grad_I, proj_u_e.u) - + rho * proj_V_e.beta * d3_dot(grad_I, proj_V_e.u); - - w = I*scn.emit_s_sz[X]*scn.emit_s_sz[Y]*PI; /* Weight */ - s = S*scn.emit_s_sz[X]*scn.emit_s_sz[Y]*PI; /* Sensib */ - -exit: - SMC_DOUBLEN(weights)[WEIGHT] = w; - SMC_DOUBLEN(weights)[SENSIB] = s; - return res; -error: - goto exit; -} - -/******************************************************************************* - * Local function - ******************************************************************************/ -res_T -compute_sensitivity_translation(struct sgs* sgs) -{ - struct smc_device_create_args args = SMC_DEVICE_CREATE_ARGS_DEFAULT; - struct smc_estimator_status status = SMC_ESTIMATOR_STATUS_NULL; - struct smc_integrator integrator = SMC_INTEGRATOR_NULL; - struct smc_device* smc = NULL; - struct smc_estimator* estimator = NULL; - struct smc_doubleN_context ctx; - res_T res = RES_OK; - ASSERT(sgs); - - if(sgs_geometry_get_sampling_mask(sgs->scene.geom) != SGS_SURFACE_Z_MAX) { - sgs_log_err(sgs, - "Invalid sensitivity emissive surface. Only positive Z face of the box " - "geometry can be a sensitivity source.\n"); - res = RES_BAD_ARG; - goto error; - } - - /* Create the Star-MonteCarlo device */ - args.logger = &sgs->logger; - args.allocator = sgs->allocator; - args.nthreads_hint = sgs->nthreads; - args.rng_type = SSP_RNG_MT19937_64; - res = smc_device_create(&args, &smc); - if(res != RES_OK) { - sgs_log_err(sgs, "Could not create the Star-MonteCarlo device -- %s.\n", - res_to_cstr(res)); - goto error; - } - - /* Setup the integrator */ - integrator.integrand = realisation; - 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, &ctx, &estimator); - if(res != RES_OK) { - sgs_log_err(sgs, "Error while solving 4V/S -- %s.\n", - res_to_cstr(res)); - goto error; - } - - /* Retrieve the estimated value */ - SMC(estimator_get_status(estimator, &status)); - if(status.NF >= integrator.max_failures) { - sgs_log_err(sgs, "Too many failures: %lu\n", (unsigned long)status.NF); - res = RES_BAD_OP; - goto error; - } - - /* Print the result */ - 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); - -exit: - if(smc) SMC(device_ref_put(smc)); - if(estimator) SMC(estimator_ref_put(estimator)); - return res; -error: - goto exit; -}