UFLValueError: Invalid type conversion - can not be converted to any UFL type

Hello,

I am working on a contact issue using a penalty term in the variational formulation.
Maybe someone can help me find a solution for the following UFL Type Error:

 File "/home/fenics/shared/mwe_rec_cropped.py", line 97, in <module>
    form = inner(sigma(u), eps(u_))*dx +pen*dot(u_, gap)*ds
  File "/usr/local/lib/python3.10/dist-packages/ufl/operators.py", line 174, in dot
    b = as_ufl(b)
  File "/usr/local/lib/python3.10/dist-packages/ufl/constantvalue.py", line 438, in as_ufl
    raise UFLValueError("Invalid type conversion: %s can not be converted"
ufl.log.UFLValueError: Invalid type conversion: <function gap at 0x7fb625a57d90> can not be converted to any UFL type.

I am probably mixing different types of algebra but as I am new to fenicsx I can not find a working expression for gap().
I would be very grateful for help.

Sketch of the problem:

MWE for the problem:

import gmsh
import numpy as np
from dolfinx import fem, mesh
from dolfinx.io import XDMFFile, gmshio
from mpi4py import MPI
from petsc4py.PETSc import ScalarType
from ufl import dx, inner, derivative, tr, Identity, sym, grad, TrialFunction, TestFunction, Measure, SpatialCoordinate, dot, sqrt

gmsh.initialize()
gmsh.model.add("rectangle")
lc=0.5e-1

# generate points for inner contour
gmsh.model.geo.addPoint(1, 1, 0, lc, 1)
gmsh.model.geo.addPoint(-1, 1, 0, lc, 2)
gmsh.model.geo.addPoint(-1, -1, 0, lc, 3)
gmsh.model.geo.addPoint(1, -1, 0, lc, 4)
# generate inner contour
gmsh.model.geo.addLine(1, 2, 1)
gmsh.model.geo.addLine(2, 3, 2)
gmsh.model.geo.addLine(3, 4, 3)
gmsh.model.geo.addLine(4, 1, 4)
# generate points for outer contour
gmsh.model.geo.addPoint(2, 2, 0, lc, 5)
gmsh.model.geo.addPoint(-2, 2, 0, lc, 6)
gmsh.model.geo.addPoint(-2, -2, 0, lc, 7)
gmsh.model.geo.addPoint(2, -2, 0, lc, 8)
# generate outer contour
gmsh.model.geo.addLine(5, 6, 5)
gmsh.model.geo.addLine(6, 7, 6)
gmsh.model.geo.addLine(7, 8, 7)
gmsh.model.geo.addLine(8, 5, 8)
# generate curveloops
gmsh.model.geo.addCurveLoop([1, 2, 3, 4], 1)
gmsh.model.geo.addCurveLoop([5, 6, 7, 8], 2)
# generate surface
gmsh.model.geo.addPlaneSurface([2, 1], 1)
gmsh.model.geo.synchronize()
# generate physical groups for boundary conditions
inside, outside, surface = 1, 2, 3
gmsh.model.addPhysicalGroup(1, [1, 2, 3, 4], inside, name="Inner Contour")
gmsh.model.addPhysicalGroup(1, [5, 6, 7, 8], outside, name="Outer Contour")
gmsh.model.addPhysicalGroup(2, [1], surface, name="Surface")
# finish gmsh
gmsh.model.mesh.generate(2)

# create a DOLFINx mesh 
dim = 2
gmsh_model_rank = 0
domain_com = MPI.COMM_SELF
domain, cell_markers, facet_markers = gmshio.model_to_mesh(gmsh.model, domain_com, gmsh_model_rank, dim)

gmsh.finalize()

tdim = domain.topology.dim
fdim = tdim - 1

# define function space
V = fem.VectorFunctionSpace(domain, ("CG",1))

# contact zones
x = SpatialCoordinate(domain)
center_x = .0
center_y = .0
D = 2.4

def gap():
    return (D/2) - sqrt( pow(x[0]-center_x, 2) + pow(x[1]-center_y, 2) )

def in_circle(x):
    return np.less_equal(((x[0]-center_x)**2 + (x[1]-center_y)**2), ((D/2)**2))

contact_facets = mesh.locate_entities_boundary(domain,fdim ,in_circle)
metadata = {"quadrature_degree": 4}
ds = Measure('ds', domain=domain, subdomain_data=contact_facets, metadata=metadata)

# test and trial functions
u = fem.Function(V, name="Displacement")
du = TrialFunction(V)
u_ = TestFunction(V)

# define outer contour as homogenous boundary condition
u_zero = np.array((0,)*domain.geometry.dim, dtype=ScalarType)
bc = fem.dirichletbc(u_zero, fem.locate_dofs_topological(V, fdim, facet_markers.find(outside)), V)

# constituive relations - linear elasticity
E = fem.Constant(domain, ScalarType(10.))
nu = fem.Constant(domain, ScalarType(0.3))
mu = E/2/(1+nu)
lmbda = E*nu/(1+nu)/(1-2*nu)
def eps(v):
    return sym(grad(v))
def sigma(v):
    return lmbda*tr(eps(v))*Identity(2) + 2.0*mu*eps(v)

pen = fem.Constant(domain, ScalarType(1e4))
form = inner(sigma(u), eps(u_))*dx + pen*dot(u_, gap)*ds
J = derivative(form, u, du)

problem = fem.petsc.NonlinearProblem(form, u, bcs=[bc], J=J)
from dolfinx import nls
solver = nls.petsc.NewtonSolver(domain.comm, problem)

First of all gap is python-function, which is not supported as input to the form.
You should be able to use gap() as long as you define it correctly.
Note that gap is not a vector-valued function, which you can inspect by printing gap().ufl_shape. As you can see by printing u_.ufl_shape, the shape should be (2,) not () which would indicate a scalar valued expression.

1 Like

Thanks for your help!

I have now changed the function name and tried to do the dot product by using the first dim of u_ only (just for syntax test purpose)

It seems, that ufl can not handle the expression itself.

Shape of pen_depth() - former gap():
()
Shape of u_[0]:
()

Traceback (most recent call last):
  File "/home/fenics/shared/mwe_rec_cropped.py", line 102, in <module>
    form = inner(sigma(u), eps(u_))*dx + pen*dot(u_[0], pen_depth)*ds 
  File "/usr/local/lib/python3.10/dist-packages/ufl/operators.py", line 174, in dot
    b = as_ufl(b)
  File "/usr/local/lib/python3.10/dist-packages/ufl/constantvalue.py", line 438, in as_ufl
    raise UFLValueError("Invalid type conversion: %s can not be converted"
ufl.log.UFLValueError: Invalid type conversion: <function pen_depth at 0x7f85f0fcfd90> can not be converted to any UFL type.

As i said earlier, this has to be
form = inner(sigma(u), eps(u_))*dx + pen*dot(u_[0], pen_depth())*ds
If pen_depth is def pen_depth():….