Skip to content

Commit a2457f5

Browse files
authored
Merge pull request geodynamics#2086 from MFraters/make_spd_function_parameter_available
Make SPD safety factor available as a parameter.
2 parents 659bb2a + c89f70f commit a2457f5

File tree

5 files changed

+39
-14
lines changed

5 files changed

+39
-14
lines changed

include/aspect/newton.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,11 @@ namespace aspect
186186
*/
187187
double get_maximum_linear_stokes_solver_tolerance();
188188

189+
/**
190+
* Get the SPD safety factor.
191+
*/
192+
double get_SPD_safety_factor() const;
193+
189194
/**
190195
* get a std::string describing the stabilization type used for the preconditioner.
191196
*/
@@ -220,6 +225,7 @@ namespace aspect
220225
unsigned int max_newton_line_search_iterations;
221226
bool use_newton_residual_scaling_method;
222227
double maximum_linear_stokes_solver_tolerance;
228+
double SPD_safety_factor;
223229
};
224230

225231
namespace Assemblers

include/aspect/utilities.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -989,7 +989,7 @@ namespace aspect
989989
double compute_spd_factor(const double eta,
990990
const SymmetricTensor<2,dim> &strain_rate,
991991
const SymmetricTensor<2,dim> &dviscosities_dstrain_rate,
992-
const double safety_factor);
992+
const double SPD_safety_factor);
993993

994994
/**
995995
* Converts an array of size dim to a Point of size dim.

source/simulator/assemblers/newton_stokes.cc

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -120,10 +120,10 @@ namespace aspect
120120
const SymmetricTensor<2,dim> strain_rate = scratch.material_model_inputs.strain_rate[q];
121121

122122
typename NewtonHandler<dim>::NewtonStabilization preconditioner_stabilization = this->get_newton_handler().get_preconditioner_stabilization();
123-
// todo: make this 0.9 into a global input parameter
123+
124124
// use the spd factor when the stabilization is PD or SPD
125125
const double alpha = (preconditioner_stabilization | NewtonHandler<dim>::NewtonStabilization::PD) != NewtonHandler<dim>::NewtonStabilization::none ?
126-
Utilities::compute_spd_factor<dim>(eta, strain_rate, viscosity_derivative_wrt_strain_rate, 0.9)
126+
Utilities::compute_spd_factor<dim>(eta, strain_rate, viscosity_derivative_wrt_strain_rate, this->get_newton_handler().get_SPD_safety_factor())
127127
:
128128
1;
129129

@@ -307,10 +307,10 @@ namespace aspect
307307
const SymmetricTensor<2,dim> viscosity_derivative_wrt_strain_rate = derivatives->viscosity_derivative_wrt_strain_rate[q];
308308
const double viscosity_derivative_wrt_pressure = derivatives->viscosity_derivative_wrt_pressure[q];
309309
typename NewtonHandler<dim>::NewtonStabilization velocity_block_stabilization = this->get_newton_handler().get_velocity_block_stabilization();
310-
// todo: make this 0.9 into a global input parameter
310+
311311
// use the spd factor when the stabilization is PD or SPD
312312
const double alpha = (velocity_block_stabilization | NewtonHandler<dim>::NewtonStabilization::PD) != NewtonHandler<dim>::NewtonStabilization::none ?
313-
Utilities::compute_spd_factor<dim>(eta, strain_rate, viscosity_derivative_wrt_strain_rate, 0.9)
313+
Utilities::compute_spd_factor<dim>(eta, strain_rate, viscosity_derivative_wrt_strain_rate, this->get_newton_handler().get_SPD_safety_factor())
314314
:
315315
1;
316316

source/simulator/newton.cc

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,14 @@ namespace aspect
244244
return maximum_linear_stokes_solver_tolerance;
245245
}
246246

247+
template <int dim>
248+
double
249+
NewtonHandler<dim>::
250+
get_SPD_safety_factor() const
251+
{
252+
return SPD_safety_factor;
253+
}
254+
247255
template <int dim>
248256
std::string
249257
NewtonHandler<dim>::
@@ -331,6 +339,18 @@ namespace aspect
331339
"When this parameter is true and the linear solver fails, we try again, but now with SPD stabilization "
332340
"for both the preconditioner and the velocity block. The SPD stabilization will remain active untill "
333341
"the next timestep, when the default values are restored.");
342+
343+
344+
prm.declare_entry ("SPD safety factor", "0.9",
345+
Patterns::Double (0,1),
346+
"When stabilizing the Newton matrix, we can encounter situations where the coefficient inside the elliptic (top-left) "
347+
"block becomes negative or zero. This coefficient has the form $1+x$ where $x$ can sometimes be smaller than $-1$. In "
348+
"this case, the top-left block of the matrix is no longer positive definite, and both preconditioners and iterative "
349+
"solvers may fail. To prevent this, the stabilization computes an $\alpha$ so that $1+\alpha x$ is never negative. "
350+
"This $\alpha$ is chosen as $1$ if $x\ge -1$, and $\alpha=-\frac 1x$ otherwise. (Note that this always leads to "
351+
"$0\le \alpha \le 1$.) On the other hand, we also want to stay away from $1+\alpha x=0$, and so modify the choice of "
352+
"$\alpha$ to be $1$ if $x\ge -c$, and $\alpha=-\frac cx$ with a $c$ between zero and one. This way, if $c<1$, we are "
353+
"assured that $1-\alpha x>c$, i.e., bounded away from zero.");
334354
}
335355
prm.leave_subsection ();
336356
}
@@ -375,6 +395,9 @@ namespace aspect
375395

376396
AssertThrow((!DEAL_II_VERSION_GTE(9,0,0) && !use_Newton_failsafe) || DEAL_II_VERSION_GTE(9,0,0),
377397
ExcMessage("The failsafe option can't be used with a deal.ii less then 9.0.0."));
398+
399+
SPD_safety_factor = prm.get_double("SPD safety factor");
400+
378401
}
379402
prm.leave_subsection ();
380403
}

source/utilities.cc

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2406,7 +2406,7 @@ namespace aspect
24062406
double compute_spd_factor(const double eta,
24072407
const SymmetricTensor<2,dim> &strain_rate,
24082408
const SymmetricTensor<2,dim> &dviscosities_dstrain_rate,
2409-
const double safety_factor)
2409+
const double SPD_safety_factor)
24102410
{
24112411
// if the strain rate is zero, or the derivative is zero, then
24122412
// the exact choice of alpha factor does not matter because the
@@ -2420,16 +2420,12 @@ namespace aspect
24202420
const double one_minus_part = 1 - (contract_a_b / norm_a_b);
24212421
const double denom = one_minus_part * one_minus_part * norm_a_b;
24222422

2423-
if (denom == 0)
2423+
// the case denom == 0 (smallest eigenvalue is zero), should return one,
2424+
// and it does here, because C_safety * 2.0 * eta is always larger then zero.
2425+
if (denom <= SPD_safety_factor * 2.0 * eta)
24242426
return 1.0;
24252427
else
2426-
{
2427-
const double alpha = (2.0*eta)/denom;
2428-
if (alpha >= 1.0)
2429-
return 1.0;
2430-
else
2431-
return std::max(0.0,safety_factor*alpha);
2432-
}
2428+
return std::max(0.0, SPD_safety_factor * ((2.0 * eta) / denom));
24332429
}
24342430

24352431

0 commit comments

Comments
 (0)