EOS/modules/class_optimize.py

203 lines
8.9 KiB
Python
Raw Normal View History

from flask import Flask, jsonify, request
import numpy as np
from modules.class_load import *
from modules.class_ems import *
from modules.class_pv_forecast import *
from modules.class_akku import *
from modules.class_strompreis import *
from modules.class_heatpump import *
from modules.class_load_container import *
from modules.class_sommerzeit import *
from modules.visualize import *
import os
from flask import Flask, send_from_directory
from pprint import pprint
import matplotlib
matplotlib.use('Agg') # Setzt das Backend auf Agg
import matplotlib.pyplot as plt
import string
from datetime import datetime
from deap import base, creator, tools, algorithms
import numpy as np
import random
import os
def isfloat(num):
try:
float(num)
return True
except:
return False
class optimization_problem:
def __init__(self, prediction_hours=24, strafe = 10):
# Werkzeug-Setup
creator.create("FitnessMin", base.Fitness, weights=(-1.0,))
creator.create("Individual", list, fitness=creator.FitnessMin)
self.toolbox = base.Toolbox()
self.prediction_hours = prediction_hours#
self.strafe = strafe
# PARAMETER
self.toolbox.register("attr_bool", random.randint, 0, 1)
self.toolbox.register("attr_bool", random.randint, 0, 1)
self.toolbox.register("individual", tools.initCycle, creator.Individual, (self.toolbox.attr_bool,self.toolbox.attr_bool), n=self.prediction_hours)
self.toolbox.register("population", tools.initRepeat, list, self.toolbox.individual)
self.toolbox.register("mate", tools.cxTwoPoint)
self.toolbox.register("mutate", tools.mutFlipBit, indpb=0.05)
self.toolbox.register("select", tools.selTournament, tournsize=3)
return
def evaluate_inner(self,individual, ems,start_hour):
discharge_hours_bin = individual[0::2]
eautocharge_hours_float = individual[1::2]
ems.reset()
ems.set_akku_discharge_hours(discharge_hours_bin)
ems.set_eauto_charge_hours(eautocharge_hours_float)
o = ems.simuliere(start_hour)
return o
# Fitness-Funktion (muss Ihre EnergieManagementSystem-Logik integrieren)
def evaluate(self,individual,ems,parameter,start_hour):
o = self.evaluate_inner(individual,ems,start_hour)
gesamtbilanz = o["Gesamtbilanz_Euro"]
# Überprüfung, ob der Mindest-SoC erreicht wird
final_soc = ems.eauto.ladezustand_in_prozent() # Nimmt den SoC am Ende des Optimierungszeitraums
strafe = 0.0
strafe = max(0,(parameter['eauto_min_soc']-ems.eauto.ladezustand_in_prozent()) * self.strafe )
gesamtbilanz += strafe
gesamtbilanz += o["Gesamt_Verluste"]/1000.0
return (gesamtbilanz,)
# Genetischer Algorithmus
def optimize(self,start_solution=None):
population = self.toolbox.population(n=100)
hof = tools.HallOfFame(1)
stats = tools.Statistics(lambda ind: ind.fitness.values)
stats.register("avg", np.mean)
stats.register("min", np.min)
stats.register("max", np.max)
print("Start:",start_solution)
if start_solution is not None and start_solution != -1:
population.insert(0, creator.Individual(start_solution))
#algorithms.eaMuPlusLambda(population, self.toolbox, 100, 200, cxpb=0.3, mutpb=0.3, ngen=500, stats=stats, halloffame=hof, verbose=True)
algorithms.eaSimple(population, self.toolbox, cxpb=0.8, mutpb=0.8, ngen=400, stats=stats, halloffame=hof, verbose=True)
return hof[0]
def optimierung_ems(self,parameter=None, start_hour=None):
############
# Parameter
############
date = (datetime.now().date() + timedelta(hours = self.prediction_hours)).strftime("%Y-%m-%d")
date_now = datetime.now().strftime("%Y-%m-%d")
akku_size = parameter['pv_akku_cap'] # Wh
year_energy = parameter['year_energy'] #2000*1000 #Wh
einspeiseverguetung_euro_pro_wh = np.full(self.prediction_hours, parameter["einspeiseverguetung_euro_pro_wh"]) #= # € / Wh 7/(1000.0*100.0)
max_heizleistung = parameter['max_heizleistung'] #1000 # 5 kW Heizleistung
wp = Waermepumpe(max_heizleistung,self.prediction_hours)
pv_forecast_url = parameter['pv_forecast_url'] #"https://api.akkudoktor.net/forecast?lat=52.52&lon=13.405&power=5000&azimuth=-10&tilt=7&powerInvertor=10000&horizont=20,27,22,20&power=4800&azimuth=-90&tilt=7&powerInvertor=10000&horizont=30,30,30,50&power=1400&azimuth=-40&tilt=60&powerInvertor=2000&horizont=60,30,0,30&power=1600&azimuth=5&tilt=45&powerInvertor=1400&horizont=45,25,30,60&past_days=5&cellCoEff=-0.36&inverterEfficiency=0.8&albedo=0.25&timezone=Europe%2FBerlin&hourly=relativehumidity_2m%2Cwindspeed_10m"
akku = PVAkku(kapazitaet_wh=akku_size,hours=self.prediction_hours,start_soc_prozent=parameter["pv_soc"])
discharge_array = np.full(self.prediction_hours,1) #np.array([1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0]) #
laden_moeglich = np.full(self.prediction_hours,1) # np.array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 0])
eauto = PVAkku(kapazitaet_wh=parameter["eauto_cap"], hours=self.prediction_hours, lade_effizienz=parameter["eauto_charge_efficiency"], entlade_effizienz=1.0, max_ladeleistung_w=parameter["eauto_charge_power"] ,start_soc_prozent=parameter["eauto_soc"])
eauto.set_charge_per_hour(laden_moeglich)
min_soc_eauto = parameter['eauto_min_soc']
start_params = parameter['start_solution']
gesamtlast = Gesamtlast()
###############
# Load Forecast
###############
lf = LoadForecast(filepath=r'load_profiles.npz', year_energy=year_energy)
#leistung_haushalt = lf.get_daily_stats(date)[0,...] # Datum anpassen
leistung_haushalt = lf.get_stats_for_date_range(date_now,date)[0,...].flatten()
gesamtlast.hinzufuegen("Haushalt", leistung_haushalt)
###############
# PV Forecast
###############
#PVforecast = PVForecast(filepath=os.path.join(r'test_data', r'pvprognose.json'))
PVforecast = PVForecast(prediction_hours = self.prediction_hours, url=pv_forecast_url)
#print("PVPOWER",parameter['pvpowernow'])
if isfloat(parameter['pvpowernow']):
PVforecast.update_ac_power_measurement(date_time=datetime.now(), ac_power_measurement=float(parameter['pvpowernow']))
#PVforecast.print_ac_power_and_measurement()
pv_forecast = PVforecast.get_pv_forecast_for_date_range(date_now,date) #get_forecast_for_date(date)
temperature_forecast = PVforecast.get_temperature_for_date_range(date_now,date)
###############
# Strompreise
###############
filepath = os.path.join (r'test_data', r'strompreise_akkudokAPI.json') # Pfad zur JSON-Datei anpassen
#price_forecast = HourlyElectricityPriceForecast(source=filepath)
price_forecast = HourlyElectricityPriceForecast(source="https://api.akkudoktor.net/prices?start="+date_now+"&end="+date+"")
specific_date_prices = price_forecast.get_price_for_daterange(date_now,date)
###############
# WP
##############
leistung_wp = wp.simulate_24h(temperature_forecast)
gesamtlast.hinzufuegen("Heatpump", leistung_wp)
ems = EnergieManagementSystem(akku=akku, gesamtlast = gesamtlast, pv_prognose_wh=pv_forecast, strompreis_euro_pro_wh=specific_date_prices, einspeiseverguetung_euro_pro_wh=einspeiseverguetung_euro_pro_wh, eauto=eauto)
o = ems.simuliere(start_hour)
def evaluate_wrapper(individual):
return self.evaluate(individual, ems, parameter,start_hour)
self.toolbox.register("evaluate", evaluate_wrapper)
start_solution = self.optimize(start_params)
best_solution = start_solution
o = self.evaluate_inner(best_solution, ems,start_hour)
eauto = ems.eauto.to_dict()
discharge_hours_bin = best_solution[0::2]
eautocharge_hours_float = best_solution[1::2]
#print(o)
visualisiere_ergebnisse(gesamtlast, pv_forecast, specific_date_prices, o,best_solution[0::2],best_solution[1::2] , temperature_forecast, start_hour, self.prediction_hours,einspeiseverguetung_euro_pro_wh)
os.system("scp visualisierungsergebnisse.pdf andreas@192.168.1.135:")
#print(eauto)
return {"discharge_hours_bin":discharge_hours_bin, "eautocharge_hours_float":eautocharge_hours_float ,"result":o ,"eauto_obj":eauto,"start_solution":best_solution}