Skip to content

Commit

Permalink
Merge pull request #52 from j-fu/correct_nodepart
Browse files Browse the repository at this point in the history
correction of node partitioning
  • Loading branch information
j-fu authored Jun 24, 2024
2 parents 27fb98f + 186166f commit d3a9252
Show file tree
Hide file tree
Showing 9 changed files with 350 additions and 147 deletions.
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "ExtendableGrids"
uuid = "cfc395e8-590f-11e8-1f13-43a2532b2fa8"
authors = ["Juergen Fuhrmann <[email protected]>", "Christian Merdon <[email protected]>", "Johannes Taraz <[email protected]>"]
version = "1.7"
version = "1.8"

[deps]
AbstractTrees = "1520ce14-60c1-5f80-bbc7-55ef81b5835c"
Expand Down
25 changes: 21 additions & 4 deletions docs/src/partitioning.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,29 @@
Grid partitioning is an experimental feature. Breaking changes
in this realm may occur with minor version updates.

The general idea is that 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) on different partitions of the same color can be performed in parallel
without writing 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
```@docs
partition
num_pcolors
num_partitions
num_partitions_per_color
num_cells_per_color
pcolors
pcolor_partitions
partition_cells
partition_bfaces
partition_nodes
num_pcolors
num_partitions
num_partitions_per_color
num_nodes_per_partition
num_cells_per_color
check_partitioning
```

Expand All @@ -31,17 +43,22 @@ RecursiveMetisPartitioning
```@docs
PColorPartitions
PartitionCells
PartitionBFaces
PartitionNodes
NodePermutation
```

## Internal API
These functions & methods are neither exported nor public.
```@docs
ExtendableGrids.trivial_partitioning!
ExtendableGrids.trivial_partitioning
ExtendableGrids.instantiate(grid::ExtendableGrid, ::Type{PColorPartitions})
ExtendableGrids.instantiate(grid::ExtendableGrid, ::Type{PartitionCells})
ExtendableGrids.instantiate(grid::ExtendableGrid, ::Type{PartitionBFaces})
ExtendableGrids.instantiate(grid::ExtendableGrid, ::Type{PartitionNodes})
ExtendableGrids.partgraph
ExtendableGrids.dopartition
ExtendableGrids.reorder_cells
ExtendableGrids.induce_node_partitioning!
```
11 changes: 5 additions & 6 deletions ext/ExtendableGridsMetisExt.jl
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
module ExtendableGridsMetisExt

import Metis
import ExtendableGrids: partition, partgraph, induce_node_partitioning!, reorder_cells
import ExtendableGrids: dopartition, partgraph, induce_node_partitioning!, reorder_cells
using ExtendableGrids, Graphs


function partition(grid::ExtendableGrid{Tc,Ti}, alg::PlainMetisPartitioning) where {Tc,Ti}
function dopartition(grid::ExtendableGrid{Tc,Ti}, alg::PlainMetisPartitioning) where {Tc,Ti}
nn = num_nodes(grid)
ncells = num_cells(grid)
cn = asparse(grid[CellNodes])
Expand Down Expand Up @@ -39,12 +39,11 @@ function partition(grid::ExtendableGrid{Tc,Ti}, alg::PlainMetisPartitioning) whe
end

pgrid=reorder_cells(grid,cellpartitions,ncellpartitions,colpart)
induce_node_partitioning!(pgrid,nc; trivial=!alg.partition_nodes, keep_nodepermutation=alg.keep_nodepermutation)
induce_node_partitioning!(pgrid,cn,nc; trivial=!alg.partition_nodes, keep_nodepermutation=alg.keep_nodepermutation)
end


function coloredpartition(cc; npart = 4, depth = 0, maxdepth=4, separatorwidth=2)
@info "depth=$depth"
mg = Metis.graph(cc)
Metis.options[Int(Metis.METIS_OPTION_CCORDER)+1] = 1

Expand Down Expand Up @@ -133,14 +132,14 @@ function coloredpartition(cc; npart = 4, depth = 0, maxdepth=4, separatorwidth=2

end

function partition(grid::ExtendableGrid{Tc,Ti}, alg::RecursiveMetisPartitioning) where {Tc,Ti}
function dopartition(grid::ExtendableGrid{Tc,Ti}, alg::RecursiveMetisPartitioning) where {Tc,Ti}
cn = asparse(grid[CellNodes])
nc = asparse(atranspose(grid[CellNodes]))
cc = nc * cn
cellpartitions, colpart = coloredpartition(cc; npart=alg.npart, maxdepth=alg.maxdepth, separatorwidth=alg.separatorwidth)
ncellpartitions=maximum(cellpartitions)
pgrid=reorder_cells(grid,cellpartitions,ncellpartitions,colpart)
induce_node_partitioning!(pgrid,nc; trivial=!alg.partition_nodes, keep_nodepermutation=alg.keep_nodepermutation)
induce_node_partitioning!(pgrid,cn,nc; trivial=!alg.partition_nodes, keep_nodepermutation=alg.keep_nodepermutation)
end


Expand Down
6 changes: 3 additions & 3 deletions src/ExtendableGrids.jl
Original file line number Diff line number Diff line change
Expand Up @@ -80,9 +80,9 @@ export isconsistent, dangling_nodes
export seemingly_equal, numbers_match

include("partitioning.jl")
export PColorPartitions, PartitionCells, PartitionNodes, NodePermutation
export num_pcolors, num_partitions, pcolors, pcolor_partitions, partition_cells, partition_nodes
export partition, num_partitions_per_color, num_cells_per_color, check_partitioning
export PColorPartitions, PartitionCells, PartitionBFaces, PartitionNodes, NodePermutation
export num_pcolors, num_partitions, pcolors, pcolor_partitions, partition_cells, partition_bfaces, partition_nodes
export partition, num_partitions_per_color, num_cells_per_color, check_partitioning, num_nodes_per_partition
export AbstractPartitioningAlgorithm, TrivialPartitioning, PlainMetisPartitioning, RecursiveMetisPartitioning

include("assemblytypes.jl")
Expand Down
11 changes: 6 additions & 5 deletions src/extendablegrid.jl
Original file line number Diff line number Diff line change
Expand Up @@ -484,12 +484,13 @@ function Base.map(f::Function, grid::ExtendableGrid)
end

function Base.show(io::IO, grid::ExtendableGrid)
str = @sprintf("%s;\ndim: %d nodes: %d cells: %d bfaces: %d",
typeof(grid), dim_space(grid), num_nodes(grid), num_cells(grid), num_bfaces(grid))
if num_edges(grid) > 0
str = @sprintf("%s;\ndim: %d nodes: %d cells: %d bfaces: %d, edges: %d\n",
typeof(grid), dim_space(grid), num_nodes(grid), num_cells(grid), num_bfaces(grid), num_edges(grid))
else
str = @sprintf("%s;\ndim: %d nodes: %d cells: %d bfaces: %d\n",
typeof(grid), dim_space(grid), num_nodes(grid), num_cells(grid), num_bfaces(grid))
str*=@sprintf(", edges: %d", num_edges(grid))
end
if num_partitions(grid)>1
str*="\npartitions/color: $(num_partitions_per_color(grid))"
end
println(io, str)
end
Expand Down
137 changes: 98 additions & 39 deletions src/io.jl
Original file line number Diff line number Diff line change
Expand Up @@ -41,23 +41,32 @@ end
"""
$(TYPEDSIGNATURES)
Write grid to file. Currently for pdelib sg and Gmsh formats.
Write grid to file.
Supported formats:
- "*.sg": pdelib sg format
"""
function Base.write(fname::String, g::ExtendableGrid; format = "")
function Base.write(fname::String, g::ExtendableGrid; format = "", kwargs...)
(fbase, fext) = splitext(fname)
if format == ""
format = fext[2:end]
end
if format == "msh"
try
simplexgrid_to_gmsh(g; filename = fname)
catch e
throw(ErrorException("Missing Gmsh extension. Add Gmsh.jl to your environment and import it to write $(fext) files."))
end
return
try
writegrid(fname,g, Val{Symbol(format)}; kwargs...)
catch e
throw(ErrorException("Writing $(fext) files not supported"))
end
end

function writegrid(filename::String, g::ExtendableGrid, ::Type{Val{:msh}};kwargs...)
try
simplexgrid_to_gmsh(g; filename)
catch e
throw(ErrorException("Missing Gmsh extension. Add Gmsh.jl to your environment and import it to write msh files."))
end
@assert format == "sg"
end

function writegrid(fname::String, g::ExtendableGrid, ::Type{Val{:sg}}; version=v"2.2", kwargs...)
dim_g = dim_grid(g)
dim_s = dim_space(g)
nn = num_nodes(g)
Expand All @@ -73,13 +82,12 @@ function Base.write(fname::String, g::ExtendableGrid; format = "")
open(fname, "w") do file
write(file, @sprintf("SimplexGrid"))
write(file, @sprintf(" "))
write(file, @sprintf("2.1\n"))
write(file, @sprintf("%s\n","$version"[1:end-2]))
write(file, @sprintf("#created by ExtendableGrids.jl (c) J.Fuhrmann et al\n"))
write(file, @sprintf("#mailto:{fuhrmann|streckenbach}@wias-berlin.de\n"))
write(file, @sprintf("#%s\n", Dates.format(Dates.now(), "yyyy-mm-ddTHH-mm-SS")))

write(file, @sprintf("DIMENSION\n%d\n", dim_g))
write(file, @sprintf("NODES\n%d %d\n", nn, dim_s))
write(file, @sprintf("DIMENSION %d\n", dim_g))
write(file, @sprintf("NODES %d %d\n", nn, dim_s))

for inode = 1:nn
for idim = 1:dim_s
Expand All @@ -88,21 +96,35 @@ function Base.write(fname::String, g::ExtendableGrid; format = "")
end
end

write(file, @sprintf("CELLS\n%d\n", nc))
write(file, @sprintf("CELLS %d\n", nc))
for icell = 1:nc
for inode = 1:(dim_g + 1)
write(file, @sprintf("%d ", cellnodes[inode, icell]))
end
write(file, @sprintf("%d\n", cellregions[icell]))
end

write(file, @sprintf("FACES\n%d\n", nbf))
write(file, @sprintf("FACES %d\n", nbf))
for ibface = 1:nbf
for inode = 1:dim_g
write(file, @sprintf("%d ", bfacenodes[inode, ibface]))
end
write(file, @sprintf("%d\n", bfaceregions[ibface]))
end

if version>v"2.1"
function writeitems(key,label)
data=g[key]
write(file, "$(label) $(length(data))\n")
for d in data
write(file, "$d\n")
end
end
writeitems(PColorPartitions,"PCOLORPARTITIONS")
writeitems(PartitionCells,"PARTITIONCELLS")
writeitems(PartitionBFaces,"PARTITIONBFACES")
writeitems(PartitionNodes,"PARTITIONNODES")
end
write(file, @sprintf("END\n"))
flush(file)
flush(file)
Expand All @@ -114,36 +136,47 @@ end
"""
$(TYPEDSIGNATURES)
Read grid from file. Currently for pdelib sg and Gmsh formats.
Read grid from file.
Supported formats:
- "*.sg": pdelib sg files
- "*.geo": gmsh geometry description (requires `using Gmsh`)
- "*.msh": gmsh mesh (requires `using Gmsh`)
"""
function simplexgrid(file::String; format = "")
Ti = Cint
function simplexgrid(file::String; format = "", kwargs...)
(fbase, fext) = splitext(file)
if format == ""
format = fext[2:end]
end
if format == "msh" || format == "geo"
grid = nothing
try
grid = simplexgrid_from_gmsh(file)
catch e
throw(ErrorException("Missing Gmsh extension. Add Gmsh.jl to your environment and import it to read $(fext) files."))
end
return grid
try
simplexgrid(file,Val{Symbol(format)}; kwargs...)
catch e
throw(ErrorException("Reading $(fext) files not supported"))
end
end

@assert format == "sg"
function simplexgrid(file::String, ::Type{Val{:msh}}; kwargs...)
try
simplexgrid_from_gmsh(file)
catch e
throw(ErrorException("Missing Gmsh extension. Add Gmsh.jl to your environment and import it to read msh files."))
end
end

function simplexgrid(file::String, ::Type{Val{:geo}}; kwargs...)
try
simplexgrid_from_gmsh(file)
catch e
throw(ErrorException("Missing Gmsh extension. Add Gmsh.jl to your environment and import it to read geo files."))
end
end

function simplexgrid(file::String, ::Type{Val{:sg}}; kwargs...)
Ti = Cint
tks = TokenStream(file)
expecttoken(tks, "SimplexGrid")
version = parse(Float64, gettoken(tks))
version20 = false

if (version == 2.0)
version20 = true
elseif (version == 2.1)
version20 = false
else
version = VersionNumber(gettoken(tks))

if version<v"2.0" || version>=v"2.3"
error("Read grid: wrong format version: $(version)")
end

Expand All @@ -153,6 +186,13 @@ function simplexgrid(file::String; format = "")
regions = Array{Ti, 1}(undef, 0)
faces = Array{Ti, 2}(undef, 0, 0)
bregions = Array{Ti, 1}(undef, 0)

pcolorpartitions=Array{Ti, 1}(undef, 0)
partitioncells=Array{Ti, 1}(undef, 0)
partitionbfaces=Array{Ti, 1}(undef, 0)
partitionnodes=Array{Ti, 1}(undef, 0)


while (true)
if (trytoken(tks, "DIMENSION"))
dim = parse(Ti, gettoken(tks))
Expand All @@ -177,7 +217,7 @@ function simplexgrid(file::String; format = "")
cells[inode, icell] = parse(Ti, gettoken(tks))
end
regions[icell] = parse(Ti, gettoken(tks))
if version20
if version==v"2.0"
for j = 1:(dim + 1)
gettoken(tks) # skip file format garbage
end
Expand All @@ -192,18 +232,37 @@ function simplexgrid(file::String; format = "")
faces[inode, iface] = parse(Ti, gettoken(tks))
end
bregions[iface] = parse(Ti, gettoken(tks))
if (version20)
if version == v"2.0"
for j = 1:(dim + 2)
gettoken(tks) #skip file format garbage
end
end
end
elseif trytoken(tks, "PCOLORPARTITIONS") && version>v"2.1"
n=parse(Ti, gettoken(tks))
pcolorpartitions=[parse(Ti, gettoken(tks)) for i=1:n]
elseif trytoken(tks, "PARTITIONCELLS") && version>v"2.1"
n=parse(Ti, gettoken(tks))
partitioncells=[parse(Ti, gettoken(tks)) for i=1:n]
elseif trytoken(tks, "PARTITIONBFACES") && version>v"2.1"
n=parse(Ti, gettoken(tks))
partitionbfaces=[parse(Ti, gettoken(tks)) for i=1:n]
elseif trytoken(tks, "PARTITIONNODES") && version>v"2.1"
n=parse(Ti, gettoken(tks))
partitionnodes=[parse(Ti, gettoken(tks)) for i=1:n]
else
expecttoken(tks, "END")
break
end
end
simplexgrid(coord, cells, regions, faces, bregions)
g=simplexgrid(coord, cells, regions, faces, bregions)
if version>v"2.1"
g[PColorPartitions]=pcolorpartitions
g[PartitionCells]=partitioncells
g[PartitionBFaces]=partitionbfaces
g[PartitionNodes]=partitionnodes
end
g
end

function simplexgrid_from_gmsh end
Expand Down
Loading

2 comments on commit d3a9252

@j-fu
Copy link
Member Author

@j-fu j-fu commented on d3a9252 Jun 24, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JuliaRegistrator
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Registration pull request created: JuliaRegistries/General/109666

Tip: Release Notes

Did you know you can add release notes too? Just add markdown formatted text underneath the comment after the text
"Release notes:" and it will be added to the registry PR, and if TagBot is installed it will also be added to the
release that TagBot creates. i.e.

@JuliaRegistrator register

Release notes:

## Breaking changes

- blah

To add them here just re-invoke and the PR will be updated.

Tagging

After the above pull request is merged, it is recommended that a tag is created on this repository for the registered package version.

This will be done automatically if the Julia TagBot GitHub Action is installed, or can be done manually through the github interface, or via:

git tag -a v1.8.0 -m "<description of version>" d3a92527224cda619b2b0ade21eef1176944c8ad
git push origin v1.8.0

Please sign in to comment.