commit c7d8821dc379c443d29216558ea8dc206af3f2fb
parent 6f76105d21e52545dfff66aefba98d0293c9b6cb
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date: Fri, 8 Dec 2017 17:54:46 +0100
Merge branch 'feature_gaussian_sunshape' into develop
Diffstat:
5 files changed, 150 insertions(+), 4 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
@@ -1066,7 +1077,7 @@ glass. Furthermore, this example illustrates the use of a *spectrum* for
front: {dielectric: {medium_i: *air_medium, medium_t: *glass_medium}}
back: {dielectric: {medium_i: *glass_medium, medium_t: *air_medium}}
-# Pimary reflectors
+# Primary reflectors
- entity:
name: "primary_reflector1"
primary: 1
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;