Variable substitution of expression

Hi

I think I might have a rather trivial question but I couldn’t find an answer in the tutorials or the forum. It builds on the hyperelastic demo https://jorgensd.github.io/dolfinx-tutorial/chapter2/hyperelasticity.html:

msh = mesh.create_box(MPI.COMM_WORLD, [np.array([0.0, 0.0, 0.0]), np.array([L, H, H])], [10, 1, 1],
                      mesh.CellType.hexahedron)
V = fem.VectorFunctionSpace(domain, ("CG", 1))
wf = fem.Function(V)                                       # change of director
Af = fem.Constant(msh, PETSc.ScalarType((1.0, 0.0, 0.0)))  # undeformed director 
af = ufl.variable(Af + wf)                                 # deformed director
L4f = ufl.variable(ufl.inner(af, af))                      # director stretch
psi_f = c4f * (L4f**2 - 1.0)                               # stored strain energy
df = ufl.diff(psi_f, af)                                   # director stress

I would like to get an expression for the director stress, df, in the reference configuration where wf = 0, i.e. I would like to substitute variable, af, with the constant, Af, in the expression for df. Is this possible?

Thanks in advance.

I think you could do:

dF=ufl.replace(ufl.algorithms.apply_derivatives.apply_derivatives(ufl.algorithms.apply_algebra_lowering.apply_algebra_lowering(df
   ...: )), {af:Af})

Thanks a lot that seemed to have worked.

I can see that after the substitution of the variable, vector af, with the constant vector, Af, no variable remains, i.e. it is a constant expression. (Note: As L4f is not a variable itself but an expression of af, I changed L4f = ufl.variable(ufl.inner(af, af)) to L4f = ufl.inner(af, af)).

Now, as per definition Af = [1, 0, 0] and c4f = 1e6, this resulting constant expression should boil down to

df(af=Af) = 4 * c4f * Af = 4 * 1e6 * [ 1, 0, 0].

How, can I check this? See below what is printed on the terminal window using pdb:

initial expression:
df(af) = d/daf (psi_f) = d/d[var0(([f[3], f[4], f[5]]) + c_0)] (c_4 * (-1.0 + ((var0(([f[3], f[4], f[5]]) + c_0)) : (var0(([f[3], f[4], f[5]]) + c_0))) ** 2))

expanded expression:
df(af) = ufl.algorithms.apply_derivatives.apply_derivatives(ufl.algorithms.apply_algebra_lowering.apply_algebra_lowering(df))
{ A | A_{i_{22}} = ({ A | A_{i_{21}} = ({ A | A_{i_{20}} = 2 * (sum_{i_{17}} ({ A | A_{i_{19}} = (var0(([f[3], f[4], f[5]]) + c_0))[i_{17}] * (conj(({ A | A_{i_{18}} = I[i_{17}, i_{18}] })))[i_{19}] + ({ A | A_{i_{18}} = I[i_{17}, i_{18}] })[i_{19}] * (conj(((var0(([f[3], f[4], f[5]]) + c_0))[i_{17}]))) }) )[i_{20}] })[i_{21}] * (sum_{i_{17}} (var0(([f[3], f[4], f[5]]) + c_0))[i_{17}] * (conj(((var0(([f[3], f[4], f[5]]) + c_0))[i_{17}]))) ) })[i_{22}] * c_4 }

resulting expression after substituting Af for af:
df(af=Af) = ufl.replace(ufl.algorithms.apply_derivatives.apply_derivatives(ufl.algorithms.apply_algebra_lowering.apply_algebra_lowering(df)), {af:Af})
{ A | A_{i_{28}} = ({ A | A_{i_{27}} = ({ A | A_{i_{26}} = 2 * (sum_{i_{23}} ({ A | A_{i_{25}} = c_0[i_{23}] * (conj(({ A | A_{i_{24}} = I[i_{23}, i_{24}] })))[i_{25}] + ({ A | A_{i_{24}} = I[i_{23}, i_{24}] })[i_{25}] * (conj((c_0[i_{23}]))) }) )[i_{26}] })[i_{27}] * (sum_{i_{23}} c_0[i_{23}] * (conj((c_0[i_{23}]))) ) })[i_{28}] * c_4 }