3.6-git
DUNE for Multi-{Phase, Component, Scale, Physics, ...} flow and transport in porous media
walldistance.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 * See the file COPYING for full copying permissions. *
5 * *
6 * This program is free software: you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by *
8 * the Free Software Foundation, either version 3 of the License, or *
9 * (at your option) any later version. *
10 * *
11 * This program is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 * GNU General Public License for more details. *
15 * *
16 * You should have received a copy of the GNU General Public License *
17 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
18 *****************************************************************************/
24#ifndef DUMUX_DISCRETIZATION_WALL_DISTANCE_HH
25#define DUMUX_DISCRETIZATION_WALL_DISTANCE_HH
26
27#include <vector>
28
29#include <dune/common/parallel/mpihelper.hh>
30#include <dune/common/shared_ptr.hh>
31#include <dune/common/reservedvector.hh>
32#include <dune/grid/common/partitionset.hh>
33
34#include <dumux/common/tag.hh>
38
39namespace Dumux {
40
47template<class GridGeometry, template<class> class DistanceField = AABBDistanceField>
49{
50 using GridView = typename GridGeometry::GridView;
51 using GridIndexType = typename IndexTraits<GridView>::GridIndex;
52 using SubControlVolumeFace = typename GridGeometry::SubControlVolumeFace;
53 using FVElementGeometry = typename GridGeometry::LocalView;
54 using Element = typename GridGeometry::GridView::template Codim<0>::Entity;
55 using Scalar = typename GridView::Grid::ctype;
56 using GlobalPosition = typename SubControlVolumeFace::GlobalPosition;
57
58 static constexpr int dim = GridView::dimension;
59 static constexpr int dimWorld = GridView::dimensionworld;
60 static_assert(dim == dimWorld, "Wall distances cannot be computed for embedded surface or network domains.");
61
62 using CornerStorage = Dune::ReservedVector<GlobalPosition, (1<<(GridView::dimension-1))>;
63
64 // We use a simplified geometry type here which allows much easier MPI communication
65 // for parallel runs compared to the Dune geometry types (due to fixed-size storage).
66 // This type only implements a minimal part of the Geometry interface.
67 struct SimpleGeometry
68 {
69 SimpleGeometry() = default;
70 SimpleGeometry(CornerStorage&& corners)
71 : corners_(std::move(corners))
72 , center_(0.0)
73 {
74 for (int i = 0; i < corners_.size(); ++i)
75 center_ += corners_[i];
76 center_ /= corners_.size();
77 }
78
79 using GlobalCoordinate = GlobalPosition;
80 using ctype = typename GlobalCoordinate::value_type;
81 static constexpr int coorddimension = GridView::dimensionworld;
82 static constexpr int mydimension = GridView::dimension-1;
83
84 std::size_t corners() const
85 { return corners_.size(); }
86
87 const auto& corner(int i) const
88 { return corners_[i]; }
89
90 const auto& center() const
91 { return center_; }
92
93 private:
94 CornerStorage corners_;
95 GlobalCoordinate center_;
96 };
97
98 struct WallDataImpl
99 {
100 GridIndexType eIdx;
101 GridIndexType scvfIdx;
102 GlobalPosition scvfOuterNormal;
103 int rank; // for parallel runs
104 };
105
106 struct ElementCenters {};
107 struct VertexCenters {};
108
109public:
112 using WallData = WallDataImpl;
113
120 template<class LocationTag, class ScvfSelectionFunctor>
121 WallDistance(std::shared_ptr<const GridGeometry> gridGeometry, LocationTag tag, const ScvfSelectionFunctor& select)
122 : gridGeometry_(gridGeometry)
123 {
124 initializeWallDistance_(select, tag);
125 }
126
133 template<class LocationTag>
134 WallDistance(std::shared_ptr<const GridGeometry> gridGeometry, LocationTag tag)
135 : WallDistance(gridGeometry, tag, [](const FVElementGeometry& fvGeometry, const SubControlVolumeFace& scvf) { return true; }) {}
136
138 template<class LocationTag, class ScvfSelectionFunctor>
139 WallDistance(const GridGeometry& gridGeometry, LocationTag tag, const ScvfSelectionFunctor& select)
140 : WallDistance(Dune::stackobject_to_shared_ptr(gridGeometry), tag, select) {}
141
143 template<class LocationTag>
144 WallDistance(const GridGeometry& gridGeometry, LocationTag tag)
145 : WallDistance(Dune::stackobject_to_shared_ptr(gridGeometry), tag) {}
146
152 const std::vector<Scalar>& wallDistance() const
153 { return distance_; }
154
160 const std::vector<WallData>& wallData() const
161 { return wallData_; }
162
163private:
170 template<class ConsiderFaceFunction, class LocationTag>
171 void initializeWallDistance_(const ConsiderFaceFunction& considerFace, LocationTag loc)
172 {
173 const std::size_t numSamplingPoints = (loc == atElementCenters)
174 ? gridGeometry_->gridView().size(0)
175 : gridGeometry_->gridView().size(dim);
176 // Reset the containers.
177 wallData_.resize(numSamplingPoints);
178 distance_.resize(numSamplingPoints, std::numeric_limits<Scalar>::max());
179
180 std::vector<SimpleGeometry> wallGeometries;
181 wallGeometries.reserve(gridGeometry_->numBoundaryScvf());
182
183 std::vector<WallData> tempWallData;
184 tempWallData.reserve(gridGeometry_->numBoundaryScvf());
185
186 // Loop over all elements: find all wall scvfs.
187 auto fvGeometry = localView(*gridGeometry_);
188 for (const auto& element : elements(gridGeometry_->gridView(), Dune::Partitions::interior))
189 {
190 fvGeometry.bindElement(element);
191 if (!fvGeometry.hasBoundaryScvf())
192 continue;
193
194 const auto eIdx = gridGeometry_->elementMapper().index(element);
195
196 for (const auto& scvf : scvfs(fvGeometry))
197 {
198 if (scvf.boundary() && considerFace(fvGeometry, scvf))
199 {
200 const auto& geo = fvGeometry.geometry(scvf);
201 CornerStorage corners;
202 for (int i = 0; i < geo.corners(); ++i)
203 corners.push_back(geo.corner(i));
204
205 wallGeometries.emplace_back(std::move(corners));
206 tempWallData.push_back(WallData{
207 eIdx, scvf.index(), scvf.unitOuterNormal(), gridGeometry_->gridView().comm().rank()
208 });
209 }
210 }
211 }
212
213#if HAVE_MPI
214 // Handle parallel runs. We need to prepare a global vector of wall geometries,
215 // containing the wall geometries of each process in order to get a correct distance field.
216 const bool isParallel = gridGeometry_->gridView().comm().size() > 1;
217 std::vector<SimpleGeometry> globalWallGeometries;
218 std::vector<WallData> globalTempWallData;
219 const auto distanceField = [&]
220 {
221 if (isParallel)
222 {
223 const auto& communication = gridGeometry_->gridView().comm();
224 const int totalNumberOfBoundaryGeometries = communication.sum(wallGeometries.size());
225 globalWallGeometries.resize(totalNumberOfBoundaryGeometries);
226 globalTempWallData.resize(totalNumberOfBoundaryGeometries);
227
228 // prepare a displacement vector
229 std::vector<int> numGeosPerProcLocal{static_cast<int>(wallGeometries.size())};
230 std::vector<int> numGeosPerProcGlobal(communication.size());
231 communication.allgather(numGeosPerProcLocal.data(), 1, numGeosPerProcGlobal.data());
232
233 std::vector<int> disp(communication.size(), 0);
234 disp[1] = numGeosPerProcGlobal[0];
235 for (int i = 2; i < numGeosPerProcGlobal.size(); ++i)
236 disp[i] = disp[i-1] + numGeosPerProcGlobal[i-1];
237
238 // concatenate the wall geometries and temp scvf data of each process into a global vector
239 communication.allgatherv(
240 wallGeometries.data(),
241 wallGeometries.size(),
242 globalWallGeometries.data(),
243 numGeosPerProcGlobal.data(),
244 disp.data()
245 );
246
247 communication.allgatherv(
248 tempWallData.data(),
249 tempWallData.size(),
250 globalTempWallData.data(),
251 numGeosPerProcGlobal.data(),
252 disp.data()
253 );
254
255 // pass the global vector of wall geometries to the distance field
256 return DistanceField<SimpleGeometry>(globalWallGeometries);
257 }
258 else
259 return DistanceField<SimpleGeometry>(wallGeometries);
260 }();
261#else
262 const DistanceField<SimpleGeometry> distanceField(wallGeometries);
263#endif
264
265 // compute sampling points
266 std::vector<GlobalPosition> points(numSamplingPoints);
267 if (loc == atElementCenters)
268 for (const auto& element : elements(gridGeometry_->gridView()))
269 points[gridGeometry_->elementMapper().index(element)] = element.geometry().center();
270 else
271 for (const auto& vertex : vertices(gridGeometry_->gridView()))
272 points[gridGeometry_->vertexMapper().index(vertex)] = vertex.geometry().corner(0);
273
274 // get the actual distances (this is the most expensive part)
275 if (loc == atElementCenters)
276 {
277 const auto kernel = [&](std::size_t eIdx){
278 const auto [d, idx] = distanceField.distanceAndIndex(points[eIdx]);
279 distance_[eIdx] = d;
280#if HAVE_MPI
281 wallData_[eIdx] = isParallel ? globalTempWallData[idx] : tempWallData[idx];
282#else
283 wallData_[eIdx] = tempWallData[idx];
284#endif
285 };
286
287 runKernel_(numSamplingPoints, kernel);
288 }
289 else
290 {
291 const auto kernel = [&](std::size_t vIdx){
292 const auto [d, idx] = distanceField.distanceAndIndex(points[vIdx]);
293 distance_[vIdx] = d;
294#if HAVE_MPI
295 wallData_[vIdx] = isParallel ? globalTempWallData[idx] : tempWallData[idx];
296#else
297 wallData_[vIdx] = tempWallData[idx];
298#endif
299 };
300
301 runKernel_(numSamplingPoints, kernel);
302 }
303 }
304
305 template<class Kernel>
306 void runKernel_(std::size_t size, const Kernel& kernel)
307 {
308 // parallelize, if we have enough work (enough evaluation points)
309 if (size > 10000)
310 Dumux::parallelFor(size, [&](const std::size_t i){ kernel(i); });
311 else
312 for (std::size_t i = 0; i < size; ++i) kernel(i);
313 }
314
315 std::vector<Scalar> distance_;
316 std::vector<WallData> wallData_;
317 std::shared_ptr<const GridGeometry> gridGeometry_;
318};
319
320} // end namespace Dumux
321
322#endif
Helper class to create (named and comparable) tagged types.
Defines the index types used for grid and local indices.
Parallel for loop (multithreading)
Corners::value_type center(const Corners &corners)
The center of a given list of corners.
Definition: center.hh:36
AABBDistanceField< Geometry > DistanceField
Class to calculate the closest distance from a point to a given set of geometries describing the doma...
Definition: distancefield.hh:129
GridCache::LocalView localView(const GridCache &gridCache)
Free function to get the local view of a grid cache object.
Definition: localview.hh:38
void parallelFor(const std::size_t count, const FunctorType &functor)
A parallel for loop (multithreading)
Definition: parallel_for.hh:172
Adaption of the non-isothermal two-phase two-component flow model to problems with CO2.
Definition: adapt.hh:29
Definition: deprecated.hh:149
constexpr Kernel kernel
Definition: couplingmanager1d3d_kernel.hh:50
typename GridView::IndexSet::IndexType GridIndex
Definition: indextraits.hh:39
Helper class to create (named and comparable) tagged types Tags any given type. The tagged type is eq...
Definition: tag.hh:42
Class to calculate the wall distance at every element or vertex of a grid.
Definition: walldistance.hh:49
static constexpr auto atVertexCenters
Definition: walldistance.hh:111
const std::vector< Scalar > & wallDistance() const
Returns a vector storing the distance from each DOF location to the nearest wall. For the atElementCe...
Definition: walldistance.hh:152
WallDistance(std::shared_ptr< const GridGeometry > gridGeometry, LocationTag tag)
Constructs a new wall distance object.
Definition: walldistance.hh:134
WallDistance(const GridGeometry &gridGeometry, LocationTag tag, const ScvfSelectionFunctor &select)
caller has to make sure the lifetime of grid geometry exceeds the lifetime of wall distance
Definition: walldistance.hh:139
WallDataImpl WallData
Definition: walldistance.hh:112
static constexpr auto atElementCenters
Definition: walldistance.hh:110
WallDistance(std::shared_ptr< const GridGeometry > gridGeometry, LocationTag tag, const ScvfSelectionFunctor &select)
Constructs a new wall distance object.
Definition: walldistance.hh:121
const std::vector< WallData > & wallData() const
Returns a vector storing additional information about the nearest scvf on the wall (element index and...
Definition: walldistance.hh:160
WallDistance(const GridGeometry &gridGeometry, LocationTag tag)
caller has to make sure the lifetime of grid geometry exceeds the lifetime of wall distance
Definition: walldistance.hh:144