From daad34104b4cc803d39c635ace282e0a056a1bd9 Mon Sep 17 00:00:00 2001 From: Julien Marrec Date: Mon, 16 Dec 2024 20:47:40 +0100 Subject: [PATCH 1/8] Add a Pytest for #10718 and register it as a CTest --- CMakeLists.txt | 15 ++++++ idd/CMakeLists.txt | 13 ----- scripts/pytests/conftest.py | 87 ++++++++++++++++++++++++++++++ scripts/pytests/test_xml_output.py | 87 ++++++++++++++++++++++++++++++ src/EnergyPlus/CMakeLists.txt | 7 +++ 5 files changed, 196 insertions(+), 13 deletions(-) create mode 100644 scripts/pytests/conftest.py create mode 100644 scripts/pytests/test_xml_output.py diff --git a/CMakeLists.txt b/CMakeLists.txt index 7d9416a4470..122856d55d6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -228,6 +228,21 @@ if(BUILD_TESTING) endif() set_property(GLOBAL PROPERTY CTEST_TARGETS_ADDED 1) # This avoids all the CTest Nightly, Continuous, etc. tests. enable_testing() + + execute_process(COMMAND ${Python_EXECUTABLE} -m pytest --version + RESULT_VARIABLE _Pytest_STATUS + OUTPUT_VARIABLE Pytest_Version + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + if(_Pytest_STATUS AND NOT _Pytest_STATUS EQUAL 0) + message(AUTHOR_WARNING "Pytest isn't installed on your system python, so some tests won't be run. Run `${Python_EXECUTABLE} -m pip install pytest`") + set(Pytest_AVAILABLE OFF) + else() + message(VERBOSE "Found Pytest: ${Pytest_Version}") + set(Pytest_AVAILABLE ON) + endif() + endif() if(ENABLE_REGRESSION_TESTING) diff --git a/idd/CMakeLists.txt b/idd/CMakeLists.txt index aa17229ab9c..fd20f9133db 100644 --- a/idd/CMakeLists.txt +++ b/idd/CMakeLists.txt @@ -68,19 +68,6 @@ set(PREVIOUS_IDD ${PREVIOUS_IDD} PARENT_SCOPE) install(FILES "${PREVIOUS_IDD}" DESTINATION "PreProcess/IDFVersionUpdater") if (BUILD_TESTING) - execute_process(COMMAND ${Python_EXECUTABLE} -m pytest --version - RESULT_VARIABLE _Pytest_STATUS - OUTPUT_VARIABLE Pytest_Version - ERROR_QUIET - OUTPUT_STRIP_TRAILING_WHITESPACE - ) - if(_Pytest_STATUS AND NOT _Pytest_STATUS EQUAL 0) - message(AUTHOR_WARNING "Pytest isn't installed on your system python, so some tests won't be run. Run `${Python_EXECUTABLE} -m pip install pytest`") - set(Pytest_AVAILABLE OFF) - else() - message(VERBOSE "Found Pytest: ${Pytest_Version}") - set(Pytest_AVAILABLE ON) - endif() if (Pytest_AVAILABLE) add_test(NAME idd_schema.test_idd_parser diff --git a/scripts/pytests/conftest.py b/scripts/pytests/conftest.py new file mode 100644 index 00000000000..2a1fe771d67 --- /dev/null +++ b/scripts/pytests/conftest.py @@ -0,0 +1,87 @@ +# 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. + +from pathlib import Path + +import pytest + + +def validate_file(arg): + if (filepath := Path(arg).expanduser()).is_file(): + return filepath + else: + raise FileNotFoundError(arg) + + +def pytest_addoption(parser): + parser.addoption("--ep-cli-path", type=validate_file, help="Path to the E+ CLI") # , required=True + + +@pytest.fixture(scope="module") +def epclipath(request): + cli_path = request.config.getoption("--ep-cli-path") + if cli_path is None: + raise ValueError("You must supply --ep-cli-path [Path]") + return cli_path + + +@pytest.fixture(scope="module") +def testfiles_dir(): + return Path(__file__).parent / "../../testfiles" + + +@pytest.fixture(scope="module") +def chig_epw(): + return Path(__file__).parent / "../../weather/USA_IL_Chicago-OHare_TMY2.epw" diff --git a/scripts/pytests/test_xml_output.py b/scripts/pytests/test_xml_output.py new file mode 100644 index 00000000000..f44af6dc3f7 --- /dev/null +++ b/scripts/pytests/test_xml_output.py @@ -0,0 +1,87 @@ +# 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. + +import re +import subprocess +from pathlib import Path + +import pytest + + +@pytest.fixture +def prepare_idf_with_xml(tmp_path: Path, testfiles_dir: Path): # tmp_path is a built-in pytest fixture + RE_TABLE = re.compile(r"(?POutputControl:Table:Style.*)HTML;", re.DOTALL) + idf_file_path = testfiles_dir / "DXCoilSystemAuto.idf" + assert idf_file_path.is_file() + content = idf_file_path.read_text() + content = RE_TABLE.sub(r"\g<1>XMLandHTML;", content) + mod_idf_file_path = tmp_path / "in.idf" + mod_idf_file_path.write_text(content) + return mod_idf_file_path + + +def test_xml_with_standard_ratings_is_valid(epclipath, prepare_idf_with_xml, chig_epw): + lxml = pytest.importorskip("lxml", reason="lxml not found, please `pip install lxml`") + from lxml import etree + + subprocess.check_call( + [str(epclipath), "-w", str(chig_epw)], + stdout=subprocess.DEVNULL, + stderr=subprocess.STDOUT, + cwd=prepare_idf_with_xml.parent, + ) + xml_out_path = prepare_idf_with_xml.parent / "eplustbl.xml" + assert xml_out_path.is_file() + root = lxml.etree.fromstring(xml_out_path.read_text(encoding="latin-1")) diff --git a/src/EnergyPlus/CMakeLists.txt b/src/EnergyPlus/CMakeLists.txt index 174e2f0d693..bf94f5b216e 100644 --- a/src/EnergyPlus/CMakeLists.txt +++ b/src/EnergyPlus/CMakeLists.txt @@ -1159,6 +1159,13 @@ if(BUILD_TESTING) TIMEOUT 10 # This used to timeout! and we expect it NOT to ) endif() + + if(Pytest_AVAILABLE) + add_test(NAME energyplus.TabularXML_IsValid + COMMAND ${Python_EXECUTABLE} -m pytest --verbose --ep-cli-path $ "${PROJECT_SOURCE_DIR}/scripts/pytests/test_xml_output.py" + ) + endif() + endif() if(UNIX AND NOT APPLE) From e59c6041ad4ac8895c92e6182699806966d3848d Mon Sep 17 00:00:00 2001 From: Julien Marrec Date: Mon, 16 Dec 2024 21:01:37 +0100 Subject: [PATCH 2/8] Define a constexpr std::string_view for the AHRI table footnotes (2017/2023) --- src/EnergyPlus/Coils/CoilCoolingDX.cc | 30 ++------------- src/EnergyPlus/DXCoils.cc | 13 +------ src/EnergyPlus/StandardRatings.cc | 54 ++------------------------- src/EnergyPlus/StandardRatings.hh | 28 ++++++++++++++ 4 files changed, 36 insertions(+), 89 deletions(-) diff --git a/src/EnergyPlus/Coils/CoilCoolingDX.cc b/src/EnergyPlus/Coils/CoilCoolingDX.cc index 6ce7bef2a44..95eb0228bd3 100644 --- a/src/EnergyPlus/Coils/CoilCoolingDX.cc +++ b/src/EnergyPlus/Coils/CoilCoolingDX.cc @@ -70,6 +70,7 @@ #include #include #include +#include #include using namespace EnergyPlus; @@ -1047,19 +1048,7 @@ void CoilCoolingDX::reportAllStandardRatings(EnergyPlusData &state) } else { OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchDXCoolCoilIEERIP, coil.name, "N/A"); } - OutputReportPredefined::addFootNoteSubTable( - state, - state.dataOutRptPredefined->pdstDXCoolCoil, - "ANSI/AHRI ratings account for supply air fan heat and electric power.
" - "1 - EnergyPlus object type.
" - "2 - Capacity less than 65K Btu/h (19050 W) - calculated as per AHRI Standard 210/240-2017.
" - "  Capacity of 65K Btu/h (19050 W) to less than 135K Btu/h (39565 W) - calculated as per AHRI Standard 340/360-2007. " - "
" - "  Capacity from 135K (39565 W) to 250K Btu/hr (73268 W) - calculated as per AHRI Standard 365-2009 - Ratings not yet " - "supported in EnergyPlus.
" - "3 - SEER (User) is calculated using user-input PLF curve and cooling coefficient of degradation.
" - "  SEER (Standard) is calculated using the default PLF curve and cooling coefficient of degradation" - "from the appropriate AHRI standard."); + OutputReportPredefined::addFootNoteSubTable(state, state.dataOutRptPredefined->pdstDXCoolCoil, StandardRatings::AHRI2017FOOTNOTE); // AHRI 2023 Standard SEER2 Calculations if (state.dataHVACGlobal->StandardRatingsMyCoolOneTimeFlag2) { @@ -1125,20 +1114,7 @@ void CoilCoolingDX::reportAllStandardRatings(EnergyPlusData &state) } else { OutputReportPredefined::PreDefTableEntry(state, state.dataOutRptPredefined->pdchDXCoolCoilIEERIP_2023, coil.name, "N/A"); } - OutputReportPredefined::addFootNoteSubTable( - state, - state.dataOutRptPredefined->pdstDXCoolCoil_2023, - "ANSI/AHRI ratings account for supply air fan heat and electric power.
" - "1 - EnergyPlus object type.
" - "2 - Capacity less than 65K Btu/h (19050 W) - calculated as per AHRI Standard 210/240-2023.
" - "  Capacity of 65K Btu/h (19050 W) to less than 135K Btu/h (39565 W) - calculated as per AHRI Standard 340/360-2022. " - "
" - "  Capacity from 135K (39565 W) to 250K Btu/hr (73268 W) - calculated as per AHRI Standard 365-2009 - Ratings not yet " - "supported in EnergyPlus.
" - "3 - SEER2 (User) is calculated using user-input PLF curve and cooling coefficient of degradation.
" - "  SEER2 (Standard) is calculated using the default PLF curve and cooling coefficient of degradation" - "from the appropriate AHRI standard.
" - "4 - Value for the Full Speed of the coil."); + OutputReportPredefined::addFootNoteSubTable(state, state.dataOutRptPredefined->pdstDXCoolCoil_2023, StandardRatings::AHRI2023FOOTNOTE); } } state.dataCoilCooingDX->stillNeedToReportStandardRatings = false; diff --git a/src/EnergyPlus/DXCoils.cc b/src/EnergyPlus/DXCoils.cc index 3f9d45b9969..885b66cb176 100644 --- a/src/EnergyPlus/DXCoils.cc +++ b/src/EnergyPlus/DXCoils.cc @@ -14824,18 +14824,7 @@ void CalcTwoSpeedDXCoilStandardRating(EnergyPlusData &state, int const DXCoilNum PreDefTableEntry(state, state.dataOutRptPredefined->pdchDXCoolCoilSEERUserIP, thisDXCoil.Name, "N/A"); PreDefTableEntry(state, state.dataOutRptPredefined->pdchDXCoolCoilSEERStandardIP, thisDXCoil.Name, "N/A"); - addFootNoteSubTable( - state, - state.dataOutRptPredefined->pdstDXCoolCoil, - "ANSI/AHRI ratings account for supply air fan heat and electric power.
" - "1 - EnergyPlus object type.
" - "2 - Capacity less than 65K Btu/h (19050 W) - calculated as per AHRI Standard 210/240-2017.
" - "  Capacity of 65K Btu/h (19050 W) to less than 135K Btu/h (39565 W) - calculated as per AHRI Standard 340/360-2007.
" - "  Capacity from 135K (39565 W) to 250K Btu/hr (73268 W) - calculated as per AHRI Standard 365-2009 - Ratings not yet supported in " - "EnergyPlus.
" - "3 - SEER (User) is calculated using user-input PLF curve and cooling coefficient of degradation.
" - "  SEER (Standard) is calculated using the default PLF curve and cooling coefficient of degradation" - "from the appropriate AHRI standard."); + addFootNoteSubTable(state, state.dataOutRptPredefined->pdstDXCoolCoil, StandardRatings::AHRI2017FOOTNOTE); PreDefTableEntry(state, state.dataOutRptPredefined->pdchVAVDXCoolCoilType, thisDXCoil.Name, "Coil:Cooling:DX:TwoSpeed"); if (thisDXCoil.RateWithInternalStaticAndFanObject) { diff --git a/src/EnergyPlus/StandardRatings.cc b/src/EnergyPlus/StandardRatings.cc index 6d43fbcdd2c..fb0bdddc744 100644 --- a/src/EnergyPlus/StandardRatings.cc +++ b/src/EnergyPlus/StandardRatings.cc @@ -6804,18 +6804,7 @@ namespace StandardRatings { } else { PreDefTableEntry(state, state.dataOutRptPredefined->pdchDXCoolCoilIEERIP, CompName, "N/A"); } - addFootNoteSubTable(state, - state.dataOutRptPredefined->pdstDXCoolCoil, - "ANSI/AHRI ratings account for supply air fan heat and electric power.
" - "1 - EnergyPlus object type.
" - "2 - Capacity less than 65K Btu/h (19050 W) - calculated as per AHRI Standard 210/240-2017.
" - "  Capacity of 65K Btu/h (19050 W) to less than 135K Btu/hv (39565 W) - calculated as per AHRI " - "Standard 340/360-2007.
" - "  Capacity from 135K (39565 W) to 250K Btu/hr (73268 W) - calculated as per AHRI Standard 365-2009 - " - "Ratings not yet supported in EnergyPlus.
" - "3 - SEER (User) is calculated using user-input PLF curve and cooling coefficient of degradation.
" - "  SEER (Standard) is calculated using the default PLF curve and cooling coefficient of degradation" - "from the appropriate AHRI standard."); + addFootNoteSubTable(state, state.dataOutRptPredefined->pdstDXCoolCoil, StandardRatings::AHRI2017FOOTNOTE); } else { // ANSI/AHRI 210/240 Standard 2023 Ratings | SEER2 if (state.dataHVACGlobal->StandardRatingsMyCoolOneTimeFlag2) { @@ -6862,19 +6851,7 @@ namespace StandardRatings { } else { PreDefTableEntry(state, state.dataOutRptPredefined->pdchDXCoolCoilIEERIP_2023, CompName, "N/A"); } - addFootNoteSubTable(state, - state.dataOutRptPredefined->pdstDXCoolCoil_2023, - "ANSI/AHRI ratings account for supply air fan heat and electric power.
" - "1 - EnergyPlus object type.
" - "2 - Capacity less than 65K Btu/h (19050 W) - calculated as per AHRI Standard 210/240-2023.
" - "  Capacity of 65K Btu/h (19050 W) to less than 135K Btu/h (39565 W) - calculated as per AHRI Standard " - "340/360-2022.
" - "  Capacity from 135K (39565 W) to 250K Btu/hr (73268 W) - calculated as per AHRI Standard 365-2009 - " - "Ratings not yet supported in EnergyPlus.
" - "3 - SEER2 (User) is calculated using user-input PLF curve and cooling coefficient of degradation.
" - "  SEER2 (Standard) is calculated using the default PLF curve and cooling coefficient of degradation" - "from the appropriate AHRI standard.
" - "4 - Value for the Full Speed of the coil."); + addFootNoteSubTable(state, state.dataOutRptPredefined->pdstDXCoolCoil_2023, StandardRatings::AHRI2023FOOTNOTE); } break; } @@ -6973,18 +6950,7 @@ namespace StandardRatings { } else { PreDefTableEntry(state, state.dataOutRptPredefined->pdchDXCoolCoilIEERIP, CompName, "N/A"); } - addFootNoteSubTable(state, - state.dataOutRptPredefined->pdstDXCoolCoil, - "ANSI/AHRI ratings account for supply air fan heat and electric power.
" - "1 - EnergyPlus object type.
" - "2 - Capacity less than 65K Btu/h (19050 W) - calculated as per AHRI Standard 210/240-2017.
" - "  Capacity of 65K Btu/h (19050 W) to less than 135K Btu/h (39565 W) - calculated as per AHRI Standard " - "340/360-2007.
" - "  Capacity from 135K (39565 W) to 250K Btu/hr (73268 W) - calculated as per AHRI Standard 365-2009 - " - "Ratings not yet supported in EnergyPlus.
" - "3 - SEER (User) is calculated using user-input PLF curve and cooling coefficient of degradation.
" - "  SEER (Standard) is calculated using the default PLF curve and cooling coefficient of degradation" - "from the appropriate AHRI standard."); + addFootNoteSubTable(state, state.dataOutRptPredefined->pdstDXCoolCoil, StandardRatings::AHRI2017FOOTNOTE); } else { // ANSI/AHRI 210/240 Standard 2023 Ratings | SEER2 if (state.dataHVACGlobal->StandardRatingsMyCoolOneTimeFlag2) { @@ -7030,19 +6996,7 @@ namespace StandardRatings { } else { PreDefTableEntry(state, state.dataOutRptPredefined->pdchDXCoolCoilIEERIP_2023, CompName, "N/A"); } - addFootNoteSubTable(state, - state.dataOutRptPredefined->pdstDXCoolCoil_2023, - "ANSI/AHRI ratings account for supply air fan heat and electric power.
" - "1 - EnergyPlus object type.
" - "2 - Capacity less than 65K Btu/h (19050 W) - calculated as per AHRI Standard 210/240-2023.
" - "  Capacity of 65K Btu/h (19050 W) to less than 135K Btu/h (39565 W) - calculated as per AHRI Standard " - "340/360-2022.
" - "  Capacity from 135K (39565 W) to 250K Btu/hr (73268 W) - calculated as per AHRI Standard 365-2009 - " - "Ratings not yet supported in EnergyPlus.
" - "3 - SEER2 (User) is calculated using user-input PLF curve and cooling coefficient of degradation.
" - "  SEER2 (Standard) is calculated using the default PLF curve and cooling coefficient of degradation" - "from the appropriate AHRI standard.
" - "4 - Value for the Full Speed of the coil."); + addFootNoteSubTable(state, state.dataOutRptPredefined->pdstDXCoolCoil_2023, StandardRatings::AHRI2023FOOTNOTE); } break; diff --git a/src/EnergyPlus/StandardRatings.hh b/src/EnergyPlus/StandardRatings.hh index 301a69f0b2b..d9f36918fda 100644 --- a/src/EnergyPlus/StandardRatings.hh +++ b/src/EnergyPlus/StandardRatings.hh @@ -58,6 +58,9 @@ #include #include +// C++ Headers +#include + namespace EnergyPlus { // Forward declarations @@ -76,6 +79,31 @@ namespace StandardRatings { Real64 constexpr HeatingOutdoorCoilInletAirDBTempH3Test(-8.33); // Outdoor air dry-bulb temp in degrees C (17F) // Test H3 (low and High Speed) Std. AHRI 210/240 + static constexpr std::string_view AHRI2017FOOTNOTE = + "ANSI/AHRI ratings account for supply air fan heat and electric power.
" + "1 - EnergyPlus object type.
" + "2 - Capacity less than 65K Btu/h (19050 W) - calculated as per AHRI Standard 210/240-2017.
" + "  Capacity of 65K Btu/h (19050 W) to less than 135K Btu/h (39565 W) - calculated as per AHRI Standard 340/360-2007. " + "
" + "  Capacity from 135K (39565 W) to 250K Btu/hr (73268 W) - calculated as per AHRI Standard 365-2009 - Ratings not yet " + "supported in EnergyPlus.
" + "3 - SEER (User) is calculated using user-input PLF curve and cooling coefficient of degradation.
" + "  SEER (Standard) is calculated using the default PLF curve and cooling coefficient of degradation" + "from the appropriate AHRI standard."; + + static constexpr std::string_view AHRI2023FOOTNOTE = + "ANSI/AHRI ratings account for supply air fan heat and electric power.
" + "1 - EnergyPlus object type.
" + "2 - Capacity less than 65K Btu/h (19050 W) - calculated as per AHRI Standard 210/240-2023.
" + "  Capacity of 65K Btu/h (19050 W) to less than 135K Btu/h (39565 W) - calculated as per AHRI Standard 340/360-2022. " + "
" + "  Capacity from 135K (39565 W) to 250K Btu/hr (73268 W) - calculated as per AHRI Standard 365-2009 - Ratings not yet " + "supported in EnergyPlus.
" + "3 - SEER2 (User) is calculated using user-input PLF curve and cooling coefficient of degradation.
" + "  SEER2 (Standard) is calculated using the default PLF curve and cooling coefficient of degradation" + "from the appropriate AHRI standard.
" + "4 - Value for the Full Speed of the coil."; + // Defrost strategy (heat pump only) enum class DefrostStrat { From 5374b1b83797c8b587e119ccdd3dba0487131faa Mon Sep 17 00:00:00 2001 From: Julien Marrec Date: Tue, 17 Dec 2024 15:28:41 +0100 Subject: [PATCH 3/8] pip install pytest lxml --- .github/workflows/test_pull_requests.yml | 2 ++ scripts/pytests/requirements.txt | 2 ++ 2 files changed, 4 insertions(+) create mode 100644 scripts/pytests/requirements.txt diff --git a/.github/workflows/test_pull_requests.yml b/.github/workflows/test_pull_requests.yml index 153b38d8f89..9e2ca4f483f 100644 --- a/.github/workflows/test_pull_requests.yml +++ b/.github/workflows/test_pull_requests.yml @@ -62,6 +62,7 @@ jobs: brew reinstall gcc@13 echo "FC=$(brew --prefix gcc@13)/bin/gfortran-13" >> $GITHUB_ENV echo MACOSX_DEPLOYMENT_TARGET=${{ matrix.macos_dev_target }} >> $GITHUB_ENV + pip install pytest lxml - name: Install Dependencies for Linux if: runner.os == 'Linux' @@ -72,6 +73,7 @@ jobs: # https://github.com/actions/runner-images/issues/10025 echo "FC=gfortran-13" >> $GITHUB_ENV fi + pip install pytest lxml # BUILD AND TEST INTEGRATION FILES ON THE BASELINE BRANCH diff --git a/scripts/pytests/requirements.txt b/scripts/pytests/requirements.txt new file mode 100644 index 00000000000..aec3ae2868c --- /dev/null +++ b/scripts/pytests/requirements.txt @@ -0,0 +1,2 @@ +pytest +lxml From 4f00fc7e90e406b961291ca58fa54bc9b4ab11f0 Mon Sep 17 00:00:00 2001 From: Julien Marrec Date: Mon, 16 Dec 2024 21:02:22 +0100 Subject: [PATCH 4/8] For XML, if footnote has brs, wrap it in CDATA --- src/EnergyPlus/OutputReportTabular.cc | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/EnergyPlus/OutputReportTabular.cc b/src/EnergyPlus/OutputReportTabular.cc index 0c404c76d54..2c727bf8561 100644 --- a/src/EnergyPlus/OutputReportTabular.cc +++ b/src/EnergyPlus/OutputReportTabular.cc @@ -17316,7 +17316,11 @@ void WriteTable(EnergyPlusData &state, } } if (!footnoteText.empty()) { - tbl_stream << fmt::format(" {}\n", footnoteText); + if (footnoteText.find("\n", footnoteText); + } else { + tbl_stream << fmt::format(" {}\n", footnoteText); + } } } } else { From ce1966c08e65763c8d7890b7e1fe153a5ff47973 Mon Sep 17 00:00:00 2001 From: Julien Marrec Date: Mon, 16 Dec 2024 21:15:12 +0100 Subject: [PATCH 5/8] Use a raw string litteral --- src/EnergyPlus/StandardRatings.hh | 47 +++++++++++++++---------------- 1 file changed, 23 insertions(+), 24 deletions(-) diff --git a/src/EnergyPlus/StandardRatings.hh b/src/EnergyPlus/StandardRatings.hh index d9f36918fda..982793f0f95 100644 --- a/src/EnergyPlus/StandardRatings.hh +++ b/src/EnergyPlus/StandardRatings.hh @@ -79,30 +79,29 @@ namespace StandardRatings { Real64 constexpr HeatingOutdoorCoilInletAirDBTempH3Test(-8.33); // Outdoor air dry-bulb temp in degrees C (17F) // Test H3 (low and High Speed) Std. AHRI 210/240 - static constexpr std::string_view AHRI2017FOOTNOTE = - "ANSI/AHRI ratings account for supply air fan heat and electric power.
" - "1 - EnergyPlus object type.
" - "2 - Capacity less than 65K Btu/h (19050 W) - calculated as per AHRI Standard 210/240-2017.
" - "  Capacity of 65K Btu/h (19050 W) to less than 135K Btu/h (39565 W) - calculated as per AHRI Standard 340/360-2007. " - "
" - "  Capacity from 135K (39565 W) to 250K Btu/hr (73268 W) - calculated as per AHRI Standard 365-2009 - Ratings not yet " - "supported in EnergyPlus.
" - "3 - SEER (User) is calculated using user-input PLF curve and cooling coefficient of degradation.
" - "  SEER (Standard) is calculated using the default PLF curve and cooling coefficient of degradation" - "from the appropriate AHRI standard."; - - static constexpr std::string_view AHRI2023FOOTNOTE = - "ANSI/AHRI ratings account for supply air fan heat and electric power.
" - "1 - EnergyPlus object type.
" - "2 - Capacity less than 65K Btu/h (19050 W) - calculated as per AHRI Standard 210/240-2023.
" - "  Capacity of 65K Btu/h (19050 W) to less than 135K Btu/h (39565 W) - calculated as per AHRI Standard 340/360-2022. " - "
" - "  Capacity from 135K (39565 W) to 250K Btu/hr (73268 W) - calculated as per AHRI Standard 365-2009 - Ratings not yet " - "supported in EnergyPlus.
" - "3 - SEER2 (User) is calculated using user-input PLF curve and cooling coefficient of degradation.
" - "  SEER2 (Standard) is calculated using the default PLF curve and cooling coefficient of degradation" - "from the appropriate AHRI standard.
" - "4 - Value for the Full Speed of the coil."; + static constexpr std::string_view AHRI2017FOOTNOTE = R"html(ANSI/AHRI ratings account for supply air fan heat and electric power.
+1 - EnergyPlus object type.
+2 - Capacity less than 65K Btu/h (19050 W) - calculated as per AHRI Standard 210/240-2017.
+  Capacity of 65K Btu/h (19050 W) to less than 135K Btu/h (39565 W) - calculated as per AHRI Standard 340/360-2007. +
+  Capacity from 135K (39565 W) to 250K Btu/hr (73268 W) - calculated as per AHRI Standard 365-2009 - Ratings not yet +supported in EnergyPlus.
+3 - SEER (User) is calculated using user-input PLF curve and cooling coefficient of degradation.
+  SEER (Standard) is calculated using the default PLF curve and cooling coefficient of degradation +from the appropriate AHRI standard.)html"; + + static constexpr std::string_view AHRI2023FOOTNOTE = R"html(ANSI/AHRI ratings account for supply air fan heat and electric power.
+1 - EnergyPlus object type.
+2 - Capacity less than 65K Btu/h (19050 W) - calculated as per AHRI Standard 210/240-2023.
+  Capacity of 65K Btu/h (19050 W) to less than 135K Btu/h (39565 W) - calculated as per AHRI Standard 340/360-2022. +
+  Capacity from 135K (39565 W) to 250K Btu/hr (73268 W) - calculated as per AHRI Standard 365-2009 - Ratings not yet +supported in EnergyPlus.
+3 - SEER2 (User) is calculated using user-input PLF curve and cooling coefficient of degradation.
+  SEER2 (Standard) is calculated using the default PLF curve and cooling coefficient of degradation +from the appropriate AHRI standard.
+4 - Value for the Full Speed of the coil. +)html"; // Defrost strategy (heat pump only) enum class DefrostStrat From 5110ecd70a0f0e65c9fe56dd8ec2a6a3e58847fe Mon Sep 17 00:00:00 2001 From: Julien Marrec Date: Mon, 16 Dec 2024 21:21:42 +0100 Subject: [PATCH 6/8] the MUST be inside the --- src/EnergyPlus/OutputReportTabular.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/EnergyPlus/OutputReportTabular.cc b/src/EnergyPlus/OutputReportTabular.cc index 2c727bf8561..bfaa15ce501 100644 --- a/src/EnergyPlus/OutputReportTabular.cc +++ b/src/EnergyPlus/OutputReportTabular.cc @@ -3106,8 +3106,8 @@ void OpenOutputTabularFile(EnergyPlusData &state) tbl_stream << " " << std::setw(2) << ort->td(5) << ':' << std::setw(2) << ort->td(6) << ':' << std::setw(2) << ort->td(7) << std::setfill(' ') << '\n'; tbl_stream << " - EnergyPlus\n"; - tbl_stream << "\n"; tbl_stream << "\n"; + tbl_stream << "\n"; tbl_stream << "\n"; tbl_stream << "

Table of Contents

\n"; tbl_stream << "\n"; From 07f523d0e6a47c9143dd250dc56f389e39f51220 Mon Sep 17 00:00:00 2001 From: Julien Marrec Date: Tue, 17 Dec 2024 15:31:43 +0100 Subject: [PATCH 7/8] Modernize the HTML footnote style: use a div, and ol instead of harcoding numbers and using   and   --- src/EnergyPlus/OutputReportTabular.cc | 2 +- src/EnergyPlus/StandardRatings.hh | 49 ++++++++++++++------------- 2 files changed, 27 insertions(+), 24 deletions(-) diff --git a/src/EnergyPlus/OutputReportTabular.cc b/src/EnergyPlus/OutputReportTabular.cc index bfaa15ce501..856126ec0c2 100644 --- a/src/EnergyPlus/OutputReportTabular.cc +++ b/src/EnergyPlus/OutputReportTabular.cc @@ -17188,7 +17188,7 @@ void WriteTable(EnergyPlusData &state, // end the table tbl_stream << "\n"; if (!footnoteText.empty()) { - tbl_stream << fmt::format("{}\n", footnoteText); + tbl_stream << fmt::format("
{}
\n", footnoteText); } tbl_stream << "

\n"; } else if (thisStyle == TableStyle::XML) { diff --git a/src/EnergyPlus/StandardRatings.hh b/src/EnergyPlus/StandardRatings.hh index 982793f0f95..4b229fc751f 100644 --- a/src/EnergyPlus/StandardRatings.hh +++ b/src/EnergyPlus/StandardRatings.hh @@ -79,29 +79,32 @@ namespace StandardRatings { Real64 constexpr HeatingOutdoorCoilInletAirDBTempH3Test(-8.33); // Outdoor air dry-bulb temp in degrees C (17F) // Test H3 (low and High Speed) Std. AHRI 210/240 - static constexpr std::string_view AHRI2017FOOTNOTE = R"html(ANSI/AHRI ratings account for supply air fan heat and electric power.
-1 - EnergyPlus object type.
-2 - Capacity less than 65K Btu/h (19050 W) - calculated as per AHRI Standard 210/240-2017.
-  Capacity of 65K Btu/h (19050 W) to less than 135K Btu/h (39565 W) - calculated as per AHRI Standard 340/360-2007. -
-  Capacity from 135K (39565 W) to 250K Btu/hr (73268 W) - calculated as per AHRI Standard 365-2009 - Ratings not yet -supported in EnergyPlus.
-3 - SEER (User) is calculated using user-input PLF curve and cooling coefficient of degradation.
-  SEER (Standard) is calculated using the default PLF curve and cooling coefficient of degradation -from the appropriate AHRI standard.)html"; - - static constexpr std::string_view AHRI2023FOOTNOTE = R"html(ANSI/AHRI ratings account for supply air fan heat and electric power.
-1 - EnergyPlus object type.
-2 - Capacity less than 65K Btu/h (19050 W) - calculated as per AHRI Standard 210/240-2023.
-  Capacity of 65K Btu/h (19050 W) to less than 135K Btu/h (39565 W) - calculated as per AHRI Standard 340/360-2022. -
-  Capacity from 135K (39565 W) to 250K Btu/hr (73268 W) - calculated as per AHRI Standard 365-2009 - Ratings not yet -supported in EnergyPlus.
-3 - SEER2 (User) is calculated using user-input PLF curve and cooling coefficient of degradation.
-  SEER2 (Standard) is calculated using the default PLF curve and cooling coefficient of degradation -from the appropriate AHRI standard.
-4 - Value for the Full Speed of the coil. -)html"; + static constexpr std::string_view AHRI2017FOOTNOTE = R"html(

ANSI/AHRI ratings account for supply air fan heat and electric power.

+
    +
  1. EnergyPlus object type.
  2. +
  3. Capacity less than 65K Btu/h (19050 W) - calculated as per AHRI Standard 210/240-2017.
    + Capacity of 65K Btu/h (19050 W) to less than 135K Btu/h (39565 W) - calculated as per AHRI Standard 340/360-2007.
    + Capacity from 135K (39565 W) to 250K Btu/hr (73268 W) - calculated as per AHRI Standard 365-2009 - Ratings not yet supported in EnergyPlus. +
  4. +
  5. SEER (User) is calculated using user-input PLF curve and cooling coefficient of degradation.
    + SEER (Standard) is calculated using the default PLF curve and cooling coefficient of degradation from the appropriate AHRI standard. +
  6. +
)html"; + + static constexpr std::string_view AHRI2023FOOTNOTE = R"html(

ANSI/AHRI ratings account for supply air fan heat and electric power.

+
    +
  1. EnergyPlus object type.
  2. +
  3. + Capacity less than 65K Btu/h (19050 W) - calculated as per AHRI Standard 210/240-2023.
    + Capacity of 65K Btu/h (19050 W) to less than 135K Btu/h (39565 W) - calculated as per AHRI Standard 340/360-2022.
    + Capacity from 135K (39565 W) to 250K Btu/hr (73268 W) - calculated as per AHRI Standard 365-2009 - Ratings not yet supported in EnergyPlus. +
  4. +
  5. + SEER2 (User) is calculated using user-input PLF curve and cooling coefficient of degradation.
    + SEER2 (Standard) is calculated using the default PLF curve and cooling coefficient of degradation from the appropriate AHRI standard. +
  6. +
  7. Value for the Full Speed of the coil.
  8. +
)html"; // Defrost strategy (heat pump only) enum class DefrostStrat From ccf4fff6b3a212a8a68605fd291d56e79bd27409 Mon Sep 17 00:00:00 2001 From: Edwin Lee Date: Fri, 10 Jan 2025 14:26:29 -0600 Subject: [PATCH 8/8] Fix license year in 2 new python files [decent_ci_skip] --- scripts/pytests/conftest.py | 2 +- scripts/pytests/test_xml_output.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/pytests/conftest.py b/scripts/pytests/conftest.py index 2a1fe771d67..08dd955a048 100644 --- a/scripts/pytests/conftest.py +++ b/scripts/pytests/conftest.py @@ -1,4 +1,4 @@ -# EnergyPlus, Copyright (c) 1996-2024, The Board of Trustees of the University +# EnergyPlus, Copyright (c) 1996-2025, 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- diff --git a/scripts/pytests/test_xml_output.py b/scripts/pytests/test_xml_output.py index f44af6dc3f7..207ed6873e9 100644 --- a/scripts/pytests/test_xml_output.py +++ b/scripts/pytests/test_xml_output.py @@ -1,4 +1,4 @@ -# EnergyPlus, Copyright (c) 1996-2024, The Board of Trustees of the University +# EnergyPlus, Copyright (c) 1996-2025, 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-