просто для объяснения вашего существующего кода каждая итерация решателя 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
et c.
другой вариант - использовать что-то вроде namedtuple
s для однократного сохранения ваших параметров. это упростило бы сохранение значений параметров вне исходного кода, что может быть желательным свойством
не совсем уверен, для чего нужны ваши параметры M
и u
, но я бы хотел настроить их таким же образом. например, передать их в make_3DOF_oscillator(M[i,:])
, что делает его доступным в fn
, или сохранить как переменную-член в конструкторе Oscillator3DOF
. в этих случаях вам нужно создать объекты в пределах for i
l oop, чтобы он получил доступ к нужному