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