star-phor

Radiative transfer solver for photoreactors.
git clone https://www.edstar.cnrs.fr/git/star-phor.git
Log | Files | Refs | README | LICENSE

sphor_accum.c (7389B)


      1 /* Copyright (C) 2024-2026 Centre National de la Recherche Scientifique
      2  * Copyright (C) 2024-2026 Clermont Auvergne INP
      3  * Copyright (C) 2024-2026 INSA Lyon
      4  * Copyright (C) 2024-2026 Institut Mines Télécom Albi-Carmaux
      5  * Copyright (C) 2024-2026 Institut National Polytechnique de Toulouse
      6  * Copyright (C) 2024-2026 |Méso|Star> (contact@meso-star.com)
      7  * Copyright (C) 2024-2026 PhotonLyX (info@photonlyx.com)
      8  * Copyright (C) 2024-2026 Université de Lorraine
      9  * Copyright (C) 2024-2026 Université Paul Sabatier
     10  * Copyright (C) 2024-2026 Université Toulouse - Jean Jaurès
     11  *
     12  * This program is free software: you can redistribute it and/or modify
     13  * it under the terms of the GNU General Public License as published by
     14  * the Free Software Foundation, either version 3 of the License, or
     15  * (at your option) any later version.
     16  *
     17  * This program is distributed in the hope that it will be useful,
     18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
     20  * GNU General Public License for more details.
     21  *
     22  * You should have received a copy of the GNU General Public License
     23  * along with this program. If not, see <http://www.gnu.org/licenses/>. */
     24 
     25 #include "sphor_accum.h"
     26 
     27 #include <math.h>
     28 
     29 struct mem_allocator;
     30 
     31 /*******************************************************************************
     32  * Local functions
     33  ******************************************************************************/
     34 extern LOCAL_SYM void
     35 accum_init
     36   (struct mem_allocator* allocator,
     37    struct accum* accum)
     38 {
     39   ASSERT(NULL != allocator);
     40   ASSERT(NULL != accum);
     41 
     42   *accum = ACCUM_NULL;
     43   str_init(allocator, &accum->observable);
     44   str_init(allocator, &accum->sensor);
     45   str_init(allocator, &accum->component);
     46 }
     47 
     48 extern LOCAL_SYM void
     49 accum_release
     50   (struct accum* accum)
     51 {
     52   ASSERT(NULL != accum);
     53 
     54   str_release(&accum->observable);
     55   str_release(&accum->sensor);
     56   str_release(&accum->component);
     57 }
     58 
     59 extern LOCAL_SYM res_T
     60 accum_copy
     61   (struct accum* dst,
     62    const struct accum* src)
     63 {
     64   res_T res = RES_OK;
     65 
     66   ASSERT(NULL != dst);
     67   ASSERT(NULL != src);
     68 
     69   dst->sum = src->sum;
     70   dst->sum2 = src->sum2;
     71   dst->n_realizations = src->n_realizations;
     72   res = str_copy(&dst->observable, &src->observable);
     73   if (RES_OK != res) { return res; }
     74   res = str_copy(&dst->sensor, &src->sensor);
     75   if (RES_OK != res) { return res; }
     76   res = str_copy(&dst->component, &src->component);
     77   return res;
     78 }
     79 
     80 extern LOCAL_SYM res_T
     81 accum_copy_and_release
     82   (struct accum* dst,
     83    struct accum* src)
     84 {
     85   res_T res = RES_OK;
     86 
     87   ASSERT(NULL != dst);
     88   ASSERT(NULL != src);
     89 
     90   dst->sum = src->sum;
     91   dst->sum2 = src->sum2;
     92   dst->n_realizations = src->n_realizations;
     93   res = str_copy_and_release(&dst->observable, &src->observable);
     94   if (RES_OK != res) { return res; }
     95   res = str_copy_and_release(&dst->sensor, &src->sensor);
     96   if (RES_OK != res) { return res; }
     97   res = str_copy_and_release(&dst->component, &src->component);
     98   return res;
     99 }
    100 
    101 extern LOCAL_SYM res_T
    102 register_accum
    103   (struct mem_allocator* allocator,
    104    char* observable,
    105    char* sensor,
    106    char* component,
    107    struct darray_accum *accums)
    108 {
    109   struct accum accum = ACCUM_NULL;
    110   res_T res = RES_OK;
    111 
    112   accum_init(allocator, &accum);
    113 
    114   str_set(&accum.observable, observable);
    115   str_set(&accum.sensor, sensor);
    116   str_set(&accum.component, component);
    117 
    118   res = darray_accum_push_back(accums, &accum);
    119   if (res != RES_OK) { goto error; }
    120 exit:
    121   accum_release(&accum);
    122   return res;
    123 error:
    124   goto exit;
    125 }
    126 
    127 extern LOCAL_SYM void
    128 accum_compute_estim
    129   (const struct accum* accum,
    130    struct estim* estim)
    131 {
    132   double sum = 0;
    133   double sum2 = 0;
    134   double samples = 0;
    135   double mean = 0;
    136   double var = 0;
    137   double std_err = 0;
    138 
    139   ASSERT(NULL != accum);
    140   ASSERT(NULL != estim);
    141 
    142   samples = (double)accum->n_realizations;
    143   sum = accum->sum;
    144   sum2 = accum->sum2;
    145 
    146   mean = sum / samples;
    147   /* Compute the sample variance. This formula is equivalent to
    148    * var = 1 / (n-1)  sum(x_i - <x>)^2 */
    149   var = (sum2 - sum * sum / samples) / (samples - 1);
    150   /* Clamp variance to 0 to guard against small negative values
    151    * caused by floating-point rounding errors */
    152   var = var < 0 ? 0 : var;
    153   std_err = sqrt (var / samples);
    154 
    155   estim->mean = mean;
    156   estim->var = var;
    157   estim->std_err = std_err;
    158 }
    159 
    160 extern LOCAL_SYM void
    161 write_accum_estim
    162   (const struct accum* accum,
    163    FILE* stream)
    164 {
    165   struct estim estim = ESTIM_NULL;
    166 
    167   ASSERT(NULL != accum);
    168   ASSERT(NULL != stream);
    169 
    170   accum_compute_estim(accum, &estim);
    171 
    172   if (0 != strcmp("\0", str_cget(&accum->component))){
    173     fprintf
    174       (stream, "%s:%s:%s:%lf:%lf\n",
    175        str_cget(&accum->observable),
    176        str_cget(&accum->sensor),
    177        str_cget(&accum->component),
    178        estim.mean, estim.std_err);
    179   } else if (0 != strcmp("\0", str_cget(&accum->sensor))){
    180     fprintf
    181       (stream, "%s:%s:%lf:%lf\n",
    182        str_cget(&accum->observable),
    183        str_cget(&accum->sensor),
    184        estim.mean, estim.std_err);
    185   } else {
    186     fprintf
    187       (stream, "%s:%lf:%lf\n",
    188        str_cget(&accum->observable),
    189        estim.mean, estim.std_err);
    190   }
    191 }
    192 
    193 extern LOCAL_SYM void
    194 accum_add
    195   (const struct accum* op0,
    196    const struct accum* op1,
    197    struct accum* result)
    198 {
    199   ASSERT(NULL != op0);
    200   ASSERT(NULL != op1);
    201   ASSERT(NULL != result);
    202 
    203   result->sum = op0->sum + op1->sum;
    204   result->sum2 = op0->sum2 + op1->sum2;
    205 }
    206 
    207 extern LOCAL_SYM void
    208 accums_add
    209   (const struct darray_accum* op0,
    210    const struct darray_accum* op1,
    211    struct darray_accum* result)
    212 {
    213   size_t i = 0;
    214   size_t naccums = 0;
    215 
    216   ASSERT(NULL != op0);
    217   ASSERT(NULL != op1);
    218   ASSERT(NULL != result);
    219 
    220   naccums = darray_accum_size_get(result);
    221   ASSERT(darray_accum_size_get(op0) == darray_accum_size_get(op1));
    222   ASSERT(darray_accum_size_get(op0) == naccums);
    223 
    224   FOR_EACH(i, 0, naccums){
    225     accum_add(darray_accum_cdata_get(op0) + i,
    226               darray_accum_cdata_get(op1) + i,
    227               darray_accum_data_get(result) + i);
    228   }
    229 }
    230 
    231 extern LOCAL_SYM void
    232 sum_accums
    233   (const struct darray_accum* accums,
    234    struct accum* tot_accum)
    235 {
    236   size_t j = 0;
    237   size_t accum_count = 0;
    238 
    239   ASSERT(NULL != accums);
    240   ASSERT(NULL != tot_accum);
    241 
    242   accum_count = darray_accum_size_get(accums);
    243 
    244   FOR_EACH(j, 0, accum_count) {
    245     struct accum* accum = NULL;
    246     accum = (struct accum*)darray_accum_cdata_get(accums) + j;
    247     accum_add(tot_accum, accum, tot_accum);
    248   }
    249 }
    250 
    251 extern LOCAL_SYM void
    252 sum_accum_lists
    253   (const struct darray_accum_list* accum_lists,
    254    struct darray_accum* accums)
    255 {
    256   size_t list_len = 0;
    257   size_t i;
    258 
    259   ASSERT(NULL != accum_lists);
    260   ASSERT(NULL != accums);
    261 
    262   list_len = darray_accum_list_size_get(accum_lists);
    263 
    264   FOR_EACH(i, 0, list_len) {
    265     struct darray_accum* accums_i = NULL;
    266     accums_i = (struct darray_accum*)darray_accum_list_cdata_get(accum_lists)+i;
    267     accums_add(accums, accums_i, accums);
    268   }
    269 }
    270 
    271 extern LOCAL_SYM void
    272 update_accum
    273   (const struct htable_accum2id* accum2id,
    274    const struct accum_key* accum_key,
    275    const double weight,
    276    struct darray_accum* accums)
    277 {
    278   size_t* paccum_id = NULL;
    279   struct accum* accum = NULL;
    280 
    281   ASSERT(NULL != accum2id);
    282   ASSERT(NULL != accums);
    283 
    284   paccum_id = htable_accum2id_find
    285     ((struct htable_accum2id *)accum2id, accum_key);
    286   ASSERT(NULL != paccum_id);
    287 
    288   accum = &darray_accum_data_get(accums)[*paccum_id];
    289 
    290   accum->sum += weight;
    291   accum->sum2 += weight*weight;
    292 }