Copying Expressions in C++

I am trying to initialize an expression to an expression class variable but I get an error during compilation. This same error occurs when I try to copy an expression. The problem can be reproduced by adding the following to the end of the hyperelasticity demo main.cpp.

const auto copy_expr = sigma_expression;

The error I get is:

hyperelasticity/main.cpp:237:28: error: use of deleted function ‘dolfinx::fem::Expression<double>::Expression(const dolfinx::fem::Expression<double>&)’
  237 |     const auto copy_expr = sigma_expression;
      |                            ^~~~~~~~~~~~~~~~
note: ‘dolfinx::fem::Expression<double>::Expression(const dolfinx::fem::Expression<double>&)’ is implicitly declared as deleted because ‘dolfinx::fem::Expression<double>’ declares a move constructor or move assignment operator
   33 | class Expression
      |       ^~~~~~~~~~

Is it because the Expressions class doesn’t have a copy constructor? I am using FEniCSx 0.5.2

Yes, Expression doesn’t have a copy builder.
I believe it was deliberately deleted.

What’s you use case? Maybe it could be used as an argument for adding a copy constructor.

It’s for making a QuadratureFunction class to use with the nonlinear solver. I was planning on having it look like this.

class QuadratureFunction
{
public:
    QuadratureFunction(dolfinx::fem::Expression<T> expr, std::shared_ptr<dolfinx::fem::Function<T>>& u,
                        std::vector<int>& cells, std::shared_ptr<dolfinx::fem::FunctionSpace>& Q) 
                        : _expr(expr), _u(u), _cells(cells), _Q(Q)
    {}
    /// Destructor
    ~QuadratureFunction();
    
    void interpolate()
    {
        auto [eval_points, _shape] = _expr.X();
        std::array<std::size_t, 2> shape
            = {_cells.size(), _shape[0] * _expr.value_size()};
        std::vector<T> values(shape[0]*shape[1]);
        _expr.eval(_cells, values, shape);
        // Move values into _u
        dolfinx::la::petsc::Vector _u_petsc(
            dolfinx::la::petsc::create_vector_wrap(*_u->x()), false);
        VecSetBlockSize(_u_petsc.vec(), _Q->dofmap()->bs());
        VecSetValuesBlockedLocal(
            _u_petsc.vec(), _u->x()->array().size() / _Q->dofmap()->bs(),
            _Q->dofmap()->list().array().data(), values.data(), INSERT_VALUES);
        _u->x()->scatter_fwd();
    }
private:
    dolfinx::fem::Expression<T> _expr;
    std::shared_ptr<dolfinx::fem::Function<T>> _u;
    std::vector<int> _cells;
    std::shared_ptr<dolfinx::fem::FunctionSpace> _Q;
};

I see.
What about using a shared_ptr?
You can use std::make_shared with the default constructor and send the shared pointer, similar to what you’re already doing for Function.

1 Like