star-phor-input

File format for describing photoreactor configurations
git clone https://www.edstar.cnrs.fr/git/star-phor-input.git
Log | Files | Refs | README | LICENSE

sphin_volume.c (11286B)


      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 #define _POSIX_C_SOURCE 200112L /* for strtok_r support */
     25 
     26 #include "sphin.h"
     27 #include "sphin_c.h"
     28 #include "sphin_config.h"
     29 #include "sphin_geometry.h"
     30 #include "sphin_prop_rad.h"
     31 #include "sphin_refractive_index.h"
     32 #include "sphin_sensor_volume.h"
     33 #include "sphin_volume.h"
     34 
     35 #include <rsys/mem_allocator.h>
     36 #include <rsys/ref_count.h>
     37 #include <rsys/rsys.h>
     38 #include <rsys/str.h>
     39 #include <rsys/text_reader.h>
     40 
     41 struct sphin_sensor_volume;
     42 
     43 /*******************************************************************************
     44  * Helper functions
     45  ******************************************************************************/
     46 static res_T
     47 volume_create
     48   (struct sphin* sphin,
     49    const char* name,
     50    struct sphin_volume** out_volume)
     51 {
     52   struct sphin_volume* volume = NULL;
     53   res_T res = RES_OK;
     54 
     55   ASSERT(NULL != sphin);
     56   ASSERT(NULL != out_volume);
     57   ASSERT(NULL != name);
     58   ASSERT('\0' != name[0]); /* Name can't be empty */
     59 
     60   volume = MEM_CALLOC(sphin->allocator, 1, sizeof(struct sphin_volume));
     61   if (NULL == volume) { res = RES_MEM_ERR; goto error; }
     62 
     63   /* Init volume ref counter and init member variables */
     64   ref_init(&volume->ref);
     65   SPHIN(ref_get(sphin));
     66   volume->sphin = sphin;
     67   volume->sensor_volume = NULL;
     68   volume->refractive_index = NULL;
     69 
     70   str_init(sphin->allocator, &volume->name);
     71   darray_sphin_geometry_ptr_init(sphin->allocator, &volume->geometries);
     72   darray_sphin_prop_rad_ptr_init(sphin->allocator, &volume->prop_rads);
     73   res = str_set(&volume->name, name);
     74   if (RES_OK != res) { goto error; }
     75 
     76 exit:
     77   *out_volume = volume;
     78   return res;
     79 error:
     80   if (NULL != volume) {
     81     SPHIN(volume_ref_put(volume));
     82     volume = NULL;
     83   }
     84   goto exit;
     85 }
     86 
     87 static void
     88 release_volume
     89   (ref_T* address)
     90 {
     91   size_t i, ngeometries, nprop_rads;
     92   struct sphin_geometry** geometries = NULL;
     93   struct sphin_prop_rad** prop_rads = NULL;
     94   struct sphin* sphin = NULL;
     95   struct sphin_sensor_volume* sensor_volume = NULL;
     96   struct sphin_refractive_index* refr_ind = NULL;
     97   struct sphin_volume* volume = NULL;
     98   ASSERT(NULL != address);
     99 
    100   volume = CONTAINER_OF(address, struct sphin_volume, ref);
    101   str_release(&volume->name);
    102 
    103   /* Retrieve the number of geometries and prop rads associated with the volume
    104    * and decrease the reference counter of each one of them */
    105   ngeometries = darray_sphin_geometry_ptr_size_get(&volume->geometries);
    106   geometries = darray_sphin_geometry_ptr_data_get(&volume->geometries);
    107 
    108   nprop_rads = darray_sphin_prop_rad_ptr_size_get(&volume->prop_rads);
    109   prop_rads = darray_sphin_prop_rad_ptr_data_get(&volume->prop_rads);
    110 
    111   /* Put references for each one of the geometries */
    112   FOR_EACH(i, 0, ngeometries) {
    113     SPHIN(geometry_ref_put(geometries[i]));
    114   }
    115   if (NULL != geometries) {
    116     darray_sphin_geometry_ptr_release(&volume->geometries);
    117   }
    118 
    119   FOR_EACH(i, 0, nprop_rads) {
    120     SPHIN(prop_rad_ref_put(prop_rads[i]));
    121   }
    122   if (NULL != prop_rads) {
    123     darray_sphin_prop_rad_ptr_release(&volume->prop_rads);
    124   }
    125   sensor_volume = volume->sensor_volume;
    126   if (NULL != sensor_volume) {
    127     SPHIN(sensor_volume_ref_put(sensor_volume));
    128   }
    129   refr_ind = volume->refractive_index;
    130   if (NULL != refr_ind) {
    131     SPHIN(refractive_index_ref_put(refr_ind));
    132   }
    133   sphin = volume->sphin;
    134   MEM_RM(sphin->allocator, volume);
    135   SPHIN(ref_put(sphin));
    136 }
    137 
    138 static res_T
    139 parse_geometry
    140   (struct sphin_volume* volume,
    141    struct txtrdr* txtrdr,
    142    char* value)
    143 {
    144   struct sphin_geometry* geom;
    145   res_T res = RES_OK;
    146 
    147   ASSERT(NULL != volume);
    148   ASSERT(NULL != txtrdr);
    149 
    150   if (NULL == value){ res = RES_BAD_ARG; goto error; }
    151 
    152   res = geometry_parse(volume->sphin, value, &geom);
    153   if (RES_OK != res) { goto error; }
    154 
    155   /* Append a new element to the end of the volume->geometries dynamic array */
    156   res = darray_sphin_geometry_ptr_push_back(&volume->geometries, &geom);
    157   if (RES_OK != res) { goto error; }
    158 
    159   res = txtrdr_read_line(txtrdr);
    160   if (RES_OK != res) { goto error; }
    161 
    162 exit:
    163   return res;
    164 error:
    165   goto exit;
    166 }
    167 
    168 /*******************************************************************************
    169  * Local functions
    170  ******************************************************************************/
    171 res_T
    172 parse_volume
    173   (struct sphin_config* config,
    174    struct txtrdr* txtrdr,
    175    const char* name)
    176 {
    177   struct sphin_volume* volume = NULL;
    178   struct str line;
    179   char* keyword = NULL;
    180   char* token = NULL;
    181   char* token_ptr = NULL;
    182   res_T res = RES_OK;
    183 
    184   ASSERT(NULL != config);
    185   ASSERT(NULL != txtrdr);
    186   ASSERT(NULL != name);
    187   ASSERT('\0' != name[0]); /* Name can't be empty */
    188 
    189   str_init(config->sphin->allocator, &line);
    190 
    191   res = volume_create(config->sphin, name, &volume);
    192   if (RES_OK != res) { goto error; }
    193 
    194   res = txtrdr_read_line(txtrdr);
    195   if (RES_OK != res) { goto error; }
    196 
    197   while (NULL != txtrdr_get_line(txtrdr)) {
    198     res = str_set(&line, txtrdr_get_cline(txtrdr));
    199     if (RES_OK != res) { goto error; }
    200     /* parse keyword */
    201     token = strtok_r(str_get(&line), ":", &token_ptr);
    202     if (NULL == token){ res = RES_BAD_ARG; goto error; }
    203     keyword = trim_keyword(token);
    204     if (NULL == keyword){ res = RES_BAD_ARG; goto error; }
    205 
    206     /* parse value */
    207     token = token_ptr;
    208     if (0 == strcmp(keyword, "geometry")){
    209       res =  parse_geometry(volume, txtrdr, token);
    210     }
    211     else if (0 == strcmp(keyword, "prop_rad")){
    212       res = parse_prop_rad(config, volume, txtrdr, token);
    213     }
    214     else if (0 == strcmp(keyword, "sensor")) {
    215       /* for the sensor_volume,
    216        * strings are not allowed in the input file after the ":"
    217        * check if there is only tabs and spaces after ":" and return an error if
    218        * not */
    219       token = strtok_r(NULL, "\t ", &token_ptr);
    220       if (NULL != token) { res = RES_BAD_ARG; goto error; }
    221       /* continue parsing otherwise */
    222       res = parse_sensor_volume
    223         (volume->sphin, txtrdr, name, &volume->sensor_volume);
    224     }
    225     else if (0 == strcmp(keyword, "refractive_index")) {
    226       /* for the sensor_volume,
    227        * strings are not allowed in the input file after the ":"
    228        * check if there is only tabs and spaces after ":" and return an error if
    229        * not */
    230       token = strtok_r(NULL, "\t ", &token_ptr);
    231       if (NULL != token) { res = RES_BAD_ARG; goto error; }
    232       /* continue parsing otherwise */
    233       res = parse_refractive_index
    234         (volume->sphin, txtrdr, &volume->refractive_index);
    235     }
    236     else {
    237       break;
    238     }
    239     if (RES_OK != res) { goto error; }
    240   }
    241 
    242   /* Append a new element to the end of the sphin_config->volumes array */
    243   res = darray_sphin_volume_ptr_push_back(&config->volumes, &volume);
    244   if (RES_OK != res) { goto error; }
    245 
    246 exit:
    247   str_release(&line);
    248   return res;
    249 error:
    250   if (NULL != volume) {
    251     SPHIN(volume_ref_put(volume));
    252     volume = NULL;
    253   }
    254   goto exit;
    255 }
    256 
    257 /*******************************************************************************
    258  * Exported functions
    259  ******************************************************************************/
    260 res_T
    261 sphin_volume_ref_get
    262   (struct sphin_volume* volume)
    263 {
    264   if (NULL == volume) {
    265     return RES_BAD_ARG;
    266   }
    267   ref_get(&volume->ref);
    268   return RES_OK;
    269 }
    270 
    271 res_T
    272 sphin_volume_ref_put
    273   (struct sphin_volume* volume)
    274 {
    275   if (NULL == volume) {
    276     return RES_BAD_ARG;
    277   }
    278   ref_put(&volume->ref, release_volume);
    279   return RES_OK;
    280 }
    281 
    282 res_T
    283 sphin_volume_get_name
    284   (struct sphin_volume* volume,
    285    char** name)
    286 {
    287   if (NULL == volume || NULL == name) {
    288     return RES_BAD_ARG;
    289   }
    290   *name = (char*)str_get((struct str*)&volume->name);
    291   return RES_OK;
    292 }
    293 
    294 res_T
    295 sphin_volume_compute_total_size
    296   (struct sphin_volume* volume,
    297    double* total_size)
    298 {
    299   double total_vol = 0.;
    300   size_t geometry_count = 0;
    301   size_t i = 0;
    302   struct sphin_geometry* geometry = NULL;
    303 
    304   if (NULL == volume) { return RES_BAD_ARG; }
    305   if (NULL == total_size) { return RES_BAD_ARG; }
    306 
    307   geometry_count = darray_sphin_geometry_ptr_size_get(&volume->geometries);
    308 
    309   FOR_EACH(i, 0, geometry_count) {
    310     geometry = darray_sphin_geometry_ptr_data_get(&volume->geometries)[i];
    311     total_vol += geometry_compute_volume(geometry, geometry->side);
    312   }
    313   *total_size = total_vol;
    314   return RES_OK;
    315 }
    316 
    317 res_T
    318 sphin_volume_get_sensor
    319   (struct sphin_volume* volume,
    320    struct sphin_sensor_volume** sensor_volume)
    321 {
    322   if (NULL == volume
    323    || NULL == sensor_volume) {
    324     return RES_BAD_ARG;
    325   }
    326   *sensor_volume = volume->sensor_volume;
    327   return RES_OK;
    328 }
    329 
    330 res_T
    331 sphin_volume_get_geometry_count
    332   (struct sphin_volume* volume,
    333    size_t* ngeometries)
    334 {
    335   if (NULL == volume || NULL == ngeometries) {
    336     return RES_BAD_ARG;
    337   }
    338 
    339   *ngeometries = darray_sphin_geometry_ptr_size_get(&volume->geometries);
    340 
    341   return RES_OK;
    342 }
    343 
    344 res_T
    345 sphin_volume_get_geometry
    346   (struct sphin_volume* volume,
    347    size_t igeometry,
    348    struct sphin_geometry** geometry)
    349 {
    350   size_t ngeometries;
    351   if (NULL == volume) {
    352     return RES_BAD_ARG;
    353   }
    354 
    355   ngeometries = darray_sphin_geometry_ptr_size_get(&volume->geometries);
    356   if (igeometry > ngeometries) {
    357     return RES_BAD_ARG;
    358   }
    359 
    360   *geometry = darray_sphin_geometry_ptr_data_get
    361     (&volume->geometries)[igeometry];
    362 
    363   return RES_OK;
    364 }
    365 
    366 res_T
    367 sphin_volume_get_prop_rad_count
    368   (struct sphin_volume* volume,
    369    size_t* prop_rad_count)
    370 {
    371   if (NULL == volume || NULL == prop_rad_count) {
    372     return RES_BAD_ARG;
    373   }
    374 
    375   *prop_rad_count = darray_sphin_prop_rad_ptr_size_get(&volume->prop_rads);
    376 
    377   return RES_OK;
    378 }
    379 
    380 res_T
    381 sphin_volume_get_prop_rad
    382   (struct sphin_volume* volume,
    383    size_t iprop_rad,
    384    struct sphin_prop_rad** prop_rad)
    385 {
    386   size_t prop_rad_count;
    387   if (NULL == volume || NULL == prop_rad) {
    388     return RES_BAD_ARG;
    389   }
    390 
    391   prop_rad_count = darray_sphin_prop_rad_ptr_size_get(&volume->prop_rads);
    392   if (iprop_rad > prop_rad_count) {
    393     return RES_BAD_ARG;
    394   }
    395 
    396   *prop_rad = darray_sphin_prop_rad_ptr_data_get(&volume->prop_rads)[iprop_rad];
    397 
    398   return RES_OK;
    399 }
    400 
    401 res_T
    402 sphin_volume_get_refractive_index
    403   (struct sphin_volume* volume,
    404    struct sphin_refractive_index** refr_ind)
    405 {
    406   if (NULL == volume
    407    || NULL == refr_ind) {
    408     return RES_BAD_ARG;
    409   }
    410   *refr_ind = volume->refractive_index;
    411   return RES_OK;
    412 }