2024-02-18 15:53:29 +01:00
import numpy as np
2024-09-20 12:02:31 +02:00
2024-02-18 14:32:27 +01:00
class PVAkku :
2024-09-20 12:02:31 +02:00
def __init__ ( self , kapazitaet_wh = None , hours = None , lade_effizienz = 0.88 , entlade_effizienz = 0.88 ,
max_ladeleistung_w = None , start_soc_prozent = 0 , min_soc_prozent = 0 , max_soc_prozent = 100 ) :
# Battery capacity in Wh
2024-02-18 14:32:27 +01:00
self . kapazitaet_wh = kapazitaet_wh
2024-09-20 12:02:31 +02:00
# Initial state of charge in Wh
2024-03-25 14:40:48 +01:00
self . start_soc_prozent = start_soc_prozent
self . soc_wh = ( start_soc_prozent / 100 ) * kapazitaet_wh
2024-02-25 16:47:28 +01:00
self . hours = hours
self . discharge_array = np . full ( self . hours , 1 )
2024-03-25 14:40:48 +01:00
self . charge_array = np . full ( self . hours , 1 )
2024-09-20 12:02:31 +02:00
# Charge and discharge efficiency
2024-03-03 18:32:47 +01:00
self . lade_effizienz = lade_effizienz
self . entlade_effizienz = entlade_effizienz
2024-03-25 14:40:48 +01:00
self . max_ladeleistung_w = max_ladeleistung_w if max_ladeleistung_w else self . kapazitaet_wh
2024-03-31 13:00:01 +02:00
self . min_soc_prozent = min_soc_prozent
self . max_soc_prozent = max_soc_prozent
2024-03-25 14:40:48 +01:00
2024-03-28 08:16:57 +01:00
def to_dict ( self ) :
return {
" kapazitaet_wh " : self . kapazitaet_wh ,
" start_soc_prozent " : self . start_soc_prozent ,
" soc_wh " : self . soc_wh ,
" hours " : self . hours ,
2024-09-20 12:02:31 +02:00
" discharge_array " : self . discharge_array . tolist ( ) , # Convert np.array to list
2024-03-28 08:16:57 +01:00
" charge_array " : self . charge_array . tolist ( ) ,
" lade_effizienz " : self . lade_effizienz ,
" entlade_effizienz " : self . entlade_effizienz ,
" max_ladeleistung_w " : self . max_ladeleistung_w
}
@classmethod
def from_dict ( cls , data ) :
2024-09-20 12:02:31 +02:00
# Create a new object with basic data
2024-03-28 08:16:57 +01:00
obj = cls (
kapazitaet_wh = data [ " kapazitaet_wh " ] ,
hours = data [ " hours " ] ,
lade_effizienz = data [ " lade_effizienz " ] ,
entlade_effizienz = data [ " entlade_effizienz " ] ,
max_ladeleistung_w = data [ " max_ladeleistung_w " ] ,
start_soc_prozent = data [ " start_soc_prozent " ]
)
2024-09-20 12:02:31 +02:00
# Set arrays
2024-03-28 08:16:57 +01:00
obj . discharge_array = np . array ( data [ " discharge_array " ] )
obj . charge_array = np . array ( data [ " charge_array " ] )
2024-09-20 12:02:31 +02:00
obj . soc_wh = data [ " soc_wh " ] # Set current state of charge, which may differ from start_soc_prozent
2024-03-28 08:16:57 +01:00
return obj
2024-02-18 15:53:29 +01:00
def reset ( self ) :
2024-03-25 14:40:48 +01:00
self . soc_wh = ( self . start_soc_prozent / 100 ) * self . kapazitaet_wh
2024-02-25 16:47:28 +01:00
self . discharge_array = np . full ( self . hours , 1 )
2024-03-25 14:40:48 +01:00
self . charge_array = np . full ( self . hours , 1 )
2024-09-20 12:02:31 +02:00
2024-02-18 15:53:29 +01:00
def set_discharge_per_hour ( self , discharge_array ) :
2024-09-20 12:02:31 +02:00
assert len ( discharge_array ) == self . hours
2024-03-28 08:16:57 +01:00
self . discharge_array = np . array ( discharge_array )
2024-02-18 14:32:27 +01:00
2024-03-25 14:40:48 +01:00
def set_charge_per_hour ( self , charge_array ) :
2024-09-20 12:02:31 +02:00
assert len ( charge_array ) == self . hours
2024-03-28 08:16:57 +01:00
self . charge_array = np . array ( charge_array )
2024-03-25 14:40:48 +01:00
2024-02-18 14:32:27 +01:00
def ladezustand_in_prozent ( self ) :
return ( self . soc_wh / self . kapazitaet_wh ) * 100
2024-02-18 15:53:29 +01:00
def energie_abgeben ( self , wh , hour ) :
if self . discharge_array [ hour ] == 0 :
2024-09-20 12:02:31 +02:00
return 0.0 , 0.0 # No energy discharge and no losses
2024-03-25 14:40:48 +01:00
2024-09-20 12:02:31 +02:00
# Calculate the maximum discharge amount considering discharge efficiency
2024-03-25 14:40:48 +01:00
max_abgebbar_wh = self . soc_wh * self . entlade_effizienz
2024-09-20 12:02:31 +02:00
# Consider the maximum discharge power of the battery
2024-05-01 14:38:16 +02:00
max_abgebbar_wh = min ( max_abgebbar_wh , self . max_ladeleistung_w )
2024-09-20 12:02:31 +02:00
# The actually discharged energy cannot exceed requested energy or maximum discharge
2024-03-25 14:40:48 +01:00
tatsaechlich_abgegeben_wh = min ( wh , max_abgebbar_wh )
2024-09-20 12:02:31 +02:00
# Calculate the actual amount withdrawn from the battery (before efficiency loss)
2024-03-25 14:40:48 +01:00
tatsaechliche_entnahme_wh = tatsaechlich_abgegeben_wh / self . entlade_effizienz
2024-09-20 12:02:31 +02:00
# Update the state of charge considering the actual withdrawal
2024-03-25 14:40:48 +01:00
self . soc_wh - = tatsaechliche_entnahme_wh
2024-09-20 12:02:31 +02:00
# Calculate losses due to efficiency
2024-03-25 14:40:48 +01:00
verluste_wh = tatsaechliche_entnahme_wh - tatsaechlich_abgegeben_wh
2024-03-03 18:32:47 +01:00
2024-09-20 12:02:31 +02:00
# Return the actually discharged energy and the losses
2024-03-25 14:40:48 +01:00
return tatsaechlich_abgegeben_wh , verluste_wh
def energie_laden ( self , wh , hour ) :
if hour is not None and self . charge_array [ hour ] == 0 :
2024-09-20 12:02:31 +02:00
return 0 , 0 # Charging not allowed in this hour
2024-03-25 14:40:48 +01:00
2024-09-20 12:02:31 +02:00
# If no value for wh is given, use the maximum charging power
2024-03-25 14:40:48 +01:00
wh = wh if wh is not None else self . max_ladeleistung_w
2024-08-24 10:22:49 +02:00
2024-09-20 12:02:31 +02:00
# Relative to the maximum charging power (between 0 and 1)
2024-08-24 10:22:49 +02:00
relative_ladeleistung = self . charge_array [ hour ]
effektive_ladeleistung = relative_ladeleistung * self . max_ladeleistung_w
2024-03-25 14:40:48 +01:00
2024-09-20 12:02:31 +02:00
# Calculate the actual charging amount considering charging efficiency
2024-08-24 10:22:49 +02:00
effektive_lademenge = min ( wh , effektive_ladeleistung )
2024-03-25 14:40:48 +01:00
2024-09-20 12:02:31 +02:00
# Update the state of charge without exceeding capacity
2024-03-31 13:00:01 +02:00
geladene_menge_ohne_verlust = min ( self . kapazitaet_wh - self . soc_wh , effektive_lademenge )
2024-05-02 10:27:33 +02:00
2024-03-31 13:00:01 +02:00
geladene_menge = geladene_menge_ohne_verlust * self . lade_effizienz
2024-05-02 10:27:33 +02:00
2024-03-25 14:40:48 +01:00
self . soc_wh + = geladene_menge
2024-09-20 12:02:31 +02:00
verluste_wh = geladene_menge_ohne_verlust * ( 1.0 - self . lade_effizienz )
2024-08-24 10:22:49 +02:00
return geladene_menge , verluste_wh
2024-08-30 11:49:44 +02:00
def aktueller_energieinhalt ( self ) :
"""
2024-09-20 12:02:31 +02:00
This method returns the current remaining energy considering efficiency .
It accounts for both charging and discharging efficiency .
2024-08-30 11:49:44 +02:00
"""
2024-09-20 12:02:31 +02:00
# Calculate remaining energy considering discharge efficiency
2024-08-30 11:49:44 +02:00
nutzbare_energie = self . soc_wh * self . entlade_effizienz
return nutzbare_energie
2024-08-24 10:22:49 +02:00
# def energie_laden(self, wh, hour):
2024-09-20 12:02:31 +02:00
# if hour is not None and self.charge_array[hour] == 0:
# return 0, 0 # Charging not allowed in this hour
2024-08-24 10:22:49 +02:00
2024-09-20 12:02:31 +02:00
# # If no value for wh is given, use the maximum charging power
# wh = wh if wh is not None else self.max_ladeleistung_w
2024-08-24 10:22:49 +02:00
2024-09-20 12:02:31 +02:00
# # Calculate the actual charging amount considering charging efficiency
# effective_charging_amount = min(wh, self.max_ladeleistung_w)
2024-08-24 10:22:49 +02:00
2024-09-20 12:02:31 +02:00
# # Update the state of charge without exceeding capacity
# charged_amount_without_loss = min(self.kapazitaet_wh - self.soc_wh, effective_charging_amount)
2024-08-24 10:22:49 +02:00
2024-09-20 12:02:31 +02:00
# charged_amount = charged_amount_without_loss * self.lade_effizienz
2024-08-24 10:22:49 +02:00
2024-09-20 12:02:31 +02:00
# self.soc_wh += charged_amount
2024-08-24 10:22:49 +02:00
2024-09-20 12:02:31 +02:00
# losses_wh = charged_amount_without_loss * (1.0 - self.lade_effizienz)
2024-02-18 14:32:27 +01:00
2024-09-20 12:02:31 +02:00
# return charged_amount, losses_wh
2024-02-18 14:32:27 +01:00
if __name__ == ' __main__ ' :
2024-09-20 12:02:31 +02:00
# Example of using the class
akku = PVAkku ( 10000 ) # A battery with 10,000 Wh capacity
print ( f " Initial state of charge: { akku . ladezustand_in_prozent ( ) } % " )
2024-02-18 14:32:27 +01:00
akku . energie_laden ( 5000 )
2024-09-20 12:02:31 +02:00
print ( f " State of charge after charging: { akku . ladezustand_in_prozent ( ) } %, Current energy content: { akku . aktueller_energieinhalt ( ) } Wh " )
2024-02-18 14:32:27 +01:00
abgegebene_energie_wh = akku . energie_abgeben ( 3000 )
2024-09-20 12:02:31 +02:00
print ( f " Discharged energy: { abgegebene_energie_wh } Wh, State of charge afterwards: { akku . ladezustand_in_prozent ( ) } %, Current energy content: { akku . aktueller_energieinhalt ( ) } Wh " )
2024-02-18 14:32:27 +01:00
akku . energie_laden ( 6000 )
2024-09-20 12:02:31 +02:00
print ( f " State of charge after further charging: { akku . ladezustand_in_prozent ( ) } %, Current energy content: { akku . aktueller_energieinhalt ( ) } Wh " )