DUNE PDELab (2.8)

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
24#include <dune/grid/yaspgrid.hh>
26
27namespace 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)
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:518
@ dimension
The dimension of the grid.
Definition: grid.hh:386
ct ctype
Define type used for coordinates in grid module.
Definition: grid.hh:521
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
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
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
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:470
constexpr HybridTreePath< T..., std::size_t > push_back(const HybridTreePath< T... > &tp, std::size_t i)
Appends a run time index to a HybridTreePath.
Definition: treepath.hh:278
constexpr auto back(const HybridTreePath< T... > &tp) -> decltype(treePathEntry< sizeof...(T) -1 >(tp))
Returns a copy of the last element of the HybridTreePath.
Definition: treepath.hh:254
Dune namespace.
Definition: alignedallocator.hh:11
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.111.3 (Dec 21, 23:30, 2024)