Binding Step-6 class with Boost.Python gives an compilation error: "use of deleted function"

13 views
Skip to first unread message

Oleg Kmechak

unread,
Jun 14, 2020, 8:34:49 PM6/14/20
to deal.II User Group
Hello All, 

I am trying to port C++ program to Python using Boost.Python. Have done already a lot of work with porting of classes(mostly based on std) and it works as expected. 
But currently strugling with the last one class to port(class Solver), which is almost the same as step-6. 

Some code(link to repo):

```cpp
class Solver
    {
        public:
            //Solver():
            //    dof_handler(triangulation),
            //    fe(3), 
            //    quadrature_formula(3),
            //    face_quadrature_formula(3)
            //{}

            ///Solver constructor
            Solver(Model *model):
                dof_handler(triangulation)
            { 
                model = model;

                //fixme
                //fe = FE_Q<DIM>{model->solver_params.quadrature_degree};
                //quadrature_formula = QGauss<DIM>{model->solver_params.quadrature_degree};
                //face_quadrature_formula = QGauss<DIM - 1>{model->solver_params.quadrature_degree};
            };
            
            ~Solver(){clear();}

            void OpenMesh(const string fileName = "river.msh");
            void run();
            void output_results(const string file_name) const;
            vector<double> integrate(const Model& mdl, const Point& point, const double angle);

            ///Clear Solver object.
            void clear()
            {
              dof_handler.clear();
              triangulation.clear();
              hanging_node_constraints.clear();
              system_matrix.clear();
              solution.reinit(0);
            }
        private:
            Model *model = NULL;

            Triangulation<DIM> triangulation;
            DoFHandler<DIM> dof_handler;

            FE_Q<DIM> fe = FE_Q<DIM>{3};
            QGauss<DIM> quadrature_formula = QGauss<DIM>{3};
            QGauss<DIM - 1> face_quadrature_formula = QGauss<DIM - 1>{3};
            
            AffineConstraints<double> hanging_node_constraints;

            SparsityPattern sparsity_pattern;
            SparseMatrix<double> system_matrix;

            Vector<double> solution;
            Vector<double> system_rhs;

            ConvergenceTable convergence_table;

            void setup_system();
            void assemble_system();
            void solve();
            void refine_grid();
    };
} // namespace River
```

BoostPython part:

```cpp
class_<River::Solver>("Solver", init<River::Model*>(args("model")))
        .def("OpenMesh", &River::Solver::OpenMesh)
        .def("run", &River::Solver::run)
        .def("output_results", &River::Solver::output_results)
        .def("integrate", &River::Solver::integrate)
        .def("clear", &River::Solver::clear)
    ;




And it gives next error, but I nowhere use copy constructor of DoFHandler nor Triangulation:

[ 98%] Building CXX object source/CMakeFiles/riversimPY.dir/pythonapi.cpp.o

In file included from /usr/include/boost/preprocessor/iteration/detail/iter/forward1.hpp:52,
                 from /usr/include/boost/python/object/value_holder.hpp:47,
                 from /usr/include/boost/python/object/class_metadata.hpp:14,
                 from /usr/include/boost/python/class.hpp:23,
                 from /usr/include/boost/python.hpp:18,
                 from /mnt/c/users/ofcra/dev/riversim/source/pythonapi.cpp:1:
/usr/include/boost/python/object/value_holder.hpp: In instantiation of ‘boost::python::objects::value_holder<Value>::value_holder(PyObject*, A0) [with A0 = boost::reference_wrapper<const River::Solver>; Value = River::Solver; PyObject = _object]’:
/usr/include/boost/python/object/make_instance.hpp:72:16:   required from ‘static Holder* boost::python::objects::make_instance<T, Holder>::construct(void*, PyObject*, boost::reference_wrapper<const T>) [with T = River::Solver; Holder = boost::python::objects::value_holder<River::Solver>; PyObject = _object]’
/usr/include/boost/python/object/make_instance.hpp:46:31:   required from ‘static PyObject* boost::python::objects::make_instance_impl<T, Holder, Derived>::execute(Arg&) [with Arg = const boost::reference_wrapper<const River::Solver>; T = River::Solver; Holder = boost::python::objects::value_holder<River::Solver>; Derived = boost::python::objects::make_instance<River::Solver, boost::python::objects::value_holder<River::Solver> >; PyObject = _object]’
/usr/include/boost/python/object/class_wrapper.hpp:29:37:   required from ‘static PyObject* boost::python::objects::class_cref_wrapper<Src, MakeInstance>::convert(const Src&) [with Src = River::Solver; MakeInstance = boost::python::objects::make_instance<River::Solver, boost::python::objects::value_holder<River::Solver> >; PyObject = _object]’
/usr/include/boost/python/converter/as_to_python_function.hpp:27:61:   required from ‘static PyObject* boost::python::converter::as_to_python_function<T, ToPython>::convert(const void*) [with T = River::Solver; ToPython = boost::python::objects::class_cref_wrapper<River::Solver, boost::python::objects::make_instance<River::Solver, boost::python::objects::value_holder<River::Solver> > >; PyObject = _object]’
/usr/include/boost/python/to_python_converter.hpp:83:9:   [ skipping 2 instantiation contexts, use -ftemplate-backtrace-limit=0 to disable ]
/usr/include/boost/python/object/class_metadata.hpp:227:55:   required from ‘static void boost::python::objects::class_metadata<T, X1, X2, X3>::register_aux2(T2*, Callback) [with T2 = River::Solver; Callback = boost::integral_constant<bool, false>; T = River::Solver; X1 = boost::python::detail::not_specified; X2 = boost::python::detail::not_specified; X3 = boost::python::detail::not_specified]’
/usr/include/boost/python/object/class_metadata.hpp:218:38:   required from ‘static void boost::python::objects::class_metadata<T, X1, X2, X3>::register_aux(void*) [with T = River::Solver; X1 = boost::python::detail::not_specified; X2 = boost::python::detail::not_specified; X3 = boost::python::detail::not_specified]’
/usr/include/boost/python/object/class_metadata.hpp:204:37:   required from ‘static void boost::python::objects::class_metadata<T, X1, X2, X3>::register_() [with T = River::Solver; X1 = boost::python::detail::not_specified; X2 = boost::python::detail::not_specified; X3 = boost::python::detail::not_specified]’
/usr/include/boost/python/class.hpp:450:28:   required from ‘void boost::python::class_<T, X1, X2, X3>::initialize(const DefVisitor&) [with DefVisitor = boost::python::init_base<boost::python::init<River::Model*> >; W = River::Solver; X1 = boost::python::detail::not_specified; X2 = boost::python::detail::not_specified; X3 = boost::python::detail::not_specified]’
/usr/include/boost/python/class.hpp:204:9:   required from ‘boost::python::class_<T, X1, X2, X3>::class_(const char*, const boost::python::init_base<DerivedT>&) [with DerivedT = boost::python::init<River::Model*>; W = River::Solver; X1 = boost::python::detail::not_specified; X2 = boost::python::detail::not_specified; X3 = boost::python::detail::not_specified]’
/mnt/c/users/ofcra/dev/riversim/source/pythonapi.cpp:473:71:   required from here
/usr/include/boost/python/object/value_holder.hpp:133:13: error: use of deleted function ‘River::Solver::Solver(const River::Solver&)’
  133 |             BOOST_PP_REPEAT_1ST(N, BOOST_PYTHON_UNFORWARD_LOCAL, nil)
      |             ^
In file included from /mnt/c/users/ofcra/dev/riversim/source/river/riversim.hpp:32,
                 from /mnt/c/users/ofcra/dev/riversim/source/app.hpp:3,
                 from /mnt/c/users/ofcra/dev/riversim/source/pythonapi.cpp:5:
/mnt/c/users/ofcra/dev/riversim/source/river/solver.hpp:83:11: note: ‘River::Solver::Solver(const River::Solver&)’ is implicitly deleted because the default definition would be ill-formed:
   83 |     class Solver
      |           ^~~~~~
/mnt/c/users/ofcra/dev/riversim/source/river/solver.hpp:83:11: error: use of deleted function ‘dealii::Triangulation<<anonymous>, <anonymous> >::Triangulation(const dealii::Triangulation<<anonymous>, <anonymous> >&) [with int dim = 2; int spacedim = 2]
In file included from /mnt/c/users/ofcra/dev/riversim/source/river/solver.hpp:29,
                 from /mnt/c/users/ofcra/dev/riversim/source/river/riversim.hpp:32,
                 from /mnt/c/users/ofcra/dev/riversim/source/app.hpp:3,
                 from /mnt/c/users/ofcra/dev/riversim/source/pythonapi.cpp:5:
/mnt/c/users/ofcra/lib/dealii_s_debug/include/deal.II/grid/tria.h:1563:3: note: declared here
 1563 |   Triangulation(const Triangulation<dim, spacedim> &) = delete;
      |   ^~~~~~~~~~~~~
In file included from /mnt/c/users/ofcra/dev/riversim/source/river/riversim.hpp:32,
                 from /mnt/c/users/ofcra/dev/riversim/source/app.hpp:3,
                 from /mnt/c/users/ofcra/dev/riversim/source/pythonapi.cpp:5:
/mnt/c/users/ofcra/dev/riversim/source/river/solver.hpp:83:11: error: use of deleted function ‘dealii::DoFHandler<dim, spacedim>::DoFHandler(const dealii::DoFHandler<dim, spacedim>&) [with int dim = 2; int spacedim = 2]’
   83 |     class Solver
      |           ^~~~~~
In file included from /mnt/c/users/ofcra/lib/dealii_s_debug/include/deal.II/dofs/dof_accessor.h:22,
                 from /mnt/c/users/ofcra/lib/dealii_s_debug/include/deal.II/fe/fe_values.h:30,
                 from /mnt/c/users/ofcra/dev/riversim/source/river/solver.hpp:39,
                 from /mnt/c/users/ofcra/dev/riversim/source/river/riversim.hpp:32,
                 from /mnt/c/users/ofcra/dev/riversim/source/app.hpp:3,
                 from /mnt/c/users/ofcra/dev/riversim/source/pythonapi.cpp:5:
/mnt/c/users/ofcra/lib/dealii_s_debug/include/deal.II/dofs/dof_handler.h:441:3: note: declared here
  441 |   DoFHandler(const DoFHandler &) = delete;
      |   ^~~~~~~~~~
make[2]: *** [source/CMakeFiles/riversimPY.dir/build.make:63: source/CMakeFiles/riversimPY.dir/pythonapi.cpp.o] Error 1
make[1]: *** [CMakeFiles/Makefile2:234: source/CMakeFiles/riversimPY.dir/all] Error 2
make: *** [Makefile:141: all] Error 2

Best, 
Oleg Kmechak

Oleg Kmechak

unread,
Jun 14, 2020, 9:09:51 PM6/14/20
to deal.II User Group
Looks like I got solution.

Problem is that Boost.Python is trying to construct some assignment operator (operator=). While it is trying to do this, its traping do deleted methods of DoFHandler and Triangulation. 
Solution(or workaround in my case) is to use option boost::noncopyable:
class_<River::Solver, boost::noncopyable>("Solver", init<River::Model*>(args("model")))
boost::copyable:
also it looks like there is possibility to overload asignment operator, but I didn't tryied it and it looks tricky.

Best, 
Oleg Kmechak 

Wolfgang Bangerth

unread,
Jun 14, 2020, 10:47:42 PM6/14/20
to dea...@googlegroups.com
On 6/14/20 7:09 PM, Oleg Kmechak wrote:
>             Solver(Model *model):
>                 dof_handler(triangulation)
>             {
>                 model = model;

Oleg,
I have not tried too carefully to look at what you're doing, but this line
doesn't look right. It is equivalent to
this->model = this->model;
which I don't think is what you want to do.

I should not that we occasionally use the following style in constructors:

Solver (Model *model)
: model (model)
{ ... }

which is initializing this->model with the given argument 'model'. But that
only works in the initializer list of a class.

You are correct that the error messages you see result from the fact that
somewhere in the Python interfaces, it is trying to create a copy
operator/constructor for the Model class, but that that doesn't exist because
the copy operations for Triangulation and DoFHandler are not allowed. That has
nothing to do with the issue above.

Best
W.

--
------------------------------------------------------------------------
Wolfgang Bangerth email: bang...@colostate.edu
www: http://www.math.colostate.edu/~bangerth/

Reply all
Reply to author
Forward
0 new messages