commit 2a6b0445ced27282e89e8133299826c1ed47231f
parent ef5867b7e4d669bc6f198a23c13646b1f66a8eec
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Thu, 21 Sep 2017 15:00:42 +0200
Merge branch 'release_0.5'
Diffstat:
9 files changed, 112 insertions(+), 111 deletions(-)
diff --git a/README.md b/README.md
@@ -26,6 +26,13 @@ variable the install directories of its dependencies.
## Release notes
+### Version 0.5
+
+- Improve the performances up to 50% by optimising the allocation of the BSDF
+ during the radiative random walk. Performance gains are mainly observed in
+ situations where the radiative paths are deep, i.e. when they bounce on many
+ surfaces.
+
### Version 0.4.2
- Energy conservation property might not be ensured when the radiative paths
diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt
@@ -24,11 +24,11 @@ option(NO_TEST "Do not build tests" OFF)
# Check dependencies
################################################################################
find_package(RCMake 0.3 REQUIRED)
-find_package(RSys 0.4 REQUIRED)
+find_package(RSys 0.5 REQUIRED)
find_package(Star3D 0.4.1 REQUIRED)
find_package(Star3DUT 0.2 REQUIRED)
find_package(StarCPR 0.1 REQUIRED)
-find_package(StarSF 0.1 REQUIRED)
+find_package(StarSF 0.3 REQUIRED)
find_package(StarSP 0.4 REQUIRED)
find_package(OpenMP 1.2 REQUIRED)
@@ -50,8 +50,8 @@ rcmake_append_runtime_dirs(_runtime_dirs RSys Star3D Star3DUT StarCPR StarSF Sta
# Configure and define targets
################################################################################
set(VERSION_MAJOR 0)
-set(VERSION_MINOR 4)
-set(VERSION_PATCH 2)
+set(VERSION_MINOR 5)
+set(VERSION_PATCH 0)
set(VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH})
set(SSOL_FILES_SRC
@@ -157,7 +157,7 @@ if(NOT NO_TEST)
build_test(${_name})
register_test(${_name} ${_name})
endfunction()
-
+
new_test(test_ssol_atmosphere)
new_test(test_ssol_by_receiver_integration)
new_test(test_ssol_camera)
diff --git a/src/ssol_device.c b/src/ssol_device.c
@@ -49,6 +49,13 @@ device_release(ref_T* ref)
ASSERT(ref);
dev = CONTAINER_OF(ref, struct ssol_device, ref);
darray_tile_release(&dev->tiles);
+ if(dev->bsdf_allocators) {
+ unsigned i;
+ FOR_EACH(i, 0, dev->nthreads) {
+ mem_shutdown_lifo_allocator(&dev->bsdf_allocators[i]);
+ }
+ MEM_RM(dev->allocator, dev->bsdf_allocators);
+ }
if(dev->s3d) S3D(device_ref_put(dev->s3d));
if(dev->scpr_mesh) SCPR(mesh_ref_put(dev->scpr_mesh));
MEM_RM(dev->allocator, dev);
@@ -67,6 +74,7 @@ ssol_device_create
{
struct ssol_device* dev = NULL;
struct mem_allocator* allocator;
+ unsigned i;
res_T res = RES_OK;
if(nthreads_hint == 0 || !out_dev) {
@@ -88,12 +96,23 @@ ssol_device_create
dev->nthreads = MMIN(nthreads_hint, (unsigned)omp_get_num_procs());
omp_set_num_threads((int)dev->nthreads);
+ dev->bsdf_allocators = MEM_CALLOC
+ (dev->allocator, dev->nthreads, sizeof(struct mem_allocator));
+ if(!dev->bsdf_allocators) {
+ res = RES_MEM_ERR;
+ goto error;
+ }
+
+ FOR_EACH(i, 0, dev->nthreads) {
+ res = mem_init_lifo_allocator
+ (&dev->bsdf_allocators[i], dev->allocator, 4096);
+ if(res != RES_OK) goto error;
+ }
+
res = darray_tile_resize(&dev->tiles, dev->nthreads);
if(res != RES_OK) goto error;
-
res = s3d_device_create(logger, mem_allocator, 0, &dev->s3d);
if(res != RES_OK) goto error;
-
res = scpr_mesh_create(mem_allocator, &dev->scpr_mesh);
if(res != RES_OK) goto error;
diff --git a/src/ssol_device_c.h b/src/ssol_device_c.h
@@ -39,6 +39,7 @@ struct s3d_device;
struct ssol_device {
struct logger* logger;
struct mem_allocator* allocator;
+ struct mem_allocator* bsdf_allocators; /* Per thread allocator */
unsigned nthreads;
int verbose;
diff --git a/src/ssol_draw_pt.c b/src/ssol_draw_pt.c
@@ -38,7 +38,6 @@
******************************************************************************/
struct thread_context {
struct ssp_rng* rng;
- struct ssf_bsdf* bsdf;
struct ranst_sun_wl* ran_wl;
float up[3];
};
@@ -48,7 +47,6 @@ thread_context_release(struct thread_context* ctx)
{
ASSERT(ctx);
if(ctx->rng) SSP(rng_ref_put(ctx->rng));
- if(ctx->bsdf) SSF(bsdf_ref_put(ctx->bsdf));
if(ctx->ran_wl) ranst_sun_wl_ref_put(ctx->ran_wl);
}
@@ -57,16 +55,10 @@ thread_context_init
(struct mem_allocator* allocator,
struct thread_context* ctx)
{
- res_T res = RES_OK;
ASSERT(ctx);
+ (void)allocator;
memset(ctx, 0, sizeof(ctx[0]));
- res = ssf_bsdf_create(allocator, &ctx->bsdf);
- if(res != RES_OK) goto error;
-exit:
- return res;
-error:
- thread_context_release(ctx);
- goto exit;
+ return RES_OK;
}
static void
@@ -143,6 +135,7 @@ Li(struct ssol_scene* scn,
struct ray_data ray_data = RAY_DATA_NULL;
struct ssol_instance* inst;
struct ssol_material* mtl;
+ struct ssf_bsdf* bsdf = NULL;
const struct shaded_shape* sshape;
struct ssol_surface_fragment frag;
size_t isshape;
@@ -229,9 +222,8 @@ Li(struct ssol_scene* scn,
/* Shaded normal may look backward the outgoing direction */
if(d3_dot(N, wo) > 0) break;
- SSF(bsdf_clear(ctx->bsdf));
- res = material_setup_bsdf
- (mtl, &frag, wl, &medium, 1/*Rendering*/, ctx->bsdf);
+ if(bsdf) SSF(bsdf_ref_put(bsdf)), bsdf = NULL;
+ res = material_create_bsdf(mtl, &frag, wl, &medium, 1/*Rendering*/, &bsdf);
if(res != RES_OK) goto error;
/* Update the ray */
@@ -248,11 +240,11 @@ Li(struct ssol_scene* scn,
d3_minus(wo, wo);
if(scn->sun) {
L += throughput * sun_lighting
- (scn->sun, view, &ray_data, ctx->bsdf, wo, N, ray_org);
+ (scn->sun, view, &ray_data, bsdf, wo, N, ray_org);
}
/* Sampling a bounce direction */
- R = ssf_bsdf_sample(ctx->bsdf, ctx->rng, wo, N, wi, &type, &pdf);
+ R = ssf_bsdf_sample(bsdf, ctx->rng, wo, N, wi, &type, &pdf);
ASSERT(0 <= R && R <= 1);
/* Due to the shading normal, the sampled direction may point in the wrong
@@ -282,6 +274,7 @@ Li(struct ssol_scene* scn,
d3_splat(val, L);
exit:
+ if(bsdf) SSF(bsdf_ref_put(bsdf));
ssol_medium_clear(&medium);
return res;
error:
diff --git a/src/ssol_material.c b/src/ssol_material.c
@@ -32,6 +32,7 @@
#include <star/ssf.h>
#include <math.h>
+#include <omp.h>
/*******************************************************************************
* Helper functions
@@ -78,15 +79,15 @@ shade_normal_default
}
static res_T
-setup_dielectric_bsdf
+create_dielectric_bsdf
(const struct ssol_material* mtl,
const struct ssol_surface_fragment* fragment,
const double wavelength, /* In nanometer */
const struct ssol_medium* medium,
- struct ssf_bsdf* bsdf)
+ struct ssf_bsdf** bsdf)
{
- struct ssf_bxdf* bxdf = NULL;
double eta_i, eta_t;
+ const int ithread = omp_get_thread_num();
res_T res = RES_OK;
ASSERT(mtl && fragment && mtl->type == SSOL_MATERIAL_DIELECTRIC);
ASSERT(medium && bsdf);
@@ -101,33 +102,28 @@ setup_dielectric_bsdf
eta_i = ssol_data_get_value(&mtl->out_medium.refractive_index, wavelength);
eta_t = ssol_data_get_value(&mtl->in_medium.refractive_index, wavelength);
- res = ssf_bxdf_create
- (mtl->dev->allocator, &ssf_specular_dielectric_dielectric_interface, &bxdf);
- if(res != RES_OK) goto error;
-
- res = ssf_specular_dielectric_dielectric_interface_setup
- (bxdf, eta_i, eta_t);
- if(res != RES_OK) goto error;
-
- res = ssf_bsdf_add(bsdf, bxdf, 1.0);
- if(res != RES_OK) goto error;
+ #define CALL(Func) { res = Func; if(res != RES_OK) goto error; } (void)0
+ CALL(ssf_bsdf_create(&mtl->dev->bsdf_allocators[ithread],
+ &ssf_specular_dielectric_dielectric_interface, bsdf));
+ CALL(ssf_specular_dielectric_dielectric_interface_setup(*bsdf, eta_i, eta_t));
+ #undef CALL
exit:
- if(bxdf) SSF(bxdf_ref_put(bxdf));
return res;
error:
+ if(*bsdf) SSF(bsdf_ref_put(*bsdf)), bsdf = NULL;
goto exit;
}
static res_T
-setup_matte_bsdf
+create_matte_bsdf
(const struct ssol_material* mtl,
const struct ssol_surface_fragment* fragment,
const double wavelength, /* In nanometer */
- struct ssf_bsdf* bsdf)
+ struct ssf_bsdf** bsdf)
{
- struct ssf_bxdf* brdf = NULL;
double reflectivity;
+ const int ithread = omp_get_thread_num();
res_T res;
ASSERT(mtl && fragment && mtl->type == SSOL_MATERIAL_MATTE);
ASSERT(bsdf);
@@ -137,35 +133,32 @@ setup_matte_bsdf
(mtl->dev, mtl->buf, wavelength, fragment, &reflectivity);
/* Setup the BRDF */
- res = ssf_bxdf_create(mtl->dev->allocator, &ssf_lambertian_reflection, &brdf);
+ res = ssf_bsdf_create
+ (&mtl->dev->bsdf_allocators[ithread], &ssf_lambertian_reflection, bsdf);
if(res != RES_OK) goto error;
- res = ssf_lambertian_reflection_setup(brdf, reflectivity);
- if(res != RES_OK) goto error;
-
- /* Setup the BSDF */
- res = ssf_bsdf_add(bsdf, brdf, 1.0);
+ res = ssf_lambertian_reflection_setup(*bsdf, reflectivity);
if(res != RES_OK) goto error;
exit:
- if(brdf) SSF(bxdf_ref_put(brdf));
return res;
error:
+ if(*bsdf) SSF(bsdf_ref_put(*bsdf)), bsdf = NULL;
goto exit;
}
static res_T
-setup_mirror_bsdf
+create_mirror_bsdf
(const struct ssol_material* mtl,
const struct ssol_surface_fragment* fragment,
const double wavelength, /* In nanometer */
const int rendering,
- struct ssf_bsdf* bsdf)
+ struct ssf_bsdf** bsdf)
{
- struct ssf_bxdf* brdf = NULL;
struct ssf_fresnel* fresnel = NULL;
struct ssf_microfacet_distribution* distrib = NULL;
double roughness;
double reflectivity;
+ const int ithread = omp_get_thread_num();
res_T res;
ASSERT(mtl && fragment && mtl->type == SSOL_MATERIAL_MIRROR);
ASSERT(bsdf);
@@ -184,9 +177,10 @@ setup_mirror_bsdf
/* Setup the BRDF */
if(roughness == 0) { /* Purely specular reflection */
- res = ssf_bxdf_create(mtl->dev->allocator, &ssf_specular_reflection, &brdf);
+ res = ssf_bsdf_create
+ (&mtl->dev->bsdf_allocators[ithread], &ssf_specular_reflection, bsdf);
if(res != RES_OK) goto error;
- res = ssf_specular_reflection_setup(brdf, fresnel);
+ res = ssf_specular_reflection_setup(*bsdf, fresnel);
if(res != RES_OK) goto error;
} else { /* Glossy reflection */
res = ssf_microfacet_distribution_create
@@ -199,42 +193,38 @@ setup_mirror_bsdf
* evaluated and consequently it returns an invalid result for direct
* lighting. */
if(rendering) {
- res = ssf_bxdf_create
- (mtl->dev->allocator, &ssf_microfacet_reflection, &brdf);
+ res = ssf_bsdf_create
+ (&mtl->dev->bsdf_allocators[ithread], &ssf_microfacet_reflection, bsdf);
} else {
- res = ssf_bxdf_create
- (mtl->dev->allocator, &ssf_microfacet2_reflection, &brdf);
+ res = ssf_bsdf_create
+ (&mtl->dev->bsdf_allocators[ithread], &ssf_microfacet2_reflection, bsdf);
}
if(res != RES_OK) goto error;
- res = ssf_microfacet_reflection_setup(brdf, fresnel, distrib);
+ res = ssf_microfacet_reflection_setup(*bsdf, fresnel, distrib);
if(res != RES_OK) goto error;
}
- /* Setup the BSDF */
- res = ssf_bsdf_add(bsdf, brdf, 1.0);
- if(res != RES_OK) goto error;
-
exit:
- if(brdf) SSF(bxdf_ref_put(brdf));
if(fresnel) SSF(fresnel_ref_put(fresnel));
if(distrib) SSF(microfacet_distribution_ref_put(distrib));
return res;
error:
+ if(*bsdf) SSF(bsdf_ref_put(*bsdf)), bsdf = NULL;
goto exit;
}
static res_T
-setup_thin_dielectric_bsdf
+create_thin_dielectric_bsdf
(const struct ssol_material* mtl,
const struct ssol_surface_fragment* fragment,
const double wavelength, /* In nanometer */
- struct ssf_bsdf* bsdf)
+ struct ssf_bsdf** bsdf)
{
- struct ssf_bxdf* bxdf = NULL;
double thickness;
double absorption;
double eta_i;
double eta_t;
+ const int ithread = omp_get_thread_num();
res_T res = RES_OK;
ASSERT(mtl && fragment && mtl->type == SSOL_MATERIAL_THIN_DIELECTRIC);
ASSERT(bsdf);
@@ -248,21 +238,17 @@ setup_thin_dielectric_bsdf
thickness = mtl->data.thin_dielectric.thickness;
/* Setup the BxDF */
- res = ssf_bxdf_create
- (mtl->dev->allocator, &ssf_thin_specular_dielectric, &bxdf);
+ res = ssf_bsdf_create
+ (&mtl->dev->bsdf_allocators[ithread], &ssf_thin_specular_dielectric, bsdf);
if(res != RES_OK) goto error;
res = ssf_thin_specular_dielectric_setup
- (bxdf, absorption, eta_i, eta_t, thickness);
- if(res != RES_OK) goto error;
-
- /* Setup the BSDF */
- res = ssf_bsdf_add(bsdf, bxdf, 1.0);
+ (*bsdf, absorption, eta_i, eta_t, thickness);
if(res != RES_OK) goto error;
exit:
- if(bxdf) SSF(bxdf_ref_put(bxdf));
return res;
error:
+ if(*bsdf) SSF(bsdf_ref_put(*bsdf)), bsdf = NULL;
goto exit;
}
@@ -661,30 +647,30 @@ material_shade_normal
}
res_T
-material_setup_bsdf
+material_create_bsdf
(const struct ssol_material* mtl,
const struct ssol_surface_fragment* fragment,
const double wavelength, /* In nanometer */
const struct ssol_medium* medium,
const int rendering, /* Is BSDF used for rendering */
- struct ssf_bsdf* bsdf)
+ struct ssf_bsdf** bsdf)
{
res_T res = RES_OK;
ASSERT(mtl);
switch(mtl->type) {
case SSOL_MATERIAL_DIELECTRIC:
- res = setup_dielectric_bsdf
+ res = create_dielectric_bsdf
(mtl, fragment, wavelength, medium, bsdf);
break;
case SSOL_MATERIAL_MATTE:
- res = setup_matte_bsdf(mtl, fragment, wavelength, bsdf);
+ res = create_matte_bsdf(mtl, fragment, wavelength, bsdf);
break;
case SSOL_MATERIAL_MIRROR:
- res = setup_mirror_bsdf(mtl, fragment, wavelength, rendering, bsdf);
+ res = create_mirror_bsdf(mtl, fragment, wavelength, rendering, bsdf);
break;
case SSOL_MATERIAL_THIN_DIELECTRIC:
- res = setup_thin_dielectric_bsdf(mtl, fragment, wavelength, bsdf);
+ res = create_thin_dielectric_bsdf(mtl, fragment, wavelength, bsdf);
break;
case SSOL_MATERIAL_VIRTUAL: /* Nothing to shade */ break;
default: FATAL("Unreachable code\n"); break;
diff --git a/src/ssol_material_c.h b/src/ssol_material_c.h
@@ -78,13 +78,13 @@ material_shade_normal
double N[3]);
extern LOCAL_SYM res_T
-material_setup_bsdf
+material_create_bsdf
(const struct ssol_material* mtl,
const struct ssol_surface_fragment* fragment,
const double wavelength, /* In nanometer */
const struct ssol_medium* medium, /* Current medium */
const int rendering, /* Is material used for rendering purposes */
- struct ssf_bsdf* bsdf); /* Bidirectional Scattering Distribution Function */
+ struct ssf_bsdf** bsdf); /* Bidirectional Scattering Distribution Function */
extern LOCAL_SYM res_T
material_get_next_medium
diff --git a/src/ssol_solver.c b/src/ssol_solver.c
@@ -51,7 +51,6 @@
******************************************************************************/
struct thread_context {
struct ssp_rng* rng;
- struct ssf_bsdf* bsdf;
struct mc_data cos_factor;
struct mc_data absorbed_by_receivers;
struct mc_data shadowed;
@@ -69,7 +68,6 @@ thread_context_release(struct thread_context* ctx)
{
ASSERT(ctx);
if(ctx->rng) SSP(rng_ref_put(ctx->rng));
- if(ctx->bsdf) SSF(bsdf_ref_put(ctx->bsdf));
htable_receiver_release(&ctx->mc_rcvs);
htable_sampled_release(&ctx->mc_samps);
darray_path_release(&ctx->paths);
@@ -78,22 +76,12 @@ thread_context_release(struct thread_context* ctx)
static res_T
thread_context_init(struct mem_allocator* allocator, struct thread_context* ctx)
{
- res_T res = RES_OK;
ASSERT(ctx);
-
memset(ctx, 0, sizeof(ctx[0]));
htable_receiver_init(allocator, &ctx->mc_rcvs);
htable_sampled_init(allocator, &ctx->mc_samps);
darray_path_init(allocator, &ctx->paths);
-
- res = ssf_bsdf_create(allocator, &ctx->bsdf);
- if(res != RES_OK) goto error;
-
-exit:
- return res;
-error:
- thread_context_release(ctx);
- goto exit;
+ return RES_OK;
}
/* Define a copy functor only for consistency since this function will not be
@@ -105,7 +93,6 @@ thread_context_copy
res_T res = RES_OK;
ASSERT(dst && src);
dst->rng = src->rng;
- dst->bsdf = src->bsdf;
dst->cos_factor = src->cos_factor;
dst->absorbed_by_receivers = src->absorbed_by_receivers;
dst->shadowed = src->shadowed;
@@ -272,6 +259,9 @@ point_init
/* Sample a sun direction */
ranst_sun_dir_get(ran_sun_dir, rng, pt->dir);
+
+ /* Sample a wavelength */
+ pt->wl = ranst_sun_wl_get(ran_sun_wl, rng);
if(pt->sshape->shape->type != SHAPE_PUNCHED) {
d3_set(N, pt->N);
@@ -356,9 +346,6 @@ point_init
f3_set_d3(pos, pt->pos);
S3D(scene_view_trace_ray(view_rt, pos, dir, range, &ray_data, &hit));
*is_lit = S3D_HIT_NONE(&hit);
- if(*is_lit) {
- pt->wl = ranst_sun_wl_get(ran_sun_wl, rng); /* Sample a wavelength */
- }
exit:
return res;
@@ -428,7 +415,6 @@ point_is_receiver(const struct point* pt)
static FINLINE res_T
point_shade
(struct point* pt,
- struct ssf_bsdf* bsdf,
const struct ssol_medium* in_medium,
struct ssol_medium* out_medium,
struct ssp_rng* rng,
@@ -436,11 +422,12 @@ point_shade
{
struct ssol_material* mtl;
struct ssol_surface_fragment frag;
+ struct ssf_bsdf* bsdf = NULL;
double propagated = 0;
double wi[3], N[3], pdf;
int type = 0;
res_T res;
- ASSERT(pt && bsdf && in_medium && out_medium && rng && dir);
+ ASSERT(pt && in_medium && out_medium && rng && dir);
/* TODO ensure that if `prim' was sampled, then the surface fragment setup
* remains valid in *all* situations, i.e. even though the point primitive
@@ -457,9 +444,9 @@ point_shade
/* Shade the surface fragment */
mtl = point_get_material(pt);
- SSF(bsdf_clear(bsdf));
- res = material_setup_bsdf(mtl, &frag, pt->wl, in_medium, 0, bsdf);
- if(res != RES_OK) return res;
+
+ res = material_create_bsdf(mtl, &frag, pt->wl, in_medium, 0, &bsdf);
+ if(res != RES_OK) goto error;
/* Perturbe the normal */
material_shade_normal(mtl, &frag, pt->wl, N);
@@ -494,7 +481,12 @@ point_shade
} else {
ssol_medium_copy(out_medium, in_medium);
}
- return RES_OK;
+
+exit:
+ if(bsdf) SSF(bsdf_ref_put(bsdf));
+ return res;
+error:
+ goto exit;
}
static FINLINE void
@@ -930,8 +922,7 @@ trace_radiative_path
} else {
/* Modulate the point weights wrt its scattering functions and generate
* an outgoing direction and set out_medium accordingly */
- res = point_shade(&pt, thread_ctx->bsdf, &in_medium, &out_medium,
- thread_ctx->rng, pt.dir);
+ res = point_shade(&pt, &in_medium, &out_medium, thread_ctx->rng, pt.dir);
if(res != RES_OK) goto error;
}
@@ -1033,10 +1024,10 @@ trace_radiative_path
double p = ssp_rng_canonical(thread_ctx->rng);
if(p > 0.5) {
pt.survivor_score += 1; /* This path survived once more */
+ roulette_interval = typical_max_depth;
} else {
cancel_mc(thread_ctx, irealisation);
killed_by_roulette = 1;
- roulette_interval = typical_max_depth;
goto exit; /* break is not enough */
}
}
@@ -1068,7 +1059,7 @@ trace_radiative_path
/* Check conservation of energy at the realisation level */
ASSERT((double)depth*DBL_EPSILON*pt.initial_flux >= fabs(pt.energy_loss));
- /* this realisation count account for many that where canceled */
+ /* this realisation accounts for many that where canceled */
if(pt.survivor_score) {
const double factor = (double)(1 << pt.survivor_score);
apply_factor_mc(thread_ctx, irealisation, factor);
diff --git a/src/test_ssol_by_receiver_integration.c b/src/test_ssol_by_receiver_integration.c
@@ -139,22 +139,26 @@ main(int argc, char** argv)
printf("Ir(target) = %g +/- %g\n",
mc_rcv.incoming_flux.E, mc_rcv.incoming_flux.SE);
CHECK(ssol_instance_set_receiver(heliostat, SSOL_FRONT, 0), RES_OK);
- CHECK(eq_eps(mc_rcv.incoming_flux.E, S_DNI_cos, S_DNI_cos * 2e-1), 1);
+ CHECK(eq_eps
+ (mc_rcv.incoming_flux.E, S_DNI_cos,
+ mc_rcv.incoming_flux.SE*3), 1);
CHECK(ssol_solve(scene, rng, 8 * N__, NULL, &estimator2), RES_OK);
CHECK(GET_MC_RCV(estimator2, target, SSOL_FRONT, &mc_rcv), RES_OK);
printf("Ir(target) = %g +/- %g\n",
mc_rcv.incoming_flux.E, mc_rcv.incoming_flux.SE);
- CHECK(eq_eps(mc_rcv.incoming_flux.E, S_DNI_cos, S_DNI_cos * 5e-2), 1);
+ CHECK(eq_eps(mc_rcv.incoming_flux.E, S_DNI_cos, mc_rcv.incoming_flux.SE*3), 1);
CHECK(ssol_estimator_ref_put(estimator1), RES_OK);
CHECK(ssol_solve(scene, rng, 3 * N__, NULL, &estimator1), RES_OK);
CHECK(GET_MC_RCV(estimator1, target, SSOL_FRONT, &mc_rcv), RES_OK);
printf("Ir(target) = %g +/- %g\n",
mc_rcv.incoming_flux.E, mc_rcv.incoming_flux.SE);
- CHECK(eq_eps(mc_rcv.incoming_flux.E, S_DNI_cos, S_DNI_cos * 1e-1), 1);
+ CHECK(eq_eps
+ (mc_rcv.incoming_flux.E, S_DNI_cos,
+ mc_rcv.incoming_flux.SE*3), 1);
CHECK(GET_MC_SAMP_X_RCV(estimator1, heliostat, target, SSOL_FRONT, &mc_rcv), RES_OK);
printf("Ir(heliostat=>target) = %g +/- %g\n",
mc_rcv.incoming_flux.E, mc_rcv.incoming_flux.SE);
- CHECK(eq_eps(mc_rcv.incoming_flux.E, S_DNI_cos, S_DNI_cos * 1e-1), 1);
+ CHECK(eq_eps(mc_rcv.incoming_flux.E, S_DNI_cos, mc_rcv.incoming_flux.SE*3), 1);
/* Free data */
CHECK(ssol_instance_ref_put(heliostat), RES_OK);