www.mooseframework.org
RichardsSUPGstandard.C
Go to the documentation of this file.
1 //* This file is part of the MOOSE framework
2 //* https://www.mooseframework.org
3 //*
4 //* All rights reserved, see COPYRIGHT for full restrictions
5 //* https://github.com/idaholab/moose/blob/master/COPYRIGHT
6 //*
7 //* Licensed under LGPL 2.1, please see LICENSE for details
8 //* https://www.gnu.org/licenses/lgpl-2.1.html
9 
10 #include "RichardsSUPGstandard.h"
11 #include "libmesh/utility.h"
12 
14 
17 {
20  "p_SUPG",
21  "p_SUPG > 0",
22  "SUPG pressure. This parameter controls the strength of the "
23  "upwinding. This parameter must be positive. If you need to track "
24  "advancing fronts in a problem, then set to less than your expected "
25  "range of pressures in your unsaturated zone. Otherwise, set "
26  "larger, and then minimal upwinding will occur and convergence will "
27  "typically be good. If you need no SUPG, it is more efficient not "
28  "to use this UserObject.");
29  params.addClassDescription(
30  "Standard SUPG relationships for Richards flow based on Appendix A of TJR Hughes, M "
31  "Mallet and A Mizukami ``A new finite element formulation for computational fluid dynamics:: "
32  "II. Behond SUPG'' Computer Methods in Applied Mechanics and Engineering 54 (1986) 341--355");
33  return params;
34 }
35 
37  : RichardsSUPG(parameters), _p_SUPG(getParam<Real>("p_SUPG"))
38 {
39 }
40 
43  RealVectorValue gradp,
44  Real density,
45  RealVectorValue gravity) const
46 {
47  return -perm * (gradp - density * gravity); // points in direction of info propagation
48 }
49 
52 {
53  return -perm;
54 }
55 
58  Real density_prime,
59  RealVectorValue gravity) const
60 {
61  return perm * density_prime * gravity;
62 }
63 
64 Real
66 {
67  if (alpha >= 5.0 || alpha <= -5.0)
68  return ((alpha > 0.0) ? 1.0 : -1.0) - 1.0 / alpha; // prevents overflows
69  else if (alpha == 0)
70  return 0.0;
71  return 1.0 / std::tanh(alpha) - 1.0 / alpha;
72 }
73 
74 Real
76 {
77  if (alpha >= 5.0 || alpha <= -5.0)
78  return 1.0 / (alpha * alpha); // prevents overflows
79  else if (alpha == 0)
80  return 1.0 / 3.0;
81  return 1.0 - Utility::pow<2>(std::cosh(alpha) / std::sinh(alpha)) + 1.0 / (alpha * alpha);
82 }
83 
84 // the following is physically 2*velocity/element_length
87  int dimen,
88  RealVectorValue xi_prime,
89  RealVectorValue eta_prime,
90  RealVectorValue zeta_prime) const
91 {
93  b(0) = xi_prime * vel;
94  if (dimen >= 2)
95  b(1) = eta_prime * vel;
96  if (dimen == 3)
97  b(2) = zeta_prime * vel;
98  return b;
99 }
100 
101 // following is d(bb*bb)/d(gradp)
104  RealTensorValue dvel_dgradp,
105  RealVectorValue xi_prime,
106  RealVectorValue eta_prime,
107  RealVectorValue zeta_prime) const
108 {
109  // if dvel_dgradp is symmetric so transpose is probably a waste of time
110  return 2.0 * ((xi_prime * vel) * (dvel_dgradp.transpose() * xi_prime) +
111  (eta_prime * vel) * (dvel_dgradp.transpose() * eta_prime) +
112  (zeta_prime * vel) * (dvel_dgradp.transpose() * zeta_prime));
113 }
114 
115 // following is d(bb*bb)/d(p)
116 Real
118  RealVectorValue dvel_dp,
119  RealVectorValue xi_prime,
120  RealVectorValue eta_prime,
121  RealVectorValue zeta_prime) const
122 {
123  return 2.0 *
124  ((xi_prime * vel) * (dvel_dp * xi_prime) + (eta_prime * vel) * (dvel_dp * eta_prime) +
125  (zeta_prime * vel) * (dvel_dp * zeta_prime));
126 }
127 
128 Real
130 {
131  // vel = velocity, b = bb
132  Real norm_v = vel.norm();
133  Real norm_b = b.norm(); // Hughes et al investigate infinity-norm and 2-norm. i just use 2-norm
134  // here. norm_b ~ 2|a|/ele_length_in_direction_of_a
135 
136  if (norm_b == 0)
137  return 0.0; // Only way for norm_b=0 is for zero ele size, or vel=0. Either way we don't have
138  // to upwind.
139 
140  Real h = 2.0 * norm_v / norm_b; // h is a measure of the element length in the "a" direction
141  Real alpha = 0.5 * norm_v * h / (traceperm * _p_SUPG); // this is the Peclet number
142 
144 
145  return xi_tilde / norm_b;
146 }
147 
150  RealTensorValue dvel_dgradp,
151  Real traceperm,
153  RealVectorValue db2_dgradp) const
154 {
155  Real norm_vel = vel.norm();
156  if (norm_vel == 0)
157  return RealVectorValue();
158 
159  RealVectorValue norm_vel_dgradp(dvel_dgradp * vel / norm_vel);
160 
161  Real norm_b = b.norm();
162  if (norm_b == 0)
163  return RealVectorValue();
164  RealVectorValue norm_b_dgradp = db2_dgradp / 2.0 / norm_b;
165 
166  Real h = 2 * norm_vel / norm_b; // h is a measure of the element length in the "a" direction
167  RealVectorValue h_dgradp(2 * norm_vel_dgradp / norm_b -
168  2.0 * norm_vel * norm_b_dgradp / norm_b / norm_b);
169 
170  Real alpha = 0.5 * norm_vel * h / traceperm / _p_SUPG; // this is the Peclet number
171  RealVectorValue alpha_dgradp =
172  0.5 * (norm_vel_dgradp * h + norm_vel * h_dgradp) / traceperm / _p_SUPG;
173 
176  RealVectorValue xi_tilde_dgradp = xi_tilde_prime * alpha_dgradp;
177 
178  RealVectorValue tau_dgradp =
179  xi_tilde_dgradp / norm_b - xi_tilde * norm_b_dgradp / (norm_b * norm_b);
180 
181  return tau_dgradp;
182 }
183 
184 Real
186  RealVectorValue dvel_dp,
187  Real traceperm,
189  Real db2_dp) const
190 {
191  Real norm_vel = vel.norm();
192  if (norm_vel == 0.0)
193  return 0.0; // this deriv is not necessarily correct, but i can't see a better thing to do
194 
195  Real norm_vel_dp = dvel_dp * vel / norm_vel;
196 
197  Real norm_b = b.norm();
198  if (norm_b == 0)
199  return 0.0; // this deriv is not necessarily correct, but i can't see a better thing to do
200  Real norm_b_dp = db2_dp / (2.0 * norm_b);
201 
202  Real h = 2.0 * norm_vel / norm_b; // h is a measure of the element length in the "a" direction
203  Real h_dp = 2.0 * norm_vel_dp / norm_b - 2.0 * norm_vel * norm_b_dp / (norm_b * norm_b);
204 
205  Real alpha = 0.5 * norm_vel * h / (traceperm * _p_SUPG); // this is the Peclet number
206  Real alpha_dp = 0.5 * (norm_vel_dp * h + norm_vel * h_dp) / (traceperm * _p_SUPG);
207 
210  Real xi_tilde_dp = xi_tilde_prime * alpha_dp;
211 
212  // Real tau = xi_tilde/norm_b;
213  const Real tau_dp = xi_tilde_dp / norm_b - xi_tilde * norm_b_dp / (norm_b * norm_b);
214 
215  return tau_dp;
216 }
217 
218 bool
220 {
221  return false;
222 }
static InputParameters validParams()
Definition: RichardsSUPG.C:15
void addRequiredRangeCheckedParam(const std::string &name, const std::string &parsed_function, const std::string &doc_string)
auto norm() const -> decltype(std::norm(Real()))
RichardsSUPGstandard(const InputParameters &parameters)
static InputParameters validParams()
Real _p_SUPG
the SUPG pressure parameter This dictates how strong the SUPG is _p_SUPG large means only a little SU...
static const std::string density
Definition: NS.h:33
Real tauSUPG(RealVectorValue vel, Real traceperm, RealVectorValue b) const
The SUPG tau parameter.
RealVectorValue velSUPG(RealTensorValue perm, RealVectorValue gradp, Real density, RealVectorValue gravity) const
SUPG velocity = -perm*(gradp - density*gravity) This points in direction of information propagation...
bool SUPG_trivial() const
returns false in this case since everything is trivial
TensorValue< Real > RealTensorValue
Real dtauSUPG_dp(RealVectorValue vel, RealVectorValue dvel_dp, Real traceperm, RealVectorValue b, Real db2_dp) const
derivative of tau wrt porepressure (keeping gradp fixed)
RealVectorValue bb(RealVectorValue vel, int dimen, RealVectorValue xi_prime, RealVectorValue eta_prime, RealVectorValue zeta_prime) const
|bb| ~ 2*velocity/element_length
base class for SUPG of the Richards equation You must override all the functions below with your spec...
Definition: RichardsSUPG.h:20
Real cosh_relation_prime(Real alpha) const
derivative of cosh_relation wrt alpha
standard SUPG relationships valid for the Richards equation.
RealVectorValue dvelSUPG_dp(RealTensorValue perm, Real density_prime, RealVectorValue gravity) const
derivative of SUPG velocity wrt porepressure (keeping gradp fixed)
RealVectorValue dbb2_dgradp(RealVectorValue vel, RealTensorValue dvel_dgradp, RealVectorValue xi_prime, RealVectorValue eta_prime, RealVectorValue zeta_prime) const
derivative of bb*bb wrt gradient of porepressure
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
static const std::string alpha
Definition: NS.h:126
void addClassDescription(const std::string &doc_string)
RealTensorValue dvelSUPG_dgradp(RealTensorValue perm) const
derivative of SUPG velocity wrt gradient of porepressure
Real dbb2_dp(RealVectorValue vel, RealVectorValue dvel_dp, RealVectorValue xi_prime, RealVectorValue eta_prime, RealVectorValue zeta_prime) const
derivative of bb*bb wrt porepressure
RealVectorValue dtauSUPG_dgradp(RealVectorValue vel, RealTensorValue dvel_dgradp, Real traceperm, RealVectorValue b, RealVectorValue db2_dgradp) const
derivative of tau wrt gradient of porepressure
Real cosh_relation(Real alpha) const
cosh(alpha)/sinh(alpha) - 1/alpha, modified at extreme values of alpha to prevent overflows ...
registerMooseObject("RichardsApp", RichardsSUPGstandard)