rnatm

Load and structure data describing an atmosphere
git clone git://git.meso-star.fr/rnatm.git
Log | Files | Refs | README | LICENSE

commit dee1860da5064bf52167534832c3903feb30fbfe
parent e9f545b525c8fbf0e5ddcf034339b311fbc512dc
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Tue, 19 Jul 2022 16:57:16 +0200

Load and structure volumetric meshes

Diffstat:
MREADME.md | 9+++++----
Mcmake/CMakeLists.txt | 9++++++---
Msrc/rnatm.c | 127+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
Msrc/rnatm.h | 7+++++--
Msrc/rnatm_c.h | 78++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/rnatm_mesh.c | 173+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
6 files changed, 391 insertions(+), 12 deletions(-)

diff --git a/README.md b/README.md @@ -20,10 +20,11 @@ on the [Rad-Net Scattering Function](https://gitlab.com/meso-star/rnsf), [RSys](https://gitlab.com/vaplv/rsys/), [Star-Aerosol](https://gitlab.com/meso-star/star-aerosol), [Star-Buffer](https://gitlab.com/meso-star/star-buffer), -[Star-CorrelatedK](https://gitlab.com/meso-star/star-ck) and -[Star-Mesh](https://gitlab.com/meso-star/star-mesh) libraries. It optionally -depends on [scdoc](https://sr.ht/~sircmpwn/scdoc/) which, if available, is used -to generate the man pages. +[Star-CorrelatedK](https://gitlab.com/meso-star/star-ck), +[Star-Mesh](https://gitlab.com/meso-star/star-mesh) and +[Star-UnstructuredVolumetricMesh](https://gitlab.com/meso-star/star-uvm) +libraries. It optionally depends on [scdoc](https://sr.ht/~sircmpwn/scdoc/) +which, if available, is used to generate the man pages. First ensure that CMake is installed on your system. Then install the RCMake package as well as the aforementioned prerequisites. Finally generate the diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt @@ -35,6 +35,7 @@ find_package(StarAerosol REQUIRED) find_package(StarBuffer REQUIRED) find_package(StarCK REQUIRED) find_package(StarMesh REQUIRED) +find_package(StarUVM 0.0 REQUIRED) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${RCMAKE_SOURCE_DIR}) include(rcmake) @@ -46,7 +47,8 @@ include_directories( ${StarAerosol_INCLUDE_DIR} ${StarBuffer_INCLUDE_DIR} ${StarCK_INCLUDE_DIR} - ${StarMesh_INCLUDE_DIR}) + ${StarMesh_INCLUDE_DIR} + ${StarUVM_INCLUDE_DIR}) ################################################################################ # Configure and define targets @@ -58,7 +60,8 @@ set(VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}) set(RNATM_FILES_SRC rnatm.c - rnatm_log.c) + rnatm_log.c + rnatm_mesh.c) set(RNATM_FILES_INC rnatm_c.h rnatm_log.h) @@ -72,7 +75,7 @@ rcmake_prepend_path(RNATM_FILES_INC_API ${RNATM_SOURCE_DIR}) rcmake_prepend_path(RNATM_FILES_DOC ${PROJECT_SOURCE_DIR}/../) add_library(rnatm SHARED ${RNATM_FILES_SRC} ${RNATM_FILES_INC} ${RNATM_FILES_INC_API}) -target_link_libraries(rnatm RSys) +target_link_libraries(rnatm RSys StarAerosol StarBuffer StarCK StarMesh StarUVM) set_target_properties(rnatm PROPERTIES DEFINE_SYMBOL RNATM_SHARED_BUILD diff --git a/src/rnatm.c b/src/rnatm.c @@ -22,6 +22,11 @@ #include "rnatm_c.h" #include "rnatm_log.h" +#include <star/sars.h> +#include <star/sbuf.h> +#include <star/sck.h> +#include <star/suvm.h> + #include <rsys/cstr.h> #include <rsys/mem_allocator.h> @@ -71,7 +76,7 @@ check_rnatm_create_args(const struct rnatm_create_args* args) if(res != RES_OK) return res; /* Invalid aerosols */ - FOR_EACH(i, 0, args->aerosols_count) { + FOR_EACH(i, 0, args->naerosols) { res = check_rnatm_aerosol_args(args->aerosols+i); if(res != RES_OK) return res; } @@ -108,10 +113,14 @@ create_rnatm res = RES_MEM_ERR; goto error; } + ref_init(&atm->ref); atm->allocator = allocator; atm->verbose = args->verbose; str_init(atm->allocator, &atm->name); + gas_init(atm->allocator, &atm->gas); + darray_aerosol_init(atm->allocator, &atm->aerosols); + if(args->logger) { atm->logger = args->logger; } else { @@ -126,6 +135,12 @@ create_rnatm } } + res = darray_aerosol_resize(&atm->aerosols, args->naerosols); + if(res != RES_OK) { + log_err(atm, "Could not allocate aerosol list -- %s\n", res_to_cstr(res)); + goto error; + } + res = str_set(&atm->name, args->name); if(res != RES_OK) { log_err(atm, "Could not setup the atmosphere name to `%s' -- %s\n", @@ -148,6 +163,8 @@ release_rnatm(ref_T* ref) ASSERT(ref); if(atm->logger == &atm->logger__) logger_release(&atm->logger__); + darray_aerosol_release(&atm->aerosols); + gas_release(&atm->gas); str_release(&atm->name); MEM_RM(atm->allocator, atm); } @@ -167,10 +184,9 @@ rnatm_create res = create_rnatm(args, &atm); if(res != RES_OK) goto error; - /* TODO res = setup_meshes(atm, args); if(res != RES_OK) goto error; - res = setup_octrees(atm, args); + /*res = setup_octrees(atm, args); if(res != RES_OK) goto error; res = setup_properties(atm, args); if(res != RES_OK) goto error; */ @@ -199,4 +215,109 @@ rnatm_ref_put(struct rnatm* atm) return RES_OK; } +/******************************************************************************* + * Local functions + ******************************************************************************/ +res_T +gas_init(struct mem_allocator* allocator, struct gas* gas) +{ + (void)allocator; + ASSERT(gas); + gas->volume = NULL; + gas->temperatures = NULL; + gas->ck = NULL; + return RES_OK; +} + +void +gas_release(struct gas* gas) +{ + ASSERT(gas); + if(gas->volume) SUVM(volume_ref_put(gas->volume)); + if(gas->temperatures) SBUF(ref_put(gas->temperatures)); + if(gas->ck) SCK(ref_put(gas->ck)); +} +res_T +gas_copy(struct gas* dst, const struct gas* src) +{ + ASSERT(dst && src); + if(dst->volume) SUVM(volume_ref_put(dst->volume)); + if(dst->temperatures) SBUF(ref_put(dst->temperatures)); + if(dst->ck) SCK(ref_put(dst->ck)); + dst->volume = src->volume; + dst->temperatures = src->temperatures; + dst->ck = src->ck; + if(dst->volume) SUVM(volume_ref_get(dst->volume)); + if(dst->temperatures) SBUF(ref_get(dst->temperatures)); + if(dst->ck) SCK(ref_get(dst->ck)); + return RES_OK; +} + +res_T +gas_copy_and_release(struct gas* dst, struct gas* src) +{ + ASSERT(dst && src); + if(dst->volume) SUVM(volume_ref_put(dst->volume)); + if(dst->temperatures) SBUF(ref_put(dst->temperatures)); + if(dst->ck) SCK(ref_put(dst->ck)); + dst->volume = src->volume; + dst->temperatures = src->temperatures; + dst->ck = src->ck; + src->volume = NULL; + src->temperatures = NULL; + src->ck = NULL; + return RES_OK; +} + +res_T +aerosol_init(struct mem_allocator* allocator, struct aerosol* aerosol) +{ + (void)allocator; + ASSERT(aerosol); + aerosol->volume = NULL; + aerosol->phase_fn_ids = NULL; + aerosol->sars = NULL; + return RES_OK; +} + +void +aerosol_release(struct aerosol* aerosol) +{ + ASSERT(aerosol); + if(aerosol->volume) SUVM(volume_ref_put(aerosol->volume)); + if(aerosol->phase_fn_ids) SBUF(ref_put(aerosol->phase_fn_ids)); + if(aerosol->sars) SARS(ref_put(aerosol->sars)); +} + +res_T +aerosol_copy(struct aerosol* dst, const struct aerosol* src) +{ + ASSERT(dst && src); + if(dst->volume) SUVM(volume_ref_put(dst->volume)); + if(dst->phase_fn_ids) SBUF(ref_put(dst->phase_fn_ids)); + if(dst->sars) SARS(ref_put(dst->sars)); + dst->volume = src->volume; + dst->phase_fn_ids = src->phase_fn_ids; + dst->sars = src->sars; + if(dst->volume) SUVM(volume_ref_get(dst->volume)); + if(dst->phase_fn_ids) SBUF(ref_get(dst->phase_fn_ids)); + if(dst->sars) SARS(ref_get(dst->sars)); + return RES_OK; +} + +res_T +aerosol_copy_and_release(struct aerosol* dst, struct aerosol* src) +{ + ASSERT(dst && src); + if(dst->volume) SUVM(volume_ref_put(dst->volume)); + if(dst->phase_fn_ids) SBUF(ref_put(dst->phase_fn_ids)); + if(dst->sars) SARS(ref_put(dst->sars)); + dst->volume = src->volume; + dst->phase_fn_ids = src->phase_fn_ids; + dst->sars = src->sars; + src->volume = NULL; + src->phase_fn_ids = NULL; + src->sars = NULL; + return RES_OK; +} diff --git a/src/rnatm.h b/src/rnatm.h @@ -68,10 +68,11 @@ static const struct rnatm_aerosol_args RNATM_AEROSOL_ARGS_NULL = struct rnatm_create_args { struct rnatm_gas_args gas; const struct rnatm_aerosol_args* aerosols; - size_t aerosols_count; - + size_t naerosols; const char* name; /* Name of the atmosphere */ + int precompute_normals; /* Pre-compute the tetrahedra normals */ + struct logger* logger; /* NULL <=> use default logger */ struct mem_allocator* allocator; /* NULL <=> use default allocator */ int verbose; /* Verbosity level */ @@ -82,6 +83,8 @@ struct rnatm_create_args { 0, /* Number of aerosols */ \ "atmosphere", /* Name */ \ \ + 0, /* Precompute tetrahedra normals */ \ + \ NULL, /* Logger */ \ NULL, /* Allocator */ \ 0 /* Verbosity level */ \ diff --git a/src/rnatm_c.h b/src/rnatm_c.h @@ -21,11 +21,84 @@ #ifndef RNATM_C_H #define RNATM_C_H +#include "rnatm.h" + +#include <rsys/dynamic_array.h> #include <rsys/logger.h> #include <rsys/ref_count.h> #include <rsys/str.h> +/******************************************************************************* + * Gas + ******************************************************************************/ +struct gas { + struct suvm_volume* volume; + struct sbuf* temperatures; + struct sck* ck; +}; + +extern LOCAL_SYM res_T +gas_init + (struct mem_allocator* allocator, + struct gas* gas); + +extern LOCAL_SYM void +gas_release + (struct gas* gas); + +extern LOCAL_SYM res_T +gas_copy + (struct gas* dst, + const struct gas* src); + +extern LOCAL_SYM res_T +gas_copy_and_release + (struct gas* dst, + struct gas* src); + +/******************************************************************************* + * Aerosol + ******************************************************************************/ +struct aerosol { + struct suvm_volume* volume; + struct sbuf* phase_fn_ids; + struct sars* sars; +}; + +extern LOCAL_SYM res_T +aerosol_init + (struct mem_allocator* allocator, + struct aerosol* aerosol); + +extern LOCAL_SYM void +aerosol_release + (struct aerosol* aerosol); + +extern LOCAL_SYM res_T +aerosol_copy + (struct aerosol* dst, + const struct aerosol* src); + +extern LOCAL_SYM res_T +aerosol_copy_and_release + (struct aerosol* dst, + struct aerosol* src); + +/* Define the dynamic array of aerosols */ +#define DARRAY_NAME aerosol +#define DARRAY_DATA struct aerosol +#define DARRAY_FUNCTOR_INIT aerosol_init +#define DARRAY_FUNCTOR_RELEASE aerosol_release +#define DARRAY_FUNCTOR_COPY aerosol_copy +#define DARRAY_FUNCTOR_COPY_AND_RELEASE aerosol_copy_and_release +#include <rsys/dynamic_array.h> + +/******************************************************************************* + * Atmosphere + ******************************************************************************/ struct rnatm { + struct gas gas; + struct darray_aerosol aerosols; struct str name; int verbose; @@ -35,4 +108,9 @@ struct rnatm { ref_T ref; }; +extern LOCAL_SYM res_T +setup_meshes + (struct rnatm* atm, + const struct rnatm_create_args* args); + #endif /* RNATM_C_H */ diff --git a/src/rnatm_mesh.c b/src/rnatm_mesh.c @@ -0,0 +1,173 @@ +/* Copyright (C) 2022 Centre National de la Recherche Scientifique + * Copyright (C) 2022 Institut de Physique du Globe de Paris + * Copyright (C) 2022 |Méso|Star> (contact@meso-star.com) + * Copyright (C) 2022 Université de Reims Champagne-Ardenne + * Copyright (C) 2022 Université de Versaille Saint-Quentin + * Copyright (C) 2022 Université Paul Sabatier (contact@laplace.univ-tlse.fr) + * + * 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 "rnatm_c.h" +#include "rnatm_log.h" + +#include <star/smsh.h> +#include <star/suvm.h> + +/******************************************************************************* + * Helper functions + ******************************************************************************/ +static res_T +check_smsh_desc(struct rnatm* atm, const struct smsh_desc* desc) +{ + res_T res = RES_OK; + ASSERT(atm && desc); + + if(desc->dnode != 3 && desc->dcell != 4) { + log_err(atm, + "An atmosphere mesh must be a 3D tetrahedral mesh " + "(dimension of the mesh: %u; dimension of the vertices: %u)\n", + desc->dnode, desc->dcell); + res = RES_BAD_ARG; + goto error; + } + +exit: + return res; +error: + goto exit; +} + +static INLINE void +tetrahedron_get_indices(const size_t itetra, size_t ids[4], void* ctx) +{ + const struct smsh_desc* desc = ctx; + const uint64_t* indices = NULL; + ASSERT(ctx && ids && itetra < desc->ncells && desc->dcell == 4); + indices = smsh_desc_get_cell(desc, itetra); + ids[0] = (size_t)indices[0]; + ids[1] = (size_t)indices[1]; + ids[2] = (size_t)indices[2]; + ids[3] = (size_t)indices[3]; +} + +static INLINE void +vertex_get_position(const size_t ivert, double pos[3], void* ctx) +{ + struct smsh_desc* desc = ctx; + const double* position = NULL; + ASSERT(ctx && pos && ivert < desc->nnodes && desc->dnode == 3); + position = smsh_desc_get_node(desc, ivert); + pos[0] = position[0]; + pos[1] = position[1]; + pos[2] = position[2]; +} + +static res_T +setup_uvm + (struct rnatm* atm, + const struct rnatm_create_args* args, + const char* filename, + struct suvm_device* suvm, + struct smsh* smsh, + struct suvm_volume** out_volume) +{ + struct suvm_tetrahedral_mesh_args mesh_args = SUVM_TETRAHEDRAL_MESH_ARGS_NULL; + struct smsh_desc smsh_desc = SMSH_DESC_NULL; + struct suvm_volume* volume = NULL; + res_T res = RES_OK; + ASSERT(atm && args && filename && suvm && smsh && out_volume); + + /* Load and retrieve the Star-Mesh data */ + res = smsh_load(smsh, filename); + if(res != RES_OK) goto error; + res = smsh_get_desc(smsh, &smsh_desc); + if(res != RES_OK) goto error; + res = check_smsh_desc(atm, &smsh_desc); + if(res != RES_OK) goto error; + + /* Partition the unstructured volumetric mesh */ + mesh_args.ntetrahedra = smsh_desc.ncells; + mesh_args.nvertices = smsh_desc.nnodes; + mesh_args.get_indices = tetrahedron_get_indices; + mesh_args.get_position = vertex_get_position; + mesh_args.tetrahedron_data = SUVM_DATA_NULL; /* Tetra data are not in SUVM */ + mesh_args.vertex_data = SUVM_DATA_NULL; /* Vertex data are not in SUVM */ + mesh_args.precompute_normals = args->precompute_normals; + mesh_args.context = &smsh_desc; + res = suvm_tetrahedral_mesh_create(suvm, &mesh_args, &volume); + if(res != RES_OK) goto error; + +exit: + *out_volume = volume; + return res; +error: + if(volume) SUVM(volume_ref_put(volume)); + goto exit; +} + +/******************************************************************************* + * Local functions + ******************************************************************************/ +res_T +setup_meshes(struct rnatm* atm, const struct rnatm_create_args* args) +{ + struct suvm_device* suvm = NULL; + struct smsh_create_args smsh_args = SMSH_CREATE_ARGS_DEFAULT; + struct smsh* smsh = NULL; + size_t i; + res_T res = RES_OK; + ASSERT(atm && args); + + /* Create the Star-UVM device */ + res = suvm_device_create(atm->logger, atm->allocator, atm->verbose, &suvm); + if(res != RES_OK) goto error; + + /* Create the Star-Mesh loader */ + smsh_args.logger = atm->logger; + smsh_args.allocator = atm->allocator; + smsh_args.verbose = atm->verbose; + res = smsh_create(&smsh_args, &smsh); + if(res != RES_OK) goto error; + + /* Load and structure gas volumetric mesh */ + res = setup_uvm + (atm, args, args->gas.smsh_filename, suvm, smsh, &atm->gas.volume); + if(res != RES_OK) goto error; + + /* Load and structure aerosol volumetric meshes */ + FOR_EACH(i, 0, args->naerosols) { + struct aerosol* aerosol = darray_aerosol_data_get(&atm->aerosols)+i; + const char* filename = args->aerosols[i].smsh_filename; + res = setup_uvm(atm, args, filename, suvm, smsh, &aerosol->volume); + if(res != RES_OK) goto error; + } + +exit: + if(smsh) SMSH(ref_put(smsh)); + if(suvm) SUVM(device_ref_put(suvm)); + return res; +error: + if(atm->gas.volume) { + SUVM(volume_ref_put(atm->gas.volume)); + atm->gas.volume = NULL; + } + FOR_EACH(i, 0, args->naerosols) { + struct aerosol* aerosol = darray_aerosol_data_get(&atm->aerosols)+i; + if(aerosol->volume) { + SUVM(volume_ref_put(aerosol->volume)); + aerosol->volume = NULL; + } + } + goto exit; +}