Amandus: Simulations based on multilevel Schwarz methods
stokes/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  **********************************************************************/
8 
9 #ifndef __stokes_solution_h
10 #define __stokes_solution_h
11 
12 #include <amandus/integrator.h>
13 #include <deal.II/base/flow_function.h>
14 #include <deal.II/base/smartpointer.h>
15 #include <deal.II/base/tensor.h>
16 #include <deal.II/integrators/divergence.h>
17 #include <deal.II/integrators/l2.h>
18 #include <deal.II/integrators/laplace.h>
19 
20 using namespace dealii;
21 using namespace LocalIntegrators;
22 using namespace MeshWorker;
23 using namespace Functions;
24 
25 namespace StokesIntegrators
26 {
33 template <int dim>
34 class SolutionRHS : public AmandusIntegrator<dim>
35 {
36 public:
37  SolutionRHS(FlowFunction<dim>& solution);
38 
39  virtual void cell(DoFInfo<dim>& dinfo, IntegrationInfo<dim>& info) const;
40  virtual void boundary(DoFInfo<dim>& dinfo, IntegrationInfo<dim>& info) const;
41  virtual void face(DoFInfo<dim>& dinfo1, DoFInfo<dim>& dinfo2, IntegrationInfo<dim>& info1,
42  IntegrationInfo<dim>& info2) const;
43 
44 private:
45  SmartPointer<FlowFunction<dim>, SolutionRHS<dim>> solution;
46 };
47 
54 template <int dim>
56 {
57 public:
58  SolutionResidual(FlowFunction<dim>& solution);
59 
60  virtual void cell(DoFInfo<dim>& dinfo, IntegrationInfo<dim>& info) const;
61  virtual void boundary(DoFInfo<dim>& dinfo, IntegrationInfo<dim>& info) const;
62  virtual void face(DoFInfo<dim>& dinfo1, DoFInfo<dim>& dinfo2, IntegrationInfo<dim>& info1,
63  IntegrationInfo<dim>& info2) const;
64 
65 private:
66  SmartPointer<FlowFunction<dim>, SolutionResidual<dim>> solution;
67 };
68 
69 template <int dim>
70 class SolutionError : public AmandusIntegrator<dim>
71 {
72 public:
73  SolutionError(FlowFunction<dim>& solution);
74 
75  virtual void cell(DoFInfo<dim>& dinfo, IntegrationInfo<dim>& info) const;
76  virtual void boundary(DoFInfo<dim>& dinfo, IntegrationInfo<dim>& info) const;
77  virtual void face(DoFInfo<dim>& dinfo1, DoFInfo<dim>& dinfo2, IntegrationInfo<dim>& info1,
78  IntegrationInfo<dim>& info2) const;
79 
80 private:
81  SmartPointer<FlowFunction<dim>, SolutionError<dim>> solution;
82 };
83 
84 //----------------------------------------------------------------------//
85 
86 template <int dim>
87 SolutionRHS<dim>::SolutionRHS(FlowFunction<dim>& solution)
88  : solution(&solution)
89 {
90  this->use_boundary = true;
91  this->use_face = false;
92 }
93 
94 template <int dim>
95 void
96 SolutionRHS<dim>::cell(DoFInfo<dim>& dinfo, IntegrationInfo<dim>& info) const
97 {
98  std::vector<std::vector<double>> rhs(
99  dim + 1, std::vector<double>(info.fe_values(0).n_quadrature_points, 0.));
100 
101  // This is not the real laplace but the rhs for stokes
102  solution->vector_laplacians(info.fe_values(0).get_quadrature_points(), rhs);
103 
104  L2::L2(dinfo.vector(0).block(0), info.fe_values(0), rhs, -1.);
105 }
106 
107 template <int dim>
108 void
109 SolutionRHS<dim>::boundary(DoFInfo<dim>&, IntegrationInfo<dim>&) const
110 {
111 }
112 
113 template <int dim>
114 void
115 SolutionRHS<dim>::face(DoFInfo<dim>&, DoFInfo<dim>&, IntegrationInfo<dim>&,
116  IntegrationInfo<dim>&) const
117 {
118 }
119 
120 //----------------------------------------------------------------------//
121 
122 template <int dim>
124  : solution(&solution)
125 {
126  this->use_boundary = true;
127  this->use_face = true;
128  this->input_vector_names.push_back("Newton iterate");
129 }
130 
131 template <int dim>
132 void
133 SolutionResidual<dim>::cell(DoFInfo<dim>& dinfo, IntegrationInfo<dim>& info) const
134 {
135  Assert(info.values.size() >= 1, ExcDimensionMismatch(info.values.size(), 1));
136  Assert(info.gradients.size() >= 1, ExcDimensionMismatch(info.values.size(), 1));
137 
138  std::vector<std::vector<double>> rhs(
139  dim + 1, std::vector<double>(info.fe_values(0).n_quadrature_points, 0.));
140 
141  // This is not the real laplace but the rhs for stokes
142  solution->vector_laplacians(info.fe_values(0).get_quadrature_points(), rhs);
143 
144  L2::L2(dinfo.vector(0).block(0), info.fe_values(0), make_slice(rhs, 0, dim));
146  dinfo.vector(0).block(0), info.fe_values(0), make_slice(info.gradients[0], 0, dim));
147  Divergence::gradient_residual(
148  dinfo.vector(0).block(0), info.fe_values(0), info.values[0][dim], -1.);
150  dinfo.vector(0).block(1), info.fe_values(1), make_slice(info.gradients[0], 0, dim), 1.);
151 }
152 
153 template <int dim>
154 void
155 SolutionResidual<dim>::boundary(DoFInfo<dim>& dinfo, IntegrationInfo<dim>& info) const
156 {
157  std::vector<std::vector<double>> values(
158  dim + 1, std::vector<double>(info.fe_values(0).n_quadrature_points, 0.));
159  solution->vector_values(info.fe_values(0).get_quadrature_points(), values);
160 
161  const unsigned int deg = info.fe_values(0).get_fe().tensor_degree();
162  Laplace::nitsche_residual(dinfo.vector(0).block(0),
163  info.fe_values(0),
164  make_slice(info.values[0], 0, dim),
165  make_slice(info.gradients[0], 0, dim),
166  make_slice(values, 0, dim),
167  Laplace::compute_penalty(dinfo, dinfo, deg, deg));
168 }
169 
170 template <int dim>
171 void
172 SolutionResidual<dim>::face(DoFInfo<dim>& dinfo1, DoFInfo<dim>& dinfo2, IntegrationInfo<dim>& info1,
173  IntegrationInfo<dim>& info2) const
174 {
175  const unsigned int deg = info1.fe_values(0).get_fe().tensor_degree();
176  Laplace::ip_residual(dinfo1.vector(0).block(0),
177  dinfo2.vector(0).block(0),
178  info1.fe_values(0),
179  info2.fe_values(0),
180  make_slice(info1.values[0], 0, dim),
181  make_slice(info1.gradients[0], 0, dim),
182  make_slice(info2.values[0], 0, dim),
183  make_slice(info2.gradients[0], 0, dim),
184  Laplace::compute_penalty(dinfo1, dinfo2, deg, deg));
185 }
186 
187 //----------------------------------------------------------------------//
188 
189 template <int dim>
191  : solution(&solution)
192 {
193  this->use_boundary = false;
194  this->use_face = false;
195  this->error_types.push_back(2);
196  this->error_types.push_back(2);
197  this->error_types.push_back(0);
198  this->error_types.push_back(2);
199  this->error_types.push_back(2);
200 }
201 
202 template <int dim>
203 void
204 SolutionError<dim>::cell(DoFInfo<dim>& dinfo, IntegrationInfo<dim>& info) const
205 {
206  Assert(dinfo.n_values() >= 5, ExcDimensionMismatch(dinfo.n_values(), 5));
207 
208  std::vector<std::vector<double>> val(
209  dim + 1, std::vector<double>(info.fe_values(0).n_quadrature_points, 0.));
210  std::vector<std::vector<Tensor<1, dim>>> grad(
211  dim + 1, std::vector<Tensor<1, dim>>(info.fe_values(0).n_quadrature_points));
212 
213  solution->vector_values(info.fe_values(0).get_quadrature_points(), val);
214  solution->vector_gradients(info.fe_values(0).get_quadrature_points(), grad);
215 
216  for (unsigned int k = 0; k < info.fe_values(0).n_quadrature_points; ++k)
217  {
218  const double dx = info.fe_values(0).JxW(k);
219 
220  Tensor<1, dim> Du0 = info.gradients[0][0][k];
221  double div = Du0[0];
222  Du0[0] -= grad[0][k][0];
223  Du0[1] -= grad[0][k][1];
224  Tensor<1, dim> Du1 = info.gradients[0][1][k];
225  div += Du1[1];
226  Du1[0] -= grad[1][k][0];
227  Du1[1] -= grad[1][k][1];
228  div -= grad[0][k][0] + grad[1][k][1];
229  double u0 = info.values[0][0][k];
230  u0 -= val[0][k];
231  double u1 = info.values[0][1][k];
232  u1 -= val[1][k];
233 
234  double p = info.values[0][dim][k];
235  p += val[dim][k];
236  Tensor<1, dim> Dp = info.gradients[0][dim][k];
237  Dp[0] += grad[dim][k][0];
238  Dp[1] += grad[dim][k][1];
239 
240  // 0. L^2(u)
241  dinfo.value(0) += (u0 * u0 + u1 * u1) * dx;
242  // 1. H^1(u)
243  dinfo.value(1) += ((Du0 * Du0) + (Du1 * Du1)) * dx;
244  // 2. div u
245  if (dinfo.value(2) < div * div)
246  dinfo.value(2) = div * div;
247  // 3. L^2(p) up to mean value
248  dinfo.value(3) += (p * p) * dx;
249  // 4. H^1(p)
250  dinfo.value(4) += (Dp * Dp) * dx;
251  }
252  for (unsigned int i = 0; i <= 4; ++i)
253  dinfo.value(i) = std::sqrt(dinfo.value(i));
254 }
255 
256 template <int dim>
257 void
258 SolutionError<dim>::boundary(DoFInfo<dim>&, IntegrationInfo<dim>&) const
259 {
260 }
261 
262 template <int dim>
263 void
264 SolutionError<dim>::face(DoFInfo<dim>&, DoFInfo<dim>&, IntegrationInfo<dim>&,
265  IntegrationInfo<dim>&) const
266 {
267 }
268 
269 /*
270  * Estimator implemented for Lshape domain
271  */
272 
273 template <int dim>
275 {
276 public:
277  SolutionEstimate(FlowFunction<dim>& solution);
278  virtual void cell(MeshWorker::DoFInfo<dim>& dinfo, MeshWorker::IntegrationInfo<dim>& info) const;
279  virtual void boundary(MeshWorker::DoFInfo<dim>& dinfo,
280  MeshWorker::IntegrationInfo<dim>& info) const;
281  virtual void face(MeshWorker::DoFInfo<dim>& dinfo1, MeshWorker::DoFInfo<dim>& dinfo2,
282  MeshWorker::IntegrationInfo<dim>& info1,
283  MeshWorker::IntegrationInfo<dim>& info2) const;
284 
285 private:
286  SmartPointer<FlowFunction<dim>, SolutionEstimate<dim>> solution;
287 };
288 
289 template <int dim>
291  : solution(&solution)
292 
293 {
294  this->use_boundary = true;
295  this->use_face = true;
296  this->add_flags(update_hessians);
297  this->add_flags(update_gradients);
298 }
299 
300 template <int dim>
301 void
302 SolutionEstimate<dim>::cell(MeshWorker::DoFInfo<dim>& dinfo,
303  MeshWorker::IntegrationInfo<dim>& info) const
304 {
305  std::vector<std::vector<double>> rhs(
306  dim + 1, std::vector<double>(info.fe_values(0).n_quadrature_points, 0.));
307 
308  solution->vector_laplacians(info.fe_values(0).get_quadrature_points(), rhs);
309 
310  const std::vector<Tensor<2, dim>>& h0 = info.hessians[0][0];
311  const std::vector<Tensor<2, dim>>& h1 = info.hessians[0][1];
312  const std::vector<Tensor<1, dim>>& p1 = info.gradients[0][dim];
313 
314  for (unsigned int k = 0; k < info.fe_values(0).n_quadrature_points; ++k)
315  {
316  Tensor<1, dim> r;
317 
318  r[0] += dinfo.cell->diameter() * (trace(h0[k]) + p1[k][0] - rhs[0][k]);
319  r[1] += dinfo.cell->diameter() * (trace(h1[k]) + p1[k][1] - rhs[1][k]);
320 
321  dinfo.value(0) += (r * r) * info.fe_values(0).JxW(k);
322  }
323 
324  dinfo.value(0) = std::sqrt(dinfo.value(0));
325 }
326 
327 template <int dim>
328 void
329 SolutionEstimate<dim>::boundary(MeshWorker::DoFInfo<dim>& dinfo,
330  MeshWorker::IntegrationInfo<dim>& info) const
331 {
332  const FEValuesBase<dim>& fe = info.fe_values();
333  std::vector<std::vector<double>> values(
334  dim + 1, std::vector<double>(info.fe_values(0).n_quadrature_points, 0.));
335  solution->vector_values(info.fe_values(0).get_quadrature_points(), values);
336 
337  const unsigned int deg = fe.get_fe().tensor_degree();
338  const double penalty = Laplace::compute_penalty(dinfo, dinfo, deg, deg);
339 
340  for (unsigned int k = 0; k < fe.n_quadrature_points; ++k)
341  {
342  Tensor<1, dim> diff;
343  for (unsigned int d = 0; d < dim; ++d)
344  {
345  diff[d] += (info.values[0][d][k] - values[d][k]);
346  }
347  dinfo.value(0) += penalty * (diff * diff) * fe.JxW(k);
348  }
349  dinfo.value(0) = std::sqrt(dinfo.value(0));
350 }
351 
352 template <int dim>
353 void
354 SolutionEstimate<dim>::face(MeshWorker::DoFInfo<dim>& dinfo1, MeshWorker::DoFInfo<dim>& dinfo2,
355  MeshWorker::IntegrationInfo<dim>& info1,
356  MeshWorker::IntegrationInfo<dim>& info2) const
357 {
358  const FEValuesBase<dim>& fe = info1.fe_values();
359  double h;
360  if (dim == 3)
361  h = std::sqrt(dinfo1.face->measure());
362  else
363  h = dinfo1.face->measure();
364 
365  const unsigned int deg1 = info1.fe_values().get_fe().tensor_degree();
366  const unsigned int deg2 = info2.fe_values().get_fe().tensor_degree();
367  const double penalty = 2. * Laplace::compute_penalty(dinfo1, dinfo2, deg1, deg2);
368  for (unsigned int k = 0; k < fe.n_quadrature_points; ++k)
369  {
370  Tensor<1, dim> diff;
371  Tensor<1, dim> diff1;
372  for (unsigned int d = 0; d < dim; ++d)
373  {
374  diff += (info1.gradients[0][d][k] - info2.gradients[0][d][k]) * fe.normal_vector(k)[d];
375 
376  diff[d] -= (info1.values[0][dim][k] - info2.values[0][dim][k]) * fe.normal_vector(k)[d];
377 
378  diff1[d] += info1.values[0][d][k] - info2.values[0][d][k];
379  }
380  dinfo1.value(0) += (penalty * (diff1 * diff1) + h * (diff * diff)) * fe.JxW(k);
381  }
382  dinfo1.value(0) = std::sqrt(dinfo1.value(0));
383  dinfo2.value(0) = dinfo1.value(0);
384 }
385 }
386 
387 #endif
SmartPointer< FlowFunction< dim >, SolutionError< dim > > solution
Definition: stokes/solution.h:81
Definition: stokes/solution.h:55
SmartPointer< FlowFunction< dim >, SolutionRHS< dim > > solution
Definition: stokes/solution.h:45
virtual void boundary(MeshWorker::DoFInfo< dim > &dinfo, MeshWorker::IntegrationInfo< dim > &info) const
Definition: stokes/solution.h:329
virtual void boundary(DoFInfo< dim > &dinfo, IntegrationInfo< dim > &info) const
Definition: stokes/solution.h:258
Definition: stokes/solution.h:274
virtual void face(MeshWorker::DoFInfo< dim > &dinfo1, MeshWorker::DoFInfo< dim > &dinfo2, MeshWorker::IntegrationInfo< dim > &info1, MeshWorker::IntegrationInfo< dim > &info2) const
Definition: stokes/solution.h:354
virtual void face(DoFInfo< dim > &dinfo1, DoFInfo< dim > &dinfo2, IntegrationInfo< dim > &info1, IntegrationInfo< dim > &info2) const
Definition: stokes/solution.h:172
Definition: stokes/solution.h:70
virtual void face(DoFInfo< dim > &dinfo1, DoFInfo< dim > &dinfo2, IntegrationInfo< dim > &info1, IntegrationInfo< dim > &info2) const
Definition: stokes/solution.h:115
SolutionResidual(FlowFunction< dim > &solution)
Definition: stokes/solution.h:123
Definition: stokes/eigen.h:37
virtual void cell(MeshWorker::DoFInfo< dim > &dinfo, MeshWorker::IntegrationInfo< dim > &info) const
Definition: stokes/solution.h:302
virtual void face(DoFInfo< dim > &dinfo1, DoFInfo< dim > &dinfo2, IntegrationInfo< dim > &info1, IntegrationInfo< dim > &info2) const
Definition: stokes/solution.h:264
virtual void boundary(DoFInfo< dim > &dinfo, IntegrationInfo< dim > &info) const
Definition: stokes/solution.h:155
virtual void cell(DoFInfo< dim > &dinfo, IntegrationInfo< dim > &info) const
Definition: stokes/solution.h:204
SolutionError(FlowFunction< dim > &solution)
Definition: stokes/solution.h:190
SmartPointer< FlowFunction< dim >, SolutionEstimate< dim > > solution
Definition: stokes/solution.h:286
std::vector< unsigned int > error_types
Definition: integrator.h:113
Definition: stokes/solution.h:34
virtual void boundary(DoFInfo< dim > &dinfo, IntegrationInfo< dim > &info) const
Definition: stokes/solution.h:109
virtual void cell(DoFInfo< dim > &dinfo, IntegrationInfo< dim > &info) const
Definition: stokes/solution.h:133
void cell_residual(dealii::Vector< number > &result, const dealii::FEValuesBase< dim > &fe, const dealii::VectorSlice< const std::vector< std::vector< dealii::Tensor< 1, dim >>>> &input, double lambda=0., double mu=1.)
Definition: elasticity/integrators.h:23
SolutionEstimate(FlowFunction< dim > &solution)
Definition: stokes/solution.h:290
SmartPointer< FlowFunction< dim >, SolutionResidual< dim > > solution
Definition: stokes/solution.h:66
virtual void cell(DoFInfo< dim > &dinfo, IntegrationInfo< dim > &info) const
Definition: stokes/solution.h:96
void add_flags(const dealii::UpdateFlags flags)
Add update flags on all objects.
Definition: integrator.h:454
Definition: integrator.h:29