Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Analysis for austria kristina #375

Merged
merged 45 commits into from
Feb 5, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
1350ea2
aplly some changes for new dhw testing
k-rieck Nov 6, 2024
2349154
add energy intensity in utsp
k-rieck Nov 13, 2024
9520e8e
add energy intensity in utsp
k-rieck Nov 13, 2024
793b59b
Merge branch 'main' of https://github.com/FZJ-IEK3-VSA/HiSim into fix…
k-rieck Nov 13, 2024
901b337
Merge branch 'main' of https://github.com/FZJ-IEK3-VSA/HiSim into mor…
k-rieck Nov 13, 2024
70e9c83
Merge branch 'fix_energy_intensity_utsp' of https://github.com/FZJ-IE…
k-rieck Nov 13, 2024
7465307
fix energy intensity utsp
k-rieck Nov 13, 2024
f25cefd
fix energy intensity utsp
k-rieck Nov 13, 2024
a98d4d7
make oil setup with new dhw method
k-rieck Nov 13, 2024
795f0da
code qualy
k-rieck Nov 14, 2024
4d6a5d5
fix code qualy
k-rieck Nov 14, 2024
080c4b2
new dhw for pellet heating
k-rieck Nov 14, 2024
8542bbb
dhw for gas
k-rieck Nov 14, 2024
4e7f5ba
add dhw district heating
k-rieck Nov 15, 2024
40c280a
add dhw district heating
k-rieck Nov 15, 2024
7eb4e35
code qualy
k-rieck Nov 15, 2024
9c6b315
some testing
k-rieck Nov 15, 2024
5298809
new dhw testing
k-rieck Nov 18, 2024
99ac6c7
analysis for austria
k-rieck Nov 18, 2024
12d2c3f
add kpis to yearly data and adapt to new format
k-rieck Nov 18, 2024
2ecf807
code qualy
k-rieck Nov 18, 2024
c3e55c3
code qualy
k-rieck Nov 18, 2024
97916db
pytest fix
k-rieck Nov 18, 2024
ce4b500
make data collection in scenario evaluation possible for old and newe…
k-rieck Nov 25, 2024
5180e94
make data collection in scenario evaluation possible for old and newe…
k-rieck Nov 25, 2024
ee782ca
fx pytest error
k-rieck Nov 28, 2024
1674432
fx code qualy
k-rieck Nov 28, 2024
5dd6beb
changed system setups slighlty for kristinas analysis
k-rieck Nov 28, 2024
8f35ddd
fix pytest
k-rieck Dec 2, 2024
96609d1
make charge and discharge output for battery
k-rieck Dec 3, 2024
244f649
household for paper
k-rieck Dec 16, 2024
4cdd965
some fixing
k-rieck Dec 16, 2024
534b26c
some fixing
k-rieck Dec 16, 2024
f680461
fix tests
k-rieck Dec 18, 2024
007bf7c
fix wetterdienst version
k-rieck Dec 18, 2024
de82eb7
fix type anotation
k-rieck Dec 18, 2024
ab8d15d
fix wetterdienst version
k-rieck Dec 18, 2024
35fa4b5
try to find well working wetterdienst version
k-rieck Dec 18, 2024
764a959
merge new wetterdienst and main
k-rieck Dec 18, 2024
9e86dac
some testing on result data collection
k-rieck Dec 19, 2024
a5123e4
Merge branch 'main' of https://github.com/FZJ-IEK3-VSA/HiSim into ana…
k-rieck Dec 19, 2024
1c7adc8
modif building air temp analysis
k-rieck Dec 20, 2024
f7f7fd7
modif building air temp analysis
k-rieck Dec 20, 2024
d8783d0
some fixing
k-rieck Dec 20, 2024
4360a2e
slight key adaptation in dataframe
k-rieck Jan 6, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 45 additions & 32 deletions hisim/components/advanced_battery_bslib.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
ConfigBase,
OpexCostDataClass,
DisplayConfig,
CapexCostDataClass
CapexCostDataClass,
)
from hisim.loadtypes import LoadTypes, Units, InandOutputType, ComponentType
from hisim.simulationparameters import SimulationParameters
Expand Down Expand Up @@ -148,6 +148,8 @@ class Battery(Component):
AcBatteryPowerUsed = "AcBatteryPowerUsed" # W
DcBatteryPowerUsed = "DcBatteryPowerUsed" # W
StateOfCharge = "StateOfCharge" # [0..1]
ChargingPower = "ChargingPower"
DischargingPower = "DischargingPower"

def __init__(
self,
Expand Down Expand Up @@ -204,10 +206,7 @@ def __init__(
field_name=self.AcBatteryPowerUsed,
load_type=LoadTypes.ELECTRICITY,
unit=Units.WATT,
postprocessing_flag=[
InandOutputType.CHARGE_DISCHARGE,
ComponentType.BATTERY,
],
postprocessing_flag=[InandOutputType.CHARGE_DISCHARGE, ComponentType.BATTERY],
output_description=f"here a description for {self.AcBatteryPowerUsed} will follow.",
)

Expand All @@ -227,6 +226,21 @@ def __init__(
postprocessing_flag=[InandOutputType.STORAGE_CONTENT],
output_description=f"here a description for {self.StateOfCharge} will follow.",
)
self.charing_power_channel: ComponentOutput = self.add_output(
object_name=self.component_name,
field_name=self.ChargingPower,
load_type=LoadTypes.ELECTRICITY,
unit=Units.WATT,
output_description=f"here a description for {self.ChargingPower} will follow.",
)

self.discharging_power_channel: ComponentOutput = self.add_output(
object_name=self.component_name,
field_name=self.DischargingPower,
load_type=LoadTypes.ELECTRICITY,
unit=Units.WATT,
output_description=f"here a description for {self.DischargingPower} will follow.",
)

def i_save_state(self) -> None:
"""Saves the state."""
Expand Down Expand Up @@ -255,19 +269,29 @@ def i_simulate(self, timestep: int, stsv: SingleTimeStepValues, force_convergenc

# Simulate on timestep
results = self.ac_coupled_battery_object.simulate(
p_load=set_point_for_ac_battery_power_in_watt,
soc=state_of_charge,
dt=time_increment_in_seconds,
p_load=set_point_for_ac_battery_power_in_watt, soc=state_of_charge, dt=time_increment_in_seconds,
)
# The bslib simulation returns how much of loading power input was actually used for charging and discharging and the resulting state of charge
ac_battery_power_used_for_charging_or_discharging_in_watt = results[0]
dc_battery_power_used_for_charging_or_discharging_in_watt = results[1]
state_of_charge = results[2]
# get charging and discharging power
if ac_battery_power_used_for_charging_or_discharging_in_watt > 0:
charging_power_in_watt = ac_battery_power_used_for_charging_or_discharging_in_watt
discharging_power_in_watt = 0
elif ac_battery_power_used_for_charging_or_discharging_in_watt < 0:
charging_power_in_watt = 0
discharging_power_in_watt = ac_battery_power_used_for_charging_or_discharging_in_watt
else:
charging_power_in_watt = 0
discharging_power_in_watt = 0

# write values for output time series
stsv.set_output_value(self.ac_battery_power_channel, ac_battery_power_used_for_charging_or_discharging_in_watt)
stsv.set_output_value(self.dc_battery_power_channel, dc_battery_power_used_for_charging_or_discharging_in_watt)
stsv.set_output_value(self.state_of_charge_channel, state_of_charge)
stsv.set_output_value(self.charing_power_channel, charging_power_in_watt)
stsv.set_output_value(self.discharging_power_channel, discharging_power_in_watt)

# write values to state
self.state.state_of_charge = state_of_charge
Expand All @@ -277,9 +301,7 @@ def write_to_report(self) -> List[str]:
return self.battery_config.get_string_dict()

@staticmethod
def get_battery_aging_information(
config: BatteryConfig
) -> Tuple[float, float]:
def get_battery_aging_information(config: BatteryConfig) -> Tuple[float, float]:
"""Calculate battery aging.

This is used to calculate investment costs for battery per simulated period.
Expand All @@ -296,42 +318,37 @@ def get_battery_aging_information(
return virtual_number_of_full_charge_cycles, config.lifetime_in_cycles

@staticmethod
def get_cost_capex(config: BatteryConfig, simulation_parameters: SimulationParameters) -> CapexCostDataClass: # pylint: disable=unused-argument
def get_cost_capex(
config: BatteryConfig, simulation_parameters: SimulationParameters
) -> CapexCostDataClass: # pylint: disable=unused-argument
"""Returns investment cost, CO2 emissions and lifetime."""
# Todo: think about livetime in cycles not in years
(virtual_number_of_full_charge_cycles, lifetime_in_cycles) = Battery.get_battery_aging_information(config=config)
(virtual_number_of_full_charge_cycles, lifetime_in_cycles) = Battery.get_battery_aging_information(
config=config
)
if lifetime_in_cycles > 0:
capex_per_simulated_period = (config.cost / lifetime_in_cycles) * (virtual_number_of_full_charge_cycles)
device_co2_footprint_per_simulated_period = (config.co2_footprint / lifetime_in_cycles) * (
virtual_number_of_full_charge_cycles
)
else:
log.warning(
"Capex calculation not valid. Check lifetime_in_cycles in Configuration of Battery."
)
log.warning("Capex calculation not valid. Check lifetime_in_cycles in Configuration of Battery.")

capex_cost_data_class = CapexCostDataClass(
capex_investment_cost_in_euro=config.cost,
device_co2_footprint_in_kg=config.co2_footprint,
lifetime_in_years=config.lifetime,
capex_investment_cost_for_simulated_period_in_euro=capex_per_simulated_period,
device_co2_footprint_for_simulated_period_in_kg=device_co2_footprint_per_simulated_period,
kpi_tag=KpiTagEnumClass.BATTERY
kpi_tag=KpiTagEnumClass.BATTERY,
)
return capex_cost_data_class

def get_cost_opex(
self,
all_outputs: List,
postprocessing_results: pd.DataFrame,
) -> OpexCostDataClass:
def get_cost_opex(self, all_outputs: List, postprocessing_results: pd.DataFrame,) -> OpexCostDataClass:
"""Calculate OPEX costs, consisting of maintenance costs."""
battery_losses_in_kwh: float = 0.0
for index, output in enumerate(all_outputs):
if (
output.postprocessing_flag is not None
and output.component_name == self.component_name
):
if output.postprocessing_flag is not None and output.component_name == self.component_name:
if InandOutputType.CHARGE_DISCHARGE in output.postprocessing_flag:
self.battery_config.charge_in_kwh = round(
postprocessing_results.iloc[:, index].clip(lower=0).sum()
Expand All @@ -353,16 +370,12 @@ def get_cost_opex(
co2_footprint_in_kg=0,
consumption_in_kwh=battery_losses_in_kwh,
loadtype=LoadTypes.ELECTRICITY,
kpi_tag=KpiTagEnumClass.BATTERY
kpi_tag=KpiTagEnumClass.BATTERY,
)

return opex_cost_data_class

def get_component_kpi_entries(
self,
all_outputs: List,
postprocessing_results: pd.DataFrame,
) -> List[KpiEntry]:
def get_component_kpi_entries(self, all_outputs: List, postprocessing_results: pd.DataFrame,) -> List[KpiEntry]:
"""Calculates KPIs for the respective component and return all KPI entries as list."""
return []

Expand Down
14 changes: 10 additions & 4 deletions hisim/postprocessing/postprocessing_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -826,6 +826,10 @@ def prepare_results_for_scenario_evaluation(self, ppdt: PostProcessingDataTransf
simple_dict_cumulative_data["year"].append(self.year)
simple_dict_cumulative_data["value"].append(value)

# add kpis to yearly dict
if PostProcessingOptions.COMPUTE_KPIS in ppdt.post_processing_options:
simple_dict_cumulative_data = self.write_kpis_in_dict(ppdt=ppdt, simple_dict_cumulative_data=simple_dict_cumulative_data)

# create dataframe
simple_df_yearly_data = pd.DataFrame(simple_dict_cumulative_data)
self.write_filename_and_save_to_csv(
Expand All @@ -849,7 +853,6 @@ def prepare_results_for_scenario_evaluation(self, ppdt: PostProcessingDataTransf
json_generator_config = JsonConfigurationGenerator(name=f"{self.scenario}")
json_generator_config.set_simulation_parameters(my_simulation_parameters=ppdt.simulation_parameters)
if ppdt.my_module_config is not None:
print(ppdt.my_module_config)
json_generator_config.set_module_config(my_module_config=ppdt.my_module_config)
json_generator_config.set_scenario_data_information_dict(scenario_data_information_dict=data_information_dict)
for component in ppdt.wrapped_components:
Expand Down Expand Up @@ -878,14 +881,16 @@ def write_kpis_in_dict(
self,
ppdt: PostProcessingDataTransfer,
simple_dict_cumulative_data: Dict[str, Any],
) -> None:
) -> Dict:
"""Write kpis in dictionary."""
# get kpis from ppdt
kpi_collection_dict = ppdt.kpi_collection_dict
try:
kpi_collection_dict = ppdt.kpi_collection_dict["BUI1"]
except Exception as exc:
raise KeyError(f"Key Error BUI1. Dict is {ppdt.kpi_collection_dict}.") from exc

for kpi_entries in kpi_collection_dict.values():
for kpi_name, kpi_entry in kpi_entries.items():

variable_name = kpi_name
variable_value = kpi_entry["value"]
variable_unit = kpi_entry["unit"]
Expand All @@ -903,6 +908,7 @@ def write_kpis_in_dict(
"KPI values should be written only to yearly or cumulative data, not to timeseries data."
) from exc
simple_dict_cumulative_data["value"].append(variable_value)
return simple_dict_cumulative_data

def get_variable_name_and_unit_from_ppdt_results_column(self, column: str) -> Tuple[str, str]:
"""Get variable name and unit for pyam dictionary."""
Expand Down
Loading
Loading