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>
412 const ScalarVector& upstreamPositions,
413 std::array<ScalarVector, dim>& positions,
414 const PointsOnLine& points)
416 if (!upstreamPositions.empty())
419 for (
const Scalar pos : upstreamPositions)
421 if ((pos < points[0].pos - points[0].radius) && (pos > gridLowerLeft))
424 DUNE_THROW(Dune::RangeError,
"Make sure to set positions only in the inlet");
430 const ScalarVector& upstreamPositions,
431 std::array<IntVector, dim>& cells)
437 if (cellsUpstream.empty())
440 if (cellsUpstream.size() != upstreamPositions.size() + 1)
443 for (
int c : cellsUpstream)
452 const ScalarVector& upstreamPositions,
453 std::array<ScalarVector, dim>& grading)
455 if (upstreamPositions.empty())
460 if (!upstreamGrading.empty())
462 if (upstreamGrading.size() != upstreamPositions.size() + 1)
463 DUNE_THROW(Dune::RangeError,
"UpstreamGrading" << std::to_string(
directionIndex) <<
" must equal UpstreamPositions" << std::to_string(
directionIndex) <<
" + 1");
465 for (
int i = 0; i < upstreamPositions.size() + 1; ++i)
475 const ScalarVector& downstreamPositions,
476 std::array<ScalarVector, dim>& gridPositions,
477 const GlobalPosition& gridUpperRight)
479 if (!downstreamPositions.empty())
481 for (
const Scalar pos : downstreamPositions)
486 DUNE_THROW(Dune::RangeError,
"Make sure to set ascending positions only in the outlet");
492 const ScalarVector& downstreamPositions,
493 std::array<IntVector, dim>& cells)
499 if (downstreamcells.empty())
502 if (downstreamcells.size() != downstreamPositions.size() + 1)
505 for (
int c : downstreamcells)
514 const ScalarVector& downstreamPositions,
515 std::array<ScalarVector, dim>& gridPositions,
516 std::array<ScalarVector, dim>& grading)
518 if (downstreamPositions.empty())
523 if (!downstreamGrading.empty())
525 if (downstreamGrading.size() != downstreamPositions.size() + 1)
526 DUNE_THROW(Dune::RangeError,
"DownstreamGrading" << std::to_string(
directionIndex) <<
" must equal DownstreamPositions" << std::to_string(
directionIndex) <<
" + 1");
528 const int offSet = gridPositions[
directionIndex].size() - downstreamPositions.size() - 2;
529 for (
int i = 0; i < downstreamPositions.size() + 1; ++i)
538 template<
class Po
intsOnLine>
540 std::array<ScalarVector, dim>& positions,
541 const PointsOnLine& points,
542 std::array<std::optional<ScalarVector>, dim>& interFacePositions,
543 const GlobalPosition& gridLowerLeft,
544 const GlobalPosition& gridUpperRight)
550 for (
const auto& point : points)
552 const auto left = point.pos - point.radius;
553 const auto right = point.pos + point.radius;
556 DUNE_THROW(Dune::RangeError,
"Pore body radii are too large, they intersect!");
570 template<
class Po
intsOnLine>
572 std::array<IntVector, dim>& cells,
573 const PointsOnLine& points)
577 const int fixedCellsBetweenPores =
getParamFromGroup<int>(modelParamGroup_,
"Grid.FixedCellsBetweenPores", -1);
580 for (
int i = 0; i < points.size(); ++i)
583 if (i < points.size() -1)
585 if (fixedCellsBetweenPores > 0)
591 const auto spacingLeft = points[i].radius*2.0 / cellsPerPore;
592 const auto spacingRight = points[i+1].radius*2.0 / cellsPerPore;
593 const auto avgSpacing = (spacingLeft + spacingRight) / 2;
594 const auto lengthBetween = (points[i+1].pos - (points[i+1].radius))
595 - (points[i].pos + (points[i].radius));
596 const int cellsBetween = std::ceil(lengthBetween / avgSpacing);
608 const ScalarVector& normalPositions,
609 std::array<ScalarVector, dim>& gridPositions,
610 const GlobalPosition& gridUpperRight)
612 if (!normalPositions.empty())
614 for (
const Scalar pos : normalPositions)
619 DUNE_THROW(Dune::RangeError,
"Make sure to set ascending normal positions");
625 const ScalarVector& normalPositions,
626 std::array<IntVector, dim>& cells)
630 if (cellsNormal.size() != normalPositions.size() + 1)
633 for (
int c : cellsNormal)
638 const ScalarVector& normalPositions,
639 std::array<ScalarVector, dim>& grading)
643 if (!normalGrading.empty())
645 if (normalGrading.size() != normalPositions.size() + 1)
646 DUNE_THROW(Dune::RangeError,
"Grading" << std::to_string(
directionIndex) <<
" must be of size " << normalPositions.size() + 1);
648 for (
int i = 0; i < normalPositions.size() + 1; ++i)
654 std::string modelParamGroup_ =
"";
655 GridConstructionData gridConstructionData_;