[英]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_dt
的t
值。 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.如果增加
linspace
的num
参数,可以使这个范围更小。
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.