Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 54657cffd5 | |||
| 210a2f9bc3 | |||
| ff88aacf4d | |||
| 9c7e5f418a | |||
| 65a56bb5a2 | |||
| eb130b6be2 | |||
| abe1c9d83d | |||
| f248d74dbe | |||
| 1cf5b45563 | |||
| 047ee6ee0f |
@@ -1 +1,2 @@
|
|||||||
__pycache__/
|
__pycache__/
|
||||||
|
production_profile.csv
|
||||||
+35042
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
@@ -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)
|
||||||
@@ -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)
|
||||||
@@ -1,17 +1,17 @@
|
|||||||
from neighborhood import Producer, Consumer, Neighborhood
|
from neighborhood import Producer, Consumer, Neighborhood
|
||||||
|
|
||||||
# Anzahl Haushalte ohne PV-Anlagen
|
# Consumer-Instanzen anlegen
|
||||||
num_consumer = 50
|
standard_consumer = Consumer(quantity=10, profile_type='std')
|
||||||
avg_consumption_per_consumer = 10
|
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
|
# Producer-Instanz anlegen
|
||||||
consumer = Consumer(num_consumer, avg_consumption_per_consumer)
|
standard_producer = Producer(quantity=0, profile_type='std')
|
||||||
producer = Producer(num_producer, avg_consumption_per_consumer, avg_production_per_producer)
|
wp_producer = Producer(quantity=0, profile_type='wp')
|
||||||
|
ea_producer = Producer(quantity=0, profile_type='ea')
|
||||||
|
|
||||||
|
|
||||||
# Instanz für Nachbarschaft anlegen und Ergebnis plotten
|
# 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()
|
neighborhood.plot_consumption()
|
||||||
+107
-63
@@ -1,90 +1,134 @@
|
|||||||
import numpy as np
|
import numpy as np
|
||||||
import matplotlib.pyplot as plt
|
import matplotlib.pyplot as plt
|
||||||
|
import pv_input as pv
|
||||||
class Consumer:
|
import pandas as pd
|
||||||
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
|
|
||||||
|
|
||||||
class Producer:
|
class Producer:
|
||||||
def __init__(self, quantity, average_consumption, average_production):
|
def __init__(self, quantity, profile_type):
|
||||||
self.quantity = quantity
|
self.quantity = quantity
|
||||||
|
self.profile_type = profile_type
|
||||||
self.consumption_profile = self.create_consumption_profile()
|
self.consumption_profile = self.create_consumption_profile()
|
||||||
self.average_consumption = average_consumption
|
|
||||||
self.production_profile = self.create_production_profile()
|
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):
|
def create_consumption_profile(self):
|
||||||
profile = np.zeros(24)
|
if self.profile_type == 'std':
|
||||||
peak_hours = [8,12,13,18,19,20,21]
|
consumption_profile = pd.read_csv('Lastprofile_gesamt.csv',delimiter=';')
|
||||||
for hour in peak_hours:
|
return consumption_profile['Leistung']*1000
|
||||||
profile[hour] = 1.5
|
elif self.profile_type == 'wp':
|
||||||
for hour in range(24):
|
consumption_profile = pd.read_csv('Lastprofile_gesamt.csv',delimiter=';')
|
||||||
if hour not in peak_hours:
|
return consumption_profile['Leistung_WP']*1000
|
||||||
profile[hour] = 0.5
|
elif self.profile_type == 'ea':
|
||||||
return profile
|
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):
|
def create_production_profile(self):
|
||||||
profile = np.zeros(24)
|
production_profile = pv.create_production_profile()
|
||||||
peak_hours = [8,9,10,11,12,13,14,15,16,17,18,19]
|
production_profile.to_csv('production_profile.csv', sep=';',header=['Leistung'])
|
||||||
for hour in peak_hours:
|
production_profile = pd.read_csv('production_profile.csv',delimiter=';')
|
||||||
profile[hour] = 1.5
|
return production_profile['Leistung']
|
||||||
for hour in range(24):
|
|
||||||
if hour not in peak_hours:
|
# Erzeugungsprofil mit der Anzahl der entsprechenden Haushalte multiplizieren
|
||||||
profile[hour] = 0
|
def calculate_final_production(self):
|
||||||
return profile
|
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:
|
class Neighborhood:
|
||||||
def __init__(self, producer, consumer):
|
def __init__(self, producers, consumers):
|
||||||
self.producer = producer
|
self.producers = producers if isinstance(producers, list) else [producers]
|
||||||
self.consumer = consumer
|
self.consumers = consumers if isinstance(consumers, list) else [consumers]
|
||||||
|
|
||||||
|
# Gesamterzeugung, Gesamtverbrauch und Nettoverbrauch plotten
|
||||||
def plot_consumption(self):
|
def plot_consumption(self):
|
||||||
total_consumption = -1*(self.consumer.calculate_daily_consumption() + self.producer.calculate_daily_consumption())
|
total_consumption = 0
|
||||||
total_production = self.producer.calculate_daily_production()
|
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
|
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
|
# Plot dimensionieren
|
||||||
plt.figure(figsize=(10, 6))
|
plt.figure(figsize=(15, 9))
|
||||||
# y-Werte den x-Werten zuordnen
|
|
||||||
plt.plot(x, total_consumption, '--', x, total_production, '--', x, net_value, '-')
|
# Barplots anlegen
|
||||||
# Titel und Achsenbeschriftungen anlegen
|
plt.bar(x, total_consumption)
|
||||||
plt.xlabel('Stunde')
|
plt.bar(x, total_production,color='orange')
|
||||||
plt.ylabel('Strom (kWh)')
|
|
||||||
plt.title('Produktion/Verbrauch Nachbarschaft')
|
# Linienplot anlegen
|
||||||
# X-Werten die Labels zuordnen
|
#plt.plot(x, net_value,'-',color='darkgreen')
|
||||||
plt.xticks(x, x_labels)
|
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
|
# 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
|
# X-Labels rotieren
|
||||||
plt.xticks(rotation=45)
|
plt.xticks(rotation=45)
|
||||||
|
|
||||||
# Grid anlegen
|
# Grid anlegen
|
||||||
|
plt.axhline(linewidth=1, color='black')
|
||||||
plt.grid(color='black', axis='y', linestyle='--', linewidth=0.5)
|
plt.grid(color='black', axis='y', linestyle='--', linewidth=0.5)
|
||||||
plt.show()
|
plt.show()
|
||||||
|
|
||||||
|
|||||||
+57
-12
@@ -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 pvlib
|
||||||
import pandas as pd
|
import pandas as pd
|
||||||
import matplotlib.pyplot as plt
|
import matplotlib.pyplot as plt
|
||||||
@@ -6,34 +16,69 @@ from pvlib.location import Location
|
|||||||
from pvlib.pvsystem import PVSystem
|
from pvlib.pvsystem import PVSystem
|
||||||
from pvlib.temperature import TEMPERATURE_MODEL_PARAMETERS
|
from pvlib.temperature import TEMPERATURE_MODEL_PARAMETERS
|
||||||
|
|
||||||
|
# Daten Standort
|
||||||
latitude = 47.2675
|
latitude = 47.2675
|
||||||
longitude = 11.3910
|
longitude = 11.3910
|
||||||
tz = 'Europe/Vienna'
|
tz = 'Europe/Vienna'
|
||||||
surface_tilt = 0
|
year = 2019
|
||||||
surface_azimuth = 180
|
|
||||||
|
|
||||||
|
# Daten für Datenbank -> Module + WR
|
||||||
database_module = pvlib.pvsystem.retrieve_sam('SandiaMod')
|
database_module = pvlib.pvsystem.retrieve_sam('SandiaMod')
|
||||||
database_inverter = pvlib.pvsystem.retrieve_sam('CECInverter')
|
database_inverter = pvlib.pvsystem.retrieve_sam('CECInverter')
|
||||||
|
|
||||||
module = database_module['Canadian_Solar_CS5P_220M___2009_']
|
module = database_module['Canadian_Solar_CS5P_220M___2009_']
|
||||||
inverter = database_inverter['ABB__PVI_4_2_OUTD_US__208V_']
|
inverter = database_inverter['ABB__PVI_4_2_OUTD_US__208V_']
|
||||||
|
|
||||||
|
# PV-Anlage definieren
|
||||||
modules_per_string = 10
|
modules_per_string = 10
|
||||||
strings_per_inverter = 2
|
strings_per_inverter = 2
|
||||||
|
surface_tilt = 20
|
||||||
|
surface_azimuth = 150
|
||||||
|
|
||||||
|
# Temperaturparameter definieren
|
||||||
temperature_parameters = TEMPERATURE_MODEL_PARAMETERS['sapm']['open_rack_glass_glass']
|
temperature_parameters = TEMPERATURE_MODEL_PARAMETERS['sapm']['open_rack_glass_glass']
|
||||||
|
|
||||||
location = Location(latitude, longitude, tz)
|
def create_production_profile():
|
||||||
system = PVSystem(surface_tilt=surface_tilt, surface_azimuth=surface_azimuth, module_parameters=module,
|
# 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,
|
inverter_parameters=inverter, temperature_model_parameters=temperature_parameters,
|
||||||
modules_per_string=modules_per_string, strings_per_inverter=strings_per_inverter)
|
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)
|
# Index-Spalte mit Zeiten für clear-sky Dataset anlegen
|
||||||
#clear_sky.plot(figsize=(16,9))
|
# times = pd.date_range(start='2020-01-01', end ='2020-12-31', freq='1h', tz=location.tz)
|
||||||
|
|
||||||
modelchain.run_model(clear_sky)
|
# clear_sky = location.get_clearsky(times)
|
||||||
modelchain.results.ac.plot(figsize=(16,9))
|
# #clear_sky.plot(figsize=(16,9))
|
||||||
plt.show()
|
|
||||||
|
# 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