Grid partitioning
All grids created from ExtendableGrids can be considered to be partitioned such that the neighborhood graph of the partitions is colored so that operations (FEM/FVM assembly, sparse matrix-vector multiplication with SparseMatrixCSC, ILU preconditioners) on different partitions of the same color can be performed in parallel without write conflicts in a multithreading environment.
The default partitioning is trivial: all cells and nodes belong to one partition, and the resulting trivial neighborhood graph is colored with one color.
API calls
ExtendableGrids.partition
— Function partition(grid::ExtendableGrid,
alg::AbstractPartitioningAlgorithm;
nodes = false,
keep_nodepermutation = false,
edges = false )
Partition cells of grid
according to alg
, such that the neigborhood graph of partitions is colored in such a way, that all partitions with a given color can be worked on in parallel. Cells are renumbered such that cell numbers for a given partition are numbered contiguously.
Return the resulting grid.
Useful for parallel FEM assembly and cellwise FVM assembly.
Keyword arguments:
nodes
: if true, induce node partitioning from cell partitioning. Used for node/edgewise FVM assembly. In addition the resulting partitioning supports parallel matrix-vector products withSparseMatrixCSC
. Nodes are renumbered compared to the original grid. Iffalse
(default), a trivial partitioning of the nodes is created such that all nodes belong to partition 1 and all others are empty.keep_nodepermutation
: if true, keep the node permutation with respect to the original grid ingrid[
NodePermutation
]
.edges
: if true, induce partitioning of edges from cell partitioning. Used for node/edgewise FVM assembly. This step creates a number of relatively expensive additional adjacencies. Iffalse
(default), a trivial partitioning of the edges is created such that all edges belong to partition 1 and all others are empty.
Access:
pcolors
returns the range of partition colorspcolor_partitions
returns the range of partition numbers for a given colorpartition_cells
provides the range of cell numbers of a given partitionpartition_nodes
provides the range of node numbers of a given partitionpartition_edges
provides the range of edge numbers of a given partition
A parallel loop over grid cells thus looks like
for color in pcolors(grid)
@threads for part in pcolor_partitions(grid, color)
for cell in partition_cells(grid, part)
...
end
end
end
Without a call to partition
, all these functions return trivial data such that the above sample code stays valid.
partition
must be called before obtaining any other adjacencies of a grid.
Currently, partitioning does not cover the boundary, boundary cells belong to one big trivial partition.
ExtendableGrids.pcolors
— Functionpcolors(grid)
Return range of all pcolors based on grid[
PColorPartitions
]
.
ExtendableGrids.pcolor_partitions
— Functionpcolor_partitions(grid, color)
Return range of partitions for given pcolor based on grid[
PColorPartitions
]
.
ExtendableGrids.partition_cells
— Functionpartition_cells(grid, part)
Return range of cells belonging to a given partition grid[
PartitionCells
]
.
ExtendableGrids.partition_bfaces
— Functionpartition_bfaces(grid, part)
Return range of boundary faces belonging to a given partition based on grid[
PartitionBFaces
]
.
ExtendableGrids.partition_nodes
— Functionpartition_nodes(grid, part)
Return range of nodes belonging to a given partition based on grid[
PartitionNodes
]
.
ExtendableGrids.partition_edges
— Functionpartition_edges(grid, part)
Return range of edges belonging to a given partition based on grid[
PartitionEdges
]
.
ExtendableGrids.num_pcolors
— Functionnum_pcolors(grid)
Return number of partition colors based on grid[
PColorPartitions
]
.
ExtendableGrids.num_partitions
— Functionnum_partitions(grid)
Return number of partitions based on grid[
PartitionCells
]
.
ExtendableGrids.num_partitions_per_color
— Functionnum_partitions_per_color(grid)
Return a vector containing the number of partitions for each of the colors of the grid partitioning. These define the maximum number of parallel threads for each color.
ExtendableGrids.num_nodes_per_partition
— Functionnum_nodes_per_partition(grid)
Return a vector containing the number of nodes for each of the partitions of the grid partitioning.
ExtendableGrids.num_edges_per_partition
— Functionnum_edges_per_partition(grid)
Return a vector containing the number of nodes for each of the partitions of the grid partitioning.
ExtendableGrids.num_cells_per_color
— Functionnum_cells_per_color(grid)
Return a vector containing the number of cells for each of the colors of the grid partitioning.
ExtendableGrids.check_partitioning
— Functioncheck_partitioning(grid;
verbose=true,
cellpartonly=false)
Check correctness of cell partitioning, necessesary for parallel assembly:
- Check if every node belongs to one of the cell partitions
- Check if no node belongs to two cell partitions of the same color at once
If cellpartonly==false
check correctness of node partitioning necessary for parallel sparse matrix multiplication and ILU preconditioning
- Check if no node belongs to two node partitions of the same color at once
- Check if no node is a neighbor of nodes from two node partitions of the same color
Partitioning algorithms
ExtendableGrids.AbstractPartitioningAlgorithm
— Typeabstract type AbstractPartitioningAlgorithm
Abstract super type for partitioning algorithms
ExtendableGrids.TrivialPartitioning
— Typestruct TrivialPartitioning <: AbstractPartitioningAlgorithm
Trivial partitioning: all grid cells belong to single partition number 1.
ExtendableGrids.PlainMetisPartitioning
— Typestruct PlainMetisPartitioning <: AbstractPartitioningAlgorithm
Subdivide grid into npart
partitions using Metis.partition
and color the resulting partition neigborhood graph. This requires to import Metis.jl in order to trigger the corresponding extension.
This algorithm allows to control the overall number of partitions. The number of partitions per color comes from the subsequent partition graph coloring and in the moment cannot be controlled.
Parameters:
npart::Int64
: Number of partitions (default: 20)
ExtendableGrids.RecursiveMetisPartitioning
— Typestruct RecursiveMetisPartitioning <: AbstractPartitioningAlgorithm
Subdivide grid into npart
partitions using Metis.partition
and calculate cell separators from this partitioning. The initial partitions get color 1, and the separator gets color 2. This is continued recursively with partitioning of the separator into npart
partitions and calculating the spearator of the separator, giving it color 3.
This algorithm allows to control the number of partitions in color 1 which correspond to the bulk of the work. The overall number of partitions will be in the range of 3*npart
.
If the grid is too coarse for that many partitions, several of them may be just empty.
Parameters:
npart::Int64
: Number of color 1 partitions (default: 4)maxdepth::Int64
: Recursion depth (default: 1)separatorwidth::Int64
: Separator width (default: 2)
Key types for grid access
ExtendableGrids.PColorPartitions
— Typeabstract type PColorPartitions <: AbstractGridIntegerArray1D
Key type describing colors of partitions. These correspond to a coloring of the neigborhood graphs of partitions such that operations (e.g. FEM assembly) on partitions of a given color can be performed in parallel.
grid[PColorPartitions]
returns an integer vector describing the partition colors ("pcolors") of a grid. Let p=grid[PColorPartitions]
. Then all partitions with numbers i ∈ p[c]:p[c+1]-1
have "color" c
. See also pcolors
.
ExtendableGrids.PartitionCells
— Typeabstract type PartitionCells <: AbstractGridIntegerArray1D
Key type describing the cells of a given partition.
grid[PartitionCells]
returns an integer vector describing the cells of a partition given by its number. Let pc=grid[PartitionCells]
. Then all cells with index i ∈ pc[p]:pc[p+1]-1
belong to partition p.
ExtendableGrids.PartitionBFaces
— Typeabstract type PartitionBFaces <: AbstractGridIntegerArray1D
Key type describing the bondary faces of a given partition.
grid[PartitionBFaces]
returns an integer vector describing the boundary faces of a partition given by its number. Let pc=grid[PartitionCells]
. Then all cells with index i ∈ pc[p]:pc[p+1]-1
belong to partition p.
ExtendableGrids.PartitionNodes
— Typeabstract type PartitionNodes <: AbstractGridIntegerArray1D
Key type describing the nodes of a given partition.
grid[PartitionNodes]
returns an integer vector describing the nodes of a partition given by its number. Let pn=grid[PartitionNodes]
. Then all nodes with index i ∈ pn[p]:pn[p+1]-1
belong to partition p.
ExtendableGrids.PartitionEdges
— Typeabstract type PartitionEdges <: AbstractGridIntegerArray1D
Key type describing the edges of a given partition.
grid[PartitionEdges]
returns an integer vector describing the edges of a partition given by its number. Let pe=grid[PartitionEdges]
. Then all edges with index i ∈ pe[p]:pe[p+1]-1
belong to partition p.
ExtendableGrids.NodePermutation
— Typeabstract type NodePermutation <: AbstractGridIntegerArray1D
Key type describing the permutation of the nodes of a partitioned grid with respect to the unpartitioned origin.
If pgrid
is the partitioned grid and grid
is the unpartitioned origin, then
pgrid[Coordinates][:,pgrid[NodePermutation]]==grid[Coordinates]
Internal API
These functions & methods are neither exported nor public.
ExtendableGrids.trivial_partitioning!
— Functiontrivial_partitioning!(grid)
(internal) Create trivial partitioning: the whole grid is partition #1 with just one color.
ExtendableGrids.trivial_partitioning
— Functiontrivial_partitioning(npart, nitems)
(internal) Create a trivial partitioning such that all items fall in the first of nparts
ExtendableGrids.instantiate
— Methodinstantiate(grid::ExtendableGrid, ::Type{PColorPartitions})
If not given otherwise, instantiate partition data with trivial partitioning.
ExtendableGrids.instantiate
— Methodinstantiate(grid::ExtendableGrid, ::Type{PartitionCells})
If not given otherwise, instantiate partition data with trivial partitioning.
ExtendableGrids.instantiate
— Methodinstantiate(grid::ExtendableGrid, ::Type{PartitionBFaces})
If not given otherwise, instantiate partition data with trivial partitioning.
ExtendableGrids.instantiate
— Methodinstantiate(grid::ExtendableGrid, ::Type{PartitionNodes})
If not given otherwise, instantiate partition data with trivial partitioning.
ExtendableGrids.partgraph
— Functionpartgraph(cellpartitions, ncellpartitions, cellcelladj)
(internal) Create neigbourhood graph for given partitioning.
ExtendableGrids.dopartition
— Functiondopartition(grid, alg)
(Internal utility function) Core function for partitioning grid cells which dispatches over partitioning algorithms. Partitioning extensions should add methods to this function.
ExtendableGrids.reorder_cells
— Functionreorder_cells(
grid,
cellpartitions,
ncellpartitions,
colpart
)
(Internal utility function) Create cell permutation such that all cells belonging to one partition are numbered contiguously, return grid with reordered cells.
ExtendableGrids.induce_node_partitioning!
— Functioninduce_node_partitioning!(
grid,
cn,
nc;
trivial,
keep_nodepermutation
)
(internal) Induce node partitioning from cell partitioning of grid
. The algorithm assumes that nodes get the partition number from the partition numbers of the cells having this node in common. If these are differnt, the highest number is taken.
Node partitioning should support parallel matrix-vector products with SparseMatrixCSC
. The current algorithm assumes that nodes get the partition number from the partition numbers of the cells having this node in common. If these are differnt, the highest number is taken.
Simply inducing node partition numbers from cell partition numbers does not always fulfill the condition that there is no node which is neigbour of nodes from two different partition with the same color.
This situation is detected and corrected by joining respective critical partitions, sacrificing a bit of parallel efficiency for correctness.
ExtendableGrids.induce_edge_partitioning!
— Functioninduce_edge_partitioning!(grid; trivial)
(internal) Induce edge partitioning from cell partitioning of grid
. The algorithm assumes that nodes get the partition number from the partition numbers of the cells having this node in common. If these are differnt, the highest number is taken.
This method triggers creation of rather complex edge information and should be called only if this information is really necessary.