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

[Draft] Hyperelasticity support (based on work by Joseph Beckett) #184

Open
wants to merge 15 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
8 changes: 7 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,10 @@ Manifest.toml

*/__pycache__

examples/benchmark/iterations
examples/benchmark/iterations

*.ipynb
/*.jl
*.vtu
*.png
*.zip
5 changes: 5 additions & 0 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4"
ColorSchemes = "35d6a980-a343-548e-a6ea-1d62b119f2f4"
Distributions = "31c24e10-a181-5473-b8eb-7969acd0382f"
Einsum = "b7d42ee7-0b51-5a75-98ca-779d3107e4c0"
FFMPEG = "c87230d0-a227-11e9-1b43-d7ebe4e7570a"
Copy link
Member Author

Choose a reason for hiding this comment

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

This is not used I think.

Ferrite = "c061ca5d-56c9-439f-9c0e-210fe06d3992"
FileIO = "5789e2e9-d7fb-5bc7-8068-2c6fae9b9549"
Flux = "587475ba-b771-5e3f-ad9e-33799f191a9c"
Expand All @@ -28,6 +29,8 @@ NonconvexPercival = "4296f080-e499-44ba-a02c-ae40015c44d5"
NonconvexSemidefinite = "9e21ff56-eb25-42d3-b86f-5b0612f555e7"
Parameters = "d96e819e-fc66-5662-9728-84c9c7592b0a"
Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f"
PlotlyJS = "f0f68f2c-4968-5e81-91da-67840de0976a"
Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
Comment on lines +32 to +33
Copy link
Member Author

Choose a reason for hiding this comment

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

Let's consider using Makie if possible since we already have an extension for Makie.

Preconditioners = "af69fa37-3177-5a40-98ee-561f696e4fcd"
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
Reexport = "189a3867-3050-52da-a836-e630ba90ab69"
Expand All @@ -36,7 +39,9 @@ Setfield = "efcf1570-3423-57d1-acb7-fd33fddbac46"
SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"
StaticArrays = "90137ffa-7385-5640-81b9-e52037218182"
Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"
StatsBase = "2913bbd2-ae8a-5f71-8c99-4fb6c76f3a91"
Copy link
Member Author

Choose a reason for hiding this comment

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

where is this used?

StatsFuns = "4c63d2b9-4356-54db-8cca-17b64c39e42c"
Symbolics = "0c5d862f-8b57-4792-8d23-62f2024744c7"
Tensors = "48a634ad-e948-5137-8d70-aa71f2a747f4"
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
TimerOutputs = "a759f4b9-e2f1-59dc-863e-4aeb61b1ea8f"
Expand Down
4 changes: 4 additions & 0 deletions src/FEA/FEA.jl
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,16 @@ using Parameters: @unpack

export AbstractFEASolver,
AbstractDisplacementSolver,
AbstractHyperelasticSolver,
DirectDisplacementSolver,
PCGDisplacementSolver,
StaticMatrixFreeDisplacementSolver,
HyperelasticDisplacementSolver,
Displacement,
Direct,
CG,
MatrixFree,
Hyperelastic,
FEASolver,
Assembly,
DefaultCriteria,
Expand All @@ -34,6 +37,7 @@ include("direct_displacement_solver.jl")
include("assembly_cg_displacement_solvers.jl")
include("matrix_free_cg_displacement_solvers.jl")
include("matrix_free_apply_bcs.jl")
include("iterative_hyperelastic_solver.jl")
include("simulate.jl")
include("solvers_api.jl")

Expand Down
242 changes: 242 additions & 0 deletions src/FEA/iterative_hyperelastic_solver.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,242 @@
abstract type AbstractHyperelasticSolver <: AbstractFEASolver end

mutable struct HyperelasticCompressibleDisplacementSolver{
T,
dim,
TP1<:AbstractPenalty{T},
TP2<:StiffnessTopOptProblem{dim,T},
TG<:GlobalFEAInfo_hyperelastic{T},
TE<:ElementFEAInfo_hyperelastic{dim,T},
Tu<:AbstractVector{T},
TF<:AbstractVector{<:AbstractMatrix{T}},
} <: AbstractHyperelasticSolver
mp
problem::TP2
globalinfo::TG
elementinfo::TE
u::Tu # JGB: u --> u0
F::TF
vars::Tu
penalty::TP1
prev_penalty::TP1
xmin::T
tsteps::Int
ntsteps::Int
end
mutable struct HyperelasticNearlyIncompressibleDisplacementSolver{
T,
dim,
TP1<:AbstractPenalty{T},
TP2<:StiffnessTopOptProblem{dim,T},
TG<:GlobalFEAInfo_hyperelastic{T},
TE<:ElementFEAInfo_hyperelastic{dim,T},
Tu<:AbstractVector{T},
TF<:AbstractVector{<:AbstractMatrix{T}},
} <: AbstractHyperelasticSolver
mp
problem::TP2
globalinfo::TG
elementinfo::TE
u::Tu # JGB: u --> u0
F::TF
vars::Tu
penalty::TP1
prev_penalty::TP1
xmin::T
tsteps::Int
ntsteps::Int
end
function Base.show(::IO, ::MIME{Symbol("text/plain")}, x::HyperelasticCompressibleDisplacementSolver)
return println("TopOpt compressible hyperelastic solver")
end
function Base.show(::IO, ::MIME{Symbol("text/plain")}, x::HyperelasticNearlyIncompressibleDisplacementSolver)
return println("TopOpt nearly-incompressible hyperelastic solver")
end
function HyperelasticDisplacementSolver(
mp, # JGB: add type later
sp::StiffnessTopOptProblem{dim,T}; # JGB: eventually add ::HyperelaticParam type
xmin=T(1)/1000,
penalty=PowerPenalty{T}(1),
prev_penalty=deepcopy(penalty),
quad_order=default_quad_order(sp),
tstep = 1,
ntsteps = 20,
nearlyincompressible=false
) where {dim,T}
u = zeros(T, ndofs(sp.ch.dh))
ts0 = tstep/ntsteps
update!(sp.ch,ts0) # set initial time-step (adjusts dirichlet bcs)
apply!(u,sp.ch) # apply dbc for initial guess
elementinfo = ElementFEAInfo_hyperelastic(mp, sp, u, quad_order, Val{:Static}, nearlyincompressible; ts = ts0) # JGB: add u
F = [zeros(typeof(elementinfo.Fes[1])) for _ in 1:getncells(sp.ch.dh.grid)]
globalinfo = GlobalFEAInfo_hyperelastic(sp) # JGB: small issue this leads to symmetric K initialization
#u = zeros(T, ndofs(sp.ch.dh)) # JGB
vars = fill(one(T), getncells(sp.ch.dh.grid) - sum(sp.black) - sum(sp.white))
varind = sp.varind
return nearlyincompressible ?
HyperelasticNearlyIncompressibleDisplacementSolver(mp, sp, globalinfo, elementinfo, u, F, vars, penalty, prev_penalty, xmin, tstep, ntsteps) :
HyperelasticCompressibleDisplacementSolver(mp, sp, globalinfo, elementinfo, u, F, vars, penalty, prev_penalty, xmin, tstep, ntsteps)
#if nearlyincompressible
# return HyperelasticNearlyIncompressibleDisplacementSolver(mp, sp, globalinfo, elementinfo, u, F, vars, penalty, prev_penalty, xmin, tstep, ntsteps)
#else
# return HyperelasticCompressibleDisplacementSolver(mp, sp, globalinfo, elementinfo, u, F, vars, penalty, prev_penalty, xmin, tstep, ntsteps)
#end
end
function (s::HyperelasticCompressibleDisplacementSolver{T})(
::Type{Val{safe}}=Val{false},
::Type{newT}=T;
assemble_f=true,
kwargs...,
) where {T,safe,newT}
elementinfo = s.elementinfo
globalinfo = s.globalinfo
dh = s.problem.ch.dh
ch = s.problem.ch

_ndofs = ndofs(dh)
un = zeros(_ndofs) # previous solution vector

NEWTON_TOL = 1e-8
NEWTON_MAXITER = 30
CG_MAXITER = 1000
TS_MAXITER_ABS = 200
TS_MAXITER_REL = 10

function HyperelasticSolverCore(ts)
update!(ch,ts)
apply!(un,ch)
#println(maximum(un))
u = zeros(_ndofs)
Δu = zeros(_ndofs)
ΔΔu = zeros(_ndofs)

newton_itr = 0
normg = zeros(NEWTON_MAXITER)
while true; newton_itr += 1
u .= un .+ Δu # current trial solution
# Compute residual norm for current guess
elementinfo = ElementFEAInfo_hyperelastic(s.mp, s.problem, u, default_quad_order(s.problem), Val{:Static}; ts=ts)
assemble_hyperelastic!(globalinfo,s.problem,elementinfo,s.vars,getpenalty(s),s.xmin,assemble_f=assemble_f)
apply_zero!(globalinfo.K,globalinfo.g,ch)
normg[newton_itr] = norm(globalinfo.g)
println("Tstep: $ts / 1]. Iteration: $newton_itr. normg is equal to " * string(normg[newton_itr]))
# Check for convergence
if normg[newton_itr] < NEWTON_TOL
break
elseif newton_itr > 1 && normg[newton_itr] > normg[newton_itr-1]
error("Newton iteration resulted in an increase in normg, aborting")
elseif newton_itr > NEWTON_MAXITER
error("Reached maximum Newton iterations, aborting")
end
# Compute increment using conjugate gradients
IterativeSolvers.cg!(ΔΔu, globalinfo.K, globalinfo.g; maxiter=CG_MAXITER)
apply_zero!(ΔΔu, ch)
Δu .-= ΔΔu
end
un = u
end

inc_up = 1.1
inc_down = 0.5
delay_up = 5
delay_down = 5
inc_delay = 10 # integer
ntsteps = s.ntsteps
iter_ts = 0
ts = 0
Δts0 = 1/ntsteps
Δts = Δts0
conv = zeros(TS_MAXITER_ABS)
#for tstep ∈ 1:ntsteps
# ts = tstep/ntsteps
#end
while ts < 1
iter_ts += 1
ts += Δts
if ts > 1
Δts = 1 - ts
ts = 1
elseif iter_ts > TS_MAXITER_REL && sum(conv[iter_ts-(TS_MAXITER_REL):iter_ts-1]) == 0
error("Reached maximum number of successive failed ts iterations ($TS_MAXITER_REL), aborting")
elseif iter_ts > TS_MAXITER_ABS
error("Reached maximum number of allowed ts iterations ($TS_MAXITER_ABS), aborting")
end
try
HyperelasticSolverCore(ts)
conv[iter_ts] = 1
if sum(conv[1:iter_ts]) == iter_ts || (iter_ts - findlast(x -> x == 0, conv[1:iter_ts-1])) > delay_up + 1 # increase Δts if it's never failed or if it's been 'inc_delay' or more successful iterations since last divergence
Δts *= inc_up
end
catch
conv[iter_ts] = 0
ts -= Δts # revert to previous successful ts
println("REMINDER TO CHECK THIS!!")
if any(x -> x == 1, conv) && (iter_ts - findlast(x -> x == 1, conv[1:iter_ts-1])) < delay_down # decrease Δts a little if it's been 'down_delay' or less failures in a row
Δts *= 1/inc_up
else
Δts *= inc_down # otherwise make a big decrease in Δts
end
end
println("ts = $ts. Δts/Δts0 = $(Δts/Δts0)")
end
s.u .= un
s.F .= elementinfo.Fes
return nothing
end

function (s::HyperelasticNearlyIncompressibleDisplacementSolver{T})(
::Type{Val{safe}}=Val{false},
::Type{newT}=T;
assemble_f=true,
reuse_fact=false,
kwargs...,
) where {T,safe,newT}
elementinfo = s.elementinfo
globalinfo = s.globalinfo
dh = s.problem.ch.dh
ch = s.problem.ch

_ndofs = ndofs(dh)
un = zeros(_ndofs) # previous solution vector

NEWTON_TOL = 1e-8
NEWTON_MAXITER = 30
CG_MAXITER = 1000

ntsteps = s.ntsteps
for tstep ∈ 1:ntsteps
ts = tstep/ntsteps
update!(ch,ts)
apply!(un,ch)
println(maximum(un))
u = zeros(_ndofs)
Δu = zeros(_ndofs)
ΔΔu = zeros(_ndofs)

newton_itr = 0
normg = zeros(NEWTON_MAXITER)
while true; newton_itr += 1
u .= un .+ Δu # current trial solution
# Compute residual norm for current guess
elementinfo = ElementFEAInfo_hyperelastic(s.mp, s.problem, u, default_quad_order(s.problem), Val{:Static}; ts=ts)
assemble_hyperelastic!(globalinfo,s.problem,elementinfo,s.vars,getpenalty(s),s.xmin,assemble_f=assemble_f)
apply_zero!(globalinfo.K,globalinfo.g,ch)
normg[newton_itr] = norm(globalinfo.g)
println("Tstep: $tstep / $ntsteps. Iteration: $newton_itr. normg is equal to " * string(normg[newton_itr]))
# Check for convergence
if normg[newton_itr] < NEWTON_TOL
break
elseif newton_itr > NEWTON_MAXITER
error("Reached maximum Newton iterations, aborting")
end
# Compute increment using conjugate gradients
IterativeSolvers.cg!(ΔΔu, globalinfo.K, globalinfo.g; maxiter=CG_MAXITER)
apply_zero!(ΔΔu, ch)
Δu .-= ΔΔu
end
un = u
end
s.u .= un
s.F .= elementinfo.Fes
return nothing
end
5 changes: 5 additions & 0 deletions src/FEA/solvers_api.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ abstract type SolverSubtype end

struct Direct <: SolverType end
struct CG <: SolverType end
struct Hyperelastic <: SolverType end

struct MatrixFree <: SolverSubtype end
struct Assembly <: SolverSubtype end
Expand Down Expand Up @@ -38,6 +39,10 @@ function FEASolver(::Type{CG}, ::Type{Assembly}, problem; kwargs...)
return PCGDisplacementSolver(problem; kwargs...)
end

function FEASolver(::Type{Hyperelastic}, mp, problem; kwargs...) # JGB: add place to add NeoHookean <: :HyperelasticParam
return HyperelasticDisplacementSolver(mp, problem; kwargs...)
end

function default_quad_order(problem)
if TopOptProblems.getdim(problem) == 2 &&
TopOptProblems.nnodespercell(problem) in (3, 6) ||
Expand Down
19 changes: 18 additions & 1 deletion src/Functions/Functions.jl
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ using SparseArrays, Statistics, ChainRulesCore, Zygote
using Nonconvex: Nonconvex
using Flux
using AbstractDifferentiation: AbstractDifferentiation
using StatsBase, Statistics
using Symbolics
using Plots:heatmap
const AD = AbstractDifferentiation

export Volume,
Expand Down Expand Up @@ -45,7 +48,17 @@ export Volume,
MaterialInterpolation,
MultiMaterialVariables,
element_densities,
tounit
tounit,
DefGradTensor,
ElementDefGradTensor,
FToK123,
orth_decomp,
sensitivityFieldFncs,
sensitivityPVW,
Entropy_Calc,
Entropy,
SMu_gen,
SAlpha_gen

const to = TimerOutput()

Expand All @@ -68,6 +81,10 @@ include("assemble_K.jl")
include("element_ksigma.jl")
include("element_k.jl")

# Goodness related
include("defgrad.jl")
include("goodness.jl")

# TODO no rrules yet
include("truss_stress.jl")

Expand Down
Loading
Loading