star-uvm

Spatial structuring of unstructured volumetric meshes
git clone git://git.meso-star.fr/star-uvm.git
Log | Files | Refs | README | LICENSE

commit 676a52edf591956877ebfa43e7f1c845dcb9bd10
parent 0cb3177c9e90ab4cbe0d1deaafa33b48d2980cbf
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Fri, 21 Feb 2025 12:19:16 +0100

Write the tetrahedral mesh output from suvm-map-data

The mesh is in VTK format. Data mapping to tetrahedra is not yet
done.

Diffstat:
MMakefile | 2+-
Msrc/suvm_map_data.c | 215++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 214 insertions(+), 3 deletions(-)

diff --git a/Makefile b/Makefile @@ -129,7 +129,7 @@ PKG_CONFIG_LOCAL = PKG_CONFIG_PATH="./:$${PKG_CONFIG_PATH}" $(PKG_CONFIG) INCS_UTIL = $$($(PKG_CONFIG_LOCAL) $(PCFLAGS) --cflags rsys smsh suvm-local.pc) LIBS_UTIL = $$($(PKG_CONFIG_LOCAL) $(PCFLAGS) --libs rsys smsh suvm-local.pc) -lm -CFLAGS_UTIL = -std=c89 $(CFLAGS_EXE) $(INCS_UTIL) +CFLAGS_UTIL = -std=c99 $(CFLAGS_EXE) $(INCS_UTIL) LDFLAGS_UTIL = $(LDFLAGS_EXE) $(LIBS_UTIL) utils: library .config_utils diff --git a/src/suvm_map_data.c b/src/suvm_map_data.c @@ -15,13 +15,19 @@ #define _POSIX_C_SOURCE 200112L /* getopt support */ -#include <rsys/rsys.h> +#include <star/smsh.h> +#include <rsys/cstr.h> +#include <rsys/mem_allocator.h> + +#include <errno.h> +#include <string.h> /* strerror */ #include <unistd.h> /* getopt */ /* Maximum number of data items that can be mapped to each cell */ #define MAX_DATA 8 +/* Input arguments */ struct args { const char* mesh; /* Tetrahedral mesh */ const char* output; /* Output file */ @@ -29,11 +35,21 @@ struct args { /* List of data names. * If a name is missing for a data item, a default name is used */ - const char* names[8]; + const char* names[MAX_DATA]; int nnames; /* Number of names */ }; static const struct args ARGS_DEFAULT = {0}; +/* Command data */ +struct cmd { + struct smsh* mesh; /* Tetrahedral mesh */ + FILE* output; /* Ouput file */ + FILE* data; /* Data to map */ + + const char* names[MAX_DATA]; +}; +static const struct cmd CMD_NULL = {0}; + /******************************************************************************* * Helper functions ******************************************************************************/ @@ -89,6 +105,196 @@ error: goto exit; } +static res_T +check_mem_leaks(void) +{ + char buffer[128] = {0}; + size_t sz = 0; + + if((sz = mem_allocated_size()) == 0) + return RES_OK; /* No memory leak */ + + size_to_cstr(sz, SIZE_ALL, NULL, buffer, sizeof(buffer)); + fprintf(stderr, "Memory leaks: %s\n", buffer); + return RES_MEM_ERR; +} + +static res_T +write_vtk_header(struct cmd* cmd) +{ + res_T res = RES_OK; + ASSERT(cmd); + + #define FPRINTF(Msg) \ + { if(fprintf(cmd->output, Msg) < 0) goto error; } (void)0 + FPRINTF("# vtk DataFile Version 2.0\n"); + FPRINTF("Volumic mesh\n"); + FPRINTF("ASCII\n"); + #undef FPRINTF + +exit: + return res; +error: + fprintf(stderr, "header write error -- %s\n", strerror(errno)); + res = RES_IO_ERR; + goto exit; +} + +static res_T +write_mesh(struct cmd* cmd) +{ + struct smsh_desc desc = SMSH_DESC_NULL; + size_t i = 0; + res_T res = RES_OK; + + ASSERT(cmd); + + SMSH(get_desc(cmd->mesh, &desc)); + ASSERT(desc.dnode == 3); + ASSERT(desc.dcell == 4); + + #define FPRINTF(...) \ + { if(fprintf(cmd->output, __VA_ARGS__) < 0) goto error; } (void)0 + + FPRINTF("DATASET UNSTRUCTURED_GRID\n"); + + /* Vertices */ + FPRINTF("POINTS %zu double\n", desc.nnodes); + FOR_EACH(i, 0, desc.nnodes) FPRINTF("%f %F %f\n", SPLIT3(desc.nodes+i*3)); + + /* Cells */ + FPRINTF("CELLS %zu %zu\n", desc.ncells, desc.ncells*(4+1)); + FOR_EACH(i, 0, desc.ncells) FPRINTF("4 %zu %zu %zu %zu\n", SPLIT4(desc.cells+i*4)); + + /* Cell types */ + FPRINTF("CELL_TYPES %zu\n", desc.ncells); + FOR_EACH(i, 0, desc.ncells) FPRINTF("10\n"); /* VTK_TETRA == 10 */ + +exit: + return res; +error: + res = RES_IO_ERR; + fprintf(stderr, "mesh write error -- %s\n", strerror(errno)); + goto exit; +} + +static res_T +setup_mesh(struct cmd* cmd, const struct args* args) +{ + struct smsh_create_args create_args = SMSH_CREATE_ARGS_DEFAULT; + struct smsh_load_args load_args = SMSH_LOAD_ARGS_NULL; + struct smsh_desc desc = SMSH_DESC_NULL; + res_T res = RES_OK; + ASSERT(cmd && args); + + create_args.verbose = 1; + if((res = smsh_create(&create_args, &cmd->mesh)) != RES_OK) goto error; + + load_args.path = args->mesh; + if((res = smsh_load(cmd->mesh, &load_args)) != RES_OK) goto error; + + if((res = smsh_get_desc(cmd->mesh, &desc)) != RES_OK) goto error; + + if(desc.dnode != 3 || desc.dcell != 4) { + fprintf(stderr, + "expecting a tetrahedral mesh -- dcell = %u, dnode = %u\n", + desc.dcell, desc.dnode); + res = RES_BAD_ARG; + goto error; + } + +exit: + return res; +error: + if(cmd->mesh) { SMSH(ref_put(cmd->mesh)); cmd->mesh = NULL; } + goto exit; +} + +static res_T +setup_data(struct cmd* cmd, const struct args* args) +{ + res_T res = RES_OK; + ASSERT(cmd && args); + + if(!args->data) { + cmd->data = stdin; + } else if((cmd->data = fopen(args->data, "r")) == NULL) { + fprintf(stderr, "error opening data file '%s' -- %s\n", + args->data, strerror(errno)); + res = RES_IO_ERR; + goto error; + } + +exit: + return res; +error: + if(cmd->data) { CHK(fclose(cmd->data) == 0); cmd->data = NULL; } + goto exit; +} + +static res_T +setup_output(struct cmd* cmd, const struct args* args) +{ + res_T res = RES_OK; + ASSERT(cmd && args); + + if(!args->output) { + cmd->output = stdout; + } else if((cmd->output = fopen(args->output, "w")) == NULL) { + fprintf(stderr, "error opening output file '%s' -- %s\n", + args->output, strerror(errno)); + res = RES_IO_ERR; + goto error; + } + +exit: + return res; +error: + if(cmd->output) { CHK(fclose(cmd->output) == 0); cmd->output = NULL; } + goto exit; +} + +static res_T +cmd_init(struct cmd* cmd, const struct args* args) +{ + res_T res = RES_OK; + ASSERT(cmd && args); + + if((res = setup_mesh(cmd, args)) != RES_OK) goto error; + if((res = setup_data(cmd, args)) != RES_OK) goto error; + if((res = setup_output(cmd, args)) != RES_OK) goto error; + memcpy(cmd->names, args->names, sizeof(char*)*MAX_DATA); + +exit: + return res; +error: + goto exit; +} + +static void +cmd_release(struct cmd* cmd) +{ + ASSERT(cmd); + if(cmd->mesh) SMSH(ref_put(cmd->mesh)); + if(cmd->data && cmd->data != stdin) CHK(fclose(cmd->data) == 0); + if(cmd->output && cmd->output != stdout) CHK(fclose(cmd->output) == 0); +} + +static res_T +cmd_run(struct cmd* cmd) +{ + res_T res = RES_OK; + ASSERT(cmd); + + if((res = write_vtk_header(cmd)) != RES_OK) goto error; + if((res = write_mesh(cmd)) != RES_OK) goto error; + +exit: + return res; +error: + goto exit; +} + /******************************************************************************* * The program ******************************************************************************/ @@ -96,13 +302,18 @@ int main(int argc, char** argv) { struct args args = ARGS_DEFAULT; + struct cmd cmd = CMD_NULL; int err = 0; res_T res = RES_OK; if((res = args_init(&args, argc, argv)) != RES_OK) goto error; + if((res = cmd_init(&cmd, &args)) != RES_OK) goto error; + if((res = cmd_run(&cmd)) != RES_OK) goto error; exit: args_release(&args); + cmd_release(&cmd); + if((res = check_mem_leaks()) != RES_OK && !err) err = 1; return err; error: err = 1;