Amandus: Simulations based on multilevel Schwarz methods
darcy/checkerboard/solution.h
Go to the documentation of this file.
1 /**********************************************************************
2  * Copyright (C) 2011 - 2014 by the authors
3  * Distributed under the MIT License
4  *
5  * See the files AUTHORS and LICENSE in the project root directory
6  **********************************************************************/
7 #ifndef __darcy_checkerboard_solution
8 #define __darcy_checkerboard_solution
9 
10 #include <deal.II/base/function.h>
11 #include <deal.II/base/tensor_function.h>
12 
13 #include <amandus/darcy/checkerboard/solution_parameters.h>
14 
15 #include <cmath>
16 #include <utility>
17 
18 namespace Darcy
19 {
20 namespace Checkerboard
21 {
22 using namespace dealii;
23 
24 inline std::pair<double, double>
25 polar_coords(const Point<2>& p)
26 {
27  double theta = std::atan2(p[1], p[0]);
28  if (theta < 0.0)
29  {
30  theta += 2 * numbers::PI;
31  }
32  return std::pair<double, double>(hypot(p[0], p[1]), theta);
33 }
34 
39 class CheckerboardTensorFunction : public TensorFunction<2, 2>
40 {
41 public:
42  typedef typename TensorFunction<2, 2>::value_type value_type;
43  CheckerboardTensorFunction(const std::vector<double>& parameters);
45 
46  virtual value_type value(const Point<2>& p) const;
47 
48  CheckerboardTensorFunction& inverse();
49 
50 private:
51  CheckerboardTensorFunction(CheckerboardTensorFunction* parent, bool nocopyconstructor);
52  std::vector<double> parameters;
54  bool is_inverse;
55 };
56 
57 CheckerboardTensorFunction::CheckerboardTensorFunction(const std::vector<double>& parameters)
58  : parameters(parameters)
59  , is_inverse(false)
60 {
61  inverse_ptr = new CheckerboardTensorFunction(this, true);
62 }
63 
65  bool /*nocopyconstructor*/)
66  : parameters(4)
67  , is_inverse(true)
68 {
69  inverse_ptr = parent;
70  for (unsigned int i = 0; i < 4; ++i)
71  {
72  parameters[i] = 1.0 / parent->parameters[i];
73  }
74 }
75 
77 {
78  if (!is_inverse)
79  {
80  delete inverse_ptr;
81  }
82 }
83 
86 {
87  return *inverse_ptr;
88 }
89 
91 CheckerboardTensorFunction::value(const Point<2>& p) const
92 {
93  Tensor<2, 2> identity;
94  for (unsigned int i = 0; i < 2; ++i)
95  {
96  identity[i][i] = 1.0;
97  }
98  unsigned int quadrant;
99  if (p(1) > 0.0)
100  {
101  if (p(0) > 0.0)
102  {
103  quadrant = 1;
104  }
105  else
106  {
107  quadrant = 2;
108  }
109  }
110  else
111  {
112  if (p(0) > 0.0)
113  {
114  quadrant = 4;
115  }
116  else
117  {
118  quadrant = 3;
119  }
120  }
121 
122  return parameters[quadrant - 1] * identity;
123 }
124 
130 class ScalarSolution : public Function<2>
131 {
132 public:
133  ScalarSolution(const std::vector<double>& parameters);
134 
135  virtual double value(const Point<2>& p, const unsigned int component = 0) const;
136  virtual Tensor<1, 2> gradient(const Point<2>& p, const unsigned int component = 0) const;
137 
138 private:
139  double mu(double theta) const;
140  double dmu(double theta) const;
141 
143 };
144 
145 ScalarSolution::ScalarSolution(const std::vector<double>& parameters)
146  : solution_parameters(parameters)
147 {
148 }
149 
150 double
151 ScalarSolution::mu(double theta) const
152 {
153  double gamma = solution_parameters.parameters[0];
154  double sigma = solution_parameters.parameters[1];
155  double rho = solution_parameters.parameters[2];
156 
157  if (0 <= theta && theta <= numbers::PI / 2.0)
158  {
159  // first quadrant
160  return (std::cos((numbers::PI / 2.0 - sigma) * gamma) *
161  std::cos((theta - numbers::PI / 2.0 + rho) * gamma));
162  }
163  else if (3 * numbers::PI / 2.0 <= theta && theta < 2 * numbers::PI)
164  {
165  // fourth quadrant
166  return (std::cos((numbers::PI / 2.0 - rho) * gamma) *
167  std::cos((theta - 3.0 * numbers::PI / 2.0 - sigma) * gamma));
168  }
169  else if (numbers::PI / 2.0 < theta && theta <= numbers::PI)
170  {
171  // second quadrant
172  return std::cos(rho * gamma) * std::cos((theta - numbers::PI + sigma) * gamma);
173  }
174  else if (numbers::PI < theta && theta < 3 * numbers::PI / 2.0)
175  {
176  // third quadrant
177  return std::cos(sigma * gamma) * std::cos((theta - numbers::PI - rho) * gamma);
178  }
179 
180  Assert(false, ExcInternalError());
181  return 0.0;
182 }
183 
184 double
185 ScalarSolution::dmu(double theta) const
186 {
187  double gamma = solution_parameters.parameters[0];
188  double sigma = solution_parameters.parameters[1];
189  double rho = solution_parameters.parameters[2];
190 
191  if (0 <= theta && theta <= numbers::PI / 2.0)
192  {
193  // first quadrant
194  return (-1.0) * gamma * std::cos((numbers::PI / 2.0 - sigma) * gamma) *
195  std::sin((theta - numbers::PI / 2.0 + rho) * gamma);
196  }
197  else if (3 * numbers::PI / 2.0 <= theta && theta < 2 * numbers::PI)
198  {
199  // fourth quadrant
200  return ((-1.0) * gamma * std::cos((numbers::PI / 2.0 - rho) * gamma) *
201  std::sin((theta - 3.0 * numbers::PI / 2.0 - sigma) * gamma));
202  }
203  else if (numbers::PI / 2.0 < theta && theta <= numbers::PI)
204  {
205  // second quadrant
206  return (-1.0) * gamma * std::cos(rho * gamma) * std::sin((theta - numbers::PI + sigma) * gamma);
207  }
208  else if (numbers::PI < theta && theta < 3 * numbers::PI / 2.0)
209  {
210  // third quadrant
211  return (-1.0) * gamma * std::cos(sigma * gamma) * std::sin((theta - numbers::PI - rho) * gamma);
212  }
213 
214  Assert(false, ExcInternalError());
215  return 0.0;
216 }
217 
218 double
219 ScalarSolution::value(const Point<2>& p, const unsigned int /*component*/) const
220 {
221  double gamma = solution_parameters.parameters[0];
222 
223  std::pair<double, double> polar = polar_coords(p);
224  double r = polar.first;
225  double theta = polar.second;
226 
227  return std::pow(r, gamma) * mu(theta);
228 }
229 
230 Tensor<1, 2>
231 ScalarSolution::gradient(const Point<2>& p, const unsigned int /*component*/) const
232 {
233  const double gamma = solution_parameters.parameters[0];
234 
235  Tensor<1, 2> grad;
236  std::pair<double, double> polar = polar_coords(p);
237  double r = polar.first;
238  double theta = polar.second;
239 
240  grad[0] =
241  std::pow(r, gamma - 1.0) * (gamma * mu(theta) * std::cos(theta) - dmu(theta) * std::sin(theta));
242  grad[1] =
243  std::pow(r, gamma - 1.0) * (gamma * mu(theta) * std::sin(theta) + dmu(theta) * std::cos(theta));
244  return grad;
245 }
246 
259 class MixedSolution : public Function<2>
260 {
261 public:
262  MixedSolution(const std::vector<double>& parameters);
263 
264  virtual double value(const Point<2>& p, const unsigned int component) const;
265 
274 };
275 
276 MixedSolution::MixedSolution(const std::vector<double>& parameters)
277  : Function<2>(2 + 1)
278  , scalar_solution(parameters)
279  , coefficient(parameters)
280 {
281 }
282 
283 double
284 MixedSolution::value(const Point<2>& p, const unsigned int component) const
285 {
286  if (component == 2)
287  {
288  return scalar_solution.value(p);
289  }
290  else
291  {
292  Tensor<1, 2> grad_u = scalar_solution.gradient(p);
293  Tensor<2, 2> coefficient_value = coefficient.value(p);
294 
295  Tensor<1, 2> value = -1.0 * coefficient_value * grad_u;
296  return value[component];
297  }
298 }
299 }
300 }
301 
302 #endif
Definition: solution_parameters.h:283
Definition: darcy/checkerboard/solution.h:259
const ScalarSolution scalar_solution
The exact scalar solution.
Definition: darcy/checkerboard/solution.h:269
~CheckerboardTensorFunction()
Definition: darcy/checkerboard/solution.h:76
TensorFunction< 2, 2 >::value_type value_type
Definition: darcy/checkerboard/solution.h:42
Vector< double > parameters
The parameters of the exact solution.
Definition: solution_parameters.h:291
CheckerboardTensorFunction * inverse_ptr
Definition: darcy/checkerboard/solution.h:53
virtual double value(const Point< 2 > &p, const unsigned int component) const
Definition: darcy/checkerboard/solution.h:284
std::pair< double, double > polar_coords(const Point< 2 > &p)
Definition: darcy/checkerboard/solution.h:25
Definition: constrained_newton.h:15
CheckerboardTensorFunction(const std::vector< double > &parameters)
Definition: darcy/checkerboard/solution.h:57
const CheckerboardTensorFunction coefficient
The corresponding checkerboard coefficient.
Definition: darcy/checkerboard/solution.h:273
MixedSolution(const std::vector< double > &parameters)
Definition: darcy/checkerboard/solution.h:276
std::vector< double > parameters
Definition: darcy/checkerboard/solution.h:52
double mu(double theta) const
Definition: darcy/checkerboard/solution.h:151
virtual value_type value(const Point< 2 > &p) const
Definition: darcy/checkerboard/solution.h:91
virtual double value(const Point< 2 > &p, const unsigned int component=0) const
Definition: darcy/checkerboard/solution.h:219
double dmu(double theta) const
Definition: darcy/checkerboard/solution.h:185
SolutionParameters solution_parameters
Definition: darcy/checkerboard/solution.h:142
virtual Tensor< 1, 2 > gradient(const Point< 2 > &p, const unsigned int component=0) const
Definition: darcy/checkerboard/solution.h:231
Definition: darcy/checkerboard/solution.h:130
CheckerboardTensorFunction & inverse()
Definition: darcy/checkerboard/solution.h:85
bool is_inverse
Definition: darcy/checkerboard/solution.h:54
Definition: darcy/checkerboard/solution.h:39
ScalarSolution(const std::vector< double > &parameters)
Definition: darcy/checkerboard/solution.h:145