Compare commits

...

10 Commits

Author SHA1 Message Date
gitadmin 54657cffd5 Lastprofile angepasst, variable Zahl an Producer+Consumer 2025-01-07 21:04:56 +01:00
Patrick Hangl 210a2f9bc3 Einlesen .csv angepasst 2025-01-07 16:02:19 +01:00
Patrick Hangl ff88aacf4d lastprofile angepasst 2025-01-07 16:01:57 +01:00
MundM99 9c7e5f418a Kleiner Prototyp für Leistungssimulation eingefügt 2025-01-04 08:48:12 +01:00
gitadmin 65a56bb5a2 PV-Ausrichtung angepasst, Neighborhood formatiert 2025-01-03 14:48:00 +01:00
gitadmin eb130b6be2 Modell funktioniert, Jahr 2019 eingestellt 2025-01-01 12:08:07 +01:00
Patrick Hangl abe1c9d83d Conversion Skript für stündliche Werte aus csv 2024-12-19 15:26:43 +01:00
Patrick Hangl f248d74dbe Lastprofile organisiert 2024-12-18 13:23:16 +01:00
Patrick Hangl 1cf5b45563 pv_input auskommentiert 2024-12-16 10:39:59 +01:00
gitadmin 047ee6ee0f Wetterdaten eingebunden 2024-12-15 22:02:41 +01:00
10 changed files with 52787 additions and 92 deletions
+1
View File
@@ -1 +1,2 @@
__pycache__/
production_profile.csv
+35042
View File
File diff suppressed because it is too large Load Diff
Binary file not shown.
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+22
View 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
View 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)
+10 -10
View File
@@ -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()
+107 -63
View File
@@ -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()
+57 -12
View File
@@ -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,34 +16,69 @@ 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']
location = Location(latitude, longitude, tz)
system = PVSystem(surface_tilt=surface_tilt, surface_azimuth=surface_azimuth, module_parameters=module,
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,
modules_per_string=modules_per_string, strings_per_inverter=strings_per_inverter)
modelchain = ModelChain(system, location)
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