在python中找到零交叉

时间:2019-05-09 18:23:12

标签: python ode odeint genfromtxt

我编写了以下代码,以查看我的ODE“ exponential_decay”在t中越过零线的情况。这是Brent Method

odr, hr, dr, cr, m = np.genfromtxt('data.txt',unpack=True)
n=0
with open('RDE_nob_trans.txt', 'w') as d:
  for i in range(len(dr)):
      c = cr[i]
      initp = dr[i]
      exponential_decay = lambda t, y: -(1/(1+t)) * (2 *(1-y)* (-2 + (y/c)) + 3 - 3 * y)
      t_span = [0, 1] # Interval of integration
      y0 = [initp] # Initial state: y(t=t_span[0])=2
      desired_answer = odr[i]
      sol_ode = solve_ivp(exponential_decay, t_span, y0) # IVP solution

      f_sol_ode = interp1d(sol_ode.t, sol_ode.y) # Build interpolated function
      ans = brentq(lambda x: f_sol_ode(x) - desired_answer, t_span[0], t_span[1])
      d.write("{0} {1} {2} {3} {4}\n".format(hr[i], dr[i], cr[i], m[i], ans))

在这段代码中,我们知道了起始点initp = dr[i],我们知道了零交点desired_answer = odr[i]处的微分方程的值,并且我们愿意找到在哪个t中这个答案。可以,我们通过此代码获得答案。 ans是过零处的t

我的问题是,如果我们现在对ODE的回答desired_answer = odr[i]不仅仅是一个数字,而是一个以t表示的值,我们应该怎么做。

我的意思是使用odr[i]我们正在读取数据文件,然后读取数字。现在考虑我们有类似odr = 0.1 * t, 0.12 *t, 0.23 *t etc.的东西,它不是数字,而是根据t的函数。

1 个答案:

答案 0 :(得分:1)

这不是solve_ivp界面的最有效使用。您可以使用event机制自动获得结果。

def event(t,y): return y-desired_answer;
event.terminal = True;

sol_ode = solve_ivp(exponential_decay, t_span, y0, events=event) # IVP solution
ans = sol_ode.t[-1]

即使您想使用自己的求解器(或求解器调用),也可以使用密集输出选项获得特定于方法的精确分段多项式插值,

sol_ode = solve_ivp(exponential_decay, t_span, y0, dense_output=True) # IVP solution
f_sol_ode = sol_ode.sol

要获取依赖于时间的函数的根,您只需编写与时间有关的代码,例如

def event(t,y): return y-0.23*t;

ans = brentq(lambda t: f_sol_ode(t) - 0.23*t, t_span[0], t_span[1])

如果要获得可靠的结果,则应显式控制公差atol, rtol