12#ifndef DUMUX_CAKE_GRID_MANAGER_HH
13#define DUMUX_CAKE_GRID_MANAGER_HH
20#include <dune/common/dynvector.hh>
21#include <dune/common/float_cmp.hh>
22#include <dune/common/math.hh>
23#include <dune/grid/common/gridfactory.hh>
37 using Scalar =
typename Grid::ctype;
39 using GridFactory = Dune::GridFactory<Grid>;
40 using GridPointer = std::shared_ptr<Grid>;
42 enum { dim = Grid::dimension,
43 dimWorld = Grid::dimensionworld };
49 void init(
const std::string& modelParamGroup =
"")
51 static_assert(dim == 2 || dim == 3,
"The CakeGridManager is only implemented for 2D and 3D.");
53 const bool verbose = getParamFromGroup<bool>(modelParamGroup,
"Grid.Verbosity",
false);
55 std::array<std::vector<Scalar>, dim> polarCoordinates;
57 Dune::FieldVector<int, dim> indices(-1);
58 createVectors(polarCoordinates, indices, modelParamGroup, verbose);
84 static void createVectors(std::array<std::vector<Scalar>, dim> &polarCoordinates,
85 Dune::FieldVector<int, dim> &indices,
86 const std::string& modelParamGroup,
90 std::array<std::vector<Scalar>, dim> positions;
92 for (
int i = 0; i < dim; ++i)
94 const bool hasRadial =
hasParamInGroup(modelParamGroup,
"Grid.Radial" + std::to_string(i));
95 const bool hasAngular =
hasParamInGroup(modelParamGroup,
"Grid.Angular" + std::to_string(i));
96 const bool hasAxial = (dim == 3) &&
hasParamInGroup(modelParamGroup,
"Grid.Axial" + std::to_string(i));
97 if (
static_cast<int>(hasRadial) +
static_cast<int>(hasAngular) +
static_cast<int>(hasAxial) != 1)
98 DUNE_THROW(Dune::RangeError,
"Multiple or no position vectors (radial, angular, axial) specified in coord direction: " << i << std::endl);
102 positions[i] = getParamFromGroup<std::vector<Scalar>>(modelParamGroup,
"Grid.Radial" + std::to_string(i));
107 positions[i] = getParamFromGroup<std::vector<Scalar>>(modelParamGroup,
"Grid.Angular" + std::to_string(i));
112 positions[i] = getParamFromGroup<std::vector<Scalar>>(modelParamGroup,
"Grid.Axial" + std::to_string(i));
116 if (!std::is_sorted(positions[i].begin(), positions[i].end()))
117 DUNE_THROW(Dune::GridError,
"Make sure to specify a monotone increasing \"Positions\" array");
119 if(positions[i].size() < 2)
120 DUNE_THROW(Dune::GridError,
"Make sure to specify position arrays with at least two entries (min and max value).");
124 for (
int i = 0; i < dim; ++i)
126 DUNE_THROW(Dune::RangeError,
"Please specify Positions Angular and Radial and Axial correctly and unambiguously!" << std::endl);
129 std::array<std::vector<int>, dim> cells;
130 for (
int i = 0; i < dim; ++i)
132 cells[i].resize(positions[i].size()-1, 1.0);
133 cells[i] = getParamFromGroup<std::vector<int>>(modelParamGroup,
"Grid.Cells" + std::to_string(i), cells[i]);
134 if (cells[i].size() + 1 != positions[i].size())
135 DUNE_THROW(Dune::RangeError,
"Make sure to specify the correct length of \"Cells\" and \"Positions\" arrays");
139 std::array<std::vector<Scalar>, dim> grading;
140 for (
int i = 0; i < dim; ++i)
142 grading[i].resize(positions[i].size()-1, 1.0);
143 grading[i] = getParamFromGroup<std::vector<Scalar>>(modelParamGroup,
"Grid.Grading" + std::to_string(i), grading[i]);
144 if (grading[i].size() + 1 != positions[i].size())
145 DUNE_THROW(Dune::RangeError,
"Make sure to specify the correct length of \"Grading\" and \"Positions\" arrays");
149 std::array<std::vector<Scalar>, dim> globalPositions;
152 for (
int dimIdx = 0; dimIdx < dim; dimIdx++)
155 std::size_t numGlobalPositions = 1;
156 for (
int zoneIdx = 0; zoneIdx < cells[dimIdx].size(); ++zoneIdx)
157 numGlobalPositions += cells[dimIdx][zoneIdx];
159 globalPositions[dimIdx].resize(numGlobalPositions);
160 std::size_t posIdx = 0;
161 for (
int zoneIdx = 0; zoneIdx < cells[dimIdx].size(); ++zoneIdx)
163 const Scalar lower = positions[dimIdx][zoneIdx];
164 const Scalar upper = positions[dimIdx][zoneIdx+1];
165 const int numCells = cells[dimIdx][zoneIdx];
166 Scalar gradingFactor = grading[dimIdx][zoneIdx];
167 const Scalar length = upper - lower;
169 bool increasingCellSize =
false;
173 std::cout <<
"dim " << dimIdx
174 <<
" lower " << lower
175 <<
" upper " << upper
176 <<
" numCells " << numCells
177 <<
" grading " << gradingFactor;
180 if (gradingFactor > 1.0)
181 increasingCellSize =
true;
185 if (gradingFactor < 0.0)
188 gradingFactor = abs(gradingFactor);
190 if (gradingFactor < 1.0)
191 increasingCellSize =
true;
194 const bool useGrading = Dune::FloatCmp::eq(gradingFactor, 1.0) ? false :
true;
199 height = 1.0 / numCells;
201 std::cout <<
" -> h " << height * length << std::endl;
206 height = (1.0 - gradingFactor) / (1.0 - power(gradingFactor, numCells));
210 std::cout <<
" -> grading_eff " << gradingFactor
211 <<
" h_min " << height * power(gradingFactor, 0) * length
212 <<
" h_max " << height * power(gradingFactor, numCells-1) * length
218 Dune::DynamicVector<Scalar> localPositions(numCells, 0.0);
219 for (
int i = 1; i < numCells; i++)
224 if (increasingCellSize)
225 hI *= power(gradingFactor, i-1);
228 hI *= power(gradingFactor, numCells-i);
230 localPositions[i] = localPositions[i-1] + hI;
233 localPositions *= length;
234 localPositions += lower;
236 for (
int i = 0; i < numCells; ++i)
237 globalPositions[dimIdx][posIdx++] = localPositions[i];
240 globalPositions[dimIdx][posIdx] = positions[dimIdx].back();
243 polarCoordinates[0] = globalPositions[indices[0]];
244 polarCoordinates[1] = globalPositions[indices[1]];
246 polarCoordinates[2] = globalPositions[dim - indices[0] - indices[1]];
249 std::transform(polarCoordinates[1].begin(), polarCoordinates[1].end(),
250 polarCoordinates[1].begin(),
251 [](Scalar s){
return s*M_PI/180; });
262 std::unique_ptr<Grid>
createCakeGrid(std::array<std::vector<Scalar>, dim> &polarCoordinates,
263 Dune::FieldVector<int, dim> &indices,
264 const std::string& modelParamGroup,
265 bool verbose =
false)
267 GridFactory gridFactory;
270 if (gridFactory.comm().rank() != 0)
271 return std::unique_ptr<Grid>(gridFactory.createGrid());
273 const auto& dR = polarCoordinates[0];
274 const auto& dA = polarCoordinates[1];
280 const int dAMax = Dune::FloatCmp::eq(dA[dA.size()-1], 2*M_PI) ? dA.size() - 2 : dA.size() - 1;
281 constexpr auto type = Dune::GeometryTypes::cube(dim);
282 const bool hasHole = dR[0] >= 1.0e-8*dR.back();
285 if constexpr (dim == 3)
287 constexpr auto prismType = Dune::GeometryTypes::prism;
288 std::vector<Scalar> dZ = polarCoordinates[2];
289 for (
int j = 0; j <= dAMax; ++j)
291 for (
int l = 0; l <= dZ.size() - 1; ++l)
293 for (
int i = hasHole ? 0 : 1; i <= dR.size()- 1; ++i)
298 Dune::FieldVector <double, dim> v(0.0);
299 v[indices[2]] = dZ[l];
300 v[indices[0]] = cos(dA[j])*dR[i];
301 v[indices[1]] = sin(dA[j])*dR[i];
304 gridFactory.insertVertex(v);
313 for (
int l = 0; l <= dZ.size() - 1; ++l)
315 Dune::FieldVector <double, dim> v(0.0);
316 v[indices[2]] = dZ[l];
322 gridFactory.insertVertex(v);
327 std::cout <<
"Filled node vector" << std::endl;
332 unsigned int rSize = hasHole ? dR.size() : dR.size()-1;
333 unsigned int zSize = dZ.size();
334 for (
int j = 0; j < dA.size() - 1; ++j)
336 for (
int l = 0; l < dZ.size() - 1; ++l)
340 for (
int i = 0; i < dR.size() - 1; ++i)
344 std::vector<unsigned int> vid({rSize*zSize*(dAMax+1) + l, z, z+rSize*zSize,
345 rSize*zSize*(dAMax+1) + l+1, z+rSize, z+rSize*zSize+rSize});
350 gridFactory.insertElement(prismType, vid);
354 std::vector<unsigned int> vid({z, z+1,
355 z+rSize*zSize, z+rSize*zSize+1,
357 z+rSize*zSize+rSize, z+rSize*zSize+rSize+1});
362 gridFactory.insertElement(type, vid);
372 for (
int i = 0; i < dR.size() - 1; ++i)
376 std::vector<unsigned int> vid({rSize*zSize*(dAMax+1) + l, z, t,
377 rSize*zSize*(dAMax+1) + l+1, z+rSize, t+rSize});
382 gridFactory.insertElement(prismType, vid);
386 std::vector<unsigned int> vid({z, z+1,
389 t+rSize, t+rSize+1});
394 gridFactory.insertElement(type, vid);
403 std::cout <<
"assign nodes 360° ends..." << std::endl;
413 constexpr auto triangleType = Dune::GeometryTypes::simplex(dim);
414 for (
int j = 0; j <= dAMax; ++j)
416 for (
int i = hasHole ? 0 : 1; i <= dR.size()- 1; ++i)
419 Dune::FieldVector <double, dim> v(0.0);
421 v[indices[0]] = cos(dA[j])*dR[i];
422 v[indices[1]] = sin(dA[j])*dR[i];
425 gridFactory.insertVertex(v);
433 Dune::FieldVector <double, dim> v(0.0);
439 gridFactory.insertVertex(v);
442 std::cout <<
"Filled node vector" << std::endl;
447 unsigned int rSize = hasHole ? dR.size() : dR.size()-1;
448 for (
int j = 0; j < dA.size() - 1; ++j)
452 for (
int i = 0; i < dR.size() - 1; ++i)
456 std::vector<unsigned int> vid({rSize*(dAMax+1), z, z+rSize});
461 gridFactory.insertElement(triangleType, vid);
465 std::vector<unsigned int> vid({z, z+1, z+rSize, z+rSize+1});
470 gridFactory.insertElement(type, vid);
479 for (
int i = 0; i < dR.size() - 1; ++i)
483 std::vector<unsigned int> vid({rSize*(dAMax+1), z, t});
488 gridFactory.insertElement(triangleType, vid);
492 std::vector<unsigned int> vid({z, z+1, t, t+1});
497 gridFactory.insertElement(type, vid);
506 std::cout <<
"assign nodes 360 ends..." << std::endl;
512 return std::unique_ptr<Grid>(gridFactory.createGrid());
534 { std::cout <<
"Coordinates of: " << v << std::endl; }
538 std::cout <<
"element vertex indices: ";
539 for (
int k = 0; k < vid.size(); ++k)
540 std::cout << vid[k] <<
" ";
541 std::cout << std::endl;
553 GridPointer cakeGrid_;
Provides a grid manager with a method for creating creating vectors with polar Coordinates and one fo...
Definition: cakegridmanager.hh:36
void init(const std::string &modelParamGroup="")
Make the grid.
Definition: cakegridmanager.hh:49
void loadBalance()
Distributes the grid on all processes of a parallel computation.
Definition: cakegridmanager.hh:527
GridPointer & gridPtr()
Returns a reference to the shared pointer to the grid.
Definition: cakegridmanager.hh:547
static void printCoordinate(const Dune::FieldVector< double, dim > &v)
Definition: cakegridmanager.hh:533
static void printIndices(const std::vector< unsigned int > &vid)
Definition: cakegridmanager.hh:536
Grid & grid()
Returns a reference to the grid.
Definition: cakegridmanager.hh:518
static void createVectors(std::array< std::vector< Scalar >, dim > &polarCoordinates, Dune::FieldVector< int, dim > &indices, const std::string &modelParamGroup, bool verbose=false)
Create vectors containing polar coordinates of all points.
Definition: cakegridmanager.hh:84
std::unique_ptr< Grid > createCakeGrid(std::array< std::vector< Scalar >, dim > &polarCoordinates, Dune::FieldVector< int, dim > &indices, const std::string &modelParamGroup, bool verbose=false)
Creates Cartesian grid from polar coordinates.
Definition: cakegridmanager.hh:262
bool hasParamInGroup(const std::string ¶mGroup, const std::string ¶m)
Check whether a key exists in the parameter tree with a model group prefix.
Definition: parameters.hh:165
The infrastructure to retrieve run-time parameters from Dune::ParameterTrees.