solstice-solver

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

ssol_ranst_sun_wl.c (5129B)


      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_ranst_sun_wl.h"
     19 
     20 #include <star/ssp.h>
     21 
     22 #include <rsys/double33.h>
     23 #include <rsys/math.h>
     24 #include <rsys/mem_allocator.h>
     25 #include <rsys/rsys.h>
     26 #include <rsys/ref_count.h>
     27 
     28 /*******************************************************************************
     29  * Distributions types for wavelengths
     30  ******************************************************************************/
     31 struct ran_piecewise_wl_state {
     32   struct ssp_ranst_piecewise_linear* spectrum;
     33 };
     34 
     35 struct ran_dirac_wl_state {
     36   double wavelength;
     37 };
     38 
     39 enum wl_ran_type {
     40   WL_DIRAC,
     41   WL_PIECEWISE,
     42   WL_TYPES_COUNT__
     43 };
     44 
     45 /* One single type for all distributions. Only the state type depends on the
     46  * distribution type */
     47 struct ranst_sun_wl {
     48   double(*get)
     49     (const struct ranst_sun_wl* ran, struct ssp_rng* rng);
     50   union {
     51     struct ran_piecewise_wl_state piecewise;
     52     struct ran_dirac_wl_state dirac;
     53   } state;
     54   enum wl_ran_type type;
     55 
     56   ref_T ref;
     57   struct mem_allocator* allocator;
     58 };
     59 
     60 /*******************************************************************************
     61  * Helper functions
     62  ******************************************************************************/
     63 static void
     64 distrib_sun_wl_release(ref_T* ref)
     65 {
     66   struct ranst_sun_wl* ran;
     67   ASSERT(ref);
     68   ran = CONTAINER_OF(ref, struct ranst_sun_wl, ref);
     69   switch (ran->type) {
     70     case WL_DIRAC:
     71       break;
     72     case WL_PIECEWISE:
     73       SSP(ranst_piecewise_linear_ref_put(ran->state.piecewise.spectrum));
     74       ran->state.piecewise.spectrum = NULL;
     75       break;
     76     default: FATAL("Unreachable code\n"); break;
     77   }
     78   MEM_RM(ran->allocator, ran);
     79 }
     80 
     81 /*******************************************************************************
     82  * Piecewise random variate
     83  ******************************************************************************/
     84 static double
     85 ran_piecewise_get
     86   (const struct ranst_sun_wl* ran,
     87    struct ssp_rng* rng)
     88 {
     89   ASSERT(ran && rng && ran->type == WL_PIECEWISE);
     90   ASSERT(ran->state.piecewise.spectrum);
     91   return ssp_ranst_piecewise_linear_get(ran->state.piecewise.spectrum, rng);
     92 }
     93 
     94 /*******************************************************************************
     95  * Dirac distribution
     96  ******************************************************************************/
     97 static double
     98 ran_dirac_get
     99   (const struct ranst_sun_wl* ran,
    100    struct ssp_rng* rng)
    101 {
    102   (void) rng;
    103   ASSERT(ran && rng && ran->type == WL_DIRAC);
    104   return ran->state.dirac.wavelength;
    105 }
    106 
    107 /*******************************************************************************
    108  * Local functions
    109  ******************************************************************************/
    110 res_T
    111 ranst_sun_wl_create
    112   (struct mem_allocator* allocator,
    113    struct ranst_sun_wl** out_ran)
    114 {
    115   struct ranst_sun_wl* ran = NULL;
    116 
    117   if (!out_ran) return RES_BAD_ARG;
    118 
    119   allocator = allocator ? allocator : &mem_default_allocator;
    120 
    121   ran = MEM_CALLOC(allocator, 1, sizeof(struct ranst_sun_wl));
    122   if (!ran) return RES_MEM_ERR;
    123 
    124   ref_init(&ran->ref);
    125   ran->allocator = allocator;
    126   *out_ran = ran;
    127 
    128   return RES_OK;
    129 }
    130 
    131 res_T
    132 ranst_sun_wl_ref_get(struct ranst_sun_wl* ran)
    133 {
    134   if (!ran) return RES_BAD_ARG;
    135   ref_get(&ran->ref);
    136   return RES_OK;
    137 }
    138 
    139 res_T
    140 ranst_sun_wl_ref_put(struct ranst_sun_wl* ran)
    141 {
    142   if (!ran) return RES_BAD_ARG;
    143   ref_put(&ran->ref, distrib_sun_wl_release);
    144   return RES_OK;
    145 }
    146 
    147 double
    148 ranst_sun_wl_get(const struct ranst_sun_wl* ran, struct ssp_rng* rng)
    149 {
    150   ASSERT(ran);
    151   return ran->get(ran, rng);
    152 }
    153 
    154 res_T
    155 ranst_sun_wl_setup
    156   (struct ranst_sun_wl* ran,
    157    const double* wavelengths,
    158    const double* intensities,
    159    const size_t sz)
    160 {
    161   res_T res = RES_OK;
    162   if(!ran || !wavelengths || !intensities || !sz)
    163     return RES_BAD_ARG;
    164 
    165   if(sz <= 1) {
    166     ran->type = WL_DIRAC;
    167     ran->get = &ran_dirac_get;
    168     ran->state.dirac.wavelength = sz ? wavelengths[0] : -1;
    169   } else {
    170     ran->type = WL_PIECEWISE;
    171     ran->get = &ran_piecewise_get;
    172     res = ssp_ranst_piecewise_linear_create
    173       (ran->allocator, &ran->state.piecewise.spectrum);
    174     if(res != RES_OK) goto error;
    175     res = ssp_ranst_piecewise_linear_setup
    176       (ran->state.piecewise.spectrum, wavelengths, intensities, sz);
    177     if(res != RES_OK) goto error;
    178   }
    179 
    180 exit:
    181   return res;
    182 error:
    183   if(ran->state.piecewise.spectrum) {
    184     SSP(ranst_piecewise_linear_ref_put(ran->state.piecewise.spectrum));
    185     ran->state.piecewise.spectrum = NULL;
    186   }
    187   goto exit;
    188 }
    189