KASKADE 7 development version
supports.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) 2016-2018 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#ifndef FEMSUPPORTS_HH
14#define FEMSUPPORTS_HH
15
16#include <algorithm>
17#include <vector>
18
19#include "scalarspace.hh"
20
21namespace Kaskade
22{
23
24 // ----------------------------------------------------------------------------------------------
25 // ----------------------------------------------------------------------------------------------
26
27
41 template <class Space, class Range>
42 std::vector<size_t> algebraicPatch(Space const& space, Range const& cells)
43 {
44 using std::begin; using std::end;
45 std::vector<size_t> dofs;
46
47 // find all ansatz functions with support intersecting the patch (these are too many, of course)
48 for (auto const& cell: cells)
49 {
50 auto const& range = space.mapper().globalIndices(cell);
51 dofs.insert(end(dofs),begin(range),end(range));
52 }
53 assert(dofs.size()>0);
54
55 // remove duplicates
56 std::sort(begin(dofs),end(dofs));
57 dofs.erase(std::unique(begin(dofs),end(dofs)),end(dofs));
58
59 // We still have too many ansatz functions, as there are some whose support extends to cells outside
60 // the given patch. Thus, for each cell in the patch, consider every neighbor that is not contained
61 // in the patch, and remove each ansatz function that lives on that patch.
62 // TODO: consider using std::set_difference, but this needs two sorted ranges (could be done efficiently by using sortedIndices),
63 // and the output range may not overlap the input range as of C++14 (why? appears to be overspecified)
64 auto const& gridview = space.gridView();
65 for (auto const& cell: cells) // step through all cells
66 for (auto fi=gridview.ibegin(cell); fi!=gridview.iend(cell); ++fi) // step through all its faces
67 if (fi->neighbor()) // if there's a neighbor
68 {
69 auto neighbor = fi->outside();
70 if (std::find(begin(cells),end(cells),neighbor)==end(cells)) // and this neigbor is not in the patch
71 for (size_t i: space.mapper().globalIndices(neighbor)) // consider all ansatz functions with
72 { // support on the neighbor...
73 auto j = std::lower_bound(begin(dofs),end(dofs),i); // and if they had been entered into
74 if (j!=end(dofs) && *j==i) // our dofs
75 {
76 dofs.erase(j); // remove them - they have support outside the patch
77 assert(dofs.size()>0); // (erasure retains the sorting of indices)
78 }
79 }
80 }
81
82 return dofs;
83 }
84
85
86
87
88
104 template <class Space, class Range>
105 std::vector<size_t> algebraicPatch(Space const& space, Range const& cells,
106 size_t vertexIdx,
107 std::vector<std::vector<size_t>> const& indicesOnFacets)
108 {
109 using std::begin; using std::end;
110 std::vector<size_t> dofs;
111 int const dim = Space::Grid::dimension;
112
113 // find all ansatz functions with support intersecting the patch (these are too many, of course)
114 for (auto const& cell: cells)
115 {
116 auto const& range = space.mapper().globalIndices(cell);
117 dofs.insert(end(dofs),begin(range),end(range));
118 }
119 assert(dofs.size()>0);
120
121 // remove duplicates
122 std::sort(begin(dofs),end(dofs));
123 dofs.erase(std::unique(begin(dofs),end(dofs)),end(dofs));
124
125 // We still have too many ansatz functions, as there are some whose support extends to cells outside
126 // the given patch. Thus, for each cell in the patch, consider the facet that lies on the patch boundary
127 // and remove each ansatz function that does not vanish on that face.
128 for (auto const& cell: cells) // step through all cells
129 {
130 int localVertexIndex = 0; // determine which cell-local index lies in the middle of the patch
131 for (int ci=0; ci<dim+1; ++ci)
132 if(space.indexSet().subIndex(cell,ci,dim) == vertexIdx)
133 localVertexIndex = ci;
134
135 for (auto const& intersection : intersections(space.gridView(), cell)) // step through all the faces
136 {
137 int indexInInside = intersection.indexInInside();
138 if (!ScalarSpaceDetail::onSimplexFace(dim,dim, localVertexIndex, indexInInside)) // if face lies on boundary of patch
139 {
140 for (size_t i: indicesOnFacets[space.indexSet().subIndex(cell,indexInInside,1)]) // consider all ansatz functions which are nonzero on this face
141 {
142 auto j = std::lower_bound(begin(dofs),end(dofs),i); // and if they have not already been removed from dofs
143 if (j!=end(dofs) && *j==i)
144 {
145 dofs.erase(j); // remove them - they have support outside the patch
146 assert(dofs.size()>0); // (erasure retains the sorting of indices)
147 }
148 }
149 }
150 }
151 }
152
153 return dofs;
154 }
155
156
164 template <class GridView>
165 auto computePatches(GridView const& gridview)
166 {
167 int const dim = GridView::dimension;
168 std::vector<std::vector<Cell<GridView>>> patches(gridview.size(dim)); // initialize with size of number of vertices
169
170 for (auto const& cell: elements(gridview)) // step through the cells
171 for (int i=0; i<cell.subEntities(dim); ++i) // and their vertices
172 patches[gridview.indexSet().subIndex(cell,i,dim)].push_back(cell); // add the cell to the patch of that vertex
173
174 return patches;
175 }
176
177}
178
179#endif
std::vector< size_t > algebraicPatch(Space const &space, Range const &cells)
Computes the global indices of all ansatz functions whose support is a subset of the union of given c...
Definition: supports.hh:42
auto computePatches(GridView const &gridview)
Computes the patches around vertices of the grid view.
Definition: supports.hh:165
bool onSimplexFace(int dim, int codim, int id, int localFaceId)
check if a given subentity E is part of a certain simplex face F
Definition: scalarspace.hh:69