Replies: 12 comments 4 replies
-
Hi @edljk , |
Beta Was this translation helpful? Give feedback.
-
Hi @termi-official, function Ferrite.faces(::Lagrange{2,RefTetrahedron,order}) where order
return (((1:(order + 1))...,), (cumsum((order + 1):-1:1)...,),
((order + 1) * (order + 2) ÷ 2 .- cumsum([0, collect(2:(order + 1))...])...,))
end I am not sure to understand what is expected for the dof assignment along faces in 2D? Was it a 3D observation? |
Beta Was this translation helpful? Give feedback.
-
Yes, and this is exactly why the assertion exist:
because as long as there is just one dof for an edge the orientation doesn't matter. |
Beta Was this translation helpful? Give feedback.
-
Thank you fredrikekre. |
Beta Was this translation helpful? Give feedback.
-
Thank you termi-official, the situation is clear now. julia> test_H1Pk(degfem = 1)
real.(λ) = [-5.3759690384243275e-15, 2.4724574365104006, 2.4724575455509052, 4.965112609288587, 9.950481029670694, 9.950806702685107, 12.466769445826522, 12.540827949304449, 20.220092594807863, 22.61794567596597]
error = 0.20382244794275017
nbdof = 441
julia> test_H1Pk(degfem = 2)
real.(λ) = [6.052240143512161e-14, 2.46740315865208, 2.467403161776321, 4.934830898153275, 9.869735676495825, 9.869735679677525, 12.33727069978334, 12.337492721885768, 19.741019778974213, 22.208093643681096]
error = 0.000487220524069798
nbdof = 1681
julia> test_H1Pk(degfem = 3)
real.(λ) = [75.29284195065094, 81.6602541282197, 90.55757001630815, 93.29508764352964, 106.32266184039761, 118.07857760635417, 122.39257092374741, 138.9103367965305, 139.3015386333036, 148.14236328416197]
error = 126.57333129516879
nbdof = 2921 using Ferrite, SparseArrays, Arpack
function test_H1Pk(; degfem::Int64 = 2, degcurve::Int64 = 1, degquad::Int64 = 6,
dim::Int64 = 2)
typecellq = degcurve == 2 ? QuadraticTriangle : Ferrite.Triangle
grid = generate_grid(typecellq, (20, 20))
typecellq = dim == 2 ? QuadraticTriangle : QuadraticTetrahedron
ip = Ferrite.Lagrange{dim, RefTetrahedron, degfem}()
qr = Ferrite.QuadratureRule{dim, RefTetrahedron}(:legendre, degquad)
ip_geom = Ferrite.Lagrange{dim, RefTetrahedron, degcurve}()
cellvalues = Ferrite.CellScalarValues(qr, ip, ip_geom)
dh = Ferrite.DofHandler(grid)
Ferrite.push!(dh, :u, 1, ip)
Ferrite.close!(dh)
K = create_sparsity_pattern(dh)
doassemble_K_ferrite!(K, cellvalues, dh)
M = create_sparsity_pattern(dh)
doassemble_M_ferrite!(M, cellvalues, dh)
# compute eigenvalues
λ, U = eigs(K, M, nev = 10, which = :LM, tol = 0., maxiter = 30_000,
sigma = rand() / 1e4)
# display
error = maximum(abs.([0, 1/4, 1/4, 1/2, 1, 1, 5/4, 5/4] * pi ^ 2 - λ[1:8]))
@show real.(λ)
@show error
nbdof = size(K, 1)
@show nbdof
return
end
function doassemble_K_ferrite!(K::SparseMatrixCSC,
cellvalues::CellScalarValues{dim},
dh::DofHandler) where {dim}
n_basefuncs = getnbasefunctions(cellvalues)
Ke = zeros(n_basefuncs, n_basefuncs)
assembler = start_assemble(K)
@inbounds for cell in CellIterator(dh)
fill!(Ke, 0)
reinit!(cellvalues, cell)
for q_point in 1:getnquadpoints(cellvalues)
dΩ = getdetJdV(cellvalues, q_point)
for i in 1:n_basefuncs
v = shape_value(cellvalues, q_point, i)
∇v = shape_gradient(cellvalues, q_point, i)
for j in 1:n_basefuncs
∇u = shape_gradient(cellvalues, q_point, j)
Ke[i, j] += (∇v ⋅ ∇u) * dΩ
end
end
end
assemble!(assembler, celldofs(cell), Ke)
end
return K
end
function doassemble_M_ferrite!(M::SparseMatrixCSC,
cellvalues::CellScalarValues{dim}, dh::DofHandler;
ρ::Union{Function, Nothing} = nothing) where {dim}
n_basefuncs = getnbasefunctions(cellvalues)
Me = zeros(n_basefuncs, n_basefuncs)
assembler = start_assemble(M)
valρ = 1.
@inbounds for cell in CellIterator(dh)
fill!(Me, 0)
reinit!(cellvalues, cell)
for q_point in 1:getnquadpoints(cellvalues)
dΩ = getdetJdV(cellvalues, q_point)
if ρ != nothing
pq = spatial_coordinate(cellvalues, q_point,
getcoordinates(cell))
valρ = ρ(pq)
end
for i in 1:n_basefuncs
v = shape_value(cellvalues, q_point, i)
for j in 1:n_basefuncs
u = shape_value(cellvalues, q_point, j)
Me[i, j] += (v * u) * valρ * dΩ
end
end
end
assemble!(assembler, celldofs(cell), Me)
end
return M
end
#--------------------------------------------------------------------------------------------------------
#----------------------------------------- Pk elements --------------------------------------------------
#--------------------------------------------------------------------------------------------------------
function Ferrite.getnbasefunctions(::Lagrange{2,RefTetrahedron,order}) where order
return (order + 1) * (order + 2) ÷ 2
end
Ferrite.nvertexdofs(::Lagrange{2,RefTetrahedron,order}) where order = 1
#Ferrite.nedgedofs(::Lagrange{2,RefTetrahedron,order}) where order = order + 1
Ferrite.nfacedofs(::Lagrange{2,RefTetrahedron,order}) where order = order - 1
function Ferrite.vertices(::Lagrange{2,RefTetrahedron,order}) where order
return (1 + order, (order + 1) * (order + 2) ÷ 2, 1)
end
function Ferrite.faces(::Lagrange{2,RefTetrahedron,order}) where order
return (((1:(order + 1))...,), (cumsum((order + 1):-1:1)...,),
((order + 1) * (order + 2) ÷ 2 .- cumsum([0, collect(2:(order + 1))...])...,))
#=
return (reverse(((1:(order + 1))...,)),
reverse(((order + 1) * (order + 2) ÷ 2 .- cumsum([0, collect(2:(order + 1))...])...,)),
reverse((cumsum((order + 1):-1:1)...,)))
=#
end
function Ferrite.reference_coordinates(::Lagrange{2,RefTetrahedron,order}) where order
coordpts = Vector{Ferrite.Vec{2, Float64}}()
for k = 0:order
for l = 0:(order - k)
push!(coordpts, Ferrite.Vec{2, Float64}((l / order, k / order)))
end
end
return coordpts
end
function Ferrite.value(ip::Lagrange{2,RefTetrahedron,order}, i::Int,
ξ::Ferrite.Vec{2}) where order
ξ1, ξ2, ξ3= 1. - sum(ξ), ξ[1], ξ[2]
i1, i2, i3 = _numlin_basis2DT(i, order)
val = one(typeof(ξ1))
i1 ≥ 1 && (val *= prod((order * ξ1 - j) / (j + 1) for j = 0:(i1 - 1)))
i2 ≥ 1 && (val *= prod((order * ξ2 - j) / (j + 1) for j = 0:(i2 - 1)))
i3 ≥ 1 && (val *= prod((order * ξ3 - j) / (j + 1) for j = 0:(i3 - 1)))
return val
end
function _numlin_basis2DT(i, order)
c, j1, j2, j3 = 0, 0, 0, 0
for k = 0:order
if i <= c + (order + 1 - k)
j2 = i - c - 1
break
else
j3 += 1
c += order + 1 - k
end
end
j1 = order - j2 -j3
return j1, j2, j3
end |
Beta Was this translation helpful? Give feedback.
-
I identified one mistake in previous code (the barycentric coordinates |
Beta Was this translation helpful? Give feedback.
-
In particular this means that the first N dofs are the same for linear and quadratic, and first M dofs the same for quad and third order etc |
Beta Was this translation helpful? Give feedback.
-
Thank you @fredrikekre for the comments and the test function. It seems that my previous piece of code passes the tests.
julia> ip = Lagrange{2, RefTetrahedron, 3}()
julia> Ferrite.getnbasefunctions(ip)
10
julia> Ferrite.nvertexdofs(ip)
1
julia> Ferrite.nedgedofs(ip) # correct?
2
julia> Ferrite.nfacedofs(ip) # correct?
2
julia> Ferrite.vertices(ip)
(1, 2, 3)
julia> Ferrite.faces(ip)
((1, 2, 4, 5), (2, 3, 6, 7), (3, 1, 8, 9))
julia> Ferrite.reference_coordinates(ip)
10×1 Matrix{Vec{2, Float64}}:
[1.0, 0.0]
[0.0, 1.0]
[0.0, 0.0]
[0.6666666666666666, 0.3333333333333333]
[0.3333333333333333, 0.6666666666666666]
[0.0, 0.6666666666666666]
[0.0, 0.3333333333333333]
[0.3333333333333333, 0.0]
[0.6666666666666666, 0.0]
[0.3333333333333333, 0.3333333333333333]
|
Beta Was this translation helpful? Give feedback.
-
No, probably this can not hold for order 3
Yea, I believe that all looks fine. Can you share your implementation, maybe open it as a WIP pull request? That might make it easier to communicate and play around with it. |
Beta Was this translation helpful? Give feedback.
-
WIP PR opened here for reference: #482 |
Beta Was this translation helpful? Give feedback.
-
Curved mesh of order > 2 not implemented yet. Not sure what should be done. Will try to have a look. Thanks. |
Beta Was this translation helpful? Give feedback.
-
Perhaps I am missing something. Here is a simple example with a circular boundary of order 3 which produces an error. p = [-0.222521 -0.974928
4.15312e-17 4.93183e-17
-0.900969 -0.433884
-0.148347 -0.649952
-0.0741736 -0.324976
-0.300323 -0.144628
-0.600646 -0.289256
-0.739526 -0.673128
-0.491692 -0.870769
-0.62349 -0.781831
0.62349 -0.781831
0.0651862 -0.997873
0.37423 -0.927336
0.41566 -0.521221
0.20783 -0.26061
0.222521 -0.974928
1.0 2.03666e-16
0.820812 -0.571199
0.958349 -0.2856
0.666667 -5.52021e-17
0.333333 3.57829e-17
0.900969 -0.433884
-0.222521 0.974928
-0.900969 0.433884
-0.491692 0.870769
-0.739526 0.673128
-0.600646 0.289256
-0.300323 0.144628
-0.0741736 0.324976
-0.148347 0.649952
-0.62349 0.781831
0.62349 0.781831
0.20783 0.26061
0.41566 0.521221
0.37423 0.927336
0.0651862 0.997873
0.222521 0.974928
-0.98736 0.158496
-0.98736 -0.158496
-1.0 1.25146e-16
0.958349 0.2856
0.820812 0.571199
0.900969 0.433884]
np = size(p, 1)
nodes = [Ferrite.Node((p[k, :]...,)) for k = 1:np]
cells = [Cell{2, 10, 3}((1, 2, 3, 4, 5, 6, 7, 8, 9, 10)),
Cell{2, 10, 3}((2, 1, 11, 5, 4, 12, 13, 14, 15, 16)),
Cell{2, 10, 3}((11, 17, 2, 18, 19, 20, 21, 15, 14, 22)),
Cell{2, 10, 3}((23, 24, 2, 25, 26, 27, 28, 29, 30, 31)),
Cell{2, 10, 3}((23, 2, 32, 30, 29, 33, 34, 35, 36, 37)),
Cell{2, 10, 3}((24, 3, 2, 38, 39, 7, 6, 28, 27, 40)),
Cell{2, 10, 3}((2, 17, 32, 21, 20, 41, 42, 34, 33, 43))]
grid = Ferrite.Grid(cells, nodes)
@show grid
ip = Lagrange{2, RefTetrahedron, 1}()
qr = QuadratureRule{2, RefTetrahedron}(:legendre, 6)
ip_geom = Lagrange{2, RefTetrahedron, 3}()
cellvalues = CellScalarValues(qr, ip, ip_geom)
dh = DofHandler(grid)
push!(dh, :u, 1, ip)
close!(dh) ERROR: LoadError: MethodError: no method matching default_interpolation(::Type{Cell{2, 10, 3}})
Closest candidates are:
default_interpolation(::Union{Type{Ferrite.Line}, Type{Line2D}, Type{Line3D}}) at .julia/dev/Ferrite/src/Grid/grid.jl:738
default_interpolation(::Union{Type{Quadrilateral}, Type{Quadrilateral3D}}) at .julia/dev/Ferrite/src/Grid/grid.jl:742
default_interpolation(::Type{QuadraticLine}) at .julia/dev/Ferrite/src/Grid/grid.jl:739
...
Stacktrace:
[1] push!(dh::DofHandler{2, Float64, Grid{2, Cell{2, 10, 3}, Float64}}, name::Symbol, dim::Int64, ip::Lagrange{2, RefTetrahedron, 1})
@ Ferrite .julia/dev/Ferrite/src/Dofs/DofHandler.jl:121
[2] top-level scope
@ Julia/experiments/ferrite/test_Ferritecurve.jl:62
[3] include(fname::String)
@ Base.MainInclude ./client.jl:451
[4] top-level scope
@ REPL[27]:1 |
Beta Was this translation helpful? Give feedback.
-
I wonder if there are some plans to generalize interpolation.jl (and whatever needed) to higher order Lagrange elements on simplices (2D/3D)?
Following Getem++ Appendix, a naive implementation in 2D for instance would be the following functions.
Trying to test these "new" elements (like
P3
), I obtained an assertion errorERROR: AssertionError: ip_info.nedgedofs <= 1
, etc..Do you have any idea of the required steps to make these new elements available?
Thanks
Beta Was this translation helpful? Give feedback.
All reactions