KASKADE 7 development version
boundaryInterpolation.hh
Go to the documentation of this file.
1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2/* */
3/* This file is part of the library KASKADE 7 */
4/* https://www.zib.de/research/projects/kaskade7-finite-element-toolbox */
5/* */
6/* Copyright (C) 2017-2023 Zuse Institute Berlin */
7/* */
8/* KASKADE 7 is distributed under the terms of the ZIB Academic License. */
9/* see $KASKADE/academic.txt */
10/* */
11/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
12
13
14#ifndef BOUNDARYINTERPOLATION_HH
15#define BOUNDARYINTERPOLATION_HH
16
17#include <algorithm>
18#include <cmath>
19#include <limits>
20#include <map>
21#include <optional>
22#include <set>
23#include <vector>
24
25#include <boost/math/constants/constants.hpp>
26
27#include "dune/common/fvector.hh"
28#include "dune/grid/common/boundarysegment.hh"
29#include "dune/grid/uggrid.hh"
30
31#include "fem/barycentric.hh"
32#include "fem/fixdune.hh"
33#include "fem/forEach.hh"
34#include "fem/gridBasics.hh"
36
38#include "utilities/power.hh"
39
40namespace Kaskade
41{
57 template <class Index, class Vector>
59 {
60 public:
61 using ctype = typename Vector::value_type;
62 constexpr static int dim = Vector::dimension;
63
71 BoundaryEdge(Index v1, Index v2, Vector const& t1, Vector const& t2)
72 : vidx{v1,v2}, t{normalize(t1),normalize(t2)}
73 {
74 if (vidx[0] > vidx[1])
75 {
76 std::swap(vidx[0],vidx[1]);
77 std::swap(t[0],t[1]);
78 }
79 }
80
86 BoundaryEdge(Index v1, Index v2)
87 : BoundaryEdge(v1,v2,Vector(1.0),Vector(1.0))
88 {
89 }
90
98 : BoundaryEdge(-1,-1)
99 {
100 }
101
107 bool operator <(BoundaryEdge const& e) const
108 {
109 return vidx < e.vidx;
110 }
111
117 bool operator ==(BoundaryEdge const& e) const
118 {
119 return vidx == e.vidx;
120 }
121
122 std::array<Index,2> vertices() const
123 {
124 return vidx;
125 }
126
127 Index vertex(int i) const
128 {
129 assert(0<=i && i<=1);
130 return vidx[i];
131 }
132
133 Vector tangent(int i) const
134 {
135 assert(0<=i && i<=1);
136 return t[i];
137 }
138
139 std::array<Vector,2> const& tangents() const
140 {
141 return t;
142 }
143
147 bool incident(Index v) const
148 {
149 return v==vidx[0] || v==vidx[1];
150 }
151
160 {
161 t[0] = normalize(t[0]+du0*t[0]);
162 t[1] = normalize(t[1]+du1*t[1]);
163 }
164
165 private:
166 std::array<Index,2> vidx;
167 std::array<Vector,2> t;
168 };
169
170 // -----------------------------------------------------------------------------------------------------
171 // -----------------------------------------------------------------------------------------------------
172
173 namespace Simplex
174 {
175 template <class Scalar, int dim>
177
178 template <class Scalar, int dim>
180
181 template <class Scalar, int dim>
182 using VertexPositions = std::array<Vector<Scalar,dim>,dim+1>;
183
184 template <class Scalar, int dim>
185 using EdgeDirections = std::array<BoundaryEdge<int,Vector<Scalar,dim>>,dim*(dim+1)/2>;
186
187 template <int dim>
188 using FaceFlags = std::array<bool,dim+1>;
189
190
205 template <class Scalar, int dim>
207 EdgeDirections<Scalar,dim> const& boundaryEdges,
208 FaceFlags<dim> const& isBoundaryFace,
210
211 template <class Scalar, int dim>
213 EdgeDirections<Scalar,dim> const& boundaryEdges,
214 FaceFlags<dim> const& isBoundaryFace,
216 }
217
218
219
220
221
226 template <class Index, class ctype, int dim>
227 struct Corner
228 {
230
232 std::array<Index,dim-1> vidx;
233
235 std::array<Vector,dim-1> vx;
236
239
241 int bsi;
242 };
243
244
249 template <class Index, class ctype, int dim>
251 {
253
255 Index vidx;
256
259
261 std::vector<Corner<Index,ctype,dim>> corners;
262 };
263
264
272 template <class GridView>
273 std::map<typename GridView::IndexSet::IndexType,
275 computeBoundaryStars(GridView const& gv)
276 {
277 constexpr int dim = GridView::dimension;
278 using ctype = typename GridView::ctype;
279 using Index = typename GridView::IndexSet::IndexType;
281
282
283 auto const& is = gv.indexSet();
284
285 // Edge tangent and surface normal information is stored for each boundary vertex.
286 std::map<Index,BoundaryStar<Index,ctype,dim>> stars;
287
288 // step through all boundary faces, adding their normals up at the vertices
289 forEachBoundaryFace(gv,[&](auto const& face)
290 {
291 if (face.neighbor()) // on periodic boundary
292 return; // - skip
293
294 Vector const n = face.centerUnitOuterNormal(); // get the face normal
295
296 int vSubIdx[dim]; // the cell-local indices of vertices
297 vertexids(dim,1,face.indexInInside(),vSubIdx); // incident to the face
298 Index vIdx[dim];
299
300 for (int i=0; i<dim; ++i) // for each vertex incident to the face
301 vIdx[i] = is.subIndex(face.inside(),vSubIdx[i],dim); // get the vertex id (later we need them in different order)
302
303 for (int i=0; i<dim; ++i) // for each vertex incident to the face
304 {
305 Corner<Index,ctype,dim> corner; // create the corner (i.e. face-vertex incidence)
306 for (int j=0; j<dim-1; ++j) // with dim-1 (i.e. codim 1) edge tangent vectors
307 {
308 corner.vidx[j] = vIdx[(i+j+1)%dim]; // target vertex of the edge and
309 corner.vx[j] = face.inside().geometry().corner(vSubIdx[(i+j+1)%dim]); // its position
310 }
311 corner.fn = n; // as well as our face normal
312 corner.bsi = face.boundarySegmentIndex();
313
314 auto& star = stars[vIdx[i]]; // append the generated corner to the list of
315 star.vidx = vIdx[i]; // corners at this vertex (storing and overwriting
316 star.vx = face.inside().geometry().corner(vSubIdx[i]); // vertex index and position multiple times with the
317 star.corners.push_back(corner); // same value).
318 }
319 });
320
321 return stars;
322 }
323
324 // ----------------------------------------------------------------------------------------------
325
330 template <class Index, class ctype, int dim>
332 {
333 public:
335
337
354 virtual bool isFeatureVertex(Index vidx, Vector const& t1, Vector const& t2, int bsid1, int bsid2) const = 0;
355
370 virtual bool isFeatureEdge(Index vidx, Vector const& n1, Vector const& n2, int bsid1, int bsid2) const = 0;
371
385 virtual bool isFeatureCurve(Index vidx, Vector const& t1, Vector const& t2) const = 0;
386
396 virtual Vector vertexNormal(Index vidx, Vector const& n) const
397 {
398 return n;
399 }
400 };
401
402
407 template <class Index, class ctype, int dim>
408 class AngleFeatureDetector: public GeometricFeatureDetector<Index,ctype,dim>
409 {
410 public:
412
422 AngleFeatureDetector(ctype featureCurveAngle=1.0, ctype featureEdgeAngle=0.5);
423
425
441 virtual bool isFeatureVertex(Index vidx, Vector const& t1, Vector const& t2, int bsid1, int bsid2) const;
442
457 virtual bool isFeatureEdge(Index vidx, Vector const& n1, Vector const& n2, int bsid1, int bsid2) const;
458
472 virtual bool isFeatureCurve(Index vidx, Vector const& t1, Vector const& t2) const;
473
474 private:
475 ctype featureCurveThreshold;
476 ctype featureEdgeThreshold;
477 };
478
479 template <class GridView>
480 using GridAngleFeatureDetector = AngleFeatureDetector<typename GridView::IndexSet::IndexType,
481 typename GridView::ctype,GridView::dimension>;
482
483
502 template <class Index, class ctype>
503 void adjustEdgeTangents(BoundaryStar<Index,ctype,3>& star, std::map<std::array<Index,2>,Dune::FieldVector<ctype,3>>& orientedEdges,
505 template <class Index, class ctype>
506 void adjustEdgeTangents(BoundaryStar<Index,ctype,2>& star, std::map<std::array<Index,2>,Dune::FieldVector<ctype,2>>& orientedEdges,
508
509 // -----------------------------------------------------------------------------------------------------
510
522 template <int dim, class Index, class ctype = double>
524 {
525 public:
527
549 template <class Grid>
551 {
552 static_assert(dim==Grid::dimension, "dimension mismatch.");
553
555
556 // Edge tangent and surface normal information is stored for each boundary vertex.
557 auto stars = computeBoundaryStars(grid.levelGridView(0));
558
559 // Modify the edge tangents incident to the boundary vertices such that a piecewise G1-continuous surface
560 // is created. If an edge is no feature edge (determined by incident face normal angle), the corner surface
561 // normals coincide afterwards (and the edge tangents are adjusted accordingly). If exactly two feature edges
562 // meet, and their tangent vectors are almost parallel, they are made parallel such as to form a G1-continuous
563 // feature curve. The modified edge tangent vectors are stored in "orientedEdges", and the stars may be
564 // modified (but are no longer needed anyways).
565
566 std::map<std::array<Index,2>,Vector> orientedEdges;
567 for (auto& vertex_star: stars)
568 adjustEdgeTangents(vertex_star.second,orientedEdges,features);
569
570 // Now combine two oriented edges into one non-oriented edge.
571 for (auto const& e: orientedEdges)
572 {
573 // find oriented edge with opposite direction
574 auto const& t2 = orientedEdges[std::array<Index,2>{e.first[1],e.first[0]}];
575 boundaryEdges2.insert(BoundaryEdge<Index,Vector>(e.first[0],e.first[1],e.second,t2));
576 }
577 }
578
579 public:
580 std::set<BoundaryEdge<Index,Vector>> boundaryEdges2;
581 };
582
588 template <class GridView>
590
591
592 //---------------------------------------------------------------------------------------------------
593 //---------------------------------------------------------------------------------------------------
594
595 namespace BoundaryInterpolationDetail
596 {
597
598 // provides an array containing the vertex positions as Dune FieldVectors of the corners of a given cell
599 template <class Cell>
600 auto getVertexPositions(Cell const& cell)
601 {
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); // corner position
606
607 return vertexPositions;
608 }
609
610 // returns optional (only if given cell has any boundary edge) an array of edges of a given cell;
611 // for boundary edges also tangents required for boundary interpolation are provided
612 template <class Cell, class GridView, class Vector, class Index>
613 auto getCellEdges(Cell const& cell, GridView const& gv,
614 std::set<BoundaryEdge<Index,Vector>> const& boundaryEdges,
615 std::array<Vector, Cell::dimension+1> const& vertexPositions)
616 {
617 constexpr int dim = Cell::dimension;
619 using ReturnType = std::optional<CellEdges>;
620
621 // Get global vertex indices.
622 std::array<Index, dim+1> vIdx;
623 for (int i=0; i<=dim; ++i)
624 vIdx[i] = gv.indexSet().subIndex(cell,i,dim);
625
626 std::vector<BoundaryEdge<int,Vector>> cellEdges2; // TODO: compute number of edges a priori and use an std::array
627 bool hasBoundaryEdges = false;
628 for (int i=0; i<dim; ++i)
629 for (int j=i+1; j<=dim; ++j)
630 {
631 BoundaryEdge<Index,Vector> edge(vIdx[i],vIdx[j],Vector(0.0),Vector(0.0));
632 auto be = boundaryEdges.find(edge);
633 if (be!=boundaryEdges.end()) // this one is a boundary edge
634 {
635 std::array<Vector,2> t = be->tangents();
636 if (vIdx[i]>vIdx[j])
637 std::swap(t[0],t[1]);
638
639 cellEdges2.push_back(BoundaryEdge<int,Vector>(i,j,t[0],t[1]));
640 hasBoundaryEdges = true;
641 }
642 else
643 {
644 Vector tx = normalize(vertexPositions[j]-vertexPositions[i]);
645 cellEdges2.push_back(BoundaryEdge<int,Vector>(i,j,tx,-tx));
646 }
647 }
648
649 if (!hasBoundaryEdges) // no boundary edges means the cell deformation
650 return ReturnType(); // is the identity -> do nothing
651
652 CellEdges cellEdges;
653 std::copy(begin(cellEdges2),end(cellEdges2),begin(cellEdges));
654 return ReturnType(cellEdges);
655 }
656
657 // returns an array of bools; an entry indicates whether corresponding face lies on the boundary
658 // (by local index of the opposite vertex, not by local face index)
659 template <class Cell, class GridView>
660 auto getIsBoundaryFace(Cell const& cell, GridView const& gv)
661 {
662 constexpr int dim = Cell::dimension;
663 using ReturnType = std::array<bool,dim+1>;
664
665 ReturnType isBoundaryFace;
666 std::fill(begin(isBoundaryFace),end(isBoundaryFace),false);
667
668 for (auto const& face: intersections(gv,cell))
669 if (face.boundary() && !face.neighbor())
670 {
671 std::array<int,dim> vSubIdx; // get the cell-local indices
672 vertexids(dim,1,face.indexInInside(),&vSubIdx[0]); // of the face corners
673
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;
678
679 for (int i=0; i<dim+1; ++i)
680 isBoundaryFace[i] |= isOppositeBoundaryFace[i];
681 }
682
683 return isBoundaryFace;
684 }
685
686
687 template <class Cell, class GridView, class Vector, class Index>
688 void getChildVertexDisplacements(Cell const& cell, GridView const& gv,
689 std::set<BoundaryEdge<Index,Vector>> const& boundaryEdges,
690 std::vector<Vector>& xs,
691 bool computeDisplacements)
692 {
693 constexpr int dim = Cell::dimension;
694
695 auto const& gv0 = gv.grid().levelGridView(0);
696
697 // find the vertices of the given coarse grid cell
698 std::array<Vector,dim+1> vertexPositions = getVertexPositions(cell);
699
700 // find all boundary Edges of the cell
701 auto cellEdges = getCellEdges(cell, gv0, boundaryEdges, vertexPositions);
702 if(!cellEdges)
703 return;
704
705 // find whether cell faces lie on boundary, faces are indexed by opposite local vertex index
706 std::array<bool,dim+1> isBoundaryFace = getIsBoundaryFace(cell, gv0);
707
708 // Now that we have set up the data describing the deformation of the given level 0 cell,
709 // step through all child leaf cells and evaluate the vertex position displacement.
710 for (auto const& child: descendantElements(cell,std::numeric_limits<int>::max())) // step through all leaf child cells
711 if (child.isLeaf())
712 for (int i=0; i<=dim; ++i) // and their corners
713 {
714 Vector const x = child.geometry().corner(i); // and get the global position
715 Index vidx = gv.indexSet().subIndex(child,i,dim); // and its global index
716
717 if ( (computeDisplacements && xs[vidx].two_norm2()>0) // most vertices will be touched from several cells.
718 || (!computeDisplacements && (xs[vidx]-x).two_norm2()>0) ) // since computing the cell interpolation is expensive,
719 continue; // we check whether this has already been computed
720
721 Vector const xi = cell.geometry().local(x); // as well as the local position in coarse grid cell
722 auto b = barycentric2(xi); // and the barycentric coordinates
723
724 Vector u = Simplex::cellInterpolation(vertexPositions,*cellEdges,isBoundaryFace,b);
725 xs[vidx] = computeDisplacements? u: x+u;
726 }
727 }
728 }
729
747 template <class GridView>
748 std::vector<Dune::FieldVector<typename GridView::ctype,GridView::dimension>>
749 interpolateVertexPositions(GridView const& gv,
750 GridBoundaryTangents<GridView> const& tangents,
751 bool computeDisplacements=false)
752 {
753 using namespace BoundaryInterpolationDetail;
754 constexpr int dim = GridView::dimension;
756
757 // Before computing displacements of the (few) boundary-affected vertices, fill the positions with
758 // the original positions as default. This will be overwritten by displaced vertices.
759 std::vector<Vector> xs(gv.size(dim)); // positions as many as vertices
760 if (!computeDisplacements)
761 for (auto const& v: vertices(gv)) // as default, enter the original positions for all vertices
762 xs[gv.indexSet().index(v)] = v.geometry().center();
763
764 // Find all boundary edges of the coarse grid.
765 auto const& gv0 = gv.grid().levelGridView(0);
766
767 // Step through all coarse grid cells that are affected by the boundary displacement
768 for (auto const& cell: elements(gv0))
769 getChildVertexDisplacements(cell,gv,tangents.boundaryEdges2,xs,computeDisplacements);
770
771 return xs;
772 }
773
774
782 template <class GridView>
784 {
785 static constexpr int dim = GridView::dimensionworld;
786 using ctype = typename GridView::ctype;
787 public:
790
792
798 BoundaryInterpolationDisplacement(GridView const& gv, GridBoundaryTangents<GridView> const& tangents)
799 : gridView(gv)
800 {
801 using namespace BoundaryInterpolationDetail;
802
803 int nCoarseCells = gridView.size(0);
804 vertexPositions.resize(nCoarseCells);
805 cellEdges.resize(nCoarseCells);
806 isBoundaryFace.resize(nCoarseCells);
807
808 for (auto const& cell: elements(gridView))
809 {
810 auto cellIdx = gridView.indexSet().index(cell);
811
812 // find the vertices of the given coarse grid cell
813 vertexPositions[cellIdx] = getVertexPositions(cell);
814
815 // find all boundary Edges of the cell
816 cellEdges[cellIdx] = getCellEdges(cell, gridView, tangents.boundaryEdges2, vertexPositions[cellIdx]);
817
818 // find whether cell faces lie on boundary, faces are indexed by opposite local vertex index
819 isBoundaryFace[cellIdx] = getIsBoundaryFace(cell, gridView);
820 }
821 }
822
841 template <class VolumeDisplacement>
842 void applyVolumeDisplacement(VolumeDisplacement const& u)
843 {
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));
848
849
850 // Evaluate the displacement at the coarse grid vertices and store the
851 // deformed vertex position. Evaluate the displacement derivative as well,
852 // and sum it up for later averaging.
853 for (auto const& cell: elements(gridView))
854 {
855 auto cellIdx = is.index(cell);
856
857 // find the vertices of the given coarse grid cell
858 for (int i=0; i<=dim; ++i)
859 {
860 auto x = cell.geometry().corner(i);
861 auto [leafCell,xi] = findCellOnLevel(cell,cell.geometry().local(x));
862 vertexPositions[cellIdx][i] = x + u.value(leafCell,xi); // displaced vertex position phi(x)
863
864 auto vidx = is.subIndex(cell,i,dim);
865 assert(0<=vidx && vidx<du.size());
866 du[vidx] += u.derivative(leafCell,xi);
867 ++count[vidx];
868
869 cellToGlobalVidx[cellIdx][i] = vidx;
870 }
871 }
872
873 // Compute averages of displacement derivative at coarse grid vertices
874 for (size_t i=0; i<du.size(); ++i)
875 {
876 assert(count[i]>0);
877 du[i] /= count[i];
878 }
879
880 // Turn al the available tangent vectors according to the averaged displacement derivative.
881 // Remember that the vertex numbers in cellEdges are *local to the cell*, not global indices.
882 for (size_t cellIdx=0; cellIdx<cellToGlobalVidx.size(); ++cellIdx)
883 if (cellEdges[cellIdx])
884 for (auto& ed: *cellEdges[cellIdx])
885 {
886 auto v0idx = cellToGlobalVidx[cellIdx][ed.vertex(0)];
887 auto v1idx = cellToGlobalVidx[cellIdx][ed.vertex(1)];
888 ed.displace(du[v0idx],du[v1idx]);
889 }
890 }
891
892
899 {
900 // Find coarse grid cell and local position in coarse cell. There are two ways to do this:
901 // (i) going down step by step, looking up the position in the father cells on the way
902 // (ii) looking up the global position in the coarse ancestor cell.
903 // We take the first route here, because (in deformed grids) the global position need not
904 // be contained in the coarse ancestor cell.
905 Cell<GridView> coarseCell = cell;
906 auto xi = xiFine;
907 while (coarseCell.hasFather())
908 {
909 xi = coarseCell.geometryInFather().global(xi);
910 coarseCell = coarseCell.father();
911 }
912 // auto const xi = coarseCell.geometry().local(cell.geometry().global(xiFine)); // dangerous if cell is from deformed grid, i.e. global Position can lie outside of coarse Cell
913
914 // We may have a volume displacement applied (implicitly assumed to be given on the vertices only
915 // and piecewise linear). Thus, this has to be computed first, before we can add the boundary interpolation
916 // correction.
917 std::size_t coarseCellIdx = gridView.indexSet().index(coarseCell);
918 auto b = barycentric2(xi);
919 Displacement u(0.0);
920 for (int i=0; i<=dim; ++i)
921 u += b[i] * (vertexPositions[coarseCellIdx][i]-coarseCell.geometry().corner(i));
922 if (cellEdges[coarseCellIdx])
923 u += Simplex::cellInterpolation(vertexPositions[coarseCellIdx],*cellEdges[coarseCellIdx],
924 isBoundaryFace[coarseCellIdx],b);
925 return u;
926 }
927
935 {
936 Cell<GridView> coarseCell = cell;
937 auto xi = xiFine;
938 while (coarseCell.hasFather())
939 {
940 xi = coarseCell.geometryInFather().global(xi);
941 coarseCell = coarseCell.father();
942 }
943
944 // Now we have the *local* position xi. But we need to compute the derivative w.r.t. the *global*
945 // position x.
946 auto dxi_dx = transpose(coarseCell.geometry().jacobianInverseTransposed(xi));
947
948 std::size_t coarseCellIdx = gridView.indexSet().index(coarseCell);
949 auto b = barycentric2(xi);
950 auto db_dx = barycentric2Derivative(xi) * dxi_dx;
951
952 Displacement u(0.0);
953 DisplacementDerivative du_dx(0.0);
954
955 for (int i=0; i<=dim; ++i)
956 {
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]);
959 }
960
961 if (cellEdges[coarseCellIdx]) // in case of constant (and, incidentally, zero) displacement, the derivative
962 du_dx += Simplex::cellInterpolationDerivative(vertexPositions[coarseCellIdx],*cellEdges[coarseCellIdx],
963 isBoundaryFace[coarseCellIdx],b) * db_dx;
964
965 return du_dx;
966 }
967
968 private:
969 GridView const gridView;
970 std::vector<Simplex::VertexPositions<ctype,dim>> vertexPositions;
971 std::vector<std::optional<Simplex::EdgeDirections<ctype,dim>>> cellEdges; // TODO: optional wastes memory. use unique_ptr instead?
972 std::vector<Simplex::FaceFlags<dim>> isBoundaryFace;
973 };
974
975 //---------------------------------------------------------------------------------------------------
976 //---------------------------------------------------------------------------------------------------
977
983 template <class VolumeDisplacement>
984 auto makeCompositeBoundaryInterpolation(VolumeDisplacement const& u,
985 GeometricFeatureDetector<typename VolumeDisplacement::Space::Grid::LevelGridView::IndexSet::IndexType,
986 typename VolumeDisplacement::Space::Grid::ctype,
987 VolumeDisplacement::Space::Grid::dimension> const& features)
988 {
989 using Grid = typename VolumeDisplacement::Space::Grid;
990 using GridView = typename Grid::LevelGridView;
991
992 GridBoundaryTangents<GridView> boundaryTangents(u.space().grid(),features);
993 BoundaryInterpolationDisplacement<GridView> bid(u.space().grid().levelGridView(0),boundaryTangents);
995 return bid;
996 }
997
998 //---------------------------------------------------------------------------------------------------
999 //---------------------------------------------------------------------------------------------------
1000
1001 template <class GridView>
1003 {
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;
1009
1010 public:
1012
1013 template <class VolumeDisplacement>
1014 BoundaryDisplacementByInterpolation(VolumeDisplacement const& displacement)
1015 {
1016 *this = displacement;
1017 features = std::make_unique<AngleFeatureDetector<Index,ctype,dim>>(1.0,0.5);
1018 }
1019
1020 template <class VolumeDisplacement>
1021 BoundaryDisplacementByInterpolation(VolumeDisplacement const& displacement, std::unique_ptr<Features> features_)
1022 : features(std::move(features_))
1023 {
1024 *this = displacement;
1025 }
1026
1027
1028
1029 template <class VolumeDisplacement>
1030 BoundaryDisplacementByInterpolation& operator=(VolumeDisplacement const& displacement)
1031 {
1032 u = std::make_unique<BoundaryInterpolationDisplacement<GridView>>(makeCompositeBoundaryInterpolation(displacement,*features));
1033 return *this;
1034 }
1035
1037
1039 {
1040 return u->value(cell,position);
1041 }
1042
1044 {
1045 return u->derivative(cell,position);
1046 }
1047
1048 private:
1049 std::unique_ptr<BoundaryInterpolationDisplacement<GridView>> u;
1050 std::unique_ptr<Features> features;
1051 };
1052
1053}
1054
1055#endif
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 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
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.
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.
static constexpr int dim
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).
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.
Definition: fixdune.hh:716
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...
Definition: forEach.hh:88
typename GridView::template Codim< 0 >::Entity Cell
The type of cells (entities of codimension 0) in the grid view.
Definition: gridBasics.hh:35
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.
Definition: barycentric.hh:122
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.
Definition: barycentric.hh:90
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 .
Definition: fixdune.hh:164
Dune::FieldVector< T, n > max(Dune::FieldVector< T, n > x, Dune::FieldVector< T, n > const &y)
Componentwise maximum.
Definition: fixdune.hh:110
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 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.
T transpose(T x)
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.