KASKADE 7 development version
boundarynormalcollector.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) 2002-2012 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 BOUNDARY_NORMAL_COLLECTOR_HH
14#define BOUNDARY_NORMAL_COLLECTOR_HH
15
16#include <algorithm>
18
19namespace Kaskade
20{
21
22 namespace BoundaryNormalCollectorDetail
23 {
24
25 template <class GridView, class NormalCollection>
26 void checkForBoundaryVertices(GridView const& gridView, NormalCollection& collection)
27 {
28 std::for_each(gridView.template begin<0>(), gridView.template end<0>(), [&](typename GridView::template Codim<0>::Iterator::Entity const& entity)
29 {
30 Dune::GeometryType const gt(entity.type().id(), GridView::dimension);
31 std::for_each(gridView.ibegin(entity), gridView.iend(entity), [&](typename GridView::IntersectionIterator::Intersection const& face)
32 {
33 if(face.boundary()) for(int vertexId=0; vertexId<face.geometry().corners(); ++vertexId) collection[gridView.indexSet().subIndex(entity, Dune::GenericReferenceElements<typename GridView::ctype,GridView::dimension>::general(gt).subEntity(face.indexInInside(),1,vertexId,GridView::dimension), GridView::dimension)].onBoundary = true;
34 });
35 });
36 }
37
38 template <class GridView, class NormalCollection>
39 void checkForBoundaryEdges(GridView const& gridView, NormalCollection& collection)
40 {
41 std::for_each(gridView.template begin<0>(), gridView.template end<0>(), [&](typename GridView::template Codim<0>::Iterator::Entity const& entity)
42 {
43 Dune::GeometryType const gt(entity.type().id(), GridView::dimension);
44 std::for_each(gridView.ibegin(entity), gridView.iend(entity), [&](typename GridView::IntersectionIterator::Intersection const& face)
45 {
46 if(face.boundary()) for(int edgeId = 0; edgeId < 3; ++edgeId)
47 collection[gridView.indexSet().subIndex(entity, Dune::GenericReferenceElements<typename GridView::ctype,GridView::dimension>::general(gt).subEntity(face.indexInInside(),1,edgeId,GridView::dimension-1), GridView::dimension-1)].onBoundary = true;
48 });
49 });
50 }
51
52 // helper function 2D
53 template <class GridView, class NormalContainer>
54 inline void outerBoundaryCheckImpl(GridView const& gridView, NormalContainer& container, std::integral_constant<int,2>)
55 {
56 checkForBoundaryVertices(gridView, container.vertexNormals);
57 }
58
59 // helper function 3D
60 template <class GridView, class NormalContainer>
61 inline void outerBoundaryCheckImpl(GridView const& gridView, NormalContainer& container, std::integral_constant<int,3>)
62 {
63 checkForBoundaryVertices(gridView, container.vertexNormals);
64 checkForBoundaryEdges(gridView, container.edgeNormals);
65 }
66
67 // emulate template specification via overloading and std::integral_constant
68 template <class GridView, class NormalContainer>
69 inline void outerBoundaryCheck(GridView const& gridView, NormalContainer& container)
70 {
71 outerBoundaryCheckImpl(gridView, container, std::integral_constant<int,GridView::dimension>());
72 }
73
74 // store normals and associate them with vertices
75 template <class GridView, class Entity, class Face, class NormalCollection, class Scalar, class MergedPolicy>
76 void getEntitiesVertexNormals(GridView const& gridView, Entity const& entity, Face const& face, NormalCollection &collection, Scalar tissue, Dune::GeometryType const& gt, MergedPolicy const& policy)
77 {
78 const int dim = GridView::dimension;
79 tissue = round(tissue);
80 int local_fidx = face.indexInInside();
81 for(int i=0; i<face.geometry().corners(); ++i){
82 // get local index in cell from local index in face
83 int local_vidx = Dune::GenericReferenceElements<Scalar,dim>::general(gt).subEntity(local_fidx,1,i,dim);
84 // get global index from local index in cell
85 int vidx = gridView.indexSet().subIndex(entity, local_vidx, dim);
86
87 Scalar tissueNeighbour = -1;
88
89 // boundary faces -> outer boundary policy
90 if( face.boundary() ){
91 if( policy.ignoreOuterBoundary(face) ){
92 collection[vidx].isRelevant = false;
93 continue;
94 }
95 } // if not on boundary:
96 else{
97 // face not on boundary, but contains boundary vertex
98 // ignore contribution from the inside of the domain
99 if(collection[vidx].onBoundary) continue;
100
101 // get tissue of neighbouring cell sharing the intersection
102 tissueNeighbour = round( policy.phaseId(*face.outside()) );
103
104 if( policy.ignoreInnerBoundary(tissue, tissueNeighbour) ){
105 collection[vidx].isRelevant = false;
106 continue;
107 }
108 }
109
110 // store normal with corresponding phase index and mark the boundary vertex
111 // on intersections the smaller phase index determines the orientation of the normal
112 // i.e. the smaller phase index is always the associated to the inside phase
113 if(tissue < tissueNeighbour-1.e-9){
114 collection[vidx].normals.push_back(face.centerUnitOuterNormal());
115 collection[vidx].weights.push_back(1.0/face.geometry().volume());
116 collection[vidx].phaseIds.push_back(tissue);
117 collection[vidx].ids.push_back(gridView.indexSet().index(entity));
118 }
119 // store the inverted normal of the "outside" phase
120 if(tissue > tissueNeighbour+1.e-9){
121 collection[vidx].normals.push_back(-1.*face.centerUnitOuterNormal());
122 collection[vidx].weights.push_back(1.0/face.geometry().volume());
123 collection[vidx].phaseIds.push_back(tissue);
124 collection[vidx].ids.push_back(gridView.indexSet().index(entity));
125 }
126 }
127 }
128
130 template <class GridView, class Entity, class Face, class NormalCollection, class Scalar, class MergedPolicy>
131 static void getEntitiesEdgeNormals(GridView const& gridView, Entity const& entity, Face const& face, NormalCollection& collection,
132 Scalar tissue, Dune::GeometryType const& gt, MergedPolicy const& policy)
133 {
134 constexpr int dim = GridView::dimension;
135 tissue = round(tissue);
136
137 // index of face in cell
138 int local_fidx = face.indexInInside();
139 // iterate over edges
140 for(int i=0; i<3; ++i){
141 // get local edge id
142 int local_eidx = Dune::GenericReferenceElements<Scalar,dim>::general(gt).subEntity(local_fidx,1,i,dim-1);
143 // get global edge id
144 int eidx = gridView.indexSet().subIndex(entity, local_eidx, dim-1);
145
146 Scalar tissueNeighbour = -1;
147 // get tissue of neighbouring cell sharing the intersection
148 if(!face.boundary()){
149 tissueNeighbour = round(policy.phaseId(*face.outside()));
150 if(policy.ignoreInnerBoundary(tissue, tissueNeighbour)){
151 collection[eidx].isRelevant = false;
152 return;
153 }
154 }
155 else
156 tissueNeighbour = tissue + 1;
157
158 // store normal with corresponding phase index and mark the boundary vertex
159 // on intersections the smaller phase index determines the orientation of the normal
160 // i.e. the smaller phase index is always the associated to the inside phase
161 if(tissue < tissueNeighbour-1.e-9){
162 collection[eidx].normals.push_back(face.centerUnitOuterNormal());
163 collection[eidx].weights.push_back(1.0);
164 collection[eidx].isRelevant = (!policy.ignoreOuterBoundary(face)) && collection[eidx].isRelevant;
165 collection[eidx].phaseIds.push_back(tissue);
166 collection[eidx].ids.push_back(gridView.indexSet().index(entity));
167 }
168 // store the inverted normal of the "outside" phase
169 if(tissue > tissueNeighbour+1.e-9){
170 collection[eidx].normals.push_back(-1.*face.centerUnitOuterNormal());
171 collection[eidx].weights.push_back(1.0);
172 collection[eidx].phaseIds.push_back(tissue);
173 collection[eidx].ids.push_back(gridView.indexSet().index(entity));
174 }
175 }
176 }
177
178 // helper function 2D
179 template <class GridView, class Entity, class Face, class NormalContainer, class Scalar, class Policy>
180 inline void collectEntityNormals(GridView const& gridView, Entity const& entity, Face const& face, NormalContainer& container, Scalar tissue,
181 Dune::GeometryType const gt, Policy const& policy, std::integral_constant<int,2>)
182 {
183 getEntitiesVertexNormals(gridView, entity, face, container.vertexNormals, tissue, gt, policy);
184 }
185
186 // helper function 3D
187 template <class GridView, class Entity, class Face, class NormalContainer, class Scalar, class Policy>
188 inline void collectEntityNormals(GridView const& gridView, Entity const& entity, Face const& face, NormalContainer& container, Scalar tissue,
189 Dune::GeometryType const gt, Policy const& policy, std::integral_constant<int,3>)
190 {
191 getEntitiesVertexNormals(gridView, entity, face, container.vertexNormals, tissue, gt, policy);
192 getEntitiesEdgeNormals(gridView, entity, face, container.edgeNormals, tissue, gt, policy);
193 }
194
195
196 // collect normals
197 template <class GridView, class NormalContainer, class MergedPolicy>
198 void getEntityNormals(GridView const& gridView, NormalContainer &container, MergedPolicy const& policy)
199 {
200 typedef typename GridView::template Codim<0>::Iterator CellIterator;
201 typedef typename CellIterator::Entity Entity;
202 typedef typename GridView::IntersectionIterator FaceIterator;
203 typedef typename FaceIterator::Intersection Face;
204 typedef typename NormalContainer::EntryType::Scalar Scalar;
205 //iterate over cells
206 std::for_each(gridView.template begin<0>(), gridView.template end<0>(),[&](Entity const& entity)
207 {
208 Scalar tissue = policy.phaseId(entity);
209 Dune::GeometryType const gt(entity.type().id(), GridView::dimension);
210 // iterate over faces
211 FaceIterator fi = gridView.ibegin(entity),
212 fend = gridView.iend(entity);
213 for(;fi!=fend;++fi) collectEntityNormals(gridView, entity, *fi, container, tissue, gt, policy, std::integral_constant<int,GridView::dimension>());
214// std::for_each(gridView.ibegin(entity), gridView.iend(entity),[&](Face const& face)
215// {
216// // emulate template specification via overloading and std::integral_constant
217// collectEntityNormals(gridView, entity, face, container, tissue, gt, policy, std::integral_constant<int,GridView::dimension>());
218// });
219 });
220 }
221
222 template <class NormalContainer>
223 inline void computeMeanNormalsImpl(NormalContainer& container, std::integral_constant<int,2>)
224 {
225 for(auto& collection : container.vertexNormals) InterpolationTools::computeMeanNormal<true>(collection);
226 }
227
228 template <class NormalContainer>
229 inline void computeMeanNormalsImpl(NormalContainer& container, std::integral_constant<int,3>)
230 {
231 for(auto& collection : container.vertexNormals) InterpolationTools::computeMeanNormal<true>(collection);
232 for(auto& collection : container.edgeNormals) InterpolationTools::computeMeanNormal<false>(collection);
233 }
234 // mean normals
235 template <class NormalContainer>
236 inline void computeMeanNormals(NormalContainer& container)
237 {
238 computeMeanNormalsImpl(container, std::integral_constant<int,NormalContainer::EntryType::dim>());
239 }
240 }
241
243
250 template<class GridView, class OuterBoundaryPolicy = Policy::ConsiderOuterBoundary, class InnerBoundaryPolicy = Policy::IgnoreInnerBoundary,
251 class Phase = typename GridView::ctype, template <class> class PhasePolicy = Policy::NoPhaseInfo>
253 {
254 public:
255 static int const dim = GridView::dimension;
256 typedef typename GridView::ctype Scalar;
258
260 BoundaryNormalCollector(GridView const& gridView_, OuterBoundaryPolicy const& outerBoundaryPolicy = OuterBoundaryPolicy(),
261 InnerBoundaryPolicy const& innerBoundaryPolicy = InnerBoundaryPolicy())
262 : gridView(gridView_), mergedPolicy(outerBoundaryPolicy,innerBoundaryPolicy, Policy::NoPhaseInfo<Scalar>())
263 {}
264
266
269 BoundaryNormalCollector(GridView const& gridView_, Phase const& phase, OuterBoundaryPolicy const& outerBoundaryPolicy = OuterBoundaryPolicy(),
270 InnerBoundaryPolicy const& innerBoundaryPolicy = InnerBoundaryPolicy())
271 : gridView(gridView_), mergedPolicy(outerBoundaryPolicy,innerBoundaryPolicy,PhasePolicy<Phase>(phase))
272 {}
273
276 {
277 NormalContainer container(gridView);
278 // identify codim-2- or codim-3-entities lying on the boundary without
279 // being part of a codim-1-entity on the boundary
281 BoundaryNormalCollectorDetail::getEntityNormals(gridView, container, mergedPolicy);
282 return container;
283 }
284
287 {
288 NormalContainer container(gridView);
289 // identify codim-2- or codim-3-entities lying on the boundary without
290 // being part of a codim-1-entity on the boundary
292 BoundaryNormalCollectorDetail::getEntityNormals(gridView, container, mergedPolicy);
294 return container;
295 }
296
297 // no default and copy constructor, no copy assignment
301
303
304 private:
305 GridView gridView;
307 };
308}
309#endif /* BOUNDARY_NORMAL_COLLECTOR_HH */
Collects face normals associated to corners (2D,3D) and edges(3D only).
NormalContainer meanNormals() const
Get average of normals incident to each vertex.
BoundaryNormalCollector(GridView const &gridView_, Phase const &phase, OuterBoundaryPolicy const &outerBoundaryPolicy=OuterBoundaryPolicy(), InnerBoundaryPolicy const &innerBoundaryPolicy=InnerBoundaryPolicy())
Constructor for the case that phase ids are provided.
NormalContainer normals() const
Get normals of all faces incident to each vertex.
InterpolationTools::NormalContainer< Scalar, dim > NormalContainer
BoundaryNormalCollector(BoundaryNormalCollector const &)=delete
BoundaryNormalCollector(GridView const &gridView_, OuterBoundaryPolicy const &outerBoundaryPolicy=OuterBoundaryPolicy(), InnerBoundaryPolicy const &innerBoundaryPolicy=InnerBoundaryPolicy())
Constructor for the case that no phase ids are provided.
BoundaryNormalCollector & operator=(BoundaryNormalCollector const &)=delete
typename GridView::Intersection Face
The type of faces in the grid view.
Definition: gridBasics.hh:42
void computeMeanNormals(NormalContainer &container)
void outerBoundaryCheckImpl(GridView const &gridView, NormalContainer &container, std::integral_constant< int, 3 >)
void checkForBoundaryVertices(GridView const &gridView, NormalCollection &collection)
void collectEntityNormals(GridView const &gridView, Entity const &entity, Face const &face, NormalContainer &container, Scalar tissue, Dune::GeometryType const gt, Policy const &policy, std::integral_constant< int, 3 >)
void getEntitiesVertexNormals(GridView const &gridView, Entity const &entity, Face const &face, NormalCollection &collection, Scalar tissue, Dune::GeometryType const &gt, MergedPolicy const &policy)
void outerBoundaryCheck(GridView const &gridView, NormalContainer &container)
void getEntityNormals(GridView const &gridView, NormalContainer &container, MergedPolicy const &policy)
void checkForBoundaryEdges(GridView const &gridView, NormalCollection &collection)
void computeMeanNormalsImpl(NormalContainer &container, std::integral_constant< int, 3 >)
Simple data container holding only vertex/edge normals and a threshold value for corner detection.
Definition: tools.hh:283