-
Notifications
You must be signed in to change notification settings - Fork 0
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
Non-overlapping dof handler #7
Merged
Merged
Conversation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Depends on Ferrite-FEM/Ferrite.jl#655 |
This branch reached parity with Ferrite-FEM/Ferrite.jl#486 on the last commit. Reproducer for the distributed assembly of the Cooks membrane problem: using FerriteDistributed
using IterativeSolvers
using PartitionedArrays, Metis
using BlockArrays
# Launch MPI
MPI.Init()
# First we generate a simple grid, specifying the 4 corners of Cooks membrane.
function create_cook_grid(nx, ny)
corners = [Vec{2}((0.0, 0.0)),
Vec{2}((48.0, 44.0)),
Vec{2}((48.0, 60.0)),
Vec{2}((0.0, 44.0))]
grid = generate_grid(Triangle, (nx, ny), corners);
## facesets for boundary conditions
addfaceset!(grid, "clamped", x -> norm(x[1]) ≈ 0.0);
addfaceset!(grid, "traction", x -> norm(x[1]) ≈ 48.0);
return FerriteDistributed.NODGrid(MPI.COMM_WORLD, grid)
end;
# Next we define a function to set up our cell- and facevalues.
function create_values(interpolation_u, interpolation_p)
## quadrature rules
qr = QuadratureRule{RefTriangle}(3)
face_qr = FaceQuadratureRule{RefTriangle}(3)
## geometric interpolation
interpolation_geom = Lagrange{RefTriangle,1}()^2
## cell and facevalues for u
cellvalues_u = CellValues(qr, interpolation_u, interpolation_geom)
facevalues_u = FaceValues(face_qr, interpolation_u, interpolation_geom)
## cellvalues for p
cellvalues_p = CellValues(qr, interpolation_p, interpolation_geom)
return cellvalues_u, cellvalues_p, facevalues_u
end;
# We create a DofHandler, with two fields, `:u` and `:p`,
# with possibly different interpolations
function create_dofhandler(grid, ipu, ipp)
dh = DofHandler(grid)
push!(dh, :u, ipu) # displacement
push!(dh, :p, ipp) # pressure
close!(dh)
return dh
end;
# We also need to add Dirichlet boundary conditions on the `"clamped"` faceset.
# We specify a homogeneous Dirichlet bc on the displacement field, `:u`.
function create_bc(dh)
ch = ConstraintHandler(dh)
add!(ch, Dirichlet(:u, getfaceset(getgrid(dh), "clamped"), (x,t) -> zero(Vec{2}), [1,2]))
close!(ch)
t = 0.0
update!(ch, t)
return ch
end;
# The material is linear elastic, which is here specified by the shear and bulk moduli
struct LinearElasticity{T}
G::T
K::T
end
# Now to the assembling of the stiffness matrix. This mixed formulation leads to a blocked
# element matrix. Since Ferrite does not force us to use any particular matrix type we will
# use a `PseudoBlockArray` from `BlockArrays.jl`.
function doassemble(cellvalues_u::CellValues, cellvalues_p::CellValues,
facevalues_u::FaceValues, grid::FerriteDistributed.NODGrid,
dh::FerriteDistributed.NODDofHandler{dim}, ch::ConstraintHandler, mp::LinearElasticity) where {dim}
assembler = start_assemble(dh, distribute_with_mpi(LinearIndices((MPI.Comm_size(MPI.COMM_WORLD),))))
nu = getnbasefunctions(cellvalues_u)
np = getnbasefunctions(cellvalues_p)
fe = PseudoBlockArray(zeros(nu + np), [nu, np]) # local force vector
ke = PseudoBlockArray(zeros(nu + np, nu + np), [nu, np], [nu, np]) # local stiffness matrix
## traction vector
t = Vec{2}((0.0, 1/16))
## cache ɛdev outside the element routine to avoid some unnecessary allocations
ɛdev = [zero(SymmetricTensor{2, dim}) for i in 1:getnbasefunctions(cellvalues_u)]
for cell in CellIterator(dh)
fill!(ke, 0)
fill!(fe, 0)
assemble_up!(ke, fe, cell, cellvalues_u, cellvalues_p, facevalues_u, grid, mp, ɛdev, t)
apply_local!(ke, fe, celldofs(cell), ch)
Ferrite.assemble!(assembler, celldofs(cell), fe, ke)
end
return end_assemble(assembler)
end;
# The element routine integrates the local stiffness and force vector for all elements.
# Since the problem results in a symmetric matrix we choose to only assemble the lower part,
# and then symmetrize it after the loop over the quadrature points.
function assemble_up!(Ke, fe, cell, cellvalues_u, cellvalues_p, facevalues_u, grid, mp, ɛdev, t)
n_basefuncs_u = getnbasefunctions(cellvalues_u)
n_basefuncs_p = getnbasefunctions(cellvalues_p)
u▄, p▄ = 1, 2
reinit!(cellvalues_u, cell)
reinit!(cellvalues_p, cell)
## We only assemble lower half triangle of the stiffness matrix and then symmetrize it.
@inbounds for q_point in 1:getnquadpoints(cellvalues_u)
for i in 1:n_basefuncs_u
ɛdev[i] = dev(symmetric(shape_gradient(cellvalues_u, q_point, i)))
end
dΩ = getdetJdV(cellvalues_u, q_point)
for i in 1:n_basefuncs_u
divδu = shape_divergence(cellvalues_u, q_point, i)
δu = shape_value(cellvalues_u, q_point, i)
for j in 1:i
Ke[BlockIndex((u▄, u▄), (i, j))] += 2 * mp.G * ɛdev[i] ⊡ ɛdev[j] * dΩ
end
end
for i in 1:n_basefuncs_p
δp = shape_value(cellvalues_p, q_point, i)
for j in 1:n_basefuncs_u
divδu = shape_divergence(cellvalues_u, q_point, j)
Ke[BlockIndex((p▄, u▄), (i, j))] += -δp * divδu * dΩ
end
for j in 1:i
p = shape_value(cellvalues_p, q_point, j)
Ke[BlockIndex((p▄, p▄), (i, j))] += - 1/mp.K * δp * p * dΩ
end
end
end
symmetrize_lower!(Ke)
## We integrate the Neumann boundary using the facevalues.
## We loop over all the faces in the cell, then check if the face
## is in our `"traction"` faceset.
@inbounds for face in 1:nfaces(cell)
if (cellid(cell), face) ∈ getfaceset(grid, "traction")
reinit!(facevalues_u, cell, face)
for q_point in 1:getnquadpoints(facevalues_u)
dΓ = getdetJdV(facevalues_u, q_point)
for i in 1:n_basefuncs_u
δu = shape_value(facevalues_u, q_point, i)
fe[i] += (δu ⋅ t) * dΓ
end
end
end
end
end
function symmetrize_lower!(K)
for i in 1:size(K,1)
for j in i+1:size(K,1)
K[i,j] = K[j,i]
end
end
end;
function solve(ν, interpolation_u, interpolation_p)
## material
Emod = 1.
Gmod = Emod / 2(1 + ν)
Kmod = Emod * ν / ((1+ν) * (1-2ν))
mp = LinearElasticity(Gmod, Kmod)
## grid, dofhandler, boundary condition
#n = 2
grid = create_cook_grid(50, 40)
dh = create_dofhandler(grid, interpolation_u, interpolation_p)
ch = create_bc(dh)
vtk_grid("cook_dgrid", dh) do vtk
vtk_partitioning(vtk, grid)
end
## cellvalues
cellvalues_u, cellvalues_p, facevalues_u = create_values(interpolation_u, interpolation_p)
## assembly and solve
K, f = doassemble(cellvalues_u, cellvalues_p, facevalues_u, grid, dh, ch, mp);
# apply!(K, f, ch)
u = cg(K, f);
## export
filename = "cook_distributed_" * (isa(interpolation_u, Lagrange{RefTriangle,1}) ? "linear" : "quadratic") *
"_linear"
vtk_grid(filename, dh) do vtkfile
vtk_point_data(vtkfile, dh, u)
vtk_partitioning(vtkfile, grid)
end
return u
end
linear = Lagrange{RefTriangle,1}()
quadratic = Lagrange{RefTriangle,2}()
# u1 = solve(0.4999999, linear^2, linear);
u2 = solve(0.4999999, quadratic^2, linear); |
23 tasks
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This implements the dof handler for fields on non-overlapping distributed grids.
TODO