Amandus: Simulations based on multilevel Schwarz methods
laplace/eigen.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 __matrix_laplace_h
8 #define __matrix_laplace_h
9 
10 #include <amandus/integrator.h>
11 #include <deal.II/integrators/divergence.h>
12 #include <deal.II/integrators/l2.h>
13 #include <deal.II/integrators/laplace.h>
14 #include <deal.II/meshworker/integration_info.h>
15 
16 using namespace dealii;
17 using namespace LocalIntegrators;
18 
20 {
32 template <int dim>
33 class Eigen : public AmandusIntegrator<dim>
34 {
35  double shift;
36 
37 public:
38  Eigen(double shift = 0.)
39  : shift(shift)
40  {
41  }
42 
43  virtual void cell(MeshWorker::DoFInfo<dim>& dinfo, MeshWorker::IntegrationInfo<dim>& info) const;
44  virtual void boundary(MeshWorker::DoFInfo<dim>& dinfo,
45  MeshWorker::IntegrationInfo<dim>& info) const;
46  virtual void face(MeshWorker::DoFInfo<dim>& dinfo1, MeshWorker::DoFInfo<dim>& dinfo2,
47  MeshWorker::IntegrationInfo<dim>& info1,
48  MeshWorker::IntegrationInfo<dim>& info2) const;
49 };
50 
51 template <int dim>
52 void
53 Eigen<dim>::cell(MeshWorker::DoFInfo<dim>& dinfo, MeshWorker::IntegrationInfo<dim>& info) const
54 {
55  Laplace::cell_matrix(dinfo.matrix(0, false).matrix, info.fe_values(0));
56  L2::mass_matrix(dinfo.matrix(0, false).matrix, info.fe_values(0), -shift);
57  if (dinfo.n_matrices() == 2)
58  L2::mass_matrix(dinfo.matrix(1, false).matrix, info.fe_values(0));
59 }
60 
61 template <int dim>
62 void
63 Eigen<dim>::boundary(MeshWorker::DoFInfo<dim>& dinfo,
64  typename MeshWorker::IntegrationInfo<dim>& info) const
65 {
66  const unsigned int deg = info.fe_values(0).get_fe().tensor_degree();
67  Laplace::nitsche_matrix(dinfo.matrix(0, false).matrix,
68  info.fe_values(0),
69  Laplace::compute_penalty(dinfo, dinfo, deg, deg));
70 }
71 
72 template <int dim>
73 void
74 Eigen<dim>::face(MeshWorker::DoFInfo<dim>& dinfo1, MeshWorker::DoFInfo<dim>& dinfo2,
75  MeshWorker::IntegrationInfo<dim>& info1,
76  MeshWorker::IntegrationInfo<dim>& info2) const
77 {
78  const unsigned int deg = info1.fe_values(0).get_fe().tensor_degree();
79  Laplace::ip_matrix(dinfo1.matrix(0, false).matrix,
80  dinfo1.matrix(0, true).matrix,
81  dinfo2.matrix(0, true).matrix,
82  dinfo2.matrix(0, false).matrix,
83  info1.fe_values(0),
84  info2.fe_values(0),
85  Laplace::compute_penalty(dinfo1, dinfo2, deg, deg));
86 }
87 
88 /*
89  * Estimator implemented for real eigenvalues only
90  */
91 template <int dim>
92 class EigenEstimate : public AmandusIntegrator<dim>
93 {
94 public:
95  EigenEstimate();
96  virtual void cell(MeshWorker::DoFInfo<dim>& dinfo, MeshWorker::IntegrationInfo<dim>& info) const;
97  virtual void boundary(MeshWorker::DoFInfo<dim>& dinfo,
98  MeshWorker::IntegrationInfo<dim>& info) const;
99  virtual void face(MeshWorker::DoFInfo<dim>& dinfo1, MeshWorker::DoFInfo<dim>& dinfo2,
100  MeshWorker::IntegrationInfo<dim>& info1,
101  MeshWorker::IntegrationInfo<dim>& info2) const;
102 
103 private:
104  virtual void extract_data(const dealii::AnyData& data);
105  std::vector<double> ev;
106 };
107 
108 template <int dim>
110 {
111  ev.clear();
112  this->use_boundary = true;
113  this->use_face = true;
114  this->add_flags(update_hessians);
115 }
116 
117 template <int dim>
118 inline void
120 {
121  const unsigned int k = MeshWorker::LocalIntegrator<dim>::input_vector_names.size();
122  ev.resize(k);
123  for (unsigned int i = 0; i < k; ++i)
124  {
125  const double* tmp = data.try_read_ptr<double>(std::string("ev") + std::to_string(i));
126  if (tmp != 0)
127  {
128  ev[i] = *tmp;
129  }
130  }
131 }
132 
133 template <int dim>
134 void
135 EigenEstimate<dim>::cell(MeshWorker::DoFInfo<dim>& dinfo,
136  MeshWorker::IntegrationInfo<dim>& info) const
137 {
138  const FEValuesBase<dim>& fe = info.fe_values();
139 
140  for (unsigned int i = 0; i < ev.size(); ++i)
141  {
142  const std::vector<double>& uh = info.values[i][0];
143  const std::vector<Tensor<2, dim>>& DDuh = info.hessians[i][0];
144 
145  for (unsigned k = 0; k < fe.n_quadrature_points; ++k)
146  {
147  const double t = dinfo.cell->diameter() * (trace(DDuh[k]) + ev[i] * uh[k]);
148  dinfo.value(0) += t * t * fe.JxW(k);
149  }
150  }
151  dinfo.value(0) = std::sqrt(dinfo.value(0));
152 }
153 
154 template <int dim>
155 void
156 EigenEstimate<dim>::boundary(MeshWorker::DoFInfo<dim>& dinfo,
157  MeshWorker::IntegrationInfo<dim>& info) const
158 {
159  const FEValuesBase<dim>& fe = info.fe_values();
160  const unsigned int deg = fe.get_fe().tensor_degree();
161  const double penalty = Laplace::compute_penalty(dinfo, dinfo, deg, deg);
162 
163  for (unsigned int i = 0; i < ev.size(); ++i)
164  {
165  const std::vector<double>& uh = info.values[i][0];
166 
167  for (unsigned k = 0; k < fe.n_quadrature_points; ++k)
168  dinfo.value(0) += penalty * uh[k] * uh[k] * fe.JxW(k);
169  }
170  dinfo.value(0) = std::sqrt(dinfo.value(0));
171 }
172 
173 template <int dim>
174 void
175 EigenEstimate<dim>::face(MeshWorker::DoFInfo<dim>& dinfo1, MeshWorker::DoFInfo<dim>& dinfo2,
176  MeshWorker::IntegrationInfo<dim>& info1,
177  MeshWorker::IntegrationInfo<dim>& info2) const
178 {
179  const FEValuesBase<dim>& fe = info1.fe_values();
180  const unsigned int deg1 = info1.fe_values().get_fe().tensor_degree();
181  const unsigned int deg2 = info2.fe_values().get_fe().tensor_degree();
182  const double penalty = 2. * Laplace::compute_penalty(dinfo1, dinfo2, deg1, deg2);
183  double h;
184  if (dim == 3)
185  h = std::sqrt(dinfo1.face->measure());
186  else
187  h = dinfo1.face->measure();
188 
189  for (unsigned int i = 0; i < ev.size(); ++i)
190  {
191  const std::vector<double>& uh1 = info1.values[i][0];
192  const std::vector<double>& uh2 = info2.values[i][0];
193  const std::vector<Tensor<1, dim>>& Duh1 = info1.gradients[i][0];
194  const std::vector<Tensor<1, dim>>& Duh2 = info2.gradients[i][0];
195 
196  for (unsigned k = 0; k < fe.n_quadrature_points; ++k)
197  {
198  double diff1 = uh1[k] - uh2[k];
199  double diff2 = fe.normal_vector(k) * Duh1[k] - fe.normal_vector(k) * Duh2[k];
200  dinfo1.value(0) += (penalty * diff1 * diff1 + h * diff2 * diff2) * fe.JxW(k);
201  }
202  }
203  dinfo1.value(0) = std::sqrt(dinfo1.value(0));
204  dinfo2.value(0) = dinfo1.value(0);
205 }
206 }
207 
208 #endif
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
Definition: laplace/eigen.h:19
Eigen(double shift=0.)
Definition: laplace/eigen.h:38
std::vector< double > ev
Definition: laplace/eigen.h:105
virtual void cell(MeshWorker::DoFInfo< dim > &dinfo, MeshWorker::IntegrationInfo< dim > &info) const
Definition: laplace/eigen.h:135
double shift
Definition: laplace/eigen.h:35
Definition: laplace/eigen.h:92
Integrator for eigenvalue problems.
Definition: laplace/eigen.h:33
Definition: integrator.h:29