【发布时间】:2022-01-16 16:17:15
【问题描述】:
我正在开发一个建模函数来模拟火车的运动。在我的脚本中,我有一个运行函数三次的检查。第二次和第三次返回相同的值,但第一次返回不同的值。
dvdtA = lambda x, v: (1 / (Tmass + mw)) * (Ap * (rg / rw)) * (((P0gauge + Patm) * V0) / (V0 + (Ap * (rg / rw) * x)) - Patm) \
-0.5 * Cd * pa * A * (v**2) - (Cr * Tmass * g)
dvdtD = lambda v: (1 / Tmass) * (- 0.5 * Cd * pa * A * (v**2) - (Cr * Tmass * g))
dxdt = lambda v: v
Ft = lambda x: (1 / (Tmass + mw)) * (Ap * (rg / rw)) * (((P0gauge + Patm) * V0) / (V0 + (Ap * (rg / rw) * x)) - Patm)
trainMotion = np.array([dvdtA, dvdtD, dxdt, Ft])
# Checking design constraints ######################################
if (Ht < 0.23) and (Wt < 0.2) and (rg/rw < 1):
# Optimization #################################################
if RK4(trainMotion, h, tspan, v0, x0, La, slipCheck) is not None:
if RK4(trainMotion, h, tspan, v0, x0, La, slipCheck)[1] < tFinish:
bestParams = np.array([r0, P0gauge, rg, Ls, rp, tankMat])
bestODE = trainMotion
bestLa = La
bestSlipCheck = slipCheck
bestTime = RK4(trainMotion, h, tspan, v0, x0, La, slipCheck)[1]
这是在 for 循环中编写的,该循环随机选择一组参数,然后运行它们以生成您在开始时看到的 ODES。错误发生在“优化”区域下方。 RK4 上的第一次调用生成的结果集与第二次和第三次不同,它们都生成完全相同的结果。我不明白为什么第一次与第二次和第三次不同。 此外,当我稍后在脚本中再次将那些“最佳[ODE/LA/etc] 插入 RK4 函数时,尽管这些参数之前已通过检查,但检查失败并返回 None。
作为参考,这里是 RK4 函数本身:
import math as mt
import numpy as np
def RungeKutta(fun, h, tspan, x0, y0, Ls, slipCheck):
yArr = np.zeros([len(tspan), 2])
yArr[0,1] = y0
yArr[0,0] = x0
for i in range(len(tspan) - 1):
k1 = fun[2](yArr[i, 1])
k2 = fun[2](yArr[i, 1] + k1 * (h/2))
k3 = fun[2](yArr[i, 1] + k2 * (h/2))
k4 = fun[2](yArr[i, 1] + k3 * h)
yArr[i+1, 0] = yArr[i, 0] + h * (k1/6 + k2/3 + k3/3 + k4/6)
if (fun[3](yArr[i+1, 0]) > slipCheck) or (yArr[i+1, 0] > 12.5):
return None
if yArr[i, 0] <= Ls:
k1 = fun[0](yArr[i, 0], yArr[i, 1])
k2 = fun[0](yArr[i, 0] + h/2, yArr[i, 1] + k1 * (h/2))
k3 = fun[0](yArr[i, 0] + h/2, yArr[i, 1] + k2 * (h/2))
k4 = fun[0](yArr[i, 0] + h, yArr[i, 1] + k3 * h)
yArr[i+1, 1] = yArr[i, 1] + h * (k1/6 + k2/3 + k3/3 + k4/6)
elif yArr[i, 0] > Ls:
k1 = fun[1](yArr[i, 1])
k2 = fun[1](yArr[i, 1] + k1 * (h/2))
k3 = fun[1](yArr[i, 1] + k2 * (h/2))
k4 = fun[1](yArr[i, 1] + k3 * h)
yArr[i+1, 1] = yArr[i, 1] + h * (k1/6 + k2/3 + k3/3 + k4/6)
if i >= 3:
if yArr[i+1, 1] < 0 and yArr[i+1, 0] > 10:
tFinish = tspan[i]
data = np.column_stack((yArr, tspan))
return data, tFinish
return None
【问题讨论】:
-
为什么要计算3次(不是真的最优),计算一次并使用3次结果,为什么不返回
(None.None),RK4总是返回2项,否则return np.column_stack((yArr, tspan)), tspan[i] -
不是所有的除法
/,而是将其转换为*,这样更快,至少在C++中,也许python语句的执行速度比/慢 -
你有没有为每次运行转储
yArr的中间结果并比较它们的不同之处,然后找出原因 -
我是否正确理解您在每次迭代中重新创建 lambda 语句?这种东西很难调试。我会推荐
def在循环之前使用相应参数的函数,以避免通过优化意外更改变量,这可能是可变数据结构的情况。 -
在 for 循环的每次迭代中都会重新创建 lambda 语句,但是这里调用了 3 次函数,它使用 lambda 函数而不重写它们。 @JonathanWeine