star-line

Structure for accelerating line importance sampling
git clone git://git.meso-star.fr/star-line.git
Log | Files | Refs | README | LICENSE

commit 282051b3137371ee09c4cf4228822ca03500992f
parent f069f3ff11ab67a53b9c6b89c88157fbff391e40
Author: Vincent Forest <vaplv@free.fr>
Date:   Wed, 20 Apr 2022 17:48:25 +0200

Build the tree

Diffstat:
Mcmake/CMakeLists.txt | 8+++++---
Msrc/sln.h | 24++++++++++++++++++++----
Msrc/sln_tree.c | 84+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------
Asrc/sln_tree_build.c | 97+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/sln_tree_c.h | 56++++++++++++++++++++++++++++++++++++++++++++++++++++++++
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 */