Sympy:使用索引对象逐步计算ODE系统

2024-05-15 07:38:37 发布

您现在位置:Python中文网/ 问答频道 /正文

我目前想在sympy中实现一个Hammerstein模型。我现在为一个简单的系统创建了一个小示例:

import numpy as np
from sympy import *

####HAMMERSTEIN MODEL####
#time
t = symbols("t")

#inputs
u = symbols('u')

#states 
y = symbols('y',cls = Function, Function = True)

#init states
y_init =symbols('y_init')

#parameters
gain = 2 #symbols('gain')
time_constant = 20000#symbols('time_constant')


#EQUATIONS

#NONLINEAR STATIC PART 
u_nonlinear = u**2 # nonlinear input


#DYNAMIC PART
# first order system with inputs
rhe = (gain * u_nonlinear - y(t)) * 1/time_constant
ode = Eq(diff(y(t),t),rhe)

#solve equation
sol_step = dsolve(ode, ics = {y(0): y_init})
sol_step = sol_step.rhs

#lambdify (sympy)
system_step =lambdify((t,u, y_init),sol_step, 'sympy')


#####SIMULATE STEPWISE######
nr_steps = 10
dt=1
u_data =IndexedBase('u_data')
y_init_data =symbols('y_init_data')

#solution vector 
sol =[]

for i in range(nr_steps):

    #first sim. step
    if i == 0:
        sol.append(system_step(dt,u_data[i],y_init_data))

    #uses the states of prev. solution as inits
    else:
        sol.append(system_step(dt,u_data[i],sol[i-1]))

#convert
system=lambdify((u_data,y_init_data),sol, 'numpy')   


#EXAMPLE
t_obs = np.linspace(0,10,10)
u_obs = np.ones(10)* 40
x_obs_init =20

#RESULT
print(system(u_obs,x_obs_init))

正如你从例子中看到的,我一步一步地解决这个问题。我总是将Sympy函数对象称为“system\u step”。 对于较大的系统,性能不是特别好

但是,我也希望在一个scipy优化器中使用模拟,这会导致多次调用它,这极大地增加了解决方案的时间

我的问题是:

1.) 是否也可以使用sympy(例如索引对象)实现此逐步计算?是否可以避免循环中的重复计算

2.)如果是这样,如果输入变量(u)的长度应保持灵活,且不由使用硬代码的固定索引(m)指定,如何实现这一点(参见nr_步骤)

多谢各位


Tags: datatimeinitstepnpsystemgainsymbols
1条回答
网友
1楼 · 发布于 2024-05-15 07:38:37

谢谢你提供的信息。如果我用恒定的输入值计算ODE系统,我不需要一步一步地计算它。然后,解决过程非常快。因此,我的想法是使用向量或索引对象来建立系统,这可以防止分步计算

我的目标是:

  • 使用可变输入变量设置系统
  • 象征性地解决系统问题,即使需要很长时间
  • Lambdify和二进制文件中的存储
  • 对不同的操作使用已解决的系统

相关问题 更多 >