C++11 自定义张量数据结构的boost::odeint输出错误

C++11 自定义张量数据结构的boost::odeint输出错误,c++11,boost,odeint,C++11,Boost,Odeint,根据@Piotr Skotnicki答案,我定义了以下数据类型: #ifndef TENSOR_HPP #define TENSOR_HPP #include <vector> #include <array> #include <boost/numeric/odeint.hpp> namespace nex { template <size_t...> struct seq {}; template <size_t N, size_t

根据@Piotr Skotnicki答案,我定义了以下数据类型:

#ifndef TENSOR_HPP
#define TENSOR_HPP

#include <vector>
#include <array>
#include <boost/numeric/odeint.hpp>

namespace nex {

template <size_t...> struct seq {};
template <size_t N, size_t... Is> struct gen_seq : gen_seq<N-1, N-1, Is...> {};
template <size_t... Is> struct gen_seq<0, Is...> { using type = seq<Is...>; };

template<typename T, typename S>
class tensor;

template<typename T, size_t... Is>
class tensor<T, seq<Is...>>
{

    typedef std::vector<T> vector;

public:

    // constructor
    tensor ();

    tensor (decltype(Is)...);

    // iterators
    using iterator       =  typename vector::iterator;
    using const_iterator =  typename vector::const_iterator;

    iterator begin()
    { return m_v.begin(); }

    const_iterator begin() const
    { return m_v.begin(); }

    iterator end() 
    { return m_v.end(); }

    const_iterator end() const
    { return m_v.end(); }

    // resizing
    size_t size() const; 

    void resize( const size_t  );

    // operators

    const T& operator() (decltype(Is)...) const;

    T& operator() (decltype(Is)...); 

private:

    // helper functions
    template <size_t I>
    auto index(const std::array<size_t, sizeof...(Is)>& a) const
    -> typename std::enable_if<I == 0, size_t>::type 
    {
        return a[I];
    }

    template <size_t I>
    auto index(const std::array<size_t, sizeof...(Is)>& a) const
    -> typename std::enable_if<I != 0, size_t>::type 
    {
        return index<I-1>(a) * s[I] + a[I];
    }

    size_t mult(size_t N) 
    {
        return N;
    }

    template <typename... S>
    size_t mult(size_t N, S... Ns) 
    {
        return N * mult(Ns...);
    }

    vector m_v;
    const std::array<size_t, sizeof...(Is)> s;

    }; // class tensor

 template<typename T, size_t... Is    
 tensor<T, seq<Is...>> :: tensor ()
   : m_v(), s{ { 0 } }
{}

template<typename T, size_t... Is>
tensor<T, seq<Is...>> :: tensor (decltype(Is)... size)
   : m_v( mult( size... ) ), s{ { size... } }
{}

template<typename T, size_t... Is>
size_t tensor<T, seq<Is...>> :: size () const 
{ return m_v.size(); }

template<typename T, size_t... Is>
void tensor<T, seq<Is...>> :: resize (const size_t n)
{ m_v.resize( n ); }

template<typename T, size_t... Is>
const T& tensor<T, seq<Is...>> :: operator() (decltype(Is)... n) const
{ return m_v.at(index<sizeof...(Is)-1>( { { n... } } ) ); }

template<typename T, size_t... Is>    
T& tensor<T, seq<Is...>> :: operator() (decltype(Is)... n) 
{ return m_v.at(index<sizeof...(Is)-1>( { { n... } } ) ); }

} // namespace nex

namespace boost { namespace numeric { namespace odeint {

template<typename T, size_t... Is>
struct is_resizeable< nex::tensor<T, nex::seq<Is...>> >
{
    typedef boost::true_type type;
    static const bool value = type::value;
};
} // namespace odeint
} // namespace numeric
} // namespace boost

template <typename T, std::size_t N>
using tensor = nex::tensor<T, typename nex::gen_seq<N>::type>;

#endif // TENSOR_HPP
\ifndef-TENSOR\u水电站
#定义张量
#包括
#包括
#包括
名称空间nex{
模板结构seq{};
模板结构gen_seq:gen_seq{};
模板结构gen_seq{using type=seq;};
模板
类张量;
模板
类张量
{
typedef std::向量;
公众:
//建造师
张量();
张量(decltype(Is)…);
//迭代器
使用迭代器=类型名向量::迭代器;
使用常量迭代器=类型名向量::常量迭代器;
迭代器begin()
{返回m_v.begin();}
常量迭代器begin()常量
{返回m_v.begin();}
迭代器结束()
{返回m_v.end();}
常量迭代器end()常量
{返回m_v.end();}
//调整大小
大小\u t大小()常量;
调整空隙大小(常数大小);
//操作员
常量T&运算符()(decltype(Is)…)常量;
运算符()(decltype(Is)…);
私人:
//辅助函数
模板
自动索引(const std::array&a)const
->typename std::enable_if::type
{
返回一个[I];
}
模板
自动索引(const std::array&a)const
->typename std::enable_if::type
{
回报指数(a)*s[I]+a[I];
}
尺寸多(尺寸N)
{
返回N;
}
模板
尺寸多(尺寸N,S…N)
{
返回N*mult(Ns…);
}
向量m_v;
常数std::数组s;
};//类张量
模板
{
typedef boost::true_类型;
静态常量布尔值=类型::值;
};
}//名称空间odeint
}//名称空间数字
}//名称空间提升
模板
使用张量=nex::张量;
#endif//TENSOR_水电站
然后我想在boost::odeint中使用这个数据类型来集成非常基本的问题

#include "tensor.hpp"

typedef tensor<double, 1> state_type;

void lorenz( const state_type &x , state_type &dxdt , const double t )
{

    dxdt(0) = x(0);
    dxdt(1) = x(1);
    dxdt(2) = x(2);
}

void write_lorenz( const state_type &x , const double t )
{
    std::cout << t << '\t' << x(0) << '\t' << x(1) << '\t' << x(2) << std::endl;
}


using namespace boost::numeric::odeint;

int main()
{
    state_type x(3);
    x(0) = 1.0 ; x(1) = 10.0 ; x(2) = 10.0;


    integrate_const( runge_kutta4< state_type >() , lorenz , x , 0.0 , 1.0 , 0.1, write_lorenz );
}
#包括“tensor.hpp”
typedef张量态_型;
void lorenz(常数状态类型&x,状态类型&dxdt,常数双t)
{
dxdt(0)=x(0);
dxdt(1)=x(1);
dxdt(2)=x(2);
}
无效写入_lorenz(常数状态_类型&x,常数双t)
{

std::cout事实上,问题在于调整大小。目前,调整张量的大小只会更改基础向量
m_v
的大小。虽然这可以确保正确的内存分配,但这是不够的。您还需要正确设置维度,即成员
s
。您也可以这样考虑:它是imp只要给定一个整数,就有可能调整多维张量的大小,您需要设置每个维度的大小。唯一的例外是一维张量,对于它,一切都很好,对于任何更高维度,这都是失败的

下面的tensor.hpp解决了这个问题,在我的快速测试中似乎运行良好:

#ifndef TENSOR_HPP
#define TENSOR_HPP

#include <vector>
#include <array>
#include <boost/numeric/odeint.hpp>

namespace nex {

template <size_t...> struct seq {};
template <size_t N, size_t... Is> struct gen_seq : gen_seq<N-1, N-1, Is...> {};
template <size_t... Is> struct gen_seq<0, Is...> { using type = seq<Is...>; };

template<typename T, typename S>
class tensor;

template<typename T, size_t... Is>
class tensor<T, seq<Is...>>
{

    typedef std::vector<T> vector;

public:

    // constructor
    tensor ();

    tensor (decltype(Is)...);

    // iterators
    using iterator       =  typename vector::iterator;
    using const_iterator =  typename vector::const_iterator;

    iterator begin()
    { return m_v.begin(); }

    const_iterator begin() const
    { return m_v.begin(); }

    iterator end() 
    { return m_v.end(); }

    const_iterator end() const
    { return m_v.end(); }

    // resizing
    size_t size() const; 

    void resize( const tensor<T, seq<Is...>>& );

    // operators

    const T& operator() (decltype(Is)...) const;

    T& operator() (decltype(Is)...); 

private:

    // helper functions
    template <size_t I>
    auto index(const std::array<size_t, sizeof...(Is)>& a) const
    -> typename std::enable_if<I == 0, size_t>::type 
    {
        return a[I];
    }

    template <size_t I>
    auto index(const std::array<size_t, sizeof...(Is)>& a) const
    -> typename std::enable_if<I != 0, size_t>::type 
    {
        return index<I-1>(a) * s[I] + a[I];
    }

    size_t mult(size_t N) 
    {
        return N;
    }

    template <typename... S>
    size_t mult(size_t N, S... Ns) 
    {
        return N * mult(Ns...);
    }

    vector m_v;
    std::array<size_t, sizeof...(Is)> s;

    }; // class tensor

    template<typename T, size_t... Is>
 tensor<T, seq<Is...>> :: tensor ()
        : m_v(), s{ { 0 } }
{}

template<typename T, size_t... Is>
tensor<T, seq<Is...>> :: tensor (decltype(Is)... size)
   : m_v( mult( size... ) ), s{ { size... } }
{}

template<typename T, size_t... Is>
size_t tensor<T, seq<Is...>> :: size () const 
{ return m_v.size(); }

template<typename T, size_t... Is>
void tensor<T, seq<Is...>> :: resize (const tensor<T, seq<Is...>> &x)
{ 
    m_v.resize( x.size() );
    s = x.s;
}

template<typename T, size_t... Is>
const T& tensor<T, seq<Is...>> :: operator() (decltype(Is)... n) const
{ return m_v.at(index<sizeof...(Is)-1>( { { n... } } ) ); }

template<typename T, size_t... Is>    
T& tensor<T, seq<Is...>> :: operator() (decltype(Is)... n) 
{ return m_v.at(index<sizeof...(Is)-1>( { { n... } } ) ); }

} // namespace nex

namespace boost { namespace numeric { namespace odeint {

template<typename T, size_t... Is>
struct is_resizeable< nex::tensor<T, nex::seq<Is...>> >
{
    typedef boost::true_type type;
    static const bool value = type::value;
};

template<typename T, size_t... Is>
struct resize_impl< nex::tensor<T, nex::seq<Is...>>, nex::tensor<T, nex::seq<Is...>> >
{
    typedef nex::tensor<T, nex::seq<Is...>> state_type;
    static void resize( state_type &x1 , const state_type &x2 )
    {
        x1.resize(x2);
    }
};

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

template <typename T, std::size_t N>
using tensor = nex::tensor<T, typename nex::gen_seq<N>::type>;

#endif // TENSOR_HPP
\ifndef-TENSOR\u水电站
#定义张量
#包括
#包括
#包括
名称空间nex{
模板结构seq{};
模板结构gen_seq:gen_seq{};
模板结构gen_seq{using type=seq;};
模板
类张量;
模板
类张量
{
typedef std::向量;
公众:
//建造师
张量();
张量(decltype(Is)…);
//迭代器
使用迭代器=类型名向量::迭代器;
使用常量迭代器=类型名向量::常量迭代器;
迭代器begin()
{返回m_v.begin();}
常量迭代器begin()常量
{返回m_v.begin();}
迭代器结束()
{返回m_v.end();}
常量迭代器end()常量
{返回m_v.end();}
//调整大小
大小\u t大小()常量;
空洞大小调整(常数张量&);
//操作员
常量T&运算符()(decltype(Is)…)常量;
运算符()(decltype(Is)…);
私人:
//辅助函数
模板
自动索引(const std::array&a)const
->typename std::enable_if::type
{
返回一个[I];
}
模板
自动索引(const std::array&a)const
->typename std::enable_if::type
{
回报指数(a)*s[I]+a[I];
}
尺寸多(尺寸N)
{
返回N;
}
模板
尺寸多(尺寸N,S…N)
{
返回N*mult(Ns…);
}
向量m_v;
std::数组s;
};//类张量
模板
张量::张量()
:m_v(),s{{0}
{}
模板
张量::张量(decltype(Is)…size)
:m_v(mult(size…),s{{size…}
{}
模板
大小张量::大小()常数
{返回m_v.size();}
模板
void张量::调整大小(常量张量和x)
{ 
m_v.resize(x.size());
s=x.s;
}
模板
常量T&tensor::operator()(decltype(Is)…n)常量
{返回m_v.at(索引({{n..}));}
模板
T&tensor::operator()(decltype(Is)…n)
{返回m_v.at(索引({{n..}));}
}//名称空间nex
名称空间boost{名称空间数值{名称空间odeint{
模板
结构可调整大小
{
typedef boost::true_类型;
静态常量布尔值=类型::值;
};
模板
struct resize_impl
{
typedef nex::张量状态_类型;
静态空洞大小调整(状态类型&x1,常量状态类型&x2)
{
x1.调整大小(x2);
}
};
}//名称空间odeint
}//名称空间数字
}//名称空间提升
模板
使用张量=nex::张量;
#endif//TENSOR_水电站

谢谢@mariomulansky!
#ifndef TENSOR_HPP
#define TENSOR_HPP

#include <vector>
#include <array>
#include <boost/numeric/odeint.hpp>

namespace nex {

template <size_t...> struct seq {};
template <size_t N, size_t... Is> struct gen_seq : gen_seq<N-1, N-1, Is...> {};
template <size_t... Is> struct gen_seq<0, Is...> { using type = seq<Is...>; };

template<typename T, typename S>
class tensor;

template<typename T, size_t... Is>
class tensor<T, seq<Is...>>
{

    typedef std::vector<T> vector;

public:

    // constructor
    tensor ();

    tensor (decltype(Is)...);

    // iterators
    using iterator       =  typename vector::iterator;
    using const_iterator =  typename vector::const_iterator;

    iterator begin()
    { return m_v.begin(); }

    const_iterator begin() const
    { return m_v.begin(); }

    iterator end() 
    { return m_v.end(); }

    const_iterator end() const
    { return m_v.end(); }

    // resizing
    size_t size() const; 

    void resize( const tensor<T, seq<Is...>>& );

    // operators

    const T& operator() (decltype(Is)...) const;

    T& operator() (decltype(Is)...); 

private:

    // helper functions
    template <size_t I>
    auto index(const std::array<size_t, sizeof...(Is)>& a) const
    -> typename std::enable_if<I == 0, size_t>::type 
    {
        return a[I];
    }

    template <size_t I>
    auto index(const std::array<size_t, sizeof...(Is)>& a) const
    -> typename std::enable_if<I != 0, size_t>::type 
    {
        return index<I-1>(a) * s[I] + a[I];
    }

    size_t mult(size_t N) 
    {
        return N;
    }

    template <typename... S>
    size_t mult(size_t N, S... Ns) 
    {
        return N * mult(Ns...);
    }

    vector m_v;
    std::array<size_t, sizeof...(Is)> s;

    }; // class tensor

    template<typename T, size_t... Is>
 tensor<T, seq<Is...>> :: tensor ()
        : m_v(), s{ { 0 } }
{}

template<typename T, size_t... Is>
tensor<T, seq<Is...>> :: tensor (decltype(Is)... size)
   : m_v( mult( size... ) ), s{ { size... } }
{}

template<typename T, size_t... Is>
size_t tensor<T, seq<Is...>> :: size () const 
{ return m_v.size(); }

template<typename T, size_t... Is>
void tensor<T, seq<Is...>> :: resize (const tensor<T, seq<Is...>> &x)
{ 
    m_v.resize( x.size() );
    s = x.s;
}

template<typename T, size_t... Is>
const T& tensor<T, seq<Is...>> :: operator() (decltype(Is)... n) const
{ return m_v.at(index<sizeof...(Is)-1>( { { n... } } ) ); }

template<typename T, size_t... Is>    
T& tensor<T, seq<Is...>> :: operator() (decltype(Is)... n) 
{ return m_v.at(index<sizeof...(Is)-1>( { { n... } } ) ); }

} // namespace nex

namespace boost { namespace numeric { namespace odeint {

template<typename T, size_t... Is>
struct is_resizeable< nex::tensor<T, nex::seq<Is...>> >
{
    typedef boost::true_type type;
    static const bool value = type::value;
};

template<typename T, size_t... Is>
struct resize_impl< nex::tensor<T, nex::seq<Is...>>, nex::tensor<T, nex::seq<Is...>> >
{
    typedef nex::tensor<T, nex::seq<Is...>> state_type;
    static void resize( state_type &x1 , const state_type &x2 )
    {
        x1.resize(x2);
    }
};

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

template <typename T, std::size_t N>
using tensor = nex::tensor<T, typename nex::gen_seq<N>::type>;

#endif // TENSOR_HPP