I am working on a Model Predictive Control for a chiller - storage tank system. I'm a thermal engineering master student and this topic is new to me, so the things I'm asking may not be for this forum, but I'm running out of ideas.
I'm developing the code in Matlab and solving the non-linear optimization problem using CasADi. The solver I'm using is Ipopt.
For the time being my actuation variables are the mass flow rate through the chiller and the temperature of the water at the chiller's outlet. With those two variables and the return temperature I calculate the chiller's cooling capacity. The equations of the models are non-linear.
The mass flow rate through the chiller has a lower and an upper limit for safety reasons:
m_chiller_min <= m_chiller <= m_chiller_max.
One of the problems I've encountered is that while I need to respect that, I also need to be able to set the variable to zero if there's no need to produce chilled water.
I have a similar problem with the chiller's capacity/partial load ratio, because it has a lower limit but also needs to be zero if needed.
I have tried declaring a binary (chiller_on
) optimization variable and using it to make m_chiller = 0 if needed:
0 <= chiller on <= 1;
m_chiller = m_chiller*chiller_on;
m_chiller_min*chiller_on <= m_chiller <= m_chiller_max;
While it converges with some difficulty, the solution is dependant on the initial guess value I give to the chiller_on value. If I give a 1 to the binary, even if the better solution is to turn off the chiller it will not do it. I have also tried this with CasADi's bonmin solver, declaring the binary as discrete, but I have the same problem.
The MPC runs well without limiting the chiller's minimum mass flow rate and partial load ratio.
I don't know if I'm doing it right, but as I said I've hit a wall. I need to find a way, preferably without any binary variables, to limit the lower value but still be able to shut it off.
Edit: I have tried this for a prediction horizon of 1, and it works:
m_chiller_max = Chiller(1).lim.m_max;
m_chiller_min = Chiller(1).lim.m_min;
con( 0 <= chiller_on <= 1 );
con( 0 <= m_chiller <= m_chiller_max*chiller_on );
con( m_chiller_min*chiller_on <= m_chiller );
I have had to use the solver bonmin for this, and declare the binary variable as discrete. I would prefer a solution without binary variables, to be able to use Ipopt.
Your formulation
m_chiller_min*chiller_on <= m_chiller <= m_chiller_max;
is not quite right.A variable x that can be zero or between L and U is called a semi-continuous variable. Many MIP solvers have built-in support for this. Otherwise, you can use a binary variable and write: