1d_fd_simple_shear

Continuum model for granular flows with pore-pressure dynamics
git clone git://src.adamsgaard.dk/1d_fd_simple_shear
Log | Files | Refs | README | LICENSE

commit 4a6213835f491e0753ed1a3f864380a75a0d30cd
parent 8e120cffa8aad6b9eab4ff77a4dfdc0ab5402dd2
Author: Anders Damsgaard <anders@adamsgaard.dk>
Date:   Tue, 25 Jun 2019 16:41:55 +0200

Use tabs for indentation and spaces for alignment

Diffstat:
Marrays.c | 148++++++++++++++++++++++++++++++++++++++++----------------------------------------
Mfluid.c | 281+++++++++++++++++++++++++++++++++++++++----------------------------------------
Mmain.c | 553++++++++++++++++++++++++++++++++++++++++---------------------------------------
Msimulation.c | 683+++++++++++++++++++++++++++++++++++++++----------------------------------------
4 files changed, 827 insertions(+), 838 deletions(-)

diff --git a/arrays.c b/arrays.c @@ -6,158 +6,158 @@ /* Translate a i,j,k index in grid with dimensions nx, ny, nz into a linear * index */ -unsigned int idx3( - const unsigned int i, const unsigned int j, const unsigned int k, - const unsigned int nx, const unsigned int ny) +unsigned int idx3(const unsigned int i, + const unsigned int j, + const unsigned int k, + const unsigned int nx, + const unsigned int ny) { - return i + nx*j + nx*ny*k; + return i + nx*j + nx*ny*k; } /* Translate a i,j,k index in grid with dimensions nx, ny, nz and a padding of * single ghost nodes into a linear index */ -unsigned int idx3g( - const unsigned int i, const unsigned int j, const unsigned int k, - const unsigned int nx, const unsigned int ny) +unsigned int idx3g(const unsigned int i, + const unsigned int j, + const unsigned int k, + const unsigned int nx, + const unsigned int ny) { - return i+1 + (nx+2)*(j+1) + (nx+2)*(ny+2)*(k+1); + return i+1 + (nx+2)*(j+1) + (nx+2)*(ny+2)*(k+1); } /* Translate a i,j index in grid with dimensions nx, ny into a linear index */ -unsigned int idx2( - const unsigned int i, const unsigned int j, const unsigned int nx) +unsigned int idx2(const unsigned int i, + const unsigned int j, + const unsigned int nx) { - return i + nx*j; + return i + nx*j; } /* Translate a i,j index in grid with dimensions nx, ny and a padding of single * ghost nodes into a linear index */ -unsigned int idx2g( - const unsigned int i, const unsigned int j, const unsigned int nx) +unsigned int idx2g(const unsigned int i, + const unsigned int j, + const unsigned int nx) { - return i+1 + (nx+2)*(j+1); + return i+1 + (nx+2)*(j+1); } /* Translate a i index in grid with a padding of single into a linear index */ unsigned int idx1g(const unsigned int i) { - return i+1; + return i+1; } /* Return an array of `n` linearly spaced values in the range [lower; upper] */ double* linspace(const double lower, const double upper, const int n) { - double *x = malloc(n*sizeof(double)); - double dx = (upper - lower)/(double)(n-1); - for (int i=0; i<n; ++i) - x[i] = lower + dx*i; - return x; + double *x = malloc(n*sizeof(double)); + double dx = (upper - lower)/(double)(n-1); + for (int i=0; i<n; ++i) + x[i] = lower + dx*i; + return x; } /* Return an array of `n` values with the value 0.0 */ double* zeros(const int n) { - double *x = malloc(n*sizeof(double)); - for (int i=0; i<n; ++i) - x[i] = 0.0; - return x; + double *x = malloc(n*sizeof(double)); + for (int i=0; i<n; ++i) + x[i] = 0.0; + return x; } /* Return an array of `n` values with the value 1.0 */ double* ones(const int n) { - double *x = malloc(n*sizeof(double)); - for (int i=0; i<n; ++i) - x[i] = 1.0; - return x; + double *x = malloc(n*sizeof(double)); + for (int i=0; i<n; ++i) + x[i] = 1.0; + return x; } /* Return an array of `n` values with a specified value */ double* initval(const double value, const int n) { - double *x = malloc(n*sizeof(double)); - for (int i=0; i<n; ++i) - x[i] = value; - return x; + double *x = malloc(n*sizeof(double)); + for (int i=0; i<n; ++i) + x[i] = value; + return x; } /* Return an array of `n` uninitialized values */ double* empty(const int n) { - return malloc(n*sizeof(double)); + return malloc(n*sizeof(double)); } /* Return largest value in array `a` with size `n` */ double max(const double* a, const int n) { - double maxval = -INFINITY; - for (int i=0; i<n; ++i) - if (a[i] > maxval) - maxval = a[i]; - return maxval; + double maxval = -INFINITY; + for (int i=0; i<n; ++i) + if (a[i] > maxval) + maxval = a[i]; + return maxval; } /* Return smallest value in array `a` with size `n` */ double min(const double* a, const int n) { - double minval = +INFINITY; - for (int i=0; i<n; ++i) - if (a[i] < minval) - minval = a[i]; - return minval; + double minval = +INFINITY; + for (int i=0; i<n; ++i) + if (a[i] < minval) + minval = a[i]; + return minval; } void print_array(const double* a, const int n) { - for (int i=0; i<n; ++i) - printf("%.17g\n", a[i]); + for (int i=0; i<n; ++i) + printf("%.17g\n", a[i]); } void print_arrays(const double* a, const double* b, const int n) { - for (int i=0; i<n; ++i) - printf("%.17g\t%.17g\n", a[i], b[i]); + for (int i=0; i<n; ++i) + printf("%.17g\t%.17g\n", a[i], b[i]); } void print_arrays_2nd_normalized(const double* a, const double* b, const int n) { - double max_b = max(b, n); - for (int i=0; i<n; ++i) - printf("%.17g\t%.17g\n", a[i], b[i]/max_b); + double max_b = max(b, n); + for (int i=0; i<n; ++i) + printf("%.17g\t%.17g\n", a[i], b[i]/max_b); } -void print_three_arrays( - const double* a, - const double* b, - const double* c, - const int n) +void print_three_arrays(const double* a, + const double* b, + const double* c, + const int n) { - for (int i=0; i<n; ++i) - printf("%.17g\t%.17g\t%.17g\n", a[i], b[i], c[i]); + for (int i=0; i<n; ++i) + printf("%.17g\t%.17g\t%.17g\n", a[i], b[i], c[i]); } -void fprint_arrays( - FILE* fp, - const double* a, - const double* b, - const int n) +void fprint_arrays(FILE* fp, const double* a, const double* b, const int n) { - for (int i=0; i<n; ++i) - fprintf(fp, "%.17g\t%.17g\n", a[i], b[i]); + for (int i=0; i<n; ++i) + fprintf(fp, "%.17g\t%.17g\n", a[i], b[i]); } -void fprint_three_arrays( - FILE* fp, - const double* a, - const double* b, - const double* c, - const int n) +void fprint_three_arrays(FILE* fp, + const double* a, + const double* b, + const double* c, + const int n) { - for (int i=0; i<n; ++i) - fprintf(fp, "%.17g\t%.17g\t%.17g\n", a[i], b[i], c[i]); + for (int i=0; i<n; ++i) + fprintf(fp, "%.17g\t%.17g\t%.17g\n", a[i], b[i], c[i]); } void copy_values(const double* in, double* out, const int n) { - for (int i=0; i<n; ++i) - out[i] = in[i]; + for (int i=0; i<n; ++i) + out[i] = in[i]; } diff --git a/fluid.c b/fluid.c @@ -5,180 +5,177 @@ void hydrostatic_fluid_pressure_distribution(struct simulation* sim) { - for (int i=0; i<sim->nz; ++i) - sim->p_f_ghost[idx1g(i)] = sim->p_f_top + - sim->phi[i]*sim->rho_f*sim->G*(sim->L_z - sim->z[i]); + for (int i=0; i<sim->nz; ++i) + sim->p_f_ghost[idx1g(i)] = sim->p_f_top + + sim->phi[i]*sim->rho_f*sim->G* + (sim->L_z - sim->z[i]); } -static double sine_wave( - const double time, - const double amplitude, - const double frequency, - const double phase, - const double base_value) +static double sine_wave(const double time, + const double amplitude, + const double frequency, + const double phase, + const double base_value) { - return amplitude*sin(2.0*PI*frequency*time + phase) + base_value; + return amplitude*sin(2.0*PI*frequency*time + phase) + base_value; } -static double darcy_pressure_change_1d( - const int i, - const int nz, - const double* p_f_ghost_in, - const double* phi, - const double* k, - const double dz, - const double dt, - const double beta_f, - const double mu_f) +static double darcy_pressure_change_1d(const int i, + const int nz, + const double* p_f_ghost_in, + const double* phi, + const double* k, + const double dz, + const double dt, + const double beta_f, + const double mu_f) { - const double p = p_f_ghost_in[idx1g(i)]; - const double p_zn = p_f_ghost_in[idx1g(i-1)]; - const double p_zp = p_f_ghost_in[idx1g(i+1)]; - - const double k_ = k[i]; - double k_zn, k_zp; - if (i==0) k_zn = k_; else k_zn = k[i-1]; - if (i==nz-1) k_zp = k_; else k_zp = k[i+1]; + const double p = p_f_ghost_in[idx1g(i)]; + const double p_zn = p_f_ghost_in[idx1g(i-1)]; + const double p_zp = p_f_ghost_in[idx1g(i+1)]; + + const double k_ = k[i]; + double k_zn, k_zp; + if (i==0) k_zn = k_; else k_zn = k[i-1]; + if (i==nz-1) k_zp = k_; else k_zp = k[i+1]; #ifdef DEBUG - printf("%d->%d: p=[%g, %g, %g]\tk=[%g, %g, %g]\n", - i, idx1g(i), - p_zn, p, p_zp, - k_zn, k_, k_zp); + printf("%d->%d: p=[%g, %g, %g]\tk=[%g, %g, %g]\n", + i, idx1g(i), + p_zn, p, p_zp, + k_zn, k_, k_zp); #endif - const double div_k_grad_p = - (2.0*k_zp*k_/(k_zp + k_) * (p_zp - p)/dz - - 2.0*k_zn*k_/(k_zn + k_) * (p - p_zn)/dz - )/dz; + const double div_k_grad_p = + (2.0*k_zp*k_/(k_zp + k_) * (p_zp - p)/dz - + 2.0*k_zn*k_/(k_zn + k_) * (p - p_zn)/dz + )/dz; #ifdef DEBUG - printf("phi[%d]=%g\tdiv_k_grad_p[%d]=%g\n", - i, phi[i], i, div_k_grad_p); + printf("phi[%d]=%g\tdiv_k_grad_p[%d]=%g\n", + i, phi[i], i, div_k_grad_p); #endif - /* return delta p */ - return dt/(beta_f*phi[i]*mu_f)*div_k_grad_p; + /* return delta p */ + return dt/(beta_f*phi[i]*mu_f)*div_k_grad_p; } -int darcy_solver_1d( - struct simulation* sim, - const int max_iter, - const double rel_tol) +int darcy_solver_1d(struct simulation* sim, + const int max_iter, + const double rel_tol) { - /* compute explicit solution to pressure change */ - double* dp_f_expl = zeros(sim->nz); - for (int i=0; i<sim->nz; ++i) - dp_f_expl[i] = darcy_pressure_change_1d( - i, - sim->nz, - sim->p_f_ghost, - sim->phi, - sim->k, - sim->dz, - sim->dt, - sim->beta_f, - sim->mu_f); - - /* choose integration method, parameter in [0.0; 1.0] - * epsilon = 0.0: explicit - * epsilon = 0.5: Crank-Nicolson - * epsilon = 1.0: implicit */ - const double epsilon = 0.5; - - /* choose relaxation factor, parameter in ]0.0; 1.0] - * theta in ]0.0; 1.0]: underrelaxation - * theta = 1.0: Gauss-Seidel - * theta > 1.0: overrelaxation */ - const double theta = 0.05; - /* const double theta = 1.7; */ - - double p_f; - - /* compute implicit solution to pressure change */ - int iter; - double* dp_f_impl = zeros(sim->nz); - double* p_f_ghost_out = zeros(sim->nz+2); - double* r_norm = zeros(sim->nz); - double r_norm_max = NAN; - double p_f_top = sine_wave( - sim->t, - sim->p_f_mod_ampl, - sim->p_f_mod_freq, - sim->p_f_mod_phase, - sim->p_f_top); - - for (iter=0; iter<max_iter; ++iter) { - - set_bc_dirichlet(sim->p_f_ghost, sim->nz, +1, p_f_top); - sim->p_f_ghost[idx1g(sim->nz-1)] = p_f_top; /* Include top node in BC */ - set_bc_neumann(sim->p_f_ghost, sim->nz, -1); + /* compute explicit solution to pressure change */ + double* dp_f_expl = zeros(sim->nz); + for (int i=0; i<sim->nz; ++i) + dp_f_expl[i] = darcy_pressure_change_1d(i, + sim->nz, + sim->p_f_ghost, + sim->phi, + sim->k, + sim->dz, + sim->dt, + sim->beta_f, + sim->mu_f); + + /* choose integration method, parameter in [0.0; 1.0] + * epsilon = 0.0: explicit + * epsilon = 0.5: Crank-Nicolson + * epsilon = 1.0: implicit */ + const double epsilon = 0.5; + + /* choose relaxation factor, parameter in ]0.0; 1.0] + * theta in ]0.0; 1.0]: underrelaxation + * theta = 1.0: Gauss-Seidel + * theta > 1.0: overrelaxation */ + const double theta = 0.05; + /* const double theta = 1.7; */ + + double p_f; + + /* compute implicit solution to pressure change */ + int iter; + double* dp_f_impl = zeros(sim->nz); + double* p_f_ghost_out = zeros(sim->nz+2); + double* r_norm = zeros(sim->nz); + double r_norm_max = NAN; + double p_f_top = sine_wave( + sim->t, + sim->p_f_mod_ampl, + sim->p_f_mod_freq, + sim->p_f_mod_phase, + sim->p_f_top); + + for (iter=0; iter<max_iter; ++iter) { + + set_bc_dirichlet(sim->p_f_ghost, sim->nz, +1, p_f_top); + sim->p_f_ghost[idx1g(sim->nz-1)] = p_f_top; /* Include top node in BC */ + set_bc_neumann(sim->p_f_ghost, sim->nz, -1); #ifdef DEBUG - puts(".. p_f_ghost after BC:"); print_array(sim->p_f_ghost, sim->nz+2); + puts(".. p_f_ghost after BC:"); print_array(sim->p_f_ghost, sim->nz+2); #endif - /* for (int i=0; i<sim->nz; ++i) */ - for (int i=0; i<sim->nz-1; ++i) - dp_f_impl[i] = darcy_pressure_change_1d( - i, - sim->nz, - sim->p_f_ghost, - sim->phi, - sim->k, - sim->dz, - sim->dt, - sim->beta_f, - sim->mu_f); - /* for (int i=0; i<sim->nz; ++i) { */ - for (int i=0; i<sim->nz-1; ++i) { + /* for (int i=0; i<sim->nz; ++i) */ + for (int i=0; i<sim->nz-1; ++i) + dp_f_impl[i] = darcy_pressure_change_1d(i, + sim->nz, + sim->p_f_ghost, + sim->phi, + sim->k, + sim->dz, + sim->dt, + sim->beta_f, + sim->mu_f); + /* for (int i=0; i<sim->nz; ++i) { */ + for (int i=0; i<sim->nz-1; ++i) { #ifdef DEBUG - printf("dp_f_expl[%d] = %g\ndp_f_impl[%d] = %g\n", - i, dp_f_expl[i], i, dp_f_impl[i]); + printf("dp_f_expl[%d] = %g\ndp_f_impl[%d] = %g\n", + i, dp_f_expl[i], i, dp_f_impl[i]); #endif - p_f = sim->p_f_ghost[idx1g(i)]; + p_f = sim->p_f_ghost[idx1g(i)]; - p_f_ghost_out[idx1g(i)] = p_f - + (1.0 - epsilon)*dp_f_expl[i] + epsilon*dp_f_impl[i]; + p_f_ghost_out[idx1g(i)] = p_f + + (1.0 - epsilon)*dp_f_expl[i] + + epsilon*dp_f_impl[i]; - /* apply relaxation */ - p_f_ghost_out[idx1g(i)] = p_f*(1.0 - theta) - + p_f_ghost_out[idx1g(i)]*theta; + /* apply relaxation */ + p_f_ghost_out[idx1g(i)] = p_f*(1.0 - theta) + + p_f_ghost_out[idx1g(i)]*theta; - r_norm[i] = (p_f_ghost_out[idx1g(i)] - p_f)/(p_f + 1e-16); - } + r_norm[i] = (p_f_ghost_out[idx1g(i)] - p_f)/(p_f + 1e-16); + } - r_norm_max = max(r_norm, sim->nz); + r_norm_max = max(r_norm, sim->nz); #ifdef DEBUG - puts(".. p_f_ghost_out:"); print_array(p_f_ghost_out, sim->nz+2); + puts(".. p_f_ghost_out:"); print_array(p_f_ghost_out, sim->nz+2); #endif - copy_values(p_f_ghost_out, sim->p_f_ghost, sim->nz+2); + copy_values(p_f_ghost_out, sim->p_f_ghost, sim->nz+2); #ifdef DEBUG - puts(".. p_f_ghost after update:"); - print_array(sim->p_f_ghost, sim->nz+2); + puts(".. p_f_ghost after update:"); + print_array(sim->p_f_ghost, sim->nz+2); #endif - if (r_norm_max <= rel_tol) { - set_bc_dirichlet(sim->p_f_ghost, sim->nz, +1, p_f_top); - sim->p_f_ghost[idx1g(sim->nz-1)] = p_f_top; /* top node in BC */ - set_bc_neumann(sim->p_f_ghost, sim->nz, -1); - free(dp_f_expl); - free(dp_f_impl); - free(p_f_ghost_out); - free(r_norm); + if (r_norm_max <= rel_tol) { + set_bc_dirichlet(sim->p_f_ghost, sim->nz, +1, p_f_top); + sim->p_f_ghost[idx1g(sim->nz-1)] = p_f_top; /* top node in BC */ + set_bc_neumann(sim->p_f_ghost, sim->nz, -1); + free(dp_f_expl); + free(dp_f_impl); + free(p_f_ghost_out); + free(r_norm); #ifdef DEBUG - printf(".. Solution converged after %d iterations\n", iter); + printf(".. Solution converged after %d iterations\n", iter); #endif - return 0; - } - } - - free(dp_f_expl); - free(dp_f_impl); - free(p_f_ghost_out); - free(r_norm); - fprintf(stderr, "darcy_solver_1d: "); - fprintf(stderr, "Solution did not converge after %d iterations\n", iter); - fprintf(stderr, ".. Residual normalized error: %f\n", r_norm_max); - return 1; + return 0; + } + } + + free(dp_f_expl); + free(dp_f_impl); + free(p_f_ghost_out); + free(r_norm); + fprintf(stderr, "darcy_solver_1d: "); + fprintf(stderr, "Solution did not converge after %d iterations\n", iter); + fprintf(stderr, ".. Residual normalized error: %f\n", r_norm_max); + return 1; } diff --git a/main.c b/main.c @@ -13,317 +13,318 @@ static void usage(void) { - struct simulation sim = init_sim(); - printf("%s: %s [OPTIONS] [NAME]\n" - "runs a simulation and outputs state in files prefixed with NAME.\n" - "If NAME is not specified, the default value '%s' is used.\n" - "optional arguments:\n" - " -N, --normalize normalize output velocity\n" - " -G, --gravity VAL gravity magnitude [m/s^2] (default %g)\n" - " -P, --normal-stress VAL normal stress on top [Pa] (default %g)\n" - " -m, --stress-ratio VAL applied stress ratio [-] (default %g)\n" - " -V, --velocity-bottom VAL base velocity at bottom [m/s] (default %g)\n" - " -A, --nonlocal-amplitude VAL amplitude of nonlocality [-] (default %g)\n" - " -b, --rate-dependence VAL rate dependence beyond yield [-] (default %g)\n" - " -f, --friction-coefficient VAL grain friction coefficient [-] (default %g)\n" - " -p, --porosity VAL porosity fraction [-] (default %g)\n" - " -d, --grain-size VAL representative grain size [m] (default %g)\n" - " -r, --density VAL grain material density [kg/m^3] (default %g)\n" - " -n, --resolution VAL number of cells in domain [-] (default %d)\n" - " -o, --origo VAL coordinate system origo [m] (default %g)\n" - " -L, --length VAL domain length [m] (default %g)\n" - " -F, --fluid enable pore fluid computations\n" - " -c, --fluid-compressibility VAL fluid compressibility [Pa^-1] (default %g)\n" - " -i, --fluid-viscosity VAL fluid viscosity [Pa*s] (default %g)\n" - " -R, --fluid-density VAL fluid density [kg/m^3] (default %g)\n" - " -k, --fluid-permeability VAL fluid intrinsic permeability [m^2] (default %g)\n" - " -O, --fluid-pressure-top VAL fluid pressure at +z edge [Pa] (default %g)\n" - " -a, --fluid-pressure-ampl VAL amplitude of pressure variations [Pa] (default %g)\n" - " -q, --fluid-pressure-freq VAL frequency of pressure variations [s^-1] (default %g)\n" - " -H, --fluid-pressure-phase VAL fluid pressure at +z edge [Pa] (default %g)\n" - " -t, --time VAL simulation start time [s] (default %g)\n" - " -T, --time-end VAL simulation end time [s] (default %g)\n" - " -D, --time-step VAL computational time step length [s] (default %g)\n" - " -I, --file-interval VAL interval between output files [s] (default %g)\n" - " -v, --version show version information\n" - " -h, --help show this message\n", - __func__, PROGNAME, - sim.name, - sim.G, - sim.P_wall, - sim.mu_wall, - sim.v_x_bot, - sim.A, - sim.b, - sim.mu_s, - sim.phi[0], - sim.d, - sim.rho_s, - sim.nz, - sim.origo_z, - sim.L_z, - sim.beta_f, - sim.mu_f, - sim.rho_f, - sim.k[0], - sim.p_f_top, - sim.p_f_mod_ampl, - sim.p_f_mod_freq, - sim.p_f_mod_phase, - sim.t, - sim.t_end, - sim.dt, - sim.file_dt); - free(sim.phi); - free(sim.k); + struct simulation sim = init_sim(); + printf("%s: %s [OPTIONS] [NAME]\n" + "runs a simulation and outputs state in files prefixed with NAME.\n" + "If NAME is not specified, the default value '%s' is used.\n" + "optional arguments:\n" + " -N, --normalize normalize output velocity\n" + " -G, --gravity VAL gravity magnitude [m/s^2] (default %g)\n" + " -P, --normal-stress VAL normal stress on top [Pa] (default %g)\n" + " -m, --stress-ratio VAL applied stress ratio [-] (default %g)\n" + " -V, --velocity-bottom VAL base velocity at bottom [m/s] (default %g)\n" + " -A, --nonlocal-amplitude VAL amplitude of nonlocality [-] (default %g)\n" + " -b, --rate-dependence VAL rate dependence beyond yield [-] (default %g)\n" + " -f, --friction-coefficient VAL grain friction coefficient [-] (default %g)\n" + " -p, --porosity VAL porosity fraction [-] (default %g)\n" + " -d, --grain-size VAL representative grain size [m] (default %g)\n" + " -r, --density VAL grain material density [kg/m^3] (default %g)\n" + " -n, --resolution VAL number of cells in domain [-] (default %d)\n" + " -o, --origo VAL coordinate system origo [m] (default %g)\n" + " -L, --length VAL domain length [m] (default %g)\n" + " -F, --fluid enable pore fluid computations\n" + " -c, --fluid-compressibility VAL fluid compressibility [Pa^-1] (default %g)\n" + " -i, --fluid-viscosity VAL fluid viscosity [Pa*s] (default %g)\n" + " -R, --fluid-density VAL fluid density [kg/m^3] (default %g)\n" + " -k, --fluid-permeability VAL fluid intrinsic permeability [m^2] (default %g)\n" + " -O, --fluid-pressure-top VAL fluid pressure at +z edge [Pa] (default %g)\n" + " -a, --fluid-pressure-ampl VAL amplitude of pressure variations [Pa] (default %g)\n" + " -q, --fluid-pressure-freq VAL frequency of pressure variations [s^-1] (default %g)\n" + " -H, --fluid-pressure-phase VAL fluid pressure at +z edge [Pa] (default %g)\n" + " -t, --time VAL simulation start time [s] (default %g)\n" + " -T, --time-end VAL simulation end time [s] (default %g)\n" + " -D, --time-step VAL computational time step length [s] (default %g)\n" + " -I, --file-interval VAL interval between output files [s] (default %g)\n" + " -v, --version show version information\n" + " -h, --help show this message\n", + __func__, PROGNAME, + sim.name, + sim.G, + sim.P_wall, + sim.mu_wall, + sim.v_x_bot, + sim.A, + sim.b, + sim.mu_s, + sim.phi[0], + sim.d, + sim.rho_s, + sim.nz, + sim.origo_z, + sim.L_z, + sim.beta_f, + sim.mu_f, + sim.rho_f, + sim.k[0], + sim.p_f_top, + sim.p_f_mod_ampl, + sim.p_f_mod_freq, + sim.p_f_mod_phase, + sim.t, + sim.t_end, + sim.dt, + sim.file_dt); + free(sim.phi); + free(sim.k); } static void version(void) { - printf("%s v%s\n" - "Licensed under the GNU Public License, v3+\n" - "written by Anders Damsgaard, anders@adamsgaard.dk\n" - "https://gitlab.com/admesg/1d_fd_simple_shear\n" - , PROGNAME, VERSION); + printf("%s v%s\n" + "Licensed under the GNU Public License, v3+\n" + "written by Anders Damsgaard, anders@adamsgaard.dk\n" + "https://gitlab.com/admesg/1d_fd_simple_shear\n" + , PROGNAME, VERSION); } int main(int argc, char* argv[]) { - /* load with default values */ - struct simulation sim = init_sim(); + /* load with default values */ + struct simulation sim = init_sim(); - int normalize = 0; + int normalize = 0; - int opt; - const char* optstring = "hvNn:G:P:m:V:A:b:f:Fp:d:r:o:L:c:i:R:k:O:a:q:H:t:T:D:I:"; - const struct option longopts[] = { - {"help", no_argument, NULL, 'h'}, - {"version", no_argument, NULL, 'v'}, - {"normalize", no_argument, NULL, 'N'}, - {"gravity", required_argument, NULL, 'G'}, - {"normal-stress", required_argument, NULL, 'P'}, - {"stress-ratio", required_argument, NULL, 'm'}, - {"velocity-bottom", required_argument, NULL, 'V'}, - {"nonlocal-amplitude", required_argument, NULL, 'A'}, - {"rate-dependence", required_argument, NULL, 'b'}, - {"friction-coefficient", required_argument, NULL, 'f'}, - {"porosity", required_argument, NULL, 'p'}, - {"grain-size", required_argument, NULL, 'd'}, - {"density", required_argument, NULL, 'r'}, - {"resolution", required_argument, NULL, 'n'}, - {"origo", required_argument, NULL, 'o'}, - {"length", required_argument, NULL, 'L'}, - {"fluid", no_argument, NULL, 'F'}, - {"fluid-compressiblity", required_argument, NULL, 'c'}, - {"fluid-viscosity", required_argument, NULL, 'i'}, - {"fluid-density", required_argument, NULL, 'R'}, - {"fluid-permeability", required_argument, NULL, 'k'}, - {"fluid-pressure-top", required_argument, NULL, 'O'}, - {"fluid-pressure-ampl", required_argument, NULL, 'a'}, - {"fluid-pressure-freq", required_argument, NULL, 'q'}, - {"fluid-pressure-phase", required_argument, NULL, 'H'}, - {"time", required_argument, NULL, 't'}, - {"time-end", required_argument, NULL, 'T'}, - {"time-step", required_argument, NULL, 'D'}, - {"file-interval", required_argument, NULL, 'I'}, - {NULL, 0, NULL, 0} - }; + int opt; + const char* optstring = "hvNn:G:P:m:V:A:b:f:Fp:d:r:o:L:c:i:R:k:O:a:q:H:t:T:D:I:"; + const struct option longopts[] = { + {"help", no_argument, NULL, 'h'}, + {"version", no_argument, NULL, 'v'}, + {"normalize", no_argument, NULL, 'N'}, + {"gravity", required_argument, NULL, 'G'}, + {"normal-stress", required_argument, NULL, 'P'}, + {"stress-ratio", required_argument, NULL, 'm'}, + {"velocity-bottom", required_argument, NULL, 'V'}, + {"nonlocal-amplitude", required_argument, NULL, 'A'}, + {"rate-dependence", required_argument, NULL, 'b'}, + {"friction-coefficient", required_argument, NULL, 'f'}, + {"porosity", required_argument, NULL, 'p'}, + {"grain-size", required_argument, NULL, 'd'}, + {"density", required_argument, NULL, 'r'}, + {"resolution", required_argument, NULL, 'n'}, + {"origo", required_argument, NULL, 'o'}, + {"length", required_argument, NULL, 'L'}, + {"fluid", no_argument, NULL, 'F'}, + {"fluid-compressiblity", required_argument, NULL, 'c'}, + {"fluid-viscosity", required_argument, NULL, 'i'}, + {"fluid-density", required_argument, NULL, 'R'}, + {"fluid-permeability", required_argument, NULL, 'k'}, + {"fluid-pressure-top", required_argument, NULL, 'O'}, + {"fluid-pressure-ampl", required_argument, NULL, 'a'}, + {"fluid-pressure-freq", required_argument, NULL, 'q'}, + {"fluid-pressure-phase", required_argument, NULL, 'H'}, + {"time", required_argument, NULL, 't'}, + {"time-end", required_argument, NULL, 'T'}, + {"time-step", required_argument, NULL, 'D'}, + {"file-interval", required_argument, NULL, 'I'}, + {NULL, 0, NULL, 0} + }; - double new_phi = sim.phi[0]; - double new_k = sim.k[0]; - while ((opt = getopt_long(argc, argv, optstring, longopts, NULL)) != -1) { - switch (opt) { - case -1: /* no more arguments */ - case 0: /* long options toggles */ - break; + double new_phi = sim.phi[0]; + double new_k = sim.k[0]; + while ((opt = getopt_long(argc, argv, optstring, longopts, NULL)) != -1) { + switch (opt) { + case -1: /* no more arguments */ + case 0: /* long options toggles */ + break; - case 'h': - usage(); - free(sim.phi); - free(sim.k); - return 0; - case 'v': - version(); - free(sim.phi); - free(sim.k); - return 0; - case 'n': - sim.nz = atoi(optarg); - break; - case 'N': - normalize = 1; - break; - case 'G': - sim.G = atof(optarg); - break; - case 'P': - sim.P_wall = atof(optarg); - break; - case 'm': - sim.mu_wall = atof(optarg); - break; - case 'V': - sim.v_x_bot = atof(optarg); - break; - case 'A': - sim.A = atof(optarg); - break; - case 'b': - sim.b = atof(optarg); - break; - case 'f': - sim.mu_s = atof(optarg); - break; - case 'p': - new_phi = atof(optarg); - break; - case 'd': - sim.d = atof(optarg); - break; - case 'r': - sim.rho_s = atof(optarg); - break; - case 'o': - sim.origo_z = atof(optarg); - break; - case 'L': - sim.L_z = atof(optarg); - break; - case 'F': - sim.fluid = 1; - break; - case 'c': - sim.beta_f = atof(optarg); - break; - case 'i': - sim.mu_f = atof(optarg); - break; - case 'R': - sim.rho_f = atof(optarg); - break; - case 'k': - new_k = atof(optarg); - break; - case 'O': - sim.p_f_top = atof(optarg); - break; - case 'a': - sim.p_f_mod_ampl = atof(optarg); - break; - case 'q': - sim.p_f_mod_freq = atof(optarg); - break; - case 'H': - sim.p_f_mod_phase = atof(optarg); - break; - case 't': - sim.t = atof(optarg); - break; - case 'T': - sim.t_end = atof(optarg); - break; - case 'D': - sim.dt = atof(optarg); - break; - case 'I': - sim.file_dt = atof(optarg); - break; + case 'h': + usage(); + free(sim.phi); + free(sim.k); + return 0; + case 'v': + version(); + free(sim.phi); + free(sim.k); + return 0; + case 'n': + sim.nz = atoi(optarg); + break; + case 'N': + normalize = 1; + break; + case 'G': + sim.G = atof(optarg); + break; + case 'P': + sim.P_wall = atof(optarg); + break; + case 'm': + sim.mu_wall = atof(optarg); + break; + case 'V': + sim.v_x_bot = atof(optarg); + break; + case 'A': + sim.A = atof(optarg); + break; + case 'b': + sim.b = atof(optarg); + break; + case 'f': + sim.mu_s = atof(optarg); + break; + case 'p': + new_phi = atof(optarg); + break; + case 'd': + sim.d = atof(optarg); + break; + case 'r': + sim.rho_s = atof(optarg); + break; + case 'o': + sim.origo_z = atof(optarg); + break; + case 'L': + sim.L_z = atof(optarg); + break; + case 'F': + sim.fluid = 1; + break; + case 'c': + sim.beta_f = atof(optarg); + break; + case 'i': + sim.mu_f = atof(optarg); + break; + case 'R': + sim.rho_f = atof(optarg); + break; + case 'k': + new_k = atof(optarg); + break; + case 'O': + sim.p_f_top = atof(optarg); + break; + case 'a': + sim.p_f_mod_ampl = atof(optarg); + break; + case 'q': + sim.p_f_mod_freq = atof(optarg); + break; + case 'H': + sim.p_f_mod_phase = atof(optarg); + break; + case 't': + sim.t = atof(optarg); + break; + case 'T': + sim.t_end = atof(optarg); + break; + case 'D': + sim.dt = atof(optarg); + break; + case 'I': + sim.file_dt = atof(optarg); + break; - default: - fprintf(stderr, "%s: invalid option -- %c\n", argv[0], opt); - fprintf(stderr, "Try `%s --help` for more information\n", - argv[0]); - return -2; - } - } - for (int i=optind; i<argc; ++i) { - if (i>optind) { - fprintf(stderr, "error: more than one simulation name specified\n"); - return 1; - } - sprintf(sim.name, "%s", argv[i]); - } + default: + fprintf(stderr, "%s: invalid option -- %c\n", argv[0], opt); + fprintf(stderr, "Try `%s --help` for more information\n", + argv[0]); + return -2; + } + } + for (int i=optind; i<argc; ++i) { + if (i>optind) { + fprintf(stderr, + "error: more than one simulation name specified\n"); + return 1; + } + sprintf(sim.name, "%s", argv[i]); + } - prepare_arrays(&sim); + prepare_arrays(&sim); - if (!isnan(new_phi)) - for (int i=0; i<sim.nz; ++i) - sim.phi[i] = new_phi; - if (!isnan(new_k)) - for (int i=0; i<sim.nz; ++i) - sim.k[i] = new_k; + if (!isnan(new_phi)) + for (int i=0; i<sim.nz; ++i) + sim.phi[i] = new_phi; + if (!isnan(new_k)) + for (int i=0; i<sim.nz; ++i) + sim.k[i] = new_k; - lithostatic_pressure_distribution(&sim); + lithostatic_pressure_distribution(&sim); - if (sim.fluid) - hydrostatic_fluid_pressure_distribution(&sim); + if (sim.fluid) + hydrostatic_fluid_pressure_distribution(&sim); #ifdef DEBUG - puts(".. p_f_ghost before iterations:"); print_array(sim.p_f_ghost, sim.nz+2); - puts(""); - puts(".. normal stress before iterations:"); print_array(sim.sigma_n, sim.nz); - puts(""); + puts(".. p_f_ghost before iterations:"); print_array(sim.p_f_ghost, sim.nz+2); + puts(""); + puts(".. normal stress before iterations:"); print_array(sim.sigma_n, sim.nz); + puts(""); #endif - double filetimeclock = 0.0; - unsigned long iter = 0; - while (sim.t <= sim.t_end) { + double filetimeclock = 0.0; + unsigned long iter = 0; + while (sim.t <= sim.t_end) { - if (sim.fluid) { - if (darcy_solver_1d(&sim, 10000, 1e-5)) - exit(1); + if (sim.fluid) { + if (darcy_solver_1d(&sim, 10000, 1e-5)) + exit(1); #ifdef DEBUG - puts(".. p_f_ghost:"); print_array(sim.p_f_ghost, sim.nz+2); - puts(""); + puts(".. p_f_ghost:"); print_array(sim.p_f_ghost, sim.nz+2); + puts(""); #endif - } + } - compute_effective_stress(&sim); - compute_friction(&sim); - compute_cooperativity_length(&sim); + compute_effective_stress(&sim); + compute_friction(&sim); + compute_cooperativity_length(&sim); - if (iter == 0) - check_simulation_parameters(&sim); + if (iter == 0) + check_simulation_parameters(&sim); #ifdef DEBUG - puts("\n## Before solver"); - puts(".. sigma_n_eff:"); print_array(sim.sigma_n_eff, sim.nz); - puts(".. mu:"); print_array(sim.mu, sim.nz); + puts("\n## Before solver"); + puts(".. sigma_n_eff:"); print_array(sim.sigma_n_eff, sim.nz); + puts(".. mu:"); print_array(sim.mu, sim.nz); #endif - if (implicit_1d_jacobian_poisson_solver(&sim, 10000, 1e-5)) - exit(1); + if (implicit_1d_jacobian_poisson_solver(&sim, 10000, 1e-5)) + exit(1); - compute_shear_strain_rate_plastic(&sim); - compute_shear_velocity(&sim); + compute_shear_strain_rate_plastic(&sim); + compute_shear_velocity(&sim); - sim.t += sim.dt; - filetimeclock += sim.dt; - iter++; + sim.t += sim.dt; + filetimeclock += sim.dt; + iter++; - if (filetimeclock >= sim.file_dt || iter == 0) { - write_output_file(&sim); - filetimeclock = 0.0; - } - } + if (filetimeclock >= sim.file_dt || iter == 0) { + write_output_file(&sim); + filetimeclock = 0.0; + } + } - if (normalize) { - double max_v_x = max(sim.v_x, sim.nz); - for (int i=0; i<sim.nz; ++i) - sim.v_x[i] /= max_v_x; - } + if (normalize) { + double max_v_x = max(sim.v_x, sim.nz); + for (int i=0; i<sim.nz; ++i) + sim.v_x[i] /= max_v_x; + } - if (sim.fluid) - for (int i=0; i<sim.nz; ++i) - printf("%.17g\t%.17g\t%.17g\t%.17g\n", - sim.z[i], - sim.v_x[i], - sim.sigma_n_eff[i], - sim.p_f_ghost[idx1g(i)]); - else - print_three_arrays(sim.z, sim.v_x, sim.sigma_n_eff, sim.nz); + if (sim.fluid) + for (int i=0; i<sim.nz; ++i) + printf("%.17g\t%.17g\t%.17g\t%.17g\n", + sim.z[i], + sim.v_x[i], + sim.sigma_n_eff[i], + sim.p_f_ghost[idx1g(i)]); + else + print_three_arrays(sim.z, sim.v_x, sim.sigma_n_eff, sim.nz); - free_arrays(&sim); - return 0; + free_arrays(&sim); + return 0; } diff --git a/simulation.c b/simulation.c @@ -6,430 +6,421 @@ void prepare_arrays(struct simulation* sim) { - sim->z = linspace(sim->origo_z, /* spatial coordinates */ - sim->origo_z + sim->L_z, - sim->nz); - sim->dz = sim->z[1] - sim->z[0]; /* cell spacing */ - sim->mu = zeros(sim->nz); /* stress ratio */ - sim->sigma_n_eff = zeros(sim->nz); /* effective normal stress */ - sim->sigma_n = zeros(sim->nz); /* normal stess */ - sim->p_f_ghost = zeros(sim->nz+2); /* fluid pressure with ghost nodes */ - free(sim->phi); - sim->phi = zeros(sim->nz); /* porosity */ - free(sim->k); - sim->k = zeros(sim->nz); /* permeability */ - sim->xi = zeros(sim->nz); /* cooperativity length */ - sim->gamma_dot_p = zeros(sim->nz); /* shear velocity */ - sim->v_x = zeros(sim->nz); /* shear velocity */ - sim->g_ghost = zeros(sim->nz+2); /* fluidity with ghost nodes */ + sim->z = linspace(sim->origo_z, /* spatial coordinates */ + sim->origo_z + sim->L_z, + sim->nz); + sim->dz = sim->z[1] - sim->z[0]; /* cell spacing */ + sim->mu = zeros(sim->nz); /* stress ratio */ + sim->sigma_n_eff = zeros(sim->nz); /* effective normal stress */ + sim->sigma_n = zeros(sim->nz); /* normal stess */ + sim->p_f_ghost = zeros(sim->nz+2); /* fluid pressure with ghost nodes */ + free(sim->phi); + sim->phi = zeros(sim->nz); /* porosity */ + free(sim->k); + sim->k = zeros(sim->nz); /* permeability */ + sim->xi = zeros(sim->nz); /* cooperativity length */ + sim->gamma_dot_p = zeros(sim->nz); /* shear velocity */ + sim->v_x = zeros(sim->nz); /* shear velocity */ + sim->g_ghost = zeros(sim->nz+2); /* fluidity with ghost nodes */ } void free_arrays(struct simulation* sim) { - free(sim->z); - free(sim->mu); - free(sim->sigma_n_eff); - free(sim->sigma_n); - free(sim->p_f_ghost); - free(sim->k); - free(sim->phi); - free(sim->xi); - free(sim->gamma_dot_p); - free(sim->v_x); - free(sim->g_ghost); + free(sim->z); + free(sim->mu); + free(sim->sigma_n_eff); + free(sim->sigma_n); + free(sim->p_f_ghost); + free(sim->k); + free(sim->phi); + free(sim->xi); + free(sim->gamma_dot_p); + free(sim->v_x); + free(sim->g_ghost); } static void warn_parameter_value( - const char message[], - const double value, - int* return_status) + const char message[], + const double value, + int* return_status) { - fprintf(stderr, "check_simulation_parameters: %s (%.17g)\n", - message, value); - *return_status = 1; + fprintf(stderr, "check_simulation_parameters: %s (%.17g)\n", + message, value); + *return_status = 1; } -static void check_float( - const char name[], - const double value, - int* return_status) +static void check_float(const char name[], + const double value, + int* return_status) { - if (isnan(value)) { - warn_parameter_value("%s is NaN", value, return_status); - *return_status = 1; - } else if (isinf(value)) { - warn_parameter_value("%s is infinite", value, return_status); - *return_status = 1; - } + if (isnan(value)) { + warn_parameter_value("%s is NaN", value, return_status); + *return_status = 1; + } else if (isinf(value)) { + warn_parameter_value("%s is infinite", value, return_status); + *return_status = 1; + } } void check_simulation_parameters(const struct simulation* sim) { - int return_status = 0; - - check_float("sim.G", sim->G, &return_status); - if (sim->G < 0.0) - warn_parameter_value("sim.G is negative", sim->G, &return_status); - - 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); - - 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); - - check_float("sim.A", sim->A, &return_status); - if (sim->A < 0.0) - warn_parameter_value("sim.A is negative", sim->A, &return_status); - - check_float("sim.b", sim->b, &return_status); - if (sim->b < 0.0) - warn_parameter_value("sim.b is negative", sim->b, &return_status); - - 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); - - 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); - - 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); - - if (sim->nz <= 0) - warn_parameter_value("sim.nz is not a positive number", sim->nz, - &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); - - if (sim->nz <= 0) - warn_parameter_value("sim.nz is not a positive number", sim->nz, - &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); - - 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); - - 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); - - check_float("sim.dt", sim->t_end, &return_status); - if (sim->dt <= 0.0) - warn_parameter_value("sim.dt is not a positive number", - 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); - - 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); - - if (sim->fluid != 0 && sim->fluid != 1) - warn_parameter_value("sim.fluid has an invalid value", - (double)sim->fluid, &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); - - 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); - - 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); - - 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); - - 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); - - 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); - - } - - if (return_status != 0) { - fprintf(stderr, "error: aborting due to invalid parameter choices\n"); - exit(return_status); - } + int return_status = 0; + + check_float("sim.G", sim->G, &return_status); + if (sim->G < 0.0) + warn_parameter_value("sim.G is negative", sim->G, &return_status); + + 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); + + 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); + + check_float("sim.A", sim->A, &return_status); + if (sim->A < 0.0) + warn_parameter_value("sim.A is negative", sim->A, &return_status); + + check_float("sim.b", sim->b, &return_status); + if (sim->b < 0.0) + warn_parameter_value("sim.b is negative", sim->b, &return_status); + + 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); + + 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); + + 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); + + if (sim->nz <= 0) + warn_parameter_value("sim.nz is not a positive number", sim->nz, + &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); + + if (sim->nz <= 0) + warn_parameter_value("sim.nz is not a positive number", sim->nz, + &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); + + 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); + + 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); + + check_float("sim.dt", sim->t_end, &return_status); + if (sim->dt <= 0.0) + warn_parameter_value("sim.dt is not a positive number", + 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); + + 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); + + if (sim->fluid != 0 && sim->fluid != 1) + warn_parameter_value("sim.fluid has an invalid value", + (double)sim->fluid, &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); + + 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); + + 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); + + 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); + + 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); + + 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); + + } + + if (return_status != 0) { + fprintf(stderr, "error: aborting due to invalid parameter choices\n"); + exit(return_status); + } } void lithostatic_pressure_distribution(struct simulation* sim) { - for (int 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]); + for (int 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]); } void compute_friction(struct simulation* sim) { - if (sim->fluid) - for (int i=0; i<sim->nz; ++i) - sim->mu[i] = sim->mu_wall/ - (sim->sigma_n_eff[i]/(sim->P_wall - sim->p_f_top)); - - else - for (int i=0; i<sim->nz; ++i) - sim->mu[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); - + if (sim->fluid) + for (int i=0; i<sim->nz; ++i) + sim->mu[i] = sim->mu_wall/ + (sim->sigma_n_eff[i]/(sim->P_wall - sim->p_f_top)); + + else + for (int i=0; i<sim->nz; ++i) + sim->mu[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); } double shear_strain_rate_plastic( - const double fluidity, - const double friction) + const double fluidity, + const double friction) { - return fluidity*friction; + return fluidity*friction; } void compute_shear_strain_rate_plastic(struct simulation* sim) { - for (int i=0; i<sim->nz; ++i) - sim->gamma_dot_p[i] = - shear_strain_rate_plastic(sim->g_ghost[idx1g(i)], sim->mu[i]); + for (int i=0; i<sim->nz; ++i) + sim->gamma_dot_p[i] = shear_strain_rate_plastic(sim->g_ghost[idx1g(i)], + sim->mu[i]); } void compute_shear_velocity(struct simulation* sim) { - // TODO: implement iterative solver - // Dirichlet BC at bottom - sim->v_x[0] = sim->v_x_bot; + // TODO: implement iterative solver + // Dirichlet BC at bottom + sim->v_x[0] = sim->v_x_bot; - for (int i=1; i<sim->nz; ++i) - sim->v_x[i] = sim->v_x[i-1] + sim->gamma_dot_p[i]*sim->dz; + for (int i=1; i<sim->nz; ++i) + sim->v_x[i] = sim->v_x[i-1] + sim->gamma_dot_p[i]*sim->dz; } void compute_effective_stress(struct simulation* sim) { - if (sim->fluid) - for (int i=0; i<sim->nz; ++i) - sim->sigma_n_eff[i] = sim->sigma_n[i] - sim->p_f_ghost[idx1g(i)]; - else - for (int i=0; i<sim->nz; ++i) - sim->sigma_n_eff[i] = sim->sigma_n[i]; + if (sim->fluid) + for (int i=0; i<sim->nz; ++i) + sim->sigma_n_eff[i] = sim->sigma_n[i] - sim->p_f_ghost[idx1g(i)]; + else + for (int i=0; i<sim->nz; ++i) + sim->sigma_n_eff[i] = sim->sigma_n[i]; } -double cooperativity_length( - const double A, - const double d, - const double mu, - const double mu_s) +double cooperativity_length(const double A, + const double d, + const double mu, + const double mu_s) { - return A*d/sqrt(fabs(mu - mu_s)); + return A*d/sqrt(fabs(mu - mu_s)); } void compute_cooperativity_length(struct simulation* sim) { - for (int i=0; i<sim->nz; ++i) - sim->xi[i] = cooperativity_length( - sim->A, sim->d, sim->mu[i], sim->mu_s); + for (int i=0; i<sim->nz; ++i) + sim->xi[i] = cooperativity_length(sim->A, sim->d, sim->mu[i], + sim->mu_s); } -double local_fluidity( - const double p, - const double mu, - const double mu_s, - const double b, - const double rho_s, - const double d) +double local_fluidity(const double p, + const double mu, + const double mu_s, + const double b, + const double rho_s, + const double d) { - if (mu <= mu_s) - return 0.0; - else - return sqrt(p/rho_s*d*d) * (mu - mu_s)/(b*mu); + if (mu <= mu_s) + return 0.0; + else + return sqrt(p/rho_s*d*d) * (mu - mu_s)/(b*mu); } void compute_local_fluidity(struct simulation* sim) { - for (int i=0; i<sim->nz; ++i) - sim->g_ghost[idx1g(i)] = local_fluidity( - sim->sigma_n_eff[i], - sim->mu[i], - sim->mu_s, - sim->b, - sim->rho_s, - sim->d); + for (int i=0; i<sim->nz; ++i) + sim->g_ghost[idx1g(i)] = local_fluidity(sim->sigma_n_eff[i], + sim->mu[i], + sim->mu_s, + sim->b, + sim->rho_s, + sim->d); } void set_bc_neumann(double* g_ghost, const int nz, const int boundary) { - if (boundary == -1) - g_ghost[0] = g_ghost[1]; - else if (boundary == +1) - g_ghost[nz+1] = g_ghost[nz]; - else { - fprintf(stderr, "set_bc_neumann: Unknown boundary %d\n", boundary); - exit(1); - } + if (boundary == -1) + g_ghost[0] = g_ghost[1]; + else if (boundary == +1) + g_ghost[nz+1] = g_ghost[nz]; + else { + fprintf(stderr, "set_bc_neumann: Unknown boundary %d\n", boundary); + exit(1); + } } -void set_bc_dirichlet( - double* g_ghost, - const int nz, - const int boundary, - const double value) +void set_bc_dirichlet(double* g_ghost, + const int nz, + const int boundary, + const double value) { - if (boundary == -1) - g_ghost[0] = value; - else if (boundary == +1) - g_ghost[nz+1] = value; - else { - fprintf(stderr, "set_bc_dirichlet: Unknown boundary %d\n", boundary); - exit(1); - } + if (boundary == -1) + g_ghost[0] = value; + else if (boundary == +1) + g_ghost[nz+1] = value; + else { + fprintf(stderr, "set_bc_dirichlet: Unknown boundary %d\n", boundary); + exit(1); + } } -void poisson_solver_1d_cell_update( - int i, - const double* g_in, - double* g_out, - double* r_norm, - const double dz, - const double* mu, - const double* p, - const double* xi, - const double mu_s, - const double b, - const double rho_s, - const double d) +void poisson_solver_1d_cell_update(int i, + const double* g_in, + double* g_out, + double* r_norm, + const double dz, + const double* mu, + const double* p, + const double* xi, + const double mu_s, + const double b, + const double rho_s, + const double d) { - double coorp_term = dz*dz/(2.0*pow(xi[i], 2.0)); - int gi = idx1g(i); - g_out[gi] = 1.0/(1.0 + coorp_term)*(coorp_term* - local_fluidity(p[i], mu[i], mu_s, b, rho_s, d) - + g_in[gi+1]/2.0 - + g_in[gi-1]/2.0); + double coorp_term = dz*dz/(2.0*pow(xi[i], 2.0)); + int gi = idx1g(i); + g_out[gi] = 1.0/(1.0 + coorp_term)*(coorp_term* + local_fluidity(p[i], mu[i], mu_s, b, rho_s, d) + + g_in[gi+1]/2.0 + + g_in[gi-1]/2.0); - r_norm[i] = pow(g_out[gi] - g_in[gi], 2.0) / (pow(g_out[gi], 2.0) + 1e-16); + r_norm[i] = pow(g_out[gi] - g_in[gi], 2.0) / (pow(g_out[gi], 2.0) + 1e-16); #ifdef DEBUG - printf("-- %d --------------\n", i); - printf("coorp_term: %g\n", coorp_term); - printf(" g_local: %g\n", local_fluidity(p[i], mu[i], mu_s, b, rho_s, d)); - printf(" g_in: %g\n", g_in[gi]); - printf(" g_out: %g\n", g_out[gi]); - printf(" r_norm: %g\n", r_norm[i]); + printf("-- %d --------------\n", i); + printf("coorp_term: %g\n", coorp_term); + printf(" g_local: %g\n", local_fluidity(p[i], mu[i], mu_s, b, rho_s, d)); + printf(" g_in: %g\n", g_in[gi]); + printf(" g_out: %g\n", g_out[gi]); + printf(" r_norm: %g\n", r_norm[i]); #endif } -int implicit_1d_jacobian_poisson_solver( - struct simulation* sim, - const int max_iter, - const double rel_tol) +int implicit_1d_jacobian_poisson_solver(struct simulation* sim, + const int max_iter, + const double rel_tol) { - double* g_ghost_out = empty(sim->nz+2); - double* r_norm = empty(sim->nz); + double* g_ghost_out = empty(sim->nz+2); + double* r_norm = empty(sim->nz); - int iter; - double r_norm_max = NAN; + int iter; + double r_norm_max = NAN; - for (iter=0; iter<max_iter; ++iter) { + for (iter=0; iter<max_iter; ++iter) { #ifdef DEBUG - printf("\n@@@ ITERATION %d @@@\n", iter); + printf("\n@@@ ITERATION %d @@@\n", iter); #endif - /* Dirichlet BCs resemble fixed particle velocities */ - set_bc_dirichlet(sim->g_ghost, sim->nz, -1, 0.0); - set_bc_dirichlet(sim->g_ghost, sim->nz, +1, 0.0); - - /* Neumann BCs resemble free surfaces */ - /* set_bc_neumann(sim->g_ghost, sim->nz, +1); */ - - for (int i=0; i<sim->nz; ++i) - poisson_solver_1d_cell_update( - i, - sim->g_ghost, - g_ghost_out, - r_norm, - sim->dz, - sim->mu, - sim->sigma_n_eff, - sim->xi, - sim->mu_s, - sim->b, - sim->rho_s, - sim->d); - r_norm_max = max(r_norm, sim->nz); - - copy_values(g_ghost_out, sim->g_ghost, sim->nz+2); - - if (r_norm_max <= rel_tol) { - set_bc_dirichlet(sim->g_ghost, sim->nz, -1, 0.0); - set_bc_dirichlet(sim->g_ghost, sim->nz, +1, 0.0); - free(g_ghost_out); - free(r_norm); - /* printf(".. Solution converged after %d iterations\n", iter); */ - return 0; - } - } - - free(g_ghost_out); - free(r_norm); - fprintf(stderr, "implicit_1d_jacobian_poisson_solver: "); - fprintf(stderr, "Solution did not converge after %d iterations\n", iter); - fprintf(stderr, ".. Residual normalized error: %f\n", r_norm_max); - return 1; + /* Dirichlet BCs resemble fixed particle velocities */ + set_bc_dirichlet(sim->g_ghost, sim->nz, -1, 0.0); + set_bc_dirichlet(sim->g_ghost, sim->nz, +1, 0.0); + + /* Neumann BCs resemble free surfaces */ + /* set_bc_neumann(sim->g_ghost, sim->nz, +1); */ + + for (int i=0; i<sim->nz; ++i) + poisson_solver_1d_cell_update(i, + sim->g_ghost, + g_ghost_out, + r_norm, + sim->dz, + sim->mu, + sim->sigma_n_eff, + sim->xi, + sim->mu_s, + sim->b, + sim->rho_s, + sim->d); + r_norm_max = max(r_norm, sim->nz); + + copy_values(g_ghost_out, sim->g_ghost, sim->nz+2); + + if (r_norm_max <= rel_tol) { + set_bc_dirichlet(sim->g_ghost, sim->nz, -1, 0.0); + set_bc_dirichlet(sim->g_ghost, sim->nz, +1, 0.0); + free(g_ghost_out); + free(r_norm); + /* printf(".. Solution converged after %d iterations\n", iter); */ + return 0; + } + } + + free(g_ghost_out); + free(r_norm); + fprintf(stderr, "implicit_1d_jacobian_poisson_solver: "); + fprintf(stderr, "Solution did not converge after %d iterations\n", iter); + fprintf(stderr, ".. Residual normalized error: %f\n", r_norm_max); + return 1; } void write_output_file(struct simulation* sim) { - char outfile[200]; - FILE *fp; - sprintf(outfile, "%s.output%05d.txt", sim->name, sim->n_file++); - - fp = fopen(outfile, "w"); - if (sim->fluid) - for (int i=0; i<sim->nz; ++i) - fprintf(fp, "%.17g\t%.17g\t%.17g\t%.17g\t%.17g\n", - sim->z[i], - sim->v_x[i], - sim->sigma_n_eff[i], - sim->p_f_ghost[idx1g(i)], - sim->mu[i]); - else - fprint_three_arrays(fp, sim->z, sim->v_x, sim->sigma_n_eff, sim->nz); - - fclose(fp); + char outfile[200]; + FILE *fp; + sprintf(outfile, "%s.output%05d.txt", sim->name, sim->n_file++); + + fp = fopen(outfile, "w"); + if (sim->fluid) + for (int i=0; i<sim->nz; ++i) + fprintf(fp, "%.17g\t%.17g\t%.17g\t%.17g\t%.17g\n", + sim->z[i], + sim->v_x[i], + sim->sigma_n_eff[i], + sim->p_f_ghost[idx1g(i)], + sim->mu[i]); + else + fprint_three_arrays(fp, sim->z, sim->v_x, sim->sigma_n_eff, sim->nz); + + fclose(fp); }