1

私は scipy.integrate パッケージの odeint 関数を使用しています:

r0 = np.array([1,2,3,4])
t=np.linspace(0,1,20)
def drdt(r,t):
    return r # or whatever else
r = odeint(drdt,r0,t)

r0 は、特定の数のポイントの初期位置を含む numpy 配列です。スクリプトの最後に、予想どおり、20 タイムステップでポイントの位置を取得します。

ここで、r の条件が満たされたときに odeint ソルバーを停止したいと思います。特に、これらのポイントの 2 つが特定のしきい値よりも近い場合に odeint を停止し、r ベクトルにいくつかの変更を加え、新しい初期位置で odeint ソルバーを続行したいと考えています。これを実装する方法はありますか?

私が考えている可能な解決策は、odeint を最後まで実行し、後で条件が満たされているかどうかを確認することですが、これはもちろんあまり効率的ではありません。

助けてくれてありがとう、ニコラ

4

1 に答える 1

1

C++の答えがあります。投稿するのに最適な場所ではないかもしれませんが、それでも興味深いかもしれません。(これを配置するのに適した場所が見つかりませんでした。これは、C++ ソリューションを探しているときに着陸した場所です)。

以下は、変数がゼロ以下になったときに統合を停止する C++ の例です。

#include <iostream>
#include <boost/range/algorithm.hpp>
#include <boost/numeric/odeint.hpp>

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


typedef double state_type;

typedef runge_kutta_cash_karp54< state_type > error_stepper_type;


class Myode{
public:
  void operator()(const state_type& x, state_type& dxdt, const double t){dxdt=-1-x;}
  static bool done(const state_type &x){return x<=0.0;}
};

int main(int argc, char* argv[]){
   Myode ode;
   state_type x=10.0;
   auto stepper =  make_controlled< error_stepper_type >( 1.0e-10 , 1.0e-6 );
   auto iter= boost::find_if(make_adaptive_range(stepper,ode,x, 0.0 , 20.0 , 0.01 ),
                 Myode::done);

   cout<<"integration stopped at"<<x<<endl;
  return 1;
}

積分は、ゼロ以下の値 x に初めて達したときに停止します (done 関数を参照)。そのため、現在のステップ サイズによっては、ゼロをはるかに下回る可能性があります。

これは c++11 コンストラクトを使用するため、コンパイラでこれを有効にする必要があることに注意してください。私の場合 (gcc 4.4) は、コンパイル コマンドに -std=gnu++0x を追加することで達成されました。

于 2015-03-23T16:42:11.590 に答える