htgop

Optical properties of a gas mixture
git clone git://git.meso-star.fr/htgop.git
Log | Files | Refs | README | LICENSE

htgop_get_radiative_properties_bounds.h (4653B)


      1 /* Copyright (C) 2018-2021, 2023 |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 "htgop.h"
     17 #include "htgop_c.h"
     18 
     19 #if !defined(DATA) || !defined(DOMAIN)
     20   #error "Missing the <DATA|DOMAIN> macro."
     21 #endif
     22 
     23 #ifndef GET_DATA
     24   #define GET_DATA(Tab, Id) ((Tab)->CONCAT(DATA,_tab)[Id])
     25 #endif
     26 
     27 /*
     28  * Generate functions that retrieve the boundaries of the radiative properties
     29  */
     30 
     31 res_T CONCAT(CONCAT(CONCAT(CONCAT(
     32 htgop_layer_,DOMAIN),_spectral_interval_quadpoints_get_),DATA),_bounds)
     33   (const struct CONCAT(CONCAT(htgop_layer_,DOMAIN),_spectral_interval)* specint,
     34    const size_t iquad_range[2],
     35    const double x_h2o_range[2],
     36    double bounds[2])
     37 {
     38   size_t iquad;
     39   res_T res = RES_OK;
     40 
     41   if(!specint || !bounds || !iquad_range) {
     42     res = RES_BAD_ARG;
     43     goto error;
     44   }
     45 
     46   if(iquad_range[0] > iquad_range[1]
     47   || iquad_range[0] >= specint->quadrature_length
     48   || iquad_range[1] >= specint->quadrature_length) {
     49     log_err(specint->htgop,
     50       "%s: invalid range of quadrature points [%lu, %lu].\n", FUNC_NAME,
     51       (unsigned long)iquad_range[0], (unsigned long)iquad_range[1]);
     52     res = RES_BAD_ARG;
     53     goto error;
     54   }
     55 
     56   bounds[0] = DBL_MAX;
     57   bounds[1] =-DBL_MAX;
     58 
     59   FOR_EACH(iquad, iquad_range[0], iquad_range[1]+1) {
     60     struct CONCAT(CONCAT(htgop_layer_,DOMAIN),_spectral_interval_tab) tab;
     61     double tab_bounds[2];
     62 
     63     HTGOP(CONCAT(CONCAT(layer_,DOMAIN),_spectral_interval_get_tab)
     64       (specint, iquad, &tab));
     65     res = CONCAT(CONCAT(CONCAT(CONCAT(
     66       htgop_layer_,DOMAIN),_spectral_interval_tab_get_),DATA),_bounds)
     67         (&tab, x_h2o_range, tab_bounds);
     68     if(res != RES_OK) goto exit;
     69 
     70     bounds[0] = MMIN(bounds[0], tab_bounds[0]);
     71     bounds[1] = MMAX(bounds[1], tab_bounds[1]);
     72   }
     73 
     74 exit:
     75   return res;
     76 error:
     77   if(bounds) {
     78     bounds[0] = DBL_MAX;
     79     bounds[1] =-DBL_MAX;
     80   }
     81   goto exit;
     82 }
     83 
     84 res_T CONCAT(CONCAT(CONCAT(CONCAT(
     85 htgop_layer_,DOMAIN),_spectral_interval_tab_get_),DATA),_bounds)
     86   (const struct CONCAT(CONCAT(htgop_layer_,DOMAIN),_spectral_interval_tab)* tab,
     87    const double x_h2o_range[2],
     88    double bounds[2])
     89 {
     90   size_t itab_range[2];
     91   double* x_h2o_low;
     92   double* x_h2o_upp;
     93   double k1, k2;
     94   size_t i;
     95   res_T res = RES_OK;
     96 
     97   if(!tab || !bounds || !x_h2o_range) {
     98     res = RES_BAD_ARG;
     99     goto error;
    100   }
    101 
    102   if(x_h2o_range[0] > x_h2o_range[1]) {
    103     log_err(tab->htgop,
    104       "%s: invalid water vapor molar fraction range [%g, %g].\n", 
    105       FUNC_NAME, SPLIT2(x_h2o_range));
    106     res = RES_BAD_ARG;
    107     goto error;
    108   }
    109 
    110   /* Find the pointers toward the first x_h2o greater than or equal to the
    111    * x_h2o boundaries */
    112   x_h2o_low = search_lower_bound(&x_h2o_range[0], tab->x_h2o_tab,
    113     tab->tab_length, sizeof(double), cmp_dbl);
    114   x_h2o_upp = search_lower_bound(&x_h2o_range[1], tab->x_h2o_tab,
    115     tab->tab_length, sizeof(double), cmp_dbl);
    116   if(!x_h2o_low || !x_h2o_upp || (x_h2o_low > x_h2o_upp)) {
    117     log_err(tab->htgop, "%s: invalid x_h2o range [%g, %g].\n",
    118       FUNC_NAME, SPLIT2(x_h2o_range));
    119     res = RES_BAD_ARG;
    120     goto error;
    121   }
    122 
    123   /* Compute the K at the boundaries of the x_h2o_range */
    124   k1 = CONCAT(CONCAT(CONCAT(
    125     layer_,DOMAIN),_spectral_interval_tab_interpolate_),DATA)
    126       (tab, x_h2o_range[0], x_h2o_low);
    127 
    128   if(x_h2o_range[0] == x_h2o_range[1]) {
    129     k2 = k1;
    130   } else {
    131     k2 = CONCAT(CONCAT(CONCAT(
    132       layer_,DOMAIN),_spectral_interval_tab_interpolate_),DATA)
    133         (tab, x_h2o_range[1], x_h2o_upp);
    134   }
    135   bounds[0] = MMIN(k1, k2);
    136   bounds[1] = MMAX(k1, k2);
    137 
    138   /* Define the remaining tabulation point to handle */
    139   itab_range[0] = (size_t)(x_h2o_low - tab->x_h2o_tab);
    140   itab_range[1] = (size_t)(x_h2o_upp - tab->x_h2o_tab);
    141 
    142   /* Iterate on the remaining tabulation point */
    143   FOR_EACH(i, itab_range[0], itab_range[1]) {
    144     const double k = GET_DATA(tab, i);
    145     bounds[0] = MMIN(bounds[0], k);
    146     bounds[1] = MMAX(bounds[1], k);
    147   }
    148 
    149 exit:
    150   return res;
    151 error:
    152   if(bounds) {
    153     bounds[0] = DBL_MAX;
    154     bounds[1] =-DBL_MAX;
    155   }
    156   goto exit;
    157 }
    158 
    159 #undef DATA
    160 #undef DOMAIN
    161 #undef GET_DATA
    162