Skip to main content
  • Home
  • Development
  • Documentation
  • Donate
  • Operational login
  • Browse the archive

swh logo
SoftwareHeritage
Software
Heritage
Archive
Features
  • Search

  • Downloads

  • Save code now

  • Add forge now

  • Help

  • 062bf3d
  • /
  • VofDataUtils
  • /
  • Grid
  • /
  • DomainInfo.h
Raw File Download

To reference or cite the objects present in the Software Heritage archive, permalinks based on SoftWare Hash IDentifiers (SWHIDs) must be used.
Select below a type of object currently browsed in order to display its associated SWHID and permalink.

  • content
  • directory
content badge
swh:1:cnt:0d2dd427d06c262664494ec74b4999e390e69003
directory badge
swh:1:dir:ea777418dfe39c945fc3cd3aae27eb67872744e4

This interface enables to generate software citations, provided that the root directory of browsed objects contains a citation.cff or codemeta.json file.
Select below a type of object currently browsed in order to generate citations for them.

  • content
  • directory
(requires biblatex-software package)
Generating citation ...
(requires biblatex-software package)
Generating citation ...
DomainInfo.h
#pragma once

#include <algorithm>
#include <array>
#include <bitset>
#include <cmath>
#include <cstddef>
#include <optional>
#include <stdexcept>
#include <vector>

#include <vtkRectilinearGrid.h>
#include <vtkSmartPointer.h>
#include <vtkType.h>
#include <vtkUnsignedCharArray.h>

#include "../Math/Vector.h"
#include "GridTypes.h"

class vtkMPIController;

namespace VofFlow {
    class DomainInfo {
    public:
        struct NeighborInfo {
            int processId = 0;
            std::bitset<6> flags;
            extent_t zeroExtent{};
            bounds_t zeroBounds{};
        };

        explicit DomainInfo(vtkRectilinearGrid* grid, vtkMPIController* mpiController = nullptr);

        [[nodiscard]] inline vtkRectilinearGrid* grid() const {
            return grid_;
        }

        [[nodiscard]] inline const extent_t& localExtent() const {
            return localExtent_;
        }

        [[nodiscard]] inline const extent_t& localZeroExtent() const {
            return localZeroExtent_;
        }

        [[nodiscard]] inline const extent_t& globalExtent() const {
            return globalExtent_;
        }

        [[nodiscard]] inline const bounds_t& localBounds() const {
            return localBounds_;
        }

        [[nodiscard]] inline const bounds_t& localZeroBounds() const {
            return localZeroBounds_;
        }

        [[nodiscard]] inline const bounds_t& globalBounds() const {
            return globalBounds_;
        }

        [[nodiscard]] inline const dim_t& cellDims() const {
            return dims_;
        }

        [[nodiscard]] inline bool isUniform() const {
            return isUniform_;
        }

        [[nodiscard]] inline bool isParallel() const {
            return isParallel_;
        }

        [[nodiscard]] inline const vtkSmartPointer<vtkUnsignedCharArray>& ghostArray() const {
            return ghostArray_;
        }

        [[nodiscard]] inline const std::vector<double>& coordsX() const {
            return coordsX_;
        }

        [[nodiscard]] inline const std::vector<double>& coordsY() const {
            return coordsY_;
        }

        [[nodiscard]] inline const std::vector<double>& coordsZ() const {
            return coordsZ_;
        }

        [[nodiscard]] inline const std::vector<double>& cellSizesX() const {
            return cellSizesX_;
        }

        [[nodiscard]] inline const std::vector<double>& cellSizesY() const {
            return cellSizesY_;
        }

        [[nodiscard]] inline const std::vector<double>& cellSizesZ() const {
            return cellSizesZ_;
        }

        [[nodiscard]] inline const std::vector<double>& cellCentersX() const {
            return cellCentersX_;
        }

        [[nodiscard]] inline const std::vector<double>& cellCentersY() const {
            return cellCentersY_;
        }

        [[nodiscard]] inline const std::vector<double>& cellCentersZ() const {
            return cellCentersZ_;
        }

        [[nodiscard]] inline const std::vector<NeighborInfo>& neighbors() const {
            return neighbors_;
        }

        [[nodiscard]] inline const std::array<std::vector<int>, 6>& neighborsByDirection() const {
            return neighborsByDirection_;
        }

        [[nodiscard]] inline vtkIdType numCells() const {
            return static_cast<vtkIdType>(dims_[0]) * static_cast<vtkIdType>(dims_[1]) *
                   static_cast<vtkIdType>(dims_[2]);
        }

        [[nodiscard]] inline posCoords_t coords(int x, int y, int z) const {
            return {coordsX_[x], coordsY_[y], coordsZ_[z]};
        }

        [[nodiscard]] inline posCoords_t coords(gridCoords_t g_coords) const {
            return coords(g_coords[0], g_coords[1], g_coords[2]);
        }

        [[nodiscard]] inline vec3 coordsVec3(int x, int y, int z) const {
            return {
                static_cast<float>(coordsX_[x]),
                static_cast<float>(coordsY_[y]),
                static_cast<float>(coordsZ_[z]),
            };
        }

        [[nodiscard]] inline vec3 coordsVec3(gridCoords_t g_coords) const {
            return coordsVec3(g_coords[0], g_coords[1], g_coords[2]);
        }

        [[nodiscard]] inline posCoords_t cellSize(int g_x, int g_y, int g_z) const {
            return {cellSizesX_[g_x], cellSizesY_[g_y], cellSizesZ_[g_z]};
        }

        [[nodiscard]] inline posCoords_t cellSize(gridCoords_t g_coords) const {
            return cellSize(g_coords[0], g_coords[1], g_coords[2]);
        }

        [[nodiscard]] inline vec3 cellSizeVec3(int g_x, int g_y, int g_z) const {
            return {
                static_cast<float>(cellSizesX_[g_x]),
                static_cast<float>(cellSizesY_[g_y]),
                static_cast<float>(cellSizesZ_[g_z]),
            };
        }

        [[nodiscard]] inline vec3 cellSizeVec3(gridCoords_t g_coords) const {
            return cellSizeVec3(g_coords[0], g_coords[1], g_coords[2]);
        }

        [[nodiscard]] inline posCoords_t cellCenter(int g_x, int g_y, int g_z) const {
            return {cellCentersX_[g_x], cellCentersY_[g_y], cellCentersZ_[g_z]};
        }

        [[nodiscard]] inline posCoords_t cellCenter(gridCoords_t g_coords) const {
            return cellCenter(g_coords[0], g_coords[1], g_coords[2]);
        }

        [[nodiscard]] inline vec3 cellCenterVec3(int g_x, int g_y, int g_z) const {
            return {
                static_cast<float>(cellCentersX_[g_x]),
                static_cast<float>(cellCentersY_[g_y]),
                static_cast<float>(cellCentersZ_[g_z]),
            };
        }

        [[nodiscard]] inline vec3 cellCenterVec3(gridCoords_t g_coords) const {
            return cellCenterVec3(g_coords[0], g_coords[1], g_coords[2]);
        }

        [[nodiscard]] inline bool isInLocalExtent(const gridCoords_t& e_coords) const {
            return Grid::isInExtent(localExtent_, e_coords);
        }

        [[nodiscard]] inline bool isInLocalExtent(int e_x, int e_y, int e_z) const {
            return isInLocalExtent(gridCoords_t{e_x, e_y, e_z});
        }

        [[nodiscard]] inline bool isInZeroExtent(const gridCoords_t& e_coords) const {
            return Grid::isInExtent(localZeroExtent_, e_coords);
        }

        [[nodiscard]] inline bool isInZeroExtent(int e_x, int e_y, int e_z) const {
            return isInZeroExtent(gridCoords_t{e_x, e_y, e_z});
        }

        [[nodiscard]] inline bool isInZeroExtent(vtkIdType idx) const {
            return isInZeroExtent(idxToExtentCoord(idx));
        }

        [[nodiscard]] inline vtkIdType gridCoordToIdx(int g_x, int g_y, int g_z) const {
            return static_cast<vtkIdType>(g_x) + static_cast<vtkIdType>(g_y) * static_cast<vtkIdType>(dims_[0]) +
                   static_cast<vtkIdType>(g_z) * static_cast<vtkIdType>(dims_[0]) * static_cast<vtkIdType>(dims_[1]);
        }

        [[nodiscard]] inline vtkIdType gridCoordToIdx(const gridCoords_t& g_coords) const {
            return gridCoordToIdx(g_coords[0], g_coords[1], g_coords[2]);
        }

        [[nodiscard]] inline gridCoords_t idxToGridCoord(vtkIdType idx) const {
            const int g_x = static_cast<int>(idx % dims_[0]);
            const int g_y = static_cast<int>((idx / dims_[0]) % dims_[1]);
            const int g_z = static_cast<int>(idx / (dims_[0] * dims_[1]));
            return {g_x, g_y, g_z};
        }

        [[nodiscard]] inline vtkIdType localExtentCoordToIdx(int e_x, int e_y, int e_z) const {
            if (!isInLocalExtent(e_x, e_y, e_z)) {
                throw std::runtime_error("Extent coord out of bounds!");
            }
            return (e_x - localExtent_[0]) + (e_y - localExtent_[2]) * dims_[0] +
                   (e_z - localExtent_[4]) * dims_[0] * dims_[1];
        }

        [[nodiscard]] inline vtkIdType localExtentCoordToIdx(const gridCoords_t& e_coords) const {
            return localExtentCoordToIdx(e_coords[0], e_coords[1], e_coords[2]);
        }

        [[nodiscard]] inline gridCoords_t idxToExtentCoord(vtkIdType idx) const {
            const auto [g_x, g_y, g_z] = idxToGridCoord(idx);
            return {localExtent_[0] + g_x, localExtent_[2] + g_y, localExtent_[4] + g_z};
        }

        [[nodiscard]] inline gridCoords_t localExtentCoordToGridCoord(int e_x, int e_y, int e_z) const {
            if (!isInLocalExtent(e_x, e_y, e_z)) {
                throw std::runtime_error("Extent coord out of bounds!");
            }
            return {e_x - localExtent_[0], e_y - localExtent_[2], e_z - localExtent_[4]};
        }

        [[nodiscard]] inline gridCoords_t localExtentCoordToGridCoord(const gridCoords_t& e_coords) const {
            return localExtentCoordToGridCoord(e_coords[0], e_coords[1], e_coords[2]);
        }

        [[nodiscard]] inline bool isInLocalBounds(const posCoords_t& pos) const {
            return Grid::isInBounds(localBounds_, pos);
        }

        [[nodiscard]] inline bool isInLocalBounds(double x, double y, double z) const {
            return isInLocalBounds(posCoords_t{x, y, z});
        }

        [[nodiscard]] inline bool isInLocalBounds(const vec3& p) const {
            return isInLocalBounds(p.x, p.y, p.z);
        }

        [[nodiscard]] inline bool isInZeroBounds(const posCoords_t& pos) const {
            return Grid::isInBounds(localZeroBounds_, pos);
        }

        [[nodiscard]] inline bool isInZeroBounds(double x, double y, double z) const {
            return isInZeroBounds(posCoords_t{x, y, z});
        }

        [[nodiscard]] inline bool isInZeroBounds(const vec3& p) const {
            return isInZeroBounds(p.x, p.y, p.z);
        }

        [[nodiscard]] inline bool isInGlobalBounds(const posCoords_t& pos) const {
            return Grid::isInBounds(globalBounds_, pos);
        }

        [[nodiscard]] inline bool isInGlobalBounds(double x, double y, double z) const {
            return isInGlobalBounds(posCoords_t{x, y, z});
        }

        [[nodiscard]] inline bool isInGlobalBounds(const vec3& p) const {
            return isInGlobalBounds(p.x, p.y, p.z);
        }

        [[nodiscard]] inline int isOutOfZeroBoundsDirection(const vec3& p) const {
            return Grid::isOutOfBoundsDirection(localZeroBounds_, posCoords_t{p.x, p.y, p.z});
        }

        [[nodiscard]] inline std::optional<StructuredCoordinates> computeStructuredCoordinates(
            const posCoords_t& p) const {
            StructuredCoordinates sc;
            if (computeStructuredCoordinates(coordsX_, p[0], sc.cellCoords[0], sc.relativeCoords[0]) &&
                computeStructuredCoordinates(coordsY_, p[1], sc.cellCoords[1], sc.relativeCoords[1]) &&
                computeStructuredCoordinates(coordsZ_, p[2], sc.cellCoords[2], sc.relativeCoords[2])) {
                return sc;
            }
            return std::nullopt;
        }

        [[nodiscard]] inline std::optional<StructuredCoordinates> computeStructuredCoordinates(const vec3& p) const {
            return computeStructuredCoordinates(posCoords_t{p.x, p.y, p.z});
        }

        [[nodiscard]] inline StructuredCoordinates computeNearestStructuredCoordinates(const posCoords_t& p) const {
            StructuredCoordinates sc;
            computeStructuredCoordinates(coordsX_, p[0], sc.cellCoords[0], sc.relativeCoords[0]);
            computeStructuredCoordinates(coordsY_, p[1], sc.cellCoords[1], sc.relativeCoords[1]);
            computeStructuredCoordinates(coordsZ_, p[2], sc.cellCoords[2], sc.relativeCoords[2]);
            return sc;
        }

        [[nodiscard]] inline StructuredCoordinates computeNearestStructuredCoordinates(const vec3& p) const {
            return computeNearestStructuredCoordinates(posCoords_t{p.x, p.y, p.z});
        }

        [[nodiscard]] inline std::optional<gridCoords_t> posToGridCoord(const posCoords_t& p) const {
            auto coords = computeStructuredCoordinates(p);
            if (coords.has_value()) {
                return coords.value().cellCoords;
            }
            return std::nullopt;
        }

        [[nodiscard]] inline std::optional<gridCoords_t> posToGridCoord(const vec3& p) const {
            return posToGridCoord(posCoords_t{p.x, p.y, p.z});
        }

        [[nodiscard]] inline gridCoords_t posToGridCoordEx(const posCoords_t& p) const {
            const auto cell = posToGridCoord(p);
            if (cell.has_value()) {
                return cell.value();
            }
            throw std::runtime_error("Position is outside of grid bounds!");
        }

        [[nodiscard]] inline gridCoords_t posToGridCoordEx(const vec3& p) const {
            return posToGridCoordEx(posCoords_t{p.x, p.y, p.z});
        }

        [[nodiscard]] inline std::optional<vtkIdType> posToIdx(const posCoords_t& p) const {
            const auto g_coords = posToGridCoord(p);
            if (g_coords.has_value()) {
                return gridCoordToIdx(g_coords.value());
            }
            return std::nullopt;
        }

        [[nodiscard]] inline std::optional<vtkIdType> posToIdx(const vec3& p) const {
            return posToIdx(posCoords_t{p.x, p.y, p.z});
        }

        [[nodiscard]] inline vtkIdType posToIdxEx(const posCoords_t& p) const {
            return gridCoordToIdx(posToGridCoordEx(p));
        }

        [[nodiscard]] inline vtkIdType posToIdxEx(const vec3& p) const {
            return gridCoordToIdx(posToGridCoordEx(p));
        }

    private:
        /**
         * VTK's `ComputeStructuredCoordinates()` is very slow. The two major points are the linear search and the
         * overhead from the GetComponent interface of the arrays. Here, we implement binary search and directly use
         * the std::vector coords.
         * Assumptions: coords is sorted and size >= 2. (Both checked in constructor.)
         */
        inline bool computeStructuredCoordinates(const std::vector<double>& coords, double pos, int& cell,
            double& pcoord) const {
            // If out of bounds return closest point.
            if (pos < coords.front()) {
                cell = 0;
                pcoord = 0.0;
                return false;
            } else if (pos >= coords.back()) {
                cell = static_cast<int>(coords.size()) - 2;
                pcoord = 1.0;
                return false;
            }

            // Shortcut for uniform grids
            if (isUniform_) {
                double relative_pos = (pos - coords.front()) / (coords.back() - coords.front()); // [0, 1)
                relative_pos *= static_cast<double>(coords.size() - 1);                          // [0, num_cells)
                double iptr = 0.0;
                pcoord = std::clamp(std::modf(relative_pos, &iptr), 0.0, 1.0);
                cell = std::clamp(static_cast<int>(iptr), 0, static_cast<int>(coords.size() - 1));
                return true;
            }

            std::size_t left = 0;
            std::size_t right = coords.size() - 1;
            while (left + 1 < right) {
                const std::size_t mid = left + (right - left) / 2;
                if (pos < coords[mid]) {
                    right = mid;
                } else {
                    left = mid;
                }
            }
            cell = static_cast<int>(left);
            pcoord = (pos - coords[left]) / (coords[right] - coords[left]);
            return true;
        }

        vtkSmartPointer<vtkRectilinearGrid> grid_;
        extent_t localExtent_;     // Extent of thread local grid.
        extent_t localZeroExtent_; // Extent of the thread local grid without ghost cells.
        extent_t globalExtent_;    // Extent of the global grid across all threads.
        bounds_t localBounds_;     // Bounds of the thread local grid domain.
        bounds_t localZeroBounds_; // Bounds of the thread local grid domain without ghost cells.
        bounds_t globalBounds_;    // Bounds of the global grid domain across all threads.
        dim_t dims_;
        bool isUniform_;
        bool isParallel_;
        vtkSmartPointer<vtkUnsignedCharArray> ghostArray_;

        std::vector<double> coordsX_;
        std::vector<double> coordsY_;
        std::vector<double> coordsZ_;
        std::vector<double> cellSizesX_;
        std::vector<double> cellSizesY_;
        std::vector<double> cellSizesZ_;
        std::vector<double> cellCentersX_;
        std::vector<double> cellCentersY_;
        std::vector<double> cellCentersZ_;

        std::vector<NeighborInfo> neighbors_;
        std::array<std::vector<int>, 6> neighborsByDirection_; // list neighbors by direction
    };
} // namespace VofFlow

back to top

Software Heritage — Copyright (C) 2015–2026, The Software Heritage developers. License: GNU AGPLv3+.
The source code of Software Heritage itself is available on our development forge.
The source code files archived by Software Heritage are available under their own copyright and licenses.
Terms of use: Archive access, API— Content policy— Contact— JavaScript license information— Web API