Amandus: Simulations based on multilevel Schwarz methods
solution_parameters.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_parameters_h
8 #define __darcy_checkerboard_solution_parameters_h
9 
10 #include <deal.II/algorithms/any_data.h>
11 #include <deal.II/base/function.h>
12 #include <deal.II/base/parameter_handler.h>
13 #include <deal.II/lac/full_matrix.h>
14 
15 #include <amandus/darcy/checkerboard/constrained_newton.h>
16 
17 namespace Darcy
18 {
19 namespace Checkerboard
20 {
21 using namespace dealii;
22 
27 class ParameterEquation : public Function<3>
28 {
29 public:
34  ParameterEquation(const std::vector<double>& coefficient);
35 
36  virtual double value(const Point<3>& p, const unsigned int component) const;
37  virtual Tensor<1, 3> gradient(const Point<3>& p, const unsigned int component) const;
38 
39 private:
40  std::vector<double> rhs;
41 };
42 
43 ParameterEquation::ParameterEquation(const std::vector<double>& coefficient)
44  : Function<3>(3)
45 {
46  rhs.push_back(coefficient[0] / coefficient[1]);
47  rhs.push_back(coefficient[1] / coefficient[2]);
48  rhs.push_back(coefficient[2] / coefficient[3]);
49 }
50 
51 double
52 ParameterEquation::value(const Point<3>& p, const unsigned int component) const
53 {
54  double gamma = p[0];
55  double sigma = p[1];
56  double rho = p[2];
57 
58  double value = 0.0;
59 
60  if (component == 0)
61  {
62  value = std::tan((numbers::PI / 2 - sigma) * gamma) * std::pow(std::tan(rho * gamma), -1);
63  }
64  else if (component == 1)
65  {
66  value = std::tan(rho * gamma) * std::pow(std::tan(sigma * gamma), -1);
67  }
68  else if (component == 2)
69  {
70  value = std::tan(sigma * gamma) * std::pow(std::tan((numbers::PI / 2 - rho) * gamma), -1);
71  }
72  else
73  {
74  Assert(false, ExcInternalError());
75  }
76 
77  return value + rhs[component];
78 }
79 
80 Tensor<1, 3>
81 ParameterEquation::gradient(const Point<3>& p, const unsigned int component) const
82 {
83  double gamma = p[0];
84  double sigma = p[1];
85  double rho = p[2];
86 
87  Tensor<1, 3> grad;
88 
89  if (component == 0)
90  {
91  grad[0] = (numbers::PI / 2 - sigma) * std::pow(std::tan(rho * gamma), -1) *
92  std::pow(std::cos(numbers::PI / 2 * gamma - sigma * gamma), -2) -
93  rho * std::tan(numbers::PI / 2 * gamma - sigma * gamma) *
94  std::pow(std::tan(rho * gamma), -2) * std::pow(std::cos(rho * gamma), -2);
95 
96  grad[1] = -1 * gamma * std::pow(std::tan(rho * gamma), -1) *
97  std::pow(std::cos(numbers::PI / 2 * gamma - sigma * gamma), -2);
98 
99  grad[2] = -1 * gamma * std::tan(numbers::PI / 2 * gamma - sigma * gamma) *
100  std::pow(std::cos(rho * gamma), -2) * std::pow(std::tan(rho * gamma), -2);
101  }
102  else if (component == 1)
103  {
104  grad[0] = rho * std::pow(std::tan(sigma * gamma), -1) * std::pow(std::cos(rho * gamma), -2) -
105  sigma * std::tan(rho * gamma) * std::pow(std::tan(sigma * gamma), -2) *
106  std::pow(std::cos(sigma * gamma), -2);
107 
108  grad[1] = -1 * gamma * std::tan(rho * gamma) * std::pow(std::cos(sigma * gamma), -2) *
109  std::pow(std::tan(sigma * gamma), -2);
110 
111  grad[2] = gamma * std::pow(std::cos(rho * gamma), -2) * std::pow(std::tan(sigma * gamma), -1);
112  }
113  else if (component == 2)
114  {
115  grad[0] = sigma * std::pow(std::cos(sigma * gamma), -2) *
116  std::pow(std::tan(numbers::PI / 2 * gamma - rho * gamma), -1) -
117  (numbers::PI / 2 - rho) * std::tan(sigma * gamma) *
118  std::pow(std::tan(numbers::PI / 2 * gamma - rho * gamma), -2) *
119  std::pow(std::cos(numbers::PI / 2 * gamma - rho * gamma), -2);
120 
121  grad[1] = gamma * std::pow(std::tan(numbers::PI / 2 * gamma - rho * gamma), -1) *
122  std::pow(std::cos(sigma * gamma), -2);
123 
124  grad[2] = gamma * std::tan(sigma * gamma) *
125  std::pow(std::cos(numbers::PI / 2 * gamma - rho * gamma), -2) *
126  std::pow(std::tan(numbers::PI / 2 * gamma - rho * gamma), -2);
127  }
128  else
129  {
130  Assert(false, ExcInternalError());
131  }
132 
133  return grad;
134 }
135 
139 template <int dim, typename VECTOR>
140 inline void
141 pointify(const VECTOR& v, Point<dim>& p)
142 {
143  AssertDimension(v.size(), dim);
144  for (unsigned int i = 0; i < dim; ++i)
145  {
146  p[i] = v[i];
147  }
148 }
149 
153 template <int dim, typename number>
154 inline void
155 jacobian(const Function<dim>& f, const Point<dim>& p, FullMatrix<number>& J)
156 {
157  AssertDimension(J.m(), f.n_components);
158  AssertDimension(J.n(), dim);
159  std::vector<Tensor<1, dim>> grads(f.n_components);
160  f.vector_gradient(p, grads);
161  for (unsigned int i = 0; i < f.n_components; ++i)
162  {
163  for (unsigned int j = 0; j < dim; ++j)
164  {
165  J.set(i, j, grads[i][j]);
166  }
167  }
168 }
169 
174 template <int dim, typename VECTOR>
175 class NewtonResidual : public Algorithms::OperatorBase
176 {
177 public:
178  NewtonResidual(const Function<dim>* f);
179  virtual void operator()(AnyData& out, const AnyData& in);
180 
181 private:
182  SmartPointer<const Function<dim>> f;
183  Point<dim> p;
184 };
185 
186 template <int dim, typename VECTOR>
188  : f(f)
189 {
190 }
191 
192 template <int dim, typename VECTOR>
193 void
194 NewtonResidual<dim, VECTOR>::operator()(AnyData& out, const AnyData& in)
195 {
196  Assert(in.size() == 1, ExcNotImplemented());
197  Assert(out.size() == 1, ExcNotImplemented());
198 
199  pointify(*(in.read<const VECTOR*>(0)), p);
200  f->vector_value(p, *out.entry<VECTOR*>(0));
201 }
202 
207 template <int dim, typename VECTOR>
208 class NewtonInvJ : public Algorithms::OperatorBase
209 {
210 public:
211  typedef typename VECTOR::value_type number;
212 
213  NewtonInvJ(const Function<dim>* f);
214  virtual void operator()(AnyData& out, const AnyData& in);
215 
216 private:
217  SmartPointer<const Function<dim>> f;
218  Point<dim> p;
219  FullMatrix<number> J;
220  FullMatrix<number> iJ;
221 };
222 
223 template <int dim, typename VECTOR>
225  : f(f)
226  , J(dim, dim)
227  , iJ(dim, dim)
228 {
229  AssertDimension(dim, f->n_components);
230 }
231 
232 template <int dim, typename VECTOR>
233 void
234 NewtonInvJ<dim, VECTOR>::operator()(AnyData& out, const AnyData& in)
235 {
236  Assert(out.size() == 1, ExcNotImplemented());
237  Assert(in.size() == 2, ExcNotImplemented());
238  Assert(in.name(0) == "Newton residual", ExcInternalError());
239  Assert(in.name(1) == "Newton iterate", ExcInternalError());
240 
241  pointify(*(in.read<const VECTOR*>(1)), p);
242  jacobian(*f, p, J);
243  iJ.invert(J);
244  iJ.vmult(*out.entry<VECTOR*>(0), *(in.read<const VECTOR*>(0)));
245 }
246 
251 template <int dim, typename VECTOR>
252 void
253 find_root(const Function<dim>& f, VECTOR& u)
254 {
256  NewtonInvJ<dim, VECTOR> iJf(&f);
257  ConstrainedNewton<VECTOR> newton(res, iJf);
258  // TODO: consider exposing reduction control parameters
259  ParameterHandler prm;
260  newton.declare_parameters(prm);
261  prm.enter_subsection("Newton");
262  prm.set("Stepsize iterations", "10");
263  prm.set("Tolerance", "1.e-12");
264  prm.set("Reduction", "0.0");
265  prm.set("Max steps", "100000");
266  prm.set("Log history", false);
267  prm.set("Log frequency", "10");
268  prm.leave_subsection();
269  newton.parse_parameters(prm);
270 
271  AnyData out;
272  AnyData in;
273 
274  VECTOR* p = &u;
275  out.add(p, "Start and end value");
276  newton(out, in);
277 }
278 
284 {
285 public:
290  SolutionParameters(const std::vector<double>& input_parameters);
291  Vector<double> parameters;
292 };
293 
294 SolutionParameters::SolutionParameters(const std::vector<double>& input_parameters)
295  : parameters(3)
296 {
297  ParameterEquation parameter_equation(input_parameters);
298  parameters[0] = 1.0;
299  parameters[1] = -1 * dealii::numbers::PI / 4.0;
300  parameters[2] = numbers::PI / 4.0;
301 
302  find_root(parameter_equation, parameters);
303 }
304 }
305 }
306 
307 #endif
Definition: solution_parameters.h:283
std::vector< double > rhs
Definition: solution_parameters.h:40
Definition: solution_parameters.h:27
SmartPointer< const Function< dim > > f
Definition: solution_parameters.h:217
FullMatrix< number > J
Definition: solution_parameters.h:219
Definition: solution_parameters.h:175
virtual void operator()(AnyData &out, const AnyData &in)
Definition: solution_parameters.h:234
Vector< double > parameters
The parameters of the exact solution.
Definition: solution_parameters.h:291
virtual void operator()(AnyData &out, const AnyData &in)
Definition: solution_parameters.h:194
Point< dim > p
Definition: solution_parameters.h:183
ParameterEquation(const std::vector< double > &coefficient)
Definition: solution_parameters.h:43
FullMatrix< number > iJ
Definition: solution_parameters.h:220
void jacobian(const Function< dim > &f, const Point< dim > &p, FullMatrix< number > &J)
Definition: solution_parameters.h:155
Point< dim > p
Definition: solution_parameters.h:218
Definition: constrained_newton.h:30
void pointify(const VECTOR &v, Point< dim > &p)
Definition: solution_parameters.h:141
SmartPointer< const Function< dim > > f
Definition: solution_parameters.h:182
Definition: constrained_newton.h:15
NewtonResidual(const Function< dim > *f)
Definition: solution_parameters.h:187
NewtonInvJ(const Function< dim > *f)
Definition: solution_parameters.h:224
virtual double value(const Point< 3 > &p, const unsigned int component) const
Definition: solution_parameters.h:52
VECTOR::value_type number
Definition: solution_parameters.h:211
void find_root(const Function< dim > &f, VECTOR &u)
Definition: solution_parameters.h:253
SolutionParameters(const std::vector< double > &input_parameters)
Definition: solution_parameters.h:294
Definition: solution_parameters.h:208
virtual Tensor< 1, 3 > gradient(const Point< 3 > &p, const unsigned int component) const
Definition: solution_parameters.h:81