Repository: NREL/OpenStudio (language: python)

Issue:
Update to EnergyPlus 22.2.0
Enhancement Request
--------------
Once v22.2-IOFreeze is released, we should update to it.

## Detailed Description

https://github.com/NREL/EnergyPlus/blob/develop/src/Transition/InputRulesFiles/Rules22-1-0-to-22-2-0.md

### Major changes
- [x] https://github.com/NREL/OpenStudio/issues/4647
  - https://github.com/NREL/OpenStudio/pull/4652
  - https://github.com/NREL/OpenStudio-resources/pull/173
- [x] https://github.com/NREL/OpenStudio/issues/4645
  - https://github.com/NREL/OpenStudio/pull/4672 
- [x] #4673

### New additions
- [x] https://github.com/NREL/OpenStudio/issues/4656
  - https://github.com/NREL/OpenStudio/pull/4687
  - https://github.com/NREL/OpenStudio-resources/pull/179
- [x] https://github.com/NREL/OpenStudio/issues/4648
  - https://github.com/NREL/OpenStudio/pull/4676
  - https://github.com/NREL/OpenStudio-resources/pull/177
- [x] https://github.com/NREL/OpenStudio/issues/4654
  - https://github.com/NREL/OpenStudio/pull/4676
  - https://github.com/NREL/OpenStudio-resources/pull/177
- [x] https://github.com/NREL/OpenStudio/issues/4646
  - https://github.com/NREL/OpenStudio/pull/4666
  - https://github.com/NREL/OpenStudio-resources/pull/176
- [x] https://github.com/NREL/OpenStudio/issues/4668
  - https://github.com/NREL/OpenStudio/pull/4669
- [x] https://github.com/NREL/OpenStudio/pull/4665
- [x] https://github.com/NREL/OpenStudio/pull/4661
- [x] https://github.com/NREL/OpenStudio/pull/4671
- [x] https://github.com/NREL/OpenStudio/pull/4662
- [x] https://github.com/NREL/OpenStudio/issues/4675
  - https://github.com/NREL/OpenStudio/pull/4677

### Minor stuff
- [x] `FuelFactors`: eliminate second/third input parameters.
- [x] `Construction:InternalSource`: min/max changes
- [x] `SwimmingPool:Indoor`: field `Make-up Water Supply Schedule Name` no longer required
  - 2f7a98f6cd8dd2669e48346ba59c1ebb505d07b4
- [x] https://github.com/NREL/OpenStudio/issues/4630 (could probably sneak this in)
  - https://github.com/NREL/OpenStudio/pull/4685

### Other



Discussion / hints:

Fix patch:
diff --git a/resources/energyplus/ProposedEnergy+.idd b/resources/energyplus/ProposedEnergy+.idd
index 62e02ad971a..08d96ac653d 100644
--- a/resources/energyplus/ProposedEnergy+.idd
+++ b/resources/energyplus/ProposedEnergy+.idd
@@ -24121,6 +24121,7 @@ ZoneHVAC:PackagedTerminalAirConditioner,
    A12, \field Cooling Coil Name
         \required-field
         \type object-list
+        \object-list CoilCoolingDX
         \object-list CoolingCoilsDXSingleSpeed
         \object-list CoolingCoilsDXVariableSpeed
         \note Needs to match a DX cooling coil object.
@@ -24303,6 +24304,7 @@ ZoneHVAC:PackagedTerminalHeatPump,
    A12, \field Cooling Coil Name
         \required-field
         \type object-list
+        \object-list CoilCoolingDX
         \object-list CoolingCoilsDXSingleSpeed
         \object-list CoolingCoilsDXVariableSpeed
         \note Needs to match in the DX Cooling Coil object.
diff --git a/resources/model/OpenStudio.idd b/resources/model/OpenStudio.idd
index 2cc77bb4766..9780bec1791 100644
--- a/resources/model/OpenStudio.idd
+++ b/resources/model/OpenStudio.idd
@@ -15828,6 +15828,7 @@ OS:Coil:Cooling:DX,
        \type alpha
        \reference CoilCoolingDX
        \reference AFNCoilNames
+       \reference DesuperHeatingCoilSources
        \reference ConnectionObject
   A3, \field Evaporator Inlet Node
        \type object-list
@@ -17246,6 +17247,7 @@ OS:CoilSystem:Cooling:DX:HeatExchangerAssisted,
   A6 ; \field Cooling Coil
        \required-field
        \type object-list
+       \object-list CoilCoolingDX
        \object-list CoolingCoilsDXSingleSpeed
        \object-list CoolingCoilsDXVariableSpeed
 
@@ -18248,6 +18250,7 @@ OS:Coil:WaterHeating:Desuperheater,
   A8,  \field Heating Source Name
        \required-field
        \type object-list
+       \object-list CoilCoolingDX
        \object-list DesuperHeatingCoilSources
        \object-list DesuperHeatingWaterOnlySources
        \note The name of the DX system used for heat reclaim.
@@ -27307,6 +27310,7 @@ OS:ZoneHVAC:PackagedTerminalHeatPump,
        \note Needs to match in the DX Cooling Coil object.
        \type object-list
        \required-field
+       \object-list CoilCoolingDX
        \object-list CoolingCoilsDXSingleSpeed
        \object-list CoolingCoilsDXVariableSpeed
   N9, \field Cooling Convergence Tolerance
@@ -27444,6 +27448,7 @@ OS:ZoneHVAC:PackagedTerminalAirConditioner,
        \note Needs to match a DX cooling coil object.
        \type object-list
        \required-field
+       \object-list CoilCoolingDX
        \object-list CoolingCoilsDXSingleSpeed
        \object-list CoolingCoilsDXVariableSpeed
   A11, \field Fan Placement
diff --git a/src/energyplus/ForwardTranslator.cpp b/src/energyplus/ForwardTranslator.cpp
index 3c4855de9b0..0e81b5f7e41 100644
--- a/src/energyplus/ForwardTranslator.cpp
+++ b/src/energyplus/ForwardTranslator.cpp
@@ -979,8 +979,12 @@ namespace energyplus {
         break;
       }
       case openstudio::IddObjectType::OS_Coil_Cooling_DX: {
-        model::CoilCoolingDX dx = modelObject.cast<CoilCoolingDX>();
-        retVal = translateCoilCoolingDX(dx);
+        model::CoilCoolingDX coil = modelObject.cast<CoilCoolingDX>();
+        if (this->isHVACComponentWithinUnitary(coil)) {
+          retVal = translateCoilCoolingDXWithoutUnitary(coil);
+        } else {
+          retVal = translateCoilCoolingDX(coil);
+        }
         break;
       }
       case openstudio::IddObjectType::OS_Coil_Cooling_DX_CurveFit_Performance: {
diff --git a/src/energyplus/ForwardTranslator.hpp b/src/energyplus/ForwardTranslator.hpp
index 0ad5dc5302f..3fcd95345bd 100644
--- a/src/energyplus/ForwardTranslator.hpp
+++ b/src/energyplus/ForwardTranslator.hpp
@@ -755,8 +755,12 @@ namespace energyplus {
 
     boost::optional<IdfObject> translateCoilCoolingDXSingleSpeed(model::CoilCoolingDXSingleSpeed& modelObject);
 
+    boost::optional<IdfObject> translateCoilCoolingDXSingleSpeedWithoutUnitary(model::CoilCoolingDXSingleSpeed& modelObject);
+
     boost::optional<IdfObject> translateCoilCoolingDX(model::CoilCoolingDX& modelObject);
 
+    boost::optional<IdfObject> translateCoilCoolingDXWithoutUnitary(model::CoilCoolingDX& modelObject);
+
     boost::optional<IdfObject> translateCoilCoolingDXCurveFitPerformance(model::CoilCoolingDXCurveFitPerformance& modelObject);
 
     boost::optional<IdfObject> translateCoilCoolingDXCurveFitOperatingMode(model::CoilCoolingDXCurveFitOperatingMode& modelObject);
@@ -765,8 +769,6 @@ namespace energyplus {
 
     boost::optional<IdfObject> translateCoilCoolingDXMultiSpeed(model::CoilCoolingDXMultiSpeed& modelObject);
 
-    boost::optional<IdfObject> translateCoilCoolingDXSingleSpeedWithoutUnitary(model::CoilCoolingDXSingleSpeed& modelObject);
-
     boost::optional<IdfObject> translateCoilCoolingDXTwoSpeed(model::CoilCoolingDXTwoSpeed& modelObject);
 
     boost::optional<IdfObject> translateCoilCoolingDXTwoSpeedWithoutUnitary(model::CoilCoolingDXTwoSpeed& modelObject);
diff --git a/src/energyplus/ForwardTranslator/ForwardTranslateCoilCoolingDX.cpp b/src/energyplus/ForwardTranslator/ForwardTranslateCoilCoolingDX.cpp
index 862a552d872..6b20bf848cf 100644
--- a/src/energyplus/ForwardTranslator/ForwardTranslateCoilCoolingDX.cpp
+++ b/src/energyplus/ForwardTranslator/ForwardTranslateCoilCoolingDX.cpp
@@ -40,7 +40,7 @@
 #include "../../model/ThermalZone_Impl.hpp"
 #include "../../model/CoilCoolingDXCurveFitPerformance.hpp"
 #include "../../model/CoilCoolingDXCurveFitPerformance_Impl.hpp"
-
+#include <utilities/idd/CoilSystem_Cooling_DX_FieldEnums.hxx>
 #include <utilities/idd/Coil_Cooling_DX_FieldEnums.hxx>
 // #include "../../utilities/idd/IddEnums.hpp"
 #include <utilities/idd/IddEnums.hxx>
@@ -51,7 +51,7 @@ namespace openstudio {
 
 namespace energyplus {
 
-  boost::optional<IdfObject> ForwardTranslator::translateCoilCoolingDX(model::CoilCoolingDX& modelObject) {
+  boost::optional<IdfObject> ForwardTranslator::translateCoilCoolingDXWithoutUnitary(model::CoilCoolingDX& modelObject) {
     boost::optional<std::string> s;
     boost::optional<double> value;
 
@@ -70,9 +70,27 @@ namespace energyplus {
     // PerformanceObjectName
     idfObject.setString(Coil_Cooling_DXFields::PerformanceObjectName, s.get());
 
-    // Evaporator Nodes are handled in the FT for AirLoopHVACUnitarySystem
+    // Evaporator Nodes are handled in the FT for AirLoopHVACUnitarySystem when inside a Unitary, but we set them here in case it's NOT inside a
+    // unitary (yet, we'll put it on a CoilSystem:Cooling:DX)
     // EvaporatorInletNodeName
     // EvaporatorOutletNodeName
+    OptionalModelObject omo = modelObject.inletModelObject();
+    if (omo) {
+      translateAndMapModelObject(*omo);
+      s = omo->name();
+      if (s) {
+        idfObject.setString(Coil_Cooling_DXFields::EvaporatorInletNodeName, *s);
+      }
+    }
+
+    omo = modelObject.outletModelObject();
+    if (omo) {
+      translateAndMapModelObject(*omo);
+      s = omo->name();
+      if (s) {
+        idfObject.setString(Coil_Cooling_DXFields::EvaporatorOutletNodeName, *s);
+      }
+    }
 
     // AvailabilityScheduleName
     {
@@ -116,5 +134,57 @@ namespace energyplus {
     return boost::optional<IdfObject>(idfObject);
   }  // End of translate function
 
+  boost::optional<IdfObject> ForwardTranslator::translateCoilCoolingDX(CoilCoolingDX& modelObject) {
+    IdfObject coilSystemCoolingDXIdf(IddObjectType::CoilSystem_Cooling_DX);
+
+    m_idfObjects.push_back(coilSystemCoolingDXIdf);
+
+    boost::optional<IdfObject> oIdfObject = translateCoilCoolingDXWithoutUnitary(modelObject);
+
+    if (!oIdfObject) {
+      return boost::none;
+    }
+
+    IdfObject idfObject = oIdfObject.get();
+
+    OptionalString s;
+
+    s = modelObject.name();
+    if (s) {
+      coilSystemCoolingDXIdf.setString(CoilSystem_Cooling_DXFields::CoolingCoilObjectType, idfObject.iddObject().name());
+
+      coilSystemCoolingDXIdf.setString(CoilSystem_Cooling_DXFields::CoolingCoilName, *s);
+
+      coilSystemCoolingDXIdf.setName(*s + " CoilSystem");
+    }
+
+    Schedule sched = modelObject.availabilitySchedule();
+    translateAndMapModelObject(sched);
+
+    coilSystemCoolingDXIdf.setString(CoilSystem_Cooling_DXFields::AvailabilityScheduleName, sched.name().get());
+
+    OptionalModelObject omo = modelObject.inletModelObject();
+    if (omo) {
+      translateAndMapModelObject(*omo);
+      s = omo->name();
+      if (s) {
+        coilSystemCoolingDXIdf.setString(CoilSystem_Cooling_DXFields::DXCoolingCoilSystemInletNodeName, *s);
+      }
+    }
+
+    omo = modelObject.outletModelObject();
+    if (omo) {
+      translateAndMapModelObject(*omo);
+      s = omo->name();
+      if (s) {
+        coilSystemCoolingDXIdf.setString(CoilSystem_Cooling_DXFields::DXCoolingCoilSystemOutletNodeName, *s);
+
+        coilSystemCoolingDXIdf.setString(CoilSystem_Cooling_DXFields::DXCoolingCoilSystemSensorNodeName, *s);
+      }
+    }
+
+    return coilSystemCoolingDXIdf;
+  }
+
 }  // end namespace energyplus
 }  // end namespace openstudio
diff --git a/src/energyplus/ForwardTranslator/ForwardTranslateCoilHeatingDesuperheater.cpp b/src/energyplus/ForwardTranslator/ForwardTranslateCoilHeatingDesuperheater.cpp
index 1ccd8df356a..d63537fc971 100644
--- a/src/energyplus/ForwardTranslator/ForwardTranslateCoilHeatingDesuperheater.cpp
+++ b/src/energyplus/ForwardTranslator/ForwardTranslateCoilHeatingDesuperheater.cpp
@@ -100,7 +100,7 @@ namespace energyplus {
       if (_heatingSource) {
 
         // Note JM 2019-03-14:
-        // If the coil in question is a DX coil (CoilCoolingDXSingleSpeed, CoilCoolingDXTwoSpeed, CoilCoolingDXTwoStageWithHumidityControlMode)
+        // If the coil in question is a DX coil (CoilCoolingDXSingleSpeed, CoilCoolingDXTwoSpeed, CoilCoolingDXTwoStageWithHumidityControlMode, CoilCoolingDX)
         // and this DX coil isn't already wrapped in a Unitary, then the FT will wrap it into a CoilSystem:Cooling:DX object and return that, but we
         // need the DX coil here and not the wrapper.
         //
@@ -111,7 +111,7 @@ namespace energyplus {
         std::string objectName;
 
         if (_heatingSource->iddObject().type() == IddObjectType::CoilSystem_Cooling_DX) {
-          // We have retrieve the coil itself, not the wrapper
+          // We must retrieve the coil itself, not the wrapper
           objectType = _heatingSource->getString(CoilSystem_Cooling_DXFields::CoolingCoilObjectType).get();
           objectName = _heatingSource->getString(CoilSystem_Cooling_DXFields::CoolingCoilName).get();
         } else {
diff --git a/src/energyplus/ForwardTranslator/ForwardTranslateCoilSystemCoolingDXHeatExchangerAssisted.cpp b/src/energyplus/ForwardTranslator/ForwardTranslateCoilSystemCoolingDXHeatExchangerAssisted.cpp
index 1a924ce7737..ff0fdaf84bd 100644
--- a/src/energyplus/ForwardTranslator/ForwardTranslateCoilSystemCoolingDXHeatExchangerAssisted.cpp
+++ b/src/energyplus/ForwardTranslator/ForwardTranslateCoilSystemCoolingDXHeatExchangerAssisted.cpp
@@ -34,13 +34,18 @@
 #include "../../model/Node_Impl.hpp"
 #include "../../model/HeatExchangerAirToAirSensibleAndLatent.hpp"
 #include "../../model/HeatExchangerAirToAirSensibleAndLatent_Impl.hpp"
+#include "../../model/CoilCoolingDX.hpp"
+#include "../../model/CoilCoolingDX_Impl.hpp"
 #include "../../model/CoilCoolingDXSingleSpeed.hpp"
 #include "../../model/CoilCoolingDXSingleSpeed_Impl.hpp"
+#include "../../model/CoilCoolingDXVariableSpeed.hpp"
+#include "../../model/CoilCoolingDXVariableSpeed_Impl.hpp"
 #include "../../model/Model.hpp"
 #include "../../utilities/core/Assert.hpp"
 #include <utilities/idd/CoilSystem_Cooling_DX_HeatExchangerAssisted_FieldEnums.hxx>
 #include <utilities/idd/HeatExchanger_AirToAir_SensibleAndLatent_FieldEnums.hxx>
 #include <utilities/idd/HeatExchanger_Desiccant_BalancedFlow_FieldEnums.hxx>
+#include <utilities/idd/Coil_Cooling_DX_FieldEnums.hxx>
 #include <utilities/idd/Coil_Cooling_DX_SingleSpeed_FieldEnums.hxx>
 #include <utilities/idd/Coil_Cooling_DX_VariableSpeed_FieldEnums.hxx>
 #include <utilities/idd/IddEnums.hxx>
@@ -120,8 +125,11 @@ namespace energyplus {
         } else if (idf->iddObject().type() == IddObjectType::Coil_Cooling_DX_VariableSpeed) {
           idf->setString(Coil_Cooling_DX_VariableSpeedFields::IndoorAirInletNodeName, hxSupplyAirOutletNodeName);
           idf->setString(Coil_Cooling_DX_VariableSpeedFields::IndoorAirOutletNodeName, hxExhaustAirInletNodeName);
+        } else if (idf->iddObject().type() == IddObjectType::Coil_Cooling_DX) {
+          idf->setString(Coil_Cooling_DXFields::EvaporatorInletNodeName, hxSupplyAirOutletNodeName);
+          idf->setString(Coil_Cooling_DXFields::EvaporatorOutletNodeName, hxExhaustAirInletNodeName);
         } else {
-          // Shouldn't happen, accepts only Coil:Cooling:DX:SingleSpeed or Coil:Cooling:DX:VariableSpeed
+          // Shouldn't happen, accepts only Coil:Cooling:DX or Coil:Cooling:DX:SingleSpeed or Coil:Cooling:DX:VariableSpeed
           LOG(Fatal, modelObject.briefDescription()
                        << " appears to have a cooling coil that shouldn't have been accepted: " << coolingCoil.briefDescription());
           OS_ASSERT(false);
diff --git a/src/energyplus/ForwardTranslator/ForwardTranslateCoilWaterHeatingDesuperheater.cpp b/src/energyplus/ForwardTranslator/ForwardTranslateCoilWaterHeatingDesuperheater.cpp
index c6cc7ced965..c963884bf00 100644
--- a/src/energyplus/ForwardTranslator/ForwardTranslateCoilWaterHeatingDesuperheater.cpp
+++ b/src/energyplus/ForwardTranslator/ForwardTranslateCoilWaterHeatingDesuperheater.cpp
@@ -158,7 +158,7 @@ namespace energyplus {
 
         // Note JM 2019-03-14:
         // If the coil in question is a DX coil (CoilCoolingDXSingleSpeed, CoilCoolingDXTwoSpeed, CoilCoolingDXTwoStageWithHumidityControlMode,
-        // CoilCoolingDXVariableSpeed, CoilCoolingDXMultiSpeed)
+        // CoilCoolingDXVariableSpeed, CoilCoolingDXMultiSpeed, CoilCoolingDX)
         // and this DX coil isn't already wrapped in a Unitary, then the FT will wrap it into a CoilSystem:Cooling:DX object and return that, but we
         // need the DX coil here and not the wrapper.
         //
@@ -170,7 +170,7 @@ namespace energyplus {
         std::string objectName;
 
         if (_heatingSource->iddObject().type() == IddObjectType::CoilSystem_Cooling_DX) {
-          // We have retrieve the coil itself, not the wrapper
+          // We must retrieve the coil itself, not the wrapper
           objectType = _heatingSource->getString(CoilSystem_Cooling_DXFields::CoolingCoilObjectType).get();
           objectName = _heatingSource->getString(CoilSystem_Cooling_DXFields::CoolingCoilName).get();
         } else {
diff --git a/src/energyplus/ForwardTranslator/ForwardTranslateZoneHVACPackagedTerminalAirConditioner.cpp b/src/energyplus/ForwardTranslator/ForwardTranslateZoneHVACPackagedTerminalAirConditioner.cpp
index 66c3205b147..e68fb23ef27 100644
--- a/src/energyplus/ForwardTranslator/ForwardTranslateZoneHVACPackagedTerminalAirConditioner.cpp
+++ b/src/energyplus/ForwardTranslator/ForwardTranslateZoneHVACPackagedTerminalAirConditioner.cpp
@@ -39,6 +39,8 @@
 #include "../../model/ZoneHVACPackagedTerminalAirConditioner_Impl.hpp"
 #include "../../model/ThermalZone.hpp"
 #include "../../model/ThermalZone_Impl.hpp"
+#include "../../model/CoilCoolingDX.hpp"
+#include "../../model/CoilCoolingDX_Impl.hpp"
 #include "../../model/CoilCoolingDXSingleSpeed.hpp"
 #include "../../model/CoilCoolingDXSingleSpeed_Impl.hpp"
 #include "../../model/CoilCoolingDXVariableSpeed.hpp"
@@ -55,6 +57,7 @@
 #include <utilities/idd/Coil_Heating_Fuel_FieldEnums.hxx>
 #include <utilities/idd/Coil_Heating_Electric_FieldEnums.hxx>
 #include <utilities/idd/Coil_Heating_Water_FieldEnums.hxx>
+#include <utilities/idd/Coil_Cooling_DX_FieldEnums.hxx>
 #include <utilities/idd/Coil_Cooling_DX_SingleSpeed_FieldEnums.hxx>
 #include <utilities/idd/Coil_Cooling_DX_VariableSpeed_FieldEnums.hxx>
 #include <utilities/idd/HeatExchanger_AirToAir_SensibleAndLatent_FieldEnums.hxx>
@@ -335,11 +338,9 @@ namespace energyplus {
 
       if (_coolingCoil->iddObject().type() == IddObjectType::Coil_Cooling_DX_SingleSpeed) {
         _coolingCoil->setString(Coil_Cooling_DX_SingleSpeedFields::AirInletNodeName, coolingCoilInletNodeName);
-
         _coolingCoil->setString(Coil_Cooling_DX_SingleSpeedFields::AirOutletNodeName, coolingCoilOutletNodeName);
       } else if (_coolingCoil->iddObject().type() == IddObjectType::Coil_Cooling_DX_VariableSpeed) {
         _coolingCoil->setString(Coil_Cooling_DX_VariableSpeedFields::IndoorAirInletNodeName, coolingCoilInletNodeName);
-
         _coolingCoil->setString(Coil_Cooling_DX_VariableSpeedFields::IndoorAirOutletNodeName, coolingCoilOutletNodeName);
       } else if (_coolingCoil->iddObject().type() == IddObjectType::CoilSystem_Cooling_DX_HeatExchangerAssisted) {
         auto hx = coolingCoil.cast<CoilSystemCoolingDXHeatExchangerAssisted>().heatExchanger();
@@ -350,6 +351,9 @@ namespace energyplus {
             _heatExchanger->setString(HeatExchanger_AirToAir_SensibleAndLatentFields::ExhaustAirOutletNodeName, coolingCoilOutletNodeName);
           }
         }
+      } else if (_coolingCoil->iddObject().type() == IddObjectType::Coil_Cooling_DX) {
+        _coolingCoil->setString(Coil_Cooling_DXFields::EvaporatorInletNodeName, coolingCoilInletNodeName);
+        _coolingCoil->setString(Coil_Cooling_DXFields::EvaporatorOutletNodeName, coolingCoilOutletNodeName);
       }
     }
 
diff --git a/src/energyplus/ForwardTranslator/ForwardTranslateZoneHVACPackagedTerminalHeatPump.cpp b/src/energyplus/ForwardTranslator/ForwardTranslateZoneHVACPackagedTerminalHeatPump.cpp
index 211c001f387..17864f9b676 100644
--- a/src/energyplus/ForwardTranslator/ForwardTranslateZoneHVACPackagedTerminalHeatPump.cpp
+++ b/src/energyplus/ForwardTranslator/ForwardTranslateZoneHVACPackagedTerminalHeatPump.cpp
@@ -37,6 +37,8 @@
 #include "../../model/ZoneHVACPackagedTerminalHeatPump_Impl.hpp"
 #include "../../model/ThermalZone.hpp"
 #include "../../model/ThermalZone_Impl.hpp"
+#include "../../model/CoilCoolingDX.hpp"
+#include "../../model/CoilCoolingDX_Impl.hpp"
 #include "../../model/CoilCoolingDXSingleSpeed.hpp"
 #include "../../model/CoilCoolingDXSingleSpeed_Impl.hpp"
 #include "../../model/CoilCoolingDXVariableSpeed.hpp"
@@ -60,6 +62,7 @@
 #include <utilities/idd/Coil_Heating_Fuel_FieldEnums.hxx>
 #include <utilities/idd/Coil_Heating_Electric_FieldEnums.hxx>
 #include <utilities/idd/Coil_Heating_Water_FieldEnums.hxx>
+#include <utilities/idd/Coil_Cooling_DX_FieldEnums.hxx>
 #include <utilities/idd/Coil_Cooling_DX_SingleSpeed_FieldEnums.hxx>
 #include <utilities/idd/Coil_Cooling_DX_VariableSpeed_FieldEnums.hxx>
 #include <utilities/idd/HeatExchanger_AirToAir_SensibleAndLatent_FieldEnums.hxx>
@@ -317,6 +320,10 @@ namespace energyplus {
     } else if (boost::optional<CoilCoolingDXVariableSpeed> dxCoil = coolingCoil.optionalCast<CoilCoolingDXVariableSpeed>()) {
       _coolingCoil = translateCoilCoolingDXVariableSpeedWithoutUnitary(dxCoil.get());
 
+      m_map.insert(std::make_pair(coolingCoil.handle(), _coolingCoil.get()));
+    } else if (boost::optional<CoilCoolingDX> dxCoil = coolingCoil.optionalCast<CoilCoolingDX>()) {
+      _coolingCoil = translateCoilCoolingDXWithoutUnitary(dxCoil.get());
+
       m_map.insert(std::make_pair(coolingCoil.handle(), _coolingCoil.get()));
     } else {
       _coolingCoil = translateAndMapModelObject(coolingCoil);
@@ -341,11 +348,9 @@ namespace energyplus {
 
       if (_coolingCoil->iddObject().type() == IddObjectType::Coil_Cooling_DX_SingleSpeed) {
         _coolingCoil->setString(Coil_Cooling_DX_SingleSpeedFields::AirInletNodeName, coolingCoilInletNodeName);
-
         _coolingCoil->setString(Coil_Cooling_DX_SingleSpeedFields::AirOutletNodeName, coolingCoilOutletNodeName);
       } else if (_coolingCoil->iddObject().type() == IddObjectType::Coil_Cooling_DX_VariableSpeed) {
         _coolingCoil->setString(Coil_Cooling_DX_VariableSpeedFields::IndoorAirInletNodeName, coolingCoilInletNodeName);
-
         _coolingCoil->setString(Coil_Cooling_DX_VariableSpeedFields::IndoorAirOutletNodeName, coolingCoilOutletNodeName);
       } else if (_coolingCoil->iddObject().type() == IddObjectType::CoilSystem_Cooling_DX_HeatExchangerAssisted) {
         auto hx = coolingCoil.cast<CoilSystemCoolingDXHeatExchangerAssisted>().heatExchanger();
@@ -356,6 +361,9 @@ namespace energyplus {
             _heatExchanger->setString(HeatExchanger_AirToAir_SensibleAndLatentFields::ExhaustAirOutletNodeName, coolingCoilOutletNodeName);
           }
         }
+      } else if (_coolingCoil->iddObject().type() == IddObjectType::Coil_Cooling_DX) {
+        _coolingCoil->setString(Coil_Cooling_DXFields::EvaporatorInletNodeName, coolingCoilInletNodeName);
+        _coolingCoil->setString(Coil_Cooling_DXFields::EvaporatorOutletNodeName, coolingCoilOutletNodeName);
       }
     }
 
diff --git a/src/energyplus/Test/CoilCoolingDX_GTest.cpp b/src/energyplus/Test/CoilCoolingDX_GTest.cpp
index e4040772fcd..4c1a1b5c8ab 100644
--- a/src/energyplus/Test/CoilCoolingDX_GTest.cpp
+++ b/src/energyplus/Test/CoilCoolingDX_GTest.cpp
@@ -44,8 +44,19 @@
 #include "../../model/AirLoopHVACUnitarySystem.hpp"
 #include "../../model/Node.hpp"
 
+#include "../../utilities/idf/IdfObject.hpp"
+#include "../../utilities/idf/IdfObject_Impl.hpp"
+#include "../../utilities/idf/WorkspaceObject.hpp"
+#include "../../utilities/idf/WorkspaceObject_Impl.hpp"
+#include "../../utilities/idf/IdfExtensibleGroup.hpp"
+#include "../../utilities/idf/WorkspaceExtensibleGroup.hpp"
+
 #include <utilities/idd/Coil_Cooling_DX_FieldEnums.hxx>
 #include <utilities/idd/Coil_Cooling_DX_CurveFit_Performance_FieldEnums.hxx>
+#include <utilities/idd/CoilSystem_Cooling_DX_FieldEnums.hxx>
+#include <utilities/idd/AirLoopHVAC_FieldEnums.hxx>
+#include <utilities/idd/BranchList_FieldEnums.hxx>
+#include <utilities/idd/Branch_FieldEnums.hxx>
 #include <utilities/idd/AirLoopHVAC_UnitarySystem_FieldEnums.hxx>
 #include <utilities/idd/IddEnums.hxx>
 
@@ -53,7 +64,7 @@ using namespace openstudio::energyplus;
 using namespace openstudio::model;
 using namespace openstudio;
 
-TEST_F(EnergyPlusFixture, ForwardTranslator_CoilCoolingDX) {
+TEST_F(EnergyPlusFixture, ForwardTranslator_CoilCoolingDX_Unitary) {
   Model m;
   CoilCoolingDXCurveFitOperatingMode operatingMode(m);
   CoilCoolingDXCurveFitPerformance performance(m, operatingMode);
@@ -82,6 +93,9 @@ TEST_F(EnergyPlusFixture, ForwardTranslator_CoilCoolingDX) {
   ASSERT_EQ(1u, idfDXs.size());
   WorkspaceObject idfDX(idfDXs[0]);
 
+  // No CoilSystem:Cooling:DX wrapper needed, it's inside a unitary
+  EXPECT_EQ(0, w.getObjectsByType(IddObjectType::CoilSystem_Cooling_DX).size());
+
   // Check that the Unitary ends up with the CoilCoolingDX
   EXPECT_EQ("Coil:Cooling:DX", idfUnitary.getString(AirLoopHVAC_UnitarySystemFields::CoolingCoilObjectType).get());
   EXPECT_EQ(idfDX.nameString(), idfUnitary.getString(AirLoopHVAC_UnitarySystemFields::CoolingCoilName).get());
@@ -138,3 +152,62 @@ TEST_F(EnergyPlusFixture, ForwardTranslator_CoilCoolingDX) {
 
   EXPECT_EQ(woBaseOperatingMode.get(), idfOperatingMode);
 }
+
+TEST_F(EnergyPlusFixture, ForwardTranslator_CoilCoolingDX_AirLoopHVAC) {
+
+  ForwardTranslator ft;
+
+  Model m;
+  CoilCoolingDXCurveFitOperatingMode operatingMode(m);
+  CoilCoolingDXCurveFitPerformance performance(m, operatingMode);
+  CoilCoolingDX dx(m, performance);
+  dx.setName("CoilCoolingDX");
+
+  AirLoopHVAC a(m);
+  Node supplyOutletNode = a.supplyOutletNode();
+  EXPECT_TRUE(dx.addToNode(supplyOutletNode));
+
+  Workspace w = ft.translateModel(m);
+  WorkspaceObjectVector idf_dxs = w.getObjectsByType(IddObjectType::Coil_Cooling_DX);
+  ASSERT_EQ(1u, idf_dxs.size());
+  WorkspaceObject idf_dx(idf_dxs[0]);
+
+  EXPECT_EQ(idf_dx.getString(Coil_Cooling_DXFields::EvaporatorInletNodeName).get(), dx.inletModelObject().get().nameString());
+  EXPECT_EQ(idf_dx.getString(Coil_Cooling_DXFields::EvaporatorOutletNodeName).get(), dx.outletModelObject().get().nameString());
+
+  EXPECT_EQ(1, w.getObjectsByType(IddObjectType::CoilSystem_Cooling_DX).size());
+
+  // Go from AirLoopHVAC to BranchList to Branch
+  WorkspaceObjectVector idf_airloops = w.getObjectsByType(IddObjectType::AirLoopHVAC);
+  ASSERT_EQ(1u, idf_airloops.size());
+
+  WorkspaceObject& idf_airLoopHVAC = idf_airloops.front();
+  WorkspaceObject idf_brlist = idf_airLoopHVAC.getTarget(AirLoopHVACFields::BranchListName).get();
+
+  // Should have one branch only
+  ASSERT_EQ(1u, idf_brlist.extensibleGroups().size());
+  auto w_eg = idf_brlist.extensibleGroups()[0].cast<WorkspaceExtensibleGroup>();
+  WorkspaceObject idf_branch = w_eg.getTarget(BranchListExtensibleFields::BranchName).get();
+
+  // There should be only one equipment on the branch
+  ASSERT_EQ(1u, idf_branch.extensibleGroups().size());
+  auto w_eg2 = idf_branch.extensibleGroups()[0].cast<WorkspaceExtensibleGroup>();
+
+  EXPECT_EQ(w_eg2.getString(BranchExtensibleFields::ComponentInletNodeName).get(), dx.inletModelObject().get().nameString());
+  EXPECT_EQ(w_eg2.getString(BranchExtensibleFields::ComponentOutletNodeName).get(), dx.outletModelObject().get().nameString());
+
+  EXPECT_EQ("CoilSystem:Cooling:DX", w_eg2.getString(BranchExtensibleFields::ComponentObjectType).get());
+  auto idf_coilSystem = w_eg2.getTarget(BranchExtensibleFields::ComponentName).get();
+  // CoilSystem:Cooling:DX wrapper needed, it's not inside a unitary
+  EXPECT_EQ(1, w.getObjectsByType(IddObjectType::CoilSystem_Cooling_DX).size());
+
+  EXPECT_EQ("Always On Discrete", idf_coilSystem.getString(CoilSystem_Cooling_DXFields::AvailabilityScheduleName).get());
+  EXPECT_EQ(dx.inletModelObject().get().nameString(), idf_coilSystem.getString(CoilSystem_Cooling_DXFields::DXCoolingCoilSystemInletNodeName).get());
+  EXPECT_EQ(dx.outletModelObject().get().nameString(),
+            idf_coilSystem.getString(CoilSystem_Cooling_DXFields::DXCoolingCoilSystemOutletNodeName).get());
+  EXPECT_EQ(dx.outletModelObject().get().nameString(),
+            idf_coilSystem.getString(CoilSystem_Cooling_DXFields::DXCoolingCoilSystemSensorNodeName).get());
+  EXPECT_EQ("Coil:Cooling:DX", idf_coilSystem.getString(CoilSystem_Cooling_DXFields::CoolingCoilObjectType).get());
+  EXPECT_EQ(dx.nameString(), idf_coilSystem.getString(CoilSystem_Cooling_DXFields::CoolingCoilName).get());
+  EXPECT_EQ(idf_dx, idf_coilSystem.getTarget(CoilSystem_Cooling_DXFields::CoolingCoilName).get());
+}
diff --git a/src/energyplus/Test/CoilHeatingDesuperheater_GTest.cpp b/src/energyplus/Test/CoilHeatingDesuperheater_GTest.cpp
index 1ec740b4262..37c69819f44 100644
--- a/src/energyplus/Test/CoilHeatingDesuperheater_GTest.cpp
+++ b/src/energyplus/Test/CoilHeatingDesuperheater_GTest.cpp
@@ -37,6 +37,9 @@
 #include "../../model/CoilCoolingDXSingleSpeed.hpp"
 #include "../../model/CoilCoolingDXTwoSpeed.hpp"
 #include "../../model/CoilCoolingDXTwoStageWithHumidityControlMode.hpp"
+#include "../../model/CoilCoolingDX.hpp"
+#include "../../model/CoilCoolingDXCurveFitOperatingMode.hpp"
+#include "../../model/CoilCoolingDXCurveFitPerformance.hpp"
 
 #include <utilities/idd/IddObject.hpp>
 #include <utilities/idd/Coil_Heating_Desuperheater_FieldEnums.hxx>
@@ -51,7 +54,11 @@ TEST_F(EnergyPlusFixture, ForwardTranslator_CoilHeatingDesuperheater) {
 
   CoilHeatingDesuperheater desuperheater(m);
 
-  std::vector<HVACComponent> testCoils = {CoilCoolingDXSingleSpeed(m), CoilCoolingDXTwoSpeed(m), CoilCoolingDXTwoStageWithHumidityControlMode(m)};
+  CoilCoolingDXCurveFitOperatingMode operatingMode(m);
+  CoilCoolingDXCurveFitPerformance performance(m, operatingMode);
+
+  std::vector<HVACComponent> testCoils = {CoilCoolingDXSingleSpeed(m), CoilCoolingDXTwoSpeed(m), CoilCoolingDXTwoStageWithHumidityControlMode(m),
+                                          CoilCoolingDX(m, performance)};
 
   ForwardTranslator forwardTranslator;
 
diff --git a/src/energyplus/Test/CoilWaterHeatingDesuperheater_GTest.cpp b/src/energyplus/Test/CoilWaterHeatingDesuperheater_GTest.cpp
index ffba79a7bca..a1fe517ce5e 100644
--- a/src/energyplus/Test/CoilWaterHeatingDesuperheater_GTest.cpp
+++ b/src/energyplus/Test/CoilWaterHeatingDesuperheater_GTest.cpp
@@ -41,6 +41,9 @@
 #include "../../model/CoilCoolingDXTwoStageWithHumidityControlMode.hpp"
 #include "../../model/CoilCoolingDXVariableSpeed.hpp"
 #include "../../model/CoilCoolingDXMultiSpeed.hpp"
+#include "../../model/CoilCoolingDX.hpp"
+#include "../../model/CoilCoolingDXCurveFitOperatingMode.hpp"
+#include "../../model/CoilCoolingDXCurveFitPerformance.hpp"
 
 // Not DX
 #include "../../model/CoilCoolingWaterToAirHeatPumpEquationFit.hpp"
@@ -66,9 +69,12 @@ TEST_F(EnergyPlusFixture, ForwardTranslator_CoilWaterHeatingDesuperheater_DXCoil
   CoilWaterHeatingDesuperheater desuperheater(m, temperatureSetpointSchedule);
   desuperheater.setRatedHeatReclaimRecoveryEfficiency(0.25);
 
+  CoilCoolingDXCurveFitOperatingMode operatingMode(m);
+  CoilCoolingDXCurveFitPerformance performance(m, operatingMode);
+
   // DX Coils that will be wrapped in CoilSystem:Cooling:DX
-  std::vector<HVACComponent> testCoils = {CoilCoolingDXSingleSpeed(m), CoilCoolingDXTwoSpeed(m), CoilCoolingDXTwoStageWithHumidityControlMode(m),
-                                          CoilCoolingDXVariableSpeed(m), CoilCoolingDXMultiSpeed(m)};
+  std::vector<HVACComponent> testCoils = {CoilCoolingDXSingleSpeed(m),   CoilCoolingDXTwoSpeed(m),   CoilCoolingDXTwoStageWithHumidityControlMode(m),
+                                          CoilCoolingDXVariableSpeed(m), CoilCoolingDXMultiSpeed(m), CoilCoolingDX(m, performance)};
 
   ForwardTranslator forwardTranslator;
 
diff --git a/src/energyplus/Test/ZoneHVACPackagedTerminalAirConditioner_GTest.cpp b/src/energyplus/Test/ZoneHVACPackagedTerminalAirConditioner_GTest.cpp
index b2993cb4653..70e24e6c590 100644
--- a/src/energyplus/Test/ZoneHVACPackagedTerminalAirConditioner_GTest.cpp
+++ b/src/energyplus/Test/ZoneHVACPackagedTerminalAirConditioner_GTest.cpp
@@ -36,6 +36,9 @@
 #include "../../model/ThermalZone.hpp"
 #include "../../model/Space.hpp"
 #include "../../model/CoilWaterHeatingDesuperheater.hpp"
+#include "../../model/CoilCoolingDX.hpp"
+#include "../../model/CoilCoolingDXCurveFitOperatingMode.hpp"
+#include "../../model/CoilCoolingDXCurveFitPerformance.hpp"
 #include "../../model/CoilCoolingDXSingleSpeed.hpp"
 #include "../../model/CoilCoolingDXVariableSpeed.hpp"
 #include "../../model/CoilSystemCoolingDXHeatExchangerAssisted.hpp"
@@ -145,3 +148,37 @@ TEST_F(EnergyPlusFixture, ForwardTranslator_ZoneHVACPackagedTerminalAirCondition
   EXPECT_EQ(0u, workspace.getObjectsByType(IddObjectType::CoilSystem_Cooling_DX).size());
   EXPECT_EQ(1u, workspace.getObjectsByType(IddObjectType::CoilSystem_Cooling_DX_HeatExchangerAssisted).size());
 }
+
+TEST_F(EnergyPlusFixture, ForwardTranslator_ZoneHVACPackagedTerminalAirConditioner_CoilCoolingDX) {
+
+  Model m;
+
+  Schedule sch = m.alwaysOnDiscreteSchedule();
+  FanConstantVolume fan(m);
+  CoilCoolingDXCurveFitOperatingMode operatingMode(m);
+  CoilCoolingDXCurveFitPerformance performance(m, operatingMode);
+  CoilCoolingDX cc(m, performance);
+  CoilHeatingElectric hc(m);
+
+  ZoneHVACPackagedTerminalAirConditioner ptac(m, sch, fan, hc, cc);
+
+  // Need to be in a thermal zone to be translated, and TZ needs at least one space
+  ThermalZone z(m);
+  ptac.addToThermalZone(z);
+  Space s(m);
+  s.setThermalZone(z);
+
+  ForwardTranslator forwardTranslator;
+  Workspace workspace = forwardTranslator.translateModel(m);
+
+  WorkspaceObjectVector idfObjs(workspace.getObjectsByType(IddObjectType::ZoneHVAC_PackagedTerminalAirConditioner));
+  ASSERT_EQ(1u, idfObjs.size());
+  WorkspaceObject idf_ptac(idfObjs[0]);
+
+  // Check that the DX coil ends up directly onto the object, and NOT a CoilSystem:Cooling:DX wrapper|
+  EXPECT_EQ("Coil:Cooling:DX", idf_ptac.getString(ZoneHVAC_PackagedTerminalAirConditionerFields::CoolingCoilObjectType).get());
+  EXPECT_EQ(cc.nameString(), idf_ptac.getString(ZoneHVAC_PackagedTerminalAirConditionerFields::CoolingCoilName).get());
+
+  EXPECT_EQ(0u, workspace.getObjectsByType(IddObjectType::CoilSystem_Cooling_DX).size());
+  EXPECT_EQ(1u, workspace.getObjectsByType(IddObjectType::Coil_Cooling_DX).size());
+}
diff --git a/src/energyplus/Test/ZoneHVACPackagedTerminalHeatPump_GTest.cpp b/src/energyplus/Test/ZoneHVACPackagedTerminalHeatPump_GTest.cpp
index 5739855ab68..a1e6eb7b8ec 100644
--- a/src/energyplus/Test/ZoneHVACPackagedTerminalHeatPump_GTest.cpp
+++ b/src/energyplus/Test/ZoneHVACPackagedTerminalHeatPump_GTest.cpp
@@ -37,6 +37,9 @@
 #include "../../model/Space.hpp"
 #include "../../model/CoilHeatingDXSingleSpeed.hpp"
 #include "../../model/CoilHeatingDXVariableSpeed.hpp"
+#include "../../model/CoilCoolingDX.hpp"
+#include "../../model/CoilCoolingDXCurveFitOperatingMode.hpp"
+#include "../../model/CoilCoolingDXCurveFitPerformance.hpp"
 #include "../../model/CoilCoolingDXSingleSpeed.hpp"
 #include "../../model/CoilCoolingDXVariableSpeed.hpp"
 #include "../../model/CoilSystemCoolingDXHeatExchangerAssisted.hpp"
@@ -157,3 +160,41 @@ TEST_F(EnergyPlusFixture, ForwardTranslator_ZoneHVACPackagedTerminalHeatPump_Coi
   EXPECT_EQ(0u, workspace.getObjectsByType(IddObjectType::CoilSystem_Cooling_DX).size());
   EXPECT_EQ(1u, workspace.getObjectsByType(IddObjectType::CoilSystem_Cooling_DX_HeatExchangerAssisted).size());
 }
+
+TEST_F(EnergyPlusFixture, ForwardTranslator_ZoneHVACPackagedTerminalHeatPump_CoilCoolingDX) {
+
+  Model m;
+
+  Schedule sch = m.alwaysOnDiscreteSchedule();
+  FanConstantVolume fan(m, sch);
+  CoilHeatingDXVariableSpeed hc(m);
+  CoilCoolingDXCurveFitOperatingMode operatingMode(m);
+  CoilCoolingDXCurveFitPerformance performance(m, operatingMode);
+  CoilCoolingDX cc(m, performance);
+  CoilHeatingElectric shc(m);
+
+  ZoneHVACPackagedTerminalHeatPump pthp(m, sch, fan, hc, cc, shc);
+
+  // Need to be in a thermal zone to be translated, with at least one space
+  ThermalZone z(m);
+  pthp.addToThermalZone(z);
+  Space s(m);
+  s.setThermalZone(z);
+
+  ForwardTranslator forwardTranslator;
+  Workspace workspace = forwardTranslator.translateModel(m);
+
+  WorkspaceObjectVector idfObjs(workspace.getObjectsByType(IddObjectType::ZoneHVAC_PackagedTerminalHeatPump));
+  ASSERT_EQ(1u, idfObjs.size());
+  WorkspaceObject idf_pthp(idfObjs[0]);
+
+  EXPECT_EQ("Coil:Heating:DX:VariableSpeed", idf_pthp.getString(ZoneHVAC_PackagedTerminalHeatPumpFields::HeatingCoilObjectType).get());
+  EXPECT_EQ(hc.nameString(), idf_pthp.getString(ZoneHVAC_PackagedTerminalHeatPumpFields::HeatingCoilName).get());
+
+  // Check that the DX coil ends up directly onto the object, and NOT a CoilSystem:Cooling:DX wrapper|
+  EXPECT_EQ("Coil:Cooling:DX", idf_pthp.getString(ZoneHVAC_PackagedTerminalHeatPumpFields::CoolingCoilObjectType).get());
+  EXPECT_EQ(cc.nameString(), idf_pthp.getString(ZoneHVAC_PackagedTerminalHeatPumpFields::CoolingCoilName).get());
+
+  EXPECT_EQ(0u, workspace.getObjectsByType(IddObjectType::CoilSystem_Cooling_DX).size());
+  EXPECT_EQ(1u, workspace.getObjectsByType(IddObjectType::Coil_Cooling_DX).size());
+}
diff --git a/src/model/CoilCoolingDX.cpp b/src/model/CoilCoolingDX.cpp
index 8d58017d075..8c763cb7072 100644
--- a/src/model/CoilCoolingDX.cpp
+++ b/src/model/CoilCoolingDX.cpp
@@ -40,10 +40,22 @@
 #include "ScheduleTypeRegistry.hpp"
 #include "CoilCoolingDXCurveFitPerformance.hpp"
 #include "CoilCoolingDXCurveFitPerformance_Impl.hpp"
+#include "Node.hpp"
+#include "Node_Impl.hpp"
 #include "AirLoopHVACUnitarySystem.hpp"
 #include "AirLoopHVACUnitarySystem_Impl.hpp"
+#include "AirLoopHVACOutdoorAirSystem.hpp"
+#include "AirLoopHVACOutdoorAirSystem_Impl.hpp"
+#include "AirLoopHVACDedicatedOutdoorAirSystem.hpp"
+#include "AirLoopHVACDedicatedOutdoorAirSystem_Impl.hpp"
 #include "AirflowNetworkEquivalentDuct.hpp"
 #include "AirflowNetworkEquivalentDuct_Impl.hpp"
+#include "CoilSystemCoolingDXHeatExchangerAssisted.hpp"
+#include "CoilSystemCoolingDXHeatExchangerAssisted_Impl.hpp"
+#include "ZoneHVACPackagedTerminalAirConditioner.hpp"
+#include "ZoneHVACPackagedTerminalAirConditioner_Impl.hpp"
+#include "ZoneHVACPackagedTerminalHeatPump.hpp"
+#include "ZoneHVACPackagedTerminalHeatPump_Impl.hpp"
 
 #include <utilities/idd/IddFactory.hxx>
 #include <utilities/idd/IddEnums.hxx>
@@ -144,11 +156,68 @@ namespace model {
         }
       }
 
+      // CoilSystemCoolingDXHeatExchangerAssisted
+      {
+        auto coilSystems = this->model().getConcreteModelObjects<CoilSystemCoolingDXHeatExchangerAssisted>();
+        for (const auto& coilSystem : coilSystems) {
+          if (coilSystem.coolingCoil().handle() == this->handle()) {
+            return coilSystem;
+          }
+        }
+      }
+
+      return boost::none;
+    }
+
+    boost::optional<ZoneHVACComponent> CoilCoolingDX_Impl::containingZoneHVACComponent() const {
+      // ZoneHVACPackagedTerminalAirConditioner
+
+      std::vector<ZoneHVACPackagedTerminalAirConditioner> zoneHVACPackagedTerminalAirConditioners =
+        this->model().getConcreteModelObjects<ZoneHVACPackagedTerminalAirConditioner>();
+
+      for (const auto& zoneHVACPackagedTerminalAirConditioner : zoneHVACPackagedTerminalAirConditioners) {
+        if (boost::optional<HVACComponent> coil = zoneHVACPackagedTerminalAirConditioner.coolingCoil()) {
+          if (coil->handle() == this->handle()) {
+            return zoneHVACPackagedTerminalAirConditioner;
+          }
+        }
+      }
+
+      // ZoneHVACPackagedTerminalHeatPump
+
+      std::vector<ZoneHVACPackagedTerminalHeatPump> zoneHVACPackagedTerminalHeatPumps =
+        this->model().getConcreteModelObjects<ZoneHVACPackagedTerminalHeatPump>();
+
+      for (const auto& zoneHVACPackagedTerminalHeatPump : zoneHVACPackagedTerminalHeatPumps) {
+        if (boost::optional<HVACComponent> coil = zoneHVACPackagedTerminalHeatPump.coolingCoil()) {
+          if (coil->handle() == this->handle()) {
+            return zoneHVACPackagedTerminalHeatPump;
+          }
+        }
+      }
+
       return boost::none;
     }
 
     bool CoilCoolingDX_Impl::addToNode(Node& node) {
-      // Only meant to be in a AirLoopHVACUnitarySystem
+      if (boost::optional<AirLoopHVAC> airLoop = node.airLoopHVAC()) {
+        if (!airLoop->demandComponent(node.handle())) {
+          // TODO: JM 2019-03-12 I'm not sure we shouldn't just restrict to ANY containingHVACComponent (disallow if part of a UnitarySystem)
+          auto t_containingHVACComponent = containingHVACComponent();
+          if (t_containingHVACComponent && t_containingHVACComponent->optionalCast<CoilSystemCoolingDXHeatExchangerAssisted>()) {
+            LOG(Warn,
+                this->briefDescription() << " cannot be connected directly when it's part of a parent CoilSystemCoolingDXHeatExchangerAssisted. "
+                                            "Please call CoilSystemCoolingDXHeatExchangerAssisted::addToNode instead");
+          } else {
+            return StraightComponent_Impl::addToNode(node);
+          }
+        }
+      } else if (boost::optional<AirLoopHVACOutdoorAirSystem> oas = node.airLoopHVACOutdoorAirSystem()) {
+        if (oas->airLoopHVACDedicatedOutdoorAirSystem()) {
+          return StraightComponent_Impl::addToNode(node);
+        }
+      }
+
       return false;
     }
 
diff --git a/src/model/CoilCoolingDX_Impl.hpp b/src/model/CoilCoolingDX_Impl.hpp
index 61bba01c317..e6473da328e 100644
--- a/src/model/CoilCoolingDX_Impl.hpp
+++ b/src/model/CoilCoolingDX_Impl.hpp
@@ -77,6 +77,8 @@ namespace model {
 
       virtual boost::optional<HVACComponent> containingHVACComponent() const override;
 
+      virtual boost::optional<ZoneHVACComponent> containingZoneHVACComponent() const override;
+
       virtual bool addToNode(Node& node) override;
 
       //@}
diff --git a/src/model/ZoneHVACPackagedTerminalAirConditioner.cpp b/src/model/ZoneHVACPackagedTerminalAirConditioner.cpp
index a922863f93c..5851405525b 100644
--- a/src/model/ZoneHVACPackagedTerminalAirConditioner.cpp
+++ b/src/model/ZoneHVACPackagedTerminalAirConditioner.cpp
@@ -471,7 +471,8 @@ namespace model {
 
       if ((coolingCoil.iddObjectType() == IddObjectType::OS_Coil_Cooling_DX_SingleSpeed)
           || (coolingCoil.iddObjectType() == IddObjectType::OS_Coil_Cooling_DX_VariableSpeed)
-          || (coolingCoil.iddObjectType() == IddObjectType::OS_CoilSystem_Cooling_DX_HeatExchangerAssisted)) {
+          || (coolingCoil.iddObjectType() == IddObjectType::OS_CoilSystem_Cooling_DX_HeatExchangerAssisted)
+          || (coolingCoil.iddObjectType() == IddObjectType::OS_Coil_Cooling_DX)) {
         isAllowedType = true;
       }
 
@@ -479,7 +480,7 @@ namespace model {
         return setPointer(OS_ZoneHVAC_PackagedTerminalAirConditionerFields::CoolingCoilName, coolingCoil.handle());
       } else {
         LOG(Warn, "Invalid Cooling Coil Type (expected CoilCoolingDXSingleSpeed or CoilSystemCoolingDXHeatExchangerAssisted or "
-                  "CoilCoolingDXVariableSpeed, not '"
+                  "CoilCoolingDXVariableSpeed or CoilCoolingDX, not '"
                     << coolingCoil.iddObjectType().valueName() << "') for " << briefDescription());
         return false;
       }
diff --git a/src/model/ZoneHVACPackagedTerminalHeatPump.cpp b/src/model/ZoneHVACPackagedTerminalHeatPump.cpp
index 2e521e0a1ca..8979b27759f 100644
--- a/src/model/ZoneHVACPackagedTerminalHeatPump.cpp
+++ b/src/model/ZoneHVACPackagedTerminalHeatPump.cpp
@@ -549,7 +549,8 @@ namespace model {
 
       if ((hvacComponent.iddObjectType() == IddObjectType::OS_Coil_Cooling_DX_SingleSpeed)
           || (hvacComponent.iddObjectType() == IddObjectType::OS_Coil_Cooling_DX_VariableSpeed)
-          || (hvacComponent.iddObjectType() == IddObjectType::OS_CoilSystem_Cooling_DX_HeatExchangerAssisted)) {
+          || (hvacComponent.iddObjectType() == IddObjectType::OS_CoilSystem_Cooling_DX_HeatExchangerAssisted)
+          || (hvacComponent.iddObjectType() == IddObjectType::OS_Coil_Cooling_DX)) {
         isAllowedType = true;
       }
 
@@ -557,7 +558,7 @@ namespace model {
         return setPointer(OS_ZoneHVAC_PackagedTerminalHeatPumpFields::CoolingCoilName, hvacComponent.handle());
       } else {
         LOG(Warn, "Invalid Cooling Coil Type (expected CoilCoolingDXSingleSpeed or CoilSystemCoolingDXHeatExchangerAssisted or "
-                  "CoilCoolingDXVariableSpeed, not '"
+                  "CoilCoolingDXVariableSpeed or CoilCoolingDX, not '"
                     << hvacComponent.iddObjectType().valueName() << "') for " << briefDescription());
         return false;
       }


Test patch:
diff --git a/src/model/test/CoilCoolingDX_GTest.cpp b/src/model/test/CoilCoolingDX_GTest.cpp
index ccc8d1ec87e..02e72def85e 100644
--- a/src/model/test/CoilCoolingDX_GTest.cpp
+++ b/src/model/test/CoilCoolingDX_GTest.cpp
@@ -47,7 +47,18 @@
 #include "../AirLoopHVACUnitarySystem.hpp"
 #include "../AirLoopHVACUnitarySystem_Impl.hpp"
 #include "../AirLoopHVAC.hpp"
+#include "../PlantLoop.hpp"
 #include "../Node.hpp"
+#include "../Node_Impl.hpp"
+#include "../CoilSystemCoolingDXHeatExchangerAssisted.hpp"
+#include "../ZoneHVACPackagedTerminalAirConditioner.hpp"
+#include "../ZoneHVACPackagedTerminalHeatPump.hpp"
+#include "../ScheduleCompact.hpp"
+#include "../CoilHeatingDXSingleSpeed.hpp"
+#include "../FanConstantVolume.hpp"
+#include "../CoilHeatingElectric.hpp"
+#include "../CoilHeatingWater.hpp"
+#include "../AirLoopHVACZoneSplitter.hpp"
 
 using namespace openstudio;
 using namespace openstudio::model;
@@ -152,41 +163,139 @@ TEST_F(ModelFixture, CoilCoolingDX_GettersSetters) {
 }
 
 TEST_F(ModelFixture, CoilCoolingDX_containingHVACComponent) {
+  {  // AirLoopHVACUnitarySystem
+    Model model;
+
+    CoilCoolingDXCurveFitOperatingMode operatingMode(model);
+    CoilCoolingDXCurveFitPerformance performance(model, operatingMode);
+    CoilCoolingDX dx(model, performance);
+    EXPECT_TRUE(dx.isRemovable());
+
+    AirLoopHVACUnitarySystem unitary(model);
+    EXPECT_TRUE(unitary.setCoolingCoil(dx));
+    ASSERT_TRUE(unitary.coolingCoil());
+    EXPECT_EQ(dx, unitary.coolingCoil().get());
+
+    ASSERT_TRUE(dx.containingHVACComponent());
+    EXPECT_EQ(unitary, dx.containingHVACComponent().get());
+
+    // Shouldn't be able to remove DX since it's contained in a HVAC Component
+    EXPECT_FALSE(dx.isRemovable());
+    auto rmed = dx.remove();
+    EXPECT_EQ(0u, rmed.size());
+    ASSERT_TRUE(unitary.coolingCoil());
+    EXPECT_EQ(dx, unitary.coolingCoil().get());
+  }
+
+  {  // CoilSystemCoolingDXHeatExchangerAssisted
+    Model model;
+
+    CoilCoolingDXCurveFitOperatingMode operatingMode(model);
+    CoilCoolingDXCurveFitPerformance performance(model, operatingMode);
+    CoilCoolingDX dx(model, performance);
+    EXPECT_TRUE(dx.isRemovable());
+
+    CoilSystemCoolingDXHeatExchangerAssisted hx(model);
+    EXPECT_TRUE(hx.setCoolingCoil(dx));
+    EXPECT_EQ(dx, hx.coolingCoil());
+
+    ASSERT_TRUE(dx.containingHVACComponent());
+    EXPECT_EQ(hx, dx.containingHVACComponent().get());
+
+    // Shouldn't be able to remove DX since it's contained in a HVAC Component
+    EXPECT_FALSE(dx.isRemovable());
+    auto rmed = dx.remove();
+    EXPECT_EQ(0u, rmed.size());
+    EXPECT_EQ(dx, hx.coolingCoil());
+  }
+}
 
-  Model model;
-
-  CoilCoolingDXCurveFitOperatingMode operatingMode(model);
-  CoilCoolingDXCurveFitPerformance performance(model, operatingMode);
-  CoilCoolingDX dx(model, performance);
-  EXPECT_TRUE(dx.isRemovable());
-
-  AirLoopHVACUnitarySystem unitary(model);
-  EXPECT_TRUE(unitary.setCoolingCoil(dx));
-  ASSERT_TRUE(unitary.coolingCoil());
-  EXPECT_EQ(dx, unitary.coolingCoil().get());
-
-  ASSERT_TRUE(dx.containingHVACComponent());
-  EXPECT_EQ(unitary, dx.containingHVACComponent().get());
-
-  // Shouldn't be able to remove DX since it's contained in a HVAC Component
-  EXPECT_FALSE(dx.isRemovable());
-  auto rmed = dx.remove();
-  EXPECT_EQ(0u, rmed.size());
-  ASSERT_TRUE(unitary.coolingCoil());
-  EXPECT_EQ(dx, unitary.coolingCoil().get());
+TEST_F(ModelFixture, CoilCoolingDX_containingZoneHVACComponent) {
+  {  // ZoneHVACPackagedTerminalAirConditioner
+    Model model;
+
+    CoilCoolingDXCurveFitOperatingMode operatingMode(model);
+    CoilCoolingDXCurveFitPerformance performance(model, operatingMode);
+    CoilCoolingDX dx(model, performance);
+    EXPECT_TRUE(dx.isRemovable());
+    ScheduleCompact availabilitySchedule(model);
+    FanConstantVolume fan(model, availabilitySchedule);
+    CoilHeatingWater heatingCoil(model, availabilitySchedule);
+
+    ZoneHVACPackagedTerminalAirConditioner ptac(model, availabilitySchedule, fan, heatingCoil, dx);
+    EXPECT_EQ(dx, ptac.coolingCoil());
+
+    ASSERT_TRUE(dx.containingZoneHVACComponent());
+    EXPECT_EQ(ptac, dx.containingZoneHVACComponent().get());
+
+    // Shouldn't be able to remove DX since it's contained in a HVAC Component
+    EXPECT_FALSE(dx.isRemovable());
+    auto rmed = dx.remove();
+    EXPECT_EQ(0u, rmed.size());
+    EXPECT_EQ(dx, ptac.coolingCoil());
+  }
+
+  {  // ZoneHVACPackagedTerminalHeatPump
+    Model model;
+
+    CoilCoolingDXCurveFitOperatingMode operatingMode(model);
+    CoilCoolingDXCurveFitPerformance performance(model, operatingMode);
+    CoilCoolingDX dx(model, performance);
+    EXPECT_TRUE(dx.isRemovable());
+    ScheduleCompact availabilitySchedule(model);
+    FanConstantVolume fan(model, availabilitySchedule);
+    CoilHeatingDXSingleSpeed heatingCoil(model);
+    CoilHeatingElectric supplementalHeatingCoil(model, availabilitySchedule);
+
+    ZoneHVACPackagedTerminalHeatPump pthp(model, availabilitySchedule, fan, heatingCoil, dx, supplementalHeatingCoil);
+    EXPECT_EQ(dx, pthp.coolingCoil());
+
+    ASSERT_TRUE(dx.containingZoneHVACComponent());
+    EXPECT_EQ(pthp, dx.containingZoneHVACComponent().get());
+
+    // Shouldn't be able to remove DX since it's contained in a HVAC Component
+    EXPECT_FALSE(dx.isRemovable());
+    auto rmed = dx.remove();
+    EXPECT_EQ(0u, rmed.size());
+    EXPECT_EQ(dx, pthp.coolingCoil());
+  }
 }
 
 TEST_F(ModelFixture, CoilCoolingDX_addToNode) {
-  // Should not be allowed, only meant to be inside a Unitary
-  Model model;
-
-  CoilCoolingDXCurveFitOperatingMode operatingMode(model);
-  CoilCoolingDXCurveFitPerformance performance(model, operatingMode);
-  CoilCoolingDX dx(model, performance);
-
-  AirLoopHVAC a(model);
-  Node supplyOutlet = a.supplyOutletNode();
-  EXPECT_FALSE(dx.addToNode(supplyOutlet));
+  Model m;
+
+  CoilCoolingDXCurveFitOperatingMode operatingMode(m);
+  CoilCoolingDXCurveFitPerformance performance(m, operatingMode);
+  CoilCoolingDX dx(m, performance);
+
+  AirLoopHVAC airLoop(m);
+
+  Node supplyOutletNode = airLoop.supplyOutletNode();
+  EXPECT_FALSE(dx.airLoopHVAC());
+  EXPECT_EQ((unsigned)2, airLoop.supplyComponents().size());
+  EXPECT_TRUE(dx.addToNode(supplyOutletNode));
+  EXPECT_EQ((unsigned)3, airLoop.supplyComponents().size());
+  EXPECT_TRUE(dx.airLoopHVAC());
+
+  Node demandNode = airLoop.zoneSplitter().lastOutletModelObject()->cast<Node>();
+  EXPECT_FALSE(dx.addToNode(demandNode));
+  // 5u: inlet splitter node mixer outlet.
+  EXPECT_EQ((unsigned)5, airLoop.demandComponents().size());
+  EXPECT_EQ((unsigned)3, airLoop.supplyComponents().size());
+  EXPECT_TRUE(dx.airLoopHVAC());
+
+  EXPECT_TRUE(dx.removeFromLoop());
+  EXPECT_EQ((unsigned)2, airLoop.supplyComponents().size());
+  EXPECT_FALSE(dx.airLoopHVAC());
+
+  PlantLoop plantLoop(m);
+  supplyOutletNode = plantLoop.supplyOutletNode();
+  EXPECT_FALSE(dx.addToNode(supplyOutletNode));
+  EXPECT_EQ((unsigned)5, plantLoop.supplyComponents().size());
+
+  Node demandOutletNode = plantLoop.demandOutletNode();
+  EXPECT_FALSE(dx.addToNode(demandOutletNode));
+  EXPECT_EQ((unsigned)5, plantLoop.demandComponents().size());
 }
 
 TEST_F(ModelFixture, CoilCoolingDX_performanceObject) {