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