1 #ifndef DUNE_FEM_ADAPTATIONMANAGER_HH
2 #define DUNE_FEM_ADAPTATIONMANAGER_HH
3 
4 //- system includes
5 #include <string>
6 
7 //- local includes
8 #include <dune/common/timer.hh>
9 #include <dune/fem/space/common/dofmanager.hh>
10 #include <dune/fem/operator/common/objpointer.hh>
11 
12 #include <dune/fem/misc/capabilities.hh>
13 #include <dune/fem/space/common/communicationmanager.hh>
14 #include <dune/fem/space/common/loadbalancer.hh>
15 #include <dune/fem/space/common/restrictprolonginterface.hh>
16 #include <dune/fem/storage/singletonlist.hh>
17 
18 #include <dune/fem/space/common/adaptcallbackhandle.hh>
19 #include <dune/fem/io/parameter.hh>
20 #include <dune/fem/io/file/persistencemanager.hh>
21 #include <dune/fem/misc/threads/threadmanager.hh>
22 
23 #include <dune/fem/space/common/dataprojection/dataprojection.hh>
24 
25 namespace Dune
26 {
27 
28   namespace Fem
29   {
30 
31   /** @addtogroup Adaptation Adaptation
32       Here the interfaces and algorithms for adapatation of a grid are
33       described and implemented.
34 
35       The strategy for restrict/prolong of data is chosen through the
36       parameter
37        \parametername \c fem.adaptation.method \n
38                       method used for
39                       prolongation/restriction of data during grid
40                       refinement;
41                       defaults to generic \n
42       Values are:
43        - 0 == none: no adaptation is performed
44        - 1 == generic: works on all grids
45        - 2 == callback: only AlbertaGrid and ALUGrid
46        .
47 
48       \remarks
49       The Interface of Adaptation Manager is described by the class
50       AdaptationManagerInterface.
51       @{
52    **/
53 
54   /** \brief AdaptationManagerInterface class.
55 
56    This Class is the result of a combination of different
57    AdaptationOperators. It is the same principle as with Mapping.
58   */
59   class AdaptationManagerInterface : virtual public LoadBalancerInterface
60   {
61   public:
62     //! \brief default constructor
AdaptationManagerInterface()63     AdaptationManagerInterface () : am_ (0) {}
64 
65     //! \brief destructor
~AdaptationManagerInterface()66     virtual ~AdaptationManagerInterface () {}
67 
68     /** \brief on call of this method the internal adaptation operator is
69         called.
70     */
adapt()71     virtual void adapt ()
72     {
73       //std::cout << "called AdaptationManagerInterface::adapt()" << std::endl;
74       if(am_) am_->adapt();
75       else
76       {
77         std::cerr << "WARNING: AdaptationManagerInterface::adapt: no adaptation manager assigned! \n";
78       }
79     }
80 
81     /** \brief returns true if adaptation manager as adaptation method different to NONE
82        \return \b true if adaptation method is not NONE, \b false otherwise
83     */
adaptive() const84     virtual bool adaptive () const
85     {
86       return (am_) ? (am_->adaptive()) : false;
87     }
88 
89     /** \brief returns name of adaptation method
90        \return name of adaptation method
91     */
methodName() const92     virtual const char * methodName() const
93     {
94       return (am_) ? (am_->methodName()) : "unknown method";
95     }
96 
97     /** \brief Assignment operator, pointer to adaptation manager is stored
98         \return reference to this (i.e. *this)
99     */
operator =(const AdaptationManagerInterface & am)100     AdaptationManagerInterface & operator = (const AdaptationManagerInterface & am)
101     {
102         /** \todo This const-casting seems strange to me! */
103       am_ = const_cast<AdaptationManagerInterface *> (&am);
104       return (*this);
105     }
106 
107     /** @copydoc LoadBalancerInterface::loadBalance */
loadBalance()108     virtual bool loadBalance ()
109     {
110       return (am_) ? (am_->loadBalance()) : false;
111     }
112 
113     /** @copydoc LoadBalancerInterface::balanceCounter */
balanceCounter() const114     virtual int balanceCounter () const
115     {
116       return (am_) ? (am_->balanceCounter()) : 0;
117     }
118 
119     /** \brief time that last adaptation cycle took */
adaptationTime() const120     virtual double adaptationTime () const
121     {
122       return 0.0;
123     }
124 
125   private:
126     //! pointer to adaptation manager
127     AdaptationManagerInterface* am_;
128   };
129 
130   /** \brief AdaptationMethod is a simple adaptation method reader class. */
131   template <class GridType>
132   class AdaptationMethod : virtual public AdaptationManagerInterface
133   {
134   public:
135     //! type of adaptation method
136     enum AdaptationMethodType { none = 0, //!< no adaptation is performed
137                                 generic = 1, //!< a generic restriction and prolongation algorithm is used
138                                 callback = 2 //!< the callback mechanism from AlbertaGrid and ALUGrid is used
139                               };
140 
141   public:
142     /** \brief constructor of AdaptationMethod
143        The following optional parameters are used
144           # 0 == none, 1 == generic, 2 == call back (only AlbertaGrid and ALUGrid)
145           AdaptationMethod: 1 # default value
146        \param grid Grid that adaptation method is read for
147 
148     */
AdaptationMethod(const GridType & grid,const ParameterReader & parameter=Parameter::container ())149     AdaptationMethod ( const GridType &grid, const ParameterReader &parameter = Parameter::container() )
150       : adaptationMethod_(generic)
151     {
152       const bool output = ( Parameter :: verbose() && ThreadManager::isMaster() );
153       int am = 1;
154       const std::string methodNames [] = { "none", "generic", "callback" };
155       am = parameter.getEnum("fem.adaptation.method", methodNames, am);
156       init(am,output);
157     }
158   private:
init(int am,const bool output)159     void init(int am,const bool output)
160     {
161 
162       // chose adaptation method
163       if(am == 2) adaptationMethod_ = callback;
164       else if(am == 1) adaptationMethod_ = generic;
165       else adaptationMethod_ = none;
166 
167       // for structred grid adaptation is disabled
168       if( ! Capabilities::isLocallyAdaptive<GridType>::v )
169       {
170         adaptationMethod_ = none;
171         if( output )
172         {
173           std::cerr << "WARNING: AdaptationMethod: adaptation disabled for structured grid! \n";
174         }
175       }
176 
177       if( output )
178       {
179         std::cout << "Created AdaptationMethod: adaptation method = " << methodName() << std::endl;
180       }
181     }
182   public:
183     //! virtual destructor
~AdaptationMethod()184     virtual ~AdaptationMethod () {}
185 
186     /** \copydoc Dune::Fem::AdaptationManagerInterface::methodName */
methodName() const187     virtual const char * methodName() const
188     {
189       switch (adaptationMethod_) {
190         case generic: return "generic";
191         case callback: return "callback";
192         case none: return "no adaptation";
193         default:  return "unknown method";
194       }
195     }
196 
197     /** \copydoc Dune::Fem::AdaptationManagerInterface::adaptive */
adaptive() const198     virtual bool adaptive () const { return adaptationMethod_ != none; }
199 
200   protected:
201     //! method identifier
202     AdaptationMethodType adaptationMethod_;
203   };
204 
205   /*! \brief This class manages the adaptation process.
206    If the method adapt is called, then the grid is adapted and also
207    all the data belonging to the given dof manager will be rearranged
208    for data set where it is necessary to keep the data.
209    */
210   template <class GridType, class RestProlOperatorImp >
211   class AdaptationManagerBase
212   : public AdaptationMethod< GridType >,
213     public ObjPointerStorage
214   {
215     typedef AdaptationMethod< GridType > BaseType;
216     typedef typename BaseType :: AdaptationMethodType AdaptationMethodType;
217 
218     template <class AdaptManager, class GridImp, bool isGoodGrid>
219     struct CallAdaptationMethod
220     {
221       template <class DofManagerImp, class RPOpImp>
adaptDune::Fem::AdaptationManagerBase::CallAdaptationMethod222       static void adapt(const AdaptManager& am, GridImp & grid,
223                         DofManagerImp& dm , RPOpImp& rpop,
224                         AdaptationMethodType adaptMethod)
225       {
226         // use generic adapt method
227         if( adaptMethod == BaseType :: generic )
228         {
229           am.template genericAdapt<All_Partition> ();
230           return ;
231         }
232 
233         // use grid call back adapt method
234         if( adaptMethod == BaseType :: callback )
235         {
236           // combine dof manager and restrict prolong operator
237           typedef RestrictProlongWrapper< GridImp, DofManagerType, RPOpImp > RPType;
238 
239           // create new handle
240           RPType restrictProlongHandle ( dm , rpop );
241 
242           // reserve memory
243           restrictProlongHandle.initialize();
244 
245           // call grid adaptation
246           grid.adapt( restrictProlongHandle );
247 
248           // do compress (if not already called)
249           restrictProlongHandle.finalize();
250           return ;
251         }
252       }
253     };
254 
255     template <class AdaptManager, class GridImp>
256     struct CallAdaptationMethod<AdaptManager,GridImp,false>
257     {
258       template <class DofManagerImp, class RPOpImp>
adaptDune::Fem::AdaptationManagerBase::CallAdaptationMethod259       static void adapt(const AdaptManager& am, GridImp & grid,
260                         DofManagerImp& dm , RPOpImp& rpop,
261                         AdaptationMethodType adaptMethod)
262       {
263         // use generic adapt method
264         if(adaptMethod != BaseType :: none )
265         {
266           // use partition type All_Partition,
267           // since we also need to iterate on ghosts
268           // for wasChanged information gathering
269           am.template genericAdapt<All_Partition> ();
270           return ;
271         }
272       }
273     };
274 
275     //! type of this class
276     typedef AdaptationManagerBase<GridType,RestProlOperatorImp> ThisType;
277 
278     //! type of dof manager
279     typedef DofManager< GridType > DofManagerType;
280 
281   public:
282     typedef typename GridType :: Traits :: LocalIdSet LocalIdSet;
283 
284     /** \brief constructor of AdaptationManagerBase
285        The following optional parameter can be used
286           # 0 == none, 1 == generic, 2 == call back (only AlbertaGrid and ALUGrid)
287           AdaptationMethod: 1 # default value
288        \param grid Grid that adaptation is done for
289        \param rpOp restriction and prlongation operator that describes how the
290         user data is projected to other grid levels
291           the following two lines:
292     */
AdaptationManagerBase(GridType & grid,RestProlOperatorImp & rpOp,const ParameterReader & parameter=Parameter::container ())293     AdaptationManagerBase ( GridType &grid, RestProlOperatorImp &rpOp, const ParameterReader &parameter = Parameter::container() )
294     : BaseType( grid, parameter ),
295       grid_( grid ),
296       dm_( DofManagerType::instance( grid_ ) ),
297       rpOp_( rpOp ),
298       adaptTime_( 0.0 ),
299       wasChanged_( false )
300     {}
301 
302     //! destructor
~AdaptationManagerBase()303     virtual ~AdaptationManagerBase () {}
304 
305     //! no public method, but has to be public, because all AdaptationManagers
306     //! must be able to call this method and the template parameters are
307     //! allways different
getRestProlOp()308     RestProlOperatorImp & getRestProlOp ()
309     {
310       return rpOp_;
311     }
312 
313     /** \brief
314        according to adaption method parameter
315        the adaption procedure is done,
316        0 == no adaptation
317        1 == generic adaption
318        2 == grid call back adaptation (only in AlbertaGrid and ALUGrid)
319     */
adapt()320     virtual void adapt ()
321     {
322       // make sure this is only called in single thread mode
323       assert( Fem :: ThreadManager :: singleThreadMode() );
324 
325       // get stopwatch
326       Dune::Timer timer;
327 
328       const bool supportsCallback = Capabilities :: supportsCallbackAdaptation< GridType > :: v;
329       CallAdaptationMethod< ThisType, GridType, supportsCallback >
330         :: adapt(*this,grid_,dm_,rpOp_,this->adaptationMethod_);
331 
332       // take time
333       adaptTime_ = timer.elapsed();
334     }
335 
336     //! \brief default load balancing method which does nothing
loadBalance()337     virtual bool loadBalance ()
338     {
339       return false;
340     }
341 
342     //! default load balancing counter is zero
balanceCounter() const343     virtual int balanceCounter () const
344     {
345       return 0;
346     }
347 
348     /** \copydoc Dune::Fem::AdaptationManagerInterface::adaptationTime */
adaptationTime() const349     virtual double adaptationTime() const
350     {
351       return adaptTime_;
352     }
353 
354   protected:
getDofManager(const GridType & grid)355     static DofManagerType& getDofManager(const GridType& grid)
356     {
357       return DofManagerType :: instance( grid );
358     }
359 
360   private:
361     /** \brief generic adaptation procedure
362        adapt defines the grid walkthrough before and after grid adaptation.
363        Note that the LocalOperator can be an combined Operator
364        Domain and Range are defined through class Operator
365     */
366     template <PartitionIteratorType pitype>
genericAdapt() const367     void genericAdapt () const
368     {
369       // initialize restrict prolong operator (e.g. PetscRestrictProlong... )
370       rpOp_.initialize();
371 
372       // call pre-adapt, returns true if at least
373       // one element is marked for coarsening
374       bool restr = grid_.preAdapt();
375 
376       // get macro grid view
377       typedef typename GridType::LevelGridView MacroGridView;
378       typedef typename MacroGridView :: template Codim<0>::
379               template Partition<pitype> :: Iterator MacroIterator;
380 
381       // reset flag
382       wasChanged_ = false ;
383 
384       if(restr)
385       {
386 
387         // get macro grid view
388         MacroGridView macroView = grid_.levelGridView( 0 );
389 
390         // make a hierarchical to insert all elements
391         // that are father of elements that might be coarsened
392 
393         {
394           // get macro iterator
395           MacroIterator endit  = macroView.template end<0,pitype>  ();
396           for(MacroIterator it = macroView.template begin<0,pitype>();
397               it != endit; ++it )
398           {
399             hierarchicRestrict( *it , dm_.indexSetRestrictProlongNoResize() );
400           }
401         }
402 
403         // if at least one element was found for restriction
404         if( wasChanged_ )
405         {
406           // now resize memory
407           dm_.resizeForRestrict();
408 
409           // now project all data to fathers
410           {
411             // get macro iterator
412             MacroIterator endit  = macroView.template end<0,pitype>  ();
413             for(MacroIterator it = macroView.template begin<0,pitype>();
414                 it != endit; ++it )
415             {
416               hierarchicRestrict( *it , rpOp_ );
417             }
418           }
419         }
420       }
421 
422       // adapt grid due to preset markers
423       // returns true if at least one element was refined
424       const bool refined = grid_.adapt();
425 
426       // if coarsening or refinement was done
427       // adjust sizes
428       if( refined || restr )
429       {
430         // resizes the index sets (insert all new indices)
431         // and resizes the memory
432         dm_.resize();
433       }
434 
435       // in case elements were created do prolongation
436       if( refined )
437       {
438         // get macro grid view
439         MacroGridView macroView = grid_.levelGridView( 0 );
440 
441         // make run through grid to project data
442         MacroIterator endit  = macroView.template end<0,pitype>  ();
443         for(MacroIterator it = macroView.template begin<0,pitype>();
444             it != endit; ++it )
445         {
446           hierarchicProlong( *it , rpOp_ );
447         }
448       }
449 
450       // notifyGlobalChange make wasChanged equal on all cores
451       if( dm_.notifyGlobalChange( wasChanged_ ) )
452       {
453         // compress index sets and data
454         // this will increase the sequence counter
455         dm_.compress();
456       }
457 
458       // do cleanup
459       grid_.postAdapt();
460 
461       // finalize restrict prolong operator (e.g. PetscRestrictProlong... )
462       rpOp_.finalize();
463     }
464 
465   private:
466     //! make hierarchic walk trough for restriction
467     template <class EntityType, class RestrictOperatorType  >
hierarchicRestrict(const EntityType & entity,RestrictOperatorType & restop) const468     bool hierarchicRestrict ( const EntityType& entity, RestrictOperatorType & restop ) const
469     {
470       if( ! entity.isLeaf() )
471       {
472         // true means we are going to restrict data
473         bool doRestrict = true;
474 
475         // check partition type
476         const bool isGhost = entity.partitionType() == GhostEntity ;
477 
478         // if the children have children then we have to go deeper
479         const int childLevel = entity.level() + 1;
480         typedef typename EntityType::HierarchicIterator HierarchicIterator;
481 
482         // check all children first
483         {
484           const HierarchicIterator endit = entity.hend( childLevel );
485           for(HierarchicIterator it = entity.hbegin( childLevel ); it != endit; ++it)
486           {
487             doRestrict &= hierarchicRestrict( *it , restop );
488           }
489         }
490 
491         // if doRestrict is still true, restrict data
492         if(doRestrict)
493         {
494           // we did at least one restriction
495           wasChanged_ = true;
496 
497           // do not restrict the solution on ghosts, this will
498           // fail, but we still need the wasChanged info, so simply
499           // calling hierarchicRestrict on interior won't work either
500           if( ! isGhost )
501           {
502             // true for first child, otherwise false
503             bool initialize = true;
504             const HierarchicIterator endit = entity.hend( childLevel );
505             for(HierarchicIterator it = entity.hbegin( childLevel ); it != endit; ++it)
506             {
507               // restrict solution
508               restop.restrictLocal( entity, *it , initialize);
509               // reset initialize flag
510               initialize = false;
511             }
512             restop.restrictFinalize(entity);
513           }
514         }
515       }
516 
517       // if all children return mightBeCoarsened,
518       // then doRestrict on father remains true
519       return entity.mightVanish();
520     }
521 
522     template <class EntityType, class ProlongOperatorType >
hierarchicProlong(const EntityType & entity,ProlongOperatorType & prolop) const523     void hierarchicProlong ( const EntityType &entity, ProlongOperatorType & prolop ) const
524     {
525       typedef typename EntityType::HierarchicIterator HierarchicIterator;
526 
527       // NOTE: initialize not working here
528       // because we call hierarchically
529 
530       // first call on this element
531       bool initialize = true;
532 
533       // check partition type
534       const bool isGhost = entity.partitionType() == GhostEntity ;
535 
536       const int maxLevel = grid_.maxLevel();
537       const HierarchicIterator endit = entity.hend( maxLevel );
538       for( HierarchicIterator it = entity.hbegin( maxLevel ); it != endit; ++it )
539       {
540         // should only get here on non-leaf entities
541         assert( !entity.isLeaf() );
542 
543         const EntityType & son = *it;
544         if( son.isNew() )
545         {
546           // the grid was obviously changed if we get here
547           wasChanged_ = true ;
548 
549           // do not prolong the solution on ghosts, this will
550           // fail, but we still need the wasChanged info, so simply
551           // calling hierarchicRestrict on interior won't work either
552           if( ! isGhost )
553           {
554             EntityType vati = son.father();
555             prolop.prolongLocal( vati , son , initialize );
556             initialize = false;
557           }
558         }
559       }
560     }
561 
562   protected:
563     //! corresponding grid
564     GridType &grid_;
565 
566     //! DofManager corresponding to grid
567     DofManagerType &dm_;
568 
569     //! Restriction and Prolongation Operator
570     RestProlOperatorImp &rpOp_;
571 
572     //! time that adaptation took
573     double adaptTime_;
574 
575     //! flag for restriction
576     mutable bool wasChanged_;
577   };
578 
579   //! factory class to create adaptation manager reference counter
580   template <class KeyType, class ObjectType>
581   struct AdaptationManagerReferenceFactory
582   {
createObjectDune::Fem::AdaptationManagerReferenceFactory583     static ObjectType* createObject(const KeyType& key)
584     {
585       return new ObjectType(0);
586     }
deleteObjectDune::Fem::AdaptationManagerReferenceFactory587     static void deleteObject(ObjectType* obj)
588     {
589       delete obj;
590     }
591   };
592 
593   /*! \brief This class manages the adaptation process including a load
594     balancing after the adaptation step. This class is created by the
595     AdaptationManager for each grid instance. See AdaptationManager for
596     details.
597   */
598   template <class GridType, class RestProlOperatorImp>
599   class AdaptationManager :
600     public AdaptationManagerBase<GridType,RestProlOperatorImp> ,
601     public LoadBalancer<GridType>,
602     public AutoPersistentObject
603   {
604     // type of key
605     typedef const GridType* KeyType;
606     // object type
607     typedef size_t ObjectType;
608     // type of factory
609     typedef AdaptationManagerReferenceFactory<KeyType, ObjectType>  FactoryType;
610 
611     // type of singleton list
612     typedef SingletonList< KeyType, ObjectType, FactoryType > ProviderType;
613 
614     typedef AdaptationManagerBase<GridType,RestProlOperatorImp> BaseType;
615     typedef LoadBalancer<GridType> Base2Type;
616 
617     using BaseType :: rpOp_;
618 
619     // reference counter to ensure only one instance per grid exists
620     ObjectType& referenceCounter_;
621 
622     // do not copy
623     AdaptationManager(const AdaptationManager&);
624 
625   public:
626     /**
627        \brief constructor of AdaptationManager
628 
629        The following optional parameters are used:
630        \code
631          # 0 == none, 1 == generic, 2 == call back (only AlbertaGrid and ALUGrid)
632          fem.adaptation.method: 1 # default value
633 
634          # balance every x-th call to adapt, 0 means no balancing
635          fem.loadbalancing.step: 1 # default value
636        \endcode
637 
638        \param grid Grid that adaptation is done for
639        \param rpOp restriction and prlongation operator that describes how the
640         user data is projected to other grid levels
641        \param balanceCounter start counter for balance cycle (default = 0)
642        \param parameter  Parameter class holding parameters
643     **/
AdaptationManager(GridType & grid,RestProlOperatorImp & rpOp,int balanceCounter,const ParameterReader & parameter=Parameter::container ())644     AdaptationManager ( GridType &grid, RestProlOperatorImp &rpOp, int balanceCounter, const ParameterReader &parameter = Parameter::container() )
645       : BaseType(grid,rpOp, parameter)
646       , Base2Type( grid, rpOp )
647       , referenceCounter_( ProviderType :: getObject( &grid ) )
648       , balanceStep_( parameter.getValue< int >( "fem.loadbalancing.step", 1 ) )
649       , balanceCounter_( balanceCounter )
650     {
651       if( ++referenceCounter_ > 1 )
652         DUNE_THROW(InvalidStateException,"Only one instance of AdaptationManager allowed per grid instance");
653       if( Parameter::verbose() )
654         std::cout << "Created LoadBalancer: balanceStep = " << balanceStep_ << std::endl;
655     }
656 
657     /**
658        \brief constructor of AdaptationManager
659 
660        The following optional parameters are used:
661        \code
662          # 0 == none, 1 == generic, 2 == call back (only AlbertaGrid and ALUGrid)
663          fem.adaptation.method: 1 # default value
664 
665          # balance every x-th call to adapt, 0 means no balancing
666          fem.loadbalancing.step: 1 # default value
667        \endcode
668 
669        \param grid Grid that adaptation is done for
670        \param rpOp restriction and prlongation operator that describes how the
671                    user data is projected to other grid levels
672        \param parameter  Parameter class holding parameters
673     **/
AdaptationManager(GridType & grid,RestProlOperatorImp & rpOp,const ParameterReader & parameter=Parameter::container ())674     AdaptationManager ( GridType &grid, RestProlOperatorImp &rpOp, const ParameterReader &parameter = Parameter::container() )
675       : AdaptationManager( grid, rpOp, 0, parameter )
676     {
677     }
678 
679     //! destructor decreasing reference counter
~AdaptationManager()680     ~AdaptationManager()
681     {
682       -- referenceCounter_;
683       ProviderType :: removeObject( referenceCounter_ );
684     }
685 
686     /** @copydoc LoadBalancerInterface::loadBalance */
loadBalance()687     virtual bool loadBalance ()
688     {
689       // same as for the adapt method
690       rpOp_.initialize () ;
691 
692       // call load balance
693       const bool result = Base2Type :: loadBalance( );
694 
695       // finalize rp object (mostly RestrictProlongDefault for PetscDF)
696       rpOp_.finalize () ;
697       return result ;
698     }
699 
700     /** @copydoc LoadBalancerInterface::loadBalanceTime */
loadBalanceTime() const701     virtual double loadBalanceTime() const
702     {
703       return Base2Type::loadBalanceTime();
704     }
705 
706     /** @copydoc AdaptationManagerInterface::adapt */
adapt()707     virtual void adapt ()
708     {
709       // adapt grid
710       BaseType :: adapt ();
711 
712       // if adaptation is enabled
713       if( this->adaptive() && (balanceStep_ > 0) )
714       {
715         // if balance counter has readed balanceStep do load balance
716         const bool callBalance = (++balanceCounter_ >= balanceStep_);
717 
718 #ifndef NDEBUG
719         // make sure load balance is called on every process
720         int willCall = (callBalance) ? 1 : 0;
721         const int iCall = willCall;
722 
723         // send info from rank 0 to all other
724         Base2Type::grid_.comm().broadcast(&willCall, 1 , 0);
725 
726         assert( willCall == iCall );
727 #endif
728 
729         if( callBalance )
730         {
731           // balance work load and restore consistency in the data
732           loadBalance();
733           balanceCounter_ = 0;
734         }
735         else
736         {
737           // only restore consistency in the data
738           Base2Type::communicate();
739         }
740       }
741     }
742 
743     //! returns actual balanceCounter for checkpointing
balanceCounter() const744     int balanceCounter () const { return balanceCounter_; }
745 
746     //! backup internal data
backup() const747     void backup() const
748     {
749       std::tuple<const int& > value( balanceCounter_ );
750       PersistenceManager::backupValue("loadbalancer",value);
751     }
752 
753     //! retore internal data
restore()754     void restore()
755     {
756       std::tuple< int& > value( balanceCounter_ );
757       PersistenceManager::restoreValue("loadbalancer",value);
758     }
759 
760   private:
761     // call loadBalance ervery balanceStep_ step
762     const int balanceStep_ ;
763     // count actual balance call
764     int balanceCounter_;
765   };
766 
767   namespace hpDG
768   {
769 
770     // AdaptationManager
771     // -----------------
772 
773     /** \brief Manages the testriction and prolongation of discrete functions in \f$(h)p\f$-adaptive computations
774      *
775      *  \tparam  DiscreteFunctionSpace  an adaptive discrete function space
776      *  \tparam  DataProjection  a DataProjection type
777      *
778      *  \ingroup DiscreteFunctionSpace_RestrictProlong
779      */
780     template< class DiscreteFunctionSpace, class DataProjection >
781     class AdaptationManager
782     : public Dune::Fem::AdaptationManagerInterface
783     {
784       using ThisType = AdaptationManager< DiscreteFunctionSpace, DataProjection >;
785 
786     public:
787       /** \brief discrete function space type */
788       using DiscreteFunctionSpaceType = DiscreteFunctionSpace;
789       /** \brief data projection type */
790       using DataProjectionType = DataProjection;
791 
792     private:
793       using GridType = typename DiscreteFunctionSpaceType::GridType;
794       using DofManagerType = DofManager< GridType >;
795 
796       class DataProjectionWrapper;
797 
798     public:
799       /** \name Construction
800        *  \{
801        */
802 
AdaptationManager(DiscreteFunctionSpaceType & space,DataProjectionType && dataProjection)803       explicit AdaptationManager ( DiscreteFunctionSpaceType &space, DataProjectionType &&dataProjection )
804         : space_( space ),
805           dataProjection_( std::forward< DataProjectionType >( dataProjection ) ),
806           dofManager_( DofManagerType::instance( space.gridPart().grid() ) ),
807           commList_( dataProjection_ ),
808           time_( 0. )
809       {}
810 
811       /** \} */
812 
813       /** \brief Deleted methods
814        *  \{
815        */
816 
817       /** \brief copy constructor */
818       AdaptationManager ( const ThisType & ) = delete;
819 
820       /** \brief assignment operator */
821       ThisType &operator= ( const ThisType & ) = delete;
822 
823       /** \} */
824 
825       /** \name Adaptation
826        *  \{
827        */
828 
829       /** \brief returns \b true */
adaptive() const830       bool adaptive () const { return true; }
831 
832       /** \brief perform adaptation */
adapt()833       void adapt ()
834       {
835         assert( Dune::Fem::ThreadManager::singleThreadMode() );
836 
837         Dune::Timer timer;
838 
839         DataProjectionWrapper wrapper( dataProjection_, dofManager() );
840         space().adapt( wrapper );
841 
842         if( dofManager().notifyGlobalChange( static_cast< bool >( wrapper ) ) )
843           dofManager().compress();
844 
845         commList_.exchange();
846 
847         time_ = timer.elapsed();
848       }
849 
850       /** \brief return name of adaptation method */
methodName() const851       const char *methodName () const { return "discrete function space adaptation"; }
852 
853       /** \brief return time spent on adaptation */
adaptationTime() const854       double adaptationTime () const { return time_; }
855 
856       /** \} */
857 
858       /** \name Load balancing
859        *  \{
860        */
861 
862       /** \brief please doc me */
loadBalance()863       bool loadBalance () { return false; }
864 
865      /** \brief please doc me */
balanceCounter() const866       int balanceCounter () const { return 0; }
867 
868       /** \brief please doc me */
loadBalanceTime() const869       double loadBalanceTime () const { return 0.; }
870 
871       /** \} */
872 
dataProjection()873       DataProjection& dataProjection() { return dataProjection_; }
874     private:
space()875       DiscreteFunctionSpaceType &space () { return space_.get(); }
876 
space() const877       const DiscreteFunctionSpaceType &space () const { return space_.get(); }
878 
dofManager()879       DofManagerType &dofManager () { return dofManager_.get(); }
880 
dofManager() const881       const DofManagerType &dofManager () const { return dofManager_.get(); }
882 
883       std::reference_wrapper< DiscreteFunctionSpaceType > space_;
884       DataProjectionType dataProjection_;
885       std::reference_wrapper< DofManagerType > dofManager_;
886       mutable CommunicationManagerList commList_;
887       double time_;
888     };
889 
890     // AdaptationManager::DataProjectionWrapper
891     // ----------------------------------------
892 
893     template< class DiscreteFunctionSpace, class DataProjection >
894     class AdaptationManager< DiscreteFunctionSpace, DataProjection >::DataProjectionWrapper
895     : public Dune::Fem::hpDG::DataProjection< DiscreteFunctionSpace, DataProjectionWrapper >
896     {
897       using BaseType = Dune::Fem::hpDG::DataProjection< DiscreteFunctionSpace, DataProjectionWrapper >;
898 
899     public:
900       using BasisFunctionSetType = typename BaseType::BasisFunctionSetType;
901       using EntityType = typename BaseType::EntityType;
902 
DataProjectionWrapper(DataProjectionType & dataProjection,DofManagerType & dofManager)903       DataProjectionWrapper ( DataProjectionType &dataProjection, DofManagerType &dofManager )
904         : dataProjection_( dataProjection ),
905           dofManager_( dofManager ),
906           modified_( false )
907       {}
908 
operator ()(const EntityType & entity,const BasisFunctionSetType & prior,const BasisFunctionSetType & present,const std::vector<std::size_t> & origin,const std::vector<std::size_t> & destination)909       void operator() ( const EntityType &entity,
910                         const BasisFunctionSetType &prior,
911                         const BasisFunctionSetType &present,
912                         const std::vector< std::size_t > &origin,
913                         const std::vector< std::size_t > &destination )
914       {
915         dofManager_.get().resizeMemory();
916         dataProjection_.get()( entity, prior, present, origin, destination );
917         modified_ = true;
918       }
919 
920       template <class TemporaryStorage>
operator ()(TemporaryStorage & tmp)921       void operator() ( TemporaryStorage& tmp )
922       {
923         dataProjection_.get()( tmp );
924         modified_ = true;
925       }
926 
operator bool() const927       explicit operator bool () const
928       {
929         return modified_;
930       }
931 
932     private:
933       std::reference_wrapper< DataProjectionType > dataProjection_;
934       std::reference_wrapper< DofManagerType > dofManager_;
935       bool modified_;
936     };
937 
938   } // namespace hpDG
939 
940 
941 
942   /** \brief A class with one static method apply to globally refine a grid.
943       All index sets are adapted to the new grid and the
944       managed dof storage is expanded - but no prolongation or
945       restriction of data is performed.
946   */
947   struct GlobalRefine
948   {
949     /** \brief apply global refinement and also adjust index sets and
950         managed dof storage. However, user data stored before is lost.
951         \param grid Grid that is globally refined
952         \param step refinement steps that are applied
953     */
954     template <class GridType>
applyDune::Fem::GlobalRefine955     static void apply(GridType& grid, const int step)
956     {
957       typedef DofManager< GridType > DofManagerType;
958       DofManagerType& dm = DofManagerType :: instance(grid);
959       grid.globalRefine(step);
960       grid.loadBalance();
961       dm.resize();
962       dm.compress();
963     }
964   };
965   /** \brief A class with one static method apply for invoking the local
966       adaptation procedure on a given grid instance.
967       All index sets are adapted to the new grid and the
968       managed dof storage is expanded - but no prolongation or
969       restriction of data is performed.
970   */
971   struct LocalRefine
972   {
973     /** \brief apply local refinement and also adjust index sets and
974         managed dof storage. However, user data stored before is lost.
975         \param grid Grid that is globally refined
976     */
977     template <class GridType>
applyDune::Fem::LocalRefine978     static void apply(GridType& grid)
979     {
980       typedef DofManager< GridType > DofManagerType;
981       DofManagerType& dm = DofManagerType :: instance(grid);
982       grid.preAdapt();
983       grid.adapt();
984       grid.postAdapt();
985       grid.loadBalance();
986       dm.resize();
987       dm.compress();
988     }
989   };
990 
991   /** @} end documentation group */
992 
993   } // namespace Fem
994 
995 } // namespace Dune
996 
997 #endif // #ifndef DUNE_FEM_ADAPTMANAGER_HH
998