2014-12-03 90 views
0

我使用odeint函數從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到最後,然後檢查是否滿足條件,但這當然不是很有效。

謝謝大家的幫助下, 尼古拉

回答

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來實現的。