star-hitran

Load line-by-line data from the HITRAN database
git clone git://git.meso-star.fr/star-hitran.git
Log | Files | Refs | README | LICENSE

shtr.h (11449B)


      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/rsys.h>
     23 
     24 #include <float.h>
     25 #include <limits.h>
     26 
     27 /* Library symbol management */
     28 #if defined(SHTR_SHARED_BUILD)  /* Build shared library */
     29   #define SHTR_API extern EXPORT_SYM
     30 #elif defined(SHTR_STATIC)  /* Use/build static library */
     31   #define SHTR_API extern LOCAL_SYM
     32 #else
     33   #define SHTR_API extern IMPORT_SYM
     34 #endif
     35 
     36 /* Helper macro that asserts if the invocation of the shtr function `Func'
     37  * returns an error. One should use this macro on shtr function calls for which
     38  * no explicit error checking is performed */
     39 #ifndef NDEBUG
     40   #define SHTR(Func) ASSERT(shtr_ ## Func == RES_OK)
     41 #else
     42   #define SHTR(Func) shtr_ ## Func
     43 #endif
     44 
     45 /* List of HITRAN species. They are classified as in the HITRAN database ,i.e.
     46  * their value corresponds to that of HITRAN. Note that they start at 1 rather
     47  * than zero and therefore do not strictly correspond to a C array index */
     48 enum shtr_molecule_id {
     49   SHTR_MOLECULE_ID_NULL = 0,
     50 
     51   SHTR_H2O,    SHTR_CO2,    SHTR_O3,     SHTR_N2O,    SHTR_CO,     SHTR_CH4,
     52   SHTR_O2,     SHTR_NO,     SHTR_SO2,    SHTR_NO2,    SHTR_NH3,    SHTR_HNO3,
     53   SHTR_OH,     SHTR_HF,     SHTR_HCl,    SHTR_HBr,    SHTR_HI,     SHTR_ClO,
     54   SHTR_OCS,    SHTR_H2CO,   SHTR_HOCl,   SHTR_N2,     SHTR_HCN,    SHTR_CH3Cl,
     55   SHTR_H2O2,   SHTR_C2H2,   SHTR_C2H6,   SHTR_PH3,    SHTR_COF2,   SHTR_SF6,
     56   SHTR_H2S,    SHTR_HCOOH,  SHTR_HO2,    SHTR_O,      SHTR_ClONO2, SHTR_NOplus,
     57   SHTR_HOBr,   SHTR_C2H4,   SHTR_CH3OH,  SHTR_CH3Br,  SHTR_CH3CN,  SHTR_CF4,
     58   SHTR_C4H2,   SHTR_HC3N,   SHTR_H2,     SHTR_CS,     SHTR_SO3,    SHTR_C2N2,
     59   SHTR_COCl2,  SHTR_SO,     SHTR_CH3F,   SHTR_GeH4,   SHTR_CS2,    SHTR_CH3I,
     60   SHTR_NF3,
     61 
     62   SHTR_MAX_MOLECULE_COUNT
     63 };
     64 
     65 /* Table that associates the molecule ID with its name */
     66 static const char* SHTR_MOLECULE_CSTR__[SHTR_MAX_MOLECULE_COUNT] = {
     67   NULL, /* SHTR_MOLECULE_ID_NULL__ */
     68 
     69   "H2O",    "CO2",    "O3",     "N2O",    "CO",     "CH4",
     70   "O2",     "NO",     "SO2",    "NO2",    "NH3",    "HNO3",
     71   "OH",     "HF",     "HCl",    "HBr",    "HI",     "ClO",
     72   "OCS",    "H2CO",   "HOCl",   "N2",     "HCN",    "CH3Cl",
     73   "H2O2",   "C2H2",   "C2H6",   "PH3",    "COF2",   "SF6",
     74   "H2S",    "HCOOH",  "HO2",    "O",      "ClONO2", "NO+",
     75   "HOBr",   "C2H4",   "CH3OH",  "CH3Br",  "CH3CN",  "CF4",
     76   "C4H2",   "HC3N",   "H2",     "CS",     "SO3",    "C2N2",
     77   "COCl2",  "SO",     "CH3F",   "GeH4",   "CS2",    "CH3I",
     78   "NF3"
     79 };
     80 
     81 static INLINE const char*
     82 shtr_molecule_cstr(const enum shtr_molecule_id id)
     83 {
     84   ASSERT(id < SHTR_MAX_MOLECULE_COUNT);
     85   return SHTR_MOLECULE_CSTR__[id];
     86 }
     87 
     88 struct shtr_isotope {
     89   double abundance; /* in ]0, 1] */
     90   double Q296K; /* Partition function at Tref = 296K */
     91   double molar_mass; /* In g.mol^-1 */
     92 
     93   /* Local idx of the molecule to which the isotope belongs */
     94   size_t molecule_id_local;
     95 
     96   int gj; /* State independent degeneracy factor */
     97   int id; /* Identifier of the isotope <=> Global index */
     98 };
     99 #define SHTR_ISOTOPE_NULL__ {0,0,0,0,0,-1}
    100 static const struct shtr_isotope SHTR_ISOTOPE_NULL =
    101   SHTR_ISOTOPE_NULL__;
    102 
    103 struct shtr_molecule {
    104   const char* name;
    105   size_t nisotopes; /* Number of isotopes */
    106   const struct shtr_isotope* isotopes;
    107   enum shtr_molecule_id id; /* Unique identifier */
    108 };
    109 #define SHTR_MOLECULE_NULL__ {NULL, 0, NULL, SHTR_MOLECULE_ID_NULL}
    110 static const struct shtr_molecule SHTR_MOLECULE_NULL =
    111   SHTR_MOLECULE_NULL__;
    112 
    113 #define SHTR_MOLECULE_IS_NULL(Molecule) \
    114   ((Molecule)->id == SHTR_MOLECULE_NULL.id)
    115 
    116 struct shtr_line {
    117   double wavenumber; /* Central wavenumber in vacuum [cm^-1] */
    118   double intensity; /* Reference intensity [cm^-1/(molec.cm^2)] */
    119   double gamma_air; /* Air broadening half-width [cm^-1.atm^-1] */
    120   double gamma_self; /* Self broadening half-width [cm^-1.atm^-1] */
    121   double lower_state_energy; /* [cm^-1] */
    122   double n_air; /* Temperature-dependant exponent */
    123   double delta_air; /* Air-pressure wavenumber shift [cm^-1.atm^-1] */
    124 
    125   enum shtr_molecule_id molecule_id;
    126 
    127   /* The value of the following isotopic index is _not_ the value of the
    128    * isotopic index read from the HITRAN file. The original value is in [0, 9]
    129    * with 0 actually meaning 10. Thus, once decoded, the index is located in
    130    * [1, 10]. The next member variable simply stores this index but decremented
    131    * by one in order to make it compatible with C indexing. As a result, it
    132    * can be used directly to index the 'isotopes' array of a 'shtr_molecule'
    133    * data structure loaded from an isotope metadata file */
    134   int32_t isotope_id_local;
    135 };
    136 #define SHTR_LINE_NULL__ {0,0,0,0,0,0,0,-1,-1}
    137 static const struct shtr_line SHTR_LINE_NULL = SHTR_LINE_NULL__;
    138 
    139 static INLINE int
    140 shtr_line_eq(const struct shtr_line* line0, const struct shtr_line* line1)
    141 {
    142   ASSERT(line0 && line1);
    143   return line0->wavenumber == line1->wavenumber
    144       && line0->intensity == line1->intensity
    145       && line0->gamma_air == line1->gamma_air
    146       && line0->gamma_self == line1->gamma_self
    147       && line0->lower_state_energy == line1->lower_state_energy
    148       && line0->n_air == line1->n_air
    149       && line0->delta_air == line1->delta_air
    150       && line0->molecule_id == line1->molecule_id
    151       && line0->isotope_id_local == line1->isotope_id_local;
    152 }
    153 
    154 struct shtr_line_param_info {
    155   double range[2];
    156   double err; /* Encoding error */
    157 };
    158 #define SHTR_LINE_PARAM_INFO_NULL__ {{DBL_MAX,-DBL_MAX}, 0}
    159 static const struct shtr_line_param_info SHTR_LINE_PARAM_INFO_NULL =
    160   SHTR_LINE_PARAM_INFO_NULL__;
    161 
    162 /* Information on a list of lines */
    163 struct shtr_line_list_info {
    164   struct shtr_line_param_info wavenumber;
    165   struct shtr_line_param_info intensity;
    166   struct shtr_line_param_info gamma_air;
    167   struct shtr_line_param_info gamma_self;
    168   struct shtr_line_param_info lower_state_energy;
    169   struct shtr_line_param_info n_air;
    170   struct shtr_line_param_info delta_air;
    171 };
    172 #define SHTR_LINE_LIST_INFO_NULL__ { \
    173   SHTR_LINE_PARAM_INFO_NULL__, \
    174   SHTR_LINE_PARAM_INFO_NULL__, \
    175   SHTR_LINE_PARAM_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 }
    181 static const struct shtr_line_list_info SHTR_LINE_LIST_INFO_NULL =
    182   SHTR_LINE_LIST_INFO_NULL__;
    183 
    184 /* Forward declarations of opaque data structures */
    185 struct shtr;
    186 struct shtr_isotope_metadata;
    187 struct shtr_line_list;
    188 struct shtr_line_view;
    189 
    190 /*******************************************************************************
    191  * Input arguments for API functions
    192  ******************************************************************************/
    193 struct shtr_create_args {
    194   struct logger* logger; /* May be NULL <=> default logger */
    195   struct mem_allocator* allocator; /* NULL <=> use default allocator */
    196   int verbose; /* Verbosity level */
    197 };
    198 #define SHTR_CREATE_ARGS_DEFAULT__ {NULL, NULL, 0}
    199 static const struct shtr_create_args SHTR_CREATE_ARGS_DEFAULT =
    200   SHTR_CREATE_ARGS_DEFAULT__;
    201 
    202 struct shtr_line_list_load_args {
    203   const char* filename; /* Name of the file to load or of the provided stream */
    204   FILE* file; /* Stream from where data are loaded. NULL <=> load from file */
    205 };
    206 #define SHTR_LINE_LIST_LOAD_ARGS_NULL__ {NULL, NULL}
    207 static const struct shtr_line_list_load_args SHTR_LINE_LIST_LOAD_ARGS_NULL =
    208   SHTR_LINE_LIST_LOAD_ARGS_NULL__;
    209 
    210 BEGIN_DECLS
    211 
    212 /*******************************************************************************
    213  * Device API
    214  ******************************************************************************/
    215 SHTR_API res_T
    216 shtr_create
    217   (const struct shtr_create_args* args,
    218    struct shtr** shtr);
    219 
    220 SHTR_API res_T
    221 shtr_ref_get
    222   (struct shtr* shtr);
    223 
    224 SHTR_API res_T
    225 shtr_ref_put
    226   (struct shtr* shtr);
    227 
    228 /*******************************************************************************
    229  * Isotope metadata API
    230  ******************************************************************************/
    231 SHTR_API res_T
    232 shtr_isotope_metadata_load
    233   (struct shtr* shtr,
    234    const char* path,
    235    struct shtr_isotope_metadata** metadata);
    236 
    237 SHTR_API res_T
    238 shtr_isotope_metadata_load_stream
    239   (struct shtr* shtr,
    240    FILE* stream,
    241    const char* stream_name, /* NULL <=> use default stream name */
    242    struct shtr_isotope_metadata** metadata);
    243 
    244 /* Load the isotope metadata serialized with the "shtr_isotope_metadata_write"
    245  * function */
    246 SHTR_API res_T
    247 shtr_isotope_metadata_create_from_stream
    248   (struct shtr* shtr,
    249    FILE* stream,
    250    struct shtr_isotope_metadata** metadata);
    251 
    252 SHTR_API res_T
    253 shtr_isotope_metadata_ref_get
    254   (struct shtr_isotope_metadata* metadata);
    255 
    256 SHTR_API res_T
    257 shtr_isotope_metadata_ref_put
    258   (struct shtr_isotope_metadata* metadata);
    259 
    260 SHTR_API res_T
    261 shtr_isotope_metadata_get_molecules_count
    262   (const struct shtr_isotope_metadata* metadata,
    263    size_t* nmolecules);
    264 
    265 SHTR_API res_T
    266 shtr_isotope_metadata_get_isotopes_count
    267   (const struct shtr_isotope_metadata* metadata,
    268    size_t* nisotopes);
    269 
    270 SHTR_API res_T
    271 shtr_isotope_metadata_get_molecule
    272   (const struct shtr_isotope_metadata* metadata,
    273    const size_t imolecule, /* Local index of the molecule in [0, molecules_count[ */
    274    struct shtr_molecule* molecule);
    275 
    276 /* `molecule' is set to SHTR_MOLECULE_NULL if `molecule_id' is not found */
    277 SHTR_API res_T
    278 shtr_isotope_metadata_find_molecule
    279   (struct shtr_isotope_metadata* metadata,
    280    const int molecule_id, /* Unique identifier of the molecule <=> Global index */
    281    struct shtr_molecule* molecule);
    282 
    283 SHTR_API res_T
    284 shtr_isotope_metadata_write
    285   (const struct shtr_isotope_metadata* metadata,
    286    FILE* stream);
    287 
    288 /*******************************************************************************
    289  * Lines API
    290  ******************************************************************************/
    291 SHTR_API res_T
    292 shtr_line_list_load
    293   (struct shtr* shtr,
    294    const struct shtr_line_list_load_args* args,
    295    struct shtr_line_list** list);
    296 
    297 /* Load the line list serialized with the "shtr_line_list_write" function */
    298 SHTR_API res_T
    299 shtr_line_list_create_from_stream
    300   (struct shtr* shtr,
    301    FILE* stream,
    302    struct shtr_line_list** list);
    303 
    304 SHTR_API res_T
    305 shtr_line_list_ref_get
    306    (struct shtr_line_list* list);
    307 
    308 SHTR_API res_T
    309 shtr_line_list_ref_put
    310    (struct shtr_line_list* list);
    311 
    312 SHTR_API res_T
    313 shtr_line_list_get_size
    314   (const struct shtr_line_list* list,
    315    size_t* nlines);
    316 
    317 SHTR_API res_T
    318 shtr_line_list_at
    319   (struct shtr_line_list* list,
    320    const size_t i,
    321    struct shtr_line* line);
    322 
    323 SHTR_API res_T
    324 shtr_line_list_write
    325   (const struct shtr_line_list* list,
    326    FILE* stream);
    327 
    328 SHTR_API res_T
    329 shtr_line_list_get_info
    330   (const struct shtr_line_list* list,
    331    struct shtr_line_list_info* info);
    332 
    333 END_DECLS
    334 
    335 #endif /* SHTR_H */