diff --git a/doc/geometries/ellipsoid.py b/doc/geometries/ellipsoid.py
new file mode 100644
index 0000000000000000000000000000000000000000..49823e9edf7c52a0480e4379fff582a328c68ea1
--- /dev/null
+++ b/doc/geometries/ellipsoid.py
@@ -0,0 +1,201 @@
+from sympy import *
+import numpy as np
+import collections
+
+x, y, z = symbols("x y z")
+a, b, c = symbols("a b c")
+
+# simplify entries of an array
+def simplify_all(A):
+  if isinstance(A, collections.Iterable):
+    return list(map(lambda a: simplify_all(a), A))
+  else:
+    return simplify(A)
+
+def add(A,B):
+  if isinstance(A, collections.Iterable):
+    return list(map(lambda a,b: add(a,b), A,B))
+  else:
+    return A + B
+
+def negate(A):
+  if isinstance(A, collections.Iterable):
+    return list(map(lambda a: negate(a), A))
+  else:
+    return -A
+
+
+X = [x,y,z]
+
+# normal vector
+div = sqrt(b**4*c**4*x**2 + a**4*c**4*y**2 + a**4*b**4**z**2)
+N = [b**2*c**2*x/div, a**2*c**2*y/div, a**2*b**2*z/div]
+
+print("N = ")
+print("return {")
+for i in range(3):
+  print("  ",ccode(N[i]),",")
+print("};")
+print("")
+
+# projection
+P = [[ (1 if i==j else 0) - N[i]*N[j] for j in range(3)] for i in range(3)]
+
+# parametrization
+nrm_X = sqrt(x**2 + y**2 + z**2)
+X0 = [x/nrm_X, y/nrm_X, z/nrm_X]
+u = atan(X0[1]/X0[0])
+v = acos(X0[2])
+X1 = [a*cos(u)*sin(v), b*sin(u)*sin(v), c*cos(v)]
+
+# jacobian of parametrization
+J = [[diff(X1[i],X[j]) for i in range(3)] for j in range(3)]
+print("J = ")
+print("return {")
+for i in range(3):
+  print("  {")
+  for j in range(3):
+    print("    ",ccode(simplify(J[i][j])),",")
+  print("  },")
+print("};")
+print("")
+
+# P(F)_j
+def project1(F):
+  return simplify_all([
+    np.sum([
+      P[i][j] * F[i]
+    for i in range(3)])
+    for j in range(3)])
+
+# P(F)_kl
+def project2(F):
+  return simplify_all([[
+    np.sum([np.sum([
+      P[i][k] * P[j][l] * F[i][j]
+    for j in range(3)]) for i in range(3)])
+    for l in range(3)]  for k in range(3)])
+
+# P(F)_lmn
+def project3(F):
+  return simplify_all([[[
+    np.sum([np.sum([np.sum([
+      P[i][l] * P[j][m] * P[k][n] * F[i][j][k]
+    for k in range(3)]) for j in range(3)]) for i in range(3)])
+    for n in range(3)]  for m in range(3)]  for l in range(3)])
+
+# P(F)_mnop
+def project4(F):
+  return simplify_all([[[[
+    np.sum([np.sum([np.sum([np.sum([
+      P[i][m] * P[j][n] * P[k][o] * P[l][p] * F[i][j][k][l]
+    for l in range(3)]) for k in range(3)]) for j in range(3)]) for i in range(3)])
+    for p in range(3)]  for o in range(3)]  for n in range(3)]  for m in range(3)])
+
+
+# Euclidean gradient
+def Grad0(f):
+  return simplify_all([
+    diff(f, X[i])
+  for i in range(3)])
+
+# surface gradient (covariant derivative of scalars)
+def grad0(f):
+  return project1(Grad0(f))
+
+def Grad1(T):
+  return simplify_all([[
+    diff(T[i], X[j])
+  for j in range(3)] for i in range(3)])
+
+# surface shape operator
+#B = negate(project2(Grad1(N)))
+
+# covariant derivative of vector field
+def grad1(T):
+  return simplify_all(add(project2(Grad1(T)), [[
+    np.sum([
+      B[i][j] * T[k] * N[k]
+    for k in range(3)])
+    for j in range(3)] for i in range(3)]))
+
+def Grad2(T):
+  return simplify_all([[[
+    diff(T[i][j], X[k])
+  for k in range(3)] for j in range(3)] for i in range(3)])
+
+def grad2(T):
+  return simplify_all([[[
+    np.sum([np.sum([np.sum([
+      P[L1][I1] * P[L2][I2] * P[L3][K] * diff(T[L1][L2], X[L3])
+    for L3 in range(3)]) for L2 in range(3)]) for L1 in range(3)]) +
+    np.sum([np.sum([
+      B[K][I1] * P[J2][I2] * T[L][J2] * N[L]
+    for J2 in range(3)]) for L in range(3)]) +
+    np.sum([np.sum([
+      B[K][I2] * P[J1][I1] * T[J1][L] * N[L]
+    for J1 in range(3)]) for L in range(3)])
+    for K in range(3)]  for I2 in range(3)] for I1 in range(3)])
+
+def Grad3(T):
+  return simplify_all([[[[
+    diff(T[i][j][k], X[l])
+  for l in range(3)] for k in range(3)] for j in range(3)] for i in range(3)])
+
+def grad3(T):
+  return simplify_all(add(project4(Grad3(T)), [[[[
+    np.sum([np.sum([np.sum([
+      B[K][I1] * P[J2][I2] * P[J3][I3] * T[L][J2][J3] * N[L]
+    for J2 in range(3)]) for J3 in range(3)]) for L in range(3)]) +
+    np.sum([np.sum([np.sum([
+      B[K][I2] * P[J1][I1] * P[J3][I3] * T[J1][L][J3] * N[L]
+    for J1 in range(3)]) for J3 in range(3)]) for L in range(3)]) +
+    np.sum([np.sum([np.sum([
+      B[K][I3] * P[J1][I1] * P[J2][I2] * T[J1][J2][L] * N[L]
+    for J1 in range(3)]) for J2 in range(3)]) for L in range(3)])
+  for K in range(3)] for I3 in range(3)] for I2 in range(3)] for I1 in range(3)]))
+
+
+
+# normal-rotation of scalar field
+def rot0(f):
+  return [diff(f*N[2],y) - diff(f*N[1],z),
+          diff(f*N[0],z) - diff(f*N[2],x),
+          diff(f*N[1],x) - diff(f*N[0],y)]
+
+def Div1(F):
+  return diff(F[0],x) + diff(F[1],y) + diff(F[2],z)
+
+def div1(F):
+  return Div1(project1(F))
+
+# def div2(t):
+#   F = Matrix([div1(t.row(0).T), div1(t.row(1).T), div1(t.row(2).T)])
+#   return P*F
+
+# div(T)_I1,I2
+def div3(T):
+  return simplify_all([[
+    np.sum([np.sum([np.sum([np.sum([np.sum([
+      P[L1][I1] * P[L2][I2] * P[L3][K] * P[L4][K] * diff(T[L1][L2][L3],X[L4])
+    for K in range(3)]) for L4 in range(3)]) for L3 in range(3)]) for L2 in range(3)]) for L1 in range(3)]) +
+    np.sum([np.sum([
+      B[I3][I1] * T[L][I2][I3] * N[L] +
+      B[I3][I2] * T[I1][L][I3] * N[L] +
+      B[I3][I3] * T[I1][I2][L] * N[L]
+    for I3 in range(3)]) for L in range(3)])
+    for I2 in range(3)]  for I1 in range(3)])
+
+#p0 = simplify_all( rot0(x*y*z) ) # => vector
+#print("p0 = ", p0)
+
+# p1 = simplify_all( grad1(p0) ) # => 2-tensor
+
+# print("p1 = ", p1)
+
+# f = simplify_all( add(negate(div3(grad2(p1))), p1) )
+# print("f = ", f)
+
+#F = simplify( -div2(grad1(p0)) + p0 )
+#print("F = ", F)
+#print("F*N = ", simplify(F.dot(N)))
\ No newline at end of file
diff --git a/dune.module b/dune.module
index 52cc00a1b1c1e2c01aa1f8339682bfccc0349065..9fafda61f4354d4fef1b5051512dc355e02fa375 100644
--- a/dune.module
+++ b/dune.module
@@ -7,5 +7,5 @@ Module: dune-curvedsurfacegrid
 Version: 0.1.0
 Maintainer: florian.stenger@tu-dresden.de
 #depending on
-Depends: dune-common dune-geometry dune-grid dune-localfunctions dune-curvilineargeometry
+Depends: dune-common dune-geometry dune-grid dune-localfunctions dune-curvedgeometry dune-functions
 Suggests: dune-alugrid dune-foamgrid
diff --git a/dune/curvedsurfacegrid/CMakeLists.txt b/dune/curvedsurfacegrid/CMakeLists.txt
index 215a05ee8864fe1edcf4d3741313009fa0ca8ce6..a48fbba883fce2dffd10dbc70dc3850330351d43 100644
--- a/dune/curvedsurfacegrid/CMakeLists.txt
+++ b/dune/curvedsurfacegrid/CMakeLists.txt
@@ -1,11 +1,9 @@
-add_subdirectory(surfacedistance)
-add_subdirectory(test)
 
-set(HEADERS
+install(FILES
   backuprestore.hh
   capabilities.hh
+  concepts.hh
   coordfunctionimplementations.hh
-  coordprovider.hh
   curvedsurfacegrid.hh
   datahandle.hh
   declaration.hh
@@ -20,7 +18,9 @@ set(HEADERS
   intersection.hh
   intersectioniterator.hh
   iterator.hh
-  )
-
-install(FILES ${HEADERS}
+  localgeometrywrapper.hh
   DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/curvedsurfacegrid)
+
+add_subdirectory(gridfunctions)
+add_subdirectory(surfacedistance)
+add_subdirectory(test)
diff --git a/dune/curvedsurfacegrid/backuprestore.hh b/dune/curvedsurfacegrid/backuprestore.hh
index 523a3d7911be275f60a89a9494466794c181cefb..2ec36e3f9184c06f0cad32f4e8d22324c01c875e 100644
--- a/dune/curvedsurfacegrid/backuprestore.hh
+++ b/dune/curvedsurfacegrid/backuprestore.hh
@@ -1,7 +1,7 @@
 // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
 // vi: set et ts=4 sw=2 sts=2:
-#ifndef DUNE_CRVSRF_BACKUPRESTORE_HH
-#define DUNE_CRVSRF_BACKUPRESTORE_HH
+#ifndef DUNE_CURVED_SURFACE_GRID_BACKUPRESTORE_HH
+#define DUNE_CURVED_SURFACE_GRID_BACKUPRESTORE_HH
 
 #include <dune/grid/common/backuprestore.hh>
 
@@ -9,84 +9,80 @@
 
 namespace Dune
 {
-
-  namespace crvsrf
+  namespace Curved
   {
 
     // BackupRestoreFacilities
     // -----------------------
 
-    template< class Grid, bool hasBackupRestoreFacilities = Capabilities::hasBackupRestoreFacilities< Grid > ::v >
+    template< class Grid, bool hasBackupRestoreFacilities = Capabilities::hasBackupRestoreFacilities<Grid> ::v >
     class BackupRestoreFacilities
     {};
 
     template< class Grid >
-    class BackupRestoreFacilities< Grid, true >
+    class BackupRestoreFacilities<Grid, true>
     {
-      typedef BackupRestoreFacilities< Grid, true > This;
+      using Self = BackupRestoreFacilities<Grid, true>;
 
     protected:
       BackupRestoreFacilities ()
       {}
 
     private:
-      BackupRestoreFacilities ( const This & );
-      This &operator= ( const This & );
+      BackupRestoreFacilities (const Self&);
+      Self& operator= (const Self&);
 
     protected:
-      const Grid &asImp () const
+      const Grid& asImp () const
       {
-        return static_cast< const Grid & >( *this );
+        return static_cast<const Grid&>(*this);
       }
 
-      Grid &asImp ()
+      Grid& asImp ()
       {
-        return static_cast< Grid & >( *this );
+        return static_cast<Grid&>(*this);
       }
     };
 
-  } // namespace crvsrf
+  } // namespace Curved
 
 
 
   // BackupRestoreFacility for CurvedSurfaceGrid
   // -------------------------------------------
 
-  template< class HostGrid, class CoordFunction, int order, bool geoCaching, class Allocator >
-  struct BackupRestoreFacility< CurvedSurfaceGrid< HostGrid, CoordFunction, order, geoCaching, Allocator > >
+  template< class GridFunction, int order >
+  struct BackupRestoreFacility<CurvedSurfaceGrid<GridFunction, order>>
   {
-    typedef CurvedSurfaceGrid< HostGrid, CoordFunction, order, geoCaching, Allocator > Grid;
-    typedef BackupRestoreFacility< HostGrid > HostBackupRestoreFacility;
+    using Grid = CurvedSurfaceGrid<GridFunction, order>;
+    using HostGrid = typename Grid::HostGrid;
+    using HostBackupRestoreFacility = BackupRestoreFacility<HostGrid>;
 
-    static void backup ( const Grid &grid, const std::string &filename )
+    static void backup (const Grid& grid, const std::string& filename)
     {
       // notice: We should also backup the coordinate function
-      HostBackupRestoreFacility::backup( grid.hostGrid(), filename );
+      HostBackupRestoreFacility::backup(grid.hostGrid(), filename);
     }
 
-    static void backup ( const Grid &grid, const std::ostream &stream )
+    static void backup (const Grid& grid, const std::ostream& stream)
     {
       // notice: We should also backup the coordinate function
-      HostBackupRestoreFacility::backup( grid.hostGrid(), stream );
+      HostBackupRestoreFacility::backup(grid.hostGrid(), stream);
     }
 
-    static Grid *restore ( const std::string &filename )
+    static Grid* restore (const std::string& filename)
     {
-      // notice: We should also restore the coordinate function
-      HostGrid *hostGrid = HostBackupRestoreFacility::restore( filename );
-      CoordFunction *coordFunction = new CoordFunction();
-      return new Grid( hostGrid, coordFunction );
+      assert(false && "Restore not yet implemented for CurvedSurfaceGrid");
+      return nullptr;
     }
 
-    static Grid *restore ( const std::istream &stream )
+    static Grid* restore (const std::istream& stream)
     {
-      // notice: We should also restore the coordinate function
-      HostGrid *hostGrid = HostBackupRestoreFacility::restore( stream );
-      CoordFunction *coordFunction = new CoordFunction();
-      return new Grid( hostGrid, coordFunction );
+      assert(false && "Restore not yet implemented for CurvedSurfaceGrid");
+      return nullptr;
     }
   };
 
 } // namespace Dune
 
-#endif // #ifndef DUNE_CRVSRF_BACKUPRESTORE_HH
+#endif // DUNE_CURVED_SURFACE_GRID_BACKUPRESTORE_HH
diff --git a/dune/curvedsurfacegrid/capabilities.hh b/dune/curvedsurfacegrid/capabilities.hh
index 60ffc200ebedd6999f3431914028169c58f38d6f..32c4a3343afe6337b31d21a3e45b35b58a0ddfdf 100644
--- a/dune/curvedsurfacegrid/capabilities.hh
+++ b/dune/curvedsurfacegrid/capabilities.hh
@@ -1,7 +1,7 @@
 // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
 // vi: set et ts=4 sw=2 sts=2:
-#ifndef DUNE_CRVSRF_CAPABILITIES_HH
-#define DUNE_CRVSRF_CAPABILITIES_HH
+#ifndef DUNE_CURVED_SURFACE_GRID_CAPABILITIES_HH
+#define DUNE_CURVED_SURFACE_GRID_CAPABILITIES_HH
 
 #include <cassert>
 
@@ -11,6 +11,7 @@
 #include <dune/grid/common/capabilities.hh>
 #include <dune/grid/geometrygrid/capabilities.hh>
 #include <dune/curvedsurfacegrid/declaration.hh>
+#include <dune/curvedsurfacegrid/gridfunctions/gridfunction.hh>
 
 namespace Dune
 {
@@ -24,61 +25,66 @@ namespace Dune
     // Capabilities from dune-grid
     // ---------------------------
 
-    template< class HostGrid, class CoordFunction, int order, bool geoCaching, class Allocator >
-    struct hasSingleGeometryType< CurvedSurfaceGrid< HostGrid, CoordFunction, order, geoCaching, Allocator > >
+    template< class GridFunction, int order >
+    struct hasSingleGeometryType< CurvedSurfaceGrid<GridFunction,order> >
     {
+      using HostGrid = GridOf_t<GridFunction>;
       static const bool v = hasSingleGeometryType< HostGrid > :: v;
       static const unsigned int topologyId = hasSingleGeometryType< HostGrid > :: topologyId;
     };
 
 
-    template< class HostGrid, class CoordFunction, int order, bool geoCaching, class Allocator, int codim >
-    struct hasEntity< CurvedSurfaceGrid< HostGrid, CoordFunction, order, geoCaching, Allocator >, codim >
+    template< class GridFunction, int order, int codim >
+    struct hasEntity< CurvedSurfaceGrid<GridFunction,order>, codim >
     {
       static const bool v = true;
     };
 
 
-    template< class HostGrid, class CoordFunction, int order, bool geoCaching, class Allocator, int codim >
-    struct hasEntityIterator< CurvedSurfaceGrid< HostGrid, CoordFunction, order, geoCaching, Allocator >, codim >
+    template< class GridFunction, int order, int codim >
+    struct hasEntityIterator< CurvedSurfaceGrid<GridFunction,order>, codim >
     {
       static const bool v = true;
     };
 
 
-    template< class HostGrid, class CoordFunction, int order, bool geoCaching, class Allocator, int codim >
-    struct canCommunicate< CurvedSurfaceGrid< HostGrid, CoordFunction, order, geoCaching, Allocator >, codim >
+    template< class GridFunction, int order, int codim >
+    struct canCommunicate< CurvedSurfaceGrid<GridFunction,order>, codim >
     {
+      using HostGrid = GridOf_t<GridFunction>;
       static const bool v = canCommunicate< HostGrid, codim >::v && hasEntity< HostGrid, codim >::v;
     };
 
 
-    template< class HostGrid, class CoordFunction, int order, bool geoCaching, class Allocator >
-    struct hasBackupRestoreFacilities< CurvedSurfaceGrid< HostGrid, CoordFunction, order, geoCaching, Allocator > >
+    template< class GridFunction, int order >
+    struct hasBackupRestoreFacilities< CurvedSurfaceGrid<GridFunction,order> >
     {
+      using HostGrid = GridOf_t<GridFunction>;
       static const bool v = hasBackupRestoreFacilities< HostGrid >::v;
     };
 
-    template< class HostGrid, class CoordFunction, int order, bool geoCaching, class Allocator >
-    struct isLevelwiseConforming< CurvedSurfaceGrid< HostGrid, CoordFunction, order, geoCaching, Allocator > >
+    template< class GridFunction, int order >
+    struct isLevelwiseConforming< CurvedSurfaceGrid<GridFunction,order> >
     {
+      using HostGrid = GridOf_t<GridFunction>;
       static const bool v = isLevelwiseConforming< HostGrid >::v;
     };
 
-    template< class HostGrid, class CoordFunction, int order, bool geoCaching, class Allocator >
-    struct isLeafwiseConforming< CurvedSurfaceGrid< HostGrid, CoordFunction, order, geoCaching, Allocator > >
+    template< class GridFunction, int order >
+    struct isLeafwiseConforming< CurvedSurfaceGrid<GridFunction,order> >
     {
+      using HostGrid = GridOf_t<GridFunction>;
       static const bool v = isLeafwiseConforming< HostGrid >::v;
     };
 
-    template< class HostGrid, class CoordFunction, int order, bool geoCaching, class Allocator >
-    struct threadSafe< CurvedSurfaceGrid< HostGrid, CoordFunction, order, geoCaching, Allocator > >
+    template< class GridFunction, int order >
+    struct threadSafe< CurvedSurfaceGrid<GridFunction,order> >
     {
       static const bool v = false;
     };
 
-    template< class HostGrid, class CoordFunction, int order, bool geoCaching, class Allocator >
-    struct viewThreadSafe< CurvedSurfaceGrid< HostGrid, CoordFunction, order, geoCaching, Allocator > >
+    template< class GridFunction, int order >
+    struct viewThreadSafe< CurvedSurfaceGrid<GridFunction,order> >
     {
       static const bool v = false;
     };
@@ -88,9 +94,10 @@ namespace Dune
     // hasHostEntity
     // -------------
 
-    template< class HostGrid, class CoordFunction, int order, bool geoCaching, class Allocator, int codim >
-    struct hasHostEntity< CurvedSurfaceGrid< HostGrid, CoordFunction, order, geoCaching, Allocator >, codim >
+    template< class GridFunction, int order, int codim >
+    struct hasHostEntity< CurvedSurfaceGrid<GridFunction,order>, codim >
     {
+      using HostGrid = GridOf_t<GridFunction>;
       static const bool v = hasEntity< HostGrid, codim >::v;
     };
 
@@ -98,4 +105,4 @@ namespace Dune
 
 } // namespace Dune
 
-#endif // #ifndef DUNE_CRVSRF_CAPABILITIES_HH
+#endif // DUNE_CURVED_SURFACE_GRID_CAPABILITIES_HH
diff --git a/dune/curvedsurfacegrid/concepts.hh b/dune/curvedsurfacegrid/concepts.hh
new file mode 100644
index 0000000000000000000000000000000000000000..2e1b9b7c59d0d61ed006e0f8f1c837247c4ae6fc
--- /dev/null
+++ b/dune/curvedsurfacegrid/concepts.hh
@@ -0,0 +1,56 @@
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+#ifndef DUNE_CURVED_SURFACE_GRID_CONCEPTS_HH
+#define DUNE_CURVED_SURFACE_GRID_CONCEPTS_HH
+
+#include <dune/common/concept.hh>
+#include <dune/curvedsurfacegrid/gridfunctions/gridentityset.hh>
+#include <dune/functions/common/functionconcepts.hh>
+
+namespace Dune {
+namespace Concept {
+
+template< class LocalContext >
+struct LocalFunction
+{
+  using LocalCoordinate = typename LocalContext::Geometry::LocalCoordinate;
+
+  template< class LF >
+  auto require(LF&& lf) -> decltype(
+    lf.bind(std::declval<LocalContext>()),
+    lf.unbind(),
+    lf.localContext(),
+    requireConcept<Dune::Functions::Concept::Callable<LocalCoordinate>>(lf),
+    requireConvertible<LocalContext>(lf.localContext())
+  );
+};
+
+template< class LF, class LocalContext >
+constexpr bool isLocalFunction()
+{ return models<Concept::LocalFunction<LocalContext>, LF>(); }
+
+
+template< class HostGrid >
+struct GridFunction
+{
+  using EntitySet = GridEntitySet<HostGrid,0>;
+  using LocalContext = typename EntitySet::Element;
+  using GlobalCoordinate = typename EntitySet::GlobalCoordinate;
+
+  template< class GF >
+  auto require(GF&& gf) -> decltype(
+    localFunction(gf),
+    gf.entitySet(),
+    requireConcept<Dune::Functions::Concept::Callable<GlobalCoordinate>>(gf),
+    requireConcept<LocalFunction<LocalContext>>(localFunction(gf))
+  );
+};
+
+template< class GF, class HostGrid >
+constexpr bool isGridFunction()
+{ return models<Concept::GridFunction<HostGrid>, GF>(); }
+
+} // end namespace Concept
+} // end namespace Dune 
+
+#endif // DUNE_CURVED_SURFACE_GRID_CONCEPTS_HH
\ No newline at end of file
diff --git a/dune/curvedsurfacegrid/coordfunctionimplementations.hh b/dune/curvedsurfacegrid/coordfunctionimplementations.hh
index 8071917340635a6e9bd5352495e07d7ef0fb1550..c54a6929a54abc248abb9371a2ead5466fe9694a 100644
--- a/dune/curvedsurfacegrid/coordfunctionimplementations.hh
+++ b/dune/curvedsurfacegrid/coordfunctionimplementations.hh
@@ -1,13 +1,12 @@
 // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
 // vi: set et ts=4 sw=2 sts=2:
-#ifndef DUNE_CRVSRF_COORDFUNCTIONIMPLEMENTATIONS_HH
-#define DUNE_CRVSRF_COORDFUNCTIONIMPLEMENTATIONS_HH
+#ifndef DUNE_CURVED_SURFACE_GRID_COORDFUNCTIONIMPLEMENTATIONS_HH
+#define DUNE_CURVED_SURFACE_GRID_COORDFUNCTIONIMPLEMENTATIONS_HH
 
 #include <dune/curvedsurfacegrid/surfacedistance/surfacedistance.hh>
 #include <dune/curvedsurfacegrid/surfacedistance/vertexmap.hh>
 #include <dune/curvedsurfacegrid/surfacedistance/vtureader.hh>
 #include <dune/grid/geometrygrid/coordfunction.hh>
-#include <cfloat>
 
 #define COLLECTOR_BENCHMARK 0
 
@@ -30,11 +29,11 @@ namespace Dune
 
   //convertDuneGridToCrvsrfMesh
   template<class GridPtr>
-  crvsrf::Mesh *convertDuneGridToCrvsrfMesh(GridPtr &grid){
+  Curved::Mesh *convertDuneGridToCrvsrfMesh(GridPtr &grid){
     auto gridView = grid->leafGridView();
 
     //determine coordinate-extrema
-    crvsrf::Vertex minc(DBL_MAX, DBL_MAX, DBL_MAX), maxc(-DBL_MAX, -DBL_MAX, -DBL_MAX);
+    Curved::Vertex minc(DBL_MAX, DBL_MAX, DBL_MAX), maxc(-DBL_MAX, -DBL_MAX, -DBL_MAX);
     for(const auto &vertexEntity : vertices(gridView)){
       const auto &vertex = vertexEntity.geometry().corner(0);
       for(int i = 0; i < grid->dimensionworld; ++i){
@@ -43,19 +42,19 @@ namespace Dune
       }
     }
 
-    crvsrf::Mesh *surface_mesh = new crvsrf::Mesh(grid->dimension, grid->dimensionworld);
-    crvsrf::VertexMap<int> vmap(minc, maxc, grid->dimensionworld);
+    Curved::Mesh *surface_mesh = new Curved::Mesh(grid->dimension, grid->dimensionworld);
+    Curved::VertexMap<int> vmap(minc, maxc, grid->dimensionworld);
 
     //build mesh
     int next_index = 0;
     for(const auto &element : elements(gridView)){
       if(element.geometry().corners() != 3){
-        crvsrf::error("Element is not a triangle in convertDuneGridToCrvsrfMesh.");
+        Curved::error("Element is not a triangle in convertDuneGridToCrvsrfMesh.");
       }
       int32_t el[grid->dimension + 1];
       for(int i = 0; i <= grid->dimension; ++i){
         auto coords = element.geometry().corner(i);
-        crvsrf::Vertex v(coords[0], coords[1], coords[2]);
+        Curved::Vertex v(coords[0], coords[1], coords[2]);
         if(!vmap.find_3d(v, el[i])){
           surface_mesh->add_vertex(v);
           el[i] = next_index;
@@ -93,7 +92,7 @@ namespace Dune
         input *= radius_ / input.two_norm();
       }
       double run_time = dbl_time() - start_time;
-      std::cout << "csphere time: " << crvsrf::ft(run_time, 11, 9)
+      std::cout << "csphere time: " << Curved::ft(run_time, 11, 9)
                       << ", count: " << inputs.size() << std::endl;
     }
     #endif
@@ -135,7 +134,7 @@ namespace Dune
         for(int i = 0; i < 3; ++i) input[i] = center_[i] + direction[i] * factor;
       }
       double run_time = dbl_time() - start_time;
-      std::cout << "sphere time: " << crvsrf::ft(run_time, 11, 9)
+      std::cout << "sphere time: " << Curved::ft(run_time, 11, 9)
                      << ", count: " << inputs.size() << std::endl;
     }
     #endif
@@ -162,29 +161,29 @@ namespace Dune
     SurfaceDistanceCoordFunction(const GridPtr &gridPtr,
                       double expansion_width=-1.0, bool no_scaling=false) : cache(nullptr){
       if(gridPtr->dimension != 2 || gridPtr->dimensionworld != 3){
-        crvsrf::error("SurfaceDistanceCoordFunction needs a triangle-surface-mesh!");
+        Curved::error("SurfaceDistanceCoordFunction needs a triangle-surface-mesh!");
       }
       surface_mesh = convertDuneGridToCrvsrfMesh(gridPtr);
-      backgrid = new crvsrf::BackGrid(*surface_mesh, expansion_width, no_scaling);
+      backgrid = new Curved::BackGrid(*surface_mesh, expansion_width, no_scaling);
       if(cached){
-        crvsrf::Vertex c_begin, c_end;
+        Curved::Vertex c_begin, c_end;
         surface_mesh->determine_coordinate_extrema(c_begin, c_end);
-        crvsrf::Vertex c_expansion = (c_end - c_begin) * 0.1;
-        cache = new crvsrf::VertexMap<crvsrf::Vertex>(c_begin - c_expansion, c_end + c_expansion, 3);
+        Curved::Vertex c_expansion = (c_end - c_begin) * 0.1;
+        cache = new Curved::VertexMap<Curved::Vertex>(c_begin - c_expansion, c_end + c_expansion, 3);
       }
     }
 
     //constructor using vtu-reader to read "file"
     SurfaceDistanceCoordFunction(const char *file,
                  double expansion_width=-1.0, bool no_scaling=false) : cache(nullptr){
-      surface_mesh = new crvsrf::Mesh(2, 3);
+      surface_mesh = new Curved::Mesh(2, 3);
       read_vtu_file(file, *surface_mesh);
-      backgrid = new crvsrf::BackGrid(*surface_mesh, expansion_width, no_scaling);
+      backgrid = new Curved::BackGrid(*surface_mesh, expansion_width, no_scaling);
       if(cached){
-        crvsrf::Vertex c_begin, c_end;
+        Curved::Vertex c_begin, c_end;
         surface_mesh->determine_coordinate_extrema(c_begin, c_end);
-        crvsrf::Vertex c_expansion = (c_end - c_begin) * 0.1;
-        cache = new crvsrf::VertexMap<crvsrf::Vertex>(c_begin - c_expansion, c_end + c_expansion, 3);
+        Curved::Vertex c_expansion = (c_end - c_begin) * 0.1;
+        cache = new Curved::VertexMap<Curved::Vertex>(c_begin - c_expansion, c_end + c_expansion, 3);
       }
     }
 
@@ -202,18 +201,18 @@ namespace Dune
     }
 
     //resetCache
-    void resetCache(crvsrf::Vertex begin = crvsrf::Vertex(),
-                     crvsrf::Vertex end = crvsrf::Vertex(),
+    void resetCache(Curved::Vertex begin = Curved::Vertex(),
+                     Curved::Vertex end = Curved::Vertex(),
                      double expansion_factor = 0.1){
       if(cached){
         delete cache;
         if(begin.is_origin() && end.is_origin()){
           surface_mesh->determine_coordinate_extrema(begin, end);
         }
-        crvsrf::Vertex c_expansion = (end - begin) * expansion_factor;
-        cache = new crvsrf::VertexMap<crvsrf::Vertex>(begin - c_expansion, end + c_expansion, 3);
+        Curved::Vertex c_expansion = (end - begin) * expansion_factor;
+        cache = new Curved::VertexMap<Curved::Vertex>(begin - c_expansion, end + c_expansion, 3);
       }else{
-        crvsrf::error("Cannot reset cache in uncached SurfaceDistanceCoordFunction!");
+        Curved::error("Cannot reset cache in uncached SurfaceDistanceCoordFunction!");
       }
     }
 
@@ -227,13 +226,25 @@ namespace Dune
 
     #if COLLECTOR_BENCHMARK != 0
     void collectorBenchmark(bool fresh_cache){
+      //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+      //! $debug: output vertex-list
+      /*std::ofstream out("vertex_list.txt", std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
+      int v_cnt = inputs.size();
+      out.write(reinterpret_cast<char*>(&v_cnt), 4);
+      for(auto &input : inputs){
+        out.write(reinterpret_cast<char*>(&input[0]), 8);
+        out.write(reinterpret_cast<char*>(&input[1]), 8);
+        out.write(reinterpret_cast<char*>(&input[2]), 8);
+      }
+      out.close();*/
+      //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
       if(cached){
         if(fresh_cache) cache->clear();
         int uncached_cnt = 0;
         double start_time = dbl_time();
         for(auto &input : inputs){
-          crvsrf::Vertex hit_vertex;
-          crvsrf::Vertex v(input[0], input[1], input[2]);
+          Curved::Vertex hit_vertex;
+          Curved::Vertex v(input[0], input[1], input[2]);
           if(!cache->find_3d(v, hit_vertex)){
             backgrid->distance_to_surface_3d(v, hit_vertex);
             cache->insert(v, hit_vertex);
@@ -241,17 +252,17 @@ namespace Dune
           }
         }
         double run_time = dbl_time() - start_time;
-        std::cout << "surfdist time: " << crvsrf::ft(run_time, 11, 9) << ", count: "<< inputs.size()
+        std::cout << "surfdist time: " << Curved::ft(run_time, 11, 9) << ", count: "<< inputs.size()
                                                      << ", uncached: " << uncached_cnt << std::endl;
       }else{ //uncached
         double start_time = dbl_time();
         for(auto &input : inputs){
-          crvsrf::Vertex hit_vertex;
-          crvsrf::Vertex v(input[0], input[1], input[2]);
+          Curved::Vertex hit_vertex;
+          Curved::Vertex v(input[0], input[1], input[2]);
           backgrid->distance_to_surface_3d(v, hit_vertex);
         }
         double run_time = dbl_time() - start_time;
-        std::cout << "surfdist time: " << crvsrf::ft(run_time, 11, 9)
+        std::cout << "surfdist time: " << Curved::ft(run_time, 11, 9)
                           << ", count: "<< inputs.size() << std::endl;
       }
     }
@@ -262,16 +273,16 @@ namespace Dune
       if(cached){
         cache->debug_output_statistics();
       }else{
-        crvsrf::error("Cannot output vertexmap-statistics in "
+        Curved::error("Cannot output vertexmap-statistics in "
                       "uncached SurfaceDistanceCoordFunction!");
       }
     }
     #endif
 
   private:
-    crvsrf::Mesh *surface_mesh;
-    crvsrf::BackGrid *backgrid;
-    crvsrf::VertexMap<crvsrf::Vertex> *cache;
+    Curved::Mesh *surface_mesh;
+    Curved::BackGrid *backgrid;
+    Curved::VertexMap<Curved::Vertex> *cache;
     #if COLLECTOR_BENCHMARK != 0
       mutable std::vector<FieldVector<double, 3> > inputs;
     #endif
@@ -284,8 +295,8 @@ namespace Dune
     #if COLLECTOR_BENCHMARK != 0
       inputs.push_back(x);
     #endif
-    crvsrf::Vertex hit_vertex;
-    crvsrf::Vertex v(x[0], x[1], x[2]);
+    Curved::Vertex hit_vertex;
+    Curved::Vertex v(x[0], x[1], x[2]);
     if(!cache->find_3d(v, hit_vertex)){
       backgrid->distance_to_surface_3d(v, hit_vertex);
       cache->insert(v, hit_vertex);
@@ -301,12 +312,12 @@ namespace Dune
     #if COLLECTOR_BENCHMARK != 0
       inputs.push_back(x);
     #endif
-    crvsrf::Vertex hit_vertex;
-    crvsrf::Vertex v(x[0], x[1], x[2]);
+    Curved::Vertex hit_vertex;
+    Curved::Vertex v(x[0], x[1], x[2]);
     backgrid->distance_to_surface_3d(v, hit_vertex);
     return {hit_vertex[0], hit_vertex[1], hit_vertex[2]};
   }
 
 } // namespace Dune
 
-#endif // #ifndef DUNE_CRVSRF_COORDFUNCTIONIMPLEMENTATIONS_HH
+#endif // DUNE_CURVED_SURFACE_GRID_COORDFUNCTIONIMPLEMENTATIONS_HH
diff --git a/dune/curvedsurfacegrid/coordprovider.hh b/dune/curvedsurfacegrid/coordprovider.hh
deleted file mode 100644
index fd1ec1575c54a55cc4db55ff07f6be5e98c4dd97..0000000000000000000000000000000000000000
--- a/dune/curvedsurfacegrid/coordprovider.hh
+++ /dev/null
@@ -1,356 +0,0 @@
-// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
-// vi: set et ts=4 sw=2 sts=2:
-#ifndef DUNE_CRVSRF_COORDPROVIDER_HH
-#define DUNE_CRVSRF_COORDPROVIDER_HH
-
-#include <array>
-
-namespace Dune
-{
-
-  namespace crvsrf
-  {
-
-    template< class Coordinate>
-    Coordinate edgeCenter(Coordinate gc1, const Coordinate &gc2)
-    {
-      for(typename Coordinate::size_type i = 0, end = gc1.size(); i < end; ++i)
-      {
-        gc1[i] = (gc1[i] + gc2[i]) / 2.0;
-      }
-      return gc1;
-    }
-
-    template< class Coordinate>
-    Coordinate edgeVertex(Coordinate gc1, const Coordinate &gc2, double factor)
-    {
-      for(typename Coordinate::size_type i = 0, end = gc1.size(); i < end; ++i)
-      {
-        gc1[i] = gc1[i] + (gc2[i] - gc1[i]) * factor;
-      }
-      return gc1;
-    }
-
-    template< class Coordinate>
-    Coordinate faceVertex(Coordinate gc1, const Coordinate &gc2, const Coordinate &gc3,
-                                            double coeff1, double coeff2, double coeff3)
-    {
-      for(typename Coordinate::size_type i = 0, end = gc1.size(); i < end; ++i)
-      {
-        gc1[i] = coeff1 * gc1[i] + coeff2 * gc2[i] + coeff3 * gc3[i];
-      }
-      return gc1;
-    }
-
-
-
-    // InterpolatoryVerticesGenerator
-    // ------------------------------
-
-    template< class Coordinate, int mydim, int order >
-    struct InterpolatoryVerticesGenerator;
-
-    //Vertex
-    template< class Coordinate, int order >
-    struct InterpolatoryVerticesGenerator< Coordinate, 0, order >
-    {
-      static void generate(const std::array<Coordinate, 1> &corners, std::vector<Coordinate> &vertices)
-      {
-        vertices.resize(1);
-        vertices[0] = corners[0];
-      }
-    };
-
-    //Edge
-    template< class Coordinate, int order >
-    struct InterpolatoryVerticesGenerator< Coordinate, 1, order >
-    {
-      static void generate(const std::array<Coordinate, 2> &corners, std::vector<Coordinate> &vertices)
-      {
-        vertices.resize(order + 1);
-        vertices[0] = corners[0];
-        for(int i = 1; i < order; ++i)
-        {
-          vertices[i] = edgeVertex(corners[0], corners[1], (double)i / order);
-        }
-        vertices[order] = corners[1];
-      }
-    };
-
-    //Triangle (order 1)
-    template< class Coordinate >
-    struct InterpolatoryVerticesGenerator< Coordinate, 2, 1 >
-    {
-      static void generate(const std::array<Coordinate, 4> &corners, std::vector<Coordinate> &vertices)
-      {
-        vertices.resize(3);
-        vertices[0] = corners[0];
-        vertices[1] = corners[1];
-        vertices[2] = corners[2];
-      }
-    };
-
-    //Triangle (order 2)
-    template< class Coordinate >
-    struct InterpolatoryVerticesGenerator< Coordinate, 2, 2 >
-    {
-      static void generate(const std::array<Coordinate, 4> &corners, std::vector<Coordinate> &vertices)
-      {
-        vertices.resize(6);
-        vertices[0] = corners[0];
-        vertices[1] = edgeCenter(corners[0], corners[1]);
-        vertices[2] = corners[1];
-        vertices[3] = edgeCenter(corners[0], corners[2]);
-        vertices[4] = edgeCenter(corners[1], corners[2]);
-        vertices[5] = corners[2];
-      }
-    };
-
-    //Triangle (order 3)
-    template< class Coordinate >
-    struct InterpolatoryVerticesGenerator< Coordinate, 2, 3 >
-    {
-      static void generate(const std::array<Coordinate, 4> &corners, std::vector<Coordinate> &vertices)
-      {
-        static const double cf1 = 1.0 / 3.0;
-        static const double cf2 = 2.0 / 3.0;
-        vertices.resize(10);
-        vertices[0] = corners[0];
-        vertices[1] = edgeVertex(corners[0], corners[1], cf1);
-        vertices[2] = edgeVertex(corners[0], corners[1], cf2);
-        vertices[3] = corners[1];
-        vertices[4] = edgeVertex(corners[0], corners[2], cf1);
-        vertices[5] = faceVertex(corners[0], corners[1], corners[2], cf1, cf1, cf1);
-        vertices[6] = edgeVertex(corners[1], corners[2], cf1);
-        vertices[7] = edgeVertex(corners[0], corners[2], cf2);
-        vertices[8] = edgeVertex(corners[1], corners[2], cf2);
-        vertices[9] = corners[2];
-      }
-    };
-
-    //Triangle (order 4)
-    template< class Coordinate >
-    struct InterpolatoryVerticesGenerator< Coordinate, 2, 4 >
-    {
-      static void generate(const std::array<Coordinate, 4> &corners, std::vector<Coordinate> &vertices)
-      {
-        static const double cf1 = 1.0 / 4.0;
-        static const double cf2 = 2.0 / 4.0;
-        static const double cf3 = 3.0 / 4.0;
-        vertices.resize(15);
-        vertices[0] = corners[0];
-        vertices[1] = edgeVertex(corners[0], corners[1], cf1);
-        vertices[2] = edgeCenter(corners[0], corners[1]);
-        vertices[3] = edgeVertex(corners[0], corners[1], cf3);
-        vertices[4] = corners[1];
-        vertices[5] = edgeVertex(corners[0], corners[2], cf1);
-        vertices[6] = faceVertex(corners[0], corners[1], corners[2], cf2, cf1, cf1);
-        vertices[7] = faceVertex(corners[0], corners[1], corners[2], cf1, cf2, cf1);
-        vertices[8] = edgeVertex(corners[1], corners[2], cf1);
-        vertices[9] = edgeCenter(corners[0], corners[2]);
-        vertices[10] = faceVertex(corners[0], corners[1], corners[2], cf1, cf1, cf2);
-        vertices[11] = edgeCenter(corners[1], corners[2]);
-        vertices[12] = edgeVertex(corners[0], corners[2], cf3);
-        vertices[13] = edgeVertex(corners[1], corners[2], cf3);
-        vertices[14] = corners[2];
-      }
-    };
-
-    //Triangle (order 5)
-    template< class Coordinate >
-    struct InterpolatoryVerticesGenerator< Coordinate, 2, 5 >
-    {
-      static void generate(const std::array<Coordinate, 4> &corners, std::vector<Coordinate> &vertices)
-      {
-        static const double cf1 = 1.0 / 5.0;
-        static const double cf2 = 2.0 / 5.0;
-        static const double cf3 = 3.0 / 5.0;
-        static const double cf4 = 4.0 / 5.0;
-        vertices.resize(21);
-        vertices[0] = corners[0];
-        vertices[1] = edgeVertex(corners[0], corners[1], cf1);
-        vertices[2] = edgeVertex(corners[0], corners[1], cf2);
-        vertices[3] = edgeVertex(corners[0], corners[1], cf3);
-        vertices[4] = edgeVertex(corners[0], corners[1], cf4);
-        vertices[5] = corners[1];
-        vertices[6] = edgeVertex(corners[0], corners[2], cf1);
-        vertices[7] = faceVertex(corners[0], corners[1], corners[2], cf3, cf1, cf1);
-        vertices[8] = faceVertex(corners[0], corners[1], corners[2], cf2, cf2, cf1);
-        vertices[9] = faceVertex(corners[0], corners[1], corners[2], cf1, cf3, cf1);
-        vertices[10] = edgeVertex(corners[1], corners[2], cf1);
-        vertices[11] = edgeVertex(corners[0], corners[2], cf2);
-        vertices[12] = faceVertex(corners[0], corners[1], corners[2], cf2, cf1, cf2);
-        vertices[13] = faceVertex(corners[0], corners[1], corners[2], cf1, cf2, cf2);
-        vertices[14] = edgeVertex(corners[1], corners[2], cf2);
-        vertices[15] = edgeVertex(corners[0], corners[2], cf3);
-        vertices[16] = faceVertex(corners[0], corners[1], corners[2], cf1, cf1, cf3);
-        vertices[17] = edgeVertex(corners[1], corners[2], cf3);
-        vertices[18] = edgeVertex(corners[0], corners[2], cf4);
-        vertices[19] = edgeVertex(corners[1], corners[2], cf4);
-        vertices[20] = corners[2];
-      }
-    };
-
-
-
-    // CoordProvider (adapted CoordVector from GeometryGrid)
-    // -----------------------------------------------------
-
-    template< int mydim, class Grid, bool fake >
-    class CoordProvider;
-
-
-    //CoordProvider (real)
-    template< int mydim, class Grid >
-    class CoordProvider< mydim, Grid, false >
-    {
-      typedef typename std::remove_const< Grid >::type::Traits Traits;
-
-      typedef typename Traits::ctype ctype;
-
-      static const int dimension = Traits::dimension;
-      static const int mydimension = mydim;
-      static const int codimension = dimension - mydimension;
-      static const int dimensionworld = Traits::dimensionworld;
-
-      typedef FieldVector< ctype, dimensionworld > Coordinate;
-
-      typedef typename Traits::HostGrid HostGrid;
-      typedef typename Traits::CoordFunction CoordFunction;
-
-      typedef typename HostGrid::template Codim< codimension >::Entity HostEntity;
-
-    public:
-      CoordProvider ( const HostEntity &hostEntity,
-                    const CoordFunction &coordFunction )
-        : coordFunction_(coordFunction),
-          hostEntity_(hostEntity)
-      {}
-
-      void calculate ( std::vector< Coordinate > &vertices ) const
-      {
-        const std::size_t numCorners = hostEntity_.geometry().corners();
-        std::array<Coordinate, (1 << mydim)> corners;
-        for( std::size_t i = 0; i < numCorners; ++i )
-          corners[i] = hostEntity_.geometry().corner(i);
-        InterpolatoryVerticesGenerator<Coordinate, mydim, Grid::order>::generate(corners, vertices);
-        for(auto &v : vertices) coordFunction_.evaluate(v, v);
-      }
-
-    private:
-      const CoordFunction &coordFunction_;
-      const HostEntity &hostEntity_;
-    };
-
-    //CoordProvider (fake)
-    template< int mydim, class Grid >
-    class CoordProvider< mydim, Grid, true >
-    {
-      typedef typename std::remove_const< Grid > :: type :: Traits Traits;
-
-      typedef typename Traits::ctype ctype;
-
-      static const int dimension = Traits::dimension;
-      static const int mydimension = mydim;
-      static const int codimension = dimension - mydimension;
-      static const int dimensionworld = Traits::dimensionworld;
-
-      typedef FieldVector< ctype, dimensionworld > Coordinate;
-
-      typedef typename Traits::HostGrid HostGrid;
-      typedef typename Traits::CoordFunction CoordFunction;
-
-      typedef typename HostGrid::template Codim< 0 >::Entity HostElement;
-
-    public:
-      CoordProvider ( const HostElement &hostElement,
-                    const unsigned int subEntity,
-                    const CoordFunction &coordFunction )
-        : coordFunction_(coordFunction),
-          hostElement_(hostElement),
-          subEntity_( subEntity )
-      {}
-
-      void calculate ( std::vector< Coordinate > &vertices ) const
-      {
-        const GeometryType type = hostElement_.geometry().type();
-        auto refElement = referenceElement< ctype, dimension >( type );
-        const std::size_t numCorners = refElement.size( subEntity_, codimension, dimension );
-        std::array<Coordinate, (1 << mydim)> corners;
-        for( std::size_t i = 0; i < numCorners; ++i )
-        {
-          const std::size_t j = refElement.subEntity( subEntity_, codimension, i, dimension );
-          corners[i] = hostElement_.geometry().corner(j);
-        }
-        InterpolatoryVerticesGenerator<Coordinate, mydim, Grid::order>::generate(corners, vertices);
-        for(auto &v : vertices) coordFunction_.evaluate(v, v);
-      }
-
-    private:
-      const CoordFunction &coordFunction_;
-      const HostElement &hostElement_;
-      const unsigned int subEntity_;
-    };
-
-
-
-    // IntersectionCoordProvider
-    // -----------------------
-
-    template< class Grid >
-    class IntersectionCoordProvider
-    {
-      typedef typename std::remove_const< Grid >::type::Traits Traits;
-
-      typedef typename Traits::ctype ctype;
-
-      static const int dimension = Traits::dimension;
-      static const int codimension = 1;
-      static const int mydimension = dimension-codimension;
-      static const int dimensionworld = Traits::dimensionworld;
-
-      typedef FieldVector< ctype, dimensionworld > Coordinate;
-
-      typedef typename Traits::HostGrid HostGrid;
-      typedef typename Traits::CoordFunction CoordFunction;
-
-      typedef typename Traits::template Codim< 0 >::GeometryImpl ElementGeometryImpl;
-      typedef typename Traits::template Codim< codimension >::LocalGeometry HostLocalGeometry;
-
-    public:
-      IntersectionCoordProvider ( const ElementGeometryImpl &elementGeometry,
-                                  const HostLocalGeometry &hostLocalGeometry,
-                                  const CoordFunction &coordFunction )
-        : coordFunction_(coordFunction),
-          elementGeometry_( elementGeometry ),
-          hostLocalGeometry_( hostLocalGeometry )
-      {}
-
-      void calculate ( std::vector< Coordinate > &vertices ) const
-      {
-        const std::size_t numCorners = hostLocalGeometry_.corners();
-        std::array<Coordinate, (1 << mydimension)> corners;
-        // $flo: coordFunction is applied here which is in contrast to GeomentryGrid's behaviour!
-        for( std::size_t i = 0; i < numCorners; ++i )
-          corners[ i ] = elementGeometry_.global( hostLocalGeometry_.corner( i ) );
-        InterpolatoryVerticesGenerator<Coordinate, mydimension, Grid::order>::generate(corners, vertices);
-        for(auto &v : vertices) coordFunction_.evaluate(v, v);
-      }
-
-      template< unsigned int numCorners >
-      void calculate ( Coordinate (&corners)[ numCorners ] ) const
-      {
-        assert( numCorners == hostLocalGeometry_.corners() );
-      }
-
-    private:
-      const CoordFunction &coordFunction_;
-      const ElementGeometryImpl &elementGeometry_;
-      HostLocalGeometry hostLocalGeometry_;
-    };
-
-  } // namespace crvsrf
-
-} // namespace Dune
-
-#endif // #ifndef DUNE_CRVSRF_COORDPROVIDER_HH
diff --git a/dune/curvedsurfacegrid/datahandle.hh b/dune/curvedsurfacegrid/datahandle.hh
index f5d22966c88585a93bfccc4ad02c0d5032c8283e..6d4e1c361b03e55e3180dbbe750f06fae33a05a0 100644
--- a/dune/curvedsurfacegrid/datahandle.hh
+++ b/dune/curvedsurfacegrid/datahandle.hh
@@ -1,7 +1,7 @@
 // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
 // vi: set et ts=4 sw=2 sts=2:
-#ifndef DUNE_CRVSRF_DATAHANDLE_HH
-#define DUNE_CRVSRF_DATAHANDLE_HH
+#ifndef DUNE_CURVED_SURFACE_GRID_DATAHANDLE_HH
+#define DUNE_CURVED_SURFACE_GRID_DATAHANDLE_HH
 
 #include <dune/common/typetraits.hh>
 
@@ -11,8 +11,7 @@
 
 namespace Dune
 {
-
-  namespace crvsrf
+  namespace Curved
   {
 
     // CommDataHandle
@@ -20,69 +19,69 @@ namespace Dune
 
     template< class Grid, class WrappedHandle >
     class CommDataHandle
-      : public CommDataHandleIF< CommDataHandle< Grid, WrappedHandle >, typename WrappedHandle::DataType >
+        : public CommDataHandleIF<CommDataHandle<Grid, WrappedHandle>, typename WrappedHandle::DataType>
     {
-      typedef typename std::remove_const< Grid >::type::Traits Traits;
+      using Traits = typename std::remove_const_t<Grid>::Traits;
 
     public:
-      CommDataHandle ( const Grid &grid, WrappedHandle &handle )
-        : grid_( grid ),
-          wrappedHandle_( handle )
+      CommDataHandle (const Grid& grid, WrappedHandle& handle)
+        : grid_(grid)
+        , wrappedHandle_(handle)
       {}
 
-      bool contains ( int dim, int codim ) const
+      bool contains (int dim, int codim) const
       {
-        const bool contains = wrappedHandle_.contains( dim, codim );
-        if( contains )
-          assertHostEntity( dim, codim );
+        const bool contains = wrappedHandle_.contains(dim, codim);
+        if (contains)
+          assertHostEntity(dim, codim);
         return contains;
       }
 
-      bool fixedSize ( int dim, int codim ) const
+      bool fixedSize (int dim, int codim) const
       {
-        return wrappedHandle_.fixedSize( dim, codim );
+        return wrappedHandle_.fixedSize(dim, codim);
       }
 
       template< class HostEntity >
-      size_t size ( const HostEntity &hostEntity ) const
+      std::size_t size (const HostEntity& hostEntity) const
       {
-        typedef typename Grid::Traits::template Codim< HostEntity::codimension >::Entity Entity;
-        typedef typename Grid::Traits::template Codim< HostEntity::codimension >::EntityImpl EntityImpl;
-        Entity entity( EntityImpl( grid_, hostEntity ) );
-        return wrappedHandle_.size( entity );
+        using Entity = typename Grid::Traits::template Codim<HostEntity::codimension>::Entity;
+        using EntityImpl = typename Grid::Traits::template Codim<HostEntity::codimension>::EntityImpl;
+        Entity entity(EntityImpl(grid_.gridFunction(), hostEntity));
+        return wrappedHandle_.size(entity);
       }
 
       template< class MessageBuffer, class HostEntity >
-      void gather ( MessageBuffer &buffer, const HostEntity &hostEntity ) const
+      void gather (MessageBuffer& buffer, const HostEntity& hostEntity) const
       {
-        typedef typename Grid::Traits::template Codim< HostEntity::codimension >::Entity Entity;
-        typedef typename Grid::Traits::template Codim< HostEntity::codimension >::EntityImpl EntityImpl;
-        Entity entity( EntityImpl( grid_, hostEntity ) );
-        wrappedHandle_.gather( buffer, entity );
+        using Entity = typename Grid::Traits::template Codim<HostEntity::codimension>::Entity;
+        using EntityImpl = typename Grid::Traits::template Codim<HostEntity::codimension>::EntityImpl;
+        Entity entity(EntityImpl(grid_.gridFunction(), hostEntity));
+        wrappedHandle_.gather(buffer, entity);
       }
 
       template< class MessageBuffer, class HostEntity >
-      void scatter ( MessageBuffer &buffer, const HostEntity &hostEntity, size_t size )
+      void scatter (MessageBuffer& buffer, const HostEntity& hostEntity, std::size_t size)
       {
-        typedef typename Grid::Traits::template Codim< HostEntity::codimension >::Entity Entity;
-        typedef typename Grid::Traits::template Codim< HostEntity::codimension >::EntityImpl EntityImpl;
-        Entity entity( EntityImpl( grid_, hostEntity ) );
-        wrappedHandle_.scatter( buffer, entity, size );
+        using Entity = typename Grid::Traits::template Codim< HostEntity::codimension >::Entity;
+        using EntityImpl = typename Grid::Traits::template Codim< HostEntity::codimension >::EntityImpl;
+        Entity entity(EntityImpl(grid_.gridFunction(), hostEntity));
+        wrappedHandle_.scatter(buffer, entity, size);
       }
 
     private:
-      static void assertHostEntity ( int dim, int codim )
+      static void assertHostEntity (int dim, int codim)
       {
-        if( !Capabilities::CodimCache< Grid >::hasHostEntity( codim ) )
-          DUNE_THROW( NotImplemented, "Host grid has no entities for codimension " << codim << "." );
+        if (!Capabilities::CodimCache<Grid>::hasHostEntity(codim))
+          DUNE_THROW(NotImplemented, "Host grid has no entities for codimension " << codim << ".");
       }
 
-      const Grid &grid_;
-      WrappedHandle &wrappedHandle_;
+    private:
+      const Grid& grid_;
+      WrappedHandle& wrappedHandle_;
     };
 
-  } // namespace crvsrf
-
+  } // namespace Curved
 } // namespace Dune
 
-#endif // #ifndef DUNE_CRVSRF_DATAHANDLE_HH
+#endif // DUNE_CURVED_SURFACE_GRID_DATAHANDLE_HH
diff --git a/dune/curvedsurfacegrid/declaration.hh b/dune/curvedsurfacegrid/declaration.hh
index 5ab0ddf5419199f47d1f56e770561cabdf11713a..292d384b0b6002237f9df6f4e9b8e6392c87ad65 100644
--- a/dune/curvedsurfacegrid/declaration.hh
+++ b/dune/curvedsurfacegrid/declaration.hh
@@ -1,14 +1,14 @@
 // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
 // vi: set et ts=4 sw=2 sts=2:
-#ifndef DUNE_CRVSRF_DECLARATION_HH
-#define DUNE_CRVSRF_DECLARATION_HH
+#ifndef DUNE_CURVED_SURFACE_GRID_DECLARATION_HH
+#define DUNE_CURVED_SURFACE_GRID_DECLARATION_HH
 
 namespace Dune
 {
 
-  template< class HostGrid, class CoordFunction, int interpolatoryOrder, bool geoCaching, class Allocator >
+  template< class GridFunction, int order >
   class CurvedSurfaceGrid;
 
 } // namespace Dune
 
-#endif // #ifndef DUNE_CRVSRF_DECLARATION_HH
+#endif // DUNE_CURVED_SURFACE_GRID_DECLARATION_HH
diff --git a/dune/curvedsurfacegrid/entity.hh b/dune/curvedsurfacegrid/entity.hh
index 24c0d7b47f4d2b212c157c33a6315bcd8d7079f9..d5179b9a1f5e5c16c68102338bdd9b5125598502 100644
--- a/dune/curvedsurfacegrid/entity.hh
+++ b/dune/curvedsurfacegrid/entity.hh
@@ -1,21 +1,17 @@
 // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
 // vi: set et ts=4 sw=2 sts=2:
-#ifndef DUNE_CRVSRF_ENTITY_HH
-#define DUNE_CRVSRF_ENTITY_HH
+#ifndef DUNE_CURVED_SURFACE_GRID_ENTITY_HH
+#define DUNE_CURVED_SURFACE_GRID_ENTITY_HH
 
+#include <dune/common/std/optional.hh>
 #include <dune/geometry/referenceelements.hh>
 
 #include <dune/grid/common/grid.hh>
-
-#include <dune/curvedsurfacegrid/capabilities.hh>
-#include <dune/curvedsurfacegrid/coordprovider.hh>
-
-#define GEO_CACHE_BENCHMARK 0
+#include <dune/curvedsurfacegrid/geometry.hh>
 
 namespace Dune
 {
-
-  namespace crvsrf
+  namespace Curved
   {
 
     // Internal Forward Declarations
@@ -23,20 +19,17 @@ namespace Dune
 
     /** \class EntityBase
      *  \brief actual implementation of the entity
-     *  \ingroup crvsrf
+     *  \ingroup CurvedGeo
      *
      *  \tparam  codim  codimension of the entity
      *  \tparam  Grid   CurvedSurfaceGrid, this entity belongs to
-     *  \tparam  fake   \b true, if the host grid does not provide this entity
-     *                  (do not specify, the default value is already the
-     *                  intended use)
      */
-    template< int codim, class Grid, bool fake = !(Capabilities::hasHostEntity< Grid, codim >::v) >
+    template< int codim, class Grid >
     class EntityBase;
 
     /** \class Entity
      *  \brief DUNE-conform implementation of the entity
-     *  \ingroup crvsrf
+     *  \ingroup CurvedGeo
      *
      *  This class merely changes the template parameters of the entity to make
      *  DUNE happy. The actual implementation of the entity can be found in
@@ -61,21 +54,10 @@ namespace Dune
     class IntersectionIterator;
 
 
-
-    // EntityBase (real)
-    // -----------------
-
-    /** \copydoc EntityBase
-     *
-     *  This specialization implements the case, where the host grid provides
-     *  the entity for this codimension, i.e., \em fake = \b false.
-     *
-     *  \nosubgrouping
-     */
-    template< int codim, class Grid >
-    class EntityBase< codim, Grid, false >
+    template< int codim, class G >
+    class EntityBase
     {
-      typedef typename std::remove_const< Grid >::type::Traits Traits;
+      using Traits = typename std::remove_const_t<G>::Traits;
 
     public:
       /** \name Attributes
@@ -90,130 +72,67 @@ namespace Dune
       //! dimension of the world
       static const int dimensionworld = Traits::dimensionworld;
 
-      //! \b true, if the entity is faked, i.e., if there is no corresponding host entity
-      static const bool fake = false;
       /** \} */
 
       /** \name Types Required by DUNE
        *  \{ */
 
       //! coordinate type of the grid
-      typedef typename Traits::ctype ctype;
+      using ctype = typename Traits::ctype;
 
-      //! type of corresponding geometry
-      typedef typename Traits::template Codim< codimension >::Geometry Geometry;
       /** \} */
 
-    private:
-      typedef typename Traits::HostGrid HostGrid;
-      typedef typename Traits::CoordFunction CoordFunction;
-
     public:
       /** \name Host Types
        *  \{ */
 
-      //! type of corresponding host entity
-      typedef typename HostGrid::template Codim< codimension >::Entity HostEntity;
-
       //! type of corresponding entity seed
-      typedef typename Traits::template Codim< codimension >::EntitySeed EntitySeed;
+      using EntitySeed = typename Traits::template Codim<codimension>::EntitySeed;
 
-      //! type of host elements, i.e., of host entities of codimension 0
-      typedef typename HostGrid::template Codim< 0 >::Entity HostElement;
       /** \} */
 
-      typedef typename Traits::template Codim< codim >::GeometryImpl GeometryImpl;
-
-    private:
-      typedef typename HostGrid::template Codim< codimension >::Geometry HostGeometry;
-
-      typedef crvsrf::CoordProvider< mydimension, Grid, fake > CoordProvider;
-
     public:
-      /** \name Construction, Initialization and Destruction
-       *  \{ */
-
-      EntityBase ()
-        : hostEntity_()
-        , grid_( nullptr )
-        , geo_( nullptr )
-      {}
-
-      EntityBase ( const Grid &grid, const EntitySeed &seed )
-        : hostEntity_( grid.hostGrid().entity( seed.impl().hostEntitySeed() ) )
-        , grid_( &grid )
-        , geo_( nullptr )
-      {}
+      using Grid = typename Traits::Grid;
+      using GridFunction = typename Traits::GridFunction;
 
-      EntityBase ( const Grid &grid, const HostElement &hostElement, int i )
-        : hostEntity_( hostElement.template subEntity<codim>(i) )
-        , grid_( &grid )
-        , geo_( nullptr )
-      {}
+      //! type of the host grid
+      using HostGrid = typename Traits::HostGrid;
 
+      //! type of corresponding host entity
+      using HostEntity = typename HostGrid::template Codim<codim>::Entity;
 
-      EntityBase ( const GeometryImpl &geo, const HostEntity &hostEntity )
-        : hostEntity_( hostEntity )
-        , grid_( &geo.grid() )
-        , geo_( new GeometryImpl( geo ) )
-      {}
+      //! type of host elements, i.e., of host entities of codimension 0
+      using HostElement = typename HostGrid::template Codim<0>::Entity;
 
-      EntityBase ( const GeometryImpl &geo, HostEntity&& hostEntity )
-        : hostEntity_( std::move( hostEntity ) )
-        , grid_( &geo.grid() )
-        , geo_( new GeometryImpl( geo ) )
-      {}
+    public:
+      EntityBase () = default;
 
-      EntityBase ( const Grid &grid, const HostEntity& hostEntity )
-        : hostEntity_( hostEntity )
-        , grid_( &grid )
-        , geo_( nullptr )
+      // Construct the entity from an entity seed
+      EntityBase (const Grid& grid, const EntitySeed& seed)
+        : hostEntity_(grid.hostGrid().entity(seed.impl().hostEntitySeed()))
+        , gridFunction_(&grid.gridFunction())
       {}
 
-      EntityBase ( const Grid &grid, HostEntity&& hostEntity )
-        : hostEntity_( std::move( hostEntity ) )
-        , grid_( &grid )
-        , geo_( nullptr )
+      // construct the entity from a subentity of a host-entity
+      EntityBase (const GridFunction& gridFunction, const HostElement& hostElement, int i)
+        : hostEntity_(hostElement.template subEntity<codim>(i))
+        , gridFunction_(&gridFunction)
       {}
 
-
-      EntityBase ( const EntityBase &other )
-        : hostEntity_( other.hostEntity_ )
-        , grid_( other.grid_ )
-        , geo_( other.geo_? new GeometryImpl( *other.geo_ ) : nullptr )
+      // construct the entity from a host-entity
+      EntityBase (const GridFunction& gridFunction, const HostEntity& hostEntity)
+        : hostEntity_(hostEntity)
+        , gridFunction_(&gridFunction)
       {}
 
-      EntityBase ( EntityBase&& other )
-        : hostEntity_( std::move( other.hostEntity_ ) )
-        , grid_( std::move( other.grid_ ) )
-        , geo_( std::move( other.geo_ ) )
+      // construct the entity from a host-entity
+      EntityBase (const GridFunction& gridFunction, HostEntity&& hostEntity)
+        : hostEntity_(std::move(hostEntity))
+        , gridFunction_(&gridFunction)
       {}
 
-      ~EntityBase ()
-      {
-        if(geo_ && !grid_->useGeometryCaching) delete geo_;
-      }
-
-      /** \} */
-
-      const EntityBase &operator= ( const EntityBase &other )
-      {
-        hostEntity_ = other.hostEntity_;
-        grid_ = other.grid_;
-        geo_ = other.geo_? new GeometryImpl( *other.geo_ ) : nullptr;
-        return *this;
-      }
-
-      const EntityBase &operator= ( EntityBase&& other )
-      {
-        hostEntity_ = std::move( other.hostEntity_ );
-        grid_ = std::move( other.grid_ );
-        geo_ = std::move( other.geo_ );
-        return *this;
-      }
-
-      /** \brief compare two entities */
-      bool equals ( const EntityBase &other) const
+      //! compare two entities
+      bool equals (const EntityBase& other) const
       {
         return hostEntity_ == other.hostEntity_;
       }
@@ -222,8 +141,8 @@ namespace Dune
       /** \name Methods Shared by Entities of All Codimensions
        *  \{ */
 
-      /** \brief obtain the name of the corresponding reference element
-       *
+      //! obtain the name of the corresponding reference element
+      /**
        *  This type can be used to access the DUNE reference element.
        */
       GeometryType type () const
@@ -231,736 +150,294 @@ namespace Dune
         return hostEntity().type();
       }
 
-      /** \brief obtain the level of this entity */
+      //! obtain the level of this entity
       int level () const
       {
         return hostEntity().level();
       }
 
-      /** \brief obtain the partition type of this entity */
+      //! obtain the partition type of this entity
       PartitionType partitionType () const
       {
         return hostEntity().partitionType();
       }
 
-      /** obtain the geometry of this entity
-       *
-       *  Each DUNE entity encapsulates a geometry object, representing the map
-       *  from the reference element to world coordinates. Wrapping the geometry
-       *  is the main objective of the CurvedSurfaceGrid.
-       *
-       *  The CurvedSurfaceGrid provides geometries of order 1-5, obtained by
-       *  interpolation of its corners \f$y_i\f$. The corners are calculated
-       *  from the corners \f$x_i\f$ of the host geometry through the
-       *  CurvedSurfaceGrid's coordinate function \f$c\f$, i.e.,
-       *  \f$y_i = c( x_i )\f$. Interpolatory vertices are added for orders 2-5
-       *  which are also transformed by \f$c\f$.
-       *
-       *  \returns a const reference to the geometry
-       */
-      Geometry geometry () const
+      //! obtain number of sub-entities of the current entity
+      unsigned int subEntities (unsigned int cc) const
       {
-        if( !geo_ )
-        {
-          Grid &grid_ref = *grid_;
-          if(grid_->useGeometryCaching)
-          {
-            auto &cached_geo =
-                    std::get<codim>(grid_ref.geometryCache_)[id(grid_ref.hostGrid().localIdSet())];
-            if(cached_geo)
-            {
-              #if GEO_CACHE_BENCHMARK != 0
-                std::cout << "u: " << grid_ref.geo_uncached
-                          << ", e: " << ++grid_ref.geo_cached_external
-                          << ", i: " << grid_ref.geo_cached_internal << std::endl;
-              #endif
-              geo_ = cached_geo;
-            }else{
-              #if GEO_CACHE_BENCHMARK != 0
-                std::cout << "u: " << ++grid_ref.geo_uncached
-                          << ", e: " << grid_ref.geo_cached_external
-                          << ", i: " << grid_ref.geo_cached_internal << std::endl;
-              #endif
-              CoordProvider coords( hostEntity(), grid().coordFunction() );
-              geo_ = new GeometryImpl( grid(), type(), coords );
-              cached_geo = geo_;
-            }
-          }else{
-            #if GEO_CACHE_BENCHMARK != 0
-              std::cout << "u: " << ++grid_ref.geo_uncached
-                        << ", e: " << grid_ref.geo_cached_external
-                        << ", i: " << grid_ref.geo_cached_internal << std::endl;
-            #endif
-            CoordProvider coords( hostEntity(), grid().coordFunction() );
-            geo_ = new GeometryImpl( grid(), type(), coords );
-          }
-        }
-        #if GEO_CACHE_BENCHMARK != 0
-          else{
-            std::cout << "u: " << grid_->geo_uncached
-                      << ", e: " << grid_->geo_cached_external
-                      << ", i: " << ++grid_->geo_cached_internal << std::endl;
-          }
-        #endif
-        return Geometry( *geo_ );
+        return hostEntity().subEntities(cc);
       }
 
-      unsigned int subEntities ( unsigned int cc ) const
+      //! return EntitySeed of host grid entity
+      EntitySeed seed () const
       {
-        return hostEntity().subEntities( cc );
+        return typename EntitySeed::Implementation(hostEntity().seed());
       }
 
-      /** \brief return EntitySeed of host grid entity */
-      EntitySeed seed () const { return typename EntitySeed::Implementation( hostEntity().seed() ); }
-      /** \} */
-
 
       /** \name Methods Supporting the Grid Implementation
        *  \{ */
 
-      const Grid &grid () const { assert( grid_ ); return *grid_; }
-
-      const HostEntity &hostEntity () const
+      const GridFunction& gridFunction () const
       {
-        return hostEntity_;
+        return *gridFunction_;
       }
 
-      /** \brief initiliaze an entity
-       *
-       *  \param[in]  hostEntity  reference to the host entity
-       *
-       */
-      void initialize ( const HostEntity &hostEntity ) { hostEntity_ = hostEntity; }
-
-      /** \brief obtain the entity's index from a host IndexSet
-       *
-       *  \internal This method is provided by the entity, because its
-       *  implementation is different for fake and non-fake entities.
-       *
-       *  \param[in]  indexSet  host IndexSet to use
-       */
-      template< class HostIndexSet >
-      typename HostIndexSet::IndexType
-      index ( const HostIndexSet &indexSet ) const
-      {
-        return indexSet.template index< codimension >( hostEntity() );
-      }
-
-      /** \brief obtain the index of a subentity from a host IndexSet
-       *
-       *  \internal This method is provided by the entity, because its
-       *  implementation is different for fake and non-fake entities.
-       *
-       *  \param[in]  indexSet  host IndexSet to use
-       *  \param[in]  i         number of the subentity
-       *  \param[in]  cd        codimension of the subentity
-       */
-      template< class HostIndexSet >
-      typename HostIndexSet::IndexType
-      subIndex ( const HostIndexSet &indexSet, int i, unsigned int cd ) const
+      //! return the wrapped host-entity
+      const HostEntity& hostEntity () const
       {
-        return indexSet.subIndex( hostEntity(), i, cd );
-      }
-
-      /** \brief check whether the entity is contained in a host index set
-       *
-       *  \internal This method is provided by the entity, because its
-       *  implementation is different for fake and non-fake entities.
-       *
-       *  \param  indexSet  host IndexSet to use
-       */
-      template< class HostIndexSet >
-      bool isContained ( const HostIndexSet &indexSet ) const
-      {
-        return indexSet.contains( hostEntity() );
+        return hostEntity_;
       }
 
-      /** \brief obtain the entity's id from a host IdSet
-       *
-       *  \internal This method is provided by the entity, because its
-       *  implementation is different for fake and non-fake entities.
-       *
-       *  \param  idSet  host IdSet to use
-       */
-      template< class HostIdSet >
-      typename HostIdSet::IdType id ( const HostIdSet &idSet ) const
-      {
-        return idSet.template id< codimension >( hostEntity() );
-      }
       /** \} */
 
     private:
       HostEntity hostEntity_;
-      const Grid *grid_;
-      mutable GeometryImpl *geo_;
+      const GridFunction* gridFunction_ = nullptr;
     };
 
 
 
-    // EntityBase (fake)
-    // -----------------
-
-    /** \copydoc EntityBase
-     *
-     *  This specialization implements the case, where the host grid does not
-     *  provide the entity for this codimension, i.e., \em fake = \b true.
-     *
-     *  \nosubgrouping
-     */
-    template< int codim, class Grid >
-    class EntityBase< codim, Grid, true >
+    template< int codim, class G >
+    class EntityBaseGeometry
+        : public EntityBase<codim, G>
     {
-      typedef typename std::remove_const< Grid >::type::Traits Traits;
-
-    public:
-      /** \name Attributes
-       *  \{ */
-
-      //! codimensioon of the entity
-      static const int codimension = codim;
-      //! dimension of the grid
-      static const int dimension = Traits::dimension;
-      //! dimension of the entity
-      static const int mydimension = dimension - codimension;
-      //! dimension of the world
-      static const int dimensionworld = Traits::dimensionworld;
-
-      //! \b true, if the entity is faked, i.e., if there is no corresponding host entity
-      static const bool fake = true;
-      /** \} */
-
-      /** \name Types Required by DUNE
-       *  \{ */
-
-      //! coordinate type of the grid
-      typedef typename Traits::ctype ctype;
-
-      //! type of corresponding geometry
-      typedef typename Traits::template Codim< codimension >::Geometry Geometry;
-      /** \} */
-
-    private:
-      typedef typename Traits::HostGrid HostGrid;
-      typedef typename Traits::CoordFunction CoordFunction;
-
-    public:
-      /** \name Host Types
-       *  \{ */
-
-      //! type of corresponding host entity
-      typedef typename HostGrid::template Codim< codimension >::Entity HostEntity;
-
-      //! type of corresponding entity seed
-      typedef typename Traits::template Codim< codimension >::EntitySeed EntitySeed;
+      using Super = EntityBase<codim, G>;
+      using Traits = typename std::remove_const_t<G>::Traits;
 
       //! type of host elements, i.e., of host entities of codimension 0
-      typedef typename HostGrid::template Codim< 0 >::Entity HostElement;
-      /** \} */
-
-      typedef typename Traits::template Codim< codimension >::GeometryImpl GeometryImpl;
-
-    private:
-      typedef typename HostGrid::template Codim< 0 >::Geometry HostGeometry;
-
-      typedef crvsrf::CoordProvider< mydimension, Grid, fake > CoordProvider;
+      using HostElement = typename Traits::HostGrid::template Codim<0>::Entity;
+      using GridFunction = typename Super::GridFunction;
 
     public:
-      /** \name Construction, Initialization and Destruction
-       *  \{ */
-
-      EntityBase ()
-        : hostElement_()
-        , subEntity_(-1)
-        , grid_(nullptr)
-        , geo_( nullptr )
-      {}
-
-      EntityBase(const Grid& grid, const HostElement& hostElement, unsigned int subEntity)
-        : hostElement_(hostElement)
-        , subEntity_(subEntity)
-        , grid_(&grid)
-        , geo_( nullptr )
-      {}
-
-      EntityBase ( const Grid &grid, const EntitySeed &seed )
-        : hostElement_( grid.hostGrid().entity( seed.impl().hostElementSeed() ) )
-        , subEntity_( seed.impl().subEntity() )
-        , grid_( &grid )
-        , geo_( nullptr )
-      {}
+      //! type of corresponding geometry
+      using Geometry = typename Traits::template Codim<codim>::Geometry;
+      using ctype = typename Geometry::ctype;
 
-      EntityBase ( const EntityBase &other )
-        : hostElement_( other.hostElement_ )
-        , subEntity_( other.subEntity_ )
-        , grid_( other.grid_ )
-        , geo_( other.geo_? new GeometryImpl( *other.geo_ ) : nullptr )
-      {}
+    public:
+      using Super::Super;
 
-      EntityBase ( EntityBase &&other )
-        : hostElement_( std::move( other.hostElement_ ) )
-        , subEntity_( std::move( other.subEntity_ ) )
-        , grid_( std::move ( other.grid_ ) )
-        , geo_( std::move( other.geo_ ) )
+      // construct the entity from a subentity of a host-entity
+      EntityBaseGeometry (const GridFunction& gridFunction, const HostElement& hostElement, int i)
+        : Super(gridFunction, hostElement, i)
+        , hostElement_(hostElement)
+        , subEntity_(i)
       {}
 
-      /*
-       * This method is required by constructors in the `Entity` class
-       * below, however it cannot do anything useful for fake
-       * entities.
-       */
-      EntityBase(const Grid& grid, const HostEntity& hostEntity)
-      {
-        DUNE_THROW(Dune::Exception, "CurvedSurfaceGrid: Cannot create fake entity of codim " << codimension << " from real host entity.");
-      }
-
-      ~EntityBase ()
+      //! obtain the geometry of this entity
+      Geometry geometry () const
       {
-        if(geo_ && !grid_->useGeometryCaching) delete geo_;
-      }
+        if (!geo_) {
+          auto localFct = localFunction(Super::gridFunction());
+          if (hostElement_) {
+            localFct.bind(*hostElement_);
 
-      /** \} */
+            auto refElem = referenceElement<ctype, Super::dimension>(hostElement_->type());
+            auto localGeometry = refElem.template geometry<codim>(subEntity_);
+            geo_ = std::make_shared<GeometryImpl>(Super::type(), localFct, localGeometry);
+          }
+          else {
+            DUNE_THROW(Dune::NotImplemented, "Geometry of entities of codim!=0 not implemented");
+          }
+        }
 
-      const EntityBase &operator= ( const EntityBase &other )
-      {
-        hostElement_ = other.hostElement_;
-        subEntity_ = other.subEntity_;
-        grid_ = other.grid_;
-        geo_ = other.geo_? new GeometryImpl( *other.geo_ ) : nullptr;
-        return *this;
+        return Geometry(*geo_);
       }
 
-      const EntityBase &operator= ( EntityBase&& other )
-      {
-        hostElement_ = std::move( other.hostElement_ );
-        subEntity_ = std::move( other.subEntity_ );
-        grid_ = std::move( other.grid_ );
-        geo_ = std::move( other.geo_ );
-        return *this;
-      }
+    private:
+      Std::optional<HostElement> hostElement_;
+      int subEntity_ = -1;
 
-      /** \brief compare two entities */
-      bool equals ( const EntityBase &other) const
-      {
-        const bool thisEnd = (subEntity() < 0);
-        const bool otherEnd = (other.subEntity() < 0);
-        if( thisEnd || otherEnd )
-          return thisEnd && otherEnd;
-
-        const int lvl = level();
-        if( lvl != other.level() )
-          return false;
-
-        const typename Traits::HostGrid::Traits::LevelIndexSet &indexSet
-          = grid().hostGrid().levelIndexSet( lvl );
-
-        const HostElement &thisElement = hostElement();
-        assert( indexSet.contains( thisElement ) );
-        const HostElement &otherElement = other.hostElement();
-        assert( indexSet.contains( otherElement ) );
-
-        const int thisIndex = indexSet.subIndex( thisElement, subEntity(), codimension );
-        const int otherIndex = indexSet.subIndex( otherElement, other.subEntity(), codimension );
-        return (thisIndex == otherIndex);
-      }
+      using GeometryImpl = typename Traits::template Codim<codim>::GeometryImpl;
+      mutable std::shared_ptr<GeometryImpl> geo_;
+    };
 
-      /** \name Methods Shared by Entities of All Codimensions
-       *  \{ */
 
-      /** \brief obtain the name of the corresponding reference element
-       *
-       *  This type can be used to access the DUNE reference element.
-       */
-      GeometryType type () const
-      {
-        auto refElement = referenceElement< ctype, dimension >( hostElement().type() );
-        return refElement.type( subEntity_, codimension );
-      }
+    template< class G >
+    class EntityBaseGeometry<0, G>
+        : public EntityBase<0, G>
+    {
+      using Super = EntityBase<0, G>;
+      using Traits = typename std::remove_const_t<G>::Traits;
 
-      /** \brief obtain the level of this entity */
-      int level () const
-      {
-        return hostElement().level();
-      }
+    public:
+      //! type of corresponding geometry
+      using Geometry = typename Traits::template Codim<0>::Geometry;
 
-      /** \brief obtain the partition type of this entity */
-      PartitionType partitionType () const
-      {
-        auto refElement = referenceElement< ctype, dimension >( hostElement().type() );
-
-        PartitionType type = vertexPartitionType( refElement, 0 );
-        if( (type != BorderEntity) && (type != FrontEntity) )
-          return type;
-
-        const int numVertices = refElement.size( subEntity_, codimension, dimension );
-        for( int i = 1; i < numVertices; ++i )
-        {
-          PartitionType vtxType = vertexPartitionType( refElement, i );
-          if( (vtxType != BorderEntity) && (vtxType != FrontEntity) )
-            return vtxType;
-          if( type != vtxType )
-            return OverlapEntity;
-        }
-        assert( (type == BorderEntity) || (type == FrontEntity) );
-        return type;
-      }
+      //! type of corresponding local geometry
+      using LocalGeometry = typename Traits::template Codim<0>::LocalGeometry;
 
-      /** obtain the geometry of this entity
-       *
+    public:
+      using Super::Super;
+
+      //! obtain the geometry of this entity
+      /**
        *  Each DUNE entity encapsulates a geometry object, representing the map
        *  from the reference element to world coordinates. Wrapping the geometry
        *  is the main objective of the CurvedSurfaceGrid.
        *
-       *  The CurvedSurfaceGrid provides geometries of order 1-5, obtained by
-       *  interpolation of its corners \f$y_i\f$. The corners are calculated
-       *  from the corners \f$x_i\f$ of the host geometry through the
-       *  CurvedSurfaceGrid's coordinate function \f$c\f$, i.e.,
-       *  \f$y_i = c( x_i )\f$. Interpolatory vertices are added for orders 2-5
-       *  which are also transformed by \f$c\f$.
+       *  The CurvedSurfaceGrid provides geometries by parametrization with local basis
+       *  functions, using the CurvedGeometry.
        *
-       *  \returns a geometry object
+       *  \returns a new curvedgeometry object
        */
       Geometry geometry () const
       {
-        if( !geo_ )
-        {
-          Grid &grid_ref = *grid_;
-          if(grid_->useGeometryCaching)
-          {
-            auto &cached_geo =
-                    std::get<codim>(grid_ref.geometryCache_)[id(grid_ref.hostGrid().localIdSet())];
-            if(cached_geo)
-            {
-              #if GEO_CACHE_BENCHMARK != 0
-                std::cout << "u: " << grid_ref.geo_uncached
-                          << ", e: " << ++grid_ref.geo_cached_external
-                          << ", i: " << grid_ref.geo_cached_internal << std::endl;
-              #endif
-              geo_ = cached_geo;
-            }else{
-              #if GEO_CACHE_BENCHMARK != 0
-                std::cout << "u: " << ++grid_ref.geo_uncached
-                          << ", e: " << grid_ref.geo_cached_external
-                          << ", i: " << grid_ref.geo_cached_internal << std::endl;
-              #endif
-              CoordProvider coords( hostElement(), subEntity_, grid().coordFunction() );
-              geo_ = new GeometryImpl( grid(), type(), coords );
-              cached_geo = geo_;
-            }
-          }else{
-            #if GEO_CACHE_BENCHMARK != 0
-              std::cout << "u: " << ++grid_ref.geo_uncached
-                        << ", e: " << grid_ref.geo_cached_external
-                        << ", i: " << grid_ref.geo_cached_internal << std::endl;
-            #endif
-            CoordProvider coords( hostElement(), subEntity_, grid().coordFunction() );
-            geo_ = new GeometryImpl( grid(), type(), coords );
-          }
+        if (!geo_) {
+          auto localFct = localFunction(Super::gridFunction());
+          localFct.bind(Super::hostEntity());
+          auto fakeDefaultGeometry = Dune::DefaultLocalGeometry<typename Super::ctype, Super::mydimension, Super::mydimension>{};
+          geo_ = std::make_shared<GeometryImpl>(Super::type(), localFct, fakeDefaultGeometry);
         }
-        #if GEO_CACHE_BENCHMARK != 0
-          else{
-            std::cout << "u: " << grid_->geo_uncached
-                      << ", e: " << grid_->geo_cached_external
-                      << ", i: " << ++grid_->geo_cached_internal << std::endl;
-          }
-        #endif
-        return Geometry( *geo_ );
-      }
-
-      unsigned int subEntities ( unsigned int cc ) const
-      {
-        auto refElement = referenceElement< ctype, dimension >( hostElement().type() );
-        return refElement.size( subEntity_, codimension, cc );
-      }
-
-      /** \brief return EntitySeed of host grid entity */
-      EntitySeed seed () const { return typename EntitySeed::Implementation( hostElement().seed(), subEntity_ ); }
-      /** \} */
-
-      /** \name Methods Supporting the Grid Implementation
-       *  \{ */
 
-      const Grid &grid () const { assert( grid_ ); return *grid_; }
-
-      const HostEntity &hostEntity () const
-      {
-        DUNE_THROW( NotImplemented, "HostGrid has no entities of codimension " << codimension << "." );
+        return Geometry(*geo_);
       }
 
-      const HostElement &hostElement () const
-      {
-        return hostElement_;
-      }
-
-      int subEntity () const { return subEntity_; }
-
-      /** \brief initiliaze an entity
-       *
-       *  \param[in]  hostElement  reference to the host element
-       *
-       *  \note The reference must remain valid as long as this entity is in
-       *        use.
-       */
-      void initialize ( const HostElement &hostElement ) { hostElement_ = hostElement; }
-
-      /** \brief obtain the entity's index from a host IndexSet
-       *
-       *  \internal This method is provided by the entity, because its
-       *  implementation is different for fake and non-fake entities.
-       *
-       *  \param[in]  indexSet  host IndexSet to use
-       */
-      template< class HostIndexSet >
-      typename HostIndexSet::IndexType index ( const HostIndexSet &indexSet ) const
-      {
-        return indexSet.subIndex( hostElement(), subEntity_, codimension );
-      }
-
-      /** \brief obtain the index of a subentity from a host IndexSet
-       *
-       *  \internal This method is provided by the entity, because its
-       *  implementation is different for fake and non-fake entities.
-       *
-       *  \param[in]  indexSet  host IndexSet to use
-       *  \param[in]  i         number of the subentity
-       *  \param[in]  cd        codimension of the subentity
-       */
-      template< class HostIndexSet >
-      typename HostIndexSet::IndexType
-      subIndex ( const HostIndexSet &indexSet, int i, unsigned int cd ) const
-      {
-        auto refElement = referenceElement< ctype, dimension >( hostElement().type() );
-        const int j = refElement.subEntity( subEntity_, codimension, i, codimension+cd );
-        return indexSet.subIndex( hostElement(), j, codimension+cd );
-      }
-
-      /** \brief check whether the entity is contained in a host index set
-       *
-       *  \internal This method is provided by the entity, because its
-       *  implementation is different for fake and non-fake entities.
-       *
-       *  \param  indexSet  host IndexSet to use
-       */
-      template< class HostIndexSet >
-      bool isContained ( const HostIndexSet &indexSet ) const
-      {
-        return indexSet.contains( hostElement() );
-      }
-
-      /** \brief obtain the entity's id from a host IdSet
-       *
-       *  \internal This method is provided by the entity, because its
-       *  implementation is different for fake and non-fake entities.
-       *
-       *  \param  idSet  host IdSet to use
-       */
-      template< class HostIdSet >
-      typename HostIdSet::IdType id ( const HostIdSet &idSet ) const
-      {
-        return idSet.subId( hostElement(), subEntity_, codimension );
-      }
-      /** \} */
-
     private:
-      PartitionType
-      vertexPartitionType ( Dune::Transitional::ReferenceElement< ctype, Dim<dimension> > refElement, int i ) const
-      {
-        const int j = refElement.subEntity( subEntity_, codimension, i, dimension );
-        return hostElement().template subEntity< dimension >( j ).partitionType();
-      }
-
-    private:
-      HostElement hostElement_;
-      unsigned int subEntity_;
-      const Grid *grid_;
-      mutable GeometryImpl *geo_;
+      using GeometryImpl = typename Traits::template Codim<0>::GeometryImpl;
+      mutable std::shared_ptr<GeometryImpl> geo_;
     };
 
 
-
     // Entity
     // ------
 
-    template< int codim, int dim, class Grid >
+    template< int codim, int dim, class G >
     class Entity
-      : public EntityBase< codim, Grid >
+        : public EntityBaseGeometry<codim, G>
     {
-      typedef EntityBase< codim, Grid > Base;
+      using Super = EntityBaseGeometry<codim, G>;
 
     public:
-      typedef typename Base::HostEntity HostEntity;
-      typedef typename Base::HostElement HostElement;
-      typedef typename Base::GeometryImpl GeometryImpl;
-      typedef typename Base::EntitySeed EntitySeed;
-
-      Entity () : Base() {}
-
-      Entity ( const Grid &grid, const EntitySeed &seed ) : Base( grid, seed ) {}
-
-      Entity ( const Grid &grid, const HostEntity &hostEntity ) : Base( grid, hostEntity ) {}
-      Entity ( const Grid &grid, HostEntity&& hostEntity ) : Base( grid, std::move( hostEntity ) ) {}
-
-      Entity ( const Grid &grid, const HostElement &hostEntity, int i ) : Base( grid, hostEntity, i ) {}
-
+      // import constructors from base class
+      using Super::Super;
     };
 
 
-
     // Entity for codimension 0
     // ------------------------
 
-    template< int dim, class Grid >
-    class Entity< 0, dim, Grid >
-      : public EntityBase< 0, Grid >
+    template< int dim, class G >
+    class Entity<0, dim, G>
+        : public EntityBaseGeometry<0, G>
     {
-      typedef EntityBase< 0, Grid > Base;
-
-      typedef typename std::remove_const< Grid >::type::Traits Traits;
+      using Super = EntityBaseGeometry<0, G>;
 
-      typedef typename Traits::HostGrid HostGrid;
+      using Traits = typename std::remove_const_t<G>::Traits;
+      using Grid = typename Traits::Grid;
+      using GridFunction = typename Grid::GridFunction;
+      using HostGrid = typename Traits::HostGrid;
 
     public:
-      /** \name Attributes
-       *  \{ */
-
-      //! codimensioon of the entity
-      static const int codimension = Base::codimension;
-      //! dimension of the grid
-      static const int dimension = Base::dimension;
-      //! dimension of the entity
-      static const int mydimension = Base::mydimension;
-      //! dimension of the world
-      static const int dimensionworld = Base::dimensionworld;
-
-      //! \b true, if the entity is faked, i.e., if there is no corresponding host entity
-      static const bool fake = Base::fake;
-      /** \} */
 
       /** \name Types Required by DUNE
        *  \{ */
 
       //! type of corresponding local geometry
-      typedef typename Traits::template Codim< codimension >::LocalGeometry LocalGeometry;
+      using LocalGeometry = typename Traits::template Codim<0>::LocalGeometry;
 
-      typedef Dune::Entity< 0, dim, Grid, Dune::crvsrf::Entity > EntityFacade;
+      //! facade type for entities
+      using EntityFacade = Dune::Entity<0, dim, G, Dune::Curved::Entity>;
 
       //! type of hierarchic iterator
-      typedef typename Traits::HierarchicIterator HierarchicIterator;
+      using HierarchicIterator = typename Traits::HierarchicIterator;
+
       //! type of leaf intersection iterator
-      typedef typename Traits::LeafIntersectionIterator LeafIntersectionIterator;
+      using LeafIntersectionIterator = typename Traits::LeafIntersectionIterator;
+
       //! type of level intersection iterator
-      typedef typename Traits::LevelIntersectionIterator LevelIntersectionIterator;
+      using LevelIntersectionIterator = typename Traits::LevelIntersectionIterator;
 
       /** \} */
 
-      typedef typename Base::HostEntity HostEntity;
-      typedef typename Base::HostElement HostElement;
-      typedef typename Base::GeometryImpl GeometryImpl;
-      typedef typename Base::EntitySeed EntitySeed;
-
-      using Base::grid;
-      using Base::hostEntity;
-
-      Entity () : Base() {}
-
-      Entity ( const Grid &grid, const HostEntity &hostEntity ) : Base( grid, hostEntity ) {}
-      Entity ( const Grid &grid, HostEntity&& hostEntity ) : Base( grid, std::move( hostEntity ) ) {}
-      Entity ( const GeometryImpl &geo, const HostEntity& hostEntity ) : Base( geo, hostEntity ) {}
-      Entity ( const GeometryImpl &geo, HostEntity &&hostEntity ) : Base( geo, std::move( hostEntity ) ) {}
-
-      Entity ( const Grid &grid, const EntitySeed &seed ) : Base( grid, seed ) {}
-
-      Entity ( const Grid &grid, const HostEntity &hostEntity, int i ) : Base( grid, hostEntity )
-      {
-        assert( i == 0 );
-      }
+      // import constructors from base class
+      using Super::Super;
 
       template< int codim >
-      typename Grid::template Codim< codim >::Entity
-      subEntity ( int i ) const
+      typename Grid::template Codim<codim>::Entity subEntity (int i) const
       {
-        typedef typename Traits::template Codim< codim >::EntityImpl EntityImpl;
-        return EntityImpl( grid(), hostEntity(), i );
+        using EntityImpl = typename Traits::template Codim<codim>::EntityImpl;
+        return EntityImpl(Super::gridFunction(), Super::hostEntity(), i);
       }
 
       LevelIntersectionIterator ilevelbegin () const
       {
-        typedef crvsrf::IntersectionIterator< Grid, typename HostGrid::LevelIntersectionIterator > LevelIntersectionIteratorImpl;
-        return LevelIntersectionIteratorImpl( *this, hostEntity().ilevelbegin() );
+        using IteratorImpl = Curved::IntersectionIterator<Grid, typename HostGrid::LevelIntersectionIterator>;
+        return IteratorImpl(*this, Super::hostEntity().ilevelbegin());
       }
 
       LevelIntersectionIterator ilevelend () const
       {
-        typedef crvsrf::IntersectionIterator< Grid, typename HostGrid::LevelIntersectionIterator > LevelIntersectionIteratorImpl;
-        return LevelIntersectionIteratorImpl( *this, hostEntity().ilevelend() );
+        using IteratorImpl = Curved::IntersectionIterator<Grid, typename HostGrid::LevelIntersectionIterator>;
+        return IteratorImpl(*this, Super::hostEntity().ilevelend());
       }
 
       LeafIntersectionIterator ileafbegin () const
       {
-        typedef crvsrf::IntersectionIterator< Grid, typename HostGrid::LeafIntersectionIterator > LeafIntersectionIteratorImpl;
-        return LeafIntersectionIteratorImpl( *this, hostEntity().ileafbegin() );
+        using IteratorImpl = Curved::IntersectionIterator<Grid, typename HostGrid::LeafIntersectionIterator>;
+        return IteratorImpl(*this, Super::hostEntity().ileafbegin());
       }
 
       LeafIntersectionIterator ileafend () const
       {
-        typedef crvsrf::IntersectionIterator< Grid, typename HostGrid::LeafIntersectionIterator > LeafIntersectionIteratorImpl;
-        return LeafIntersectionIteratorImpl( *this, hostEntity().ileafend() );
+        using IteratorImpl = Curved::IntersectionIterator<Grid, typename HostGrid::LeafIntersectionIterator>;
+        return IteratorImpl(*this, Super::hostEntity().ileafend());
       }
 
       bool hasBoundaryIntersections () const
       {
-        return hostEntity().hasBoundaryIntersections();
+        return Super::hostEntity().hasBoundaryIntersections();
       }
 
       bool isLeaf () const
       {
-        return hostEntity().isLeaf();
+        return Super::hostEntity().isLeaf();
       }
 
       EntityFacade father () const
       {
-        return Entity( grid(), hostEntity().father() );
+        return Entity(Super::gridFunction(), Super::hostEntity().father());
       }
 
       bool hasFather () const
       {
-        return hostEntity().hasFather();
+        return Super::hostEntity().hasFather();
       }
 
       LocalGeometry geometryInFather () const
       {
-        return hostEntity().geometryInFather();
+        return Super::hostEntity().geometryInFather();
       }
 
-      HierarchicIterator hbegin ( int maxLevel ) const
+      HierarchicIterator hbegin (int maxLevel) const
       {
-        typedef crvsrf::HierarchicIterator< Grid > HierarchicIteratorImpl;
-        return HierarchicIteratorImpl( grid(), hostEntity().hbegin( maxLevel ) );
+        using IteratorImpl = Curved::HierarchicIterator<G>;
+        return IteratorImpl(Super::gridFunction(), Super::hostEntity().hbegin(maxLevel));
       }
 
-      HierarchicIterator hend ( int maxLevel ) const
+      HierarchicIterator hend (int maxLevel) const
       {
-        typedef crvsrf::HierarchicIterator< Grid > HierarchicIteratorImpl;
-        return HierarchicIteratorImpl( grid(), hostEntity().hend( maxLevel ) );
+        using IteratorImpl = Curved::HierarchicIterator<G>;
+        return IteratorImpl(Super::gridFunction(), Super::hostEntity().hend(maxLevel));
       }
 
       bool isRegular () const
       {
-        return hostEntity().isRegular();
+        return Super::hostEntity().isRegular();
       }
 
       bool isNew () const
       {
-        return hostEntity().isNew();
+        return Super::hostEntity().isNew();
       }
 
       bool mightVanish () const
       {
-        return hostEntity().mightVanish();
+        return Super::hostEntity().mightVanish();
       }
     };
 
-  } // namespace crvsrf
-
+  } // namespace Curved
 } // namespace Dune
 
-#endif // #ifndef DUNE_CRVSRF_ENTITY_HH
+#endif // DUNE_CURVED_SURFACE_GRID_ENTITY_HH
diff --git a/dune/curvedsurfacegrid/entityseed.hh b/dune/curvedsurfacegrid/entityseed.hh
index bdeb2538c340d95c2acb7d44747325f9562cbcaa..73a953c5e056c30c4ece15941013ebd38038f20f 100644
--- a/dune/curvedsurfacegrid/entityseed.hh
+++ b/dune/curvedsurfacegrid/entityseed.hh
@@ -1,7 +1,7 @@
 // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
 // vi: set et ts=4 sw=2 sts=2:
-#ifndef DUNE_CRVSRF_ENTITYSEED_HH
-#define DUNE_CRVSRF_ENTITYSEED_HH
+#ifndef DUNE_CURVED_SURFACE_GRID_ENTITYSEED_HH
+#define DUNE_CURVED_SURFACE_GRID_ENTITYSEED_HH
 
 #include <dune/common/typetraits.hh>
 
@@ -10,109 +10,47 @@
 
 namespace Dune
 {
-
-  namespace crvsrf
+  namespace Curved
   {
 
-    // Internal Forward Declarations
-    // -----------------------------
-
-    template< int codim, class Grid, bool fake = !(Capabilities::hasHostEntity< Grid, codim >::v) >
-    class EntitySeed;
-
-
+    // EntitySeed
+    // ----------
 
-    // EntitySeed (real)
-    // -----------------
-
-    template< int codim, class Grd >
-    class EntitySeed< codim, Grd, false >
+    template< int codim, class G >
+    class EntitySeed
     {
-      typedef typename std::remove_const< Grd >::type::Traits Traits;
+      using Traits = typename std::remove_const_t<G>::Traits;
+      using HostGrid = typename Traits::HostGrid;
+      using HostEntitySeed = typename HostGrid::template Codim<codim>::EntitySeed;
 
     public:
       static const int codimension = codim;
-      static const int dimension = Traits::dimension;
-      static const int mydimension = dimension - codimension;
-      static const int dimensionworld = Traits::dimensionworld;
-
-      static const bool fake = false;
-
-      typedef typename Traits::Grid Grid;
-      typedef typename Traits::template Codim< codim >::Entity Entity;
-
-      typedef typename Traits::HostGrid HostGrid;
-      typedef typename HostGrid::template Codim< codim >::EntitySeed HostEntitySeed;
 
       //! default construct an invalid entity seed
-      EntitySeed ( )
-      {}
+      EntitySeed () = default;
 
-      explicit EntitySeed ( const HostEntitySeed &hostEntitySeed )
-        : hostEntitySeed_( hostEntitySeed )
+      //! construct the entity-seed from a host-entity seed
+      explicit EntitySeed (const HostEntitySeed& hostEntitySeed)
+        : hostEntitySeed_(hostEntitySeed)
       {}
 
       //! check whether the EntitySeed refers to a valid Entity
-      bool isValid() const
+      bool isValid () const
       {
         return hostEntitySeed_.isValid();
       }
 
-      const HostEntitySeed &hostEntitySeed () const { return hostEntitySeed_; }
-
-    private:
-      HostEntitySeed hostEntitySeed_;
-    };
-
-
-
-    // EntitySeed (fake)
-    // -----------------
-
-    template< int codim, class Grd >
-    class EntitySeed< codim, Grd, true >
-    {
-      typedef typename std::remove_const< Grd >::type::Traits Traits;
-
-    public:
-      static const int codimension = codim;
-      static const int dimension = Traits::dimension;
-      static const int mydimension = dimension - codimension;
-      static const int dimensionworld = Traits::dimensionworld;
-
-      static const bool fake = true;
-
-      typedef typename Traits::Grid Grid;
-      typedef typename Traits::template Codim< codim >::Entity Entity;
-
-      typedef typename Traits::HostGrid HostGrid;
-      typedef typename HostGrid::template Codim< 0 >::EntitySeed HostElementSeed;
-
-      //! default construct an invalid entity seed
-      EntitySeed ( )
-      {}
-
-      explicit EntitySeed ( const HostElementSeed &hostElementSeed, unsigned int subEntity )
-        : hostElementSeed_( hostElementSeed ),
-          subEntity_( subEntity )
-      {}
-
-      //! check whether the EntitySeed refers to a valid Entity
-      bool isValid() const
+      //! return the entity seed of the host-entity
+      const HostEntitySeed& hostEntitySeed () const
       {
-        return hostElementSeed_.isValid();
+        return hostEntitySeed_;
       }
 
-      const HostElementSeed &hostElementSeed () const { return hostElementSeed_; }
-      unsigned int subEntity () const { return subEntity_; }
-
     private:
-      HostElementSeed hostElementSeed_;
-      unsigned int subEntity_;
+      HostEntitySeed hostEntitySeed_ = {};
     };
 
-  } // namespace crvsrf
-
+  } // namespace Curved
 } // namespace Dune
 
-#endif // #ifndef DUNE_CRVSRF_ENTITYSEED_HH
+#endif // DUNE_CURVED_SURFACE_GRID_ENTITYSEED_HH
diff --git a/dune/curvedsurfacegrid/geometry.hh b/dune/curvedsurfacegrid/geometry.hh
index e152f2fa94d24cafd973d14da100719e40c13a24..d07966e3e47649ad5391770d566c04b4be3ca119 100644
--- a/dune/curvedsurfacegrid/geometry.hh
+++ b/dune/curvedsurfacegrid/geometry.hh
@@ -1,223 +1,226 @@
 // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
 // vi: set et ts=4 sw=2 sts=2:
-#ifndef DUNE_CRVSRF_GEOMETRY_HH
-#define DUNE_CRVSRF_GEOMETRY_HH
-
-#include <utility>
-
+#ifndef DUNE_CURVED_SURFACE_GRID_GEOMETRY_HH
+#define DUNE_CURVED_SURFACE_GRID_GEOMETRY_HH
+
+#include <cassert>
+#include <functional>
+#include <iterator>
+#include <limits>
+#include <vector>
+
+#include <dune/common/diagonalmatrix.hh>
+#include <dune/common/fmatrix.hh>
+#include <dune/common/fvector.hh>
 #include <dune/common/typetraits.hh>
+#include <dune/common/std/optional.hh>
+#include <dune/common/std/type_traits.hh>
 
-#include <dune/curvilineargeometry/curvilineargeometry.hh>
+#include <dune/curvedgeometry/curvedgeometry.hh>
+#include <dune/curvedgeometry/localfunctiongeometry.hh>
+
+#include <dune/geometry/affinegeometry.hh>
+#include <dune/geometry/multilineargeometry.hh>
+#include <dune/geometry/quadraturerules.hh>
 #include <dune/geometry/referenceelements.hh>
 #include <dune/geometry/type.hh>
 
-#include <dune/grid/common/capabilities.hh>
-#include <dune/curvedsurfacegrid/coordprovider.hh>
+#include "localgeometrywrapper.hh"
 
 namespace Dune
 {
-
-  namespace crvsrf
+  namespace Curved
   {
-
-    // InferHasSingleGeometryType
-    // --------------------------
-
-    template< class hasSingleGeometryType, int dim, int mydim >
-    struct InferHasSingleGeometryType
+    /// \brief Curved geometry implementation based on local basis function parametrization
+    /**
+     *  Parametrization of the geometry by a differentiable localFunction
+     *
+     *  \tparam  LF      localFunction parametrizing the geometry
+     *  \tparam  LG      localGeometry for coordinate transform from subEntity to element,
+     *                   see \ref Impl::DefaultLocalGeometry and \ref Impl::LocalGeometryInterface
+     *  \tparam  ORDER   Polynomial order of lagrange parametrization. If order < 0 use localFunction.
+     */
+    template <class ct, int mydim, int cdim, class LF, class LG, int ORDER = -1>
+    class Geometry
+        : public LagrangeCurvedGeometry<ct, mydim, cdim, (ORDER > 0 ? ORDER : 1)>
     {
-    private:
-      static const unsigned int id = hasSingleGeometryType::topologyId;
-      static const unsigned int idMask = (1u << mydim) - 1u;
+      using Super = LagrangeCurvedGeometry<ct, mydim, cdim, (ORDER > 0 ? ORDER : 1)>;
 
-    public:
-      static const bool v = hasSingleGeometryType::v && ((mydim == dim) || ((id | 1u) == 1u) || ((id | 1u) == idMask));
-      static const unsigned int topologyId = (v ? id & idMask : ~0u);
-    };
+      //! type of the localFunction representation the geometry parametrization
+      using LocalFunction = LF;
 
-    template< class hasSingleGeometryType, int dim >
-    struct InferHasSingleGeometryType< hasSingleGeometryType, dim, 1 >
-    {
-      static const bool v = true;
-      static const unsigned int topologyId = Impl::CubeTopology< 1 >::type::id;
-    };
+      //! type of coordinate transformation for subEntities to codim=0 entities
+      using LocalGeometry = LG;
 
-    template< class hasSingleGeometryType, int dim >
-    struct InferHasSingleGeometryType< hasSingleGeometryType, dim, 0 >
-    {
-      static const bool v = true;
-      static const unsigned int topologyId = Impl::CubeTopology< 0 >::type::id;
+      /// type of reference element
+      using ReferenceElements = Dune::ReferenceElements<ct, mydim>;
+      using ReferenceElement = typename ReferenceElements::ReferenceElement;
+
+    public:
+      /// \brief constructor from localFunction to parametrize the geometry
+      /**
+       *  \param[in]  refElement     reference element for the geometry
+       *  \param[in]  localFunction  localFunction for the parametrization of the geometry
+       *                             (stored by value)
+       *  \param[in]  args...        argument to construct the local geometry
+       *
+       */
+      template <class... Args>
+      Geometry (const ReferenceElement& refElement, const LocalFunction& localFunction, Args&&... args)
+        : Super(refElement, [localFunction, localGeometry=LocalGeometry{std::forward<Args>(args)...}](auto const& local)
+          {
+            return localFunction(localGeometry.global(local));
+          })
+      {}
+
+      /// \brief constructor, forwarding to the other constructor that take a reference-element
+      /**
+       *  \param[in]  gt             geometry type
+       *  \param[in]  localFunction  localFunction for the parametrization of the geometry
+       *                             (stored by value)
+       *  \param[in]  args...        argument to construct the local geometry
+       */
+      template <class... Args>
+      Geometry (Dune::GeometryType gt, const LocalFunction& localFunction, Args&&... args)
+        : Geometry(ReferenceElements::general(gt), localFunction, std::forward<Args>(args)...)
+      {}
     };
 
-    // GeometryTraits
-    // --------------
 
-    template< class Grid >
-    struct GeometryTraits
+    // Specialization for the case that ORDER < 0: Use LocalFunction `LF` directly as parametrization
+    template <class ct, int mydim, int cdim, class LF, class LG>
+    class Geometry<ct,mydim,cdim,LF,LG,-1>
+        : public LocalFunctionGeometry<LF,LG>
     {
-      typedef typename std::remove_const< Grid >::type::Traits Traits;
+      using Super = LocalFunctionGeometry<LF,LG>;
 
-      typedef typename Traits::ctype ctype;
+      //! type of the localFunction representation the geometry parametrization
+      using LocalFunction = LF;
 
-      typedef Impl::FieldMatrixHelper< ctype > MatrixHelper;
+      //! type of coordinate transformation for subEntities to codim=0 entities
+      using LocalGeometry = LG;
 
-      static ctype tolerance () { return 16 * std::numeric_limits< ctype >::epsilon(); }
+      /// type of reference element
+      using ReferenceElements = Dune::ReferenceElements<ct, mydim>;
+      using ReferenceElement = typename ReferenceElements::ReferenceElement;
 
-      template< int mydim >
-      struct hasSingleGeometryType
-        : public InferHasSingleGeometryType< Capabilities::hasSingleGeometryType< Grid >, Traits::dimension, mydim >
-      {};
+    public:
+      /// \brief constructor from localFunction to parametrize the geometry
+      /**
+       *  \param[in]  refElement     reference element for the geometry
+       *  \param[in]  localFunction  localFunction for the parametrization of the geometry
+       *                             (stored by value)
+       *  \param[in]  args...        argument to construct the local geometry
+       *
+       */
+      template <class... Args>
+      Geometry (const ReferenceElement& refElement, const LocalFunction& localFunction, Args&&... args)
+        : Super(refElement, localFunction, LocalGeometry{std::forward<Args>(args)...})
+      {}
+
+      /// \brief constructor, forwarding to the other constructor that take a reference-element
+      /**
+       *  \param[in]  gt             geometry type
+       *  \param[in]  localFunction  localFunction for the parametrization of the geometry
+       *                             (stored by value)
+       *  \param[in]  args...        argument to construct the local geometry
+       */
+      template <class... Args>
+      Geometry (Dune::GeometryType gt, const LocalFunction& localFunction, Args&&... args)
+        : Super(gt, localFunction, LocalGeometry{std::forward<Args>(args)...})
+      {}
     };
 
 
+  #ifndef DOXYGEN
 
-    // Geometry
-    // --------
-
-    template< int mydim, int cdim, class Grid >
-    class Geometry
+    // Specialization for vertex geometries
+    template <class ct, int cdim, class LF, class LG>
+    class VertexGeometry
+        : public AffineGeometry<ct,0,cdim>
     {
-      typedef Geometry< mydim, cdim, Grid > This;
-
-      typedef typename std::remove_const< Grid >::type::Traits Traits;
-
-      template< int, int, class > friend class Geometry;
-
-    public:
-      typedef typename Traits::ctype ctype;
+      using Super = AffineGeometry<ct,0,cdim>;
 
-      static const int mydimension = mydim;
-      static const int coorddimension = cdim;
-      static const int dimension = Traits::dimension;
-      static const int codimension = dimension - mydimension;
+      using LocalFunction = LF;
+      using LocalGeometry = LG;
 
-    protected:
-      typedef CachedCurvilinearGeometry<ctype, mydimension, coorddimension> BasicMapping;
-
-      struct Mapping
-        : public BasicMapping
-      {
-        typedef typename BasicMapping::GlobalCoordinate GlobalCoordinate;
-
-        template< class CoordVector >
-        Mapping ( const GeometryType &type, const CoordVector &coords )
-          : BasicMapping( type, coords, Grid::order ),
-            refCount_( 0 )
-        {}
+      //! tolerance to numerical algorithms
+      static ct tolerance () { return ct(16) * std::numeric_limits<ct>::epsilon(); }
 
-        void addReference () { ++refCount_; }
-        bool removeReference () { return (--refCount_ == 0); }
-
-      private:
-        unsigned int refCount_;
-      };
+      struct Construct {};
 
     public:
-      typedef typename Mapping::LocalCoordinate LocalCoordinate;
-      typedef typename Mapping::GlobalCoordinate GlobalCoordinate;
-
-      typedef typename Mapping::JacobianTransposed JacobianTransposed;
-      typedef typename Mapping::JacobianInverseTransposed JacobianInverseTransposed;
-
-      Geometry () : grid_( nullptr ), mapping_( nullptr ) {}
+      /// type of reference element
+      using ReferenceElements = Dune::ReferenceElements<ct, 0>;
+      using ReferenceElement = typename ReferenceElements::ReferenceElement;
 
-      explicit Geometry ( const Grid &grid ) : grid_( &grid ), mapping_( nullptr ) {}
+      /// type of local coordinates
+      using LocalCoordinate = FieldVector<ct, 0>;
 
-      template< class CoordVector >
-      Geometry ( const Grid &grid, const GeometryType &type, const CoordVector &coords )
-        : grid_( &grid )
-      {
-        assert( int( type.dim() ) == mydimension );
-        std::vector<GlobalCoordinate> vertices;
-        coords.calculate( vertices );
-        void *mappingStorage = grid.allocateStorage( sizeof( Mapping ) );
-        mapping_ = new( mappingStorage ) Mapping( type, vertices );
-        mapping_->addReference();
-      }
-
-      Geometry ( const This &other )
-        : grid_( other.grid_ ),
-          mapping_( other.mapping_ )
-      {
-        if( mapping_ )
-          mapping_->addReference();
-      }
+      /// type of global coordinates
+      using GlobalCoordinate = FieldVector<ct, cdim>;
 
-      Geometry ( This&& other )
-        : grid_( other.grid_ ),
-          mapping_( other.mapping_ )
-      {
-        other.grid_ = nullptr;
-        other.mapping_ = nullptr;
-      }
+    protected:
+      VertexGeometry (Construct, const ReferenceElement& refElement, const LocalFunction& localFunction,
+                      const LocalGeometry& lg)
+        : Super(refElement, std::vector<GlobalCoordinate>{localFunction(lg.global(refElement.position(0,0)))})
+      {}
 
-      ~Geometry ()
+    public:
+      template <class... Args>
+      VertexGeometry (const ReferenceElement& refElement, const LocalFunction& lf, Args&&... args)
+        : VertexGeometry(Construct{}, refElement, lf, LocalGeometry(std::forward<Args>(args)...))
+      {}
+
+      template <class... Args>
+      VertexGeometry (Dune::GeometryType gt, const LocalFunction& lf, Args&&... args)
+        : VertexGeometry(Construct{}, ReferenceElements::general(gt), lf,
+                   LocalGeometry(std::forward<Args>(args)...))
+      {}
+
+      Std::optional<LocalCoordinate> checkedLocal (const GlobalCoordinate& globalCoord) const
       {
-        if( mapping_ && mapping_->removeReference() )
-          destroyMapping();
-      }
+        auto localCoord = Super::local(globalCoord);
+        if ((globalCoord - Super::global(localCoord)).two_norm2() > tolerance())
+          return {};
 
-      const This &operator= ( const This &other )
-      {
-        if( other.mapping_ )
-          other.mapping_->addReference();
-        if( mapping_ && mapping_->removeReference() )
-          destroyMapping();
-        grid_ = other.grid_;
-        mapping_ = other.mapping_;
-        return *this;
+        return localCoord;
       }
 
-      const This &operator= ( This&& other )
+      GlobalCoordinate normal (const LocalCoordinate& local) const
       {
-        using std::swap;
-        swap( grid_, other.grid_ );
-        swap( mapping_, other.mapping_ );
-        return *this;
+        DUNE_THROW(Dune::NotImplemented,
+          "ERROR: normal() method only defined for edges in 2D and faces in 3D");
+        return GlobalCoordinate(0);
       }
 
-      explicit operator bool () const { return bool( mapping_ ); }
-
-      bool affine () const { return mapping_->affine(); }
-      GeometryType type () const { return mapping_->type(); }
-
-      std::vector<GlobalCoordinate> interpolatoryVertices() const { return mapping_->vertexSet(); }
-      int corners () const { return mapping_->nCorner(); }
-      GlobalCoordinate corner ( const int i ) const { return mapping_->corner( i ); }
-      GlobalCoordinate center () const { return mapping_->center(); }
-
-      GlobalCoordinate global ( const LocalCoordinate &local ) const { return mapping_->global( local ); }
-      LocalCoordinate local ( const GlobalCoordinate &global ) const
-      {
-        LocalCoordinate l;
-        DUNE_UNUSED bool b = mapping_->local( global, l );
-        assert(b);
-        return l;
-      }
-
-      GlobalCoordinate normal ( const LocalCoordinate &local ) const { return mapping_->normal( local ); }
-
-      ctype integrationElement ( const LocalCoordinate &local ) const { return mapping_->integrationElement( local ); }
-      ctype volume () const { return mapping_->volume(std::numeric_limits<ctype>::epsilon()); }
-
-      JacobianTransposed jacobianTransposed ( const LocalCoordinate &local ) const { return mapping_->jacobianTransposed( local ); }
-      JacobianInverseTransposed jacobianInverseTransposed ( const LocalCoordinate &local ) const { return mapping_->jacobianInverseTransposed( local ); }
+    private:
+      VertexGeometry const& flatGeometry () const { return *this; }
+    };
 
-      const Grid &grid () const { assert( grid_ ); return *grid_; }
 
-    private:
-      void destroyMapping ()
-      {
-        mapping_->~Mapping();
-        grid().deallocateStorage( mapping_, sizeof( Mapping ) );
-      }
+    // Specialization for vertex geometries
+    template <class ct, int cdim, class LF, class LG, int order>
+    class Geometry<ct,0,cdim,LF,LG,order>
+        : public VertexGeometry<ct,cdim,LF,LG>
+    {
+      using Super = VertexGeometry<ct,cdim,LF,LG>;
+    public:
+      using Super::Super;
+    };
 
-      const Grid *grid_;
-      Mapping* mapping_;
+    template <class ct, int cdim, class LF, class LG>
+    class Geometry<ct,0,cdim,LF,LG,-1>
+        : public VertexGeometry<ct,cdim,LF,LG>
+    {
+      using Super = VertexGeometry<ct,cdim,LF,LG>;
+    public:
+      using Super::Super;
     };
 
-  } // namespace crvsrf
+#endif // DOXYGEN
 
+  } // end namespace Curved
 } // namespace Dune
 
-#endif // #ifndef DUNE_CRVSRF_GEOMETRY_HH
+#endif // DUNE_CURVED_SURFACE_GRID_GEOMETRY_HH
diff --git a/dune/curvedsurfacegrid/grid.hh b/dune/curvedsurfacegrid/grid.hh
index 6fd67dae0d8e83dd0209e5f98de7bcb971f030d2..060c090159305c5c86f4bfd65bfefc3a8b01a91d 100644
--- a/dune/curvedsurfacegrid/grid.hh
+++ b/dune/curvedsurfacegrid/grid.hh
@@ -1,111 +1,110 @@
 // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
 // vi: set et ts=4 sw=2 sts=2:
-#ifndef DUNE_CRVSRF_GRID_HH
-#define DUNE_CRVSRF_GRID_HH
+#ifndef DUNE_CURVED_SURFACE_GRID_GRID_HH
+#define DUNE_CURVED_SURFACE_GRID_GRID_HH
 
 #include <dune/common/deprecated.hh>
+#include <dune/common/shared_ptr.hh>
 
 #include <dune/grid/common/grid.hh>
 
+#include <dune/curvedsurfacegrid/concepts.hh>
 #include <dune/curvedsurfacegrid/gridfamily.hh>
 #include <dune/curvedsurfacegrid/backuprestore.hh>
 #include <dune/curvedsurfacegrid/datahandle.hh>
+#include <dune/curvedsurfacegrid/gridfunctions/analyticgridfunction.hh>
+#include <dune/curvedsurfacegrid/gridfunctions/gridfunction.hh>
+#include <dune/functions/common/functionconcepts.hh>
 #include <dune/grid/geometrygrid/identity.hh>
 #include <dune/grid/geometrygrid/persistentcontainer.hh>
 #include <dune/grid/geometrygrid/grid.hh>
 
 namespace Dune
 {
+  namespace Impl
+  {
+    template< class GridFunction, int order >
+    struct CurvedSurfaceGridBase
+    {
+      using HG = GridOf_t<GridFunction>;
+
+      using type = GridDefaultImplementation<
+        HG::dimension, Curved::DimRange<GridFunction>::value, typename HG::ctype,
+        Curved::GridFamily<GridFunction,order>
+      >;
+    };
+  }
+
+  template< class GridFunction, int order >
+  using CurvedSurfaceGridBase = typename Impl::CurvedSurfaceGridBase<GridFunction,order>::type;
+
 
   // CurvedSurfaceGrid
   // -----------------
 
   /** \class CurvedSurfaceGrid
    *  \brief grid wrapper replacing the geometries
-   *  \ingroup crvsrf
-   *
-   *  CurvedSurfaceGrid wraps another DUNE grid and replaces its geometry by the
-   *  generic geometries from dune-grid. It also adds interpolatory vertices according
-   *  to the desired polynomial order, treating the geometry as a curved variant of the
-   *  host geometry. The coordinates for the mapped corners and interpolatory vertices
-   *  are obtained by applying a coordinate function.
-   *
-   *  An example of a coordinate function is given by the following code:
-      \code
-      class ExampleFunction
-      : public Dune :: AnalyticalCoordFunction< double, 2, 3, ExampleFunction >
-      {
-        typedef ExampleFunction This;
-        typedef Dune :: AnalyticalCoordFunction< double, 2, 3, This > Base;
-
-      public:
-        typedef Base :: DomainVector DomainVector;
-        typedef Base :: RangeVector RangeVector;
-
-        void evaluate ( const DomainVector &x, RangeVector &y ) const
-        {
-          y[ 0 ] = x[ 0 ];
-          y[ 1 ] = x[ 1 ];
-          y[ 2 ] = x[ 0 ] + x[ 1 ];
-        }
-      };
-      \endcode
+   *  \ingroup CurvedGeo
    *
-   *  \note A dune-fem Function can be used as a coordinate function.
-   *        The evaluation of discrete functions would be very expensive,
-   *        though.
+   *  CurvedSurfaceGrid wraps another DUNE grid and replaces its geometry by an implementation
+   *  of a CurvedGeometry.
    *
-   *  \tparam HostGrid       DUNE grid to be wrapped (called host grid)
-   *  \tparam CoordFunction  coordinate function
+   *  \tparam GF     GridViewFunction defined on a (flat) hostgrid
+   *  \tparam ORDER  Polynomial order of local lagrange basis functions to use when approximating
+   *                 the curved geometry. [optional]
    *
    *  \nosubgrouping
    */
-  template< class HostGrid, class CoordFunction = DefaultCoordFunction< HostGrid >,
-    int interpolatoryOrder = 1, bool geoCaching = true, class Allocator = std::allocator< void > >
-  class CurvedSurfaceGrid
-  /** \cond */
-    : public GridDefaultImplementation
-        < HostGrid::dimension, CoordFunction::dimRange, typename HostGrid::ctype,
-        crvsrf::GridFamily< HostGrid, CoordFunction, interpolatoryOrder, geoCaching, Allocator > >,
-      public crvsrf::ExportParams< HostGrid, CoordFunction >,
-      public crvsrf::BackupRestoreFacilities< CurvedSurfaceGrid< HostGrid, CoordFunction,
-                                            interpolatoryOrder, geoCaching, Allocator > >
-      /** \endcond */
-  {
-    typedef CurvedSurfaceGrid< HostGrid, CoordFunction, interpolatoryOrder,
-                                                geoCaching, Allocator > Grid;
+  template< class GF, int ORDER = -1 >
+  class CurvedSurfaceGrid;
 
-    typedef GridDefaultImplementation
-    < HostGrid::dimension, CoordFunction::dimRange, typename HostGrid::ctype,
-        crvsrf::GridFamily< HostGrid, CoordFunction, interpolatoryOrder, geoCaching, Allocator > >
-    Base;
+  //! Generator for CurvedSurfaceGrid from a grid-functions
+  template< class HostGrid, class GF, int ORDER = -1, 
+    std::enable_if_t<Dune::Concept::isGridFunction<GF, HostGrid>(), int> = 0>
+  auto curedSurfaceGrid (HostGrid& hostGrid, GF&& gridFunction) 
+  {
+    static_assert(std::is_same<HostGrid, GridOf_t<std::decay_t<GF>>>::value, "GridFunction must be defined on the HostGrid");
+    return CurvedSurfaceGrid<std::decay_t<GF>,ORDER>{hostGrid, std::forward<GF>(gridFunction)};
+  }
+
+  //! Generator for CurvedSurfaceGrid from a callable
+  template< class HostGrid, class F, int ORDER = -1, 
+    std::enable_if_t<not Dune::Concept::isGridFunction<F, HostGrid>(), int> = 0>
+  auto curedSurfaceGrid (HostGrid& hostGrid, F&& callable) 
+  {
+    using GlobalCoordinate = typename GridEntitySet<HostGrid,0>::GlobalCoordinate;
+    static_assert(Functions::Concept::isCallable<F, GlobalCoordinate>(), "Function must be callable");
+    auto gridFct = analyticGridFunction<HostGrid>(std::forward<F>(callable));
+    return CurvedSurfaceGrid<decltype(gridFct),ORDER>{hostGrid, std::move(gridFct)};
+  }
 
-    friend class crvsrf::HierarchicIterator< const Grid >;
 
-    template< int, class, bool > friend class crvsrf::EntityBase;
-    template< int, int, class > friend class crvsrf::Geometry;
-    template< class, class, class > friend class crvsrf::GridView;
-    template< class, class > friend class crvsrf::Intersection;
-    template< class, class > friend class crvsrf::IntersectionIterator;
-    template< class, class > friend class crvsrf::IdSet;
-    template< class, class > friend class crvsrf::IndexSet;
-    template< class > friend struct HostGridAccess;
+  template< class GF, int ORDER >
+  class CurvedSurfaceGrid
+      : public CurvedSurfaceGridBase<GF,ORDER>
+      , public Curved::BackupRestoreFacilities<CurvedSurfaceGrid<GF,ORDER> >
+  {
+    using Self = CurvedSurfaceGrid;
+    using Super = CurvedSurfaceGridBase<GF,ORDER>;
 
-    template< class, class > friend class crvsrf::CommDataHandle;
+    // friend declarations
+    template< class, class > friend class Curved::IdSet;
+    template< class, class > friend class Curved::IndexSet;
 
   public:
-    /** \cond */
-    typedef crvsrf::GridFamily< HostGrid, CoordFunction, interpolatoryOrder, geoCaching, Allocator > GridFamily;
-    /** \endcond */
+    using GridFunction = GF;
+    using GridFamily = Curved::GridFamily<GF,ORDER>;
 
     /** \name Traits
      *  \{ */
 
     //! type of the grid traits
-    typedef typename GridFamily::Traits Traits;
+    using Traits = typename GridFamily::Traits;
 
-    /** \brief traits structure containing types for a codimension
-     *
+    using HostGrid = typename Traits::HostGrid;
+
+    //! traits structure containing types for a codimension
+    /**
      *  \tparam codim  codimension
      *
      *  \nosubgrouping
@@ -119,21 +118,25 @@ namespace Dune
      *  \{ */
 
     //! iterator over the grid hierarchy
-    typedef typename Traits::HierarchicIterator HierarchicIterator;
+    using HierarchicIterator = typename Traits::HierarchicIterator;
+
     //! iterator over intersections with other entities on the leaf level
-    typedef typename Traits::LeafIntersectionIterator LeafIntersectionIterator;
+    using LeafIntersectionIterator = typename Traits::LeafIntersectionIterator;
+
     //! iterator over intersections with other entities on the same level
-    typedef typename Traits::LevelIntersectionIterator LevelIntersectionIterator;
+    using LevelIntersectionIterator = typename Traits::LevelIntersectionIterator;
 
     /** \} */
 
+
     /** \name Grid View Types
      *  \{ */
 
-    /** \brief type of view for leaf grid */
-    typedef typename GridFamily::Traits::LeafGridView LeafGridView;
-    /** \brief type of view for level grid */
-    typedef typename GridFamily::Traits::LevelGridView LevelGridView;
+    //! type of view for leaf grid
+    using LeafGridView = typename GridFamily::Traits::LeafGridView;
+
+    //! type of view for level grid
+    using LevelGridView = typename GridFamily::Traits::LevelGridView;
 
     /** \} */
 
@@ -149,7 +152,7 @@ namespace Dune
      *
      *  The leaf index set is a model of Dune::IndexSet.
      */
-    typedef typename Traits::LeafIndexSet LeafIndexSet;
+    using LeafIndexSet = typename Traits::LeafIndexSet;
 
     /** \brief type of level index set
      *
@@ -159,7 +162,7 @@ namespace Dune
      *
      *  The level index set is a model of Dune::IndexSet.
      */
-    typedef typename Traits::LevelIndexSet LevelIndexSet;
+    using LevelIndexSet = typename Traits::LevelIndexSet;
 
     /** \brief type of global id set
      *
@@ -171,7 +174,7 @@ namespace Dune
      *
      *  The global id set is a model of Dune::IdSet.
      */
-    typedef typename Traits::GlobalIdSet GlobalIdSet;
+    using GlobalIdSet = typename Traits::GlobalIdSet;
 
     /** \brief type of local id set
      *
@@ -188,7 +191,7 @@ namespace Dune
      *
      *  The global id set is a model of Dune::IdSet.
      */
-    typedef typename Traits::LocalIdSet LocalIdSet;
+    using LocalIdSet = typename Traits::LocalIdSet;
 
     /** \} */
 
@@ -196,92 +199,49 @@ namespace Dune
      * \{ */
 
     //! type of vector coordinates (e.g., double)
-    typedef typename Traits::ctype ctype;
+    using ctype = typename Traits::ctype;
 
     //! communicator with all other processes having some part of the grid
-    typedef typename Traits::CollectiveCommunication CollectiveCommunication;
-
-    //! lagrange-order of curved elements
-    static const int order = interpolatoryOrder;
-
-    //! determines whether geometry-objects are cached beyond entity-lifetime
-    static const bool useGeometryCaching = geoCaching;
+    using CollectiveCommunication = typename Traits::CollectiveCommunication;
 
     /** \} */
 
     /** \name Construction and Destruction
      *  \{ */
 
-    /** \brief constructor
-     *
-     *  The references to host grid and coordinate function are stored in the
-     *  grid. Therefore, they must remain valid until the grid is destroyed.
-     *
-     *  \param[in]  hostGrid       reference to the grid to wrap
-     *  \param[in]  coordFunction  reference to the coordinate function
-     *  \param[in]  allocator      storage allocator
-     */
-    CurvedSurfaceGrid ( HostGrid &hostGrid, CoordFunction &coordFunction, const Allocator &allocator = Allocator() )
-      : hostGrid_( &hostGrid ),
-        coordFunction_( &coordFunction ),
-        removeHostGrid_( false ),
-        levelIndexSets_( hostGrid_->maxLevel()+1, nullptr, allocator ),
-        storageAllocator_( allocator )
-    {assert(order >= 1 && order <= 5);}
-
-    /** \brief constructor
-     *
-     *  The grid takes ownership of the pointers to host grid and coordinate
-     *  function. They will be deleted when the grid is destroyed.
-     *
-     *  \param[in]  hostGrid       pointer to the grid to wrap
-     *  \param[in]  coordFunction  pointer to the coordinate function
-     *  \param[in]  allocator      storage allocator
-     */
-    CurvedSurfaceGrid ( HostGrid *hostGrid, CoordFunction *coordFunction, const Allocator &allocator = Allocator() )
-      : hostGrid_( hostGrid ),
-        coordFunction_( coordFunction ),
-        removeHostGrid_( true ),
-        levelIndexSets_( hostGrid_->maxLevel()+1, nullptr, allocator ),
-        storageAllocator_( allocator )
-    {assert(order >= 1 && order <= 5);}
-
-    /** \brief constructor
-     *
-     *  The grid takes ownership of the pointer to host grid and it will
-     *  be deleted when the grid is destroyed. The coordinate function
-     *  is automatically constructed.
-     *
-     *  \param[in]  hostGrid       pointer to the grid to wrap
-     *  \param[in]  allocator      storage allocator
-     */
-    CurvedSurfaceGrid ( HostGrid *hostGrid, const Allocator &allocator = Allocator() )
-      : hostGrid_( hostGrid ),
-        coordFunction_( new CoordFunction( this->hostGrid() ) ),
-        removeHostGrid_( true ),
-        levelIndexSets_( hostGrid_->maxLevel()+1, nullptr, allocator ),
-        storageAllocator_( allocator )
-    {assert(order >= 1 && order <= 5);}
-
-
-    /** \brief destructor
+    //! constructor for host-grid given by reference
+    /**
+     *  The references to host grid is stored in the grid. It must be valid until this grid
+     *  wrapper is destroyed.
+     *
+     *  \param[in]  hostGrid      reference to the grid to wrap
+     *  \param[in]  gridFunction  mapping from global coordinates in the host geometry
+     *                            to global coordinates in the curved geometry
+     * 
+     *  If the gridFunction is passed by (non-const) reference it is stored as a non-destroying shared_ptr.
+     *  Otherwise it is copied or moved into a new object (stored as shared_ptr as well).
      */
+    template <class GF_,
+      std::enable_if_t<std::is_same<GF,std::decay_t<GF_>>::value, int> = 0>
+    CurvedSurfaceGrid (HostGrid& hostGrid, GF_&& gridFunction, std::integral_constant<int,ORDER> = {})
+      : hostGrid_(hostGrid)
+      , gridFunction_(wrap_or_move(std::forward<GF_>(gridFunction)))
+      , levelIndexSets_(hostGrid_.maxLevel()+1, nullptr)
+    {}
+
+    template <class F_,
+      std::enable_if_t<std::is_same<GF,AnalyticGridFunction<HostGrid,std::decay_t<F_>>>::value, int> = 0>
+    CurvedSurfaceGrid (HostGrid& hostGrid, F_&& callable, std::integral_constant<int,ORDER> = {})
+      : CurvedSurfaceGrid(hostGrid, analyticGridFunction<HostGrid>(std::forward<F_>(callable)))
+    {}
+
+    //! destructor
     ~CurvedSurfaceGrid ()
     {
-      for(auto &mapEntry : std::get<0>(geometryCache_)) delete mapEntry.second;
-      for(auto &mapEntry : std::get<1>(geometryCache_)) delete mapEntry.second;
-      for(auto &mapEntry : std::get<2>(geometryCache_)) delete mapEntry.second;
-
-      for( unsigned int i = 0; i < levelIndexSets_.size(); ++i )
+      for (unsigned int i = 0; i < levelIndexSets_.size(); ++i)
       {
-        if( levelIndexSets_[ i ] )
-          delete( levelIndexSets_[ i ] );
-      }
-
-      if( removeHostGrid_ )
-      {
-        delete coordFunction_;
-        delete hostGrid_;
+        if (levelIndexSets_[i])
+          delete (levelIndexSets_[i]);
       }
     }
 
@@ -290,8 +250,8 @@ namespace Dune
     /** \name Size Methods
      *  \{ */
 
-    /** \brief obtain maximal grid level
-     *
+    //! obtain maximal grid level
+    /**
      *  Grid levels are numbered 0, ..., L, where L is the value returned by
      *  this method.
      *
@@ -302,116 +262,112 @@ namespace Dune
       return hostGrid().maxLevel();
     }
 
-    /** \brief obtain number of entites on a level
-     *
+    //! obtain number of entites on a level
+    /**
      *  \param[in]  level  level to consider
      *  \param[in]  codim  codimension to consider
      *
-     *  \returns number of entities of codimension \em codim on grid level
-     *           \em level.
+     *  \returns number of entities of codimension `codim` on grid level `level`.
      */
-    int size ( int level, int codim ) const
+    int size (int level, int codim) const
     {
-      return levelGridView( level ).size( codim );
+      return levelGridView(level).size(codim);
     }
 
-    /** \brief obtain number of leaf entities
-     *
+    //! obtain number of leaf entities
+    /**
      *  \param[in]  codim  codimension to consider
      *
      *  \returns number of leaf entities of codimension \em codim
      */
-    int size ( int codim ) const
+    int size (int codim) const
     {
-      return leafGridView().size( codim );
+      return leafGridView().size(codim);
     }
 
-    /** \brief obtain number of entites on a level
-     *
+    //! obtain number of entites on a level
+    /**
      *  \param[in]  level  level to consider
      *  \param[in]  type   geometry type to consider
      *
-     *  \returns number of entities with a geometry of type \em type on grid
-     *           level \em level.
+     *  \returns number of entities with a geometry of type `type` on grid level `level`.
      */
-    int size ( int level, GeometryType type ) const
+    int size (int level, GeometryType type) const
     {
-      return levelGridView( level ).size( type );
+      return levelGridView(level).size(type);
     }
 
-    /** \brief obtain number of leaf entities
-     *
-     *  \returns number of leaf entities with a geometry of type \em type
+    //! obtain number of leaf entities
+    /**
+     *  \returns number of leaf entities with a geometry of type `type`
      */
-    int size ( GeometryType type ) const
+    int size (GeometryType type) const
     {
-      return leafGridView().size( type );
+      return leafGridView().size(type);
     }
 
-    /** \brief returns the number of boundary segments within the macro grid
-     *
+    //! returns the number of boundary segments within the macro grid
+    /**
      *  \returns number of boundary segments within the macro grid
      */
-    size_t numBoundarySegments () const
+    std::size_t numBoundarySegments () const
     {
-      return hostGrid().numBoundarySegments( );
+      return hostGrid().numBoundarySegments();
     }
     /** \} */
 
-    const GlobalIdSet &globalIdSet () const
+    const GlobalIdSet& globalIdSet () const
     {
-      if( !globalIdSet_ )
-        globalIdSet_ = GlobalIdSet( hostGrid().globalIdSet() );
-      assert( globalIdSet_ );
+      if (!globalIdSet_)
+        globalIdSet_ = GlobalIdSet(hostGrid().globalIdSet());
+      assert(globalIdSet_);
       return globalIdSet_;
     }
 
-    const LocalIdSet &localIdSet () const
+    const LocalIdSet& localIdSet () const
     {
-      if( !localIdSet_ )
-        localIdSet_ = LocalIdSet( hostGrid().localIdSet() );
-      assert( localIdSet_ );
+      if (!localIdSet_)
+        localIdSet_ = LocalIdSet(hostGrid().localIdSet());
+      assert(localIdSet_);
       return localIdSet_;
     }
 
-    const LevelIndexSet &levelIndexSet ( int level ) const
+    const LevelIndexSet& levelIndexSet (int level) const
     {
-      assert( levelIndexSets_.size() == (size_t)(maxLevel()+1) );
-      if( (level < 0) || (level > maxLevel()) )
-      {
-        DUNE_THROW( GridError, "LevelIndexSet for nonexisting level " << level
-                                                                      << " requested." );
-      }
+      assert(levelIndexSets_.size() == (size_t)(maxLevel()+1));
+
+      if ((level < 0) || (level > maxLevel()))
+        DUNE_THROW(GridError, "LevelIndexSet for nonexisting level " << level << " requested.");
 
-      LevelIndexSet *&levelIndexSet = levelIndexSets_[ level ];
-      if( !levelIndexSet )
-        levelIndexSet = new LevelIndexSet( hostGrid().levelIndexSet( level ) );
-      assert( levelIndexSet );
+      LevelIndexSet*& levelIndexSet = levelIndexSets_[level];
+      if (!levelIndexSet)
+        levelIndexSet = new LevelIndexSet(hostGrid().levelIndexSet(level));
+      assert(levelIndexSet);
       return *levelIndexSet;
     }
 
-    const LeafIndexSet &leafIndexSet () const
+    const LeafIndexSet& leafIndexSet () const
     {
-      if( !leafIndexSet_ )
-        leafIndexSet_.reset( hostGrid().leafIndexSet() );
-      assert( leafIndexSet_ );
+      if (!leafIndexSet_)
+        leafIndexSet_.reset(hostGrid().leafIndexSet());
+      assert(leafIndexSet_);
       return leafIndexSet_;
     }
 
-    void globalRefine ( int refCount )
+    void globalRefine (int refCount)
     {
-      hostGrid().globalRefine( refCount );
+      hostGrid().globalRefine(refCount);
       update();
     }
 
-    bool mark ( int refCount, const typename Codim< 0 >::Entity &entity )
+    bool mark (int refCount, const typename Codim<0>::Entity& entity)
     {
-      return hostGrid().mark( refCount, getHostEntity< 0 >( entity ) );
+      return hostGrid().mark(refCount, getHostEntity<0>(entity));
     }
 
-    int getMark ( const typename Codim< 0 >::Entity &entity ) const
+    int getMark (const typename Codim<0>::Entity& entity) const
     {
-      return hostGrid().getMark( getHostEntity< 0 >( entity ) );
+      return hostGrid().getMark(getHostEntity<0>(entity));
     }
 
     bool preAdapt ()
@@ -434,24 +390,23 @@ namespace Dune
     /** \name Parallel Data Distribution and Communication Methods
      *  \{ */
 
-    /** \brief obtain CollectiveCommunication object
-     *
+    //! obtain CollectiveCommunication object
+    /**
      *  The CollectiveCommunication object should be used to globally
      *  communicate information between all processes sharing this grid.
      *
      *  \note The CollectiveCommunication object returned is identical to the
      *        one returned by the host grid.
      */
-    const CollectiveCommunication &comm () const
+    const CollectiveCommunication& comm () const
     {
       return hostGrid().comm();
     }
 
-#if 0
     // data handle interface different between geo and interface
 
-    /** \brief rebalance the load each process has to handle
-     *
+    //! rebalance the load each process has to handle
+    /**
      *  A parallel grid is redistributed such that each process has about
      *  the same load (e.g., the same number of leaf entites).
      *
@@ -461,14 +416,14 @@ namespace Dune
      */
     bool loadBalance ()
     {
-      const bool gridChanged= hostGrid().loadBalance();
-      if( gridChanged )
+      const bool gridChanged = hostGrid().loadBalance();
+      if (gridChanged)
         update();
       return gridChanged;
     }
 
-    /** \brief rebalance the load each process has to handle
-     *
+    //! rebalance the load each process has to handle
+    /**
      *  A parallel grid is redistributed such that each process has about
      *  the same load (e.g., the same number of leaf entites).
      *
@@ -483,44 +438,29 @@ namespace Dune
      */
 
     template< class DataHandle, class Data >
-    bool loadBalance ( CommDataHandleIF< DataHandle, Data > &datahandle )
+    bool loadBalance (CommDataHandleIF<DataHandle, Data>& datahandle)
     {
-      typedef CommDataHandleIF< DataHandle, Data > DataHandleIF;
-      typedef crvsrf::CommDataHandle< Grid, DataHandleIF > WrappedDataHandle;
+      using DataHandleIF = CommDataHandleIF<DataHandle, Data>;
+      using WrappedDataHandle = Curved::CommDataHandle<Self, DataHandleIF>;
 
-      WrappedDataHandle wrappedDataHandle( *this, datahandle );
-      const bool gridChanged = hostGrid().loadBalance( wrappedDataHandle );
-      if( gridChanged )
+      WrappedDataHandle wrappedDataHandle(*this, datahandle);
+      const bool gridChanged = hostGrid().loadBalance(wrappedDataHandle);
+      if (gridChanged)
         update();
       return gridChanged;
     }
-#endif
 
-    /** \brief obtain Entity from EntitySeed
-     *
+    //! obtain Entity from EntitySeed
+    /**
      *  EntitySeed survives to a grid modification which only changes the grid coordinates.
-     *  Therefore it is consistent to use an EntitySeed to rebuild an Entity after this kind of grid modification.
-     *
-     *  An example of this is given by the following code:
-        \code
-        // store seed of the first entity in the leaf view
-        const auto& gv = grid.leafGridView();
-        const auto& entity = (*(gv.template begin<0>()));
-        auto seed = entity.seed();
-
-        // perform a grid modification
-        grid.coordFunction().setTime(t);
-
-        // rebuild first entity from the seed
-        const auto& newEntity = grid.entity(seed);
-        \endcode
+     *  Therefore it is consistent to use an EntitySeed to rebuild an Entity after this kind
+     *  of grid modification.
      */
     template< class EntitySeed >
-    typename Traits::template Codim< EntitySeed::codimension >::Entity
-    entity ( const EntitySeed &seed ) const
+    typename Traits::template Codim<EntitySeed::codimension>::Entity entity (const EntitySeed& seed) const
     {
-      typedef typename Traits::template Codim< EntitySeed::codimension >::EntityImpl EntityImpl;
-      return EntityImpl( *this, seed );
+      using EntityImpl = typename Traits::template Codim<EntitySeed::codimension>::EntityImpl;
+      return EntityImpl(*this, seed);
     }
 
     /** \} */
@@ -528,18 +468,18 @@ namespace Dune
     /** \name Grid Views
      *  \{ */
 
-    /** \brief View for a grid level */
-    LevelGridView levelGridView ( int level ) const
+    //! View for a grid level
+    LevelGridView levelGridView (int level) const
     {
-      typedef typename LevelGridView::GridViewImp ViewImp;
-      return LevelGridView( ViewImp( *this, hostGrid().levelGridView( level ) ) );
+      using ViewImp = typename LevelGridView::GridViewImp;
+      return LevelGridView(ViewImp(*this, hostGrid().levelGridView(level)));
     }
 
-    /** \brief View for the leaf grid */
+    //! View for the leaf grid
     LeafGridView leafGridView () const
     {
-      typedef typename LeafGridView::GridViewImp ViewImp;
-      return LeafGridView( ViewImp( *this, hostGrid().leafGridView() ) );
+      using ViewImp = typename LeafGridView::GridViewImp;
+      return LeafGridView(ViewImp(*this, hostGrid().leafGridView()));
     }
 
     /** \} */
@@ -547,20 +487,20 @@ namespace Dune
     /** \name Miscellaneous Methods
      *  \{ */
 
-    /** \brief obtain constant reference to the host grid */
-    const HostGrid &hostGrid () const
+    //! obtain constant reference to the host grid
+    const HostGrid& hostGrid () const
     {
-      return *hostGrid_;
+      return hostGrid_;
     }
 
-    /** \brief obtain mutable reference to the host grid */
-    HostGrid &hostGrid ()
+    //! obtain mutable reference to the host grid
+    HostGrid& hostGrid ()
     {
-      return *hostGrid_;
+      return hostGrid_;
     }
 
-    /** \brief update grid caches
-     *
+    //! update grid caches
+    /**
      *  This method has to be called whenever the underlying host grid changes.
      *
      *  \note If you adapt the host grid through this geometry grid's
@@ -570,75 +510,92 @@ namespace Dune
     void update ()
     {
       // adapt the coordinate function
-      GeoGrid::AdaptCoordFunction< typename CoordFunction::Interface >::adapt( coordFunction() );
+      // GeoGrid::AdaptCoordFunction<typename CoordFunction::Interface>::adapt(coordFunction());
 
       const int newNumLevels = maxLevel()+1;
       const int oldNumLevels = levelIndexSets_.size();
 
-      for( int i = newNumLevels; i < oldNumLevels; ++i )
+      for (int i = newNumLevels; i < oldNumLevels; ++i)
       {
-        if( levelIndexSets_[ i ] )
-          delete levelIndexSets_[ i ];
+        if (levelIndexSets_[i])
+          delete levelIndexSets_[i];
       }
-      levelIndexSets_.resize( newNumLevels, nullptr );
+      levelIndexSets_.resize(newNumLevels, nullptr);
     }
 
-    /** \brief obtain constant reference to the coordinate function */
-    const CoordFunction &coordFunction () const { return *coordFunction_; }
-
-    /** \brief obtain mutable reference to the coordinate function. */
-    CoordFunction &coordFunction () { return *coordFunction_; }
+    //! obtain constant reference to the coordinate function
+    GridFunction const& gridFunction () const 
+    { 
+      return *gridFunction_; 
+    }
 
-    /** \} */
+    GridFunction& gridFunction () 
+    { 
+      return *gridFunction_; 
+    }
 
-  protected:
-    template< int codim >
-    static const typename HostGrid::template Codim< codim >::Entity &
-    getHostEntity( const typename Codim< codim >::Entity &entity )
+    bool useGeometryCaching () const
     {
-      return entity.impl().hostEntity();
+      return useGeometryCaching_;
     }
 
-    void *allocateStorage ( std::size_t size ) const
+    void setGeometryCaching (bool cache)
     {
-      return storageAllocator_.allocate( size );
+      useGeometryCaching_ = cache;
     }
 
-    void deallocateStorage ( void *p, std::size_t size ) const
+    /** \} */
+
+  protected:
+    template< int codim >
+    static const typename HostGrid::template Codim<codim>::Entity&
+    getHostEntity(const typename Codim<codim>::Entity& entity)
     {
-      storageAllocator_.deallocate( (char *)p, size );
+      return entity.impl().hostEntity();
     }
 
   private:
-    HostGrid *const hostGrid_;
-    CoordFunction *coordFunction_;
-    bool removeHostGrid_;
-    mutable std::vector< LevelIndexSet *, typename Allocator::template rebind< LevelIndexSet * >::other > levelIndexSets_;
+    HostGrid& hostGrid_;
+    std::shared_ptr<GridFunction> gridFunction_;
+
+    bool useGeometryCaching_ = false;
+
+    mutable std::vector<LevelIndexSet*> levelIndexSets_;
     mutable LeafIndexSet leafIndexSet_;
     mutable GlobalIdSet globalIdSet_;
     mutable LocalIdSet localIdSet_;
-    mutable typename Allocator::template rebind< char >::other storageAllocator_;
-    #if GEO_CACHE_BENCHMARK != 0
-      mutable int geo_cached_internal = 0;
-      mutable int geo_cached_external = 0;
-      mutable int geo_uncached = 0;
-    #endif
-    mutable std::tuple< std::map< typename HostGrid::Traits::LocalIdSet::IdType,
-                            typename Traits::template Codim<0>::GeometryImpl* >,
-                        std::map< typename HostGrid::Traits::LocalIdSet::IdType,
-                            typename Traits::template Codim<1>::GeometryImpl* >,
-                        std::map< typename HostGrid::Traits::LocalIdSet::IdType,
-                            typename Traits::template Codim<2>::GeometryImpl* > > geometryCache_;
+
+  private:
+    template <class Indices>
+    struct GeometryCache;
+
+    template <int... codims>
+    struct GeometryCache<std::integer_sequence<int,codims...>>
+    {
+      using type = std::tuple<
+        std::map<
+          typename HostGrid::Traits::LocalIdSet::IdType,
+          typename Traits::template Codim<codims>::GeometryImpl
+        >...
+      >;
+    };
+
+    mutable typename GeometryCache<std::make_integer_sequence<int,Traits::dimension+1>>::type geometryCache_;
   };
 
+  //! Deduction guide for CurvedSurfaceGrid from a grid-functions or callables
+  template< class HostGrid, class GF, int ORDER = -1 >
+  CurvedSurfaceGrid (HostGrid& hostGrid, GF&& gridFunction, std::integral_constant<int,ORDER> = {}) 
+    -> CurvedSurfaceGrid<GridFunctionOf_t<HostGrid,std::decay_t<GF>>,ORDER>;
+
 
   // CurvedSurfaceGrid::Codim
   // ------------------------
 
-  template< class HostGrid, class CoordFunction, int order, bool geoCaching, class Allocator >
+  template< class GridFunction, int ORDER >
   template< int codim >
-  struct CurvedSurfaceGrid< HostGrid, CoordFunction, order, geoCaching, Allocator >::Codim
-    : public Base::template Codim< codim >
+  struct CurvedSurfaceGrid<GridFunction,ORDER>::Codim
+    : public Super::template Codim< codim >
   {
     /** \name Entity types
      *  \{ */
@@ -647,7 +604,7 @@ namespace Dune
      *
      *  The entity is a model of Dune::Entity.
      */
-    typedef typename Traits::template Codim< codim >::Entity Entity;
+    using Entity = typename Traits::template Codim< codim >::Entity;
 
     /** \} */
 
@@ -662,7 +619,7 @@ namespace Dune
      *  The geometry is a model of Dune::Geometry, implemented through the
      *  generic geometries provided by dune-grid.
      */
-    typedef typename Traits::template Codim< codim >::Geometry Geometry;
+    using Geometry = typename Traits::template Codim< codim >::Geometry;
 
     /** \brief type of local geometry
      *
@@ -672,7 +629,7 @@ namespace Dune
      *  The local geometry is a model of Dune::Geometry, implemented through
      *  the generic geometries provided by dune-grid.
      */
-    typedef typename Traits::template Codim< codim >::LocalGeometry LocalGeometry;
+    using LocalGeometry = typename Traits::template Codim< codim >::LocalGeometry;
 
     /** \} */
 
@@ -682,12 +639,10 @@ namespace Dune
     template< PartitionIteratorType pitype >
     struct Partition
     {
-      typedef typename Traits::template Codim< codim >
-      ::template Partition< pitype >::LeafIterator
-      LeafIterator;
-      typedef typename Traits::template Codim< codim >
-      ::template Partition< pitype >::LevelIterator
-      LevelIterator;
+      using LeafIterator
+        = typename Traits::template Codim<codim>::template Partition< pitype >::LeafIterator;
+      using LevelIterator
+        = typename Traits::template Codim<codim>::template Partition< pitype >::LevelIterator;
     };
 
     /** \brief type of leaf iterator
@@ -697,7 +652,7 @@ namespace Dune
      *
      *  The level iterator is a model of Dune::LevelIterator.
      */
-    typedef typename Partition< All_Partition >::LeafIterator LeafIterator;
+    using LeafIterator = typename Partition< All_Partition >::LeafIterator;
 
     /** \brief type of level iterator
      *
@@ -706,11 +661,11 @@ namespace Dune
      *
      *  The leaf iterator is a model of Dune::LeafIterator.
      */
-    typedef typename Partition< All_Partition >::LevelIterator LevelIterator;
+    using LevelIterator = typename Partition< All_Partition >::LevelIterator;
 
     /** \} */
   };
 
 } // namespace Dune
 
-#endif // #ifndef DUNE_CRVSRF_GRID_HH
+#endif // DUNE_CURVED_SURFACE_GRID_GRID_HH
diff --git a/dune/curvedsurfacegrid/gridfamily.hh b/dune/curvedsurfacegrid/gridfamily.hh
index e3a621902a5cdcd67f2a0734b5982a3d4e412a77..46e017a3b81dfa8bf9b5a80c9991d3999a736181 100644
--- a/dune/curvedsurfacegrid/gridfamily.hh
+++ b/dune/curvedsurfacegrid/gridfamily.hh
@@ -1,7 +1,9 @@
 // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
 // vi: set et ts=4 sw=2 sts=2:
-#ifndef DUNE_CRVSRF_GRIDFAMILY_HH
-#define DUNE_CRVSRF_GRIDFAMILY_HH
+#ifndef DUNE_CURVED_SURFACE_GRID_GRIDFAMILY_HH
+#define DUNE_CURVED_SURFACE_GRID_GRIDFAMILY_HH
+
+#include <type_traits>
 
 #include <dune/grid/common/grid.hh>
 #include <dune/curvedsurfacegrid/capabilities.hh>
@@ -14,106 +16,134 @@
 #include <dune/curvedsurfacegrid/iterator.hh>
 #include <dune/curvedsurfacegrid/idset.hh>
 #include <dune/curvedsurfacegrid/indexsets.hh>
+#include <dune/curvedsurfacegrid/localgeometrywrapper.hh>
+#include <dune/curvedsurfacegrid/gridfunctions/gridfunction.hh>
+
+#include <dune/functions/common/functionconcepts.hh>
+#include <dune/functions/common/signature.hh>
+#include <dune/functions/gridfunctions/localderivativetraits.hh>
 
 namespace Dune
 {
 
   /** \brief namespace containing the implementations of CurvedSurfaceGrid
-   *  \ingroup crvsrf
+   *  \ingroup CurvedGeo
    */
-  namespace crvsrf
+  namespace Curved
   {
-
-    // ExportParams
-    // ------------
-
-    template< class HG, class CF >
-    class ExportParams
+    template< class GF >
+    struct DimRange
     {
-      static const bool isCoordFunction = GeoGrid::isCoordFunctionInterface< typename CF::Interface >::value;
-      static_assert(isCoordFunction, "Invalid CoordFunction.");
-
-    public:
-      typedef HG HostGrid;
-      typedef CF CoordFunction;
+      using SigTraits = Functions::SignatureTraits<GF>;
+      using Range = typename SigTraits::RawRange;
+      static const int value = Range::size();
     };
 
+    template< class GF, class LF >
+    struct DifferentiableLocalFunction
+    {
+      using EntitySet = typename GF::EntitySet;
+      using LocalContext = typename EntitySet::Element;
 
+      using Range = typename Functions::SignatureTraits<GF>::Range;
+      using LocalSignature = Range(typename EntitySet::LocalCoordinate);
+
+      static const bool value = Functions::Concept::isDifferentiableLocalFunction<LF,LocalSignature,LocalContext,Functions::LocalDerivativeTraits<EntitySet>::template Traits>();
+    };
 
     // GridFamily
     // ----------
 
-    template< class HG, class CF, int order, bool geoCaching, class Allocator >
+    template< class GF, int order >
     struct GridFamily
     {
       struct Traits
       {
-        typedef CurvedSurfaceGrid< HG, CF, order, geoCaching, Allocator > Grid;
+        using Grid = CurvedSurfaceGrid<GF,order>;
+        using HostGrid = GridOf_t<GF>;
+
+        using GridFunction = GF;
+        using LocalFunction = std::decay_t<decltype(localFunction(std::declval<GF const&>()))>;
 
-        typedef HG HostGrid;
-        typedef CF CoordFunction;
+        static const bool differentiableLocalFunction = DifferentiableLocalFunction<GF, LocalFunction>::value;
+        static_assert((differentiableLocalFunction || order>0), "Either provide a differentiable GridFunction or set ORDER > 0");
 
-        typedef typename HostGrid::ctype ctype;
+        using ctype = typename HostGrid::ctype;
 
         static const int dimension = HostGrid::dimension;
-        static const int dimensionworld = CoordFunction::dimRange;
+        static const int dimensionworld = DimRange<GridFunction>::value;
 
-        typedef Dune::Intersection< const Grid, crvsrf::Intersection< const Grid, typename HostGrid::LeafIntersection > > LeafIntersection;
-        typedef Dune::Intersection< const Grid, crvsrf::Intersection< const Grid, typename HostGrid::LevelIntersection > > LevelIntersection;
+        using LeafIntersection
+          = Dune::Intersection<const Grid, Curved::Intersection<const Grid, typename HostGrid::LeafIntersection>>;
+        using LevelIntersection
+          = Dune::Intersection<const Grid, Curved::Intersection<const Grid, typename HostGrid::LevelIntersection>>;
 
-        typedef Dune::IntersectionIterator
-        < const Grid, crvsrf::IntersectionIterator< const Grid, typename HostGrid::LeafIntersectionIterator >, crvsrf::Intersection< const Grid, typename HostGrid::LeafIntersection > >
-        LeafIntersectionIterator;
-        typedef Dune::IntersectionIterator
-        < const Grid, crvsrf::IntersectionIterator< const Grid, typename HostGrid::LevelIntersectionIterator >, crvsrf::Intersection< const Grid, typename HostGrid::LevelIntersection > >
-        LevelIntersectionIterator;
+        using LeafIntersectionIterator
+          = Dune::IntersectionIterator<const Grid, Curved::IntersectionIterator<const Grid, typename HostGrid::LeafIntersectionIterator>, Curved::Intersection<const Grid, typename HostGrid::LeafIntersection> >;
+        using LevelIntersectionIterator
+          = Dune::IntersectionIterator<const Grid, Curved::IntersectionIterator<const Grid, typename HostGrid::LevelIntersectionIterator >, Curved::Intersection<const Grid, typename HostGrid::LevelIntersection> >;
 
-        typedef Dune::EntityIterator< 0, const Grid, crvsrf::HierarchicIterator< const Grid > >
-        HierarchicIterator;
+        using HierarchicIterator
+          = Dune::EntityIterator<0, const Grid, Curved::HierarchicIterator<const Grid>>;
 
         template< int codim >
         struct Codim
         {
-          typedef Dune::crvsrf::Geometry< dimension-codim, dimensionworld, const Grid > GeometryImpl;
-          typedef Dune::Geometry< dimension-codim, dimensionworld, const Grid, Dune::crvsrf::Geometry > Geometry;
-          typedef typename HostGrid::template Codim< codim >::LocalGeometry LocalGeometry;
+          using LocalGeometry = typename HostGrid::template Codim<codim>::LocalGeometry;
+
+          using LocalTransformation = std::conditional_t<(codim == 0),
+            DefaultLocalGeometry<ctype, dimension, dimension>,
+            Curved::LocalGeometryWrapper<LocalGeometry>>;
 
-          typedef crvsrf::Entity< codim, dimension, const Grid > EntityImpl;
-          typedef Dune::Entity< codim, dimension, const Grid, crvsrf::Entity > Entity;
+          template < int mydim, int cdim, class GridImpl >
+          using GeometryImplTemplate
+            = Curved::Geometry<ctype, mydim, cdim, LocalFunction, LocalTransformation, order>;
 
-          typedef Dune::EntitySeed< const Grid, crvsrf::EntitySeed< codim, const Grid > > EntitySeed;
+          // geometry types
+          using GeometryImpl = GeometryImplTemplate<dimension-codim, dimensionworld, const Grid>;
+          using Geometry = Dune::Geometry<dimension-codim, dimensionworld, const Grid, GeometryImplTemplate>;
+
+          // entity types
+          using EntityImpl = Curved::Entity<codim, dimension, const Grid>;
+          using Entity = Dune::Entity<codim, dimension, const Grid, Curved::Entity>;
+
+          using EntitySeed = Dune::EntitySeed<const Grid, Curved::EntitySeed<codim, const Grid> >;
 
           template< PartitionIteratorType pitype >
           struct Partition
           {
-            typedef crvsrf::Iterator< typename HostGrid::LeafGridView, codim, pitype, const Grid > LeafIteratorImp;
-            typedef Dune::EntityIterator< codim, const Grid, LeafIteratorImp > LeafIterator;
+            using LeafIteratorImp
+              = Curved::Iterator<typename HostGrid::LeafGridView, codim, pitype, const Grid>;
+            using LeafIterator = Dune::EntityIterator<codim, const Grid, LeafIteratorImp>;
 
-            typedef crvsrf::Iterator< typename HostGrid::LevelGridView, codim, pitype, const Grid > LevelIteratorImp;
-            typedef Dune::EntityIterator< codim, const Grid, LevelIteratorImp > LevelIterator;
+            using LevelIteratorImp
+              = Curved::Iterator<typename HostGrid::LevelGridView, codim, pitype, const Grid>;
+            using LevelIterator = Dune::EntityIterator<codim, const Grid, LevelIteratorImp>;
           };
 
-          typedef typename Partition< All_Partition >::LeafIterator LeafIterator;
-          typedef typename Partition< All_Partition >::LevelIterator LevelIterator;
+          using LeafIterator = typename Partition< All_Partition >::LeafIterator;
+          using LevelIterator = typename Partition< All_Partition >::LevelIterator;
         };
 
-        typedef crvsrf::IndexSet< const Grid, typename HostGrid::Traits::LeafIndexSet > LeafIndexSet;
-        typedef crvsrf::IndexSet< const Grid, typename HostGrid::Traits::LevelIndexSet > LevelIndexSet;
+        // index-sets
+        using LeafIndexSet = Curved::IndexSet<const Grid, typename HostGrid::Traits::LeafIndexSet>;
+        using LevelIndexSet = Curved::IndexSet<const Grid, typename HostGrid::Traits::LevelIndexSet>;
 
-        typedef crvsrf::IdSet< const Grid, typename HostGrid::Traits::GlobalIdSet >
-        GlobalIdSet;
-        typedef crvsrf::IdSet< const Grid, typename HostGrid::Traits::LocalIdSet >
-        LocalIdSet;
+        // id-sets
+        using GlobalIdSet = Curved::IdSet<const Grid, typename HostGrid::Traits::GlobalIdSet>;
+        using LocalIdSet = Curved::IdSet<const Grid, typename HostGrid::Traits::LocalIdSet>;
 
-        typedef typename HostGrid::Traits::CollectiveCommunication CollectiveCommunication;
+        using CollectiveCommunication = typename HostGrid::Traits::CollectiveCommunication;
 
-        typedef Dune::GridView< crvsrf::GridViewTraits< typename HostGrid::LeafGridView, CoordFunction, order, geoCaching,  Allocator > > LeafGridView;
-        typedef Dune::GridView< crvsrf::GridViewTraits< typename HostGrid::LevelGridView, CoordFunction, order, geoCaching, Allocator > > LevelGridView;
+        // grid views
+        using LeafGridView
+          = Dune::GridView<Curved::GridViewTraits<typename HostGrid::LeafGridView, GF, order>>;
+        using LevelGridView
+          = Dune::GridView<Curved::GridViewTraits<typename HostGrid::LevelGridView, GF, order>>;
       };
     };
 
-  } // namespace crvsrf
-
+  } // namespace Curved
 } // namespace Dune
 
-#endif // #ifndef DUNE_CRVSRF_GRIDFAMILY_HH
+#endif // DUNE_CURVED_SURFACE_GRID_GRIDFAMILY_HH
diff --git a/dune/curvedsurfacegrid/gridfunctions/CMakeLists.txt b/dune/curvedsurfacegrid/gridfunctions/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..4f35979cc7e3e2e06d56adf08ae145f8b1019d5f
--- /dev/null
+++ b/dune/curvedsurfacegrid/gridfunctions/CMakeLists.txt
@@ -0,0 +1,9 @@
+install(FILES 
+  analyticgridfunction.hh
+  discretegridviewfunction.hh
+  gridentityset.hh
+  gridfunction.hh
+  normalgridviewfunction.hh
+  spheregridfunction.hh
+  torusgridfunction.hh
+  DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/curvedsurfacegrid/gridfunctions)
diff --git a/dune/curvedsurfacegrid/gridfunctions/analyticgridfunction.hh b/dune/curvedsurfacegrid/gridfunctions/analyticgridfunction.hh
new file mode 100644
index 0000000000000000000000000000000000000000..cbdeaaf8226397e8f1663d7ea40bb7a80428b424
--- /dev/null
+++ b/dune/curvedsurfacegrid/gridfunctions/analyticgridfunction.hh
@@ -0,0 +1,204 @@
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+#ifndef DUNE_CURVED_SURFACE_GRID_ANALYTIC_GRIDFUNCTION_HH
+#define DUNE_CURVED_SURFACE_GRID_ANALYTIC_GRIDFUNCTION_HH
+
+#include <type_traits>
+#include <utility>
+
+#include <dune/common/typeutilities.hh>
+#include <dune/common/std/optional.hh>
+
+#include "gridentityset.hh"
+
+namespace Dune
+{
+  //! LocalFunction associated to the \ref AnalyticGridFunction
+  /**
+   * \tparam LocalContext  Context this localFunction can be bound to, e.g. a grid element
+   * \tparam F             Type of a function that can be evaluated in global coordinates.
+   **/
+  template< class LocalContext, class F >
+  class LocalAnalyticGridFunction;
+
+  //! Generator for \ref LocalAnalyticGridFunction
+  /**
+   * \param  ff            Function that can be evaluated at global coordinates of the \ref LocalContext
+   * \tparam LocalContext  Context this localFunction can be bound to, e.g. a grid element
+   **/
+  template< class LocalContext, class FF >
+  auto localAnalyticGridFunction (FF&& ff)
+  {
+    using F = std::decay_t<FF>;
+    return LocalAnalyticGridFunction<LocalContext, F>{std::forward<FF>(ff)};
+  }
+
+
+  template< class LC, class Functor >
+  class LocalAnalyticGridFunction
+  {
+  public:
+    using LocalContext = LC;
+    using Geometry = typename LocalContext::Geometry;
+
+    using Domain = typename Geometry::GlobalCoordinate;
+    using LocalDomain = typename Geometry::LocalCoordinate;
+    using Range = std::result_of_t<Functor(Domain)>;
+    using Signature = Range(LocalDomain);
+
+  public:
+    //! Constructor. Stores the functor f by value
+    template< class FF,
+      disableCopyMove<LocalAnalyticGridFunction, FF> = 0>
+    LocalAnalyticGridFunction (FF&& f)
+      : f_(std::forward<FF>(f))
+    {}
+
+    //! bind the LocalFunction to the local context
+    /**
+     * Stores the localContext and its geometry in a cache variable
+     **/
+    void bind (const LocalContext& localContext)
+    {
+      localContext_.emplace(localContext);
+      geometry_.emplace(localContext.geometry());
+    }
+
+    //! unbind the localContext from the localFunction
+    /**
+     * Reset the geometry
+     **/
+    void unbind ()
+    {
+      geometry_.reset();
+      localContext_.reset();
+    }
+
+    //! evaluate the stored function in local coordinates
+    /**
+     * Transform the local coordinates to global coordinates first,
+     * then evalute the stored functor.
+     **/
+    Range operator() (const LocalDomain& x) const
+    {
+      assert(!!geometry_);
+      return f_(geometry_->global(x));
+    }
+
+    //! return the bound localContext.
+    const LocalContext& localContext () const
+    {
+      assert(!!localContext_);
+      return *localContext_;
+    }
+
+    //! obtain the functor
+    const Functor& f () const
+    {
+      return f_;
+    }
+
+  private:
+    Functor f_;
+
+    // some caches
+    Std::optional<LocalContext> localContext_;
+    Std::optional<Geometry> geometry_;
+  };
+
+  //! Derivative of a \ref LocalAnalyticGridFunction
+  /**
+   * Participates in overload resolution only if the functor `F` is differentiable
+   **/
+  template< class LC, class F >
+  auto derivative (const LocalAnalyticGridFunction<LC,F>& t)
+    -> decltype(localAnalyticGridFunction<LC>(derivative(t.f())))
+  {
+    return localAnalyticGridFunction<LC>(derivative(t.f()));
+  }
+
+
+  //! GridFunction associated to the mapping F
+  /**
+   * \tparam Grid       The grid type with elements the corresponding LocalFunction can be bound to
+   * \tparam F          Type of a function that can be evaluated in global coordinates.
+   **/
+  template< class Grid, class F >
+  class AnalyticGridFunction;
+
+  //! Generator for \ref AnalyticGridFunction
+  /**
+   * \param  ff    Function that can be evaluated at global coordinates of the \ref Grid
+   * \tparam Grid  The grid type with elements the corresponding LocalFunction can be bound to
+   **/
+  template< class Grid, class FF >
+  auto analyticGridFunction (FF&& ff)
+  {
+    using F = std::decay_t<FF>;
+    return AnalyticGridFunction<Grid, F>{std::forward<FF>(ff)};
+  }
+
+
+  template< class GridType, class Functor >
+  class AnalyticGridFunction
+  {
+  public:
+    using Grid = GridType;
+    using EntitySet = GridEntitySet<Grid,0>;
+
+    using Domain = typename EntitySet::GlobalCoordinate;
+    using Range = std::result_of_t<Functor(Domain)>;
+    using Signature = Range(Domain);
+
+  public:
+    //! Constructor. Stores the functor f by value
+    template< class FF,
+      disableCopyMove<AnalyticGridFunction, FF> = 0>
+    AnalyticGridFunction (FF&& f)
+      : f_(std::forward<FF>(f))
+    {}
+
+    //! evaluate the stored function in global coordinates
+    Range operator() (const Domain& x) const
+    {
+      return f_(x);
+    }
+
+    //! construct the \ref LocalAnalyticGridFunction
+    using LocalFunction = LocalAnalyticGridFunction<typename EntitySet::Element, Functor>;
+    friend LocalFunction localFunction (const AnalyticGridFunction& t)
+    {
+      return LocalFunction(t.f_);
+    }
+
+    //! obtain the stored \ref GridEntitySet
+    const EntitySet& entitySet () const
+    {
+      return entitySet_;
+    }
+
+    //! obtain the functor
+    const Functor& f () const
+    {
+      return f_;
+    }
+
+  private:
+    Functor f_;
+    EntitySet entitySet_;
+  };
+
+  //! Derivative of an \ref AnalyticGridFunction
+  /**
+   * Participates in overload resolution only if the functor `F` is differentiable
+   **/
+  template< class Grid, class F >
+  auto derivative (const AnalyticGridFunction<Grid,F>& t)
+    -> decltype(analyticGridFunction<Grid>(derivative(t.f())))
+  {
+    return analyticGridFunction<Grid>(derivative(t.f()));
+  }
+
+} // end namespace Dune
+
+#endif // DUNE_CURVED_SURFACE_GRID_ANALYTIC_GRIDFUNCTION_HH
diff --git a/dune/curvedsurfacegrid/gridfunctions/discretegridviewfunction.hh b/dune/curvedsurfacegrid/gridfunctions/discretegridviewfunction.hh
new file mode 100644
index 0000000000000000000000000000000000000000..bf291c3b4cd6f5f92d3315af6e3fbf7d3674ac55
--- /dev/null
+++ b/dune/curvedsurfacegrid/gridfunctions/discretegridviewfunction.hh
@@ -0,0 +1,297 @@
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+#ifndef DUNE_CURVED_SURFACE_GRID_DISCRETE_GRIDVIEWFUNCTION_HH
+#define DUNE_CURVED_SURFACE_GRID_DISCRETE_GRIDVIEWFUNCTION_HH
+
+#include <array>
+#include <vector>
+
+#include <dune/common/fvector.hh>
+#include <dune/functions/backends/istlvectorbackend.hh>
+#include <dune/functions/common/defaultderivativetraits.hh>
+#include <dune/functions/functionspacebases/basistags.hh>
+#include <dune/functions/functionspacebases/defaultglobalbasis.hh>
+#include <dune/functions/functionspacebases/lagrangebasis.hh>
+#include <dune/functions/functionspacebases/powerbasis.hh>
+#include <dune/functions/gridfunctions/gridviewentityset.hh>
+#include <dune/functions/gridfunctions/localderivativetraits.hh>
+#include <dune/grid/utility/hierarchicsearch.hh>
+#include <dune/istl/bvector.hh>
+
+
+namespace Dune
+{
+  namespace Impl
+  {
+    template <class Sig, int degree, template <class> class Traits>
+    struct DerivativeRangeType;
+
+    template <class R, class D, int degree, template <class> class DerivativeTraits>
+    struct DerivativeRangeType<R(D), degree, DerivativeTraits>
+    {
+      using DerivativeRange = typename DerivativeTraits<R(D)>::Range;
+      using type = typename DerivativeRangeType<DerivativeRange(D), degree-1, DerivativeTraits>::type;
+    };
+
+    template <class R, class D, template <class> class Traits>
+    struct DerivativeRangeType<R(D), 0, Traits>
+    {
+      using type = R;
+    };
+  }
+
+  //! Grid-view function representing a coordinate map from a reference grid to world
+  /**
+   * \tparam GridView   The grid-view type this coordinate function is defined on
+   * \tparam dow        Dimension of the world this coordfunction mapps into
+   * \tparam ORDER      Polynomial order of the local parametrization
+   * \tparam T          Type of the basis range-type and coefficient type
+   **/
+  template< class GridView, int dow = GridView::dimensionworld, int ORDER = -1, class T = double >
+  class DiscreteGridViewFunction;
+
+  //! Generator for \ref DiscreteGridViewFunction
+  /**
+   * \param gridView   Function that can be evaluated at global coordinates of the \ref Grid
+   * \param order      Polynomial order of the local parametrization [ORDER]
+   * 
+   * \tparam ORDER  Polynomial order of the local parametrization [-1]
+   * \tparam T      Range-type of the basis and coefficient value-type [double]
+   **/
+  template< int dow, int ORDER = -1, class T = double, class GridView >
+  auto discreteGridViewFunction (const GridView& gridView, int order = ORDER)
+  {
+    return DiscreteGridViewFunction<GridView,dow,ORDER,T>{gridView, order};
+  }
+
+
+  template< class GridView, int dow, int ORDER, class T >
+  class DiscreteGridViewFunction
+  {
+    static auto makeBasis (const GridView& gridView, int order)
+    {
+      namespace BF = Functions::BasisFactory;
+      return BF::makeBasis(gridView, BF::power<dow>(BF::lagrange<T>(order), BF::blockedInterleaved()));
+    }
+
+    using Basis = decltype(makeBasis(std::declval<GridView>(), ORDER));
+
+  public:
+    using EntitySet = Functions::GridViewEntitySet<GridView,0>;
+
+    using Domain = typename EntitySet::GlobalCoordinate;
+    using Range = FieldVector<T,dow>;
+    using Signature = Range(Domain);
+
+  private:
+    using VectorType = BlockVector<Range>;
+
+    template< int derivativeOrder = 0 >
+    class LocalFunction
+    {
+      using LocalView = typename Basis::LocalView;
+      using LocalFiniteElement = typename LocalView::Tree::ChildType::FiniteElement;
+      using LocalBasis = typename LocalFiniteElement::Traits::LocalBasisType;
+
+      template <class Sig>
+      using DerivativeTraits = typename Functions::LocalDerivativeTraits<EntitySet, Functions::DefaultDerivativeTraits>::template Traits<Sig>;
+
+    public:
+      using LocalContext = typename LocalView::Element;
+      using Geometry = typename LocalContext::Geometry;
+
+      using RangeType = typename DiscreteGridViewFunction::Range;
+
+      using Domain = typename EntitySet::LocalCoordinate;
+
+      template <int degree>
+      using DerivativeRange = typename Impl::DerivativeRangeType<RangeType(Domain), degree, DerivativeTraits>::type;
+
+      using Range = DerivativeRange<derivativeOrder>;
+      using Signature = Range(Domain);
+
+    public:
+      template <class LV>
+      LocalFunction (LV&& localView, const VectorType& coords)
+        : localView_(std::forward<LV>(localView))
+        , coords_(coords)
+      {}
+
+      //! Collect the coords from all element DOFs into a local
+      //! vector that can be accessed in the operator() for interpolation
+      void bind (const LocalContext& element)
+      {
+        localView_.bind(element);
+
+        const auto& leafNode = localView_.tree().child(0);
+        localCoords_.resize(leafNode.size());
+
+        // collect local coordinate vectors
+        for (std::size_t i = 0; i < localCoords_.size(); ++i) {
+          auto idx = localView_.index(leafNode.localIndex(i));
+          localCoords_[i] = coords_[idx[0]];
+        }
+
+        if constexpr (derivativeOrder == 1)
+          geometry_.emplace(element.geometry());
+
+        bound_ = true;
+      }
+
+      void unbind ()
+      {
+        localView_.unbind();
+        bound_ = false;
+      }
+
+      LocalContext const& localContext () const
+      {
+        assert(bound_);
+        return localView_.element();
+      }
+
+      //! Evaluate coordinates in local coordinates
+      //! by interpolation of stored coords in \ref localCoords_.
+      Range operator() (const Domain& local) const 
+      {
+        static_assert(derivativeOrder < 2, "Higher-order derivatives not implemented");
+
+        if constexpr (derivativeOrder == 0)
+          return evaluateFunction(local);
+        else if constexpr (derivativeOrder == 1)
+          return evaluateJacobian(local);
+
+        return Range(0);
+      }
+
+      friend LocalFunction<derivativeOrder+1> derivative (LocalFunction const& lf)
+      {
+        return LocalFunction<derivativeOrder+1>{lf.localView_, lf.coords_};
+      }
+
+    private:
+      DerivativeRange<0> evaluateFunction (const Domain& local) const 
+      {
+        assert(bound_);
+
+        const auto& leafNode = localView_.tree().child(0);
+        const auto& lfe = leafNode.finiteElement();
+
+        // evaluate basis functions in local coordinate
+        lfe.localBasis().evaluateFunction(local, shapeValues_);
+        assert(localCoords_.size() == shapeValues_.size());
+
+        DerivativeRange<0> x(0);
+        for (std::size_t i = 0; i < localCoords_.size(); ++i)
+          x.axpy(shapeValues_[i], localCoords_[i]);
+
+        return x;
+      }
+
+      DerivativeRange<1> evaluateJacobian (const Domain& local) const 
+      {
+        assert(bound_);
+
+        const auto& leafNode = localView_.tree().child(0);
+        const auto& lfe = leafNode.finiteElement();
+
+        // evaluate basis functions in local coordinate
+        lfe.localBasis().evaluateJacobian(local, shapeGradients_);
+        assert(localCoords_.size() == shapeGradients_.size());
+
+        // transform gradients to global coordinates
+        auto jit = geometry_->jacobianInverseTransposed(local);
+        gradients_.resize(shapeGradients_.size());
+        for (std::size_t i = 0; i < shapeGradients_.size(); ++i)
+          jit.mv(shapeGradients_[i][0], gradients_[i]);
+
+        DerivativeRange<1> J(0);
+        for (std::size_t i = 0; i < localCoords_.size(); ++i)
+          for (int j = 0; j < J.N(); ++j)
+            J[j].axpy(localCoords_[i][j], gradients_[i]);
+
+        return J;
+      }
+
+    private:
+      LocalView localView_;
+      const VectorType& coords_;
+
+      std::vector<RangeType> localCoords_;
+      Std::optional<Geometry> geometry_;
+      mutable std::vector<typename LocalBasis::Traits::RangeType> shapeValues_;
+      mutable std::vector<typename LocalBasis::Traits::JacobianType> shapeGradients_;
+      mutable std::vector<DerivativeRange<0>> gradients_;
+
+      bool bound_ = false;
+    };
+
+  public:
+    //! Constructor.
+    DiscreteGridViewFunction (const GridView& gridView, int order = (ORDER > 0 ? ORDER : 1))
+      : entitySet_(gridView)
+      , basis_(makeBasis(gridView, order))
+    {
+      update(gridView);
+    }
+
+    void update (const GridView& gridView)
+    {
+      entitySet_ = EntitySet{gridView};
+      basis_.update(gridView);
+
+      coords_.resize(basis_.size());
+    }
+
+    //! evaluate in global coordinates
+    Range operator() (const Domain& x) const
+    {
+      using Grid = typename GridView::Grid;
+      using IS = typename GridView::IndexSet;
+
+      const auto& gv = entitySet_.gridView();
+      HierarchicSearch<Grid,IS> hsearch{gv.grid(), gv.indexSet()};
+
+      auto element = hsearch.findEntity(x);
+      auto geometry = element.geometry();
+      auto localFct = localFunction(*this);
+      localFct.bind(element);
+      return localFct(geometry.local(x));
+    }
+
+    //! Create a local function of this grifunction
+    friend LocalFunction<0> localFunction (const DiscreteGridViewFunction& gf)
+    {
+      return LocalFunction<0>{gf.basis_.localView(), gf.coords_};
+    }
+
+    //! obtain the stored \ref GridViewEntitySet
+    const EntitySet& entitySet () const
+    {
+      return entitySet_;
+    }
+
+    const Basis& basis () const 
+    {
+      return basis_;
+    }
+
+    const VectorType& coefficients () const 
+    {
+      return coords_;
+    }
+
+    VectorType& coefficients ()
+    {
+      return coords_;
+    }
+
+  private:
+    EntitySet entitySet_;
+    Basis basis_;
+    VectorType coords_;
+  };
+
+} // end namespace Dune
+
+#endif // DUNE_CURVED_SURFACE_GRID_DISCRETE_GRIDVIEWFUNCTION_HH
diff --git a/dune/curvedsurfacegrid/gridfunctions/ellipsoidgridfunction.hh b/dune/curvedsurfacegrid/gridfunctions/ellipsoidgridfunction.hh
new file mode 100644
index 0000000000000000000000000000000000000000..ea8d06d62aa4a459d9fee65cb30eae4a889340de
--- /dev/null
+++ b/dune/curvedsurfacegrid/gridfunctions/ellipsoidgridfunction.hh
@@ -0,0 +1,136 @@
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+#ifndef DUNE_CURVED_SURFACE_GRID_SPHERE_GRIDFUNCTION_HH
+#define DUNE_CURVED_SURFACE_GRID_SPHERE_GRIDFUNCTION_HH
+
+#include <type_traits>
+
+#include <dune/common/math.hh>
+#include <dune/functions/common/defaultderivativetraits.hh>
+
+#include "analyticgridfunction.hh"
+
+namespace Dune
+{
+  // Ellipsoid functor
+  template< class T >
+  class EllipsoidProjection
+  {
+    T a_;
+    T b_;
+    T c_;
+
+  public:
+    //! Constructor of ellipsoid by major axes
+    EllipsoidProjection (T a, T b, T c)
+      : a_(a)
+      , b_(b)
+      , c_(c)
+    {}
+
+    //! project the coordinate to the ellipsoid
+    // NOTE: This is not a closes-point projection, but a spherical-coordinate projection
+    template< class Domain >
+    Domain operator() (const Domain& X) const
+    {
+      using std::sin; using std::cos;
+      auto [phi,theta] = angles(X);
+      return {a_*cos(phi)*sin(theta), b_*sin(phi)*sin(theta), c_*cos(theta)};
+    }
+
+    //! derivative of the projection
+    friend auto derivative (const EllipsoidProjection& ellipsoid)
+    {
+      return [a=ellipsoid.a_,b=ellipsoid.b_,c=ellipsoid.c_](auto const& X)
+      {
+        using std::sqrt;
+        using Domain = std::decay_t<decltype(X)>;
+        using DerivativeTraits = Functions::DefaultDerivativeTraits<Domain(Domain)>;
+        typename DerivativeTraits::Range out;
+
+        T x = X[0], y = X[1], z = X[2];
+        T x2 = x*x, y2 = y*y, z2 = z*z;
+        T x5 = x2*x2*x;
+
+        T nrm0 = x2 + y2;
+        T nrm1 = x2 + y2 + z2;
+        T nrm2 = sqrt(nrm0/nrm1);
+        T nrm3 = sqrt(nrm0/x2);
+        T nrm4 = sqrt(nrm1)*nrm1;
+        T nrm5 = sqrt(nrm0)*nrm4;
+
+        return {
+          {
+             a*x*nrm3*(y2 + z2)/nrm5 ,
+            -b*y*nrm0/(nrm3*nrm5) ,
+            -c*z*x/nrm4
+          },
+          {
+            -a*x2*y*nrm3/nrm5 ,
+             b*nrm0*nrm0*nrm0*(x2 + z2)/(x5*power(nrm3, 5)*nrm5) ,
+            -c*y*z/nrm4
+          },
+          {
+            -a*z*nrm0/(nrm3*nrm5) ,
+            -b*y*z*nrm0/(x*nrm3*nrm5) ,
+             c*(x2 + y2)/nrm4
+          }
+        };
+      };
+    }
+
+    //! Normal vector
+    template< class Domain >
+    Domain normal (const Domain& X) const
+    {
+      using std::sqrt;
+      T x = X[0], y = X[1], z = X[2];
+      T a2 = a_*a_, b2 = b_*b_, c2 = c_*c_;
+
+      auto div = sqrt(b2*b2*c2*c2*x*x + a2*a2*c2*c2*y*y + a2*a2*b2*b2*z*z);
+      return {b2*c2*x/div, a2*c2*y/div, a2*b2*z/div};
+    }
+    
+    //! Mean curvature
+    template< class Domain >
+    T mean_curvature (const Domain& X) const
+    {
+      using std::sqrt; using std::abs;
+      T x = X[0], y = X[1], z = X[2];
+      T a2 = a_*a_, b2 = b_*b_, c2 = c_*c_;
+
+      auto div = 2*a2*b2*c2*power(sqrt(x*x/(a2*a2) + y*y/(b2*b2) + z*z/(c2*c2)), 3);
+      return abs(x*x + y*y + z*z - a2 - b2 - c2)/div;
+    }
+
+    //! Gaussian curvature
+    template< class Domain >
+    T gauss_curvature (const Domain& X) const 
+    {
+      T x = X[0], y = X[1], z = X[2];
+      T a2 = a_*a_, b2 = b_*b_, c2 = c_*c_;
+
+      auto div = a2*b2*c2*power(x*x/(a2*a2) + y*y/(b2*b2) + z*z/(c2*c2), 2);
+      return T(1)/div;
+    }
+
+  private:
+    FieldVector<T,2> angles (Domain x) const 
+    {
+      using std::acos; using std::atan2;
+      x /= x.two_norm();
+
+      return {atan2(x[1], x[0]), acos(x[2])};
+    }
+  };
+
+  //! construct a grid function representing a sphere parametrization
+  template< class Grid, class T >
+  auto ellipsoidGridFunction (T a, T b, T c)
+  {
+    return analyticGridFunction<Grid>(EllipsoidProjection<T>{a,b,c});
+  }
+
+} // end namespace Dune
+
+#endif // DUNE_CURVED_SURFACE_GRID_SPHERE_GRIDFUNCTION_HH
diff --git a/dune/curvedsurfacegrid/gridfunctions/gridentityset.hh b/dune/curvedsurfacegrid/gridfunctions/gridentityset.hh
new file mode 100644
index 0000000000000000000000000000000000000000..4588b4cd02e271f7cd78428c35c32f416a6c67e5
--- /dev/null
+++ b/dune/curvedsurfacegrid/gridfunctions/gridentityset.hh
@@ -0,0 +1,34 @@
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+#ifndef DUNE_CURVED_SURFACE_GRID_GRID_ENTITYSET_HH
+#define DUNE_CURVED_SURFACE_GRID_GRID_ENTITYSET_HH
+
+namespace Dune
+{
+  //! A set of entities of given `codim` of a `Grid`
+  /**
+   * \tparam GridType  The grid type
+   * \tparam codim     Codimension of the entities to define the set of.
+   *
+   * \note This entityset just defines types
+   **/
+  template< class GridType, int codim >
+  class GridEntitySet
+  {
+  public:
+    //! Type of the grid
+    using Grid = GridType;
+
+    //! Type of Elements contained in this EntitySet
+    using Element = typename Grid::template Codim<codim>::Entity;
+
+    //! Type of local coordinates with respect to the Element
+    using LocalCoordinate = typename Element::Geometry::LocalCoordinate;
+
+    //! Type of global coordinates with respect to the Element
+    using GlobalCoordinate = typename Element::Geometry::GlobalCoordinate;
+  };
+
+} // end namespace Dune 
+
+#endif // DUNE_CURVED_SURFACE_GRID_GRID_ENTITYSET_HH
diff --git a/dune/curvedsurfacegrid/gridfunctions/gridfunction.hh b/dune/curvedsurfacegrid/gridfunctions/gridfunction.hh
new file mode 100644
index 0000000000000000000000000000000000000000..28d7b21a70d2727576fef3268f42306378f571a6
--- /dev/null
+++ b/dune/curvedsurfacegrid/gridfunctions/gridfunction.hh
@@ -0,0 +1,46 @@
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+#ifndef DUNE_CURVED_SURFACE_GRID_GRIDFUNCTION_HH
+#define DUNE_CURVED_SURFACE_GRID_GRIDFUNCTION_HH
+
+#include <type_traits>
+#include <dune/curvedsurfacegrid/concepts.hh>
+#include <dune/curvedsurfacegrid/gridfunctions/analyticgridfunction.hh>
+
+namespace Dune
+{
+  namespace Impl
+  {
+    template< class ES, class = void >
+    struct GridOf;
+
+    template< class ES >
+    struct GridOf<ES, std::void_t<typename ES::GridView>>
+    {
+      using type = typename ES::GridView::Grid;
+    };
+
+    template< class ES >
+    struct GridOf<ES, std::void_t<typename ES::Grid>>
+    {
+      using type = typename ES::Grid;
+    };
+
+  } // end namespace Impl
+
+  //! Type-Traits to extract the grid-type from a GridFunction `GF`
+  template< class GF >
+  using GridOf_t = typename Impl::GridOf<std::decay_t<decltype(std::declval<GF>().entitySet())>>::type;
+
+  //! Conditionally define the GridFunction type.
+  /**
+   * If the type `GF` is a GridFunction on the grid `Grid`, use this type as GridFunction type,
+   * Otherwise it is a functor and construct an \ref AnalyticGridFunction on the `Grid`.
+   **/
+  template< class Grid, class GF >
+  using GridFunctionOf_t
+    = std::conditional_t<Dune::Concept::isGridFunction<GF, Grid>(), GF, AnalyticGridFunction<Grid,GF>>;
+
+} // end namespace Dune
+
+#endif // DUNE_CURVED_SURFACE_GRID_GRIDFUNCTION_HH
diff --git a/dune/curvedsurfacegrid/gridfunctions/normalgridviewfunction.hh b/dune/curvedsurfacegrid/gridfunctions/normalgridviewfunction.hh
new file mode 100644
index 0000000000000000000000000000000000000000..847f71601ca381d84bdc0d94e9a14427cec716e7
--- /dev/null
+++ b/dune/curvedsurfacegrid/gridfunctions/normalgridviewfunction.hh
@@ -0,0 +1,207 @@
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+#ifndef DUNE_CURVED_SURFACE_GRID_NORMAL_GRIDVIEWFUNCTION_HH
+#define DUNE_CURVED_SURFACE_GRID_NORMAL_GRIDVIEWFUNCTION_HH
+
+#include <array>
+#include <vector>
+
+#include <dune/common/fvector.hh>
+#include <dune/functions/backends/istlvectorbackend.hh>
+#include <dune/functions/functionspacebases/basistags.hh>
+#include <dune/functions/functionspacebases/defaultglobalbasis.hh>
+#include <dune/functions/functionspacebases/lagrangebasis.hh>
+#include <dune/functions/functionspacebases/powerbasis.hh>
+#include <dune/functions/gridfunctions/gridviewentityset.hh>
+#include <dune/grid/utility/hierarchicsearch.hh>
+#include <dune/istl/bvector.hh>
+
+
+namespace Dune 
+{
+  //! Grid-view function representing averaged normal vector
+  /**
+   * \tparam GridView   The grid-view this grid-view-function is defined on
+   * \tparam ORDER      Polynomial order of the lagrange bases used for representing the normals
+   * \tparam T          Value type used for the basis and the coefficients
+   **/
+  template< class GridView, int ORDER = -1, class T = double >
+  class NormalGridViewFunction
+  {
+    static auto makeBasis (const GridView& gridView, int order)
+    {
+      namespace BF = BasisFactory;
+      return BF::makeBasis(gridView, BF::power<GridView::dimensionworld>(BF::lagrange<T>(order), BF::blockedInterleaved()));
+    }
+
+    using Basis = decltype(makeBasis(std::declval<GridView>(), ORDER));
+
+  public:
+    using EntitySet = GridViewEntitySet<GridView,0>;
+
+    using Domain = typename EntitySet::GlobalCoordinate;
+    using Range = FieldVector<T,GridView::dimensionworld>;
+
+    using VectorType = BlockVector<Range>;
+
+  private:
+    class LocalFunction
+    {
+      using LocalView = typename Basis::LocalView;
+      using LocalContext = typename LocalView::Element;
+
+      using Domain = typename EntitySet::LocalCoordinate;
+      using Range = typename NormalGridViewFunction::Range;
+
+    public:
+      LocalFunction (LocalView&& localView, const VectorType& normals)
+        : localView_(std::move(localView))
+        , normals_(normals)
+      {}
+
+      //! Collect the normal vector from all element DOFs into a local
+      //! vector that can be accessed in the operator() for interpolation
+      void bind (const LocalContext& element)
+      {
+        localView_.bind(element);
+
+        const auto& leafNode = localView_.tree().child(0);
+        localNormals_.resize(leafNode.size());
+
+        // collect local normal vectors
+        for (std::size_t i = 0; i < localNormals_.size(); ++i) {
+          auto idx = localView_.index(leafNode.localIndex(i));
+          localNormals_[i] = normals_[idx[0]];
+        }
+
+        bound_ = true;
+      }
+
+      void unbind ()
+      {
+        localView_.unbind();
+        bound_ = false;
+      }
+
+      // evaluate normal vectors in local coordinate
+      // by interpolation of stored local normals.
+      Range operator() (const Domain& local) const 
+      {
+        assert(bound_);
+
+        const auto& leafNode = localView_.tree().child(0);
+        const auto& lfe = leafNode.finiteElement();
+
+        // evaluate basis functions in local coordinate
+        lfe.localBasis().evaluateFunction(local, shapeValues_);
+        assert(localNormals_.size() == shapeValues_.size());
+
+        Range n(0);
+        for (std::size_t i = 0; i < localNormals_.size(); ++i)
+          n.axpy(shapeValues_[i], localNormals_[i]);
+
+        // return normalized vector
+        return n / n.two_norm();
+      }
+
+    private:
+      LocalView localView_;
+      const VectorType& normals_;
+
+      std::vector<Range> localNormals_;
+      mutable std::vector<FieldVector<T,1>> shapeValues_;
+      bool bound_ = false;
+    };
+
+  public:
+    //! Constructor of the grid function. 
+    /** 
+     * Creates a global basis of a power of langrange nodes of given order.
+     * The constructor argument `order` is defaulted to the class template parameter.
+     **/
+    NormalGridViewFunction (const GridView& gridView, int order = ORDER)
+      : entitySet_(gridView)
+      , basis_(makeBasis(gridView, order))
+    {
+      update(gridView);
+    }
+
+    //! Epdate the grid function. 
+    /**
+     * This calculates a mean average of normal vectors in the  DOFs of the basis. 
+     * Those averages are stored normalized in the coefficients vector.
+     **/
+    void update (const GridView& gridView)
+    {
+      entitySet_ = EntitySet{gridView};
+      basis_.update(gridView);
+
+      normals_.resize(basis_.size());
+      normals_ = 0;
+
+      // compute normal vectors by mean averaging
+      auto localView = basis_.localView();
+      for (const auto& e : elements(basis_.gridView()))
+      {
+        localView.bind(e);
+        auto geometry = e.geometry();
+
+        const auto& leafNode = localView.tree().child(0);
+        const auto& lfe = leafNode.finiteElement();
+
+        // interpolate normal of geometry
+        std::vector<Range> localNormals;
+        lfe.localInterpolation().interpolate([&](const auto& local) -> Range {
+          return Dune::normal(geometry, local);
+        }, localNormals);
+
+        // copy to global vector
+        for (std::size_t i = 0; i < localNormals.size(); ++i) {
+          auto idx = localView.index(leafNode.localIndex(i));
+          normals_[idx[0]] += localNormals[i];
+        }
+      }
+
+      // normalize vector
+      for (std::size_t i = 0; i < normals_.size(); ++i)
+        normals_[i] /= normals_[i].two_norm();
+    }
+
+    //! Evaluate normal vectors in global coordinates
+    // NOTE: expensive
+    Range operator() (const Domain& x) const 
+    {
+      using Grid = typename GridView::Grid;
+      using IS = typename GridView::IndexSet;
+
+      const auto& gv = basis_.gridView();
+      HierarchicSearch<Grid,IS> hsearch{gv.grid(), gv.indexSet()};
+
+      auto element = hsearch.findEntity(x);
+      auto geometry = element.geometry();
+      auto localFct = localFunction(*this);
+      localFct.bind(element);
+      return localFct(geometry.local(x));
+    }
+
+    //! Create a local function of this grifunction
+    friend LocalFunction localFunction (const NormalGridViewFunction& gf)
+    {
+      return LocalFunction{gf.basis_.localView(), gf.normals_};
+    }
+
+    //! obtain the stored \ref GridViewEntitySet
+    const EntitySet& entitySet () const
+    {
+      return entitySet_;
+    }
+
+  private:
+    EntitySet entitySet_;
+    Basis basis_;
+    VectorType normals_;
+  };
+
+} // end namespace Dune 
+
+#endif // DUNE_CURVED_SURFACE_GRID_NORMAL_GRIDVIEWFUNCTION_HH
diff --git a/dune/curvedsurfacegrid/gridfunctions/spheregridfunction.hh b/dune/curvedsurfacegrid/gridfunctions/spheregridfunction.hh
new file mode 100644
index 0000000000000000000000000000000000000000..9bc8fc38026b6756d2ac8a58f09385b20003793b
--- /dev/null
+++ b/dune/curvedsurfacegrid/gridfunctions/spheregridfunction.hh
@@ -0,0 +1,77 @@
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+#ifndef DUNE_CURVED_SURFACE_GRID_SPHERE_GRIDFUNCTION_HH
+#define DUNE_CURVED_SURFACE_GRID_SPHERE_GRIDFUNCTION_HH
+
+#include <type_traits>
+
+#include <dune/curvedsurfacegrid/gridfunctions/analyticgridfunction.hh>
+#include <dune/functions/common/defaultderivativetraits.hh>
+
+namespace Dune
+{
+  // Sphere functor
+  template< class T >
+  struct SphereProjection
+  {
+    T radius_;
+
+    SphereProjection (T radius)
+      : radius_(radius)
+    {}
+
+    //! project the coordinate to the sphere at origin with `radius`
+    template< class Domain >
+    Domain operator() (const Domain& x) const
+    {
+      return x * (radius_ / x.two_norm());
+    }
+
+    //! derivative of the projection
+    friend auto derivative (const SphereProjection& sphere)
+    {
+      return [r=sphere.radius_](auto const& x)
+      {
+        using Domain = std::decay_t<decltype(x)>;
+        using DerivativeTraits = Functions::DefaultDerivativeTraits<Domain(Domain)>;
+        typename DerivativeTraits::Range out;
+
+        auto nrm = x.two_norm();
+        for (int i = 0; i < out.N(); ++i)
+          for (int j = 0; j < out.M(); ++j)
+            out[i][j] = r * ((i == j ? 1 : 0) - (x[i]/nrm) * (x[j]/nrm)) / nrm;
+        return out;
+      };
+    }
+
+    //! normal vector = x/|x|
+    template< class Domain >
+    Domain normal (const Domain& x) const
+    {
+      return x / x.two_norm();
+    }
+
+    //! mean curvature of the sphere = 1/R
+    template< class Domain >
+    T mean_curvature (const Domain& /*x*/) const
+    {
+      return T(1)/radius_;
+    }
+
+    //! surface area of the sphere = 4*pi*r^2
+    T area () const
+    {
+      return 4*M_PI*radius_*radius_;
+    }
+  };
+
+  //! construct a grid function representing a sphere parametrization
+  template< class Grid, class T >
+  auto sphereGridFunction (T radius)
+  {
+    return analyticGridFunction<Grid>(SphereProjection<T>{radius});
+  }
+
+} // end namespace Dune
+
+#endif // DUNE_CURVED_SURFACE_GRID_SPHERE_GRIDFUNCTION_HH
diff --git a/dune/curvedsurfacegrid/gridfunctions/torusgridfunction.hh b/dune/curvedsurfacegrid/gridfunctions/torusgridfunction.hh
new file mode 100644
index 0000000000000000000000000000000000000000..df1fb7dee1ae2c0fbc3faf7ab402facba40f09ea
--- /dev/null
+++ b/dune/curvedsurfacegrid/gridfunctions/torusgridfunction.hh
@@ -0,0 +1,115 @@
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+#ifndef DUNE_CURVED_SURFACE_GRID_TORUS_GRIDFUNCTION_HH
+#define DUNE_CURVED_SURFACE_GRID_TORUS_GRIDFUNCTION_HH
+
+#include <type_traits>
+
+#include <dune/common/math.hh>
+#include <dune/curvedsurfacegrid/gridfunctions/analyticgridfunction.hh>
+#include <dune/functions/common/defaultderivativetraits.hh>
+
+namespace Dune
+{
+  // torus functor
+  template< class T >
+  struct TorusProjection
+  {
+    T R_;
+    T r_;
+
+    TorusProjection (T R, T r)
+      : R_(R)
+      , r_(r)
+    {}
+
+    // closest point projection
+    FieldVector<T,3> operator()(FieldVector<T,3> x) const
+    {
+      using std::abs;
+
+      FieldVector<T,3> x2{x[0], x[1], T(0)};
+      T norm2 = x2.two_norm();
+      assert(norm2 > std::numeric_limits<T>::epsilon());
+
+      FieldVector<T,3> c = x2 * (R_ / norm2);
+      x2 = x - c;
+
+      norm2 = x2.two_norm();
+      assert(norm2 > std::numeric_limits<T>::epsilon());
+      x = c + x2 * (r_ / norm2);
+
+      assert(abs(phi(x)) < 10*std::numeric_limits<T>::epsilon());
+      return x;
+    }
+
+    T phi(FieldVector<T,3> const& x) const
+    {
+      using std::sqrt;
+      T phi0 = sqrt(x[0]*x[0] + x[1]*x[1]) - R_;
+      return phi0*phi0 + x[2]*x[2] - r_*r_;
+    }
+
+    FieldVector<T,3> normal (FieldVector<T,3> X) const
+    {
+      using std::sqrt;
+      X = (*this)(X);
+
+      T x = X[0], y = X[1], z = X[2];
+      // T x2y2_1_2 = sqrt(x*x + y*y);
+      // assert(x2y2_1_2 > std::numeric_limits<T>::epsilon());
+
+      // return { x - 2*x/x2y2_1_2, y - 2*y/x2y2_1_2, z };
+
+      T x2 = x*x, y2 = y*y, z2 = z*z;
+      auto factor1 = x2 + y2 + z2 - 5;
+      auto factor2 = x2 + y2 + z2 + 3;
+      auto factor1_2 = factor1*factor1;
+      auto factor2_2 = factor2*factor2;
+      auto div = sqrt(x2*factor1_2 + y2*factor1_2 + z2*factor2_2);
+      return {
+        x*factor1/div,
+        y*factor1/div,
+        z*factor2/div
+      };
+
+    }
+
+    T mean_curvature (FieldVector<T,3> X) const
+    {
+      using std::sqrt;
+      X = (*this)(X);
+
+      T x = X[0], y = X[1], z = X[2];
+      // T x2y2_1_2 = sqrt(x*x + y*y);
+
+      // return -(3 - 2/x2y2_1_2)/2;
+
+      T x2 = x*x, y2 = y*y, z2 = z*z;
+      T x3 = x*x2,y3 = y*y2,z3 = z*z2;
+      auto factor1 = x2 + y2 + z2 - 5;
+      auto factor2 = x2 + y2 + z2 + 3;
+      auto factor1_2 = factor1*factor1;
+      auto factor2_2 = factor2*factor2;
+      auto div = sqrt(x2*factor1_2 + y2*factor1_2 + z2*factor2_2);
+      auto div2= power(div, 3);
+      return -(2*x2/div + x*factor1*(-2*x3*factor1 - 2*x*y2*factor1 - 2*x*z2*factor2 - x*factor1_2)/div2 + 2*y2/div + y*factor1*(-2*x2*y*factor1 - 2*y3*factor1 - 2*y*z2*factor2 - y*factor1_2)/div2 + 2*z2/div + z*factor2*(-2*x2*z*factor1 - 2*y2*z*factor1 - 2*z3*factor2 - z*factor2_2)/div2 + 2*factor1/div + factor2/div) ;
+    }
+
+    //! surface area of the torus = 4*pi^2*r1*r2
+    T area () const
+    {
+      return 4*M_PI*M_PI*R_*r_;
+    }
+  };
+
+  //! construct a grid function representing a torus parametrization
+  template< class Grid, class T >
+  auto torusGridFunction (T R, T r)
+  {
+    return analyticGridFunction<Grid>(TorusProjection<T>{R,r});
+  }
+
+} // end namespace Dune
+
+#endif // DUNE_CURVED_SURFACE_GRID_TORUS_GRIDFUNCTION_HH
diff --git a/dune/curvedsurfacegrid/gridview.hh b/dune/curvedsurfacegrid/gridview.hh
index 48c2cae238b94d0c7b28b21a75d06175769fb7ea..a075c1f855550386e332eaa6b177619838b377b6 100644
--- a/dune/curvedsurfacegrid/gridview.hh
+++ b/dune/curvedsurfacegrid/gridview.hh
@@ -1,14 +1,14 @@
 // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
 // vi: set et ts=4 sw=2 sts=2:
-#ifndef DUNE_CRVSRF_GRIDVIEW_HH
-#define DUNE_CRVSRF_GRIDVIEW_HH
+#ifndef DUNE_CURVED_SURFACE_GRID_GRIDVIEW_HH
+#define DUNE_CURVED_SURFACE_GRID_GRIDVIEW_HH
 
-#include <dune/common/typetraits.hh>
-#include <dune/common/exceptions.hh>
+#include <cassert>
+#include <utility>
 
-#include <dune/grid/common/capabilities.hh>
 #include <dune/grid/common/gridview.hh>
 #include <dune/curvedsurfacegrid/datahandle.hh>
+#include <dune/curvedsurfacegrid/declaration.hh>
 #include <dune/curvedsurfacegrid/indexsets.hh>
 #include <dune/curvedsurfacegrid/intersection.hh>
 #include <dune/curvedsurfacegrid/intersectioniterator.hh>
@@ -16,63 +16,59 @@
 
 namespace Dune
 {
-
-  namespace crvsrf
+  namespace Curved
   {
 
     // Internal Forward Declarations
     // -----------------------------
 
-    template< class HGV, class CoordFunction, int order, bool geoCaching, class Allocator >
+    template< class HGV, class GF, int order >
     class GridView;
 
 
-
     // GridViewTraits
     // --------------
 
-    template< class HGV, class CoordFunction, int order, bool geoCaching, class Allocator >
+    template< class HGV, class GF, int order >
     class GridViewTraits
     {
-      friend class GridView< HGV, CoordFunction, order, geoCaching, Allocator >;
+      friend class GridView<HGV, GF, order>;
 
-      typedef HGV HostGridView;
+      using HostGridView = HGV;
+      using GridFunction = GF;
 
-      typedef typename HostGridView::Grid HostGrid;
-      typedef typename HostGridView::Intersection HostIntersection;
-      typedef typename HostGridView::IntersectionIterator HostIntersectionIterator;
+      using HostGrid = typename HostGridView::Grid;
+      using HostIntersection = typename HostGridView::Intersection;
+      using HostIntersectionIterator = typename HostGridView::IntersectionIterator;
 
     public:
-      typedef GridView< HostGridView, CoordFunction, order, geoCaching, Allocator > GridViewImp;
-
-      typedef Dune::CurvedSurfaceGrid< HostGrid, CoordFunction, order, geoCaching, Allocator > Grid;
-
-      typedef crvsrf::IndexSet< const Grid, typename HostGridView::IndexSet > IndexSet;
+      using GridViewImp = GridView<HostGridView, GridFunction, order>;
+      using Grid = Dune::CurvedSurfaceGrid<GridFunction, order>;
+      using IndexSet = Curved::IndexSet<const Grid, typename HostGridView::IndexSet>;
 
-      typedef Dune::Intersection< const Grid, crvsrf::Intersection< const Grid, HostIntersection > > Intersection;
+      using Intersection = Dune::Intersection<const Grid, Curved::Intersection<const Grid, HostIntersection> >;
 
-      typedef Dune::IntersectionIterator
-      < const Grid, crvsrf::IntersectionIterator< const Grid, HostIntersectionIterator >, crvsrf::Intersection< const Grid, HostIntersection > >
-      IntersectionIterator;
+      using IntersectionIterator
+        = Dune::IntersectionIterator<const Grid, Curved::IntersectionIterator<const Grid, HostIntersectionIterator>, Curved::Intersection<const Grid, HostIntersection> >;
 
-      typedef typename HostGridView::CollectiveCommunication CollectiveCommunication;
+      using CollectiveCommunication = typename HostGridView::CollectiveCommunication;
 
       template< int codim >
       struct Codim
       {
-        typedef crvsrf::Iterator< HostGridView, codim, All_Partition, const Grid > IteratorImp;
-        typedef Dune::EntityIterator< codim, const Grid, IteratorImp > Iterator;
+        using IteratorImp = Curved::Iterator<HostGridView, codim, All_Partition, const Grid>;
+        using Iterator = Dune::EntityIterator<codim, const Grid, IteratorImp>;
 
-        typedef typename Grid::Traits::template Codim< codim >::Entity Entity;
+        using Entity = typename Grid::Traits::template Codim<codim>::Entity;
 
-        typedef typename Grid::template Codim< codim >::Geometry Geometry;
-        typedef typename Grid::template Codim< codim >::LocalGeometry LocalGeometry;
+        using Geometry = typename Grid::template Codim<codim>::Geometry;
+        using LocalGeometry = typename Grid::template Codim<codim>::LocalGeometry;
 
         template< PartitionIteratorType pit >
         struct Partition
         {
-          typedef crvsrf::Iterator< HostGridView, codim, pit, const Grid > IteratorImp;
-          typedef Dune::EntityIterator< codim, const Grid, IteratorImp > Iterator;
+          using IteratorImp = Curved::Iterator<HostGridView, codim, pit, const Grid>;
+          using Iterator = Dune::EntityIterator<codim, const Grid, IteratorImp>;
         };
       };
 
@@ -84,149 +80,161 @@ namespace Dune
     // GridView
     // --------
 
-    template< class HGV, class CoordFunction, int order, bool geoCaching, class Allocator >
+    template< class HGV, class GF, int order >
     class GridView
     {
-      typedef GridView< HGV, CoordFunction, order, geoCaching, Allocator > This;
+      using Self = GridView;
 
     public:
-      typedef GridViewTraits< HGV, CoordFunction, order, geoCaching, Allocator > Traits;
-
-      typedef typename Traits::HostGridView HostGridView;
-
-      typedef typename Traits::Grid Grid;
-
-      typedef typename Traits::IndexSet IndexSet;
+      using Traits = GridViewTraits<HGV, GF, order>;
 
-      typedef typename Traits::Intersection Intersection;
-
-      typedef typename Traits::IntersectionIterator IntersectionIterator;
-
-      typedef typename Traits::CollectiveCommunication CollectiveCommunication;
+      using HostGridView = typename Traits::HostGridView;
+      using Grid = typename Traits::Grid;
+      using GridFunction = GF;
+      using IndexSet = typename Traits::IndexSet;
+      using Intersection = typename Traits::Intersection;
+      using IntersectionIterator = typename Traits::IntersectionIterator;
+      using CollectiveCommunication = typename Traits::CollectiveCommunication;
 
       template< int codim >
       struct Codim
-        : public Traits::template Codim< codim >
+          : public Traits::template Codim<codim>
       {};
 
       static const bool conforming = Traits::conforming;
 
-      GridView ( const Grid &grid, const HostGridView &hostGridView )
-        : grid_( &grid ), hostGridView_( hostGridView )
+    public:
+      // construct from a host-gridview
+      GridView (const Grid& grid, const HostGridView& hostGridView)
+        : grid_(&grid)
+        , hostGridView_(hostGridView)
       {}
 
-      GridView ( const This &other )
-        : grid_( other.grid_ ), hostGridView_( other.hostGridView_ )
+      //! copy constructor. Only copies grid and hostGridView
+      GridView (const Self& other)
+        : grid_(other.grid_)
+        , hostGridView_(other.hostGridView_)
       {}
 
-      GridView ( This &&other )
-        : grid_( other.grid_ ), hostGridView_( std::move( other.hostGridView_ ) )
+      //! move constructor. Only moves grid and hostGridView
+      GridView (Self&& other)
+        : grid_(other.grid_)
+        , hostGridView_(std::move(other.hostGridView_))
       {}
 
-      This &operator= ( const This &other )
+      //! copy-assignment operator
+      Self& operator= (const Self& other)
       {
         grid_ = other.grid_;
         hostGridView_ = other.hostGridView_;
-        if( indexSet_ )
-          indexSet_.reset( hostGridView().indexSet() );
+        if (indexSet_)
+          indexSet_.reset(hostGridView().indexSet());
         return *this;
       }
 
-      This &operator= ( This &&other )
+      //! move-assignment operator
+      Self& operator= (Self&& other)
       {
         grid_ = other.grid_;
-        hostGridView_ = std::move( other.hostGridView_ );
-        if( indexSet_ )
-          indexSet_.reset( hostGridView().indexSet() );
+        hostGridView_ = std::move(other.hostGridView_);
+        if (indexSet_)
+          indexSet_.reset(hostGridView().indexSet()); // TODO: find a better way for copy and move!
         return *this;
       }
 
-      const Grid &grid () const
+      const Grid& grid () const
       {
         assert( grid_ );
         return *grid_;
       }
 
-      const IndexSet &indexSet () const
+      const GridFunction& gridFunction () const
       {
-        indexSet_.reset( hostGridView().indexSet() );
+        return grid().gridFunction();
+      }
+
+      const IndexSet& indexSet () const
+      {
+        indexSet_.reset(hostGridView().indexSet());
         return indexSet_;
       }
 
-      int size ( int codim ) const
+      int size (int codim) const
       {
-        return hostGridView().size( codim );
+        return hostGridView().size(codim);
       }
 
-      int size ( const GeometryType &type ) const
+      int size (const GeometryType& type) const
       {
-        return hostGridView().size( type );
+        return hostGridView().size(type);
       }
 
       template< int codim >
-      typename Codim< codim >::Iterator begin () const
+      typename Codim<codim>::Iterator begin () const
       {
-        return begin< codim, All_Partition >();
+        return begin<codim, All_Partition>();
       }
 
       template< int codim, PartitionIteratorType pit >
-      typename Codim< codim >::template Partition< pit >::Iterator begin () const
+      typename Codim<codim>::template Partition<pit>::Iterator begin () const
       {
-        return Traits::template Codim< codim >::template Partition< pit >::IteratorImp::begin( grid(), hostGridView() );
+        using IteratorImp = typename Traits::template Codim<codim>::template Partition<pit>::IteratorImp;
+        return IteratorImp::begin(gridFunction(), hostGridView());
       }
 
       template< int codim >
-      typename Codim< codim >::Iterator end () const
+      typename Codim<codim>::Iterator end () const
       {
-        return end< codim, All_Partition >();
+        return end<codim, All_Partition>();
       }
 
       template< int codim, PartitionIteratorType pit >
-      typename Codim< codim >::template Partition< pit >::Iterator end () const
+      typename Codim<codim>::template Partition<pit>::Iterator end () const
       {
-        return Traits::template Codim< codim >::template Partition< pit >::IteratorImp::end( grid(), hostGridView() );
+        using IteratorImp = typename Traits::template Codim<codim>::template Partition<pit>::IteratorImp;
+        return IteratorImp::end(gridFunction(), hostGridView());
       }
 
-      IntersectionIterator ibegin ( const typename Codim< 0 >::Entity &entity ) const
+      IntersectionIterator ibegin (const typename Codim<0>::Entity& entity) const
       {
-        typedef crvsrf::IntersectionIterator< const Grid, typename HostGridView::IntersectionIterator > IntersectionIteratorImpl;
-        return IntersectionIteratorImpl( entity, hostGridView().ibegin( entity.impl().hostEntity() ) );
+        using IteratorImpl = Curved::IntersectionIterator<const Grid, typename HostGridView::IntersectionIterator>;
+        return IteratorImpl(entity, hostGridView().ibegin(entity.impl().hostEntity()));
       }
 
-      IntersectionIterator iend ( const typename Codim< 0 >::Entity &entity ) const
+      IntersectionIterator iend (const typename Codim<0>::Entity& entity) const
       {
-        typedef crvsrf::IntersectionIterator< const Grid, typename HostGridView::IntersectionIterator > IntersectionIteratorImpl;
-        return IntersectionIteratorImpl( entity, hostGridView().iend( entity.impl().hostEntity() ) );
+        using IteratorImpl = Curved::IntersectionIterator<const Grid, typename HostGridView::IntersectionIterator>;
+        return IteratorImpl(entity, hostGridView().iend(entity.impl().hostEntity()));
       }
 
-      const CollectiveCommunication &comm () const
+      const CollectiveCommunication& comm () const
       {
         return hostGridView().comm();
       }
 
-      int overlapSize ( int codim ) const
+      int overlapSize (int codim) const
       {
-        return hostGridView().overlapSize( codim );
+        return hostGridView().overlapSize(codim);
       }
 
-      int ghostSize ( int codim ) const
+      int ghostSize (int codim) const
       {
-        return hostGridView().ghostSize( codim );
+        return hostGridView().ghostSize(codim);
       }
 
       template< class DataHandle, class Data >
-      void communicate ( CommDataHandleIF< DataHandle, Data > &dataHandle,
-                         InterfaceType interface,
-                         CommunicationDirection direction ) const
+      void communicate (CommDataHandleIF<DataHandle, Data>& dataHandle,
+                        InterfaceType interface,
+                        CommunicationDirection direction) const
       {
-        typedef CommDataHandleIF< DataHandle, Data > DataHandleIF;
-        typedef crvsrf::CommDataHandle< Grid, DataHandleIF > WrappedDataHandle;
+        using DataHandleIF = CommDataHandleIF<DataHandle, Data>;
+        using WrappedDataHandle = Curved::CommDataHandle<Grid, DataHandleIF>;
 
-        WrappedDataHandle wrappedDataHandle( grid(), dataHandle );
-        hostGridView().communicate( wrappedDataHandle, interface, direction );
+        WrappedDataHandle wrappedDataHandle(grid(), dataHandle);
+        hostGridView().communicate(wrappedDataHandle, interface, direction);
       }
 
-      const HostGridView &hostGridView () const { return hostGridView_; }
+      const HostGridView& hostGridView () const { return hostGridView_; }
 
     private:
       const Grid *grid_;
@@ -234,8 +242,7 @@ namespace Dune
       mutable IndexSet indexSet_;
     };
 
-  } // namespace crvsrf
-
+  } // namespace Curved
 } // namespace Dune
 
-#endif // #ifndef DUNE_CRVSRF_GRIDVIEW_HH
+#endif // DUNE_CURVED_SURFACE_GRID_GRIDVIEW_HH
diff --git a/dune/curvedsurfacegrid/idset.hh b/dune/curvedsurfacegrid/idset.hh
index 2f387adb896a48d1c44e937ffef4826fa86a4a34..197cb3a1de671245879faeb14e12f27434f9a3ff 100644
--- a/dune/curvedsurfacegrid/idset.hh
+++ b/dune/curvedsurfacegrid/idset.hh
@@ -1,14 +1,15 @@
 // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
 // vi: set et ts=4 sw=2 sts=2:
-#ifndef DUNE_CRVSRF_IDSET_HH
-#define DUNE_CRVSRF_IDSET_HH
+#ifndef DUNE_CURVED_SURFACE_GRID_IDSET_HH
+#define DUNE_CURVED_SURFACE_GRID_IDSET_HH
+
+#include <type_traits>
 
 #include <dune/grid/common/indexidset.hh>
 
 namespace Dune
 {
-
-  namespace crvsrf
+  namespace Curved
   {
 
     // IdSet
@@ -16,67 +17,63 @@ namespace Dune
 
     template< class Grid, class HostIdSet >
     class IdSet
-      : public Dune::IdSet< Grid, IdSet< Grid, HostIdSet >, typename HostIdSet::IdType >
+        : public Dune::IdSet<Grid, IdSet<Grid, HostIdSet>, typename HostIdSet::IdType>
     {
-      typedef IdSet< Grid, HostIdSet > This;
-      typedef Dune::IdSet< Grid, This, typename HostIdSet::IdType > Base;
+      using Self = IdSet;
+      using Super = Dune::IdSet<Grid, Self, typename HostIdSet::IdType>;
 
-      typedef typename std::remove_const< Grid >::type::Traits Traits;
+      using Traits = typename std::remove_const<Grid>::type::Traits;
 
     public:
-      typedef typename HostIdSet::IdType IdType;
-
-      using Base::subId;
+      using IdType = typename HostIdSet::IdType;
 
-      IdSet ()
-        : hostIdSet_( 0 )
-      {}
+    public:
+      IdSet () = default;
 
-      explicit IdSet ( const HostIdSet &hostIdSet )
-        : hostIdSet_( &hostIdSet )
+      explicit IdSet (const HostIdSet& hostIdSet)
+        : hostIdSet_(&hostIdSet)
       {}
 
-      IdSet ( const This &other )
-        : hostIdSet_( other.hostIdSet_ )
+      //! Copy constructor. Copies only the host-idset pointer
+      IdSet (const IdSet& other)
+        : hostIdSet_(other.hostIdSet_)
       {}
 
-      const This &operator= ( const This &other )
+      //! Copy-assignment operator. Copies only the host-idset pointer
+      IdSet& operator= (const IdSet& other)
       {
         hostIdSet_ = other.hostIdSet_;
         return *this;
       }
 
       template< int codim >
-      IdType id ( const typename Traits::template Codim< codim >::Entity &entity ) const
+      IdType id (const typename Traits::template Codim<codim>::Entity& entity) const
       {
-        return entity.impl().id( hostIdSet() );
+        return hostIdSet().id(Grid::template getHostEntity<codim>(entity));
       }
 
-      template< class Entity >
-      IdType id ( const Entity &entity ) const
-      {
-        return id< Entity::codimension >( entity );
-      }
+      using Super::id;
 
-      IdType subId ( const typename Traits::template Codim< 0 >::Entity &entity, int i, unsigned int codim ) const
+      IdType subId (const typename Traits::template Codim<0>::Entity& entity, int i, unsigned int codim) const
       {
-        return hostIdSet().subId( Grid::template getHostEntity< 0 >( entity ), i, codim );
+        return hostIdSet().subId(Grid::template getHostEntity<0>(entity), i, codim);
       }
 
-      explicit operator bool () const { return bool( hostIdSet_ ); }
+      using Super::subId;
+
+      explicit operator bool () const { return bool(hostIdSet_); }
 
     private:
-      const HostIdSet &hostIdSet () const
+      const HostIdSet& hostIdSet () const
       {
         assert( *this );
         return *hostIdSet_;
       }
 
-      const HostIdSet *hostIdSet_;
+      const HostIdSet* hostIdSet_ = nullptr;
     };
 
-  } // namespace crvsrf
-
+  } // namespace Curved
 } // namespace Dune
 
-#endif // #ifndef DUNE_CRVSRF_IDSET_HH
+#endif // DUNE_CURVED_SURFACE_GRID_IDSET_HH
diff --git a/dune/curvedsurfacegrid/indexsets.hh b/dune/curvedsurfacegrid/indexsets.hh
index dded072bbed0944a4498e822dc56ef61c2aa7aae..fc05296903c73b78fdc4938238993eb2dc704172 100644
--- a/dune/curvedsurfacegrid/indexsets.hh
+++ b/dune/curvedsurfacegrid/indexsets.hh
@@ -1,21 +1,17 @@
 // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
 // vi: set et ts=4 sw=2 sts=2:
-#ifndef DUNE_CRVSRF_INDEXSETS_HH
-#define DUNE_CRVSRF_INDEXSETS_HH
+#ifndef DUNE_CURVED_SURFACE_GRID_INDEXSETS_HH
+#define DUNE_CURVED_SURFACE_GRID_INDEXSETS_HH
 
+#include <type_traits>
 #include <vector>
 
-#include <dune/common/typetraits.hh>
-
 #include <dune/grid/common/gridenums.hh>
 #include <dune/grid/common/indexidset.hh>
 
-#include <dune/curvedsurfacegrid/declaration.hh>
-
 namespace Dune
 {
-
-  namespace crvsrf
+  namespace Curved
   {
 
     // IndexSet
@@ -23,90 +19,86 @@ namespace Dune
 
     template< class Grid, class HostIndexSet >
     class IndexSet
-      : public Dune::IndexSet< Grid, IndexSet< Grid, HostIndexSet >, typename HostIndexSet::IndexType, typename HostIndexSet::Types >
+        : public Dune::IndexSet<Grid, IndexSet<Grid, HostIndexSet>, typename HostIndexSet::IndexType, typename HostIndexSet::Types>
     {
-      typedef IndexSet< Grid, HostIndexSet > This;
-      typedef Dune::IndexSet< Grid, This, typename HostIndexSet::IndexType, typename HostIndexSet::Types > Base;
-
-      typedef typename std::remove_const< Grid >::type::Traits Traits;
+      using Self = IndexSet;
+      using Super = Dune::IndexSet<Grid, Self, typename HostIndexSet::IndexType, typename HostIndexSet::Types>;
 
-      typedef typename Traits::HostGrid HostGrid;
+      using Traits = typename std::remove_const_t<Grid>::Traits;
+      using HostGrid = typename Traits::HostGrid;
 
     public:
       static const int dimension = Traits::dimension;
 
-      typedef typename Base::IndexType IndexType;
+      using IndexType = typename Super::IndexType;
 
-      typedef typename Base::Types Types;
+      using Types = typename Super::Types;
 
+    public:
       IndexSet () = default;
 
-      explicit IndexSet ( const HostIndexSet &hostIndexSet )
-        : hostIndexSet_( &hostIndexSet )
+      explicit IndexSet (const HostIndexSet& hostIndexSet)
+        : hostIndexSet_(&hostIndexSet)
       {}
 
-      // The index set contains a pointer to the host index set, so copying or assigning this can be dangerous.
-      IndexSet ( const This & ) = delete;
-      IndexSet ( This && ) = delete;
-
-      IndexSet &operator= ( const This & ) = delete;
-      IndexSet &operator= ( This && ) = delete;
-
-      using Base::index;
-      using Base::subIndex;
-
       template< int cc >
-      IndexType index ( const typename Traits::template Codim< cc >::Entity &entity ) const
+      IndexType index (const typename Traits::template Codim<cc>::Entity& entity) const
       {
-        return entity.impl().index( hostIndexSet() );
+        return hostIndexSet().index(Grid::template getHostEntity<cc>(entity));
       }
 
+      using Super::index;
+
       template< int cc >
-      IndexType subIndex ( const typename Traits::template Codim< cc >::Entity &entity, int i, unsigned int codim ) const
+      IndexType subIndex (const typename Traits::template Codim<cc>::Entity& entity, int i, unsigned int codim) const
       {
-        return entity.impl().subIndex( hostIndexSet(), i, codim );
+        return hostIndexSet().subIndex(Grid::template getHostEntity<cc>(entity), i, codim);
       }
 
-      IndexType size ( GeometryType type ) const
+      using Super::subIndex;
+
+      IndexType size (GeometryType type) const
       {
-        return hostIndexSet().size( type );
+        return hostIndexSet().size(type);
       }
 
-      int size ( int codim ) const
+      int size (int codim) const
       {
-        return hostIndexSet().size( codim );
+        return hostIndexSet().size(codim);
       }
 
       template< class Entity >
-      bool contains ( const Entity &entity ) const
+      bool contains (const Entity& entity) const
       {
-        return entity.impl().isContained( hostIndexSet() );
+        return hostIndexSet().contains(Grid::template getHostEntity<Entity::codimension>(entity));
       }
 
-      Types types ( int codim ) const { return hostIndexSet().types( codim ); }
+      Types types (int codim) const
+      {
+        return hostIndexSet().types(codim);
+      }
 
-      const std::vector< GeometryType > &geomTypes ( int codim ) const
+      const std::vector<GeometryType>& geomTypes (int codim) const
       {
-        return hostIndexSet().geomTypes( codim );
+        return hostIndexSet().geomTypes(codim);
       }
 
-      explicit operator bool () const { return bool( hostIndexSet_ ); }
+      explicit operator bool () const { return bool(hostIndexSet_); }
 
       void reset () { hostIndexSet_ = nullptr; }
-      void reset ( const HostIndexSet &hostIndexSet ) { hostIndexSet_ = &hostIndexSet; }
+      void reset (const HostIndexSet& hostIndexSet) { hostIndexSet_ = &hostIndexSet; }
 
     private:
-      const HostIndexSet &hostIndexSet () const
+      const HostIndexSet& hostIndexSet () const
       {
         assert( *this );
         return *hostIndexSet_;
       }
 
-      const HostIndexSet *hostIndexSet_ = nullptr;
+      const HostIndexSet* hostIndexSet_ = nullptr;
     };
 
-  } // namespace crvsrf
-
+  } // namespace Curved
 } // namespace Dune
 
-#endif // #ifndef DUNE_CRVSRF_INDEXSETS_HH
+#endif // DUNE_CURVED_SURFACE_GRID_INDEXSETS_HH
diff --git a/dune/curvedsurfacegrid/intersection.hh b/dune/curvedsurfacegrid/intersection.hh
index 41e1274b09797a7bd0efae14b08aa7c4c20a50f8..2ad1e7e7f17948269d7dbac0c09bc15baa7e72b1 100644
--- a/dune/curvedsurfacegrid/intersection.hh
+++ b/dune/curvedsurfacegrid/intersection.hh
@@ -1,15 +1,18 @@
 // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
 // vi: set et ts=4 sw=2 sts=2:
-#ifndef DUNE_CRVSRF_INTERSECTION_HH
-#define DUNE_CRVSRF_INTERSECTION_HH
+#ifndef DUNE_CURVED_SURFACE_GRID_INTERSECTION_HH
+#define DUNE_CURVED_SURFACE_GRID_INTERSECTION_HH
 
-#include <dune/curvedsurfacegrid/declaration.hh>
-#include <dune/curvedsurfacegrid/coordprovider.hh>
+#include <type_traits>
+#include <utility>
+
+#include <dune/common/fvector.hh>
+#include <dune/common/std/optional.hh>
+#include <dune/geometry/referenceelements.hh>
 
 namespace Dune
 {
-
-  namespace crvsrf
+  namespace Curved
   {
 
     // Intersection
@@ -18,63 +21,50 @@ namespace Dune
     template< class Grid, class HostIntersection >
     class Intersection
     {
-      typedef typename HostIntersection::Geometry HostGeometry;
-      typedef typename HostIntersection::LocalGeometry HostLocalGeometry;
+      using HostGeometry = typename HostIntersection::Geometry;
+      using HostLocalGeometry = typename HostIntersection::LocalGeometry;
 
-      typedef typename std::remove_const< Grid >::type::Traits Traits;
+      using Traits = typename std::remove_const_t<Grid>::Traits;
+      using GridFunction = typename Traits::GridFunction;
 
     public:
-      typedef typename Traits::ctype ctype;
+      using ctype = typename Traits::ctype;
 
       static const int dimension = Traits::dimension;
       static const int dimensionworld = Traits::dimensionworld;
 
-      typedef typename Traits::template Codim< 0 >::Entity Entity;
-      typedef typename Traits::template Codim< 1 >::Geometry Geometry;
-      typedef typename Traits::template Codim< 1 >::LocalGeometry LocalGeometry;
-
-      typedef typename Traits::template Codim< 0 >::Geometry ElementGeometry;
+      using Entity = typename Traits::template Codim<0>::Entity;
+      using Geometry = typename Traits::template Codim<1>::Geometry;
+      using LocalGeometry = typename Traits::template Codim<1>::LocalGeometry;
+      using ElementGeometry = typename Traits::template Codim<0>::Geometry;
 
     private:
-      typedef crvsrf::IntersectionCoordProvider< Grid > ICoordProvider;
-
-      typedef typename Traits::template Codim< 0 >::EntityImpl EntityImpl;
-
-      typedef typename Traits::template Codim< 1 >::GeometryImpl GeometryImpl;
-      typedef typename Traits::template Codim< 0 >::GeometryImpl ElementGeometryImpl;
+      using EntityImpl = typename Traits::template Codim<0>::EntityImpl;
+      using GeometryImpl = typename Traits::template Codim<1>::GeometryImpl;
 
     public:
+      Intersection() = default;
 
-      Intersection()
-      {}
-
-      explicit Intersection ( const HostIntersection &hostIntersection, const ElementGeometryImpl &insideGeo )
-        : hostIntersection_( hostIntersection )
-        , insideGeo_ ( insideGeo )
-        , geo_( grid() )
-      {}
-
-      explicit Intersection ( HostIntersection&& hostIntersection, const ElementGeometryImpl &insideGeo )
-        : hostIntersection_( std::move( hostIntersection ) )
-        , insideGeo_ ( insideGeo )
-        , geo_( grid() )
+      Intersection (const HostIntersection& hostIntersection, const GridFunction& gridFunction)
+        : hostIntersection_(hostIntersection)
+        , gridFunction_(&gridFunction)
       {}
 
-      bool equals ( const Intersection &other) const
+      bool equals (const Intersection& other) const
       {
         return hostIntersection_ == other.hostIntersection_;
       }
 
-      explicit operator bool () const { return bool( hostIntersection_ ); }
+      explicit operator bool () const { return bool(hostIntersection_); }
 
       Entity inside () const
       {
-        return EntityImpl( insideGeo_, hostIntersection().inside() );
+        return EntityImpl(gridFunction(), hostIntersection().inside());
       }
 
       Entity outside () const
       {
-        return EntityImpl( grid(), hostIntersection().outside() );
+        return EntityImpl(gridFunction(), hostIntersection().outside());
       }
 
       bool boundary () const { return hostIntersection().boundary(); }
@@ -98,14 +88,21 @@ namespace Dune
         return hostIntersection().geometryInOutside();
       }
 
+      //! Construct a curved geometry for the intersection.
+      /**
+       * This does only work properly if the intersection is a full subEntity of inside and
+       * outside and the trace of the local basis functions along that subEntity is again
+       * a local basis function of codim=1
+       **/
       Geometry geometry () const
       {
-        if( !geo_ )
+        if (!geo_)
         {
-          ICoordProvider coords( insideGeo_, geometryInInside(), grid().coordFunction() );
-          geo_ = GeometryImpl( grid(), type(), coords );
+          auto localFct = localFunction(gridFunction());
+          localFct.bind(hostIntersection().inside());
+          geo_.emplace(type(), localFct, hostIntersection().geometryInInside());
         }
-        return Geometry( geo_ );
+        return Geometry(*geo_);
       }
 
       GeometryType type () const { return hostIntersection().type(); }
@@ -120,70 +117,72 @@ namespace Dune
         return hostIntersection().indexInOutside();
       }
 
-      FieldVector< ctype, dimensionworld >
-      integrationOuterNormal ( const FieldVector< ctype, dimension-1 > &local ) const
+      FieldVector<ctype, dimensionworld> outerNormal (const FieldVector<ctype, dimension-1>& local) const
       {
-        const LocalGeometry geoInInside = geometryInInside();
-        const int idxInInside = indexInInside();
-
-        auto refElement = referenceElement< ctype, dimension >( insideGeo_.type() );
-
-        FieldVector< ctype, dimension > x( geoInInside.global( local ) );
-        const typename ElementGeometryImpl::JacobianInverseTransposed &jit = insideGeo_.jacobianInverseTransposed( x );
-        FieldVector< ctype, dimension > refNormal = refElement.integrationOuterNormal( idxInInside );
-
-        FieldVector< ctype, dimensionworld > normal;
-        jit.mv( refNormal, normal );
-        if( !conforming() )
-          normal *= geoInInside.volume() / refElement.template geometry< 1 >( idxInInside ).volume();
-        normal *= jit.detInv();
-        //normal *= insideGeo_.integrationElement( x );
-        return normal;
+        return outerNormalImpl(local, false);
       }
 
-      FieldVector< ctype, dimensionworld >
-      outerNormal ( const FieldVector< ctype, dimension-1 > &local ) const
+      FieldVector<ctype, dimensionworld> integrationOuterNormal (const FieldVector<ctype, dimension-1>& local) const
       {
-        auto refElement = referenceElement< ctype, dimension >( insideGeo_.type() );
-
-        FieldVector< ctype, dimension > x( geometryInInside().global( local ) );
-        const typename ElementGeometryImpl::JacobianInverseTransposed &jit = insideGeo_.jacobianInverseTransposed( x );
-        FieldVector< ctype, dimension > refNormal = refElement.integrationOuterNormal( indexInInside() );
-
-        FieldVector< ctype, dimensionworld > normal;
-        jit.mv( refNormal, normal );
-        return normal;
+        return outerNormalImpl(local, true);
       }
 
-      FieldVector< ctype, dimensionworld >
-      unitOuterNormal ( const FieldVector< ctype, dimension-1 > &local ) const
+      FieldVector<ctype, dimensionworld> unitOuterNormal (const FieldVector<ctype, dimension-1>& local) const
       {
-        FieldVector< ctype, dimensionworld > normal = outerNormal( local );
-        normal *= (ctype( 1 ) / normal.two_norm());
-        return normal;
+        FieldVector<ctype, dimensionworld> normal = outerNormal(local);
+        return normal /= normal.two_norm();
       }
 
-      FieldVector< ctype, dimensionworld > centerUnitOuterNormal () const
+      FieldVector<ctype, dimensionworld> centerUnitOuterNormal () const
       {
-        auto refFace = referenceElement< ctype, dimension-1 >( type() );
-        return unitOuterNormal( refFace.position( 0, 0 ) );
+        auto refFace = referenceElement<ctype, dimension-1>(type());
+        return unitOuterNormal(refFace.position(0, 0));
       }
 
-      const HostIntersection &hostIntersection () const
+      const HostIntersection& hostIntersection () const
       {
         return hostIntersection_;
       }
 
-      const Grid &grid () const { return insideGeo_.grid(); }
+      const GridFunction& gridFunction () const { return *gridFunction_; }
+
+    private:
+      FieldVector<ctype, dimensionworld>
+      outerNormalImpl (const FieldVector<ctype, dimension-1>& local, bool scaleByIntegrationElement) const
+      {
+        if (!insideGeo_)
+          insideGeo_.emplace(inside().impl().geometry());
+
+        const LocalGeometry geoInInside = geometryInInside();
+        const int idxInInside = indexInInside();
+        auto refElement = referenceElement<ctype, dimension>(insideGeo_->type());
+
+        FieldVector<ctype, dimension> x(geoInInside.global(local));
+        const auto& jit = insideGeo_->jacobianInverseTransposed(x);
+        FieldVector<ctype, dimension> refNormal = refElement.integrationOuterNormal(idxInInside);
+
+        FieldVector<ctype, dimensionworld> normal;
+        jit.mv(refNormal, normal);
+
+        if (scaleByIntegrationElement) {
+          if (!conforming())
+            normal *= geoInInside.volume() / refElement.template geometry<1>(idxInInside).volume();
+          // normal *= jit.detInv(); TODO: what is detInv()?
+        }
+
+        return normal;
+      }
 
     private:
       HostIntersection hostIntersection_;
-      ElementGeometryImpl insideGeo_;
-      mutable GeometryImpl geo_;
-    };
+      const GridFunction* gridFunction_ = nullptr;
 
-  } // namespace crvsrf
+      // geometry caches
+      mutable Std::optional<ElementGeometry> insideGeo_;
+      mutable Std::optional<GeometryImpl> geo_;
+    };
 
+  } // namespace Curved
 } // namespace Dune
 
-#endif // #ifndef DUNE_CRVSRF_INTERSECTION_HH
+#endif // DUNE_CURVED_SURFACE_GRID_INTERSECTION_HH
diff --git a/dune/curvedsurfacegrid/intersectioniterator.hh b/dune/curvedsurfacegrid/intersectioniterator.hh
index 9f8760da15fe25bf29c6f5fbb37307fe72a98677..367add5f3d7046b5fb57ae96aedc4f0bc9483c24 100644
--- a/dune/curvedsurfacegrid/intersectioniterator.hh
+++ b/dune/curvedsurfacegrid/intersectioniterator.hh
@@ -1,14 +1,13 @@
 // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
 // vi: set et ts=4 sw=2 sts=2:
-#ifndef DUNE_CRVSRF_INTERSECTIONITERATOR_HH
-#define DUNE_CRVSRF_INTERSECTIONITERATOR_HH
+#ifndef DUNE_CURVED_SURFACE_GRID_INTERSECTIONITERATOR_HH
+#define DUNE_CURVED_SURFACE_GRID_INTERSECTIONITERATOR_HH
 
 #include <dune/curvedsurfacegrid/intersection.hh>
 
 namespace Dune
 {
-
-  namespace crvsrf
+  namespace Curved
   {
 
     // IntersectionIterator
@@ -17,51 +16,26 @@ namespace Dune
     template< class Grid, class HostIntersectionIterator >
     class IntersectionIterator
     {
-      typedef typename std::remove_const< Grid >::type::Traits Traits;
-
-      typedef crvsrf::Intersection< Grid, typename HostIntersectionIterator::Intersection > IntersectionImpl;
+      using IntersectionImpl = Curved::Intersection<Grid, typename HostIntersectionIterator::Intersection>;
 
-      typedef typename Traits::template Codim< 0 >::Geometry ElementGeometry;
-      typedef typename Traits::template Codim< 0 >::GeometryImpl ElementGeometryImpl;
+      using Traits = typename std::remove_const_t<Grid>::Traits;
+      using GridFunction = typename Traits::GridFunction;
+      using Element = typename Traits::template Codim<0>::Entity;
+      using ElementGeometry = typename Traits::template Codim<0>::Geometry;
+      //using ElementGeometryImpl = typename Traits::template Codim<0>::GeometryImpl;
 
     public:
-      typedef Dune::Intersection< Grid, IntersectionImpl > Intersection;
-
-      IntersectionIterator()
-      {}
+      using Intersection = Dune::Intersection< Grid, IntersectionImpl>;
 
-      template< class Entity >
-      IntersectionIterator ( const Entity &inside,
-                             const HostIntersectionIterator &hostIterator )
-        : hostIterator_( hostIterator )
-        , insideGeo_( inside.geometry().impl() )
-      {}
-
-      IntersectionIterator ( const IntersectionIterator &other )
-        : hostIterator_( other.hostIterator_ )
-        , insideGeo_( other.insideGeo_ )
-      {}
+      IntersectionIterator() = default;
 
-      IntersectionIterator ( IntersectionIterator&& other )
-        : hostIterator_( std::move( other.hostIterator_ ) )
-        , insideGeo_( std::move( other.insideGeo_ ) )
+      //template< class Entity >
+      IntersectionIterator (const Element& inside, const HostIntersectionIterator& hostIterator)
+        : hostIterator_(hostIterator)
+        , gridFunction_(&inside.impl().gridFunction())
       {}
 
-      IntersectionIterator &operator= ( const IntersectionIterator &other )
-      {
-        hostIterator_ = other.hostIterator_;
-        insideGeo_ = other.insideGeo_;
-        return *this;
-      }
-
-      IntersectionIterator &operator= ( IntersectionIterator&& other )
-      {
-        hostIterator_ = std::move( other.hostIterator_ );
-        insideGeo_ = std::move( other.insideGeo_ );
-        return *this;
-      }
-
-      bool equals ( const IntersectionIterator &other ) const
+      bool equals (const IntersectionIterator& other) const
       {
         return (hostIterator_ == other.hostIterator_);
       }
@@ -73,18 +47,15 @@ namespace Dune
 
       Intersection dereference () const
       {
-        return IntersectionImpl( *hostIterator_, insideGeo_ );
+        return IntersectionImpl(*hostIterator_, *gridFunction_);
       }
 
     private:
-
       HostIntersectionIterator hostIterator_;
-      ElementGeometryImpl insideGeo_;
-
+      const GridFunction* gridFunction_ = nullptr;
     };
 
-  } // namespace crvsrf
-
+  } // namespace Curved
 } // namespace Dune
 
-#endif // #ifndef DUNE_CRVSRF_INTERSECTIONITERATOR_HH
+#endif // DUNE_CURVED_SURFACE_GRID_INTERSECTIONITERATOR_HH
diff --git a/dune/curvedsurfacegrid/iterator.hh b/dune/curvedsurfacegrid/iterator.hh
index dec42e9fdae176e8bb9d972699b14e1bb7f4a012..f20eee37a6cae37a90b5373c382c1b8b34bbb230 100644
--- a/dune/curvedsurfacegrid/iterator.hh
+++ b/dune/curvedsurfacegrid/iterator.hh
@@ -1,212 +1,54 @@
 // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
 // vi: set et ts=4 sw=2 sts=2:
-#ifndef DUNE_CRVSRF_ITERATOR_HH
-#define DUNE_CRVSRF_ITERATOR_HH
+#ifndef DUNE_CURVED_SURFACE_GRID_ITERATOR_HH
+#define DUNE_CURVED_SURFACE_GRID_ITERATOR_HH
 
 #include <cassert>
-
 #include <type_traits>
 #include <utility>
 
 #include <dune/geometry/referenceelements.hh>
-
 #include <dune/curvedsurfacegrid/entity.hh>
 
 namespace Dune
 {
-
-  namespace crvsrf
+  namespace Curved
   {
-
     // Internal Forward Declarations
     // -----------------------------
 
-    template< class HostGridView, int codim, PartitionIteratorType pitype, class Grid,
-              bool fake = !Capabilities::hasHostEntity< Grid, codim >::v >
+    template< class HostGridView, int codim, PartitionIteratorType pitype, class Grid >
     class Iterator;
 
     template< class Grid >
     class HierarchicIterator;
 
 
-
-    // PartitionIteratorFilter
-    // -----------------------
-
-    template< int codim, PartitionIteratorType pitype, class Grid >
-    struct PartitionIteratorFilter;
-
-    template< int codim, class Grid >
-    struct PartitionIteratorFilter< codim, Interior_Partition, Grid >
-    {
-      static const int dimension = std::remove_const< Grid >::type::dimension;
-      static const int codimension = codim;
-
-      static const PartitionIteratorType Element_Partition = Interior_Partition;
-
-      typedef typename std::remove_const< Grid >::type::ctype ctype;
-      typedef typename std::remove_const< Grid >::type::Traits::template Codim< 0 >::Entity Element;
-      typedef Transitional::ReferenceElement< ctype, Dim<dimension> > RefElement;
-
-      static bool apply ( const RefElement &refElement,
-                          const Element &element, int subEntity )
-      {
-        const int size = refElement.size( subEntity, codim, dimension );
-        for( int i = 0; i < size; ++i )
-        {
-          const int j = refElement.subEntity( subEntity, codim, i, dimension );
-          PartitionType type = element.template subEntity< dimension >( j ).partitionType();
-          if( type == InteriorEntity )
-            return true;
-        }
-        return false;
-      }
-    };
-
-    template< int codim, class Grid >
-    struct PartitionIteratorFilter< codim, InteriorBorder_Partition, Grid >
-    {
-      static const int dimension = std::remove_const< Grid >::type::dimension;
-      static const int codimension = codim;
-
-      static const PartitionIteratorType Element_Partition = Interior_Partition;
-
-      typedef typename std::remove_const< Grid >::type::ctype ctype;
-      typedef typename std::remove_const< Grid >::type::Traits::template Codim< 0 >::Entity Element;
-      typedef Transitional::ReferenceElement< ctype, Dim<dimension> > RefElement;
-
-      static bool apply ( const RefElement &refElement,
-                          const Element &element, int subEntity )
-      {
-        return true;
-      }
-    };
-
-    template< int codim, class Grid >
-    struct PartitionIteratorFilter< codim, Overlap_Partition, Grid >
-    {
-      static const int dimension = std::remove_const< Grid >::type::dimension;
-      static const int codimension = codim;
-
-      static const PartitionIteratorType Element_Partition = Overlap_Partition;
-
-      typedef typename std::remove_const< Grid >::type::ctype ctype;
-      typedef typename std::remove_const< Grid >::type::Traits::template Codim< 0 >::Entity Element;
-      typedef Transitional::ReferenceElement< ctype, Dim<dimension> > RefElement;
-
-      static bool apply ( const RefElement &refElement,
-                          const Element &element, int subEntity )
-      {
-        if( element.partitionType() == InteriorEntity )
-          return true;
-
-        const int size = refElement.size( subEntity, codim, dimension );
-        for( int i = 0; i < size; ++i )
-        {
-          const int j = refElement.subEntity( subEntity, codim, i, dimension );
-          PartitionType type = element.template subEntity< dimension >( j ).partitionType();
-          if( (type == OverlapEntity) || (type == BorderEntity) )
-            return true;
-        }
-        return false;
-      }
-    };
-
-    template< int codim, class Grid >
-    struct PartitionIteratorFilter< codim, OverlapFront_Partition, Grid >
-    {
-      static const int dimension = std::remove_const< Grid >::type::dimension;
-      static const int codimension = codim;
-
-      static const PartitionIteratorType Element_Partition = Overlap_Partition;
-
-      typedef typename std::remove_const< Grid >::type::ctype ctype;
-      typedef typename std::remove_const< Grid >::type::Traits::template Codim< 0 >::Entity Element;
-      typedef Transitional::ReferenceElement< ctype, Dim<dimension> > RefElement;
-
-      static bool apply ( const RefElement &refElement,
-                          const Element &element, int subEntity )
-      {
-        return true;
-      }
-    };
-
-    template< int codim, class Grid >
-    struct PartitionIteratorFilter< codim, All_Partition, Grid >
-    {
-      static const int dimension = std::remove_const< Grid >::type::dimension;
-      static const int codimension = codim;
-
-      static const PartitionIteratorType Element_Partition = All_Partition;
-
-      typedef typename std::remove_const< Grid >::type::ctype ctype;
-      typedef typename std::remove_const< Grid >::type::Traits::template Codim< 0 >::Entity Element;
-      typedef Transitional::ReferenceElement< ctype, Dim<dimension> > RefElement;
-
-      static bool apply ( const RefElement &refElement,
-                          const Element &element, int subEntity )
-      {
-        return true;
-      }
-    };
-
-    template< int codim, class Grid >
-    struct PartitionIteratorFilter< codim, Ghost_Partition, Grid >
-    {
-      static const int dimension = std::remove_const< Grid >::type::dimension;
-      static const int codimension = codim;
-
-      static const PartitionIteratorType Element_Partition = Ghost_Partition;
-
-      typedef typename std::remove_const< Grid >::type::ctype ctype;
-      typedef typename std::remove_const< Grid >::type::Traits::template Codim< 0 >::Entity Element;
-      typedef Transitional::ReferenceElement< ctype, Dim<dimension> > RefElement;
-
-      static bool apply ( const RefElement &refElement,
-                          const Element &element, int subEntity )
-      {
-        const int size = refElement.size( subEntity, codim, dimension );
-        for( int i = 0; i < size; ++i )
-        {
-          const int j = refElement.subEntity( subEntity, codim, i, dimension );
-          PartitionType type = element.template subEntity< dimension >( j ).partitionType();
-          if( type == GhostEntity )
-            return true;
-        }
-        return false;
-      }
-    };
-
-
-
-    // Iterator (real)
-    // ---------------
+    // Iterator
+    // --------
 
     template< class HostGridView, int codim, PartitionIteratorType pitype, class G >
-    class Iterator< HostGridView, codim, pitype, G, false >
+    class Iterator
     {
-      typedef typename std::remove_const< G >::type::Traits Traits;
+      using Traits = typename std::remove_const_t<G>::Traits;
 
     public:
-      typedef typename Traits::Grid Grid;
-
       static const int codimension = codim;
 
-      typedef typename Traits::template Codim< codimension >::Entity Entity;
-
-      static const bool fake = false;
+      using Grid = typename Traits::Grid;
+      using GridFunction = typename Traits::GridFunction;
+      using Entity = typename Traits::template Codim<codimension>::Entity;
 
     private:
-      typedef crvsrf::Entity< codimension, Traits::dimension, G > EntityImpl;
-
-      typedef typename HostGridView::template Codim< codim >::template Partition< pitype >::Iterator HostEntityIterator;
+      using EntityImpl = Curved::Entity<codimension, Traits::dimension, G>;
+      using HostEntityIterator = typename HostGridView::template Codim<codim>::template Partition<pitype>::Iterator;
 
     public:
-      Iterator () : grid_( nullptr ) {}
+      Iterator () = default;
 
-      Iterator ( const Grid &grid, HostEntityIterator hostEntityIterator )
-        : grid_( &grid ),
-          hostEntityIterator_( std::move( hostEntityIterator ) )
+      Iterator (const GridFunction& gridFunction, HostEntityIterator hostEntityIterator)
+        : gridFunction_(&gridFunction)
+        , hostEntityIterator_(std::move(hostEntityIterator))
       {}
 
       void increment ()
@@ -214,180 +56,70 @@ namespace Dune
         ++hostEntityIterator_;
       }
 
-      bool equals ( const Iterator &rhs ) const
+      bool equals (const Iterator& rhs) const
       {
         return hostEntityIterator_ == rhs.hostEntityIterator_;
       }
 
       Entity dereference () const
       {
-        return EntityImpl( grid(), *hostEntityIterator_ );
+        return EntityImpl(gridFunction(), *hostEntityIterator_);
       }
 
-      int level () const { return hostEntityIterator_.level(); }
-
-      const Grid &grid () const
+      int level () const
       {
-        assert( grid_ );
-        return *grid_;
+        return hostEntityIterator_.level();
       }
 
-      static Iterator begin ( const Grid &grid, const HostGridView &hostGridView )
+      const GridFunction& gridFunction () const
       {
-        HostEntityIterator hostEntityIterator = hostGridView.template begin< codimension, pitype >();
-        return Iterator( grid, std::move( hostEntityIterator ) );
+        return *gridFunction_;
       }
 
-      static Iterator end ( const Grid &grid, const HostGridView &hostGridView )
+      static Iterator begin (const GridFunction& gf, const HostGridView& hostGridView)
       {
-        HostEntityIterator hostEntityIterator = hostGridView.template end< codimension, pitype >();
-        return Iterator( grid, std::move( hostEntityIterator ) );
+        HostEntityIterator hostEntityIterator = hostGridView.template begin<codimension, pitype>();
+        return Iterator(gf, std::move(hostEntityIterator));
       }
 
-    private:
-      const Grid *grid_;
-      HostEntityIterator hostEntityIterator_;
-    };
-
-
-
-    // Iterator (fake)
-    // ---------------
-
-    template< class HostGridView, int codim, PartitionIteratorType pitype, class G >
-    class Iterator< HostGridView, codim, pitype, G, true >
-    {
-      typedef typename std::remove_const< G >::type::Traits Traits;
-
-    public:
-      typedef typename Traits::Grid Grid;
-
-      static const int codimension = codim;
-
-      typedef typename Traits::template Codim< codimension >::Entity Entity;
-
-    private:
-      typedef crvsrf::Entity< codimension, Traits::dimension, G > EntityImpl;
-
-      typedef PartitionIteratorFilter< codim, pitype, typename HostGridView::Grid > Filter;
-
-      typedef typename HostGridView::template Codim<0>::template Partition< Filter::Element_Partition >::Iterator HostElementIterator;
-      typedef typename HostElementIterator::Entity HostElement;
-      typedef typename HostGridView::IndexSet HostIndexSet;
-
-    public:
-      Iterator () : grid_( nullptr ), subEntity_( -1 ), hostIndexSet_( nullptr ) {}
-
-      Iterator ( const Grid &grid, HostElementIterator hostElementIterator, HostElementIterator hostEnd, const HostIndexSet &hostIndexSet )
-        : grid_( &grid ),
-          hostElementIterator_( hostElementIterator ),
-          hostEnd_( hostEnd ),
-          subEntity_( -1 ),
-          hostIndexSet_( &hostIndexSet )
+      static Iterator end (const GridFunction& gf, const HostGridView& hostGridView)
       {
-        if( hostElementIterator_ != hostEnd_ )
-        {
-          visited_.resize( hostIndexSet_->size( codimension ), false );
-          increment();
-        }
-      }
-
-      void increment ()
-      {
-        typedef typename Traits::ctype ctype;
-
-        while( hostElementIterator_ != hostEnd_ )
-        {
-          const HostElement &hostElement = *hostElementIterator_;
-
-          auto refElement = referenceElement< ctype, Traits::dimension >( hostElement.type() );
-
-          ++subEntity_;
-          const int count = refElement.size( codimension );
-          for( ; subEntity_ < count; ++subEntity_ )
-          {
-            if( !Filter::apply( refElement, hostElement, subEntity_ ) )
-              continue;
-
-            const size_t index = hostIndexSet_->subIndex( hostElement, subEntity_, codimension );
-            if( !visited_[ index ] )
-            {
-              visited_[ index ] = true;
-              return;
-            }
-          }
-          ++hostElementIterator_;
-          subEntity_ = -1;
-        }
-      }
-
-      bool equals ( const Iterator &rhs ) const
-      {
-        return hostElementIterator_ == rhs.hostElementIterator_ && ( hostElementIterator_ == hostEnd_ || subEntity_ == rhs.subEntity_ );
-      }
-
-      Entity dereference () const
-      {
-        return EntityImpl( grid(), *hostElementIterator_, subEntity_ );
-      }
-
-      int level () const { return hostElementIterator_.level(); }
-
-      const Grid &grid () const
-      {
-        assert( grid_ );
-        return *grid_;
-      }
-
-      static Iterator begin ( const Grid &grid, const HostGridView &hostGridView )
-      {
-        HostElementIterator first = hostGridView.template begin< 0, Filter::Element_Partition >();
-        HostElementIterator last = hostGridView.template end< 0, Filter::Element_Partition >();
-        return Iterator( grid, std::move( first ), std::move( last ), hostGridView.indexSet() );
-      }
-
-      static Iterator end ( const Grid &grid, const HostGridView &hostGridView )
-      {
-        HostElementIterator last = hostGridView.template end< 0, Filter::Element_Partition >();
-        return Iterator( grid, last, last, hostGridView.indexSet() );
+        HostEntityIterator hostEntityIterator = hostGridView.template end<codimension, pitype>();
+        return Iterator(gf, std::move(hostEntityIterator));
       }
 
     private:
-      const Grid *grid_;
-      HostElementIterator hostElementIterator_, hostEnd_;
-      int subEntity_;
-      const HostIndexSet *hostIndexSet_;
-      std::vector< bool > visited_;
+      const GridFunction* gridFunction_;
+      HostEntityIterator hostEntityIterator_;
     };
 
 
-
     // HierarchicIterator
     // ------------------
 
     template< class G >
     class HierarchicIterator
     {
-      typedef typename std::remove_const< G >::type::Traits Traits;
+      using Traits = typename std::remove_const_t<G>::Traits;
 
     public:
-      typedef typename Traits::Grid Grid;
-
       static const int codimension = 0;
 
-      typedef typename Traits::template Codim< codimension >::Entity Entity;
+      using Grid = typename Traits::Grid;
+      using GridFunction = typename Traits::GridFunction;
+      using Entity = typename Traits::template Codim<codimension>::Entity;
 
     private:
-      typedef crvsrf::Entity< codimension, Traits::dimension, G > EntityImpl;
-
-      typedef typename Grid::HostGrid::HierarchicIterator HostEntityIterator;
+      using EntityImpl = Curved::Entity<codimension, Traits::dimension, G>;
+      using HostEntityIterator = typename Grid::Traits::HostGrid::HierarchicIterator;
 
     public:
-      HierarchicIterator () : grid_( nullptr ) {}
+      HierarchicIterator () = default;
 
-      HierarchicIterator ( const Grid &grid, HostEntityIterator hostEntityIterator )
-        : grid_( &grid ),
-          hostEntityIterator_( std::move( hostEntityIterator ) )
+      //! Constructor. Stores a pointer to the grid and the iterator by value.
+      HierarchicIterator (const GridFunction& gridFunction, HostEntityIterator hostEntityIterator)
+        : gridFunction_(&gridFunction)
+        , hostEntityIterator_(std::move(hostEntityIterator))
       {}
 
       void increment ()
@@ -395,31 +127,32 @@ namespace Dune
         ++hostEntityIterator_;
       }
 
-      bool equals ( const HierarchicIterator &rhs ) const
+      bool equals (const HierarchicIterator& rhs) const
       {
         return hostEntityIterator_ == rhs.hostEntityIterator_;
       }
 
       Entity dereference () const
       {
-        return EntityImpl( grid(), *hostEntityIterator_ );
+        return EntityImpl(gridFunction(), *hostEntityIterator_);
       }
 
-      int level () const { return hostEntityIterator_.level(); }
+      int level () const
+      {
+        return hostEntityIterator_.level();
+      }
 
-      const Grid &grid () const
+      const GridFunction& gridFunction () const
       {
-        assert( grid_ );
-        return *grid_;
+        return *gridFunction_;
       }
 
     private:
-      const Grid *grid_;
+      const GridFunction* gridFunction_ = nullptr;
       HostEntityIterator hostEntityIterator_;
     };
 
-  } // namespace crvsrf
-
+  } // namespace Curved
 } // namespace Dune
 
-#endif // #ifndef DUNE_CRVSRF_ITERATOR_HH
+#endif // DUNE_CURVED_SURFACE_GRID_ITERATOR_HH
diff --git a/dune/curvedsurfacegrid/localgeometrywrapper.hh b/dune/curvedsurfacegrid/localgeometrywrapper.hh
new file mode 100644
index 0000000000000000000000000000000000000000..412d51cfcf5c9cfccb11041ffab6a7399dba665b
--- /dev/null
+++ b/dune/curvedsurfacegrid/localgeometrywrapper.hh
@@ -0,0 +1,43 @@
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+#ifndef DUNE_CURVED_SURFACE_GRID_LOCALGEOMETRYWRAPPER_HH
+#define DUNE_CURVED_SURFACE_GRID_LOCALGEOMETRYWRAPPER_HH
+
+#include <functional>
+#include <utility>
+
+namespace Dune
+{
+  namespace Curved
+  {
+    /// type-erased wrapper for local geometries
+    /**
+     * \tparam LG  Type of a local geometry
+     **/
+    template <class LG>
+    struct LocalGeometryWrapper
+    {
+      using LocalCoordinate = typename LG::LocalCoordinate;
+      using GlobalCoordinate = typename LG::GlobalCoordinate;
+      using JacobianTransposed = typename LG::JacobianTransposed;
+
+      template <class LocalGeometry>
+      LocalGeometryWrapper(const LocalGeometry& lg)
+        : global([lg](auto const& local) { return lg.global(local); })
+        , jacobianTransposed([lg](auto const& local) { return lg.jacobianTransposed(local); })
+      {}
+
+      template <class GlobalFct, class JacobianTransposedFct>
+      LocalGeometryWrapper(GlobalFct&& g, JacobianTransposedFct&& jt)
+        : global(std::forward<GlobalFct>(g))
+        , jacobianTransposed(std::forward<JacobianTransposedFct>(jt))
+      {}
+
+      std::function<GlobalCoordinate(LocalCoordinate)> global;
+      std::function<JacobianTransposed(LocalCoordinate)> jacobianTransposed;
+    };
+
+  } // end namespace Curved
+} // end namespace Dune
+
+#endif // DUNE_CURVED_SURFACE_GRID_LOCALGEOMETRYWRAPPER_HH
diff --git a/dune/curvedsurfacegrid/surfacedistance/CMakeLists.txt b/dune/curvedsurfacegrid/surfacedistance/CMakeLists.txt
index 9eab2b301019ce67ab0d87cb6ff9db9809adff1a..525b283cb3981c2a6b76c6c685e7ed2dc019dd73 100644
--- a/dune/curvedsurfacegrid/surfacedistance/CMakeLists.txt
+++ b/dune/curvedsurfacegrid/surfacedistance/CMakeLists.txt
@@ -7,7 +7,9 @@ dune_add_library("surfacedistance" OBJECT
   vtureader.hh)
 
 #install headers
-install(FILES datastructures.hh
-              surfacedistance.hh
-              vtureader.hh
-        DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/curvedsurfacegrid/surfacedistance)
+install(FILES 
+  datastructures.hh
+  surfacedistance.hh
+  vertexmap.hh
+  vtureader.hh
+  DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/curvedsurfacegrid/surfacedistance)
diff --git a/dune/curvedsurfacegrid/surfacedistance/datastructures.hh b/dune/curvedsurfacegrid/surfacedistance/datastructures.hh
index 6642b6275e682b25e64e735d1fdc8466b021d64c..948f925784006879defa1e5c20e5ab41da8f5308 100644
--- a/dune/curvedsurfacegrid/surfacedistance/datastructures.hh
+++ b/dune/curvedsurfacegrid/surfacedistance/datastructures.hh
@@ -1,13 +1,14 @@
-#ifndef DUNE_CRVSRF_DATASTRUCTURES_HH
-#define DUNE_CRVSRF_DATASTRUCTURES_HH
+#ifndef DUNE_CURVED_SURFACE_GRID_DATASTRUCTURES_HH
+#define DUNE_CURVED_SURFACE_GRID_DATASTRUCTURES_HH
 
 #include <fstream>
 #include <sstream>
 #include <vector>
 #include <list>
 #include <stdint.h>
+#include <cfloat>
 
-namespace Dune{ namespace crvsrf{
+namespace Dune{ namespace Curved{
 
 const int output_precision = 10;
 const size_t npos = std::string::npos;
@@ -237,8 +238,8 @@ struct Mesh{
   //determine_coordinate_extrema
   void determine_coordinate_extrema(Vertex &min_value, Vertex &max_value) const{
     for(int p = 0; p < dim_of_world; ++p){
-      max_value[p] = -9e100;
-      min_value[p] = 9e100;
+      max_value[p] = -DBL_MAX;
+      min_value[p] = DBL_MAX;
     }
     for(int i = 0, i_end = vertices.size(); i < i_end; ++i){
       for(int p = 0; p < dim_of_world; ++p){
@@ -249,6 +250,6 @@ struct Mesh{
   }
 };
 
-}} //end namespace Dune::crvsrf
+}} //end namespace Dune::CurvedGeo
 
-#endif //DUNE_CRVSRF_DATASTRUCTURES_HH
+#endif //DUNE_CURVED_SURFACE_GRID_DATASTRUCTURES_HH
diff --git a/dune/curvedsurfacegrid/surfacedistance/surfacedistance.cc b/dune/curvedsurfacegrid/surfacedistance/surfacedistance.cc
index 9d69339c189defff7ab716ed3c939ec44fce4071..65eca88b71fb56f202c0dea7b5485181cfff043e 100644
--- a/dune/curvedsurfacegrid/surfacedistance/surfacedistance.cc
+++ b/dune/curvedsurfacegrid/surfacedistance/surfacedistance.cc
@@ -2,7 +2,7 @@
 #include <iostream>
 #include <cmath>
 
-using namespace Dune::crvsrf;
+using namespace Dune::Curved;
 
 //                    #########################
 //                    ##  Geometry-Routines  ##
diff --git a/dune/curvedsurfacegrid/surfacedistance/surfacedistance.hh b/dune/curvedsurfacegrid/surfacedistance/surfacedistance.hh
index 8bc837a16737f0db22134f2579d52a49c9549e7d..1a696d7d3afa8304052a7cb0077bef23d0b1300e 100644
--- a/dune/curvedsurfacegrid/surfacedistance/surfacedistance.hh
+++ b/dune/curvedsurfacegrid/surfacedistance/surfacedistance.hh
@@ -1,9 +1,9 @@
-#ifndef DUNE_CRVSRF_SURFACEDISTANCE_HH
-#define DUNE_CRVSRF_SURFACEDISTANCE_HH
+#ifndef DUNE_CURVED_SURFACE_GRID_SURFACEDISTANCE_HH
+#define DUNE_CURVED_SURFACE_GRID_SURFACEDISTANCE_HH
 
 #include <dune/curvedsurfacegrid/surfacedistance/datastructures.hh>
 
-namespace Dune{ namespace crvsrf{
+namespace Dune{ namespace Curved{
 
 //--------------------< BackGrid >
 struct BackGrid{
@@ -31,6 +31,6 @@ struct BackGrid{
                                    double &min_distance, Vertex &hit_vertex);
 };
 
-}} //end namespace Dune::crvsrf
+}} //end namespace Dune::CurvedGeo
 
-#endif //DUNE_CRVSRF_SURFACEDISTANCE_HH
+#endif //DUNE_CURVED_SURFACE_GRID_SURFACEDISTANCE_HH
diff --git a/dune/curvedsurfacegrid/surfacedistance/vertexmap.hh b/dune/curvedsurfacegrid/surfacedistance/vertexmap.hh
index 59a11622e939b2355ce55a9cf4557f717eb75d5b..e21481d3a7f1d5c4328ca9ccd85a18d3ded8eab8 100644
--- a/dune/curvedsurfacegrid/surfacedistance/vertexmap.hh
+++ b/dune/curvedsurfacegrid/surfacedistance/vertexmap.hh
@@ -1,11 +1,12 @@
-#ifndef DUNE_CRVSRF_VERTEXMAP_HH
-#define DUNE_CRVSRF_VERTEXMAP_HH
+#ifndef DUNE_CURVED_SURFACE_GRID_VERTEXMAP_HH
+#define DUNE_CURVED_SURFACE_GRID_VERTEXMAP_HH
 
 #include <dune/curvedsurfacegrid/surfacedistance/datastructures.hh>
+#include <cmath>
 
 #define VERTEXMAP_DEBUG_MODE 0
 
-namespace Dune{ namespace crvsrf{
+namespace Dune{ namespace Curved{
 
 //--------------------< VertexMap >
 template<typename T> struct VertexMap{
@@ -56,7 +57,7 @@ template<typename T> int VertexMap<T>::partition_threshold = 64;
 template<typename T> int VertexMap<T>::depth_threshold_1d = 19;
 template<typename T> int VertexMap<T>::depth_threshold_2d = 10;
 template<typename T> int VertexMap<T>::depth_threshold_3d = 7;
-template<typename T> double VertexMap<T>::config_epsilon = epsilon;
+template<typename T> double VertexMap<T>::config_epsilon = Curved::epsilon;
 
 //--------------------< destructor >
 template<typename T> VertexMap<T>::~VertexMap(){ //$ACL_exclude
@@ -184,7 +185,7 @@ template<typename T> bool VertexMap<T>::find_1d(const Vertex &v, T &result){
     for(typename std::vector<std::pair<Vertex, T> >::iterator it = entries.begin(),
                                                end = entries.end(); it != end; ++it){
       Vertex &t = it->first;
-      if(abs(t.c[0] - v.c[0]) <= config_epsilon){
+      if(fabs(t.c[0] - v.c[0]) <= config_epsilon){
         result = it->second;
         return true;
       }
@@ -202,7 +203,7 @@ template<typename T> bool VertexMap<T>::find_2d(const Vertex &v, T &result){
     for(typename std::vector<std::pair<Vertex, T> >::iterator it = entries.begin(),
                                                end = entries.end(); it != end; ++it){
       Vertex &t = it->first;
-      if(abs(t.c[0] - v.c[0]) <= config_epsilon && abs(t.c[1] - v.c[1]) <= config_epsilon){
+      if(fabs(t.c[0] - v.c[0]) <= config_epsilon && fabs(t.c[1] - v.c[1]) <= config_epsilon){
         result = it->second;
         return true;
       }
@@ -226,8 +227,8 @@ template<typename T> bool VertexMap<T>::find_3d(const Vertex &v, T &result){
     for(typename std::vector<std::pair<Vertex, T> >::iterator it = entries.begin(),
                                                end = entries.end(); it != end; ++it){
       Vertex &t = it->first;
-      if(abs(t.c[0] - v.c[0]) <= config_epsilon && abs(t.c[1] - v.c[1]) <= config_epsilon
-                                                 && abs(t.c[2] - v.c[2]) <= config_epsilon){
+      if(fabs(t.c[0] - v.c[0]) <= config_epsilon && fabs(t.c[1] - v.c[1]) <= config_epsilon
+                                                 && fabs(t.c[2] - v.c[2]) <= config_epsilon){
         result = it->second;
         return true;
       }
@@ -385,6 +386,6 @@ template<typename T> void VertexMap<T>::debug_output(int indentation/*=0*/){
 }
 #endif
 
-}} //end namespace Dune::crvsrf
+}} //end namespace Dune::CurvedGeo
 
-#endif //DUNE_CRVSRF_VERTEXMAP_HH
+#endif //DUNE_CURVED_SURFACE_GRID_VERTEXMAP_HH
diff --git a/dune/curvedsurfacegrid/surfacedistance/vtureader.cc b/dune/curvedsurfacegrid/surfacedistance/vtureader.cc
index 37a5ad2d288b40a860a01755ffcf834ca301ca4e..37b965cec4f448bc5ec86ff2860657b7c96c8cb1 100644
--- a/dune/curvedsurfacegrid/surfacedistance/vtureader.cc
+++ b/dune/curvedsurfacegrid/surfacedistance/vtureader.cc
@@ -8,7 +8,7 @@
   #include <boost/iostreams/filter/bzip2.hpp> //bzip2 is slower but compresses better, usually.
 #endif
 
-using namespace Dune::crvsrf;
+using namespace Dune::Curved;
 
 //--------------------< decompress_buffer >
 //Use this routine if the size of the uncompressed data 'osize' is known. Decompresses buffer 'ibuf'
@@ -186,7 +186,7 @@ struct VtuValueDecompressor : public VtuValueReader{
 
 //--------------------< read_vtu_file >
 //triangular meshes in 2d- and 3d-worlds and tetrahedral meshes in 3d worlds supported at the moment
-void Dune::crvsrf::read_vtu_file(std::string file, Mesh &m, std::vector<DataVector*> &vecs,
+void Dune::Curved::read_vtu_file(std::string file, Mesh &m, std::vector<DataVector*> &vecs,
                                                      std::vector<DataVector*> &element_vecs){
   std::string buf = "";
   std::string connectivity_buf;
@@ -621,7 +621,7 @@ void Dune::crvsrf::read_vtu_file(std::string file, Mesh &m, std::vector<DataVect
         vvr->initialize();
         if(datatypes_point_data[e] == "Float32"){
           unsigned entry_count = vvr->total_size / 4;
-          if(int(entry_count / component_counts_point_data[e]) != m.vertices.size()){
+          if(entry_count / component_counts_point_data[e] != m.vertices.size()){
             error("Number of vertices does not match length of appended data for vertex-vector "
                                                                                    + ft(e) + ".");
           }
@@ -632,7 +632,7 @@ void Dune::crvsrf::read_vtu_file(std::string file, Mesh &m, std::vector<DataVect
           }
         }else if(datatypes_point_data[e] == "Float64"){
           unsigned entry_count = vvr->total_size / 8;
-          if(int(entry_count / component_counts_point_data[e]) != m.vertices.size()){
+          if(entry_count / component_counts_point_data[e] != m.vertices.size()){
             error("Number of vertices does not match length of appended data for vertex-vector "
                                                                                    + ft(e) + ".");
           }
@@ -643,7 +643,7 @@ void Dune::crvsrf::read_vtu_file(std::string file, Mesh &m, std::vector<DataVect
           }
         }else if(datatypes_point_data[e] == "Int64"){
           unsigned entry_count = vvr->total_size / 8;
-          if(int(entry_count / component_counts_point_data[e]) != m.vertices.size()){
+          if(entry_count / component_counts_point_data[e] != m.vertices.size()){
             error("Number of vertices does not match length of appended data for vertex-vector "
                                                                                    + ft(e) + ".");
           }
@@ -664,7 +664,7 @@ void Dune::crvsrf::read_vtu_file(std::string file, Mesh &m, std::vector<DataVect
         vvr->initialize();
         if(datatypes_cell_data[e] == "Float32"){
           unsigned entry_count = vvr->total_size / 4;
-          if(int(entry_count / component_counts_cell_data[e]) != m.elements.size()){
+          if(entry_count / component_counts_cell_data[e] != m.elements.size()){
             error("Number of elements does not match length of appended data for element-vector "
                                                                                     + ft(e) + ".");
           }
@@ -675,7 +675,7 @@ void Dune::crvsrf::read_vtu_file(std::string file, Mesh &m, std::vector<DataVect
           }
         }else if(datatypes_cell_data[e] == "Float64"){
           unsigned entry_count = vvr->total_size / 8;
-          if(int(entry_count / component_counts_cell_data[e]) != m.elements.size()){
+          if(entry_count / component_counts_cell_data[e] != m.elements.size()){
             error("Number of elements does not match length of appended data for element-vector "
                                                                                     + ft(e) + ".");
           }
@@ -686,7 +686,7 @@ void Dune::crvsrf::read_vtu_file(std::string file, Mesh &m, std::vector<DataVect
           }
         }else if(datatypes_cell_data[e] == "Int64"){
           unsigned entry_count = vvr->total_size / 8;
-          if(int(entry_count / component_counts_cell_data[e]) != m.elements.size()){
+          if(entry_count / component_counts_cell_data[e] != m.elements.size()){
             error("Number of elements does not match length of appended data for element-vector "
                                                                                     + ft(e) + ".");
           }
diff --git a/dune/curvedsurfacegrid/surfacedistance/vtureader.hh b/dune/curvedsurfacegrid/surfacedistance/vtureader.hh
index 1ca20344d1257d970d131e4cd1dd1fa089e44bc3..9f65ecc55f4c4795c9eb3c48fdb141f764919ef3 100644
--- a/dune/curvedsurfacegrid/surfacedistance/vtureader.hh
+++ b/dune/curvedsurfacegrid/surfacedistance/vtureader.hh
@@ -1,9 +1,9 @@
-#ifndef DUNE_CRVSRF_VTUREADER_HH
-#define DUNE_CRVSRF_VTUREADER_HH
+#ifndef DUNE_CURVED_SURFACE_GRID_VTUREADER_HH
+#define DUNE_CURVED_SURFACE_GRID_VTUREADER_HH
 
 #include <dune/curvedsurfacegrid/surfacedistance/datastructures.hh>
 
-namespace Dune{ namespace crvsrf{
+namespace Dune{ namespace Curved{
 
 void read_vtu_file(std::string file, Mesh &m,
                    std::vector<DataVector*> &vecs, std::vector<DataVector*> &element_vecs);
@@ -14,6 +14,6 @@ inline void read_vtu_file(std::string file, Mesh &m){ //$ACL_exclude
   read_vtu_file(file, m, vecs, element_vecs);
 }
 
-}} //end namespace Dune::crvsrf
+}} //end namespace Dune::CurvedGeo
 
-#endif //DUNE_CRVSRF_VTUREADER_HH
+#endif //DUNE_CURVED_SURFACE_GRID_VTUREADER_HH
diff --git a/dune/curvedsurfacegrid/test/CMakeLists.txt b/dune/curvedsurfacegrid/test/CMakeLists.txt
index a8d20ab9064ba479696a37317302604c02e84aa2..d3600c70c0277ee229de1310e7fe503be18fbc51 100644
--- a/dune/curvedsurfacegrid/test/CMakeLists.txt
+++ b/dune/curvedsurfacegrid/test/CMakeLists.txt
@@ -1,5 +1,30 @@
 if (dune-foamgrid_FOUND)
-  dune_add_test(SOURCES test_curvedsurfacegrid.cc
+  dune_add_test(SOURCES convergence.cc
+                COMPILE_DEFINITIONS DUNE_GRID_PATH=${PROJECT_SOURCE_DIR}/example/)
+  add_dune_alberta_flags(convergence WORLDDIM 3)
+
+  dune_add_test(SOURCES discretegridviewfunction.cc
+                COMPILE_DEFINITIONS DUNE_GRID_PATH=${PROJECT_SOURCE_DIR}/example/)
+  add_dune_alberta_flags(discretegridviewfunction WORLDDIM 3)
+
+  dune_add_test(SOURCES analyticgridviewfunction.cc
                 COMPILE_DEFINITIONS DUNE_GRID_PATH=${PROJECT_SOURCE_DIR}/example/)
-  add_dune_alberta_flags(test_curvedsurfacegrid WORLDDIM 3)
 endif ()
+
+dune_add_test(NAME test-curvedsurfacegrid-yaspgrid
+              SOURCES test-curvedsurfacegrid.cc
+              LINK_LIBRARIES dunegrid
+              COMPILE_DEFINITIONS COORDFUNCTION=IdenticalCoordFunction<double,2>
+                                  CACHECOORDFUNCTION=0
+                                  DUNE_GRID_EXAMPLE_GRIDS_PATH=\"${PROJECT_SOURCE_DIR}/doc/grids/\"
+                                  GRIDTYPE=Dune::YaspGrid<2>)
+
+dune_add_test(NAME test-curvedsurfacegrid-albertagrid
+              SOURCES test-curvedsurfacegrid.cc
+              LINK_LIBRARIES dunegrid
+              COMPILE_DEFINITIONS COORDFUNCTION=IdenticalCoordFunction<double,2>
+                                  CACHECOORDFUNCTION=0
+                                  DUNE_GRID_EXAMPLE_GRIDS_PATH=\"${PROJECT_SOURCE_DIR}/doc/grids/\"
+                                  GRIDTYPE=Dune::AlbertaGrid<2,2>
+              CMAKE_GUARD ALBERTA_FOUND)
+add_dune_alberta_flags(test-curvedsurfacegrid-albertagrid WORLDDIM 2)
diff --git a/dune/curvedsurfacegrid/test/analyticgridviewfunction.cc b/dune/curvedsurfacegrid/test/analyticgridviewfunction.cc
new file mode 100644
index 0000000000000000000000000000000000000000..c79e9663525cf0d450f74fa2f0ab20054161fd17
--- /dev/null
+++ b/dune/curvedsurfacegrid/test/analyticgridviewfunction.cc
@@ -0,0 +1,54 @@
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+#include <iostream>
+
+#include <dune/common/parallel/mpihelper.hh> // An initializer of MPI
+#include <dune/foamgrid/foamgrid.hh>
+#include <dune/functions/common/differentiablefunctionfromcallables.hh>
+#include <dune/functions/common/functionconcepts.hh>
+#include <dune/functions/gridfunctions/analyticgridviewfunction.hh>
+#include <dune/grid/io/file/gmshreader.hh>
+
+#define STR(s) STR_HELPER(s)
+#define STR_HELPER(s) #s
+
+int main(int argc, char** argv)
+{
+  using namespace Dune;
+  MPIHelper::instance(argc, argv);
+
+  using Grid = FoamGrid<2,3>;
+  using GridView = typename Grid::LeafGridView;
+  std::unique_ptr<Grid> grid = GmshReader<Grid>::read( STR(DUNE_GRID_PATH) "sphere_coarse.msh");
+
+  using Signature = FieldVector<double,3>(FieldVector<double,3>);
+  using LocalSignature = FieldVector<double,3>(FieldVector<double,2>);
+
+  auto f = Functions::makeDifferentiableFunctionFromCallables(
+    Functions::SignatureTag<Signature>{},
+    [](auto const& x) { return FieldMatrix<double,3>(0); },
+    [](auto const& x) { return FieldMatrix<double,3,3>(0); }
+  );
+
+  auto gf = Functions::makeAnalyticGridViewFunction(f, grid->leafGridView());
+  using GF = decltype(gf);
+
+  static_assert(Functions::Concept::isFunction<GF,Signature>(), "");
+  static_assert(Functions::Concept::isDifferentiableFunction<GF,Signature>(), "");
+
+  auto lf = localFunction(gf);
+  using LF = decltype(lf);
+
+  static_assert(Functions::Concept::isFunction<LF,LocalSignature>(), "");
+
+  using EntitySet = Functions::GridViewEntitySet<GridView,0>;
+  using LocalContext = typename EntitySet::Element;
+
+  static_assert(Functions::Concept::isLocalFunction<LF,LocalSignature,LocalContext>(), "");
+  static_assert(Functions::Concept::isDifferentiableFunction<LF,LocalSignature,Functions::LocalDerivativeTraits<EntitySet>::template Traits>(), "");
+  static_assert(Functions::Concept::isDifferentiableLocalFunction<LF,LocalSignature,LocalContext,Functions::LocalDerivativeTraits<EntitySet>::template Traits>(), "");
+}
\ No newline at end of file
diff --git a/dune/curvedsurfacegrid/test/convergence.cc b/dune/curvedsurfacegrid/test/convergence.cc
new file mode 100644
index 0000000000000000000000000000000000000000..d157d6bfa2ce74eb55314e06356d4d344dca8686
--- /dev/null
+++ b/dune/curvedsurfacegrid/test/convergence.cc
@@ -0,0 +1,223 @@
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+#include <iostream>
+#include <dune/common/parallel/mpihelper.hh> // An initializer of MPI
+#include <dune/curvedsurfacegrid/curvedsurfacegrid.hh>
+#include <dune/curvedsurfacegrid/gridfunctions/spheregridfunction.hh>
+#include <dune/curvedsurfacegrid/gridfunctions/torusgridfunction.hh>
+#include <dune/geometry/quadraturerules.hh>
+#include <dune/grid/io/file/gmshreader.hh>
+#include <dune/localfunctions/lagrange/pk.hh>
+//#include <dune/grid/albertagrid.hh>
+#include <dune/foamgrid/foamgrid.hh>
+
+#define STR(s) STR_HELPER(s)
+#define STR_HELPER(s) #s
+
+#define TORUS
+
+const int order = 3;
+const int quad_order = order+6;
+const int num_levels = 4;
+
+// Test Hausdorf-distance
+template <class Grid>
+typename Grid::ctype inf_error(Grid const& grid)
+{
+  std::cout << "inf_error..." << std::endl;
+  using QuadProvider = Dune::QuadratureRules<typename Grid::ctype, 2>;
+  typename Grid::ctype dist = 0;
+  auto projection = grid.gridFunction().f();
+  for (auto const& element : elements(grid.leafGridView()))
+  {
+    auto geometry = element.geometry();
+
+    auto const& quadRule = QuadProvider::rule(element.type(), quad_order);
+    for (auto const& qp : quadRule) {
+      auto x = geometry.global(qp.position());
+      auto y = projection(x);
+      dist = std::max(dist, (x - y).two_norm());
+    }
+  }
+
+  return dist;
+}
+
+// Test integrated Hausdorf-distance
+template <class Grid>
+typename Grid::ctype L2_error(Grid const& grid)
+{
+  std::cout << "L2_error..." << std::endl;
+  using QuadProvider = Dune::QuadratureRules<typename Grid::ctype, 2>;
+  typename Grid::ctype dist = 0;
+  auto projection = grid.gridFunction().f();
+  for (auto const& element : elements(grid.leafGridView()))
+  {
+    auto geometry = element.geometry();
+
+    auto const& quadRule = QuadProvider::rule(element.type(), quad_order);
+    for (auto const& qp : quadRule) {
+      auto x = geometry.global(qp.position());
+      auto y = projection(x);
+      dist += (x - y).two_norm2() * qp.weight() * geometry.integrationElement(qp.position());
+    }
+  }
+
+  return std::sqrt(dist);
+}
+
+// Test integrated error in normal vectors
+template <class Grid>
+typename Grid::ctype normal_error(Grid const& grid)
+{
+  std::cout << "normal_error..." << std::endl;
+  using QuadProvider = Dune::QuadratureRules<typename Grid::ctype, 2>;
+  typename Grid::ctype dist = 0;
+
+  auto projection = grid.gridFunction().f();
+  for (auto const& element : elements(grid.leafGridView()))
+  {
+    auto geometry = element.geometry();
+    auto const& quadRule = QuadProvider::rule(element.type(), quad_order);
+    for (auto const& qp : quadRule) {
+      auto x = geometry.impl().normal(qp.position());
+      auto y = projection.normal(geometry.global(qp.position()));
+      dist += (x - y).two_norm2() * qp.weight() * geometry.integrationElement(qp.position());
+    }
+  }
+
+  return std::sqrt(dist);
+}
+
+// Test integrated error in mean curvature
+template <class Grid>
+typename Grid::ctype curvature_error(Grid const& grid)
+{
+  std::cout << "curvature_error..." << std::endl;
+  using GlobalCoordinate = typename Grid::template Codim<0>::Entity::Geometry::GlobalCoordinate;
+  using QuadProvider = Dune::QuadratureRules<typename Grid::ctype, 2>;
+  using FiniteElementType = Dune::PkLocalFiniteElement<typename Grid::ctype, typename Grid::ctype, 2, order+4>;
+  FiniteElementType fe;
+
+  using LBTraits = typename FiniteElementType::Traits::LocalBasisType::Traits;
+  std::vector<typename LBTraits::JacobianType> shapeGradients;
+  std::vector<GlobalCoordinate> gradients;
+  std::vector<GlobalCoordinate> normals;
+
+  auto projection = grid.gridFunction().f();
+
+  typename Grid::ctype dist = 0;
+  for (auto const& element : elements(grid.leafGridView()))
+  {
+    auto geometry = element.geometry();
+    auto const& localBasis = fe.localBasis();
+    auto const& localInterpolation = fe.localInterpolation();
+
+    auto f = [&](auto const& local) -> GlobalCoordinate
+    {
+      auto x = geometry.impl().normal(local);
+      return x;
+    };
+    localInterpolation.interpolate(f, normals);
+
+    shapeGradients.resize(localBasis.size());
+    gradients.resize(localBasis.size());
+
+    auto const& quadRule = QuadProvider::rule(element.type(), quad_order);
+    for (auto const& qp : quadRule) {
+      auto jInvT = geometry.jacobianInverseTransposed(qp.position());
+      localBasis.evaluateJacobian(qp.position(), shapeGradients);
+
+      for (std::size_t i = 0; i < gradients.size(); ++i)
+        jInvT.mv(shapeGradients[i][0], gradients[i]);
+
+      typename Grid::ctype H = 0;
+      for (std::size_t i = 0; i < gradients.size(); ++i)
+        H += normals[i].dot(gradients[i]);
+
+      auto H_exact = projection.mean_curvature(geometry.global(qp.position()));
+      dist += std::abs(H/2 - H_exact) * qp.weight() * geometry.integrationElement(qp.position());
+    }
+  }
+
+  return dist;
+}
+
+// longest edge in the grid
+template <class Grid>
+typename Grid::ctype edge_length(Grid const& grid)
+{
+  typename Grid::ctype h = 0;
+  for (auto const& e : edges(grid.hostGrid().leafGridView()))
+    h = std::max(h, e.geometry().volume());
+
+  return h;
+}
+
+
+int main(int argc, char** argv)
+{
+  using namespace Dune;
+  MPIHelper::instance(argc, argv);
+
+  auto grid_order = std::integral_constant<int,order>{};
+
+  // using HostGrid = AlbertaGrid<2,3>;
+  using HostGrid = FoamGrid<2,3>;
+#if defined(SPHERE)
+  std::unique_ptr<HostGrid> hostGrid = GmshReader<HostGrid>::read( STR(DUNE_GRID_PATH) "sphere_coarse.msh");
+  auto gridFct = sphereGridFunction<HostGrid>(1.0);
+#elif defined(TORUS)
+  std::unique_ptr<HostGrid> hostGrid = GmshReader<HostGrid>::read( STR(DUNE_GRID_PATH) "torus.msh");
+  auto gridFct = torusGridFunction<HostGrid>(2.0, 1.0);
+#endif
+
+  CurvedSurfaceGrid grid(*hostGrid, gridFct, grid_order);
+  using Grid = decltype(grid);
+  std::vector<typename Grid::ctype> inf_errors, L2_errors, normal_errors, curvature_errors, edge_lengths;
+  for (int i = 0; i < num_levels; ++i) {
+    if (i > 0)
+      grid.globalRefine(1);
+
+    std::cout << "level = " << i << std::endl;
+    inf_errors.push_back( inf_error(grid) );
+    L2_errors.push_back( L2_error(grid) );
+    normal_errors.push_back( normal_error(grid) );
+    curvature_errors.push_back( curvature_error(grid) );
+    edge_lengths.push_back( edge_length(grid) );
+  }
+
+
+  std::vector<typename Grid::ctype> eocInf(num_levels, 0), eocL2(num_levels, 0), eocNormal(num_levels, 0), eocCurvature(num_levels, 0);
+  for (int i = 1; i < num_levels; ++i) {
+    eocInf[i]       = std::log(inf_errors[i]/inf_errors[i-1]) / std::log(edge_lengths[i]/edge_lengths[i-1]);
+    eocL2[i]        = std::log(L2_errors[i]/L2_errors[i-1]) / std::log(edge_lengths[i]/edge_lengths[i-1]);
+    eocNormal[i]    = std::log(normal_errors[i]/normal_errors[i-1]) / std::log(edge_lengths[i]/edge_lengths[i-1]);
+    eocCurvature[i] = std::log(curvature_errors[i]/curvature_errors[i-1]) / std::log(edge_lengths[i]/edge_lengths[i-1]);
+  }
+
+  auto print_line = [](auto i, auto const& data) {
+    std::cout << i;
+    for (auto const& d : data)
+      std::cout << '\t' << "| " << d;
+    std::cout << std::endl;
+  };
+
+  auto print_break = [] {
+    std::cout.width(8 + 8*16);
+    std::cout.fill('-');
+    std::cout << '-' << std::endl;
+    std::cout.fill(' ');
+  };
+
+  std::cout.setf(std::ios::scientific);
+  print_line("level", std::vector<std::string>{"err_inf", "eoc_inf", "err_L2", "eoc_L2", "err_norm", "eoc_norm", "err_curv", "eoc_curv"});
+  print_break();
+
+  for (int i = 0; i < num_levels; ++i)
+    print_line(i, std::vector<double>{inf_errors[i], eocInf[i], L2_errors[i], eocL2[i], normal_errors[i], eocNormal[i], curvature_errors[i], eocCurvature[i]});
+}
diff --git a/dune/curvedsurfacegrid/test/test_curvedsurfacegrid.cc b/dune/curvedsurfacegrid/test/discretegridviewfunction.cc
similarity index 85%
rename from dune/curvedsurfacegrid/test/test_curvedsurfacegrid.cc
rename to dune/curvedsurfacegrid/test/discretegridviewfunction.cc
index 67ccf96f77df82dd5311f474e6f5c7e814318383..969573b2d523922e4acbbdee93357d8328485c48 100644
--- a/dune/curvedsurfacegrid/test/test_curvedsurfacegrid.cc
+++ b/dune/curvedsurfacegrid/test/discretegridviewfunction.cc
@@ -7,23 +7,29 @@
 #include <iostream>
 #include <dune/common/parallel/mpihelper.hh> // An initializer of MPI
 #include <dune/curvedsurfacegrid/curvedsurfacegrid.hh>
+#include <dune/curvedsurfacegrid/gridfunctions/discretegridviewfunction.hh>
 #include <dune/geometry/quadraturerules.hh>
 #include <dune/grid/io/file/gmshreader.hh>
 #include <dune/localfunctions/lagrange/pk.hh>
 //#include <dune/grid/albertagrid.hh>
 #include <dune/foamgrid/foamgrid.hh>
 
+#include <dune/functions/common/differentiablefunctionfromcallables.hh>
+#include <dune/functions/functionspacebases/interpolate.hh>
+//#include <dune/functions/gridfunctions/analyticgridviewfunction.hh>
+
 #define STR(s) STR_HELPER(s)
 #define STR_HELPER(s) #s
 
-const int order = 3;
-const int quad_order = order+5;
+const int order = 2;
+const int quad_order = order+4;
 const int num_levels = 5;
 
 // Test Hausdorf-distance
 template <class Grid, class Projection>
 typename Grid::ctype inf_error(Grid const& grid, Projection const& projection)
 {
+  std::cout << "inf_error..." << std::endl;
   using QuadProvider = Dune::QuadratureRules<typename Grid::ctype, 2>;
   typename Grid::ctype dist = 0;
   for (auto const& element : elements(grid.leafGridView()))
@@ -45,6 +51,7 @@ typename Grid::ctype inf_error(Grid const& grid, Projection const& projection)
 template <class Grid, class Projection>
 typename Grid::ctype L2_error(Grid const& grid, Projection const& projection)
 {
+  std::cout << "L2_error..." << std::endl;
   using QuadProvider = Dune::QuadratureRules<typename Grid::ctype, 2>;
   typename Grid::ctype dist = 0;
   for (auto const& element : elements(grid.leafGridView()))
@@ -66,6 +73,7 @@ typename Grid::ctype L2_error(Grid const& grid, Projection const& projection)
 template <class Grid, class Projection>
 typename Grid::ctype normal_error(Grid const& grid, Projection const& projection)
 {
+  std::cout << "normal_error..." << std::endl;
   using QuadProvider = Dune::QuadratureRules<typename Grid::ctype, 2>;
   typename Grid::ctype dist = 0;
   for (auto const& element : elements(grid.leafGridView()))
@@ -89,10 +97,10 @@ typename Grid::ctype normal_error(Grid const& grid, Projection const& projection
 template <class Grid, class Projection>
 typename Grid::ctype curvature_error(Grid const& grid, Projection const& projection)
 {
-  using LocalCoordinate = typename Grid::template Codim<0>::Entity::Geometry::LocalCoordinate;
+  std::cout << "curvature_error..." << std::endl;
   using GlobalCoordinate = typename Grid::template Codim<0>::Entity::Geometry::GlobalCoordinate;
   using QuadProvider = Dune::QuadratureRules<typename Grid::ctype, 2>;
-  using FiniteElementType = Dune::PkLocalFiniteElement<typename Grid::ctype, typename Grid::ctype, 2, order+2>;
+  using FiniteElementType = Dune::PkLocalFiniteElement<typename Grid::ctype, typename Grid::ctype, 2, order+4>;
   FiniteElementType fe;
 
   using LBTraits = typename FiniteElementType::Traits::LocalBasisType::Traits;
@@ -144,30 +152,38 @@ template <class Grid>
 typename Grid::ctype edge_length(Grid const& grid)
 {
   typename Grid::ctype h = 0;
-  for (auto const& e : edges(grid.leafGridView()))
+  for (auto const& e : edges(grid.hostGrid().leafGridView()))
     h = std::max(h, e.geometry().volume());
 
   return h;
 }
 
+
 int main(int argc, char** argv)
 {
   using namespace Dune;
-  MPIHelper& helper = MPIHelper::instance(argc, argv);
+  MPIHelper::instance(argc, argv);
 
   // using HostGrid = AlbertaGrid<2,3>;
   using HostGrid = FoamGrid<2,3>;
   std::unique_ptr<HostGrid> hostGrid = GmshReader<HostGrid>::read( STR(DUNE_GRID_PATH) "sphere_coarse.msh");
 
-  SphereCoordFunction sphere({0.0, 0.0, 0.0}, 1.0);
-  using Grid = CurvedSurfaceGrid<HostGrid, SphereCoordFunction, order>;
-  Grid grid(*hostGrid, sphere);
+  using Signature = FieldVector<double,3>(FieldVector<double,3>);
+  auto sphere = [](auto const& x) { return x / x.two_norm(); };
+  auto sphereGridFct = discreteGridViewFunction<3>(hostGrid->leafGridView(), order);
+
+  using Grid = CurvedSurfaceGrid<decltype(sphereGridFct)>;
+  Grid grid(*hostGrid, sphereGridFct);
 
   std::vector<typename Grid::ctype> inf_errors, L2_errors, normal_errors, curvature_errors, edge_lengths;
   for (int i = 0; i < num_levels; ++i) {
     if (i > 0)
       grid.globalRefine(1);
 
+    std::cout << "i = " << i << std::endl;
+    sphereGridFct.update(hostGrid->leafGridView());
+    Functions::interpolate(sphereGridFct.basis(), sphereGridFct.coefficients(), sphere);
+
     inf_errors.push_back( inf_error(grid, sphere) );
     L2_errors.push_back( L2_error(grid, sphere) );
     normal_errors.push_back( normal_error(grid, sphere) );
diff --git a/dune/curvedsurfacegrid/test/test-curvedsurfacegrid.cc b/dune/curvedsurfacegrid/test/test-curvedsurfacegrid.cc
new file mode 100644
index 0000000000000000000000000000000000000000..d3ce4574e4cf02fbd9f472ab6731730626e8d08c
--- /dev/null
+++ b/dune/curvedsurfacegrid/test/test-curvedsurfacegrid.cc
@@ -0,0 +1,253 @@
+// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+// vi: set et ts=4 sw=2 sts=2:
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef COORDFUNCTION
+
+#include <dune/common/timer.hh>
+
+#include <dune/curvedsurfacegrid/capabilities.hh>
+#include <dune/curvedsurfacegrid/curvedsurfacegrid.hh>
+#include <dune/curvedsurfacegrid/coordfunctionimplementations.hh>
+// #include <dune/grid/io/file/dgfparser.hh>
+#if HAVE_UG
+#include <dune/grid/albertagrid.hh>
+// #include <dune/grid/albertagrid/dgfparser.hh>
+#endif
+#include <dune/grid/yaspgrid.hh>
+// #include <dune/grid/io/file/dgfparser/dgfyasp.hh>
+// #include <dune/grid/io/file/dgfparser/dgfgeogrid.hh>
+#include <dune/grid/utility/structuredgridfactory.hh>
+#include <dune/grid/test/functions.hh>
+
+#include <dune/grid/test/gridcheck.hh>
+#include <dune/grid/test/checkcommunicate.hh>
+#include <dune/grid/test/checkgeometryinfather.hh>
+#include <dune/grid/test/checkintersectionit.hh>
+#include <dune/grid/test/checkiterators.hh>
+#include <dune/grid/test/checkpartition.hh>
+#include <dune/grid/test/checkgeometry.hh>
+
+#include <dune/functions/common/differentiablefunctionfromcallables.hh>
+#include <dune/functions/common/signature.hh>
+#include <dune/functions/gridfunctions/analyticgridviewfunction.hh>
+
+namespace Dune
+{
+  template< int dim, int dimworld >
+  class AlbertaGrid;
+}
+
+using namespace Dune;
+
+template< int dim, int dimworld >
+struct EnableLevelIntersectionIteratorCheck< AlbertaGrid< dim, dimworld > >
+{
+  static const bool v = false;
+};
+
+template< class GridFunction, int order >
+struct EnableLevelIntersectionIteratorCheck< CurvedSurfaceGrid< GridFunction, order > >
+{
+  using HostGrid = typename GridFunction::GridView::Grid;
+  static const bool v = EnableLevelIntersectionIteratorCheck< HostGrid >::v;
+};
+
+typedef GRIDTYPE HostGrid;
+static const int dow = HostGrid::dimensionworld;
+
+// define an identity coordinate mapping
+struct Identity
+{
+  FieldVector<double,dow> operator() (const FieldVector<double,dow>& x) const
+  {
+    return x;
+  }
+};
+
+// define the derivative of an identity coorinate mapping
+struct DIdentity
+{
+  FieldMatrix<double,dow,dow> operator() (const FieldVector<double,dow>& x) const
+  {
+    FieldMatrix<double,dow,dow> I(0);
+    for (int i = 0; i < dow; ++i)
+      I[i][i] = 1;
+    return I;
+  }
+};
+
+// construct a differentiable callable from two callables
+using IdentityFunction = Functions::DifferentiableFunctionFromCallables<
+  FieldVector<double,dow>(FieldVector<double,dow>),
+  Functions::DefaultDerivativeTraits,
+  Identity,
+  DIdentity>;
+
+// Construct a GridFunction from the differentiable callable
+using IdentityGridFunction = Functions::AnalyticGridViewFunction<
+  FieldVector<double,dow>(FieldVector<double,dow>),
+  typename HostGrid::LeafGridView,
+  IdentityFunction>;
+
+using GridFunction = IdentityGridFunction;
+
+
+template <class GridType>
+void test()
+{
+  using SingleGeometry = Dune::Capabilities::hasSingleGeometryType<GridType>;
+  bool useSimplices = Dune::GeometryType(SingleGeometry::topologyId, GridType::dimension, false).isSimplex();
+  auto gridPtr = useSimplices
+    ? Dune::StructuredGridFactory<HostGrid>::createSimplexGrid({0.0, 0.0}, {1.0, 1.0}, {1u, 1u})
+    : Dune::StructuredGridFactory<HostGrid>::createCubeGrid({0.0, 0.0}, {1.0, 1.0}, {1u, 1u});
+
+  IdentityFunction idFct(Identity{}, DIdentity{});
+  IdentityGridFunction idGridFct(idFct, gridPtr->leafGridView());
+  GridType geogrid(*gridPtr, idGridFct);
+
+  geogrid.globalRefine( 1 );
+  geogrid.loadBalance();
+
+  std::cerr << "Checking grid..." << std::endl;
+  gridcheck( geogrid );
+
+  std::cerr << "Checking geometry... " << std::endl;
+  Dune::GeometryChecker< GridType > checker;
+
+  checker.checkGeometry( geogrid.leafGridView() );
+  for( int i = 0; i <= geogrid.maxLevel(); ++i )
+    checker.checkGeometry( geogrid.levelGridView( i ) );
+
+  std::cerr << "Checking geometry in father..." << std::endl;
+  checkGeometryInFather( geogrid );
+  std::cerr << "Checking intersections..." << std::endl;
+  checkIntersectionIterator( geogrid, !EnableLevelIntersectionIteratorCheck< HostGrid >::v );
+
+  checkIterators( geogrid.leafGridView() );
+  for( int i = 0; i <= geogrid.maxLevel(); ++i )
+    checkIterators( geogrid.levelGridView( i ) );
+
+  checkPartitionType( geogrid.leafGridView() );
+  for( int i = 0; i <= geogrid.maxLevel(); ++i )
+    checkPartitionType( geogrid.levelGridView( i ) );
+
+  std::cerr << "Checking geometry lifetime..." << std::endl;
+  checkGeometryLifetime( geogrid.leafGridView() );
+
+  std::cerr << "Checking communication..." << std::endl;
+  checkCommunication( geogrid, -1, std::cout );
+  if( EnableLevelIntersectionIteratorCheck< HostGrid >::v )
+  {
+    for( int i = 0; i <= geogrid.maxLevel(); ++i )
+      checkCommunication( geogrid, i, std::cout );
+  }
+
+}
+
+#if 0
+void testNestedCurvedSurfaceGrid(const std::string& gridfile) {
+
+  using NestedCurvedSurfaceGrid
+    = Dune::CurvedSurfaceGrid< CurvedSurfaceGrid, Dune::IdenticalCoordFunction< Grid::ctype, dow >, 2 >;
+  using NestedGgLeafView = NestedCurvedSurfaceGrid::LeafGridView;
+
+  using SingleGeometry = Dune::Capabilities::hasSingleGeometryType<NestedCurvedSurfaceGrid>;
+  bool useSimplices = Dune::GeometryType(SingleGeometry::topologyId, NestedCurvedSurfaceGrid::dimension, false).isSimplex();
+  auto gridPtr = useSimplices
+    ? Dune::StructuredGridFactory<NestedCurvedSurfaceGrid>::createSimplexGrid({0.0, 0.0}, {1.0, 1.0}, {4u, 4u})
+    : Dune::StructuredGridFactory<NestedCurvedSurfaceGrid>::createCubeGrid({0.0, 0.0}, {1.0, 1.0}, {4u, 4u});
+
+  NestedCurvedSurfaceGrid &geogrid = *gridPtr;
+  geogrid.globalRefine( 1 );
+
+  // creating different variables for storing grid views
+  NestedGgLeafView gv1 = geogrid.leafGridView();
+  std::shared_ptr<NestedGgLeafView> pgv2;
+  NestedGgLeafView gv3 = geogrid.leafGridView();
+
+  // use geometry grid views copy constructor and copy assignment operator
+  {
+    NestedGgLeafView tmpGv = geogrid.leafGridView();
+    // copying/assigning temporary grid view would be dangerous with default implementation of copy constructor or copy assignment operator from geomrtry grid view
+    pgv2 = std::make_shared<NestedGgLeafView> (tmpGv);
+    gv3 = tmpGv;
+  }
+  // The following test would now be guaranteed to fail with the default implementation of geometry grid views copy constructor
+  // assert(&(pgv2->indexSet().hostIndexSet()) == &(pgv2->impl().hostGridView().indexSet()))
+  // but this would not compile since the member functions impl() and hostIndexSet() are protected/private.
+  // So we do the following
+
+  // get index sets and do some arbitrary test to check whether they work correctly
+  auto const& is1 = gv1.indexSet();
+  auto const& is2 = pgv2->indexSet();
+  auto const& is3 = gv3.indexSet();
+  for(auto const& e : elements(gv1)) {
+    bool idxCorrect = (is1.index(e)==is2.index(e));
+    idxCorrect &= (is1.index(e)==is3.index(e));
+    assert(idxCorrect);
+  }
+}
+#endif
+
+int main ( int argc, char **argv )
+try
+{
+  Dune::MPIHelper::instance( argc, argv );
+
+  // std::string gridfile = DUNE_GRID_EXAMPLE_GRIDS_PATH "dgf/cube-2.dgf";
+  // if (argc >= 2)
+  //   gridfile = argv[1];
+
+  Dune::Timer watch;
+
+  watch.reset();
+  test<CurvedSurfaceGrid<GridFunction>>();
+  std::cout << "=== CurvedSurfaceGrid took " << watch.elapsed() << " seconds\n";
+
+  // watch.reset();
+  // testNestedCurvedSurfaceGrid(gridfile);
+  // std::cout << "=== NestedCurvedSurfaceGrid took " << watch.elapsed() << " seconds\n";
+
+  // // Check with a discrete coordinate function
+  // Dune::GridPtr<Grid> hostGridPtr(gridfile);
+  // auto& hostGrid = *hostGridPtr;
+  // const int dim = Grid::dimension;
+
+  // typedef Grid::LeafGridView HostGridView;
+  // const HostGridView& hostGridView = hostGrid.leafGridView();
+
+  // std::vector<Dune::FieldVector<double,dim> > vertexPositions(hostGridView.size(dim));
+
+  // for (const auto& vertex : vertices(hostGridView))
+  //   vertexPositions[hostGridView.indexSet().index(vertex)] = vertex.geometry().corner(0);
+
+  // typedef Dune::GeometryGrid<Grid, DeformationFunction<HostGridView> > DiscretelyTransformedGrid;
+  // DeformationFunction<HostGridView> discreteTransformation(hostGridView, vertexPositions);
+  // DiscretelyTransformedGrid discretelyTransformedGrid(hostGrid, discreteTransformation);
+
+  // gridcheck(discretelyTransformedGrid);
+
+  return 0;
+}
+catch( const Dune::Exception &e )
+{
+  std::cerr << e << std::endl;
+  return 1;
+}
+catch( const std::exception &e )
+{
+  std::cerr << e.what() << std::endl;
+  return 1;
+}
+catch( ... )
+{
+  std::cerr << "Unknown exception raised." << std::endl;
+  return 1;
+}
+
+#else
+#error "COORDFUNCTION not defined (e.g., Helix, Circle; see functions.hh)"
+#endif
diff --git a/example/example.cc b/example/example.cc
index 74bf7ee740fa859458fd2e6d6b8d62b24643b7d4..227fc8be268f1e3e6593dab73686e4f298f5314a 100644
--- a/example/example.cc
+++ b/example/example.cc
@@ -2,7 +2,7 @@
 // vi: set et ts=4 sw=2 sts=2:
 
 #ifdef HAVE_CONFIG_H
-# include "config.h"
+  #include "config.h"
 #endif
 #include <iostream>
 #include <dune/common/parallel/mpihelper.hh> // An initializer of MPI
@@ -37,37 +37,43 @@ int main(int argc, char** argv)
   //load host-grid (ALUGrid)
   using HostGridType = Dune::ALUGrid<2, 3, simplex, conforming>;
   GridFactory<HostGridType> gridFactory;
-  GmshReader<HostGridType>::read(gridFactory, "dune-curvedsurfacegrid/example/sphere_coarse.msh");
+  GmshReader<HostGridType>::read(gridFactory, "example/sphere_coarse.msh");
   std::shared_ptr<HostGridType> hostGrid(gridFactory.createGrid());
 
-  const int ip_order = 5; //interpolatory order for curved elements
+  const int ip_order = 3; //interpolatory order for curved elements
 
   //case1: projection to actual sphere
   {
     SphereCoordFunction sphereCF(/*center=*/{0.0, 0.0, 0.0}, /*radius=*/1.0);
-    using GridType = CurvedSurfaceGrid<HostGridType, SphereCoordFunction, ip_order>;
-    GridType grid(*hostGrid, sphereCF);
+    CurvedSurfaceGrid grid(*hostGrid, std::ref(sphereCF), std::integral_constant<int, ip_order>{});
 
-    using GridView = GridType::LeafGridView;
-    GridView gridView = grid.leafGridView();
+    auto gridView = grid.leafGridView();
+    using GridView = decltype(gridView);
     VTKWriter<GridView> vtkWriter(gridView);
     vtkWriter.write("sphere1_real_elements");
     SubsamplingVTKWriter<GridView> ssvtkWriter(gridView, refinementIntervals(ip_order));
-    ssvtkWriter.write("sphere1_fake_elements" + crvsrf::ft(ip_order, 2));
+    ssvtkWriter.write("sphere1_fake_elements" + Curved::ft(ip_order, 2));
+    #if COLLECTOR_BENCHMARK != 0
+      std::cout << "benchmark-result for SphereCoordFunction:" << std::endl;
+      sphereCF.collectorBenchmark(true);
+    #endif
   }
 
   //case2: projection to a surface-mesh of a sphere
   {
-    SurfaceDistanceCoordFunction surfdistCF("dune-curvedsurfacegrid/example/sphere_fine.vtu");
-    using GridType = CurvedSurfaceGrid<HostGridType, SurfaceDistanceCoordFunction<>, ip_order>;
-    GridType grid(*hostGrid, surfdistCF);
-
-    using GridView = GridType::LeafGridView;
-    GridView gridView = grid.leafGridView();
+    SurfaceDistanceCoordFunction<> surfdistCF("example/sphere_fine.vtu");
+    CurvedSurfaceGrid grid(*hostGrid, std::ref(surfdistCF), std::integral_constant<int, ip_order>{});
+    
+    auto gridView = grid.leafGridView();
+    using GridView = decltype(gridView);
     VTKWriter<GridView> vtkWriter(gridView);
     vtkWriter.write("sphere2_real_elements");
     SubsamplingVTKWriter<GridView> ssvtkWriter(gridView, refinementIntervals(ip_order));
-    ssvtkWriter.write("sphere2_fake_elements" + crvsrf::ft(ip_order, 2));
+    ssvtkWriter.write("sphere2_fake_elements" + Curved::ft(ip_order, 2));
+    #if COLLECTOR_BENCHMARK != 0
+      std::cout << "benchmark-result for SurfaceDistanceCoordFunction:" << std::endl;
+      surfdistCF.collectorBenchmark(true);
+    #endif
   }
 
   return 0;
diff --git a/example/torus.geo b/example/torus.geo
new file mode 100644
index 0000000000000000000000000000000000000000..8507aece381265936bab90894d6299ab8a7de6fd
--- /dev/null
+++ b/example/torus.geo
@@ -0,0 +1,21 @@
+h = 0.75;
+r1 = 2.0;
+r2 = 1.0;
+
+Point(1) = {r1,    0.0, 0.0, h};
+Point(2) = {r1+r2, 0.0, 0.0, h};
+Point(3) = {r1,    0.0, r2,  h};
+Point(4) = {r1-r2, 0.0, 0.0, h};
+Point(5) = {r1,    0.0,-r2,  h};
+
+
+Circle(1) = {2,1,3};
+Circle(2) = {3,1,4};
+Circle(3) = {4,1,5};
+Circle(4) = {5,1,2};
+Line Loop(5) = {1,2,3,4};
+
+
+first[]  = Extrude {{0,0,2}, {0,0,0}, -2*Pi/3}{Line{1,2,3,4};                                  Layers{10};};
+second[] = Extrude {{0,0,2}, {0,0,0}, -2*Pi/3}{Line{first[0],first[4],first[8],first[12]};     Layers{10};};
+third[]  = Extrude {{0,0,2}, {0,0,0}, -2*Pi/3}{Line{second[0],second[4],second[8],second[12]}; Layers{10};};
diff --git a/example/torus.msh b/example/torus.msh
new file mode 100644
index 0000000000000000000000000000000000000000..d8fa670bbfe2b0092ddd6923dfc841e07f56b947
--- /dev/null
+++ b/example/torus.msh
@@ -0,0 +1,1269 @@
+$MeshFormat
+2.2 0 8
+$EndMeshFormat
+$Nodes
+366
+1 2 0 0
+2 3 0 0
+3 2 0 1
+4 1 0 0
+5 2 0 -1
+6 -1.499999999999999 -2.598076211353316 0
+7 -0.9999999999999996 -1.732050807568877 0
+8 -0.9999999999999996 -1.732050807568877 1
+9 0 0 0
+10 0 0 1
+11 -0.4999999999999998 -0.8660254037844387 0
+12 -0.9999999999999996 -1.732050807568877 -1
+13 0 0 -1
+14 -1.500000000000001 2.598076211353315 0
+15 -1.000000000000001 1.732050807568877 0
+16 -1.000000000000001 1.732050807568877 1
+17 -0.5000000000000003 0.8660254037844384 0
+18 -1.000000000000001 1.732050807568877 -1
+19 2.866025403785138 0 0.4999999999987891
+20 2.500000000001257 0 0.866025403783713
+21 1.500000000001257 0 0.8660254037851645
+22 1.133974596216123 0 0.5000000000009737
+23 1.133974596214797 0 -0.4999999999986767
+24 1.499999999998618 0 -0.8660254037836409
+25 2.499999999998673 0 -0.8660254037852049
+26 2.866025403783845 0 -0.5000000000010285
+27 -1.433012701892568 -2.482050807569483 0.4999999999987891
+28 -1.250000000000628 -2.165063509462185 0.866025403783713
+29 2.934442802201417 -0.623735072453278 0
+30 2.740636372927803 -1.2202099292274 0
+31 2.427050983124842 -1.763355756877419 0
+32 2.007391819076575 -2.229434476432183 0
+33 1.5 -2.598076211353316 0
+34 0.927050983124843 -2.85316954888546 0
+35 0.313585389802961 -2.98356568610482 0
+36 -0.31358538980296 -2.98356568610482 0
+37 -0.927050983124842 -2.853169548885461 0
+38 1.956295201467611 -0.4158233816355186 1
+39 1.827090915285202 -0.8134732861516003 1
+40 1.618033988749895 -1.175570504584946 1
+41 1.338261212717716 -1.486289650954788 1
+42 1 -1.732050807568877 1
+43 0.6180339887498953 -1.902113032590307 1
+44 0.2090569265353074 -1.989043790736547 1
+45 -0.2090569265353067 -1.989043790736547 1
+46 -0.6180339887498947 -1.902113032590307 1
+47 -0.7500000000006283 -1.299038105677747 0.8660254037851645
+48 -0.5669872981080615 -0.9820508075693641 0.5000000000009737
+49 0.9781476007338057 -0.2079116908177593 0
+50 0.9135454576426009 -0.4067366430758002 0
+51 0.8090169943749475 -0.587785252292473 0
+52 0.6691306063588582 -0.7431448254773941 0
+53 0.5000000000000001 -0.8660254037844386 0
+54 0.3090169943749477 -0.9510565162951535 0
+55 0.1045284632676537 -0.9945218953682733 0
+56 -0.1045284632676533 -0.9945218953682734 0
+57 -0.3090169943749473 -0.9510565162951536 0
+58 -0.5669872981073985 -0.9820508075682157 -0.4999999999986767
+59 -0.7499999999993088 -1.299038105675461 -0.8660254037836409
+60 1.956295201467611 -0.4158233816355186 -1
+61 1.827090915285202 -0.8134732861516003 -1
+62 1.618033988749895 -1.175570504584946 -1
+63 1.338261212717716 -1.486289650954788 -1
+64 1 -1.732050807568877 -1
+65 0.6180339887498953 -1.902113032590307 -1
+66 0.2090569265353074 -1.989043790736547 -1
+67 -0.2090569265353067 -1.989043790736547 -1
+68 -0.6180339887498947 -1.902113032590307 -1
+69 -1.249999999999336 -2.165063509459948 -0.8660254037852049
+70 -1.433012701891922 -2.482050807568363 -0.5000000000010285
+71 -1.43301270189257 2.482050807569482 0.4999999999987891
+72 -1.250000000000629 2.165063509462184 0.866025403783713
+73 -2.007391819076574 -2.229434476432183 0
+74 -2.427050983124841 -1.76335575687742 0
+75 -2.740636372927802 -1.220209929227401 0
+76 -2.934442802201416 -0.6237350724532786 0
+77 -3 -8.881784197001252e-16 0
+78 -2.934442802201417 0.6237350724532765 0
+79 -2.740636372927803 1.2202099292274 0
+80 -2.427050983124843 1.763355756877418 0
+81 -2.007391819076575 2.229434476432182 0
+82 -1.338261212717716 -1.486289650954789 1
+83 -1.618033988749894 -1.175570504584946 1
+84 -1.827090915285202 -0.8134732861516009 1
+85 -1.956295201467611 -0.4158233816355192 1
+86 -2 -6.661338147750939e-16 1
+87 -1.956295201467611 0.4158233816355177 1
+88 -1.827090915285202 0.8134732861515995 1
+89 -1.618033988749895 1.175570504584946 1
+90 -1.338261212717717 1.486289650954788 1
+91 -0.7500000000006291 1.299038105677746 0.8660254037851645
+92 -0.566987298108062 0.9820508075693637 0.5000000000009737
+93 -0.669130606358858 -0.7431448254773945 0
+94 -0.8090169943749472 -0.5877852522924732 0
+95 -0.9135454576426008 -0.4067366430758004 0
+96 -0.9781476007338055 -0.2079116908177596 0
+97 -1 -3.33066907387547e-16 0
+98 -0.9781476007338057 0.2079116908177588 0
+99 -0.913545457642601 0.4067366430757998 0
+100 -0.8090169943749477 0.5877852522924728 0
+101 -0.6691306063588585 0.743144825477394 0
+102 -0.566987298107399 0.9820508075682153 -0.4999999999986767
+103 -0.7499999999993094 1.299038105675461 -0.8660254037836409
+104 -1.338261212717716 -1.486289650954789 -1
+105 -1.618033988749894 -1.175570504584946 -1
+106 -1.827090915285202 -0.8134732861516009 -1
+107 -1.956295201467611 -0.4158233816355192 -1
+108 -2 -6.661338147750939e-16 -1
+109 -1.956295201467611 0.4158233816355177 -1
+110 -1.827090915285202 0.8134732861515995 -1
+111 -1.618033988749895 1.175570504584946 -1
+112 -1.338261212717717 1.486289650954788 -1
+113 -1.249999999999337 2.165063509459947 -0.8660254037852049
+114 -1.433012701891923 2.482050807568362 -0.5000000000010285
+115 -0.9270509831248432 2.85316954888546 0
+116 -0.3135853898029612 2.98356568610482 0
+117 0.3135853898029592 2.98356568610482 0
+118 0.927050983124841 2.85316954888546 0
+119 1.499999999999999 2.598076211353316 0
+120 2.007391819076573 2.229434476432184 0
+121 2.427050983124841 1.76335575687742 0
+122 2.740636372927802 1.220209929227402 0
+123 2.934442802201416 0.6237350724532793 0
+124 -0.6180339887498958 1.902113032590307 1
+125 -0.2090569265353078 1.989043790736546 1
+126 0.2090569265353058 1.989043790736547 1
+127 0.6180339887498938 1.902113032590307 1
+128 0.9999999999999989 1.732050807568878 1
+129 1.338261212717715 1.486289650954789 1
+130 1.618033988749894 1.175570504584947 1
+131 1.827090915285201 0.8134732861516014 1
+132 1.956295201467611 0.4158233816355197 1
+133 -0.3090169943749479 0.9510565162951534 0
+134 -0.1045284632676539 0.9945218953682732 0
+135 0.1045284632676529 0.9945218953682733 0
+136 0.3090169943749469 0.9510565162951536 0
+137 0.4999999999999994 0.8660254037844388 0
+138 0.6691306063588577 0.7431448254773947 0
+139 0.809016994374947 0.5877852522924736 0
+140 0.9135454576426006 0.4067366430758007 0
+141 0.9781476007338055 0.2079116908177598 0
+142 -0.6180339887498958 1.902113032590307 -1
+143 -0.2090569265353078 1.989043790736546 -1
+144 0.2090569265353058 1.989043790736547 -1
+145 0.6180339887498938 1.902113032590307 -1
+146 0.9999999999999989 1.732050807568878 -1
+147 1.338261212717715 1.486289650954789 -1
+148 1.618033988749894 1.175570504584947 -1
+149 1.827090915285201 0.8134732861516014 -1
+150 1.956295201467611 0.4158233816355197 -1
+151 2.803395872354569 -0.5958801876276194 0.4999999999987891
+152 2.618244489116214 -1.165717551705532 0.4999999999987891
+153 2.318663257972498 -1.684607465040484 0.4999999999987891
+154 1.917745316274641 -2.129871948509684 0.4999999999987891
+155 1.433012701892569 -2.482050807569482 0.4999999999987891
+156 0.885650556079929 -2.725752136137304 0.4999999999987891
+157 0.2995812311437171 -2.850325016746016 0.4999999999987891
+158 -0.2995812311437161 -2.850325016746016 0.4999999999987891
+159 -0.8856505560799282 -2.725752136137304 0.4999999999987891
+160 2.457788834473116 -0.5585808090791482 0.8538836493846262
+161 2.28386364410765 -1.016841607690012 0.866025403783713
+162 2.022542485938386 -1.469463130731921 0.866025403783713
+163 1.672826515897986 -1.857862063694419 0.866025403783713
+164 1.250000000000629 -2.165063509462185 0.866025403783713
+165 0.7725424859377575 -2.377641290739079 0.866025403783713
+166 0.2613211581692655 -2.486304738421933 0.866025403783713
+167 -0.2613211581692647 -2.486304738421933 0.866025403783713
+168 -0.7725424859377568 -2.377641290739079 0.866025403783713
+169 1.467221401101938 -0.3118675362269004 0.8660254037851645
+170 1.37031818646505 -0.6101049646142116 0.8660254037851645
+171 1.213525491563438 -0.8816778784394486 0.8660254037851645
+172 1.003695909539129 -1.114717238217025 0.8660254037851645
+173 0.7500000000006288 -1.299038105677747 0.8660254037851645
+174 0.46352549156281 -1.426584774443926 0.8660254037851645
+175 0.1567926949016119 -1.49178284305366 0.8660254037851645
+176 -0.1567926949016114 -1.49178284305366 0.8660254037851645
+177 -0.4635254915628095 -1.426584774443926 0.8660254037851645
+178 1.109194530581887 -0.2357665756436801 0.5000000000009737
+179 1.035937341455342 -0.461229020598182 0.5000000000009737
+180 0.9174047195283128 -0.6665335441301493 0.5000000000009737
+181 0.7587771091616361 -0.8427073534008295 0.5000000000009737
+182 0.5669872981080618 -0.982050807569364 0.5000000000009737
+183 0.3504174214202513 -1.07847392904451 0.5000000000009737
+184 0.1185326219270295 -1.127762564728331 0.5000000000009737
+185 -0.1185326219270291 -1.127762564728332 0.5000000000009737
+186 -0.350417421420251 -1.07847392904451 0.5000000000009737
+187 1.094959055324797 -0.2357701569459001 -0.475075318985737
+188 1.021173134131693 -0.4595456912005819 -0.4746234628973696
+189 0.9095100339921045 -0.6679505243144811 -0.4902806457954332
+190 0.7587771091607488 -0.842707353399844 -0.4999999999986767
+191 0.5669872981073988 -0.9820508075682156 -0.4999999999986767
+192 0.3504174214198416 -1.078473929043249 -0.4999999999986767
+193 0.1185326219268909 -1.127762564727013 -0.4999999999986767
+194 -0.1185326219268905 -1.127762564727013 -0.4999999999986767
+195 -0.3504174214198412 -1.078473929043249 -0.4999999999986767
+196 1.467221401099357 -0.3118675362263517 -0.8660254037836409
+197 1.370318186462639 -0.6101049646131382 -0.8660254037836409
+198 1.213525491561303 -0.8816778784378974 -0.8660254037836409
+199 1.003695909537363 -1.114717238215064 -0.8660254037836409
+200 0.7499999999993092 -1.299038105675461 -0.8660254037836409
+201 0.4635254915619945 -1.426584774441416 -0.8660254037836409
+202 0.1567926949013361 -1.491782843051036 -0.8660254037836409
+203 -0.1567926949013356 -1.491782843051036 -0.8660254037836409
+204 -0.463525491561994 -1.426584774441416 -0.8660254037836409
+205 2.445369001833216 -0.5197792270441224 -0.8660254037852049
+206 2.210389954128842 -0.9905934561298378 -0.9064982563823011
+207 1.967713631373399 -1.436869361469521 -0.8997084138781953
+208 1.64314363637288 -1.836810279410605 -0.8855696330863744
+209 1.234834495411327 -2.159058632959478 -0.8732694960183166
+210 0.7725424859369592 -2.377641290736622 -0.8660254037852049
+211 0.2613211581689955 -2.486304738419364 -0.8660254037852049
+212 -0.2613211581689946 -2.486304738419364 -0.8660254037852049
+213 -0.7725424859369583 -2.377641290736622 -0.8660254037852049
+214 2.803395872353305 -0.5958801876273506 -0.5000000000010285
+215 2.618244489115033 -1.165717551705006 -0.5000000000010285
+216 2.318663257971452 -1.684607465039724 -0.5000000000010285
+217 1.917745316273776 -2.129871948508724 -0.5000000000010285
+218 1.433012701891923 -2.482050807568363 -0.5000000000010285
+219 0.8856505560795296 -2.725752136136074 -0.5000000000010285
+220 0.2995812311435819 -2.85032501674473 -0.5000000000010285
+221 -0.299581231143581 -2.850325016744731 -0.5000000000010285
+222 -0.8856505560795286 -2.725752136136075 -0.5000000000010285
+223 -1.91774531627464 -2.129871948509685 0.4999999999987891
+224 -2.318663257972497 -1.684607465040485 0.4999999999987891
+225 -2.618244489116213 -1.165717551705533 0.4999999999987891
+226 -2.803395872354568 -0.5958801876276203 0.4999999999987891
+227 -2.866025403785138 -8.881784197001252e-16 0.4999999999987891
+228 -2.80339587235457 0.5958801876276181 0.4999999999987891
+229 -2.618244489116214 1.16571755170553 0.4999999999987891
+230 -2.318663257972498 1.684607465040483 0.4999999999987891
+231 -1.917745316274641 2.129871948509684 0.4999999999987891
+232 -1.712639590136044 -1.849217163004404 0.8538836485963579
+233 -2.022542485938385 -1.469463130731922 0.866025403783713
+234 -2.28386364410765 -1.016841607690012 0.866025403783713
+235 -2.445369001835743 -0.5197792270446605 0.866025403783713
+236 -2.500000000001257 -8.881784197001252e-16 0.866025403783713
+237 -2.445369001835744 0.5197792270446583 0.866025403783713
+238 -2.283863644107651 1.01684160769001 0.866025403783713
+239 -2.022542485938386 1.469463130731921 0.866025403783713
+240 -1.672826515897987 1.857862063694419 0.866025403783713
+241 -1.003695909539128 -1.114717238217026 0.8660254037851645
+242 -1.213525491563438 -0.881677878439449 0.8660254037851645
+243 -1.37031818646505 -0.610104964614212 0.8660254037851645
+244 -1.467221401101938 -0.3118675362269009 0.8660254037851645
+245 -1.500000000001257 -5.551115123125783e-16 0.8660254037851645
+246 -1.467221401101938 0.3118675362268997 0.8660254037851645
+247 -1.37031818646505 0.6101049646142109 0.8660254037851645
+248 -1.213525491563439 0.8816778784394482 0.8660254037851645
+249 -1.003695909539129 1.114717238217025 0.8660254037851645
+250 -0.7587771091616358 -0.8427073534008298 0.5000000000009737
+251 -0.9174047195283126 -0.6665335441301496 0.5000000000009737
+252 -1.035937341455342 -0.4612290205981823 0.5000000000009737
+253 -1.109194530581887 -0.2357665756436804 0.5000000000009737
+254 -1.133974596216123 -3.885780586188048e-16 0.5000000000009737
+255 -1.109194530581887 0.2357665756436796 0.5000000000009737
+256 -1.035937341455342 0.4612290205981815 0.5000000000009737
+257 -0.917404719528313 0.6665335441301492 0.5000000000009737
+258 -0.7587771091616363 0.8427073534008294 0.5000000000009737
+259 -0.7481559088883528 -0.8302230159821991 -0.4704813284992345
+260 -0.9080564300337524 -0.6546284896371164 -0.4739006808591849
+261 -1.033141194038673 -0.4537054124936579 -0.4901726550580774
+262 -1.10919453058059 -0.2357665756434048 -0.4999999999986767
+263 -1.133974596214797 -3.885780586188048e-16 -0.4999999999986767
+264 -1.10919453058059 0.2357665756434039 -0.4999999999986767
+265 -1.035937341454131 0.4612290205976423 -0.4999999999986767
+266 -0.9174047195272402 0.6665335441293697 -0.4999999999986767
+267 -0.758777109160749 0.8427073533998439 -0.4999999999986767
+268 -1.003695909537362 -1.114717238215065 -0.8660254037836409
+269 -1.213525491561303 -0.8816778784378978 -0.8660254037836409
+270 -1.370318186462639 -0.6101049646131387 -0.8660254037836409
+271 -1.467221401099357 -0.3118675362263521 -0.8660254037836409
+272 -1.499999999998618 -4.440892098500626e-16 -0.8660254037836409
+273 -1.467221401099357 0.311867536226351 -0.8660254037836409
+274 -1.370318186462639 0.6101049646131377 -0.8660254037836409
+275 -1.213525491561304 0.881677878437897 -0.8660254037836409
+276 -1.003695909537363 1.114717238215064 -0.8660254037836409
+277 -1.672826515896257 -1.8578620636925 -0.8660254037852049
+278 -1.963074073363551 -1.418957125151159 -0.9064982567775998
+279 -2.22822218443823 -0.9856553115685951 -0.8997084139355865
+280 -2.412296183629799 -0.5045989907473138 -0.8855696323715803
+281 -2.487216873139954 0.01013127547259973 -0.8732694954395391
+282 -2.445369001833216 0.5197792270441215 -0.8660254037852049
+283 -2.28386364410529 1.01684160768896 -0.8660254037852049
+284 -2.022542485936295 1.469463130730402 -0.8660254037852049
+285 -1.672826515896258 1.857862063692499 -0.8660254037852049
+286 -1.917745316273775 -2.129871948508725 -0.5000000000010285
+287 -2.31866325797145 -1.684607465039725 -0.5000000000010285
+288 -2.618244489115032 -1.165717551705007 -0.5000000000010285
+289 -2.803395872353304 -0.5958801876273514 -0.5000000000010285
+290 -2.866025403783845 -8.881784197001252e-16 -0.5000000000010285
+291 -2.803395872353305 0.5958801876273493 -0.5000000000010285
+292 -2.618244489115033 1.165717551705005 -0.5000000000010285
+293 -2.318663257971452 1.684607465039724 -0.5000000000010285
+294 -1.917745316273777 2.129871948508723 -0.5000000000010285
+295 -0.8856505560799294 2.725752136137303 0.4999999999987891
+296 -0.2995812311437176 2.850325016746015 0.4999999999987891
+297 0.2995812311437149 2.850325016746015 0.4999999999987891
+298 0.8856505560799268 2.725752136137304 0.4999999999987891
+299 1.433012701892567 2.482050807569483 0.4999999999987891
+300 1.917745316274639 2.129871948509686 0.4999999999987891
+301 2.318663257972496 1.684607465040485 0.4999999999987891
+302 2.618244489116213 1.165717551705533 0.4999999999987891
+303 2.803395872354568 0.5958801876276207 0.4999999999987891
+304 -0.7451492462280477 2.407797970999816 0.8538836502101366
+305 -0.2613211581692664 2.486304738421933 0.866025403783713
+306 0.2613211581692634 2.486304738421933 0.866025403783713
+307 0.7725424859377554 2.37764129073908 0.866025403783713
+308 1.250000000000627 2.165063509462186 0.866025403783713
+309 1.672826515897985 1.857862063694421 0.866025403783713
+310 2.022542485938384 1.469463130731923 0.866025403783713
+311 2.28386364410765 1.016841607690013 0.866025403783713
+312 2.445369001835743 0.5197792270446611 0.866025403783713
+313 -0.4635254915628102 1.426584774443926 0.8660254037851645
+314 -0.1567926949016123 1.49178284305366 0.8660254037851645
+315 0.1567926949016109 1.49178284305366 0.8660254037851645
+316 0.4635254915628089 1.426584774443926 0.8660254037851645
+317 0.7500000000006277 1.299038105677747 0.8660254037851645
+318 1.003695909539128 1.114717238217026 0.8660254037851645
+319 1.213525491563437 0.8816778784394492 0.8660254037851645
+320 1.37031818646505 0.6101049646142124 0.8660254037851645
+321 1.467221401101938 0.3118675362269012 0.8660254037851645
+322 -0.3504174214202515 1.07847392904451 0.5000000000009737
+323 -0.1185326219270297 1.127762564728331 0.5000000000009737
+324 0.1185326219270287 1.127762564728331 0.5000000000009737
+325 0.3504174214202505 1.07847392904451 0.5000000000009737
+326 0.5669872981080611 0.9820508075693642 0.5000000000009737
+327 0.7587771091616354 0.84270735340083 0.5000000000009737
+328 0.9174047195283123 0.6665335441301499 0.5000000000009737
+329 1.035937341455342 0.4612290205981826 0.5000000000009737
+330 1.109194530581887 0.2357665756436807 0.5000000000009737
+331 -0.3464858812642241 1.060027172900686 -0.4660042150082114
+332 -0.1132045779631444 1.113326322193858 -0.473240860746253
+333 0.1235920473007865 1.121529907056787 -0.4900741448982694
+334 0.3504174214198407 1.078473929043249 -0.4999999999986767
+335 0.5669872981073981 0.9820508075682158 -0.4999999999986767
+336 0.758777109160748 0.8427073533998446 -0.4999999999986767
+337 0.9174047195272395 0.6665335441293705 -0.4999999999986767
+338 1.03593734145413 0.4612290205976433 -0.4999999999986767
+339 1.10919453058059 0.2357665756434049 -0.4999999999986767
+340 -0.4635254915619947 1.426584774441416 -0.8660254037836409
+341 -0.1567926949013363 1.491782843051035 -0.8660254037836409
+342 0.156792694901335 1.491782843051036 -0.8660254037836409
+343 0.4635254915619933 1.426584774441416 -0.8660254037836409
+344 0.7499999999993083 1.299038105675461 -0.8660254037836409
+345 1.003695909537362 1.114717238215065 -0.8660254037836409
+346 1.213525491561302 0.881677878437898 -0.8660254037836409
+347 1.370318186462638 0.6101049646131389 -0.8660254037836409
+348 1.467221401099357 0.3118675362263523 -0.8660254037836409
+349 -0.7725424859369594 2.377641290736622 -0.8660254037852049
+350 -0.2473158789728229 2.409550581694328 -0.9064982558924878
+351 0.2605085543773697 2.422524675641298 -0.8997084124871373
+352 0.7691525487586987 2.341409273183444 -0.8855696314358248
+353 1.252382377980021 2.148927360156276 -0.873269495088661
+354 1.672826515896256 1.8578620636925 -0.8660254037852049
+355 2.022542485936293 1.469463130730404 -0.8660254037852049
+356 2.283863644105289 1.016841607688962 -0.8660254037852049
+357 2.445369001833216 0.5197792270441236 -0.8660254037852049
+358 -0.88565055607953 2.725752136136074 -0.5000000000010285
+359 -0.2995812311435826 2.85032501674473 -0.5000000000010285
+360 0.2995812311435799 2.850325016744731 -0.5000000000010285
+361 0.8856505560795274 2.725752136136075 -0.5000000000010285
+362 1.433012701891921 2.482050807568364 -0.5000000000010285
+363 1.917745316273774 2.129871948508725 -0.5000000000010285
+364 2.31866325797145 1.684607465039726 -0.5000000000010285
+365 2.618244489115032 1.165717551705007 -0.5000000000010285
+366 2.803395872353304 0.5958801876273521 -0.5000000000010285
+$EndNodes
+$Elements
+894
+1 15 2 0 1 1
+2 15 2 0 2 2
+3 15 2 0 3 3
+4 15 2 0 4 4
+5 15 2 0 5 5
+6 15 2 0 6 6
+7 15 2 0 7 7
+8 15 2 0 8 8
+9 15 2 0 12 9
+10 15 2 0 14 10
+11 15 2 0 17 11
+12 15 2 0 20 12
+13 15 2 0 26 13
+14 15 2 0 27 14
+15 15 2 0 28 15
+16 15 2 0 29 16
+17 15 2 0 32 17
+18 15 2 0 35 18
+19 1 2 0 1 2 19
+20 1 2 0 1 19 20
+21 1 2 0 1 20 3
+22 1 2 0 2 3 21
+23 1 2 0 2 21 22
+24 1 2 0 2 22 4
+25 1 2 0 3 4 23
+26 1 2 0 3 23 24
+27 1 2 0 3 24 5
+28 1 2 0 4 5 25
+29 1 2 0 4 25 26
+30 1 2 0 4 26 2
+31 1 2 0 6 6 27
+32 1 2 0 6 27 28
+33 1 2 0 6 28 8
+34 1 2 0 7 2 29
+35 1 2 0 7 29 30
+36 1 2 0 7 30 31
+37 1 2 0 7 31 32
+38 1 2 0 7 32 33
+39 1 2 0 7 33 34
+40 1 2 0 7 34 35
+41 1 2 0 7 35 36
+42 1 2 0 7 36 37
+43 1 2 0 7 37 6
+44 1 2 0 8 3 38
+45 1 2 0 8 38 39
+46 1 2 0 8 39 40
+47 1 2 0 8 40 41
+48 1 2 0 8 41 42
+49 1 2 0 8 42 43
+50 1 2 0 8 43 44
+51 1 2 0 8 44 45
+52 1 2 0 8 45 46
+53 1 2 0 8 46 8
+54 1 2 0 10 8 47
+55 1 2 0 10 47 48
+56 1 2 0 10 48 11
+57 1 2 0 12 4 49
+58 1 2 0 12 49 50
+59 1 2 0 12 50 51
+60 1 2 0 12 51 52
+61 1 2 0 12 52 53
+62 1 2 0 12 53 54
+63 1 2 0 12 54 55
+64 1 2 0 12 55 56
+65 1 2 0 12 56 57
+66 1 2 0 12 57 11
+67 1 2 0 14 11 58
+68 1 2 0 14 58 59
+69 1 2 0 14 59 12
+70 1 2 0 16 5 60
+71 1 2 0 16 60 61
+72 1 2 0 16 61 62
+73 1 2 0 16 62 63
+74 1 2 0 16 63 64
+75 1 2 0 16 64 65
+76 1 2 0 16 65 66
+77 1 2 0 16 66 67
+78 1 2 0 16 67 68
+79 1 2 0 16 68 12
+80 1 2 0 18 12 69
+81 1 2 0 18 69 70
+82 1 2 0 18 70 6
+83 1 2 0 22 14 71
+84 1 2 0 22 71 72
+85 1 2 0 22 72 16
+86 1 2 0 23 6 73
+87 1 2 0 23 73 74
+88 1 2 0 23 74 75
+89 1 2 0 23 75 76
+90 1 2 0 23 76 77
+91 1 2 0 23 77 78
+92 1 2 0 23 78 79
+93 1 2 0 23 79 80
+94 1 2 0 23 80 81
+95 1 2 0 23 81 14
+96 1 2 0 24 8 82
+97 1 2 0 24 82 83
+98 1 2 0 24 83 84
+99 1 2 0 24 84 85
+100 1 2 0 24 85 86
+101 1 2 0 24 86 87
+102 1 2 0 24 87 88
+103 1 2 0 24 88 89
+104 1 2 0 24 89 90
+105 1 2 0 24 90 16
+106 1 2 0 26 16 91
+107 1 2 0 26 91 92
+108 1 2 0 26 92 17
+109 1 2 0 28 11 93
+110 1 2 0 28 93 94
+111 1 2 0 28 94 95
+112 1 2 0 28 95 96
+113 1 2 0 28 96 97
+114 1 2 0 28 97 98
+115 1 2 0 28 98 99
+116 1 2 0 28 99 100
+117 1 2 0 28 100 101
+118 1 2 0 28 101 17
+119 1 2 0 30 17 102
+120 1 2 0 30 102 103
+121 1 2 0 30 103 18
+122 1 2 0 32 12 104
+123 1 2 0 32 104 105
+124 1 2 0 32 105 106
+125 1 2 0 32 106 107
+126 1 2 0 32 107 108
+127 1 2 0 32 108 109
+128 1 2 0 32 109 110
+129 1 2 0 32 110 111
+130 1 2 0 32 111 112
+131 1 2 0 32 112 18
+132 1 2 0 34 18 113
+133 1 2 0 34 113 114
+134 1 2 0 34 114 14
+135 1 2 0 39 14 115
+136 1 2 0 39 115 116
+137 1 2 0 39 116 117
+138 1 2 0 39 117 118
+139 1 2 0 39 118 119
+140 1 2 0 39 119 120
+141 1 2 0 39 120 121
+142 1 2 0 39 121 122
+143 1 2 0 39 122 123
+144 1 2 0 39 123 2
+145 1 2 0 40 16 124
+146 1 2 0 40 124 125
+147 1 2 0 40 125 126
+148 1 2 0 40 126 127
+149 1 2 0 40 127 128
+150 1 2 0 40 128 129
+151 1 2 0 40 129 130
+152 1 2 0 40 130 131
+153 1 2 0 40 131 132
+154 1 2 0 40 132 3
+155 1 2 0 44 17 133
+156 1 2 0 44 133 134
+157 1 2 0 44 134 135
+158 1 2 0 44 135 136
+159 1 2 0 44 136 137
+160 1 2 0 44 137 138
+161 1 2 0 44 138 139
+162 1 2 0 44 139 140
+163 1 2 0 44 140 141
+164 1 2 0 44 141 4
+165 1 2 0 48 18 142
+166 1 2 0 48 142 143
+167 1 2 0 48 143 144
+168 1 2 0 48 144 145
+169 1 2 0 48 145 146
+170 1 2 0 48 146 147
+171 1 2 0 48 147 148
+172 1 2 0 48 148 149
+173 1 2 0 48 149 150
+174 1 2 0 48 150 5
+175 2 2 0 9 2 19 151
+176 2 2 0 9 2 151 29
+177 2 2 0 9 29 151 152
+178 2 2 0 9 29 152 30
+179 2 2 0 9 30 152 153
+180 2 2 0 9 30 153 31
+181 2 2 0 9 31 153 154
+182 2 2 0 9 31 154 32
+183 2 2 0 9 32 154 155
+184 2 2 0 9 32 155 33
+185 2 2 0 9 33 155 156
+186 2 2 0 9 33 156 34
+187 2 2 0 9 34 156 157
+188 2 2 0 9 34 157 35
+189 2 2 0 9 35 157 158
+190 2 2 0 9 35 158 36
+191 2 2 0 9 36 158 159
+192 2 2 0 9 36 159 37
+193 2 2 0 9 37 159 27
+194 2 2 0 9 37 27 6
+195 2 2 0 9 19 20 160
+196 2 2 0 9 19 160 151
+197 2 2 0 9 151 160 161
+198 2 2 0 9 151 161 152
+199 2 2 0 9 152 161 162
+200 2 2 0 9 152 162 153
+201 2 2 0 9 153 162 163
+202 2 2 0 9 153 163 154
+203 2 2 0 9 154 163 164
+204 2 2 0 9 154 164 155
+205 2 2 0 9 155 164 165
+206 2 2 0 9 155 165 156
+207 2 2 0 9 156 165 166
+208 2 2 0 9 156 166 157
+209 2 2 0 9 157 166 167
+210 2 2 0 9 157 167 158
+211 2 2 0 9 158 167 168
+212 2 2 0 9 158 168 159
+213 2 2 0 9 159 168 28
+214 2 2 0 9 159 28 27
+215 2 2 0 9 20 3 38
+216 2 2 0 9 20 38 160
+217 2 2 0 9 160 38 39
+218 2 2 0 9 160 39 161
+219 2 2 0 9 161 39 40
+220 2 2 0 9 161 40 162
+221 2 2 0 9 162 40 41
+222 2 2 0 9 162 41 163
+223 2 2 0 9 163 41 42
+224 2 2 0 9 163 42 164
+225 2 2 0 9 164 42 43
+226 2 2 0 9 164 43 165
+227 2 2 0 9 165 43 44
+228 2 2 0 9 165 44 166
+229 2 2 0 9 166 44 45
+230 2 2 0 9 166 45 167
+231 2 2 0 9 167 45 46
+232 2 2 0 9 167 46 168
+233 2 2 0 9 168 46 8
+234 2 2 0 9 168 8 28
+235 2 2 0 13 3 21 169
+236 2 2 0 13 3 169 38
+237 2 2 0 13 38 169 170
+238 2 2 0 13 38 170 39
+239 2 2 0 13 39 170 171
+240 2 2 0 13 39 171 40
+241 2 2 0 13 40 171 172
+242 2 2 0 13 40 172 41
+243 2 2 0 13 41 172 173
+244 2 2 0 13 41 173 42
+245 2 2 0 13 42 173 174
+246 2 2 0 13 42 174 43
+247 2 2 0 13 43 174 175
+248 2 2 0 13 43 175 44
+249 2 2 0 13 44 175 176
+250 2 2 0 13 44 176 45
+251 2 2 0 13 45 176 177
+252 2 2 0 13 45 177 46
+253 2 2 0 13 46 177 47
+254 2 2 0 13 46 47 8
+255 2 2 0 13 21 22 178
+256 2 2 0 13 21 178 169
+257 2 2 0 13 169 178 179
+258 2 2 0 13 169 179 170
+259 2 2 0 13 170 179 180
+260 2 2 0 13 170 180 171
+261 2 2 0 13 171 180 181
+262 2 2 0 13 171 181 172
+263 2 2 0 13 172 181 182
+264 2 2 0 13 172 182 173
+265 2 2 0 13 173 182 183
+266 2 2 0 13 173 183 174
+267 2 2 0 13 174 183 184
+268 2 2 0 13 174 184 175
+269 2 2 0 13 175 184 185
+270 2 2 0 13 175 185 176
+271 2 2 0 13 176 185 186
+272 2 2 0 13 176 186 177
+273 2 2 0 13 177 186 48
+274 2 2 0 13 177 48 47
+275 2 2 0 13 22 4 49
+276 2 2 0 13 22 49 178
+277 2 2 0 13 178 49 50
+278 2 2 0 13 178 50 179
+279 2 2 0 13 179 50 51
+280 2 2 0 13 179 51 180
+281 2 2 0 13 180 51 52
+282 2 2 0 13 180 52 181
+283 2 2 0 13 181 52 53
+284 2 2 0 13 181 53 182
+285 2 2 0 13 182 53 54
+286 2 2 0 13 182 54 183
+287 2 2 0 13 183 54 55
+288 2 2 0 13 183 55 184
+289 2 2 0 13 184 55 56
+290 2 2 0 13 184 56 185
+291 2 2 0 13 185 56 57
+292 2 2 0 13 185 57 186
+293 2 2 0 13 186 57 11
+294 2 2 0 13 186 11 48
+295 2 2 0 17 4 23 187
+296 2 2 0 17 4 187 49
+297 2 2 0 17 49 187 188
+298 2 2 0 17 49 188 50
+299 2 2 0 17 50 188 189
+300 2 2 0 17 50 189 51
+301 2 2 0 17 51 189 190
+302 2 2 0 17 51 190 52
+303 2 2 0 17 52 190 191
+304 2 2 0 17 52 191 53
+305 2 2 0 17 53 191 192
+306 2 2 0 17 53 192 54
+307 2 2 0 17 54 192 193
+308 2 2 0 17 54 193 55
+309 2 2 0 17 55 193 194
+310 2 2 0 17 55 194 56
+311 2 2 0 17 56 194 195
+312 2 2 0 17 56 195 57
+313 2 2 0 17 57 195 58
+314 2 2 0 17 57 58 11
+315 2 2 0 17 23 24 196
+316 2 2 0 17 23 196 187
+317 2 2 0 17 187 196 197
+318 2 2 0 17 187 197 188
+319 2 2 0 17 188 197 198
+320 2 2 0 17 188 198 189
+321 2 2 0 17 189 198 199
+322 2 2 0 17 189 199 190
+323 2 2 0 17 190 199 200
+324 2 2 0 17 190 200 191
+325 2 2 0 17 191 200 201
+326 2 2 0 17 191 201 192
+327 2 2 0 17 192 201 202
+328 2 2 0 17 192 202 193
+329 2 2 0 17 193 202 203
+330 2 2 0 17 193 203 194
+331 2 2 0 17 194 203 204
+332 2 2 0 17 194 204 195
+333 2 2 0 17 195 204 59
+334 2 2 0 17 195 59 58
+335 2 2 0 17 24 5 60
+336 2 2 0 17 24 60 196
+337 2 2 0 17 196 60 61
+338 2 2 0 17 196 61 197
+339 2 2 0 17 197 61 62
+340 2 2 0 17 197 62 198
+341 2 2 0 17 198 62 63
+342 2 2 0 17 198 63 199
+343 2 2 0 17 199 63 64
+344 2 2 0 17 199 64 200
+345 2 2 0 17 200 64 65
+346 2 2 0 17 200 65 201
+347 2 2 0 17 201 65 66
+348 2 2 0 17 201 66 202
+349 2 2 0 17 202 66 67
+350 2 2 0 17 202 67 203
+351 2 2 0 17 203 67 68
+352 2 2 0 17 203 68 204
+353 2 2 0 17 204 68 12
+354 2 2 0 17 204 12 59
+355 2 2 0 21 5 25 205
+356 2 2 0 21 5 205 60
+357 2 2 0 21 60 205 206
+358 2 2 0 21 60 206 61
+359 2 2 0 21 61 206 207
+360 2 2 0 21 61 207 62
+361 2 2 0 21 62 207 208
+362 2 2 0 21 62 208 63
+363 2 2 0 21 63 208 209
+364 2 2 0 21 63 209 64
+365 2 2 0 21 64 209 210
+366 2 2 0 21 64 210 65
+367 2 2 0 21 65 210 211
+368 2 2 0 21 65 211 66
+369 2 2 0 21 66 211 212
+370 2 2 0 21 66 212 67
+371 2 2 0 21 67 212 213
+372 2 2 0 21 67 213 68
+373 2 2 0 21 68 213 69
+374 2 2 0 21 68 69 12
+375 2 2 0 21 25 26 214
+376 2 2 0 21 25 214 205
+377 2 2 0 21 205 214 215
+378 2 2 0 21 205 215 206
+379 2 2 0 21 206 215 216
+380 2 2 0 21 206 216 207
+381 2 2 0 21 207 216 217
+382 2 2 0 21 207 217 208
+383 2 2 0 21 208 217 218
+384 2 2 0 21 208 218 209
+385 2 2 0 21 209 218 219
+386 2 2 0 21 209 219 210
+387 2 2 0 21 210 219 220
+388 2 2 0 21 210 220 211
+389 2 2 0 21 211 220 221
+390 2 2 0 21 211 221 212
+391 2 2 0 21 212 221 222
+392 2 2 0 21 212 222 213
+393 2 2 0 21 213 222 70
+394 2 2 0 21 213 70 69
+395 2 2 0 21 26 2 29
+396 2 2 0 21 26 29 214
+397 2 2 0 21 214 29 30
+398 2 2 0 21 214 30 215
+399 2 2 0 21 215 30 31
+400 2 2 0 21 215 31 216
+401 2 2 0 21 216 31 32
+402 2 2 0 21 216 32 217
+403 2 2 0 21 217 32 33
+404 2 2 0 21 217 33 218
+405 2 2 0 21 218 33 34
+406 2 2 0 21 218 34 219
+407 2 2 0 21 219 34 35
+408 2 2 0 21 219 35 220
+409 2 2 0 21 220 35 36
+410 2 2 0 21 220 36 221
+411 2 2 0 21 221 36 37
+412 2 2 0 21 221 37 222
+413 2 2 0 21 222 37 6
+414 2 2 0 21 222 6 70
+415 2 2 0 25 6 27 223
+416 2 2 0 25 6 223 73
+417 2 2 0 25 73 223 224
+418 2 2 0 25 73 224 74
+419 2 2 0 25 74 224 225
+420 2 2 0 25 74 225 75
+421 2 2 0 25 75 225 226
+422 2 2 0 25 75 226 76
+423 2 2 0 25 76 226 227
+424 2 2 0 25 76 227 77
+425 2 2 0 25 77 227 228
+426 2 2 0 25 77 228 78
+427 2 2 0 25 78 228 229
+428 2 2 0 25 78 229 79
+429 2 2 0 25 79 229 230
+430 2 2 0 25 79 230 80
+431 2 2 0 25 80 230 231
+432 2 2 0 25 80 231 81
+433 2 2 0 25 81 231 71
+434 2 2 0 25 81 71 14
+435 2 2 0 25 27 28 232
+436 2 2 0 25 27 232 223
+437 2 2 0 25 223 232 233
+438 2 2 0 25 223 233 224
+439 2 2 0 25 224 233 234
+440 2 2 0 25 224 234 225
+441 2 2 0 25 225 234 235
+442 2 2 0 25 225 235 226
+443 2 2 0 25 226 235 236
+444 2 2 0 25 226 236 227
+445 2 2 0 25 227 236 237
+446 2 2 0 25 227 237 228
+447 2 2 0 25 228 237 238
+448 2 2 0 25 228 238 229
+449 2 2 0 25 229 238 239
+450 2 2 0 25 229 239 230
+451 2 2 0 25 230 239 240
+452 2 2 0 25 230 240 231
+453 2 2 0 25 231 240 72
+454 2 2 0 25 231 72 71
+455 2 2 0 25 28 8 82
+456 2 2 0 25 28 82 232
+457 2 2 0 25 232 82 83
+458 2 2 0 25 232 83 233
+459 2 2 0 25 233 83 84
+460 2 2 0 25 233 84 234
+461 2 2 0 25 234 84 85
+462 2 2 0 25 234 85 235
+463 2 2 0 25 235 85 86
+464 2 2 0 25 235 86 236
+465 2 2 0 25 236 86 87
+466 2 2 0 25 236 87 237
+467 2 2 0 25 237 87 88
+468 2 2 0 25 237 88 238
+469 2 2 0 25 238 88 89
+470 2 2 0 25 238 89 239
+471 2 2 0 25 239 89 90
+472 2 2 0 25 239 90 240
+473 2 2 0 25 240 90 16
+474 2 2 0 25 240 16 72
+475 2 2 0 29 8 47 241
+476 2 2 0 29 8 241 82
+477 2 2 0 29 82 241 242
+478 2 2 0 29 82 242 83
+479 2 2 0 29 83 242 243
+480 2 2 0 29 83 243 84
+481 2 2 0 29 84 243 244
+482 2 2 0 29 84 244 85
+483 2 2 0 29 85 244 245
+484 2 2 0 29 85 245 86
+485 2 2 0 29 86 245 246
+486 2 2 0 29 86 246 87
+487 2 2 0 29 87 246 247
+488 2 2 0 29 87 247 88
+489 2 2 0 29 88 247 248
+490 2 2 0 29 88 248 89
+491 2 2 0 29 89 248 249
+492 2 2 0 29 89 249 90
+493 2 2 0 29 90 249 91
+494 2 2 0 29 90 91 16
+495 2 2 0 29 47 48 250
+496 2 2 0 29 47 250 241
+497 2 2 0 29 241 250 251
+498 2 2 0 29 241 251 242
+499 2 2 0 29 242 251 252
+500 2 2 0 29 242 252 243
+501 2 2 0 29 243 252 253
+502 2 2 0 29 243 253 244
+503 2 2 0 29 244 253 254
+504 2 2 0 29 244 254 245
+505 2 2 0 29 245 254 255
+506 2 2 0 29 245 255 246
+507 2 2 0 29 246 255 256
+508 2 2 0 29 246 256 247
+509 2 2 0 29 247 256 257
+510 2 2 0 29 247 257 248
+511 2 2 0 29 248 257 258
+512 2 2 0 29 248 258 249
+513 2 2 0 29 249 258 92
+514 2 2 0 29 249 92 91
+515 2 2 0 29 48 11 93
+516 2 2 0 29 48 93 250
+517 2 2 0 29 250 93 94
+518 2 2 0 29 250 94 251
+519 2 2 0 29 251 94 95
+520 2 2 0 29 251 95 252
+521 2 2 0 29 252 95 96
+522 2 2 0 29 252 96 253
+523 2 2 0 29 253 96 97
+524 2 2 0 29 253 97 254
+525 2 2 0 29 254 97 98
+526 2 2 0 29 254 98 255
+527 2 2 0 29 255 98 99
+528 2 2 0 29 255 99 256
+529 2 2 0 29 256 99 100
+530 2 2 0 29 256 100 257
+531 2 2 0 29 257 100 101
+532 2 2 0 29 257 101 258
+533 2 2 0 29 258 101 17
+534 2 2 0 29 258 17 92
+535 2 2 0 33 11 58 259
+536 2 2 0 33 11 259 93
+537 2 2 0 33 93 259 260
+538 2 2 0 33 93 260 94
+539 2 2 0 33 94 260 261
+540 2 2 0 33 94 261 95
+541 2 2 0 33 95 261 262
+542 2 2 0 33 95 262 96
+543 2 2 0 33 96 262 263
+544 2 2 0 33 96 263 97
+545 2 2 0 33 97 263 264
+546 2 2 0 33 97 264 98
+547 2 2 0 33 98 264 265
+548 2 2 0 33 98 265 99
+549 2 2 0 33 99 265 266
+550 2 2 0 33 99 266 100
+551 2 2 0 33 100 266 267
+552 2 2 0 33 100 267 101
+553 2 2 0 33 101 267 102
+554 2 2 0 33 101 102 17
+555 2 2 0 33 58 59 268
+556 2 2 0 33 58 268 259
+557 2 2 0 33 259 268 269
+558 2 2 0 33 259 269 260
+559 2 2 0 33 260 269 270
+560 2 2 0 33 260 270 261
+561 2 2 0 33 261 270 271
+562 2 2 0 33 261 271 262
+563 2 2 0 33 262 271 272
+564 2 2 0 33 262 272 263
+565 2 2 0 33 263 272 273
+566 2 2 0 33 263 273 264
+567 2 2 0 33 264 273 274
+568 2 2 0 33 264 274 265
+569 2 2 0 33 265 274 275
+570 2 2 0 33 265 275 266
+571 2 2 0 33 266 275 276
+572 2 2 0 33 266 276 267
+573 2 2 0 33 267 276 103
+574 2 2 0 33 267 103 102
+575 2 2 0 33 59 12 104
+576 2 2 0 33 59 104 268
+577 2 2 0 33 268 104 105
+578 2 2 0 33 268 105 269
+579 2 2 0 33 269 105 106
+580 2 2 0 33 269 106 270
+581 2 2 0 33 270 106 107
+582 2 2 0 33 270 107 271
+583 2 2 0 33 271 107 108
+584 2 2 0 33 271 108 272
+585 2 2 0 33 272 108 109
+586 2 2 0 33 272 109 273
+587 2 2 0 33 273 109 110
+588 2 2 0 33 273 110 274
+589 2 2 0 33 274 110 111
+590 2 2 0 33 274 111 275
+591 2 2 0 33 275 111 112
+592 2 2 0 33 275 112 276
+593 2 2 0 33 276 112 18
+594 2 2 0 33 276 18 103
+595 2 2 0 37 12 69 277
+596 2 2 0 37 12 277 104
+597 2 2 0 37 104 277 278
+598 2 2 0 37 104 278 105
+599 2 2 0 37 105 278 279
+600 2 2 0 37 105 279 106
+601 2 2 0 37 106 279 280
+602 2 2 0 37 106 280 107
+603 2 2 0 37 107 280 281
+604 2 2 0 37 107 281 108
+605 2 2 0 37 108 281 282
+606 2 2 0 37 108 282 109
+607 2 2 0 37 109 282 283
+608 2 2 0 37 109 283 110
+609 2 2 0 37 110 283 284
+610 2 2 0 37 110 284 111
+611 2 2 0 37 111 284 285
+612 2 2 0 37 111 285 112
+613 2 2 0 37 112 285 113
+614 2 2 0 37 112 113 18
+615 2 2 0 37 69 70 286
+616 2 2 0 37 69 286 277
+617 2 2 0 37 277 286 287
+618 2 2 0 37 277 287 278
+619 2 2 0 37 278 287 288
+620 2 2 0 37 278 288 279
+621 2 2 0 37 279 288 289
+622 2 2 0 37 279 289 280
+623 2 2 0 37 280 289 290
+624 2 2 0 37 280 290 281
+625 2 2 0 37 281 290 291
+626 2 2 0 37 281 291 282
+627 2 2 0 37 282 291 292
+628 2 2 0 37 282 292 283
+629 2 2 0 37 283 292 293
+630 2 2 0 37 283 293 284
+631 2 2 0 37 284 293 294
+632 2 2 0 37 284 294 285
+633 2 2 0 37 285 294 114
+634 2 2 0 37 285 114 113
+635 2 2 0 37 70 6 73
+636 2 2 0 37 70 73 286
+637 2 2 0 37 286 73 74
+638 2 2 0 37 286 74 287
+639 2 2 0 37 287 74 75
+640 2 2 0 37 287 75 288
+641 2 2 0 37 288 75 76
+642 2 2 0 37 288 76 289
+643 2 2 0 37 289 76 77
+644 2 2 0 37 289 77 290
+645 2 2 0 37 290 77 78
+646 2 2 0 37 290 78 291
+647 2 2 0 37 291 78 79
+648 2 2 0 37 291 79 292
+649 2 2 0 37 292 79 80
+650 2 2 0 37 292 80 293
+651 2 2 0 37 293 80 81
+652 2 2 0 37 293 81 294
+653 2 2 0 37 294 81 14
+654 2 2 0 37 294 14 114
+655 2 2 0 41 14 71 295
+656 2 2 0 41 14 295 115
+657 2 2 0 41 115 295 296
+658 2 2 0 41 115 296 116
+659 2 2 0 41 116 296 297
+660 2 2 0 41 116 297 117
+661 2 2 0 41 117 297 298
+662 2 2 0 41 117 298 118
+663 2 2 0 41 118 298 299
+664 2 2 0 41 118 299 119
+665 2 2 0 41 119 299 300
+666 2 2 0 41 119 300 120
+667 2 2 0 41 120 300 301
+668 2 2 0 41 120 301 121
+669 2 2 0 41 121 301 302
+670 2 2 0 41 121 302 122
+671 2 2 0 41 122 302 303
+672 2 2 0 41 122 303 123
+673 2 2 0 41 123 303 19
+674 2 2 0 41 123 19 2
+675 2 2 0 41 71 72 304
+676 2 2 0 41 71 304 295
+677 2 2 0 41 295 304 305
+678 2 2 0 41 295 305 296
+679 2 2 0 41 296 305 306
+680 2 2 0 41 296 306 297
+681 2 2 0 41 297 306 307
+682 2 2 0 41 297 307 298
+683 2 2 0 41 298 307 308
+684 2 2 0 41 298 308 299
+685 2 2 0 41 299 308 309
+686 2 2 0 41 299 309 300
+687 2 2 0 41 300 309 310
+688 2 2 0 41 300 310 301
+689 2 2 0 41 301 310 311
+690 2 2 0 41 301 311 302
+691 2 2 0 41 302 311 312
+692 2 2 0 41 302 312 303
+693 2 2 0 41 303 312 20
+694 2 2 0 41 303 20 19
+695 2 2 0 41 72 16 124
+696 2 2 0 41 72 124 304
+697 2 2 0 41 304 124 125
+698 2 2 0 41 304 125 305
+699 2 2 0 41 305 125 126
+700 2 2 0 41 305 126 306
+701 2 2 0 41 306 126 127
+702 2 2 0 41 306 127 307
+703 2 2 0 41 307 127 128
+704 2 2 0 41 307 128 308
+705 2 2 0 41 308 128 129
+706 2 2 0 41 308 129 309
+707 2 2 0 41 309 129 130
+708 2 2 0 41 309 130 310
+709 2 2 0 41 310 130 131
+710 2 2 0 41 310 131 311
+711 2 2 0 41 311 131 132
+712 2 2 0 41 311 132 312
+713 2 2 0 41 312 132 3
+714 2 2 0 41 312 3 20
+715 2 2 0 45 16 91 313
+716 2 2 0 45 16 313 124
+717 2 2 0 45 124 313 314
+718 2 2 0 45 124 314 125
+719 2 2 0 45 125 314 315
+720 2 2 0 45 125 315 126
+721 2 2 0 45 126 315 316
+722 2 2 0 45 126 316 127
+723 2 2 0 45 127 316 317
+724 2 2 0 45 127 317 128
+725 2 2 0 45 128 317 318
+726 2 2 0 45 128 318 129
+727 2 2 0 45 129 318 319
+728 2 2 0 45 129 319 130
+729 2 2 0 45 130 319 320
+730 2 2 0 45 130 320 131
+731 2 2 0 45 131 320 321
+732 2 2 0 45 131 321 132
+733 2 2 0 45 132 321 21
+734 2 2 0 45 132 21 3
+735 2 2 0 45 91 92 322
+736 2 2 0 45 91 322 313
+737 2 2 0 45 313 322 323
+738 2 2 0 45 313 323 314
+739 2 2 0 45 314 323 324
+740 2 2 0 45 314 324 315
+741 2 2 0 45 315 324 325
+742 2 2 0 45 315 325 316
+743 2 2 0 45 316 325 326
+744 2 2 0 45 316 326 317
+745 2 2 0 45 317 326 327
+746 2 2 0 45 317 327 318
+747 2 2 0 45 318 327 328
+748 2 2 0 45 318 328 319
+749 2 2 0 45 319 328 329
+750 2 2 0 45 319 329 320
+751 2 2 0 45 320 329 330
+752 2 2 0 45 320 330 321
+753 2 2 0 45 321 330 22
+754 2 2 0 45 321 22 21
+755 2 2 0 45 92 17 133
+756 2 2 0 45 92 133 322
+757 2 2 0 45 322 133 134
+758 2 2 0 45 322 134 323
+759 2 2 0 45 323 134 135
+760 2 2 0 45 323 135 324
+761 2 2 0 45 324 135 136
+762 2 2 0 45 324 136 325
+763 2 2 0 45 325 136 137
+764 2 2 0 45 325 137 326
+765 2 2 0 45 326 137 138
+766 2 2 0 45 326 138 327
+767 2 2 0 45 327 138 139
+768 2 2 0 45 327 139 328
+769 2 2 0 45 328 139 140
+770 2 2 0 45 328 140 329
+771 2 2 0 45 329 140 141
+772 2 2 0 45 329 141 330
+773 2 2 0 45 330 141 4
+774 2 2 0 45 330 4 22
+775 2 2 0 49 17 102 331
+776 2 2 0 49 17 331 133
+777 2 2 0 49 133 331 332
+778 2 2 0 49 133 332 134
+779 2 2 0 49 134 332 333
+780 2 2 0 49 134 333 135
+781 2 2 0 49 135 333 334
+782 2 2 0 49 135 334 136
+783 2 2 0 49 136 334 335
+784 2 2 0 49 136 335 137
+785 2 2 0 49 137 335 336
+786 2 2 0 49 137 336 138
+787 2 2 0 49 138 336 337
+788 2 2 0 49 138 337 139
+789 2 2 0 49 139 337 338
+790 2 2 0 49 139 338 140
+791 2 2 0 49 140 338 339
+792 2 2 0 49 140 339 141
+793 2 2 0 49 141 339 23
+794 2 2 0 49 141 23 4
+795 2 2 0 49 102 103 340
+796 2 2 0 49 102 340 331
+797 2 2 0 49 331 340 341
+798 2 2 0 49 331 341 332
+799 2 2 0 49 332 341 342
+800 2 2 0 49 332 342 333
+801 2 2 0 49 333 342 343
+802 2 2 0 49 333 343 334
+803 2 2 0 49 334 343 344
+804 2 2 0 49 334 344 335
+805 2 2 0 49 335 344 345
+806 2 2 0 49 335 345 336
+807 2 2 0 49 336 345 346
+808 2 2 0 49 336 346 337
+809 2 2 0 49 337 346 347
+810 2 2 0 49 337 347 338
+811 2 2 0 49 338 347 348
+812 2 2 0 49 338 348 339
+813 2 2 0 49 339 348 24
+814 2 2 0 49 339 24 23
+815 2 2 0 49 103 18 142
+816 2 2 0 49 103 142 340
+817 2 2 0 49 340 142 143
+818 2 2 0 49 340 143 341
+819 2 2 0 49 341 143 144
+820 2 2 0 49 341 144 342
+821 2 2 0 49 342 144 145
+822 2 2 0 49 342 145 343
+823 2 2 0 49 343 145 146
+824 2 2 0 49 343 146 344
+825 2 2 0 49 344 146 147
+826 2 2 0 49 344 147 345
+827 2 2 0 49 345 147 148
+828 2 2 0 49 345 148 346
+829 2 2 0 49 346 148 149
+830 2 2 0 49 346 149 347
+831 2 2 0 49 347 149 150
+832 2 2 0 49 347 150 348
+833 2 2 0 49 348 150 5
+834 2 2 0 49 348 5 24
+835 2 2 0 53 18 113 349
+836 2 2 0 53 18 349 142
+837 2 2 0 53 142 349 350
+838 2 2 0 53 142 350 143
+839 2 2 0 53 143 350 351
+840 2 2 0 53 143 351 144
+841 2 2 0 53 144 351 352
+842 2 2 0 53 144 352 145
+843 2 2 0 53 145 352 353
+844 2 2 0 53 145 353 146
+845 2 2 0 53 146 353 354
+846 2 2 0 53 146 354 147
+847 2 2 0 53 147 354 355
+848 2 2 0 53 147 355 148
+849 2 2 0 53 148 355 356
+850 2 2 0 53 148 356 149
+851 2 2 0 53 149 356 357
+852 2 2 0 53 149 357 150
+853 2 2 0 53 150 357 25
+854 2 2 0 53 150 25 5
+855 2 2 0 53 113 114 358
+856 2 2 0 53 113 358 349
+857 2 2 0 53 349 358 359
+858 2 2 0 53 349 359 350
+859 2 2 0 53 350 359 360
+860 2 2 0 53 350 360 351
+861 2 2 0 53 351 360 361
+862 2 2 0 53 351 361 352
+863 2 2 0 53 352 361 362
+864 2 2 0 53 352 362 353
+865 2 2 0 53 353 362 363
+866 2 2 0 53 353 363 354
+867 2 2 0 53 354 363 364
+868 2 2 0 53 354 364 355
+869 2 2 0 53 355 364 365
+870 2 2 0 53 355 365 356
+871 2 2 0 53 356 365 366
+872 2 2 0 53 356 366 357
+873 2 2 0 53 357 366 26
+874 2 2 0 53 357 26 25
+875 2 2 0 53 114 14 115
+876 2 2 0 53 114 115 358
+877 2 2 0 53 358 115 116
+878 2 2 0 53 358 116 359
+879 2 2 0 53 359 116 117
+880 2 2 0 53 359 117 360
+881 2 2 0 53 360 117 118
+882 2 2 0 53 360 118 361
+883 2 2 0 53 361 118 119
+884 2 2 0 53 361 119 362
+885 2 2 0 53 362 119 120
+886 2 2 0 53 362 120 363
+887 2 2 0 53 363 120 121
+888 2 2 0 53 363 121 364
+889 2 2 0 53 364 121 122
+890 2 2 0 53 364 122 365
+891 2 2 0 53 365 122 123
+892 2 2 0 53 365 123 366
+893 2 2 0 53 366 123 2
+894 2 2 0 53 366 2 26
+$EndElements