commit 4d8ea4713863127bd43efea696e729c69e05440a
parent 12357da771597e74ca7b2f9893f536d93eff10f0
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Mon, 16 May 2022 11:43:34 +0200
Add the mixture data structure
A mixture encompasses line data for a spectral range, a pressure and a
temperature, for a set of molecules defined by the user, with their
specific concentration and threshold, and whose isotopes to be
manipulated are defined by the user with their corresponding abundance.
Previously, the mixture was defined when creating the tree. It became a
specific data structure to allow the same mixture to be used by several
trees.
Diffstat:
12 files changed, 1078 insertions(+), 701 deletions(-)
diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt
@@ -52,6 +52,7 @@ set(SLN_FILES_SRC
sln_device.c
sln_line.c
sln_log.c
+ sln_mixture.c
sln_polyline.c
sln_tree.c
sln_tree_build.c
@@ -60,6 +61,7 @@ set(SLN_FILES_INC
sln_device_c.h
sln_line.h
sln_log.h
+ sln_mixture_c.h
sln_polyline.h)
set(SLN_FILES_INC_API
sln.h)
@@ -98,6 +100,7 @@ if(NOT NO_TEST)
endfunction()
new_test(test_sln_device)
+ new_test(test_sln_mixture StarHITRAN)
new_test(test_sln_tree StarHITRAN)
endif()
diff --git a/src/sln.h b/src/sln.h
@@ -87,7 +87,7 @@ struct sln_molecule {
#define SLN_MOLECULE_NULL__ {{SLN_ISOTOPE_NULL__}, 0, 0, 0, 0}
static const struct sln_molecule SLN_MOLECULE_NULL = SLN_MOLECULE_NULL__;
-struct sln_tree_create_args {
+struct sln_mixture_create_args {
/* Isotope metadata and overall list of spectral lines */
struct shtr_isotope_metadata* metadata;
struct shtr_lines_list* lines;
@@ -102,7 +102,24 @@ struct sln_tree_create_args {
/* Thermodynamic properties */
double pressure; /* In atm */
double temperature; /* In K */
+};
+#define SLN_MIXTURE_CREATE_ARGS_DEFAULT__ \
+ {NULL, NULL, {SLN_MOLECULE_NULL__}, 0, {0, DBL_MAX}, 0, 0}
+static const struct sln_mixture_create_args SLN_MIXTURE_CREATE_ARGS_DEFAULT =
+ SLN_MIXTURE_CREATE_ARGS_DEFAULT__;
+
+struct sln_mixture_desc {
+ double wavenumber_range[2]; /* Spectral range */
+ double pressure; /* In atm */
+ double temperature; /* In K */
+ size_t nlines; /* Number of partitionned lines */
+};
+#define SLN_MIXTURE_DESC_NULL__ {{0,0},0,0,0}
+static const struct sln_mixture_desc SLN_MIXTURE_DESC_NULL =
+ SLN_MIXTURE_DESC_NULL__;
+struct sln_tree_create_args {
+ /* Max number of lines per leaf */
size_t max_nlines_per_leaf;
/* Hint on the number of vertices around the the line center */
@@ -110,24 +127,20 @@ struct sln_tree_create_args {
/* Relative error used to simplify the spectrum mesh. The larger it is, the
* coarser the mesh */
- float mesh_decimation_err;
+ float mesh_decimation_err;
enum sln_line_profile line_profile;
};
-#define SLN_TREE_CREATE_ARGS_DEFAULT__ \
- {NULL, NULL, {SLN_MOLECULE_NULL__}, 0, {0, DBL_MAX}, 0, 0, 1, \
- 16, 0.01f, SLN_LINE_PROFILE_VOIGT}
+#define SLN_TREE_CREATE_ARGS_DEFAULT__ {1, 16, 0.01f, SLN_LINE_PROFILE_VOIGT}
static const struct sln_tree_create_args SLN_TREE_CREATE_ARGS_DEFAULT =
SLN_TREE_CREATE_ARGS_DEFAULT__;
struct sln_tree_desc {
- double wavenumber_range[2]; /* Spectral range */
- double pressure; /* In atm */
- double temperature; /* In K */
- size_t nlines; /* Number of partitionned lines */
size_t max_nlines_per_leaf; /* max #lines per leaf */
+ double mesh_decimation_err;
+ enum sln_line_profile line_profile;
};
-#define SLN_TREE_DESC_NULL__ {{0,0},0,0,0,0}
+#define SLN_TREE_DESC_NULL__ {0,0,0}
static const struct sln_tree_desc SLN_TREE_DESC_NULL = SLN_TREE_DESC_NULL__;
struct sln_vertex { /* 8 Bytes */
@@ -146,8 +159,9 @@ static const struct sln_mesh SLN_MESH_NULL = SLN_MESH_NULL__;
/* Forward declarations of opaque data structures */
struct sln_device;
-struct sln_tree;
+struct sln_mixture;
struct sln_node;
+struct sln_tree;
/*******************************************************************************
* Device API
@@ -166,11 +180,33 @@ sln_device_ref_put
(struct sln_device* sln);
/*******************************************************************************
+ * Mixture API
+ ******************************************************************************/
+SLN_API res_T
+sln_mixture_create
+ (struct sln_device* sln,
+ const struct sln_mixture_create_args* args,
+ struct sln_mixture** mixture);
+
+SLN_API res_T
+sln_mixture_ref_get
+ (struct sln_mixture* mixture);
+
+SLN_API res_T
+sln_mixture_ref_put
+ (struct sln_mixture* mixture);
+
+SLN_API res_T
+sln_mixture_get_desc
+ (const struct sln_mixture* mixture,
+ struct sln_mixture_desc* desc);
+
+/*******************************************************************************
* Tree API
******************************************************************************/
SLN_API res_T
sln_tree_create
- (struct sln_device* sln,
+ (struct sln_mixture* mixture,
const struct sln_tree_create_args* args,
struct sln_tree** tree);
diff --git a/src/sln_line.c b/src/sln_line.c
@@ -19,6 +19,7 @@
#include "sln_device_c.h"
#include "sln_line.h"
#include "sln_log.h"
+#include "sln_mixture_c.h"
#include "sln_tree_c.h"
#include <lblu.h>
@@ -64,7 +65,7 @@ line_intensity
static res_T
line_profile_factor
- (const struct sln_tree* tree,
+ (const struct sln_mixture* mixture,
const struct shtr_line* shtr_line,
double* out_profile_factor)
{
@@ -89,31 +90,31 @@ line_profile_factor
int isoid; /* Isotope id local to its molecule */
res_T res = RES_OK;
- ASSERT(tree && shtr_line && out_profile_factor);
+ ASSERT(mixture && shtr_line && out_profile_factor);
/* Fetch the molecule data */
- mol_params = tree_get_molecule_params(tree, shtr_line->molecule_id);
+ mol_params = mixture_get_molecule_params(mixture, shtr_line->molecule_id);
SHTR(isotope_metadata_find_molecule
- (tree->metadata, shtr_line->molecule_id, &molecule));
+ (mixture->metadata, shtr_line->molecule_id, &molecule));
ASSERT(!SHTR_MOLECULE_IS_NULL(&molecule));
ASSERT(molecule.nisotopes > (size_t)shtr_line->isotope_id_local);
isotope = molecule.isotopes + shtr_line->isotope_id_local;
- nu_c = line_center(shtr_line, tree->pressure);
+ nu_c = line_center(shtr_line, mixture->pressure);
/* Compute the intensity */
- Ps = tree->pressure * mol_params->concentration;
- density = (AVOGADRO_NUMBER * Ps) / (PERFECT_GAZ_CONSTANT * tree->temperature);
+ Ps = mixture->pressure * mol_params->concentration;
+ density = (AVOGADRO_NUMBER * Ps) / (PERFECT_GAZ_CONSTANT * mixture->temperature);
density = density * 1e-6; /* Convert in molec.cm^-3 */
/* Compute the partition function. TODO precompute it for molid/isoid */
Q_Tref = isotope->Q296K;
molid = shtr_line->molecule_id;
isoid = shtr_line->isotope_id_local+1/*Local indices start at 1 in BD_TIPS*/;
- T = tree->temperature;
+ T = mixture->temperature;
BD_TIPS_2017(&molid, &T, &isoid, &gj, &Q_T);
if(Q_T <= 0) {
- log_err(tree->sln,
+ log_err(mixture->sln,
"molecule %d: isotope %d: invalid partition function at T=%g\n",
molid, isoid, T);
res = RES_BAD_ARG;
@@ -130,7 +131,7 @@ line_profile_factor
intensity_ref = shtr_line->intensity/isotope->abundance*iso_abundance;
}
intensity = line_intensity(intensity_ref, shtr_line->lower_state_energy, Q,
- tree->temperature, T_REF, nu_c);
+ mixture->temperature, T_REF, nu_c);
profile_factor = 1.e2 * density * intensity; /* In m^-1.cm^-1 */
@@ -178,7 +179,7 @@ error:
* only the set of wavenumbers from the line center to its upper bound. */
static res_T
regular_mesh_fragmented
- (const struct sln_tree* tree,
+ (const struct sln_mixture* mixture,
const struct line* line,
const struct molecule_params* mol_params,
const double fragment_length,
@@ -194,11 +195,11 @@ regular_mesh_fragmented
double line_nu_max = 0; /* In cm^-1 */
res_T res = RES_OK;
- ASSERT(tree && line && mol_params && wavenumbers);
+ ASSERT(mixture && line && mol_params && wavenumbers);
ASSERT(fragment_length > 0);
ASSERT(IS_POW2(nvertices));
- ASSERT(line->wavenumber + mol_params->cutoff > tree->wavenumber_range[0]);
- ASSERT(line->wavenumber - mol_params->cutoff < tree->wavenumber_range[1]);
+ ASSERT(line->wavenumber + mol_params->cutoff > mixture->wavenumber_range[0]);
+ ASSERT(line->wavenumber - mol_params->cutoff < mixture->wavenumber_range[1]);
/* Compute the spectral range of the line from its center to its cutoff */
line_nu_min = line->wavenumber;
@@ -227,13 +228,13 @@ regular_mesh_fragmented
exit:
return res;
error:
- log_err(tree->sln, "Error meshing the line -- %s.\n", res_to_cstr(res));
+ log_err(mixture->sln, "Error meshing the line -- %s.\n", res_to_cstr(res));
goto exit;
}
static res_T
eval_mesh
- (const struct sln_tree* tree,
+ (const struct sln_mixture* mixture,
const size_t iline,
const struct darray_double* wavenumbers,
struct darray_double* values)
@@ -243,7 +244,7 @@ eval_mesh
double range[2];
double cutoff;
res_T res = RES_OK;
- ASSERT(tree && wavenumbers && values);
+ ASSERT(mixture && wavenumbers && values);
nvertices = darray_double_size_get(wavenumbers);
ASSERT(nvertices);
@@ -251,7 +252,7 @@ eval_mesh
res = darray_double_resize(values, nvertices);
if(res != RES_OK) goto error;
- SHTR(lines_view_get_line(tree->lines_view, iline, &shtr_line));
+ SHTR(lines_view_get_line(mixture->lines_view, iline, &shtr_line));
/* Calculate the spectral range in which the vertices should be evaluated.
* Recall that a line being symmetrical in its center, we will only evaluate
@@ -260,22 +261,22 @@ eval_mesh
* to emit all the vertices needed to mesh the upper half _and_ the lower
* half of a possibly clipped line */
cutoff = MMAX
- (shtr_line->wavenumber - tree->wavenumber_range[0],
- tree->wavenumber_range[1] - shtr_line->wavenumber);
- range[0] = MMIN(shtr_line->wavenumber, tree->wavenumber_range[0]);
+ (shtr_line->wavenumber - mixture->wavenumber_range[0],
+ mixture->wavenumber_range[1] - shtr_line->wavenumber);
+ range[0] = MMIN(shtr_line->wavenumber, mixture->wavenumber_range[0]);
range[1] = shtr_line->wavenumber + cutoff;
FOR_EACH(ivertex, 0, nvertices) {
const double nu = darray_double_cdata_get(wavenumbers)[ivertex];
if(nu < range[0]) continue;
if(nu > range[1]) break;
- darray_double_data_get(values)[ivertex] = line_value(tree, iline, nu);
+ darray_double_data_get(values)[ivertex] = line_value(mixture, iline, nu);
}
exit:
return res;
error:
- log_err(tree->sln, "Error evaluating the line mesh -- %s.\n",
+ log_err(mixture->sln, "Error evaluating the line mesh -- %s.\n",
res_to_cstr(res));
goto exit;
}
@@ -302,7 +303,7 @@ save_line_mesh
ASSERT(darray_double_size_get(wavenumbers) == darray_double_size_get(values));
ASSERT(spectral_range && spectral_range[0] <= spectral_range[1]);
- line = darray_line_cdata_get(&tree->lines) + iline;
+ line = darray_line_cdata_get(&tree->mixture->lines) + iline;
nvertices = darray_vertex_size_get(&tree->vertices);
nwavenumbers = darray_double_size_get(wavenumbers);
@@ -314,7 +315,7 @@ save_line_mesh
/* Allocate the list of line vertices */
res = darray_vertex_resize(&tree->vertices, nvertices + line_nvertices);
if(res != RES_OK) {
- log_err(tree->sln, "Error allocating the line vertices -- %s.\n",
+ log_err(tree->mixture->sln, "Error allocating the line vertices -- %s.\n",
res_to_cstr(res));
goto error;
}
@@ -326,7 +327,7 @@ save_line_mesh
if(line->wavenumber - mol_params->cutoff <= spectral_range[0]) {
struct sln_vertex* vtx = darray_vertex_data_get(&tree->vertices) + i;
vtx->wavenumber = (float)spectral_range[0];
- vtx->ka = (float)line_value(tree, iline, vtx->wavenumber);
+ vtx->ka = (float)line_value(tree->mixture, iline, vtx->wavenumber);
++i;
}
@@ -369,7 +370,7 @@ save_line_mesh
if(line->wavenumber + mol_params->cutoff >= spectral_range[1]) {
struct sln_vertex* vtx = darray_vertex_data_get(&tree->vertices) + i;
vtx->wavenumber = (float)spectral_range[1];
- vtx->ka = (float)line_value(tree, iline, vtx->wavenumber);
+ vtx->ka = (float)line_value(tree->mixture, iline, vtx->wavenumber);
++i;
}
@@ -394,7 +395,7 @@ error:
* Local function
******************************************************************************/
res_T
-line_setup(struct sln_tree* tree, const size_t iline)
+line_setup(struct sln_mixture* mixture, const size_t iline)
{
struct shtr_molecule molecule = SHTR_MOLECULE_NULL;
const struct shtr_line* shtr_line = NULL;
@@ -402,29 +403,29 @@ line_setup(struct sln_tree* tree, const size_t iline)
double molar_mass = 0; /* In kg.mol^-1 */
const struct molecule_params* mol_params = NULL;
res_T res = RES_OK;
- ASSERT(tree && iline < darray_line_size_get(&tree->lines));
+ ASSERT(mixture && iline < darray_line_size_get(&mixture->lines));
- line = darray_line_data_get(&tree->lines) + iline;
+ line = darray_line_data_get(&mixture->lines) + iline;
- SHTR(lines_view_get_line(tree->lines_view, iline, &shtr_line));
+ SHTR(lines_view_get_line(mixture->lines_view, iline, &shtr_line));
SHTR(isotope_metadata_find_molecule
- (tree->metadata, shtr_line->molecule_id, &molecule));
+ (mixture->metadata, shtr_line->molecule_id, &molecule));
ASSERT(!SHTR_MOLECULE_IS_NULL(&molecule));
ASSERT(molecule.nisotopes > (size_t)shtr_line->isotope_id_local);
- mol_params = tree_get_molecule_params(tree, shtr_line->molecule_id);
+ mol_params = mixture_get_molecule_params(mixture, shtr_line->molecule_id);
/* Convert the molar mass of the line from g.mol^-1 to kg.mol^-1 */
molar_mass = molecule.isotopes[shtr_line->isotope_id_local].molar_mass*1e-3;
/* Setup the line */
- res = line_profile_factor(tree, shtr_line, &line->profile_factor);
+ res = line_profile_factor(mixture, shtr_line, &line->profile_factor);
if(res != RES_OK) goto error;
- line->wavenumber = line_center(shtr_line, tree->pressure);
+ line->wavenumber = line_center(shtr_line, mixture->pressure);
line->gamma_d = sln_compute_line_half_width_doppler
- (line->wavenumber, molar_mass, tree->temperature);
+ (line->wavenumber, molar_mass, mixture->temperature);
line->gamma_l = sln_compute_line_half_width_lorentz(shtr_line->gamma_air,
- shtr_line->gamma_self, tree->pressure, mol_params->concentration);
+ shtr_line->gamma_self, mixture->pressure, mol_params->concentration);
exit:
return res;
@@ -434,20 +435,20 @@ error:
double
line_value
- (const struct sln_tree* tree,
+ (const struct sln_mixture* mixture,
const size_t iline,
const double wavenumber)
{
const struct line* line = NULL;
const struct shtr_line* shtr_line = NULL;
const struct molecule_params* mol_params = NULL;
- ASSERT(tree && iline < darray_line_size_get(&tree->lines));
+ ASSERT(mixture && iline < darray_line_size_get(&mixture->lines));
/* Retrieve the molecular parameters of the line to be mesh */
- SHTR(lines_view_get_line(tree->lines_view, iline, &shtr_line));
- mol_params = tree_get_molecule_params(tree, shtr_line->molecule_id);
+ SHTR(lines_view_get_line(mixture->lines_view, iline, &shtr_line));
+ mol_params = mixture_get_molecule_params(mixture, shtr_line->molecule_id);
- line = darray_line_cdata_get(&tree->lines) + iline;
+ line = darray_line_cdata_get(&mixture->lines) + iline;
if(wavenumber < line->wavenumber - mol_params->cutoff
|| wavenumber > line->wavenumber + mol_params->cutoff) {
@@ -474,13 +475,13 @@ line_mesh
size_t nvertices_adjusted = 0; /* computed from nvertices_hint */
res_T res = RES_OK;
ASSERT(tree && nvertices_hint);
- ASSERT(iline < darray_line_size_get(&tree->lines));
+ ASSERT(iline < darray_line_size_get(&tree->mixture->lines));
- line = darray_line_cdata_get(&tree->lines) + iline;
- SHTR(lines_view_get_line(tree->lines_view, iline, &shtr_line));
+ line = darray_line_cdata_get(&tree->mixture->lines) + iline;
+ SHTR(lines_view_get_line(tree->mixture->lines_view, iline, &shtr_line));
- darray_double_init(tree->sln->allocator, &values);
- darray_double_init(tree->sln->allocator, &wavenumbers);
+ darray_double_init(tree->mixture->sln->allocator, &values);
+ darray_double_init(tree->mixture->sln->allocator, &wavenumbers);
/* Adjust the hint on the number of vertices. This is not actually the real
* number of vertices but a adjusted hint on it. This new value ensures that
@@ -490,18 +491,18 @@ line_mesh
nvertices_adjusted = round_up_pow2(nvertices_adjusted);
/* Retrieve the molecular parameters of the line to be mesh */
- mol_params = tree_get_molecule_params(tree, shtr_line->molecule_id);
+ mol_params = mixture_get_molecule_params(tree->mixture, shtr_line->molecule_id);
/* Emit the vertex coordinates, i.e. the wavenumbers */
- res = regular_mesh_fragmented
- (tree, line, mol_params, line->gamma_l, nvertices_adjusted, &wavenumbers);
+ res = regular_mesh_fragmented(tree->mixture, line, mol_params, line->gamma_l,
+ nvertices_adjusted, &wavenumbers);
if(res != RES_OK) goto error;
/* Evaluate the mesh vertices, i.e. define the line value for the list of
* wavenumbers */
- eval_mesh(tree, iline, &wavenumbers, &values);
+ eval_mesh(tree->mixture, iline, &wavenumbers, &values);
- res = save_line_mesh(tree, iline, mol_params, tree->wavenumber_range,
+ res = save_line_mesh(tree, iline, mol_params, tree->mixture->wavenumber_range,
&wavenumbers, &values, vertices_range);
if(res != RES_OK) goto error;
diff --git a/src/sln_line.h b/src/sln_line.h
@@ -31,6 +31,7 @@ struct line {
};
/* Forward declaration */
+struct sln_mixture;
struct sln_tree;
struct darray_vertex;
@@ -45,12 +46,12 @@ line_center
extern LOCAL_SYM res_T
line_setup
- (struct sln_tree* tree,
+ (struct sln_mixture* mixture,
const size_t iline);
extern LOCAL_SYM double
line_value
- (const struct sln_tree* tree,
+ (const struct sln_mixture* mixture,
const size_t iline,
const double wavenumber);
diff --git a/src/sln_mixture.c b/src/sln_mixture.c
@@ -0,0 +1,416 @@
+/* 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 "sln.h"
+#include "sln_device_c.h"
+#include "sln_log.h"
+#include "sln_mixture_c.h"
+
+#include <star/shtr.h>
+
+STATIC_ASSERT(SLN_MAX_MOLECULES_COUNT <= SHTR_MAX_MOLECULES_COUNT,
+ Invalid_SLN_MAX_MOLECULES_COUNT);
+STATIC_ASSERT(SLN_MAX_ISOTOPES_COUNT <= SHTR_MAX_ISOTOPES_COUNT,
+ Invalid_SLN_MAX_ISOTOPES_COUNT);
+
+/*******************************************************************************
+ * Helper functions
+ ******************************************************************************/
+static res_T
+check_sln_isotope
+ (struct sln_device* sln,
+ const char* caller,
+ const int32_t mol_id,
+ const size_t mol_nisos,
+ const struct sln_isotope* isotope)
+{
+ ASSERT(sln && caller && mol_nisos && isotope);
+
+ if(isotope->id_local >= SLN_MAX_ISOTOPES_COUNT) {
+ log_err(sln,
+ "%s: molecule %d: isotope %d: invalid isotope local identifier. "
+ "It must be less than %d.\n",
+ caller, mol_id, isotope->id_local, SLN_MAX_ISOTOPES_COUNT);
+ return RES_BAD_ARG;
+ }
+
+ if((size_t)isotope->id_local >= mol_nisos) {
+ log_warn(sln,
+ "%s: molecule %d: the isotope local index %d exceeds "
+ "the overall number of isotopes %lu.\n",
+ caller, mol_id, isotope->id_local, mol_nisos);
+ return RES_OK; /* Do not check the others isotope parameters */
+ }
+
+ if(isotope->abundance < 0) {
+ log_err(sln,
+ "%s: molecule %d: isotope %d: invalid abundance %g.\n",
+ caller, mol_id, isotope->id_local, isotope->abundance);
+ return RES_BAD_ARG;
+ }
+
+ return RES_OK;
+}
+
+static res_T
+check_sln_molecule
+ (struct sln_device* sln,
+ const char* caller,
+ struct shtr_isotope_metadata* metadata,
+ const struct sln_molecule* molecule)
+{
+ double abundances_sum = 0;
+ struct shtr_molecule mol = SHTR_MOLECULE_NULL;
+ size_t i;
+ ASSERT(sln && caller && metadata && molecule);
+
+ if(molecule->id >= SLN_MAX_MOLECULES_COUNT) {
+ log_err(sln,
+ "%s: molecule %d: invalid molecule indentifier. It must be less than %d.\n",
+ caller, molecule->id, SLN_MAX_MOLECULES_COUNT);
+ return RES_BAD_ARG;
+ }
+
+ SHTR(isotope_metadata_find_molecule(metadata, molecule->id, &mol));
+ if(SHTR_MOLECULE_IS_NULL(&mol)) {
+ log_warn(sln,
+ "%s: the molecule %d is not found in the isotope metadata.\n",
+ caller, molecule->id);
+ return RES_OK; /* Do not check the others molecule parameters */
+ }
+
+ if(molecule->nisotopes >= SLN_MAX_ISOTOPES_COUNT) {
+ log_err(sln,
+ "%s: too many isotopes %lu regarding the maximum number of per molecule "
+ "isotopes (SLN_MAX_ISOTOPES_COUNT = %lu).\n",
+ caller,
+ (unsigned long)molecule->nisotopes,
+ (unsigned long)SLN_MAX_ISOTOPES_COUNT);
+ return RES_BAD_ARG;
+ }
+
+ abundances_sum = 0;
+ FOR_EACH(i, 0, molecule->nisotopes) {
+ const res_T res = check_sln_isotope
+ (sln, caller, molecule->id, molecule->nisotopes, molecule->isotopes+i);
+ if(res != RES_OK) return res;
+ abundances_sum += molecule->isotopes[i].abundance;
+ }
+
+ if(abundances_sum > 1) {
+ log_err(sln,
+ "%s: molecule %d: the sum of the isotope abundances %g is invalid. "
+ "It must be less than or equal to 1.\n",
+ caller, molecule->id, abundances_sum);
+ return RES_BAD_ARG;
+ }
+
+ if(molecule->concentration < 0) {
+ log_err(sln, "%s: molecule %d: invalid concentration %g.\n",
+ caller, molecule->id, molecule->concentration);
+ return RES_BAD_ARG;
+ }
+
+ if(molecule->cutoff <= 0) {
+ log_err(sln, "%s: molecule %d: invalid line cutoff %g.\n",
+ caller, molecule->id, molecule->concentration);
+ return RES_BAD_ARG;
+ }
+
+ return RES_OK;
+}
+
+static res_T
+check_sln_mixture_create_args
+ (struct sln_device* sln,
+ const char* caller,
+ const struct sln_mixture_create_args* args)
+{
+ double concentrations_sum = 0;
+ size_t i;
+ ASSERT(sln && caller);
+ if(!args) return RES_BAD_ARG;
+
+ /* Check lines data base */
+ if(!args->metadata || !args->lines) {
+ return RES_BAD_ARG;
+ }
+
+ /* Check the list of molecules to be taken into account */
+ if(args->nmolecules >= SLN_MAX_MOLECULES_COUNT) {
+ log_err(sln,
+ "%s: too many molecules %lu regarding the maximum number of molecules "
+ "(SLN_MAX_MOLECULES_COUNT = %lu).\n",
+ caller,
+ (unsigned long)args->nmolecules,
+ (unsigned long)SLN_MAX_MOLECULES_COUNT);
+ return RES_BAD_ARG;
+ }
+
+ concentrations_sum = 0;
+ FOR_EACH(i, 0, args->nmolecules) {
+ const res_T res = check_sln_molecule
+ (sln, caller, args->metadata, args->molecules+i);
+ if(res != RES_OK) return res;
+ concentrations_sum += args->molecules[i].concentration;
+ }
+
+ if(concentrations_sum > 1) {
+ log_err(sln,
+ "%s: the sum of the molecule concentrations %g is invalid. "
+ "It must be less than or equal to 1.\n",
+ caller, concentrations_sum);
+ return RES_BAD_ARG;
+ }
+
+ if(args->pressure < 0) {
+ log_err(sln, "%s: invalid pressure %g.\n", caller, args->pressure);
+ return RES_BAD_ARG;
+ }
+
+ if(args->temperature < 0) {
+ log_err(sln, "%s: invalid temperature %g.\n", caller, args->temperature);
+ return RES_BAD_ARG;
+ }
+
+ return RES_OK;
+}
+
+static res_T
+create_lines_view
+ (struct sln_device* sln,
+ const struct sln_mixture_create_args* mixture_args,
+ struct shtr_lines_view** out_view)
+{
+ struct shtr_lines_view_create_args view_args = SHTR_LINES_VIEW_CREATE_ARGS_NULL;
+ struct shtr_lines_view* view = NULL;
+ size_t imol, iiso;
+ res_T res = RES_OK;
+ (void)sln;
+
+ ASSERT(sln && mixture_args && out_view);
+
+ view_args.wavenumber_range[0] = mixture_args->wavenumber_range[0];
+ view_args.wavenumber_range[1] = mixture_args->wavenumber_range[1];
+ view_args.nmolecules = mixture_args->nmolecules;
+
+ FOR_EACH(imol, 0, mixture_args->nmolecules) {
+ struct shtr_isotope_selection* view_mol = view_args.molecules + imol;
+ const struct sln_molecule* mixture_mol = mixture_args->molecules + imol;
+
+ view_mol->id = mixture_mol->id;
+ view_mol->nisotopes = mixture_mol->nisotopes;
+ FOR_EACH(iiso, 0, mixture_mol->nisotopes) {
+ view_mol->isotope_ids_local[iiso] = mixture_mol->isotopes[iiso].id_local;
+ }
+ }
+
+ /* FIXME we have to handle the lines whose center +/- cutoff intersect the
+ * spectral range. Currently Star-HITRAN only selects the lines whose center
+ * is included into the spectral range. One has to fix this! */
+ res = shtr_lines_view_create(mixture_args->lines, &view_args, &view);
+ if(res != RES_OK) goto error;
+
+exit:
+ *out_view = view;
+ return res;
+error:
+ if(view) { SHTR(lines_view_ref_put(view)); view = NULL; }
+ goto exit;
+}
+
+static void
+molecules_params_reset(struct molecule_params params[SLN_MAX_MOLECULES_COUNT])
+{
+ size_t imol;
+ ASSERT(params);
+
+ /* Clean up the params */
+ FOR_EACH(imol, 0, SLN_MAX_MOLECULES_COUNT) {
+ size_t iiso;
+ params[imol].concentration = -1;
+ params[imol].cutoff = -1;
+ FOR_EACH(iiso, 0, SLN_MAX_ISOTOPES_COUNT) {
+ params[imol].isotopes_abundance[iiso] = -1;
+ }
+ }
+}
+
+static res_T
+setup_molecule_params
+ (struct sln_device* sln,
+ const struct sln_mixture_create_args* args,
+ struct molecule_params params[SLN_MAX_MOLECULES_COUNT])
+{
+ size_t imol;
+ ASSERT(sln && args && params);
+ (void)sln;
+
+ molecules_params_reset(params);
+
+ FOR_EACH(imol, 0, args->nmolecules) {
+ const struct sln_molecule* mol = &args->molecules[imol];
+ size_t iiso;
+ ASSERT(mol->id < SLN_MAX_MOLECULES_COUNT);
+
+ params[mol->id].concentration = mol->concentration;
+ params[mol->id].cutoff = mol->cutoff;
+ FOR_EACH(iiso, 0, mol->nisotopes) {
+ const struct sln_isotope* iso = &mol->isotopes[iiso];
+ ASSERT(iso->id_local < SLN_MAX_ISOTOPES_COUNT);
+
+ params[mol->id].isotopes_abundance[iso->id_local] = iso->abundance;
+ }
+ }
+
+ return RES_OK;
+}
+
+static INLINE res_T
+store_input_args
+ (struct sln_device* sln,
+ const struct sln_mixture_create_args* args,
+ struct sln_mixture* mixture)
+{
+ ASSERT(sln && args && mixture);
+ (void)sln;
+ mixture->wavenumber_range[0] = args->wavenumber_range[0];
+ mixture->wavenumber_range[1] = args->wavenumber_range[1];
+ mixture->temperature = args->temperature;
+ mixture->pressure = args->pressure;
+ SHTR(isotope_metadata_ref_get(args->metadata));
+ mixture->metadata = args->metadata;
+ return RES_OK;
+}
+
+static res_T
+setup_lines(struct sln_mixture* mixture, const char* caller)
+{
+ size_t iline, nlines;
+ res_T res = RES_OK;
+ ASSERT(mixture && caller);
+
+ SHTR(lines_view_get_size(mixture->lines_view, &nlines));
+
+ res = darray_line_resize(&mixture->lines, nlines);
+ if(res != RES_OK) {
+ log_err(mixture->sln,
+ "%s: error allocating the list of precomputed line data.\n",
+ caller);
+ goto error;
+ }
+
+ FOR_EACH(iline, 0, nlines) {
+ res = line_setup(mixture, iline);
+ if(res != RES_OK) goto error;
+ }
+
+exit:
+ return res;
+error:
+ darray_line_clear(&mixture->lines);
+ goto exit;
+}
+
+
+static void
+release_mixture(ref_T* ref)
+{
+ struct sln_mixture* mixture = CONTAINER_OF(ref, struct sln_mixture, ref);
+ struct sln_device* sln = NULL;
+ ASSERT(ref);
+ sln = mixture->sln;
+ if(mixture->metadata) SHTR(isotope_metadata_ref_put(mixture->metadata));
+ if(mixture->lines_view) SHTR(lines_view_ref_put(mixture->lines_view));
+ darray_line_release(&mixture->lines);
+ MEM_RM(sln->allocator, mixture);
+ SLN(device_ref_put(sln));
+}
+
+/*******************************************************************************
+ * Exported functions
+ ******************************************************************************/
+res_T
+sln_mixture_create
+ (struct sln_device* sln,
+ const struct sln_mixture_create_args* args,
+ struct sln_mixture** out_mixture)
+{
+ struct sln_mixture* mixture = NULL;
+ res_T res = RES_OK;
+
+ if(!sln || !out_mixture) { res = RES_BAD_ARG; goto error; }
+ res = check_sln_mixture_create_args(sln, FUNC_NAME, args);
+ if(res != RES_OK) goto error;
+
+ mixture = MEM_CALLOC(sln->allocator, 1, sizeof(struct sln_mixture));
+ if(!mixture) {
+ log_err(sln, "%s: could not allocate the mixture data structure.\n",
+ FUNC_NAME);
+ res = RES_MEM_ERR;
+ goto error;
+ }
+ ref_init(&mixture->ref);
+ SLN(device_ref_get(sln));
+ mixture->sln = sln;
+ darray_line_init(sln->allocator, &mixture->lines);
+
+ #define CALL(Func) { if(RES_OK != (res = Func)) goto error; } (void)0
+ CALL(create_lines_view(sln, args, &mixture->lines_view));
+ CALL(setup_molecule_params(sln, args, mixture->molecules_params));
+ CALL(store_input_args(sln, args, mixture));
+ CALL(setup_lines(mixture, FUNC_NAME));
+ #undef CALL
+
+exit:
+ if(out_mixture) *out_mixture = mixture;
+ return res;
+error:
+ if(mixture) { SLN(mixture_ref_put(mixture)); mixture = NULL; }
+ goto exit;
+}
+
+res_T
+sln_mixture_ref_get(struct sln_mixture* mixture)
+{
+ if(!mixture) return RES_BAD_ARG;
+ ref_get(&mixture->ref);
+ return RES_OK;
+}
+
+res_T
+sln_mixture_ref_put(struct sln_mixture* mixture)
+{
+ if(!mixture) return RES_BAD_ARG;
+ ref_put(&mixture->ref, release_mixture);
+ return RES_OK;
+}
+
+res_T
+sln_mixture_get_desc
+ (const struct sln_mixture* mixture,
+ struct sln_mixture_desc* desc)
+{
+ if(!mixture || !desc) return RES_BAD_ARG;
+ desc->wavenumber_range[0] = mixture->wavenumber_range[0];
+ desc->wavenumber_range[1] = mixture->wavenumber_range[1];
+ desc->temperature = mixture->temperature;
+ desc->pressure = mixture->pressure;
+ desc->nlines = darray_line_size_get(&mixture->lines);
+ return RES_OK;
+}
diff --git a/src/sln_mixture_c.h b/src/sln_mixture_c.h
@@ -0,0 +1,72 @@
+/* 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 SLN_MIXTURE_C_H
+#define SLN_MIXTURE_C_H
+
+#include "sln.h"
+#include "sln_line.h"
+
+#include <rsys/dynamic_array.h>
+#include <rsys/ref_count.h>
+
+struct sln_device;
+struct shtr_lines_view;
+
+/* Generate the dynamic array of lines */
+#define DARRAY_DATA struct line
+#define DARRAY_NAME line
+#include <rsys/dynamic_array.h>
+
+struct molecule_params {
+ /* Map the isotope local identifier to its abundance */
+ double isotopes_abundance[SLN_MAX_ISOTOPES_COUNT];
+
+ double concentration;
+ double cutoff;
+};
+
+struct sln_mixture {
+ /* Map the molecule id to its parameters (i.e. concentration, cutoff,
+ * isotopes abundance) */
+ struct molecule_params molecules_params[SLN_MAX_MOLECULES_COUNT];
+
+ struct shtr_isotope_metadata* metadata;
+ struct shtr_lines_view* lines_view; /* Set of lines */
+
+ /* Store per line precomputed data */
+ struct darray_line lines;
+
+ double temperature; /* In Kelvin */
+ double pressure; /* In atm */
+ double wavenumber_range[2]; /* Spectral range [cm^-1] */
+
+ struct sln_device* sln;
+ ref_T ref;
+};
+
+static INLINE const struct molecule_params*
+mixture_get_molecule_params
+ (const struct sln_mixture* mixture,
+ const int32_t molecules_id)
+{
+ ASSERT(mixture && molecules_id >= 0 && molecules_id < SLN_MAX_MOLECULES_COUNT);
+ return mixture->molecules_params + molecules_id;
+}
+
+#endif /* SLN_MIXTURE_C_H */
diff --git a/src/sln_tree.c b/src/sln_tree.c
@@ -19,354 +19,77 @@
#include "sln.h"
#include "sln_device_c.h"
#include "sln_log.h"
+#include "sln_mixture_c.h"
#include "sln_tree_c.h"
#include <star/shtr.h>
-STATIC_ASSERT(SLN_MAX_MOLECULES_COUNT <= SHTR_MAX_MOLECULES_COUNT,
- Invalid_SLN_MAX_MOLECULES_COUNT);
-STATIC_ASSERT(SLN_MAX_ISOTOPES_COUNT <= SHTR_MAX_ISOTOPES_COUNT,
- Invalid_SLN_MAX_ISOTOPES_COUNT);
-
/*******************************************************************************
* Helper functions
******************************************************************************/
static res_T
-check_sln_isotope
- (struct sln_device* sln,
- const char* func_name,
- const int32_t mol_id,
- const size_t mol_nisos,
- const struct sln_isotope* isotope)
-{
- ASSERT(sln && func_name && mol_nisos && isotope);
-
- if(isotope->id_local >= SLN_MAX_ISOTOPES_COUNT) {
- log_err(sln,
- "%s: molecule %d: isotope %d: invalid isotope local identifier. "
- "It must be less than %d.\n",
- func_name, mol_id, isotope->id_local, SLN_MAX_ISOTOPES_COUNT);
- return RES_BAD_ARG;
- }
-
- if((size_t)isotope->id_local >= mol_nisos) {
- log_warn(sln,
- "%s: molecule %d: the isotope local index %d exceeds "
- "the overall number of isotopes %lu.\n",
- func_name, mol_id, isotope->id_local, mol_nisos);
- return RES_OK; /* Do not check the others isotope parameters */
- }
-
- if(isotope->abundance < 0) {
- log_err(sln,
- "%s: molecule %d: isotope %d: invalid abundance %g.\n",
- func_name, mol_id, isotope->id_local, isotope->abundance);
- return RES_BAD_ARG;
- }
-
- return RES_OK;
-}
-
-static res_T
-check_sln_molecule
- (struct sln_device* sln,
- const char* func_name,
- struct shtr_isotope_metadata* metadata,
- const struct sln_molecule* molecule)
-{
- double abundances_sum = 0;
- struct shtr_molecule mol = SHTR_MOLECULE_NULL;
- size_t i;
- ASSERT(sln && func_name && metadata && molecule);
-
- if(molecule->id >= SLN_MAX_MOLECULES_COUNT) {
- log_err(sln,
- "%s: molecule %d: invalid molecule indentifier. It must be less than %d.\n",
- func_name, molecule->id, SLN_MAX_MOLECULES_COUNT);
- return RES_BAD_ARG;
- }
-
- SHTR(isotope_metadata_find_molecule(metadata, molecule->id, &mol));
- if(SHTR_MOLECULE_IS_NULL(&mol)) {
- log_warn(sln,
- "%s: the molecule %d is not found in the isotope metadata.\n",
- func_name, molecule->id);
- return RES_OK; /* Do not check the others molecule parameters */
- }
-
- if(molecule->nisotopes >= SLN_MAX_ISOTOPES_COUNT) {
- log_err(sln,
- "%s: too many isotopes %lu regarding the maximum number of per molecule "
- "isotopes (SLN_MAX_ISOTOPES_COUNT = %lu).\n",
- func_name,
- (unsigned long)molecule->nisotopes,
- (unsigned long)SLN_MAX_ISOTOPES_COUNT);
- return RES_BAD_ARG;
- }
-
- abundances_sum = 0;
- FOR_EACH(i, 0, molecule->nisotopes) {
- const res_T res = check_sln_isotope
- (sln, func_name, molecule->id, molecule->nisotopes, molecule->isotopes+i);
- if(res != RES_OK) return res;
- abundances_sum += molecule->isotopes[i].abundance;
- }
-
- if(abundances_sum > 1) {
- log_err(sln,
- "%s: molecule %d: the sum of the isotope abundances %g is invalid. "
- "It must be less than or equal to 1.\n",
- func_name, molecule->id, abundances_sum);
- return RES_BAD_ARG;
- }
-
- if(molecule->concentration < 0) {
- log_err(sln, "%s: molecule %d: invalid concentration %g.\n",
- func_name, molecule->id, molecule->concentration);
- return RES_BAD_ARG;
- }
-
- if(molecule->cutoff <= 0) {
- log_err(sln, "%s: molecule %d: invalid line cutoff %g.\n",
- func_name, molecule->id, molecule->concentration);
- return RES_BAD_ARG;
- }
-
- return RES_OK;
-}
-
-static res_T
check_sln_tree_create_args
(struct sln_device* sln,
- const char* func_name,
+ const char* caller,
const struct sln_tree_create_args* args)
{
- double concentrations_sum = 0;
- size_t i;
- ASSERT(sln && func_name);
+ ASSERT(sln && caller);
if(!args) return RES_BAD_ARG;
- /* Check lines data base */
- if(!args->metadata || !args->lines) {
- return RES_BAD_ARG;
- }
-
- /* Check the list of molecules to be taken into account */
- if(args->nmolecules >= SLN_MAX_MOLECULES_COUNT) {
- log_err(sln,
- "%s: too many molecules %lu regarding the maximum number of molecules "
- "(SLN_MAX_MOLECULES_COUNT = %lu).\n",
- func_name,
- (unsigned long)args->nmolecules,
- (unsigned long)SLN_MAX_MOLECULES_COUNT);
- return RES_BAD_ARG;
- }
-
- concentrations_sum = 0;
- FOR_EACH(i, 0, args->nmolecules) {
- const res_T res = check_sln_molecule
- (sln, func_name, args->metadata, args->molecules+i);
- if(res != RES_OK) return res;
- concentrations_sum += args->molecules[i].concentration;
- }
-
- if(concentrations_sum > 1) {
- log_err(sln,
- "%s: the sum of the molecule concentrations %g is invalid. "
- "It must be less than or equal to 1.\n",
- func_name, concentrations_sum);
- return RES_BAD_ARG;
- }
-
- if(args->pressure < 0) {
- log_err(sln, "%s: invalid pressure %g.\n", func_name, args->pressure);
- return RES_BAD_ARG;
- }
-
- if(args->temperature < 0) {
- log_err(sln, "%s: invalid temperature %g.\n", func_name, args->temperature);
- return RES_BAD_ARG;
- }
-
- if(args->max_nlines_per_leaf == 0) {
- log_err(sln, "%s: invalid maximum number of lines per leaf %lu.\n",
- func_name, (unsigned long)args->max_nlines_per_leaf);
+ /* Currently only 1 line per leaf is accepted */
+ if(args->max_nlines_per_leaf != 1) {
+ log_err(sln,
+ "%s: invalid maximum number of lines per leaf %lu. "
+ "Currently it must be set to 1.\n",
+ caller, (unsigned long)args->max_nlines_per_leaf);
return RES_BAD_ARG;
}
if(args->nvertices_hint == 0) {
log_err(sln,
"%s: invalid hint on the number of vertices around the line center %lu.\n",
- func_name, (unsigned long)args->nvertices_hint);
+ caller, (unsigned long)args->nvertices_hint);
return RES_BAD_ARG;
}
if(args->mesh_decimation_err < 0) {
log_err(sln, "%s: invalid decimation error %g.\n",
- func_name, args->mesh_decimation_err);
+ caller, args->mesh_decimation_err);
return RES_BAD_ARG;
}
if((unsigned)args->line_profile >= SLN_LINE_PROFILES_COUNT__) {
log_err(sln, "%s: invalid line profile %d.\n",
- func_name, args->line_profile);
+ caller, args->line_profile);
return RES_BAD_ARG;
}
return RES_OK;
}
-static res_T
-create_lines_view
- (struct sln_device* sln,
- const struct sln_tree_create_args* tree_args,
- struct shtr_lines_view** out_view)
-{
- struct shtr_lines_view_create_args view_args = SHTR_LINES_VIEW_CREATE_ARGS_NULL;
- struct shtr_lines_view* view = NULL;
- size_t imol, iiso;
- res_T res = RES_OK;
- (void)sln;
-
- ASSERT(sln && tree_args && out_view);
-
- view_args.wavenumber_range[0] = tree_args->wavenumber_range[0];
- view_args.wavenumber_range[1] = tree_args->wavenumber_range[1];
- view_args.nmolecules = tree_args->nmolecules;
-
- FOR_EACH(imol, 0, tree_args->nmolecules) {
- struct shtr_isotope_selection* view_mol = view_args.molecules + imol;
- const struct sln_molecule* tree_mol = tree_args->molecules + imol;
-
- view_mol->id = tree_mol->id;
- view_mol->nisotopes = tree_mol->nisotopes;
- FOR_EACH(iiso, 0, tree_mol->nisotopes) {
- view_mol->isotope_ids_local[iiso] = tree_mol->isotopes[iiso].id_local;
- }
- }
-
- /* FIXME we have to handle the lines whose center +/- cutoff intersect the
- * spectral range. Currently Star-HITRAN only selects the lines whose center
- * is included into the spectral range. One has to fix this! */
- res = shtr_lines_view_create(tree_args->lines, &view_args, &view);
- if(res != RES_OK) goto error;
-
-exit:
- *out_view = view;
- return res;
-error:
- if(view) { SHTR(lines_view_ref_put(view)); view = NULL; }
- goto exit;
-}
-
-static void
-molecules_params_reset(struct molecule_params params[SLN_MAX_MOLECULES_COUNT])
-{
- size_t imol;
- ASSERT(params);
-
- /* Clean up the params */
- FOR_EACH(imol, 0, SLN_MAX_MOLECULES_COUNT) {
- size_t iiso;
- params[imol].concentration = -1;
- params[imol].cutoff = -1;
- FOR_EACH(iiso, 0, SLN_MAX_ISOTOPES_COUNT) {
- params[imol].isotopes_abundance[iiso] = -1;
- }
- }
-}
-
-static res_T
-setup_molecule_params
- (struct sln_device* sln,
- const struct sln_tree_create_args* args,
- struct molecule_params params[SLN_MAX_MOLECULES_COUNT])
-{
- size_t imol;
- ASSERT(sln && args && params);
- (void)sln;
-
- molecules_params_reset(params);
-
- FOR_EACH(imol, 0, args->nmolecules) {
- const struct sln_molecule* mol = &args->molecules[imol];
- size_t iiso;
- ASSERT(mol->id < SLN_MAX_MOLECULES_COUNT);
-
- params[mol->id].concentration = mol->concentration;
- params[mol->id].cutoff = mol->cutoff;
- FOR_EACH(iiso, 0, mol->nisotopes) {
- const struct sln_isotope* iso = &mol->isotopes[iiso];
- ASSERT(iso->id_local < SLN_MAX_ISOTOPES_COUNT);
-
- params[mol->id].isotopes_abundance[iso->id_local] = iso->abundance;
- }
- }
-
- return RES_OK;
-}
-
static INLINE res_T
store_input_args
- (struct sln_device* sln,
- const struct sln_tree_create_args* args,
- struct sln_tree* tree)
+ (struct sln_tree* tree,
+ const struct sln_tree_create_args* args)
{
- ASSERT(sln && args && tree);
- (void)sln;
- tree->wavenumber_range[0] = args->wavenumber_range[0];
- tree->wavenumber_range[1] = args->wavenumber_range[1];
+ ASSERT(args && tree);
tree->max_nlines_per_leaf = args->max_nlines_per_leaf;
- tree->temperature = args->temperature;
- tree->pressure = args->pressure;
- SHTR(isotope_metadata_ref_get(args->metadata));
- tree->metadata = args->metadata;
+ tree->mesh_decimation_err = args->mesh_decimation_err;
+ tree->line_profile = args->line_profile;
return RES_OK;
}
-static res_T
-setup_lines(struct sln_tree* tree, const char* caller)
-{
- size_t iline, nlines;
- res_T res = RES_OK;
- ASSERT(tree && caller);
-
- SHTR(lines_view_get_size(tree->lines_view, &nlines));
-
- res = darray_line_resize(&tree->lines, nlines);
- if(res != RES_OK) {
- log_err(tree->sln,
- "%s: error allocating the list of precomputed line data.\n",
- caller);
- goto error;
- }
-
- FOR_EACH(iline, 0, nlines) {
- res = line_setup(tree, iline);
- if(res != RES_OK) goto error;
- }
-
-exit:
- return res;
-error:
- darray_line_clear(&tree->lines);
- goto exit;
-}
-
static void
release_tree(ref_T* ref)
{
struct sln_tree* tree = CONTAINER_OF(ref, struct sln_tree, ref);
- struct sln_device* sln = NULL;
+ struct sln_mixture* mixture = NULL;
ASSERT(ref);
- sln = tree->sln;
- if(tree->metadata) SHTR(isotope_metadata_ref_put(tree->metadata));
- if(tree->lines_view) SHTR(lines_view_ref_put(tree->lines_view));
- darray_line_release(&tree->lines);
+ mixture = tree->mixture;
darray_node_release(&tree->nodes);
darray_vertex_release(&tree->vertices);
- MEM_RM(sln->allocator, tree);
- SLN(device_ref_put(sln));
+ MEM_RM(mixture->sln->allocator, tree);
+ SLN(mixture_ref_put(mixture));
}
/*******************************************************************************
@@ -374,36 +97,32 @@ release_tree(ref_T* ref)
******************************************************************************/
res_T
sln_tree_create
- (struct sln_device* sln,
+ (struct sln_mixture* mixture,
const struct sln_tree_create_args* args,
struct sln_tree** out_tree)
{
struct sln_tree* tree = NULL;
res_T res = RES_OK;
- if(!sln || !out_tree) { res = RES_BAD_ARG; goto error; }
- res = check_sln_tree_create_args(sln, FUNC_NAME, args);
+ if(!mixture || !out_tree) { res = RES_BAD_ARG; goto error; }
+ res = check_sln_tree_create_args(mixture->sln, FUNC_NAME, args);
if(res != RES_OK) goto error;
- tree = MEM_CALLOC(sln->allocator, 1, sizeof(struct sln_tree));
+ tree = MEM_CALLOC(mixture->sln->allocator, 1, sizeof(struct sln_tree));
if(!tree) {
- log_err(sln, "%s: could not allocate the tree data structure.\n",
+ log_err(mixture->sln, "%s: could not allocate the tree data structure.\n",
FUNC_NAME);
res = RES_MEM_ERR;
goto error;
}
ref_init(&tree->ref);
- SLN(device_ref_get(sln));
- tree->sln = sln;
- darray_line_init(sln->allocator, &tree->lines);
- darray_node_init(sln->allocator, &tree->nodes);
- darray_vertex_init(sln->allocator, &tree->vertices);
+ SLN(mixture_ref_get(mixture));
+ tree->mixture = mixture;
+ darray_node_init(mixture->sln->allocator, &tree->nodes);
+ darray_vertex_init(mixture->sln->allocator, &tree->vertices);
#define CALL(Func) { if(RES_OK != (res = Func)) goto error; } (void)0
- CALL(create_lines_view(sln, args, &tree->lines_view));
- CALL(setup_molecule_params(sln, args, tree->molecules_params));
- CALL(store_input_args(sln, args, tree));
- CALL(setup_lines(tree, FUNC_NAME));
+ CALL(store_input_args(tree, args));
CALL(tree_build(tree, args));
#undef CALL
@@ -434,26 +153,11 @@ sln_tree_ref_put(struct sln_tree* tree)
res_T
sln_tree_get_desc(const struct sln_tree* tree, struct sln_tree_desc* desc)
{
- res_T res = RES_OK;
-
- if(!tree || !desc) {
- res = RES_BAD_ARG;
- goto error;
- }
-
- desc->wavenumber_range[0] = tree->wavenumber_range[0];
- desc->wavenumber_range[1] = tree->wavenumber_range[1];
+ if(!tree || !desc) return RES_BAD_ARG;
desc->max_nlines_per_leaf = tree->max_nlines_per_leaf;
- desc->temperature = tree->temperature;
- desc->pressure = tree->pressure;
-
- res = shtr_lines_view_get_size(tree->lines_view, &desc->nlines);
- if(res != RES_OK) goto error;
-
-exit:
- return res;
-error:
- goto exit;
+ desc->mesh_decimation_err = tree->mesh_decimation_err;
+ desc->line_profile = tree->line_profile;
+ return RES_OK;
}
const struct sln_node*
@@ -499,7 +203,7 @@ sln_node_get_line
return RES_BAD_ARG;
return shtr_lines_view_get_line
- (tree->lines_view, node->range[0] + iline, line);
+ (tree->mixture->lines_view, node->range[0] + iline, line);
}
res_T
diff --git a/src/sln_tree_build.c b/src/sln_tree_build.c
@@ -19,6 +19,7 @@
#include "sln.h"
#include "sln_log.h"
#include "sln_polyline.h"
+#include "sln_mixture_c.h"
#include "sln_tree_c.h"
#include <star/shtr.h>
@@ -58,10 +59,11 @@ build_leaf_polyline
if(res != RES_OK) goto error;
/* Decimate the line mesh */
- res = polyline_decimate(tree->sln, darray_vertex_data_get(&tree->vertices),
- vertices_range, args->mesh_decimation_err);
+ res = polyline_decimate
+ (tree->mixture->sln, darray_vertex_data_get(&tree->vertices),
+ vertices_range, args->mesh_decimation_err);
if(res != RES_OK) {
- log_err(tree->sln, "Error while decimating the line mesh -- %s.\n",
+ log_err(tree->mixture->sln, "Error while decimating the line mesh -- %s.\n",
res_to_cstr(res));
goto error;
}
@@ -81,17 +83,17 @@ error:
static INLINE double
compute_ka
- (const struct sln_tree* tree,
+ (const struct sln_mixture* mixture,
const double wavenumber,
const size_t line_range[2])
{
double ka = 0;
size_t iline = 0;
- ASSERT(tree && wavenumber >= 0 && line_range);
+ ASSERT(mixture && wavenumber >= 0 && line_range);
ASSERT(line_range[0] <= line_range[1]);
FOR_EACH(iline, line_range[0], line_range[1]+1) {
- ka += line_value(tree, iline, wavenumber);
+ ka += line_value(mixture, iline, wavenumber);
}
return ka;
}
@@ -119,7 +121,8 @@ merge_node_polylines
/* Allocate the memory space to store the new polyline */
res = darray_vertex_resize(&tree->vertices, vertices_range[1] + 1);
if(res != RES_OK) {
- log_err(tree->sln, "Error in merging polylines -- %s.\n", res_to_cstr(res));
+ log_err(tree->mixture->sln, "Error in merging polylines -- %s.\n",
+ res_to_cstr(res));
goto error;
}
vertices = darray_vertex_data_get(&tree->vertices);
@@ -136,12 +139,12 @@ merge_node_polylines
if(nu0 < nu1) {
/* The vertex comes from the node0 */
nu = vertices[ivtx0].wavenumber;
- ka = (float)(vertices[ivtx0].ka + compute_ka(tree, nu, node1->range));
+ ka = (float)(vertices[ivtx0].ka + compute_ka(tree->mixture, nu, node1->range));
++ivtx0;
} else if(nu0 > nu1) {
/* The vertex comes from the node1 */
nu = vertices[ivtx1].wavenumber;
- ka = (float)(vertices[ivtx1].ka + compute_ka(tree, nu, node0->range));
+ ka = (float)(vertices[ivtx1].ka + compute_ka(tree->mixture, nu, node0->range));
++ivtx1;
} else {
/* The vertex is shared by node0 and node1 */
@@ -156,10 +159,13 @@ merge_node_polylines
}
/* Decimate the resulting polyline */
- res = polyline_decimate(tree->sln, darray_vertex_data_get(&tree->vertices),
- vertices_range, args->mesh_decimation_err);
+ res = polyline_decimate
+ (tree->mixture->sln,
+ darray_vertex_data_get(&tree->vertices),
+ vertices_range,
+ args->mesh_decimation_err);
if(res != RES_OK) {
- log_err(tree->sln, "Error while decimating the line mesh -- %s.\n",
+ log_err(tree->mixture->sln, "Error while decimating the line mesh -- %s.\n",
res_to_cstr(res));
goto error;
}
@@ -250,7 +256,7 @@ partition_lines
res_T res = RES_OK;
ASSERT(tree && args);
- SHTR(lines_view_get_size(tree->lines_view, &nlines));
+ SHTR(lines_view_get_size(tree->mixture->lines_view, &nlines));
#define NODE(Id) (darray_node_data_get(&tree->nodes) + (Id))
#define CREATE_NODE { \
diff --git a/src/sln_tree_c.h b/src/sln_tree_c.h
@@ -25,7 +25,7 @@
#include <rsys/dynamic_array.h>
#include <rsys/ref_count.h>
-struct sln_device;
+struct sln_mixture;
struct sln_tree_create_args;
struct shtr_lines_view;
@@ -39,11 +39,6 @@ struct sln_node { /* 32 Bytes */
#define SLN_NODE_NULL__ {{0,0},0,0,0}
static const struct sln_node SLN_NODE_NULL = SLN_NODE_NULL__;
-/* Generate the dynamic array of lines */
-#define DARRAY_DATA struct line
-#define DARRAY_NAME line
-#include <rsys/dynamic_array.h>
-
/* Generate the dynamic array of nodes */
#define DARRAY_DATA struct sln_node
#define DARRAY_NAME node
@@ -54,34 +49,15 @@ static const struct sln_node SLN_NODE_NULL = SLN_NODE_NULL__;
#define DARRAY_NAME vertex
#include <rsys/dynamic_array.h>
-struct molecule_params {
- /* Map the isotope local identifier to its abundance */
- double isotopes_abundance[SLN_MAX_ISOTOPES_COUNT];
-
- double concentration;
- double cutoff;
-};
-
struct sln_tree {
- /* Map the molecule id to its parameters (i.e. concentration, cutoff,
- * isotopes abundance) */
- struct molecule_params molecules_params[SLN_MAX_MOLECULES_COUNT];
-
- struct shtr_isotope_metadata* metadata;
- struct shtr_lines_view* lines_view; /* Set of lines */
-
- /* Store per line precomputed data */
- struct darray_line lines;
-
struct darray_node nodes; /* Nodes used to partition the lines */
struct darray_vertex vertices; /* List of vertices */
- double temperature; /* In Kelvin */
- double pressure; /* In atm */
- double wavenumber_range[2]; /* Spectral range [cm^-1] */
size_t max_nlines_per_leaf;
+ double mesh_decimation_err;
+ enum sln_line_profile line_profile;
- struct sln_device* sln;
+ struct sln_mixture* mixture;
ref_T ref;
};
@@ -90,13 +66,4 @@ tree_build
(struct sln_tree* tree,
const struct sln_tree_create_args* args);
-static INLINE const struct molecule_params*
-tree_get_molecule_params
- (const struct sln_tree* tree,
- const int32_t molecules_id)
-{
- ASSERT(tree && molecules_id >= 0 && molecules_id < SLN_MAX_MOLECULES_COUNT);
- return tree->molecules_params + molecules_id;
-}
-
#endif /* SLN_TREE_C_H */
diff --git a/src/test_sln_lines.h b/src/test_sln_lines.h
@@ -0,0 +1,197 @@
+/* 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 TEST_SLN_LINES_H
+#define TEST_SLN_LINES_H
+
+#include <star/shtr.h>
+#include <rsys/rsys.h>
+#include <stdio.h>
+
+static const struct shtr_isotope g_H2O_isotopes[] = {
+ {9.97317E-01, 1.7458E+02, 18.010565, 0, 1, 161},
+ {1.99983E-03, 1.7605E+02, 20.014811, 0, 1, 181},
+ {3.71884E-04, 1.0521E+03, 19.014780, 0, 6, 171},
+ {3.10693E-04, 8.6474E+02, 19.016740, 0, 6, 162},
+ {6.23003E-07, 8.7557E+02, 21.020985, 0, 6, 182},
+ {1.15853E-07, 5.2268E+03, 20.020956, 0, 36, 172},
+ {2.41974E-08, 1.0278E+03, 20.022915, 0, 1, 262}
+};
+static const struct shtr_molecule g_H2O = {
+ "H2O", sizeof(g_H2O_isotopes)/sizeof(struct shtr_isotope), g_H2O_isotopes, 1,
+};
+
+static const struct shtr_isotope g_CO2_isotopes[] = {
+ {9.84204E-01, 2.8609E+02, 43.989830, 1, 1, 626},
+ {1.10574E-02, 5.7664E+02, 44.993185, 1, 2, 636},
+ {3.94707E-03, 6.0781E+02, 45.994076, 1, 1, 628},
+ {7.33989E-04, 3.5426E+03, 44.994045, 1, 6, 627},
+ {4.43446E-05, 1.2255E+03, 46.997431, 1, 2, 638},
+ {8.24623E-06, 7.1413E+03, 45.997400, 1, 12, 637},
+ {3.95734E-06, 3.2342E+02, 47.998320, 1, 1, 828},
+ {1.47180E-06, 3.7666E+03, 46.998291, 1, 6, 827},
+ {1.36847E-07, 1.0972E+04, 45.998262, 1, 1, 727},
+ {4.44600E-08, 6.5224E+02, 49.001675, 1, 2, 838},
+ {1.65354E-08, 7.5950E+03, 48.001646, 1, 12, 837},
+ {1.53745E-09, 2.2120E+04, 47.001618, 1, 2, 737}
+};
+static const struct shtr_molecule g_CO2 = {
+ "CO2", sizeof(g_CO2_isotopes)/sizeof(struct shtr_isotope), g_CO2_isotopes, 2,
+};
+
+static const struct shtr_isotope g_O3_isotopes[] = {
+ {9.92901E-01, 3.4750E+03, 47.984745, 2, 1, 666},
+ {3.98194E-03, 7.5846E+03, 49.988991, 2, 1, 668},
+ {1.99097E-03, 3.7030E+03, 49.988991, 2, 1, 686},
+ {7.40475E-04, 4.4044E+04, 48.988960, 2, 6, 667},
+ {3.70237E-04, 2.1742E+04, 48.988960, 2, 6, 676}
+};
+static const struct shtr_molecule g_O3 = {
+ "O3", sizeof(g_O3_isotopes)/sizeof(struct shtr_isotope), g_O3_isotopes, 3
+};
+
+static const struct shtr_line g_lines[] = {
+ {0.00156, 2.685e-36, 0.0695, 0.428, 399.7263, 0.79, 0.000240, 1, 5},
+ {0.03406, 5.898e-37, 0.0883, 0.410, 1711.6192, 0.79, 0.000000, 1, 5},
+ {0.03445, 5.263e-33, 0.0504, 0.329, 1570.0616, 0.79, 0.001940, 1, 3},
+ {0.03628, 9.296e-29, 0.0704, 0.095, 522.5576, 0.81, 0.000000, 3, 0},
+ {0.03671, 2.555e-37, 0.0389, 0.304, 2337.5190, 0.79, 0.002660, 1, 4},
+ {0.08403, 8.190e-33, 0.0753, 0.394, 568.0017, 0.79, 0.002180, 1, 4},
+ {0.08653, 5.376e-29, 0.0691, 0.083, 1061.6864, 0.76, 0.000000, 3, 0},
+ {0.09642, 6.675e-37, 0.0570, 0.351, 2516.3150, 0.79, 0.000000, 1, 4},
+ {0.16772, 2.456e-28, 0.0823, 0.105, 751.2922, 0.77, 0.000000, 3, 0},
+ {0.18582, 5.338e-32, 0.0925, 0.428, 1717.3356, 0.79, 0.004100, 1, 3},
+ {0.19368, 2.553e-32, 0.0901, 0.428, 293.8010, 0.79, 0.001260, 1, 5},
+ {0.19688, 1.447e-31, 0.0901, 0.428, 292.3093, 0.79, 0.001260, 1, 4},
+ {0.19757, 6.063e-29, 0.0681, 0.078, 1401.6146, 0.76, 0.000000, 3, 0},
+ {0.21281, 8.238e-31, 0.0780, 0.103, 127.4733, 0.78, 0.000000, 3, 4},
+ {0.21282, 5.999e-31, 0.0780, 0.103, 127.4733, 0.78, 0.000000, 3, 4},
+ {0.21283, 7.737e-31, 0.0780, 0.103, 127.4733, 0.78, 0.000000, 3, 4},
+ {0.21283, 6.394e-31, 0.0780, 0.103, 127.4733, 0.78, 0.000000, 3, 4},
+ {0.21284, 7.260e-31, 0.0780, 0.103, 127.4732, 0.78, 0.000000, 3, 4},
+ {0.21284, 6.813e-31, 0.0780, 0.103, 127.4733, 0.78, 0.000000, 3, 4},
+ {0.21728, 5.928e-29, 0.0823, 0.105, 1153.4099, 0.77, 0.000000, 3, 0},
+ {0.25818, 3.110e-32, 0.0539, 0.311, 1958.1248, 0.79, 0.008600, 1, 3},
+ {0.26618, 1.468e-32, 0.0801, 0.378, 2118.9452, 0.79, 0.003100, 1, 3},
+ {0.27091, 1.362e-35, 0.0539, 0.311, 1949.2032, 0.79, 0.008600, 1, 5},
+ {0.28910, 2.058e-30, 0.0878, 0.106, 7.8611, 0.76, 0.000000, 3, 3},
+ {0.29412, 8.666e-33, 0.0795, 0.378, 679.8760, 0.79, 0.004170, 1, 5},
+ {0.29477, 1.457e-30, 0.0660, 0.340, 1238.7943, 0.79, 0.007260, 1, 3},
+ {0.29673, 1.609e-30, 0.0773, 0.103, 138.7916, 0.78, 0.000000, 3, 3},
+ {0.29673, 1.195e-30, 0.0773, 0.103, 138.7916, 0.78, 0.000000, 3, 3},
+ {0.29676, 1.268e-30, 0.0773, 0.103, 138.7916, 0.78, 0.000000, 3, 3},
+ {1.46280, 7.205e-26, 0.0696, 0.090, 702.3167, 0.82, 0.000000, 3, 0},
+ {1.46899, 7.847e-28, 0.0704, 0.095, 1557.6290, 0.81, 0.000000, 3, 0},
+ {1.47237, 1.700e-34, 0.0633, 0.297, 2389.2994, 0.79, 0.013980, 1, 4},
+ {1.47273, 1.131e-32, 0.0903, 0.123, 0.7753, 0.69, 0.000814, 2, 2},
+ {1.47863, 5.318e-33, 0.0925, 0.428, 2877.6872, 0.79, 0.006200, 1, 3},
+ {1.48860, 1.058e-27, 0.0760, 0.102, 163.7760, 0.78, 0.000000, 3, 1},
+ {1.49043, 4.787e-31, 0.0773, 0.103, 139.7879, 0.78, 0.000000, 3, 4},
+ {1.49044, 3.139e-29, 0.0773, 0.103, 139.7879, 0.78, 0.000000, 3, 4},
+ {1.49044, 3.332e-29, 0.0773, 0.103, 139.7880, 0.78, 0.000000, 3, 4},
+ {1.49045, 2.785e-29, 0.0773, 0.103, 139.7880, 0.78, 0.000000, 3, 4},
+ {1.49045, 2.625e-29, 0.0773, 0.103, 139.7880, 0.78, 0.000000, 3, 4},
+ {1.49057, 5.941e-27, 0.0909, 0.106, 703.4398, 0.76, 0.000000, 3, 0},
+ {1.49110, 1.537e-29, 0.0714, 0.098, 381.8992, 0.80, 0.000000, 3, 3},
+ {1.49111, 1.828e-29, 0.0714, 0.098, 381.8992, 0.80, 0.000000, 3, 3},
+ {1.49111, 1.648e-29, 0.0714, 0.098, 381.8992, 0.80, 0.000000, 3, 3},
+ {1.49111, 1.766e-29, 0.0714, 0.098, 381.8991, 0.80, 0.000000, 3, 3},
+ {1.49111, 1.706e-29, 0.0714, 0.098, 381.8991, 0.80, 0.000000, 3, 3},
+ {1.49674, 1.208e-25, 0.0719, 0.102, 190.2125, 0.79, 0.000000, 3, 0},
+ {1.50216, 4.971e-28, 0.0696, 0.090, 1734.9796, 0.82, 0.000000, 3, 0},
+ {1.51178, 3.047e-27, 0.0766, 0.103, 1195.5580, 0.78, 0.000000, 3, 0},
+ {1.51399, 1.986e-27, 0.0765, 0.104, 1129.0675, 0.77, 0.000000, 3, 0},
+ {1.51442, 2.601e-34, 0.0903, 0.123, 0.7572, 0.69, 0.000814, 2, 3},
+ {1.51443, 3.981e-34, 0.0903, 0.123, 0.7572, 0.69, 0.000814, 2, 3},
+ {1.51443, 6.637e-35, 0.0903, 0.123, 0.7572, 0.69, 0.000814, 2, 3},
+ {1.51444, 3.902e-34, 0.0903, 0.123, 0.7572, 0.69, 0.000814, 2, 3},
+ {1.51445, 1.394e-33, 0.0903, 0.123, 0.7572, 0.69, 0.000814, 2, 3},
+ {1.51446, 7.166e-34, 0.0903, 0.123, 0.7572, 0.69, 0.000814, 2, 3},
+ {1.51446, 2.787e-34, 0.0903, 0.123, 0.7572, 0.69, 0.000814, 2, 3},
+ {1.51446, 5.096e-34, 0.0903, 0.123, 0.7572, 0.69, 0.000814, 2, 3},
+ {1.51448, 1.672e-34, 0.0903, 0.123, 0.7572, 0.69, 0.000814, 2, 3},
+ {1.51597, 4.443e-30, 0.0704, 0.097, 463.6953, 0.81, 0.000000, 3, 3},
+ {1.51600, 5.172e-30, 0.0704, 0.097, 463.6952, 0.81, 0.000000, 3, 3},
+ {1.51603, 4.580e-30, 0.0704, 0.097, 463.6952, 0.81, 0.000000, 3, 3},
+ {1.51605, 5.019e-30, 0.0704, 0.097, 463.6951, 0.81, 0.000000, 3, 3}
+};
+const size_t g_nlines = sizeof(g_lines) / sizeof(struct shtr_line);
+
+/*******************************************************************************
+ * Helper functions
+ ******************************************************************************/
+static INLINE void
+write_shtr_isotope(FILE* fp, const struct shtr_isotope* isotope)
+{
+ CHK(fp && isotope);
+ fprintf(fp, " %d %.5E %.4E %d %.6f\n",
+ isotope->id,
+ isotope->abundance,
+ isotope->Q296K,
+ isotope->gj,
+ isotope->molar_mass);
+}
+
+static INLINE void
+write_shtr_molecule(FILE* fp, const struct shtr_molecule* molecule)
+{
+ size_t i;
+ CHK(fp && molecule);
+
+ fprintf(fp, " %s (%d)\n", molecule->name, molecule->id);
+ FOR_EACH(i, 0, molecule->nisotopes) {
+ write_shtr_isotope(fp, molecule->isotopes+i);
+ }
+}
+
+static INLINE void
+write_shtr_lines
+ (FILE* fp,
+ const struct shtr_line* lines,
+ const size_t nlines)
+{
+ size_t i;
+
+ CHK(fp && (!nlines || lines));
+ FOR_EACH(i, 0, nlines) {
+ fprintf(fp,
+ "%2d%1d%12.6f%10.3e 0.000E-00.%04d%5.3f%10.4f%4.2f%8.6f"
+ /* Dummy remaining data */
+ " 0 0 0" /* Global upper quanta */
+ " 0 0 0" /* Global upper quanta */
+ " 5 5 0 " /* Local upper quanta */
+ " 5 5 1 " /* Local lower quanta */
+ "562220" /* Error indices */
+ "5041 7833348" /* References */
+ " " /* Line mixing flag */
+ " 66.0" /* g' */
+ " 66.0" /* g'' */
+ "\n",
+ lines[i].molecule_id,
+ lines[i].isotope_id_local == 9 ? 0 : lines[i].isotope_id_local+1,
+ lines[i].wavenumber,
+ lines[i].intensity,
+ (int)(lines[i].gamma_air*10000+0.5/*round*/),
+ lines[i].gamma_self,
+ lines[i].lower_state_energy,
+ lines[i].n_air,
+ lines[i].delta_air);
+ }
+}
+
+#endif /* TEST_SLN_LINES_H */
diff --git a/src/test_sln_mixture.c b/src/test_sln_mixture.c
@@ -0,0 +1,183 @@
+/* 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 "test_sln_lines.h"
+#include "sln.h"
+
+#include <star/shtr.h>
+#include <rsys/math.h>
+#include <rsys/mem_allocator.h>
+
+/*******************************************************************************
+ * Helper function
+ ******************************************************************************/
+static void
+test_mixture
+ (struct sln_device* sln,
+ struct shtr_isotope_metadata* metadata,
+ struct shtr_lines_list* lines_list)
+{
+ struct sln_mixture_create_args mixture_args = SLN_MIXTURE_CREATE_ARGS_DEFAULT;
+ struct sln_mixture_desc desc = SLN_MIXTURE_DESC_NULL;
+ struct sln_mixture* mixture = NULL;
+ size_t nlines = 0;
+
+ mixture_args.metadata = metadata;
+ mixture_args.lines = lines_list;
+ mixture_args.molecules[0].nisotopes = 0; /* Handle all isotopes */
+ mixture_args.molecules[0].concentration = 1.0/3.0;
+ mixture_args.molecules[0].cutoff = 25;
+ mixture_args.molecules[0].id = 1; /* H2O */
+ mixture_args.molecules[1].nisotopes = 0; /* Handle all isotopes */
+ mixture_args.molecules[1].concentration = 1.0/3.0;
+ mixture_args.molecules[1].cutoff = 50;
+ mixture_args.molecules[1].id = 2; /* CO2 */
+ mixture_args.molecules[2].nisotopes = 0; /* Handle all isotopes */
+ mixture_args.molecules[2].concentration = 1.0/3.0;
+ mixture_args.molecules[2].cutoff = 25;
+ mixture_args.molecules[2].id = 3; /* O3 */
+ mixture_args.nmolecules = 3;
+ mixture_args.wavenumber_range[0] = 0;
+ mixture_args.wavenumber_range[1] = INF;
+ mixture_args.pressure = 1;
+ mixture_args.temperature = 296;
+ CHK(sln_mixture_create(NULL, &mixture_args, &mixture) == RES_BAD_ARG);
+ CHK(sln_mixture_create(sln, NULL, &mixture) == RES_BAD_ARG);
+ CHK(sln_mixture_create(sln, NULL, NULL) == RES_BAD_ARG);
+ CHK(sln_mixture_create(sln, &mixture_args, &mixture) == RES_OK);
+
+ CHK(sln_mixture_get_desc(NULL, &desc) == RES_BAD_ARG);
+ CHK(sln_mixture_get_desc(mixture, NULL) == RES_BAD_ARG);
+ CHK(sln_mixture_get_desc(mixture, &desc) == RES_OK);
+
+ CHK(shtr_lines_list_get_size(lines_list, &nlines) == RES_OK);
+
+ CHK(desc.wavenumber_range[0] == mixture_args.wavenumber_range[0]);
+ CHK(desc.wavenumber_range[1] == mixture_args.wavenumber_range[1]);
+ CHK(desc.temperature = mixture_args.temperature);
+ CHK(desc.pressure == mixture_args.pressure);
+ CHK(desc.nlines == nlines); /* All the lines are taken into the count */
+
+ CHK(sln_mixture_ref_get(NULL) == RES_BAD_ARG);
+ CHK(sln_mixture_ref_get(mixture) == RES_OK);
+ CHK(sln_mixture_ref_put(NULL) == RES_BAD_ARG);
+ CHK(sln_mixture_ref_put(mixture) == RES_OK);
+ CHK(sln_mixture_ref_put(mixture) == RES_OK);
+
+ mixture_args.metadata = NULL;
+ CHK(sln_mixture_create(sln, &mixture_args, &mixture) == RES_BAD_ARG);
+
+ mixture_args.metadata = metadata;
+ mixture_args.lines = NULL;
+ CHK(sln_mixture_create(sln, &mixture_args, &mixture) == RES_BAD_ARG);
+
+ mixture_args.metadata = metadata;
+ mixture_args.lines = NULL;
+ CHK(sln_mixture_create(sln, &mixture_args, &mixture) == RES_BAD_ARG);
+
+ mixture_args.lines = lines_list;
+ mixture_args.molecules[0].concentration = 1;
+ CHK(sln_mixture_create(sln, &mixture_args, &mixture) == RES_BAD_ARG);
+
+ mixture_args.molecules[0].concentration = -1;
+ CHK(sln_mixture_create(sln, &mixture_args, &mixture) == RES_BAD_ARG);
+
+ mixture_args.molecules[0].concentration = 1.0/3.0;
+ mixture_args.molecules[0].cutoff = 0;
+ CHK(sln_mixture_create(sln, &mixture_args, &mixture) == RES_BAD_ARG);
+
+ mixture_args.molecules[0].cutoff = 25;
+ mixture_args.pressure = -1;
+ CHK(sln_mixture_create(sln, &mixture_args, &mixture) == RES_BAD_ARG);
+
+ mixture_args.pressure = 1;
+ mixture_args.temperature = -1;
+ CHK(sln_mixture_create(sln, &mixture_args, &mixture) == RES_BAD_ARG);
+ mixture_args.temperature = 296;
+
+ mixture_args.molecules[0].nisotopes = 2;
+ mixture_args.molecules[0].isotopes[0].abundance = 0.6;
+ mixture_args.molecules[0].isotopes[0].id_local = 0;
+ mixture_args.molecules[0].isotopes[1].abundance = 0.5;
+ mixture_args.molecules[0].isotopes[1].id_local = 1;
+ CHK(sln_mixture_create(sln, &mixture_args, &mixture) == RES_BAD_ARG);
+ mixture_args.molecules[0].isotopes[0].abundance = 0.5;
+
+ CHK(sln_mixture_create(sln, &mixture_args, &mixture) == RES_OK);
+ CHK(sln_mixture_ref_put(mixture) == RES_OK);
+
+ mixture_args.molecules[0].id = SLN_MAX_MOLECULES_COUNT;
+ CHK(sln_mixture_create(sln, &mixture_args, &mixture) == RES_BAD_ARG);
+ mixture_args.molecules[0].id = 1;
+ mixture_args.molecules[0].isotopes[0].id_local = SLN_MAX_ISOTOPES_COUNT;
+ CHK(sln_mixture_create(sln, &mixture_args, &mixture) == RES_BAD_ARG);
+}
+
+/*******************************************************************************
+ * Test function
+ ******************************************************************************/
+int
+main(int argc, char** argv)
+{
+ struct sln_device_create_args dev_args = SLN_DEVICE_CREATE_ARGS_DEFAULT;
+
+ struct sln_device* sln = NULL;
+
+ struct shtr_create_args shtr_args = SHTR_CREATE_ARGS_DEFAULT;
+ struct shtr* shtr = NULL;
+ struct shtr_lines_list* lines_list = NULL;
+ struct shtr_isotope_metadata* metadata = NULL;
+
+ FILE* fp_lines = NULL;
+ FILE* fp_mdata = NULL;
+ (void)argc, (void)argv;
+
+ /* Generate the file of the isotope metadata */
+ CHK(fp_mdata = tmpfile());
+ fprintf(fp_mdata, "Molecule # Iso Abundance Q(296K) gj Molar Mass(g)\n");
+ write_shtr_molecule(fp_mdata, &g_H2O);
+ write_shtr_molecule(fp_mdata, &g_CO2);
+ write_shtr_molecule(fp_mdata, &g_O3);
+ rewind(fp_mdata);
+
+ /* Generate the file of lines */
+ CHK(fp_lines = tmpfile());
+ write_shtr_lines(fp_lines, g_lines, g_nlines);
+ rewind(fp_lines);
+
+ /* Load the isotope metadata and the lines */
+ shtr_args.verbose = 1;
+ CHK(shtr_create(&shtr_args, &shtr) == RES_OK);
+ CHK(shtr_isotope_metadata_load_stream(shtr, fp_mdata, NULL, &metadata) == RES_OK);
+ CHK(shtr_lines_list_load_stream(shtr, fp_lines, NULL, &lines_list) == RES_OK);
+
+ CHK(fclose(fp_lines) == 0);
+ CHK(fclose(fp_mdata) == 0);
+
+ dev_args.verbose = 1;
+ CHK(sln_device_create(&dev_args, &sln) == RES_OK);
+
+ test_mixture(sln, metadata, lines_list);
+
+ CHK(sln_device_ref_put(sln) == RES_OK);
+ CHK(shtr_ref_put(shtr) == RES_OK);
+ CHK(shtr_lines_list_ref_put(lines_list) == RES_OK);
+ CHK(shtr_isotope_metadata_ref_put(metadata) == RES_OK);
+ CHK(mem_allocated_size() == 0);
+ return 0;
+}
diff --git a/src/test_sln_tree.c b/src/test_sln_tree.c
@@ -16,6 +16,7 @@
* 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 "test_sln_lines.h"
#include "sln.h"
#include <star/shtr.h>
@@ -25,177 +26,6 @@
#include <rsys/mem_allocator.h>
/*******************************************************************************
- * Input data
- ******************************************************************************/
-static const struct shtr_isotope g_H2O_isotopes[] = {
- {9.97317E-01, 1.7458E+02, 18.010565, 0, 1, 161},
- {1.99983E-03, 1.7605E+02, 20.014811, 0, 1, 181},
- {3.71884E-04, 1.0521E+03, 19.014780, 0, 6, 171},
- {3.10693E-04, 8.6474E+02, 19.016740, 0, 6, 162},
- {6.23003E-07, 8.7557E+02, 21.020985, 0, 6, 182},
- {1.15853E-07, 5.2268E+03, 20.020956, 0, 36, 172},
- {2.41974E-08, 1.0278E+03, 20.022915, 0, 1, 262}
-};
-static const struct shtr_molecule g_H2O = {
- "H2O", sizeof(g_H2O_isotopes)/sizeof(struct shtr_isotope), g_H2O_isotopes, 1,
-};
-
-static const struct shtr_isotope g_CO2_isotopes[] = {
- {9.84204E-01, 2.8609E+02, 43.989830, 1, 1, 626},
- {1.10574E-02, 5.7664E+02, 44.993185, 1, 2, 636},
- {3.94707E-03, 6.0781E+02, 45.994076, 1, 1, 628},
- {7.33989E-04, 3.5426E+03, 44.994045, 1, 6, 627},
- {4.43446E-05, 1.2255E+03, 46.997431, 1, 2, 638},
- {8.24623E-06, 7.1413E+03, 45.997400, 1, 12, 637},
- {3.95734E-06, 3.2342E+02, 47.998320, 1, 1, 828},
- {1.47180E-06, 3.7666E+03, 46.998291, 1, 6, 827},
- {1.36847E-07, 1.0972E+04, 45.998262, 1, 1, 727},
- {4.44600E-08, 6.5224E+02, 49.001675, 1, 2, 838},
- {1.65354E-08, 7.5950E+03, 48.001646, 1, 12, 837},
- {1.53745E-09, 2.2120E+04, 47.001618, 1, 2, 737}
-};
-static const struct shtr_molecule g_CO2 = {
- "CO2", sizeof(g_CO2_isotopes)/sizeof(struct shtr_isotope), g_CO2_isotopes, 2,
-};
-
-static const struct shtr_isotope g_O3_isotopes[] = {
- {9.92901E-01, 3.4750E+03, 47.984745, 2, 1, 666},
- {3.98194E-03, 7.5846E+03, 49.988991, 2, 1, 668},
- {1.99097E-03, 3.7030E+03, 49.988991, 2, 1, 686},
- {7.40475E-04, 4.4044E+04, 48.988960, 2, 6, 667},
- {3.70237E-04, 2.1742E+04, 48.988960, 2, 6, 676}
-};
-static const struct shtr_molecule g_O3 = {
- "O3", sizeof(g_O3_isotopes)/sizeof(struct shtr_isotope), g_O3_isotopes, 3
-};
-
-static const struct shtr_line g_lines[] = {
- {0.00156, 2.685e-36, 0.0695, 0.428, 399.7263, 0.79, 0.000240, 1, 5},
- {0.03406, 5.898e-37, 0.0883, 0.410, 1711.6192, 0.79, 0.000000, 1, 5},
- {0.03445, 5.263e-33, 0.0504, 0.329, 1570.0616, 0.79, 0.001940, 1, 3},
- {0.03628, 9.296e-29, 0.0704, 0.095, 522.5576, 0.81, 0.000000, 3, 0},
- {0.03671, 2.555e-37, 0.0389, 0.304, 2337.5190, 0.79, 0.002660, 1, 4},
- {0.08403, 8.190e-33, 0.0753, 0.394, 568.0017, 0.79, 0.002180, 1, 4},
- {0.08653, 5.376e-29, 0.0691, 0.083, 1061.6864, 0.76, 0.000000, 3, 0},
- {0.09642, 6.675e-37, 0.0570, 0.351, 2516.3150, 0.79, 0.000000, 1, 4},
- {0.16772, 2.456e-28, 0.0823, 0.105, 751.2922, 0.77, 0.000000, 3, 0},
- {0.18582, 5.338e-32, 0.0925, 0.428, 1717.3356, 0.79, 0.004100, 1, 3},
- {0.19368, 2.553e-32, 0.0901, 0.428, 293.8010, 0.79, 0.001260, 1, 5},
- {0.19688, 1.447e-31, 0.0901, 0.428, 292.3093, 0.79, 0.001260, 1, 4},
- {0.19757, 6.063e-29, 0.0681, 0.078, 1401.6146, 0.76, 0.000000, 3, 0},
- {0.21281, 8.238e-31, 0.0780, 0.103, 127.4733, 0.78, 0.000000, 3, 4},
- {0.21282, 5.999e-31, 0.0780, 0.103, 127.4733, 0.78, 0.000000, 3, 4},
- {0.21283, 7.737e-31, 0.0780, 0.103, 127.4733, 0.78, 0.000000, 3, 4},
- {0.21283, 6.394e-31, 0.0780, 0.103, 127.4733, 0.78, 0.000000, 3, 4},
- {0.21284, 7.260e-31, 0.0780, 0.103, 127.4732, 0.78, 0.000000, 3, 4},
- {0.21284, 6.813e-31, 0.0780, 0.103, 127.4733, 0.78, 0.000000, 3, 4},
- {0.21728, 5.928e-29, 0.0823, 0.105, 1153.4099, 0.77, 0.000000, 3, 0},
- {0.25818, 3.110e-32, 0.0539, 0.311, 1958.1248, 0.79, 0.008600, 1, 3},
- {0.26618, 1.468e-32, 0.0801, 0.378, 2118.9452, 0.79, 0.003100, 1, 3},
- {0.27091, 1.362e-35, 0.0539, 0.311, 1949.2032, 0.79, 0.008600, 1, 5},
- {0.28910, 2.058e-30, 0.0878, 0.106, 7.8611, 0.76, 0.000000, 3, 3},
- {0.29412, 8.666e-33, 0.0795, 0.378, 679.8760, 0.79, 0.004170, 1, 5},
- {0.29477, 1.457e-30, 0.0660, 0.340, 1238.7943, 0.79, 0.007260, 1, 3},
- {0.29673, 1.609e-30, 0.0773, 0.103, 138.7916, 0.78, 0.000000, 3, 3},
- {0.29673, 1.195e-30, 0.0773, 0.103, 138.7916, 0.78, 0.000000, 3, 3},
- {0.29676, 1.268e-30, 0.0773, 0.103, 138.7916, 0.78, 0.000000, 3, 3},
- {1.46280, 7.205e-26, 0.0696, 0.090, 702.3167, 0.82, 0.000000, 3, 0},
- {1.46899, 7.847e-28, 0.0704, 0.095, 1557.6290, 0.81, 0.000000, 3, 0},
- {1.47237, 1.700e-34, 0.0633, 0.297, 2389.2994, 0.79, 0.013980, 1, 4},
- {1.47273, 1.131e-32, 0.0903, 0.123, 0.7753, 0.69, 0.000814, 2, 2},
- {1.47863, 5.318e-33, 0.0925, 0.428, 2877.6872, 0.79, 0.006200, 1, 3},
- {1.48860, 1.058e-27, 0.0760, 0.102, 163.7760, 0.78, 0.000000, 3, 1},
- {1.49043, 4.787e-31, 0.0773, 0.103, 139.7879, 0.78, 0.000000, 3, 4},
- {1.49044, 3.139e-29, 0.0773, 0.103, 139.7879, 0.78, 0.000000, 3, 4},
- {1.49044, 3.332e-29, 0.0773, 0.103, 139.7880, 0.78, 0.000000, 3, 4},
- {1.49045, 2.785e-29, 0.0773, 0.103, 139.7880, 0.78, 0.000000, 3, 4},
- {1.49045, 2.625e-29, 0.0773, 0.103, 139.7880, 0.78, 0.000000, 3, 4},
- {1.49057, 5.941e-27, 0.0909, 0.106, 703.4398, 0.76, 0.000000, 3, 0},
- {1.49110, 1.537e-29, 0.0714, 0.098, 381.8992, 0.80, 0.000000, 3, 3},
- {1.49111, 1.828e-29, 0.0714, 0.098, 381.8992, 0.80, 0.000000, 3, 3},
- {1.49111, 1.648e-29, 0.0714, 0.098, 381.8992, 0.80, 0.000000, 3, 3},
- {1.49111, 1.766e-29, 0.0714, 0.098, 381.8991, 0.80, 0.000000, 3, 3},
- {1.49111, 1.706e-29, 0.0714, 0.098, 381.8991, 0.80, 0.000000, 3, 3},
- {1.49674, 1.208e-25, 0.0719, 0.102, 190.2125, 0.79, 0.000000, 3, 0},
- {1.50216, 4.971e-28, 0.0696, 0.090, 1734.9796, 0.82, 0.000000, 3, 0},
- {1.51178, 3.047e-27, 0.0766, 0.103, 1195.5580, 0.78, 0.000000, 3, 0},
- {1.51399, 1.986e-27, 0.0765, 0.104, 1129.0675, 0.77, 0.000000, 3, 0},
- {1.51442, 2.601e-34, 0.0903, 0.123, 0.7572, 0.69, 0.000814, 2, 3},
- {1.51443, 3.981e-34, 0.0903, 0.123, 0.7572, 0.69, 0.000814, 2, 3},
- {1.51443, 6.637e-35, 0.0903, 0.123, 0.7572, 0.69, 0.000814, 2, 3},
- {1.51444, 3.902e-34, 0.0903, 0.123, 0.7572, 0.69, 0.000814, 2, 3},
- {1.51445, 1.394e-33, 0.0903, 0.123, 0.7572, 0.69, 0.000814, 2, 3},
- {1.51446, 7.166e-34, 0.0903, 0.123, 0.7572, 0.69, 0.000814, 2, 3},
- {1.51446, 2.787e-34, 0.0903, 0.123, 0.7572, 0.69, 0.000814, 2, 3},
- {1.51446, 5.096e-34, 0.0903, 0.123, 0.7572, 0.69, 0.000814, 2, 3},
- {1.51448, 1.672e-34, 0.0903, 0.123, 0.7572, 0.69, 0.000814, 2, 3},
- {1.51597, 4.443e-30, 0.0704, 0.097, 463.6953, 0.81, 0.000000, 3, 3},
- {1.51600, 5.172e-30, 0.0704, 0.097, 463.6952, 0.81, 0.000000, 3, 3},
- {1.51603, 4.580e-30, 0.0704, 0.097, 463.6952, 0.81, 0.000000, 3, 3},
- {1.51605, 5.019e-30, 0.0704, 0.097, 463.6951, 0.81, 0.000000, 3, 3}
-};
-const size_t g_nlines = sizeof(g_lines) / sizeof(struct shtr_line);
-
-static void
-write_shtr_isotope(FILE* fp, const struct shtr_isotope* isotope)
-{
- CHK(fp && isotope);
- fprintf(fp, " %d %.5E %.4E %d %.6f\n",
- isotope->id,
- isotope->abundance,
- isotope->Q296K,
- isotope->gj,
- isotope->molar_mass);
-}
-
-static void
-write_shtr_molecule(FILE* fp, const struct shtr_molecule* molecule)
-{
- size_t i;
- CHK(fp && molecule);
-
- fprintf(fp, " %s (%d)\n", molecule->name, molecule->id);
- FOR_EACH(i, 0, molecule->nisotopes) {
- write_shtr_isotope(fp, molecule->isotopes+i);
- }
-}
-
-static void
-write_shtr_lines
- (FILE* fp,
- const struct shtr_line* lines,
- const size_t nlines)
-{
- size_t i;
-
- CHK(fp && (!nlines || lines));
- FOR_EACH(i, 0, nlines) {
- fprintf(fp,
- "%2d%1d%12.6f%10.3e 0.000E-00.%04d%5.3f%10.4f%4.2f%8.6f"
- /* Dummy remaining data */
- " 0 0 0" /* Global upper quanta */
- " 0 0 0" /* Global upper quanta */
- " 5 5 0 " /* Local upper quanta */
- " 5 5 1 " /* Local lower quanta */
- "562220" /* Error indices */
- "5041 7833348" /* References */
- " " /* Line mixing flag */
- " 66.0" /* g' */
- " 66.0" /* g'' */
- "\n",
- lines[i].molecule_id,
- lines[i].isotope_id_local == 9 ? 0 : lines[i].isotope_id_local+1,
- lines[i].wavenumber,
- lines[i].intensity,
- (int)(lines[i].gamma_air*10000+0.5/*round*/),
- lines[i].gamma_self,
- lines[i].lower_state_energy,
- lines[i].n_air,
- lines[i].delta_air);
- }
-}
-
-/*******************************************************************************
* Helper function
******************************************************************************/
static int
@@ -250,7 +80,7 @@ find_line
static void
check_tree
(const struct sln_tree* tree,
- struct shtr_lines_list* lines_list)
+ const struct shtr_lines_list* lines_list)
{
#define STACK_SIZE 64
const struct shtr_line* list = NULL;
@@ -321,10 +151,7 @@ dump_line(FILE* stream, const struct sln_mesh* mesh)
}
static void
-test_tree
- (struct sln_device* sln,
- struct shtr_isotope_metadata* metadata,
- struct shtr_lines_list* lines_list)
+test_tree(struct sln_mixture* mixture, const struct shtr_lines_list* lines_list)
{
struct sln_tree_create_args tree_args = SLN_TREE_CREATE_ARGS_DEFAULT;
struct sln_tree_desc desc = SLN_TREE_DESC_NULL;
@@ -334,39 +161,22 @@ test_tree
const struct shtr_line* line = NULL;
size_t nlines = 0;
- tree_args.metadata = metadata;
- tree_args.lines = lines_list;
- tree_args.molecules[0].nisotopes = 0; /* Handle all isotopes */
- tree_args.molecules[0].concentration = 1.0/3.0;
- tree_args.molecules[0].cutoff = 25;
- tree_args.molecules[0].id = 1; /* H2O */
- tree_args.molecules[1].nisotopes = 0; /* Handle all isotopes */
- tree_args.molecules[1].concentration = 1.0/3.0;
- tree_args.molecules[1].cutoff = 50;
- tree_args.molecules[1].id = 2; /* CO2 */
- tree_args.molecules[2].nisotopes = 0; /* Handle all isotopes */
- tree_args.molecules[2].concentration = 1.0/3.0;
- tree_args.molecules[2].cutoff = 25;
- tree_args.molecules[2].id = 3; /* CO2 */
- tree_args.nmolecules = 3;
- tree_args.wavenumber_range[0] = 0;
- tree_args.wavenumber_range[1] = INF;
- tree_args.pressure = 1;
- tree_args.temperature = 296;
- tree_args.max_nlines_per_leaf = 1;
- CHK(sln_tree_create(sln, &tree_args, &tree) == RES_OK);
+ CHK(mixture && lines_list);
+
+ CHK(sln_tree_create(NULL, &tree_args, &tree) == RES_BAD_ARG);
+ CHK(sln_tree_create(mixture, NULL, &tree) == RES_BAD_ARG);
+ CHK(sln_tree_create(mixture, &tree_args, NULL) == RES_BAD_ARG);
+ CHK(sln_tree_create(mixture, &tree_args, &tree) == RES_OK);
CHK(shtr_lines_list_get_size(lines_list, &nlines) == RES_OK);
CHK(sln_tree_get_desc(NULL, &desc) == RES_BAD_ARG);
CHK(sln_tree_get_desc(tree, NULL) == RES_BAD_ARG);
CHK(sln_tree_get_desc(tree, &desc) == RES_OK);
- CHK(desc.wavenumber_range[0] == tree_args.wavenumber_range[0]);
- CHK(desc.wavenumber_range[1] == tree_args.wavenumber_range[1]);
+
CHK(desc.max_nlines_per_leaf == tree_args.max_nlines_per_leaf);
- CHK(desc.temperature = tree_args.temperature);
- CHK(desc.pressure == tree_args.pressure);
- CHK(desc.nlines == nlines); /* All the lines are taken into the count */
+ CHK(desc.mesh_decimation_err == tree_args.mesh_decimation_err);
+ CHK(desc.line_profile == tree_args.line_profile);
CHK(node = sln_tree_get_root(tree));
while(!sln_node_is_leaf(node)) {
@@ -398,64 +208,20 @@ test_tree
CHK(sln_tree_ref_put(tree) == RES_OK);
CHK(sln_tree_ref_put(tree) == RES_OK);
- tree_args.metadata = NULL;
- CHK(sln_tree_create(sln, &tree_args, &tree) == RES_BAD_ARG);
-
- tree_args.metadata = metadata;
- tree_args.lines = NULL;
- CHK(sln_tree_create(sln, &tree_args, &tree) == RES_BAD_ARG);
-
- tree_args.metadata = metadata;
- tree_args.lines = NULL;
- CHK(sln_tree_create(sln, &tree_args, &tree) == RES_BAD_ARG);
-
- tree_args.lines = lines_list;
- tree_args.molecules[0].concentration = 1;
- CHK(sln_tree_create(sln, &tree_args, &tree) == RES_BAD_ARG);
-
- tree_args.molecules[0].concentration = -1;
- CHK(sln_tree_create(sln, &tree_args, &tree) == RES_BAD_ARG);
-
- tree_args.molecules[0].concentration = 1.0/3.0;
- tree_args.molecules[0].cutoff = 0;
- CHK(sln_tree_create(sln, &tree_args, &tree) == RES_BAD_ARG);
-
- tree_args.molecules[0].cutoff = 25;
- tree_args.pressure = -1;
- CHK(sln_tree_create(sln, &tree_args, &tree) == RES_BAD_ARG);
-
- tree_args.pressure = 1;
- tree_args.temperature = -1;
- CHK(sln_tree_create(sln, &tree_args, &tree) == RES_BAD_ARG);
-
- tree_args.temperature = 296;
tree_args.max_nlines_per_leaf = 0;
- CHK(sln_tree_create(sln, &tree_args, &tree) == RES_BAD_ARG);
+ CHK(sln_tree_create(mixture, &tree_args, &tree) == RES_BAD_ARG);
tree_args.max_nlines_per_leaf = 1;
tree_args.mesh_decimation_err = -1;
- CHK(sln_tree_create(sln, &tree_args, &tree) == RES_BAD_ARG);
+ CHK(sln_tree_create(mixture, &tree_args, &tree) == RES_BAD_ARG);
tree_args.mesh_decimation_err = 1e-1f;
- CHK(sln_tree_create(sln, &tree_args, &tree) == RES_OK);
- CHK(sln_tree_ref_put(tree) == RES_OK);
+ tree_args.line_profile = SLN_LINE_PROFILES_COUNT__;
+ CHK(sln_tree_create(mixture, &tree_args, &tree) == RES_BAD_ARG);
- tree_args.molecules[0].nisotopes = 2;
- tree_args.molecules[0].isotopes[0].abundance = 0.6;
- tree_args.molecules[0].isotopes[0].id_local = 0;
- tree_args.molecules[0].isotopes[1].abundance = 0.5;
- tree_args.molecules[0].isotopes[1].id_local = 1;
- CHK(sln_tree_create(sln, &tree_args, &tree) == RES_BAD_ARG);
- tree_args.molecules[0].isotopes[0].abundance = 0.5;
-
- CHK(sln_tree_create(sln, &tree_args, &tree) == RES_OK);
+ tree_args.line_profile = SLN_LINE_PROFILE_VOIGT;
+ CHK(sln_tree_create(mixture, &tree_args, &tree) == RES_OK);
CHK(sln_tree_ref_put(tree) == RES_OK);
-
- tree_args.molecules[0].id = SLN_MAX_MOLECULES_COUNT;
- CHK(sln_tree_create(sln, &tree_args, &tree) == RES_BAD_ARG);
- tree_args.molecules[0].id = 1;
- tree_args.molecules[0].isotopes[0].id_local = SLN_MAX_ISOTOPES_COUNT;
- CHK(sln_tree_create(sln, &tree_args, &tree) == RES_BAD_ARG);
}
/*******************************************************************************
@@ -465,7 +231,9 @@ int
main(int argc, char** argv)
{
struct sln_device_create_args dev_args = SLN_DEVICE_CREATE_ARGS_DEFAULT;
+ struct sln_mixture_create_args mixture_args = SLN_MIXTURE_CREATE_ARGS_DEFAULT;
struct sln_device* sln = NULL;
+ struct sln_mixture* mixture = NULL;
struct shtr_create_args shtr_args = SHTR_CREATE_ARGS_DEFAULT;
struct shtr* shtr = NULL;
@@ -501,9 +269,32 @@ main(int argc, char** argv)
dev_args.verbose = 1;
CHK(sln_device_create(&dev_args, &sln) == RES_OK);
- test_tree(sln, metadata, lines_list);
+ /* Create the mixture */
+ mixture_args.metadata = metadata;
+ mixture_args.lines = lines_list;
+ mixture_args.molecules[0].nisotopes = 0; /* Handle all isotopes */
+ mixture_args.molecules[0].concentration = 1.0/3.0;
+ mixture_args.molecules[0].cutoff = 25;
+ mixture_args.molecules[0].id = 1; /* H2O */
+ mixture_args.molecules[1].nisotopes = 0; /* Handle all isotopes */
+ mixture_args.molecules[1].concentration = 1.0/3.0;
+ mixture_args.molecules[1].cutoff = 50;
+ mixture_args.molecules[1].id = 2; /* CO2 */
+ mixture_args.molecules[2].nisotopes = 0; /* Handle all isotopes */
+ mixture_args.molecules[2].concentration = 1.0/3.0;
+ mixture_args.molecules[2].cutoff = 25;
+ mixture_args.molecules[2].id = 3; /* O3 */
+ mixture_args.nmolecules = 3;
+ mixture_args.wavenumber_range[0] = 0;
+ mixture_args.wavenumber_range[1] = INF;
+ mixture_args.pressure = 1;
+ mixture_args.temperature = 296;
+ CHK(sln_mixture_create(sln, &mixture_args, &mixture) == RES_OK);
+
+ test_tree(mixture, lines_list);
CHK(sln_device_ref_put(sln) == RES_OK);
+ CHK(sln_mixture_ref_put(mixture) == RES_OK);
CHK(shtr_ref_put(shtr) == RES_OK);
CHK(shtr_lines_list_ref_put(lines_list) == RES_OK);
CHK(shtr_isotope_metadata_ref_put(metadata) == RES_OK);