Hi,
I’m in the process of solving a Landau theory model concerning a crystal where strain and electric polarization are coupled. I’m trying to minimize the total free energy given by:
F = Fl(P, α) + Fc(ε, C) + Fq(P, ε, q) + Fg(∇P, G)
function Fl(P::JuAFEM.Vec{3}, α)
P² = P.^2
P⁴ = P.^4
return α[1, 1, 1] * sum(P²)
+ α[1, 1, 1] * sum(P⁴)
+ α[1, 1, 2] * sum(P.^6)
+ α[1, 2, 1] * (P²[1]*P²[2] + P²[2]*P²[3] + P²[1]*P²[3])
+ α[1, 1, 2] * (P⁴[1]*(P²[2] + P²[3]) + P⁴[2]*(P²[1] + P²[3]) + P⁴[3]*(P²[1] + P²[2]))
+ α[1, 2, 3] * prod(P²)
end
Fc(ε::Tensor{2, 3}, C::Tensor{4, 3}) = 0.5ε ⊡ C ⊡ ɛ
Fq(P::Vec{3}, ε::Tensor{2, 3}, q::Tensor{4, 3}) = -P ⋅ (ε ⊡ q) ⋅ P
Fg(∇P::Tensor{2, 3}, G::Tensor{4, 3}) = 0.5∇P ⊡ G ⊡ ∇P
ε
is the gradient of the displacement field in all directions, P
is the polarization, C
gives the penalty for creating strain, q
the coupling between strain and polarization P
, G
the Ginzburg coefficients for spatial variation of P
and α
the different Landau components for free energy from P
.
Since we are dealing with 6 variables u_1,2,3, P_1,2,3
in 2D, on a mesh of size > 2000x600
, throwing it into Optim.jl
and brute force optimize it is pretty much impossible. Next option is to analytically minimize the free energy with regards to the two fields (u
, P
) and solve the equations on a FEM model. This results in a system of nonlinear equations.
Now we come to the questions. Looking at the examples of JuAFEM
I can almost understand how to solve a nonlinear model, but since I’m not really an expert on FEM I don’t fully understand how to connect JuAFEM
to a nonlinear solver like NLsolve
, is this possible? And if so, how does one go about it? The second question is more about how to use ForwardDiff
, can I exploit this package to not have to analytically compute the derivatives of F
, which result in the nonlinear equations? This would be a great aid, because the derivation is pretty cumbersome and prone to errors. The main thing I don’t fully understand is if it’s possible to derive the Fq
equation, which couples the two fields, through the gradient ε
. From what I read, ForwardDiff
only works when a function can be called with one Vector
input or basically 1 parameter, can I use a tuple to derive this? Will that impact performance?
Is there another suite of packages I should have a look at, or that encompass everything I want to do?
Thanks in advance for any comments/ help!
Cheers