282class SnappyGridManager :
public Dumux::GridManager<Dune::YaspGrid<dim, Dune::TensorProductCoordinates<typename OtherGridCreator::Grid::ctype, OtherGridCreator::Grid::LeafGridView::dimensionworld>>>
284 using Scalar =
typename OtherGridCreator::Grid::ctype;
285 using OtherGrid =
typename OtherGridCreator::Grid;
286 using IntVector = std::vector<int>;
287 using ScalarVector = std::vector<Scalar>;
289 static constexpr auto dimWorld = OtherGrid::LeafGridView::dimensionworld;
290 using GlobalPosition = Dune::FieldVector<Scalar, dimWorld>;
293 using LowDimGridData =
typename OtherGridCreator::GridData;
295 struct GridConstructionData
297 std::array<ScalarVector, dim> positions;
298 std::array<IntVector, dim> cells;
299 std::array<ScalarVector, dim> grading;
300 std::array<std::optional<ScalarVector>, dim> interfacePositions;
305 using ParentType::ParentType;
308 void init(
const OtherGrid& otherGrid,
const LowDimGridData& otherData,
const std::string& modelParamGroup =
"")
310 modelParamGroup_ = modelParamGroup;
311 std::array<ScalarVector, dim> positions;
312 std::array<IntVector, dim> cells;
313 std::array<ScalarVector, dim> grading;
314 std::array<std::optional<ScalarVector>, dim> interFacePositions;
321 "Grid.CouplinglineNormal",
322 [](){ GlobalPosition tmp(0.0); tmp[tmp.size()-1] = 1.0;
return tmp; }());
324 const auto couplingPlaneNormalDirectionIndex = SnappyGridManagerHelper::directionIndex(couplingPlaneNormal);
325 const auto couplingPlane = SnappyGridManagerHelper::makeCouplingPlane(lowerLeft, upperRight, couplingPlaneNormal, modelParamGroup);
327 std::cout <<
"plane: \n";
328 for (
int i = 0; i < couplingPlane.corners(); ++i)
329 std::cout << couplingPlane.corner(i) << std::endl;
331 const auto pointsOnAxisParallelLines = SnappyGridManagerHelper::getPointsOnLine(lowerLeft, upperRight, couplingPlaneNormal, otherGrid.leafGridView(), otherData, modelParamGroup_);
333 for (
int i = 0; i < dim; ++i)
336 positions[i].push_back(lowerLeft[i]);
338 if (i != couplingPlaneNormalDirectionIndex)
340 if (!pointsOnAxisParallelLines[i].has_value())
341 DUNE_THROW(Dune::GridError,
"Something went wrong with the coupling plane normal");
343 const auto& pointsOnLine = (*pointsOnAxisParallelLines[i]);
345 std::cout <<
"point " << i << std::endl;
346 for (
auto x : pointsOnLine)
347 std::cout << x.pos << std::endl;
352 addUpstreamPositions_(i, upstreamPositions, positions, pointsOnLine);
353 addUpstreamCells_(i, upstreamPositions, cells);
355 addCouplingPositions_(i, positions, pointsOnLine, interFacePositions, lowerLeft, upperRight);
356 addCouplingCells_(i, cells, pointsOnLine);
359 const ScalarVector downstreamPositions =
getParamFromGroup<ScalarVector>(modelParamGroup,
"Grid.DownstreamPositions" + std::to_string(i), ScalarVector{});
361 addDownstreamPositions_(i, downstreamPositions, positions, upperRight);
362 addDownstreamCells_(i, downstreamPositions, cells);
365 positions[i].push_back(upperRight[i]);
369 grading[i].resize(positions[i].size()-1, 1.0);
371 addUpstreamGrading_(i, upstreamPositions, grading);
372 addDownstreamGrading_(i, downstreamPositions, positions, grading);
377 if (i != couplingPlaneNormalDirectionIndex)
378 DUNE_THROW(Dune::GridError,
"Something went wrong with the coupling plane normal");
383 addNormalPositions_(i, normalPositions, positions, upperRight);
384 positions[i].push_back(upperRight[i]);
385 addNormalCells_(i, normalPositions, cells);
386 grading[i].resize(positions[i].size()-1, 1.0);
387 addNormalGrading_(i, normalPositions, grading);
390 if (positions[i].size() != cells[i].size() + 1)
391 DUNE_THROW(Dune::GridError,
"Wrong number of cells in " << i);
397 gridConstructionData_ = GridConstructionData{std::move(positions), std::move(cells), std::move(grading), std::move(interFacePositions)};
402 {
return gridConstructionData_; }
410 template<
class Po
intsOnLine>
411 void addUpstreamPositions_(
const int directionIndex,
412 const ScalarVector& upstreamPositions,
413 std::array<ScalarVector, dim>& positions,
414 const PointsOnLine& points)
416 if (!upstreamPositions.empty())
418 const Scalar gridLowerLeft = positions[directionIndex][0];
419 for (
const Scalar pos : upstreamPositions)
421 if ((pos < points[0].pos - points[0].radius) && (pos > gridLowerLeft))
422 positions[directionIndex].push_back(pos);
424 DUNE_THROW(Dune::RangeError,
"Make sure to set positions only in the inlet");
429 void addUpstreamCells_(
const int directionIndex,
430 const ScalarVector& upstreamPositions,
431 std::array<IntVector, dim>& cells)
434 "Grid.UpstreamCells" + std::to_string(directionIndex),
437 if (cellsUpstream.empty())
440 if (cellsUpstream.size() != upstreamPositions.size() + 1)
441 DUNE_THROW(Dumux::ParameterException,
"UpstreamCells" << std::to_string(directionIndex) <<
" must equal UpstreamPositions" << std::to_string(directionIndex) <<
" + 1");
443 for (
int c : cellsUpstream)
446 DUNE_THROW(Dumux::ParameterException,
"UpstreamCells" << std::to_string(directionIndex) <<
" must have values greater than zero.");
447 cells[directionIndex].push_back(c);
451 void addUpstreamGrading_(
const int directionIndex,
452 const ScalarVector& upstreamPositions,
453 std::array<ScalarVector, dim>& grading)
455 const ScalarVector upstreamGrading =
getParamFromGroup<ScalarVector>(modelParamGroup_,
"Grid.UpstreamGrading" + std::to_string(directionIndex), ScalarVector{});
457 if (!upstreamGrading.empty())
459 if (upstreamGrading.size() != upstreamPositions.size() + 1)
460 DUNE_THROW(Dune::RangeError,
"UpstreamGrading" << std::to_string(directionIndex) <<
" must equal UpstreamPositions" << std::to_string(directionIndex) <<
" + 1");
462 for (
int i = 0; i < upstreamPositions.size() + 1; ++i)
463 grading[directionIndex][i] = upstreamGrading[i];
471 void addDownstreamPositions_(
const int directionIndex,
472 const ScalarVector& downstreamPositions,
473 std::array<ScalarVector, dim>& gridPositions,
474 const GlobalPosition& gridUpperRight)
476 if (!downstreamPositions.empty())
478 for (
const Scalar pos : downstreamPositions)
480 if ((pos > gridPositions[directionIndex].back()) && (pos < gridUpperRight[directionIndex]))
481 gridPositions[directionIndex].push_back(pos);
483 DUNE_THROW(Dune::RangeError,
"Make sure to set ascending positions only in the outlet");
488 void addDownstreamCells_(
const int directionIndex,
489 const ScalarVector& downstreamPositions,
490 std::array<IntVector, dim>& cells)
493 "Grid.DownstreamCells" + std::to_string(directionIndex),
496 if (downstreamcells.empty())
499 if (downstreamcells.size() != downstreamPositions.size() + 1)
500 DUNE_THROW(Dumux::ParameterException,
"DownstreamCells" << std::to_string(directionIndex) <<
" must equal DownstreamPositions" << std::to_string(directionIndex) <<
" + 1");
502 for (
int c : downstreamcells)
505 DUNE_THROW(Dumux::ParameterException,
"DownstreamCells" << std::to_string(directionIndex) <<
" must have values greater than zero.");
506 cells[directionIndex].push_back(c);
510 void addDownstreamGrading_(
const int directionIndex,
511 const ScalarVector& downstreamPositions,
512 std::array<ScalarVector, dim>& gridPositions,
513 std::array<ScalarVector, dim>& grading)
515 const ScalarVector downstreamGrading =
getParamFromGroup<ScalarVector>(modelParamGroup_,
"Grid.DownstreamGrading" + std::to_string(directionIndex), ScalarVector{});
517 if (!downstreamGrading.empty())
519 if (downstreamGrading.size() != downstreamPositions.size() + 1)
520 DUNE_THROW(Dune::RangeError,
"DownstreamGrading" << std::to_string(directionIndex) <<
" must equal DownstreamPositions" << std::to_string(directionIndex) <<
" + 1");
522 const int offSet = gridPositions[directionIndex].size() - downstreamPositions.size() - 2;
523 for (
int i = 0; i < downstreamPositions.size() + 1; ++i)
524 grading[directionIndex][offSet + i] = downstreamGrading[i];
532 template<
class Po
intsOnLine>
533 void addCouplingPositions_(
const int directionIndex,
534 std::array<ScalarVector, dim>& positions,
535 const PointsOnLine& points,
536 std::array<std::optional<ScalarVector>, dim>& interFacePositions,
537 const GlobalPosition& gridLowerLeft,
538 const GlobalPosition& gridUpperRight)
541 interFacePositions[directionIndex] = ScalarVector{};
544 for (
const auto& point : points)
546 const auto left = point.pos - point.radius;
547 const auto right = point.pos + point.radius;
549 if (left < positions[directionIndex].back())
550 DUNE_THROW(Dune::RangeError,
"Pore body radii are too large, they intersect!");
552 if (left > gridLowerLeft[directionIndex])
553 positions[directionIndex].push_back(left);
555 if (right < gridUpperRight[directionIndex])
556 positions[directionIndex].push_back(right);
558 interFacePositions[directionIndex]->push_back(left);
559 interFacePositions[directionIndex]->push_back(right);
560 assert(interFacePositions[directionIndex].has_value());
564 template<
class Po
intsOnLine>
565 void addCouplingCells_(
const int directionIndex,
566 std::array<IntVector, dim>& cells,
567 const PointsOnLine& points)
571 const int fixedCellsBetweenPores =
getParamFromGroup<int>(modelParamGroup_,
"Grid.FixedCellsBetweenPores", -1);
574 for (
int i = 0; i < points.size(); ++i)
576 cells[directionIndex].push_back(cellsPerPore);
577 if (i < points.size() -1)
579 if (fixedCellsBetweenPores > 0)
580 cells[directionIndex].push_back(fixedCellsBetweenPores);
585 const auto spacingLeft = points[i].radius*2.0 / cellsPerPore;
586 const auto spacingRight = points[i+1].radius*2.0 / cellsPerPore;
587 const auto avgSpacing = (spacingLeft + spacingRight) / 2;
588 const auto lengthBetween = (points[i+1].pos - (points[i+1].radius))
589 - (points[i].pos + (points[i].radius));
590 const int cellsBetween = std::ceil(lengthBetween / avgSpacing);
591 cells[directionIndex].push_back(cellsBetween);
601 void addNormalPositions_(
const int directionIndex,
602 const ScalarVector& normalPositions,
603 std::array<ScalarVector, dim>& gridPositions,
604 const GlobalPosition& gridUpperRight)
606 if (!normalPositions.empty())
608 for (
const Scalar pos : normalPositions)
610 if ((pos > gridPositions[directionIndex].back()) && (pos < gridUpperRight[directionIndex]))
611 gridPositions[directionIndex].push_back(pos);
613 DUNE_THROW(Dune::RangeError,
"Make sure to set ascending normal positions");
618 void addNormalCells_(
const int directionIndex,
619 const ScalarVector& normalPositions,
620 std::array<IntVector, dim>& cells)
624 if (cellsNormal.size() != normalPositions.size() + 1)
625 DUNE_THROW(Dumux::ParameterException,
"Cells" << std::to_string(directionIndex) <<
" must be of size " << normalPositions.size() + 1);
627 for (
int c : cellsNormal)
628 cells[directionIndex].push_back(c);
631 void addNormalGrading_(
const int directionIndex,
632 const ScalarVector& normalPositions,
633 std::array<ScalarVector, dim>& grading)
637 if (!normalGrading.empty())
639 if (normalGrading.size() != normalPositions.size() + 1)
640 DUNE_THROW(Dune::RangeError,
"Grading" << std::to_string(directionIndex) <<
" must be of size " << normalPositions.size() + 1);
642 for (
int i = 0; i < normalPositions.size() + 1; ++i)
643 grading[directionIndex][i] = normalGrading[i];
648 std::string modelParamGroup_ =
"";
649 GridConstructionData gridConstructionData_;