Error: Problem with Expression inside an Expression: Missing eval() function (must be overloaded)

Hey,

I’m experiencing a weird behaviour of fenics: I basically want to use one C++ -Expression inside another C++ -Expression. If I use both times the simple version (something like Expression(‘x[0]’, degree=2) ), then it works, however when I want to use the complex version with CompiledExpression it gives me the following error:

***-------------------------------------------------------------------------
*** Error: Unable to evaluate expression.
*** Reason: Missing eval() function (must be overloaded).
*** Where: This error was encountered inside Expression.cpp.
*** Process: 0

*** DOLFIN version: 2019.2.0.dev0
*** Git changeset: unknown
*** -------------------------------------------------------------------------

Here is a minimal example that partially works and hopefully explains my problem better:

from fenics import *
import matplotlib.pyplot as plt

mesh = UnitSquareMesh(10,10)
V = FunctionSpace(mesh, 'P', 1)

exp_1 = Expression( '10', degree=2)
exp_from_exp_1 = Expression('10*exp_1', exp_1=exp_1, degree=2) # this works

cpp_code = '''#include <pybind11/pybind11.h>
#include <pybind11/eigen.h>
namespace py = pybind11;

#include <dolfin/function/Expression.h> // for expressions


class Exp2 : public dolfin::Expression
{
   public:
       Exp2() : dolfin::Expression(){} 
       void eval(Eigen::Ref<Eigen::VectorXd> values, Eigen::Ref<const Eigen::VectorXd> x, const ufc::cell& cell) const override
       {
           values[0] = 10;
       }

};
PYBIND11_MODULE(SIGNATURE, m)
{
   py::class_<Exp2, std::shared_ptr<Exp2>, dolfin::Expression>(m, "Exp2")
   .def(py::init<>());
}
'''
exp_2 = CompiledExpression( compile_cpp_code(cpp_code).Exp2(), degree=2)
exp_from_exp_2 = Expression('10*exp_2', exp_2=exp_2, degree=2)


test1 = interpolate(exp_1, V) # this works
test2 = interpolate(exp_2, V) # this works
test3 = interpolate(exp_from_exp_1, V) # this works
test4 = interpolate(exp_from_exp_2, V) # this does not work

Note that the interpolation of exp_from_exp_2 does not work, however the interpolation for exp_from_exp_1 does. What am I missing?

Ok, I have found a solution: I assume that the simple expression ( Expression(‘10*exp_2’, exp_2=exp_2, degree=2) ) calls the function Exp2.eval(values, x). I defined the function eval(values, x, cell), thus the former could not be found, returning said error.
Is this a bug in fenics?

In summary this code that works for me:

from fenics import *
import matplotlib.pyplot as plt

mesh = UnitSquareMesh(10,10)
V = FunctionSpace(mesh, 'P', 1)

exp_1 = Expression( '10', degree=2)
exp_from_exp_1 = Expression('10*exp_1', exp_1=exp_1, degree=2) # this works

cpp_code = '''#include <pybind11/pybind11.h>
#include <pybind11/eigen.h>
namespace py = pybind11;

#include <dolfin/function/Expression.h> // for expressions


class Exp2 : public dolfin::Expression
{
   public:
       Exp2() : dolfin::Expression(){} 
       void eval(Eigen::Ref<Eigen::VectorXd> values, Eigen::Ref<const Eigen::VectorXd> x) const override
       {
           values[0] = 10;
       }

};
PYBIND11_MODULE(SIGNATURE, m)
{
   py::class_<Exp2, std::shared_ptr<Exp2>, dolfin::Expression>(m, "Exp2")
   .def(py::init<>());
}
'''
exp_2 = CompiledExpression( compile_cpp_code(cpp_code).Exp2(), degree=2)
exp_from_exp_2 = Expression('10*exp_2', exp_2=exp_2, degree=2)


test1 = interpolate(exp_1, V) # this works
test2 = interpolate(exp_2, V) # this works
test3 = interpolate(exp_from_exp_1, V) # this works
test4 = interpolate(exp_from_exp_2, V) # this does not work

Only difference is that I removed the requirement for cell in the eval function.

This workaround does work as well: Evaluate UserExpression with eval_cell - #2 by Maeggis, however I don’t find it to be very elegant nor intuitive