diff --git a/developer/doc/ReleaseNotes/OpenStudio_Release_Notes_3_8_0_TBD.md b/developer/doc/ReleaseNotes/OpenStudio_Release_Notes_3_8_0_20240508.md similarity index 80% rename from developer/doc/ReleaseNotes/OpenStudio_Release_Notes_3_8_0_TBD.md rename to developer/doc/ReleaseNotes/OpenStudio_Release_Notes_3_8_0_20240508.md index 8a70cec5ba0..c55450476ea 100644 --- a/developer/doc/ReleaseNotes/OpenStudio_Release_Notes_3_8_0_TBD.md +++ b/developer/doc/ReleaseNotes/OpenStudio_Release_Notes_3_8_0_20240508.md @@ -1,6 +1,6 @@ # OpenStudio Version 3.8.0 -_Release Notes_ - _TBD_ +_Release Notes_ - 2024-05-08 These release notes describe version 3.8.0 of the OpenStudio SDK developed by the National Renewable Energy Laboratory (NREL), Buildings and Thermal Sciences Center, Commercial Buildings Research Group, Tools Development Section, and associated collaborators. The notes are organized into the following sections: @@ -28,9 +28,9 @@ __**OpenStudio SDK 3.8.0**__ # Where to Find OpenStudio SDK Documentation - OpenStudio SDK release documentation, including these release notes, tutorials, and other user documentation, is available at [https://www.openstudio.net/](https://www.openstudio.net/.) -- C++ API documentation is available at [https://openstudio-sdk-documentation.s3.amazonaws.com/index.html](https://openstudio-sdk-documentation.s3.amazonaws.com/index.html) -- Measure development documentation is available at [http://nrel.github.io/OpenStudio-user-documentation/reference/measure_writing_guide/](http://nrel.github.io/OpenStudio-user-documentation/reference/measure_writing_guide/ ) -- A roadmap for planned features is available at http://nrel.github.io/OpenStudio-user-documentation/getting_started/roadmap/. +- C++ API documentation is available at [OpenStudio SDK Documentation](https://openstudio-sdk-documentation.s3.amazonaws.com/index.html) +- Measure development documentation is available at [OpenStudio Measure Writer's Reference Guide](http://nrel.github.io/OpenStudio-user-documentation/reference/measure_writing_guide/ ) +- A roadmap for planned features is available at [Roadmap](http://nrel.github.io/OpenStudio-user-documentation/getting_started/roadmap/) # Installation Notes @@ -53,7 +53,7 @@ As usual, you can refer to the **[OpenStudio SDK Compatibility Matrix](https://g - Download and install [OpenStudio SDK](https://github.com/NREL/openstudio) and/or any third party tool that embeds the OpenStudio SDK into their software such as [openstudiocoalition/OpenStudioApplication](https://github.com/openstudiocoalition/OpenStudioApplication) depending on your needs. Select components for installation. Note that OpenStudio Application is a standalone app and does not require you to install OpenStudio SDK. - A BCL AUth Key is no longer needed to access content on [Building Component Library (BCL)](https://bcl.nrel.gov) BCL is typically accessed through third party OpenStudio applications to provide modelers access to building components and OpenStudio measures; however you an also browse it and download content using the BCL link above. -For help with common installation problems please visit, http://nrel.github.io/OpenStudio-user-documentation/getting_started/getting_started/. +For help with common installation problems please visit [Getting Started](http://nrel.github.io/OpenStudio-user-documentation/getting_started/getting_started/). # OpenStudio SDK: @@ -87,11 +87,12 @@ For a list of deprecated and removed methods, please refer to [deprecated_method * [#5037](https://github.com/NREL/OpenStudio/issues/5037) * [#4918](https://github.com/NREL/OpenStudio/issues/4918) -* [#TBD]() Refactoring and relocating model methods that has been in the openStudio-extension Gem to be in the openstudio-standards Gem or in OpenStudio C++ SDK. A few methods will be moved directly into measures. The result of this is that with OpenStudio 3.8.0 no measures should have to require 'openstudio-extension' within a measure's Ruby code. -* [#TBD]() Update to version 0.6.0 of the openstudio_standards Gem. In addition to some refactoring, this release also included conversion of 90.1 data to formal database. +* Refactoring and relocating model methods that has been in the openstudio-extensio-gem Gem to be in the openstudio-standards Gem or in OpenStudio C++ SDK. A few methods will be moved directly into measures. The result of this is that with OpenStudio 3.8.0 no measures should have to require 'openstudio-extension' within a measure's Ruby code. + * [#5142](https://github.com/NREL/OpenStudio/pull/5142) - Add native support for measure argument methods in OsLib_HelperMethods -* [#TBD]() Enhancements to the Building Component Library (BCL) +* Enhancements to the Building Component Library (BCL) + * [#5126](https://github.com/NREL/OpenStudio/pull/5126) - Add versionModified, repo, org, releaseTag to BCLSearchResult * Support for OpenStudio Python Measures * Updating Measure Details page to include measure language * Link to GitHub Repo from Measure Details page @@ -111,16 +112,27 @@ For a list of deprecated and removed methods, please refer to [deprecated_method ## Minor changes and bug fixes -* -* -* - -## Known Issues / Limitations - -* -* -* +Refer to the changelog on the release page at [v3.8.0](https://github.com/NREL/OpenStudio/releases/v3.8.0) **Full Changelog**: https://github.com/NREL/OpenStudio/compare/v3.7.0...v3.8.0 **New Contributors**: + +### OpenStudio Standards v0.6.1 + +Update the openstudio-standards gem to version [0.6.1](https://github.com/NREL/openstudio-standards/releases/tag/v0.6.1) +In addition to some refactoring, this release also included conversion of 90.1 data to formal database. + +--- +# This YAML header controls the pandoc (via TeX) to PDF settings +# To convert the markdown to pdf, do `pandoc release_notes.md -o release_notes.pdf` +title: 'OpenStudio Release Notes - 3.8.0' +author: +- National Renewable Energy Laboratory +colorlinks: true +linkcolor: blue +urlcolor: Mahogany +toccolor: gray +geometry: +- margin=1in +--- diff --git a/developer/doc/ReleaseNotes/OpenStudio_Release_Notes_3_8_0_20240508.pdf b/developer/doc/ReleaseNotes/OpenStudio_Release_Notes_3_8_0_20240508.pdf new file mode 100644 index 00000000000..6bde86229b1 Binary files /dev/null and b/developer/doc/ReleaseNotes/OpenStudio_Release_Notes_3_8_0_20240508.pdf differ diff --git a/developer/doc/ReleaseNotes/OpenStudio_Release_Notes_3_9_0_TBD.md b/developer/doc/ReleaseNotes/OpenStudio_Release_Notes_3_9_0_TBD.md new file mode 100644 index 00000000000..6cded456f37 --- /dev/null +++ b/developer/doc/ReleaseNotes/OpenStudio_Release_Notes_3_9_0_TBD.md @@ -0,0 +1,118 @@ +# OpenStudio Version 3.9.0 + +_Release Notes_ - _TDB_ + +These release notes describe version 3.9.0 of the OpenStudio SDK developed by the National Renewable Energy Laboratory (NREL), Buildings and Thermal Sciences Center, Commercial Buildings Research Group, Tools Development Section, and associated collaborators. The notes are organized into the following sections: + +- Overview +- Where to Find OpenStudio Documentation +- Installation Notes +- OpenStudio SDK: Changelog + +# Overview + +As of April 2020, development and distribution of the OpenStudioApplication and the SketchUp plugin have transitioned to the OpenStudio Coalition, who is independently managing and distributing the software through its own [openstudiocoalition/OpenStudioApplication](https://github.com/openstudiocoalition/OpenStudioApplication) repository. The OpenStudio SDK is continuing to be actively developed and distributed by NREL and is released two times per year, through a spring and a fall release. + +Below is the list of components that is included in this SDK installer: + +__**OpenStudio SDK 3.9.0**__ +- EnergyPlus +- Command Line Interface (CLI) +- Radiance +- Ruby API +- Python API +- C++ SDK + +**Note** that [PAT](https://github.com/NREL/OpenStudio-PAT) is not included in either the SDK or the OpenStudio Coalition's Application installers. You will need to install PAT separately which is distributed on the [OpenStudio-PAT](https://github.com/NREL/OpenStudio-PAT) GitHub page. + +# Where to Find OpenStudio SDK Documentation + +- OpenStudio SDK release documentation, including these release notes, tutorials, and other user documentation, is available at [https://www.openstudio.net/](https://www.openstudio.net/.) +- C++ API documentation is available at [OpenStudio SDK Documentation](https://openstudio-sdk-documentation.s3.amazonaws.com/index.html) +- Measure development documentation is available at [OpenStudio Measure Writer's Reference Guide](http://nrel.github.io/OpenStudio-user-documentation/reference/measure_writing_guide/ ) +- A roadmap for planned features is available at [Roadmap](http://nrel.github.io/OpenStudio-user-documentation/getting_started/roadmap/) + +# Installation Notes + +OpenStudio SDK 3.9.0 is supported on: + +* 64-bit Windows 7 – 11 +* macOS: 11.6+ x86_64, 12.1+ arm64 +* Ubuntu: 20.04 x86_64, 22.04 x86_64, 22.04 arm64 +* Centos7 + +OpenStudio SDK 3.9.0 supports [EnergyPlus Release 24.2.0a](https://github.com/NREL/EnergyPlus/releases/tag/24.2.0a), which is bundled with the OpenStudio installer. It is no longer necessary to download and install EnergyPlus separately. Other builds of EnergyPlus are not supported by OpenStudio SDK 3.9.0. + +OpenStudio SDK 3.9.0 supports Radiance 5.0.a.12, which is bundled with the OpenStudio installer; users no longer must install Radiance separately, and OpenStudio will use the included Radiance version regardless of any other versions that may be installed on the system. Other builds of Radiance are not supported by OpenStudio SDK 3.9.0. + +As usual, you can refer to the **[OpenStudio SDK Compatibility Matrix](https://github.com/NREL/OpenStudio/wiki/OpenStudio-SDK-Version-Compatibility-Matrix)** for more information. + + +## Installation Steps + +- Download and install [OpenStudio SDK](https://github.com/NREL/openstudio) and/or any third party tool that embeds the OpenStudio SDK into their software such as [openstudiocoalition/OpenStudioApplication](https://github.com/openstudiocoalition/OpenStudioApplication) depending on your needs. Select components for installation. Note that OpenStudio Application is a standalone app and does not require you to install OpenStudio SDK. +- A BCL AUth Key is no longer needed to access content on [Building Component Library (BCL)](https://bcl.nrel.gov) BCL is typically accessed through third party OpenStudio applications to provide modelers access to building components and OpenStudio measures; however you an also browse it and download content using the BCL link above. + +For help with common installation problems please visit [Getting Started](http://nrel.github.io/OpenStudio-user-documentation/getting_started/getting_started/). + +# OpenStudio SDK: Changelog + +The 3.9.0 is a **major** release. This update includes several new features, performance improvements, and bug fixes. + +## C++ Workflow code + +As of OpenStudio SDK 3.7.0 a re-written workflow written in C++ is used by default in place of the Ruby based Workflow Gem that had been used in the past. This enhancement is in support of Python measures being used in an OpenStudio workflow, including mixed language workflows that include both Ruby Measures and Python Measures. If you need to use the older Workflow Gem implementation, you can do that by using the `classic` subcommand after `openstudio`. `classic` will be deprecated in a future version of OpenStudio. + +## Python Bindings + +As of OpenStudio SDK 3.2.0, Python bindings are officially supported and distributed through Python Package Index (PyPI). To install, users will need to have Python3 installed along with pip and simply run the following command in a terminal window. + +`pip install openstudio==3.9.0` + +Please see [openstudio on PyPi](https://pypi.org/project/openstudio/) for further instructions on how to install. Users can also visit the test channel at [openstudio on TestPyPi](https://test.pypi.org/project/openstudio/) to install development bindings. + +You can also refer to the [OpenStudio SDK Python Binding Version Compatibility Matrix](https://github.com/NREL/OpenStudio/wiki/OpenStudio-SDK-Python-Binding-Version-Compatibility-Matrix) to see the list of supported platforms and python versions. + +## New Features, Major Fixes and API-breaking changes + +* [#5242](https://github.com/NREL/OpenStudio/pull/5242) - Update to EnergyPlus v24.2.0a + * To see the full list of additions and changes, refer to the issue [#5240](https://github.com/NREL/OpenStudio/issues/5240) + +* [#5237](https://github.com/NREL/OpenStudio/pull/5237) - Updates to Controller:OutdoorAir + * This PR implements the fields `Humidistat Control Zone Name` and `Electronic Enthalpy Limit Curve` + * `ControllerOutdoorAir` has two API-breaking changes for `High Humidity Outdoor Air Flow Ratio` and `Control High Indoor Humidity Based on Outdoor Humidity Ratio`. These fields are now-required, so the getters no longer return an optional + * `getHighHumidityOutdoorAirFlowRatio` (`boost::optional` to `double`) + * `getControlHighIndoorHumidityBasedOnOutdoorHumidityRatio` (`boost::optional` to `bool`) + +## Minor changes and bug fixes + +Refer to the changelog on the release page at [v3.9.0](https://github.com/NREL/OpenStudio/releases/v3.9.0) + +**Full Changelog**: https://github.com/NREL/OpenStudio/compare/v3.9.0...v3.9.0 + +**New Contributors**: + +### OpenStudio Standards v@STANDARDS_VERSION@ + +Update the openstudio-standards gem to version [@STANDARDS_VERSION@](https://github.com/NREL/openstudio-standards/releases/tag/v@STANDARDS_VERSION@) +In addition to some refactoring, this release also included conversion of 90.1 data to formal database. + + +### OpenStudio Server vXXX + + + + +--- +# This YAML header controls the pandoc (via TeX) to PDF settings +# To convert the markdown to pdf, do `pandoc release_notes.md -o release_notes.pdf` +title: 'OpenStudio Release Notes - 3.9.0' +author: +- National Renewable Energy Laboratory +colorlinks: true +linkcolor: blue +urlcolor: Mahogany +toccolor: gray +geometry: +- margin=1in +--- diff --git a/developer/doc/ReleaseNotes/ReleaseNotes_template.md b/developer/doc/ReleaseNotes/ReleaseNotes_template.md index 66362ec6f98..e24f1ddbf2f 100644 --- a/developer/doc/ReleaseNotes/ReleaseNotes_template.md +++ b/developer/doc/ReleaseNotes/ReleaseNotes_template.md @@ -20,6 +20,7 @@ __**OpenStudio SDK @VERSION@**__ - Command Line Interface (CLI) - Radiance - Ruby API +- Python API - C++ SDK **Note** that [PAT](https://github.com/NREL/OpenStudio-PAT) is not included in either the SDK or the OpenStudio Coalition's Application installers. You will need to install PAT separately which is distributed on the [OpenStudio-PAT](https://github.com/NREL/OpenStudio-PAT) GitHub page. @@ -27,20 +28,20 @@ __**OpenStudio SDK @VERSION@**__ # Where to Find OpenStudio SDK Documentation - OpenStudio SDK release documentation, including these release notes, tutorials, and other user documentation, is available at [https://www.openstudio.net/](https://www.openstudio.net/.) -- C++ API documentation is available at [https://openstudio-sdk-documentation.s3.amazonaws.com/index.html](https://openstudio-sdk-documentation.s3.amazonaws.com/index.html) -- Measure development documentation is available at [http://nrel.github.io/OpenStudio-user-documentation/reference/measure_writing_guide/](http://nrel.github.io/OpenStudio-user-documentation/reference/measure_writing_guide/ ) -- A roadmap for planned features is available at http://nrel.github.io/OpenStudio-user-documentation/getting_started/roadmap/. +- C++ API documentation is available at [OpenStudio SDK Documentation](https://openstudio-sdk-documentation.s3.amazonaws.com/index.html) +- Measure development documentation is available at [OpenStudio Measure Writer's Reference Guide](http://nrel.github.io/OpenStudio-user-documentation/reference/measure_writing_guide/ ) +- A roadmap for planned features is available at [Roadmap](http://nrel.github.io/OpenStudio-user-documentation/getting_started/roadmap/) # Installation Notes OpenStudio SDK @VERSION@ is supported on: * 64-bit Windows 7 – 11 -* macOS: 10.15+ x86_64, 12.1+ arm64 +* macOS: 11.6+ x86_64, 12.1+ arm64 * Ubuntu: 20.04 x86_64, 22.04 x86_64, 22.04 arm64 * Centos7 -OpenStudio SDK @VERSION@ supports [EnergyPlus Release 23.1.0](https://github.com/NREL/EnergyPlus/releases/tag/v23.1.0), which is bundled with the OpenStudio installer. It is no longer necessary to download and install EnergyPlus separately. Other builds of EnergyPlus are not supported by OpenStudio SDK @VERSION@. +OpenStudio SDK @VERSION@ supports [EnergyPlus Release @EP_VERSION@](https://github.com/NREL/EnergyPlus/releases/tag/v@EP_VERSION@), which is bundled with the OpenStudio installer. It is no longer necessary to download and install EnergyPlus separately. Other builds of EnergyPlus are not supported by OpenStudio SDK @VERSION@. OpenStudio SDK @VERSION@ supports Radiance 5.0.a.12, which is bundled with the OpenStudio installer; users no longer must install Radiance separately, and OpenStudio will use the included Radiance version regardless of any other versions that may be installed on the system. Other builds of Radiance are not supported by OpenStudio SDK @VERSION@. @@ -49,17 +50,18 @@ As usual, you can refer to the **[OpenStudio SDK Compatibility Matrix](https://g ## Installation Steps -- Download and install [OpenStudio SDK](https://github.com/NREL/openstudio) and/or [openstudiocoalition/OpenStudioApplication](https://github.com/openstudiocoalition/OpenStudioApplication) depending on your needs. Select components for installation. Note that OpenStudio Application is a standalone app and does not require you to install OpenStudio SDK. -- Setup a Building Component Library (BCL) account to access online building components and measures. View instructions on how to setup your account and configure the key in OpenStudio. -- The OpenStudio Application SketchUp Plug-in requires SketchUp 2021-2022 (not available for Linux). The OpenStudio Application SketchUp Plug-in does not support older versions of SketchUp. SketchUp must be installed before OpenStudio Application to automatically activate the plugin. If you install SketchUp after OpenStudio Application, simply re-run the OpenStudio Application installer. +- Download and install [OpenStudio SDK](https://github.com/NREL/openstudio) and/or any third party tool that embeds the OpenStudio SDK into their software such as [openstudiocoalition/OpenStudioApplication](https://github.com/openstudiocoalition/OpenStudioApplication) depending on your needs. Select components for installation. Note that OpenStudio Application is a standalone app and does not require you to install OpenStudio SDK. +- A BCL AUth Key is no longer needed to access content on [Building Component Library (BCL)](https://bcl.nrel.gov) BCL is typically accessed through third party OpenStudio applications to provide modelers access to building components and OpenStudio measures; however you an also browse it and download content using the BCL link above. -For help with common installation problems please visit, http://nrel.github.io/OpenStudio-user-documentation/getting_started/getting_started/. +For help with common installation problems please visit [Getting Started](http://nrel.github.io/OpenStudio-user-documentation/getting_started/getting_started/). # OpenStudio SDK: Changelog -The @VERSION@ is a release. This update includes several new features, performance improvements, and bug fixes. -You can find the list of Pull Requests that got into this release [here](https://github.com/NREL/OpenStudio/pulls?utf8=%E2%9C%93&q=is%3Apr+is%3Aclosed+created%3A2023-05-12..2023-10-26+). +The @VERSION@ is a **** release. This update includes several new features, performance improvements, and bug fixes. +## C++ Workflow code + +As of OpenStudio SDK 3.7.0 a re-written workflow written in C++ is used by default in place of the Ruby based Workflow Gem that had been used in the past. This enhancement is in support of Python measures being used in an OpenStudio workflow, including mixed language workflows that include both Ruby Measures and Python Measures. If you need to use the older Workflow Gem implementation, you can do that by using the `classic` subcommand after `openstudio`. `classic` will be deprecated in a future version of OpenStudio. ## Python Bindings @@ -78,16 +80,33 @@ You can also refer to the [OpenStudio SDK Python Binding Version Compatibility M ## Minor changes and bug fixes +Refer to the changelog on the release page at [v@VERSION@](https://github.com/NREL/OpenStudio/releases/v@VERSION@) **Full Changelog**: https://github.com/NREL/OpenStudio/compare/v@VERSION@...v@VERSION@ **New Contributors**: -### OpenStudio Standards vXXX +### OpenStudio Standards v@STANDARDS_VERSION@ + +Update the openstudio-standards gem to version [@STANDARDS_VERSION@](https://github.com/NREL/openstudio-standards/releases/tag/v@STANDARDS_VERSION@) +In addition to some refactoring, this release also included conversion of 90.1 data to formal database. ### OpenStudio Server vXXX -## Issue Statistics Since Previous Release + +--- +# This YAML header controls the pandoc (via TeX) to PDF settings +# To convert the markdown to pdf, do `pandoc release_notes.md -o release_notes.pdf` +title: 'OpenStudio Release Notes - @VERSION@' +author: +- National Renewable Energy Laboratory +colorlinks: true +linkcolor: blue +urlcolor: Mahogany +toccolor: gray +geometry: +- margin=1in +--- diff --git a/resources/model/OpenStudio.idd b/resources/model/OpenStudio.idd index 105e0d2169f..95d26f8ffdc 100644 --- a/resources/model/OpenStudio.idd +++ b/resources/model/OpenStudio.idd @@ -22427,7 +22427,7 @@ OS:Controller:OutdoorAir, \note This field is only used when the field High Humidity Control = Yes. \type real \minimum> 0 - \default 1.0 + \required-field A19, \field Control High Indoor Humidity Based on Outdoor Humidity Ratio \note If No is selected, the outdoor air flow rate is modified any time indoor relative \note humidity is above the humidistat setpoint. If Yes is selected, the outdoor air @@ -22435,7 +22435,7 @@ OS:Controller:OutdoorAir, \note setpoint and the outdoor humidity ratio is less than the indoor humidity ratio. \note This field is only used when the field High Humidity Control = Yes. \type choice - \default Yes + \required-field \key Yes \key No A20, \field Heat Recovery Bypass Control Type diff --git a/src/energyplus/ForwardTranslator/ForwardTranslateControllerOutdoorAir.cpp b/src/energyplus/ForwardTranslator/ForwardTranslateControllerOutdoorAir.cpp index 989cd310e08..3b4ebd3b03c 100644 --- a/src/energyplus/ForwardTranslator/ForwardTranslateControllerOutdoorAir.cpp +++ b/src/energyplus/ForwardTranslator/ForwardTranslateControllerOutdoorAir.cpp @@ -9,6 +9,9 @@ #include "../../model/ControllerMechanicalVentilation.hpp" #include "../../model/Node.hpp" #include "../../model/Schedule.hpp" +#include "../../model/ThermalZone.hpp" +#include "../../model/Curve.hpp" +#include "../../model/ZoneControlHumidistat.hpp" #include #include @@ -119,9 +122,14 @@ namespace energyplus { } else { idfObject.setString(openstudio::Controller_OutdoorAirFields::EconomizerMaximumLimitDewpointTemperature, ""); } + /////////////////////////////////////////////////////////////////////////// // Field: Electronic Enthalpy Limit Curve Name //////////////////////////// - idfObject.setString(openstudio::Controller_OutdoorAirFields::ElectronicEnthalpyLimitCurveName, ""); + if (boost::optional curve = modelObject.electronicEnthalpyLimitCurve()) { + if (boost::optional _curve = translateAndMapModelObject(curve.get())) { + idfObject.setString(Controller_OutdoorAirFields::ElectronicEnthalpyLimitCurveName, _curve->name().get()); + } + } /////////////////////////////////////////////////////////////////////////// // Field: Economizer Minimum Limit DryBulb Temperature //////////////////// @@ -151,6 +159,17 @@ namespace energyplus { } } + // HumidistatControlZoneName + if (auto zone_ = modelObject.humidistatControlZone()) { + if (boost::optional humidistat = zone_->zoneControlHumidistat()) { + idfObject.setString(openstudio::Controller_OutdoorAirFields::HumidistatControlZoneName, zone_->nameString()); + } else { + LOG(Warn, modelObject.briefDescription() << " has a humidistat control zone " << zone_->nameString() + << " without a zone control humidistat; humidistat control zone field will not be translated"); + idfObject.setString(openstudio::Controller_OutdoorAirFields::HighHumidityControl, "No"); + } + } + // HighHumidityOutdoorAirFlowRatio d = modelObject.getHighHumidityOutdoorAirFlowRatio(); if (d) { @@ -158,13 +177,10 @@ namespace energyplus { } // ControlHighIndoorHumidityBasedonOutdoorHumidityRatio - ob = modelObject.getControlHighIndoorHumidityBasedOnOutdoorHumidityRatio(); - if (ob) { - if (*ob) { - idfObject.setString(openstudio::Controller_OutdoorAirFields::ControlHighIndoorHumidityBasedonOutdoorHumidityRatio, "Yes"); - } else { - idfObject.setString(openstudio::Controller_OutdoorAirFields::ControlHighIndoorHumidityBasedonOutdoorHumidityRatio, "No"); - } + if (modelObject.getControlHighIndoorHumidityBasedOnOutdoorHumidityRatio()) { + idfObject.setString(openstudio::Controller_OutdoorAirFields::ControlHighIndoorHumidityBasedonOutdoorHumidityRatio, "Yes"); + } else { + idfObject.setString(openstudio::Controller_OutdoorAirFields::ControlHighIndoorHumidityBasedonOutdoorHumidityRatio, "No"); } // HeatRecoveryBypassControlType diff --git a/src/energyplus/ReverseTranslator/ReverseTranslateControllerOutdoorAir.cpp b/src/energyplus/ReverseTranslator/ReverseTranslateControllerOutdoorAir.cpp index 4fb7d3fe808..3b7450b05ee 100644 --- a/src/energyplus/ReverseTranslator/ReverseTranslateControllerOutdoorAir.cpp +++ b/src/energyplus/ReverseTranslator/ReverseTranslateControllerOutdoorAir.cpp @@ -6,6 +6,14 @@ #include "../ReverseTranslator.hpp" #include "../../model/ControllerOutdoorAir.hpp" #include "../../model/ControllerOutdoorAir_Impl.hpp" +#include "../../model/ThermalZone.hpp" +#include "../../model/ThermalZone_Impl.hpp" +#include "../../model/Space.hpp" +#include "../../model/Space_Impl.hpp" +#include "../../model/Curve.hpp" +#include "../../model/Curve_Impl.hpp" +#include "../../model/Schedule.hpp" +#include "../../model/Schedule_Impl.hpp" #include #include "../../utilities/idd/IddEnums.hpp" #include @@ -22,6 +30,9 @@ namespace energyplus { return boost::none; } + boost::optional _wo; + boost::optional _mo; + ControllerOutdoorAir mo(m_model); boost::optional s = workspaceObject.getString(Controller_OutdoorAirFields::Name); @@ -64,9 +75,14 @@ namespace energyplus { mo.setEconomizerMaximumLimitDewpointTemperature(value.get()); } - s = workspaceObject.getString(Controller_OutdoorAirFields::ElectronicEnthalpyLimitCurveName); - if (s) { - LOG(Error, "ControllerOutdoorAir " << workspaceObject.briefDescription() << " references a curve that is not supported"); + if ((_wo = workspaceObject.getTarget(Controller_OutdoorAirFields::ElectronicEnthalpyLimitCurveName))) { + if ((_mo = translateAndMapWorkspaceObject(_wo.get()))) { + if (boost::optional _curve = _mo->optionalCast()) { + mo.setElectronicEnthalpyLimitCurve(_curve.get()); + } else { + LOG(Warn, workspaceObject.briefDescription() << " has a wrong type for 'Electronic Enthalpy Limit Curve Name'"); + } + } } value = workspaceObject.getDouble(Controller_OutdoorAirFields::EconomizerMinimumLimitDryBulbTemperature); @@ -84,22 +100,34 @@ namespace energyplus { mo.setMinimumLimitType(s.get()); } - s = workspaceObject.getString(Controller_OutdoorAirFields::MinimumOutdoorAirScheduleName); - if (s) { - LOG(Warn, - "ControllerOutdoorAir " << workspaceObject.briefDescription() << " references a minimum outdoor air schedule, which is not supported"); + if ((_wo = workspaceObject.getTarget(Controller_OutdoorAirFields::MinimumOutdoorAirScheduleName))) { + if ((_mo = translateAndMapWorkspaceObject(_wo.get()))) { + if (boost::optional _schedule = _mo->optionalCast()) { + mo.setMinimumOutdoorAirSchedule(_schedule.get()); + } else { + LOG(Warn, workspaceObject.briefDescription() << " has a wrong type for 'Minimum Outdoor Air Schedule Name'"); + } + } } - s = workspaceObject.getString(Controller_OutdoorAirFields::MinimumFractionofOutdoorAirScheduleName); - if (s) { - LOG(Warn, "ControllerOutdoorAir " << workspaceObject.briefDescription() - << " references a minimum fraction of outdoor air schedule, which is not supported"); + if ((_wo = workspaceObject.getTarget(Controller_OutdoorAirFields::MinimumFractionofOutdoorAirScheduleName))) { + if ((_mo = translateAndMapWorkspaceObject(_wo.get()))) { + if (boost::optional _schedule = _mo->optionalCast()) { + mo.setMinimumFractionofOutdoorAirSchedule(_schedule.get()); + } else { + LOG(Warn, workspaceObject.briefDescription() << " has a wrong type for 'Minimum Fraction of Outdoor Air Schedule Name'"); + } + } } - s = workspaceObject.getString(Controller_OutdoorAirFields::MaximumFractionofOutdoorAirScheduleName); - if (s) { - LOG(Warn, "ControllerOutdoorAir " << workspaceObject.briefDescription() - << " references a maximum fraction of outdoor air schedule, which is not supported"); + if ((_wo = workspaceObject.getTarget(Controller_OutdoorAirFields::MaximumFractionofOutdoorAirScheduleName))) { + if ((_mo = translateAndMapWorkspaceObject(_wo.get()))) { + if (boost::optional _schedule = _mo->optionalCast()) { + mo.setMaximumFractionofOutdoorAirSchedule(_schedule.get()); + } else { + LOG(Warn, workspaceObject.briefDescription() << " has a wrong type for 'Maximum Fraction of Outdoor Air Schedule Name'"); + } + } } s = workspaceObject.getString(Controller_OutdoorAirFields::MechanicalVentilationControllerName); @@ -108,24 +136,27 @@ namespace energyplus { "ControllerOutdoorAir " << workspaceObject.briefDescription() << " references a mechanical ventilation controller, which is not supported"); } - s = workspaceObject.getString(Controller_OutdoorAirFields::TimeofDayEconomizerControlScheduleName); - if (s) { - LOG(Warn, "ControllerOutdoorAir " << workspaceObject.briefDescription() - << " references a time of day economizer control schedule, which is not supported"); - } - - s = workspaceObject.getString(Controller_OutdoorAirFields::HighHumidityControl); - if (s) { - if (istringEqual("Yes", s.get())) { - mo.setHighHumidityControl(true); - } else { - mo.setHighHumidityControl(false); + if ((_wo = workspaceObject.getTarget(Controller_OutdoorAirFields::TimeofDayEconomizerControlScheduleName))) { + if ((_mo = translateAndMapWorkspaceObject(_wo.get()))) { + if (boost::optional _schedule = _mo->optionalCast()) { + mo.setTimeofDayEconomizerControlSchedule(_schedule.get()); + } else { + LOG(Warn, workspaceObject.briefDescription() << " has a wrong type for 'Time of Day Economizer Control Schedule Name'"); + } } } - s = workspaceObject.getString(Controller_OutdoorAirFields::HumidistatControlZoneName); - if (s) { - LOG(Warn, "ControllerOutdoorAir " << workspaceObject.briefDescription() << " references a high humidity control zone, which is not supported"); + if ((_wo = workspaceObject.getTarget(Controller_OutdoorAirFields::HumidistatControlZoneName))) { + if ((_mo = translateAndMapWorkspaceObject(_wo.get()))) { + // Zone is translated, and a Space is returned instead + if (boost::optional space_ = _mo->optionalCast()) { + if (auto z_ = space_->thermalZone()) { + mo.setHumidistatControlZone(z_.get()); + } + } else { + LOG(Warn, workspaceObject.briefDescription() << " has a wrong type for 'Humidistat Control Zone Name'"); + } + } } value = workspaceObject.getDouble(Controller_OutdoorAirFields::HighHumidityOutdoorAirFlowRatio); diff --git a/src/energyplus/ReverseTranslator/ReverseTranslateFanSystemModel.cpp b/src/energyplus/ReverseTranslator/ReverseTranslateFanSystemModel.cpp index 7d6229fbaa1..95f3b3dd148 100644 --- a/src/energyplus/ReverseTranslator/ReverseTranslateFanSystemModel.cpp +++ b/src/energyplus/ReverseTranslator/ReverseTranslateFanSystemModel.cpp @@ -133,6 +133,7 @@ namespace energyplus { } } } + // Night Ventilation Mode Pressure Rise: Optional Double if (boost::optional _nightVentilationModePressureRise = workspaceObject.getDouble(Fan_SystemModelFields::NightVentilationModePressureRise)) { diff --git a/src/model/AirConditionerVariableRefrigerantFlow.cpp b/src/model/AirConditionerVariableRefrigerantFlow.cpp index b91756d0af8..10160f2ceb4 100644 --- a/src/model/AirConditionerVariableRefrigerantFlow.cpp +++ b/src/model/AirConditionerVariableRefrigerantFlow.cpp @@ -1064,7 +1064,6 @@ namespace model { bool AirConditionerVariableRefrigerantFlow_Impl::setHeatPumpWasteHeatRecovery(bool heatPumpWasteHeatRecovery) { return setBooleanFieldValue(OS_AirConditioner_VariableRefrigerantFlowFields::HeatPumpWasteHeatRecovery, heatPumpWasteHeatRecovery); - ; } bool AirConditionerVariableRefrigerantFlow_Impl::setEquivalentPipingLengthusedforPipingCorrectionFactorinCoolingMode( diff --git a/src/model/ControllerOutdoorAir.cpp b/src/model/ControllerOutdoorAir.cpp index 284665f9e1c..21affb4dc7f 100644 --- a/src/model/ControllerOutdoorAir.cpp +++ b/src/model/ControllerOutdoorAir.cpp @@ -11,12 +11,14 @@ #include "ControllerMechanicalVentilation_Impl.hpp" #include "ScheduleCompact.hpp" #include "ScheduleCompact_Impl.hpp" -#include "CurveQuadratic.hpp" -#include "CurveQuadratic_Impl.hpp" +#include "Curve.hpp" +#include "Curve_Impl.hpp" #include "AirflowNetworkOutdoorAirflow.hpp" #include "AirflowNetworkOutdoorAirflow_Impl.hpp" #include "AirflowNetworkCrack.hpp" #include "AirflowNetworkCrack_Impl.hpp" +#include "ThermalZone.hpp" +#include "ThermalZone_Impl.hpp" #include "Model.hpp" #include "Model_Impl.hpp" @@ -25,6 +27,7 @@ #include #include "../utilities/core/Compare.hpp" #include "../utilities/core/Assert.hpp" +#include "../utilities/core/DeprecatedHelpers.hpp" using openstudio::Handle; using openstudio::OptionalHandle; @@ -86,70 +89,24 @@ namespace model { // return any children objects in the hierarchy std::vector ControllerOutdoorAir_Impl::children() const { std::vector result; - //result.push_back(this->getElectronicEnthalpyLimitCurve()); - //result.push_back(this->getMinimumOutdoorAirSchedule()); - //result.push_back(this->getMinimumFractionOfOutdoorAirSchedule()); - //result.push_back(this->getMaximumFractionOfOutdoorAirSchedule()); - //result.push_back(this->getTimeOfDayEconomizerControlSchedule()); std::vector myAFNItems = getObject().getModelObjectSources(AirflowNetworkOutdoorAirflow::iddObjectType()); result.insert(result.end(), myAFNItems.begin(), myAFNItems.end()); return result; } - CurveQuadratic ControllerOutdoorAir_Impl::getElectronicEnthalpyLimitCurve() const { - try { - OptionalWorkspaceObject wo = this->getTarget(openstudio::OS_Controller_OutdoorAirFields::ElectronicEnthalpyLimitCurveName); - OptionalCurveQuadratic curveQuadratic = wo->optionalCast(); - return *curveQuadratic; - } catch (...) { - LOG(Error, "Failed to retrieve electronic enthalpy limit curve") - throw; - } - } - - ScheduleCompact ControllerOutdoorAir_Impl::getMinimumOutdoorAirSchedule() const { - try { - OptionalWorkspaceObject wo = this->getTarget(openstudio::OS_Controller_OutdoorAirFields::MinimumOutdoorAirScheduleName); - OptionalScheduleCompact schedule = wo->optionalCast(); - return *schedule; - } catch (...) { - LOG(Error, "Failed to retrieve minimum outdoor air schedule") - throw; - } - } - - ScheduleCompact ControllerOutdoorAir_Impl::getMinimumFractionOfOutdoorAirSchedule() const { - try { - OptionalWorkspaceObject wo = this->getTarget(openstudio::OS_Controller_OutdoorAirFields::MinimumFractionofOutdoorAirScheduleName); - OptionalScheduleCompact schedule = wo->optionalCast(); - return *schedule; - } catch (...) { - LOG(Error, "Failed to retrieve minimum fraciton of outdoor air schedule") - throw; - } + boost::optional ControllerOutdoorAir_Impl::electronicEnthalpyLimitCurve() const { + return getObject().getModelObjectTarget(OS_Controller_OutdoorAirFields::ElectronicEnthalpyLimitCurveName); } - ScheduleCompact ControllerOutdoorAir_Impl::getMaximumFractionOfOutdoorAirSchedule() const { - try { - OptionalWorkspaceObject wo = this->getTarget(openstudio::OS_Controller_OutdoorAirFields::MaximumFractionofOutdoorAirScheduleName); - OptionalScheduleCompact schedule = wo->optionalCast(); - return *schedule; - } catch (...) { - LOG(Error, "Failed to retrieve maximum fraction of outdoor air schedule") - throw; - } + bool ControllerOutdoorAir_Impl::setElectronicEnthalpyLimitCurve(const Curve& curve) { + bool result = setPointer(OS_Controller_OutdoorAirFields::ElectronicEnthalpyLimitCurveName, curve.handle()); + return result; } - ScheduleCompact ControllerOutdoorAir_Impl::getTimeOfDayEconomizerControlSchedule() const { - try { - OptionalWorkspaceObject wo = this->getTarget(openstudio::OS_Controller_OutdoorAirFields::TimeofDayEconomizerControlScheduleName); - OptionalScheduleCompact schedule = wo->optionalCast(); - return *schedule; - } catch (...) { - LOG(Error, "Failed to retrieve time of day economizer control schedule") - throw; - } + void ControllerOutdoorAir_Impl::resetElectronicEnthalpyLimitCurve() { + bool result = setString(OS_Controller_OutdoorAirFields::ElectronicEnthalpyLimitCurveName, ""); + OS_ASSERT(result); } OptionalAirLoopHVACOutdoorAirSystem ControllerOutdoorAir_Impl::airLoopHVACOutdoorAirSystem() const { @@ -224,7 +181,6 @@ namespace model { bool ControllerOutdoorAir_Impl::setEconomizerControlType(const std::string& value) { return setString(openstudio::OS_Controller_OutdoorAirFields::EconomizerControlType, value); - ; } std::string ControllerOutdoorAir_Impl::getEconomizerControlActionType() const { @@ -233,7 +189,6 @@ namespace model { bool ControllerOutdoorAir_Impl::setEconomizerControlActionType(const std::string& value) { return setString(openstudio::OS_Controller_OutdoorAirFields::EconomizerControlActionType, value); - ; } //get needs to return a boost optional double since "" is a valid input @@ -303,7 +258,6 @@ namespace model { bool ControllerOutdoorAir_Impl::setLockoutType(const std::string& value) { return setString(openstudio::OS_Controller_OutdoorAirFields::LockoutType, value); - ; } std::string ControllerOutdoorAir_Impl::getMinimumLimitType() const { @@ -312,60 +266,45 @@ namespace model { bool ControllerOutdoorAir_Impl::setMinimumLimitType(const std::string& value) { return setString(openstudio::OS_Controller_OutdoorAirFields::MinimumLimitType, value); - ; } boost::optional ControllerOutdoorAir_Impl::getHighHumidityControl() const { - boost::optional retVal; + return getBooleanFieldValue(OS_Controller_OutdoorAirFields::HighHumidityControl); + } - if (OptionalString s = getString(OS_Controller_OutdoorAirFields::HighHumidityControl)) { - if (istringEqual(s.get(), "yes")) { - retVal = true; - } else { - retVal = false; - } - } + boost::optional ControllerOutdoorAir_Impl::humidistatControlZone() const { + return getObject().getModelObjectTarget(OS_Controller_OutdoorAirFields::HumidistatControlZoneName); + } - return retVal; + bool ControllerOutdoorAir_Impl::setHumidistatControlZone(const ThermalZone& thermalZone) { + bool result = setPointer(OS_Controller_OutdoorAirFields::HumidistatControlZoneName, thermalZone.handle()); + result = result && setString(OS_Controller_OutdoorAirFields::HighHumidityControl, "Yes"); + return result; } - bool ControllerOutdoorAir_Impl::setHighHumidityControl(bool val) { - if (val) { - return setString(OS_Controller_OutdoorAirFields::HighHumidityControl, "Yes"); - } else { - return setString(OS_Controller_OutdoorAirFields::HighHumidityControl, "No"); - } + void ControllerOutdoorAir_Impl::resetHumidistatControlZone() { + bool result = setString(OS_Controller_OutdoorAirFields::HumidistatControlZoneName, ""); + result = result && setString(OS_Controller_OutdoorAirFields::HighHumidityControl, "No"); + OS_ASSERT(result); } - OptionalDouble ControllerOutdoorAir_Impl::getHighHumidityOutdoorAirFlowRatio() const { - return getDouble(openstudio::OS_Controller_OutdoorAirFields::HighHumidityOutdoorAirFlowRatio); + double ControllerOutdoorAir_Impl::getHighHumidityOutdoorAirFlowRatio() const { + boost::optional value = getDouble(openstudio::OS_Controller_OutdoorAirFields::HighHumidityOutdoorAirFlowRatio, true); + OS_ASSERT(value); + return value.get(); } + bool ControllerOutdoorAir_Impl::setHighHumidityOutdoorAirFlowRatio(double v) { - return setDouble(openstudio::OS_Controller_OutdoorAirFields::HighHumidityOutdoorAirFlowRatio, v); - ; + bool result = setDouble(openstudio::OS_Controller_OutdoorAirFields::HighHumidityOutdoorAirFlowRatio, v); + return result; } - boost::optional ControllerOutdoorAir_Impl::getControlHighIndoorHumidityBasedOnOutdoorHumidityRatio() const { - boost::optional retVal; - OptionalString s = getString(OS_Controller_OutdoorAirFields::ControlHighIndoorHumidityBasedonOutdoorHumidityRatio); - if (!s) { - return retVal; - } - std::string temp = *s; - boost::to_lower(temp); - if (temp == "no") { - retVal = false; - } else { - retVal = true; - } - return retVal; + bool ControllerOutdoorAir_Impl::getControlHighIndoorHumidityBasedOnOutdoorHumidityRatio() const { + return getBooleanFieldValue(OS_Controller_OutdoorAirFields::ControlHighIndoorHumidityBasedonOutdoorHumidityRatio); } + bool ControllerOutdoorAir_Impl::setControlHighIndoorHumidityBasedOnOutdoorHumidityRatio(bool v) { - if (v) { - return setString(OS_Controller_OutdoorAirFields::ControlHighIndoorHumidityBasedonOutdoorHumidityRatio, "No"); - } else { - return setString(OS_Controller_OutdoorAirFields::ControlHighIndoorHumidityBasedonOutdoorHumidityRatio, "Yes"); - } + return setBooleanFieldValue(OS_Controller_OutdoorAirFields::ControlHighIndoorHumidityBasedonOutdoorHumidityRatio, v); } OptionalString ControllerOutdoorAir_Impl::getHeatRecoveryBypassControlType() const { @@ -599,10 +538,9 @@ namespace model { setString(OS_Controller_OutdoorAirFields::MaximumFractionofOutdoorAirScheduleName, ""); setString(OS_Controller_OutdoorAirFields::ControllerMechanicalVentilation, ""); setString(OS_Controller_OutdoorAirFields::TimeofDayEconomizerControlScheduleName, ""); - setHighHumidityControl(false); - setString(OS_Controller_OutdoorAirFields::HumidistatControlZoneName, ""); - setString(OS_Controller_OutdoorAirFields::HighHumidityOutdoorAirFlowRatio, ""); - setString(OS_Controller_OutdoorAirFields::ControlHighIndoorHumidityBasedonOutdoorHumidityRatio, ""); + setString(OS_Controller_OutdoorAirFields::HighHumidityControl, "No"); + setHighHumidityOutdoorAirFlowRatio(1.0); + setControlHighIndoorHumidityBasedOnOutdoorHumidityRatio(true); setHeatRecoveryBypassControlType("BypassWhenWithinEconomizerLimits"); setEconomizerOperationStaging("InterlockedWithMechanicalCooling"); @@ -612,24 +550,16 @@ namespace model { ControllerOutdoorAir::ControllerOutdoorAir(std::shared_ptr impl) : ParentObject(std::move(impl)) {} - CurveQuadratic ControllerOutdoorAir::getElectronicEnthalpyLimitCurve() const { - return getImpl()->getElectronicEnthalpyLimitCurve(); + boost::optional ControllerOutdoorAir::electronicEnthalpyLimitCurve() const { + return getImpl()->electronicEnthalpyLimitCurve(); } - ScheduleCompact ControllerOutdoorAir::getMinimumOutdoorAirSchedule() const { - return getImpl()->getMinimumOutdoorAirSchedule(); + bool ControllerOutdoorAir::setElectronicEnthalpyLimitCurve(const Curve& curve) { + return getImpl()->setElectronicEnthalpyLimitCurve(curve); } - ScheduleCompact ControllerOutdoorAir::getMinimumFractionOfOutdoorAirSchedule() const { - return getImpl()->getMinimumFractionOfOutdoorAirSchedule(); - } - - ScheduleCompact ControllerOutdoorAir::getMaximumFractionOfOutdoorAirSchedule() const { - return getImpl()->getMaximumFractionOfOutdoorAirSchedule(); - } - - ScheduleCompact ControllerOutdoorAir::getTimeOfDayEconomizerControlSchedule() const { - return getImpl()->getTimeOfDayEconomizerControlSchedule(); + void ControllerOutdoorAir::resetElectronicEnthalpyLimitCurve() { + getImpl()->resetElectronicEnthalpyLimitCurve(); } boost::optional ControllerOutdoorAir::airLoopHVACOutdoorAirSystem() const { @@ -725,10 +655,23 @@ namespace model { } bool ControllerOutdoorAir::setHighHumidityControl(bool val) { - return getImpl()->setHighHumidityControl(val); + DEPRECATED_AT_MSG(3, 8, 0, "Use setHumidistatControlZone instead."); + return false; + } + + boost::optional ControllerOutdoorAir::humidistatControlZone() const { + return getImpl()->humidistatControlZone(); + } + + bool ControllerOutdoorAir::setHumidistatControlZone(const ThermalZone& thermalZone) { + return getImpl()->setHumidistatControlZone(thermalZone); + } + + void ControllerOutdoorAir::resetHumidistatControlZone() { + getImpl()->resetHumidistatControlZone(); } - boost::optional ControllerOutdoorAir::getHighHumidityOutdoorAirFlowRatio() const { + double ControllerOutdoorAir::getHighHumidityOutdoorAirFlowRatio() const { return getImpl()->getHighHumidityOutdoorAirFlowRatio(); } @@ -736,7 +679,7 @@ namespace model { return getImpl()->setHighHumidityOutdoorAirFlowRatio(v); } - boost::optional ControllerOutdoorAir::getControlHighIndoorHumidityBasedOnOutdoorHumidityRatio() const { + bool ControllerOutdoorAir::getControlHighIndoorHumidityBasedOnOutdoorHumidityRatio() const { return getImpl()->getControlHighIndoorHumidityBasedOnOutdoorHumidityRatio(); } diff --git a/src/model/ControllerOutdoorAir.hpp b/src/model/ControllerOutdoorAir.hpp index 125b29b2dcb..aaf95cc0cb5 100644 --- a/src/model/ControllerOutdoorAir.hpp +++ b/src/model/ControllerOutdoorAir.hpp @@ -8,6 +8,7 @@ #include "ModelAPI.hpp" #include "ParentObject.hpp" +#include "../utilities/core/Deprecated.hpp" namespace openstudio { @@ -19,12 +20,13 @@ namespace model { } // namespace detail - class CurveQuadratic; + class Curve; class ScheduleCompact; class ControllerMechanicalVentilation; class AirLoopHVACOutdoorAirSystem; class AirflowNetworkOutdoorAirflow; class AirflowNetworkCrack; + class ThermalZone; class MODEL_API ControllerOutdoorAir : public ParentObject { @@ -90,8 +92,9 @@ namespace model { bool setEconomizerMaximumLimitDewpointTemperature(double value); void resetEconomizerMaximumLimitDewpointTemperature(); - //QuadraticCurve getElectronicEnthalpyLimitCurve() const; - //bool setElectronicEnthalpyLimitCurve(QuadraticCurve c); + boost::optional electronicEnthalpyLimitCurve() const; + bool setElectronicEnthalpyLimitCurve(const Curve& curve); + void resetElectronicEnthalpyLimitCurve(); //get needs to return a boost optional double since "" is a valid input boost::optional getEconomizerMinimumLimitDryBulbTemperature() const; @@ -105,15 +108,16 @@ namespace model { bool setMinimumLimitType(const std::string& value); boost::optional getHighHumidityControl() const; - bool setHighHumidityControl(bool val); + OS_DEPRECATED(3, 8, 0) bool setHighHumidityControl(bool val); - //Zone getHumidistatControlZone() const; - //bool setHumidistatControlZone(Zone z) + boost::optional humidistatControlZone() const; + bool setHumidistatControlZone(const ThermalZone& thermalZone); + void resetHumidistatControlZone(); - boost::optional getHighHumidityOutdoorAirFlowRatio() const; + double getHighHumidityOutdoorAirFlowRatio() const; bool setHighHumidityOutdoorAirFlowRatio(double v); - boost::optional getControlHighIndoorHumidityBasedOnOutdoorHumidityRatio() const; + bool getControlHighIndoorHumidityBasedOnOutdoorHumidityRatio() const; bool setControlHighIndoorHumidityBasedOnOutdoorHumidityRatio(bool v); boost::optional getHeatRecoveryBypassControlType() const; @@ -147,18 +151,6 @@ namespace model { explicit ControllerOutdoorAir(std::shared_ptr impl); private: - CurveQuadratic getElectronicEnthalpyLimitCurve() const; - - ScheduleCompact getMinimumOutdoorAirSchedule() const; - - ScheduleCompact getMinimumFractionOfOutdoorAirSchedule() const; - - ScheduleCompact getMaximumFractionOfOutdoorAirSchedule() const; - - //Controller:MechanicalVentilation getMechanicalVentilationController() const; - - ScheduleCompact getTimeOfDayEconomizerControlSchedule() const; - ControllerOutdoorAir(const Handle& handle, const Model& model); REGISTER_LOGGER("openstudio.model.ControllerOutdoorAir"); diff --git a/src/model/ControllerOutdoorAir_Impl.hpp b/src/model/ControllerOutdoorAir_Impl.hpp index c496e4095d7..04a4b4b0f7d 100644 --- a/src/model/ControllerOutdoorAir_Impl.hpp +++ b/src/model/ControllerOutdoorAir_Impl.hpp @@ -11,11 +11,12 @@ namespace openstudio { namespace model { - class CurveQuadratic; + class Curve; class ScheduleCompact; class AirLoopHVACOutdoorAirSystem; class ControllerMechanicalVentilation; class AirflowNetworkOutdoorAirflow; + class ThermalZone; namespace detail { @@ -67,8 +68,9 @@ namespace model { boost::optional getEconomizerMaximumLimitDewpointTemperature() const; bool setEconomizerMaximumLimitDewpointTemperature(boost::optional value); - //QuadraticCurve getElectronicEnthalpyLimitCurve() const; - //bool setElectronicEnthalpyLimitCurve(QuadraticCurve c); + boost::optional electronicEnthalpyLimitCurve() const; + bool setElectronicEnthalpyLimitCurve(const Curve& curve); + void resetElectronicEnthalpyLimitCurve(); //get needs to return a boost optional double since "" is a valid input boost::optional getEconomizerMinimumLimitDryBulbTemperature() const; @@ -81,15 +83,15 @@ namespace model { bool setMinimumLimitType(const std::string& value); boost::optional getHighHumidityControl() const; - bool setHighHumidityControl(bool val); - //Zone getHumidistatControlZone() const; - //bool setHumidistatControlZone(Zone z) + boost::optional humidistatControlZone() const; + bool setHumidistatControlZone(const ThermalZone& thermalZone); + void resetHumidistatControlZone(); - OptionalDouble getHighHumidityOutdoorAirFlowRatio() const; + double getHighHumidityOutdoorAirFlowRatio() const; bool setHighHumidityOutdoorAirFlowRatio(double v); - boost::optional getControlHighIndoorHumidityBasedOnOutdoorHumidityRatio() const; + bool getControlHighIndoorHumidityBasedOnOutdoorHumidityRatio() const; bool setControlHighIndoorHumidityBasedOnOutdoorHumidityRatio(bool v); OptionalString getHeatRecoveryBypassControlType() const; @@ -98,16 +100,6 @@ namespace model { std::string economizerOperationStaging() const; bool setEconomizerOperationStaging(const std::string& v); - CurveQuadratic getElectronicEnthalpyLimitCurve() const; - - ScheduleCompact getMinimumOutdoorAirSchedule() const; - - ScheduleCompact getMinimumFractionOfOutdoorAirSchedule() const; - - ScheduleCompact getMaximumFractionOfOutdoorAirSchedule() const; - - ScheduleCompact getTimeOfDayEconomizerControlSchedule() const; - boost::optional airLoopHVACOutdoorAirSystem() const; boost::optional minimumOutdoorAirFlowRate() const; diff --git a/src/model/test/ControllerOutdoorAir_GTest.cpp b/src/model/test/ControllerOutdoorAir_GTest.cpp index 6062f9af7a6..dcb8b47e80f 100644 --- a/src/model/test/ControllerOutdoorAir_GTest.cpp +++ b/src/model/test/ControllerOutdoorAir_GTest.cpp @@ -15,6 +15,8 @@ #include "../AirflowNetworkCrack_Impl.hpp" #include "../AirflowNetworkReferenceCrackConditions.hpp" #include "../AirflowNetworkReferenceCrackConditions_Impl.hpp" +#include "../ThermalZone.hpp" +#include "../CurveQuadratic.hpp" #include #include @@ -76,4 +78,37 @@ TEST_F(ModelFixture, ControllerOutdoorAir_GettersSetters) { // Economizer Operation Staging EXPECT_TRUE(controller.setEconomizerOperationStaging("EconomizerFirst")); EXPECT_EQ("EconomizerFirst", controller.economizerOperationStaging()); + + // Electronic Enthalpy Limit Curve + EXPECT_FALSE(controller.electronicEnthalpyLimitCurve()); + CurveQuadratic electronicEnthalpyLimitCurve(model); + EXPECT_TRUE(controller.setElectronicEnthalpyLimitCurve(electronicEnthalpyLimitCurve)); + ASSERT_TRUE(controller.electronicEnthalpyLimitCurve()); + EXPECT_EQ(electronicEnthalpyLimitCurve, controller.electronicEnthalpyLimitCurve().get()); + controller.resetElectronicEnthalpyLimitCurve(); + EXPECT_FALSE(controller.electronicEnthalpyLimitCurve()); + + // Humidistat Control Zone + ASSERT_TRUE(controller.getHighHumidityControl()); + EXPECT_FALSE(controller.getHighHumidityControl().get()); + ThermalZone humidistatControlZone(model); + EXPECT_TRUE(controller.setHumidistatControlZone(humidistatControlZone)); + ASSERT_TRUE(controller.humidistatControlZone()); + EXPECT_EQ(humidistatControlZone, controller.humidistatControlZone().get()); + ASSERT_TRUE(controller.getHighHumidityControl()); + EXPECT_TRUE(controller.getHighHumidityControl().get()); + controller.resetHumidistatControlZone(); + EXPECT_FALSE(controller.humidistatControlZone()); + ASSERT_TRUE(controller.getHighHumidityControl()); + EXPECT_FALSE(controller.getHighHumidityControl().get()); + + // High Humidity Outdoor Air Flow Ratio + EXPECT_EQ(1.0, controller.getHighHumidityOutdoorAirFlowRatio()); + EXPECT_TRUE(controller.setHighHumidityOutdoorAirFlowRatio(2.0)); + EXPECT_EQ(2.0, controller.getHighHumidityOutdoorAirFlowRatio()); + + // Control High Indoor Humidity Based on Outdoor Humidity Ratio + EXPECT_TRUE(controller.getControlHighIndoorHumidityBasedOnOutdoorHumidityRatio()); + EXPECT_TRUE(controller.setControlHighIndoorHumidityBasedOnOutdoorHumidityRatio(false)); + EXPECT_FALSE(controller.getControlHighIndoorHumidityBasedOnOutdoorHumidityRatio()); } diff --git a/src/osversion/VersionTranslator.cpp b/src/osversion/VersionTranslator.cpp index b4c7b138e15..97bb0906262 100644 --- a/src/osversion/VersionTranslator.cpp +++ b/src/osversion/VersionTranslator.cpp @@ -144,7 +144,8 @@ namespace osversion { m_updateMethods[VersionString("3.6.0")] = &VersionTranslator::update_3_5_1_to_3_6_0; m_updateMethods[VersionString("3.7.0")] = &VersionTranslator::update_3_6_1_to_3_7_0; m_updateMethods[VersionString("3.8.0")] = &VersionTranslator::update_3_7_0_to_3_8_0; - // m_updateMethods[VersionString("3.8.0")] = &VersionTranslator::defaultUpdate; + m_updateMethods[VersionString("3.9.0")] = &VersionTranslator::update_3_8_0_to_3_9_0; + // m_updateMethods[VersionString("3.9.0")] = &VersionTranslator::defaultUpdate; // List of previous versions that may be updated to this one. // - To increment the translator, add an entry for the version just released (branched for @@ -181,9 +182,9 @@ namespace osversion { VersionString("2.7.1"), VersionString("2.7.2"), VersionString("2.8.0"), VersionString("2.8.1"), VersionString("2.9.0"), VersionString("2.9.1"), VersionString("3.0.0"), VersionString("3.0.1"), VersionString("3.1.0"), VersionString("3.2.0"), VersionString("3.2.1"), VersionString("3.3.0"), VersionString("3.4.0"), VersionString("3.5.0"), VersionString("3.5.1"), - VersionString("3.6.0"), VersionString("3.6.1"), VersionString("3.7.0"), + VersionString("3.6.0"), VersionString("3.6.1"), VersionString("3.7.0"), VersionString("3.8.0"), // Note: do **not** include the **current** version in m_startVersions, stop at the previous release - //VersionString("3.8.0"), + //VersionString("3.9.0"), }; } @@ -9196,5 +9197,52 @@ namespace osversion { } // end update_3_7_0_to_3_8_0 + std::string VersionTranslator::update_3_8_0_to_3_9_0(const IdfFile& idf_3_8_0, const IddFileAndFactoryWrapper& idd_3_9_0) { + std::stringstream ss; + boost::optional value; + + ss << idf_3_8_0.header() << '\n' << '\n'; + IdfFile targetIdf(idd_3_9_0.iddFile()); + ss << targetIdf.versionObject().get(); + + for (const IdfObject& object : idf_3_8_0.objects()) { + auto iddname = object.iddObject().name(); + + if (iddname == "OS:Controller:OutdoorAir") { + + // 2 Fields have been made required from 3.8.0 to 3.9.0: + // ---------------------------------------------- + // * High Humidity Outdoor Air Flow Ratio * 24 + // * Control High Indoor Humidity Based on Outdoor Humidity Ratio * 25 + + auto iddObject = idd_3_9_0.getObject(iddname); + IdfObject newObject(iddObject.get()); + + for (size_t i = 0; i < object.numFields(); ++i) { + if ((value = object.getString(i))) { + newObject.setString(i, value.get()); + } + } + + if (newObject.isEmpty(24)) { + newObject.setDouble(24, 1.0); + } + if (newObject.isEmpty(25)) { + newObject.setString(25, "Yes"); + } + + ss << newObject; + m_refactored.emplace_back(std::move(object), std::move(newObject)); + + // No-op + } else { + ss << object; + } + } + + return ss.str(); + + } // end update_3_8_0_to_3_9_0 + } // namespace osversion } // namespace openstudio diff --git a/src/osversion/VersionTranslator.hpp b/src/osversion/VersionTranslator.hpp index b5a93555c6f..4600c2faa75 100644 --- a/src/osversion/VersionTranslator.hpp +++ b/src/osversion/VersionTranslator.hpp @@ -236,6 +236,7 @@ namespace osversion { std::string update_3_5_1_to_3_6_0(const IdfFile& idf_3_5_1, const IddFileAndFactoryWrapper& idd_3_6_0); std::string update_3_6_1_to_3_7_0(const IdfFile& idf_3_6_1, const IddFileAndFactoryWrapper& idd_3_7_0); std::string update_3_7_0_to_3_8_0(const IdfFile& idf_3_7_0, const IddFileAndFactoryWrapper& idd_3_8_0); + std::string update_3_8_0_to_3_9_0(const IdfFile& idf_3_8_0, const IddFileAndFactoryWrapper& idd_3_9_0); IdfObject updateUrlField_0_7_1_to_0_7_2(const IdfObject& object, unsigned index); diff --git a/src/osversion/test/3_9_0/test_vt_ControllerOutdoorAir.osm b/src/osversion/test/3_9_0/test_vt_ControllerOutdoorAir.osm new file mode 100644 index 00000000000..9884e2629ce --- /dev/null +++ b/src/osversion/test/3_9_0/test_vt_ControllerOutdoorAir.osm @@ -0,0 +1,56 @@ + +OS:Version, + {ff5269f8-4354-477b-aa90-d656733b4909}, !- Handle + 3.8.0; !- Version Identifier + +OS:Controller:OutdoorAir, + {2b51de85-c6f1-42e2-be76-53aabac1dd57}, !- Handle + Controller Outdoor Air 1, !- Name + , !- Relief Air Outlet Node Name + , !- Return Air Node Name + , !- Mixed Air Node Name + , !- Actuator Node Name + 0, !- Minimum Outdoor Air Flow Rate {m3/s} + Autosize, !- Maximum Outdoor Air Flow Rate {m3/s} + NoEconomizer, !- Economizer Control Type + ModulateFlow, !- Economizer Control Action Type + 28, !- Economizer Maximum Limit Dry-Bulb Temperature {C} + 64000, !- Economizer Maximum Limit Enthalpy {J/kg} + , !- Economizer Maximum Limit Dewpoint Temperature {C} + , !- Electronic Enthalpy Limit Curve Name + -100, !- Economizer Minimum Limit Dry-Bulb Temperature {C} + NoLockout, !- Lockout Type + FixedMinimum, !- Minimum Limit Type + , !- Minimum Outdoor Air Schedule Name + , !- Minimum Fraction of Outdoor Air Schedule Name + , !- Maximum Fraction of Outdoor Air Schedule Name + {1a10e873-d7f2-412b-96c4-81731937086b}, !- Controller Mechanical Ventilation + , !- Time of Day Economizer Control Schedule Name + No, !- High Humidity Control + , !- Humidistat Control Zone Name + , !- High Humidity Outdoor Air Flow Ratio + , !- Control High Indoor Humidity Based on Outdoor Humidity Ratio + BypassWhenWithinEconomizerLimits, !- Heat Recovery Bypass Control Type + InterlockedWithMechanicalCooling; !- Economizer Operation Staging + +OS:Controller:MechanicalVentilation, + {1a10e873-d7f2-412b-96c4-81731937086b}, !- Handle + Controller Mechanical Ventilation 1, !- Name + {68a1d80e-6ef4-49d0-ad28-8dbf399ebd36}, !- Availability Schedule + , !- Demand Controlled Ventilation + ; !- System Outdoor Air Method + +OS:Schedule:Constant, + {68a1d80e-6ef4-49d0-ad28-8dbf399ebd36}, !- Handle + Always On Discrete, !- Name + {bc7824f2-a62d-4a3b-914b-8a1b3eb143da}, !- Schedule Type Limits Name + 1; !- Value + +OS:ScheduleTypeLimits, + {bc7824f2-a62d-4a3b-914b-8a1b3eb143da}, !- Handle + OnOff, !- Name + 0, !- Lower Limit Value + 1, !- Upper Limit Value + Discrete, !- Numeric Type + Availability; !- Unit Type + diff --git a/src/osversion/test/3_9_0/test_vt_ControllerOutdoorAir.rb b/src/osversion/test/3_9_0/test_vt_ControllerOutdoorAir.rb new file mode 100644 index 00000000000..8b50085a61a --- /dev/null +++ b/src/osversion/test/3_9_0/test_vt_ControllerOutdoorAir.rb @@ -0,0 +1,9 @@ +#require '/usr/local/openstudio-3.8.0/Ruby/openstudio' + +include OpenStudio::Model + +m = Model.new + +controller = ControllerOutdoorAir.new(m) + +m.save('test_vt_ControllerOutdoorAir.osm', true) diff --git a/src/osversion/test/VersionTranslator_GTest.cpp b/src/osversion/test/VersionTranslator_GTest.cpp index d7d81842494..41b14e429b0 100644 --- a/src/osversion/test/VersionTranslator_GTest.cpp +++ b/src/osversion/test/VersionTranslator_GTest.cpp @@ -3938,8 +3938,8 @@ TEST_F(OSVersionFixture, update_3_6_1_to_3_7_0_ControllerOutdoorAir) { EXPECT_TRUE(coa.isEmpty(21)); // Time of Day Economizer Control Schedule Name EXPECT_EQ("No", coa.getString(22).get()); // High Humidity Control EXPECT_TRUE(coa.isEmpty(23)); // Humidistat Control Zone Name - EXPECT_TRUE(coa.isEmpty(24)); // High Humidity Outdoor Air Flow Ratio - EXPECT_TRUE(coa.isEmpty(25)); // Control High Indoor Humidity Based on Outdoor Humidity Ratio + EXPECT_EQ(1.0, coa.getDouble(24).get()); // High Humidity Outdoor Air Flow Ratio + EXPECT_EQ("Yes", coa.getString(25).get()); // Control High Indoor Humidity Based on Outdoor Humidity Ratio EXPECT_EQ("BypassWhenWithinEconomizerLimits", coa.getString(26).get()); // Heat Recovery Bypass Control Type EXPECT_EQ("InterlockedWithMechanicalCooling", coa.getString(27).get()); // Economizer Operation Staging } @@ -4207,3 +4207,45 @@ TEST_F(OSVersionFixture, update_3_7_0_to_3_8_0_ScheduleDay) { EXPECT_EQ(0, sch_day.getInt(5).get()); // Minute 1 EXPECT_EQ(0, sch_day.getDouble(6).get()); // Value Until Time 1 } + +TEST_F(OSVersionFixture, update_3_8_0_to_3_9_0_ControllerOutdoorAir) { + openstudio::path path = resourcesPath() / toPath("osversion/3_9_0/test_vt_ControllerOutdoorAir.osm"); + osversion::VersionTranslator vt; + boost::optional model = vt.loadModel(path); + ASSERT_TRUE(model) << "Failed to load " << path; + + openstudio::path outPath = resourcesPath() / toPath("osversion/3_9_0/test_vt_ControllerOutdoorAir_updated.osm"); + model->save(outPath, true); + + std::vector controllers = model->getObjectsByType("OS:Controller:OutdoorAir"); + ASSERT_EQ(1u, controllers.size()); + WorkspaceObject controller = controllers[0]; + + EXPECT_EQ("Controller Outdoor Air 1", controller.getString(1).get()); // Name + EXPECT_TRUE(controller.isEmpty(2)); // Relief Air Outlet Node Name + EXPECT_TRUE(controller.isEmpty(3)); // Return Air Node Name + EXPECT_TRUE(controller.isEmpty(4)); // Mixed Air Node Name + EXPECT_TRUE(controller.isEmpty(5)); // Actuator Node Name + EXPECT_EQ(0.0, controller.getDouble(6).get()); // Minimum Outdoor Air Flow Rate {m3/s} + EXPECT_EQ("Autosize", controller.getString(7).get()); // Maximum Outdoor Air Flow Rate {m3/s} + EXPECT_EQ("NoEconomizer", controller.getString(8).get()); // Economizer Control Type + EXPECT_EQ("ModulateFlow", controller.getString(9).get()); // Economizer Control Action Type + EXPECT_EQ(28.0, controller.getDouble(10).get()); // Economizer Maximum Limit Dry-Bulb Temperature {C} + EXPECT_EQ(64000.0, controller.getDouble(11).get()); // Economizer Maximum Limit Enthalpy {J/kg} + EXPECT_TRUE(controller.isEmpty(12)); // Economizer Maximum Limit Dewpoint Temperature {C} + EXPECT_TRUE(controller.isEmpty(13)); // Electronic Enthalpy Limit Curve Name + EXPECT_EQ(-100.0, controller.getDouble(14).get()); // Economizer Minimum Limit Dry-Bulb Temperature {C} + EXPECT_EQ("NoLockout", controller.getString(15).get()); // Lockout Type + EXPECT_EQ("FixedMinimum", controller.getString(16).get()); // Minimum Limit Type + EXPECT_TRUE(controller.isEmpty(17)); // Minimum Outdoor Air Schedule Name + EXPECT_TRUE(controller.isEmpty(18)); // Minimum Fraction of Outdoor Air Schedule Name + EXPECT_TRUE(controller.isEmpty(19)); // Maximum Fraction of Outdoor Air Schedule Name + ASSERT_TRUE(controller.getTarget(20)); // Controller Mechanical Ventilation + EXPECT_TRUE(controller.isEmpty(21)); // Time of Day Economizer Control Schedule Name + EXPECT_EQ("No", controller.getString(22).get()); // High Humidity Control + EXPECT_TRUE(controller.isEmpty(23)); // Humidistat Control Zone Name + EXPECT_EQ(1.0, controller.getDouble(24).get()); // High Humidity Outdoor Air Flow Ratio + EXPECT_EQ("Yes", controller.getString(25).get()); // Control High Indoor Humidity Based on Outdoor Humidity Ratio + EXPECT_EQ("BypassWhenWithinEconomizerLimits", controller.getString(26).get()); // Heat Recovery Bypass Control Type + EXPECT_EQ("InterlockedWithMechanicalCooling", controller.getString(27).get()); // Economizer Operation Staging +}