ug4
load_balancing_impl.hpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2011-2015: G-CSC, Goethe University Frankfurt
3  * Author: Sebastian Reiter
4  *
5  * This file is part of UG4.
6  *
7  * UG4 is free software: you can redistribute it and/or modify it under the
8  * terms of the GNU Lesser General Public License version 3 (as published by the
9  * Free Software Foundation) with the following additional attribution
10  * requirements (according to LGPL/GPL v3 §7):
11  *
12  * (1) The following notice must be displayed in the Appropriate Legal Notices
13  * of covered and combined works: "Based on UG4 (www.ug4.org/license)".
14  *
15  * (2) The following notice must be displayed at a prominent place in the
16  * terminal output of covered works: "Based on UG4 (www.ug4.org/license)".
17  *
18  * (3) The following bibliography is recommended for citation and must be
19  * preserved in all covered files:
20  * "Reiter, S., Vogel, A., Heppner, I., Rupp, M., and Wittum, G. A massively
21  * parallel geometric multigrid solver on hierarchically distributed grids.
22  * Computing and visualization in science 16, 4 (2013), 151-164"
23  * "Vogel, A., Reiter, S., Rupp, M., Nägel, A., and Wittum, G. UG4 -- a novel
24  * flexible software system for simulating pde based models on high performance
25  * computers. Computing and visualization in science 16, 4 (2013), 165-179"
26  *
27  * This program is distributed in the hope that it will be useful,
28  * but WITHOUT ANY WARRANTY; without even the implied warranty of
29  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30  * GNU Lesser General Public License for more details.
31  */
32 
33 #ifndef __H__UG__load_balancing_impl__
34 #define __H__UG__load_balancing_impl__
35 
36 #include <vector>
37 #include "load_balancing.h"
38 #include "common/static_assert.h"
41 
42 namespace ug
43 {
44 
47 
49 template <class TElem, class TIterator, class TAAPos>
51  TIterator begin, TIterator end,
52  int numCellsX, int numCellsY, int numCellsZ,
53  TAAPos& aaPos,
54  typename Grid::traits<TElem>::callback cbConsiderElem,
55  int bucketSubset)
56 {
57  using namespace ug;
58  using namespace std;
59 
60  typedef typename TAAPos::ValueType vector_t;
61 
62 // make sure that the dimension is right
63  UG_STATIC_ASSERT(TAAPos::ValueType::Size >= 2,
64  TAPosition_has_to_be_at_least_two_dimensional);
65 
66  UG_ASSERT(shOut.grid(), "A grid has to be associated with the "
67  "specified subset handler.");
68 
69  if((numCellsX < 1) || (numCellsY < 1) || (numCellsZ < 1)){
70  UG_THROW("At least one cell per direction should be specified.");
71  }
72 
73  Grid& grid = *shOut.grid();
74 
75 // collect all elements which shall be considered for partitioning.
76 // All others are assigned to bucketSubset
77  vector<TElem*> elems;
78  for(TIterator iter = begin; iter != end; ++iter){
79  if(cbConsiderElem(*iter))
80  elems.push_back(*iter);
81  else
82  shOut.assign_subset(*iter, bucketSubset);
83  }
84 
85 // calculate the bounding box
86  vector_t tmin(0), tmax(0);
87  {
88  grid.begin_marking();
89  vector<Vertex*> vrts, associatedVrts;
90  for(TIterator iter = begin; iter != end; ++iter){
91  CollectAssociated(vrts, grid, *iter);
92  for(size_t i = 0; i < vrts.size(); ++i){
93  if(!grid.is_marked(vrts[i])){
94  associatedVrts.push_back(vrts[i]);
95  grid.mark(vrts[i]);
96  }
97  }
98  }
99  grid.end_marking();
100 
101  CalculateBoundingBox(tmin, tmax, associatedVrts.begin(),
102  associatedVrts.end(), aaPos);
103  }
104 
105  vector3 min, max;
106  VecCopy(min, tmin, 0);
107  VecCopy(max, tmax, 0);
108 
109  number width = max.x() - min.x();
110  number height = max.y() - min.y();
111  number depth = max.z() - min.z();
112 
113  if((width < SMALL) && numCellsX > 1){
114  UG_LOG("Can't execute PartitionElements_Rectangle: Geometry has no width.\n");
115  return false;
116  }
117  if((height < SMALL) && numCellsY > 1){
118  UG_LOG("Can't execute PartitionElements_Rectangle: Geometry has no height.\n");
119  return false;
120  }
121  if((depth < SMALL) && numCellsZ > 1){
122  UG_LOG("Can't execute PartitionElements_Rectangle: Geometry has no height.\n");
123  return false;
124  }
125 
126 
127 // iterate over all elements and calculate the index at which they shall be
128 // inserted into the subset handler
129  for(typename vector<TElem*>::iterator iter = elems.begin();
130  iter != elems.end(); ++iter)
131  {
132  TElem* elem = *iter;
133  vector3 center;
134  VecCopy(center, CalculateCenter(elem, aaPos), 0);
135 
136  // get the cell index
137  int xInd = 0;
138  if(numCellsX > 1)
139  xInd = (int)((number)numCellsX * (center.x() - min.x()) / width);
140  int yInd = 0;
141  if(numCellsY > 1)
142  yInd = (int)((number)numCellsY * (center.y() - min.y()) / height);
143  int zInd = 0;
144  if(numCellsZ > 1)
145  zInd = (int)((number)numCellsZ * (center.z() - min.z()) / depth);
146 
147  // calculate the subset index (one could think of several alternatives here)
148  int si = zInd * numCellsX * numCellsY + yInd * numCellsX + xInd;
149 
150  // assign the subset
151  shOut.assign_subset(elem, si);
152  }
153  return true;
154 }
155 }// end of namespace
156 
157 #endif
158 
159 
160 
161 
162 
163 
164 
165 // This is some old and unmaintained code.
166 // Maybe it will be useful somewhen...
195 /*
196 template <class TElem, int IDimension>
197 bool PartitionElementsByRepeatedIntersectionKD(ug::SubsetHandler& shOut,
198  ug::Grid& grid,
199  int numSubsets,
200  ug::APosition& aVrtPos)
201 {
202 // TODO: move implementation to separate ..._impl.hpp file.
203  using namespace ug;
204  using namespace std;
205 
206  typedef KDTreeStatic<APosition, IDimension> KDTree;
207  typedef typename geometry_traits<TElem>::iterator ElemIterator;
208 
209 // get the max-size from the number of subsets that shall be constructed
210  int treeDepth = 0;
211  int numLeafs = 1;
212  while(numLeafs < numSubsets)
213  {
214  treeDepth++;
215  numLeafs *= 2;
216  }
217 
218  if(numLeafs != numSubsets)
219  {
220  LOG("PROBLEM in PartitionElementsByRepeatedIntersection: ");
221  LOG("numSubsets has to be chosen as a power of 2)\n");
222  return false;
223  }
224 
225 // fill a kd-tree with the vertices. This will help to find the elem-partition later on.
226  KDTree kdTree;
227  kdTree.create_from_grid(grid, grid.vertices_begin(), grid.vertices_end(),
228  aVrtPos, treeDepth, 1, KDSD_CIRCULAR);
229 
230 // get the leafs
231  vector<typename KDTree::Node*> vLeafs;
232  kdTree.get_leafs(vLeafs);
233 
234  if(vLeafs.size() != numLeafs)
235  {
236  // the algorithm failed, since it is not suited to deal with the
237  // given grid and the given parameters.
238  // You could try to distribute your grid onto less processes.
239  // The problem is, that the amount of vertices on both sides of a cut
240  // is not the same. This could be improved, by not choosing the cut-plane
241  // in the kd-tree in a geometric way, but by choosing it so, that
242  // the amount of vertices on both sides equals.
243  // To avoid this problem you could try to rotate your grid. Try to align it
244  // with the x, y and z axis - or write a better algorithm! This one is only
245  // suited for simple test-problems!!!
246  LOG("PROBLEM in PartitionElementsByRepeatedIntersection: ");
247  LOG("could not find the correct intersections.\n");
248  LOG("This can happen depending on the properties of the grid.\n");
249  LOG("Search the source-code for more informations.\n");
250  return false;
251  }
252 
253  shOut.clear();
254 
255 // we need a vertex-selector
256  VertexSelector sel(grid);
257 
258 // iterate through the leafs. They are sorted in a special way.
259  for(uint i = 0; i < vLeafs.size(); ++i)
260  {
261  // select all vertices of the leaf.
262  sel.select(vLeafs[i]->m_pvVertices->begin(), vLeafs[i]->m_pvVertices->end());
263 
264  // now iterate through the elements of the grid.
265  for(ElemIterator iter = grid.begin<TElem>(); iter != grid.end<TElem>(); ++iter)
266  {
267  // push all elements that do not reference unselected vertices into the i-th subset.
268  // all elements will be assigned to a subset this way, since all vertices are
269  // selected in the last iteration.
270  TElem* ele = *iter;
271  // make sure, that the element is not already assigned to a subset.
272  if(shOut.get_subset_index(ele) == -1)
273  {
274  bool bAllSelected = true;
275  for(int j = 0; j < ele->num_vertices(); ++j)
276  {
277  if(!sel.is_selected(ele->vertex(j)))
278  {
279  bAllSelected = false;
280  break;
281  }
282  }
283 
284  // if all vertices were selected, we'll push the element to the subset.
285  if(bAllSelected)
286  shOut.assign_subset(ele, i);
287  }
288  }
289  }
290 
291 //TODO: exchange elements between subsets until all subsets meet a certain criterion.
292 
293  return true;
294 }
295 */
Manages the elements of a grid and their interconnection.
Definition: grid.h:132
void end_marking()
ends a marking sequence. Call this method when you're done with marking.
Definition: grid.cpp:1285
bool is_marked(GridObject *obj) const
returns true if the object is marked, false if not.
Definition: grid_impl.hpp:843
void mark(GridObject *obj)
marks the object. Calls are only valid between calls to Grid::begin_marking and Grid::end_marking.
Definition: grid_impl.hpp:773
void begin_marking()
begin marking.
Definition: grid.cpp:1262
Partitions elements of a grid into several subsets.
Definition: subset_handler_grid.h:53
void assign_subset(Vertex *elem, int subsetIndex)
assigns a vertex to a subset.
Definition: subset_handler_grid.cpp:204
Grid * grid() const
returns a pointer to the grid on which the subset-handler works.
Definition: subset_handler_interface.cpp:304
UG_API void CollectAssociated(std::vector< Vertex * > &vVertexOut, Grid &grid, GridObject *obj, bool clearContainer=true)
Definition: grid_util_impl.hpp:169
bool PartitionElements_RegularGrid(SubsetHandler &shOut, TIterator begin, TIterator end, int numCellsX, int numCellsY, int numCellsZ, TAAPos &aaPos, typename Grid::traits< TElem >::callback cbConsiderElem=ConsiderAll(), int bucketSubset=-1)
Partitions the elements in the grid by sorting them into a regular grid.
Definition: load_balancing_impl.hpp:50
#define UG_ASSERT(expr, msg)
Definition: assert.h:70
#define UG_THROW(msg)
Definition: error.h:57
#define UG_STATIC_ASSERT(expr, msg)
Checks an expression at compile-time and raises a compile-error if the expression equals 0.
Definition: static_assert.h:63
#define UG_LOG(msg)
Definition: log.h:367
double number
Definition: types.h:124
void CalculateCenter(vector_t &centerOut, const vector_t *pointSet, size_t numPoints)
calculates the center of a point-set
Definition: math_util_impl.hpp:98
void VecCopy(vector_target_t &target, const vector_source_t &source, typename vector_target_t::value_type fill)
Copy contents between vectors of possibly different types.
Definition: math_vector_functions_common_impl.hpp:56
Definition: smart_pointer.h:814
the ug namespace
const number SMALL
Definition: math_constants.h:41
AABox< typename TAAPos::ValueType > CalculateBoundingBox(Vertex *e, TAAPos aaPos)
calculates the smallest axis aligned box that contains the given vertex
Definition: bounding_box_util.h:43
boost::function< bool(base_object *)> callback
callback type for the elements base type.
Definition: grid.h:150