diff --git a/src/EnergyPlus/AirflowNetworkSolver.cc b/src/EnergyPlus/AirflowNetworkSolver.cc index b8b7f265b88..586833c4d20 100644 --- a/src/EnergyPlus/AirflowNetworkSolver.cc +++ b/src/EnergyPlus/AirflowNetworkSolver.cc @@ -520,8 +520,14 @@ namespace AirflowNetworkSolver { if ( LIST >= 1 ) { gio::write( Unit21, Format_901 ) << "Flow: " << i << n << M << AirflowNetworkLinkSimu( i ).DP << AFLOW( i ) << AFLOW2( i ); } - SUMAF( n ) = SUMAF( n ) - AFLOW( i ) - AFLOW2( i ); - SUMAF( M ) += AFLOW( i ) + AFLOW2( i ); + if ( AirflowNetworkCompData( AirflowNetworkLinkageData( i ).CompNum ).CompTypeNum == CompTypeNum_HOP ) { + SUMAF( n ) = SUMAF( n ) - AFLOW( i ); + SUMAF( M ) += AFLOW( i ); + } + else { + SUMAF( n ) = SUMAF( n ) - AFLOW( i ) - AFLOW2( i ); + SUMAF( M ) += AFLOW( i ) + AFLOW2( i ); + } } for ( n = 1; n <= NetworkNumOfNodes; ++n ) { if ( LIST >= 1 ) gio::write( Unit21, Format_903 ) << "Room: " << n << PZ( n ) << SUMAF( n ) << TZ( n ); @@ -539,9 +545,12 @@ namespace AirflowNetworkSolver { AirflowNetworkLinkSimu( i ).FLOW2 = -AFLOW( i ); } if ( AirflowNetworkCompData( AirflowNetworkLinkageData( i ).CompNum ).CompTypeNum == CompTypeNum_HOP ) { - if ( AFLOW2( i ) != 0.0 ) { + if ( AFLOW( i ) > 0.0 ) { AirflowNetworkLinkSimu( i ).FLOW = AFLOW( i ) + AFLOW2( i ); AirflowNetworkLinkSimu( i ).FLOW2 = AFLOW2( i ); + } else { + AirflowNetworkLinkSimu( i ).FLOW = AFLOW2( i ); + AirflowNetworkLinkSimu( i ).FLOW2 = -AFLOW( i ) + AFLOW2( i ); } } if ( AirflowNetworkLinkageData( i ).DetOpenNum > 0 ) { @@ -920,9 +929,6 @@ namespace AirflowNetworkSolver { if ( AirflowNetworkCompData( j ).CompTypeNum == CompTypeNum_DOP ) { AFLOW2( i ) = F( 2 ); } - if ( AirflowNetworkCompData( j ).CompTypeNum == CompTypeNum_HOP ) { - AFLOW2( i ) = F( 2 ); - } if ( LIST >= 3 ) gio::write( Unit21, Format_901 ) << " NRi:" << i << n << M << AirflowNetworkLinkSimu( i ).DP << F( 1 ) << DF( 1 ); FLAG = 1; if ( AirflowNetworkNodeData( n ).NodeTypeNum == 0 ) { @@ -3162,7 +3168,7 @@ Label999: ; DH = 4.0 * ( Width * Height ) / 2.0 / ( Width + Height ) * Fact; // Check which zone is higher - + NF = 1; if ( Fact == 0.0 ) { GenericCrack( coef, expn, LFLAG, PDROP, n, M, F, DF, NF ); return; @@ -3222,7 +3228,7 @@ Label999: ; DF( 1 ) = dp1fma12 - dp1fma21; F( 2 ) = 0.0; if ( fma12 != 0.0 && fma21 != 0.0 ) { - F( 2 ) = fma21; + F( 2 ) = BuoFlow; } DF( 2 ) = 0.0; diff --git a/src/EnergyPlus/EvaporativeCoolers.cc b/src/EnergyPlus/EvaporativeCoolers.cc index a2a0e556e74..10e56c93aba 100644 --- a/src/EnergyPlus/EvaporativeCoolers.cc +++ b/src/EnergyPlus/EvaporativeCoolers.cc @@ -2327,7 +2327,7 @@ namespace EvaporativeCoolers { } else { FlowRatio = 1.0; } - if ( AirMassFlowSec >= 0.0 ) { + if ( AirMassFlowSec > 0.0 ) { RhoAirSec = PsyRhoAirFnPbTdbW( OutBaroPress, EDBTSec, EHumRatSec ); RhoAirSys = PsyRhoAirFnPbTdbW( OutBaroPress, EvapCond( EvapCoolNum ).InletTemp, EvapCond( EvapCoolNum ).InletHumRat ); if ( DryOrWetOperatingMode == DryModulated || DryOrWetOperatingMode == DryFull ) { diff --git a/src/EnergyPlus/ManageElectricPower.cc b/src/EnergyPlus/ManageElectricPower.cc index a8ee4c1af84..15914f39a7e 100644 --- a/src/EnergyPlus/ManageElectricPower.cc +++ b/src/EnergyPlus/ManageElectricPower.cc @@ -1528,7 +1528,7 @@ namespace ManageElectricPower { SetupOutputVariable( "Transformer Load Loss Energy [J]", Transformer( TransfNum ).LoadLossEnergy, "System", "Sum", Transformer( TransfNum ).Name ); SetupOutputVariable( "Transformer Thermal Loss Rate [W]", Transformer( TransfNum ).ThermalLossRate, "System", "Average", Transformer( TransfNum ).Name ); SetupOutputVariable( "Transformer Thermal Loss Energy [J]", Transformer( TransfNum ).ThermalLossEnergy, "System", "Sum", Transformer( TransfNum ).Name ); - SetupOutputVariable( "Transformer Distribution Electric Loss Energy [J]", Transformer( TransfNum ).ElecUseUtility, "System", "Sum", Transformer( TransfNum ).Name, _, "Electricity", _, _, "System" ); + SetupOutputVariable( "Transformer Distribution Electric Loss Energy [J]", Transformer( TransfNum ).ElecUseUtility, "System", "Sum", Transformer( TransfNum ).Name, _, "Electricity", "ExteriorEquipment", "Transformer", "System" ); SetupOutputVariable( "Transformer Cogeneration Electric Loss Energy [J]", Transformer( TransfNum ).ElecProducedCoGen, "System", "Sum", Transformer( TransfNum ).Name, _, "ElectricityProduced", "COGENERATION", _, "System" ); if ( Transformer( TransfNum ).ZoneNum > 0 ) { @@ -3029,26 +3029,9 @@ namespace ManageElectricPower { Pw = tmpPdraw / Numbattery; q0 = ElecStorage( ElecStorNum ).LastTimeStepAvailable + ElecStorage( ElecStorNum ).LastTimeStepBound; - I0 = 10.0; // Initial assumption - T0 = qmax / I0; // Initial Assumption - qmaxf = qmax * k * c * T0 / ( 1.0 - std::exp( -k * T0 ) + c * ( k * T0 - 1.0 + std::exp( -k * T0 ) ) ); //Initial calculation of a function qmax(I) - Xf = ( qmax - q0 ) / qmaxf; - Ef = E0c + CurveValue( ElecStorage( ElecStorNum ).DischargeCurveNum, Xf ); //E0d+Ac*Xf+Cc*X/(Dc-Xf) - Volt = Ef - I0 * InternalR; - Inew = Pw / Volt; - Tnew = qmaxf / Inew; - error = 1.0; - - while ( error > 0.0001 ) { //Iteration process to get converged current(I) - I0 = Inew; - T0 = Tnew; - qmaxf = qmax * k * c * T0 / ( 1.0 - std::exp( -k * T0 ) + c * ( k * T0 - 1.0 + std::exp( -k * T0 ) ) ); - Xf = ( qmax - q0 ) / qmaxf; - Ef = E0c + CurveValue( ElecStorage( ElecStorNum ).DischargeCurveNum, Xf ); //E0c+Ad*Xf+Cd*X/(Dd-Xf) - Volt = Ef - I0 * InternalR; - Inew = Pw / Volt; - Tnew = qmaxf / Inew; - error = std::abs( Inew - I0 ); + bool ok = determineCurrentForBatteryDischarge( I0, T0, Volt, Pw, q0, ElecStorage( ElecStorNum ).DischargeCurveNum, k, c, qmax, E0c, InternalR ); + if ( !ok ){ + ShowFatalError( "ElectricLoadCenter:Storage:Battery named=\"" + ElecStorage( ElecStorNum ).Name + "\". Battery discharge current could not be estimated due to iteration limit reached. " ); } dividend = k * ElecStorage( ElecStorNum ).LastTimeStepAvailable * std::exp( -k * TimeStepSys ) + q0 * k * c * ( 1.0 - std::exp( -k * TimeStepSys ) ); @@ -3192,6 +3175,82 @@ namespace ManageElectricPower { //***************************************************************************************************************** + bool + determineCurrentForBatteryDischarge( + Real64& curI0, + Real64& curT0, + Real64& curVolt, + Real64 const Pw, + Real64 const q0, + int const CurveNum, + Real64 const k, + Real64 const c, + Real64 const qmax, + Real64 const E0c, + Real64 const InternalR ) + { + // FUNCTION INFORMATION: + // AUTHOR B. Griffith + // DATE WRITTEN June-August 2008 + // MODIFIED BG May 2009, added EMS + // BN (FSEC) Feb 2010 (pass out two storage values) + // Y. KyungTae & W. Wang July-August, 2011 Added a battery model + // RE-ENGINEERED Jason Glazer, GARD Analytics, February 2015, refactor charge calculation into a function + + // PURPOSE OF THIS FUNCTION: + // Calculate the current for battery discharge in a separate function so that it could be called from the unit tests + + // METHODOLOGY EMPLOYED: + // na + + // REFERENCES: + // na + + // Using/Aliasing + using CurveManager::CurveValue; + + // Locals + // FUNCTION ARGUMENT DEFINITIONS: + + // INTERFACE BLOCK SPECIFICATIONS: + // na + + // DERIVED TYPE DEFINITIONS: + // na + + // FUNCTION LOCAL VARIABLE DECLARATIONS: + curI0 = 10.0; // Initial assumption + curT0 = qmax / curI0; // Initial Assumption + Real64 qmaxf = qmax * k * c * curT0 / ( 1.0 - std::exp( -k * curT0 ) + c * ( k * curT0 - 1.0 + std::exp( -k * curT0 ) ) ); //Initial calculation of a function qmax(I) + Real64 Xf = ( qmax - q0 ) / qmaxf; + Real64 Ef = E0c + CurveValue( CurveNum, Xf ); //E0d+Ac*Xf+Cc*X/(Dc-Xf) + curVolt = Ef - curI0 * InternalR; + Real64 Inew = Pw / curVolt; + Real64 Tnew = qmaxf / Inew; + Real64 error = 1.0; + int countForIteration = 0; + bool exceedIterationLimit = false; + + while ( error > 0.0001 ) { //Iteration process to get converged current(I) + curI0 = Inew; + curT0 = Tnew; + qmaxf = qmax * k * c * curT0 / ( 1.0 - std::exp( -k * curT0 ) + c * ( k * curT0 - 1.0 + std::exp( -k * curT0 ) ) ); + Xf = ( qmax - q0 ) / qmaxf; + Ef = E0c + CurveValue( CurveNum, Xf ); //E0c+Ad*Xf+Cd*X/(Dd-Xf) + curVolt = Ef - curI0 * InternalR; + Inew = Pw / curVolt; + Tnew = qmaxf / Inew; + error = std::abs( Inew - curI0 ); + countForIteration++; + if ( countForIteration > 1000 ){ + exceedIterationLimit = true; + break; + } + } + return (!exceedIterationLimit); + } + + void FigureElectricalStorageZoneGains() { diff --git a/src/EnergyPlus/ManageElectricPower.hh b/src/EnergyPlus/ManageElectricPower.hh index 5fa5d01cdeb..5bca159b83d 100644 --- a/src/EnergyPlus/ManageElectricPower.hh +++ b/src/EnergyPlus/ManageElectricPower.hh @@ -1029,6 +1029,21 @@ namespace ManageElectricPower { //***************************************************************************************************************** + bool + determineCurrentForBatteryDischarge( + Real64& curI0, + Real64& curT0, + Real64& curVolt, + Real64 const Pw, + Real64 const q0, + int const CurveNum, + Real64 const k, + Real64 const c, + Real64 const qmax, + Real64 const E0c, + Real64 const InternalR + ); + void FigureElectricalStorageZoneGains(); diff --git a/src/EnergyPlus/OutputReportTabular.cc b/src/EnergyPlus/OutputReportTabular.cc index 651690d2a20..89646b7efab 100644 --- a/src/EnergyPlus/OutputReportTabular.cc +++ b/src/EnergyPlus/OutputReportTabular.cc @@ -7208,6 +7208,18 @@ namespace OutputReportTabular { } tableBody( 16, iResource ) = RealToStr( useVal( 15, iResource ), 2 ); } + // add warning message if end use values do not add up to total + Real64 curTotal = 0.0; + for ( iResource = 1; iResource <= 6; ++iResource ) { + curTotal = 0.0; + for ( int jUse = 1; jUse <= 14; ++jUse ) { + curTotal += useVal( jUse, iResource ); + } + if ( abs( curTotal - collapsedTotal( iResource ) ) > ( collapsedTotal( iResource ) * 0.001 )) { + ShowWarningError( "In the Annual Building Utility Performance Summary Report the total row does not match the sum of the column for: " + columnHead( 1 ) ); + } + } + //complete the LEED end use table using the same values // for certain rows in the LEED table the subcategories are necessary so first compute those values leedFansParkFromFan = 0.0; diff --git a/src/ExpandObjects/epfilter.f90 b/src/ExpandObjects/epfilter.f90 index 348a76c987f..f4058e20c0a 100644 --- a/src/ExpandObjects/epfilter.f90 +++ b/src/ExpandObjects/epfilter.f90 @@ -3481,13 +3481,16 @@ REAL FUNCTION StringToReal(stringIn) IF (LEN_TRIM(stringIn) .GE. 1) THEN IF (VERIFY(TRIM(stringIn),'-0123456789.E+') .EQ. 0) THEN - READ(stringIn,*) StringToReal + READ(stringIn,*,ERR=2222) StringToReal ELSE StringToReal = 0 END IF ELSE StringToReal = 0 END IF +RETURN + +2222 StringToReal = 0 END FUNCTION !---------------------------------------------------------------------------------- diff --git a/tst/EnergyPlus/unit/AirflowNetworkSolver.unit.cc b/tst/EnergyPlus/unit/AirflowNetworkSolver.unit.cc new file mode 100644 index 00000000000..90ed849bc08 --- /dev/null +++ b/tst/EnergyPlus/unit/AirflowNetworkSolver.unit.cc @@ -0,0 +1,87 @@ +// EnergyPlus::AirflowNetworkSolver unit tests + +// Google test headers +#include + +// C++ Headers +//#include +//#include +//#include + +// ObjexxFCL Headers +//#include +//#include +//#include + +// EnergyPlus Headers +#include +#include +#include + +using namespace EnergyPlus; +using namespace AirflowNetworkBalanceManager; +using namespace DataAirflowNetwork; +using namespace AirflowNetworkSolver; + +TEST( AirflowNetworkSolverTest, HorizontalOpening ) +{ + + int i = 1; + int j = 1; + int CurveNum; + int n; + int m; + int NF; + FArray1D< Real64 > F; + FArray1D< Real64 > DF; + + n = 1; + m = 2; + + + AirflowNetworkCompData.allocate( j ); + AirflowNetworkCompData( j ).TypeNum = 1; + MultizoneSurfaceData.allocate( i ); + MultizoneSurfaceData( i ).Width = 10.0; + MultizoneSurfaceData( i ).Height = 5.0; + MultizoneSurfaceData( i ).OpenFactor = 1.0; + + RHOZ.allocate( 2 ); + RHOZ( 1 ) = 1.2; + RHOZ( 2 ) = 1.18; + + MultizoneCompHorOpeningData.allocate( 1 ); + MultizoneCompHorOpeningData( 1 ).FlowCoef = 0.1; + MultizoneCompHorOpeningData( 1 ).FlowExpo = 0.5; + MultizoneCompHorOpeningData( 1 ).Slope = 90.0; + MultizoneCompHorOpeningData( 1 ).DischCoeff = 0.2; + + F.allocate( 2 ); + DF.allocate( 2 ); + + AirflowNetworkLinkageData.allocate( i ); + AirflowNetworkLinkageData( i ).NodeHeights( 1 ) = 4.0; + AirflowNetworkLinkageData( i ).NodeHeights( 2 ) = 2.0; + + AFEHOP( 1, 1, 0.05, 1, 1, 2, F, DF, NF ); + EXPECT_NEAR( 3.47863, F( 1 ), 0.00001 ); + EXPECT_NEAR( 34.7863, DF( 1 ), 0.0001 ); + EXPECT_NEAR( 2.96657, F( 2 ), 0.00001 ); + EXPECT_EQ( 0.0, DF( 2 ) ); + + AFEHOP( 1, 1, -0.05, 1, 1, 2, F, DF, NF ); + EXPECT_NEAR( -3.42065, F( 1 ), 0.00001 ); + EXPECT_NEAR( 34.20649, DF( 1 ), 0.0001 ); + EXPECT_NEAR( 2.96657, F( 2 ), 0.00001 ); + EXPECT_EQ( 0.0, DF( 2 ) ); + + AirflowNetworkLinkageData.deallocate(); + DF.deallocate(); + F.deallocate(); + RHOZ.deallocate(); + MultizoneCompHorOpeningData.deallocate(); + MultizoneSurfaceData.deallocate(); + AirflowNetworkCompData.deallocate(); +} + + diff --git a/tst/EnergyPlus/unit/CMakeLists.txt b/tst/EnergyPlus/unit/CMakeLists.txt index eb313664541..c9c7fdecadf 100644 --- a/tst/EnergyPlus/unit/CMakeLists.txt +++ b/tst/EnergyPlus/unit/CMakeLists.txt @@ -4,6 +4,7 @@ INCLUDE_DIRECTORIES( ${CMAKE_SOURCE_DIR}/src/EnergyPlus ) set( test_src AdvancedAFN.unit.cc AirflowNetworkBalanceManager.unit.cc + AirflowNetworkSolver.unit.cc DataPlant.unit.cc DataZoneEquipment.unit.cc DXCoils.unit.cc @@ -12,8 +13,9 @@ set( test_src FluidCoolers.unit.cc GroundHeatExchangers.unit.cc HeatBalanceManager.unit.cc - HVACStandaloneERV.unit.cc Humidifiers.unit.cc + HVACStandaloneERV.unit.cc + ManageElectricPower.unit.cc MixedAir.unit.cc PurchasedAirManager.unit.cc OutputProcessor.unit.cc diff --git a/tst/EnergyPlus/unit/ManageElectricPower.unit.cc b/tst/EnergyPlus/unit/ManageElectricPower.unit.cc new file mode 100644 index 00000000000..ee28a68283c --- /dev/null +++ b/tst/EnergyPlus/unit/ManageElectricPower.unit.cc @@ -0,0 +1,51 @@ +// EnergyPlus::ExteriorEnergyUse Unit Tests + +// Google Test Headers +#include + +// EnergyPlus Headers +#include +#include +#include + +using namespace EnergyPlus; +using namespace EnergyPlus::ManageElectricPower; +using namespace EnergyPlus::CurveManager; +using namespace ObjexxFCL; +using namespace DataGlobals; + +TEST( ManageElectricPowerTest, BatteryDischargeTest ) +{ + + NumCurves = 1; + PerfCurve.allocate( NumCurves ); + PerfCurve( 1 ).CurveType = CurveType_RectangularHyperbola1; + PerfCurve( 1 ).InterpolationType = EvaluateCurveToLimits; + PerfCurve( 1 ).Coeff1 = 0.0899; + PerfCurve( 1 ).Coeff2 = -98.24; + PerfCurve( 1 ).Coeff3 = -.0082; + int CurveNum1 = 1; + Real64 k = 0.5874; + Real64 c = 0.37; + Real64 qmax = 86.1; + Real64 E0c = 12.6; + Real64 InternalR = 0.054; + + Real64 I0 = 0.159; + Real64 T0 = 537.9; + Real64 Volt = 12.59; + Real64 Pw = 2.0; + Real64 q0 = 60.2; + + EXPECT_TRUE( determineCurrentForBatteryDischarge( I0, T0, Volt, Pw, q0, CurveNum1, k, c, qmax, E0c, InternalR ) ); + + I0 = -222.7; + T0 = -0.145; + Volt = 24.54; + Pw = 48000; + q0 = 0; + + EXPECT_FALSE( determineCurrentForBatteryDischarge( I0, T0, Volt, Pw, q0, CurveNum1, k, c, qmax, E0c, InternalR ) ); + + PerfCurve.deallocate(); +}