简体   繁体   中英

How to fix "Solution Not Found" Error in Gekko Optimization with rolling principle

My program is optimizing the charging and decharging of a home battery to minimize the cost of electricity at the end of the year. In this case there also is a PV, which means that sometimes you're injecting electricity into the grid and receive money. The electricity usage of homes is measured each 15 minutes, so I have 96 measurement point in 1 day. I want to optimilize the charging and decharging of the battery for 2 days, so that day 1 takes the usage of day 2 into account. I wrote a controller that reads the data and gives each time the input values for 2 days to the optimization. With a rolling principle, it goes to the next 2 days and so on. Below you can see the code from my controller.

from gekko import GEKKO
from simulationModel2_2d_1 import getSimulation2
from exportModel2 import exportToExcelModel2
import numpy as np
#import matplotlib.pyplot as plt
import pandas as pd
import time
import math

# ------------------------ Import and read input data ------------------------

file = r'Data Sim 2.xlsx'

data = pd.read_excel(file, sheet_name='Input', na_values='NaN')

dataRead = pd.DataFrame(data, columns= ['Timestep','Verbruik woning (kWh)','Netto afname (kWh)','Prijs afname (€/kWh)',
                                            'Prijs injectie (€/kWh)','Capaciteit batterij (kW)',
                                            'Capaciteit batterij (kWh)','Rendement (%)',
                                            'Verbruikersprofiel','Capaciteit PV (kWp)','Aantal dagen'])

timestep = dataRead['Timestep'].to_numpy()                                 
usage_home = dataRead['Verbruik woning (kWh)'].to_numpy()
net_offtake = dataRead['Netto afname (kWh)'].to_numpy()
price_offtake = dataRead['Prijs afname (€/kWh)'].to_numpy()
price_injection = dataRead['Prijs injectie (€/kWh)'].to_numpy()
cap_batt_kW = dataRead['Capaciteit batterij (kW)'].iloc[0]              
cap_batt_kWh = dataRead['Capaciteit batterij (kWh)'].iloc[0]
efficiency = dataRead['Rendement (%)'].iloc[0]
usersprofile = dataRead['Verbruikersprofiel'].iloc[0]
days = dataRead['Aantal dagen'].iloc[0]
pv = dataRead['Capaciteit PV (kWp)'].iloc[0]

# ------------- Optimization model & Rolling principle (2 days) --------------

# Initialise model
m = GEKKO()

# Output data
ts = []
charging = []                       # Amount to charge/decharge batterij
e_batt = []                         # Amount of energy in the battery
usage_net = []                      # Usage after home, battery and pv
p_paid = []                         # Price paid for energy of 15min

# Energy in battery to pass
energy = 0

# Iterate each day for one year
for d in range(int(days)-1):
    d1_timestep = []
    d1_net_offtake = []
    d1_price_offtake = []
    d1_price_injection = []
    d2_timestep = []
    d2_net_offtake = []
    d2_price_offtake = []
    d2_price_injection = []
    
    # Iterate timesteps
    for i in range(96):
        d1_timestep.append(timestep[d*96+i])
        d2_timestep.append(timestep[d*96+i+96])
        
        d1_net_offtake.append(net_offtake[d*96+i])
        d2_net_offtake.append(net_offtake[d*96+i+96])
        
        d1_price_offtake.append(price_offtake[d*96+i])
        d2_price_offtake.append(price_offtake[d*96+i+96])
        
        d1_price_injection.append(price_injection[d*96+i])
        d2_price_injection.append(price_injection[d*96+i+96])
    
    # Input data simulation of 2 days
    ts_temp = np.concatenate((d1_timestep, d2_timestep))
    net_offtake_temp = np.concatenate((d1_net_offtake, d2_net_offtake))
    price_offtake_temp = np.concatenate((d1_price_offtake, d2_price_offtake))
    price_injection_temp = np.concatenate((d1_price_injection, d2_price_injection))
    if(d == 7):
        print(ts_temp)
        print(energy)
    # Simulatie uitvoeren
    charging_temp, e_batt_temp, usage_net_temp, p_paid_temp, energy_temp = getSimulation2(ts_temp, net_offtake_temp, price_offtake_temp, price_injection_temp,                                                                                     cap_batt_kW, cap_batt_kWh, efficiency, energy, pv)
    
    # Take over output first day, unless last 2 days
    energy = energy_temp
    if(d == (days-2)):
        for t in range(1,len(ts_temp)):
            ts.append(ts_temp[t])
            charging.append(charging_temp[t])
            e_batt.append(e_batt_temp[t])
            usage_net.append(usage_net_temp[t])
            p_paid.append(p_paid_temp[t])
    elif(d == 0):
        for t in range(int(len(ts_temp)/2)+1):
            ts.append(ts_temp[t])
            charging.append(charging_temp[t])
            e_batt.append(e_batt_temp[t])
            usage_net.append(usage_net_temp[t])
            p_paid.append(p_paid_temp[t])
    else:
        for t in range(1,int(len(ts_temp)/2)+1):
            ts.append(ts_temp[t])
            charging.append(charging_temp[t])
            e_batt.append(e_batt_temp[t])
            usage_net.append(usage_net_temp[t])
            p_paid.append(p_paid_temp[t])
            
    print('Simulation day '+str(d+1)+' complete.')
    
# ------------------------ Export output data to Excel -----------------------

a = exportToExcelModel2(ts, usage_home, net_offtake, price_offtake, price_injection, charging, e_batt, usage_net, p_paid, cap_batt_kW, cap_batt_kWh, efficiency, usersprofile, pv)
print(a)

The optimization with Gekko happens in the following code:

from gekko import GEKKO

def getSimulation2(timestep, net_offtake, price_offtake, price_injection, 
                   cap_batt_kW, cap_batt_kWh, efficiency, start_energy, pv):
    
    # ---------------------------- Optimization model ----------------------------
       
    # Initialise model
    m = GEKKO(remote = False)
    
    # Global options
    m.options.SOLVER = 1
    m.options.IMODE  = 6
    
    # Constants
    speed_charging = cap_batt_kW/4
    m.time = timestep
        
    max_cap_batt = m.Const(value = cap_batt_kWh)
    min_cap_batt = m.Const(value = 0)
    max_charge = m.Const(value = speed_charging)                                    # max battery can charge in 15min
    max_decharge = m.Const(value = -speed_charging)                                 # max battery can decharge in 15min
    
    # Parameters
    usage_home = m.Param(net_offtake)
    price_offtake = m.Param(price_offtake)
    price_injection = m.Param(price_injection)
    
    # Variables
    e_batt = m.Var(value=start_energy, lb = min_cap_batt, ub = max_cap_batt)  # energy in battery
    price_paid = m.Var()                                              # price paid each 15min
    charging = m.Var(lb = max_decharge, ub = max_charge)              # amount charge/decharge each 15min
    usage_net = m.Var(lb=min_cap_batt)
    
    # Equations
    m.Equation(e_batt==(m.integral(charging)+start_energy)*efficiency)
    m.Equation(-charging <= e_batt)
    m.Equation(usage_net==usage_home + charging)
    price = m.Intermediate(m.if2(usage_net*1e6, price_injection, price_offtake))
    price_paid = m.Intermediate(usage_net * price / 100)
    
    # Objective 
    m.Minimize(price_paid)
    
    # Solve problem
    m.options.COLDSTART=2
    m.solve()
    
    m.options.TIME_SHIFT=0
    m.options.COLDSTART=0
    m.solve()
          
    # Energy to pass
    energy_left = e_batt[95]
    
    #m.cleanup()
    
    return charging, e_batt, usage_net, price_paid, energy_left

The data you need for input can be found in this Excel document: https://docs.google.com/spreadsheets/d/1S40Ut9-eN_PrftPCNPoWl8WDDQtu54f0/edit?usp=sharing&ouid=104786612700360067470&rtpof=true&sd=true

With this code, it always ends at day 17 with the "Solution Not Found" Error. I already tried extending the default iteration limit to 500 but it didn't work. I also tried with other solvers but also no improvement. By presolving with COLDSTART it already reached day 17, without this it ends at day 8.

I solved the days were my optimization ends individually and then the solution was always found immediately with the same code. Someone who can explain this to me and maybe find a solution? Thanks in advance!

This is kind of big to troubleshoot, but here are some general ideas that might help. This assumes, as you said, that the model solves fine for day 1-2, and day 3-4, and day 5-6, etc. And that those results pass inspection (aka the basic model is working as you say).

Then something is (obviously) amiss around day 17. Some things to look at and try:

  • Start the model at day 16-17, see if it works in isolation
  • gather your results as you go and do a time series plot of the key variables, maybe one of them is on an obvious bad trend towards a limit causing an infeasibility... Perhaps the e_batt variable is slowly declining because not enough PV energy is available and hits minimum on Day 17
  • Radically change the upper/lower bounds on your variables to test them to see if they might be involved in the infeasibility (assuming there is one)
  • Make a different (fake) dataset where the solution is assured and kind of obvious... all constants or a pattern that you know will produce some known result and test the model outputs against it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM