Skip to content

Commit a839585

Browse files
authored
Merge pull request #137 from Zenmo/coopBattery
Coop battery implementation
2 parents f477c3d + 323962b commit a839585

File tree

7 files changed

+130
-0
lines changed

7 files changed

+130
-0
lines changed

Zero_engine.alpx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -973,6 +973,10 @@
973973
<Id>1725879557284</Id>
974974
<Name><![CDATA[SELF_CONSUMPTION]]></Name>
975975
</Option>
976+
<Option>
977+
<Id>1742557314771</Id>
978+
<Name><![CDATA[BALANCE_COOP]]></Name>
979+
</Option>
976980
<Option>
977981
<Id>1734001947459</Id>
978982
<Name><![CDATA[OFF]]></Name>

_alp/Agents/EnergyCoop/Code/Functions.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1186,6 +1186,7 @@
11861186
f_calculateKPIs();
11871187
}
11881188

1189+
f_connectCoopBattery();
11891190
/*ALCODEEND*/}
11901191

11911192
double f_getGroupContractDeliveryCapacity_kW()
@@ -1664,3 +1665,18 @@ HashSet<GridConnection> f_getAllChildCustomerGridConnections_recursion(HashSet<G
16641665

16651666
/*ALCODEEND*/}
16661667

1668+
double f_connectCoopBattery()
1669+
{/*ALCODESTART::1742569887460*/
1670+
GCGridBattery coopBattery = findFirst(energyModel.GridBatteries, bat -> bat.p_batteryOperationMode == OL_BatteryOperationMode.BALANCE_COOP);
1671+
1672+
if(coopBattery != null){
1673+
//Reset previous state
1674+
coopBattery.v_previousPowerElectricity_kW = 0;
1675+
1676+
//Connect to coop
1677+
coopBattery.c_parentCoops.add(this);
1678+
c_memberGridConnections.add(coopBattery);
1679+
v_liveAssetsMetaData.hasBattery = true;
1680+
}
1681+
/*ALCODEEND*/}
1682+

_alp/Agents/EnergyCoop/Code/Functions.xml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -565,4 +565,20 @@
565565
<ShowLabel>true</ShowLabel>
566566
<Body xmlns:al="http://anylogic.com"/>
567567
</Function>
568+
<Function AccessType="default" StaticFunction="false">
569+
<ReturnModificator>VOID</ReturnModificator>
570+
<ReturnType>double</ReturnType>
571+
<Id>1742569887460</Id>
572+
<Name><![CDATA[f_connectCoopBattery]]></Name>
573+
<X>890</X>
574+
<Y>160</Y>
575+
<Label>
576+
<X>10</X>
577+
<Y>0</Y>
578+
</Label>
579+
<PublicFlag>false</PublicFlag>
580+
<PresentationFlag>true</PresentationFlag>
581+
<ShowLabel>true</ShowLabel>
582+
<Body xmlns:al="http://anylogic.com"/>
583+
</Function>
568584
</Functions>

_alp/Agents/EnergyModel/Code/Functions.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1773,6 +1773,9 @@ EnergyCoop f_removeEnergyCoop(EnergyCoop energyCoop)
17731773
// Removing this coop from the list of coops in the GC
17741774
for (GridConnection GC : energyCoop.f_getAllChildMemberGridConnections()) {
17751775
GC.c_parentCoops.remove(energyCoop);
1776+
if(GC instanceof GCGridBattery && GC.p_batteryOperationMode == OL_BatteryOperationMode.BALANCE_COOP){
1777+
GC.f_setActive(false);
1778+
}
17761779
}
17771780

17781781
// Remove energyCoop from pop_energyCoops.

_alp/Agents/GCGridBattery/Code/Functions.java

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,11 @@ else if(EA.j_ea instanceof J_EAStorageElectric && ((J_EAStorageElectric)EA.j_ea)
6868
f_batteryManagementPrice(v_batterySOC_fr);
6969
} else if (p_batteryOperationMode == OL_BatteryOperationMode.NODAL_PRICING){
7070
f_batteryManagementPriceGrid(v_batterySOC_fr);
71+
} else if (p_batteryOperationMode == OL_BatteryOperationMode.BALANCE_COOP){
72+
f_batteryManagementBalanceCOOP(v_batterySOC_fr);
7173
}
7274

75+
7376
p_batteryAsset.f_updateAllFlows(p_batteryAsset.v_powerFraction_fr);
7477
//J_FlowsMap flowsMap = flowsPair.getFirst();
7578
//v_batteryPowerElectric_kW = flowsMap.get(OL_EnergyCarriers.ELECTRICITY);
@@ -342,3 +345,55 @@ else if (WTP_discharge_eurpkWh < currentElectricityPriceCharge_eurpkWh) {
342345

343346
/*ALCODEEND*/}
344347

348+
double f_batteryManagementBalanceCOOP(double batterySOC)
349+
{/*ALCODESTART::1742557292690*/
350+
351+
if(c_parentCoops.isEmpty()){
352+
return;
353+
}
354+
355+
EnergyCoop parentCoop = c_parentCoops.get(0);
356+
357+
if (p_batteryAsset.getStorageCapacity_kWh() != 0){
358+
double CoopConnectionCapacityDelivery_kW = parentCoop.v_liveConnectionMetaData.contractedDeliveryCapacity_kW * 0.9; //10% reduction, to accord for time step delay
359+
double CoopConnectionCapacityFeedin_kW = parentCoop.v_liveConnectionMetaData.contractedDeliveryCapacity_kW * 0.9; //10% reduction, to accord for time step delay
360+
double v_previousPowerBattery_kW = v_previousPowerElectricity_kW;// Assumes battery is only asset on gridconnection!! p_batteryAsset.electricityConsumption_kW-p_batteryAsset.electricityProduction_kW;
361+
double currentCoopElectricityBalance_kW = parentCoop.v_liveData.data_liveElectricityBalance_kW.getY(parentCoop.v_liveData.data_liveElectricityBalance_kW.size() - 1) - v_previousPowerBattery_kW;
362+
363+
double availableChargePower_kW = CoopConnectionCapacityDelivery_kW - currentCoopElectricityBalance_kW; // Max battery charging power within grid capacity
364+
double availableDischargePower_kW = CoopConnectionCapacityFeedin_kW + currentCoopElectricityBalance_kW; // Max discharging power within grid capacity
365+
//Tuning parameters
366+
double FeedbackGain_kWpSOC = 3 * p_batteryAsset.getCapacityElectric_kW(); // How strongly to aim for SOC setpoint
367+
double FeedforwardGain_kWpKw = 0.1; // Feedforward based on current surpluss in Coop
368+
double chargeOffset_kW = 0; // Charging 'bias', basically increases SOC setpoint slightly during the whole day.
369+
double chargeSetpoint_kW = 0;
370+
371+
//Congestion prevention
372+
if (availableChargePower_kW < 0) { //Delivery side
373+
p_batteryAsset.v_powerFraction_fr = max(-1, availableChargePower_kW / p_batteryAsset.getCapacityElectric_kW());
374+
return;
375+
}
376+
if (availableDischargePower_kW < 0) { //Feedin side
377+
p_batteryAsset.v_powerFraction_fr = min(1, -availableDischargePower_kW / p_batteryAsset.getCapacityElectric_kW());
378+
return;
379+
}
380+
381+
if (energyModel.v_currentSolarPowerNormalized_r > 0.1) {
382+
if (currentCoopElectricityBalance_kW < 0) {
383+
p_batteryAsset.v_powerFraction_fr = max(-1, min(1, -currentCoopElectricityBalance_kW / p_batteryAsset.getCapacityElectric_kW()));
384+
}
385+
}
386+
else {
387+
double expectedWind_kWh = parentCoop.v_liveAssetsMetaData.totalInstalledWindPower_kW * energyModel.v_WindYieldForecast_fr * energyModel.p_forecastTime_h;
388+
double expectedSolar_kWh = parentCoop.v_liveAssetsMetaData.totalInstalledPVPower_kW * energyModel.v_SolarYieldForecast_fr * energyModel.p_forecastTime_h;
389+
double incomingPower_fr = (expectedSolar_kWh + expectedWind_kWh) / p_batteryAsset.getStorageCapacity_kWh();
390+
double SOC_setp_fr = 1 - incomingPower_fr;
391+
392+
chargeSetpoint_kW = FeedbackGain_kWpSOC*(SOC_setp_fr - p_batteryAsset.getCurrentStateOfCharge());
393+
chargeSetpoint_kW = min(max(chargeSetpoint_kW, availableDischargePower_kW),availableChargePower_kW); // Don't allow too much (dis)charging!
394+
p_batteryAsset.v_powerFraction_fr = max(-1,min(1, chargeSetpoint_kW / p_batteryAsset.getCapacityElectric_kW()));
395+
}
396+
}
397+
398+
/*ALCODEEND*/}
399+

_alp/Agents/GCGridBattery/Code/Functions.xml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,4 +164,28 @@
164164
</Parameter>
165165
<Body xmlns:al="http://anylogic.com"/>
166166
</Function>
167+
<Function AccessType="public" StaticFunction="false">
168+
<ReturnModificator>VOID</ReturnModificator>
169+
<ReturnType>double</ReturnType>
170+
<Id>1742557292690</Id>
171+
<Name><![CDATA[f_batteryManagementBalanceCOOP]]></Name>
172+
<Description><![CDATA[Regeling voor balancering van Coop-load.
173+
174+
@author: Gillis Hommen
175+
@since: 28-12-2022]]></Description>
176+
<X>1160</X>
177+
<Y>750</Y>
178+
<Label>
179+
<X>10</X>
180+
<Y>0</Y>
181+
</Label>
182+
<PublicFlag>false</PublicFlag>
183+
<PresentationFlag>true</PresentationFlag>
184+
<ShowLabel>true</ShowLabel>
185+
<Parameter>
186+
<Name><![CDATA[batterySOC]]></Name>
187+
<Type><![CDATA[double]]></Type>
188+
</Parameter>
189+
<Body xmlns:al="http://anylogic.com"/>
190+
</Function>
167191
</Functions>

_alp/Agents/GridConnection/Code/Functions.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2471,6 +2471,12 @@ else if (flowsMap.get(EC) > 0){
24712471
energyModel.v_liveAssetsMetaData.totalInstalledWindPower_kW -= v_liveAssetsMetaData.totalInstalledWindPower_kW;
24722472
energyModel.v_liveAssetsMetaData.totalInstalledBatteryStorageCapacity_MWh -= v_liveAssetsMetaData.totalInstalledBatteryStorageCapacity_MWh;
24732473

2474+
for(EnergyCoop coop : c_parentCoops){
2475+
coop.v_liveAssetsMetaData.totalInstalledPVPower_kW -= v_liveAssetsMetaData.totalInstalledPVPower_kW;
2476+
coop.v_liveAssetsMetaData.totalInstalledWindPower_kW -= v_liveAssetsMetaData.totalInstalledWindPower_kW;
2477+
coop.v_liveAssetsMetaData.totalInstalledBatteryStorageCapacity_MWh -= v_liveAssetsMetaData.totalInstalledBatteryStorageCapacity_MWh;
2478+
}
2479+
24742480
// Reset Connection Capacity to default
24752481
f_nfatoSetConnectionCapacity(true);
24762482

@@ -2523,6 +2529,12 @@ else if (flowsMap.get(EC) > 0){
25232529
energyModel.v_liveAssetsMetaData.totalInstalledPVPower_kW += v_liveAssetsMetaData.totalInstalledPVPower_kW;
25242530
energyModel.v_liveAssetsMetaData.totalInstalledWindPower_kW += v_liveAssetsMetaData.totalInstalledWindPower_kW;
25252531
energyModel.v_liveAssetsMetaData.totalInstalledBatteryStorageCapacity_MWh += v_liveAssetsMetaData.totalInstalledBatteryStorageCapacity_MWh;
2532+
2533+
for(EnergyCoop coop : c_parentCoops){
2534+
coop.v_liveAssetsMetaData.totalInstalledPVPower_kW += v_liveAssetsMetaData.totalInstalledPVPower_kW;
2535+
coop.v_liveAssetsMetaData.totalInstalledWindPower_kW += v_liveAssetsMetaData.totalInstalledWindPower_kW;
2536+
coop.v_liveAssetsMetaData.totalInstalledBatteryStorageCapacity_MWh += v_liveAssetsMetaData.totalInstalledBatteryStorageCapacity_MWh;
2537+
}
25262538
}
25272539

25282540
//Update the 'isActive' variable

0 commit comments

Comments
 (0)