Odeint 错误:使用已删除的函数‘boost::numeric::odeint::state_wrapper<State<3>&, void>::state_wrapper()’

问题描述 投票:0回答:1

我正在尝试利用 Odeint 和 Eigen 用 C++ 编写一个通用积分器,但我一直在努力让 Odeint 对继承自 Eigen 的自定义状态向量类感到满意。为了提供最小的可重现代码,首先我要定义我的自定义向量类,这实际上是从我的项目复制粘贴的:

#include <boost/numeric/odeint.hpp>
#include <eigen3/Eigen/Dense>
#include <functional>
#include <iostream>
#include <vector>

using namespace Eigen;
namespace odeint = boost::numeric::odeint;

template <size_t N>
using VReal = Eigen::Vector<double, N>;
using VReal3 = VReal<3>;

template <size_t N>
class State : public Eigen::Vector<double, 2 * N> {
   private:
    double t = 0;

   public:
    /////////////////////// Constructors ///////////////////////
    ///                                                      ///

    // default constructor
    State() : Eigen::Vector<double, 2 * N>() { this->setZero(); }
    // constructor with constant value
    State(const double val) : Eigen::Vector<double, 2 * N>() {
        this->setConstant(val);
    }
    // Constructor with initializer list
    State(std::initializer_list<double> init_list)
        : Eigen::Vector<double, 2 * N>() {
        assert(init_list.size() ==
               2 * N);  // Ensure the initializer list is the correct size
        int i = 0;
        for (double val : init_list) {
            (*this)[i++] = val;
        }
    }
    // Constructor with VReal of 2N elements
    State(const Eigen::Vector<double, 2 * N>& vec)
        : Eigen::Vector<double, 2 * N>(vec) {}

    // Constructor with 2 VReal of N rows
    State(VReal<N> head, VReal<N> tail) {
        this->template head<N>() = head;
        this->template tail<N>() = tail;
    }

    // move constructor
    State(State&& other) noexcept
        : Eigen::Vector<double, 2 * N>(std::move(other)) {
        t = other.t;
    }
    // copy constructor
    State(const State& other)
        : Eigen::Vector<double, 2 * N>(other), t(other.t) {}
    ///                                                       ///
    ////////////////////////////////////////////////////////////

    /////////////////////////// Operators ///////////////////////////
    ///                                                           ///

    // operator=
    State& operator=(const State& other) {
        if (this != &other) {
            this->Eigen::Vector<double, 2 * N>::operator=(other);
            t = other.t;
        }
        return *this;
    }
    // move operator=
    State& operator=(State&& other) noexcept {
        if (this != &other) {
            this->Eigen::Vector<double, 2 * N>::operator=(std::move(other));
            t = other.t;
        }
        return *this;
    }
    // Copy with Eigen::Matrix
    State& operator=(
        const Eigen::Matrix<double, 2 * N, 1, 0, 2 * N, 1>& other) {
        Eigen::Vector<double, 2 * N>::operator=(other);
        return *this;
    }

    //// Operators (+=, -=, *=, /=) for State (scalar) and State (vector)
    ////

    // Vectorial
    State operator+(const State& other) {
        return State(this->Eigen::Vector<double, 2 * N>::operator+(other));
    }
    State& operator+=(const State& other) {
        this->Eigen::Vector<double, 2 * N>::operator+=(other);
        return *this;
    }
    State& operator-(const State& other) {
        return State(this->Eigen::Vector<double, 2 * N>::operator-(other));
    }
    State& operator-=(const State& other) {
        this->Eigen::Vector<double, 2 * N>::operator-=(other);
        return *this;
    }

    // Scalar
    State& operator*(const double scalar) {
        return State(this->Eigen::Vector<double, 2 * N>::operator*(scalar));
    }
    State& operator*=(const double scalar) {
        this->Eigen::Vector<double, 2 * N>::operator*=(scalar);
        return *this;
    }

    State& operator/(const double scalar) {
        return State(this->Eigen::Vector<double, 2 * N>::operator/(scalar));
    }
    State& operator/=(const double scalar) {
        this->Eigen::Vector<double, 2 * N>::operator/=(scalar);
        return *this;
    }
    // Vector product
    State& operator*(const State& other) {
        return State(this->Eigen::Vector<double, 2 * N>::operator*(other));
    }
    State& operator*=(const State& other) {
        this->Eigen::Vector<double, 2 * N>::operator*=(other);
        return *this;
    }
    ///                                                            ///
    //////////////////////////////////////////////////////////////////

    /////////////////////////// Methods ///////////////////////////

    VReal<N> X() const { return this->template head<N>(); }
    VReal<N> X_dot() const { return this->template tail<N>(); }
};

还有更多的类来执行集成步骤,这些类遵循与我的项目相同的理念,但它们是最小的,并且您在这里看到的一些奇怪的选择在整个代码中是有意义的:

template <size_t N>
class Model {
    // Ballistic model without drag force
   private:
   public:
    Model() {}
    void operator()(const State<N>& x, State<N>& dxdt, double t) {
        dxdt.X() = x.X_dot();
        dxdt.X_dot() = Eigen::Vector<double, N>::Zero();
    }
};

template <size_t N>
class RK4Stepper {
   public:
    RK4Stepper() {}
    ~RK4Stepper() {}

    void do_step(Model<N> h, State<N>& in, double t, State<N>& out, double dt) {
        stepper.do_step(h, in, t, out, dt);
    }

   private:
    odeint::runge_kutta4<State<N>&, double, State<N>&, double,
                         odeint::vector_space_algebra>
        stepper;
};

template <size_t N>
class Sim {
   private:
    RK4Stepper<N> stepper;

   public:
    Sim() {}
    void run(Model<N> h, State<N> S0) {
        std::cout << "Sim::run() called" << std::endl;
        // std::reference_wrapper<Model<N>> h_ref = *h;

        for (int i = 0; i < 10; i++) {
            std::cout << "i = " << i << std::endl;

            State<N> S1;
            stepper.do_step(h, S0, 0.0, S1, 0.1);

            S0 = S1;
        }
    }
};

这是主要功能:

int main() {
    Model<3> model;

    Sim<3> sim;
    sim.run(model, State<3>(Eigen::Vector3d(1.0, 2.0, 3.0),
                            Eigen::Vector3d(4.0, 5.0, 6.0)));

    return 0;
}

现在,如果我尝试编译这些,我会收到以下错误:

In file included from /usr/include/boost/numeric/odeint/stepper/runge_kutta4.hpp:27,
                 from /usr/include/boost/numeric/odeint.hpp:29,
                 from main.cpp:2:
/usr/include/boost/numeric/odeint/stepper/explicit_generic_rk.hpp: In instantiation of ‘boost::numeric::odeint::explicit_generic_rk<StageCount, Order, State, Value, Deriv, Time, Algebra, Operations, Resizer>::explicit_generic_rk(const coef_a_type&, const coef_b_type&, const coef_c_type&, const algebra_type&) [with long unsigned int StageCount = 4; long unsigned int Order = 4; State = State<3>&; Value = double; Deriv = State<3>&; Time = double; Algebra = boost::numeric::odeint::vector_space_algebra; Operations = boost::numeric::odeint::default_operations; Resizer = boost::numeric::odeint::initially_resizer; coef_a_type = boost::fusion::vector<const boost::array<double, 1>, const boost::array<double, 2>, const boost::array<double, 3> >; coef_b_type = boost::array<double, 4>; coef_c_type = boost::array<double, 4>; algebra_type = boost::numeric::odeint::vector_space_algebra]’:
/usr/include/boost/numeric/odeint/stepper/runge_kutta4.hpp:141:81:   required from ‘boost::numeric::odeint::runge_kutta4<State, Value, Deriv, Time, Algebra, Operations, Resizer>::runge_kutta4(const algebra_type&) [with State = State<3>&; Value = double; Deriv = State<3>&; Time = double; Algebra = boost::numeric::odeint::vector_space_algebra; Operations = boost::numeric::odeint::default_operations; Resizer = boost::numeric::odeint::initially_resizer; algebra_type = boost::numeric::odeint::vector_space_algebra]’
main.cpp:154:18:   required from ‘RK4Stepper<N>::RK4Stepper() [with long unsigned int N = 3]’
main.cpp:173:11:   required from ‘Sim<N>::Sim() [with long unsigned int N = 3]’
main.cpp:192:12:   required from here
/usr/include/boost/numeric/odeint/stepper/explicit_generic_rk.hpp:141:64: error: use of deleted function ‘boost::numeric::odeint::state_wrapper<State<3>&, void>::state_wrapper()’
  141 |     : stepper_base_type( algebra ) , m_rk_algorithm( a , b , c )
      |                                                                ^
In file included from /usr/include/boost/numeric/odeint/util/ublas_wrapper.hpp:33,
                 from /usr/include/boost/numeric/odeint.hpp:25:
/usr/include/boost/numeric/odeint/util/state_wrapper.hpp:36:8: note: ‘boost::numeric::odeint::state_wrapper<State<3>&, void>::state_wrapper()’ is implicitly deleted because the default definition would be ill-formed:
   36 | struct state_wrapper
      |        ^~~~~~~~~~~~~
/usr/include/boost/numeric/odeint/util/state_wrapper.hpp:36:8: error: uninitialized reference member in ‘struct boost::numeric::odeint::state_wrapper<State<3>&, void>’
/usr/include/boost/numeric/odeint/util/state_wrapper.hpp:40:7: note: ‘State<3>& boost::numeric::odeint::state_wrapper<State<3>&, void>::m_v’ should be initialized
   40 |     V m_v;
      |       ^~~
/usr/include/boost/numeric/odeint/stepper/explicit_generic_rk.hpp:141:64: error: use of deleted function ‘boost::numeric::odeint::state_wrapper<State<3>&, void>::state_wrapper()’
  141 |     : stepper_base_type( algebra ) , m_rk_algorithm( a , b , c )
      |                                                                ^
/usr/include/boost/numeric/odeint/stepper/explicit_generic_rk.hpp:141:64: error: use of deleted function ‘boost::numeric::odeint::state_wrapper<State<3>&, void>::state_wrapper()’
In file included from /usr/include/boost/numeric/odeint/stepper/euler.hpp:23,
                 from /usr/include/boost/numeric/odeint.hpp:27:
/usr/include/boost/numeric/odeint/stepper/base/explicit_stepper_base.hpp: In instantiation of ‘boost::numeric::odeint::explicit_stepper_base<Stepper, Order, State, Value, Deriv, Time, Algebra, Operations, Resizer>::explicit_stepper_base(const algebra_type&) [with Stepper = boost::numeric::odeint::explicit_generic_rk<4, 4, State<3>&, double, State<3>&, double, boost::numeric::odeint::vector_space_algebra, boost::numeric::odeint::default_operations, boost::numeric::odeint::initially_resizer>; short unsigned int Order = 4; State = State<3>&; Value = double; Deriv = State<3>&; Time = double; Algebra = boost::numeric::odeint::vector_space_algebra; Operations = boost::numeric::odeint::default_operations; Resizer = boost::numeric::odeint::initially_resizer; algebra_type = boost::numeric::odeint::vector_space_algebra]’:
/usr/include/boost/numeric/odeint/stepper/explicit_generic_rk.hpp:141:64:   required from ‘boost::numeric::odeint::explicit_generic_rk<StageCount, Order, State, Value, Deriv, Time, Algebra, Operations, Resizer>::explicit_generic_rk(const coef_a_type&, const coef_b_type&, const coef_c_type&, const algebra_type&) [with long unsigned int StageCount = 4; long unsigned int Order = 4; State = State<3>&; Value = double; Deriv = State<3>&; Time = double; Algebra = boost::numeric::odeint::vector_space_algebra; Operations = boost::numeric::odeint::default_operations; Resizer = boost::numeric::odeint::initially_resizer; coef_a_type = boost::fusion::vector<const boost::array<double, 1>, const boost::array<double, 2>, const boost::array<double, 3> >; coef_b_type = boost::array<double, 4>; coef_c_type = boost::array<double, 4>; algebra_type = boost::numeric::odeint::vector_space_algebra]’
/usr/include/boost/numeric/odeint/stepper/runge_kutta4.hpp:141:81:   required from ‘boost::numeric::odeint::runge_kutta4<State, Value, Deriv, Time, Algebra, Operations, Resizer>::runge_kutta4(const algebra_type&) [with State = State<3>&; Value = double; Deriv = State<3>&; Time = double; Algebra = boost::numeric::odeint::vector_space_algebra; Operations = boost::numeric::odeint::default_operations; Resizer = boost::numeric::odeint::initially_resizer; algebra_type = boost::numeric::odeint::vector_space_algebra]’
main.cpp:154:18:   required from ‘RK4Stepper<N>::RK4Stepper() [with long unsigned int N = 3]’
main.cpp:173:11:   required from ‘Sim<N>::Sim() [with long unsigned int N = 3]’
main.cpp:192:12:   required from here
/usr/include/boost/numeric/odeint/stepper/base/explicit_stepper_base.hpp:94:42: error: use of deleted function ‘boost::numeric::odeint::state_wrapper<State<3>&, void>::state_wrapper()’
   94 |     : algebra_stepper_base_type( algebra )
      |                                          ^

现在,我明白了编译器想要告诉我的内容。 Odeint 无法弄清楚如何消化我的自定义 State 类,并且不知道如何对其执行代数运算。但正如在这个答案中一样,我认为我需要做的就是在步进器模板定义中指定 vector_space_algebra ,但这显然不起作用。那么我应该怎么做才能让 Odeint 对我的自定义课程感到满意呢?

c++ eigen odeint
1个回答
0
投票

根据@chtz 评论,更改

odeint::runge_kutta4<State<N>&, double, State<N>&, double, odeint::vector_space_algebra> stepper;

odeint::runge_kutta4<State<N>, double, State<N>, double, odeint::vector_space_algebra> stepper;

修复了错误。 谢谢你@chtz<3

© www.soinside.com 2019 - 2024. All rights reserved.