Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cooling Panel UA Calculation Bug for Large Capacity/Low Water Flow Rate #6181

Merged
merged 10 commits into from Aug 19, 2017
Expand Up @@ -571,15 +571,15 @@ \subsubsection{Inputs}\label{inputs-3-028-1}

\paragraph{Field: Rated Water Mass Flow Rate}\label{field-rated-water-mass-flow-rate}

This field is the rated standard water flow rate in kg/s that was used to obtain the rated capacity under rated conditions. This value along with the other rated conditions is used to calculate the overall heat transfer coefficient (U-Value) that will be used to characterize the heat transfer between the water being circulated through the panel and the air in the space. The default value is 0.063kg/s (1 gpm). If it is blank or zero, the default value is assumed.
This field is the rated standard water flow rate in kg/s that was used to obtain the design cooling capacity under rated temperature conditions. This value along with the rated space and water inlet temperatures as well as the cooling capacity (whether autosized or entered by the user) to calculate the overall heat transfer coefficient (U-Value) that will be used to characterize the heat transfer between the water being circulated through the panel and the air in the space. Users should note that if this value is too low in comparison to the cooling design capacity that the program will produce an error message and the user must adjust one of these two parameters or the rated temperature values. The default value is 0.063kg/s (1 gpm). If it is blank or zero, the default value is assumed.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that perhaps the second sentence here needs a "is used" someplace.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jasondegraw I agree...I thought I had commented on this earlier and it is not showing up here now. Anyway, yes, I will correct this as soon as possible.


\paragraph{Field: Cooling Design Capacity Method}\label{field-cooling-design-capacity-method-2}

Enter the method used to determine the heating design capacity for scalable sizing. Input allowed is either \emph{CoolingDesignCapacity}, \emph{CapacityPerFloorArea}, and \emph{FractionOfAutosizedCoolingCapacity}. If this input field is left blank or zero, then autosizing is assumed. \emph{CoolingDesignCapacity} means the user specifies the magnitude of maximum or nominal cooling capacity or the program calculates the maximum or nominal design cooling capacity if autosize is specified. \emph{CapacityPerFloorArea} means the program calculates the design cooling capacity from the user specified cooling capacity per floor area and floor area of the zone served by the cooling panel unit. \emph{FractionOfAutosizedCoolingCapacity} means the program calculates the design cooling capacity from user specified fraction and the auto-sized design cooling capacity. The default method is \emph{CoolingDesignCapacity}.

\paragraph{Field: Cooling Design Capacity}\label{field-cooling-design-capacity-2}

This field is for the cooling panel unit nominal cooling capacity in watts. This field can be autosized by EnergyPlus. When the Cooling Design Capacity Method is \emph{CoolingDesignCapacity}~ and this input is is blank, autosizing is assumed. Design day sizing run must be specified.
This field is for the cooling panel unit nominal cooling capacity in watts at the rated flow rate of water through the unit (see Rated Water Mass Flow Rate field above). This field can be autosized by EnergyPlus. When the Cooling Design Capacity Method is \emph{CoolingDesignCapacity}~ and this input is is blank, autosizing is assumed. Design day sizing run must be specified.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if another commit is required, this text could be corrected. "is is"

... and this input is is blank, autosizing is assumed.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rraustad I see it and will correct it. Need to make another commit to add things to the code per your other comments so this will get in.

\paragraph{Field: Cooling Design Capacity Per Floor Area}\label{field-cooling-design-capacity-per-floor-area-2}

Expand Down
43 changes: 38 additions & 5 deletions src/EnergyPlus/ChilledCeilingPanelSimple.cc
Expand Up @@ -1015,29 +1015,62 @@ namespace CoolingPanelSimple {

RegisterPlantCompDesignFlow( CoolingPanel( CoolingPanelNum ).WaterInletNode, CoolingPanel( CoolingPanelNum ).WaterVolFlowRateMax );

bool SizeUAErrorFlag = false;
SizeCoolingPanelUA( CoolingPanelNum, SizeUAErrorFlag );
if ( SizeUAErrorFlag ) ShowFatalError( "SizeCoolingPanelUA: Program terminated for previous conditions." );

}

void
SizeCoolingPanelUA(
int const CoolingPanelNum,
bool & SizeUAError
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we change this function so rather than returning the error status via the reference it returns true on success and false on failure? It's a more "C++" way of doing this.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jasondegraw Any objections to lumping this comment together with some other C++ modifications that have been requested? That is already the subject for Followup for new cooling panel ZoneHVAC:CoolingPanel:RadiantConvective:Water (GitHub Issue #5823).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@RKStrand That sounds good to me.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@RKStrand I think maybe I was unclear on what I was suggesting here, sorry if that was the case. What I was suggesting here was to change the function signature to bool SizeCoolingPanelUA(int const CoolingPanelNum) rather than use a reference.

)
{
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

spacing severely messed up here

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, this was messed up. Fixed now.

// SUBROUTINE INFORMATION:
// AUTHOR Rick Strand
// DATE WRITTEN June 2017

// PURPOSE OF THIS SUBROUTINE:
// This subroutine sizes UA value for the simple chilled ceiling panel.

// These initializations are mainly the calculation of the UA value for the heat exchanger formulation of the simple cooling panel
Real64 Cp;
Real64 MDot;
Real64 MDotXCp;
Real64 Qrated;
Real64 Tinletr;
Real64 Tzoner;
Real64 RatCapToTheoMax; // Ratio of unit capacity to theoretical maximum output based on rated parameters

SizeUAError = false;
Cp = 4120.0; // Just an approximation, don't need to get an exact number
Copy link
Contributor

@rraustad rraustad Aug 10, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why don't we need an exact number if a few lines below we test for RatCapToTheoMax < 1.0 ?? What if RatCapToTheoMax is 1.0001 because we weren't accurate on Cp?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rraustad Well, I see your point that perhaps this needs a bit of tolerance in here. This is mostly to trap the clearly illogical. I will outline something in response to your next comment.

MDot = CoolingPanel( CoolingPanelNum ).RatedWaterFlowRate;
MDotXCp = Cp * MDot;
Qrated = CoolingPanel( CoolingPanelNum ).ScaledCoolingCapacity;
Tinletr = CoolingPanel( CoolingPanelNum ).RatedWaterTemp;
Tzoner = CoolingPanel( CoolingPanelNum ).RatedZoneAirTemp;
RatCapToTheoMax = std::abs(Qrated) / ( MDotXCp * std::abs( Tinletr - Tzoner ) );
if (RatCapToTheoMax >= 1.0 ) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why can't RatCapToTheoMax = 1?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rraustad Two reasons. First because physically you can't get more heat transfer out of the fluid than physically possible. Having a ratio of higher than 1 means that the exit temperature of the water leaving the panel would be warmer than the room temperature, violating the 2nd Law. Second because in the code following this it would take the log of a zero or negative number which would cause a crash. Basically the user is setting up a cooling panel that is better than a perfect heat transfer device using rated input that does not make sense. Admittedly, with a fixed Cp number this could result if the user is "flying to close to the sun". I will adjust the code to be a little more gracious but also to limit the RatCaptoTheoMax number to something that will still allow a calculation. So, it will only trap things when there is really a problem with the input.

ShowSevereError( "SizeCoolingPanelUA: Unit=[" + cCMO_CoolingPanel_Simple + ',' + CoolingPanel( CoolingPanelNum ).EquipID + "] has a cooling capacity that is greater than the maximum possible value." );
ShowContinueError( "The result of this is that a UA value is impossible to calculate." );
ShowContinueError( "Check the rated input for temperatures, flow, and capacity for this unit." );
ShowContinueError( "The ratio of the capacity to the rated theoretical maximum must be less than unity." );
ShowContinueError( "The most likely cause for this is probably either the capacity (whether autosized or hardwired) being too high or the rated flow being too low." );
SizeUAError = true;
CoolingPanel( CoolingPanelNum ).UA = 1.0;
}
if ( Tinletr >= Tzoner ) {
ShowSevereError( "SizeCoolingPanel: Unit=[" + cCMO_CoolingPanel_Simple + ',' + CoolingPanel( CoolingPanelNum ).EquipID + "] has a rated water temperature that is higher than the rated zone temperature." );
ShowSevereError( "SizeCoolingPanelUA: Unit=[" + cCMO_CoolingPanel_Simple + ',' + CoolingPanel( CoolingPanelNum ).EquipID + "] has a rated water temperature that is higher than the rated zone temperature." );
ShowContinueError( "Such a situation would not lead to cooling and thus the rated water or zone temperature or both should be adjusted." );
ShowFatalError( "SizeCoolingPanel: Program terminated for previous conditions." );
SizeUAError = true;
CoolingPanel( CoolingPanelNum ).UA = 1.0;
} else {
CoolingPanel( CoolingPanelNum ).UA = -MDotXCp * log( 1.0 - ( std::abs(Qrated) / ( MDotXCp * std::abs( Tinletr - Tzoner ) ) ) );
CoolingPanel( CoolingPanelNum ).UA = -MDotXCp * log( 1.0 - RatCapToTheoMax );
if ( CoolingPanel( CoolingPanelNum ).UA <= 0.0 ) {
ShowSevereError( "SizeCoolingPanel: Unit=[" + cCMO_CoolingPanel_Simple + ',' + CoolingPanel( CoolingPanelNum ).EquipID + "] has a zero or negative calculated UA value." );
ShowSevereError( "SizeCoolingPanelUA: Unit=[" + cCMO_CoolingPanel_Simple + ',' + CoolingPanel( CoolingPanelNum ).EquipID + "] has a zero or negative calculated UA value." );
ShowContinueError( "This is not allowed. Please check the rated input parameters for this device to ensure that the values are correct." );
ShowFatalError( "SizeCoolingPanel: Program terminated for previous conditions." );
SizeUAError = true;
}
}

Expand Down
5 changes: 5 additions & 0 deletions src/EnergyPlus/ChilledCeilingPanelSimple.hh
Expand Up @@ -254,6 +254,11 @@ namespace CoolingPanelSimple {
void SizeCoolingPanel(
int const CoolingPanelNum
);

void SizeCoolingPanelUA(
int const CoolingPanelNum,
bool & SizeUAError
);

void
CalcCoolingPanel(
Expand Down
37 changes: 37 additions & 0 deletions tst/EnergyPlus/unit/ChilledCeilingPanelSimple.unit.cc
Expand Up @@ -105,5 +105,42 @@ namespace EnergyPlus {

}

TEST_F( EnergyPlusFixture, SizeCoolingPanelUA )
{

int CoolingPanelNum; // Cooling panel number
bool SizeUAErrorFlag;

CoolingPanelNum = 1;
SizeUAErrorFlag = false;

CoolingPanelSimple::CoolingPanel.allocate( CoolingPanelNum );

CoolingPanel( CoolingPanelNum ).RatedWaterFlowRate = 1.0;

// No error case
CoolingPanel( CoolingPanelNum ).RatedWaterFlowRate = 1.0;
CoolingPanel( CoolingPanelNum ).ScaledCoolingCapacity = 4000.0;
CoolingPanel( CoolingPanelNum ).RatedWaterTemp = 20.0;
CoolingPanel( CoolingPanelNum ).RatedZoneAirTemp = 21.0;
SizeCoolingPanelUA( CoolingPanelNum, SizeUAErrorFlag );
EXPECT_EQ( SizeUAErrorFlag, false );

// Capacity too high case
CoolingPanel( CoolingPanelNum ).RatedWaterFlowRate = 1.0;
CoolingPanel( CoolingPanelNum ).ScaledCoolingCapacity = 5000.0;
CoolingPanel( CoolingPanelNum ).RatedWaterTemp = 20.0;
CoolingPanel( CoolingPanelNum ).RatedZoneAirTemp = 21.0;
SizeCoolingPanelUA( CoolingPanelNum, SizeUAErrorFlag );
EXPECT_EQ( SizeUAErrorFlag, true );

// Water temperature higher than zone temperature (not cooling) case
CoolingPanel( CoolingPanelNum ).RatedWaterFlowRate = 1.0;
CoolingPanel( CoolingPanelNum ).ScaledCoolingCapacity = 4000.0;
CoolingPanel( CoolingPanelNum ).RatedWaterTemp = 21.0;
CoolingPanel( CoolingPanelNum ).RatedZoneAirTemp = 20.0;
SizeCoolingPanelUA( CoolingPanelNum, SizeUAErrorFlag );
EXPECT_EQ( SizeUAErrorFlag, true );

}
}