2017-07-08 3 views
0

j'allais résoudre plusieurs équations différentielles de la matrice, de la forme d/dt (X) = F(X), où X est une grande matrice complexe et F représente une fonction de celui-ci. J'ai essayé d'utiliser de Boost odeint avec state_type comme cx_mat d'Armadillo. Mais il produit une erreur de compilation pour le type pas à pas contrôlé. Mon exemple de code est le suivantde cx_mat Armadillo et l'erreur de compilation odeint Boost

#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); 
} 

Ce code donne l'erreur de compilation suivante:

/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)); 

Ce que je peux comprendre que Armadillo ne supporte pas la copie d'une matrice réelle (mat) dans un complexe (cx_mat), comme

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

Ce qui se passe quelque part dans odeint. En ce moment, je suis en surmontant cela en copiant la matrice entière dans std::vector<std::complex<double> > le mettre dans la fonction ode, puis à l'intérieur de la fonction à nouveau copier std::vector<std::complex<double> > en cx_mat, calculer F(X), puis le copier dans std::vector<std::complex<double> > et retour. Évidemment, c'est très lent et inefficace.

Une solution simple au problème? Si possible, je peux vouloir passer à Eigen, si cela aide.

Répondre

0

Oui, les types d'état à valeur complexe ne fonctionnent pas bien avec les variables adaptatives car odeint ne fait pas la différence entre state_type et error_type. C'est à dire. il utilise aussi state_type pour stocker l'erreur, mais cela ne fonctionne pas pour les états state_types complexes, alors que l'erreur doit être une matrice à double valeur. Je ne sais pas si Eigen joue avec ça, mais ça vaut le coup d'essayer. N'hésitez pas à déposer un billet sur https://github.com/headmyshoulder/odeint-v2, mais ce sera un grand changement ...

+0

Eigen n'a pas aidé. Je pense que le problème réside dans odeint lui-même. –