2024-10-16 15:40:04 +02:00
|
|
|
import numpy as np
|
|
|
|
|
import pytest
|
|
|
|
|
|
2026-03-11 17:18:45 +01:00
|
|
|
from akkudoktoreos.config.configabc import TimeWindow, TimeWindowSequence
|
2025-10-28 02:50:31 +01:00
|
|
|
from akkudoktoreos.devices.genetic.battery import Battery
|
|
|
|
|
from akkudoktoreos.devices.genetic.homeappliance import HomeAppliance
|
|
|
|
|
from akkudoktoreos.devices.genetic.inverter import Inverter
|
|
|
|
|
from akkudoktoreos.optimization.genetic.genetic import GeneticSimulation
|
|
|
|
|
from akkudoktoreos.optimization.genetic.geneticdevices import (
|
2024-12-19 14:50:19 +01:00
|
|
|
ElectricVehicleParameters,
|
2025-10-28 02:50:31 +01:00
|
|
|
HomeApplianceParameters,
|
|
|
|
|
InverterParameters,
|
2024-12-19 14:50:19 +01:00
|
|
|
SolarPanelBatteryParameters,
|
|
|
|
|
)
|
2025-10-28 02:50:31 +01:00
|
|
|
from akkudoktoreos.optimization.genetic.geneticparams import (
|
|
|
|
|
GeneticEnergyManagementParameters,
|
|
|
|
|
GeneticOptimizationParameters,
|
|
|
|
|
)
|
|
|
|
|
from akkudoktoreos.optimization.genetic.geneticsolution import GeneticSimulationResult
|
2026-03-11 17:18:45 +01:00
|
|
|
from akkudoktoreos.utils.datetimeutil import to_duration, to_time
|
2024-10-16 15:40:04 +02:00
|
|
|
|
|
|
|
|
start_hour = 0
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Example initialization of necessary components
|
|
|
|
|
@pytest.fixture
|
2025-10-28 02:50:31 +01:00
|
|
|
def genetic_simulation_2(config_eos) -> GeneticSimulation:
|
2025-02-12 21:35:51 +01:00
|
|
|
"""Fixture to create an EnergyManagement instance with given test parameters."""
|
2024-12-15 14:40:03 +01:00
|
|
|
# Assure configuration holds the correct values
|
2025-01-12 05:19:37 +01:00
|
|
|
config_eos.merge_settings_from_dict(
|
2025-01-18 14:26:34 +01:00
|
|
|
{"prediction": {"hours": 48}, "optimization": {"hours": 24}}
|
2025-01-12 05:19:37 +01:00
|
|
|
)
|
2025-01-18 14:26:34 +01:00
|
|
|
assert config_eos.prediction.hours == 48
|
2026-07-29 12:56:08 +02:00
|
|
|
assert config_eos.optimization.genetic.horizon_hours == 24
|
2024-12-15 14:40:03 +01:00
|
|
|
|
2024-10-16 15:40:04 +02:00
|
|
|
# Initialize the battery and the inverter
|
2024-12-19 14:50:19 +01:00
|
|
|
akku = Battery(
|
|
|
|
|
SolarPanelBatteryParameters(
|
2025-10-28 02:50:31 +01:00
|
|
|
device_id="battery1",
|
|
|
|
|
capacity_wh=5000,
|
|
|
|
|
initial_soc_percentage=80,
|
|
|
|
|
min_soc_percentage=10,
|
|
|
|
|
),
|
|
|
|
|
prediction_hours = config_eos.prediction.hours,
|
2024-11-15 22:27:25 +01:00
|
|
|
)
|
2024-10-16 15:40:04 +02:00
|
|
|
akku.reset()
|
2025-01-12 05:19:37 +01:00
|
|
|
|
|
|
|
|
inverter = Inverter(
|
2025-10-28 02:50:31 +01:00
|
|
|
InverterParameters(device_id="inverter1", max_power_wh=10000, battery_id=akku.parameters.device_id),
|
|
|
|
|
battery = akku,
|
2025-01-12 05:19:37 +01:00
|
|
|
)
|
2024-10-16 15:40:04 +02:00
|
|
|
|
|
|
|
|
# Household device (currently not used, set to None)
|
2024-11-26 00:53:16 +01:00
|
|
|
home_appliance = HomeAppliance(
|
|
|
|
|
HomeApplianceParameters(
|
2025-01-12 05:19:37 +01:00
|
|
|
device_id="dishwasher1",
|
2024-11-26 00:53:16 +01:00
|
|
|
consumption_wh=2000,
|
|
|
|
|
duration_h=2,
|
2025-10-28 02:50:31 +01:00
|
|
|
time_windows=None,
|
|
|
|
|
),
|
2026-07-29 12:56:08 +02:00
|
|
|
optimization_hours = config_eos.optimization.genetic.horizon_hours,
|
2025-10-28 02:50:31 +01:00
|
|
|
prediction_hours = config_eos.prediction.hours,
|
2024-10-16 15:40:04 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
# Example initialization of electric car battery
|
2024-12-19 14:50:19 +01:00
|
|
|
eauto = Battery(
|
|
|
|
|
ElectricVehicleParameters(
|
2025-10-28 02:50:31 +01:00
|
|
|
device_id="ev1", capacity_wh=26400, initial_soc_percentage=10, min_soc_percentage=10
|
2024-12-19 14:50:19 +01:00
|
|
|
),
|
2025-10-28 02:50:31 +01:00
|
|
|
prediction_hours = config_eos.prediction.hours,
|
2024-11-15 22:27:25 +01:00
|
|
|
)
|
2024-10-16 15:40:04 +02:00
|
|
|
|
|
|
|
|
# Parameters based on previous example data
|
2025-01-18 14:26:34 +01:00
|
|
|
pv_prognose_wh = [0.0] * config_eos.prediction.hours
|
2024-10-16 15:40:04 +02:00
|
|
|
pv_prognose_wh[10] = 5000.0
|
|
|
|
|
pv_prognose_wh[11] = 5000.0
|
|
|
|
|
|
2025-01-18 14:26:34 +01:00
|
|
|
strompreis_euro_pro_wh = [0.001] * config_eos.prediction.hours
|
2024-11-26 22:28:05 +01:00
|
|
|
strompreis_euro_pro_wh[0:10] = [0.00001] * 10
|
|
|
|
|
strompreis_euro_pro_wh[11:15] = [0.00005] * 4
|
2024-10-22 10:33:50 +02:00
|
|
|
strompreis_euro_pro_wh[20] = 0.00001
|
2024-10-16 15:40:04 +02:00
|
|
|
|
|
|
|
|
einspeiseverguetung_euro_pro_wh = [0.00007] * len(strompreis_euro_pro_wh)
|
2024-12-15 14:40:03 +01:00
|
|
|
preis_euro_pro_wh_akku = 0.0001
|
2024-10-16 15:40:04 +02:00
|
|
|
|
|
|
|
|
gesamtlast = [
|
|
|
|
|
676.71,
|
|
|
|
|
876.19,
|
|
|
|
|
527.13,
|
|
|
|
|
468.88,
|
|
|
|
|
531.38,
|
|
|
|
|
517.95,
|
|
|
|
|
483.15,
|
|
|
|
|
472.28,
|
|
|
|
|
1011.68,
|
|
|
|
|
995.00,
|
|
|
|
|
1053.07,
|
|
|
|
|
1063.91,
|
|
|
|
|
1320.56,
|
|
|
|
|
1132.03,
|
|
|
|
|
1163.67,
|
|
|
|
|
1176.82,
|
|
|
|
|
1216.22,
|
|
|
|
|
1103.78,
|
|
|
|
|
1129.12,
|
|
|
|
|
1178.71,
|
|
|
|
|
1050.98,
|
|
|
|
|
988.56,
|
|
|
|
|
912.38,
|
|
|
|
|
704.61,
|
|
|
|
|
516.37,
|
|
|
|
|
868.05,
|
|
|
|
|
694.34,
|
|
|
|
|
608.79,
|
|
|
|
|
556.31,
|
|
|
|
|
488.89,
|
|
|
|
|
506.91,
|
|
|
|
|
804.89,
|
|
|
|
|
1141.98,
|
|
|
|
|
1056.97,
|
|
|
|
|
992.46,
|
|
|
|
|
1155.99,
|
|
|
|
|
827.01,
|
|
|
|
|
1257.98,
|
|
|
|
|
1232.67,
|
|
|
|
|
871.26,
|
|
|
|
|
860.88,
|
|
|
|
|
1158.03,
|
|
|
|
|
1222.72,
|
|
|
|
|
1221.04,
|
|
|
|
|
949.99,
|
|
|
|
|
987.01,
|
|
|
|
|
733.99,
|
|
|
|
|
592.97,
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
# Initialize the energy management system with the respective parameters
|
2025-10-28 02:50:31 +01:00
|
|
|
simulation = GeneticSimulation()
|
|
|
|
|
simulation.prepare(
|
|
|
|
|
GeneticEnergyManagementParameters(
|
2024-11-15 22:27:25 +01:00
|
|
|
pv_prognose_wh=pv_prognose_wh,
|
|
|
|
|
strompreis_euro_pro_wh=strompreis_euro_pro_wh,
|
|
|
|
|
einspeiseverguetung_euro_pro_wh=einspeiseverguetung_euro_pro_wh,
|
2024-12-15 14:40:03 +01:00
|
|
|
preis_euro_pro_wh_akku=preis_euro_pro_wh_akku,
|
2024-11-15 22:27:25 +01:00
|
|
|
gesamtlast=gesamtlast,
|
|
|
|
|
),
|
2026-07-29 12:56:08 +02:00
|
|
|
optimization_hours = config_eos.optimization.genetic.horizon_hours,
|
2025-10-28 02:50:31 +01:00
|
|
|
prediction_hours = config_eos.prediction.hours,
|
2024-12-16 15:33:00 +01:00
|
|
|
inverter=inverter,
|
2024-12-22 12:03:48 +01:00
|
|
|
ev=eauto,
|
2024-11-26 00:53:16 +01:00
|
|
|
home_appliance=home_appliance,
|
2024-10-16 15:40:04 +02:00
|
|
|
)
|
|
|
|
|
|
2025-01-18 14:26:34 +01:00
|
|
|
ac = np.full(config_eos.prediction.hours, 0.0)
|
2024-10-16 15:40:04 +02:00
|
|
|
ac[20] = 1
|
2025-11-08 15:42:18 +01:00
|
|
|
simulation.ac_charge_hours = ac
|
2025-01-18 14:26:34 +01:00
|
|
|
dc = np.full(config_eos.prediction.hours, 0.0)
|
2024-10-16 15:40:04 +02:00
|
|
|
dc[11] = 1
|
2025-11-08 15:42:18 +01:00
|
|
|
simulation.dc_charge_hours = dc
|
|
|
|
|
simulation.home_appliance_start_hour = 2
|
2024-10-16 15:40:04 +02:00
|
|
|
|
2025-10-28 02:50:31 +01:00
|
|
|
return simulation
|
2024-10-16 15:40:04 +02:00
|
|
|
|
|
|
|
|
|
2025-10-28 02:50:31 +01:00
|
|
|
def test_simulation(genetic_simulation_2):
|
2025-02-12 21:35:51 +01:00
|
|
|
"""Test the EnergyManagement simulation method."""
|
2025-10-28 02:50:31 +01:00
|
|
|
simulation = genetic_simulation_2
|
2024-10-16 15:40:04 +02:00
|
|
|
|
|
|
|
|
# Simulate starting from hour 0 (this value can be adjusted)
|
2025-10-28 02:50:31 +01:00
|
|
|
result = simulation.simulate(start_hour=start_hour)
|
2024-10-16 15:40:04 +02:00
|
|
|
|
|
|
|
|
# --- Pls do not remove! ---
|
|
|
|
|
# visualisiere_ergebnisse(
|
2025-10-28 02:50:31 +01:00
|
|
|
# simulation.gesamtlast,
|
|
|
|
|
# simulation.pv_prognose_wh,
|
|
|
|
|
# simulation.strompreis_euro_pro_wh,
|
2024-10-16 15:40:04 +02:00
|
|
|
# result,
|
2025-10-28 02:50:31 +01:00
|
|
|
# simulation.akku.discharge_array+simulation.akku.charge_array,
|
2024-10-16 15:40:04 +02:00
|
|
|
# None,
|
2025-10-28 02:50:31 +01:00
|
|
|
# simulation.pv_prognose_wh,
|
2024-10-16 15:40:04 +02:00
|
|
|
# start_hour,
|
|
|
|
|
# 48,
|
|
|
|
|
# np.full(48, 0.0),
|
|
|
|
|
# filename="visualization_results.pdf",
|
|
|
|
|
# extra_data=None,
|
|
|
|
|
# )
|
|
|
|
|
|
|
|
|
|
# Assertions to validate results
|
|
|
|
|
assert result is not None, "Result should not be None"
|
|
|
|
|
assert isinstance(result, dict), "Result should be a dictionary"
|
2025-10-28 02:50:31 +01:00
|
|
|
assert GeneticSimulationResult(**result) is not None
|
2024-10-16 15:40:04 +02:00
|
|
|
assert "Last_Wh_pro_Stunde" in result, "Result should contain 'Last_Wh_pro_Stunde'"
|
|
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
Check the result of the simulation based on expected values.
|
|
|
|
|
"""
|
|
|
|
|
# Example result returned from the simulation (used for assertions)
|
|
|
|
|
assert result is not None, "Result should not be None."
|
|
|
|
|
|
|
|
|
|
# Check that the result is a dictionary
|
|
|
|
|
assert isinstance(result, dict), "Result should be a dictionary."
|
|
|
|
|
|
|
|
|
|
# Verify that the expected keys are present in the result
|
|
|
|
|
expected_keys = [
|
|
|
|
|
"Last_Wh_pro_Stunde",
|
|
|
|
|
"Netzeinspeisung_Wh_pro_Stunde",
|
|
|
|
|
"Netzbezug_Wh_pro_Stunde",
|
|
|
|
|
"Kosten_Euro_pro_Stunde",
|
|
|
|
|
"akku_soc_pro_stunde",
|
|
|
|
|
"Einnahmen_Euro_pro_Stunde",
|
|
|
|
|
"Gesamtbilanz_Euro",
|
2024-11-15 22:27:25 +01:00
|
|
|
"EAuto_SoC_pro_Stunde",
|
2024-10-16 15:40:04 +02:00
|
|
|
"Gesamteinnahmen_Euro",
|
|
|
|
|
"Gesamtkosten_Euro",
|
|
|
|
|
"Verluste_Pro_Stunde",
|
|
|
|
|
"Gesamt_Verluste",
|
2024-11-26 00:53:16 +01:00
|
|
|
"Home_appliance_wh_per_hour",
|
2024-10-16 15:40:04 +02:00
|
|
|
]
|
|
|
|
|
|
|
|
|
|
for key in expected_keys:
|
|
|
|
|
assert key in result, f"The key '{key}' should be present in the result."
|
|
|
|
|
|
|
|
|
|
# Check the length of the main arrays
|
2025-02-24 10:00:09 +01:00
|
|
|
assert len(result["Last_Wh_pro_Stunde"]) == 48, (
|
|
|
|
|
"The length of 'Last_Wh_pro_Stunde' should be 48."
|
|
|
|
|
)
|
|
|
|
|
assert len(result["Netzeinspeisung_Wh_pro_Stunde"]) == 48, (
|
|
|
|
|
"The length of 'Netzeinspeisung_Wh_pro_Stunde' should be 48."
|
|
|
|
|
)
|
|
|
|
|
assert len(result["Netzbezug_Wh_pro_Stunde"]) == 48, (
|
|
|
|
|
"The length of 'Netzbezug_Wh_pro_Stunde' should be 48."
|
|
|
|
|
)
|
|
|
|
|
assert len(result["Kosten_Euro_pro_Stunde"]) == 48, (
|
|
|
|
|
"The length of 'Kosten_Euro_pro_Stunde' should be 48."
|
|
|
|
|
)
|
|
|
|
|
assert len(result["akku_soc_pro_stunde"]) == 48, (
|
|
|
|
|
"The length of 'akku_soc_pro_stunde' should be 48."
|
|
|
|
|
)
|
2024-10-16 15:40:04 +02:00
|
|
|
|
2024-10-22 10:33:50 +02:00
|
|
|
# Verfify DC and AC Charge Bins
|
2025-11-08 15:42:18 +01:00
|
|
|
assert abs(result["akku_soc_pro_stunde"][2] - 80.0) < 1e-5, (
|
|
|
|
|
"'akku_soc_pro_stunde[2]' should be 80.0."
|
2025-02-24 10:00:09 +01:00
|
|
|
)
|
2025-11-08 15:42:18 +01:00
|
|
|
assert abs(result["akku_soc_pro_stunde"][10] - 80.0) < 1e-5, (
|
|
|
|
|
"'akku_soc_pro_stunde[10]' should be 80."
|
2025-02-24 10:00:09 +01:00
|
|
|
)
|
2024-10-16 15:40:04 +02:00
|
|
|
|
2025-02-24 10:00:09 +01:00
|
|
|
assert abs(result["Netzeinspeisung_Wh_pro_Stunde"][10] - 3946.93) < 1e-3, (
|
|
|
|
|
"'Netzeinspeisung_Wh_pro_Stunde[11]' should be 3946.93."
|
|
|
|
|
)
|
2024-10-16 15:40:04 +02:00
|
|
|
|
2025-11-08 15:42:18 +01:00
|
|
|
assert abs(result["Netzeinspeisung_Wh_pro_Stunde"][11] - 2799.7263636361786) < 1e-3, (
|
|
|
|
|
"'Netzeinspeisung_Wh_pro_Stunde[11]' should be 2799.7263636361786."
|
2025-02-24 10:00:09 +01:00
|
|
|
)
|
2024-10-16 15:40:04 +02:00
|
|
|
|
2025-11-08 15:42:18 +01:00
|
|
|
assert abs(result["akku_soc_pro_stunde"][20] - 100) < 1e-5, (
|
|
|
|
|
"'akku_soc_pro_stunde[20]' should be 100."
|
2025-02-24 10:00:09 +01:00
|
|
|
)
|
2025-11-08 15:42:18 +01:00
|
|
|
assert abs(result["Last_Wh_pro_Stunde"][20] - 1050.98) < 1e-3, (
|
|
|
|
|
"'Last_Wh_pro_Stunde[20]' should be 1050.98."
|
2025-02-24 10:00:09 +01:00
|
|
|
)
|
2024-10-16 15:40:04 +02:00
|
|
|
|
|
|
|
|
print("All tests passed successfully.")
|
2025-01-26 19:12:14 +01:00
|
|
|
|
|
|
|
|
|
2025-10-28 02:50:31 +01:00
|
|
|
def test_set_parameters(genetic_simulation_2):
|
2025-02-12 21:35:51 +01:00
|
|
|
"""Test the set_parameters method of EnergyManagement."""
|
2025-10-28 02:50:31 +01:00
|
|
|
simulation = genetic_simulation_2
|
2025-01-26 19:12:14 +01:00
|
|
|
|
|
|
|
|
# Check if parameters are set correctly
|
2025-10-28 02:50:31 +01:00
|
|
|
assert simulation.load_energy_array is not None, "load_energy_array should not be None"
|
|
|
|
|
assert simulation.pv_prediction_wh is not None, "pv_prediction_wh should not be None"
|
|
|
|
|
assert simulation.elect_price_hourly is not None, "elect_price_hourly should not be None"
|
|
|
|
|
assert simulation.elect_revenue_per_hour_arr is not None, (
|
2025-02-24 10:00:09 +01:00
|
|
|
"elect_revenue_per_hour_arr should not be None"
|
|
|
|
|
)
|
2025-01-26 19:12:14 +01:00
|
|
|
|
|
|
|
|
|
2025-10-28 02:50:31 +01:00
|
|
|
def test_reset(genetic_simulation_2):
|
2025-02-12 21:35:51 +01:00
|
|
|
"""Test the reset method of EnergyManagement."""
|
2025-10-28 02:50:31 +01:00
|
|
|
simulation = genetic_simulation_2
|
|
|
|
|
simulation.reset()
|
|
|
|
|
assert simulation.ev.current_soc_percentage() == simulation.ev.parameters.initial_soc_percentage, "EV SOC should be reset to initial value"
|
|
|
|
|
assert simulation.battery.current_soc_percentage() == simulation.battery.parameters.initial_soc_percentage, (
|
2025-02-24 10:00:09 +01:00
|
|
|
"Battery SOC should be reset to initial value"
|
|
|
|
|
)
|