Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions Zero_engine.alpx
Original file line number Diff line number Diff line change
Expand Up @@ -977,6 +977,10 @@
<Id>1734001947459</Id>
<Name><![CDATA[OFF]]></Name>
</Option>
<Option>
<Id>1746607342910</Id>
<Name><![CDATA[BATTERY_ALGORITHM_BAS]]></Name>
</Option>
</OptionList>
<OptionList>
<Id>1668693527447</Id>
Expand Down Expand Up @@ -1514,6 +1518,10 @@
<Id>1741864496371</Id>
<Name><![CDATA[J_ConnectionMetaData]]></Name>
</JavaClass>
<JavaClass>
<Id>1746606645736</Id>
<Name><![CDATA[J_BatteryAlgorithmBas]]></Name>
</JavaClass>
</JavaClasses>
<RequiredLibraryReference>
<LibraryName>com.anylogic.libraries.modules.markup_descriptors</LibraryName>
Expand Down
14 changes: 14 additions & 0 deletions _alp/Agents/GCGridBattery/Code/Functions.java
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}


Expand Down Expand Up @@ -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*/}

20 changes: 20 additions & 0 deletions _alp/Agents/GCGridBattery/Code/Functions.xml
Original file line number Diff line number Diff line change
Expand Up @@ -188,4 +188,24 @@
</Parameter>
<Body xmlns:al="http://anylogic.com"/>
</Function>
<Function AccessType="default" StaticFunction="false">
<ReturnModificator>VOID</ReturnModificator>
<ReturnType>double</ReturnType>
<Id>1746605418870</Id>
<Name><![CDATA[f_batteryManagementBas]]></Name>
<X>1160</X>
<Y>780</Y>
<Label>
<X>10</X>
<Y>0</Y>
</Label>
<PublicFlag>false</PublicFlag>
<PresentationFlag>true</PresentationFlag>
<ShowLabel>true</ShowLabel>
<Parameter>
<Name><![CDATA[currentBatteryStateOfCharge_fr]]></Name>
<Type><![CDATA[double]]></Type>
</Parameter>
<Body xmlns:al="http://anylogic.com"/>
</Function>
</Functions>
22 changes: 22 additions & 0 deletions _alp/Agents/GCGridBattery/Variables.xml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,28 @@
</InitialValue>
</Properties>
</Variable>
<Variable Class="PlainVariable">
<Id>1746606592165</Id>
<Name><![CDATA[v_batteryAlgorithmBas]]></Name>
<X>1160</X>
<Y>800</Y>
<Label>
<X>10</X>
<Y>0</Y>
</Label>
<PublicFlag>false</PublicFlag>
<PresentationFlag>true</PresentationFlag>
<ShowLabel>true</ShowLabel>
<Properties SaveInSnapshot="true"
Constant="false"
AccessType="public"
StaticVariable="false">
<Type><![CDATA[J_BatteryAlgorithmBas]]></Type>
<InitialValue Class="CodeValue">
<Code><![CDATA[new J_BatteryAlgorithmBas(this)]]></Code>
</InitialValue>
</Properties>
</Variable>
<Variable Class="Parameter">
<Id>1732029220158</Id>
<Name><![CDATA[p_isSliderGC]]></Name>
Expand Down
81 changes: 81 additions & 0 deletions _alp/Classes/Class.J_BatteryAlgorithmBas.java
Original file line number Diff line number Diff line change
@@ -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<br>
* It needs to be changed when this class gets changed
*/
private static final long serialVersionUID = 1L;

}