dune-grid  2.3beta2
structuredgridfactory.hh
Go to the documentation of this file.
1 // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 // vi: set et ts=4 sw=2 sts=2:
3 #ifndef DUNE_STRUCTURED_GRID_FACTORY_HH
4 #define DUNE_STRUCTURED_GRID_FACTORY_HH
5 
10 #include <algorithm>
11 #include <cstddef>
12 #include <cstdlib>
13 
14 #include <dune/common/array.hh>
15 #include <dune/common/classname.hh>
16 #include <dune/common/exceptions.hh>
17 #include <dune/common/fvector.hh>
18 #include <dune/common/parallel/mpihelper.hh>
19 #include <dune/common/shared_ptr.hh>
20 
22 #include <dune/grid/yaspgrid.hh>
23 #include <dune/grid/sgrid.hh>
24 
25 namespace Dune {
26 
29  template <class GridType>
31  {
32  typedef typename GridType::ctype ctype;
33 
34  static const int dim = GridType::dimension;
35 
36  static const int dimworld = GridType::dimensionworld;
37 
40  class MultiIndex
41  : public array<unsigned int,dim>
42  {
43 
44  // The range of each component
45  array<unsigned int,dim> limits_;
46 
47  public:
49  MultiIndex(const array<unsigned int,dim>& limits)
50  : limits_(limits)
51  {
52  std::fill(this->begin(), this->end(), 0);
53  }
54 
56  MultiIndex& operator++() {
57 
58  for (int i=0; i<dim; i++) {
59 
60  // Augment digit
61  (*this)[i]++;
62 
63  // If there is no carry-over we can stop here
64  if ((*this)[i]<limits_[i])
65  break;
66 
67  (*this)[i] = 0;
68 
69  }
70  return *this;
71  }
72 
74  size_t cycle() const {
75  size_t result = 1;
76  for (int i=0; i<dim; i++)
77  result *= limits_[i];
78  return result;
79  }
80 
81  };
82 
84  static void insertVertices(GridFactory<GridType>& factory,
85  const FieldVector<ctype,dimworld>& lowerLeft,
86  const FieldVector<ctype,dimworld>& upperRight,
87  const array<unsigned int,dim>& vertices)
88  {
89 
90  MultiIndex index(vertices);
91 
92  // Compute the total number of vertices to be created
93  int numVertices = index.cycle();
94 
95  // Create vertices
96  for (int i=0; i<numVertices; i++, ++index) {
97 
98  // scale the multiindex to obtain a world position
99  FieldVector<double,dimworld> pos(0);
100  for (int j=0; j<dimworld; j++)
101  pos[j] = lowerLeft[j] + index[j] * (upperRight[j]-lowerLeft[j])/(vertices[j]-1);
102 
103  factory.insertVertex(pos);
104 
105  }
106 
107  }
108 
109  // Compute the index offsets needed to move to the adjacent vertices
110  // in the different coordinate directions
111  static array<unsigned int, dim> computeUnitOffsets(const array<unsigned int,dim>& vertices)
112  {
113  array<unsigned int, dim> unitOffsets;
114  if (dim>0) // paranoia
115  unitOffsets[0] = 1;
116 
117  for (int i=1; i<dim; i++)
118  unitOffsets[i] = unitOffsets[i-1] * vertices[i-1];
119 
120  return unitOffsets;
121  }
122 
123  public:
124 
130  static shared_ptr<GridType> createCubeGrid(const FieldVector<ctype,dimworld>& lowerLeft,
131  const FieldVector<ctype,dimworld>& upperRight,
132  const array<unsigned int,dim>& elements)
133  {
134  // The grid factory
135  GridFactory<GridType> factory;
136 
137  if (MPIHelper::getCollectiveCommunication().rank() == 0)
138  {
139  // Insert uniformly spaced vertices
140  array<unsigned int,dim> vertices = elements;
141  for( size_t i = 0; i < vertices.size(); ++i )
142  vertices[i]++;
143 
144  // Insert vertices for structured grid into the factory
145  insertVertices(factory, lowerLeft, upperRight, vertices);
146 
147  // Compute the index offsets needed to move to the adjacent
148  // vertices in the different coordinate directions
149  array<unsigned int, dim> unitOffsets =
150  computeUnitOffsets(vertices);
151 
152  // Compute an element template (the cube at (0,...,0). All
153  // other cubes are constructed by moving this template around
154  unsigned int nCorners = 1<<dim;
155 
156  std::vector<unsigned int> cornersTemplate(nCorners,0);
157 
158  for (size_t i=0; i<nCorners; i++)
159  for (int j=0; j<dim; j++)
160  if ( i & (1<<j) )
161  cornersTemplate[i] += unitOffsets[j];
162 
163  // Insert elements
164  MultiIndex index(elements);
165 
166  // Compute the total number of elementss to be created
167  int numElements = index.cycle();
168 
169  for (int i=0; i<numElements; i++, ++index) {
170 
171  // 'base' is the index of the lower left element corner
172  unsigned int base = 0;
173  for (int j=0; j<dim; j++)
174  base += index[j] * unitOffsets[j];
175 
176  // insert new element
177  std::vector<unsigned int> corners = cornersTemplate;
178  for (size_t j=0; j<corners.size(); j++)
179  corners[j] += base;
180 
181  factory.insertElement
182  (GeometryType(GeometryType::cube, dim), corners);
183 
184  }
185 
186  } // if(rank == 0)
187 
188  // Create the grid and hand it to the calling method
189  return shared_ptr<GridType>(factory.createGrid());
190 
191  }
192 
199  static shared_ptr<GridType> createSimplexGrid(const FieldVector<ctype,dimworld>& lowerLeft,
200  const FieldVector<ctype,dimworld>& upperRight,
201  const array<unsigned int,dim>& elements)
202  {
203  // The grid factory
204  GridFactory<GridType> factory;
205 
206  if(MPIHelper::getCollectiveCommunication().rank() == 0)
207  {
208  // Insert uniformly spaced vertices
209  array<unsigned int,dim> vertices = elements;
210  for (std::size_t i=0; i<vertices.size(); i++)
211  vertices[i]++;
212 
213  insertVertices(factory, lowerLeft, upperRight, vertices);
214 
215  // Compute the index offsets needed to move to the adjacent
216  // vertices in the different coordinate directions
217  array<unsigned int, dim> unitOffsets =
218  computeUnitOffsets(vertices);
219 
220  // Insert the elements
221  std::vector<unsigned int> corners(dim+1);
222 
223  // Loop over all "cubes", and split up each cube into dim!
224  // (factorial) simplices
225  MultiIndex elementsIndex(elements);
226  size_t cycle = elementsIndex.cycle();
227 
228  for (size_t i=0; i<cycle; ++elementsIndex, i++) {
229 
230  // 'base' is the index of the lower left element corner
231  unsigned int base = 0;
232  for (int j=0; j<dim; j++)
233  base += elementsIndex[j] * unitOffsets[j];
234 
235  // each permutation of the unit vectors gives a simplex.
236  std::vector<unsigned int> permutation(dim);
237  for (int j=0; j<dim; j++)
238  permutation[j] = j;
239 
240  do {
241 
242  // Make a simplex
243  std::vector<unsigned int> corners(dim+1);
244  corners[0] = base;
245 
246  for (int j=0; j<dim; j++)
247  corners[j+1] =
248  corners[j] + unitOffsets[permutation[j]];
249 
250  factory.insertElement
252  corners);
253 
254  } while (std::next_permutation(permutation.begin(),
255  permutation.end()));
256 
257  }
258 
259  } // if(rank == 0)
260 
261  // Create the grid and hand it to the calling method
262  return shared_ptr<GridType>(factory.createGrid());
263  }
264 
265  };
266 
276  template<int dim>
278  typedef YaspGrid<dim> GridType;
279  typedef typename GridType::ctype ctype;
280  static const int dimworld = GridType::dimensionworld;
281 
282  public:
292  static shared_ptr<GridType>
293  createCubeGrid(const FieldVector<ctype,dimworld>& lowerLeft,
294  const FieldVector<ctype,dimworld>& upperRight,
295  const array<unsigned int,dim>& elements)
296  {
297  for(int d = 0; d < dimworld; ++d)
298  if(std::abs(lowerLeft[d]) > std::abs(upperRight[d])*1e-10)
299  DUNE_THROW(GridError, className<StructuredGridFactory>()
300  << "::createCubeGrid(): The lower coordinates "
301  "must be at the origin for YaspGrid.");
302 
303  Dune::array<int, dim> elements_;
304  std::copy(elements.begin(), elements.end(), elements_.begin());
305 
306  return shared_ptr<GridType>
307  (new GridType(upperRight, elements_,
308  std::bitset<dim>(false), 0));
309  }
310 
316  static shared_ptr<GridType>
317  createSimplexGrid(const FieldVector<ctype,dimworld>& lowerLeft,
318  const FieldVector<ctype,dimworld>& upperRight,
319  const array<unsigned int,dim>& elements)
320  {
321  DUNE_THROW(GridError, className<StructuredGridFactory>()
322  << "::createSimplexGrid(): Simplices are not supported "
323  "by YaspGrid.");
324  }
325 
326  };
327 
334  template<int dim>
335  class StructuredGridFactory<SGrid<dim, dim> > {
336  typedef SGrid<dim, dim> GridType;
337  typedef typename GridType::ctype ctype;
338  static const int dimworld = GridType::dimensionworld;
339 
340  public:
347  static shared_ptr<GridType>
348  createCubeGrid(const FieldVector<ctype,dimworld>& lowerLeft,
349  const FieldVector<ctype,dimworld>& upperRight,
350  const array<unsigned int,dim>& elements)
351  {
352  FieldVector<int, dim> elements_;
353  std::copy(elements.begin(), elements.end(), elements_.begin());
354 
355  return shared_ptr<GridType>
356  (new GridType(elements_, lowerLeft, upperRight));
357  }
358 
368  static shared_ptr<GridType>
369  createSimplexGrid(const FieldVector<ctype,dimworld>& lowerLeft,
370  const FieldVector<ctype,dimworld>& upperRight,
371  const array<unsigned int,dim>& elements)
372  {
373  DUNE_THROW(GridError, className<StructuredGridFactory>()
374  << "::createSimplexGrid(): Simplices are not supported "
375  "by SGrid.");
376  }
377  };
378 
379 } // namespace Dune
380 
381 #endif