commit ee44c5cd546e95227cc9d66afd9f19379295d355
parent a17d23562d7c3d7af70c9fdb63e4cb5b1a4b7371
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date: Fri, 7 Oct 2016 14:45:10 +0200
Change output from acii to binary
Don't output realisations' information anymore (to be used for implicitly
computed MC indicators).
Due to precision concerns, some tests' tolerance have been changed.
Diffstat:
14 files changed, 142 insertions(+), 76 deletions(-)
diff --git a/src/ssol.h b/src/ssol.h
@@ -194,6 +194,21 @@ struct ssol_mirror_shader {
static const struct ssol_mirror_shader SSOL_MIRROR_SHADER_NULL =
SSOL_MIRROR_SHADER_NULL__;
+/* The type of data produced on receiver hits
+ as ssol_solve() write them on its FILE* argument */
+struct receiver_data {
+ uint64_t realization_id;
+ int64_t date;
+ uint32_t segment_id;
+ uint32_t receiver_id;
+ float wavelength;
+ float pos[3];
+ float in_dir[3];
+ float normal[3];
+ float weight;
+ float uv[2];
+};
+
/*
* All the ssol structures are ref counted. Once created with the appropriated
* `ssol_<TYPE>_create' function, the caller implicitly owns the created data,
diff --git a/src/ssol_c.h b/src/ssol_c.h
@@ -56,5 +56,10 @@ hit_filter_function
#define NON_BOOL 99
+/* hack until the needed API comes from a merge */
+#define FRONT_FLAG 0
+#define RECEIVER_ID_MASK 0x7FFFFFFF
+#define BACK_FLAG 0x80000000
+
#endif /* SSOL_C_H */
diff --git a/src/ssol_scene.c b/src/ssol_scene.c
@@ -28,6 +28,8 @@
#include <rsys/list.h>
#include <rsys/mem_allocator.h>
#include <rsys/rsys.h>
+#include <rsys/float2.h>
+#include <rsys/float3.h>
#include <rsys/double33.h>
/*******************************************************************************
@@ -340,6 +342,7 @@ hit_filter_function
struct ssol_instance* inst;
const struct ssol_shape* shape;
const struct str* receiver_name;
+ uint32_t receiver_id;
struct realisation* rs = realisation;
struct segment* seg;
@@ -405,24 +408,28 @@ hit_filter_function
if(seg->hit_front) {
seg->hit_material = inst->object->mtl_front;
receiver_name = &inst->receiver_front;
+ receiver_id = FRONT_FLAG;
} else {
d3_muld(seg->hit_normal, seg->hit_normal, -1);
seg->hit_material = inst->object->mtl_back;
receiver_name = &inst->receiver_back;
+ receiver_id = BACK_FLAG;
}
/* Check if the hit surface is a receiver that registers hit data */
/* impacts on receivers before sampled surfaces are not registered */
if (!seg->sun_segment && !str_is_empty(receiver_name)) {
struct receiver_record candidate;
- d3_set(candidate.dir, seg->dir);
- candidate.hit_distance = seg->hit_distance;
- d3_set(candidate.hit_normal, seg->hit_normal);
- d3_set(candidate.hit_pos, seg->hit_pos);
+ uint32_t id;
+ f3_set_d3(candidate.dir, seg->dir);
+ candidate.hit_distance = (float)seg->hit_distance;
+ f3_set_d3(candidate.hit_normal, seg->hit_normal);
+ f3_set_d3(candidate.hit_pos, seg->hit_pos);
candidate.instance = inst;
- candidate.receiver_name = str_cget(receiver_name);
- candidate.uv[0] = seg->hit.uv[0];
- candidate.uv[1] = seg->hit.uv[1];
+ S3D(shape_get_id(inst->shape_rt, &id));
+ ASSERT((id & RECEIVER_ID_MASK) == id);
+ candidate.receiver_id = receiver_id | id;
+ f2_set(candidate.uv, seg->hit.uv);
darray_receiver_record_push_back(
&rs->data.receiver_record_candidates, &candidate);
}
diff --git a/src/ssol_solver.c b/src/ssol_solver.c
@@ -28,6 +28,7 @@
#include "ssol_ranst_sun_dir.h"
#include "ssol_ranst_sun_wl.h"
+#include <rsys/float2.h>
#include <rsys/float3.h>
#include <rsys/double3.h>
#include <rsys/double44.h>
@@ -553,6 +554,7 @@ receive_sunlight(struct realisation* rs)
const struct str* receiver_name = NULL;
const struct ssol_sun* sun;
struct starting_point* start;
+ uint32_t receiver_id;
ASSERT(rs && rs->s_idx == 0);
seg = current_segment(rs);
@@ -630,20 +632,24 @@ receive_sunlight(struct realisation* rs)
/* if the sampled instance is a receiver, register the sampled point */
if(start->front_exposed) {
receiver_name = &start->instance->receiver_front;
+ receiver_id = FRONT_FLAG;
} else {
receiver_name = &start->instance->receiver_back;
+ receiver_id = BACK_FLAG;
}
/* if the sampled instance holds a receiver, push a candidate */
if(!str_is_empty(receiver_name)) {
+ uint32_t id;
struct receiver_record candidate;
- d3_set(candidate.dir, seg->dir);
+ f3_set_d3(candidate.dir, seg->dir);
candidate.hit_distance = 0; /* no atmospheric attenuation for sun rays */
- d3_set(candidate.hit_normal, seg->hit_normal);
- d3_set(candidate.hit_pos, seg->hit_pos);
+ f3_set_d3(candidate.hit_normal, seg->hit_normal);
+ f3_set_d3(candidate.hit_pos, seg->hit_pos);
candidate.instance = start->instance;
- candidate.receiver_name = str_cget(receiver_name);
- candidate.uv[0] = start->uv[0];
- candidate.uv[1] = start->uv[1];
+ S3D(shape_get_id(start->instance->shape_rt, &id));
+ ASSERT((id & RECEIVER_ID_MASK) == id);
+ candidate.receiver_id = receiver_id | id;
+ f2_set(candidate.uv, start->uv);
darray_receiver_record_push_back(
&rs->data.receiver_record_candidates, &candidate);
}
@@ -690,6 +696,8 @@ filter_receiver_hit_candidates(struct realisation* rs)
candidates->hit_distance <= tmax && candidates < candidates_end;
candidates++)
{
+ struct receiver_data out;
+ float weight;
if (candidates->hit_distance == prev_distance) {
size_t i = 0, is_duplicate = 0;
struct ssol_instance** ptr = darray_instances_ptr_data_get(inst_array);
@@ -709,20 +717,21 @@ filter_receiver_hit_candidates(struct realisation* rs)
darray_instances_ptr_clear(inst_array);
darray_instances_ptr_push_back(inst_array, &candidates->instance);
}
- /* output valid receiver hits */
- fprintf(rs->data.out_stream,
- "Receiver '%s': %u %u %g %g (%g:%g:%g) (%g:%g:%g) (%g:%g:%g) (%g:%g)\n",
- candidates->receiver_name,
- (unsigned) rs->rs_id,
- (unsigned) rs->s_idx,
- rs->wavelength,
- /* take amosphere into account with the correct distance */
- seg->weight * compute_atmosphere_attenuation(
- rs->data.scene->atmosphere, candidates->hit_distance, rs->wavelength),
- SPLIT3(candidates->hit_pos),
- SPLIT3(candidates->dir),
- SPLIT3(candidates->hit_normal),
- SPLIT2(candidates->uv));
+
+ /* take amosphere into account with distance to receiver */
+ weight = (float) (seg->weight * compute_atmosphere_attenuation(
+ rs->data.scene->atmosphere, candidates->hit_distance, rs->wavelength));
+ out.realization_id = rs->rs_id;
+ out.date = 0; /* TODO */
+ out.segment_id = rs->s_idx;
+ out.receiver_id = candidates->receiver_id;
+ out.wavelength = (float)rs->wavelength;
+ f3_set(out.pos, candidates->hit_pos);
+ f3_set(out.in_dir, candidates->dir);
+ f3_set(out.normal, candidates->hit_normal);
+ out.weight = weight;
+ f2_set(out.uv, candidates->uv);
+ fwrite(&out, sizeof(struct receiver_data), 1, rs->data.out_stream);
}
/* reset candidates */
darray_receiver_record_clear(&rs->data.receiver_record_candidates);
@@ -797,10 +806,13 @@ ssol_solve
} while (rs.end == TERM_NONE);
}
/* propagation ended */
+#if 0
+ /* TODO: use this to feed the implicit MC computations */
fprintf(output, "Realisation %u success mask: 0x%0x\n",
(unsigned) r, rs.success_mask);
fprintf(output, "Realisation %u end: %s\n\n",
(unsigned) r, END_TEXT[rs.end]);
+#endif // 0
/* must retry failed realisations */
if (rs.end == TERM_ERR) {
diff --git a/src/ssol_solver_c.h b/src/ssol_solver_c.h
@@ -95,12 +95,12 @@ struct starting_point {
struct receiver_record {
struct ssol_instance* instance;
- const char* receiver_name;
- double dir[4];
- double hit_pos[3];
+ uint32_t receiver_id;
+ float dir[4];
+ float hit_pos[3];
float uv[2];
- double hit_normal[3]; /* face the incoming dir */
- double hit_distance;
+ float hit_normal[3]; /* face the incoming dir */
+ float hit_distance;
};
#define DARRAY_DATA struct segment
@@ -138,8 +138,8 @@ struct realisation {
struct starting_point start;
struct solver_data data;
double wavelength;
- size_t s_idx;
size_t rs_id;
+ uint32_t s_idx;
uint32_t success_mask;
};
diff --git a/src/test_ssol_solver1.c b/src/test_ssol_solver1.c
@@ -67,6 +67,7 @@ main(int argc, char** argv)
double dbl;
FILE* tmp = NULL;
double m, std;
+ uint32_t r_id;
(void) argc, (void) argv;
@@ -192,7 +193,8 @@ main(int argc, char** argv)
CHECK(!tmp, 0);
#define N 5000
CHECK(ssol_solve(scene, rng, N, tmp), RES_OK);
- CHECK(pp_sum(tmp, "cible", N, &m, &std), RES_OK);
+ CHECK(get_receiver_id(target, 1, &r_id), RES_OK);
+ CHECK(pp_sum(tmp, r_id, N, &m, &std), RES_OK);
logger_print(&logger, LOG_OUTPUT, "\nP = %g +/- %g\n", m, std);
#define DNI_cos (1000 * cos(PI / 4))
CHECK(eq_eps(m, 4 * DNI_cos, MMAX(4 * DNI_cos * 1e-2, std)), 1);
@@ -210,7 +212,7 @@ main(int argc, char** argv)
tmp = tmpfile();
CHECK(ssol_solve(scene, rng, N, tmp), RES_OK);
- CHECK(pp_sum(tmp, "cible", N, &m, &std), RES_OK);
+ CHECK(pp_sum(tmp, r_id, N, &m, &std), RES_OK);
logger_print(&logger, LOG_OUTPUT, "\nP = %g +/- %g\n", m, std);
CHECK(eq_eps(m, 4 * DNI_cos, MMAX(4 * DNI_cos * 1e-2, std)), 1);
CHECK(eq_eps(std, 0, 1e-4), 1);
@@ -225,7 +227,7 @@ main(int argc, char** argv)
NCHECK(tmp = tmpfile(), 0);
CHECK(ssol_solve(scene, rng, N, tmp), RES_OK);
- CHECK(pp_sum(tmp, "cible", N, &m, &std), RES_OK);
+ CHECK(pp_sum(tmp, r_id, N, &m, &std), RES_OK);
logger_print(&logger, LOG_OUTPUT, "\nP = %g +/- %g\n", m, std);
CHECK(fclose(tmp), 0);
CHECK(eq_eps(m, 4 * DNI_cos, MMAX(4 * DNI_cos * 1e-2, std)), 1);
@@ -244,7 +246,7 @@ main(int argc, char** argv)
NCHECK(tmp = tmpfile(), 0);
CHECK(ssol_solve(scene, rng, N, tmp), RES_OK);
- CHECK(pp_sum(tmp, "cible", N, &m, &std), RES_OK);
+ CHECK(pp_sum(tmp, r_id, N, &m, &std), RES_OK);
logger_print(&logger, LOG_OUTPUT, "\nP = %g +/- %g\n", m, std);
CHECK(fclose(tmp), 0);
#define K (exp(-0.1 * 4 * sqrt(2)))
@@ -263,7 +265,7 @@ main(int argc, char** argv)
CHECK(ssol_spectrum_setup(abs, wavelengths, ka, 2), RES_OK);
NCHECK(tmp = tmpfile(), 0);
CHECK(ssol_solve(scene, rng, N, tmp), RES_OK);
- CHECK(pp_sum(tmp, "cible", N, &m, &std), RES_OK);
+ CHECK(pp_sum(tmp, r_id, N, &m, &std), RES_OK);
logger_print(&logger, LOG_OUTPUT, "\nP = %g +/- %g\n", m, std);
CHECK(fclose(tmp), 0);
#define K2 (exp(-0.121 * 4 * sqrt(2)))
diff --git a/src/test_ssol_solver2.c b/src/test_ssol_solver2.c
@@ -78,6 +78,7 @@ main(int argc, char** argv)
double transform3[12]; /* 3x4 column major matrix */
FILE* tmp;
double m, std;
+ uint32_t r_id;
(void) argc, (void) argv;
@@ -178,7 +179,8 @@ main(int argc, char** argv)
tmp = tmpfile();
#define N 10000
CHECK(ssol_solve(scene, rng, N, tmp), RES_OK);
- CHECK(pp_sum(tmp, "cible", N, &m, &std), RES_OK);
+ CHECK(get_receiver_id(target, 1, &r_id), RES_OK);
+ CHECK(pp_sum(tmp, r_id, N, &m, &std), RES_OK);
logger_print(&logger, LOG_OUTPUT, "\nP = %g +/- %g\n", m, std);
#define DNI_cos (1000 * cos(PI / 4))
CHECK(eq_eps(m, 4 * DNI_cos, 4 * DNI_cos * 1e-4), 1);
diff --git a/src/test_ssol_solver2b.c b/src/test_ssol_solver2b.c
@@ -78,6 +78,7 @@ main(int argc, char** argv)
double transform3[12]; /* 3x4 column major matrix */
FILE* tmp;
double m, std;
+ uint32_t r_id;
(void) argc, (void) argv;
@@ -183,7 +184,8 @@ main(int argc, char** argv)
tmp = tmpfile();
#define N 50000
CHECK(ssol_solve(scene, rng, N, tmp), RES_OK);
- CHECK(pp_sum(tmp, "cible", N, &m, &std), RES_OK);
+ CHECK(get_receiver_id(target, 1, &r_id), RES_OK);
+ CHECK(pp_sum(tmp, r_id, N, &m, &std), RES_OK);
logger_print(&logger, LOG_OUTPUT, "\nP = %g +/- %g\n", m, std);
#define DNI_cos (1000 * cos(PI / 4))
CHECK(eq_eps(m, 2 * DNI_cos, MMAX(2 * DNI_cos * 1e-2, std)), 1);
diff --git a/src/test_ssol_solver3.c b/src/test_ssol_solver3.c
@@ -67,10 +67,10 @@ main(int argc, char** argv)
double transform[12]; /* 3x4 column major matrix */
FILE* tmp;
double m, std;
+ uint32_t r_id;
(void) argc, (void) argv;
- d33_splat(transform, 0);
d3_splat(transform + 9, 0);
d33_rotation_pitch(transform, PI); /* flip faces: invert normal */
transform[11] = 2; /* +2 offset along Z axis */
@@ -133,13 +133,12 @@ main(int argc, char** argv)
CHECK(ssol_instance_set_target_mask(target, 0x1, 0), RES_OK);
CHECK(ssol_instance_dont_sample(target, 1), RES_OK);
CHECK(ssol_scene_attach_instance(scene, target), RES_OK);
-
- CHECK(ssol_solve(scene, rng, 20, stdout), RES_OK);
-
+
tmp = tmpfile();
-#define N 10000
+#define N 20000
CHECK(ssol_solve(scene, rng, N, tmp), RES_OK);
- CHECK(pp_sum(tmp, "cible", N, &m, &std), RES_OK);
+ CHECK(get_receiver_id(target, 1, &r_id), RES_OK);
+ CHECK(pp_sum(tmp, r_id, N, &m, &std), RES_OK);
logger_print(&logger, LOG_OUTPUT, "\nP = %g +/- %g\n", m, std);
#define DNI_cos (1000 * cos(PI / 4))
CHECK(eq_eps(m, 4 * DNI_cos, 4 * DNI_cos * 2e-1), 1);
diff --git a/src/test_ssol_solver3N.c b/src/test_ssol_solver3N.c
@@ -113,6 +113,7 @@ main(int argc, char** argv)
double m, std;
int i, j, k;
(void) argc, (void) argv;
+ uint32_t r_id;
mem_init_proxy_allocator(&allocator, &mem_default_allocator);
@@ -201,7 +202,8 @@ main(int argc, char** argv)
tmp = tmpfile();
#define N 10000
CHECK(ssol_solve(scene, rng, N, tmp), RES_OK);
- CHECK(pp_sum(tmp, "cible", N, &m, &std), RES_OK);
+ CHECK(get_receiver_id(target, 1, &r_id), RES_OK);
+ CHECK(pp_sum(tmp, r_id, N, &m, &std), RES_OK);
logger_print(&logger, LOG_OUTPUT, "\nP = %g +/- %g\n", m, std);
#define DNI_cos (1000 * cos(PI / 8))
CHECK(eq_eps(m, 4 * NX * NY * NZ * DNI_cos, 4 * NX * NY * NZ * DNI_cos * 2e-1), 1);
diff --git a/src/test_ssol_solver4.c b/src/test_ssol_solver4.c
@@ -68,10 +68,10 @@ main(int argc, char** argv)
double transform[12]; /* 3x4 column major matrix */
FILE* tmp;
double m1, std1, m2, std2;
+ uint32_t r_id1, r_id2;
(void) argc, (void) argv;
#define FOCAL 10
- d33_splat(transform, 0);
d3_splat(transform + 9, 0);
d33_rotation_pitch(transform, PI); /* flip faces: invert normal */
transform[11] = FOCAL; /* +FOCAL offset along Z axis */
@@ -140,18 +140,18 @@ main(int argc, char** argv)
CHECK(ssol_instance_set_target_mask(target2, 0x1, 0), RES_OK);
CHECK(ssol_instance_dont_sample(target2, 1), RES_OK);
CHECK(ssol_scene_attach_instance(scene, target2), RES_OK);
-
- CHECK(ssol_solve(scene, rng, 20, stdout), RES_OK);
-
+
tmp = tmpfile();
#define N 10000
CHECK(ssol_solve(scene, rng, N, tmp), RES_OK);
- CHECK(pp_sum(tmp, "cible1", N, &m1, &std1), RES_OK);
- CHECK(pp_sum(tmp, "cible2", N, &m2, &std2), RES_OK);
+ CHECK(get_receiver_id(target1, 1, &r_id1), RES_OK);
+ CHECK(get_receiver_id(target2, 1, &r_id2), RES_OK);
+ CHECK(pp_sum(tmp, r_id1, N, &m1, &std1), RES_OK);
+ CHECK(pp_sum(tmp, r_id2, N, &m2, &std2), RES_OK);
logger_print(&logger, LOG_OUTPUT, "\nP = %g +/- %g\n", m1, std1);
#define DNI_cos (1000 * cos(0))
CHECK(eq_eps(m1, 400 * DNI_cos, 400 * DNI_cos * 1e-4), 1);
- CHECK(eq_eps(std1, 0, 0.1), 1);
+ CHECK(eq_eps(std1, 0, 1), 1);
CHECK(m1, m2);
CHECK(std1, std2);
diff --git a/src/test_ssol_solver5.c b/src/test_ssol_solver5.c
@@ -67,10 +67,10 @@ main(int argc, char** argv)
double transform[12]; /* 3x4 column major matrix */
FILE* tmp;
double m, std;
+ uint32_t r_id;
(void) argc, (void) argv;
#define FOCAL 10
- d33_splat(transform, 0);
d3_splat(transform + 9, 0);
d33_rotation_pitch(transform, PI); /* flip faces: invert normal */
transform[11] = FOCAL; /* +FOCAL offset along Z axis */
@@ -134,16 +134,15 @@ main(int argc, char** argv)
CHECK(ssol_instance_dont_sample(target, 1), RES_OK);
CHECK(ssol_scene_attach_instance(scene, target), RES_OK);
- CHECK(ssol_solve(scene, rng, 20, stdout), RES_OK);
-
tmp = tmpfile();
#define N 10000
CHECK(ssol_solve(scene, rng, N, tmp), RES_OK);
- CHECK(pp_sum(tmp, "cible", N, &m, &std), RES_OK);
+ CHECK(get_receiver_id(target, 1, &r_id), RES_OK);
+ CHECK(pp_sum(tmp, r_id, N, &m, &std), RES_OK);
logger_print(&logger, LOG_OUTPUT, "\nP = %g +/- %g\n", m, std);
#define DNI_cos (1000 * cos(0))
CHECK(eq_eps(m, 400 * DNI_cos, 20), 1);
- CHECK(eq_eps(std, 0, 0.1), 1);
+ CHECK(eq_eps(std, 0, 1), 1);
/* free data */
diff --git a/src/test_ssol_utils.c b/src/test_ssol_utils.c
@@ -23,33 +23,50 @@
#include <stdio.h>
#include <string.h>
+/* hack until the needed API comes from a merge */
+#include "ssol_instance_c.h"
+#include "ssol_c.h"
+res_T
+get_receiver_id (struct ssol_instance* instance, const int front_face, uint32_t* id) {
+ struct str* rec;
+
+ if (!instance || !id)
+ return RES_BAD_ARG;
+ rec = front_face ? &instance->receiver_front : &instance->receiver_back;
+ if(str_is_empty(rec))
+ return RES_BAD_ARG;
+
+ S3D(shape_get_id(instance->shape_rt, id));
+ *id |= (front_face ? FRONT_FLAG : BACK_FLAG);
+ return RES_OK;
+}
+
res_T
pp_sum
(FILE* f,
- const char* target,
+ const uint32_t receiver_id,
const size_t count,
double* mean,
double* std)
{
+ struct receiver_data hit;
double sum = 0;
double sum2 = 0;
double E, V, SE;
- char expect_tok[256];
- ASSERT(f && target && mean && std && count);
+
+ if(!f || !mean || !std || !count)
+ return RES_BAD_ARG;
- snprintf(expect_tok, 256, "'%s':", target);
rewind(f);
- while (!feof(f)) {
- char buf[256];
- if (fgets(buf, 256, f)) {
- char tok[256];
- double w;
- if (2 == sscanf(buf, "Receiver %s %*f %*f %*f %lf", tok, &w)) {
- if (strcmp(tok, expect_tok)) continue;
- sum += w;
- sum2 += w * w;
- }
- }
+ while (1 == fread(&hit, sizeof(struct receiver_data), 1, f)) {
+ if (ferror(f))
+ return RES_BAD_ARG;
+
+ if (receiver_id != hit.receiver_id)
+ continue;
+
+ sum += hit.weight;
+ sum2 += hit.weight * hit.weight;
}
E = sum / (double)count;
diff --git a/src/test_ssol_utils.h b/src/test_ssol_utils.h
@@ -40,10 +40,14 @@ check_memory_allocator(struct mem_allocator* allocator)
extern LOCAL_SYM res_T
pp_sum
- (FILE* f,
- const char* target,
+ (FILE* f,
+ const uint32_t receiver_id,
const size_t count,
double* mean,
double* std);
+/* hack until the needed API comes from a merge */
+struct ssol_instance;
+res_T get_receiver_id(struct ssol_instance* instance, const int front_face, uint32_t* id);
+
#endif /* TEST_SSOL_UTILS_H */