1 #ifndef DUNE_FEM_DISCRETEFUNCTION_HH
2 #define DUNE_FEM_DISCRETEFUNCTION_HH
3 
4 #include <cassert>
5 
6 #include <complex>
7 #include <memory>
8 #include <ostream>
9 #include <string>
10 #include <typeindex>
11 
12 #include <dune/common/dynvector.hh>
13 
14 #include <dune/fem/function/common/dofiterator.hh>
15 #include <dune/fem/function/common/function.hh>
16 #include <dune/fem/function/common/functor.hh>
17 #include <dune/fem/function/common/scalarproducts.hh>
18 #include <dune/fem/function/common/rangegenerators.hh>
19 #include <dune/fem/function/localfunction/temporary.hh>
20 #include <dune/fem/gridpart/common/entitysearch.hh>
21 #include <dune/fem/io/file/persistencemanager.hh>
22 #include <dune/fem/io/streams/streams.hh>
23 #include <dune/fem/misc/functor.hh>
24 #include <dune/fem/misc/threads/threadmanager.hh>
25 #include <dune/fem/space/common/discretefunctionspace.hh>
26 #include <dune/fem/storage/envelope.hh>
27 #include <dune/fem/storage/referencevector.hh>
28 #include <dune/fem/version.hh>
29 
30 
31 namespace Dune
32 {
33 
34   namespace Fem
35   {
36 
37     /** @addtogroup DiscreteFunction
38      *  The DiscreteFunction is responsible for the dof storage. This can be
39      *  done in various ways an is left to the user. The user has to derive his
40      *  own implementation from the DiscreteFunctionDefault class. The implementations
41      *  in the default class which are ineffecient for the dof storage in the derived
42      *  class can be overloaded.
43      *
44      *  \remarks
45      *  The interface for using a DiscreteFunction is defined by
46      *  the class DiscreteFunctionInterface.
47      *
48      *  @{
49      */
50 
51     /** \brief base class for determing whether a class is a discrete function or not */
52     class IsDiscreteFunction
53     {};
54 
55     /** \brief base class for determing whether a function has local functions or not */
56     class HasLocalFunction
57     {};
58 
59 
60     template< class DiscreteFunction >
61     struct DiscreteFunctionTraits;
62 
63     template< class Traits >
64     class DiscreteFunctionDefault;
65 
66     //----------------------------------------------------------------------
67     //-
68     //-  --DiscreteFunctionInterface
69     //-
70     //----------------------------------------------------------------------
71     /** This is the interface of a discrete function which describes the
72      *  features of a discrete function.
73      *  It contains a local function and a dof iterator which can
74      *  iterate over all dofs of one level. Via the method access the local
75      *  dofs and basis functions can be accessed for a given entity.
76      *  The DOF-Iterators are STL-like Iterators, i.e. they can be dereferenced
77      *  giving the corresponding DOF.
78      *
79      *  \interfaceclass
80      */
81     template< class Impl >
82     class DiscreteFunctionInterface
83     : public Fem::Function< typename DiscreteFunctionTraits< Impl >::DiscreteFunctionSpaceType::FunctionSpaceType, Impl >,
84       public IsDiscreteFunction,
85       public HasLocalFunction
86     {
87       typedef DiscreteFunctionInterface< Impl > ThisType;
88       typedef Fem::Function< typename DiscreteFunctionTraits< Impl >::DiscreteFunctionSpaceType::FunctionSpaceType, Impl > BaseType;
89 
90     public:
91       //! type of the traits
92       typedef DiscreteFunctionTraits< Impl > Traits;
93 
94       //! type of the implementaton (Barton-Nackman)
95       typedef typename Traits :: DiscreteFunctionType DiscreteFunctionType;
96 
97       //! type of associated discrete function space
98       typedef typename Traits :: DiscreteFunctionSpaceType DiscreteFunctionSpaceType;
99 
100       //! type of associated function space
101       typedef typename DiscreteFunctionSpaceType :: FunctionSpaceType FunctionSpaceType;
102 
103       //! type of the discrete function interface (this type)
104       typedef DiscreteFunctionInterface< Impl > DiscreteFunctionInterfaceType;
105 
106       //! type of domain field, i.e. type of coordinate component
107       typedef typename DiscreteFunctionSpaceType :: DomainFieldType DomainFieldType;
108       //! type of range field, i.e. dof type
109       typedef typename DiscreteFunctionSpaceType :: RangeFieldType RangeFieldType;
110       //! type of domain, i.e. type of coordinates
111       typedef typename DiscreteFunctionSpaceType :: DomainType DomainType;
112       //! type of range, i.e. result of evaluation
113       typedef typename DiscreteFunctionSpaceType :: RangeType RangeType;
114       //! type of jacobian, i.e. type of evaluated gradient
115       typedef typename DiscreteFunctionSpaceType :: JacobianRangeType JacobianRangeType;
116 
117       //! type of the underlying grid part
118       typedef typename DiscreteFunctionSpaceType::GridPartType GridPartType;
119       typedef typename GridPartType::GridViewType GridView;
120 
121       //! type of the underlying grid
122       typedef typename DiscreteFunctionSpaceType :: GridType GridType;
123 
124       //! type of local functions
125       typedef typename Traits :: LocalFunctionType LocalFunctionType;
126 
127       //! type of the dof vector used in the discrete function implementation
128       typedef typename Traits :: DofVectorType  DofVectorType;
129 
130       //! type of the dof iterator used in the discrete function implementation
131       typedef typename Traits :: DofIteratorType DofIteratorType;
132 
133       //! type of the constantdof iterator used in the discrete function implementation
134       typedef typename Traits :: ConstDofIteratorType ConstDofIteratorType;
135 
136       typedef typename Traits :: DofType DofType;
137       typedef typename Traits :: DofBlockType DofBlockType;
138       typedef typename Traits :: ConstDofBlockType ConstDofBlockType;
139       typedef typename Traits :: DofBlockPtrType DofBlockPtrType;
140       typedef typename Traits :: ConstDofBlockPtrType ConstDofBlockPtrType;
141 
142       //! type of mapping base class for this discrete function
143       typedef typename BaseType :: MappingType MappingType;
144 
145       typedef typename DiscreteFunctionSpaceType::LocalBlockIndices BlockIndices;
146 
147       //! size of the dof blocks
148       static constexpr std::size_t blockSize = Hybrid::size( BlockIndices() );
149 
150       template< class Operation >
151       struct CommDataHandle
152       {
153         typedef typename DiscreteFunctionSpaceType
154           :: template CommDataHandle< DiscreteFunctionType, Operation > :: Type
155           Type;
156       };
157 
158       //! type of entity local functions are defined on
159       typedef typename DiscreteFunctionSpaceType :: EntityType  EntityType;
160 
161     protected:
162       using BaseType::asImp;
163 
164       //! default constructor
165       DiscreteFunctionInterface () = default;
166 
167       DiscreteFunctionInterface ( const ThisType& ) = default;
168       DiscreteFunctionInterface ( ThisType && ) = default;
169     public:
170       ThisType& operator= ( ThisType&& ) = delete;
171       ThisType &operator= ( const ThisType& ) = delete;
172 
dofVector()173       DofVectorType &dofVector()
174       {
175         return asImp().dofVector();
176       }
dofVector() const177       const DofVectorType &dofVector() const
178       {
179         return asImp().dofVector();
180       }
181 
182       /** \brief obtain the name of the discrete function
183        *
184        *  \returns string holding name of discrete function
185        */
name() const186       const std::string &name () const
187       {
188         return asImp().name();
189       }
190 
191       /** \brief obtain the name of the discrete function
192        *
193        *  \returns string holding name of discrete function
194        */
name()195       std::string &name ()
196       {
197         return asImp().name();
198       }
199 
200       /** \brief obtain an upper bound on the polynomial order of the underlying space.
201        */
order() const202       const std::string &order () const
203       {
204         return asImp().order();
205       }
206 
207       /** \copydoc Dune::Fem::DiscreteFunctionSpaceInterface::continuous */
continuous() const208       bool continuous() const
209       {
210         return asImp().continuous();
211       }
212 
213       /** \brief obtain a reference to the corresponding DiscreteFunctionSpace */
space() const214       const DiscreteFunctionSpaceType &space () const
215       {
216         return asImp().space();
217       }
218 
219       /** \brief obtain a reference to the underlying grid part */
gridPart() const220       const GridPartType &gridPart () const
221       {
222         return asImp().gridPart();
223       }
224 
225       /** \brief obtain a local function for an entity (read-write)
226        *
227        *  \param[in]  entity  Entity to focus view of discrete function
228        *  \returns a local function associated with the entity
229        */
230       [[deprecated("Use {Const,Temporary,Mutable}LocalFunction and LocalContribution instead!")]]
localFunction(const EntityType & entity)231       LocalFunctionType localFunction ( const EntityType &entity )
232       {
233         return asImp().localFunction( entity );
234       }
235 
236       /** \brief obtain a local function for an entity (read-write)
237        *
238        *  \param[in]  entity  Entity to focus view of discrete function
239        *  \returns a local function associated with the entity
240        */
241       [[deprecated("Use {Const,Temporary,Mutable}LocalFunction and LocalContribution instead!")]]
localFunction(const EntityType & entity) const242       const LocalFunctionType localFunction ( const EntityType &entity ) const
243       {
244         return asImp().localFunction( entity );
245       }
246 
247       /** \brief obtain an uninitialized local function (read-write)
248        *
249        *  \note before calling any method of the local function initialize it passing an entity
250        *
251        *  \returns an uninitialized local function
252        */
253       [[deprecated("Use {Const,Temporary,Mutable}LocalFunction and LocalContribution instead!")]]
localFunction()254       LocalFunctionType localFunction ()
255       {
256         return asImp().localFunction();
257       }
258 
259 
260       /** \brief add scaled local Dofs to dof vector associated with the entity
261        *
262        *  \param[in]  entity    Entity to focus view of discrete function
263        *  \param[in]  s         scaling factor
264        *  \param[in]  localDofs the local dofs vector to be added
265        */
266       template< class LocalDofs >
addScaledLocalDofs(const EntityType & entity,const RangeFieldType & s,const LocalDofs & localDofs)267       void addScaledLocalDofs ( const EntityType &entity, const RangeFieldType &s, const LocalDofs &localDofs )
268       {
269         asImp().addScaledLocalDofs( entity, s, localDofs );
270       }
271 
272       /** \brief add local Dofs to dof vector associated with the entity
273        *
274        *  \param[in]  entity    Entity to focus view of discrete function
275        *  \param[in]  localDofs the local dofs vector to be added
276        */
277       template< class LocalDofs >
addLocalDofs(const EntityType & entity,const LocalDofs & localDofs)278       void addLocalDofs ( const EntityType &entity, const LocalDofs &localDofs )
279       {
280         asImp().addLocalDofs( entity, localDofs );
281       }
282 
283       /** \brief set local Dofs to dof vector associated with the entity
284        *
285        *  \param[in]  entity    Entity to focus view of discrete function
286        *  \param[in]  localDofs the local dofs vector to be set
287        */
288       template< class LocalDofs >
setLocalDofs(const EntityType & entity,const LocalDofs & localDofs)289       void setLocalDofs ( const EntityType &entity, const LocalDofs &localDofs )
290       {
291         asImp().setLocalDofs( entity, localDofs );
292       }
293 
294       /** \brief fill local Dofs to dof vector associated with the entity
295        *
296        *  \param[in]   entity    Entity to focus view of discrete function
297        *  \param[out]  localDofs the local dofs vector to be set
298        *
299        *  \note localDofs should have sufficient size to store the dof values
300        */
301       template< class Vector >
getLocalDofs(const EntityType & entity,Vector & localDofs) const302       void getLocalDofs ( const EntityType &entity, Vector &localDofs ) const
303       {
304         asImp().getLocalDofs( entity, localDofs );
305       }
306 
307       /** \brief obtain an uninitialized local function (read-write)
308        *
309        * \note before calling any method of the local function initialize it passing an entity
310        *
311        *  \returns an uninitialized local function
312        */
313       [[deprecated("Use {Const,Temporary,Mutable}LocalFunction and LocalContribution instead!")]]
localFunction() const314       const LocalFunctionType localFunction () const
315       {
316         return asImp().localFunction();
317       }
318 
319       /** \brief set all degrees of freedom to zero */
clear()320       void clear()
321       {
322         asImp().clear();
323       }
324 
325       /** \brief obtain total number of DoFs
326        *
327        *  The number of DoFs (degrees of freedom) can also be seen as the size
328        *  of the discrete function, i.e., the size of the vector that forms this
329        *  discrete funciton.
330        *
331        *  \returns total number of DoFs for this discrete function
332        */
size() const333       int size() const
334       {
335         return asImp().size();
336       }
337 
338       /** \brief obtain total number of blocks, i.e. size / blockSize.
339        *
340        *  The number of blocks of DoFs (degrees of freedom) can also be seen
341        *  as the size of the discrete function divided by the blockSize.
342        *
343        *  \returns total number of DoFs blocks
344        */
blocks() const345       int blocks() const
346       {
347         return asImp().blocks();
348       }
349 
350       /** \brief obtain an iterator pointing to the first DoF (read-only)
351        *
352        *  \returns a DoF iterator pointing to first DoF (degre of freedom)
353        */
dbegin() const354       ConstDofIteratorType dbegin () const
355       {
356         return asImp().dbegin ();
357       }
358 
359       /** \brief obtain an iterator pointing behind the last DoF (read-only)
360        *
361        *  \returns a DoF iterator pointing behind the last DoF (degree of freedom)
362        */
dend() const363       ConstDofIteratorType dend () const
364       {
365         return asImp().dend ();
366       }
367 
368       /** \brief obtain an iterator pointing to the first DoF (read-write)
369        *
370        *  \returns a DoF iterator pointing to first DoF (degre of freedom)
371        */
dbegin()372       DofIteratorType dbegin ()
373       {
374         return asImp().dbegin ();
375       }
376 
377       /** \brief obtain an iterator pointing behind the last DoF (read-write)
378        *
379        *  \returns a DoF iterator pointing behind the last DoF (degree of freedom)
380        */
dend()381       DofIteratorType dend ()
382       {
383         return asImp().dend ();
384       }
385 
386       /** \brief axpy operation
387        *
388        *  Adds s * g to this discrete function.
389        *
390        *  \param[in]  s  scalar value to scale g with
391        *  \param[in]  g  discrete function to add
392        */
axpy(const RangeFieldType & s,const DiscreteFunctionInterfaceType & g)393       void axpy( const RangeFieldType &s, const DiscreteFunctionInterfaceType &g )
394       {
395         asImp().axpy( s, g );
396       }
397 
398       /** \brief Scalar product between the DoFs of two discrete functions
399        *
400        *  \note This is a parallel scalar product, so do not sum over all
401        *        processes after calling scalarProductDofs!
402        *
403        *  \note It is assumed that the discrete function has been communicated
404        *        (i.e., every local DoF hat the value of the corresponding global
405        *        DoF).
406        *
407        *  \param[in]  other  discrete function to evaluate the scalar product with
408        *
409        *  \returns the scalar product of the DoF-vectors
410        */
411       template <class DFType>
scalarProductDofs(const DiscreteFunctionInterface<DFType> & other) const412       RangeFieldType scalarProductDofs ( const DiscreteFunctionInterface< DFType > &other ) const
413       {
414         return asImp().scalarProductDofs( other.asImp() );
415       }
416 
417       /** \brief Squared small l^2 norm of all dofs
418        *
419        *  \note This is already parallel, so do not sum over all
420        *        processes after calling scalarProductDofs!
421        *
422        *  \note It is assumed that the discrete function has been communicated
423        *        (i.e., every local DoF hat the value of the corresponding global
424        *        DoF).
425        *
426        *  \returns the squared norm of the DoF-vectors
427        */
normSquaredDofs() const428       typename Dune::FieldTraits< RangeFieldType >::real_type normSquaredDofs ( ) const
429       {
430         return asImp().normSquaredDofs( );
431       }
432 
433       /** \brief print all DoFs to a stream (for debugging purposes)
434        *
435        *  \param[in]  out  stream to print to
436        */
print(std::ostream & out) const437       void print( std :: ostream &out ) const
438       {
439         asImp().print( out );
440       }
441 
442       /** \brief check for NaNs
443        *  \returns if one of the DoFs is NaN \b false is returned, otherwise \b true
444        */
dofsValid() const445       bool dofsValid () const
446       {
447         return asImp().dofsValid();
448       }
449 
450       /** \brief assign the DoFs of another discrete function to this one
451        *
452        *  \param[in]  g  discrete function which is copied
453        */
454       template < class DFType >
assign(const DiscreteFunctionInterface<DFType> & g)455       void assign( const DiscreteFunctionInterface< DFType > &g )
456       {
457         asImp().assign( g );
458       }
459 
460       /** \brief return reference to data handle object */
461       template< class Operation >
dataHandle(const Operation & operation)462       typename CommDataHandle< Operation >::Type dataHandle( const Operation &operation )
463       {
464         return asImp().dataHandle( operation );
465       }
466 
467       /** \brief do default communication of space for this discrete function */
communicate()468       void communicate()
469       {
470         CHECK_AND_CALL_INTERFACE_IMPLEMENTATION( asImp().communicate() );
471       }
472 
473       /** \brief add another discrete function to this one
474        *
475        *  \param[in]  g  discrete function to add
476        *
477        *  \returns a reference to this discrete function (i.e. *this)
478        */
479       template < class DFType >
operator +=(const DiscreteFunctionInterface<DFType> & g)480       DiscreteFunctionType &operator+=(const DiscreteFunctionInterface< DFType > &g)
481       {
482         return asImp().operator+=( g );
483       }
484 
485       /** \brief substract all degrees of freedom from given discrete function using the dof iterators
486        *
487        *  \param[in] g discrete function which is substracted from this discrete function
488        *
489        *  \returns reference to this (i.e. *this)
490        */
491       template < class DFType >
operator -=(const DiscreteFunctionInterface<DFType> & g)492       DiscreteFunctionType &operator-=(const DiscreteFunctionInterface< DFType > &g)
493       {
494         return asImp().operator-=( g );
495       }
496 
497       /** \brief multiply all DoFs by a scalar factor
498        *
499        *  \param[in]  scalar  factor to muliply all DoFs by
500        *
501        *  \returns a reference to this discrete function (i.e. *this)
502        */
operator *=(const RangeFieldType & scalar)503       DiscreteFunctionType &operator*= ( const RangeFieldType &scalar )
504       {
505         return asImp() *= scalar;
506       }
507 
508       /** \brief devide all DoFs by a scalar factor
509        *
510        *  \param[in]  scalar  factor to divide all DoFs by
511        *
512        *  \returns a reference to this discrete function (i.e. *this)
513        */
operator /=(const RangeFieldType & scalar)514       DiscreteFunctionType &operator/= ( const RangeFieldType &scalar )
515       {
516         return asImp() /= scalar;
517       }
518 
519       /** \brief read the discrete function from a stream
520        *
521        *  \param[in]  in  stream to read the discrete function from
522        *
523        *  \note This call will automatically enable dof compression for this
524        *        discrete function.
525        */
526       template< class StreamTraits >
read(InStreamInterface<StreamTraits> & in)527       void read ( InStreamInterface< StreamTraits > &in )
528       {
529         asImp().read( in );
530       }
531 
532       /** \brief write the discrete function into a stream
533        *
534        *  \param[in]  out  stream to write the discrete function to
535        */
536       template< class StreamTraits >
write(OutStreamInterface<StreamTraits> & out) const537       void write ( OutStreamInterface< StreamTraits > &out ) const
538       {
539         asImp().write( out );
540       }
541 
542       /** \brief Enable this discrete function for dof compression,
543        *   i.e. during grid changes a dof compression
544        *   is done when the DofManagers compress is called.
545        */
enableDofCompression()546       void enableDofCompression()
547       {
548         asImp().enableDofCompression();
549       }
550 
551       //TODO: this needs to be revised, the definition should be in GridPart
552       typedef LoadBalanceLeafData< ThisType > DefaultLoadBalanceContainsCheckType;
defaultLoadBalanceContainsCheck() const553       DefaultLoadBalanceContainsCheckType defaultLoadBalanceContainsCheck() const
554       {
555         return DefaultLoadBalanceContainsCheckType( *this );
556       }
557     };
558 
559 
560 
561     //*************************************************************************
562     //
563     //  --DiscreteFunctionDefault
564     //
565     //! Default implementation of the discrete function. This class is
566     //! responsible for the dof storage. Different implementations of the
567     //! discrete function use different dof storage.
568     //! The default implementation provides +=, -= and so on operators and
569     //! a DofIterator access, which can run over all dofs in an efficient way.
570     //! Furthermore with an entity you can access a local function to evaluate
571     //! the discrete function by multiplying the dofs and the basefunctions.
572     //!
573     //*************************************************************************
574     template< class Impl >
575     class DiscreteFunctionDefault
576     : public DiscreteFunctionInterface< Impl > ,
577       public PersistentObject
578     {
579       typedef DiscreteFunctionDefault< Impl > ThisType;
580       typedef DiscreteFunctionInterface< Impl > BaseType;
581 
582     public:
583       typedef typename BaseType :: Traits Traits;
584 
585       //! type of the discrete function (Barton-Nackman parameter)
586       typedef Impl DiscreteFunctionType;
587 
588       typedef typename BaseType::DiscreteFunctionInterfaceType DiscreteFunctionInterfaceType;
589 
590     private:
591       typedef DiscreteFunctionDefault< Impl > DiscreteFunctionDefaultType;
592 
593       enum { myId_ = 0 };
594 
595     protected:
596       typedef ParallelScalarProduct< DiscreteFunctionInterfaceType > ScalarProductType;
597 
598     public:
599       //! type of discrete function space
600       typedef typename BaseType::DiscreteFunctionSpaceType DiscreteFunctionSpaceType;
601 
602       //! type of the underlying grid part
603       typedef typename BaseType::GridPartType GridPartType;
604 
605       //! type of domain vector
606       typedef typename DiscreteFunctionSpaceType :: DomainType DomainType;
607       //! type of range vector
608       typedef typename DiscreteFunctionSpaceType :: RangeType RangeType;
609       //! type of jacobian
610       typedef typename DiscreteFunctionSpaceType :: JacobianRangeType JacobianRangeType;
611       //! type of hessian
612       typedef typename DiscreteFunctionSpaceType :: HessianRangeType HessianRangeType;
613 
614       //! type of domain field (usually a float type)
615       typedef typename DiscreteFunctionSpaceType :: DomainFieldType DomainFieldType;
616       //! type of range field (usually a float type)
617       typedef typename DiscreteFunctionSpaceType :: RangeFieldType RangeFieldType;
618 
619       //! type of the dof iterator
620       typedef typename Traits :: DofIteratorType DofIteratorType;
621       //! type of the const dof iterator
622       typedef typename Traits :: ConstDofIteratorType ConstDofIteratorType;
623 
624       //! type of DofVector
625       typedef typename Traits :: DofVectorType     DofVectorType;
626 
627       //! type of LocalDofVector
628       typedef typename Traits :: LocalDofVectorType LocalDofVectorType;
629       //! type of LocalDofVector
630       typedef typename Traits :: LocalDofVectorAllocatorType LocalDofVectorAllocatorType;
631 
632       //! type of local functions
633       typedef typename BaseType :: LocalFunctionType LocalFunctionType;
634       typedef typename LocalFunctionType::LocalCoordinateType LocalCoordinateType;
635 
636       typedef typename BaseType :: DofBlockType DofBlockType;
637       typedef typename BaseType :: ConstDofBlockType ConstDofBlockType;
638       typedef typename BaseType :: DofBlockPtrType DofBlockPtrType;
639       typedef typename BaseType :: ConstDofBlockPtrType ConstDofBlockPtrType;
640 
641       typedef typename BaseType :: EntityType EntityType ;
642 
643       typedef typename BaseType :: DofType DofType;
644 
645       //! size type of the block vector
646       typedef typename DofVectorType::SizeType SizeType;
647 
648       using BaseType::blockSize;
649 
650       template< class Operation >
651       struct CommDataHandle
652       : public BaseType :: template CommDataHandle< Operation >
653       {};
654 
655     protected:
656       using BaseType :: asImp;
657 
658       typedef TemporaryLocalFunction< DiscreteFunctionSpaceType > TemporaryLocalFunctionType;
659 
660       /** \brief Constructor storing discrete function space and local function
661        *         factory
662        *
663        *  The discrete function space is passed to the interface class and the
664        *  local function storage is initialized.
665        *
666        *  \param[in]  name       name of the discrete function
667        *  \param[in]  dfSpace    discrete function space
668        *  \param[in]  lfFactory  local function factory
669        */
670       DiscreteFunctionDefault ( const std::string &name, const DiscreteFunctionSpaceType &dfSpace );
671 
672       DiscreteFunctionDefault ( std::string name, std::shared_ptr< const DiscreteFunctionSpaceType > dfSpace );
673 
674       DiscreteFunctionDefault ( const ThisType& );
675       DiscreteFunctionDefault ( ThisType && other );
676 
677     public:
678       ThisType& operator= ( ThisType&& ) = delete;
679       ThisType &operator= ( const ThisType& ) = delete;
680 
681       // Default Implementations
682       // -----------------------
683 
684       /** \copydoc Dune::Fem::DiscreteFunctionInterface::name() const */
name() const685       const std::string &name () const { return name_; }
686 
687       /** \copydoc Dune::Fem::DiscreteFunctionInterface::name() */
name()688       std::string &name () { return name_; }
689 
690       /** \copydoc Dune::Fem::DiscreteFunctionInterface::order() */
order() const691       constexpr int order() const
692       {
693         return space().order();
694       }
695 
696       /** \copydoc Dune::Fem::DiscreteFunctionInterface::continuous */
continuous() const697       bool continuous() const
698       {
699         return space().continuous();
700       }
701 
702       /** \copydoc Dune::Fem::DiscreteFunctionInterface::space() const */
space() const703       const DiscreteFunctionSpaceType &space () const { return *dfSpace_; }
704 
705       /** \brief obtain a reference to the underlying grid part */
gridPart() const706       const GridPartType &gridPart () const { return space().gridPart(); }
707 
708       /** \copydoc Dune::Fem::DiscreteFunctionInterface::localFunction(const EntityType &entity) */
709       [[deprecated("Use {Const,Temporary,Mutable}LocalFunction and LocalContribution instead!")]]
localFunction(const EntityType & entity)710       LocalFunctionType localFunction ( const EntityType &entity ) { return LocalFunctionType( asImp(), entity ); }
711 
712       /** \copydoc Dune::Fem::DiscreteFunctionInterface::localFunction(const EntityType &entity) */
713       [[deprecated("Use {Const,Temporary,Mutable}LocalFunction and LocalContribution instead!")]]
localFunction(const EntityType & entity) const714       const LocalFunctionType localFunction ( const EntityType &entity ) const { return LocalFunctionType( asImp(), entity ); }
715 
716       /** \copydoc Dune::Fem::DiscreteFunctionInterface::localFunction() */
717       [[deprecated("Use {Const,Temporary,Mutable}LocalFunction and LocalContribution instead!")]]
localFunction()718       LocalFunctionType localFunction () { return LocalFunctionType( asImp() ); }
719 
720       /** \copydoc Dune::Fem::DiscreteFunctionInterface::localFunction() */
721       [[deprecated("Use {Const,Temporary,Mutable}LocalFunction and LocalContribution instead!")]]
localFunction() const722       const LocalFunctionType localFunction () const { return LocalFunctionType( asImp() ); }
723 
724       /** \copydoc Dune::Fem::DiscreteFunctionInterface::clear() */
clear()725       void clear() { dofVector().clear(); }
726 
dofVector()727       DofVectorType &dofVector() { return asImp().dofVector(); }
dofVector() const728       const DofVectorType &dofVector() const { return asImp().dofVector(); }
729 
730       /** \copydoc Dune::Fem::DiscreteFunctionInterface::blocks() */
blocks() const731       int blocks() const { return dofVector().size(); }
732 
733       /** \copydoc Dune::Fem::DiscreteFunctionInterface::block( unsigned int index ) */
block(unsigned int index)734       DofBlockPtrType block ( unsigned int index )
735       {
736         return dofVector().blockPtr( index );
737       }
738 
739       /** \copydoc Dune::Fem::DiscreteFunctionInterface::block( unsigned int index ) const */
block(unsigned int index) const740       ConstDofBlockPtrType block ( unsigned int index ) const
741       {
742         return dofVector().blockPtr( index );
743       }
744 
745       /** \brief Return the number of blocks in the block vector
746        *
747        *  \return Number of block in the block vector
748        */
size() const749       SizeType size () const { return dofVector().size() * blockSize; }
750 
751       /** \brief Obtain the constant iterator pointing to the first dof
752        *
753        *  \return Constant iterator pointing to the first dof
754        */
dbegin() const755       ConstDofIteratorType dbegin () const { return dofVector().begin(); }
756 
757       /** \brief Obtain the non-constant iterator pointing to the first dof
758        *
759        *  \return Non-Constant iterator pointing to the first dof
760        */
dbegin()761       DofIteratorType dbegin () { return dofVector().begin(); }
762 
763       /** \brief Obtain the constant iterator pointing to the last dof
764        *
765        *  \return Constant iterator pointing to the last dof
766        */
dend() const767       ConstDofIteratorType dend () const { return dofVector().end(); }
768 
769       /** \brief Obtain the non-constant iterator pointing to the last dof
770        *
771        *  \return Non-Constant iterator pointing to the last dof
772        */
dend()773       DofIteratorType dend () { return dofVector().end(); }
774 
775       /** \copydoc Dune::Fem::DiscreteFunctionInterface::axpy(const RangeFieldType &s,const DiscreteFunctionInterfaceType &g) */
776       template <class DFType>
777       void axpy ( const RangeFieldType &s, const DiscreteFunctionInterface< DFType > &g );
778 
779       /** \copydoc Dune::Fem::DiscreteFunctionInterface::axpy(const RangeFieldType &s,const DiscreteFunctionInterfaceType &g) */
axpy(const RangeFieldType & s,const DiscreteFunctionInterfaceType & g)780       void axpy ( const RangeFieldType &s, const DiscreteFunctionInterfaceType& g )
781       {
782         dofVector().axpy( s, g.dofVector() );
783       }
784 
785       /** \copydoc Dune::Fem::DiscreteFunctionInterface::scalarProductDofs */
786       template <class DFType>
scalarProductDofs(const DiscreteFunctionInterface<DFType> & other) const787       RangeFieldType scalarProductDofs ( const DiscreteFunctionInterface< DFType > &other ) const
788       {
789         return scalarProduct_.scalarProductDofs( *this, other );
790       }
791 
792       /** \copydoc Dune::Fem::DiscreteFunctionInterface::normSquaredDofs */
normSquaredDofs() const793       typename Dune::FieldTraits< RangeFieldType >::real_type normSquaredDofs ( ) const
794       {
795         return std::real( (*this).scalarProductDofs( *this ));
796       }
797 
798       /** \copydoc Dune::Fem::DiscreteFunctionInterface::print */
799       void print ( std :: ostream &out ) const;
800 
801       /** \copydoc Dune::Fem::DiscreteFunctionInterface::dofsValid */
802       inline bool dofsValid () const;
803 
804       /** \copydoc Dune::Fem::DiscreteFunctionInterface::assign(const DiscreteFunctionInterfaceType &g) */
805       template <class DFType>
806       void assign ( const DiscreteFunctionInterface< DFType > &g );
807 
808       /** \copydoc Dune::Fem::DiscreteFunctionInterface::assign(const DiscreteFunctionInterfaceType &g) */
assign(const DiscreteFunctionType & g)809       void assign ( const DiscreteFunctionType &g )
810       {
811         dofVector() = g.dofVector();
812       }
813 
814       /** \copydoc Dune::Fem::DiscreteFunctionInterface::dataHandle */
815       template< class Operation >
816       typename CommDataHandle< Operation >::Type dataHandle ( const Operation &operation );
817 
818       /** \copydoc Dune::Fem::DiscreteFunctionInterface::communicate() */
communicate()819       void communicate()
820       {
821         assert( Fem :: ThreadManager :: singleThreadMode() );
822         this->space().communicate( asImp() );
823       }
824 
825       /** \copydoc Dune::Fem::Function::evaluate(const DomainType &x,RangeType &value) const */
evaluate(const DomainType & x,RangeType & value) const826       void evaluate ( const DomainType &x, RangeType &value ) const
827       {
828         asImp().evaluateGlobal( x, [ &value ] ( const LocalCoordinateType &x, const TemporaryLocalFunctionType &localFunction )
829                                               { localFunction.evaluate( x, value ); } );
830       }
831 
832       /** \copydoc Dune::Fem::Function::jacobian(const DomainType &x,JacobianRangeType &jacobian) const */
jacobian(const DomainType & x,JacobianRangeType & jacobian) const833       void jacobian ( const DomainType &x, JacobianRangeType &jacobian ) const
834       {
835         asImp().evaluateGlobal( x, [ &jacobian ] ( const LocalCoordinateType &x, const TemporaryLocalFunctionType &localFunction )
836                                                  { localFunction.jacobian( x, jacobian ); } );
837 
838       }
839 
840       /** \copydoc Dune::Fem::Function::hessian (const DomainType &x,HessianRangeType &hessian) const */
hessian(const DomainType & x,HessianRangeType & hessian) const841       void hessian ( const DomainType &x, HessianRangeType &hessian ) const
842       {
843         asImp().evaluateGlobal( x, [ &hessian ] ( const LocalCoordinateType &x, const TemporaryLocalFunctionType &localFunction )
844                                                 { localFunction.hessian( x, hessian ); } );
845       }
846 
847       /** \copydoc Dune::Fem::DiscreteFunctionInterface::operator+=(const DiscreteFunctionInterface< DFType > &g) */
848       template <class DFType>
849       DiscreteFunctionType &operator+=(const DiscreteFunctionInterface< DFType > &g);
850 
851       /** \copydoc Dune::Fem::DiscreteFunctionInterface::operator+=(const DiscreteFunctionInterface< DFType > &g) */
operator +=(const DiscreteFunctionType & g)852       DiscreteFunctionType &operator+=(const DiscreteFunctionType &g)
853       {
854         dofVector() += g.dofVector();
855         return asImp();
856       }
857 
858       /** \copydoc Dune::Fem::DiscreteFunctionInterface::operator-=(const DiscreteFunctionInterface< DFType > &g) */
859       template <class DFType>
860       DiscreteFunctionType &operator-=(const DiscreteFunctionInterface< DFType > &g);
861 
862       /** \copydoc Dune::Fem::DiscreteFunctionInterface::operator-=(const DiscreteFunctionInterface< DFType > &g) */
operator -=(const DiscreteFunctionType & g)863       DiscreteFunctionType &operator-=(const DiscreteFunctionType& g)
864       {
865         dofVector() -= g.dofVector();
866         return asImp();
867       }
868 
869       /** \brief multiply all DoFs with a scalar factor
870        *
871        *  \param[in]  scalar  factor to multiply DoFs with
872        *
873        *  \returns reference to this discrete function (i.e. *this)
874        */
operator *=(const RangeFieldType & scalar)875       DiscreteFunctionType &operator*= ( const RangeFieldType &scalar )
876       {
877         dofVector() *= scalar;
878         return asImp();
879       }
880 
881       /** \brief devide all DoFs by a scalar factor
882        *
883        *  \param[in]  scalar  factor with which all dofs are devided
884        *
885        *  \returns reference to this discrete function (i.e. *this)
886        */
operator /=(const RangeFieldType & scalar)887       DiscreteFunctionType &operator/= ( const RangeFieldType &scalar )
888       {
889         return BaseType :: operator*=( RangeFieldType(1 ) / scalar );
890       }
891 
892       /** \copydoc Dune::Fem::DiscreteFunctionInterface::read */
893       template< class StreamTraits >
894       inline void read ( InStreamInterface< StreamTraits > &in );
895 
896       /** \copydoc Dune::Fem::DiscreteFunctionInterface::write */
897       template< class StreamTraits >
898       inline void write ( OutStreamInterface< StreamTraits > &out ) const;
899 
900       /** \copydoc Dune::Fem::DiscreteFunctionInterface::enableDofCompression()
901        *
902        *  \note The default implementation does nothing.
903        */
enableDofCompression()904       void enableDofCompression ()
905       {}
906 
907 
908       /** \copydoc Dune::Fem::DiscreteFunctionInterface::addScaledLocalDofs */
909       template< class LocalDofs >
addScaledLocalDofs(const EntityType & entity,const RangeFieldType & s,const LocalDofs & localDofs)910       void addScaledLocalDofs ( const EntityType &entity, const RangeFieldType &s, const LocalDofs &localDofs )
911       {
912         LeftAddScaled< const LocalDofs, const RangeFieldType > assignFunctor( localDofs, s );
913         space().blockMapper().mapEach( entity, dofBlockFunctor( dofVector(), assignFunctor ) );
914       }
915 
916       /** \copydoc Dune::Fem::DiscreteFunctionInterface::addLocalDofs */
917       template< class LocalDofs >
addLocalDofs(const EntityType & entity,const LocalDofs & localDofs)918       void addLocalDofs ( const EntityType &entity, const LocalDofs &localDofs )
919       {
920         LeftAdd< const LocalDofs > assignFunctor( localDofs );
921         space().blockMapper().mapEach( entity, dofBlockFunctor( dofVector(), assignFunctor ) );
922       }
923 
924       /** \copydoc Dune::Fem::DiscreteFunctionInterface::setLocalDofs */
925       template< class LocalDofs >
setLocalDofs(const EntityType & entity,const LocalDofs & localDofs)926       void setLocalDofs ( const EntityType &entity, const LocalDofs &localDofs )
927       {
928         LeftAssign< const LocalDofs > assignFunctor( localDofs );
929         space().blockMapper().mapEach( entity, dofBlockFunctor( dofVector(), assignFunctor ) );
930       }
931 
932       /** \copydoc Dune::Fem::DiscreteFunctionInterface::getLocalDofs */
933       template< class Vector >
getLocalDofs(const EntityType & entity,Vector & localDofs) const934       void getLocalDofs ( const EntityType &entity, Vector &localDofs ) const
935       {
936         AssignFunctor< Vector > assignFunctor( localDofs );
937         space().blockMapper().mapEach( entity, dofBlockFunctor( dofVector(), assignFunctor ) );
938       }
939 
940       // Non-Interface Methods
941       // ---------------------
942 
943       template <class DFType>
944       inline bool operator== ( const DiscreteFunctionInterface< DFType>  &g ) const;
945 
946       template <class DFType>
operator !=(const DiscreteFunctionInterface<DFType> & g) const947       bool operator!= ( const DiscreteFunctionInterface< DFType > &g ) const
948       {
949         return !(operator==( g ));
950       }
951 
952       /** \brief obtain the local function storage
953        *
954        *  \returns a reference to the local function storage
955        */
localDofVectorAllocator() const956       LocalDofVectorAllocatorType &localDofVectorAllocator () const
957       {
958         return ldvAllocator_;
959       }
960 
961       /** \brief Initiate the assemble of values using the LocalContribution concept
962        *  \tparam AssembleOperation the specific operation (Add, Set, ...)
963        */
964       template< class AssembleOperation >
beginAssemble()965       void beginAssemble ()
966       {
967         const std::type_index id( typeid( AssembleOperation ) );
968         if( assembleOperation_ != id )
969         {
970           if( assembleOperation_ != std::type_index( typeid( void ) ) )
971             DUNE_THROW( InvalidStateException, "Another assemble operation in progress" );
972           assembleOperation_ = id;
973           assert( assembleCount_ == 0 );
974           AssembleOperation::begin( asImp() );
975         }
976         ++assembleCount_;
977       }
978 
979       /** \brief Finalize the assemble of values using the LocalContribution concept
980        *  \tparam AssembleOperation the specific operation (Add, Set, ...)
981        */
982       template< class AssembleOperation >
endAssemble()983       void endAssemble ()
984       {
985         const std::type_index id( typeid( AssembleOperation ) );
986         if( assembleOperation_ != id )
987           DUNE_THROW( InvalidStateException, "Assemble operation not in progress" );
988         assert( assembleCount_ > 0 );
989         if( --assembleCount_ == 0 )
990         {
991           AssembleOperation::end( asImp() );
992           assembleOperation_ = std::type_index( typeid( void ) );
993         }
994       }
995 
996       //! get local Dofs and store a reference to it in the LocalDofVector
getLocalDofReferences(const EntityType & entity,LocalDofVectorType & localDofs)997       void getLocalDofReferences ( const EntityType &entity, LocalDofVectorType &localDofs )
998       {
999         AssignVectorReference< LocalDofVectorType > assignFunctor( localDofs );
1000         space().blockMapper().mapEach( entity, dofBlockFunctor( dofVector(), assignFunctor ) );
1001       }
1002 
1003     protected:
1004       /** \copydoc Dune::PersistentObject::backup */
backup() const1005       virtual void backup() const
1006       {
1007         // get backup stream from persistence manager and write to it
1008         write( PersistenceManager :: backupStream() );
1009       }
1010 
1011       /** \copydoc Dune::PersistentObject::restore */
restore()1012       virtual void restore()
1013       {
1014         // get restore stream from persistence manager and read from it
1015         read( PersistenceManager :: restoreStream() );
1016       }
1017 
1018       /** \copydoc Dune::PersistentObject::insertSubData */
1019       virtual void insertSubData();
1020 
1021       /** \copydoc Dune::PersistentObject::removeSubData */
1022       virtual void removeSubData();
1023 
1024       /** \brief evaluate functor in global coordinate */
1025       template< class Functor >
1026       void evaluateGlobal ( const DomainType &x, Functor functor ) const;
1027 
1028       // only PersistenceManager should call backup and restore
1029       friend class PersistenceManager;
1030 
1031       std::shared_ptr< const DiscreteFunctionSpaceType > dfSpace_;
1032 
1033       // the local function storage
1034       typename Traits :: LocalDofVectorStackType ldvStack_;
1035       mutable LocalDofVectorAllocatorType ldvAllocator_;
1036 
1037       mutable TemporaryLocalFunctionType localFunction_;
1038 
1039       std::string name_;
1040       ScalarProductType scalarProduct_;
1041 
1042       std::type_index assembleOperation_ = std::type_index( typeid( void ) );;
1043       std::size_t assembleCount_ = 0;
1044     }; // end class DiscreteFunctionDefault
1045 
1046 
1047     template< class DiscreteFunction >
1048     class ManagedDiscreteFunction;
1049 
1050 
1051     template< class DiscreteFunction >
1052     struct DiscreteFunctionTraits< ManagedDiscreteFunction< DiscreteFunction > >
1053     : public DiscreteFunctionTraits< DiscreteFunction > {};
1054 
1055 
1056     /** \class DiscreteFunctionTraits
1057      *  \brief Traits class for a DiscreteFunction
1058      *
1059      *  \tparam  DiscreteFunctionSpace   space the discrete function lives in
1060      *  \tparam  DofVector             implementation class of the block vector
1061      */
1062     template< typename DiscreteFunctionSpace, typename DofVector >
1063     struct DefaultDiscreteFunctionTraits
1064     {
1065       typedef DofVector DofVectorType;
1066 
1067       typedef DiscreteFunctionSpace                           DiscreteFunctionSpaceType;
1068       typedef typename DiscreteFunctionSpaceType::DomainType  DomainType;
1069       typedef typename DiscreteFunctionSpaceType::RangeType   RangeType;
1070 
1071       typedef typename DofVectorType::IteratorType            DofIteratorType;
1072       typedef typename DofVectorType::ConstIteratorType       ConstDofIteratorType;
1073       typedef typename DofVectorType::DofBlockType            DofBlockType;
1074       typedef typename DofVectorType::ConstDofBlockType       ConstDofBlockType;
1075       typedef typename DofVectorType::DofBlockPtrType         DofBlockPtrType;
1076       typedef typename DofVectorType::ConstDofBlockPtrType    ConstDofBlockPtrType;
1077 
1078       typedef typename DiscreteFunctionSpaceType::BlockMapperType MapperType;
1079       typedef typename DofVectorType::FieldType DofType;
1080 
1081       typedef ThreadSafeValue< UninitializedObjectStack >         LocalDofVectorStackType;
1082       typedef StackAllocator< DofType, LocalDofVectorStackType* > LocalDofVectorAllocatorType;
1083       typedef DynamicReferenceVector< DofType, LocalDofVectorAllocatorType > LocalDofVectorType;
1084     };
1085 
1086 
1087   ///@}
1088 
1089   } // end namespace Fem
1090 
1091 } // end namespace Dune
1092 
1093 #include "discretefunction_inline.hh"
1094 
1095 #include "gridfunctionadapter.hh"
1096 #endif // #ifndef DUNE_FEM_DISCRETEFUNCTION_HH
1097