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:
| M | src/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;
}