Trial and test functions of mixed Nedelec and Lagrange element

I’m trying to port an old Dolfin program based on this paper to DolfinX.
System I’m trying to solve contains \vec{E} vector split into \vec{E}_\perp^\Re, \vec{E}_\perp^\Im, E_z^\Re and E_z^\Im parts. Therefore, to solve the problem I need a pair of vector test functions \vec{w}^\Re and \vec{w}^\Im and a pair of scalar test functions v^\Re and v^\Im.
The old code contained the following definition of test and trial functions for this problem:

Vtr = FiniteElement("Nedelec 1st kind H(curl)", mesh.ufl_cell(), 1)
Vlr = FiniteElement("Lagrange", mesh.ufl_cell(), 1)
Vli = Vlr
Vti = Vtr
V = FunctionSpace(mesh, MixedElement([Vtr, Vti, Vlr, Vli]))
(uvr,uvi,usr,usi) = TrialFunctions(V)
(vvr,vvi,vsr,vsi) = TestFunctions(V)

This snippet is a MWE for DolfinX:

import dolfinx
import numpy as np
import ufl
from mpi4py import MPI

mesh = dolfinx.UnitSquareMesh(MPI.COMM_WORLD, 10, 10)

Hcurl = ufl.FiniteElement("Nedelec 1st kind H(curl)", mesh.ufl_cell(), 1)
H1 = ufl.FiniteElement("Lagrange", mesh.ufl_cell(), 1)

V = dolfinx.FunctionSpace(mesh, ufl.MixedElement(Hcurl, Hcurl, H1, H1))
u = ufl.TrialFunction(V)
v = ufl.TestFunction(V)
print(f"Trial function shape {u.ufl_shape}")
print(f"Test function shape {v.ufl_shape}")

Shape of trial and test functions u and v in this example is (6,). How do I create 2 vector and 2 scalar trial and test functions for this problem?

Could I use the following code?

eperp_re = ufl.as_vector((u[0], u[1]))
eperp_im = ufl.as_vector((u[2], u[3]))
ez_re = u[4]
ez_im = u[5]
wre = ufl.as_vector((v[0], v[1]))
wim = ufl.as_vector((v[2], v[3]))
vre = v[4]
vim = v[5]

The code you proposed looks okay, but I think you should also be able to use ufl.TrialFunctions(V) and ufl.TestFunctions(V), as you did with old DOLFIN. (Based on the notation, you might also want to look into DOLFIN-X’s support for complex numbers.)

1 Like

Thanks for the reply! Using ufl.TrialFunction(V) and ufl.TestFunction(V) raises too many values to unpack error.

you might also want to look into DOLFIN-X’s support for complex numbers

I will definitely try it after porting the real number version and compare the results.

As @kamensky said, you need to use

not

The following code works with the latest dolfinx from docker (docker run -ti -e DISPLAY=$DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix -v $(pwd):/root/shared -w /root/shared --rm dolfinx/dolfinx)

import dolfinx
import numpy as np
import ufl
from mpi4py import MPI

mesh = dolfinx.UnitSquareMesh(MPI.COMM_WORLD, 10, 10)

Hcurl = ufl.FiniteElement("Nedelec 1st kind H(curl)", mesh.ufl_cell(), 1)
H1 = ufl.FiniteElement("Lagrange", mesh.ufl_cell(), 1)

V = dolfinx.FunctionSpace(mesh, ufl.MixedElement(Hcurl, Hcurl, H1, H1))

(uvr,uvi,usr,usi) = ufl.TrialFunctions(V)
(vvr,vvi,vsr,vsi) = ufl.TestFunctions(V)

print(uvr, uvi, usr, usi)
1 Like

Yes, after reading the docs it’s obvious:

ufl.TestFunction = TestFunction(function_space, part=None)
UFL value: Create a test function argument to a form.

ufl.TestFunctions = TestFunctions(function_space)
UFL value: Create a TestFunction in a mixed space, and return a
tuple with the function components corresponding to the subelements.

Thanks again!