diff --git a/Zero_engine.alpx b/Zero_engine.alpx
index e6cc477e..4a5e381e 100644
--- a/Zero_engine.alpx
+++ b/Zero_engine.alpx
@@ -1781,6 +1781,16 @@
1762850578079
+
+ 1763557451043
+
+ 1762850578079
+
+
+ 1763570262548
+
+ 1752680962144
+
com.anylogic.libraries.modules.markup_descriptors
diff --git a/_alp/Classes/Class.J_EAConversion.java b/_alp/Classes/Class.J_EAConversion.java
index cfbbcde7..15fc141f 100644
--- a/_alp/Classes/Class.J_EAConversion.java
+++ b/_alp/Classes/Class.J_EAConversion.java
@@ -33,7 +33,8 @@ public J_EAConversion(Agent parentAgent, OL_EnergyAssetType energyAssetType, dou
@Override
public void f_updateAllFlows(double powerFraction_fr) {
- if ( powerFraction_fr < 0 ) {
+ powerFraction_fr = roundToDecimal(powerFraction_fr, J_GlobalParameters.floatingPointPrecision);
+ if(powerFraction_fr < 0) {
throw new RuntimeException("Impossible to operate conversion asset with negative powerfraction.");
}
else if ( powerFraction_fr == 0 ) {
diff --git a/_alp/Classes/Class.J_GlobalParameters.java b/_alp/Classes/Class.J_GlobalParameters.java
new file mode 100644
index 00000000..199e2ec5
--- /dev/null
+++ b/_alp/Classes/Class.J_GlobalParameters.java
@@ -0,0 +1,7 @@
+/**
+ * J_GlobalParameters
+ */
+public abstract class J_GlobalParameters {
+ //public final static double floatingPointErrorMargin = 1e-15;
+ public final static int floatingPointPrecision = 15;
+}
\ No newline at end of file
diff --git a/_alp/Classes/Class.J_HeatingFunctionLibrary.java b/_alp/Classes/Class.J_HeatingFunctionLibrary.java
new file mode 100644
index 00000000..a61b29be
--- /dev/null
+++ b/_alp/Classes/Class.J_HeatingFunctionLibrary.java
@@ -0,0 +1,76 @@
+/**
+ * J_HeatingFunctionLibrary
+ */
+public abstract class J_HeatingFunctionLibrary {
+
+ public static double managePTAndHotWaterHeatBuffer(J_EAStorageHeat hotWaterBuffer, List ptAssets, double hotWaterDemand_kW){
+ //Calculate the pt production
+ double ptProduction_kW = 0;
+ for (J_EA j_ea : ptAssets) {
+ ptProduction_kW -= j_ea.getLastFlows().get(OL_EnergyCarriers.HEAT);
+ }
+
+ //Calculate the remaining hot water energy need after pt production, also calculate the remaining unused pt production
+ double remainingHotWater_kW = max(0, hotWaterDemand_kW - ptProduction_kW); // Need to do this, because pt has already compensated the hot water demand in the gc flows, so just need to update this value
+ double remainingPTProduction_kW = max(0, ptProduction_kW - hotWaterDemand_kW);
+
+ if(hotWaterBuffer != null){
+ double chargeSetpoint_kW = 0;
+ if(remainingHotWater_kW > 0) {
+ chargeSetpoint_kW = -remainingHotWater_kW;
+ }
+ else if(remainingPTProduction_kW > 0) {
+ chargeSetpoint_kW = remainingPTProduction_kW;
+ }
+ hotWaterBuffer.v_powerFraction_fr = chargeSetpoint_kW / hotWaterBuffer.getCapacityHeat_kW();
+ hotWaterBuffer.f_updateAllFlows(hotWaterBuffer.v_powerFraction_fr);
+
+ double heatBufferCharge_kW = hotWaterBuffer.getLastFlows().get(OL_EnergyCarriers.HEAT);
+
+ if(remainingHotWater_kW > 0){//Only if the current pt production, wasnt enough, adjust the hotwater demand with the buffer, cause then the buffer will have tried to discharge
+ remainingHotWater_kW = max(0, remainingHotWater_kW + heatBufferCharge_kW);
+ }
+ else {//Curtail the remaining pt that is not used for hot water
+ remainingPTProduction_kW = max(0, remainingPTProduction_kW - heatBufferCharge_kW);
+ }
+ }
+
+ if (remainingPTProduction_kW > 0) {//Heat (for now always curtail over produced heat!)
+ for (J_EAProduction j_ea : ptAssets) {
+ remainingPTProduction_kW -= j_ea.curtailEnergyCarrierProduction( OL_EnergyCarriers.HEAT, remainingPTProduction_kW);
+
+ if (remainingPTProduction_kW <= 0) {
+ break;
+ }
+ }
+ }
+ return remainingHotWater_kW;
+ }
+
+ public static double manageHotWaterHeatBuffer(J_EAStorageHeat hotWaterBuffer, double hotWaterDemand_kW, double availableHeatingPower_kWth, double timeStep_h){
+ if(hotWaterDemand_kW > availableHeatingPower_kWth + hotWaterBuffer.getCurrentStateOfCharge_kWh() / timeStep_h) {
+ throw new RuntimeException("Hot water demand is higher than available power.");
+ }
+
+ //Heating asset should always try to fill the heat buffer as fast as possible.
+ double hotWaterDemandFromHeatingAsset_kW = min(availableHeatingPower_kWth, hotWaterDemand_kW + (hotWaterBuffer.getStorageCapacity_kWh() - hotWaterBuffer.getCurrentStateOfCharge_kWh()));
+ double heatIntoBuffer_kW = hotWaterDemandFromHeatingAsset_kW - hotWaterDemand_kW;
+
+
+ hotWaterBuffer.v_powerFraction_fr = heatIntoBuffer_kW / hotWaterBuffer.getCapacityHeat_kW();
+ hotWaterBuffer.f_updateAllFlows(hotWaterBuffer.v_powerFraction_fr);
+
+
+ return hotWaterDemandFromHeatingAsset_kW;
+ }
+}
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/_alp/Classes/Class.J_HeatingManagementHeatpumpOffPeak.java b/_alp/Classes/Class.J_HeatingManagementHeatpumpOffPeak.java
index 9cdb899f..516165e0 100644
--- a/_alp/Classes/Class.J_HeatingManagementHeatpumpOffPeak.java
+++ b/_alp/Classes/Class.J_HeatingManagementHeatpumpOffPeak.java
@@ -24,7 +24,11 @@ public class J_HeatingManagementHeatpumpOffPeak implements I_HeatingManagement {
private J_EABuilding building;
private J_EAConversion heatingAsset;
private J_HeatingPreferences heatingPreferences;
-
+ private J_EAStorageHeat hotWaterBuffer;
+ private List ptAssets;
+ private boolean hasPT = false;
+ private boolean hasHotWaterBuffer = false;
+
// PI control gains
private double P_gain_kWpDegC = 1*1;
private double I_gain_kWphDegC = 0.1*2;
@@ -74,13 +78,27 @@ public void manageHeating() {
calculatePreHeatParameters();
}
- //Adjust the hot water and overall heat demand with the buffer and pt
double hotWaterDemand_kW = gc.p_DHWAsset != null ? gc.p_DHWAsset.getLastFlows().get(OL_EnergyCarriers.HEAT) : 0;
- double remainingHotWaterDemand_kW = managePTAndHotWaterHeatBuffer(hotWaterDemand_kW);
+ double ptAssetPower_kW = ptAssets != null ? sum(ptAssets, pt -> pt.getLastFlows().get(OL_EnergyCarriers.HEAT)) : 0;
+ double additionalHeatDemand_kW = (gc.fm_currentBalanceFlows_kW.get(OL_EnergyCarriers.HEAT) - hotWaterDemand_kW + (-ptAssetPower_kW));
+
+ double currentHeatDemand_kW = additionalHeatDemand_kW;
+ double availableAssetPowerForHotWater_kWth = heatingAsset.getOutputCapacity_kW() - additionalHeatDemand_kW;
+
+ //Manage hot water if additional systems are present
+ if(this.hasPT) {
+ //Adjust the hot water and overall heat demand with the buffer and pt
+ double remainingHotWaterDemand_kW = J_HeatingFunctionLibrary.managePTAndHotWaterHeatBuffer(hotWaterBuffer, ptAssets, hotWaterDemand_kW); // This function updates the buffer and curtails PT if needed -> current balanceflow is updated accordingly.
+ currentHeatDemand_kW += remainingHotWaterDemand_kW;
+ }
+ else if(this.hasHotWaterBuffer) {
+ double heatDemandFromHeatingAssetForHotWater_kW = J_HeatingFunctionLibrary.manageHotWaterHeatBuffer(this.hotWaterBuffer, hotWaterDemand_kW, availableAssetPowerForHotWater_kWth, this.timeStep_h);
+ currentHeatDemand_kW += heatDemandFromHeatingAssetForHotWater_kW;
+ }
+ else {
+ currentHeatDemand_kW += hotWaterDemand_kW;
+ }
- //Get the remaining heat demand (hot water, and potential other profiles)
- double otherHeatDemand_kW = gc.fm_currentBalanceFlows_kW.get(OL_EnergyCarriers.HEAT);
-
//Determine if time is in reduced Heating interval
boolean timeIsInReducedHeatingInterval = ((timeOfDay_h - startTimeOfReducedHeatingInterval_hr + 24) % 24) < reducedHeatingIntervalLength_hr;
boolean timeIsInPreheatInterval = ((timeOfDay_h - (startTimeOfReducedHeatingInterval_hr - preHeatDuration_hr) + 24) % 24) < preHeatDuration_hr;
@@ -115,11 +133,11 @@ else if (timeOfDay_h < heatingPreferences.getStartOfDayTime_h() || timeOfDay_h >
double buildingHeatingDemand_kW = max(0,deltaT_degC * P_gain_kWpDegC + I_state_hDegC * I_gain_kWphDegC);
//Set asset power
- double assetPower_kW = min(heatingAsset.getOutputCapacity_kW(), buildingHeatingDemand_kW + otherHeatDemand_kW); // minimum not strictly needed as asset will limit power by itself. Could be used later if we notice demand is higher than capacity of heating asset.
+ double assetPower_kW = min(heatingAsset.getOutputCapacity_kW(), buildingHeatingDemand_kW + currentHeatDemand_kW); // minimum not strictly needed as asset will limit power by itself. Could be used later if we notice demand is higher than capacity of heating asset.
heatingAsset.f_updateAllFlows( assetPower_kW / heatingAsset.getOutputCapacity_kW() );
//Set building power (other heat demand gets bias if asset does not have enough capacity)
- double heatIntoBuilding_kW = max(0, assetPower_kW - otherHeatDemand_kW);
+ double heatIntoBuilding_kW = max(0, assetPower_kW - currentHeatDemand_kW);
building.f_updateAllFlows( heatIntoBuilding_kW / building.getCapacityHeat_kW() );
}
@@ -188,53 +206,6 @@ private void calculatePreHeatParameters() {
//For now, preheat duration of 2 hours is assumed.
}
}
-
- private double managePTAndHotWaterHeatBuffer(double hotWaterDemand_kW){
-
- //Calculate the pt production
- double ptProduction_kW = 0;
- List ptAssets = findAll(gc.c_productionAssets, ea -> ea.energyAssetType == OL_EnergyAssetType.PHOTOTHERMAL);
- for (J_EA j_ea : ptAssets) {
- ptProduction_kW -= j_ea.getLastFlows().get(OL_EnergyCarriers.HEAT);
- }
-
- //Calculate the remaining hot water energy need after pt production, also calculate the remaining unused pt production
- double remainingHotWater_kW = max(0, hotWaterDemand_kW - ptProduction_kW); // Need to do this, because pt has already compensated the hot water demand in the gc flows, so just need to update this value
- double remainingPTProduction_kW = max(0, ptProduction_kW - hotWaterDemand_kW);
-
- if(gc.p_heatBuffer != null){
- double chargeSetpoint_kW = 0;
- if(remainingHotWater_kW > 0) {
- chargeSetpoint_kW = -remainingHotWater_kW;
- }
- else if(remainingPTProduction_kW > 0) {
- chargeSetpoint_kW = remainingPTProduction_kW;
- }
- gc.p_heatBuffer.v_powerFraction_fr = chargeSetpoint_kW / gc.p_heatBuffer.getCapacityHeat_kW();
- gc.p_heatBuffer.f_updateAllFlows(gc.p_heatBuffer.v_powerFraction_fr);
-
- double heatBufferCharge_kW = gc.p_heatBuffer.getLastFlows().get(OL_EnergyCarriers.HEAT);
-
- if(remainingHotWater_kW > 0){//Only if the current pt production, wasnt enough, adjust the hotwater demand with the buffer, cause then the buffer will have tried to discharge
- remainingHotWater_kW = max(0, remainingHotWater_kW + heatBufferCharge_kW);
- }
- else {//Curtail the remaining pt that is not used for hot water
- remainingPTProduction_kW = max(0, remainingPTProduction_kW - heatBufferCharge_kW);
- if (remainingPTProduction_kW > 0) {//Heat (for now always curtail over produced heat!)
- for (J_EAProduction j_ea : ptAssets) {
- remainingPTProduction_kW -= j_ea.curtailEnergyCarrierProduction( OL_EnergyCarriers.HEAT, remainingPTProduction_kW);
-
- if (remainingPTProduction_kW <= 0) {
- break;
- }
- }
- }
- }
- }
- return remainingHotWater_kW;
- }
-
-
public void setStartTimeOfReducedHeatingInterval_hr(double startTimeOfReducedHeatingInterval_hr) {
@@ -268,16 +239,20 @@ public void initializeAssets() {
if (!validHeatingTypes.contains(this.currentHeatingType)) {
throw new RuntimeException(this.getClass() + " does not support heating type: " + this.currentHeatingType);
}
- J_EAProduction ptAsset = findFirst(gc.c_productionAssets, ea -> ea.energyAssetType == OL_EnergyAssetType.PHOTOTHERMAL);
- if (ptAsset != null) {
+ List ptAssets = findAll(gc.c_productionAssets, ea -> ea.energyAssetType == OL_EnergyAssetType.PHOTOTHERMAL);
+ if (ptAssets.size() > 0) {
if(gc.p_DHWAsset == null) {
throw new RuntimeException(this.getClass() + " requires a hot water demand to make sense to use this heating management with PT.");
}
+ this.ptAssets = ptAssets;
+ this.hasPT = true;
}
if (gc.p_heatBuffer != null) {
- if(gc.p_DHWAsset == null && ptAsset == null) {
- throw new RuntimeException(this.getClass() + " requires a hot water demand and PT to make sense to use this heating management with a heatbuffer.");
+ if(gc.p_DHWAsset == null) {
+ throw new RuntimeException(this.getClass() + " requires a hot water demand to make sense to use this heating management with a heatbuffer.");
}
+ this.hotWaterBuffer = gc.p_heatBuffer;
+ this.hasHotWaterBuffer = true;
}
if(gc.p_BuildingThermalAsset != null) {
this.building = gc.p_BuildingThermalAsset;
diff --git a/_alp/Classes/Class.J_HeatingManagementPIcontrol.java b/_alp/Classes/Class.J_HeatingManagementPIcontrol.java
index 109d83bf..8c6966c6 100644
--- a/_alp/Classes/Class.J_HeatingManagementPIcontrol.java
+++ b/_alp/Classes/Class.J_HeatingManagementPIcontrol.java
@@ -29,7 +29,11 @@ public class J_HeatingManagementPIcontrol implements I_HeatingManagement {
private J_EABuilding building;
private J_EAConversion heatingAsset;
private J_HeatingPreferences heatingPreferences;
-
+ private J_EAStorageHeat hotWaterBuffer;
+ private List ptAssets;
+ private boolean hasPT = false;
+ private boolean hasHotWaterBuffer = false;
+
// PI control gains
private double P_gain_kWpDegC = 1*1;
private double I_gain_kWphDegC = 0.1*2;
@@ -61,11 +65,26 @@ public void manageHeating() {
}
double hotWaterDemand_kW = gc.p_DHWAsset != null ? gc.p_DHWAsset.getLastFlows().get(OL_EnergyCarriers.HEAT) : 0;
+ double ptAssetPower_kW = ptAssets != null ? sum(ptAssets, pt -> pt.getLastFlows().get(OL_EnergyCarriers.HEAT)) : 0;
+ double additionalHeatDemand_kW = (gc.fm_currentBalanceFlows_kW.get(OL_EnergyCarriers.HEAT) - hotWaterDemand_kW + (-ptAssetPower_kW));
+
+ double currentHeatDemand_kW = additionalHeatDemand_kW;
+ double availableAssetPowerForHotWater_kWth = heatingAsset.getOutputCapacity_kW() - additionalHeatDemand_kW;
- //Adjust the hot water and overall heat demand with the buffer and pt
- double remainingHotWaterDemand_kW = managePTAndHotWaterHeatBuffer(hotWaterDemand_kW);
+ //Manage hot water if additional systems are present
+ if(this.hasPT) {
+ //Adjust the hot water and overall heat demand with the buffer and pt
+ double remainingHotWaterDemand_kW = J_HeatingFunctionLibrary.managePTAndHotWaterHeatBuffer(hotWaterBuffer, ptAssets, hotWaterDemand_kW); // This function updates the buffer and curtails PT if needed -> current balanceflow is updated accordingly.
+ currentHeatDemand_kW += remainingHotWaterDemand_kW;
+ }
+ else if(this.hasHotWaterBuffer) {
+ double heatDemandFromHeatingAssetForHotWater_kW = J_HeatingFunctionLibrary.manageHotWaterHeatBuffer(this.hotWaterBuffer, hotWaterDemand_kW, availableAssetPowerForHotWater_kWth, this.timeStep_h);
+ currentHeatDemand_kW += heatDemandFromHeatingAssetForHotWater_kW;
+ }
+ else {
+ currentHeatDemand_kW += hotWaterDemand_kW;
+ }
- double otherHeatDemand_kW = gc.fm_currentBalanceFlows_kW.get(OL_EnergyCarriers.HEAT);
double buildingTemp_degC = building.getCurrentTemperature();
double timeOfDay_h = gc.energyModel.t_hourOfDay;
@@ -86,73 +105,33 @@ public void manageHeating() {
buildingHeatingDemand_kW = max(0,deltaT_degC * P_gain_kWpDegC + I_state_hDegC * I_gain_kWphDegC);
- double assetPower_kW = min(heatingAsset.getOutputCapacity_kW(),buildingHeatingDemand_kW + otherHeatDemand_kW); // minimum not strictly needed as asset will limit power by itself. Could be used later if we notice demand is higher than capacity of heating asset.
+ double assetPower_kW = min(heatingAsset.getOutputCapacity_kW(),buildingHeatingDemand_kW + currentHeatDemand_kW); // minimum not strictly needed as asset will limit power by itself. Could be used later if we notice demand is higher than capacity of heating asset.
heatingAsset.f_updateAllFlows( assetPower_kW / heatingAsset.getOutputCapacity_kW() );
- double heatIntoBuilding_kW = max(0, assetPower_kW - otherHeatDemand_kW);
+ double heatIntoBuilding_kW = max(0, assetPower_kW - currentHeatDemand_kW);
building.f_updateAllFlows( heatIntoBuilding_kW / building.getCapacityHeat_kW() );
}
- private double managePTAndHotWaterHeatBuffer(double hotWaterDemand_kW){
-
- //Calculate the pt production
- double ptProduction_kW = 0;
- List ptAssets = findAll(gc.c_productionAssets, ea -> ea.energyAssetType == OL_EnergyAssetType.PHOTOTHERMAL);
- for (J_EA j_ea : ptAssets) {
- ptProduction_kW -= j_ea.getLastFlows().get(OL_EnergyCarriers.HEAT);
- }
-
- //Calculate the remaining hot water energy need after pt production, also calculate the remaining unused pt production
- double remainingHotWater_kW = max(0, hotWaterDemand_kW - ptProduction_kW); // Need to do this, because pt has already compensated the hot water demand in the gc flows, so just need to update this value
- double remainingPTProduction_kW = max(0, ptProduction_kW - hotWaterDemand_kW);
-
- if(gc.p_heatBuffer != null){
- double chargeSetpoint_kW = 0;
- if(remainingHotWater_kW > 0) {
- chargeSetpoint_kW = -remainingHotWater_kW;
- }
- else if(remainingPTProduction_kW > 0) {
- chargeSetpoint_kW = remainingPTProduction_kW;
- }
- gc.p_heatBuffer.v_powerFraction_fr = chargeSetpoint_kW / gc.p_heatBuffer.getCapacityHeat_kW();
- gc.p_heatBuffer.f_updateAllFlows(gc.p_heatBuffer.v_powerFraction_fr);
-
- double heatBufferCharge_kW = gc.p_heatBuffer.getLastFlows().get(OL_EnergyCarriers.HEAT);
-
- if(remainingHotWater_kW > 0){//Only if the current pt production, wasnt enough, adjust the hotwater demand with the buffer, cause then the buffer will have tried to discharge
- remainingHotWater_kW = max(0, remainingHotWater_kW + heatBufferCharge_kW);
- }
- else {//Curtail the remaining pt that is not used for hot water
- remainingPTProduction_kW = max(0, remainingPTProduction_kW - heatBufferCharge_kW);
- if (remainingPTProduction_kW > 0) {//Heat (for now always curtail over produced heat!)
- for (J_EAProduction j_ea : ptAssets) {
- remainingPTProduction_kW -= j_ea.curtailEnergyCarrierProduction( OL_EnergyCarriers.HEAT, remainingPTProduction_kW);
-
- if (remainingPTProduction_kW <= 0) {
- break;
- }
- }
- }
- }
- }
- return remainingHotWater_kW;
- }
public void initializeAssets() {
if (!validHeatingTypes.contains(this.currentHeatingType)) {
throw new RuntimeException(this.getClass() + " does not support heating type: " + this.currentHeatingType);
}
- J_EAProduction ptAsset = findFirst(gc.c_productionAssets, ea -> ea.energyAssetType == OL_EnergyAssetType.PHOTOTHERMAL);
- if (ptAsset != null) {
+ List ptAssets = findAll(gc.c_productionAssets, ea -> ea.energyAssetType == OL_EnergyAssetType.PHOTOTHERMAL);
+ if (ptAssets.size() > 0) {
if(gc.p_DHWAsset == null) {
throw new RuntimeException(this.getClass() + " requires a hot water demand to make sense to use this heating management with PT.");
}
+ this.ptAssets = ptAssets;
+ this.hasPT = true;
}
if (gc.p_heatBuffer != null) {
- if(gc.p_DHWAsset == null && ptAsset == null) {
- throw new RuntimeException(this.getClass() + " requires a hot water demand and PT to make sense to use this heating management with a heatbuffer.");
+ if(gc.p_DHWAsset == null) {
+ throw new RuntimeException(this.getClass() + " requires a hot water demand to make sense to use this heating management with heatbuffer.");
}
+ this.hotWaterBuffer = gc.p_heatBuffer;
+ this.hasHotWaterBuffer = true;
}
if(gc.p_BuildingThermalAsset != null) {
this.building = gc.p_BuildingThermalAsset;
diff --git a/_alp/Classes/Class.J_HeatingManagementPIcontrolHybridHeatpump.java b/_alp/Classes/Class.J_HeatingManagementPIcontrolHybridHeatpump.java
index 11ea6f04..01ddce00 100644
--- a/_alp/Classes/Class.J_HeatingManagementPIcontrolHybridHeatpump.java
+++ b/_alp/Classes/Class.J_HeatingManagementPIcontrolHybridHeatpump.java
@@ -24,6 +24,9 @@ public class J_HeatingManagementPIcontrolHybridHeatpump implements I_HeatingMana
private J_EAConversionHeatPump heatPumpAsset;
private J_EAConversionGasBurner gasBurnerAsset;
private J_HeatingPreferences heatingPreferences;
+ private J_EAStorageHeat hotWaterBuffer;
+ private List ptAssets;
+ private boolean hasPT = false;
// PI control gains
private double P_gain_kWpDegC = 1*1;
@@ -58,8 +61,10 @@ public void manageHeating() {
double hotWaterDemand_kW = gc.p_DHWAsset != null ? gc.p_DHWAsset.getLastFlows().get(OL_EnergyCarriers.HEAT) : 0;
- //Adjust the hot water and overall heat demand with the buffer and pt
- double remainingHotWaterDemand_kW = managePTAndHotWaterHeatBuffer(hotWaterDemand_kW); // This function updates the buffer and curtails PT if needed -> current balanceflow is updated accordingly.
+ if(hasPT) {
+ //Adjust the hot water and overall heat demand with the buffer and pt
+ double remainingHotWaterDemand_kW = J_HeatingFunctionLibrary.managePTAndHotWaterHeatBuffer(hotWaterBuffer, ptAssets, hotWaterDemand_kW); // This function updates the buffer and curtails PT if needed -> current balanceflow is updated accordingly.
+ }
double otherHeatDemand_kW = gc.fm_currentBalanceFlows_kW.get(OL_EnergyCarriers.HEAT);
@@ -106,66 +111,23 @@ public void manageHeating() {
}
- private double managePTAndHotWaterHeatBuffer(double hotWaterDemand_kW){
-
- //Calculate the pt production
- double ptProduction_kW = 0;
- List ptAssets = findAll(gc.c_productionAssets, ea -> ea.energyAssetType == OL_EnergyAssetType.PHOTOTHERMAL);
- for (J_EA j_ea : ptAssets) {
- ptProduction_kW -= j_ea.getLastFlows().get(OL_EnergyCarriers.HEAT);
- }
-
- //Calculate the remaining hot water energy need after pt production, also calculate the remaining unused pt production
- double remainingHotWater_kW = max(0, hotWaterDemand_kW - ptProduction_kW); // Need to do this, because pt has already compensated the hot water demand in the gc flows, so just need to update this value
- double remainingPTProduction_kW = max(0, ptProduction_kW - hotWaterDemand_kW);
-
- if(gc.p_heatBuffer != null){
- double chargeSetpoint_kW = 0;
- if(remainingHotWater_kW > 0) {
- chargeSetpoint_kW = -remainingHotWater_kW;
- }
- else if(remainingPTProduction_kW > 0) {
- chargeSetpoint_kW = remainingPTProduction_kW;
- }
- gc.p_heatBuffer.v_powerFraction_fr = chargeSetpoint_kW / gc.p_heatBuffer.getCapacityHeat_kW();
- gc.p_heatBuffer.f_updateAllFlows(gc.p_heatBuffer.v_powerFraction_fr);
-
- double heatBufferCharge_kW = gc.p_heatBuffer.getLastFlows().get(OL_EnergyCarriers.HEAT);
-
- if(remainingHotWater_kW > 0){//Only if the current pt production, wasnt enough, adjust the hotwater demand with the buffer, cause then the buffer will have tried to discharge
- remainingHotWater_kW = max(0, remainingHotWater_kW + heatBufferCharge_kW);
- }
- else {//Curtail the remaining pt that is not used for hot water
- remainingPTProduction_kW = max(0, remainingPTProduction_kW - heatBufferCharge_kW);
- if (remainingPTProduction_kW > 0) {//Heat (for now always curtail over produced heat!)
- for (J_EAProduction j_ea : ptAssets) {
- remainingPTProduction_kW -= j_ea.curtailEnergyCarrierProduction( OL_EnergyCarriers.HEAT, remainingPTProduction_kW);
-
- if (remainingPTProduction_kW <= 0) {
- break;
- }
- }
- }
- }
- }
- return remainingHotWater_kW;
- }
-
-
public void initializeAssets() {
if (!validHeatingTypes.contains(this.currentHeatingType)) {
throw new RuntimeException(this.getClass() + " does not support heating type: " + this.currentHeatingType);
}
- J_EAProduction ptAsset = findFirst(gc.c_productionAssets, ea -> ea.energyAssetType == OL_EnergyAssetType.PHOTOTHERMAL);
- if (ptAsset != null) {
+ List ptAssets = findAll(gc.c_productionAssets, ea -> ea.energyAssetType == OL_EnergyAssetType.PHOTOTHERMAL);
+ if (ptAssets.size() > 0) {
if(gc.p_DHWAsset == null) {
throw new RuntimeException(this.getClass() + " requires a hot water demand to make sense to use this heating management with PT.");
}
+ this.hasPT = true;
+ this.ptAssets = ptAssets;
}
if (gc.p_heatBuffer != null) {
- if(gc.p_DHWAsset == null && ptAsset == null) {
- throw new RuntimeException(this.getClass() + " requires a hot water demand and PT to make sense to use this heating management with a heatbuffer.");
+ if(gc.p_DHWAsset == null || ptAssets.size() == 0) {
+ throw new RuntimeException(this.getClass() + " requires a hot water demand and pt to make sense to use this heating management.");
}
+ this.hotWaterBuffer = gc.p_heatBuffer;
}
if(gc.p_BuildingThermalAsset != null) {
this.building = gc.p_BuildingThermalAsset;
diff --git a/_alp/Classes/Class.J_HeatingManagementSimple.java b/_alp/Classes/Class.J_HeatingManagementSimple.java
index bad5a140..16c6591e 100644
--- a/_alp/Classes/Class.J_HeatingManagementSimple.java
+++ b/_alp/Classes/Class.J_HeatingManagementSimple.java
@@ -28,6 +28,9 @@ public class J_HeatingManagementSimple implements I_HeatingManagement {
private J_EABuilding building;
private J_EAConversion heatingAsset;
private J_HeatingPreferences heatingPreferences;
+ private J_EAStorageHeat hotWaterBuffer;
+ private List ptAssets;
+ private boolean hasPT = false;
/**
* Default constructor
@@ -40,52 +43,7 @@ public J_HeatingManagementSimple( GridConnection gc, OL_GridConnectionHeatingTyp
this.gc = gc;
this.currentHeatingType = heatingType;
}
-
- public double managePTAndHotWaterHeatBuffer(double hotWaterDemand_kW){
-
- //Calculate the pt production
- double ptProduction_kW = 0;
- List ptAssets = findAll(gc.c_productionAssets, ea -> ea.energyAssetType == OL_EnergyAssetType.PHOTOTHERMAL);
- for (J_EA j_ea : ptAssets) {
- ptProduction_kW -= j_ea.getLastFlows().get(OL_EnergyCarriers.HEAT);
- }
-
- //Calculate the remaining hot water energy need after pt production, also calculate the remaining unused pt production
- double remainingHotWater_kW = max(0, hotWaterDemand_kW - ptProduction_kW); // Need to do this, because pt has already compensated the hot water demand in the gc flows, so just need to update this value
- double remainingPTProduction_kW = max(0, ptProduction_kW - hotWaterDemand_kW);
-
- if(gc.p_heatBuffer != null){
- double chargeSetpoint_kW = 0;
- if(remainingHotWater_kW > 0) {
- chargeSetpoint_kW = -remainingHotWater_kW;
- }
- else if(remainingPTProduction_kW > 0) {
- chargeSetpoint_kW = remainingPTProduction_kW;
- }
- gc.p_heatBuffer.v_powerFraction_fr = chargeSetpoint_kW / gc.p_heatBuffer.getCapacityHeat_kW();
- gc.p_heatBuffer.f_updateAllFlows(gc.p_heatBuffer.v_powerFraction_fr);
-
- double heatBufferCharge_kW = gc.p_heatBuffer.getLastFlows().get(OL_EnergyCarriers.HEAT);
-
- if(remainingHotWater_kW > 0){//Only if the current pt production, wasnt enough, adjust the hotwater demand with the buffer, cause then the buffer will have tried to discharge
- remainingHotWater_kW = max(0, remainingHotWater_kW + heatBufferCharge_kW);
- }
- else {//Curtail the remaining pt that is not used for hot water
- remainingPTProduction_kW = max(0, remainingPTProduction_kW - heatBufferCharge_kW);
- if (remainingPTProduction_kW > 0) {//Heat (for now always curtail over produced heat!)
- for (J_EAProduction j_ea : ptAssets) {
- remainingPTProduction_kW -= j_ea.curtailEnergyCarrierProduction( OL_EnergyCarriers.HEAT, remainingPTProduction_kW);
-
- if (remainingPTProduction_kW <= 0) {
- break;
- }
- }
- }
- }
- }
- return remainingHotWater_kW;
- }
-
+
public void manageHeating() {
if ( !isInitialized ) {
@@ -94,8 +52,9 @@ public void manageHeating() {
double hotWaterDemand_kW = gc.p_DHWAsset != null ? gc.p_DHWAsset.getLastFlows().get(OL_EnergyCarriers.HEAT) : 0;
- //Adjust the hot water and overall heat demand with the buffer and pt
- double remainingHotWaterDemand_kW = managePTAndHotWaterHeatBuffer(hotWaterDemand_kW); // also updates fm_currentBalanceFlows_kW(heat)!
+ if(hasPT) {//Adjust the hot water and overall heat demand with the buffer and pt
+ double remainingHotWaterDemand_kW = J_HeatingFunctionLibrary.managePTAndHotWaterHeatBuffer(hotWaterBuffer, ptAssets, hotWaterDemand_kW); // also updates fm_currentBalanceFlows_kW(heat)!
+ }
double heatDemand_kW = gc.fm_currentBalanceFlows_kW.get(OL_EnergyCarriers.HEAT);
@@ -138,16 +97,19 @@ public void initializeAssets() {
if (!validHeatingTypes.contains(this.currentHeatingType)) {
throw new RuntimeException(this.getClass() + " does not support heating type: " + this.currentHeatingType);
}
- J_EAProduction ptAsset = findFirst(gc.c_productionAssets, ea -> ea.energyAssetType == OL_EnergyAssetType.PHOTOTHERMAL);
- if (ptAsset != null) {
+ List ptAssets = findAll(gc.c_productionAssets, ea -> ea.energyAssetType == OL_EnergyAssetType.PHOTOTHERMAL);
+ if (ptAssets.size() > 0) {
if(gc.p_DHWAsset == null) {
throw new RuntimeException(this.getClass() + " requires a hot water demand to make sense to use this heating management with PT.");
}
+ this.ptAssets = ptAssets;
+ this.hasPT = true;
}
if (gc.p_heatBuffer != null) {
- if(gc.p_DHWAsset == null && ptAsset == null) {
- throw new RuntimeException(this.getClass() + " requires a hot water demand and PT to make sense to use this heating management with a heatbuffer.");
+ if(gc.p_DHWAsset == null || ptAssets.size() == 0) {
+ throw new RuntimeException(this.getClass() + " requires a hot water demand and PT to make sense to use this heating management with heatbuffer.");
}
+ this.hotWaterBuffer = gc.p_heatBuffer;
}
if(gc.p_BuildingThermalAsset != null) {
this.building = gc.p_BuildingThermalAsset;