DUNE-FEM (unstable)

elliptic.hh
1 /**************************************************************************
2 
3  The dune-fem module is a module of DUNE (see www.dune-project.org).
4  It is based on the dune-grid interface library
5  extending the grid interface by a number of discretization algorithms
6  for solving non-linear systems of partial differential equations.
7 
8  Copyright (C) 2003 - 2015 Robert Kloefkorn
9  Copyright (C) 2003 - 2010 Mario Ohlberger
10  Copyright (C) 2004 - 2015 Andreas Dedner
11  Copyright (C) 2005 Adrian Burri
12  Copyright (C) 2005 - 2015 Mirko Kraenkel
13  Copyright (C) 2006 - 2015 Christoph Gersbacher
14  Copyright (C) 2006 - 2015 Martin Nolte
15  Copyright (C) 2011 - 2015 Tobias Malkmus
16  Copyright (C) 2012 - 2015 Stefan Girke
17  Copyright (C) 2013 - 2015 Claus-Justus Heine
18  Copyright (C) 2013 - 2014 Janick Gerstenberger
19  Copyright (C) 2013 Sven Kaulman
20  Copyright (C) 2013 Tom Ranner
21  Copyright (C) 2015 Marco Agnese
22  Copyright (C) 2015 Martin Alkaemper
23 
24 
25  The dune-fem module is free software; you can redistribute it and/or
26  modify it under the terms of the GNU General Public License as
27  published by the Free Software Foundation; either version 2 of
28  the License, or (at your option) any later version.
29 
30  The dune-fem module is distributed in the hope that it will be useful,
31  but WITHOUT ANY WARRANTY; without even the implied warranty of
32  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
33  GNU General Public License for more details.
34 
35  You should have received a copy of the GNU General Public License along
36  with this program; if not, write to the Free Software Foundation, Inc.,
37  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
38 
39 **************************************************************************/
40 #ifndef DUNE_FEM_SCHEMES_ELLIPTIC_HH
41 #define DUNE_FEM_SCHEMES_ELLIPTIC_HH
42 
43 #include <cstddef>
44 
45 #include <dune/common/timer.hh>
46 #include <dune/common/fmatrix.hh>
47 
48 #include <dune/fem/quadrature/cachingquadrature.hh>
49 #include <dune/fem/operator/common/operator.hh>
50 #include <dune/fem/operator/common/stencil.hh>
51 
52 #include <dune/fem/common/bindguard.hh>
53 #include <dune/fem/function/common/localcontribution.hh>
54 #include <dune/fem/function/localfunction/const.hh>
55 
56 #include <dune/fem/operator/common/differentiableoperator.hh>
57 #include <dune/fem/operator/common/temporarylocalmatrix.hh>
58 
59 
60 // include parameter handling
61 #include <dune/fem/io/parameter.hh>
62 #include <dune/fem/io/file/dataoutput.hh>
63 
64 // fempy includes
65 #include <dune/fempy/quadrature/fempyquadratures.hh>
66 
67 // EllipticOperator
68 // ----------------
69 
71 template< class DomainDiscreteFunction, class RangeDiscreteFunction, class Model>
73 : public virtual Dune::Fem::Operator< DomainDiscreteFunction, RangeDiscreteFunction >
75 {
76  typedef DomainDiscreteFunction DomainFunctionType;
77  typedef RangeDiscreteFunction RangeFunctionType;
78  typedef Model ModelType;
79  typedef Model DirichletModelType;
80 
81  typedef typename DomainFunctionType::DiscreteFunctionSpaceType DomainDiscreteFunctionSpaceType;
82  typedef typename DomainFunctionType::LocalFunctionType DomainLocalFunctionType;
83  typedef typename DomainLocalFunctionType::RangeType DomainRangeType;
84  typedef typename DomainLocalFunctionType::JacobianRangeType DomainJacobianRangeType;
85  typedef typename RangeFunctionType::DiscreteFunctionSpaceType RangeDiscreteFunctionSpaceType;
86  typedef typename RangeFunctionType::LocalFunctionType RangeLocalFunctionType;
87  typedef typename RangeLocalFunctionType::RangeType RangeRangeType;
88  typedef typename RangeLocalFunctionType::JacobianRangeType RangeJacobianRangeType;
89 
90  // the following types must be identical for domain and range
91  typedef typename RangeDiscreteFunctionSpaceType::IteratorType IteratorType;
92  typedef typename IteratorType::Entity EntityType;
93  typedef typename EntityType::Geometry GeometryType;
94  typedef typename RangeDiscreteFunctionSpaceType::DomainType DomainType;
95  typedef typename RangeDiscreteFunctionSpaceType::GridPartType GridPartType;
96  typedef typename GridPartType::IntersectionIteratorType IntersectionIteratorType;
97  typedef typename IntersectionIteratorType::Intersection IntersectionType;
98 
101 
102  EllipticOperator ( const RangeDiscreteFunctionSpaceType &rangeSpace,
103  ModelType &model,
104  const Dune::Fem::ParameterReader &parameter = Dune::Fem::Parameter::container() )
105  : model_( model ),
106  dSpace_(rangeSpace), rSpace_(rangeSpace)
107  {}
108  EllipticOperator ( const DomainDiscreteFunctionSpaceType &dSpace,
109  const RangeDiscreteFunctionSpaceType &rSpace,
110  ModelType &model,
111  const Dune::Fem::ParameterReader &parameter = Dune::Fem::Parameter::container() )
112  : model_( model ),
113  dSpace_(dSpace), rSpace_(rSpace),
114  interiorOrder_(-1), surfaceOrder_(-1)
115  {}
116 
118  virtual void operator() ( const DomainFunctionType &u, RangeFunctionType &w ) const
119  { apply(u,w); }
120  template <class GF>
121  void operator()( const GF &u, RangeFunctionType &w ) const
122  { apply(u,w); }
123  template <class GF>
124  void apply( const GF &u, RangeFunctionType &w ) const;
125 
126  const DomainDiscreteFunctionSpaceType& domainSpace() const
127  {
128  return dSpace_;
129  }
130  const RangeDiscreteFunctionSpaceType& rangeSpace() const
131  {
132  return rSpace_;
133  }
134  const ModelType &model () const { return model_; }
135  ModelType &model () { return model_; }
136 
137  void setQuadratureOrders(unsigned int interior, unsigned int surface)
138  {
139  interiorOrder_ = interior;
140  surfaceOrder_ = surface;
141  }
142 
143 protected:
144  int interiorOrder_, surfaceOrder_;
145 private:
146  ModelType &model_;
147  const DomainDiscreteFunctionSpaceType &dSpace_;
148  const RangeDiscreteFunctionSpaceType &rSpace_;
149 };
150 
151 
152 
153 // DifferentiableEllipticOperator
154 // ------------------------------
155 
157 template< class JacobianOperator, class Model >
159 : public EllipticOperator< typename JacobianOperator::DomainFunctionType, typename JacobianOperator::RangeFunctionType, Model >,
160  public Dune::Fem::DifferentiableOperator< JacobianOperator >
162 {
164 
165  typedef JacobianOperator JacobianOperatorType;
166 
169  typedef typename BaseType::ModelType ModelType;
170 
171  typedef typename DomainFunctionType::DiscreteFunctionSpaceType DomainDiscreteFunctionSpaceType;
172  typedef typename DomainFunctionType::LocalFunctionType DomainLocalFunctionType;
173  typedef typename DomainLocalFunctionType::RangeType DomainRangeType;
174  typedef typename DomainLocalFunctionType::JacobianRangeType DomainJacobianRangeType;
175  typedef typename RangeFunctionType::DiscreteFunctionSpaceType RangeDiscreteFunctionSpaceType;
176  typedef typename RangeFunctionType::LocalFunctionType RangeLocalFunctionType;
177  typedef typename RangeLocalFunctionType::RangeType RangeRangeType;
178  typedef typename RangeLocalFunctionType::JacobianRangeType RangeJacobianRangeType;
179 
180  // the following types must be identical for domain and range
181  typedef typename RangeDiscreteFunctionSpaceType::IteratorType IteratorType;
182  typedef typename IteratorType::Entity EntityType;
183  typedef typename EntityType::Geometry GeometryType;
184  typedef typename RangeDiscreteFunctionSpaceType::DomainType DomainType;
185  typedef typename RangeDiscreteFunctionSpaceType::GridPartType GridPartType;
186  typedef typename GridPartType::IntersectionIteratorType IntersectionIteratorType;
187  typedef typename IntersectionIteratorType::Intersection IntersectionType;
188 
189  typedef typename BaseType::QuadratureType QuadratureType;
190  // quadrature for faces - used for Neuman b.c.
191  typedef typename BaseType::FaceQuadratureType FaceQuadratureType;
192 
194  DifferentiableEllipticOperator ( const RangeDiscreteFunctionSpaceType &space,
195  ModelType &model,
196  const Dune::Fem::ParameterReader &parameter = Dune::Fem::Parameter::container() )
197  : BaseType( space, space, model, parameter )
198  {}
200  DifferentiableEllipticOperator ( const DomainDiscreteFunctionSpaceType &dSpace,
201  const RangeDiscreteFunctionSpaceType &rSpace,
202  ModelType &model,
203  const Dune::Fem::ParameterReader &parameter = Dune::Fem::Parameter::container() )
204  : BaseType( dSpace, rSpace, model, parameter )
205  {}
206 
208  void jacobian ( const DomainFunctionType &u, JacobianOperatorType &jOp ) const
209  { assemble(u,jOp); }
210  template <class GridFunctionType>
211  void jacobian ( const GridFunctionType &u, JacobianOperatorType &jOp ) const
212  { assemble(u,jOp); }
213  template <class GridFunctionType>
214  void assemble ( const GridFunctionType &u, JacobianOperatorType &jOp ) const;
215  using BaseType::operator();
216 
217  using BaseType::model;
218  using BaseType::interiorOrder_;
219  using BaseType::surfaceOrder_;
220 };
221 
222 
223 
224 // Implementation of EllipticOperator
225 // ----------------------------------
226 
227 template< class DomainDiscreteFunction, class RangeDiscreteFunction, class Model >
228 template<class GF>
230  ::apply( const GF &u, RangeFunctionType &w ) const
231 {
232  w.clear();
233  // get discrete function space
234  const RangeDiscreteFunctionSpaceType &dfSpace = w.space();
235 
236  // get local representation of the discrete functions
237  Dune::Fem::ConstLocalFunction< GF > uLocal( u );
238  Dune::Fem::AddLocalContribution< RangeFunctionType > wLocal( w );
239 
240  // iterate over grid
241  for( const EntityType &entity : dfSpace )
242  {
243  if( !model().init( entity ) )
244  continue;
245 
246  // get elements geometry
247  const GeometryType &geometry = entity.geometry();
248 
249  auto uGuard = Dune::Fem::bindGuard( uLocal, entity );
250  auto wGuard = Dune::Fem::bindGuard( wLocal, entity );
251 
252  // obtain quadrature order
253  const int quadOrder = interiorOrder_==-1?
254  uLocal.order() + wLocal.order() : interiorOrder_;
255 
256  { // element integral
257  QuadratureType quadrature( entity, quadOrder );
258  const size_t numQuadraturePoints = quadrature.nop();
259  for( size_t pt = 0; pt < numQuadraturePoints; ++pt )
260  {
262  const typename QuadratureType::CoordinateType &x = quadrature.point( pt );
263  const double weight = quadrature.weight( pt ) * geometry.integrationElement( x );
264 
265  DomainRangeType vu;
266  uLocal.evaluate( quadrature[ pt ], vu );
267  DomainJacobianRangeType du;
268  uLocal.jacobian( quadrature[ pt ], du );
269 
270  // compute mass contribution (studying linear case so linearizing around zero)
271  RangeRangeType avu( 0 );
272  model().source( quadrature[ pt ], vu, du, avu );
273  avu *= weight;
274  // add to local functional wLocal.axpy( quadrature[ pt ], avu );
275 
276  RangeJacobianRangeType adu( 0 );
277  // apply diffusive flux
278  model().flux( quadrature[ pt ], vu, du, adu );
279  adu *= weight;
280 
281  // add to local function
282  wLocal.axpy( quadrature[ pt ], avu, adu );
284  }
285  }
286 
287  if( model().hasNeumanBoundary() && entity.hasBoundaryIntersections() )
288  {
289  const IntersectionIteratorType iitend = dfSpace.gridPart().iend( entity );
290  for( IntersectionIteratorType iit = dfSpace.gridPart().ibegin( entity ); iit != iitend; ++iit )
291  {
292  const IntersectionType &intersection = *iit;
293  if( !intersection.boundary() )
294  continue;
295 
296  std::array<int,RangeRangeType::dimension> components(0);
297 
298  const bool hasDirichletComponent = model().isDirichletIntersection( intersection, components );
299 
300  const auto &intersectionGeometry = intersection.geometry();
301  const int quadOrder = surfaceOrder_==-1?
302  uLocal.order() + wLocal.order() : surfaceOrder_;
303  FaceQuadratureType quadInside( dfSpace.gridPart(), intersection, quadOrder, FaceQuadratureType::INSIDE );
304  const std::size_t numQuadraturePoints = quadInside.nop();
305  for( std::size_t pt = 0; pt < numQuadraturePoints; ++pt )
306  {
307  const auto &x = quadInside.localPoint( pt );
308  double weight = quadInside.weight( pt ) * intersectionGeometry.integrationElement( x );
309  DomainRangeType vu;
310  uLocal.evaluate( quadInside[ pt ], vu );
311  RangeRangeType alpha( 0 );
312  model().alpha( quadInside[ pt ], vu, alpha );
313  alpha *= weight;
314  for( int k = 0; k < RangeRangeType::dimension; ++k )
315  if( hasDirichletComponent && components[ k ] )
316  alpha[ k ] = 0;
317  wLocal.axpy( quadInside[ pt ], alpha );
318  }
319  }
320  }
321  }
322 
323  w.communicate();
324 }
325 
326 
327 
328 // Implementation of DifferentiableEllipticOperator
329 // ------------------------------------------------
330 
331 template< class JacobianOperator, class Model >
332 template<class GF>
334  ::assemble ( const GF &u, JacobianOperator &jOp ) const
335 {
336  // std::cout << "starting assembly\n";
337  // Dune::Timer timer;
338  typedef typename DomainDiscreteFunctionSpaceType::BasisFunctionSetType DomainBasisFunctionSetType;
339  typedef typename RangeDiscreteFunctionSpaceType::BasisFunctionSetType RangeBasisFunctionSetType;
341 
342  const DomainDiscreteFunctionSpaceType &domainSpace = jOp.domainSpace();
343  const RangeDiscreteFunctionSpaceType &rangeSpace = jOp.rangeSpace();
344 
346  jOp.reserve(stencil);
347  jOp.clear();
348  TmpLocalMatrixType jLocal( domainSpace, rangeSpace );
349 
350  const int domainBlockSize = domainSpace.localBlockSize; // is equal to 1 for scalar functions
351  std::vector< typename DomainLocalFunctionType::RangeType > phi( domainSpace.blockMapper().maxNumDofs()*domainBlockSize );
352  std::vector< typename DomainLocalFunctionType::JacobianRangeType > dphi( domainSpace.blockMapper().maxNumDofs()*domainBlockSize );
353  const int rangeBlockSize = rangeSpace.localBlockSize; // is equal to 1 for scalar functions
354  std::vector< typename RangeLocalFunctionType::RangeType > rphi( rangeSpace.blockMapper().maxNumDofs()*rangeBlockSize );
355  std::vector< typename RangeLocalFunctionType::JacobianRangeType > rdphi( rangeSpace.blockMapper().maxNumDofs()*rangeBlockSize );
356 
357  Dune::Fem::ConstLocalFunction< GF > uLocal( u );
358  // std::cout << " in assembly: start element loop size=" << rangeSpace.gridPart().grid().size(0) << " time= " << timer.elapsed() << std::endl;;
359  for( const EntityType &entity : rangeSpace )
360  {
361  if( !model().init( entity ) )
362  continue;
363 
364  const GeometryType &geometry = entity.geometry();
365 
366  auto uGuard = Dune::Fem::bindGuard( uLocal, entity );
367  jLocal.bind( entity, entity );
368  jLocal.clear();
369 
370  const DomainBasisFunctionSetType &domainBaseSet = jLocal.domainBasisFunctionSet();
371  const RangeBasisFunctionSetType &rangeBaseSet = jLocal.rangeBasisFunctionSet();
372  const std::size_t domainNumBasisFunctions = domainBaseSet.size();
373 
374  const int quadOrder = interiorOrder_==-1?
375  domainSpace.order() + rangeSpace.order() : interiorOrder_;
376  QuadratureType quadrature( entity, quadOrder );
377  const size_t numQuadraturePoints = quadrature.nop();
378  for( size_t pt = 0; pt < numQuadraturePoints; ++pt )
379  {
381  const typename QuadratureType::CoordinateType &x = quadrature.point( pt );
382  const double weight = quadrature.weight( pt ) * geometry.integrationElement( x );
383 
384  // evaluate all basis functions at given quadrature point
385  domainBaseSet.evaluateAll( quadrature[ pt ], phi );
386  rangeBaseSet.evaluateAll( quadrature[ pt ], rphi );
387 
388  // evaluate jacobians of all basis functions at given quadrature point
389  domainBaseSet.jacobianAll( quadrature[ pt ], dphi );
390  rangeBaseSet.jacobianAll( quadrature[ pt ], rdphi );
391 
392  // get value for linearization
393  DomainRangeType u0;
394  DomainJacobianRangeType jacU0;
395  uLocal.evaluate( quadrature[ pt ], u0 );
396  uLocal.jacobian( quadrature[ pt ], jacU0 );
397 
398  RangeRangeType aphi( 0 );
399  RangeJacobianRangeType adphi( 0 );
400  for( std::size_t localCol = 0; localCol < domainNumBasisFunctions; ++localCol )
401  {
402  // if mass terms or right hand side is present
403  model().linSource( u0, jacU0, quadrature[ pt ], phi[ localCol ], dphi[localCol], aphi );
404 
405  // if gradient term is present
406  model().linFlux( u0, jacU0, quadrature[ pt ], phi[ localCol ], dphi[ localCol ], adphi );
407 
408  // get column object and call axpy method
409  jLocal.column( localCol ).axpy( rphi, rdphi, aphi, adphi, weight );
410  }
412  }
413 
414  if( model().hasNeumanBoundary() && entity.hasBoundaryIntersections() )
415  {
416  const IntersectionIteratorType iitend = rangeSpace.gridPart().iend( entity );
417  for( IntersectionIteratorType iit = rangeSpace.gridPart().ibegin( entity ); iit != iitend; ++iit ) // looping over intersections
418  {
419  const IntersectionType &intersection = *iit;
420  if( !intersection.boundary() )
421  continue;
422 
423  std::array<int,RangeRangeType::dimension> components(0);
424  bool hasDirichletComponent = model().isDirichletIntersection( intersection, components );
425 
426  const auto &intersectionGeometry = intersection.geometry();
427  const int quadOrder = surfaceOrder_==-1?
428  domainSpace.order() + rangeSpace.order() : surfaceOrder_;
429  FaceQuadratureType quadInside( rangeSpace.gridPart(), intersection, quadOrder, FaceQuadratureType::INSIDE );
430  const std::size_t numQuadraturePoints = quadInside.nop();
431  for( std::size_t pt = 0; pt < numQuadraturePoints; ++pt )
432  {
433  const auto &x = quadInside.localPoint( pt );
434  const double weight = quadInside.weight( pt ) * intersectionGeometry.integrationElement( x );
435  DomainRangeType u0;
436  uLocal.evaluate( quadInside[ pt ], u0 );
437  domainBaseSet.evaluateAll( quadInside[ pt ], phi );
438  for( std::size_t localCol = 0; localCol < domainNumBasisFunctions; ++localCol )
439  {
440  RangeRangeType alpha( 0 );
441  model().linAlpha( u0,quadInside[ pt ], phi[ localCol ], alpha );
442  for( int k = 0; k < RangeRangeType::dimension; ++k )
443  if( hasDirichletComponent && components[ k ] )
444  alpha[ k ] = 0;
445  jLocal.column( localCol ).axpy( phi, alpha, weight );
446  }
447  }
448  }
449  }
450  jOp.addLocalMatrix( entity, entity, jLocal );
451  jLocal.unbind();
452  } // end grid traversal
453  // std::cout << " in assembly: final " << timer.elapsed() << std::endl;;
454  jOp.flushAssembly();
455 }
456 #endif // #ifndef DUNE_FEM_SCHEMES_ELLIPTIC_HH
quadrature class supporting base function caching
Definition: cachingquadrature.hh:41
abstract differentiable operator
Definition: differentiableoperator.hh:29
BaseType::RangeFunctionType RangeFunctionType
type of discrete function in the operator's range
Definition: differentiableoperator.hh:40
JacobianOperator JacobianOperatorType
type of linear operator modelling the operator's Jacobian
Definition: differentiableoperator.hh:35
BaseType::DomainFunctionType DomainFunctionType
type of discrete function in the operator's domain
Definition: differentiableoperator.hh:38
Traits::IntersectionIteratorType IntersectionIteratorType
type of IntersectionIterator
Definition: gridpart.hh:111
const DomainSpaceType & domainSpace() const
access to the domain space
Definition: localmatrix.hh:382
A local matrix with a small array as storage.
Definition: temporarylocalmatrix.hh:100
Implements a matrix constructed from a given type representing a field and compile-time given number ...
concept Intersection
Model of an intersection.
Definition: intersection.hh:23
concept Entity
Model of a grid entity.
Definition: entity.hh:107
concept Geometry
Model of a geometry object.
Definition: geometry.hh:29
constexpr Interior interior
PartitionSet for the interior partition.
Definition: partitionset.hh:271
[Class for linearizable elliptic operator]
Definition: elliptic.hh:162
DifferentiableEllipticOperator(const DomainDiscreteFunctionSpaceType &dSpace, const RangeDiscreteFunctionSpaceType &rSpace, ModelType &model, const Dune::Fem::ParameterReader &parameter=Dune::Fem::Parameter::container())
contructor
Definition: elliptic.hh:200
DifferentiableEllipticOperator(const RangeDiscreteFunctionSpaceType &space, ModelType &model, const Dune::Fem::ParameterReader &parameter=Dune::Fem::Parameter::container())
contructor
Definition: elliptic.hh:194
void jacobian(const DomainFunctionType &u, JacobianOperatorType &jOp) const
method to setup the jacobian of the operator for storage in a matrix
Definition: elliptic.hh:208
Stencil contaning the entries (en,en) for all entities in the space. Defailt for an operator over a L...
Definition: stencil.hh:349
abstract operator
Definition: operator.hh:34
DomainFunction DomainFunctionType
type of discrete function in the operator's domain
Definition: operator.hh:36
JacobianOperator::RangeFunctionType RangeFunctionType
type of discrete function in the operator's range
Definition: operator.hh:38
[Class for elliptic operator]
Definition: elliptic.hh:75
void apply(const GF &u, RangeFunctionType &w) const
Definition: elliptic.hh:230
virtual void operator()(const DomainFunctionType &u, RangeFunctionType &w) const
application operator
Definition: elliptic.hh:118
A simple timing class.
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.80.0 (May 16, 22:29, 2024)