Compare commits
10 Commits
3ad2e47361
...
54657cffd5
| Author | SHA1 | Date | |
|---|---|---|---|
| 54657cffd5 | |||
|
|
210a2f9bc3 | ||
|
|
ff88aacf4d | ||
|
|
9c7e5f418a | ||
| 65a56bb5a2 | |||
| eb130b6be2 | |||
|
|
abe1c9d83d | ||
|
|
f248d74dbe | ||
|
|
1cf5b45563 | ||
| 047ee6ee0f |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1 +1,2 @@
|
||||
__pycache__/
|
||||
production_profile.csv
|
||||
35042
Lastprofil_SWBT.csv
Normal file
35042
Lastprofil_SWBT.csv
Normal file
File diff suppressed because it is too large
Load Diff
BIN
Lastprofil_VDEW.xls
Normal file
BIN
Lastprofil_VDEW.xls
Normal file
Binary file not shown.
8762
Lastprofil_final_H0.csv
Normal file
8762
Lastprofil_final_H0.csv
Normal file
File diff suppressed because it is too large
Load Diff
8761
Lastprofile_gesamt.csv
Normal file
8761
Lastprofile_gesamt.csv
Normal file
File diff suppressed because it is too large
Load Diff
22
Leitungssimulation.py
Normal file
22
Leitungssimulation.py
Normal file
@@ -0,0 +1,22 @@
|
||||
import numpy as np
|
||||
import math
|
||||
import matplotlib as plt
|
||||
|
||||
#Units are SI-Units except for cable cross-section
|
||||
|
||||
def distance(x1,y1,x2,y2):
|
||||
distance = math.sqrt(((x2-x1)^2)*((y2-y1)^2))
|
||||
return distance
|
||||
|
||||
def resistance(l,a,rho):
|
||||
#Calculate the resistance between 2 coordinates
|
||||
#Add 10% of length for various factors such as transitions and hanging lines
|
||||
r = l*a*rho
|
||||
return r
|
||||
|
||||
def power_loss(resitance,voltage,power):
|
||||
loss = (voltage^2)/resistance
|
||||
return loss
|
||||
|
||||
def run():
|
||||
distance(1,2,3,4)
|
||||
18
conversion.py
Normal file
18
conversion.py
Normal file
@@ -0,0 +1,18 @@
|
||||
import csv
|
||||
|
||||
def process_csv(input_file, output_file):
|
||||
n = -2
|
||||
with open(input_file, mode='r', newline='') as infile:
|
||||
reader = csv.reader(infile)
|
||||
with open(output_file, mode='w', newline='') as outfile:
|
||||
writer = csv.writer(outfile)
|
||||
for row in reader:
|
||||
n = n + 1
|
||||
if n==4:
|
||||
writer.writerow(row)
|
||||
n = 0
|
||||
|
||||
# Beispielhafte Verwendung
|
||||
input_file = 'Lastprofil_SWBT.csv'
|
||||
output_file = 'Lastprofil_final_H0.csv'
|
||||
process_csv(input_file, output_file)
|
||||
20
main.py
20
main.py
@@ -1,17 +1,17 @@
|
||||
from neighborhood import Producer, Consumer, Neighborhood
|
||||
|
||||
# Anzahl Haushalte ohne PV-Anlagen
|
||||
num_consumer = 50
|
||||
avg_consumption_per_consumer = 10
|
||||
# Consumer-Instanzen anlegen
|
||||
standard_consumer = Consumer(quantity=10, profile_type='std')
|
||||
wp_consumer = Consumer(quantity=0, profile_type='wp')
|
||||
ea_consumer = Consumer(quantity=0, profile_type='ea')
|
||||
|
||||
# Anzahl Haushalte mit PV-Anlagen
|
||||
num_producer = 10
|
||||
avg_production_per_producer = 20
|
||||
|
||||
# Instanzen für Erzeuger und Verbraucher anlegen
|
||||
consumer = Consumer(num_consumer, avg_consumption_per_consumer)
|
||||
producer = Producer(num_producer, avg_consumption_per_consumer, avg_production_per_producer)
|
||||
# Producer-Instanz anlegen
|
||||
standard_producer = Producer(quantity=0, profile_type='std')
|
||||
wp_producer = Producer(quantity=0, profile_type='wp')
|
||||
ea_producer = Producer(quantity=0, profile_type='ea')
|
||||
|
||||
|
||||
# Instanz für Nachbarschaft anlegen und Ergebnis plotten
|
||||
neighborhood = Neighborhood(producer, consumer)
|
||||
neighborhood = Neighborhood(producers=[standard_producer, wp_producer, ea_producer], consumers=[standard_consumer, wp_consumer, ea_consumer])
|
||||
neighborhood.plot_consumption()
|
||||
170
neighborhood.py
170
neighborhood.py
@@ -1,90 +1,134 @@
|
||||
import numpy as np
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
class Consumer:
|
||||
def __init__(self, quantity, average_consumption):
|
||||
self.quantity = quantity
|
||||
self.consumption_profile = self.create_consumption_profile()
|
||||
self.average_consumption = average_consumption
|
||||
|
||||
def create_consumption_profile(self):
|
||||
profile = np.zeros(24)
|
||||
peak_hours = [12]
|
||||
for hour in peak_hours:
|
||||
profile[hour] = 1.5
|
||||
for hour in range(24):
|
||||
if hour not in peak_hours:
|
||||
profile[hour] = 0.8
|
||||
return profile
|
||||
|
||||
def calculate_daily_consumption(self):
|
||||
daily_consumption = self.quantity * self.average_consumption * self.consumption_profile
|
||||
return daily_consumption
|
||||
import pv_input as pv
|
||||
import pandas as pd
|
||||
|
||||
class Producer:
|
||||
def __init__(self, quantity, average_consumption, average_production):
|
||||
def __init__(self, quantity, profile_type):
|
||||
self.quantity = quantity
|
||||
self.profile_type = profile_type
|
||||
self.consumption_profile = self.create_consumption_profile()
|
||||
self.average_consumption = average_consumption
|
||||
self.production_profile = self.create_production_profile()
|
||||
self.average_production = average_production
|
||||
self.final_consumption = self.calculate_final_consumption()
|
||||
self.final_production = self.calculate_final_production()
|
||||
|
||||
# Vebrauchsprofile aus CSV-Datei in Dataframe einlesen und je nach profile_type die entsprechende Leistungs-Series extrahieren
|
||||
def create_consumption_profile(self):
|
||||
profile = np.zeros(24)
|
||||
peak_hours = [8,12,13,18,19,20,21]
|
||||
for hour in peak_hours:
|
||||
profile[hour] = 1.5
|
||||
for hour in range(24):
|
||||
if hour not in peak_hours:
|
||||
profile[hour] = 0.5
|
||||
return profile
|
||||
if self.profile_type == 'std':
|
||||
consumption_profile = pd.read_csv('Lastprofile_gesamt.csv',delimiter=';')
|
||||
return consumption_profile['Leistung']*1000
|
||||
elif self.profile_type == 'wp':
|
||||
consumption_profile = pd.read_csv('Lastprofile_gesamt.csv',delimiter=';')
|
||||
return consumption_profile['Leistung_WP']*1000
|
||||
elif self.profile_type == 'ea':
|
||||
consumption_profile = pd.read_csv('Lastprofile_gesamt.csv',delimiter=';')
|
||||
return consumption_profile['Leistung_EA']*1000
|
||||
|
||||
# Verbrauchsprofil mit der Anzahl der entsprechenden Haushalte multiplizieren
|
||||
def calculate_final_consumption(self):
|
||||
final_consumption = self.consumption_profile.mul(self.quantity)
|
||||
return final_consumption
|
||||
|
||||
# Erzegungsprofil über PV_Input.py erstelln, in .csv schreiben und von dort dann die Leistungs-Series extrahieren
|
||||
def create_production_profile(self):
|
||||
profile = np.zeros(24)
|
||||
peak_hours = [8,9,10,11,12,13,14,15,16,17,18,19]
|
||||
for hour in peak_hours:
|
||||
profile[hour] = 1.5
|
||||
for hour in range(24):
|
||||
if hour not in peak_hours:
|
||||
profile[hour] = 0
|
||||
return profile
|
||||
production_profile = pv.create_production_profile()
|
||||
production_profile.to_csv('production_profile.csv', sep=';',header=['Leistung'])
|
||||
production_profile = pd.read_csv('production_profile.csv',delimiter=';')
|
||||
return production_profile['Leistung']
|
||||
|
||||
# Erzeugungsprofil mit der Anzahl der entsprechenden Haushalte multiplizieren
|
||||
def calculate_final_production(self):
|
||||
final_production = self.production_profile.mul(self.quantity)
|
||||
return final_production
|
||||
|
||||
|
||||
|
||||
class Consumer:
|
||||
def __init__(self, quantity, profile_type):
|
||||
self.quantity = quantity
|
||||
self.profile_type = profile_type
|
||||
self.consumption_profile = self.create_consumption_profile()
|
||||
self.final_consumption = self.calculate_final_consumption()
|
||||
|
||||
# Vebrauchsprofile aus CSV-Datei in Dataframe einlesen und je nach profile_type die entsprechende Leistungs-Series extrahieren
|
||||
def create_consumption_profile(self):
|
||||
if self.profile_type == 'std':
|
||||
consumption_profile = pd.read_csv('Lastprofile_gesamt.csv',delimiter=';')
|
||||
return consumption_profile['Leistung']*1000
|
||||
elif self.profile_type == 'wp':
|
||||
consumption_profile = pd.read_csv('Lastprofile_gesamt.csv',delimiter=';')
|
||||
return consumption_profile['Leistung_WP']*1000
|
||||
elif self.profile_type == 'ea':
|
||||
consumption_profile = pd.read_csv('Lastprofile_gesamt.csv',delimiter=';')
|
||||
return consumption_profile['Leistung_EA']*1000
|
||||
|
||||
|
||||
# Verbrauchsprofil mit der Anzahl der entsprechenden Haushalte multiplizieren
|
||||
def calculate_final_consumption(self):
|
||||
final_consumption = self.consumption_profile.mul(self.quantity)
|
||||
return final_consumption
|
||||
|
||||
def calculate_daily_consumption(self):
|
||||
daily_consumption = self.quantity * self.average_consumption * self.consumption_profile
|
||||
return daily_consumption
|
||||
|
||||
def calculate_daily_production(self):
|
||||
daily_production = self.quantity * self.average_production * self.production_profile
|
||||
return daily_production
|
||||
|
||||
class Neighborhood:
|
||||
def __init__(self, producer, consumer):
|
||||
self.producer = producer
|
||||
self.consumer = consumer
|
||||
def __init__(self, producers, consumers):
|
||||
self.producers = producers if isinstance(producers, list) else [producers]
|
||||
self.consumers = consumers if isinstance(consumers, list) else [consumers]
|
||||
|
||||
# Gesamterzeugung, Gesamtverbrauch und Nettoverbrauch plotten
|
||||
def plot_consumption(self):
|
||||
total_consumption = -1*(self.consumer.calculate_daily_consumption() + self.producer.calculate_daily_consumption())
|
||||
total_production = self.producer.calculate_daily_production()
|
||||
total_consumption = 0
|
||||
total_production = 0
|
||||
# Verbrauch der Consumer subtrahieren
|
||||
for consumer in self.consumers:
|
||||
total_consumption -= consumer.final_consumption
|
||||
# Zusätzlich Verbrauch der Producer subtrahieren
|
||||
for producer in self.producers:
|
||||
total_consumption -= producer.final_consumption
|
||||
# Produktion der Producer addieren
|
||||
for producer in self.producers:
|
||||
total_production += producer.final_production
|
||||
# Netto-Erzeugnis ausrechnen
|
||||
net_value = total_consumption + total_production
|
||||
# Rollendes Mittel des netto-Erzeugnisses ausrechnen
|
||||
net_value_mean = net_value.rolling(24).mean()
|
||||
|
||||
|
||||
# X-Werte anlegen, einen Wert löschen da 8761 Werte vorhanden sind, aber nur 8760 benötigt werden
|
||||
x = pd.date_range(start='2018-12-31', end ='2019-12-31', freq='1h')
|
||||
x = x[:-1]
|
||||
|
||||
# X-Werte anlegen
|
||||
x = range(24)
|
||||
x_labels = ['01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23', '24']
|
||||
# Plot dimensionieren
|
||||
plt.figure(figsize=(10, 6))
|
||||
# y-Werte den x-Werten zuordnen
|
||||
plt.plot(x, total_consumption, '--', x, total_production, '--', x, net_value, '-')
|
||||
# Titel und Achsenbeschriftungen anlegen
|
||||
plt.xlabel('Stunde')
|
||||
plt.ylabel('Strom (kWh)')
|
||||
plt.title('Produktion/Verbrauch Nachbarschaft')
|
||||
# X-Werten die Labels zuordnen
|
||||
plt.xticks(x, x_labels)
|
||||
plt.figure(figsize=(15, 9))
|
||||
|
||||
# Barplots anlegen
|
||||
plt.bar(x, total_consumption)
|
||||
plt.bar(x, total_production,color='orange')
|
||||
|
||||
# Linienplot anlegen
|
||||
#plt.plot(x, net_value,'-',color='darkgreen')
|
||||
plt.plot(x, net_value_mean,'-',color='darkgreen')
|
||||
|
||||
# Achsenbeschriftungen anlegen
|
||||
plt.xlabel('Kalendertag')
|
||||
plt.ylabel('Leistung (W)')
|
||||
|
||||
# Titel anlegen
|
||||
#plt.title('Netto-leistung Nachbarschaft - Fall XXX')
|
||||
plt.title('Erzeugung, Verbrauch und Netto-Leistung (Rollendes Mittel 24h) - Fall XXX')
|
||||
|
||||
# X-Ticks nur monatlich plotten
|
||||
monthly_ticks = pd.date_range(start='2018-12-31', end ='2019-12-31', freq='1MS')
|
||||
plt.xticks(monthly_ticks)
|
||||
|
||||
# Legende anlegen
|
||||
plt.legend(['Verbrauch', 'Produktion', 'Netto-Wert'], loc='upper right')
|
||||
plt.legend(['Netto-Leistung', 'Leistung Verbrauch', 'Leistung Erzeugung'], loc='upper right')
|
||||
|
||||
# X-Labels rotieren
|
||||
plt.xticks(rotation=45)
|
||||
|
||||
# Grid anlegen
|
||||
plt.axhline(linewidth=1, color='black')
|
||||
plt.grid(color='black', axis='y', linestyle='--', linewidth=0.5)
|
||||
plt.show()
|
||||
|
||||
|
||||
63
pv_input.py
63
pv_input.py
@@ -1,3 +1,13 @@
|
||||
# 3 Möglichkeiten für Ertragsberechnung: Clear Sky Modell, TMY oder POA-Data
|
||||
# Clear Sky: Strahlungsmodell, welches theoretische Strahlungsdaten an bestimmten Standpunkt enthält welche eine flache Oberfläche treffen - vewerndet g(i)-Strahlungsdaten
|
||||
# TMY = Typical Meteorolical Year - reale Strahlungsdaten welche eine flache Oberfläche treffen - vewerndet g(i)-Strahlungsdaten
|
||||
# POA = Plane of Array - was das PV-Modul (und dessen Ausrichtung) wirklich trifft - verwendet POA-Strahlungsdaten
|
||||
|
||||
# G(i), poa_global = Global irradiance on inclined plane (W/m^2)
|
||||
# Gb(i), poa_direct = Beam (direct) irradiance on inclined plane (W/m^2)
|
||||
# Gd(i), poa_sky_diffuse = Diffuse irradiance on inclined plane (W/m^2)
|
||||
# Gr(i), poa_ground_diffuse = Reflected irradiance on inclined plane (W/m^2)
|
||||
|
||||
import pvlib
|
||||
import pandas as pd
|
||||
import matplotlib.pyplot as plt
|
||||
@@ -6,22 +16,29 @@ from pvlib.location import Location
|
||||
from pvlib.pvsystem import PVSystem
|
||||
from pvlib.temperature import TEMPERATURE_MODEL_PARAMETERS
|
||||
|
||||
# Daten Standort
|
||||
latitude = 47.2675
|
||||
longitude = 11.3910
|
||||
tz = 'Europe/Vienna'
|
||||
surface_tilt = 0
|
||||
surface_azimuth = 180
|
||||
year = 2019
|
||||
|
||||
# Daten für Datenbank -> Module + WR
|
||||
database_module = pvlib.pvsystem.retrieve_sam('SandiaMod')
|
||||
database_inverter = pvlib.pvsystem.retrieve_sam('CECInverter')
|
||||
|
||||
module = database_module['Canadian_Solar_CS5P_220M___2009_']
|
||||
inverter = database_inverter['ABB__PVI_4_2_OUTD_US__208V_']
|
||||
|
||||
# PV-Anlage definieren
|
||||
modules_per_string = 10
|
||||
strings_per_inverter = 2
|
||||
surface_tilt = 20
|
||||
surface_azimuth = 150
|
||||
|
||||
# Temperaturparameter definieren
|
||||
temperature_parameters = TEMPERATURE_MODEL_PARAMETERS['sapm']['open_rack_glass_glass']
|
||||
|
||||
def create_production_profile():
|
||||
# Location + PVSystem-Objekte anlegen und Modelchain damit füttern
|
||||
location = Location(latitude, longitude, tz)
|
||||
system = PVSystem(surface_tilt=surface_tilt, surface_azimuth=surface_azimuth, module_parameters=module,
|
||||
inverter_parameters=inverter, temperature_model_parameters=temperature_parameters,
|
||||
@@ -29,11 +46,39 @@ system = PVSystem(surface_tilt=surface_tilt, surface_azimuth=surface_azimuth, mo
|
||||
|
||||
modelchain = ModelChain(system, location)
|
||||
|
||||
times = pd.date_range(start='2021-07-01', end ='2021-07-07', freq='1min', tz=location.tz)
|
||||
# Ertragssimulation mit Clear-Sky Modell
|
||||
|
||||
clear_sky = location.get_clearsky(times)
|
||||
#clear_sky.plot(figsize=(16,9))
|
||||
# Index-Spalte mit Zeiten für clear-sky Dataset anlegen
|
||||
# times = pd.date_range(start='2020-01-01', end ='2020-12-31', freq='1h', tz=location.tz)
|
||||
|
||||
modelchain.run_model(clear_sky)
|
||||
modelchain.results.ac.plot(figsize=(16,9))
|
||||
plt.show()
|
||||
# clear_sky = location.get_clearsky(times)
|
||||
# #clear_sky.plot(figsize=(16,9))
|
||||
|
||||
# modelchain.run_model(clear_sky)
|
||||
|
||||
# Ertragssimulation mit realen Strahlungsdaten aus Wetterjahr
|
||||
|
||||
# Hier ist Süden Azimuth = 0°, bei PVLib ist es 180°
|
||||
poa_data, meta, inputs = pvlib.iotools.get_pvgis_hourly(latitude=latitude, longitude=longitude, start=year, end=year, raddatabase='PVGIS-SARAH3', components=True, surface_tilt=surface_tilt,
|
||||
surface_azimuth=surface_azimuth-150, outputformat='json', usehorizon=True, userhorizon=None, pvcalculation=False, peakpower=None,
|
||||
pvtechchoice='crystSi', mountingplace='free', loss=0, trackingtype=0, optimal_surface_tilt=False, optimalangles=False,
|
||||
url='https://re.jrc.ec.europa.eu/api/', map_variables=True, timeout=30)
|
||||
|
||||
# Notwendige Spalten ausrechnen und hinzufügen, sodass Modelchain sie verwenden kann
|
||||
poa_data['poa_diffuse'] = poa_data['poa_sky_diffuse'] + poa_data['poa_ground_diffuse']
|
||||
poa_data['poa_global'] = poa_data['poa_diffuse'] + poa_data['poa_direct']
|
||||
|
||||
# Daten in csv exportieren
|
||||
#poa_data.to_csv('poa_data.csv')
|
||||
|
||||
# Index des Dataframe mit datetime-Index von Pandas überschreiben
|
||||
poa_data.index = pd.to_datetime((poa_data.index))
|
||||
# Diese Funktion benötigt POA-Daten anstatt g(i)-Daten -> DOKU
|
||||
modelchain.run_model_from_poa(poa_data)
|
||||
|
||||
# Ergebnis plotten
|
||||
#modelchain.results.ac.plot(figsize=(16,9))
|
||||
#plt.show()
|
||||
|
||||
# Rückgabewert
|
||||
return modelchain.results.ac
|
||||
Reference in New Issue
Block a user