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