Peano
FrictionLaws.py
Go to the documentation of this file.
1 # This file is part of the ExaHyPE2 project. For conditions of distribution and
2 # use, please see the copyright notice at www.peano-framework.org
3 
4 friction_coefficients = r"""
5  const double Zeta = 35.0 * tarch::la::PI / 180.0; // Conversion of degrees to radians
6  const double Zeta1 = 28.95 * tarch::la::PI / 180.0;
7  const double Zeta2 = 44.09 * tarch::la::PI / 180.0;
8  const double Zeta3 = 31.81 * tarch::la::PI / 180.0;
9 
10  const double Mu1 = std::tan(Zeta1);
11  const double Mu2 = std::tan(Zeta2);
12  const double Mu3 = std::tan(Zeta3);
13 
14  constexpr double Beta = 1.07;
15  constexpr double Gamma = 2.01;
16  constexpr double BetaStar = 0.06;
17  // Kappa in the friction law is assumed to be 1 and is just initialised as a
18  // const double here using Kappa. The user can apply std::pow((Fr/BetaStar),
19  // Kappa) for evaluating T here in case the value of Kappa is different
20  // from 1.
21 
22  constexpr double Kappa = 1.0;
23  constexpr double FrictionLengthScale = 0.00035;
24 
25  const double Nu = (2.0 / 9.0) * (FrictionLengthScale / Beta) * (GRAV * std::sin(Zeta) / std::sqrt(GRAV * std::cos(Zeta))) * (((Mu2 - Mu1) / (std::tan(Zeta) - Mu1)) - 1.0);
26  const double Hstart = FrictionLengthScale * (((Mu2 - Mu1) / (std::tan(Zeta) - Mu3)) - 1.0);
27  const double Hstop = FrictionLengthScale * (((Mu2 - Mu1) / (std::tan(Zeta) - Mu1)) - 1.0);
28 """
29 
30 max_eigenvalue = friction_coefficients + r"""
31  double result{0.0};
32 
33  if (tarch::la::greater(Q[Shortcuts::h], 0.0)) {
34  const double u = Q[Shortcuts::hu + normal] / Q[Shortcuts::h];
35  const double c = std::sqrt(GRAV * std::cos(Zeta) * Q[Shortcuts::h]);
36  result = std::fmax(std::fabs(u - c), std::fabs(u + c));
37  }
38 
39  return result;
40 """
41 
42 flux = friction_coefficients + r"""
43  if (tarch::la::greater(Q[Shortcuts::h], 0.0)) {
44  const double ih = 1.0 / Q[Shortcuts::h];
45  F[Shortcuts::h] = Q[Shortcuts::hu + normal];
46  switch (normal) {
47  case 0:
48  F[Shortcuts::hu] = ih * Q[Shortcuts::hu] * Q[Shortcuts::hu] + 0.5 * GRAV * std::cos(Zeta) * Q[Shortcuts::h] * Q[Shortcuts::h];
49  F[Shortcuts::hv] = ih * Q[Shortcuts::hu] * Q[Shortcuts::hv];
50  break;
51  case 1:
52  F[Shortcuts::hu] = ih * Q[Shortcuts::hv] * Q[Shortcuts::hu];
53  F[Shortcuts::hv] = ih * Q[Shortcuts::hv] * Q[Shortcuts::hv] + 0.5 * GRAV * std::cos(Zeta) * Q[Shortcuts::h] * Q[Shortcuts::h];
54  break;
55  }
56  } else {
57  F[Shortcuts::h] = 0.0;
58  F[Shortcuts::hu] = 0.0;
59  F[Shortcuts::hv] = 0.0;
60  }
61 """
62 
63 nonconservative_product = friction_coefficients + r"""
64  BTimesDeltaQ[Shortcuts::h] = 0.0;
65  BTimesDeltaQ[Shortcuts::hu] = 0.0;
66  BTimesDeltaQ[Shortcuts::hv] = 0.0;
67  BTimesDeltaQ[Shortcuts::b] = 0.0;
68 
69  const double hx = (Q[Shortcuts::hx] - 0.5 * deltaQ[Shortcuts::hx]) / (1.0 * h(0));
70  const double hy = (Q[Shortcuts::hy] - 0.5 * deltaQ[Shortcuts::hy]) / (1.0 * h(1));
71 
72  // u
73  const double ux = (Q[Shortcuts::ux] - 0.5 * deltaQ[Shortcuts::ux]) / (1.0 * h(0));
74  const double uy = (Q[Shortcuts::uy] - 0.5 * deltaQ[Shortcuts::uy]) / (1.0 * h(1));
75  const double uxx = (Q[Shortcuts::uxx] - 0.5 * deltaQ[Shortcuts::uxx]) / (h(0) * h(0));
76  const double uyy = (Q[Shortcuts::uyy] - 0.5 * deltaQ[Shortcuts::uyy]) / (h(1) * h(1));
77  const double uxy = (Q[Shortcuts::uxy] - 0.5 * deltaQ[Shortcuts::uxy]) / (4.0 * h(0) * h(1));
78 
79  // v
80  const double vx = (Q[Shortcuts::vx] - 0.5 * deltaQ[Shortcuts::vx]) / (1.0 * h(0));
81  const double vy = (Q[Shortcuts::vy] - 0.5 * deltaQ[Shortcuts::vy]) / (1.0 * h(1));
82  const double vxx = (Q[Shortcuts::vxx] - 0.5 * deltaQ[Shortcuts::vxx]) / (h(0) * h(0));
83  const double vyy = (Q[Shortcuts::vyy] - 0.5 * deltaQ[Shortcuts::vyy]) / (h(1) * h(1));
84  const double vxy = (Q[Shortcuts::vxy] - 0.5 * deltaQ[Shortcuts::vxy]) / (4.0 * h(0) * h(1));
85 
86  switch (normal) {
87  case 0: // x
88  BTimesDeltaQ[Shortcuts::hu] = -(h(0) * Nu * std::sqrt(Q[Shortcuts::h]) * (1.5 * hx * ux + Q[Shortcuts::h] * uxx));
89  BTimesDeltaQ[Shortcuts::hv] = -(h(0) * 0.5 * Nu * std::sqrt(Q[Shortcuts::h]) * (1.5 * hx * (uy + vx) + Q[Shortcuts::h] * (uxy + vxx)));
90  break;
91  case 1: // y
92  BTimesDeltaQ[Shortcuts::hu] = -(h(1) * 0.5 * Nu * std::sqrt(Q[Shortcuts::h]) * (1.5 * hy * (uy + vx) + Q[Shortcuts::h] * (uyy + vxy)));
93  BTimesDeltaQ[Shortcuts::hv] = -(h(1) * Nu * std::sqrt(Q[Shortcuts::h]) * (1.5 * hy * vy + Q[Shortcuts::h] * vyy));
94  break;
95  }
96 """
97 
98 coulomb_friction = friction_coefficients + r"""
99  S[Shortcuts::h] = 0.0;
100  S[Shortcuts::hu] = 0.0;
101  S[Shortcuts::hv] = 0.0;
102 
103  if (tarch::la::greater(Q[Shortcuts::h], 0.0)) {
104  const double u{Q[Shortcuts::hu + 0] / Q[Shortcuts::h]};
105  const double v{Q[Shortcuts::hu + 1] / Q[Shortcuts::h]};
106  const double velMagnitudeSqr{u * u + v * v};
107  if (tarch::la::greater(velMagnitudeSqr, 0.0)) {
108  const double zx{Q[Shortcuts::bx] / h(0)};
109  const double zy{Q[Shortcuts::by] / h(1)};
110  const double c{1.0 / std::sqrt(1.0 + zx * zx + zy * zy)};
111  const double friction{-GRAV * (Mu1 * Q[Shortcuts::h] * c)};
112  const double velMagnitude{std::sqrt(velMagnitudeSqr)};
113  S[Shortcuts::hu] += u / velMagnitude * friction;
114  S[Shortcuts::hv] += v / velMagnitude * friction;
115  }
116  }
117 """
118 
119 material_dependent_basal_friction = friction_coefficients + r"""
120  if (tarch::la::greater(Q[Shortcuts::h], 0.0)) {
121  const double ih = 1.0 / Q[Shortcuts::h];
122  const double u = ih * Q[Shortcuts::hu];
123  const double v = ih * Q[Shortcuts::hv];
124  const double ubar = std::sqrt(Q[Shortcuts::hu] * Q[Shortcuts::hu] + Q[Shortcuts::hv] * Q[Shortcuts::hv]) * ih;
125  const double Fr = ubar / std::sqrt(GRAV * Q[Shortcuts::h] * std::cos(Zeta));
126  const double Hstar = (BetaStar + Gamma) * Hstop / Beta;
127 
128  double Mu = 1.0;
129  if (Fr > BetaStar) {
130  const double vstop = (Q[Shortcuts::h] * Beta) / (Fr + Gamma);
131  const double Mustop = Mu1 + (Mu1 - Mu2) / (1.0 + vstop / FrictionLengthScale);
132  Mu = Mustop;
133  } else if (Fr > 0.0 && Fr <= BetaStar) {
134  const double vstart = Q[Shortcuts::h];
135  const double vstop = Q[Shortcuts::h] * Beta / (BetaStar + Gamma);
136  const double Mustart = Mu3 + (Mu1 - Mu2) / (1.0 + vstart / FrictionLengthScale);
137  const double Mustop = Mu1 + (Mu1 - Mu2) / (1.0 + vstop / FrictionLengthScale);
138  const double T = Mustart + (Mustop - Mustart) * std::pow((Fr / BetaStar), Kappa);
139  Mu = T;
140  } else if (tarch::la::equals(Fr, 0.0)) {
141  const double vstart = Q[Shortcuts::h];
142  const double Mustart = Mu3 + (Mu1 - Mu2) / (1.0 + vstart / FrictionLengthScale);
143  Mu = Mustart;
144  }
145 
146  if (tarch::la::equals(ubar, 0.0)) {
147  const double hx = Q[Shortcuts::hx] / h(0);
148  const double hy = Q[Shortcuts::hy] / h(1);
149  const tarch::la::Vector<DIMENSIONS, double> frictionVector = {std::tan(Zeta) - hx, -hy};
150  const double frictionVectorMagnitude = tarch::la::norm2(frictionVector);
151  if (tarch::la::greater(Mu, frictionVectorMagnitude)) {
152  Mu = frictionVectorMagnitude;
153  }
154 
155  if (tarch::la::equals(Mu, 0.0)) {
156  S[Shortcuts::h] = 0.0;
157  S[Shortcuts::hu] = Q[Shortcuts::h] * GRAV * std::sin(Zeta);
158  S[Shortcuts::hv] = 0.0;
159  } else {
160  S[Shortcuts::h] = 0.0;
161  S[Shortcuts::hu] = Q[Shortcuts::h] * GRAV * std::sin(Zeta) - Mu * (frictionVector(0) / frictionVectorMagnitude) * Q[Shortcuts::h] * GRAV * std::cos(Zeta);
162  S[Shortcuts::hv] = -Mu * (frictionVector(1) / frictionVectorMagnitude) * Q[Shortcuts::h] * GRAV * std::cos(Zeta);
163  }
164  } else if (tarch::la::greater(ubar, 0.0)) {
165  S[Shortcuts::h] = 0.0;
166  S[Shortcuts::hu] = Q[Shortcuts::h] * GRAV * std::sin(Zeta) - Mu * (u / ubar) * Q[Shortcuts::h] * GRAV * std::cos(Zeta);
167  S[Shortcuts::hv] = -Mu * (v / ubar) * Q[Shortcuts::h] * GRAV * std::cos(Zeta);
168  }
169  } else {
170  S[Shortcuts::h] = 0.0;
171  S[Shortcuts::hu] = 0.0;
172  S[Shortcuts::hv] = 0.0;
173  }
174 """