C++ Armadillo与Boost Odeint冲突:Odeint在集成期间将状态向量调整为零

C++ Armadillo与Boost Odeint冲突:Odeint在集成期间将状态向量调整为零,c++,c++11,boost,armadillo,C++,C++11,Boost,Armadillo,我刚刚开始使用boostodeint来集成一个ODE系统。为了方便起见,我想把它与犰狳一起使用,因为这两个都是现代的C++库,使用方便的API。但是,如果我将arma::vec指定为状态类型,那么在集成的第一步,integrate\u adaptive()会立即将状态向量调整为0x1。我在这里发布了一个简单的例子: #include <iostream> #include <armadillo> #include <boost/numeric/odeint.hpp

我刚刚开始使用boostodeint来集成一个ODE系统。为了方便起见,我想把它与犰狳一起使用,因为这两个都是现代的C++库,使用方便的API。但是,如果我将
arma::vec
指定为状态类型,那么在集成的第一步,
integrate\u adaptive()
会立即将状态向量调整为
0x1
。我在这里发布了一个简单的例子:

#include <iostream>
#include <armadillo>

#include <boost/numeric/odeint.hpp>

using namespace std;
using namespace arma;
using namespace boost::numeric::odeint;

typedef vec state_type;

class harm_osc
{
    private:
    mat my_A;

    public:
        harm_osc(double gam)
        {
            my_A = { {0.0, 1.0}, {-gam*gam, 0.0} };
        }

        harm_osc()
        {
            my_A = { {0.0, 1.0}, {-1.0, 0.0} };
        }

        void operator() (const vec& x, vec& dxdt, const double t)
        {
            cout << "size of x: " << size(x) << endl;
            cout << "size of dxdt: " << size(dxdt) << endl;
            dxdt = my_A*x;
        }
};

class observer
{
    private:
        mat& my_states;
        vec& my_times;                        

    public:
        observer(mat& states, vec& times):
            my_states(states),
            my_times(times)
        {}    

        void operator() (const vec& x, double t)
        {
            my_states.insert_rows(my_states.n_rows, x);
            my_times.insert_rows(my_times.n_rows, t);
            cout << t << '\t';
            for(auto elem : x)
                cout << elem << '\t';
            cout << endl;
        }
};

typedef runge_kutta_cash_karp54<state_type> error_stepper_type;
typedef controlled_runge_kutta<error_stepper_type> controlled_stepper_type;

int main()
{
    state_type x = {0.0, 1.0};

    vec t;
    mat x_full;

    integrate_adaptive(make_controlled<error_stepper_type>(1e-5, 1e-5), harm_osc(1.0), x, 0.0, 200.0, 0.01, observer(x_full, t));
}
#包括
#包括
#包括
使用名称空间std;
使用arma;
使用名称空间boost::numeric::odeint;
类型定义向量状态_类型;
等级伤害(osc)
{
私人:
垫子;
公众:
harm_osc(双gam)
{
my_A={{0.0,1.0},{-gam*gam,0.0};
}
harm_osc()
{
my_A={{0.0,1.0},{-1.0,0.0};
}
void运算符()
{

coutOdeint在内部存储多个中间状态。在您的情况下,我认为它不知道如何正确调整中间状态的大小。这可以通过引入正确的调整大小适配器轻松解决:

namespace boost { namespace numeric { namespace odeint {

template <>
struct is_resizeable<arma::vec>
{
    typedef boost::true_type type;
    const static bool value = type::value;
};

template <>
struct same_size_impl<arma::vec, arma::vec>
{
    static bool same_size(const arma::vec& x, const arma::vec& y)
    {
        return x.size() == y.size();   // or use .n_elem attributes
    }
};

template<>
struct resize_impl<arma::vec, arma::vec>
{
    static void resize(arma::vec &v1, const arma::vec& v2)
    {
        v1.resize(v2.size());     // not sure if this is correct for arma
    }
};

} } } // namespace boost::numeric::odeint
namespace boost{namespace numeric{namespace odeint{
模板

struct是可调整大小的

对标准示例()稍加调整,就可以得到一个工作代码:

#include <boost/numeric/odeint.hpp>
#include <armadillo>
#include <iostream>

namespace boost { 
namespace numeric { 
namespace odeint {

template<>
struct is_resizeable< arma::vec >
{
 typedef boost::true_type type;
 static const bool value = type::value;
};

} } }

typedef arma::vec state_type;

void lorenz( const state_type &x , state_type &dxdt , const double t )
{
const double sigma( 10.0 );
const double R( 28.0 );
const double b( 8.0 / 3.0 );

dxdt[0] = sigma * ( x[1] - x[0] );
dxdt[1] = R * x[0] - x[1] - x[0] * x[2];
dxdt[2] = -b * x[2] + x[0] * x[1];
}

using namespace boost::numeric::odeint;

int main()
{
state_type x(3);
x[0] = 5.0 ; x[1] = 10.0 ; x[2] = 10.0;

// make sure resizing is ON
BOOST_STATIC_ASSERT( is_resizeable<state_type>::value == true );
// no further work is required
std::cout << "initial x : " << x << std::endl; 
integrate_const( runge_kutta4< state_type >() , lorenz , x , 
0.0 , 10.0 , 0.1 );
std::cout << "final x : " << x << std::endl;
return 0; 
}
#包括
#包括
#包括
名称空间提升{
名称空间数字{
名称空间odeint{
模板
结构可调整大小
{
typedef boost::true_类型;
静态常量布尔值=类型::值;
};
} } }
typedef arma::vec state_type;
void lorenz(常数状态类型&x,状态类型&dxdt,常数双t)
{
恒双西格玛(10.0);
常数双R(28.0);
常数双b(8.0/3.0);
dxdt[0]=sigma*(x[1]-x[0]);
dxdt[1]=R*x[0]-x[1]-x[0]*x[2];
dxdt[2]=-b*x[2]+x[0]*x[1];
}
使用名称空间boost::numeric::odeint;
int main()
{
状态_类型x(3);
x[0]=5.0;x[1]=10.0;x[2]=10.0;
//确保“调整大小”处于启用状态
BOOST\u STATIC\u ASSERT(可调整大小::value==true);
//不需要进一步的工作
标准::cout