簡體   English   中英

用Python和Euler公式求解非線性方程組

[英]Solving system of nonlinear equations with Python, Euler's formula

我正在研究和分析Python中的微分方程組。 首先,我是在scipy.integrate dopri5和范圍Odeint的幫助下解決它的。 算好了。 然后,我嘗試使用歐拉方法求解方程。 等式和代碼如下,

dj = -mu*(J**3 - (C - C0)*J - F)

dc = J + C*F + a*J**2

df = J*F - C



T = 100
dt = 0.001
t = np.linspace(0, T, int(T/dt)+1)
j = np.zeros(len(t))
c = np.zeros(len(t))
f = np.zeros(len(t))

# Initial condition
j[0] = 0.1
c[0] = -0.5
f[0] = 0.1

a = 0.3025
C0 = 0.5
mu = 50

for i in range(len(t)):
    j[i+1] = j[i] + (-mu * (j[i]**3 - (c[i] - C0)*j[i] - f[i]))*dt
    c[i+1] = c[i] + (j[i] + c[i] * f[i] + (a * j[i])**2)*dt
    f[i+1] = f[i] + (j[i] * f[i] - c[i])*dt

當其他兩種方法都不能使用時,為什么沒有歐拉方法不起作用?

在第一次迭代中, i為0,循環的第一行實際上是:

j[0] = j[-1] + (-mu * (j[-1]**3 - (c[-1] - C0)*j[-1] - f[-1]))*dt

j[-1]是最后一個元素j ,就像c[-1]是最后一個元素c等最初它們是全零,所以j[0]變為0,同樣,這將覆蓋初始條件。 要解決此問題,請將range(len(t))更改為range(1,len(t)) (無論如何,模型在前9200個步驟后會發散。)

正如DYZ所說,您的計算在第一次循環迭代中是不正確的,因為j[-1]j最后一個元素,您已將其初始化為零。

但是,您的代碼浪費了很多RAM。 我假設您只想包含T結果加上初始值的數組,而不是每個步驟都計算出的結果。 下面的代碼通過double for循環實現了這一目標。 在這段代碼中,我們實際上並沒有從Numpy中獲得任何好處,因此,我不必理會它的導入。

需要注意的是歐拉積分不是很准確,你通常需要使用步長小於所需條件通過更復雜的積分算法。 正如DYZ所提到的,在當前步長的情況下,計算在循環結束之前會有所不同。

這是使用較小步長的代碼的修改版本。

T = 100
dt = 0.00001
steps = int(T / dt)
substeps = int(steps / T)

# Recalculate `dt` to compensate for possible truncation 
# in the `steps` and `substeps` calculations
dt = 1.0 / substeps
print('steps, substeps, dt:', steps, substeps, dt)

a = 0.3025
C0 = 0.5
mu = 50

#dj = -mu*(J**3 - (C - C0)*J - F)
#dc = J + C*F + a*J**2
#df = J*F - C

# Initial condition
j = 0.1
c = -0.5
f = 0.1

jlst, clst, flst = [j], [c], [f]
for i in range(T):
    for _ in range(substeps):
        j1 = j + (-mu * (j**3 - (c - C0)*j - f))*dt
        c1 = c + (j + c * f + (a * j)**2)*dt
        f1 = f + (j * f - c)*dt
        j, c, f = j1, c1, f1

    jlst.append(j)
    clst.append(c)
    flst.append(f)

def round_seq(seq, places=6):
    return [round(u, places) for u in seq]

print('j:', round_seq(jlst), end='\n\n')
print('c:', round_seq(clst), end='\n\n')
print('f:', round_seq(flst), end='\n\n')

輸出

steps, substeps, dt: 10000000 100000 1e-05
j: [0.1, 0.585459, 1.26718, 3.557956, -1.311867, -0.647698, -0.133683, 0.395812, 0.964856, 3.009683, -2.025674, -1.047722, -0.48872, 0.044296, 0.581284, 1.245423, 14.725407, -1.715456, -0.907364, -0.372118, 0.167733, 0.705257, 1.511711, -3.588555, -1.476817, -0.778593, -0.253874, 0.289294, 0.837128, 1.985792, -2.652462, -1.28088, -0.657113, -0.132971, 0.409071, 0.983504, 3.229393, -2.1809, -1.113977, -0.539586, -0.009829, 0.528546, 1.156086, 8.23469, -1.838582, -0.967078, -0.423261, 0.113883, 0.650319, 1.381138, 12.045565, -1.575015, -0.833861, -0.305952, 0.23632, 0.778052, 1.734888, -2.925769, -1.362437, -0.709641, -0.186249, 0.356775, 0.917051, 2.507782, -2.367126, -1.184147, -0.590753, -0.063942, 0.476121, 1.07614, 5.085211, -1.976542, -1.029395, -0.474206, 0.059772, 0.596505, 1.273214, 17.083466, -1.682855, -0.890842, -0.357555, 0.182944, 0.721096, 1.554496, -3.331861, -1.450497, -0.763182, -0.239007, 0.30425, 0.85435, 2.076595, -2.584081, -1.258788, -0.642362, -0.117774, 0.423883, 1.003181, 3.521072, -2.132709, -1.094792, -0.525123]

c: [-0.5, -0.302644, 0.847742, 12.886781, 0.177404, -0.423405, -0.569541, -0.521669, -0.130084, 7.97828, -0.109606, -0.363033, -0.538874, -0.61005, -0.506872, 0.05076, 216.678959, -0.198445, -0.408569, -0.566869, -0.603713, -0.451729, 0.58959, 2.252504, -0.246645, -0.451, -0.588697, -0.587898, -0.375758, 2.152898, -0.087229, -0.295185, -0.49006, -0.603411, -0.562389, -0.263696, 8.901196, -0.132332, -0.342969, -0.525087, -0.609991, -0.526417, -0.077251, 67.082608, -0.177771, -0.389092, -0.555341, -0.607658, -0.47794, 0.293664, 147.817033, -0.225425, -0.432796, -0.579951, -0.595996, -0.412269, 1.235928, -0.037058, -0.273963, -0.473412, -0.597912, -0.574782, -0.318837, 4.581828, -0.113301, -0.3222, -0.51029, -0.608168, -0.543547, -0.172371, 24.718184, -0.157526, -0.369151, -0.542732, -0.609811, -0.500922, 0.09504, 291.915024, -0.204371, -0.414, -0.56993, -0.602265, -0.443622, 0.700005, 0.740665, -0.25268, -0.456048, -0.590933, -0.585265, -0.36427, 2.528225, -0.093699, -0.301181, -0.494644, -0.60469, -0.558516, -0.245806, 10.941068, -0.137816, -0.348805, -0.52912]

f: [0.1, 0.68085, 1.615135, 1.01107, -2.660947, -0.859348, -0.134789, 0.476782, 1.520241, 4.892319, -9.514924, -2.041217, -0.61413, 0.060247, 0.792463, 2.510586, 11.393914, -6.222736, -1.559576, -0.438133, 0.200729, 1.033274, 3.348756, -39.664752, -4.304545, -1.201378, -0.282146, 0.349631, 1.331995, 4.609547, -20.169056, -3.104072, -0.923759, -0.138225, 0.513633, 1.716341, 6.739864, -11.717002, -2.307614, -0.699883, 7.4e-05, 0.700823, 2.22957, 11.017447, -7.434886, -1.751919, -0.512171, 0.138566, 0.922012, 2.9434, -30.549886, -5.028825, -1.346261, -0.348547, 0.282981, 1.19254, 3.987366, -26.554232, -3.566328, -1.0374, -0.200198, 0.439487, 1.535198, 5.645421, -14.674838, -2.619369, -0.792589, -0.060175, 0.615387, 1.985246, 8.779969, -8.991742, -1.972575, -0.590788, 0.077534, 0.820118, 2.599728, 8.879606, -5.928246, -1.509453, -0.417854, 0.218635, 1.066761, 3.477148, -36.053938, -4.124934, -1.163178, -0.263755, 0.369033, 1.37438, 4.811848, -18.741635, -2.987496, -0.893457, -0.120864, 0.535433, 1.771958, 7.117055, -11.027021, -2.227847, -0.674889]

在我的舊2GHz機器上,這大約需要75秒。

使用dt = 0.000005 (在這台機器上花費將近2分鍾的時間), jcf的最終值分別為-0.524774,-0.529217和-0.674293,因此看來我們開始趨於收斂。


感謝LutzL指出,由於stepssubsteps計算中的舍入, dt可能需要調整。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM