1 #ifndef DUNE_FEM_DOFMANAGER_HH
2 #define DUNE_FEM_DOFMANAGER_HH
3 
4 #include <cassert>
5 #include <string>
6 #include <list>
7 
8 #include <dune/common/exceptions.hh>
9 #include <dune/common/stdstreams.hh>
10 #include <dune/common/version.hh>
11 
12 #if HAVE_DUNE_ALUGRID
13 #include <dune/alugrid/common/interfaces.hh>
14 #endif
15 
16 #include <dune/fem/gridpart/common/indexset.hh>
17 #include <dune/fem/io/parameter.hh>
18 #include <dune/fem/io/streams/standardstreams.hh>
19 #include <dune/fem/misc/gridobjectstreams.hh>
20 #include <dune/fem/misc/threads/threadmanager.hh>
21 #include <dune/fem/space/common/datacollector.hh>
22 #include <dune/fem/space/common/restrictprolonginterface.hh>
23 #include <dune/fem/space/mapper/dofmapper.hh>
24 #include <dune/fem/storage/dynamicarray.hh>
25 #include <dune/fem/storage/singletonlist.hh>
26 
27 #include <dune/grid/common/datahandleif.hh>
28 #if HAVE_DUNE_ALUGRID
29 #include <dune/alugrid/common/ldbhandleif.hh>
30 #endif
31 
32 namespace Dune
33 {
34 
35   namespace Fem
36   {
37 
38     /** @addtogroup DofManager
39 
40         @{
41     **/
42 
43     // forward declaration
44     template <class GridType> class DofManager;
45     template <class DofManagerImp> class DofManagerFactory;
46 
47 
48     ///////////////////////////////////////////////////////////////////////
49     //
50     //  ManagedIndexSetInterface
51     //
52     ///////////////////////////////////////////////////////////////////////
53     /*! This class is the virtual interface for the index sets managed by
54       the DofManager. The derived classes are of the type ManagedIndexSet<IndexSet>.
55       This means we don't have to inherit every index set we want to use with
56       this DofManager.
57       */
58     class ManagedIndexSetInterface
59     {
60       ManagedIndexSetInterface(const ManagedIndexSetInterface& org);
61     protected:
62       // use address of object as id
63       typedef const void * IdentifierType;
64       // pointer to compare index sets
65       IdentifierType setPtr_;
66       // reference counter
67       size_t referenceCounter_;
68 
69       template< class IndexSet >
ManagedIndexSetInterface(const IndexSet & iset)70       explicit ManagedIndexSetInterface ( const IndexSet &iset )
71       : setPtr_( getIdentifier( iset ) ),
72         referenceCounter_( 1 )
73       {
74       }
75 
76     public:
77       virtual ~ManagedIndexSetInterface () = default;
78 
79       //! resize of index set
80       virtual void resize () = 0;
81       //! compress of index set
82       virtual bool compress () = 0;
83 
84       /** \copydoc Dune::PersistentObject :: backup */
85       virtual void backup() const = 0;
86       /** \copydoc Dune::PersistentObject :: restore */
87       virtual void restore() = 0;
88 
89       //! new read/write methods using binary streams
90       virtual void write( StandardOutStream& out ) const = 0;
91       virtual void read( StandardInStream& out ) = 0;
92 
93       //! increase reference counter
addReference()94       void addReference ( ) { ++referenceCounter_; }
95 
96       //! decrease reference counter and return true if zero reached
removeReference()97       bool removeReference ( )
98       {
99         return (--referenceCounter_ == 0);
100       }
101 
102       template< class IndexSet >
equals(const IndexSet & iset) const103       bool equals ( const IndexSet &iset ) const
104       {
105         return (getIdentifier( iset ) == setPtr_);
106       }
107 
108     private:
109       template< class IndexSet >
getIdentifier(const IndexSet & iset) const110       IdentifierType getIdentifier ( const IndexSet &iset ) const
111       {
112         return static_cast< IdentifierType >( &iset );
113       }
114     };
115 
116     template <class IndexSetType, class EntityType> class RemoveIndicesFromSet;
117     template <class IndexSetType, class EntityType> class InsertIndicesToSet;
118 
119     template <class IndexSetType, class EntityType>
120     class ManagedIndexSet :
121       public ManagedIndexSetInterface ,
122       public LocalInlinePlus < ManagedIndexSet<IndexSetType,EntityType> , EntityType >
123     {
124       typedef LocalInterface<EntityType> LocalIndexSetObjectsType;
125     protected:
126       // the dof set stores number of dofs on entity for each codim
127       IndexSetType & indexSet_;
128 
129       // insertion and removal of indices
130       InsertIndicesToSet   <IndexSetType, EntityType> insertIdxObj_;
131       RemoveIndicesFromSet <IndexSetType, EntityType> removeIdxObj_;
132 
133       LocalIndexSetObjectsType & indexSetList_;
134       LocalIndexSetObjectsType & insertList_;
135       LocalIndexSetObjectsType & removeList_;
136 
137     public:
138       //! type of base class
139       typedef ManagedIndexSetInterface BaseType;
140 
141       //! Constructor of MemObject, only to call from DofManager
ManagedIndexSet(const IndexSetType & iset,LocalIndexSetObjectsType & indexSetList,LocalIndexSetObjectsType & insertList,LocalIndexSetObjectsType & removeList)142       ManagedIndexSet ( const IndexSetType & iset,
143                         LocalIndexSetObjectsType & indexSetList,
144                         LocalIndexSetObjectsType & insertList,
145                         LocalIndexSetObjectsType & removeList )
146        : BaseType( iset )
147        , indexSet_ (const_cast<IndexSetType &> (iset))
148        , insertIdxObj_(indexSet_), removeIdxObj_(indexSet_)
149        , indexSetList_(indexSetList)
150        , insertList_(insertList)
151        , removeList_(removeList)
152       {
153         this->setPtr_ = (void *) &indexSet_;
154 
155         indexSetList_ += *this;
156         if( Capabilities::isConsecutiveIndexSet<IndexSetType>::v )
157         {
158           insertList_ += insertIdxObj_;
159           removeList_ += removeIdxObj_;
160         }
161       }
162 
163       //! desctructor
~ManagedIndexSet()164       ~ManagedIndexSet ()
165       {
166         indexSetList_.remove( *this );
167         if( Capabilities::isConsecutiveIndexSet<IndexSetType>::v )
168         {
169           insertList_.remove( insertIdxObj_ );
170           removeList_.remove( removeIdxObj_ );
171         }
172       }
173 
174       //! wrap resize of index set
resize()175       void resize ()
176       {
177         indexSet_.resize();
178       }
179 
180       //! wrap compress of index set
compress()181       bool compress ()
182       {
183         return indexSet_.compress();
184       }
185 
186       // forward backup call to indexSet
backup() const187       virtual void backup () const
188       {
189         indexSet_.backup();
190       }
191 
192       // forward restore call to indexSet
restore()193       virtual void restore ()
194       {
195         indexSet_.restore();
196       }
197 
198       //! new write method
read(StandardInStream & in)199       virtual void read( StandardInStream& in ) { indexSet_.read( in ); }
200 
201       //! new write method
write(StandardOutStream & out) const202       virtual void write( StandardOutStream& out ) const { indexSet_.write( out ); }
203     };
204 
205     /////////////////////////////////////////////////////////////
206     //
207     // DofStorageInterface
208     //
209     /////////////////////////////////////////////////////////////
210     /** \brief Interface class for a dof storage object to be stored in
211         discrete functions */
212     class DofStorageInterface
213     {
214     protected:
215       //! do not allow to create explicit instances
216       DofStorageInterface() = default;
217 
218     public:
219       //! destructor
220       virtual ~DofStorageInterface() = default;
221 
222       //! enable dof compression for dof storage (default is empty)
enableDofCompression()223       virtual void enableDofCompression() { }
224 
225       //! size of space, i.e. mapper.size()
226       virtual int size () const = 0;
227     };
228 
229 
230     /** \brief Interface class for a dof storage object that can be managed
231         (resized and compressed) by the DofManager
232     */
233     class ManagedDofStorageInterface : public DofStorageInterface
234     {
235     protected:
236       //! do not allow to create explicit instances
237       ManagedDofStorageInterface() = default;
238 
239     public:
240       //! destructor
241       virtual ~ManagedDofStorageInterface() = default;
242 
243       //! resize memory
244       virtual void resize ( const bool enlargeOnly ) = 0;
245       //! resize memory
246       virtual void reserve (int newSize) = 0;
247       //! compressed the underlying dof vector and clear the array if it's
248       //! temporary and clearresizedarrays is enabled (default)
249       virtual void dofCompress ( const bool clearResizedArrays ) = 0;
250       //! return size of mem used by MemObject
251       virtual size_t usedMemorySize() const = 0;
252     };
253 
254 
255     template <class MemObjectType> class ResizeMemoryObjects;
256     template <class MemObjectType> class ReserveMemoryObjects;
257 
258     /*!
259       A ManagedDofStorage holds the memory for one DiscreteFunction and the
260       corresponding DofArrayMemory. ManagedDofStorageImplementation implements the
261       basic features such as resize and dof compression. If a DiscreteFunction is signed in by a
262       function space, then such a MemObject is created by the DofManager.
263       The MemObject also knows the DofMapper from the function space which the
264       discrete function belongs to. Here we dont know the exact type of the dof
265       mapper therefore the methods newSize and calcInsertPoints of the mappers
266       have to be virtual. This isnt a problem because this methods should only
267       be called during memory reorganizing which is only once per timestep.
268     */
269     template <class GridImp, class MapperType , class DofArrayType>
270     class ManagedDofStorageImplementation : public ManagedDofStorageInterface
271     {
272       // interface for MemObject lists
273       typedef LocalInterface< int > MemObjectCheckType;
274     protected:
275       // type of this class
276       typedef ManagedDofStorageImplementation <GridImp, MapperType , DofArrayType> ThisType;
277 
278       typedef DofManager<GridImp> DofManagerType;
279 
280       // reference to dof manager
281       DofManagerType &dm_;
282 
283       // the dof set stores number of dofs on entity for each codim
284       MapperType &mapper_;
285 
286       // Array which the dofs are stored in
287       DofArrayType& array_;
288 
289       typedef ResizeMemoryObjects < ThisType > ResizeMemoryObjectType;
290       typedef ReserveMemoryObjects  < ThisType > ReserveMemoryObjectType;
291       ResizeMemoryObjectType  resizeMemObj_;
292       ReserveMemoryObjectType reserveMemObj_;
293 
294       // true if data need to be compressed
295       bool dataCompressionEnabled_;
296 
297     public:
298       ManagedDofStorageImplementation(const ManagedDofStorageImplementation& ) = delete;
299 
300     protected:
301       //! Constructor of ManagedDofStorageImplementation, only to call from derived classes
ManagedDofStorageImplementation(const GridImp & grid,const MapperType & mapper,DofArrayType & array)302       ManagedDofStorageImplementation ( const GridImp& grid,
303                                         const MapperType& mapper,
304                                         DofArrayType& array )
305         : dm_( DofManagerType :: instance( grid ) ),
306           mapper_ ( const_cast<MapperType& >(mapper)),
307           array_( array ),
308           resizeMemObj_(*this),
309           reserveMemObj_(*this),
310           dataCompressionEnabled_(false)
311       {
312         // add to dof manager
313         dm_.addDofStorage( *this );
314 
315         // set memory over estimate factor, only for DofArray
316         array_.setMemoryFactor( dm_.memoryFactor() );
317       }
318 
319       //! \brief destructor deleting MemObject from resize and reserve List
~ManagedDofStorageImplementation()320       ~ManagedDofStorageImplementation()
321       {
322         // remove from dof manager
323         dm_.removeDofStorage( *this );
324       }
325 
326     public:
327       //! return object that calls resize of this memory object
resizeMemoryObject()328       ResizeMemoryObjectType& resizeMemoryObject() { return resizeMemObj_; }
329 
330       //! return object that calls reserve of this memory object
reserveMemoryObject()331       ReserveMemoryObjectType& reserveMemoryObject() { return reserveMemObj_; }
332 
333       //! return size of underlying array
size() const334       int size () const { return array_.size(); }
335 
336       //! resize the memory with the new size
resize(const bool enlargeOnly)337       void resize ( const bool enlargeOnly )
338       {
339         resize( std::integral_constant< bool, Capabilities::isAdaptiveDofMapper< MapperType >::v >(), enlargeOnly );
340       }
341 
342       //! reserve memory for what is comming
reserve(const int needed)343       inline void reserve ( const int needed )
344       {
345         // if index set is compressible, then add requested size
346         if( mapper().consecutive() )
347         {
348           const int nSize = size() + (needed * mapper().maxNumDofs());
349           array_.reserve( nSize );
350         }
351         else
352         {
353           // if compress is not needed just resize with given size
354           // therefore use newSize to enleage array
355           assert( ! mapper().consecutive() );
356           // resize array
357           resize ( false );
358         }
359       }
360 
361       //! copy the dof from the rear section of the vector to the holes
dofCompress(const bool clearResizedArrays)362       void dofCompress ( const bool clearResizedArrays )
363       {
364         // get current size
365         const int nSize = mapper().size();
366 
367         // if data is non-temporary do data compression
368         if( dataCompressionEnabled_ )
369         {
370           // get old size (which we still have in array)
371           const int oldSize = array_.size();
372 
373           // NOTE: new size can also be larger than old size
374           // e.g. during loadBalancing when ghosts where
375           // introduced before compressing the index set
376 
377           // begin with block zero since closing of holes
378           // has to be done anyway if the mapper is consecutive
379           const int numBlocks = mapper().numBlocks();
380           for( int block = 0; block < numBlocks; ++block )
381           {
382             // move memory
383             moveToFront( oldSize, block );
384 
385             // only close holes for consecutive mappers
386             if( mapper().consecutive () )
387             {
388               // run over all holes and copy array vules to new place
389               const int holes = mapper().numberOfHoles( block );
390               for( int i = 0; i < holes; ++i )
391               {
392                 const int oldIndex = mapper().oldIndex( i, block );
393                 const int newIndex = mapper().newIndex( i, block );
394 
395                 assert( newIndex < nSize );
396                 // implements array_[ newIndex ] = array_[ oldIndex ] ;
397                 array_.copyContent( newIndex, oldIndex );
398               }
399             }
400           }
401         }
402 
403         // store new size, which should be smaller then actual size
404         array_.resize( nSize );
405 
406         if( clearResizedArrays && ! dataCompressionEnabled_ )
407         {
408           // if enabled clear temporary data to avoid occasionally NaN values
409           array_.clear();
410         }
411       }
412 
413       //! return used memory size
usedMemorySize() const414       size_t usedMemorySize() const
415       {
416         return ((size_t) sizeof(ThisType) + array_.usedMemorySize());
417       }
418 
419       //! enable dof compression for this MemObject
enableDofCompression()420       void enableDofCompression()
421       {
422         dataCompressionEnabled_ = true;
423       }
424 
425       //! return reference to array for DiscreteFunction
getArray()426       DofArrayType & getArray() { return array_; }
427 
428     protected:
mapper() const429       inline MapperType &mapper () const
430       {
431         return mapper_;
432       }
433 
434       // resize for non-adaptive mappers
resize(std::false_type,const bool enlargeOnly)435       void resize ( std::false_type, const bool enlargeOnly )
436       {
437         // note: The mapper might already have been updated, so do not use
438         //       it to obtain old array size.
439         mapper().update(); // make sure the mapper is up2date
440 
441         const int newSize = mapper().size();
442         const int oldSize = array_.size();
443 
444         if( enlargeOnly && newSize < oldSize ) return ;
445 
446         if( newSize != oldSize )
447           array_.resize( newSize );
448       }
449 
450       // resize for adaptive mappers
resize(std::true_type,const bool enlargeOnly)451       void resize ( std::true_type, const bool enlargeOnly )
452       {
453         // note: The mapper is adaptive and has been updated automatically, so
454         //       do not use it to obtain old array size.
455         const int oldSize = array_.size();
456 
457         // get current size
458         const int nSize = mapper().size();
459 
460         // if enlarge only option is given only resize
461         // if new size if larger than old size
462         if( enlargeOnly && nSize <= oldSize ) return ;
463 
464         // if nothing changed do nothing
465         if( nSize == oldSize ) return ;
466 
467         // resize memory to current value
468         array_.resize( nSize );
469 
470         // if data is only temporary data, don't adjust memory
471         if( ! dataCompressionEnabled_ || enlargeOnly ) return ;
472 
473         // now check all blocks beginning with the largest
474         const int numBlocks = mapper().numBlocks();
475 
476         // initialize upperBound
477         int upperBound = oldSize ;
478 
479         // make sure offset of block 0 is zero
480         assert( mapper().offSet( 0 ) == 0 );
481         assert( mapper().oldOffSet( 0 ) == 0 );
482 
483         // skip block 0 (since offset == 0)
484         for( int block = numBlocks-1; block >= 1; --block )
485         {
486           // get offsets
487           const int newOffSet = mapper().offSet( block );
488           const int oldOffSet = mapper().oldOffSet( block );
489 
490           // make sure new offset is larger
491           assert( newOffSet >= oldOffSet );
492 
493           // if off set is not zero
494           if( newOffSet > oldOffSet )
495           {
496             // calculate block size
497             const int blockSize = upperBound - oldOffSet;
498             // move block backward
499             array_.memMoveBackward( blockSize, oldOffSet, newOffSet );
500 
501             // update upper bound
502             upperBound = oldOffSet;
503           }
504         }
505       }
506 
507       // move array to rear insertion points
resizeAndMoveToRear()508       void resizeAndMoveToRear ()
509       {
510       }
511 
512       //! move block to front again
moveToFront(const int oldSize,const int block)513       void moveToFront ( const int oldSize, const int block )
514       {
515         // get insertion point from block
516         const int oldOffSet = mapper().oldOffSet( block );
517 
518         // get new off set
519         const int newOffSet = mapper().offSet( block );
520 
521         // here we should have at least the same offsets
522         assert( newOffSet <= oldOffSet );
523 
524         // only if block is not starting from zero
525         if( newOffSet < oldOffSet )
526         {
527           // get number of blocks
528           const int numBlocks = mapper().numBlocks();
529 
530           // for last section upperBound is size
531           const int upperBound
532             = (block == numBlocks - 1) ? oldSize : mapper().oldOffSet( block + 1 );
533           const int blockSize = upperBound - oldOffSet;
534 
535           // move block forward
536           array_.memMoveForward( blockSize, oldOffSet, newOffSet );
537         }
538       }
539     };
540 
541     /*! A ManagedDofStorage holds the memory for one DiscreteFunction. */
542     template <class GridImp, class MapperType , class DofArrayType>
543     class ManagedDofStorage : public ManagedDofStorageImplementation< GridImp, MapperType, DofArrayType >
544     {
545       typedef ManagedDofStorageImplementation< GridImp, MapperType, DofArrayType > BaseType;
546     protected:
547       DofArrayType myArray_;
548     public:
549       //! Constructor of ManagedDofStorage
ManagedDofStorage(const GridImp & grid,const MapperType & mapper)550       ManagedDofStorage( const GridImp& grid,
551                          const MapperType& mapper )
552         : BaseType( grid, mapper, myArray_ ),
553           myArray_( mapper.size() )
554       {
555       }
556     };
557 
558     //! default implementation for creating a managed dof storage
559     template< class DofStorageType, class GridType, class MapperType >
560     static inline std::pair< DofStorageInterface* , DofStorageType* >
allocateManagedDofStorage(const GridType & grid,const MapperType & mapper,const DofStorageType * =0)561       allocateManagedDofStorage( const GridType& grid,
562                                  const MapperType& mapper,
563                                  const DofStorageType * = 0 )
564     {
565       // create managed dof storage
566       typedef ManagedDofStorage< GridType, MapperType,
567                                  DofStorageType > ManagedDofStorageType;
568 
569       ManagedDofStorageType* mds = new ManagedDofStorageType( grid, mapper );
570       assert( mds );
571 
572       // return pair with dof storage pointer and array pointer
573       return std::pair< DofStorageInterface* , DofStorageType* >
574               ( mds , & mds->getArray () );
575     }
576 
577 
578 
579     ///////////////////////////////////////////////////////////////
580     //
581     //  RestrictPorlong for Index Sets
582     //
583     ///////////////////////////////////////////////////////////////
584 
585     template <class IndexSetType, class EntityType>
586     class RemoveIndicesFromSet
587     : public LocalInlinePlus < RemoveIndicesFromSet<IndexSetType,EntityType> , EntityType >
588     {
589     private:
590       // the dof set stores number of dofs on entity for each codim
591       IndexSetType & indexSet_;
592 
593     public:
594       // Constructor of MemObject, only to call from DofManager
RemoveIndicesFromSet(IndexSetType & iset)595       explicit RemoveIndicesFromSet ( IndexSetType & iset ) : indexSet_ (iset) {}
596 
597       //! apply wraps the removeEntity Method of the index set
apply(EntityType & entity)598       inline void apply ( EntityType & entity )
599       {
600         indexSet_.removeEntity( entity );
601       }
602     };
603 
604     template <class IndexSetType, class EntityType>
605     class InsertIndicesToSet
606     : public LocalInlinePlus < InsertIndicesToSet< IndexSetType, EntityType > , EntityType >
607     {
608     private:
609       // the dof set stores number of dofs on entity for each codim
610       IndexSetType & indexSet_;
611 
612     public:
613       // Constructor of MemObject, only to call from DofManager
InsertIndicesToSet(IndexSetType & iset)614       explicit InsertIndicesToSet ( IndexSetType & iset ) : indexSet_ (iset) {}
615 
616       //! apply wraps the insertEntity method of the index set
apply(EntityType & entity)617       inline void apply ( EntityType & entity )
618       {
619         indexSet_.insertEntity( entity );
620       }
621     };
622 
623     template <class MemObjectType>
624     class ResizeMemoryObjects
625     : public LocalInlinePlus < ResizeMemoryObjects < MemObjectType > , int >
626     {
627     private:
628       // the dof set stores number of dofs on entity for each codim
629       MemObjectType & memobj_;
630 
631     public:
632       // Constructor of MemObject, only to call from DofManager
ResizeMemoryObjects(MemObjectType & mo)633       ResizeMemoryObjects ( MemObjectType & mo ) : memobj_ (mo) {}
ResizeMemoryObjects(const ResizeMemoryObjects & org)634       ResizeMemoryObjects ( const ResizeMemoryObjects& org )
635         : memobj_(org.memobj_)
636       {}
637 
638       // resize mem object, parameter not needed
apply(int & enlargeOnly)639       inline void apply ( int& enlargeOnly )
640       {
641         memobj_.resize( bool(enlargeOnly) );
642       }
643     };
644 
645     // this class is the object for a single MemObject to
646     template <class MemObjectType>
647     class ReserveMemoryObjects
648     : public LocalInlinePlus < ReserveMemoryObjects < MemObjectType > , int >
649     {
650     private:
651       // the dof set stores number of dofs on entity for each codim
652       MemObjectType & memobj_;
653 
654     public:
655       // Constructor of MemObject, only to call from DofManager
ReserveMemoryObjects(MemObjectType & mo)656       ReserveMemoryObjects ( MemObjectType & mo ) : memobj_ (mo) {}
657 
658       // reserve for at least chunkSize new values
apply(int & chunkSize)659       inline void apply ( int & chunkSize )
660       {
661         memobj_.reserve( chunkSize );
662       }
663     };
664 
665 
666     // this is the dofmanagers object which is being used during restriction
667     // and prolongation process for adding and removing indices to and from
668     // index sets which belong to functions that belong to that dofmanager
669     template <class DofManagerType , class RestrictProlongIndexSetType, bool doResize >
670     class IndexSetRestrictProlong  :
671       public RestrictProlongInterface<
672               RestrictProlongTraits<
673                 IndexSetRestrictProlong<DofManagerType,RestrictProlongIndexSetType,doResize>, double > >
674     {
675       DofManagerType & dm_;
676 
677       RestrictProlongIndexSetType & insert_;
678       RestrictProlongIndexSetType & remove_;
679     public:
680 
IndexSetRestrictProlong(DofManagerType & dm,RestrictProlongIndexSetType & is,RestrictProlongIndexSetType & rm)681       IndexSetRestrictProlong ( DofManagerType & dm , RestrictProlongIndexSetType & is, RestrictProlongIndexSetType & rm )
682         : dm_(dm) , insert_( is ), remove_( rm ) {}
683 
684       //! restrict data to father and resize memory if doResize is true
685       template <class EntityType>
restrictLocal(const EntityType & father,const EntityType & son,bool initialize) const686       inline void restrictLocal ( const EntityType & father, const EntityType & son , bool initialize ) const
687       {
688         // insert index of father
689         insert_.apply( father );
690         // mark index of son for removal
691         remove_.apply( son );
692 
693         // resize memory if doResize is true
694         if ( doResize )
695         {
696           dm_.resizeMemory();
697         }
698       }
699 
700       template <class EntityType>
restrictFinalize(const EntityType & father) const701       inline void restrictFinalize( const EntityType &father ) const
702       {}
703 
704       //! prolong data to children and resize memory if doResize is true
705       template <class EntityType>
prolongLocal(const EntityType & father,const EntityType & son,bool initialize) const706       inline void prolongLocal ( const EntityType & father, const EntityType & son , bool initialize ) const
707       {
708         // mark index of father for removal
709         remove_.apply( father );
710         // insert index of son
711         insert_.apply( son );
712 
713         // resize memory if doResize is true
714         if ( doResize )
715         {
716           dm_.resizeMemory();
717         }
718       }
719     };
720 
721     // empty restrict prolong operator
722     class EmptyIndexSetRestrictProlong  :
723       public RestrictProlongInterface< RestrictProlongTraits< EmptyIndexSetRestrictProlong, double > >
724     {
725     public:
EmptyIndexSetRestrictProlong()726       EmptyIndexSetRestrictProlong() {}
727       //! restrict data to father and resize memory if doResize is true
728       template <class EntityType>
restrictLocal(EntityType & father,EntityType & son,bool initialize) const729       inline void restrictLocal ( EntityType & father, EntityType & son , bool initialize ) const {}
730       //! prolong data to children and resize memory if doResize is true
731       template <class EntityType>
prolongLocal(EntityType & father,EntityType & son,bool initialize) const732       inline void prolongLocal ( EntityType & father, EntityType & son , bool initialize ) const {}
733     };
734 
735 
736     class DofManError : public Exception {};
737 
738     /*!
739      The DofManager is responsible for managing memory allocation and freeing
740      for all discrete functions living on the grid the manager belongs to.
741      There is only one DofManager per grid.
742      Each discrete function knows its dofmanager and can sign in.
743      If the grid is adapted, then the
744      dofmanager reorganizes the memory if necessary. The DofManager holds a
745      list of MemObjects which manage the memory and the corresponding
746      mapper so they can determine the size of new memory.
747      Furthermore the DofManager holds an IndexSet which the DofMapper needs for
748      calculating the indices in the dof vector for a given entity and local dof
749      number. This IndexSet is delivered to the mapper when a function space is
750      created. The default value for the IndexSet is the DefaultIndexSet class
751      which is mostly a wrapper for the grid indices.
752     */
753     // --DofManager
754     template< class Grid >
755     class DofManager :
756 #if HAVE_DUNE_ALUGRID
757       public IsDofManager,
758       public LoadBalanceHandleWithReserveAndCompress,
759 #endif
760       // DofManager behaves like a communication data handle for load balancing
761       public CommDataHandleIF< DofManager< Grid >, char >
762     {
763       typedef DofManager< Grid > ThisType;
764 
765       friend struct DefaultSingletonFactory< const Grid*, ThisType >;
766       friend class DofManagerFactory< ThisType >;
767 
768     public:
769       //! type of Grid this DofManager belongs to
770       typedef Grid GridType;
771 
772       typedef typename GridObjectStreamTraits< GridType >::InStreamType  XtractStreamImplType;
773       typedef typename GridObjectStreamTraits< GridType >::OutStreamType InlineStreamImplType;
774     public:
775       // types of inlining and xtraction stream types
776       typedef MessageBufferIF< XtractStreamImplType > XtractStreamType;
777       typedef MessageBufferIF< InlineStreamImplType > InlineStreamType;
778 
779       // types of data collectors
780       typedef DataCollectorInterface<GridType, XtractStreamType >   DataXtractorType;
781       typedef DataCollectorInterface<GridType, InlineStreamType  >  DataInlinerType;
782 
783       typedef typename GridType :: template Codim< 0 > :: Entity  ElementType ;
784 
785     private:
786       typedef std::list< ManagedDofStorageInterface* > ListType;
787       typedef LocalInterface< int > MemObjectCheckType;
788       typedef std::list< ManagedIndexSetInterface * > IndexListType;
789 
790       // list with MemObjects, for each DiscreteFunction we have one MemObject
791       ListType memList_;
792 
793       // list of all different indexsets
794       IndexListType indexList_;
795 
796       // the dofmanager belong to one grid only
797       const GridType &grid_;
798 
799       // index set for mapping
800       mutable DataInlinerType  dataInliner_;
801       mutable DataXtractorType dataXtractor_;
802 
803       //! type of IndexSet change interfaces
804       //// use const Entities as parameters (typedef here to avoid confusion)
805       typedef const ElementType  ConstElementType;
806       typedef LocalInterface< ConstElementType > LocalIndexSetObjectsType;
807 
808       mutable LocalIndexSetObjectsType indexSets_;
809 
810       mutable LocalIndexSetObjectsType insertIndices_;
811       mutable LocalIndexSetObjectsType removeIndices_;
812 
813       // lists containing all MemObjects
814       // to have fast access during resize and reserve
815       mutable MemObjectCheckType resizeMemObjs_;
816       mutable MemObjectCheckType reserveMemObjs_;
817 
818       //! if chunk size if small then defaultChunkSize is used
819       const int defaultChunkSize_;
820 
821       //! number of sequence, incremented every resize is called
822       int sequence_;
823 
824     public:
825       typedef IndexSetRestrictProlong< ThisType, LocalIndexSetObjectsType , true >
826         NewIndexSetRestrictProlongType;
827       typedef IndexSetRestrictProlong< ThisType, LocalIndexSetObjectsType , false >
828         IndexSetRestrictProlongNoResizeType;
829 
830       // old type
831       typedef EmptyIndexSetRestrictProlong IndexSetRestrictProlongType;
832 
833       // this class needs to call resizeMemory
834       friend class IndexSetRestrictProlong< ThisType , LocalIndexSetObjectsType , true  > ;
835       friend class IndexSetRestrictProlong< ThisType , LocalIndexSetObjectsType , false > ;
836 
837     private:
838       // combine object holding all index set for restrict and prolong
839       NewIndexSetRestrictProlongType indexSetRestrictProlong_;
840       IndexSetRestrictProlongNoResizeType indexSetRestrictProlongNoResize_;
841 
842       // old type
843       IndexSetRestrictProlongType indexRPop_;
844 
845       //! memory over estimation factor for re-allocation
846       double memoryFactor_;
847 
848       //! true if temporary arrays should be reset to zero after resize
849       const bool clearResizedArrays_;
850 
851       //**********************************************************
852       //**********************************************************
853       //! Constructor
DofManager(const GridType * grid)854       inline explicit DofManager ( const GridType *grid )
855       : grid_( *grid ),
856         defaultChunkSize_( 128 ),
857         sequence_( 0 ),
858         indexSetRestrictProlong_( *this, insertIndices_ , removeIndices_ ),
859         indexSetRestrictProlongNoResize_( *this, insertIndices_ , removeIndices_ ),
860         indexRPop_(),
861         memoryFactor_( Parameter :: getValidValue( "fem.dofmanager.memoryfactor",  double( 1.1 ),
862             [] ( double value ) { return value >= 1.0; } ) ),
863         clearResizedArrays_( Parameter :: getValue("fem.dofmanager.clearresizedarrays", bool( true ) ) )
864       {
865         // only print memory factor if it deviates from the default value
866         if( std::abs( memoryFactor_ - 1.1 ) > 1e-12 )
867           if( Parameter::verbose() && (grid_.comm().rank() == 0) )
868             std::cout << "Created DofManager with memory factor " << memoryFactor_ << "." << std::endl;
869       }
870 
871       //! Desctructor, removes all MemObjects and IndexSetObjects
872       ~DofManager ();
873 
874     public:
875       DofManager( const ThisType& ) = delete;
876 
877       //! return factor to over estimate new memory allocation
memoryFactor() const878       double memoryFactor() const { return memoryFactor_; }
879 
880       /** \brief add index set to dof manager's list of index sets
881        *
882        *  During adaptation, all index sets known to the dof manager are notified
883        *  of the changes.
884        *
885        *  To register an index set with the dof manager, it has to satisfy the
886        *  following interface:
887        *  \code
888        *  void insertEntity ( const Element & );
889        *  void removeEntity ( const Element & );
890        *  void resize();
891        *  bool compress();
892        *  void write( OutStreamInterface<Traits>& );
893        *  void read( InStreamInterface<Traits>& )
894        *  \endcode
895        *
896        *  \param[in]  iset  index set to add to list
897        */
898       template <class IndexSetType>
899       inline void addIndexSet (const IndexSetType &iset );
900 
901       /** \brief removed index set from dof manager's list of index sets
902        *
903        *  During adaptation, all index sets known to the dof manager are notified
904        *  of the changes.
905        *
906        *  \param[in]  iset  index set to add to list
907        */
908       template <class IndexSetType>
909       inline void removeIndexSet (const IndexSetType &iset );
910 
911       /** \brief add a managed dof storage to the dof manager.
912           \param dofStorage  dof storage to add which must fulfill the
913                  ManagedDofStorageInterface
914       */
915       template <class ManagedDofStorageImp>
916       void addDofStorage(ManagedDofStorageImp& dofStorage);
917 
918       /** \brief remove a managed dof storage from the dof manager.
919           \param dofStorage  dof storage to remove which must fulfill the
920                  ManagedDofStorageInterface
921       */
922       template <class ManagedDofStorageImp>
923       void removeDofStorage(ManagedDofStorageImp& dofStorage);
924 
925       //! returns the index set restriction and prolongation operator
indexSetRestrictProlong()926       NewIndexSetRestrictProlongType & indexSetRestrictProlong ()
927       {
928         // hier muss statt dessen ein Combiniertes Object erzeugt werden.
929         // dafuer sollte bei einhaengen der IndexSets ein Methoden Pointer
930         // erzeugt werden, welcher die den IndexSet mit einem anderen Object
931         // kombiniert
932         return indexSetRestrictProlong_;
933       }
934 
935       //! returns the index set restriction and prolongation operator
indexSetRestrictProlongNoResize()936       IndexSetRestrictProlongNoResizeType& indexSetRestrictProlongNoResize()
937       {
938         // return index set restrict/prolong operator that is only inserting
939         // and mark for removal indices but not doing resize
940         return indexSetRestrictProlongNoResize_;
941       }
942 
943       //! if dofmanagers list is not empty return true
hasIndexSets() const944       bool hasIndexSets() const
945       {
946         return ! insertIndices_.empty();
947       }
948 
949       /** \brief return used memory size of all MemObjects in bytes. */
usedMemorySize() const950       size_t usedMemorySize () const
951       {
952         size_t used = 0;
953         for(auto memObjectPtr : memList_)
954           used += memObjectPtr->usedMemorySize();
955         return used;
956       }
957 
958       /** \brief resize memory before data restriction
959           during grid adaptation is done.
960       */
resizeForRestrict()961       void resizeForRestrict ()
962       {
963         resizeMemory();
964       }
965 
966       /** \brief reserve memory for at least nsize elements,
967        *         dummy is needed for dune-grid ALUGrid version */
reserveMemory(int nsize,bool dummy=false)968       void reserveMemory ( int nsize, bool dummy = false )
969       {
970         int localChunkSize = std::max(nsize, defaultChunkSize_ );
971         assert( localChunkSize > 0 );
972 
973         // reserves (size + chunkSize * elementMemory), see above
974         reserveMemObjs_.apply ( localChunkSize );
975       }
976 
977       /** \brief return number of sequence, if dofmanagers memory was changed by
978           calling some method like resize, then also this number will increase
979          \note The increase of this number could be larger than 1
980       */
sequence() const981       int sequence () const { return sequence_; }
982 
983       /** \brief Resize index sets and memory due to what the mapper has as new size.
984           \note This will increase the sequence counter by 1.
985       */
resize()986       void resize()
987       {
988         for(auto indexSetPtr : indexList_)
989           indexSetPtr->resize();
990         resizeMemory();
991       }
992 
993       /** \brief Inserts entity to all index sets added to dof manager. */
insertEntity(ConstElementType & element)994       inline void insertEntity( ConstElementType & element )
995       {
996         // insert new index
997         insertIndices_.apply( element );
998 
999         // resize memory
1000         resizeMemory();
1001       }
1002 
1003       /** \brief Removes entity from all index sets added to dof manager. */
removeEntity(ConstElementType & element)1004       inline void removeEntity( ConstElementType & element )
1005       {
1006         removeIndices_.apply( element );
1007       }
1008 
1009       //! resize the MemObject if necessary
resizeMemory()1010       void resizeMemory()
1011       {
1012         int enlargeOnly = 0;
1013         // pass dummy parameter
1014         resizeMemObjs_.apply ( enlargeOnly );
1015       }
1016 
1017       //! resize the MemObject if necessary
enlargeMemory()1018       void enlargeMemory()
1019       {
1020         int enlargeOnly = 1;
1021         // pass dummy parameter
1022         resizeMemObjs_.apply ( enlargeOnly );
1023       }
1024 
1025       /** \brief increase the DofManagers internal sequence number
1026           \note  This will increase the sequence counter by 1.
1027       */
incrementSequenceNumber()1028       void incrementSequenceNumber ()
1029       {
1030         // mark next sequence
1031         ++sequence_;
1032 
1033         // check that sequence number is the same for all processes
1034         assert( sequence_ == grid_.comm().max( sequence_ ) );
1035       }
1036 
1037       //- --compress
1038       /** \brief Compress all data that is hold by this dofmanager
1039           \note  This will increase the sequence counter by 1.
1040       */
compress()1041       void compress()
1042       {
1043         // mark next sequence
1044         incrementSequenceNumber ();
1045 
1046         // compress indexsets first
1047         for(auto indexSetPtr : indexList_)
1048         {
1049           // reset compressed so the next time compress of index set is called
1050           indexSetPtr->compress();
1051         }
1052 
1053         // compress all data now
1054         for(auto memObjectPtr : memList_)
1055         {
1056           // if correponding index was not compressed yet, this is called in
1057           // the MemObject dofCompress, if index has not changes, nothing happens
1058           // if IndexSet actual needs  no compress, nothing happens to the
1059           // data either
1060           // also data is resized, which means the vector is getting shorter
1061           memObjectPtr->dofCompress ( clearResizedArrays_ );
1062         }
1063       }
1064 
1065       //! communicate new sequence number
notifyGlobalChange(const bool wasChanged) const1066       bool notifyGlobalChange( const bool wasChanged ) const
1067       {
1068         // make sure that wasChanged is the same on all cores
1069         int wasChangedCounter = int( wasChanged );
1070         return bool( grid_.comm().max( wasChangedCounter ) );
1071       }
1072 
1073       //! add data handler for data inlining to dof manager
1074       template <class DataCollType>
addDataInliner(DataCollType & d)1075       void addDataInliner ( DataCollType & d)
1076       {
1077         dataInliner_ += d;
1078       }
1079 
1080       //! clear data inliner list
clearDataInliners()1081       void clearDataInliners ()
1082       {
1083         dataInliner_.clear();
1084       }
1085 
1086       //! add data handler for data xtracting to dof manager
1087       template <class DataCollType>
addDataXtractor(DataCollType & d)1088       void addDataXtractor ( DataCollType & d)
1089       {
1090         dataXtractor_ += d;
1091       }
1092 
1093       //! clear data xtractor list
clearDataXtractors()1094       void clearDataXtractors ()
1095       {
1096         dataXtractor_.clear();
1097       }
1098 
1099       //////////////////////////////////////////////////////////
1100       //  CommDataHandleIF methods
1101       //////////////////////////////////////////////////////////
1102 
1103       //! the dof manager only transfers element data during load balancing
contains(const int dim,const int codim) const1104       bool contains( const int dim, const int codim ) const
1105       {
1106         return ( codim == 0 );
1107       }
1108 
1109       //! fixed size is false
fixedSize(const int dim,const int codim) const1110       bool fixedSize( const int dim, const int codim ) const
1111       {
1112         return false;
1113       }
1114 
1115       //! for convenience
1116       template <class Entity>
size(const Entity &) const1117       size_t size( const Entity& ) const
1118       {
1119         DUNE_THROW(NotImplemented,"DofManager::size should not be called!");
1120         return 0;
1121       }
1122 
1123       //! packs all data attached to this entity
gather(InlineStreamType & str,ConstElementType & element) const1124       void gather( InlineStreamType& str, ConstElementType& element ) const
1125       {
1126         dataInliner_.apply(str, element);
1127 
1128         // remove entity from index sets
1129         const_cast< ThisType & >( *this ).removeEntity( element );
1130       }
1131 
1132       template <class MessageBuffer, class Entity>
gather(MessageBuffer & str,const Entity & entity) const1133       void gather( MessageBuffer& str, const Entity& entity ) const
1134       {
1135         DUNE_THROW(NotImplemented,"DofManager::gather( entity ) with codim > 0 not implemented");
1136       }
1137 
1138       //! unpacks all data attached of this entity from message buffer
scatter(XtractStreamType & str,ConstElementType & element,size_t)1139       void scatter ( XtractStreamType& str, ConstElementType& element, size_t )
1140       {
1141         // insert entity into index sets
1142         insertEntity( element );
1143 
1144         // here the elements already have been created
1145         // that means we can xtract data
1146         dataXtractor_.apply(str, element);
1147       }
1148 
1149       //! unpacks all data of this entity from message buffer
1150       template <class MessageBuffer, class Entity>
scatter(MessageBuffer & str,const Entity & entity,size_t)1151       void scatter ( MessageBuffer & str, const Entity& entity, size_t )
1152       {
1153         DUNE_THROW(NotImplemented,"DofManager::scatter( entity ) with codim > 0 not implemented");
1154       }
1155 
1156       //********************************************************
1157       // Interface for PersistentObjects
1158       //********************************************************
1159 
1160       /** \copydoc Dune::PersistentObject :: backup */
backup() const1161       void backup () const
1162       {
1163         for(auto indexSetPtr : indexList_)
1164           indexSetPtr->backup();
1165       }
1166 
1167       /** \copydoc Dune::PersistentObject :: restore */
restore()1168       void restore ()
1169       {
1170         for(auto indexSetPtr : indexList_)
1171           indexSetPtr->restore();
1172 
1173         // make all index sets consistent
1174         // before any data is read this can be
1175         // assured since DofManager is an
1176         // AutoPersistentObject and thus in the
1177         // beginning of the list, fater the grid of course
1178         resize();
1179       }
1180 
1181       //********************************************************
1182       // read/write using fem streams
1183       //********************************************************
1184       /** \brief write all index sets to a given stream
1185        *
1186        *  \param[out]  out  stream to write to
1187        */
1188       template < class OutStream >
write(OutStream & out) const1189       void write( OutStream& out ) const
1190       {
1191         for(auto indexSetPtr : indexList_)
1192           indexSetPtr->write( out );
1193       }
1194 
1195       /** \brief read all index sets from a given stream
1196        *
1197        *  \param[in] in  stream to read from
1198        */
1199       template < class InStream >
read(InStream & in)1200       void read( InStream& in )
1201       {
1202         for(auto indexSetPtr : indexList_)
1203           indexSetPtr->read( in );
1204       }
1205 
1206       //********************************************************
1207       // Interface for DofManager access
1208       //********************************************************
1209 
1210       /** \brief obtain a reference to the DofManager for a given grid
1211        *
1212        *  \param[in]  grid  grid for which the DofManager is desired
1213        *
1214        *  \returns a reference to the singleton instance of the DofManager
1215        */
instance(const GridType & grid)1216       static inline ThisType& instance( const GridType& grid )
1217       {
1218         typedef DofManagerFactory< ThisType > DofManagerFactoryType;
1219         return DofManagerFactoryType :: instance( grid );
1220       }
1221     };
1222 
1223     //***************************************************************************
1224     //
1225     //  inline implemenations
1226     //
1227     //***************************************************************************
1228 
1229     template <class GridType>
~DofManager()1230     inline DofManager<GridType>::~DofManager ()
1231     {
1232       if(memList_.size() > 0)
1233       {
1234         while( memList_.rbegin() != memList_.rend())
1235         {
1236           DofStorageInterface * mobj = (* memList_.rbegin() );
1237           dverb << "Removing '" << mobj << "' from DofManager!\n";
1238           memList_.pop_back();
1239         }
1240       }
1241 
1242       if(indexList_.size() > 0)
1243       {
1244 #ifndef NDEBUG
1245         std::cerr << "ERROR: Not all index sets have been removed from DofManager yet!" << std::endl;
1246 #endif
1247         while ( indexList_.rbegin() != indexList_.rend())
1248         {
1249           ManagedIndexSetInterface* iobj = (* indexList_.rbegin() );
1250           indexList_.pop_back();
1251           if(iobj) delete iobj;
1252         }
1253       }
1254     }
1255 
1256     template <class GridType>
1257     template <class IndexSetType>
1258     inline void DofManager<GridType>::
addIndexSet(const IndexSetType & iset)1259     addIndexSet (const IndexSetType &iset )
1260     {
1261       assert( Fem :: ThreadManager:: singleThreadMode() );
1262 
1263       typedef ManagedIndexSet< IndexSetType, ConstElementType > ManagedIndexSetType;
1264       ManagedIndexSetType * indexSet = 0;
1265 
1266       // search index set list in reverse order to find latest index sets faster
1267       auto endit = indexList_.rend();
1268       for(auto it = indexList_.rbegin(); it != endit; ++it )
1269       {
1270         ManagedIndexSetInterface *set = *it;
1271         if( set->equals( iset ) )
1272         {
1273           set->addReference();
1274 
1275           indexSet = static_cast< ManagedIndexSetType * >( set );
1276           break;
1277         }
1278       }
1279 
1280       if( !indexSet )
1281       {
1282         indexSet = new ManagedIndexSetType ( iset, indexSets_ , insertIndices_ , removeIndices_  );
1283         indexList_.push_back( static_cast< ManagedIndexSetInterface * >( indexSet ) );
1284       }
1285     }
1286 
1287     template <class GridType>
1288     template <class IndexSetType>
removeIndexSet(const IndexSetType & iset)1289     inline void DofManager<GridType>::removeIndexSet ( const IndexSetType &iset )
1290     {
1291       assert( Fem :: ThreadManager:: singleThreadMode() );
1292 
1293       // search index set list in reverse order to find latest index sets faster
1294       auto endit = indexList_.rend();
1295       for( auto it = indexList_.rbegin(); it != endit; ++it )
1296       {
1297         ManagedIndexSetInterface *set = *it;
1298         if( set->equals( iset ) )
1299         {
1300           if( set->removeReference() )
1301           {
1302             // reverse iterators cannot be erased directly, so erase the base
1303             // (forward) iterator
1304             // Note: see, e.g., Stroustrup, section 16.3.2 about the decrement
1305             auto fit = it.base();
1306             indexList_.erase( --fit );
1307             // delete proxy
1308             delete set;
1309           }
1310           return;
1311         }
1312       }
1313 
1314       // we should never get here
1315       DUNE_THROW(InvalidStateException,"Could not remove index from DofManager set!");
1316     }
1317 
1318     template <class GridType>
1319     template <class ManagedDofStorageImp>
addDofStorage(ManagedDofStorageImp & dofStorage)1320     void DofManager<GridType>::addDofStorage(ManagedDofStorageImp& dofStorage)
1321     {
1322       // make sure we got an ManagedDofStorage
1323       ManagedDofStorageInterface* obj = &dofStorage;
1324 
1325       // push_front, makes search faster
1326       memList_.push_front( obj );
1327 
1328       // add the special object to the memResize list object
1329       resizeMemObjs_  += dofStorage.resizeMemoryObject();
1330 
1331       // the same for the reserve call
1332       reserveMemObjs_ += dofStorage.reserveMemoryObject();
1333     }
1334 
1335 
1336     template <class GridType>
1337     template <class ManagedDofStorageImp>
removeDofStorage(ManagedDofStorageImp & dofStorage)1338     void DofManager<GridType>::removeDofStorage(ManagedDofStorageImp& dofStorage)
1339     {
1340       // make sure we got an ManagedDofStorage
1341       auto obj = &dofStorage;
1342 
1343       // search list starting from tail
1344       auto endit = memList_.end();
1345       for( auto it = memList_.begin();it != endit ; ++it)
1346       {
1347         if(*it == obj)
1348         {
1349           // alloc new mem and copy old mem
1350           memList_.erase( it );
1351 
1352           // remove from list
1353           resizeMemObjs_.remove( dofStorage.resizeMemoryObject() );
1354           reserveMemObjs_.remove( dofStorage.reserveMemoryObject() );
1355 
1356           return ;
1357         }
1358       }
1359     }
1360 
1361     //@}
1362 
1363 
1364     /** \class DofManagerFactory
1365      *  \ingroup DofManager
1366      *  \brief Singleton provider for the DofManager
1367      *
1368      *  DofManagerFactory guarantees that at most one instance of DofManager
1369      *  is generated for each grid.
1370      */
1371     template< class DofManagerImp >
1372     class DofManagerFactory
1373     {
1374       typedef DofManagerFactory< DofManagerImp > ThisType;
1375 
1376     public:
1377       typedef DofManagerImp DofManagerType;
1378       typedef typename DofManagerType :: GridType GridType;
1379 
1380     private:
1381       typedef const GridType *KeyType;
1382 
1383       typedef SingletonList< KeyType, DofManagerType > DMProviderType;
1384 
1385       // declare friendship becase of methods instance
1386       friend class DofManager< GridType >;
1387 
1388     protected:
1389       /** \brief obtain a reference to the DofManager for a given grid
1390        *
1391        *  \param[in]  grid  grid for which the DofManager is desired
1392        *
1393        *  \returns a reference to the singleton instance of the DofManager
1394        */
instance(const GridType & grid)1395       inline static DofManagerType &instance ( const GridType &grid )
1396       {
1397         DofManagerType *dm = getDmFromList( grid );
1398         if( !dm )
1399           return DMProviderType :: getObject( &grid );
1400         return *dm;
1401       }
1402 
1403       //! writes DofManager of corresponding grid, when DofManager exists
1404       inline static bool
writeDofManagerNew(const GridType & grid,const std::string & filename,int timestep)1405       writeDofManagerNew ( const GridType &grid,
1406                            const std :: string &filename,
1407                            int timestep )
1408       {
1409         DofManagerType *dm = getDmFromList( grid );
1410         /*
1411         if( dm )
1412           return dm->writeIndexSets( filename, timestep );
1413           */
1414         return false;
1415       }
1416 
1417       //! reads DofManager of corresponding grid, when DofManager exists
1418       inline static bool
readDofManagerNew(const GridType & grid,const std::string & filename,int timestep)1419       readDofManagerNew ( const GridType &grid,
1420                           const std :: string &filename,
1421                           int timestep )
1422       {
1423         DofManagerType *dm = getDmFromList( grid );
1424         /*
1425         if( dm )
1426           return dm->readIndexSets( filename, timestep );
1427           */
1428         return false;
1429       }
1430 
1431     public:
1432       //! delete the dof manager that belong to the given grid
deleteDofManager(DofManagerType & dm)1433       inline static void deleteDofManager ( DofManagerType &dm )
1434       {
1435         DMProviderType :: removeObject( &dm );
1436       }
1437 
1438     private:
1439       // return pointer to dof manager for given grid
getDmFromList(const GridType & grid)1440       inline static DofManagerType *getDmFromList( const GridType &grid )
1441       {
1442         return (DMProviderType :: getObjFromList( &grid )).first;
1443       }
1444     };
1445 
1446   } // namespace Fem
1447 
1448 } // namespace Dune
1449 
1450 #endif // #ifndef DUNE_FEM_DOFMANAGER_HH
1451