Amandus: Simulations based on multilevel Schwarz methods
integrator.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 amandus_integrator_h
10 #define amandus_integrator_h
11 
12 #include <deal.II/algorithms/any_data.h>
13 #include <deal.II/base/function.h>
14 #include <deal.II/base/quadrature.h>
15 #include <deal.II/base/smartpointer.h>
16 #include <deal.II/base/vector_slice.h>
17 #include <deal.II/fe/block_mask.h>
18 #include <deal.II/integrators/l2.h>
19 #include <deal.II/meshworker/integration_info.h>
20 #include <deal.II/meshworker/local_integrator.h>
21 
22 #include <string>
23 
28 template <int dim>
29 class AmandusIntegrator : public dealii::MeshWorker::LocalIntegrator<dim>
30 {
31 public:
44  virtual void extract_data(const dealii::AnyData& data);
48  double timestep;
49 
54  unsigned int n_errors() const;
55 
62  unsigned int error_type(unsigned int i) const;
63 
67  std::string error_name(unsigned int i) const;
68 
72  dealii::UpdateFlags update_flags() const;
76  dealii::UpdateFlags update_flags_face() const;
80  void add_flags(const dealii::UpdateFlags flags);
84  void add_flags_face(const dealii::UpdateFlags flags);
85 
93  dealii::SmartPointer<dealii::Quadrature<dim>> cell_quadrature;
99  dealii::SmartPointer<dealii::Quadrature<dim - 1>> boundary_quadrature;
105  dealii::SmartPointer<dealii::Quadrature<dim - 1>> face_quadrature;
106 
107 protected:
113  std::vector<unsigned int> error_types;
114 
120  std::vector<std::string> error_names;
121 
122 private:
123  dealii::UpdateFlags u_flags;
124  dealii::UpdateFlags f_flags;
125 };
126 
136 template <int dim>
138 {
139 public:
141  : block_idx(dealii::numbers::invalid_unsigned_int)
142  {
143  }
144 
145  ErrorIntegrator(const dealii::Function<dim>& solution)
146  : block_idx(dealii::numbers::invalid_unsigned_int)
147  , solution(&solution)
148  {
149  this->use_cell = false;
150  this->use_face = false;
151  this->use_boundary = false;
152  }
153 
154  unsigned int
155  size() const
156  {
157  return error_integrators.size();
158  }
159 
160  void
161  add(ErrorIntegrator<dim>* error_integrator)
162  {
163  dealii::ComponentMask new_component_mask(this->solution->n_components, true);
164  this->add(error_integrator, new_component_mask);
165  }
166 
167  void
168  add(ErrorIntegrator<dim>* error_integrator, dealii::ComponentMask new_component_mask)
169  {
170  error_integrator->component_mask = new_component_mask;
171  error_integrator->solution = this->solution;
172  error_integrator->block_idx = error_integrators.size();
173  error_integrators.push_back(error_integrator);
174  this->add_flags(error_integrator->update_flags());
175  this->use_cell = this->use_cell || error_integrator->use_cell;
176  this->use_face = this->use_face || error_integrator->use_face;
177  this->use_boundary = this->use_boundary || error_integrator->use_boundary;
178  }
179 
180  virtual void
181  cell(dealii::MeshWorker::DoFInfo<dim>& dinfo,
182  dealii::MeshWorker::IntegrationInfo<dim>& info) const
183  {
184  for (std::size_t i = 0; i < error_integrators.size(); ++i)
185  {
186  if (error_integrators[i]->use_cell)
187  {
188  error_integrators[i]->cell(dinfo, info);
189  }
190  }
191  }
192 
193  virtual void
194  boundary(dealii::MeshWorker::DoFInfo<dim>& dinfo,
195  dealii::MeshWorker::IntegrationInfo<dim>& info) const
196  {
197  for (std::size_t i = 0; i < error_integrators.size(); ++i)
198  {
199  if (error_integrators[i]->use_boundary)
200  {
201  error_integrators[i]->boundary(dinfo, info);
202  }
203  }
204  }
205 
206  virtual void
207  face(dealii::MeshWorker::DoFInfo<dim>& dinfo1, dealii::MeshWorker::DoFInfo<dim>& dinfo2,
208  dealii::MeshWorker::IntegrationInfo<dim>& info1,
209  dealii::MeshWorker::IntegrationInfo<dim>& info2) const
210  {
211  for (std::size_t i = 0; i < error_integrators.size(); ++i)
212  {
213  if (error_integrators[i]->use_face)
214  {
215  error_integrators[i]->face(dinfo1, dinfo2, info1, info2);
216  }
217  }
218  }
219 
220 protected:
221  dealii::ComponentMask component_mask;
222  unsigned int block_idx;
223  dealii::SmartPointer<const dealii::Function<dim>> solution;
224 
225 private:
226  std::vector<dealii::SmartPointer<ErrorIntegrator<dim>>> error_integrators;
227 };
228 
229 namespace Integrators
230 {
236 template <int dim>
237 class Theta : public AmandusIntegrator<dim>
238 {
239 public:
286  Theta(AmandusIntegrator<dim>& client, bool implicit,
287  dealii::BlockMask blocks = dealii::BlockMask(), bool enforce_homogenity = false);
288  virtual void extract_data(const dealii::AnyData& data);
289 
290 private:
291  virtual void cell(dealii::MeshWorker::DoFInfo<dim>& dinfo,
292  dealii::MeshWorker::IntegrationInfo<dim>& info) const;
293  virtual void boundary(dealii::MeshWorker::DoFInfo<dim>& dinfo,
294  dealii::MeshWorker::IntegrationInfo<dim>& info) const;
295  virtual void face(dealii::MeshWorker::DoFInfo<dim>& dinfo1,
296  dealii::MeshWorker::DoFInfo<dim>& dinfo2,
297  dealii::MeshWorker::IntegrationInfo<dim>& info1,
298  dealii::MeshWorker::IntegrationInfo<dim>& info2) const;
299  dealii::SmartPointer<AmandusIntegrator<dim>, Theta<dim>> client;
301  dealii::BlockMask block_mask;
303 };
304 
305 template <int dim>
307 {
308 public:
310  {
311  this->use_cell = true;
312  this->use_face = false;
313  this->use_boundary = false;
314  this->add_flags(dealii::update_JxW_values | dealii::update_values |
315  dealii::update_quadrature_points);
316  }
317  virtual void cell(dealii::MeshWorker::DoFInfo<dim>& dinfo,
318  dealii::MeshWorker::IntegrationInfo<dim>& info) const;
319 };
320 
321 template <int dim>
322 void
323 L2ErrorIntegrator<dim>::cell(dealii::MeshWorker::DoFInfo<dim>& dinfo,
324  dealii::MeshWorker::IntegrationInfo<dim>& info) const
325 {
326  Assert(info.values.size() >= 1, dealii::ExcDimensionMismatch(info.values.size(), 1));
327 
328  const unsigned int fev_idx = 0;
329  const unsigned int approximation_idx = 0;
330 
331  const std::vector<dealii::Point<dim>>& q_points = info.fe_values(fev_idx).get_quadrature_points();
332  const std::vector<double>& q_weights = info.fe_values(fev_idx).get_JxW_values();
333 
334  std::vector<double> solution_values(q_points.size());
335  for (unsigned int component = 0; component < this->component_mask.size(); ++component)
336  {
337  if (this->component_mask[component])
338  {
339  this->solution->value_list(q_points, solution_values, component);
340  const std::vector<double>& approximation_values = info.values[approximation_idx][component];
341  for (std::size_t q = 0; q < q_points.size(); ++q)
342  {
343  double error = solution_values[q] - approximation_values[q];
344  dinfo.value(this->block_idx) += error * error * q_weights[q];
345  }
346  }
347  }
348  dinfo.value(this->block_idx) = std::sqrt(dinfo.value(this->block_idx));
349 }
350 
351 template <int dim>
353 {
354 public:
356  {
357  this->use_cell = true;
358  this->use_face = false;
359  this->use_boundary = false;
360  this->add_flags(dealii::update_JxW_values | dealii::update_gradients |
361  dealii::update_quadrature_points);
362  }
363 
364  virtual void cell(dealii::MeshWorker::DoFInfo<dim>& dinfo,
365  dealii::MeshWorker::IntegrationInfo<dim>& info) const;
366 };
367 
368 template <int dim>
369 void
370 H1ErrorIntegrator<dim>::cell(dealii::MeshWorker::DoFInfo<dim>& dinfo,
371  dealii::MeshWorker::IntegrationInfo<dim>& info) const
372 {
373  Assert(info.values.size() >= 1, dealii::ExcDimensionMismatch(info.values.size(), 1));
374 
375  const unsigned int fev_idx = 0;
376  const unsigned int approximation_idx = 0;
377 
378  const std::vector<dealii::Point<dim>>& q_points = info.fe_values(fev_idx).get_quadrature_points();
379  const std::vector<double>& q_weights = info.fe_values(fev_idx).get_JxW_values();
380 
381  std::vector<dealii::Tensor<1, dim, double>> solution_grads(q_points.size());
382  for (unsigned int component = 0; component < this->component_mask.size(); ++component)
383  {
384  if (this->component_mask[component])
385  {
386  this->solution->gradient_list(q_points, solution_grads, component);
387  const std::vector<dealii::Tensor<1, dim, double>>& approximation_grads =
388  info.gradients[approximation_idx][component];
389  for (std::size_t q = 0; q < q_points.size(); ++q)
390  {
391  double error = (solution_grads[q] - approximation_grads[q]).norm();
392  dinfo.value(this->block_idx) += error * error * q_weights[q];
393  }
394  }
395  }
396  dinfo.value(this->block_idx) = std::sqrt(dinfo.value(this->block_idx));
397 }
398 }
399 
400 // TODO: Update flags should be set by derived classes with add_flags. Right
401 // now some update flags are always set by this constructor. For
402 // compatibility keep it this way until the applications are adjusted.
403 template <int dim>
405  : timestep(0.)
406  , cell_quadrature(0)
408  , face_quadrature(0)
409  , u_flags(dealii::update_JxW_values | dealii::update_values | dealii::update_gradients |
410  dealii::update_quadrature_points)
411 {
412 }
413 
414 template <int dim>
415 inline dealii::UpdateFlags
417 {
418  return u_flags;
419 }
420 
421 template <int dim>
422 inline dealii::UpdateFlags
424 {
425  return f_flags;
426 }
427 
428 template <int dim>
429 inline unsigned int
431 {
432  return error_types.size();
433 }
434 
435 template <int dim>
436 inline unsigned int
438 {
439  AssertIndexRange(i, n_errors());
440  return error_types[i];
441 }
442 
443 template <int dim>
444 inline std::string
446 {
447  if (error_names.size() > i)
448  return error_names[i];
449  return std::string();
450 }
451 
452 template <int dim>
453 inline void
454 AmandusIntegrator<dim>::add_flags(const dealii::UpdateFlags flags)
455 {
456  u_flags |= flags;
457 }
458 
459 template <int dim>
460 inline void
461 AmandusIntegrator<dim>::add_flags_face(const dealii::UpdateFlags flags)
462 {
463  f_flags |= flags;
464 }
465 
466 template <int dim>
467 inline void
468 AmandusIntegrator<dim>::extract_data(const dealii::AnyData& data)
469 {
470  const double* ts = data.try_read_ptr<double>("Timestep");
471  if (ts != 0)
472  {
473  timestep = *ts;
474  }
475 }
476 
477 namespace Integrators
478 {
479 template <int dim>
480 inline Theta<dim>::Theta(AmandusIntegrator<dim>& cl, bool implicit, dealii::BlockMask blocks,
481  bool enforce_homogenity)
482  : client(&cl)
483  , block_mask(blocks)
484  , enforce_homogenity(enforce_homogenity)
485 {
486  is_implicit = implicit;
487  this->use_cell = client->use_cell;
488  this->use_boundary = client->use_boundary;
489  this->use_face = client->use_face;
490 
491  this->add_flags(client->update_flags());
492 }
493 
494 template <int dim>
495 inline void
496 Theta<dim>::extract_data(const dealii::AnyData& data)
497 {
498  client->extract_data(data);
499  const double* ts = data.try_read_ptr<double>("Timestep");
500  if (ts != 0)
501  {
502  this->timestep = *ts;
503  }
504 }
505 
506 template <int dim>
507 void
508 Theta<dim>::cell(dealii::MeshWorker::DoFInfo<dim>& dinfo,
509  dealii::MeshWorker::IntegrationInfo<dim>& info) const
510 {
511  client->cell(dinfo, info);
512  const double factor = is_implicit ? this->timestep : -this->timestep;
513  for (unsigned int i = 0; i < dinfo.n_vectors(); ++i)
514  dinfo.vector(i) *= factor;
515  for (unsigned int i = 0; i < dinfo.n_matrices(); ++i)
516  dinfo.matrix(i, false).matrix *= factor;
517 
518  const dealii::FiniteElement<dim>& fe = info.finite_element();
519 
520  unsigned int comp = 0;
521  for (unsigned int b = 0; b < fe.n_base_elements(); ++b)
522  {
523  unsigned int k = fe.first_block_of_base(b);
524  const dealii::FiniteElement<dim>& base = fe.base_element(b);
525  for (unsigned int m = 0; m < fe.element_multiplicity(b); ++m)
526  {
527  unsigned int block_idx = k + m;
528  if (this->block_mask[block_idx]) // add mass operator
529  {
530  for (unsigned int i = 0; i < dinfo.n_vectors(); ++i)
531  {
532  dealii::LocalIntegrators::L2::L2(
533  dinfo.vector(i).block(block_idx),
534  info.fe_values(b),
535  dealii::make_slice(info.values[0], comp, base.n_components()));
536  }
537 
538  for (unsigned int i = 0; i < dinfo.n_matrices(); ++i)
539  {
540  dealii::MatrixBlock<dealii::FullMatrix<double>>& local_matrix_block =
541  dinfo.matrix(i, false);
542  if (local_matrix_block.row == block_idx && local_matrix_block.column == block_idx)
543  {
544  dealii::LocalIntegrators::L2::mass_matrix(local_matrix_block.matrix, info.fe_values(b));
545  }
546  }
547  }
548  else if (this->enforce_homogenity && !this->is_implicit)
549  {
550  for (unsigned int i = 0; i < dinfo.n_vectors(); ++i)
551  {
552  dinfo.vector(i).block(block_idx) = 0.0;
553  }
554  }
555  comp += base.n_components();
556  }
557  }
558 }
559 
560 template <int dim>
561 void
562 Theta<dim>::boundary(dealii::MeshWorker::DoFInfo<dim>& dinfo,
563  dealii::MeshWorker::IntegrationInfo<dim>& info) const
564 {
565  client->boundary(dinfo, info);
566  const double factor = is_implicit ? this->timestep : -this->timestep;
567  for (unsigned int i = 0; i < dinfo.n_vectors(); ++i)
568  dinfo.vector(i) *= factor;
569  for (unsigned int i = 0; i < dinfo.n_matrices(); ++i)
570  dinfo.matrix(i, false).matrix *= factor;
571 }
572 
573 template <int dim>
574 void
575 Theta<dim>::face(dealii::MeshWorker::DoFInfo<dim>& dinfo1, dealii::MeshWorker::DoFInfo<dim>& dinfo2,
576  dealii::MeshWorker::IntegrationInfo<dim>& info1,
577  dealii::MeshWorker::IntegrationInfo<dim>& info2) const
578 {
579  client->face(dinfo1, dinfo2, info1, info2);
580  const double factor = is_implicit ? this->timestep : -this->timestep;
581  for (unsigned int i = 0; i < dinfo2.n_vectors(); ++i)
582  {
583  dinfo1.vector(i) *= factor;
584  dinfo2.vector(i) *= factor;
585  }
586  for (unsigned int i = 0; i < dinfo1.n_matrices(); ++i)
587  {
588  dinfo1.matrix(i, false).matrix *= factor;
589  dinfo1.matrix(i, true).matrix *= factor;
590  dinfo2.matrix(i, false).matrix *= factor;
591  dinfo2.matrix(i, true).matrix *= factor;
592  }
593 }
594 
598 template <int dim>
599 class MeanIntegrator : public dealii::MeshWorker::LocalIntegrator<dim>
600 {
601 public:
603  : dealii::MeshWorker::LocalIntegrator<dim>(true, false, false)
604  {
605  }
606 
607  virtual void
608  cell(dealii::MeshWorker::DoFInfo<dim>& dinfo,
609  dealii::MeshWorker::IntegrationInfo<dim>& info) const
610  {
611  // this only works for scalars fe values
612  const std::vector<double> one(info.fe_values(0).n_quadrature_points, 1.0);
613  for (unsigned int i = 0; i < dinfo.vector(0).n_blocks(); ++i)
614  if (info.fe_values(i).get_fe().n_components() == 1)
615  dealii::LocalIntegrators::L2::L2(dinfo.vector(0).block(i), info.fe_values(i), one);
616  }
617 };
618 }
619 
620 #endif
dealii::SmartPointer< const dealii::Function< dim > > solution
Definition: integrator.h:223
Definition: integrator.h:137
dealii::SmartPointer< dealii::Quadrature< dim > > cell_quadrature
Quadrature rule used on cells.
Definition: integrator.h:93
Definition: integrator.h:237
void add(ErrorIntegrator< dim > *error_integrator)
Definition: integrator.h:161
ErrorIntegrator()
Definition: integrator.h:140
std::vector< std::string > error_names
Definition: integrator.h:120
L2ErrorIntegrator()
Definition: integrator.h:309
Definition: integrator.h:352
dealii::ComponentMask component_mask
Definition: integrator.h:221
dealii::SmartPointer< dealii::Quadrature< dim-1 > > boundary_quadrature
Quadrature rule used on boundary faces.
Definition: integrator.h:99
virtual void extract_data(const dealii::AnyData &data)
Extract data independent of the cell.
Definition: integrator.h:496
Definition: integrator.h:229
dealii::UpdateFlags f_flags
Definition: integrator.h:124
AmandusIntegrator()
Definition: integrator.h:404
dealii::UpdateFlags update_flags_face() const
Returns the update flags to be used on boundary and interior faces.
Definition: integrator.h:423
double timestep
Current timestep if applicable.
Definition: integrator.h:48
unsigned int size() const
Definition: integrator.h:155
dealii::SmartPointer< dealii::Quadrature< dim-1 > > face_quadrature
Quadrature rule used on faces.
Definition: integrator.h:105
std::string error_name(unsigned int i) const
Definition: integrator.h:445
bool enforce_homogenity
Definition: integrator.h:302
virtual void face(dealii::MeshWorker::DoFInfo< dim > &dinfo1, dealii::MeshWorker::DoFInfo< dim > &dinfo2, dealii::MeshWorker::IntegrationInfo< dim > &info1, dealii::MeshWorker::IntegrationInfo< dim > &info2) const
Definition: integrator.h:207
H1ErrorIntegrator()
Definition: integrator.h:355
void add_flags_face(const dealii::UpdateFlags flags)
Add update flags on boundary and internal faces.
Definition: integrator.h:461
virtual void cell(dealii::MeshWorker::DoFInfo< dim > &dinfo, dealii::MeshWorker::IntegrationInfo< dim > &info) const
Definition: integrator.h:508
virtual void face(dealii::MeshWorker::DoFInfo< dim > &dinfo1, dealii::MeshWorker::DoFInfo< dim > &dinfo2, dealii::MeshWorker::IntegrationInfo< dim > &info1, dealii::MeshWorker::IntegrationInfo< dim > &info2) const
Definition: integrator.h:575
MeanIntegrator()
Definition: integrator.h:602
bool is_implicit
Definition: integrator.h:300
dealii::UpdateFlags update_flags() const
Returns the update flags to be used.
Definition: integrator.h:416
virtual void boundary(dealii::MeshWorker::DoFInfo< dim > &dinfo, dealii::MeshWorker::IntegrationInfo< dim > &info) const
Definition: integrator.h:194
std::vector< dealii::SmartPointer< ErrorIntegrator< dim > > > error_integrators
Definition: integrator.h:226
virtual void cell(dealii::MeshWorker::DoFInfo< dim > &dinfo, dealii::MeshWorker::IntegrationInfo< dim > &info) const
Definition: integrator.h:181
std::vector< unsigned int > error_types
Definition: integrator.h:113
Definition: integrator.h:306
Definition: integrator.h:599
unsigned int n_errors() const
Definition: integrator.h:430
void add(ErrorIntegrator< dim > *error_integrator, dealii::ComponentMask new_component_mask)
Definition: integrator.h:168
virtual void cell(dealii::MeshWorker::DoFInfo< dim > &dinfo, dealii::MeshWorker::IntegrationInfo< dim > &info) const
Definition: integrator.h:608
ErrorIntegrator(const dealii::Function< dim > &solution)
Definition: integrator.h:145
unsigned int block_idx
Definition: integrator.h:222
virtual void boundary(dealii::MeshWorker::DoFInfo< dim > &dinfo, dealii::MeshWorker::IntegrationInfo< dim > &info) const
Definition: integrator.h:562
virtual void extract_data(const dealii::AnyData &data)
Extract data independent of the cell.
Definition: integrator.h:468
dealii::BlockMask block_mask
Definition: integrator.h:301
unsigned int error_type(unsigned int i) const
Definition: integrator.h:437
void add_flags(const dealii::UpdateFlags flags)
Add update flags on all objects.
Definition: integrator.h:454
dealii::SmartPointer< AmandusIntegrator< dim >, Theta< dim > > client
Definition: integrator.h:299
Definition: integrator.h:29
dealii::UpdateFlags u_flags
Definition: integrator.h:123