solstice

Compute collected power and efficiencies of a solar plant
git clone git://git.meso-star.com/solstice.git
Log | Files | Refs | README | LICENSE

commit 61b790042233aab17745d60e6920df097a599820
parent 620f2f62a2213e01f7c334e5ae0c1a8257c82e51
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date:   Mon, 24 Apr 2017 14:31:08 +0200

Merge branch 'feature_contours' into develop

Diffstat:
Mcmake/CMakeLists.txt | 1+
Mdoc/input | 18+++++++++++++++---
Msrc/parser/solparser_geometry.c | 91++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
Msrc/parser/solparser_shape.h | 12++++++++++++
Msrc/parser/test_solparser3.c | 2+-
Msrc/parser/test_solparser6.c | 15+++++++++++++--
Msrc/parser/yaml/test_ko_0.yaml | 87+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
Msrc/parser/yaml/test_ok_6.yaml | 26++++++++++++++++++++++++--
Msrc/solstice_object.c | 29+++++++++++++++++++++++++----
Ayaml/test08.ref | 12++++++++++++
Ayaml/test08.yaml | 40++++++++++++++++++++++++++++++++++++++++
Ayaml/test08_receiver.yaml | 1+
12 files changed, 317 insertions(+), 17 deletions(-)

diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt @@ -157,6 +157,7 @@ if(NOT NO_TEST) add_test_simulation(test05) add_test_simulation(test06) add_test_simulation(test07) + add_test_simulation(test08) endif() diff --git a/doc/input b/doc/input @@ -146,7 +146,7 @@ cylinder: height: REAL # in ]0, INF) radius: REAL # in ]0, INF) -[ slices: INTEGER # in [4, 4096]. Default 32 ] +[ slices: INTEGER # in [4, 4096]. Default 16 ] [ stacks: INTEGER # in [1, 4096]. Default 1 ] <obj> ::= @@ -197,12 +197,12 @@ <plane> ::= plane: clip: <polyclip-list> -[ slices: INTEGER ] # in [1, 4096). Default 1 +[ slices: INTEGER # in [1, 4096). Default 1 ] <sphere> ::= sphere: radius: REAL # in ]0, INF) -[ slices: INTEGER # in [4, 4096). Default 32 ] +[ slices: INTEGER # in [4, 4096). Default 16 ] [ stacks: INTEGER # in [2, 4096]. Default slices/2 ] <stl> ::= @@ -216,8 +216,20 @@ <polyclip> ::= operation: <AND|SUB> + <contour-descriptor> + +<contour-descriptor> ::= + <vertices-descriptor> + | <circle-descriptor> + +<vertices-descriptor> ::= vertices: <vertices-list> +<circle-descriptor> ::= + circle: + radius: REAL # in ]0, INF) +[ segments: INTEGER # in [3, 4096). Default 64 ] + <vertices-list> ::= - <real2> - <real2> diff --git a/src/parser/solparser_geometry.c b/src/parser/solparser_geometry.c @@ -100,13 +100,92 @@ error: } static res_T +parse_circle + (struct solparser* parser, + yaml_document_t* doc, + const yaml_node_t* circle, + struct solparser_circleclip* clip) +{ + enum { RADIUS, SEGMENTS }; + intptr_t i, n; + int mask = 0; /* Register the parsed attributes */ + res_T res = RES_OK; + ASSERT(doc && circle && clip); + + if(circle->type != YAML_MAPPING_NODE) { + log_err(parser, circle, + "expect a mapping of clipping circles parameters.\n"); + res = RES_BAD_ARG; + goto error; + } + + n = circle->data.mapping.pairs.top - circle->data.mapping.pairs.start; + clip->segments = 64; /* default value */ + FOR_EACH(i, 0, n) { + yaml_node_t* key; + yaml_node_t* val; + + key = yaml_document_get_node(doc, circle->data.mapping.pairs.start[i].key); + val = yaml_document_get_node(doc, circle->data.mapping.pairs.start[i].value); + if (key->type != YAML_SCALAR_NODE) { + log_err(parser, key, "expect a clipping circle parameter.\n"); + res = RES_BAD_ARG; + goto error; + } + + #define SETUP_MASK(Flag, Name) { \ + if(mask & BIT(Flag)) { \ + log_err(parser, key, \ + "the clipping circle parameter `"Name"' is already defined.\n"); \ + res = RES_BAD_ARG; \ + goto error; \ + } \ + mask |= BIT(Flag); \ + } (void)0 + if(!strcmp((char*)key->data.scalar.value, "radius")) { + SETUP_MASK(RADIUS, "radius"); + res = parse_real(parser, val, nextafter(0, 1), DBL_MAX, &clip->radius); + } + else if (!strcmp((char*)key->data.scalar.value, "segments")) { + SETUP_MASK(SEGMENTS, "segments"); + res = parse_integer(parser, val, 3, 4096, &clip->segments); + } else { + log_err(parser, key, "unknown clipping circle 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, circle, \ + "the clipping circle parameter `"Name"' is missing.\n"); \ + res = RES_BAD_ARG; \ + goto error; \ + } (void)0 + CHECK_PARAM(RADIUS, "radius"); + #undef CHECK_PARAM + +exit: + return res; +error: + goto exit; +} + +static res_T parse_polyclip (struct solparser* parser, yaml_document_t* doc, const yaml_node_t* polyclip, struct solparser_polyclip* clip) { - enum { OPERATION, VERTICES }; + enum { OPERATION, CONTOUR }; intptr_t i, n; int mask = 0; /* Register the parsed attributes */ res_T res = RES_OK; @@ -145,8 +224,14 @@ parse_polyclip SETUP_MASK(OPERATION, "operation"); res = parse_clip_op(parser, val, &clip->op); } else if(!strcmp((char*)key->data.scalar.value, "vertices")) { - SETUP_MASK(VERTICES, "vertices"); + SETUP_MASK(CONTOUR, "contour"); + clip->contour_type = SOLPARSER_CLIP_CONTOUR_POLY; res = parse_vertices(parser, doc, val, &clip->vertices); + } + else if(!strcmp((char*)key->data.scalar.value, "circle")) { + SETUP_MASK(CONTOUR, "contour"); + clip->contour_type = SOLPARSER_CLIP_CONTOUR_CIRCLE; + res = parse_circle(parser, doc, val, &clip->circle); } else { log_err(parser, key, "unknown clipping polygon parameter `%s'.\n", key->data.scalar.value); @@ -168,7 +253,7 @@ parse_polyclip goto error; \ } (void)0 CHECK_PARAM(OPERATION, "operation"); - CHECK_PARAM(VERTICES, "vertices"); + CHECK_PARAM(CONTOUR, "contour"); #undef CHECK_PARAM exit: diff --git a/src/parser/solparser_shape.h b/src/parser/solparser_shape.h @@ -26,6 +26,11 @@ enum solparser_clip_op { SOLPARSER_CLIP_OP_SUB }; +enum solparser_clip_contour_type { + SOLPARSER_CLIP_CONTOUR_CIRCLE, + SOLPARSER_CLIP_CONTOUR_POLY +}; + enum solparser_shape_type { SOLPARSER_SHAPE_CUBOID, SOLPARSER_SHAPE_CYLINDER, @@ -42,9 +47,16 @@ enum solparser_shape_type { /******************************************************************************* * Clipping polygon ******************************************************************************/ +struct solparser_circleclip { + double radius; + long segments; +}; + struct solparser_polyclip { enum solparser_clip_op op; + enum solparser_clip_contour_type contour_type; struct darray_double vertices; + struct solparser_circleclip circle; }; static INLINE void diff --git a/src/parser/test_solparser3.c b/src/parser/test_solparser3.c @@ -37,7 +37,7 @@ static const char* input[] = { " radius: 100\n", " clip:\n", " - operation : AND\n", - " vertices : [[1, 2],[3, 4],[6, 7]]\n", + " circle: { radius: 4 }\n", " material: *lambertian\n", "- sun: \n", " dni: 1\n", diff --git a/src/parser/test_solparser6.c b/src/parser/test_solparser6.c @@ -71,13 +71,13 @@ main(int argc, char** argv) fprintf(stream, " - plane:\n"); fprintf(stream, " clip :\n"); fprintf(stream, " - operation : AND\n"); - fprintf(stream, " vertices : [[1, 2], [3, 4], [6, 7]]\n"); + fprintf(stream, " circle : { radius: 1, segments: 8 }\n"); fprintf(stream, " material: { ?virtual }\n"); fprintf(stream, " - hemisphere:\n"); fprintf(stream, " radius: 100\n"); fprintf(stream, " clip :\n"); fprintf(stream, " - operation : AND\n"); - fprintf(stream, " vertices : [[1, 2], [3, 4], [6, 7]]\n"); + fprintf(stream, " circle : { radius: 1 }\n"); fprintf(stream, " material: { ?virtual }\n"); rewind(stream); @@ -115,6 +115,7 @@ main(int argc, char** argv) CHECK(darray_polyclip_size_get(&parabol->polyclips), 1); polyclip = darray_polyclip_cdata_get(&parabol->polyclips); CHECK(polyclip->op, SOLPARSER_CLIP_OP_AND); + CHECK(polyclip->contour_type, SOLPARSER_CLIP_CONTOUR_POLY); CHECK(solparser_polyclip_get_vertices_count(polyclip), 3); solparser_polyclip_get_vertex(polyclip, 0, pos); CHECK(pos[0], 1); @@ -146,6 +147,11 @@ main(int argc, char** argv) CHECK(shape->type, SOLPARSER_SHAPE_PLANE); plane = solparser_get_shape_plane(parser, shape->data.plane); CHECK(plane->nslices, 1); /* Default value */ + CHECK(darray_polyclip_size_get(&plane->polyclips), 1); + polyclip = darray_polyclip_cdata_get(&plane->polyclips); + CHECK(polyclip->contour_type, SOLPARSER_CLIP_CONTOUR_CIRCLE); + CHECK(polyclip->circle.radius, 1); + CHECK(polyclip->circle.segments, 8); obj_id = solparser_geometry_get_object(geom, 4); obj = solparser_get_object(parser, obj_id); @@ -154,6 +160,11 @@ main(int argc, char** argv) hemisphere = solparser_get_shape_hemisphere(parser, shape->data.hemisphere);; CHECK(hemisphere->radius, 100); CHECK(hemisphere->nslices, -1); /* Default value: auto */ + CHECK(darray_polyclip_size_get(&hemisphere->polyclips), 1); + polyclip = darray_polyclip_cdata_get(&hemisphere->polyclips); + CHECK(polyclip->contour_type, SOLPARSER_CLIP_CONTOUR_CIRCLE); + CHECK(polyclip->circle.radius, 1); + CHECK(polyclip->circle.segments, 64); /* Default value */ solparser_entity_iterator_next(&it); CHECK(solparser_entity_iterator_eq(&it, &end), 1); diff --git a/src/parser/yaml/test_ko_0.yaml b/src/parser/yaml/test_ko_0.yaml @@ -394,7 +394,20 @@ # # <polyclip> ::= # operation: <AND|SUB> -# vertices: <vertices-list> +# <contour-descriptor> +# +# <contour-descriptor> ::= +# <vertices-descriptor> +# | <circle-descriptor> +# +# <vertices-descriptor> ::= +# vertices: <vertices-list> +# +# <circle-descriptor> ::= +# circle: +# radius: REAL # in ]0, INF) +# [ segments: INTEGER # in [3, 4096). Default 64 ] +# # # <vertices-list> ::= # - <real2> @@ -432,7 +445,7 @@ clip: - operation: dummy --- -# missing vertices parameter +# missing contour parameter - geometry: - plane: clip: @@ -471,6 +484,76 @@ - operation: AND vertices: [ [0, 1, 2], [3, 4], [6, 7] ] --- +# missing circle definition +- geometry: + - plane: + clip: + - circle: +--- +# missing radius value +- geometry: + - plane: + clip: + - circle: { radius: } +--- +# invalid number "dummy" +- geometry: + - plane: + clip: + - operation: AND + circle: { radius: "dummy" } +--- +# invalid number "dummy" +- geometry: + - plane: + clip: + - operation: AND + circle: { segments: "dummy" } +--- +# 0 invalid +- geometry: + - plane: + clip: + - circle: { radius: 0 } +--- +# 2 invalid +- geometry: + - plane: + clip: + - circle: { segments: 2 } +--- +# missing radius +- geometry: + - plane: + clip: + - circle: { segments: 10 } +--- +# 2x radius +- geometry: + - plane: + clip: + - circle: { radius: 1, radius: 1 } +--- +# 2x segments +- geometry: + - plane: + clip: + - circle: { segments: 10, segments: 10 } +--- +# 2x contour +- geometry: + - plane: + clip: + - vertices: [ [1, 2], [3, 4], [6, 7] ] + circle: { radius: 1 } +--- +# 2x operation +- geometry: + - plane: + clip: + - operation: AND + operation: OR +--- # # <cuboid> ::= diff --git a/src/parser/yaml/test_ok_6.yaml b/src/parser/yaml/test_ok_6.yaml @@ -104,5 +104,27 @@ clip: - operation: AND vertices: [[-30.0, -20.0], [-30.0, 20.0], [30.0, 20.0], [30.0, -20.0]] - - +--- +- sun: { dni: 1, spectrum: [{wavelength: 1, data: 1}] } +- entity: + name: entity + primary: 1 + geometry: + - material: { mirror: { reflectivity: 0, roughness: 0.5 } } + hyperbol: + focals: { real: 1, image: 1 } + clip: + - operation: AND + circle: { radius: 1 } +--- +- sun: { dni: 1, spectrum: [{wavelength: 1, data: 1}] } +- entity: + name: entity + primary: 1 + geometry: + - material: { mirror: { reflectivity: 0, roughness: 0.5 } } + hyperbol: + focals: { real: 1, image: 1 } + clip: + - operation: AND + circle: { radius: 1, segments: 32 } diff --git a/src/solstice_object.c b/src/solstice_object.c @@ -108,6 +108,16 @@ solparser_clip_op_to_ssol_clipping_op(const enum solparser_clip_op op) } } +static void +get_circular(const size_t ivert, double position[2], void* ctx) +{ + struct solparser_circleclip* data = (struct solparser_circleclip*)ctx; + const double a = (double)ivert * 2 * PI / (double)data->segments; + ASSERT(ivert < data->segments); + position[0] = data->radius * cos(a); + position[1] = data->radius * sin(a); +} + static res_T create_ssol_shape_mesh (struct solstice* solstice, @@ -353,10 +363,21 @@ create_ssol_shape_punched_surface const struct solparser_polyclip* clip; clip = darray_polyclip_cdata_get(clips) + iclip; - carvings[iclip].get = get_carving_pos; - carvings[iclip].nb_vertices = solparser_polyclip_get_vertices_count(clip); - carvings[iclip].operation = solparser_clip_op_to_ssol_clipping_op(clip->op); - carvings[iclip].context = (void*)clip; + switch(clip->contour_type) { + case SOLPARSER_CLIP_CONTOUR_POLY: + carvings[iclip].get = get_carving_pos; + carvings[iclip].nb_vertices = solparser_polyclip_get_vertices_count(clip); + carvings[iclip].operation = solparser_clip_op_to_ssol_clipping_op(clip->op); + carvings[iclip].context = (void*)clip; + break; + case SOLPARSER_CLIP_CONTOUR_CIRCLE: + carvings[iclip].get = get_circular; + carvings[iclip].nb_vertices = clip->circle.segments; + carvings[iclip].operation = solparser_clip_op_to_ssol_clipping_op(clip->op); + carvings[iclip].context = (void*)&clip->circle; + break; + default: FATAL("Unreachable code.\n"); + } } punched_surf.quadric = quadric; diff --git a/yaml/test08.ref b/yaml/test08.ref @@ -0,0 +1,12 @@ +#--- Sun direction: 0 63 (-0.45399 -0 -0.891007) +7 1 1 10000 0 +85.5109 0 +0 0 +0.917875 0.000431307 +0 0 +78.4137 2.52319e-08 +0 0 +0 0 +reflector.pivot.small_square 6 1 FRONT: -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 BACK: 0 0 78.4137 2.52319e-08 0 0 0 0 0 0 +reflector.pivot.parabol 2 85.5109 10000 0 0 0 0 +6 2 FRONT: -1 -1 -1 -1 -1 -1 -1 -1 BACK: 0 0 78.4137 2.52319e-08 0 0 0 0 diff --git a/yaml/test08.yaml b/yaml/test08.yaml @@ -0,0 +1,40 @@ +- sun: &sun { dni: 1 } + +- material: &lambertian + front: + matte: { reflectivity: 1 } + back: + matte: { reflectivity: 1 } + +- material: &specular + mirror: { reflectivity: 1, roughness: 0 } + +- template: &self_oriented_parabol + name: "pivot" + transform: { translation: [0, 0, 4], rotation: [0, 0, 90] } + x_pivot: + target: { sun: *sun } + children: + - name: "parabol" + primary: 1 + geometry: + - material: *specular + parabol: + focal: 4 + clip: + - operation: AND + circle: { radius: 5 } + - name: "small_square" + transform: { translation: [0, 0, 4] } + primary: 0 + geometry: + - material: { virtual: } + plane: + clip: + - operation: AND + vertices: [ [-0.50, -0.50], [-0.50, 0.50], [0.50, 0.50], [0.50, -0.50] ] + +- entity: + name: "reflector" + transform: { rotation: [0, 0, 0], translation: [0, 0, 0] } + children: [ *self_oriented_parabol ] diff --git a/yaml/test08_receiver.yaml b/yaml/test08_receiver.yaml @@ -0,0 +1 @@ +- { name: "reflector.pivot.small_square", side: BACK }