cngf-pf

continuum model for granular flows with pore-pressure dynamics (renamed from 1d_fd_simple_shear)
git clone git://src.adamsgaard.dk/cngf-pf # fast
git clone https://src.adamsgaard.dk/cngf-pf.git # slow
Log | Files | Refs | README | LICENSE Back to index

commit c8a8f4d1023c7ba4fca2f979e454c42f5747dd06
parent 8ee190a791f59c6d83108b5f7018217a652f47c8
Author: Anders Damsgaard <anders@adamsgaard.dk>
Date:   Fri,  3 Jul 2026 11:50:16 +0200

test: add reset_column round-trip check against a fresh column run

Diffstat:
Mtest/Makefile | 15++++++++++++---
Atest/test_reset_column.c | 140+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 152 insertions(+), 3 deletions(-)

diff --git a/test/Makefile b/test/Makefile @@ -16,6 +16,7 @@ TESTS = cngf_pf_dry \ shear_flux_dry \ shear_flux_wet \ test_error_path \ + test_reset_column \ #cngf_pf_dry_transient \ # Skipped tests: @@ -27,7 +28,8 @@ TESTS = cngf_pf_dry \ # 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,\ +STANDARDS := $(filter-out cngf_pf_wet_equilibrium.std test_error_path.std \ + test_reset_column.std,\ $(TESTS:=.std)) CNGF_PF_DRY_OPTS = -o 0.03 -L 0.64 -n 40e3 @@ -136,6 +138,13 @@ test_error_path: $(BIN) ./$@ rm -f $@ +# In-process check: rerunning a column after reset_column() must reproduce a +# fresh prepare_arrays() run bit for bit. +test_reset_column: $(BIN) + $(CC) -I.. -o $@ $@.c ../simulation.o ../arrays.o ../fluid.o -lm + ./$@ + rm -f $@ + cngf_pf_dry.std: $(BIN) ./$(BIN) $(CNGF_PF_DRY_OPTS) > $@ @@ -188,7 +197,7 @@ $(BIN): make -C .. clean: - rm -f *.txt test_error_path + rm -f *.txt test_error_path test_reset_column # Benchmark configurations for performance/stability testing # These are more intensive than the regression tests @@ -211,4 +220,4 @@ bench_wet_large: 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 +.PHONY: $(TESTS) cngf_pf_wet_equilibrium test_error_path test_reset_column test standards clean bench bench_dry_small bench_dry_large bench_wet_small bench_wet_large diff --git a/test/test_reset_column.c b/test/test_reset_column.c @@ -0,0 +1,140 @@ +/* + * In-process check that reset_column() returns a used simulation struct to a + * state equivalent to a freshly prepared one: running the same column setup + * after a reset must reproduce a fresh run bit for bit. A host embedder + * (e.g. PISM) relies on this to reuse one allocated struct across many + * independent till columns. + */ +#include <math.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "../fluid.h" +#include "../simulation.h" + +#define NSTEPS 3 +#define PHI_TEST 0.3 +#define K_TEST 2e-15 + +static int +cmp(const char *name, const double *a, const double *b, int n) +{ + if (memcmp(a, b, (size_t)n * sizeof(double)) != 0) { + fprintf(stderr, "error: %s differs between fresh and reset run\n", + name); + return 1; + } + return 0; +} + +static int +setup_column(struct simulation *sim) +{ + int i; + + for (i = 0; i < sim->nz; ++i) { + sim->phi[i] = PHI_TEST; + sim->k[i] = K_TEST; + } + hydrostatic_fluid_pressure_distribution(sim); + lithostatic_pressure_distribution(sim); + compute_effective_stress(sim); + return set_largest_fluid_timestep(sim, 0.5); +} + +static int +run_column(struct simulation *sim) +{ + int n, ret; + + for (n = 0; n < NSTEPS; ++n) + if ((ret = coupled_shear_solver(sim, 100000, 1e-5))) { + fprintf(stderr, "error: solver returned %d at step %d\n", + ret, n); + return 1; + } + return 0; +} + +static void +init_column(struct simulation *sim) +{ + init_sim(sim); + sim->nz = 10; + sim->origo_z = 0.03; + sim->L_z = 0.64; + sim->P_wall = 40e3; + sim->fluid = 1; +} + +int +main(void) +{ + int i, status = 0; + struct simulation fresh, reused; + + init_column(&fresh); + if (prepare_arrays(&fresh)) { + fprintf(stderr, "error: prepare_arrays failed\n"); + return 2; + } + if (setup_column(&fresh) || run_column(&fresh)) + return 2; + + /* dirty a second struct with a different column, then reset and rerun + * the same column as the fresh reference */ + init_column(&reused); + if (prepare_arrays(&reused)) { + fprintf(stderr, "error: prepare_arrays failed\n"); + return 2; + } + for (i = 0; i < reused.nz; ++i) { + reused.phi[i] = 0.2; + reused.k[i] = 1.9e-15; + } + hydrostatic_fluid_pressure_distribution(&reused); + lithostatic_pressure_distribution(&reused); + compute_effective_stress(&reused); + if (set_largest_fluid_timestep(&reused, 0.5) || run_column(&reused)) + return 2; + + reset_column(&reused); + if (setup_column(&reused) || run_column(&reused)) + return 2; + + status |= cmp("phi", fresh.phi, reused.phi, fresh.nz); + status |= cmp("k", fresh.k, reused.k, fresh.nz); + status |= cmp("v_x", fresh.v_x, reused.v_x, fresh.nz); + status |= cmp("d_x", fresh.d_x, reused.d_x, fresh.nz); + status |= cmp("mu", fresh.mu, reused.mu, fresh.nz); + status |= cmp("mu_c", fresh.mu_c, reused.mu_c, fresh.nz); + status |= cmp("sigma_n", fresh.sigma_n, reused.sigma_n, fresh.nz); + status |= cmp("sigma_n_eff", fresh.sigma_n_eff, reused.sigma_n_eff, + fresh.nz); + status |= cmp("gamma_dot_p", fresh.gamma_dot_p, reused.gamma_dot_p, + fresh.nz); + status |= cmp("I", fresh.I, reused.I, fresh.nz); + status |= cmp("tan_psi", fresh.tan_psi, reused.tan_psi, fresh.nz); + status |= cmp("xi", fresh.xi, reused.xi, fresh.nz); + status |= cmp("g_local", fresh.g_local, reused.g_local, fresh.nz); + status |= cmp("phi_c", fresh.phi_c, reused.phi_c, fresh.nz); + status |= cmp("phi_dot", fresh.phi_dot, reused.phi_dot, fresh.nz); + status |= cmp("p_f_dot", fresh.p_f_dot, reused.p_f_dot, fresh.nz); + status |= cmp("p_f_ghost", fresh.p_f_ghost, reused.p_f_ghost, + fresh.nz + 2); + status |= cmp("p_f_next_ghost", fresh.p_f_next_ghost, + reused.p_f_next_ghost, fresh.nz + 2); + status |= cmp("g_ghost", fresh.g_ghost, reused.g_ghost, fresh.nz + 2); + status |= cmp("t", &fresh.t, &reused.t, 1); + status |= cmp("mu_wall", &fresh.mu_wall, &reused.mu_wall, 1); + + free_arrays(&fresh); + free_arrays(&reused); + + if (status) + return 1; + + printf("ok: reset_column reproduces a fresh column run\n"); + return 0; +}