Как применить мертвое время из модели FOPDT к управляемой переменной в MPC gekko

Я пытаюсь построить модель MPC с предварительно оцененными значениями k, tau и theta в уравнении FOPDT. Я реализовал это предложение для оценки мертвого времени с помощью cspline: Как оценить значение тета в уравнении FOPDT с помощью gekko?.

Однако я не могу сделать то же самое с MPC, потому что я не могу использовать MV в качестве второго аргумента cspline для применения мертвого времени. Если вместо этого я использую переменную gekko для этого второго аргумента, MV не меняются, потому что они не присутствуют в уравнении. У меня есть две MV, одна CV и две возмущающие переменные. Как в этом случае применить мертвое время? Спасибо

import numpy as np
import time
import plotly.express as px 
from gekko import GEKKO
import json
from datetime import datetime

start_time_count = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
print("start_time: ", start_time_count)

dist1 = d19jcSliceMPC['Cond_PID_SP'].values
mv1 = d19jcSliceMPC['Front_PID_PV'].values
mv2 = d19jcSliceMPC['Rear_PID_PV'].values
dist2 = d19jcSliceMPC['Pull_rolling'].values
cv1 = d19jcSliceMPC['Cond_Center_Btm_TC'].values

run_time = 3.0 * 60.0 
n = int(0.2*run_time)

Tsp1 = 1163.0 #setpoint

m = GEKKO(name='MPCbtmTC',remote=False)
m.time = np.linspace(0,n-1,n)
time_uc = m.Param(m.time)

# MV
Front = m.MV(value=mv1)
Front_ss = m.Param(value=mv1[0])
KpFront = m.Param(value=1.685312)
tauFront = m.Param(value=5.770839)
thetaFront = m.Param(value=0.114705)
t1 = np.linspace(-1,n-1,n)
ucFront = m.Var(); tm1 = m.Var(); m.Equation(tm1==time_uc-thetaFront)
m.cspline(tm1,ucFront,t1,np.array(Front),bound_x=False)

Rear = m.MV(value=mv2)
Rear_ss = m.Param(value=mv2[0])
KpRear = m.Param(value=0.1)
tauRear = m.Param(value=36.0)
thetaRear = m.Param(value=3.779397)
t2 = np.linspace(-4,n-1,n)
ucRear = m.Var(); tm2 = m.Var(); m.Equation(tm2==time_uc-thetaRear)
m.cspline(tm2,ucRear,t2,np.array(Rear),bound_x=False)

Front.STATUS = 1  # use to control temperature
Front.FSTATUS = 0 # no feedback measurement
Front.LOWER = 1160.0
Front.UPPER = 1200.0
Front.DMAX = 2.0
Front.COST = 0.0
Front.DCOST = 1.0e-4

Rear.STATUS = 1  # use to control temperature
Rear.FSTATUS = 0 # no feedback measurement
Rear.LOWER = 1180.0
Rear.UPPER = 1220.0
Rear.DMAX = 2.0
Rear.COST = 0.0
Rear.DCOST = 1.0e-4

# Parameters (disturbance)
CondSP = m.Param(value=dist1)
CondSP_ss = m.Param(value=dist1[0])
KpCondSP = m.Param(value=4.990293)
tauCondSP = m.Param(value=29.272660)
thetaCondSP = m.Param(value=2.554230)
t3 = np.linspace(-3,n-1,n)
ucCondSP = m.Var(); tm3 = m.Var(); m.Equation(tm3==time_uc-thetaCondSP)
m.cspline(tm3,ucCondSP,t3,dist1,bound_x=False)

Pull = m.Param(value=dist2)
Pull_ss = m.Param(value=dist2[0])
KpPull = m.Param(value=0.151304)
tauPull = m.Param(value=4.128567)
thetaPull = m.Param(value=0.0)
t4 = np.linspace(-0,n-1,n)
ucPull = m.Var(); tm4 = m.Var(); m.Equation(tm4==time_uc-thetaPull)
m.cspline(tm4,ucPull,t4,dist2,bound_x=False)

# Controlled variable
TC1_ss = m.Param(value=cv1[0])
TC1 = m.CV(value=TC1_ss.value)
TC1.STATUS = 1     # minimize error with setpoint range
TC1.FSTATUS = 1    # receive measurement
TC1.TR_INIT = 2    # reference trajectory
TC1.TAU = 2       # time constant for response

# Equation
m.Equation(TC1.dt()==(KpFront*(ucFront-Front_ss)-(TC1-TC1_ss))/tauFront + (KpRear*(ucRear-Rear_ss)-(TC1-TC1_ss))/tauRear+ 
                     (KpCondSP*(ucCondSP-CondSP_ss)-(TC1-TC1_ss))/tauCondSP + (KpPull*(ucPull-Pull_ss)-(TC1-TC1_ss))/tauPull)

# Global Options
m.options.IMODE   = 6 # MPC
m.options.CV_TYPE = 1 # Objective type
m.options.NODES   = 3 # Collocation nodes
m.options.SOLVER  = 1 # 1=APOPT, 3=IPOPT

TC1.MEAS = cv1[0]
# input setpoint with deadband +/- DT
DT = 0.1
TC1.SPHI = Tsp1 + DT
TC1.SPLO = Tsp1 - DT
# solve MPC
m.solve(disp=False)    
# get additional solution information
with open(m.path+'//results.json') as f:
    results = json.load(f)

finish_time_count = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
print("end_time: ", finish_time_count)

df_plot = pd.DataFrame({'DateTime' : d19jcSliceMPC.time,
                        'CV (TC1)' : results['v9.bcv'],
                        'SPHI' : results['v9.sp_hi'],
                        'SPLO' : results['v9.sp_lo'],
                        'Front' : Front,
                        'Rear' : Rear})
figGekko = px.line(df_plot, 
                   x='DateTime',
                   y=['CV (TC1)','SPHI','SPLO','Front','Rear'],
                   labels={"value": "Degrees Celsius"},
                   title = "MPC")
figGekko.update_layout(legend_title_text='')
figGekko.show()

Изменить:

Как и было предложено, я изменил на

ucFront = m.Var(); m.Equation(ucFront==Front) 
tm1 = m.Var(); m.Equation(tm1==time_uc-thetaFront)
m.cspline(tm1,ucFront,t1,np.array(Front),bound_x=False)

но я получаю эту ошибку:

Error: Exception: Access Violation
At line 359 of file ./f90/cqp.f90
Traceback: not available, compile with -ftrace=frame or -ftrace=full

Error: 'results.json' not found. Check above for additional error details

Если я оставлю только MV в качестве несмещенного ввода, я получу ту же ошибку, что и раньше

TypeError: y_data must be a python list or numpy array

person Daniel Baptista    schedule 15.12.2020    source источник
comment
Даниэль, я думаю, вы можете представить еще один набор клипов GEKKO MV для несмещенных входов. Например, в m.cspline (смещенное время, смещенный ввод, несмещенное время, несмещенный ввод) установите смещенные аргументы как переменные Gekko (m.Var) и установите несмещенные входные данные как Gekko MV, которые вы оставили их как не-Gekko. переменные в вашем коде.   -  person Junho Park    schedule 15.12.2020


Ответы (1)


Как правильно заметил Джунхо Парк, вы можете создать другую переменную x, например:

MV = m.MV()  # use MV in MPC application

x  = m.Var() # use x with cspline function
m.Equation(x==MV) # connect x and MV

Объект cspline жалуется на MV, потому что ему нужна вычисляемая переменная вместо типа, который по умолчанию является фиксированным и потребляет определенную степень свободы.

person John Hedengren    schedule 16.12.2020
comment
Спасибо за ваш ответ. Проблема все еще не решена, пожалуйста, проверьте правку моего вопроса. - person Daniel Baptista; 17.12.2020
comment
Похоже, возникла проблема с решателем APOPT. Не могли бы вы вместо этого попробовать решатель IPOPT с m.options.SOLVER=3. Я не могу воспроизвести ошибку, потому что у меня нет файлов данных. - person John Hedengren; 17.12.2020
comment
Я получил Exception: @error: Solution Not Found. Кроме того, в обоих случаях MV сохраняют начальные значения, а переменные, используемые с cspline, установлены на 0. - person Daniel Baptista; 17.12.2020
comment
И с m.solve(disp=True) я получил вот эту причину ошибки EXIT: Converged to a point of local infeasibility. Problem may be infeasible. An error occured. The error code is 2 - person Daniel Baptista; 17.12.2020
comment
Решатель обнаружил, что уравнения не могут быть удовлетворены с заданными уравнениями и ограничениями. Вот несколько вещей, которые можно попробовать: (1) Установить m.options.NODES=2 для проверки удаления внутренних узлов, (2) удалить ограничения, которые могут ограничивать сходимость решателя, особенно ограничения на переменные и CV, (3) добавить ограничения на MV, чтобы помочь они сходятся, давая ему меньшую область поиска. - person John Hedengren; 18.12.2020
comment
С (1) я получил успешное решение, но MV не изменились, как это было раньше, без уравнения m.Equation(ucFront==Front). В (2) и (3) я попытался увеличить зону нечувствительности уставки и изменить границы MV и DMAX, но безрезультатно. Эта проблема возникает только тогда, когда я добавляю тэту с cspline к MV, если я удаляю эти строки и помещаю MV непосредственно в уравнение, решатель работает нормально, но без мертвого времени из MV. - person Daniel Baptista; 20.12.2020
comment
Может быть, попробуйте установить theta=0, чтобы проверить решение с помощью m.Equation(ucFront==Front). Может ли решение с m.options.SOLVER=1 быть правильным? Я думал, что предыдущие попытки с m.options.SOLVER=3 дали неудачное решение. Нельзя доверять неудачному решению. - person John Hedengren; 20.12.2020
comment
Да, m.options.SOLVER=3 дал неудачное решение, за исключением (1) с m.options.NODES=2. До этого, в моем исходном посте, soutions с m.options.SOLVER=1 удавалось только тогда, когда я не использовал cspline на MV, вот что я говорил - person Daniel Baptista; 20.12.2020
comment
С theta=0 я получаю аналогичный результат (1) с m.options.NODES=2. Я получил решение, но MV не изменился. - person Daniel Baptista; 20.12.2020
comment
Чтобы уточнить, если я удалю cspline на MV и использую m.options.SOLVER=3, я все равно получу успешное решение, как и с m.options.SOLVER=1, поэтому это не похоже на проблему решателя. Но в этих случаях у меня нет мертвого времени, применяемого к MV. - person Daniel Baptista; 20.12.2020
comment
Еще можно попробовать установить bound_x=True, чтобы оптимизатор не выполнял поиск за пределами cspline. - person John Hedengren; 20.12.2020
comment
Он все еще не работает с этой опцией ... Есть еще догадки, что это может быть? - person Daniel Baptista; 04.01.2021
comment
Какую ошибку выдает? Нарушение прав доступа, максимальное количество итераций, успешное решение, но с плохими результатами, или недопустимое решение? - person John Hedengren; 04.01.2021
comment
Я получаю те же результаты с bound_x = True. Если я устанавливаю мертвое время (тета) на нормальное значение, я получаю недопустимое решение. Если я установлю его на 0, я получу неправильное решение, потому что MV не меняется. - person Daniel Baptista; 05.01.2021