star-schiff

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

commit 47de63c3c9a62ef4b0c5a605154c811393d9cdd1
parent e22a1821b16b63a81a32d4b1c33b30d9da6eee71
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Thu, 15 Oct 2015 14:50:50 +0200

Fix the Schiff estimator whit several sampled directions

The Monte Carlo weight of the sampled directions were incorrectly
accumulated. Let N directions sampled for a given geometry, the
resulting MC weight is W = 1/N Sum_i^N(w).

Diffstat:
Msrc/sschiff_estimator.c | 26++++++++++++++++----------
Msrc/test_sschiff_estimator_sphere.c | 52++++++++++++++++++++++++++--------------------------
2 files changed, 42 insertions(+), 36 deletions(-)

diff --git a/src/sschiff_estimator.c b/src/sschiff_estimator.c @@ -52,6 +52,8 @@ struct accum { size_t naccums; }; +static const struct accum ACCUM_NULL = { 0, 0, 0 }; + struct sschiff_estimator { double wavelength; @@ -180,7 +182,7 @@ compute_monte_carlo_weight const float pos[3], /* World space centroid of the RT volume */ const float lower[3], /* Lower boundary of the RT volume */ const float upper[3], /* Upper boundary of the RT volume */ - struct accum* accum) + double* weight) { struct s3d_hit hit; double sample[2]; @@ -192,7 +194,7 @@ compute_monte_carlo_weight float x[3], y[3]; float rcp_pdf; res_T res = RES_OK; - ASSERT(scn && rng && mtl && basis && pos && lower && upper && accum); + ASSERT(scn && rng && mtl && basis && pos && lower && upper && weight); f2_sub(plane_size, upper, lower); rcp_pdf = plane_size[0] * plane_size[1] * 1.e-12f/*Metter^2 to micron^2*/; @@ -215,12 +217,12 @@ compute_monte_carlo_weight S3D(scene_trace_ray(scn, ray_org, axis_z, range, &hit)); + *weight = 0; if(!S3D_HIT_NONE(&hit)) { struct sschiff_material_properties props; double n_r, k_r; double n_e, k_e, lambda_e; double path_length; - double weight; res = compute_path_length(dev, scn, &hit, ray_org, axis_z, &path_length); if(res != RES_OK) goto error; @@ -234,13 +236,9 @@ compute_monte_carlo_weight lambda_e = wavelength / n_e; k_e = 2.0 * PI / lambda_e; - weight = 2.0 * rcp_pdf + *weight = 2.0 * rcp_pdf * (1.0 - exp(-k_e*k_r*path_length) * cos(k_e*(n_r - 1.0)*path_length)); - - accum->weight += weight; - accum->sqr_weight += weight * weight; } - accum->naccums += 1; exit: return res; @@ -332,6 +330,7 @@ radiative_properties struct sschiff_material* material, struct accum* accum) { + double weight_dirs = 0.0; float lower[3], upper[3]; float aabb_pt[8][3]; float centroid[3]; @@ -360,6 +359,7 @@ radiative_properties f3_mulf(centroid, f3_add(centroid, lower, upper), 0.5f); FOR_EACH(idir, 0, desc->sampled_directions_count) { + double weight; float dir[4]; float basis[9]; float transform[12]; @@ -386,7 +386,9 @@ radiative_properties } compute_monte_carlo_weight(dev, scene, rng, material, - desc->wavelength, basis, centroid, lower, upper, accum); + desc->wavelength, basis, centroid, lower, upper, &weight); + + weight_dirs += weight; #if 0 /* Compute an image of the shape transformed in the footprint space */ { @@ -397,6 +399,10 @@ radiative_properties } #endif } + weight_dirs /= (double)desc->sampled_directions_count; + accum->weight += weight_dirs; + accum->sqr_weight += weight_dirs * weight_dirs; + accum->naccums += 1; return RES_OK; } @@ -495,7 +501,7 @@ sschiff_integrate goto error; } - memset(&estimator->extinction_cross_section, 0, sizeof(struct accum)); + estimator->extinction_cross_section = ACCUM_NULL; FOR_EACH(i, 0, desc->sampled_geometries_count) { struct sschiff_material material = SSCHIFF_NULL_MATERIAL; diff --git a/src/test_sschiff_estimator_sphere.c b/src/test_sschiff_estimator_sphere.c @@ -41,13 +41,13 @@ struct result { double extinction_cross_section; }; -struct sphere { +struct geometry { float* vertices; /* List of float[3] */ unsigned* indices; /* List of unsigned[3] */ }; struct sampler_context { - struct sphere unit_sphere; + struct geometry geometry; double wavelength; double medium_refractive_index; double relative_real_refractive_index; @@ -55,8 +55,8 @@ struct sampler_context { double mean_radius; }; -struct sphere_context { - struct sphere* unit_sphere; +struct sphere { + struct geometry* geometry; float radius; }; @@ -82,27 +82,27 @@ get_material_property static void get_indices(const unsigned itri, unsigned ids[3], void* ctx) { - struct sphere_context* sphere = ctx; + struct sphere* sphere = ctx; const size_t i = itri * 3; - CHECK(sa_size(sphere->unit_sphere->indices) % 3, 0); - CHECK(itri < sa_size(sphere->unit_sphere->indices) / 3, 1); - ids[0] = sphere->unit_sphere->indices[i + 0]; - ids[1] = sphere->unit_sphere->indices[i + 1]; - ids[2] = sphere->unit_sphere->indices[i + 2]; + CHECK(sa_size(sphere->geometry->indices) % 3, 0); + CHECK(itri < sa_size(sphere->geometry->indices) / 3, 1); + ids[0] = sphere->geometry->indices[i + 0]; + ids[1] = sphere->geometry->indices[i + 1]; + ids[2] = sphere->geometry->indices[i + 2]; } static INLINE void get_position(const unsigned ivert, float vertex[3], void* ctx) { - struct sphere_context* sphere = ctx; + struct sphere* sphere = ctx; const size_t i = ivert * 3; - CHECK(sa_size(sphere->unit_sphere->vertices) % 3, 0); - CHECK(ivert < sa_size(sphere->unit_sphere->vertices) / 3, 1); - vertex[0] = sphere->unit_sphere->vertices[i + 0] * sphere->radius; - vertex[1] = sphere->unit_sphere->vertices[i + 1] * sphere->radius; - vertex[2] = sphere->unit_sphere->vertices[i + 2] * sphere->radius; + CHECK(sa_size(sphere->geometry->vertices) % 3, 0); + CHECK(ivert < sa_size(sphere->geometry->vertices) / 3, 1); + vertex[0] = sphere->geometry->vertices[i + 0] * sphere->radius; + vertex[1] = sphere->geometry->vertices[i + 1] * sphere->radius; + vertex[2] = sphere->geometry->vertices[i + 2] * sphere->radius; } static res_T @@ -114,14 +114,14 @@ sample_sphere { struct s3d_vertex_data attrib; struct sampler_context* sampler_ctx = sampler_context; - struct sphere_context sphere; + struct sphere sphere; size_t nverts, nprims; NCHECK(rng, NULL); NCHECK(mtl, NULL); NCHECK(shape, NULL); - sphere.unit_sphere = &sampler_ctx->unit_sphere; + sphere.geometry = &sampler_ctx->geometry; sphere.radius = (float)ssp_ran_lognormal (rng, log(sampler_ctx->mean_radius), log(1.18)); @@ -132,15 +132,15 @@ sample_sphere mtl->get_property = get_material_property; mtl->material = sampler_ctx; - nverts = sa_size(sphere.unit_sphere->vertices) / 3/*#coords*/; - nprims = sa_size(sphere.unit_sphere->indices) / 3/*#indices per prim*/; + nverts = sa_size(sphere.geometry->vertices) / 3/*#coords*/; + nprims = sa_size(sphere.geometry->indices) / 3/*#indices per prim*/; return s3d_mesh_setup_indexed_vertices(shape, (unsigned)nprims, get_indices, (unsigned)nverts, &attrib, 1, &sphere); } static void -unit_sphere_init(struct sphere* sphere, const unsigned ntheta) +sphere_init(struct geometry* sphere, const unsigned ntheta) { const unsigned nphi = (unsigned)(((double)ntheta + 0.5) / 2.0); const double step_theta = 2*PI / (double)ntheta; @@ -220,7 +220,7 @@ unit_sphere_init(struct sphere* sphere, const unsigned ntheta) } static void -unit_sphere_release(struct sphere* sphere) +sphere_release(struct geometry* sphere) { sa_release(sphere->vertices); sa_release(sphere->indices); @@ -250,8 +250,8 @@ check_schiff_estimation desc.sample_geometry = sample_sphere; desc.scattering_angles_count = 1; desc.sampler_context = sampler_ctx; - desc.sampled_geometries_count = 1000; - desc.sampled_directions_count = 1; + desc.sampled_geometries_count = 100; + desc.sampled_directions_count = 100; desc.wavelength = 6.e-7; printf("Schiff sphere estimation - m: %g; n_r: %g; kappa_r: %g; n_e: %g\n", @@ -327,7 +327,7 @@ main(int argc, char** argv) CHECK(ssp_rng_create(&allocator, &ssp_rng_threefry, &rng), RES_OK); CHECK(sschiff_device_create(NULL, &allocator, 0, NULL, &dev), RES_OK); - unit_sphere_init(&sampler_ctx.unit_sphere, 64); + sphere_init(&sampler_ctx.geometry, 64); sampler_ctx.wavelength = 0.6e-6; sampler_ctx.relative_real_refractive_index = 1.1; @@ -381,7 +381,7 @@ main(int argc, char** argv) CHECK(sschiff_device_ref_put(dev), RES_OK); CHECK(ssp_rng_ref_put(rng), RES_OK); - unit_sphere_release(&sampler_ctx.unit_sphere); + sphere_release(&sampler_ctx.geometry); check_memory_allocator(&allocator); mem_shutdown_proxy_allocator(&allocator); CHECK(mem_allocated_size(), 0);