commit 56fc20939a04b6ce553dfd9dc2da0ce1dd2b3b87
parent 8e7a5b5825d3ae39f99e1cca59be5b12632f41f2
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Wed, 4 May 2022 16:43:53 +0200
Clip the line mesh to the spectral range
Diffstat:
3 files changed, 70 insertions(+), 12 deletions(-)
diff --git a/src/sln.h b/src/sln.h
@@ -76,7 +76,8 @@ static const struct sln_isotope SLN_ISOTOPE_NULL = SLN_ISOTOPE_NULL__;
struct sln_molecule {
/* List of isotopes to be taken into account */
struct sln_isotope isotopes[SLN_MAX_ISOTOPES_COUNT];
- size_t nisotopes; /* 0 <=> select all the isotopes of the molecules */
+ /* 0 <=> select all the isotopes of the molecules with refernce abundance */
+ size_t nisotopes;
double concentration;
double cutoff; /* in cm^-1 */
@@ -122,6 +123,20 @@ struct sln_tree_desc {
#define SLN_TREE_DESC_NULL__ {{0,0},0,0,0,0}
static const struct sln_tree_desc SLN_TREE_DESC_NULL = SLN_TREE_DESC_NULL__;
+struct sln_vertex { /* 8 Bytes */
+ float wavenumber; /* in cm^-1 */
+ float ka;
+};
+#define SLN_VERTEX_NULL__ {0,0}
+static const struct sln_vertex SLN_VERTEX_NULL = SLN_VERTEX_NULL__;
+
+struct sln_mesh {
+ const struct sln_vertex* vertices;
+ size_t nvertices;
+};
+#define SLN_MESH_NULL__ {NULL,0}
+static const struct sln_mesh SLN_MESH_NULL = SLN_MESH_NULL__;
+
/* Forward declarations of opaque data structures */
struct sln_device;
struct sln_tree;
diff --git a/src/sln_line.c b/src/sln_line.c
@@ -197,6 +197,8 @@ regular_mesh_fragmented
ASSERT(tree && 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]);
/* Compute the spectral range of the line from its center to its cutoff */
line_nu_min = line->wavenumber;
@@ -236,7 +238,10 @@ eval_mesh
const struct darray_double* wavenumbers,
struct darray_double* values)
{
+ const struct shtr_line* shtr_line = NULL;
size_t ivertex, nvertices;
+ double range[2];
+ double cutoff;
res_T res = RES_OK;
ASSERT(tree && wavenumbers && values);
@@ -246,8 +251,24 @@ 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));
+
+ /* Calculate the spectral range in which the vertices should be evaluated.
+ * Recall that a line being symmetrical in its center, we will only evaluate
+ * its upper half. Anyway, note that a line clipped by the spectral range is
+ * no longer symmetric. In the following, we thus adjust the spectral range
+ * 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]);
+ 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);
}
@@ -372,23 +393,50 @@ line_mesh
goto error;
}
- /* Copy the first half of the line vertices */
i = tree_nvertices;
+
+ /* Emit the 1st vertex for the lower bound of the spectral range if the line
+ * cut it */
+ if(line->wavenumber - mol_params->cutoff <= tree->wavenumber_range[0]) {
+ struct sln_vertex* vtx = darray_vertex_data_get(&tree->vertices) + i;
+ vtx->wavenumber = (float)tree->wavenumber_range[0];
+ vtx->ka = (float)line_value(tree, iline, vtx->wavenumber);
+ ++i;
+ }
+
+ /* Copy the first half of the line vertices */
FOR_EACH_REVERSE(ivertex, line_nvertices-1, 0) {
- struct vertex* vtx = darray_vertex_data_get(&tree->vertices) + i;
- vtx->wavenumber = (float)darray_double_cdata_get(&wavenumbers)[ivertex];
+ struct sln_vertex* vtx = darray_vertex_data_get(&tree->vertices) + i;
+ double nu = (float)darray_double_cdata_get(&wavenumbers)[ivertex];
+ nu = line->wavenumber - nu + line->wavenumber;
+ if(nu <= tree->wavenumber_range[0]) continue;/* Out of range */
+ vtx->wavenumber = (float)nu;
vtx->ka = (float)darray_double_cdata_get(&values)[ivertex];
++i;
}
/* Copy the vertex of the line center and the second half of the line
* vertices */
FOR_EACH(ivertex, 0, line_nvertices) {
- struct vertex* vtx = darray_vertex_data_get(&tree->vertices) + i;
- vtx->wavenumber = (float)darray_double_cdata_get(&wavenumbers)[ivertex];
+ struct sln_vertex* vtx = darray_vertex_data_get(&tree->vertices) + i;
+ const double nu = darray_double_cdata_get(&wavenumbers)[ivertex];
+ if(nu >= tree->wavenumber_range[1]) break;/* Out of range */
+ vtx->wavenumber = (float)nu;
vtx->ka = (float)darray_double_cdata_get(&values)[ivertex];
++i;
}
+ /* Emit the last vertex for the upper bound of the spectral range */
+ if(line->wavenumber + mol_params->cutoff >= tree->wavenumber_range[1]) {
+ struct sln_vertex* vtx = darray_vertex_data_get(&tree->vertices) + i;
+ vtx->wavenumber = (float)tree->wavenumber_range[1];
+ vtx->ka = (float)line_value(tree, iline, vtx->wavenumber);
+ ++i;
+ }
+
+ /* Several vertices could be deleted due to spectral range. So, resize the
+ * list of vertices to the effective number of registered vertices. */
+ CHK(darray_vertex_resize(&tree->vertices, i) == RES_OK);
+
exit:
darray_double_release(&values);
darray_double_release(&wavenumbers);
diff --git a/src/sln_tree_c.h b/src/sln_tree_c.h
@@ -40,11 +40,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__;
-struct vertex { /* 8 Bytes */
- float wavenumber; /* in cm^-1 */
- float ka;
-};
-
/* Generate the dynamic array of lines */
#define DARRAY_DATA struct line
#define DARRAY_NAME line
@@ -56,7 +51,7 @@ struct vertex { /* 8 Bytes */
#include <rsys/dynamic_array.h>
/* Generate the dynamic array of vertices */
-#define DARRAY_DATA struct vertex
+#define DARRAY_DATA struct sln_vertex
#define DARRAY_NAME vertex
#include <rsys/dynamic_array.h>