Why is my MV unable to converge when normal Vars can?

Viewed 64

I am developing a model for a power grid. I am at the phase now where I need to put in power plant ramp rates. In my model it converges in like 2 seconds when I have Gas as an m.Var, as soon as I change it to an m.MV it can't find a solution. I am trying to change it to an m.MV so that I can limit its ramping ability. In the model the max it actually ramps is around 1900 but I was only going to limit it to 3000. Is there another type of variable that would work better? is there any reason why it can't converge as an m.MV?

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


"""
Max capacities based on MISO South Grid, Prices are currently based
google averages for a power source but will be specific to Miso soon
"""

nhrs = 240
Gas_cap = 23000  # MW
Gas_start = 18771  # Starting value for 2018-01-01
Gas_cost = 38  # $/MW
Gas_min = 5000  # MW

Coal_cap = 6500  # MW
Coal_start = 962  # Starting value for 2018-01-01
Coal_cost = 76  # $/MW
Coal_min = 900  # MW

Hydro_cap = 500  # MW
Hydro_start = 500  # Starting value for 2018-01-01
Hydro_cost = 21  # $/MW
Hydro_min = 50  # MW

Nuc_cap = 5500  # MW
Nuc_start = 5375  # Starting value for 2018-01-01
Nuc_cost = 20  # $/MW
Nuc_min = 2800  # %capacity

Other_cap = 1000  # MW
Other_start = 859.3  # Starting value for 2018-01-01
Other_cost = 10  # $/MW
Other_min = 100  # MW

query = """SELECT "Actual_Load_MWh", Date_Time FROM "Load_By_Region"
            WHERE Region = "South"
                AND Date_Time BETWEEN date('2018-01-01') and date('2018-12-31')
                """

con = create_engine('sqlite:///../../../../data/MISO_data.db')
Miso_data = pd.read_sql(query, con)
load_data = pd.to_numeric(Miso_data['Actual_Load_MWh']).values[:nhrs]

date = Miso_data['Date_Time'].values[:nhrs]
Time = np.arange(len(date))
# plt.plot(Time, load_data)

m = GEKKO()
m.time = Time

load = m.Param(load_data)

Nuc = m.MV(value=Nuc_start, lb=Nuc_min, ub=Nuc_cap)
Nuc.DMAX = 1413  # MW from MISO Ramp rates
Gas = m.Var(value=Gas_start, lb=Gas_min, ub=Gas_cap)
#Gas.DMAX = 3900 # MW from MISO Ramp rates
Coal = m.MV(value=Coal_start, lb=Coal_min, ub=Coal_cap)
Coal.DMAX = 2146  # MW from MISO Ramp rates
Hydro = m.MV(value=Hydro_start, lb=Hydro_min, ub=Hydro_cap)
Hydro.DMAX = 209  # MW from MISO Ramp rates
Other = m.MV(value=Other_start, lb=Other_min, ub=Other_cap)
Other.DMAX = 605  # MW from MISO Ramp rates

slack = m.Var(lb=0)
Cost = m.Var(value=0)
CostMWh = m.Var(value=0)
# Gasramp = m.Var(value=0)

# m.Equation(Gasramp == Gas.dt())
m.Equation(load == Nuc + Gas + Coal + Hydro + Other + slack)
m.Equation(Cost == Nuc*Nuc_cost + Gas*Gas_cost + Coal*Coal_cost +
           Hydro*Hydro_cost + Other*Other_cost + slack*1e8)
m.Equation(CostMWh == Cost/load)
m.Obj(Cost)
m.options.IMODE = 5
m.options.SOLVER = 3
m.solve()

1 Answers

I couldn't run your exact case because I don't have access to the database you are using. Below is a self-contained problem that converges to an optimal solution. This won't help because you are having a problem with your dataset. Here are a few tips on using the m.MV() model.

  • Initialize the model with simulation before optimizing. This is possible by setting m.options.COLDSTART=2 with m.solve() and then m.options.COLDSTART=0 and m.options.TIME_SHIFT=0 (to not update the initial conditions) with another m.solve(). The MV model has additional equations that solve better when initialized.
  • Here is a reference for more tips on initialization:
    • Safdarnejad, S.M., Hedengren, J.D., Lewis, N.R., Haseltine, E., Initialization Strategies for Optimization of Dynamic Systems, Computers and Chemical Engineering, Vol. 78, pp. 39-50, DOI: 10.1016/j.compchemeng.2015.04.016.
from gekko import GEKKO
import numpy as np

"""
Max capacities based on MISO South Grid, Prices are currently based
google averages for a power source but will be specific to Miso soon
"""

nhrs = 240
Gas_cap = 23000  # MW
Gas_start = 18771  # Starting value for 2018-01-01
Gas_cost = 38  # $/MW
Gas_min = 5000  # MW

Coal_cap = 6500  # MW
Coal_start = 962  # Starting value for 2018-01-01
Coal_cost = 76  # $/MW
Coal_min = 900  # MW

Hydro_cap = 500  # MW
Hydro_start = 500  # Starting value for 2018-01-01
Hydro_cost = 21  # $/MW
Hydro_min = 50  # MW

Nuc_cap = 5500  # MW
Nuc_start = 5375  # Starting value for 2018-01-01
Nuc_cost = 20  # $/MW
Nuc_min = 2800  # %capacity

Other_cap = 1000  # MW
Other_start = 859.3  # Starting value for 2018-01-01
Other_cost = 10  # $/MW
Other_min = 100  # MW

Time = np.arange(10)

m = GEKKO()
m.time = Time

load = m.Param(np.ones_like(Time)*13000)

Nuc = m.MV(value=Nuc_start, lb=Nuc_min, ub=Nuc_cap)
Nuc.DMAX = 1413  # MW from MISO Ramp rates
Gas = m.MV(value=Gas_start, lb=Gas_min, ub=Gas_cap)
Gas.STATUS = 1
Coal = m.MV(value=Coal_start, lb=Coal_min, ub=Coal_cap)
Coal.DMAX = 2146  # MW from MISO Ramp rates
Hydro = m.MV(value=Hydro_start, lb=Hydro_min, ub=Hydro_cap)
Hydro.DMAX = 209  # MW from MISO Ramp rates
Other = m.MV(value=Other_start, lb=Other_min, ub=Other_cap)
Other.DMAX = 605  # MW from MISO Ramp rates

slack = m.Var(lb=0)
Cost = m.Var(value=0)
CostMWh = m.Var(value=0)

m.Equation(load == Nuc + Gas + Coal + Hydro + Other + slack)
m.Equation(Cost == Nuc*Nuc_cost + Gas*Gas_cost + Coal*Coal_cost +
           Hydro*Hydro_cost + Other*Other_cost + slack*1e8)
m.Equation(CostMWh == Cost/load)
m.Obj(Cost)

m.options.SOLVER = 3
m.options.IMODE = 5

# Initialize, if needed
#m.options.COLDSTART=2
#m.solve()

m.options.TIME_SHIFT=0
m.options.COLDSTART=0
m.solve()
Related