stardis-solver

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

sdis_estimator_buffer.c (7444B)


      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_estimator_buffer_c.h"
     20 #include "sdis_log.h"
     21 
     22 #include <star/ssp.h>
     23 
     24 struct sdis_estimator_buffer {
     25   struct sdis_estimator** estimators; /* Row major per pixel estimators */
     26   size_t width;
     27   size_t height;
     28 
     29   struct accum temperature;
     30   struct accum realisation_time;
     31   size_t nrealisations; /* #successes */
     32   size_t nfailures;
     33 
     34   /* State of the RNG after the simulation */
     35   struct ssp_rng* rng;
     36 
     37   ref_T ref;
     38   struct sdis_device* dev;
     39 };
     40 
     41 /*******************************************************************************
     42  * Helper functions
     43  ******************************************************************************/
     44 static void
     45 estimator_buffer_release(ref_T* ref)
     46 {
     47   struct sdis_estimator_buffer* buf;
     48   struct sdis_device* dev;
     49   size_t i;
     50   ASSERT(ref);
     51 
     52   buf = CONTAINER_OF(ref, struct sdis_estimator_buffer, ref);
     53   dev = buf->dev;
     54 
     55   if(buf->estimators) {
     56     FOR_EACH(i, 0, buf->width*buf->height) {
     57       if(buf->estimators[i]) SDIS(estimator_ref_put(buf->estimators[i]));
     58     }
     59     MEM_RM(dev->allocator, buf->estimators);
     60   }
     61 
     62   if(buf->rng) SSP(rng_ref_put(buf->rng));
     63   MEM_RM(dev->allocator, buf);
     64   SDIS(device_ref_put(dev));
     65 }
     66 
     67 /*******************************************************************************
     68  * Exported functions
     69  ******************************************************************************/
     70 res_T
     71 sdis_estimator_buffer_ref_get(struct sdis_estimator_buffer* buf)
     72 {
     73   if(!buf) return RES_BAD_ARG;
     74   ref_get(&buf->ref);
     75   return RES_OK;
     76 }
     77 
     78 res_T
     79 sdis_estimator_buffer_ref_put(struct sdis_estimator_buffer* buf)
     80 {
     81   if(!buf) return RES_BAD_ARG;
     82   ref_put(&buf->ref, estimator_buffer_release);
     83   return RES_OK;
     84 }
     85 
     86 res_T
     87 sdis_estimator_buffer_get_definition
     88   (const struct sdis_estimator_buffer* buf, size_t definition[2])
     89 {
     90   if(!buf || !definition) return RES_BAD_ARG;
     91   definition[0] = buf->width;
     92   definition[1] = buf->height;
     93   return RES_OK;
     94 }
     95 
     96 res_T
     97 sdis_estimator_buffer_at
     98   (const struct sdis_estimator_buffer* buf,
     99    const size_t x,
    100    const size_t y,
    101    const struct sdis_estimator** estimator)
    102 {
    103   if(!buf || x >= buf->width || y >= buf->height || !estimator)
    104     return RES_BAD_ARG;
    105   *estimator = estimator_buffer_grab(buf, x, y);
    106   return RES_OK;
    107 }
    108 
    109 res_T
    110 sdis_estimator_buffer_get_realisation_count
    111   (const struct sdis_estimator_buffer* buf, size_t* nrealisations)
    112 {
    113   if(!buf || !nrealisations) return RES_BAD_ARG;
    114   *nrealisations = buf->nrealisations;
    115   return RES_OK;
    116 }
    117 
    118 res_T
    119 sdis_estimator_buffer_get_failure_count
    120   (const struct sdis_estimator_buffer* buf, size_t* nfailures)
    121 {
    122   if(!buf || !nfailures) return RES_BAD_ARG;
    123   *nfailures = buf->nfailures;
    124   return RES_OK;
    125 }
    126 
    127 #define SETUP_MC(Mc, Acc) {                                                    \
    128   (Mc)->E = (Acc)->sum / (double)(Acc)->count;                                 \
    129   (Mc)->V = (Acc)->sum2 / (double)(Acc)->count - (Mc)->E*(Mc)->E;              \
    130   (Mc)->V = MMAX((Mc)->V, 0);                                                  \
    131   (Mc)->SE = sqrt((Mc)->V / (double)(Acc)->count);                             \
    132 } (void)0
    133 
    134 res_T
    135 sdis_estimator_buffer_get_temperature
    136   (const struct sdis_estimator_buffer* buf, struct sdis_mc* mc)
    137 {
    138   if(!buf || !mc) return RES_BAD_ARG;
    139   SETUP_MC(mc, &buf->temperature);
    140   return RES_OK;
    141 }
    142 
    143 res_T
    144 sdis_estimator_buffer_get_realisation_time
    145   (const struct sdis_estimator_buffer* buf, struct sdis_mc* mc)
    146 {
    147   if(!buf || !mc) return RES_BAD_ARG;
    148   SETUP_MC(mc, &buf->realisation_time);
    149   return RES_OK;
    150 }
    151 
    152 res_T
    153 sdis_estimator_buffer_get_rng_state
    154   (const struct sdis_estimator_buffer* buf, struct ssp_rng** rng_state)
    155 {
    156   if(!buf || !rng_state) return RES_BAD_ARG;
    157   *rng_state = buf->rng;
    158   return RES_OK;
    159 }
    160 
    161 #undef SETUP_MC
    162 
    163 /*******************************************************************************
    164  * Local functions
    165  ******************************************************************************/
    166 res_T
    167 estimator_buffer_create
    168   (struct sdis_device* dev,
    169    const size_t width,
    170    const size_t height,
    171    struct sdis_estimator_buffer** out_buf)
    172 {
    173   struct sdis_estimator_buffer* buf = NULL;
    174   size_t i;
    175   res_T res = RES_OK;
    176 
    177   if(!dev || !width || !height || !out_buf) {
    178     res = RES_BAD_ARG;
    179     goto error;
    180   }
    181 
    182   buf = MEM_CALLOC(dev->allocator, 1, sizeof(*buf));
    183   if(!buf) { res = RES_MEM_ERR; goto error; }
    184 
    185   ref_init(&buf->ref);
    186   SDIS(device_ref_get(dev));
    187   buf->dev = dev;
    188   buf->width = width;
    189   buf->height = height;
    190 
    191   buf->estimators = MEM_CALLOC
    192     (dev->allocator, width*height, sizeof(*buf->estimators));
    193   if(!buf->estimators) {
    194     log_err(dev, "%s: could not allocate a buffer of estimators of %lux%lu.\n",
    195       FUNC_NAME, (unsigned long)width, (unsigned long)height);
    196     res = RES_MEM_ERR;
    197     goto error;
    198   }
    199 
    200   FOR_EACH(i, 0, width*height) {
    201     res = estimator_create(dev, SDIS_ESTIMATOR_TEMPERATURE, buf->estimators+i);
    202     if(res != RES_OK) goto error;
    203   }
    204 
    205 exit:
    206   if(out_buf) *out_buf = buf;
    207   return res;
    208 error:
    209   if(buf) {
    210     SDIS(estimator_buffer_ref_put(buf));
    211     buf = NULL;
    212   }
    213   goto exit;
    214 }
    215 
    216 struct sdis_estimator*
    217 estimator_buffer_grab
    218   (const struct sdis_estimator_buffer* buf,
    219    const size_t x,
    220    const size_t y)
    221 {
    222   ASSERT(x < buf->width && y < buf->height);
    223   return buf->estimators[y*buf->width + x];
    224 }
    225 
    226 void
    227 estimator_buffer_setup_realisations_count
    228   (struct sdis_estimator_buffer* buf,
    229    const size_t nrealisations,
    230    const size_t nsuccesses)
    231 {
    232   ASSERT(buf && nrealisations && nsuccesses && nsuccesses<=nrealisations);
    233   buf->nrealisations = nsuccesses;
    234   buf->nfailures = nrealisations - nsuccesses;
    235 }
    236 
    237 void
    238 estimator_buffer_setup_temperature
    239   (struct sdis_estimator_buffer* buf,
    240    const double sum,
    241    const double sum2)
    242 {
    243   ASSERT(buf && buf->nrealisations);
    244   buf->temperature.sum = sum;
    245   buf->temperature.sum2 = sum2;
    246   buf->temperature.count = buf->nrealisations;
    247 }
    248 
    249 void
    250 estimator_buffer_setup_realisation_time
    251   (struct sdis_estimator_buffer* buf,
    252    const double sum,
    253    const double sum2)
    254 {
    255   ASSERT(buf && buf->nrealisations);
    256   buf->realisation_time.sum = sum;
    257   buf->realisation_time.sum2 = sum2;
    258   buf->realisation_time.count = buf->nrealisations;
    259 }
    260 
    261 res_T
    262 estimator_buffer_save_rng_state
    263   (struct sdis_estimator_buffer* buf,
    264    const struct ssp_rng_proxy* proxy)
    265 {
    266   ASSERT(buf && proxy);
    267 
    268   /* Release the previous RNG state if any */
    269   if(buf->rng) {
    270     SSP(rng_ref_put(buf->rng));
    271     buf->rng = NULL;
    272   }
    273   return create_rng_from_rng_proxy(buf->dev, proxy, &buf->rng);
    274 }
    275 
    276 /* Define the functions generic to the observable type */
    277 #define SDIS_X_OBS probe
    278 #include "sdis_estimator_buffer_X_obs.h"
    279 #define SDIS_X_OBS probe_boundary
    280 #include "sdis_estimator_buffer_X_obs.h"