KASKADE 7 development version
gridtreepolicy.hh
Go to the documentation of this file.
1/*
2 * gridtreepolicy.h
3 *
4 * Created on: 17.12.2011
5 * Author: Lars
6 */
7
8#ifndef GRIDTREEPOLICY_HH_
9#define GRIDTREEPOLICY_HH_
10
11#include <cmath>
12#include <utility>
13#include <vector>
14#include <dune/common/fvector.hh>
17
18namespace {
19 using namespace GeometricObject;
20
22 template <class Scalar, int dim>
23 struct SearchDetail{
24 SearchDetail(Scalar const f, Scalar const l, Scalar const s, Direction const dir) : first(f), last(l), split(s), delta(last-split), direction(dir)
25 {}
26
27 template <class BoundingBoxType>
28 SearchDetail(BoundingBoxType const& boundingBox, Direction dir) :
29 first(boundingBox.coord[dir].first), last(boundingBox.coord[dir].second),
30 split(0.5*(boundingBox.coord[dir].first+boundingBox.coord[dir].second)), delta(split-first), direction(dir)
31 {}
32
33 Scalar const first, last;
34 Scalar split, delta;
35 Direction const direction;
36 };
37
42 template <class Scalar, int dim, class BoundingBoxType>
43 BoundingBoxType createBoundingBox(BoundingBoxType const& boundingBox, SearchDetail<Scalar,dim> const& searchDetail, bool const lower)
44 {
45 BoundingBoxType newBoundingBox;
46 if(lower) newBoundingBox.coord[searchDetail.direction].first = boundingBox.coord[searchDetail.direction].first,
47 newBoundingBox.coord[searchDetail.direction].second = searchDetail.split;
48 else newBoundingBox.coord[searchDetail.direction].first = searchDetail.split,
49 newBoundingBox.coord[searchDetail.direction].second = boundingBox.coord[searchDetail.direction].second;
50
51 size_t dir = (1+searchDetail.direction)%dim;
52 newBoundingBox.coord[dir].first = boundingBox.coord[dir].first, newBoundingBox.coord[dir].second = boundingBox.coord[dir].second;
53 dir = (2+searchDetail.direction)%dim;
54 newBoundingBox.coord[dir].first = boundingBox.coord[dir].first, newBoundingBox.coord[dir].second = boundingBox.coord[dir].second;
55 return newBoundingBox;
56 }
57
59 template <class Cell, class Partition>
60 void addCell(Cell const& cell, SearchDetail<typename Cell::Geometry::ctype, Cell::dimension> const searchDetail, Partition &partition)
61 {
62 bool left = false, right = false;
63
64 for(int cornerId=0; cornerId<cell.geometry().corners(); ++cornerId)
65 (cell.geometry().corner(cornerId)[searchDetail.direction] < (searchDetail.split)) ? left = true : right = true;
66
67 if(left) partition.first.push_back(&cell);
68 if(right) partition.second.push_back(&cell);
69 }
70
71 template <class Partition>
72 void swapPartition(Partition &p1, Partition &p2)
73 {
74 std::swap(p1.first,p2.first);
75 std::swap(p1.second,p2.second);
76 }
77
78 template <class Partition>
79 void clear(Partition &partition)
80 {
81 partition.first.clear();
82 partition.second.clear();
83 }
84
86 template <class Partition>
87 size_t getDifference(Partition const& partition)
88 {
89 return (size_t) std::abs((int)partition.first.size()-(int)partition.second.size());
90 }
91
93 template <class Partition, class Scalar>
94 bool checkPartition(Partition const& partition, Scalar const difference)
95 {
96 return (getDifference(partition) < difference);
97 }
98
99 Direction changeDirection(Direction dir)
100 {
101 if(dir==X) return Y;
102 if(dir==Y) return Z;
103 return X;
104 }
105}
106
108template <class Cell, class BoundingBox>
110 static int const dim = Cell::dimension;
111 typedef typename Cell::Geometry::ctype Scalar;
113 typedef std::pair<std::vector<GPC const*>, std::vector<GPC const*> > Partition;
114
115 // create tree node's children
116 template <class TreeNode>
117 void createChildren(BoundingBox const& boundingBox, std::vector<GPC const*> const& cells_, Direction dir, std::pair<TreeNode*, TreeNode*> &children, Scalar const reltol, Scalar const height, Scalar const maxHeight)
118 {
119
120 // split cell vector
121 Scalar const MINIMAL_DELTA = 0.01;
122 size_t const numberOfCells = cells_.size();
123 size_t const tolerance = std::max((size_t)std::fabs(numberOfCells*reltol), (size_t)25);
124 SearchDetail<Scalar,dim> searchDetail(boundingBox, dir);
125 Partition partition, tmpPartition;
126
127 splitCells(searchDetail, cells_, partition);
128 size_t difference = getDifference(partition);
129 while(difference > tolerance && searchDetail.delta > MINIMAL_DELTA)
130 {
131 searchDetail.delta *= 0.5;
132 searchDetail.split += searchDetail.delta;
133 splitCells(searchDetail, cells_, tmpPartition);
134 if(checkPartition(tmpPartition, difference))
135 {
136 swapPartition(partition,tmpPartition);
137 difference = getDifference(partition);
138 continue;
139 }
140 else
141 {
142 clear(tmpPartition);
143 searchDetail.split -= 2.*searchDetail.delta;
144 splitCells(searchDetail, cells_, tmpPartition);
145 if(checkPartition(tmpPartition, difference))
146 {
147 swapPartition(partition,tmpPartition);
148 difference = getDifference(partition);
149 }
150 else searchDetail.split += searchDetail.delta;
151 }
152 clear(tmpPartition);
153 }
154
155 // create children
156 children.first = new TreeNode(createBoundingBox(boundingBox,searchDetail,true), partition.first, changeDirection(searchDetail.direction), reltol, height+1, maxHeight);
157 children.second = new TreeNode(createBoundingBox(boundingBox,searchDetail,false), partition.second, changeDirection(searchDetail.direction), reltol, height+1, maxHeight);
158 }
159
160 void splitCells(SearchDetail<Scalar,dim> const& searchDetail, std::vector<GPC const*> const& cells_, Partition &partition) const
161 {
162 typename std::vector<GPC const*>::const_iterator ci=cells_.begin(), cend=cells_.end();
163 for(;ci!=cend; ++ci) addCell(**ci, searchDetail, partition);
164 /*std::for_each(cells_.begin(), cells_.end(), [](Cell const* cell)
165 {
166 addCell(*cell, searchDetail, partition);
167 });*/
168 }
169};
170
171#endif /* GRIDTREEPOLICY_HH_ */
A wrapper class for access to protected constructors.
typename GridView::template Codim< 0 >::Entity Cell
The type of cells (entities of codimension 0) in the grid view.
Definition: gridBasics.hh:35
Dune::FieldVector< T, n > max(Dune::FieldVector< T, n > x, Dune::FieldVector< T, n > const &y)
Componentwise maximum.
Definition: fixdune.hh:110
std::pair< Dune::FieldVector< double, Cell::dimension >, Dune::FieldVector< double, Cell::dimension > > boundingBox(Cell const &cell)
Computes the bounding box of a cell.
Definition: fixdune.hh:766
The default splitting policy.
void createChildren(BoundingBox const &boundingBox, std::vector< GPC const * > const &cells_, Direction dir, std::pair< TreeNode *, TreeNode * > &children, Scalar const reltol, Scalar const height, Scalar const maxHeight)
static int const dim
GetProtectedConstructor< Cell > GPC
void splitCells(SearchDetail< Scalar, dim > const &searchDetail, std::vector< GPC const * > const &cells_, Partition &partition) const
Cell::Geometry::ctype Scalar
std::pair< std::vector< GPC const * >, std::vector< GPC const * > > Partition