star-schiff

Library for estimating radiative properties
git clone git://git.meso-star.com/star-schiff.git
Log | Files | Refs | README | LICENSE

commit 191dee04476221ae1f25a4878895af71b5437202
parent 29430c46f57e0db91bf0c09c2506aeb65bb39696
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Mon, 19 Oct 2015 14:48:12 +0200

Update the Schiff integration API

Diffstat:
Msrc/sschiff.h | 30+++++++++++++++---------------
Msrc/sschiff_estimator.c | 54++++++++++++++++++++++++++++--------------------------
Msrc/test_sschiff_estimator_cylinder.c | 19++++++++++---------
Msrc/test_sschiff_estimator_sphere.c | 64+++++++++++++++++++++++++++++++---------------------------------
4 files changed, 84 insertions(+), 83 deletions(-)

diff --git a/src/sschiff.h b/src/sschiff.h @@ -49,21 +49,23 @@ #define SSCHIFF(Func) sschiff_ ## Func #endif -/* Forward declaration of external types */ +/* Forward declaration of external types. */ struct mem_allocator; struct logger; struct s3d_device; struct s3d_shape; struct ssp_rng; +/* Optical properties of a material handled by the Schiff integrator. */ struct sschiff_material_properties { double medium_refractive_index; double relative_real_refractive_index; double relative_imaginary_refractive_index; }; +/* Client side material used by the Schiff integrator */ struct sschiff_material { - /* Retrieve the refractive complex index of the material */ + /* Retrieve the optical properties of the material */ void (*get_property) (void* material, const double wavelength, @@ -73,23 +75,17 @@ struct sschiff_material { static const struct sschiff_material SSCHIFF_NULL_MATERIAL = { NULL, NULL }; -/* Descriptor of an integration */ -struct sschiff_integrator_desc { - res_T (*sample_geometry) /* Sample a geometry i.e. a shape and its material */ +struct sschiff_geometry_distribution { + res_T (*sample) /* Sample a geometry i.e. a shape and its material */ (struct ssp_rng* rng, struct sschiff_material* mtl, /* Sampled material */ struct s3d_shape* shape, /* Sampled shape */ - void* sampler_context); - void* sampler_context; - double wavelength; /* Wavelenght to estimate */ - size_t scattering_angles_count; /* # of scattering angles to handle */ - size_t sampled_geometries_count; /* # geometries to sample */ - size_t sampled_directions_count; /* # directions to sample per geometry */ + void* context); + void* context; }; -static const struct sschiff_integrator_desc SSCHIFF_NULL_INTEGRATOR_DESC = { - NULL, NULL, 0, 0, 0, 0 -}; +static const struct sschiff_geometry_distribution +SSCHIFF_NULL_GEOMETRY_DISTRIBUTION = { NULL, NULL }; /* Result of the Monte Carlo estimation */ struct sschiff_estimator_status { @@ -128,7 +124,11 @@ SSCHIFF_API res_T sschiff_integrate (struct sschiff_device* dev, struct ssp_rng* rng, - struct sschiff_integrator_desc* desc, + struct sschiff_geometry_distribution* distribution, + const double wavelength, /* Wavelenght to estimate */ + const size_t scattering_angles_count, /* # of scattering angles to handle */ + const size_t sampled_geometries_count, /* # geometries to sample */ + const size_t sampled_directions_count, /* # directions to sample per geometry */ struct sschiff_estimator** estimator); SSCHIFF_API res_T diff --git a/src/sschiff_estimator.c b/src/sschiff_estimator.c @@ -26,7 +26,7 @@ * The fact that you are presently reading this means that you have had * knowledge of the CeCILL license and that you accept its terms. */ -#define _POSIX_C_SOURCE 200112L +#define _POSIX_C_SOURCE 200112L /* nextafterf support */ #include "sschiff.h" #include "sschiff_device.h" @@ -44,8 +44,7 @@ #include <math.h> -#define NDIRS 1000 /* # Sampled directions */ - +/* Type of computed Monte Carlo weights */ enum weight_type { WEIGHT_EXTINCTION_CROSS_SECTION, WEIGHT_ABSORPTION_CROSS_SECTION, @@ -54,6 +53,7 @@ enum weight_type { WEIGHTS_COUNT }; +/* Accumulator of Monte Carlo weights */ struct accum { double weight; double sqr_weight; @@ -82,7 +82,7 @@ morton2D_decode(const uint32_t u32) return (uint16_t)x; } -/* Compute an orthonormal basis where `dir' is the Z axis */ +/* Compute an orthonormal basis where `dir' is the Z axis. */ static void build_basis(const float dir[3], float basis[9]) { @@ -93,7 +93,7 @@ build_basis(const float dir[3], float basis[9]) /* Define which axis direction is minimal and use its unit vector to compute * a vector ortogonal to `dir'. This ensures that the unit vector and `dir' - * are not colinear and thus that their cross product is not a zero vector */ + * are not colinear and thus that their cross product is not a zero vector. */ FOR_EACH(i, 0, 3) dir_abs[i] = absf(dir[i]); if(dir_abs[0] < dir_abs[1]) { if(dir_abs[0] < dir_abs[2]) f3(axis_min, 1.f, 0.f, 0.f); @@ -340,8 +340,9 @@ static res_T radiative_properties (struct sschiff_device* dev, struct ssp_rng* rng, - struct sschiff_integrator_desc* desc, const int istep, + const double wavelength, + const size_t ndirs, struct s3d_scene* scene, struct sschiff_material_properties* props, struct accum accums[WEIGHTS_COUNT]) @@ -352,7 +353,7 @@ radiative_properties float centroid[3]; size_t idir; int i; - ASSERT(dev && rng && desc && props && accums); + ASSERT(dev && rng && ndirs && props && accums); (void)istep; S3D(scene_get_aabb(scene, lower, upper)); @@ -376,7 +377,7 @@ radiative_properties f3_mulf(centroid, f3_add(centroid, lower, upper), 0.5f); memset(weights_dirs, 0, sizeof(weights_dirs)); - FOR_EACH(idir, 0, desc->sampled_directions_count) { + FOR_EACH(idir, 0, ndirs) { double weights[WEIGHTS_COUNT]; float dir[4]; float basis[9]; @@ -402,8 +403,8 @@ radiative_properties f3_max(upper, upper, pt[i]); } - compute_monte_carlo_weight(dev, scene, rng, props, - desc->wavelength, basis, centroid, lower, upper, weights); + compute_monte_carlo_weight(dev, scene, rng, props, wavelength, basis, + centroid, lower, upper, weights); FOR_EACH(i, 0, WEIGHTS_COUNT) weights_dirs[i] += weights[i]; @@ -417,7 +418,7 @@ radiative_properties #endif } FOR_EACH(i, 0, WEIGHTS_COUNT) { - weights_dirs[i] /= (double)desc->sampled_directions_count; + weights_dirs[i] /= (double)ndirs; accums[i].weight += weights_dirs[i]; accums[i].sqr_weight += weights_dirs[i] * weights_dirs[i]; accums[i].naccums += 1; @@ -437,14 +438,10 @@ get_status(const struct accum* acc, struct sschiff_estimator_status* status) } static char -check_desc(struct sschiff_integrator_desc* desc) +check_distribution(struct sschiff_geometry_distribution* distrib) { - ASSERT(desc); - return desc->sample_geometry - && desc->scattering_angles_count - && desc->sampled_geometries_count - && desc->sampled_directions_count - && desc->wavelength > 0.f; + ASSERT(distrib); + return distrib->sample != NULL; } static void @@ -496,7 +493,11 @@ res_T sschiff_integrate (struct sschiff_device* dev, struct ssp_rng* rng, - struct sschiff_integrator_desc* desc, + struct sschiff_geometry_distribution* distrib, + const double wavelength, + const size_t scattering_angles_count, + const size_t sampled_geometries_count, + const size_t sampled_directions_count, struct sschiff_estimator** out_estimator) { struct sschiff_estimator* estimator = NULL; @@ -504,15 +505,16 @@ sschiff_integrate struct s3d_scene* scene = NULL; size_t i; res_T res = RES_OK; + (void)scattering_angles_count; - if(!dev || !rng || !desc || !check_desc(desc) || !out_estimator) { + if(!dev || !rng || !distrib || !check_distribution(distrib) || !out_estimator) { res = RES_BAD_ARG; goto error; } res = estimator_create(dev, &estimator); if(res != RES_OK) goto error; - estimator->wavelength = desc->wavelength; + estimator->wavelength = wavelength; res = s3d_shape_create_mesh(dev->s3d, &shape); if(res != RES_OK) { @@ -532,21 +534,21 @@ sschiff_integrate } memset(estimator->accums, 0, sizeof(struct accum)*WEIGHTS_COUNT); - FOR_EACH(i, 0, desc->sampled_geometries_count) { + FOR_EACH(i, 0, sampled_geometries_count) { struct sschiff_material material = SSCHIFF_NULL_MATERIAL; struct sschiff_material_properties props; - res = desc->sample_geometry(rng, &material, shape, desc->sampler_context); + res = distrib->sample(rng, &material, shape, distrib->context); if(res != RES_OK) { log_error(dev, "Error in sampling a Schiff geometry.\n"); goto error; } - material.get_property(material.material, desc->wavelength, &props); + material.get_property(material.material, wavelength, &props); S3D(scene_begin_session(scene, S3D_TRACE)); - res = radiative_properties(dev, rng, desc, (int)i, scene, &props, - estimator->accums); + res = radiative_properties(dev, rng, (int)i, wavelength, + sampled_directions_count, scene, &props, estimator->accums); if(res != RES_OK) goto error; S3D(scene_end_session(scene)); diff --git a/src/test_sschiff_estimator_cylinder.c b/src/test_sschiff_estimator_cylinder.c @@ -806,7 +806,7 @@ main(int argc, char** argv) struct mem_allocator allocator; struct sampler_context sampler_ctx; struct sschiff_device* dev; - struct sschiff_integrator_desc desc = SSCHIFF_NULL_INTEGRATOR_DESC; + struct sschiff_geometry_distribution distrib = SSCHIFF_NULL_GEOMETRY_DISTRIBUTION; struct sschiff_estimator* estimator; struct sschiff_estimator_status status; struct ssp_rng* rng; @@ -883,24 +883,25 @@ main(int argc, char** argv) sampler_ctx.aspect_ratio = 0.263; sampler_ctx.mean_radius = 0.983; - desc.sample_geometry = sample_cylinder; - desc.sampler_context = &sampler_ctx; - desc.scattering_angles_count = 1; - desc.sampled_geometries_count = 300; - desc.sampled_directions_count = 30; + distrib.sample = sample_cylinder; + distrib.context = &sampler_ctx; FOR_EACH(i, 0, nresults) { + const size_t nscatt_angles = 1; + const size_t ngeoms = 300; + const size_t ndirs = 30; + const double wavelength = results[i].wavelength; double dst; - desc.wavelength = results[i].wavelength; time_current(&t0); - CHECK(sschiff_integrate(dev, rng, &desc, &estimator), RES_OK); + CHECK(sschiff_integrate(dev, rng, &distrib, wavelength, nscatt_angles, + ngeoms, ndirs, &estimator), RES_OK); time_current(&t1); time_sub(&t0, &t1, &t0); time_dump(&t0, TIME_MIN|TIME_SEC|TIME_MSEC, NULL, buf, sizeof(buf)); CHECK(sschiff_estimator_get_extinction_cross_section(estimator, &status), RES_OK); - CHECK(status.nsteps, desc.sampled_geometries_count); + CHECK(status.nsteps, ngeoms); dst = status.E - results[i].extinction_cross_section; printf( diff --git a/src/test_sschiff_estimator_sphere.c b/src/test_sschiff_estimator_sphere.c @@ -241,21 +241,22 @@ check_schiff_estimation { char buf[64]; struct sschiff_estimator* estimator; - struct sschiff_integrator_desc desc = SSCHIFF_NULL_INTEGRATOR_DESC; + struct sschiff_geometry_distribution distrib = SSCHIFF_NULL_GEOMETRY_DISTRIBUTION; struct sschiff_estimator_status status; struct time t0, t1; size_t i; + const size_t nscatt_angles = 1; + const size_t ngeoms = 100; + const size_t ndirs = 10; + const double wavelength = sampler_ctx->wavelength; + NCHECK(sampler_ctx, NULL); NCHECK(results, NULL); NCHECK(results, 0); - desc.sample_geometry = sample_sphere; - desc.scattering_angles_count = 1; - desc.sampler_context = sampler_ctx; - desc.sampled_geometries_count = 100; - desc.sampled_directions_count = 10; - desc.wavelength = sampler_ctx->wavelength; + distrib.sample = sample_sphere; + distrib.context = sampler_ctx; printf("Schiff sphere estimation - m: %g; n_r: %g; kappa_r: %g; n_e: %g\n", sampler_ctx->wavelength, @@ -268,14 +269,15 @@ check_schiff_estimation sampler_ctx->mean_radius = results[i].mean_radius; time_current(&t0); - CHECK(sschiff_integrate(dev, rng, &desc, &estimator), RES_OK); + CHECK(sschiff_integrate(dev, rng, &distrib, wavelength, nscatt_angles, + ngeoms, ndirs, &estimator), RES_OK); time_current(&t1); time_sub(&t0, &t1, &t0); time_dump(&t0, TIME_MIN|TIME_SEC|TIME_MSEC, NULL, buf, sizeof(buf)); printf("%d - mean radius: %5.2fe-6 - %s: \n", (int)i, results[i].mean_radius, buf); CHECK(sschiff_estimator_get_extinction_cross_section(estimator, &status), RES_OK); - CHECK(status.nsteps, desc.sampled_geometries_count); + CHECK(status.nsteps, ngeoms); dst = status.E - results[i].extinction_cross_section; printf(" Extinction cross section = %7.2g ~ %12.7g +/- %12.7g (%6.2g)\n", results[i].extinction_cross_section, status.E, status.SE, dst / status.SE); @@ -310,7 +312,7 @@ main(int argc, char** argv) struct mem_allocator allocator; struct sampler_context sampler_ctx; struct sschiff_device* dev; - struct sschiff_integrator_desc desc = SSCHIFF_NULL_INTEGRATOR_DESC; + struct sschiff_geometry_distribution distrib = SSCHIFF_NULL_GEOMETRY_DISTRIBUTION; struct sschiff_estimator* estimator; struct sschiff_estimator_status status; struct ssp_rng* rng; @@ -354,29 +356,25 @@ main(int argc, char** argv) sampler_ctx.mean_radius = 1.0; sampler_ctx.sigma = 1.18; - desc.sample_geometry = sample_sphere; - desc.sampler_context = &sampler_ctx; - desc.wavelength = sampler_ctx.wavelength; - desc.scattering_angles_count = 1; - desc.sampled_geometries_count = 1; - desc.sampled_directions_count = 1; - - CHECK(sschiff_integrate(NULL, NULL, NULL, NULL), RES_BAD_ARG); - CHECK(sschiff_integrate(dev, NULL, NULL, NULL), RES_BAD_ARG); - CHECK(sschiff_integrate(NULL, rng, NULL, NULL), RES_BAD_ARG); - CHECK(sschiff_integrate(dev, rng, NULL, NULL), RES_BAD_ARG); - CHECK(sschiff_integrate(NULL, NULL, &desc, NULL), RES_BAD_ARG); - CHECK(sschiff_integrate(dev, NULL, &desc, NULL), RES_BAD_ARG); - CHECK(sschiff_integrate(NULL, rng, &desc, NULL), RES_BAD_ARG); - CHECK(sschiff_integrate(dev, rng, &desc, NULL), RES_BAD_ARG); - CHECK(sschiff_integrate(NULL, NULL, NULL, &estimator), RES_BAD_ARG); - CHECK(sschiff_integrate(dev, NULL, NULL, &estimator), RES_BAD_ARG); - CHECK(sschiff_integrate(NULL, rng, NULL, &estimator), RES_BAD_ARG); - CHECK(sschiff_integrate(dev, rng, NULL, &estimator), RES_BAD_ARG); - CHECK(sschiff_integrate(NULL, NULL, &desc, &estimator), RES_BAD_ARG); - CHECK(sschiff_integrate(dev, NULL, &desc, &estimator), RES_BAD_ARG); - CHECK(sschiff_integrate(NULL, rng, &desc, &estimator), RES_BAD_ARG); - CHECK(sschiff_integrate(dev, rng, &desc, &estimator), RES_OK); + distrib.sample = sample_sphere; + distrib.context = &sampler_ctx; + + CHECK(sschiff_integrate(NULL, NULL, NULL, 0.6e-6, 1, 1, 1, NULL), RES_BAD_ARG); + CHECK(sschiff_integrate(dev, NULL, NULL, 0.6e-6, 1, 1, 1, NULL), RES_BAD_ARG); + CHECK(sschiff_integrate(NULL, rng, NULL, 0.6e-6, 1, 1, 1, NULL), RES_BAD_ARG); + CHECK(sschiff_integrate(dev, rng, NULL, 0.6e-6, 1, 1, 1, NULL), RES_BAD_ARG); + CHECK(sschiff_integrate(NULL, NULL, &distrib, 0.6e-6, 1, 1, 1, NULL), RES_BAD_ARG); + CHECK(sschiff_integrate(dev, NULL, &distrib, 0.6e-6, 1, 1, 1, NULL), RES_BAD_ARG); + CHECK(sschiff_integrate(NULL, rng, &distrib, 0.6e-6, 1, 1, 1, NULL), RES_BAD_ARG); + CHECK(sschiff_integrate(dev, rng, &distrib, 0.6e-6, 1, 1, 1, NULL), RES_BAD_ARG); + CHECK(sschiff_integrate(NULL, NULL, NULL, 0.6e-6, 1, 1, 1, &estimator), RES_BAD_ARG); + CHECK(sschiff_integrate(dev, NULL, NULL, 0.6e-6, 1, 1, 1, &estimator), RES_BAD_ARG); + CHECK(sschiff_integrate(NULL, rng, NULL, 0.6e-6, 1, 1, 1, &estimator), RES_BAD_ARG); + CHECK(sschiff_integrate(dev, rng, NULL, 0.6e-6, 1, 1, 1, &estimator), RES_BAD_ARG); + CHECK(sschiff_integrate(NULL, NULL, &distrib, 0.6e-6, 1, 1, 1, &estimator), RES_BAD_ARG); + CHECK(sschiff_integrate(dev, NULL, &distrib, 0.6e-6, 1, 1, 1, &estimator), RES_BAD_ARG); + CHECK(sschiff_integrate(NULL, rng, &distrib, 0.6e-6, 1, 1, 1, &estimator), RES_BAD_ARG); + CHECK(sschiff_integrate(dev, rng, &distrib, 0.6e-6, 1, 1, 1, &estimator), RES_OK); CHECK(sschiff_estimator_get_extinction_cross_section(NULL, NULL), RES_BAD_ARG); CHECK(sschiff_estimator_get_extinction_cross_section(estimator, NULL), RES_BAD_ARG);