8 #include <dune/functions/functionspacebases/subentitydofs.hh> 10 #include <amdis/LinearAlgebra.hpp> 11 #include <amdis/Output.hpp> 12 #include <amdis/functions/FunctionFromCallable.hpp> 13 #include <amdis/typetree/Traversal.hpp> 17 template <
class Mat,
class Sol,
class Rhs,
class Basis,
class TP>
21 if (!
bool(hasConnectedIntersections_)) {
22 hasConnectedIntersections_ =
true;
23 const auto& gridView = basis_.gridView().grid().levelGridView(0);
24 for (
auto const& element : elements(gridView)) {
25 for (
const auto& intersection : intersections(gridView, element)) {
26 if (!boundarySubset_(intersection))
29 if (!intersection.neighbor()) {
30 hasConnectedIntersections_ =
false;
37 if (*hasConnectedIntersections_)
44 template <
class Mat,
class Sol,
class Rhs,
class Basis,
class TP>
49 static const auto tol = sqrt(std::numeric_limits<typename Domain::field_type>::epsilon());
50 periodicNodes_.assign(basis_.dimension(),
false);
52 auto localView = basis_.localView();
53 auto seDOFs = Dune::Functions::subEntityDOFs(basis_);
54 const auto& gridView = basis_.gridView();
55 for (
auto const& element : elements(gridView)) {
56 if (!element.hasBoundaryIntersections())
59 localView.bind(element);
60 for (
const auto& intersection : intersections(gridView, element)) {
61 if (!boundarySubset_(intersection))
65 "Neighbors of periodic intersection not assigned. Use a periodic Grid instead!");
68 localView.bind(intersection.inside());
69 seDOFs.bind(localView, intersection.indexInInside(), 1);
70 std::vector<std::size_t> insideDOFs(seDOFs.begin(), seDOFs.end());
71 std::vector<MultiIndex> insideGlobalDOFs(insideDOFs.size());
72 std::transform(insideDOFs.begin(), insideDOFs.end(), insideGlobalDOFs.begin(),
73 [&](std::size_t localIndex) {
return localView.index(localIndex); });
74 auto insideCoords = coords(localView.tree(), insideDOFs);
77 localView.bind(intersection.outside());
78 seDOFs.bind(localView, intersection.indexInOutside(), 1);
79 std::vector<std::size_t> outsideDOFs(seDOFs.begin(), seDOFs.end());
80 auto outsideCoords = coords(localView.tree(), outsideDOFs);
83 assert(insideDOFs.size() == outsideDOFs.size());
84 for (std::size_t i = 0; i < insideCoords.size(); ++i) {
85 auto x = faceTrafo_.evaluate(insideCoords[i]);
86 for (std::size_t j = 0; j < outsideCoords.size(); ++j) {
87 auto const& y = outsideCoords[j];
88 if (distance(x,y) < tol) {
89 periodicNodes_[insideGlobalDOFs[i]] =
true;
90 associations_[insideGlobalDOFs[i]] = localView.index(outsideDOFs[j]);
103 using ctype =
typename D::field_type;
106 CompareTol(ctype tol)
110 bool operator()(D
const& lhs, D
const& rhs)
const 113 for (
int i = 0; i < D::dimension; i++) {
114 if (abs(lhs[i] - rhs[i]) < tol_)
116 return lhs[i] < rhs[i];
127 template <
class Mat,
class Sol,
class Rhs,
class Basis,
class TP>
132 static const auto tol = sqrt(std::numeric_limits<typename Domain::field_type>::epsilon());
133 periodicNodes_.assign(basis_.dimension(),
false);
136 using EntitySeed =
typename SubspaceBasis::GridView::Grid::template Codim<0>::EntitySeed;
137 using CoordAssoc = std::map<Domain, std::vector<std::pair<EntitySeed,int>>, Impl::CompareTol<Domain>>;
138 CoordAssoc coordAssoc(Impl::CompareTol<Domain>{tol});
141 const auto& gridView = basis_.gridView();
142 for (
auto const& element : elements(gridView)) {
143 for (
const auto& intersection : intersections(gridView, element)) {
144 if (!boundarySubset_(intersection))
147 auto x = intersection.geometry().center();
148 auto seed = intersection.inside().seed();
149 coordAssoc[x].push_back({seed,intersection.indexInInside()});
150 coordAssoc[faceTrafo_.evaluate(x)].push_back({seed,intersection.indexInInside()});
154 auto localView = basis_.localView();
155 auto seDOFs = Dune::Functions::subEntityDOFs(basis_);
156 for (
auto const& assoc : coordAssoc) {
157 auto const& seeds = assoc.second;
158 if (seeds.size() != 2)
162 auto el1 = gridView.grid().entity(seeds[0].first);
164 seDOFs.bind(localView, seeds[0].second, 1);
165 std::vector<std::size_t> insideDOFs(seDOFs.begin(), seDOFs.end());
166 std::vector<MultiIndex> insideGlobalDOFs(insideDOFs.size());
167 std::transform(insideDOFs.begin(), insideDOFs.end(), insideGlobalDOFs.begin(),
168 [&](std::size_t localIndex) {
return localView.index(localIndex); });
169 auto insideCoords = coords(localView.tree(), insideDOFs);
172 auto el2 = gridView.grid().entity(seeds[1].first);
174 seDOFs.bind(localView, seeds[1].second, 1);
175 std::vector<std::size_t> outsideDOFs(seDOFs.begin(), seDOFs.end());
176 auto outsideCoords = coords(localView.tree(), outsideDOFs);
179 assert(insideDOFs.size() == outsideDOFs.size());
180 for (std::size_t i = 0; i < insideCoords.size(); ++i) {
181 auto x = faceTrafo_.evaluate(insideCoords[i]);
182 for (std::size_t j = 0; j < outsideCoords.size(); ++j) {
183 auto const& y = outsideCoords[j];
184 if (distance(x,y) < tol) {
185 periodicNodes_[insideGlobalDOFs[i]] =
true;
186 associations_[insideGlobalDOFs[i]] = localView.index(outsideDOFs[j]);
194 template <
class Mat,
class Sol,
class Rhs,
class Basis,
class TP>
195 template <
class Node>
197 coords(Node
const& tree, std::vector<std::size_t>
const& localIndices)
const 199 std::vector<Domain> dofCoords(localIndices.size());
202 std::size_t size = node.finiteElement().size();
203 auto geometry = node.element().geometry();
205 auto const& localInterpol = node.finiteElement().localInterpolation();
206 using FiniteElement = TYPEOF(node.finiteElement());
207 using DomainType =
typename FiniteElement::Traits::LocalBasisType::Traits::DomainType;
208 using RangeType =
typename FiniteElement::Traits::LocalBasisType::Traits::RangeType;
210 std::array<std::vector<typename RangeType::field_type>, Domain::dimension> coeffs;
211 for (
int d = 0; d < Domain::dimension; ++d) {
212 auto evalCoord = [&](DomainType
const& local) -> RangeType {
return geometry.global(local)[d]; };
213 auto evalCoordFct = functionFromCallable<RangeType(DomainType)>(evalCoord);
214 localInterpol.interpolate(evalCoordFct, coeffs[d]);
217 for (std::size_t j = 0; j < localIndices.size(); ++j) {
219 for (std::size_t i = 0; i < size; ++i) {
220 if (node.localIndex(i) == localIndices[j]) {
221 for (
int d = 0; d < Domain::dimension; ++d)
226 dofCoords[j] = std::move(x);
234 template <
class Mat,
class Sol,
class Rhs,
class Basis,
class TP>
236 apply(Mat& matrix, Sol& solution, Rhs& rhs)
238 periodicBC(matrix, solution, rhs, periodicNodes_, associations_);
void for_each_leaf_node(Tree &&tree, LeafFunc &&leafFunc)
Traverse tree and visit each leaf node.
Definition: Traversal.hpp:127
void apply(Mat &matrix, Sol &solution, Rhs &rhs) override
Move matrix rows (and columns) of dependant DOFs to the corresponding master DOFs.
Definition: PeriodicBC.inc.hpp:236
Contains all classes needed for solving linear and non linear equation systems.
Definition: AdaptBase.hpp:6
Implements a periodic boundary condition.
Definition: PeriodicBC.hpp:61
void init() override
Compute the pairs of associated boundary DOFs.
Definition: PeriodicBC.inc.hpp:19
void test_exit(bool condition, std::string const &str, Args &&... args)
test for condition and in case of failure print message and exit
Definition: Output.hpp:163