Taking derivatives from mixed space

Hi,

I am trying to reproduce the dolfiny plasticity demo in dolfinx. I figured that I have to use mixed_element(), but I am having problems with taking the derivative. My MWE is:


import ufl
from mpi4py import MPI
from dolfinx import fem, mesh
import basix
from basix.ufl import mixed_element

domain = mesh.create_box(MPI.COMM_WORLD, [[0.0, 0.0, 0.0], [1.0, 1.0, 1.0]], [1, 1, 1], mesh.CellType.hexahedron)

Ue = basix.ufl.element("P", domain.basix_cell(), 1, shape=(domain.geometry.dim,))
He = basix.ufl.quadrature_element(domain.basix_cell(), value_shape=(), degree=1)
Te = basix.ufl.blocked_element(He, shape=(domain.geometry.dim, domain.geometry.dim), symmetry=True)

V_el = mixed_element([Ue, Te])
V = fem.functionspace(domain, V_el)

(u, P) = ufl.TrialFunctions(V)
(δu, δP) = ufl.TestFunctions(V)

F = ufl.Identity(3)+ ufl.grad(u)

δE_du = ufl.derivative(F, u, δu)
δE_dP = ufl.derivative(F, P, δP)

# dx = ufl.Measure("dx", domain=domain)
# form = (ufl.inner(δE_du, P) + ufl.inner(δE_du, P)  )* dx
# forms = ufl.extract_blocks(form)

which results in the following error message:

Traceback (most recent call last):
  File "/home/bjoern/examples/minimal_example_error2.py", line 22, in <module>
    δE_du = ufl.derivative(F, u, δu)
            ^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/ufl/formoperators.py", line 349, in derivative
    coefficients, arguments = _handle_derivative_arguments(form, coefficient, argument)
                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/ufl/formoperators.py", line 274, in _handle_derivative_arguments
    raise ValueError(f"Expecting an indexed coefficient, not {ufl_err_str(f)}")
ValueError: Expecting an indexed coefficient, not <Argument id=140389611234480>

The “working MWE” in dolfiny is:

#!/usr/bin/env python3
from mpi4py import MPI

import basix
import ufl
from dolfinx import fem, mesh

import dolfiny

domain = mesh.create_box(
    MPI.COMM_WORLD, [[0.0, 0.0, 0.0], [1.0, 1.0, 1.0]], [1, 1, 1], mesh.CellType.hexahedron
)


Ue = basix.ufl.element("P", domain.basix_cell(), 1, shape=(domain.geometry.dim,))
He = basix.ufl.quadrature_element(domain.basix_cell(), value_shape=(), degree=1)
Te = basix.ufl.blocked_element(He, shape=(domain.geometry.dim, domain.geometry.dim), symmetry=True)
Tf = fem.functionspace(domain, Te)
Uf = fem.functionspace(domain, Ue)


u = fem.Function(Uf)
δu = ufl.TestFunction(Uf)

P = fem.Function(Tf)
δP = ufl.TestFunction(Tf)

m, δm = [u, P], [δu, δP]

F = ufl.Identity(3) + ufl.grad(u)

δE = dolfiny.expression.derivative(F, m, δm)

dx = ufl.Measure("dx", domain=domain)

form = ufl.inner(δE, P) * dx
forms = dolfiny.function.extract_blocks(form, δm)

I am running Fenicx 0.9 on WSL Ubuntu / Windows. Many thanks in advance!

I think you need to use a dolfinx Function instead of a TrialFunction, the same way it is done in your dolfiny example.
This seems to be the equivalent of dolfiny that you are trying to make:

import ufl
from mpi4py import MPI
from dolfinx import fem, mesh
import basix
from basix.ufl import mixed_element

domain = mesh.create_box(
    MPI.COMM_WORLD,
    [[0.0, 0.0, 0.0], [1.0, 1.0, 1.0]],
    [1, 1, 1],
    mesh.CellType.hexahedron,
)

Ue = basix.ufl.element("P", domain.basix_cell(), 1, shape=(domain.geometry.dim,))
He = basix.ufl.quadrature_element(domain.basix_cell(), value_shape=(), degree=1)
Te = basix.ufl.blocked_element(
    He, shape=(domain.geometry.dim, domain.geometry.dim), symmetry=True
)

V_el = mixed_element([Ue, Te])
V = fem.functionspace(domain, V_el)

w = fem.Function(V)
u, P = ufl.split(w)
δw = ufl.TestFunction(V)

F = ufl.Identity(3) + ufl.grad(u)
δE = ufl.derivative(F, w, δw)

dx = ufl.Measure("dx", domain=domain)
form = (ufl.inner(δE, P)) * dx
forms = ufl.extract_blocks(form)
2 Likes

Thats it, thanks a lot for your help!

1 Like