40 using GridView =
typename FineGridGeometry::GridView;
41 using CoarseGridView =
typename CoarseGridGeometry::GridView;
42 static_assert(CoarseGridView::dimension + 1 == GridView::dimension);
43 static_assert(CoarseGridView::dimensionworld + 1 == GridView::dimensionworld);
44 using Element =
typename GridView::template Codim<0>::Entity;
50 std::shared_ptr<const FineGridGeometry> gridGeometryFine)
52 build_(*gridGeometryCoarse, *gridGeometryFine);
62 return coarseToFine_.at(idxCoarse);
72 return fineToCoarse_.at(idxFine);
80 return coarseToFine_.size();
91 void build_(
const CoarseGridGeometry& gridGeometryCoarse,
92 const FineGridGeometry& gridGeometryFine)
94 const std::size_t numberOfCoarseElements = gridGeometryCoarse.elementMapper().size();
95 const std::size_t numberOfFineElements = gridGeometryFine.elementMapper().size();
97 if (numberOfCoarseElements == 0)
98 DUNE_THROW(Dune::InvalidStateException,
"Cannot construct columns for an empty coarse grid");
100 coarseToFine_.clear();
101 coarseToFine_.resize(numberOfCoarseElements);
103 fineToCoarse_.clear();
104 fineToCoarse_.resize(numberOfFineElements);
106 for (
const auto& elementFine : elements(gridGeometryFine.gridView()))
108 const auto idxFine = gridGeometryFine.elementMapper().index(elementFine);
109 const auto fineCenter = elementFine.geometry().center();
111 Dune::FieldVector<Scalar, CoarseGridView::dimensionworld> horizontalCenter;
112 for (
int axis = 0; axis < CoarseGridView::dimensionworld; ++axis)
113 horizontalCenter[axis] = fineCenter[axis];
114 const auto coarseCandidates =
intersectingEntities(horizontalCenter, gridGeometryCoarse.boundingBoxTree());
115 if (coarseCandidates.empty())
116 DUNE_THROW(Dune::InvalidStateException,
"Fine element " << idxFine <<
" is not contained in a coarse element");
117 if (coarseCandidates.size() != 1)
118 DUNE_THROW(Dune::InvalidStateException,
"Fine element " << idxFine <<
" intersects more than one coarse element");
119 const auto idxCoarse = coarseCandidates.front();
120 const auto coarseGeometry = gridGeometryCoarse.element(idxCoarse).geometry();
121 for (
int axis = 0; axis < CoarseGridView::dimensionworld; ++axis)
123 const auto coarseBounds = axisBounds_(coarseGeometry, axis);
124 const auto fineBounds = axisBounds_(elementFine.geometry(), axis);
125 const Scalar tolerance = 1e-10*(coarseBounds[1] - coarseBounds[0]);
127 if (abs(coarseBounds[0] - fineBounds[0]) > tolerance || abs(coarseBounds[1] - fineBounds[1]) > tolerance)
128 DUNE_THROW(Dune::InvalidStateException,
"Coarse and fine grids must have matching horizontal cell bounds");
131 coarseToFine_[idxCoarse].push_back(elementFine);
132 fineToCoarse_[idxFine] = idxCoarse;
136 sanityCheckColumn_(numberOfCoarseElements, numberOfFineElements);
140 template<
class Geometry>
141 static std::array<Scalar, 2> axisBounds_(
const Geometry& geometry,
int axis)
143 std::array<Scalar, 2> bounds{geometry.corner(0)[axis], geometry.corner(0)[axis]};
144 for (
int corner = 1; corner < geometry.corners(); ++corner)
146 bounds[0] = std::min(bounds[0], geometry.corner(corner)[axis]);
147 bounds[1] = std::max(bounds[1], geometry.corner(corner)[axis]);
155 static constexpr int verticalAxis = GridView::dimensionworld - 1;
156 for (
auto&
column : coarseToFine_)
158 std::sort(
column.begin(),
column.end(), [](
const Element& a,
const Element& b)
160 return a.geometry().center()[verticalAxis] < b.geometry().center()[verticalAxis];
171 void sanityCheckColumn_(
const std::size_t numberOfCoarseElements,
172 const std::size_t numberOfFineElements)
174 static constexpr int verticalAxis = GridView::dimensionworld - 1;
175 if (numberOfFineElements == 0 || numberOfFineElements % numberOfCoarseElements != 0)
176 DUNE_THROW(Dune::InvalidStateException,
"Each coarse element must map to a nonempty column of equal size");
177 const auto expectedColumnSize = numberOfFineElements / numberOfCoarseElements;
179 for (std::size_t coarseIdx = 0; coarseIdx < coarseToFine_.size(); ++coarseIdx)
181 const auto&
column = coarseToFine_[coarseIdx];
184 if (
column.size() != expectedColumnSize)
185 DUNE_THROW(Dune::InvalidStateException,
"Unexpected number of fine elements in column " << coarseIdx);
188 for (std::size_t i = 1; i <
column.size(); ++i)
190 const Scalar previousZ =
column[i - 1].geometry().center()[verticalAxis];
191 const Scalar currentZ =
column[i].geometry().center()[verticalAxis];
193 if (!(previousZ < currentZ))
194 DUNE_THROW(Dune::InvalidStateException,
"Fine elements do not have strictly increasing vertical coordinates in column " << coarseIdx);
199 std::vector<Column> coarseToFine_;
200 std::vector<std::size_t> fineToCoarse_;
std::vector< std::pair< int, std::size_t > > intersectingEntities(const Dune::FieldVector< ctype, dimworld > &point, const DistributedBoundingBoxTree< EntitySet > &tree, bool isCartesianGrid=false, bool onlyOwned=true)
Compute all intersections between entities and a point on a distributed tree.
Definition distributedintersectingentities.hh:81