From 3b7f27dcff26b07b63aebca67bf9923d38bb8578 Mon Sep 17 00:00:00 2001 From: 20182294 Date: Thu, 8 May 2025 11:29:17 +0200 Subject: [PATCH] Battery class created for GCGridBattery used for testing battery algorithms. --- Zero_engine.alpx | 8 ++ _alp/Agents/GCGridBattery/Code/Functions.java | 14 ++++ _alp/Agents/GCGridBattery/Code/Functions.xml | 20 +++++ _alp/Agents/GCGridBattery/Variables.xml | 22 +++++ _alp/Classes/Class.J_BatteryAlgorithmBas.java | 81 +++++++++++++++++++ 5 files changed, 145 insertions(+) create mode 100644 _alp/Classes/Class.J_BatteryAlgorithmBas.java diff --git a/Zero_engine.alpx b/Zero_engine.alpx index a415cad2..3b82aa6c 100644 --- a/Zero_engine.alpx +++ b/Zero_engine.alpx @@ -977,6 +977,10 @@ 1734001947459 + 1668693527447 @@ -1514,6 +1518,10 @@ 1741864496371 + + 1746606645736 + + com.anylogic.libraries.modules.markup_descriptors diff --git a/_alp/Agents/GCGridBattery/Code/Functions.java b/_alp/Agents/GCGridBattery/Code/Functions.java index fc84b0ea..0a37750f 100644 --- a/_alp/Agents/GCGridBattery/Code/Functions.java +++ b/_alp/Agents/GCGridBattery/Code/Functions.java @@ -70,6 +70,8 @@ else if(EA.j_ea instanceof J_EAStorageElectric && ((J_EAStorageElectric)EA.j_ea) f_batteryManagementPriceGrid(v_batterySOC_fr); } else if (p_batteryOperationMode == OL_BatteryOperationMode.BALANCE_COOP){ f_batteryManagementBalanceCOOP(v_batterySOC_fr); + } else if (p_batteryOperationMode == OL_BatteryOperationMode.BATTERY_ALGORITHM_BAS){ + f_batteryManagementBas(v_batterySOC_fr); } @@ -397,3 +399,15 @@ else if (WTP_discharge_eurpkWh < currentElectricityPriceCharge_eurpkWh) { /*ALCODEEND*/} +double f_batteryManagementBas(double currentBatteryStateOfCharge_fr) +{/*ALCODESTART::1746605418870*/ +if (p_batteryAsset.getStorageCapacity_kWh() != 0){ + + double chargeSetpoint_kW = 0; + + chargeSetpoint_kW = v_batteryAlgorithmBas.calculateChargeSetpoint_kW(currentBatteryStateOfCharge_fr); // Don't allow too much (dis)charging! + p_batteryAsset.v_powerFraction_fr = max(-1,min(1, chargeSetpoint_kW / p_batteryAsset.getCapacityElectric_kW())); + +} +/*ALCODEEND*/} + diff --git a/_alp/Agents/GCGridBattery/Code/Functions.xml b/_alp/Agents/GCGridBattery/Code/Functions.xml index 09eda1aa..eae890c4 100644 --- a/_alp/Agents/GCGridBattery/Code/Functions.xml +++ b/_alp/Agents/GCGridBattery/Code/Functions.xml @@ -188,4 +188,24 @@ + + VOID + double + 1746605418870 + + 1160 + 780 + + false + true + true + + + + + + diff --git a/_alp/Agents/GCGridBattery/Variables.xml b/_alp/Agents/GCGridBattery/Variables.xml index a045d52b..055dffa2 100644 --- a/_alp/Agents/GCGridBattery/Variables.xml +++ b/_alp/Agents/GCGridBattery/Variables.xml @@ -45,6 +45,28 @@ + + 1746606592165 + + 1160 + 800 + + false + true + true + + + + + + + 1732029220158 diff --git a/_alp/Classes/Class.J_BatteryAlgorithmBas.java b/_alp/Classes/Class.J_BatteryAlgorithmBas.java new file mode 100644 index 00000000..1875c9d0 --- /dev/null +++ b/_alp/Classes/Class.J_BatteryAlgorithmBas.java @@ -0,0 +1,81 @@ +/** + * J_BatteryAlgorithmBas + */ +public class J_BatteryAlgorithmBas implements Serializable { + + private GridConnection parentGC; + /** + * Default constructor + */ + public J_BatteryAlgorithmBas(GridConnection parentGC) { + + this.parentGC = parentGC; + + } + + + public double calculateChargeSetpoint_kW(double SOC){ + + double batteryChargeSetpoint_kW = 0; + + //double currentElectricityPriceEPEX_eurpkWh = energyModel.v_epexForecast_eurpkWh; + + GridNode node = parentGC.l_parentNodeElectric.getConnectedAgent(); + if (parentGC.p_batteryAsset.getStorageCapacity_kWh() != 0){ + double currentCoopElectricitySurplus_kW = 0; + double CoopConnectionCapacity_kW = 0; + double v_previousPowerBattery_kW = parentGC.v_previousPowerElectricity_kW;// Assumes battery is only asset on gridconnection!! p_batteryAsset.electricityConsumption_kW-p_batteryAsset.electricityProduction_kW; + GridNode GN = parentGC.l_parentNodeElectric.getConnectedAgent(); + if(parentGC.l_ownerActor.getConnectedAgent() instanceof ConnectionOwner) { + currentCoopElectricitySurplus_kW = -GN.v_currentLoad_kW + v_previousPowerBattery_kW; + CoopConnectionCapacity_kW = 0.9*GN.p_capacity_kW; // Use only 90% of capacity for robustness against delay + //} + } else { // Get gridload directly from node + currentCoopElectricitySurplus_kW = -node.v_currentLoad_kW + v_previousPowerBattery_kW; + CoopConnectionCapacity_kW = 0.95*node.p_capacity_kW; // Use only 90% of capacity for robustness against delay + } + + double availableChargePower_kW = CoopConnectionCapacity_kW + currentCoopElectricitySurplus_kW; // Max battery charging power within grid capacity + double availableDischargePower_kW = currentCoopElectricitySurplus_kW - CoopConnectionCapacity_kW; // Max discharging power within grid capacity + double FeedbackGain_kWpSOC = 3 * parentGC.p_batteryAsset.getCapacityElectric_kW(); // How strongly to aim for SOC setpoint + double FeedforwardGain_kWpKw = 0.1; // Feedforward based on current surpluss in Coop + double chargeOffset_kW = 0; // Charging 'bias', basically increases SOC setpoint slightly during the whole day. + double chargeSetpoint_kW = 0; + //traceln("Test"); + if (availableChargePower_kW < 0) { // prevent congestion + batteryChargeSetpoint_kW = availableChargePower_kW; + return batteryChargeSetpoint_kW; + } + if (parentGC.energyModel.v_currentSolarPowerNormalized_r > 0.1) { + if (GN.v_currentLoad_kW < 0) { + batteryChargeSetpoint_kW = availableChargePower_kW; + return batteryChargeSetpoint_kW; + } + } + else { + double expectedWind_kWh = node.v_totalInstalledWindPower_kW * parentGC.energyModel.v_WindYieldForecast_fr * parentGC.energyModel.p_forecastTime_h; + double expectedSolar_kWh = node.v_totalInstalledPVPower_kW * parentGC.energyModel.v_SolarYieldForecast_fr * parentGC.energyModel.p_forecastTime_h; + double incomingPower_fr = (expectedSolar_kWh + expectedWind_kWh) / parentGC.p_batteryAsset.getStorageCapacity_kWh(); + double SOC_setp_fr = 1 - incomingPower_fr; + + chargeSetpoint_kW = FeedbackGain_kWpSOC*(SOC_setp_fr - parentGC.p_batteryAsset.getCurrentStateOfCharge()); + chargeSetpoint_kW = min(max(chargeSetpoint_kW, availableDischargePower_kW),availableChargePower_kW); // Don't allow too much (dis)charging! + batteryChargeSetpoint_kW = availableChargePower_kW; + return batteryChargeSetpoint_kW; + } + } + return batteryChargeSetpoint_kW; + } + + @Override + public String toString() { + return super.toString(); + } + + /** + * This number is here for model snapshot storing purpose
+ * It needs to be changed when this class gets changed + */ + private static final long serialVersionUID = 1L; + +} \ No newline at end of file