diff --git a/src/EnergyPlus/FanCoilUnits.cc b/src/EnergyPlus/FanCoilUnits.cc index 86016b5a678..5bfbf68ce34 100644 --- a/src/EnergyPlus/FanCoilUnits.cc +++ b/src/EnergyPlus/FanCoilUnits.cc @@ -2128,6 +2128,7 @@ namespace FanCoilUnits { ZoneEqSizing(CurZoneEqNum).AirVolFlow = FanCoil(FanCoilNum).MaxAirVolFlow; ZoneEqSizing(CurZoneEqNum).DesCoolingLoad = FanCoil(FanCoilNum).DesCoolingLoad; ZoneEqSizing(CurZoneEqNum).DesHeatingLoad = FanCoil(FanCoilNum).DesHeatingLoad; + ZoneEqSizing(CurZoneEqNum).DesignSizeFromParent = true; } if (ErrorsFound) { diff --git a/src/EnergyPlus/WaterCoils.cc b/src/EnergyPlus/WaterCoils.cc index 6b7e208c7b0..b11bc5af450 100644 --- a/src/EnergyPlus/WaterCoils.cc +++ b/src/EnergyPlus/WaterCoils.cc @@ -2196,14 +2196,29 @@ namespace WaterCoils { } bPRINT = false; // do not print this sizing request since the autosized value is needed and this input may not be autosized (we // should print this!) - TempSize = AutoSize; // get the autosized air volume flow rate for use in other calculations + if (WaterCoil(CoilNum).DesAirVolFlowRate == DataFlowUsedForSizing) { + TempSize = WaterCoil(CoilNum).DesAirVolFlowRate; // represents parent object has hard-sized airflow + } else { + TempSize = AutoSize; // get the autosized air volume flow rate for use in other calculations + } SizingString.clear(); // doesn't matter CompName = WaterCoil(CoilNum).Name; RequestSizing(state, CompType, CompName, CoolingAirflowSizing, SizingString, TempSize, bPRINT, RoutineName); WaterCoil(CoilNum).InletAirMassFlowRate = StdRhoAir * TempSize; // inlet air mass flow rate is the autosized value - DataAirFlowUsedForSizing = TempSize; // many autosized inputs use the design (autosized) air volume flow rate, save this value - DataFlowUsedForSizing = TempSize; - + // Check if the air volume flow rate is defined in parent HVAC equipment and set water coil design air volume flow rate accordingly + if (CurZoneEqNum > 0) { + if (ZoneEqSizing(CurZoneEqNum).DesignSizeFromParent && WaterCoil(CoilNum).DesAirVolFlowRate == TempSize) { + DataAirFlowUsedForSizing = ZoneEqSizing(CurZoneEqNum).AirVolFlow; + DataFlowUsedForSizing = ZoneEqSizing(CurZoneEqNum).AirVolFlow; + WaterCoil(CoilNum).DesAirVolFlowRate = AutoSize; // represents water coil being autosized + } else { + DataAirFlowUsedForSizing = TempSize; // many autosized inputs use the design (autosized) air volume flow rate, save this value + DataFlowUsedForSizing = TempSize; + } + } else { + DataAirFlowUsedForSizing = TempSize; // many autosized inputs use the design (autosized) air volume flow rate, save this value + DataFlowUsedForSizing = TempSize; + } if (CurSysNum > 0 && CurOASysNum == 0) { Real64 DesCoilExitHumRat(0.0); // fix coil sizing inconsistency GetCoilDesFlowT(CurSysNum, CpAirStd, DesCoilAirFlow, DesCoilExitTemp, DesCoilExitHumRat); @@ -2227,7 +2242,16 @@ namespace WaterCoils { DataCapacityUsedForSizing = TempSize; TempSize = WaterCoil(CoilNum).MaxWaterVolFlowRate; RequestSizing(state, CompType, CompName, CoolingWaterflowSizing, SizingString, TempSize, bPRINT, RoutineName); - DataWaterFlowUsedForSizing = TempSize; + // Check if the water flow rate is defined in parent HVAC equipment and set water coil design water flow rate accordingly + if (CurZoneEqNum > 0) { + if (ZoneEqSizing(CurZoneEqNum).DesignSizeFromParent) { + DataWaterFlowUsedForSizing = ZoneEqSizing(CurZoneEqNum).MaxCWVolFlow; + } else { + DataWaterFlowUsedForSizing = TempSize; + } + } else { + DataWaterFlowUsedForSizing = TempSize; + } // end pre-sizing data calculations if (WaterCoil(CoilNum).WaterCoilModel == CoilModel_Detailed) { // 'DETAILED FLAT FIN' @@ -2586,8 +2610,19 @@ namespace WaterCoils { DataFractionUsedForSizing = 1.0; } RequestSizing(state, CompType, CompName, SizingMethod, SizingString, TempSize, bPRINT, RoutineName); - WaterCoil(CoilNum).MaxWaterVolFlowRate = TempSize; - DataWaterFlowUsedForSizing = WaterCoil(CoilNum).MaxWaterVolFlowRate; + // Check if the water flow rate is defined in parent HVAC equipment and set water coil design water flow rate accordingly + if (CurZoneEqNum > 0) { + if (ZoneEqSizing(CurZoneEqNum).DesignSizeFromParent) { + DataWaterFlowUsedForSizing = ZoneEqSizing(CurZoneEqNum).MaxHWVolFlow; + WaterCoil(CoilNum).MaxWaterVolFlowRate = ZoneEqSizing(CurZoneEqNum).MaxHWVolFlow; + } else { + DataWaterFlowUsedForSizing = TempSize; + WaterCoil(CoilNum).MaxWaterVolFlowRate = TempSize; + } + } else { + DataWaterFlowUsedForSizing = TempSize; + WaterCoil(CoilNum).MaxWaterVolFlowRate = TempSize; + } DataConstantUsedForSizing = 0.0; // reset these in case NomCapUserInp was true DataFractionUsedForSizing = 0.0; if (WaterCoil(CoilNum).MaxWaterVolFlowRate <= 0.0) { @@ -5941,10 +5976,10 @@ namespace WaterCoils { UtilityRoutines::SameString(CoilType, "Coil:Cooling:Water")) { WhichCoil = UtilityRoutines::FindItem(CoilName, WaterCoil); if (WhichCoil != 0) { - if (UtilityRoutines::SameString(CoilType, "Coil:Cooling:Water") && WaterCoil(WhichCoil).DesAirVolFlowRate < 0.0) { + if (WaterCoil(WhichCoil).DesAirVolFlowRate <= 0.0) { WaterCoil(WhichCoil).DesAirVolFlowRate = CoilDesFlow; } else { - WaterCoil(WhichCoil).DesAirVolFlowRate = CoilDesFlow; + //WaterCoil(WhichCoil).DesAirVolFlowRate = CoilDesFlow; } } else { ShowSevereError("GetCoilMaxWaterFlowRate: Could not find Coil, Type=\"" + CoilType + "\" Name=\"" + CoilName + "\""); diff --git a/tst/EnergyPlus/unit/AirTerminalSingleDuctMixer.unit.cc b/tst/EnergyPlus/unit/AirTerminalSingleDuctMixer.unit.cc index a50bf828398..02ec60aee7f 100644 --- a/tst/EnergyPlus/unit/AirTerminalSingleDuctMixer.unit.cc +++ b/tst/EnergyPlus/unit/AirTerminalSingleDuctMixer.unit.cc @@ -7760,14 +7760,14 @@ TEST_F(EnergyPlusFixture, AirTerminalSingleDuctMixer_SimFCU_ATMInletSideTest) SecondaryAirMassFlowRate = Node(thisFanCoil.AirInNode).MassFlowRate - PrimaryAirMassFlowRate; // check results in cooling mode operation EXPECT_NEAR(QZnReq, QUnitOut, 5.0); - EXPECT_NEAR(thisFanCoil.PLR, 0.83865, 0.00001); + EXPECT_NEAR(thisFanCoil.PLR, 0.78843, 0.00001); // check mass flow rates EXPECT_NEAR(PrimaryAirMassFlowRate, 0.2, 0.000001); - EXPECT_NEAR(SecondaryAirMassFlowRate, 0.405995, 0.000001); + EXPECT_NEAR(SecondaryAirMassFlowRate, 0.369710, 0.000001); EXPECT_NEAR(Node(thisFanCoil.AirInNode).MassFlowRate, thisFan.InletAirMassFlowRate, 0.000001); EXPECT_NEAR(Node(thisFanCoil.ATMixerPriNode).MassFlowRate, 0.2, 0.0001); - EXPECT_NEAR(Node(thisFanCoil.ATMixerSecNode).MassFlowRate, 0.405995, 0.000001); - EXPECT_NEAR(Node(thisFanCoil.ATMixerOutNode).MassFlowRate, 0.605995, 0.000001); + EXPECT_NEAR(Node(thisFanCoil.ATMixerSecNode).MassFlowRate, 0.369710, 0.000001); + EXPECT_NEAR(Node(thisFanCoil.ATMixerOutNode).MassFlowRate, 0.569710, 0.000001); } TEST_F(EnergyPlusFixture, AirTerminalSingleDuctMixer_FCU_NightCycleTest) diff --git a/tst/EnergyPlus/unit/FanCoilUnits.unit.cc b/tst/EnergyPlus/unit/FanCoilUnits.unit.cc index e49be9b2004..01bb55fa2a9 100644 --- a/tst/EnergyPlus/unit/FanCoilUnits.unit.cc +++ b/tst/EnergyPlus/unit/FanCoilUnits.unit.cc @@ -2087,6 +2087,8 @@ namespace EnergyPlus { UpdateScheduleValues(); ZoneEqSizing.allocate(1); + ZoneEqSizing(CurZoneEqNum).SizingMethod.allocate(16); + ZoneEqSizing(CurZoneEqNum).SizingMethod(16) = 0; CurDeadBandOrSetback.allocate(1); CurDeadBandOrSetback(1) = false; TempControlType.allocate(1); @@ -2795,6 +2797,8 @@ namespace EnergyPlus { UpdateScheduleValues(); ZoneEqSizing.allocate(1); + ZoneEqSizing(CurZoneEqNum).SizingMethod.allocate(16); + ZoneEqSizing(CurZoneEqNum).SizingMethod(16) = 0; CurDeadBandOrSetback.allocate(1); CurDeadBandOrSetback(1) = false; TempControlType.allocate(1); @@ -3206,6 +3210,8 @@ namespace EnergyPlus { UpdateScheduleValues(); ZoneEqSizing.allocate(1); + ZoneEqSizing(CurZoneEqNum).SizingMethod.allocate(16); + ZoneEqSizing(CurZoneEqNum).SizingMethod(16) = 0; CurDeadBandOrSetback.allocate(1); CurDeadBandOrSetback(1) = false; TempControlType.allocate(1); @@ -3566,6 +3572,8 @@ namespace EnergyPlus { DataEnvironment::DayOfYear_Schedule = General::OrdinalDay(Month, DayOfMonth, 1); UpdateScheduleValues(); ZoneEqSizing.allocate(1); + ZoneEqSizing(CurZoneEqNum).SizingMethod.allocate(16); + ZoneEqSizing(CurZoneEqNum).SizingMethod(16) = 0; CurDeadBandOrSetback.allocate(1); CurDeadBandOrSetback(1) = false; TempControlType.allocate(1); @@ -3931,6 +3939,8 @@ namespace EnergyPlus { DataEnvironment::DayOfYear_Schedule = General::OrdinalDay(Month, DayOfMonth, 1); UpdateScheduleValues(); ZoneEqSizing.allocate(1); + ZoneEqSizing(CurZoneEqNum).SizingMethod.allocate(16); + ZoneEqSizing(CurZoneEqNum).SizingMethod(16) = 0; CurDeadBandOrSetback.allocate(1); CurDeadBandOrSetback(1) = false; TempControlType.allocate(1); @@ -4296,6 +4306,8 @@ namespace EnergyPlus { DataEnvironment::DayOfYear_Schedule = General::OrdinalDay(Month, DayOfMonth, 1); UpdateScheduleValues(); ZoneEqSizing.allocate(1); + ZoneEqSizing(CurZoneEqNum).SizingMethod.allocate(16); + ZoneEqSizing(CurZoneEqNum).SizingMethod(16) = 0; CurDeadBandOrSetback.allocate(1); CurDeadBandOrSetback(1) = false; TempControlType.allocate(1); diff --git a/tst/EnergyPlus/unit/WaterCoils.unit.cc b/tst/EnergyPlus/unit/WaterCoils.unit.cc index 501f8ee774e..e8608132b9c 100644 --- a/tst/EnergyPlus/unit/WaterCoils.unit.cc +++ b/tst/EnergyPlus/unit/WaterCoils.unit.cc @@ -65,13 +65,26 @@ #include #include #include +#include +#include #include +#include +#include +#include #include #include #include +#include +#include #include +#include +#include +#include +#include #include #include +#include +#include #include #include #include @@ -85,9 +98,22 @@ using namespace DataEnvironment; using namespace EnergyPlus::DataGlobals; using namespace EnergyPlus::DataPlant; using namespace EnergyPlus::DataSizing; +using namespace EnergyPlus::DataHeatBalance; +using namespace EnergyPlus::DataHeatBalFanSys; using namespace EnergyPlus::DataHVACGlobals; +using namespace EnergyPlus::DataLoopNode; +using namespace EnergyPlus::DataZoneEnergyDemands; +using namespace EnergyPlus::DataZoneEquipment; +using namespace EnergyPlus::FanCoilUnits; +using namespace EnergyPlus::Fans; using namespace EnergyPlus::FluidProperties; +using namespace EnergyPlus::General; +using namespace EnergyPlus::GlobalNames; +using namespace EnergyPlus::HeatBalanceManager; +using namespace EnergyPlus::MixedAir; using namespace EnergyPlus::Psychrometrics; +using namespace EnergyPlus::ReportSizingManager; +using namespace EnergyPlus::ScheduleManager; using namespace EnergyPlus::SizingManager; using namespace EnergyPlus::WaterCoils; using namespace EnergyPlus::Psychrometrics; @@ -360,8 +386,8 @@ TEST_F(WaterCoilsTest, WaterCoolingCoilSizing) ZoneEqSizing(1).HeatingAirFlow = true; ZoneEqSizing(1).HeatingAirVolFlow = 0.1; FinalZoneSizing(1).DesHeatMassFlow = StdRhoAir * ZoneEqSizing(1).HeatingAirVolFlow; - MySizeFlag.allocate(1); - MySizeFlag(CoilNum) = true; + WaterCoils::MySizeFlag.allocate(1); + WaterCoils::MySizeFlag(CoilNum) = true; MyUAAndFlowCalcFlag.allocate(1); MyUAAndFlowCalcFlag(CoilNum) = true; @@ -465,8 +491,8 @@ TEST_F(WaterCoilsTest, CoilHeatingWaterUASizing) MyUAAndFlowCalcFlag.allocate(1); MyUAAndFlowCalcFlag(1) = true; - MySizeFlag.allocate(1); - MySizeFlag(1) = true; + WaterCoils::MySizeFlag.allocate(1); + WaterCoils::MySizeFlag(1) = true; // run water coil sizing createCoilSelectionReportObj(); @@ -538,7 +564,7 @@ TEST_F(WaterCoilsTest, CoilHeatingWaterUASizing) FinalZoneSizing(CurZoneEqNum).ZoneHumRatAtHeatPeak = 0.008; TermUnitFinalZoneSizing(CurTermUnitSizingNum) = FinalZoneSizing(CurZoneEqNum); - MySizeFlag(1) = true; + WaterCoils::MySizeFlag(1) = true; // run water coil sizing SizeWaterCoil(state, CoilNum); @@ -617,8 +643,8 @@ TEST_F(WaterCoilsTest, CoilHeatingWaterLowAirFlowUASizing) MyUAAndFlowCalcFlag.allocate(1); MyUAAndFlowCalcFlag(1) = true; - MySizeFlag.allocate(1); - MySizeFlag(1) = true; + WaterCoils::MySizeFlag.allocate(1); + WaterCoils::MySizeFlag(1) = true; // run water coil sizing createCoilSelectionReportObj(); @@ -691,7 +717,7 @@ TEST_F(WaterCoilsTest, CoilHeatingWaterLowAirFlowUASizing) FinalZoneSizing(CurZoneEqNum).ZoneHumRatAtHeatPeak = 0.008; TermUnitFinalZoneSizing(CurTermUnitSizingNum) = FinalZoneSizing(CurZoneEqNum); - MySizeFlag(1) = true; + WaterCoils::MySizeFlag(1) = true; // run water coil sizing SizeWaterCoil(state, CoilNum); @@ -774,8 +800,8 @@ TEST_F(WaterCoilsTest, CoilHeatingWaterUASizingLowHwaterInletTemp) MyUAAndFlowCalcFlag.allocate(1); MyUAAndFlowCalcFlag(1) = true; - MySizeFlag.allocate(1); - MySizeFlag(1) = true; + WaterCoils::MySizeFlag.allocate(1); + WaterCoils::MySizeFlag(1) = true; // run water coil sizing createCoilSelectionReportObj(); @@ -861,7 +887,7 @@ TEST_F(WaterCoilsTest, CoilCoolingWaterSimpleSizing) WaterCoil(CoilNum).Name = "Test Simple Water Cooling Coil"; WaterCoil(CoilNum).WaterLoopNum = 1; WaterCoil(CoilNum).WaterCoilType = CoilType_Cooling; - WaterCoil(CoilNum).WaterCoilType_Num = WaterCoil_Cooling; // Coil:Cooling:Water + WaterCoil(CoilNum).WaterCoilType_Num = WaterCoils::WaterCoil_Cooling; // Coil:Cooling:Water WaterCoil(CoilNum).WaterCoilModel = CoilModel_Cooling; WaterCoil(CoilNum).RequestingAutoSize = true; @@ -1201,8 +1227,8 @@ TEST_F(WaterCoilsTest, HotWaterHeatingCoilAutoSizeTempTest) MyUAAndFlowCalcFlag.allocate(1); MyUAAndFlowCalcFlag(1) = true; - MySizeFlag.allocate(1); - MySizeFlag(1) = true; + WaterCoils::MySizeFlag.allocate(1); + WaterCoils::MySizeFlag(1) = true; // run water coil sizing SizeWaterCoil(state, CoilNum); @@ -1231,3 +1257,349 @@ TEST_F(WaterCoilsTest, HotWaterHeatingCoilAutoSizeTempTest) // check heating coil design water flow rate calculated here and sizing results are identical EXPECT_DOUBLE_EQ(DesWaterFlowRate, WaterCoil(CoilNum).MaxWaterVolFlowRate); } + +TEST_F(WaterCoilsTest, FanCoilCoolingWaterFlowTest) +{ + PlantSizData.allocate(2); + NumPltSizInput = 2; + + PlantSizData(2).PlantLoopName = "ChilledWaterLoop"; + PlantSizData(2).ExitTemp = 7.22; // chilled water coil inlet water temp + PlantSizData(2).DeltaT = 6.67; + PlantSizData(1).PlantLoopName = "HotWaterLoop"; + PlantSizData(1).ExitTemp = 60; // hot water coil inlet water temp + PlantSizData(1).DeltaT = 12; + int FanCoilNum(1); + int ZoneNum(1); + int ControlledZoneNum(1); + bool FirstHVACIteration(true); + bool ErrorsFound(false); + Real64 QZnReq(0.0); + Real64 HotWaterMassFlowRate(0.0); + Real64 ColdWaterMassFlowRate(0.0); + Real64 QUnitOut(0.0); + Real64 AirMassFlow(0.0); + Real64 MaxAirMassFlow(0.0); + Real64 LatOutputProvided(0.0); + + DataEnvironment::OutBaroPress = 101325.0; + DataEnvironment::StdRhoAir = 1.20; + WaterCoils::GetWaterCoilsInputFlag = true; + NumCoils = 0; + DataGlobals::NumOfTimeStepInHour = 1; + DataGlobals::TimeStep = 1; + DataGlobals::MinutesPerTimeStep = 60; + + InitializePsychRoutines(); + + std::string const idf_objects = delimited_string({ + " Zone,", + " EAST ZONE, !- Name", + " 0, !- Direction of Relative North { deg }", + " 0, !- X Origin { m }", + " 0, !- Y Origin { m }", + " 0, !- Z Origin { m }", + " 1, !- Type", + " 1, !- Multiplier", + " autocalculate, !- Ceiling Height { m }", + " autocalculate; !- Volume { m3 }", + " ZoneHVAC:EquipmentConnections,", + " EAST ZONE, !- Zone Name", + " Zone1Equipment, !- Zone Conditioning Equipment List Name", + " Zone1Inlets, !- Zone Air Inlet Node or NodeList Name", + " Zone1Exhausts, !- Zone Air Exhaust Node or NodeList Name", + " Zone 1 Node, !- Zone Air Node Name", + " Zone 1 Outlet Node; !- Zone Return Air Node Name", + " ZoneHVAC:EquipmentList,", + " Zone1Equipment, !- Name", + " SequentialLoad, !- Load Distribution Scheme", + " ZoneHVAC:FourPipeFanCoil, !- Zone Equipment 1 Object Type", + " Zone1FanCoil, !- Zone Equipment 1 Name", + " 1, !- Zone Equipment 1 Cooling Sequence", + " 1; !- Zone Equipment 1 Heating or No - Load Sequence", + " NodeList,", + " Zone1Inlets, !- Name", + " Zone1FanCoilAirOutletNode; !- Node 1 Name", + " NodeList,", + " Zone1Exhausts, !- Name", + " Zone1FanCoilAirInletNode; !- Node 1 Name", + " OutdoorAir:NodeList,", + " Zone1FanCoilOAInNode; !- Node or NodeList Name 1", + " OutdoorAir:Mixer,", + " Zone1FanCoilOAMixer, !- Name", + " Zone1FanCoilOAMixerOutletNode, !- Mixed Air Node Name", + " Zone1FanCoilOAInNode, !- Outdoor Air Stream Node Name", + " Zone1FanCoilExhNode, !- Relief Air Stream Node Name", + " Zone1FanCoilAirInletNode; !- Return Air Stream Node Name", + " Schedule:Compact,", + " FanAndCoilAvailSched, !- Name", + " Fraction, !- Schedule Type Limits Name", + " Through: 12/31, !- Field 1", + " For: AllDays, !- Field 2", + " Until: 24:00, 1.0; !- Field 3", + " ScheduleTypeLimits,", + " Fraction, !- Name", + " 0.0, !- Lower Limit Value", + " 1.0, !- Upper Limit Value", + " CONTINUOUS; !- Numeric Type", + " Fan:OnOff,", + " Zone1FanCoilFan, !- Name", + " FanAndCoilAvailSched, !- Availability Schedule Name", + " 0.5, !- Fan Total Efficiency", + " 75.0, !- Pressure Rise { Pa }", + " Autosize, !- Maximum Flow Rate { m3 / s }", + " 0.9, !- Motor Efficiency", + " 1.0, !- Motor In Airstream Fraction", + " Zone1FanCoilOAMixerOutletNode, !- Air Inlet Node Name", + " Zone1FanCoilFanOutletNode, !- Air Outlet Node Name", + " , !- Fan Power Ratio Function of Speed Ratio Curve Name", + " ; !- Fan Efficiency Ratio Function of Speed Ratio Curve Name ", + " Coil:Cooling:Water,", + " Zone1FanCoilCoolingCoil, !- Name", + " FanAndCoilAvailSched, !- Availability Schedule Namev", + " Autosize, !- Design Water Flow Rate { m3 / s }", + " Autosize, !- Design Air Flow Rate { m3 / s }", + " 7.22, !- Design Inlet Water Temperature { Cv }", + " 24.340, !- Design Inlet Air Temperature { C }", + " 14.000, !- Design Outlet Air Temperature { C }", + " 0.0095, !- Design Inlet Air Humidity Ratio { kgWater / kgDryAir }", + " 0.0090, !- Design Outlet Air Humidity Ratio { kgWater / kgDryAir }", + " Zone1FanCoilChWInletNode, !- Water Inlet Node Name", + " Zone1FanCoilChWOutletNode, !- Water Outlet Node Name", + " Zone1FanCoilFanOutletNode, !- Air Inlet Node Name", + " Zone1FanCoilCCOutletNode, !- Air Outlet Node Name", + " SimpleAnalysis, !- Type of Analysis", + " CrossFlow; !- Heat Exchanger Configuration", + " Coil:Heating:Water,", + " Zone1FanCoilHeatingCoil, !- Name", + " FanAndCoilAvailSched, !- Availability Schedule Name", + " 150.0, !- U - Factor Times Area Value { W / K }", + " Autosize, !- Maximum Water Flow Rate { m3 / s }", + " Zone1FanCoilHWInletNode, !- Water Inlet Node Name", + " Zone1FanCoilHWOutletNode, !- Water Outlet Node Name", + " Zone1FanCoilCCOutletNode, !- Air Inlet Node Name", + " Zone1FanCoilAirOutletNode, !- Air Outlet Node Name", + " UFactorTimesAreaAndDesignWaterFlowRate, !- Performance Input Method", + " autosize, !- Rated Capacity { W }", + " 82.2, !- Rated Inlet Water Temperature { C }", + " 16.6, !- Rated Inlet Air Temperature { C }", + " 71.1, !- Rated Outlet Water Temperature { C }", + " 32.2, !- Rated Outlet Air Temperature { C }", + " ; !- Rated Ratio for Air and Water Convection", + " ZoneHVAC:FourPipeFanCoil,", + " Zone1FanCoil, !- Name", + " FanAndCoilAvailSched, !- Availability Schedule Name", + " ConstantFanVariableFlow, !- Capacity Control Method", + " 0.5, !- Maximum Supply Air Flow Rate { m3 / s }", + " 0.3, !- Low Speed Supply Air Flow Ratio", + " 0.6, !- Medium Speed Supply Air Flow Ratio", + " 0.1, !- Maximum Outdoor Air Flow Rate { m3 / s }", + " FanAndCoilAvailSched, !- Outdoor Air Schedule Name", + " Zone1FanCoilAirInletNode, !- Air Inlet Node Name", + " Zone1FanCoilAirOutletNode, !- Air Outlet Node Name", + " OutdoorAir:Mixer, !- Outdoor Air Mixer Object Type", + " Zone1FanCoilOAMixer, !- Outdoor Air Mixer Name", + " Fan:OnOff, !- Supply Air Fan Object Type", + " Zone1FanCoilFan, !- Supply Air Fan Name", + " Coil:Cooling:Water, !- Cooling Coil Object Type", + " Zone1FanCoilCoolingCoil, !- Cooling Coil Name", + " 0.0002, !- Maximum Cold Water Flow Rate { m3 / s }", + " 0.0, !- Minimum Cold Water Flow Rate { m3 / s }", + " 0.001, !- Cooling Convergence Tolerance", + " Coil:Heating:Water, !- Heating Coil Object Type", + " Zone1FanCoilHeatingCoil, !- Heating Coil Name", + " 0.0002, !- Maximum Hot Water Flow Rate { m3 / s }", + " 0.0, !- Minimum Hot Water Flow Rate { m3 / s }", + " 0.001; !- Heating Convergence Tolerance", + + }); + + ASSERT_TRUE(process_idf(idf_objects)); + + GetZoneData(ErrorsFound); + EXPECT_EQ("EAST ZONE", Zone(1).Name); + + GetZoneEquipmentData1(state); + ProcessScheduleInput(state.files); + ScheduleInputProcessed = true; + GetFanInput(state); + EXPECT_EQ(DataHVACGlobals::FanType_SimpleOnOff, Fan(1).FanType_Num); + + GetFanCoilUnits(state); + EXPECT_EQ("CONSTANTFANVARIABLEFLOW", FanCoil(1).CapCtrlMeth); + EXPECT_EQ("OUTDOORAIR:MIXER", FanCoil(1).OAMixType); + EXPECT_EQ("FAN:ONOFF", FanCoil(1).FanType); + EXPECT_EQ("COIL:COOLING:WATER", FanCoil(1).CCoilType); + EXPECT_EQ("COIL:HEATING:WATER", FanCoil(1).HCoilType); + + TotNumLoops = 2; + PlantLoop.allocate(TotNumLoops); + + AirMassFlow = 0.60; + MaxAirMassFlow = 0.60; + + // cooling load only + HotWaterMassFlowRate = 0.0; + ColdWaterMassFlowRate = 0.14; + + Node(OAMixer(1).RetNode).MassFlowRate = AirMassFlow; + Node(OAMixer(1).RetNode).MassFlowRateMax = MaxAirMassFlow; + + Node(OAMixer(1).RetNode).Temp = 24.0; + Node(OAMixer(1).RetNode).Enthalpy = 36000; + Node(OAMixer(1).RetNode).HumRat = PsyWFnTdbH(Node(OAMixer(1).RetNode).Temp, Node(OAMixer(1).RetNode).Enthalpy); + + Node(OAMixer(1).InletNode).Temp = 30.0; + Node(OAMixer(1).InletNode).Enthalpy = 53000; + Node(OAMixer(1).InletNode).HumRat = PsyWFnTdbH(Node(OAMixer(1).InletNode).Temp, Node(OAMixer(1).InletNode).Enthalpy); + + Node(FanCoil(1).AirInNode).MassFlowRate = AirMassFlow; + Node(FanCoil(1).AirInNode).MassFlowRateMin = AirMassFlow; + Node(FanCoil(1).AirInNode).MassFlowRateMinAvail = AirMassFlow; + Node(FanCoil(1).AirInNode).MassFlowRateMax = MaxAirMassFlow; + Node(FanCoil(1).AirInNode).MassFlowRateMaxAvail = MaxAirMassFlow; + + FanCoil(1).OutAirMassFlow = 0.0; + FanCoil(1).MaxAirMassFlow = MaxAirMassFlow; + FanCoil(1).MaxCoolCoilFluidFlow = 0.14; + FanCoil(1).MaxHeatCoilFluidFlow = 0.14; + + Node(FanCoil(1).OutsideAirNode).MassFlowRateMax = 0.0; + Node(FanCoil(1).CoolCoilFluidInletNode).MassFlowRateMax = 0.14; + Node(FanCoil(1).HeatCoilFluidInletNode).MassFlowRateMax = 0.14; + Node(FanCoil(1).CoolCoilFluidInletNode).MassFlowRateMaxAvail = 0.14; + Node(FanCoil(1).HeatCoilFluidInletNode).MassFlowRateMaxAvail = 0.14; + + Fan(1).InletAirMassFlowRate = AirMassFlow; + Fan(1).MaxAirMassFlowRate = MaxAirMassFlow; + + Node(Fan(1).InletNodeNum).MassFlowRate = AirMassFlow; + Node(Fan(1).InletNodeNum).MassFlowRateMin = AirMassFlow; + Node(Fan(1).InletNodeNum).MassFlowRateMax = AirMassFlow; + Node(Fan(1).InletNodeNum).MassFlowRateMaxAvail = AirMassFlow; + + WaterCoil(2).UACoilTotal = 470.0; + WaterCoil(2).UACoilExternal = 611.0; + WaterCoil(2).UACoilInternal = 2010.0; + WaterCoil(2).TotCoilOutsideSurfArea = 50.0; + + Node(WaterCoil(2).AirInletNodeNum).MassFlowRate = AirMassFlow; + Node(WaterCoil(2).AirInletNodeNum).MassFlowRateMin = AirMassFlow; + Node(WaterCoil(2).AirInletNodeNum).MassFlowRateMax = AirMassFlow; + Node(WaterCoil(2).AirInletNodeNum).MassFlowRateMaxAvail = AirMassFlow; + + WaterCoil(2).InletWaterMassFlowRate = ColdWaterMassFlowRate; + WaterCoil(2).MaxWaterMassFlowRate = ColdWaterMassFlowRate; + Node(WaterCoil(2).WaterInletNodeNum).MassFlowRate = ColdWaterMassFlowRate; + Node(WaterCoil(2).WaterInletNodeNum).MassFlowRateMaxAvail = ColdWaterMassFlowRate; + Node(WaterCoil(2).WaterInletNodeNum).Temp = 6.0; + Node(WaterCoil(2).WaterOutletNodeNum).MassFlowRate = ColdWaterMassFlowRate; + Node(WaterCoil(2).WaterOutletNodeNum).MassFlowRateMaxAvail = ColdWaterMassFlowRate; + + Node(WaterCoil(1).AirInletNodeNum).MassFlowRate = AirMassFlow; + Node(WaterCoil(1).AirInletNodeNum).MassFlowRateMaxAvail = AirMassFlow; + + Node(WaterCoil(1).WaterInletNodeNum).Temp = 60.0; + Node(WaterCoil(1).WaterInletNodeNum).MassFlowRate = HotWaterMassFlowRate; + Node(WaterCoil(1).WaterInletNodeNum).MassFlowRateMaxAvail = HotWaterMassFlowRate; + Node(WaterCoil(1).WaterOutletNodeNum).MassFlowRate = HotWaterMassFlowRate; + Node(WaterCoil(1).WaterOutletNodeNum).MassFlowRateMaxAvail = HotWaterMassFlowRate; + WaterCoil(1).InletWaterMassFlowRate = HotWaterMassFlowRate; + WaterCoil(1).MaxWaterMassFlowRate = HotWaterMassFlowRate; + + for (int l = 1; l <= TotNumLoops; ++l) { + auto &loop(PlantLoop(l)); + loop.LoopSide.allocate(2); + auto &loopside(PlantLoop(l).LoopSide(1)); + loopside.TotalBranches = 1; + loopside.Branch.allocate(1); + auto &loopsidebranch(PlantLoop(l).LoopSide(1).Branch(1)); + loopsidebranch.TotalComponents = 1; + loopsidebranch.Comp.allocate(1); + } + + DataHeatBalFanSys::TempControlType.allocate(1); + DataHeatBalFanSys::TempControlType(1) = 4; + + WaterCoil(2).WaterLoopNum = 1; + WaterCoil(2).WaterLoopSide = 1; + WaterCoil(2).WaterLoopBranchNum = 1; + WaterCoil(2).WaterLoopCompNum = 1; + + WaterCoil(1).WaterLoopNum = 2; + WaterCoil(1).WaterLoopSide = 1; + WaterCoil(1).WaterLoopBranchNum = 1; + WaterCoil(1).WaterLoopCompNum = 1; + + PlantLoop(2).Name = "ChilledWaterLoop"; + PlantLoop(2).FluidName = "ChilledWater"; + PlantLoop(2).FluidIndex = 1; + PlantLoop(2).FluidName = "WATER"; + PlantLoop(2).LoopSide(1).Branch(1).Comp(1).Name = WaterCoil(2).Name; + PlantLoop(2).LoopSide(1).Branch(1).Comp(1).TypeOf_Num = WaterCoils::WaterCoil_Cooling; + PlantLoop(2).LoopSide(1).Branch(1).Comp(1).NodeNumIn = WaterCoil(2).WaterInletNodeNum; + PlantLoop(2).LoopSide(1).Branch(1).Comp(1).NodeNumOut = WaterCoil(2).WaterOutletNodeNum; + PlantLoop(2).LoopSide(1).FlowLock = 0; + + PlantLoop(1).Name = "HotWaterLoop"; + PlantLoop(1).FluidName = "HotWater"; + PlantLoop(1).FluidIndex = 1; + PlantLoop(1).FluidName = "WATER"; + PlantLoop(1).LoopSide(1).Branch(1).Comp(1).Name = WaterCoil(1).Name; + PlantLoop(1).LoopSide(1).Branch(1).Comp(1).TypeOf_Num = WaterCoil_SimpleHeating; + PlantLoop(1).LoopSide(1).Branch(1).Comp(1).NodeNumIn = WaterCoil(1).WaterInletNodeNum; + PlantLoop(1).LoopSide(1).Branch(1).Comp(1).NodeNumOut = WaterCoil(1).WaterOutletNodeNum; + PlantLoop(1).LoopSide(1).FlowLock = 0; + + FanCoil(1).CoolCoilLoopNum = 2; + FanCoil(1).HeatCoilLoopNum = 1; + FanCoil(1).CoolCoilLoopSide = 1; + FanCoil(1).HeatCoilLoopSide = 1; + FanCoil(1).HeatCoilFluidOutletNodeNum = WaterCoil(1).WaterOutletNodeNum; + FanCoil(1).CoolCoilFluidOutletNodeNum = WaterCoil(2).WaterOutletNodeNum; + FanCoil(1).CoolCoilBranchNum = 1; + FanCoil(1).CoolCoilCompNum = 1; + FanCoil(1).HeatCoilBranchNum = 1; + FanCoil(1).HeatCoilCompNum = 1; + + HeatingLoad = false; + CoolingLoad = true; + ZoneSysEnergyDemand.allocate(1); + ZoneSysEnergyDemand(1).RemainingOutputReqToCoolSP = -4000.00; + ZoneSysEnergyDemand(1).RemainingOutputReqToHeatSP = -8000.0; + FanCoil(1).SpeedFanSel = 2; + QUnitOut = 0.0; + QZnReq = -4000.0; + + DataGlobals::DoingSizing = true; + + CurZoneEqNum = 1; + ZoneSizingRunDone = true; + DataSizing::ZoneEqSizing.allocate(CurZoneEqNum); + DataSizing::ZoneEqSizing(DataSizing::CurZoneEqNum).SizingMethod.allocate(25); + DataSizing::ZoneEqSizing(CurZoneEqNum).SizingMethod(25) = 0; + ZoneEqFanCoil = true; + ZoneEqSizing(CurZoneEqNum).DesignSizeFromParent = true; + + // User-specified air volume flow rate from the ZoneHVAC:FourPipeFanCoil object + DataSizing::ZoneEqSizing(CurZoneEqNum).AirVolFlow = 0.5; + // User-specified water flow rate from the ZoneHVAC:FourPipeFanCoil object + DataSizing::ZoneEqSizing(CurZoneEqNum).MaxCWVolFlow = 0.0002; + // User-specified water flow rate from the ZoneHVAC:FourPipeFanCoil object + DataSizing::ZoneEqSizing(CurZoneEqNum).MaxHWVolFlow = 0.0002; + + // Initial design air volume flow rate based on the design conditions + WaterCoil(2).DesAirVolFlowRate = DataSizing::AutoSize; + // Initial design water flow rate based on the design conditions + WaterCoil(2).MaxWaterVolFlowRate = DataSizing::AutoSize; + + // normal cooling simulation for constant fan variable flow fan coil + Sim4PipeFanCoil(state, FanCoilNum, ZoneNum, ControlledZoneNum, FirstHVACIteration, QUnitOut, LatOutputProvided); + + // Expect final design air volume flow rate to equal the user-specified air volume flow rate from the ZoneHVAC:FourPipeFanCoil object + EXPECT_EQ(WaterCoil(2).DesAirVolFlowRate, 0.5); + // Expect final design water flow rate to equal the user-specified water flow rate from the ZoneHVAC:FourPipeFanCoil object + EXPECT_EQ(WaterCoil(2).MaxWaterVolFlowRate, 0.0002); + + +} \ No newline at end of file