From 28bdb41510458487555b4a3e06d660b11a04953c Mon Sep 17 00:00:00 2001 From: Yujie Xu Date: Thu, 12 Sep 2024 09:51:57 -0700 Subject: [PATCH 01/16] change rootsolver to BisectionThenRegulaFalsi to speed up --- src/EnergyPlus/ExtendedHI.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/EnergyPlus/ExtendedHI.cc b/src/EnergyPlus/ExtendedHI.cc index a585e8c37a0..2579fa49c59 100644 --- a/src/EnergyPlus/ExtendedHI.cc +++ b/src/EnergyPlus/ExtendedHI.cc @@ -522,7 +522,7 @@ namespace ExtendedHI { // The function computes the extended heat index, in Kelvinn auto const HVACSystemRootSolverBackup = state.dataRootFinder->HVACSystemRootFinding.HVACSystemRootSolver; - state.dataRootFinder->HVACSystemRootFinding.HVACSystemRootSolver = HVACSystemRootSolverAlgorithm::Bisection; + state.dataRootFinder->HVACSystemRootFinding.HVACSystemRootSolver = HVACSystemRootSolverAlgorithm::BisectionThenRegulaFalsi; int eqvar_name = find_eqvar_name(state, Ta, RH); Real64 eqvar_value = find_eqvar_value(state, Ta, RH); From 6e8fcc876cf8ed38c0532a765ae64b563a3aa57b Mon Sep 17 00:00:00 2001 From: Yujie Xu Date: Thu, 12 Sep 2024 10:38:49 -0700 Subject: [PATCH 02/16] Revert "Revert "Adopt the Extended Heat Index calculation in zone resilience"" This reverts commit a0f92d6fdf8a9666076dee4c916113d42225b6d0. --- .../resilience-metrics.tex | 78 +-- src/EnergyPlus/CMakeLists.txt | 2 + src/EnergyPlus/ExtendedHI.cc | 2 +- src/EnergyPlus/ExtendedHI.hh | 91 +++ src/EnergyPlus/HeatBalanceSurfaceManager.cc | 30 +- tst/EnergyPlus/unit/CMakeLists.txt | 1 + tst/EnergyPlus/unit/ExtendedHI.unit.cc | 625 ++++++++++++++++++ .../unit/HeatBalanceSurfaceManager.unit.cc | 4 +- 8 files changed, 743 insertions(+), 90 deletions(-) create mode 100644 src/EnergyPlus/ExtendedHI.hh create mode 100644 tst/EnergyPlus/unit/ExtendedHI.unit.cc diff --git a/doc/engineering-reference/src/special-modules-reporting/resilience-metrics.tex b/doc/engineering-reference/src/special-modules-reporting/resilience-metrics.tex index 8f2b0d478dc..3055edd3414 100644 --- a/doc/engineering-reference/src/special-modules-reporting/resilience-metrics.tex +++ b/doc/engineering-reference/src/special-modules-reporting/resilience-metrics.tex @@ -66,69 +66,17 @@ \subsubsection{Heat Index}\label{heat-index} \end{tabular} \end{table} -The computation of the heat index is a refinement of a result obtained by +Before version 24.2, the computation of the heat index is a refinement of a result obtained by multiple regression analysis carried out by Lans P. Rothfusz and described in a -1990 National Weather Service (NWS) Technical Attachment (SR 90-23) [4-5]. The -calculation is based on degree Fahrenheit. +1990 National Weather Service (NWS) Technical Attachment (SR 90-23) [4-5]. -The regression equation of Rothfusz is -\begin{equation} \label{eq:rm-1} -HI = c_1 + c_2T + c_3R + c_4TR + c_5T^2 + c_6R^2 + c_7T^2R + c_8TR^2 + c_9T^2R^2 -\end{equation} - -where - -HI = heat index (expressed as an apparent temperature in degrees Fahrenheit), - -T = ambient dry-bulb temperature (in degrees Fahrenheit), - -R = relative humidity (percentage value between 0 and 100), - -$c_1$ = -42.379, - -$c_2$ = 2.04901523, - -$c_3$ = 10.14333127, - -$c_4$ = -0.22475541, - -$c_5$ = -0.00683783, - -$c_6$ = -0.05481717, - -$c_7$ = 0.00122874, - -$c_8$ = 0.00085282, - -$c_9$ = -0.00000199. - -If the RH is less than 13\% and the temperature is between 80 and \IP{112}{\fahrenheit}, then -the following adjustment is subtracted from HI: - -\begin{equation} \label{eq:rm-2} -HI = (13 - R) / 4 * ((17 - |T - 95|) / 17)^{0.5} -\end{equation} - -Otherwise, if the RH is greater than 85\% and the temperature is between 80 and -\IP{87}{\fahrenheit}, then the following adjustment is added to HI: - -\begin{equation} \label{eq:rm-3} -HI = (R - 85) / 10 * (87 - T) / 5 -\end{equation} - -The Rothfusz regression is not appropriate when conditions of temperature and -humidity warrant a heat index value below about \IP{80}{\fahrenheit}. In those cases, a simpler -formula is applied to calculate values consistent with Steadman's results: - -\begin{equation} \label{eq:rm-4} -HI = 0.5 * (T + 61.0 + (T - 68.0) * 1.2 + (R * 0.094)) -\end{equation} - -In practice, the simple formula is computed first based on the temperature and -humidity. If this heat index value is \IP{80}{\fahrenheit} or higher, the full regression -equation along with any adjustment as described above is applied. The Rothfusz -regression is not valid for extreme temperature and relative humidity conditions -beyond the range of data considered by Steadman. +Starting from version 24.2, the heat index calculation adopts the extended heat +index method developed by Lu \& Romps [17]. The previous heat index gives +unrealistic results for very hot and humid or very cold and dry conditions. The +extended index extends the domain of the heat index calculation to all +combinations of temperature and relative humidity and gives a more realistic heat +index for the extreme conditions. The implementation in EnergyPlus is based on +the released Python code by Lu and Romps [18]. The Heat Index Hours (accumulated hours for a space) and Heat Index OccupantHours (accumulated hours for the sum of all occupants in a space) of @@ -516,3 +464,11 @@ \subsection{References} {[}16{]} ACGIH, Threshold Limit Values (TLVs) and Biological Exposure Indices (BEIs), 2012. doi:10.1073/pnas.0703993104. + +{[}17{]} Lu, Yi-Chuan, and David M. Romps. ``Extending the heat index''. Journal +of Applied Meteorology and Climatology 61, no. 10 (2022): 1367-1383. +doi:10.1073/pnas.0703993104. + +{[}18{]} Lu, Yi-Chuan, and David M. Romps. ``Lu and Romps, Extending the heat index, JAMC, 2022'', +Physics of Climate, February 23, 2023. +https://romps.berkeley.edu/papers/pubs-2020-heatindex.html. diff --git a/src/EnergyPlus/CMakeLists.txt b/src/EnergyPlus/CMakeLists.txt index cfb928e00dc..56f664ba014 100644 --- a/src/EnergyPlus/CMakeLists.txt +++ b/src/EnergyPlus/CMakeLists.txt @@ -262,6 +262,8 @@ set(SRC EvaporativeFluidCoolers.hh ExhaustAirSystemManager.cc ExhaustAirSystemManager.hh + ExtendedHI.cc + ExtendedHI.hh ExteriorEnergyUse.cc ExteriorEnergyUse.hh ExternalInterface.cc diff --git a/src/EnergyPlus/ExtendedHI.cc b/src/EnergyPlus/ExtendedHI.cc index 2579fa49c59..a585e8c37a0 100644 --- a/src/EnergyPlus/ExtendedHI.cc +++ b/src/EnergyPlus/ExtendedHI.cc @@ -522,7 +522,7 @@ namespace ExtendedHI { // The function computes the extended heat index, in Kelvinn auto const HVACSystemRootSolverBackup = state.dataRootFinder->HVACSystemRootFinding.HVACSystemRootSolver; - state.dataRootFinder->HVACSystemRootFinding.HVACSystemRootSolver = HVACSystemRootSolverAlgorithm::BisectionThenRegulaFalsi; + state.dataRootFinder->HVACSystemRootFinding.HVACSystemRootSolver = HVACSystemRootSolverAlgorithm::Bisection; int eqvar_name = find_eqvar_name(state, Ta, RH); Real64 eqvar_value = find_eqvar_value(state, Ta, RH); diff --git a/src/EnergyPlus/ExtendedHI.hh b/src/EnergyPlus/ExtendedHI.hh new file mode 100644 index 00000000000..b839ea571eb --- /dev/null +++ b/src/EnergyPlus/ExtendedHI.hh @@ -0,0 +1,91 @@ +// EnergyPlus, Copyright (c) 1996-2024, The Board of Trustees of the University of Illinois, +// The Regents of the University of California, through Lawrence Berkeley National Laboratory +// (subject to receipt of any required approvals from the U.S. Dept. of Energy), Oak Ridge +// National Laboratory, managed by UT-Battelle, Alliance for Sustainable Energy, LLC, and other +// contributors. All rights reserved. +// +// NOTICE: This Software was developed under funding from the U.S. Department of Energy and the +// U.S. Government consequently retains certain rights. As such, the U.S. Government has been +// granted for itself and others acting on its behalf a paid-up, nonexclusive, irrevocable, +// worldwide license in the Software to reproduce, distribute copies to the public, prepare +// derivative works, and perform publicly and display publicly, and to permit others to do so. +// +// Redistribution and use in source and binary forms, with or without modification, are permitted +// provided that the following conditions are met: +// +// (1) Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// (2) Redistributions in binary form must reproduce the above copyright notice, this list of +// conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// +// (3) Neither the name of the University of California, Lawrence Berkeley National Laboratory, +// the University of Illinois, U.S. Dept. of Energy nor the names of its contributors may be +// used to endorse or promote products derived from this software without specific prior +// written permission. +// +// (4) Use of EnergyPlus(TM) Name. If Licensee (i) distributes the software in stand-alone form +// without changes from the version obtained under this License, or (ii) Licensee makes a +// reference solely to the software portion of its product, Licensee must refer to the +// software as "EnergyPlus version X" software, where "X" is the version number Licensee +// obtained under this License and may not use a different name for the software. Except as +// specifically required in this Section (4), Licensee shall not use in a company name, a +// product name, in advertising, publicity, or other promotional activities any name, trade +// name, trademark, logo, or other designation of "EnergyPlus", "E+", "e+" or confusingly +// similar designation, without the U.S. Department of Energy's prior written consent. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR +// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY +// AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +#ifndef extendedHI_hh_INCLUDED +#define extendedHI_hh_INCLUDED + +// EnergyPlus Headers +#include +#include +#include + +namespace EnergyPlus { + +// Forward declarations +struct EnergyPlusData; + +namespace ExtendedHI { + + enum class EqvarName + { + Invalid = -1, + Phi = 1, + Rf = 2, + Rs = 3, + DTcdt = 4, + Num + }; + + Real64 pvstar(Real64 T); + Real64 Le(Real64 T); + Real64 Qv(Real64 Ta, Real64 Pa); + Real64 Zs(Real64 Rs); + Real64 Ra(Real64 Ts, Real64 Ta); + Real64 Ra_bar(Real64 Tf, Real64 Ta); + Real64 Ra_un(Real64 Ts, Real64 Ta); + int find_eqvar_name(EnergyPlusData &state, Real64 Ta, Real64 RH); + Real64 find_eqvar_value(EnergyPlusData &state, Real64 Ta, Real64 RH); + Real64 find_eqvar_phi(EnergyPlusData &state, Real64 Ta, Real64 RH); + Real64 find_eqvar_Rf(EnergyPlusData &state, Real64 Ta, Real64 RH); + Real64 find_eqvar_rs(EnergyPlusData &state, Real64 Ta, Real64 RH); + Real64 find_T(EnergyPlusData &state, int eqvar_name, Real64 eqvar); + Real64 heatindex(EnergyPlusData &state, Real64 Ta, Real64 RH); + +} // namespace ExtendedHI +} // namespace EnergyPlus + +#endif diff --git a/src/EnergyPlus/HeatBalanceSurfaceManager.cc b/src/EnergyPlus/HeatBalanceSurfaceManager.cc index d121537afdd..3faf6e3dda9 100644 --- a/src/EnergyPlus/HeatBalanceSurfaceManager.cc +++ b/src/EnergyPlus/HeatBalanceSurfaceManager.cc @@ -87,6 +87,7 @@ #include #include #include +#include #include #include #include @@ -5516,36 +5517,13 @@ void CalcThermalResilience(EnergyPlusData &state) // The heat index equation set is fit to Fahrenheit units, so the zone air temperature values are first convert to F, // then heat index is calculated and converted back to C. if (state.dataHeatBalSurfMgr->reportVarHeatIndex || state.dataOutRptTab->displayThermalResilienceSummary) { - // Constance for heat index regression equation of Rothfusz. - Real64 constexpr c1 = -42.379; - Real64 constexpr c2 = 2.04901523; - Real64 constexpr c3 = 10.14333127; - Real64 constexpr c4 = -.22475541; - Real64 constexpr c5 = -.00683783; - Real64 constexpr c6 = -.05481717; - Real64 constexpr c7 = .00122874; - Real64 constexpr c8 = .00085282; - Real64 constexpr c9 = -.00000199; for (int ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) { Real64 const ZoneT = state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneNum).ZTAV; Real64 const ZoneW = state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneNum).airHumRatAvg; - Real64 const ZoneRH = Psychrometrics::PsyRhFnTdbWPb(state, ZoneT, ZoneW, state.dataEnvrn->OutBaroPress) * 100.0; + Real64 const ZoneRH = Psychrometrics::PsyRhFnTdbWPb(state, ZoneT, ZoneW, state.dataEnvrn->OutBaroPress); Real64 const ZoneTF = ZoneT * (9.0 / 5.0) + 32.0; - Real64 HI; - - if (ZoneTF < 80) { - HI = 0.5 * (ZoneTF + 61.0 + (ZoneTF - 68.0) * 1.2 + (ZoneRH * 0.094)); - } else { - HI = c1 + c2 * ZoneTF + c3 * ZoneRH + c4 * ZoneTF * ZoneRH + c5 * ZoneTF * ZoneTF + c6 * ZoneRH * ZoneRH + - c7 * ZoneTF * ZoneTF * ZoneRH + c8 * ZoneTF * ZoneRH * ZoneRH + c9 * ZoneTF * ZoneTF * ZoneRH * ZoneRH; - if (ZoneRH < 13 && ZoneTF < 112) { - HI -= (13 - ZoneRH) / 4 * std::sqrt((17 - abs(ZoneTF - 95)) / 17); - } else if (ZoneRH > 85 && ZoneTF < 87) { - HI += (ZoneRH - 85) / 10 * (87 - ZoneTF) / 5; - } - } - HI = (HI - 32.0) * (5.0 / 9.0); - state.dataHeatBal->Resilience(ZoneNum).ZoneHeatIndex = HI; + // calculate extended heat index + state.dataHeatBal->Resilience(ZoneNum).ZoneHeatIndex = ExtendedHI::heatindex(state, ZoneT + Constant::Kelvin, ZoneRH) - Constant::Kelvin; } } if (state.dataHeatBalSurfMgr->reportVarHumidex || state.dataOutRptTab->displayThermalResilienceSummary) { diff --git a/tst/EnergyPlus/unit/CMakeLists.txt b/tst/EnergyPlus/unit/CMakeLists.txt index 63eaff06bbc..3259c7e9983 100644 --- a/tst/EnergyPlus/unit/CMakeLists.txt +++ b/tst/EnergyPlus/unit/CMakeLists.txt @@ -110,6 +110,7 @@ set(test_src EvaporativeCoolers.unit.cc EvaporativeFluidCoolers.unit.cc ExhaustSystem.unit.cc + ExtendedHI.unit.cc ExteriorEnergyUse.unit.cc FanCoilUnits.unit.cc Fans.unit.cc diff --git a/tst/EnergyPlus/unit/ExtendedHI.unit.cc b/tst/EnergyPlus/unit/ExtendedHI.unit.cc new file mode 100644 index 00000000000..e2a00657cfa --- /dev/null +++ b/tst/EnergyPlus/unit/ExtendedHI.unit.cc @@ -0,0 +1,625 @@ +// EnergyPlus, Copyright (c) 1996-2024, The Board of Trustees of the University of Illinois, +// The Regents of the University of California, through Lawrence Berkeley National Laboratory +// (subject to receipt of any required approvals from the U.S. Dept. of Energy), Oak Ridge +// National Laboratory, managed by UT-Battelle, Alliance for Sustainable Energy, LLC, and other +// contributors. All rights reserved. +// +// NOTICE: This Software was developed under funding from the U.S. Department of Energy and the +// U.S. Government consequently retains certain rights. As such, the U.S. Government has been +// granted for itself and others acting on its behalf a paid-up, nonexclusive, irrevocable, +// worldwide license in the Software to reproduce, distribute copies to the public, prepare +// derivative works, and perform publicly and display publicly, and to permit others to do so. +// +// Redistribution and use in source and binary forms, with or without modification, are permitted +// provided that the following conditions are met: +// +// (1) Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// (2) Redistributions in binary form must reproduce the above copyright notice, this list of +// conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// +// (3) Neither the name of the University of California, Lawrence Berkeley National Laboratory, +// the University of Illinois, U.S. Dept. of Energy nor the names of its contributors may be +// used to endorse or promote products derived from this software without specific prior +// written permission. +// +// (4) Use of EnergyPlus(TM) Name. If Licensee (i) distributes the software in stand-alone form +// without changes from the version obtained under this License, or (ii) Licensee makes a +// reference solely to the software portion of its product, Licensee must refer to the +// software as "EnergyPlus version X" software, where "X" is the version number Licensee +// obtained under this License and may not use a different name for the software. Except as +// specifically required in this Section (4), Licensee shall not use in a company name, a +// product name, in advertising, publicity, or other promotional activities any name, trade +// name, trademark, logo, or other designation of "EnergyPlus", "E+", "e+" or confusingly +// similar designation, without the U.S. Department of Energy's prior written consent. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR +// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY +// AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + +// Google Test Headers +#include + +#include +#include +#include +#include + +// EnergyPlus Headers +#include "Fixtures/EnergyPlusFixture.hh" +#include +#include +#include + +using namespace EnergyPlus; +using namespace ExtendedHI; + +TEST_F(EnergyPlusFixture, extendedHI_pvstar) +{ + Real64 tol = 1e-8; + std::vector T_values = {200, 210, 220, 230, 240, 250, 260, 270, 280, 290, 300, 310, 320, 330, 340, 350, 360, 370}; + std::vector result = {0.16315953, + 0.70457376, + 2.66392126, + 8.97272134, + 27.31539419, + 76.07472151, + 195.83100376, + 470.03352248, + 991.92542226, + 1920.68015554, + 3538.94082369, + 6235.88791594, + 10554.04916628, + 17222.31477378, + 27187.71571487, + 41643.76611223, + 62053.26405691, + 90163.72448627}; + + for (size_t i = 0; i < T_values.size(); ++i) { + EXPECT_NEAR(ExtendedHI::pvstar(T_values[i]), result[i], tol); + } +} + +TEST_F(EnergyPlusFixture, extendedHI_Le) +{ + Real64 tol = 1e-2; + std::vector T_values = {200, 210, 220, 230, 240, 250, 260, 270, 280, 290, 300, 310, 320, 330, 340, 350, 360, 370}; + std::vector result = {2663805.16, + 2641405.16, + 2619005.16, + 2596605.16, + 2574205.16, + 2551805.16, + 2529405.16, + 2507005.16, + 2484605.16, + 2462205.16, + 2439805.16, + 2417405.16, + 2395005.16, + 2372605.16, + 2350205.16, + 2327805.16, + 2305405.16, + 2283005.16}; + for (size_t i = 0; i < T_values.size(); ++i) { + EXPECT_NEAR(ExtendedHI::Le(T_values[i]), result[i], tol); + } +} + +TEST_F(EnergyPlusFixture, extendedHI_Qv) +{ + Real64 tol = 1e-8; + std::vector T_values = {200, 210, 220, 230, 240, 250, 260, 270, 280, 290, 300, 310, 320, 330, 340, 350, 360, 370}; + std::vector P_values = {1, 10, 100, 1000, 10000}; + std::vector> result = {{49.94618971, 49.91176799, 49.56755081, 46.12537897, 11.70366056}, + {47.35664275, 47.32222103, 46.97800385, 43.53583201, 9.1141136}, + {44.76709579, 44.73267407, 44.38845689, 40.94628505, 6.52456664}, + {42.17754883, 42.14312711, 41.79890993, 38.35673809, 3.93501968}, + {39.58800187, 39.55358015, 39.20936297, 35.76719113, 1.34547272}, + {36.99845491, 36.96403319, 36.61981601, 33.17764417, -1.24407424}, + {34.40890795, 34.37448623, 34.03026905, 30.58809721, -3.8336212}, + {31.81936099, 31.78493927, 31.44072209, 27.99855025, -6.42316816}, + {29.22981403, 29.19539231, 28.85117513, 25.40900329, -9.01271512}, + {26.64026707, 26.60584535, 26.26162817, 22.81945633, -11.60226208}, + {24.05072011, 24.01629839, 23.67208121, 20.22990937, -14.19180904}, + {21.46117315, 21.42675143, 21.08253425, 17.64036241, -16.781356}, + {18.87162619, 18.83720447, 18.49298729, 15.05081545, -19.37090296}, + {16.28207923, 16.24765751, 15.90344033, 12.46126849, -21.96044992}, + {13.69253227, 13.65811055, 13.31389337, 9.87172153, -24.54999688}, + {11.10298531, 11.06856359, 10.72434641, 7.28217457, -27.13954384}, + {8.51343835, 8.47901663, 8.13479945, 4.69262761, -29.7290908}, + {5.92389139, 5.88946967, 5.54525249, 2.10308065, -32.31863776}}; + for (size_t i = 0; i < T_values.size(); ++i) { + for (size_t j = 0; j < P_values.size(); ++j) { + EXPECT_NEAR(ExtendedHI::Qv(T_values[i], P_values[j]), result[i][j], tol); + } + } +} + +TEST_F(EnergyPlusFixture, extendedHI_Zs) +{ + Real64 tol = 1e-8; + std::vector Rs_values = {0.0387, 0.5, 1, 1.2}; + std::vector result = {52.1, 18750000.0, 600000000.0, 1492991999.9999998}; + for (size_t i = 0; i < Rs_values.size(); ++i) { + EXPECT_NEAR(ExtendedHI::Zs(Rs_values[i]), result[i], tol); + } +} + +TEST_F(EnergyPlusFixture, extendedHI_Ra) +{ + Real64 tol = 1e-8; + std::vector Ts_values = {240, 260, 280, 300, 320, 340, 360}; + std::vector Ta_values = {240, 260, 280, 300, 320, 340, 360}; + std::vector> result = {{0.05003743, 0.04919687, 0.04829495, 0.04733483, 0.04632048, 0.04525658, 0.04414843}, + {0.04919687, 0.04834035, 0.0474255, 0.04645568, 0.045435, 0.0443682, 0.04326057}, + {0.04829495, 0.0474255, 0.04650092, 0.04552473, 0.04450111, 0.04343485, 0.04233118}, + {0.04733483, 0.04645568, 0.04552473, 0.0445456, 0.04352252, 0.04246025, 0.04136396}, + {0.04632048, 0.045435, 0.04450111, 0.04352252, 0.04250345, 0.0414486, 0.04036303}, + {0.04525658, 0.0443682, 0.04343485, 0.04246025, 0.0414486, 0.04040451, 0.03933288}, + {0.04414843, 0.04326057, 0.04233118, 0.04136396, 0.04036303, 0.03933288, 0.03827822}}; + for (size_t i = 0; i < Ts_values.size(); ++i) { + for (size_t j = 0; j < Ta_values.size(); ++j) { + EXPECT_NEAR(ExtendedHI::Ra(Ts_values[i], Ta_values[j]), result[i][j], tol); + } + } +} + +TEST_F(EnergyPlusFixture, extendedHI_Ra_bar) +{ + Real64 tol = 1e-8; + std::vector Tf_values = {240, 260, 280, 300, 320, 340, 360}; + std::vector Ta_values = {240, 260, 280, 300, 320, 340, 360}; + std::vector> result = {{0.07141547, 0.06983279, 0.06815365, 0.0663875, 0.06454507, 0.06263806, 0.06067882}, + {0.06983279, 0.06823771, 0.06655337, 0.06478927, 0.06295607, 0.06106521, 0.05912865}, + {0.06815365, 0.06655337, 0.06487109, 0.06311629, 0.06129941, 0.05943158, 0.0575243}, + {0.0663875, 0.06478927, 0.06311629, 0.06137788, 0.05958421, 0.05774599, 0.05587418}, + {0.06454507, 0.06295607, 0.06129941, 0.05958421, 0.05782026, 0.05601779, 0.05418719}, + {0.06263806, 0.06106521, 0.05943158, 0.05774599, 0.05601779, 0.05425668, 0.05247244}, + {0.06067882, 0.05912865, 0.0575243, 0.05587418, 0.05418719, 0.05247244, 0.0507391}}; + + for (size_t i = 0; i < Tf_values.size(); ++i) { + for (size_t j = 0; j < Ta_values.size(); ++j) { + EXPECT_NEAR(ExtendedHI::Ra_bar(Tf_values[i], Ta_values[j]), result[i][j], tol); + } + } +} + +TEST_F(EnergyPlusFixture, extendedHI_Ra_un) +{ + Real64 tol = 1e-8; + std::vector Tf_values = {240, 260, 280, 300, 320, 340, 360}; + std::vector Ta_values = {240, 260, 280, 300, 320, 340, 360}; + std::vector> result = {{0.06787493, 0.06642598, 0.06488609, 0.06326346, 0.06156753, 0.05980867, 0.05799795}, + {0.06642598, 0.06496324, 0.06341598, 0.0617925, 0.06010222, 0.05835534, 0.05656263}, + {0.06488609, 0.06341598, 0.06186786, 0.06025007, 0.0585719, 0.0568433, 0.05507465}, + {0.06326346, 0.0617925, 0.06025007, 0.05864444, 0.05698468, 0.05528041, 0.05354159}, + {0.06156753, 0.06010222, 0.0585719, 0.05698468, 0.05534934, 0.05367512, 0.0519715}, + {0.05980867, 0.05835534, 0.0568433, 0.05528041, 0.05367512, 0.05203623, 0.0503727}, + {0.05799795, 0.05656263, 0.05507465, 0.05354159, 0.0519715, 0.0503727, 0.0487536}}; + for (size_t i = 0; i < Tf_values.size(); ++i) { + for (size_t j = 0; j < Ta_values.size(); ++j) { + EXPECT_NEAR(ExtendedHI::Ra_un(Tf_values[i], Ta_values[j]), result[i][j], tol); + } + } +} + +TEST_F(EnergyPlusFixture, extendedHI_find_eqvar) +{ + Real64 tol = 1e-5; + std::vector Ta_values = {240, 260, 280, 300, 320, 340, 360}; + std::vector RH_values = {0, 0.2, 0.4, 0.6, 0.8, 1.0}; + std::vector> result_0 = {{static_cast(EqvarName::Rf), + static_cast(EqvarName::Rf), + static_cast(EqvarName::Rf), + static_cast(EqvarName::Rf), + static_cast(EqvarName::Rf), + static_cast(EqvarName::Rf)}, + {static_cast(EqvarName::Rf), + static_cast(EqvarName::Rf), + static_cast(EqvarName::Rf), + static_cast(EqvarName::Rf), + static_cast(EqvarName::Rf), + static_cast(EqvarName::Rf)}, + {static_cast(EqvarName::Rf), + static_cast(EqvarName::Rf), + static_cast(EqvarName::Rf), + static_cast(EqvarName::Rf), + static_cast(EqvarName::Rf), + static_cast(EqvarName::Rf)}, + {static_cast(EqvarName::Rf), + static_cast(EqvarName::Rs), + static_cast(EqvarName::Rs), + static_cast(EqvarName::Rs), + static_cast(EqvarName::Rs), + static_cast(EqvarName::Rs)}, + {static_cast(EqvarName::Rs), + static_cast(EqvarName::Rs), + static_cast(EqvarName::DTcdt), + static_cast(EqvarName::DTcdt), + static_cast(EqvarName::DTcdt), + static_cast(EqvarName::DTcdt)}, + {static_cast(EqvarName::Rs), + static_cast(EqvarName::DTcdt), + static_cast(EqvarName::DTcdt), + static_cast(EqvarName::DTcdt), + static_cast(EqvarName::DTcdt), + static_cast(EqvarName::DTcdt)}, + {static_cast(EqvarName::Rs), + static_cast(EqvarName::DTcdt), + static_cast(EqvarName::DTcdt), + static_cast(EqvarName::DTcdt), + static_cast(EqvarName::DTcdt), + static_cast(EqvarName::DTcdt)}}; + + std::vector> result_1 = {{33.04275, 32.69563, 32.35542, 32.02191, 31.69491, 31.37423}, + {1.56043, 1.54633, 1.53238, 1.51858, 1.50491, 1.49139}, + {0.44248, 0.42288, 0.40403, 0.38594, 0.36856, 0.35189}, + {0.01107, 0.03821, 0.03685, 0.03533, 0.03356, 0.0314}, + {0.02699, 0.02259, 0.00048, 0.00338, 0.00628, 0.00918}, + {0.02073, 0.00466, 0.01213, 0.0196, 0.02707, 0.03453}, + {0.00147, 0.01691, 0.03395, 0.051, 0.06804, 0.08509}}; + + for (size_t i = 0; i < Ta_values.size(); ++i) { + for (size_t j = 0; j < RH_values.size(); ++j) { + EXPECT_EQ(find_eqvar_name(*state, Ta_values[i], RH_values[j]), result_0[i][j]); + EXPECT_NEAR(find_eqvar_value(*state, Ta_values[i], RH_values[j]), result_1[i][j], tol); + } + } +} + +TEST_F(EnergyPlusFixture, extendedHI_find_T) +{ + Real64 tol = 1e-7; + state->dataRootFinder->HVACSystemRootFinding.HVACSystemRootSolver = HVACSystemRootSolverAlgorithm::Bisection; + std::vector Rf_values = {30, 32, 34, 36, 38}; + std::vector result_0_rf = {240.0675404, 239.9711237, 239.8858108, 239.8097882, 239.7416167}; + for (size_t i = 0; i < Rf_values.size(); ++i) { + EXPECT_NEAR(ExtendedHI::find_T(*state, static_cast(EnergyPlus::ExtendedHI::EqvarName::Rf), Rf_values[i]), result_0_rf[i], tol); + } + std::vector Rs_values = {0.01, 0.02, 0.03}; + std::vector result_0_rs = {337.8697, 329.7587, 307.4816}; + tol = 1e-4; + for (size_t i = 0; i < Rs_values.size(); ++i) { + EXPECT_NEAR(ExtendedHI::find_T(*state, static_cast(EnergyPlus::ExtendedHI::EqvarName::Rs), Rs_values[i]), result_0_rs[i], tol); + } + std::vector phi_values = {0.86, 0.88, 0.90, 0.92, 0.94, 0.96}; + std::vector result_0_phi = {228.6900, 215.9994, 199.0012, 175.1865, 139.7124, 82.0478}; + for (size_t i = 0; i < phi_values.size(); ++i) { + EXPECT_NEAR(ExtendedHI::find_T(*state, static_cast(EnergyPlus::ExtendedHI::EqvarName::Phi), phi_values[i]), result_0_phi[i], tol); + } + std::vector dTcdt_values = {0.01, 0.03, 0.05, 0.07, 0.09}; + std::vector result_0_dTcdt = {412.5272, 512.3596, 584.547, 641.1988, 688.0423}; + for (size_t i = 0; i < dTcdt_values.size(); ++i) { + EXPECT_NEAR(ExtendedHI::find_T(*state, static_cast(EnergyPlus::ExtendedHI::EqvarName::DTcdt), dTcdt_values[i]), result_0_dTcdt[i], tol); + } +} + +TEST_F(EnergyPlusFixture, extendedHI_heatindex) +{ + + state->dataRootFinder->HVACSystemRootFinding.HVACSystemRootSolver = HVACSystemRootSolverAlgorithm::Bisection; + std::vector> HI_values = {{199.9994, 199.9997, 200.0}, + {209.9976, 209.9988, 210.0}, + {219.9916, 219.9958, 220.0}, + {229.974, 229.987, 230.0}, + {239.9254, 239.9627, 240.0}, + {249.7677, 249.8837, 250.0}, + {259.3736, 259.6864, 260.0}, + {268.5454, 269.2746, 270.0}, + {277.2234, 278.6369, 280.0}, + {285.7511, 288.2814, 290.7861}, + {297.5738, 300.2923, 305.3947}, + {305.555, 318.6226, 359.9063}, + {313.0299, 359.0539, 407.5345}, + {320.5089, 398.576, 464.9949}, + {328.0358, 445.8599, 530.5525}, + {333.2806, 500.0422, 601.9518}, + {343.6313, 559.664, 677.2462}, + {354.1826, 623.196, 755.0833}}; + + std::vector T_values = {200, 210, 220, 230, 240, 250, 260, 270, 280, 290, 300, 310, 320, 330, 340, 350, 360, 370}; + std::vector RH_values = {0, 0.5, 1}; + + Real64 tol = 1e-4; + + for (size_t i = 0; i < T_values.size(); ++i) { + for (size_t j = 0; j < RH_values.size(); ++j) { + Real64 HI = HI_values[i][j]; + EXPECT_NEAR(ExtendedHI::heatindex(*state, T_values[i], RH_values[j]), HI, tol); + } + } +} + +// helper: calculating HI the old way +Real64 calcHI(Real64 ZoneTF, Real64 ZoneRH) +{ + Real64 HI; + Real64 constexpr c1 = -42.379; + Real64 constexpr c2 = 2.04901523; + Real64 constexpr c3 = 10.14333127; + Real64 constexpr c4 = -.22475541; + Real64 constexpr c5 = -.00683783; + Real64 constexpr c6 = -.05481717; + Real64 constexpr c7 = .00122874; + Real64 constexpr c8 = .00085282; + Real64 constexpr c9 = -.00000199; + if (ZoneTF < 80) { + HI = 0.5 * (ZoneTF + 61.0 + (ZoneTF - 68.0) * 1.2 + (ZoneRH * 0.094)); + } else { + HI = c1 + c2 * ZoneTF + c3 * ZoneRH + c4 * ZoneTF * ZoneRH + c5 * ZoneTF * ZoneTF + c6 * ZoneRH * ZoneRH + c7 * ZoneTF * ZoneTF * ZoneRH + + c8 * ZoneTF * ZoneRH * ZoneRH + c9 * ZoneTF * ZoneTF * ZoneRH * ZoneRH; + if (ZoneRH < 13 && ZoneTF < 112) { + HI -= (13 - ZoneRH) / 4 * std::sqrt((17 - abs(ZoneTF - 95)) / 17); + } else if (ZoneRH > 85 && ZoneTF < 87) { + HI += (ZoneRH - 85) / 10 * (87 - ZoneTF) / 5; + } + } + HI = (HI - 32.0) * (5.0 / 9.0); + return HI; +} + +constexpr Real64 Fahrenheit2Celsius(Real64 F) +{ + return (F - 32.0) * 5.0 / 9.0; +} + +// compare different the old and new HI method +TEST_F(EnergyPlusFixture, extendedHI_heatindex_compare) +{ + // uncomment the following to write out outputs comparing the old HI and the extended HI + // for (int T = 80; T < 112; T += 2) { + // for (int RH_percent = 40; RH_percent < 105; RH_percent += 5) { + // fmt::print("{},{},{},{}\n", T, Fahrenheit2Celsius(T) + 273.15, RH_percent, calcHI(T * 1.0, RH_percent) + 273.15); + // } + // } + // + // fmt::print("--------------------------extended HI------------------------------\n"); + // + // for (int T = 80; T < 112; T += 2) { + // for (int RH_percent = 40; RH_percent < 105; RH_percent += 5) { + // fmt::print("{},{},{},{}\n", + // T, + // Fahrenheit2Celsius(T) + 273.15, + // RH_percent, + // ExtendedHI::heatindex(*state, Fahrenheit2Celsius(T) + 273.15, RH_percent / 100.0, false)); + // } + // } + + std::vector> HI_values = {{299.50263955106493, + 299.776740099187, + 300.0697403535014, + 300.3840374486754, + 300.7224627089454, + 301.0883855406428, + 301.48585129820276, + 301.91976206202526, + 302.39612058678176, + 302.9223619942786, + 303.50781721121166, + 304.164366737823, + 304.90738965163473}, + {300.7371586287627, + 301.08082855993416, + 301.45165138470475, + 301.85347046062816, + 302.29090810229536, + 302.7695771184517, + 303.2963640097296, + 303.8798186200438, + 304.5306942932075, + 305.2627171872882, + 306.0937017010292, + 307.0472131000133, + 308.15511379914824}, + {302.02736771141645, + 302.4561810697196, + 302.92349559196737, + 303.4353941195877, + 303.9993409969611, + 304.62460199545603, + 305.322829571669, + 306.10889266303275, + 307.00207884714473, + 308.027883155155, + 309.2207373859128, + 313.0628398671979, + 321.5848247316899}, + {303.3841495186789, + 303.9170689758612, + 304.50409744807985, + 305.1547874516109, + 305.88112467259634, + 306.69836198852863, + 307.62622559734154, + 308.69069155014586, + 309.9266883142991, + 311.38231908960734, + 318.54246110946406, + 328.0043066147482, + 333.3393972698832}, + {304.8199354641838, + 305.48032203514595, + 306.21634121227544, + 307.0429394330131, + 307.97934497182723, + 309.05072723689955, + 310.29069143289234, + 311.7451353772776, + 313.95530016103294, + 323.83440227771644, + 332.4701096833451, + 334.90678639907856, + 337.31894975469913}, + {306.3492841011612, + 307.16624582593795, + 308.0886627669679, + 309.13992447021883, + 310.35097800020594, + 311.7636495939223, + 313.43586634553503, + 317.6494802389061, + 328.3628307696199, + 333.74059265770484, + 336.3222867687, + 338.8761290133698, + 341.4020377426641}, + {307.98957814869937, + 308.99980285495985, + 310.15708861581516, + 311.49815879471134, + 313.0731694836868, + 314.95241500844713, + 320.7787010347238, + 331.8317274673609, + 334.83416476810817, + 337.5699159357464, + 340.2740648871986, + 342.94652084296104, + 345.6054543473874}, + {309.7619108116487, + 311.0122043680167, + 312.46811247605365, + 314.187658362207, + 316.2529625179013, + 323.0801825976232, + 332.79726637585554, + 335.7326857879525, + 338.63242015999276, + 341.4963439834537, + 344.32435625989456, + 347.16610411327565, + 349.9882094984059}, + {311.6922567837173, + 313.2431093422929, + 315.0828601612011, + 317.30399334745016, + 324.3992667720886, + 333.3013983833371, + 336.4164381631417, + 339.4910959439585, + 342.5252268166514, + 345.53482289920794, + 348.55059671303025, + 351.53749776567565, + 354.49586372385966}, + {313.81305196962785, + 315.74373047973495, + 318.0832217884017, + 324.6363173221471, + 333.556578377611, + 336.86389599752147, + 340.12557708716486, + 343.3414515358163, + 346.5464459863142, + 349.74051965837134, + 352.90212786378106, + 356.0316775160027, + 359.1295787363197}, + {316.1653665843187, + 318.58128181367647, + 323.6855917231878, + 333.5378166526789, + 337.0514521509176, + 340.51358119759243, + 343.9240011043148, + 347.3324049610528, + 350.715991469624, + 354.063080122869, + 357.3741601619986, + 360.6497245162609, + 363.89026874647243}, + {318.80192411888856, + 321.8453275115462, + 333.2175307610305, + 336.9530971109634, + 340.63061076856684, + 344.2498254548991, + 347.8701384467422, + 351.4554844770464, + 354.99980266642524, + 358.5036799122463, + 361.96770739537897, + 365.39247917797184, + 368.7785908780643}, + {321.79129250056576, + 332.5651462195674, + 336.5400431206217, + 340.4496004333487, + 344.2935131903505, + 348.13508995372104, + 351.9356167348451, + 355.6900213044719, + 359.3990061376826, + 363.0632788382354, + 366.6835501792957, + 370.2605324515025, + 373.7949378686608}, + {329.9497329717269, + 335.7802855706541, + 339.9405041738646, + 344.0269053383963, + 348.1004405542626, + 352.130907458195, + 356.1095161383855, + 360.03710570017574, + 363.9145213572192, + 367.74261204962386, + 371.5222280813032, + 375.2542191799148, + 378.9394325375906}, + {334.63809705979656, + 339.06981446722057, + 343.41864144138526, + 347.7367934017093, + 352.013488568773, + 356.2318584616878, + 360.3929031532607, + 364.49763041891856, + 368.54705243284116, + 372.5421826945967, + 376.48403349361615, + 380.3736132776248, + 384.2119247702067}, + {337.80000485421624, + 342.43363185960334, + 347.0118012771127, + 351.55276412755484, + 356.0280998123926, + 360.438997685269, + 364.78665706905304, + 369.07228278025286, + 373.2970810952247, + 377.4622562734294, + 381.56900731119094, + 385.6185252717114, + 389.61199074954493}}; + + std::vector T_values; + for (int i = 0; i < 16; ++i) { + T_values.push_back(80 + 2 * i); + } + std::vector RH_values; + for (int i = 0; i < 13; ++i) { + RH_values.push_back(40 + 5 * i); + } + + Real64 extended; + for (size_t i = 0; i < T_values.size(); ++i) { + for (size_t j = 0; j < RH_values.size(); ++j) { + extended = ExtendedHI::heatindex(*state, Fahrenheit2Celsius(T_values[i]) + 273.15, RH_values[j] / 100.0); + EXPECT_NEAR(HI_values[i][j], extended, 1e-4); + } + } +} diff --git a/tst/EnergyPlus/unit/HeatBalanceSurfaceManager.unit.cc b/tst/EnergyPlus/unit/HeatBalanceSurfaceManager.unit.cc index dbb84bbd90a..9601e745d0b 100644 --- a/tst/EnergyPlus/unit/HeatBalanceSurfaceManager.unit.cc +++ b/tst/EnergyPlus/unit/HeatBalanceSurfaceManager.unit.cc @@ -3258,7 +3258,7 @@ TEST_F(EnergyPlusFixture, HeatBalanceSurfaceManager_TestResilienceMetricReport) state->dataZoneTempPredictorCorrector->zoneHeatBalance(1).airHumRatAvg = 0.0022; // RH = 10% CalcThermalResilience(*state); ReportThermalResilience(*state); - EXPECT_NEAR(26, state->dataHeatBal->Resilience(1).ZoneHeatIndex, 0.5); + EXPECT_NEAR(25, state->dataHeatBal->Resilience(1).ZoneHeatIndex, 0.5); EXPECT_NEAR(23, state->dataHeatBal->Resilience(1).ZoneHumidex, 1); // Heat Index Case 4: Rothfusz regression, other than the above conditions; @@ -3833,7 +3833,7 @@ TEST_F(EnergyPlusFixture, HeatBalanceSurfaceManager_TestThermalResilienceReportR state->dataZoneTempPredictorCorrector->zoneHeatBalance(1).airHumRatAvg = 0.0022; // RH = 10% CalcThermalResilience(*state); ReportThermalResilience(*state); - EXPECT_NEAR(26, state->dataHeatBal->Resilience(1).ZoneHeatIndex, 0.5); + EXPECT_NEAR(25, state->dataHeatBal->Resilience(1).ZoneHeatIndex, 0.5); EXPECT_NEAR(23, state->dataHeatBal->Resilience(1).ZoneHumidex, 1); // Heat Index Case 4: Rothfusz regression, other than the above conditions; From b23f9ad0ab7205d60da9e52c79a414581dfd6acc Mon Sep 17 00:00:00 2001 From: Yujie Xu Date: Thu, 12 Sep 2024 10:39:44 -0700 Subject: [PATCH 03/16] change root solver to BisectionThenRegulaFalsi for speed --- src/EnergyPlus/ExtendedHI.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/EnergyPlus/ExtendedHI.cc b/src/EnergyPlus/ExtendedHI.cc index a585e8c37a0..2579fa49c59 100644 --- a/src/EnergyPlus/ExtendedHI.cc +++ b/src/EnergyPlus/ExtendedHI.cc @@ -522,7 +522,7 @@ namespace ExtendedHI { // The function computes the extended heat index, in Kelvinn auto const HVACSystemRootSolverBackup = state.dataRootFinder->HVACSystemRootFinding.HVACSystemRootSolver; - state.dataRootFinder->HVACSystemRootFinding.HVACSystemRootSolver = HVACSystemRootSolverAlgorithm::Bisection; + state.dataRootFinder->HVACSystemRootFinding.HVACSystemRootSolver = HVACSystemRootSolverAlgorithm::BisectionThenRegulaFalsi; int eqvar_name = find_eqvar_name(state, Ta, RH); Real64 eqvar_value = find_eqvar_value(state, Ta, RH); From bd977166cf7fafccd3c6cfb75c1b8f2dfaccadd4 Mon Sep 17 00:00:00 2001 From: Yujie Xu Date: Thu, 12 Sep 2024 16:19:44 -0700 Subject: [PATCH 04/16] save Zs(Rs) value in a variable --- src/EnergyPlus/ExtendedHI.cc | 60 ++++++++++++++++++++---------------- 1 file changed, 34 insertions(+), 26 deletions(-) diff --git a/src/EnergyPlus/ExtendedHI.cc b/src/EnergyPlus/ExtendedHI.cc index 2579fa49c59..0dd04c3e7f8 100644 --- a/src/EnergyPlus/ExtendedHI.cc +++ b/src/EnergyPlus/ExtendedHI.cc @@ -171,7 +171,8 @@ namespace ExtendedHI { Real64 phi = 0.84; Real64 Pa = RH * pvstar(Ta); Real64 Rs = 0.0387; - Real64 m = (Pc - Pa) / (Zs(Rs) + Za); + Real64 ZsRs = Zs(Rs); + Real64 m = (Pc - Pa) / (ZsRs + Za); Real64 Ts; int SolFla; General::SolveRoot( @@ -180,7 +181,7 @@ namespace ExtendedHI { maxIter, SolFla, Ts, - [&](Real64 Ts) { return (Ts - Ta) / Ra(Ts, Ta) + (Pc - Pa) / (Zs(Rs) + Za) - (Tc - Ts) / Rs; }, + [&](Real64 Ts) { return (Ts - Ta) / Ra(Ts, Ta) + (Pc - Pa) / (ZsRs + Za) - (Tc - Ts) / Rs; }, std::max(0.0, std::min(Tc, Ta) - Rs * std::abs(m)), std::max(Tc, Ta) + Rs * std::abs(m)); Real64 flux1 = Q - Qv(Ta, Pa) - (1.0 - phi) * (Tc - Ts) / Rs; @@ -195,8 +196,9 @@ namespace ExtendedHI { Real64 Pa = RH * pvstar(Ta); Real64 Rs = 0.0387; Real64 phi = 0.84; - Real64 m_bar = (Pc - Pa) / (Zs(Rs) + Za_bar); - Real64 m = (Pc - Pa) / (Zs(Rs) + Za); + Real64 ZsRs = Zs(Rs); + Real64 m_bar = (Pc - Pa) / (ZsRs + Za_bar); + Real64 m = (Pc - Pa) / (ZsRs + Za); Real64 Ts; int SolFla; General::SolveRoot( @@ -205,7 +207,7 @@ namespace ExtendedHI { maxIter, SolFla, Ts, - [&](Real64 Ts) { return (Ts - Ta) / Ra(Ts, Ta) + (Pc - Pa) / (Zs(Rs) + Za) - (Tc - Ts) / Rs; }, + [&](Real64 Ts) { return (Ts - Ta) / Ra(Ts, Ta) + (Pc - Pa) / (ZsRs + Za) - (Tc - Ts) / Rs; }, std::max(0.0, std::min(Tc, Ta) - Rs * std::abs(m)), std::max(Tc, Ta) + Rs * std::abs(m)); Real64 Tf; @@ -215,7 +217,7 @@ namespace ExtendedHI { maxIter, SolFla, Tf, - [&](Real64 Tf) { return (Tf - Ta) / Ra_bar(Tf, Ta) + (Pc - Pa) / (Zs(Rs) + Za_bar) - (Tc - Tf) / Rs; }, + [&](Real64 Tf) { return (Tf - Ta) / Ra_bar(Tf, Ta) + (Pc - Pa) / (ZsRs + Za_bar) - (Tc - Tf) / Rs; }, std::max(0.0, std::min(Tc, Ta) - Rs * std::abs(m_bar)), std::max(Tc, Ta) + Rs * std::abs(m_bar)); Real64 flux1 = Q - Qv(Ta, Pa) - (1.0 - phi) * (Tc - Ts) / Rs; @@ -232,7 +234,7 @@ namespace ExtendedHI { SolFla, Tf, [&](Real64 Tf) { - return (Tf - Ta) / Ra_bar(Tf, Ta) + (Pc - Pa) * (Tf - Ta) / ((Zs(Rs) + Za_bar) * (Tf - Ta) + r * Ra_bar(Tf, Ta) * (Ts_bar - Tf)) - + return (Tf - Ta) / Ra_bar(Tf, Ta) + (Pc - Pa) * (Tf - Ta) / ((ZsRs + Za_bar) * (Tf - Ta) + r * Ra_bar(Tf, Ta) * (Ts_bar - Tf)) - (Tc - Ts_bar) / Rs; }, Ta, @@ -250,8 +252,9 @@ namespace ExtendedHI { Real64 Pa = RH * pvstar(Ta); Real64 phi = 0.84; Real64 Rs = 0.0387; - Real64 m = (Pc - Pa) / (Zs(Rs) + Za); - Real64 m_bar = (Pc - Pa) / (Zs(Rs) + Za_bar); + Real64 ZsRs = Zs(Rs); + Real64 m = (Pc - Pa) / (ZsRs + Za); + Real64 m_bar = (Pc - Pa) / (ZsRs + Za_bar); Real64 Ts; int SolFla; General::SolveRoot( @@ -260,7 +263,7 @@ namespace ExtendedHI { maxIter, SolFla, Ts, - [&](Real64 Ts) { return (Ts - Ta) / Ra(Ts, Ta) + (Pc - Pa) / (Zs(Rs) + Za) - (Tc - Ts) / Rs; }, + [&](Real64 Ts) { return (Ts - Ta) / Ra(Ts, Ta) + (Pc - Pa) / (ZsRs + Za) - (Tc - Ts) / Rs; }, std::max(0.0, std::min(Tc, Ta) - Rs * std::abs(m)), std::max(Tc, Ta) + Rs * std::abs(m)); Real64 Tf; @@ -270,7 +273,7 @@ namespace ExtendedHI { maxIter, SolFla, Tf, - [&](Real64 Tf) { return (Tf - Ta) / Ra_bar(Tf, Ta) + (Pc - Pa) / (Zs(Rs) + Za_bar) - (Tc - Tf) / Rs; }, + [&](Real64 Tf) { return (Tf - Ta) / Ra_bar(Tf, Ta) + (Pc - Pa) / (ZsRs + Za_bar) - (Tc - Tf) / Rs; }, std::max(0.0, std::min(Tc, Ta) - Rs * std::abs(m_bar)), std::max(Tc, Ta) + Rs * std::abs(m_bar)); Real64 flux1 = Q - Qv(Ta, Pa) - (1.0 - phi) * (Tc - Ts) / Rs; @@ -288,7 +291,8 @@ namespace ExtendedHI { 0.0, Tc); Rs = (Tc - Ts) / (Q - Qv(Ta, Pa)); - Real64 Ps = Pc - (Pc - Pa) * Zs(Rs) / (Zs(Rs) + Za_un); + ZsRs = Zs(Rs); + Real64 Ps = Pc - (Pc - Pa) * ZsRs / (ZsRs + Za_un); if (Ps > phi_salt * pvstar(Ts)) { General::SolveRoot( state, @@ -313,9 +317,10 @@ namespace ExtendedHI { Real64 dTcdt = 0.0; Real64 Pa = RH * pvstar(Ta); Real64 Rs = 0.0387; + Real64 ZsRs = Zs(Rs); Real64 phi = 0.84; - Real64 m = (Pc - Pa) / (Zs(Rs) + Za); - Real64 m_bar = (Pc - Pa) / (Zs(Rs) + Za_bar); + Real64 m = (Pc - Pa) / (ZsRs + Za); + Real64 m_bar = (Pc - Pa) / (ZsRs + Za_bar); Real64 Ts; int SolFla; General::SolveRoot( @@ -324,7 +329,7 @@ namespace ExtendedHI { maxIter, SolFla, Ts, - [&](Real64 Ts) { return (Ts - Ta) / Ra(Ts, Ta) + (Pc - Pa) / (Zs(Rs) + Za) - (Tc - Ts) / Rs; }, + [&](Real64 Ts) { return (Ts - Ta) / Ra(Ts, Ta) + (Pc - Pa) / (ZsRs + Za) - (Tc - Ts) / Rs; }, std::max(0.0, std::min(Tc, Ta) - Rs * std::abs(m)), std::max(Tc, Ta) + Rs * std::abs(m)); Real64 Tf; @@ -334,7 +339,7 @@ namespace ExtendedHI { maxIter, SolFla, Tf, - [&](Real64 Tf) { return (Tf - Ta) / Ra_bar(Tf, Ta) + (Pc - Pa) / (Zs(Rs) + Za_bar) - (Tc - Tf) / Rs; }, + [&](Real64 Tf) { return (Tf - Ta) / Ra_bar(Tf, Ta) + (Pc - Pa) / (ZsRs + Za_bar) - (Tc - Tf) / Rs; }, std::max(0.0, std::min(Tc, Ta) - Rs * std::abs(m_bar)), std::max(Tc, Ta) + Rs * std::abs(m_bar)); Real64 flux1 = Q - Qv(Ta, Pa) - (1.0 - phi) * (Tc - Ts) / Rs; @@ -351,9 +356,10 @@ namespace ExtendedHI { Real64 Pa = RH * pvstar(Ta); Real64 Rs = 0.0387; + Real64 ZsRs = Zs(Rs); Real64 phi = 0.84; - Real64 m = (Pc - Pa) / (Zs(Rs) + Za); - Real64 m_bar = (Pc - Pa) / (Zs(Rs) + Za_bar); + Real64 m = (Pc - Pa) / (ZsRs + Za); + Real64 m_bar = (Pc - Pa) / (ZsRs + Za_bar); int SolFla; Real64 Ts; @@ -363,7 +369,7 @@ namespace ExtendedHI { maxIter, SolFla, Ts, - [&](Real64 Ts) { return (Ts - Ta) / Ra(Ts, Ta) + (Pc - Pa) / (Zs(Rs) + Za) - (Tc - Ts) / Rs; }, + [&](Real64 Ts) { return (Ts - Ta) / Ra(Ts, Ta) + (Pc - Pa) / (ZsRs + Za) - (Tc - Ts) / Rs; }, std::max(0.0, std::min(Tc, Ta) - Rs * std::abs(m)), std::max(Tc, Ta) + Rs * std::abs(m)); @@ -374,7 +380,7 @@ namespace ExtendedHI { maxIter, SolFla, Tf, - [&](Real64 Tf) { return (Tf - Ta) / Ra_bar(Tf, Ta) + (Pc - Pa) / (Zs(Rs) + Za_bar) - (Tc - Tf) / Rs; }, + [&](Real64 Tf) { return (Tf - Ta) / Ra_bar(Tf, Ta) + (Pc - Pa) / (ZsRs + Za_bar) - (Tc - Tf) / Rs; }, std::max(0.0, std::min(Tc, Ta) - Rs * std::abs(m_bar)), std::max(Tc, Ta) + Rs * std::abs(m_bar)); Real64 flux1 = Q - Qv(Ta, Pa) - (1.0 - phi) * (Tc - Ts) / Rs; @@ -401,8 +407,9 @@ namespace ExtendedHI { Real64 Rs = 0.0387; Real64 phi = 0.84; Real64 dTcdt = 0.0; - Real64 m = (Pc - Pa) / (Zs(Rs) + Za); - Real64 m_bar = (Pc - Pa) / (Zs(Rs) + Za_bar); + Real64 ZsRs = Zs(Rs); + Real64 m = (Pc - Pa) / (ZsRs + Za); + Real64 m_bar = (Pc - Pa) / (ZsRs + Za_bar); int SolFla; Real64 Ts; @@ -412,7 +419,7 @@ namespace ExtendedHI { maxIter, SolFla, Ts, - [&](Real64 Ts) { return (Ts - Ta) / Ra(Ts, Ta) + (Pc - Pa) / (Zs(Rs) + Za) - (Tc - Ts) / Rs; }, + [&](Real64 Ts) { return (Ts - Ta) / Ra(Ts, Ta) + (Pc - Pa) / (ZsRs + Za) - (Tc - Ts) / Rs; }, std::max(0.0, std::min(Tc, Ta) - Rs * std::abs(m)), std::max(Tc, Ta) + Rs * std::abs(m)); @@ -423,7 +430,7 @@ namespace ExtendedHI { maxIter, SolFla, Tf, - [&](Real64 Tf) { return (Tf - Ta) / Ra_bar(Tf, Ta) + (Pc - Pa) / (Zs(Rs) + Za_bar) - (Tc - Tf) / Rs; }, + [&](Real64 Tf) { return (Tf - Ta) / Ra_bar(Tf, Ta) + (Pc - Pa) / (ZsRs + Za_bar) - (Tc - Tf) / Rs; }, std::max(0.0, std::min(Tc, Ta) - Rs * std::abs(m_bar)), std::max(Tc, Ta) + Rs * std::abs(m_bar)); Real64 flux1 = Q - Qv(Ta, Pa) - (1.0 - phi) * (Tc - Ts) / Rs; @@ -442,7 +449,7 @@ namespace ExtendedHI { SolFla, Tf, [&](Real64 Tf) { - return (Tf - Ta) / Ra_bar(Tf, Ta) + (Pc - Pa) * (Tf - Ta) / ((Zs(Rs) + Za_bar) * (Tf - Ta) + r * Ra_bar(Tf, Ta) * (Ts_bar - Tf)) - + return (Tf - Ta) / Ra_bar(Tf, Ta) + (Pc - Pa) * (Tf - Ta) / ((ZsRs + Za_bar) * (Tf - Ta) + r * Ra_bar(Tf, Ta) * (Ts_bar - Tf)) - (Tc - Ts_bar) / Rs; }, Ta, @@ -462,7 +469,8 @@ namespace ExtendedHI { 0.0, Tc); Rs = (Tc - Ts) / (Q - Qv(Ta, Pa)); - Real64 Ps = Pc - (Pc - Pa) * Zs(Rs) / (Zs(Rs) + Za_un); + ZsRs = Zs(Rs); + Real64 Ps = Pc - (Pc - Pa) * ZsRs / (ZsRs + Za_un); if (Ps > phi_salt * pvstar(Ts)) { General::SolveRoot( state, From 5e96092686416079491c9e1820d5f7bc6a572e66 Mon Sep 17 00:00:00 2001 From: Yujie Xu Date: Thu, 12 Sep 2024 16:51:20 -0700 Subject: [PATCH 05/16] find eqvar name and value together --- src/EnergyPlus/ExtendedHI.cc | 59 +++++------------------------------- src/EnergyPlus/ExtendedHI.hh | 3 +- 2 files changed, 8 insertions(+), 54 deletions(-) diff --git a/src/EnergyPlus/ExtendedHI.cc b/src/EnergyPlus/ExtendedHI.cc index 0dd04c3e7f8..1e71b9ad173 100644 --- a/src/EnergyPlus/ExtendedHI.cc +++ b/src/EnergyPlus/ExtendedHI.cc @@ -351,57 +351,8 @@ namespace ExtendedHI { return dTcdt; } - int find_eqvar_name(EnergyPlusData &state, Real64 Ta, Real64 RH) - { - - Real64 Pa = RH * pvstar(Ta); - Real64 Rs = 0.0387; - Real64 ZsRs = Zs(Rs); - Real64 phi = 0.84; - Real64 m = (Pc - Pa) / (ZsRs + Za); - Real64 m_bar = (Pc - Pa) / (ZsRs + Za_bar); - - int SolFla; - Real64 Ts; - General::SolveRoot( - state, - tol, - maxIter, - SolFla, - Ts, - [&](Real64 Ts) { return (Ts - Ta) / Ra(Ts, Ta) + (Pc - Pa) / (ZsRs + Za) - (Tc - Ts) / Rs; }, - std::max(0.0, std::min(Tc, Ta) - Rs * std::abs(m)), - std::max(Tc, Ta) + Rs * std::abs(m)); - - Real64 Tf; - General::SolveRoot( - state, - tol, - maxIter, - SolFla, - Tf, - [&](Real64 Tf) { return (Tf - Ta) / Ra_bar(Tf, Ta) + (Pc - Pa) / (ZsRs + Za_bar) - (Tc - Tf) / Rs; }, - std::max(0.0, std::min(Tc, Ta) - Rs * std::abs(m_bar)), - std::max(Tc, Ta) + Rs * std::abs(m_bar)); - Real64 flux1 = Q - Qv(Ta, Pa) - (1.0 - phi) * (Tc - Ts) / Rs; - Real64 flux2 = Q - Qv(Ta, Pa) - (1.0 - phi) * (Tc - Ts) / Rs - phi * (Tc - Tf) / Rs; - - if (flux1 <= 0.0) { - return static_cast(EqvarName::Phi); - } else if (flux2 <= 0.0) { - return static_cast(EqvarName::Rf); - } else { - Real64 flux3 = Q - Qv(Ta, Pa) - (Tc - Ta) / Ra_un(Tc, Ta) - (phi_salt * pvstar(Tc) - Pa) / Za_un; - if (flux3 < 0.0) { - return static_cast(EqvarName::Rs); - } else { - return static_cast(EqvarName::DTcdt); - } - } - } - // given T and RH, returns a key and value pair - Real64 find_eqvar_value(EnergyPlusData &state, Real64 Ta, Real64 RH) + Real64 find_eqvar_name_and_value(EnergyPlusData &state, Real64 Ta, Real64 RH, int &varname) { Real64 Pa = RH * pvstar(Ta); Real64 Rs = 0.0387; @@ -438,9 +389,11 @@ namespace ExtendedHI { Real64 Rf; if (flux1 <= 0.0) { + varname = static_cast(EqvarName::Phi); phi = 1.0 - (Q - Qv(Ta, Pa)) * Rs / (Tc - Ts); return phi; } else if (flux2 <= 0.0) { + varname = static_cast(EqvarName::Rf); Real64 Ts_bar = Tc - (Q - Qv(Ta, Pa)) * Rs / phi + (1.0 / phi - 1.0) * (Tc - Ts); General::SolveRoot( state, @@ -459,6 +412,7 @@ namespace ExtendedHI { } else { Real64 flux3 = Q - Qv(Ta, Pa) - (Tc - Ta) / Ra_un(Tc, Ta) - (phi_salt * pvstar(Tc) - Pa) / Za_un; if (flux3 < 0.0) { + varname = static_cast(EqvarName::Rs); General::SolveRoot( state, tol, @@ -485,6 +439,7 @@ namespace ExtendedHI { } return Rs; } else { + varname = static_cast(EqvarName::DTcdt); Rs = 0.0; dTcdt = (1.0 / C) * flux3; return dTcdt; @@ -531,8 +486,8 @@ namespace ExtendedHI { auto const HVACSystemRootSolverBackup = state.dataRootFinder->HVACSystemRootFinding.HVACSystemRootSolver; state.dataRootFinder->HVACSystemRootFinding.HVACSystemRootSolver = HVACSystemRootSolverAlgorithm::BisectionThenRegulaFalsi; - int eqvar_name = find_eqvar_name(state, Ta, RH); - Real64 eqvar_value = find_eqvar_value(state, Ta, RH); + int eqvar_name = 0; + Real64 eqvar_value = find_eqvar_name_and_value(state, Ta, RH, eqvar_name); Real64 T = find_T(state, eqvar_name, eqvar_value); diff --git a/src/EnergyPlus/ExtendedHI.hh b/src/EnergyPlus/ExtendedHI.hh index b839ea571eb..5c4a271de88 100644 --- a/src/EnergyPlus/ExtendedHI.hh +++ b/src/EnergyPlus/ExtendedHI.hh @@ -77,8 +77,7 @@ namespace ExtendedHI { Real64 Ra(Real64 Ts, Real64 Ta); Real64 Ra_bar(Real64 Tf, Real64 Ta); Real64 Ra_un(Real64 Ts, Real64 Ta); - int find_eqvar_name(EnergyPlusData &state, Real64 Ta, Real64 RH); - Real64 find_eqvar_value(EnergyPlusData &state, Real64 Ta, Real64 RH); + Real64 find_eqvar_name_and_value(EnergyPlusData &state, Real64 Ta, Real64 RH, int &varname); Real64 find_eqvar_phi(EnergyPlusData &state, Real64 Ta, Real64 RH); Real64 find_eqvar_Rf(EnergyPlusData &state, Real64 Ta, Real64 RH); Real64 find_eqvar_rs(EnergyPlusData &state, Real64 Ta, Real64 RH); From b96c3a5c4f556b71da04140762222d08d2eb3777 Mon Sep 17 00:00:00 2001 From: Yujie Xu Date: Thu, 12 Sep 2024 17:39:35 -0700 Subject: [PATCH 06/16] update unit test find_eqvar_name and value --- tst/EnergyPlus/unit/ExtendedHI.unit.cc | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/tst/EnergyPlus/unit/ExtendedHI.unit.cc b/tst/EnergyPlus/unit/ExtendedHI.unit.cc index e2a00657cfa..5d8f94e733e 100644 --- a/tst/EnergyPlus/unit/ExtendedHI.unit.cc +++ b/tst/EnergyPlus/unit/ExtendedHI.unit.cc @@ -271,10 +271,13 @@ TEST_F(EnergyPlusFixture, extendedHI_find_eqvar) {0.02073, 0.00466, 0.01213, 0.0196, 0.02707, 0.03453}, {0.00147, 0.01691, 0.03395, 0.051, 0.06804, 0.08509}}; + int eqvar_name = 0; + Real64 eqvar_value = 0.0; for (size_t i = 0; i < Ta_values.size(); ++i) { for (size_t j = 0; j < RH_values.size(); ++j) { - EXPECT_EQ(find_eqvar_name(*state, Ta_values[i], RH_values[j]), result_0[i][j]); - EXPECT_NEAR(find_eqvar_value(*state, Ta_values[i], RH_values[j]), result_1[i][j], tol); + eqvar_value = find_eqvar_name_and_value(*state, Ta_values[i], RH_values[j], eqvar_name); + EXPECT_EQ(eqvar_name, result_0[i][j]); + EXPECT_NEAR(eqvar_value, result_1[i][j], tol); } } } From 660006965463ee23abbe207c44d4a03b6471d77f Mon Sep 17 00:00:00 2001 From: Yujie Xu Date: Thu, 12 Sep 2024 18:03:16 -0700 Subject: [PATCH 07/16] save Ra_bar calculation result --- src/EnergyPlus/ExtendedHI.cc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/EnergyPlus/ExtendedHI.cc b/src/EnergyPlus/ExtendedHI.cc index 1e71b9ad173..8f63eb0785c 100644 --- a/src/EnergyPlus/ExtendedHI.cc +++ b/src/EnergyPlus/ExtendedHI.cc @@ -234,7 +234,8 @@ namespace ExtendedHI { SolFla, Tf, [&](Real64 Tf) { - return (Tf - Ta) / Ra_bar(Tf, Ta) + (Pc - Pa) * (Tf - Ta) / ((ZsRs + Za_bar) * (Tf - Ta) + r * Ra_bar(Tf, Ta) * (Ts_bar - Tf)) - + Real64 Ra_barTfTa = Ra_bar(Tf, Ta); + return (Tf - Ta) / Ra_barTfTa + (Pc - Pa) * (Tf - Ta) / ((ZsRs + Za_bar) * (Tf - Ta) + r * Ra_barTfTa * (Ts_bar - Tf)) - (Tc - Ts_bar) / Rs; }, Ta, @@ -402,7 +403,8 @@ namespace ExtendedHI { SolFla, Tf, [&](Real64 Tf) { - return (Tf - Ta) / Ra_bar(Tf, Ta) + (Pc - Pa) * (Tf - Ta) / ((ZsRs + Za_bar) * (Tf - Ta) + r * Ra_bar(Tf, Ta) * (Ts_bar - Tf)) - + Real64 Ra_barTfTa = Ra_bar(Tf, Ta); + return (Tf - Ta) / Ra_barTfTa + (Pc - Pa) * (Tf - Ta) / ((ZsRs + Za_bar) * (Tf - Ta) + r * Ra_barTfTa * (Ts_bar - Tf)) - (Tc - Ts_bar) / Rs; }, Ta, From 58a77d92d15c64d0e2917ef546ba3336eda4cd1b Mon Sep 17 00:00:00 2001 From: Yujie Xu Date: Thu, 12 Sep 2024 20:57:39 -0700 Subject: [PATCH 08/16] restrict domain of extended HI application --- src/EnergyPlus/HeatBalanceSurfaceManager.cc | 34 +++++++++++++++++++-- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/src/EnergyPlus/HeatBalanceSurfaceManager.cc b/src/EnergyPlus/HeatBalanceSurfaceManager.cc index 3faf6e3dda9..edc353eb40d 100644 --- a/src/EnergyPlus/HeatBalanceSurfaceManager.cc +++ b/src/EnergyPlus/HeatBalanceSurfaceManager.cc @@ -5520,10 +5520,38 @@ void CalcThermalResilience(EnergyPlusData &state) for (int ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) { Real64 const ZoneT = state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneNum).ZTAV; Real64 const ZoneW = state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneNum).airHumRatAvg; - Real64 const ZoneRH = Psychrometrics::PsyRhFnTdbWPb(state, ZoneT, ZoneW, state.dataEnvrn->OutBaroPress); + Real64 const ZoneRH = Psychrometrics::PsyRhFnTdbWPb(state, ZoneT, ZoneW, state.dataEnvrn->OutBaroPress) * 100.0; Real64 const ZoneTF = ZoneT * (9.0 / 5.0) + 32.0; - // calculate extended heat index - state.dataHeatBal->Resilience(ZoneNum).ZoneHeatIndex = ExtendedHI::heatindex(state, ZoneT + Constant::Kelvin, ZoneRH) - Constant::Kelvin; + if (ZoneTF * 2.7 + 109.1 - ZoneRH * 100.0 > 0.0) { + Real64 constexpr c1 = -42.379; + Real64 constexpr c2 = 2.04901523; + Real64 constexpr c3 = 10.14333127; + Real64 constexpr c4 = -.22475541; + Real64 constexpr c5 = -.00683783; + Real64 constexpr c6 = -.05481717; + Real64 constexpr c7 = .00122874; + Real64 constexpr c8 = .00085282; + Real64 constexpr c9 = -.00000199; + Real64 HI; + + if (ZoneTF < 80) { + HI = 0.5 * (ZoneTF + 61.0 + (ZoneTF - 68.0) * 1.2 + (ZoneRH * 0.094)); + } else { + HI = c1 + c2 * ZoneTF + c3 * ZoneRH + c4 * ZoneTF * ZoneRH + c5 * ZoneTF * ZoneTF + c6 * ZoneRH * ZoneRH + + c7 * ZoneTF * ZoneTF * ZoneRH + c8 * ZoneTF * ZoneRH * ZoneRH + c9 * ZoneTF * ZoneTF * ZoneRH * ZoneRH; + if (ZoneRH < 13 && ZoneTF < 112) { + HI -= (13 - ZoneRH) / 4 * std::sqrt((17 - abs(ZoneTF - 95)) / 17); + } else if (ZoneRH > 85 && ZoneTF < 87) { + HI += (ZoneRH - 85) / 10 * (87 - ZoneTF) / 5; + } + } + HI = (HI - 32.0) * (5.0 / 9.0); + state.dataHeatBal->Resilience(ZoneNum).ZoneHeatIndex = HI; + } else { + // calculate extended heat index + state.dataHeatBal->Resilience(ZoneNum).ZoneHeatIndex = + ExtendedHI::heatindex(state, ZoneT + Constant::Kelvin, ZoneRH / 100.0) - Constant::Kelvin; + } } } if (state.dataHeatBalSurfMgr->reportVarHumidex || state.dataOutRptTab->displayThermalResilienceSummary) { From 16faa3137327f745939434b8b68750da66aebb8a Mon Sep 17 00:00:00 2001 From: Yujie Xu Date: Thu, 12 Sep 2024 23:57:51 -0700 Subject: [PATCH 09/16] Revert "restrict domain of extended HI application" This reverts commit 58a77d92d15c64d0e2917ef546ba3336eda4cd1b. --- src/EnergyPlus/HeatBalanceSurfaceManager.cc | 34 ++------------------- 1 file changed, 3 insertions(+), 31 deletions(-) diff --git a/src/EnergyPlus/HeatBalanceSurfaceManager.cc b/src/EnergyPlus/HeatBalanceSurfaceManager.cc index edc353eb40d..3faf6e3dda9 100644 --- a/src/EnergyPlus/HeatBalanceSurfaceManager.cc +++ b/src/EnergyPlus/HeatBalanceSurfaceManager.cc @@ -5520,38 +5520,10 @@ void CalcThermalResilience(EnergyPlusData &state) for (int ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) { Real64 const ZoneT = state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneNum).ZTAV; Real64 const ZoneW = state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneNum).airHumRatAvg; - Real64 const ZoneRH = Psychrometrics::PsyRhFnTdbWPb(state, ZoneT, ZoneW, state.dataEnvrn->OutBaroPress) * 100.0; + Real64 const ZoneRH = Psychrometrics::PsyRhFnTdbWPb(state, ZoneT, ZoneW, state.dataEnvrn->OutBaroPress); Real64 const ZoneTF = ZoneT * (9.0 / 5.0) + 32.0; - if (ZoneTF * 2.7 + 109.1 - ZoneRH * 100.0 > 0.0) { - Real64 constexpr c1 = -42.379; - Real64 constexpr c2 = 2.04901523; - Real64 constexpr c3 = 10.14333127; - Real64 constexpr c4 = -.22475541; - Real64 constexpr c5 = -.00683783; - Real64 constexpr c6 = -.05481717; - Real64 constexpr c7 = .00122874; - Real64 constexpr c8 = .00085282; - Real64 constexpr c9 = -.00000199; - Real64 HI; - - if (ZoneTF < 80) { - HI = 0.5 * (ZoneTF + 61.0 + (ZoneTF - 68.0) * 1.2 + (ZoneRH * 0.094)); - } else { - HI = c1 + c2 * ZoneTF + c3 * ZoneRH + c4 * ZoneTF * ZoneRH + c5 * ZoneTF * ZoneTF + c6 * ZoneRH * ZoneRH + - c7 * ZoneTF * ZoneTF * ZoneRH + c8 * ZoneTF * ZoneRH * ZoneRH + c9 * ZoneTF * ZoneTF * ZoneRH * ZoneRH; - if (ZoneRH < 13 && ZoneTF < 112) { - HI -= (13 - ZoneRH) / 4 * std::sqrt((17 - abs(ZoneTF - 95)) / 17); - } else if (ZoneRH > 85 && ZoneTF < 87) { - HI += (ZoneRH - 85) / 10 * (87 - ZoneTF) / 5; - } - } - HI = (HI - 32.0) * (5.0 / 9.0); - state.dataHeatBal->Resilience(ZoneNum).ZoneHeatIndex = HI; - } else { - // calculate extended heat index - state.dataHeatBal->Resilience(ZoneNum).ZoneHeatIndex = - ExtendedHI::heatindex(state, ZoneT + Constant::Kelvin, ZoneRH / 100.0) - Constant::Kelvin; - } + // calculate extended heat index + state.dataHeatBal->Resilience(ZoneNum).ZoneHeatIndex = ExtendedHI::heatindex(state, ZoneT + Constant::Kelvin, ZoneRH) - Constant::Kelvin; } } if (state.dataHeatBalSurfMgr->reportVarHumidex || state.dataOutRptTab->displayThermalResilienceSummary) { From 4f4809f4777513d8db5240bf383a138c2df38612 Mon Sep 17 00:00:00 2001 From: Yujie Xu Date: Fri, 13 Sep 2024 00:11:13 -0700 Subject: [PATCH 10/16] try using a shorter termination for bisection solver --- src/EnergyPlus/ExtendedHI.cc | 2 +- src/EnergyPlus/General.cc | 8 ++++++++ src/EnergyPlus/HVACSystemRootFindingAlgorithm.hh | 1 + 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/EnergyPlus/ExtendedHI.cc b/src/EnergyPlus/ExtendedHI.cc index 1e71b9ad173..e9b9f7a7a91 100644 --- a/src/EnergyPlus/ExtendedHI.cc +++ b/src/EnergyPlus/ExtendedHI.cc @@ -485,7 +485,7 @@ namespace ExtendedHI { // The function computes the extended heat index, in Kelvinn auto const HVACSystemRootSolverBackup = state.dataRootFinder->HVACSystemRootFinding.HVACSystemRootSolver; - state.dataRootFinder->HVACSystemRootFinding.HVACSystemRootSolver = HVACSystemRootSolverAlgorithm::BisectionThenRegulaFalsi; + state.dataRootFinder->HVACSystemRootFinding.HVACSystemRootSolver = HVACSystemRootSolverAlgorithm::ShortBisectionThenRegulaFalsi; int eqvar_name = 0; Real64 eqvar_value = find_eqvar_name_and_value(state, Ta, RH, eqvar_name); diff --git a/src/EnergyPlus/General.cc b/src/EnergyPlus/General.cc index 65a1dd95fed..a9d287a0df0 100644 --- a/src/EnergyPlus/General.cc +++ b/src/EnergyPlus/General.cc @@ -241,6 +241,14 @@ void SolveRoot(const EnergyPlusData &state, } break; } + case HVACSystemRootSolverAlgorithm::ShortBisectionThenRegulaFalsi: { + if (NIte < 3) { + XTemp = (X1 + X0) / 2.0; + } else { + XTemp = (Y0 * X1 - Y1 * X0) / DY; + } + break; + } default: { XTemp = (Y0 * X1 - Y1 * X0) / DY; } diff --git a/src/EnergyPlus/HVACSystemRootFindingAlgorithm.hh b/src/EnergyPlus/HVACSystemRootFindingAlgorithm.hh index 6138bacc004..3487423d534 100644 --- a/src/EnergyPlus/HVACSystemRootFindingAlgorithm.hh +++ b/src/EnergyPlus/HVACSystemRootFindingAlgorithm.hh @@ -59,6 +59,7 @@ enum class HVACSystemRootSolverAlgorithm : int RegulaFalsiThenBisection, BisectionThenRegulaFalsi, Alternation, + ShortBisectionThenRegulaFalsi, Num }; struct HVACSystemRootFindingAlgorithm From ec8f0babb51302212ceeed61cdeed0ca33db43f4 Mon Sep 17 00:00:00 2001 From: Yujie Xu Date: Fri, 13 Sep 2024 09:18:04 -0700 Subject: [PATCH 11/16] Try using RegulaFalsiThenBisection --- src/EnergyPlus/ExtendedHI.cc | 2 +- tst/EnergyPlus/unit/ExtendedHI.unit.cc | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/EnergyPlus/ExtendedHI.cc b/src/EnergyPlus/ExtendedHI.cc index 217fa03dd65..602efab4d92 100644 --- a/src/EnergyPlus/ExtendedHI.cc +++ b/src/EnergyPlus/ExtendedHI.cc @@ -487,7 +487,7 @@ namespace ExtendedHI { // The function computes the extended heat index, in Kelvinn auto const HVACSystemRootSolverBackup = state.dataRootFinder->HVACSystemRootFinding.HVACSystemRootSolver; - state.dataRootFinder->HVACSystemRootFinding.HVACSystemRootSolver = HVACSystemRootSolverAlgorithm::ShortBisectionThenRegulaFalsi; + state.dataRootFinder->HVACSystemRootFinding.HVACSystemRootSolver = HVACSystemRootSolverAlgorithm::RegulaFalsiThenBisection; int eqvar_name = 0; Real64 eqvar_value = find_eqvar_name_and_value(state, Ta, RH, eqvar_name); diff --git a/tst/EnergyPlus/unit/ExtendedHI.unit.cc b/tst/EnergyPlus/unit/ExtendedHI.unit.cc index 5d8f94e733e..e7d10422bba 100644 --- a/tst/EnergyPlus/unit/ExtendedHI.unit.cc +++ b/tst/EnergyPlus/unit/ExtendedHI.unit.cc @@ -340,7 +340,8 @@ TEST_F(EnergyPlusFixture, extendedHI_heatindex) for (size_t i = 0; i < T_values.size(); ++i) { for (size_t j = 0; j < RH_values.size(); ++j) { Real64 HI = HI_values[i][j]; - EXPECT_NEAR(ExtendedHI::heatindex(*state, T_values[i], RH_values[j]), HI, tol); + // fixme: temporary comment out to try other solver + // EXPECT_NEAR(ExtendedHI::heatindex(*state, T_values[i], RH_values[j]), HI, tol); } } } From 9e32af5bd2034644ff24ad5cab1e263942d32d9d Mon Sep 17 00:00:00 2001 From: Yujie Xu Date: Fri, 13 Sep 2024 09:37:58 -0700 Subject: [PATCH 12/16] Revert "save Ra_bar calculation result" This reverts commit 660006965463ee23abbe207c44d4a03b6471d77f. --- src/EnergyPlus/ExtendedHI.cc | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/EnergyPlus/ExtendedHI.cc b/src/EnergyPlus/ExtendedHI.cc index 602efab4d92..0c107f01de5 100644 --- a/src/EnergyPlus/ExtendedHI.cc +++ b/src/EnergyPlus/ExtendedHI.cc @@ -234,8 +234,7 @@ namespace ExtendedHI { SolFla, Tf, [&](Real64 Tf) { - Real64 Ra_barTfTa = Ra_bar(Tf, Ta); - return (Tf - Ta) / Ra_barTfTa + (Pc - Pa) * (Tf - Ta) / ((ZsRs + Za_bar) * (Tf - Ta) + r * Ra_barTfTa * (Ts_bar - Tf)) - + return (Tf - Ta) / Ra_bar(Tf, Ta) + (Pc - Pa) * (Tf - Ta) / ((ZsRs + Za_bar) * (Tf - Ta) + r * Ra_bar(Tf, Ta) * (Ts_bar - Tf)) - (Tc - Ts_bar) / Rs; }, Ta, @@ -403,8 +402,7 @@ namespace ExtendedHI { SolFla, Tf, [&](Real64 Tf) { - Real64 Ra_barTfTa = Ra_bar(Tf, Ta); - return (Tf - Ta) / Ra_barTfTa + (Pc - Pa) * (Tf - Ta) / ((ZsRs + Za_bar) * (Tf - Ta) + r * Ra_barTfTa * (Ts_bar - Tf)) - + return (Tf - Ta) / Ra_bar(Tf, Ta) + (Pc - Pa) * (Tf - Ta) / ((ZsRs + Za_bar) * (Tf - Ta) + r * Ra_bar(Tf, Ta) * (Ts_bar - Tf)) - (Tc - Ts_bar) / Rs; }, Ta, From f488176c5fcb82d7eee12f2f65bc92f85fe3f181 Mon Sep 17 00:00:00 2001 From: Yujie Xu Date: Fri, 13 Sep 2024 09:41:33 -0700 Subject: [PATCH 13/16] Revert "Try using RegulaFalsiThenBisection" This reverts commit ec8f0babb51302212ceeed61cdeed0ca33db43f4. --- src/EnergyPlus/ExtendedHI.cc | 2 +- tst/EnergyPlus/unit/ExtendedHI.unit.cc | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/EnergyPlus/ExtendedHI.cc b/src/EnergyPlus/ExtendedHI.cc index 0c107f01de5..e9b9f7a7a91 100644 --- a/src/EnergyPlus/ExtendedHI.cc +++ b/src/EnergyPlus/ExtendedHI.cc @@ -485,7 +485,7 @@ namespace ExtendedHI { // The function computes the extended heat index, in Kelvinn auto const HVACSystemRootSolverBackup = state.dataRootFinder->HVACSystemRootFinding.HVACSystemRootSolver; - state.dataRootFinder->HVACSystemRootFinding.HVACSystemRootSolver = HVACSystemRootSolverAlgorithm::RegulaFalsiThenBisection; + state.dataRootFinder->HVACSystemRootFinding.HVACSystemRootSolver = HVACSystemRootSolverAlgorithm::ShortBisectionThenRegulaFalsi; int eqvar_name = 0; Real64 eqvar_value = find_eqvar_name_and_value(state, Ta, RH, eqvar_name); diff --git a/tst/EnergyPlus/unit/ExtendedHI.unit.cc b/tst/EnergyPlus/unit/ExtendedHI.unit.cc index e7d10422bba..5d8f94e733e 100644 --- a/tst/EnergyPlus/unit/ExtendedHI.unit.cc +++ b/tst/EnergyPlus/unit/ExtendedHI.unit.cc @@ -340,8 +340,7 @@ TEST_F(EnergyPlusFixture, extendedHI_heatindex) for (size_t i = 0; i < T_values.size(); ++i) { for (size_t j = 0; j < RH_values.size(); ++j) { Real64 HI = HI_values[i][j]; - // fixme: temporary comment out to try other solver - // EXPECT_NEAR(ExtendedHI::heatindex(*state, T_values[i], RH_values[j]), HI, tol); + EXPECT_NEAR(ExtendedHI::heatindex(*state, T_values[i], RH_values[j]), HI, tol); } } } From b813d6ed7c7fe7daf1ee9151f84acff435b37913 Mon Sep 17 00:00:00 2001 From: Yujie Xu Date: Fri, 13 Sep 2024 10:28:02 -0700 Subject: [PATCH 14/16] Revert "Revert "restrict domain of extended HI application"" This reverts commit 16faa3137327f745939434b8b68750da66aebb8a. --- src/EnergyPlus/HeatBalanceSurfaceManager.cc | 34 +++++++++++++++++++-- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/src/EnergyPlus/HeatBalanceSurfaceManager.cc b/src/EnergyPlus/HeatBalanceSurfaceManager.cc index 3faf6e3dda9..edc353eb40d 100644 --- a/src/EnergyPlus/HeatBalanceSurfaceManager.cc +++ b/src/EnergyPlus/HeatBalanceSurfaceManager.cc @@ -5520,10 +5520,38 @@ void CalcThermalResilience(EnergyPlusData &state) for (int ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) { Real64 const ZoneT = state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneNum).ZTAV; Real64 const ZoneW = state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneNum).airHumRatAvg; - Real64 const ZoneRH = Psychrometrics::PsyRhFnTdbWPb(state, ZoneT, ZoneW, state.dataEnvrn->OutBaroPress); + Real64 const ZoneRH = Psychrometrics::PsyRhFnTdbWPb(state, ZoneT, ZoneW, state.dataEnvrn->OutBaroPress) * 100.0; Real64 const ZoneTF = ZoneT * (9.0 / 5.0) + 32.0; - // calculate extended heat index - state.dataHeatBal->Resilience(ZoneNum).ZoneHeatIndex = ExtendedHI::heatindex(state, ZoneT + Constant::Kelvin, ZoneRH) - Constant::Kelvin; + if (ZoneTF * 2.7 + 109.1 - ZoneRH * 100.0 > 0.0) { + Real64 constexpr c1 = -42.379; + Real64 constexpr c2 = 2.04901523; + Real64 constexpr c3 = 10.14333127; + Real64 constexpr c4 = -.22475541; + Real64 constexpr c5 = -.00683783; + Real64 constexpr c6 = -.05481717; + Real64 constexpr c7 = .00122874; + Real64 constexpr c8 = .00085282; + Real64 constexpr c9 = -.00000199; + Real64 HI; + + if (ZoneTF < 80) { + HI = 0.5 * (ZoneTF + 61.0 + (ZoneTF - 68.0) * 1.2 + (ZoneRH * 0.094)); + } else { + HI = c1 + c2 * ZoneTF + c3 * ZoneRH + c4 * ZoneTF * ZoneRH + c5 * ZoneTF * ZoneTF + c6 * ZoneRH * ZoneRH + + c7 * ZoneTF * ZoneTF * ZoneRH + c8 * ZoneTF * ZoneRH * ZoneRH + c9 * ZoneTF * ZoneTF * ZoneRH * ZoneRH; + if (ZoneRH < 13 && ZoneTF < 112) { + HI -= (13 - ZoneRH) / 4 * std::sqrt((17 - abs(ZoneTF - 95)) / 17); + } else if (ZoneRH > 85 && ZoneTF < 87) { + HI += (ZoneRH - 85) / 10 * (87 - ZoneTF) / 5; + } + } + HI = (HI - 32.0) * (5.0 / 9.0); + state.dataHeatBal->Resilience(ZoneNum).ZoneHeatIndex = HI; + } else { + // calculate extended heat index + state.dataHeatBal->Resilience(ZoneNum).ZoneHeatIndex = + ExtendedHI::heatindex(state, ZoneT + Constant::Kelvin, ZoneRH / 100.0) - Constant::Kelvin; + } } } if (state.dataHeatBalSurfMgr->reportVarHumidex || state.dataOutRptTab->displayThermalResilienceSummary) { From 23c3005d97667f8e88627b915808715267c9b1dd Mon Sep 17 00:00:00 2001 From: Yujie Xu Date: Fri, 13 Sep 2024 10:46:27 -0700 Subject: [PATCH 15/16] fix application domain equation --- src/EnergyPlus/HeatBalanceSurfaceManager.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/EnergyPlus/HeatBalanceSurfaceManager.cc b/src/EnergyPlus/HeatBalanceSurfaceManager.cc index edc353eb40d..1875ef883d0 100644 --- a/src/EnergyPlus/HeatBalanceSurfaceManager.cc +++ b/src/EnergyPlus/HeatBalanceSurfaceManager.cc @@ -5522,7 +5522,7 @@ void CalcThermalResilience(EnergyPlusData &state) Real64 const ZoneW = state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneNum).airHumRatAvg; Real64 const ZoneRH = Psychrometrics::PsyRhFnTdbWPb(state, ZoneT, ZoneW, state.dataEnvrn->OutBaroPress) * 100.0; Real64 const ZoneTF = ZoneT * (9.0 / 5.0) + 32.0; - if (ZoneTF * 2.7 + 109.1 - ZoneRH * 100.0 > 0.0) { + if (ZoneTF * 3.0 + ZoneRH * 100.0 - 340.0 < 0.0) { Real64 constexpr c1 = -42.379; Real64 constexpr c2 = 2.04901523; Real64 constexpr c3 = 10.14333127; From ec88e02b48ebc29c8ea620c6a2bcb5873036addd Mon Sep 17 00:00:00 2001 From: Yujie Xu Date: Wed, 25 Sep 2024 17:51:30 -0700 Subject: [PATCH 16/16] Add global control of heat index method choice --- idd/Energy+.idd.in | 11 ++++++ src/EnergyPlus/DataHeatBalance.hh | 14 ++++++++ src/EnergyPlus/HeatBalanceManager.cc | 34 +++++++++++++++++++ src/EnergyPlus/HeatBalanceManager.hh | 2 ++ src/EnergyPlus/HeatBalanceSurfaceManager.cc | 2 +- ...Uncontrolled_Win_ASH55_Thermal_Comfort.idf | 3 ++ 6 files changed, 65 insertions(+), 1 deletion(-) diff --git a/idd/Energy+.idd.in b/idd/Energy+.idd.in index fa0cf2f26d9..da81362f9e2 100644 --- a/idd/Energy+.idd.in +++ b/idd/Energy+.idd.in @@ -977,6 +977,17 @@ HVACSystemRootFindingAlgorithm, \type integer \default 5 +HeatIndexAlgorithm, + \memo Specify whether the simplified or the extended method should be used + \memo Simplified: based on regression analysis carried out by Lans P. Rothfusz + \memo Extended: Based on paper by Lu & Romps + \unique-object + A1 ; \field Algorithm + \type choice + \key Simplified + \key Extended + \default Simplified + \group Compliance Objects Compliance:Building, diff --git a/src/EnergyPlus/DataHeatBalance.hh b/src/EnergyPlus/DataHeatBalance.hh index d0c04f26035..7de88a379c4 100644 --- a/src/EnergyPlus/DataHeatBalance.hh +++ b/src/EnergyPlus/DataHeatBalance.hh @@ -547,6 +547,19 @@ namespace DataHeatBalance { { } }; + + enum class HeatIndexMethod : int + { + Invalid = -1, + Simplified, + Extended, + Num + }; + static constexpr std::array(HeatIndexMethod::Num)> HeatIndexMethodUC = { + "SIMPLIFIED", + "EXTENDED", + }; + struct ZoneData : ZoneSpaceData { // Members @@ -1847,6 +1860,7 @@ struct HeatBalanceData : BaseGlobalStruct bool NoRegularMaterialsUsed = true; bool DoLatentSizing = false; // true when latent sizing is performed during zone sizing bool isAnyLatentLoad = false; + DataHeatBalance::HeatIndexMethod heatIndexMethod = DataHeatBalance::HeatIndexMethod::Simplified; Array1D ZoneListSNLoadHeatEnergy; Array1D ZoneListSNLoadCoolEnergy; diff --git a/src/EnergyPlus/HeatBalanceManager.cc b/src/EnergyPlus/HeatBalanceManager.cc index a4c2d6ceed3..2c2b3f14cd6 100644 --- a/src/EnergyPlus/HeatBalanceManager.cc +++ b/src/EnergyPlus/HeatBalanceManager.cc @@ -277,6 +277,8 @@ namespace HeatBalanceManager { GetIncidentSolarMultiplier(state, ErrorsFound); + GetHeatIndexMethod(state, ErrorsFound); + // Added SV 6/26/2013 to load scheduled surface gains GetScheduledSurfaceGains(state, ErrorsFound); @@ -2165,6 +2167,38 @@ namespace HeatBalanceManager { } } + void GetHeatIndexMethod(EnergyPlusData &state, bool &ErrorsFound) + { + static constexpr std::string_view RoutineName("GetHeatIndexMethod: "); + + Array1D_string Alphas(1); + Array1D Numbers(1); + int NumAlpha; + int NumNumber; + int IOStat; + + state.dataHeatBalMgr->CurrentModuleObject = "HeatIndexAlgorithm"; + int NumObjects = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, state.dataHeatBalMgr->CurrentModuleObject); + if (NumObjects > 0) { + state.dataInputProcessing->inputProcessor->getObjectItem(state, + state.dataHeatBalMgr->CurrentModuleObject, + 1, + Alphas, + NumAlpha, + Numbers, + NumNumber, + IOStat, + state.dataIPShortCut->lNumericFieldBlanks, + state.dataIPShortCut->lAlphaFieldBlanks, + state.dataIPShortCut->cAlphaFieldNames, + state.dataIPShortCut->cNumericFieldNames); + if (NumAlpha > 0) { + state.dataHeatBal->heatIndexMethod = + static_cast(getEnumValue(DataHeatBalance::HeatIndexMethodUC, Util::makeUPPER(Alphas(1)))); + } + } + } + void GetZoneLocalEnvData(EnergyPlusData &state, bool &ErrorsFound) // Error flag indicator (true if errors found) { // SUBROUTINE INFORMATION: diff --git a/src/EnergyPlus/HeatBalanceManager.hh b/src/EnergyPlus/HeatBalanceManager.hh index 7b415723c7b..e688bdd0f98 100644 --- a/src/EnergyPlus/HeatBalanceManager.hh +++ b/src/EnergyPlus/HeatBalanceManager.hh @@ -167,6 +167,8 @@ namespace HeatBalanceManager { void GetIncidentSolarMultiplier(EnergyPlusData &state, bool &ErrorsFound); + void GetHeatIndexMethod(EnergyPlusData &state, bool &ErrorsFound); + void GetScheduledSurfaceGains(EnergyPlusData &state, bool &ErrorsFound); // If errors found in input void CheckScheduledSurfaceGains(EnergyPlusData &state, int const ZoneNum); // Zone number for which error check will be performed diff --git a/src/EnergyPlus/HeatBalanceSurfaceManager.cc b/src/EnergyPlus/HeatBalanceSurfaceManager.cc index 1875ef883d0..f283b9f64b4 100644 --- a/src/EnergyPlus/HeatBalanceSurfaceManager.cc +++ b/src/EnergyPlus/HeatBalanceSurfaceManager.cc @@ -5522,7 +5522,7 @@ void CalcThermalResilience(EnergyPlusData &state) Real64 const ZoneW = state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneNum).airHumRatAvg; Real64 const ZoneRH = Psychrometrics::PsyRhFnTdbWPb(state, ZoneT, ZoneW, state.dataEnvrn->OutBaroPress) * 100.0; Real64 const ZoneTF = ZoneT * (9.0 / 5.0) + 32.0; - if (ZoneTF * 3.0 + ZoneRH * 100.0 - 340.0 < 0.0) { + if (state.dataHeatBal->heatIndexMethod == DataHeatBalance::HeatIndexMethod::Simplified) { Real64 constexpr c1 = -42.379; Real64 constexpr c2 = 2.04901523; Real64 constexpr c3 = 10.14333127; diff --git a/testfiles/1ZoneUncontrolled_Win_ASH55_Thermal_Comfort.idf b/testfiles/1ZoneUncontrolled_Win_ASH55_Thermal_Comfort.idf index f357a9ebc52..e0a12c4c1b3 100644 --- a/testfiles/1ZoneUncontrolled_Win_ASH55_Thermal_Comfort.idf +++ b/testfiles/1ZoneUncontrolled_Win_ASH55_Thermal_Comfort.idf @@ -653,6 +653,9 @@ 7.5, !- Y-Coordinate of Reference Point {m} 0.7; !- Z-Coordinate of Reference Point {m} + HeatIndexAlgorithm, + Simplified; + Output:Variable,*,Site Outdoor Air Barometric Pressure,hourly; Output:Variable,*,Site Outdoor Air Drybulb Temperature,hourly;