|
| 1 | +using HyperFEM |
| 2 | +using HyperFEM: jacobian, solve! |
| 3 | +using HyperFEM.ComputationalModels.PostMetrics |
| 4 | +using HyperFEM.ComputationalModels.CartesianTags |
| 5 | +using Gridap, GridapGmsh, GridapSolvers, DrWatson |
| 6 | +using GridapSolvers.NonlinearSolvers |
| 7 | +using Gridap.FESpaces |
| 8 | + |
| 9 | +folder = joinpath(@__DIR__, "results", "ThermoViscoElectric") |
| 10 | +setupfolder(folder; remove=".vtu") |
| 11 | + |
| 12 | + |
| 13 | +long = 100 # m |
| 14 | +width = 100 # m |
| 15 | +thick = 1 # m |
| 16 | +domain = (0.0, long, 0.0, width, 0.0, thick) |
| 17 | +partition = (8, 2, 2) |
| 18 | +geometry = CartesianDiscreteModel(domain, partition) |
| 19 | +labels = get_face_labeling(geometry) |
| 20 | + |
| 21 | +add_tag_from_tags!(labels, "fixed", [CartesianTags.edgeX00 ;CartesianTags.edgeX10 ;CartesianTags.edge0Y0 ;CartesianTags.edge1Y0;CartesianTags.corner000; CartesianTags.corner100 ; CartesianTags.corner010 ; CartesianTags.corner110 ]) |
| 22 | +add_tag_from_tags!(labels, "bottom", CartesianTags.faceZ0) |
| 23 | +add_tag_from_tags!(labels, "top", CartesianTags.faceZ1) |
| 24 | + |
| 25 | + |
| 26 | +# Constitutive model |
| 27 | +hyper_elastic_model = NeoHookean3D(λ=10000.0, μ=2.0e5) |
| 28 | +viscous_branch_1 = ViscousIncompressible(IncompressibleNeoHookean3D(λ=0.0, μ=4.0e5); τ=2.0) |
| 29 | +viscous_branch_2 = ViscousIncompressible(IncompressibleNeoHookean3D(λ=0.0, μ=2.0e4); τ=10.0) |
| 30 | +visco_elastic_model = GeneralizedMaxwell(hyper_elastic_model, viscous_branch_1, viscous_branch_2) |
| 31 | +elec_model = IdealDielectric(ε=3.5416e-11) |
| 32 | +therm_model = ThermalModel(Cv=100.0, θr=293.15, α=1.1631, κ=10.0) |
| 33 | +cons_model = ThermoElectroMech_Bonet(therm_model, elec_model, visco_elastic_model) |
| 34 | +ku = Kinematics(Mechano, Solid) |
| 35 | +ke = Kinematics(Electro, Solid) |
| 36 | +kt = Kinematics(Thermo, Solid) |
| 37 | +F, _... = get_Kinematics(ku) |
| 38 | +E = get_Kinematics(ke) |
| 39 | + |
| 40 | +# Setup integration |
| 41 | +order = 1 |
| 42 | +degree = 2 * order |
| 43 | +Ω = Triangulation(geometry) |
| 44 | +dΩ = Measure(Ω, degree) |
| 45 | +t_end = 1.0 # s |
| 46 | +Δt = 0.005 # s |
| 47 | + |
| 48 | +# Dirichlet boundary conditions |
| 49 | +evolu(Λ) = 1.0 |
| 50 | +dir_u_tags = ["fixed"] |
| 51 | +dir_u_values = [[0.0, 0.0, 0.0]] |
| 52 | +dir_u_timesteps = [evolu] |
| 53 | +dirichlet_u = DirichletBC(dir_u_tags, dir_u_values, dir_u_timesteps) |
| 54 | + |
| 55 | +evolφ(Λ) = Λ |
| 56 | +dir_φ_tags = ["bottom", "top"] |
| 57 | +dir_φ_values = [0.0, 0.002] |
| 58 | +dir_φ_timesteps = [evolφ, evolφ] |
| 59 | +dirichlet_φ = DirichletBC(dir_φ_tags, dir_φ_values, dir_φ_timesteps) |
| 60 | + |
| 61 | +dirichlet_θ = NothingBC() |
| 62 | +dirichlet_bc = MultiFieldBC([dirichlet_u, dirichlet_φ, dirichlet_θ]) |
| 63 | + |
| 64 | +# Finite Elements |
| 65 | +reffeu = ReferenceFE(lagrangian, VectorValue{3,Float64}, order) |
| 66 | +reffeφ = ReferenceFE(lagrangian, Float64, order) |
| 67 | +reffeθ = ReferenceFE(lagrangian, Float64, order) |
| 68 | + |
| 69 | +# Test FE Spaces |
| 70 | +Vu = TestFESpace(geometry, reffeu, dirichlet_u, conformity=:H1) |
| 71 | +Vφ = TestFESpace(geometry, reffeφ, dirichlet_φ, conformity=:H1) |
| 72 | +Vθ = TestFESpace(geometry, reffeθ, dirichlet_θ, conformity=:H1) |
| 73 | + |
| 74 | +# Trial FE Spaces and state variables |
| 75 | +Uu = TrialFESpace(Vu, dirichlet_u) |
| 76 | +Uφ = TrialFESpace(Vφ, dirichlet_φ) |
| 77 | +Uθ = TrialFESpace(Vθ, dirichlet_θ) |
| 78 | +uh⁺ = FEFunction(Uu, zero_free_values(Uu)) |
| 79 | +φh⁺ = FEFunction(Uφ, zero_free_values(Uφ)) |
| 80 | +θh⁺ = FEFunction(Uθ, zero_free_values(Uθ)) |
| 81 | + |
| 82 | +Uu⁻ = TrialFESpace(Vu, dirichlet_u) |
| 83 | +Uφ⁻ = TrialFESpace(Vφ, dirichlet_φ) |
| 84 | +Uθ⁻ = TrialFESpace(Vθ, dirichlet_θ) |
| 85 | +uh⁻ = FEFunction(Uu⁻, zero_free_values(Uu⁻)) |
| 86 | +φh⁻ = FEFunction(Uφ⁻, zero_free_values(Uφ⁻)) |
| 87 | +θh⁻ = FEFunction(Uθ⁻, zero_free_values(Uθ⁻)) |
| 88 | + |
| 89 | +Uη⁻ = TrialFESpace(Vθ) |
| 90 | +ηh⁻ = FEFunction(Uη⁻, zero_free_values(Uη⁻)) |
| 91 | + |
| 92 | +UD⁻ = TrialFESpace(Vθ) |
| 93 | +Dh⁻ = FEFunction(UD⁻, zero_free_values(UD⁻)) |
| 94 | + |
| 95 | +Fh = F∘∇(uh⁺)' |
| 96 | +Fh⁻ = F∘∇(uh⁻)' |
| 97 | +A = initializeStateVariables(cons_model, dΩ) |
| 98 | + |
| 99 | +# ================================= |
| 100 | +# Weak forms: residual and jacobian |
| 101 | +# ================================= |
| 102 | + |
| 103 | +Ψ, ∂Ψ∂F, ∂Ψ∂E, ∂Ψ∂θ, ∂∂Ψ∂FF, ∂∂Ψ∂EE, ∂∂Ψ∂θθ, ∂∂Ψ∂FE, ∂∂Ψ∂Fθ, ∂∂Ψ∂Eθ, _ = cons_model(Δt=Δt) |
| 104 | +D, ∂D∂θ = Dissipation(cons_model, Δt) |
| 105 | +η(x...) = -∂Ψ∂θ(x...) |
| 106 | +∂η∂θ(x...) = -∂∂Ψ∂θθ(x...) |
| 107 | +κ = cons_model.thermo.κ |
| 108 | + |
| 109 | +Mechano_coupling(Λ) = uh⁻ + (uh⁺ - uh⁻) * Λ |
| 110 | +Electro_coupling(Λ) = φh⁻ + (φh⁺ - φh⁻) * Λ |
| 111 | +Thermo_coupling(Λ) = θh⁻ + (θh⁺ - θh⁻) * Λ |
| 112 | + |
| 113 | +# Electro |
| 114 | +res_elec(Λ) = (φ, vφ) -> residual(cons_model, Electro, (ku, ke, kt), (Mechano_coupling(Λ), φ, Thermo_coupling(Λ)), vφ, dΩ, 0.0, Fh⁻, A...; Δt=Δt) |
| 115 | +jac_elec(Λ) = (φ, dφ, vφ) -> jacobian(cons_model, Electro, (ku, ke, kt), (Mechano_coupling(Λ), φ, Thermo_coupling(Λ)), dφ, vφ, dΩ, 0.0, Fh⁻, A...; Δt=Δt) |
| 116 | + |
| 117 | +# Mechano |
| 118 | +res_mec(Λ) = (u, v) -> residual(cons_model, Mechano, (ku, ke, kt), (u, Electro_coupling(Λ), Thermo_coupling(Λ)), v, dΩ, 0.0, Fh⁻, A...; Δt=Δt) |
| 119 | +jac_mec(Λ) = (u, du, v) -> jacobian(cons_model, Mechano, (ku, ke, kt), (u, Electro_coupling(Λ), Thermo_coupling(Λ)), du, v, dΩ, 0.0, Fh⁻, A...; Δt=Δt) |
| 120 | + |
| 121 | +# Thermo |
| 122 | +res_therm(Λ) = (θ, vθ) -> begin |
| 123 | + uhᵞ = Mechano_coupling(Λ) |
| 124 | + φhᵞ = Electro_coupling(Λ) |
| 125 | + ∫( 1/Δt*(θ*η∘(F∘∇(uhᵞ), E∘∇(φhᵞ), θ, Fh⁻, A...) - θh⁻*ηh⁻)*vθ + |
| 126 | + -1/Δt*0.5*(η∘(F∘∇(uhᵞ), E∘∇(φhᵞ), θ, Fh⁻, A...) + ηh⁻)*(θ - θh⁻)*vθ + |
| 127 | + -0.5*(D∘(F∘∇(uhᵞ), E∘∇(φhᵞ), θ, Fh⁻, A...) + Dh⁻)*vθ + |
| 128 | + 0.5*(κ * ∇(θ)·∇(vθ)) + 0.5*(κ * ∇(θh⁻)·∇(vθ)) |
| 129 | + )dΩ |
| 130 | +end |
| 131 | +jac_therm(Λ) = (θ, dθ, vθ) -> begin |
| 132 | + uhᵞ = Mechano_coupling(Λ) |
| 133 | + φhᵞ = Electro_coupling(Λ) |
| 134 | + ∫( 1/Δt*(η∘(F∘∇(uhᵞ), E∘∇(φhᵞ), θ, Fh⁻, A...) + θ*∂η∂θ∘(F∘∇(uhᵞ), E∘∇(φhᵞ), θ, Fh⁻, A...))*dθ*vθ + |
| 135 | + -1/Δt*0.5*(∂η∂θ∘(F∘∇(uhᵞ), E∘∇(φhᵞ), θ, Fh⁻, A...)*(θ - θh⁻) + (η∘(F∘∇(uhᵞ), E∘∇(φhᵞ), θ, Fh⁻, A...) + ηh⁻))*dθ*vθ + |
| 136 | + -0.5*∂D∂θ∘(F∘∇(uhᵞ), E∘∇(φhᵞ), θ, Fh⁻, A...)*dθ*vθ + |
| 137 | + 0.5*κ*∇(dθ)·∇(vθ) |
| 138 | + )dΩ |
| 139 | +end |
| 140 | + |
| 141 | +# nonlinear solver electro |
| 142 | +ls = LUSolver() |
| 143 | +nls = NewtonSolver(ls; maxiter=20, atol=1e-6, rtol=1e-6, verbose=true) |
| 144 | +comp_model_elec = StaticNonlinearModel(res_elec, jac_elec, Uφ, Vφ, dirichlet_φ; nls=nls, xh=φh⁺, xh⁻=φh⁻) |
| 145 | + |
| 146 | +# nonlinear solver mechano |
| 147 | +comp_model_mec = StaticNonlinearModel(res_mec, jac_mec, Uu, Vu, dirichlet_u; nls=nls, xh=uh⁺, xh⁻=uh⁻) |
| 148 | + |
| 149 | +# nonlinear solver thermo |
| 150 | +comp_model_mec = StaticNonlinearModel(res_therm, jac_therm, Uθ, Vθ, dirichlet_θ; nls=nls, xh=θh⁺, xh⁻=θh⁻) |
| 151 | + |
| 152 | +# nonlinear staggered model |
| 153 | +comp_model = StaggeredModel((comp_model_elec, comp_model_mec), (φh⁺, uh⁺, θh⁺), (φh⁻, uh⁻, θh⁻)) |
| 154 | + |
| 155 | +count = Ref{Int}(0) |
| 156 | + |
| 157 | +# Postprocessor to save results |
| 158 | +function driverpost(post) |
| 159 | + step = post.iter |
| 160 | + pvd = post.cachevtk[3] |
| 161 | + filePath = post.cachevtk[2] |
| 162 | + count[] += 1 |
| 163 | + |
| 164 | + push!(uz, component_LInf(uh⁺, :z, Ω)) |
| 165 | + if post.cachevtk[1] |
| 166 | + pvd[step] = createvtk(Ω, filePath * "/TIME_$(count[])" * ".vtu", cellfields=["u" => uh⁺, "φ" => φh⁺]) |
| 167 | + end |
| 168 | + updateStateVariables!(A, cons_model, Δt, F∘∇(uh⁺), F∘∇(uh⁻)) |
| 169 | +end |
| 170 | + |
| 171 | +post_model = PostProcessor(comp_model_mec, driverpost; is_vtk=true, filepath=folder) |
| 172 | + |
| 173 | +args_elec = Dict(:stepping => (nsteps=1, maxbisec=1)) |
| 174 | +args_mec = Dict(:stepping => (nsteps=1, maxbisec=1)) |
| 175 | +args_therm = Dict(:stepping => (nsteps=1, maxbisec=1), :post=>post_model) |
| 176 | +args = (args_elec, args_mec, args_therm) |
| 177 | + |
| 178 | +t = [0:Δt:t_end-Δt...] |
| 179 | +uz = Float64[] |
| 180 | +nsteps = t_end / Δt |
| 181 | +solve!(comp_model; stepping=(nsteps=nsteps, nsubsteps=1, maxbisec=1), kargsolve=args) |
| 182 | + |
| 183 | +plot(t, uz) |
| 184 | + |
| 185 | +@assert uz[end] ≈ 1.39059921e-5 |
| 186 | +@assert norm(uz) ≈ 8.79961900e-5 |
0 commit comments