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

Support for node and edge sets #41

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion .github/workflows/CI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
fail-fast: false
matrix:
version:
- '1.6'
- '1.10'
- '1'
- 'nightly'
os:
Expand Down
5 changes: 3 additions & 2 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,13 @@ Ferrite = "c061ca5d-56c9-439f-9c0e-210fe06d3992"
Gmsh = "705231aa-382f-11e9-3f0c-b7cb4346fdeb"

[compat]
Ferrite = "0.3, 1"
Ferrite = "1"
Gmsh = "0.2, 0.3"
julia = "1.6"

[extras]
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"

[targets]
test = ["Test"]
test = ["Test", "LinearAlgebra"]
9 changes: 7 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,19 +50,24 @@ gmsh.model.mesh.renumberNodes()
gmsh.model.mesh.renumberElements()

# transfer the gmsh information
nodes = tonodes()
nodes, gmsh_nodeidx = tonodes()
elements, gmsh_elementidx = toelements(dim)
cellsets = tocellsets(dim, gmsh_elementidx)
nodesets = tonodesets(gmsh_nodeidx)

# "Domain" is the name of a PhysicalGroup and saves all cells that define the computational domain
domaincellset = cellsets["Domain"]
elements = elements[collect(domaincellset)]

boundarydict = toboundary(facedim)
facesets = tofacetsets(boundarydict, elements)

# Edge sets (physical groups of dimension 1) must be saved separately as they are not stored in Ferrite's grid defintion.
edgesets = toedgetsets(elements)

gmsh.finalize()

Grid(elements, nodes, facesets=facesets, cellsets=cellsets)
Grid(elements, nodes, facesets=facesets, cellsets=cellsets, nodesets=nodesets)
```

## Elements numbering & Supported elements
Expand Down
89 changes: 61 additions & 28 deletions src/FerriteGmsh.jl
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ end
function tonodes()
nodeid, nodes = gmsh.model.mesh.getNodes()
dim = Int64(gmsh.model.getDimension()) # Int64 otherwise julia crashes
return [Node(Vec{dim}(nodes[i:i + (dim - 1)])) for i in 1:3:length(nodes)]
return [Node(Vec{dim}(nodes[i:i + (dim - 1)])) for i in 1:3:length(nodes)], Int64.(nodeid)
end

function toelements(dim::Int)
Expand Down Expand Up @@ -235,54 +235,86 @@ function toboundary(dim::Int)
append!(boundaryconnectivity, [Tuple(boundarynodetags[i:i + (numnodes - 1)]) for i in 1:numnodes:length(boundarynodetags)])
end
boundarydict[name] = boundaryconnectivity
end
end
return boundarydict
end

function _add_to_facetsettuple!(facetsettuple::Set{FacetIndex}, boundaryfacet::Tuple, element_facets)
for (eleidx, elefacets) in enumerate(element_facets)
function _add_to_boundarysettuple!(boundarsettuple::Set{IndexType}, boundaryfacet::Tuple, element_boundaries) where IndexType
for (eleidx, elefacets) in enumerate(element_boundaries)
if any(issubset.(elefacets, (boundaryfacet,)))
localfacet = findfirst(x -> issubset(x,boundaryfacet), elefacets)
push!(facetsettuple, FacetIndex(eleidx, localfacet))
push!(boundarsettuple, IndexType(eleidx, localfacet))
end
end
return facetsettuple
return boundarsettuple
end

function tofacetsets(boundarydict::Dict{String,Vector}, elements::Vector{<:Ferrite.AbstractCell})
element_facets = facets.(elements)
facetsets = Dict{String,Set{FacetIndex}}()
for (boundaryname, boundaryfacets) in boundarydict
facetsettuple = Set{FacetIndex}()
for boundaryfacet in boundaryfacets
_add_to_facetsettuple!(facetsettuple, boundaryfacet, element_facets)
function boundary_to_setdefinition(::Val{IndexType}, boundarydict::Dict{String,Vector}, element_boundaries) where IndexType
boundarySet = Dict{String,Set{IndexType}}()
for (boundaryname, boundaryentities) in boundarydict
boundarysettuple = Set{IndexType}()
for boundaryentity in boundaryentities
_add_to_boundarysettuple!(boundarysettuple, boundaryentity, element_boundaries)
end
facetsets[boundaryname] = facetsettuple
boundarySet[boundaryname] = boundarysettuple
end
return facetsets
return boundarySet
end

function tocellsets(dim::Int, global_elementtags::Vector{Int})
cellsets = Dict{String,Set{Int}}()
element_to_cell_mapping = Dict(zip(global_elementtags, eachindex(global_elementtags)))
tofacetsets(boundarydict::Dict{String,Vector}, elements::Vector{<:Ferrite.AbstractCell}) = boundary_to_setdefinition(Val(FacetIndex), boundarydict, (facets(e) for e in elements))

"""
toedgeset(elements::Vector{<:Ferrite.AbstractCell})
toedgeset(grid::Grid)

Generate a dictionary of edge sets (Set{Ferrite.EdgeIndex}), i.e., physical groups of dim=1, using the element definitions in `elements` or `grid`.
Ferrite does not store edge sets in the grid, but they can be used to define boundary conditions.

The function `toedgeset` reguires that the GMSH model has not been finalized.
Therefore, when using [`togrid`](@ref), `Gmsh.initialize()` must be called before `togrid` to bypass the automatic initialization and finalization of the GMSH model.

*Examples*
```jldoctest
using FerriteGmsh

gmsh.initialize()
grid = togrid("meshfile.msh")
edgesets = toedgeset(grid)
gmsh.finalize()

edgesets = toedgeset(grid) # Errors as gmsh has not been initialized
```
"""
toedgetsets(elements::Vector{<:Ferrite.AbstractCell}) = boundary_to_setdefinition(Val(Ferrite.EdgeIndex), toboundary(1), (Ferrite.edges(e) for e in elements))
toedgetsets(grid::Grid) = toedgetsets(Ferrite.getcells(grid))

getMeshEntity(::Val{0}, entity) = [gmsh.model.mesh.getNodes(0, entity)[1]]
getMeshEntity(::Val{T}, entity) where T = gmsh.model.mesh.getElements(T, entity)[2]

function todimEntitysets(dim::Int, global_entity_tags::Vector{Int})
entityset = Dict{String,Set{Int}}()
gmsh_to_ferrite_mapping = Dict(zip(global_entity_tags, eachindex(global_entity_tags)))
physicalgroups = gmsh.model.getPhysicalGroups(dim)
for (_, physicaltag) in physicalgroups
gmshname = gmsh.model.getPhysicalName(dim, physicaltag)
isempty(gmshname) ? (name = "$physicaltag") : (name = gmshname)
entities = gmsh.model.getEntitiesForPhysicalGroup(dim,physicaltag)
cellsetelements = Set{Int}()
ferrite_entities = Set{Int}()
for entity in entities
_, elementtags, _= gmsh.model.mesh.getElements(dim, entity)
elementtags = getMeshEntity(Val(dim), entity)
elementtags = reduce(vcat,elementtags) |> x-> convert(Vector{Int},x)
for ele in elementtags
push!(cellsetelements, element_to_cell_mapping[ele])
push!(ferrite_entities, gmsh_to_ferrite_mapping[ele])
end
cellsets[name] = cellsetelements
entityset[name] = ferrite_entities
end
end
return cellsets
return entityset
end

tocellsets(dim::Int, global_entity_tags::Vector{Int}) = todimEntitysets(dim, global_entity_tags)
tonodesets(global_entity_tags::Vector{Int}) = todimEntitysets(0, global_entity_tags)

"""
togrid(filename::String; domain="")

Expand Down Expand Up @@ -327,9 +359,10 @@ function togrid(; domain="")
end
gmsh.model.mesh.renumberNodes()
gmsh.model.mesh.renumberElements()
nodes = tonodes()
nodes, gmsh_nodeidx = tonodes()
nodesets = todimEntitysets(0, gmsh_nodeidx)
elements, gmsh_elementidx = toelements(dim)
cellsets = tocellsets(dim, gmsh_elementidx)
cellsets = todimEntitysets(dim, gmsh_elementidx)

if !isempty(domain)
domaincellset = cellsets[domain]
Expand All @@ -343,14 +376,14 @@ function togrid(; domain="")
gmsh.option.setNumber("Mesh.SaveAll",0)
end
@static if isdefined(Ferrite, :FacetIndex)
return Grid(elements, nodes, facetsets=facetsets, cellsets=cellsets)
return Grid(elements, nodes, facetsets=facetsets, cellsets=cellsets, nodesets=nodesets)
else # Compat for Ferrite before v1.0
return Grid(elements, nodes, facesets=facetsets, cellsets=cellsets)
return Grid(elements, nodes, facesets=facetsets, cellsets=cellsets, nodesets=nodesets)
end
end

export gmsh
export tonodes, toelements, toboundary, tofacetsets, tocellsets, togrid
export tonodes, toelements, toboundary, tofacetsets, tocellsets, togrid, tonodesets, toedgetsets

@deprecate tofacesets tofacetsets

Expand Down
2 changes: 1 addition & 1 deletion test/devtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ gmsh.model.setPhysicalName(1,5,"My Boundary")
ps = gmsh.model.addPhysicalGroup(2, [1])
gmsh.model.setPhysicalName(2, ps, "My Domain")
gmsh.model.mesh.generate(2)
nodes = tonodes()
nodes,_ = tonodes()
elements, gmsh_eleidx = toelements(2)
boundarydict = toboundary(1)
faceset = tofacetsets(boundarydict, elements)
Expand Down
1 change: 1 addition & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,6 @@ include("test_mixed_mesh.jl")
include("test_multiple_entities_group.jl")
include("test_togrid.jl")
include("test_saveall_flag.jl")
include("test_grid_sets_examples.jl")

@test_throws SystemError togrid("this-file-does-not-exist.msh")
Loading
Loading