star-gf

Compute Gebhart factors
git clone git://git.meso-star.fr/star-gf.git
Log | Files | Refs | README | LICENSE

commit c30ea2d0f67698513c8213dec6f33335e1785d40
parent c22998c6d97f1fc27a9976224b20346056ed52a0
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Fri, 24 Jul 2015 17:25:55 +0200

Change the API of the sgf_context

Replace the spectral band identifier by the number of spectral bands.
The sgf_integrate use this data to compute the Gebhart Factor for *all*
spectral bands. Up to now, only one spectral band was computed per
sgf_integrate call. With this update, the radiative flux of each
spectral band of a primitive are computed and stored sequentially.

Diffstat:
Msrc/sgf.c | 69++++++++++++++++++++++++++++++++++++++++++---------------------------
Msrc/sgf.h | 11+++++++++--
Msrc/test_sgf_cube.c | 8++++++--
Msrc/test_sgf_tetrahedron.c | 10+++++++---
4 files changed, 64 insertions(+), 34 deletions(-)

diff --git a/src/sgf.c b/src/sgf.c @@ -55,9 +55,11 @@ static res_T gebhart_radiative_path (struct sgf_accum* result, struct ssp_rng* rng, - struct sgf_context* ctx) + struct sgf_context* ctx, + const size_t ispectral_band) { struct s3d_hit hit; + struct sgf_accum* gebfac; /* Gebhart factor */ double transmissivity = 1.0; double proba_reflec_spec; double emissivity; @@ -65,18 +67,17 @@ gebhart_radiative_path double specularity; const double trans_min = 1.e-8; size_t iprim, iprim_from; - size_t nbounce = 0; float vec0[3], vec1[3]; float triangle[3][3]; float normal[3]; float pos[3]; float dir[4]; float range[2]; - float dist; + ASSERT(ispectral_band < ctx->spectral_bands_count); /* Discard faces with no emissivity */ emissivity = ctx->get_material_property(ctx->material, - SGF_MATERIAL_EMISSIVITY, ctx->primitive_id, ctx->spectral_band_id); + SGF_MATERIAL_EMISSIVITY, ctx->primitive_id, ispectral_band); if(emissivity <= 0.0) return RES_OK; @@ -122,31 +123,38 @@ gebhart_radiative_path f3_add(pos, vec0, pos); iprim = hit.prim.prim_id; ASSERT(iprim < ctx->primitives_count); -#ifndef NDEBUG + + /* FIXME Why ? */ ctx->get_triangle(ctx->geometry, iprim, triangle); - dist = f3_dot(pos, normal) - f3_dot(normal, triangle[0]);/*Ax + By + Cz + D*/ - ASSERT(eq_eps(dist, 0, 1.e-6f)); + ssp_ran_triangle_uniform(rng, triangle[0], triangle[1], triangle[2], pos); +#ifndef NDEBUG + { + /*Ax + By + Cz + D*/ + const float dist = f3_dot(pos, normal) - f3_dot(normal, triangle[0]); + ASSERT(eq_eps(dist, 0, 1.e-6f)); + } #endif /* Fetch material property */ emissivity = ctx->get_material_property - (ctx->material, SGF_MATERIAL_EMISSIVITY, iprim, ctx->spectral_band_id); + (ctx->material, SGF_MATERIAL_EMISSIVITY, iprim, ispectral_band); specularity = ctx->get_material_property - (ctx->material, SGF_MATERIAL_SPECULARITY, iprim, ctx->spectral_band_id); + (ctx->material, SGF_MATERIAL_SPECULARITY, iprim, ispectral_band); reflectivity = ctx->get_material_property - (ctx->material, SGF_MATERIAL_REFLECTIVITY, iprim, ctx->spectral_band_id); + (ctx->material, SGF_MATERIAL_REFLECTIVITY, iprim, ispectral_band); + gebfac = result + iprim * ctx->spectral_bands_count; if(transmissivity > trans_min) { const double weight = transmissivity * emissivity; - result[iprim].radiative_flux += weight; - result[iprim].sqr_radiative_flux += weight * weight; + gebfac[ispectral_band].radiative_flux += weight; + gebfac[ispectral_band].sqr_radiative_flux += weight * weight; transmissivity = transmissivity * (1.0 - emissivity); } else { /* Russian roulette */ if(ssp_rng_canonical(rng) < emissivity) { const double weight = transmissivity; - result[iprim].radiative_flux += weight; - result[iprim].sqr_radiative_flux += weight * weight; + gebfac[ispectral_band].radiative_flux += weight; + gebfac[ispectral_band].sqr_radiative_flux += weight * weight; break; } } @@ -166,15 +174,15 @@ gebhart_radiative_path f3_add(dir, dir, vec0); f3_normalize(dir, dir); } - ++nbounce; ctx->get_triangle(ctx->geometry, iprim, triangle); } -/* ASSERT(nbounce <= 1);*/ #if 1 && !defined(NDEBUG) { /* Ensure the energy conservation property */ double sum_radiative_flux = 0.0; + gebfac = result; FOR_EACH(iprim, 0, ctx->primitives_count) { - sum_radiative_flux += result[iprim].radiative_flux; + sum_radiative_flux += gebfac[ispectral_band].radiative_flux; + gebfac += ctx->spectral_bands_count; } ASSERT(eq_eps(sum_radiative_flux, 1.0, 1.e-6)); } @@ -189,22 +197,29 @@ gebhart_factor_integrand void* context) { struct sgf_context* ctx = context; + struct sgf_accum* buf; size_t nfailures = 0; + size_t iband = 0; res_T res = RES_OK; - do { - accum_buffer_clear(result); - res = gebhart_radiative_path(darray_gfacc_data_get(result), rng, ctx); - } while(res == RES_BAD_OP && (++nfailures < MAX_FAILURES)); + ASSERT(result && rng && context); + + buf = darray_gfacc_data_get(result); + FOR_EACH(iband, 0, ctx->spectral_bands_count) { + do { + accum_buffer_clear(result); + res = gebhart_radiative_path(buf, rng, ctx, iband); + } while(res == RES_BAD_OP && (++nfailures < MAX_FAILURES)); - if(ctx->verbose) { - if(nfailures >= MAX_FAILURES) { - logger_print(ctx->logger, LOG_ERROR, + if(ctx->verbose) { + if(nfailures >= MAX_FAILURES) { + logger_print(ctx->logger, LOG_ERROR, "Too many radiative path failures. The geometry might be wrongly setuped. The\n" "geometry should be closed and 2D-manifold. In addition its normals must point\n" "*into* the volume with respect to a Clock Wise vertex ordering\n"); - } else if(res != RES_OK) { - logger_print(ctx->logger, LOG_ERROR, - "Critical error in the computation of the gebhart factor\n"); + } else if(res != RES_OK) { + logger_print(ctx->logger, LOG_ERROR, + "Critical error in the computation of the Gebhart factor\n"); + } } } } diff --git a/src/sgf.h b/src/sgf.h @@ -69,7 +69,7 @@ struct sgf_context { size_t primitives_count; /* Total number of primitives */ size_t primitive_id; /* Triangle id on which the integration is performed */ - size_t spectral_band_id; /* Identifier of the spectral band */ + size_t spectral_bands_count; /* Total number of spectral bands */ struct s3d_scene* scene; /* Star-3D encapsulation of the geometry */ struct logger* logger; /* Message logger */ @@ -88,10 +88,17 @@ struct sgf_accum { BEGIN_DECLS +/* Integrate the Gebhart Factor. The output `accum_buffer' stores the + * accumulated radiative flux emitted from `ctx->primitive_id' to each + * primitive and for each spectral band. The size of accum_buffer must be at + * least equal to ctx->primitives_count * ctx->spectral_bands_count. The + * spectral bands of a primitive are stored sequentially. For instance, let the + * face F and N spectral bands, the accumulated radiative flux of F are saved + * in accum_buffer[F*N .. F*N + N). */ SGF_API res_T sgf_integrate (struct smc_device* smc, - struct sgf_context* contex, + struct sgf_context* context, const size_t steps_count, struct sgf_accum* accum_buffer); diff --git a/src/test_sgf_cube.c b/src/test_sgf_cube.c @@ -135,7 +135,7 @@ main(int argc, char** argv) ctx.get_material_property = get_material_property; ctx.material = &mtr; ctx.primitives_count = nprims; - ctx.spectral_band_id = 0; + ctx.spectral_bands_count = 1; ctx.scene = scn; ctx.logger = LOGGER_DEFAULT; ctx.verbose = 1; @@ -214,17 +214,21 @@ main(int argc, char** argv) FOR_EACH(iprim, 0, nprims/2) { const struct sgf_accum* row = gfacc + iprim * nprims; size_t icol; + double sum = 0.0; FOR_EACH(icol, 0, nprims/2) { const double E = row[icol].radiative_flux / ((double)nsteps_adjusted); + sum += E; printf("%.6f ", E); } printf("\n"); + /* Ensure the energy conservation property */ + CHECK(eq_eps(sum, 1.0, 1.e-6), 1); } printf("\n"); /* Standard error */ FOR_EACH(iprim, 0, nprims/2) { - const struct sgf_accum* row = gfacc + iprim * 12; + const struct sgf_accum* row = gfacc + iprim * nprims; size_t icol; FOR_EACH(icol, 0, nprims/2) { const double V = row[icol].sqr_radiative_flux / ((double)nsteps_adjusted) diff --git a/src/test_sgf_tetrahedron.c b/src/test_sgf_tetrahedron.c @@ -35,7 +35,7 @@ #include <star/s3d.h> #include <star/smc.h> -#define NSTEPS 10000L +#define NSTEPS 100000L static const float vertices[] = { 0.57735026918962576450f, 0.f, 0.f, @@ -79,7 +79,7 @@ main(int argc, char** argv) CHECK(s3d_shape_create_mesh(s3d, &shape), RES_OK); CHECK(s3d_scene_create(s3d, &scn), RES_OK); CHECK(s3d_scene_attach_shape(scn, shape), RES_OK); - CHECK(smc_device_create(NULL, NULL, SMC_NTHREADS_DEFAULT, &smc), RES_OK); + CHECK(smc_device_create(NULL, NULL, 1, &smc), RES_OK); attribs[0].type = S3D_FLOAT3; attribs[0].usage = S3D_POSITION; @@ -102,7 +102,7 @@ main(int argc, char** argv) ctx.get_material_property = get_material_property; ctx.material = &mtr; ctx.primitives_count = nprims; - ctx.spectral_band_id = 0; + ctx.spectral_bands_count = 1; ctx.scene = scn; ctx.logger = LOGGER_DEFAULT; ctx.verbose = 1; @@ -121,11 +121,15 @@ main(int argc, char** argv) FOR_EACH(iprim, 0, nprims) { const struct sgf_accum* row = gfacc + iprim * nprims; unsigned icol; + double sum = 0.0; FOR_EACH(icol, 0, nprims) { const double E = row[icol].radiative_flux / NSTEPS; + sum += E; printf("%.6f ", E); } printf("\n"); + /* Ensure the energy conservation property */ + CHECK(eq_eps(sum, 1.0, 1.e-6), 1); } printf("\n");