commit ac5ff20a46de29579ebc66ad468ed7d090c6d03a
parent 92fb592d0bd18bef9855ce1b5a596107c0fa40bb
Author: Anders Damsgaard <anders@adamsgaard.dk>
Date: Fri, 3 Jul 2026 11:25:05 +0200
test: add wet equilibrium and in-process error-path checks
- cngf_pf_wet_equilibrium: self-validating invariant asserting the top
physical node equals p_f_top (no .std baseline to bless a bug).
- test_error_path: in-process check that coupled_shear_solver returns a
non-zero code instead of terminating the caller.
- Exclude self-validating tests from the regenerable STANDARDS.
Diffstat:
2 files changed, 74 insertions(+), 3 deletions(-)
diff --git a/test/Makefile b/test/Makefile
@@ -7,6 +7,7 @@ TESTS = cngf_pf_dry \
cngf_pf_dry_cohesive \
cngf_pf_dry_vconst \
cngf_pf_wet \
+ cngf_pf_wet_equilibrium \
cngf_pf_wet_norm \
cngf_pf_wet_vari \
cngf_pf_wet_vari_diff \
@@ -14,6 +15,7 @@ TESTS = cngf_pf_dry \
cngf_pf_wet_vari_pulse_vlim \
shear_flux_dry \
shear_flux_wet \
+ test_error_path \
#cngf_pf_dry_transient \
# Skipped tests:
@@ -23,7 +25,10 @@ TESTS = cngf_pf_dry \
# - max_depth_misc: test config uses removed -O option
-STANDARDS := $(TESTS:=.std)
+# Self-validating tests carry no .std baseline, so exclude them from the
+# regenerable standards.
+STANDARDS := $(filter-out cngf_pf_wet_equilibrium.std test_error_path.std,\
+ $(TESTS:=.std))
CNGF_PF_DRY_OPTS = -o 0.03 -L 0.64 -n 40e3
CNGF_PF_DRY_NORM_OPTS = -o 0.03 -L 0.64 -n 40e3 -N
@@ -81,6 +86,16 @@ cngf_pf_dry_vconst: $(BIN)
cngf_pf_wet: $(BIN)
./$(BIN) $(CNGF_PF_WET_OPTS) | diff $@.std -
+# Self-validating invariant (no .std baseline): starting from the hydrostatic
+# initial state with a constant top pressure and no forcing, the profile must
+# stay hydrostatic, so the top physical node must equal p_f_top (0 Pa here).
+cngf_pf_wet_equilibrium: $(BIN)
+ ./$(BIN) $(CNGF_PF_WET_OPTS) | tail -n1 | \
+ awk '{ d = $$4; if (d < 0) d = -d; \
+ if (d > 1.0) { \
+ printf "error: top p_f deviates from p_f_top: %s Pa\n", $$4; \
+ exit 1 } }'
+
cngf_pf_wet_norm: $(BIN)
./$(BIN) $(CNGF_PF_WET_NORM_OPTS) | diff $@.std -
@@ -114,6 +129,13 @@ shear_flux_dry: $(BIN) $(BIN3)
shear_flux_wet: $(BIN)
./$(BIN) $(CNGF_PF_WET_OPTS) | ./$(BIN3) | diff $@.std -
+# In-process check: a non-converging solver must return a non-zero code
+# instead of terminating the process.
+test_error_path: $(BIN)
+ $(CC) -I.. -o $@ $@.c ../simulation.o ../arrays.o ../fluid.o -lm
+ ./$@
+ rm -f $@
+
cngf_pf_dry.std: $(BIN)
./$(BIN) $(CNGF_PF_DRY_OPTS) > $@
@@ -166,7 +188,7 @@ $(BIN):
make -C ..
clean:
- rm -f *.txt
+ rm -f *.txt test_error_path
# Benchmark configurations for performance/stability testing
# These are more intensive than the regression tests
@@ -189,4 +211,4 @@ bench_wet_large:
bench: bench_dry_small bench_dry_large bench_wet_small bench_wet_large
-.PHONY: $(TESTS) test standards clean bench bench_dry_small bench_dry_large bench_wet_small bench_wet_large
+.PHONY: $(TESTS) cngf_pf_wet_equilibrium test_error_path test standards clean bench bench_dry_small bench_dry_large bench_wet_small bench_wet_large
diff --git a/test/test_error_path.c b/test/test_error_path.c
@@ -0,0 +1,49 @@
+/*
+ * In-process check that a non-converging configuration makes
+ * coupled_shear_solver() return a non-zero error code instead of terminating
+ * the calling process. A host embedder (e.g. PISM) relies on this so a single
+ * failing column cannot kill the MPI process.
+ */
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "../simulation.h"
+
+int
+main(void)
+{
+ int i, ret;
+ struct simulation sim;
+
+ init_sim(&sim);
+ sim.nz = 10;
+ sim.origo_z = 0.03;
+ sim.L_z = 0.64;
+ sim.P_wall = 40e3;
+ sim.v_x_fix = 1e-3; /* velocity-driven mode */
+
+ if (prepare_arrays(&sim)) {
+ fprintf(stderr, "error: prepare_arrays failed\n");
+ return 2;
+ }
+ for (i = 0; i < sim.nz; ++i)
+ sim.phi[i] = 0.25;
+
+ lithostatic_pressure_distribution(&sim);
+ compute_effective_stress(&sim);
+
+ /* max_iter = 0 forces the stress solver to exceed its iteration budget
+ * and return a non-zero code rather than aborting the process */
+ ret = coupled_shear_solver(&sim, 0, 1e-5);
+
+ free_arrays(&sim);
+
+ if (ret == 0) {
+ fprintf(stderr, "error: solver unexpectedly converged (ret = 0)\n");
+ return 1;
+ }
+
+ printf("ok: coupled_shear_solver returned %d without terminating\n", ret);
+ return 0;
+}