atrstm

Load and structure a combustion gas mixture
git clone git://git.meso-star.fr/atrstm.git
Log | Files | Refs | README | LICENSE

commit 93a23f206fd9258a1c3304c2e05dadd0d09865f5
parent 1f74f76ba128ff6593160cf05132a4ebff9b17ce
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Mon, 25 Jan 2021 21:35:27 +0100

Add the atrstm_dump_svx_octree function

Diffstat:
Mcmake/CMakeLists.txt | 1+
Msrc/atrstm.h | 9++++++---
Asrc/atrstm_dump_svx_octree.c | 238+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 245 insertions(+), 3 deletions(-)

diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt @@ -55,6 +55,7 @@ set(VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}) set(ATRSTM_FILES_SRC atrstm.c atrstm_cache.c + atrstm_dump_svx_octree.c atrstm_log.c atrstm_partition.c atrstm_radcoefs.c diff --git a/src/atrstm.h b/src/atrstm.h @@ -217,6 +217,9 @@ struct atrstm_dump_svx_octree_args { static const struct atrstm_dump_svx_octree_args ATRSTM_DUMP_SVX_OCTREE_ARGS_DEFAULT = ATRSTM_DUMP_SVX_OCTREE_ARGS_DEFAULT__; +typedef double atrstm_radcoefs_T[ATRSTM_RADCOEFS_COUNT__]; +typedef double atrstm_radcoefs_svx_T[ATRSTM_RADCOEFS_COUNT__][ATRSTM_SVX_OPS_COUNT__]; + /* Forward declaration of extern data types */ struct logger; struct mem_allocator; @@ -252,19 +255,19 @@ ATRSTM_API res_T atrstm_fetch_radcoefs (const struct atrstm* atrstm, const struct atrstm_fetch_radcoefs_args* args, - double radcoefs[ATRSTM_RADCOEFS_COUNT__]);/*In m^-1*/ + atrstm_radcoefs_T radcoefs); /* In m^-1 */ ATRSTM_API res_T atrstm_fetch_radcoefs_svx (const struct atrstm* atrstm, const struct atrstm_fetch_radcoefs_svx_args* args, - double radcoefs[ATRSTM_RADCOEFS_COUNT__][ATRSTM_SVX_OPS_COUNT__]);/*In m^-1*/ + atrstm_radcoefs_svx_T radcoefs); /* In m^-1 */ ATRSTM_API res_T atrstm_fetch_radcoefs_svx_voxel (const struct atrstm* atrstm, const struct atrstm_fetch_radcoefs_svx_voxel_args* args, - double radcoefs[ATRSTM_RADCOEFS_COUNT__][ATRSTM_SVX_OPS_COUNT__]);/*In m^-1*/ + atrstm_radcoefs_svx_T radcoefs); /* In m^-1 */ ATRSTM_API res_T atrstm_dump_svx_octree diff --git a/src/atrstm_dump_svx_octree.c b/src/atrstm_dump_svx_octree.c @@ -0,0 +1,238 @@ +/* Copyright (C) 2020 CNRS + * + * 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 "atrstm.h" +#include "atrstm_c.h" + +#include <rsys/dynamic_array_double.h> +#include <rsys/dynamic_array_size_t.h> +#include <rsys/hash_table.h> + +#include <star/svx.h> + +struct vertex { + double x; + double y; + double z; +}; + +static char +vertex_eq(const struct vertex* v0, const struct vertex* v1) +{ + return eq_eps(v0->x, v1->x, 1.e-6) + && eq_eps(v0->y, v1->y, 1.e-6) + && eq_eps(v0->z, v1->z, 1.e-6); +} + +/* Generate the htable_vertex data structure */ +#define HTABLE_NAME vertex +#define HTABLE_KEY struct vertex +#define HTABLE_DATA size_t +#define HTABLE_KEY_FUNCTOR_EQ vertex_eq +#include <rsys/hash_table.h> + +/* Temporary data structure used to dump the octree data into a VTK file */ +struct octree_data { + struct htable_vertex vertex2id; /* Map a coordinate to its vertex id */ + struct darray_double vertices; /* Array of unique vertices */ + struct darray_double data; /* List of registered leaf data */ + struct darray_size_t cells; /* Ids of the cell vertices */ + const struct atrstm* atrstm; +}; + +/******************************************************************************* + * Helper functions + ******************************************************************************/ +static int +check_dump_octree_args + (const struct atrstm* atrstm, + const struct atrstm_dump_svx_octree_args* args) +{ + ASSERT(atrstm && args); + (void)atrstm; + return args + && args->iband == ATRSTM_DUMP_SVX_OCTREE_ARGS_DEFAULT.iband /* Not use yet */ + && args->iquad == ATRSTM_DUMP_SVX_OCTREE_ARGS_DEFAULT.iquad; /* Not use yet */ +} + +static void +octree_data_init + (const struct atrstm* atrstm, + struct octree_data* data) +{ + ASSERT(data); + htable_vertex_init(atrstm->allocator, &data->vertex2id); + darray_double_init(atrstm->allocator, &data->vertices); + darray_double_init(atrstm->allocator, &data->data); + darray_size_t_init(atrstm->allocator, &data->cells); + data->atrstm = atrstm; +} + +static void +octree_data_release(struct octree_data* data) +{ + ASSERT(data); + htable_vertex_release(&data->vertex2id); + darray_double_release(&data->vertices); + darray_double_release(&data->data); + darray_size_t_release(&data->cells); +} + +static void +register_leaf + (const struct svx_voxel* leaf, + const size_t ileaf, + void* context) +{ + struct atrstm_fetch_radcoefs_svx_voxel_args args = + ATRSTM_FETCH_RADCOEFS_SVX_VOXEL_ARGS_DEFAULT; + atrstm_radcoefs_svx_T radcoefs; + struct octree_data* ctx = context; + struct vertex v[8]; + double kext_min; + double kext_max; + int i; + ASSERT(leaf && ctx); + (void)ileaf; + + /* Compute the leaf vertices */ + v[0].x = leaf->lower[0]; v[0].y = leaf->lower[1]; v[0].z = leaf->lower[2]; + v[1].x = leaf->upper[0]; v[1].y = leaf->lower[1]; v[1].z = leaf->lower[2]; + v[2].x = leaf->lower[0]; v[2].y = leaf->upper[1]; v[2].z = leaf->lower[2]; + v[3].x = leaf->upper[0]; v[3].y = leaf->upper[1]; v[3].z = leaf->lower[2]; + v[4].x = leaf->lower[0]; v[4].y = leaf->lower[1]; v[4].z = leaf->upper[2]; + v[5].x = leaf->upper[0]; v[5].y = leaf->lower[1]; v[5].z = leaf->upper[2]; + v[6].x = leaf->lower[0]; v[6].y = leaf->upper[1]; v[6].z = leaf->upper[2]; + v[7].x = leaf->upper[0]; v[7].y = leaf->upper[1]; v[7].z = leaf->upper[2]; + + FOR_EACH(i, 0, 8) { + size_t *pid = htable_vertex_find(&ctx->vertex2id, v+i); + size_t id; + if(pid) { + id = *pid; + } else { /* Register the leaf vertex */ + id = darray_double_size_get(&ctx->vertices)/3; + CHK(RES_OK == htable_vertex_set(&ctx->vertex2id, v+i, &id)); + CHK(RES_OK == darray_double_push_back(&ctx->vertices, &v[i].x)); + CHK(RES_OK == darray_double_push_back(&ctx->vertices, &v[i].y)); + CHK(RES_OK == darray_double_push_back(&ctx->vertices, &v[i].z)); + } + /* Add the vertex id to the leaf cell */ + CHK(RES_OK == darray_size_t_push_back(&ctx->cells, &id)); + } + + /* Fetch leaf data */ + args.voxel = *leaf; + args.components_mask = ATRSTM_CPNTS_MASK_ALL; + args.radcoefs_mask = ATRSTM_RADCOEF_FLAG_Kext; + args.operations_mask = ATRSTM_SVX_OPS_MASK_ALL; + ATRSTM(fetch_radcoefs_svx_voxel(ctx->atrstm, &args, radcoefs)); + + /* Register leaf data */ + kext_min = radcoefs[ATRSTM_RADCOEF_Kext][ATRSTM_SVX_OP_MIN]; + kext_max = radcoefs[ATRSTM_RADCOEF_Kext][ATRSTM_SVX_OP_MAX]; + if(kext_min > kext_max) {/* Empty voxel */ + kext_min = kext_max = 0; + } + + CHK(RES_OK == darray_double_push_back(&ctx->data, &kext_min)); + CHK(RES_OK == darray_double_push_back(&ctx->data, &kext_max)); +} + +/******************************************************************************* + * Exported functions + ******************************************************************************/ +res_T +atrstm_dump_svx_octree + (const struct atrstm* atrstm, + const struct atrstm_dump_svx_octree_args* args, + FILE* stream) +{ + struct octree_data data; + const double* leaf_data; + size_t nvertices; + size_t ncells; + size_t i; + res_T res = RES_OK; + + if(!atrstm || !check_dump_octree_args(atrstm, args)) { + res = RES_BAD_ARG; + goto error; + } + + octree_data_init(atrstm, &data); + + /* Register leaf data */ + SVX(tree_for_each_leaf(atrstm->octree, register_leaf, &data)); + nvertices = darray_double_size_get(&data.vertices)/3/*#coords per vertex*/; + ncells = darray_size_t_size_get(&data.cells)/8/*#ids per cell*/; +#ifndef NDEBUG + { + struct svx_tree_desc octree_desc = SVX_TREE_DESC_NULL; + SVX(tree_get_desc(atrstm->octree, &octree_desc)); + ASSERT(ncells == octree_desc.nleaves); + } +#endif + + /* Write headers */ + fprintf(stream, "# vtk DataFile Version 2.0\n"); + fprintf(stream, "Radiative coefficients in [%g, %g]\n", + atrstm->wlen_range[0], atrstm->wlen_range[1]); + fprintf(stream, "ASCII\n"); + fprintf(stream, "DATASET UNSTRUCTURED_GRID\n"); + + /* Write vertex coordinates */ + fprintf(stream, "POINTS %lu float\n", (unsigned long)nvertices); + FOR_EACH(i, 0, nvertices) { + fprintf(stream, "%g %g %g\n", + SPLIT3(darray_double_cdata_get(&data.vertices) + i*3)); + } + + /* Write the cells */ + fprintf(stream, "CELLS %lu %lu\n", + (unsigned long)ncells, + (unsigned long)(ncells*(8/*#verts per cell*/ + 1/*1st field of a cell*/))); + FOR_EACH(i, 0, ncells) { + fprintf(stream, "8 %lu %lu %lu %lu %lu %lu %lu %lu\n", + (unsigned long)darray_size_t_cdata_get(&data.cells)[i*8+0], + (unsigned long)darray_size_t_cdata_get(&data.cells)[i*8+1], + (unsigned long)darray_size_t_cdata_get(&data.cells)[i*8+2], + (unsigned long)darray_size_t_cdata_get(&data.cells)[i*8+3], + (unsigned long)darray_size_t_cdata_get(&data.cells)[i*8+4], + (unsigned long)darray_size_t_cdata_get(&data.cells)[i*8+5], + (unsigned long)darray_size_t_cdata_get(&data.cells)[i*8+6], + (unsigned long)darray_size_t_cdata_get(&data.cells)[i*8+7]); + } + + /* Write the cell type */ + fprintf(stream, "CELL_TYPES %lu\n", (unsigned long)ncells); + FOR_EACH(i, 0, ncells) fprintf(stream, "11\n"); + + /* Write the cell data */ + leaf_data = darray_double_cdata_get(&data.data); + fprintf(stream, "CELL_DATA %lu\n", (unsigned long)ncells); + fprintf(stream, "SCALARS Kext double 2\n"); + fprintf(stream, "LOOKUP_TABLE default\n"); + FOR_EACH(i, 0, ncells) { + fprintf(stream, "%g %g\n", leaf_data[i*2+0], leaf_data[i*2+1]); + } + octree_data_release(&data); + +exit: + return res; +error: + goto exit; +} +