3.6-git
DUNE for Multi-{Phase, Component, Scale, Physics, ...} flow and transport in porous media
Loading...
Searching...
No Matches
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).
Class to calculate the closest distance from a point to a given set of geometries describing the doma...
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
@ vertex
Definition fieldtype.hh:35
@ element
Definition fieldtype.hh:35
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
Definition common/properties.hh:100
Helper class to create (named and comparable) tagged types Tags any given type. The tagged type is eq...
Definition tag.hh:42
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
Class to calculate the closest distance from a point to a given set of geometries describing the doma...
Definition distancefield.hh:45