commit bd06ecca27908f0e4c2c0d97e571c3a33d617ecb
parent 0137c8983b0702bc42a1274518917f870f0c6d0a
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Mon, 14 Feb 2022 12:10:57 +0100
Start implementing transitions parsing
Diffstat:
3 files changed, 322 insertions(+), 3 deletions(-)
diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt
@@ -47,6 +47,7 @@ set(SHITRAN_FILES_SRC
shitran.c
shitran_log.c
shitran_isotope_metadata.c
+ shitran_transitions.c
shitran_param.c)
set(SHITRAN_FILES_INC
shitran_c.h
diff --git a/src/shitran.h b/src/shitran.h
@@ -76,9 +76,26 @@ static const struct shitran_molecule SHITRAN_MOLECULE_NULL =
#define SHITRAN_MOLECULE_IS_NULL(Molecule) \
((Molecule)->id == SHITRAN_MOLECULE_NULL.id)
-/* Forward declarations */
+struct shitran_transition {
+ float wavenumber; /* Central wavenumber in vacuum [cm^-1] */
+ float intensity; /* Reference intensity [cm^-1/(molec.cm^2)] */
+ float gamma_air; /* Air broadening half-width [cm^-1.atm^-1] */
+ float gamma_self; /* Self broadening half-width [cm^-1.atm^-1] */
+ float lower_state_energy; /* [cm^-1] */
+ float n_air; /* Temperature-dependant exponent */
+ float delta_air; /* Air-pressure wavenumber shift [cm^-1.atm^-1] */
+
+ int16_t molecule_id;
+ int16_t isotope_id_local;
+};
+#define SHITRAN_TRANSITION_NULL__ {0,0,0,0,0,0,0,-1,-1}
+static const struct shitran_transition SHITRAN_TRANSITION_NULL =
+ SHITRAN_TRANSITION_NULL__;
+
+/* Forward declarations of opaque data structures */
struct shitran;
struct shitran_isotope_metadata;
+struct shitran_transitions;
BEGIN_DECLS
@@ -135,16 +152,40 @@ shitran_isotope_metadata_get_isotopes_count
SHITRAN_API res_T
shitran_isotope_metadata_get_molecule
(const struct shitran_isotope_metadata* metadata,
- const size_t imolecule, /* Index of the molecule in [0, molecules_count[ */
+ const size_t imolecule, /* Local index of the molecule in [0, molecules_count[ */
struct shitran_molecule* molecule);
/* `molecule' is set to SHITRAN_MOLECULE_NULL if `molecule_id' is not found */
SHITRAN_API res_T
shitran_isotope_metadata_find_molecule
(struct shitran_isotope_metadata* metadata,
- const int molecule_id, /* Unique identifier of the molecule */
+ const int molecule_id, /* Unique identifier of the molecule <=> Global index */
struct shitran_molecule* molecule);
+/*******************************************************************************
+ * Transitions API
+ ******************************************************************************/
+SHITRAN_API res_T
+shitran_transitions_load
+ (struct shitran* shitran,
+ const char* path,
+ struct shitran_transitions** transitions);
+
+SHITRAN_API res_T
+shitran_transitions_load_stream
+ (struct shitran* shitran,
+ FILE* stream,
+ const char* stream_name, /* NULL <=> use default stream name */
+ struct shitran_transitions** transitions);
+
+SHITRAN_API res_T
+shitran_transitions_ref_get
+ (struct shitran_transitions* transitions);
+
+SHITRAN_API res_T
+shitran_transitions_ref_put
+ (struct shitran_transitions* transitions);
+
END_DECLS
#endif /* SHITRAN_H */
diff --git a/src/shitran_transitions.c b/src/shitran_transitions.c
@@ -0,0 +1,277 @@
+/* Copyright (C) 2022 CNRS - LMD
+ * Copyright (C) 2022 |Meso|Star> (contact@meso-star.com)
+ * Copyright (C) 2022 Université Paul Sabatier - IRIT
+ * Copyright (C) 2022 Université Paul Sabatier - Laplace
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef SHITRAN_TRANSITIONS_H
+#define SHITRAN_TRANSITIONS_H
+
+#include "shitran.h"
+#include "shitran_c.h"
+#include "shitran_log.h"
+#include "shitran_param.h"
+
+#include <rsys/cstr.h>
+#include <rsys/dynamic_array.h>
+#include <rsys/text_reader.h>
+
+/* Generate the dynamic array of transitions */
+#define DARRAY_NAME transition
+#define DARRAY_DATA struct shitran_transition
+#include <rsys/dynamic_array.h>
+
+struct shitran_transitions {
+ /* List of transitions */
+ struct darray_transition transitions;
+
+ struct shitran* shitran;
+ ref_T ref;
+};
+
+/*******************************************************************************
+ * Helper functions
+ ******************************************************************************/
+static res_T
+create_transitions
+ (struct shitran* shitran,
+ struct shitran_transitions** out_transitions)
+{
+ struct shitran_transitions* transitions = NULL;
+ res_T res = RES_OK;
+ ASSERT(shitran && out_transitions);
+
+ transitions = MEM_CALLOC(shitran->allocator, 1, sizeof(*transitions));
+ if(!transitions) {
+ log_err(shitran, "Could not allocate the transitions data structure.\n");
+ res = RES_MEM_ERR;
+ goto error;
+ }
+ ref_init(&transitions->ref);
+ SHITRAN(ref_get(shitran));
+ transitions->shitran = shitran;
+ darray_transition_init(shitran->allocator, &transitions->transitions);
+
+exit:
+ *out_transitions = transitions;
+ return res;
+error:
+ goto exit;
+}
+
+static res_T
+parse_transition(struct shitran_transitions* transitions, struct txtrdr* txtrdr)
+{
+ struct shitran_transition tr = SHITRAN_TRANSITION_NULL;
+ struct param_desc param = PARAM_DESC_NULL;
+ struct shitran* shitran = NULL;
+ char* line = NULL;
+ char* str = NULL;
+ char* end = NULL;
+ char backup;
+ int molecule_id;
+ int isotope_id_local;
+ res_T res = RES_OK;
+
+ ASSERT(transitions && txtrdr);
+
+ line = txtrdr_get_line(txtrdr);
+ ASSERT(line);
+
+ shitran = transitions->shitran;
+ param.path = txtrdr_get_name(txtrdr);
+ param.line = txtrdr_get_line_num(txtrdr);
+
+ str = end = line;
+ backup = str[0];
+ #define NEXT(Size) { \
+ *end = backup; \
+ str = end; \
+ end = str+(Size); \
+ backup = *end; \
+ *end = '\0'; \
+ } (void)0
+ #define PARSE(Var, Size, Type, Name, Low, Upp, LowIncl, UppIncl) { \
+ NEXT(Size); \
+ param.name = (Name); \
+ param.low = (Low); \
+ param.upp = (Upp); \
+ param.is_low_incl = (LowIncl); \
+ param.is_upp_incl = (UppIncl); \
+ res = parse_param_##Type(shitran, str, ¶m, Var); \
+ if(res != RES_OK) goto error; \
+ } (void)0
+
+ PARSE(&molecule_id, 2, int, "molecule identifier", 0,99,1,1);
+ tr.molecule_id = (int16_t)molecule_id;
+
+ PARSE(&isotope_id_local, 1, int, "isotope local identifier", 0,9,1,1);
+ tr.isotope_id_local = (int16_t)
+ (isotope_id_local == 0 ? 9 : (isotope_id_local - 1));
+
+ PARSE(&tr.wavenumber, 12, float, "central wavenumber", 0,INF,0,1);
+ PARSE(&tr.intensity, 10, float, "reference intensity", 0,INF,0,1);
+
+ NEXT(10); /* Skip the Enstein coef */
+
+ PARSE(&tr.gamma_air, 5, float, "air broadening half-width", 0,INF,0,1);
+ PARSE(&tr.gamma_self, 5, float, "self broadening half-width", 0,INF,0,1);
+ PARSE(&tr.lower_state_energy, 10, float, "lower state energy", 0,INF,0,1);
+ PARSE(&tr.n_air, 4, float, "temperature-dependent exponent", 0,INF,0,1);
+ PARSE(&tr.delta_air, 8, float, "air-pressure wavenumber shift", -INF,INF,1,1);
+
+ /* Skip the remaining values */
+
+ #undef NEXT
+ #undef PARSE
+
+ res = darray_transition_push_back(&transitions->transitions, &tr);
+ if(res != RES_OK) {
+ log_err(transitions->shitran,
+ "%s:%lu: error storing the transition -- %s.\n",
+ param.path, (unsigned long)param.line, res_to_cstr(res));
+ goto error;
+ }
+
+exit:
+ return res;
+error:
+ goto exit;
+}
+
+static res_T
+load_stream
+ (struct shitran* shitran,
+ FILE* stream,
+ const char* name,
+ struct shitran_transitions** out_transitions)
+{
+ struct shitran_transitions* transitions = NULL;
+ struct txtrdr* txtrdr = NULL;
+ res_T res = RES_OK;
+ ASSERT(shitran && stream && name && out_transitions);
+
+ res = create_transitions(shitran, &transitions);
+ if(res != RES_OK) goto error;
+
+ res = txtrdr_stream(transitions->shitran->allocator, stream, name,
+ 0/*No comment char*/, &txtrdr);
+ if(res != RES_OK) {
+ log_err(shitran, "%s: error creating the text reader -- %s.\n",
+ name, res_to_cstr(res));
+ goto error;
+ }
+
+ for(;;) {
+ res = txtrdr_read_line(txtrdr);
+ if(res != RES_OK) {
+ log_err(shitran, "%s: error reading the line `%lu' -- %s.\n",
+ name, (unsigned long)txtrdr_get_line_num(txtrdr), res_to_cstr(res));
+ goto error;
+ }
+
+ if(!txtrdr_get_cline(txtrdr)) break; /* No more parsed line */
+ res = parse_transition(transitions, txtrdr);
+ if(res != RES_OK) goto error;
+ }
+
+exit:
+ if(txtrdr) txtrdr_ref_put(txtrdr);
+ *out_transitions = transitions;
+ return res;
+error:
+ if(transitions) {
+ SHITRAN(transitions_ref_put(transitions));
+ transitions = NULL;
+ }
+ goto exit;
+}
+
+static void
+release_transitions(ref_T * ref)
+{
+ struct shitran* shitran = NULL;
+ struct shitran_transitions* transitions = CONTAINER_OF
+ (ref, struct shitran_transitions, ref);
+ ASSERT(ref);
+ shitran = transitions->shitran;
+ darray_transition_release(&transitions->transitions);
+ MEM_RM(shitran->allocator, transitions);
+ SHITRAN(ref_put(transitions->shitran));
+}
+
+/*******************************************************************************
+ * Exported functions
+ ******************************************************************************/
+res_T
+shitran_transitions_load
+ (struct shitran* shitran,
+ const char* path,
+ struct shitran_transitions** transitions)
+{
+ FILE* file = NULL;
+ res_T res = RES_OK;
+
+ if(!shitran || !path || !transitions) {
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ file = fopen(path, "r");
+ if(!file) {
+ log_err(shitran, "%s: error opening file `%s'.\n", FUNC_NAME, path);
+ res = RES_IO_ERR;
+ goto error;
+ }
+
+ res = load_stream(shitran, file, path, transitions);
+ if(res != RES_OK) goto error;
+
+exit:
+ if(file) fclose(file);
+ return res;
+error:
+ goto exit;
+}
+
+res_T
+shitran_transitions_load_stream
+ (struct shitran* shitran,
+ FILE* stream,
+ const char* stream_name,
+ struct shitran_transitions** transitions)
+{
+ if(!shitran || !stream || !transitions) return RES_BAD_ARG;
+ return load_stream
+ (shitran, stream, stream_name ? stream_name : "<stream>", transitions);
+}
+
+res_T
+shitran_transitions_ref_get(struct shitran_transitions* transitions)
+{
+ if(!transitions) return RES_BAD_ARG;
+ ref_get(&transitions->ref);
+ return RES_OK;
+}
+
+res_T
+shitran_transitions_ref_put(struct shitran_transitions* transitions)
+{
+ if(!transitions) return RES_BAD_ARG;
+ ref_put(&transitions->ref, release_transitions);
+ return RES_OK;
+}
+
+#endif /* SHITRAN_TRANSITIONS_H */