python - 如何在了解时间常数和稳态值的 gekko 中构建过程模拟器

标签 python process simulator gekko non-linear

我有一个非常复杂的非线性动力系统,我从 CFD(计算流体动力学)知道每个时间实例的时间常数和稳态响应。我如何 (1) 使用此信息构建流程模拟器? (2) 如果我知道测量的输入和输出以及稳态值,如何调整时间常数值?

最佳答案

问题 1:构建流程模拟器

您可能想首先尝试线性时间序列模型,如果不起作用,然后再尝试非线性模型。下面是一个用于识别线性时间序列模型的示例脚本。

Linear identification

from gekko import GEKKO
import pandas as pd
import matplotlib.pyplot as plt

# load data and parse into columns
url = 'http://apmonitor.com/do/uploads/Main/tclab_dyn_data2.txt'
data = pd.read_csv(url)
t = data['Time']
u = data[['H1','H2']]
y = data[['T1','T2']]

# generate time-series model
m = GEKKO(remote=False) # remote=True for MacOS

# system identification
na = 2 # output coefficients
nb = 2 # input coefficients
yp,p,K = m.sysid(t,u,y,na,nb,diaglevel=1)

plt.figure()
plt.subplot(2,1,1)
plt.plot(t,u)
plt.legend([r'$u_0$',r'$u_1$'])
plt.ylabel('MVs')
plt.subplot(2,1,2)
plt.plot(t,y)
plt.plot(t,yp)
plt.legend([r'$y_0$',r'$y_1$',r'$z_0$',r'$z_1$'])
plt.ylabel('CVs')
plt.xlabel('Time')
plt.savefig('sysid.png')
plt.show()

请注意,数据可以是动态数据,不一定分为稳态和动态部分。您需要调用m.sysid正确的输入为 detailed in the documentation 。一旦你有了一个好的模型,你可以使用 m.arx(p) 将其转换为模拟器。哪里pm.sysid 的参数输出功能。

如果线性识别不起作用,那么您可以尝试非线性方法,如 TCLab B Exercise (See Python Gekko Neural Network) 中所示。 。您可以使用Gekko's Deep Learning capabilities以简化编码。建立稳态关系后,使用微分方程添加一阶或二阶关系的动力学,该微分方程将稳态输出与动态输出相关联,例如 m.Equation(tau * x.dt() + x = x_ss)哪里tau是时间常数,x.dt()是时间导数,x是动态输出,x_ss是稳态输出。这称为 Hammerstein 模型,因为稳态先于动态计算。您还可以将动态作为维纳模型放在输入上。您可以在线找到有关 Hammerstein-Wiener 模型的更多信息。

问题 2:调整时间常数

如果您已经有了稳态关系并且想要调整时间常数,那么回归是一种强大的方法,因为它可以尝试时间常数的许多不同组合,以最小化模型之间的差异和测量。有几个使用 scipy.optimize.minimize 执行此操作的示例和 gekko .

Estimate Parameters with Python Gekko

import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
from gekko import GEKKO

# Import or generate data
filename = 'tclab_dyn_data2.csv'
try:
    data = pd.read_csv(filename)
except:
    url = 'http://apmonitor.com/do/uploads/Main/tclab_dyn_data2.txt'
    data = pd.read_csv(url)

# Create GEKKO Model
m = GEKKO()
m.time = data['Time'].values

# Parameters to Estimate
U = m.FV(value=10,lb=1,ub=20)
alpha1 = m.FV(value=0.01,lb=0.003,ub=0.03)  # W / % heater
alpha2 = m.FV(value=0.005,lb=0.002,ub=0.02) # W / % heater

# STATUS=1 allows solver to adjust parameter
U.STATUS = 1  
alpha1.STATUS = 1 
alpha2.STATUS = 1 

# Measured inputs
Q1 = m.MV(value=data['H1'].values)
Q2 = m.MV(value=data['H2'].values)

# State variables
TC1 = m.CV(value=data['T1'].values)
TC1.FSTATUS = 1    # minimize fstatus * (meas-pred)^2
TC2 = m.CV(value=data['T2'].values)
TC2.FSTATUS = 1    # minimize fstatus * (meas-pred)^2

Ta = m.Param(value=19.0+273.15)     # K
mass = m.Param(value=4.0/1000.0)    # kg
Cp = m.Param(value=0.5*1000.0)      # J/kg-K    
A = m.Param(value=10.0/100.0**2)    # Area not between heaters in m^2
As = m.Param(value=2.0/100.0**2)    # Area between heaters in m^2
eps = m.Param(value=0.9)            # Emissivity
sigma = m.Const(5.67e-8)            # Stefan-Boltzmann

# Heater temperatures in Kelvin
T1 = m.Intermediate(TC1+273.15)
T2 = m.Intermediate(TC2+273.15)

# Heat transfer between two heaters
Q_C12 = m.Intermediate(U*As*(T2-T1)) # Convective
Q_R12 = m.Intermediate(eps*sigma*As*(T2**4-T1**4)) # Radiative

# Semi-fundamental correlations (energy balances)
m.Equation(TC1.dt() == (1.0/(mass*Cp))*(U*A*(Ta-T1) \
                    + eps * sigma * A * (Ta**4 - T1**4) \
                    + Q_C12 + Q_R12 \
                    + alpha1*Q1))

m.Equation(TC2.dt() == (1.0/(mass*Cp))*(U*A*(Ta-T2) \
                    + eps * sigma * A * (Ta**4 - T2**4) \
                    - Q_C12 - Q_R12 \
                    + alpha2*Q2))

# Options
m.options.IMODE   = 5 # MHE
m.options.EV_TYPE = 2 # Objective type
m.options.NODES   = 2 # Collocation nodes
m.options.SOLVER  = 3 # IPOPT

# Solve
m.solve(disp=True)

# Parameter values
print('U     : ' + str(U.value[0]))
print('alpha1: ' + str(alpha1.value[0]))
print('alpha2: ' + str(alpha2.value[0]))

# Create plot
plt.figure()
ax=plt.subplot(2,1,1)
ax.grid()
plt.plot(data['Time'],data['T1'],'ro',label=r'$T_1$ measured')
plt.plot(m.time,TC1.value,color='purple',linestyle='--',\
         linewidth=3,label=r'$T_1$ predicted')
plt.plot(data['Time'],data['T2'],'bx',label=r'$T_2$ measured')
plt.plot(m.time,TC2.value,color='orange',linestyle='--',\
         linewidth=3,label=r'$T_2$ predicted')
plt.ylabel('Temperature (degC)')
plt.legend(loc=2)
ax=plt.subplot(2,1,2)
ax.grid()
plt.plot(data['Time'],data['H1'],'r-',\
         linewidth=3,label=r'$Q_1$')
plt.plot(data['Time'],data['H2'],'b:',\
         linewidth=3,label=r'$Q_2$')
plt.ylabel('Heaters')
plt.xlabel('Time (sec)')
plt.legend(loc='best')
plt.show()

关于python - 如何在了解时间常数和稳态值的 gekko 中构建过程模拟器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59075158/

相关文章:

Python 包文件夹结构

python - Github API,获取用 Python 语言编写的最受好评的公共(public)存储库

c++ - 如果在共享内存中,pthread 互斥锁是否可以跨线程工作?

iphone - Xcode - 如何获取 iPhone 11 模拟器进行开发?

simulator - 自动化 Blackberry 10 模拟器操作

python - 如何克服Python中的 "classmethod is not callable"

python - xlsxwriter 的 set_header 未按预期工作

ubuntu - docker daemon 没有在我的 ubuntu vm 中启动, "service start"ok by "ps"没有结果

c# - 如何使用c#关闭外部应用程序

iphone - 在模拟器中启动 iOS 应用程序时出现白色 View