python - 在迭代调用的函数中存储和加载参数的有效方法
问题描述
我一直在研究需要模拟系统的问题。我已经剥离了我写的相关代码,只写了对这个问题很重要的部分。
def oscillatorParams():
K1,K2,K3 = 1e5,1e6,1e2
B1,B2,B3 = 100,100,100
a1,a2,a3 = 1,1,1
b1,b2,b3 = 1,1,1
I1,I2,I3 = 1000,10000,20000
return K1,K2,K3,B1,B2,B3,a1,a2,a3,b1,b2,b3,I1,I2,I3
def ode_3DOF_oscillator(state,t, u):
K1, K2, K3, B1, B2, B3, a1, a2, a3, b1, b2, b3, I1, I2, I3 = oscillatorParams()
..equations for the odesolver..
return [omega[0],omega[1],omega[2],dw1dt,dw2dt,dw3dt]
def runSim(u,dt,T):
t=np.arange(0,T,dt) ; N=len(t)
for i in range(0, N ):
if i==N-1 or i==N:
tt = [t[i], t[i]] # [t1 t2]
else:
tt = [t[i], t[i+1]] # [t1 t2]
x=odeint(ode_3DOF_oscillator,x0,tt,args=(M[i,:],))
return t,y1,y2,y3
我没有很强的编程背景,我对如何以最佳方式实现参数感到困惑。我更愿意将参数存储在某处以使其易于编辑,因为我可能会在多个其他文件中使用这些函数,但我假设此函数将继续为每个 ode_3DOF_oscillator(state,t,u) 调用分配参数。有没有更好的方法来解决这个问题?
解决方案
只是为了解释您现有的代码,ODE 求解器 Python 的每次迭代都必须:
ode_3DOF_oscillator
立即调用的调用oscillatorParams
- 局部变量被设置为您的参数变量
- 局部变量变成元组并且函数返回
- 返回的元组被解包到一组局部变量中以供以后使用
- 其余代码运行,直到它返回结果
假设你很高兴在源代码中硬编码参数值,我会做类似的事情:
def make_3DOF_oscillator():
K1,K2,K3 = 1e5,1e6,1e2
B1,B2,B3 = 100,100,100
a1,a2,a3 = 1,1,1
b1,b2,b3 = 1,1,1
I1,I2,I3 = 1000,10000,20000
def fn(state, t, u):
# ..equations for the odesolver..
return [omega[0],omega[1],omega[2],dw1dt,dw2dt,dw3dt]
return fn
def runSim(u,dt,T):
myfn = make_3DOF_oscillator()
t=np.arange(0,T,dt) ; N=len(t)
for i in range(0, N ):
if i==N-1 or i==N:
tt = [t[i], t[i]] # [t1 t2]
else:
tt = [t[i], t[i+1]] # [t1 t2]
x=odeint(myfn, x0,tt,args=(M[i,:],))
return t,y1,y2,y3
这会带来良好的性能,因为参数可以作为局部变量直接在函数中使用fn
(与稍微慢一些的全局变量相反)。参数也只设置一次,而不是每一步。
否则,假设性能不是问题并且您不介意输入更多内容,则可以使用类:
class Oscillator3DOF:
def __init__(self):
self.K1, self.K2, self.K3 = 1e5,1e6,1e2
self.B1, self.B2, self.B3 = 100,100,100
self.a1, self.a2, self.a3 = 1,1,1
self.b1, self.b2, self.b3 = 1,1,1
self.I1, self.I2, self.I3 = 1000,10000,20000
def deriv(self, y, t, u):
# ..equations for the odesolver..
return [omega[0],omega[1],omega[2],dw1dt,dw2dt,dw3dt]
def runSim(u,dt,T):
system = Oscillator3DOF()
t=np.arange(0,T,dt) ; N=len(t)
for i in range(0, N ):
if i==N-1 or i==N:
tt = [t[i], t[i]] # [t1 t2]
else:
tt = [t[i], t[i+1]] # [t1 t2]
x=odeint(system.deriv, x0,tt,args=(M[i,:],))
return t,y1,y2,y3
请注意,deriv
将访问参数self.K1
等。
另一种选择是使用类似namedtuple
s 的东西来存储你的参数一次。这将更容易将参数值保存在源代码之外,这可能是一个理想的属性
不太确定您的M
和u
参数的用途,但我很想以相同的方式设置它们。例如,将它们传递给make_3DOF_oscillator(M[i,:])
使其在 中可用fn
,或将其保存为 的构造函数中的成员变量Oscillator3DOF
。在这些情况下,您希望在for i
循环中创建对象,以便它可以访问正确的东西
推荐阅读
- python - 如何将图像划分为大小均匀、需要时重叠的图块?
- algorithmic-trading - 风险管理:如果已经做多,请不要下新订单
- c# - Math.Log 的舍入行为
- android - 如何为 VideoView 添加字幕?
- javascript - 使用 html 和 javascript 显示来自 json 文件的多个“块”数据
- angular - Angular 抛出错误“无法遵循符号链接”
- react-native - 在 react-native 中获取主包中图像的文件路径
- php - 通过 Wordpress rest api 下载的 Excel 文件已损坏
- prolog - Prolog 前身数学
- javascript - 使用 Await 读取异步对象集