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