From 89729365d49d40197ea5c1bf88824d2a0529232d Mon Sep 17 00:00:00 2001
From: TotoGaz <49004943+TotoGaz@users.noreply.github.com>
Date: Fri, 22 Mar 2024 15:24:25 -0700
Subject: [PATCH 001/106] First dummy version that compiles.
---
src/coreComponents/mesh/CMakeLists.txt | 2 +
.../mesh/generators/MeshBlockMappings.cpp | 142 ++++++++++++++++++
.../mesh/generators/MeshBlockMappings.hpp | 103 +++++++++++++
3 files changed, 247 insertions(+)
create mode 100644 src/coreComponents/mesh/generators/MeshBlockMappings.cpp
create mode 100644 src/coreComponents/mesh/generators/MeshBlockMappings.hpp
diff --git a/src/coreComponents/mesh/CMakeLists.txt b/src/coreComponents/mesh/CMakeLists.txt
index 6065ef14dae..1fafa2eb0a6 100644
--- a/src/coreComponents/mesh/CMakeLists.txt
+++ b/src/coreComponents/mesh/CMakeLists.txt
@@ -54,6 +54,7 @@ set( mesh_headers
generators/InternalMeshGenerator.hpp
generators/InternalWellGenerator.hpp
generators/InternalWellboreGenerator.hpp
+ generators/MeshBlockMappings.hpp
generators/MeshGeneratorBase.hpp
generators/ParMETISInterface.hpp
generators/ParticleMeshGenerator.hpp
@@ -127,6 +128,7 @@ set( mesh_sources
generators/InternalMeshGenerator.cpp
generators/InternalWellGenerator.cpp
generators/InternalWellboreGenerator.cpp
+ generators/MeshBlockMappings.cpp
generators/MeshGeneratorBase.cpp
generators/ParMETISInterface.cpp
generators/ParticleMeshGenerator.cpp
diff --git a/src/coreComponents/mesh/generators/MeshBlockMappings.cpp b/src/coreComponents/mesh/generators/MeshBlockMappings.cpp
new file mode 100644
index 00000000000..191071fc22e
--- /dev/null
+++ b/src/coreComponents/mesh/generators/MeshBlockMappings.cpp
@@ -0,0 +1,142 @@
+/*
+ * ------------------------------------------------------------------------------------------------------------
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ * Copyright (c) 2018-2020 Lawrence Livermore National Security LLC
+ * Copyright (c) 2018-2020 The Board of Trustees of the Leland Stanford Junior University
+ * Copyright (c) 2018-2020 TotalEnergies
+ * Copyright (c) 2020- GEOSX Contributors
+ * All rights reserved
+ *
+ * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details.
+ * ------------------------------------------------------------------------------------------------------------
+ */
+
+#include "MeshBlockMappings.hpp"
+
+namespace geos
+{
+
+using namespace dataRepository;
+
+MeshBlockMappings::MeshBlockMappings( string const & name,
+ Group * const parent )
+ :
+ CellBlockManagerABC( name, parent )
+{
+ this->registerGroup< Group >( viewKeyStruct::cellBlocks() );
+ this->registerGroup< Group >( viewKeyStruct::faceBlocks() );
+ this->registerGroup< Group >( viewKeyStruct::lineBlocks() );
+}
+
+Group & MeshBlockMappings::getCellBlocks()
+{
+ return this->getGroup( viewKeyStruct::cellBlocks() );
+}
+
+Group & MeshBlockMappings::getFaceBlocks()
+{
+ return this->getGroup( viewKeyStruct::faceBlocks() );
+}
+
+LineBlockABC const & MeshBlockMappings::getLineBlock( string name ) const
+{
+ return this->getGroup( viewKeyStruct::lineBlocks() ).getGroup< LineBlockABC >( name );
+}
+
+Group const & MeshBlockMappings::getCellBlocks() const
+{
+ return this->getGroup( viewKeyStruct::cellBlocks() );
+}
+
+Group const & MeshBlockMappings::getFaceBlocks() const
+{
+ return this->getGroup( viewKeyStruct::faceBlocks() );
+}
+
+localIndex MeshBlockMappings::numNodes() const
+{
+ return m_numNodes;
+}
+
+localIndex MeshBlockMappings::numEdges() const
+{
+ return m_numEdges;
+}
+
+localIndex MeshBlockMappings::numFaces() const
+{
+ return m_numFaces;
+}
+
+array2d< real64, nodes::REFERENCE_POSITION_PERM > MeshBlockMappings::getNodePositions() const
+{
+ return {};
+}
+
+ArrayOfArrays< localIndex > MeshBlockMappings::getNodeToEdges() const
+{
+ return {};
+}
+
+ArrayOfArrays< localIndex > MeshBlockMappings::getNodeToFaces() const
+{
+ return {};
+}
+
+ToCellRelation< ArrayOfArrays< localIndex>> MeshBlockMappings::getNodeToElements() const
+{
+ return {};
+}
+
+array2d< localIndex > MeshBlockMappings::getEdgeToNodes() const
+{
+ return {};
+}
+
+ArrayOfArrays< localIndex > MeshBlockMappings::getEdgeToFaces() const
+{
+ return {};
+}
+
+ArrayOfArrays< localIndex > MeshBlockMappings::getFaceToNodes() const
+{
+ return {};
+}
+
+ArrayOfArrays< localIndex > MeshBlockMappings::getFaceToEdges() const
+{
+ return {};
+}
+
+ToCellRelation< array2d< localIndex>> MeshBlockMappings::getFaceToElements() const
+{
+ return {};
+}
+
+array1d< globalIndex > MeshBlockMappings::getNodeLocalToGlobal() const
+{
+ return {};
+}
+
+std::map< string, SortedArray< localIndex>> const & MeshBlockMappings::getNodeSets() const
+{
+ return m_nodeSets;
+}
+
+real64 MeshBlockMappings::getGlobalLength() const
+{
+ return m_globalLength;
+}
+
+void MeshBlockMappings::generateHighOrderMaps( localIndex const order,
+ globalIndex const maxVertexGlobalID,
+ globalIndex const maxEdgeGlobalID,
+ globalIndex const maxFaceGlobalID,
+ arrayView1d< globalIndex const > const edgeLocalToGlobal,
+ arrayView1d< globalIndex const > const faceLocalToGlobal )
+{
+ GEOS_ERROR( "`MeshBlockMappings::generateHighOrderMaps` is not implemented and should not be called." );
+}
+
+} // geos
\ No newline at end of file
diff --git a/src/coreComponents/mesh/generators/MeshBlockMappings.hpp b/src/coreComponents/mesh/generators/MeshBlockMappings.hpp
new file mode 100644
index 00000000000..00fc352c020
--- /dev/null
+++ b/src/coreComponents/mesh/generators/MeshBlockMappings.hpp
@@ -0,0 +1,103 @@
+/*
+ * ------------------------------------------------------------------------------------------------------------
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ * Copyright (c) 2018-2020 Lawrence Livermore National Security LLC
+ * Copyright (c) 2018-2020 The Board of Trustees of the Leland Stanford Junior University
+ * Copyright (c) 2018-2020 TotalEnergies
+ * Copyright (c) 2020- GEOSX Contributors
+ * All rights reserved
+ *
+ * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details.
+ * ------------------------------------------------------------------------------------------------------------
+ */
+
+#ifndef GEOS_GENERATORS_MESHBLOCKMAPPINGS_HPP
+#define GEOS_GENERATORS_MESHBLOCKMAPPINGS_HPP
+
+#include "CellBlockManagerABC.hpp"
+
+namespace geos
+{
+
+class MeshBlockMappings: public CellBlockManagerABC
+{
+public:
+ MeshBlockMappings( string const & name, Group * const parent );
+
+ virtual Group & getCellBlocks() override;
+
+ virtual Group & getFaceBlocks() override;
+
+ virtual LineBlockABC const & getLineBlock( string name ) const override;
+
+ virtual Group const & getCellBlocks() const override;
+
+ virtual Group const & getFaceBlocks() const override;
+
+ virtual localIndex numNodes() const override;
+
+ virtual localIndex numEdges() const override;
+
+ virtual localIndex numFaces() const override;
+
+ virtual array2d< real64, nodes::REFERENCE_POSITION_PERM > getNodePositions() const override;
+
+ virtual ArrayOfArrays< localIndex > getNodeToEdges() const override;
+
+ virtual ArrayOfArrays< localIndex > getNodeToFaces() const override;
+
+ virtual ToCellRelation< ArrayOfArrays< localIndex>> getNodeToElements() const override;
+
+ virtual array2d< localIndex > getEdgeToNodes() const override;
+
+ virtual ArrayOfArrays< localIndex > getEdgeToFaces() const override;
+
+ virtual ArrayOfArrays< localIndex > getFaceToNodes() const override;
+
+ virtual ArrayOfArrays< localIndex > getFaceToEdges() const override;
+
+ virtual ToCellRelation< array2d< localIndex>> getFaceToElements() const override;
+
+ virtual array1d< globalIndex > getNodeLocalToGlobal() const override;
+
+ virtual std::map< string, SortedArray< localIndex>> const & getNodeSets() const override;
+
+ virtual real64 getGlobalLength() const override;
+
+ virtual void generateHighOrderMaps( localIndex const order,
+ globalIndex const maxVertexGlobalID,
+ globalIndex const maxEdgeGlobalID,
+ globalIndex const maxFaceGlobalID,
+ arrayView1d< globalIndex const > const edgeLocalToGlobal,
+ arrayView1d< globalIndex const > const faceLocalToGlobal ) override;
+
+private:
+
+ struct viewKeyStruct
+ {
+ /// Cell blocks key
+ static constexpr char const * cellBlocks()
+ { return "cellBlocks"; }
+
+ /// Face blocks key
+ static constexpr char const * faceBlocks()
+ { return "faceBlocks"; }
+
+ /// Line blocks key
+ static constexpr char const * lineBlocks()
+ { return "lineBlocks"; }
+ };
+
+ std::map< string, SortedArray< localIndex > > m_nodeSets;
+
+ real64 m_globalLength;
+
+ localIndex m_numNodes;
+ localIndex m_numFaces;
+ localIndex m_numEdges;
+};
+
+} // geos
+
+#endif //GEOS_GENERATORS_MESHBLOCKMAPPINGS_HPP
From 095b262ee69d3c3ee9793395dac7c4f99a93cd46 Mon Sep 17 00:00:00 2001
From: TotoGaz <49004943+TotoGaz@users.noreply.github.com>
Date: Tue, 2 Apr 2024 14:53:57 -0700
Subject: [PATCH 002/106] v0 of the doc
---
.../KeyComponents/Ghosting/ghosting.rst | 21 +++++
.../Ghosting/ghosting_algorithm.plantuml | 40 +++++++++
.../Ghosting/global_ghosting_setup.plantuml | 90 +++++++++++++++++++
.../Ghosting/global_numbering.plantuml | 46 ++++++++++
4 files changed, 197 insertions(+)
create mode 100644 src/docs/sphinx/developerGuide/KeyComponents/Ghosting/ghosting.rst
create mode 100644 src/docs/sphinx/developerGuide/KeyComponents/Ghosting/ghosting_algorithm.plantuml
create mode 100644 src/docs/sphinx/developerGuide/KeyComponents/Ghosting/global_ghosting_setup.plantuml
create mode 100644 src/docs/sphinx/developerGuide/KeyComponents/Ghosting/global_numbering.plantuml
diff --git a/src/docs/sphinx/developerGuide/KeyComponents/Ghosting/ghosting.rst b/src/docs/sphinx/developerGuide/KeyComponents/Ghosting/ghosting.rst
new file mode 100644
index 00000000000..95133902259
--- /dev/null
+++ b/src/docs/sphinx/developerGuide/KeyComponents/Ghosting/ghosting.rst
@@ -0,0 +1,21 @@
+.. _ghosting:
+
+Ghosting setup
+######################
+
+This describes the setup of the ghosting.
+
+
+.. _global_ghosting_setup:
+.. uml:: global_ghosting_setup.plantuml
+ :caption: The global parallel algorithm
+
+
+.. _global_numbering:
+.. uml:: global_numbering.plantuml
+ :caption: The global numbering algorithm
+
+
+.. _ghosting_algorithm:
+.. uml:: ghosting_algorithm.plantuml
+ :caption: The ghosting algorithm
diff --git a/src/docs/sphinx/developerGuide/KeyComponents/Ghosting/ghosting_algorithm.plantuml b/src/docs/sphinx/developerGuide/KeyComponents/Ghosting/ghosting_algorithm.plantuml
new file mode 100644
index 00000000000..6201b833620
--- /dev/null
+++ b/src/docs/sphinx/developerGuide/KeyComponents/Ghosting/ghosting_algorithm.plantuml
@@ -0,0 +1,40 @@
+@startuml
+
+
+
+participant "Rank k" as rk
+
+activate rk #WhiteSmoke
+
+rk -> rk++ #orange: Assemble paralllel sparse\nadjacency matrix A
+
+[<--> rk: Parallel matrix\nassembly (mpi)
+
+rk -> rk--++ #orange: Define rhs graph nodes support arrays\n(under the form of a parallel matrix)
+
+deactivate rk
+
+rk -\ rk-- <>
+
+loop halo size
+rk -> rk++ #tomato: Compute ancestors using parallel\nmatrix-matrix multiplication
+[<--> rk: matrix-matrix\nparallel multiplication (mpi)
+rk -> rk--++ #tomato: Compute descendants using parallel\nmatrix-matrix multiplication
+[<--> rk: matrix-matrix\nparallel multiplication (mpi)
+|||
+rk -\ rk-- <>
+end
+
+rk -> rk++ #tomato: Update (add and remove)\nneighbor ranks
+rk -> rk--++ #LimeGreen: Compute mappings\n(including ghosted information)
+|||
+|||
+
+@enduml
diff --git a/src/docs/sphinx/developerGuide/KeyComponents/Ghosting/global_ghosting_setup.plantuml b/src/docs/sphinx/developerGuide/KeyComponents/Ghosting/global_ghosting_setup.plantuml
new file mode 100644
index 00000000000..93c4911f182
--- /dev/null
+++ b/src/docs/sphinx/developerGuide/KeyComponents/Ghosting/global_ghosting_setup.plantuml
@@ -0,0 +1,90 @@
+@startuml
+skinparam BoxPadding 10
+participant "Rank 0" as r0
+participant "..." as rtmp0
+box neighborhood of rank k #AliceBlue
+participant "Rank k-1" as rkm1
+participant "Rank k" as rk
+participant "Rank k+1" as rkp1
+end box
+participant "..." as rtmpn
+participant "Rank n" as rn
+
+==global numbering==
+
+activate r0 #WhiteSmoke
+activate rtmp0 #WhiteSmoke
+activate rkm1 #WhiteSmoke
+activate rk #WhiteSmoke
+activate rkp1 #WhiteSmoke
+activate rtmpn #WhiteSmoke
+activate rn #WhiteSmoke
+
+group Exchange meshes information ■ & \ncompute intersections ■ [mpi send/recv]
+
+!pragma teoz true
+
+r0 -[#tomato]->(90) rkm1++ #LimeGreen
+& rkm1 -[#tomato]->(50) r0
+& r0 -[#tomato]->(80) rtmpn++ #LimeGreen
+& rtmpn -[#tomato]->(100) r0++ #LimeGreen
+& rtmpn -[#tomato]->(120) rn++ #LimeGreen
+& rtmp0 -[#tomato]->(10) rkm1
+& rkm1 -[#tomato]->(40) rtmp0++ #LimeGreen
+& rn -[#tomato]->(50) rtmpn
+& rk -[#tomato]>(50) rkm1
+& rk -[#red]>(10) rkp1
+& rkm1 -[#red]>(40) rk
+& rkm1 -[#red]>(50) rkp1++ #LimeGreen
+& rkp1 -[#red]>(80) rk++ #LimeGreen
+& rkp1 -[#red]>(70) rkm1glob
+
+
+end group
+
+group Compute and exchange offsets ■, and number ■ [mpi scan]
+
+deactivate rtmp0
+
+deactivate r0
+r0 -> r0++ #tomato
+deactivate rkm1
+activate rtmp0 #tomato
+r0 -[#red]>> rtmp0-- #tomato
+
+r0 -> r0++ #DeepSkyBlue
+
+
+deactivate rn
+deactivate rk
+
+activate rkm1 #tomato
+rtmp0 -[#red]>> rkm1-- #tomato
+deactivate rkp1
+rtmp0 -> rtmp0++ #DeepSkyBlue
+
+
+activate rk #tomato
+rkm1 -[#red]>> rk-- #tomato
+rkm1 -> rkm1++ #DeepSkyBlue
+
+deactivate rtmpn
+
+activate rkp1 #tomato
+rk -[#red]>> rkp1-- #tomato
+rk -> rk++ #DeepSkyBlue
+
+activate rtmpn #tomato
+rkp1 -[#red]>> rtmpn-- #tomato
+rkp1 -> rkp1++ #DeepSkyBlue
+
+activate rn #tomato
+rtmpn -[#red]>> rn-- #tomato
+rtmpn -> rtmpn++ #DeepSkyBlue
+
+deactivate rn
+rn -> rn++ #DeepSkyBlue
+
+end group
+
+@enduml
diff --git a/src/docs/sphinx/developerGuide/KeyComponents/Ghosting/global_numbering.plantuml b/src/docs/sphinx/developerGuide/KeyComponents/Ghosting/global_numbering.plantuml
new file mode 100644
index 00000000000..d1d5364d92a
--- /dev/null
+++ b/src/docs/sphinx/developerGuide/KeyComponents/Ghosting/global_numbering.plantuml
@@ -0,0 +1,46 @@
+@startuml
+
+
+
+
+participant "Rank k" as rk
+
+activate rk #WhiteSmoke
+
+rk -> rk++ #LimeGreen: Format mesh information
+deactivate rk
+
+rk -> rk++ #tomato: Exchange mesh information
+[<--> rk: Communications with neighbor\n(mpi send/recv)
+deactivate rk
+
+rk -> rk++ #LimeGreen: Compute intersections\nof edges and faces
+rk -> rk++ #SpringGreen: Sort edges and faces\nfor efficient access
+rk -> rk--++ #SpringGreen: Associate edges and faces\nto neighbor ranks
+rk -> rk--++ #SpringGreen: Invert and sort associations
+|||
+rk -\ rk-- <>
+rk -\ rk-- <>
+
+'deactivate rk
+
+[--> rk++ #tomato: Receive offsets\nfrom previous ranks (mpi scan)
+rk -> rk++ #coral: Compute offsets
+deactivate rk
+rk -->]: Send updated offsets\nto next ranks (mpi scan)
+
+deactivate rk
+
+rk -> rk++ #DeepSkyBlue: Number edges and faces\nconsistently accros ranks
+
+|||
+|||
+
+@enduml
From 82184262528b81ed357e3098c8fa1fbaefeb18dc Mon Sep 17 00:00:00 2001
From: TotoGaz <49004943+TotoGaz@users.noreply.github.com>
Date: Tue, 2 Apr 2024 15:14:59 -0700
Subject: [PATCH 003/106] Forgot toc...
---
.../sphinx/developerGuide/KeyComponents/index_KeyComponents.rst | 2 ++
1 file changed, 2 insertions(+)
diff --git a/src/docs/sphinx/developerGuide/KeyComponents/index_KeyComponents.rst b/src/docs/sphinx/developerGuide/KeyComponents/index_KeyComponents.rst
index 6960fe15c24..4f3ec44f5c9 100644
--- a/src/docs/sphinx/developerGuide/KeyComponents/index_KeyComponents.rst
+++ b/src/docs/sphinx/developerGuide/KeyComponents/index_KeyComponents.rst
@@ -18,6 +18,8 @@ The main code components are described here.
./../../../../coreComponents/mesh/docs/meshDeveloperGuide
+ ./Ghosting/ghosting.rst
+
./../../../../coreComponents/linearAlgebra/docs/DofManager.rst
./LvArray
From fc3154f870ca31b24a440728a3c381352ebbf233 Mon Sep 17 00:00:00 2001
From: TotoGaz <49004943+TotoGaz@users.noreply.github.com>
Date: Tue, 2 Apr 2024 17:35:40 -0700
Subject: [PATCH 004/106] moved doc!
---
.../mesh/docs}/Ghosting/ghosting.rst | 6 +++---
.../mesh/docs}/Ghosting/ghosting_algorithm.plantuml | 0
.../mesh/docs}/Ghosting/global_ghosting_setup.plantuml | 0
.../mesh/docs}/Ghosting/global_numbering.plantuml | 0
.../developerGuide/KeyComponents/index_KeyComponents.rst | 2 +-
5 files changed, 4 insertions(+), 4 deletions(-)
rename src/{docs/sphinx/developerGuide/KeyComponents => coreComponents/mesh/docs}/Ghosting/ghosting.rst (57%)
rename src/{docs/sphinx/developerGuide/KeyComponents => coreComponents/mesh/docs}/Ghosting/ghosting_algorithm.plantuml (100%)
rename src/{docs/sphinx/developerGuide/KeyComponents => coreComponents/mesh/docs}/Ghosting/global_ghosting_setup.plantuml (100%)
rename src/{docs/sphinx/developerGuide/KeyComponents => coreComponents/mesh/docs}/Ghosting/global_numbering.plantuml (100%)
diff --git a/src/docs/sphinx/developerGuide/KeyComponents/Ghosting/ghosting.rst b/src/coreComponents/mesh/docs/Ghosting/ghosting.rst
similarity index 57%
rename from src/docs/sphinx/developerGuide/KeyComponents/Ghosting/ghosting.rst
rename to src/coreComponents/mesh/docs/Ghosting/ghosting.rst
index 95133902259..a3cdf6f5a93 100644
--- a/src/docs/sphinx/developerGuide/KeyComponents/Ghosting/ghosting.rst
+++ b/src/coreComponents/mesh/docs/Ghosting/ghosting.rst
@@ -7,15 +7,15 @@ This describes the setup of the ghosting.
.. _global_ghosting_setup:
-.. uml:: global_ghosting_setup.plantuml
+.. uml:: /coreComponents/mesh/docs/Ghosting/global_ghosting_setup.plantuml
:caption: The global parallel algorithm
.. _global_numbering:
-.. uml:: global_numbering.plantuml
+.. uml:: /coreComponents/mesh/docs/Ghosting/global_numbering.plantuml
:caption: The global numbering algorithm
.. _ghosting_algorithm:
-.. uml:: ghosting_algorithm.plantuml
+.. uml:: /coreComponents/mesh/docs/Ghosting/ghosting_algorithm.plantuml
:caption: The ghosting algorithm
diff --git a/src/docs/sphinx/developerGuide/KeyComponents/Ghosting/ghosting_algorithm.plantuml b/src/coreComponents/mesh/docs/Ghosting/ghosting_algorithm.plantuml
similarity index 100%
rename from src/docs/sphinx/developerGuide/KeyComponents/Ghosting/ghosting_algorithm.plantuml
rename to src/coreComponents/mesh/docs/Ghosting/ghosting_algorithm.plantuml
diff --git a/src/docs/sphinx/developerGuide/KeyComponents/Ghosting/global_ghosting_setup.plantuml b/src/coreComponents/mesh/docs/Ghosting/global_ghosting_setup.plantuml
similarity index 100%
rename from src/docs/sphinx/developerGuide/KeyComponents/Ghosting/global_ghosting_setup.plantuml
rename to src/coreComponents/mesh/docs/Ghosting/global_ghosting_setup.plantuml
diff --git a/src/docs/sphinx/developerGuide/KeyComponents/Ghosting/global_numbering.plantuml b/src/coreComponents/mesh/docs/Ghosting/global_numbering.plantuml
similarity index 100%
rename from src/docs/sphinx/developerGuide/KeyComponents/Ghosting/global_numbering.plantuml
rename to src/coreComponents/mesh/docs/Ghosting/global_numbering.plantuml
diff --git a/src/docs/sphinx/developerGuide/KeyComponents/index_KeyComponents.rst b/src/docs/sphinx/developerGuide/KeyComponents/index_KeyComponents.rst
index 4f3ec44f5c9..2fb4c31d9ac 100644
--- a/src/docs/sphinx/developerGuide/KeyComponents/index_KeyComponents.rst
+++ b/src/docs/sphinx/developerGuide/KeyComponents/index_KeyComponents.rst
@@ -18,7 +18,7 @@ The main code components are described here.
./../../../../coreComponents/mesh/docs/meshDeveloperGuide
- ./Ghosting/ghosting.rst
+ ./../../../../coreComponents/mesh/docs/Ghosting/ghosting.rst
./../../../../coreComponents/linearAlgebra/docs/DofManager.rst
From 44365e520203df4c8fb0a433ce78170b0fb63ad5 Mon Sep 17 00:00:00 2001
From: TotoGaz <49004943+TotoGaz@users.noreply.github.com>
Date: Tue, 2 Apr 2024 18:13:16 -0700
Subject: [PATCH 005/106] small plantuml test
---
src/coreComponents/mesh/docs/Ghosting/ghosting.rst | 5 +++++
src/coreComponents/mesh/docs/Ghosting/test.plantuml | 5 +++++
2 files changed, 10 insertions(+)
create mode 100644 src/coreComponents/mesh/docs/Ghosting/test.plantuml
diff --git a/src/coreComponents/mesh/docs/Ghosting/ghosting.rst b/src/coreComponents/mesh/docs/Ghosting/ghosting.rst
index a3cdf6f5a93..126e28c67bc 100644
--- a/src/coreComponents/mesh/docs/Ghosting/ghosting.rst
+++ b/src/coreComponents/mesh/docs/Ghosting/ghosting.rst
@@ -6,6 +6,11 @@ Ghosting setup
This describes the setup of the ghosting.
+.. _plantuml_test:
+.. uml:: /coreComponents/mesh/docs/Ghosting/test.plantuml
+ :caption: Some test
+
+
.. _global_ghosting_setup:
.. uml:: /coreComponents/mesh/docs/Ghosting/global_ghosting_setup.plantuml
:caption: The global parallel algorithm
diff --git a/src/coreComponents/mesh/docs/Ghosting/test.plantuml b/src/coreComponents/mesh/docs/Ghosting/test.plantuml
new file mode 100644
index 00000000000..fad8541bb08
--- /dev/null
+++ b/src/coreComponents/mesh/docs/Ghosting/test.plantuml
@@ -0,0 +1,5 @@
+@startuml
+
+title Empty Diagram
+
+@enduml
From 15b5cb31bb180e60bf24d73e6121c945203bdc50 Mon Sep 17 00:00:00 2001
From: TotoGaz <49004943+TotoGaz@users.noreply.github.com>
Date: Tue, 2 Apr 2024 19:05:05 -0700
Subject: [PATCH 006/106] update rtd machine
---
.readthedocs.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.readthedocs.yml b/.readthedocs.yml
index cac04680e9d..093ec654d50 100644
--- a/.readthedocs.yml
+++ b/.readthedocs.yml
@@ -4,7 +4,7 @@
version: 2
build:
- os: "ubuntu-20.04"
+ os: "ubuntu-22.04"
apt_packages:
- npm
- plantuml
From 2f5c2f635c2e9502b3e8c4e17285ff62cf4d0612 Mon Sep 17 00:00:00 2001
From: TotoGaz <49004943+TotoGaz@users.noreply.github.com>
Date: Tue, 2 Apr 2024 21:06:02 -0700
Subject: [PATCH 007/106] update plantuml
---
.readthedocs.yml | 5 ++++-
src/conf.py | 2 +-
2 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/.readthedocs.yml b/.readthedocs.yml
index 093ec654d50..b1c5ba8da4b 100644
--- a/.readthedocs.yml
+++ b/.readthedocs.yml
@@ -6,8 +6,9 @@ version: 2
build:
os: "ubuntu-22.04"
apt_packages:
+ - curl
- npm
- - plantuml
+ - openjdk-21-jre-headless
- texlive
tools:
nodejs: "16"
@@ -16,6 +17,8 @@ build:
post_install:
- npm install -g npm@9.8.1
- npm install -g @mermaid-js/mermaid-cli@10.3.1
+ # If you change the `/tmp/plantuml.jar` path, be sure to also update where this path is used as well (e.g. in `conf.py`).
+ - curl -fsSL https://github.com/plantuml/plantuml/releases/download/v1.2024.3/plantuml-gplv2-1.2024.3.jar -o /tmp/plantuml.jar
# Set requirements to build the docs
python:
diff --git a/src/conf.py b/src/conf.py
index 99989855bd3..f27f7843963 100644
--- a/src/conf.py
+++ b/src/conf.py
@@ -112,7 +112,7 @@
'sphinxcontrib.programoutput'
]
-plantuml = "/usr/bin/plantuml"
+plantuml = "/usr/bin/java -Djava.awt.headless=true -jar /tmp/plantuml.jar"
plantuml_output_format = "svg_img"
plot_html_show_source_link = True
From 177397a8a67c7aba339a6c6f6d2e5af380c1f9db Mon Sep 17 00:00:00 2001
From: TotoGaz <49004943+TotoGaz@users.noreply.github.com>
Date: Tue, 2 Apr 2024 21:27:14 -0700
Subject: [PATCH 008/106] fix diagrams + remove tests
---
src/coreComponents/mesh/docs/Ghosting/ghosting.rst | 5 -----
.../mesh/docs/Ghosting/global_ghosting_setup.plantuml | 4 +---
src/coreComponents/mesh/docs/Ghosting/test.plantuml | 5 -----
3 files changed, 1 insertion(+), 13 deletions(-)
delete mode 100644 src/coreComponents/mesh/docs/Ghosting/test.plantuml
diff --git a/src/coreComponents/mesh/docs/Ghosting/ghosting.rst b/src/coreComponents/mesh/docs/Ghosting/ghosting.rst
index 126e28c67bc..a3cdf6f5a93 100644
--- a/src/coreComponents/mesh/docs/Ghosting/ghosting.rst
+++ b/src/coreComponents/mesh/docs/Ghosting/ghosting.rst
@@ -6,11 +6,6 @@ Ghosting setup
This describes the setup of the ghosting.
-.. _plantuml_test:
-.. uml:: /coreComponents/mesh/docs/Ghosting/test.plantuml
- :caption: Some test
-
-
.. _global_ghosting_setup:
.. uml:: /coreComponents/mesh/docs/Ghosting/global_ghosting_setup.plantuml
:caption: The global parallel algorithm
diff --git a/src/coreComponents/mesh/docs/Ghosting/global_ghosting_setup.plantuml b/src/coreComponents/mesh/docs/Ghosting/global_ghosting_setup.plantuml
index 93c4911f182..a53dd78c486 100644
--- a/src/coreComponents/mesh/docs/Ghosting/global_ghosting_setup.plantuml
+++ b/src/coreComponents/mesh/docs/Ghosting/global_ghosting_setup.plantuml
@@ -10,8 +10,6 @@ end box
participant "..." as rtmpn
participant "Rank n" as rn
-==global numbering==
-
activate r0 #WhiteSmoke
activate rtmp0 #WhiteSmoke
activate rkm1 #WhiteSmoke
@@ -37,7 +35,7 @@ r0 -[#tomato]->(90) rkm1++ #LimeGreen
& rkm1 -[#red]>(40) rk
& rkm1 -[#red]>(50) rkp1++ #LimeGreen
& rkp1 -[#red]>(80) rk++ #LimeGreen
-& rkp1 -[#red]>(70) rkm1glob
+& rkp1 -[#red]>(70) rkm1
end group
diff --git a/src/coreComponents/mesh/docs/Ghosting/test.plantuml b/src/coreComponents/mesh/docs/Ghosting/test.plantuml
deleted file mode 100644
index fad8541bb08..00000000000
--- a/src/coreComponents/mesh/docs/Ghosting/test.plantuml
+++ /dev/null
@@ -1,5 +0,0 @@
-@startuml
-
-title Empty Diagram
-
-@enduml
From 1f3c11265311f8b6a37667406113a5f63ecb8d67 Mon Sep 17 00:00:00 2001
From: TotoGaz <49004943+TotoGaz@users.noreply.github.com>
Date: Tue, 2 Apr 2024 21:45:26 -0700
Subject: [PATCH 009/106] add missing package
---
.readthedocs.yml | 1 +
1 file changed, 1 insertion(+)
diff --git a/.readthedocs.yml b/.readthedocs.yml
index b1c5ba8da4b..fb65157537c 100644
--- a/.readthedocs.yml
+++ b/.readthedocs.yml
@@ -7,6 +7,7 @@ build:
os: "ubuntu-22.04"
apt_packages:
- curl
+ - graphviz
- npm
- openjdk-21-jre-headless
- texlive
From 7d25eef6356d7014b75726ccc2fccec31b71474d Mon Sep 17 00:00:00 2001
From: TotoGaz <49004943+TotoGaz@users.noreply.github.com>
Date: Thu, 4 Apr 2024 15:44:33 -0700
Subject: [PATCH 010/106] First version of the poc in python
---
scripts/ghosting.py | 254 ++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 254 insertions(+)
create mode 100644 scripts/ghosting.py
diff --git a/scripts/ghosting.py b/scripts/ghosting.py
new file mode 100644
index 00000000000..f75cda8ae98
--- /dev/null
+++ b/scripts/ghosting.py
@@ -0,0 +1,254 @@
+from collections import defaultdict
+from dataclasses import dataclass
+from glob import glob
+import logging
+import sys
+from typing import (
+ Collection,
+ Dict,
+ Optional,
+ FrozenSet,
+ Mapping
+)
+from copy import deepcopy
+
+from vtkmodules.vtkCommonDataModel import (
+ vtkUnstructuredGrid
+)
+from vtkmodules.vtkIOXML import (
+ vtkXMLUnstructuredGridReader,
+)
+from vtkmodules.util.numpy_support import (
+ vtk_to_numpy,
+ numpy_to_vtk,
+)
+from vtk import (vtkCell,
+ vtkBoundingBox)
+
+logger = logging.getLogger("ghosting")
+
+
+def __read_vtu(vtk_input_file: str) -> Optional[vtkUnstructuredGrid]:
+ reader = vtkXMLUnstructuredGridReader()
+ logger.info(f"Testing file format \"{vtk_input_file}\" using XML format reader...")
+ if reader.CanReadFile(vtk_input_file):
+ reader.SetFileName(vtk_input_file)
+ logger.info(f"Reader matches. Reading file \"{vtk_input_file}\" using XML format reader.")
+ reader.Update()
+ return reader.GetOutput()
+ else:
+ logger.info("Reader did not match the input file format.")
+ return None
+
+
+@dataclass(frozen=True)
+class Node:
+ local: int # vtk index
+ global_: int # vtk global index
+
+
+@dataclass(frozen=True)
+class Edge:
+ nodes: tuple[int, int] # Local indices in the vtk mesh. Sorted.
+
+
+@dataclass(frozen=True)
+class MeshGraph:
+ nodes: Collection[Node]
+ edges: Collection[Edge]
+
+
+def build_edges(mesh: vtkUnstructuredGrid, points_gids) -> Collection[Edge]:
+ tmp: set[Edge] = set()
+ for c in range(mesh.GetNumberOfCells()):
+ cell: vtkCell = mesh.GetCell(c)
+ for e in range(cell.GetNumberOfEdges()):
+ edge: vtkCell = cell.GetEdge(e)
+ ls = edge.GetPointId(0), edge.GetPointId(1)
+ # g0, g1 = points_gids[l0], points_gids[l1]
+ # tmp.add(tuple(sorted((g0, g1))))
+ nodes = tuple(sorted(ls))
+ tmp.add(Edge(nodes))
+ return tuple(tmp)
+
+
+def compute_graph(mesh: vtkUnstructuredGrid) -> MeshGraph:
+ num_points: int = mesh.GetNumberOfPoints()
+ points_gids = vtk_to_numpy(mesh.GetPointData().GetGlobalIds())
+ nodes = []
+ for l, g in enumerate(points_gids):
+ nodes.append(Node(l, g))
+ edges: Collection[Edge] = build_edges(mesh, points_gids)
+ graph: MeshGraph = MeshGraph(tuple(nodes), edges)
+ return graph
+
+
+def find_overlapping_edges(graphs: Collection[MeshGraph], neighbors: Collection[Collection[int]]):
+ # [rank] -> [ [edge sorted global nodes] -> [edge index in the MeshGraph] ]
+ tmp: dict[int, dict[tuple[int, int], int]] = dict()
+ for rank, graph in enumerate(graphs):
+ d: dict[tuple[int, int], int] = {}
+ for ie, edge in enumerate(graph.edges):
+ gn0: int = graph.nodes[edge.nodes[0]].global_
+ gn1: int = graph.nodes[edge.nodes[1]].global_
+ gns: tuple[int, int] = tuple(sorted((gn0, gn1)))
+ d[gns] = ie
+ tmp[rank] = d
+
+ # # Build a global to local map for the nodes
+ # ng2l: dict[int, tuple[int, int]] = {} # local is in fact (rank, local)
+ # for rank, graph in enumerate(graphs):
+ # for node in graph.nodes:
+ # ng2l[node.global_] = (rank, node.local)
+
+ # raise ValueError("TODO") # Maybe `intersections` should be done neighborhood by neighborhood, so is `count`, as a tmp.
+ # [rank_a, rank_b] -> [Collection[Edge]]
+ # intersections: dict[tuple[int, ...], set[tuple[int, int]]] = defaultdict(set)
+
+ rank_to_intersections: list[dict[tuple[int, ...], set[tuple[int, int]]]] = []
+ for i in range(len(graphs)):
+ rank_to_intersections.append(defaultdict(set))
+
+ for current_rank, intersection in enumerate(rank_to_intersections):
+ count: dict[tuple[int, int], set[int]] = defaultdict(set)
+ other_ranks = neighbors[current_rank]
+ # for current_rank, other_ranks in enumerate(neighbors):
+ all_ranks = [current_rank, ] + other_ranks
+ for rank in all_ranks:
+ for edge in tmp[rank]:
+ count[edge].add(rank)
+ for edge, ranks in count.items():
+ if len(ranks) > 0 and current_rank in ranks:
+ intersection[tuple(sorted(ranks))].add(edge)
+
+ # Check if neighborhood is too wide...
+ for current_rank, other_ranks in enumerate(neighbors):
+ i = rank_to_intersections[current_rank]
+ useful_neighbors = set()
+ for ranks, edges in i.items():
+ if edges:
+ useful_neighbors |= set(ranks)
+ print(f"Ranks '{set([current_rank, ] + other_ranks) - useful_neighbors}' are not required for rank {current_rank}.")
+
+ # Now let's build the scan (or equivalent)
+ scans: list[Mapping[tuple[int, ...], int]] = []
+ # for rank in range(len(graphs)): # PUT BACK
+ for rank, intersections in enumerate(rank_to_intersections):
+ scan = {} if len(scans) == 0 else deepcopy(scans[-1])
+ for ranks, edges in intersections.items():
+ # I want the current rank to have its own information for easy access to the offset,
+ # so there's no special case between what the local information and the information from the other ranks.
+ # Hence the `+ 1` so it's included in the `range`
+ if set(range(rank + 1)) & set(ranks):
+ scan[ranks] = len(edges)
+ scans.append(scan)
+
+ offset_scans: list[Mapping[tuple[int, ...], int]] = []
+ for scan in scans:
+ offset_scan: dict[tuple[int, ...], int] = dict()
+ i: int = 0
+ for ranks in sorted(scan.keys()):
+ n: int = scan.get(ranks)
+ offset_scan[ranks] = i
+ i += n
+ offset_scans.append(offset_scan)
+
+ # From `intersections`, let's mimic an intersection for the rank only
+ real_intersection: list[Mapping[tuple[int, ...], FrozenSet[tuple[int, int]]]] = []
+ # for rank in range(len(graphs)): # PUT BACK
+ for rank, intersections in enumerate(rank_to_intersections):
+ i: Dict[tuple[int, ...], set[tuple[int, int]]] = dict()
+ for ranks, edges in intersections.items():
+ if rank in ranks:
+ i[ranks] = edges
+ real_intersection.append(i)
+
+ return real_intersection, offset_scans
+
+
+def do_the_numbering(intersection: Mapping[tuple[int, ...], FrozenSet[tuple[int, int]]],
+ offset_scan: Mapping[tuple[int, ...], int]) -> Mapping[tuple[int, int], int]:
+ numbered_edges: dict[tuple[int, int], int] = dict()
+ for ranks, edges in sorted(intersection.items()):
+ off: int = offset_scan[ranks]
+ for edge in sorted(edges):
+ numbered_edges[edge] = off
+ off += 1
+ return numbered_edges
+
+
+def validation(numberings: Mapping[tuple[int, int], int]) -> int:
+ all_nodes = set()
+ all_edges = dict()
+ for numbering in numberings:
+ for nodes, gei in numbering.items():
+ all_nodes |= set(nodes)
+ res = all_edges.get(nodes)
+ if res is None:
+ all_edges[nodes] = gei
+ elif res != nodes:
+ assert res == gei
+ expected_num_edges: int = 3 * 10 * 11 * 11
+ expected_num_nodes: int = 11 * 11 * 11
+ assert len(all_edges) == expected_num_edges
+ assert set(all_edges.values()) == set(range(expected_num_edges))
+ assert all_nodes == set(range(expected_num_nodes))
+ return 0
+
+
+def build_neighborhood(meshes: Collection[vtkUnstructuredGrid]) -> Collection[Collection[int]]:
+ bounding_boxes: list[vtkBoundingBox] = []
+ for mesh in meshes:
+ bb = vtkBoundingBox()
+ bb.AddBox(mesh.GetBounds())
+ bb.Inflate(0.1)
+ bounding_boxes.append(bb)
+ neighbors: list[list[int]] = []
+ for rank, bb in enumerate(bounding_boxes):
+ n = []
+ for other_rank, other_bb in enumerate(bounding_boxes):
+ if rank == other_rank:
+ continue
+ if bb.Intersects(other_bb):
+ n.append(other_rank)
+ neighbors.append(n)
+ return neighbors
+
+
+def main() -> int:
+ # For each rank, contains the raw vtk mesh.
+ meshes: list[vtkUnstructuredGrid] = []
+ pattern: str = "/Users/j0436735/Downloads/meshes-cube/main-*.vtu"
+ # pattern: str = "/Users/j0436735/Downloads/meshes-cube-25/main-*.vtu"
+ for file_name in glob(pattern):
+ m = __read_vtu(file_name)
+ if m:
+ meshes.append(m)
+
+ # For each rank, contains the neighbor rank (candidates).
+ neighbors: Collection[Collection[int]] = build_neighborhood(meshes)
+
+ # For each rank, contains the graph built upon the vtk mesh.
+ graphs = []
+ for m in meshes:
+ graphs.append(compute_graph(m))
+
+ # Perform the core computation of the intersection.
+ # `intersections` will contain the intersection for each rank,
+ # while `offset_scans` will contains the offset for the global numbering,
+ # as it would be done in during the `MPI_scan`.
+ intersections: Collection[Mapping[tuple[int, ...], FrozenSet[tuple[int, int]]]]
+ offset_scans: Collection[Mapping[tuple[int, ...], int]]
+ intersections, offset_scans = find_overlapping_edges(graphs, neighbors)
+
+ # Finish by doing the global numbering for real.
+ numberings: list[Mapping[tuple[int, int], int]] = []
+ for i, o in zip(intersections, offset_scans):
+ numberings.append(do_the_numbering(i, o))
+
+ # Small validation
+ return validation(numberings)
+
+
+if __name__ == '__main__':
+ sys.exit(main())
From 11f6331b2a121eb2ae577406afaefcf24fd5dca5 Mon Sep 17 00:00:00 2001
From: TotoGaz <49004943+TotoGaz@users.noreply.github.com>
Date: Thu, 4 Apr 2024 16:26:26 -0700
Subject: [PATCH 011/106] A little cleaning before sharing.
---
scripts/ghosting.py | 125 +++++++++++++++++++-------------------------
1 file changed, 53 insertions(+), 72 deletions(-)
diff --git a/scripts/ghosting.py b/scripts/ghosting.py
index f75cda8ae98..a6dd4c3e717 100644
--- a/scripts/ghosting.py
+++ b/scripts/ghosting.py
@@ -1,14 +1,15 @@
from collections import defaultdict
from dataclasses import dataclass
from glob import glob
+from itertools import chain
import logging
import sys
from typing import (
Collection,
- Dict,
+ Iterable,
+ Mapping,
Optional,
- FrozenSet,
- Mapping
+ Sequence,
)
from copy import deepcopy
@@ -20,7 +21,6 @@
)
from vtkmodules.util.numpy_support import (
vtk_to_numpy,
- numpy_to_vtk,
)
from vtk import (vtkCell,
vtkBoundingBox)
@@ -65,15 +65,12 @@ def build_edges(mesh: vtkUnstructuredGrid, points_gids) -> Collection[Edge]:
for e in range(cell.GetNumberOfEdges()):
edge: vtkCell = cell.GetEdge(e)
ls = edge.GetPointId(0), edge.GetPointId(1)
- # g0, g1 = points_gids[l0], points_gids[l1]
- # tmp.add(tuple(sorted((g0, g1))))
- nodes = tuple(sorted(ls))
+ nodes: tuple[int, int] = tuple(sorted(ls))
tmp.add(Edge(nodes))
return tuple(tmp)
def compute_graph(mesh: vtkUnstructuredGrid) -> MeshGraph:
- num_points: int = mesh.GetNumberOfPoints()
points_gids = vtk_to_numpy(mesh.GetPointData().GetGlobalIds())
nodes = []
for l, g in enumerate(points_gids):
@@ -83,90 +80,75 @@ def compute_graph(mesh: vtkUnstructuredGrid) -> MeshGraph:
return graph
-def find_overlapping_edges(graphs: Collection[MeshGraph], neighbors: Collection[Collection[int]]):
- # [rank] -> [ [edge sorted global nodes] -> [edge index in the MeshGraph] ]
- tmp: dict[int, dict[tuple[int, int], int]] = dict()
+def mpi_scan(rank_to_intersections: Iterable[Mapping[tuple[int, ...], frozenset[tuple[int, int]]]]) -> Sequence[Mapping[tuple[int, ...], int]]:
+ scans: list[Mapping[tuple[int, ...], int]] = []
+ for rank, intersections in enumerate(rank_to_intersections):
+ scan = {} if len(scans) == 0 else deepcopy(scans[-1])
+ for ranks, edges in intersections.items():
+ # I want the current rank to have its own information for easy access to the offset,
+ # so there's no special case between what the local information and the information from the other ranks.
+ # Hence the `+ 1` so it's included in the `range`
+ if set(range(rank + 1)) & set(ranks):
+ scan[ranks] = len(edges)
+ scans.append(scan)
+
+ offset_scans: list[Mapping[tuple[int, ...], int]] = []
+ for scan in scans:
+ offset_scan: dict[tuple[int, ...], int] = dict()
+ intersect: int = 0
+ for ranks in sorted(scan.keys()):
+ n: int = scan.get(ranks)
+ offset_scan[ranks] = intersect
+ intersect += n
+ offset_scans.append(offset_scan)
+
+ return offset_scans
+
+
+def find_overlapping_edges(graphs: Collection[MeshGraph], neighbors: Sequence[Collection[int]]):
+ # [rank] -> [edge sorted global nodes]
+ tmp: dict[int, set[tuple[int, int]]] = dict()
for rank, graph in enumerate(graphs):
- d: dict[tuple[int, int], int] = {}
+ # d: dict[tuple[int, int], int] = {}
+ d: set[tuple[int, int]] = set()
for ie, edge in enumerate(graph.edges):
gn0: int = graph.nodes[edge.nodes[0]].global_
gn1: int = graph.nodes[edge.nodes[1]].global_
gns: tuple[int, int] = tuple(sorted((gn0, gn1)))
- d[gns] = ie
+ d.add(gns)
tmp[rank] = d
- # # Build a global to local map for the nodes
- # ng2l: dict[int, tuple[int, int]] = {} # local is in fact (rank, local)
- # for rank, graph in enumerate(graphs):
- # for node in graph.nodes:
- # ng2l[node.global_] = (rank, node.local)
-
- # raise ValueError("TODO") # Maybe `intersections` should be done neighborhood by neighborhood, so is `count`, as a tmp.
- # [rank_a, rank_b] -> [Collection[Edge]]
- # intersections: dict[tuple[int, ...], set[tuple[int, int]]] = defaultdict(set)
-
+ # "Allocate"...
rank_to_intersections: list[dict[tuple[int, ...], set[tuple[int, int]]]] = []
- for i in range(len(graphs)):
+ for intersect in range(len(graphs)):
rank_to_intersections.append(defaultdict(set))
+ # .... fill.
for current_rank, intersection in enumerate(rank_to_intersections):
count: dict[tuple[int, int], set[int]] = defaultdict(set)
other_ranks = neighbors[current_rank]
# for current_rank, other_ranks in enumerate(neighbors):
- all_ranks = [current_rank, ] + other_ranks
- for rank in all_ranks:
+ all_ranks_in_the_neighborhood = chain((current_rank,), other_ranks)
+ for rank in all_ranks_in_the_neighborhood:
for edge in tmp[rank]:
count[edge].add(rank)
for edge, ranks in count.items():
if len(ranks) > 0 and current_rank in ranks:
intersection[tuple(sorted(ranks))].add(edge)
- # Check if neighborhood is too wide...
+ # For information, check if neighborhood is too wide...
for current_rank, other_ranks in enumerate(neighbors):
- i = rank_to_intersections[current_rank]
- useful_neighbors = set()
- for ranks, edges in i.items():
+ intersect: dict[tuple[int, ...], set[tuple[int, int]]] = rank_to_intersections[current_rank]
+ useful_neighbors: set[tuple[int, ...]] = set()
+ for ranks, edges in intersect.items():
if edges:
useful_neighbors |= set(ranks)
- print(f"Ranks '{set([current_rank, ] + other_ranks) - useful_neighbors}' are not required for rank {current_rank}.")
-
- # Now let's build the scan (or equivalent)
- scans: list[Mapping[tuple[int, ...], int]] = []
- # for rank in range(len(graphs)): # PUT BACK
- for rank, intersections in enumerate(rank_to_intersections):
- scan = {} if len(scans) == 0 else deepcopy(scans[-1])
- for ranks, edges in intersections.items():
- # I want the current rank to have its own information for easy access to the offset,
- # so there's no special case between what the local information and the information from the other ranks.
- # Hence the `+ 1` so it's included in the `range`
- if set(range(rank + 1)) & set(ranks):
- scan[ranks] = len(edges)
- scans.append(scan)
-
- offset_scans: list[Mapping[tuple[int, ...], int]] = []
- for scan in scans:
- offset_scan: dict[tuple[int, ...], int] = dict()
- i: int = 0
- for ranks in sorted(scan.keys()):
- n: int = scan.get(ranks)
- offset_scan[ranks] = i
- i += n
- offset_scans.append(offset_scan)
-
- # From `intersections`, let's mimic an intersection for the rank only
- real_intersection: list[Mapping[tuple[int, ...], FrozenSet[tuple[int, int]]]] = []
- # for rank in range(len(graphs)): # PUT BACK
- for rank, intersections in enumerate(rank_to_intersections):
- i: Dict[tuple[int, ...], set[tuple[int, int]]] = dict()
- for ranks, edges in intersections.items():
- if rank in ranks:
- i[ranks] = edges
- real_intersection.append(i)
+ print(f"Ranks '{set([current_rank, ] + other_ranks) - useful_neighbors}' are not required by rank {current_rank}.")
- return real_intersection, offset_scans
+ return rank_to_intersections
-def do_the_numbering(intersection: Mapping[tuple[int, ...], FrozenSet[tuple[int, int]]],
+def do_the_numbering(intersection: Mapping[tuple[int, ...], frozenset[tuple[int, int]]],
offset_scan: Mapping[tuple[int, ...], int]) -> Mapping[tuple[int, int], int]:
numbered_edges: dict[tuple[int, int], int] = dict()
for ranks, edges in sorted(intersection.items()):
@@ -177,7 +159,7 @@ def do_the_numbering(intersection: Mapping[tuple[int, ...], FrozenSet[tuple[int,
return numbered_edges
-def validation(numberings: Mapping[tuple[int, int], int]) -> int:
+def validation(numberings: Iterable[Mapping[tuple[int, int], int]]) -> int:
all_nodes = set()
all_edges = dict()
for numbering in numberings:
@@ -218,8 +200,8 @@ def build_neighborhood(meshes: Collection[vtkUnstructuredGrid]) -> Collection[Co
def main() -> int:
# For each rank, contains the raw vtk mesh.
meshes: list[vtkUnstructuredGrid] = []
- pattern: str = "/Users/j0436735/Downloads/meshes-cube/main-*.vtu"
- # pattern: str = "/Users/j0436735/Downloads/meshes-cube-25/main-*.vtu"
+ # pattern: str = "/Users/j0436735/Downloads/meshes-cube/main-*.vtu"
+ pattern: str = "/Users/j0436735/Downloads/meshes-cube-25/main-*.vtu"
for file_name in glob(pattern):
m = __read_vtu(file_name)
if m:
@@ -237,9 +219,8 @@ def main() -> int:
# `intersections` will contain the intersection for each rank,
# while `offset_scans` will contains the offset for the global numbering,
# as it would be done in during the `MPI_scan`.
- intersections: Collection[Mapping[tuple[int, ...], FrozenSet[tuple[int, int]]]]
- offset_scans: Collection[Mapping[tuple[int, ...], int]]
- intersections, offset_scans = find_overlapping_edges(graphs, neighbors)
+ intersections: Collection[Mapping[tuple[int, ...], frozenset[tuple[int, int]]]] = find_overlapping_edges(graphs, neighbors)
+ offset_scans: Collection[Mapping[tuple[int, ...], int]] = mpi_scan(intersections)
# Finish by doing the global numbering for real.
numberings: list[Mapping[tuple[int, int], int]] = []
From 087897eea8960cb042e4700040562c407df6e641 Mon Sep 17 00:00:00 2001
From: TotoGaz <49004943+TotoGaz@users.noreply.github.com>
Date: Thu, 4 Apr 2024 17:18:04 -0700
Subject: [PATCH 012/106] Little type hints improvements.
---
scripts/ghosting.py | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/scripts/ghosting.py b/scripts/ghosting.py
index a6dd4c3e717..b59bf10efd0 100644
--- a/scripts/ghosting.py
+++ b/scripts/ghosting.py
@@ -58,7 +58,7 @@ class MeshGraph:
edges: Collection[Edge]
-def build_edges(mesh: vtkUnstructuredGrid, points_gids) -> Collection[Edge]:
+def build_edges(mesh: vtkUnstructuredGrid) -> Collection[Edge]:
tmp: set[Edge] = set()
for c in range(mesh.GetNumberOfCells()):
cell: vtkCell = mesh.GetCell(c)
@@ -75,7 +75,7 @@ def compute_graph(mesh: vtkUnstructuredGrid) -> MeshGraph:
nodes = []
for l, g in enumerate(points_gids):
nodes.append(Node(l, g))
- edges: Collection[Edge] = build_edges(mesh, points_gids)
+ edges: Collection[Edge] = build_edges(mesh)
graph: MeshGraph = MeshGraph(tuple(nodes), edges)
return graph
@@ -87,7 +87,7 @@ def mpi_scan(rank_to_intersections: Iterable[Mapping[tuple[int, ...], frozenset[
for ranks, edges in intersections.items():
# I want the current rank to have its own information for easy access to the offset,
# so there's no special case between what the local information and the information from the other ranks.
- # Hence the `+ 1` so it's included in the `range`
+ # Hence, the `+ 1` so it's included in the `range`
if set(range(rank + 1)) & set(ranks):
scan[ranks] = len(edges)
scans.append(scan)
@@ -105,7 +105,7 @@ def mpi_scan(rank_to_intersections: Iterable[Mapping[tuple[int, ...], frozenset[
return offset_scans
-def find_overlapping_edges(graphs: Collection[MeshGraph], neighbors: Sequence[Collection[int]]):
+def find_overlapping_edges(graphs: Collection[MeshGraph], neighbors: Sequence[Iterable[int]]):
# [rank] -> [edge sorted global nodes]
tmp: dict[int, set[tuple[int, int]]] = dict()
for rank, graph in enumerate(graphs):
@@ -178,7 +178,7 @@ def validation(numberings: Iterable[Mapping[tuple[int, int], int]]) -> int:
return 0
-def build_neighborhood(meshes: Collection[vtkUnstructuredGrid]) -> Collection[Collection[int]]:
+def build_neighborhood(meshes: Collection[vtkUnstructuredGrid]) -> Sequence[Sequence[int]]:
bounding_boxes: list[vtkBoundingBox] = []
for mesh in meshes:
bb = vtkBoundingBox()
@@ -208,7 +208,7 @@ def main() -> int:
meshes.append(m)
# For each rank, contains the neighbor rank (candidates).
- neighbors: Collection[Collection[int]] = build_neighborhood(meshes)
+ neighbors: Sequence[Sequence[int]] = build_neighborhood(meshes)
# For each rank, contains the graph built upon the vtk mesh.
graphs = []
@@ -217,7 +217,7 @@ def main() -> int:
# Perform the core computation of the intersection.
# `intersections` will contain the intersection for each rank,
- # while `offset_scans` will contains the offset for the global numbering,
+ # while `offset_scans` will contain the offset for the global numbering,
# as it would be done in during the `MPI_scan`.
intersections: Collection[Mapping[tuple[int, ...], frozenset[tuple[int, int]]]] = find_overlapping_edges(graphs, neighbors)
offset_scans: Collection[Mapping[tuple[int, ...], int]] = mpi_scan(intersections)
From ae9a45641d3be1b29f29bb6ca3132f644071b5c7 Mon Sep 17 00:00:00 2001
From: TotoGaz <49004943+TotoGaz@users.noreply.github.com>
Date: Fri, 5 Apr 2024 18:59:05 -0700
Subject: [PATCH 013/106] Small optimization
---
scripts/ghosting.py | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/scripts/ghosting.py b/scripts/ghosting.py
index b59bf10efd0..1c0a8cc30fc 100644
--- a/scripts/ghosting.py
+++ b/scripts/ghosting.py
@@ -93,13 +93,13 @@ def mpi_scan(rank_to_intersections: Iterable[Mapping[tuple[int, ...], frozenset[
scans.append(scan)
offset_scans: list[Mapping[tuple[int, ...], int]] = []
- for scan in scans:
+ for rank, scan in enumerate(scans):
offset_scan: dict[tuple[int, ...], int] = dict()
intersect: int = 0
for ranks in sorted(scan.keys()):
- n: int = scan.get(ranks)
- offset_scan[ranks] = intersect
- intersect += n
+ if max(ranks) >= rank: # Remove the entries that cannot play any more role.
+ offset_scan[ranks] = intersect
+ intersect += scan.get(ranks)
offset_scans.append(offset_scan)
return offset_scans
From 778cd82a57553a2fa574b22174589c3f7c62c7de Mon Sep 17 00:00:00 2001
From: TotoGaz <49004943+TotoGaz@users.noreply.github.com>
Date: Fri, 5 Apr 2024 21:09:40 -0700
Subject: [PATCH 014/106] Revert "Small optimization"
This reverts commit ae9a45641d3be1b29f29bb6ca3132f644071b5c7.
---
scripts/ghosting.py | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/scripts/ghosting.py b/scripts/ghosting.py
index 1c0a8cc30fc..b59bf10efd0 100644
--- a/scripts/ghosting.py
+++ b/scripts/ghosting.py
@@ -93,13 +93,13 @@ def mpi_scan(rank_to_intersections: Iterable[Mapping[tuple[int, ...], frozenset[
scans.append(scan)
offset_scans: list[Mapping[tuple[int, ...], int]] = []
- for rank, scan in enumerate(scans):
+ for scan in scans:
offset_scan: dict[tuple[int, ...], int] = dict()
intersect: int = 0
for ranks in sorted(scan.keys()):
- if max(ranks) >= rank: # Remove the entries that cannot play any more role.
- offset_scan[ranks] = intersect
- intersect += scan.get(ranks)
+ n: int = scan.get(ranks)
+ offset_scan[ranks] = intersect
+ intersect += n
offset_scans.append(offset_scan)
return offset_scans
From 5d2bf531ae30104d1cc89e3ffcc5664ac4080377 Mon Sep 17 00:00:00 2001
From: TotoGaz <49004943+TotoGaz@users.noreply.github.com>
Date: Wed, 10 Apr 2024 15:02:58 -0700
Subject: [PATCH 015/106] First version that's exchanging edges properly.
---
scripts/NamedType.py | 31 +++
scripts/ghosting.py | 6 +-
src/coreComponents/common/GeosxConfig.hpp.in | 2 +-
src/coreComponents/mesh/CMakeLists.txt | 21 ++
.../mesh/generators/NewGhosting.cpp | 247 ++++++++++++++++++
.../mesh/generators/NewGhosting.hpp | 31 +++
.../mesh/generators/VTKMeshGenerator.cpp | 11 +
.../mesh/generators/VTKMeshGenerator.hpp | 4 +
.../mesh/mpiCommunications/CommID.hpp | 2 +-
9 files changed, 350 insertions(+), 5 deletions(-)
create mode 100644 scripts/NamedType.py
create mode 100644 src/coreComponents/mesh/generators/NewGhosting.cpp
create mode 100644 src/coreComponents/mesh/generators/NewGhosting.hpp
diff --git a/scripts/NamedType.py b/scripts/NamedType.py
new file mode 100644
index 00000000000..b1d0173e95e
--- /dev/null
+++ b/scripts/NamedType.py
@@ -0,0 +1,31 @@
+import logging
+
+import gdb
+
+logger = logging.getLogger("NamedType")
+
+
+class NamedTypePrinter(object):
+ def __init__(self, val: gdb.Value):
+ self.val = val["value_"]
+
+ def to_string(self) -> str:
+ return self.val
+
+
+def build_array_printer():
+ pp = gdb.printing.RegexpCollectionPrettyPrinter("NamedType")
+ pp.add_printer('fluent::NamedType', '^fluent::NamedType<.*>$', NamedTypePrinter)
+ return pp
+
+
+try:
+ import gdb.printing
+ gdb.printing.register_pretty_printer(gdb.current_objfile(), build_array_printer())
+except ImportError:
+ logger.warning("Could not register LvArray pretty printers.")
+
+
+# import debugpy
+# debugpy.listen(("0.0.0.0", 64018))
+# debugpy.wait_for_client()
diff --git a/scripts/ghosting.py b/scripts/ghosting.py
index b59bf10efd0..b65ba557197 100644
--- a/scripts/ghosting.py
+++ b/scripts/ghosting.py
@@ -200,9 +200,9 @@ def build_neighborhood(meshes: Collection[vtkUnstructuredGrid]) -> Sequence[Sequ
def main() -> int:
# For each rank, contains the raw vtk mesh.
meshes: list[vtkUnstructuredGrid] = []
- # pattern: str = "/Users/j0436735/Downloads/meshes-cube/main-*.vtu"
- pattern: str = "/Users/j0436735/Downloads/meshes-cube-25/main-*.vtu"
- for file_name in glob(pattern):
+ pattern: str = "/Users/j0436735/Downloads/meshes-cube/main-*.vtu"
+ # pattern: str = "/Users/j0436735/Downloads/meshes-cube-25/main-*.vtu"
+ for file_name in sorted(glob(pattern)):
m = __read_vtu(file_name)
if m:
meshes.append(m)
diff --git a/src/coreComponents/common/GeosxConfig.hpp.in b/src/coreComponents/common/GeosxConfig.hpp.in
index 4b69fa93652..debea82b685 100644
--- a/src/coreComponents/common/GeosxConfig.hpp.in
+++ b/src/coreComponents/common/GeosxConfig.hpp.in
@@ -165,7 +165,7 @@
#cmakedefine petsc_VERSION @petsc_VERSION@
/// Version information for VTK
-#cmakedefine VTK_VERSION @VTK_VERSION@
+// #cmakedefine VTK_VERSION @VTK_VERSION@
/// Version information for fmt
#cmakedefine fmt_VERSION @fmt_VERSION@
diff --git a/src/coreComponents/mesh/CMakeLists.txt b/src/coreComponents/mesh/CMakeLists.txt
index 1fafa2eb0a6..1ad47f2e12f 100644
--- a/src/coreComponents/mesh/CMakeLists.txt
+++ b/src/coreComponents/mesh/CMakeLists.txt
@@ -152,10 +152,30 @@ set( mesh_sources
set( dependencyList ${parallelDeps} schema dataRepository constitutive finiteElement parmetis metis )
+include( FetchContent )
+
+FetchContent_Declare(
+ NamedType
+ GIT_REPOSITORY https://github.com/joboccara/NamedType.git
+ GIT_TAG master
+)
+
+FetchContent_GetProperties( NamedType )
+#FetchContent_MakeAvailable( namedtype )
+if( NOT namedtype_POPULATED )
+ message( STATUS "Fetching NamedType..." )
+ FetchContent_Populate( NamedType )
+ add_subdirectory( ${namedtype_SOURCE_DIR} ${namedtype_BINARY_DIR} )
+endif()
+
+list( APPEND dependencyList NamedType )
+
+
if( ENABLE_VTK )
message(STATUS "Adding VTK readers")
set( mesh_headers ${mesh_headers}
generators/CollocatedNodes.hpp
+ generators/NewGhosting.hpp
generators/VTKFaceBlockUtilities.hpp
generators/VTKMeshGenerator.hpp
generators/VTKMeshGeneratorTools.hpp
@@ -164,6 +184,7 @@ if( ENABLE_VTK )
)
set( mesh_sources ${mesh_sources}
generators/CollocatedNodes.cpp
+ generators/NewGhosting.cpp
generators/VTKFaceBlockUtilities.cpp
generators/VTKMeshGenerator.cpp
generators/VTKMeshGeneratorTools.cpp
diff --git a/src/coreComponents/mesh/generators/NewGhosting.cpp b/src/coreComponents/mesh/generators/NewGhosting.cpp
new file mode 100644
index 00000000000..a3107ed2402
--- /dev/null
+++ b/src/coreComponents/mesh/generators/NewGhosting.cpp
@@ -0,0 +1,247 @@
+/*
+ * ------------------------------------------------------------------------------------------------------------
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ * Copyright (c) 2018-2020 Lawrence Livermore National Security LLC
+ * Copyright (c) 2018-2020 The Board of Trustees of the Leland Stanford Junior University
+ * Copyright (c) 2018-2020 TotalEnergies
+ * Copyright (c) 2019- GEOSX Contributors
+ * All rights reserved
+ *
+ * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details.
+ * ------------------------------------------------------------------------------------------------------------
+ */
+
+#include "NewGhosting.hpp"
+
+#include "mesh/mpiCommunications/CommunicationTools.hpp"
+#include "mesh/mpiCommunications/MPI_iCommData.hpp"
+#include "mesh/mpiCommunications/NeighborCommunicator.hpp"
+
+#include "common/MpiWrapper.hpp"
+#include "common/DataTypes.hpp"
+
+#include
+
+#include
+
+#include
+#include
+
+
+namespace geos::ghosting
+{
+
+using NodeLocIdx = fluent::NamedType< localIndex, struct NodeLocIdxTag, fluent::Comparable, fluent::Printable >;
+using NodeGlbIdx = fluent::NamedType< globalIndex, struct NodeGlbIdxTag, fluent::Comparable, fluent::Printable >;
+using EdgeLocIdx = fluent::NamedType< localIndex, struct EdgeLocIdxTag, fluent::Comparable, fluent::Printable >;
+using EdgeGlbIdx = fluent::NamedType< globalIndex, struct EdgeGlbIdxTag, fluent::Comparable, fluent::Printable >;
+using FaceLocIdx = fluent::NamedType< localIndex, struct FaceLocIdxTag, fluent::Comparable, fluent::Printable >;
+using FaceGlbIdx = fluent::NamedType< globalIndex, struct FaceGlbIdxTag, fluent::Comparable, fluent::Printable >;
+using CellLocIdx = fluent::NamedType< localIndex, struct CellLocIdxTag, fluent::Comparable, fluent::Printable >;
+using CellGlbIdx = fluent::NamedType< globalIndex, struct CellGlbIdxTag, fluent::Comparable, fluent::Printable >;
+
+using MpiRank = fluent::NamedType< int, struct MpiRankTag, fluent::Comparable, fluent::Printable >;
+
+//struct Edge
+//{
+// std::pair< NodeGlbIdx, NodeGlbIdx > nodes;
+//};
+
+//struct Face
+//{
+// std::vector< NodeGlbIdx > nodes;
+//};
+
+using Edge = std::pair< NodeGlbIdx, NodeGlbIdx >;
+using Face = std::vector< NodeGlbIdx >;
+
+struct Exchange
+{
+ std::set< Edge > edges;
+// std::set< Face > faces;
+};
+
+Exchange buildExchangeData( vtkSmartPointer< vtkDataSet > mesh )
+{
+ vtkIdTypeArray const * globalPtIds = vtkIdTypeArray::FastDownCast( mesh->GetPointData()->GetGlobalIds() );
+
+ std::vector< Edge > tmp;
+
+ // Pre-allocation of the temporary.
+ {
+ std::size_t numEdges = 0;
+ for( auto c = 0; c < mesh->GetNumberOfCells(); ++c )
+ {
+ vtkCell * cell = mesh->GetCell( c );
+ numEdges += cell->GetNumberOfEdges();
+ }
+ tmp.reserve( numEdges );
+ }
+
+ // Filling the temporary.
+ for( auto c = 0; c < mesh->GetNumberOfCells(); ++c )
+ {
+ vtkCell * cell = mesh->GetCell( c );
+ for( auto e = 0; e < cell->GetNumberOfEdges(); ++e )
+ {
+ vtkCell * edge = cell->GetEdge( e );
+ vtkIdType const ln0 = edge->GetPointId( 0 ), ln1 = edge->GetPointId( 1 );
+ vtkIdType const gn0 = globalPtIds->GetValue( ln0 ), gn1 = globalPtIds->GetValue( ln1 );
+ tmp.emplace_back( std::minmax( { gn0, gn1 } ) );
+ }
+ }
+
+ // Removing the duplicates by copying into a `std::set`.
+ std::set< Edge > const edges{ tmp.cbegin(), tmp.cend() };
+
+ return { edges };
+}
+
+array1d< globalIndex > convertExchange( Exchange const & exchange )
+{
+ array1d< globalIndex > result;
+ result.reserve( 2 * exchange.edges.size() );
+ for( Edge const & edge: exchange.edges )
+ {
+ result.emplace_back( edge.first.get() );
+ result.emplace_back( edge.second.get() );
+ }
+
+ return result;
+}
+
+Exchange convertExchange( array1d< globalIndex > const & input )
+{
+ Exchange exchange;
+
+ for( auto i = 0; i < input.size(); ++ ++i )
+ {
+ NodeGlbIdx gn0{ input[i] }, gn1{ input[i + 1] };
+ exchange.edges.insert( std::minmax( gn0, gn1 ) );
+ }
+
+ return exchange;
+}
+
+/**
+ * @brief
+ * @param exchanged
+ * @param neighborhood including current rank
+ */
+std::map< std::set< MpiRank >, std::set< Edge > > findOverlappingEdges( std::map< MpiRank, Exchange > const & exchanged,
+ MpiRank curRank,
+ std::set< MpiRank > const & neighborhood )
+{
+ GEOS_LOG_RANK( "Starting findOverlappingEdges" );
+ GEOS_LOG_RANK( "exchanged.size() = " << exchanged.size() );
+
+ std::map< Edge, std::set< MpiRank > > counts; // TODO Use better intersection algorithms?
+ for( MpiRank const & rank: neighborhood )
+ {
+ for( Edge const & edge: exchanged.at( rank ).edges )
+ {
+ counts[edge].insert( rank );
+ }
+ }
+
+ std::map< std::set< MpiRank >, std::set< Edge > > ranksToIntersections;
+ for( auto const & [edge, ranks]: counts )
+ {
+ if( ranks.find( curRank ) != ranks.cend() )
+ {
+ ranksToIntersections[ranks].insert( edge );
+ }
+ }
+
+ // Checking if neighborhood is too wide... // TODO do we care?
+ std::set< MpiRank > usefulNeighbors;
+ for( auto const & [ranks, edges]: ranksToIntersections )
+ {
+ if( not edges.empty() )
+ {
+ usefulNeighbors.insert( ranks.cbegin(), ranks.cend() );
+ }
+ }
+ std::vector< MpiRank > uselessNeighbors;
+ std::set_difference( neighborhood.cbegin(), neighborhood.cend(), usefulNeighbors.cbegin(), usefulNeighbors.cend(), std::back_inserter( uselessNeighbors ) );
+ // TODO... Remove the neighbors?
+ GEOS_LOG_RANK( "Ending findOverlappingEdges" );
+
+ return ranksToIntersections;
+}
+
+// TODO Duplicated
+std::map< MpiRank, Exchange > exchange( int commId,
+ std::vector< NeighborCommunicator > & neighbors,
+ Exchange && data )
+{
+ MPI_iCommData commData( commId );
+ integer const numNeighbors = LvArray::integerConversion< integer >( neighbors.size() );
+ commData.resize( numNeighbors );
+
+
+ array1d< globalIndex > const cv = convertExchange( data );
+
+ for( integer i = 0; i < numNeighbors; ++i )
+ {
+ neighbors[i].mpiISendReceiveSizes( cv,
+ commData.mpiSendBufferSizeRequest( i ),
+ commData.mpiRecvBufferSizeRequest( i ),
+ commId,
+ MPI_COMM_GEOSX );
+ }
+
+ MpiWrapper::waitAll( numNeighbors, commData.mpiSendBufferSizeRequest(), commData.mpiSendBufferSizeStatus() );
+ MpiWrapper::waitAll( numNeighbors, commData.mpiRecvBufferSizeRequest(), commData.mpiRecvBufferSizeStatus() );
+
+ array1d< array1d< globalIndex > > tmpOutput( neighbors.size() );
+
+ for( integer i = 0; i < numNeighbors; ++i )
+ {
+ neighbors[i].mpiISendReceiveData( cv,
+ commData.mpiSendBufferRequest( i ),
+ tmpOutput[i],
+ commData.mpiRecvBufferRequest( i ),
+ commId,
+ MPI_COMM_GEOSX );
+ }
+ MpiWrapper::waitAll( numNeighbors, commData.mpiSendBufferRequest(), commData.mpiSendBufferStatus() );
+ MpiWrapper::waitAll( numNeighbors, commData.mpiRecvBufferRequest(), commData.mpiRecvBufferStatus() );
+
+ std::map< MpiRank, Exchange > output;
+ for( auto i = 0; i < numNeighbors; ++i )
+ {
+ output[MpiRank{ neighbors[i].neighborRank() }] = convertExchange( tmpOutput[i] );
+ }
+ output[MpiRank{ MpiWrapper::commRank() }] = std::move( data );
+ return output;
+}
+
+
+void doTheNewGhosting( vtkSmartPointer< vtkDataSet > mesh,
+ std::set< int > const & neighbors )
+{
+ // Now we exchange the data with our neighbors.
+ MpiRank const curRank{ MpiWrapper::commRank() };
+
+ std::vector< NeighborCommunicator > ncs;
+ for( int const & rank: neighbors )
+ {
+ ncs.emplace_back( rank );
+ }
+
+ std::set< MpiRank > neighborhood;
+ for( int const & rank: neighbors )
+ {
+ neighborhood.insert( MpiRank{ rank } );
+ }
+ neighborhood.insert( curRank );
+
+ CommID const commId = CommunicationTools::getInstance().getCommID();
+ std::map< MpiRank, Exchange > const exchanged = exchange( int( commId ), ncs, buildExchangeData( mesh ) );
+
+ std::map< std::set< MpiRank >, std::set< Edge > > const overlappingEdges = findOverlappingEdges( exchanged, curRank, neighborhood );
+}
+
+} // end of namespace geos::ghosting
diff --git a/src/coreComponents/mesh/generators/NewGhosting.hpp b/src/coreComponents/mesh/generators/NewGhosting.hpp
new file mode 100644
index 00000000000..b908d9cfb2c
--- /dev/null
+++ b/src/coreComponents/mesh/generators/NewGhosting.hpp
@@ -0,0 +1,31 @@
+/*
+ * ------------------------------------------------------------------------------------------------------------
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ * Copyright (c) 2018-2020 Lawrence Livermore National Security LLC
+ * Copyright (c) 2018-2020 The Board of Trustees of the Leland Stanford Junior University
+ * Copyright (c) 2018-2020 TotalEnergies
+ * Copyright (c) 2019- GEOSX Contributors
+ * All rights reserved
+ *
+ * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details.
+ * ------------------------------------------------------------------------------------------------------------
+ */
+
+#ifndef GEOS_NEWGHOSTING_HPP
+#define GEOS_NEWGHOSTING_HPP
+
+#include
+#include
+
+#include
+
+namespace geos::ghosting
+{
+
+void doTheNewGhosting( vtkSmartPointer< vtkDataSet > mesh,
+ std::set< int > const & neighbors );
+
+} // end of namespace ghosting
+
+#endif // include guard
diff --git a/src/coreComponents/mesh/generators/VTKMeshGenerator.cpp b/src/coreComponents/mesh/generators/VTKMeshGenerator.cpp
index b45ed3f9e30..72ebf48c0d1 100644
--- a/src/coreComponents/mesh/generators/VTKMeshGenerator.cpp
+++ b/src/coreComponents/mesh/generators/VTKMeshGenerator.cpp
@@ -21,6 +21,7 @@
#include "mesh/generators/VTKFaceBlockUtilities.hpp"
#include "mesh/generators/VTKMeshGeneratorTools.hpp"
#include "mesh/generators/CellBlockManager.hpp"
+#include "mesh/generators/NewGhosting.hpp"
#include "common/DataTypes.hpp"
#include
@@ -74,6 +75,11 @@ VTKMeshGenerator::VTKMeshGenerator( string const & name,
" If set to 0 (default value), the GlobalId arrays in the input mesh are used if available, and generated otherwise."
" If set to a negative value, the GlobalId arrays in the input mesh are not used, and generated global Ids are automatically generated."
" If set to a positive value, the GlobalId arrays in the input mesh are used and required, and the simulation aborts if they are not available" );
+
+ registerWrapper( viewKeyStruct::useNewGhostingString(), &m_useNewGhosting ).
+ setInputFlag( InputFlags::OPTIONAL ).
+ setApplyDefaultValue( 0 ).
+ setDescription( "Controls the use of the new ghosting implementation." );
}
void VTKMeshGenerator::fillCellBlockManager( CellBlockManager & cellBlockManager, SpatialPartition & partition )
@@ -102,6 +108,11 @@ void VTKMeshGenerator::fillCellBlockManager( CellBlockManager & cellBlockManager
}
GEOS_LOG_RANK_0( GEOS_FMT( "{} '{}': generating GEOSX mesh data structure", catalogName(), getName() ) );
+ if( m_useNewGhosting )
+ {
+ GEOS_LOG_RANK( "Here we go, new ghosting!" );
+ ghosting::doTheNewGhosting( m_vtkMesh, partition.getMetisNeighborList() );
+ }
GEOS_LOG_LEVEL_RANK_0( 2, " preprocessing..." );
m_cellMap = vtk::buildCellMap( *m_vtkMesh, m_attributeName );
diff --git a/src/coreComponents/mesh/generators/VTKMeshGenerator.hpp b/src/coreComponents/mesh/generators/VTKMeshGenerator.hpp
index 3fae5d6d343..83845f27c42 100644
--- a/src/coreComponents/mesh/generators/VTKMeshGenerator.hpp
+++ b/src/coreComponents/mesh/generators/VTKMeshGenerator.hpp
@@ -109,6 +109,7 @@ class VTKMeshGenerator : public ExternalMeshGeneratorBase
constexpr static char const * partitionRefinementString() { return "partitionRefinement"; }
constexpr static char const * partitionMethodString() { return "partitionMethod"; }
constexpr static char const * useGlobalIdsString() { return "useGlobalIds"; }
+ constexpr static char const * useNewGhostingString() { return "useNewGhosting"; }
};
/// @endcond
@@ -149,6 +150,9 @@ class VTKMeshGenerator : public ExternalMeshGeneratorBase
/// Whether global id arrays should be used, if available
integer m_useGlobalIds = 0;
+ // Whether we should use the new ghosting implementation.
+ integer m_useNewGhosting = 0;
+
/// Method (library) used to partition the mesh
vtk::PartitionMethod m_partitionMethod = vtk::PartitionMethod::parmetis;
diff --git a/src/coreComponents/mesh/mpiCommunications/CommID.hpp b/src/coreComponents/mesh/mpiCommunications/CommID.hpp
index 143e55eb18c..7c904234f07 100644
--- a/src/coreComponents/mesh/mpiCommunications/CommID.hpp
+++ b/src/coreComponents/mesh/mpiCommunications/CommID.hpp
@@ -59,7 +59,7 @@ class CommID
CommID & operator=( CommID && ) = delete;
/// user defined conversion operator to int
- constexpr operator int()
+ constexpr operator int() const
{ return m_id; }
private:
From bcd7fba87385f4987c9b9bea105ff44faf0f90f6 Mon Sep 17 00:00:00 2001
From: TotoGaz <49004943+TotoGaz@users.noreply.github.com>
Date: Thu, 11 Apr 2024 23:34:34 -0700
Subject: [PATCH 016/106] Use hollow meshes for neighboring ranks
(optimization)
---
scripts/ghosting.py | 79 +++++++++++++++++++++++++++++++++------------
1 file changed, 58 insertions(+), 21 deletions(-)
diff --git a/scripts/ghosting.py b/scripts/ghosting.py
index b65ba557197..38640c71614 100644
--- a/scripts/ghosting.py
+++ b/scripts/ghosting.py
@@ -6,6 +6,7 @@
import sys
from typing import (
Collection,
+ Generator,
Iterable,
Mapping,
Optional,
@@ -14,16 +15,22 @@
from copy import deepcopy
from vtkmodules.vtkCommonDataModel import (
- vtkUnstructuredGrid
+ vtkBoundingBox,
+ vtkCell,
+ vtkPolyData,
+ vtkUnstructuredGrid,
)
from vtkmodules.vtkIOXML import (
vtkXMLUnstructuredGridReader,
)
+from vtkmodules.vtkFiltersGeometry import (
+ vtkDataSetSurfaceFilter,
+)
from vtkmodules.util.numpy_support import (
vtk_to_numpy,
)
-from vtk import (vtkCell,
- vtkBoundingBox)
+# from vtk import (vtkCell,
+# vtkBoundingBox)
logger = logging.getLogger("ghosting")
@@ -58,9 +65,11 @@ class MeshGraph:
edges: Collection[Edge]
-def build_edges(mesh: vtkUnstructuredGrid) -> Collection[Edge]:
+def build_edges(mesh: vtkUnstructuredGrid, cells: Generator[int, None, None] | None) -> Collection[Edge]:
+ if cells is None:
+ cells = range(mesh.GetNumberOfCells())
tmp: set[Edge] = set()
- for c in range(mesh.GetNumberOfCells()):
+ for c in cells:
cell: vtkCell = mesh.GetCell(c)
for e in range(cell.GetNumberOfEdges()):
edge: vtkCell = cell.GetEdge(e)
@@ -70,16 +79,32 @@ def build_edges(mesh: vtkUnstructuredGrid) -> Collection[Edge]:
return tuple(tmp)
-def compute_graph(mesh: vtkUnstructuredGrid) -> MeshGraph:
+def compute_graph(mesh: vtkUnstructuredGrid, cells=None) -> MeshGraph:
points_gids = vtk_to_numpy(mesh.GetPointData().GetGlobalIds())
nodes = []
for l, g in enumerate(points_gids):
nodes.append(Node(l, g))
- edges: Collection[Edge] = build_edges(mesh)
+ edges: Collection[Edge] = build_edges(mesh, cells)
graph: MeshGraph = MeshGraph(tuple(nodes), edges)
return graph
+def compute_hollow_graph(mesh: vtkUnstructuredGrid) -> MeshGraph:
+ f = vtkDataSetSurfaceFilter()
+ f.PassThroughCellIdsOn()
+ f.PassThroughPointIdsOff()
+ f.FastModeOff()
+
+ # Note that we do not need the original points, but we could keep them as well if needed
+ original_cells_key = "ORIGINAL_CELLS"
+ f.SetOriginalCellIdsName(original_cells_key)
+
+ boundary_mesh = vtkPolyData()
+ f.UnstructuredGridExecute(mesh, boundary_mesh)
+ original_cells = vtk_to_numpy(boundary_mesh.GetCellData().GetArray(original_cells_key))
+ return compute_graph(mesh, set(original_cells))
+
+
def mpi_scan(rank_to_intersections: Iterable[Mapping[tuple[int, ...], frozenset[tuple[int, int]]]]) -> Sequence[Mapping[tuple[int, ...], int]]:
scans: list[Mapping[tuple[int, ...], int]] = []
for rank, intersections in enumerate(rank_to_intersections):
@@ -105,8 +130,10 @@ def mpi_scan(rank_to_intersections: Iterable[Mapping[tuple[int, ...], frozenset[
return offset_scans
-def find_overlapping_edges(graphs: Collection[MeshGraph], neighbors: Sequence[Iterable[int]]):
- # [rank] -> [edge sorted global nodes]
+def build_rank_to_edges(graphs: Iterable[MeshGraph]) -> dict[int, set[tuple[int, int]]]:
+ """
+ Builds the mapping from ranks to the edges (as pairs of global node indices)
+ """
tmp: dict[int, set[tuple[int, int]]] = dict()
for rank, graph in enumerate(graphs):
# d: dict[tuple[int, int], int] = {}
@@ -117,23 +144,31 @@ def find_overlapping_edges(graphs: Collection[MeshGraph], neighbors: Sequence[It
gns: tuple[int, int] = tuple(sorted((gn0, gn1)))
d.add(gns)
tmp[rank] = d
+ return tmp
+
+
+def find_overlapping_edges(graphs: Collection[MeshGraph],
+ hollow_graphs: Collection[MeshGraph],
+ neighbors: Sequence[Iterable[int]]):
+ # [rank] -> [edge sorted global nodes]
+ tmp_g: Mapping[int, set[tuple[int, int]]] = build_rank_to_edges(graphs)
+ tmp_hg: Mapping[int, set[tuple[int, int]]] = build_rank_to_edges(hollow_graphs)
- # "Allocate"...
+ # "Instanciate"...
rank_to_intersections: list[dict[tuple[int, ...], set[tuple[int, int]]]] = []
for intersect in range(len(graphs)):
rank_to_intersections.append(defaultdict(set))
- # .... fill.
+ # ... fill.
for current_rank, intersection in enumerate(rank_to_intersections):
count: dict[tuple[int, int], set[int]] = defaultdict(set)
- other_ranks = neighbors[current_rank]
- # for current_rank, other_ranks in enumerate(neighbors):
- all_ranks_in_the_neighborhood = chain((current_rank,), other_ranks)
- for rank in all_ranks_in_the_neighborhood:
- for edge in tmp[rank]:
+ for edge in tmp_g[current_rank]:
+ count[edge].add(current_rank)
+ for rank in neighbors[current_rank]:
+ for edge in tmp_hg[rank]:
count[edge].add(rank)
for edge, ranks in count.items():
- if len(ranks) > 0 and current_rank in ranks:
+ if current_rank in ranks:
intersection[tuple(sorted(ranks))].add(edge)
# For information, check if neighborhood is too wide...
@@ -200,8 +235,8 @@ def build_neighborhood(meshes: Collection[vtkUnstructuredGrid]) -> Sequence[Sequ
def main() -> int:
# For each rank, contains the raw vtk mesh.
meshes: list[vtkUnstructuredGrid] = []
- pattern: str = "/Users/j0436735/Downloads/meshes-cube/main-*.vtu"
- # pattern: str = "/Users/j0436735/Downloads/meshes-cube-25/main-*.vtu"
+ # pattern: str = "/Users/j0436735/Downloads/meshes-cube/main-*.vtu"
+ pattern: str = "/Users/j0436735/Downloads/meshes-cube-25/main-*.vtu"
for file_name in sorted(glob(pattern)):
m = __read_vtu(file_name)
if m:
@@ -211,15 +246,17 @@ def main() -> int:
neighbors: Sequence[Sequence[int]] = build_neighborhood(meshes)
# For each rank, contains the graph built upon the vtk mesh.
- graphs = []
+ graphs: list[MeshGraph] = []
+ hollow_graphs: list[MeshGraph] = []
for m in meshes:
graphs.append(compute_graph(m))
+ hollow_graphs.append(compute_hollow_graph(m))
# Perform the core computation of the intersection.
# `intersections` will contain the intersection for each rank,
# while `offset_scans` will contain the offset for the global numbering,
# as it would be done in during the `MPI_scan`.
- intersections: Collection[Mapping[tuple[int, ...], frozenset[tuple[int, int]]]] = find_overlapping_edges(graphs, neighbors)
+ intersections: Collection[Mapping[tuple[int, ...], frozenset[tuple[int, int]]]] = find_overlapping_edges(graphs, hollow_graphs, neighbors)
offset_scans: Collection[Mapping[tuple[int, ...], int]] = mpi_scan(intersections)
# Finish by doing the global numbering for real.
From 1de9f067df685f59fd5d21b150fedad226d39dbe Mon Sep 17 00:00:00 2001
From: TotoGaz <49004943+TotoGaz@users.noreply.github.com>
Date: Fri, 12 Apr 2024 08:55:51 -0700
Subject: [PATCH 017/106] Start work for Faces
---
.../mesh/generators/NewGhosting.cpp | 90 ++++++++++++++-----
1 file changed, 69 insertions(+), 21 deletions(-)
diff --git a/src/coreComponents/mesh/generators/NewGhosting.cpp b/src/coreComponents/mesh/generators/NewGhosting.cpp
index a3107ed2402..f72da49a7a3 100644
--- a/src/coreComponents/mesh/generators/NewGhosting.cpp
+++ b/src/coreComponents/mesh/generators/NewGhosting.cpp
@@ -54,48 +54,84 @@ using MpiRank = fluent::NamedType< int, struct MpiRankTag, fluent::Comparable, f
//};
using Edge = std::pair< NodeGlbIdx, NodeGlbIdx >;
-using Face = std::vector< NodeGlbIdx >;
+using Face = std::set< NodeGlbIdx >;
struct Exchange
{
std::set< Edge > edges;
-// std::set< Face > faces;
+ std::set< Face > faces;
+// SortedArray< Edge > edges;
+// SortedArray< Face > faces;
};
+template< bool DO_PACKING >
+localIndex
+Pack( buffer_unit_type *& buffer,
+ Exchange const & exchange )
+{
+ localIndex sizeOfPackedChars = 0;
+ sizeOfPackedChars += Pack< DO_PACKING >( buffer, exchange.edges );
+ sizeOfPackedChars += Pack< DO_PACKING >( buffer, exchange.faces );
+ return sizeOfPackedChars;
+}
+
+
Exchange buildExchangeData( vtkSmartPointer< vtkDataSet > mesh )
{
vtkIdTypeArray const * globalPtIds = vtkIdTypeArray::FastDownCast( mesh->GetPointData()->GetGlobalIds() );
- std::vector< Edge > tmp;
+ std::vector< Edge > tmpEdges;
+ std::vector< Face > tmpFaces;
- // Pre-allocation of the temporary.
+ // Pre-allocation of the temporary vectors.
{
std::size_t numEdges = 0;
+ std::size_t numFaces = 0;
for( auto c = 0; c < mesh->GetNumberOfCells(); ++c )
{
vtkCell * cell = mesh->GetCell( c );
numEdges += cell->GetNumberOfEdges();
+ numFaces += cell->GetNumberOfFaces();
}
- tmp.reserve( numEdges );
+ tmpEdges.reserve( numEdges );
+ tmpFaces.reserve( numFaces );
}
// Filling the temporary.
for( auto c = 0; c < mesh->GetNumberOfCells(); ++c )
{
vtkCell * cell = mesh->GetCell( c );
+
for( auto e = 0; e < cell->GetNumberOfEdges(); ++e )
{
vtkCell * edge = cell->GetEdge( e );
- vtkIdType const ln0 = edge->GetPointId( 0 ), ln1 = edge->GetPointId( 1 );
- vtkIdType const gn0 = globalPtIds->GetValue( ln0 ), gn1 = globalPtIds->GetValue( ln1 );
- tmp.emplace_back( std::minmax( { gn0, gn1 } ) );
+ vtkIdType const ln0 = edge->GetPointId( 0 );
+ vtkIdType const ln1 = edge->GetPointId( 1 );
+ vtkIdType const gn0 = globalPtIds->GetValue( ln0 );
+ vtkIdType const gn1 = globalPtIds->GetValue( ln1 );
+ tmpEdges.emplace_back( std::minmax( { gn0, gn1 } ) );
+ }
+
+ for( auto f = 0; f < cell->GetNumberOfFaces(); ++f )
+ {
+ vtkCell * face = cell->GetFace( f );
+ vtkIdList * pids = face->GetPointIds();
+ Face ff;
+ for( auto i = 0; i < pids->GetNumberOfIds(); ++i )
+ {
+ vtkIdType const lni = face->GetPointId( i );
+ vtkIdType const gni = globalPtIds->GetValue( lni );
+ ff.insert( NodeGlbIdx{ gni } );
+ }
+ tmpFaces.emplace_back( ff );
}
}
// Removing the duplicates by copying into a `std::set`.
- std::set< Edge > const edges{ tmp.cbegin(), tmp.cend() };
+ std::set< Edge > edges{ tmpEdges.cbegin(), tmpEdges.cend() }; // SortedArray requires the input to be sorted already.
+ std::set< Face > faces{ tmpFaces.cbegin(), tmpFaces.cend() };
- return { edges };
+ return { std::move( edges ), std::move( faces ) };
}
array1d< globalIndex > convertExchange( Exchange const & exchange )
@@ -127,21 +163,33 @@ Exchange convertExchange( array1d< globalIndex > const & input )
/**
* @brief
* @param exchanged
- * @param neighborhood including current rank
+ * @param neighbors excluding current rank
*/
std::map< std::set< MpiRank >, std::set< Edge > > findOverlappingEdges( std::map< MpiRank, Exchange > const & exchanged,
MpiRank curRank,
- std::set< MpiRank > const & neighborhood )
+ std::set< MpiRank > const & neighbors )
{
GEOS_LOG_RANK( "Starting findOverlappingEdges" );
GEOS_LOG_RANK( "exchanged.size() = " << exchanged.size() );
std::map< Edge, std::set< MpiRank > > counts; // TODO Use better intersection algorithms?
- for( MpiRank const & rank: neighborhood )
+ // We "register" all the edges of the current rank: they are the only one we're interested in.
+ for( Edge const & edge: exchanged.at( curRank ).edges )
+ {
+ counts.emplace_hint( counts.end(), edge, std::set< MpiRank >{ curRank } );
+ }
+
+ // We now loop on the neighbor edges.
+ // If a neighbor has an edge in common with the current rank, they we store it.
+ for( MpiRank const & neighborRank: neighbors ) // This does not include the current rank.
{
- for( Edge const & edge: exchanged.at( rank ).edges )
+ for( Edge const & edge: exchanged.at( neighborRank ).edges )
{
- counts[edge].insert( rank );
+ auto it = counts.find( edge );
+ if( it != counts.cend() ) // TODO Extract `counts.cend()` out of the loop.
+ {
+ it->second.insert( neighborRank );
+ }
}
}
@@ -154,7 +202,7 @@ std::map< std::set< MpiRank >, std::set< Edge > > findOverlappingEdges( std::map
}
}
- // Checking if neighborhood is too wide... // TODO do we care?
+ // Checking if neighbors is too wide... // TODO do we care?
std::set< MpiRank > usefulNeighbors;
for( auto const & [ranks, edges]: ranksToIntersections )
{
@@ -164,7 +212,7 @@ std::map< std::set< MpiRank >, std::set< Edge > > findOverlappingEdges( std::map
}
}
std::vector< MpiRank > uselessNeighbors;
- std::set_difference( neighborhood.cbegin(), neighborhood.cend(), usefulNeighbors.cbegin(), usefulNeighbors.cend(), std::back_inserter( uselessNeighbors ) );
+ std::set_difference( neighbors.cbegin(), neighbors.cend(), usefulNeighbors.cbegin(), usefulNeighbors.cend(), std::back_inserter( uselessNeighbors ) );
// TODO... Remove the neighbors?
GEOS_LOG_RANK( "Ending findOverlappingEdges" );
@@ -218,6 +266,7 @@ std::map< MpiRank, Exchange > exchange( int commId,
return output;
}
+using ScannedOffsets = std::map< std::set< MpiRank >, integer >;
void doTheNewGhosting( vtkSmartPointer< vtkDataSet > mesh,
std::set< int > const & neighbors )
@@ -231,17 +280,16 @@ void doTheNewGhosting( vtkSmartPointer< vtkDataSet > mesh,
ncs.emplace_back( rank );
}
- std::set< MpiRank > neighborhood;
+ std::set< MpiRank > neighbors_;
for( int const & rank: neighbors )
{
- neighborhood.insert( MpiRank{ rank } );
+ neighbors_.insert( MpiRank{ rank } );
}
- neighborhood.insert( curRank );
CommID const commId = CommunicationTools::getInstance().getCommID();
std::map< MpiRank, Exchange > const exchanged = exchange( int( commId ), ncs, buildExchangeData( mesh ) );
- std::map< std::set< MpiRank >, std::set< Edge > > const overlappingEdges = findOverlappingEdges( exchanged, curRank, neighborhood );
+ std::map< std::set< MpiRank >, std::set< Edge > > const overlappingEdges = findOverlappingEdges( exchanged, curRank, neighbors_ );
}
} // end of namespace geos::ghosting
From 5b5d14074ae236c5dc99a8f488aa4a69e2fa9acb Mon Sep 17 00:00:00 2001
From: TotoGaz <49004943+TotoGaz@users.noreply.github.com>
Date: Fri, 12 Apr 2024 14:02:51 -0700
Subject: [PATCH 018/106] Exchange hollow information instead.
---
.../mesh/generators/NewGhosting.cpp | 80 +++++++++++++++----
1 file changed, 66 insertions(+), 14 deletions(-)
diff --git a/src/coreComponents/mesh/generators/NewGhosting.cpp b/src/coreComponents/mesh/generators/NewGhosting.cpp
index f72da49a7a3..d709dbd5260 100644
--- a/src/coreComponents/mesh/generators/NewGhosting.cpp
+++ b/src/coreComponents/mesh/generators/NewGhosting.cpp
@@ -23,7 +23,10 @@
#include
+#include
#include
+#include
+#include
#include
#include
@@ -76,7 +79,30 @@ Pack( buffer_unit_type *& buffer,
}
-Exchange buildExchangeData( vtkSmartPointer< vtkDataSet > mesh )
+std::set< vtkIdType > extractBoundaryCells( vtkSmartPointer< vtkDataSet > mesh )
+{
+ auto f = vtkDataSetSurfaceFilter::New();
+ f->PassThroughCellIdsOn();
+ f->PassThroughPointIdsOff();
+ f->FastModeOff();
+
+ string const originalCellsKey = "ORIGINAL_CELLS";
+ f->SetOriginalCellIdsName( originalCellsKey.c_str() );
+ auto boundaryMesh = vtkPolyData::New();
+ f->UnstructuredGridExecute( mesh, boundaryMesh );
+ vtkIdTypeArray const * originalCells = vtkIdTypeArray::FastDownCast( boundaryMesh->GetCellData()->GetArray( originalCellsKey.c_str() ) );
+
+ std::set< vtkIdType > boundaryCellIdxs;
+ for( auto i = 0; i < originalCells->GetNumberOfTuples(); ++i )
+ {
+ boundaryCellIdxs.insert( originalCells->GetValue( i ) );
+ }
+
+ return boundaryCellIdxs;
+}
+
+
+Exchange buildSpecificData( vtkSmartPointer< vtkDataSet > mesh, std::set< vtkIdType > const & cellIds )
{
vtkIdTypeArray const * globalPtIds = vtkIdTypeArray::FastDownCast( mesh->GetPointData()->GetGlobalIds() );
@@ -87,7 +113,7 @@ Exchange buildExchangeData( vtkSmartPointer< vtkDataSet > mesh )
{
std::size_t numEdges = 0;
std::size_t numFaces = 0;
- for( auto c = 0; c < mesh->GetNumberOfCells(); ++c )
+ for( vtkIdType const & c : cellIds )
{
vtkCell * cell = mesh->GetCell( c );
numEdges += cell->GetNumberOfEdges();
@@ -134,6 +160,7 @@ Exchange buildExchangeData( vtkSmartPointer< vtkDataSet > mesh )
return { std::move( edges ), std::move( faces ) };
}
+
array1d< globalIndex > convertExchange( Exchange const & exchange )
{
array1d< globalIndex > result;
@@ -147,6 +174,24 @@ array1d< globalIndex > convertExchange( Exchange const & exchange )
return result;
}
+
+Exchange buildFullData( vtkSmartPointer< vtkDataSet > mesh )
+{
+ std::set< vtkIdType > cellIds;
+ for( vtkIdType i = 0; i < mesh->GetNumberOfCells(); ++i )
+ {
+ cellIds.insert( cellIds.end(), i );
+ }
+
+ return buildSpecificData( mesh, cellIds );
+}
+
+
+Exchange buildExchangeData( vtkSmartPointer< vtkDataSet > mesh )
+{
+ return buildSpecificData( mesh, extractBoundaryCells( mesh ) );
+}
+
Exchange convertExchange( array1d< globalIndex > const & input )
{
Exchange exchange;
@@ -222,7 +267,7 @@ std::map< std::set< MpiRank >, std::set< Edge > > findOverlappingEdges( std::map
// TODO Duplicated
std::map< MpiRank, Exchange > exchange( int commId,
std::vector< NeighborCommunicator > & neighbors,
- Exchange && data )
+ Exchange const & data )
{
MPI_iCommData commData( commId );
integer const numNeighbors = LvArray::integerConversion< integer >( neighbors.size() );
@@ -243,13 +288,13 @@ std::map< MpiRank, Exchange > exchange( int commId,
MpiWrapper::waitAll( numNeighbors, commData.mpiSendBufferSizeRequest(), commData.mpiSendBufferSizeStatus() );
MpiWrapper::waitAll( numNeighbors, commData.mpiRecvBufferSizeRequest(), commData.mpiRecvBufferSizeStatus() );
- array1d< array1d< globalIndex > > tmpOutput( neighbors.size() );
+ array1d< array1d< globalIndex > > rawExchanged( neighbors.size() );
for( integer i = 0; i < numNeighbors; ++i )
{
neighbors[i].mpiISendReceiveData( cv,
commData.mpiSendBufferRequest( i ),
- tmpOutput[i],
+ rawExchanged[i],
commData.mpiRecvBufferRequest( i ),
commId,
MPI_COMM_GEOSX );
@@ -260,36 +305,43 @@ std::map< MpiRank, Exchange > exchange( int commId,
std::map< MpiRank, Exchange > output;
for( auto i = 0; i < numNeighbors; ++i )
{
- output[MpiRank{ neighbors[i].neighborRank() }] = convertExchange( tmpOutput[i] );
+ output[MpiRank{ neighbors[i].neighborRank() }] = convertExchange( rawExchanged[i] );
}
- output[MpiRank{ MpiWrapper::commRank() }] = std::move( data );
return output;
}
using ScannedOffsets = std::map< std::set< MpiRank >, integer >;
+
void doTheNewGhosting( vtkSmartPointer< vtkDataSet > mesh,
- std::set< int > const & neighbors )
+ std::set< MpiRank > const & neighbors )
{
// Now we exchange the data with our neighbors.
MpiRank const curRank{ MpiWrapper::commRank() };
std::vector< NeighborCommunicator > ncs;
- for( int const & rank: neighbors )
+ for( MpiRank const & rank: neighbors )
{
- ncs.emplace_back( rank );
+ ncs.emplace_back( rank.get() );
}
+ CommID const commId = CommunicationTools::getInstance().getCommID();
+ std::map< MpiRank, Exchange > exchanged = exchange( int( commId ), ncs, buildExchangeData( mesh ) );
+ exchanged[MpiRank{ MpiWrapper::commRank() }] = buildFullData( mesh );
+
+ std::map< std::set< MpiRank >, std::set< Edge > > const overlappingEdges = findOverlappingEdges( exchanged, curRank, neighbors );
+}
+
+void doTheNewGhosting( vtkSmartPointer< vtkDataSet > mesh,
+ std::set< int > const & neighbors )
+{
std::set< MpiRank > neighbors_;
for( int const & rank: neighbors )
{
neighbors_.insert( MpiRank{ rank } );
}
- CommID const commId = CommunicationTools::getInstance().getCommID();
- std::map< MpiRank, Exchange > const exchanged = exchange( int( commId ), ncs, buildExchangeData( mesh ) );
-
- std::map< std::set< MpiRank >, std::set< Edge > > const overlappingEdges = findOverlappingEdges( exchanged, curRank, neighbors_ );
+ return doTheNewGhosting(mesh, neighbors_);
}
} // end of namespace geos::ghosting
From aac9c2f70250ddf49d073214aa6eca9c7e72dbb8 Mon Sep 17 00:00:00 2001
From: TotoGaz <49004943+TotoGaz@users.noreply.github.com>
Date: Fri, 12 Apr 2024 17:27:35 -0700
Subject: [PATCH 019/106] Exchanging faces as well.
---
.../mesh/generators/NewGhosting.cpp | 110 +++++++++++++-----
1 file changed, 84 insertions(+), 26 deletions(-)
diff --git a/src/coreComponents/mesh/generators/NewGhosting.cpp b/src/coreComponents/mesh/generators/NewGhosting.cpp
index d709dbd5260..f376fbca27a 100644
--- a/src/coreComponents/mesh/generators/NewGhosting.cpp
+++ b/src/coreComponents/mesh/generators/NewGhosting.cpp
@@ -102,7 +102,8 @@ std::set< vtkIdType > extractBoundaryCells( vtkSmartPointer< vtkDataSet > mesh )
}
-Exchange buildSpecificData( vtkSmartPointer< vtkDataSet > mesh, std::set< vtkIdType > const & cellIds )
+Exchange buildSpecificData( vtkSmartPointer< vtkDataSet > mesh,
+ std::set< vtkIdType > const & cellIds )
{
vtkIdTypeArray const * globalPtIds = vtkIdTypeArray::FastDownCast( mesh->GetPointData()->GetGlobalIds() );
@@ -113,7 +114,7 @@ Exchange buildSpecificData( vtkSmartPointer< vtkDataSet > mesh, std::set< vtkIdT
{
std::size_t numEdges = 0;
std::size_t numFaces = 0;
- for( vtkIdType const & c : cellIds )
+ for( vtkIdType const & c: cellIds )
{
vtkCell * cell = mesh->GetCell( c );
numEdges += cell->GetNumberOfEdges();
@@ -163,18 +164,67 @@ Exchange buildSpecificData( vtkSmartPointer< vtkDataSet > mesh, std::set< vtkIdT
array1d< globalIndex > convertExchange( Exchange const & exchange )
{
+ std::size_t const edgeSize = 1 + 2 * std::size( exchange.edges );
+ std::size_t faceSize = 1;
+ for( Face const & face: exchange.faces )
+ {
+ faceSize += 1 + std::size( face ); // `+1` because we need to store the size so we know where to stop.
+ }
+
array1d< globalIndex > result;
- result.reserve( 2 * exchange.edges.size() );
+ result.reserve( edgeSize + faceSize );
+
+ result.emplace_back( std::size( exchange.edges ) );
for( Edge const & edge: exchange.edges )
{
result.emplace_back( edge.first.get() );
result.emplace_back( edge.second.get() );
}
+ result.emplace_back( std::size( exchange.faces ) );
+ for( Face const & face: exchange.faces )
+ {
+ result.emplace_back( std::size( face ) );
+ for( NodeGlbIdx const & n: face )
+ {
+ result.emplace_back( n.get() );
+ }
+ }
return result;
}
+Exchange convertExchange( array1d< globalIndex > const & input )
+{
+ Exchange exchange;
+
+ globalIndex const numEdges = input[0];
+ int i;
+ for( i = 1; i < 2 * numEdges + 1; i += 2 )
+ {
+ NodeGlbIdx gn0{ input[i] }, gn1{ input[i + 1] };
+ exchange.edges.insert( std::minmax( gn0, gn1 ) );
+ }
+ GEOS_ASSERT_EQ( std::size_t(numEdges), exchange.edges.size() );
+
+ globalIndex const numFaces = input[i];
+ for( ++i; i < input.size(); )
+ {
+ auto const s = input[i++];
+ std::set< NodeGlbIdx > face;
+ for( int j = 0; j < s; ++j, ++i )
+ {
+ face.insert( NodeGlbIdx{ input[i] } );
+ }
+ exchange.faces.insert( face );
+ }
+
+ GEOS_ASSERT_EQ( std::size_t(numFaces), exchange.faces.size() );
+
+ return exchange;
+}
+
+
Exchange buildFullData( vtkSmartPointer< vtkDataSet > mesh )
{
std::set< vtkIdType > cellIds;
@@ -192,31 +242,22 @@ Exchange buildExchangeData( vtkSmartPointer< vtkDataSet > mesh )
return buildSpecificData( mesh, extractBoundaryCells( mesh ) );
}
-Exchange convertExchange( array1d< globalIndex > const & input )
+struct Buckets
{
- Exchange exchange;
+ std::map< std::set< MpiRank >, std::set< Edge > > edges;
+ std::map< std::set< MpiRank >, std::set< Face > > faces;
+};
- for( auto i = 0; i < input.size(); ++ ++i )
- {
- NodeGlbIdx gn0{ input[i] }, gn1{ input[i + 1] };
- exchange.edges.insert( std::minmax( gn0, gn1 ) );
- }
-
- return exchange;
-}
/**
* @brief
* @param exchanged
* @param neighbors excluding current rank
*/
-std::map< std::set< MpiRank >, std::set< Edge > > findOverlappingEdges( std::map< MpiRank, Exchange > const & exchanged,
- MpiRank curRank,
- std::set< MpiRank > const & neighbors )
+Buckets buildIntersectionBuckets( std::map< MpiRank, Exchange > const & exchanged,
+ MpiRank curRank,
+ std::set< MpiRank > const & neighbors )
{
- GEOS_LOG_RANK( "Starting findOverlappingEdges" );
- GEOS_LOG_RANK( "exchanged.size() = " << exchanged.size() );
-
std::map< Edge, std::set< MpiRank > > counts; // TODO Use better intersection algorithms?
// We "register" all the edges of the current rank: they are the only one we're interested in.
for( Edge const & edge: exchanged.at( curRank ).edges )
@@ -238,18 +279,34 @@ std::map< std::set< MpiRank >, std::set< Edge > > findOverlappingEdges( std::map
}
}
- std::map< std::set< MpiRank >, std::set< Edge > > ranksToIntersections;
+ std::map< std::set< MpiRank >, std::set< Edge > > edgeBuckets;
for( auto const & [edge, ranks]: counts )
{
if( ranks.find( curRank ) != ranks.cend() )
{
- ranksToIntersections[ranks].insert( edge );
+ edgeBuckets[ranks].insert( edge );
}
}
+ std::map< std::set< MpiRank >, std::set< Face > > faceBuckets;
+ std::set< Face > curFaces = exchanged.at( curRank ).faces;
+ for( MpiRank const & neighborRank: neighbors ) // This does not include the current rank.
+ {
+ for( Face const & face: exchanged.at( neighborRank ).faces )
+ {
+ auto it = curFaces.find( face );
+ if( it != curFaces.cend() )
+ {
+ faceBuckets[{ curRank, neighborRank }].insert( *it );
+ curFaces.erase( it );
+ }
+ }
+ }
+ faceBuckets[{ curRank }] = curFaces;
+
// Checking if neighbors is too wide... // TODO do we care?
std::set< MpiRank > usefulNeighbors;
- for( auto const & [ranks, edges]: ranksToIntersections )
+ for( auto const & [ranks, edges]: edgeBuckets )
{
if( not edges.empty() )
{
@@ -259,11 +316,11 @@ std::map< std::set< MpiRank >, std::set< Edge > > findOverlappingEdges( std::map
std::vector< MpiRank > uselessNeighbors;
std::set_difference( neighbors.cbegin(), neighbors.cend(), usefulNeighbors.cbegin(), usefulNeighbors.cend(), std::back_inserter( uselessNeighbors ) );
// TODO... Remove the neighbors?
- GEOS_LOG_RANK( "Ending findOverlappingEdges" );
- return ranksToIntersections;
+ return { edgeBuckets, faceBuckets };
}
+
// TODO Duplicated
std::map< MpiRank, Exchange > exchange( int commId,
std::vector< NeighborCommunicator > & neighbors,
@@ -320,6 +377,7 @@ void doTheNewGhosting( vtkSmartPointer< vtkDataSet > mesh,
MpiRank const curRank{ MpiWrapper::commRank() };
std::vector< NeighborCommunicator > ncs;
+ ncs.reserve( neighbors.size() );
for( MpiRank const & rank: neighbors )
{
ncs.emplace_back( rank.get() );
@@ -329,7 +387,7 @@ void doTheNewGhosting( vtkSmartPointer< vtkDataSet > mesh,
std::map< MpiRank, Exchange > exchanged = exchange( int( commId ), ncs, buildExchangeData( mesh ) );
exchanged[MpiRank{ MpiWrapper::commRank() }] = buildFullData( mesh );
- std::map< std::set< MpiRank >, std::set< Edge > > const overlappingEdges = findOverlappingEdges( exchanged, curRank, neighbors );
+ Buckets const buckets = buildIntersectionBuckets( exchanged, curRank, neighbors );
}
void doTheNewGhosting( vtkSmartPointer< vtkDataSet > mesh,
@@ -341,7 +399,7 @@ void doTheNewGhosting( vtkSmartPointer< vtkDataSet > mesh,
neighbors_.insert( MpiRank{ rank } );
}
- return doTheNewGhosting(mesh, neighbors_);
+ return doTheNewGhosting( mesh, neighbors_ );
}
} // end of namespace geos::ghosting
From 299325ab4b1bce6bf0180df40aeef5ceb02b7bc7 Mon Sep 17 00:00:00 2001
From: TotoGaz <49004943+TotoGaz@users.noreply.github.com>
Date: Fri, 12 Apr 2024 17:44:45 -0700
Subject: [PATCH 020/106] Estimate the max buffer size using an MPI::sum
---
.../mesh/generators/NewGhosting.cpp | 25 +++++++++++++++++++
1 file changed, 25 insertions(+)
diff --git a/src/coreComponents/mesh/generators/NewGhosting.cpp b/src/coreComponents/mesh/generators/NewGhosting.cpp
index f376fbca27a..fe481c097c7 100644
--- a/src/coreComponents/mesh/generators/NewGhosting.cpp
+++ b/src/coreComponents/mesh/generators/NewGhosting.cpp
@@ -370,6 +370,29 @@ std::map< MpiRank, Exchange > exchange( int commId,
using ScannedOffsets = std::map< std::set< MpiRank >, integer >;
+std::size_t buildMaxBufferSize( Buckets const & buckets )
+{
+ std::size_t edgeSize = std::size( buckets.edges );
+ for( auto const & [ranks, edges]: buckets.edges )
+ {
+ edgeSize += std::size( ranks ) + 1;
+ edgeSize += 2 * std::size( edges ) + 1;
+ }
+
+ std::size_t faceSize = std::size( buckets.faces );
+ for( auto const & [ranks, faces]: buckets.faces )
+ {
+ faceSize += std::size( ranks ) + 1;
+ for( Face const & face: faces )
+ {
+ faceSize = std::size( face ) + 1;
+ }
+ }
+
+ std::size_t const total = edgeSize + faceSize;
+ return MpiWrapper::sum( total );
+}
+
void doTheNewGhosting( vtkSmartPointer< vtkDataSet > mesh,
std::set< MpiRank > const & neighbors )
{
@@ -388,6 +411,8 @@ void doTheNewGhosting( vtkSmartPointer< vtkDataSet > mesh,
exchanged[MpiRank{ MpiWrapper::commRank() }] = buildFullData( mesh );
Buckets const buckets = buildIntersectionBuckets( exchanged, curRank, neighbors );
+
+ std::size_t const maxBufferSize = buildMaxBufferSize( buckets );
}
void doTheNewGhosting( vtkSmartPointer< vtkDataSet > mesh,
From b26854db9148fa732d572e94103a3247c6e55ede Mon Sep 17 00:00:00 2001
From: TotoGaz <49004943+TotoGaz@users.noreply.github.com>
Date: Fri, 12 Apr 2024 17:56:59 -0700
Subject: [PATCH 021/106] Wrong impl + first struct to hold the offsets.
---
.../mesh/generators/NewGhosting.cpp | 31 +++++++++----------
1 file changed, 15 insertions(+), 16 deletions(-)
diff --git a/src/coreComponents/mesh/generators/NewGhosting.cpp b/src/coreComponents/mesh/generators/NewGhosting.cpp
index fe481c097c7..71210cea9a4 100644
--- a/src/coreComponents/mesh/generators/NewGhosting.cpp
+++ b/src/coreComponents/mesh/generators/NewGhosting.cpp
@@ -367,30 +367,29 @@ std::map< MpiRank, Exchange > exchange( int commId,
return output;
}
-using ScannedOffsets = std::map< std::set< MpiRank >, integer >;
+
+struct ScannedOffsets
+{
+ std::map< std::set< MpiRank >, EdgeGlbIdx > edgeOffsets;
+ std::map< std::set< MpiRank >, FaceGlbIdx > faceOffsets;
+ EdgeGlbIdx edgeRestart;
+ FaceGlbIdx faceRestart;
+};
std::size_t buildMaxBufferSize( Buckets const & buckets )
{
- std::size_t edgeSize = std::size( buckets.edges );
- for( auto const & [ranks, edges]: buckets.edges )
+ auto const f = []( auto const & bucket ) -> std::size_t
{
- edgeSize += std::size( ranks ) + 1;
- edgeSize += 2 * std::size( edges ) + 1;
- }
-
- std::size_t faceSize = std::size( buckets.faces );
- for( auto const & [ranks, faces]: buckets.faces )
- {
- faceSize += std::size( ranks ) + 1;
- for( Face const & face: faces )
+ std::size_t size = std::size( bucket );
+ for( auto const & [ranks, _]: bucket )
{
- faceSize = std::size( face ) + 1;
+ size += std::size( ranks ) + 1 + 1; // One `+1` for the size of the ranks set, the other one for the offset
}
- }
+ return size;
+ };
- std::size_t const total = edgeSize + faceSize;
- return MpiWrapper::sum( total );
+ return MpiWrapper::sum( f( buckets.edges ) + f( buckets.faces ) );
}
void doTheNewGhosting( vtkSmartPointer< vtkDataSet > mesh,
From ca65b2dc68dcf0e8c66a057afcd8382b7213f1eb Mon Sep 17 00:00:00 2001
From: TotoGaz <49004943+TotoGaz@users.noreply.github.com>
Date: Fri, 12 Apr 2024 19:13:04 -0700
Subject: [PATCH 022/106] Comment
---
src/coreComponents/mesh/generators/NewGhosting.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/coreComponents/mesh/generators/NewGhosting.cpp b/src/coreComponents/mesh/generators/NewGhosting.cpp
index 71210cea9a4..f56c82baccd 100644
--- a/src/coreComponents/mesh/generators/NewGhosting.cpp
+++ b/src/coreComponents/mesh/generators/NewGhosting.cpp
@@ -389,7 +389,7 @@ std::size_t buildMaxBufferSize( Buckets const & buckets )
return size;
};
- return MpiWrapper::sum( f( buckets.edges ) + f( buckets.faces ) );
+ return MpiWrapper::sum( f( buckets.edges ) + f( buckets.faces ) ); // Add the ScannedOffsets::{edge, face}Restart
}
void doTheNewGhosting( vtkSmartPointer< vtkDataSet > mesh,
From da4103a298285412e5b0b3d5d1b7211a4e010f09 Mon Sep 17 00:00:00 2001
From: TotoGaz <49004943+TotoGaz@users.noreply.github.com>
Date: Wed, 24 Apr 2024 16:57:19 -0700
Subject: [PATCH 023/106] add json lib for faster dev
---
src/coreComponents/mesh/CMakeLists.txt | 9 ++++++++-
src/coreComponents/mesh/generators/NewGhosting.cpp | 3 +++
2 files changed, 11 insertions(+), 1 deletion(-)
diff --git a/src/coreComponents/mesh/CMakeLists.txt b/src/coreComponents/mesh/CMakeLists.txt
index 1ad47f2e12f..d0a1fd717ad 100644
--- a/src/coreComponents/mesh/CMakeLists.txt
+++ b/src/coreComponents/mesh/CMakeLists.txt
@@ -168,7 +168,14 @@ if( NOT namedtype_POPULATED )
add_subdirectory( ${namedtype_SOURCE_DIR} ${namedtype_BINARY_DIR} )
endif()
-list( APPEND dependencyList NamedType )
+include(FetchContent)
+
+FetchContent_Declare(json URL https://github.com/nlohmann/json/releases/download/v3.11.3/json.tar.xz)
+FetchContent_MakeAvailable(json)
+
+#target_link_libraries(foo PRIVATE nlohmann_json::nlohmann_json)
+
+list( APPEND dependencyList NamedType nlohmann_json::nlohmann_json)
if( ENABLE_VTK )
diff --git a/src/coreComponents/mesh/generators/NewGhosting.cpp b/src/coreComponents/mesh/generators/NewGhosting.cpp
index f56c82baccd..070c025bfd1 100644
--- a/src/coreComponents/mesh/generators/NewGhosting.cpp
+++ b/src/coreComponents/mesh/generators/NewGhosting.cpp
@@ -28,6 +28,9 @@
#include
#include
+#include
+using json = nlohmann::json;
+
#include
#include
From c129c9cf7485f92dbac5232a4fedaa77468aa1a7 Mon Sep 17 00:00:00 2001
From: TotoGaz <49004943+TotoGaz@users.noreply.github.com>
Date: Wed, 24 Apr 2024 16:59:56 -0700
Subject: [PATCH 024/106] use tuple instead of pair for edges
---
src/coreComponents/mesh/generators/NewGhosting.cpp | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/coreComponents/mesh/generators/NewGhosting.cpp b/src/coreComponents/mesh/generators/NewGhosting.cpp
index 070c025bfd1..79e290b06c5 100644
--- a/src/coreComponents/mesh/generators/NewGhosting.cpp
+++ b/src/coreComponents/mesh/generators/NewGhosting.cpp
@@ -59,7 +59,7 @@ using MpiRank = fluent::NamedType< int, struct MpiRankTag, fluent::Comparable, f
// std::vector< NodeGlbIdx > nodes;
//};
-using Edge = std::pair< NodeGlbIdx, NodeGlbIdx >;
+using Edge = std::tuple< NodeGlbIdx, NodeGlbIdx >;
using Face = std::set< NodeGlbIdx >;
struct Exchange
@@ -180,8 +180,8 @@ array1d< globalIndex > convertExchange( Exchange const & exchange )
result.emplace_back( std::size( exchange.edges ) );
for( Edge const & edge: exchange.edges )
{
- result.emplace_back( edge.first.get() );
- result.emplace_back( edge.second.get() );
+ result.emplace_back( std::get< 0 >( edge ).get() );
+ result.emplace_back( std::get< 1 >( edge ).get() );
}
result.emplace_back( std::size( exchange.faces ) );
for( Face const & face: exchange.faces )
From 38978557ce2f443f9ff5e8f7d214a3f3aabc6a91 Mon Sep 17 00:00:00 2001
From: TotoGaz <49004943+TotoGaz@users.noreply.github.com>
Date: Wed, 24 Apr 2024 17:05:28 -0700
Subject: [PATCH 025/106] save poc
---
scripts/poc.cpp | 203 ++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 203 insertions(+)
create mode 100644 scripts/poc.cpp
diff --git a/scripts/poc.cpp b/scripts/poc.cpp
new file mode 100644
index 00000000000..9a725635b76
--- /dev/null
+++ b/scripts/poc.cpp
@@ -0,0 +1,203 @@
+/*
+ * Compile: mpicxx -std=c++20 -I /tmp/json/include scan.cpp -o scan
+ * Launch: mpirun -n 5 scan
+ */
+
+#include
+
+using json = nlohmann::json;
+
+#include
+
+#include
+#include
+
+#include
+#include
+#include