diff --git a/CHANGELOG.md b/CHANGELOG.md index 28e8a07..f19ea87 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.2.0] + +Required breaking changes to support Ferrite v1 and later. +### Changed + - Keyword arg of `get_ferrite_grid`: `generate_facesets` -> `generate_facetsets` + - Function renamed: `create_faceset` -> `create_facetset` ## [0.1.8] diff --git a/Project.toml b/Project.toml index 5a27af5..4c9ce71 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "FerriteMeshParser" uuid = "0f8c756f-80dd-4a75-85c6-b0a5ab9d4620" authors = ["Knut Andreas Meyer and contributors"] -version = "0.1.8" +version = "0.2.0" [deps] Ferrite = "c061ca5d-56c9-439f-9c0e-210fe06d3992" diff --git a/docs/src/index.md b/docs/src/index.md index 00b6fdd..88e29b7 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -21,5 +21,5 @@ get_ferrite_grid ``` ```@docs -create_faceset +create_facetset ``` \ No newline at end of file diff --git a/docs/src/literate/compact_tension.jl b/docs/src/literate/compact_tension.jl index afbb769..1211c6f 100644 --- a/docs/src/literate/compact_tension.jl +++ b/docs/src/literate/compact_tension.jl @@ -30,17 +30,18 @@ println([(key, length(set)) for (key, set) in Ferrite.getcellsets(grid)]) # As we see, in addition to the sets created in Abaqus, the cellsets also include a set # for each abaqus element type (useful if you for example defined reduced integration -# in only part of the domain and want to have this in Ferrite). Finally, facesets are -# automatically created by default (can be turned off by `generate_facesets=false` +# in only part of the domain and want to have this in Ferrite). Finally, facetsets are +# automatically created by default (can be turned off by `generate_facetsets=false` # argument) based on the nodesets: println([(key, length(set)) for (key, set) in Ferrite.getfacesets(grid)]) -# Clearly, the faceset `"CrackZone"` doesn't make much sense, but unless the mesh is -# very large it doesn't hurt. The facesets can be created manually from each nodeset -# by using the `create_faceset` function: -faceset = create_faceset(grid, getnodeset(grid,"Hole")); -# This can if desired be merged into the grid by -merge!(Ferrite.getfacesets(grid), Dict("HoleManual" => faceset)) -println([(key, length(set)) for (key, set) in Ferrite.getfacesets(grid)]) +# Clearly, the facetset `"CrackZone"` doesn't make much sense, but unless the mesh is +# very large it doesn't hurt. The facetsets can be created manually from each nodeset +# by using the `create_facetset` function: +facetset = create_facetset(grid, getnodeset(grid,"Hole")); +# This can, if desired, be merged into the grid by +# ```julia +# addfaceset!(grid, "HoleManual", facetset) +# ``` # #md # ## [Plain Program](@id compact-tension-plain-program) diff --git a/src/FerriteMeshParser.jl b/src/FerriteMeshParser.jl index 7d2968d..c5801dd 100644 --- a/src/FerriteMeshParser.jl +++ b/src/FerriteMeshParser.jl @@ -1,5 +1,8 @@ module FerriteMeshParser -using Ferrite +using Ferrite: + Ferrite, Grid, Node, Vec, + getcells, getnodes, getcoordinates, getncells + # Convenience when debugging const DEBUG_PARSE = false @@ -23,6 +26,20 @@ struct InvalidFileContent <: Exception end Base.showerror(io::IO, e::InvalidFileContent) = println(io, e.msg) +@static if !isdefined(Ferrite, :SerendipityQuadraticHexahedron) + const SerendipityQuadraticHexahedron = Ferrite.Cell{3,20,6} + const SerendipityQuadraticQuadrilateral = Ferrite.Cell{2,8,4} +else + const SerendipityQuadraticHexahedron = Ferrite.SerendipityQuadraticHexahedron + const SerendipityQuadraticQuadrilateral = Ferrite.SerendipityQuadraticQuadrilateral +end + +const FacetsDefined = isdefined(Ferrite, :FacetIndex) # Ferrite after v1.0 (Ferrite#914) + +const FacetIndex = FacetsDefined ? Ferrite.FacetIndex : Ferrite.FaceIndex +const facets = FacetsDefined ? Ferrite.facets : Ferrite.faces +const addfacetset! = FacetsDefined ? Ferrite.addfacetset! : Ferrite.addfaceset! + include("rawmesh.jl") include("elements.jl") include("reading_utils.jl") @@ -34,7 +51,7 @@ include("gridcreator.jl") filename; meshformat=AutomaticMeshFormat(), user_elements=Dict{String,DataType}(), - generate_facesets=true + generate_facetsets=true ) Create a `Ferrite.Grid` by reading in the file specified by `filename`. @@ -44,45 +61,46 @@ Optional arguments: is given in, normally automatically detected by the file extension * `user_elements`: Used to add extra elements not supported, might require a separate cell constructor. -* `generate_facesets`: Should facesets be automatically generated from all nodesets? +* `generate_facetsets`: Should facesets be automatically generated from all nodesets? """ -function get_ferrite_grid(filename; meshformat=AutomaticMeshFormat(), user_elements::Dict{String,DataType}=Dict{String,DataType}(), generate_facesets::Bool=true) +function get_ferrite_grid(filename; meshformat=AutomaticMeshFormat(), user_elements::Dict{String, DataType}=Dict{String, DataType}(), generate_facetsets::Bool=true, generate_facesets=nothing) + generate_facesets !== nothing && error("The keyword generate_facesets is deprecated, use generate_facetsets instead") detected_format = detect_mesh_format(filename, meshformat) mesh = read_mesh(filename, detected_format) checkmesh(mesh) grid = create_grid(mesh, detected_format, user_elements) - generate_facesets && generate_facesets!(grid) + generate_facetsets && generate_facetsets!(grid) return grid end """ - create_faceset( + create_facetset( grid::Ferrite.AbstractGrid, nodeset::Set{Int}, cellset::Union{UnitRange{Int},Set{Int}}=1:getncells(grid) ) -Find the faces in the grid for which all nodes are in `nodeset`. Return them as a `Set{FaceIndex}`. +Find the facets in the grid for which all nodes are in `nodeset`. Return them as a `Set{FacetIndex}`. A `cellset` can be given to only look only for faces amongst those cells to speed up the computation. Otherwise the search is over all cells. -This function is normally only required when calling `get_ferrite_grid` with `generate_facesets=false`. -The created `faceset` can be added to the grid as `addfaceset!(grid, "facesetkey", faceset)` +This function is normally only required when calling `get_ferrite_grid` with `generate_facetsets=false`. +The created `facetset` can be added to the grid as `addfacetset!(grid, "facetsetkey", facetset)` """ -function create_faceset(grid::Ferrite.AbstractGrid, nodeset::AbstractSet{Int}, cellset=1:getncells(grid)) - faceset = sizehint!(Set{FaceIndex}(), length(nodeset)) +function create_facetset(grid::Ferrite.AbstractGrid, nodeset::AbstractSet{Int}, cellset=1:getncells(grid)) + facetset = sizehint!(Set{FacetIndex}(), length(nodeset)) for (cellid, cell) in enumerate(getcells(grid)) cellid ∈ cellset || continue if any(n-> n ∈ nodeset, cell.nodes) - for (faceid, face) in enumerate(Ferrite.faces(cell)) - if all(n -> n ∈ nodeset, face) - push!(faceset, FaceIndex(cellid, faceid)) + for (facetid, facet) in enumerate(facets(cell)) + if all(n -> n ∈ nodeset, facet) + push!(facetset, FacetIndex(cellid, facetid)) end end end end - return faceset + return facetset end detect_mesh_format(_, meshformat) = meshformat @@ -94,6 +112,12 @@ function detect_mesh_format(filename, ::AutomaticMeshFormat) end end -export get_ferrite_grid, create_faceset +export get_ferrite_grid, create_facetset + +# Deprecated +function create_faceset(args...) + error("create_faceset is no longer supported, use create_facetset instead") +end +export create_faceset end diff --git a/src/elements.jl b/src/elements.jl index 5ee8c75..9f70d0e 100644 --- a/src/elements.jl +++ b/src/elements.jl @@ -1,22 +1,17 @@ -@static if !isdefined(Ferrite, :SerendipityQuadraticHexahedron) - const SerendipityQuadraticHexahedron = Cell{3,20,6} - const SerendipityQuadraticQuadrilateral = Cell{2,8,4} -end - function get_element_type_dict(::AbaqusMeshFormat) - quad = (Quadrilateral, ("CPE4", "CPS4", "CPE4R", "CPS4R")) + quad = (Ferrite.Quadrilateral, ("CPE4", "CPS4", "CPE4R", "CPS4R")) quad2 = (SerendipityQuadraticQuadrilateral, ("CPS8", "CPS8R", "CPE8", "CPE8R")) - tria = (Triangle, ("CPE3", "CPS3")) - tria2 = (QuadraticTriangle, ("CPE6", "CPS6", "CPE6M", "CPS6M")) - tetra = (Tetrahedron, ("C3D4",)) - tetra2 = (QuadraticTetrahedron, ("C3D10",)) - hexa = (Hexahedron, ("C3D8","C3D8R")) + tria = (Ferrite.Triangle, ("CPE3", "CPS3")) + tria2 = (Ferrite.QuadraticTriangle, ("CPE6", "CPS6", "CPE6M", "CPS6M")) + tetra = (Ferrite.Tetrahedron, ("C3D4",)) + tetra2 = (Ferrite.QuadraticTetrahedron, ("C3D10",)) + hexa = (Ferrite.Hexahedron, ("C3D8","C3D8R")) hexa2 = (SerendipityQuadraticHexahedron, ("C3D20","C3D20R")) - dict = Dict{String,DataType}() + dict = Dict{String, DataType}() for types in (quad, tria, quad2, tria2, tetra, tetra2, hexa, hexa2) - merge!(dict, Dict(code=>types[1] for code in types[2])) + merge!(dict, Dict(code => types[1] for code in types[2])) end return dict end diff --git a/src/gridcreator.jl b/src/gridcreator.jl index f39e018..022def5 100644 --- a/src/gridcreator.jl +++ b/src/gridcreator.jl @@ -17,9 +17,9 @@ function create_nodes(rawnodes::RawNodes, ::Val{dim}) where{dim} return nodes end -function create_cells(rawelementsdict::Dict{String,RawElements}, user_elements::Dict, format) +function create_cells(rawelementsdict::Dict{String, RawElements}, user_elements::Dict, format) builtin_elements = get_element_type_dict(format) - num_elements = sum(getnumelements.(values(rawelementsdict))) + num_elements = sum(getnumelements, values(rawelementsdict)) cells_generic = Array{Ferrite.AbstractCell}(undef, num_elements) for (key, rawelements) in rawelementsdict if haskey(user_elements, key) # user_elements are prioritized over builtin @@ -31,14 +31,14 @@ function create_cells(rawelementsdict::Dict{String,RawElements}, user_elements:: end end # Return a Union of cell types as this should be faster to use than a generic cell - cell_type = Union{(typeof.(unique(typeof,cells_generic))...)} - cells = convert(Array{cell_type}, cells_generic) + CellType = Union{(typeof.(unique(typeof, cells_generic))...)} + cells = convert(Array{CellType}, cells_generic) return cells end function addcells!(cells, elementtype, rawelements::RawElements, format) for (i, element_number) in enumerate(getnumbers(rawelements)) - node_numbers = gettopology(rawelements)[:,i] + node_numbers = gettopology(rawelements)[:, i] cells[element_number] = create_cell(elementtype, node_numbers, format) end end @@ -56,13 +56,15 @@ end """ - function generate_facesets!(grid::Ferrite.Grid) + function generate_facetsets!(grid::Ferrite.Grid) Based on all nodesets in `grid`, generate facesets for those sets. +If there is a cellset in the grid with the same name as the nodeset, +only facets for cells in that cellset with be created. """ -function generate_facesets!(grid::Ferrite.Grid) +function generate_facetsets!(grid::Ferrite.Grid) for (key, set) in Ferrite.getnodesets(grid) cellset = get(Ferrite.getcellsets(grid), key, 1:getncells(grid)) - addfaceset!(grid, key, create_faceset(grid, set, cellset)) + addfacetset!(grid, key, create_facetset(grid, set, cellset)) end -end \ No newline at end of file +end diff --git a/test/runtests.jl b/test/runtests.jl index d541255..b521dfb 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -7,7 +7,7 @@ using Aqua Aqua.test_all(FerriteMeshParser; ambiguities = false) Aqua.test_ambiguities(FerriteMeshParser) # This excludes Core and Base, which gets many ambiguities with ForwardDiff - + # Function to retrieve test fields gettestfile(args...) = joinpath(@__DIR__, "test_files", args...) @@ -22,6 +22,10 @@ if !isdefined(Main, :SerendipityQuadrilateral) Ferrite.faces(c::SerendipityQuadrilateral) = ((c.nodes[1],c.nodes[2]), (c.nodes[2],c.nodes[3]), (c.nodes[3],c.nodes[4]), (c.nodes[4],c.nodes[1])) end +if !isdefined(Ferrite, :getfacetset) + getfacetset(args...) = Ferrite.getfaceset(args...) +end + if isdefined(Ferrite, :FieldHandler) create_cell_values(ip; order=1) = CellScalarValues(QuadratureRule{Ferrite.getdim(ip), Ferrite.getrefshape(ip)}(order), ip, ip) else # v1.0 @@ -66,12 +70,12 @@ end @test _getgridtype(grid_mixed) == Union{Triangle,Quadrilateral} end -@testset "facesetgeneration" begin +@testset "facet set generation" begin filename = gettestfile("compact_tension.inp") grid = get_ferrite_grid(filename) - face_set = create_faceset(grid, getnodeset(grid, "Hole")) - @test getfaceset(grid, "Hole") == face_set - @test face_set == create_faceset(grid, getnodeset(grid, "Hole"), getcellset(grid, "Hole")) # Test that including cells doesn't change the created sets + face_set = create_facetset(grid, getnodeset(grid, "Hole")) + @test getfacetset(grid, "Hole") == face_set + @test face_set == create_facetset(grid, getnodeset(grid, "Hole"), getcellset(grid, "Hole")) # Test that including cells doesn't change the created sets end @testset "exceptions" begin @@ -96,6 +100,9 @@ end showerror(io, FerriteMeshParser.UnsupportedElementType(test_string)) @test contains(String(take!(io)), test_string) + grid = get_ferrite_grid(gettestfile("compact_tension.inp")) + nset = getnodeset(grid, "Hole") + @test_throws ErrorException("create_faceset is no longer supported, use create_facetset instead") create_faceset(grid, nset) end @testset "ordering" begin