Gekko optimal control. Air density equation goes wrong

Viewed 67

So I am optimizing plane flight using optimal control. The plane flies certain distance (path variable) and then the simulation stops. The solver is trying to minimize the fuel consumption (m.Maximize(masstffinal), by maximizing the mass value.

And I tried to implement air pressure and air density equations. The pressure equation works fine, but the density does not.

For air pressure I used this one:enter image description here

It turned into this m.Equation(pressure==101325*(1-(0.0065*h)/T0)**((g*0.0289652)/(8.31446*0.0065)))

And for the air density, I used this one: enter image description here

I turned it into this: m.Equation(Ro==(pressure*0.0289652)/(8.31446*T)) But for some reason, when I am trying to run the program with the density equation active, the simulation runs until the maximum cycle count gets achieved. What am I doing wrong with that density equation?

My code:

import numpy as np
import matplotlib.pyplot as plt
from gekko import GEKKO
import math
#Gekko model
m = GEKKO(remote=False)

#Time points
nt = 11
tm =  np.linspace(0,100,nt)
m.time = tm

# Variables
Ro = m.Var(value=1.1)#air density
g = m.Const(value=9.80665)
pressure = m.Var(value=101325)#
T = m.Var(value=281)#temp
T0 = m.Const(value=288)#temp at see level
S = m.Const(value=122.6)
Cd = m.Const(value=0.1)
FuelFlow = m.Var()
D = m.Var()#drag
Thrmax = m.Const(value=200000)#macimum throttle
Thr = m.Var()
V = m.Var(value=100,lb=0,ub=240)#velocity
#Vmin = m.Var(value=100)
nu = m.Var(value=0)#angle
nuu = nu.value
x = m.Var(value=0,lb=0)#x position
h = m.Var(value=1000)# height
mass = m.Var(value=60000)
path = m.Const(value=5000000) #intended distance length
L = m.Var()

p = np.zeros(nt)
p[-1] = 1.0
final = m.Param(value=p)

m.options.MAX_ITER=10000 # iteration number

#Fixed Variable
tf = m.FV(value=1,lb=0.0001,ub=1000.0)#
tf.STATUS = 1

# Parameters
Tcontr = m.MV(value=0.2,lb=0.2,ub=1)
Tcontr.STATUS = 1
Tcontr.DCOST = 0

# Equations
m.Equation(x.dt()==tf*(V*(math.cos(nuu.value))))#
m.Equation(Thr==Tcontr*Thrmax)
m.Equation(V.dt()==tf*((Thr-D)/mass))#
m.Equation(mass.dt()==tf*(-Thr*(FuelFlow/60000)))#

m.Equation(T==T0-(0.0065*h))
m.Equation(pressure==101325*(1-(0.0065*h)/T0)**((g*0.0289652)/(8.31446*0.0065)))# equation works
m.Equation(Ro==(pressure*0.0289652)/(8.31446*T))# equation does not work

m.Equation(D==0.5*Ro*(V**2)*Cd*S)
m.Equation(FuelFlow==0.75882*(1+(V/2938.5)))
m.Equation(x*final<=path)

# Objective Function
m.Minimize(final*(x-path)**2)
m.Maximize(mass*tf*final)
m.options.IMODE = 6
m.options.NODES = 2 # it was 3 before
m.options.MV_TYPE = 1
m.options.SOLVER = 3
#m.open_folder() # to search for infeasibilities
m.solve()

tm = tm * tf.value[0]
    
fig, axs = plt.subplots(6)
fig.suptitle('Results')
axs[0].plot(tm,Tcontr,'r-',LineWidth=2,label=r'$Tcontr$')
axs[0].legend(loc='best')
axs[1].plot(tm,V.value,'b-',LineWidth=2,label=r'$V$')
axs[1].legend(loc='best')
axs[2].plot(tm,x.value,'r--',LineWidth=2,label=r'$x$')
axs[2].legend(loc='best')
axs[3].plot(tm,D.value,'g-',LineWidth=2,label=r'$D$')
axs[3].legend(loc='best')
axs[4].plot(tm,mass.value,'g:',LineWidth=2,label=r'$mass$')
axs[4].legend(loc='best')
axs[5].plot(tm,T.value,'p-',LineWidth=2,label=r'$T$')
axs[5].legend(loc='best')
#axs[6].plot(tm,Ro.value,'p-',LineWidth=2,label=r'$Ro$')
#axs[6].legend(loc='best')
plt.xlabel('Time')
#plt.ylabel('Value')
plt.show()
1 Answers

A couple things that can help with the problem of not finding a solution:

  1. Add constraints to variables to help the solver stay within a reasonable range.
# Variables
T = m.Var(value=281,lb=100)#temp
h = m.Var(value=1000,lb=0)# height
mass = m.Var(value=60000,lb=1000)
tf = m.FV(value=1,lb=0.1,ub=100.0)#

If the solution is at a constraint then consider opening the constraints further and resolve either from the prior solution or start over.

  1. Avoid divide-by-zero by rearranging equations.
#m.Equation(Ro==(pressure*0.0289652)/(8.31446*T))# equation does not work
m.Equation(Ro*(8.31446*T)==(pressure*0.0289652))

Generally, the solver will either be successful or unsuccessful after a couple hundred iterations. Setting MAX_ITER=100000 may cause excessive time if the solution is not successful.

Solution

import numpy as np
import matplotlib.pyplot as plt
from gekko import GEKKO
import math
#Gekko model
m = GEKKO(remote=False)

#Time points
nt = 101
tm =  np.linspace(0,100,nt)
m.time = tm

# Variables
Ro = m.Var(value=1.1)#air density
g = m.Const(value=9.80665)
pressure = m.Var(value=101325)#
T = m.Var(value=281,lb=100)#temp
T0 = m.Const(value=288)#temp at see level
S = m.Const(value=122.6)
Cd = m.Const(value=0.1)
FuelFlow = m.Var()
D = m.Var()#drag
Thrmax = m.Const(value=200000)#maximum throttle
Thr = m.Var()
V = m.Var(value=100,lb=0,ub=240)#velocity
#Vmin = m.Var(value=100)
nu = m.Var(value=0)#angle
nuu = nu.value
x = m.Var(value=0,lb=0)#x position
h = m.Var(value=1000,lb=0)# height
mass = m.Var(value=60000,lb=1000)
path = m.Const(value=5000000) #intended distance length
L = m.Var()

p = np.zeros(nt)
p[-1] = 1.0
final = m.Param(value=p)

m.options.MAX_ITER=200 # iteration number

#Fixed Variable
tf = m.FV(value=1,lb=0.1,ub=100.0)#
tf.STATUS = 1

# Parameters
Tcontr = m.MV(value=0.2,lb=0.2,ub=1)
Tcontr.STATUS = 1
Tcontr.DCOST = 0

# Equations
m.Equation(x.dt()==tf*(V*(math.cos(nuu.value))))#
m.Equation(Thr==Tcontr*Thrmax)
m.Equation(V.dt()==tf*((Thr-D)/mass))#
m.Equation(mass.dt()==tf*(-Thr*(FuelFlow/60000)))#

m.Equation(T==T0-(0.0065*h))
m.Equation(pressure==101325*(1-(0.0065*h)/T0)**((g*0.0289652)/(8.31446*0.0065)))# equation works
m.Equation(Ro*(8.31446*T)==(pressure*0.0289652))# equation does not work

m.Equation(D==0.5*Ro*(V**2)*Cd*S)
m.Equation(FuelFlow==0.75882*(1+(V/2938.5)))
m.Equation(x*final<=path)

# Objective Function
m.Minimize(final*(x-path)**2)
m.Maximize(mass*tf*final)
m.options.IMODE = 6
m.options.NODES = 2 # it was 3 before
m.options.MV_TYPE = 1
m.options.SOLVER = 3
#m.open_folder() # to search for infeasibilities
m.solve()

tm = tm * tf.value[0]
    
fig, axs = plt.subplots(6)
fig.suptitle('Results')
axs[0].plot(tm,Tcontr,'r-',lw=2,label=r'$Tcontr$')
axs[0].legend(loc='best')
axs[1].plot(tm,V.value,'b-',lw=2,label=r'$V$')
axs[1].legend(loc='best')
axs[2].plot(tm,x.value,'r--',lw=2,label=r'$x$')
axs[2].legend(loc='best')
axs[3].plot(tm,D.value,'g-',lw=2,label=r'$D$')
axs[3].legend(loc='best')
axs[4].plot(tm,mass.value,'g:',lw=2,label=r'$mass$')
axs[4].legend(loc='best')
axs[5].plot(tm,T.value,'p-',lw=2,label=r'$T$')
axs[5].legend(loc='best')
#axs[6].plot(tm,Ro.value,'p-',lw=2,label=r'$Ro$')
#axs[6].legend(loc='best')
plt.xlabel('Time')
#plt.ylabel('Value')
plt.show()
Related