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

commit 3a7aba76b8d9036d1e848d83ce7afe5b858f0f95
parent 57c2521bcea370515cbdc686ea17d6ff2d2914ea
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Mon, 23 May 2022 14:53:39 +0200

Rename shtr_lines_<list|view> in shtr_line_<list|view>

Diffstat:
Mcmake/CMakeLists.txt | 6+++---
Msrc/shtr.h | 82++++++++++++++++++++++++++++++++++++++++----------------------------------------
Asrc/shtr_line_list.c | 420+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/shtr_line_list_c.h | 44++++++++++++++++++++++++++++++++++++++++++++
Asrc/shtr_line_view.c | 409+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Dsrc/shtr_lines_list.c | 420-------------------------------------------------------------------------------
Dsrc/shtr_lines_list_c.h | 44--------------------------------------------
Dsrc/shtr_lines_view.c | 409-------------------------------------------------------------------------------
Msrc/test_shtr_lines.c | 290++++++++++++++++++++++++++++++++++++++++----------------------------------------
9 files changed, 1062 insertions(+), 1062 deletions(-)

diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt @@ -48,11 +48,11 @@ set(SHTR_FILES_SRC shtr_log.c shtr_isotope_metadata.c shtr_param.c - shtr_lines_list.c - shtr_lines_view.c) + shtr_line_list.c + shtr_line_view.c) set(SHTR_FILES_INC shtr_c.h - shtr_lines_list_c.h + shtr_line_list_c.h shtr_log.h shtr_param.h) set(SHTR_FILES_INC_API diff --git a/src/shtr.h b/src/shtr.h @@ -111,8 +111,8 @@ shtr_line_eq(const struct shtr_line* line0, const struct shtr_line* line1) /* Forward declarations of opaque data structures */ struct shtr; struct shtr_isotope_metadata; -struct shtr_lines_list; -struct shtr_lines_view; +struct shtr_line_list; +struct shtr_line_view; /******************************************************************************* * Input arguments for API functions @@ -139,7 +139,7 @@ struct shtr_isotope_selection { static const struct shtr_isotope_selection SHTR_ISOTOPE_SELECTION_NULL = SHTR_ISOTOPE_SELECTION_NULL__; -struct shtr_lines_view_create_args { +struct shtr_line_view_create_args { double wavenumber_range[2]; /* Spectral range */ /* List of molecule be selected */ @@ -148,11 +148,11 @@ struct shtr_lines_view_create_args { double pressure; /* In atm. Used to compute the line center */ }; -#define SHTR_LINES_VIEW_CREATE_ARGS_NULL__ \ +#define SHTR_LINE_VIEW_CREATE_ARGS_NULL__ \ {{0,0}, {SHTR_ISOTOPE_SELECTION_NULL__}, 0, 0} -static const struct shtr_lines_view_create_args -SHTR_LINES_VIEW_CREATE_ARGS_NULL = - SHTR_LINES_VIEW_CREATE_ARGS_NULL__; +static const struct shtr_line_view_create_args +SHTR_LINE_VIEW_CREATE_ARGS_NULL = + SHTR_LINE_VIEW_CREATE_ARGS_NULL__; BEGIN_DECLS @@ -236,86 +236,86 @@ shtr_isotope_metadata_write * Lines API ******************************************************************************/ SHTR_API res_T -shtr_lines_list_load +shtr_line_list_load (struct shtr* shtr, const char* path, - struct shtr_lines_list** list); + struct shtr_line_list** list); SHTR_API res_T -shtr_lines_list_load_stream +shtr_line_list_load_stream (struct shtr* shtr, FILE* stream, const char* stream_name, /* NULL <=> use default stream name */ - struct shtr_lines_list** list); + struct shtr_line_list** list); -/* Load the line list serialized with the "shtr_lines_list_write" function */ +/* Load the line list serialized with the "shtr_line_list_write" function */ SHTR_API res_T -shtr_lines_list_create_from_stream +shtr_line_list_create_from_stream (struct shtr* shtr, FILE* stream, - struct shtr_lines_list** list); + struct shtr_line_list** list); SHTR_API res_T -shtr_lines_list_ref_get - (struct shtr_lines_list* list); +shtr_line_list_ref_get + (struct shtr_line_list* list); SHTR_API res_T -shtr_lines_list_ref_put - (struct shtr_lines_list* list); +shtr_line_list_ref_put + (struct shtr_line_list* list); SHTR_API res_T -shtr_lines_list_get_size - (const struct shtr_lines_list* list, +shtr_line_list_get_size + (const struct shtr_line_list* list, size_t* nlines); SHTR_API res_T -shtr_lines_list_get - (const struct shtr_lines_list* list, +shtr_line_list_get + (const struct shtr_line_list* list, const struct shtr_line* lines[]); SHTR_API res_T -shtr_lines_list_write - (const struct shtr_lines_list* list, +shtr_line_list_write + (const struct shtr_line_list* list, FILE* stream); /******************************************************************************* * Lines view API ******************************************************************************/ SHTR_API res_T -shtr_lines_view_create - (struct shtr_lines_list* list, - const struct shtr_lines_view_create_args* args, - struct shtr_lines_view** view); +shtr_line_view_create + (struct shtr_line_list* list, + const struct shtr_line_view_create_args* args, + struct shtr_line_view** view); -/* Load the line list serialized with the "shtr_lines_view_write" function */ +/* Load the line list serialized with the "shtr_line_view_write" function */ SHTR_API res_T -shtr_lines_view_create_from_stream +shtr_line_view_create_from_stream (struct shtr* shtr, FILE* stream, - struct shtr_lines_view** view); + struct shtr_line_view** view); SHTR_API res_T -shtr_lines_view_ref_get - (struct shtr_lines_view* view); +shtr_line_view_ref_get + (struct shtr_line_view* view); SHTR_API res_T -shtr_lines_view_ref_put - (struct shtr_lines_view* view); +shtr_line_view_ref_put + (struct shtr_line_view* view); SHTR_API res_T -shtr_lines_view_get_size - (const struct shtr_lines_view* view, +shtr_line_view_get_size + (const struct shtr_line_view* view, size_t* nlines); SHTR_API res_T -shtr_lines_view_get_line - (const struct shtr_lines_view* view, +shtr_line_view_get_line + (const struct shtr_line_view* view, const size_t iline, const struct shtr_line** line); SHTR_API res_T -shtr_lines_view_write - (const struct shtr_lines_view* view, +shtr_line_view_write + (const struct shtr_line_view* view, FILE* stream); END_DECLS diff --git a/src/shtr_line_list.c b/src/shtr_line_list.c @@ -0,0 +1,420 @@ +/* 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/>. */ + +#include "shtr.h" +#include "shtr_c.h" +#include "shtr_line_list_c.h" +#include "shtr_log.h" +#include "shtr_param.h" + +#include <rsys/cstr.h> +#include <rsys/text_reader.h> + +/******************************************************************************* + * Helper functions + ******************************************************************************/ +static res_T +create_line_list(struct shtr* shtr, struct shtr_line_list** out_list) +{ + struct shtr_line_list* list = NULL; + res_T res = RES_OK; + ASSERT(shtr && out_list); + + list = MEM_CALLOC(shtr->allocator, 1, sizeof(*list)); + if(!list) { + log_err(shtr, "Could not allocate the list of lines.\n"); + res = RES_MEM_ERR; + goto error; + } + ref_init(&list->ref); + SHTR(ref_get(shtr)); + list->shtr = shtr; + darray_line_init(shtr->allocator, &list->lines); + +exit: + *out_list = list; + return res; +error: + if(list) { + SHTR(line_list_ref_put(list)); + list = NULL; + } + goto exit; +} + +static res_T +parse_line(struct shtr_line_list* list, struct txtrdr* txtrdr) +{ + struct shtr_line ln = SHTR_LINE_NULL; + struct param_desc param = PARAM_DESC_NULL; + struct shtr* shtr = 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(list && txtrdr); + + line = txtrdr_get_line(txtrdr); + ASSERT(line); + + shtr = list->shtr; + 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(shtr, str, &param, Var); \ + if(res != RES_OK) goto error; \ + } (void)0 + + PARSE(&molecule_id, 2, int, "molecule identifier", 0,99,1,1); + ln.molecule_id = (int32_t)molecule_id; + + PARSE(&isotope_id_local, 1, int, "isotope local identifier", 0,9,1,1); + ln.isotope_id_local = (int32_t) + (isotope_id_local == 0 ? 9 : (isotope_id_local - 1)); + + PARSE(&ln.wavenumber, 12, double, "central wavenumber", 0,INF,0,1); + PARSE(&ln.intensity, 10, double, "reference intensity", 0,INF,0,1); + + NEXT(10); /* Skip the Enstein coef */ + + PARSE(&ln.gamma_air, 5, double, "air broadening half-width", 0,INF,1,1); + PARSE(&ln.gamma_self, 5, double, "self broadening half-width", 0,INF,1,1); + + /* Handle unavailable lower state energy */ + PARSE(&ln.lower_state_energy, 10, double, "lower state energy",-INF,INF,1,1); + if(ln.lower_state_energy == -1) { + log_warn(shtr, + "%s:%lu: the lower state energy is unavailable for this line, so it is " + "ignored.\n", txtrdr_get_name(txtrdr), txtrdr_get_line_num(txtrdr)); + goto exit; /* Skip the line */ + } + /* Check the domain validity */ + if(ln.lower_state_energy < 0) { + log_err(shtr, + "%s:%lu: invalid lower state energy %g. It must be in [0, INF].\n", + txtrdr_get_name(txtrdr), txtrdr_get_line_num(txtrdr), + ln.lower_state_energy); + res = RES_BAD_ARG; + goto error; + } + + PARSE(&ln.n_air, 4, double, "temperature-dependent exponent",-INF,INF,1,1); + PARSE(&ln.delta_air, 8, double, "air-pressure wavenumber shift", -INF,INF,1,1); + + /* Skip the remaining values */ + + #undef NEXT + #undef PARSE + + /* Check the size of the remaining data to ensure that there is at least the + * expected number of bytes wrt the HITRAN fileformat */ + *end = backup; + str = end; + if(strlen(str) != 93) { + log_err(list->shtr, "%s:%lu: missing data after delta air.\n", + param.path, (unsigned long)param.line); + res = RES_BAD_ARG; + goto error; + } + + if(darray_line_size_get(&list->lines)) { + const struct shtr_line* last_ln = darray_line_cdata_get(&list->lines) + + darray_line_size_get(&list->lines) - 1; + if(last_ln->wavenumber > ln.wavenumber) { + log_err(list->shtr, + "%s:%lu: lines are not sorted in ascending order wrt their wavenumber.\n", + txtrdr_get_name(txtrdr), txtrdr_get_line_num(txtrdr)); + res = RES_BAD_ARG; + goto error; + } + } + + res = darray_line_push_back(&list->lines, &ln); + if(res != RES_OK) { + log_err(list->shtr, + "%s:%lu: error storing the line -- %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 shtr* shtr, + FILE* stream, + const char* name, + struct shtr_line_list** out_lines) +{ + struct shtr_line_list* list = NULL; + struct txtrdr* txtrdr = NULL; + res_T res = RES_OK; + ASSERT(shtr && stream && name && out_lines); + + res = create_line_list(shtr, &list); + if(res != RES_OK) goto error; + + res = txtrdr_stream(list->shtr->allocator, stream, name, + 0/*No comment char*/, &txtrdr); + if(res != RES_OK) { + log_err(shtr, "%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(shtr, "%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_line(list, txtrdr); + if(res != RES_OK) goto error; + } + +exit: + if(txtrdr) txtrdr_ref_put(txtrdr); + *out_lines = list; + return res; +error: + if(list) { + SHTR(line_list_ref_put(list)); + list = NULL; + } + goto exit; +} + +static void +release_lines(ref_T * ref) +{ + struct shtr* shtr = NULL; + struct shtr_line_list* list = CONTAINER_OF + (ref, struct shtr_line_list, ref); + ASSERT(ref); + shtr = list->shtr; + darray_line_release(&list->lines); + MEM_RM(shtr->allocator, list); + SHTR(ref_put(shtr)); +} + +/******************************************************************************* + * Exported functions + ******************************************************************************/ +res_T +shtr_line_list_load + (struct shtr* shtr, + const char* path, + struct shtr_line_list** list) +{ + FILE* file = NULL; + res_T res = RES_OK; + + if(!shtr || !path || !list) { + res = RES_BAD_ARG; + goto error; + } + + file = fopen(path, "r"); + if(!file) { + log_err(shtr, "%s: error opening file `%s'.\n", FUNC_NAME, path); + res = RES_IO_ERR; + goto error; + } + + res = load_stream(shtr, file, path, list); + if(res != RES_OK) goto error; + +exit: + if(file) fclose(file); + return res; +error: + goto exit; +} + +res_T +shtr_line_list_load_stream + (struct shtr* shtr, + FILE* stream, + const char* stream_name, + struct shtr_line_list** list) +{ + if(!shtr || !stream || !list) return RES_BAD_ARG; + return load_stream + (shtr, stream, stream_name ? stream_name : "<stream>", list); +} + +res_T +shtr_line_list_create_from_stream + (struct shtr* shtr, + FILE* stream, + struct shtr_line_list** out_list) +{ + struct shtr_line_list* list = NULL; + size_t nlines; + int version = 0; + res_T res = RES_OK; + + if(!shtr || !out_list || !stream) { + res = RES_BAD_ARG; + goto error; + } + + res = create_line_list(shtr, &list); + if(res != RES_OK) goto error; + + #define READ(Var, Nb) { \ + if(fread((Var), sizeof(*(Var)), (Nb), stream) != (Nb)) { \ + if(feof(stream)) { \ + res = RES_BAD_ARG; \ + } else if(ferror(stream)) { \ + res = RES_IO_ERR; \ + } else { \ + res = RES_UNKNOWN_ERR; \ + } \ + log_err(shtr, "%s: error reading isotope metadata -- %s.\n", \ + FUNC_NAME, res_to_cstr(res)); \ + goto error; \ + } \ + } (void)0 + READ(&version, 1); + if(version != SHTR_LINE_LIST_VERSION) { + log_err(shtr, + "%s: unexpected line list version %d. " + "Expecting a line list in version %d.\n", + FUNC_NAME, version, SHTR_LINE_LIST_VERSION); + res = RES_BAD_ARG; + goto error; + } + + READ(&nlines, 1); + res = darray_line_resize(&list->lines, nlines); + if(res != RES_OK) { + log_err(shtr, "%s: error allocating the line list -- %s.\n", + FUNC_NAME, res_to_cstr(res)); + goto error; + } + + READ(darray_line_data_get(&list->lines), nlines); + #undef READ + +exit: + if(out_list) *out_list = list; + return res; +error: + if(list) { + SHTR(line_list_ref_put(list)); + list = NULL; + } + goto exit; +} + +res_T +shtr_line_list_ref_get(struct shtr_line_list* list) +{ + if(!list) return RES_BAD_ARG; + ref_get(&list->ref); + return RES_OK; +} + +res_T +shtr_line_list_ref_put(struct shtr_line_list* list) +{ + if(!list) return RES_BAD_ARG; + ref_put(&list->ref, release_lines); + return RES_OK; +} + +res_T +shtr_line_list_get_size + (const struct shtr_line_list* list, + size_t* nlines) +{ + if(!list || !nlines) return RES_BAD_ARG; + *nlines = darray_line_size_get(&list->lines); + return RES_OK; +} + +res_T +shtr_line_list_get + (const struct shtr_line_list* list, + const struct shtr_line* line_list[]) +{ + if(!list || !line_list) return RES_BAD_ARG; + *line_list = darray_line_cdata_get(&list->lines); + return RES_OK; +} + +res_T +shtr_line_list_write + (const struct shtr_line_list* list, + FILE* stream) +{ + size_t nlines = 0; + res_T res = RES_OK; + + if(!list || !stream) { + res = RES_BAD_ARG; + goto error; + } + + nlines = darray_line_size_get(&list->lines); + + #define WRITE(Var, Nb) { \ + if(fwrite((Var), sizeof(*(Var)), (Nb), stream) != (Nb)) { \ + log_err(list->shtr, "%s: error writing line list.\n", FUNC_NAME); \ + res = RES_IO_ERR; \ + goto error; \ + } \ + } (void)0 + WRITE(&SHTR_LINE_LIST_VERSION, 1); + WRITE(&nlines, 1); + WRITE(darray_line_cdata_get(&list->lines), nlines); + #undef WRITE + +exit: + return res; +error: + goto exit; +} diff --git a/src/shtr_line_list_c.h b/src/shtr_line_list_c.h @@ -0,0 +1,44 @@ +/* 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 SHTR_LINE_LIST_C_H +#define SHTR_LINE_LIST_C_H + +#include <rsys/dynamic_array.h> +#include <rsys/ref_count.h> + +/* Generate the dynamic array of lines */ +#define DARRAY_NAME line +#define DARRAY_DATA struct shtr_line +#include <rsys/dynamic_array.h> + +struct shtr; + +/* Version of the line list. One should increment it and perform a version + * management onto serialized data when the line list structure are updated. */ +static const int SHTR_LINE_LIST_VERSION = 0; + +struct shtr_line_list { + /* Lines sorted in ascending order wrt their wavenumber */ + struct darray_line lines; + + struct shtr* shtr; + ref_T ref; +}; + +#endif /* SHTR_LINE_LIST_C_H */ diff --git a/src/shtr_line_view.c b/src/shtr_line_view.c @@ -0,0 +1,409 @@ +/* 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/>. */ + +#define _POSIX_C_SOURCE 200112L /* nextafter */ + +#include "shtr.h" +#include "shtr_c.h" +#include "shtr_line_list_c.h" +#include "shtr_log.h" + +#include <rsys/cstr.h> +#include <rsys/dynamic_array_size_t.h> + +#include <math.h> + +/* Version of the line view. One should increment it and perform a version + * management onto serialized data when the line view structure are updated. */ +static const int SHTR_LINE_VIEW_VERSION = 0; + +struct shtr_line_view { + struct shtr_line_list* list; + struct darray_size_t line_ids; /* Indices of the selected lines */ + ref_T ref; +}; + +struct molecule_selection { + /* Map the isotope local identifier to a boolean defining if the isotope is + * selected or not */ + char isotopes[SHTR_MAX_ISOTOPES_COUNT]; + double cutoff; /* Molecule cutoff */ +}; + +/******************************************************************************* + * Helper functions + ******************************************************************************/ +static res_T +check_shtr_isotope_selection + (struct shtr* shtr, + const char* caller, + const struct shtr_isotope_selection* molecule) +{ + size_t i; + ASSERT(caller && molecule); + + if((size_t)molecule->id >= SHTR_MAX_MOLECULES_COUNT) { + log_err(shtr, + "%s: molecule %d: invalid molecule identifier. " + "It must be less than %d.\n", + caller, molecule->id, SHTR_MAX_MOLECULES_COUNT); + return RES_BAD_ARG; + } + + if(molecule->cutoff <= 0) { + log_err(shtr, "%s: molecule %d: invalid cutoff %g.\n", + caller, molecule->id, molecule->cutoff); + return RES_BAD_ARG; + } + + FOR_EACH(i, 0, molecule->nisotopes) { + if(molecule->isotope_ids_local[i] >= SHTR_MAX_ISOTOPES_COUNT) { + log_err(shtr, + "%s: molecule %d: isotope %d: invalid isotope local identifier. " + "It must be less than %d.\n", + caller, + molecule->id, + molecule->isotope_ids_local[i], + SHTR_MAX_ISOTOPES_COUNT); + return RES_BAD_ARG; + } + } + return RES_OK; +} + + +static res_T +check_shtr_line_view_create_args + (struct shtr* shtr, + const char* caller, + const struct shtr_line_view_create_args* args) +{ + size_t i; + ASSERT(caller); + + if(!args) return RES_BAD_ARG; + + if(args->wavenumber_range[0] > args->wavenumber_range[1]) { + log_err(shtr, "%s: invalid line view spectral range [%g, %g].\n", + caller, args->wavenumber_range[0], args->wavenumber_range[1]); + return RES_BAD_ARG; + } + + if(args->pressure < 0) { + log_err(shtr, "%s: invalid pressure %g.\n", caller, args->pressure); + return RES_BAD_ARG; + } + + FOR_EACH(i, 0, args->nmolecules) { + const res_T res = check_shtr_isotope_selection + (shtr, caller, &args->molecules[i]); + if(res != RES_OK) return res; + + } + return RES_OK; +} + +static res_T +create_line_view(struct shtr* shtr, struct shtr_line_view** out_view) +{ + struct shtr_line_view* view = NULL; + res_T res = RES_OK; + ASSERT(shtr && out_view); + + view = MEM_CALLOC(shtr->allocator, 1, sizeof(*view)); + if(!view) { + log_err(shtr, "Could not allocate the line view.\n"); + res = RES_MEM_ERR; + goto error; + } + ref_init(&view->ref); + darray_size_t_init(shtr->allocator, &view->line_ids); + +exit: + *out_view = view; + return res; +error: + if(view) { + SHTR(line_view_ref_put(view)); + view = NULL; + } + goto exit; +} + +static res_T +select_lines + (struct shtr_line_view* view, + const char* caller, + const struct shtr_line_view_create_args* args) +{ + const struct shtr_line* lines; + struct molecule_selection selection[SHTR_MAX_MOLECULES_COUNT]; + size_t imol; + size_t iiso; + size_t iline; + size_t nlines; + res_T res = RES_OK; + ASSERT(view && caller && args); + + /* Nothing to do */ + if(args->nmolecules == 0) goto exit; + + /* Setup the selection lookup table that map the isotope of a molecule to a + * boolean defining if it is selected */ + memset(selection, 0, sizeof(selection)); + FOR_EACH(imol, 0, args->nmolecules) { + const int32_t mol_id = args->molecules[imol].id; + ASSERT(mol_id < SHTR_MAX_MOLECULES_COUNT); + selection[mol_id].cutoff = args->molecules[imol].cutoff; + + if(args->molecules[imol].nisotopes == 0) { /* Select all isotopes */ + FOR_EACH(iiso, 0, SHTR_MAX_ISOTOPES_COUNT) { + selection[mol_id].isotopes[iiso] = 1; + } + + } else { + FOR_EACH(iiso, 0, args->molecules[imol].nisotopes) { + const int32_t iso_id = args->molecules[imol].isotope_ids_local[iiso]; + ASSERT(iso_id < SHTR_MAX_ISOTOPES_COUNT); + selection[mol_id].isotopes[iso_id] = 1; + } + } + } + + lines = darray_line_cdata_get(&view->list->lines); + nlines = darray_line_size_get(&view->list->lines); + + /* Iterate through list of lines to find the ones to select based on spectral + * range and isotope selection */ + FOR_EACH(iline, 0, nlines) { + const struct shtr_line* line = lines + iline; + double nu = 0; + + /* The line is not selected */ + if(selection[line->molecule_id].isotopes[line->isotope_id_local] == 0) { + continue; + } + + /* Compute the line center for the submitted pressure */ + nu = line->wavenumber + line->delta_air * args->pressure; + + /* The line is out of the spectral range */ + if(nu + selection[line->molecule_id].cutoff < args->wavenumber_range[0] + || nu - selection[line->molecule_id].cutoff > args->wavenumber_range[1]) { + continue; + } + + res = darray_size_t_push_back(&view->line_ids, &iline); + if(res != RES_OK) { + log_err(view->list->shtr, + "%s: could not register the line into the view -- %s.\n", + caller, res_to_cstr(res)); + goto error; + } + } + +exit: + return res; +error: + darray_size_t_clear(&view->line_ids); + goto exit; +} + +static void +release_line_view(ref_T* ref) +{ + struct shtr_line_view* view = CONTAINER_OF(ref, struct shtr_line_view, ref); + struct shtr_line_list* list = view->list; + ASSERT(ref); + darray_size_t_release(&view->line_ids); + MEM_RM(list->shtr->allocator, view); + SHTR(line_list_ref_put(list)); +} + +/******************************************************************************* + * Exported functions + ******************************************************************************/ +res_T +shtr_line_view_create + (struct shtr_line_list* list, + const struct shtr_line_view_create_args* args, + struct shtr_line_view** out_view) +{ + struct shtr_line_view* view = NULL; + res_T res = RES_OK; + + if(!list || !out_view) { res = RES_BAD_ARG; goto error; } + + res = check_shtr_line_view_create_args(list->shtr, FUNC_NAME, args); + if(res != RES_OK) goto error; + + res = create_line_view(list->shtr, &view); + if(res != RES_OK) goto error; + SHTR(line_list_ref_get(list)); + view->list = list; + + res = select_lines(view, FUNC_NAME, args); + if(res != RES_OK) goto error; + +exit: + if(out_view) *out_view = view; + return res; +error: + if(view) { SHTR(line_view_ref_put(view)); view = NULL; } + goto exit; +} + +res_T +shtr_line_view_create_from_stream + (struct shtr* shtr, + FILE* stream, + struct shtr_line_view** out_view) +{ + struct shtr_line_view* view = NULL; + size_t nids; + int version; + res_T res = RES_OK; + + if(!shtr || !stream || !out_view) { res = RES_BAD_ARG; goto error; } + + res = create_line_view(shtr, &view); + if(res != RES_OK) goto error; + + #define READ(Var, Nb) { \ + if(fread((Var), sizeof(*(Var)), (Nb), stream) != (Nb)) { \ + if(feof(stream)) { \ + res = RES_BAD_ARG; \ + } else if(ferror(stream)) { \ + res = RES_IO_ERR; \ + } else { \ + res = RES_UNKNOWN_ERR; \ + } \ + log_err(shtr, "%s: error reading isotope metadata -- %s.\n", \ + FUNC_NAME, res_to_cstr(res)); \ + goto error; \ + } \ + } (void)0 + READ(&version, 1); + if(version != SHTR_LINE_VIEW_VERSION) { + log_err(shtr, + "%s: unexpected line view version %d. " + "Expecting a line view in version %d.\n", + FUNC_NAME, version, SHTR_LINE_VIEW_VERSION); + res = RES_BAD_ARG; + goto error; + } + + res = shtr_line_list_create_from_stream(shtr, stream, &view->list); + if(res != RES_OK) goto error; + + READ(&nids, 1); + res = darray_size_t_resize(&view->line_ids, nids); + if(res != RES_OK) { + log_err(shtr, "%s: error allocating the line view -- %s.\n", + FUNC_NAME, res_to_cstr(res)); + goto error; + } + + READ(darray_size_t_data_get(&view->line_ids), nids); + #undef READ + +exit: + if(out_view) *out_view = view; + return res; +error: + if(view) { + SHTR(line_view_ref_put(view)); + view = NULL; + } + goto exit; +} + +res_T +shtr_line_view_ref_get(struct shtr_line_view* view) +{ + if(!view) return RES_BAD_ARG; + ref_get(&view->ref); + return RES_OK; +} + +res_T +shtr_line_view_ref_put(struct shtr_line_view* view) +{ + if(!view) return RES_BAD_ARG; + ref_put(&view->ref, release_line_view); + return RES_OK; +} + +res_T +shtr_line_view_get_size(const struct shtr_line_view* view, size_t* sz) +{ + if(!view || !sz) return RES_BAD_ARG; + *sz = darray_size_t_size_get(&view->line_ids); + return RES_OK; +} + +res_T +shtr_line_view_get_line + (const struct shtr_line_view* view, + const size_t iline, + const struct shtr_line** line) +{ + size_t i; + if(!view || !line || iline >= darray_size_t_size_get(&view->line_ids)) { + return RES_BAD_ARG; + } + i = darray_size_t_cdata_get(&view->line_ids)[iline]; + *line = darray_line_cdata_get(&view->list->lines) + i; + return RES_OK; +} + +res_T +shtr_line_view_write + (const struct shtr_line_view* view, + FILE* stream) +{ + size_t nids = 0; + res_T res = RES_OK; + + if(!view || !stream) { + res = RES_BAD_ARG; + goto error; + } + + #define WRITE(Var, Nb) { \ + if(fwrite((Var), sizeof(*(Var)), (Nb), stream) != (Nb)) { \ + log_err(view->list->shtr, "%s: error writing line view.\n", FUNC_NAME); \ + res = RES_IO_ERR; \ + goto error; \ + } \ + } (void)0 + WRITE(&SHTR_LINE_VIEW_VERSION, 1); + + res = shtr_line_list_write(view->list, stream); + if(res != RES_OK) goto error; + + nids = darray_size_t_size_get(&view->line_ids); + WRITE(&nids, 1); + WRITE(darray_size_t_cdata_get(&view->line_ids), nids); + #undef WRITE + +exit: + return res; +error: + goto exit; +} diff --git a/src/shtr_lines_list.c b/src/shtr_lines_list.c @@ -1,420 +0,0 @@ -/* 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/>. */ - -#include "shtr.h" -#include "shtr_c.h" -#include "shtr_lines_list_c.h" -#include "shtr_log.h" -#include "shtr_param.h" - -#include <rsys/cstr.h> -#include <rsys/text_reader.h> - -/******************************************************************************* - * Helper functions - ******************************************************************************/ -static res_T -create_lines_list(struct shtr* shtr, struct shtr_lines_list** out_list) -{ - struct shtr_lines_list* list = NULL; - res_T res = RES_OK; - ASSERT(shtr && out_list); - - list = MEM_CALLOC(shtr->allocator, 1, sizeof(*list)); - if(!list) { - log_err(shtr, "Could not allocate the list of lines.\n"); - res = RES_MEM_ERR; - goto error; - } - ref_init(&list->ref); - SHTR(ref_get(shtr)); - list->shtr = shtr; - darray_line_init(shtr->allocator, &list->lines); - -exit: - *out_list = list; - return res; -error: - if(list) { - SHTR(lines_list_ref_put(list)); - list = NULL; - } - goto exit; -} - -static res_T -parse_line(struct shtr_lines_list* list, struct txtrdr* txtrdr) -{ - struct shtr_line ln = SHTR_LINE_NULL; - struct param_desc param = PARAM_DESC_NULL; - struct shtr* shtr = 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(list && txtrdr); - - line = txtrdr_get_line(txtrdr); - ASSERT(line); - - shtr = list->shtr; - 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(shtr, str, &param, Var); \ - if(res != RES_OK) goto error; \ - } (void)0 - - PARSE(&molecule_id, 2, int, "molecule identifier", 0,99,1,1); - ln.molecule_id = (int32_t)molecule_id; - - PARSE(&isotope_id_local, 1, int, "isotope local identifier", 0,9,1,1); - ln.isotope_id_local = (int32_t) - (isotope_id_local == 0 ? 9 : (isotope_id_local - 1)); - - PARSE(&ln.wavenumber, 12, double, "central wavenumber", 0,INF,0,1); - PARSE(&ln.intensity, 10, double, "reference intensity", 0,INF,0,1); - - NEXT(10); /* Skip the Enstein coef */ - - PARSE(&ln.gamma_air, 5, double, "air broadening half-width", 0,INF,1,1); - PARSE(&ln.gamma_self, 5, double, "self broadening half-width", 0,INF,1,1); - - /* Handle unavailable lower state energy */ - PARSE(&ln.lower_state_energy, 10, double, "lower state energy",-INF,INF,1,1); - if(ln.lower_state_energy == -1) { - log_warn(shtr, - "%s:%lu: the lower state energy is unavailable for this line, so it is " - "ignored.\n", txtrdr_get_name(txtrdr), txtrdr_get_line_num(txtrdr)); - goto exit; /* Skip the line */ - } - /* Check the domain validity */ - if(ln.lower_state_energy < 0) { - log_err(shtr, - "%s:%lu: invalid lower state energy %g. It must be in [0, INF].\n", - txtrdr_get_name(txtrdr), txtrdr_get_line_num(txtrdr), - ln.lower_state_energy); - res = RES_BAD_ARG; - goto error; - } - - PARSE(&ln.n_air, 4, double, "temperature-dependent exponent",-INF,INF,1,1); - PARSE(&ln.delta_air, 8, double, "air-pressure wavenumber shift", -INF,INF,1,1); - - /* Skip the remaining values */ - - #undef NEXT - #undef PARSE - - /* Check the size of the remaining data to ensure that there is at least the - * expected number of bytes wrt the HITRAN fileformat */ - *end = backup; - str = end; - if(strlen(str) != 93) { - log_err(list->shtr, "%s:%lu: missing data after delta air.\n", - param.path, (unsigned long)param.line); - res = RES_BAD_ARG; - goto error; - } - - if(darray_line_size_get(&list->lines)) { - const struct shtr_line* last_ln = darray_line_cdata_get(&list->lines) - + darray_line_size_get(&list->lines) - 1; - if(last_ln->wavenumber > ln.wavenumber) { - log_err(list->shtr, - "%s:%lu: lines are not sorted in ascending order wrt their wavenumber.\n", - txtrdr_get_name(txtrdr), txtrdr_get_line_num(txtrdr)); - res = RES_BAD_ARG; - goto error; - } - } - - res = darray_line_push_back(&list->lines, &ln); - if(res != RES_OK) { - log_err(list->shtr, - "%s:%lu: error storing the line -- %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 shtr* shtr, - FILE* stream, - const char* name, - struct shtr_lines_list** out_lines) -{ - struct shtr_lines_list* list = NULL; - struct txtrdr* txtrdr = NULL; - res_T res = RES_OK; - ASSERT(shtr && stream && name && out_lines); - - res = create_lines_list(shtr, &list); - if(res != RES_OK) goto error; - - res = txtrdr_stream(list->shtr->allocator, stream, name, - 0/*No comment char*/, &txtrdr); - if(res != RES_OK) { - log_err(shtr, "%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(shtr, "%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_line(list, txtrdr); - if(res != RES_OK) goto error; - } - -exit: - if(txtrdr) txtrdr_ref_put(txtrdr); - *out_lines = list; - return res; -error: - if(list) { - SHTR(lines_list_ref_put(list)); - list = NULL; - } - goto exit; -} - -static void -release_lines(ref_T * ref) -{ - struct shtr* shtr = NULL; - struct shtr_lines_list* list = CONTAINER_OF - (ref, struct shtr_lines_list, ref); - ASSERT(ref); - shtr = list->shtr; - darray_line_release(&list->lines); - MEM_RM(shtr->allocator, list); - SHTR(ref_put(shtr)); -} - -/******************************************************************************* - * Exported functions - ******************************************************************************/ -res_T -shtr_lines_list_load - (struct shtr* shtr, - const char* path, - struct shtr_lines_list** list) -{ - FILE* file = NULL; - res_T res = RES_OK; - - if(!shtr || !path || !list) { - res = RES_BAD_ARG; - goto error; - } - - file = fopen(path, "r"); - if(!file) { - log_err(shtr, "%s: error opening file `%s'.\n", FUNC_NAME, path); - res = RES_IO_ERR; - goto error; - } - - res = load_stream(shtr, file, path, list); - if(res != RES_OK) goto error; - -exit: - if(file) fclose(file); - return res; -error: - goto exit; -} - -res_T -shtr_lines_list_load_stream - (struct shtr* shtr, - FILE* stream, - const char* stream_name, - struct shtr_lines_list** list) -{ - if(!shtr || !stream || !list) return RES_BAD_ARG; - return load_stream - (shtr, stream, stream_name ? stream_name : "<stream>", list); -} - -res_T -shtr_lines_list_create_from_stream - (struct shtr* shtr, - FILE* stream, - struct shtr_lines_list** out_list) -{ - struct shtr_lines_list* list = NULL; - size_t nlines; - int version = 0; - res_T res = RES_OK; - - if(!shtr || !out_list || !stream) { - res = RES_BAD_ARG; - goto error; - } - - res = create_lines_list(shtr, &list); - if(res != RES_OK) goto error; - - #define READ(Var, Nb) { \ - if(fread((Var), sizeof(*(Var)), (Nb), stream) != (Nb)) { \ - if(feof(stream)) { \ - res = RES_BAD_ARG; \ - } else if(ferror(stream)) { \ - res = RES_IO_ERR; \ - } else { \ - res = RES_UNKNOWN_ERR; \ - } \ - log_err(shtr, "%s: error reading isotope metadata -- %s.\n", \ - FUNC_NAME, res_to_cstr(res)); \ - goto error; \ - } \ - } (void)0 - READ(&version, 1); - if(version != SHTR_LINES_LIST_VERSION) { - log_err(shtr, - "%s: unexpected line list version %d. " - "Expecting a line list in version %d.\n", - FUNC_NAME, version, SHTR_LINES_LIST_VERSION); - res = RES_BAD_ARG; - goto error; - } - - READ(&nlines, 1); - res = darray_line_resize(&list->lines, nlines); - if(res != RES_OK) { - log_err(shtr, "%s: error allocating the line list -- %s.\n", - FUNC_NAME, res_to_cstr(res)); - goto error; - } - - READ(darray_line_data_get(&list->lines), nlines); - #undef READ - -exit: - if(out_list) *out_list = list; - return res; -error: - if(list) { - SHTR(lines_list_ref_put(list)); - list = NULL; - } - goto exit; -} - -res_T -shtr_lines_list_ref_get(struct shtr_lines_list* list) -{ - if(!list) return RES_BAD_ARG; - ref_get(&list->ref); - return RES_OK; -} - -res_T -shtr_lines_list_ref_put(struct shtr_lines_list* list) -{ - if(!list) return RES_BAD_ARG; - ref_put(&list->ref, release_lines); - return RES_OK; -} - -res_T -shtr_lines_list_get_size - (const struct shtr_lines_list* list, - size_t* nlines) -{ - if(!list || !nlines) return RES_BAD_ARG; - *nlines = darray_line_size_get(&list->lines); - return RES_OK; -} - -res_T -shtr_lines_list_get - (const struct shtr_lines_list* list, - const struct shtr_line* lines_list[]) -{ - if(!list || !lines_list) return RES_BAD_ARG; - *lines_list = darray_line_cdata_get(&list->lines); - return RES_OK; -} - -res_T -shtr_lines_list_write - (const struct shtr_lines_list* list, - FILE* stream) -{ - size_t nlines = 0; - res_T res = RES_OK; - - if(!list || !stream) { - res = RES_BAD_ARG; - goto error; - } - - nlines = darray_line_size_get(&list->lines); - - #define WRITE(Var, Nb) { \ - if(fwrite((Var), sizeof(*(Var)), (Nb), stream) != (Nb)) { \ - log_err(list->shtr, "%s: error writing line list.\n", FUNC_NAME); \ - res = RES_IO_ERR; \ - goto error; \ - } \ - } (void)0 - WRITE(&SHTR_LINES_LIST_VERSION, 1); - WRITE(&nlines, 1); - WRITE(darray_line_cdata_get(&list->lines), nlines); - #undef WRITE - -exit: - return res; -error: - goto exit; -} diff --git a/src/shtr_lines_list_c.h b/src/shtr_lines_list_c.h @@ -1,44 +0,0 @@ -/* 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 SHTR_LINES_LIST_C_H -#define SHTR_LINES_LIST_C_H - -#include <rsys/dynamic_array.h> -#include <rsys/ref_count.h> - -/* Generate the dynamic array of lines */ -#define DARRAY_NAME line -#define DARRAY_DATA struct shtr_line -#include <rsys/dynamic_array.h> - -struct shtr; - -/* Version of the line list. One should increment it and perform a version - * management onto serialized data when the line list structure are updated. */ -static const int SHTR_LINES_LIST_VERSION = 0; - -struct shtr_lines_list { - /* Lines sorted in ascending order wrt their wavenumber */ - struct darray_line lines; - - struct shtr* shtr; - ref_T ref; -}; - -#endif /* SHTR_LINES_LIST_C_H */ diff --git a/src/shtr_lines_view.c b/src/shtr_lines_view.c @@ -1,409 +0,0 @@ -/* 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/>. */ - -#define _POSIX_C_SOURCE 200112L /* nextafter */ - -#include "shtr.h" -#include "shtr_c.h" -#include "shtr_lines_list_c.h" -#include "shtr_log.h" - -#include <rsys/cstr.h> -#include <rsys/dynamic_array_size_t.h> - -#include <math.h> - -/* Version of the line view. One should increment it and perform a version - * management onto serialized data when the line view structure are updated. */ -static const int SHTR_LINES_VIEW_VERSION = 0; - -struct shtr_lines_view { - struct shtr_lines_list* list; - struct darray_size_t line_ids; /* Indices of the selected lines */ - ref_T ref; -}; - -struct molecule_selection { - /* Map the isotope local identifier to a boolean defining if the isotope is - * selected or not */ - char isotopes[SHTR_MAX_ISOTOPES_COUNT]; - double cutoff; /* Molecule cutoff */ -}; - -/******************************************************************************* - * Helper functions - ******************************************************************************/ -static res_T -check_shtr_isotope_selection - (struct shtr* shtr, - const char* caller, - const struct shtr_isotope_selection* molecule) -{ - size_t i; - ASSERT(caller && molecule); - - if((size_t)molecule->id >= SHTR_MAX_MOLECULES_COUNT) { - log_err(shtr, - "%s: molecule %d: invalid molecule identifier. " - "It must be less than %d.\n", - caller, molecule->id, SHTR_MAX_MOLECULES_COUNT); - return RES_BAD_ARG; - } - - if(molecule->cutoff <= 0) { - log_err(shtr, "%s: molecule %d: invalid cutoff %g.\n", - caller, molecule->id, molecule->cutoff); - return RES_BAD_ARG; - } - - FOR_EACH(i, 0, molecule->nisotopes) { - if(molecule->isotope_ids_local[i] >= SHTR_MAX_ISOTOPES_COUNT) { - log_err(shtr, - "%s: molecule %d: isotope %d: invalid isotope local identifier. " - "It must be less than %d.\n", - caller, - molecule->id, - molecule->isotope_ids_local[i], - SHTR_MAX_ISOTOPES_COUNT); - return RES_BAD_ARG; - } - } - return RES_OK; -} - - -static res_T -check_shtr_lines_view_create_args - (struct shtr* shtr, - const char* caller, - const struct shtr_lines_view_create_args* args) -{ - size_t i; - ASSERT(caller); - - if(!args) return RES_BAD_ARG; - - if(args->wavenumber_range[0] > args->wavenumber_range[1]) { - log_err(shtr, "%s: invalid lines view spectral range [%g, %g].\n", - caller, args->wavenumber_range[0], args->wavenumber_range[1]); - return RES_BAD_ARG; - } - - if(args->pressure < 0) { - log_err(shtr, "%s: invalid pressure %g.\n", caller, args->pressure); - return RES_BAD_ARG; - } - - FOR_EACH(i, 0, args->nmolecules) { - const res_T res = check_shtr_isotope_selection - (shtr, caller, &args->molecules[i]); - if(res != RES_OK) return res; - - } - return RES_OK; -} - -static res_T -create_lines_view(struct shtr* shtr, struct shtr_lines_view** out_view) -{ - struct shtr_lines_view* view = NULL; - res_T res = RES_OK; - ASSERT(shtr && out_view); - - view = MEM_CALLOC(shtr->allocator, 1, sizeof(*view)); - if(!view) { - log_err(shtr, "Could not allocate the line view.\n"); - res = RES_MEM_ERR; - goto error; - } - ref_init(&view->ref); - darray_size_t_init(shtr->allocator, &view->line_ids); - -exit: - *out_view = view; - return res; -error: - if(view) { - SHTR(lines_view_ref_put(view)); - view = NULL; - } - goto exit; -} - -static res_T -select_lines - (struct shtr_lines_view* view, - const char* caller, - const struct shtr_lines_view_create_args* args) -{ - const struct shtr_line* lines; - struct molecule_selection selection[SHTR_MAX_MOLECULES_COUNT]; - size_t imol; - size_t iiso; - size_t iline; - size_t nlines; - res_T res = RES_OK; - ASSERT(view && caller && args); - - /* Nothing to do */ - if(args->nmolecules == 0) goto exit; - - /* Setup the selection lookup table that map the isotope of a molecule to a - * boolean defining if it is selected */ - memset(selection, 0, sizeof(selection)); - FOR_EACH(imol, 0, args->nmolecules) { - const int32_t mol_id = args->molecules[imol].id; - ASSERT(mol_id < SHTR_MAX_MOLECULES_COUNT); - selection[mol_id].cutoff = args->molecules[imol].cutoff; - - if(args->molecules[imol].nisotopes == 0) { /* Select all isotopes */ - FOR_EACH(iiso, 0, SHTR_MAX_ISOTOPES_COUNT) { - selection[mol_id].isotopes[iiso] = 1; - } - - } else { - FOR_EACH(iiso, 0, args->molecules[imol].nisotopes) { - const int32_t iso_id = args->molecules[imol].isotope_ids_local[iiso]; - ASSERT(iso_id < SHTR_MAX_ISOTOPES_COUNT); - selection[mol_id].isotopes[iso_id] = 1; - } - } - } - - lines = darray_line_cdata_get(&view->list->lines); - nlines = darray_line_size_get(&view->list->lines); - - /* Iterate through list of lines to find the ones to select based on spectral - * range and isotope selection */ - FOR_EACH(iline, 0, nlines) { - const struct shtr_line* line = lines + iline; - double nu = 0; - - /* The line is not selected */ - if(selection[line->molecule_id].isotopes[line->isotope_id_local] == 0) { - continue; - } - - /* Compute the line center for the submitted pressure */ - nu = line->wavenumber + line->delta_air * args->pressure; - - /* The line is out of the spectral range */ - if(nu + selection[line->molecule_id].cutoff < args->wavenumber_range[0] - || nu - selection[line->molecule_id].cutoff > args->wavenumber_range[1]) { - continue; - } - - res = darray_size_t_push_back(&view->line_ids, &iline); - if(res != RES_OK) { - log_err(view->list->shtr, - "%s: could not register the line into the view -- %s.\n", - caller, res_to_cstr(res)); - goto error; - } - } - -exit: - return res; -error: - darray_size_t_clear(&view->line_ids); - goto exit; -} - -static void -release_lines_view(ref_T* ref) -{ - struct shtr_lines_view* view = CONTAINER_OF(ref, struct shtr_lines_view, ref); - struct shtr_lines_list* list = view->list; - ASSERT(ref); - darray_size_t_release(&view->line_ids); - MEM_RM(list->shtr->allocator, view); - SHTR(lines_list_ref_put(list)); -} - -/******************************************************************************* - * Exported functions - ******************************************************************************/ -res_T -shtr_lines_view_create - (struct shtr_lines_list* list, - const struct shtr_lines_view_create_args* args, - struct shtr_lines_view** out_view) -{ - struct shtr_lines_view* view = NULL; - res_T res = RES_OK; - - if(!list || !out_view) { res = RES_BAD_ARG; goto error; } - - res = check_shtr_lines_view_create_args(list->shtr, FUNC_NAME, args); - if(res != RES_OK) goto error; - - res = create_lines_view(list->shtr, &view); - if(res != RES_OK) goto error; - SHTR(lines_list_ref_get(list)); - view->list = list; - - res = select_lines(view, FUNC_NAME, args); - if(res != RES_OK) goto error; - -exit: - if(out_view) *out_view = view; - return res; -error: - if(view) { SHTR(lines_view_ref_put(view)); view = NULL; } - goto exit; -} - -res_T -shtr_lines_view_create_from_stream - (struct shtr* shtr, - FILE* stream, - struct shtr_lines_view** out_view) -{ - struct shtr_lines_view* view = NULL; - size_t nids; - int version; - res_T res = RES_OK; - - if(!shtr || !stream || !out_view) { res = RES_BAD_ARG; goto error; } - - res = create_lines_view(shtr, &view); - if(res != RES_OK) goto error; - - #define READ(Var, Nb) { \ - if(fread((Var), sizeof(*(Var)), (Nb), stream) != (Nb)) { \ - if(feof(stream)) { \ - res = RES_BAD_ARG; \ - } else if(ferror(stream)) { \ - res = RES_IO_ERR; \ - } else { \ - res = RES_UNKNOWN_ERR; \ - } \ - log_err(shtr, "%s: error reading isotope metadata -- %s.\n", \ - FUNC_NAME, res_to_cstr(res)); \ - goto error; \ - } \ - } (void)0 - READ(&version, 1); - if(version != SHTR_LINES_VIEW_VERSION) { - log_err(shtr, - "%s: unexpected line view version %d. " - "Expecting a line view in version %d.\n", - FUNC_NAME, version, SHTR_LINES_VIEW_VERSION); - res = RES_BAD_ARG; - goto error; - } - - res = shtr_lines_list_create_from_stream(shtr, stream, &view->list); - if(res != RES_OK) goto error; - - READ(&nids, 1); - res = darray_size_t_resize(&view->line_ids, nids); - if(res != RES_OK) { - log_err(shtr, "%s: error allocating the line view -- %s.\n", - FUNC_NAME, res_to_cstr(res)); - goto error; - } - - READ(darray_size_t_data_get(&view->line_ids), nids); - #undef READ - -exit: - if(out_view) *out_view = view; - return res; -error: - if(view) { - SHTR(lines_view_ref_put(view)); - view = NULL; - } - goto exit; -} - -res_T -shtr_lines_view_ref_get(struct shtr_lines_view* view) -{ - if(!view) return RES_BAD_ARG; - ref_get(&view->ref); - return RES_OK; -} - -res_T -shtr_lines_view_ref_put(struct shtr_lines_view* view) -{ - if(!view) return RES_BAD_ARG; - ref_put(&view->ref, release_lines_view); - return RES_OK; -} - -res_T -shtr_lines_view_get_size(const struct shtr_lines_view* view, size_t* sz) -{ - if(!view || !sz) return RES_BAD_ARG; - *sz = darray_size_t_size_get(&view->line_ids); - return RES_OK; -} - -res_T -shtr_lines_view_get_line - (const struct shtr_lines_view* view, - const size_t iline, - const struct shtr_line** line) -{ - size_t i; - if(!view || !line || iline >= darray_size_t_size_get(&view->line_ids)) { - return RES_BAD_ARG; - } - i = darray_size_t_cdata_get(&view->line_ids)[iline]; - *line = darray_line_cdata_get(&view->list->lines) + i; - return RES_OK; -} - -res_T -shtr_lines_view_write - (const struct shtr_lines_view* view, - FILE* stream) -{ - size_t nids = 0; - res_T res = RES_OK; - - if(!view || !stream) { - res = RES_BAD_ARG; - goto error; - } - - #define WRITE(Var, Nb) { \ - if(fwrite((Var), sizeof(*(Var)), (Nb), stream) != (Nb)) { \ - log_err(view->list->shtr, "%s: error writing line view.\n", FUNC_NAME); \ - res = RES_IO_ERR; \ - goto error; \ - } \ - } (void)0 - WRITE(&SHTR_LINES_VIEW_VERSION, 1); - - res = shtr_lines_list_write(view->list, stream); - if(res != RES_OK) goto error; - - nids = darray_size_t_size_get(&view->line_ids); - WRITE(&nids, 1); - WRITE(darray_size_t_cdata_get(&view->line_ids), nids); - #undef WRITE - -exit: - return res; -error: - goto exit; -} diff --git a/src/test_shtr_lines.c b/src/test_shtr_lines.c @@ -115,7 +115,7 @@ test_load(struct shtr* shtr) }; const size_t nlines = sizeof(l) / sizeof(struct shtr_line); - struct shtr_lines_list* list = NULL; + struct shtr_line_list* list = NULL; const struct shtr_line* lines = NULL; const char* filename = "test_lines.txt"; FILE* fp = NULL; @@ -125,57 +125,57 @@ test_load(struct shtr* shtr) print_lines(fp, l, nlines); rewind(fp); - CHK(shtr_lines_list_load_stream(NULL, fp, NULL, &list) == RES_BAD_ARG); - CHK(shtr_lines_list_load_stream(shtr, NULL, NULL, &list) == RES_BAD_ARG); - CHK(shtr_lines_list_load_stream(shtr, fp, NULL, NULL) == RES_BAD_ARG); - CHK(shtr_lines_list_load_stream(shtr, fp, NULL, &list) == RES_OK); + CHK(shtr_line_list_load_stream(NULL, fp, NULL, &list) == RES_BAD_ARG); + CHK(shtr_line_list_load_stream(shtr, NULL, NULL, &list) == RES_BAD_ARG); + CHK(shtr_line_list_load_stream(shtr, fp, NULL, NULL) == RES_BAD_ARG); + CHK(shtr_line_list_load_stream(shtr, fp, NULL, &list) == RES_OK); - CHK(shtr_lines_list_get_size(NULL, &n) == RES_BAD_ARG); - CHK(shtr_lines_list_get_size(list, NULL) == RES_BAD_ARG); - CHK(shtr_lines_list_get_size(list, &n) == RES_OK); + CHK(shtr_line_list_get_size(NULL, &n) == RES_BAD_ARG); + CHK(shtr_line_list_get_size(list, NULL) == RES_BAD_ARG); + CHK(shtr_line_list_get_size(list, &n) == RES_OK); CHK(n == nlines); - CHK(shtr_lines_list_get(NULL, &lines) == RES_BAD_ARG); - CHK(shtr_lines_list_get(list, NULL) == RES_BAD_ARG); - CHK(shtr_lines_list_get(list, &lines) == RES_OK); + CHK(shtr_line_list_get(NULL, &lines) == RES_BAD_ARG); + CHK(shtr_line_list_get(list, NULL) == RES_BAD_ARG); + CHK(shtr_line_list_get(list, &lines) == RES_OK); FOR_EACH(i, 0, n) CHK(shtr_line_eq(lines+i, l+i)); - CHK(shtr_lines_list_ref_get(NULL) == RES_BAD_ARG); - CHK(shtr_lines_list_ref_get(list) == RES_OK); - CHK(shtr_lines_list_ref_put(NULL) == RES_BAD_ARG); - CHK(shtr_lines_list_ref_put(list) == RES_OK); - CHK(shtr_lines_list_ref_put(list) == RES_OK); + CHK(shtr_line_list_ref_get(NULL) == RES_BAD_ARG); + CHK(shtr_line_list_ref_get(list) == RES_OK); + CHK(shtr_line_list_ref_put(NULL) == RES_BAD_ARG); + CHK(shtr_line_list_ref_put(list) == RES_OK); + CHK(shtr_line_list_ref_put(list) == RES_OK); CHK(fclose(fp) == 0); - CHK(shtr_lines_list_load(NULL, filename, &list) == RES_BAD_ARG); - CHK(shtr_lines_list_load(shtr, NULL, &list) == RES_BAD_ARG); - CHK(shtr_lines_list_load(shtr, filename, NULL) == RES_BAD_ARG); - CHK(shtr_lines_list_load(shtr, filename, &list) == RES_OK); + CHK(shtr_line_list_load(NULL, filename, &list) == RES_BAD_ARG); + CHK(shtr_line_list_load(shtr, NULL, &list) == RES_BAD_ARG); + CHK(shtr_line_list_load(shtr, filename, NULL) == RES_BAD_ARG); + CHK(shtr_line_list_load(shtr, filename, &list) == RES_OK); - CHK(shtr_lines_list_get_size(list, &n) == RES_OK); + CHK(shtr_line_list_get_size(list, &n) == RES_OK); CHK(n == nlines); - CHK(shtr_lines_list_get(list, &lines) == RES_OK); + CHK(shtr_line_list_get(list, &lines) == RES_OK); FOR_EACH(i, 0, n) CHK(shtr_line_eq(lines+i, l+i)); - CHK(shtr_lines_list_ref_put(list) == RES_OK); + CHK(shtr_line_list_ref_put(list) == RES_OK); } static void test_line (struct shtr* shtr, const struct shtr_line* ln, const res_T res) { - struct shtr_lines_list* list = NULL; + struct shtr_line_list* list = NULL; FILE* fp = NULL; CHK(fp = tmpfile()); print_lines(fp, ln, 1); rewind(fp); - CHK(shtr_lines_list_load_stream(shtr, fp, NULL, &list) == res); + CHK(shtr_line_list_load_stream(shtr, fp, NULL, &list) == res); CHK(fclose(fp) == 0); - if(res == RES_OK) CHK(shtr_lines_list_ref_put(list) == RES_OK); + if(res == RES_OK) CHK(shtr_line_list_ref_put(list) == RES_OK); } static void @@ -185,7 +185,7 @@ test_load_failures(struct shtr* shtr) 0.000134, 2.672E-38, 0.0533, 0.410, 608.4727, 0.79, 0.000060, 1, 4, }; struct shtr_line ln; - struct shtr_lines_list* list = NULL; + struct shtr_line_list* list = NULL; FILE* fp = NULL; /* Check that the reference line is valid */ @@ -232,14 +232,14 @@ test_load_failures(struct shtr* shtr) ln.wavenumber -= 1e-4; print_lines(fp, &ln, 1); rewind(fp); - CHK(shtr_lines_list_load_stream(shtr, fp, NULL, &list) == RES_BAD_ARG); + CHK(shtr_line_list_load_stream(shtr, fp, NULL, &list) == RES_BAD_ARG); CHK(fclose(fp) == 0); } static void -check_lines_list_equality - (const struct shtr_lines_list* list1, - const struct shtr_lines_list* list2) +check_line_list_equality + (const struct shtr_line_list* list1, + const struct shtr_line_list* list2) { const struct shtr_line* lines1 = NULL; const struct shtr_line* lines2 = NULL; @@ -247,13 +247,13 @@ check_lines_list_equality size_t iline, nlines; CHK(list1 && list2); - CHK(shtr_lines_list_get_size(list1, &n1) == RES_OK); - CHK(shtr_lines_list_get_size(list2, &n2) == RES_OK); + CHK(shtr_line_list_get_size(list1, &n1) == RES_OK); + CHK(shtr_line_list_get_size(list2, &n2) == RES_OK); CHK(n1 == n2); nlines = n1; - CHK(shtr_lines_list_get(list1, &lines1) == RES_OK); - CHK(shtr_lines_list_get(list2, &lines2) == RES_OK); + CHK(shtr_line_list_get(list1, &lines1) == RES_OK); + CHK(shtr_line_list_get(list2, &lines2) == RES_OK); FOR_EACH(iline, 0, nlines) { CHK(shtr_line_eq(lines1+iline, lines2+iline)); } @@ -271,48 +271,48 @@ test_serialization(struct shtr* shtr) }; const size_t nlines = sizeof(l) / sizeof(struct shtr_line); - struct shtr_lines_list* list1 = NULL; - struct shtr_lines_list* list2 = NULL; + struct shtr_line_list* list1 = NULL; + struct shtr_line_list* list2 = NULL; FILE* fp = NULL; CHK(fp = tmpfile()); print_lines(fp, l, nlines); rewind(fp); - CHK(shtr_lines_list_load_stream(shtr, fp, NULL, &list1) == RES_OK); + CHK(shtr_line_list_load_stream(shtr, fp, NULL, &list1) == RES_OK); fclose(fp); CHK(fp = tmpfile()); - CHK(shtr_lines_list_write(NULL, fp) == RES_BAD_ARG); - CHK(shtr_lines_list_write(list1, NULL) == RES_BAD_ARG); - CHK(shtr_lines_list_write(list1, fp) == RES_OK); + CHK(shtr_line_list_write(NULL, fp) == RES_BAD_ARG); + CHK(shtr_line_list_write(list1, NULL) == RES_BAD_ARG); + CHK(shtr_line_list_write(list1, fp) == RES_OK); rewind(fp); - CHK(shtr_lines_list_create_from_stream(NULL, fp, &list2) == RES_BAD_ARG); - CHK(shtr_lines_list_create_from_stream(shtr, NULL, &list2) == RES_BAD_ARG); - CHK(shtr_lines_list_create_from_stream(shtr, fp, NULL) == RES_BAD_ARG); - CHK(shtr_lines_list_create_from_stream(shtr, fp, &list2) == RES_OK); + CHK(shtr_line_list_create_from_stream(NULL, fp, &list2) == RES_BAD_ARG); + CHK(shtr_line_list_create_from_stream(shtr, NULL, &list2) == RES_BAD_ARG); + CHK(shtr_line_list_create_from_stream(shtr, fp, NULL) == RES_BAD_ARG); + CHK(shtr_line_list_create_from_stream(shtr, fp, &list2) == RES_OK); fclose(fp); - check_lines_list_equality(list1, list2); + check_line_list_equality(list1, list2); - CHK(shtr_lines_list_ref_put(list1) == RES_OK); - CHK(shtr_lines_list_ref_put(list2) == RES_OK); + CHK(shtr_line_list_ref_put(list1) == RES_OK); + CHK(shtr_line_list_ref_put(list2) == RES_OK); } static void check_view - (const struct shtr_lines_list* list, - const struct shtr_lines_view* view, - const struct shtr_lines_view_create_args* args) + (const struct shtr_line_list* list, + const struct shtr_line_view* view, + const struct shtr_line_view_create_args* args) { const struct shtr_line* lines = NULL; size_t i, n; size_t nlines_selected = 0; CHK(list && view && args); - CHK(shtr_lines_list_get_size(list, &n) == RES_OK); - CHK(shtr_lines_list_get(list, &lines) == RES_OK); + CHK(shtr_line_list_get_size(list, &n) == RES_OK); + CHK(shtr_line_list_get(list, &lines) == RES_OK); FOR_EACH(i, 0, n) { const struct shtr_line* line = NULL; double nu = 0; @@ -346,12 +346,12 @@ check_view continue; /* Skip the isotope */ } - CHK(shtr_lines_view_get_line(view, nlines_selected, &line) == RES_OK); + CHK(shtr_line_view_get_line(view, nlines_selected, &line) == RES_OK); CHK(shtr_line_eq(line, lines+i)); nlines_selected += 1; } - CHK(shtr_lines_view_get_size(view, &n) == RES_OK); + CHK(shtr_line_view_get_size(view, &n) == RES_OK); CHK(n == nlines_selected); } @@ -427,9 +427,9 @@ test_view(struct shtr* shtr) const double cutoff = 0.01; - struct shtr_lines_view_create_args args = SHTR_LINES_VIEW_CREATE_ARGS_NULL; - struct shtr_lines_list* list = NULL; - struct shtr_lines_view* view = NULL; + struct shtr_line_view_create_args args = SHTR_LINE_VIEW_CREATE_ARGS_NULL; + struct shtr_line_list* list = NULL; + struct shtr_line_view* view = NULL; const struct shtr_line* line = NULL; const char* filename = "test_lines.txt"; FILE* fp = NULL; @@ -439,7 +439,7 @@ test_view(struct shtr* shtr) print_lines(fp, l, nlines); rewind(fp); - CHK(shtr_lines_list_load_stream(shtr, fp, NULL, &list) == RES_OK); + CHK(shtr_line_list_load_stream(shtr, fp, NULL, &list) == RES_OK); args.wavenumber_range[0] = 0; args.wavenumber_range[1] = INF; @@ -451,116 +451,116 @@ test_view(struct shtr* shtr) args.molecules[2].cutoff = cutoff; args.nmolecules = 3; args.pressure = 0; - CHK(shtr_lines_view_create(NULL, &args, &view) == RES_BAD_ARG); - CHK(shtr_lines_view_create(list, NULL, &view) == RES_BAD_ARG); - CHK(shtr_lines_view_create(list, &args, NULL) == RES_BAD_ARG); - CHK(shtr_lines_view_create(list, &args, &view) == RES_OK); - - CHK(shtr_lines_view_get_size(NULL, &n) == RES_BAD_ARG); - CHK(shtr_lines_view_get_size(view, NULL) == RES_BAD_ARG); - CHK(shtr_lines_view_get_size(view, &n) == RES_OK); + CHK(shtr_line_view_create(NULL, &args, &view) == RES_BAD_ARG); + CHK(shtr_line_view_create(list, NULL, &view) == RES_BAD_ARG); + CHK(shtr_line_view_create(list, &args, NULL) == RES_BAD_ARG); + CHK(shtr_line_view_create(list, &args, &view) == RES_OK); + + CHK(shtr_line_view_get_size(NULL, &n) == RES_BAD_ARG); + CHK(shtr_line_view_get_size(view, NULL) == RES_BAD_ARG); + CHK(shtr_line_view_get_size(view, &n) == RES_OK); CHK(n == nlines); - CHK(shtr_lines_view_get_line(NULL, 0, &line) == RES_BAD_ARG); - CHK(shtr_lines_view_get_line(view, n, &line) == RES_BAD_ARG); - CHK(shtr_lines_view_get_line(view, 0, NULL) == RES_BAD_ARG); + CHK(shtr_line_view_get_line(NULL, 0, &line) == RES_BAD_ARG); + CHK(shtr_line_view_get_line(view, n, &line) == RES_BAD_ARG); + CHK(shtr_line_view_get_line(view, 0, NULL) == RES_BAD_ARG); FOR_EACH(i, 0, n) { - CHK(shtr_lines_view_get_line(view, i, &line) == RES_OK); + CHK(shtr_line_view_get_line(view, i, &line) == RES_OK); CHK(shtr_line_eq(line, l+i)); } - CHK(shtr_lines_view_ref_get(NULL) == RES_BAD_ARG); - CHK(shtr_lines_view_ref_get(view) == RES_OK); - CHK(shtr_lines_view_ref_put(NULL) == RES_BAD_ARG); - CHK(shtr_lines_view_ref_put(view) == RES_OK); - CHK(shtr_lines_view_ref_put(view) == RES_OK); + CHK(shtr_line_view_ref_get(NULL) == RES_BAD_ARG); + CHK(shtr_line_view_ref_get(view) == RES_OK); + CHK(shtr_line_view_ref_put(NULL) == RES_BAD_ARG); + CHK(shtr_line_view_ref_put(view) == RES_OK); + CHK(shtr_line_view_ref_put(view) == RES_OK); args.wavenumber_range[0] = 1; args.wavenumber_range[1] = 0; - CHK(shtr_lines_view_create(list, &args, &view) == RES_BAD_ARG); + CHK(shtr_line_view_create(list, &args, &view) == RES_BAD_ARG); args.wavenumber_range[0] = 0; args.wavenumber_range[1] = 1; args.nmolecules = 0; - CHK(shtr_lines_view_create(list, &args, &view) == RES_OK); - CHK(shtr_lines_view_get_size(view, &n) == RES_OK); + CHK(shtr_line_view_create(list, &args, &view) == RES_OK); + CHK(shtr_line_view_get_size(view, &n) == RES_OK); CHK(n == 0); - CHK(shtr_lines_view_ref_put(view) == RES_OK); + CHK(shtr_line_view_ref_put(view) == RES_OK); args.pressure = -1; - CHK(shtr_lines_view_create(list, &args, &view) == RES_BAD_ARG); + CHK(shtr_line_view_create(list, &args, &view) == RES_BAD_ARG); args.pressure = 0; args.molecules[0].cutoff = -1; args.nmolecules = 3; - CHK(shtr_lines_view_create(list, &args, &view) == RES_BAD_ARG); + CHK(shtr_line_view_create(list, &args, &view) == RES_BAD_ARG); args.molecules[0].cutoff = cutoff; args.wavenumber_range[0] = nextafter(l[nlines-1].wavenumber, INF) + cutoff; args.wavenumber_range[1] = INF; - CHK(shtr_lines_view_create(list, &args, &view) == RES_OK); - CHK(shtr_lines_view_get_size(view, &n) == RES_OK); + CHK(shtr_line_view_create(list, &args, &view) == RES_OK); + CHK(shtr_line_view_get_size(view, &n) == RES_OK); CHK(n == 0); - CHK(shtr_lines_view_ref_put(view) == RES_OK); + CHK(shtr_line_view_ref_put(view) == RES_OK); args.wavenumber_range[0] = 0; args.wavenumber_range[1] = 1.50; - CHK(shtr_lines_view_create(list, &args, &view) == RES_OK); + CHK(shtr_line_view_create(list, &args, &view) == RES_OK); check_view(list, view, &args); - CHK(shtr_lines_view_ref_put(view) == RES_OK); + CHK(shtr_line_view_ref_put(view) == RES_OK); args.wavenumber_range[0] = 1.50; args.wavenumber_range[1] = 1.51603; - CHK(shtr_lines_view_create(list, &args, &view) == RES_OK); + CHK(shtr_line_view_create(list, &args, &view) == RES_OK); check_view(list, view, &args); - CHK(shtr_lines_view_ref_put(view) == RES_OK); + CHK(shtr_line_view_ref_put(view) == RES_OK); args.wavenumber_range[0] = 0.29477; args.wavenumber_range[1] = 0.29477; - CHK(shtr_lines_view_create(list, &args, &view) == RES_OK); - CHK(shtr_lines_view_get_size(view, &n) == RES_OK); + CHK(shtr_line_view_create(list, &args, &view) == RES_OK); + CHK(shtr_line_view_get_size(view, &n) == RES_OK); CHK(n == 6); check_view(list, view, &args); - CHK(shtr_lines_view_ref_put(view) == RES_OK); + CHK(shtr_line_view_ref_put(view) == RES_OK); args.wavenumber_range[0] = 0.09642; args.wavenumber_range[1] = 0.21283; - CHK(shtr_lines_view_create(list, &args, &view) == RES_OK); - CHK(shtr_lines_view_get_size(view, &n) == RES_OK); + CHK(shtr_line_view_create(list, &args, &view) == RES_OK); + CHK(shtr_line_view_get_size(view, &n) == RES_OK); CHK(n == 14); check_view(list, view, &args); - CHK(shtr_lines_view_ref_put(view) == RES_OK); + CHK(shtr_line_view_ref_put(view) == RES_OK); args.molecules[0].id = 2; args.nmolecules = 1; - CHK(shtr_lines_view_create(list, &args, &view) == RES_OK); - CHK(shtr_lines_view_get_size(view, &n) == RES_OK); + CHK(shtr_line_view_create(list, &args, &view) == RES_OK); + CHK(shtr_line_view_get_size(view, &n) == RES_OK); CHK(n == 0); - CHK(shtr_lines_view_ref_put(view) == RES_OK); + CHK(shtr_line_view_ref_put(view) == RES_OK); args.molecules[1].id = 1; args.nmolecules = 2; - CHK(shtr_lines_view_create(list, &args, &view) == RES_OK); - CHK(shtr_lines_view_get_size(view, &n) == RES_OK); + CHK(shtr_line_view_create(list, &args, &view) == RES_OK); + CHK(shtr_line_view_get_size(view, &n) == RES_OK); CHK(n == 4); check_view(list, view, &args); - CHK(shtr_lines_view_ref_put(view) == RES_OK); + CHK(shtr_line_view_ref_put(view) == RES_OK); args.molecules[1].id = 3; args.nmolecules = 2; - CHK(shtr_lines_view_create(list, &args, &view) == RES_OK); - CHK(shtr_lines_view_get_size(view, &n) == RES_OK); + CHK(shtr_line_view_create(list, &args, &view) == RES_OK); + CHK(shtr_line_view_get_size(view, &n) == RES_OK); CHK(n == 10); check_view(list, view, &args); - CHK(shtr_lines_view_ref_put(view) == RES_OK); + CHK(shtr_line_view_ref_put(view) == RES_OK); args.wavenumber_range[0] = 0; args.wavenumber_range[1] = INF; args.molecules[0].id = 2; args.nmolecules = 1; - CHK(shtr_lines_view_create(list, &args, &view) == RES_OK); + CHK(shtr_line_view_create(list, &args, &view) == RES_OK); check_view(list, view, &args); - CHK(shtr_lines_view_ref_put(view) == RES_OK); + CHK(shtr_line_view_ref_put(view) == RES_OK); args.molecules[0].id = 1; args.molecules[0].cutoff = 1e-6; @@ -568,16 +568,16 @@ test_view(struct shtr* shtr) args.nmolecules = 1; args.wavenumber_range[0] = 0.1899; args.wavenumber_range[1] = 0.195; - CHK(shtr_lines_view_create(list, &args, &view) == RES_OK); - CHK(shtr_lines_view_get_size(view, &n) == RES_OK); + CHK(shtr_line_view_create(list, &args, &view) == RES_OK); + CHK(shtr_line_view_get_size(view, &n) == RES_OK); CHK(n == 1); - CHK(shtr_lines_view_ref_put(view) == RES_OK); + CHK(shtr_line_view_ref_put(view) == RES_OK); args.pressure = 1; - CHK(shtr_lines_view_create(list, &args, &view) == RES_OK); - CHK(shtr_lines_view_get_size(view, &n) == RES_OK); + CHK(shtr_line_view_create(list, &args, &view) == RES_OK); + CHK(shtr_line_view_get_size(view, &n) == RES_OK); CHK(n == 2); check_view(list, view, &args); - CHK(shtr_lines_view_ref_put(view) == RES_OK); + CHK(shtr_line_view_ref_put(view) == RES_OK); args.wavenumber_range[0] = 0; args.wavenumber_range[1] = INF; @@ -594,35 +594,35 @@ test_view(struct shtr* shtr) args.molecules[1].isotope_ids_local[1] = 3; args.molecules[1].nisotopes = 2; args.nmolecules = 2; - CHK(shtr_lines_view_create(list, &args, &view) == RES_OK); - CHK(shtr_lines_view_get_size(view, &n) == RES_OK); + CHK(shtr_line_view_create(list, &args, &view) == RES_OK); + CHK(shtr_line_view_get_size(view, &n) == RES_OK); CHK(n == 35); check_view(list, view, &args); - CHK(shtr_lines_view_ref_put(view) == RES_OK); + CHK(shtr_line_view_ref_put(view) == RES_OK); - CHK(shtr_lines_list_ref_put(list) == RES_OK); + CHK(shtr_line_list_ref_put(list) == RES_OK); CHK(fclose(fp) == 0); } static void -check_lines_view_equality - (const struct shtr_lines_view* view1, - const struct shtr_lines_view* view2) +check_line_view_equality + (const struct shtr_line_view* view1, + const struct shtr_line_view* view2) { size_t n1, n2; size_t iline, nlines; CHK(view1 && view2); - CHK(shtr_lines_view_get_size(view1, &n1) == RES_OK); - CHK(shtr_lines_view_get_size(view2, &n2) == RES_OK); + CHK(shtr_line_view_get_size(view1, &n1) == RES_OK); + CHK(shtr_line_view_get_size(view2, &n2) == RES_OK); CHK(n1 == n2); nlines = n1; FOR_EACH(iline, 0, nlines) { const struct shtr_line* line1 = NULL; const struct shtr_line* line2 = NULL; - CHK(shtr_lines_view_get_line(view1, iline, &line1) == RES_OK); - CHK(shtr_lines_view_get_line(view2, iline, &line2) == RES_OK); + CHK(shtr_line_view_get_line(view1, iline, &line1) == RES_OK); + CHK(shtr_line_view_get_line(view2, iline, &line2) == RES_OK); CHK(shtr_line_eq(line1, line2)); } } @@ -699,17 +699,17 @@ test_view_serialization(struct shtr* shtr) const double cutoff = 25; - struct shtr_lines_view_create_args args = SHTR_LINES_VIEW_CREATE_ARGS_NULL; - struct shtr_lines_list* list = NULL; - struct shtr_lines_view* view1 = NULL; - struct shtr_lines_view* view2 = NULL; + struct shtr_line_view_create_args args = SHTR_LINE_VIEW_CREATE_ARGS_NULL; + struct shtr_line_list* list = NULL; + struct shtr_line_view* view1 = NULL; + struct shtr_line_view* view2 = NULL; FILE* fp = NULL; CHK(fp = tmpfile()); print_lines(fp, l, nlines); rewind(fp); - CHK(shtr_lines_list_load_stream(shtr, fp, NULL, &list) == RES_OK); + CHK(shtr_line_list_load_stream(shtr, fp, NULL, &list) == RES_OK); fclose(fp); args.wavenumber_range[0] = 0; @@ -722,25 +722,25 @@ test_view_serialization(struct shtr* shtr) args.molecules[2].cutoff = cutoff; args.nmolecules = 3; args.pressure = 0; - CHK(shtr_lines_view_create(list, &args, &view1) == RES_OK); - CHK(shtr_lines_list_ref_put(list) == RES_OK); + CHK(shtr_line_view_create(list, &args, &view1) == RES_OK); + CHK(shtr_line_list_ref_put(list) == RES_OK); CHK(fp = tmpfile()); - CHK(shtr_lines_view_write(NULL, fp) == RES_BAD_ARG); - CHK(shtr_lines_view_write(view1, NULL) == RES_BAD_ARG); - CHK(shtr_lines_view_write(view1, fp) == RES_OK); + CHK(shtr_line_view_write(NULL, fp) == RES_BAD_ARG); + CHK(shtr_line_view_write(view1, NULL) == RES_BAD_ARG); + CHK(shtr_line_view_write(view1, fp) == RES_OK); rewind(fp); - CHK(shtr_lines_view_create_from_stream(NULL, fp, &view2) == RES_BAD_ARG); - CHK(shtr_lines_view_create_from_stream(shtr, NULL, &view2) == RES_BAD_ARG); - CHK(shtr_lines_view_create_from_stream(shtr, fp, NULL) == RES_BAD_ARG); - CHK(shtr_lines_view_create_from_stream(shtr, fp, &view2) == RES_OK); + CHK(shtr_line_view_create_from_stream(NULL, fp, &view2) == RES_BAD_ARG); + CHK(shtr_line_view_create_from_stream(shtr, NULL, &view2) == RES_BAD_ARG); + CHK(shtr_line_view_create_from_stream(shtr, fp, NULL) == RES_BAD_ARG); + CHK(shtr_line_view_create_from_stream(shtr, fp, &view2) == RES_OK); fclose(fp); - check_lines_view_equality(view1, view2); + check_line_view_equality(view1, view2); - CHK(shtr_lines_view_ref_put(view1) == RES_OK); - CHK(shtr_lines_view_ref_put(view2) == RES_OK); + CHK(shtr_line_view_ref_put(view1) == RES_OK); + CHK(shtr_line_view_ref_put(view2) == RES_OK); } static void @@ -767,18 +767,18 @@ check_line(const struct shtr_line* ln) static void test_load_file(struct shtr* shtr, const char* path) { - struct shtr_lines_list* list = NULL; + struct shtr_line_list* list = NULL; const struct shtr_line* lines = NULL; size_t i, n; CHK(path); printf("Loading `%s'.\n", path); - CHK(shtr_lines_list_load(shtr, path, &list) == RES_OK); - CHK(shtr_lines_list_get_size(list, &n) == RES_OK); + CHK(shtr_line_list_load(shtr, path, &list) == RES_OK); + CHK(shtr_line_list_get_size(list, &n) == RES_OK); printf(" #lines: %lu\n", n); - CHK(shtr_lines_list_get(list, &lines) == RES_OK); + CHK(shtr_line_list_get(list, &lines) == RES_OK); FOR_EACH(i, 0, n) check_line(lines+i); - CHK(shtr_lines_list_ref_put(list) == RES_OK); + CHK(shtr_line_list_ref_put(list) == RES_OK); } int