Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactoring of the ghosting setup #3063

Draft
wants to merge 120 commits into
base: develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
120 commits
Select commit Hold shift + click to select a range
8972936
First dummy version that compiles.
TotoGaz Mar 22, 2024
f0293b8
Merge branch 'develop' into feature/TotoGaz/newGhosting
TotoGaz Apr 2, 2024
095b262
v0 of the doc
TotoGaz Apr 2, 2024
8218426
Forgot toc...
TotoGaz Apr 2, 2024
fc3154f
moved doc!
TotoGaz Apr 3, 2024
44365e5
small plantuml test
TotoGaz Apr 3, 2024
15b5cb3
update rtd machine
TotoGaz Apr 3, 2024
2f5c2f6
update plantuml
TotoGaz Apr 3, 2024
177397a
fix diagrams + remove tests
TotoGaz Apr 3, 2024
1f3c112
add missing package
TotoGaz Apr 3, 2024
7d25eef
First version of the poc in python
TotoGaz Apr 4, 2024
11f6331
A little cleaning before sharing.
TotoGaz Apr 4, 2024
a83b0e9
Merge branch 'develop' into feature/TotoGaz/newGhosting
TotoGaz Apr 4, 2024
087897e
Little type hints improvements.
TotoGaz Apr 5, 2024
ae9a456
Small optimization
TotoGaz Apr 6, 2024
778cd82
Revert "Small optimization"
TotoGaz Apr 6, 2024
5d2bf53
First version that's exchanging edges properly.
TotoGaz Apr 10, 2024
bcd7fba
Use hollow meshes for neighboring ranks (optimization)
TotoGaz Apr 12, 2024
1de9f06
Start work for Faces
TotoGaz Apr 12, 2024
5b5d140
Exchange hollow information instead.
TotoGaz Apr 12, 2024
aac9c2f
Exchanging faces as well.
TotoGaz Apr 13, 2024
299325a
Estimate the max buffer size using an MPI::sum
TotoGaz Apr 13, 2024
b26854d
Wrong impl + first struct to hold the offsets.
TotoGaz Apr 13, 2024
ca65b2d
Comment
TotoGaz Apr 13, 2024
5e28c1b
Merge branch 'develop' into feature/TotoGaz/newGhosting
TotoGaz Apr 22, 2024
da4103a
add json lib for faster dev
TotoGaz Apr 24, 2024
c129c9c
use tuple instead of pair for edges
TotoGaz Apr 24, 2024
3897855
save poc
TotoGaz Apr 25, 2024
4ba3a64
use pointer to instance for local information.
TotoGaz Apr 25, 2024
321672b
change names of buffers
TotoGaz Apr 25, 2024
650aa23
First OK exchange of the edges offsets
TotoGaz Apr 26, 2024
74e05cc
Reorder the nodes of the face and comments.
TotoGaz Apr 26, 2024
d963be5
Merge branch 'develop' into feature/TotoGaz/newGhosting
TotoGaz Apr 26, 2024
d90608c
Reorder the nodes of the face and comments.
TotoGaz Apr 27, 2024
a9b227d
Some doc
TotoGaz Apr 27, 2024
a7f4279
Gather/reduce the max nodes, edges, faces, cells from all the ranks.
TotoGaz Apr 29, 2024
f0e6d87
Change template type name.
TotoGaz Apr 30, 2024
3e75ddd
Build graph connection as a structure
TotoGaz Apr 30, 2024
881f393
Merge branch 'develop' into feature/TotoGaz/newGhosting
TotoGaz Apr 30, 2024
2cfef8d
Merge branch 'develop' into feature/TotoGaz/newGhosting
TotoGaz May 3, 2024
cb77e63
Change the serialization of Exchange (use json)
TotoGaz May 3, 2024
6b1eda9
Add nodes to the Exchange
TotoGaz May 3, 2024
53497d5
Compute the rank intersection for the nodes as well.
TotoGaz May 3, 2024
1c28df0
Refactor duplicated code
TotoGaz May 3, 2024
406d0b3
Build the mesh graph for owned entities.
TotoGaz May 3, 2024
635be4b
Small code simplifications.
TotoGaz May 4, 2024
5b82526
First (a priori) valid assembly of the adjacency graph matrix.
TotoGaz May 9, 2024
1131f58
Merge branch 'develop' into feature/TotoGaz/newGhosting
TotoGaz May 9, 2024
4c214a2
Handle rectanguler trilinos matrix using domain and range maps.
TotoGaz May 9, 2024
401c5bc
First adjacency matrix multiplications that go through.
TotoGaz May 10, 2024
0ab79a1
Little renamings for the domain/range maps
TotoGaz May 10, 2024
638a659
Handling the transposition of the ghosting matrix + extracting the row.
TotoGaz May 10, 2024
5058c29
This version managegs appropriately the quantities that are owned and…
TotoGaz May 10, 2024
43adb71
Removing one step in the adjacency multiplication process.
TotoGaz May 10, 2024
f88b927
Print cells instead.
TotoGaz May 14, 2024
96b2eb2
Create an include folder for the public interface
TotoGaz May 14, 2024
b6f30c9
Move CellBlockABC and FaceBlockABC to the include folder.
TotoGaz May 15, 2024
4bacf19
Have doTheNewGhosting return a pointer to the mesh data.
TotoGaz May 15, 2024
d722a88
Move indices to their own file
TotoGaz May 15, 2024
7cf2c53
Fist incomplete impl of the new public interface of the module.
TotoGaz May 15, 2024
c5ccbf6
Add nodiscard and ghost rank for the EdgeMgr.
TotoGaz May 15, 2024
04e23ff
Save commit before removing lots of dead code.
TotoGaz May 16, 2024
ec25942
remove dead code
TotoGaz May 16, 2024
08cf210
Changed rowMap into ownedMap
TotoGaz May 16, 2024
857db9f
Add [[nodiscard]]s
TotoGaz May 16, 2024
8885ae0
Merge branch 'develop' into feature/TotoGaz/newGhosting
TotoGaz May 16, 2024
4113721
Remove graphNodeMap and compute the transposed matrix once for all.
TotoGaz May 16, 2024
8273d6d
Extract neighbor data for all the geometrical quantities.
TotoGaz May 16, 2024
c6528ad
Use a compound struct.
TotoGaz May 16, 2024
ec7ea67
Create ghostRank and l2g for EdgeMgr.
TotoGaz May 16, 2024
e10d796
Gathering the information for missing quantities.
TotoGaz May 20, 2024
3a99461
Fix naming conventions.
TotoGaz May 20, 2024
3217ee2
Comments
TotoGaz May 20, 2024
1dcba3d
Split the MeshGraph in 2 instances dedicated to owned and present geo…
TotoGaz May 20, 2024
b040012
Create and return a Ghost graph + rename `Ghost` struct to `Ownerships`
TotoGaz May 20, 2024
d6dc0f4
Merge branch 'develop' into feature/TotoGaz/newGhosting
TotoGaz May 20, 2024
385986c
remove wrong doxygen
TotoGaz May 20, 2024
4b2e61c
Added a dedicated file for the global numbering.
TotoGaz May 20, 2024
ff8e765
Split global numbering and ghosting
TotoGaz May 21, 2024
0d91fae
Remove useless identity matrix
TotoGaz May 21, 2024
b3d911c
Finish the class that manages the matrix index <-> geometry index con…
TotoGaz May 21, 2024
ec7f990
Mainly comments
TotoGaz May 22, 2024
dadc03b
Send and receive ghost should be OK.
TotoGaz May 23, 2024
2736da6
Use the exact size during the extraction + manage the node case for d…
TotoGaz May 23, 2024
3014912
Conveys all the ordering, flip, shift information through the adjacen…
TotoGaz May 25, 2024
ab38a00
Remove unused variable
TotoGaz May 25, 2024
25989c2
Small code refactoring
TotoGaz May 30, 2024
68cd212
Move buidPods to its own file + some structure in headers for definit…
TotoGaz May 30, 2024
d62326f
Building the EdgeMgrImpl
TotoGaz May 31, 2024
cd30c9c
Merge mesh graphs into a big one.
TotoGaz Jun 3, 2024
5c1e718
Change the `start` of the EdgeInfo.
TotoGaz Jun 3, 2024
31367df
Start the work for Cell mappings.
TotoGaz Jun 3, 2024
6ab3165
Add a CellBlk, unit test the face reordering, continue filling the im…
TotoGaz Jun 4, 2024
0ed550f
Separating g2l and l2g.
TotoGaz Jun 4, 2024
93f5169
Split the construction of the upward matrix information from the ghos…
TotoGaz Jun 4, 2024
b3b1b5f
Use one single pair of vectors when copying the rows.
TotoGaz Jun 5, 2024
29aaf4e
Node positions are now exchanged.
TotoGaz Jun 6, 2024
02e636a
Merge branch 'develop' into feature/TotoGaz/newGhosting
TotoGaz Jun 6, 2024
a799687
Give the node positions to the NodeMgr.
TotoGaz Jun 6, 2024
3ccdb41
Start bringing the new mappings to the core of geos.
TotoGaz Jun 6, 2024
2382685
First end-to-end version that runs Laplace in parallel.
TotoGaz Jun 14, 2024
8705452
remove elemRegionManager from setGeometricalRelations and use the cel…
TotoGaz Jun 14, 2024
11f191f
Merge branch 'develop' into feature/TotoGaz/newGhosting
TotoGaz Jun 14, 2024
fbe4bb3
Extract the ghostRank from the send/recv instead of duplicating it.
TotoGaz Jun 14, 2024
2a97f46
Compute the neighbors from the send/recv information.
TotoGaz Jun 14, 2024
87df323
Do not provide the l2g map anymore and let the client compute it from…
TotoGaz Jun 15, 2024
c3fc603
Merge branch 'develop' into feature/TotoGaz/newGhosting
TotoGaz Jun 15, 2024
4b10843
Making it work with tpetra and integer matrices.
TotoGaz Jun 22, 2024
77eef65
extractedValues is now a collection of integers, no more float
TotoGaz Jun 22, 2024
bf89fce
Fix sorting inconsistency
TotoGaz Jun 25, 2024
d5440b9
forgot a `const`
TotoGaz Jun 26, 2024
025a132
Micro c++ improvements and renamings.
TotoGaz Jul 1, 2024
f1cb41d
Merge branch 'develop' into feature/TotoGaz/newGhosting
TotoGaz Jul 1, 2024
cb01dc9
Merge branch 'develop' into feature/TotoGaz/newGhosting
TotoGaz Jul 2, 2024
7058cb3
Comments/Documentation for New Ghosting Architecture (#3189)
ryar9534 Jul 3, 2024
d9d06d2
initial attempt at adding cell type
ryar9534 Jul 8, 2024
020955f
fixed bug for hex meshes with elem type
ryar9534 Jul 8, 2024
a62ce3a
attempt at mutliple cell types, need to debug
ryar9534 Jul 11, 2024
ba0f889
Revert "attempt at mutliple cell types, need to debug"
ryar9534 Jul 11, 2024
1be9277
Re-added impl of multi types which works for hex mesh, need to debug …
ryar9534 Jul 15, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 13 additions & 11 deletions host-configs/environment.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -28,17 +28,19 @@ endif()
if(NOT DEFINED ENABLE_TRILINOS)
set(ENABLE_TRILINOS "$ENV{ENABLE_TRILINOS}" CACHE BOOL "" FORCE)
endif()
if(ENABLE_TRILINOS)
set(GEOSX_LA_INTERFACE "Trilinos" CACHE STRING "" FORCE)
else()
set(ENABLE_TRILINOS FALSE CACHE BOOL "" FORCE)
endif()

if( (ENABLE_HYPRE AND ENABLE_TRILINOS) OR (NOT ENABLE_TRILINOS AND NOT ENABLE_HYPRE))
MESSAGE(SEND_ERROR "Exactly one of ENABLE_HYPRE and ENABLE_TRILINOS must be defined.")
MESSAGE(SEND_ERROR "ENABLE_HYPRE = ${ENABLE_HYPRE}.")
MESSAGE(SEND_ERROR "ENABLE_TRILINOS = ${ENABLE_TRILINOS}.")
endif()
#if(ENABLE_TRILINOS)
# set(GEOSX_LA_INTERFACE "Trilinos" CACHE STRING "" FORCE)
#else()
# set(ENABLE_TRILINOS FALSE CACHE BOOL "" FORCE)
#endif()

set(ENABLE_TRILINOS TRUE CACHE BOOL "" FORCE)

#if( (ENABLE_HYPRE AND ENABLE_TRILINOS) OR (NOT ENABLE_TRILINOS AND NOT ENABLE_HYPRE))
# MESSAGE(SEND_ERROR "Exactly one of ENABLE_HYPRE and ENABLE_TRILINOS must be defined.")
# MESSAGE(SEND_ERROR "ENABLE_HYPRE = ${ENABLE_HYPRE}.")
# MESSAGE(SEND_ERROR "ENABLE_TRILINOS = ${ENABLE_TRILINOS}.")
#endif()

MESSAGE(STATUS "GEOSX_LA_INTERFACE = ${GEOSX_LA_INTERFACE}")

Expand Down
31 changes: 31 additions & 0 deletions scripts/NamedType.py
Original file line number Diff line number Diff line change
@@ -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()
272 changes: 272 additions & 0 deletions scripts/ghosting.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,272 @@
from collections import defaultdict
from dataclasses import dataclass
from glob import glob
from itertools import chain
import logging
import sys
from typing import (
Collection,
Generator,
Iterable,
Mapping,
Optional,
Sequence,
)
from copy import deepcopy

from vtkmodules.vtkCommonDataModel import (
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)

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, cells: Generator[int, None, None] | None) -> Collection[Edge]:
if cells is None:
cells = range(mesh.GetNumberOfCells())
tmp: set[Edge] = set()
for c in cells:
cell: vtkCell = mesh.GetCell(c)
for e in range(cell.GetNumberOfEdges()):
edge: vtkCell = cell.GetEdge(e)
ls = edge.GetPointId(0), edge.GetPointId(1)
nodes: tuple[int, int] = tuple(sorted(ls))
tmp.add(Edge(nodes))
return tuple(tmp)


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, 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):
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 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] = {}
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.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)

# "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.
for current_rank, intersection in enumerate(rank_to_intersections):
count: dict[tuple[int, int], set[int]] = defaultdict(set)
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 current_rank in ranks:
intersection[tuple(sorted(ranks))].add(edge)

# For information, check if neighborhood is too wide...
for current_rank, other_ranks in enumerate(neighbors):
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 by rank {current_rank}.")

return rank_to_intersections


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: Iterable[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]) -> Sequence[Sequence[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 sorted(glob(pattern)):
m = __read_vtu(file_name)
if m:
meshes.append(m)

# For each rank, contains the neighbor rank (candidates).
neighbors: Sequence[Sequence[int]] = build_neighborhood(meshes)

# For each rank, contains the graph built upon the vtk mesh.
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, hollow_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]] = []
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())
Loading
Loading