From 6bf19d9310ee096caf38aa0492cc43f65543bd53 Mon Sep 17 00:00:00 2001 From: rraustad Date: Thu, 7 Nov 2024 11:42:48 -0500 Subject: [PATCH 1/5] Correct crash in DOAS fan sizing --- .../Autosizing/SystemAirFlowSizing.cc | 132 ++++++++++-------- 1 file changed, 74 insertions(+), 58 deletions(-) diff --git a/src/EnergyPlus/Autosizing/SystemAirFlowSizing.cc b/src/EnergyPlus/Autosizing/SystemAirFlowSizing.cc index 21208557a57..fc1a6dcdb84 100644 --- a/src/EnergyPlus/Autosizing/SystemAirFlowSizing.cc +++ b/src/EnergyPlus/Autosizing/SystemAirFlowSizing.cc @@ -777,24 +777,63 @@ Real64 SystemAirFlowSizer::size(EnergyPlusData &state, Real64 _originalValue, bo } } else { - auto &sysSizPeakDDNum = state.dataSize->SysSizPeakDDNum(this->curSysNum); + if (this->curOASysNum > 0) { + if (this->oaSysEqSizing(this->curOASysNum).AirFlow) { + // Parent object sets system flow rate + this->autoSizedValue = this->oaSysEqSizing(this->curOASysNum).AirVolFlow; + } else if (this->oaSysEqSizing(this->curOASysNum).CoolingAirFlow || this->oaSysEqSizing(this->curOASysNum).HeatingAirFlow) { + // Parent object sets heating flow rate + this->autoSizedValue = std::max(this->oaSysEqSizing(this->curOASysNum).CoolingAirVolFlow, + this->oaSysEqSizing(this->curOASysNum).HeatingAirVolFlow); + } else if (outsideAirSys(this->curOASysNum).AirLoopDOASNum > -1) { + this->autoSizedValue = + this->airloopDOAS[outsideAirSys(this->curOASysNum).AirLoopDOASNum].SizingMassFlow / state.dataEnvrn->StdRhoAir; + } else { + this->autoSizedValue = this->finalSysSizing(this->curSysNum).DesOutAirVolFlow; + } + } else { + auto &sysSizPeakDDNum = state.dataSize->SysSizPeakDDNum(this->curSysNum); + + if (this->airLoopSysFlag) { + auto const &unitarysysEqSizing = this->unitarySysEqSizing(this->curSysNum); + if (unitarysysEqSizing.CoolingAirFlow && unitarysysEqSizing.HeatingAirFlow) { + this->autoSizedValue = std::max(unitarysysEqSizing.CoolingAirVolFlow, unitarysysEqSizing.HeatingAirVolFlow); + if (this->autoSizedValue == unitarysysEqSizing.CoolingAirVolFlow) { + if (sysSizPeakDDNum.CoolFlowPeakDD > 0 && sysSizPeakDDNum.CoolFlowPeakDD <= state.dataEnvrn->TotDesDays) { + auto &desDayInput = state.dataWeather->DesDayInput(sysSizPeakDDNum.CoolFlowPeakDD); + DDNameFanPeak = desDayInput.Title; + dateTimeFanPeak = format("{}/{} {}", + desDayInput.Month, + desDayInput.DayOfMonth, + state.dataRptCoilSelection->coilSelectionReportObj->getTimeText( + state, sysSizPeakDDNum.TimeStepAtCoolFlowPk(sysSizPeakDDNum.CoolFlowPeakDD))); + } - if (this->airLoopSysFlag) { - auto const &unitarysysEqSizing = this->unitarySysEqSizing(this->curSysNum); - if (unitarysysEqSizing.CoolingAirFlow && unitarysysEqSizing.HeatingAirFlow) { - this->autoSizedValue = std::max(unitarysysEqSizing.CoolingAirVolFlow, unitarysysEqSizing.HeatingAirVolFlow); - if (this->autoSizedValue == unitarysysEqSizing.CoolingAirVolFlow) { + } else if (this->autoSizedValue == unitarysysEqSizing.HeatingAirVolFlow) { + if (this->finalSysSizing(this->curSysNum).HeatDDNum > 0 && + this->finalSysSizing(this->curSysNum).HeatDDNum <= state.dataEnvrn->TotDesDays) { + auto &desDayInput = state.dataWeather->DesDayInput(this->finalSysSizing(this->curSysNum).HeatDDNum); + DDNameFanPeak = desDayInput.Title; + dateTimeFanPeak = format("{}/{} {}", + desDayInput.Month, + desDayInput.DayOfMonth, + state.dataRptCoilSelection->coilSelectionReportObj->getTimeText( + state, this->finalSysSizing(this->curSysNum).SysHeatAirTimeStepPk)); + } + } + } else if (unitarysysEqSizing.CoolingAirFlow) { + this->autoSizedValue = unitarysysEqSizing.CoolingAirVolFlow; if (sysSizPeakDDNum.CoolFlowPeakDD > 0 && sysSizPeakDDNum.CoolFlowPeakDD <= state.dataEnvrn->TotDesDays) { auto &desDayInput = state.dataWeather->DesDayInput(sysSizPeakDDNum.CoolFlowPeakDD); - DDNameFanPeak = desDayInput.Title; + DDNameFanPeak = state.dataWeather->DesDayInput(sysSizPeakDDNum.CoolFlowPeakDD).Title; dateTimeFanPeak = format("{}/{} {}", desDayInput.Month, desDayInput.DayOfMonth, state.dataRptCoilSelection->coilSelectionReportObj->getTimeText( state, sysSizPeakDDNum.TimeStepAtCoolFlowPk(sysSizPeakDDNum.CoolFlowPeakDD))); } - - } else if (this->autoSizedValue == unitarysysEqSizing.HeatingAirVolFlow) { + } else if (unitarysysEqSizing.HeatingAirFlow) { + this->autoSizedValue = unitarysysEqSizing.HeatingAirVolFlow; if (this->finalSysSizing(this->curSysNum).HeatDDNum > 0 && this->finalSysSizing(this->curSysNum).HeatDDNum <= state.dataEnvrn->TotDesDays) { auto &desDayInput = state.dataWeather->DesDayInput(this->finalSysSizing(this->curSysNum).HeatDDNum); @@ -805,31 +844,32 @@ Real64 SystemAirFlowSizer::size(EnergyPlusData &state, Real64 _originalValue, bo state.dataRptCoilSelection->coilSelectionReportObj->getTimeText( state, this->finalSysSizing(this->curSysNum).SysHeatAirTimeStepPk)); } - } - } else if (unitarysysEqSizing.CoolingAirFlow) { - this->autoSizedValue = unitarysysEqSizing.CoolingAirVolFlow; - if (sysSizPeakDDNum.CoolFlowPeakDD > 0 && sysSizPeakDDNum.CoolFlowPeakDD <= state.dataEnvrn->TotDesDays) { - auto &desDayInput = state.dataWeather->DesDayInput(sysSizPeakDDNum.CoolFlowPeakDD); - DDNameFanPeak = state.dataWeather->DesDayInput(sysSizPeakDDNum.CoolFlowPeakDD).Title; - dateTimeFanPeak = format("{}/{} {}", - desDayInput.Month, - desDayInput.DayOfMonth, - state.dataRptCoilSelection->coilSelectionReportObj->getTimeText( - state, sysSizPeakDDNum.TimeStepAtCoolFlowPk(sysSizPeakDDNum.CoolFlowPeakDD))); - } - } else if (unitarysysEqSizing.HeatingAirFlow) { - this->autoSizedValue = unitarysysEqSizing.HeatingAirVolFlow; - if (this->finalSysSizing(this->curSysNum).HeatDDNum > 0 && - this->finalSysSizing(this->curSysNum).HeatDDNum <= state.dataEnvrn->TotDesDays) { - auto &desDayInput = state.dataWeather->DesDayInput(this->finalSysSizing(this->curSysNum).HeatDDNum); - DDNameFanPeak = desDayInput.Title; - dateTimeFanPeak = format("{}/{} {}", - desDayInput.Month, - desDayInput.DayOfMonth, - state.dataRptCoilSelection->coilSelectionReportObj->getTimeText( - state, this->finalSysSizing(this->curSysNum).SysHeatAirTimeStepPk)); - } + } else { + this->autoSizedValue = this->finalSysSizing(this->curSysNum).DesMainVolFlow; + if (this->autoSizedValue == this->finalSysSizing(this->curSysNum).DesHeatVolFlow) { + if (this->finalSysSizing(this->curSysNum).HeatDDNum > 0 && + this->finalSysSizing(this->curSysNum).HeatDDNum <= state.dataEnvrn->TotDesDays) { + auto &desDayInput = state.dataWeather->DesDayInput(this->finalSysSizing(this->curSysNum).HeatDDNum); + DDNameFanPeak = desDayInput.Title; + dateTimeFanPeak = format("{}/{} {}", + desDayInput.Month, + desDayInput.DayOfMonth, + state.dataRptCoilSelection->coilSelectionReportObj->getTimeText( + state, this->finalSysSizing(this->curSysNum).SysHeatAirTimeStepPk)); + } + } else if (this->autoSizedValue == this->finalSysSizing(this->curSysNum).DesCoolVolFlow) { + if (sysSizPeakDDNum.CoolFlowPeakDD > 0 && sysSizPeakDDNum.CoolFlowPeakDD <= state.dataEnvrn->TotDesDays) { + auto &desDayInput = state.dataWeather->DesDayInput(sysSizPeakDDNum.CoolFlowPeakDD); + DDNameFanPeak = desDayInput.Title; + dateTimeFanPeak = format("{}/{} {}", + desDayInput.Month, + desDayInput.DayOfMonth, + state.dataRptCoilSelection->coilSelectionReportObj->getTimeText( + state, sysSizPeakDDNum.TimeStepAtCoolFlowPk(sysSizPeakDDNum.CoolFlowPeakDD))); + } + } + } } else { this->autoSizedValue = this->finalSysSizing(this->curSysNum).DesMainVolFlow; if (this->autoSizedValue == this->finalSysSizing(this->curSysNum).DesHeatVolFlow) { @@ -855,32 +895,8 @@ Real64 SystemAirFlowSizer::size(EnergyPlusData &state, Real64 _originalValue, bo } } } - } else { - this->autoSizedValue = this->finalSysSizing(this->curSysNum).DesMainVolFlow; - if (this->autoSizedValue == this->finalSysSizing(this->curSysNum).DesHeatVolFlow) { - if (this->finalSysSizing(this->curSysNum).HeatDDNum > 0 && - this->finalSysSizing(this->curSysNum).HeatDDNum <= state.dataEnvrn->TotDesDays) { - auto &desDayInput = state.dataWeather->DesDayInput(this->finalSysSizing(this->curSysNum).HeatDDNum); - DDNameFanPeak = desDayInput.Title; - dateTimeFanPeak = format("{}/{} {}", - desDayInput.Month, - desDayInput.DayOfMonth, - state.dataRptCoilSelection->coilSelectionReportObj->getTimeText( - state, this->finalSysSizing(this->curSysNum).SysHeatAirTimeStepPk)); - } - } else if (this->autoSizedValue == this->finalSysSizing(this->curSysNum).DesCoolVolFlow) { - if (sysSizPeakDDNum.CoolFlowPeakDD > 0 && sysSizPeakDDNum.CoolFlowPeakDD <= state.dataEnvrn->TotDesDays) { - auto &desDayInput = state.dataWeather->DesDayInput(sysSizPeakDDNum.CoolFlowPeakDD); - DDNameFanPeak = desDayInput.Title; - dateTimeFanPeak = format("{}/{} {}", - desDayInput.Month, - desDayInput.DayOfMonth, - state.dataRptCoilSelection->coilSelectionReportObj->getTimeText( - state, sysSizPeakDDNum.TimeStepAtCoolFlowPk(sysSizPeakDDNum.CoolFlowPeakDD))); - } - } + if (this->dataFractionUsedForSizing > 0.0) this->autoSizedValue = this->autoSizedValue * this->dataFractionUsedForSizing; } - if (this->dataFractionUsedForSizing > 0.0) this->autoSizedValue = this->autoSizedValue * this->dataFractionUsedForSizing; } } } else if (this->dataNonZoneNonAirloopValue > 0) { From 0d248a018268c782f008f4e17d4abb772f86af56 Mon Sep 17 00:00:00 2001 From: rraustad Date: Thu, 7 Nov 2024 12:23:22 -0500 Subject: [PATCH 2/5] Add unit test --- .../Autosizing/SystemAirFlowSizing.unit.cc | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/tst/EnergyPlus/unit/Autosizing/SystemAirFlowSizing.unit.cc b/tst/EnergyPlus/unit/Autosizing/SystemAirFlowSizing.unit.cc index 2c2441eedca..aa03014ee70 100644 --- a/tst/EnergyPlus/unit/Autosizing/SystemAirFlowSizing.unit.cc +++ b/tst/EnergyPlus/unit/Autosizing/SystemAirFlowSizing.unit.cc @@ -960,6 +960,25 @@ TEST_F(AutoSizingFixture, SystemAirFlowSizingGauntlet) eiooutput = std::string(" Component Sizing Information, Coil:Heating:Water, MyWaterCoil, Design Size Maximum Flow Rate [m3/s], 3.50000\n" " Component Sizing Information, Coil:Heating:Water, MyWaterCoil, User-Specified Maximum Flow Rate [m3/s], 2.20000\n"); EXPECT_TRUE(compare_eio_stream(eiooutput, true)); + + // Test 58 - DOAS fan air flow rate autosizing + state->dataSize->HRFlowSizingFlag = false; + state->dataSize->CurOASysNum = 1; + state->dataAirLoop->OutsideAirSys(1).AirLoopDOASNum = 0; + AirLoopHVACDOAS::AirLoopDOAS thisDOAS; + state->dataAirLoopHVACDOAS->airloopDOAS.push_back(thisDOAS); + // use 0.53 m3/s multiplied by StdRhoAir = 1.2 + state->dataAirLoopHVACDOAS->airloopDOAS[state->dataAirLoop->OutsideAirSys(1).AirLoopDOASNum].SizingMassFlow = 0.53 * 1.2; + inputValue = DataSizing::AutoSize; + + // do sizing + sizer.wasAutoSized = false; + printFlag = true; + sizer.initializeWithinEP(*this->state, "Fan:SystemModel", "MyDOASFan", printFlag, routineName); + sizedValue = sizer.size(*this->state, inputValue, errorsFound); + EXPECT_ENUM_EQ(AutoSizingResultType::NoError, sizer.errorType); // cumulative of previous calls + EXPECT_TRUE(sizer.wasAutoSized); + EXPECT_NEAR(0.53, sizedValue, 0.01); // auto-sized value } } // namespace EnergyPlus From b249e6f62756d0870207d0592b7ab95f080d2296 Mon Sep 17 00:00:00 2001 From: rraustad Date: Fri, 8 Nov 2024 08:52:57 -0500 Subject: [PATCH 3/5] Revise OA system fan sizing methodology --- src/EnergyPlus/AirLoopHVACDOAS.cc | 2 -- src/EnergyPlus/Autosizing/SystemAirFlowSizing.cc | 10 ++-------- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/src/EnergyPlus/AirLoopHVACDOAS.cc b/src/EnergyPlus/AirLoopHVACDOAS.cc index b382733e760..47c86dc7399 100644 --- a/src/EnergyPlus/AirLoopHVACDOAS.cc +++ b/src/EnergyPlus/AirLoopHVACDOAS.cc @@ -994,13 +994,11 @@ namespace AirLoopHVACDOAS { this->GetDesignDayConditions(state); if (this->m_FanIndex > 0 && this->m_FanTypeNum == SimAirServingZones::CompType::Fan_System_Object) { - state.dataFans->fans(this->m_FanIndex)->maxAirFlowRate = sizingMassFlow / state.dataEnvrn->StdRhoAir; state.dataLoopNodes->Node(this->m_FanInletNodeNum).MassFlowRateMaxAvail = sizingMassFlow; state.dataLoopNodes->Node(this->m_FanOutletNodeNum).MassFlowRateMaxAvail = sizingMassFlow; state.dataLoopNodes->Node(this->m_FanOutletNodeNum).MassFlowRateMax = sizingMassFlow; } if (this->m_FanIndex > 0 && this->m_FanTypeNum == SimAirServingZones::CompType::Fan_ComponentModel) { - state.dataFans->fans(this->m_FanIndex)->maxAirFlowRate = sizingMassFlow / state.dataEnvrn->StdRhoAir; state.dataFans->fans(this->m_FanIndex)->minAirFlowRate = 0.0; state.dataFans->fans(this->m_FanIndex)->maxAirMassFlowRate = sizingMassFlow; state.dataLoopNodes->Node(this->m_FanInletNodeNum).MassFlowRateMaxAvail = sizingMassFlow; diff --git a/src/EnergyPlus/Autosizing/SystemAirFlowSizing.cc b/src/EnergyPlus/Autosizing/SystemAirFlowSizing.cc index fc1a6dcdb84..843bcfacd30 100644 --- a/src/EnergyPlus/Autosizing/SystemAirFlowSizing.cc +++ b/src/EnergyPlus/Autosizing/SystemAirFlowSizing.cc @@ -778,14 +778,8 @@ Real64 SystemAirFlowSizer::size(EnergyPlusData &state, Real64 _originalValue, bo } else { if (this->curOASysNum > 0) { - if (this->oaSysEqSizing(this->curOASysNum).AirFlow) { - // Parent object sets system flow rate - this->autoSizedValue = this->oaSysEqSizing(this->curOASysNum).AirVolFlow; - } else if (this->oaSysEqSizing(this->curOASysNum).CoolingAirFlow || this->oaSysEqSizing(this->curOASysNum).HeatingAirFlow) { - // Parent object sets heating flow rate - this->autoSizedValue = std::max(this->oaSysEqSizing(this->curOASysNum).CoolingAirVolFlow, - this->oaSysEqSizing(this->curOASysNum).HeatingAirVolFlow); - } else if (outsideAirSys(this->curOASysNum).AirLoopDOASNum > -1) { + // should a parent object ever override DOAS or OASystem flow rate (e.g., using oaSysEqSizing().AirVolFlow)? + if (outsideAirSys(this->curOASysNum).AirLoopDOASNum > -1) { this->autoSizedValue = this->airloopDOAS[outsideAirSys(this->curOASysNum).AirLoopDOASNum].SizingMassFlow / state.dataEnvrn->StdRhoAir; } else { From 3bf1d387e3b528d8ad4a8934a5f8d87d15a9ee43 Mon Sep 17 00:00:00 2001 From: rraustad Date: Sat, 21 Dec 2024 13:59:52 -0500 Subject: [PATCH 4/5] Use same sizing as OA controller max --- src/EnergyPlus/Autosizing/SystemAirFlowSizing.cc | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/EnergyPlus/Autosizing/SystemAirFlowSizing.cc b/src/EnergyPlus/Autosizing/SystemAirFlowSizing.cc index 843bcfacd30..0cc1866b2fd 100644 --- a/src/EnergyPlus/Autosizing/SystemAirFlowSizing.cc +++ b/src/EnergyPlus/Autosizing/SystemAirFlowSizing.cc @@ -783,7 +783,19 @@ Real64 SystemAirFlowSizer::size(EnergyPlusData &state, Real64 _originalValue, bo this->autoSizedValue = this->airloopDOAS[outsideAirSys(this->curOASysNum).AirLoopDOASNum].SizingMassFlow / state.dataEnvrn->StdRhoAir; } else { - this->autoSizedValue = this->finalSysSizing(this->curSysNum).DesOutAirVolFlow; + switch (this->curDuctType) { + case HVAC::AirDuctType::Cooling: { + this->autoSizedValue = this->finalSysSizing(this->curSysNum).DesCoolVolFlow; + } break; + case HVAC::AirDuctType::Heating: { + this->autoSizedValue = this->finalSysSizing(this->curSysNum).DesHeatVolFlow; + } break; + case HVAC::AirDuctType::Main: + case HVAC::AirDuctType::Other: + default: { + this->autoSizedValue = this->finalSysSizing(this->curSysNum).DesMainVolFlow; + } break; + } } } else { auto &sysSizPeakDDNum = state.dataSize->SysSizPeakDDNum(this->curSysNum); From d357c9f8ebcb06830f584a9fb7e59fa59a241304 Mon Sep 17 00:00:00 2001 From: rraustad Date: Sat, 21 Dec 2024 18:08:12 -0500 Subject: [PATCH 5/5] Add peak timestamp --- .../Autosizing/SystemAirFlowSizing.cc | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/EnergyPlus/Autosizing/SystemAirFlowSizing.cc b/src/EnergyPlus/Autosizing/SystemAirFlowSizing.cc index 0cc1866b2fd..7238efb36e9 100644 --- a/src/EnergyPlus/Autosizing/SystemAirFlowSizing.cc +++ b/src/EnergyPlus/Autosizing/SystemAirFlowSizing.cc @@ -796,6 +796,29 @@ Real64 SystemAirFlowSizer::size(EnergyPlusData &state, Real64 _originalValue, bo this->autoSizedValue = this->finalSysSizing(this->curSysNum).DesMainVolFlow; } break; } + if (this->autoSizedValue == this->finalSysSizing(this->curSysNum).DesHeatVolFlow) { + if (this->finalSysSizing(this->curSysNum).HeatDDNum > 0 && + this->finalSysSizing(this->curSysNum).HeatDDNum <= state.dataEnvrn->TotDesDays) { + auto &desDayInput = state.dataWeather->DesDayInput(this->finalSysSizing(this->curSysNum).HeatDDNum); + DDNameFanPeak = desDayInput.Title; + dateTimeFanPeak = format("{}/{} {}", + desDayInput.Month, + desDayInput.DayOfMonth, + state.dataRptCoilSelection->coilSelectionReportObj->getTimeText( + state, this->finalSysSizing(this->curSysNum).SysHeatAirTimeStepPk)); + } + } else if (this->autoSizedValue == this->finalSysSizing(this->curSysNum).DesCoolVolFlow) { + auto &sysSizPeakDDNum = state.dataSize->SysSizPeakDDNum(this->curSysNum); + if (sysSizPeakDDNum.CoolFlowPeakDD > 0 && sysSizPeakDDNum.CoolFlowPeakDD <= state.dataEnvrn->TotDesDays) { + auto &desDayInput = state.dataWeather->DesDayInput(sysSizPeakDDNum.CoolFlowPeakDD); + DDNameFanPeak = desDayInput.Title; + dateTimeFanPeak = format("{}/{} {}", + desDayInput.Month, + desDayInput.DayOfMonth, + state.dataRptCoilSelection->coilSelectionReportObj->getTimeText( + state, sysSizPeakDDNum.TimeStepAtCoolFlowPk(sysSizPeakDDNum.CoolFlowPeakDD))); + } + } } } else { auto &sysSizPeakDDNum = state.dataSize->SysSizPeakDDNum(this->curSysNum);