version 3.11-dev
Loading...
Searching...
No Matches
columnmapping.hh
Go to the documentation of this file.
1// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2// vi: set et ts=4 sw=4 sts=4:
3//
4// SPDX-FileCopyrightText: Copyright © DuMux Project contributors, see AUTHORS.md in root folder
5// SPDX-License-Identifier: GPL-3.0-or-later
6//
12
13#ifndef DUMUX_TWOPVE_COLUMN_MAPPING_HH
14#define DUMUX_TWOPVE_COLUMN_MAPPING_HH
15
16#include <algorithm>
17#include <array>
18#include <cmath>
19#include <cstddef>
20#include <memory>
21#include <vector>
22
23#include <dune/common/exceptions.hh>
24#include <dune/common/fvector.hh>
25#include <dune/grid/common/rangegenerators.hh>
26
28
29namespace Dumux {
30
37template<class CoarseGridGeometry, class FineGridGeometry, class Scalar>
39{
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;
45
46public:
47 using Column = std::vector<Element>;
48
49 TwoPVEColumnMapping(std::shared_ptr<const CoarseGridGeometry> gridGeometryCoarse,
50 std::shared_ptr<const FineGridGeometry> gridGeometryFine)
51 {
52 build_(*gridGeometryCoarse, *gridGeometryFine);
53 }
54
60 const Column& column(std::size_t idxCoarse) const
61 {
62 return coarseToFine_.at(idxCoarse);
63 }
64
70 std::size_t coarseIndex(std::size_t idxFine) const
71 {
72 return fineToCoarse_.at(idxFine);
73 }
74
78 std::size_t numberOfColumns() const noexcept
79 {
80 return coarseToFine_.size();
81 }
82
83private:
84
91 void build_(const CoarseGridGeometry& gridGeometryCoarse,
92 const FineGridGeometry& gridGeometryFine)
93 {
94 const std::size_t numberOfCoarseElements = gridGeometryCoarse.elementMapper().size();
95 const std::size_t numberOfFineElements = gridGeometryFine.elementMapper().size();
96
97 if (numberOfCoarseElements == 0)
98 DUNE_THROW(Dune::InvalidStateException, "Cannot construct columns for an empty coarse grid");
99
100 coarseToFine_.clear();
101 coarseToFine_.resize(numberOfCoarseElements);
102
103 fineToCoarse_.clear();
104 fineToCoarse_.resize(numberOfFineElements);
105
106 for (const auto& elementFine : elements(gridGeometryFine.gridView()))
107 {
108 const auto idxFine = gridGeometryFine.elementMapper().index(elementFine);
109 const auto fineCenter = elementFine.geometry().center();
110
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)
122 {
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]);
126 using std::abs;
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");
129 }
130
131 coarseToFine_[idxCoarse].push_back(elementFine);
132 fineToCoarse_[idxFine] = idxCoarse;
133 }
134
135 sortColumns_();
136 sanityCheckColumn_(numberOfCoarseElements, numberOfFineElements);
137 }
138
140 template<class Geometry>
141 static std::array<Scalar, 2> axisBounds_(const Geometry& geometry, int axis)
142 {
143 std::array<Scalar, 2> bounds{geometry.corner(0)[axis], geometry.corner(0)[axis]};
144 for (int corner = 1; corner < geometry.corners(); ++corner)
145 {
146 bounds[0] = std::min(bounds[0], geometry.corner(corner)[axis]);
147 bounds[1] = std::max(bounds[1], geometry.corner(corner)[axis]);
148 }
149 return bounds;
150 }
151
153 void sortColumns_()
154 {
155 static constexpr int verticalAxis = GridView::dimensionworld - 1;
156 for (auto& column : coarseToFine_)
157 {
158 std::sort(column.begin(), column.end(), [](const Element& a, const Element& b)
159 {
160 return a.geometry().center()[verticalAxis] < b.geometry().center()[verticalAxis];
161 });
162 }
163 }
164
171 void sanityCheckColumn_(const std::size_t numberOfCoarseElements,
172 const std::size_t numberOfFineElements)
173 {
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;
178
179 for (std::size_t coarseIdx = 0; coarseIdx < coarseToFine_.size(); ++coarseIdx)
180 {
181 const auto& column = coarseToFine_[coarseIdx];
182
183 // check size
184 if (column.size() != expectedColumnSize)
185 DUNE_THROW(Dune::InvalidStateException, "Unexpected number of fine elements in column " << coarseIdx);
186
187 // check ordering
188 for (std::size_t i = 1; i < column.size(); ++i)
189 {
190 const Scalar previousZ = column[i - 1].geometry().center()[verticalAxis];
191 const Scalar currentZ = column[i].geometry().center()[verticalAxis];
192
193 if (!(previousZ < currentZ))
194 DUNE_THROW(Dune::InvalidStateException, "Fine elements do not have strictly increasing vertical coordinates in column " << coarseIdx);
195 }
196 }
197 }
198
199 std::vector<Column> coarseToFine_;
200 std::vector<std::size_t> fineToCoarse_;
201};
202
203} // end namespace Dumux
204
205#endif
const Column & column(std::size_t idxCoarse) const
Returns the column of fine-level elements given a coarse-level index.
Definition columnmapping.hh:60
std::size_t numberOfColumns() const noexcept
Returns the number of coarse-level columns.
Definition columnmapping.hh:78
std::vector< Element > Column
Definition columnmapping.hh:47
TwoPVEColumnMapping(std::shared_ptr< const CoarseGridGeometry > gridGeometryCoarse, std::shared_ptr< const FineGridGeometry > gridGeometryFine)
Definition columnmapping.hh:49
std::size_t coarseIndex(std::size_t idxFine) const
Returns the coarse-level column index the given fine-level index belongs to.
Definition columnmapping.hh:70
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
Algorithms that finds which geometric entities intersect.
typename ScalarType< X >::Type Scalar
Definition odesolver.hh:52
Definition adapt.hh:17