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 47965602f1064654c333c0e048253f67e0f3a6de
parent 8af1dd6353c0d9dbdbdd238b75ba6fad0ee23b32
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date:   Fri, 31 Mar 2017 11:02:06 +0200

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

Diffstat:
Mcmake/CMakeLists.txt | 1+
Msrc/solstice.c | 2++
Msrc/solstice.h | 16++++++++++++++++
Msrc/solstice_entity.c | 28+++++++++++++++++++++++-----
Msrc/solstice_solve.c | 165+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------
Msrc/test_solstice_simulation.c | 384+++++++++++++++++++++++++++++++++++++++++++++++++------------------------------
Myaml/beam_down.ref | 52++++++++++++++++++++++++++++++++++++++++++++++------
Myaml/test01.ref | 11+++++++++--
Myaml/test02.ref | 13++++++++++---
Myaml/test02.yaml | 4+++-
Myaml/test03.ref | 11+++++++++--
Myaml/test04.ref | 12++++++++++--
Myaml/test05.ref | 11+++++++++--
Ayaml/test06.ref | 12++++++++++++
Ayaml/test06.yaml | 62++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ayaml/test06_receiver.yaml | 1+
16 files changed, 584 insertions(+), 201 deletions(-)

diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt @@ -155,6 +155,7 @@ if(NOT NO_TEST) add_test_simulation(test03) add_test_simulation(test04) add_test_simulation(test05) + add_test_simulation(test06) endif() diff --git a/src/solstice.c b/src/solstice.c @@ -536,6 +536,7 @@ solstice_init htable_object_init(allocator, &solstice->objects); htable_anchor_init(allocator, &solstice->anchors); htable_receiver_init(allocator, &solstice->receivers); + htable_primary_init(allocator, &solstice->primaries); darray_nodes_init(allocator, &solstice->roots); darray_nodes_init(allocator, &solstice->pivots); darray_double_init(allocator, &solstice->sun_dirs); @@ -644,6 +645,7 @@ solstice_release(struct solstice* solstice) htable_object_release(&solstice->objects); htable_anchor_release(&solstice->anchors); htable_receiver_release(&solstice->receivers); + htable_primary_release(&solstice->primaries); darray_nodes_release(&solstice->roots); darray_nodes_release(&solstice->pivots); darray_double_release(&solstice->sun_dirs); diff --git a/src/solstice.h b/src/solstice.h @@ -38,6 +38,10 @@ struct solstice_receiver { int per_primitive; }; +struct solstice_primary { + struct solstice_node* node; +}; + #define DARRAY_NAME nodes #define DARRAY_DATA struct solstice_node* #include <rsys/dynamic_array.h> @@ -69,6 +73,17 @@ struct solstice_receiver { #define HTABLE_DATA struct solstice_receiver #include <rsys/hash_table.h> +#define HTABLE_NAME primary +#define HTABLE_KEY struct str +#define HTABLE_KEY_FUNCTOR_INIT str_init +#define HTABLE_KEY_FUNCTOR_RELEASE str_release +#define HTABLE_KEY_FUNCTOR_COPY str_copy +#define HTABLE_KEY_FUNCTOR_COPY_AND_RELEASE str_copy_and_release +#define HTABLE_KEY_FUNCTOR_EQ str_eq +#define HTABLE_KEY_FUNCTOR_HASH str_hash +#define HTABLE_DATA struct solstice_primary +#include <rsys/hash_table.h> + struct solstice { struct ssol_device* ssol; struct ssol_scene* scene; @@ -80,6 +95,7 @@ struct solstice { struct htable_object objects; struct htable_anchor anchors; struct htable_receiver receivers; + struct htable_primary primaries; struct darray_nodes roots; struct darray_nodes pivots; struct ssol_material* mtl_virtual; /* Shared virtual material */ diff --git a/src/solstice_entity.c b/src/solstice_entity.c @@ -19,6 +19,8 @@ #include <solstice/ssol.h> #include <solstice/sanim.h> +#include <rsys/double33.h> + /******************************************************************************* * Helper function ******************************************************************************/ @@ -26,13 +28,19 @@ static res_T update_instance_transform (const struct sanim_node* n, const double transform[12], void* data) { + res_T res = RES_OK; struct solstice_node* node; - ASSERT(n && transform); + ASSERT(n && transform && data); (void)data; - node = CONTAINER_OF(n, struct solstice_node, anim); if(node->type != SOLSTICE_NODE_GEOMETRY) return RES_OK; - return ssol_instance_set_transform(node->instance, transform); + res = ssol_instance_set_transform(node->instance, transform); + if(res != RES_OK) goto error; + +exit: + return res; +error: + goto exit; } static res_T @@ -328,6 +336,16 @@ create_node str_cget(&entity->name)); goto error; } + if (entity->primary) { + struct solstice_primary p; + p.node = node; + res = htable_primary_set(&solstice->primaries, name, &p); + if (res != RES_OK) { + fprintf(stderr, "Could not define the entity `%s' as primary.\n", + str_cget(&entity->name)); + goto error; + } + } } /* Setup the entity receiver flags */ @@ -448,7 +466,7 @@ solstice_setup_entities(struct solstice* solstice) /* Initialialised the world space position of the entity geometry */ res = sanim_node_visit_tree - (&root->anim, dummy_sun_dir, NULL, update_instance_transform); + (&root->anim, dummy_sun_dir, solstice, update_instance_transform); if(res != RES_OK) { fprintf(stderr, "Could not setup the transformation of the entity geometries.\n"); @@ -486,7 +504,7 @@ solstice_update_entities(struct solstice* solstice, const double sun_dir[3]) /* Initialialised the world space position of the entity geometry */ res = sanim_node_visit_tree - (&node->anim, sun_dir, NULL, update_instance_transform); + (&node->anim, sun_dir, solstice, update_instance_transform); if(res != RES_OK) { fprintf(stderr, "Could not update the transformation of the entity geometries.\n"); diff --git a/src/solstice_solve.c b/src/solstice_solve.c @@ -26,10 +26,11 @@ static void write_mc_global(struct solstice* solstice, struct ssol_estimator* estimator) { struct ssol_mc_global mc_global; - struct htable_receiver_iterator it, end; + struct htable_receiver_iterator r_it, r_end; + struct htable_primary_iterator p_it, p_end; const struct solparser_sun* solparser_sun = NULL; - size_t nexperiments; - double irradiance_factor; + size_t nexperiments, nfailed, nprimary; + double area, potential, irradiance_factor; ASSERT(solstice && estimator); #define MC_RCV_NONE { \ @@ -42,20 +43,44 @@ write_mc_global(struct solstice* solstice, struct ssol_estimator* estimator) /* get global information */ SSOL(estimator_get_mc_global(estimator, &mc_global)); - SSOL(estimator_get_count(estimator, &nexperiments)); - SSOL(estimator_get_sampled_area(estimator, &irradiance_factor)); + SSOL(estimator_get_realisation_count(estimator, &nexperiments)); + SSOL(estimator_get_sampled_count(estimator, &nprimary)); + SSOL(estimator_get_failed_count(estimator, &nfailed)); + SSOL(estimator_get_sampled_area(estimator, &area)); solparser_sun = solparser_get_sun(solstice->parser); - irradiance_factor = 1.0 / (solparser_sun->dni * irradiance_factor); + potential = solparser_sun->dni * area; + irradiance_factor = 1 / potential; - fprintf(solstice->output, "%lu %lu\n", + /* Counts */ + fprintf(solstice->output, "%lu %lu %lu %lu %lu\n", + 7, /* #global results count */ (unsigned long)htable_receiver_size_get(&solstice->receivers), - (unsigned long)nexperiments); + (unsigned long)nprimary, + (unsigned long)nexperiments, + (unsigned long)nfailed); - htable_receiver_begin(&solstice->receivers, &it); - htable_receiver_end(&solstice->receivers, &end); - while(!htable_receiver_iterator_eq(&it, &end)) { - const struct str* name = htable_receiver_iterator_key_get(&it); - struct solstice_receiver* rcv = htable_receiver_iterator_data_get(&it); + /* Global data */ + fprintf(solstice->output, "%g %g\n", + potential, 0.); + fprintf(solstice->output, "%g %g\n", + mc_global.absorbed.E, mc_global.absorbed.SE); + fprintf(solstice->output, "%g %g\n", + mc_global.cos_factor.E, mc_global.cos_factor.SE); + fprintf(solstice->output, "%g %g\n", + mc_global.shadowed.E, mc_global.shadowed.SE); + fprintf(solstice->output, "%g %g\n", + mc_global.missing.E, mc_global.missing.SE); + fprintf(solstice->output, "%g %g\n", + mc_global.atmosphere.E, mc_global.atmosphere.SE); + fprintf(solstice->output, "%g %g\n", + mc_global.reflectivity.E, mc_global.reflectivity.SE); + + /* Receivers' data */ + htable_receiver_begin(&solstice->receivers, &r_it); + htable_receiver_end(&solstice->receivers, &r_end); + while(!htable_receiver_iterator_eq(&r_it, &r_end)) { + const struct str* name = htable_receiver_iterator_key_get(&r_it); + struct solstice_receiver* rcv = htable_receiver_iterator_data_get(&r_it); struct ssol_instance* inst = rcv->node->instance; struct ssol_mc_receiver front = MC_RCV_NONE; struct ssol_mc_receiver back = MC_RCV_NONE; @@ -63,47 +88,121 @@ write_mc_global(struct solstice* solstice, struct ssol_estimator* estimator) double b_eff_E = -1, b_eff_SE = -1; /* Back efficiency */ uint32_t id; - htable_receiver_iterator_next(&it); + htable_receiver_iterator_next(&r_it); switch(rcv->side) { case SRCVL_FRONT: SSOL(estimator_get_mc_receiver(estimator, inst, SSOL_FRONT, &front)); - f_eff_E = front.integrated_irradiance.E * irradiance_factor; - f_eff_SE = front.integrated_irradiance.SE * irradiance_factor; + f_eff_E = front.integrated_absorbed_irradiance.E * irradiance_factor; + f_eff_SE = front.integrated_absorbed_irradiance.SE * irradiance_factor; break; case SRCVL_BACK: SSOL(estimator_get_mc_receiver(estimator, inst, SSOL_BACK, &back)); - b_eff_E = back.integrated_irradiance.E * irradiance_factor; - b_eff_SE = back.integrated_irradiance.SE * irradiance_factor; + b_eff_E = back.integrated_absorbed_irradiance.E * irradiance_factor; + b_eff_SE = back.integrated_absorbed_irradiance.SE * irradiance_factor; break; case SRCVL_FRONT_AND_BACK: SSOL(estimator_get_mc_receiver(estimator, inst, SSOL_FRONT, &front)); SSOL(estimator_get_mc_receiver(estimator, inst, SSOL_BACK, &back)); - f_eff_E = front.integrated_irradiance.E * irradiance_factor; - f_eff_SE = front.integrated_irradiance.SE * irradiance_factor; - b_eff_E = back.integrated_irradiance.E * irradiance_factor; - b_eff_SE = back.integrated_irradiance.SE * irradiance_factor; + f_eff_E = front.integrated_absorbed_irradiance.E * irradiance_factor; + f_eff_SE = front.integrated_absorbed_irradiance.SE * irradiance_factor; + b_eff_E = back.integrated_absorbed_irradiance.E * irradiance_factor; + b_eff_SE = back.integrated_absorbed_irradiance.SE * irradiance_factor; break; default: FATAL("Unreachable code.\n"); break; } SSOL(instance_get_id(inst, &id)); + SSOL(instance_get_area(inst, &area)); fprintf(solstice->output, - "%s %u %g %g %g %g %g %g %g %g %g %g %g %g %g %g %g %g %g %g %g %g\n", - str_cget(name), (unsigned)id, + "%s %u %g " + "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, area, + front.integrated_absorbed_irradiance.E, front.integrated_absorbed_irradiance.SE, front.integrated_irradiance.E, front.integrated_irradiance.SE, - back.integrated_irradiance.E, back.integrated_irradiance.SE, front.reflectivity_loss.E, front.reflectivity_loss.SE, - back.reflectivity_loss.E, back.reflectivity_loss.SE, front.absorptivity_loss.E, front.absorptivity_loss.SE, + f_eff_E, f_eff_SE, + back.integrated_absorbed_irradiance.E, back.integrated_absorbed_irradiance.SE, + back.integrated_irradiance.E, back.integrated_irradiance.SE, + back.reflectivity_loss.E, back.reflectivity_loss.SE, back.absorptivity_loss.E, back.absorptivity_loss.SE, - front.cos_loss.E, front.cos_loss.SE, - back.cos_loss.E, back.cos_loss.SE, - f_eff_E, f_eff_SE, b_eff_E, b_eff_SE); + b_eff_E, b_eff_SE); } - fprintf(solstice->output, "%g %g\n", - mc_global.shadowed.E, mc_global.shadowed.SE); - fprintf(solstice->output, "%g %g\n", - mc_global.missing.E, mc_global.missing.SE); + /* 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)) { + 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; + uint32_t id; + + htable_primary_iterator_next(&p_it); + SSOL(estimator_get_mc_sampled(estimator, prim->node->instance, &sampled)); + SSOL(instance_get_id(prim->node->instance, &id)); + SSOL(instance_get_area(prim->node->instance, &area)); + fprintf(solstice->output, + "%s %u %g %lu " + "%g %g %g %g\n", + str_cget(name), (unsigned) id, area, (unsigned long)sampled.nb_samples, + sampled.cos_factor.E, sampled.cos_factor.SE, + sampled.shadowed.E, sampled.shadowed.SE + ); + } + + /* ReceiverXprimarys' data */ + htable_receiver_begin(&solstice->receivers, &r_it); + htable_receiver_end(&solstice->receivers, &r_end); + while (!htable_receiver_iterator_eq(&r_it, &r_end)) { + struct solstice_receiver* rcv = htable_receiver_iterator_data_get(&r_it); + struct ssol_instance* rcv_inst = rcv->node->instance; + uint32_t rcv_id, prim_id; + + 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)) { + 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; + struct ssol_mc_receiver back = MC_RCV_NONE; + + SSOL(instance_get_id(prim_inst, &prim_id)); + switch (rcv->side) { + case SRCVL_FRONT: + SSOL(estimator_get_mc_sampled_x_receiver + (estimator, prim_inst, rcv_inst, SSOL_FRONT, &front)); + break; + case SRCVL_BACK: + SSOL(estimator_get_mc_sampled_x_receiver + (estimator, prim_inst, rcv_inst, SSOL_BACK, &back)); + break; + case SRCVL_FRONT_AND_BACK: + SSOL(estimator_get_mc_sampled_x_receiver + (estimator, prim_inst, rcv_inst, SSOL_FRONT, &front)); + SSOL(estimator_get_mc_sampled_x_receiver + (estimator, prim_inst, rcv_inst, SSOL_BACK, &back)); + break; + default: FATAL("Unreachable code.\n"); break; + } + fprintf(solstice->output, + "%u %u " + "FRONT: %g %g %g %g %g %g %g %g " + "BACK: %g %g %g %g %g %g %g %g\n", + (unsigned) rcv_id, (unsigned) prim_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, + front.absorptivity_loss.E, front.absorptivity_loss.SE, + back.integrated_absorbed_irradiance.E, back.integrated_absorbed_irradiance.SE, + back.integrated_irradiance.E, back.integrated_irradiance.SE, + back.reflectivity_loss.E, back.reflectivity_loss.SE, + back.absorptivity_loss.E, back.absorptivity_loss.SE); + htable_primary_iterator_next(&p_it); + } + htable_receiver_iterator_next(&r_it); + } } static void diff --git a/src/test_solstice_simulation.c b/src/test_solstice_simulation.c @@ -17,6 +17,7 @@ #include <rsys/rsys.h> #include <rsys/math.h> +#include <rsys/double2.h> #include <math.h> #include <stdio.h> @@ -37,20 +38,52 @@ enum side { BACK }; -enum result_type { +enum global_result_type { + GLOBAL_POTENTIAL, + GLOBAL_ABSORBED, + GLOBAL_COS, + GLOBAL_SHADOW, + GLOBAL_MISSING, + GLOBAL_ATMOSPHERE, + GLOBAL_REFLECTIVITY, + GLOBAL_RESULTS_COUNT__ +}; + +enum receiver_result_type { + FIRST_RECEIVER_RESULT, + FRONT_INTEGRATED_ABSORBED_IRRADIANCE = FIRST_RECEIVER_RESULT, FRONT_INTEGRATED_IRRADIANCE, - BACK_INTEGRATED_IRRADIANCE, FRONT_REFLECTIVITY_LOSS, - BACK_REFLECTIVITY_LOSS, FRONT_ABSORPTIVITY_LOSS, - BACK_ABSORPTIVITY_LOSS, - FRONT_COS_LOSS, - BACK_COS_LOSS, FRONT_EFFICIENCY, + BACK_INTEGRATED_ABSORBED_IRRADIANCE, + BACK_INTEGRATED_IRRADIANCE, + BACK_REFLECTIVITY_LOSS, + BACK_ABSORPTIVITY_LOSS, BACK_EFFICIENCY, - MAX_RESULTS_COUNT__ + RECEIVER_RESULTS_COUNT__ +}; + +enum primary_result_type { + FIRST_PRIMARY_RESULT, + PRIMARY_SHADOW = FIRST_PRIMARY_RESULT, + PRIMARY_RESULTS_COUNT__ }; +struct counts { + unsigned long global, receiver, primary, realisation, failed; +}; + +static int +counts_ok(const struct counts* ref, const struct counts* c) +{ + CHECK(ref->global, GLOBAL_RESULTS_COUNT__); + CHECK(c->global, GLOBAL_RESULTS_COUNT__); + return ref->receiver == c->receiver + && ref->primary == c->primary + && ref->failed >= c->failed; +} + #define MAX_LINE_LEN 2048 static const char @@ -170,63 +203,146 @@ read_line(char* line, size_t max_line_len, FILE* stream) return 1; } -static void -get_dir_and_counts - (FILE* ref_file, +static int +get_angles_and_counts + (FILE* file, double angles[2], - unsigned long* recv_count, - unsigned long* realisation_count) + struct counts* counts) { char line[MAX_LINE_LEN]; - int n; + int r; - NCHECK(ref_file, NULL); + NCHECK(file, NULL); NCHECK(angles, NULL); - NCHECK(recv_count, NULL); - NCHECK(realisation_count, NULL); + NCHECK(counts, NULL); /* Get sun dir */ - CHECK(read_line(line, sizeof(line), ref_file), 1); + r = read_line(line, sizeof(line), file); + if (!r) { + CHECK(feof(file), 1); + return 0; + } CHECK(IS_NEW_BLOCK(line, sundir_header), 1); - n = sscanf(line+strlen(sundir_header), "%lg%lg", &angles[0], &angles[1]); - CHECK(n, 2); + CHECK( + sscanf(line+strlen(sundir_header), "%lg%lg", &angles[0], &angles[1]), + 2); + + /* Get counts */ + CHECK(read_line(line, sizeof(line), file), 1); + CHECK( + sscanf(line, + "%lu %lu %lu %lu %lu", + &counts->global, &counts->receiver, &counts->primary, + &counts->realisation, &counts->failed), + 5); + return 1; +} - /* Get #receivers and #realisations */ - CHECK(read_line(line, sizeof(line), ref_file), 1); - n = sscanf(line, "%lu%lu", recv_count, realisation_count); - CHECK(n, 2); +static void +read_global(FILE* file, double* E, double* SE) +{ + char line[MAX_LINE_LEN]; + CHECK(read_line(line, sizeof(line), file), 1); + CHECK( + sscanf(line, "%lg %lg", E, SE), + 2); } static void -read_recv(const char* line, char name[], double E[], double SE[]) +read_recv(FILE* file, char name[], double E[], double SE[]) { - int n; + char line[MAX_LINE_LEN]; - NCHECK(line, NULL); + NCHECK(file, NULL); NCHECK(name, NULL); NCHECK(E, NULL); NCHECK(SE, NULL); - n = sscanf(line, - "%s%*u%lg%lg%lg%lg%lg%lg%lg%lg%lg%lg%lg%lg%lg%lg%lg%lg%lg%lg%lg%lg", - name, - &E[FRONT_INTEGRATED_IRRADIANCE], &SE[FRONT_INTEGRATED_IRRADIANCE], - &E[BACK_INTEGRATED_IRRADIANCE], &SE[BACK_INTEGRATED_IRRADIANCE], - &E[FRONT_REFLECTIVITY_LOSS], &SE[FRONT_REFLECTIVITY_LOSS], - &E[BACK_REFLECTIVITY_LOSS], &SE[BACK_REFLECTIVITY_LOSS], - &E[FRONT_ABSORPTIVITY_LOSS], &SE[FRONT_ABSORPTIVITY_LOSS], - &E[BACK_ABSORPTIVITY_LOSS], &SE[BACK_ABSORPTIVITY_LOSS], - &E[FRONT_COS_LOSS], &SE[FRONT_COS_LOSS], - &E[BACK_COS_LOSS], &SE[BACK_COS_LOSS], - &E[FRONT_EFFICIENCY], &SE[FRONT_EFFICIENCY], - &E[BACK_EFFICIENCY], &SE[BACK_EFFICIENCY]); - - CHECK(n, 2*MAX_RESULTS_COUNT__+1); + CHECK(read_line(line, sizeof(line), file), 1); + CHECK( + sscanf(line, + "%s %*lu %*lg " + "FRONT: %lg %lg %lg %lg %lg %lg %lg %lg %lg %lg " + " BACK: %lg %lg %lg %lg %lg %lg %lg %lg %lg %lg", + name, /* ID, area */ + &E[FRONT_INTEGRATED_ABSORBED_IRRADIANCE], + &SE[FRONT_INTEGRATED_ABSORBED_IRRADIANCE], + &E[FRONT_INTEGRATED_IRRADIANCE], &SE[FRONT_INTEGRATED_IRRADIANCE], + &E[FRONT_REFLECTIVITY_LOSS], &SE[FRONT_REFLECTIVITY_LOSS], + &E[FRONT_ABSORPTIVITY_LOSS], &SE[FRONT_ABSORPTIVITY_LOSS], + &E[FRONT_EFFICIENCY], &SE[FRONT_EFFICIENCY], + &E[BACK_INTEGRATED_ABSORBED_IRRADIANCE], + &SE[BACK_INTEGRATED_ABSORBED_IRRADIANCE], + &E[BACK_INTEGRATED_IRRADIANCE], &SE[BACK_INTEGRATED_IRRADIANCE], + &E[BACK_REFLECTIVITY_LOSS], &SE[BACK_REFLECTIVITY_LOSS], + &E[BACK_ABSORPTIVITY_LOSS], &SE[BACK_ABSORPTIVITY_LOSS], + &E[BACK_EFFICIENCY], &SE[BACK_EFFICIENCY]), + 2 * RECEIVER_RESULTS_COUNT__ + 1); +} + +static void +read_primary + (FILE* file, char name[], double* area, double* cos, double E[], double SE[]) +{ + char line[MAX_LINE_LEN]; + + NCHECK(file, NULL); + NCHECK(area, NULL); + NCHECK(cos, NULL); + NCHECK(E, NULL); + NCHECK(SE, NULL); + + CHECK(read_line(line, sizeof(line), file), 1); + CHECK( + sscanf(line, + "%s %*lu " + "%lg %lg %*lu " + "%lg %lg\n", + name, /* ID */ + area, cos, /* count */ + &E[PRIMARY_SHADOW], &SE[PRIMARY_SHADOW]), + 2 * PRIMARY_RESULTS_COUNT__ + 3); +} + +static void +read_recvXprim + (FILE* file, + unsigned long* rcv_id, + unsigned long* prim_id, + double E[], + double SE[]) +{ + char line[MAX_LINE_LEN]; + + NCHECK(file, NULL); + NCHECK(rcv_id, NULL); + NCHECK(prim_id, NULL); + NCHECK(E, NULL); + NCHECK(SE, NULL); + + CHECK(read_line(line, sizeof(line), file), 1); + CHECK( + sscanf(line, + "%lu %lu " + "FRONT: %lg %lg %lg %lg %lg %lg %lg %lg " + " BACK: %lg %lg %lg %lg %lg %lg %lg %lg", + rcv_id, prim_id, + &E[FRONT_INTEGRATED_ABSORBED_IRRADIANCE], + &SE[FRONT_INTEGRATED_ABSORBED_IRRADIANCE], + &E[FRONT_INTEGRATED_IRRADIANCE], &SE[FRONT_INTEGRATED_IRRADIANCE], + &E[FRONT_REFLECTIVITY_LOSS], &SE[FRONT_REFLECTIVITY_LOSS], + &E[FRONT_ABSORPTIVITY_LOSS], &SE[FRONT_ABSORPTIVITY_LOSS], + &E[BACK_INTEGRATED_ABSORBED_IRRADIANCE], + &SE[BACK_INTEGRATED_ABSORBED_IRRADIANCE], + &E[BACK_INTEGRATED_IRRADIANCE], &SE[BACK_INTEGRATED_IRRADIANCE], + &E[BACK_REFLECTIVITY_LOSS], &SE[BACK_REFLECTIVITY_LOSS], + &E[BACK_ABSORPTIVITY_LOSS], &SE[BACK_ABSORPTIVITY_LOSS]), + 2 * (RECEIVER_RESULTS_COUNT__ - 2 /* efficiencies not read */) + 2); } #define POSITIVE_OR_M_ONE(x) ((x) == -1 || (x) >= 0) -static FINLINE int +static int is_compatible_with (const double ref_E, const double ref_SE, @@ -252,106 +368,80 @@ is_compatible_with static void check_1_reference - (FILE* tested_file, - const char* rcv_name, - const double* reference_E, - const double* reference_SE) + (FILE* ref_file, + FILE* test_file, + const struct counts* counts) { - double a[2]; - unsigned long c1, c2; - int found = 0; - - NCHECK(tested_file, NULL); - NCHECK(rcv_name, NULL); - NCHECK(reference_E, NULL); - NCHECK(reference_SE, NULL); - - get_dir_and_counts(tested_file, a, &c1, &c2); /* Skip headers */ + unsigned n; - while(!feof(tested_file) && !found) { - char line[MAX_LINE_LEN]; - char tested_rcv_name[MAX_LINE_LEN]; - double tested_E[MAX_RESULTS_COUNT__], tested_SE[MAX_RESULTS_COUNT__]; - enum result_type r; - - CHECK(read_line(line, sizeof(line), tested_file), 1); + NCHECK(ref_file, NULL); + NCHECK(test_file, NULL); + NCHECK(counts, NULL); - read_recv(line, tested_rcv_name, tested_E, tested_SE); - if(strcmp(rcv_name, tested_rcv_name)) continue; + /* both files' pointer are just past the new bloc header */ - FOR_EACH(r, FRONT_INTEGRATED_IRRADIANCE, MAX_RESULTS_COUNT__) { + for (n = 0; n < counts->global; n++) { + double reference_E, reference_SE, test_E, test_SE; + read_global(ref_file, &reference_E, &reference_SE); + read_global(test_file, &test_E, &test_SE); + CHECK(is_compatible_with(reference_E, reference_SE, test_E, test_SE), 1); + } + for (n = 0; n < counts->receiver; n++) { + char ref_rcv_name[MAX_LINE_LEN], test_rcv_name[MAX_LINE_LEN]; + double reference_E[RECEIVER_RESULTS_COUNT__]; + double reference_SE[RECEIVER_RESULTS_COUNT__]; + double test_E[RECEIVER_RESULTS_COUNT__]; + double test_SE[RECEIVER_RESULTS_COUNT__]; + enum receiver_result_type r; + + read_recv(ref_file, ref_rcv_name, reference_E, reference_SE); + read_recv(test_file, test_rcv_name, test_E, test_SE); + CHECK(strcmp(ref_rcv_name, test_rcv_name), 0); + FOR_EACH(r, FIRST_RECEIVER_RESULT, RECEIVER_RESULTS_COUNT__) { CHECK(is_compatible_with - (reference_E[r], reference_SE[r], tested_E[r], tested_SE[r]), 1); + (reference_E[r], reference_SE[r], test_E[r], test_SE[r]), 1); } - found = 1; } - CHECK(found, 1); -} - -static void -check_1_global - (FILE* tested_file, - const double reference_E, - const double reference_SE, - const unsigned rank) -{ - char line[MAX_LINE_LEN]; - double a[2]; - unsigned long recv_count, r2; - unsigned i; - int nb; - double tested_E, tested_SE; - - get_dir_and_counts(tested_file, a, &recv_count, &r2); - - /* Skip receivers */ - while(recv_count--) CHECK(read_line(line, sizeof(line), tested_file), 1); - - /* Read the rank th global data */ - FOR_EACH(i, 0, rank+1) CHECK(read_line(line, sizeof(line), tested_file), 1); - - nb = sscanf(line, "%lg%lg", &tested_E, &tested_SE); - CHECK(nb, 2); - CHECK(is_compatible_with(reference_E, reference_SE, tested_E, tested_SE), 1); -} - -static void -check_references(FILE* ref_file, FILE* tested_file) -{ - char line[MAX_LINE_LEN]; - unsigned nb_global = 0; - fpos_t pos; - - NCHECK(ref_file, NULL); - NCHECK(tested_file, NULL); - - CHECK(fgetpos(ref_file, &pos), 0); - while(read_line(line, sizeof(line), ref_file)) { - double val, std; - int nb = 0; - - if(IS_NEW_BLOCK(line, sundir_header)) { - /* Keep the header as a part of the following block */ - CHECK(fsetpos(ref_file, &pos), 0); - break; + for (n = 0; n < counts->primary; n++) { + char ref_prim_name[MAX_LINE_LEN], test_prim_name[MAX_LINE_LEN]; + double reference_E[PRIMARY_RESULTS_COUNT__]; + double reference_SE[PRIMARY_RESULTS_COUNT__]; + double test_E[PRIMARY_RESULTS_COUNT__]; + double test_SE[PRIMARY_RESULTS_COUNT__]; + double ref_area, ref_cos; + double test_area, test_cos; + enum primary_result_type r; + + read_primary(ref_file, ref_prim_name, &ref_area, &ref_cos, reference_E, reference_SE); + read_primary(test_file, test_prim_name, &test_area, &test_cos, test_E, test_SE); + CHECK(is_compatible_with(ref_area, 0, test_area, 0), 1); + CHECK(is_compatible_with(ref_cos, 0, test_cos, 0), 1); + CHECK(strcmp(ref_prim_name, test_prim_name), 0); + FOR_EACH(r, FIRST_RECEIVER_RESULT, PRIMARY_RESULTS_COUNT__) { + CHECK(is_compatible_with + (reference_E[r], reference_SE[r], test_E[r], test_SE[r]), 1); } - - nb = sscanf(line, "%lg%lg", &val, &std); - CHECK(nb == 0 || nb == 2, 1); - - rewind(tested_file); - if(nb != 0) { - check_1_global(tested_file, val, std, nb_global); - nb_global++; - } else { - char ref_name[MAX_LINE_LEN]; - double reference_E[MAX_RESULTS_COUNT__]; - double reference_SE[MAX_RESULTS_COUNT__]; - read_recv(line, ref_name, reference_E, reference_SE); - check_1_reference(tested_file, ref_name, reference_E, reference_SE); + } + for (n = 0; n < counts->receiver * counts->primary; n++) { + double reference_E[RECEIVER_RESULTS_COUNT__]; + double reference_SE[RECEIVER_RESULTS_COUNT__]; + double test_E[RECEIVER_RESULTS_COUNT__]; + double test_SE[RECEIVER_RESULTS_COUNT__]; + unsigned long ref_rcv_id, ref_prim_id; + unsigned long test_rcv_id, test_prim_id; + + enum receiver_result_type r; + read_recvXprim(ref_file, &ref_rcv_id, &ref_prim_id, reference_E, reference_SE); + read_recvXprim(test_file, &test_rcv_id, &test_prim_id, test_E, test_SE); + /* we rely on the order of outputs */ + CHECK(ref_rcv_id, test_rcv_id); + CHECK(ref_prim_id, test_prim_id); + FOR_EACH(r, FIRST_RECEIVER_RESULT, RECEIVER_RESULTS_COUNT__) { + if (r == FRONT_EFFICIENCY || r == BACK_EFFICIENCY) + continue; /* not read */ + CHECK(is_compatible_with + (reference_E[r], reference_SE[r], test_E[r], test_SE[r]), 1); } - - CHECK(fgetpos(ref_file, &pos), 0); } } @@ -373,7 +463,7 @@ do_check(const char* binary, const char* dir, const char* base_name) { char ref_file_name[128]; FILE* ref_file; - unsigned long c1, realisation_count; + struct counts ref_counts, test_counts; int n; int err; ASSERT(base_name); @@ -386,30 +476,34 @@ do_check(const char* binary, const char* dir, const char* base_name) while(!feof(ref_file)) { char cmd[512]; - char tested_file_name[128]; - double sun_angles[2]; - FILE* fp = NULL; + char test_file_name[128]; + double ref_sun_angles[2], test_sun_angles[2]; + FILE* test_file = NULL; int fd = -1; - get_dir_and_counts(ref_file, sun_angles, &c1, &realisation_count); + if (!get_angles_and_counts(ref_file, ref_sun_angles, &ref_counts)) + break; /* EOF */ - fd = create_tmp_file(tested_file_name, sizeof(tested_file_name)); - fp = fdopen(fd, "r"); - NCHECK(fp, NULL); + fd = create_tmp_file(test_file_name, sizeof(test_file_name)); + test_file = fdopen(fd, "r"); + NCHECK(test_file, NULL); n = snprintf(cmd, sizeof(cmd), "%s -o %s -f -D %g,%g -n %lu -R %s%s_receiver.yaml %s%s.yaml", - binary, tested_file_name, SPLIT2(sun_angles), realisation_count, + binary, test_file_name, SPLIT2(ref_sun_angles), ref_counts.realisation, dir, base_name, dir, base_name); CHECK((unsigned)n < sizeof(cmd), 1); err = system(cmd); CHECK(err, 0); - check_references(ref_file, fp); + get_angles_and_counts(test_file, test_sun_angles, &test_counts); + CHECK(d2_eq(ref_sun_angles, test_sun_angles), 1); + CHECK(counts_ok(&ref_counts, &test_counts), 1); + check_1_reference(ref_file, test_file, &ref_counts); - fclose(fp); - remove(tested_file_name); + fclose(test_file); + remove(test_file_name); } } diff --git a/yaml/beam_down.ref b/yaml/beam_down.ref @@ -1,12 +1,52 @@ #--- Sun direction: 90 90 (-3.7494e-33 -6.12323e-17 -1) -2 10000 -tower.secondary.hyperbol 10 465.484 0.0183212 0 0 0 0 0 0 0 0 0 0 34.5362 0.00509812 0 0 0.930888 3.66392e-05 0 0 -tower.receptor 14 465.484 0.0183212 -1 -1 0 0 -1 -1 0 0 -1 -1 34.5362 0.00509812 -1 -1 0.930888 3.66392e-05 -1 -1 +7 2 5 10000 0 +500.043 0 # Potential +465.484 0.0183212 +0.930883 3.66351e-05 0 0 0 0 +0 0 +0 0 +tower.secondary.hyperbol 10 421.957 FRONT: 0 0 465.484 0.0183212 0 0 0 0 0 0 BACK: 0 0 0 0 0 0 0 0 0 0 +tower.receptor 14 25 FRONT: 465.484 0.0183212 465.484 0.0183212 0 0 0 0 0.930888 3.66392e-05 BACK: -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 +heliostat4.temp-heliostat150.pivot.reflector 6 100.009 1999 0 0 0 0 +heliostat5.temp-heliostat150.pivot.reflector 30 100.009 1986 0 0 0 0 +heliostat3.temp-heliostat150.pivot.reflector 22 100.009 1997 0 0 0 0 +heliostat2.temp-heliostat150.pivot.reflector 26 100.009 1994 0 0 0 0 +heliostat1.temp-heliostat150.pivot.reflector 34 100.009 2024 0 0 0 0 +10 6 FRONT: 0 0 93.126 1.86312 0 0 0 0 BACK: 0 0 0 0 0 0 0 0 +10 30 FRONT: 0 0 92.325 1.85463 0 0 0 0 BACK: 0 0 0 0 0 0 0 0 +10 22 FRONT: 0 0 93.051 1.86278 0 0 0 0 BACK: 0 0 0 0 0 0 0 0 +10 26 FRONT: 0 0 92.8912 1.86133 0 0 0 0 BACK: 0 0 0 0 0 0 0 0 +10 34 FRONT: 0 0 94.0913 1.86784 0 0 0 0 BACK: 0 0 0 0 0 0 0 0 +14 6 FRONT: 93.126 1.86312 93.126 1.86312 0 0 0 0 BACK: -1 -1 -1 -1 -1 -1 -1 -1 +14 30 FRONT: 92.325 1.85463 92.325 1.85463 0 0 0 0 BACK: -1 -1 -1 -1 -1 -1 -1 -1 +14 22 FRONT: 93.051 1.86278 93.051 1.86278 0 0 0 0 BACK: -1 -1 -1 -1 -1 -1 -1 -1 +14 26 FRONT: 92.8912 1.86133 92.8912 1.86133 0 0 0 0 BACK: -1 -1 -1 -1 -1 -1 -1 -1 +14 34 FRONT: 94.0913 1.86784 94.0913 1.86784 0 0 0 0 BACK: -1 -1 -1 -1 -1 -1 -1 -1 #--- Sun direction: 50 50 (-0.413176 -0.492404 -0.766044) -2 10000 -tower.secondary.hyperbol 10 400.227 0.111144 0 0 0 0 0 0 0 0 0 0 99.7686 0.107226 0 0 0.800384 0.000222269 0 0 -tower.receptor 14 136.561 1.90791 -1 -1 0 0 -1 -1 0 0 -1 -1 32.9896 0.464742 -1 -1 0.273098 0.0038155 -1 -1 +7 2 5 10000 0 +500.043 0 +136.561 1.90791 +0.80038 0.000222269 +0 0 +244.012 1.94769 0 0 0 0 +tower.secondary.hyperbol 10 421.957 FRONT: 0 0 400.227 0.111144 0 0 0 0 0 0 BACK: 0 0 0 0 0 0 0 0 0 0 +tower.receptor 14 25 FRONT: 136.561 1.90791 136.561 1.90791 0 0 0 0 0.273098 0.0038155 BACK: -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 +heliostat4.temp-heliostat150.pivot.reflector 6 100.009 2045 0 0 0 0 +heliostat5.temp-heliostat150.pivot.reflector 30 100.009 1956 0 0 0 0 +heliostat3.temp-heliostat150.pivot.reflector 22 100.009 1948 0 0 0 0 +heliostat2.temp-heliostat150.pivot.reflector 26 100.009 2049 0 0 0 0 +heliostat1.temp-heliostat150.pivot.reflector 34 100.009 2002 0 0 0 0 +10 6 FRONT: 0 0 80.2952 1.58372 0 0 0 0 BACK: 0 0 0 0 0 0 0 0 +10 30 FRONT: 0 0 75.2847 1.52678 0 0 0 0 BACK: 0 0 0 0 0 0 0 0 +10 22 FRONT: 0 0 77.9198 1.58423 0 0 0 0 BACK: 0 0 0 0 0 0 0 0 +10 26 FRONT: 0 0 83.5939 1.64675 0 0 0 0 BACK: 0 0 0 0 0 0 0 0 +10 34 FRONT: 0 0 83.1332 1.66167 0 0 0 0 BACK: 0 0 0 0 0 0 0 0 +14 6 FRONT: 22.2344 0.907756 22.2344 0.907756 0 0 0 0 BACK: -1 -1 -1 -1 -1 -1 -1 -1 +14 30 FRONT: 18.29 0.819036 18.29 0.819036 0 0 0 0 BACK: -1 -1 -1 -1 -1 -1 -1 -1 +14 22 FRONT: 24.7238 0.963323 24.7238 0.963323 0 0 0 0 BACK: -1 -1 -1 -1 -1 -1 -1 -1 +14 26 FRONT: 33.4259 1.11916 33.4259 1.11916 0 0 0 0 BACK: -1 -1 -1 -1 -1 -1 -1 -1 +14 34 FRONT: 37.8866 1.19599 37.8866 1.19599 0 0 0 0 BACK: -1 -1 -1 -1 -1 -1 -1 -1 diff --git a/yaml/test01.ref b/yaml/test01.ref @@ -1,5 +1,12 @@ #--- Sun direction: 0 90 (-6.12323e-17 -0 -1) -1 10000 -square_receiver 2 -1 -1 1 0 -1 -1 0 0 -1 -1 0 0 -1 -1 0 0 -1 -1 1 0 +7 1 1 10000 0 +1 0 0 0 +1 0 0 0 +1 0 +0 0 +0 0 +square_receiver 2 100 FRONT: -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 BACK: 0 0 1 0 0 0 0 0 0 0 +reflector 6 1 10000 0 0 0 0 +2 6 FRONT: -1 -1 -1 -1 -1 -1 -1 -1 BACK: 0 0 1 0 0 0 0 0 diff --git a/yaml/test02.ref b/yaml/test02.ref @@ -1,5 +1,12 @@ #--- Sun direction: 0 90 (-6.12323e-17 -0 -1) -1 100000 -square_receiver 2 -1 -1 1 0.0313065 -1 -1 0 0 -1 -1 0 0 -1 -1 0 0 -1 -1 0.01003 0.000315109 +7 1 1 10000 0 +100 0 +0.96 0.0975082 +1 0 0 0 -99 0.0313065 +99.04 0.0975082 +0 0 +0 0 +square_receiver 2 1 FRONT: -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 BACK: 0.96 0.0975082 0.96 0.0975082 0 0 0 0 0.0096 0.000975082 +reflector 6 100 10000 0 0 0 0 +2 6 FRONT: -1 -1 -1 -1 -1 -1 -1 -1 BACK: 0.96 0.0975082 0.96 0.0975082 0 0 0 0 diff --git a/yaml/test02.yaml b/yaml/test02.yaml @@ -7,7 +7,9 @@ - geometry: &small_square - - material: { virtual: } + - material: + front: { virtual: } + back: { matte: { reflectivity: 0 } } plane: clip: - operation: AND diff --git a/yaml/test03.ref b/yaml/test03.ref @@ -1,5 +1,12 @@ #--- Sun direction: 0 45 (-0.707107 -0 -0.707107) -1 10000 -square_receiver 2 -1 -1 0.707107 0 -1 -1 0 0 -1 -1 0 0 -1 -1 0.292893 0 -1 -1 0.707107 0 +7 1 1 10000 0 +1 0 0 0 +0.707107 0 0 0 +0.707107 0 +0 0 +0 0 +square_receiver 2 100 FRONT: -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 BACK: 0 0 0.707107 0 0 0 0 0 0 0 +reflector 6 1 10000 0 0 0 0 +2 6 FRONT: -1 -1 -1 -1 -1 -1 -1 -1 BACK: 0 0 0.707107 0 0 0 0 0 diff --git a/yaml/test04.ref b/yaml/test04.ref @@ -1,4 +1,12 @@ #--- Sun direction: 0 45 (-0.707107 -0 -0.707107) -1 10000 -square_receiver 2 0 0 0.707107 0 0 0 0 0 0 0 0 0 0 0 0.292893 0 0 0 0.707107 0 +7 1 1 10000 0 +1 0 0 0 +0.707107 0 +0 0 +0.707107 0 +0 0 +0 0 +square_receiver 2 100 FRONT: 0 0 0 0 0 0 0 0 0 0 BACK: 0 0 0.707107 0 0 0 0 0 0 0 +reflector 6 1 10000 0 0 0 0 +2 6 FRONT: 0 0 0 0 0 0 0 0 BACK: 0 0 0.707107 0 0 0 0 0 diff --git a/yaml/test05.ref b/yaml/test05.ref @@ -1,5 +1,12 @@ #--- Sun direction: 0 90 (-6.12323e-17 -0 -1) -1 10000 -spherical_receiver 2 -1 -1 1 0 -1 -1 0 0 -1 -1 0 0 -1 -1 0 0 -1 -1 1 0 +7 1 1 10000 0 +1 0 0 0 +1 0 0 0 +1 0 +0 0 +0 0 +spherical_receiver 2 50.2403 FRONT: -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 BACK: 0 0 1 0 0 0 0 0 0 0 +reflector 6 1 10000 0 0 0 0 +2 6 FRONT: -1 -1 -1 -1 -1 -1 -1 -1 BACK: 0 0 1 0 0 0 0 0 diff --git a/yaml/test06.ref b/yaml/test06.ref @@ -0,0 +1,12 @@ +#--- Sun direction: 0 63 (-0.45399 -0 -0.891007) +7 1 1 10000 0 +111.97 0 +0 0 +0.896295 0.000571234 +0 0 +100 0 +0 0 +0 0 +reflector.ground.pivot.small_square 10 1 FRONT: -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 BACK: 0 0 100 0 0 0 0 0 0 0 +reflector.ground.pivot.parabol 6 111.97 10000 0 0 0 0 +10 6 FRONT: -1 -1 -1 -1 -1 -1 -1 -1 BACK: 0 0 100 0 0 0 0 0 diff --git a/yaml/test06.yaml b/yaml/test06.yaml @@ -0,0 +1,62 @@ +- sun: &sun + dni: 1 + spectrum: [{wavelength: 1, data: 1}] + +- material: &lambertian + front: + matte: { reflectivity: 1 } + back: + matte: { reflectivity: 1 } + +- material: &specular + mirror: { reflectivity: 1, roughness: 0 } + + +- template: &self_oriented_parabol + name: "ground" + primary: 0 + geometry: + - material: *lambertian + plane: + clip: + - operation: AND + vertices: + - [-20.0, -20.0] + - [-20.0, 20.0] + - [ 20.0, 20.0] + - [ 20.0, -20.0] + children: + - 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 + vertices: [[-5.0, -5.0], [-5.0, 5.0], [5.0, 5.0], [5.0, -5.0]] + - 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/test06_receiver.yaml b/yaml/test06_receiver.yaml @@ -0,0 +1 @@ +- { name: "reflector.ground.pivot.small_square", side: BACK }