From 20dd32e1d613bba4ae07823da40d24f93857bb6f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Robert=20Kl=C3=B6fkorn?=
 <robertk@mathematik.uni-stuttgart.de>
Date: Wed, 23 Mar 2005 14:59:02 +0000
Subject: [PATCH] All files for dune interface of ALU3DGrid.

git-svn-id: https://dune.mathematik.uni-freiburg.de/svn/alugrid/trunk@150 0d966ed9-3843-0410-af09-ebfb50bd7c74
---
 src/duneinterface/gitter_dune_impl.cc     | 181 ++++++
 src/duneinterface/gitter_dune_impl.h      |  30 +
 src/duneinterface/gitter_dune_pll_impl.cc | 638 ++++++++++++++++++++++
 src/duneinterface/gitter_dune_pll_impl.h  |  80 +++
 src/duneinterface/gitter_dune_pll_mgb.cc  | 560 +++++++++++++++++++
 5 files changed, 1489 insertions(+)
 create mode 100644 src/duneinterface/gitter_dune_impl.cc
 create mode 100644 src/duneinterface/gitter_dune_impl.h
 create mode 100644 src/duneinterface/gitter_dune_pll_impl.cc
 create mode 100644 src/duneinterface/gitter_dune_pll_impl.h
 create mode 100644 src/duneinterface/gitter_dune_pll_mgb.cc

diff --git a/src/duneinterface/gitter_dune_impl.cc b/src/duneinterface/gitter_dune_impl.cc
new file mode 100644
index 000000000..d1e1a7c77
--- /dev/null
+++ b/src/duneinterface/gitter_dune_impl.cc
@@ -0,0 +1,181 @@
+// Robert Kloefkorn (c) 2004 - 2005 
+#ifndef GITTER_DUNE_IMPL_CC_INCLUDED
+#define GITTER_DUNE_IMPL_CC_INCLUDED
+
+#include "gitter_dune_impl.h"
+
+void GitterDuneBasis :: backupIndices (ostream & out)
+{
+  // backup indices 
+  bool indices = true; out.put(indices);  // indices == true
+
+  // store max indices 
+  for(int i=0; i< numOfIndexManager ; i++)
+    indexManager(i).backupIndexSet(out);
+
+  { // backup index of elements 
+    AccessIterator <helement_STI> :: Handle ew (container ()) ;
+    for (ew.first () ; ! ew.done () ; ew.next ()) ew.item ().backupIndex (out) ;
+  }
+  {
+    // backup index of vertices 
+    LeafIterator < vertex_STI > w ( *this );
+    for( w->first(); ! w->done() ; w->next () ) w->item().backupIndex(out);
+  }
+
+  return ;
+}
+
+// go down all children and check index 
+inline void GitterDuneBasis :: 
+goDownHelement( Gitter::helement_STI & el , vector<bool> & idxcheck)
+{
+  typedef Gitter :: helement_STI ElType;
+  assert( (static_cast<size_t> (el.getIndex())) < idxcheck.size() );
+  idxcheck[ el.getIndex() ] = false;
+  for( ElType * ch = el.down() ; ch ; ch = ch->next())
+    goDownHelement( *ch , idxcheck );
+
+  return ;
+}
+
+void GitterDuneBasis ::restoreIndices (istream & in) 
+{
+  bool indices = in.get();
+  if(indices)
+  {
+    for(int i=0; i< numOfIndexManager ; i++)
+      this->indexManager(i).restoreIndexSet( in );
+
+    // restore index of elements 
+    {
+      AccessIterator < helement_STI >:: Handle ew(container());
+      for ( ew.first(); !ew.done(); ew.next()) ew.item().restoreIndex (in);
+    }
+    // restore index of vertices
+    {
+      LeafIterator < vertex_STI > w ( *this );
+      for( w->first(); ! w->done() ; w->next () ) w->item().restoreIndex(in);
+    }
+
+    { // reconstruct holes 
+      {
+        enum { elements = 0 };
+        // for elements 
+        int idxsize = this->indexManager(elements).getMaxIndex();
+        vector < bool > checkidx ( idxsize );
+        for(int i=0; i<idxsize; i++) checkidx[i] = true;
+
+        AccessIterator < helement_STI >:: Handle ew(container());
+        for ( ew.first(); !ew.done(); ew.next())
+        {
+          goDownHelement( ew.item() , checkidx );
+        }
+
+        for(int i=0; i<idxsize; i++)
+        {
+          if(checkidx[i] == true)
+            this->indexManager(elements).freeIndex(i);
+        }
+      }
+      {
+        enum { vertices = 3 };
+        // for vertices 
+        LeafIterator < vertex_STI > w ( *this );
+        int idxsize = this->indexManager(vertices).getMaxIndex();
+
+        vector < bool > checkidx ( idxsize );
+        for(int i=0; i<idxsize; i++) checkidx[i] = true;
+        for( w->first(); ! w->done() ; w->next () )
+        {
+          assert( (static_cast<size_t> (w->item().getIndex())) < checkidx.size() );
+          checkidx[ w->item().getIndex() ] = false;
+        }
+
+        for(int i=0; i<idxsize; i++)
+        {
+          if(checkidx[i] == true)
+            this->indexManager(vertices).freeIndex(i);
+        }
+      }
+    }
+  }
+  else 
+  {
+    cerr<< "WARNING: indices not read! file = "<< __FILE__ << ", line = " << __LINE__ << "\n";
+  }
+    
+  return ;
+}
+
+// wird von Dune verwendet 
+void GitterDuneBasis :: duneBackup (const char * fileName)
+{
+  // diese Methode wird von der Dune Schnittstelle aufgerufen und ruft
+  // intern lediglich backup (siehe oben) und backupCMode des Makrogitters
+  // auf, allerdings wird hier der path und filename in einer variablen
+  // uebergeben 
+
+  assert (debugOption (20) ? (cout << "**INFO GitterDuneBasis :: duneBackup (const char * = \""
+                       << fileName << "\") " << endl, 1) : 1) ;
+
+  ofstream out (fileName) ;
+  if (!out) {
+    cerr << "**WARNUNG (IGNORIERT) GitterDuneBasis :: duneBackup (const char *, double) Fehler beim Anlegen von < "
+         << (fileName ? fileName : "null") << " >" << endl ;
+  }
+  else
+  {
+    FSLock lock (fileName) ;
+    Gitter :: backup (out) ;
+    GitterDuneBasis :: backupIndices (out) ;
+
+    {
+      char *fullName = new char[strlen(fileName)+20];
+      if(!fullName)
+      {
+        cerr << "**WARNUNG GitterDuneBasis :: duneBackup (, const char *, double) :";
+        cerr << "couldn't allocate fullName! " << endl;
+        abort();
+      }
+      sprintf(fullName,"%s.macro",fileName);
+      ofstream macro (fullName) ;
+
+      if(!macro)
+      {
+        cerr << "**WARNUNG (IGNORIERT) GitterDuneBasis :: duneBackup (const char *, const char *) Fehler beim Anlegen von < "
+         << (fullName ? fullName : "null") << " >" << endl ;
+      }
+      else
+      {
+        container ().backupCMode (macro) ;
+      }
+      delete [] fullName;
+    }
+  }
+  return ;
+}
+
+// wird von Dune verwendet 
+void GitterDuneBasis :: duneRestore (const char * fileName)
+{
+  // diese Methode wird von der Dune Schnittstelle aufgerufen 
+  // diese Methode ruft intern restore auf, hier wird lediglich 
+  // der path und filename in einer variablen uebergeben
+
+  assert (debugOption (20) ? (cout << "**INFO GitterDuneBasis :: duneRestore (const char * = \""
+                 << fileName << "\") " << endl, 1) : 1) ;
+
+  ifstream in (fileName) ;
+  if (!in) {
+    cerr << "**WARNUNG (IGNORIERT) GitterDuneBasis :: duneRestore (const char *, double & ) Fehler beim \"Offnen von < "
+         << (fileName ? fileName : "null") << " > " << endl ;
+  } else {
+    Gitter :: restore (in) ;
+    GitterDuneBasis :: restoreIndices (in);
+  }
+  return ;
+}
+
+
+#endif
diff --git a/src/duneinterface/gitter_dune_impl.h b/src/duneinterface/gitter_dune_impl.h
new file mode 100644
index 000000000..ef6a26ee4
--- /dev/null
+++ b/src/duneinterface/gitter_dune_impl.h
@@ -0,0 +1,30 @@
+#ifndef GITTER_DUNE_IMPL_H_INCLUDED
+#define GITTER_DUNE_IMPL_H_INCLUDED
+
+#include "gitter_impl.h"
+#include "lock.h"
+
+class GitterDuneBasis :  public virtual GitterBasis 
+{
+protected:
+  void backupIndices  (ostream & out);
+  void restoreIndices (istream & in );
+
+  inline void goDownHelement( helement_STI & el , vector<bool> & idxcheck);
+  
+public:
+  // write status of grid  
+  virtual void duneBackup  (const char*) ; 
+
+  // read status of grid 
+  virtual void duneRestore (const char*) ;
+  // Constructor getting macro file name 
+};
+
+class GitterDuneImpl : public GitterBasisImpl , public GitterDuneBasis 
+{
+public:
+  inline GitterDuneImpl (const char *filename) : GitterBasisImpl ( filename ) {}
+};
+
+#endif
diff --git a/src/duneinterface/gitter_dune_pll_impl.cc b/src/duneinterface/gitter_dune_pll_impl.cc
new file mode 100644
index 000000000..5f7682993
--- /dev/null
+++ b/src/duneinterface/gitter_dune_pll_impl.cc
@@ -0,0 +1,638 @@
+#ifndef GITTER_DUNE_PLL_IMPL_CC_INCLUDED
+#define GITTER_DUNE_PLL_IMPL_CC_INCLUDED
+
+#include "gitter_dune_pll_impl.h"
+#include "gitter_dune_pll_mgb.cc"
+
+bool GitterDunePll :: duneNotifyNewGrid ()
+{
+  assert (debugOption (20) ? (cout << "**GitterPll :: loadBalancerGridChangesNotify () " << endl, 1) : 1) ;
+  const int start = clock (), me = mpAccess ().myrank (), np = mpAccess ().psize () ;
+  LoadBalancer :: DataBase db ;
+  {
+    AccessIterator < hface_STI > :: Handle w (containerPll ()) ;
+    for (w.first () ; ! w.done () ; w.next ()) w.item ().accessPllX ().ldbUpdateGraphEdge (db) ;
+  }
+  {
+    AccessIterator < helement_STI > :: Handle w (containerPll ()) ;
+    for (w.first () ; ! w.done () ; w.next ()) w.item ().accessPllX ().ldbUpdateGraphVertex (db) ;
+  }
+  bool neu = false ;
+  {
+    // Kriterium, wann eine Lastneuverteilung vorzunehmen ist:
+    // 
+    // load  - eigene ElementLast
+    // mean  - mittlere ElementLast
+    // nload - Lastverh"altnis
+
+    double load = db.accVertexLoad () ;
+    vector < double > v (mpAccess ().gcollect (load)) ;
+    double mean = accumulate (v.begin (), v.end (), 0.0) / double (np) ;
+
+    for (vector < double > :: iterator i = v.begin () ; i != v.end () ; i ++)
+      neu |= (*i > mean ? (*i > (_ldbOver * mean) ? true : false) : (*i < (_ldbUnder * mean) ? true : false)) ;
+  }
+  return neu;
+}
+
+
+
+void GitterDunePll :: duneNotifyGridChanges ()
+{
+  Gitter :: notifyGridChanges () ;
+  duneExchangeDynamicState () ;
+  return ;
+}
+
+
+// done call notify and loadBalancer  
+bool GitterDunePll :: duneAdapt ()   
+{
+  __STATIC_myrank = mpAccess ().myrank () ;
+  __STATIC_turn ++ ;
+  assert (debugOption (20) ? (cout << "**INFO GitterDunePll :: duneAdapt ()" << endl, 1) : 1) ;
+  assert (! iterators_attached ()) ;
+  int start = clock () ;
+  bool refined = this->refine() ;
+  int lap = clock () ;
+  this->coarse ();
+  int end = clock () ;
+  if (debugOption (1))
+  {
+    float u1 = (float)(lap - start)/(float)(CLOCKS_PER_SEC) ;
+    float u2 = (float)(end - lap)/(float)(CLOCKS_PER_SEC) ;
+    float u3 = (float)(end - start)/(float)(CLOCKS_PER_SEC) ;
+    cout << "**INFO GitterDunePll :: adapt () [ref (loops)|cse|all] " << u1 << " ("
+         << _refineLoops << ") " << u2 << " " << u3 << endl ;
+  }
+  duneNotifyGridChanges () ;
+  balanceGrid_ = duneNotifyNewGrid();
+
+  return refined;
+}
+
+
+
+bool GitterDunePll :: duneLoadBalance () 
+{
+  loadBalancerGridChangesNotify () ;
+  return true;
+}
+
+bool GitterDunePll :: duneLoadBalance (GatherScatterType & gs) {
+  assert (debugOption (20) ? (cout << "**GitterDunePll :: loadBalancerGridChangesNotify () " << endl, 1) : 1) ;
+  const int start = clock (), me = mpAccess ().myrank (), np = mpAccess ().psize () ;
+  LoadBalancer :: DataBase db ;
+  {
+    AccessIterator < hface_STI > :: Handle w (containerPll ()) ;
+    for (w.first () ; ! w.done () ; w.next ()) w.item ().accessPllX ().ldbUpdateGraphEdge (db) ;
+  }
+  {
+    AccessIterator < helement_STI > :: Handle w (containerPll ()) ;
+    for (w.first () ; ! w.done () ; w.next ()) w.item ().accessPllX ().ldbUpdateGraphVertex (db) ;
+  }
+  bool neu = false ;
+  {
+  // Kriterium, wann eine Lastneuverteilung vorzunehmen ist:
+  // 
+  // load  - eigene ElementLast
+  // mean  - mittlere ElementLast
+  // nload - Lastverh"altnis
+  
+    double load = db.accVertexLoad () ;
+    vector < double > v (mpAccess ().gcollect (load)) ;
+    double mean = accumulate (v.begin (), v.end (), 0.0) / double (np) ;
+
+    for (vector < double > :: iterator i = v.begin () ; i != v.end () ; i ++)
+      neu |= (*i > mean ? (*i > (_ldbOver * mean) ? true : false) : (*i < (_ldbUnder * mean) ? true : false));
+  }
+  if (neu) 
+  {
+    if (mpAccess ().gmax (_ldbMethod)) 
+    {
+      duneRepartitionMacroGrid (db, gs) ;
+      notifyMacroGridChanges () ;
+    }
+  }
+  return true;
+}
+
+void GitterDunePll :: duneExchangeDynamicState () 
+{
+  // Die Methode wird jedesmal aufgerufen, wenn sich der dynamische
+  // Zustand des Gitters ge"andert hat: Verfeinerung und alle Situationen
+  // die einer "Anderung des statischen Zustands entsprechen. Sie wird in
+  // diesem Fall NACH dem Update des statischen Zustands aufgerufen, und
+  // kann demnach von einem korrekten statischen Zustand ausgehen. F"ur
+  // Methoden die noch h"aufigere Updates erfordern m"ussen diese in der
+  // Regel hier eingeschleift werden.
+  {
+  int mallocedsize;
+  const int nl = mpAccess ().nlinks () ;
+  const int start = clock () ;
+  try 
+  {
+    typedef Insert < AccessIteratorTT < hface_STI > :: InnerHandle,
+                TreeIterator < hface_STI, is_def_true < hface_STI > > > InnerIteratorType;
+    typedef Insert < AccessIteratorTT < hface_STI > :: OuterHandle, 
+                TreeIterator < hface_STI, is_def_true < hface_STI > > > OuterIteratorType;
+                
+    vector < ObjectStream > osv (nl) ;
+    {
+      for (int l = 0 ; l < nl ; l ++) 
+      {
+        {
+          AccessIteratorTT < hface_STI > :: InnerHandle mif (this->containerPll (),l) ;
+          AccessIteratorTT < hface_STI > :: OuterHandle mof (this->containerPll (),l) ;
+
+          InnerIteratorType wi (mif);
+          for (wi.first () ; ! wi.done () ; wi.next ()) 
+          {
+            pair < ElementPllXIF_t *, int > p = wi.item ().accessPllX ().accessInnerPllX () ;
+            p.first->writeDynamicState (osv [l], p.second) ;
+          }
+        
+          OuterIteratorType wo (mof);
+          for (wo.first () ; ! wo.done () ; wo.next ()) 
+          {
+            pair < ElementPllXIF_t *, int > p = wo.item ().accessPllX ().accessInnerPllX () ;
+            p.first->writeDynamicState (osv [l], p.second) ;
+          }
+        }
+      } 
+    }
+    
+    osv = mpAccess ().exchange (osv) ;
+    
+    { 
+      for (int l = 0 ; l < nl ; l ++ ) 
+      {
+        {
+          AccessIteratorTT < hface_STI > :: OuterHandle mof (this->containerPll (),l) ;
+          AccessIteratorTT < hface_STI > :: InnerHandle mif (this->containerPll (),l) ;
+        
+          OuterIteratorType wo (mof) ;
+          for (wo.first () ; ! wo.done () ; wo.next ()) 
+          {
+            pair < ElementPllXIF_t *, int > p = wo.item ().accessPllX ().accessOuterPllX () ;
+            p.first->readDynamicState (osv [l], p.second) ;
+          }
+        
+          InnerIteratorType wi (mif);
+          for (wi.first () ; ! wi.done () ; wi.next ()) 
+          {
+            pair < ElementPllXIF_t *, int > p = wi.item ().accessPllX ().accessOuterPllX () ;
+            p.first->readDynamicState (osv [l], p.second) ;
+          }
+        }
+      } 
+    }
+  } 
+  catch (Parallel ::  AccessPllException) 
+  {
+    cerr << "  FEHLER Parallel :: AccessPllException entstanden in: " << __FILE__ << " " << __LINE__ << endl ;
+  }
+  assert (debugOption (20) ? (cout << "**INFO GitterDunePll :: exchangeDynamicState () used " << (float)(clock () - start)/(float)(CLOCKS_PER_SEC) << " sec. " << endl, 1) : 1 ) ;
+  }
+}
+
+void GitterDunePll :: duneExchangeData (GatherScatterType & gs) 
+{
+  // Die Methode wird jedesmal aufgerufen, wenn sich der dynamische
+  // Zustand des Gitters ge"andert hat: Verfeinerung und alle Situationen
+  // die einer "Anderung des statischen Zustands entsprechen. Sie wird in
+  // diesem Fall NACH dem Update des statischen Zustands aufgerufen, und
+  // kann demnach von einem korrekten statischen Zustand ausgehen. F"ur
+  // Methoden die noch h"aufigere Updates erfordern m"ussen diese in der
+  // Regel hier eingeschleift werden.
+  {
+  int mallocedsize;
+  const int nl = mpAccess ().nlinks () ;
+  const int start = clock () ;
+  try 
+  {
+    typedef Insert < AccessIteratorTT < hface_STI > :: InnerHandle,
+                TreeIterator < hface_STI, is_def_true < hface_STI > > > InnerIteratorType;
+    typedef Insert < AccessIteratorTT < hface_STI > :: OuterHandle, 
+                TreeIterator < hface_STI, is_def_true < hface_STI > > > OuterIteratorType;
+                
+    vector < ObjectStream > osv (nl) ;
+    {
+      for (int l = 0 ; l < nl ; l ++) 
+      {
+        {
+          AccessIteratorTT < hface_STI > :: InnerHandle mif (this->containerPll (),l) ;
+          AccessIteratorTT < hface_STI > :: OuterHandle mof (this->containerPll (),l) ;
+
+          InnerIteratorType wi (mif);
+          for (wi.first () ; ! wi.done () ; wi.next ()) 
+          {
+            pair < ElementPllXIF_t *, int > p = wi.item ().accessPllX ().accessInnerPllX () ;
+            p.first->writeDynamicState (osv [l], p.second) ;
+            p.first->writeDynamicState (osv [l], gs) ;
+          }
+        
+          OuterIteratorType wo (mof);
+          for (wo.first () ; ! wo.done () ; wo.next ()) 
+          {
+            pair < ElementPllXIF_t *, int > p = wo.item ().accessPllX ().accessInnerPllX () ;
+            p.first->writeDynamicState (osv [l], p.second) ;
+            p.first->writeDynamicState (osv [l], gs) ;
+          }
+        }
+      } 
+    }
+    
+    osv = mpAccess ().exchange (osv) ;
+    
+    { 
+      for (int l = 0 ; l < nl ; l ++ ) 
+      {
+        {
+          AccessIteratorTT < hface_STI > :: OuterHandle mof (this->containerPll (),l) ;
+          AccessIteratorTT < hface_STI > :: InnerHandle mif (this->containerPll (),l) ;
+        
+          OuterIteratorType wo (mof) ;
+          for (wo.first () ; ! wo.done () ; wo.next ()) 
+          {
+            pair < ElementPllXIF_t *, int > p = wo.item ().accessPllX ().accessOuterPllX () ;
+            p.first->readDynamicState (osv [l], p.second) ;
+            p.first->readDynamicState (osv [l], gs) ;
+          }
+        
+          InnerIteratorType wi (mif);
+          for (wi.first () ; ! wi.done () ; wi.next ()) 
+          {
+            pair < ElementPllXIF_t *, int > p = wi.item ().accessPllX ().accessOuterPllX () ;
+            p.first->readDynamicState (osv [l], p.second) ;
+            p.first->readDynamicState (osv [l], gs ) ;
+          }
+        }
+      } 
+    }
+  } 
+  catch (Parallel ::  AccessPllException) 
+  {
+    cerr << "  FEHLER Parallel :: AccessPllException entstanden in: " << __FILE__ << " " << __LINE__ << endl ;
+  }
+  assert (debugOption (20) ? (cout << "**INFO GitterDunePll :: exchangeDynamicState () used " << (float)(clock () - start)/(float)(CLOCKS_PER_SEC) << " sec. " << endl, 1) : 1 ) ;
+  }
+}
+
+bool GitterDunePll :: refine () {
+  assert (debugOption (5) ? (cout << "**INFO GitterPll :: refine () " << endl, 1) : 1) ;
+  const int nl = mpAccess ().nlinks (), start = clock () ;
+  bool state = false ;
+  vector < vector < hedge_STI * > > innerEdges (nl), outerEdges (nl) ;
+  vector < vector < hface_STI * > > innerFaces (nl), outerFaces (nl) ;
+  {
+  // Erst die Zeiger auf alle Fl"achen und Kanten mit paralleler
+  // Mehrdeutigkeit sichern, da die LeafIteratorTT < . > nach dem 
+  // Verfeinern auf gitter nicht mehr stimmen werden. Die Technik
+  // ist zul"assig, da keine mehrfache Verfeinerung entstehen kann.
+  
+    {for (int l = 0 ; l < nl ; l ++) {
+      //cout << "refinepll \n";
+      LeafIteratorTT < hface_STI > fw (*this,l) ;
+      LeafIteratorTT < hedge_STI > dw (*this,l) ;
+      for (fw.outer ().first () ; ! fw.outer().done () ; fw.outer ().next ())
+        outerFaces [l].push_back (& fw.outer ().item ()) ;
+      for (fw.inner ().first () ; ! fw.inner ().done () ; fw.inner ().next ())
+        innerFaces [l].push_back (& fw.inner ().item ()) ;
+      for (dw.outer ().first () ; ! dw.outer().done () ; dw.outer ().next ())
+        outerEdges [l].push_back (& dw.outer ().item ()) ;
+      for (dw.inner ().first () ; ! dw.inner ().done () ; dw.inner ().next ())
+        innerEdges [l].push_back (& dw.inner ().item ()) ;
+    }}
+      // jetzt normal verfeinern und den Status der Verfeinerung
+  // [unvollst"andige / vollst"andige Verfeinerung] sichern.
+    
+    __STATIC_phase = 1 ;
+    
+    state = Gitter :: refine () ;
+       
+  // Phase des Fl"achenausgleichs an den Schnittfl"achen des
+  // verteilten Gitters. Weil dort im sequentiellen Fall pseudorekursive
+  // Methodenaufrufe vorliegen k"onnen, muss solange iteriert werden,
+  // bis die Situation global station"ar ist.
+  
+    __STATIC_phase = 2 ;
+  
+    bool repeat (false) ;
+    _refineLoops = 0 ;
+    do {
+      repeat = false ;
+      {
+        vector < ObjectStream > osv (nl) ;
+        try {
+      //cout << "refinepll 2 \n";
+    for (int l = 0 ; l < nl ; l ++) {
+            {for (vector < hface_STI * > :: const_iterator i = outerFaces [l].begin () ;
+              i != outerFaces [l].end () ; (*i ++)->accessPllX ().accessOuterPllX ().first->getRefinementRequest (osv [l])) ; }
+            {for (vector < hface_STI * > :: const_iterator i = innerFaces [l].begin () ;
+              i != innerFaces [l].end () ; (*i ++)->accessPllX ().accessOuterPllX ().first->getRefinementRequest (osv [l])) ; }
+          }
+  } catch (Parallel :: AccessPllException) {
+          cerr << "**FEHLER (FATAL) AccessPllException in " << __FILE__ << " " << __LINE__ << endl ; abort () ;
+        }
+  
+        osv = mpAccess ().exchange (osv) ;
+  
+        try {
+    for (int l = 0 ; l < nl ; l ++) {
+            {for (vector < hface_STI * > :: const_iterator i = innerFaces [l].begin () ;
+              i != innerFaces [l].end () ; repeat |= (*i ++)->accessPllX ().accessOuterPllX ().first->setRefinementRequest (osv [l])) ; }
+            {for (vector < hface_STI * > :: const_iterator i = outerFaces [l].begin () ;
+              i != outerFaces [l].end () ; repeat |= (*i ++)->accessPllX ().accessOuterPllX ().first->setRefinementRequest (osv [l])) ; }
+          }
+  } catch (Parallel :: AccessPllException) {
+          cerr << "**FEHLER (FATAL) AccessPllException in " << __FILE__ << " " << __LINE__ << endl ; abort () ;
+        }
+      }
+
+      _refineLoops ++ ;
+    } while (mpAccess ().gmax (repeat ? 1 : 0)) ;
+
+  // Jetzt noch die Kantensituation richtigstellen, es gen"ugt ein Durchlauf,
+  // weil die Verfeinerung einer Kante keine Fernwirkungen hat. Vorsicht: Die
+  // Kanten sind bez"uglich ihrer Identifikation sternf"ormig organisiert, d.h.
+  // es muss die Verfeinerungsinformation einmal am Eigent"umer gesammelt und
+  // dann wieder zur"ucktransportiert werden, eine einfache L"osung, wie bei
+  // den Fl"achen (1/1 Beziehung) scheidet aus.
+
+    __STATIC_phase = 3 ;
+
+    {
+      vector < ObjectStream > osv (nl) ;
+      {for (int l = 0 ; l < nl ; l ++) 
+        for (vector < hedge_STI * > :: const_iterator i = outerEdges [l].begin () ;
+          i != outerEdges [l].end () ; (*i ++)->accessPllX ().getRefinementRequest (osv [l])) ;
+      }
+      osv = mpAccess ().exchange (osv) ;
+      {for (int l = 0 ; l < nl ; l ++)
+        for (vector < hedge_STI * > :: const_iterator i = innerEdges [l].begin () ;
+          i != innerEdges [l].end () ; (*i ++)->accessPllX ().setRefinementRequest (osv [l])) ;
+      }
+    }   // ~vector < ObjectStream > ... 
+    {
+      vector < ObjectStream > osv (nl) ;
+      {for (int l = 0 ; l < nl ; l ++)
+        for (vector < hedge_STI * > :: const_iterator i = innerEdges [l].begin () ;
+          i != innerEdges [l].end () ; (*i ++)->accessPllX ().getRefinementRequest (osv [l])) ;
+      }
+      osv = mpAccess ().exchange (osv) ;
+      {for (int l = 0 ; l < nl ; l ++)
+        for (vector < hedge_STI * > :: const_iterator i = outerEdges [l].begin () ;
+          i != outerEdges [l].end () ; (*i ++)->accessPllX ().setRefinementRequest (osv [l])) ;
+      }
+    }   // ~vector < ObjectStream > ... 
+  }
+  
+  __STATIC_phase = -1 ;
+  
+  return state ;
+}
+
+void GitterDunePll :: coarse () {
+  assert (debugOption (20) ? (cout << "**INFO GitterPll :: coarse () " << endl, 1) : 1) ;
+  const int nl = mpAccess ().nlinks () ;
+  
+  {
+    vector < vector < hedge_STI * > > innerEdges (nl), outerEdges (nl) ;
+    vector < vector < hface_STI * > > innerFaces (nl), outerFaces (nl) ;
+  
+    for (int l = 0 ; l < nl ; l ++) {
+    
+  // Zun"achst werden f"ur alle Links die Zeiger auf Gitterojekte mit
+  // Mehrdeutigkeit gesichert, die an der Wurzel einer potentiellen
+  // Vergr"oberungsoperation sitzen -> es sind die Knoten in der Hierarchie,
+  // deren Kinder alle Bl"atter sind. Genau diese Knoten sollen gegen"uber
+  // der Vergr"oberung blockiert werden und dann die Vergr"oberung falls
+  // sie zul"assig ist, sp"ater durchgef"uhrt werden (pending) ;
+    
+      AccessIteratorTT < hface_STI > :: InnerHandle mfwi (containerPll (),l) ;
+      AccessIteratorTT < hface_STI > :: OuterHandle mfwo (containerPll (),l) ;
+      AccessIteratorTT < hedge_STI > :: InnerHandle mdwi (containerPll (),l) ;
+      AccessIteratorTT < hedge_STI > :: OuterHandle mdwo (containerPll (),l) ;
+      
+  // Die inneren und a"usseren Iteratoren der potentiell vergr"oberungsf"ahigen
+  // Fl"achen "uber den Grobgitterfl"achen. In den Elementen passiert erstmal
+  // nichts, solange nicht mit mehrfachen Grobgitterelementen gearbeitet wird.
+      
+      Insert < AccessIteratorTT < hface_STI > :: InnerHandle, 
+        TreeIterator < hface_STI, childs_are_leafs < hface_STI > > > fwi (mfwi) ;
+      Insert < AccessIteratorTT < hface_STI > :: OuterHandle, 
+        TreeIterator < hface_STI, childs_are_leafs < hface_STI > > > fwo (mfwo) ;
+      
+  // Die inneren und a"usseren Iteratoren der potentiell vergr"oberungsf"ahigen
+  // Kanten "uber den Grobgitterkanten.
+      
+      Insert < AccessIteratorTT < hedge_STI > :: InnerHandle, 
+        TreeIterator < hedge_STI, childs_are_leafs < hedge_STI > > > dwi (mdwi) ;
+      Insert < AccessIteratorTT < hedge_STI > :: OuterHandle, 
+        TreeIterator < hedge_STI, childs_are_leafs < hedge_STI > > > dwo (mdwo) ;
+
+  // Die inneren und a"usseren Iteratoren der potentiell vergr"oberungsf"ahigen
+  // Kanten "uber den Grobgitterfl"achen. Diese Konstruktion wird beim Tetraeder-
+  // gitter notwendig, weil dort keine Aussage der Form:
+  //
+
+      Insert < AccessIteratorTT < hface_STI > :: InnerHandle, 
+        TreeIterator < hface_STI, has_int_edge < hface_STI > > > efi (mfwi) ;
+      Insert < AccessIteratorTT < hface_STI > :: OuterHandle, 
+        TreeIterator < hface_STI, has_int_edge < hface_STI > > > efo (mfwo) ;
+      Wrapper < Insert < AccessIteratorTT < hface_STI > :: InnerHandle, 
+        TreeIterator < hface_STI, has_int_edge < hface_STI > > >, InternalEdge > eifi (efi) ;
+      Wrapper < Insert < AccessIteratorTT < hface_STI > :: OuterHandle, 
+        TreeIterator < hface_STI, has_int_edge < hface_STI > > >, InternalEdge > eifo (efo) ;
+      Insert < Wrapper < Insert < AccessIteratorTT < hface_STI > :: InnerHandle, 
+        TreeIterator < hface_STI, has_int_edge < hface_STI > > >, InternalEdge >,
+  TreeIterator < hedge_STI, childs_are_leafs < hedge_STI > > > dfi (eifi) ;
+      Insert < Wrapper < Insert < AccessIteratorTT < hface_STI > :: OuterHandle, 
+        TreeIterator < hface_STI, has_int_edge < hface_STI > > >, InternalEdge >,
+  TreeIterator < hedge_STI, childs_are_leafs < hedge_STI > > > dfo (eifo) ;
+
+  // Die 'item ()' Resultatwerte (Zeiger) werden in Vektoren gesichert, weil die
+  // Kriterien die zur Erzeugung der Iteratoren angewendet wurden (Filter) nach
+  // einer teilweisen Vergr"oberung nicht mehr g"ultig sein werden, d.h. die 
+  // Iterationsobjekte "andern w"ahrend der Vergr"oberung ihre Eigenschaften.
+  // Deshalb werden sie auch am Ende des Blocks aufgegeben. Der Vektor 'cache'
+  // ist zul"assig, weil kein Objekt auf das eine Referenz im 'cache' vorliegt
+  // beseitigt werden kann. Sie sind alle ein Niveau darunter.
+
+      for (fwi.first () ; ! fwi.done () ; fwi.next ()) innerFaces [l].push_back (& fwi.item ()) ;
+      for (fwo.first () ; ! fwo.done () ; fwo.next ()) outerFaces [l].push_back (& fwo.item ()) ;
+      for (dwo.first () ; ! dwo.done () ; dwo.next ()) outerEdges [l].push_back (& dwo.item ()) ;
+      for (dfo.first () ; ! dfo.done () ; dfo.next ()) outerEdges [l].push_back (& dfo.item ()) ;
+      for (dwi.first () ; ! dwi.done () ; dwi.next ()) innerEdges [l].push_back (& dwi.item ()) ;
+      for (dfi.first () ; ! dfi.done () ; dfi.next ()) innerEdges [l].push_back (& dfi.item ()) ;
+    }
+    try {
+  // Erstmal alles was mehrdeutig ist, gegen die drohende Vergr"oberung sichern.
+  // Danach werden sukzessive die Fl"achenlocks aufgehoben, getestet und
+  // eventuell vergr"obert, dann das gleiche Spiel mit den Kanten.
+
+      for (int l = 0 ; l < nl ; l ++) {
+        {for (vector < hedge_STI * > :: iterator i = outerEdges [l].begin () ;
+            i != outerEdges [l].end () ; (*i ++)->accessPllX ().lockAndTry ()) ; }
+        {for (vector < hedge_STI * > :: iterator i = innerEdges [l].begin () ;
+            i != innerEdges [l].end () ; (*i ++)->accessPllX ().lockAndTry ()) ; }
+        {for (vector < hface_STI * > :: iterator i = outerFaces [l].begin () ;
+            i != outerFaces [l].end () ; (*i ++)->accessPllX ().accessOuterPllX ().first->lockAndTry ()) ; }
+        {for (vector < hface_STI * > :: iterator i = innerFaces [l].begin () ;
+            i != innerFaces [l].end () ; (*i ++)->accessPllX ().accessOuterPllX ().first->lockAndTry ()) ; }
+      }
+      
+        // Gitter :: coarse () ist elementorientiert, d.h. die Vergr"oberung auf Fl"achen und
+  // Kanten wird nur durch Vermittlung eines sich vergr"obernden Knotens in der Element-
+  // hierarchie angestossen. In allen gegen Vergr"oberung 'gelockten' Fl"achen und Kanten
+  // wird die angeforderte Operation zur"uckgewiesen, um erst sp"ater von aussen nochmals
+  // angestossen zu werden.
+      
+      __STATIC_phase = 4 ;
+      
+      Gitter :: coarse () ;
+      
+    } catch (Parallel :: AccessPllException) {
+      cerr << "**FEHLER (FATAL) AccessPllException beim Vergr\"obern der Elementhierarchie oder\n" ;
+      cerr << "  beim locken der Fl\"achen- bzw. Kantenb\"aume aufgetreten. In " << __FILE__ << " " << __LINE__ << endl ;
+      abort () ;
+    }
+    try {
+    
+  // Phase des Fl"achenausgleichs des verteilten Vergr"oberungsalgorithmus
+  // alle Schnittfl"achenpaare werden daraufhin untersucht, ob eine
+  // Vergr"oberung in beiden Teilgittern durchgef"uhrt werden darf,
+  // wenn ja, wird in beiden Teilgittern vergr"obert und der Vollzug
+  // getestet.
+  
+      __STATIC_phase = 5 ;
+    
+      vector < vector < int > > clean (nl) ;
+      {
+        vector < vector < int > > inout (nl) ;
+        {for (int l = 0 ; l < nl ; l ++)
+          for (vector < hface_STI * > :: iterator i = outerFaces [l].begin () ; i != outerFaces [l].end () ; i ++)
+            inout [l].push_back ((*i)->accessPllX ().accessOuterPllX ().first->lockAndTry ()) ;
+        }
+        inout = mpAccess ().exchange (inout) ;
+        {for (int l = 0 ; l < nl ; l ++) {
+          clean [l] = vector < int > (innerFaces [l].size (), long (true)) ;
+    vector < int > :: iterator j = clean [l].begin (), k = inout [l].begin () ;
+          for (vector < hface_STI * > :: iterator i = innerFaces [l].begin () ; i != innerFaces [l].end () ; i ++, j++, k++) {
+      assert (j != clean [l].end ()) ; assert (k != inout [l].end ()) ;
+      (*j) &= (*k) && (*i)->accessPllX ().accessOuterPllX ().first->lockAndTry () ;
+    }
+        }}
+      }
+      {
+        vector < vector < int > > inout (nl) ;
+        {for (int l = 0 ; l < nl ; l ++) {
+          vector < int > :: iterator j = clean [l].begin () ;
+    for (vector < hface_STI * > :: iterator i = innerFaces [l].begin () ; i != innerFaces [l].end () ; i ++, j++) {
+      inout [l].push_back (*j) ;
+      (*i)->accessPllX ().accessOuterPllX ().first->unlockAndResume (bool (*j)) ;
+    }
+        }}
+      
+        inout = mpAccess ().exchange (inout) ;
+      
+        {for (int l = 0 ; l < nl ; l ++) {
+          vector < int > :: iterator j = inout [l].begin () ;
+          for (vector < hface_STI * > :: iterator i = outerFaces [l].begin () ; i != outerFaces [l].end () ; i ++, j++) {
+      assert (j != inout [l].end ()) ;
+      (*i)->accessPllX ().accessOuterPllX ().first->unlockAndResume (bool (*j)) ;
+    }
+        }}
+      }
+    } catch (Parallel :: AccessPllException) {
+      cerr << "**FEHLER (FATAL) AccessPllException beim Vergr\"obern der Fl\"achenb\"aume\n" ;
+      cerr << "  aufgetreten. In " << __FILE__ << " " << __LINE__ << endl ;
+      abort () ;
+    }
+    try {
+    
+  // Phase des Kantenausgleichs im parallelen Vergr"oberungsalgorithmus:
+  
+      __STATIC_phase  = 6 ;
+    
+  // Weil hier jede Kante nur eindeutig auftreten darf, muss sie in einem
+  // map als Adresse hinterlegt werden, dann k"onnen die verschiedenen
+  // Refcounts aus den verschiedenen Links tats"achlich global miteinander
+  // abgemischt werden. Dazu werden zun"achst alle eigenen Kanten auf ihre
+  // Vergr"oberbarkeit hin untersucht und dieser Zustand (true = vergr"oberbar
+  // false = darf nicht vergr"obert werden) im map 'clean' hinterlegt. Dazu
+  // kommt noch ein zweiter 'bool' Wert, der anzeigt ob die Kante schon ab-
+  // schliessend vergr"obert wurde oder nicht. 
+    
+      map < hedge_STI *, pair < bool, bool >, less < hedge_STI * > > clean ;
+      
+      {for (int l = 0 ; l < nl ; l ++)
+        for (vector < hedge_STI * > :: iterator i = innerEdges [l].begin () ; i != innerEdges [l].end () ; i ++)
+    if (clean.find (*i) == clean.end ()) clean [*i] = pair < bool, bool > ((*i)->accessPllX ().lockAndTry (), true) ;
+      }
+      {
+        vector < vector < int > > inout (nl) ;
+        {for (int l = 0 ; l < nl ; l ++)
+          for (vector < hedge_STI * > :: iterator i = outerEdges [l].begin () ; i != outerEdges [l].end () ; i ++)
+            inout [l].push_back ((*i)->accessPllX ().lockAndTry ()) ;
+  }
+        inout = mpAccess ().exchange (inout) ;
+        {for (int l = 0 ; l < nl ; l ++) {
+    vector < int > :: const_iterator j = inout [l].begin () ;
+          for (vector < hedge_STI * > :: iterator i = innerEdges [l].begin () ; i != innerEdges [l].end () ; i ++, j++) {
+      assert (j != inout [l].end ()) ;
+            assert (clean.find (*i) != clean.end ()) ;
+            if (*j == false) clean [*i] = pair < bool, bool > (false, clean[*i].second) ; 
+    }
+        }}
+      }
+      {
+        vector < vector < int > > inout (nl) ;
+        {for (int l = 0 ; l < nl ; l ++) {
+    for (vector < hedge_STI * > :: iterator i = innerEdges [l].begin () ; i != innerEdges [l].end () ; i ++) {
+      assert (clean.find (*i) != clean.end ()) ;
+      pair < bool, bool > & a = clean [*i] ;
+      inout [l].push_back (a.first) ;
+      if (a.second) {
+  
+  // Wenn wir hier sind, kann die Kante tats"achlich vergr"obert werden, genauer gesagt,
+  // sie wird es auch und der R"uckgabewert testet den Vollzug der Aktion. Weil aber nur
+  // einmal vergr"obert werden kann, und die Iteratoren 'innerEdges [l]' aber eventuell
+  // mehrfach "uber eine Kante hinweglaufen, muss diese Vergr"oberung im map 'clean'
+  // vermerkt werden. Dann wird kein zweiter Versuch unternommen.
+  
+        a.second = false ;
+        bool b = (*i)->accessPllX ().unlockAndResume (a.first) ;
+        assert (b == a.first) ;
+      }
+    }
+        }}
+        inout = mpAccess ().exchange (inout) ;
+        {for (int l = 0 ; l < nl ; l ++) {
+          vector < int > :: iterator j = inout [l].begin () ;
+          for (vector < hedge_STI * > :: iterator i = outerEdges [l].begin () ; i != outerEdges [l].end () ; i ++, j++) {
+      assert (j != inout [l].end ()) ;
+      
+  // Selbe Situation wie oben, aber der Eigent"umer der Kante hat mitgeteilt, dass sie
+  // vergr"obert werden darf und auch wird auf allen Teilgebieten also auch hier. Der
+  // Vollzug der Vergr"oberung wird durch den R"uckgabewert getestet.
+      
+      bool b = (*i)->accessPllX ().unlockAndResume (bool (*j)) ;
+      assert (b == bool (*j)) ;
+    }
+        }}
+      }
+    } catch (Parallel :: AccessPllException) {
+      cerr << "**FEHLER (FATAL) AccessPllException beim Vergr\"obern der Kantenb\"aume\n" ;
+      cerr << "  aufgetreten. In " << __FILE__ << " " << __LINE__ << endl ;
+      abort () ;
+    }
+  }
+  
+  __STATIC_phase = -1 ;
+  
+  return ;
+}
+
+#endif
diff --git a/src/duneinterface/gitter_dune_pll_impl.h b/src/duneinterface/gitter_dune_pll_impl.h
new file mode 100644
index 000000000..3179341fb
--- /dev/null
+++ b/src/duneinterface/gitter_dune_pll_impl.h
@@ -0,0 +1,80 @@
+#ifndef GITTER_DUNE_PLL_IMPL_H_INCLUDED
+#define GITTER_DUNE_PLL_IMPL_H_INCLUDED
+
+#ifdef _ANSI_HEADER
+  using namespace std;
+  #include <numeric>
+#else
+#endif
+
+#include "gitter_dune_impl.h"
+ 
+#include "gitter_pll_impl.h"
+#include "gitter_pll_ldb.h"
+  
+static bool writeLogFile = false;
+
+class GitterDunePll : public GitterBasisPll , public virtual GitterDuneBasis
+{
+  
+protected:  
+  bool balanceGrid_;
+
+public:
+  typedef Gitter :: Geometric Geometric;
+  typedef GitterDuneImpl :: Objects  Objects;
+  
+  GitterDunePll (const char * filename , MpAccessLocal &mp) 
+    : GitterBasisPll (filename,mp) , balanceGrid_ (false) 
+  {
+    // logfile is defined in gitter_impl.h    
+    /*
+    char logFileName [32];
+    sprintf(logFileName,"logfile.%d",mpAccess().myrank());
+    cerr << "open logfile = " << logFileName << "\n";
+
+    logFile.close();
+    logFile.open (logFileName);
+    logFile << "logfile of processor " << mpAccess().myrank() << "\n";
+    */
+  };
+
+  ~GitterDunePll () {
+    /*
+    logFile.close();
+    */
+  }
+
+  bool refine (); 
+
+  void coarse ();
+
+  // done call notify and loadBalancer  
+  bool duneAdapt ();
+
+  // return true if grid has to be balanced again 
+  bool duneNotifyNewGrid ();
+
+  bool duneLoadBalance () ; // call loadBalancer 
+  bool duneLoadBalance (GatherScatterType & ) ; // call loadBalancer a
+
+  void duneRepartitionMacroGrid (LoadBalancer :: DataBase &, GatherScatterType & gs) ;
+  void repartitionMacroGrid (LoadBalancer :: DataBase &) ;
+ 
+  // notifyGridChanges for dune
+  void duneNotifyGridChanges (); 
+  
+  // exchange changed elements  
+  void duneExchangeDynamicState ();
+  
+  // exchange data of dune 
+  void duneExchangeData (GatherScatterType &);
+
+  // return indexmanger 
+  IndexManagerType & indexManager(int codim)
+  {
+    return containerPll().indexManager(codim);
+  }
+
+};
+#endif
diff --git a/src/duneinterface/gitter_dune_pll_mgb.cc b/src/duneinterface/gitter_dune_pll_mgb.cc
new file mode 100644
index 000000000..0843733bb
--- /dev/null
+++ b/src/duneinterface/gitter_dune_pll_mgb.cc
@@ -0,0 +1,560 @@
+// (c) Robert Kloefkorn 2004 - 2005 
+#ifndef GITTER_DUNE_PLL_MGB_CC_INCLUDED
+#define GITTER_DUNE_PLL_MGB_CC_INCLUDED
+
+#ifdef IBM_XLC
+  #define _ANSI_HEADER
+#endif
+  
+#include <assert.h>
+#include <time.h>
+#include <stdio.h>
+
+#ifdef _ANSI_HEADER
+  using namespace std;
+  #include <iostream>
+  #include <iomanip>
+  #include <algorithm>
+#else
+  #include <iostream.h>
+  #include <iomanip.h>
+  #include <algo.h>
+#endif
+
+#include "serialize.h"
+#include "gitter_mgb.h"
+
+#include "gitter_pll_sti.h"
+#include "gitter_pll_mgb.h"
+
+class DuneParallelGridMover : public ParallelGridMover {
+  public :
+    DuneParallelGridMover (BuilderIF &i); 
+
+    // if not finalized yet, finalize is called 
+    ~DuneParallelGridMover () ;
+    inline void initialize (); //former constructor
+    inline void finalize ();   //former destructor
+    
+    // overlaoded, because calles unpackHbnd3 
+    inline void unpackAll (vector < ObjectStream > &) ;
+    inline void duneUnpackAll (vector < ObjectStream > &, GatherScatterType & ) ;
+
+  protected :
+    void duneUnpackTetra (ObjectStream &,GatherScatterType &) ;
+    // overloaded, because calles InsertUniqueHbnd3_withPoint
+    inline void unpackHbnd3Int (ObjectStream & os); 
+    
+    bool InsertUniqueHbnd3_withPoint (int (&)[3], Gitter :: hbndseg ::
+            bnd_t,const double (&p) [3]) ;
+        
+};
+
+// new method that gets coord of ghost point 
+bool DuneParallelGridMover :: InsertUniqueHbnd3_withPoint (int (&v)[3],         
+      Gitter :: hbndseg_STI ::bnd_t bt, const double (&p)[3]) {
+  int twst = cyclicReorder (v,v+3) ;
+  faceKey_t key (v [0], v [1], v [2]) ;
+  if (bt == Gitter :: hbndseg_STI :: closure) {
+    if (_hbnd3Int.find (key) == _hbnd3Int.end ()) {
+      hface3_GEO * face =  InsertUniqueHface3 (v).first ;
+      // here the point is stored 
+      _hbnd3Int [key] = new Hbnd3IntStorage (face,twst,p) ;
+      return true ;
+    }
+  } else {
+    if (_hbnd3Map.find (key) == _hbnd3Map.end ()) {
+      hface3_GEO * face =  InsertUniqueHface3 (v).first ;
+      hbndseg3_GEO * hb3 = myBuilder ().insert_hbnd3 (face,twst,bt) ;
+      _hbnd3Map [key] = hb3 ;
+      return true ;
+    }
+  }
+  return false ;
+}
+
+// overloaded method because here we call insertion with point 
+inline void DuneParallelGridMover :: unpackHbnd3Int (ObjectStream & os) 
+{
+  double p [3] = {0.0,0.0,0.0};
+  int bfake, v [3] ;
+  os.readObject (bfake) ;
+  Gitter :: hbndseg :: bnd_t b = (Gitter :: hbndseg :: bnd_t) bfake;
+  
+  os.readObject (v[0]) ;
+  os.readObject (v[1]) ;
+  os.readObject (v[2]) ;
+
+  int readPoint = 0; 
+  os.readObject( readPoint ); 
+
+  if( readPoint ) 
+  {
+    os.readObject (p[0]) ;
+    os.readObject (p[1]) ;
+    os.readObject (p[2]) ;
+  }
+
+  if(b == Gitter :: hbndseg :: closure)
+  {
+    //cout << "Insert Unique Hbnd3 p \n";
+    InsertUniqueHbnd3_withPoint (v, b, p ) ;
+  }
+  else
+  {
+    assert(readPoint == 0);
+    // old method defined in base class 
+    InsertUniqueHbnd3 (v, b ) ;
+  }
+  return ;
+}
+
+
+void DuneParallelGridMover :: duneUnpackTetra (ObjectStream & os, GatherScatterType & gs) {
+  int v [4] ;
+  os.readObject (v[0]) ;
+  os.readObject (v[1]) ;
+  os.readObject (v[2]) ;
+  os.readObject (v[3]) ;
+  pair < tetra_GEO *, bool > p = InsertUniqueTetra (v) ;
+  p.first->accessPllX ().duneUnpackSelf (os,gs,p.second) ;
+  return ;
+}
+
+void DuneParallelGridMover :: unpackAll (vector < ObjectStream > & osv) {
+  for (vector < ObjectStream > :: iterator j = osv.begin () ; j != osv.end () ; j ++) {
+    ObjectStream & os (*j) ;
+    int code = MacroGridMoverIF :: ENDMARKER ;
+    for (os.readObject (code) ; code != MacroGridMoverIF :: ENDMARKER ; os.readObject (code)) {
+      switch (code) {
+      case MacroGridMoverIF:: VERTEX :
+        unpackVertex (os) ;
+        break ;
+      case MacroGridMoverIF :: EDGE1 :
+        unpackHedge1 (os) ;
+        break ;
+      case MacroGridMoverIF :: FACE3 :
+        unpackHface3 (os) ;
+        break ;
+      case MacroGridMoverIF :: FACE4 :
+        unpackHface4 (os) ;
+        break ;
+      case MacroGridMoverIF :: TETRA :
+        unpackTetra (os) ;
+        break ;
+      case MacroGridMoverIF :: HEXA :
+        unpackHexa (os) ;
+        break ;
+      case MacroGridMoverIF :: PERIODIC3 :
+        unpackPeriodic3 (os) ;
+        break ;
+      case MacroGridMoverIF :: PERIODIC4 :
+        unpackPeriodic4 (os) ;
+        break ;
+      case MacroGridMoverIF :: HBND3INT :
+        unpackHbnd3Int (os) ;
+        break ;
+      case MacroGridMoverIF :: HBND3EXT :
+        unpackHbnd3Ext (os) ;
+        break ;
+      case MacroGridMoverIF :: HBND4INT :
+      case MacroGridMoverIF :: HBND4EXT :
+        unpackHbnd4 (os) ;
+        break ;
+      default :
+  cerr << "**FEHLER (FATAL) Unbekannte Gitterobjekt-Codierung gelesen [" << code << "]\n" ;
+  cerr << "  Weitermachen unm\"oglich. In " << __FILE__ << " " << __LINE__ << endl ;
+  abort () ;
+        break ;
+      }
+    }
+  }  
+  return ;
+}
+
+void DuneParallelGridMover :: duneUnpackAll (vector < ObjectStream > & osv,
+    GatherScatterType & gs) {
+  for (vector < ObjectStream > :: iterator j = osv.begin () ; j != osv.end () ; j ++) {
+    ObjectStream & os (*j) ;
+    int code = MacroGridMoverIF :: ENDMARKER ;
+    for (os.readObject (code) ; code != MacroGridMoverIF :: ENDMARKER ; os.readObject (code)) {
+      switch (code) {
+      case MacroGridMoverIF:: VERTEX :
+  unpackVertex (os) ;
+  break ;
+      case MacroGridMoverIF :: EDGE1 :
+        unpackHedge1 (os) ;
+  break ;
+      case MacroGridMoverIF :: FACE3 :
+        unpackHface3 (os) ;
+  break ;
+      case MacroGridMoverIF :: FACE4 :
+  unpackHface4 (os) ;
+  break ;
+      case MacroGridMoverIF :: TETRA :
+        duneUnpackTetra (os,gs) ;
+        break ;
+      case MacroGridMoverIF :: HEXA :
+  unpackHexa (os) ;
+        break ;
+      case MacroGridMoverIF :: PERIODIC3 :
+        unpackPeriodic3 (os) ;
+        break ;
+// Anfang - Neu am 23.5.02 (BS)
+      case MacroGridMoverIF :: PERIODIC4 :
+        unpackPeriodic4 (os) ;
+        break ;
+// Ende - Neu am 23.5.02 (BS)
+      case MacroGridMoverIF :: HBND3INT :
+        unpackHbnd3Int (os) ;
+        break ;
+      case MacroGridMoverIF :: HBND3EXT :
+        unpackHbnd3Ext (os) ;
+        break ;
+      case MacroGridMoverIF :: HBND4INT :
+      case MacroGridMoverIF :: HBND4EXT :
+  unpackHbnd4 (os) ;
+        break ;
+      default :
+  cerr << "**FEHLER (FATAL) Unbekannte Gitterobjekt-Codierung gelesen [" << code << "]\n" ;
+  cerr << "  Weitermachen unm\"oglich. In " << __FILE__ << " " << __LINE__ << endl ;
+  abort () ;
+        break ;
+      }
+    }
+  }  
+  return ;
+}
+
+// calles initialize, former Constructor of MacroGridBuilder
+DuneParallelGridMover :: DuneParallelGridMover (BuilderIF & i) : ParallelGridMover (i,false) 
+{
+  initialize();
+}
+
+// overloaded, because here we use the new insertInternal method 
+void DuneParallelGridMover :: initialize ()
+{
+  {
+    for (list < VertexGeo * > :: iterator i = myBuilder ()._vertexList.begin () ;
+      i != myBuilder ()._vertexList.end () ; myBuilder ()._vertexList.erase (i ++)) 
+        _vertexMap [(*i)->ident ()] = (*i) ;
+  }
+  {
+    for (list < hedge1_GEO * > :: iterator i = myBuilder ()._hedge1List.begin () ;
+      i != myBuilder ()._hedge1List.end () ; myBuilder ()._hedge1List.erase (i ++)) {
+      long k = (*i)->myvertex (0)->ident (), l = (*i)->myvertex (1)->ident () ;
+      _edgeMap [edgeKey_t (k < l ? k : l, k < l ? l : k)] = (*i) ;
+    }
+  }
+  {for (list < hface3_GEO * > :: iterator i = myBuilder ()._hface3List.begin () ; i != myBuilder ()._hface3List.end () ;
+     myBuilder ()._hface3List.erase (i ++)) {
+      _face3Map [faceKey_t ((*i)->myvertex (0)->ident (),(*i)->myvertex (1)->ident (), (*i)->myvertex (2)->ident ())] = (*i) ;
+  }}
+  {
+    for (list < hface4_GEO * > :: iterator i = myBuilder ()._hface4List.begin () ; i != myBuilder ()._hface4List.end () ; 
+      myBuilder ()._hface4List.erase (i ++)) _face4Map [faceKey_t ((*i)->myvertex (0)->ident (),(*i)->myvertex (1)->ident (),
+        (*i)->myvertex (2)->ident ())] = (*i) ;
+  }
+  {for (list < hbndseg4_GEO * > :: iterator i = myBuilder ()._hbndseg4List.begin () ; i != myBuilder ()._hbndseg4List.end () ; myBuilder ()._hbndseg4List.erase (i++)) {
+    faceKey_t key ((*i)->myhface4 (0)->myvertex (0)->ident (), (*i)->myhface4 (0)->myvertex (1)->ident (), (*i)->myhface4 (0)->myvertex (2)->ident ()) ;
+    if ((*i)->bndtype () == Gitter :: hbndseg_STI :: closure) {
+      _hbnd4Int [key] = (void *) new pair < hface4_GEO *, int > ((*i)->myhface4 (0), (*i)->twist (0)) ;
+      delete (*i) ;
+    } else {
+      _hbnd4Map [key] = (*i) ;
+    }
+  }}
+  {for (list < hbndseg3_GEO * > :: iterator i = myBuilder ()._hbndseg3List.begin () ; i != myBuilder ()._hbndseg3List.end () ;
+    myBuilder ()._hbndseg3List.erase (i++)) {
+    faceKey_t key ((*i)->myhface3 (0)->myvertex (0)->ident (), (*i)->myhface3 (0)->myvertex (1)->ident (), (*i)->myhface3 (0)->myvertex (2)->ident ()) ;
+    if ((*i)->bndtype () == Gitter :: hbndseg_STI :: closure) 
+    {
+      // change
+      if((*i)->getGhost())
+      {
+        typedef Gitter :: Geometric :: tetra_GEO  tetra_GEO;
+        tetra_GEO * gh = static_cast<tetra_GEO *> ((*i)->getGhost());
+        // see insert_ghosttetra, point 3 is the new point 
+        _hbnd3Int [key] = new Hbnd3IntStorage ((*i)->myhface3 (0), (*i)->twist (0), gh->myvertex(3)->Point()) ;
+      }
+      // until here
+      else 
+        _hbnd3Int [key] = new Hbnd3IntStorage ((*i)->myhface3 (0), (*i)->twist (0)) ;
+      delete (*i) ;
+    } else {
+      _hbnd3Map [key] = (*i) ;
+    }
+  }}
+  {for (list < tetra_GEO * > :: iterator i = myBuilder ()._tetraList.begin () ; i != myBuilder ()._tetraList.end () ; 
+      myBuilder ()._tetraList.erase (i++)) {
+      _tetraMap [elementKey_t ((*i)->myvertex (0)->ident (), (*i)->myvertex (1)->ident (), 
+           (*i)->myvertex (2)->ident (), (*i)->myvertex (3)->ident ())] = (*i) ;
+  }}
+  {for (list < periodic3_GEO * > :: iterator i = myBuilder ()._periodic3List.begin () ; i != myBuilder ()._periodic3List.end () ; 
+      myBuilder ()._periodic3List.erase (i++)) {
+      _periodic3Map [elementKey_t ((*i)->myvertex (0)->ident (), (*i)->myvertex (1)->ident (), 
+           (*i)->myvertex (2)->ident (), -((*i)->myvertex (3)->ident ())-1)] = (*i) ;
+  }}
+  {for (list < periodic4_GEO * > :: iterator i = myBuilder ()._periodic4List.begin () ; i != myBuilder ()._periodic4List.end () ; 
+      myBuilder ()._periodic4List.erase (i++)) {
+      _periodic4Map [elementKey_t ((*i)->myvertex (0)->ident (), (*i)->myvertex (1)->ident (), 
+           (*i)->myvertex (3)->ident (), -((*i)->myvertex (4)->ident ())-1)] = (*i) ;
+  }}
+  {
+    for (list < hexa_GEO * > :: iterator i = myBuilder ()._hexaList.begin () ; i != myBuilder ()._hexaList.end () ; 
+      myBuilder ()._hexaList.erase (i++)) _hexaMap [elementKey_t ((*i)->myvertex (0)->ident (), (*i)->myvertex (1)->ident (), 
+                  (*i)->myvertex (3)->ident (), (*i)->myvertex (4)->ident ())] = (*i) ;
+  }
+
+  // from constructor ParallelGridMover 
+  vector < elementKey_t > toDelete ;
+  {for (elementMap_t :: iterator i = _hexaMap.begin () ; i != _hexaMap.end () ; i ++)
+    if (Gitter :: InternalElement ()(*((hexa_GEO *)(*i).second)).accessPllX ().erasable ()) {
+      toDelete.push_back ((*i).first) ;
+    }
+  }
+  {for (elementMap_t :: iterator i = _tetraMap.begin () ; i != _tetraMap.end () ; i ++)
+    if (Gitter :: InternalElement ()(*((tetra_GEO *)(*i).second)).accessPllX ().erasable ()) {
+      toDelete.push_back ((*i).first) ;
+    }
+  }
+  {for (elementMap_t :: iterator i = _periodic3Map.begin () ; i != _periodic3Map.end () ; i ++)
+    if (Gitter :: InternalElement ()(*((periodic3_GEO *)(*i).second)).accessPllX ().erasable ()) {
+      toDelete.push_back ((*i).first) ;
+    }
+  }
+  {for (elementMap_t :: iterator i = _periodic4Map.begin () ; i != _periodic4Map.end () ; i ++)
+    if (Gitter :: InternalElement ()(*((periodic4_GEO *)(*i).second)).accessPllX ().erasable ()) {
+      toDelete.push_back ((*i).first) ;
+    }
+  }
+  {for (vector < elementKey_t > :: iterator i = toDelete.begin () ; i != toDelete.end () ; i ++ )
+    removeElement (*i) ;
+  }
+
+  this->_initialized = true;
+  return ; 
+}
+
+// destructor calles finalize if not finalized yet 
+DuneParallelGridMover :: ~DuneParallelGridMover () 
+{
+  if(!_finalized) finalize();
+}   
+
+// overloaded, because here we use the new insertInternal method 
+void DuneParallelGridMover :: finalize ()
+{
+  //cout << "finalize on DuneParallelGridMover called! \n";
+  {for (elementMap_t :: iterator i = _hexaMap.begin () ; i != _hexaMap.end () ; _hexaMap.erase (i++))
+    myBuilder ()._hexaList.push_back ((hexa_GEO *)(*i).second) ;
+  }
+  {for (elementMap_t :: iterator i = _tetraMap.begin () ; i != _tetraMap.end () ; _tetraMap.erase (i++))
+    myBuilder ()._tetraList.push_back ((tetra_GEO *)(*i).second) ;
+  }
+  {for (elementMap_t :: iterator i = _periodic3Map.begin () ; i != _periodic3Map.end () ; _periodic3Map.erase (i++))
+    myBuilder ()._periodic3List.push_back ((periodic3_GEO *)(*i).second) ;
+  }
+  
+  {for (elementMap_t :: iterator i = _periodic4Map.begin () ; i != _periodic4Map.end () ; _periodic4Map.erase (i++))
+    myBuilder ()._periodic4List.push_back ((periodic4_GEO *)(*i).second) ;
+  }
+
+  {for (faceMap_t :: iterator i = _hbnd4Map.begin () ; i != _hbnd4Map.end () ; )
+    if (((hbndseg4_GEO *)(*i).second)->myhface4 (0)->ref == 1) {
+      delete (hbndseg4_GEO *)(*i).second ;
+      _hbnd4Map.erase (i++) ;
+    } else {
+      myBuilder ()._hbndseg4List.push_back ((hbndseg4_GEO *)(*i ++).second) ;
+    }
+  }
+  {for (faceMap_t :: iterator i = _hbnd3Map.begin () ; i != _hbnd3Map.end () ; )
+    if (((hbndseg3_GEO *)(*i).second)->myhface3 (0)->ref == 1) {
+      delete (hbndseg3_GEO *)(*i).second ;
+      _hbnd3Map.erase (i++) ;
+    } else {
+      myBuilder ()._hbndseg3List.push_back ((hbndseg3_GEO *)(*i ++).second) ;
+    }
+  }
+  {for (faceMap_t :: iterator i = _hbnd4Int.begin () ; i != _hbnd4Int.end () ; i ++) {
+    const pair < hface4_GEO *, int > & p = * (pair < hface4_GEO *, int > *)(*i).second ;
+    if (p.first->ref == 1) {
+      hbndseg4_GEO * hb4 = myBuilder ().insert_hbnd4 (p.first,p.second,Gitter :: hbndseg_STI :: closure) ;
+      myBuilder ()._hbndseg4List.push_back (hb4) ;
+    }
+    delete (pair < hface4_GEO *, int > *)(*i).second ;
+  }}
+
+  // here the internal boundary elements are created 
+  {for (hbndintMap_t :: iterator i = _hbnd3Int.begin () ; i != _hbnd3Int.end () ; i ++) {
+    const Hbnd3IntStorage & p = * (Hbnd3IntStorage *) (*i).second ;
+    if (p.first()->ref == 1) {
+      hbndseg3_GEO * hb3 = myBuilder().insert_hbnd3 ( p.first(),p.second(),
+                        Gitter :: hbndseg_STI :: closure , p.getPoint() );
+      myBuilder ()._hbndseg3List.push_back (hb3) ;
+    }
+    delete (pair < hface3_GEO *, int > *)(*i).second ;
+  }}
+  {for (faceMap_t :: iterator i = _face4Map.begin () ; i != _face4Map.end () ; )
+    if (!((hface4_GEO *)(*i).second)->ref) {
+      delete (hface4_GEO *)(*i).second ;
+      _face4Map.erase (i++) ;
+    } else {
+      //assert (((hface4_GEO *)(*i).second)->ref == 2) ;
+      myBuilder ()._hface4List.push_back ((hface4_GEO *)(*i ++).second ) ;
+    }
+  }
+  {for (faceMap_t :: iterator i = _face3Map.begin () ; i != _face3Map.end () ; ) {
+    if (!((hface3_GEO *)(*i).second)->ref) {
+      delete (hface3_GEO *)(*i).second ;
+      _face3Map.erase (i++) ;
+    } else {
+      //assert (((hface3_GEO *)(*i).second)->ref == 2) ;
+      myBuilder ()._hface3List.push_back ((hface3_GEO *)(*i ++).second ) ;
+    }
+  }}
+  {for (edgeMap_t :: iterator i = _edgeMap.begin () ; i != _edgeMap.end () ; )
+    if (!(*i).second->ref) {
+      delete (*i).second ;
+      _edgeMap.erase (i++) ;
+    } else {
+      assert ((*i).second->ref >= 1) ;
+      myBuilder ()._hedge1List.push_back ((*i ++).second) ;
+    }
+  }
+  {for (vertexMap_t :: iterator i = _vertexMap.begin () ; i != _vertexMap.end () ; )
+    if (!(*i).second->ref) {
+      delete (*i).second ;
+      _vertexMap.erase (i++) ;
+    } else {
+      assert ((*i).second->ref >= 2) ;
+      myBuilder ()._vertexList.push_back ((*i ++).second) ;
+    }
+  }
+  myBuilder ()._modified = true ;	// wichtig !
+  this->_finalized = true;
+  return ;
+}
+
+//*************************************************************************
+//  repartition method of class GitterDunePll 
+//*************************************************************************
+// method was overloaded because here we use our DuneParallelGridMover 
+void GitterDunePll :: repartitionMacroGrid (LoadBalancer :: DataBase & db) {
+
+  if (db.repartition (mpAccess (), LoadBalancer :: DataBase :: method (_ldbMethod))) {
+    
+    const long start = clock () ;
+    long lap1 (start), lap2 (start), lap3 (start), lap4 (start) ;
+    mpAccess ().removeLinkage () ;
+    mpAccess ().insertRequestSymetric (db.scan ()) ;
+    const int me = mpAccess ().myrank (), nl = mpAccess ().nlinks () ;
+    {
+      AccessIterator < helement_STI > :: Handle w (containerPll ()) ;
+      for (w.first () ; ! w.done () ; w.next ()) {
+      int to = db.getDestination (w.item ().accessPllX ().ldbVertexIndex ()) ;
+        if (me != to)
+          w.item ().accessPllX ().attach2 (mpAccess ().link (to)) ;
+      }
+    }
+    lap1 = clock () ;
+    vector < ObjectStream > osv (nl) ;
+    {
+      AccessIterator < vertex_STI > :: Handle w (containerPll ()) ;
+      for (w.first () ; ! w.done () ; w.next ()) w.item ().accessPllX ().packAll (osv) ;
+    }
+    {
+      AccessIterator < hedge_STI > :: Handle w (containerPll ()) ;
+      for (w.first () ; ! w.done () ; w.next ()) w.item ().accessPllX ().packAll (osv) ;
+    }
+    {
+      AccessIterator < hface_STI > :: Handle w (containerPll ()) ;
+      for (w.first () ; ! w.done () ; w.next ()) w.item ().accessPllX ().packAll (osv) ;
+    }
+    {
+      AccessIterator < helement_STI > :: Handle w (containerPll ()) ;
+      for (w.first () ; ! w.done () ; w.next ()) w.item ().accessPllX ().packAll (osv) ;
+    }
+    {
+      for (vector < ObjectStream > :: iterator i = osv.begin () ; i != osv.end () ; 
+        (*i++).writeObject (MacroGridMoverIF :: ENDMARKER)) ;
+    }
+    lap2 = clock () ;
+    osv = mpAccess ().exchange (osv) ;
+    lap3 = clock () ;
+    {
+      DuneParallelGridMover pgm (containerPll ()) ;
+      pgm.unpackAll (osv) ;
+    }
+    lap4 = clock () ;
+    if (MacroGridBuilder :: debugOption (20)) {
+      cout << "**INFO GitterDunePll :: repartitionMacroGrid () [ass|pck|exc|upk|all] " ;
+      cout << setw (5) << (float)(lap1 - start)/(float)(CLOCKS_PER_SEC) << " " ;
+      cout << setw (5) << (float)(lap2 - lap1)/(float)(CLOCKS_PER_SEC) << " " ;
+      cout << setw (5) << (float)(lap3 - lap2)/(float)(CLOCKS_PER_SEC) << " " ;
+      cout << setw (5) << (float)(lap4 - lap3)/(float)(CLOCKS_PER_SEC) << " " ;
+      cout << setw (5) << (float)(lap4 - start)/(float)(CLOCKS_PER_SEC) << " sec." << endl ;
+    }
+  }
+  return ;
+}
+void GitterDunePll :: duneRepartitionMacroGrid (LoadBalancer :: DataBase & db, GatherScatterType & gs) {
+
+  if (db.repartition (mpAccess (), LoadBalancer :: DataBase :: method (_ldbMethod))) {
+    const long start = clock () ;
+    long lap1 (start), lap2 (start), lap3 (start), lap4 (start) ;
+    mpAccess ().removeLinkage () ;
+    mpAccess ().insertRequestSymetric (db.scan ()) ;
+    const int me = mpAccess ().myrank (), nl = mpAccess ().nlinks () ;
+    {
+      AccessIterator < helement > :: Handle w (containerPll ()) ;
+      for (w.first () ; ! w.done () ; w.next ()) {
+      int to = db.getDestination (w.item ().accessPllX ().ldbVertexIndex ()) ;
+        if (me != to)
+          w.item ().accessPllX ().attach2 (mpAccess ().link (to)) ;
+      }
+    }
+    lap1 = clock () ;
+    vector < ObjectStream > osv (nl) ;
+    {
+      AccessIterator < vertex_STI > :: Handle w (containerPll ()) ;
+      for (w.first () ; ! w.done () ; w.next ()) w.item ().accessPllX ().packAll (osv) ;
+    }
+    {
+      AccessIterator < hedge_STI > :: Handle w (containerPll ()) ;
+      for (w.first () ; ! w.done () ; w.next ()) w.item ().accessPllX ().packAll (osv) ;
+    }
+    {
+      AccessIterator < hface_STI > :: Handle w (containerPll ()) ;
+      for (w.first () ; ! w.done () ; w.next ()) w.item ().accessPllX ().packAll (osv) ;
+    }
+    {
+      AccessIterator < helement_STI > :: Handle w (containerPll ()) ;
+      for (w.first () ; ! w.done () ; w.next ()) w.item ().accessPllX ().dunePackAll (osv,gs) ;
+    }
+    {
+      for (vector < ObjectStream > :: iterator i = osv.begin () ; i != osv.end () ; 
+        (*i++).writeObject (MacroGridMoverIF :: ENDMARKER)) ;
+    }
+    lap2 = clock () ;
+    osv = mpAccess ().exchange (osv) ;
+    lap3 = clock () ;
+    {
+      DuneParallelGridMover pgm (containerPll ()) ;
+      pgm.duneUnpackAll (osv,gs) ;
+    }
+    lap4 = clock () ;
+    if (MacroGridBuilder :: debugOption (20)) {
+      cout << "**INFO GitterDunePll :: repartitionMacroGrid () [ass|pck|exc|upk|all] " ;
+      cout << setw (5) << (float)(lap1 - start)/(float)(CLOCKS_PER_SEC) << " " ;
+      cout << setw (5) << (float)(lap2 - lap1)/(float)(CLOCKS_PER_SEC) << " " ;
+      cout << setw (5) << (float)(lap3 - lap2)/(float)(CLOCKS_PER_SEC) << " " ;
+      cout << setw (5) << (float)(lap4 - lap3)/(float)(CLOCKS_PER_SEC) << " " ;
+      cout << setw (5) << (float)(lap4 - start)/(float)(CLOCKS_PER_SEC) << " sec." << endl ;
+    }
+  }
+  return ;
+}
+
+#endif
-- 
GitLab