stardis-solver

Solve coupled heat transfers
git clone git://git.meso-star.fr/stardis-solver.git
Log | Files | Refs | README | LICENSE

sdis_estimator.c (8427B)


      1 /* Copyright (C) 2016-2025 |Méso|Star> (contact@meso-star.com)
      2  *
      3  * This program is free software: you can redistribute it and/or modify
      4  * it under the terms of the GNU General Public License as published by
      5  * the Free Software Foundation, either version 3 of the License, or
      6  * (at your option) any later version.
      7  *
      8  * This program is distributed in the hope that it will be useful,
      9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
     11  * GNU General Public License for more details.
     12  *
     13  * You should have received a copy of the GNU General Public License
     14  * along with this program. If not, see <http://www.gnu.org/licenses/>. */
     15 
     16 #include "sdis.h"
     17 #include "sdis_device_c.h"
     18 #include "sdis_estimator_c.h"
     19 #include "sdis_log.h"
     20 
     21 #include <star/ssp.h>
     22 
     23 #include <rsys/cstr.h>
     24 #include <rsys/mutex.h>
     25 
     26 /*******************************************************************************
     27  * Helper functions
     28  ******************************************************************************/
     29 static void
     30 estimator_release(ref_T* ref)
     31 {
     32   struct sdis_estimator* estimator = NULL;
     33   struct sdis_device* dev = NULL;
     34   ASSERT(ref);
     35   estimator = CONTAINER_OF(ref, struct sdis_estimator, ref);
     36   dev = estimator->dev;
     37   darray_heat_path_release(&estimator->paths);
     38   if(estimator->mutex) mutex_destroy(estimator->mutex);
     39   if(estimator->rng) SSP(rng_ref_put(estimator->rng));
     40   MEM_RM(dev->allocator, estimator);
     41   SDIS(device_ref_put(dev));
     42 }
     43 
     44 /*******************************************************************************
     45  * Exported functions
     46  ******************************************************************************/
     47 res_T
     48 sdis_estimator_ref_get(struct sdis_estimator* estimator)
     49 {
     50   if(!estimator) return RES_BAD_ARG;
     51   ref_get(&estimator->ref);
     52   return RES_OK;
     53 }
     54 
     55 res_T
     56 sdis_estimator_ref_put(struct sdis_estimator* estimator)
     57 {
     58   if(!estimator) return RES_BAD_ARG;
     59   ref_put(&estimator->ref, estimator_release);
     60   return RES_OK;
     61 }
     62 
     63 res_T
     64 sdis_estimator_get_type
     65   (const struct sdis_estimator* estimator, enum sdis_estimator_type* type)
     66 {
     67   if(!estimator || !type) return RES_BAD_ARG;
     68   *type = estimator->type;
     69   return RES_OK;
     70 }
     71 
     72 res_T
     73 sdis_estimator_get_realisation_count
     74   (const struct sdis_estimator* estimator, size_t* nrealisations)
     75 {
     76   if(!estimator || !nrealisations) return RES_BAD_ARG;
     77   *nrealisations = estimator->nrealisations;
     78   return RES_OK;
     79 }
     80 
     81 res_T
     82 sdis_estimator_get_failure_count
     83   (const struct sdis_estimator* estimator, size_t* nfailures)
     84 {
     85   if(!estimator || !nfailures) return RES_BAD_ARG;
     86   *nfailures = estimator->nfailures;
     87   return RES_OK;
     88 }
     89 
     90 #define SETUP_MC(Mc, Acc) {                                                    \
     91   (Mc)->E = (Acc)->sum / (double)(Acc)->count;                                 \
     92   (Mc)->V = (Acc)->sum2 / (double)(Acc)->count - (Mc)->E*(Mc)->E;              \
     93   (Mc)->V = MMAX((Mc)->V, 0);                                                  \
     94   (Mc)->SE = sqrt((Mc)->V / (double)(Acc)->count);                             \
     95 } (void)0
     96 
     97 res_T
     98 sdis_estimator_get_temperature
     99   (const struct sdis_estimator* estimator, struct sdis_mc* mc)
    100 {
    101   if(!estimator || !mc 
    102   || (  estimator->type != SDIS_ESTIMATOR_TEMPERATURE
    103      && estimator->type != SDIS_ESTIMATOR_FLUX))
    104     return RES_BAD_ARG;
    105   SETUP_MC(mc, &estimator->temperature);
    106   return RES_OK;
    107 }
    108 
    109 res_T
    110 sdis_estimator_get_realisation_time
    111   (const struct sdis_estimator* estimator, struct sdis_mc* mc)
    112 {
    113   if(!estimator || !mc) return RES_BAD_ARG;
    114   SETUP_MC(mc, &estimator->realisation_time);
    115   return RES_OK;
    116 }
    117 
    118 res_T
    119 sdis_estimator_get_convective_flux
    120   (const struct sdis_estimator* estimator, struct sdis_mc* flux)
    121 {
    122   if(!estimator || !flux || estimator->type != SDIS_ESTIMATOR_FLUX)
    123     return RES_BAD_ARG;
    124   SETUP_MC(flux, &estimator->fluxes[FLUX_CONVECTIVE]);
    125   return RES_OK;
    126 }
    127 
    128 res_T
    129 sdis_estimator_get_radiative_flux
    130   (const struct sdis_estimator* estimator, struct sdis_mc* flux)
    131 {
    132   if(!estimator || !flux || estimator->type != SDIS_ESTIMATOR_FLUX)
    133     return RES_BAD_ARG;
    134   SETUP_MC(flux, &estimator->fluxes[FLUX_RADIATIVE]);
    135   return RES_OK;
    136 }
    137 
    138 res_T
    139 sdis_estimator_get_imposed_flux
    140   (const struct sdis_estimator* estimator, struct sdis_mc* flux)
    141 {
    142   if(!estimator || !flux || estimator->type != SDIS_ESTIMATOR_FLUX)
    143     return RES_BAD_ARG;
    144   SETUP_MC(flux, &estimator->fluxes[FLUX_IMPOSED]);
    145   return RES_OK;
    146 }
    147 
    148 res_T
    149 sdis_estimator_get_total_flux
    150   (const struct sdis_estimator* estimator, struct sdis_mc* flux)
    151 {
    152   if(!estimator || !flux || estimator->type != SDIS_ESTIMATOR_FLUX)
    153     return RES_BAD_ARG;
    154   SETUP_MC(flux, &estimator->fluxes[FLUX_TOTAL]);
    155   return RES_OK;
    156 }
    157 
    158 res_T
    159 sdis_estimator_get_power
    160   (const struct sdis_estimator* estimator, struct sdis_mc* power)
    161 {
    162   if(!estimator || !power || estimator->type != SDIS_ESTIMATOR_POWER)
    163     return RES_BAD_ARG;
    164   SETUP_MC(power, &estimator->power.power);
    165   power->E *= estimator->power.spread;
    166   return RES_OK;
    167 }
    168 
    169 #undef SETUP_MC
    170 
    171 res_T
    172 sdis_estimator_get_paths_count
    173   (const struct sdis_estimator* estimator, size_t* npaths)
    174 {
    175   if(!estimator || !npaths) return RES_BAD_ARG;
    176   *npaths = darray_heat_path_size_get(&estimator->paths);
    177   return RES_OK;
    178 }
    179 
    180 SDIS_API res_T
    181 sdis_estimator_get_path
    182   (const struct sdis_estimator* estimator,
    183    const size_t ipath,
    184    const struct sdis_heat_path** path)
    185 {
    186   if(!estimator || !path
    187   || ipath >= darray_heat_path_size_get(&estimator->paths))
    188     return RES_BAD_ARG;
    189   *path = darray_heat_path_cdata_get(&estimator->paths) + ipath;
    190   return RES_OK;
    191 }
    192 
    193 res_T
    194 sdis_estimator_for_each_path
    195   (const struct sdis_estimator* estimator,
    196    sdis_process_heat_path_T func,
    197    void* context)
    198 {
    199   const struct sdis_heat_path* paths = NULL;
    200   size_t i, n;
    201   res_T res = RES_OK;
    202 
    203   if(!estimator || !func) {
    204     res = RES_BAD_ARG;
    205     goto error;
    206   }
    207 
    208   SDIS(estimator_get_paths_count(estimator, &n));
    209   paths = darray_heat_path_cdata_get(&estimator->paths);
    210   FOR_EACH(i, 0, n) {
    211     res = func(paths+i, context);
    212     if(res != RES_OK) goto error;
    213   }
    214 
    215 exit:
    216   return res;
    217 error:
    218   goto exit;
    219 }
    220 
    221 res_T
    222 sdis_estimator_get_rng_state
    223   (const struct sdis_estimator* estimator,
    224    struct ssp_rng** rng_state)
    225 {
    226   if(!estimator || !rng_state) return RES_BAD_ARG;
    227   *rng_state = estimator->rng;
    228   return RES_OK;
    229 }
    230 
    231 /*******************************************************************************
    232  * Local functions
    233  ******************************************************************************/
    234 res_T
    235 estimator_create
    236   (struct sdis_device* dev,
    237    const enum sdis_estimator_type type,
    238    struct sdis_estimator** out_estimator)
    239 {
    240   struct sdis_estimator* estimator = NULL;
    241   res_T res = RES_OK;
    242 
    243   if(!dev
    244   || (unsigned)type >= SDIS_ESTIMATOR_TYPES_COUNT__
    245   || !out_estimator) {
    246     res = RES_BAD_ARG;
    247     goto error;
    248   }
    249 
    250   estimator = MEM_CALLOC(dev->allocator, 1, sizeof(struct sdis_estimator));
    251   if(!estimator) {
    252     res = RES_MEM_ERR;
    253     goto error;
    254   }
    255   ref_init(&estimator->ref);
    256   SDIS(device_ref_get(dev));
    257   estimator->nrealisations = 0;
    258   estimator->nfailures = 0;
    259   estimator->dev = dev;
    260   estimator->type = type;
    261   darray_heat_path_init(dev->allocator, &estimator->paths);
    262 
    263   estimator->mutex = mutex_create();
    264   if(!estimator->mutex) {
    265     res = RES_MEM_ERR;
    266     goto error;
    267   }
    268 
    269 exit:
    270   if(out_estimator) *out_estimator = estimator;
    271   return res;
    272 error:
    273   if(estimator) {
    274     SDIS(estimator_ref_put(estimator));
    275     estimator = NULL;
    276   }
    277   goto exit;
    278 }
    279 
    280 res_T
    281 estimator_add_and_release_heat_path
    282   (struct sdis_estimator* estimator, struct sdis_heat_path* path)
    283 {
    284   struct sdis_heat_path* dst = NULL;
    285   size_t i;
    286   res_T res = RES_OK;
    287   ASSERT(estimator && path);
    288 
    289   mutex_lock(estimator->mutex);
    290 
    291   i = darray_heat_path_size_get(&estimator->paths);
    292 
    293   res = darray_heat_path_resize(&estimator->paths, i+1);
    294   if(res != RES_OK) goto error;
    295 
    296   dst = darray_heat_path_data_get(&estimator->paths) + i;
    297   res = heat_path_copy_and_release(dst, path);
    298   if(res != RES_OK) goto error;
    299 
    300 exit:
    301   mutex_unlock(estimator->mutex);
    302   return res;
    303 error:
    304   goto exit;
    305 }
    306 
    307 res_T
    308 estimator_save_rng_state
    309   (struct sdis_estimator* estimator,
    310    const struct ssp_rng_proxy* proxy)
    311 {
    312   ASSERT(estimator && proxy);
    313   /* Release the previous RNG state if any */
    314   if(estimator->rng) {
    315     SSP(rng_ref_put(estimator->rng));
    316     estimator->rng = NULL;
    317   }
    318   return create_rng_from_rng_proxy(estimator->dev, proxy, &estimator->rng);
    319 }
    320