dune-pdelab  2.4.1-rc2
convectiondiffusionfem.hh
Go to the documentation of this file.
1 // -*- tab-width: 4; indent-tabs-mode: nil -*-
2 #ifndef DUNE_PDELAB_CONVECTIONDIFFUSIONFEM_HH
3 #define DUNE_PDELAB_CONVECTIONDIFFUSIONFEM_HH
4 
5 #include<vector>
6 
14 
16 
17 namespace Dune {
18  namespace PDELab {
19 
34  template<typename T, typename FiniteElementMap>
36  public Dune::PDELab::NumericalJacobianApplyVolume<ConvectionDiffusionFEM<T,FiniteElementMap> >,
37  public Dune::PDELab::NumericalJacobianApplyBoundary<ConvectionDiffusionFEM<T,FiniteElementMap> >,
38  public Dune::PDELab::NumericalJacobianVolume<ConvectionDiffusionFEM<T,FiniteElementMap> >,
39  public Dune::PDELab::NumericalJacobianBoundary<ConvectionDiffusionFEM<T,FiniteElementMap> >,
42  public Dune::PDELab::InstationaryLocalOperatorDefaultMethods<typename T::Traits::RangeFieldType>
43  {
44  public:
45  // pattern assembly flags
46  enum { doPatternVolume = true };
47 
48  // residual assembly flags
49  enum { doAlphaVolume = true };
50  enum { doAlphaBoundary = true };
51 
52  ConvectionDiffusionFEM (T& param_, int intorderadd_=0)
53  : param(param_), intorderadd(intorderadd_)
54  {
55  }
56 
57  // volume integral depending on test and ansatz functions
58  template<typename EG, typename LFSU, typename X, typename LFSV, typename R>
59  void alpha_volume (const EG& eg, const LFSU& lfsu, const X& x, const LFSV& lfsv, R& r) const
60  {
61  // domain and range field type
62  typedef typename LFSU::Traits::FiniteElementType::
63  Traits::LocalBasisType::Traits::RangeFieldType RF;
64 
65  typedef typename LFSU::Traits::SizeType size_type;
66 
67  // dimensions
68  const int dim = EG::Entity::dimension;
69 
70  // select quadrature rule
71  auto geo = eg.geometry();
72  auto intorder = intorderadd+2*lfsu.finiteElement().localBasis().order();
73 
74  // evaluate diffusion tensor at cell center, assume it is constant over elements
75  auto ref_el = referenceElement(geo);
76  auto localcenter = ref_el.position(0,0);
77  auto tensor = param.A(eg.entity(),localcenter);
78 
79  // loop over quadrature points
80  for (const auto& ip : quadratureRule(geo,intorder))
81  {
82  // evaluate basis functions
83  // std::vector<RangeType> phi(lfsu.size());
84  // lfsu.finiteElement().localBasis().evaluateFunction(ip.position(),phi);
85  auto& phi = cache.evaluateFunction(ip.position(),lfsu.finiteElement().localBasis());
86 
87  // evaluate u
88  RF u=0.0;
89  for (size_type i=0; i<lfsu.size(); i++)
90  u += x(lfsu,i)*phi[i];
91 
92  // evaluate gradient of shape functions (we assume Galerkin method lfsu=lfsv)
93  // std::vector<JacobianType> js(lfsu.size());
94  // lfsu.finiteElement().localBasis().evaluateJacobian(ip.position(),js);
95  auto& js = cache.evaluateJacobian(ip.position(),lfsu.finiteElement().localBasis());
96 
97  // transform gradients of shape functions to real element
98  auto jac = geo.jacobianInverseTransposed(ip.position());
99 
100  std::vector<Dune::FieldVector<RF,dim> > gradphi(lfsu.size());
101  for (size_type i=0; i<lfsu.size(); i++)
102  jac.mv(js[i][0],gradphi[i]);
103 
104  // compute gradient of u
105  Dune::FieldVector<RF,dim> gradu(0.0);
106  for (size_type i=0; i<lfsu.size(); i++)
107  gradu.axpy(x(lfsu,i),gradphi[i]);
108 
109  // compute A * gradient of u
110  Dune::FieldVector<RF,dim> Agradu(0.0);
111  tensor.umv(gradu,Agradu);
112 
113  // evaluate velocity field, sink term and source term
114  auto b = param.b(eg.entity(),ip.position());
115  auto c = param.c(eg.entity(),ip.position());
116  auto f = param.f(eg.entity(),ip.position());
117 
118  // integrate (A grad u)*grad phi_i - u b*grad phi_i + c*u*phi_i
119  RF factor = ip.weight() * geo.integrationElement(ip.position());
120  for (size_type i=0; i<lfsu.size(); i++)
121  r.accumulate(lfsu,i,( Agradu*gradphi[i] - u*(b*gradphi[i]) + (c*u-f)*phi[i] )*factor);
122  }
123  }
124 
125  // jacobian of volume term
126  template<typename EG, typename LFSU, typename X, typename LFSV, typename M>
127  void jacobian_volume (const EG& eg, const LFSU& lfsu, const X& x, const LFSV& lfsv,
128  M& mat) const
129  {
130  // domain and range field type
131  typedef typename LFSU::Traits::FiniteElementType::
132  Traits::LocalBasisType::Traits::DomainFieldType DF;
133  typedef typename LFSU::Traits::FiniteElementType::
134  Traits::LocalBasisType::Traits::RangeFieldType RF;
135  typedef typename LFSU::Traits::FiniteElementType::
136  Traits::LocalBasisType::Traits::JacobianType JacobianType;
137  typedef typename LFSU::Traits::FiniteElementType::
138  Traits::LocalBasisType::Traits::RangeType RangeType;
139  typedef typename LFSU::Traits::SizeType size_type;
140 
141  // dimensions
142  const int dim = EG::Entity::dimension;
143 
144  // select quadrature rule
145  Dune::GeometryType gt = eg.geometry().type();
146  const int intorder = intorderadd+2*lfsu.finiteElement().localBasis().order();
147  const Dune::QuadratureRule<DF,dim>& rule = Dune::QuadratureRules<DF,dim>::rule(gt,intorder);
148 
149  // evaluate diffusion tensor at cell center, assume it is constant over elements
150  typename T::Traits::PermTensorType tensor;
151  Dune::FieldVector<DF,dim> localcenter = Dune::ReferenceElements<DF,dim>::general(gt).position(0,0);
152  tensor = param.A(eg.entity(),localcenter);
153 
154  // loop over quadrature points
155  for (const auto& ip : rule)
156  {
157  // evaluate gradient of shape functions (we assume Galerkin method lfsu=lfsv)
158  // std::vector<JacobianType> js(lfsu.size());
159  // lfsu.finiteElement().localBasis().evaluateJacobian(ip.position(),js);
160  const std::vector<JacobianType>& js = cache.evaluateJacobian(ip.position(),lfsu.finiteElement().localBasis());
161 
162  // transform gradient to real element
163  const typename EG::Geometry::JacobianInverseTransposed jac
164  = eg.geometry().jacobianInverseTransposed(ip.position());
165  std::vector<Dune::FieldVector<RF,dim> > gradphi(lfsu.size());
166  std::vector<Dune::FieldVector<RF,dim> > Agradphi(lfsu.size());
167  for (size_type i=0; i<lfsu.size(); i++)
168  {
169  jac.mv(js[i][0],gradphi[i]);
170  tensor.mv(gradphi[i],Agradphi[i]);
171  }
172 
173  // evaluate basis functions
174  // std::vector<RangeType> phi(lfsu.size());
175  // lfsu.finiteElement().localBasis().evaluateFunction(ip.position(),phi);
176  const std::vector<RangeType>& phi = cache.evaluateFunction(ip.position(),lfsu.finiteElement().localBasis());
177 
178  // evaluate velocity field, sink term and source te
179  typename T::Traits::RangeType b = param.b(eg.entity(),ip.position());
180  typename T::Traits::RangeFieldType c = param.c(eg.entity(),ip.position());
181 
182  // integrate (A grad phi_j)*grad phi_i - phi_j b*grad phi_i + c*phi_j*phi_i
183  RF factor = ip.weight() * eg.geometry().integrationElement(ip.position());
184  for (size_type j=0; j<lfsu.size(); j++)
185  for (size_type i=0; i<lfsu.size(); i++)
186  mat.accumulate(lfsu,i,lfsu,j,( Agradphi[j]*gradphi[i]-phi[j]*(b*gradphi[i])+c*phi[j]*phi[i] )*factor);
187  }
188  }
189 
190  // boundary integral
191  template<typename IG, typename LFSU, typename X, typename LFSV, typename R>
192  void alpha_boundary (const IG& ig,
193  const LFSU& lfsu_s, const X& x_s, const LFSV& lfsv_s,
194  R& r_s) const
195  {
196  // domain and range field type
197  typedef typename LFSV::Traits::FiniteElementType::
198  Traits::LocalBasisType::Traits::DomainFieldType DF;
199  typedef typename LFSV::Traits::FiniteElementType::
200  Traits::LocalBasisType::Traits::RangeFieldType RF;
201  typedef typename LFSV::Traits::FiniteElementType::
202  Traits::LocalBasisType::Traits::RangeType RangeType;
203 
204  typedef typename LFSV::Traits::SizeType size_type;
205 
206  // dimensions
207  const int dim = IG::dimension;
208 
209  // get cell entity
210  auto inside_cell = ig.inside();
211 
212  // evaluate boundary condition type
213  Dune::GeometryType gtface = ig.geometryInInside().type();
214  Dune::FieldVector<DF,dim-1> facecenterlocal = Dune::ReferenceElements<DF,dim-1>::general(gtface).position(0,0);
216  bctype = param.bctype(ig.intersection(),facecenterlocal);
217 
218  // skip rest if we are on Dirichlet boundary
220 
221  // select quadrature rule
222  const int intorder = intorderadd+2*lfsu_s.finiteElement().localBasis().order();
223  const Dune::QuadratureRule<DF,dim-1>& rule = Dune::QuadratureRules<DF,dim-1>::rule(gtface,intorder);
224 
225  // loop over quadrature points and integrate normal flux
226  for (const auto& ip : rule)
227  {
228  // position of quadrature point in local coordinates of element
229  Dune::FieldVector<DF,dim> local = ig.geometryInInside().global(ip.position());
230 
231  // evaluate shape functions (assume Galerkin method)
232  // std::vector<RangeType> phi(lfsu_s.size());
233  // lfsu_s.finiteElement().localBasis().evaluateFunction(local,phi);
234  const std::vector<RangeType>& phi = cache.evaluateFunction(local,lfsu_s.finiteElement().localBasis());
235 
237  {
238  // evaluate flux boundary condition
239  typename T::Traits::RangeFieldType j = param.j(ig.intersection(),ip.position());
240 
241  // integrate j
242  RF factor = ip.weight()*ig.geometry().integrationElement(ip.position());
243  for (size_type i=0; i<lfsu_s.size(); i++)
244  r_s.accumulate(lfsu_s,i,j*phi[i]*factor);
245  }
246 
248  {
249  // evaluate u
250  RF u=0.0;
251  for (size_type i=0; i<lfsu_s.size(); i++)
252  u += x_s(lfsu_s,i)*phi[i];
253 
254  // evaluate velocity field and outer unit normal
255  typename T::Traits::RangeType b = param.b(inside_cell,local);
256  const Dune::FieldVector<DF,dim> n = ig.unitOuterNormal(ip.position());
257 
258  // evaluate outflow boundary condition
259  typename T::Traits::RangeFieldType o = param.o(ig.intersection(),ip.position());
260 
261  // integrate o
262  RF factor = ip.weight()*ig.geometry().integrationElement(ip.position());
263  for (size_type i=0; i<lfsu_s.size(); i++)
264  r_s.accumulate(lfsu_s,i,( (b*n)*u + o)*phi[i]*factor);
265  }
266  }
267  }
268 
269  // jacobian contribution from boundary
270  template<typename IG, typename LFSU, typename X, typename LFSV, typename M>
271  void jacobian_boundary (const IG& ig,
272  const LFSU& lfsu_s, const X& x_s, const LFSV& lfsv_s,
273  M& mat_s) const
274  {
275  // domain and range field type
276  typedef typename LFSV::Traits::FiniteElementType::
277  Traits::LocalBasisType::Traits::DomainFieldType DF;
278  typedef typename LFSV::Traits::FiniteElementType::
279  Traits::LocalBasisType::Traits::RangeFieldType RF;
280  typedef typename LFSV::Traits::FiniteElementType::
281  Traits::LocalBasisType::Traits::RangeType RangeType;
282 
283  typedef typename LFSV::Traits::SizeType size_type;
284 
285  // dimensions
286  const int dim = IG::dimension;
287 
288  // get cell entity
289  auto inside_cell = ig.inside();
290 
291  // evaluate boundary condition type
292  Dune::GeometryType gtface = ig.geometryInInside().type();
293  Dune::FieldVector<DF,dim-1> facecenterlocal = Dune::ReferenceElements<DF,dim-1>::general(gtface).position(0,0);
295  bctype = param.bctype(ig.intersection(),facecenterlocal);
296 
297  // skip rest if we are on Dirichlet boundary
300 
301  // select quadrature rule
302  const int intorder = intorderadd+2*lfsu_s.finiteElement().localBasis().order();
303  const Dune::QuadratureRule<DF,dim-1>& rule = Dune::QuadratureRules<DF,dim-1>::rule(gtface,intorder);
304 
305  // loop over quadrature points and integrate normal flux
306  for (const auto& ip : rule)
307  {
308  // position of quadrature point in local coordinates of element
309  Dune::FieldVector<DF,dim> local = ig.geometryInInside().global(ip.position());
310 
311  // evaluate shape functions (assume Galerkin method)
312  // std::vector<RangeType> phi(lfsu_s.size());
313  // lfsu_s.finiteElement().localBasis().evaluateFunction(local,phi);
314  const std::vector<RangeType>& phi = cache.evaluateFunction(local,lfsu_s.finiteElement().localBasis());
315 
316  // evaluate velocity field and outer unit normal
317  typename T::Traits::RangeType b = param.b(inside_cell,local);
318  const Dune::FieldVector<DF,dim> n = ig.unitOuterNormal(ip.position());
319 
320  // integrate
321  RF factor = ip.weight()*ig.geometry().integrationElement(ip.position());
322  for (size_type j=0; j<lfsu_s.size(); j++)
323  for (size_type i=0; i<lfsu_s.size(); i++)
324  mat_s.accumulate(lfsu_s,i,lfsu_s,j,(b*n)*phi[j]*phi[i]*factor);
325  }
326  }
327 
328 
330  void setTime (double t)
331  {
332  param.setTime(t);
333  }
334 
335  private:
336  T& param;
337  int intorderadd;
338  typedef typename FiniteElementMap::Traits::FiniteElementType::Traits::LocalBasisType LocalBasisType;
340  };
341 
342 
343 
359  template<typename T>
362  {
363  enum { dim = T::Traits::GridViewType::dimension };
364 
365  typedef typename T::Traits::RangeFieldType Real;
367 
368  public:
369  // pattern assembly flags
370  enum { doPatternVolume = false };
371  enum { doPatternSkeleton = false };
372 
373  // residual assembly flags
374  enum { doAlphaVolume = true };
375  enum { doAlphaSkeleton = true };
376  enum { doAlphaBoundary = true };
377 
380  : param(param_)
381  {}
382 
383  // volume integral depending on test and ansatz functions
384  template<typename EG, typename LFSU, typename X, typename LFSV, typename R>
385  void alpha_volume (const EG& eg, const LFSU& lfsu, const X& x, const LFSV& lfsv, R& r) const
386  {
387  // domain and range field type
388  typedef typename LFSU::Traits::FiniteElementType::
389  Traits::LocalBasisType::Traits::DomainFieldType DF;
390  typedef typename LFSU::Traits::FiniteElementType::
391  Traits::LocalBasisType::Traits::RangeFieldType RF;
392  typedef typename LFSU::Traits::FiniteElementType::
393  Traits::LocalBasisType::Traits::RangeType RangeType;
394  typedef typename LFSU::Traits::SizeType size_type;
395 
396  // dimensions
397  const int dim = EG::Geometry::mydimension;
398  const int intorder = 2*lfsu.finiteElement().localBasis().order();
399 
400  // select quadrature rule
401  Dune::GeometryType gt = eg.geometry().type();
402  const Dune::QuadratureRule<DF,dim>& rule = Dune::QuadratureRules<DF,dim>::rule(gt,intorder);
403 
404  // loop over quadrature points
405  RF sum(0.0);
406  for (const auto& ip : rule)
407  {
408  // evaluate basis functions
409  std::vector<RangeType> phi(lfsu.size());
410  lfsu.finiteElement().localBasis().evaluateFunction(ip.position(),phi);
411 
412  // evaluate u
413  RF u=0.0;
414  for (size_type i=0; i<lfsu.size(); i++)
415  u += x(lfsu,i)*phi[i];
416 
417  // evaluate reaction term
418  typename T::Traits::RangeFieldType c = param.c(eg.entity(),ip.position());
419 
420  // evaluate right hand side parameter function
421  typename T::Traits::RangeFieldType f = param.f(eg.entity(),ip.position());
422 
423  // integrate f^2
424  RF factor = ip.weight() * eg.geometry().integrationElement(ip.position());
425  sum += (f*f-c*c*u*u)*factor;
426  }
427 
428  // accumulate cell indicator
429  DF h_T = diameter(eg.geometry());
430  r.accumulate(lfsv,0,h_T*h_T*sum);
431  }
432 
433 
434  // skeleton integral depending on test and ansatz functions
435  // each face is only visited ONCE!
436  template<typename IG, typename LFSU, typename X, typename LFSV, typename R>
437  void alpha_skeleton (const IG& ig,
438  const LFSU& lfsu_s, const X& x_s, const LFSV& lfsv_s,
439  const LFSU& lfsu_n, const X& x_n, const LFSV& lfsv_n,
440  R& r_s, R& r_n) const
441  {
442  // domain and range field type
443  typedef typename LFSU::Traits::FiniteElementType::
444  Traits::LocalBasisType::Traits::DomainFieldType DF;
445  typedef typename LFSU::Traits::FiniteElementType::
446  Traits::LocalBasisType::Traits::RangeFieldType RF;
447  typedef typename LFSU::Traits::FiniteElementType::
448  Traits::LocalBasisType::Traits::JacobianType JacobianType;
449  typedef typename LFSU::Traits::SizeType size_type;
450 
451  // dimensions
452  const int dim = IG::dimension;
453 
454  // get cell entities from both sides of the intersection
455  auto inside_cell = ig.inside();
456  auto outside_cell = ig.outside();
457 
458  // evaluate permeability tensors
459  const Dune::FieldVector<DF,dim>&
460  inside_local = Dune::ReferenceElements<DF,dim>::general(inside_cell.type()).position(0,0);
461  const Dune::FieldVector<DF,dim>&
462  outside_local = Dune::ReferenceElements<DF,dim>::general(outside_cell.type()).position(0,0);
463  typename T::Traits::PermTensorType A_s, A_n;
464  A_s = param.A(inside_cell,inside_local);
465  A_n = param.A(outside_cell,outside_local);
466 
467  // select quadrature rule
468  const int intorder = 2*lfsu_s.finiteElement().localBasis().order();
469  Dune::GeometryType gtface = ig.geometryInInside().type();
470  const Dune::QuadratureRule<DF,dim-1>& rule = Dune::QuadratureRules<DF,dim-1>::rule(gtface,intorder);
471 
472  // transformation
473  typename IG::Entity::Geometry::JacobianInverseTransposed jac;
474 
475  // tensor times normal
476  const Dune::FieldVector<DF,dim> n_F = ig.centerUnitOuterNormal();
477  Dune::FieldVector<RF,dim> An_F_s;
478  A_s.mv(n_F,An_F_s);
479  Dune::FieldVector<RF,dim> An_F_n;
480  A_n.mv(n_F,An_F_n);
481 
482  // loop over quadrature points and integrate normal flux
483  RF sum(0.0);
484  for (const auto& ip : rule)
485  {
486  // position of quadrature point in local coordinates of elements
487  Dune::FieldVector<DF,dim> iplocal_s = ig.geometryInInside().global(ip.position());
488  Dune::FieldVector<DF,dim> iplocal_n = ig.geometryInOutside().global(ip.position());
489 
490  // evaluate gradient of basis functions
491  std::vector<JacobianType> gradphi_s(lfsu_s.size());
492  lfsu_s.finiteElement().localBasis().evaluateJacobian(iplocal_s,gradphi_s);
493  std::vector<JacobianType> gradphi_n(lfsu_n.size());
494  lfsu_n.finiteElement().localBasis().evaluateJacobian(iplocal_n,gradphi_n);
495 
496  // transform gradients of shape functions to real element
497  jac = inside_cell.geometry().jacobianInverseTransposed(iplocal_s);
498  std::vector<Dune::FieldVector<RF,dim> > tgradphi_s(lfsu_s.size());
499  for (size_type i=0; i<lfsu_s.size(); i++) jac.mv(gradphi_s[i][0],tgradphi_s[i]);
500  jac = outside_cell.geometry().jacobianInverseTransposed(iplocal_n);
501  std::vector<Dune::FieldVector<RF,dim> > tgradphi_n(lfsu_n.size());
502  for (size_type i=0; i<lfsu_n.size(); i++) jac.mv(gradphi_n[i][0],tgradphi_n[i]);
503 
504  // compute gradient of u
505  Dune::FieldVector<RF,dim> gradu_s(0.0);
506  for (size_type i=0; i<lfsu_s.size(); i++)
507  gradu_s.axpy(x_s(lfsu_s,i),tgradphi_s[i]);
508  Dune::FieldVector<RF,dim> gradu_n(0.0);
509  for (size_type i=0; i<lfsu_n.size(); i++)
510  gradu_n.axpy(x_n(lfsu_n,i),tgradphi_n[i]);
511 
512  // integrate
513  RF factor = ip.weight() * ig.geometry().integrationElement(ip.position());
514  RF jump = (An_F_s*gradu_s)-(An_F_n*gradu_n);
515  sum += 0.25*jump*jump*factor;
516  }
517 
518  // accumulate indicator
519  // DF h_T = diameter(ig.geometry());
520  DF h_T = std::max(diameter(inside_cell.geometry()),diameter(outside_cell.geometry()));
521  r_s.accumulate(lfsv_s,0,h_T*sum);
522  r_n.accumulate(lfsv_n,0,h_T*sum);
523  }
524 
525 
526  // boundary integral depending on test and ansatz functions
527  // We put the Dirchlet evaluation also in the alpha term to save some geometry evaluations
528  template<typename IG, typename LFSU, typename X, typename LFSV, typename R>
529  void alpha_boundary (const IG& ig,
530  const LFSU& lfsu_s, const X& x_s, const LFSV& lfsv_s,
531  R& r_s) const
532  {
533  // domain and range field type
534  typedef typename LFSU::Traits::FiniteElementType::
535  Traits::LocalBasisType::Traits::DomainFieldType DF;
536  typedef typename LFSU::Traits::FiniteElementType::
537  Traits::LocalBasisType::Traits::RangeFieldType RF;
538  typedef typename LFSU::Traits::FiniteElementType::
539  Traits::LocalBasisType::Traits::JacobianType JacobianType;
540  typedef typename LFSU::Traits::SizeType size_type;
541 
542  // dimensions
543  const int dim = IG::dimension;
544 
545  auto inside_cell = ig.inside();
546  // evaluate permeability tensors
547  const Dune::FieldVector<DF,dim>&
548  inside_local = Dune::ReferenceElements<DF,dim>::general(inside_cell.type()).position(0,0);
549  typename T::Traits::PermTensorType A_s;
550  A_s = param.A(inside_cell,inside_local);
551  const Dune::FieldVector<DF,dim> n_F = ig.centerUnitOuterNormal();
552  Dune::FieldVector<RF,dim> An_F_s;
553  A_s.mv(n_F,An_F_s);
554 
555  // select quadrature rule
556  const int intorder = 2*lfsu_s.finiteElement().localBasis().order();
557  Dune::GeometryType gtface = ig.geometryInInside().type();
558  const Dune::QuadratureRule<DF,dim-1>& rule = Dune::QuadratureRules<DF,dim-1>::rule(gtface,intorder);
559 
560  // transformation
561  typename IG::Entity::Geometry::JacobianInverseTransposed jac;
562 
563  // evaluate boundary condition
564  const Dune::FieldVector<DF,dim-1>
565  face_local = Dune::ReferenceElements<DF,dim-1>::general(gtface).position(0,0);
566  BCType bctype = param.bctype(ig.intersection(),face_local);
568  return;
569 
570  // loop over quadrature points and integrate normal flux
571  RF sum(0.0);
572  for (const auto& ip : rule)
573  {
574  // position of quadrature point in local coordinates of elements
575  Dune::FieldVector<DF,dim> iplocal_s = ig.geometryInInside().global(ip.position());
576 
577  // evaluate gradient of basis functions
578  std::vector<JacobianType> gradphi_s(lfsu_s.size());
579  lfsu_s.finiteElement().localBasis().evaluateJacobian(iplocal_s,gradphi_s);
580 
581  // transform gradients of shape functions to real element
582  jac = inside_cell.geometry().jacobianInverseTransposed(iplocal_s);
583  std::vector<Dune::FieldVector<RF,dim> > tgradphi_s(lfsu_s.size());
584  for (size_type i=0; i<lfsu_s.size(); i++) jac.mv(gradphi_s[i][0],tgradphi_s[i]);
585 
586  // compute gradient of u
587  Dune::FieldVector<RF,dim> gradu_s(0.0);
588  for (size_type i=0; i<lfsu_s.size(); i++)
589  gradu_s.axpy(x_s(lfsu_s,i),tgradphi_s[i]);
590 
591  // evaluate flux boundary condition
592  RF j = param.j(ig.intersection(),ip.position());
593 
594  // integrate
595  RF factor = ip.weight() * ig.geometry().integrationElement(ip.position());
596  RF jump = j+(An_F_s*gradu_s);
597  sum += jump*jump*factor;
598  }
599 
600  // accumulate indicator
601  //DF h_T = diameter(ig.geometry());
602  DF h_T = diameter(inside_cell.geometry());
603  r_s.accumulate(lfsv_s,0,h_T*sum);
604  }
605 
606  private:
607  T& param; // two phase parameter class
608 
609  template<class GEO>
610  typename GEO::ctype diameter (const GEO& geo) const
611  {
612  typedef typename GEO::ctype DF;
613  DF hmax = -1.0E00;
614  const int dim = GEO::coorddimension;
615  for (int i=0; i<geo.corners(); i++)
616  {
617  Dune::FieldVector<DF,dim> xi = geo.corner(i);
618  for (int j=i+1; j<geo.corners(); j++)
619  {
620  Dune::FieldVector<DF,dim> xj = geo.corner(j);
621  xj -= xi;
622  hmax = std::max(hmax,xj.two_norm());
623  }
624  }
625  return hmax;
626  }
627 
628  };
629 
630 
646  template<typename T>
650  {
651  enum { dim = T::Traits::GridViewType::dimension };
652 
653  typedef typename T::Traits::RangeFieldType Real;
655 
656  public:
657  // pattern assembly flags
658  enum { doPatternVolume = false };
659  enum { doPatternSkeleton = false };
660 
661  // residual assembly flags
662  enum { doAlphaVolume = true };
663 
665  // supply time step from implicit Euler scheme
666  ConvectionDiffusionTemporalResidualEstimator1 (T& param_, double time_, double dt_)
667  : param(param_), time(time_), dt(dt_), cmax(0)
668  {}
669 
670  // volume integral depending on test and ansatz functions
671  template<typename EG, typename LFSU, typename X, typename LFSV, typename R>
672  void alpha_volume (const EG& eg, const LFSU& lfsu, const X& x, const LFSV& lfsv, R& r) const
673  {
674  // domain and range field type
675  typedef typename LFSU::Traits::FiniteElementType::
676  Traits::LocalBasisType::Traits::DomainFieldType DF;
677  typedef typename LFSU::Traits::FiniteElementType::
678  Traits::LocalBasisType::Traits::RangeFieldType RF;
679  typedef typename LFSU::Traits::FiniteElementType::
680  Traits::LocalBasisType::Traits::RangeType RangeType;
681  typedef typename LFSU::Traits::SizeType size_type;
682 
683  // dimensions
684  const int dim = EG::Geometry::mydimension;
685  const int intorder = 2*lfsu.finiteElement().localBasis().order();
686 
687  // select quadrature rule
688  Dune::GeometryType gt = eg.geometry().type();
689  const Dune::QuadratureRule<DF,dim>& rule = Dune::QuadratureRules<DF,dim>::rule(gt,intorder);
690 
691  // loop over quadrature points
692  RF sum(0.0);
693  RF fsum_up(0.0);
694  RF fsum_mid(0.0);
695  RF fsum_down(0.0);
696  for (const auto& ip : rule)
697  {
698  // evaluate basis functions
699  std::vector<RangeType> phi(lfsu.size());
700  lfsu.finiteElement().localBasis().evaluateFunction(ip.position(),phi);
701 
702  // evaluate u
703  RF u=0.0;
704  for (size_type i=0; i<lfsu.size(); i++)
705  u += x(lfsu,i)*phi[i];
706 
707  // integrate f^2
708  RF factor = ip.weight() * eg.geometry().integrationElement(ip.position());
709  sum += u*u*factor;
710 
711  // evaluate right hand side parameter function
712  param.setTime(time);
713  typename T::Traits::RangeFieldType f_down = param.f(eg.entity(),ip.position());
714  param.setTime(time+0.5*dt);
715  typename T::Traits::RangeFieldType f_mid = param.f(eg.entity(),ip.position());
716  param.setTime(time+dt);
717  typename T::Traits::RangeFieldType f_up = param.f(eg.entity(),ip.position());
718  RF f_average = (1.0/6.0)*f_down + (2.0/3.0)*f_mid + (1.0/6.0)*f_up;
719 
720  // integrate f-f_average
721  fsum_down += (f_down-f_average)*(f_down-f_average)*factor;
722  fsum_mid += (f_mid-f_average)*(f_mid-f_average)*factor;
723  fsum_up += (f_up-f_average)*(f_up-f_average)*factor;
724  }
725 
726  // accumulate cell indicator
727  DF h_T = diameter(eg.geometry());
728  r.accumulate(lfsv,0,(h_T*h_T/dt)*sum); // h^2*k_n||jump/k_n||^2
729  r.accumulate(lfsv,0,h_T*h_T * dt*((1.0/6.0)*fsum_down+(2.0/3.0)*fsum_mid+(1.0/6.0)*fsum_up) ); // h^2*||f-time_average(f)||^2_0_s_t
730  }
731 
732  void clearCmax ()
733  {
734  cmax = 0;
735  }
736 
737  double getCmax () const
738  {
739  return cmax;
740  }
741 
742  private:
743  T& param; // two phase parameter class
744  double time;
745  double dt;
746  mutable double cmax;
747 
748  template<class GEO>
749  typename GEO::ctype diameter (const GEO& geo) const
750  {
751  typedef typename GEO::ctype DF;
752  DF hmax = -1.0E00;
753  const int dim = GEO::coorddimension;
754  for (int i=0; i<geo.corners(); i++)
755  {
756  Dune::FieldVector<DF,dim> xi = geo.corner(i);
757  for (int j=i+1; j<geo.corners(); j++)
758  {
759  Dune::FieldVector<DF,dim> xj = geo.corner(j);
760  xj -= xi;
761  hmax = std::max(hmax,xj.two_norm());
762  }
763  }
764  return hmax;
765  }
766 
767  };
768 
769  // a functor that can be used to evaluate rhs parameter function in interpolate
770  template<typename T, typename EG>
772  {
773  public:
774  CD_RHS_LocalAdapter (const T& t_, const EG& eg_) : t(t_), eg(eg_)
775  {}
776 
777  template<typename X, typename Y>
778  inline void evaluate (const X& x, Y& y) const
779  {
780  y[0] = t.f(eg.entity(),x);
781  }
782 
783  private:
784  const T& t;
785  const EG& eg;
786  };
787 
803  template<typename T>
807  {
808  enum { dim = T::Traits::GridViewType::dimension };
809 
810  typedef typename T::Traits::RangeFieldType Real;
812 
813  public:
814  // pattern assembly flags
815  enum { doPatternVolume = false };
816  enum { doPatternSkeleton = false };
817 
818  // residual assembly flags
819  enum { doAlphaVolume = true };
820  enum { doAlphaBoundary = true };
821 
823  // supply time step from implicit Euler scheme
824  ConvectionDiffusionTemporalResidualEstimator (T& param_, double time_, double dt_)
825  : param(param_), time(time_), dt(dt_)
826  {}
827 
828  // volume integral depending on test and ansatz functions
829  template<typename EG, typename LFSU, typename X, typename LFSV, typename R>
830  void alpha_volume (const EG& eg, const LFSU& lfsu, const X& x, const LFSV& lfsv, R& r) const
831  {
832  // domain and range field type
833  typedef typename LFSU::Traits::FiniteElementType::
834  Traits::LocalBasisType::Traits::DomainFieldType DF;
835  typedef typename LFSU::Traits::FiniteElementType::
836  Traits::LocalBasisType::Traits::RangeFieldType RF;
837  typedef typename LFSU::Traits::FiniteElementType::
838  Traits::LocalBasisType::Traits::RangeType RangeType;
839  typedef typename LFSU::Traits::SizeType size_type;
840  typedef typename LFSU::Traits::FiniteElementType::
841  Traits::LocalBasisType::Traits::JacobianType JacobianType;
842 
843  // dimensions
844  const int dim = EG::Geometry::mydimension;
845  const int intorder = 2*lfsu.finiteElement().localBasis().order();
846 
847  // select quadrature rule
848  Dune::GeometryType gt = eg.geometry().type();
849  const Dune::QuadratureRule<DF,dim>& rule = Dune::QuadratureRules<DF,dim>::rule(gt,intorder);
850 
851  // interpolate f as finite element function to compute the gradient
852  CD_RHS_LocalAdapter<T,EG> f_adapter(param,eg);
853  std::vector<RF> f_up, f_down, f_mid;
854  param.setTime(time);
855  lfsu.finiteElement().localInterpolation().interpolate(f_adapter,f_down);
856  param.setTime(time+0.5*dt);
857  lfsu.finiteElement().localInterpolation().interpolate(f_adapter,f_mid);
858  param.setTime(time+dt);
859  lfsu.finiteElement().localInterpolation().interpolate(f_adapter,f_up);
860 
861  // loop over quadrature points
862  RF sum(0.0);
863  RF sum_grad(0.0);
864  RF fsum_grad_up(0.0);
865  RF fsum_grad_mid(0.0);
866  RF fsum_grad_down(0.0);
867  for (const auto& ip : rule)
868  {
869  // evaluate basis functions
870  std::vector<RangeType> phi(lfsu.size());
871  lfsu.finiteElement().localBasis().evaluateFunction(ip.position(),phi);
872 
873  // evaluate u
874  RF u=0.0;
875  for (size_type i=0; i<lfsu.size(); i++)
876  u += x(lfsu,i)*phi[i];
877 
878  // integrate jump
879  RF factor = ip.weight() * eg.geometry().integrationElement(ip.position());
880  sum += u*u*factor;
881 
882  // evaluate gradient of shape functions (we assume Galerkin method lfsu=lfsv)
883  std::vector<JacobianType> js(lfsu.size());
884  lfsu.finiteElement().localBasis().evaluateJacobian(ip.position(),js);
885 
886  // transform gradients of shape functions to real element
887  const typename EG::Geometry::JacobianInverseTransposed jac =
888  eg.geometry().jacobianInverseTransposed(ip.position());
889  std::vector<Dune::FieldVector<RF,dim> > gradphi(lfsu.size());
890  for (size_type i=0; i<lfsu.size(); i++)
891  jac.mv(js[i][0],gradphi[i]);
892 
893  // compute gradient of u
894  Dune::FieldVector<RF,dim> gradu(0.0);
895  for (size_type i=0; i<lfsu.size(); i++)
896  gradu.axpy(x(lfsu,i),gradphi[i]);
897 
898  // integrate jump of gradient
899  sum_grad += (gradu*gradu)*factor;
900 
901  // compute gradients of f
902  Dune::FieldVector<RF,dim> gradf_down(0.0);
903  for (size_type i=0; i<lfsu.size(); i++) gradf_down.axpy(f_down[i],gradphi[i]);
904  Dune::FieldVector<RF,dim> gradf_mid(0.0);
905  for (size_type i=0; i<lfsu.size(); i++) gradf_mid.axpy(f_mid[i],gradphi[i]);
906  Dune::FieldVector<RF,dim> gradf_up(0.0);
907  for (size_type i=0; i<lfsu.size(); i++) gradf_up.axpy(f_up[i],gradphi[i]);
908  Dune::FieldVector<RF,dim> gradf_average(0.0);
909  for (size_type i=0; i<lfsu.size(); i++)
910  gradf_average.axpy((1.0/6.0)*f_down[i]+(2.0/3.0)*f_mid[i]+(1.0/6.0)*f_up[i],gradphi[i]);
911 
912  // integrate grad(f-f_average)
913  gradf_down -= gradf_average;
914  fsum_grad_down += (gradf_down*gradf_down)*factor;
915  gradf_mid -= gradf_average;
916  fsum_grad_mid += (gradf_mid*gradf_mid)*factor;
917  gradf_up -= gradf_average;
918  fsum_grad_up += (gradf_up*gradf_up)*factor;
919  }
920 
921  // accumulate cell indicator
922  DF h_T = diameter(eg.geometry());
923  r.accumulate(lfsv,0,dt * sum_grad); // k_n*||grad(jump)||^2
924  r.accumulate(lfsv,0,dt*dt * dt*((1.0/6.0)*fsum_grad_down+(2.0/3.0)*fsum_grad_mid+(1.0/6.0)*fsum_grad_up)); // k_n^2*||grad(f-time_average(f))||^2_s_t
925  }
926 
927  // boundary integral depending on test and ansatz functions
928  // We put the Dirchlet evaluation also in the alpha term to save some geometry evaluations
929  template<typename IG, typename LFSU, typename X, typename LFSV, typename R>
930  void alpha_boundary (const IG& ig,
931  const LFSU& lfsu_s, const X& x_s, const LFSV& lfsv_s,
932  R& r_s) const
933  {
934  // domain and range field type
935  typedef typename LFSU::Traits::FiniteElementType::
936  Traits::LocalBasisType::Traits::DomainFieldType DF;
937  typedef typename LFSU::Traits::FiniteElementType::
938  Traits::LocalBasisType::Traits::RangeFieldType RF;
939 
940  // dimensions
941  const int dim = IG::dimension;
942 
943  // select quadrature rule
944  const int intorder = 2*lfsu_s.finiteElement().localBasis().order();
945  Dune::GeometryType gtface = ig.geometryInInside().type();
946  const Dune::QuadratureRule<DF,dim-1>& rule = Dune::QuadratureRules<DF,dim-1>::rule(gtface,intorder);
947 
948  // evaluate boundary condition
949  const Dune::FieldVector<DF,dim-1>
950  face_local = Dune::ReferenceElements<DF,dim-1>::general(gtface).position(0,0);
951  BCType bctype = param.bctype(ig.intersection(),face_local);
953  return;
954 
955  // loop over quadrature points and integrate
956  RF sum_up(0.0);
957  RF sum_down(0.0);
958  for (const auto& ip : rule)
959  {
960  // evaluate flux boundary condition
961  param.setTime(time);
962  RF j_down = param.j(ig.intersection(),ip.position());
963  param.setTime(time+0.5*dt);
964  RF j_mid = param.j(ig.intersection(),ip.position());
965  param.setTime(time+dt);
966  RF j_up = param.j(ig.intersection(),ip.position());
967 
968  // integrate
969  RF factor = ip.weight() * ig.geometry().integrationElement(ip.position());
970  sum_down += (j_down-j_mid)*(j_down-j_mid)*factor;
971  sum_up += (j_up-j_mid)*(j_up-j_mid)*factor;
972  }
973 
974  // accumulate indicator
975  //DF h_T = diameter(ig.geometry());
976  auto inside_cell = ig.inside();
977  DF h_T = diameter(inside_cell.geometry());
978  r_s.accumulate(lfsv_s,0,(h_T+dt*dt/h_T)*dt*0.5*(sum_down+sum_up));
979  }
980 
981  private:
982  T& param; // two phase parameter class
983  double time;
984  double dt;
985 
986  template<class GEO>
987  typename GEO::ctype diameter (const GEO& geo) const
988  {
989  typedef typename GEO::ctype DF;
990  DF hmax = -1.0E00;
991  const int dim = GEO::coorddimension;
992  for (int i=0; i<geo.corners(); i++)
993  {
994  Dune::FieldVector<DF,dim> xi = geo.corner(i);
995  for (int j=i+1; j<geo.corners(); j++)
996  {
997  Dune::FieldVector<DF,dim> xj = geo.corner(j);
998  xj -= xi;
999  hmax = std::max(hmax,xj.two_norm());
1000  }
1001  }
1002  return hmax;
1003  }
1004 
1005  };
1006 
1007 
1008 
1009  }
1010 }
1011 #endif
ConvectionDiffusionTemporalResidualEstimator1(T &param_, double time_, double dt_)
constructor: pass parameter object
Definition: convectiondiffusionfem.hh:666
double getCmax() const
Definition: convectiondiffusionfem.hh:737
CD_RHS_LocalAdapter(const T &t_, const EG &eg_)
Definition: convectiondiffusionfem.hh:774
Definition: convectiondiffusionfem.hh:35
void alpha_boundary(const IG &ig, const LFSU &lfsu_s, const X &x_s, const LFSV &lfsv_s, R &r_s) const
Definition: convectiondiffusionfem.hh:930
void alpha_boundary(const IG &ig, const LFSU &lfsu_s, const X &x_s, const LFSV &lfsv_s, R &r_s) const
Definition: convectiondiffusionfem.hh:529
Definition: convectiondiffusionfem.hh:804
sparsity pattern generator
Definition: pattern.hh:13
void alpha_boundary(const IG &ig, const LFSU &lfsu_s, const X &x_s, const LFSV &lfsv_s, R &r_s) const
Definition: convectiondiffusionfem.hh:192
void setTime(double t)
set time in parameter class
Definition: convectiondiffusionfem.hh:330
ConvectionDiffusionFEM(T &param_, int intorderadd_=0)
Definition: convectiondiffusionfem.hh:52
const IG & ig
Definition: constraints.hh:148
static const int dim
Definition: adaptivity.hh:83
Implement jacobian_boundary() based on alpha_boundary()
Definition: numericaljacobian.hh:250
ReferenceElementWrapper< ReferenceElement< typename Geometry::ctype, Geometry::mydimension > > referenceElement(const Geometry &geo)
Returns the reference element for the given geometry.
Definition: referenceelements.hh:144
Definition: adaptivity.hh:27
Definition: convectiondiffusionparameter.hh:65
Type
Definition: convectiondiffusionparameter.hh:65
Definition: convectiondiffusionfem.hh:46
Implements linear and nonlinear versions of jacobian_apply_boundary() based on alpha_boundary() ...
Definition: numericaljacobianapply.hh:285
Default flags for all local operators.
Definition: flags.hh:18
void alpha_volume(const EG &eg, const LFSU &lfsu, const X &x, const LFSV &lfsv, R &r) const
Definition: convectiondiffusionfem.hh:672
QuadratureRuleWrapper< QuadratureRule< typename Geometry::ctype, Geometry::mydimension > > quadratureRule(const Geometry &geo, std::size_t order, QuadratureType::Enum quadrature_type=QuadratureType::GaussLegendre)
Returns a quadrature rule for the given geometry.
Definition: quadraturerules.hh:117
Definition: convectiondiffusionparameter.hh:65
Implement jacobian_volume() based on alpha_volume()
Definition: numericaljacobian.hh:31
Default class for additional methods in instationary local operators.
Definition: idefault.hh:89
void jacobian_boundary(const IG &ig, const LFSU &lfsu_s, const X &x_s, const LFSV &lfsv_s, M &mat_s) const
Definition: convectiondiffusionfem.hh:271
ConvectionDiffusionTemporalResidualEstimator(T &param_, double time_, double dt_)
constructor: pass parameter object
Definition: convectiondiffusionfem.hh:824
Definition: convectiondiffusionparameter.hh:65
void alpha_volume(const EG &eg, const LFSU &lfsu, const X &x, const LFSV &lfsv, R &r) const
Definition: convectiondiffusionfem.hh:59
Definition: convectiondiffusionfem.hh:360
Definition: convectiondiffusionfem.hh:647
void clearCmax()
Definition: convectiondiffusionfem.hh:732
void jacobian_volume(const EG &eg, const LFSU &lfsu, const X &x, const LFSV &lfsv, M &mat) const
Definition: convectiondiffusionfem.hh:127
void evaluate(const X &x, Y &y) const
Definition: convectiondiffusionfem.hh:778
store values of basis functions and gradients in a cache
Definition: localbasiscache.hh:17
ConvectionDiffusionFEMResidualEstimator(T &param_)
constructor: pass parameter object
Definition: convectiondiffusionfem.hh:379
Implements linear and nonlinear versions of jacobian_apply_volume() based on alpha_volume() ...
Definition: numericaljacobianapply.hh:32
Definition: convectiondiffusionfem.hh:771
void alpha_skeleton(const IG &ig, const LFSU &lfsu_s, const X &x_s, const LFSV &lfsv_s, const LFSU &lfsu_n, const X &x_n, const LFSV &lfsv_n, R &r_s, R &r_n) const
Definition: convectiondiffusionfem.hh:437
void alpha_volume(const EG &eg, const LFSU &lfsu, const X &x, const LFSV &lfsv, R &r) const
Definition: convectiondiffusionfem.hh:830
Definition: convectiondiffusionfem.hh:50
void alpha_volume(const EG &eg, const LFSU &lfsu, const X &x, const LFSV &lfsv, R &r) const
Definition: convectiondiffusionfem.hh:385
Definition: convectiondiffusionfem.hh:49