commit 78c1c9ae4a38b977eddc8d582a27ad3a184e0973
parent 8d3f3f33dd24cba5b478ad728964b8e23aac8153
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date: Wed, 18 Apr 2018 14:48:11 +0200
Allow to output per-primitive incoming and/or absorbed fluxes.
Was previously restricted to incoming flux.
Diffstat:
10 files changed, 163 insertions(+), 69 deletions(-)
diff --git a/doc/solstice-receiver.5.txt b/doc/solstice-receiver.5.txt
@@ -47,10 +47,12 @@ that is tracked is defined by the *side* attribute of the receiver. Note that
the front and the back side of a geometry can be both considered if the *side*
attribute is set to *FRONT_AND_BACK*. Refer to the *solstice-input*(5)
specification for informations on which side of the geometry is front facing or
-back facing. Finally, if the optional *per_primitive* flag is set to *1*,
+back facing. Finally, if the optional *per_primitive* flag is set,
*solstice*(1) will estimate the irradiance for each triangle of the receiver
and use these data to generate a receiver map as described in
-*solstice-output*(5).
+*solstice-output*(5). The *per-primitive* flag can be set to *INCOMING*,
+*ABSORBED* or *INCOMING_AND_ABSORBED* to produce the incoming flux map, the
+absorbed flux map, or both.
GRAMMAR
-------
@@ -62,12 +64,17 @@ _______
<receiver> ::= name: <entity-identifier>
side: <side-identifier>
- [ per_primitive: INTEGER ] # in [0, 1]
+ [ per_primitive: <per-primitive-mode> ]
<side-identifier> ::= FRONT
| BACK
| FRONT_AND_BACK
+<per-primitive-mode> ::= NONE
+ | INCOMING
+ | ABSORBED
+ | INCOMING_AND_ABSORBED
+
<entity-identifier> # Defined in *solstice-input*(5)
_______
@@ -75,12 +82,13 @@ EXAMPLES
--------
Define that the front and back side of the entity *small_square* are
-receivers. For each side, enable the computation of per triangle irradiance.
+receivers. For each side, enable the computation of per triangle absorbed
+irradiance.
.......
- name: small_square
side: FRONT_AND_BACK
- per_primitive: 1
+ per_primitive: ABSORBED
.......
Declare that the front side of 3 reflectors are receivers. Use the YAML
@@ -93,11 +101,11 @@ compact notation to reduce the number of lines:
......
Declare that the back side of *receiver* is effectively a receiver and enable
-the estimation of its associated irradiance map. Make a receiver from the front
-side of the reflector named *LFR0.pivot.reflector*:
+the estimation of its associated incoming irradiance map. Make a receiver from
+the front side of the reflector named *LFR0.pivot.reflector*:
.......
-- {name: receiver, side: BACK, per_primitive: 1}
+- {name: receiver, side: BACK, per_primitive: INCOMING}
- {name: LFR0.pivot.reflector, side: FRONT}
.......
diff --git a/src/receivers/srcvl.c b/src/receivers/srcvl.c
@@ -28,7 +28,7 @@
struct receiver {
struct str name;
enum srcvl_side side;
- int per_primitive;
+ enum srcvl_pp_output per_primitive_output;
};
static INLINE void
@@ -37,7 +37,7 @@ receiver_init(struct mem_allocator* allocator, struct receiver* receiver)
ASSERT(receiver);
str_init(allocator, &receiver->name);
receiver->side = SRCVL_FRONT_AND_BACK;
- receiver->per_primitive = 0;
+ receiver->per_primitive_output = SRCVL_PP_NONE;
}
static INLINE void
@@ -52,7 +52,7 @@ receiver_copy(struct receiver* dst, const struct receiver* src)
{
ASSERT(dst && src);
dst->side = src->side;
- dst->per_primitive = src->per_primitive;
+ dst->per_primitive_output = src->per_primitive_output;
return str_copy(&dst->name, &src->name);
}
@@ -61,7 +61,7 @@ receiver_copy_and_release(struct receiver* dst, struct receiver* src)
{
ASSERT(dst && src);
dst->side = src->side;
- dst->per_primitive = src->per_primitive;
+ dst->per_primitive_output = src->per_primitive_output;
return str_copy_and_release(&dst->name, &src->name);
}
@@ -168,26 +168,34 @@ error:
}
static res_T
-parse_integer(struct srcvl* srcvl, yaml_node_t* integer, int* dst)
+parse_pp_output
+ (struct srcvl* srcvl,
+ yaml_node_t* side,
+ enum srcvl_side* out_side)
{
res_T res = RES_OK;
- ASSERT(integer && dst);
+ ASSERT(side && out_side);
- if(integer->type != YAML_SCALAR_NODE
- || !strlen((char*)integer->data.scalar.value)) {
- log_err(srcvl, integer, "expect an integer.\n");
+ if(side->type != YAML_SCALAR_NODE) {
+ log_err(srcvl, side, "expect a character string.\n");
res = RES_BAD_ARG;
goto error;
}
- res = cstr_to_int((char*)integer->data.scalar.value, dst);
- if(res != RES_OK) {
- log_err(srcvl, integer, "invalid integer `%s'.\n",
- integer->data.scalar.value);
+ if(!strcmp((char*) side->data.scalar.value, "NONE")) {
+ *out_side = SRCVL_PP_NONE;
+ } else if(!strcmp((char*) side->data.scalar.value, "INCOMING")) {
+ *out_side = SRCVL_PP_INCOMING;
+ } else if(!strcmp((char*) side->data.scalar.value, "ABSORBED")) {
+ *out_side = SRCVL_PP_ABSORBED;
+ } else if(!strcmp((char*) side->data.scalar.value, "INCOMING_AND_ABSORBED")) {
+ *out_side = SRCVL_PP_INCOMING_AND_ABSORBED;
+ } else {
+ log_err(srcvl, side, "unknown per primitive output type value `%s'.\n",
+ side->data.scalar.value);
res = RES_BAD_ARG;
goto error;
}
-
exit:
return res;
error:
@@ -251,7 +259,7 @@ parse_receiver
res = parse_side(srcvl, val, &solreceiver->side);
} else if(!strcmp((char*)key->data.scalar.value, "per_primitive")) {
SETUP_MASK(PER_PRIMITIVE, "per_primitive");
- res = parse_integer(srcvl, val, &solreceiver->per_primitive);
+ res = parse_pp_output(srcvl, val, &solreceiver->per_primitive_output);
} else {
log_err(srcvl, key, "unknown receiver parameter `%s'.\n",
key->data.scalar.value);
@@ -461,6 +469,6 @@ srcvl_get
r = darray_receiver_cdata_get(&srcvl->receivers) + i;
receiver->name = str_cget(&r->name);
receiver->side = r->side;
- receiver->per_primitive = r->per_primitive;
+ receiver->per_primitive_output = r->per_primitive_output;
}
diff --git a/src/receivers/srcvl.h b/src/receivers/srcvl.h
@@ -19,15 +19,22 @@
#include <rsys/rsys.h>
enum srcvl_side {
- SRCVL_FRONT,
- SRCVL_BACK,
- SRCVL_FRONT_AND_BACK
+ SRCVL_FRONT = BIT(0),
+ SRCVL_BACK = BIT(1),
+ SRCVL_FRONT_AND_BACK = SRCVL_FRONT + SRCVL_BACK
+};
+
+enum srcvl_pp_output {
+ SRCVL_PP_NONE = 0,
+ SRCVL_PP_INCOMING = BIT(0),
+ SRCVL_PP_ABSORBED = BIT(1),
+ SRCVL_PP_INCOMING_AND_ABSORBED = SRCVL_PP_INCOMING + SRCVL_PP_ABSORBED
};
struct srcvl_receiver {
const char* name;
enum srcvl_side side;
- int per_primitive; /* Define if per primitive receiver is enabled */
+ enum srcvl_pp_output per_primitive_output;
};
struct mem_allocator;
diff --git a/src/receivers/test_srcvl2.c b/src/receivers/test_srcvl2.c
@@ -39,48 +39,60 @@ main(int argc, char** argv)
fprintf(stream, "- { name: entity3, side: BACK }\n");
fprintf(stream, "- name: entity4\n");
fprintf(stream, " side: FRONT_AND_BACK\n");
- fprintf(stream, "- { name: entity5, side: BACK, per_primitive: 1 }\n");
- fprintf(stream, "- { name: entity6, per_primitive: 0, side: FRONT }\n");
+ fprintf(stream, "- { name: entity5, side: BACK, per_primitive: INCOMING }\n");
+ fprintf(stream, "- { name: entity6, side: BACK, per_primitive: ABSORBED }\n");
+ fprintf(stream, "- { name: entity7, side: BACK, per_primitive: INCOMING_AND_ABSORBED }\n");
+ fprintf(stream, "- { name: entity8, per_primitive: NONE, side: FRONT }\n");
rewind(stream);
CHK(srcvl_setup_stream(srcvl, NULL, stream) == RES_OK);
CHK(srcvl_load(srcvl) == RES_OK);
- CHK(srcvl_count(srcvl) == 7);
+ CHK(srcvl_count(srcvl) == 9);
srcvl_get(srcvl, 0, &receiver);
CHK(strcmp(receiver.name, "entity0") == 0);
CHK(receiver.side == SRCVL_FRONT_AND_BACK);
- CHK(receiver.per_primitive == 0);
+ CHK(receiver.per_primitive_output == SRCVL_PP_NONE);
srcvl_get(srcvl, 1, &receiver);
CHK(strcmp(receiver.name, "entity1") == 0);
CHK(receiver.side == SRCVL_FRONT_AND_BACK);
- CHK(receiver.per_primitive == 0);
+ CHK(receiver.per_primitive_output == SRCVL_PP_NONE);
srcvl_get(srcvl, 2, &receiver);
CHK(strcmp(receiver.name, "entity2") == 0);
CHK(receiver.side == SRCVL_FRONT);
- CHK(receiver.per_primitive == 0);
+ CHK(receiver.per_primitive_output == SRCVL_PP_NONE);
srcvl_get(srcvl, 3, &receiver);
CHK(strcmp(receiver.name, "entity3") == 0);
CHK(receiver.side == SRCVL_BACK);
- CHK(receiver.per_primitive == 0);
+ CHK(receiver.per_primitive_output == SRCVL_PP_NONE);
srcvl_get(srcvl, 4, &receiver);
CHK(strcmp(receiver.name, "entity4") == 0);
CHK(receiver.side == SRCVL_FRONT_AND_BACK);
- CHK(receiver.per_primitive == 0);
+ CHK(receiver.per_primitive_output == SRCVL_PP_NONE);
srcvl_get(srcvl, 5, &receiver);
CHK(strcmp(receiver.name, "entity5") == 0);
CHK(receiver.side == SRCVL_BACK);
- CHK(receiver.per_primitive == 1);
+ CHK(receiver.per_primitive_output == SRCVL_PP_INCOMING);
srcvl_get(srcvl, 6, &receiver);
CHK(strcmp(receiver.name, "entity6") == 0);
+ CHK(receiver.side == SRCVL_BACK);
+ CHK(receiver.per_primitive_output == SRCVL_PP_ABSORBED);
+
+ srcvl_get(srcvl, 7, &receiver);
+ CHK(strcmp(receiver.name, "entity7") == 0);
+ CHK(receiver.side == SRCVL_BACK);
+ CHK(receiver.per_primitive_output == SRCVL_PP_INCOMING_AND_ABSORBED);
+
+ srcvl_get(srcvl, 8, &receiver);
+ CHK(strcmp(receiver.name, "entity8") == 0);
CHK(receiver.side == SRCVL_FRONT);
- CHK(receiver.per_primitive == 0);
+ CHK(receiver.per_primitive_output == SRCVL_PP_NONE);
CHK(srcvl_load(srcvl) == RES_BAD_OP);
diff --git a/src/receivers/yaml/test_ko.yaml b/src/receivers/yaml/test_ko.yaml
@@ -25,4 +25,7 @@
- name: test
per_primitive:
---
-- per_primitive: 1
+- name: test
+ per_primitive: NOPE
+---
+- per_primitive: NONE
diff --git a/src/receivers/yaml/test_ok.yaml b/src/receivers/yaml/test_ok.yaml
@@ -13,6 +13,6 @@
{name: test},
{side: FRONT_AND_BACK, name: "Hello world"},
{name: Hello world, side: BACK}
- {name: hop, per_primitive: 1}
+ {name: hop, per_primitive: ABSORBED}
{per_primitive: 0, name: test}
]
diff --git a/src/solstice.c b/src/solstice.c
@@ -357,7 +357,7 @@ setup_sun_dirs(struct solstice* solstice, const struct solstice_args* args)
goto error;
}
res = darray_double_resize(&solstice->sun_angles, args->nsun_dirs*2/*#dims*/);
- if (res != RES_OK) {
+ if(res != RES_OK) {
fprintf(stderr,
"Could not reserve the list of %lu sun angles.\n",
(unsigned long)args->nsun_dirs);
@@ -476,7 +476,7 @@ setup_receivers(struct solstice* solstice, struct srcvl* srcvl)
receiver->node = NULL;
receiver->side = rcv.side;
- receiver->per_primitive = rcv.per_primitive;
+ receiver->per_primitive_output = rcv.per_primitive_output;
name = str_cget(&receiver->name);
res = htable_receiver_set(&solstice->receivers, &name, &i);
diff --git a/src/solstice.h b/src/solstice.h
@@ -37,7 +37,7 @@ struct solstice_receiver {
struct str name;
struct solstice_node* node;
enum srcvl_side side;
- int per_primitive;
+ enum srcvl_pp_output per_primitive_output;
};
static INLINE void
@@ -48,7 +48,7 @@ solstice_receiver_init
str_init(allocator, &rcv->name);
rcv->node = NULL;
rcv->side = SRCVL_FRONT_AND_BACK;
- rcv->per_primitive = 0;
+ rcv->per_primitive_output = SRCVL_PP_NONE;
}
static INLINE void
@@ -66,7 +66,7 @@ solstice_receiver_copy
ASSERT(dst && src);
dst->node = src->node;
dst->side = src->side;
- dst->per_primitive = src->per_primitive;
+ dst->per_primitive_output = src->per_primitive_output;
return str_copy(&dst->name, &src->name);
}
@@ -79,7 +79,7 @@ solstice_receiver_copy_and_release
ASSERT(dst && src);
dst->node = src->node;
dst->side = src->side;
- dst->per_primitive = src->per_primitive;
+ dst->per_primitive_output = src->per_primitive_output;
res = str_copy_and_release(&dst->name, &src->name);
if(res != RES_OK) return res;
solstice_receiver_release(src);
diff --git a/src/solstice_entity.c b/src/solstice_entity.c
@@ -83,6 +83,20 @@ srcvl_side_to_ssol_mask(const enum srcvl_side side)
return mask;
}
+static INLINE int
+srcvl_per_prim_to_bool(const enum srcvl_pp_output output)
+{
+ int mask = 0;
+ switch (output) {
+ case SRCVL_PP_NONE: mask = 0; break;
+ case SRCVL_PP_INCOMING: mask = 1; break;
+ case SRCVL_PP_ABSORBED: mask = 1; break;
+ case SRCVL_PP_INCOMING_AND_ABSORBED: mask = 1; break;
+ default: FATAL("Unreachable code.\n"); break;
+ }
+ return mask;
+}
+
static struct solstice_node*
create_empty_node
(struct solstice* solstice, const struct solparser_entity* entity)
@@ -338,11 +352,11 @@ create_node
str_cget(&entity->name));
goto error;
}
- if (entity->primary) {
+ if(entity->primary) {
struct solstice_primary p;
p.node = node;
res = htable_primary_set(&solstice->primaries, name, &p);
- if (res != RES_OK) {
+ if(res != RES_OK) {
fprintf(stderr, "Could not define the entity `%s' as primary.\n",
str_cget(&entity->name));
goto error;
@@ -354,13 +368,14 @@ create_node
str = str_cget(name);
pircv = htable_receiver_find(&solstice->receivers, &str);
if(pircv) {
- int mask;
+ int side_mask, output;
rcv = darray_receiver_data_get(&solstice->rcvs_list) + *pircv;
ASSERT(rcv->node == NULL); /* Receiver is not attached to a node */
- mask = srcvl_side_to_ssol_mask(rcv->side);
+ side_mask = srcvl_side_to_ssol_mask(rcv->side);
+ output = srcvl_per_prim_to_bool(rcv->per_primitive_output);
- res = solstice_node_geometry_set_receiver(node, mask, rcv->per_primitive);
+ res = solstice_node_geometry_set_receiver(node, side_mask, output);
if(res != RES_OK) {
fprintf(stderr, "Could not define the entity `%s' as a receiver.\n",
str_cget(&entity->name));
diff --git a/src/solstice_solve.c b/src/solstice_solve.c
@@ -136,7 +136,7 @@ write_mc_global(struct solstice* solstice, struct ssol_estimator* estimator)
/* Primary-instances' data */
htable_primary_begin(&solstice->primaries, &p_it);
htable_primary_end(&solstice->primaries, &p_end);
- while (!htable_primary_iterator_eq(&p_it, &p_end)) {
+ while(!htable_primary_iterator_eq(&p_it, &p_end)) {
const struct str* name = htable_primary_iterator_key_get(&p_it);
struct solstice_primary* prim = htable_primary_iterator_data_get(&p_it);
struct ssol_mc_sampled sampled;
@@ -165,7 +165,7 @@ write_mc_global(struct solstice* solstice, struct ssol_estimator* estimator)
SSOL(instance_get_id(rcv_inst, &rcv_id));
htable_primary_begin(&solstice->primaries, &p_it);
htable_primary_end(&solstice->primaries, &p_end);
- while (!htable_primary_iterator_eq(&p_it, &p_end)) {
+ while(!htable_primary_iterator_eq(&p_it, &p_end)) {
struct solstice_primary* prim = htable_primary_iterator_data_get(&p_it);
struct ssol_instance* prim_inst = prim->node->instance;
struct ssol_mc_receiver front = MC_RCV_NONE__;
@@ -259,7 +259,7 @@ dump_shape_triangle_indices
}
static void
-dump_mc_shape
+dump_mc_shape_in
(struct solstice* solstice,
struct ssol_shape* shape,
struct ssol_mc_shape* mc_shape)
@@ -278,15 +278,36 @@ dump_mc_shape
}
static void
+dump_mc_shape_abs
+ (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.absorbed_flux.E,
+ mc_prim.absorbed_flux.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)
+ const enum ssol_side_flag side,
+ const enum srcvl_pp_output output)
{
size_t ishape, nshapes;
struct ssol_mc_receiver mc_rcv;
const char* name;
+ const char* flux;
ASSERT(solstice && estimator && inst);
SSOL(estimator_get_mc_receiver(estimator, inst, side, &mc_rcv));
@@ -296,8 +317,13 @@ dump_per_primitive_mc_estimations
case SSOL_BACK: name = "Back_faces"; break;
default: FATAL("Unreachable code.\n"); break;
}
+ switch (output) {
+ case SRCVL_PP_INCOMING: flux = "Incoming_flux"; break;
+ case SRCVL_PP_ABSORBED: flux = "Absorbed_flux"; break;
+ default: FATAL("Unreachable code.\n"); break;
+ }
- fprintf(solstice->output, "SCALARS %s float 2\n", name);
+ fprintf(solstice->output, "SCALARS %s__%s float 2\n", name, flux);
fprintf(solstice->output, "LOOKUP_TABLE default\n");
SSOL(instance_get_shaded_shapes_count(inst, &nshapes));
@@ -306,7 +332,14 @@ dump_per_primitive_mc_estimations
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);
+ switch (output) {
+ case SRCVL_PP_INCOMING:
+ dump_mc_shape_in(solstice, inst_sshape.shape, &mc_shape);
+ break;
+ case SRCVL_PP_ABSORBED:
+ dump_mc_shape_abs(solstice, inst_sshape.shape, &mc_shape);
+ break;
+ }
}
}
@@ -327,6 +360,7 @@ write_per_receiver_mc_primitive
size_t offset;
int mask, prim;
+ ASSERT(rcv->side);
SSOL(instance_is_receiver(inst, &mask, &prim));
CHK(mask != 0);
if(!prim) continue;
@@ -371,18 +405,25 @@ write_per_receiver_mc_primitive
/* 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;
+ if(rcv->side & SRCVL_FRONT) {
+ if(rcv->per_primitive_output & SRCVL_PP_INCOMING) {
+ dump_per_primitive_mc_estimations(solstice, estimator, inst,
+ SSOL_FRONT, SRCVL_PP_INCOMING);
+ }
+ if(rcv->per_primitive_output & SRCVL_PP_ABSORBED) {
+ dump_per_primitive_mc_estimations(solstice, estimator, inst,
+ SSOL_FRONT, SRCVL_PP_ABSORBED);
+ }
+ }
+ if(rcv->side & SRCVL_BACK) {
+ if(rcv->per_primitive_output & SRCVL_PP_INCOMING) {
+ dump_per_primitive_mc_estimations(solstice, estimator, inst,
+ SSOL_BACK, SRCVL_PP_INCOMING);
+ }
+ if(rcv->per_primitive_output & SRCVL_PP_ABSORBED) {
+ dump_per_primitive_mc_estimations(solstice, estimator, inst,
+ SSOL_BACK, SRCVL_PP_ABSORBED);
+ }
}
}
}