简体   繁体   English

Python - 使用带有 ODEINT 的克罗内克三角洲

[英]Python - Using a Kronecker Delta with ODEINT

I'm trying to plot the output from an ODE using a Kronecker delta function which should only become 'active' at a specific time = t1.我正在尝试使用 Kronecker delta function 从 ODE 中 plot output ,它应该只在特定时间变为“活动”。 This should give a sawtooth like response where the initial value decays down exponentially until t=t1 where it rises again instantly before decaying down once again.这应该给出一个锯齿状的响应,其中初始值呈指数衰减,直到 t=t1,在此它立即再次上升,然后再次衰减。 However, when I plot this it looks like the solver is seeing the Kronecker delta function as zero for all time t.然而,当我 plot 这看起来像求解器看到克罗内克三角洲 function 在所有时间 t 为零。 Is there anyway to do this in Python?无论如何在 Python 中这样做吗?

from scipy import KroneckerDelta
import scipy.integrate as sp
import matplotlib.pyplot as plt
import numpy as np

def dy_dt(y,t):

    dy_dt = 500*KroneckerDelta(t,t1) - 2y

return dy_dt

t1 = 4
y0 = 500
t = np.arrange(0,10,0.1)

y = sp.odeint(dy_dt,y0,t)

plt.plot(t,y)

I think the problem could be internal rounding errors, because 0.1 cannot be represented exactly as a python float .我认为问题可能是内部舍入错误,因为 0.1 不能完全表示为 python float I would try我会尝试

import math

def dy_dt(y,t): 
    if math.isclose(t, t1):
        return 500 - 2*y
    else:
        return -2y

Also the documentation of odeint suggests using the args parameter instead of global variables to give your derivative function access to additional arguments and replacing np.arange by np.linspace : odeint的文档还建议使用args参数而不是全局变量来让您的派生 function 访问额外的 arguments 并用np.arange替换np.linspace

import scipy.integrate as sp 
import matplotlib.pyplot as plt 
import numpy as np 
import math

def dy_dt(y, t, t1): 
    if math.isclose(t, t1):
        return 500 - 2*y
    else:
        return -2*y

t1 = 4 
y0 = 500 
t = np.linspace(0, 10, num=101) 
y = sp.odeint(dy_dt, y0, t, args=(t1,)) 
plt.plot(t, y)

I did not test the code so tell me if there is anything wrong with it.我没有测试代码,所以告诉我它是否有任何问题。


EDIT:编辑:

When testing my code I took a look at the t values for which dy_dt is evaluated.在测试我的代码时,我查看了评估dy_dtt值。 I noticed that odeint does not only use the t values that where specified, but alters them slightly:我注意到odeint不仅使用指定的t值,而且稍微改变了它们:

...
3.6636447422787928
3.743098503914526
3.822552265550259
3.902006027185992
3.991829287543431
4.08165254790087
4.171475808258308
...

Now using my method, we get现在使用我的方法,我们得到

math.isclose(3.991829287543431, 4) # False

because the default tolerance is set to a relative error of at most 10^(-9), so the odeint function "misses" the bump of the derivative at 4. Luckily, we can fix that by specifying a higher error threshold:因为默认容差设置为最多 10^(-9) 的相对误差,所以odeint function “错过”导数在 4 处的凸点。幸运的是,我们可以通过指定更高的错误阈值来解决这个问题:

def dy_dt(y, t, t1): 
    if math.isclose(t, t1, abs_tol=0.01):
        return 500 - 2*y
    else:
        return -2*y

Now dy_dt is very high for all values between 3.99 and 4.01.现在dy_dt对于 3.99 和 4.01 之间的所有值都非常高。 It is possible to make this range smaller if the num argument of linspace is increased.如果增加linspacenum参数,可以使这个范围更小。


TL;DR TL;博士

Your problem is not a problem of python but a problem of numerically solving an differential equation: You need to alter your derivative for an interval of sufficient length, otherwise the solver will likely miss the interesting spot.您的问题不是 python 的问题,而是数值求解微分方程的问题:您需要将导数更改为足够长的间隔,否则求解器可能会错过有趣的点。 A kronecker delta does not work with numeric approaches to solving ODEs. kronecker delta 不适用于求解 ODE 的数值方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM