Error with UFL condition in complex-valued problems

Hello all,

I am trying to use ufl.conditional for a complex-valued problem. For the condition argument, I have tried both binary operators (<, <=, >, >=) and UFL operators (ufl.lt, ufl.le, ufl.gt, ufl.ge) without success.

Even when using ufl.real on a complex-valued function, the condition is still interpreted as complex-valued.

For information, I am running version v0.10.0.post2 of dolfinx on the dolfinx/dolfinx:stable docker container, inside Ubuntu 24.04.4 LTS.

This is a minimal example reproducing the problem:

import ufl
import numpy as np

from mpi4py import MPI
from petsc4py import PETSc
from dolfinx import fem, mesh
from dolfinx.fem.petsc import NewtonSolverNonlinearProblem

assert np.dtype(PETSc.ScalarType).kind == "c"

mesh = mesh.create_unit_square(MPI.COMM_WORLD, 10, 10)
V = fem.functionspace(mesh, ("Lagrange", 1))
u_d = fem.Constant(mesh, PETSc.ScalarType(37))

u, v = fem.Function(V), ufl.TestFunction(V)
f = fem.Constant(mesh, PETSc.ScalarType(100 - 2j))
kappa = ufl.conditional(
    ufl.real(u) < 60.0,
    PETSc.ScalarType(1.0),
    PETSc.ScalarType(2.0),
)

a = kappa * ufl.inner(ufl.grad(u), ufl.grad(v)) * ufl.dx
L = ufl.inner(f, v) * ufl.dx

left_dofs = fem.locate_dofs_geometrical(V, lambda x: np.isclose(x[0], 0.0))
bc = fem.dirichletbc(u_d, left_dofs, V)

problem = NewtonSolverNonlinearProblem(a - L, u, bcs=[bc])
problem.solve()

and the associated output:

libffcx_forms_399ecc8094b42cd457da27b87257025beac63879.c: In function ‘tabulate_tensor_integral_2f0d983d2d4c01adb5a6f5fee96df96ca99ba4a9_triangle’:
libffcx_forms_399ecc8094b42cd457da27b87257025beac63879.c:695:28: error: invalid operands to binary < (have ‘complex double’ and ‘double’)
  695 | bool sp_083_29 = sp_083_28 < 60.0;
      |                            ^
Traceback (most recent call last):
  File "/dolfinx-env/lib/python3.12/site-packages/setuptools/_distutils/spawn.py", line 87, in spawn
    subprocess.check_call(cmd, env=_inject_macos_ver(env))
  File "/usr/lib/python3.12/subprocess.py", line 413, in check_call
    raise CalledProcessError(retcode, cmd)
subprocess.CalledProcessError: Command '['/usr/bin/x86_64-linux-gnu-gcc', '-fno-strict-overflow', '-Wsign-compare', '-DNDEBUG', '-g', '-O2', '-Wall', '-fPIC', '-I/dolfinx-env/lib/python3.12/site-packages/ffcx/codegeneration', '-I/dolfinx-env/include', '-I/usr/include/python3.12', '-c', 'libffcx_forms_399ecc8094b42cd457da27b87257025beac63879.c', '-o', './libffcx_forms_399ecc8094b42cd457da27b87257025beac63879.o', '-std=c17', '-O2']' returned non-zero exit status 1.

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/dolfinx-env/lib/python3.12/site-packages/setuptools/_distutils/compilers/C/unix.py", line 221, in _compile
    self.spawn(compiler_so + cc_args + [src, '-o', obj] + extra_postargs)
  File "/dolfinx-env/lib/python3.12/site-packages/setuptools/_distutils/compilers/C/base.py", line 1158, in spawn
    spawn(cmd, dry_run=self.dry_run, **kwargs)
  File "/dolfinx-env/lib/python3.12/site-packages/setuptools/_distutils/spawn.py", line 93, in spawn
    raise DistutilsExecError(
distutils.errors.DistutilsExecError: command '/usr/bin/x86_64-linux-gnu-gcc' failed with exit code 1

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/dolfinx-env/lib/python3.12/site-packages/cffi/ffiplatform.py", line 48, in _build
    dist.run_command('build_ext')
  File "/dolfinx-env/lib/python3.12/site-packages/setuptools/dist.py", line 1102, in run_command
    super().run_command(command)
  File "/dolfinx-env/lib/python3.12/site-packages/setuptools/_distutils/dist.py", line 1021, in run_command
    cmd_obj.run()
  File "/dolfinx-env/lib/python3.12/site-packages/setuptools/command/build_ext.py", line 96, in run
    _build_ext.run(self)
  File "/dolfinx-env/lib/python3.12/site-packages/setuptools/_distutils/command/build_ext.py", line 368, in run
    self.build_extensions()
  File "/dolfinx-env/lib/python3.12/site-packages/setuptools/_distutils/command/build_ext.py", line 484, in build_extensions
    self._build_extensions_serial()
  File "/dolfinx-env/lib/python3.12/site-packages/setuptools/_distutils/command/build_ext.py", line 510, in _build_extensions_serial
    self.build_extension(ext)
  File "/dolfinx-env/lib/python3.12/site-packages/setuptools/command/build_ext.py", line 261, in build_extension
    _build_ext.build_extension(self, ext)
  File "/dolfinx-env/lib/python3.12/site-packages/Cython/Distutils/build_ext.py", line 136, in build_extension
    super().build_extension(ext)
  File "/dolfinx-env/lib/python3.12/site-packages/setuptools/_distutils/command/build_ext.py", line 565, in build_extension
    objects = self.compiler.compile(
              ^^^^^^^^^^^^^^^^^^^^^^
  File "/dolfinx-env/lib/python3.12/site-packages/setuptools/_distutils/compilers/C/base.py", line 655, in compile
    self._compile(obj, src, ext, cc_args, extra_postargs, pp_opts)
  File "/dolfinx-env/lib/python3.12/site-packages/setuptools/_distutils/compilers/C/unix.py", line 223, in _compile
    raise CompileError(msg)
distutils.compilers.C.errors.CompileError: command '/usr/bin/x86_64-linux-gnu-gcc' failed with exit code 1

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "ufl_conditional_complex_mwe.py", line 29, in <module>
    problem = NewtonSolverNonlinearProblem(a - L, u, bcs=[bc])
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/dolfinx-complex/lib/python3.12/dist-packages/dolfinx/fem/petsc.py", line 1479, in __init__
    self._L = _create_form(
              ^^^^^^^^^^^^^
  File "/usr/local/dolfinx-complex/lib/python3.12/dist-packages/dolfinx/fem/forms.py", line 449, in form
    return _create_form(form)
           ^^^^^^^^^^^^^^^^^^
  File "/usr/local/dolfinx-complex/lib/python3.12/dist-packages/dolfinx/fem/forms.py", line 441, in _create_form
    return _form(form)
           ^^^^^^^^^^^
  File "/usr/local/dolfinx-complex/lib/python3.12/dist-packages/dolfinx/fem/forms.py", line 361, in _form
    ufcx_form, module, code = jit.ffcx_jit(
                              ^^^^^^^^^^^^^
  File "/usr/local/dolfinx-complex/lib/python3.12/dist-packages/dolfinx/jit.py", line 60, in mpi_jit
    return local_jit(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/dolfinx-complex/lib/python3.12/dist-packages/dolfinx/jit.py", line 215, in ffcx_jit
    r = ffcx.codegeneration.jit.compile_forms([ufl_object], options=p_ffcx, **p_jit)
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/dolfinx-env/lib/python3.12/site-packages/ffcx/codegeneration/jit.py", line 244, in compile_forms
    raise e
  File "/dolfinx-env/lib/python3.12/site-packages/ffcx/codegeneration/jit.py", line 224, in compile_forms
    impl = _compile_objects(
           ^^^^^^^^^^^^^^^^^
  File "/dolfinx-env/lib/python3.12/site-packages/ffcx/codegeneration/jit.py", line 399, in _compile_objects
    ffibuilder.compile(tmpdir=cache_dir, verbose=True, debug=cffi_debug)
  File "/dolfinx-env/lib/python3.12/site-packages/cffi/api.py", line 727, in compile
    return recompile(self, module_name, source, tmpdir=tmpdir,
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/dolfinx-env/lib/python3.12/site-packages/cffi/recompiler.py", line 1581, in recompile
    outputfilename = ffiplatform.compile('.', ext,
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/dolfinx-env/lib/python3.12/site-packages/cffi/ffiplatform.py", line 20, in compile
    outputfilename = _build(tmpdir, ext, compiler_verbose, debug)
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/dolfinx-env/lib/python3.12/site-packages/cffi/ffiplatform.py", line 54, in _build
    raise VerificationError('%s: %s' % (e.__class__.__name__, e))
cffi.VerificationError: CompileError: command '/usr/bin/x86_64-linux-gnu-gcc' failed with exit code 1

Any ideas for getting around this problem ?

Best,

1 Like

This looks like it might be a bug. If you look at the generated code:

float _Complex sp_083_27 = crealf(sp_083_26);
bool sp_083_28 = sp_083_27 < 60.0;

It looks like the variable sp_083_27 which is the translation of ufl.real(u) does not have the type expected to be returned by crealf which is float. The < operator is therefore invalid when comparing complex numbers (I’m using PETSC_ARCH=linux-gnu-complex64-32).

@dokken may have more insight, but it seems this should be reported as a bug in FFCx.

Seems like a bug to me:

from mpi4py import MPI

import ufl
import basix.ufl
import dolfinx
cell = basix.CellType.triangle
c_el = basix.ufl.element("Lagrange", cell, 1, shape=(2,))
mesh = ufl.Mesh(c_el)
el = basix.ufl.element("Lagrange", cell, 1)
V = ufl.FunctionSpace(mesh, el)
u = ufl.Coefficient(V)
c = ufl.conditional(ufl.gt(ufl.real(u), 0), 1, 0)
J = c * ufl.dx


scalar_type = "float64"
scalar_type = "complex128"
Jh = dolfinx.fem.compile_form(MPI.COMM_WORLD, J, form_compiler_options={"scalar_type": scalar_type})

yields:

libffcx_forms_3c93f5bcb1264cecdb1827c501f934aec839b2e4.c: In function ‘tabulate_tensor_integral_a66be3d5d9a1761d870c072e1ccafc761594310b_triangle’:
libffcx_forms_3c93f5bcb1264cecdb1827c501f934aec839b2e4.c:650:26: error: invalid operands to binary > (have ‘complex double’ and ‘double’)
  650 | bool sp_083_7 = sp_083_6 > 0.0;

Removing the compile_form and inspecting the form, as @nate did, yields:

 python -m ffcx mwe_complex.py --scalar_type=complex128
double _Complex sp_083_5 = creal(w0);
double _Complex sp_083_6 = creal(sp_083_5);
bool sp_083_7 = sp_083_6 > 0.0;

which to me seems like a bug.

1 Like