commit bc9f037f22b3f5ac05a73426b2d5c3eddf89881f
parent 92eae8328afc2a958a22515e161c83af061b9c26
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date: Mon, 6 Mar 2017 19:11:16 +0100
First commit; not tested on Linux yet.
Diffstat:
10 files changed, 606 insertions(+), 6 deletions(-)
diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt
@@ -59,6 +59,7 @@ include_directories(
################################################################################
add_subdirectory(parser)
add_subdirectory(receivers)
+add_subdirectory(test_model)
################################################################################
# Generate files
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/test_model/CMakeLists.txt b/cmake/test_model/CMakeLists.txt
@@ -0,0 +1,52 @@
+# 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/>.
+
+cmake_minimum_required(VERSION 2.8)
+project(test_model C)
+
+set(TESTMODEL_SOURCE_DIR ${PROJECT_SOURCE_DIR}/../../src/test_model)
+
+################################################################################
+# Define include directories
+################################################################################
+include_directories(
+ ${LibYAML_INCLUDE_DIR}
+ ${RSys_INCLUDE_DIR}
+ ${TESTMODEL_SOURCE_DIR}/../)
+
+################################################################################
+# Configure and define targets
+################################################################################
+set(TESTMODEL_FILES_SRC
+ test_model.c)
+
+# Prepend each file in the `TESTMODEL_FILES_<SRC|INC>' list by `TESTMODEL_SOURCE_DIR'
+rcmake_prepend_path(TESTMODEL_FILES_SRC ${TESTMODEL_SOURCE_DIR})
+
+if(CMAKE_COMPILER_IS_GNUCC)
+ set(MATH_LIB m)
+endif()
+
+add_executable(test_model ${TESTMODEL_FILES_SRC})
+
+################################################################################
+# Tests
+################################################################################
+if(NOT NO_TEST)
+ add_test(test_beam_down test_model beam_down)
+
+ rcmake_copy_runtime_libraries(test_model)
+
+endif()
diff --git a/src/solstice.c b/src/solstice.c
@@ -306,11 +306,11 @@ static res_T
setup_sun_dirs(struct solstice* solstice, const struct solstice_args* args)
{
double* sun_dirs = NULL;
- size_t i;
+ size_t i, ii;
res_T res = RES_OK;
ASSERT(solstice && args);
- res = darray_double_resize(&solstice->sun_dirs, args->nsun_dirs*3/*#dims*/);
+ res = darray_double_resize(&solstice->sun_dirs, (args->nsun_dirs + args->nsun_dirs3)*3/*#dims*/);
if(res != RES_OK) {
fprintf(stderr,
"Could not reserve the list of %lu sun directions.\n",
@@ -323,6 +323,9 @@ setup_sun_dirs(struct solstice* solstice, const struct solstice_args* args)
FOR_EACH(i, 0, args->nsun_dirs) {
spherical_to_cartesian_sun_dir(args->sun_dirs + i, sun_dirs + i*3/*#dims*/);
}
+ FOR_EACH(ii, 0, args->nsun_dirs3) {
+ d3_normalize(sun_dirs + (i + ii) * 3/*#dims*/, &args->sun_dirs3[ii].x);
+ }
exit:
return res;
@@ -664,6 +667,7 @@ 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\n", SPLIT3(sun_dir));
res = solstice_update_entities(solstice, sun_dir);
if(res != RES_OK) goto error;
@@ -683,7 +687,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_args.c b/src/solstice_args.c
@@ -44,6 +44,8 @@ print_help(const char* program)
printf(
" -D <dirs> list of sun directions.\n");
printf(
+" -3 <dir> sun direction.\n");
+ printf(
" -f do not prompt before overwriting the output file submitted\n"
" with the '-o' option.\n");
printf(
@@ -162,6 +164,57 @@ error:
}
static res_T
+parse_sun_dir3(const char* str, struct solstice_args* args)
+{
+ char buf[512];
+ char* tk;
+ char* ctx;
+ size_t len;
+ res_T res = RES_OK;
+ ASSERT(str && args);
+
+ if (strlen(str) >= sizeof(buf) - 1/*NULL char*/) {
+ fprintf(stderr,
+ "Could not duplicate the list of sun directions `%s'.\n", str);
+ res = RES_MEM_ERR;
+ goto error;
+ }
+ strncpy(buf, str, sizeof(buf));
+
+ tk = strtok_r(buf, ":", &ctx);
+ while (tk) {
+ struct solstice_args_dir3 tmp;
+
+ res = cstr_to_list_double(tk, ',', &tmp.x, &len, 3);
+ if (res == RES_OK && len != 3) res = RES_BAD_ARG;
+ if (res != RES_OK) {
+ fprintf(stderr, "Invalid sun direction `%s'.\n", tk);
+ goto error;
+ }
+
+ if (tmp.x == 0 && tmp.y == 0 && tmp.z == 0) {
+ fprintf(stderr, "Invalid 0,0,0 sun direction.\n");
+ res = RES_BAD_ARG;
+ goto error;
+ }
+ sa_push(args->sun_dirs3, tmp);
+
+ tk = strtok_r(NULL, ":", &ctx);
+ }
+ args->nsun_dirs3 += sa_size(args->sun_dirs3);
+
+exit:
+ return res;
+error:
+ if (args->sun_dirs3) {
+ sa_release(args->sun_dirs3);
+ args->sun_dirs3 = NULL;
+ args->nsun_dirs3 = 0;
+ }
+ goto exit;
+}
+
+static res_T
parse_image_definition
(const char* str,
unsigned long* width,
@@ -438,11 +491,14 @@ solstice_args_init(struct solstice_args* args, const int argc, char** argv)
*args = SOLSTICE_ARGS_DEFAULT;
optind = 0;
- while((opt = getopt(argc, argv, "D:fg:Hhn:o:qR:r:t:")) != -1) {
+ while((opt = getopt(argc, argv, "D:3:fg:Hhn:o:qR:r:t:")) != -1) {
switch(opt) {
case 'D':
res = parse_sun_dir_list(optarg, args);
break;
+ case '3':
+ res = parse_sun_dir3(optarg, args);
+ break;
case 'f': args->force_overwriting = 1; break;
case 'H': args->output_hits = 1; break;
case 'h':
@@ -476,7 +532,7 @@ solstice_args_init(struct solstice_args* args, const int argc, char** argv)
if(!args->rendering
&& args->dump_format == SOLSTICE_ARGS_DUMP_NONE
- && !args->nsun_dirs) {
+ && 0 == args->nsun_dirs + args->nsun_dirs3) {
fprintf(stderr, "Missing sun direction.\n");
res = RES_BAD_ARG;
goto error;
@@ -505,6 +561,7 @@ solstice_args_release(struct solstice_args* args)
{
ASSERT(args);
sa_release(args->sun_dirs);
+ sa_release(args->sun_dirs3);
*args = SOLSTICE_ARGS_NULL;
}
diff --git a/src/solstice_args.h.in b/src/solstice_args.h.in
@@ -24,6 +24,10 @@ struct solstice_args_spherical {
double elevation; /* In radians */
};
+struct solstice_args_dir3 {
+ double x, y, z;
+};
+
enum solstice_args_dump_format {
SOLSTICE_ARGS_DUMP_OBJ,
SOLSTICE_ARGS_DUMP_NONE
@@ -45,6 +49,8 @@ struct solstice_args {
/* List of sun directions */
struct solstice_args_spherical* sun_dirs;
size_t nsun_dirs;
+ struct solstice_args_dir3* sun_dirs3;
+ size_t nsun_dirs3;
struct {
double pos[3];
@@ -81,6 +87,8 @@ static const struct solstice_args SOLSTICE_ARGS_NULL = SOLSTICE_ARGS_NULL__;
\
NULL, /* sun_dirs */ \
0, /* # nsun_dirs */ \
+ NULL, /* sun_dirs3 */ \
+ 0, /* # nsun_dirs3 */ \
\
{ /* Camera */ \
{ @SOLSTICE_ARGS_DEFAULT_CAMERA_POS@ }, \
diff --git a/src/test_model/test_model.c b/src/test_model/test_model.c
@@ -0,0 +1,364 @@
+/* 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/>. */
+
+#include <rsys/rsys.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+
+#ifdef COMPILER_CL
+ /* Wrap POSIX functions and constants */
+ #include <io.h>
+ #define fdopen _fdopen
+ #define fileno _fileno
+ #define execvp _execvp
+#endif
+
+#ifndef COMPILER_CL
+#include <linux/limits.h> /* MAX_PATH */
+#endif
+
+enum side {
+ FRONT,
+ BACK
+};
+
+enum RESULTS {
+ 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__
+};
+
+static int
+file_exists(const char* name)
+{
+ FILE* f = fopen(name, "r");
+ if (!f) return 0;
+ fclose(f);
+ return 1;
+}
+
+#define MAX_LINE_LEN 2048
+static res_T
+get_dir_and_counts
+ (FILE* ref_file,
+ double sun_dir[3],
+ size_t* recv_count,
+ size_t* realisation_count)
+{
+ const char sundir_header [] = "#--- Sun direction:";
+ char line[MAX_LINE_LEN];
+
+ ASSERT(ref_file);
+ if (!fgets(line, sizeof(line), ref_file)) return RES_BAD_ARG;
+ if (0 != strncmp(line, sundir_header, strlen(sundir_header)))
+ return RES_BAD_ARG;
+ /* get sun dir */
+ if (3 != sscanf(line + strlen(sundir_header),
+ "%lg%lg%lg", &sun_dir[0], &sun_dir[1], &sun_dir[2])) {
+ return RES_BAD_ARG;
+ }
+ /* get sun dir */
+ if (!fgets(line, sizeof(line), ref_file)) return RES_BAD_ARG;
+ if (2 != sscanf(line, "%zu%zu", recv_count, realisation_count))
+ return RES_BAD_ARG;
+ return RES_OK;
+}
+
+#define READ_RECV(Name, Values, Std) \
+{ \
+ if (2 * MAX_RESULTS_COUNT__ + 1 \
+ != sscanf(line, \
+ "%s%*zu%lg%lg%lg%lg%lg%lg%lg%lg%lg%lg%lg%lg%lg%lg%lg%lg%lg%lg%lg%lg", \
+ Name, \
+ &Values[FRONT_INTEGRATED_IRRADIANCE], &Std[FRONT_INTEGRATED_IRRADIANCE], \
+ &Values[BACK_INTEGRATED_IRRADIANCE], &Std[BACK_INTEGRATED_IRRADIANCE], \
+ &Values[FRONT_REFLECTIVITY_LOSS], &Std[FRONT_REFLECTIVITY_LOSS], \
+ &Values[BACK_REFLECTIVITY_LOSS], &Std[BACK_REFLECTIVITY_LOSS], \
+ &Values[FRONT_ABSORPTIVITY_LOSS], &Std[FRONT_ABSORPTIVITY_LOSS], \
+ &Values[BACK_ABSORPTIVITY_LOSS], &Std[BACK_ABSORPTIVITY_LOSS], \
+ &Values[FRONT_COS_LOSS], &Std[FRONT_COS_LOSS], \
+ &Values[BACK_COS_LOSS], &Std[BACK_COS_LOSS], \
+ &Values[FRONT_EFFICIENCY], &Std[FRONT_EFFICIENCY], \
+ &Values[BACK_EFFICIENCY], &Std[BACK_EFFICIENCY]) \
+ ) \
+ { \
+ res = RES_BAD_ARG; \
+ goto error; \
+ } \
+}
+
+#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)
+{
+ ASSERT(POSITIVE_OR_M_ONE(ref_E) && POSITIVE_OR_M_ONE(ref_SE)
+ && POSITIVE_OR_M_ONE(test_E) && POSITIVE_OR_M_ONE(test_SE));
+ if (ref_E == -1) {
+ ASSERT(ref_SE == -1);
+ return (test_E == -1 && test_SE == -1);
+ }
+ ASSERT(ref_SE != -1);
+ return (fabs(ref_E - test_E) <= 2 * ref_SE && test_SE <= 2 * ref_SE);
+}
+
+static res_T
+check_1_reference
+ (const char* tested_file_name,
+ const char* rcv_name,
+ const double* reference_E,
+ const double* reference_SE)
+{
+ res_T res = RES_OK;
+ ASSERT(tested_file_name && rcv_name && reference_E && reference_SE);
+ FILE* tested_file = fopen(tested_file_name, "r");
+ double d[3];
+ size_t c1, c2;
+
+ if (!tested_file) {
+ res = RES_IO_ERR;
+ goto end;
+ }
+ res = get_dir_and_counts(tested_file, d, &c1, &c2); /* skip headers */
+ if (res != RES_OK) goto error;
+ while(!feof(tested_file)) {
+ char line[MAX_LINE_LEN];
+ char tested_rcv_name[MAX_LINE_LEN];
+ double tested_E[MAX_RESULTS_COUNT__], tested_SE[MAX_RESULTS_COUNT__];
+ enum RESULTS r;
+ if (!fgets(line, sizeof(line), tested_file)) {
+ res = RES_BAD_ARG;
+ goto error;
+ }
+ READ_RECV(tested_rcv_name, tested_E, tested_SE);
+ if (strcmp(rcv_name, tested_rcv_name)) continue;
+ for (r = FRONT_INTEGRATED_IRRADIANCE; r < MAX_RESULTS_COUNT__; r++) {
+ if (!is_compatible_with
+ (reference_E[r], reference_SE[r], tested_E[r], tested_SE[r]))
+ {
+ res = RES_BAD_ARG;
+ goto error;
+ }
+ }
+ goto end; /* success */
+ }
+ res = RES_BAD_ARG; /* could not find data */
+end:
+ if (tested_file) fclose(tested_file);
+ return res;
+error:
+ goto end;
+}
+
+static res_T
+check_1_global
+ (const char* tested_file_name,
+ const double reference_E,
+ const double reference_SE,
+ const unsigned rank)
+{
+ res_T res = RES_OK;
+ char line[MAX_LINE_LEN];
+ FILE* tested_file;
+ double d[3];
+ size_t recv_count, r2;
+ unsigned i;
+ int nb;
+ double tested_E, tested_SE;
+
+ ASSERT(tested_file_name);
+ tested_file = fopen(tested_file_name, "r");
+ if (!tested_file) {
+ res = RES_IO_ERR;
+ goto end;
+ }
+ res = get_dir_and_counts(tested_file, d, &recv_count, &r2);
+ if (res != RES_OK) goto error;
+ /* skip receivers */
+ for ( ; recv_count--; ) {
+ if (!fgets(line, sizeof(line), tested_file)) {
+ res = RES_BAD_ARG;
+ goto error;
+ }
+ }
+ /* read the rank th global data */
+ for (i = 0; i <= rank; i++) {
+ if (!fgets(line, sizeof(line), tested_file)) {
+ res = RES_BAD_ARG;
+ goto error;
+ }
+ }
+ nb = sscanf(line, "%lg%lg", &tested_E, &tested_SE);
+ if (nb != 2) {
+ res = RES_BAD_ARG;
+ goto error;
+ }
+ if (!is_compatible_with
+ (reference_E, reference_SE, tested_E, tested_SE)) {
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+end:
+ if (tested_file) fclose(tested_file);
+ return res;
+error:
+ goto end;
+}
+
+
+static res_T
+check_references
+ (FILE* ref_file, const char* tested_file_name)
+{
+ res_T res = RES_OK;
+ char line[MAX_LINE_LEN];
+ int nb_global = 0;
+
+ ASSERT(ref_file && tested_file_name);
+ for ( ; ; ) {
+ int nb = 0;
+ double val, std;
+ if (!fgets(line, sizeof(line), ref_file)) {
+ if (feof(ref_file)) goto end;
+ res = RES_BAD_ARG;
+ goto error;
+ }
+ nb = sscanf(line, "%lg%lg", &val, &std);
+ ASSERT(nb == 0 || nb == 2);
+ if (nb != 0) {
+ res = check_1_global(tested_file_name, val, std, nb_global);
+ if (res != RES_OK) goto error;
+ nb_global++;
+ }
+ else {
+ char ref_name[MAX_LINE_LEN];
+ double reference_E[MAX_RESULTS_COUNT__], reference_SE[MAX_RESULTS_COUNT__];
+ READ_RECV(ref_name, reference_E, reference_SE);
+ res =
+ check_1_reference(tested_file_name, ref_name, reference_E, reference_SE);
+ if (res != RES_OK) goto error;
+ }
+ };
+
+end:
+ CHECK(remove(tested_file_name), 0);
+ return res;
+error:
+ goto end;
+}
+
+static FINLINE res_T
+create_tmp_file_name(char* out_name)
+{
+ ASSERT(out_name);
+#ifdef COMPILER_CL
+ if (tmpnam_s(out_name, L_tmpnam_s)) return RES_IO_ERR;
+#else
+ int fd;
+ strncpy(out_name, "solstice_tmp_file_XXXXXX", L_tmpnam_s);
+ fd = mkstemp(out_name);
+ if (-1 == fd) return RES_IO_ERR;
+ /* just want a name */
+ close(fd);
+#endif
+ return RES_OK;
+}
+
+static res_T
+do_check(const char* base_name)
+{
+ res_T res = RES_OK;
+ FILE* ref_file;
+ char ref_file_name[MAX_PATH];
+ size_t c1, realisation_count;
+
+ ASSERT(base_name);
+ snprintf(ref_file_name, MAX_PATH, "../../yaml/%s.ref", base_name);
+ ref_file = fopen(ref_file_name, "r");
+ if (!ref_file) {
+ res = RES_IO_ERR;
+ printf("Cannot open file '%s'\n", base_name);
+ goto end;
+ }
+ while (!feof(ref_file)) {
+ char cmd[128 + 3 * MAX_PATH];
+ double sun_dir[3];
+ char tested_file_name[L_tmpnam_s];
+#ifdef COMPILER_CL
+ char* exe_name = "..\\Debug\\solstice.exe";
+#else
+ char* exe_name = "../Debug/solstice.exe";
+#endif
+
+ res = get_dir_and_counts(ref_file, sun_dir, &c1, &realisation_count);
+ if (res != RES_OK) goto end;
+
+ res = create_tmp_file_name(tested_file_name);
+ if (res != RES_OK) goto end;
+
+ snprintf(cmd, sizeof(cmd),
+ "%s -o %s -f -3 %lg,%lg,%lg -n %zu -R ../../yaml/%s_receiver.yaml ../../yaml/%s.yaml",
+ exe_name, tested_file_name, SPLIT3(sun_dir), realisation_count, base_name, base_name);
+ if (system(cmd)) {
+ res = RES_BAD_ARG;
+ goto end;
+ }
+ res = check_references(ref_file, tested_file_name);
+ if (res != RES_OK) {
+ goto end;
+ }
+ }
+end:
+ if (ref_file) fclose(ref_file);
+ return res;
+}
+
+/*
+ * FIXME: does not manage multiple sun directions
+ */
+int
+main(int argc, char** argv)
+{
+ int err = 0;
+
+ if (argc != 2) goto usage;
+
+ if (RES_OK != do_check(argv[1]))
+ goto error;
+
+exit:
+ return err;
+usage:
+ printf("Usage: %s <file_base_name>\n", argv[0]);
+error:
+ err = 1;
+ goto exit;
+}
+
diff --git a/yaml/beam_down.ref b/yaml/beam_down.ref
@@ -0,0 +1,5 @@
+#--- Sun direction: -3.7494e-33 -6.12323e-17 -1
+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
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 @@
+- { name: "tower.receptor", side: FRONT }