diff --git a/Zero_engine.alpx b/Zero_engine.alpx
index 058d4c06..c3111ee5 100644
--- a/Zero_engine.alpx
+++ b/Zero_engine.alpx
@@ -1107,6 +1107,11 @@
1755154772688
+
+ 1756210851750
+
+ 1752677826356
+
EULER
@@ -1665,6 +1670,40 @@
1755154772688
+
+ 1756208281968
+
+ 1752677826356
+
+
+ 1756210474555
+
+
+
+ 1756210846035
+
+ 1756210851750
+
+
+ 1756211095187
+
+ 1756210851750
+
+
+ 1756212442478
+
+ 1756210851750
+
+
+ 1756213000574
+
+ 1756210851750
+
+
+ 1756213864971
+
+ 1756210851750
+
com.anylogic.libraries.modules.markup_descriptors
diff --git a/_alp/Agents/EnergyCoop/Code/Functions.java b/_alp/Agents/EnergyCoop/Code/Functions.java
index b59ed006..8fdae1f6 100644
--- a/_alp/Agents/EnergyCoop/Code/Functions.java
+++ b/_alp/Agents/EnergyCoop/Code/Functions.java
@@ -1576,8 +1576,21 @@ EnergyCoop f_addAssetFlow(OL_AssetFlowCategories AC)
/*ALCODEEND*/}
-List f_getMemberGridConnectionsCollectionPointer()
+ArrayList f_getMemberGridConnectionsCollectionPointer()
{/*ALCODESTART::1754908113703*/
return this.c_memberGridConnections; // This should NOT be a copy, it should be a pointer!!
/*ALCODEEND*/}
+double f_aggregatorBatteryManagement_EnergyCoop()
+{/*ALCODESTART::1756207893357*/
+if(p_aggregatorBatteryManagement != null){
+ p_aggregatorBatteryManagement.manageExternalSetpoints();
+}
+/*ALCODEEND*/}
+
+double f_aggregatorManagement_EnergyCoop()
+{/*ALCODESTART::1756207893363*/
+//Run battery setpoint management
+f_aggregatorBatteryManagement_EnergyCoop();
+/*ALCODEEND*/}
+
diff --git a/_alp/Agents/EnergyCoop/Code/Functions.xml b/_alp/Agents/EnergyCoop/Code/Functions.xml
index 71e7911b..7c3d4a08 100644
--- a/_alp/Agents/EnergyCoop/Code/Functions.xml
+++ b/_alp/Agents/EnergyCoop/Code/Functions.xml
@@ -691,7 +691,7 @@
RETURNS_VALUE
- List<GridConnection>
+ ArrayList<GridConnection>
1754908113703
1440
@@ -705,4 +705,36 @@
true
+
+ VOID
+ double
+ 1756207893357
+
+ 670
+ 690
+
+ false
+ true
+ true
+
+
+
+ VOID
+ double
+ 1756207893363
+
+ 650
+ 670
+
+ false
+ true
+ true
+
+
diff --git a/_alp/Agents/EnergyCoop/Variables.xml b/_alp/Agents/EnergyCoop/Variables.xml
index 73f51e1a..46803b54 100644
--- a/_alp/Agents/EnergyCoop/Variables.xml
+++ b/_alp/Agents/EnergyCoop/Variables.xml
@@ -1984,6 +1984,31 @@
+
+ 1756207893367
+
+ 690
+ 710
+
+ false
+ true
+ true
+
+
+ NONE
+ false
+
+ 1756207893365
+ TEXT_BOX
+ 0
+ 100
+ NO_DELIMETER
+
+
+
1679563561816
diff --git a/_alp/Agents/EnergyModel/Code/Functions.java b/_alp/Agents/EnergyModel/Code/Functions.java
index 65ba6772..f7d44df2 100644
--- a/_alp/Agents/EnergyModel/Code/Functions.java
+++ b/_alp/Agents/EnergyModel/Code/Functions.java
@@ -176,6 +176,8 @@
}
}
+//OLD LOCATION OF AGGREGATOR CALL, NECESSARY IF MANAGEMENT IS WITHOUT TIME STEP DELAY
+
for(GridConnection gc : c_gridConnections) { // Can't do this in parallel due to different threads writing to the same values!
fm_currentBalanceFlows_kW.addFlows(gc.fm_currentBalanceFlows_kW);
@@ -202,6 +204,9 @@
v_currentEnergyExport_kW += max( 0, -netFlow_kW );
}
+//Call aggregator functions (ONLY WORK WITH TIME STEP DELAY FOR NOW) (LOCATION OF THIS CALL IS NOT DETERMINED YET, FOR NOW HERE)
+f_runAggregators();
+
/*ALCODEEND*/}
double f_initializeForecasts()
@@ -1139,3 +1144,13 @@ List f_getPausedGridConnectionsCollectionPointer()
return this.c_pausedGridConnections;
/*ALCODEEND*/}
+double f_runAggregators()
+{/*ALCODESTART::1756207695591*/
+//Function used to perform central management functions (like setpoint battery steering)
+
+//Run energy coop aggrator
+for (EnergyCoop EC : pop_energyCoops) {
+ EC.f_aggregatorManagement_EnergyCoop();
+}
+/*ALCODEEND*/}
+
diff --git a/_alp/Agents/EnergyModel/Code/Functions.xml b/_alp/Agents/EnergyModel/Code/Functions.xml
index b8d77990..fa4c56a3 100644
--- a/_alp/Agents/EnergyModel/Code/Functions.xml
+++ b/_alp/Agents/EnergyModel/Code/Functions.xml
@@ -6,7 +6,7 @@
1664894248130
1090
- 290
+ 310
-
- 1667746610980
-
-
- true
- -190
- 400
-
- 10
- 0
-
- false
- false
- true
-
-
-
-
-
-
-
1674329641809
@@ -171,7 +147,7 @@
1720442507543
270
- 260
+ 240
10
0
@@ -194,7 +170,7 @@
270
- 160
+ 170
10
0
@@ -217,7 +193,7 @@
270
- 140
+ 150
10
0
@@ -239,7 +215,7 @@
1720520594279
270
- 280
+ 260
10
0
@@ -284,7 +260,7 @@
1721821764640
270
- 300
+ 280
10
0
@@ -304,7 +280,7 @@
270
- 200
+ 210
10
0
@@ -327,7 +303,7 @@
270
- 180
+ 190
10
0
@@ -443,7 +419,7 @@
1731576190939
- 320
+ 380
660
10
@@ -462,7 +438,7 @@
1733478609497
- 330
+ 390
700
10
@@ -481,7 +457,7 @@
1733478609500
- 330
+ 390
680
10
@@ -519,7 +495,7 @@
1741182119260
- 320
+ 390
840
10
@@ -538,7 +514,7 @@
1741182119264
- 320
+ 390
900
10
@@ -557,7 +533,7 @@
1741277722819
- 320
+ 390
860
10
@@ -579,7 +555,7 @@
1741871129695
- 330
+ 400
920
10
@@ -598,7 +574,7 @@
1741942930553
- 330
+ 400
940
10
@@ -794,7 +770,7 @@
1668695364192
620
- 480
+ 500
10
0
@@ -847,7 +823,7 @@
1676449763319
620
- 460
+ 480
10
0
@@ -872,7 +848,7 @@
1684919785784
620
- 520
+ 540
10
0
@@ -897,7 +873,7 @@
1692878211840
620
- 270
+ 290
10
0
@@ -922,7 +898,7 @@
1692890035894
50
- 450
+ 460
10
0
@@ -947,7 +923,7 @@
1692973005119
620
- 210
+ 230
10
0
@@ -975,7 +951,7 @@
1697021029662
50
- 295
+ 315
10
0
@@ -1000,7 +976,7 @@
1697021029674
50
- 315
+ 335
10
0
@@ -1025,7 +1001,7 @@
1698935198538
50
- 410
+ 420
10
0
@@ -1050,7 +1026,7 @@
1700492967648
50
- 275
+ 295
10
0
@@ -1100,7 +1076,7 @@
1714137460172
50
- 430
+ 440
10
0
@@ -1125,7 +1101,7 @@
1718887078133
50
- 389
+ 399
10
0
@@ -1204,7 +1180,7 @@
50
- 350
+ 370
10
0
@@ -1304,7 +1280,7 @@
1752752664510
640
- 500
+ 520
10
0
@@ -1329,7 +1305,7 @@
1753366605959
270
- 320
+ 310
10
0
@@ -1357,7 +1333,7 @@
1755154851784
640
- 350
+ 370
10
0
@@ -1403,7 +1379,7 @@
1659962626907
600
- 440
+ 460
10
0
@@ -1421,7 +1397,7 @@
1659962626909
600
- 190
+ 210
10
0
@@ -1439,7 +1415,7 @@
1659962626911
600
- 230
+ 250
10
0
@@ -1457,7 +1433,7 @@
1659962626913
600
- 250
+ 270
10
0
@@ -1475,7 +1451,7 @@
1667746389220
600
- 290
+ 310
10
0
@@ -1493,7 +1469,7 @@
1669115948280
620
- 370
+ 390
10
0
@@ -1511,7 +1487,7 @@
1692864624612
620
- 310
+ 330
10
0
@@ -1529,7 +1505,7 @@
1700044359363
600
- 168
+ 188
10
0
@@ -1547,7 +1523,7 @@
1704895219414
50
- 480
+ 490
10
0
@@ -1565,7 +1541,7 @@
1711012701187
620
- 390
+ 410
10
0
@@ -1582,8 +1558,8 @@
1742484728807
- 270
- 420
+ 50
+ 250
10
0
@@ -1601,7 +1577,7 @@
1750258408126
600
- 416
+ 436
10
0
@@ -1638,7 +1614,7 @@
1754581015887
620
- 330
+ 350
10
0
diff --git a/_alp/Classes/Class.I_AggregatorBatteryManagement.java b/_alp/Classes/Class.I_AggregatorBatteryManagement.java
new file mode 100644
index 00000000..081abbea
--- /dev/null
+++ b/_alp/Classes/Class.I_AggregatorBatteryManagement.java
@@ -0,0 +1,26 @@
+import com.fasterxml.jackson.annotation.JsonTypeInfo;
+import com.fasterxml.jackson.annotation.JsonSubTypes;
+import com.fasterxml.jackson.annotation.JsonIdentityInfo;
+import com.fasterxml.jackson.annotation.ObjectIdGenerators;
+@JsonIdentityInfo(generator = ObjectIdGenerators.UUIDGenerator.class, property = "@id")
+
+@JsonTypeInfo(
+ use = JsonTypeInfo.Id.NAME,
+ include = JsonTypeInfo.As.PROPERTY,
+ property = "type" // 👈 this will be the field name in your JSON 👈
+ )
+@JsonSubTypes({
+ @JsonSubTypes.Type(value = J_AggregatorBatteryManagementOff.class, name = "J_AggregatorBatteryManagementOff"),
+ @JsonSubTypes.Type(value = J_AggregatorBatteryManagementCollectiveSelfConsumption_batterySize.class, name = "J_AggregatorBatteryManagementCollectiveSelfConsumption_batterySize"),
+ @JsonSubTypes.Type(value = J_AggregatorBatteryManagementCollectiveSelfConsumption_exportRate.class, name = "J_AggregatorBatteryManagementCollectiveSelfConsumption_exportRate"),
+ @JsonSubTypes.Type(value = J_AggregatorBatteryManagementCollectiveSelfConsumption_exportRateGH.class, name = "J_AggregatorBatteryManagementCollectiveSelfConsumption_exportRateGH"),
+})
+
+/**
+ * I_AggregatorBatteryManagement
+ */
+
+public interface I_AggregatorBatteryManagement
+{
+ void manageExternalSetpoints();
+}
\ No newline at end of file
diff --git a/_alp/Classes/Class.I_BatteryManagement.java b/_alp/Classes/Class.I_BatteryManagement.java
index 7dd7eb08..5550c05f 100644
--- a/_alp/Classes/Class.I_BatteryManagement.java
+++ b/_alp/Classes/Class.I_BatteryManagement.java
@@ -16,6 +16,7 @@
@JsonSubTypes.Type(value = J_BatteryManagementPrice.class, name = "J_BatteryManagementPrice"),
@JsonSubTypes.Type(value = J_BatteryManagementSelfConsumption.class, name = "J_BatteryManagementSelfConsumption"),
@JsonSubTypes.Type(value = J_BatteryManagementSelfConsumptionGridNode.class, name = "J_BatteryManagementSelfConsumptionGridNode"),
+ @JsonSubTypes.Type(value = J_BatteryManagementExternalSetpoint.class, name = "J_BatteryManagementExternalSetpoint"),
})
// Add other known subtypes here if needed
diff --git a/_alp/Classes/Class.I_InterfaceAggragotrBatteryManagement.java b/_alp/Classes/Class.I_InterfaceAggragotrBatteryManagement.java
new file mode 100644
index 00000000..5b105154
--- /dev/null
+++ b/_alp/Classes/Class.I_InterfaceAggragotrBatteryManagement.java
@@ -0,0 +1,8 @@
+/**
+ * I_InterfaceAggragotrBatteryManagement
+ */
+
+public interface I_InterfaceAggragotrBatteryManagement
+{
+ void updateExternalSetpoints();
+}
\ No newline at end of file
diff --git a/_alp/Classes/Class.J_AggregatorBatteryManagementCollectiveSelfConsumption_batterySize.java b/_alp/Classes/Class.J_AggregatorBatteryManagementCollectiveSelfConsumption_batterySize.java
new file mode 100644
index 00000000..cc83935c
--- /dev/null
+++ b/_alp/Classes/Class.J_AggregatorBatteryManagementCollectiveSelfConsumption_batterySize.java
@@ -0,0 +1,68 @@
+/**
+ * J_AggregatorBatteryManagementCollectiveSelfConsumption_batterySize
+ */
+
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility;
+
+@JsonAutoDetect(
+ fieldVisibility = Visibility.ANY, //
+ getterVisibility = Visibility.NONE,
+ isGetterVisibility = Visibility.NONE,
+ setterVisibility = Visibility.NONE,
+ creatorVisibility = Visibility.NONE
+)
+
+public class J_AggregatorBatteryManagementCollectiveSelfConsumption_batterySize implements I_AggregatorBatteryManagement {
+
+ EnergyCoop energyCoop;
+
+ /**
+ * Default constructor
+ */
+ public J_AggregatorBatteryManagementCollectiveSelfConsumption_batterySize( ) {
+
+ }
+
+ public J_AggregatorBatteryManagementCollectiveSelfConsumption_batterySize( EnergyCoop energyCoop) {
+ this.energyCoop = energyCoop;
+ }
+
+ public void manageExternalSetpoints() {
+ //Get all members that have a battery that is put on the external setpoint mode
+ List memberedGCWithSetpointBatteries = findAll(energyCoop.f_getMemberGridConnectionsCollectionPointer(), GC -> GC.p_batteryAsset != null && GC.p_batteryAlgorithm != null && GC.p_batteryAlgorithm instanceof J_BatteryManagementExternalSetpoint);
+
+ double collectiveChargeSetpoint_kW = 0;
+ double sumOfBatteryCapacities_kWh = 0;
+ for(GridConnection GC : energyCoop.f_getMemberGridConnectionsCollectionPointer()) {
+ double currentBatteryPowerElectric = 0;
+ if(memberedGCWithSetpointBatteries.contains(GC)) {
+ currentBatteryPowerElectric = GC.fm_currentAssetFlows_kW.get(OL_AssetFlowCategories.batteriesChargingPower_kW) - GC.fm_currentAssetFlows_kW.get(OL_AssetFlowCategories.batteriesDischargingPower_kW);
+
+ //Get total active usable battery capacity
+ sumOfBatteryCapacities_kWh += (GC.v_liveAssetsMetaData.totalInstalledBatteryStorageCapacity_MWh*1000);
+ }
+ collectiveChargeSetpoint_kW -= (GC.fm_currentBalanceFlows_kW.get(OL_EnergyCarriers.ELECTRICITY) - currentBatteryPowerElectric);
+ }
+
+ // Generate setpoints and 'push' to memberGridConnections for next timestep
+ for(int i = 0; i
+ * It needs to be changed when this class gets changed
+ */
+ private static final long serialVersionUID = 1L;
+
+}
\ No newline at end of file
diff --git a/_alp/Classes/Class.J_AggregatorBatteryManagementCollectiveSelfConsumption_exportRate.java b/_alp/Classes/Class.J_AggregatorBatteryManagementCollectiveSelfConsumption_exportRate.java
new file mode 100644
index 00000000..9c5d9aa0
--- /dev/null
+++ b/_alp/Classes/Class.J_AggregatorBatteryManagementCollectiveSelfConsumption_exportRate.java
@@ -0,0 +1,123 @@
+/**
+ * J_AggregatorBatteryManagementCollectiveSelfConsumption_exportRate
+ */
+
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility;
+
+@JsonAutoDetect(
+ fieldVisibility = Visibility.ANY, //
+ getterVisibility = Visibility.NONE,
+ isGetterVisibility = Visibility.NONE,
+ setterVisibility = Visibility.NONE,
+ creatorVisibility = Visibility.NONE
+)
+
+public class J_AggregatorBatteryManagementCollectiveSelfConsumption_exportRate implements I_AggregatorBatteryManagement {
+
+ EnergyCoop energyCoop;
+
+ /**
+ * Default constructor
+ */
+ public J_AggregatorBatteryManagementCollectiveSelfConsumption_exportRate() {
+
+ }
+
+ public J_AggregatorBatteryManagementCollectiveSelfConsumption_exportRate( EnergyCoop energyCoop) {
+ this.energyCoop = energyCoop;
+ }
+
+ public void manageExternalSetpoints() {
+ //Get all members that have a battery that is put on the external setpoint mode
+ List memberedGCWithSetpointBatteries = findAll(energyCoop.f_getMemberGridConnectionsCollectionPointer(), GC -> GC.p_batteryAsset != null && GC.p_batteryAlgorithm != null && GC.p_batteryAlgorithm instanceof J_BatteryManagementExternalSetpoint);
+
+ //Determine prefered charge setpoint of the battery, for maximum (collective) selfconsumption (equal to negative or positive balance)
+ double collectiveChargeSetpoint_kW = 0;
+ for(GridConnection GC : energyCoop.f_getMemberGridConnectionsCollectionPointer()) {
+ double currentBatteryPowerElectric = 0;
+ if(memberedGCWithSetpointBatteries.contains(GC)) {
+ currentBatteryPowerElectric = GC.fm_currentAssetFlows_kW.get(OL_AssetFlowCategories.batteriesChargingPower_kW) - GC.fm_currentAssetFlows_kW.get(OL_AssetFlowCategories.batteriesDischargingPower_kW);
+ }
+
+ collectiveChargeSetpoint_kW -= (GC.fm_currentBalanceFlows_kW.get(OL_EnergyCarriers.ELECTRICITY) - currentBatteryPowerElectric);
+ }
+
+ //Initialize iterable gc list
+ List memberedGCWithSetpointBatteries_withFreeCapacity = new ArrayList();
+
+ //Only add the gc that have the same direction as net coop charge flow to the gc that will use their battery
+ for(GridConnection GC : memberedGCWithSetpointBatteries){
+
+ double currentBatteryPowerElectric = GC.fm_currentAssetFlows_kW.get(OL_AssetFlowCategories.batteriesChargingPower_kW) - GC.fm_currentAssetFlows_kW.get(OL_AssetFlowCategories.batteriesDischargingPower_kW);
+
+ double gc_balanceFlow = GC.fm_currentBalanceFlows_kW.get(OL_EnergyCarriers.ELECTRICITY) - currentBatteryPowerElectric;
+ if((collectiveChargeSetpoint_kW < 0 && -gc_balanceFlow < 0) || (collectiveChargeSetpoint_kW > 0 && -gc_balanceFlow > 0)){
+ memberedGCWithSetpointBatteries_withFreeCapacity.add(GC);
+ }
+ }
+
+ //Initialize variables
+ double remainingSumOfChargeSetpoints_kW = collectiveChargeSetpoint_kW;
+ double gc_balanceFlowElectricity_kW;
+ double gc_calculatedChargeSetpoint_kW;
+ double gc_actualChargeSetpoint_kW;
+ List memberedGCWithSetpointBatteries_noCapacity = new ArrayList();
+
+ //Loop until no gc have battery capacity left or the setpoint is reached
+ while( Math.abs(remainingSumOfChargeSetpoints_kW) > 0.0001 && memberedGCWithSetpointBatteries_withFreeCapacity.size() > 0){
+ memberedGCWithSetpointBatteries_noCapacity.clear();
+ double removedSumOfChargedSetpoints_kW = 0;
+ double totalBalanceFlowRemainingGC_kW = 0;
+
+ //Calculate the new combined balance flow, to use for distributing the remaining chargeSetpoint
+ for(GridConnection GC : memberedGCWithSetpointBatteries_withFreeCapacity){
+ double currentBatteryPowerElectric = GC.fm_currentAssetFlows_kW.get(OL_AssetFlowCategories.batteriesChargingPower_kW) - GC.fm_currentAssetFlows_kW.get(OL_AssetFlowCategories.batteriesDischargingPower_kW);
+ totalBalanceFlowRemainingGC_kW += (GC.fm_currentBalanceFlows_kW.get(OL_EnergyCarriers.ELECTRICITY) - currentBatteryPowerElectric);
+ }
+ if (Math.abs(totalBalanceFlowRemainingGC_kW) < 0.0001) {
+ traceln("Warning: totalBalanceFlowRemainingGC is zero, cant distribute any further, nr GC left: " + memberedGCWithSetpointBatteries_withFreeCapacity.size());
+ break;
+ }
+
+ //Iterate over the gc that still have space left in their charge capacity or battery storage
+ for(GridConnection GC : memberedGCWithSetpointBatteries_withFreeCapacity){
+ J_BatteryManagementExternalSetpoint gridConnectionBatteryAlgorithm = (J_BatteryManagementExternalSetpoint)GC.p_batteryAlgorithm;
+ double currentBatteryPowerElectric = GC.fm_currentAssetFlows_kW.get(OL_AssetFlowCategories.batteriesChargingPower_kW) - GC.fm_currentAssetFlows_kW.get(OL_AssetFlowCategories.batteriesDischargingPower_kW);
+
+ gc_balanceFlowElectricity_kW = GC.fm_currentBalanceFlows_kW.get(OL_EnergyCarriers.ELECTRICITY) - currentBatteryPowerElectric;
+ gc_calculatedChargeSetpoint_kW = gridConnectionBatteryAlgorithm.getChargeSetpoint_kW() + remainingSumOfChargeSetpoints_kW * ( gc_balanceFlowElectricity_kW / totalBalanceFlowRemainingGC_kW);
+
+ //First remove setpoint from previous iteration again
+ removedSumOfChargedSetpoints_kW -= gridConnectionBatteryAlgorithm.getChargeSetpoint_kW();
+
+ //Set and get new setpoint
+ gc_actualChargeSetpoint_kW = gridConnectionBatteryAlgorithm.setChargeSetpoint_kW(gc_calculatedChargeSetpoint_kW);
+
+ //Add new setpoint to removed setpiont total for this iteration again (netto this is increased by the additional amount compared to last iteration)
+ removedSumOfChargedSetpoints_kW += gc_actualChargeSetpoint_kW;
+
+ //If the actual setpoint that has been returned by the gc is not equal to the required setpoint, it means the gc cant charge/dis charge any further, so remove it from the pool
+ if(gc_calculatedChargeSetpoint_kW != gc_actualChargeSetpoint_kW){
+ memberedGCWithSetpointBatteries_noCapacity.add(GC);
+ }
+ }
+ //Update the remaining pool of GC and to be distributed setpoint_kW
+ memberedGCWithSetpointBatteries_withFreeCapacity.removeAll(memberedGCWithSetpointBatteries_noCapacity);
+ remainingSumOfChargeSetpoints_kW -= removedSumOfChargedSetpoints_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;
+
+}
+
diff --git a/_alp/Classes/Class.J_AggregatorBatteryManagementCollectiveSelfConsumption_exportRateGH.java b/_alp/Classes/Class.J_AggregatorBatteryManagementCollectiveSelfConsumption_exportRateGH.java
new file mode 100644
index 00000000..30a8ea37
--- /dev/null
+++ b/_alp/Classes/Class.J_AggregatorBatteryManagementCollectiveSelfConsumption_exportRateGH.java
@@ -0,0 +1,90 @@
+/**
+ * J_AggregatorBatteryManagementCollectiveSelfConsumption_exportRateGH
+ */
+
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility;
+
+@JsonAutoDetect(
+ fieldVisibility = Visibility.ANY, //
+ getterVisibility = Visibility.NONE,
+ isGetterVisibility = Visibility.NONE,
+ setterVisibility = Visibility.NONE,
+ creatorVisibility = Visibility.NONE
+)
+
+public class J_AggregatorBatteryManagementCollectiveSelfConsumption_exportRateGH implements I_AggregatorBatteryManagement {
+
+ EnergyCoop energyCoop;
+
+ /**
+ * Default constructor
+ */
+ public J_AggregatorBatteryManagementCollectiveSelfConsumption_exportRateGH() {
+
+ }
+
+ public J_AggregatorBatteryManagementCollectiveSelfConsumption_exportRateGH( EnergyCoop energyCoop) {
+ this.energyCoop = energyCoop;
+ }
+
+ public void manageExternalSetpoints() {
+ //Get all members that have a battery that is put on the external setpoint mode
+ List memberedGCWithSetpointBatteries = findAll(energyCoop.f_getMemberGridConnectionsCollectionPointer(), GC -> GC.p_batteryAsset != null && GC.p_batteryAlgorithm != null && GC.p_batteryAlgorithm instanceof J_BatteryManagementExternalSetpoint);
+
+ //Determine prefered charge setpoint of the battery, for maximum (collective) selfconsumption (equal to negative or positive balance) and the total delivery and feedin
+ double collectiveChargeSetpoint_kW = 0;
+ double totalCurrentFeedin_kW = 0;
+ double totalCurrentDelivery_kW = 0;
+ double sumOfBatteryCapacities_kWh = 0;
+ for(GridConnection GC : energyCoop.f_getMemberGridConnectionsCollectionPointer()) {
+ double currentBatteryPowerElectric = 0;
+ if(memberedGCWithSetpointBatteries.contains(GC)) {
+ currentBatteryPowerElectric = GC.fm_currentAssetFlows_kW.get(OL_AssetFlowCategories.batteriesChargingPower_kW) - GC.fm_currentAssetFlows_kW.get(OL_AssetFlowCategories.batteriesDischargingPower_kW);
+
+ //Get total active usable battery capacity
+ sumOfBatteryCapacities_kWh += (GC.v_liveAssetsMetaData.totalInstalledBatteryStorageCapacity_MWh*1000);
+ }
+ collectiveChargeSetpoint_kW -= GC.fm_currentBalanceFlows_kW.get(OL_EnergyCarriers.ELECTRICITY) - currentBatteryPowerElectric;
+ totalCurrentFeedin_kW+=max(0,-(GC.fm_currentBalanceFlows_kW.get(OL_EnergyCarriers.ELECTRICITY) - currentBatteryPowerElectric));
+ totalCurrentDelivery_kW+=max(0,(GC.fm_currentBalanceFlows_kW.get(OL_EnergyCarriers.ELECTRICITY) - currentBatteryPowerElectric));
+ }
+
+ // For all qualifying GCs, make balanceflow zero if possible. Also, distinguish between collective feedin and collective delivery
+ double remainingSumOfChargeSetpoints_kW = collectiveChargeSetpoint_kW;
+
+ // Divide setpoint proportional to feedin power per GC
+ for (GridConnection GC : memberedGCWithSetpointBatteries) {
+ double GC_Setpoint_kW=0;
+ if (collectiveChargeSetpoint_kW > 0) {
+ GC_Setpoint_kW = collectiveChargeSetpoint_kW * max(0,-GC.fm_currentBalanceFlows_kW.get(OL_EnergyCarriers.ELECTRICITY))/totalCurrentFeedin_kW; // Divide summed charge-power proportional to feedin power on each GC.
+ } else if (collectiveChargeSetpoint_kW < 0){
+ GC_Setpoint_kW = collectiveChargeSetpoint_kW * max(0,GC.fm_currentBalanceFlows_kW.get(OL_EnergyCarriers.ELECTRICITY))/totalCurrentDelivery_kW; // Divide summed charge-power proportional to delivery power on each GC.
+ }
+ remainingSumOfChargeSetpoints_kW -= ((J_BatteryManagementExternalSetpoint)GC.p_batteryAlgorithm).setChargeSetpoint_kW(GC_Setpoint_kW);
+ }
+
+ // If some of the batteries are full, try distribute remaining charge setpoint over all batteries, proportional to batterysize
+ if (Math.abs(remainingSumOfChargeSetpoints_kW) > 0.01) {
+ //traceln("Dividing positive charge power proportional to battery size");
+ double chargeSetpointToBeDevided_kW = remainingSumOfChargeSetpoints_kW;
+ for (GridConnection GC : memberedGCWithSetpointBatteries) {
+ double GC_addedSetpoint_kW = chargeSetpointToBeDevided_kW * ( GC.p_batteryAsset.getStorageCapacity_kWh() / sumOfBatteryCapacities_kWh); // Divide summed charge-power proportional to battery size on each GC.
+ double GC_currentSetpoint_kW = ((J_BatteryManagementExternalSetpoint)GC.p_batteryAlgorithm).getChargeSetpoint_kW();
+ remainingSumOfChargeSetpoints_kW -= (((J_BatteryManagementExternalSetpoint)GC.p_batteryAlgorithm).setChargeSetpoint_kW(GC_addedSetpoint_kW+GC_currentSetpoint_kW)-GC_currentSetpoint_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;
+
+}
diff --git a/_alp/Classes/Class.J_AggregatorBatteryManagementOff.java b/_alp/Classes/Class.J_AggregatorBatteryManagementOff.java
new file mode 100644
index 00000000..fa493b73
--- /dev/null
+++ b/_alp/Classes/Class.J_AggregatorBatteryManagementOff.java
@@ -0,0 +1,47 @@
+
+/**
+ * J_AggregatorBatteryManagementOff
+ */
+
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility;
+
+@JsonAutoDetect(
+ fieldVisibility = Visibility.ANY, //
+ getterVisibility = Visibility.NONE,
+ isGetterVisibility = Visibility.NONE,
+ setterVisibility = Visibility.NONE,
+ creatorVisibility = Visibility.NONE
+)
+
+public class J_AggregatorBatteryManagementOff implements I_AggregatorBatteryManagement {
+
+ EnergyCoop energyCoop;
+
+ /**
+ * Default constructor
+ */
+ public J_AggregatorBatteryManagementOff( ) {
+
+ }
+
+ public J_AggregatorBatteryManagementOff( EnergyCoop energyCoop) {
+ this.energyCoop = energyCoop;
+ }
+
+ public void manageExternalSetpoints() {
+ //Do nothing
+ }
+
+ @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
diff --git a/_alp/Classes/Class.J_BatteryManagementExternalSetpoint.java b/_alp/Classes/Class.J_BatteryManagementExternalSetpoint.java
new file mode 100644
index 00000000..c324f9e6
--- /dev/null
+++ b/_alp/Classes/Class.J_BatteryManagementExternalSetpoint.java
@@ -0,0 +1,63 @@
+/**
+ * J_BatteryManagementExternalSetpoint
+ */
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility;
+
+@JsonAutoDetect(
+ fieldVisibility = Visibility.ANY, //
+ getterVisibility = Visibility.NONE,
+ isGetterVisibility = Visibility.NONE,
+ setterVisibility = Visibility.NONE,
+ creatorVisibility = Visibility.NONE
+)
+
+public class J_BatteryManagementExternalSetpoint implements I_BatteryManagement {
+
+ GridConnection gc;
+ private double currentChargeSetpoint_kW = 0;
+ /**
+ * Default constructor
+ */
+ public J_BatteryManagementExternalSetpoint( ) {
+
+ }
+
+ public J_BatteryManagementExternalSetpoint( GridConnection gc) {
+ this.gc = gc;
+ }
+
+ public double setChargeSetpoint_kW(double chargeSetpoint_kW) {
+ if (gc.p_batteryAsset!=null) {
+ this.currentChargeSetpoint_kW = max(min(chargeSetpoint_kW, gc.p_batteryAsset.getMaxChargePower_kW()), -gc.p_batteryAsset.getMaxDischargePower_kW());
+ } else {
+ this.currentChargeSetpoint_kW = 0.0;
+ }
+ return this.currentChargeSetpoint_kW;
+ }
+
+ public double getChargeSetpoint_kW() {
+ return this.currentChargeSetpoint_kW;
+ }
+
+ public void manageBattery() {
+
+ //Manage the battery with the set charge setpoint
+ gc.p_batteryAsset.f_updateAllFlows(this.currentChargeSetpoint_kW / gc.p_batteryAsset.getCapacityElectric_kW());
+
+ //Reset the value again.
+ this.currentChargeSetpoint_kW = 0;
+ }
+
+ @Override
+ public String toString() {
+ return "J_BatteryManagementExternalSetpoint with currentChargeSetpoint_kW " + this.currentChargeSetpoint_kW + " kW";
+ }
+
+ /**
+ * 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
diff --git a/_alp/Classes/Class.J_EAStorageElectric.java b/_alp/Classes/Class.J_EAStorageElectric.java
index 3fd4b45f..76d0144a 100644
--- a/_alp/Classes/Class.J_EAStorageElectric.java
+++ b/_alp/Classes/Class.J_EAStorageElectric.java
@@ -118,6 +118,14 @@ public double getCapacityAvailable_kW() {
return availableCapacity_kW;
}
+ public double getMaxChargePower_kW() { // Always a positive number!
+ return min(capacityElectric_kW, (1-stateOfCharge_fr) * storageCapacity_kWh / timestep_h / etaCharge_r);
+ }
+
+ public double getMaxDischargePower_kW() { // Always a positive number!
+ return min(capacityElectric_kW, stateOfCharge_fr * storageCapacity_kWh / timestep_h * etaDischarge_r);
+ }
+
public double getCapacityElectric_kW() {
return this.capacityElectric_kW;
}