Skip to content
Snippets Groups Projects
Select Git revision
  • 23dfd571a96f2afb6b42756702a449d6a2c6499e
  • develop default protected
  • feature/variational-hydro
  • origin/stage/bouguettaia
  • feature/gmsh-reader
  • feature/reconstruction
  • save_clemence
  • feature/kinetic-schemes
  • feature/local-dt-fsi
  • feature/composite-scheme-sources
  • feature/composite-scheme-other-fluxes
  • feature/serraille
  • feature/composite-scheme
  • hyperplastic
  • feature/polynomials
  • feature/gks
  • feature/implicit-solver-o2
  • feature/coupling_module
  • feature/implicit-solver
  • feature/merge-local-dt-fsi
  • master protected
  • v0.5.0 protected
  • v0.4.1 protected
  • v0.4.0 protected
  • v0.3.0 protected
  • v0.2.0 protected
  • v0.1.0 protected
  • Kidder
  • v0.0.4 protected
  • v0.0.3 protected
  • v0.0.2 protected
  • v0 protected
  • v0.0.1 protected
33 results

Messenger.cpp

Blame
  • Connectivity.hpp 17.56 KiB
    #ifndef CONNECTIVITY_HPP
    #define CONNECTIVITY_HPP
    
    #include <PugsAssert.hpp>
    #include <PugsMacros.hpp>
    
    #include <PugsUtils.hpp>
    
    #include <PugsTraits.hpp>
    
    #include <TinyVector.hpp>
    
    #include <ItemValue.hpp>
    
    #include <IConnectivity.hpp>
    
    #include <ConnectivityMatrix.hpp>
    #include <ItemToItemMatrix.hpp>
    
    #include <ConnectivityComputer.hpp>
    #include <SubItemValuePerItem.hpp>
    
    #include <algorithm>
    #include <vector>
    
    #include <CellType.hpp>
    
    #include <CSRGraph.hpp>
    
    #include <ItemType.hpp>
    #include <RefId.hpp>
    #include <RefItemList.hpp>
    
    #include <SynchronizerManager.hpp>
    
    #include <iostream>
    #include <set>
    
    class ConnectivityDescriptor;
    
    template <size_t Dim>
    class Connectivity final : public IConnectivity
    {
     public:
      PUGS_INLINE
      static std::shared_ptr<Connectivity<Dim>> build(const ConnectivityDescriptor&);
    
     private:
      constexpr static auto& itemTId = ItemTypeId<Dim>::itemTId;
    
     public:
      static constexpr size_t Dimension = Dim;
    
      PUGS_INLINE
      size_t
      dimension() const final
      {
        return Dimension;
      }
    
     private:
      ConnectivityMatrix m_item_to_item_matrix[Dimension + 1][Dimension + 1];
      WeakCellValue<const CellType> m_cell_type;
    
      WeakCellValue<const int> m_cell_global_index;
    
      WeakCellValue<const int> m_cell_number;
      WeakFaceValue<const int> m_face_number;
      WeakEdgeValue<const int> m_edge_number;
      WeakNodeValue<const int> m_node_number;
    
      WeakCellValue<const int> m_cell_owner;
      WeakCellValue<const bool> m_cell_is_owned;
    
      WeakFaceValue<const int> m_face_owner;
      WeakFaceValue<const bool> m_face_is_owned;
    
      WeakEdgeValue<const int> m_edge_owner;
      WeakEdgeValue<const bool> m_edge_is_owned;
    
      WeakNodeValue<const int> m_node_owner;
      WeakNodeValue<const bool> m_node_is_owned;
    
      WeakFaceValuePerCell<const bool> m_cell_face_is_reversed;
      WeakEdgeValuePerFace<const bool> m_face_edge_is_reversed;
    
      WeakNodeValuePerCell<const unsigned short> m_cell_local_numbers_in_their_nodes;
      WeakEdgeValuePerCell<const unsigned short> m_cell_local_numbers_in_their_edges;
      WeakFaceValuePerCell<const unsigned short> m_cell_local_numbers_in_their_faces;
    
      WeakCellValuePerFace<const unsigned short> m_face_local_numbers_in_their_cells;
      WeakEdgeValuePerFace<const unsigned short> m_face_local_numbers_in_their_edges;
      WeakNodeValuePerFace<const unsigned short> m_face_local_numbers_in_their_nodes;
    
      WeakCellValuePerEdge<const unsigned short> m_edge_local_numbers_in_their_cells;
      WeakFaceValuePerEdge<const unsigned short> m_edge_local_numbers_in_their_faces;
      WeakNodeValuePerEdge<const unsigned short> m_edge_local_numbers_in_their_nodes;
    
      WeakCellValuePerNode<const unsigned short> m_node_local_numbers_in_their_cells;
      WeakEdgeValuePerNode<const unsigned short> m_node_local_numbers_in_their_edges;
      WeakFaceValuePerNode<const unsigned short> m_node_local_numbers_in_their_faces;
    
      ConnectivityComputer m_connectivity_computer;
    
      std::vector<RefCellList> m_ref_cell_list_vector;
      std::vector<RefFaceList> m_ref_face_list_vector;
      std::vector<RefEdgeList> m_ref_edge_list_vector;
      std::vector<RefNodeList> m_ref_node_list_vector;
    
      WeakCellValue<const double> m_inv_cell_nb_nodes;
    
      void _computeCellFaceAndFaceNodeConnectivities();
    
      template <typename SubItemValuePerItemType>
      PUGS_INLINE const SubItemValuePerItemType&
      _lazzyBuildItemNumberInTheirChild(const SubItemValuePerItemType& sub_item_value_per_item) const
      {
        using ReversedItemOfItem = typename SubItemValuePerItemType::ItemOfItemType::Reversed;
        if (not sub_item_value_per_item.isBuilt()) {
          const_cast<SubItemValuePerItemType&>(sub_item_value_per_item) =
            m_connectivity_computer.computeLocalItemNumberInChildItem<ReversedItemOfItem>(*this);
        }
        return sub_item_value_per_item;
      }
    
      friend class ConnectivityComputer;
    
      PUGS_INLINE
      const ConnectivityMatrix&
      _getMatrix(const ItemType& item_type_0, const ItemType& item_type_1) const
      {
        const ConnectivityMatrix& connectivity_matrix = m_item_to_item_matrix[itemTId(item_type_0)][itemTId(item_type_1)];
        if (not connectivity_matrix.isBuilt()) {
          const_cast<ConnectivityMatrix&>(connectivity_matrix) =
            m_connectivity_computer.computeConnectivityMatrix(*this, item_type_0, item_type_1);
        }
        return connectivity_matrix;
      }
    
     public:
      PUGS_INLINE
      const auto&
      cellType() const
      {
        return m_cell_type;
      }
    
      PUGS_INLINE
      const auto&
      cellNumber() const
      {
        return m_cell_number;
      }
    
      PUGS_INLINE
      const auto&
      faceNumber() const
      {
        return m_face_number;
      }
    
      PUGS_INLINE
      const auto&
      edgeNumber() const
      {
        return m_edge_number;
      }
    
      PUGS_INLINE
      const auto&
      nodeNumber() const
      {
        return m_node_number;
      }
    
      template <ItemType item_type>
      PUGS_INLINE const auto&
      number() const
      {
        if constexpr (item_type == ItemType::cell) {
          return m_cell_number;
        } else if constexpr (item_type == ItemType::face) {
          return m_face_number;
        } else if constexpr (item_type == ItemType::edge) {
          return m_edge_number;
        } else if constexpr (item_type == ItemType::node) {
          return m_node_number;
        } else {
          static_assert(is_false_item_type_v<item_type>, "unknown ItemType");
        }
      }
    
      PUGS_INLINE
      const auto&
      cellOwner() const
      {
        return m_cell_owner;
      }
    
      PUGS_INLINE
      const auto&
      faceOwner() const
      {
        return m_face_owner;
      }
    
      PUGS_INLINE
      const auto&
      edgeOwner() const
      {
        std::cerr << __FILE__ << ':' << __LINE__ << ": edge owner not built\n";
        std::terminate();
        return m_edge_owner;
      }
    
      PUGS_INLINE
      const auto&
      nodeOwner() const
      {
        return m_node_owner;
      }
    
      template <ItemType item_type>
      PUGS_INLINE const auto&
      owner() const
      {
        if constexpr (item_type == ItemType::cell) {
          return m_cell_owner;
        } else if constexpr (item_type == ItemType::face) {
          return m_face_owner;
        } else if constexpr (item_type == ItemType::edge) {
          return m_edge_owner;
        } else if constexpr (item_type == ItemType::node) {
          return m_node_owner;
        } else {
          static_assert(is_false_item_type_v<item_type>, "unknown ItemType");
        }
      }
    
      PUGS_INLINE
      const auto&
      cellIsOwned() const
      {
        return m_cell_is_owned;
      }
    
      PUGS_INLINE
      const auto&
      faceIsOwned() const
      {
        return m_face_is_owned;
      }
    
      PUGS_INLINE
      const auto&
      edgeIsOwned() const
      {
        std::cerr << __FILE__ << ':' << __LINE__ << ": edge is owned not built\n";
        std::terminate();
        return m_edge_is_owned;
      }
    
      PUGS_INLINE
      const auto&
      nodeIsOwned() const
      {
        return m_node_is_owned;
      }
    
      template <ItemType item_type>
      PUGS_INLINE const auto&
      isOwned() const
      {
        if constexpr (item_type == ItemType::cell) {
          return m_cell_is_owned;
        } else if constexpr (item_type == ItemType::face) {
          return m_face_is_owned;
        } else if constexpr (item_type == ItemType::edge) {
          return m_edge_is_owned;
        } else if constexpr (item_type == ItemType::node) {
          return m_node_is_owned;
        } else {
          static_assert(is_false_item_type_v<item_type>, "unknown ItemType");
        }
      }
    
      PUGS_INLINE
      const bool&
      isConnectivityMatrixBuilt(const ItemType& item_type_0, const ItemType& item_type_1) const
      {
        const ConnectivityMatrix& connectivity_matrix = m_item_to_item_matrix[itemTId(item_type_0)][itemTId(item_type_1)];
        return connectivity_matrix.isBuilt();
      }
      template <ItemType source_item_type, ItemType target_item_type>
      PUGS_INLINE auto
      getItemToItemMatrix() const
      {
        return ItemToItemMatrix<source_item_type, target_item_type>(_getMatrix(source_item_type, target_item_type));
      }
    
      PUGS_INLINE
      auto
      cellToFaceMatrix() const
      {
        return this->template getItemToItemMatrix<ItemType::cell, ItemType::face>();
      }
    
      PUGS_INLINE
      auto
      cellToEdgeMatrix() const
      {
        return this->template getItemToItemMatrix<ItemType::cell, ItemType::edge>();
      }
    
      PUGS_INLINE
      auto
      cellToNodeMatrix() const
      {
        return this->template getItemToItemMatrix<ItemType::cell, ItemType::node>();
      }
    
      PUGS_INLINE
      auto
      faceToCellMatrix() const
      {
        return this->template getItemToItemMatrix<ItemType::face, ItemType::cell>();
      }
    
      PUGS_INLINE
      auto
      faceToEdgeMatrix() const
      {
        return this->template getItemToItemMatrix<ItemType::face, ItemType::edge>();
      }
    
      PUGS_INLINE
      auto
      faceToNodeMatrix() const
      {
        return this->template getItemToItemMatrix<ItemType::face, ItemType::node>();
      }
    
      PUGS_INLINE
      auto
      edgeToCellMatrix() const
      {
        return this->template getItemToItemMatrix<ItemType::edge, ItemType::cell>();
      }
    
      PUGS_INLINE
      auto
      edgeToFaceMatrix() const
      {
        return this->template getItemToItemMatrix<ItemType::edge, ItemType::face>();
      }
    
      PUGS_INLINE
      auto
      edgeToNodeMatrix() const
      {
        return this->template getItemToItemMatrix<ItemType::edge, ItemType::node>();
      }
    
      PUGS_INLINE
      auto
      nodeToCellMatrix() const
      {
        return this->template getItemToItemMatrix<ItemType::node, ItemType::cell>();
      }
    
      PUGS_INLINE
      auto
      nodeToFaceMatrix() const
      {
        return this->template getItemToItemMatrix<ItemType::node, ItemType::face>();
      }
    
      PUGS_INLINE
      auto
      nodeToEdgeMatrix() const
      {
        return this->template getItemToItemMatrix<ItemType::node, ItemType::edge>();
      }
    
      PUGS_INLINE
      const auto&
      cellFaceIsReversed() const
      {
        static_assert(Dimension > 1, "reversed faces makes no sense in dimension 1");
        return m_cell_face_is_reversed;
      }
    
      PUGS_INLINE
      const auto&
      faceEdgeIsReversed() const
      {
        static_assert(Dimension > 2, "reversed edges makes no sense in dimension 1 or 2");
        return m_face_edge_is_reversed;
      }
    
      PUGS_INLINE
      const auto&
      cellLocalNumbersInTheirNodes() const
      {
        return _lazzyBuildItemNumberInTheirChild(m_cell_local_numbers_in_their_nodes);
      }
    
      PUGS_INLINE
      const auto&
      cellLocalNumbersInTheirEdges() const
      {
        if constexpr (Dimension > 2) {
          return _lazzyBuildItemNumberInTheirChild(m_cell_local_numbers_in_their_edges);
        } else {
          return cellLocalNumbersInTheirFaces();
        }
      }
    
      PUGS_INLINE
      const auto&
      cellLocalNumbersInTheirFaces() const
      {
        if constexpr (Dimension > 1) {
          return _lazzyBuildItemNumberInTheirChild(m_cell_local_numbers_in_their_faces);
        } else {
          return cellLocalNumbersInTheirNodes();
        }
      }
    
      PUGS_INLINE
      const auto&
      faceLocalNumbersInTheirCells() const
      {
        if constexpr (Dimension > 1) {
          return _lazzyBuildItemNumberInTheirChild(m_face_local_numbers_in_their_cells);
        } else {
          return nodeLocalNumbersInTheirCells();
        }
      }
    
      PUGS_INLINE
      const auto&
      faceLocalNumbersInTheirEdges() const
      {
        static_assert(Dimension > 2, "this function has no meaning in 1d or 2d");
        return _lazzyBuildItemNumberInTheirChild(m_face_local_numbers_in_their_edges);
      }
    
      PUGS_INLINE
      const auto&
      faceLocalNumbersInTheirNodes() const
      {
        static_assert(Dimension > 1, "this function has no meaning in 1d");
        return _lazzyBuildItemNumberInTheirChild(m_face_local_numbers_in_their_nodes);
      }
    
      PUGS_INLINE
      const auto&
      edgeLocalNumbersInTheirCells() const
      {
        if constexpr (Dimension > 2) {
          return _lazzyBuildItemNumberInTheirChild(m_edge_local_numbers_in_their_cells);
        } else {
          return faceLocalNumbersInTheirCells();
        }
      }
    
      PUGS_INLINE
      const auto&
      edgeLocalNumbersInTheirFaces() const
      {
        static_assert(Dimension > 2, "this function has no meaning in 1d or 2d");
        return _lazzyBuildItemNumberInTheirChild(m_edge_local_numbers_in_their_faces);
      }
    
      PUGS_INLINE
      const auto&
      edgeLocalNumbersInTheirNodes() const
      {
        static_assert(Dimension > 2, "this function has no meaning in 1d or 2d");
        return _lazzyBuildItemNumberInTheirChild(m_edge_local_numbers_in_their_nodes);
      }
    
      PUGS_INLINE
      const auto&
      nodeLocalNumbersInTheirCells() const
      {
        return _lazzyBuildItemNumberInTheirChild(m_node_local_numbers_in_their_cells);
      }
    
      PUGS_INLINE
      const auto&
      nodeLocalNumbersInTheirEdges() const
      {
        static_assert(Dimension > 2, "this function has no meaning in 1d or 2d");
        return _lazzyBuildItemNumberInTheirChild(m_node_local_numbers_in_their_edges);
      }
    
      PUGS_INLINE
      const auto&
      nodeLocalNumbersInTheirFaces() const
      {
        static_assert(Dimension > 1, "this function has no meaning in 1d");
        return _lazzyBuildItemNumberInTheirChild(m_node_local_numbers_in_their_faces);
      }
    
      template <ItemType item_type>
      size_t
      numberOfRefItemList() const
      {
        if constexpr (item_type == ItemType::cell) {
          return m_ref_cell_list_vector.size();
        } else if constexpr (item_type == ItemType::face) {
          return m_ref_face_list_vector.size();
        } else if constexpr (item_type == ItemType::edge) {
          return m_ref_edge_list_vector.size();
        } else if constexpr (item_type == ItemType::node) {
          return m_ref_node_list_vector.size();
        } else {
          static_assert(is_false_item_type_v<item_type>, "Unexpected item type");
        }
      }
    
      template <ItemType item_type>
      const RefItemList<item_type>&
      refItemList(const size_t& i) const
      {
        if constexpr (item_type == ItemType::cell) {
          return m_ref_cell_list_vector[i];
        } else if constexpr (item_type == ItemType::face) {
          return m_ref_face_list_vector[i];
        } else if constexpr (item_type == ItemType::edge) {
          return m_ref_edge_list_vector[i];
        } else if constexpr (item_type == ItemType::node) {
          return m_ref_node_list_vector[i];
        } else {
          static_assert(is_false_item_type_v<item_type>, "Unexpected item type");
        }
      }
    
      template <ItemType item_type>
      void
      addRefItemList(const RefItemList<item_type>& ref_item_list)
      {
        if constexpr (item_type == ItemType::cell) {
          m_ref_cell_list_vector.push_back(ref_item_list);
        } else if constexpr (item_type == ItemType::face) {
          m_ref_face_list_vector.push_back(ref_item_list);
        } else if constexpr (item_type == ItemType::edge) {
          m_ref_edge_list_vector.push_back(ref_item_list);
        } else if constexpr (item_type == ItemType::node) {
          m_ref_node_list_vector.push_back(ref_item_list);
        } else {
          static_assert(is_false_item_type_v<item_type>, "Unexpected item type");
        }
      }
    
      PUGS_INLINE
      CSRGraph
      cellToCellGraph() const
      {
        std::vector<std::set<int>> cell_cells(this->numberOfCells());
        if constexpr (true) {
          const auto& face_to_cell_matrix = this->faceToCellMatrix();
    
          for (FaceId l = 0; l < this->numberOfFaces(); ++l) {
            const auto& face_to_cell = face_to_cell_matrix[l];
            if (face_to_cell.size() > 1) {
              const CellId cell_0 = face_to_cell[0];
              const CellId cell_1 = face_to_cell[1];
    
              cell_cells[cell_0].insert(cell_1);
              cell_cells[cell_1].insert(cell_0);
            }
          }
        } else {
          const auto& node_to_cell_matrix = this->nodeToCellMatrix();
    
          for (NodeId l = 0; l < this->numberOfNodes(); ++l) {
            const auto& node_to_cell = node_to_cell_matrix[l];
            for (size_t i_cell = 0; i_cell < node_to_cell.size(); ++i_cell) {
              const CellId cell_0 = node_to_cell[i_cell];
              for (size_t j_cell = 0; j_cell < i_cell; ++j_cell) {
                const CellId cell_1 = node_to_cell[j_cell];
                cell_cells[cell_0].insert(cell_1);
                cell_cells[cell_1].insert(cell_0);
              }
            }
          }
        }
    
        Array<int> entries(this->numberOfCells() + 1);
        entries[0] = 0;
        for (size_t j = 0; j < this->numberOfCells(); ++j) {
          entries[j + 1] = entries[j] + cell_cells[j].size();
        }
        Array<int> neighbors(entries[this->numberOfCells()]);
        {
          size_t k = 0;
          for (size_t j = 0; j < this->numberOfCells(); ++j) {
            for (CellId cell_id : cell_cells[j]) {
              neighbors[k] = m_cell_global_index[cell_id];
              ++k;
            }
          }
        }
        return CSRGraph(entries, neighbors);
      }
    
      PUGS_INLINE
      size_t
      numberOfNodes() const final
      {
        const auto& node_to_cell_matrix = this->_getMatrix(ItemType::node, ItemType::cell);
        return node_to_cell_matrix.numRows();
      }
    
      PUGS_INLINE
      size_t
      numberOfEdges() const final
      {
        const auto& edge_to_node_matrix = this->_getMatrix(ItemType::edge, ItemType::node);
        return edge_to_node_matrix.numRows();
      }
    
      PUGS_INLINE
      size_t
      numberOfFaces() const final
      {
        const auto& face_to_node_matrix = this->_getMatrix(ItemType::face, ItemType::cell);
        return face_to_node_matrix.numRows();
      }
    
      PUGS_INLINE
      size_t
      numberOfCells() const final
      {
        const auto& cell_to_node_matrix = this->_getMatrix(ItemType::cell, ItemType::node);
        return cell_to_node_matrix.numRows();
      }
    
      CellValue<const double>
      invCellNbNodes() const
      {
        if (not m_inv_cell_nb_nodes.isBuilt()) {
          const auto& cell_to_node_matrix = m_item_to_item_matrix[itemTId(ItemType::cell)][itemTId(ItemType::node)];
    
          WeakCellValue<double> inv_cell_nb_nodes(*this);
          parallel_for(
            this->numberOfCells(), PUGS_LAMBDA(const CellId& j) {
              const auto& cell_nodes = cell_to_node_matrix.rowConst(j);
              inv_cell_nb_nodes[j]   = 1. / cell_nodes.length;
            });
          const_cast<WeakCellValue<const double>&>(m_inv_cell_nb_nodes) = inv_cell_nb_nodes;
        }
    
        return m_inv_cell_nb_nodes;
      }
    
      Connectivity(const Connectivity&) = delete;
    
     private:
      Connectivity();
      void _buildFrom(const ConnectivityDescriptor& descriptor);
    
     public:
      ~Connectivity()
      {
        auto& manager = SynchronizerManager::instance();
        manager.deleteConnectivitySynchronizer(this);
      }
    };
    
    template <size_t Dim>
    PUGS_INLINE std::shared_ptr<Connectivity<Dim>>
    Connectivity<Dim>::build(const ConnectivityDescriptor& descriptor)
    {
      std::shared_ptr<Connectivity<Dim>> connectivity_ptr(new Connectivity<Dim>);
      connectivity_ptr->_buildFrom(descriptor);
    
      return connectivity_ptr;
    }
    
    using Connectivity3D = Connectivity<3>;
    using Connectivity2D = Connectivity<2>;
    using Connectivity1D = Connectivity<1>;
    
    #endif   // CONNECTIVITY_HPP