Amandus: Simulations based on multilevel Schwarz methods
darcy/integrators.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_integrators_h
8 #define __darcy_integrators_h
9 
10 #include <amandus/integrator.h>
11 
12 #include <deal.II/base/exceptions.h>
13 #include <deal.II/base/point.h>
14 #include <deal.II/base/tensor.h>
15 #include <deal.II/base/tensor_function.h>
16 #include <deal.II/integrators/divergence.h>
17 #include <deal.II/integrators/l2.h>
18 #include <deal.II/integrators/laplace.h>
19 #include <deal.II/meshworker/dof_info.h>
20 #include <deal.II/meshworker/integration_info.h>
21 
28 namespace DarcyIntegrators
29 {
39 template <int dim>
40 void
41 weighted_mass_matrix(dealii::FullMatrix<double>& M, const dealii::FEValuesBase<dim>& fe,
42  const dealii::TensorFunction<2, dim>& weight)
43 {
44  const unsigned int n_dofs = fe.dofs_per_cell;
45  const unsigned int n_components = fe.get_fe().n_components();
46  AssertDimension(n_components, dim);
47  const unsigned int n_quadrature_points = fe.n_quadrature_points;
48  std::vector<dealii::Tensor<2, dim>> weight_values(n_quadrature_points);
49  weight.value_list(fe.get_quadrature_points(), weight_values);
50 
51  for (unsigned int q = 0; q < n_quadrature_points; ++q)
52  {
53  const double dx = fe.JxW(q);
54 
55  for (unsigned int i = 0; i < n_dofs; ++i)
56  {
57  for (unsigned int j = 0; j < n_dofs; ++j)
58  {
59  for (unsigned int k1 = 0; k1 < n_components; ++k1)
60  {
61  for (unsigned int k2 = 0; k2 < n_components; ++k2)
62  {
63  M(i, j) += (dx * weight_values[q][k1][k2] * fe.shape_value_component(i, q, k2) *
64  fe.shape_value_component(j, q, k1));
65  }
66  }
67  }
68  }
69  }
70 }
71 
76 template <int dim>
77 class IdentityTensorFunction : public dealii::TensorFunction<2, dim>
78 {
79 public:
80  typedef typename dealii::TensorFunction<2, dim>::value_type value_type;
82 
83  virtual value_type value(const dealii::Point<dim>& p) const;
84 
85  dealii::Tensor<2, dim> identity;
86 };
87 
88 template <int dim>
90 {
91  for (unsigned int i = 0; i < dim; ++i)
92  {
93  identity[i][i] = 1.0;
94  }
95 }
96 
97 template <int dim>
99 IdentityTensorFunction<dim>::value(const dealii::Point<dim>& /*p*/) const
100 {
101  return identity;
102 }
103 
119 template <int dim>
121 {
122 public:
124  SystemIntegrator(const dealii::TensorFunction<2, dim>& weight);
125  ~SystemIntegrator();
126 
127  virtual void cell(dealii::MeshWorker::DoFInfo<dim>& dinfo,
128  dealii::MeshWorker::IntegrationInfo<dim>& info) const;
129 
130 private:
131  void init();
132  const dealii::TensorFunction<2, dim>* const weight_ptr;
133  dealii::SmartPointer<const dealii::TensorFunction<2, dim>> weight;
134 };
135 
136 template <int dim>
138  : weight_ptr(new IdentityTensorFunction<dim>)
139  , weight(weight_ptr)
140 {
141  init();
142 }
143 
144 template <int dim>
145 SystemIntegrator<dim>::SystemIntegrator(const dealii::TensorFunction<2, dim>& weight)
146  : weight_ptr(0)
147  , weight(&weight)
148 {
149  init();
150 }
151 
152 template <int dim>
154 {
155  if (weight_ptr != 0)
156  {
157  weight = 0;
158  delete weight_ptr;
159  }
160 }
161 
162 template <int dim>
163 void
165 {
166  this->use_cell = true;
167  this->use_boundary = false;
168  this->use_face = false;
169 
170  this->add_flags(dealii::update_JxW_values | dealii::update_values | dealii::update_gradients |
171  dealii::update_quadrature_points);
172 }
173 
174 template <int dim>
175 void
176 SystemIntegrator<dim>::cell(dealii::MeshWorker::DoFInfo<dim>& dinfo,
177  dealii::MeshWorker::IntegrationInfo<dim>& info) const
178 {
179  AssertDimension(dinfo.n_matrices(), 4);
180 
181  weighted_mass_matrix(dinfo.matrix(0).matrix, info.fe_values(0), *weight);
183  dinfo.matrix(2).matrix, info.fe_values(0), info.fe_values(1));
184  dinfo.matrix(1).matrix.copy_transposed(dinfo.matrix(2).matrix);
185  dinfo.matrix(1).matrix *= -1.0;
186 }
187 
203 template <int dim>
204 class RHSIntegrator : public AmandusIntegrator<dim>
205 {
206 public:
207  RHSIntegrator(const dealii::Function<dim>& boundary_function);
208 
209  virtual void boundary(dealii::MeshWorker::DoFInfo<dim>& dinfo,
210  dealii::MeshWorker::IntegrationInfo<dim>& info) const;
211 
212 private:
213  dealii::SmartPointer<const dealii::Function<dim>> boundary_function;
214 };
215 
216 template <int dim>
217 RHSIntegrator<dim>::RHSIntegrator(const dealii::Function<dim>& boundary_function)
218  : boundary_function(&boundary_function)
219 {
220  AssertDimension(boundary_function.n_components, 1);
221  this->use_cell = false;
222  this->use_boundary = true;
223  this->use_face = false;
224 
225  this->add_flags(dealii::update_JxW_values | dealii::update_values |
226  dealii::update_quadrature_points);
227 }
228 
229 template <int dim>
230 void
231 RHSIntegrator<dim>::boundary(dealii::MeshWorker::DoFInfo<dim>& dinfo,
232  dealii::MeshWorker::IntegrationInfo<dim>& info) const
233 {
234  const unsigned int n_quadrature_points = info.fe_values(0).n_quadrature_points;
235 
236  std::vector<double> boundary_values(n_quadrature_points);
237  boundary_function->value_list(info.fe_values(0).get_quadrature_points(), boundary_values, dim);
238 
239  dealii::LocalIntegrators::Divergence::u_times_n_residual(
240  dinfo.vector(0).block(0), info.fe_values(0), boundary_values, -1.0);
241 }
242 
248 template <int dim>
250 {
251 public:
252  ErrorIntegrator(const dealii::Function<dim>& exact_solution);
253  ErrorIntegrator(const dealii::Function<dim>& exact_solution,
254  const dealii::TensorFunction<2, dim>& weight);
255  ~ErrorIntegrator();
256 
257  virtual void cell(dealii::MeshWorker::DoFInfo<dim>& dinfo,
258  dealii::MeshWorker::IntegrationInfo<dim>& info) const;
259 
260 private:
261  void init();
262 
263  const dealii::SmartPointer<const dealii::Function<dim>> exact_solution;
264 
265  const dealii::TensorFunction<2, dim>* const owned_weight;
266  dealii::SmartPointer<const dealii::TensorFunction<2, dim>> weight;
267 };
268 
269 template <int dim>
270 ErrorIntegrator<dim>::ErrorIntegrator(const dealii::Function<dim>& exact_solution)
271  : exact_solution(&exact_solution)
272  , owned_weight(new IdentityTensorFunction<dim>)
273  , weight(owned_weight)
274 {
275  init();
276 }
277 
278 template <int dim>
280  const dealii::TensorFunction<2, dim>& weight)
281  : exact_solution(&exact_solution)
282  , owned_weight(0)
283  , weight(&weight)
284 {
285  init();
286 }
287 
288 template <int dim>
290 {
291  if (owned_weight != 0)
292  {
293  weight = 0;
294  delete owned_weight;
295  }
296 }
297 
298 template <int dim>
299 void
301 {
302  AssertDimension(exact_solution->n_components, dim + 1);
303  this->use_cell = true;
304  this->use_boundary = false;
305  this->use_face = false;
306 
307  this->add_flags(dealii::update_JxW_values | dealii::update_values | dealii::update_gradients |
308  dealii::update_quadrature_points);
309 }
310 
311 template <int dim>
312 void
313 ErrorIntegrator<dim>::cell(dealii::MeshWorker::DoFInfo<dim>& dinfo,
314  dealii::MeshWorker::IntegrationInfo<dim>& info) const
315 {
316  const dealii::FEValuesBase<dim>& velocity_fe_values = info.fe_values(0);
317  const dealii::FEValuesBase<dim>& pressure_fe_values = info.fe_values(1);
318 
319  const std::vector<std::vector<double>>& velocity_approximation = info.values[0];
320  const std::vector<double>& pressure_approximation = info.values[0][dim];
321 
322  std::vector<std::vector<double>> velocity_exact(
323  dim, std::vector<double>(velocity_fe_values.n_quadrature_points));
324  std::vector<double> pressure_exact(pressure_fe_values.n_quadrature_points);
325  for (unsigned int i = 0; i < dim; ++i)
326  {
327  exact_solution->value_list(velocity_fe_values.get_quadrature_points(), velocity_exact[i], i);
328  }
329  exact_solution->value_list(pressure_fe_values.get_quadrature_points(), pressure_exact, dim);
330 
331  std::vector<dealii::Tensor<2, dim>> weight_values(velocity_fe_values.n_quadrature_points);
332  weight->value_list(velocity_fe_values.get_quadrature_points(), weight_values);
333 
334  // L2 error of velocity
335  double velocity_l2_error = 0;
336  for (unsigned int i = 0; i < dim; ++i)
337  {
338  for (unsigned int j = 0; j < dim; ++j)
339  {
340  for (unsigned int q = 0; q < velocity_fe_values.n_quadrature_points; ++q)
341  {
342  velocity_l2_error +=
343  (weight_values[q][i][j] * (velocity_exact[j][q] - velocity_approximation[j][q]) *
344  (velocity_exact[i][q] - velocity_approximation[i][q]) * velocity_fe_values.JxW(q));
345  }
346  }
347  }
348  dinfo.value(0) = std::sqrt(velocity_l2_error);
349 
350  // L2 error of pressure
351  double pressure_l2_error = 0;
352  for (unsigned int q = 0; q < pressure_fe_values.n_quadrature_points; ++q)
353  {
354  pressure_l2_error +=
355  (std::pow(pressure_exact[q] - pressure_approximation[q], 2) * pressure_fe_values.JxW(q));
356  }
357  dinfo.value(1) = std::sqrt(pressure_l2_error);
358 }
359 }
360 
361 #endif
virtual void cell(dealii::MeshWorker::DoFInfo< dim > &dinfo, dealii::MeshWorker::IntegrationInfo< dim > &info) const
Definition: darcy/integrators.h:176
void weighted_mass_matrix(dealii::FullMatrix< double > &M, const dealii::FEValuesBase< dim > &fe, const dealii::TensorFunction< 2, dim > &weight)
Definition: darcy/integrators.h:41
dealii::SmartPointer< const dealii::TensorFunction< 2, dim > > weight
Definition: darcy/integrators.h:133
dealii::Tensor< 2, dim > identity
Definition: darcy/integrators.h:85
void cell_matrix(dealii::FullMatrix< double > &M, 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: matrix_integrators.h:23
RHSIntegrator(const dealii::Function< dim > &boundary_function)
Definition: darcy/integrators.h:217
ErrorIntegrator(const dealii::Function< dim > &exact_solution)
Definition: darcy/integrators.h:270
virtual void cell(dealii::MeshWorker::DoFInfo< dim > &dinfo, dealii::MeshWorker::IntegrationInfo< dim > &info) const
Definition: darcy/integrators.h:313
const dealii::TensorFunction< 2, dim > *const owned_weight
Definition: darcy/integrators.h:265
dealii::SmartPointer< const dealii::Function< dim > > boundary_function
Definition: darcy/integrators.h:213
void init()
Definition: darcy/integrators.h:300
virtual void boundary(dealii::MeshWorker::DoFInfo< dim > &dinfo, dealii::MeshWorker::IntegrationInfo< dim > &info) const
Definition: darcy/integrators.h:231
Definition: darcy/integrators.h:249
~ErrorIntegrator()
Definition: darcy/integrators.h:289
const dealii::SmartPointer< const dealii::Function< dim > > exact_solution
Definition: darcy/integrators.h:263
~SystemIntegrator()
Definition: darcy/integrators.h:153
void init()
Definition: darcy/integrators.h:164
Definition: estimator.h:33
virtual value_type value(const dealii::Point< dim > &p) const
Definition: darcy/integrators.h:99
Definition: darcy/integrators.h:120
Definition: darcy/integrators.h:77
dealii::TensorFunction< 2, dim >::value_type value_type
Definition: darcy/integrators.h:80
Definition: darcy/integrators.h:204
IdentityTensorFunction()
Definition: darcy/integrators.h:89
dealii::SmartPointer< const dealii::TensorFunction< 2, dim > > weight
Definition: darcy/integrators.h:266
SystemIntegrator()
Definition: darcy/integrators.h:137
const dealii::TensorFunction< 2, dim > *const weight_ptr
Definition: darcy/integrators.h:132
void add_flags(const dealii::UpdateFlags flags)
Add update flags on all objects.
Definition: integrator.h:454
Definition: integrator.h:29