2016-07-27 8 views
1

私は現在、クラス内で微分方程式を解くためにgsl_odeiv2メソッドを使用しています。しかし、よく知られているメンバ関数の問題のため、私はクラスの中で私のode-systemを定義することはできません。私は現在、回避策を使用しています: 私はグローバル名前空間で私のODEを定義します。gsl_odeiv2 in C++クラス:int(...)のテンプレートラッパーode

ODE.hpp: 
#include "EoS.hpp" 

#include <gsl/gsl_math.h> 
#include <gsl/gsl_errno.h> 

namespace ODEs 
{ 
    struct tov_eq_params {EoS *eos;}; 
    int tov_eq(double, const double *, double *, void *); 
} 

ODE.cpp: 
namespace ODEs { 
    int tov_eq(double r, const double *PM, double *dPdM, void *p) { 
     struct tov_eq_params * params = (struct tov_eq_params *)p; 
     EoS *eos = (params->eos); 
     ... 
    return GSL_SUCCESS 
    } 
} 

、パラメータとしてcoustomタイプ(クラスEOS)のオブジェクトへのポインタを使用します。私が使用している教材を解くクラスの中で私は以下を使用します:

... 
struct tov_eq_params comp_tov_params = {(this->star_eos)}; 
gsl_odeiv2_evolve *comp_tov_evolve = gsl_odeiv2_evolve_alloc(3); 
gsl_odeiv2_system comp_tov_system = {tov_eq, NULL, 3,&comp_tov_params}; 
... 

私のシステムをinitaliseする:これはうまくいきますが、グローバルな名前空間で微分方程式を宣言する必要があるため、ちょっと混乱します。

gsl_functions stackoverflow.com/questions/.../how-to-avoid-static-member-function-when-using-gsl-with-c/...にテンプレートラッパーを使用して、C++クラスでそれらを使用できることがわかっています。私は実際にそこに記述されているラッパーを使用して、クラス内のgsl_integrationメソッドの関数を定義し、完全に動作し、書くのがはるかにクリーンでコードも少なくなっています。例えば:私は私のstar_eosは、関数の内部で上記直接使うからオブジェクトを使用することができます:私はint型(ダブルR、constのダブル*のPM、このようなテンプレートのラッパーを記述しようとした

auto dBf = [=](double r)->double{ 
     return 4 * M_PI * gsl_pow_2(r) * (this->star_eos)->nbar(this->P(r)) * sqrt(this->expLambda(r))* 1e54; 
    }; 
    gsl_function_pp<decltype(dBf)> dBfp(dBf); 
    gsl_function *dB = static_cast<gsl_function*>(&dBfp); 

ダブル* dPdM、void *型のp )関数はgsl_odeiv2_systemが必要ですが、私はC++を初めて使っていて、テンプレート/ static_castメカニズムを完全に理解していないため失敗しました。

gsl_odeivメソッドとそのodeシステムをテンプレートラッパーとともに使用する人がいますか?あるいは、gsl_functionsで説明したものと似たテンプレートをint(...)odeで作ることができます。

答えて

0

グローバルな名前空間に設定された微分方程式をどのように扱うのか考えてみると、私の問題の解決策が見つかりました。私は今、ワーキングラッパーを持っています。だから私はbassicallyので、システムの寸法とポインタを指定するための薄暗いint型を持ってode_System私の新しいクラスに保存されているすべての私の具体的な情報を、持っている

//gsl_wrapper.hpp 
#include <iostream> 
#include <vector> 
#include <functional> 

#include <gsl/gsl_math.h> 
#include <gsl/gsl_errno.h> 

namespace gsl_wrapper { 

    class ode_System{ 
    public: 
     ode_System(int); 
     int dim; 
     std::function<double (double, const double *, double *, int)> *df; 

    }; 

    struct ode_struct {ode_System *ode;}; 
    int ode(double, const double *, double *, void *); 
} 

//gsl_wrapper.cpp 
#include "../../include/gsl_wrapper.hpp" 

namespace gsl_wrapper { 

    ode_System::ode_System(int dim) { 
     this->dim=dim; 
    } 

    int ode(double r, const double *f, double *df, void *p) { 
     struct ode_struct * params = (struct ode_struct *)p; 
     ode_System *odeFunc = (params->ode); 

     int dim = odeFunc->dim; 
     std::function<double (double, const double *, double *, int)> dfeq=*(odeFunc->df); 

     for(int i=0;i<dim;i++){ 
      df[i] = dfeq(r,f,df,i); 
     } 

     return GSL_SUCCESS; 
    } 

}; 

:グローバル名前空間では、私は以下の持っていますstd :: functionオブジェクトです。このオブジェクトは、数学微分方程式系を表します。

私はgsl_odeiv2を使用して微分方程式を解決したい私のクラス、内部では、私はラムダ関数を使用して、そのシステムを定義します。

std::function<double (double, const double *, double *, int)> dPMeq = [=](double r , const double * PM, double *dPdM, int i)->double{ 
    double df; 
    switch (i) 
    { 
     case 0: 
      df = ... // df_1/dr 
      break; 
     case 1: 
      df = ... // df_2/dr 
      break; 
     case 2: 
      df = ... // df_3/dr 
      break; 
     default: 
      GSL_ERROR_VAL ("comp_tov_eq:", GSL_FAILURE,GSL_FAILURE); 
      df = 0; 
    } 
    return df; 
}; 

を上記のシステムは、3つの微分方程式の結合系を表しています。次に適切な次元のode_Systemオブジェクトを宣言し、関数ポインタdfを定義済みのシステムに設定します。そして、私はそのシステムを基準とした構造を必要として行わ:私はgsl_odeiv2_systemで私のクラス内で定義された私の微分方程式を使用することができます(私の知る限り、これは同じようにうまく機能言うことができるように

ode_System tov(3); 
tov.df= &dPMeq; 
struct ode_struct comp_tov_params = {&tov}; 
gsl_odeiv2_evolve *comp_tov_evolve = gsl_odeiv2_evolve_alloc(3); 
gsl_odeiv2_system comp_tov_system = {ode, NULL, 3, &comp_tov_params}; 
... 

をか私の質問で提示した実装と同じです。それはいくつかのクリーンアップを使用することができますが、原則としてこれは私のために正常に動作します。

しかし、誰かがこれを行うより良い方法を知っている場合は、お気軽に共有してください!