commit bfb86ef9008e86da090c6d6c84e165517d0a85b0
parent 7fe3756e69502a715e4554615f16304d6ef76565
Author: Anders Damsgaard <anders@adamsgaard.dk>
Date:   Wed, 18 Nov 2020 13:55:10 +0100
preallocate arrays for iterative solvers
Diffstat:
| M | fluid.c |  |  | 135 | ++++++++++++++++++++++++++++++++++++++++--------------------------------------- | 
| M | simulation.c |  |  | 97 | ++++++++++++++++++++++++++++++++++++++----------------------------------------- | 
| M | simulation.h |  |  | 6 | ++++++ | 
3 files changed, 121 insertions(+), 117 deletions(-)
diff --git a/fluid.c b/fluid.c
@@ -111,21 +111,24 @@ set_fluid_bcs(double *p_f_ghost, struct simulation *sim, const double p_f_top)
 
 static double
 darcy_pressure_change_1d(const int i,
-			 const int nz,
-			 const double *p_f_ghost_in,
-			 const double *phi,
-			 const double *phi_dot,
-			 const double *k,
-			 const double dz,
-			 const double beta_f,
-			 const double alpha,
-			 const double mu_f,
-			 const double D)
+                         const int nz,
+                         const double *p_f_ghost_in,
+                         const double *phi,
+                         const double *phi_dot,
+                         const double *k,
+                         const double dz,
+                         const double beta_f,
+                         const double alpha,
+                         const double mu_f,
+                         const double D)
 {
 	double k_, div_k_grad_p, k_zn, k_zp;
 
 	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);
+		return D * (p_f_ghost_in[i + 2]
+		            - 2.0 * p_f_ghost_in[i + 1]
+		            + p_f_ghost_in[i])
+		       / (dz * dz);
 
 	else {
 
@@ -171,17 +174,13 @@ darcy_solver_1d(struct simulation *sim,
 {
 	int i, iter, solved = 0;
 	double epsilon, p_f_top, r_norm_max = NAN;
-	double *p_f_dot_expl, *p_f_dot_impl, *p_f_ghost_new;
-	double *tmp, *r_norm, *old_val;
-
-	p_f_dot_impl = zeros(sim->nz);
-	p_f_dot_expl = zeros(sim->nz);
-	p_f_ghost_new = zeros(sim->nz + 2);
+	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 = 1.0: implicit */
+	/* epsilon = 0.5; */
 	epsilon = 0.5;
 
 	if (isnan(sim->p_f_mod_pulse_time))
@@ -205,84 +204,80 @@ darcy_solver_1d(struct simulation *sim,
 
 
 	/* set fluid BCs (1 of 2) */
-	copy_values(sim->p_f_ghost, p_f_ghost_new, sim->nz + 2);
-	set_fluid_bcs(p_f_ghost_new, sim, p_f_top);
+	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) {
-		/* compute explicit solution to pressure change */
 		for (i = 0; i < sim->nz; ++i)
-			p_f_dot_expl[i] = darcy_pressure_change_1d(i,
-			                                           sim->nz,
-			                                           sim->p_f_ghost,
-			                                           sim->phi,
-			                                           sim->phi_dot,
-			                                           sim->k,
-			                                           sim->dz,
-			                                           sim->beta_f,
-			                                           sim->alpha,
-			                                           sim->mu_f,
-													   sim->D);
+			sim->p_f_dot_expl[i] = darcy_pressure_change_1d(i,
+			                                                sim->nz,
+			                                                sim->p_f_ghost,
+			                                                sim->phi,
+			                                                sim->phi_dot,
+			                                                sim->k,
+			                                                sim->dz,
+			                                                sim->beta_f,
+			                                                sim->alpha,
+			                                                sim->mu_f,
+													        sim->D);
 	}
+
+	/* implicit solution with Jacobian iterations */
 	if (epsilon > 0.0) {
-		/* compute implicit solution with Jacobian iterations */
-		r_norm = zeros(sim->nz);
-		old_val = empty(sim->nz);
 
 		for (iter = 0; iter < max_iter; ++iter) {
-			copy_values(sim->p_f_dot, old_val, sim->nz);
+			copy_values(sim->p_f_dot_impl, sim->old_val, sim->nz);
 
 			/* set fluid BCs (2 of 2) */
-			set_fluid_bcs(p_f_ghost_new, sim, p_f_top);
+			set_fluid_bcs(sim->new_ghost, sim, p_f_top);
 #ifdef DEBUG
 			puts(".. p_f_ghost after BC:");
-			print_array(p_f_ghost_new, sim->nz + 2);
+			print_array(sim->new_ghost, sim->nz + 2);
 #endif
 
 			for (i = 0; i < sim->nz - 1; ++i)
-				p_f_dot_impl[i] = darcy_pressure_change_1d(i,
-				                                           sim->nz,
-				                                           p_f_ghost_new,
-				                                           sim->phi,
-				                                           sim->phi_dot,
-				                                           sim->k,
-				                                           sim->dz,
-				                                           sim->beta_f,
-				                                           sim->alpha,
-				                                           sim->mu_f,
-														   sim->D);
+				sim->p_f_dot_impl[i] = darcy_pressure_change_1d(i,
+				                                                sim->nz,
+				                                                sim->new_ghost,
+				                                                sim->phi,
+				                                                sim->phi_dot,
+				                                                sim->k,
+				                                                sim->dz,
+				                                                sim->beta_f,
+				                                                sim->alpha,
+				                                                sim->mu_f,
+														        sim->D);
 
 			for (i = 0; i < sim->nz - 1; ++i) {
-				sim->p_f_dot[i] = epsilon * p_f_dot_impl[i] + (1.0 - epsilon) * p_f_dot_expl[i];
-				p_f_ghost_new[i + 1] += sim->p_f_dot[i] * sim->dt;
-				r_norm[i] = fabs(residual(sim->p_f_dot[i], old_val[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]));
 			}
 
-			r_norm_max = max(r_norm, sim->nz);
+			r_norm_max = max(sim->p_f_dot_impl_r_norm, sim->nz);
 #ifdef DEBUG
 			puts(".. p_f_ghost_new:");
-			print_array(p_f_ghost_new, sim->nz + 2);
+			print_array(sim->new_ghost, sim->nz + 2);
 #endif
 
-			tmp = p_f_ghost_new;
-			p_f_ghost_new = sim->p_f_ghost;
+			tmp = sim->new_ghost;
+			sim->new_ghost = sim->p_f_ghost;
 			sim->p_f_ghost = tmp;
 #ifdef DEBUG
 			puts(".. p_f_ghost after update:");
-			print_array(p_f_ghost_new, sim->nz + 2);
+			print_array(sim->new_ghost, sim->nz + 2);
 #endif
 
 			if (r_norm_max <= rel_tol) {
 #ifdef DEBUG
-				printf(".. Solution converged after %d iterations\n", iter);
+				printf(".. Iterative solution converged after %d iterations\n", iter);
 #endif
 				solved = 1;
 				break;
 			}
 		}
-		free(p_f_dot_impl);
-		free(p_f_dot_expl);
-		free(p_f_ghost_new);
-		free(r_norm);
 		if (!solved) {
 			fprintf(stderr, "darcy_solver_1d: ");
 			fprintf(stderr, "Solution did not converge after %d iterations\n",
@@ -290,15 +285,21 @@ darcy_solver_1d(struct simulation *sim,
 			fprintf(stderr, ".. Residual normalized error: %f\n", r_norm_max);
 		}
 	} else {
-		for (i = 0; i < sim->nz; ++i)
-			sim->p_f_dot[i] = p_f_dot_expl[i];
 		solved = 1;
+	}
+
+	for (i = 0; i < sim->nz; ++i)
+		sim->p_f_dot[i] = epsilon * sim->p_f_dot_impl[i]
+		                  + (1.0 - epsilon) * sim->p_f_dot_expl[i];
+
 #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(p_f_dot_expl, sim->nz);
+		print_array(sim->p_f_dot_expl, sim->nz);
 #endif
-		free(p_f_dot_expl);
-	}
+
 	set_fluid_bcs(sim->p_f_ghost, sim, p_f_top);
 
 	return solved - 1;
diff --git a/simulation.c b/simulation.c
@@ -141,27 +141,33 @@ prepare_arrays(struct simulation *sim)
 	free(sim->phi);
 	free(sim->k);
 
-	sim->z = linspace(sim->origo_z,	     /* spatial coordinates */
+	sim->z = linspace(sim->origo_z,
 			  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->mu_c = zeros(sim->nz);          /* critical-state 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 */
-	sim->p_f_dot = zeros(sim->nz);       /* fluid pressure change */
-	sim->phi = zeros(sim->nz);           /* porosity */
-	sim->phi_c = zeros(sim->nz);         /* critical-state porosity */
-	sim->phi_dot = zeros(sim->nz);       /* rate of porosity change */
-	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_local = zeros(sim->nz);       /* local fluidity */
-	sim->g_ghost = zeros(sim->nz + 2);   /* fluidity with ghost nodes */
-	sim->I = zeros(sim->nz);             /* inertia number */
-	sim->tan_psi = zeros(sim->nz);       /* tan(dilatancy_angle) */
+	sim->dz = sim->z[1] - sim->z[0];
+	sim->mu = zeros(sim->nz);
+	sim->mu_c = zeros(sim->nz);
+	sim->sigma_n_eff = zeros(sim->nz);
+	sim->sigma_n = zeros(sim->nz);
+	sim->p_f_ghost = zeros(sim->nz + 2);
+	sim->p_f_dot = zeros(sim->nz);
+	sim->p_f_dot_expl = zeros(sim->nz);
+	sim->p_f_dot_impl = zeros(sim->nz);
+	sim->p_f_dot_impl_r_norm = zeros(sim->nz);
+	sim->phi = zeros(sim->nz);
+	sim->phi_c = zeros(sim->nz);
+	sim->phi_dot = zeros(sim->nz);
+	sim->k = zeros(sim->nz);
+	sim->xi = zeros(sim->nz);
+	sim->gamma_dot_p = zeros(sim->nz);
+	sim->v_x = zeros(sim->nz);
+	sim->g_local = zeros(sim->nz);
+	sim->g_ghost = zeros(sim->nz + 2);
+	sim->g_r_norm = zeros(sim->nz);
+	sim->I = zeros(sim->nz);
+	sim->tan_psi = zeros(sim->nz);
+	sim->old_val = empty(sim->nz);
+	sim->new_ghost = empty(sim->nz + 2);
 }
 
 void
@@ -174,6 +180,9 @@ free_arrays(struct simulation *sim)
 	free(sim->sigma_n);
 	free(sim->p_f_ghost);
 	free(sim->p_f_dot);
+	free(sim->p_f_dot_expl);
+	free(sim->p_f_dot_impl);
+	free(sim->p_f_dot_impl_r_norm);
 	free(sim->k);
 	free(sim->phi);
 	free(sim->phi_c);
@@ -183,8 +192,11 @@ free_arrays(struct simulation *sim)
 	free(sim->v_x);
 	free(sim->g_local);
 	free(sim->g_ghost);
+	free(sim->g_r_norm);
 	free(sim->I);
 	free(sim->tan_psi);
+	free(sim->old_val);
+	free(sim->new_ghost);
 }
 
 static void
@@ -642,11 +654,11 @@ implicit_1d_jacobian_poisson_solver(struct simulation *sim,
 {
 	int iter, i;
 	double r_norm_max = NAN;
-	double *tmp, *g_ghost_out = empty(sim->nz + 2), *r_norm = empty(sim->nz);
+	double *tmp;
 
 	for (iter = 0; iter < max_iter; ++iter) {
 #ifdef DEBUG
-		printf("\n@@@ ITERATION %d @@@\n", iter);
+		printf("\n@@@ %s: ITERATION %d @@@\n", __func__, iter);
 #endif
 		/* Dirichlet BCs resemble fixed particle velocities */
 		set_bc_dirichlet(sim->g_ghost, sim->nz, -1, 0.0);
@@ -659,31 +671,28 @@ implicit_1d_jacobian_poisson_solver(struct simulation *sim,
 			poisson_solver_1d_cell_update(i,
 			                              sim->g_ghost,
 			                              sim->g_local,
-			                              g_ghost_out,
-			                              r_norm,
+			                              sim->new_ghost,
+			                              sim->g_r_norm,
 			                              sim->dz,
 			                              sim->xi);
-		r_norm_max = max(r_norm, sim->nz);
+		r_norm_max = max(sim->g_r_norm, sim->nz);
 
-		tmp = g_ghost_out;
-		g_ghost_out = sim->g_ghost;
+		tmp = sim->new_ghost;
+		sim->new_ghost = sim->g_ghost;
 		sim->g_ghost = tmp;
 
 		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); */
+#ifdef DEBUG
+			printf(".. Solution converged after %d iterations\n", iter + 1);
+#endif
 			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, "Solution did not converge after %d iterations\n", iter + 1);
 	fprintf(stderr, ".. Residual normalized error: %f\n", r_norm_max);
 	return 1;
 }
@@ -753,24 +762,19 @@ temporal_increment(struct simulation *sim)
 
 int
 coupled_shear_solver(struct simulation *sim,
-		     const int max_iter,
-		     const double rel_tol)
+                     const int max_iter,
+                     const double rel_tol)
 {
 	int i, coupled_iter, stress_iter = 0;
-	double *r_norm, *old_val;
 	double r_norm_max, vel_res_norm = NAN, mu_wall_orig = sim->mu_wall;
 
-	if (sim->transient) {
-		r_norm = empty(sim->nz);
-		old_val = empty(sim->nz);
-	}
 	do {			/* stress iterations */
 
 		coupled_iter = 0;
 		do {		/* coupled iterations */
 
 			if (sim->transient) {
-				copy_values(sim->phi_dot, old_val, sim->nz);
+				copy_values(sim->phi_dot, sim->old_val, sim->nz);
 
 				/* step 1 */
 				compute_inertia_number(sim);	/* Eq. 1 */
@@ -828,14 +832,12 @@ coupled_shear_solver(struct simulation *sim,
 			/* stable porosity change field == coupled solution converged */
 			if (sim->transient) {
 				for (i = 0; i < sim->nz; ++i)
-					r_norm[i] = fabs(residual(sim->phi_dot[i], old_val[i]));
-				r_norm_max = max(r_norm, sim->nz);
+					sim->g_r_norm[i] = fabs(residual(sim->phi_dot[i], sim->old_val[i]));
+				r_norm_max = max(sim->g_r_norm, sim->nz);
 				if (r_norm_max <= rel_tol)
 					break;
 
 				if (coupled_iter++ >= max_iter) {
-					free(r_norm);
-					free(old_val);
 					fprintf(stderr, "coupled_shear_solver: ");
 					fprintf(stderr, "Transient solution did not converge "
 						"after %d iterations\n", coupled_iter);
@@ -872,11 +874,6 @@ coupled_shear_solver(struct simulation *sim,
 	if (!isnan(sim->v_x_limit))
 		sim->mu_wall = mu_wall_orig;
 
-	if (sim->transient) {
-		free(r_norm);
-		free(old_val);
-	}
-
 	temporal_increment(sim);
 
 	return 0;
diff --git a/simulation.h b/simulation.h
@@ -107,6 +107,9 @@ struct simulation {
 	double *sigma_n;      /* normal stress [Pa] */
 	double *p_f_ghost;    /* fluid pressure [Pa] */
 	double *p_f_dot;      /* fluid pressure change [Pa/s] */
+	double *p_f_dot_expl; /* fluid pressure change (explicit solution) [Pa/s] */
+	double *p_f_dot_impl; /* fluid pressure change (implicit solution) [Pa/s] */
+	double *p_f_dot_impl_r_norm; /* normalized residual fluid pressure change [-] */
 	double *k;            /* hydraulic permeability [m^2] */
 	double *phi;          /* porosity [-] */
 	double *phi_c;        /* critical-state porosity [-] */
@@ -116,8 +119,11 @@ struct simulation {
 	double *v_x;          /* shear velocity [m/s] */
 	double *g_local;      /* local fluidity */
 	double *g_ghost;      /* fluidity with ghost nodes */
+	double *g_r_norm;     /* normalized residual of fluidity field */
 	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 */
 };
 
 void init_sim(struct simulation *sim);