solstice

Compute collected power and efficiencies of a solar plant
git clone git://git.meso-star.com/solstice.git
Log | Files | Refs | README | LICENSE

solparser_pivot.c (12975B)


      1 /* Copyright (C) 2018-2026 |Meso|Star> (contact@meso-star.com)
      2  * Copyright (C) 2016-2018 CNRS
      3  *
      4  * This program is free software: you can redistribute it and/or modify
      5  * it under the terms of the GNU General Public License as published by
      6  * the Free Software Foundation, either version 3 of the License, or
      7  * (at your option) any later version.
      8  *
      9  * This program is distributed in the hope that it will be useful,
     10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
     12  * GNU General Public License for more details.
     13  *
     14  * You should have received a copy of the GNU General Public License
     15  * along with this program. If not, see <http://www.gnu.org/licenses/>. */
     16 
     17 #include "solparser_c.h"
     18 
     19 /*******************************************************************************
     20  * Helper functions
     21  ******************************************************************************/
     22 static res_T
     23 parse_anchor_alias
     24   (struct solparser* parser,
     25    const yaml_node_t* alias,
     26    const struct solparser_pivot_id pivot,
     27    struct solparser_anchor_id* out_ianchor)
     28 {
     29   const struct solparser_anchor* anchor = NULL;
     30   intptr_t ianchor = INTPTR_MAX;
     31   res_T res = RES_OK;
     32   ASSERT(parser && alias && out_ianchor);
     33 
     34   if(alias->type != YAML_SCALAR_NODE) {
     35     log_err(parser, alias, "expect an anchor idententifier.\n");
     36     res = RES_BAD_ARG;
     37     goto error;
     38   }
     39 
     40   if(!strncmp((char*)alias->data.scalar.value, "self.", 5)) {
     41     struct target_alias tgt;
     42     tgt.pivot = pivot;
     43     tgt.alias = alias;
     44     res = darray_tgtalias_push_back(&parser->tgtaliases, &tgt);
     45     if(res != RES_OK) {
     46       log_err(parser, alias, "could not register the anchor alias.\n");
     47       goto error;
     48     }
     49   } else {
     50     anchor = solparser_find_anchor(parser, (char*)alias->data.scalar.value);
     51     if(!anchor) {
     52       log_err(parser, alias, "undefined anchor `%s'.\n",
     53         alias->data.scalar.value);
     54       res = RES_BAD_ARG;
     55       goto error;
     56     }
     57 
     58     ianchor = anchor - darray_anchor_cdata_get(&parser->anchors);
     59     ASSERT(ianchor >= 0);
     60     ASSERT((size_t)ianchor < darray_anchor_size_get(&parser->anchors));
     61   }
     62 
     63 exit:
     64   out_ianchor->i = (size_t)ianchor;
     65   return res;
     66 error:
     67   ianchor = INTPTR_MAX;
     68   goto exit;
     69 }
     70 
     71 static res_T
     72 parse_target
     73   (struct solparser* parser,
     74    yaml_document_t* doc,
     75    const yaml_node_t* target_node,
     76    struct solparser_target* target,
     77    struct solparser_pivot_id pivot_id)
     78 {
     79   enum { POLICY };
     80   intptr_t i, n;
     81   int mask = 0; /* Register the parsed attributes */
     82   res_T res = RES_OK;
     83   ASSERT(doc && target_node && target);
     84 
     85   if(target_node->type != YAML_MAPPING_NODE) {
     86     log_err(parser, target_node, "expect a target definition.\n");
     87     res = RES_BAD_ARG;
     88     goto error;
     89   }
     90 
     91   n = target_node->data.mapping.pairs.top - target_node->data.mapping.pairs.start;
     92   FOR_EACH(i, 0, n) {
     93     yaml_node_t* key;
     94     yaml_node_t* val;
     95 
     96     key = yaml_document_get_node(doc, target_node->data.mapping.pairs.start[i].key);
     97     val = yaml_document_get_node(doc, target_node->data.mapping.pairs.start[i].value);
     98     if(key->type != YAML_SCALAR_NODE) {
     99       log_err(parser, key, "expect a target parameter.\n");
    100       res = RES_BAD_ARG;
    101       goto error;
    102     }
    103 
    104     #define SETUP_MASK(Flag, Name) {                                           \
    105       if(mask & BIT(Flag)) {                                                   \
    106         log_err(parser, key, "the target "Name" is already defined.\n");       \
    107         res = RES_BAD_ARG;                                                     \
    108         goto error;                                                            \
    109       }                                                                        \
    110       mask |= BIT(Flag);                                                       \
    111     } (void)0
    112     if(!strcmp((char*)key->data.scalar.value, "anchor")) {
    113       SETUP_MASK(POLICY, "policy");
    114       target->type = SOLPARSER_TARGET_ANCHOR;
    115       res = parse_anchor_alias(parser, val, pivot_id, &target->data.anchor);
    116     } else if(!strcmp((char*)key->data.scalar.value, "direction")) {
    117       SETUP_MASK(POLICY, "policy");
    118       target->type = SOLPARSER_TARGET_DIRECTION;
    119       res = parse_real3
    120         (parser, doc, val, -DBL_MAX, DBL_MAX, target->data.direction);
    121     } else if(!strcmp((char*)key->data.scalar.value, "position")) {
    122       SETUP_MASK(POLICY, "policy");
    123       target->type = SOLPARSER_TARGET_POSITION;
    124       res = parse_real3
    125         (parser, doc, val, -DBL_MAX, DBL_MAX, target->data.position);
    126     } else if(!strcmp((char*)key->data.scalar.value, "sun")) {
    127       /* There is only one sun per YAML file. It is thus sufficient to define
    128        * the target_type to SOLPARSER_TARGET_SUN to indentify which data is
    129        * targeted, i.e. it is not necessary to store the identifier of the sun
    130        * to target */
    131       struct solparser_sun* sun;
    132       SETUP_MASK(POLICY, "policy");
    133       target->type = SOLPARSER_TARGET_SUN;
    134       res = parse_sun(parser, doc, val, &sun);
    135     } else {
    136       log_err(parser, key, "unknown target parameter `%s'.\n",
    137         key->data.scalar.value);
    138       res = RES_BAD_ARG;
    139       goto error;
    140     }
    141     if(res != RES_OK) {
    142       log_node(parser, key);
    143       goto error;
    144     }
    145     #undef SETUP_MASK
    146   }
    147 
    148   if(!(mask & BIT(POLICY))) {
    149     log_err(parser, target_node, "the target policy is missing.\n");
    150     res = RES_BAD_ARG;
    151     goto error;
    152   }
    153 
    154 exit:
    155   return res;
    156 error:
    157   goto exit;
    158 }
    159 
    160 /*******************************************************************************
    161  * Local functions
    162  ******************************************************************************/
    163 res_T
    164 parse_x_pivot
    165   (struct solparser* parser,
    166    yaml_document_t* doc,
    167    const yaml_node_t* x_pivot,
    168    struct solparser_pivot_id* out_isolpivot)
    169 {
    170   enum { REF_POINT, TARGET };
    171   struct solparser_x_pivot* solxpivot = NULL;
    172   size_t isolpivot = SIZE_MAX;
    173   int mask = 0; /* Register the parsed attributes */
    174   intptr_t i, n;
    175   res_T res = RES_OK;
    176   ASSERT(doc && x_pivot && out_isolpivot);
    177 
    178   if(x_pivot->type != YAML_MAPPING_NODE) {
    179     log_err(parser, x_pivot, "expect a x_pivot definition.\n");
    180     res = RES_BAD_ARG;
    181     goto error;
    182   }
    183 
    184   /* Allocate the solstice pivot */
    185   isolpivot = darray_x_pivot_size_get(&parser->x_pivots);
    186   res = darray_x_pivot_resize(&parser->x_pivots, isolpivot + 1);
    187   if(res != RES_OK) {
    188     log_err(parser, x_pivot, "could not allocate the x_pivot.\n");
    189     res = RES_BAD_ARG;
    190     goto error;
    191   }
    192   solxpivot = darray_x_pivot_data_get(&parser->x_pivots) + isolpivot;
    193 
    194   n = x_pivot->data.mapping.pairs.top - x_pivot->data.mapping.pairs.start;
    195   d3_splat(solxpivot->ref_point, 0); /* default value */
    196   FOR_EACH(i, 0, n) {
    197     yaml_node_t* key;
    198     yaml_node_t* val;
    199 
    200     key = yaml_document_get_node(doc, x_pivot->data.mapping.pairs.start[i].key);
    201     val = yaml_document_get_node(doc, x_pivot->data.mapping.pairs.start[i].value);
    202     if(key->type != YAML_SCALAR_NODE) {
    203       log_err(parser, key, "expect x_pivot parameters.\n");
    204       res = RES_BAD_ARG;
    205       goto error;
    206     }
    207     #define SETUP_MASK(Flag, Name) {                                           \
    208       if(mask & BIT(Flag)) {                                                   \
    209         log_err(parser, key,                                                   \
    210           "the x_pivot parameter `"Name"' is already defined.\n");             \
    211         res = RES_BAD_ARG;                                                     \
    212         goto error;                                                            \
    213       }                                                                        \
    214       mask |= BIT(Flag);                                                       \
    215     } (void)0
    216     if(!strcmp((char*)key->data.scalar.value, "ref_point")) {
    217       SETUP_MASK(REF_POINT, "point");
    218       res = parse_real3(parser, doc, val, -DBL_MAX, DBL_MAX, solxpivot->ref_point);
    219     } else if(!strcmp((char*)key->data.scalar.value, "target")) {
    220       struct solparser_pivot_id pivot_id;
    221       pivot_id.i = (size_t) (solxpivot - darray_x_pivot_cdata_get(&parser->x_pivots));
    222       SETUP_MASK(TARGET, "target");
    223       res = parse_target(parser, doc, val, &solxpivot->target, pivot_id);
    224     } else {
    225       log_err(parser, key, "unknown x_pivot parameter `%s'.\n",
    226         key->data.scalar.value);
    227       res = RES_BAD_ARG;
    228       goto error;
    229     }
    230     if(res != RES_OK) {
    231       log_node(parser, key);
    232       goto error;
    233     }
    234     #undef SETUP_MASK
    235   }
    236   #define CHECK_PARAM(Flag, Name)                                              \
    237     if(!(mask & BIT(Flag))) {                                                  \
    238       log_err(parser, x_pivot, "the x_pivot parameter `"Name"' is missing.\n");\
    239       res = RES_BAD_ARG;                                                       \
    240       goto error;                                                              \
    241     } (void)0
    242   CHECK_PARAM(TARGET, "target");
    243   #undef CHECK_PARAM
    244 
    245 exit:
    246   out_isolpivot->i = isolpivot;
    247   return res;
    248 error:
    249   if(solxpivot) {
    250     darray_x_pivot_pop_back(&parser->x_pivots);
    251     isolpivot = SIZE_MAX;
    252   }
    253   goto exit;
    254 }
    255 
    256 res_T
    257 parse_zx_pivot
    258   (struct solparser* parser,
    259    yaml_document_t* doc,
    260    const yaml_node_t* zx_pivot,
    261    struct solparser_pivot_id* out_isolpivot)
    262 {
    263   enum { SPACING, REF_POINT, TARGET };
    264   struct solparser_zx_pivot* solxzpivot = NULL;
    265   size_t isolpivot = SIZE_MAX;
    266   int mask = 0; /* Register the parsed attributes */
    267   intptr_t i, n;
    268   res_T res = RES_OK;
    269   ASSERT(doc && zx_pivot && out_isolpivot);
    270 
    271   if(zx_pivot->type != YAML_MAPPING_NODE) {
    272     log_err(parser, zx_pivot, "expect a zx_pivot definition.\n");
    273     res = RES_BAD_ARG;
    274     goto error;
    275   }
    276 
    277   /* Allocate the solstice pivot */
    278   isolpivot = darray_zx_pivot_size_get(&parser->zx_pivots);
    279   res = darray_zx_pivot_resize(&parser->zx_pivots, isolpivot + 1);
    280   if(res != RES_OK) {
    281     log_err(parser, zx_pivot, "could not allocate the zx_pivot.\n");
    282     res = RES_BAD_ARG;
    283     goto error;
    284   }
    285   solxzpivot = darray_zx_pivot_data_get(&parser->zx_pivots) + isolpivot;
    286 
    287   n = zx_pivot->data.mapping.pairs.top - zx_pivot->data.mapping.pairs.start;
    288   solxzpivot->spacing = 0; /* default value */
    289   d3_splat(solxzpivot->ref_point, 0); /* default value */
    290   FOR_EACH(i, 0, n) {
    291     yaml_node_t* key;
    292     yaml_node_t* val;
    293 
    294     key = yaml_document_get_node(doc, zx_pivot->data.mapping.pairs.start[i].key);
    295     val = yaml_document_get_node(
    296       doc, zx_pivot->data.mapping.pairs.start[i].value);
    297     if(key->type != YAML_SCALAR_NODE) {
    298       log_err(parser, key, "expect zx_pivot parameters.\n");
    299       res = RES_BAD_ARG;
    300       goto error;
    301     }
    302     #define SETUP_MASK(Flag, Name) {                                           \
    303       if(mask & BIT(Flag)) {                                                   \
    304         log_err(parser, key,                                                   \
    305           "the zx_pivot parameter `"Name"' is already defined.\n");            \
    306         res = RES_BAD_ARG;                                                     \
    307         goto error;                                                            \
    308       }                                                                        \
    309       mask |= BIT(Flag);                                                       \
    310     } (void)0
    311     if(!strcmp((char*) key->data.scalar.value, "spacing")) {
    312       SETUP_MASK(SPACING, "spacing");
    313       res = parse_real(parser, val, 0, DBL_MAX, &solxzpivot->spacing);
    314     } else if(!strcmp((char*) key->data.scalar.value, "ref_point")) {
    315       SETUP_MASK(REF_POINT, "ref_point");
    316       res = parse_real3(
    317         parser, doc, val, -DBL_MAX, DBL_MAX, solxzpivot->ref_point);
    318     } else if(!strcmp((char*) key->data.scalar.value, "target")) {
    319       struct solparser_pivot_id pivot_id;
    320       pivot_id.i =
    321         (size_t) (solxzpivot - darray_zx_pivot_cdata_get(&parser->zx_pivots));
    322       SETUP_MASK(TARGET, "target");
    323       res = parse_target(parser, doc, val, &solxzpivot->target, pivot_id);
    324     } else {
    325       log_err(parser, key, "unknown zx_pivot parameter `%s'.\n",
    326         key->data.scalar.value);
    327       res = RES_BAD_ARG;
    328       goto error;
    329     }
    330     if(res != RES_OK) {
    331       log_node(parser, key);
    332       goto error;
    333     }
    334     #undef SETUP_MASK
    335   }
    336   #define CHECK_PARAM(Flag, Name)                                              \
    337     if(!(mask & BIT(Flag))) {                                                  \
    338       log_err(parser, zx_pivot,                                                \
    339          "the zx_pivot parameter `"Name"' is missing.\n");                     \
    340       res = RES_BAD_ARG;                                                       \
    341       goto error;                                                              \
    342     } (void)0
    343   CHECK_PARAM(TARGET, "target");
    344   #undef CHECK_PARAM
    345 
    346 exit:
    347   out_isolpivot->i = isolpivot;
    348   return res;
    349 error:
    350   if(solxzpivot) {
    351     darray_zx_pivot_pop_back(&parser->zx_pivots);
    352     isolpivot = SIZE_MAX;
    353   }
    354   goto exit;
    355 }
    356 
    357