38 using GridView =
typename GridGeometry::GridView;
40 using SubControlVolumeFace =
typename GridGeometry::SubControlVolumeFace;
41 using FVElementGeometry =
typename GridGeometry::LocalView;
42 using Element =
typename GridGeometry::GridView::template Codim<0>::Entity;
43 using Scalar =
typename GridView::Grid::ctype;
44 using GlobalPosition =
typename SubControlVolumeFace::GlobalPosition;
46 static constexpr int dim = GridView::dimension;
47 static constexpr int dimWorld = GridView::dimensionworld;
48 static_assert(dim == dimWorld,
"Wall distances cannot be computed for embedded surface or network domains.");
50 using CornerStorage = Dune::ReservedVector<GlobalPosition, (1<<(GridView::dimension-1))>;
57 SimpleGeometry() =
default;
58 SimpleGeometry(CornerStorage&& corners)
59 : corners_(std::move(corners))
62 for (
int i = 0; i < corners_.size(); ++i)
63 center_ += corners_[i];
64 center_ /= corners_.size();
67 using GlobalCoordinate = GlobalPosition;
68 using ctype =
typename GlobalCoordinate::value_type;
69 static constexpr int coorddimension = GridView::dimensionworld;
70 static constexpr int mydimension = GridView::dimension-1;
72 std::size_t corners()
const
73 {
return corners_.size(); }
75 const auto& corner(
int i)
const
76 {
return corners_[i]; }
78 const auto& center()
const
82 CornerStorage corners_;
83 GlobalCoordinate center_;
89 GridIndexType scvfIdx;
90 GlobalPosition scvfOuterNormal;
94 struct ElementCenters {};
95 struct VertexCenters {};
108 template<
class LocationTag,
class ScvfSelectionFunctor>
109 WallDistance(std::shared_ptr<const GridGeometry> gridGeometry, LocationTag tag,
const ScvfSelectionFunctor& select)
110 : gridGeometry_(gridGeometry)
112 initializeWallDistance_(select, tag);
121 template<
class LocationTag>
122 WallDistance(std::shared_ptr<const GridGeometry> gridGeometry, LocationTag tag)
123 :
WallDistance(gridGeometry, tag, [](const FVElementGeometry& fvGeometry, const SubControlVolumeFace& scvf) {
return true; }) {}
126 template<
class LocationTag,
class ScvfSelectionFunctor>
127 WallDistance(
const GridGeometry& gridGeometry, LocationTag tag,
const ScvfSelectionFunctor& select)
128 :
WallDistance(
Dune::stackobject_to_shared_ptr(gridGeometry), tag, select) {}
131 template<
class LocationTag>
141 {
return distance_; }
149 {
return wallData_; }
158 template<
class Cons
iderFaceFunction,
class LocationTag>
159 void initializeWallDistance_(
const ConsiderFaceFunction& considerFace, LocationTag loc)
162 ? gridGeometry_->gridView().size(0)
163 : gridGeometry_->gridView().size(dim);
165 wallData_.resize(numSamplingPoints);
166 distance_.resize(numSamplingPoints, std::numeric_limits<Scalar>::max());
168 std::vector<SimpleGeometry> wallGeometries;
169 wallGeometries.reserve(gridGeometry_->numBoundaryScvf());
171 std::vector<WallData> tempWallData;
172 tempWallData.reserve(gridGeometry_->numBoundaryScvf());
175 auto fvGeometry =
localView(*gridGeometry_);
176 for (
const auto& element : elements(gridGeometry_->gridView(),
Dune::Partitions::interior))
178 fvGeometry.bindElement(element);
179 if (!fvGeometry.hasBoundaryScvf())
182 const auto eIdx = gridGeometry_->elementMapper().index(element);
184 for (
const auto& scvf : scvfs(fvGeometry))
186 if (scvf.boundary() && considerFace(fvGeometry, scvf))
188 const auto& geo = fvGeometry.geometry(scvf);
189 CornerStorage corners;
190 for (
int i = 0; i < geo.corners(); ++i)
191 corners.push_back(geo.corner(i));
193 wallGeometries.emplace_back(std::move(corners));
195 eIdx, scvf.index(), scvf.unitOuterNormal(), gridGeometry_->gridView().comm().rank()
204 const bool isParallel = gridGeometry_->gridView().comm().size() > 1;
205 std::vector<SimpleGeometry> globalWallGeometries;
206 std::vector<WallData> globalTempWallData;
207 const auto distanceField = [&]
211 const auto& communication = gridGeometry_->gridView().comm();
212 const int totalNumberOfBoundaryGeometries = communication.sum(wallGeometries.size());
213 globalWallGeometries.resize(totalNumberOfBoundaryGeometries);
214 globalTempWallData.resize(totalNumberOfBoundaryGeometries);
217 std::vector<int> numGeosPerProcLocal{
static_cast<int>(wallGeometries.size())};
218 std::vector<int> numGeosPerProcGlobal(communication.size());
219 communication.allgather(numGeosPerProcLocal.data(), 1, numGeosPerProcGlobal.data());
221 std::vector<int> disp(communication.size(), 0);
222 disp[1] = numGeosPerProcGlobal[0];
223 for (
int i = 2; i < numGeosPerProcGlobal.size(); ++i)
224 disp[i] = disp[i-1] + numGeosPerProcGlobal[i-1];
227 communication.allgatherv(
228 wallGeometries.data(),
229 wallGeometries.size(),
230 globalWallGeometries.data(),
231 numGeosPerProcGlobal.data(),
235 communication.allgatherv(
238 globalTempWallData.data(),
239 numGeosPerProcGlobal.data(),
244 return DistanceField<SimpleGeometry>(globalWallGeometries);
247 return DistanceField<SimpleGeometry>(wallGeometries);
250 const DistanceField<SimpleGeometry> distanceField(wallGeometries);
254 std::vector<GlobalPosition> points(numSamplingPoints);
256 for (
const auto& element : elements(gridGeometry_->gridView()))
259 for (
const auto& vertex : vertices(gridGeometry_->gridView()))
260 points[gridGeometry_->vertexMapper().index(
vertex)] =
vertex.geometry().corner(0);
265 const auto kernel = [&](std::size_t eIdx){
266 const auto [d, idx] = distanceField.distanceAndIndex(points[eIdx]);
269 wallData_[eIdx] = isParallel ? globalTempWallData[idx] : tempWallData[idx];
271 wallData_[eIdx] = tempWallData[idx];
275 runKernel_(numSamplingPoints, kernel);
279 const auto kernel = [&](std::size_t vIdx){
280 const auto [d, idx] = distanceField.distanceAndIndex(points[vIdx]);
283 wallData_[vIdx] = isParallel ? globalTempWallData[idx] : tempWallData[idx];
285 wallData_[vIdx] = tempWallData[idx];
289 runKernel_(numSamplingPoints, kernel);
293 template<
class Kernel>
294 void runKernel_(std::size_t size,
const Kernel& kernel)
300 for (std::size_t i = 0; i < size; ++i)
kernel(i);
303 std::vector<Scalar> distance_;
304 std::vector<WallData> wallData_;
305 std::shared_ptr<const GridGeometry> gridGeometry_;