Skip to content

Commit

Permalink
Merge pull request #3863 from NREL/issue-3728
Browse files Browse the repository at this point in the history
Addresses #3728, add new DOAS to AHU objects
  • Loading branch information
kbenne authored Mar 8, 2021
2 parents 17704c3 + 049844b commit 83b05b5
Show file tree
Hide file tree
Showing 25 changed files with 1,572 additions and 39 deletions.
49 changes: 49 additions & 0 deletions resources/model/OpenStudio.idd
Original file line number Diff line number Diff line change
Expand Up @@ -10198,6 +10198,7 @@ OS:AirLoopHVAC:OutdoorAirSystem,
A2, \field Name
\type alpha
\required-field
\reference AirLoopHVACOASysNames
\reference ConnectionObject
A3, \field Controller Name
\type object-list
Expand Down Expand Up @@ -10229,6 +10230,54 @@ OS:AirLoopHVAC:OutdoorAirSystem,
\required-field
\object-list ConnectionNames

OS:AirLoopHVAC:DedicatedOutdoorAirSystem,
\extensible:1 Just duplicate last field and comments (changing numbering, please)
\min-fields 9
\memo Defines a central forced air system to provide dedicated outdoor air to multiple
\memo AirLoopHVACs.
A1, \field Handle
\type handle
\required-field
A2, \field Name
\required-field
\type alpha
\reference DOASAirLoops
\reference ConnectionObject
A3, \field Outdoor Air System
\note Enter the name of an AirLoopHVAC:OutdoorAirSystem object.
\required-field
\type object-list
\object-list AirLoopHVACOASysNames
\object-list ConnectionObject
A4, \field Availability Schedule
\note Availability schedule name for this system. Schedule value > 0 means the system is available.
\note If this field is blank, the system is always available.
\required-field
\type object-list
\object-list ScheduleNames
N1, \field Preheat Design Temperature
\required-field
\type real
\units C
N2, \field Preheat Design Humidity Ratio
\required-field
\type real
\units kgWater/kgDryAir
N3, \field Precool Design Temperature
\required-field
\type real
\units C
N4, \field Precool Design Humidity Ratio
\required-field
\type real
\units kgWater/kgDryAir
A5; \field Air Loop 1
\note The rest of fields are extensible. It requires AirLoopHVAC names served by
\note an AirLoopHVAC:DedicatedOutdoorAirSystem.
\begin-extensible
\type object-list
\object-list AirPrimaryLoops

OS:AirLoopHVAC:ReturnPlenum,
\extensible:1 Just duplicate last field and comments (changing numbering, please)
\min-fields 1
Expand Down
3 changes: 3 additions & 0 deletions src/energyplus/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ set(${target_name}_src
ForwardTranslator/ForwardTranslateAirGap.cpp
ForwardTranslator/ForwardTranslateAirLoopHVAC.cpp
ForwardTranslator/ForwardTranslateAirLoopHVACOutdoorAirSystem.cpp
ForwardTranslator/ForwardTranslateAirLoopHVACDedicatedOutdoorAirSystem.cpp
ForwardTranslator/ForwardTranslateAirLoopHVACReturnPlenum.cpp
ForwardTranslator/ForwardTranslateAirLoopHVACSupplyPlenum.cpp
ForwardTranslator/ForwardTranslateAirLoopHVACUnitaryHeatCoolVAVChangeoverBypass.cpp
Expand Down Expand Up @@ -419,6 +420,7 @@ set(${target_name}_src
ReverseTranslator.cpp
ReverseTranslator/ReverseTranslateAirLoopHVAC.cpp
ReverseTranslator/ReverseTranslateAirLoopHVACOutdoorAirSystem.cpp
ReverseTranslator/ReverseTranslateAirLoopHVACDedicatedOutdoorAirSystem.cpp
ReverseTranslator/ReverseTranslateAirTerminalSingleDuctConstantVolumeReheat.cpp
ReverseTranslator/ReverseTranslateAirTerminalSingleDuctConstantVolumeNoReheat.cpp
ReverseTranslator/ReverseTranslateAirTerminalSingleDuctVAVNoReheat.cpp
Expand Down Expand Up @@ -593,6 +595,7 @@ set(${target_name}_test_src
Test/AirWallMaterial_GTest.cpp

Test/AirLoopHVAC_GTest.cpp
Test/AirLoopHVACDedicatedOutdoorAirSystem_GTest.cpp
Test/PlantLoop_GTest.cpp

# Test/AvailabilityManagerAssignmentList_GTest.cpp
Expand Down
16 changes: 14 additions & 2 deletions src/energyplus/ForwardTranslator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -502,6 +502,13 @@ namespace energyplus {
idfObject.setName(node.name().get());
}

// get AirLoopHVACDedicatedOutdoorAirSystem in sorted order
std::vector<AirLoopHVACDedicatedOutdoorAirSystem> doass = model.getConcreteModelObjects<AirLoopHVACDedicatedOutdoorAirSystem>();
std::sort(doass.begin(), doass.end(), WorkspaceObjectNameLess());
for (AirLoopHVACDedicatedOutdoorAirSystem doas : doass) {
translateAndMapModelObject(doas);
}

// get air loops in sorted order
std::vector<AirLoopHVAC> airLoops = model.getConcreteModelObjects<AirLoopHVAC>();
std::sort(airLoops.begin(), airLoops.end(), WorkspaceObjectNameLess());
Expand Down Expand Up @@ -716,6 +723,11 @@ namespace energyplus {
retVal = translateAirLoopHVACOutdoorAirSystem(oaSystem);
break;
}
case openstudio::IddObjectType::OS_AirLoopHVAC_DedicatedOutdoorAirSystem: {
model::AirLoopHVACDedicatedOutdoorAirSystem doaSystem = modelObject.cast<AirLoopHVACDedicatedOutdoorAirSystem>();
retVal = translateAirLoopHVACDedicatedOutdoorAirSystem(doaSystem);
break;
}
case openstudio::IddObjectType::OS_AirLoopHVAC_UnitaryHeatPump_AirToAir: {
model::AirLoopHVACUnitaryHeatPumpAirToAir unitary = modelObject.cast<AirLoopHVACUnitaryHeatPumpAirToAir>();
retVal = translateAirLoopHVACUnitaryHeatPumpAirToAir(unitary);
Expand Down Expand Up @@ -3101,8 +3113,8 @@ namespace energyplus {
result.push_back(IddObjectType::OS_AirLoopHVAC);
result.push_back(IddObjectType::OS_AirLoopHVAC_ControllerList);

// Translated by AirLoopHVAC (and AirLoopHVAC:DedicatedOutdoorAirSystem but not wrapped)
// result.push_back(IddObjectType::OS_AirLoopHVAC_OutdoorAirSystem)
// Translated by AirLoopHVAC
// result.push_back(IddObjectType::OS_AirLoopHVAC_OutdoorAirSystem);

result.push_back(IddObjectType::OS_AirLoopHVAC_UnitaryHeatCool_VAVChangeoverBypass);
result.push_back(IddObjectType::OS_AirLoopHVAC_UnitaryCoolOnly);
Expand Down
3 changes: 3 additions & 0 deletions src/energyplus/ForwardTranslator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ namespace model {
class AirTerminalSingleDuctVAVHeatAndCoolReheat;
class AirLoopHVACZoneMixer;
class AirLoopHVACOutdoorAirSystem;
class AirLoopHVACDedicatedOutdoorAirSystem;
class AirWallMaterial;
class AvailabilityManagerAssignmentList;
class AvailabilityManagerHybridVentilation;
Expand Down Expand Up @@ -597,6 +598,8 @@ namespace energyplus {

boost::optional<IdfObject> translateAirLoopHVACOutdoorAirSystem(model::AirLoopHVACOutdoorAirSystem& modelObject);

boost::optional<IdfObject> translateAirLoopHVACDedicatedOutdoorAirSystem(model::AirLoopHVACDedicatedOutdoorAirSystem& modelObject);

boost::optional<IdfObject>
translateAirLoopHVACUnitaryHeatCoolVAVChangeoverBypass(model::AirLoopHVACUnitaryHeatCoolVAVChangeoverBypass& modelObject);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
/***********************************************************************************************************************
* OpenStudio(R), Copyright (c) 2008-2020, Alliance for Sustainable Energy, LLC, and other contributors. All rights reserved.
*
* 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 copyright holder nor the names of any contributors may be used to endorse or promote products
* derived from this software without specific prior written permission from the respective party.
*
* (4) Other than as required in clauses (1) and (2), distributions in any form of modifications or other derivative works
* may not use the "OpenStudio" trademark, "OS", "os", or any other confusingly similar designation without specific prior
* written permission from Alliance for Sustainable Energy, LLC.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND ANY 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 HOLDER(S), ANY CONTRIBUTORS, THE UNITED STATES GOVERNMENT, OR THE UNITED
* STATES DEPARTMENT OF ENERGY, NOR ANY OF THEIR EMPLOYEES, 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.
***********************************************************************************************************************/

#include "../ForwardTranslator.hpp"

#include "../../model/Model.hpp"
#include "../../model/AirLoopHVACDedicatedOutdoorAirSystem.hpp"
#include "../../model/AirLoopHVACDedicatedOutdoorAirSystem_Impl.hpp"
#include "../../model/AirLoopHVACOutdoorAirSystem.hpp"
#include "../../model/Schedule.hpp"
#include "../../model/AirLoopHVAC.hpp"
#include "../../model/Node.hpp"
#include "../../model/AirLoopHVACZoneMixer.hpp"
#include "../../model/AirLoopHVACZoneSplitter.hpp"

#include <utilities/idd/AirLoopHVAC_DedicatedOutdoorAirSystem_FieldEnums.hxx>
#include <utilities/idd/AirLoopHVAC_Mixer_FieldEnums.hxx>
#include <utilities/idd/AirLoopHVAC_Splitter_FieldEnums.hxx>
#include <utilities/idd/IddEnums.hxx>
#include "../../utilities/idf/IdfExtensibleGroup.hpp"

using namespace openstudio::model;

namespace openstudio {

namespace energyplus {

boost::optional<IdfObject>
ForwardTranslator::translateAirLoopHVACDedicatedOutdoorAirSystem(model::AirLoopHVACDedicatedOutdoorAirSystem& modelObject) {
boost::optional<double> value;
IdfObject idfObject(IddObjectType::AirLoopHVAC_DedicatedOutdoorAirSystem);

m_idfObjects.push_back(idfObject);

// Name
std::string name = modelObject.name().get();
idfObject.setString(openstudio::AirLoopHVAC_DedicatedOutdoorAirSystemFields::Name, name);

// Availability Schedule Name
Schedule schedule = modelObject.availabilitySchedule();
if (boost::optional<IdfObject> _schedule = translateAndMapModelObject(schedule)) {
idfObject.setString(AirLoopHVAC_DedicatedOutdoorAirSystemFields::AvailabilityScheduleName, _schedule->name().get());
}

// AirLoopHVAC:OutdoorAirSystem Name
AirLoopHVACOutdoorAirSystem oaSystem = modelObject.airLoopHVACOutdoorAirSystem();
if (boost::optional<IdfObject> _oaSystem = translateAndMapModelObject(oaSystem)) {
idfObject.setString(AirLoopHVAC_DedicatedOutdoorAirSystemFields::AirLoopHVAC_OutdoorAirSystemName, _oaSystem->name().get());
}

// AirLoopHVAC:Mixer Name
std::string mixerName(modelObject.nameString() + " Mixer");
idfObject.setString(AirLoopHVAC_DedicatedOutdoorAirSystemFields::AirLoopHVAC_MixerName, mixerName);
IdfObject idfMixer(openstudio::IddObjectType::AirLoopHVAC_Mixer);
idfMixer.setString(AirLoopHVAC_MixerFields::Name, mixerName);
idfMixer.setString(AirLoopHVAC_MixerFields::OutletNodeName, idfMixer.name().get() + " Outlet");

// AirLoopHVAC:Splitter Name
std::string splitterName(modelObject.nameString() + " Splitter");
idfObject.setString(AirLoopHVAC_DedicatedOutdoorAirSystemFields::AirLoopHVAC_SplitterName, splitterName);
IdfObject idfSplitter(openstudio::IddObjectType::AirLoopHVAC_Splitter);
idfSplitter.setString(AirLoopHVAC_SplitterFields::Name, splitterName);
idfSplitter.setString(AirLoopHVAC_SplitterFields::InletNodeName, oaSystem.outdoorAirModelObject().get().nameString());

// Preheat Design Temperature
if ((value = modelObject.preheatDesignTemperature())) {
idfObject.setDouble(AirLoopHVAC_DedicatedOutdoorAirSystemFields::PreheatDesignTemperature, value.get());
}

// Preheat Design Humidity Ratio
if ((value = modelObject.preheatDesignHumidityRatio())) {
idfObject.setDouble(AirLoopHVAC_DedicatedOutdoorAirSystemFields::PreheatDesignHumidityRatio, value.get());
}

// Precool Design Temperature
if ((value = modelObject.precoolDesignTemperature())) {
idfObject.setDouble(AirLoopHVAC_DedicatedOutdoorAirSystemFields::PrecoolDesignTemperature, value.get());
}

// Precool Design Humidity Ratio
if ((value = modelObject.precoolDesignHumidityRatio())) {
idfObject.setDouble(AirLoopHVAC_DedicatedOutdoorAirSystemFields::PrecoolDesignHumidityRatio, value.get());
}

// Number of AirLoopHVAC
idfObject.setInt(AirLoopHVAC_DedicatedOutdoorAirSystemFields::NumberofAirLoopHVAC, modelObject.numberofAirLoops());

// AirLoopHVAC x Name
boost::optional<AirLoopHVACOutdoorAirSystem> oas;
for (auto airLoop : modelObject.airLoops()) {
auto eg = idfObject.pushExtensibleGroup();
eg.setString(AirLoopHVAC_DedicatedOutdoorAirSystemExtensibleFields::AirLoopHVACName, airLoop.nameString());

oas = airLoop.airLoopHVACOutdoorAirSystem();
OS_ASSERT(oas);

// AirLoopHVAC:Mixer Name
auto egMixer = idfMixer.pushExtensibleGroup();
egMixer.setString(AirLoopHVAC_MixerExtensibleFields::InletNodeName, oas->outboardReliefNode().get().nameString());

// AirLoopHVAC:Splitter Name
auto egSplitter = idfSplitter.pushExtensibleGroup();
egSplitter.setString(AirLoopHVAC_SplitterExtensibleFields::OutletNodeName, oas->outboardOANode().get().nameString());
}

m_idfObjects.push_back(idfMixer);
m_idfObjects.push_back(idfSplitter);

return boost::optional<IdfObject>(idfObject);
}

} // namespace energyplus

} // namespace openstudio
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@
#include "../../model/AirToAirComponent_Impl.hpp"
#include "../../model/AirLoopHVACOutdoorAirSystem.hpp"
#include "../../model/AirLoopHVACOutdoorAirSystem_Impl.hpp"
#include "../../model/AirLoopHVACDedicatedOutdoorAirSystem.hpp"
#include "../../model/AirLoopHVACDedicatedOutdoorAirSystem_Impl.hpp"
#include "../../model/ControllerOutdoorAir.hpp"
#include "../../model/ControllerOutdoorAir_Impl.hpp"
#include "../../model/ControllerWaterCoil.hpp"
Expand Down Expand Up @@ -72,6 +74,11 @@ namespace energyplus {

m_idfObjects.push_back(idfObject);

boost::optional<ModelObject> mixedAirModelObject = modelObject.mixedAirModelObject();
boost::optional<ModelObject> outdoorAirModelObject = modelObject.outdoorAirModelObject();
boost::optional<ModelObject> reliefAirModelObject = modelObject.reliefAirModelObject();
boost::optional<ModelObject> returnAirModelObject = modelObject.returnAirModelObject();

// Name
std::string name = modelObject.name().get();
idfObject.setString(openstudio::AirLoopHVAC_OutdoorAirSystemFields::Name, name);
Expand All @@ -81,16 +88,18 @@ namespace energyplus {
_controllerList.setName(name + " Controller List");
_controllerList.clearExtensibleGroups();
m_idfObjects.push_back(_controllerList);
idfObject.setString(openstudio::AirLoopHVAC_OutdoorAirSystemFields::ControllerListName, _controllerList.name().get());

ControllerOutdoorAir controllerOutdoorAir = modelObject.getControllerOutdoorAir();
boost::optional<IdfObject> _controllerOutdoorAir = translateAndMapModelObject(controllerOutdoorAir);
OS_ASSERT(_controllerOutdoorAir);

idfObject.setString(openstudio::AirLoopHVAC_OutdoorAirSystemFields::ControllerListName, _controllerList.name().get());
if (!modelObject.airLoopHVACDedicatedOutdoorAirSystem()) {
boost::optional<IdfObject> _controllerOutdoorAir = translateAndMapModelObject(controllerOutdoorAir);
OS_ASSERT(_controllerOutdoorAir);

IdfExtensibleGroup eg = _controllerList.pushExtensibleGroup();
eg.setString(AirLoopHVAC_ControllerListExtensibleFields::ControllerObjectType, _controllerOutdoorAir->iddObject().name());
eg.setString(AirLoopHVAC_ControllerListExtensibleFields::ControllerName, _controllerOutdoorAir->name().get());
IdfExtensibleGroup eg = _controllerList.pushExtensibleGroup();
eg.setString(AirLoopHVAC_ControllerListExtensibleFields::ControllerObjectType, _controllerOutdoorAir->iddObject().name());
eg.setString(AirLoopHVAC_ControllerListExtensibleFields::ControllerName, _controllerOutdoorAir->name().get());
}

std::vector<ModelObject> controllers;
auto components = modelObject.components();
Expand Down Expand Up @@ -155,30 +164,39 @@ namespace energyplus {

m_idfObjects.push_back(equipmentListIdf);

IdfObject outdoorAirMixerIdf(IddObjectType::OutdoorAir_Mixer);
outdoorAirMixerIdf.setName(name + " Outdoor Air Mixer");
m_idfObjects.push_back(outdoorAirMixerIdf);
unsigned i = 1;
if (!modelObject.airLoopHVACDedicatedOutdoorAirSystem()) {
IdfObject outdoorAirMixerIdf(IddObjectType::OutdoorAir_Mixer);
outdoorAirMixerIdf.setName(name + " Outdoor Air Mixer");
m_idfObjects.push_back(outdoorAirMixerIdf);

s = mixedAirModelObject->name();
if (s) {
outdoorAirMixerIdf.setString(OutdoorAir_MixerFields::MixedAirNodeName, *s);
}
s = outdoorAirModelObject->name();
if (s) {
outdoorAirMixerIdf.setString(OutdoorAir_MixerFields::OutdoorAirStreamNodeName, *s);
}

s = modelObject.mixedAirModelObject()->name();
if (s) {
outdoorAirMixerIdf.setString(OutdoorAir_MixerFields::MixedAirNodeName, *s);
}
s = modelObject.outdoorAirModelObject()->name();
if (s) {
outdoorAirMixerIdf.setString(OutdoorAir_MixerFields::OutdoorAirStreamNodeName, *s);
}
s = reliefAirModelObject->name();
if (s) {
outdoorAirMixerIdf.setString(OutdoorAir_MixerFields::ReliefAirStreamNodeName, *s);
}

s = modelObject.reliefAirModelObject()->name();
if (s) {
outdoorAirMixerIdf.setString(OutdoorAir_MixerFields::ReliefAirStreamNodeName, *s);
}
s = returnAirModelObject->name();
if (s) {
outdoorAirMixerIdf.setString(OutdoorAir_MixerFields::ReturnAirStreamNodeName, *s);
}

s = modelObject.returnAirModelObject()->name();
if (s) {
outdoorAirMixerIdf.setString(OutdoorAir_MixerFields::ReturnAirStreamNodeName, *s);
s = outdoorAirMixerIdf.iddObject().name();
equipmentListIdf.setString(i, *s);
++i;
s = outdoorAirMixerIdf.name();
equipmentListIdf.setString(i, *s);
++i;
}

unsigned i = 1;
ModelObjectVector oaModelObjects = modelObject.oaComponents();
for (auto oaIt = oaModelObjects.begin(); oaIt != oaModelObjects.end(); ++oaIt) {
if (boost::optional<IdfObject> idfObject = translateAndMapModelObject(*oaIt)) {
Expand All @@ -204,12 +222,6 @@ namespace energyplus {
}
}

s = outdoorAirMixerIdf.iddObject().name();
equipmentListIdf.setString(i, *s);
++i;
s = outdoorAirMixerIdf.name();
equipmentListIdf.setString(i, *s);

s = equipmentListIdf.name();
if (s) {
idfObject.setString(openstudio::AirLoopHVAC_OutdoorAirSystemFields::OutdoorAirEquipmentListName, *s);
Expand Down
Loading

0 comments on commit 83b05b5

Please sign in to comment.