commit 21dd82121e9c7e88a897cfff52647d5aeb4a7843
parent 81b84a2d012892840aa5c9810ee07b1de38cf335
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Thu, 9 Mar 2017 16:39:58 +0100
Merge remote-tracking branch 'origin/develop' into feature_path_tracing
Diffstat:
33 files changed, 1287 insertions(+), 23 deletions(-)
diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt
@@ -140,6 +140,22 @@ if(NOT NO_TEST)
new_test(test_solstice_args)
+ build_test(test_solstice_simulation)
+ function(add_test_simulation _name)
+ add_test(NAME test_solstice_simulation_${_name}
+ COMMAND test_solstice_simulation
+ $<TARGET_FILE:solstice>
+ ${SOLSTICE_SOURCE_DIR}/../yaml/
+ ${_name})
+ endfunction()
+
+ add_test_simulation(beam_down)
+ add_test_simulation(test01)
+ add_test_simulation(test02)
+ add_test_simulation(test03)
+ add_test_simulation(test04)
+ add_test_simulation(test05)
+
endif()
################################################################################
diff --git a/cmake/parser/CMakeLists.txt b/cmake/parser/CMakeLists.txt
@@ -39,7 +39,7 @@ set(SOLPARSER_FILES_INC
solparser_shape.h
solparser_sun.h)
-# Prepend each file in the `SOLSTICE_FILES_<SRC|INC>' list by `SOLSTICE_SOURCE_DIR'
+# Prepend each file in the `SOLPARSER_FILES_<SRC|INC>' list by `SOLPARSER_SOURCE_DIR'
rcmake_prepend_path(SOLPARSER_FILES_SRC ${SOLPARSER_SOURCE_DIR})
rcmake_prepend_path(SOLPARSER_FILES_INC ${SOLPARSER_SOURCE_DIR})
rcmake_prepend_path(SOLPARSER_FILES_DOC ${PROJECT_SOURCE_DIR}/../)
diff --git a/cmake/receivers/CMakeLists.txt b/cmake/receivers/CMakeLists.txt
@@ -65,6 +65,7 @@ if(NOT NO_TEST)
${SRCVL_SOURCE_DIR}/yaml/test_ko.yaml)
new_test(test_srcvl2)
+ rcmake_copy_runtime_libraries(test_srcvl)
endif()
diff --git a/doc/input b/doc/input
@@ -130,6 +130,7 @@
# | <obj>
# | <parabol>
# | <parabolic-cylinder>
+# | <hyperbol>
# | <plane>
# | <sphere>
# | <stl>
@@ -158,6 +159,16 @@
# focal: REAL # in ]0, INF)
# clip: <polyclip-list>
#
+# <hyperbol> ::= # (x^2 + y^2) / a^2 - (z + z0 - g/2)^2 / b^2 + 1 = 0
+# hyperbol: # with g = img_focal + real_focal; f = real_focal / g;
+# # a^2 = g^2(f - f^2); b = g(f - 1/2); z0 = |b| + g/2
+# focals: <hyperboloid_focals>
+# clip: <polyclip-list>
+#
+# <hyperboloid_focals> ::=
+# real: REAL # in ]0, INF)
+# image: REAL # in ]0, INF)
+#
# <plane> ::=
# plane:
# clip: <polyclip-list>
@@ -247,7 +258,10 @@
#
# <anchor-data> ::=
# name: STRING
-# position: <real3>
+# <position-description>
+#
+# <position-description> ::=
+# position: <real3> | hyperboloid_image_focals: <hyperboloid_focals>
#
# # "self" references the first level entity
# <entity-identifier> ::=
diff --git a/src/parser/solparser.c b/src/parser/solparser.c
@@ -104,6 +104,16 @@ struct target_alias {
solparser_shape_paraboloid_copy_and_release
#include <rsys/dynamic_array.h>
+/* Declare the array of hyperboloids */
+#define DARRAY_NAME hyperboloid
+#define DARRAY_DATA struct solparser_shape_hyperboloid
+#define DARRAY_FUNCTOR_INIT solparser_shape_hyperboloid_init
+#define DARRAY_FUNCTOR_RELEASE solparser_shape_hyperboloid_release
+#define DARRAY_FUNCTOR_COPY solparser_shape_hyperboloid_copy
+#define DARRAY_FUNCTOR_COPY_AND_RELEASE \
+ solparser_shape_hyperboloid_copy_and_release
+#include <rsys/dynamic_array.h>
+
/* Declare the array of planes */
#define DARRAY_NAME plane
#define DARRAY_DATA struct solparser_shape_plane
@@ -192,6 +202,7 @@ struct solparser {
struct darray_impgeom objs;
struct darray_paraboloid parabols;
struct darray_paraboloid parabolic_cylinders;
+ struct darray_hyperboloid hyperbols;
struct darray_plane planes;
struct darray_sphere spheres;
struct darray_impgeom stls;
@@ -389,6 +400,7 @@ parser_clear(struct solparser* parser)
darray_impgeom_clear(&parser->objs);
darray_paraboloid_clear(&parser->parabols);
darray_paraboloid_clear(&parser->parabolic_cylinders);
+ darray_hyperboloid_clear(&parser->hyperbols);
darray_plane_clear(&parser->planes);
darray_sphere_clear(&parser->spheres);
darray_impgeom_clear(&parser->stls);
@@ -440,6 +452,7 @@ parser_release(ref_T* ref)
darray_impgeom_release(&parser->objs);
darray_paraboloid_release(&parser->parabols);
darray_paraboloid_release(&parser->parabolic_cylinders);
+ darray_hyperboloid_release(&parser->hyperbols);
darray_plane_release(&parser->planes);
darray_sphere_release(&parser->spheres);
darray_impgeom_release(&parser->stls);
@@ -1925,6 +1938,170 @@ error:
}
static res_T
+parse_focals_description
+ (struct solparser* parser,
+ yaml_document_t* doc,
+ const yaml_node_t* desc,
+ struct hyperboloid_focals* focals)
+{
+ enum { REAL, IMAGE };
+ intptr_t i, n;
+ int mask = 0; /* Register the parsed attributes */
+ res_T res = RES_OK;
+ ASSERT(doc && desc && focals);
+
+ if (desc->type != YAML_MAPPING_NODE) {
+ log_err(parser, desc, "expect a mapping of focal parameters.\n");
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ n = desc->data.mapping.pairs.top - desc->data.mapping.pairs.start;
+ FOR_EACH(i, 0, n) {
+ yaml_node_t* key;
+ yaml_node_t* val;
+
+ key = yaml_document_get_node(doc, desc->data.mapping.pairs.start[i].key);
+ val = yaml_document_get_node(doc, desc->data.mapping.pairs.start[i].value);
+ if (key->type != YAML_SCALAR_NODE) {
+ log_err(parser, key, "expect focal parameters.\n");
+ res = RES_BAD_ARG;
+ goto error;
+ }
+ #define SETUP_MASK(Flag, Name) { \
+ if(mask & BIT(Flag)) { \
+ log_err(parser, key, \
+ "the focal parameter `"Name"' is already defined.\n"); \
+ res = RES_BAD_ARG; \
+ goto error; \
+ } \
+ mask |= BIT(Flag); \
+ } (void)0
+ if (!strcmp((char*) key->data.scalar.value, "real")) {
+ SETUP_MASK(REAL, "real");
+ res = parse_real(parser, val, nextafter(0, 1), DBL_MAX, &focals->real);
+ }
+ else if (!strcmp((char*) key->data.scalar.value, "image")) {
+ SETUP_MASK(IMAGE, "image");
+ res = parse_real(parser, val, nextafter(0, 1), DBL_MAX, &focals->image);
+ }
+ if (res != RES_OK) {
+ log_node(parser, key);
+ goto error;
+ }
+ }
+ #undef SETUP_MASK
+ #define CHECK_PARAM(Flag, Name) \
+ if(!(mask & BIT(Flag))) { \
+ log_err(parser, desc, \
+ "the focal parameter `"Name"' is missing.\n"); \
+ res = RES_BAD_ARG; \
+ goto error; \
+ } (void)0
+ CHECK_PARAM(REAL, "real");
+ CHECK_PARAM(IMAGE, "image");
+ #undef CHECK_PARAM
+
+exit:
+ return res;
+error:
+ goto exit;
+}
+
+static res_T
+parse_hyperboloid
+ (struct solparser* parser,
+ yaml_document_t* doc,
+ const yaml_node_t* hyperboloid,
+ struct solparser_shape_hyperboloid_id* out_ishape)
+{
+ enum { CLIP, FOCAL };
+ struct solparser_shape_hyperboloid* shape = NULL;
+ size_t ishape = SIZE_MAX;
+ intptr_t i, n;
+ int mask = 0; /* Register the parsed attributes */
+ res_T res = RES_OK;
+ ASSERT(doc && hyperboloid && out_ishape);
+
+ if (hyperboloid->type != YAML_MAPPING_NODE) {
+ log_err(parser, hyperboloid, "expect a mapping of hyperbol parameters.\n");
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ /* Allocate a hyperboloid shape */
+ ishape = darray_hyperboloid_size_get(&parser->hyperbols);
+ res = darray_hyperboloid_resize(&parser->hyperbols, ishape + 1);
+ if (res != RES_OK) {
+ log_err(parser, hyperboloid, "could not allocate the hyperbol shape.\n");
+ goto error;
+ }
+ shape = darray_hyperboloid_data_get(&parser->hyperbols) + ishape;
+
+ n = hyperboloid->data.mapping.pairs.top - hyperboloid->data.mapping.pairs.start;
+ FOR_EACH(i, 0, n) {
+ yaml_node_t* key;
+ yaml_node_t* val;
+
+ key = yaml_document_get_node(doc, hyperboloid->data.mapping.pairs.start[i].key);
+ val = yaml_document_get_node(doc, hyperboloid->data.mapping.pairs.start[i].value);
+ if (key->type != YAML_SCALAR_NODE) {
+ log_err(parser, key, "expect hyperbol parameters.\n");
+ res = RES_BAD_ARG;
+ goto error;
+ }
+ #define SETUP_MASK(Flag, Name) { \
+ if(mask & BIT(Flag)) { \
+ log_err(parser, key, \
+ "the hyperbol parameter `"Name"' is already defined.\n"); \
+ res = RES_BAD_ARG; \
+ goto error; \
+ } \
+ mask |= BIT(Flag); \
+ } (void)0
+ if (!strcmp((char*) key->data.scalar.value, "clip")) {
+ SETUP_MASK(CLIP, "clip");
+ res = parse_clip(parser, doc, val, &shape->polyclips);
+ }
+ else if (!strcmp((char*) key->data.scalar.value, "focals")) {
+ SETUP_MASK(FOCAL, "focals");
+ res = parse_focals_description(parser, doc, val, &shape->focals);
+ }
+ else {
+ log_err(parser, key, "unknown hyperbol parameter `%s'.\n",
+ key->data.scalar.value);
+ res = RES_BAD_ARG;
+ goto error;
+ }
+ if (res != RES_OK) {
+ log_node(parser, key);
+ goto error;
+ }
+ #undef SETUP_MASK
+ }
+ #define CHECK_PARAM(Flag, Name) \
+ if(!(mask & BIT(Flag))) { \
+ log_err(parser, hyperboloid, \
+ "the hyperbol parameter `"Name"' is missing.\n"); \
+ res = RES_BAD_ARG; \
+ goto error; \
+ } (void)0
+ CHECK_PARAM(CLIP, "clip");
+ CHECK_PARAM(FOCAL, "focals");
+ #undef CHECK_PARAM
+
+exit :
+ out_ishape->i = ishape;
+ return res;
+error:
+ if (shape) {
+ darray_hyperboloid_pop_back(&parser->hyperbols);
+ ishape = SIZE_MAX;
+ }
+ goto exit;
+}
+
+static res_T
parse_plane
(struct solparser* parser,
yaml_document_t* doc,
@@ -2197,6 +2374,11 @@ parse_object
shape->type = SOLPARSER_SHAPE_PARABOLIC_CYLINDER;
res = parse_paraboloid
(parser, doc, val, shape->type, &shape->data.parabolic_cylinder);
+ }
+ else if (!strcmp((char*) key->data.scalar.value, "hyperbol")) {
+ SETUP_MASK(SHAPE, "shape");
+ shape->type = SOLPARSER_SHAPE_HYPERBOL;
+ res = parse_hyperboloid(parser, doc, val, &shape->data.hyperbol);
} else if(!strcmp((char*)key->data.scalar.value, "plane")) {
SETUP_MASK(SHAPE, "shape");
shape->type = SOLPARSER_SHAPE_PLANE;
@@ -2466,8 +2648,16 @@ parse_anchor
SETUP_MASK(NAME, "name");
res = parse_identifier_string(parser, val, &solanchor->name);
} else if(!strcmp((char*)key->data.scalar.value, "position")) {
- SETUP_MASK(POSITION, "position");
+ SETUP_MASK(POSITION, "position description");
res = parse_real3(parser, doc, val, -DBL_MAX, DBL_MAX, solanchor->position);
+ }
+ else if (!strcmp((char*) key->data.scalar.value, "hyperboloid_image_focals"))
+ {
+ struct hyperboloid_focals focals;
+ SETUP_MASK(POSITION, "position description");
+ res = parse_focals_description(parser, doc, val, &focals);
+ if (res != RES_OK) goto error;
+ d3(solanchor->position, 0, 0, focals.image);
} else {
log_err(parser, key, "unknown anchor parameter `%s'.\n",
key->data.scalar.value);
@@ -2488,7 +2678,7 @@ parse_anchor
goto error; \
} (void)0
CHECK_PARAM(NAME, "name");
- CHECK_PARAM(POSITION, "position");
+ CHECK_PARAM(POSITION, "position description");
#undef CHECK_PARAM
res = anchor_register_name(parser, anchor, htable, isolanchor);
@@ -3442,6 +3632,7 @@ solparser_create
darray_impgeom_init(mem_allocator, &parser->objs);
darray_paraboloid_init(mem_allocator, &parser->parabols);
darray_paraboloid_init(mem_allocator, &parser->parabolic_cylinders);
+ darray_hyperboloid_init(mem_allocator, &parser->hyperbols);
darray_plane_init(mem_allocator, &parser->planes);
darray_sphere_init(mem_allocator, &parser->spheres);
darray_impgeom_init(mem_allocator, &parser->stls);
@@ -3874,6 +4065,15 @@ solparser_get_shape_parabolic_cylinder
return darray_paraboloid_cdata_get(&parser->parabolic_cylinders)+paraboloid.i;
}
+const struct solparser_shape_hyperboloid*
+solparser_get_shape_hyperbol
+ (const struct solparser* parser,
+ const struct solparser_shape_hyperboloid_id hyperboloid)
+{
+ ASSERT(parser && hyperboloid.i < darray_hyperboloid_size_get(&parser->hyperbols));
+ return darray_hyperboloid_cdata_get(&parser->hyperbols) + hyperboloid.i;
+}
+
const struct solparser_shape_plane*
solparser_get_shape_plane
(const struct solparser* parser,
diff --git a/src/parser/solparser.h b/src/parser/solparser.h
@@ -162,6 +162,11 @@ solparser_get_shape_parabolic_cylinder
(const struct solparser* parser,
const struct solparser_shape_paraboloid_id paraboloid);
+extern LOCAL_SYM const struct solparser_shape_hyperboloid*
+solparser_get_shape_hyperbol
+ (const struct solparser* parser,
+ const struct solparser_shape_hyperboloid_id hyperboloid);
+
extern LOCAL_SYM const struct solparser_shape_plane*
solparser_get_shape_plane
(const struct solparser* parser,
diff --git a/src/parser/solparser_shape.h b/src/parser/solparser_shape.h
@@ -32,6 +32,7 @@ enum solparser_shape_type {
SOLPARSER_SHAPE_OBJ, /* Imported Alias Wavefront obj */
SOLPARSER_SHAPE_PARABOL,
SOLPARSER_SHAPE_PARABOLIC_CYLINDER,
+ SOLPARSER_SHAPE_HYPERBOL,
SOLPARSER_SHAPE_PLANE,
SOLPARSER_SHAPE_SPHERE,
SOLPARSER_SHAPE_STL /* Imported STereo Lithography */
@@ -198,6 +199,58 @@ solparser_shape_paraboloid_copy_and_release
}
/*******************************************************************************
+* Hyperboloid shape
+******************************************************************************/
+struct hyperboloid_focals {
+ double real, image;
+};
+
+#define HYPERBOLOID_FOCALS_NULL__ { 0, 0 }
+static const struct hyperboloid_focals
+HYPERBOLOID_FOCALS_NULL = HYPERBOLOID_FOCALS_NULL__;
+
+struct solparser_shape_hyperboloid {
+ struct hyperboloid_focals focals;
+ struct darray_polyclip polyclips;
+};
+
+static INLINE void
+solparser_shape_hyperboloid_init
+ (struct mem_allocator* allocator,
+ struct solparser_shape_hyperboloid* hyperboloid)
+{
+ ASSERT(hyperboloid);
+ darray_polyclip_init(allocator, &hyperboloid->polyclips);
+}
+
+static INLINE void
+solparser_shape_hyperboloid_release(struct solparser_shape_hyperboloid* hyperboloid)
+{
+ ASSERT(hyperboloid);
+ darray_polyclip_release(&hyperboloid->polyclips);
+}
+
+static INLINE res_T
+solparser_shape_hyperboloid_copy
+ (struct solparser_shape_hyperboloid* dst,
+ const struct solparser_shape_hyperboloid* src)
+{
+ ASSERT(dst && src);
+ dst->focals = src->focals;
+ return darray_polyclip_copy(&dst->polyclips, &src->polyclips);
+}
+
+static INLINE res_T
+solparser_shape_hyperboloid_copy_and_release
+ (struct solparser_shape_hyperboloid* dst,
+ struct solparser_shape_hyperboloid* src)
+{
+ ASSERT(dst && src);
+ dst->focals = src->focals;
+ return darray_polyclip_copy_and_release(&dst->polyclips, &src->polyclips);
+}
+
+/*******************************************************************************
* Plane shape
******************************************************************************/
struct solparser_shape_plane {
@@ -260,6 +313,7 @@ struct solparser_shape_cuboid_id { size_t i; };
struct solparser_shape_cylinder_id { size_t i; };
struct solparser_shape_imported_geometry_id { size_t i; };
struct solparser_shape_paraboloid_id { size_t i; };
+struct solparser_shape_hyperboloid_id { size_t i; };
struct solparser_shape_plane_id { size_t i; };
struct solparser_shape_sphere_id { size_t i; };
@@ -271,6 +325,7 @@ struct solparser_shape {
struct solparser_shape_imported_geometry_id obj;
struct solparser_shape_paraboloid_id parabol;
struct solparser_shape_paraboloid_id parabolic_cylinder;
+ struct solparser_shape_hyperboloid_id hyperbol;
struct solparser_shape_plane_id plane;
struct solparser_shape_sphere_id sphere;
struct solparser_shape_imported_geometry_id stl;
diff --git a/src/parser/test_solparser3.c b/src/parser/test_solparser3.c
@@ -25,6 +25,13 @@ static const char* input[] = {
"- geometry: &cylinder2\n",
" - cylinder: { radius: 1, height: 10 }\n",
" material: *lambertian\n",
+ "- geometry: &hyperbol1\n",
+ " - hyperbol:\n",
+ " focals: &hyp1_focals { real: 4, image: 1 }\n",
+ " clip:\n",
+ " - operation : AND\n",
+ " vertices : [[1, 2],[3, 4],[6, 7]]\n",
+ " material: *lambertian\n",
"- sun: \n",
" dni: 1\n",
" spectrum: [{wavelength: 1, data: 1}]\n",
@@ -37,6 +44,8 @@ static const char* input[] = {
" position: [1, 2, 3]\n",
" - name: anchor1\n",
" position: [4, 5, 6]\n",
+ " - name: anchor2\n",
+ " hyperboloid_image_focals: *hyp1_focals\n",
" children:\n",
" - name: entity0a\n",
" primary: 1\n",
@@ -49,6 +58,9 @@ static const char* input[] = {
" position: [4, 5, 6]\n",
" - name: entity0b\n",
" position: [7, 8, 9]\n",
+ " - name: entity0c\n",
+ " primary: 0\n",
+ " geometry: *hyperbol1\n",
"- entity:\n",
" name: entity1\n",
" x_pivot:\n",
@@ -60,6 +72,11 @@ static const char* input[] = {
" spacing: 1\n",
" ref_point: [1, 2, 3]\n",
" target: { anchor: \"entity0.entity0b.anchor0\" }\n",
+ "- entity:\n",
+ " name: entity3\n",
+ " x_pivot:\n",
+ " ref_point: [4, 2, 3]\n",
+ " target: { anchor: \"entity0.anchor2\" }\n",
NULL
};
@@ -120,8 +137,8 @@ check_entity0
matte = solparser_get_material_matte(parser, mtl->data.matte);
CHECK(matte->reflectivity, 0.5);
- CHECK(solparser_entity_get_children_count(entity0), 2);
- CHECK(solparser_entity_get_anchors_count(entity0), 2);
+ CHECK(solparser_entity_get_children_count(entity0), 3);
+ CHECK(solparser_entity_get_anchors_count(entity0), 3);
anchor_id = solparser_entity_get_anchor(entity0, 0);
entity0_anchor0 = solparser_get_anchor(parser, anchor_id);
@@ -186,13 +203,14 @@ check_entity1
CHECK(solparser_entity_get_children_count(entity1), 0);
x_pivot = solparser_get_x_pivot(parser, entity1->data.x_pivot);
+ NCHECK(x_pivot, NULL);
CHECK(d3_eq(x_pivot->ref_point, d3(tmp, 1, 2, 3)), 1);
CHECK(x_pivot->target.type, SOLPARSER_TARGET_ANCHOR);
}
static void
check_entity2
-(struct solparser* parser, const struct solparser_entity* entity2)
+ (struct solparser* parser, const struct solparser_entity* entity2)
{
double tmp[3];
@@ -205,11 +223,32 @@ check_entity2
CHECK(solparser_entity_get_children_count(entity2), 0);
zx_pivot = solparser_get_zx_pivot(parser, entity2->data.zx_pivot);
+ NCHECK(zx_pivot, NULL);
CHECK(zx_pivot->spacing, 1);
CHECK(d3_eq(zx_pivot->ref_point, d3(tmp, 1, 2, 3)), 1);
CHECK(zx_pivot->target.type, SOLPARSER_TARGET_ANCHOR);
}
+static void
+check_entity3
+ (struct solparser* parser, const struct solparser_entity* entity3)
+{
+ double tmp[3];
+
+ NCHECK(parser, NULL);
+ NCHECK(entity3, NULL);
+
+ CHECK(strcmp(str_cget(&entity3->name), "entity3"), 0);
+ CHECK(entity3->type, SOLPARSER_ENTITY_X_PIVOT);
+ CHECK(solparser_entity_get_anchors_count(entity3), 0);
+ CHECK(solparser_entity_get_children_count(entity3), 0);
+
+ x_pivot = solparser_get_x_pivot(parser, entity3->data.x_pivot);
+ NCHECK(x_pivot, NULL);
+ CHECK(d3_eq(x_pivot->ref_point, d3(tmp, 4, 2, 3)), 1);
+ CHECK(x_pivot->target.type, SOLPARSER_TARGET_ANCHOR);
+}
+
int
main(int argc, char** argv)
{
@@ -256,6 +295,9 @@ main(int argc, char** argv)
}
else if(!strcmp(str_cget(&entity->name), "entity2")) {
check_entity2(parser, entity);
+ }
+ else if (!strcmp(str_cget(&entity->name), "entity3")) {
+ check_entity3(parser, entity);
} else {
FATAL("Unexpected entity name.\n");
}
diff --git a/src/parser/test_solparser6.c b/src/parser/test_solparser6.c
@@ -31,6 +31,9 @@ main(int argc, char** argv)
const struct solparser_material* mtl;
const struct solparser_object* obj;
const struct solparser_shape* shape;
+ const struct solparser_shape_sphere* sphere;
+ const struct solparser_shape_paraboloid* parabol;
+ const struct solparser_shape_hyperboloid* hyperbol;
FILE* stream;
(void)argc, (void)argv;
@@ -45,8 +48,20 @@ main(int argc, char** argv)
fprintf(stream, " name: test\n");
fprintf(stream, " primary: 0\n");
fprintf(stream, " geometry:\n");
- fprintf(stream, " - sphere: { radius: 1 }\n");
- fprintf(stream, " material: { ?virtual }\n");
+ fprintf(stream, " - sphere: { radius: 1 }\n");
+ fprintf(stream, " material: { ?virtual }\n");
+ fprintf(stream, " - parabol:\n");
+ fprintf(stream, " focal: 10\n");
+ fprintf(stream, " clip :\n");
+ fprintf(stream, " - operation : AND\n");
+ fprintf(stream, " vertices : [[1, 2], [3, 4], [6, 7]]\n");
+ fprintf(stream, " material: { ?virtual }\n");
+ fprintf(stream, " - hyperbol:\n");
+ fprintf(stream, " focals: { real: 10, image: 2 }\n");
+ fprintf(stream, " clip :\n");
+ fprintf(stream, " - operation : AND\n");
+ fprintf(stream, " vertices : [[1, 2], [3, 4], [6, 7]]\n");
+ fprintf(stream, " material: { ?virtual }\n");
rewind(stream);
CHECK(solparser_setup(parser, NULL, stream), RES_OK);
@@ -63,11 +78,31 @@ main(int argc, char** argv)
CHECK(solparser_entity_get_children_count(entity), 0);
CHECK(entity->type, SOLPARSER_ENTITY_GEOMETRY);
geom = solparser_get_geometry(parser, entity->data.geometry);
- CHECK(solparser_geometry_get_objects_count(geom), 1);
+ CHECK(solparser_geometry_get_objects_count(geom), 3);
+
obj_id = solparser_geometry_get_object(geom, 0);
obj = solparser_get_object(parser, obj_id);
shape = solparser_get_shape(parser, obj->shape);
CHECK(shape->type, SOLPARSER_SHAPE_SPHERE);
+ sphere = solparser_get_shape_sphere(parser, shape->data.sphere);
+ CHECK(sphere->radius, 1);
+ CHECK(sphere->nslices, 16);
+
+ obj_id = solparser_geometry_get_object(geom, 1);
+ obj = solparser_get_object(parser, obj_id);
+ shape = solparser_get_shape(parser, obj->shape);
+ CHECK(shape->type, SOLPARSER_SHAPE_PARABOL);
+ parabol = solparser_get_shape_parabol(parser, shape->data.parabol);
+ CHECK(parabol->focal, 10);
+
+ obj_id = solparser_geometry_get_object(geom, 2);
+ obj = solparser_get_object(parser, obj_id);
+ shape = solparser_get_shape(parser, obj->shape);
+ CHECK(shape->type, SOLPARSER_SHAPE_HYPERBOL);
+ hyperbol = solparser_get_shape_hyperbol(parser, shape->data.hyperbol);
+ CHECK(hyperbol->focals.real, 10);
+ CHECK(hyperbol->focals.image, 2);
+
mtl2 = solparser_get_material_double_sided(parser, obj->mtl2);
CHECK(mtl2->front.i, mtl2->back.i);
mtl = solparser_get_material(parser, mtl2->front);
diff --git a/src/parser/yaml/test_ko_0.yaml b/src/parser/yaml/test_ko_0.yaml
@@ -624,6 +624,96 @@
---
#
+# <hyperbol> ::=
+# hyperbol: # (x^2 + y^2) / a^2 - (z + z0 - 1/2)^2 / b^2 + 1 = 0
+# # with g = img_focal + real_focal; f = real_focal / g;
+# # a^2 = g^2(f - f^2); b = g(f - 1/2); z0 = |b| + g/2
+# focals: <hyperboloid_focals>
+# clip: <polyclip-list>
+#
+# <hyperboloid_focals> ::=
+# real: REAL # in ]0, INF)
+# image: REAL # in ]0, INF)
+#
+# missing hyperbol definition
+- geometry: [ { hyperbol: } ]
+---
+# unknown dummy parameter
+- geometry: [ { hyperbol: { dummy: 1 } } ]
+---
+# missing focals definition
+- geometry: [ { hyperbol: { focals: } } ]
+---
+# missing real value
+- geometry: [ { hyperbol: { focals: { real: } } } ]
+---
+# missing image value
+- geometry: [ { hyperbol: { focals: { image: } } } ]
+---
+# missing clip value
+- geometry: [ { hyperbol: { clip: } } ]
+---
+# real should be a number
+- geometry: [ { hyperbol: { focals: { real: "dummy" } } } ]
+---
+# -1 invalid
+- geometry: [ { hyperbol: { focals: { real: -1 } } } ]
+---
+# 0 invalid
+- geometry: [ { hyperbol: { focals: { real: 0 } } } ]
+---
+# image should be a number
+- geometry: [ { hyperbol: { focals: { image: "dummy" } } } ]
+---
+# -1 invalid
+- geometry: [ { hyperbol: { focals: { image: -1 } } } ]
+---
+# 0 invalid
+- geometry: [ { hyperbol: { focals: { image: 0 } } } ]
+---
+# missing clip parameter
+- geometry: [ { hyperbol: { focals: { real: 1, image: 1 } } } ]
+---
+# missing real parameter
+- geometry:
+ - hyperbol:
+ focals: { image: 1 }
+ clip:
+ - operation: AND
+ vertices: [ [1, 2], [3, 4], [6, 7] ]
+---
+# missing image parameter
+- geometry:
+ - hyperbol:
+ focals: { real: 10 }
+ clip:
+ - operation: AND
+ vertices: [ [1, 2], [3, 4], [6, 7] ]
+---
+# 2x focals
+- geometry:
+ - hyperbol:
+ focals: { real: 1, image: 1 }
+ focals: { real: 1, image: 1 }
+---
+# 2x real
+- geometry: [ { hyperbol: { focals: { real: 1, real: 1 } } } ]
+---
+# 2x image
+- geometry: [ { hyperbol: { focals: { image: 1, image: 1 } } } ]
+---
+# 2x clip
+- geometry:
+ - hyperbol:
+ clip:
+ - operation: AND
+ vertices: [ [1, 2], [3, 4], [6, 7] ]
+ clip:
+ - operation: AND
+ vertices: [ [1, 2], [3, 4], [6, 7] ]
+---
+
+#
# <plane> ::=
# plane:
# clip: <polyclip-list>
@@ -1066,30 +1156,71 @@
#
# <anchor-data> ::=
# name: STRING
-# position: <real3>
+# <position-description>
#
+# <position-description> ::=
+# position: <real3> | hyperboloid_image_focals: <hyperboloid_focals>
+#
# missing anchors definition
- entity:
anchors:
---
-# missing position
+# missing name definition
- entity:
- anchors:
- - name: "anchor"
+ anchors: [ name: ]
+---
+# missing position definition
+- entity:
+ anchors: [ position: ]
+---
+# missing hyperboloid_image_focals definition
+- entity:
+ anchors: [ { hyperboloid_image_focals: } ]
+---
+# missing position-description
+- entity:
+ anchors: [ { name: "anchor" } ]
+---
+# position should have 3 values
+- entity:
+ anchors: [ { name: "anchor", position: [ -4, 5.2 ] } ]
+---
+# position should have 3 values
+- entity:
+ anchors: [ { name: "anchor", position: [ -4, 5.2, 0, 5 ] } ]
---
# missing name
- entity:
+ anchors: [ { position: [ -4, 5.2, 0 ] } ]
+---
+# 2x name
+- entity:
+ anchors: [ { name: "anchor", name: "anchor" } ]
+---
+# 2x position-description
+- entity:
+ anchors: [ { position: [ -4, 5.2, 0 ], position: [ -4, 5.2, 0 ] } ]
+---
+# 2x position-description
+- entity:
anchors:
- - position: [ -4, 5.2, 0 ]
+ - hyperboloid_image_focals: { real: 1, image: 1 }
+ hyperboloid_image_focals: { real: 1, image: 1 }
+---
+# 2x position-description
+- entity:
+ anchors:
+ - hyperboloid_image_focals: { real: 1, image: 1 }
+ position: [ -4, 5.2, 0 ]
---
# 2 anchors with same name
- entity:
anchors:
- - name: "anchor"
- position: [ -4, 5.2, 0 ]
- - name: "anchor"
- position: [ -4, 5.2, 0 ]
+ - name: "anchor"
+ position: [ -4, 5.2, 0 ]
+ - name: "anchor"
+ position: [ -4, 5.2, 0 ]
---
#
diff --git a/src/solstice.c b/src/solstice.c
@@ -20,6 +20,8 @@
#include "solstice_args.h"
#include "parser/solparser.h"
+#include <rsys/double2.h>
+
#include <sys/stat.h>
#include <sys/types.h>
@@ -306,6 +308,7 @@ static res_T
setup_sun_dirs(struct solstice* solstice, const struct solstice_args* args)
{
double* sun_dirs = NULL;
+ double* sun_angles = NULL;
size_t i;
res_T res = RES_OK;
ASSERT(solstice && args);
@@ -316,18 +319,26 @@ setup_sun_dirs(struct solstice* solstice, const struct solstice_args* args)
"Could not reserve the list of %lu sun directions.\n",
(unsigned long)args->nsun_dirs);
goto error;
-
}
-
+ res = darray_double_resize(&solstice->sun_angles, args->nsun_dirs*2/*#dims*/);
+ if (res != RES_OK) {
+ fprintf(stderr,
+ "Could not reserve the list of %lu sun angles.\n",
+ (unsigned long)args->nsun_dirs);
+ goto error;
+ }
sun_dirs = darray_double_data_get(&solstice->sun_dirs);
+ sun_angles = darray_double_data_get(&solstice->sun_angles);
FOR_EACH(i, 0, args->nsun_dirs) {
spherical_to_cartesian_sun_dir(args->sun_dirs + i, sun_dirs + i*3/*#dims*/);
+ d2(sun_angles + i*2, args->sun_dirs[i].azimuth, args->sun_dirs[i].elevation);
}
exit:
return res;
error:
darray_double_clear(&solstice->sun_dirs);
+ darray_double_clear(&solstice->sun_angles);
goto exit;
}
@@ -531,6 +542,7 @@ solstice_init
darray_nodes_init(allocator, &solstice->roots);
darray_nodes_init(allocator, &solstice->pivots);
darray_double_init(allocator, &solstice->sun_dirs);
+ darray_double_init(allocator, &solstice->sun_angles);
solstice->allocator = allocator ? allocator : &mem_default_allocator;
@@ -633,12 +645,14 @@ solstice_release(struct solstice* solstice)
darray_nodes_release(&solstice->roots);
darray_nodes_release(&solstice->pivots);
darray_double_release(&solstice->sun_dirs);
+ darray_double_release(&solstice->sun_angles);
}
res_T
solstice_run(struct solstice* solstice)
{
const double* sun_dirs = NULL;
+ const double* sun_angles = NULL;
size_t nsun_dirs = 0;
size_t i;
int dump;
@@ -647,6 +661,7 @@ solstice_run(struct solstice* solstice)
ASSERT(solstice);
sun_dirs = darray_double_cdata_get(&solstice->sun_dirs);
+ sun_angles = darray_double_cdata_get(&solstice->sun_angles);
nsun_dirs = darray_double_size_get(&solstice->sun_dirs);
ASSERT(nsun_dirs%3 == 0);
nsun_dirs /= 3/*#dims*/;
@@ -674,6 +689,8 @@ solstice_run(struct solstice* solstice)
} else {
FOR_EACH(i, 0, nsun_dirs) {
const double* sun_dir = sun_dirs + i*3/*#dims*/;
+ fprintf(solstice->output, "#--- Sun direction: %g %g (%g %g %g)\n",
+ SPLIT2(sun_angles), SPLIT3(sun_dir));
res = solstice_update_entities(solstice, sun_dir);
if(res != RES_OK) goto error;
@@ -694,7 +711,6 @@ solstice_run(struct solstice* solstice)
res = solstice_solve(solstice);
if(res != RES_OK) goto error;
}
- fprintf(solstice->output, "#--- Sun direction: %g %g %g\n", SPLIT3(sun_dir));
}
}
diff --git a/src/solstice.h b/src/solstice.h
@@ -94,6 +94,7 @@ struct solstice {
enum solstice_args_dump_split_mode dump_split_mode;
struct darray_double sun_dirs; /* List of double3 */
+ struct darray_double sun_angles;
size_t nrealisations; /* # realisations */
FILE* output; /* Output stream */
diff --git a/src/solstice_entity.c b/src/solstice_entity.c
@@ -37,7 +37,7 @@ update_instance_transform
static res_T
merge_name
- (struct str* RESTRICT output,
+ (struct str* output,
const struct str* name0,
const struct str* name1)
{
diff --git a/src/solstice_object.c b/src/solstice_object.c
@@ -434,6 +434,29 @@ create_parabolic_cylinder
}
static res_T
+create_hyperbol
+ (struct solstice* solstice,
+ const double transform[12],
+ const struct solparser_shape_hyperboloid_id id,
+ struct ssol_shape** out_ssol_shape)
+{
+ const struct solparser_shape_hyperboloid* hyperboloid;
+ struct ssol_quadric quadric = SSOL_QUADRIC_DEFAULT;
+ ASSERT(solstice);
+
+ hyperboloid = solparser_get_shape_hyperbol(solstice->parser, id);
+
+ quadric.type = SSOL_QUADRIC_HYPERBOL;
+ quadric.data.hyperbol.real_focal = hyperboloid->focals.real;
+ quadric.data.hyperbol.img_focal = hyperboloid->focals.image;
+ d33_set(quadric.transform, transform);
+ d3_set(quadric.transform + 9, transform + 9);
+
+ return create_ssol_shape_punched_surface
+ (solstice, &hyperboloid->polyclips, &quadric, out_ssol_shape);
+}
+
+static res_T
create_plane
(struct solstice* solstice,
const double transform[12],
@@ -503,6 +526,9 @@ create_shaded_shape
res = create_parabolic_cylinder
(solstice, transform, shape->data.parabol, ssol_shape);
break;
+ case SOLPARSER_SHAPE_HYPERBOL:
+ res = create_hyperbol(solstice, transform, shape->data.hyperbol, ssol_shape);
+ break;
case SOLPARSER_SHAPE_PLANE:
res = create_plane(solstice, transform, shape->data.plane, ssol_shape);
break;
diff --git a/src/test_solstice_simulation.c b/src/test_solstice_simulation.c
@@ -0,0 +1,327 @@
+/* Copyright (C) CNRS 2016-2017
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#define _POSIX_C_SOURCE 200809L /* mkstemp support */
+
+#include <rsys/rsys.h>
+#include <rsys/math.h>
+
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef COMPILER_CL
+ /* Wrap POSIX functions and constants */
+ #include <io.h>
+ #define fdopen _fdopen
+#endif
+
+enum side {
+ FRONT,
+ BACK
+};
+
+enum result_type {
+ FRONT_INTEGRATED_IRRADIANCE,
+ BACK_INTEGRATED_IRRADIANCE,
+ FRONT_REFLECTIVITY_LOSS,
+ BACK_REFLECTIVITY_LOSS,
+ FRONT_ABSORPTIVITY_LOSS,
+ BACK_ABSORPTIVITY_LOSS,
+ FRONT_COS_LOSS,
+ BACK_COS_LOSS,
+ FRONT_EFFICIENCY,
+ BACK_EFFICIENCY,
+ MAX_RESULTS_COUNT__
+};
+
+#define MAX_LINE_LEN 2048
+
+static const char
+sundir_header [] = "#--- Sun direction:";
+
+#define IS_NEW_BLOCK(Line, Header) (!strncmp((Line), (Header), strlen(Header)))
+
+static int
+read_line(char* line, size_t max_line_len, FILE* stream)
+{
+ ASSERT(stream && line && max_line_len);
+ line = fgets(line, (int)max_line_len, stream);
+ if(!line) return 0;
+ CHECK(strlen(line) + 1 < max_line_len, 1);
+ return 1;
+}
+
+static void
+get_dir_and_counts
+ (FILE* ref_file,
+ double angles[2],
+ unsigned long* recv_count,
+ unsigned long* realisation_count)
+{
+ char line[MAX_LINE_LEN];
+ int n;
+
+ NCHECK(ref_file, NULL);
+ NCHECK(angles, NULL);
+ NCHECK(recv_count, NULL);
+ NCHECK(realisation_count, NULL);
+
+ /* Get sun dir */
+ CHECK(read_line(line, sizeof(line), ref_file), 1);
+ CHECK(IS_NEW_BLOCK(line, sundir_header), 1);
+ n = sscanf(line+strlen(sundir_header), "%lg%lg", &angles[0], &angles[1]);
+ CHECK(n, 2);
+
+ /* Get #receivers and #realisations */
+ CHECK(read_line(line, sizeof(line), ref_file), 1);
+ n = sscanf(line, "%lu%lu", recv_count, realisation_count);
+ CHECK(n, 2);
+}
+
+static void
+read_recv(const char* line, char name[], double E[], double SE[])
+{
+ int n;
+
+ NCHECK(line, NULL);
+ NCHECK(name, NULL);
+ NCHECK(E, NULL);
+ NCHECK(SE, NULL);
+
+ n = sscanf(line,
+ "%s%*u%lg%lg%lg%lg%lg%lg%lg%lg%lg%lg%lg%lg%lg%lg%lg%lg%lg%lg%lg%lg",
+ name,
+ &E[FRONT_INTEGRATED_IRRADIANCE], &SE[FRONT_INTEGRATED_IRRADIANCE],
+ &E[BACK_INTEGRATED_IRRADIANCE], &SE[BACK_INTEGRATED_IRRADIANCE],
+ &E[FRONT_REFLECTIVITY_LOSS], &SE[FRONT_REFLECTIVITY_LOSS],
+ &E[BACK_REFLECTIVITY_LOSS], &SE[BACK_REFLECTIVITY_LOSS],
+ &E[FRONT_ABSORPTIVITY_LOSS], &SE[FRONT_ABSORPTIVITY_LOSS],
+ &E[BACK_ABSORPTIVITY_LOSS], &SE[BACK_ABSORPTIVITY_LOSS],
+ &E[FRONT_COS_LOSS], &SE[FRONT_COS_LOSS],
+ &E[BACK_COS_LOSS], &SE[BACK_COS_LOSS],
+ &E[FRONT_EFFICIENCY], &SE[FRONT_EFFICIENCY],
+ &E[BACK_EFFICIENCY], &SE[BACK_EFFICIENCY]);
+
+ CHECK(n, 2*MAX_RESULTS_COUNT__+1);
+}
+
+#define POSITIVE_OR_M_ONE(x) ((x) == -1 || (x) >= 0)
+
+static FINLINE int
+is_compatible_with
+ (const double ref_E,
+ const double ref_SE,
+ const double test_E,
+ const double test_SE)
+{
+ double SE;
+
+ CHECK(POSITIVE_OR_M_ONE(ref_E), 1);
+ CHECK(POSITIVE_OR_M_ONE(ref_SE), 1);
+ CHECK(POSITIVE_OR_M_ONE(test_E), 1);
+ CHECK(POSITIVE_OR_M_ONE(test_SE), 1);
+
+ if(ref_E == -1) {
+ CHECK(ref_SE, -1);
+ return (test_E == -1 && test_SE == -1);
+ }
+
+ NCHECK(ref_SE, -1);
+ SE = ref_SE > 0 ? 2 * ref_SE : (ref_E > 0 ? ref_E * 1e-6 : 1e-6);
+ return (fabs(ref_E - test_E) <= SE && test_SE <= SE);
+}
+
+static void
+check_1_reference
+ (FILE* tested_file,
+ const char* rcv_name,
+ const double* reference_E,
+ const double* reference_SE)
+{
+ double a[2];
+ size_t c1, c2;
+ int found = 0;
+
+ NCHECK(tested_file, NULL);
+ NCHECK(rcv_name, NULL);
+ NCHECK(reference_E, NULL);
+ NCHECK(reference_SE, NULL);
+
+ get_dir_and_counts(tested_file, a, &c1, &c2); /* Skip headers */
+
+ while(!feof(tested_file) && !found) {
+ char line[MAX_LINE_LEN];
+ char tested_rcv_name[MAX_LINE_LEN];
+ double tested_E[MAX_RESULTS_COUNT__], tested_SE[MAX_RESULTS_COUNT__];
+ enum result_type r;
+
+ CHECK(read_line(line, sizeof(line), tested_file), 1);
+
+ read_recv(line, tested_rcv_name, tested_E, tested_SE);
+ if(strcmp(rcv_name, tested_rcv_name)) continue;
+
+ FOR_EACH(r, FRONT_INTEGRATED_IRRADIANCE, MAX_RESULTS_COUNT__) {
+ CHECK(is_compatible_with
+ (reference_E[r], reference_SE[r], tested_E[r], tested_SE[r]), 1);
+ }
+ found = 1;
+ }
+ CHECK(found, 1);
+}
+
+static void
+check_1_global
+ (FILE* tested_file,
+ const double reference_E,
+ const double reference_SE,
+ const unsigned rank)
+{
+ char line[MAX_LINE_LEN];
+ double a[2];
+ size_t recv_count, r2;
+ unsigned i;
+ int nb;
+ double tested_E, tested_SE;
+
+ get_dir_and_counts(tested_file, a, &recv_count, &r2);
+
+ /* Skip receivers */
+ while(recv_count--) CHECK(read_line(line, sizeof(line), tested_file), 1);
+
+ /* Read the rank th global data */
+ FOR_EACH(i, 0, rank+1) CHECK(read_line(line, sizeof(line), tested_file), 1);
+
+ nb = sscanf(line, "%lg%lg", &tested_E, &tested_SE);
+ CHECK(nb, 2);
+ CHECK(is_compatible_with(reference_E, reference_SE, tested_E, tested_SE), 1);
+}
+
+static void
+check_references(FILE* ref_file, FILE* tested_file)
+{
+ char line[MAX_LINE_LEN];
+ unsigned nb_global = 0;
+ fpos_t pos;
+
+ NCHECK(ref_file, NULL);
+ NCHECK(tested_file, NULL);
+
+ CHECK(fgetpos(ref_file, &pos), 0);
+ while(read_line(line, sizeof(line), ref_file)) {
+ double val, std;
+ int nb = 0;
+
+ if(IS_NEW_BLOCK(line, sundir_header)) {
+ /* Keep the header as a part of the following block */
+ CHECK(fsetpos(ref_file, &pos), 0);
+ break;
+ }
+
+ nb = sscanf(line, "%lg%lg", &val, &std);
+ CHECK(nb == 0 || nb == 2, 1);
+
+ rewind(tested_file);
+ if(nb != 0) {
+ check_1_global(tested_file, val, std, nb_global);
+ nb_global++;
+ } else {
+ char ref_name[MAX_LINE_LEN];
+ double reference_E[MAX_RESULTS_COUNT__];
+ double reference_SE[MAX_RESULTS_COUNT__];
+ read_recv(line, ref_name, reference_E, reference_SE);
+ check_1_reference(tested_file, ref_name, reference_E, reference_SE);
+ }
+
+ CHECK(fgetpos(ref_file, &pos), 0);
+ }
+}
+
+static FINLINE int
+create_tmp_file_name(char* name, const size_t max_sizeof_name)
+{
+ const char* template = "solstice_tmp_file_XXXXXX";
+ int fd;
+ NCHECK(name, NULL);
+ CHECK(strlen(template)+1 <= max_sizeof_name-1, 1);
+ strcpy(name, template);
+ fd = mkstemp(name);
+ NCHECK(fd, -1);
+ return fd;
+}
+
+static void
+do_check(const char* binary, const char* dir, const char* base_name)
+{
+ char ref_file_name[128];
+ FILE* ref_file;
+ unsigned long c1, realisation_count;
+ int n;
+ ASSERT(base_name);
+
+ n = snprintf(ref_file_name, sizeof(ref_file_name), "%s%s.ref", dir, base_name);
+ CHECK((size_t)n < sizeof(ref_file_name), 1);
+
+ ref_file = fopen(ref_file_name, "r");
+ NCHECK(ref_file, NULL);
+
+ while(!feof(ref_file)) {
+ char cmd[512];
+ char tested_file_name[128];
+ double sun_angles[2];
+ FILE* fp = NULL;
+ int fd = -1;
+
+ get_dir_and_counts(ref_file, sun_angles, &c1, &realisation_count);
+
+ fd = create_tmp_file_name(tested_file_name, sizeof(tested_file_name));
+ fp = fdopen(fd, "r");
+ NCHECK(fp, NULL);
+
+ n = snprintf(cmd, sizeof(cmd),
+ "%s -o %s -f -D %g,%g -n %lu -R %s%s_receiver.yaml %s%s.yaml",
+ binary, tested_file_name, SPLIT2(sun_angles), realisation_count,
+ dir, base_name, dir, base_name);
+ CHECK((unsigned)n < sizeof(cmd), 1);
+
+ CHECK(system(cmd), RES_OK);
+
+ check_references(ref_file, fp);
+
+ fclose(fp);
+ remove(tested_file_name);
+ }
+}
+
+int
+main(int argc, char** argv)
+{
+ int err = 0;
+
+ if(argc != 4) {
+ printf("Usage: %s <solstice-binary> <file-path> <file-base-name>\n", argv[0]);
+ goto error;
+ }
+
+ do_check(argv[1], argv[2], argv[3]);
+
+exit:
+ return err;
+error:
+ err = 1;
+ goto exit;
+}
+
diff --git a/yaml/beam_down.ref b/yaml/beam_down.ref
@@ -0,0 +1,12 @@
+#--- Sun direction: 0 90 (-3.7494e-33 -6.12323e-17 -1)
+2 10000
+tower.secondary.hyperbol 10 465.464 0.00509812 0 0 0 0 0 0 0 0 0 0 34.5362 0.00509812 0 0 0.930847 1.01954e-05 0 0
+tower.receptor 14 465.464 0.00509812 -1 -1 0 0 -1 -1 0 0 -1 -1 34.5362 0.00509812 -1 -1 0.930847 1.01954e-05 -1 -1
+0 0
+0 0
+#--- Sun direction: 50 50 (-0.413176 -0.492404 -0.766044)
+2 10000
+tower.secondary.hyperbol 10 400.231 0.107226 0 0 0 0 0 0 0 0 0 0 99.7686 0.107226 0 0 0.800393 0.000214433 0 0
+tower.receptor 14 136.51 1.90718 -1 -1 0 0 -1 -1 0 0 -1 -1 32.9896 0.464742 -1 -1 0.272997 0.00381404 -1 -1
+0 0
+0 0
diff --git a/yaml/beam_down.yaml b/yaml/beam_down.yaml
@@ -0,0 +1,108 @@
+# Debug/solstice -D 90,90 -R ../yaml/beam_down_receiver.yaml ../yaml/beam_down.yaml
+# Debug/solstice -D 90,90 -r pos=-100,-100,50:tgt=0,0,50:up=0,0,1:img=1000x800 -o ../yaml/beam_down.ppm -f ../yaml/beam_down.yaml
+#
+# 1 10000
+# tower.receptor 14 465.464 0.00509812 -1 -1 0 0 -1 -1 0 0 -1 -1 34.5362 0.00509812 -1 -1 0.930847 1.01954e-05 -1 -1
+# 0 0
+# 0 0
+# --- Sun direction: -3.7494e-33 -6.12323e-17 -1
+
+- sun: &sun { dni: 1, spectrum: [{wavelength: 1, data: 1}] }
+
+- material: &mirror { mirror: { reflectivity: 1, roughness: 0 } }
+- material: &black { matte: { reflectivity: 0 } }
+- material: &virtual { virtual: }
+
+- template: &hyperbol
+ name: hyperbol
+ primary: 0
+ geometry:
+ - hyperbol:
+ focals: &hyperbol_focals { real: 100, image: 20 }
+ clip:
+ - operation: AND
+ #vertices: [[-25, -25], [-25, 25], [25, 25], [25, -25]]
+ vertices: [[-5, 0], [20, -10], [35, 0], [20, 10]]
+ material: { front: *mirror, back: *virtual }
+ anchors:
+ - name: image_point
+ hyperboloid_image_focals: *hyperbol_focals
+
+- geometry: &target
+ - plane:
+ clip:
+ - operation: AND
+ vertices: [[-2.5, -2.5], [-2.5, 2.5], [2.5, 2.5], [2.5, -2.5]]
+ #vertices: [[-1, -1], [-1, 1], [1, 1], [1, -1]]
+ #vertices: [[-.5, -.5], [-.5, .5], [.5, .5], [.5, -.5]]
+ #vertices: [[-.1, -.1], [-.1, .1], [.1, .1], [.1, -.1]]
+ material: *black
+
+- geometry: &primary150
+ - parabol:
+ focal: 150
+ clip:
+ - operation: AND
+ vertices: [[-5, -5], [-5, 5], [5, 5], [5, -5]]
+ #vertices: [[-3, -3], [-3, 3], [3, 3], [3, -3]]
+ #vertices: [[-2, -2], [-2, 2], [2, 2], [2, -2]]
+ #vertices: [[-1, -1], [-1, 1], [1, 1], [1, -1]]
+ #vertices: [[-.01, -.01], [-.01, .01], [.01, .01], [.01, -.01]]
+ material: *mirror
+
+- template: &temp_heliostat150
+ name: "temp-heliostat150"
+ primary: 0
+ geometry:
+ - cylinder: { radius: 0.3, height: 10 }
+ transform: { translation: [0, 0, 5] }
+ material: *black
+ children:
+ - name: "pivot"
+ transform: { translation: [0, 0, 10] }
+ zx_pivot:
+ spacing: 1
+ target: { anchor: tower.secondary.hyperbol.image_point }
+ children:
+ - name: "reflector"
+ transform: { rotation: [-90, 0, 0] }
+ primary: 1
+ geometry: *primary150
+
+- entity:
+ name: "tower"
+ children:
+ - name: secondary
+ children: [ *hyperbol ]
+ transform: { translation: [ 0, 0, 100 ] }
+ - name: receptor
+ geometry: *target
+ primary: 0
+ - name: "building"
+ primary: 0
+ geometry:
+ - cylinder: { radius: 1, height: 110 }
+ transform: { translation: [-4, 0, 55] }
+ material: *black
+
+- entity:
+ name: "heliostat1"
+ transform: { translation: [100, -30, 0] }
+ children: [ *temp_heliostat150 ]
+- entity:
+ name: "heliostat2"
+ transform: { translation: [101, -15, 0] }
+ children: [ *temp_heliostat150 ]
+- entity:
+ name: "heliostat3"
+ transform: { translation: [102, 0, 0] }
+ children: [ *temp_heliostat150 ]
+- entity:
+ name: "heliostat4"
+ transform: { translation: [101, 15, 0] }
+ children: [ *temp_heliostat150 ]
+- entity:
+ name: "heliostat5"
+ transform: { translation: [100, 30, 0] }
+ children: [ *temp_heliostat150 ]
+
+\ No newline at end of file
diff --git a/yaml/beam_down_receiver.yaml b/yaml/beam_down_receiver.yaml
@@ -0,0 +1,2 @@
+- { name: "tower.receptor", side: FRONT }
+- { name: "tower.secondary.hyperbol" }
+\ No newline at end of file
diff --git a/yaml/test01.ref b/yaml/test01.ref
@@ -0,0 +1,5 @@
+#--- Sun direction: 0 90 (-6.12323e-17 -0 -1)
+1 10000
+square_receiver 2 -1 -1 1 0 -1 -1 0 0 -1 -1 0 0 -1 -1 0 0 -1 -1 1 0
+0 0
+0 0
diff --git a/yaml/test01.yaml b/yaml/test01.yaml
@@ -0,0 +1,50 @@
+- sun: &sun
+ dni: 1
+ spectrum: [{wavelength: 1, data: 1}]
+
+- material: &specular
+ front:
+ mirror: { reflectivity: 1, roughness: 0 }
+ back:
+ mirror: { reflectivity: 1, roughness: 0 }
+
+
+- geometry: &small_square
+ - material: *specular
+ plane:
+ clip:
+ - operation: AND
+ vertices:
+ - [-0.50, -0.50]
+ - [-0.50, 0.50]
+ - [0.50, 0.50]
+ - [0.50, -0.50]
+
+- geometry: &big_square
+ - material: { virtual: }
+ plane:
+ clip:
+ - operation: AND
+ vertices:
+ - [-5.00, -5.00]
+ - [-5.00, 5.00]
+ - [5.00, 5.00]
+ - [5.00, -5.00]
+
+
+- entity:
+ name: "reflector"
+ primary: 1
+ transform: { rotation: [0, 0, 0], translation: [0, 0, 0] }
+ geometry: *small_square
+
+
+
+- entity:
+ name: "square_receiver"
+ primary: 0
+ transform: { rotation: [0, 0, 0], translation: [0, 0, 2] }
+ geometry: *big_square
+
+
+
diff --git a/yaml/test01_receiver.yaml b/yaml/test01_receiver.yaml
@@ -0,0 +1 @@
+- { name: "square_receiver", side: BACK }
diff --git a/yaml/test02.ref b/yaml/test02.ref
@@ -0,0 +1,5 @@
+#--- Sun direction: 0 90 (-6.12323e-17 -0 -1)
+1 100000
+square_receiver 2 -1 -1 1 0.0313065 -1 -1 0 0 -1 -1 0 0 -1 -1 0 0 -1 -1 0.01003 0.000315109
+0 0
+99 0.0313065
diff --git a/yaml/test02.yaml b/yaml/test02.yaml
@@ -0,0 +1,47 @@
+- sun: &sun
+ dni: 1
+ spectrum: [{wavelength: 1, data: 1}]
+
+- material: &specular
+ mirror: { reflectivity: 1, roughness: 0 }
+
+
+- geometry: &small_square
+ - material: { virtual: }
+ plane:
+ clip:
+ - operation: AND
+ vertices:
+ - [-0.50, -0.50]
+ - [-0.50, 0.50]
+ - [0.50, 0.50]
+ - [0.50, -0.50]
+
+- geometry: &big_square
+ - material: *specular
+ plane:
+ clip:
+ - operation: AND
+ vertices:
+ - [-5.00, -5.00]
+ - [-5.00, 5.00]
+ - [5.00, 5.00]
+ - [5.00, -5.00]
+
+
+- entity:
+ name: "reflector"
+ primary: 1
+ transform: { rotation: [0, 0, 0], translation: [0, 0, 0] }
+ geometry: *big_square
+
+
+
+- entity:
+ name: "square_receiver"
+ primary: 0
+ transform: { rotation: [0, 0, 0], translation: [0, 0, 2] }
+ geometry: *small_square
+
+
+
diff --git a/yaml/test02_receiver.yaml b/yaml/test02_receiver.yaml
@@ -0,0 +1 @@
+- { name: "square_receiver", side: BACK }
diff --git a/yaml/test03.ref b/yaml/test03.ref
@@ -0,0 +1,5 @@
+#--- Sun direction: 0 45 (-0.707107 -0 -0.707107)
+1 10000
+square_receiver 2 -1 -1 0.707107 0 -1 -1 0 0 -1 -1 0 0 -1 -1 0.292893 0 -1 -1 0.707107 0
+0 0
+0 0
diff --git a/yaml/test03.yaml b/yaml/test03.yaml
@@ -0,0 +1,49 @@
+- sun: &sun
+ dni: 1
+ spectrum: [{wavelength: 1, data: 1}]
+
+- material: &specular
+ front:
+ mirror: { reflectivity: 1, roughness: 0 }
+ back:
+ mirror: { reflectivity: 1, roughness: 0 }
+
+- geometry: &small_square
+ - material: *specular
+ plane:
+ clip:
+ - operation: AND
+ vertices:
+ - [-0.50, -0.50]
+ - [-0.50, 0.50]
+ - [0.50, 0.50]
+ - [0.50, -0.50]
+
+- geometry: &big_square
+ - material: { virtual: }
+ plane:
+ clip:
+ - operation: AND
+ vertices:
+ - [-5.00, -5.00]
+ - [-5.00, 5.00]
+ - [5.00, 5.00]
+ - [5.00, -5.00]
+
+
+- entity:
+ name: "reflector"
+ primary: 1
+ transform: { rotation: [0, 0, 0], translation: [0, 0, 0] }
+ geometry: *small_square
+
+
+
+- entity:
+ name: "square_receiver"
+ primary: 0
+ transform: { rotation: [0, 0, 0], translation: [-2, 0, 2] }
+ geometry: *big_square
+
+
+
diff --git a/yaml/test03_receiver.yaml b/yaml/test03_receiver.yaml
@@ -0,0 +1 @@
+- { name: "square_receiver", side: BACK }
diff --git a/yaml/test04.ref b/yaml/test04.ref
@@ -0,0 +1,4 @@
+#--- Sun direction: 0 45 (-0.707107 -0 -0.707107)
+1 10000
+square_receiver 2 0 0 0.707107 0 0 0 0 0 0 0 0 0 0 0 0.292893 0 0 0 0.707107 0
+0 0
diff --git a/yaml/test04.yaml b/yaml/test04.yaml
@@ -0,0 +1,52 @@
+- sun: &sun
+ dni: 1
+ spectrum: [{wavelength: 1, data: 1}]
+
+- material: &specular
+ front:
+ mirror: { reflectivity: 1, roughness: 0 }
+ back:
+ mirror: { reflectivity: 1, roughness: 0 }
+
+- material: &black
+ matte: { reflectivity: 0 }
+
+- geometry: &small_square
+ - material: *specular
+ plane:
+ clip:
+ - operation: AND
+ vertices:
+ - [-0.50, -0.50]
+ - [-0.50, 0.50]
+ - [0.50, 0.50]
+ - [0.50, -0.50]
+
+- geometry: &big_square
+ - material: { virtual: }
+ plane:
+ clip:
+ - operation: AND
+ vertices:
+ - [-5.00, -5.00]
+ - [-5.00, 5.00]
+ - [5.00, 5.00]
+ - [5.00, -5.00]
+
+
+- entity:
+ name: "reflector"
+ primary: 1
+ transform: { rotation: [0, 0, 0], translation: [0, 0, 0] }
+ geometry: *small_square
+
+
+
+- entity:
+ name: "square_receiver"
+ primary: 0
+ transform: { rotation: [0, -45, 0], translation: [-2, 0, 2] }
+ geometry: *big_square
+
+
+
diff --git a/yaml/test04_receiver.yaml b/yaml/test04_receiver.yaml
@@ -0,0 +1 @@
+- { name: "square_receiver", side: FRONT_AND_BACK }
diff --git a/yaml/test05.ref b/yaml/test05.ref
@@ -0,0 +1,5 @@
+#--- Sun direction: 0 90 (-6.12323e-17 -0 -1)
+1 10000
+spherical_receiver 2 -1 -1 1 0 -1 -1 0 0 -1 -1 0 0 -1 -1 0 0 -1 -1 1 0
+0 0
+0 0
diff --git a/yaml/test05.yaml b/yaml/test05.yaml
@@ -0,0 +1,44 @@
+- sun: &sun
+ dni: 1
+ spectrum: [{wavelength: 1, data: 1}]
+
+- material: &lambertian
+ front:
+ matte: { reflectivity: 1 }
+ back:
+ matte: { reflectivity: 1 }
+
+- geometry: &small_square
+ - material: *lambertian
+ plane:
+ clip:
+ - operation: AND
+ vertices:
+ - [-0.50, -0.50]
+ - [-0.50, 0.50]
+ - [0.50, 0.50]
+ - [0.50, -0.50]
+
+- geometry: &big_sphere
+ - material: { virtual: }
+ sphere:
+ radius: 2.0
+ slices: 128
+
+
+- entity:
+ name: "reflector"
+ primary: 1
+ transform: { rotation: [0, 0, 0], translation: [0, 0, 0] }
+ geometry: *small_square
+
+
+
+- entity:
+ name: "spherical_receiver"
+ primary: 0
+ transform: { rotation: [0, 0, 0], translation: [0, 0, 0] }
+ geometry: *big_sphere
+
+
+
diff --git a/yaml/test05_receiver.yaml b/yaml/test05_receiver.yaml
@@ -0,0 +1 @@
+- { name: "spherical_receiver", side: BACK }