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]; }
 
   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(),
 
  254        std::vector<GlobalPosition> points(numSamplingPoints);
 
  256            for (
const auto& element : elements(gridGeometry_->gridView()))
 
  257                points[gridGeometry_->elementMapper().index(element)] = 
element.geometry().center();
 
  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_;