star-gas

Load and structure gas data
git clone git://git.meso-star.fr/star-gas.git
Log | Files | Refs | README | LICENSE

commit 9cbcd3f1ca58337bc6c39e6aa115fbf22369fc53
parent 6a65aa86cab3e5f2f5616bb3706d28ad0e00c8b7
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Tue,  3 Mar 2026 16:44:17 +0100

Test the gas creation API

Diffstat:
MMakefile | 57++++++++++++++++++++++++++++++++++++++++++++++++++++++---
Asrc/test_sgas.c | 225+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 279 insertions(+), 3 deletions(-)

diff --git a/Makefile b/Makefile @@ -23,7 +23,7 @@ LIBNAME_SHARED = libsgas.so LIBNAME = $(LIBNAME_$(LIB_TYPE)) default: library -all: default util +all: default util tests ################################################################################ # Library @@ -88,7 +88,7 @@ util: library $(UTIL_DEP) $(MAKE) -fMakefile -f$(UTIL_DEP) sgas-lint $(UTIL_DEP): config.mk sgas-local.pc - $(CC) $(CFLAGS_UTIL) -MM -MT "$(@:.d=.o) $@" $(@:.d=.c) -MF $@ + @$(CC) $(CFLAGS_UTIL) -MM -MT "$(@:.d=.o) $@" $(@:.d=.c) -MF $@ $(UTIL_OBJ): config.mk sgas-local.pc $(CC) $(CFLAGS_UTIL) -c $(@:.o=.c) -o $@ @@ -147,9 +147,60 @@ uninstall: rm -f "$(DESTDIR)$(PREFIX)/share/doc/star-gas/COPYING" rm -f "$(DESTDIR)$(PREFIX)/share/doc/star-gas/README.md" -clean: clean_util +clean: clean_test clean_util rm -f $(DEP) $(OBJ) $(LIBNAME) rm -f .config libsgas.o sgas.pc sgas-local.pc lint: mandoc -Tlint -Wwarning doc/sgas-lint.1 + +################################################################################ +# Tests +################################################################################ +TEST_SRC = src/test_sgas.c +TEST_OBJ = $(TEST_SRC:.c=.o) +TEST_DEP = $(TEST_SRC:.c=.d) +TEST_TGT = $(TEST_SRC:.c=.t) + +INCS_TEST = $$($(PKG_CONFIG_LOCAL) $(PCFLAGS) --cflags rsys sgas-local) +LIBS_TEST = $$($(PKG_CONFIG_LOCAL) $(PCFLAGS) --libs rsys sgas-local) + +CFLAGS_TEST = -std=c89 $(CFLAGS_EXE) $(INCS_TEST) +LDFLAGS_TEST = $(LDFLAGS_EXE) $(LIBS_TEST) + +tests: library $(TEST_DEP) $(TEST_TGT) + @$(MAKE) -fMakefile \ + $$(for i in $(TEST_DEP); do echo -f"$${i}"; done) \ + $$(for i in $(TEST_TGT); do echo -f"$${i}"; done) \ + test_list + +$(TEST_TGT): + @{ \ + exe="$$(basename "$@" ".t")"; \ + printf '%s: %s\n' "$${exe}" $(@:.t=.o); \ + printf 'test_list: %s\n' "$${exe}"; \ + } > $@ + +$(TEST_DEP): config.mk sgas-local.pc + @$(CC) $(CFLAGS_TEST) -MM -MT "$(@:.d=.o) $@" $(@:.d=.c) -MF $@ + +$(TEST_OBJ): config.mk sgas-local.pc + $(CC) $(CFLAGS_TEST) -c $(@:.o=.c) -o $@ + +test_sgas: config.mk sgas-local.pc $(LIBNAME) + $(CC) $(CFLAGS_TEST) -o $@ src/$@.o $(LDFLAGS_TEST) + +clean_test: + rm -f $(TEST_DEP) $(TEST_OBJ) $(TEST_TGT) + rm -f mesh.smsh props.atrtp props_list.txt + +test: tests + @err=0; \ + printf 'test_sgas'; \ + if "./test_sgas" > /dev/null 2>&1; then \ + printf '\n'; \ + else \ + printf ': error %s\n' "$$?"; \ + err=$$((err+1)); \ + fi; \ + [ "$${err}" -eq 0 ] diff --git a/src/test_sgas.c b/src/test_sgas.c @@ -0,0 +1,225 @@ +/* Copyright (C) 2025, 2026 |Méso|Star> (contact@meso-star.com) + * Copyright (C) 2025, 2026 Université de Lorraine + * + * 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 "sgas.h" +#include <rsys/mem_allocator.h> + +static const double box_vertices[9/*#vertices*/*3/*#coords per vertex*/] = { + 0.0, 0.0, 0.0, + 1.0, 0.0, 0.0, + 0.0, 1.0, 0.0, + 1.0, 1.0, 0.0, + 0.0, 0.0, 1.0, + 1.0, 0.0, 1.0, + 0.0, 1.0, 1.0, + 1.0, 1.0, 1.0, + 0.5, 0.5, 0.5 +}; +static const uint64_t box_nverts = + (uint64_t)(sizeof(box_vertices) / (sizeof(double)*3)); + +/* The following array lists the indices toward the 3D vertices of each + * boundary triangle. The index 8 references the vertex at the center of the + * box. + * ,2---,3 ,2----3 + * ,' | ,'/| ,'/| \ | Y + * 6----7' / | 6' / | \ | | + * |', | / ,1 | / ,0---,1 o--X + * | ',|/,' |/,' | ,' / + * 4----5' 4----5' Z */ +static const uint64_t box_indices[12/*#tetras*/*4/*#indices per tetra*/] = { + 0, 1, 2, 8, 1, 3, 2, 8, /* -Z */ + 0, 2, 4, 8, 2, 6, 4, 8, /* -X */ + 4, 6, 5, 8, 6, 7, 5, 8, /* +Z */ + 3, 5, 7, 8, 5, 3, 1, 8, /* +X */ + 2, 7, 6, 8, 7, 2, 3, 8, /* +Y */ + 0, 5, 1, 8, 5, 0, 4, 8 /* -Y */ +}; +static const uint64_t box_ntetras = + (uint64_t)(sizeof(box_indices) / (sizeof(uint64_t)*4)); + +/******************************************************************************* + * Helper functions + ******************************************************************************/ +static void +write_smsh + (FILE* fp, + const double* verts, + const uint64_t nverts, + const uint64_t* ids, + const uint64_t ntetras) +{ + const uint64_t pagesize = 8192; + const uint32_t dimnode = 3; + const uint32_t dimcell = 4; + + + #define WRITE(Item, Count) \ + CHK(fwrite(Item, sizeof(*Item), (Count), fp) == (Count)) + + #define PADDING { \ + char byte = 0; \ + CHK(fseek(fp, (long)ALIGN_SIZE((size_t)ftell(fp), pagesize)-1, SEEK_SET) == 0); \ + CHK(fwrite(&byte, sizeof(byte), 1, fp) == 1); /* EOF indicator */ \ + } (void)0 + + /* Header */ + WRITE(&pagesize, 1); + WRITE(&nverts, 1); + WRITE(&ntetras, 1); + WRITE(&dimnode, 1); + WRITE(&dimcell, 1); + PADDING; + + /* Nodes */ + WRITE(verts, nverts*dimnode); + PADDING; + + /* Cells */ + WRITE(ids, ntetras*dimcell); + PADDING; + + CHK(fflush(fp) == 0); + + #undef WRITE + #undef PADDING +} + +static void +write_atrtp + (FILE* fp, + const uint64_t ntetras, + const uint64_t time_index) +{ + const uint64_t pagesize = 8192; + size_t i = 9; + + #define WRITE(Item, Count) \ + CHK(fwrite(Item, sizeof(*Item), (Count), fp) == (Count)) + + #define PADDING { \ + char byte = 0; \ + CHK(fseek(fp, (long)ALIGN_SIZE((size_t)ftell(fp), pagesize)-1, SEEK_SET) == 0); \ + CHK(fwrite(&byte, sizeof(byte), 1, fp) == 1); /* EOF indicator */ \ + } (void)0 + + /* Header */ + WRITE(&pagesize, 1); + WRITE(&ntetras, 1); + PADDING; + + FOR_EACH(i, 0, ntetras) { + /* Define an offset to be applied to thermodynamic properties in order to + * discriminate them by tetrahedron and temporal step */ + const double offset = (double)time_index*10 + (double)i*100; + const double pressure = 1 + offset; + const double temperature = 2 + offset; + const double xH2O = 3 + offset; + const double xCO2 = 4 + offset; + const double xCO = 5 + offset; + const double dummy = 0; + WRITE(&pressure, 1); + WRITE(&temperature, 1); + WRITE(&xH2O, 1); + WRITE(&xCO2, 1); + WRITE(&xCO, 1); + WRITE(&dummy, 1); /* vf-soot */ + WRITE(&dummy, 1); /* np-soot */ + WRITE(&dummy, 1); /* dp-soot */ + } + PADDING; +} + +static void +test_gas_creation(void) +{ + struct sgas_create_args args = SGAS_CREATE_ARGS_DEFAULT; + struct sgas* gas = NULL; + + const char* name_mesh = "mesh.smsh"; + const char* name_props = "props.atrtp"; + const char* name_props_list = "props_list.txt"; + FILE* fp_mesh = NULL; + FILE* fp_props = NULL; + FILE* fp_props_list = NULL; + + CHK(fp_mesh = fopen(name_mesh, "w+")); + write_smsh(fp_mesh, box_vertices, box_nverts, box_indices, box_ntetras); + + CHK(fp_props = fopen(name_props, "w")); + write_atrtp(fp_props, box_ntetras, 0/*time step*/); + CHK(fclose(fp_props) == 0); + + CHK(fp_props_list = fopen(name_props_list, "w+")); + CHK(fprintf(fp_props_list, "0 %s\n", name_props)); + CHK(fflush(fp_props_list) == 0); + + args.mesh.name = name_mesh; + args.therm_props_list.name = name_props_list; + args.verbose = 3; + + CHK(sgas_create(NULL, &gas) == RES_BAD_ARG); + CHK(sgas_create(&args, NULL) == RES_BAD_ARG); + CHK(sgas_create(&args, &gas) == RES_OK); + + CHK(sgas_ref_get(NULL) == RES_BAD_ARG); + CHK(sgas_ref_get(gas) == RES_OK); + CHK(sgas_ref_put(NULL) == RES_BAD_ARG); + CHK(sgas_ref_put(gas) == RES_OK); + CHK(sgas_ref_put(gas) == RES_OK); + + /* Missing mesh */ + args.mesh.name = NULL; + CHK(sgas_create(&args, &gas) == RES_BAD_ARG); + + /* Missing therm props list */ + args.mesh.name = name_mesh; + args.therm_props_list.name = NULL; + CHK(sgas_create(&args, &gas) == RES_BAD_ARG); + + /* Invalid stream of therm propos list */ + args.mesh.name = name_mesh; + args.therm_props_list.name = NULL; + args.therm_props_list.stream = fp_props_list; + CHK(sgas_create(&args, &gas) == RES_BAD_ARG); + + rewind(fp_props_list); + CHK(sgas_create(&args, &gas) == RES_OK); + CHK(sgas_ref_put(gas) == RES_OK); + + /* Invalid stream of mesh */ + rewind(fp_props_list); + args.mesh.stream = fp_mesh; + CHK(sgas_create(&args, &gas) != RES_OK); + + rewind(fp_mesh); + CHK(sgas_create(&args, &gas) == RES_OK); + CHK(sgas_ref_put(gas) == RES_OK); + + CHK(fclose(fp_mesh) == 0); + CHK(fclose(fp_props_list) == 0); +} + +/******************************************************************************* + * The test + ******************************************************************************/ +int +main(void) +{ + test_gas_creation(); + CHK(mem_allocated_size() == 0); + return 0; +}