diff --git a/src/EnergyPlus/DataPhotovoltaics.hh b/src/EnergyPlus/DataPhotovoltaics.hh index ae83d1178d4..49c108d7d45 100644 --- a/src/EnergyPlus/DataPhotovoltaics.hh +++ b/src/EnergyPlus/DataPhotovoltaics.hh @@ -406,6 +406,7 @@ namespace DataPhotovoltaics { std::string SurfaceName; // named surface in heat balance domain std::string PerfObjName; int SurfacePtr; // index for named surface + int Zone; // index for zone (for getting any zone multipliers) int PVModelType; // type of performance modeling, Simple, TRNSYS or Equivalent 1-diode, or Sandia/King model int CellIntegrationMode; // how are PV cells integrated with other E+ modeling Real64 NumModNSeries; // number of modules in series in one string @@ -427,6 +428,7 @@ namespace DataPhotovoltaics { // Default Constructor PVArrayStruct() : SurfacePtr( 0 ), + Zone( 0 ), PVModelType( 0 ), CellIntegrationMode( 0 ), NumModNSeries( 1.0 ), diff --git a/src/EnergyPlus/Photovoltaics.cc b/src/EnergyPlus/Photovoltaics.cc index a117d0887d5..cf5edad728d 100644 --- a/src/EnergyPlus/Photovoltaics.cc +++ b/src/EnergyPlus/Photovoltaics.cc @@ -421,6 +421,7 @@ namespace Photovoltaics { ShowContinueError( "Entered in " + cCurrentModuleObject + " = " + cAlphaArgs( 1 ) ); ShowContinueError( "Surface is not exposed to solar, check surface bounday condition" ); } + PVarray( PVnum ).Zone = GetPVZone( PVarray( PVnum ).SurfacePtr ); // check surface orientation, warn if upside down if ( ( Surface( SurfNum ).Tilt < -95.0 ) || ( Surface( SurfNum ).Tilt > 95.0 ) ) { @@ -757,6 +758,34 @@ namespace Photovoltaics { } + int + GetPVZone( int const SurfNum ) + { + // SUBROUTINE INFORMATION: + // AUTHOR Rick Strand + // DATE WRITTEN Sept 2017 + + // PURPOSE OF THIS SUBROUTINE: + // Get the zone number for this PV array for use when zone multipliers are applied + + using DataHeatBalance::Zone; + using DataGlobals::NumOfZones; + using DataSurfaces::Surface; + using InputProcessor::FindItemInList; + + int GetPVZone( 0 ); + + if ( SurfNum > 0 ) { + GetPVZone = Surface( SurfNum ).Zone; + if ( GetPVZone == 0 ) { // might need to get the zone number from the name + GetPVZone = FindItemInList( Surface( SurfNum ).ZoneName, Zone, NumOfZones ); + } + } + + return GetPVZone; + + } + // ************************************** void @@ -856,47 +885,28 @@ namespace Photovoltaics { // AUTHOR B. Griffith // DATE WRITTEN Jan. 2004 // MODIFIED B. Griffith, Aug. 2008 - // RE-ENGINEERED na // PURPOSE OF THIS SUBROUTINE: // collect statements that assign to variables tied to output variables - // METHODOLOGY EMPLOYED: - // - - // REFERENCES: - // na - - // USE STATEMENTS: - // na // Using/Aliasing using DataHeatBalance::Zone; + using DataGlobals::NumOfZones; using DataSurfaces::Surface; using DataHeatBalFanSys::QPVSysSource; using TranspiredCollector::SetUTSCQdotSource; - - // Locals - // SUBROUTINE ARGUMENT DEFINITIONS: - - // SUBROUTINE PARAMETER DEFINITIONS: - // na - - // INTERFACE BLOCK SPECIFICATIONS: - // na - - // DERIVED TYPE DEFINITIONS: - // na + using InputProcessor::FindItemInList; // SUBROUTINE LOCAL VARIABLE DECLARATIONS: int thisZone; // working index for zones PVarray( PVnum ).Report.DCEnergy = PVarray( PVnum ).Report.DCPower * ( TimeStepSys * SecInHour ); - + // add check for multiplier. if surface is attached to a zone that is on a multiplier // then PV production should be multiplied out as well - if ( Surface( PVarray( PVnum ).SurfacePtr ).Zone != 0 ) { // might need to apply multiplier - thisZone = Surface( PVarray( PVnum ).SurfacePtr ).Zone; + thisZone = PVarray( PVnum ).Zone; + if ( thisZone != 0 ) { // might need to apply multiplier PVarray( PVnum ).Report.DCEnergy *= ( Zone( thisZone ).Multiplier * Zone( thisZone ).ListMultiplier ); PVarray( PVnum ).Report.DCPower *= ( Zone( thisZone ).Multiplier * Zone( thisZone ).ListMultiplier ); } diff --git a/src/EnergyPlus/Photovoltaics.hh b/src/EnergyPlus/Photovoltaics.hh index 496bc687c3d..b72f83ed9b5 100644 --- a/src/EnergyPlus/Photovoltaics.hh +++ b/src/EnergyPlus/Photovoltaics.hh @@ -104,6 +104,11 @@ namespace Photovoltaics { void GetPVInput(); + + int + GetPVZone( + int const SurfNum + ); // ************************************** diff --git a/tst/EnergyPlus/unit/Photovoltaics.unit.cc b/tst/EnergyPlus/unit/Photovoltaics.unit.cc index 2f89d896350..4ac2e67c84a 100644 --- a/tst/EnergyPlus/unit/Photovoltaics.unit.cc +++ b/tst/EnergyPlus/unit/Photovoltaics.unit.cc @@ -51,6 +51,9 @@ // EnergyPlus Headers #include +#include +#include +#include #include "Fixtures/EnergyPlusFixture.hh" @@ -73,3 +76,62 @@ TEST_F( EnergyPlusFixture, PV_Sandia_AirMassAtHighZenith ) EXPECT_NEAR( airMass, 26.24135, 0.1 ); } + +TEST_F( EnergyPlusFixture, PV_ReportPV_ZoneIndexNonZero ) +{ + // unit test for issue #6222, test to make sure zone index in surface on which PV is placed is not zero so zone multiplier is applied properly + + EnergyPlus::DataPhotovoltaics::PVarray.deallocate(); + DataHeatBalance::Zone.deallocate(); + DataSurfaces::Surface.deallocate(); + + EnergyPlus::DataPhotovoltaics::PVarray.allocate( 3 ); + DataHeatBalance::Zone.allocate( 2 ); + DataSurfaces::Surface.allocate( 3 ); + + DataGlobals::NumOfZones = 2; + DataHeatBalance::Zone( 1 ).Name = "Zone1"; + DataHeatBalance::Zone( 1 ).ListMultiplier = 1.0; + DataHeatBalance::Zone( 1 ).Multiplier = 5.0; + DataHeatBalance::Zone( 2 ).Name = "Zone2"; + DataHeatBalance::Zone( 2 ).ListMultiplier = 10.0; + DataHeatBalance::Zone( 2 ).Multiplier = 1.0; + + EnergyPlus::DataPhotovoltaics::NumPVs = 3; + EnergyPlus::DataPhotovoltaics::PVarray( 1 ).SurfacePtr = 1; + EnergyPlus::DataPhotovoltaics::PVarray( 1 ).CellIntegrationMode = -9999; + EnergyPlus::DataPhotovoltaics::PVarray( 2 ).SurfacePtr = 2; + EnergyPlus::DataPhotovoltaics::PVarray( 2 ).CellIntegrationMode = -9999; + EnergyPlus::DataPhotovoltaics::PVarray( 3 ).SurfacePtr = 3; + EnergyPlus::DataPhotovoltaics::PVarray( 3 ).CellIntegrationMode = -9999; + + DataSurfaces::Surface( 1 ).Zone = 1; + DataSurfaces::Surface( 1 ).ZoneName = "Zone1"; + DataSurfaces::Surface( 2 ).Zone = 0; + DataSurfaces::Surface( 2 ).ZoneName = "Zone2"; + DataSurfaces::Surface( 3 ).Zone = 0; + DataSurfaces::Surface( 3 ).ZoneName = "None"; + + // Test 1: Zone 1--PV has multiplier, Zone index already set + EnergyPlus::DataPhotovoltaics::PVarray( 1 ).Report.DCPower = 1000.0; + EnergyPlus::DataPhotovoltaics::PVarray( 1 ).Zone = Photovoltaics::GetPVZone( EnergyPlus::DataPhotovoltaics::PVarray( 1 ).SurfacePtr ); + Photovoltaics::ReportPV( 1 ); + EXPECT_EQ( EnergyPlus::DataPhotovoltaics::PVarray( 1 ).Zone, 1 ); + EXPECT_NEAR( EnergyPlus::DataPhotovoltaics::PVarray( 1 ).Report.DCPower, 5000.0, 0.1 ); + + // Test 2: Zone 2--PV has multiplier, Zone index not set yet + EnergyPlus::DataPhotovoltaics::PVarray( 2 ).Report.DCPower = 1000.0; + EnergyPlus::DataPhotovoltaics::PVarray( 2 ).Zone = Photovoltaics::GetPVZone( EnergyPlus::DataPhotovoltaics::PVarray( 2 ).SurfacePtr ); + Photovoltaics::ReportPV( 2 ); + EXPECT_EQ( EnergyPlus::DataPhotovoltaics::PVarray( 2 ).Zone, 2 ); + EXPECT_NEAR( EnergyPlus::DataPhotovoltaics::PVarray( 2 ).Report.DCPower, 10000.0, 0.1 ); + + // Test 3: Zone 3--PV not attached to any zone, Zone Index does not get set + EnergyPlus::DataPhotovoltaics::PVarray( 3 ).Report.DCPower = 1000.0; + EnergyPlus::DataPhotovoltaics::PVarray( 3 ).Zone = Photovoltaics::GetPVZone( EnergyPlus::DataPhotovoltaics::PVarray( 3 ).SurfacePtr ); + Photovoltaics::ReportPV( 3 ); + EXPECT_EQ( EnergyPlus::DataPhotovoltaics::PVarray( 3 ).Zone, 0 ); + EXPECT_NEAR( EnergyPlus::DataPhotovoltaics::PVarray( 3 ).Report.DCPower, 1000.0, 0.1 ); + +} +