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 436220a82c7f6d7b69ca528adb4d31329bd2bfba
parent 16d2c2926b923fed8c21444760ade03af1f06165
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date:   Fri,  8 Dec 2017 17:51:13 +0100

Add the gaussian sunshape.

Diffstat:
Mdoc/solstice-input.5.txt | 13++++++++++++-
Msrc/parser/solparser_sun.c | 68++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/parser/solparser_sun.h | 5++++-
Msrc/parser/yaml/test_ko_0.yaml | 27++++++++++++++++++++++++++-
Msrc/solstice_sun.c | 39+++++++++++++++++++++++++++++++++++++++
5 files changed, 149 insertions(+), 3 deletions(-)

diff --git a/doc/solstice-input.5.txt b/doc/solstice-input.5.txt @@ -247,7 +247,7 @@ _______ [ <spectrum> ] # Default is the smarts295 spectrum [ <sun-shape> ] -<sun-shape> ::= <pillbox> | <buie> +<sun-shape> ::= <pillbox> | <gaussian> | <buie> <buie> ::= buie: csr: REAL # in [1e-6, 0.849] @@ -255,6 +255,9 @@ _______ <pillbox> ::= pillbox: half_angle: REAL # in ]0, 90] +<gaussian> ::= gaussian: + std_dev: REAL # in ]0, INF) + ---------------------------------------- <atmosphere> ::= atmosphere: @@ -321,6 +324,14 @@ shapes are: Its single *half_angle* parameter is the sun's disk half-angle in degrees, that is linked to the apparent size of the sun. A typical half_angle is 0.2664. +*gaussian*:: + The *gaussian* distribution defines a gaussian distribution of the solar + incoming direction. Its single *std_dev* parameter is the standard deviation + of the distribution in degrees. Values around 0.2 are typical. + As the gaussian distribution is not truncated, the resulting sun vector can + theoreticaly be oriented towards the sun, especially with a big, non-typical + *std_dev* value. + *buie*:: The *buie* distribution, as first discribed in [3]. Its single *csr* parameter is the ratio between the circumsolar irradiance and the sum of diff --git a/src/parser/solparser_sun.c b/src/parser/solparser_sun.c @@ -150,6 +150,70 @@ error: goto exit; } +static res_T +parse_gaussian + (struct solparser* parser, + yaml_document_t* doc, + const yaml_node_t* gaussian, + struct solparser_sun_gaussian* sun) +{ + enum { STD_DEV }; + intptr_t i, n; + int mask = 0; /* Register the parsed attributes */ + res_T res = RES_OK; + ASSERT(doc && gaussian && sun); + + if(gaussian->type != YAML_MAPPING_NODE) { + log_err(parser, gaussian, + "expect a gaussian definition of the sun radial angular distribution.\n"); + res = RES_BAD_ARG; + goto error; + } + + n = gaussian->data.mapping.pairs.top - gaussian->data.mapping.pairs.start; + FOR_EACH(i, 0, n) { + yaml_node_t* key; + yaml_node_t* val; + + key = yaml_document_get_node(doc, gaussian->data.mapping.pairs.start[i].key); + val = yaml_document_get_node(doc, gaussian->data.mapping.pairs.start[i].value); + if(key->type != YAML_SCALAR_NODE) { + log_err(parser, key, "expect a gaussian parameter.\n"); + res = RES_BAD_ARG; + goto error; + } + if(!strcmp((char*)key->data.scalar.value, "std_dev")) { + if(mask & BIT(STD_DEV)) { + log_err(parser, key, "the gaussian `std_dev' is already defined.\n"); + res = RES_BAD_ARG; + goto error; + } + mask |= BIT(STD_DEV); + res = parse_real(parser, val, nextafter(0, 1), 90, &sun->std_dev); + } else { + log_err(parser, gaussian, "unknown gaussian parameter `%s'.\n", + key->data.scalar.value); + res = RES_BAD_ARG; + goto error; + } + if(res != RES_OK) { + log_node(parser, key); + goto error; + } + } + + if(!(mask & BIT(STD_DEV))) { + log_err(parser, gaussian, "the gaussian std_dev parameter is missing.\n"); + res = RES_BAD_ARG; + goto error; + } + +exit: + return res; +error: + goto exit; +} + /******************************************************************************* * Local functions ******************************************************************************/ @@ -220,6 +284,10 @@ parse_sun SETUP_MASK(RADIAL_ANGULAR_DISTRIB, "radial angular distribution"); solsun->radang_distrib_type = SOLPARSER_SUN_RADANG_DISTRIB_PILLBOX; res = parse_pillbox(parser, doc, val, &solsun->radang_distrib.pillbox); + } else if(!strcmp((char*)key->data.scalar.value, "gaussian")) { + SETUP_MASK(RADIAL_ANGULAR_DISTRIB, "radial angular distribution"); + solsun->radang_distrib_type = SOLPARSER_SUN_RADANG_DISTRIB_GAUSSIAN; + res = parse_gaussian(parser, doc, val, &solsun->radang_distrib.gaussian); } else if(!strcmp((char*)key->data.scalar.value, "spectrum")) { SETUP_MASK(SPECTRUM, "spectrum"); res = parse_spectrum(parser, doc, val, 0, DBL_MAX, &solsun->spectrum); diff --git a/src/parser/solparser_sun.h b/src/parser/solparser_sun.h @@ -22,11 +22,13 @@ enum solparser_sun_radang_distrib_type { /* Radial Angular distribution */ SOLPARSER_SUN_RADANG_DISTRIB_BUIE, SOLPARSER_SUN_RADANG_DISTRIB_DIRECTIONAL, - SOLPARSER_SUN_RADANG_DISTRIB_PILLBOX + SOLPARSER_SUN_RADANG_DISTRIB_PILLBOX, + SOLPARSER_SUN_RADANG_DISTRIB_GAUSSIAN }; struct solparser_sun_buie { double csr; }; struct solparser_sun_pillbox { double half_angle; }; +struct solparser_sun_gaussian { double std_dev; }; struct solparser_sun { double dni; /* In ]0, INF) */ @@ -35,6 +37,7 @@ struct solparser_sun { union { struct solparser_sun_buie buie; struct solparser_sun_pillbox pillbox; + struct solparser_sun_gaussian gaussian; } radang_distrib; }; diff --git a/src/parser/yaml/test_ko_0.yaml b/src/parser/yaml/test_ko_0.yaml @@ -98,6 +98,31 @@ --- # +# <gaussian> ::= +# gaussian: +# std_dev: REAL # in ]0, INF) +# + +# missing gaussian definition +- sun: { gaussian: } +--- +# missing std_dev value +- sun: { gaussian: { std_dev: } } +--- +# std_dev should be a number +- sun: { gaussian: { std_dev: "dummy"} } +--- +# 0 invalid +- sun: { gaussian: { std_dev: 0} } +--- +# 2x std_dev +- sun: { gaussian: { std_dev: 1, std_dev: 1} } +--- +# unknown dummy parameter +- sun: { gaussian: { dummy: 1} } +--- + +# # <buie> ::= # buie: # csr: REAL # in ]0, 1[ @@ -133,7 +158,7 @@ # [ <radial-angular-distribution> ] # # <radial-angular-distribution> ::= -# <pillbox> | <buie> +# <pillbox> | <gaussian> | <buie> # # missing dni diff --git a/src/solstice_sun.c b/src/solstice_sun.c @@ -123,6 +123,42 @@ error: goto exit; } +static res_T +create_sun_gaussian + (struct solstice* solstice, + const struct solparser_sun* solparser_sun, + struct ssol_sun** out_sun) +{ + struct ssol_sun* sun = NULL; + res_T res = RES_OK; + ASSERT(solstice && solparser_sun && out_sun); + ASSERT(solparser_sun->radang_distrib_type + == SOLPARSER_SUN_RADANG_DISTRIB_GAUSSIAN); + + res = ssol_sun_create_gaussian(solstice->ssol, &sun); + if(res != RES_OK) { + fprintf(stderr, "Could not create the solver gaussian sun.\n"); + goto error; + } + + res = ssol_sun_gaussian_set_std_dev + (sun, MDEG2RAD(solparser_sun->radang_distrib.gaussian.std_dev)); + if(res != RES_OK) { + fprintf(stderr, "Could not setup standard deviation for the solver gaussian sun.\n"); + goto error; + } + +exit: + *out_sun = sun; + return res; +error: + if(sun) { + SSOL(sun_ref_put(sun)); + sun = NULL; + } + goto exit; +} + static void get_wavelength(const size_t i, double* wlen, double* data, void* ctx) { @@ -201,6 +237,9 @@ solstice_create_sun(struct solstice* solstice) case SOLPARSER_SUN_RADANG_DISTRIB_PILLBOX: res = create_sun_pillbox(solstice, solparser_sun, &sun); break; + case SOLPARSER_SUN_RADANG_DISTRIB_GAUSSIAN: + res = create_sun_gaussian(solstice, solparser_sun, &sun); + break; default: FATAL("Unreachable code.\n"); break; } if(res != RES_OK) goto error;