solstice

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

solstice_sun.c (7629B)


      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 "solstice_c.h"
     18 #include "solstice_sun_spectrum.h"
     19 #include "parser/solparser.h"
     20 #include "parser/solparser_sun.h"
     21 
     22 #include <solstice/ssol.h>
     23 
     24 /*******************************************************************************
     25  * Helper functions
     26  ******************************************************************************/
     27 static res_T
     28 create_sun_buie
     29   (struct solstice* solstice,
     30    const struct solparser_sun* solparser_sun,
     31    struct ssol_sun** out_sun)
     32 {
     33   struct ssol_sun* sun = NULL;
     34   res_T res = RES_OK;
     35   ASSERT(solstice && solparser_sun && out_sun);
     36   ASSERT(solparser_sun->radang_distrib_type == SOLPARSER_SUN_RADANG_DISTRIB_BUIE);
     37 
     38   res = ssol_sun_create_buie(solstice->ssol, &sun);
     39   if(res != RES_OK) {
     40     fprintf(stderr, "Could not create the solver buie sun.\n");
     41     goto error;
     42   }
     43 
     44   res = ssol_sun_set_buie_param(sun, solparser_sun->radang_distrib.buie.csr);
     45   if(res != RES_OK) {
     46     fprintf(stderr, "Could setup the buie parameter of the solver sun.\n");
     47     goto error;
     48   }
     49 
     50 exit:
     51   *out_sun = sun;
     52   return res;
     53 error:
     54   if(sun) {
     55     SSOL(sun_ref_put(sun));
     56     sun = NULL;
     57   }
     58   goto exit;
     59 }
     60 
     61 static res_T
     62 create_sun_dir
     63   (struct solstice* solstice,
     64    const struct solparser_sun* solparser_sun,
     65    struct ssol_sun** out_sun)
     66 {
     67   struct ssol_sun* sun = NULL;
     68   res_T res = RES_OK;
     69   (void)solparser_sun;
     70   ASSERT(solstice && solparser_sun && out_sun);
     71   ASSERT(solparser_sun->radang_distrib_type
     72       == SOLPARSER_SUN_RADANG_DISTRIB_DIRECTIONAL);
     73 
     74   res = ssol_sun_create_directional(solstice->ssol, &sun);
     75   if(res != RES_OK) {
     76     fprintf(stderr, "Could not create the solver directional sun.\n");
     77     goto error;
     78   }
     79 
     80 exit:
     81   *out_sun = sun;
     82   return res;
     83 error:
     84   if(sun) {
     85     SSOL(sun_ref_put(sun));
     86     sun = NULL;
     87   }
     88   goto exit;
     89 }
     90 
     91 static res_T
     92 create_sun_pillbox
     93   (struct solstice* solstice,
     94    const struct solparser_sun* solparser_sun,
     95    struct ssol_sun** out_sun)
     96 {
     97   struct ssol_sun* sun = NULL;
     98   res_T res = RES_OK;
     99   ASSERT(solstice && solparser_sun && out_sun);
    100   ASSERT(solparser_sun->radang_distrib_type
    101       == SOLPARSER_SUN_RADANG_DISTRIB_PILLBOX);
    102 
    103   res = ssol_sun_create_pillbox(solstice->ssol, &sun);
    104   if(res != RES_OK) {
    105     fprintf(stderr, "Could not create the solver pillbox sun.\n");
    106     goto error;
    107   }
    108 
    109   res = ssol_sun_pillbox_set_half_angle
    110     (sun, MDEG2RAD(solparser_sun->radang_distrib.pillbox.half_angle));
    111   if(res != RES_OK) {
    112     fprintf(stderr, "Could not setup half_angle for the solver pillbox sun.\n");
    113     goto error;
    114   }
    115 
    116 exit:
    117   *out_sun = sun;
    118   return res;
    119 error:
    120   if(sun) {
    121     SSOL(sun_ref_put(sun));
    122     sun = NULL;
    123   }
    124   goto exit;
    125 }
    126 
    127 static res_T
    128 create_sun_gaussian
    129   (struct solstice* solstice,
    130    const struct solparser_sun* solparser_sun,
    131    struct ssol_sun** out_sun)
    132 {
    133   struct ssol_sun* sun = NULL;
    134   res_T res = RES_OK;
    135   ASSERT(solstice && solparser_sun && out_sun);
    136   ASSERT(solparser_sun->radang_distrib_type
    137     == SOLPARSER_SUN_RADANG_DISTRIB_GAUSSIAN);
    138 
    139   res = ssol_sun_create_gaussian(solstice->ssol, &sun);
    140   if(res != RES_OK) {
    141     fprintf(stderr, "Could not create the solver gaussian sun.\n");
    142     goto error;
    143   }
    144 
    145   res = ssol_sun_gaussian_set_std_dev
    146     (sun, MDEG2RAD(solparser_sun->radang_distrib.gaussian.std_dev));
    147   if(res != RES_OK) {
    148     fprintf(stderr, "Could not setup standard deviation for the solver gaussian sun.\n");
    149     goto error;
    150   }
    151 
    152 exit:
    153   *out_sun = sun;
    154   return res;
    155 error:
    156   if(sun) {
    157     SSOL(sun_ref_put(sun));
    158     sun = NULL;
    159   }
    160   goto exit;
    161 }
    162 
    163 static void
    164 get_wavelength(const size_t i, double* wlen, double* data, void* ctx)
    165 {
    166   const double* spectrum = ctx;
    167   ASSERT(wlen && data && ctx);
    168   *wlen = spectrum[i*2+0];
    169   *data = spectrum[i*2+1];
    170 }
    171 
    172 static res_T
    173 create_default_sun_spectrum
    174   (struct solstice* solstice,
    175    const struct solparser_sun* solparser_sun,
    176    struct ssol_spectrum** out_spectrum)
    177 {
    178   struct ssol_spectrum* spectrum = NULL;
    179   const double* data;
    180   size_t size;
    181   res_T res = RES_OK;
    182 
    183   /* The solparser_sun may be used if the default spectrum is defined wrt the
    184    * sun type */
    185   (void)solparser_sun;
    186 
    187   res = ssol_spectrum_create(solstice->ssol, &spectrum);
    188   if(res != RES_OK) {
    189     fprintf(stderr, "Could not create the spectrum of the solver sun.\n");
    190     goto error;
    191   }
    192 
    193   if(solparser_has_spectrum(solstice->parser)) {
    194     data = solstice_sun_spectrum_smarts;
    195     size = solstice_sun_spectrum_smarts_size;
    196   } else {
    197     data = solstice_sun_spectrum_dummy;
    198     size = solstice_sun_spectrum_dummy_size;
    199   }
    200 
    201   res = ssol_spectrum_setup(spectrum, get_wavelength, size, (void*)data);
    202   if(res != RES_OK) {
    203     fprintf(stderr, "Coul not setup the default spectrum of the solver sun.\n");
    204     goto error;
    205   }
    206 
    207 exit:
    208   *out_spectrum = spectrum;
    209   return res;
    210 error:
    211   if(spectrum) {
    212     SSOL(spectrum_ref_put(spectrum));
    213     spectrum = NULL;
    214   }
    215   goto exit;
    216 }
    217 
    218 /*******************************************************************************
    219  * Local function
    220  ******************************************************************************/
    221 res_T
    222 solstice_create_sun(struct solstice* solstice)
    223 {
    224   struct ssol_sun* sun = NULL;
    225   struct ssol_spectrum* spectrum = NULL;
    226   const struct solparser_sun* solparser_sun = NULL;
    227   res_T res = RES_OK;
    228   ASSERT(solstice);
    229 
    230   solparser_sun = solparser_get_sun(solstice->parser);
    231   switch(solparser_sun->radang_distrib_type) {
    232     case SOLPARSER_SUN_RADANG_DISTRIB_BUIE:
    233       res = create_sun_buie(solstice, solparser_sun, &sun);
    234       break;
    235     case SOLPARSER_SUN_RADANG_DISTRIB_DIRECTIONAL:
    236       res = create_sun_dir(solstice, solparser_sun, &sun);
    237       break;
    238     case SOLPARSER_SUN_RADANG_DISTRIB_PILLBOX:
    239       res = create_sun_pillbox(solstice, solparser_sun, &sun);
    240       break;
    241     case SOLPARSER_SUN_RADANG_DISTRIB_GAUSSIAN:
    242       res = create_sun_gaussian(solstice, solparser_sun, &sun);
    243       break;
    244     default: FATAL("Unreachable code.\n"); break;
    245   }
    246   if(res != RES_OK) goto error;
    247 
    248   if(!SOLPARSER_ID_IS_VALID(solparser_sun->spectrum)) {
    249     res = create_default_sun_spectrum(solstice, solparser_sun, &spectrum);
    250     if(res != RES_OK) goto error;
    251   } else {
    252     res = solstice_create_ssol_spectrum
    253       (solstice, solparser_sun->spectrum, &spectrum);
    254     if(res != RES_OK) goto error;
    255   }
    256 
    257   res = ssol_sun_set_spectrum(sun, spectrum);
    258   if(res != RES_OK) {
    259     fprintf(stderr, "Could not attach the spectrum to the sun.\n");
    260     goto error;
    261   }
    262 
    263   res = ssol_sun_set_dni(sun, solparser_sun->dni);
    264   if(res != RES_OK) {
    265     fprintf(stderr, "Could not setup the DNI of the sun.\n");
    266     goto error;
    267   }
    268 
    269   res = ssol_scene_attach_sun(solstice->scene, sun);
    270   if(res != RES_OK) {
    271     fprintf(stderr, "Could not attach the sun to the scene.\n");
    272     goto error;
    273   }
    274 
    275 exit:
    276   if(spectrum) SSOL(spectrum_ref_put(spectrum));
    277   solstice->sun = sun;
    278   return res;
    279 error:
    280   if(sun) {
    281     SSOL(sun_ref_put(sun));
    282     sun = NULL;
    283   }
    284 
    285   goto exit;
    286 }
    287