star-gf

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

commit de44f0c3189f33c8115036c6f2d9fa51999e372c
parent c116b67b0b45168552d0f6a9b9af4ca335a2510e
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Fri, 25 Sep 2015 16:32:36 +0200

Add and test the sgf_estimator_get_status_infinity function

Return the estimated radiative flux that does not reach a geometry.

Diffstat:
Msrc/sgf.h | 9+++++++++
Msrc/sgf_estimator.c | 90++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------
Msrc/test_sgf_cube.c | 15+++++++++++++++
Msrc/test_sgf_tetrahedron.c | 7++++++-
4 files changed, 105 insertions(+), 16 deletions(-)

diff --git a/src/sgf.h b/src/sgf.h @@ -131,6 +131,8 @@ SGF_API res_T sgf_estimator_ref_put (struct sgf_estimator* estimator); +/* Return the estimated Gebhart Factor between the estimator primitive and + * `primitive_id'. */ SGF_API res_T sgf_estimator_get_status (struct sgf_estimator* estimator, @@ -138,6 +140,13 @@ sgf_estimator_get_status const size_t spectral_band_id, struct sgf_status* status); +/* Return the estimated radiative flux that hit nothing */ +SGF_API res_T +sgf_estimator_get_status_infinity + (struct sgf_estimator* estimator, + const size_t spectral_band, + struct sgf_status* status); + END_DECLS #endif /* SGF_H */ diff --git a/src/sgf_estimator.c b/src/sgf_estimator.c @@ -49,6 +49,8 @@ struct accum { /* Estimator of the Gebhart Factor of a given face to all the other ones */ struct sgf_estimator { struct darray_accum buf; /* Integrated radiative flux of each primitive */ + struct darray_accum buf_infinity; /* Radiative flux going to the infinity */ + size_t nsteps; /* # realisations */ size_t nprims; /* # primitives */ size_t nbands; /* # spectral bands */ @@ -75,10 +77,27 @@ accum_weight(struct accum* accums, const size_t iface, const double weight) accums[iface].sqr_radiative_flux += weight * weight; } +static FINLINE void +setup_status + (const struct accum* acc, + const size_t nsteps, + struct sgf_status* status) +{ + ASSERT(acc && status && nsteps); + + status->E = acc->radiative_flux / (double)nsteps; /* Expected value */ + status->V = /* Variance */ + acc->sqr_radiative_flux / (double)nsteps + - (acc->radiative_flux * acc->radiative_flux) / (double)(nsteps * nsteps); + status->SE = sqrt(status->V / (double)nsteps); /* Standard error */ + status->nsteps = nsteps; /* # realisations */ +} + /* Return RES_BAD_OP on numerical issue. i.e. the radiative path is skipped */ static res_T gebhart_radiative_path (struct accum* accums, + struct accum* accum_infinity, struct ssp_rng* rng, const size_t primitive_id, struct sgf_scene_desc* desc) @@ -88,10 +107,10 @@ gebhart_radiative_path struct s3d_attrib attrib; const double trans_min = 1.e-8; /* Minimum transmissivity threshold */ - double outside_radiative_flux = 0.0; double proba_reflec_spec; double transmissivity, emissivity, reflectivity, specularity; #ifndef NDEBUG + double infinite_radiative_flux = 0.0; double sum_radiative_flux = 0.f; #endif @@ -103,6 +122,8 @@ gebhart_radiative_path float range[2]; /* Traced ray range */ float u, v; + ASSERT(accums && accum_infinity && rng && desc); + /* Discard faces with no emissivity */ emissivity = desc->get_material_property(desc->material, SGF_MATERIAL_EMISSIVITY, primitive_id, 0); @@ -127,7 +148,6 @@ gebhart_radiative_path ssp_ran_hemisphere_cos(rng, normal, dir); transmissivity = 1.0; - outside_radiative_flux = 0.0; for(;;) { /* Here we go */ prim_from = prim; @@ -140,7 +160,11 @@ gebhart_radiative_path } if(S3D_HIT_NONE(&hit)) { /* The ray is outside the volume */ - outside_radiative_flux += transmissivity; + accum_infinity->radiative_flux += transmissivity; + accum_infinity->sqr_radiative_flux += transmissivity * transmissivity; +#ifndef NDEBUG + infinite_radiative_flux = transmissivity; +#endif break; } @@ -194,7 +218,7 @@ gebhart_radiative_path } #if !defined(NDEBUG) /* Check the energy conservation property */ - ASSERT(eq_eps(sum_radiative_flux + outside_radiative_flux, 1.0, 1.e6)); + ASSERT(eq_eps(sum_radiative_flux + infinite_radiative_flux, 1.0, 1.e6)); #endif return RES_OK; } @@ -219,6 +243,7 @@ estimator_create(struct sgf_device* dev, struct sgf_estimator** out_estimator) SGF(device_ref_get(dev)); estimator->dev = dev; darray_accum_init(dev->allocator, &estimator->buf); + darray_accum_init(dev->allocator, &estimator->buf_infinity); exit: *out_estimator = estimator; @@ -240,6 +265,7 @@ estimator_release(ref_T* ref) ASSERT(ref); estimator = CONTAINER_OF(ref, struct sgf_estimator, ref); darray_accum_release(&estimator->buf); + darray_accum_release(&estimator->buf_infinity); dev = estimator->dev; MEM_RM(dev->allocator, estimator); SGF(device_ref_put(dev)); @@ -295,24 +321,40 @@ sgf_integrate goto error; } - /* Allocate internal memory space */ + /* Allocate and init the Gebhart Factor result buffer */ res = darray_accum_resize(&estimator->buf, nprims*desc->spectral_bands_count); if(res != RES_OK) { if(dev->verbose) { logger_print(dev->logger, LOG_ERROR, -"Couldn't allocate the Gebhart Factor integration data structure.\n"); + "Couldn't allocate the Gebhart Factor result buffer.\n"); } goto error; } memset(darray_accum_data_get(&estimator->buf), 0, darray_accum_size_get(&estimator->buf)*sizeof(struct accum)); + /* Allocate and init the infinite radiative flux buffer */ + res = darray_accum_resize(&estimator->buf_infinity, desc->spectral_bands_count); + if(res != RES_OK) { + if(dev->verbose) { + logger_print(dev->logger, LOG_ERROR, + "Couldn't allocate the buffer of infinite radiative flux.\n"); + } + goto error; + } + memset(darray_accum_data_get(&estimator->buf_infinity), 0, + darray_accum_size_get(&estimator->buf_infinity)*sizeof(struct accum)); + /* Invoke the Gebhart factor integration. */ FOR_EACH(ispectral_band, 0, desc->spectral_bands_count) { struct accum* accums = darray_accum_data_get(&estimator->buf) + ispectral_band * nprims; + struct accum* accum_infinity = + darray_accum_data_get(&estimator->buf_infinity) + ispectral_band; + FOR_EACH(istep, 0, steps_count) { - res = gebhart_radiative_path(accums, rng, primitive_id, desc); + res = gebhart_radiative_path + (accums, accum_infinity, rng, primitive_id, desc); if(res != RES_OK) goto error; } } @@ -352,7 +394,6 @@ sgf_estimator_get_status struct sgf_status* status) { struct accum* acc; - size_t nsteps; size_t iacc; if(!estimator || !status) @@ -376,14 +417,33 @@ sgf_estimator_get_status iacc = ispectral_band * estimator->nprims + iprimitive; ASSERT(iacc < darray_accum_size_get(&estimator->buf)); acc = darray_accum_data_get(&estimator->buf) + iacc; - nsteps = estimator->nsteps; + setup_status(acc, estimator->nsteps, status); - status->E = acc->radiative_flux / (double)nsteps; /* Expected value */ - status->V = /* Variance */ - acc->sqr_radiative_flux / (double)nsteps - - (acc->radiative_flux * acc->radiative_flux) / (double)(nsteps * nsteps); - status->SE = sqrt(status->V / (double)nsteps); /* Standard error */ - status->nsteps = nsteps; /* # realisations */ + return RES_OK; +} + +res_T +sgf_estimator_get_status_infinity + (struct sgf_estimator* estimator, + const size_t ispectral_band, + struct sgf_status* status) +{ + struct accum* acc; + + if(!estimator || !status) + return RES_BAD_ARG; + + if(ispectral_band >= estimator->nbands) { + if(estimator->dev->verbose) { + logger_print(estimator->dev->logger, LOG_ERROR, + "Out of bound spectral band index `%lu'\n", ispectral_band); + } + return RES_BAD_ARG; + } + + ASSERT(ispectral_band < darray_accum_size_get(&estimator->buf_infinity)); + acc = darray_accum_data_get(&estimator->buf_infinity) + ispectral_band; + setup_status(acc, estimator->nsteps, status); return RES_OK; } diff --git a/src/test_sgf_cube.c b/src/test_sgf_cube.c @@ -232,7 +232,17 @@ main(int argc, char** argv) CHECK(sgf_estimator_get_status(estimator, SIZE_MAX, 0, status), RES_BAD_ARG); CHECK(sgf_estimator_get_status(NULL, 0, 0, status), RES_BAD_ARG); CHECK(sgf_estimator_get_status(estimator, 0, 0, status), RES_OK); + CHECK(status->nsteps, NSTEPS); + CHECK(sgf_estimator_get_status_infinity(NULL, SIZE_MAX, NULL), RES_BAD_ARG); + CHECK(sgf_estimator_get_status_infinity(estimator, SIZE_MAX, NULL), RES_BAD_ARG); + CHECK(sgf_estimator_get_status_infinity(NULL, 0, NULL), RES_BAD_ARG); + CHECK(sgf_estimator_get_status_infinity(estimator, 0, NULL), RES_BAD_ARG); + CHECK(sgf_estimator_get_status_infinity(NULL, SIZE_MAX, NULL), RES_BAD_ARG); + CHECK(sgf_estimator_get_status_infinity(estimator, SIZE_MAX, status), RES_BAD_ARG); + CHECK(sgf_estimator_get_status_infinity(NULL, 0, status), RES_BAD_ARG); + CHECK(sgf_estimator_get_status_infinity(estimator, 0, status), RES_OK); + CHECK(eq_eps(status->E, 0, status->SE), 1); CHECK(status->nsteps, NSTEPS); CHECK(sgf_estimator_ref_get(NULL), RES_BAD_ARG); @@ -246,15 +256,20 @@ main(int argc, char** argv) for(iprim = 0; iprim < nprims; ++iprim) { size_t iprim2; struct sgf_status* row = status + iprim * nprims; + struct sgf_status inf; const int ithread = omp_get_thread_num(); struct sgf_estimator* est; CHECK(sgf_integrate(sgf, rngs[ithread], iprim, &scn_desc, NSTEPS, &est), RES_OK); + CHECK(sgf_estimator_get_status_infinity(est, 0, &inf), RES_OK); + CHECK(eq_eps(inf.E, 0, 3 * inf.SE), 1); + FOR_EACH(iprim2, 0, nprims) { CHECK(sgf_estimator_get_status(est, iprim2, 0, row + iprim2), RES_OK); CHECK(row[iprim2].nsteps, NSTEPS); } + CHECK(sgf_estimator_ref_put(est), RES_OK); } diff --git a/src/test_sgf_tetrahedron.c b/src/test_sgf_tetrahedron.c @@ -121,11 +121,16 @@ main(int argc, char** argv) #pragma omp parallel for for(iprim = 0; iprim < nprims; ++iprim) { struct sgf_status* row = status + iprim*nprims; + struct sgf_status inf; struct sgf_estimator* estimator = NULL; size_t iprim2; const int ithread = omp_get_thread_num(); CHECK(sgf_integrate(sgf, rngs[ithread], iprim, &desc, NSTEPS, &estimator), RES_OK); + + CHECK(sgf_estimator_get_status_infinity(estimator, 0, &inf), RES_OK); + CHECK(eq_eps(inf.E, 0, 3*inf.SE), 1); + FOR_EACH(iprim2, 0, nprims) { CHECK(sgf_estimator_get_status(estimator, iprim2, 0, row + iprim2), RES_OK); CHECK(row[iprim2].nsteps, NSTEPS); @@ -145,7 +150,7 @@ main(int argc, char** argv) } printf("\n"); /* Ensure the energy conservation property */ - CHECK(eq_eps(sum, 1.0, 1.e-6), 1); + CHECK(eq_eps(sum, 1.0, 1.e-3), 1); } printf("\n");