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: 7 additions & 1 deletion Zero_engine.alpx
Original file line number Diff line number Diff line change
Expand Up @@ -1595,7 +1595,8 @@
<JavaClass>
<Id>1753167599716</Id>
<Name><![CDATA[J_HeatingManagementBuildingHybridHeatPump]]></Name>
<Folder>1762850578079</Folder>
<ExcludeFromBuild>true</ExcludeFromBuild>
<Folder>1762850602203</Folder>
</JavaClass>
<JavaClass>
<Id>1753795104493</Id>
Expand Down Expand Up @@ -1775,6 +1776,11 @@
<Name><![CDATA[I_AssetManagement]]></Name>
<Folder>1762850551601</Folder>
</JavaClass>
<JavaClass>
<Id>1763394890431</Id>
<Name><![CDATA[J_HeatingManagementPIcontrolHybridHeatpump]]></Name>
<Folder>1762850578079</Folder>
</JavaClass>
</JavaClasses>
<RequiredLibraryReference>
<LibraryName>com.anylogic.libraries.modules.markup_descriptors</LibraryName>
Expand Down
2 changes: 1 addition & 1 deletion _alp/Classes/Class.I_HeatingManagement.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "type")


public interface I_HeatingManagement extends I_AssetManagement{
public interface I_HeatingManagement extends I_AssetManagement{
void manageHeating();
// Initiliaze throws an exception when the configuration of assets is not a valid combination
void initializeAssets();
Expand Down
3 changes: 2 additions & 1 deletion _alp/Classes/Class.J_AVGC_data.java
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,8 @@ public class J_AVGC_data implements Serializable {

public double p_avgCOPHeatpump;
public double p_avgEfficiencyHeatpump_fr;
public double p_avgOutputTemperatureHeatpump_degC;
public double p_avgOutputTemperatureElectricHeatpump_degC;
public double p_avgOutputTemperatureHybridHeatpump_degC;
public double p_minHeatpumpElectricCapacity_kW;

public double p_avgEfficiencyGasBurner_fr;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ private double[] getNettoBalanceForecast_kW() {
double[] heatPower_kW = ZeroMath.arrayMultiply(Arrays.copyOfRange(surveyHeatDemandProfile.a_energyProfile_kWh, startTimeDayIndex, endTimeDayIndex), surveyHeatDemandProfile.getProfileScaling_fr()/p_timestep_h);
//traceln(heatPower_kW);
double eta_r = parentGC.energyModel.avgc_data.p_avgEfficiencyHeatpump_fr;
double outputTemperature_degC = parentGC.energyModel.avgc_data.p_avgOutputTemperatureHeatpump_degC;
double outputTemperature_degC = parentGC.energyModel.avgc_data.p_avgOutputTemperatureElectricHeatpump_degC;
for(double time = energyModel_time_h; time < energyModel_time_h + 24; time += p_timestep_h){
double baseTemperature_degC = parentGC.energyModel.pp_ambientTemperature_degC.getValue(time);
double COP_r = eta_r * ( 273.15 + outputTemperature_degC ) / ( outputTemperature_degC - baseTemperature_degC );
Expand All @@ -129,7 +129,7 @@ private double[] getNettoBalanceForecast_kW() {
if(genericHeatDemandProfile != null){

double eta_r = parentGC.energyModel.avgc_data.p_avgEfficiencyHeatpump_fr;
double outputTemperature_degC = parentGC.energyModel.avgc_data.p_avgOutputTemperatureHeatpump_degC;
double outputTemperature_degC = parentGC.energyModel.avgc_data.p_avgOutputTemperatureElectricHeatpump_degC;

for(double time = energyModel_time_h; time < energyModel_time_h + 24; time += p_timestep_h){
double baseTemperature_degC = parentGC.energyModel.pp_ambientTemperature_degC.getValue(time);
Expand Down
110 changes: 85 additions & 25 deletions _alp/Classes/Class.J_HeatingManagementBuildingHybridHeatPump.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,6 @@ public class J_HeatingManagementBuildingHybridHeatPump implements I_HeatingManag
private J_EAConversionHeatPump heatPumpAsset;
private J_EAConversionGasBurner gasBurnerAsset;
private J_HeatingPreferences heatingPreferences;


private double heatingKickinTreshhold_degC = 1;

/**
* Default constructor
Expand All @@ -40,52 +37,115 @@ public J_HeatingManagementBuildingHybridHeatPump( GridConnection gc, OL_GridConn
this.gc = gc;
this.currentHeatingType = heatingType;
}

public J_HeatingManagementBuildingHybridHeatPump( GridConnection gc, OL_GridConnectionHeatingType heatingType, double heatingKickinTreshhold_degC ) {
this.gc = gc;
this.currentHeatingType = heatingType;
this.heatingKickinTreshhold_degC = heatingKickinTreshhold_degC;
}

public void manageHeating() {
if ( !isInitialized ) {
this.initializeAssets();
}
double heatDemand_kW = gc.fm_currentBalanceFlows_kW.get(OL_EnergyCarriers.HEAT);
double buildingPower_kW = 0;
double assetOutputPower_kW = heatPumpAsset.getCOP() > 3.0 ? heatPumpAsset.getOutputCapacity_kW() : gasBurnerAsset.getOutputCapacity_kW();

//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 otherHeatDemand_kW = gc.fm_currentBalanceFlows_kW.get(OL_EnergyCarriers.HEAT);

double buildingHeatingDemand_kW = 0;
double buildingTemp_degC = building.getCurrentTemperature();
double timeOfDay_h = gc.energyModel.t_hourOfDay;
if (timeOfDay_h < heatingPreferences.getStartOfDayTime_h() || timeOfDay_h >= heatingPreferences.getStartOfNightTime_h()) {
if (buildingTemp_degC < heatingPreferences.getNightTimeSetPoint_degC() - heatingKickinTreshhold_degC) {
double buildingPowerSetpoint_kW = (heatingPreferences.getNightTimeSetPoint_degC() - buildingTemp_degC) * this.building.heatCapacity_JpK / 3.6e6 / gc.energyModel.p_timeStep_h;
buildingPower_kW = min(assetOutputPower_kW - heatDemand_kW, buildingPowerSetpoint_kW);
if (buildingTemp_degC < heatingPreferences.getNightTimeSetPoint_degC()) {
buildingHeatingDemand_kW = (heatingPreferences.getNightTimeSetPoint_degC() - buildingTemp_degC) * this.building.heatCapacity_JpK / 3.6e6 / gc.energyModel.p_timeStep_h;
}
}
else {
if (buildingTemp_degC < heatingPreferences.getDayTimeSetPoint_degC() - heatingKickinTreshhold_degC) {
double buildingPowerSetpoint_kW = (heatingPreferences.getDayTimeSetPoint_degC() - buildingTemp_degC) * this.building.heatCapacity_JpK / 3.6e6 / gc.energyModel.p_timeStep_h;
buildingPower_kW = min(assetOutputPower_kW - heatDemand_kW, buildingPowerSetpoint_kW);
if (buildingTemp_degC < heatingPreferences.getDayTimeSetPoint_degC()) {
buildingHeatingDemand_kW = (heatingPreferences.getDayTimeSetPoint_degC() - buildingTemp_degC) * this.building.heatCapacity_JpK / 3.6e6 / gc.energyModel.p_timeStep_h;
}
}


//Set asset power based on the COP (All demand profiles (hot water, etc.) always go to the gasburner!)
double heatpumpAssetPower_kW = 0;
double gasBurnerAssetPower_kW = 0;
double heatIntoBuilding_kW = 0;

if (heatPumpAsset.getCOP() > 3.0 ) {
heatPumpAsset.f_updateAllFlows( (buildingPower_kW + heatDemand_kW) / heatPumpAsset.getOutputCapacity_kW() );
building.f_updateAllFlows( buildingPower_kW / building.getCapacityHeat_kW() );
gasBurnerAsset.f_updateAllFlows( 0.0 );
heatpumpAssetPower_kW = min(heatPumpAsset.getOutputCapacity_kW(), buildingHeatingDemand_kW);
gasBurnerAssetPower_kW = min(gasBurnerAsset.getOutputCapacity_kW(), otherHeatDemand_kW + max(0, buildingHeatingDemand_kW - heatpumpAssetPower_kW));
heatIntoBuilding_kW = heatpumpAssetPower_kW + max(0, gasBurnerAssetPower_kW - otherHeatDemand_kW);
}
else {
gasBurnerAsset.f_updateAllFlows( (buildingPower_kW + heatDemand_kW) / gasBurnerAsset.getOutputCapacity_kW() );
building.f_updateAllFlows( buildingPower_kW / building.getCapacityHeat_kW() );
heatPumpAsset.f_updateAllFlows( 0.0 );
heatpumpAssetPower_kW = 0.0;
gasBurnerAssetPower_kW = min(gasBurnerAsset.getOutputCapacity_kW(), buildingHeatingDemand_kW + otherHeatDemand_kW);
heatIntoBuilding_kW = max(0, gasBurnerAssetPower_kW - otherHeatDemand_kW);
}

//Update flows with found asset powers
heatPumpAsset.f_updateAllFlows( heatpumpAssetPower_kW / heatPumpAsset.getOutputCapacity_kW() );
gasBurnerAsset.f_updateAllFlows( gasBurnerAssetPower_kW / gasBurnerAsset.getOutputCapacity_kW());
building.f_updateAllFlows( heatIntoBuilding_kW / building.getCapacityHeat_kW() );

}

private double managePTAndHotWaterHeatBuffer(double hotWaterDemand_kW){

//Calculate the pt production
double ptProduction_kW = 0;
List<J_EAProduction> 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) {
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.");
}
}
if (gc.p_heatBuffer != null) {
throw new RuntimeException(this.getClass() + " does not support heat buffers.");
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_BuildingThermalAsset != null) {
this.building = gc.p_BuildingThermalAsset;
Expand Down
2 changes: 1 addition & 1 deletion _alp/Classes/Class.J_HeatingManagementPIcontrol.java
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ public void manageHeating() {

}

public double managePTAndHotWaterHeatBuffer(double hotWaterDemand_kW){
private double managePTAndHotWaterHeatBuffer(double hotWaterDemand_kW){

//Calculate the pt production
double ptProduction_kW = 0;
Expand Down
Loading