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:
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;
+}