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 (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 */