Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

generalize the SPD factor #5754

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 3 additions & 7 deletions include/aspect/utilities.h
Original file line number Diff line number Diff line change
Expand Up @@ -841,17 +841,13 @@ namespace aspect
* this in the Newton paper (Fraters et al., Geophysical Journal
* International, 2019) where we derived a factor of
* $\frac{2\eta(\varepsilon(\mathbf u))}{\left[1-\frac{b:a}{\|a\| \|b\|} \right]^2\|a\|\|b\|}$,
* which we reset to a maximum of one, and if it is smaller then one,
* which we reset to a maximum of one, and if it is smaller than one,
* a safety_factor scales the value to make sure that 1-alpha won't get to
* close to zero. However, as later pointed out by Yimin Jin, the computation
* is wrong, see https://github.com/geodynamics/aspect/issues/5555. Instead,
* the function now computes the factor as
* $(2 \eta) / (a:b + b:a)$, again capped at a maximal value of 1,
* and using a safety factor from below.
*
* In practice, $a$ and $b$ are almost always parallel to each other,
* and $a:b + b:a = 2a:b$, in which case one can drop the factor
* of $2$ everywhere in the computations.
* $\frac{2\eta(\varepsilon(\mathbf u))}{\left[1-\frac{b:a}{\|a\| \|b\|} \right]\|a\|\|b\|}$,
* again capped at a maximal value of 1, and using a safety factor from below.
*/
template <int dim>
double compute_spd_factor(const double eta,
Expand Down
23 changes: 10 additions & 13 deletions source/utilities.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2546,28 +2546,25 @@ namespace aspect

// The factor in the Newton matrix is going to be of the form
// 2*eta I + (a \otimes b + b \otimes a)
// where a=strain_rate and b=dviscosities_dstrain_rate.
//
// If a,b are parallel, this simplifies to
// [2*eta + 2 a:b] I = 2 [eta + a:b] I
// where a=strain_rate and b=dviscosities_dstrain_rate,
// and we need to make sure that
// [eta + alpha a:b] > (1-safety_factor)*eta
// eta + alpha (a:b - |a||b|) / 2 >= (1-safety_factor)*eta
// by choosing alpha appropriately.

// So, first check: If
// [eta + a:b] > (1-safety_factor)*eta
// alpha (|a||b| - a:b) <= 2*safety_factor*eta
// is already satisfied, then we can choose alpha=1
const double a_colon_b = strain_rate * dviscosities_dstrain_rate;
if (eta + a_colon_b > eta * (1. - SPD_safety_factor))
const double norm_a_b = std::sqrt((strain_rate * strain_rate) * (dviscosities_dstrain_rate * dviscosities_dstrain_rate));
const double contract_a_b = strain_rate * dviscosities_dstrain_rate;
const double denominator = norm_a_b - contract_a_b;

if (denominator <= 2.0 * SPD_safety_factor * eta)
return 1.0;
else
{
// Otherwise solve the equation above for alpha, which yields
// a:b = -safety_factor*eta / a:b
// This can only ever happen if a:b < 0, so we get
// a:b = safety_factor * abs(eta / a:b)
Assert (a_colon_b < 0, ExcInternalError());
return SPD_safety_factor * std::abs(eta / a_colon_b);
// alpha = 2*safety_factor*eta / (|a||b| - a:b)
return 2.0 * SPD_safety_factor * eta / denominator;
}
}

Expand Down
Loading