shtr.h (13516B)
1 /* Copyright (C) 2022, 2025, 2026 |Méso|Star> (contact@meso-star.com) 2 * Copyright (C) 2025, 2026 Université de Lorraine 3 * Copyright (C) 2022 Centre National de la Recherche Scientifique 4 * Copyright (C) 2022 Université Paul Sabatier 5 * 6 * This program is free software: you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation, either version 3 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program. If not, see <http://www.gnu.org/licenses/>. */ 18 19 #ifndef SHTR_H 20 #define SHTR_H 21 22 #include <rsys/hash.h> 23 #include <rsys/rsys.h> 24 25 #include <float.h> 26 #include <limits.h> 27 28 /* Library symbol management */ 29 #if defined(SHTR_SHARED_BUILD) /* Build shared library */ 30 #define SHTR_API extern EXPORT_SYM 31 #elif defined(SHTR_STATIC) /* Use/build static library */ 32 #define SHTR_API extern LOCAL_SYM 33 #else 34 #define SHTR_API extern IMPORT_SYM 35 #endif 36 37 /* Helper macro that asserts if the invocation of the shtr function `Func' 38 * returns an error. One should use this macro on shtr function calls for which 39 * no explicit error checking is performed */ 40 #ifndef NDEBUG 41 #define SHTR(Func) ASSERT(shtr_ ## Func == RES_OK) 42 #else 43 #define SHTR(Func) shtr_ ## Func 44 #endif 45 46 #define SHTR_MAX_ISOTOPE_COUNT 16 47 48 /* List of HITRAN species. They are classified as in the HITRAN database, i.e. 49 * their value corresponds to that of HITRAN. Note that they start at 1 rather 50 * than zero and therefore do not strictly correspond to a C array index */ 51 enum shtr_molecule_id { 52 SHTR_MOLECULE_ID_NULL = 0, 53 54 SHTR_H2O, SHTR_CO2, SHTR_O3, SHTR_N2O, SHTR_CO, SHTR_CH4, 55 SHTR_O2, SHTR_NO, SHTR_SO2, SHTR_NO2, SHTR_NH3, SHTR_HNO3, 56 SHTR_OH, SHTR_HF, SHTR_HCl, SHTR_HBr, SHTR_HI, SHTR_ClO, 57 SHTR_OCS, SHTR_H2CO, SHTR_HOCl, SHTR_N2, SHTR_HCN, SHTR_CH3Cl, 58 SHTR_H2O2, SHTR_C2H2, SHTR_C2H6, SHTR_PH3, SHTR_COF2, SHTR_SF6, 59 SHTR_H2S, SHTR_HCOOH, SHTR_HO2, SHTR_O, SHTR_ClONO2, SHTR_NOplus, 60 SHTR_HOBr, SHTR_C2H4, SHTR_CH3OH, SHTR_CH3Br, SHTR_CH3CN, SHTR_CF4, 61 SHTR_C4H2, SHTR_HC3N, SHTR_H2, SHTR_CS, SHTR_SO3, SHTR_C2N2, 62 SHTR_COCl2, SHTR_SO, SHTR_CH3F, SHTR_GeH4, SHTR_CS2, SHTR_CH3I, 63 SHTR_NF3, 64 65 SHTR_MAX_MOLECULE_COUNT 66 }; 67 68 /* Table that associates the molecule ID with its name */ 69 static const char* SHTR_MOLECULE_CSTR__[SHTR_MAX_MOLECULE_COUNT] = { 70 NULL, /* SHTR_MOLECULE_ID_NULL__ */ 71 72 "H2O", "CO2", "O3", "N2O", "CO", "CH4", 73 "O2", "NO", "SO2", "NO2", "NH3", "HNO3", 74 "OH", "HF", "HCl", "HBr", "HI", "ClO", 75 "OCS", "H2CO", "HOCl", "N2", "HCN", "CH3Cl", 76 "H2O2", "C2H2", "C2H6", "PH3", "COF2", "SF6", 77 "H2S", "HCOOH", "HO2", "O", "ClONO2", "NO+", 78 "HOBr", "C2H4", "CH3OH", "CH3Br", "CH3CN", "CF4", 79 "C4H2", "HC3N", "H2", "CS", "SO3", "C2N2", 80 "COCl2", "SO", "CH3F", "GeH4", "CS2", "CH3I", 81 "NF3" 82 }; 83 84 static INLINE const char* 85 shtr_molecule_cstr(const enum shtr_molecule_id id) 86 { 87 ASSERT(id < SHTR_MAX_MOLECULE_COUNT); 88 return SHTR_MOLECULE_CSTR__[id]; 89 } 90 91 struct shtr_isotope { 92 double abundance; /* in ]0, 1] */ 93 double Q296K; /* Partition function at Tref = 296K */ 94 double molar_mass; /* In g.mol^-1 */ 95 96 /* Local idx of the molecule to which the isotope belongs */ 97 size_t molecule_id_local; 98 99 int gj; /* State independent degeneracy factor */ 100 int id; /* Identifier of the isotope <=> Global index */ 101 }; 102 #define SHTR_ISOTOPE_NULL__ {0,0,0,0,0,-1} 103 static const struct shtr_isotope SHTR_ISOTOPE_NULL = 104 SHTR_ISOTOPE_NULL__; 105 106 struct shtr_molecule { 107 const char* name; 108 size_t nisotopes; /* Number of isotopes */ 109 const struct shtr_isotope* isotopes; 110 enum shtr_molecule_id id; /* Unique identifier */ 111 }; 112 #define SHTR_MOLECULE_NULL__ {NULL, 0, NULL, SHTR_MOLECULE_ID_NULL} 113 static const struct shtr_molecule SHTR_MOLECULE_NULL = 114 SHTR_MOLECULE_NULL__; 115 116 #define SHTR_MOLECULE_IS_NULL(Molecule) \ 117 ((Molecule)->id == SHTR_MOLECULE_NULL.id) 118 119 struct shtr_line { 120 double wavenumber; /* Central wavenumber in vacuum [cm^-1] */ 121 double intensity; /* Reference intensity [cm^-1/(molec.cm^2)] */ 122 double gamma_air; /* Air broadening half-width [cm^-1.atm^-1] */ 123 double gamma_self; /* Self broadening half-width [cm^-1.atm^-1] */ 124 double lower_state_energy; /* [cm^-1] */ 125 double n_air; /* Temperature-dependant exponent */ 126 double delta_air; /* Air-pressure wavenumber shift [cm^-1.atm^-1] */ 127 128 enum shtr_molecule_id molecule_id; 129 130 /* The value of the following isotopic index is _not_ the value of the 131 * isotopic index read from the HITRAN file. The original value is in [0, 9] 132 * with 0 actually meaning 10. Thus, once decoded, the index is located in 133 * [1, 10]. The next member variable simply stores this index but decremented 134 * by one in order to make it compatible with C indexing. As a result, it 135 * can be used directly to index the 'isotopes' array of a 'shtr_molecule' 136 * data structure loaded from an isotope metadata file */ 137 int32_t isotope_id_local; 138 }; 139 #define SHTR_LINE_NULL__ {0,0,0,0,0,0,0,-1,-1} 140 static const struct shtr_line SHTR_LINE_NULL = SHTR_LINE_NULL__; 141 142 static INLINE int 143 shtr_line_eq(const struct shtr_line* line0, const struct shtr_line* line1) 144 { 145 ASSERT(line0 && line1); 146 return line0->wavenumber == line1->wavenumber 147 && line0->intensity == line1->intensity 148 && line0->gamma_air == line1->gamma_air 149 && line0->gamma_self == line1->gamma_self 150 && line0->lower_state_energy == line1->lower_state_energy 151 && line0->n_air == line1->n_air 152 && line0->delta_air == line1->delta_air 153 && line0->molecule_id == line1->molecule_id 154 && line0->isotope_id_local == line1->isotope_id_local; 155 } 156 157 struct shtr_line_param_info { 158 double range[2]; 159 double err; /* Encoding error */ 160 }; 161 #define SHTR_LINE_PARAM_INFO_NULL__ {{DBL_MAX,-DBL_MAX}, 0} 162 static const struct shtr_line_param_info SHTR_LINE_PARAM_INFO_NULL = 163 SHTR_LINE_PARAM_INFO_NULL__; 164 165 /* Information on a list of lines */ 166 struct shtr_line_list_info { 167 struct shtr_line_param_info wavenumber; 168 struct shtr_line_param_info intensity; 169 struct shtr_line_param_info gamma_air; 170 struct shtr_line_param_info gamma_self; 171 struct shtr_line_param_info lower_state_energy; 172 struct shtr_line_param_info n_air; 173 struct shtr_line_param_info delta_air; 174 }; 175 #define SHTR_LINE_LIST_INFO_NULL__ { \ 176 SHTR_LINE_PARAM_INFO_NULL__, \ 177 SHTR_LINE_PARAM_INFO_NULL__, \ 178 SHTR_LINE_PARAM_INFO_NULL__, \ 179 SHTR_LINE_PARAM_INFO_NULL__, \ 180 SHTR_LINE_PARAM_INFO_NULL__, \ 181 SHTR_LINE_PARAM_INFO_NULL__, \ 182 SHTR_LINE_PARAM_INFO_NULL__, \ 183 } 184 static const struct shtr_line_list_info SHTR_LINE_LIST_INFO_NULL = 185 SHTR_LINE_LIST_INFO_NULL__; 186 187 /* Forward declarations of opaque data structures */ 188 struct shtr; 189 struct shtr_isotope_metadata; 190 struct shtr_line_list; 191 struct shtr_line_view; 192 193 /******************************************************************************* 194 * Input arguments for API functions 195 ******************************************************************************/ 196 struct shtr_create_args { 197 struct logger* logger; /* May be NULL <=> default logger */ 198 struct mem_allocator* allocator; /* NULL <=> use default allocator */ 199 int verbose; /* Verbosity level */ 200 }; 201 #define SHTR_CREATE_ARGS_DEFAULT__ {NULL, NULL, 0} 202 static const struct shtr_create_args SHTR_CREATE_ARGS_DEFAULT = 203 SHTR_CREATE_ARGS_DEFAULT__; 204 205 /* Load lines saved in HITRAN format */ 206 struct shtr_line_list_load_args { 207 /* Name of the file to load or of the provided stream. 208 * NULL <=> uses a default name for the stream to be loaded, which must 209 * therefore be defined. */ 210 const char* filename; 211 212 /* Stream from where data are loaded. 213 * NULL <=> loading from the file name, which must therefore be defined */ 214 FILE* file; 215 }; 216 #define SHTR_LINE_LIST_LOAD_ARGS_NULL__ {NULL, NULL} 217 static const struct shtr_line_list_load_args SHTR_LINE_LIST_LOAD_ARGS_NULL = 218 SHTR_LINE_LIST_LOAD_ARGS_NULL__; 219 220 /* Read the lines stored in the internal format of the shtr library, i.e., as 221 * they were written by the shtr_line_list_write function */ 222 struct shtr_line_list_read_args { 223 /* Name of the file to read or of the provided stream. 224 * NULL <=> uses a default name for the stream to be read, which must 225 * therefore be defined. */ 226 const char* filename; /* Name of the file to read */ 227 FILE* file; /* Stream from where data are read. NULL <=> read from file */ 228 229 /* Range of line indices to read. The limits are included. 230 * If the lower limit is greater than or equal to the number of lines to read, 231 * no lines are read. 232 * If the upper limit is greater than or equal to the number of lines to read, 233 * all lines from the lower limit are read. 234 * If the range is degenerate, an error is returned. */ 235 size_t range[2]; 236 }; 237 #define SHTR_LINE_LIST_READ_ARGS_NULL__ {NULL, NULL, {0,SIZE_MAX}} 238 static const struct shtr_line_list_read_args SHTR_LINE_LIST_READ_ARGS_NULL = 239 SHTR_LINE_LIST_READ_ARGS_NULL__; 240 241 struct shtr_line_list_write_args { 242 /* Name of the file in which the list of lines is serialized. 243 * NULL <=> uses a default name for the stream to be written, which must 244 * therefore be defined. */ 245 const char* filename; /* Name of the file to read */ 246 247 /* Stream where data is written. 248 * NULL <=> write to the file defined by "filename" */ 249 FILE* file; 250 }; 251 #define SHTR_LINE_LIST_WRITE_ARGS_NULL__ {NULL, NULL} 252 static const struct shtr_line_list_write_args SHTR_LINE_LIST_WRITE_ARGS_NULL = 253 SHTR_LINE_LIST_WRITE_ARGS_NULL__; 254 255 BEGIN_DECLS 256 257 /******************************************************************************* 258 * Device API 259 ******************************************************************************/ 260 SHTR_API res_T 261 shtr_create 262 (const struct shtr_create_args* args, 263 struct shtr** shtr); 264 265 SHTR_API res_T 266 shtr_ref_get 267 (struct shtr* shtr); 268 269 SHTR_API res_T 270 shtr_ref_put 271 (struct shtr* shtr); 272 273 /******************************************************************************* 274 * Isotope metadata API 275 ******************************************************************************/ 276 SHTR_API res_T 277 shtr_isotope_metadata_load 278 (struct shtr* shtr, 279 const char* path, 280 struct shtr_isotope_metadata** metadata); 281 282 SHTR_API res_T 283 shtr_isotope_metadata_load_stream 284 (struct shtr* shtr, 285 FILE* stream, 286 const char* stream_name, /* NULL <=> use default stream name */ 287 struct shtr_isotope_metadata** metadata); 288 289 /* Load the isotope metadata serialized with the "shtr_isotope_metadata_write" 290 * function */ 291 SHTR_API res_T 292 shtr_isotope_metadata_create_from_stream 293 (struct shtr* shtr, 294 FILE* stream, 295 struct shtr_isotope_metadata** metadata); 296 297 SHTR_API res_T 298 shtr_isotope_metadata_ref_get 299 (struct shtr_isotope_metadata* metadata); 300 301 SHTR_API res_T 302 shtr_isotope_metadata_ref_put 303 (struct shtr_isotope_metadata* metadata); 304 305 SHTR_API res_T 306 shtr_isotope_metadata_get_molecules_count 307 (const struct shtr_isotope_metadata* metadata, 308 size_t* nmolecules); 309 310 SHTR_API res_T 311 shtr_isotope_metadata_get_isotopes_count 312 (const struct shtr_isotope_metadata* metadata, 313 size_t* nisotopes); 314 315 SHTR_API res_T 316 shtr_isotope_metadata_get_molecule 317 (const struct shtr_isotope_metadata* metadata, 318 const size_t imolecule, /* Local index of the molecule in [0, molecules_count[ */ 319 struct shtr_molecule* molecule); 320 321 /* `molecule' is set to SHTR_MOLECULE_NULL if `molecule_id' is not found */ 322 SHTR_API res_T 323 shtr_isotope_metadata_find_molecule 324 (struct shtr_isotope_metadata* metadata, 325 const int molecule_id, /* Unique identifier of the molecule <=> Global index */ 326 struct shtr_molecule* molecule); 327 328 SHTR_API res_T 329 shtr_isotope_metadata_write 330 (const struct shtr_isotope_metadata* metadata, 331 FILE* stream); 332 333 SHTR_API res_T 334 shtr_isotope_metadata_hash 335 (const struct shtr_isotope_metadata* metadata, 336 hash256_T hash); 337 338 /******************************************************************************* 339 * Lines API 340 ******************************************************************************/ 341 SHTR_API res_T 342 shtr_line_list_load 343 (struct shtr* shtr, 344 const struct shtr_line_list_load_args* args, 345 struct shtr_line_list** list); 346 347 /* Load the line list serialized with the "shtr_line_list_write" function */ 348 SHTR_API res_T 349 shtr_line_list_read 350 (struct shtr* shtr, 351 const struct shtr_line_list_read_args* args, 352 struct shtr_line_list** list); 353 354 SHTR_API res_T 355 shtr_line_list_ref_get 356 (struct shtr_line_list* list); 357 358 SHTR_API res_T 359 shtr_line_list_ref_put 360 (struct shtr_line_list* list); 361 362 SHTR_API res_T 363 shtr_line_list_get_size 364 (const struct shtr_line_list* list, 365 size_t* nlines); 366 367 SHTR_API res_T 368 shtr_line_list_at 369 (struct shtr_line_list* list, 370 const size_t i, 371 struct shtr_line* line); 372 373 SHTR_API res_T 374 shtr_line_list_write 375 (const struct shtr_line_list* list, 376 const struct shtr_line_list_write_args* args); 377 378 SHTR_API res_T 379 shtr_line_list_get_info 380 (const struct shtr_line_list* list, 381 struct shtr_line_list_info* info); 382 383 SHTR_API res_T 384 shtr_line_list_hash 385 (const struct shtr_line_list* list, 386 hash256_T hash); 387 388 END_DECLS 389 390 #endif /* SHTR_H */