Question: The following is related to this question : predictive control model using GEKKO I am still traying applying MPC to maintain the temperature of a room within a defined range(16,18), as Professor @John explained last time.the gain is normally listed as K=array([[0.93705481,−12.24012156]]). Thus, an increase in β by +1 leads to a decrease in T by -12.24, while an increase in Text by +1 leads to an increase in T by +0.937. In my case, I tried to implement an external temperature profile for a day (sinusoidal), and I modified the control to vary between 0 and 1, not just 0 or 1, since the equipment can operate within this range. I also adjusted m.bint.MV_STEP_HOR=1 so that the control is updated at each iteration. However, the control still does not react! Even when the external temperature increases or decreases, the control remains unchanged. I run the corrected code from my previous question: # Import library import numpy as np import pandas as pd import time from gekko import GEKKO from numpy import array total_minutes_in_day = 24 * 60 interval = 5 # minutes num_points = total_minutes_in_day // interval # Générer les points de temps time_points = np.linspace(0, total_minutes_in_day, num_points) temperature = 8.5 + 11.5 * np.sin((2 * np.pi / total_minutes_in_day) * time_points - (np.pi / 2)) temperature = np.clip(temperature, -3, 20) plt.plot(time_points, temperature) plt.xlabel('Temps (minutes)') plt.ylabel('Température (°C)') plt.title('Variation de Tex sur une journée') plt.savefig('Tex pour une jrn') plt.grid(True) plt.show() K = array([[ 0.93705481, -12.24012156]]) p = {'a': array([[ 1.08945247], [-0.00242145], [-0.00245978], [-0.00272713], [-0.00295845], [-0.00319119], [-0.00343511], [-0.00366243], [-0.00394247], [-0.06665054]]), 'b': array([[[-0.05160235, -0.01039767], [ 0.00173511, -0.01552485], [ 0.00174602, -0.01179519], [ 0.00180031, -0.01052658], [ 0.00186416, -0.00822121], [ 0.00193947, -0.00570905], [ 0.00202877, -0.00344507], [ 0.00211395, -0.00146947], [ 0.00223514, 0.00021945], [ 0.03800987, 0.04243736]]]), 'c': array([0.0265903])} # i have used only 200 mes of T_externel T_externel = temperature m = GEKKO(remote=False) m.y = m.Array(m.CV,1) m.u = m.Array(m.MV,2) m.arx(p,m.y,m.u) # rename CVs m.T = m.y[0] # rename MVs m.beta = m.u[1] m.free(m.beta) m.bint = m.MV(0,lb=0,ub=1) m.Equation(m.beta==m.bint) # distrubance m.d = m.u[0] # distrubance and parametres m.d = m.Param(T_externel[0]) m.bias = m.Param(0) m.Tb = m.CV() m.Equation(m.Tb==m.T+m.bias) # steady state initialization m.options.IMODE = 1 m.solve(disp=False) # set up MPC m.d.value = T_externel m.options.IMODE = 6 # MPC m.options.CV_TYPE = 1 # the objective is an l1-norm (region) m.options.NODES = 2 # Collocation nodes m.options.SOLVER = 3 # IPOPT m.time = np.arange(0,len(T_externel)*300,300) # step time = 300s # Manipulated variables m.bint.STATUS = 1 # calculated by the optimizer m.bint.FSTATUS = 0 # use measured value m.bint.DCOST = 0.0 # Delta cost penalty for MV movement m.bint.UPPER = 1.0 # Upper bound m.bint.LOWER = 0.0 # Lower bound m.bint.MV_STEP_HOR = 1 m.bint.value = 0 # Controlled variables m.Tb.STATUS = 1 # drive to set point m.Tb.FSTATUS = 0 # receive measurement m.Tb.SPHI = 18 # set point high level m.Tb.SPLO = 16 # set point low level m.Tb.WSPHI = 100 # set point high priority m.Tb.WSPLO = 100 # set point low priority T_MEAS = 20 # Temperature starts at 17 m.Tb.value = T_MEAS m.bias.value = T_MEAS - m.T.value[0] m.options.SOLVER = 1 m.solve(disp=False) if m.options.APPSTATUS == 1: # Retrieve new values beta = m.beta.NEWVAL else: # Solution failed beta = 0.0  

Answer: The solution that you showed was able to find a solution with a single step to keep within the temperature range (17-19). Tightening the temperature range (16.5-17.5) shows additional movement of the MV over the time period and shows that it is responsive. Unless there is a violation of this temperature range, the controller does not take action if there is even a small DCOST value to move the MV.  The dynamics influence the speed of the response. A better insulated building will have a slower response to changes in the external temperature. One other suggestion is that the bint Manipulated Variable isn't needed when solving for continuous instead of integer solutions. Here is the complete code with bint removed and the tighter temperature target range: # Import library import numpy as np import pandas as pd import time from gekko import GEKKO from numpy import array import matplotlib.pyplot as plt total_minutes_in_day = 24 * 60 interval = 5 # minutes num_points = total_minutes_in_day // interval # Générer les points de temps time_points = np.linspace(0, total_minutes_in_day, num_points) temperature = 8.5 + 11.5 * np.sin((2 * np.pi / total_minutes_in_day) * time_points - (np.pi / 2)) temperature = np.clip(temperature, -3, 20) K = array([[ 0.93705481, -12.24012156]]) p = {'a': array([[ 1.08945247], [-0.00242145], [-0.00245978], [-0.00272713], [-0.00295845], [-0.00319119], [-0.00343511], [-0.00366243], [-0.00394247], [-0.06665054]]), 'b': array([[[-0.05160235, -0.01039767], [ 0.00173511, -0.01552485], [ 0.00174602, -0.01179519], [ 0.00180031, -0.01052658], [ 0.00186416, -0.00822121], [ 0.00193947, -0.00570905], [ 0.00202877, -0.00344507], [ 0.00211395, -0.00146947], [ 0.00223514, 0.00021945], [ 0.03800987, 0.04243736]]]), 'c': array([0.0265903])} T_externel = temperature m = GEKKO(remote=False) m.y = m.Array(m.CV,1) m.u = m.Array(m.MV,2) m.arx(p,m.y,m.u) # rename CVs m.T = m.y[0] # rename MVs m.beta = m.u[1] # distrubance m.d = m.u[0] # distrubance and parametres m.d = m.Param(T_externel[0]) m.bias = m.Param(0) m.Tb = m.CV() m.Equation(m.Tb==m.T+m.bias) # steady state initialization m.options.IMODE = 1 m.solve(disp=False) # set up MPC m.d.value = T_externel m.options.IMODE = 6 # MPC m.options.CV_TYPE = 1 # the objective is an l1-norm (region) m.options.NODES = 2 # Collocation nodes m.options.SOLVER = 3 # IPOPT m.time = np.arange(0,len(T_externel)*300,300) # step time = 300s # Manipulated variables m.beta.STATUS = 1 # calculated by the optimizer m.beta.FSTATUS = 0 # use measured value m.beta.DCOST = 0.0 # Delta cost penalty for MV movement m.beta.UPPER = 1.0 # Upper bound m.beta.LOWER = 0.0 # Lower bound m.beta.MV_STEP_HOR = 1 m.beta.value = 0 # Controlled variables m.Tb.STATUS = 1 # drive to set point m.Tb.FSTATUS = 0 # receive measurement m.Tb.SPHI = 17.5 # set point high level m.Tb.SPLO = 16.5 # set point low level m.Tb.WSPHI = 100 # set point high priority m.Tb.WSPLO = 100 # set point low priority T_MEAS = 20 m.Tb.value = T_MEAS m.bias.value = T_MEAS - m.T.value[0] m.options.SOLVER = 3 m.solve(disp=False) if m.options.APPSTATUS == 1: # Retrieve new values beta = m.beta.NEWVAL else: # Solution failed beta = 0.0 # Plot the results plt.figure(figsize=(8,3.5)) plt.subplot(2,1,1) plt.plot(m.time,m.Tb.value,'r-',label=r'$T_{biased}$') plt.plot(m.time,m.T.value,'r--',label=r'$T_{unbiased}$') plt.plot(m.time,m.d.value,'g:',label=r'$T_{ext}$') plt.plot([0,m.time[-1]],[m.Tb.SPHI,m.Tb.SPHI],'k--',label='Upper Bound') plt.plot([0,m.time[-1]],[m.Tb.SPLO,m.Tb.SPLO],'k--',label='Lower Bound') plt.ylabel('Temperature (°C)') plt.legend(loc=1); plt.grid() plt.subplot(2,1,2) plt.step(m.time,m.beta.value,'b--',label=r'$\beta$') plt.ylabel('optimal control') plt.xlabel('Time (sec)') plt.legend(loc=1); plt.grid() plt.savefig('results.png',dpi=300) plt.show()