Python 电容放电-用复合函数解微分方程

Python 电容放电-用复合函数解微分方程,python,python-3.x,physics,differential-equations,Python,Python 3.x,Physics,Differential Equations,我是python新手。我试图在网上寻找解决我问题的方法,但没有找到。 我想解一个微分方程,求出电容器通过自身泄漏电流放电时,在时间V(t)内的电压。要求解的方程如下所示: dV(t)/dt=I(V)/C,V(0)=V_init 式中,I(V)是泄漏电流,它取决于电容器电压V。I有:泄漏电流作为电压、电容和初始条件的函数。对测量的泄漏电流进行插值,以获得V的平滑函数: def fitfunc(V, B, D, E): return B*(V**E)*exp(D*V) coeff_fit,

我是python新手。我试图在网上寻找解决我问题的方法,但没有找到。 我想解一个微分方程,求出电容器通过自身泄漏电流放电时,在时间V(t)内的电压。要求解的方程如下所示:

dV(t)/dt=I(V)/C,V(0)=V_init

式中,I(V)是泄漏电流,它取决于电容器电压V。I有:泄漏电流作为电压、电容和初始条件的函数。对测量的泄漏电流进行插值,以获得V的平滑函数:

def fitfunc(V, B, D, E):
    return  B*(V**E)*exp(D*V)
coeff_fit, coeffcov = scipy.optimize.curve_fit(fitfunc, forced_voltage, measured_current, p0=[1e-8, 1, 1], maxfev=50000)

V = numpy.linspace(0, 4, 100001)
I = coeff_fit[0] * (V**coeff_fit[2]) * exp(coeff_fit[1] * V)
C = 1e-9
V_init = 1
我在看scipy.integrate.odeint,但我不知道如何明确电流取决于电压而不是时间。 你能帮帮我吗?多谢各位

如果你把方程重新排列一下,你可以得到

因为C是常数

您现在可以将其集成

您可以使用
scipy.integrate
获取RHS

from scipy.integrate import quad
#define your I as a function of V
def I(V):
    return V
res, err = quad(f, 0, 2) #limits of your V
或者,如果要将给定数据用作数组,请使用

import scipy
res = scipy.integrate.simps(I,V) #I and V are the arrays of measured data

然后你可以使用res来得到V(t),然后设置V的初始值来得到常数。

我尝试在for循环中“手动”求解微分方程,但没有使用复杂的函数,结果比我想象的要简单。下面是我如何实现它的:

from numpy import asarray, argmin, linspace
from matplotlib.pyplot import semilogx, grid
def find_nearest(array, value):
    array = asarray(array)
    idx = (abs(array - value)).argmin()
    return idx

V_init = 1.0 # [V]
C = 1e-9 # [F]
max_time = 1e8
dt = 1000
time = linspace(0, max_time, int(max_time/dt))
V_t = [V_init]

for time_index, instant in enumerate(time):
    I_leak = I[find_nearest(V, V_t[time_index])]
    dV = -dt*I_leak/C
    V_t += [V_t[time_index] + dV]

semilogx(time, V_t[0:-1])
grid(True)

不过,我还是很好奇,是否有更干净的办法来解决这个问题。如果你有任何想法,请告诉我

谢谢你的帮助!但我想我的解释不清楚。我为V=numpy.linspace(0,2100)提供的示例就是我测量的每个泄漏电流点的外加电压。一旦我知道在任何外加电压下我有多少泄漏电流,然后我给电容器充电到一定的电压V_init,让它自己放电。我想知道电压在时间上是如何下降的。你的函数
I=I(V)
似乎只是作为数据给出的,即作为
V
的输入值和
I
的输出值的表格。如果是这样的话,那么可能首先你需要对它进行插值,至少得到一个连续函数
I=I(V)
,然后求解微分方程。是这样吗?谢谢你的输入,我现在正在做插值,我可以得到我想要的I(V)的任意多个点。那我该怎么做?你用的是什么插值方案?在此基础上,可以在两次测量之间精确地求解方程。或者,可以简单地应用类似于solve_ivp函数的东西。但在你的问题中加入你的插值方案是很重要的,这样其他人就可以决定建议什么了。我补充道:)谢谢!一般来说,你想做类似的事情吗?用odeint替换solve_ivp应该很容易,甚至可以简化一点代码。因此本质上,
I_leak=scipy.interpolate.interp1d(V,I)
V_t=odeint(lambda vt,t:-I_leak(vt)/C,V_init,time)
。谢谢你,它工作得很好,速度也很快!)我很好奇这是怎么回事:odeint怎么知道lambda中的“t”和最后一个参数“time”是同一回事?它怎么知道它是dV_t/dt而不是dV_t/dvt呢?第一个参数中的变量严格地是该参数的局部变量。对于ODE
dx/dt=f(x(t),函数的格式应为
f(x,t)
。不遵守这个命令会产生错误或奇怪的结果。请注意,所有其他scipy ODE积分器都使用切换参数顺序
f(t,x)
。我理解。非常感谢你!