commit 282051b3137371ee09c4cf4228822ca03500992f
parent f069f3ff11ab67a53b9c6b89c88157fbff391e40
Author: Vincent Forest <vaplv@free.fr>
Date: Wed, 20 Apr 2022 17:48:25 +0200
Build the tree
Diffstat:
5 files changed, 252 insertions(+), 17 deletions(-)
diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt
@@ -28,12 +28,13 @@ option(NO_TEST "Do not build tests" OFF)
################################################################################
find_package(RCMake 0.4 REQUIRED)
find_package(RSys 0.12.1 REQUIRED)
+find_package(StarHITRAN REQUIRED)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${RCMAKE_SOURCE_DIR})
include(rcmake)
include(rcmake_runtime)
-include_directories(${RSys_INCLUDE_DIR})
+include_directories(${RSys_INCLUDE_DIR} ${StarHITRAN_INCLUDE_DIR})
################################################################################
# Configure and define targets
@@ -46,7 +47,8 @@ set(VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH})
set(SLN_FILES_SRC
sln_device.c
sln_log.c
- sln_tree.c)
+ sln_tree.c
+ sln_tree_build.c)
set(SLN_FILES_INC
sln_device_c.h
sln_log.h)
@@ -63,7 +65,7 @@ rcmake_prepend_path(SLN_FILES_DOC ${PROJECT_SOURCE_DIR}/../)
add_library(sln SHARED
${SLN_FILES_SRC} ${SLN_FILES_INC} ${SLN_FILES_INC_API})
-target_link_libraries(sln RSys)
+target_link_libraries(sln RSys StarHITRAN)
set_target_properties(sln PROPERTIES
DEFINE_SYMBOL SLN_SHARED_BUILD
diff --git a/src/sln.h b/src/sln.h
@@ -20,6 +20,7 @@
#define SLN_H
#include <rsys/rsys.h>
+#include <float.h>
/* Library symbol management */
#if defined(SLN_SHARED_BUILD) /* Build shared library */
@@ -39,6 +40,9 @@
#define SLN(Func) sln_ ## Func
#endif
+#define SLN_MAX_MOLECULES_COUNT 100
+#define SLN_MAX_ISOTOPES_COUNT 10
+
/* Forwar declaration of external data structures */
struct logger;
struct mem_allocator;
@@ -55,28 +59,40 @@ static const struct sln_device_create_args SLN_DEVICE_CREATE_ARGS_DEFAULT =
SLN_DEVICE_CREATE_ARGS_DEFAULT__;
struct sln_molecule {
+ /* List of isotopes identifier to consider for this molecule. The listed
+ * idenfiers are _local_ to the molecule */
+ int32_t isotope_ids_local[SLN_MAX_ISOTOPES_COUNT];
+ size_t nisotopes; /* 0 <=> select all the isotopes */
+
+ /* TODO check with Yaniss if these parameters are per molecule or per isotope */
double concentration;
double cutoff; /* in cm^1 */
- int32_t id; /* Identifier of the molecule into the isotopo metadata */
+
+ int32_t id; /* Identifier of the molecule into the isotope metadata */
};
+#define SLN_MOLECULE_NULL__ {{0}, 0, 0, 0, 0}
+static const struct sln_molecule SLN_MOLECULE_NULL = SLN_MOLECULE_NULL__;
struct sln_tree_create_args {
/* Isotope metadata and overall list of spectral lines */
const struct shtr_isotope_metadata* metadata;
- const struct shtr_lines_list* lines;
+ struct shtr_lines_list* lines;
/* List of molecules to be taken into account with its associated
* concentration and cutoff */
- const struct sln_molecule* molecules;
+ const struct sln_molecule molecules[SLN_MAX_MOLECULES_COUNT];
size_t nmolecules;
+ double wavenumber_range[2]; /* Spectral range */
+
/* Thermodynamic properties */
double pressure; /* In atm */
double temperature; /* In K */
size_t max_nlines_per_leaf;
};
-#define SLN_TREE_CREATE_ARGS_DEFAULT__ {NULL, NULL, NULL, 0, 0, 0, 64}
+#define SLN_TREE_CREATE_ARGS_DEFAULT__ \
+ {NULL, NULL, {SLN_MOLECULE_NULL__}, 0, {0, DBL_MAX}, 0, 0, 64}
static const struct sln_tree_create_args SLN_TREE_CREATE_ARGS_DEFAULT =
SLN_TREE_CREATE_ARGS_DEFAULT__;
diff --git a/src/sln_tree.c b/src/sln_tree.c
@@ -19,13 +19,9 @@
#include "sln.h"
#include "sln_device_c.h"
#include "sln_log.h"
+#include "sln_tree_c.h"
-#include <rsys/ref_count.h>
-
-struct sln_tree {
- struct sln_device* sln;
- ref_T ref;
-};
+#include <star/shtr.h>
/*******************************************************************************
* Helper functions
@@ -36,7 +32,18 @@ check_sln_molecule
const char* func_name,
const struct sln_molecule* molecule)
{
- ASSERT(sln && molecule);
+ ASSERT(sln && func_name && molecule);
+
+ 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;
+ }
+
/* TODO check with Yaniss */
if(molecule->concentration < 0) {
log_err(sln, "%s: molecule `%d': invalid concentration `%g'.\n",
@@ -58,16 +65,21 @@ check_sln_tree_create_args
const struct sln_tree_create_args* args)
{
size_t i;
- ASSERT(sln);
+ ASSERT(sln && func_name);
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 && args->molecules) {
+ 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;
}
FOR_EACH(i, 0, args->nmolecules) {
@@ -87,6 +99,50 @@ check_sln_tree_create_args
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)
+{
+ 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);
+ 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->isotope_ids_local[iiso];
+ }
+ }
+
+ 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
release_tree(ref_T* ref)
{
@@ -94,6 +150,8 @@ release_tree(ref_T* ref)
struct sln_device* sln = NULL;
ASSERT(ref);
sln = tree->sln;
+ if(tree->lines_view) SHTR(lines_view_ref_put(tree->lines_view));
+ darray_node_release(&tree->nodes);
MEM_RM(sln->allocator, tree);
SLN(device_ref_put(sln));
}
@@ -124,6 +182,12 @@ sln_tree_create
ref_init(&tree->ref);
SLN(device_ref_get(sln));
tree->sln = sln;
+ darray_node_init(sln->allocator, &tree->nodes);
+
+ res = create_lines_view(sln, args, &tree->lines_view);
+ if(res != RES_OK) goto error;
+ res = tree_build(tree, args);
+ if(res != RES_OK) goto error;
exit:
if(out_tree) *out_tree = tree;
diff --git a/src/sln_tree_build.c b/src/sln_tree_build.c
@@ -0,0 +1,97 @@
+/* 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_tree_c.h"
+#include <star/shtr.h>
+
+/*******************************************************************************
+ * Local functions
+ ******************************************************************************/
+res_T
+tree_build
+ (struct sln_tree* tree,
+ const struct sln_tree_create_args* args)
+{
+ size_t stack[64];
+ struct node* node = NULL;
+ size_t istack = 0;
+ size_t nlines;
+ res_T res = RES_OK;
+
+ ASSERT(tree && args);
+ SHTR(lines_view_get_size(tree->lines_view, &nlines));
+
+ #define CREATE_NODE { \
+ res = darray_node_push_back(&tree->nodes, &NODE_NULL); \
+ if(res != RES_OK) goto error; \
+ } (void)0
+
+ CREATE_NODE; /* Alloc the root node */
+
+ /* Setup the root node */
+ node = darray_node_data_get(&tree->nodes);
+ node->range[0] = 0;
+ node->range[1] = nlines - 1;
+
+ while(node) {
+ const size_t inode = (size_t)(node - darray_node_cdata_get(&tree->nodes));
+ nlines = node->range[1] - node->range[0] + 1; /* #lines into the node */
+
+ /* Make a leaf */
+ if(nlines < args->max_nlines_per_leaf) {
+ node->offset = -1;
+ node = istack ? darray_node_data_get(&tree->nodes)+stack[--istack] : NULL;
+
+ /* Split the node */
+ } else {
+ const size_t split = (nlines + 1/*ceil*/)/2; /* Median split */
+ struct node* children = NULL;
+
+ /* Compute the index toward the 2 children (first is the left child,
+ * followed by the righ child) */
+ size_t ichildren = darray_node_size_get(&tree->nodes);
+
+ /* Define the offset from the current node to its children */
+ ASSERT(ichildren > inode);
+ node->offset = (int64_t)(ichildren - inode);
+
+ CREATE_NODE; /* Alloc left child */
+ CREATE_NODE; /* Alloc right child */
+
+ children = darray_node_data_get(&tree->nodes)+ichildren;
+
+ /* Setup the left child */
+ children[0].range[0] = node->range[0];
+ children[0].range[1] = split-1;
+ /* Setup the right child */
+ children[1].range[0] = split;
+ children[1].range[1] = node->range[1];
+
+ node = children + 0; /* Make left children the current node */
+ stack[istack] = ichildren + 1; /* Push the right children */
+ }
+ }
+ #undef CREATE_NODE
+
+exit:
+ return res;
+error:
+ darray_node_clear(&tree->nodes);
+ goto exit;
+}
diff --git a/src/sln_tree_c.h b/src/sln_tree_c.h
@@ -0,0 +1,56 @@
+/* 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_TREE_C_H
+#define SLN_TREE_C_H
+
+#include <rsys/dynamic_array.h>
+#include <rsys/ref_count.h>
+
+struct sln_device;
+struct sln_tree_create_args;
+struct shtr_lines_view;
+
+struct node {
+ /* Range of the line indices corresponding to the node. Both the lower and
+ * upper indices are included into the node */
+ uint64_t range[2];
+ int64_t offset; /* Offset toward the node's children (left then right) */
+};
+#define NODE_NULL__ {{0,0},0}
+static const struct node NODE_NULL = NODE_NULL__;
+
+/* Generate the dynamic array of nodes */
+#define DARRAY_DATA struct node
+#define DARRAY_NAME node
+#include <rsys/dynamic_array.h>
+
+struct sln_tree {
+ struct shtr_lines_view* lines_view; /* Set of lines */
+ struct darray_node nodes; /* Nodes used to partition the lines */
+
+ struct sln_device* sln;
+ ref_T ref;
+};
+
+extern LOCAL_SYM res_T
+tree_build
+ (struct sln_tree* tree,
+ const struct sln_tree_create_args* args);
+
+#endif /* SLN_TREE_C_H */