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 7aae3e6b609c9f22fca6e8155a2547ac5c3b9965
parent 4c50d38e687d57b1fc0b82b60d7133f2a338204b
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date:   Fri, 17 Mar 2017 10:34:28 +0100

Merge remote-tracking branch 'origin/develop' into feature_outputs

Diffstat:
Mcmake/parser/CMakeLists.txt | 4++--
Mdoc/input | 497+++++++++++++++++++++++++++++++++++++++++--------------------------------------
Msrc/parser/solparser.c | 77+++++++++++++++++++++++++++++++++++++++++++----------------------------------
Msrc/parser/solparser_shape.h | 27++++++++++++++++++++-------
Msrc/parser/test_solparser6.c | 34+++++++++++++++++++++++++++++++++-
Msrc/parser/yaml/test_ko_0.yaml | 55+++++++++++++++++++++++++++++++++++++++++++++++++++++--
Asrc/parser/yaml/test_ok_6.yaml | 108+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/solstice.c | 2++
Msrc/solstice_object.c | 33++++++++++++++++++++-------------
Msrc/solstice_solve.c | 171+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
Msrc/test_solstice_simulation.c | 206++++++++++++++++++++++++++++++++++++++++---------------------------------------
11 files changed, 809 insertions(+), 405 deletions(-)

diff --git a/cmake/parser/CMakeLists.txt b/cmake/parser/CMakeLists.txt @@ -68,8 +68,6 @@ if(NOT NO_TEST) endfunction() build_test(test_solparser) - add_test(test_grammar_example test_solparser - ${PROJECT_SOURCE_DIR}/../../doc/input) add_test(test_solparser_ok_0 test_solparser ${SOLPARSER_SOURCE_DIR}/yaml/test_ok_0.yaml) add_test(test_solparser_ok_1 test_solparser @@ -82,6 +80,8 @@ if(NOT NO_TEST) ${SOLPARSER_SOURCE_DIR}/yaml/test_ok_4.yaml) add_test(test_solparser_ok_5 test_solparser ${SOLPARSER_SOURCE_DIR}/yaml/test_ok_5.yaml) + add_test(test_solparser_ok_6 test_solparser + ${SOLPARSER_SOURCE_DIR}/yaml/test_ok_6.yaml) add_test(test_solparser_ko test_solparser -e ${SOLPARSER_SOURCE_DIR}/yaml/test_ko_0.yaml) diff --git a/doc/input b/doc/input @@ -1,6 +1,6 @@ -# -------------------------------------------------------------------------------- -# 1/ Exemple -# -------------------------------------------------------------------------------- +#-------------------------------------------------------------------------------- +# 1/ Example +#-------------------------------------------------------------------------------- # Declare materials - material: &lambertian matte: @@ -77,243 +77,256 @@ transform: { translation: [10, 11, 12] } children: [ *composition ] -# -------------------------------------------------------------------------------- +#-------------------------------------------------------------------------------- # 2/ Grammar -# -------------------------------------------------------------------------------- -# <solar-factory> ::= -# <sun> -# <items> -# -# <items> ::= -# - <item> -# [ - <item> ... ] -# -# <item> ::= -# <geometry> -# | <material> -# | <entity> -# | <template> -# -# ---------------------------------------- -# <geometry> ::= -# geometry: -# - <object> -# [ - <object> ... ] -# -# <object> ::= -# <shape> -# <material> -# [ <transform> ] -# -# <x_pivot> ::= -# x_pivot: -# [ ref_point: <real3>. Default 0,0,0 ] -# <target> -# -# <zx_pivot> ::= -# zx_pivot: -# [ spacing: REAL # in [0, INF). Default 0 ] -# [ ref_point: <real3>. Default 0,0,0 ] -# <target> -# -# <target> ::= -# target: -# anchor: <anchor-identifier> -# | direction: <real3> -# | position: <real3> -# | <sun> -# -# ---------------------------------------- -# <shape> ::= -# <cuboid> -# | <cylinder> -# | <obj> -# | <parabol> -# | <parabolic-cylinder> -# | <hyperbol> -# | <plane> -# | <sphere> -# | <stl> -# -# <cuboid> ::= -# cuboid: -# size: <real3*+> -# -# <cylinder> ::= -# cylinder: -# height: REAL # in ]0, INF) -# radius: REAL # in ]0, INF) -# [ slices: INTEGER ] # in [4, 4096]. Default 16 -# -# <obj> ::= -# obj: -# path: PATH -# -# <parabol> ::= -# parabol: # x^2 + y^2 - 4*focal*z = 0 -# focal: REAL # in ]0, INF) -# clip: <polyclip-list> -# -# <parabolic-cylinder> ::= -# parabolic-cylinder: # y^2 - 4*focal*z = 0 -# 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> -# -# <sphere> ::= -# sphere: -# radius: REAL # in ]0, INF) -# [ slices: INTEGER ] # in [4, 4096]. Default 16 -# -# <stl> ::= -# stl: -# path: PATH -# -# ---------------------------------------- -# <polyclip-list> ::= -# - <polyclip> -# [ - <polyclip> ... ] -# -# <polyclip> ::= -# operation: <AND|SUB> -# vertices: <vertices-list> -# -# <vertices-list> ::= -# - <real2> -# - <real2> -# - <real2> -# [ - <real2> ... ] -# -# ---------------------------------------- -# <material> ::= -# <material-descriptor> | <double-sided-material> -# -# <double-sided-material> ::= -# front: <material-descriptor> -# back: <material-descriptor> -# -# <material-descriptor> ::= -# <mirror> | <matte> | <thin-dielectric> | <virtual> -# -# <mirror> ::= -# mirror: -# reflectivity: REAL # in [0, 1] -# roughness: REAL # in [0, 1] -# -# <matte> ::= -# matte: -# reflectivity: REAL # in [0, 1] -# -# <virtual> ::= -# virtual: EMPTY-STRING -# -# <thin-dielectric> ::= -# thin_dielectric: -# absorption: REAL # in [0, INF) -# thickness: REAL # in [0, INF) -# refractive_index: REAL # in ]0, INF) -# -# ---------------------------------------- -# <entity> ::= -# entity: -# <entity-data> -# -# <template> ::= -# template: -# <entity-data> -# -# <entity-data> ::= -# name: STRING # except "self" -# [ <geometry-data> | <x_pivot> | <zx_pivot> ] -# [ <anchors> ] -# [ <transform> ] -# [ <children> ] -# -# <geometry-data> ::= -# primary: INTEGER # in [0, 1] -# <geometry> -# -# <children> ::= -# children: -# - <entity-data> -# [ - <entity-data> ... ] -# -# <anchors> ::= -# anchors: -# - <anchor-data> -# [ - <anchor-data> ... ] -# -# <anchor-data> ::= -# name: STRING -# <position-description> -# -# <position-description> ::= -# position: <real3> | hyperboloid_image_focals: <hyperboloid_focals> -# -# # "self" references the first level entity -# <entity-identifier> ::= -# <self|STRING>[.STRING ... ] -# -# <anchor-identifier> ::= -# <entity-identifier>.STRING -# -# ---------------------------------------- -# <sun> ::= -# sun: -# dni: REAL # Direct Normal Irradiance in ]0, INF) -# <spectrum> -# [ <radial-angular-distribution> ] -# -# <radial-angular-distribution> ::= -# <pillbox> | <buie> -# -# <buie> ::= -# buie: -# csr: REAL # in [1e-6, 0.849] -# -# <pillbox> ::= -# pillbox: -# aperture: REAL # in ]0, 90] -# -# ---------------------------------------- -# <transform> ::= -# transform: -# translation: <real3> -# rotation: <real3> -# -# <real2> ::= -# - REAL -# - REAL -# -# <real3> ::= -# - REAL -# - REAL -# - REAL -# -# <real3*+> ::= -# - REAL # in ]0, inf) -# - REAL # in ]0, inf) -# - REAL # in ]0, inf) -# -# <spectrum> ::= -# spectrum: -# - <spectrum-data> -# [ - <spectrum-data> ... ] -# -# <spectrum-data> ::= -# wavelength: REAL # in [0, INF) -# data: REAL # in [0, INF) -# +#-------------------------------------------------------------------------------- +<solar-factory> ::= + <sun> + <items> + +<items> ::= + - <item> +[ - <item> ... ] + +<item> ::= + <geometry> + | <material> + | <entity> + | <template> + +#---------------------------------------- +<geometry> ::= + geometry: + - <object> +[ - <object> ... ] + +<object> ::= + <shape> + <material> +[ <transform> ] + +<x_pivot> ::= + x_pivot: +[ ref_point: <real3>. Default 0,0,0 ] + <target> + +<zx_pivot> ::= + zx_pivot: +[ spacing: REAL # in [0, INF). Default 0 ] +[ ref_point: <real3>. Default 0,0,0 ] + <target> + +<target> ::= + target: + anchor: <anchor-identifier> + | direction: <real3> + | position: <real3> + | <sun> + +#---------------------------------------- +<shape> ::= + <cuboid> + | <cylinder> + | <obj> + | <parabol> + | <parabolic-cylinder> + | <hyperbol> + | <plane> + | <sphere> + | <stl> + +<cuboid> ::= + cuboid: + size: <real3*+> + +<cylinder> ::= + cylinder: + height: REAL # in ]0, INF) + radius: REAL # in ]0, INF) +[ slices: INTEGER ] # in [4, 4096]. Default 16 + +<obj> ::= + obj: + path: PATH + +# x^2 + y^2 - 4*focal*z = 0 +<parabol> ::= + parabol: + focal: REAL # in ]0, INF) + clip: <polyclip-list> + # By default slices is automatically compute with respect to the parabol + # curvature +[ slices: INTEGER ] # in [4, 4096) + +<parabolic-cylinder> ::= + parabolic-cylinder: # y^2 - 4*focal*z = 0 + focal: REAL # in ]0, INF) + clip: <polyclip-list> + # By default slices is automatically compute with respect to the hyperbol + # curvature +[ slices: INTEGER ] # in [4, 4096) + +# (x^2 + y^2) / a^2 - (z + z0 - g/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 +<hyperbol> ::= + hyperbol: + focals: <hyperboloid_focals> + clip: <polyclip-list> + # By default slices is automatically compute with respect to the hyperbol + # curvature +[ slices: INTEGER ] # in [4, 4096) + +<hyperboloid_focals> ::= + real: REAL # in ]0, INF) + image: REAL # in ]0, INF) + +<plane> ::= + plane: + clip: <polyclip-list> +[ slices: INTEGER ] # in [1, 4096). Default 1 + +<sphere> ::= + sphere: + radius: REAL # in ]0, INF) +[ slices: INTEGER ] # in [4, 4096]. Default 16 + +<stl> ::= + stl: + path: PATH + +#---------------------------------------- +<polyclip-list> ::= + - <polyclip> +[ - <polyclip> ... ] + +<polyclip> ::= + operation: <AND|SUB> + vertices: <vertices-list> + +<vertices-list> ::= + - <real2> + - <real2> + - <real2> +[ - <real2> ... ] + +#---------------------------------------- +<material> ::= + <material-descriptor> | <double-sided-material> + +<double-sided-material> ::= + front: <material-descriptor> + back: <material-descriptor> + +<material-descriptor> ::= + <mirror> | <matte> | <thin-dielectric> | <virtual> + +<mirror> ::= + mirror: + reflectivity: REAL # in [0, 1] + roughness: REAL # in [0, 1] + +<matte> ::= + matte: + reflectivity: REAL # in [0, 1] + +<virtual> ::= + virtual: EMPTY-STRING + +<thin-dielectric> ::= + thin_dielectric: + absorption: REAL # in [0, INF) + thickness: REAL # in [0, INF) + refractive_index: REAL # in ]0, INF) + +#---------------------------------------- +<entity> ::= + entity: + <entity-data> + +<template> ::= + template: + <entity-data> + +<entity-data> ::= + name: STRING # except "self" +[ <geometry-data> | <x_pivot> | <zx_pivot> ] +[ <anchors> ] +[ <transform> ] +[ <children> ] + +<geometry-data> ::= + primary: INTEGER # in [0, 1] + <geometry> + +<children> ::= + children: + - <entity-data> +[ - <entity-data> ... ] + +<anchors> ::= + anchors: + - <anchor-data> +[ - <anchor-data> ... ] + +<anchor-data> ::= + name: STRING + <position-description> + +<position-description> ::= + position: <real3> | hyperboloid_image_focals: <hyperboloid_focals> + +# "self" references the first level entity +<entity-identifier> ::= + <self|STRING>[.STRING ... ] + +<anchor-identifier> ::= + <entity-identifier>.STRING + +#---------------------------------------- +<sun> ::= + sun: + dni: REAL # Direct Normal Irradiance in ]0, INF) + <spectrum> +[ <radial-angular-distribution> ] + +<radial-angular-distribution> ::= + <pillbox> | <buie> + +<buie> ::= + buie: + csr: REAL # in [1e-6, 0.849] + +<pillbox> ::= + pillbox: + aperture: REAL # in ]0, 90] + +#---------------------------------------- +<transform> ::= + transform: + translation: <real3> + rotation: <real3> + +<real2> ::= + - REAL + - REAL + +<real3> ::= + - REAL + - REAL + - REAL + +<real3*+> ::= + - REAL # in ]0, inf) + - REAL # in ]0, inf) + - REAL # in ]0, inf) + +<spectrum> ::= + spectrum: + - <spectrum-data> +[ - <spectrum-data> ... ] + +<spectrum-data> ::= + wavelength: REAL # in [0, INF) + data: REAL # in [0, INF) + diff --git a/src/parser/solparser.c b/src/parser/solparser.c @@ -1839,7 +1839,7 @@ parse_paraboloid const enum solparser_shape_type type, struct solparser_shape_paraboloid_id* out_ishape) { - enum { CLIP, FOCAL }; + enum { CLIP, FOCAL, SLICES }; struct solparser_shape_paraboloid* shape = NULL; struct darray_paraboloid* paraboloids; const char* name; @@ -1903,6 +1903,9 @@ parse_paraboloid } else if(!strcmp((char*)key->data.scalar.value, "focal")) { SETUP_MASK(FOCAL, "focal"); res = parse_real(parser, val, nextafter(0, 1), DBL_MAX, &shape->focal); + } else if(!strcmp((char*)key->data.scalar.value, "slices")) { + SETUP_MASK(SLICES, "slices"); + res = parse_integer(parser, val, 4, 4096, &shape->nslices); } else { log_err(parser, key, "unknown %s parameter `%s'.\n", name, key->data.scalar.value); @@ -1942,7 +1945,7 @@ parse_focals_description (struct solparser* parser, yaml_document_t* doc, const yaml_node_t* desc, - struct hyperboloid_focals* focals) + struct solparser_hyperboloid_focals* focals) { enum { REAL, IMAGE }; intptr_t i, n; @@ -1950,7 +1953,7 @@ parse_focals_description res_T res = RES_OK; ASSERT(doc && desc && focals); - if (desc->type != YAML_MAPPING_NODE) { + if(desc->type != YAML_MAPPING_NODE) { log_err(parser, desc, "expect a mapping of focal parameters.\n"); res = RES_BAD_ARG; goto error; @@ -1963,7 +1966,7 @@ parse_focals_description 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) { + if(key->type != YAML_SCALAR_NODE) { log_err(parser, key, "expect focal parameters.\n"); res = RES_BAD_ARG; goto error; @@ -1977,15 +1980,14 @@ parse_focals_description } \ mask |= BIT(Flag); \ } (void)0 - if (!strcmp((char*) key->data.scalar.value, "real")) { + 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")) { + } 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) { + if(res != RES_OK) { log_node(parser, key); goto error; } @@ -2015,7 +2017,7 @@ parse_hyperboloid const yaml_node_t* hyperboloid, struct solparser_shape_hyperboloid_id* out_ishape) { - enum { CLIP, FOCAL }; + enum { CLIP, FOCAL, SLICES }; struct solparser_shape_hyperboloid* shape = NULL; size_t ishape = SIZE_MAX; intptr_t i, n; @@ -2023,7 +2025,7 @@ parse_hyperboloid res_T res = RES_OK; ASSERT(doc && hyperboloid && out_ishape); - if (hyperboloid->type != YAML_MAPPING_NODE) { + if(hyperboloid->type != YAML_MAPPING_NODE) { log_err(parser, hyperboloid, "expect a mapping of hyperbol parameters.\n"); res = RES_BAD_ARG; goto error; @@ -2032,7 +2034,7 @@ parse_hyperboloid /* Allocate a hyperboloid shape */ ishape = darray_hyperboloid_size_get(&parser->hyperbols); res = darray_hyperboloid_resize(&parser->hyperbols, ishape + 1); - if (res != RES_OK) { + if(res != RES_OK) { log_err(parser, hyperboloid, "could not allocate the hyperbol shape.\n"); goto error; } @@ -2045,7 +2047,7 @@ parse_hyperboloid 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) { + if(key->type != YAML_SCALAR_NODE) { log_err(parser, key, "expect hyperbol parameters.\n"); res = RES_BAD_ARG; goto error; @@ -2059,21 +2061,22 @@ parse_hyperboloid } \ mask |= BIT(Flag); \ } (void)0 - if (!strcmp((char*) key->data.scalar.value, "clip")) { + 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")) { + } else if(!strcmp((char*)key->data.scalar.value, "focals")) { SETUP_MASK(FOCAL, "focals"); res = parse_focals_description(parser, doc, val, &shape->focals); - } - else { + } else if(!strcmp((char*)key->data.scalar.value, "slices")) { + SETUP_MASK(SLICES, "slices"); + res = parse_integer(parser, val, 4, 4096, &shape->nslices); + } else { log_err(parser, key, "unknown hyperbol parameter `%s'.\n", key->data.scalar.value); res = RES_BAD_ARG; goto error; } - if (res != RES_OK) { + if(res != RES_OK) { log_node(parser, key); goto error; } @@ -2094,7 +2097,7 @@ exit : out_ishape->i = ishape; return res; error: - if (shape) { + if(shape) { darray_hyperboloid_pop_back(&parser->hyperbols); ishape = SIZE_MAX; } @@ -2108,7 +2111,7 @@ parse_plane const yaml_node_t* plane, struct solparser_shape_plane_id* out_ishape) { - enum { CLIP }; + enum { CLIP, SLICES }; struct solparser_shape_plane* shape = NULL; size_t ishape = SIZE_MAX; intptr_t i, n; @@ -2143,14 +2146,22 @@ parse_plane res = RES_BAD_ARG; goto error; } + #define SETUP_MASK(Flag, Name) { \ + if(mask & BIT(Flag)) { \ + log_err(parser, key, \ + "the plane 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")) { - if(mask & BIT(CLIP)) { - log_err(parser, key, "the plane clipping is already defined.\n"); - res = RES_BAD_ARG; - goto error; - } - mask |= BIT(CLIP); + SETUP_MASK(CLIP, "clip"); res = parse_clip(parser, doc, val, &shape->polyclips); + } else if(!strcmp((char*)key->data.scalar.value, "slices")) { + SETUP_MASK(SLICES, "slices"); + res = parse_integer(parser, val, 1, 4096, &shape->nslices); } else { log_err(parser, key, "unknown plane parameter `%s'.\n", key->data.scalar.value); @@ -2161,6 +2172,7 @@ parse_plane log_node(parser, key); goto error; } + #undef SETUP_MASK } if(!(mask & BIT(CLIP))) { log_err(parser, plane, "the plane parameter `clip' is missing.\n"); @@ -2374,8 +2386,7 @@ 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")) { + } 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); @@ -2650,13 +2661,11 @@ parse_anchor } else if(!strcmp((char*)key->data.scalar.value, "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; + } else if(!strcmp((char*) key->data.scalar.value, "hyperboloid_image_focals")) { + struct solparser_hyperboloid_focals focals; SETUP_MASK(POSITION, "position description"); res = parse_focals_description(parser, doc, val, &focals); - if (res != RES_OK) goto error; + if(res != RES_OK) goto error; d3(solanchor->position, 0, 0, focals.image); } else { log_err(parser, key, "unknown anchor parameter `%s'.\n", @@ -2848,7 +2857,7 @@ parse_entity } else if(!strcmp((char*)key->data.scalar.value, "name")) { SETUP_MASK(NAME, "name"); res = parse_identifier_string(parser, val, &solent.name); - if (!strcmp(str_get(&solent.name), "self")) { + if(!strcmp(str_get(&solent.name), "self")) { /* self is a reserved keyword */ log_err(parser, key, "Reserved keywords cannot be used as names: %s.\n", str_get(&solent.name)); diff --git a/src/parser/solparser_shape.h b/src/parser/solparser_shape.h @@ -159,7 +159,8 @@ solparser_shape_imported_geometry_copy_and_release ******************************************************************************/ struct solparser_shape_paraboloid { double focal; - struct darray_polyclip polyclips; + long nslices; /* < 0 if not defined */ + struct darray_polyclip polyclips; }; static INLINE void @@ -168,6 +169,7 @@ solparser_shape_paraboloid_init struct solparser_shape_paraboloid* paraboloid) { ASSERT(paraboloid); + paraboloid->nslices = -1; darray_polyclip_init(allocator, &paraboloid->polyclips); } @@ -185,6 +187,7 @@ solparser_shape_paraboloid_copy { ASSERT(dst && src); dst->focal = src->focal; + dst->nslices = src->nslices; return darray_polyclip_copy(&dst->polyclips, &src->polyclips); } @@ -195,23 +198,26 @@ solparser_shape_paraboloid_copy_and_release { ASSERT(dst && src); dst->focal = src->focal; + dst->nslices = src->nslices; return darray_polyclip_copy_and_release(&dst->polyclips, &src->polyclips); } /******************************************************************************* * Hyperboloid shape ******************************************************************************/ -struct hyperboloid_focals { - double real, image; +struct solparser_hyperboloid_focals { + double real; + double image; }; -#define HYPERBOLOID_FOCALS_NULL__ { 0, 0 } -static const struct hyperboloid_focals -HYPERBOLOID_FOCALS_NULL = HYPERBOLOID_FOCALS_NULL__; +#define SOLPARSER_HYPERBOLOID_FOCALS_NULL__ { 0, 0 } +static const struct solparser_hyperboloid_focals +SOLPARSER_HYPERBOLOID_FOCALS_NULL = SOLPARSER_HYPERBOLOID_FOCALS_NULL__; struct solparser_shape_hyperboloid { - struct hyperboloid_focals focals; + struct solparser_hyperboloid_focals focals; struct darray_polyclip polyclips; + long nslices; /* < 0 if not defined */ }; static INLINE void @@ -220,6 +226,7 @@ solparser_shape_hyperboloid_init struct solparser_shape_hyperboloid* hyperboloid) { ASSERT(hyperboloid); + hyperboloid->nslices = -1; darray_polyclip_init(allocator, &hyperboloid->polyclips); } @@ -237,6 +244,7 @@ solparser_shape_hyperboloid_copy { ASSERT(dst && src); dst->focals = src->focals; + dst->nslices = src->nslices; return darray_polyclip_copy(&dst->polyclips, &src->polyclips); } @@ -247,6 +255,7 @@ solparser_shape_hyperboloid_copy_and_release { ASSERT(dst && src); dst->focals = src->focals; + dst->nslices = src->nslices; return darray_polyclip_copy_and_release(&dst->polyclips, &src->polyclips); } @@ -255,6 +264,7 @@ solparser_shape_hyperboloid_copy_and_release ******************************************************************************/ struct solparser_shape_plane { struct darray_polyclip polyclips; + long nslices; }; static INLINE void @@ -263,6 +273,7 @@ solparser_shape_plane_init struct solparser_shape_plane* plane) { ASSERT(plane); + plane->nslices = 1; darray_polyclip_init(allocator, &plane->polyclips); } @@ -279,6 +290,7 @@ solparser_shape_plane_copy const struct solparser_shape_plane* src) { ASSERT(dst && src); + dst->nslices = src->nslices; return darray_polyclip_copy(&dst->polyclips, &src->polyclips); } @@ -288,6 +300,7 @@ solparser_shape_plane_copy_and_release struct solparser_shape_plane* src) { ASSERT(dst && src); + dst->nslices = src->nslices; return darray_polyclip_copy_and_release(&dst->polyclips, &src->polyclips); } diff --git a/src/parser/test_solparser6.c b/src/parser/test_solparser6.c @@ -33,7 +33,10 @@ main(int argc, char** argv) const struct solparser_shape* shape; const struct solparser_shape_sphere* sphere; const struct solparser_shape_paraboloid* parabol; + const struct solparser_shape_plane* plane; const struct solparser_shape_hyperboloid* hyperbol; + const struct solparser_polyclip* polyclip; + double pos[2]; FILE* stream; (void)argc, (void)argv; @@ -52,16 +55,23 @@ main(int argc, char** argv) fprintf(stream, " material: { ?virtual }\n"); fprintf(stream, " - parabol:\n"); fprintf(stream, " focal: 10\n"); + fprintf(stream, " slices : 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, " slices : 20\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, " - plane:\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); @@ -78,7 +88,7 @@ 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), 3); + CHECK(solparser_geometry_get_objects_count(geom), 4); obj_id = solparser_geometry_get_object(geom, 0); obj = solparser_get_object(parser, obj_id); @@ -94,6 +104,20 @@ main(int argc, char** argv) CHECK(shape->type, SOLPARSER_SHAPE_PARABOL); parabol = solparser_get_shape_parabol(parser, shape->data.parabol); CHECK(parabol->focal, 10); + CHECK(parabol->nslices, 10); + CHECK(darray_polyclip_size_get(&parabol->polyclips), 1); + polyclip = darray_polyclip_cdata_get(&parabol->polyclips); + CHECK(polyclip->op, SOLPARSER_CLIP_OP_AND); + CHECK(solparser_polyclip_get_vertices_count(polyclip), 3); + solparser_polyclip_get_vertex(polyclip, 0, pos); + CHECK(pos[0], 1); + CHECK(pos[1], 2); + solparser_polyclip_get_vertex(polyclip, 1, pos); + CHECK(pos[0], 3); + CHECK(pos[1], 4); + solparser_polyclip_get_vertex(polyclip, 2, pos); + CHECK(pos[0], 6); + CHECK(pos[1], 7); obj_id = solparser_geometry_get_object(geom, 2); obj = solparser_get_object(parser, obj_id); @@ -102,12 +126,20 @@ main(int argc, char** argv) hyperbol = solparser_get_shape_hyperbol(parser, shape->data.hyperbol); CHECK(hyperbol->focals.real, 10); CHECK(hyperbol->focals.image, 2); + CHECK(hyperbol->nslices, 20); mtl2 = solparser_get_material_double_sided(parser, obj->mtl2); CHECK(mtl2->front.i, mtl2->back.i); mtl = solparser_get_material(parser, mtl2->front); CHECK(mtl->type, SOLPARSER_MATERIAL_VIRTUAL); + obj_id = solparser_geometry_get_object(geom, 3); + obj = solparser_get_object(parser, obj_id); + shape = solparser_get_shape(parser, obj->shape); + CHECK(shape->type, SOLPARSER_SHAPE_PLANE); + plane = solparser_get_shape_plane(parser, shape->data.plane); + CHECK(plane->nslices, 1); /* 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 @@ -570,6 +570,33 @@ - operation: AND vertices: [ [1, 2], [3, 4], [6, 7] ] --- +# invalid slices +- geometry: + - parabol: + slices: 1 + focal: 1 + clip: + - operation: AND + vertices: [ [1, 2], [3, 4], [6, 7] ] +--- +# invalid slices +- geometry: + - parabol: + slices: 0 + focal: 1 + clip: + - operation: AND + vertices: [ [1, 2], [3, 4], [6, 7] ] +--- +# invalid slices +- geometry: + - parabol: + slices: 4097 + focal: 1 + clip: + - operation: AND + vertices: [ [1, 2], [3, 4], [6, 7] ] +--- # # <parabolic-cylinder> ::= @@ -634,7 +661,7 @@ # <hyperboloid_focals> ::= # real: REAL # in ]0, INF) # image: REAL # in ]0, INF) -# +# # missing hyperbol definition - geometry: [ { hyperbol: } ] --- @@ -735,7 +762,31 @@ - operation: AND vertices: [ [1, 2], [3, 4], [6, 7] ] --- +# invalid slices +- geometry: &target + - plane: + slices: 0 + clip: + - operation: AND + vertices: + - [-0.50, -0.50] + - [-0.50, 0.50] + - [0.50, 0.50] + - [0.50, -0.50] +--- +# invalid slices +- geometry: &target + - plane: + slices: 4097 + clip: + - operation: AND + vertices: + - [-0.50, -0.50] + - [-0.50, 0.50] + - [0.50, 0.50] + - [0.50, -0.50] +--- # # <sphere> ::= # sphere: @@ -1160,7 +1211,7 @@ # # <position-description> ::= # position: <real3> | hyperboloid_image_focals: <hyperboloid_focals> -# +# # missing anchors definition - entity: diff --git a/src/parser/yaml/test_ok_6.yaml b/src/parser/yaml/test_ok_6.yaml @@ -0,0 +1,108 @@ +- sun: { dni: 1, spectrum: [{wavelength: 1, data: 1}] } +- entity: + name: entity + primary: 1 + geometry: + - material: { mirror: { reflectivity: 0, roughness: 0.5 } } + plane: + slices: 4 + clip: + - operation: AND + vertices: + - [-0.50, -0.50] + - [-0.50, 0.50] + - [0.50, 0.50] + - [0.50, -0.50] +--- +- sun: { dni: 1, spectrum: [{wavelength: 1, data: 1}] } +- entity: + name: entity + primary: 1 + geometry: + - material: { mirror: { reflectivity: 0, roughness: 0.5 } } + plane: + clip: + - operation: AND + vertices: + - [-0.50, -0.50] + - [-0.50, 0.50] + - [0.50, 0.50] + - [0.50, -0.50] +--- +- sun: { dni: 1, spectrum: [{wavelength: 1, data: 1}] } +- entity: + name: entity + primary: 1 + geometry: + - material: { mirror: { reflectivity: 0, roughness: 0.5 } } + parabol: + slices: 40 + focal: 18 + 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 } } + parabol: + focal: 18 + 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 } } + parabolic-cylinder: + slices: 40 + focal: 18 + 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 } } + parabolic-cylinder: + focal: 18 + 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: + slices: 40 + focals: { real: 1, image: 1 } + 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 + vertices: [[-30.0, -20.0], [-30.0, 20.0], [30.0, 20.0], [30.0, -20.0]] + + diff --git a/src/solstice.c b/src/solstice.c @@ -677,6 +677,8 @@ solstice_run(struct solstice* solstice) goto error; } + fprintf(solstice->output, "#--- No Sun direction\n"); + if(dump) { res = solstice_dump(solstice); if(res != RES_OK) goto error; diff --git a/src/solstice_object.c b/src/solstice_object.c @@ -284,21 +284,21 @@ create_stl ASSERT(str_cget(&stl->filename)); res = sstl_create(NULL, solstice->allocator, 0, &tmp_stl); - if (res != RES_OK) { + if(res != RES_OK) { fprintf(stderr, "Could not create a Solstice Solver STL shape.\n"); goto error; } res = sstl_load(tmp_stl, str_cget(&stl->filename)); - if (res != RES_OK) goto error; + if(res != RES_OK) goto error; res = sstl_get_desc(tmp_stl, &tmp_desc); - if (res != RES_OK) goto error; + if(res != RES_OK) goto error; ASSERT(tmp_desc.triangles_count <= UINT_MAX); ASSERT(tmp_desc.vertices_count <= UINT_MAX); mesh_ctx.transform = transform; mesh_ctx.desc = tmp_desc; res = ssol_shape_create_mesh(solstice->ssol, &ssol_shape); - if (res != RES_OK) { + if(res != RES_OK) { fprintf(stderr, "Could not create the STL mesh shape.\n"); goto error; } @@ -308,20 +308,17 @@ create_stl res = ssol_mesh_setup(ssol_shape, (unsigned)tmp_desc.triangles_count, mesh_ctx_sstl_get_ids, (unsigned)tmp_desc.vertices_count, &vertex_data, 1, &mesh_ctx); - if (res != RES_OK) { + if(res != RES_OK) { fprintf(stderr, "Could not setup STL mesh.\n"); goto error; } exit: - if (tmp_stl) { - SSTL(ref_put(tmp_stl)); - tmp_stl = NULL; - } + if(tmp_stl) SSTL(ref_put(tmp_stl)); *out_stl = ssol_shape; return res; error: - if (ssol_shape) { + if(ssol_shape) { SSOL(shape_ref_put(ssol_shape)); ssol_shape = NULL; } @@ -405,7 +402,9 @@ create_parabol quadric.data.parabol.focal = paraboloid->focal; d33_set(quadric.transform, transform); d3_set(quadric.transform+9, transform+9); - + if(paraboloid->nslices > 0) { /* nslices is set */ + quadric.slices_count_hint = (size_t)paraboloid->nslices; + } return create_ssol_shape_punched_surface (solstice, &paraboloid->polyclips, &quadric, out_ssol_shape); } @@ -424,9 +423,12 @@ create_parabolic_cylinder paraboloid = solparser_get_shape_parabolic_cylinder(solstice->parser, id); quadric.type = SSOL_QUADRIC_PARABOLIC_CYLINDER; - quadric.data.parabol.focal = paraboloid->focal; + quadric.data.parabolic_cylinder.focal = paraboloid->focal; d33_set(quadric.transform, transform); d3_set(quadric.transform+9, transform+9); + if(paraboloid->nslices > 0) { /* nslices is set */ + quadric.slices_count_hint = (size_t)paraboloid->nslices; + } return create_ssol_shape_punched_surface (solstice, &paraboloid->polyclips, &quadric, out_ssol_shape); @@ -451,6 +453,9 @@ create_hyperbol quadric.data.hyperbol.img_focal = hyperboloid->focals.image; d33_set(quadric.transform, transform); d3_set(quadric.transform + 9, transform + 9); + if(hyperboloid->nslices > 0) { /* nslices is set */ + quadric.slices_count_hint = (size_t)hyperboloid->nslices; + } return create_ssol_shape_punched_surface (solstice, &hyperboloid->polyclips, &quadric, out_ssol_shape); @@ -464,12 +469,14 @@ create_plane struct ssol_shape** out_ssol_shape) { const struct solparser_shape_plane* plane; - struct ssol_quadric quadric; + struct ssol_quadric quadric = SSOL_QUADRIC_DEFAULT; ASSERT(solstice); plane = solparser_get_shape_plane(solstice->parser, id); + ASSERT(plane->nslices > 0); quadric.type = SSOL_QUADRIC_PLANE; + quadric.slices_count_hint = (size_t)plane->nslices; d33_set(quadric.transform, transform); d3_set(quadric.transform+9, transform+9); diff --git a/src/solstice_solve.c b/src/solstice_solve.c @@ -23,7 +23,7 @@ * Helper function ******************************************************************************/ static void -write_global_mc(struct solstice* solstice, struct ssol_estimator* estimator) +write_mc_global(struct solstice* solstice, struct ssol_estimator* estimator) { struct ssol_mc_global mc_global; struct htable_receiver_iterator r_it, r_end; @@ -106,7 +106,7 @@ write_global_mc(struct solstice* solstice, struct ssol_estimator* estimator) "%s %u " "FRONT: %g %g %g %g %g %g %g %g %g %g " "BACK: %g %g %g %g %g %g %g %g %g %g\n", - str_cget(name), (unsigned) id, + str_cget(name), (unsigned)id, front.integrated_absorbed_irradiance.E, front.integrated_absorbed_irradiance.SE, front.integrated_irradiance.E, front.integrated_irradiance.SE, front.reflectivity_loss.E, front.reflectivity_loss.SE, @@ -198,6 +198,170 @@ write_global_mc(struct solstice* solstice, struct ssol_estimator* estimator) } } +static void +dump_instantiated_shaded_shape_vertices + (struct solstice* solstice, + const struct ssol_instantiated_shaded_shape* inst_sshape) +{ + unsigned ivert, nverts; + ASSERT(solstice && inst_sshape); + + SSOL(shape_get_vertices_count(inst_sshape->shape, &nverts)); + FOR_EACH(ivert, 0, nverts) { + double pos[3]; + SSOL(instantiated_shaded_shape_get_vertex_attrib + (inst_sshape, ivert, SSOL_POSITION, pos)); + fprintf(solstice->output, "%f %f %f\n", SPLIT3(pos)); + } +} + +static void +dump_shape_triangle_indices + (struct solstice* solstice, + const struct ssol_shape* shape, + const size_t offset) +{ + unsigned itri, ntris; + ASSERT(solstice && shape); + + SSOL(shape_get_triangles_count(shape, &ntris)); + FOR_EACH(itri, 0, ntris) { + unsigned ids[3]; + SSOL(shape_get_triangle_indices(shape, itri, ids)); + fprintf(solstice->output, "3 %lu %lu %lu\n", + (unsigned long)(ids[0] + offset), + (unsigned long)(ids[1] + offset), + (unsigned long)(ids[2] + offset)); + } +} + +static void +dump_mc_shape + (struct solstice* solstice, + struct ssol_shape* shape, + struct ssol_mc_shape* mc_shape) +{ + unsigned itri, ntris; + ASSERT(solstice && shape && mc_shape); + + SSOL(shape_get_triangles_count(shape, &ntris)); + FOR_EACH(itri, 0, ntris) { + struct ssol_mc_primitive mc_prim; + SSOL(mc_shape_get_mc_primitive(mc_shape, itri, &mc_prim)); + fprintf(solstice->output, "%g %g\n", + mc_prim.integrated_irradiance.E, + mc_prim.integrated_irradiance.SE); + } +} + +static void +dump_per_primitive_mc_estimations + (struct solstice* solstice, + struct ssol_estimator* estimator, + struct ssol_instance* inst, + const enum ssol_side_flag side) +{ + size_t ishape, nshapes; + struct ssol_mc_receiver mc_rcv; + const char* name; + ASSERT(solstice && estimator && inst); + + SSOL(estimator_get_mc_receiver(estimator, inst, side, &mc_rcv)); + + switch(side) { + case SSOL_FRONT: name = "Front_faces"; break; + case SSOL_BACK: name = "Back_faces"; break; + default: FATAL("Unreachable code.\n"); break; + } + + fprintf(solstice->output, "SCALARS %s float 2\n", name); + fprintf(solstice->output, "LOOKUP_TABLE default\n"); + + SSOL(instance_get_shaded_shapes_count(inst, &nshapes)); + FOR_EACH(ishape, 0, nshapes) { + struct ssol_instantiated_shaded_shape inst_sshape; + struct ssol_mc_shape mc_shape; + SSOL(instance_get_shaded_shape(inst, ishape, &inst_sshape)); + SSOL(mc_receiver_get_mc_shape(&mc_rcv, inst_sshape.shape, &mc_shape)); + dump_mc_shape(solstice, inst_sshape.shape, &mc_shape); + } +} + +static void +write_per_receiver_mc_primitive + (struct solstice* solstice, struct ssol_estimator* estimator) +{ + struct htable_receiver_iterator it, end; + ASSERT(solstice && estimator); + + htable_receiver_begin(&solstice->receivers, &it); + htable_receiver_end(&solstice->receivers, &end); + while(!htable_receiver_iterator_eq(&it, &end)) { + struct ssol_instantiated_shaded_shape inst_sshape; + const struct str* name = htable_receiver_iterator_key_get(&it); + struct solstice_receiver* rcv = htable_receiver_iterator_data_get(&it); + struct ssol_instance* inst = rcv->node->instance; + size_t ishape, nshapes; + size_t nverts, ntris; + size_t offset; + + htable_receiver_iterator_next(&it); + SSOL(instance_get_shaded_shapes_count(inst, &nshapes)); + + /* Write the header */ + fprintf(solstice->output, "# vtk DataFile Version 2.0\n"); + fprintf(solstice->output, "%s\n", str_cget(name)); + fprintf(solstice->output, "ASCII\n"); + fprintf(solstice->output, "DATASET POLYDATA\n"); + + /* Compute the overall number of vertices & triangles of the receiver */ + nverts = ntris = 0; + FOR_EACH(ishape, 0, nshapes) { + unsigned shape_nverts, shape_ntris; + SSOL(instance_get_shaded_shape(inst, ishape, &inst_sshape)); + SSOL(shape_get_vertices_count(inst_sshape.shape, &shape_nverts)); + SSOL(shape_get_triangles_count(inst_sshape.shape, &shape_ntris)); + nverts += shape_nverts; + ntris += shape_ntris; + } + + /* Write the positions of the receiver shaded shapes */ + fprintf(solstice->output, "POINTS %lu float\n", (unsigned long)nverts); + FOR_EACH(ishape, 0, nshapes) { + SSOL(instance_get_shaded_shape(inst, ishape, &inst_sshape)); + dump_instantiated_shaded_shape_vertices(solstice, &inst_sshape); + } + + /* Write the triangles of the receiver shade shapes */ + offset = 0; + fprintf(solstice->output, "POLYGONS %lu %lu\n", + (unsigned long)ntris, (unsigned long)ntris*4); + FOR_EACH(ishape, 0, nshapes) { + unsigned shape_nverts; + SSOL(instance_get_shaded_shape(inst, ishape, &inst_sshape)); + SSOL(shape_get_vertices_count(inst_sshape.shape, &shape_nverts)); + dump_shape_triangle_indices(solstice, inst_sshape.shape, offset); + offset += shape_nverts; + } + + /* Write front faces MC estimations */ + fprintf(solstice->output, "CELL_DATA %lu\n", (unsigned long)ntris); + switch(rcv->side) { + case SRCVL_FRONT: + dump_per_primitive_mc_estimations(solstice, estimator, inst, SSOL_FRONT); + break; + case SRCVL_BACK: + dump_per_primitive_mc_estimations(solstice, estimator, inst, SSOL_BACK); + break; + case SRCVL_FRONT_AND_BACK: + dump_per_primitive_mc_estimations(solstice, estimator, inst, SSOL_FRONT); + dump_per_primitive_mc_estimations(solstice, estimator, inst, SSOL_BACK); + break; + default: FATAL("Unreachable code.\n"); break; + } + } +} + /******************************************************************************* * Local functions ******************************************************************************/ @@ -234,7 +398,8 @@ solstice_solve(struct solstice* solstice) goto error; } - write_global_mc(solstice, estimator); + write_mc_global(solstice, estimator); + write_per_receiver_mc_primitive(solstice, estimator); if(solstice->output_hits) { sz = (size_t)ftell(bin_stream); diff --git a/src/test_solstice_simulation.c b/src/test_solstice_simulation.c @@ -31,106 +31,6 @@ #include <sys/stat.h> #define fdopen _fdopen #define open _open - #define mktemp _mktemp - - /* mkstemp extracted from libc/sysdeps/posix/tempname.c. Copyright - (C) 1991-1999, 2000, 2001, 2006 Free Software Foundation, Inc. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. */ - - static const char letters [] = - "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; - - /* Generate a temporary file name based on TMPL. TMPL must match the - rules for mk[s]temp (i.e. end in "XXXXXX"). The name constructed - does not exist at the time of the call to mkstemp. TMPL is - overwritten with the result. */ - int - mkstemp(char *tmpl) - { - size_t len; - char *XXXXXX; - static unsigned long long value; - unsigned long long random_time_bits; - unsigned int count; - int fd = -1; - int save_errno = errno; - - /* A lower bound on the number of temporary files to attempt to - generate. The maximum total number of temporary file names that - can exist for a given template is 62**6. It should never be - necessary to try all these combinations. Instead if a reasonable - number of names is tried (we define reasonable as 62**3) fail to - give the system administrator the chance to remove the problems. */ - #define ATTEMPTS_MIN (62 * 62 * 62) - - /* The number of times to attempt to generate a temporary file. To - conform to POSIX, this must be no smaller than TMP_MAX. */ - #if ATTEMPTS_MIN < TMP_MAX - unsigned int attempts = TMP_MAX; - #else - unsigned int attempts = ATTEMPTS_MIN; - #endif - - len = strlen(tmpl); - if (len < 6 || strcmp(&tmpl[len - 6], "XXXXXX")) { - errno = EINVAL; - return -1; - } - - /* This is where the Xs start. */ - XXXXXX = &tmpl[len - 6]; - - /* Get some more or less random data. */ - { - SYSTEMTIME stNow; - FILETIME ftNow; - - /* get system time */ - GetSystemTime(&stNow); - stNow.wMilliseconds = 500; - if (!SystemTimeToFileTime(&stNow, &ftNow)) { - errno = -1; - return -1; - } - - random_time_bits = (((unsigned long long)ftNow.dwHighDateTime << 32) - | (unsigned long long)ftNow.dwLowDateTime); - } - value += random_time_bits ^ (unsigned long long)GetCurrentThreadId(); - - for (count = 0; count < attempts; value += 7777, ++count) { - unsigned long long v = value; - - /* Fill in the random bits. */ - XXXXXX[0] = letters[v % 62]; - v /= 62; - XXXXXX[1] = letters[v % 62]; - v /= 62; - XXXXXX[2] = letters[v % 62]; - v /= 62; - XXXXXX[3] = letters[v % 62]; - v /= 62; - XXXXXX[4] = letters[v % 62]; - v /= 62; - XXXXXX[5] = letters[v % 62]; - - fd = open(tmpl, O_RDWR|O_CREAT|O_EXCL, S_IREAD|S_IWRITE); - if (fd >= 0) { - errno = save_errno; - return fd; - } - else if (errno != EEXIST) - return -1; - } - - /* We got out of the loop because we ran out of combinations to try. */ - errno = EEXIST; - return -1; - } #endif enum side { @@ -187,6 +87,108 @@ sundir_header [] = "#--- Sun direction:"; #define IS_NEW_BLOCK(Line, Header) (!strncmp((Line), (Header), strlen(Header))) + +#ifdef COMPILER_CL +/* mkstemp extracted from libc/sysdeps/posix/tempname.c. Copyright + * (C) 1991-1999, 2000, 2001, 2006 Free Software Foundation, Inc. + * + * The GNU C Library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. */ + +static const char letters [] = +"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + +/* Generate a temporary file name based on TMPL. TMPL must match the + * rules for mk[s]temp (i.e. end in "XXXXXX"). The name constructed + * does not exist at the time of the call to mkstemp. TMPL is + * overwritten with the result. */ +int +mkstemp(char *tmpl) +{ + size_t len; + char *XXXXXX; + static unsigned long long value; + unsigned long long random_time_bits; + unsigned int count; + int fd = -1; + int save_errno = errno; + + /* A lower bound on the number of temporary files to attempt to + * generate. The maximum total number of temporary file names that + * can exist for a given template is 62**6. It should never be + * necessary to try all these combinations. Instead if a reasonable + * number of names is tried (we define reasonable as 62**3) fail to + * give the system administrator the chance to remove the problems. */ + #define ATTEMPTS_MIN (62 * 62 * 62) + + /* The number of times to attempt to generate a temporary file. To + * conform to POSIX, this must be no smaller than TMP_MAX. */ + #if ATTEMPTS_MIN < TMP_MAX + unsigned int attempts = TMP_MAX; + #else + unsigned int attempts = ATTEMPTS_MIN; + #endif + + len = strlen(tmpl); + if (len < 6 || strcmp(&tmpl[len - 6], "XXXXXX")) { + errno = EINVAL; + return -1; + } + + /* This is where the Xs start. */ + XXXXXX = &tmpl[len - 6]; + + /* Get some more or less random data. */ + { + SYSTEMTIME stNow; + FILETIME ftNow; + + /* get system time */ + GetSystemTime(&stNow); + stNow.wMilliseconds = 500; + if (!SystemTimeToFileTime(&stNow, &ftNow)) { + errno = -1; + return -1; + } + + random_time_bits = (((unsigned long long)ftNow.dwHighDateTime << 32) + | (unsigned long long)ftNow.dwLowDateTime); + } + value += random_time_bits ^ (unsigned long long)GetCurrentThreadId(); + + for (count = 0; count < attempts; value += 7777, ++count) { + unsigned long long v = value; + + /* Fill in the random bits. */ + XXXXXX[0] = letters[v % 62]; + v /= 62; + XXXXXX[1] = letters[v % 62]; + v /= 62; + XXXXXX[2] = letters[v % 62]; + v /= 62; + XXXXXX[3] = letters[v % 62]; + v /= 62; + XXXXXX[4] = letters[v % 62]; + v /= 62; + XXXXXX[5] = letters[v % 62]; + + fd = open(tmpl, O_RDWR|O_CREAT|O_EXCL, S_IREAD|S_IWRITE); + if (fd >= 0) { + errno = save_errno; + return fd; + } + else if (errno != EEXIST) + return -1; + } + + /* We got out of the loop because we ran out of combinations to try. */ + errno = EEXIST; + return -1; +} +#endif + static int read_line(char* line, size_t max_line_len, FILE* stream) { @@ -462,6 +464,7 @@ do_check(const char* binary, const char* dir, const char* base_name) FILE* ref_file; struct counts ref_counts, test_counts; int n; + int err; ASSERT(base_name); n = snprintf(ref_file_name, sizeof(ref_file_name), "%s%s.ref", dir, base_name); @@ -490,7 +493,8 @@ do_check(const char* binary, const char* dir, const char* base_name) dir, base_name, dir, base_name); CHECK((unsigned)n < sizeof(cmd), 1); - CHECK(system(cmd), RES_OK); + err = system(cmd); + CHECK(err, 0); get_angles_and_counts(test_file, test_sun_angles, &test_counts); CHECK(d2_eq(ref_sun_angles, test_sun_angles), 1);