c++ - Armadillo的cx_mat和Boost的odeint编译报错

标签 c++ c++11 boost armadillo odeint

我打算求解几个矩阵微分方程,形式为 d/dt (X) = F(X) , 其中X是一个大的复杂矩阵,F表示它的一些功能。我尝试将 Boost 的 odeintstate_type 一起使用作为 Armadillo 的 cx_mat .但它会为受控步进器类型产生编译错误。我的示例代码如下

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

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

using state_type = arma::cx_mat;


void ode(const state_type& X, state_type& derr, double) {
  derr =  X;  // sample derivative, can be anything else
}

// define resizable and norm_inf
namespace boost { namespace numeric { namespace odeint {

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

template <>
struct same_size_impl<arma::cx_mat, arma::cx_mat> {
    static bool same_size(const arma::cx_mat& x, const arma::cx_mat& y)
    {
      return arma::size(x) == arma::size(y);
    }
};

template<>
struct resize_impl<arma::cx_mat, arma::cx_mat> {
      static void resize(arma::cx_mat& v1, const arma::cx_mat& v2) {
      v1.resize(arma::size(v2));
    }
};


template<>
 struct vector_space_norm_inf<state_type> {
    typedef double result_type;
    result_type operator()(const state_type& p) const
    {
      return arma::norm(p, "inf");
    }
};



} } } // namespace boost::numeric::odeint





using stepper =  runge_kutta_dopri5<state_type, double, state_type, double, vector_space_algebra>;

int main () {

  cx_mat A = randu<cx_mat>(4, 4);


  integrate_adaptive( make_controlled<stepper>(1E-10, 1E-10),  ode, A, 0.0 , 10.0, 0.1);
}  

此代码给出以下编译错误:

/usr/include/armadillo_bits/Mat_meat.hpp:5153:3: error: static assertion failed: error: incorrect or unsupported type
   arma_type_check(( is_same_type< eT, typename T1::elem_type >::no ));

据我所知, Armadillo 不支持将真实矩阵(mat)复制到复杂矩阵(cx_mat)中,例如

mat Z = something;
cx_mat Y = Z;  // ERROR

这发生在 odeint 的某处。现在我通过将整个矩阵复制到 std::vector<std::complex<double> > 来克服这个问题将其放入函数ode , 然后在函数内部再次复制整个 std::vector<std::complex<double> >进入cx_mat , 计算 F(X) , 然后复制到 std::vector<std::complex<double> >并返回。显然,这是非常缓慢和低效的。

有什么简单的解决方法吗?? 如果可能的话,如果有帮助的话,我可能想转向 Eigen。

最佳答案

您好,我知道这已经很老了,但是当我遇到同样的问题时偶然发现它,我想分享我的解决方案。我使用了 Eigen,并添加了一些类似于 Armadillo 中的小部件,它对我有用(使用 icpc 和 g++ 测试编译)。 这里有一个最小的代码片段:

#include<Eigen/Eigen>
#include<boost/numeric/odeint.hpp>
#include<iostream>
#include<complex>
#include<boost/numeric/odeint/external/eigen/eigen_algebra.hpp>

typedef std::complex<double> cdoub;
typedef Eigen::MatrixXcd state_type;

namespace boost {
namespace numeric {
namespace odeint {

template<typename B,int S1,int S2,int O, int M1, int M2>
struct algebra_dispatcher< Eigen::Matrix<B,S1,S2,O,M1,M2> >
{
    typedef vector_space_algebra algebra_type;
};

template<>
 struct vector_space_norm_inf<state_type> {
    typedef double result_type;
    result_type operator()(const state_type& p) const
    {
      return p.lpNorm<Eigen::Infinity>();
    }
};
}}}

namespace Eigen {
template<typename D, int Rows, int Cols>
Matrix<D, Rows, Cols> operator/(const Matrix<D, Rows, Cols>& v1, const Matrix<D, Rows, Cols>& v2)
{
    return v1.array()/v2.array();
}   

template<typename D, int Rows, int Cols>
Matrix<D, Rows, Cols>
abs(Matrix<D, Rows, Cols> const& m) {
    return m.cwiseAbs();
}
}

/* The rhs of x' = f(x) */
void harmonic_oscillator( const state_type &x , state_type &dxdt , const double /* t */ )
{
    dxdt = x;
}
//]

int main() {
    using namespace boost::numeric::odeint;
    state_type X0(3,3);
    X0 = state_type::Random(3,3);
    state_type xout = X0;

    typedef runge_kutta_dopri5<state_type,double,state_type,double,vector_space_algebra> error_stepper_type;
    typedef controlled_runge_kutta< error_stepper_type > controlled_stepper_type;
    controlled_stepper_type controlled_stepper;

    double t =0.0;
    double dt = 0.1;

    controlled_stepper.try_step(harmonic_oscillator, X0, t, dt);

    std::cout << X0 << std::endl;
}

也许问题已经解决了,但是这里又出现了问题https://gist.github.com/jefftrull/5625b77c0f86c439f29f五天前我想分享它,希望它能有所帮助:)

关于c++ - Armadillo的cx_mat和Boost的odeint编译报错,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44987226/

相关文章:

c++ - 无法使用 FindWindowExA() 找到子窗口

c++ - 二进制文件格式与基于文本的格式文件大小

c++ - shared_ptr 无法解析

c++ - 将 std::complex 值的 boost::multi_array 复制到 mxArray

c++ - Boost wave上下文concept_check问题

C++ OpenGL SDL 屏幕问题

Android NDK clang 编译器找不到 std::make_unique

c++ - tbb parallel_reduce 用于 OpenMP 缩减的片段

c++ - 了解返回时的右值引用

c++ - 编译器忽略的函数模板特化