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_surface.c (12386B)


      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_brdf.h"
     28 #include "sphin_btdf.h"
     29 #include "sphin_c.h"
     30 #include "sphin_config.h"
     31 #include "sphin_geometry.h"
     32 #include "sphin_sensor_surface.h"
     33 #include "sphin_source_surface.h"
     34 #include "sphin_surface.h"
     35 
     36 #include <rsys/mem_allocator.h>
     37 #include <rsys/ref_count.h>
     38 #include <rsys/rsys.h>
     39 #include <rsys/str.h>
     40 #include <rsys/text_reader.h>
     41 
     42 struct sphin_brdf;
     43 struct sphin_btdf;
     44 struct sphin_sensor_surface;
     45 struct sphin_source_surface;
     46 
     47 struct sphin_surface {
     48   struct str name;
     49   struct sphin* sphin;
     50   struct sphin_brdf* brdf;
     51   struct sphin_btdf* btdf;
     52   struct darray_sphin_geometry_ptr geometries; /* dynamic array of struct
     53                                         geometry. see rsys/dynamic_array.h */
     54   struct sphin_sensor_surface* sensor_surface;
     55   struct sphin_source_surface* source_surface;
     56   ref_T ref;
     57 };
     58 
     59 /*******************************************************************************
     60  * Helper functions
     61  ******************************************************************************/
     62 static res_T
     63 surface_create
     64   (struct sphin* sphin,
     65    const char* name,
     66    struct sphin_surface** out_surface)
     67 {
     68   struct sphin_surface* surface = NULL;
     69   res_T res = RES_OK;
     70 
     71   ASSERT(NULL != sphin);
     72   ASSERT(NULL != out_surface);
     73   ASSERT(NULL != name);
     74   ASSERT('\0' != name[0]); /* Name can't be empty */
     75 
     76   surface = MEM_CALLOC(sphin->allocator, 1, sizeof(struct sphin_surface));
     77   if (NULL == surface) { res = RES_MEM_ERR; goto error; }
     78 
     79   /* Init volume ref counter and init member variables */
     80   ref_init(&surface->ref);
     81   SPHIN(ref_get(sphin));
     82   surface->sphin = sphin;
     83   surface->brdf = NULL;
     84   surface->btdf = NULL;
     85   surface->sensor_surface= NULL;
     86   surface->source_surface = NULL;
     87 
     88   str_init(sphin->allocator, &surface->name);
     89   darray_sphin_geometry_ptr_init(sphin->allocator, &surface->geometries);
     90   res = str_set(&surface->name, name);
     91   if (RES_OK != res) { goto error; }
     92 
     93 exit:
     94   *out_surface = surface;
     95   return res;
     96 error:
     97   if (NULL != surface) {
     98     SPHIN(surface_ref_put(surface));
     99     surface = NULL;
    100   }
    101   goto exit;
    102 }
    103 
    104 static void
    105 release_surface
    106   (ref_T* address)
    107 {
    108   size_t i, ngeometries;
    109   struct sphin* sphin = NULL;
    110   struct sphin_brdf* brdf = NULL;
    111   struct sphin_btdf* btdf = NULL;
    112   struct sphin_geometry** geometries = NULL;
    113   struct sphin_sensor_surface* sensor_surface = NULL;
    114   struct sphin_source_surface* source_surface = NULL;
    115   struct sphin_surface* surface = NULL;
    116   ASSERT(NULL != address);
    117 
    118   surface = CONTAINER_OF(address, struct sphin_surface, ref);
    119   str_release(&surface->name);
    120 
    121   /* Retrieve the number of geometries associated with the volume and decrease
    122    * the reference counter of each one of them */
    123   ngeometries = darray_sphin_geometry_ptr_size_get(&surface->geometries);
    124   geometries = darray_sphin_geometry_ptr_data_get(&surface->geometries);
    125 
    126   /* Put references for each one of the geometries */
    127   FOR_EACH(i, 0, ngeometries) {
    128     SPHIN(geometry_ref_put(geometries[i]));
    129   };
    130 
    131   if (NULL != geometries) {
    132     darray_sphin_geometry_ptr_release(&surface->geometries);
    133   }
    134 
    135   sphin = surface->sphin;
    136   brdf = surface->brdf;
    137   btdf = surface->btdf;
    138   sensor_surface = surface->sensor_surface;
    139   source_surface = surface->source_surface;
    140   MEM_RM(sphin->allocator, surface);
    141   if (NULL != source_surface) {
    142     SPHIN(source_surface_ref_put(source_surface));
    143   }
    144   if (NULL != sensor_surface) {
    145     SPHIN(sensor_surface_ref_put(sensor_surface));
    146   }
    147   if (NULL != brdf) {
    148     SPHIN(brdf_ref_put(brdf));
    149   }
    150   if (NULL != btdf) {
    151     SPHIN(btdf_ref_put(btdf));
    152   }
    153   SPHIN(ref_put(sphin));
    154 }
    155 
    156 static res_T
    157 parse_geometry
    158   (struct sphin_surface* surface,
    159    struct txtrdr* txtrdr,
    160    char* value)
    161 {
    162   struct sphin_geometry* geom = NULL;
    163   res_T res = RES_OK;
    164 
    165   ASSERT(NULL != surface);
    166   ASSERT(NULL != txtrdr);
    167 
    168   if (NULL == value) {res = RES_BAD_ARG; goto error; }
    169 
    170   res = geometry_parse(surface->sphin, value, &geom);
    171   if (RES_OK != res) { goto error; }
    172 
    173   /* Append a new element to the end of the volume->geometries dynamic array */
    174   res = darray_sphin_geometry_ptr_push_back(&surface->geometries, &geom);
    175   if (RES_OK != res) { goto error; }
    176 
    177   res = txtrdr_read_line(txtrdr);
    178   if (RES_OK != res) { goto error; }
    179 
    180 exit:
    181   return res;
    182 error:
    183   goto exit;
    184 }
    185 
    186 /*******************************************************************************
    187  * Local functions
    188  ******************************************************************************/
    189 res_T
    190 parse_surface
    191   (struct sphin_config* config,
    192    struct txtrdr* txtrdr,
    193    const char* name)
    194 {
    195   struct sphin_surface* surface = NULL;
    196   struct str line;
    197   char* keyword = NULL;
    198   char* token = NULL;
    199   char* token_ptr = NULL;
    200   res_T res = RES_OK;
    201 
    202   ASSERT(NULL != config);
    203   ASSERT(NULL != txtrdr);
    204   ASSERT(NULL != name);
    205   ASSERT('\0' != name[0]); /* Name can't be empty */
    206 
    207   str_init(config->sphin->allocator, &line);
    208 
    209   res = surface_create(config->sphin, name, &surface);
    210   if (RES_OK != res) { goto error; }
    211 
    212   res = txtrdr_read_line(txtrdr);
    213   if (RES_OK != res) { goto error; }
    214 
    215   while (NULL != txtrdr_get_line(txtrdr)) {
    216     res = str_set(&line, txtrdr_get_cline(txtrdr));
    217     if (RES_OK != res) { goto error; }
    218 
    219     /* parse keyword */
    220     token = strtok_r(str_get(&line), ":", &token_ptr);
    221     if (NULL == token){ res = RES_BAD_ARG; goto error; }
    222     keyword = trim_keyword(token);
    223     if (NULL == keyword){ res = RES_BAD_ARG; goto error; }
    224     /* parse value */
    225     token = token_ptr;
    226     if (0 == strcmp(keyword, "geometry")){
    227       res = parse_geometry(surface, txtrdr, token);
    228     }
    229     else if (0 == strcmp(keyword, "brdf")){
    230       res = parse_brdf(surface->sphin, txtrdr, token, &surface->brdf);
    231     }
    232     else if (0 == strcmp(keyword, "btdf")){
    233       res = parse_btdf(surface->sphin, txtrdr, token, &surface->btdf);
    234     }
    235     else if (0 == strcmp(keyword, "source")) {
    236       /* source should not have a name.
    237        * strings are not allowed in the input file after the :
    238        * check if there is only tabs and spaces after : */
    239       token = strtok_r(NULL, " \t", &token_ptr);
    240       if (NULL != token) { res = RES_BAD_ARG; goto error; }
    241       res = parse_source_surface(surface->sphin,
    242                                  txtrdr, name, &surface->source_surface);
    243     }
    244     else if (0 == strcmp(keyword, "sensor")) {
    245       /* sensor_surface should not have a name.
    246        * strings are not allowed in the input file after the :
    247        * check if there is only tabs and spaces after : */
    248       token = strtok_r(NULL, " \t", &token_ptr);
    249       if (NULL != token) { res = RES_BAD_ARG; goto error; }
    250       res = parse_sensor_surface
    251         (surface->sphin, txtrdr, name, &surface->sensor_surface);
    252     }
    253     else {
    254       break;
    255     }
    256     if (RES_OK != res) { goto error; }
    257   }
    258 
    259   /* Append a new element to the end of the sphin_config->surfaces array */
    260   res = darray_sphin_surface_ptr_push_back(&config->surfaces, &surface);
    261   if (RES_OK != res) { goto error; }
    262 
    263 exit:
    264   str_release(&line);
    265   return res;
    266 error:
    267   if (NULL != surface) {
    268     SPHIN(surface_ref_put(surface));
    269     surface = NULL;
    270   }
    271   goto exit;
    272 }
    273 
    274 /*******************************************************************************
    275  * Exported functions
    276  ******************************************************************************/
    277 res_T
    278 sphin_surface_ref_get
    279   (struct sphin_surface* surface)
    280 {
    281   if (NULL == surface) {
    282     return RES_BAD_ARG;
    283   }
    284   ref_get(&surface->ref);
    285   return RES_OK;
    286 }
    287 
    288 res_T
    289 sphin_surface_ref_put
    290   (struct sphin_surface* surface)
    291 {
    292   if (NULL == surface) {
    293     return RES_BAD_ARG;
    294   }
    295   ref_put(&surface->ref, release_surface);
    296   return RES_OK;
    297 }
    298 
    299 res_T
    300 sphin_surface_get_name
    301   (struct sphin_surface* surface,
    302    char** name)
    303 {
    304   if (NULL == surface || NULL == name) {
    305     return RES_BAD_ARG;
    306   }
    307   *name = (char*)str_get((struct str*)&surface->name);
    308   return RES_OK;
    309 }
    310 
    311 res_T
    312 sphin_surface_get_sensor
    313   (struct sphin_surface* surface,
    314    struct sphin_sensor_surface** sensor_surface)
    315 {
    316   if (NULL == surface
    317    || NULL == sensor_surface) {
    318     return RES_BAD_ARG;
    319   }
    320   *sensor_surface = surface->sensor_surface;
    321   return RES_OK;
    322 }
    323 
    324 res_T
    325 sphin_surface_get_brdf
    326   (const struct sphin_surface* surface,
    327    struct sphin_brdf** brdf)
    328 {
    329   if (NULL == surface || NULL == brdf) {
    330     return RES_BAD_ARG;
    331   }
    332   *brdf = surface->brdf;
    333   return RES_OK;
    334 }
    335 
    336 res_T
    337 sphin_surface_get_btdf
    338   (const struct sphin_surface* surface,
    339    struct sphin_btdf** btdf)
    340 {
    341   if (NULL == surface || NULL == btdf) {
    342     return RES_BAD_ARG;
    343   }
    344   *btdf = surface->btdf;
    345   return RES_OK;
    346 }
    347 
    348 res_T
    349 sphin_surface_get_source
    350   (const struct sphin_surface* surface,
    351    struct sphin_source_surface** source_surface)
    352 {
    353   if (NULL == surface || NULL == source_surface) {
    354     return RES_BAD_ARG;
    355   }
    356 
    357   *source_surface = surface->source_surface; /* NULL if surface has no source */
    358   return RES_OK;
    359 }
    360 
    361 res_T
    362 sphin_surface_get_geometry_count
    363   (struct sphin_surface* surface,
    364    size_t* ngeometries)
    365 {
    366   if (NULL == surface) {
    367     return RES_BAD_ARG;
    368   }
    369 
    370   *ngeometries = darray_sphin_geometry_ptr_size_get(&surface->geometries);
    371 
    372   return RES_OK;
    373 }
    374 
    375 res_T
    376 sphin_surface_get_geometry
    377   (struct sphin_surface* surface,
    378    size_t igeometry,
    379    struct sphin_geometry** geometry)
    380 {
    381   size_t ngeometries;
    382   if (NULL == surface) {
    383     return RES_BAD_ARG;
    384   }
    385 
    386   ngeometries = darray_sphin_geometry_ptr_size_get(&surface->geometries);
    387   if (igeometry > ngeometries) {
    388     return RES_BAD_ARG;
    389   }
    390 
    391   *geometry = darray_sphin_geometry_ptr_data_get
    392     (&surface->geometries)[igeometry];
    393 
    394   return RES_OK;
    395 }
    396 
    397 res_T
    398 sphin_surface_compute_total_area
    399   (struct sphin_surface* surface,
    400    double* area)
    401 {
    402   double total_geometry_area = 0;
    403   size_t geometry_count = 0;
    404   size_t i = 0;
    405   struct sphin_geometry* geometry = NULL;
    406   res_T res = RES_OK;
    407 
    408   geometry_count = darray_sphin_geometry_ptr_size_get(&surface->geometries);
    409 
    410   FOR_EACH(i, 0, geometry_count) {
    411     geometry = darray_sphin_geometry_ptr_data_get(&surface->geometries)[i];
    412     total_geometry_area += geometry_compute_area(geometry);
    413   }
    414 
    415   *area = total_geometry_area;
    416   return res;
    417 }
    418 
    419 res_T
    420 sphin_surface_source_get_power
    421   (struct sphin_surface* surface,
    422    double* power)
    423 {
    424   double sum_powers = 0;
    425   double total_geometry_area = 0;
    426   size_t geometry_count = 0;
    427   size_t i = 0;
    428   struct sphin_geometry* geometry = NULL;
    429   struct sphin_source_surface* source_surface = NULL;
    430   struct sphin_source_surface_flux_density density =
    431     SPHIN_SOURCE_SURFACE_FLUX_DENSITY_NULL;
    432   res_T res = RES_OK;
    433 
    434   source_surface = surface->source_surface;
    435 
    436   if (NULL == source_surface) {
    437     res = RES_BAD_ARG;
    438     goto error;
    439   }
    440 
    441   res = sphin_source_surface_get_flux_density(source_surface, &density);
    442   if (RES_OK != res) { goto error; }
    443 
    444   geometry_count = darray_sphin_geometry_ptr_size_get(&surface->geometries);
    445 
    446   FOR_EACH(i, 0, geometry_count) {
    447     geometry = darray_sphin_geometry_ptr_data_get(&surface->geometries)[i];
    448     total_geometry_area += geometry_compute_area(geometry);
    449   }
    450 
    451   sum_powers = total_geometry_area * density.flux_density;
    452 
    453 exit:
    454   *power = sum_powers;
    455   return res;
    456 error:
    457   goto exit;
    458 }