star-gas

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

commit a16447a8f2adc2f0ca910ac923f2fb44c0eb01fb
parent 46fb7a7a6bb210431e7929b4939514dfdaf95db4
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Wed,  4 Mar 2026 10:34:10 +0100

Test spatio-temporal queries of gas properties

Diffstat:
Msrc/test_sgas.c | 165+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------
1 file changed, 154 insertions(+), 11 deletions(-)

diff --git a/src/test_sgas.c b/src/test_sgas.c @@ -14,9 +14,21 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ +#define _POSIX_C_SOURCE 200809L /* snprintf */ + #include "sgas.h" + #include <rsys/mem_allocator.h> +#include <stdio.h> + +/* Indentifier of thermodynamic properties */ +enum { PRESSURE, TEMPERATURE, XH2O, XCO2, XCO }; + +/* Define the value of a property according to its type of property, the + * tetrahedron to which it is attached and the time to which it is defined */ +#define PROP_VAL(Prop, Tetra, Time) ((double)(Prop+Tetra*100+Time*10)) + static const double box_vertices[9/*#vertices*/*3/*#coords per vertex*/] = { 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, @@ -122,28 +134,44 @@ write_atrtp 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 pressure = PROP_VAL(PRESSURE, i, time_index); + const double temperature = PROP_VAL(TEMPERATURE, i, time_index); + const double xH2O = PROP_VAL(XH2O, i, time_index); + const double xCO2 = PROP_VAL(XCO2, i, time_index); + const double xCO = PROP_VAL(XCO, i, time_index); + + /* Value of properties not exposed by the sgas library but required by the + * atrtp format. Its only requirement is that it be valid with respect to + * the properties for which it is used. */ 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 */ + WRITE(&dummy, 1); /* vf-soot (not used) */ + WRITE(&dummy, 1); /* np-soot (not used) */ + WRITE(&dummy, 1); /* dp-soot (not used) */ } PADDING; } static void +check_props + (const struct sgas_props* props, + const uint64_t tetra, + const uint64_t time) +{ + CHK(props); + CHK(props->pressure == PROP_VAL(PRESSURE, tetra, time)); + CHK(props->temperature == PROP_VAL(TEMPERATURE, tetra, time)); + CHK(props->xH2O == PROP_VAL(XH2O, tetra, time)); + CHK(props->xCO2 == PROP_VAL(XCO2, tetra, time)); + CHK(props->xCO == PROP_VAL(XCO, tetra, time)); +} + +static void test_gas_creation(void) { struct sgas_create_args args = SGAS_CREATE_ARGS_DEFAULT; @@ -213,6 +241,120 @@ test_gas_creation(void) CHK(fclose(fp_props_list) == 0); } +static void +test_gas_query(void) +{ + struct sgas_create_args args = SGAS_CREATE_ARGS_DEFAULT; + struct sgas_props props = SGAS_PROPS_NULL; + struct sgas* gas = NULL; + + const char* name_mesh = "mesh.smsh"; + const char* name_props_list = "props_list.txt"; + FILE* fp_mesh = NULL; + FILE* fp_props_list = NULL; + + double pos[3] = {0}; + const int ntime_steps = 4; + int i = 0; + + /* Create the gas mesh */ + CHK(fp_mesh = fopen(name_mesh, "w")); + write_smsh(fp_mesh, box_vertices, box_nverts, box_indices, box_ntetras); + CHK(fclose(fp_mesh) == 0); + + CHK(fp_props_list = fopen(name_props_list, "w")); + + /* Write the time varying thermodynamic properties + * and the file that lists them */ + FOR_EACH(i, 0, ntime_steps) { + char name_props[32] = {0}; + FILE* fp_props = NULL; + + CHK((size_t)snprintf(name_props, sizeof(name_props), "props%d.atrtp", i) + < sizeof(name_props)-1/*NULL byte*/); + + CHK(fp_props = fopen(name_props, "w")); + write_atrtp(fp_props, box_ntetras, (uint64_t)i/*time step*/); + CHK(fclose(fp_props) == 0); + + CHK(fprintf(fp_props_list, "0.%de1 %s\n", i, name_props) != 0); + } + CHK(fclose(fp_props_list) == 0); + + /* Create the gas from the previous data */ + args.mesh.name = name_mesh; + args.therm_props_list.name = name_props_list; + args.verbose = 1; + CHK(sgas_create(&args, &gas) == RES_OK); + + CHK(sgas_get_props(NULL, pos, 0, &props) == RES_BAD_ARG); + CHK(sgas_get_props(gas, NULL, 0, &props) == RES_BAD_ARG); + CHK(sgas_get_props(gas, pos, 0, NULL) == RES_BAD_ARG); + + /* The position is outside the mesh + * and therefore all returned properties are null */ + pos[0] = pos[1] = pos[2] = -1; + CHK(sgas_get_props(gas, pos, 0, &props) == RES_OK); + CHK(props.pressure == SGAS_PROPS_NULL.pressure); + CHK(props.temperature == SGAS_PROPS_NULL.temperature); + CHK(props.xH2O == SGAS_PROPS_NULL.xH2O); + CHK(props.xCO2 == SGAS_PROPS_NULL.xCO2); + CHK(props.xCO == SGAS_PROPS_NULL.xCO); + + /* Query the first tetrahedron at the first time */ + pos[0] = 0.25; + pos[1] = 0.50; + pos[2] = 0.25; + CHK(sgas_get_props(gas, pos, 0, &props) == RES_OK); + check_props(&props, 0/*tetra*/, 0/*time*/); + + /* Query the second tetrahedron, always at the first time */ + pos[0] = 0.75; + pos[1] = 0.50; + pos[2] = 0.25; + CHK(sgas_get_props(gas, pos, 0, &props) == RES_OK); + check_props(&props, 1/*tetra*/, 0/*time*/); + + /* Do not move but query a time beyond the limit, i.e. time is truncated at + * the last defined time */ + CHK(sgas_get_props(gas, pos, ntime_steps, &props) == RES_OK); + check_props(&props, 1/*tetra*/, (uint64_t)(ntime_steps-1)/*time*/); + + /* Query a time near the third time step */ + CHK(sgas_get_props(gas, pos, 1.51, &props) == RES_OK); + check_props(&props, 1/*tetra*/, 2/*time*/); + CHK(sgas_get_props(gas, pos, 2.49, &props) == RES_OK); + check_props(&props, 1/*tetra*/, 2/*time*/); + + /* Query a position in the 9^th tetrahedron near the second time step. + * + * Note that the position was calculated from the vertices of the tetrahedron + * using the ssp_ran_tetrahedron_uniform function of the Star-SamPling + * library, via an adhoc executable. Do not use Star-SamPling directly here + * avoid making it a project dependency. */ + pos[0] = 0.23; + pos[1] = 0.98; + pos[2] = 0.52; + CHK(sgas_get_props(gas, pos, 0.7, &props) == RES_OK); + check_props(&props, 8/*tetra*/, 1/*time*/); + + /* Query properties in the same position but exactly between 2 steps of time. + * In this case, none of the two times is better than the other. The queried + * time step depends only on a choice of arbitrary implementation. Below is + * therefore verified that the properties returned correspond to those of the + * tetrahedron for one of the 2 valid time steps */ + CHK(sgas_get_props(gas, pos, 1.5, &props) == RES_OK); + if(props.pressure == PROP_VAL(PRESSURE, 8/*tetra*/, 1/*time*/)) { + check_props(&props, 8/*tetra*/, 1/*time*/); + } else if(props.pressure == PROP_VAL(PRESSURE, 8/*tetra*/, 2/*time*/)) { + check_props(&props, 8/*tetra*/, 2/*time*/); + } else { + CHK(0); /* Unexpected properties values */ + } + + CHK(sgas_ref_put(gas) == RES_OK); +} + /******************************************************************************* * The test ******************************************************************************/ @@ -220,6 +362,7 @@ int main(void) { test_gas_creation(); + test_gas_query(); CHK(mem_allocated_size() == 0); return 0; }