 # Problem when combining test and trial functions from different spaces

Hi all,

I am trying to solve a set of equations that involve velocity, pressure and temperature.
The finite element spaces that I am using for the different variables are the following:

# Finite element spaces

import ufl
v_cg2 = ufl.VectorElement(“CG”, mesh.ufl_cell(), 2)
p_cg1 = ufl.FiniteElement(“CG”, mesh.ufl_cell(), 1)
T_cg2 = ufl.FiniteElement(“CG”, mesh.ufl_cell(), 2)
V = dolfinx.FunctionSpace(mesh, v_cg2) # Velocity function space
Q = dolfinx.FunctionSpace(mesh, p_cg1) # Pressure function space
W = dolfinx.FunctionSpace(mesh, T_cg2) # Temperature function space

# Trial and test functions

u = ufl.TrialFunction(V) # Velocity (trial)
v = ufl.TestFunction(V) # Velocity (test)
p = ufl.TrialFunction(Q) # Pressure (trial)
q = ufl.TestFunction(Q) # Pressure (test)
T = ufl.TrialFunction(W) # Temperature (trial)
w = ufl.TestFunction(W) # Temperature (test)

The problem is that the equations are coupled, so I need to solve them simultaneously. However, I am getting errors when I try to build the bilinear form, since I need to combine test and trial functions from different element spaces.
For example, I need to compute the following term:

L1 = inner(q,(gamma*p-T))*dx
A = dolfinx.fem.assemble_matrix(L1)
A.assemble()

which gives me the following error:

Found different Arguments with same number and part.
Did you combine test or trial functions from different spaces?
The Arguments found are:
v_1
v_0
v_1
ERROR:UFL:Found different Arguments with same number and part.
Did you combine test or trial functions from different spaces?
The Arguments found are:
v_1
v_0
v_1
Traceback (most recent call last):
File “/root/dolfinX/Test.py”, line 110, in
A = dolfinx.fem.assemble_matrix(L1)
File “/usr/lib/python3.9/functools.py”, line 877, in wrapper
return dispatch(args.__class__)(*args, **kw)
File “/usr/local/dolfinx-real/lib/python3.8/dist-packages/dolfinx/fem/assemble.py”, line 283, in assemble_matrix
A = cpp.fem.create_matrix(_create_cpp_form(a))
File “/usr/local/dolfinx-real/lib/python3.8/dist-packages/dolfinx/fem/assemble.py”, line 35, in create_cpp_form
return Form(form).cpp_object
File “/usr/local/dolfinx-real/lib/python3.8/dist-packages/dolfinx/fem/form.py”, line 56, in __init

self._ufc_form, module, self._code = jit.ffcx_jit(
File “/usr/local/dolfinx-real/lib/python3.8/dist-packages/dolfinx/jit.py”, line 54, in mpi_jit
return local_jit(*args, **kwargs)
File “/usr/local/dolfinx-real/lib/python3.8/dist-packages/dolfinx/jit.py”, line 204, in ffcx_jit
r = ffcx.codegeneration.jit.compile_forms([ufl_object], parameters=p_ffcx, **p_jit)
File “/usr/local/lib/python3.9/dist-packages/ffcx/codegeneration/jit.py”, line 145, in compile_forms
ffcx.naming.compute_signature(forms, _compute_parameter_signature(p)
File “/usr/local/lib/python3.9/dist-packages/ffcx/naming.py”, line 24, in compute_signature
object_signature += ufl_object.signature()
File “/usr/local/lib/python3.9/dist-packages/ufl/form.py”, line 243, in signature
self._compute_signature()
File “/usr/local/lib/python3.9/dist-packages/ufl/form.py”, line 487, in _compute_signature
self._compute_renumbering())
File “/usr/local/lib/python3.9/dist-packages/ufl/form.py”, line 460, in _compute_renumbering
cn = self.coefficient_numbering()
File “/usr/local/lib/python3.9/dist-packages/ufl/form.py”, line 234, in coefficient_numbering
self._analyze_form_arguments()
File “/usr/local/lib/python3.9/dist-packages/ufl/form.py”, line 447, in _analyze_form_arguments
arguments, coefficients = extract_arguments_and_coefficients(self)
File “/usr/local/lib/python3.9/dist-packages/ufl/algorithms/analysis.py”, line 127, in extract_arguments_and_coefficients
error(msg)
File “/usr/local/lib/python3.9/dist-packages/ufl/log.py”, line 158, in error
raise self._exception_type(self._format_raw(*message))
ufl.log.UFLException: Found different Arguments with same number and part.
Did you combine test or trial functions from different spaces?
The Arguments found are:
v_1
v_0
v_1

What I understand then is that I cannot combine test and trial functions from different spaces. Therefore, I defined a mixed finite element space to try to fix this error:

# Mixed finite element space

import ufl
v_cg2 = ufl.VectorElement(“CG”, mesh.ufl_cell(), 2)
p_cg1 = ufl.FiniteElement(“CG”, mesh.ufl_cell(), 1)
T_cg2 = ufl.FiniteElement(“CG”, mesh.ufl_cell(), 2)
mel = ufl.MixedElement([v_cg2, p_cg1, T_cg2])
Y = dolfinx.FunctionSpace(mesh, mel) # Mixed function space

and redefined the trial and test functions as follows:

# Trial and test functions

u = ufl.TrialFunction(Y) # Velocity (trial)
v = ufl.TestFunction(Y) # Velocity (test)
p = ufl.TrialFunction(Y) # Pressure (trial)
q = ufl.TestFunction(Y) # Pressure (test)
T = ufl.TrialFunction(Y) # Temperature (trial)
w = ufl.TestFunction(Y) # Temperature (test)

This approach fixes the previous error, but now I am getting another one when I try to compute another term:

L2 = inner(w,div(u))*dx
A = dolfinx.fem.assemble_matrix(L2)
A.assemble()

The error now is:

Shapes do not match: <Argument id=140363992421472> and <Div id=140364133793920>.
ERROR:UFL:Shapes do not match: <Argument id=140363992421472> and <Div id=140364133793920>.
Traceback (most recent call last):
File “/root/dolfinX/Test.py”, line 105, in <module>
L2 = inner(w,div(u))*dx
File “/usr/local/lib/python3.9/dist-packages/ufl/operators.py”, line 158, in inner
return Inner(a, b)
File “/usr/local/lib/python3.9/dist-packages/ufl/tensoralgebra.py”, line 147, in __new__
error(“Shapes do not match: %s and %s.” % (ufl_err_str(a), ufl_err_str(b)))
File “/usr/local/lib/python3.9/dist-packages/ufl/log.py”, line 158, in error
raise self._exception_type(self._format_raw(*message))
ufl.log.UFLException: Shapes do not match: <Argument id=140363992421472> and <Div id=140364133793920>.

This means that the shape of w is different from the shape of div(u), which is understandable since now w and u belong to the same mixed space W (and when taking the divergence of u, the space changes).

Consequently, my question would be how can I combine test and trial functions that belong to different spaces to build the bilinear form. Does anybody have any idea?

My minimal example is:

# Import
from mpi4py import MPI
rank = MPI.COMM_WORLD.rank
import dolfinx
from ufl import Identity, div, dot, ds, dx, inner, lhs, nabla_grad, rhs, sym, Dn, grad

‘’’ Generation of geometry and mesh ‘’’
# Domain dimensions
L = 3
H = 0.5
gdim = 3

# Initialise meshing process
import gmsh
gmsh.initialize()

# Geometry
if rank == 0:
fluid = gmsh.model.occ.addBox(0, 0, 0, L, H, H)
gmsh.model.occ.synchronize()

# Generate mesh
if rank == 0:
gmsh.model.mesh.generate(gdim)
gmsh.write(“meshTVAchannel.msh”)

# Domain marker
fluid_marker = 1
if rank == 0:
volumes = gmsh.model.getEntities(dim=gdim)
gmsh.model.setPhysicalName(volumes, fluid_marker, “Fluid”)

# Boundary markers
import numpy as np
inlet_marker, outlet_marker, wall_marker = 2, 3, 4
inflow, outflow, walls = [], [], []
if rank == 0:
boundaries = gmsh.model.getBoundary(volumes)
for boundary in boundaries:
center_of_mass = gmsh.model.occ.getCenterOfMass(boundary, boundary)
if np.allclose(center_of_mass, [0, H/2, 0]):
inflow.append(boundary)
elif np.allclose(center_of_mass, [L, H/2, 0]):
outflow.append(boundary)
else:
walls.append(boundary)
gmsh.model.setPhysicalName(1, wall_marker, “Walls”)
gmsh.model.setPhysicalName(1, inlet_marker, “Inlet”)
gmsh.model.setPhysicalName(1, outlet_marker, “Outlet”)

# Import mesh to dolfinX
from gmsh_helpers import gmsh_model_to_mesh
mesh, facet_tags = gmsh_model_to_mesh(gmsh.model, cell_data=True, facet_data=False, gdim=3)

‘’’ Generation of finite element spaces ‘’’
# Finite element spaces
import ufl
v_cg2 = ufl.VectorElement(“CG”, mesh.ufl_cell(), 2)
p_cg1 = ufl.FiniteElement(“CG”, mesh.ufl_cell(), 1)
T_cg2 = ufl.FiniteElement(“CG”, mesh.ufl_cell(), 2)
mel = ufl.MixedElement([v_cg2, p_cg1, T_cg2])
V = dolfinx.FunctionSpace(mesh, v_cg2)
Q = dolfinx.FunctionSpace(mesh, p_cg1)
W = dolfinx.FunctionSpace(mesh, T_cg2)
Y = dolfinx.FunctionSpace(mesh, mel)

# Trial and test functions
u = ufl.TrialFunction(V)
v = ufl.TestFunction(V)
p = ufl.TrialFunction(Q)
q = ufl.TestFunction(Q)
T = ufl.TrialFunction(W)
w = ufl.TestFunction(W)
# # Trial and test functions
# u = ufl.TrialFunction(Y)
# v = ufl.TestFunction(Y)
# p = ufl.TrialFunction(Y)
# q = ufl.TestFunction(Y)
# T = ufl.TrialFunction(Y)
# w = ufl.TestFunction(Y)

# Numerical parameters
gamma = 1.017

‘’’’ Left-hand side ‘’’
# First component
L1 = inner(q,(gamma*p-T))*dx

# Second component
L2 = inner(w,div(u))*dx

L = L1 + L2

A = dolfinx.fem.assemble_matrix(L)
A.assemble()

Thank you very much in advance!

Please make sure that your code is properly formatted (indentation preserved) using 3x encapsulation, and make sure to remove all code not needed for reproducibility.

Sorry, I did not paste the code in the correct format. Please find below a minimal example for the first error and a minimal example for the second error.

# Minimal example for first error

# Import
import dolfinx
from ufl import Identity, div, dot, ds, dx, inner, lhs, nabla_grad, rhs, sym, Dn, grad

# Domain dimensions
L = 3
H = 0.5
gdim = 3

# Initialise meshing process
import gmsh
gmsh.initialize()

# Geometry
fluid = gmsh.model.occ.addBox(0, 0, 0, L, H, H)
gmsh.model.occ.synchronize()

# Generate mesh
gmsh.model.mesh.generate(gdim)

# Domain marker
fluid_marker = 1
volumes = gmsh.model.getEntities(dim=gdim)
gmsh.model.setPhysicalName(volumes, fluid_marker, 'Fluid')

# Import mesh to dolfinX
from gmsh_helpers import gmsh_model_to_mesh
mesh, facet_tags = gmsh_model_to_mesh(gmsh.model, cell_data=True, facet_data=False, gdim=3)

# Finite element spaces
import ufl
v_cg2 = ufl.VectorElement('CG', mesh.ufl_cell(), 2)
p_cg1 = ufl.FiniteElement('CG', mesh.ufl_cell(), 1)
T_cg2 = ufl.FiniteElement('CG', mesh.ufl_cell(), 2)
mel = ufl.MixedElement([v_cg2, p_cg1, T_cg2])
V = dolfinx.FunctionSpace(mesh, v_cg2)
Q = dolfinx.FunctionSpace(mesh, p_cg1)
W = dolfinx.FunctionSpace(mesh, T_cg2)
Y = dolfinx.FunctionSpace(mesh, mel)

# Trial and test functions
u = ufl.TrialFunction(V)
v = ufl.TestFunction(V)
p = ufl.TrialFunction(Q)
q = ufl.TestFunction(Q)
T = ufl.TrialFunction(W)
w = ufl.TestFunction(W)

# Numerical parameters
gamma = 1.017

# First component
L1 = inner(q,(gamma*p-T))*dx

# Assemble bilinear form
A = dolfinx.fem.assemble_matrix(L1)
A.assemble()


# Minimal example for the second error

# Import
import dolfinx
from ufl import Identity, div, dot, ds, dx, inner, lhs, nabla_grad, rhs, sym, Dn, grad

# Domain dimensions
L = 3
H = 0.5
gdim = 3

# Initialise meshing process
import gmsh
gmsh.initialize()

# Geometry
fluid = gmsh.model.occ.addBox(0, 0, 0, L, H, H)
gmsh.model.occ.synchronize()

# Generate mesh
gmsh.model.mesh.generate(gdim)

# Domain marker
fluid_marker = 1
volumes = gmsh.model.getEntities(dim=gdim)
gmsh.model.setPhysicalName(volumes, fluid_marker, 'Fluid')

# Import mesh to dolfinX
from gmsh_helpers import gmsh_model_to_mesh
mesh, facet_tags = gmsh_model_to_mesh(gmsh.model, cell_data=True, facet_data=False, gdim=3)

# Finite element spaces
import ufl
v_cg2 = ufl.VectorElement('CG', mesh.ufl_cell(), 2)
p_cg1 = ufl.FiniteElement('CG', mesh.ufl_cell(), 1)
T_cg2 = ufl.FiniteElement('CG', mesh.ufl_cell(), 2)
mel = ufl.MixedElement([v_cg2, p_cg1, T_cg2])
V = dolfinx.FunctionSpace(mesh, v_cg2)
Q = dolfinx.FunctionSpace(mesh, p_cg1)
W = dolfinx.FunctionSpace(mesh, T_cg2)
Y = dolfinx.FunctionSpace(mesh, mel)

# Trial and test functions
u = ufl.TrialFunction(Y)
v = ufl.TestFunction(Y)
p = ufl.TrialFunction(Y)
q = ufl.TestFunction(Y)
T = ufl.TrialFunction(Y)
w = ufl.TestFunction(Y)

# Numerical parameters
gamma = 1.017

# Second component
L2 = inner(w,div(u))*dx

# Assemble bilinear form
A = dolfinx.fem.assemble_matrix(L2)
A.assemble()


You need to split the trial function from the mixed space for each component, which can either be done by

y = ufl.TrialFunction(Y)
u, p, T = ufl.split(y)


or use ufl.TrialFunctions, as shown below:

# Import
import dolfinx
from ufl import  div, dx, inner, FiniteElement, VectorElement, TrialFunctions, TestFunctions, MixedElement
from mpi4py import MPI
mesh = dolfinx.UnitCubeMesh(MPI.COMM_WORLD, 10, 10, 10)
v_cg2 = VectorElement('CG', mesh.ufl_cell(), 2)
p_cg1 = FiniteElement('CG', mesh.ufl_cell(), 1)
T_cg2 = FiniteElement('CG', mesh.ufl_cell(), 2)
mel = MixedElement([v_cg2, p_cg1, T_cg2])
V = dolfinx.FunctionSpace(mesh, v_cg2)
Q = dolfinx.FunctionSpace(mesh, p_cg1)
W = dolfinx.FunctionSpace(mesh, T_cg2)
Y = dolfinx.FunctionSpace(mesh, mel)

# Trial and test functions
u, p, T = TrialFunctions(Y)
v, q, w = TestFunctions(Y)

# Numerical parameters
gamma = 1.017

# Second component
L2 = inner(w,div(u))*dx

# Assemble bilinear form
A = dolfinx.fem.assemble_matrix(L2)
A.assemble()
`
1 Like

Thank you very much! It’s working now.