htgop

Optical properties of a gas mixture
git clone git://git.meso-star.fr/htgop.git
Log | Files | Refs | README | LICENSE

commit 940e2f9a8fbbacdadacc178a5961070b17082e32
parent 8e88632e8fdbdb9772b954cfd9c722123a244c11
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Mon, 29 Jan 2018 10:04:43 +0100

Implement the load function

Diffstat:
Mcmake/CMakeLists.txt | 5++++-
Msrc/htgop.c | 333++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
Msrc/htgop_c.h | 42+++++++++++++++++++++++++++++++++++++++---
Asrc/htgop_dbllst.h | 31+++++++++++++++++++++++++++++++
Asrc/htgop_layer.h | 229+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/htgop_parse_layers_spectral_intervals_data.h | 104+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/htgop_spectral_intervals.h | 73+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
7 files changed, 811 insertions(+), 6 deletions(-)

diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt @@ -43,7 +43,10 @@ set(VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}) set(HTGOP_FILES_SRC htgop.c) set(SSOL_FILES_INC - htgop_c.h) + htgop_c.h + htgop_layer.h + htgop_parse_layers_spectral_intervals_data.h + htgop_spectral_intervals.h) set(SSOL_FILES_INC_API htgop.h) diff --git a/src/htgop.c b/src/htgop.c @@ -16,24 +16,300 @@ #include "htgop.h" #include "htgop_c.h" +#include <rsys/cstr.h> #include <rsys/logger.h> #include <rsys/mem_allocator.h> +#include <rsys/stretchy_array.h> + +#include <string.h> + +/******************************************************************************* + * Reader + ******************************************************************************/ +struct reader { + FILE* stream; + const char* name; + size_t iline; + char* line; +}; + +static void +reader_init(struct reader* rdr, FILE* stream, const char* name) +{ + ASSERT(rdr && stream && name); + memset(rdr, 0, sizeof(struct reader)); + rdr->stream = stream; + rdr->name = name; + rdr->iline = 0; + rdr->line = sa_add(rdr->line, 128); + ASSERT(rdr->line); +} + +static void +reader_release(struct reader* rdr) +{ + ASSERT(rdr); + sa_release(rdr->line); +} + +/* Read a non empty line */ +static char* +read_line(struct reader* rdr) +{ + const int chunk = 32; + + do { + if(!fgets(rdr->line, (int)sa_size(rdr->line), rdr->stream)) return NULL; + ++rdr->iline; + + /* Ensure that the whole line is read */ + while(!strrchr(rdr->line, '\n') && !feof(rdr->stream)) { + CHK(fgets(sa_add(rdr->line, (size_t)chunk), chunk, rdr->stream)); + } + + rdr->line[strcspn(rdr->line, "#\n\r")] = '\0'; /* Rm new line & comments */ + } while(strspn(rdr->line, " \t") == strlen(rdr->line)); /* Empty line */ + return rdr->line; +} /******************************************************************************* * Helper functions - ******************************************************************************/ + ******************************************************************************/ +static void +log_msg + (const struct htgop* htgop, + const enum log_type stream, + const char* msg, + va_list vargs) +{ + ASSERT(htgop && msg); + if(htgop->verbose) { + res_T res; (void)res; + res = logger_vprint(htgop->logger, stream, msg, vargs); + ASSERT(res == RES_OK); + } +} + +static res_T +parse_spectral_intervals + (struct htgop* htgop, + struct reader* rdr, + const unsigned long nspecints, + struct spectral_intervals* specints) +{ + unsigned long ispecint; + double* wave_numbers = NULL; + struct darray_double* quadratures = NULL; + res_T res = RES_OK; + (void)htgop; + ASSERT(htgop && rdr && nspecints && specints); + + #define CALL(Func) { if((res = Func) != RES_OK) goto error; } (void)0 + + /* Allocate the memory space for the wave numbers and the quadratures */ + CALL(darray_double_resize(&specints->wave_numbers, nspecints + 1)); + CALL(darray_dbllst_resize(&specints->quadratures, nspecints)); + wave_numbers = darray_double_data_get(&specints->wave_numbers); + quadratures = darray_dbllst_data_get(&specints->quadratures); + + FOR_EACH(ispecint, 0, nspecints) { + double* quadrature = NULL; + double wave_number_low; + double wave_number_upp; + unsigned long quad_len; + unsigned long iquad; + + /* Parse the interval bounds */ + CALL(cstr_to_double(read_line(rdr), &wave_number_low)); + CALL(cstr_to_double(read_line(rdr), &wave_number_upp)); + + /* Check and register the interval bounds */ + if(wave_number_low >= wave_number_upp) { + res = RES_BAD_ARG; + goto error; + } + if(ispecint == 0) { + wave_numbers[ispecint] = wave_number_low; + } else if(wave_number_low != wave_numbers[ispecint]) { + res = RES_BAD_ARG; + goto error; + } + wave_numbers[ispecint + 1] = wave_number_upp; + + /* Parse and allocate the quadrature length */ + CALL(cstr_to_ulong(read_line(rdr), &quad_len)); + + /* Allocate the points of the quadrature */ + CALL(darray_double_resize(&quadratures[ispecint], quad_len)); + quadrature = darray_double_data_get(&quadratures[ispecint]); + + /* Read the weight of the quadrature points */ + FOR_EACH(iquad, 0, quad_len) { + CALL(cstr_to_double(read_line(rdr), &quadrature[iquad])); + } + } + + #undef CALL + +exit: + return res; +error: + darray_double_clear(&specints->wave_numbers); + darray_dbllst_clear(&specints->quadratures); + goto exit; +} + +/* Generate the parse_layers_spectral_intervals_ka_lw function */ +#define LAYER_SPECINT_DATA ka +#define LAYER_SPECINT_DOMAIN lw +#include "htgop_parse_layers_spectral_intervals_data.h" +/* Generate the parse_layers_spectral_intervals_ka_sw function */ +#define LAYER_SPECINT_DATA ka +#define LAYER_SPECINT_DOMAIN sw +#include "htgop_parse_layers_spectral_intervals_data.h" +/* Generate the parse_layers_spectral_intervals_ks_sw function */ +#define LAYER_SPECINT_DATA ks +#define LAYER_SPECINT_DOMAIN sw +#include "htgop_parse_layers_spectral_intervals_data.h" + +static res_T +parse_layers_spectral_intervals(struct htgop* htgop, struct reader* rdr) +{ + struct layer* layers = NULL; + size_t lw_nspecints, sw_nspecints, nlays; + size_t ilay; + res_T res = RES_OK; + ASSERT(htgop && rdr); + + nlays = darray_layer_size_get(&htgop->layers); + ASSERT(nlays > 0); + lw_nspecints = darray_double_size_get(&htgop->lw_specints.wave_numbers) - 1; + sw_nspecints = darray_double_size_get(&htgop->sw_specints.wave_numbers) - 1; + ASSERT(lw_nspecints > 0 && sw_nspecints); + + #define CALL(Func) { if((res = Func) != RES_OK) goto error; } (void)0 + /* Allocate the per layer spectral intervals */ + FOR_EACH(ilay, 0, nlays) { + CALL(darray_lay_lw_specint_resize(&layers[ilay].lw_specints, lw_nspecints)); + CALL(darray_lay_sw_specint_resize(&layers[ilay].sw_specints, sw_nspecints)); + } + /* Parse the spectral data of the layers */ + CALL(parse_layers_spectral_intervals_ka_lw(htgop, rdr)); + CALL(parse_layers_spectral_intervals_ka_sw(htgop, rdr)); + CALL(parse_layers_spectral_intervals_ks_sw(htgop, rdr)); + #undef CALL + +exit: + return res; +error: + FOR_EACH(ilay, 0, nlays) { + darray_lay_lw_specint_clear(&layers[ilay].lw_specints); + darray_lay_sw_specint_clear(&layers[ilay].sw_specints); + } + goto exit; +} + +static res_T +load_stream(struct htgop* htgop, FILE* stream, const char* stream_name) +{ + struct reader rdr; + struct level* levels = NULL; + struct layer* layers = NULL; + unsigned long nlvls, nlays, tab_len, nspecints_lw, nspecints_sw; + unsigned long ilvl, ilay, itab; + res_T res = RES_OK; + ASSERT(htgop && stream && stream_name); + reader_init(&rdr, stream, stream_name); + + #define CALL(Func) { if((res = Func) != RES_OK) goto error; } + + /* Parse the number of levels/layers */ + CALL(cstr_to_ulong(read_line(&rdr), &nlvls)); + CALL(cstr_to_ulong(read_line(&rdr), &nlays)); + if(nlvls != nlays + 1) { res = RES_BAD_ARG; goto error; } + + /* Parse the ground temperature */ + CALL(cstr_to_double(read_line(&rdr), &htgop->ground.temperature)); + + /* Allocate the per level data */ + CALL(darray_level_resize(&htgop->levels, nlvls)); + CALL(darray_layer_resize(&htgop->layers, nlays)); + levels = darray_level_data_get(&htgop->levels); + layers = darray_layer_data_get(&htgop->layers); + + /* Per level data */ + FOR_EACH(ilvl, 0, nlvls) { /* Pressure */ + CALL(cstr_to_double(read_line(&rdr), &levels[ilvl].pressure)); + } + FOR_EACH(ilvl, 0, nlvls) { /* Temperature */ + CALL(cstr_to_double(read_line(&rdr), &levels[ilvl].temperature)); + } + FOR_EACH(ilvl, 0, nlvls) { /* Height */ + CALL(cstr_to_double(read_line(&rdr), &levels[ilvl].height)); + } + + /* Per layer x H2O nominal */ + FOR_EACH(ilay, 0, nlays) { + CALL(cstr_to_double(read_line(&rdr), &layers[ilay].x_h2o_nominal)); + } + + /* Parse the length of the tabulation */ + CALL(cstr_to_ulong(read_line(&rdr), &tab_len)); + + /* Allocate the tabulated xH2O of each layer */ + FOR_EACH(ilay, 0, nlays) { + CALL(darray_double_resize(&layers[ilay].x_h2o_tab, tab_len)); + } + + /* Parse the tabulated xH2O of each layer */ + FOR_EACH(itab, 0, tab_len) { + FOR_EACH(ilay, 0, nlays) { + double* x_h2o_tab = darray_double_data_get(&layers[ilay].x_h2o_tab); + CALL(cstr_to_double(read_line(&rdr), &x_h2o_tab[itab])); + } + } + + /* Parse the long/short wave emissivity of the hround */ + CALL(cstr_to_double(read_line(&rdr), &htgop->ground.lw_emissivity)); + CALL(cstr_to_double(read_line(&rdr), &htgop->ground.sw_emissivity)); + + /* Parse the numver of long/short wave spectral intervals */ + CALL(cstr_to_ulong(read_line(&rdr), &nspecints_lw)); + CALL(cstr_to_ulong(read_line(&rdr), &nspecints_sw)); + + /* Parse the data of the long/short wave spectral intervals */ + CALL(parse_spectral_intervals(htgop, &rdr, nspecints_lw, &htgop->lw_specints)); + CALL(parse_spectral_intervals(htgop, &rdr, nspecints_sw, &htgop->sw_specints)); + + /* Parse the spectral data of the layers */ + CALL(parse_layers_spectral_intervals(htgop, &rdr)); + + #undef CALL + +exit: + reader_release(&rdr); + return res; +error: + log_err(htgop, "%s:%lu: Parsing error.\n", rdr.name, rdr.iline); + goto exit; +} + static void release_htgop(ref_T* ref) { struct htgop* htgop; ASSERT(ref); htgop = CONTAINER_OF(ref, struct htgop, ref); + spectral_intervals_release(&htgop->lw_specints); + spectral_intervals_release(&htgop->sw_specints); + darray_level_release(&htgop->levels); + darray_layer_release(&htgop->layers); MEM_RM(htgop->allocator, htgop); } /******************************************************************************* * Exported functions - ******************************************************************************/ + ******************************************************************************/ res_T htgop_create (struct logger* log, @@ -68,6 +344,10 @@ htgop_create htgop->allocator = allocator; htgop->logger = logger; htgop->verbose = verbose; + spectral_intervals_init(allocator, &htgop->lw_specints); + spectral_intervals_init(allocator, &htgop->sw_specints); + darray_level_init(allocator, &htgop->levels); + darray_layer_init(allocator, &htgop->layers); exit: if(out_htgop) *out_htgop = htgop; @@ -96,3 +376,52 @@ htgop_ref_put(struct htgop* htgop) return RES_OK; } +res_T +htgop_load(struct htgop* htgop, const char* filename) +{ + FILE* file = NULL; + res_T res = RES_OK; + + if(!htgop || !filename) { + res = RES_BAD_ARG; + goto error; + } + + file = fopen(filename, "r"); + if(!file) { + log_err(htgop, "%s: error opening file `%s'.\n", FUNC_NAME, filename); + res = RES_IO_ERR; + goto error; + } + + res = load_stream(htgop, file, filename); + if(res != RES_OK) goto error; + +exit: + if(file) fclose(file); + return res; +error: + goto exit; +} + +res_T +htgop_load_stream(struct htgop* htgop, FILE* stream) +{ + if(!htgop || !stream) return RES_BAD_ARG; + return load_stream(htgop, stream, "<stream>"); +} + +/******************************************************************************* + * Local functions + ******************************************************************************/ +void +log_err(const struct htgop* htgop, const char* msg, ...) +{ + va_list vargs_list; + ASSERT(htgop && msg); + + va_start(vargs_list, msg); + log_msg(htgop, LOG_ERROR, msg, vargs_list); + va_end(vargs_list); +} + diff --git a/src/htgop_c.h b/src/htgop_c.h @@ -16,18 +16,54 @@ #ifndef HTGOP_C_H #define HTGOP_C_H +#include "htgop_layer.h" +#include "htgop_spectral_intervals.h" + +#include <rsys/dynamic_array.h> #include <rsys/ref_count.h> -struct logger; -struct mem_allocator; +struct ground { + double temperature; /* In Kelvin */ + double lw_emissivity; /* Long wave emissivity */ + double sw_emissivity; /* Short wave emissivity */ +}; + +struct level { + double pressure; /* In Pascal */ + double temperature; /* In Kelvin */ + double height; /* In meter */ +}; + +/* Generate the dynamic array of level */ +#define DARRAY_NAME level +#define DARRAY_DATA struct level +#include <rsys/dynamic_array.h> struct htgop { - int verbose; + struct ground ground; + + /* Description of the spectral intervals for the short/long wave domain */ + struct spectral_intervals lw_specints; + struct spectral_intervals sw_specints; + struct darray_layer layers; /* Par layer data */ + struct darray_level levels; /* Per level data (#level = #layer + 1 ) */ + + int verbose; /* Verbosity level */ struct logger* logger; struct mem_allocator* allocator; ref_T ref; }; +extern LOCAL_SYM void +log_err + (const struct htgop* htgop, + const char* fmt, + ...) +#ifdef COMPILER_GCC + __attribute((format(printf, 2, 3))) +#endif + ; + #endif /* HTGOP_C_H */ diff --git a/src/htgop_dbllst.h b/src/htgop_dbllst.h @@ -0,0 +1,31 @@ +/* Copyright (C) |Meso|Star> 2018 (contact@meso-star.com) + * + * 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 HTGOP_DBLLST_H +#define HTGOP_DBLLST_H + +#include <rsys/dynamic_array_double.h> + +/* Generate the darray_dbllst dynamic array */ +#define DARRAY_NAME dbllst +#define DARRAY_DATA struct darray_double +#define DARRAY_FUNCTOR_INIT darray_double_init +#define DARRAY_FUNCTOR_RELEASE darray_double_release +#define DARRAY_FUNCTOR_COPY darray_double_copy +#define DARRAY_FUNCTOR_COPY_AND_RELEASE darray_double_copy_and_release +#include <rsys/dynamic_array.h> + +#endif /* HTGOP_DBLLST_H */ + diff --git a/src/htgop_layer.h b/src/htgop_layer.h @@ -0,0 +1,229 @@ +/* Copyright (C) |Meso|Star> 2018 (contact@meso-star.com) + * + * 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 HTGOP_LAYER_H +#define HTGOP_LAYER_H + +#include "htgop_dbllst.h" +#include <rsys/dynamic_array.h> + +/******************************************************************************* + * Long wave spectral interval of a layer. Each data are defined per quadrature + * point. + ******************************************************************************/ +struct layer_lw_spectral_interval { + struct darray_double ka_nominal; /* Nominal absorption coef */ + struct darray_dbllst ka_tab; /* Tabulated absorption coef */ +}; + +static INLINE void +layer_lw_spectral_interval_init + (struct mem_allocator* allocator, struct layer_lw_spectral_interval* inter) +{ + ASSERT(inter); + darray_double_init(allocator, &inter->ka_nominal); + darray_dbllst_init(allocator, &inter->ka_tab); +} + +static INLINE void +layer_lw_spectral_interval_release(struct layer_lw_spectral_interval* inter) +{ + ASSERT(inter); + darray_double_release(&inter->ka_nominal); + darray_dbllst_release(&inter->ka_tab); +} + +static INLINE res_T +layer_lw_spectral_interval_copy + (struct layer_lw_spectral_interval* dst, + const struct layer_lw_spectral_interval* src) +{ + res_T res = RES_OK; + ASSERT(dst && src); + #define CALL(Func) { if(RES_OK != (res = Func)) return res; } (void)0 + CALL(darray_double_copy(&dst->ka_nominal, &src->ka_nominal)); + CALL(darray_dbllst_copy(&dst->ka_tab, &src->ka_tab)); + #undef CALL + return RES_OK; +} + +static INLINE res_T +layer_lw_spectral_interval_copy_and_release + (struct layer_lw_spectral_interval* dst, + struct layer_lw_spectral_interval* src) +{ + res_T res = RES_OK; + ASSERT(dst && src); + #define CALL(Func) { if(RES_OK != (res = Func)) return res; } (void)0 + CALL(darray_double_copy_and_release(&dst->ka_nominal, &src->ka_nominal)); + CALL(darray_dbllst_copy_and_release(&dst->ka_tab, &src->ka_tab)); + #undef CALL + layer_lw_spectral_interval_release(src); + return RES_OK; +} + +/* Generate the darray_lay_lw_specint dynamic array */ +#define DARRAY_NAME lay_lw_specint +#define DARRAY_DATA struct layer_lw_spectral_interval +#define DARRAY_FUNCTOR_INIT layer_lw_spectral_interval_init +#define DARRAY_FUNCTOR_RELEASE layer_lw_spectral_interval_release +#define DARRAY_FUNCTOR_COPY layer_lw_spectral_interval_copy +#define DARRAY_FUNCTOR_COPY_AND_RELEASE \ + layer_lw_spectral_interval_copy_and_release +#include <rsys/dynamic_array.h> + +/******************************************************************************* + * Short wave spectral interval of a layer. Each data are defined per + * quadrature point. + ******************************************************************************/ +struct layer_sw_spectral_interval { + struct darray_double ka_nominal; /* Nominal absorption coef */ + struct darray_double ks_nominal; /* Nominal diffusion coef */ + struct darray_dbllst ka_tab; /* Tabulated absorption coef */ + struct darray_dbllst ks_tab; /* Tabulated diffusion coef */ +}; + +static INLINE void +layer_sw_spectral_interval_init + (struct mem_allocator* allocator, struct layer_sw_spectral_interval* inter) +{ + ASSERT(inter); + darray_double_init(allocator, &inter->ka_nominal); + darray_double_init(allocator, &inter->ks_nominal); + darray_dbllst_init(allocator, &inter->ka_tab); + darray_dbllst_init(allocator, &inter->ks_tab); +} + +static INLINE void +layer_sw_spectral_interval_release(struct layer_sw_spectral_interval* inter) +{ + ASSERT(inter); + darray_double_release(&inter->ka_nominal); + darray_double_release(&inter->ks_nominal); + darray_dbllst_release(&inter->ka_tab); + darray_dbllst_release(&inter->ks_tab); +} + +static INLINE res_T +layer_sw_spectral_interval_copy + (struct layer_sw_spectral_interval* dst, + const struct layer_sw_spectral_interval* src) +{ + res_T res = RES_OK; + ASSERT(dst && src); + #define CALL(Func) { if(RES_OK != (res = Func)) return res; } (void)0 + CALL(darray_double_copy(&dst->ka_nominal, &src->ka_nominal)); + CALL(darray_double_copy(&dst->ks_nominal, &src->ks_nominal)); + CALL(darray_dbllst_copy(&dst->ka_tab, &src->ka_tab)); + CALL(darray_dbllst_copy(&dst->ks_tab, &src->ks_tab)); + #undef CALL + return RES_OK; +} + +static INLINE res_T +layer_sw_spectral_interval_copy_and_release + (struct layer_sw_spectral_interval* dst, + struct layer_sw_spectral_interval* src) +{ + res_T res = RES_OK; + ASSERT(dst && src); + #define CALL(Func) { if(RES_OK != (res = Func)) return res; } (void)0 + CALL(darray_double_copy_and_release(&dst->ka_nominal, &src->ka_nominal)); + CALL(darray_double_copy_and_release(&dst->ks_nominal, &src->ks_nominal)); + CALL(darray_dbllst_copy_and_release(&dst->ka_tab, &src->ka_tab)); + CALL(darray_dbllst_copy_and_release(&dst->ks_tab, &src->ks_tab)); + #undef CALL + layer_sw_spectral_interval_release(src); + return RES_OK; +} + +/* Generate the darray_lay_sw_specint dynamic array */ +#define DARRAY_NAME lay_sw_specint +#define DARRAY_DATA struct layer_sw_spectral_interval +#define DARRAY_FUNCTOR_INIT layer_sw_spectral_interval_init +#define DARRAY_FUNCTOR_RELEASE layer_sw_spectral_interval_release +#define DARRAY_FUNCTOR_COPY layer_sw_spectral_interval_copy +#define DARRAY_FUNCTOR_COPY_AND_RELEASE \ + layer_sw_spectral_interval_copy_and_release +#include <rsys/dynamic_array.h> + +/******************************************************************************* + * Per layer data + ******************************************************************************/ +struct layer { + double x_h2o_nominal; /* Nominal molar fraction of water vapor */ + struct darray_double x_h2o_tab; /* Tabulated xH2O */ + struct darray_lay_lw_specint lw_specints; /* Long wave spectral interval data */ + struct darray_lay_sw_specint sw_specints; /* Short wave spectral interval data */ +}; + +static INLINE void +layer_init(struct mem_allocator* allocator, struct layer* layer) +{ + ASSERT(layer); + darray_double_init(allocator, &layer->x_h2o_tab); + darray_lay_lw_specint_init(allocator, &layer->lw_specints); + darray_lay_sw_specint_init(allocator, &layer->sw_specints); +} + +static INLINE void +layer_release(struct layer* layer) +{ + ASSERT(layer); + darray_double_release(&layer->x_h2o_tab); + darray_lay_lw_specint_release(&layer->lw_specints); + darray_lay_sw_specint_release(&layer->sw_specints); +} + +static INLINE res_T +layer_copy(struct layer* dst, const struct layer* src) +{ + res_T res = RES_OK; + ASSERT(dst && src); + dst->x_h2o_nominal = src->x_h2o_nominal; + #define CALL(Func) { if(RES_OK != (res = Func)) return res; } (void)0 + CALL(darray_double_copy(&dst->x_h2o_tab, &src->x_h2o_tab)); + CALL(darray_lay_lw_specint_copy(&dst->lw_specints, &src->lw_specints)); + CALL(darray_lay_sw_specint_copy(&dst->sw_specints, &src->sw_specints)); + #undef CALL + return RES_OK; +} + +static INLINE res_T +layer_copy_and_release(struct layer* dst, struct layer* src) +{ + res_T res = RES_OK; + ASSERT(dst && src); + dst->x_h2o_nominal = src->x_h2o_nominal; + #define CALL(Func) { if(RES_OK != (res = Func)) return res; } (void)0 + CALL(darray_double_copy_and_release(&dst->x_h2o_tab, &src->x_h2o_tab)); + CALL(darray_lay_lw_specint_copy_and_release(&dst->lw_specints, &src->lw_specints)); + CALL(darray_lay_sw_specint_copy_and_release(&dst->sw_specints, &src->sw_specints)); + #undef CALL + layer_release(src); + return RES_OK; +} + +/* Generate the darray_layer dynamic array */ +#define DARRAY_NAME layer +#define DARRAY_DATA struct layer +#define DARRAY_FUNCTOR_INIT layer_init +#define DARRAY_FUNCTOR_RELEASE layer_release +#define DARRAY_FUNCTOR_COPY layer_copy +#define DARRAY_FUNCTOR_COPY_AND_RELEASE layer_copy_and_release +#include <rsys/dynamic_array.h> + +#endif /* HTGOP_LAYER_H */ + diff --git a/src/htgop_parse_layers_spectral_intervals_data.h b/src/htgop_parse_layers_spectral_intervals_data.h @@ -0,0 +1,104 @@ +/* Copyright (C) |Meso|Star> 2018 (contact@meso-star.com) + * + * 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/>. */ + +/* + * Generate the function parsing a per layer and per spectral interval data for + * a given domain long/short wave. + */ + +#if !defined(LAYER_SPECINT_DATA) || !defined(LAYER_SPECINT_DOMAIN) + #error "Missing the LAYER_SPECINT_<DATA|XDOMAIN> macro." +#endif + +#define DATA CONCAT(CONCAT(LAYER_SPECINT_DATA, _), LAYER_SPECINT_DOMAIN) +#define XDOMAIN(Name) CONCAT(CONCAT(LAYER_SPECINT_DOMAIN, _), Name) +#define XDATA(Name) CONCAT(CONCAT(LAYER_SPECINT_DATA, _), Name) + +static res_T +CONCAT(parse_layers_spectral_intervals_, DATA) + (struct htgop* htgop, struct reader* rdr) +{ + struct layer* layers = NULL; + size_t nspecints, nlays, tab_len, quad_len; + size_t ispecint, ilay, itab, iquad; + res_T res = RES_OK; + ASSERT(htgop && rdr); + + layers = darray_layer_data_get(&htgop->layers); + nlays = darray_layer_size_get(&htgop->layers); + ASSERT(nlays > 0); + + tab_len = darray_double_size_get(&layers[0].x_h2o_tab); + ASSERT(tab_len > 0); + + nspecints = darray_double_size_get(&htgop->XDOMAIN(specints).wave_numbers)-1; + ASSERT(nspecints > 0); + + #define CALL(Func) { if((res = Func) != RES_OK) goto error; } (void)0 + FOR_EACH(ispecint, 0, nspecints) { + struct CONCAT(layer_, XDOMAIN(spectral_interval))* layspecint; + struct darray_double* quad; /* Quadrature of the current interval */ + double* XDATA(nominal); + struct darray_double* XDATA(tab); + + quad = darray_dbllst_data_get + (&htgop->XDOMAIN(specints).quadratures) + ispecint; + quad_len = darray_double_size_get(quad); + + /* Allocate the per layer data */ + FOR_EACH(ilay, 0, nlays) { + layspecint = CONCAT(CONCAT(darray_lay_, XDOMAIN(specint)), _data_get) + (&layers[ilay].XDOMAIN(specints)) + ispecint; + CALL(darray_double_resize(&layspecint->XDATA(nominal), quad_len)); + CALL(darray_dbllst_resize(&layspecint->XDATA(tab), quad_len)); + FOR_EACH(iquad, 0, quad_len) { /* Tabulated data */ + XDATA(tab) = darray_dbllst_data_get(&layspecint->XDATA(tab)) + iquad; + CALL(darray_double_resize(XDATA(tab), tab_len)); + } + } + + FOR_EACH(iquad, 0, quad_len) { + /* Read per layer nominal data */ + FOR_EACH(ilay, 0, nlays) { + layspecint = CONCAT(CONCAT(darray_lay_, XDOMAIN(specint)), _data_get) + (&layers[ilay].XDOMAIN(specints)) + ispecint; + XDATA(nominal) = darray_double_data_get(&layspecint->XDATA(nominal)); + CALL(cstr_to_double(read_line(rdr), &XDATA(nominal)[iquad])); + } + + /* Read per layer tabulated data */ + FOR_EACH(itab, 0, tab_len) { + FOR_EACH(ilay, 0, nlays) { + layspecint = CONCAT(CONCAT(darray_lay_, XDOMAIN(specint)), _data_get) + (&layers[ilay].XDOMAIN(specints)) + ispecint; + XDATA(tab) = darray_dbllst_data_get(&layspecint->XDATA(tab)) + iquad; + CALL(cstr_to_double(read_line(rdr), &darray_double_data_get(XDATA(tab))[itab])); + } + } + } + } + #undef CALL + +exit: + return res; +error: + goto exit; +} + +#undef DATA +#undef XDOMAIN +#undef XDATA +#undef LAYER_SPECINT_DATA +#undef LAYER_SPECINT_DOMAIN diff --git a/src/htgop_spectral_intervals.h b/src/htgop_spectral_intervals.h @@ -0,0 +1,73 @@ +/* Copyright (C) |Meso|Star> 2018 (contact@meso-star.com) + * + * 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 HTGOP_SPECTRAL_INTERVALS_H +#define HTGOP_SPECTRAL_INTERVALS_H + +#include "htgop_dbllst.h" + +struct spectral_intervals { + /* List of wave numbers, in cm^-1, sorted in ascending order. + * #wave numbers == #intervals + 1 */ + struct darray_double wave_numbers; + struct darray_dbllst quadratures; /* Per spectral interval quadrature weight */ +}; + +static INLINE void +spectral_intervals_init + (struct mem_allocator* allocator, struct spectral_intervals* sinters) +{ + ASSERT(sinters); + darray_double_init(allocator, &sinters->wave_numbers); + darray_dbllst_init(allocator, &sinters->quadratures); +} + +static INLINE void +spectral_intervals_release(struct spectral_intervals* sinters) +{ + ASSERT(sinters); + darray_double_release(&sinters->wave_numbers); + darray_dbllst_release(&sinters->quadratures); +} + +static INLINE res_T +spectral_intervals_copy + (struct spectral_intervals* dst, const struct spectral_intervals* src) +{ + res_T res = RES_OK; + ASSERT(dst && src); + #define CALL(Func) { if(RES_OK != (res = Func)) return res; } (void)0 + CALL(darray_double_copy(&dst->wave_numbers, &src->wave_numbers)); + CALL(darray_dbllst_copy(&dst->quadratures, &src->quadratures)); + #undef CALL + return RES_OK; +} + +static INLINE res_T +spectral_intervals_copy_and_release + (struct spectral_intervals* dst, struct spectral_intervals* src) +{ + res_T res = RES_OK; + ASSERT(dst && src); + #define CALL(Func) { if(RES_OK != (res = Func)) return res; } (void)0 + CALL(darray_double_copy_and_release(&dst->wave_numbers, &src->wave_numbers)); + CALL(darray_dbllst_copy_and_release(&dst->quadratures, &src->quadratures)); + #undef CALL + spectral_intervals_release(src); + return RES_OK; +} + +#endif /* HTGOP_SPECTRAL_INTERVALS_H */ +