14#ifndef BOUNDARYINTERPOLATION_HH
15#define BOUNDARYINTERPOLATION_HH
25#include <boost/math/constants/constants.hpp>
27#include "dune/common/fvector.hh"
28#include "dune/grid/common/boundarysegment.hh"
29#include "dune/grid/uggrid.hh"
57 template <
class Index,
class Vector>
61 using ctype =
typename Vector::value_type;
62 constexpr static int dim = Vector::dimension;
72 : vidx{v1,v2}, t{normalize(t1),normalize(t2)}
74 if (vidx[0] > vidx[1])
76 std::swap(vidx[0],vidx[1]);
109 return vidx < e.vidx;
119 return vidx == e.vidx;
129 assert(0<=i && i<=1);
135 assert(0<=i && i<=1);
149 return v==vidx[0] || v==vidx[1];
161 t[0] = normalize(t[0]+du0*t[0]);
162 t[1] = normalize(t[1]+du1*t[1]);
166 std::array<Index,2> vidx;
167 std::array<Vector,2> t;
175 template <
class Scalar,
int dim>
178 template <
class Scalar,
int dim>
181 template <
class Scalar,
int dim>
184 template <
class Scalar,
int dim>
185 using EdgeDirections = std::array<BoundaryEdge<int,Vector<Scalar,dim>>,dim*(dim+1)/2>;
205 template <
class Scalar,
int dim>
211 template <
class Scalar,
int dim>
226 template <
class Index,
class ctype,
int dim>
249 template <
class Index,
class ctype,
int dim>
272 template <
class Gr
idView>
273 std::map<
typename GridView::IndexSet::IndexType,
277 constexpr int dim = GridView::dimension;
278 using ctype =
typename GridView::ctype;
279 using Index =
typename GridView::IndexSet::IndexType;
283 auto const& is = gv.indexSet();
286 std::map<Index,BoundaryStar<Index,ctype,dim>> stars;
294 Vector const n = face.centerUnitOuterNormal();
297 vertexids(dim,1,face.indexInInside(),vSubIdx);
300 for (
int i=0; i<dim; ++i)
301 vIdx[i] = is.subIndex(face.inside(),vSubIdx[i],dim);
303 for (
int i=0; i<dim; ++i)
306 for (
int j=0; j<dim-1; ++j)
308 corner.
vidx[j] = vIdx[(i+j+1)%dim];
309 corner.
vx[j] = face.inside().geometry().corner(vSubIdx[(i+j+1)%dim]);
312 corner.
bsi = face.boundarySegmentIndex();
314 auto& star = stars[vIdx[i]];
316 star.vx = face.inside().geometry().corner(vSubIdx[i]);
317 star.corners.push_back(corner);
330 template <
class Index,
class ctype,
int dim>
407 template <
class Index,
class ctype,
int dim>
475 ctype featureCurveThreshold;
476 ctype featureEdgeThreshold;
479 template <
class Gr
idView>
481 typename GridView::ctype,GridView::dimension>;
502 template <
class Index,
class ctype>
505 template <
class Index,
class ctype>
522 template <
int dim,
class Index,
class ctype =
double>
549 template <
class Gr
id>
552 static_assert(dim==Grid::dimension,
"dimension mismatch.");
566 std::map<std::array<Index,2>,
Vector> orientedEdges;
567 for (
auto& vertex_star: stars)
571 for (
auto const& e: orientedEdges)
574 auto const& t2 = orientedEdges[std::array<Index,2>{e.first[1],e.first[0]}];
588 template <
class Gr
idView>
595 namespace BoundaryInterpolationDetail
599 template <
class Cell>
602 constexpr int dim = Cell::dimension;
603 std::array<Dune::FieldVector<typename Cell::Geometry::ctype, dim>, dim+1> vertexPositions;
604 for (
int i=0; i<=dim; ++i)
605 vertexPositions[i] = cell.geometry().corner(i);
607 return vertexPositions;
612 template <
class Cell,
class Gr
idView,
class Vector,
class Index>
615 std::array<Vector, Cell::dimension+1>
const& vertexPositions)
617 constexpr int dim = Cell::dimension;
619 using ReturnType = std::optional<CellEdges>;
622 std::array<Index, dim+1> vIdx;
623 for (
int i=0; i<=dim; ++i)
624 vIdx[i] = gv.indexSet().subIndex(cell,i,dim);
626 std::vector<BoundaryEdge<int,Vector>> cellEdges2;
627 bool hasBoundaryEdges =
false;
628 for (
int i=0; i<dim; ++i)
629 for (
int j=i+1; j<=dim; ++j)
632 auto be = boundaryEdges.find(edge);
633 if (be!=boundaryEdges.end())
635 std::array<Vector,2> t = be->tangents();
637 std::swap(t[0],t[1]);
640 hasBoundaryEdges =
true;
644 Vector tx = normalize(vertexPositions[j]-vertexPositions[i]);
649 if (!hasBoundaryEdges)
653 std::copy(begin(cellEdges2),end(cellEdges2),begin(cellEdges));
654 return ReturnType(cellEdges);
659 template <
class Cell,
class Gr
idView>
662 constexpr int dim = Cell::dimension;
663 using ReturnType = std::array<bool,dim+1>;
665 ReturnType isBoundaryFace;
666 std::fill(begin(isBoundaryFace),end(isBoundaryFace),
false);
668 for (
auto const& face: intersections(gv,cell))
669 if (face.boundary() && !face.neighbor())
671 std::array<int,dim> vSubIdx;
672 vertexids(dim,1,face.indexInInside(),&vSubIdx[0]);
674 std::array<bool,dim+1> isOppositeBoundaryFace;
675 std::fill(begin(isOppositeBoundaryFace),end(isOppositeBoundaryFace),
true);
676 for (
int i=0; i<dim; ++i)
677 isOppositeBoundaryFace[vSubIdx[i]] =
false;
679 for (
int i=0; i<dim+1; ++i)
680 isBoundaryFace[i] |= isOppositeBoundaryFace[i];
683 return isBoundaryFace;
687 template <
class Cell,
class Gr
idView,
class Vector,
class Index>
690 std::vector<Vector>& xs,
691 bool computeDisplacements)
693 constexpr int dim = Cell::dimension;
695 auto const& gv0 = gv.grid().levelGridView(0);
701 auto cellEdges =
getCellEdges(cell, gv0, boundaryEdges, vertexPositions);
712 for (
int i=0; i<=dim; ++i)
714 Vector const x = child.geometry().corner(i);
715 Index vidx = gv.indexSet().subIndex(child,i,dim);
717 if ( (computeDisplacements && xs[vidx].two_norm2()>0)
718 || (!computeDisplacements && (xs[vidx]-x).two_norm2()>0) )
721 Vector const xi = cell.geometry().local(x);
725 xs[vidx] = computeDisplacements? u: x+u;
747 template <
class Gr
idView>
748 std::vector<Dune::FieldVector<typename GridView::ctype,GridView::dimension>>
750 GridBoundaryTangents<GridView>
const& tangents,
751 bool computeDisplacements=
false)
753 using namespace BoundaryInterpolationDetail;
754 constexpr int dim = GridView::dimension;
759 std::vector<Vector> xs(gv.size(dim));
760 if (!computeDisplacements)
761 for (
auto const& v: vertices(gv))
762 xs[gv.indexSet().index(v)] = v.geometry().center();
765 auto const& gv0 = gv.grid().levelGridView(0);
768 for (
auto const& cell: elements(gv0))
782 template <
class Gr
idView>
785 static constexpr int dim = GridView::dimensionworld;
786 using ctype =
typename GridView::ctype;
801 using namespace BoundaryInterpolationDetail;
803 int nCoarseCells = gridView.size(0);
804 vertexPositions.resize(nCoarseCells);
805 cellEdges.resize(nCoarseCells);
806 isBoundaryFace.resize(nCoarseCells);
808 for (
auto const& cell: elements(gridView))
810 auto cellIdx = gridView.indexSet().index(cell);
816 cellEdges[cellIdx] =
getCellEdges(cell, gridView, tangents.boundaryEdges2, vertexPositions[cellIdx]);
841 template <
class VolumeDisplacement>
844 auto const& is = gridView.indexSet();
845 std::vector<Dune::FieldMatrix<ctype,dim,dim>> du(is.size(dim),0.0);
846 std::vector<int>
count(du.size(),0);
847 std::vector<std::array<size_t,dim+1>> cellToGlobalVidx(is.size(0));
853 for (
auto const& cell: elements(gridView))
855 auto cellIdx = is.index(cell);
858 for (
int i=0; i<=dim; ++i)
860 auto x = cell.geometry().corner(i);
862 vertexPositions[cellIdx][i] = x + u.value(leafCell,xi);
864 auto vidx = is.subIndex(cell,i,dim);
865 assert(0<=vidx && vidx<du.size());
866 du[vidx] += u.derivative(leafCell,xi);
869 cellToGlobalVidx[cellIdx][i] = vidx;
874 for (
size_t i=0; i<du.size(); ++i)
882 for (
size_t cellIdx=0; cellIdx<cellToGlobalVidx.size(); ++cellIdx)
883 if (cellEdges[cellIdx])
884 for (
auto& ed: *cellEdges[cellIdx])
886 auto v0idx = cellToGlobalVidx[cellIdx][ed.vertex(0)];
887 auto v1idx = cellToGlobalVidx[cellIdx][ed.vertex(1)];
888 ed.displace(du[v0idx],du[v1idx]);
907 while (coarseCell.hasFather())
909 xi = coarseCell.geometryInFather().global(xi);
910 coarseCell = coarseCell.father();
917 std::size_t coarseCellIdx = gridView.indexSet().index(coarseCell);
920 for (
int i=0; i<=dim; ++i)
921 u += b[i] * (vertexPositions[coarseCellIdx][i]-coarseCell.geometry().corner(i));
922 if (cellEdges[coarseCellIdx])
924 isBoundaryFace[coarseCellIdx],b);
938 while (coarseCell.hasFather())
940 xi = coarseCell.geometryInFather().global(xi);
941 coarseCell = coarseCell.father();
946 auto dxi_dx =
transpose(coarseCell.geometry().jacobianInverseTransposed(xi));
948 std::size_t coarseCellIdx = gridView.indexSet().index(coarseCell);
955 for (
int i=0; i<=dim; ++i)
957 u += b[i] * (vertexPositions[coarseCellIdx][i]-coarseCell.geometry().corner(i));
958 du_dx +=
outerProduct(vertexPositions[coarseCellIdx][i]-coarseCell.geometry().corner(i),db_dx[i]);
961 if (cellEdges[coarseCellIdx])
963 isBoundaryFace[coarseCellIdx],b) * db_dx;
969 GridView
const gridView;
970 std::vector<Simplex::VertexPositions<ctype,dim>> vertexPositions;
971 std::vector<std::optional<Simplex::EdgeDirections<ctype,dim>>> cellEdges;
972 std::vector<Simplex::FaceFlags<dim>> isBoundaryFace;
983 template <
class VolumeDisplacement>
986 typename VolumeDisplacement::Space::Grid::ctype,
987 VolumeDisplacement::Space::Grid::dimension>
const& features)
989 using Grid =
typename VolumeDisplacement::Space::Grid;
990 using GridView =
typename Grid::LevelGridView;
992 GridBoundaryTangents<GridView> boundaryTangents(u.space().grid(),features);
1001 template <
class Gr
idView>
1004 using Grid =
typename GridView::Grid;
1005 using Index =
typename Grid::LevelGridView::IndexSet::IndexType;
1006 using ctype =
typename Grid::ctype;
1007 static int const dim = Grid::dimension;
1013 template <
class VolumeDisplacement>
1016 *
this = displacement;
1017 features = std::make_unique<AngleFeatureDetector<Index,ctype,dim>>(1.0,0.5);
1020 template <
class VolumeDisplacement>
1022 : features(std::move(features_))
1024 *
this = displacement;
1029 template <
class VolumeDisplacement>
1032 u = std::make_unique<BoundaryInterpolationDisplacement<GridView>>(makeCompositeBoundaryInterpolation(displacement,*features));
1040 return u->value(cell,position);
1045 return u->derivative(cell,position);
1049 std::unique_ptr<BoundaryInterpolationDisplacement<GridView>> u;
1050 std::unique_ptr<Features> features;
Specifying geometric features in terms of angles between face normals and edge tangents.
AngleFeatureDetector(ctype featureCurveAngle=1.0, ctype featureEdgeAngle=0.5)
Constructor.
virtual bool isFeatureEdge(Index vidx, Vector const &n1, Vector const &n2, int bsid1, int bsid2) const
Decides whether a boundary edge of a 3D domain is part of a smooth boundary patch or not.
virtual bool isFeatureVertex(Index vidx, Vector const &t1, Vector const &t2, int bsid1, int bsid2) const
Decides whether two boundary edges emanating from a joint vertex of a 2D domain are part of a smooth ...
virtual ~AngleFeatureDetector()
virtual bool isFeatureCurve(Index vidx, Vector const &t1, Vector const &t2) const
Decides whether two feature boundary edges of a 3D domain meeting in a joint vertex are part of a smo...
BoundaryDisplacementByInterpolation(VolumeDisplacement const &displacement, std::unique_ptr< Features > features_)
BoundaryDisplacementByInterpolation & operator=(VolumeDisplacement const &displacement)
BoundaryDisplacementByInterpolation(VolumeDisplacement const &displacement)
DisplacementDerivative derivative(Cell< GridView > const &cell, LocalPosition< GridView > const &position) const
GlobalPosition< GridView > value(Cell< GridView > const &cell, LocalPosition< GridView > const &position) const
int order(Cell< GridView > const &) const
A class storing a boundary edge consisting of two vertex indices and associated boundary curve tangen...
std::array< Vector, 2 > const & tangents() const
bool incident(Index v) const
Checks whether the edge is incident to the given vertex.
Index vertex(int i) const
bool operator<(BoundaryEdge const &e) const
Comparison by lexicographic order of the vertex indices.
BoundaryEdge()
Default constructor.
BoundaryEdge(Index v1, Index v2)
Constructor taking only the vertex indices.
bool operator==(BoundaryEdge const &e) const
Comparison by vertex indices.
std::array< Index, 2 > vertices() const
BoundaryEdge(Index v1, Index v2, Vector const &t1, Vector const &t2)
Constructor taking vertex indices and tangent vectors.
void displace(Dune::FieldMatrix< ctype, dim, dim > const &du0, Dune::FieldMatrix< ctype, dim, dim > const &du1)
Applies displacement to the tangent vectors.
typename Vector::value_type ctype
Vector tangent(int i) const
The BoundaryInterpolationDisplacement class provides a Kaskade WeakFunctionView on the displacement f...
void applyVolumeDisplacement(VolumeDisplacement const &u)
Provides a -continuous boundary displacement of deformed grids.
BoundaryInterpolationDisplacement(GridView const &gv, GridBoundaryTangents< GridView > const &tangents)
Constructor precomputes for each level-0-cell data that is needed for boundary interpolation.
BoundaryInterpolationDisplacement(BoundaryInterpolationDisplacement &&)=default
Displacement value(Cell< GridView > const &cell, LocalPosition< GridView > const &xiFine) const
Provides the displacement for a point given by cell and local position .
DisplacementDerivative derivative(Cell< GridView > const &cell, LocalPosition< GridView > const &xiFine) const
Provides the global displacement derivative (w.r.t. global variable ) for a point given by cell and l...
A class providing information about domain boundary tangent vectors.
BoundaryTangents(Grid const &grid, GeometricFeatureDetector< Index, ctype, dim > const &features)
Constructor.
std::set< BoundaryEdge< Index, Vector > > boundaryEdges2
The interface for specifying feature edges and feature vertices.
virtual bool isFeatureCurve(Index vidx, Vector const &t1, Vector const &t2) const =0
Decides whether two feature boundary edges of a 3D domain meeting in a joint vertex are part of a smo...
virtual bool isFeatureEdge(Index vidx, Vector const &n1, Vector const &n2, int bsid1, int bsid2) const =0
Decides whether a boundary edge of a 3D domain is part of a smooth boundary patch or not.
virtual bool isFeatureVertex(Index vidx, Vector const &t1, Vector const &t2, int bsid1, int bsid2) const =0
Decides whether two boundary edges emanating from a joint vertex of a 2D domain are part of a smooth ...
virtual Vector vertexNormal(Index vidx, Vector const &n) const
Provides a surface normal at non-feature vertices (where no feature edge passes through).
virtual ~GeometricFeatureDetector()
This file contains various utility functions that augment the basic functionality of Dune.
int count(Cell const &cell, int codim)
Computes the number of subentities of codimension c of a given entity.
Vector< Scalar, dim > cellInterpolation(VertexPositions< Scalar, dim > const &vertices, EdgeDirections< Scalar, dim > const &boundaryEdges, FaceFlags< dim > const &isBoundaryFace, Barycentric< Scalar, dim > b)
Computes a boundary displacement based on blended cubic rational Bezier curves.
void forEachBoundaryFace(GridView const &gridView, Functor functor)
iterates over each boundary face and applies functor to face. Each boundary face is visited exactly o...
typename GridView::template Codim< 0 >::Entity Cell
The type of cells (entities of codimension 0) in the grid view.
std::vector< Dune::FieldVector< typename GridView::ctype, GridView::dimension > > interpolateVertexPositions(GridView const &gv, GridBoundaryTangents< GridView > const &tangents, bool computeDisplacements=false)
Computes a new position for each grid vertex based on boundary interpolation.
Dune::FieldMatrix< CoordType, dim+1, dim > barycentric2Derivative(Dune::FieldVector< CoordType, dim > const &x)
Computes the derivative of the barycentric coordinates of a point in the unit simplex.
std::pair< Cell, Dune::FieldVector< ctype, Cell::dimension > > findCellOnLevel(Cell cell, Dune::FieldVector< ctype, Cell::dimension > xi, int level=std::numeric_limits< int >::max())
Returns a descendant or ancestor cell of the given cell containing the specified local coordinate.
Dune::FieldVector< CoordType, dim+1 > barycentric2(Dune::FieldVector< CoordType, dim > const &x)
Computes barycentric coordinates of a point in the unit simplex.
auto makeCompositeBoundaryInterpolation(VolumeDisplacement const &u, GeometricFeatureDetector< typename VolumeDisplacement::Space::Grid::LevelGridView::IndexSet::IndexType, typename VolumeDisplacement::Space::Grid::ctype, VolumeDisplacement::Space::Grid::dimension > const &features)
Creates a composite boundary interpolation displacement from a volume displacement.
Dune::FieldMatrix< T, n, m > outerProduct(Dune::FieldVector< T, n > const &x, Dune::FieldVector< T, m > const &y)
outer vector product .
Dune::FieldVector< T, n > max(Dune::FieldVector< T, n > x, Dune::FieldVector< T, n > const &y)
Componentwise maximum.
void getChildVertexDisplacements(Cell const &cell, GridView const &gv, std::set< BoundaryEdge< Index, Vector > > const &boundaryEdges, std::vector< Vector > &xs, bool computeDisplacements)
auto getCellEdges(Cell const &cell, GridView const &gv, std::set< BoundaryEdge< Index, Vector > > const &boundaryEdges, std::array< Vector, Cell::dimension+1 > const &vertexPositions)
auto getVertexPositions(Cell const &cell)
auto getIsBoundaryFace(Cell const &cell, GridView const &gv)
std::array< Vector< Scalar, dim >, dim+1 > VertexPositions
Dune::FieldVector< Scalar, dim > Vector
std::array< BoundaryEdge< int, Vector< Scalar, dim > >, dim *(dim+1)/2 > EdgeDirections
Dune::FieldMatrix< Scalar, dim, dim+1 > cellInterpolationDerivative(VertexPositions< Scalar, dim > const &vertices, EdgeDirections< Scalar, dim > const &boundaryEdges, FaceFlags< dim > const &isBoundaryFace, Barycentric< Scalar, dim > b)
std::array< bool, dim+1 > FaceFlags
void adjustEdgeTangents(BoundaryStar< Index, ctype, 3 > &star, std::map< std::array< Index, 2 >, Dune::FieldVector< ctype, 3 > > &orientedEdges, GeometricFeatureDetector< Index, ctype, 3 > const &features)
Detects feature edges and adjusts the edge tangent vectors accordingly.
std::map< typename GridView::IndexSet::IndexType, BoundaryStar< typename GridView::IndexSet::IndexType, typename GridView::ctype, GridView::dimension > > computeBoundaryStars(GridView const &gv)
Computes the boundary stars (i.e. corners around a vertex) for all boundary vertices of the grid view...
void vertexids(int d, int c, int k, int *idx)
Computes the d-c+1 local vertex indices of the vertices incident to the k-th subentity of codimension...
A class storing all the corners (vertex-boundaryface incidences) at a boundary vertex.
std::vector< Corner< Index, ctype, dim > > corners
Corners of the incident faces.
Vector vx
Center vertex position.
Index vidx
Center vertex index.
A class storing algebraic and geometric information about a vertex-boundaryface incidence in simplici...
Simplex::Vector< ctype, dim > Vector
Vector fn
Face normal at the corner.
int bsi
Boundary segment index of the face.
std::array< Index, dim-1 > vidx
Indices of the other vertices of the face.
std::array< Vector, dim-1 > vx
Positions of the other vertices.