Dune Core Modules (2.6.0)

tensorgridfactory.hh
Go to the documentation of this file.
1 #ifndef DUNE_GRID_UTILITY_TENSORGRIDFACTORY_HH
2 #define DUNE_GRID_UTILITY_TENSORGRIDFACTORY_HH
3 
18 #include<array>
19 #include<memory>
20 #include<vector>
21 
22 #include <dune/common/fvector.hh>
24 #include <dune/grid/yaspgrid.hh>
26 
27 namespace Dune
28 {
29  // forward declaration of TensorGridFactoryCreator, which is the real factory
30  // that should be specialized for each grid.
31  template<typename Grid>
32  class TensorGridFactoryCreator;
33 
38  template<typename Grid>
40  {
41  public:
42  typedef typename Grid::Traits::CollectiveCommunication Comm;
43  typedef typename Grid::ctype ctype;
44  static const int dim = Grid::dimension;
45 
46  std::unique_ptr<Grid> createGrid(Comm comm = Comm())
47  {
48  TensorGridFactoryCreator<Grid> creator(*this);
49  return creator.createGrid(comm);
50  }
51 
52  std::array<std::vector<ctype> , dim> coords() const
53  {
54  return _coords;
55  }
56 
58  std::vector<ctype>& operator[](std::size_t d)
59  {
60  return _coords[d];
61  }
62 
64  const std::vector<ctype>& operator[](std::size_t d) const
65  {
66  return _coords[d];
67  }
68 
77  void setStart (int d, ctype value)
78  {
79  _coords[d].resize(1);
80  _coords[d][0] = value;
81  }
82 
91  void fillIntervals (int d, int n, ctype h)
92  {
93  emptyCheck (d);
94  for (int i = 0; i < n; i++)
95  _coords[d].push_back (_coords[d].back () + h);
96  }
97 
106  void fillRange (int d, int n, ctype end)
107  {
108  emptyCheck (d);
109  const ctype h = (end - _coords[d].back ()) / n;
110  for (int i = 0; i < n - 1; i++)
111  _coords[d].push_back (_coords[d].back () + h);
112  _coords[d].push_back (end);
113  }
114 
123  void fillUntil (int d, ctype h, ctype end)
124  {
125  emptyCheck (d);
126  while (_coords[d].back () < end)
127  _coords[d].push_back (_coords[d].back () + h);
128  }
129 
142  void geometricFillIntervals (int d, int n, ctype ratio, ctype h0 =
143  static_cast<ctype> (0))
144  {
145  emptyCheck (d);
146  ctype h = h0;
147  if (h0 == static_cast<ctype>(0))
148  h = lastInterval (d) * ratio;
149  for (int i = 0; i < n; i++)
150  {
151  _coords[d].push_back (_coords[d].back () + h);
152  h *= ratio;
153  }
154  }
155 
168  void geometricFillUntil (int d, ctype ratio, ctype end, ctype h0 = static_cast<ctype> (0))
169  {
170  emptyCheck (d);
171  ctype h = h0;
172  if (h0 == static_cast<ctype>(0))
173  h = lastInterval (d) * ratio;
174  while (_coords[d].back () < end)
175  {
176  _coords[d].push_back (_coords[d].back () + h);
177  h *= ratio;
178  }
179  }
180 
195  void geometricFillRange (int d, int n, ctype end, ctype h =
196  static_cast<ctype> (0),
197  bool first = true)
198  {
199  emptyCheck (d);
200  if (h < 1e-8)
201  h = lastInterval (d);
202  ctype ratio = newton (n, _coords[d].back (), end, h);
203  if (!first)
204  {
205  h = h * pow (ratio, n - 1);
206  ratio = 1 / ratio;
207  }
208  for (int i = 0; i < n - 1; i++)
209  {
210  _coords[d].push_back (_coords[d].back () + h);
211  h *= ratio;
212  }
213  _coords[d].push_back (end);
214  }
215 
217  void print()
218  {
219  for (int i=0; i<dim; i++)
220  {
221  std::cout << "Container in direction " << i << ":" << std::endl << "Coordinates: ";
222  for (auto it = _coords[i].begin(); it != _coords[i].end(); ++it)
223  std::cout << *it << " ";
224  std::cout << std::endl << "Interval lengths: ";
225 
226  std::vector<ctype> meshsize;
227  for (auto it = _coords[i].begin(); it != _coords[i].end()-1;)
228  {
229  meshsize.push_back(-1.*(*it));
230  ++it;
231  meshsize.back() += *it;
232  }
233 
234  for (auto it = meshsize.begin(); it != meshsize.end(); ++it)
235  std::cout << *it << " ";
236  std::cout << std::endl << "Ratios between interval lengths: ";
237 
238  std::vector<ctype> ratios;
239  for (auto it = meshsize.begin(); it != meshsize.end() - 1 ;)
240  ratios.push_back((1./(*it)) * *(++it));
241 
242  for (auto it = ratios.begin(); it != ratios.end(); ++it)
243  std::cout << *it << " ";
244  std::cout << std::endl << std::endl << std::endl;
245  }
246  }
247 
248  private:
249  // check whether the ith component is empty and add a 0.0 entry if so
250  void emptyCheck (int i)
251  {
252  if (_coords[i].empty ())
253  _coords[i].push_back (static_cast<ctype> (0));
254  }
255 
256  // returns the last interval length in direction d
257  ctype lastInterval (int d)
258  {
259  if (_coords[d].size () < 2)
260  DUNE_THROW(
261  GridError,
262  "Not enough elements in coordinate container to deduce interval length in TensorYaspFactory");
263  else
264  return _coords[d].back () - _coords[d][_coords[d].size () - 2];
265  }
266 
270  ctype newton (int n, ctype x_s, ctype x_e, ctype h)
271  {
272  ctype m = (x_e - x_s) / h;
273  ctype xold = 0.0;
274  ctype xnew = x_e - x_s;
275  while (std::abs (xnew - xold) > 1E-8)
276  {
277  xold = xnew;
278  xnew = xold
279  - (-pow (xold, n) + m * xold - m + 1)
280  / (-n * pow (xold, n - 1) + m);
281  }
282  if (std::abs (xnew - 1) < 1E-6)
283  {
284  xold = x_e - x_s;
285  xnew = 0.0;
286  while (std::abs (xnew - xold) > 1E-8)
287  {
288  xold = xnew;
289  xnew = xold
290  - (-pow (xold, n) + m * xold - m + 1)
291  / (-n * pow (xold, n - 1) + m);
292  }
293  }
294  return xnew;
295  }
296 
297  std::array<std::vector<ctype>, dim> _coords;
298  };
299 
300  // class that implements the actual grid creation process. The default is implementing
301  // standard creation for unstructured grids. Provide a specialization for other grids.
302  template<typename Grid>
303  class TensorGridFactoryCreator
304  {
305  public:
306  typedef typename Grid::Traits::CollectiveCommunication Comm;
307  typedef typename Grid::ctype ctype;
308  static const int dim = Grid::dimension;
309 
310  TensorGridFactoryCreator(const TensorGridFactory<Grid>& factory) : _factory(factory) {}
311 
312  std::unique_ptr<Grid> createGrid(Comm comm)
313  {
314  // The grid factory
315  GridFactory<Grid> fac;
316 
317  if (comm.rank() == 0)
318  {
319  // determine the size of the grid
320  std::array<unsigned int, dim> vsizes, esizes;
321  std::size_t size = 1;
322  for (std::size_t i = 0; i<dim; ++i)
323  {
324  vsizes[i] = _factory[i].size();
325  esizes[i] = vsizes[i] - 1;
326  size *= vsizes[i];
327  }
328 
329  // insert all vertices
330  FactoryUtilities::MultiIndex<dim> index(vsizes);
331  for (std::size_t i=0; i<size; ++i, ++index)
332  {
334  for (std::size_t j = 0; j<dim; ++j)
335  position[j] = _factory[j][index[j]];
336  fac.insertVertex(position);
337  }
338 
339  // compute the offsets
340  std::array<std::size_t, dim> offsets;
341  offsets[0] = 1;
342  for (std::size_t i=1; i<dim; i++)
343  offsets[i] = offsets[i-1] * vsizes[i-1];
344 
345  // Compute an element template (the cube at (0,...,0). All
346  // other cubes are constructed by moving this template around
347  unsigned int nCorners = 1<<dim;
348 
349  std::vector<unsigned int> cornersTemplate(nCorners,0);
350 
351  for (size_t i=0; i<nCorners; i++)
352  for (int j=0; j<dim; j++)
353  if ( i & (1<<j) )
354  cornersTemplate[i] += offsets[j];
355 
356  // Insert elements
357  FactoryUtilities::MultiIndex<dim> eindex(esizes);
358 
359  // Compute the total number of elements to be created
360  int numElements = eindex.cycle();
361 
362  for (int i=0; i<numElements; i++, ++eindex)
363  {
364  // 'base' is the index of the lower left element corner
365  unsigned int base = 0;
366  for (int j=0; j<dim; j++)
367  base += eindex[j] * offsets[j];
368 
369  // insert new element
370  std::vector<unsigned int> corners = cornersTemplate;
371  for (size_t j=0; j<corners.size(); j++)
372  corners[j] += base;
373 
374  fac.insertElement(GeometryTypes::cube(dim), corners);
375  }
376  }
377 
378  return std::unique_ptr<Grid>(fac.createGrid());
379  }
380 
381  private:
382  const TensorGridFactory<Grid>& _factory;
383  };
384 
385  template<typename ctype, int dim>
386  class TensorGridFactoryCreator<YaspGrid<dim, TensorProductCoordinates<ctype, dim> > >
387  {
388  public:
389  typedef YaspGrid<dim, TensorProductCoordinates<ctype, dim> > Grid;
390  typedef typename Grid::CollectiveCommunication Comm;
391 
392  TensorGridFactoryCreator(const TensorGridFactory<Grid>& factory) : _factory(factory) {}
393 
394  std::unique_ptr<Grid> createGrid(Comm comm)
395  {
396  return std::make_unique<Grid>(_factory.coords(), std::bitset<dim>(0ULL), 1, comm);
397  }
398  private:
399  const TensorGridFactory<Grid>& _factory;
400  };
401 }
402 
403 #endif
GridFamily::Traits::CollectiveCommunication CollectiveCommunication
A type that is a model of Dune::CollectiveCommunication. It provides a portable way for collective co...
Definition: grid.hh:519
@ dimension
The dimension of the grid.
Definition: grid.hh:387
ct ctype
Define type used for coordinates in grid module.
Definition: grid.hh:522
A factory class for conveniently creating tensorproduct grids.
Definition: tensorgridfactory.hh:40
void fillRange(int d, int n, ctype end)
fills the range to end with n intervals in direction d
Definition: tensorgridfactory.hh:106
void geometricFillRange(int d, int n, ctype end, ctype h=static_cast< ctype >(0), bool first=true)
fills a coordinate range in direction d with n intervals according to a geometric series
Definition: tensorgridfactory.hh:195
void fillUntil(int d, ctype h, ctype end)
adds intervals in direction d until a given coordinate is reached
Definition: tensorgridfactory.hh:123
void geometricFillUntil(int d, ctype ratio, ctype end, ctype h0=static_cast< ctype >(0))
adds intervals in direction d according with a given length ratio until a given coordinate is reached
Definition: tensorgridfactory.hh:168
std::vector< ctype > & operator[](std::size_t d)
allow to manually tune the factory by overloading operator[] to export the coordinate vectors in the ...
Definition: tensorgridfactory.hh:58
void print()
print the coordinate information given to the factory so far
Definition: tensorgridfactory.hh:217
void fillIntervals(int d, int n, ctype h)
pushs n intervals of length h in direction d
Definition: tensorgridfactory.hh:91
void setStart(int d, ctype value)
set a starting value in a given direction d
Definition: tensorgridfactory.hh:77
void geometricFillIntervals(int d, int n, ctype ratio, ctype h0=static_cast< ctype >(0))
adds n intervals in direction d with a given length ratio and a given starting interval length.
Definition: tensorgridfactory.hh:142
const std::vector< ctype > & operator[](std::size_t d) const
allow to manually tune the factory by overloading operator[] to export the coordinate vectors in the ...
Definition: tensorgridfactory.hh:64
Provide a generic factory class for unstructured grids.
Implements a multiindex with arbitrary dimension and fixed index ranges This is used by various facto...
Implements a vector constructed from a given type representing a field and a compile-time given size.
#define DUNE_THROW(E, m)
Definition: exceptions.hh:216
constexpr GeometryType cube(unsigned int dim)
Returns a GeometryType representing a hypercube of dimension dim.
Definition: type.hh:705
Dune namespace.
Definition: alignedallocator.hh:10
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.80.0 (Apr 19, 22:31, 2024)