Invalid ranks 1 and 1 in product

I am trying to implement the following corrector equation for a fixed \omega.


where I define A(y,\omega) as \kappa below and regard x as y_1, regard y as y_2.

With the inspiration of this link, I wrote the following code.

from dolfin import *
import ufl
import matplotlib.pyplot as plt
import numpy

# Create mesh and define function space
mesh = UnitSquareMesh(4, 6)
P1 = FiniteElement('Lagrange', mesh.ufl_cell(), 1)
R = FiniteElement('Real', mesh.ufl_cell(), 0)
X = FunctionSpace(mesh, P1*R)

# Define subdomains
subdomains = MeshFunction("size_t", mesh, 2)
class Omega_0(SubDomain):
    def inside(self, x, on_boundary):
        return True if x[1] <= 0.5 else False
class Omega_1(SubDomain):
    def inside(self, x, on_boundary):
        return True if x[1] >= 0.5 else False
# Mark subdomains with numbers 0 and 1
subdomain_0 = Omega_0()
subdomain_1 = Omega_1()
subdomain_0.mark(subdomains, 0)
subdomain_1.mark(subdomains, 1)

# plot(subdomains, title='subdomains')

# fill cell value in k
V0 = FunctionSpace(mesh,"DG",0)
k = Function(V0)
k_values = [1.5, 50] # values of k in the two subdomains
for cell_no in range(len(subdomains.array())):
    subdomain_no = subdomains.array()[cell_no]
    k.vector()[cell_no] = k_values[subdomain_no]
# print('k degree of freedoms:', k.vector().get_local())

# define corrector equation
u, m = TrialFunctions(X)
v, r = TestFunctions(X)
Fc = u*r*dx + + m*v*ds
# Fl = inner(nabla_grad(u) + Constant((1,0)), k*nabla_grad(v))*dx
Fl = nabla_grad(u) * k * nabla_grad(v) * dx + k * nabla_grad(v) * dx
F = Fc + Fl

# Compute first order corrector    
x = Function(X)
solve(F == 0, x)
uh, mh = x.split()

But unfortunately, I got this error in Fl = nabla_grad(u) * k * nabla_grad(v) * dx + k * nabla_grad(v) * dx.

Exception has occurred: UFLException
Invalid ranks 1 and 1 in product.
  File "/mnt/c/Users/Hanyue/Desktop/periodic_homo/", line 65, in <module>
    Fl = nabla_grad(u) * k * nabla_grad(v) * dx + k * nabla_grad(v) * dx
ufl.log.UFLException: Invalid ranks 1 and 1 in product.

Is anyone know how to fix it? To be honest, I don’t really understand the rank here.

The “rank” here refers to the number of indices a tensor has, e.g., a scalar has rank 0, a vector has rank 1, a matrix has rank 2, and so on. Applying nabla_grad to a scalar field results in a vector field (rank 1). The * operator between a scalar and a vector is interpreted as scalar multiplication, so nabla_grad(u) * k results in another vector field (rank 1). However, the notion of multiplying two rank-1 vectors together (as in the second * in Fl) is ambiguous, since it could reasonably be interpreted as a dot product (returning a scalar), a cross product (returning a vector), or a tensor/outer product (returning a matrix). This is why FEniCS UFL has separate functions dot, cross, and outer to avoid ambiguity. (There is also inner, which is equivalent to dot for vectors, but these functions have different behaviors for higher-rank tensors.)

Extrapolating from other diffusion-like problems (without understanding your particular application), I would guess that what you want is dot(k*nabla_grad(u),nabla_grad(v)) in the first term of Fl. However, the second term of Fl is vector-valued as written, which would make the + invalid (adding a scalar to a vector). It’s not clear to me what the ranks are supposed to be of all symbols in the original mathematical notation; it seems like the scalar-valued k in the code is acting as A in the formulation, but the formulation takes a transpose of A and applies the divergence operator, which wouldn’t make sense for a scalar field.