solstice-solver

Solver library of the solstice app
git clone git://git.meso-star.com/solstice-solver.git
Log | Files | Refs | README | LICENSE

ssol_sun.c (6845B)


      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 "ssol.h"
     18 #include "ssol_device_c.h"
     19 #include "ssol_sun_c.h"
     20 #include "ssol_ranst_sun_dir.h"
     21 #include "ssol_ranst_sun_wl.h"
     22 #include "ssol_spectrum_c.h"
     23 
     24 #include <rsys/rsys.h>
     25 #include <rsys/mem_allocator.h>
     26 #include <rsys/ref_count.h>
     27 #include <rsys/math.h>
     28 #include <rsys/double3.h>
     29 
     30 #include <string.h>
     31 
     32 /*******************************************************************************
     33  * Helper functions
     34  ******************************************************************************/
     35 static void
     36 sun_release(ref_T* ref)
     37 {
     38   struct ssol_device* dev;
     39   struct ssol_sun* sun = CONTAINER_OF(ref, struct ssol_sun, ref);
     40   ASSERT(ref);
     41   dev = sun->dev;
     42   ASSERT(dev && dev->allocator);
     43   if(sun->spectrum) SSOL(spectrum_ref_put(sun->spectrum));
     44   MEM_RM(dev->allocator, sun);
     45   SSOL(device_ref_put(dev));
     46 }
     47 
     48 static res_T
     49 sun_create
     50   (struct ssol_device* dev, struct ssol_sun** out_sun, enum sun_type type)
     51 {
     52   struct ssol_sun* sun = NULL;
     53   res_T res = RES_OK;
     54   if(!dev || !out_sun || type >= SUN_TYPES_COUNT__) {
     55     return RES_BAD_ARG;
     56   }
     57 
     58   sun = (struct ssol_sun*)MEM_CALLOC
     59     (dev->allocator, 1, sizeof(struct ssol_sun));
     60   if(!sun) {
     61     res = RES_MEM_ERR;
     62     goto error;
     63   }
     64 
     65   SSOL(device_ref_get(dev));
     66   sun->dev = dev;
     67   sun->type = type;
     68   ref_init(&sun->ref);
     69 
     70 exit:
     71   if(out_sun) *out_sun = sun;
     72   return res;
     73 error:
     74   if(sun) {
     75     SSOL(sun_ref_put(sun));
     76     sun = NULL;
     77   }
     78   goto exit;
     79 }
     80 
     81 /*******************************************************************************
     82  * Exported ssol_image functions
     83  ******************************************************************************/
     84 res_T
     85 ssol_sun_create_directional(struct ssol_device* dev, struct ssol_sun** out_sun)
     86 {
     87   return sun_create(dev, out_sun, SUN_DIRECTIONAL);
     88 }
     89 
     90 res_T
     91 ssol_sun_create_pillbox(struct ssol_device* dev, struct ssol_sun** out_sun)
     92 {
     93   return sun_create(dev, out_sun, SUN_PILLBOX);
     94 }
     95 
     96 res_T
     97 ssol_sun_create_gaussian(struct ssol_device* dev, struct ssol_sun** out_sun)
     98 {
     99   return sun_create(dev, out_sun, SUN_GAUSSIAN);
    100 }
    101 
    102 res_T
    103 ssol_sun_create_buie
    104   (struct ssol_device* dev, struct ssol_sun** out_sun)
    105 {
    106   return sun_create(dev, out_sun, SUN_BUIE);
    107 }
    108 
    109 res_T
    110 ssol_sun_ref_get(struct ssol_sun* sun)
    111 {
    112   if(!sun)
    113     return RES_BAD_ARG;
    114   ref_get(&sun->ref);
    115   return RES_OK;
    116 }
    117 
    118 res_T
    119 ssol_sun_ref_put(struct ssol_sun* sun)
    120 {
    121   if(!sun)
    122     return RES_BAD_ARG;
    123   ref_put(&sun->ref, sun_release);
    124   return RES_OK;
    125 }
    126 
    127 res_T
    128 ssol_sun_set_direction(struct ssol_sun* sun, const double direction[3])
    129 {
    130   if(!sun || !direction)
    131     return RES_BAD_ARG;
    132   if(0 == d3_normalize(sun->direction, direction))
    133     /* zero vector */
    134     return RES_BAD_ARG;
    135   return RES_OK;
    136 }
    137 
    138 res_T
    139 ssol_sun_get_direction(const struct ssol_sun* sun, double direction[3])
    140 {
    141   if(!sun || !direction)
    142     return RES_BAD_ARG;
    143   d3_set(direction, sun->direction);
    144   return RES_OK;
    145 }
    146 
    147 res_T
    148 ssol_sun_set_dni(struct ssol_sun* sun, const double dni)
    149 {
    150   if(!sun || dni <= 0)
    151     return RES_BAD_ARG;
    152   sun->dni = dni;
    153   return RES_OK;
    154 }
    155 
    156 res_T
    157 ssol_sun_get_dni(const struct ssol_sun* sun, double* dni)
    158 {
    159   if(!sun || !dni)
    160     return RES_BAD_ARG;
    161   *dni = sun->dni;
    162   return RES_OK;
    163 }
    164 
    165 res_T
    166 ssol_sun_set_spectrum(struct ssol_sun* sun, struct ssol_spectrum* spectrum)
    167 {
    168   if(!sun || !spectrum)
    169     return RES_BAD_ARG;
    170   if(spectrum == sun->spectrum) /* no change */
    171     return RES_OK;
    172   if(sun->spectrum)
    173     SSOL(spectrum_ref_put(sun->spectrum));
    174   SSOL(spectrum_ref_get(spectrum));
    175   sun->spectrum = spectrum;
    176   return RES_OK;
    177 }
    178 
    179 res_T
    180 ssol_sun_pillbox_set_half_angle(struct ssol_sun* sun, const double half_angle)
    181 {
    182   if(!sun || half_angle <= 0 || half_angle > PI * 0.5 || sun->type != SUN_PILLBOX)
    183     return RES_BAD_ARG;
    184   sun->data.pillbox.half_angle = half_angle;
    185   return RES_OK;
    186 }
    187 
    188 res_T
    189 ssol_sun_gaussian_set_std_dev(struct ssol_sun* sun, const double std_dev)
    190 {
    191   if(!sun || std_dev <= 0 || sun->type != SUN_GAUSSIAN)
    192     return RES_BAD_ARG;
    193   sun->data.gaussian.std_dev = std_dev;
    194   return RES_OK;
    195 }
    196 
    197 res_T
    198 ssol_sun_set_buie_param
    199   (struct ssol_sun* sun,
    200    const double ratio)
    201 {
    202   if(!sun
    203   || ratio <= 0
    204   || ratio >= 1
    205   || sun->type != SUN_BUIE)
    206     return RES_BAD_ARG;
    207   sun->data.csr.ratio = ratio;
    208   return RES_OK;
    209 }
    210 
    211 /*******************************************************************************
    212  * Local function
    213  ******************************************************************************/
    214 res_T
    215 sun_create_direction_distribution
    216   (struct ssol_sun* sun, struct ranst_sun_dir** out_ran_dir)
    217 {
    218   struct ranst_sun_dir* ran_dir = NULL;
    219   res_T res = RES_OK;
    220   ASSERT(sun && out_ran_dir);
    221 
    222   res = ranst_sun_dir_create(sun->dev->allocator, &ran_dir);
    223   if(res != RES_OK) goto error;
    224   switch(sun->type) {
    225     case SUN_DIRECTIONAL:
    226       res = ranst_sun_dir_dirac_setup(ran_dir, sun->direction);
    227       break;
    228     case SUN_PILLBOX:
    229       res = ranst_sun_dir_pillbox_setup
    230         (ran_dir, sun->data.pillbox.half_angle, sun->direction);
    231       break;
    232     case SUN_GAUSSIAN:
    233       res = ranst_sun_dir_gaussian_setup
    234         (ran_dir, sun->data.gaussian.std_dev, sun->direction);
    235       break;
    236     case SUN_BUIE:
    237       res = ranst_sun_dir_buie_setup
    238         (ran_dir, sun->data.csr.ratio, sun->direction);
    239       break;
    240     default: FATAL("Unreachable code\n"); break;
    241   }
    242 exit:
    243   *out_ran_dir = ran_dir;
    244   return res;
    245 error:
    246   if(ran_dir) {
    247     CHK(ranst_sun_dir_ref_put(ran_dir) == RES_OK);
    248     ran_dir = NULL;
    249   }
    250   goto exit;
    251 }
    252 
    253 res_T
    254 sun_create_wavelength_distribution
    255   (struct ssol_sun* sun, struct ranst_sun_wl** out_ran_wl)
    256 {
    257   struct ranst_sun_wl* ran_wl = NULL;
    258   res_T res = RES_OK;
    259   ASSERT(sun && out_ran_wl);
    260 
    261   res = ranst_sun_wl_create(sun->dev->allocator, &ran_wl);
    262   if(res != RES_OK) goto error;
    263 
    264   res = ranst_sun_wl_setup(ran_wl,
    265     darray_double_cdata_get(&sun->spectrum->wavelengths),
    266     darray_double_cdata_get(&sun->spectrum->intensities),
    267     darray_double_size_get(&sun->spectrum->wavelengths));
    268   if(res != RES_OK) goto error;
    269 
    270 exit:
    271   *out_ran_wl = ran_wl;
    272   return res;
    273 error:
    274   if(ran_wl) {
    275     CHK(ranst_sun_wl_ref_put(ran_wl) == RES_OK);
    276     ran_wl = NULL;
    277   }
    278   goto exit;
    279 }