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 58aabfabbd2e3c01e27e30d908514cebef245b2a
parent 74fadc86b83bfaa0064ecf36dc68689c7db2036f
Author: Anders Damsgaard <anders@adamsgaard.dk>
Date:   Mon, 23 Nov 2020 13:20:43 +0100

fix code style and correct top fluid pressure with dirichlet BC

Diffstat:
Mcngf-pf.1 | 4++--
Mcngf-pf.c | 87+++++++++++++++++++++++++++++++++++++++----------------------------------------
Mfluid.c | 161+++++++++++++++++++++++++++++++++++++++++++++----------------------------------
Mmax_depth_simple_shear.c | 54++++++++++++++++++++++++++----------------------------
Mshear_flux.c | 15+++++++--------
Msimulation.c | 161++++++++++++++++++++++++++++++++++++++++++-------------------------------------
Msimulation.h | 2+-
7 files changed, 255 insertions(+), 229 deletions(-)

diff --git a/cngf-pf.1 b/cngf-pf.1 @@ -75,9 +75,9 @@ Only relevant with fluid dynamics enabled .It Fl c Ar grain-cohesion Granular material cohesion [Pa] (default 0). .It Fl D Ar fluid-diffusivity -Fluid diffusion coefficient [m^2/s] (default -1). Overrides fluid +Fluid diffusion coefficient [m^2/s] (default -1). Overrides fluid permeability (-k), grain compressibility (-P), fluid compressibility -(-C), and fluid viscosity (-i). Do not use for transient simulations +(-C), and fluid viscosity (-i). Do not use for transient simulations (-T). Disabled when set to a negative value. .It Fl d Ar grain-size Granular material representative grain size [m] (default 0.04). diff --git a/cngf-pf.c b/cngf-pf.c @@ -3,6 +3,7 @@ #include <string.h> #include <time.h> #include <unistd.h> +#include <err.h> #include "simulation.h" #include "fluid.h" @@ -22,45 +23,45 @@ static void usage(void) { fprintf(stderr, "usage: %s " - "[-A grain-nonlocal-ampl] " - "[-a fluid-pressure-ampl] " - "[-b grain-rate-dependence] " - "[-C fluid-compressibility] " - "[-c grain-cohesion] " - "[-d grain-size] " - "[-D fluid-diffusivity] " - "[-e end-time] " - "[-F] " - "[-f applied-shear-friction] " - "[-g gravity-accel] " - "[-H fluid-pressure-phase] " - "[-h] " - "[-I file-interval] " - "[-i fluid-viscosity] " - "[-K dilatancy-constant] " - "[-k fluid-permeability] " - "[-L length] " - "[-l applied-shear-vel-limit] " - "[-m grain-friction] " - "[-N] " - "[-n normal-stress] " - "[-O fluid-pressure-top] " - "[-o origo] " - "[-P grain-compressibility] " - "[-p grain-porosity] " - "[-q fluid-pressure-freq] " - "[-R fluid-density] " - "[-r grain-density] " - "[-S fluid-pressure-pulse-shape] " - "[-s applied-shear-vel] " - "[-T] " - "[-t curr-time] " - "[-U resolution] " - "[-u fluid-pulse-time] " - "[-v] " - "[-Y max-porosity] " - "[-y min-porosity] " - "[name]\n", argv0); + "[-A grain-nonlocal-ampl] " + "[-a fluid-pressure-ampl] " + "[-b grain-rate-dependence] " + "[-C fluid-compressibility] " + "[-c grain-cohesion] " + "[-d grain-size] " + "[-D fluid-diffusivity] " + "[-e end-time] " + "[-F] " + "[-f applied-shear-friction] " + "[-g gravity-accel] " + "[-H fluid-pressure-phase] " + "[-h] " + "[-I file-interval] " + "[-i fluid-viscosity] " + "[-K dilatancy-constant] " + "[-k fluid-permeability] " + "[-L length] " + "[-l applied-shear-vel-limit] " + "[-m grain-friction] " + "[-N] " + "[-n normal-stress] " + "[-O fluid-pressure-top] " + "[-o origo] " + "[-P grain-compressibility] " + "[-p grain-porosity] " + "[-q fluid-pressure-freq] " + "[-R fluid-density] " + "[-r grain-density] " + "[-S fluid-pressure-pulse-shape] " + "[-s applied-shear-vel] " + "[-T] " + "[-t curr-time] " + "[-U resolution] " + "[-u fluid-pulse-time] " + "[-v] " + "[-Y max-porosity] " + "[-y min-porosity] " + "[name]\n", argv0); exit(1); } @@ -79,10 +80,8 @@ main(int argc, char *argv[]) #endif #ifdef __OpenBSD__ - if (pledge("stdio wpath cpath", NULL) == -1) { - fprintf(stderr, "error: pledge failed"); - exit(2); - } + if (pledge("stdio wpath cpath", NULL) == -1) + err(2, "pledge failed"); #endif init_sim(&sim); @@ -276,7 +275,7 @@ main(int argc, char *argv[]) if ((filetimeclock >= sim.file_dt || iter == 1) && strncmp(sim.name, DEFAULT_SIMULATION_NAME, - sizeof(DEFAULT_SIMULATION_NAME)) != 0) { + sizeof(DEFAULT_SIMULATION_NAME)) != 0) { write_output_file(&sim, normalize); filetimeclock = 0.0; } diff --git a/fluid.c b/fluid.c @@ -1,5 +1,6 @@ #include <stdlib.h> #include <math.h> +#include <err.h> #include "simulation.h" #include "arrays.h" @@ -10,8 +11,8 @@ hydrostatic_fluid_pressure_distribution(struct simulation *sim) for (i = 0; i < sim->nz; ++i) sim->p_f_ghost[i + 1] = sim->p_f_top - + sim->phi[i] * sim->rho_f * sim->G - * (sim->L_z - sim->z[i]); + + sim->phi[i] * sim->rho_f * sim->G + * (sim->L_z - sim->z[i]); } static double @@ -19,7 +20,8 @@ diffusivity(struct simulation *sim, int i) { if (sim->D > 0.0) return sim->D; else - return sim->k[i]/((sim->alpha + sim->phi[i] * sim->beta_f) * sim->mu_f); + return sim->k[i] + / ((sim->alpha + sim->phi[i] * sim->beta_f) * sim->mu_f); } /* Determines the largest time step for the current simulation state. Note @@ -56,7 +58,7 @@ set_largest_fluid_timestep(struct simulation *sim, const double safety) sim->dt = safety * 0.5 * dx_min * dx_min / diff_max; if (sim->file_dt * 0.5 < sim->dt) - sim->dt = sim->file_dt; + sim->dt = sim->file_dt; return 0; } @@ -100,8 +102,10 @@ square_pulse(const double time, static void set_fluid_bcs(double *p_f_ghost, struct simulation *sim, const double p_f_top) { - set_bc_dirichlet(p_f_ghost, sim->nz, +1, p_f_top); - p_f_ghost[sim->nz] = p_f_top; /* Include top node in BC */ + /* correct ghost node at top BC for hydrostatic pressure gradient */ + set_bc_dirichlet(p_f_ghost, sim->nz, +1, + p_f_top - sim->phi[0] * sim->rho_f * sim->G * sim->dz); + p_f_ghost[sim->nz] = p_f_top; /* include top node in BC */ set_bc_neumann(p_f_ghost, sim->nz, -1, @@ -127,11 +131,8 @@ darcy_pressure_change_1d(const int i, if (D > 0.0) return D * (p_f_ghost_in[i + 2] - 2.0 * p_f_ghost_in[i + 1] - + p_f_ghost_in[i]) - / (dz * dz); - + + p_f_ghost_in[i]) / (dz * dz); else { - k_ = k[i]; if (i == 0) k_zn = k_; @@ -141,29 +142,25 @@ darcy_pressure_change_1d(const int i, k_zp = k_; else k_zp = k[i + 1]; -#ifdef DEBUG - printf("%d->%d: p=[%g, %g, %g]\tk=[%g, %g, %g]\n", - i, i + 1, - p_f_ghost_in[i], p_f_ghost_in[i + 1], p_f_ghost_in[i + 2], - k_zn, k_, k_zp); -#endif div_k_grad_p = (2.0 * k_zp * k_ / (k_zp + k_) - * (p_f_ghost_in[i + 2] - - p_f_ghost_in[i + 1]) / dz - - 2.0 * k_zn * k_ / (k_zn + k_) - * (p_f_ghost_in[i + 1] - - p_f_ghost_in[i]) / dz - ) / dz; + * (p_f_ghost_in[i + 2] - p_f_ghost_in[i + 1]) / dz + - 2.0 * k_zn * k_ / (k_zn + k_) + * (p_f_ghost_in[i + 1] - p_f_ghost_in[i]) / dz +) / dz; #ifdef DEBUG - printf("darcy_pressure_change [%d]: phi=%g\tdiv_k_grad_p=%g\tphi_dot=%g\n", - i, phi[i], div_k_grad_p, phi_dot[i]); + printf("%s [%d]: phi=%g\tdiv_k_grad_p=%g\tphi_dot=%g\n", + __func__, i, phi[i], div_k_grad_p, phi_dot[i]); + + printf(" p[%d, %d, %d] = [%g, %g, %g]\tk=[%g, %g, %g]\n", + i, i + 1, i + 2, + p_f_ghost_in[i], p_f_ghost_in[i + 1], p_f_ghost_in[i + 2], + k_zn, k_, k_zp); #endif - /* TODO: add advective term */ return 1.0 / ((alpha + beta_f * phi[i]) * mu_f) * div_k_grad_p - - 1.0 / ((alpha + beta_f * phi[i]) * (1.0 - phi[i])) * phi_dot[i]; + - 1.0 / ((alpha + beta_f * phi[i]) * (1.0 - phi[i])) * phi_dot[i]; } } @@ -174,41 +171,44 @@ darcy_solver_1d(struct simulation *sim, { int i, iter, solved = 0; double epsilon, p_f_top, r_norm_max = NAN; - double *tmp; /* choose integration method, parameter in [0.0; 1.0] * epsilon = 0.0: explicit * epsilon = 0.5: Crank-Nicolson * epsilon = 1.0: implicit */ - epsilon = 0.0; + epsilon = 0.5; + + for (i = 0; i < sim->nz; ++i) + sim->p_f_dot_impl[i] = sim->p_f_dot_expl[i] = 0.0; if (isnan(sim->p_f_mod_pulse_time)) p_f_top = sim->p_f_top - + sine_wave(sim->t, - sim->p_f_mod_ampl, - sim->p_f_mod_freq, - sim->p_f_mod_phase); + + sine_wave(sim->t, + sim->p_f_mod_ampl, + sim->p_f_mod_freq, + sim->p_f_mod_phase); else if (sim->p_f_mod_pulse_shape == 1) p_f_top = sim->p_f_top - + square_pulse(sim->t, - sim->p_f_mod_ampl, - sim->p_f_mod_freq, - sim->p_f_mod_pulse_time); + + square_pulse(sim->t, + sim->p_f_mod_ampl, + sim->p_f_mod_freq, + sim->p_f_mod_pulse_time); else p_f_top = sim->p_f_top - + triangular_pulse(sim->t, - sim->p_f_mod_ampl, - sim->p_f_mod_freq, - sim->p_f_mod_pulse_time); - + + triangular_pulse(sim->t, + sim->p_f_mod_ampl, + sim->p_f_mod_freq, + sim->p_f_mod_pulse_time); /* set fluid BCs (1 of 2) */ set_fluid_bcs(sim->p_f_ghost, sim, p_f_top); - copy_values(sim->p_f_ghost, sim->new_ghost, sim->nz + 2); /* explicit solution to pressure change */ if (epsilon < 1.0) { - for (i = 0; i < sim->nz; ++i) +#ifdef DEBUG + printf("\nEXPLICIT SOLVER IN %s\n", __func__); +#endif + for (i = 0; i < sim->nz - 1; ++i) sim->p_f_dot_expl[i] = darcy_pressure_change_1d(i, sim->nz, sim->p_f_ghost, @@ -219,26 +219,38 @@ darcy_solver_1d(struct simulation *sim, sim->beta_f, sim->alpha, sim->mu_f, - sim->D); + sim->D); + } /* implicit solution with Jacobian iterations */ if (epsilon > 0.0) { +#ifdef DEBUG + printf("\nEXPLICIT SOLVER IN %s\n", __func__); +#endif + copy_values(sim->p_f_ghost, sim->tmp_ghost, sim->nz + 2); + for (iter = 0; iter < max_iter; ++iter) { copy_values(sim->p_f_dot_impl, sim->old_val, sim->nz); +#ifdef DEBUG + puts(".. p_f_ghost bfore BC:"); + print_array(sim->tmp_ghost, sim->nz + 2); +#endif + /* set fluid BCs (2 of 2) */ - set_fluid_bcs(sim->new_ghost, sim, p_f_top); + set_fluid_bcs(sim->tmp_ghost, sim, p_f_top); + #ifdef DEBUG puts(".. p_f_ghost after BC:"); - print_array(sim->new_ghost, sim->nz + 2); + print_array(sim->tmp_ghost, sim->nz + 2); #endif for (i = 0; i < sim->nz - 1; ++i) sim->p_f_dot_impl[i] = darcy_pressure_change_1d(i, sim->nz, - sim->new_ghost, + sim->tmp_ghost, sim->phi, sim->phi_dot, sim->k, @@ -246,27 +258,26 @@ darcy_solver_1d(struct simulation *sim, sim->beta_f, sim->alpha, sim->mu_f, - sim->D); + sim->D); - for (i = 0; i < sim->nz - 1; ++i) { - sim->new_ghost[i + 1] = sim->p_f_ghost[i + 1] - + sim->p_f_dot_impl[i] * sim->dt; - sim->p_f_dot_impl_r_norm[i] = fabs(residual( - sim->p_f_dot_impl[i], sim->old_val[i])); - } + /*for (i = 0; i < sim->nz; ++i) + printf("sim->p_f_dot_impl[%d] = %g (t = %g s, iter = %d)\n", + i, sim->p_f_dot_impl[i], sim->t, iter);*/ - r_norm_max = max(sim->p_f_dot_impl_r_norm, sim->nz); -#ifdef DEBUG - puts(".. p_f_ghost_new:"); - print_array(sim->new_ghost, sim->nz + 2); -#endif + /*for (i = 0; i < sim->nz; ++i) + if (fabs(sim->p_f_dot_impl[i]) > 1e-12) + errx(1, "sim->p_f_dot_impl[%d] = %g (t = %g s, iter = %d)", + i, sim->p_f_dot_impl[i], sim->t, iter);*/ + + for (i = 0; i < sim->nz; ++i) + if (isnan(sim->p_f_dot_impl[i])) + errx(1, "NaN at sim->p_f_dot_impl[%d] (t = %g s, iter = %d)", + i, sim->t, iter); - tmp = sim->new_ghost; - sim->new_ghost = sim->p_f_ghost; - sim->p_f_ghost = tmp; + r_norm_max = max(sim->p_f_dot_impl_r_norm, sim->nz - 1); #ifdef DEBUG - puts(".. p_f_ghost after update:"); - print_array(sim->new_ghost, sim->nz + 2); + puts(".. p_f_ghost_new:"); + print_array(sim->tmp_ghost, sim->nz + 2); #endif if (r_norm_max <= rel_tol) { @@ -291,15 +302,25 @@ darcy_solver_1d(struct simulation *sim, sim->p_f_dot[i] = epsilon * sim->p_f_dot_impl[i] + (1.0 - epsilon) * sim->p_f_dot_expl[i]; + set_fluid_bcs(sim->p_f_ghost, sim, p_f_top); + #ifdef DEBUG - printf(".. epsilon = %s\n", epsilon); - puts(".. p_f_dot_impl:"); - print_array(sim->p_f_dot_impl, sim->nz); - puts(".. p_f_dot_expl:"); - print_array(sim->p_f_dot_expl, sim->nz); + printf(".. epsilon = %g\n", epsilon); + puts(".. p_f_dot_expl:"); + print_array(sim->p_f_dot_expl, sim->nz); + puts(".. p_f_dot_impl:"); + print_array(sim->p_f_dot_impl, sim->nz); #endif - set_fluid_bcs(sim->p_f_ghost, sim, p_f_top); + for (i = 0; i < sim->nz; ++i) + if (isnan(sim->p_f_dot_expl[i]) || isinf(sim->p_f_dot_expl[i])) + errx(1, "invalid: sim->p_f_dot_expl[%d] = %g (t = %g s)", + i, sim->p_f_dot_expl[i], sim->t); + + for (i = 0; i < sim->nz; ++i) + if (isnan(sim->p_f_dot_impl[i]) || isinf(sim->p_f_dot_impl[i])) + errx(1, "invalid: sim->p_f_dot_impl[%d] = %g (t = %g s)", + i, sim->p_f_dot_impl[i], sim->t); return solved - 1; } diff --git a/max_depth_simple_shear.c b/max_depth_simple_shear.c @@ -4,6 +4,7 @@ #include <math.h> #include <getopt.h> #include <time.h> +#include <err.h> #include "simulation.h" #include "arg.h" @@ -27,21 +28,21 @@ static void usage(void) { fprintf(stderr, "usage: %s " - "[-a fluid-pressure-ampl] " - "[-C fluid-compressibility] " - "[-D fluid-diffusivity] " - "[-g gravity-accel] " - "[-h] " - "[-i fluid-viscosity] " - "[-k fluid-permeability] " - "[-O fluid-pressure-top] " - "[-P grain-compressibility] " - "[-p grain-porosity] " - "[-q fluid-pressure-freq] " - "[-R fluid-density] " - "[-r grain-density] " - "[-v] " - "\n", argv0); + "[-a fluid-pressure-ampl] " + "[-C fluid-compressibility] " + "[-D fluid-diffusivity] " + "[-g gravity-accel] " + "[-h] " + "[-i fluid-viscosity] " + "[-k fluid-permeability] " + "[-O fluid-pressure-top] " + "[-P grain-compressibility] " + "[-p grain-porosity] " + "[-q fluid-pressure-freq] " + "[-R fluid-density] " + "[-r grain-density] " + "[-v] " + "\n", argv0); exit(1); } @@ -51,7 +52,9 @@ skin_depth(const struct simulation *sim) if (sim->D > 0.0) return sqrt(sim->D / (M_PI * sim->p_f_mod_freq)); else - return sqrt(sim->k[0] / (sim->mu_f * (sim->alpha + sim->phi[0] * sim->beta_f) * M_PI * sim->p_f_mod_freq)); + return sqrt(sim->k[0] / (sim->mu_f + * (sim->alpha + sim->phi[0] * sim->beta_f) + * M_PI * sim->p_f_mod_freq)); } /* using alternate form: sin(x) + cos(x) = sqrt(2)*sin(x + pi/4) */ @@ -65,8 +68,8 @@ eff_normal_stress_gradient(struct simulation * sim, double d_s, double z_) exit(10); } return sqrt(2.0) * sin((3.0 * M_PI / 2.0 - z_ / d_s) + M_PI / 4.0) - + (sim->rho_s - sim->rho_f) * sim->G * d_s - / sim->p_f_mod_ampl * exp(z_ / d_s); + + (sim->rho_s - sim->rho_f) * sim->G * d_s + / sim->p_f_mod_ampl * exp(z_ / d_s); } /* use Brent's method for finding roots (Press et al., 2007) */ @@ -88,9 +91,8 @@ zbrent(struct simulation *sim, fb = (*f) (sim, d_s, b); if ((fa > 0.0 && fb > 0.0) || (fa < 0.0 && fb < 0.0)) { - fprintf(stderr, - "error: %s: no root in range %g,%g m\n", - __func__, x1, x2); + warnx("%s: no root in range %g,%g m\n", + __func__, x1, x2); free_arrays(sim); exit(11); } @@ -149,9 +151,7 @@ zbrent(struct simulation *sim, b += ((xm) >= 0.0 ? fabs(tol1) : -fabs(tol1)); fb = (*f) (sim, d_s, b); } - fprintf(stderr, - "error: %s: exceeded maximum number of iterations", - __func__); + warnx("error: %s: exceeded maximum number of iterations", __func__); free_arrays(sim); exit(12); return NAN; @@ -172,10 +172,8 @@ main(int argc, char *argv[]) #endif #ifdef __OpenBSD__ - if (pledge("stdio", NULL) == -1) { - fprintf(stderr, "error: pledge failed"); - exit(2); - } + if (pledge("stdio", NULL) == -1) + err(2, "pledge failed"); #endif init_sim(&sim); diff --git a/shear_flux.c b/shear_flux.c @@ -2,6 +2,7 @@ #include <unistd.h> #include <stdio.h> #include <stdlib.h> +#include <err.h> #include "arg.h" @@ -11,10 +12,10 @@ static void usage(void) { fprintf(stderr, "usage: %s " - "[-v] " - "[-h] " - "[file ...] " - "\n", argv0); + "[-v] " + "[-h] " + "[file ...] " + "\n", argv0); exit(1); } @@ -46,10 +47,8 @@ main(int argc, char *argv[]) FILE *fp; #ifdef __OpenBSD__ - if (pledge("stdio rpath", NULL) == -1) { - fprintf(stderr, "error: pledge failed"); - exit(2); - } + if (pledge("stdio rpath", NULL) == -1) + err(2, "pledge failed"); #endif ARGBEGIN { diff --git a/simulation.c b/simulation.c @@ -1,6 +1,7 @@ #include <stdio.h> #include <stdlib.h> #include <math.h> +#include <err.h> #include "arrays.h" #include "simulation.h" #include "fluid.h" @@ -135,15 +136,15 @@ prepare_arrays(struct simulation *sim) { if (sim->nz < 2) { fprintf(stderr, "error: grid size (nz) must be at least 2 but is %d\n", - sim->nz); + sim->nz); exit(1); } free(sim->phi); free(sim->k); sim->z = linspace(sim->origo_z, - sim->origo_z + sim->L_z, - sim->nz); + sim->origo_z + sim->L_z, + sim->nz); sim->dz = sim->z[1] - sim->z[0]; sim->mu = zeros(sim->nz); sim->mu_c = zeros(sim->nz); @@ -167,7 +168,7 @@ prepare_arrays(struct simulation *sim) sim->I = zeros(sim->nz); sim->tan_psi = zeros(sim->nz); sim->old_val = empty(sim->nz); - sim->new_ghost = empty(sim->nz + 2); + sim->tmp_ghost = empty(sim->nz + 2); } void @@ -196,13 +197,13 @@ free_arrays(struct simulation *sim) free(sim->I); free(sim->tan_psi); free(sim->old_val); - free(sim->new_ghost); + free(sim->tmp_ghost); } static void warn_parameter_value(const char message[], - const double value, - int *return_status) + const double value, + int *return_status) { fprintf(stderr, "check_simulation_parameters: %s (%.17g)\n", @@ -243,14 +244,14 @@ check_simulation_parameters(struct simulation *sim) check_float("sim->P_wall", sim->P_wall, &return_status); if (sim->P_wall < 0.0) warn_parameter_value("sim->P_wall is negative", sim->P_wall, - &return_status); + &return_status); check_float("sim->v_x_bot", sim->v_x_bot, &return_status); check_float("sim->mu_wall", sim->mu_wall, &return_status); if (sim->mu_wall < 0.0) warn_parameter_value("sim->mu_wall is negative", sim->mu_wall, - &return_status); + &return_status); check_float("sim->A", sim->A, &return_status); if (sim->A < 0.0) @@ -263,128 +264,134 @@ check_simulation_parameters(struct simulation *sim) check_float("sim->mu_s", sim->mu_s, &return_status); if (sim->mu_s < 0.0) warn_parameter_value("sim->mu_s is negative", sim->mu_s, - &return_status); + &return_status); check_float("sim->C", sim->C, &return_status); check_float("sim->d", sim->d, &return_status); if (sim->d <= 0.0) warn_parameter_value("sim->d is not a positive number", sim->d, - &return_status); + &return_status); check_float("sim->rho_s", sim->rho_s, &return_status); if (sim->rho_s <= 0.0) warn_parameter_value("sim->rho_s is not a positive number", sim->rho_s, - &return_status); + &return_status); if (sim->nz <= 0) warn_parameter_value("sim->nz is not a positive number", sim->nz, - &return_status); + &return_status); check_float("sim->origo_z", sim->origo_z, &return_status); check_float("sim->L_z", sim->L_z, &return_status); if (sim->L_z <= sim->origo_z) warn_parameter_value("sim->L_z is smaller or equal to sim->origo_z", - sim->L_z, &return_status); + sim->L_z, &return_status); if (sim->nz <= 0) warn_parameter_value("sim->nz is not a positive number", sim->nz, - &return_status); + &return_status); check_float("sim->dz", sim->dz, &return_status); if (sim->dz <= 0.0) warn_parameter_value("sim->dz is not a positive number", sim->dz, - &return_status); + &return_status); check_float("sim->t", sim->t, &return_status); if (sim->t < 0.0) warn_parameter_value("sim->t is a negative number", - sim->t, &return_status); + sim->t, &return_status); check_float("sim->t_end", sim->t_end, &return_status); if (sim->t > sim->t_end) warn_parameter_value("sim->t_end is smaller than sim->t", - sim->t, &return_status); + sim->t, &return_status); check_float("sim->dt", sim->dt, &return_status); if (sim->dt <= 0.0) warn_parameter_value("sim->dt is not a positive number", - sim->dt, &return_status); + sim->dt, &return_status); check_float("sim->file_dt", sim->file_dt, &return_status); if (sim->file_dt < 0.0) warn_parameter_value("sim->file_dt is a negative number", - sim->file_dt, &return_status); + sim->file_dt, &return_status); check_float("sim->phi[0]", sim->phi[0], &return_status); if (sim->phi[0] < 0.0 || sim->phi[0] > 1.0) warn_parameter_value("sim->phi[0] is not within [0;1]", - sim->phi[0], &return_status); + sim->phi[0], &return_status); check_float("sim->phi_min", sim->phi_min, &return_status); if (sim->phi_min < 0.0 || sim->phi_min > 1.0) warn_parameter_value("sim->phi_min is not within [0;1]", - sim->phi_min, &return_status); + sim->phi_min, &return_status); check_float("sim->phi_max", sim->phi_max, &return_status); if (sim->phi_max < 0.0 || sim->phi_max > 1.0) warn_parameter_value("sim->phi_max is not within [0;1]", - sim->phi_max, &return_status); + sim->phi_max, &return_status); check_float("sim->dilatancy_constant", sim->dilatancy_constant, &return_status); if (sim->dilatancy_constant < 0.0 || sim->dilatancy_constant > 100.0) warn_parameter_value("sim->dilatancy_constant is not within [0;100]", - sim->dilatancy_constant, &return_status); + sim->dilatancy_constant, &return_status); if (sim->fluid != 0 && sim->fluid != 1) warn_parameter_value("sim->fluid has an invalid value", - (double) sim->fluid, &return_status); + (double) sim->fluid, &return_status); if (sim->transient != 0 && sim->transient != 1) warn_parameter_value("sim->transient has an invalid value", - (double) sim->transient, &return_status); + (double) sim->transient, &return_status); if (sim->fluid) { - check_float("sim->p_f_mod_ampl", sim->p_f_mod_ampl, &return_status); if (sim->p_f_mod_ampl < 0.0) warn_parameter_value("sim->p_f_mod_ampl is not a zero or positive", - sim->p_f_mod_ampl, &return_status); + sim->p_f_mod_ampl, &return_status); if (sim->P_wall - sim->p_f_mod_ampl < 0.0) warn_parameter_value("sim->P_wall - sim->p_f_mod_ampl is negative", - sim->P_wall - sim->p_f_mod_ampl, - &return_status); + sim->P_wall - sim->p_f_mod_ampl, + &return_status); check_float("sim->p_f_mod_freq", sim->p_f_mod_freq, &return_status); if (sim->p_f_mod_freq < 0.0) warn_parameter_value("sim->p_f_mod_freq is not a zero or positive", - sim->p_f_mod_freq, &return_status); + sim->p_f_mod_freq, &return_status); check_float("sim->beta_f", sim->beta_f, &return_status); if (sim->beta_f <= 0.0) warn_parameter_value("sim->beta_f is not positive", - sim->beta_f, &return_status); + sim->beta_f, &return_status); check_float("sim->alpha", sim->alpha, &return_status); if (sim->alpha <= 0.0) warn_parameter_value("sim->alpha is not positive", - sim->alpha, &return_status); + sim->alpha, &return_status); check_float("sim->mu_f", sim->mu_f, &return_status); if (sim->mu_f <= 0.0) warn_parameter_value("sim->mu_f is not positive", - sim->mu_f, &return_status); + sim->mu_f, &return_status); check_float("sim->rho_f", sim->rho_f, &return_status); if (sim->rho_f <= 0.0) warn_parameter_value("sim->rho_f is not positive", - sim->rho_f, &return_status); + sim->rho_f, &return_status); check_float("sim->k[0]", sim->k[0], &return_status); if (sim->k[0] <= 0.0) warn_parameter_value("sim->k[0] is not positive", - sim->k[0], &return_status); + sim->k[0], &return_status); + + check_float("sim->D", sim->D, &return_status); + if (sim->transient && sim->D > 0.0) + warn_parameter_value("constant diffusivity does not work in " + "transient simulations", + sim->D, &return_status); + } if (return_status != 0) { fprintf(stderr, "error: aborting due to invalid parameter choices\n"); @@ -398,9 +405,9 @@ lithostatic_pressure_distribution(struct simulation *sim) int i; for (i = 0; i < sim->nz; ++i) - sim->sigma_n[i] = sim->P_wall + - (1.0 - sim->phi[i]) * sim->rho_s * sim->G * - (sim->L_z - sim->z[i]); + sim->sigma_n[i] = sim->P_wall + + (1.0 - sim->phi[i]) * sim->rho_s * sim->G + * (sim->L_z - sim->z[i]); } /* NEW FUNCTIONS START */ @@ -412,7 +419,7 @@ compute_inertia_number(struct simulation *sim) for (i = 0; i < sim->nz; ++i) sim->I[i] = sim->gamma_dot_p[i] * sim->d - / sqrt(sim->sigma_n_eff[i] / sim->rho_s); + / sqrt(sim->sigma_n_eff[i] / sim->rho_s); } void @@ -432,13 +439,13 @@ compute_critical_state_friction(struct simulation *sim) if (sim->fluid) for (i = 0; i < sim->nz; ++i) - sim->mu_c[i] = sim->mu_wall / - (sim->sigma_n_eff[i] / (sim->P_wall - sim->p_f_top)); + sim->mu_c[i] = sim->mu_wall / (sim->sigma_n_eff[i] + / (sim->P_wall - sim->p_f_top)); else for (i = 0; i < sim->nz; ++i) - sim->mu_c[i] = sim->mu_wall / - (1.0 + (1.0 - sim->phi[i]) * sim->rho_s * sim->G * - (sim->L_z - sim->z[i]) / sim->P_wall); + sim->mu_c[i] = sim->mu_wall + / (1.0 + (1.0 - sim->phi[i]) * sim->rho_s * sim->G * + (sim->L_z - sim->z[i]) / sim->P_wall); } static void @@ -479,8 +486,8 @@ compute_permeability(struct simulation *sim) for (i = 0; i < sim->nz; ++i) sim->k[i] = pow(sim->d, 2.0) / 180.0 - * pow(sim->phi[i], 3.0) - / pow(1.0 - sim->phi[i], 2.0); + * pow(sim->phi[i], 3.0) + / pow(1.0 - sim->phi[i], 2.0); } /* NEW FUNCTIONS END */ @@ -498,7 +505,7 @@ compute_shear_strain_rate_plastic(struct simulation *sim) for (i = 0; i < sim->nz; ++i) sim->gamma_dot_p[i] = shear_strain_rate_plastic(sim->g_ghost[i + 1], - sim->mu[i]); + sim->mu[i]); } static void @@ -593,10 +600,8 @@ set_bc_neumann(double *a, a[0] = a[1] + df * dx; else if (boundary == +1) a[nz + 1] = a[nz] - df * dx; - else { - fprintf(stderr, "set_bc_neumann: Unknown boundary %d\n", boundary); - exit(1); - } + else + errx(1, "%s: Unknown boundary %d\n", __func__, boundary); } void @@ -609,10 +614,8 @@ set_bc_dirichlet(double *a, a[0] = value; else if (boundary == +1) a[nz + 1] = value; - else { - fprintf(stderr, "set_bc_dirichlet: Unknown boundary %d\n", boundary); - exit(1); - } + else + errx(1, "%s: Unknown boundary %d\n", __func__, boundary); } double @@ -633,8 +636,8 @@ poisson_solver_1d_cell_update(int i, double coorp_term = dz * dz / (2.0 * pow(xi[i], 2.0)); g_out[i + 1] = 1.0 / (1.0 + coorp_term) - * (coorp_term * g_local[i] + g_in[i + 2] / 2.0 + g_in[i] / 2.0); - + * (coorp_term * g_local[i] + g_in[i + 2] / 2.0 + + g_in[i] / 2.0); r_norm[i] = residual(g_out[i + 1], g_in[i + 1]); #ifdef DEBUG @@ -671,14 +674,14 @@ implicit_1d_jacobian_poisson_solver(struct simulation *sim, poisson_solver_1d_cell_update(i, sim->g_ghost, sim->g_local, - sim->new_ghost, + sim->tmp_ghost, sim->g_r_norm, sim->dz, sim->xi); r_norm_max = max(sim->g_r_norm, sim->nz); - tmp = sim->new_ghost; - sim->new_ghost = sim->g_ghost; + tmp = sim->tmp_ghost; + sim->tmp_ghost = sim->g_ghost; sim->g_ghost = tmp; if (r_norm_max <= rel_tol) { @@ -704,7 +707,7 @@ write_output_file(struct simulation *sim, const int normalize) FILE *fp; snprintf(outfile, sizeof(outfile), "%s.output%05d.txt", - sim->name, sim->n_file++); + sim->name, sim->n_file++); if ((fp = fopen(outfile, "w")) != NULL) { print_output(sim, fp, normalize); @@ -753,9 +756,16 @@ temporal_increment(struct simulation *sim) for (i = 0; i < sim->nz; ++i) sim->phi[i] += sim->phi_dot[i] * sim->dt; - if (sim->fluid) - for (i = 0; i < sim->nz; ++i) - sim->p_f_ghost[i + 1] += sim->p_f_dot[i] * sim->dt; + if (sim->fluid) { + for (i = 0; i < sim->nz; ++i) { + if (isnan(sim->p_f_dot[i])) { + errx(1, "encountered NaN at sim->p_f_dot[%d] (t = %g s)", + i, sim->t); + } else { + sim->p_f_ghost[i + 1] += sim->p_f_dot[i] * sim->dt; + } + } + } sim->t += sim->dt; } @@ -769,7 +779,6 @@ coupled_shear_solver(struct simulation *sim, double r_norm_max, vel_res_norm = NAN, mu_wall_orig = sim->mu_wall; do { /* stress iterations */ - coupled_iter = 0; do { /* coupled iterations */ @@ -806,8 +815,8 @@ coupled_shear_solver(struct simulation *sim, /* step 8, Eq. 11 */ if (implicit_1d_jacobian_poisson_solver(sim, - MAX_ITER_GRANULAR, - RTOL_GRANULAR)) + MAX_ITER_GRANULAR, + RTOL_GRANULAR)) exit(12); /* step 9 */ @@ -840,9 +849,9 @@ coupled_shear_solver(struct simulation *sim, if (coupled_iter++ >= max_iter) { fprintf(stderr, "coupled_shear_solver: "); fprintf(stderr, "Transient solution did not converge " - "after %d iterations\n", coupled_iter); + "after %d iterations\n", coupled_iter); fprintf(stderr, ".. Residual normalized error: %g\n", - r_norm_max); + r_norm_max); return 1; } } @@ -851,25 +860,25 @@ coupled_shear_solver(struct simulation *sim, if (!isnan(sim->v_x_limit) || !isnan(sim->v_x_fix)) { if (!isnan(sim->v_x_limit)) { vel_res_norm = (sim->v_x_limit - sim->v_x[sim->nz - 1]) - / (sim->v_x[sim->nz - 1] + 1e-12); + / (sim->v_x[sim->nz - 1] + 1e-12); if (vel_res_norm > 0.0) vel_res_norm = 0.0; } else { vel_res_norm = (sim->v_x_fix - sim->v_x[sim->nz - 1]) - / (sim->v_x[sim->nz - 1] + 1e-12); + / (sim->v_x[sim->nz - 1] + 1e-12); } sim->mu_wall *= 1.0 + (vel_res_norm * 1e-2); } if (++stress_iter > MAX_ITER_STRESS) { fprintf(stderr, "error: stress solution did not converge:\n"); fprintf(stderr, "v_x=%g, v_x_fix=%g, v_x_limit=%g, " - "vel_res_norm=%g, mu_wall=%g\n", - sim->v_x[sim->nz - 1], sim->v_x_fix, sim->v_x_limit, - vel_res_norm, sim->mu_wall); + "vel_res_norm=%g, mu_wall=%g\n", + sim->v_x[sim->nz - 1], sim->v_x_fix, sim->v_x_limit, + vel_res_norm, sim->mu_wall); return 10; } } while ((!isnan(sim->v_x_fix) || !isnan(sim->v_x_limit)) - && fabs(vel_res_norm) > RTOL_STRESS); + && fabs(vel_res_norm) > RTOL_STRESS); if (!isnan(sim->v_x_limit)) sim->mu_wall = mu_wall_orig; diff --git a/simulation.h b/simulation.h @@ -123,7 +123,7 @@ struct simulation { double *I; /* inertia number [-] */ double *tan_psi; /* tan(dilatancy_angle) [-] */ double *old_val; /* temporary storage for iterative solvers */ - double *new_ghost; /* temporary storage for iterative solvers */ + double *tmp_ghost; /* temporary storage for iterative solvers */ }; void init_sim(struct simulation *sim);