Repository: NREL/OpenStudio (language: python)

Issue:
E+ 22.2.0: Wrap Chiller:Electric:ASHRAE205
Enhancement Request
--------------
<!--- Provide a general summary of the feature you would like to see implemented -->

## Detailed Description
<!--- Provide a detailed description of the change or addition you are proposing. Include screenshot/schemas as appropriate -->

## Possible Implementation
<!--- Not mandatory, but if you can, suggest an idea for implementing the feature -->

E+ 22.2.0: Wrap Chiller:Electric:ASHRAE205
Enhancement Request
--------------
<!--- Provide a general summary of the feature you would like to see implemented -->

## Detailed Description
<!--- Provide a detailed description of the change or addition you are proposing. Include screenshot/schemas as appropriate -->

## Possible Implementation
<!--- Not mandatory, but if you can, suggest an idea for implementing the feature -->



Discussion / hints:

Fix patch:
diff --git a/resources/CMakeLists.txt b/resources/CMakeLists.txt
index 10271e10aa8..a7b682aebd0 100644
--- a/resources/CMakeLists.txt
+++ b/resources/CMakeLists.txt
@@ -162,6 +162,7 @@ set(model_resources_src
   model/offset_tests.osm
   model/ParkUnder_Retail_Office_C2.osm
   model/ASHRAECourthouse.osm
+  model/A205ExampleChiller.RS0001.a205.cbor
 )
 
 
diff --git a/resources/energyplus/ProposedEnergy+.idd b/resources/energyplus/ProposedEnergy+.idd
index 00a56b47253..a7aedd13f3f 100644
--- a/resources/energyplus/ProposedEnergy+.idd
+++ b/resources/energyplus/ProposedEnergy+.idd
@@ -42357,6 +42357,127 @@ Boiler:Steam,
        \retaincase
        \default General
 
+Chiller:Electric:ASHRAE205,
+   \min-fields 11
+   \memo This chiller model utilizes ASHRAE Standard 205 compliant representations
+   \memo for chillers (Representation Specification RS0001).
+  A1,  \field Name
+       \type alpha
+       \reference Chillers
+       \required-field
+       \reference-class-name validPlantEquipmentTypes
+       \reference validPlantEquipmentNames
+       \reference-class-name validBranchEquipmentTypes
+       \reference validBranchEquipmentNames
+  A2,  \field Representation File Name
+       \note The name of the ASHRAE205 RS0001 (chiller) representation file
+       \type alpha
+       \retaincase
+       \required-field
+  A3,  \field Performance Interpolation Method
+       \type choice
+       \key Linear
+       \key Cubic
+       \default Linear
+  N1,  \field Rated Capacity
+       \note Not yet implemented / reserved for future use. Full load capacity at AHRI 550/590 test conditions.
+       \note Used to scale representation data.
+       \type real
+       \units W
+       \minimum> 0.0
+       \autosizable
+       \default autosize
+  N2,  \field Sizing Factor
+       \note Multiplies the autosized flow rates.
+       \type real
+       \minimum> 0.0
+       \default 1.0
+  A4 , \field Ambient Temperature Indicator
+       \note Used to determine standby losses
+       \required-field
+       \type choice
+       \key Schedule
+       \key Zone
+       \key Outdoors
+  A5 , \field Ambient Temperature Schedule Name
+       \type object-list
+       \object-list ScheduleNames
+  A6, \field Ambient Temperature Zone Name
+       \note Any energy imbalance on the chiller results in heat added to this zone.
+       \type object-list
+       \object-list ZoneNames
+  A7, \field Ambient Temperature Outdoor Air Node Name
+       \type node
+       \note required for Ambient Temperature Indicator=Outdoors
+  A8,  \field Chilled Water Inlet Node Name
+       \type node
+       \required-field
+  A9,  \field Chilled Water Outlet Node Name
+       \type node
+       \required-field
+  A10, \field Chilled Water Maximum Requested Flow Rate
+       \type real
+       \units m3/s
+       \minimum> 0
+       \autosizable
+       \ip-units gal/min
+       \default autosize
+  A11, \field Condenser Inlet Node Name
+       \type node
+  A12, \field Condenser Outlet Node Name
+       \type node
+  A13, \field Condenser Maximum Requested Flow Rate
+       \type real
+       \units m3/s
+       \minimum> 0
+       \autosizable
+       \ip-units gal/min
+       \default autosize
+  A14, \field Chiller Flow Mode
+       \note Select operating mode for fluid flow through the chiller. "NotModulated" is for
+       \note either variable or constant pumping with flow controlled by the external plant system.
+       \note "ConstantFlow" is for constant pumping with flow controlled by chiller to operate at
+       \note full design flow rate. "LeavingSetpointModulated" is for variable pumping with flow
+       \note controlled by chiller to vary flow to target a leaving temperature setpoint.
+       \type choice
+       \key ConstantFlow
+       \key LeavingSetpointModulated
+       \key NotModulated
+       \default NotModulated
+  A15, \field Oil Cooler Inlet Node Name
+       \note Use if the oil cooler uses an external cooling loop, otherwise the oil cooler will add
+       \note heat to the ambient conditions (i.e., it is air cooled).
+       \type node
+  A16, \field Oil Cooler Outlet Node Name
+       \type node
+  A17, \field Oil Cooler Design Flow Rate
+       \type real
+       \units m3/s
+       \minimum> 0
+       \ip-units gal/min
+  A18, \field Auxiliary Inlet Node Name
+       \note Use if the auxiliary components of the chiller use an external cooling loop, otherwise
+       \note the auxiliary components will add heat to the ambient conditions (i.e., they are air cooled).
+       \type node
+  A19, \field Auxiliary Outlet Node Name
+       \type node
+  A20, \field Auxiliary Cooling Design Flow Rate
+       \type real
+       \units m3/s
+       \minimum> 0
+       \ip-units gal/min
+  A21, \field Heat Recovery Inlet Node Name
+       \note Not yet implemented / reserved for future use. Heat recovery is not yet within scope of ASHRAE Stanard 205.
+       \type node
+  A21, \field Heat Recovery Outlet Node Name
+       \note Not yet implemented / reserved for future use. Heat recovery is not yet within scope of ASHRAE Stanard 205.
+       \type node
+  A23; \field End-Use Subcategory
+       \note Any text may be used here to categorize the end-uses in the ABUPS End Uses by Subcategory table.
+       \type alpha
+       \retaincase
+       \default General
+
 Chiller:Electric:EIR,
        \min-fields 23
        \memo This chiller model is the empirical model from the DOE-2 building Energy
diff --git a/resources/model/A205ExampleChiller.RS0001.a205.cbor b/resources/model/A205ExampleChiller.RS0001.a205.cbor
new file mode 100644
index 00000000000..7f8e55453f6
Binary files /dev/null and b/resources/model/A205ExampleChiller.RS0001.a205.cbor differ
diff --git a/resources/model/OpenStudio.idd b/resources/model/OpenStudio.idd
index 0629c730b79..e10cb6c0243 100644
--- a/resources/model/OpenStudio.idd
+++ b/resources/model/OpenStudio.idd
@@ -13813,6 +13813,137 @@ OS:Chiller:Electric:ReformulatedEIR,
        \retaincase
        \default General
 
+OS:Chiller:Electric:ASHRAE205,
+   \min-fields 12
+   \memo This chiller model utilizes ASHRAE Standard 205 compliant representations
+   \memo for chillers (Representation Specification RS0001).
+  A1,  \field Handle
+       \type handle
+       \required-field
+  A2,  \field Name
+       \type alpha
+       \reference Chillers
+       \required-field
+       \reference ConnectionObject
+  A3,  \field Representation File Name
+       \note The name of the ASHRAE205 RS0001 (chiller) representation file
+       \type object-list
+       \object-list ExternalFileNames
+       \required-field
+  A4,  \field Performance Interpolation Method
+       \type choice
+       \key Linear
+       \key Cubic
+       \required-field
+  N1,  \field Rated Capacity
+       \note Not yet implemented / reserved for future use. Full load capacity at AHRI 550/590 test conditions.
+       \note Used to scale representation data.
+       \type real
+       \units W
+       \minimum> 0.0
+       \autosizable
+       \required-field
+  N2,  \field Sizing Factor
+       \note Multiplies the autosized flow rates.
+       \type real
+       \minimum> 0.0
+       \required-field
+  A5 , \field Ambient Temperature Indicator
+       \note Used to determine standby losses
+       \required-field
+       \type choice
+       \key Schedule
+       \key Zone
+       \key Outdoors
+  A6 , \field Ambient Temperature Schedule Name
+       \type object-list
+       \object-list ScheduleNames
+  A7, \field Ambient Temperature Zone Name
+       \note Any energy imbalance on the chiller results in heat added to this zone.
+       \type object-list
+       \object-list ThermalZoneNames
+  A8, \field Ambient Temperature Outdoor Air Node Name
+       \type alpha
+       \note required for Ambient Temperature Indicator=Outdoors
+  A9,  \field Chilled Water Inlet Node Name
+       \type object-list
+       \object-list ConnectionNames
+       \required-field
+  A10, \field Chilled Water Outlet Node Name
+       \type object-list
+       \object-list ConnectionNames
+       \required-field
+  A11, \field Chilled Water Maximum Requested Flow Rate
+       \type real
+       \units m3/s
+       \minimum> 0
+       \autosizable
+       \ip-units gal/min
+       \required-field
+  A12, \field Condenser Inlet Node Name
+       \type object-list
+       \object-list ConnectionNames
+  A13, \field Condenser Outlet Node Name
+       \type object-list
+       \object-list ConnectionNames
+  A14, \field Condenser Maximum Requested Flow Rate
+       \type real
+       \units m3/s
+       \minimum> 0
+       \autosizable
+       \ip-units gal/min
+       \required-field
+  A15, \field Chiller Flow Mode
+       \note Select operating mode for fluid flow through the chiller. "NotModulated" is for
+       \note either variable or constant pumping with flow controlled by the external plant system.
+       \note "ConstantFlow" is for constant pumping with flow controlled by chiller to operate at
+       \note full design flow rate. "LeavingSetpointModulated" is for variable pumping with flow
+       \note controlled by chiller to vary flow to target a leaving temperature setpoint.
+       \type choice
+       \key ConstantFlow
+       \key LeavingSetpointModulated
+       \key NotModulated
+       \required-field
+  A16, \field Oil Cooler Inlet Node Name
+       \note Use if the oil cooler uses an external cooling loop, otherwise the oil cooler will add
+       \note heat to the ambient conditions (i.e., it is air cooled).
+       \type object-list
+       \object-list ConnectionNames
+  A17, \field Oil Cooler Outlet Node Name
+       \type object-list
+       \object-list ConnectionNames
+  A18, \field Oil Cooler Design Flow Rate
+       \type real
+       \units m3/s
+       \minimum> 0
+       \ip-units gal/min
+  A19, \field Auxiliary Inlet Node Name
+       \note Use if the auxiliary components of the chiller use an external cooling loop, otherwise
+       \note the auxiliary components will add heat to the ambient conditions (i.e., they are air cooled).
+       \type object-list
+       \object-list ConnectionNames
+  A20, \field Auxiliary Outlet Node Name
+       \type object-list
+       \object-list ConnectionNames
+  A21, \field Auxiliary Cooling Design Flow Rate
+       \type real
+       \units m3/s
+       \minimum> 0
+       \ip-units gal/min
+  A22, \field Heat Recovery Inlet Node Name
+       \note Not yet implemented / reserved for future use. Heat recovery is not yet within scope of ASHRAE Stanard 205.
+       \type object-list
+       \object-list ConnectionNames
+  A22, \field Heat Recovery Outlet Node Name
+       \note Not yet implemented / reserved for future use. Heat recovery is not yet within scope of ASHRAE Stanard 205.
+       \type object-list
+       \object-list ConnectionNames
+  A24; \field End-Use Subcategory
+       \note Any text may be used here to categorize the end-uses in the ABUPS End Uses by Subcategory table.
+       \type alpha
+       \retaincase
+       \default General
+
 OS:CentralHeatPumpSystem,
   A1,  \field Handle
        \type handle
diff --git a/src/energyplus/CMakeLists.txt b/src/energyplus/CMakeLists.txt
index 39f2dd9788d..76eb248ddc2 100644
--- a/src/energyplus/CMakeLists.txt
+++ b/src/energyplus/CMakeLists.txt
@@ -62,6 +62,7 @@ set(${target_name}_src
   ForwardTranslator/ForwardTranslateCFactorUndergroundWallConstruction.cpp
   ForwardTranslator/ForwardTranslateChillerAbsorption.cpp
   ForwardTranslator/ForwardTranslateChillerAbsorptionIndirect.cpp
+  ForwardTranslator/ForwardTranslateChillerElectricASHRAE205.cpp
   ForwardTranslator/ForwardTranslateChillerElectricEIR.cpp
   ForwardTranslator/ForwardTranslateChillerElectricReformulatedEIR.cpp
   ForwardTranslator/ForwardTranslateChillerHeaterPerformanceElectricEIR.cpp
@@ -457,6 +458,7 @@ set(${target_name}_src
   ReverseTranslator/ReverseTranslateBuilding.cpp
   ReverseTranslator/ReverseTranslateBuildingSurfaceDetailed.cpp
   ReverseTranslator/ReverseTranslateControllerOutdoorAir.cpp
+  ReverseTranslator/ReverseTranslateChillerElectricASHRAE205.cpp
   ReverseTranslator/ReverseTranslateCoilCoolingDX.cpp
   ReverseTranslator/ReverseTranslateCoilCoolingDXCurveFitPerformance.cpp
   ReverseTranslator/ReverseTranslateCoilCoolingDXCurveFitOperatingMode.cpp
@@ -659,6 +661,7 @@ set(${target_name}_test_src
   Test/AvailabilityManagerNightCycle_GTest.cpp
   Test/AvailabilityManagerHybridVentilation_GTest.cpp
   Test/Building_GTest.cpp
+  Test/ChillerElectricASHRAE205_GTest.cpp
   Test/CentralHeatPumpSystem_GTest.cpp
   Test/CoilCoolingDX_GTest.cpp
   Test/CoilCoolingDXCurveFitPerformance_GTest.cpp
diff --git a/src/energyplus/ForwardTranslator.cpp b/src/energyplus/ForwardTranslator.cpp
index 3c4855de9b0..bdbce99d3bb 100644
--- a/src/energyplus/ForwardTranslator.cpp
+++ b/src/energyplus/ForwardTranslator.cpp
@@ -937,6 +937,11 @@ namespace energyplus {
         retVal = translateChillerAbsorptionIndirect(mo);
         break;
       }
+      case openstudio::IddObjectType::OS_Chiller_Electric_ASHRAE205: {
+        auto mo = modelObject.cast<ChillerElectricASHRAE205>();
+        retVal = translateChillerElectricASHRAE205(mo);
+        break;
+      }
       case openstudio::IddObjectType::OS_Chiller_Electric_EIR: {
         model::ChillerElectricEIR chiller = modelObject.cast<ChillerElectricEIR>();
         retVal = translateChillerElectricEIR(chiller);
diff --git a/src/energyplus/ForwardTranslator.hpp b/src/energyplus/ForwardTranslator.hpp
index 0ad5dc5302f..9e574f5c240 100644
--- a/src/energyplus/ForwardTranslator.hpp
+++ b/src/energyplus/ForwardTranslator.hpp
@@ -121,6 +121,7 @@ namespace model {
   class CFactorUndergroundWallConstruction;
   class ChillerAbsorption;
   class ChillerAbsorptionIndirect;
+  class ChillerElectricASHRAE205;
   class ChillerElectricEIR;
   class ChillerElectricReformulatedEIR;
   class ChillerHeaterPerformanceElectricEIR;
@@ -747,6 +748,8 @@ namespace energyplus {
 
     boost::optional<IdfObject> translateChillerAbsorptionIndirect(model::ChillerAbsorptionIndirect& modelObject);
 
+    boost::optional<IdfObject> translateChillerElectricASHRAE205(model::ChillerElectricASHRAE205& modelObject);
+
     boost::optional<IdfObject> translateChillerElectricEIR(model::ChillerElectricEIR& modelObject);
 
     boost::optional<IdfObject> translateChillerElectricReformulatedEIR(model::ChillerElectricReformulatedEIR& modelObject);
diff --git a/src/energyplus/ForwardTranslator/ForwardTranslateChillerElectricASHRAE205.cpp b/src/energyplus/ForwardTranslator/ForwardTranslateChillerElectricASHRAE205.cpp
new file mode 100644
index 00000000000..aedd4562165
--- /dev/null
+++ b/src/energyplus/ForwardTranslator/ForwardTranslateChillerElectricASHRAE205.cpp
@@ -0,0 +1,218 @@
+/***********************************************************************************************************************
+*  OpenStudio(R), Copyright (c) 2008-2022, 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/ChillerElectricASHRAE205.hpp"
+
+#include "../../model/Schedule.hpp"
+#include "../../model/ExternalFile.hpp"
+#include "../../model/ThermalZone.hpp"
+
+#include "../../model/Node.hpp"
+#include "../../model/Node_Impl.hpp"
+
+#include <utilities/idd/Chiller_Electric_ASHRAE205_FieldEnums.hxx>
+// #include "../../utilities/idd/IddEnums.hpp"
+#include <utilities/idd/IddEnums.hxx>
+
+using namespace openstudio::model;
+
+namespace openstudio {
+
+namespace energyplus {
+
+  boost::optional<IdfObject> ForwardTranslator::translateChillerElectricASHRAE205(model::ChillerElectricASHRAE205& modelObject) {
+
+    path filePath = modelObject.representationFile().filePath();
+    if (!openstudio::filesystem::exists(filePath)) {
+      LOG(Warn, modelObject.briefDescription() << "will not be translated, cannot find the representation file '" << filePath << "'");
+      return boost::none;
+    }
+
+    // make the path correct for this system
+    filePath = openstudio::filesystem::system_complete(filePath);
+
+    if (!modelObject.chilledWaterLoop()) {
+      LOG(Warn, modelObject.briefDescription() << "will not be translated, it not on a Chilled Water Loop.");
+      return boost::none;
+    }
+
+    // Instantiate an IdfObject of the class to store the values
+    IdfObject idfObject = createRegisterAndNameIdfObject(openstudio::IddObjectType::Chiller_Electric_ASHRAE205, modelObject);
+
+    // Representation File Name: Required String
+    idfObject.setString(Chiller_Electric_ASHRAE205Fields::RepresentationFileName, openstudio::toString(filePath));
+
+    // Performance Interpolation Method
+    std::string performanceInterpolationMethod = modelObject.performanceInterpolationMethod();
+    idfObject.setString(Chiller_Electric_ASHRAE205Fields::PerformanceInterpolationMethod, performanceInterpolationMethod);
+
+    if (modelObject.isRatedCapacityAutosized()) {
+      idfObject.setString(Chiller_Electric_ASHRAE205Fields::RatedCapacity, "Autosize");
+    } else {
+      idfObject.setDouble(Chiller_Electric_ASHRAE205Fields::RatedCapacity, modelObject.ratedCapacity().get());
+    }
+
+    // Sizing Factor: Optional Double
+    idfObject.setDouble(Chiller_Electric_ASHRAE205Fields::SizingFactor, modelObject.sizingFactor());
+
+    // Ambient Temperature Indicator: Required String
+    std::string ambientTemperatureIndicator = modelObject.ambientTemperatureIndicator();
+    bool ambientTempOk = false;
+
+    if (openstudio::istringEqual("Schedule", ambientTemperatureIndicator)) {
+      // Ambient Temperature Schedule Name: Optional Object
+      if (boost::optional<Schedule> _ambientTemperatureSchedule = modelObject.ambientTemperatureSchedule()) {
+        if (boost::optional<IdfObject> _owo = translateAndMapModelObject(_ambientTemperatureSchedule.get())) {
+          idfObject.setString(Chiller_Electric_ASHRAE205Fields::AmbientTemperatureScheduleName, _owo->nameString());
+          ambientTempOk = true;
+        }
+      }
+    } else if (openstudio::istringEqual("Zone", ambientTemperatureIndicator)) {
+      // Ambient Temperature Zone Name: Optional Object
+      if (boost::optional<ThermalZone> _ambientTemperatureZone = modelObject.ambientTemperatureZone()) {
+        if (boost::optional<IdfObject> _owo = translateAndMapModelObject(_ambientTemperatureZone.get())) {
+          idfObject.setString(Chiller_Electric_ASHRAE205Fields::AmbientTemperatureZoneName, _owo->nameString());
+          ambientTempOk = true;
+        }
+      }
+    } else if (openstudio::istringEqual("Outdoors", ambientTemperatureIndicator)) {
+      ambientTempOk = true;
+    }
+    if (!ambientTempOk) {
+      LOG(Warn, "For " << modelObject.briefDescription() << " the Ambient Temperature Indicator is " << ambientTemperatureIndicator
+                       << " but the required objects don't match. Falling back to 'Outdoors'");
+      ambientTemperatureIndicator = "Outdoors";
+    }
+
+    idfObject.setString(Chiller_Electric_ASHRAE205Fields::AmbientTemperatureIndicator, ambientTemperatureIndicator);
+
+    if (openstudio::istringEqual("Outdoors", ambientTemperatureIndicator)) {
+      std::string oaNodeName = modelObject.nameString() + " OA Node";
+      if (boost::optional<std::string> s_ = modelObject.ambientTemperatureOutdoorAirNodeName()) {
+        oaNodeName = s_.get();
+      }
+
+      idfObject.setString(Chiller_Electric_ASHRAE205Fields::AmbientTemperatureOutdoorAirNodeName, oaNodeName);
+
+      IdfObject _oaNodeList(openstudio::IddObjectType::OutdoorAir_NodeList);
+      _oaNodeList.setString(0, oaNodeName);
+      m_idfObjects.push_back(_oaNodeList);
+    }
+
+    // Chilled Water Node Names: Required Nodes
+    if (auto node_ = modelObject.chilledWaterInletNode()) {
+      idfObject.setString(Chiller_Electric_ASHRAE205Fields::ChilledWaterInletNodeName, node_->nameString());
+    }
+
+    if (auto node_ = modelObject.chilledWaterOutletNode()) {
+      idfObject.setString(Chiller_Electric_ASHRAE205Fields::ChilledWaterOutletNodeName, node_->nameString());
+    }
+
+    // Optional Nodes
+
+    // Condenser
+    if (auto node_ = modelObject.condenserInletNode()) {
+      idfObject.setString(Chiller_Electric_ASHRAE205Fields::CondenserInletNodeName, node_->nameString());
+    }
+
+    if (auto node_ = modelObject.condenserOutletNode()) {
+      idfObject.setString(Chiller_Electric_ASHRAE205Fields::CondenserOutletNodeName, node_->nameString());
+    }
+
+    // Heat Recovery
+    if (auto node_ = modelObject.heatRecoveryInletNode()) {
+      idfObject.setString(Chiller_Electric_ASHRAE205Fields::HeatRecoveryInletNodeName, node_->nameString());
+    }
+
+    if (auto node_ = modelObject.heatRecoveryOutletNode()) {
+      idfObject.setString(Chiller_Electric_ASHRAE205Fields::HeatRecoveryOutletNodeName, node_->nameString());
+    }
+
+    // Oil Cooler
+    if (auto node_ = modelObject.oilCoolerInletNode()) {
+      idfObject.setString(Chiller_Electric_ASHRAE205Fields::OilCoolerInletNodeName, node_->nameString());
+    }
+
+    if (auto node_ = modelObject.oilCoolerOutletNode()) {
+      idfObject.setString(Chiller_Electric_ASHRAE205Fields::OilCoolerOutletNodeName, node_->nameString());
+    }
+
+    // Auxiliary
+    if (auto node_ = modelObject.auxiliaryInletNode()) {
+      idfObject.setString(Chiller_Electric_ASHRAE205Fields::AuxiliaryInletNodeName, node_->nameString());
+    }
+
+    if (auto node_ = modelObject.auxiliaryOutletNode()) {
+      idfObject.setString(Chiller_Electric_ASHRAE205Fields::AuxiliaryOutletNodeName, node_->nameString());
+    }
+
+    if (modelObject.isChilledWaterMaximumRequestedFlowRateAutosized()) {
+      idfObject.setString(Chiller_Electric_ASHRAE205Fields::ChilledWaterMaximumRequestedFlowRate, "Autosize");
+    } else {
+      // ChilledWater Maximum Requested Flow Rate: boost::optional<double>
+      if (boost::optional<double> _chilledWaterMaximumRequestedFlowRate = modelObject.chilledWaterMaximumRequestedFlowRate()) {
+        idfObject.setDouble(Chiller_Electric_ASHRAE205Fields::ChilledWaterMaximumRequestedFlowRate, _chilledWaterMaximumRequestedFlowRate.get());
+      }
+    }
+
+    if (modelObject.isCondenserMaximumRequestedFlowRateAutosized()) {
+      idfObject.setString(Chiller_Electric_ASHRAE205Fields::CondenserMaximumRequestedFlowRate, "Autosize");
+    } else {
+      // Condenser Maximum Requested Flow Rate: boost::optional<double>
+      if (boost::optional<double> _condenserMaximumRequestedFlowRate = modelObject.condenserMaximumRequestedFlowRate()) {
+        idfObject.setDouble(Chiller_Electric_ASHRAE205Fields::CondenserMaximumRequestedFlowRate, _condenserMaximumRequestedFlowRate.get());
+      }
+    }
+
+    // Chiller Flow Mode: Optional String
+    idfObject.setString(Chiller_Electric_ASHRAE205Fields::ChillerFlowMode, modelObject.chillerFlowMode());
+
+    // Oil Cooler Design Flow Rate: boost::optional<double>
+    if (boost::optional<double> _oilCoolerDesignFlowRate = modelObject.oilCoolerDesignFlowRate()) {
+      idfObject.setDouble(Chiller_Electric_ASHRAE205Fields::OilCoolerDesignFlowRate, _oilCoolerDesignFlowRate.get());
+    }
+
+    // Auxiliary Cooling Design Flow Rate: boost::optional<double>
+    if (boost::optional<double> _auxiliaryCoolingDesignFlowRate = modelObject.auxiliaryCoolingDesignFlowRate()) {
+      idfObject.setDouble(Chiller_Electric_ASHRAE205Fields::AuxiliaryCoolingDesignFlowRate, _auxiliaryCoolingDesignFlowRate.get());
+    }
+
+    // End-Use Subcategory: Optional String
+    if (!modelObject.isEndUseSubcategoryDefaulted()) {
+      idfObject.setString(Chiller_Electric_ASHRAE205Fields::EndUseSubcategory, modelObject.endUseSubcategory());
+    }
+
+    return idfObject;
+  }  // End of translate function
+
+}  // end namespace energyplus
+}  // end namespace openstudio
diff --git a/src/energyplus/ForwardTranslator/ForwardTranslatePlantEquipmentOperationSchemes.cpp b/src/energyplus/ForwardTranslator/ForwardTranslatePlantEquipmentOperationSchemes.cpp
index 92fbac64159..7852a789cd2 100644
--- a/src/energyplus/ForwardTranslator/ForwardTranslatePlantEquipmentOperationSchemes.cpp
+++ b/src/energyplus/ForwardTranslator/ForwardTranslatePlantEquipmentOperationSchemes.cpp
@@ -43,6 +43,8 @@
 #include "../../model/CentralHeatPumpSystemModule.hpp"
 #include "../../model/ChillerHeaterPerformanceElectricEIR.hpp"
 
+#include "../../model/ChillerElectricASHRAE205.hpp"
+#include "../../model/ChillerElectricASHRAE205_Impl.hpp"
 #include "../../model/ChillerElectricEIR.hpp"
 #include "../../model/ChillerElectricEIR_Impl.hpp"
 #include "../../model/ChillerElectricReformulatedEIR.hpp"
@@ -204,8 +206,14 @@ namespace energyplus {
         // Probably check if all modules have a ChillerHeaterPerformanceComponent
         // that has a flow rate hardsized, and multiple by the number of performance comp
         // Better to add a method to centralheatpumpsystem, for eg "totalDesignFlowRate"
-        // Problem is that you need to know which loop is requesting this since there are three
-        // "Design XXX Water Flow Rate" (XXX= Chilled Water, Condenser Water, or Hot Water)
+        // Problem is that you need to know which loop is requesting this since there are two supply loops with
+        // "Design XXX Water Flow Rate" (XXX= Chilled Water, or Hot Water)
+        break;
+      }
+
+      case openstudio::IddObjectType::OS_Chiller_Electric_ASHRAE205: {
+        auto chiller = component.cast<ChillerElectricASHRAE205>();
+        result = chiller.chilledWaterMaximumRequestedFlowRate();
         break;
       }
       case openstudio::IddObjectType::OS_Chiller_Electric_EIR: {
@@ -483,6 +491,9 @@ namespace energyplus {
         // As a result, this is handled in coolingComponents() and heatingComponents() directly
         return ComponentType::NONE;
       }
+      case openstudio::IddObjectType::OS_Chiller_Electric_ASHRAE205: {
+        return ComponentType::COOLING;
+      }
       case openstudio::IddObjectType::OS_Chiller_Electric_EIR: {
         return ComponentType::COOLING;
       }
diff --git a/src/energyplus/ForwardTranslator/ForwardTranslatePlantLoop.cpp b/src/energyplus/ForwardTranslator/ForwardTranslatePlantLoop.cpp
index 9712c31f76d..e2cd3bb2ee5 100644
--- a/src/energyplus/ForwardTranslator/ForwardTranslatePlantLoop.cpp
+++ b/src/energyplus/ForwardTranslator/ForwardTranslatePlantLoop.cpp
@@ -54,6 +54,8 @@
 #include "../../model/BoilerHotWater_Impl.hpp"
 #include "../../model/CentralHeatPumpSystem.hpp"
 #include "../../model/CentralHeatPumpSystem_Impl.hpp"
+#include "../../model/ChillerElectricASHRAE205.hpp"
+#include "../../model/ChillerElectricASHRAE205_Impl.hpp"
 #include "../../model/ChillerElectricEIR.hpp"
 #include "../../model/ChillerElectricEIR_Impl.hpp"
 #include "../../model/ChillerElectricReformulatedEIR.hpp"
@@ -152,6 +154,8 @@ namespace energyplus {
     if (modelObjects.size() > 0) {
       int i = 0;
 
+      boost::optional<Node> prevNode_;
+
       for (auto& modelObject : modelObjects) {
         boost::optional<Node> inletNode;
         boost::optional<Node> outletNode;
@@ -167,6 +171,7 @@ namespace energyplus {
 
         if (modelObject.optionalCast<Node>()) {
           // Skip nodes we don't want them showing up on branches
+          prevNode_ = modelObject.cast<Node>();
           continue;
         }
 
@@ -334,21 +339,45 @@ namespace energyplus {
             auto sourceLoop = central_hp->sourcePlantLoop();
 
             // supply = cooling Loop
-            if (loop.handle() == coolingLoop->handle()) {
+            if (coolingLoop && loop.handle() == coolingLoop->handle()) {
               inletNode = waterToWaterComponent->supplyInletModelObject()->optionalCast<Node>();
               outletNode = waterToWaterComponent->supplyOutletModelObject()->optionalCast<Node>();
 
               // tertiary = heating loop
-            } else if (loop.handle() == heatingLoop->handle()) {
+            } else if (heatingLoop && loop.handle() == heatingLoop->handle()) {
               inletNode = waterToWaterComponent->tertiaryInletModelObject()->optionalCast<Node>();
               outletNode = waterToWaterComponent->tertiaryOutletModelObject()->optionalCast<Node>();
 
               // demand = source loop
-            } else if (loop.handle() == sourceLoop->handle()) {
+            } else if (sourceLoop && loop.handle() == sourceLoop->handle()) {
               inletNode = waterToWaterComponent->demandInletModelObject()->optionalCast<Node>();
               outletNode = waterToWaterComponent->demandOutletModelObject()->optionalCast<Node>();
             }
 
+          } else if (auto ch = modelObject.optionalCast<ChillerElectricASHRAE205>()) {
+            // This one has **FIVE** loops and can be potentially several time on the same loop (demand side, eg: Condenser + Oil Cooler + Auxiliary)
+
+            // Doing this: `if (ch->chilledWaterLoop() && loop.handle() == ch->chilledWaterLoop()->handle())` isn't enough because we could be on the
+            // same loop, so we rely on prevNode_ instead
+            OS_ASSERT(prevNode_);
+
+            if (ch->chilledWaterInletNode() && ch->chilledWaterInletNode()->handle() == prevNode_->handle()) {
+              inletNode = ch->chilledWaterInletNode();
+              outletNode = ch->chilledWaterOutletNode();
+            } else if (ch->condenserInletNode() && ch->condenserInletNode()->handle() == prevNode_->handle()) {
+              inletNode = ch->condenserInletNode();
+              outletNode = ch->condenserOutletNode();
+            } else if (ch->heatRecoveryInletNode() && ch->heatRecoveryInletNode()->handle() == prevNode_->handle()) {
+              inletNode = ch->heatRecoveryInletNode();
+              outletNode = ch->heatRecoveryOutletNode();
+            } else if (ch->oilCoolerInletNode() && ch->oilCoolerInletNode()->handle() == prevNode_->handle()) {
+              inletNode = ch->oilCoolerInletNode();
+              outletNode = ch->oilCoolerOutletNode();
+            } else if (ch->auxiliaryInletNode() && ch->auxiliaryInletNode()->handle() == prevNode_->handle()) {
+              inletNode = ch->auxiliaryInletNode();
+              outletNode = ch->auxiliaryOutletNode();
+            }
+
             // Regular case
           } else if (isSupplyBranch) {
             inletNode = waterToWaterComponent->supplyInletModelObject()->optionalCast<Node>();
diff --git a/src/energyplus/ForwardTranslator/ForwardTranslateSizingPlant.cpp b/src/energyplus/ForwardTranslator/ForwardTranslateSizingPlant.cpp
index 88c8399b6bf..2700fe9de6d 100644
--- a/src/energyplus/ForwardTranslator/ForwardTranslateSizingPlant.cpp
+++ b/src/energyplus/ForwardTranslator/ForwardTranslateSizingPlant.cpp
@@ -68,6 +68,9 @@ namespace energyplus {
       case openstudio::IddObjectType::OS_DistrictHeating: {
         return PlantSizingType::HOTWATER;
       }
+      case openstudio::IddObjectType::OS_Chiller_Electric_ASHRAE205: {
+        return PlantSizingType::CHILLEDWATER;
+      }
       case openstudio::IddObjectType::OS_Chiller_Electric_EIR: {
         return PlantSizingType::CHILLEDWATER;
       }
diff --git a/src/energyplus/ReverseTranslator.cpp b/src/energyplus/ReverseTranslator.cpp
index 9d3ef0e8997..45028fa46de 100644
--- a/src/energyplus/ReverseTranslator.cpp
+++ b/src/energyplus/ReverseTranslator.cpp
@@ -338,6 +338,10 @@ namespace energyplus {
         modelObject = translateBuilding(workspaceObject);
         break;
       }
+      case openstudio::IddObjectType::Chiller_Electric_ASHRAE205: {
+        modelObject = translateChillerElectricASHRAE205(workspaceObject);
+        break;
+      }
       case openstudio::IddObjectType::Coil_Heating_Fuel: {
         //modelObject = translateCoilHeatingGas(workspaceObject );
         break;
diff --git a/src/energyplus/ReverseTranslator.hpp b/src/energyplus/ReverseTranslator.hpp
index 73bbda6606e..24cdf0f6b64 100644
--- a/src/energyplus/ReverseTranslator.hpp
+++ b/src/energyplus/ReverseTranslator.hpp
@@ -95,6 +95,8 @@ namespace energyplus {
 
     boost::optional<model::ModelObject> translateBuildingSurfaceDetailed(const WorkspaceObject& workspaceObject);
 
+    boost::optional<model::ModelObject> translateChillerElectricASHRAE205(const WorkspaceObject& workspaceObject);
+
     boost::optional<model::ModelObject> translateControllerOutdoorAir(const WorkspaceObject& workspaceObject);
 
     boost::optional<model::ModelObject> translateCoilHeatingGas(const WorkspaceObject& workspaceObject);
diff --git a/src/energyplus/ReverseTranslator/ReverseTranslateChillerElectricASHRAE205.cpp b/src/energyplus/ReverseTranslator/ReverseTranslateChillerElectricASHRAE205.cpp
new file mode 100644
index 00000000000..cc170740031
--- /dev/null
+++ b/src/energyplus/ReverseTranslator/ReverseTranslateChillerElectricASHRAE205.cpp
@@ -0,0 +1,183 @@
+/***********************************************************************************************************************
+*  OpenStudio(R), Copyright (c) 2008-2022, 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 "../ReverseTranslator.hpp"
+
+#include "../../model/ChillerElectricASHRAE205.hpp"
+
+#include "../../model/Schedule.hpp"
+#include "../../model/Schedule_Impl.hpp"
+
+#include "../../model/ThermalZone.hpp"
+#include "../../model/ThermalZone_Impl.hpp"
+#include "../../model/Space.hpp"
+#include "../../model/Space_Impl.hpp"
+
+#include "../../model/ExternalFile.hpp"
+
+#include <utilities/idd/Chiller_Electric_ASHRAE205_FieldEnums.hxx>
+#include <utilities/idd/IddEnums.hxx>
+
+using namespace openstudio::model;
+
+namespace openstudio {
+
+namespace energyplus {
+
+  boost::optional<ModelObject> ReverseTranslator::translateChillerElectricASHRAE205(const WorkspaceObject& workspaceObject) {
+
+    std::string fileName = workspaceObject.getString(Chiller_Electric_ASHRAE205Fields::RepresentationFileName).get();
+    boost::optional<ExternalFile> extfile = ExternalFile::getExternalFile(m_model, fileName);
+
+    if (!extfile) {
+      LOG(Error, "Could not translate " << workspaceObject.briefDescription() << ", cannot find Representation File \"" << fileName << "\"");
+      return boost::none;
+    }
+
+    boost::optional<std::string> ambientTemperatureIndicator_ =
+      workspaceObject.getString(Chiller_Electric_ASHRAE205Fields::AmbientTemperatureIndicator);
+    if (!ambientTemperatureIndicator_) {
+      LOG(Error, "For " << workspaceObject.briefDescription() << ", cannot find required property 'Ambient Temperature Indicator'");
+      return boost::none;
+    }
+
+    openstudio::model::ChillerElectricASHRAE205 modelObject(extfile.get());
+
+    // Name
+    if (boost::optional<std::string> _name = workspaceObject.name()) {
+      modelObject.setName(_name.get());
+    }
+
+    // Performance Interpolation Method: Optional String
+    if (boost::optional<std::string> _performanceInterpolationMethod =
+          workspaceObject.getString(Chiller_Electric_ASHRAE205Fields::PerformanceInterpolationMethod)) {
+      modelObject.setPerformanceInterpolationMethod(_performanceInterpolationMethod.get());
+    }
+
+    // Rated Capacity: Optional Double
+    if (boost::optional<double> _ratedCapacity = workspaceObject.getDouble(Chiller_Electric_ASHRAE205Fields::RatedCapacity)) {
+      modelObject.setRatedCapacity(_ratedCapacity.get());
+    }
+
+    // Sizing Factor: Optional Double
+    if (boost::optional<double> _sizingFactor = workspaceObject.getDouble(Chiller_Electric_ASHRAE205Fields::SizingFactor)) {
+      modelObject.setSizingFactor(_sizingFactor.get());
+    }
+
+    // Ambient Temperature Indicator: Required String
+    if (openstudio::istringEqual("Schedule", ambientTemperatureIndicator_.get())) {
+
+      // Ambient Temperature Schedule Name: Optional Object
+      if (auto wo_sch_ = workspaceObject.getTarget(Chiller_Electric_ASHRAE205Fields::AmbientTemperatureScheduleName)) {
+        if (auto mo_sch_ = translateAndMapWorkspaceObject(wo_sch_.get())) {
+          if (boost::optional<Schedule> sch_ = mo_sch_->optionalCast<Schedule>()) {
+            modelObject.setAmbientTemperatureSchedule(sch_.get());
+          } else {
+            LOG(Warn, workspaceObject.briefDescription() << " has a wrong type for 'Ambient Temperature Schedule Name'");
+          }
+        }
+      } else {
+        LOG(Warn, workspaceObject.briefDescription()
+                    << " has an Ambient Temperature Indicator of type 'Schedule', but no Schedule assigned. Falling back to 'Outdoors'");
+      }
+    } else if (openstudio::istringEqual("Zone", ambientTemperatureIndicator_.get())) {
+
+      // Ambient Temperature Zone Name: Optional Object
+      if (auto wo_z_ = workspaceObject.getTarget(Chiller_Electric_ASHRAE205Fields::AmbientTemperatureZoneName)) {
+        if (auto mo_ = translateAndMapWorkspaceObject(wo_z_.get())) {
+          // Zone is translated, and a Space is returned instead
+          if (boost::optional<Space> space_ = mo_->optionalCast<Space>()) {
+            if (auto z_ = space_->thermalZone()) {
+              modelObject.setAmbientTemperatureZone(z_.get());
+            }
+          } else {
+            LOG(Warn, workspaceObject.briefDescription() << " has a wrong type for 'Ambient Temperature Zone Name'");
+          }
+        }
+      } else {
+        LOG(Warn, workspaceObject.briefDescription()
+                    << " has an Ambient Temperature Indicator of type 'Zone', but no Zone assigned. Falling back to 'Outdoors'");
+      }
+    } else {
+      // Ambient Temperature Outdoor Air Node Name: Optional Node
+      if (boost::optional<std::string> s_ = workspaceObject.getString(Chiller_Electric_ASHRAE205Fields::AmbientTemperatureOutdoorAirNodeName)) {
+        modelObject.setAmbientTemperatureOutdoorAirNodeName(s_.get());
+      }
+    }
+
+    // Chilled Water Maximum Requested Flow Rate: Optional Double
+    if (boost::optional<double> _chilledWaterMaximumRequestedFlowRate =
+          workspaceObject.getDouble(Chiller_Electric_ASHRAE205Fields::ChilledWaterMaximumRequestedFlowRate)) {
+      modelObject.setChilledWaterMaximumRequestedFlowRate(_chilledWaterMaximumRequestedFlowRate.get());
+    }
+
+    // Condenser Maximum Requested Flow Rate: Optional Double
+    if (boost::optional<double> _condenserMaximumRequestedFlowRate =
+          workspaceObject.getDouble(Chiller_Electric_ASHRAE205Fields::CondenserMaximumRequestedFlowRate)) {
+      modelObject.setCondenserMaximumRequestedFlowRate(_condenserMaximumRequestedFlowRate.get());
+    }
+
+    // Chiller Flow Mode: Optional String
+    if (boost::optional<std::string> _chillerFlowMode = workspaceObject.getString(Chiller_Electric_ASHRAE205Fields::ChillerFlowMode)) {
+      modelObject.setChillerFlowMode(_chillerFlowMode.get());
+    }
+
+    if (boost::optional<double> _oilCoolerDesignFlowRate = workspaceObject.getDouble(Chiller_Electric_ASHRAE205Fields::OilCoolerDesignFlowRate)) {
+      modelObject.setOilCoolerDesignFlowRate(_oilCoolerDesignFlowRate.get());
+    }
+
+    // Auxiliary Cooling Design Flow Rate: Optional Double
+    if (boost::optional<double> _auxiliaryCoolingDesignFlowRate =
+          workspaceObject.getDouble(Chiller_Electric_ASHRAE205Fields::AuxiliaryCoolingDesignFlowRate)) {
+      modelObject.setAuxiliaryCoolingDesignFlowRate(_auxiliaryCoolingDesignFlowRate.get());
+    }
+
+    // End-Use Subcategory: Optional String
+    if (boost::optional<std::string> _endUseSubcategory = workspaceObject.getString(Chiller_Electric_ASHRAE205Fields::EndUseSubcategory)) {
+      modelObject.setEndUseSubcategory(_endUseSubcategory.get());
+    }
+
+    if (workspaceObject.getTarget(Chiller_Electric_ASHRAE205Fields::ChilledWaterInletNodeName)
+        || workspaceObject.getTarget(Chiller_Electric_ASHRAE205Fields::ChilledWaterOutletNodeName)
+        || workspaceObject.getTarget(Chiller_Electric_ASHRAE205Fields::CondenserInletNodeName)
+        || workspaceObject.getTarget(Chiller_Electric_ASHRAE205Fields::CondenserOutletNodeName)
+        || workspaceObject.getTarget(Chiller_Electric_ASHRAE205Fields::HeatRecoveryInletNodeName)
+        || workspaceObject.getTarget(Chiller_Electric_ASHRAE205Fields::HeatRecoveryOutletNodeName)
+        || workspaceObject.getTarget(Chiller_Electric_ASHRAE205Fields::OilCoolerInletNodeName)
+        || workspaceObject.getTarget(Chiller_Electric_ASHRAE205Fields::OilCoolerOutletNodeName)
+        || workspaceObject.getTarget(Chiller_Electric_ASHRAE205Fields::AuxiliaryInletNodeName)
+        || workspaceObject.getTarget(Chiller_Electric_ASHRAE205Fields::AuxiliaryOutletNodeName)) {
+      LOG(Warn, "For " << workspaceObject.briefDescription() << " Loop Connections are NOT ReverseTranslated.");
+    }
+
+    return modelObject;
+  }  // End of translate function
+
+}  // end namespace energyplus
+}  // end namespace openstudio
diff --git a/src/energyplus/ReverseTranslator/ReverseTranslateCoilCoolingDX.cpp b/src/energyplus/ReverseTranslator/ReverseTranslateCoilCoolingDX.cpp
index 1c37e6a1eda..76a4b069204 100644
--- a/src/energyplus/ReverseTranslator/ReverseTranslateCoilCoolingDX.cpp
+++ b/src/energyplus/ReverseTranslator/ReverseTranslateCoilCoolingDX.cpp
@@ -38,6 +38,8 @@
 #include "../../model/Schedule_Impl.hpp"
 #include "../../model/ThermalZone.hpp"
 #include "../../model/ThermalZone_Impl.hpp"
+#include "../../model/Space.hpp"
+#include "../../model/Space_Impl.hpp"
 #include "../../model/CoilCoolingDXCurveFitPerformance.hpp"
 #include "../../model/CoilCoolingDXCurveFitPerformance_Impl.hpp"
 
@@ -90,10 +92,14 @@ namespace energyplus {
     }
 
     if ((target = workspaceObject.getTarget(openstudio::Coil_Cooling_DXFields::CondenserZoneName))) {
-      OptionalModelObject modelObject = translateAndMapWorkspaceObject(*target);
-      if (modelObject) {
-        if (auto optZ = modelObject->optionalCast<ThermalZone>()) {
-          dx.setCondenserZone(optZ.get());
+      if (auto mo_ = translateAndMapWorkspaceObject(*target)) {
+        // Zone is translated, and a Space is returned instead
+        if (boost::optional<Space> space_ = mo_->optionalCast<Space>()) {
+          if (auto z_ = space_->thermalZone()) {
+            dx.setCondenserZone(z_.get());
+          }
+        } else {
+          LOG(Warn, workspaceObject.briefDescription() << " has a wrong type for 'Condenser Zone Name'");
         }
       }
     }
diff --git a/src/energyplus/ReverseTranslator/ReverseTranslateElectricLoadCenterStorageConverter.cpp b/src/energyplus/ReverseTranslator/ReverseTranslateElectricLoadCenterStorageConverter.cpp
index 190d87fb177..6aa2e3c63fc 100644
--- a/src/energyplus/ReverseTranslator/ReverseTranslateElectricLoadCenterStorageConverter.cpp
+++ b/src/energyplus/ReverseTranslator/ReverseTranslateElectricLoadCenterStorageConverter.cpp
@@ -36,6 +36,8 @@
 #include "../../model/Schedule_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"
 
@@ -53,7 +55,7 @@ namespace energyplus {
 
   OptionalModelObject ReverseTranslator::translateElectricLoadCenterStorageConverter(const WorkspaceObject& workspaceObject) {
 
-    OptionalModelObject result, omo;
+    OptionalModelObject omo;
     OptionalDouble optD;
     boost::optional<WorkspaceObject> owo;
     OptionalString optS;
@@ -116,9 +118,12 @@ namespace energyplus {
 
     // ZoneName
     if ((owo = workspaceObject.getTarget(ElectricLoadCenter_Storage_ConverterFields::ZoneName))) {
-      if ((omo = translateAndMapWorkspaceObject(owo.get()))) {
-        if (boost::optional<ThermalZone> thermalZone = omo->optionalCast<ThermalZone>()) {
-          elcConv.setThermalZone(thermalZone.get());
+      if (boost::optional<ModelObject> mo = translateAndMapWorkspaceObject(owo.get())) {
+        // Zone is translated, and a Space is returned instead
+        if (boost::optional<Space> space_ = mo->optionalCast<Space>()) {
+          if (auto z_ = space_->thermalZone()) {
+            elcConv.setThermalZone(z_.get());
+          }
         }
       }
     }
@@ -129,8 +134,7 @@ namespace energyplus {
       elcConv.setRadiativeFraction(*optD);
     }
 
-    result = elcConv;
-    return result;
+    return elcConv;
   }
 
 }  // namespace energyplus
diff --git a/src/energyplus/ReverseTranslator/ReverseTranslateElectricLoadCenterStorageLiIonNMCBattery.cpp b/src/energyplus/ReverseTranslator/ReverseTranslateElectricLoadCenterStorageLiIonNMCBattery.cpp
index cc449caa718..33a399ee4bf 100644
--- a/src/energyplus/ReverseTranslator/ReverseTranslateElectricLoadCenterStorageLiIonNMCBattery.cpp
+++ b/src/energyplus/ReverseTranslator/ReverseTranslateElectricLoadCenterStorageLiIonNMCBattery.cpp
@@ -36,6 +36,8 @@
 #include "../../model/Schedule_Impl.hpp"
 #include "../../model/ThermalZone.hpp"
 #include "../../model/ThermalZone_Impl.hpp"
+#include "../../model/Space.hpp"
+#include "../../model/Space_Impl.hpp"
 
 #include <utilities/idd/ElectricLoadCenter_Storage_LiIonNMCBattery_FieldEnums.hxx>
 
@@ -50,7 +52,6 @@ namespace energyplus {
 
   OptionalModelObject ReverseTranslator::translateElectricLoadCenterStorageLiIonNMCBattery(const WorkspaceObject& workspaceObject) {
 
-    OptionalModelObject result, temp;
     OptionalDouble d;
     boost::optional<WorkspaceObject> owo;
     OptionalString optS;
@@ -105,8 +106,11 @@ namespace energyplus {
     // ZoneName
     if ((owo = workspaceObject.getTarget(ElectricLoadCenter_Storage_LiIonNMCBatteryFields::ZoneName))) {
       if (boost::optional<ModelObject> mo = translateAndMapWorkspaceObject(owo.get())) {
-        if (boost::optional<ThermalZone> thermalZone = mo->optionalCast<ThermalZone>()) {
-          elcStorLiIonNMCBattery.setThermalZone(thermalZone.get());
+        // Zone is translated, and a Space is returned instead
+        if (boost::optional<Space> space_ = mo->optionalCast<Space>()) {
+          if (auto z_ = space_->thermalZone()) {
+            elcStorLiIonNMCBattery.setThermalZone(z_.get());
+          }
         }
       }
     }
@@ -201,7 +205,7 @@ namespace energyplus {
       elcStorLiIonNMCBattery.setBatteryCellInternalElectricalResistance(*d);
     }
 
-    return result;
+    return elcStorLiIonNMCBattery;
   }
 
 }  // namespace energyplus
diff --git a/src/energyplus/ReverseTranslator/ReverseTranslateElectricLoadCenterStorageSimple.cpp b/src/energyplus/ReverseTranslator/ReverseTranslateElectricLoadCenterStorageSimple.cpp
index eedf6bd6327..81ae5ca5b40 100644
--- a/src/energyplus/ReverseTranslator/ReverseTranslateElectricLoadCenterStorageSimple.cpp
+++ b/src/energyplus/ReverseTranslator/ReverseTranslateElectricLoadCenterStorageSimple.cpp
@@ -36,6 +36,8 @@
 #include "../../model/Schedule_Impl.hpp"
 #include "../../model/ThermalZone.hpp"
 #include "../../model/ThermalZone_Impl.hpp"
+#include "../../model/Space.hpp"
+#include "../../model/Space_Impl.hpp"
 
 #include <utilities/idd/ElectricLoadCenter_Storage_Simple_FieldEnums.hxx>
 
@@ -50,7 +52,6 @@ namespace energyplus {
 
   OptionalModelObject ReverseTranslator::translateElectricLoadCenterStorageSimple(const WorkspaceObject& workspaceObject) {
 
-    OptionalModelObject result, temp;
     OptionalDouble d;
     boost::optional<WorkspaceObject> owo;
     OptionalString optS;
@@ -74,9 +75,14 @@ namespace energyplus {
 
     // ZoneName
     if ((owo = workspaceObject.getTarget(ElectricLoadCenter_Storage_SimpleFields::ZoneName))) {
-      if (boost::optional<ModelObject> mo = translateAndMapWorkspaceObject(owo.get())) {
-        if (boost::optional<ThermalZone> thermalZone = mo->optionalCast<ThermalZone>()) {
-          elcStorSimple.setThermalZone(thermalZone.get());
+      if (boost::optional<ModelObject> mo_ = translateAndMapWorkspaceObject(owo.get())) {
+        // Zone is translated, and a Space is returned instead
+        if (boost::optional<Space> space_ = mo_->optionalCast<Space>()) {
+          if (auto z_ = space_->thermalZone()) {
+            elcStorSimple.setThermalZone(z_.get());
+          }
+        } else {
+          LOG(Warn, workspaceObject.briefDescription() << " has a wrong type for 'Zone Name'");
         }
       }
     }
@@ -129,8 +135,7 @@ namespace energyplus {
       elcStorSimple.setInitialStateofCharge(*d);
     }
 
-    result = elcStorSimple;
-    return result;
+    return elcStorSimple;
   }
 
 }  // namespace energyplus
diff --git a/src/energyplus/ReverseTranslator/ReverseTranslateFanSystemModel.cpp b/src/energyplus/ReverseTranslator/ReverseTranslateFanSystemModel.cpp
index 9116a155ba5..011fc6937b4 100644
--- a/src/energyplus/ReverseTranslator/ReverseTranslateFanSystemModel.cpp
+++ b/src/energyplus/ReverseTranslator/ReverseTranslateFanSystemModel.cpp
@@ -39,6 +39,8 @@
 #include "../../model/Curve_Impl.hpp"
 #include "../../model/ThermalZone.hpp"
 #include "../../model/ThermalZone_Impl.hpp"
+#include "../../model/Space.hpp"
+#include "../../model/Space_Impl.hpp"
 
 #include "../../utilities/idf/IdfExtensibleGroup.hpp"
 
@@ -170,13 +172,17 @@ namespace energyplus {
     // Motor Loss Zone Name: Optional Object
     if ((_wo = workspaceObject.getTarget(Fan_SystemModelFields::MotorLossZoneName))) {
       if ((_mo = translateAndMapWorkspaceObject(_wo.get()))) {
-        if (boost::optional<ThermalZone> _motorLossZone = _mo->optionalCast<ThermalZone>()) {
-          modelObject.setMotorLossZone(_motorLossZone.get());
+        // Zone is translated, and a Space is returned instead
+        if (boost::optional<Space> space_ = _mo->optionalCast<Space>()) {
+          if (auto z_ = space_->thermalZone()) {
+            modelObject.setMotorLossZone(z_.get());
+          }
         } else {
           LOG(Warn, workspaceObject.briefDescription() << " has a wrong type for 'Motor Loss Zone Name'");
         }
       }
     }
+
     // Motor Loss Radiative Fraction: Optional Double
     if (boost::optional<double> _motorLossRadiativeFraction = workspaceObject.getDouble(Fan_SystemModelFields::MotorLossRadiativeFraction)) {
       modelObject.setMotorLossRadiativeFraction(_motorLossRadiativeFraction.get());
diff --git a/src/energyplus/ReverseTranslator/ReverseTranslateRefrigerationCase.cpp b/src/energyplus/ReverseTranslator/ReverseTranslateRefrigerationCase.cpp
index 30856e8a333..bb94d8ffea4 100644
--- a/src/energyplus/ReverseTranslator/ReverseTranslateRefrigerationCase.cpp
+++ b/src/energyplus/ReverseTranslator/ReverseTranslateRefrigerationCase.cpp
@@ -36,6 +36,9 @@
 #include "../../model/ThermalZone_Impl.hpp"
 #include "../../model/CurveCubic.hpp"
 #include "../../model/CurveCubic_Impl.hpp"
+#include "../../model/Space.hpp"
+#include "../../model/Space_Impl.hpp"
+
 #include <utilities/idd/Refrigeration_Case_FieldEnums.hxx>
 #include "../../utilities/idd/IddEnums.hpp"
 #include <utilities/idd/IddEnums.hxx>
@@ -88,12 +91,18 @@ namespace energyplus {
       }
       // ZoneName
       if ((wo = workspaceObject.getTarget(Refrigeration_CaseFields::ZoneName))) {
-        if (boost::optional<ModelObject> mo = translateAndMapWorkspaceObject(wo.get())) {
-          if (boost::optional<ThermalZone> thermalZone = mo->optionalCast<ThermalZone>()) {
-            refrigerationCase->setThermalZone(thermalZone.get());
+        if (boost::optional<ModelObject> mo_ = translateAndMapWorkspaceObject(wo.get())) {
+          // Zone is translated, and a Space is returned instead
+          if (boost::optional<Space> space_ = mo_->optionalCast<Space>()) {
+            if (auto z_ = space_->thermalZone()) {
+              refrigerationCase->setThermalZone(z_.get());
+            }
+          } else {
+            LOG(Warn, workspaceObject.briefDescription() << " has a wrong type for 'Zone Name'");
           }
         }
       }
+
       // RatedAmbientTemperature
       value = workspaceObject.getDouble(Refrigeration_CaseFields::RatedAmbientTemperature);
       if (value) {
diff --git a/src/energyplus/ReverseTranslator/ReverseTranslateZoneCrossMixing.cpp b/src/energyplus/ReverseTranslator/ReverseTranslateZoneCrossMixing.cpp
index a1ffe2e8ea5..49e88815abf 100644
--- a/src/energyplus/ReverseTranslator/ReverseTranslateZoneCrossMixing.cpp
+++ b/src/energyplus/ReverseTranslator/ReverseTranslateZoneCrossMixing.cpp
@@ -33,6 +33,8 @@
 #include "../../model/ZoneMixing_Impl.hpp"
 #include "../../model/ThermalZone.hpp"
 #include "../../model/ThermalZone_Impl.hpp"
+#include "../../model/Space.hpp"
+#include "../../model/Space_Impl.hpp"
 #include "../../model/Schedule.hpp"
 #include "../../model/Schedule_Impl.hpp"
 
@@ -57,9 +59,15 @@ namespace energyplus {
     OptionalWorkspaceObject target = workspaceObject.getTarget(openstudio::ZoneCrossMixingFields::ZoneorSpaceName);
     OptionalThermalZone zone;
     if (target) {
-      OptionalModelObject modelObject = translateAndMapWorkspaceObject(*target);
-      if (modelObject) {
-        zone = modelObject->optionalCast<ThermalZone>();
+      if (OptionalModelObject modelObject = translateAndMapWorkspaceObject(*target)) {
+        if (target->iddObject().type() == IddObjectType::Zone) {
+          // Zone maps to Space in RT
+          if (auto s_ = modelObject->optionalCast<Space>()) {
+            zone = s_->thermalZone();
+          }
+        } else {
+          // It's a space, but we don't allow mapping to a space in model SDK for now, and we don't have a Space RT... so we'll never get here
+        }
       }
     }
 
@@ -71,8 +79,13 @@ namespace energyplus {
     OptionalThermalZone sourceZone;
     if (target) {
       OptionalModelObject modelObject = translateAndMapWorkspaceObject(*target);
-      if (modelObject) {
-        sourceZone = modelObject->optionalCast<ThermalZone>();
+      if (target->iddObject().type() == IddObjectType::Zone) {
+        // Zone maps to Space in RT
+        if (auto s_ = modelObject->optionalCast<Space>()) {
+          sourceZone = s_->thermalZone();
+        }
+      } else {
+        // It's a space, but we don't allow mapping to a space in model SDK for now, and we don't have a Space RT... so we'll never get here
       }
     }
 
diff --git a/src/energyplus/ReverseTranslator/ReverseTranslateZoneMixing.cpp b/src/energyplus/ReverseTranslator/ReverseTranslateZoneMixing.cpp
index d2c47866e95..94467e6a714 100644
--- a/src/energyplus/ReverseTranslator/ReverseTranslateZoneMixing.cpp
+++ b/src/energyplus/ReverseTranslator/ReverseTranslateZoneMixing.cpp
@@ -33,6 +33,8 @@
 #include "../../model/ZoneMixing_Impl.hpp"
 #include "../../model/ThermalZone.hpp"
 #include "../../model/ThermalZone_Impl.hpp"
+#include "../../model/Space.hpp"
+#include "../../model/Space_Impl.hpp"
 #include "../../model/Schedule.hpp"
 #include "../../model/Schedule_Impl.hpp"
 
@@ -57,9 +59,15 @@ namespace energyplus {
     OptionalWorkspaceObject target = workspaceObject.getTarget(openstudio::ZoneMixingFields::ZoneorSpaceName);
     OptionalThermalZone zone;
     if (target) {
-      OptionalModelObject modelObject = translateAndMapWorkspaceObject(*target);
-      if (modelObject) {
-        zone = modelObject->optionalCast<ThermalZone>();
+      if (OptionalModelObject modelObject = translateAndMapWorkspaceObject(*target)) {
+        if (target->iddObject().type() == IddObjectType::Zone) {
+          // Zone maps to Space in RT
+          if (auto s_ = modelObject->optionalCast<Space>()) {
+            zone = s_->thermalZone();
+          }
+        } else {
+          // It's a space, but we don't allow mapping to a space in model SDK for now, and we don't have a Space RT... so we'll never get here
+        }
       }
     }
 
@@ -67,7 +75,26 @@ namespace energyplus {
       return boost::none;
     }
 
+    target = workspaceObject.getTarget(openstudio::ZoneMixingFields::SourceZoneorSpaceName);
+    OptionalThermalZone sourceZone;
+    if (target) {
+      OptionalModelObject modelObject = translateAndMapWorkspaceObject(*target);
+      if (target->iddObject().type() == IddObjectType::Zone) {
+        // Zone maps to Space in RT
+        if (auto s_ = modelObject->optionalCast<Space>()) {
+          sourceZone = s_->thermalZone();
+        }
+      } else {
+        // It's a space, but we don't allow mapping to a space in model SDK for now, and we don't have a Space RT... so we'll never get here
+      }
+    }
+
+    if (!sourceZone) {
+      return boost::none;
+    }
+
     openstudio::model::ZoneMixing mixing(*zone);
+    mixing.setSourceZone(sourceZone.get());
 
     OptionalString s = workspaceObject.name();
     if (s) {
@@ -120,16 +147,6 @@ namespace energyplus {
       LOG(Error, "Unknown DesignFlowRateCalculationMethod value for workspace object" << workspaceObject);
     }
 
-    target = workspaceObject.getTarget(openstudio::ZoneMixingFields::SourceZoneorSpaceName);
-    if (target) {
-      OptionalModelObject modelObject = translateAndMapWorkspaceObject(*target);
-      if (modelObject) {
-        if (modelObject->optionalCast<ThermalZone>()) {
-          mixing.setSourceZone(modelObject->cast<ThermalZone>());
-        }
-      }
-    }
-
     d = workspaceObject.getDouble(openstudio::ZoneMixingFields::DeltaTemperature);
     if (d) {
       mixing.setDeltaTemperature(*d);
diff --git a/src/energyplus/Test/ChillerElectricASHRAE205_GTest.cpp b/src/energyplus/Test/ChillerElectricASHRAE205_GTest.cpp
new file mode 100644
index 00000000000..a5d8772f984
--- /dev/null
+++ b/src/energyplus/Test/ChillerElectricASHRAE205_GTest.cpp
@@ -0,0 +1,408 @@
+/***********************************************************************************************************************
+*  OpenStudio(R), Copyright (c) 2008-2022, 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 <gtest/gtest.h>
+#include "EnergyPlusFixture.hpp"
+
+#include "../ErrorFile.hpp"
+#include "../ForwardTranslator.hpp"
+#include "../ReverseTranslator.hpp"
+
+#include "../../model/ChillerElectricASHRAE205.hpp"
+#include "../../model/ChillerElectricASHRAE205_Impl.hpp"
+
+#include "../../model/ExternalFile.hpp"
+#include "../../model/ExternalFile_Impl.hpp"
+
+#include "../../model/ThermalZone.hpp"
+#include "../../model/Space.hpp"
+#include "../../model/PlantLoop.hpp"
+#include "../../model/PlantLoop_Impl.hpp"
+#include "../../model/Node.hpp"
+#include "../../model/Node_Impl.hpp"
+#include "../../model/Schedule.hpp"
+#include "../../model/ScheduleConstant.hpp"
+#include "../../model/Mixer.hpp"
+#include "../../model/Splitter.hpp"
+
+#include "../../utilities/geometry/Point3d.hpp"
+
+#include "../../utilities/idf/IdfObject.hpp"
+#include "../../utilities/idf/WorkspaceObject.hpp"
+#include "../../utilities/idf/IdfExtensibleGroup.hpp"
+#include "../../utilities/idf/WorkspaceExtensibleGroup.hpp"
+
+// E+ FieldEnums
+#include <utilities/idd/IddEnums.hxx>
+#include <utilities/idd/IddFactory.hxx>
+
+#include <utilities/idd/Chiller_Electric_ASHRAE205_FieldEnums.hxx>
+
+#include <utilities/idd/PlantLoop_FieldEnums.hxx>
+#include <utilities/idd/PlantEquipmentOperationSchemes_FieldEnums.hxx>
+
+#include <utilities/idd/PlantEquipmentOperation_HeatingLoad_FieldEnums.hxx>
+#include <utilities/idd/PlantEquipmentOperation_CoolingLoad_FieldEnums.hxx>
+#include <utilities/idd/PlantEquipmentOperation_Uncontrolled_FieldEnums.hxx>
+
+#include <utilities/idd/PlantEquipmentList_FieldEnums.hxx>
+
+#include <utilities/idd/BranchList_FieldEnums.hxx>
+#include <utilities/idd/Branch_FieldEnums.hxx>
+
+#include "../../utilities/core/PathHelpers.hpp"
+#include <resources.hxx>
+#include <vector>
+
+using namespace openstudio::energyplus;
+using namespace openstudio::model;
+using namespace openstudio;
+
+/* Ensures that the nodes that translated correctly
+ * that means correct node names in the ChillerElectricASHRAE205 but also
+ * on the Branches
+ */
+TEST_F(EnergyPlusFixture, ForwardTranslator_ChillerElectricASHRAE205) {
+
+  ForwardTranslator ft;
+
+  Model m;
+
+  auto createLoop = [&m](const std::string& prefix) {
+    PlantLoop p(m);
+    static constexpr std::array<std::string_view, 10> compNames = {
+      "Supply Inlet", "Supply Splitter", "Supply Connection Node", "Supply Mixer", "Supply Outlet",
+      "Demand Inlet", "Demand Splitter", "Demand Connection Node", "Demand Mixer", "Demand Outlet",
+    };
+    p.setName(prefix);
+    for (size_t i = 0; auto& comp : p.components()) {
+      comp.setName(prefix + " " + std::string{compNames[i++]});
+    }
+    return p;
+  };
+
+  openstudio::path p = resourcesPath() / toPath("model/A205ExampleChiller.RS0001.a205.cbor");
+  EXPECT_TRUE(exists(p));
+
+  boost::optional<ExternalFile> representationFile = ExternalFile::getExternalFile(m, openstudio::toString(p));
+  ASSERT_TRUE(representationFile);
+
+  ChillerElectricASHRAE205 ch(representationFile.get());
+
+  EXPECT_TRUE(ch.setPerformanceInterpolationMethod("Cubic"));
+  ch.autosizeRatedCapacity();
+  EXPECT_TRUE(ch.setSizingFactor(1.1));
+
+  ThermalZone z(m);
+  z.setName("Basement");
+  {
+    std::vector<Point3d> sPoints{{0, 0, 0}, {0, 1, 0}, {1, 1, 0}, {1, 0, 0}};
+    auto space_ = Space::fromFloorPrint(sPoints, 3.0, m);
+    ASSERT_TRUE(space_);
+    EXPECT_TRUE(space_->setThermalZone(z));
+  }
+
+  EXPECT_TRUE(ch.setAmbientTemperatureZone(z));
+
+  EXPECT_TRUE(ch.setChilledWaterMaximumRequestedFlowRate(0.0428));
+
+  auto chwLoop = createLoop("chwLoop");
+  EXPECT_TRUE(chwLoop.addSupplyBranchForComponent(ch));
+
+  auto cndLoop = createLoop("cndLoop");
+  EXPECT_TRUE(cndLoop.addDemandBranchForComponent(ch));
+  EXPECT_TRUE(ch.setCondenserMaximumRequestedFlowRate(0.0552));
+
+  EXPECT_TRUE(ch.setChillerFlowMode("ConstantFlow"));
+
+  auto ocLoop = createLoop("ocLoop");
+  EXPECT_TRUE(ch.addDemandBranchOnOilCoolerLoop(ocLoop));
+  EXPECT_TRUE(ch.setOilCoolerDesignFlowRate(0.001));
+
+  auto auxLoop = createLoop("auxLoop");
+  EXPECT_TRUE(ch.addDemandBranchOnAuxiliaryLoop(auxLoop));
+  EXPECT_TRUE(ch.setAuxiliaryCoolingDesignFlowRate(0.002));
+
+  EXPECT_TRUE(ch.setEndUseSubcategory("Chiller"));
+
+  ch.chilledWaterInletNode()->setName("ChilledWater Inlet Node");
+  ch.chilledWaterOutletNode()->setName("ChilledWater Outlet Node");
+  ch.condenserInletNode()->setName("Condenser Inlet Node");
+  ch.condenserOutletNode()->setName("Condenser Outlet Node");
+
+  ch.oilCoolerInletNode()->setName("OilCooler Inlet Node");
+  ch.oilCoolerOutletNode()->setName("OilCooler Outlet Node");
+  ch.auxiliaryInletNode()->setName("Auxiliary Inlet Node");
+  ch.auxiliaryOutletNode()->setName("Auxiliary Outlet Node");
+
+  if constexpr (ChillerElectricASHRAE205::isHeatRecoverySupportedByEnergyplus) {
+    auto hrLoop = createLoop("hrLoop");
+    EXPECT_TRUE(hrLoop.addDemandBranchForComponent(ch, true));
+    ch.heatRecoveryInletNode()->setName("HeatRecovery Inlet Node");
+    ch.heatRecoveryOutletNode()->setName("HeatRecovery Outlet Node");
+  }
+
+  {
+    Workspace w = ft.translateModel(m);
+
+    std::vector<WorkspaceObject> woChs = w.getObjectsByType(IddObjectType::Chiller_Electric_ASHRAE205);
+    ASSERT_EQ(1, woChs.size());
+    auto& woCh = woChs.front();
+
+    EXPECT_EQ(ch.nameString(), woCh.getString(Chiller_Electric_ASHRAE205Fields::Name).get());
+    EXPECT_EQ(representationFile->filePath(), woCh.getString(Chiller_Electric_ASHRAE205Fields::RepresentationFileName).get());
+    EXPECT_EQ("Cubic", woCh.getString(Chiller_Electric_ASHRAE205Fields::PerformanceInterpolationMethod).get());
+    EXPECT_EQ("Autosize", woCh.getString(Chiller_Electric_ASHRAE205Fields::RatedCapacity).get());
+    EXPECT_EQ(1.1, woCh.getDouble(Chiller_Electric_ASHRAE205Fields::SizingFactor).get());
+
+    EXPECT_EQ("Zone", woCh.getString(Chiller_Electric_ASHRAE205Fields::AmbientTemperatureIndicator).get());
+    EXPECT_TRUE(woCh.isEmpty(Chiller_Electric_ASHRAE205Fields::AmbientTemperatureScheduleName));
+    EXPECT_EQ("Basement", woCh.getString(Chiller_Electric_ASHRAE205Fields::AmbientTemperatureZoneName).get());
+    EXPECT_TRUE(woCh.isEmpty(Chiller_Electric_ASHRAE205Fields::AmbientTemperatureOutdoorAirNodeName));
+
+    EXPECT_EQ(0.0428, woCh.getDouble(Chiller_Electric_ASHRAE205Fields::ChilledWaterMaximumRequestedFlowRate).get());
+
+    EXPECT_EQ(0.0552, woCh.getDouble(Chiller_Electric_ASHRAE205Fields::CondenserMaximumRequestedFlowRate).get());
+
+    EXPECT_EQ("ConstantFlow", woCh.getString(Chiller_Electric_ASHRAE205Fields::ChillerFlowMode).get());
+
+    EXPECT_EQ(0.001, woCh.getDouble(Chiller_Electric_ASHRAE205Fields::OilCoolerDesignFlowRate).get());
+
+    EXPECT_EQ(0.002, woCh.getDouble(Chiller_Electric_ASHRAE205Fields::AuxiliaryCoolingDesignFlowRate).get());
+
+    EXPECT_EQ("Chiller", woCh.getString(Chiller_Electric_ASHRAE205Fields::EndUseSubcategory).get());
+
+    EXPECT_EQ("ChilledWater Inlet Node", woCh.getString(Chiller_Electric_ASHRAE205Fields::ChilledWaterInletNodeName).get());
+    EXPECT_EQ("ChilledWater Outlet Node", woCh.getString(Chiller_Electric_ASHRAE205Fields::ChilledWaterOutletNodeName).get());
+    EXPECT_EQ(ch.chilledWaterInletNode()->nameString(), woCh.getString(Chiller_Electric_ASHRAE205Fields::ChilledWaterInletNodeName).get());
+    EXPECT_EQ(ch.chilledWaterOutletNode()->nameString(), woCh.getString(Chiller_Electric_ASHRAE205Fields::ChilledWaterOutletNodeName).get());
+
+    EXPECT_EQ("Condenser Inlet Node", woCh.getString(Chiller_Electric_ASHRAE205Fields::CondenserInletNodeName).get());
+    EXPECT_EQ("Condenser Outlet Node", woCh.getString(Chiller_Electric_ASHRAE205Fields::CondenserOutletNodeName).get());
+    EXPECT_EQ(ch.condenserInletNode()->nameString(), woCh.getString(Chiller_Electric_ASHRAE205Fields::CondenserInletNodeName).get());
+    EXPECT_EQ(ch.condenserOutletNode()->nameString(), woCh.getString(Chiller_Electric_ASHRAE205Fields::CondenserOutletNodeName).get());
+
+    EXPECT_EQ("OilCooler Inlet Node", woCh.getString(Chiller_Electric_ASHRAE205Fields::OilCoolerInletNodeName).get());
+    EXPECT_EQ("OilCooler Outlet Node", woCh.getString(Chiller_Electric_ASHRAE205Fields::OilCoolerOutletNodeName).get());
+    EXPECT_EQ(ch.oilCoolerInletNode()->nameString(), woCh.getString(Chiller_Electric_ASHRAE205Fields::OilCoolerInletNodeName).get());
+    EXPECT_EQ(ch.oilCoolerOutletNode()->nameString(), woCh.getString(Chiller_Electric_ASHRAE205Fields::OilCoolerOutletNodeName).get());
+
+    EXPECT_EQ("Auxiliary Inlet Node", woCh.getString(Chiller_Electric_ASHRAE205Fields::AuxiliaryInletNodeName).get());
+    EXPECT_EQ("Auxiliary Outlet Node", woCh.getString(Chiller_Electric_ASHRAE205Fields::AuxiliaryOutletNodeName).get());
+    EXPECT_EQ(ch.auxiliaryInletNode()->nameString(), woCh.getString(Chiller_Electric_ASHRAE205Fields::AuxiliaryInletNodeName).get());
+    EXPECT_EQ(ch.auxiliaryOutletNode()->nameString(), woCh.getString(Chiller_Electric_ASHRAE205Fields::AuxiliaryOutletNodeName).get());
+
+    if constexpr (ChillerElectricASHRAE205::isHeatRecoverySupportedByEnergyplus) {
+      EXPECT_EQ("HeatRecovery Inlet Node", woCh.getString(Chiller_Electric_ASHRAE205Fields::HeatRecoveryInletNodeName).get());
+      EXPECT_EQ("HeatRecovery Outlet Node", woCh.getString(Chiller_Electric_ASHRAE205Fields::HeatRecoveryOutletNodeName).get());
+      EXPECT_EQ(ch.heatRecoveryInletNode()->nameString(), woCh.getString(Chiller_Electric_ASHRAE205Fields::HeatRecoveryInletNodeName).get());
+      EXPECT_EQ(ch.heatRecoveryOutletNode()->nameString(), woCh.getString(Chiller_Electric_ASHRAE205Fields::HeatRecoveryOutletNodeName).get());
+    }
+
+    // Check node names on supply/demand branches
+    // Checks that the special case implemented in ForwardTranslatePlantLoop::populateBranch does the right job
+
+    struct Expected
+    {
+      bool isSupply = true;
+      std::string plantName;
+      std::string inletNodeName;
+      std::string outletNodeName;
+    };
+
+    std::vector<Expected> expecteds = {
+      {true, ch.chilledWaterLoop()->nameString(), ch.chilledWaterInletNode()->nameString(), ch.chilledWaterOutletNode()->nameString()},
+      {false, ch.condenserWaterLoop()->nameString(), ch.condenserInletNode()->nameString(), ch.condenserOutletNode()->nameString()},
+      {false, ch.oilCoolerLoop()->nameString(), ch.oilCoolerInletNode()->nameString(), ch.oilCoolerOutletNode()->nameString()},
+      {false, ch.auxiliaryLoop()->nameString(), ch.auxiliaryInletNode()->nameString(), ch.auxiliaryOutletNode()->nameString()},
+    };
+
+    if constexpr (ChillerElectricASHRAE205::isHeatRecoverySupportedByEnergyplus) {
+      expecteds.emplace_back(false, ch.heatRecoveryLoop()->nameString(), ch.heatRecoveryInletNode()->nameString(),
+                             ch.heatRecoveryOutletNode()->nameString());
+    }
+
+    for (const auto& e : expecteds) {
+      auto p_ = w.getObjectByTypeAndName(IddObjectType::PlantLoop, e.plantName);
+      ASSERT_TRUE(p_.is_initialized()) << "Cannot find PlantLoop named " << e.plantName;
+      WorkspaceObject idf_plant = p_.get();
+      unsigned index = e.isSupply ? PlantLoopFields::PlantSideBranchListName : PlantLoopFields::DemandSideBranchListName;
+      WorkspaceObject idf_brlist = idf_plant.getTarget(index).get();
+
+      // Should have at least three branches: supply inlet, the one with the Chiller, supply outlet.
+      // On the demand side, there's also a bypass branch that is added by the FT by default
+      ASSERT_EQ(e.isSupply ? 3 : 4, idf_brlist.extensibleGroups().size()) << "Failed for " << e.plantName;
+      // Get the Chiller one
+      auto w_eg = idf_brlist.extensibleGroups()[1].cast<WorkspaceExtensibleGroup>();
+      WorkspaceObject idf_branch = w_eg.getTarget(BranchListExtensibleFields::BranchName).get();
+
+      // There should be only one equipment on the branch
+      ASSERT_EQ(1, idf_branch.extensibleGroups().size());
+      auto w_eg2 = idf_branch.extensibleGroups()[0].cast<WorkspaceExtensibleGroup>();
+
+      ASSERT_EQ(w_eg2.getString(BranchExtensibleFields::ComponentName).get(), ch.nameString());
+      ASSERT_EQ(w_eg2.getString(BranchExtensibleFields::ComponentInletNodeName).get(), e.inletNodeName);
+      ASSERT_EQ(w_eg2.getString(BranchExtensibleFields::ComponentOutletNodeName).get(), e.outletNodeName);
+
+      WorkspaceObject idf_plant_op = p_->getTarget(PlantLoopFields::PlantEquipmentOperationSchemeName).get();
+      if (e.isSupply) {
+        // Should have created a Cooling Load one only
+        ASSERT_EQ(1, idf_plant_op.extensibleGroups().size());
+        auto w_eg = idf_plant_op.extensibleGroups()[0].cast<WorkspaceExtensibleGroup>();
+        ASSERT_EQ("PlantEquipmentOperation:CoolingLoad",
+                  w_eg.getString(PlantEquipmentOperationSchemesExtensibleFields::ControlSchemeObjectType).get());
+
+        // Get the Operation Scheme
+        auto op_scheme_ = w_eg.getTarget(PlantEquipmentOperationSchemesExtensibleFields::ControlSchemeName);
+        ASSERT_TRUE(op_scheme_);
+
+        // Get the Plant Equipment List of this CoolingLoad scheme
+        // There should only be one Load Range
+        ASSERT_EQ(1u, op_scheme_->extensibleGroups().size());
+
+        // Load range 1
+        w_eg = op_scheme_->extensibleGroups()[0].cast<WorkspaceExtensibleGroup>();
+        auto peq_list_ = w_eg.getTarget(PlantEquipmentOperation_HeatingLoadExtensibleFields::RangeEquipmentListName);
+        ASSERT_TRUE(peq_list_);
+
+        // Should have one equipment on it: CentralHeatPumpSystem
+        auto peqs = peq_list_->extensibleGroups();
+        ASSERT_EQ(1, peqs.size());
+        ASSERT_EQ("Chiller:Electric:ASHRAE205", peqs.front().getString(PlantEquipmentListExtensibleFields::EquipmentObjectType).get());
+        ASSERT_EQ(ch.nameString(), peqs.front().getString(PlantEquipmentListExtensibleFields::EquipmentName).get());
+
+      } else {
+        EXPECT_EQ(0, idf_plant_op.extensibleGroups().size());
+      }
+    }
+  }
+
+  // Not assigned to a Chilled Water Loop? not translated, it's required
+  ch.removeFromPlantLoop();
+  {
+    // Assigned to a Surface
+    Workspace w = ft.translateModel(m);
+
+    EXPECT_EQ(0, w.getObjectsByType(IddObjectType::Chiller_Electric_ASHRAE205).size());
+  }
+}
+
+TEST_F(EnergyPlusFixture, ReverseTranslator_ChillerElectricASHRAE205) {
+
+  ReverseTranslator rt;
+
+  Workspace w(StrictnessLevel::Minimal, IddFileType::EnergyPlus);
+
+  auto wo_zone = w.addObject(IdfObject(IddObjectType::Zone)).get();
+  wo_zone.setName("Basement");
+
+  auto woCh = w.addObject(IdfObject(IddObjectType::Chiller_Electric_ASHRAE205)).get();
+  woCh.setName("Chiller ASHRAE205");
+
+  openstudio::path p = resourcesPath() / toPath("model/A205ExampleChiller.RS0001.a205.cbor");
+  EXPECT_TRUE(exists(p));
+
+  EXPECT_TRUE(woCh.setString(Chiller_Electric_ASHRAE205Fields::RepresentationFileName, openstudio::toString(p)));
+  EXPECT_TRUE(woCh.setString(Chiller_Electric_ASHRAE205Fields::PerformanceInterpolationMethod, "Cubic"));
+  EXPECT_TRUE(woCh.setString(Chiller_Electric_ASHRAE205Fields::RatedCapacity, ""));  // Defaults to Autosize
+  EXPECT_TRUE(woCh.setDouble(Chiller_Electric_ASHRAE205Fields::SizingFactor, 1.1));
+  EXPECT_TRUE(woCh.setString(Chiller_Electric_ASHRAE205Fields::AmbientTemperatureIndicator, "Zone"));
+  EXPECT_TRUE(woCh.setString(Chiller_Electric_ASHRAE205Fields::AmbientTemperatureScheduleName, ""));
+  EXPECT_TRUE(woCh.setPointer(Chiller_Electric_ASHRAE205Fields::AmbientTemperatureZoneName, wo_zone.handle()));
+  EXPECT_TRUE(woCh.setString(Chiller_Electric_ASHRAE205Fields::AmbientTemperatureOutdoorAirNodeName, ""));
+  EXPECT_TRUE(woCh.setDouble(Chiller_Electric_ASHRAE205Fields::ChilledWaterMaximumRequestedFlowRate, 0.0428));
+  EXPECT_TRUE(woCh.setDouble(Chiller_Electric_ASHRAE205Fields::CondenserMaximumRequestedFlowRate, 0.0552));
+  EXPECT_TRUE(woCh.setString(Chiller_Electric_ASHRAE205Fields::ChillerFlowMode, "ConstantFlow"));
+  EXPECT_TRUE(woCh.setDouble(Chiller_Electric_ASHRAE205Fields::OilCoolerDesignFlowRate, 0.001));
+  EXPECT_TRUE(woCh.setDouble(Chiller_Electric_ASHRAE205Fields::AuxiliaryCoolingDesignFlowRate, 0.002));
+  EXPECT_TRUE(woCh.setString(Chiller_Electric_ASHRAE205Fields::EndUseSubcategory, "Chiller"));
+
+  // Nodes not RT'ed
+  EXPECT_TRUE(woCh.setString(Chiller_Electric_ASHRAE205Fields::ChilledWaterInletNodeName, "ChilledWater Inlet Node"));
+  EXPECT_TRUE(woCh.setString(Chiller_Electric_ASHRAE205Fields::ChilledWaterOutletNodeName, "ChilledWater Outlet Node"));
+  EXPECT_TRUE(woCh.setString(Chiller_Electric_ASHRAE205Fields::CondenserInletNodeName, "Condenser Inlet Node"));
+  EXPECT_TRUE(woCh.setString(Chiller_Electric_ASHRAE205Fields::CondenserOutletNodeName, "Condenser Outlet Node"));
+  EXPECT_TRUE(woCh.setString(Chiller_Electric_ASHRAE205Fields::OilCoolerInletNodeName, "OilCooler Inlet Node"));
+  EXPECT_TRUE(woCh.setString(Chiller_Electric_ASHRAE205Fields::OilCoolerOutletNodeName, "OilCooler Outlet Node"));
+  EXPECT_TRUE(woCh.setString(Chiller_Electric_ASHRAE205Fields::AuxiliaryInletNodeName, "Auxiliary Inlet Node"));
+  EXPECT_TRUE(woCh.setString(Chiller_Electric_ASHRAE205Fields::AuxiliaryOutletNodeName, "Auxiliary Outlet Node"));
+  EXPECT_TRUE(woCh.setString(Chiller_Electric_ASHRAE205Fields::HeatRecoveryInletNodeName, "HeatRecovery Inlet Node"));
+  EXPECT_TRUE(woCh.setString(Chiller_Electric_ASHRAE205Fields::HeatRecoveryOutletNodeName, "HeatRecovery Outlet Node"));
+
+  Model m = rt.translateWorkspace(w);
+
+  auto chs = m.getConcreteModelObjects<ChillerElectricASHRAE205>();
+  ASSERT_EQ(1, chs.size());
+  auto& ch = chs.front();
+
+  ASSERT_TRUE(ch.name());
+  EXPECT_EQ("Chiller ASHRAE205", ch.nameString());
+  EXPECT_EQ("A205ExampleChiller.RS0001.a205.cbor", ch.representationFile().fileName());
+  EXPECT_EQ("Cubic", ch.performanceInterpolationMethod());
+  EXPECT_TRUE(ch.isRatedCapacityAutosized());
+  EXPECT_EQ(1.1, ch.sizingFactor());
+  EXPECT_EQ("Zone", ch.ambientTemperatureIndicator());
+  EXPECT_FALSE(ch.ambientTemperatureSchedule());
+  ASSERT_TRUE(ch.ambientTemperatureZone());
+  EXPECT_EQ("Basement", ch.ambientTemperatureZone()->nameString());
+  EXPECT_FALSE(ch.ambientTemperatureOutdoorAirNodeName());
+
+  EXPECT_FALSE(ch.isChilledWaterMaximumRequestedFlowRateAutosized());
+  ASSERT_TRUE(ch.chilledWaterMaximumRequestedFlowRate());
+  EXPECT_EQ(0.0428, ch.chilledWaterMaximumRequestedFlowRate().get());
+
+  EXPECT_FALSE(ch.isCondenserMaximumRequestedFlowRateAutosized());
+  ASSERT_TRUE(ch.condenserMaximumRequestedFlowRate());
+  EXPECT_EQ(0.0552, ch.condenserMaximumRequestedFlowRate().get());
+
+  EXPECT_EQ("ConstantFlow", ch.chillerFlowMode());
+
+  ASSERT_TRUE(ch.oilCoolerDesignFlowRate());
+  EXPECT_EQ(0.001, ch.oilCoolerDesignFlowRate().get());
+  ASSERT_TRUE(ch.auxiliaryCoolingDesignFlowRate());
+  EXPECT_EQ(0.002, ch.auxiliaryCoolingDesignFlowRate().get());
+
+  EXPECT_EQ("Chiller", ch.endUseSubcategory());
+
+  EXPECT_FALSE(ch.chilledWaterLoop());
+  EXPECT_FALSE(ch.condenserWaterLoop());
+  EXPECT_FALSE(ch.heatRecoveryLoop());
+  EXPECT_FALSE(ch.oilCoolerLoop());
+  EXPECT_FALSE(ch.auxiliaryLoop());
+  EXPECT_FALSE(ch.chilledWaterInletNode());
+  EXPECT_FALSE(ch.chilledWaterOutletNode());
+  EXPECT_FALSE(ch.condenserInletNode());
+  EXPECT_FALSE(ch.condenserOutletNode());
+  EXPECT_FALSE(ch.heatRecoveryInletNode());
+  EXPECT_FALSE(ch.heatRecoveryOutletNode());
+  EXPECT_FALSE(ch.oilCoolerInletNode());
+  EXPECT_FALSE(ch.oilCoolerOutletNode());
+  EXPECT_FALSE(ch.auxiliaryInletNode());
+  EXPECT_FALSE(ch.auxiliaryOutletNode());
+}
diff --git a/src/model/CMakeLists.txt b/src/model/CMakeLists.txt
index 30e15e8c4b3..c73cb7d6b86 100644
--- a/src/model/CMakeLists.txt
+++ b/src/model/CMakeLists.txt
@@ -281,6 +281,9 @@ set(${target_name}_src
   ChillerAbsorptionIndirect.hpp
   ChillerAbsorptionIndirect_Impl.hpp
   ChillerAbsorptionIndirect.cpp
+  ChillerElectricASHRAE205.hpp
+  ChillerElectricASHRAE205_Impl.hpp
+  ChillerElectricASHRAE205.cpp
   ChillerElectricEIR.hpp
   ChillerElectricEIR_Impl.hpp
   ChillerElectricEIR.cpp
@@ -1891,6 +1894,7 @@ set(${target_name}_test_src
   # test/CentralHeatPumpSystemModule_GTest.cpp => Included in the above
   test/ChillerAbsorption_GTest.cpp
   test/ChillerAbsorptionIndirect_GTest.cpp
+  test/ChillerElectricASHRAE205_GTest.cpp
   test/ChillerElectricEIR_GTest.cpp
   test/ChillerElectricReformulatedEIR_GTest.cpp
   test/ChillerHeaterPerformanceElectricEIR_GTest.cpp
diff --git a/src/model/ChillerElectricASHRAE205.cpp b/src/model/ChillerElectricASHRAE205.cpp
new file mode 100644
index 00000000000..18a33a96c4b
--- /dev/null
+++ b/src/model/ChillerElectricASHRAE205.cpp
@@ -0,0 +1,1179 @@
+/***********************************************************************************************************************
+*  OpenStudio(R), Copyright (c) 2008-2022, 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 "ChillerElectricASHRAE205.hpp"
+#include "ChillerElectricASHRAE205_Impl.hpp"
+
+#include "ExternalFile.hpp"
+#include "ExternalFile_Impl.hpp"
+#include "Schedule.hpp"
+#include "Schedule_Impl.hpp"
+#include "Node.hpp"
+#include "Node_Impl.hpp"
+#include "PlantLoop.hpp"
+#include "ThermalZone.hpp"
+#include "ThermalZone_Impl.hpp"
+#include "Model.hpp"
+#include "Mixer.hpp"
+#include "Splitter.hpp"
+
+#include "ScheduleTypeLimits.hpp"
+#include "ScheduleTypeRegistry.hpp"
+
+#include <utilities/idd/IddFactory.hxx>
+#include <utilities/idd/IddEnums.hxx>
+#include <utilities/idd/OS_Chiller_Electric_ASHRAE205_FieldEnums.hxx>
+
+#include "../utilities/units/Unit.hpp"
+
+#include "../utilities/core/Assert.hpp"
+
+namespace openstudio {
+namespace model {
+
+  namespace detail {
+
+    ChillerElectricASHRAE205_Impl::ChillerElectricASHRAE205_Impl(const IdfObject& idfObject, Model_Impl* model, bool keepHandle)
+      : WaterToWaterComponent_Impl(idfObject, model, keepHandle) {
+      OS_ASSERT(idfObject.iddObject().type() == ChillerElectricASHRAE205::iddObjectType());
+    }
+
+    ChillerElectricASHRAE205_Impl::ChillerElectricASHRAE205_Impl(const openstudio::detail::WorkspaceObject_Impl& other, Model_Impl* model,
+                                                                 bool keepHandle)
+      : WaterToWaterComponent_Impl(other, model, keepHandle) {
+      OS_ASSERT(other.iddObject().type() == ChillerElectricASHRAE205::iddObjectType());
+    }
+
+    ChillerElectricASHRAE205_Impl::ChillerElectricASHRAE205_Impl(const ChillerElectricASHRAE205_Impl& other, Model_Impl* model, bool keepHandle)
+      : WaterToWaterComponent_Impl(other, model, keepHandle) {}
+
+    const std::vector<std::string>& ChillerElectricASHRAE205_Impl::outputVariableNames() const {
+      static std::vector<std::string> result{"Chiller Part Load Ratio",
+                                             "Chiller Cycling Ratio",
+                                             "Minimum Part Load Ratio",
+                                             "Chiller Electricity Rate",
+                                             "Chiller Electricity Energy",
+                                             "Chiller Evaporator Cooling Rate",
+                                             "Chiller Evaporator Cooling Energy",
+                                             "Chiller Evaporator Inlet Temperature",
+                                             "Chiller Evaporator Outlet Temperature",
+                                             "Chiller Evaporator Mass Flow Rate",
+                                             "Chiller Condenser Heat Transfer Rate",
+                                             "Chiller Condenser Heat Transfer Energy",
+                                             "Chiller COP",
+                                             "Chiller Condenser Inlet Temperature",
+                                             "Chiller Condenser Outlet Temperature",
+                                             "Chiller Condenser Mass Flow Rate",
+                                             "Chiller Effective Heat Rejection Temperature",
+                                             "Chiller Zone Heat Gain Rate",
+                                             "Chiller Zone Heat Gain Energy",
+                                             "Oil Cooler Heat Transfer Rate",
+                                             "Oil Cooler Heat Transfer Energy",
+                                             "Auxiliary Heat Transfer Rate",
+                                             "Auxiliary Heat Transfer Energy"};
+      return result;
+    }
+
+    IddObjectType ChillerElectricASHRAE205_Impl::iddObjectType() const {
+      return ChillerElectricASHRAE205::iddObjectType();
+    }
+
+    std::vector<ScheduleTypeKey> ChillerElectricASHRAE205_Impl::getScheduleTypeKeys(const Schedule& schedule) const {
+      std::vector<ScheduleTypeKey> result;
+      UnsignedVector fieldIndices = getSourceIndices(schedule.handle());
+      UnsignedVector::const_iterator b(fieldIndices.begin());
+      UnsignedVector::const_iterator e(fieldIndices.end());
+      if (std::find(b, e, OS_Chiller_Electric_ASHRAE205Fields::AmbientTemperatureScheduleName) != e) {
+        result.emplace_back("ChillerElectricASHRAE205", "Ambient Temperature");
+      }
+      return result;
+    }
+
+    boost::optional<ExternalFile> ChillerElectricASHRAE205_Impl::optionalRepresentationFile() const {
+      return getObject<ModelObject>().getModelObjectTarget<ExternalFile>(OS_Chiller_Electric_ASHRAE205Fields::RepresentationFileName);
+    }
+
+    ExternalFile ChillerElectricASHRAE205_Impl::representationFile() const {
+      boost::optional<ExternalFile> value = optionalRepresentationFile();
+      if (!value) {
+        LOG_AND_THROW(briefDescription() << " does not have a Representation File attached.");
+      }
+      return value.get();
+    }
+
+    bool ChillerElectricASHRAE205_Impl::setRepresentationFile(const ExternalFile& externalFile) {
+      bool result = setPointer(OS_Chiller_Electric_ASHRAE205Fields::RepresentationFileName, externalFile.handle());
+      return result;
+    }
+
+    std::string ChillerElectricASHRAE205_Impl::performanceInterpolationMethod() const {
+      boost::optional<std::string> value = getString(OS_Chiller_Electric_ASHRAE205Fields::PerformanceInterpolationMethod, true);
+      OS_ASSERT(value);
+      return value.get();
+    }
+
+    bool ChillerElectricASHRAE205_Impl::setPerformanceInterpolationMethod(const std::string& performanceInterpolationMethod) {
+      bool result = setString(OS_Chiller_Electric_ASHRAE205Fields::PerformanceInterpolationMethod, performanceInterpolationMethod);
+      return result;
+    }
+
+    boost::optional<double> ChillerElectricASHRAE205_Impl::ratedCapacity() const {
+      return getDouble(OS_Chiller_Electric_ASHRAE205Fields::RatedCapacity, true);
+    }
+
+    bool ChillerElectricASHRAE205_Impl::isRatedCapacityAutosized() const {
+      bool result = false;
+      boost::optional<std::string> value = getString(OS_Chiller_Electric_ASHRAE205Fields::RatedCapacity, true);
+      if (value) {
+        result = openstudio::istringEqual(value.get(), "Autosize");
+      }
+      return result;
+    }
+
+    bool ChillerElectricASHRAE205_Impl::setRatedCapacity(double ratedCapacity) {
+      bool result = setDouble(OS_Chiller_Electric_ASHRAE205Fields::RatedCapacity, ratedCapacity);
+      return result;
+    }
+
+    void ChillerElectricASHRAE205_Impl::autosizeRatedCapacity() {
+      bool result = setString(OS_Chiller_Electric_ASHRAE205Fields::RatedCapacity, "Autosize");
+      OS_ASSERT(result);
+    }
+
+    double ChillerElectricASHRAE205_Impl::sizingFactor() const {
+      boost::optional<double> value = getDouble(OS_Chiller_Electric_ASHRAE205Fields::SizingFactor, true);
+      OS_ASSERT(value);
+      return value.get();
+    }
+
+    bool ChillerElectricASHRAE205_Impl::setSizingFactor(double sizingFactor) {
+      bool result = setDouble(OS_Chiller_Electric_ASHRAE205Fields::SizingFactor, sizingFactor);
+      return result;
+    }
+
+    std::string ChillerElectricASHRAE205_Impl::ambientTemperatureIndicator() const {
+      boost::optional<std::string> value = getString(OS_Chiller_Electric_ASHRAE205Fields::AmbientTemperatureIndicator, true);
+      OS_ASSERT(value);
+      return value.get();
+    }
+
+    bool ChillerElectricASHRAE205_Impl::setAmbientTemperatureIndicator(const std::string& ambientTemperatureIndicator) {
+      bool result = setString(OS_Chiller_Electric_ASHRAE205Fields::AmbientTemperatureIndicator, ambientTemperatureIndicator);
+      return result;
+    }
+
+    boost::optional<Schedule> ChillerElectricASHRAE205_Impl::ambientTemperatureSchedule() const {
+      return getObject<ModelObject>().getModelObjectTarget<Schedule>(OS_Chiller_Electric_ASHRAE205Fields::AmbientTemperatureScheduleName);
+    }
+
+    bool ChillerElectricASHRAE205_Impl::setAmbientTemperatureSchedule(Schedule& schedule) {
+      bool result =
+        setSchedule(OS_Chiller_Electric_ASHRAE205Fields::AmbientTemperatureScheduleName, "ChillerElectricASHRAE205", "Ambient Temperature", schedule);
+      if (result) {
+        bool ok = setAmbientTemperatureIndicator("Schedule");
+        OS_ASSERT(ok);
+      }
+      return result;
+    }
+
+    void ChillerElectricASHRAE205_Impl::resetAmbientTemperatureSchedule() {
+      bool result = setString(OS_Chiller_Electric_ASHRAE205Fields::AmbientTemperatureScheduleName, "");
+      OS_ASSERT(result);
+      if (openstudio::istringEqual("Schedule", ambientTemperatureIndicator())) {
+        result = setAmbientTemperatureIndicator("Outdoors");
+        OS_ASSERT(result);
+      }
+    }
+
+    boost::optional<ThermalZone> ChillerElectricASHRAE205_Impl::ambientTemperatureZone() const {
+      return getObject<ModelObject>().getModelObjectTarget<ThermalZone>(OS_Chiller_Electric_ASHRAE205Fields::AmbientTemperatureZoneName);
+    }
+
+    bool ChillerElectricASHRAE205_Impl::setAmbientTemperatureZone(const ThermalZone& thermalZone) {
+      bool result = setPointer(OS_Chiller_Electric_ASHRAE205Fields::AmbientTemperatureZoneName, thermalZone.handle());
+      if (result) {
+        bool ok = setAmbientTemperatureIndicator("Zone");
+        OS_ASSERT(ok);
+      }
+      return result;
+    }
+
+    void ChillerElectricASHRAE205_Impl::resetAmbientTemperatureZone() {
+      bool result = setString(OS_Chiller_Electric_ASHRAE205Fields::AmbientTemperatureZoneName, "");
+      OS_ASSERT(result);
+      if (openstudio::istringEqual("Zone", ambientTemperatureIndicator())) {
+        result = setAmbientTemperatureIndicator("Outdoors");
+        OS_ASSERT(result);
+      }
+    }
+
+    boost::optional<std::string> ChillerElectricASHRAE205_Impl::ambientTemperatureOutdoorAirNodeName() const {
+      return getString(OS_Chiller_Electric_ASHRAE205Fields::AmbientTemperatureOutdoorAirNodeName, false, true);
+    }
+
+    bool ChillerElectricASHRAE205_Impl::setAmbientTemperatureOutdoorAirNodeName(const std::string& ambientTemperatureOutdoorAirNodeName) {
+      bool result = setString(OS_Chiller_Electric_ASHRAE205Fields::AmbientTemperatureOutdoorAirNodeName, ambientTemperatureOutdoorAirNodeName);
+      if (result) {
+        bool ok = setAmbientTemperatureIndicator("Outdoors");
+        OS_ASSERT(ok);
+      }
+      return result;
+    }
+
+    void ChillerElectricASHRAE205_Impl::resetAmbientTemperatureOutdoorAirNodeName() {
+      bool result = setString(OS_Chiller_Electric_ASHRAE205Fields::AmbientTemperatureOutdoorAirNodeName, "");
+      OS_ASSERT(result);
+    }
+
+    boost::optional<double> ChillerElectricASHRAE205_Impl::chilledWaterMaximumRequestedFlowRate() const {
+      return getDouble(OS_Chiller_Electric_ASHRAE205Fields::ChilledWaterMaximumRequestedFlowRate, true);
+    }
+
+    bool ChillerElectricASHRAE205_Impl::isChilledWaterMaximumRequestedFlowRateAutosized() const {
+      bool result = false;
+      boost::optional<std::string> value = getString(OS_Chiller_Electric_ASHRAE205Fields::ChilledWaterMaximumRequestedFlowRate, true);
+      if (value) {
+        result = openstudio::istringEqual(value.get(), "Autosize");
+      }
+      return result;
+    }
+
+    bool ChillerElectricASHRAE205_Impl::setChilledWaterMaximumRequestedFlowRate(double chilledWaterMaximumRequestedFlowRate) {
+      bool result = setDouble(OS_Chiller_Electric_ASHRAE205Fields::ChilledWaterMaximumRequestedFlowRate, chilledWaterMaximumRequestedFlowRate);
+      return result;
+    }
+
+    void ChillerElectricASHRAE205_Impl::autosizeChilledWaterMaximumRequestedFlowRate() {
+      bool result = setString(OS_Chiller_Electric_ASHRAE205Fields::ChilledWaterMaximumRequestedFlowRate, "Autosize");
+      OS_ASSERT(result);
+    }
+
+    boost::optional<double> ChillerElectricASHRAE205_Impl::condenserMaximumRequestedFlowRate() const {
+      return getDouble(OS_Chiller_Electric_ASHRAE205Fields::CondenserMaximumRequestedFlowRate, true);
+    }
+
+    bool ChillerElectricASHRAE205_Impl::isCondenserMaximumRequestedFlowRateAutosized() const {
+      bool result = false;
+      boost::optional<std::string> value = getString(OS_Chiller_Electric_ASHRAE205Fields::CondenserMaximumRequestedFlowRate, true);
+      if (value) {
+        result = openstudio::istringEqual(value.get(), "Autosize");
+      }
+      return result;
+    }
+
+    bool ChillerElectricASHRAE205_Impl::setCondenserMaximumRequestedFlowRate(double condenserMaximumRequestedFlowRate) {
+      bool result = setDouble(OS_Chiller_Electric_ASHRAE205Fields::CondenserMaximumRequestedFlowRate, condenserMaximumRequestedFlowRate);
+      return result;
+    }
+
+    void ChillerElectricASHRAE205_Impl::autosizeCondenserMaximumRequestedFlowRate() {
+      bool result = setString(OS_Chiller_Electric_ASHRAE205Fields::CondenserMaximumRequestedFlowRate, "Autosize");
+      OS_ASSERT(result);
+    }
+
+    std::string ChillerElectricASHRAE205_Impl::chillerFlowMode() const {
+      boost::optional<std::string> value = getString(OS_Chiller_Electric_ASHRAE205Fields::ChillerFlowMode, true);
+      OS_ASSERT(value);
+      return value.get();
+    }
+
+    bool ChillerElectricASHRAE205_Impl::setChillerFlowMode(const std::string& chillerFlowMode) {
+      bool result = setString(OS_Chiller_Electric_ASHRAE205Fields::ChillerFlowMode, chillerFlowMode);
+      return result;
+    }
+
+    boost::optional<double> ChillerElectricASHRAE205_Impl::oilCoolerDesignFlowRate() const {
+      return getDouble(OS_Chiller_Electric_ASHRAE205Fields::OilCoolerDesignFlowRate, true);
+    }
+
+    bool ChillerElectricASHRAE205_Impl::setOilCoolerDesignFlowRate(double oilCoolerDesignFlowRate) {
+      bool result = setDouble(OS_Chiller_Electric_ASHRAE205Fields::OilCoolerDesignFlowRate, oilCoolerDesignFlowRate);
+      return result;
+    }
+
+    void ChillerElectricASHRAE205_Impl::resetOilCoolerDesignFlowRate() {
+      bool result = setString(OS_Chiller_Electric_ASHRAE205Fields::OilCoolerDesignFlowRate, "");
+      OS_ASSERT(result);
+    }
+
+    boost::optional<double> ChillerElectricASHRAE205_Impl::auxiliaryCoolingDesignFlowRate() const {
+      return getDouble(OS_Chiller_Electric_ASHRAE205Fields::AuxiliaryCoolingDesignFlowRate, true);
+    }
+
+    bool ChillerElectricASHRAE205_Impl::setAuxiliaryCoolingDesignFlowRate(double auxiliaryCoolingDesignFlowRate) {
+      bool result = setDouble(OS_Chiller_Electric_ASHRAE205Fields::AuxiliaryCoolingDesignFlowRate, auxiliaryCoolingDesignFlowRate);
+      return result;
+    }
+
+    void ChillerElectricASHRAE205_Impl::resetAuxiliaryCoolingDesignFlowRate() {
+      bool result = setString(OS_Chiller_Electric_ASHRAE205Fields::AuxiliaryCoolingDesignFlowRate, "");
+      OS_ASSERT(result);
+    }
+
+    std::string ChillerElectricASHRAE205_Impl::endUseSubcategory() const {
+      boost::optional<std::string> value = getString(OS_Chiller_Electric_ASHRAE205Fields::EndUseSubcategory, true);
+      OS_ASSERT(value);
+      return value.get();
+    }
+
+    bool ChillerElectricASHRAE205_Impl::isEndUseSubcategoryDefaulted() const {
+      return isEmpty(OS_Chiller_Electric_ASHRAE205Fields::EndUseSubcategory);
+    }
+
+    bool ChillerElectricASHRAE205_Impl::setEndUseSubcategory(const std::string& endUseSubcategory) {
+      bool result = setString(OS_Chiller_Electric_ASHRAE205Fields::EndUseSubcategory, endUseSubcategory);
+      OS_ASSERT(result);
+      return result;
+    }
+
+    void ChillerElectricASHRAE205_Impl::resetEndUseSubcategory() {
+      bool result = setString(OS_Chiller_Electric_ASHRAE205Fields::EndUseSubcategory, "");
+      OS_ASSERT(result);
+    }
+
+    boost::optional<double> ChillerElectricASHRAE205_Impl::autosizedRatedCapacity() {
+      return getAutosizedValue("Design Size Rated Capacity", "W");
+    }
+
+    boost::optional<double> ChillerElectricASHRAE205_Impl::autosizedChilledWaterMaximumRequestedFlowRate() {
+      return getAutosizedValue("Design Size Chilled Water Maximum Requested Flow Rate", "m3/s");
+    }
+
+    boost::optional<double> ChillerElectricASHRAE205_Impl::autosizedCondenserMaximumRequestedFlowRate() {
+      return getAutosizedValue("Design Size Condenser Maximum Requested Flow Rate", "m3/s");
+    }
+
+    void ChillerElectricASHRAE205_Impl::autosize() {
+      autosizeRatedCapacity();
+      autosizeChilledWaterMaximumRequestedFlowRate();
+      autosizeCondenserMaximumRequestedFlowRate();
+    }
+
+    void ChillerElectricASHRAE205_Impl::applySizingValues() {
+      boost::optional<double> val;
+      val = autosizedRatedCapacity();
+      if (val) {
+        setRatedCapacity(val.get());
+      }
+
+      val = autosizedChilledWaterMaximumRequestedFlowRate();
+      if (val) {
+        setChilledWaterMaximumRequestedFlowRate(val.get());
+      }
+
+      val = autosizedCondenserMaximumRequestedFlowRate();
+      if (val) {
+        setCondenserMaximumRequestedFlowRate(val.get());
+      }
+    }
+
+    // Primary: Chiller Water
+    unsigned ChillerElectricASHRAE205_Impl::supplyInletPort() const {
+      return OS_Chiller_Electric_ASHRAE205Fields::ChilledWaterInletNodeName;
+    }
+
+    unsigned ChillerElectricASHRAE205_Impl::supplyOutletPort() const {
+      return OS_Chiller_Electric_ASHRAE205Fields::ChilledWaterOutletNodeName;
+    }
+
+    boost::optional<Node> ChillerElectricASHRAE205_Impl::chilledWaterInletNode() const {
+      if (auto mo_ = supplyInletModelObject()) {
+        return mo_->optionalCast<Node>();
+      }
+      return boost::none;
+    }
+
+    boost::optional<Node> ChillerElectricASHRAE205_Impl::chilledWaterOutletNode() const {
+      if (auto mo_ = supplyOutletModelObject()) {
+        return mo_->optionalCast<Node>();
+      }
+      return boost::none;
+    }
+
+    // Secondary: Condenser Loop
+
+    unsigned ChillerElectricASHRAE205_Impl::demandInletPort() const {
+      return OS_Chiller_Electric_ASHRAE205Fields::CondenserInletNodeName;
+    }
+
+    unsigned ChillerElectricASHRAE205_Impl::demandOutletPort() const {
+      return OS_Chiller_Electric_ASHRAE205Fields::CondenserOutletNodeName;
+    }
+
+    boost::optional<Node> ChillerElectricASHRAE205_Impl::condenserInletNode() const {
+      if (auto mo_ = demandInletModelObject()) {
+        return mo_->optionalCast<Node>();
+      }
+      return boost::none;
+    }
+
+    boost::optional<Node> ChillerElectricASHRAE205_Impl::condenserOutletNode() const {
+      if (auto mo_ = demandOutletModelObject()) {
+        return mo_->optionalCast<Node>();
+      }
+      return boost::none;
+    }
+
+    // Tertiary: Heat Recovery
+    unsigned ChillerElectricASHRAE205_Impl::tertiaryInletPort() const {
+      return OS_Chiller_Electric_ASHRAE205Fields::HeatRecoveryInletNodeName;
+    }
+
+    unsigned ChillerElectricASHRAE205_Impl::tertiaryOutletPort() const {
+      return OS_Chiller_Electric_ASHRAE205Fields::HeatRecoveryOutletNodeName;
+    }
+
+    boost::optional<Node> ChillerElectricASHRAE205_Impl::heatRecoveryInletNode() const {
+      if (auto mo_ = tertiaryInletModelObject()) {
+        return mo_->optionalCast<Node>();
+      }
+      return boost::none;
+    }
+
+    boost::optional<Node> ChillerElectricASHRAE205_Impl::heatRecoveryOutletNode() const {
+      if (auto mo_ = tertiaryOutletModelObject()) {
+        return mo_->optionalCast<Node>();
+      }
+      return boost::none;
+    }
+
+    bool ChillerElectricASHRAE205_Impl::addToNode(Node& node) {
+      boost::optional<PlantLoop> t_plantLoop = node.plantLoop();
+
+      // If trying to add to a node that is on the demand side of a plant loop
+      if (t_plantLoop) {
+        if (t_plantLoop->demandComponent(node.handle())) {
+          // If there is already a another loop where it's on the demand side (condenser Plant Loop)
+          boost::optional<PlantLoop> cndLoop_ = this->condenserWaterLoop();
+          if (cndLoop_) {
+            // And it's not the same as the node's loop
+            if (t_plantLoop.get() != cndLoop_.get()) {
+              // And if there is no Heat Recovery (tertiary)
+              if (!this->heatRecoveryLoop().is_initialized()) {
+                // Then try to add it to the tertiary one
+                LOG(Warn, "Calling addToTertiaryNode to connect it to the tertiary (=Heat Recovery) loop for " << briefDescription());
+                return this->addToTertiaryNode(node);
+              }
+            }
+          }
+        }
+      }
+
+      // All other cases, call the base class implementation
+      return WaterToWaterComponent_Impl::addToNode(node);
+    }
+
+    bool ChillerElectricASHRAE205_Impl::addToTertiaryNode(Node& node) {
+
+      if constexpr (!ChillerElectricASHRAE205::isHeatRecoverySupportedByEnergyplus) {
+        LOG(Warn, "For " << briefDescription() << ", Heat Recovery isn't implemented by EnergyPlus yet, so tertiary connection is disabled.");
+        return false;
+      }
+
+      auto t_plantLoop = node.plantLoop();
+
+      // Only accept adding to a node that is on a demand side of a plant loop
+      // Since tertiary here = heat recovery loop (heating)
+      if (t_plantLoop) {
+        if (t_plantLoop->demandComponent(node.handle())) {
+          // Call base class method which accepts both supply and demand
+          return WaterToWaterComponent_Impl::addToTertiaryNode(node);
+        } else {
+          LOG(Info,
+              "Tertiary Loop (Heat Recovery Loop) connections can only be placed on the Demand side (of a Heating Loop), for " << briefDescription());
+        }
+      }
+      return false;
+    }
+
+    std::vector<HVACComponent> ChillerElectricASHRAE205_Impl::edges(const boost::optional<HVACComponent>& prev) {
+      // This handles supply, demand, and tertiary connections
+      std::vector<HVACComponent> edges = WaterToWaterComponent_Impl::edges(prev);
+
+      auto pushOilCoolerOutletModelObject = [&]() {
+        if (auto edgeModelObject = oilCoolerOutletModelObject()) {
+          auto edgeHVACComponent = edgeModelObject->optionalCast<HVACComponent>();
+          OS_ASSERT(edgeHVACComponent);
+          edges.push_back(edgeHVACComponent.get());
+        }
+      };
+
+      auto pushAuxiliaryOutletModelObject = [&]() {
+        if (auto edgeModelObject = auxiliaryOutletModelObject()) {
+          auto edgeHVACComponent = edgeModelObject->optionalCast<HVACComponent>();
+          OS_ASSERT(edgeHVACComponent);
+          edges.push_back(edgeHVACComponent.get());
+        }
+      };
+
+      if (prev) {
+        if (auto inletModelObject = oilCoolerInletModelObject()) {
+          if (prev.get() == inletModelObject.get()) {
+            pushOilCoolerOutletModelObject();
+            return edges;
+          }
+        }
+        if (auto inletModelObject = auxiliaryInletModelObject()) {
+          if (prev.get() == inletModelObject.get()) {
+            pushAuxiliaryOutletModelObject();
+            return edges;
+          }
+        }
+      } else {
+        pushOilCoolerOutletModelObject();
+        pushAuxiliaryOutletModelObject();
+        return edges;
+      }
+
+      return edges;
+    }
+
+    boost::optional<PlantLoop> ChillerElectricASHRAE205_Impl::plantLoop() const {
+      if (boost::optional<ModelObject> mo_ = supplyOutletModelObject()) {
+        if (boost::optional<Node> n_ = mo_->optionalCast<Node>()) {
+          return n_->plantLoop();
+        }
+      }
+      return boost::none;
+    }
+
+    boost::optional<PlantLoop> ChillerElectricASHRAE205_Impl::secondaryPlantLoop() const {
+      if (boost::optional<ModelObject> mo_ = demandOutletModelObject()) {
+        if (boost::optional<Node> n_ = mo_->optionalCast<Node>()) {
+          return n_->plantLoop();
+        }
+      }
+      return boost::none;
+    }
+
+    boost::optional<PlantLoop> ChillerElectricASHRAE205_Impl::tertiaryPlantLoop() const {
+      if (boost::optional<ModelObject> mo_ = tertiaryOutletModelObject()) {
+        if (boost::optional<Node> n_ = mo_->optionalCast<Node>()) {
+          return n_->plantLoop();
+        }
+      }
+      return boost::none;
+    }
+
+    boost::optional<PlantLoop> ChillerElectricASHRAE205_Impl::chilledWaterLoop() const {
+      return plantLoop();
+    }
+
+    boost::optional<PlantLoop> ChillerElectricASHRAE205_Impl::condenserWaterLoop() const {
+      return secondaryPlantLoop();
+    }
+    boost::optional<PlantLoop> ChillerElectricASHRAE205_Impl::heatRecoveryLoop() const {
+      return tertiaryPlantLoop();
+    }
+
+    // Extra loops
+
+    /// Oil Cooler Loop
+
+    unsigned ChillerElectricASHRAE205_Impl::oilCoolerInletPort() const {
+      return OS_Chiller_Electric_ASHRAE205Fields::OilCoolerInletNodeName;
+    }
+
+    OptionalModelObject ChillerElectricASHRAE205_Impl::oilCoolerInletModelObject() const {
+      return connectedObject(ChillerElectricASHRAE205_Impl::oilCoolerInletPort());
+    }
+
+    boost::optional<Node> ChillerElectricASHRAE205_Impl::oilCoolerInletNode() const {
+      if (auto mo_ = oilCoolerInletModelObject()) {
+        return mo_->optionalCast<Node>();
+      }
+      return boost::none;
+    }
+
+    unsigned ChillerElectricASHRAE205_Impl::oilCoolerOutletPort() const {
+      return OS_Chiller_Electric_ASHRAE205Fields::OilCoolerOutletNodeName;
+    }
+
+    OptionalModelObject ChillerElectricASHRAE205_Impl::oilCoolerOutletModelObject() const {
+      return connectedObject(ChillerElectricASHRAE205_Impl::oilCoolerOutletPort());
+    }
+
+    boost::optional<Node> ChillerElectricASHRAE205_Impl::oilCoolerOutletNode() const {
+      if (auto mo_ = oilCoolerOutletModelObject()) {
+        return mo_->optionalCast<Node>();
+      }
+      return boost::none;
+    }
+
+    boost::optional<PlantLoop> ChillerElectricASHRAE205_Impl::oilCoolerLoop() const {
+      if (boost::optional<Node> n_ = oilCoolerOutletNode()) {
+        return n_->plantLoop();
+      }
+      return boost::none;
+    }
+
+    bool ChillerElectricASHRAE205_Impl::removeFromOilCoolerLoop() {
+      if (auto plant = oilCoolerLoop()) {
+        return HVACComponent_Impl::removeFromLoop(plant->demandInletNode(), plant->demandOutletNode(), oilCoolerInletPort(), oilCoolerOutletPort());
+      }
+
+      return false;
+    }
+
+    bool ChillerElectricASHRAE205_Impl::addDemandBranchOnOilCoolerLoop(PlantLoop& plantLoop) {
+      Model _model = this->model();
+
+      if (plantLoop.model() != _model) {
+        return false;
+      }
+
+      Splitter splitter = plantLoop.demandSplitter();
+      Mixer mixer = plantLoop.demandMixer();
+
+      if (splitter.outletModelObjects().size() == 1u) {
+        if (boost::optional<ModelObject> mo = splitter.lastOutletModelObject()) {
+          if (boost::optional<Node> node = mo->optionalCast<Node>()) {
+            if ((node->outletModelObject().get() == mixer) && (node->inletModelObject().get() == splitter)) {
+
+              return addToOilCoolerLoopNode(node.get());
+            }
+          }
+        }
+      }
+
+      unsigned nextOutletPort = splitter.nextOutletPort();
+      unsigned nextInletPort = mixer.nextInletPort();
+
+      Node node(_model);
+
+      _model.connect(splitter, nextOutletPort, node, node.inletPort());
+      _model.connect(node, node.outletPort(), mixer, nextInletPort);
+
+      if (addToOilCoolerLoopNode(node)) {
+        return true;
+      }
+
+      _model.disconnect(node, node.outletPort());
+      _model.disconnect(node, node.inletPort());
+      node.remove();
+
+      return false;
+    }
+
+    bool ChillerElectricASHRAE205_Impl::addToOilCoolerLoopNode(Node& node) {
+
+      // One of the example files actually has the Oil Coiler and Auxiliary nodes in series on the same branch...
+      // But this would require a bunch of changes to allow a component to be twice on the same branch, so I'm not allowing it
+      if (node.getImpl<Node_Impl>()->isConnected(getObject<ModelObject>())) {
+        // if ((oilCoolerInletNode() && (node.handle() == oilCoolerInletNode()->handle()))
+        //     || (oilCoolerOutletNode() && (node.handle() == oilCoolerOutletNode()->handle()))) {
+        return false;
+      }
+
+      auto plantLoop_ = node.plantLoop();
+      if (!plantLoop_) {
+        LOG(Warn, "For " << briefDescription() << ", Oil Cooler Loop can only be connected to a PlantLoop");
+        return false;
+      }
+
+      if (!plantLoop_->demandComponent(node.handle())) {
+        LOG(Warn, "For " << briefDescription() << ", Oil Cooler Loop can only be connected to a PlantLoop on the demand side");
+        return false;
+      }
+
+      HVACComponent systemStartComponent = plantLoop_->demandInletNode();
+      HVACComponent systemEndComponent = plantLoop_->demandOutletNode();
+
+      removeFromOilCoolerLoop();
+
+      return HVACComponent_Impl::addToNode(node, systemStartComponent, systemEndComponent, oilCoolerInletPort(), oilCoolerOutletPort());
+    }
+
+    /// Auxiliary Loop
+
+    unsigned ChillerElectricASHRAE205_Impl::auxiliaryInletPort() const {
+      return OS_Chiller_Electric_ASHRAE205Fields::AuxiliaryInletNodeName;
+    }
+
+    OptionalModelObject ChillerElectricASHRAE205_Impl::auxiliaryInletModelObject() const {
+      return connectedObject(ChillerElectricASHRAE205_Impl::auxiliaryInletPort());
+    }
+
+    boost::optional<Node> ChillerElectricASHRAE205_Impl::auxiliaryInletNode() const {
+      if (auto mo_ = auxiliaryInletModelObject()) {
+        return mo_->optionalCast<Node>();
+      }
+      return boost::none;
+    }
+
+    unsigned ChillerElectricASHRAE205_Impl::auxiliaryOutletPort() const {
+      return OS_Chiller_Electric_ASHRAE205Fields::AuxiliaryOutletNodeName;
+    }
+
+    OptionalModelObject ChillerElectricASHRAE205_Impl::auxiliaryOutletModelObject() const {
+      return connectedObject(ChillerElectricASHRAE205_Impl::auxiliaryOutletPort());
+    }
+
+    boost::optional<Node> ChillerElectricASHRAE205_Impl::auxiliaryOutletNode() const {
+      if (auto mo_ = auxiliaryOutletModelObject()) {
+        return mo_->optionalCast<Node>();
+      }
+      return boost::none;
+    }
+
+    boost::optional<PlantLoop> ChillerElectricASHRAE205_Impl::auxiliaryLoop() const {
+      if (boost::optional<Node> n_ = auxiliaryOutletNode()) {
+        return n_->plantLoop();
+      }
+      return boost::none;
+    }
+
+    bool ChillerElectricASHRAE205_Impl::removeFromAuxiliaryLoop() {
+      if (auto plant = auxiliaryLoop()) {
+        return HVACComponent_Impl::removeFromLoop(plant->demandInletNode(), plant->demandOutletNode(), auxiliaryInletPort(), auxiliaryOutletPort());
+      }
+
+      return false;
+    }
+
+    bool ChillerElectricASHRAE205_Impl::addDemandBranchOnAuxiliaryLoop(PlantLoop& plantLoop) {
+      Model _model = this->model();
+
+      if (plantLoop.model() != _model) {
+        return false;
+      }
+
+      Splitter splitter = plantLoop.demandSplitter();
+      Mixer mixer = plantLoop.demandMixer();
+
+      if (splitter.outletModelObjects().size() == 1u) {
+        if (boost::optional<ModelObject> mo = splitter.lastOutletModelObject()) {
+          if (boost::optional<Node> node = mo->optionalCast<Node>()) {
+            if ((node->outletModelObject().get() == mixer) && (node->inletModelObject().get() == splitter)) {
+
+              return addToAuxiliaryLoopNode(node.get());
+            }
+          }
+        }
+      }
+
+      unsigned nextOutletPort = splitter.nextOutletPort();
+      unsigned nextInletPort = mixer.nextInletPort();
+
+      Node node(_model);
+
+      _model.connect(splitter, nextOutletPort, node, node.inletPort());
+      _model.connect(node, node.outletPort(), mixer, nextInletPort);
+
+      if (addToAuxiliaryLoopNode(node)) {
+        return true;
+      }
+
+      _model.disconnect(node, node.outletPort());
+      _model.disconnect(node, node.inletPort());
+      node.remove();
+
+      return false;
+    }
+
+    bool ChillerElectricASHRAE205_Impl::addToAuxiliaryLoopNode(Node& node) {
+
+      // One of the example files actually has the Oil Coiler and Auxiliary nodes in series on the same branch...
+      // But this would require a bunch of changes to allow a component to be twice on the same branch, so I'm not allowing it
+      if (node.getImpl<Node_Impl>()->isConnected(getObject<ModelObject>())) {
+        // if ((auxiliaryInletNode() && (node.handle() == auxiliaryInletNode()->handle()))
+        //     || (auxiliaryOutletNode() && (node.handle() == auxiliaryOutletNode()->handle()))) {
+        return false;
+      }
+
+      auto plantLoop_ = node.plantLoop();
+      if (!plantLoop_) {
+        LOG(Warn, "For " << briefDescription() << ", Oil Cooler Loop can only be connected to a PlantLoop");
+        return false;
+      }
+
+      if (!plantLoop_->demandComponent(node.handle())) {
+        LOG(Warn, "For " << briefDescription() << ", Oil Cooler Loop can only be connected to a PlantLoop on the demand side");
+        return false;
+      }
+
+      HVACComponent systemStartComponent = plantLoop_->demandInletNode();
+      HVACComponent systemEndComponent = plantLoop_->demandOutletNode();
+
+      removeFromAuxiliaryLoop();
+
+      return HVACComponent_Impl::addToNode(node, systemStartComponent, systemEndComponent, auxiliaryInletPort(), auxiliaryOutletPort());
+    }
+
+    ModelObject ChillerElectricASHRAE205_Impl::clone(Model model) const {
+      // WaterToWaterComponent resets the supply, demand and tertiary ports
+      auto mo = WaterToWaterComponent_Impl::clone(model);
+
+      mo.setString(oilCoolerInletPort(), "");
+      mo.setString(oilCoolerOutletPort(), "");
+      mo.setString(auxiliaryInletPort(), "");
+      mo.setString(auxiliaryOutletPort(), "");
+      return mo;
+    }
+
+  }  // namespace detail
+
+  ChillerElectricASHRAE205::ChillerElectricASHRAE205(const ExternalFile& representationFile)
+    : WaterToWaterComponent(ChillerElectricASHRAE205::iddObjectType(), representationFile.model()) {
+    OS_ASSERT(getImpl<detail::ChillerElectricASHRAE205_Impl>());
+
+    auto filePath = representationFile.filePath();
+    bool ok = (toString(filePath.extension()) == ".cbor");
+    if (!ok) {
+      remove();
+      LOG_AND_THROW("External file must have a .cbor extension, got externalfile='" << filePath << "'.");
+    }
+    ok = setPointer(OS_Chiller_Electric_ASHRAE205Fields::RepresentationFileName, representationFile.handle());
+    OS_ASSERT(ok);
+
+    setPerformanceInterpolationMethod("Linear");
+    autosizeRatedCapacity();
+    setSizingFactor(1.0);
+    getImpl<detail::ChillerElectricASHRAE205_Impl>()->setAmbientTemperatureIndicator("Outdoors");
+    autosizeChilledWaterMaximumRequestedFlowRate();
+    autosizeCondenserMaximumRequestedFlowRate();
+    setChillerFlowMode("NotModulated");
+    setEndUseSubcategory("General");
+  }
+
+  IddObjectType ChillerElectricASHRAE205::iddObjectType() {
+    return {IddObjectType::OS_Chiller_Electric_ASHRAE205};
+  }
+
+  std::vector<std::string> ChillerElectricASHRAE205::performanceInterpolationMethodValues() {
+    return getIddKeyNames(IddFactory::instance().getObject(iddObjectType()).get(),
+                          OS_Chiller_Electric_ASHRAE205Fields::PerformanceInterpolationMethod);
+  }
+
+  std::vector<std::string> ChillerElectricASHRAE205::ambientTemperatureIndicatorValues() {
+    return getIddKeyNames(IddFactory::instance().getObject(iddObjectType()).get(), OS_Chiller_Electric_ASHRAE205Fields::AmbientTemperatureIndicator);
+  }
+
+  std::vector<std::string> ChillerElectricASHRAE205::chillerFlowModeValues() {
+    return getIddKeyNames(IddFactory::instance().getObject(iddObjectType()).get(), OS_Chiller_Electric_ASHRAE205Fields::ChillerFlowMode);
+  }
+
+  ExternalFile ChillerElectricASHRAE205::representationFile() const {
+    return getImpl<detail::ChillerElectricASHRAE205_Impl>()->representationFile();
+  }
+
+  std::string ChillerElectricASHRAE205::performanceInterpolationMethod() const {
+    return getImpl<detail::ChillerElectricASHRAE205_Impl>()->performanceInterpolationMethod();
+  }
+
+  boost::optional<double> ChillerElectricASHRAE205::ratedCapacity() const {
+    return getImpl<detail::ChillerElectricASHRAE205_Impl>()->ratedCapacity();
+  }
+
+  bool ChillerElectricASHRAE205::isRatedCapacityAutosized() const {
+    return getImpl<detail::ChillerElectricASHRAE205_Impl>()->isRatedCapacityAutosized();
+  }
+
+  boost::optional<double> ChillerElectricASHRAE205::autosizedRatedCapacity() {
+    return getImpl<detail::ChillerElectricASHRAE205_Impl>()->autosizedRatedCapacity();
+  }
+
+  double ChillerElectricASHRAE205::sizingFactor() const {
+    return getImpl<detail::ChillerElectricASHRAE205_Impl>()->sizingFactor();
+  }
+
+  std::string ChillerElectricASHRAE205::ambientTemperatureIndicator() const {
+    return getImpl<detail::ChillerElectricASHRAE205_Impl>()->ambientTemperatureIndicator();
+  }
+
+  boost::optional<Schedule> ChillerElectricASHRAE205::ambientTemperatureSchedule() const {
+    return getImpl<detail::ChillerElectricASHRAE205_Impl>()->ambientTemperatureSchedule();
+  }
+
+  boost::optional<ThermalZone> ChillerElectricASHRAE205::ambientTemperatureZone() const {
+    return getImpl<detail::ChillerElectricASHRAE205_Impl>()->ambientTemperatureZone();
+  }
+
+  boost::optional<std::string> ChillerElectricASHRAE205::ambientTemperatureOutdoorAirNodeName() const {
+    return getImpl<detail::ChillerElectricASHRAE205_Impl>()->ambientTemperatureOutdoorAirNodeName();
+  }
+
+  boost::optional<double> ChillerElectricASHRAE205::chilledWaterMaximumRequestedFlowRate() const {
+    return getImpl<detail::ChillerElectricASHRAE205_Impl>()->chilledWaterMaximumRequestedFlowRate();
+  }
+
+  bool ChillerElectricASHRAE205::isChilledWaterMaximumRequestedFlowRateAutosized() const {
+    return getImpl<detail::ChillerElectricASHRAE205_Impl>()->isChilledWaterMaximumRequestedFlowRateAutosized();
+  }
+
+  boost::optional<double> ChillerElectricASHRAE205::autosizedChilledWaterMaximumRequestedFlowRate() {
+    return getImpl<detail::ChillerElectricASHRAE205_Impl>()->autosizedChilledWaterMaximumRequestedFlowRate();
+  }
+
+  boost::optional<double> ChillerElectricASHRAE205::condenserMaximumRequestedFlowRate() const {
+    return getImpl<detail::ChillerElectricASHRAE205_Impl>()->condenserMaximumRequestedFlowRate();
+  }
+
+  bool ChillerElectricASHRAE205::isCondenserMaximumRequestedFlowRateAutosized() const {
+    return getImpl<detail::ChillerElectricASHRAE205_Impl>()->isCondenserMaximumRequestedFlowRateAutosized();
+  }
+
+  boost::optional<double> ChillerElectricASHRAE205::autosizedCondenserMaximumRequestedFlowRate() {
+    return getImpl<detail::ChillerElectricASHRAE205_Impl>()->autosizedCondenserMaximumRequestedFlowRate();
+  }
+
+  std::string ChillerElectricASHRAE205::chillerFlowMode() const {
+    return getImpl<detail::ChillerElectricASHRAE205_Impl>()->chillerFlowMode();
+  }
+
+  boost::optional<double> ChillerElectricASHRAE205::oilCoolerDesignFlowRate() const {
+    return getImpl<detail::ChillerElectricASHRAE205_Impl>()->oilCoolerDesignFlowRate();
+  }
+
+  boost::optional<double> ChillerElectricASHRAE205::auxiliaryCoolingDesignFlowRate() const {
+    return getImpl<detail::ChillerElectricASHRAE205_Impl>()->auxiliaryCoolingDesignFlowRate();
+  }
+
+  std::string ChillerElectricASHRAE205::endUseSubcategory() const {
+    return getImpl<detail::ChillerElectricASHRAE205_Impl>()->endUseSubcategory();
+  }
+
+  bool ChillerElectricASHRAE205::isEndUseSubcategoryDefaulted() const {
+    return getImpl<detail::ChillerElectricASHRAE205_Impl>()->isEndUseSubcategoryDefaulted();
+  }
+
+  bool ChillerElectricASHRAE205::setRepresentationFile(const ExternalFile& externalFile) {
+    return getImpl<detail::ChillerElectricASHRAE205_Impl>()->setRepresentationFile(externalFile);
+  }
+
+  bool ChillerElectricASHRAE205::setPerformanceInterpolationMethod(const std::string& performanceInterpolationMethod) {
+    return getImpl<detail::ChillerElectricASHRAE205_Impl>()->setPerformanceInterpolationMethod(performanceInterpolationMethod);
+  }
+
+  bool ChillerElectricASHRAE205::setRatedCapacity(double ratedCapacity) {
+    return getImpl<detail::ChillerElectricASHRAE205_Impl>()->setRatedCapacity(ratedCapacity);
+  }
+
+  void ChillerElectricASHRAE205::autosizeRatedCapacity() {
+    getImpl<detail::ChillerElectricASHRAE205_Impl>()->autosizeRatedCapacity();
+  }
+
+  bool ChillerElectricASHRAE205::setSizingFactor(double sizingFactor) {
+    return getImpl<detail::ChillerElectricASHRAE205_Impl>()->setSizingFactor(sizingFactor);
+  }
+
+  // Done via the other setAmbientXXX
+  // bool ChillerElectricASHRAE205::setAmbientTemperatureIndicator(const std::string& ambientTemperatureIndicator) {
+  //   return getImpl<detail::ChillerElectricASHRAE205_Impl>()->setAmbientTemperatureIndicator(ambientTemperatureIndicator);
+  // }
+
+  bool ChillerElectricASHRAE205::setAmbientTemperatureSchedule(Schedule& schedule) {
+    return getImpl<detail::ChillerElectricASHRAE205_Impl>()->setAmbientTemperatureSchedule(schedule);
+  }
+
+  void ChillerElectricASHRAE205::resetAmbientTemperatureSchedule() {
+    getImpl<detail::ChillerElectricASHRAE205_Impl>()->resetAmbientTemperatureSchedule();
+  }
+
+  bool ChillerElectricASHRAE205::setAmbientTemperatureZone(const ThermalZone& thermalZone) {
+    return getImpl<detail::ChillerElectricASHRAE205_Impl>()->setAmbientTemperatureZone(thermalZone);
+  }
+
+  void ChillerElectricASHRAE205::resetAmbientTemperatureZone() {
+    getImpl<detail::ChillerElectricASHRAE205_Impl>()->resetAmbientTemperatureZone();
+  }
+
+  bool ChillerElectricASHRAE205::setAmbientTemperatureOutdoorAirNodeName(const std::string& ambientTemperatureOutdoorAirNodeName) {
+    return getImpl<detail::ChillerElectricASHRAE205_Impl>()->setAmbientTemperatureOutdoorAirNodeName(ambientTemperatureOutdoorAirNodeName);
+  }
+
+  void ChillerElectricASHRAE205::resetAmbientTemperatureOutdoorAirNodeName() {
+    getImpl<detail::ChillerElectricASHRAE205_Impl>()->resetAmbientTemperatureOutdoorAirNodeName();
+  }
+
+  bool ChillerElectricASHRAE205::setChilledWaterMaximumRequestedFlowRate(double chilledWaterMaximumRequestedFlowRate) {
+    return getImpl<detail::ChillerElectricASHRAE205_Impl>()->setChilledWaterMaximumRequestedFlowRate(chilledWaterMaximumRequestedFlowRate);
+  }
+
+  void ChillerElectricASHRAE205::autosizeChilledWaterMaximumRequestedFlowRate() {
+    getImpl<detail::ChillerElectricASHRAE205_Impl>()->autosizeChilledWaterMaximumRequestedFlowRate();
+  }
+
+  bool ChillerElectricASHRAE205::setCondenserMaximumRequestedFlowRate(double condenserMaximumRequestedFlowRate) {
+    return getImpl<detail::ChillerElectricASHRAE205_Impl>()->setCondenserMaximumRequestedFlowRate(condenserMaximumRequestedFlowRate);
+  }
+
+  void ChillerElectricASHRAE205::autosizeCondenserMaximumRequestedFlowRate() {
+    getImpl<detail::ChillerElectricASHRAE205_Impl>()->autosizeCondenserMaximumRequestedFlowRate();
+  }
+
+  bool ChillerElectricASHRAE205::setChillerFlowMode(const std::string& chillerFlowMode) {
+    return getImpl<detail::ChillerElectricASHRAE205_Impl>()->setChillerFlowMode(chillerFlowMode);
+  }
+
+  bool ChillerElectricASHRAE205::setOilCoolerDesignFlowRate(double oilCoolerDesignFlowRate) {
+    return getImpl<detail::ChillerElectricASHRAE205_Impl>()->setOilCoolerDesignFlowRate(oilCoolerDesignFlowRate);
+  }
+
+  void ChillerElectricASHRAE205::resetOilCoolerDesignFlowRate() {
+    getImpl<detail::ChillerElectricASHRAE205_Impl>()->resetOilCoolerDesignFlowRate();
+  }
+
+  bool ChillerElectricASHRAE205::setAuxiliaryCoolingDesignFlowRate(double auxiliaryCoolingDesignFlowRate) {
+    return getImpl<detail::ChillerElectricASHRAE205_Impl>()->setAuxiliaryCoolingDesignFlowRate(auxiliaryCoolingDesignFlowRate);
+  }
+
+  void ChillerElectricASHRAE205::resetAuxiliaryCoolingDesignFlowRate() {
+    getImpl<detail::ChillerElectricASHRAE205_Impl>()->resetAuxiliaryCoolingDesignFlowRate();
+  }
+
+  bool ChillerElectricASHRAE205::setEndUseSubcategory(const std::string& endUseSubcategory) {
+    return getImpl<detail::ChillerElectricASHRAE205_Impl>()->setEndUseSubcategory(endUseSubcategory);
+  }
+
+  void ChillerElectricASHRAE205::resetEndUseSubcategory() {
+    getImpl<detail::ChillerElectricASHRAE205_Impl>()->resetEndUseSubcategory();
+  }
+
+  // Convenience getters
+
+  boost::optional<PlantLoop> ChillerElectricASHRAE205::chilledWaterLoop() const {
+    return getImpl<detail::ChillerElectricASHRAE205_Impl>()->chilledWaterLoop();
+  }
+
+  boost::optional<Node> ChillerElectricASHRAE205::chilledWaterInletNode() const {
+    return getImpl<detail::ChillerElectricASHRAE205_Impl>()->chilledWaterInletNode();
+  }
+
+  boost::optional<Node> ChillerElectricASHRAE205::chilledWaterOutletNode() const {
+    return getImpl<detail::ChillerElectricASHRAE205_Impl>()->chilledWaterOutletNode();
+  }
+
+  boost::optional<PlantLoop> ChillerElectricASHRAE205::condenserWaterLoop() const {
+    return getImpl<detail::ChillerElectricASHRAE205_Impl>()->condenserWaterLoop();
+  }
+
+  boost::optional<Node> ChillerElectricASHRAE205::condenserInletNode() const {
+    return getImpl<detail::ChillerElectricASHRAE205_Impl>()->condenserInletNode();
+  }
+
+  boost::optional<Node> ChillerElectricASHRAE205::condenserOutletNode() const {
+    return getImpl<detail::ChillerElectricASHRAE205_Impl>()->condenserOutletNode();
+  }
+
+  boost::optional<PlantLoop> ChillerElectricASHRAE205::heatRecoveryLoop() const {
+    return getImpl<detail::ChillerElectricASHRAE205_Impl>()->heatRecoveryLoop();
+  }
+
+  boost::optional<Node> ChillerElectricASHRAE205::heatRecoveryInletNode() const {
+    return getImpl<detail::ChillerElectricASHRAE205_Impl>()->heatRecoveryInletNode();
+  }
+
+  boost::optional<Node> ChillerElectricASHRAE205::heatRecoveryOutletNode() const {
+    return getImpl<detail::ChillerElectricASHRAE205_Impl>()->heatRecoveryOutletNode();
+  }
+
+  // Oil Cooler Loop
+
+  unsigned ChillerElectricASHRAE205::oilCoolerInletPort() const {
+    return getImpl<detail::ChillerElectricASHRAE205_Impl>()->oilCoolerInletPort();
+  }
+  boost::optional<ModelObject> ChillerElectricASHRAE205::oilCoolerInletModelObject() const {
+    return getImpl<detail::ChillerElectricASHRAE205_Impl>()->oilCoolerInletModelObject();
+  }
+  boost::optional<Node> ChillerElectricASHRAE205::oilCoolerInletNode() const {
+    return getImpl<detail::ChillerElectricASHRAE205_Impl>()->oilCoolerInletNode();
+  }
+
+  unsigned ChillerElectricASHRAE205::oilCoolerOutletPort() const {
+    return getImpl<detail::ChillerElectricASHRAE205_Impl>()->oilCoolerOutletPort();
+  }
+  boost::optional<ModelObject> ChillerElectricASHRAE205::oilCoolerOutletModelObject() const {
+    return getImpl<detail::ChillerElectricASHRAE205_Impl>()->oilCoolerOutletModelObject();
+  }
+  boost::optional<Node> ChillerElectricASHRAE205::oilCoolerOutletNode() const {
+    return getImpl<detail::ChillerElectricASHRAE205_Impl>()->oilCoolerOutletNode();
+  }
+
+  boost::optional<PlantLoop> ChillerElectricASHRAE205::oilCoolerLoop() const {
+    return getImpl<detail::ChillerElectricASHRAE205_Impl>()->oilCoolerLoop();
+  }
+
+  bool ChillerElectricASHRAE205::addDemandBranchOnOilCoolerLoop(PlantLoop& plantLoop) {
+    return getImpl<detail::ChillerElectricASHRAE205_Impl>()->addDemandBranchOnOilCoolerLoop(plantLoop);
+  }
+
+  bool ChillerElectricASHRAE205::addToOilCoolerLoopNode(Node& node) {
+    return getImpl<detail::ChillerElectricASHRAE205_Impl>()->addToOilCoolerLoopNode(node);
+  }
+
+  bool ChillerElectricASHRAE205::removeFromOilCoolerLoop() {
+    return getImpl<detail::ChillerElectricASHRAE205_Impl>()->removeFromOilCoolerLoop();
+  }
+
+  // Auxiliary Loop
+
+  unsigned ChillerElectricASHRAE205::auxiliaryInletPort() const {
+    return getImpl<detail::ChillerElectricASHRAE205_Impl>()->auxiliaryInletPort();
+  }
+  boost::optional<ModelObject> ChillerElectricASHRAE205::auxiliaryInletModelObject() const {
+    return getImpl<detail::ChillerElectricASHRAE205_Impl>()->auxiliaryInletModelObject();
+  }
+  boost::optional<Node> ChillerElectricASHRAE205::auxiliaryInletNode() const {
+    return getImpl<detail::ChillerElectricASHRAE205_Impl>()->auxiliaryInletNode();
+  }
+
+  unsigned ChillerElectricASHRAE205::auxiliaryOutletPort() const {
+    return getImpl<detail::ChillerElectricASHRAE205_Impl>()->auxiliaryOutletPort();
+  }
+  boost::optional<ModelObject> ChillerElectricASHRAE205::auxiliaryOutletModelObject() const {
+    return getImpl<detail::ChillerElectricASHRAE205_Impl>()->auxiliaryOutletModelObject();
+  }
+  boost::optional<Node> ChillerElectricASHRAE205::auxiliaryOutletNode() const {
+    return getImpl<detail::ChillerElectricASHRAE205_Impl>()->auxiliaryOutletNode();
+  }
+
+  boost::optional<PlantLoop> ChillerElectricASHRAE205::auxiliaryLoop() const {
+    return getImpl<detail::ChillerElectricASHRAE205_Impl>()->auxiliaryLoop();
+  }
+
+  bool ChillerElectricASHRAE205::addDemandBranchOnAuxiliaryLoop(PlantLoop& plantLoop) {
+    return getImpl<detail::ChillerElectricASHRAE205_Impl>()->addDemandBranchOnAuxiliaryLoop(plantLoop);
+  }
+
+  bool ChillerElectricASHRAE205::addToAuxiliaryLoopNode(Node& node) {
+    return getImpl<detail::ChillerElectricASHRAE205_Impl>()->addToAuxiliaryLoopNode(node);
+  }
+
+  bool ChillerElectricASHRAE205::removeFromAuxiliaryLoop() {
+    return getImpl<detail::ChillerElectricASHRAE205_Impl>()->removeFromAuxiliaryLoop();
+  }
+
+  /// @cond
+  ChillerElectricASHRAE205::ChillerElectricASHRAE205(std::shared_ptr<detail::ChillerElectricASHRAE205_Impl> impl)
+    : WaterToWaterComponent(std::move(impl)) {}
+  /// @endcond
+
+}  // namespace model
+}  // namespace openstudio
diff --git a/src/model/ChillerElectricASHRAE205.hpp b/src/model/ChillerElectricASHRAE205.hpp
new file mode 100644
index 00000000000..396f376c9d3
--- /dev/null
+++ b/src/model/ChillerElectricASHRAE205.hpp
@@ -0,0 +1,231 @@
+/***********************************************************************************************************************
+*  OpenStudio(R), Copyright (c) 2008-2022, 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.
+***********************************************************************************************************************/
+
+#ifndef MODEL_CHILLERELECTRICASHRAE205_HPP
+#define MODEL_CHILLERELECTRICASHRAE205_HPP
+
+#include <model/ModelAPI.hpp>
+#include "WaterToWaterComponent.hpp"
+
+namespace openstudio {
+
+namespace model {
+
+  class ExternalFile;
+  class Node;
+  class ThermalZone;
+  class Schedule;
+
+  namespace detail {
+
+    class ChillerElectricASHRAE205_Impl;
+
+  }  // namespace detail
+
+  /** ChillerElectricASHRAE205 is a WaterToWaterComponent that wraps the OpenStudio IDD object 'OS:Chiller:Electric:ASHRAE205'. */
+  class MODEL_API ChillerElectricASHRAE205 : public WaterToWaterComponent
+  {
+   public:
+    /** @name Constructors and Destructors */
+    //@{
+
+    explicit ChillerElectricASHRAE205(const ExternalFile& representationFile);
+
+    virtual ~ChillerElectricASHRAE205() = default;
+
+    // TODO: once supported by E+, re-enable
+    static constexpr bool isHeatRecoverySupportedByEnergyplus = false;
+
+    //@}
+
+    static IddObjectType iddObjectType();
+
+    static std::vector<std::string> performanceInterpolationMethodValues();
+
+    static std::vector<std::string> ambientTemperatureIndicatorValues();
+
+    static std::vector<std::string> chillerFlowModeValues();
+
+    /** @name Getters */
+    //@{
+
+    ExternalFile representationFile() const;
+
+    std::string performanceInterpolationMethod() const;
+
+    boost::optional<double> ratedCapacity() const;
+    bool isRatedCapacityAutosized() const;
+
+    double sizingFactor() const;
+
+    std::string ambientTemperatureIndicator() const;
+
+    boost::optional<Schedule> ambientTemperatureSchedule() const;
+
+    boost::optional<ThermalZone> ambientTemperatureZone() const;
+
+    boost::optional<std::string> ambientTemperatureOutdoorAirNodeName() const;
+
+    boost::optional<double> chilledWaterMaximumRequestedFlowRate() const;
+    bool isChilledWaterMaximumRequestedFlowRateAutosized() const;
+
+    boost::optional<double> condenserMaximumRequestedFlowRate() const;
+    bool isCondenserMaximumRequestedFlowRateAutosized() const;
+
+    std::string chillerFlowMode() const;
+
+    boost::optional<double> oilCoolerDesignFlowRate() const;
+
+    boost::optional<double> auxiliaryCoolingDesignFlowRate() const;
+
+    std::string endUseSubcategory() const;
+    bool isEndUseSubcategoryDefaulted() const;
+
+    //@}
+    /** @name Setters */
+    //@{
+
+    bool setRepresentationFile(const ExternalFile& externalFile);
+
+    bool setPerformanceInterpolationMethod(const std::string& performanceInterpolationMethod);
+
+    bool setRatedCapacity(double ratedCapacity);
+    void autosizeRatedCapacity();
+
+    bool setSizingFactor(double sizingFactor);
+
+    // This is done via the setAmbientXXX methods
+    // bool setAmbientTemperatureIndicator(const std::string& ambientTemperatureIndicator);
+
+    /** This will make the Ambient Temperature Indicator = 'Schedule' */
+    bool setAmbientTemperatureSchedule(Schedule& schedule);
+    /** This will reset the Ambient Temperature Indicator = 'Outdoors' */
+    void resetAmbientTemperatureSchedule();
+
+    /** This will make the Ambient Temperature Indicator = 'Zone' */
+    bool setAmbientTemperatureZone(const ThermalZone& thermalZone);
+    /** This will reset the Ambient Temperature Indicator = 'Outdoors' */
+    void resetAmbientTemperatureZone();
+
+    /** This will make the Ambient Temperature Indicator = 'Outdoors' */
+    bool setAmbientTemperatureOutdoorAirNodeName(const std::string& ambientTemperatureOutdoorAirNodeName);
+    /** This will reset the Ambient Temperature Indicator = 'Outdoors'. A default Outdoor Air Node Name will be used in the ForwardTranslator */
+    void resetAmbientTemperatureOutdoorAirNodeName();
+
+    bool setChilledWaterMaximumRequestedFlowRate(double chilledWaterMaximumRequestedFlowRate);
+    void autosizeChilledWaterMaximumRequestedFlowRate();
+
+    bool setCondenserMaximumRequestedFlowRate(double condenserMaximumRequestedFlowRate);
+    void autosizeCondenserMaximumRequestedFlowRate();
+
+    bool setChillerFlowMode(const std::string& chillerFlowMode);
+
+    bool setOilCoolerDesignFlowRate(double oilCoolerDesignFlowRate);
+    void resetOilCoolerDesignFlowRate();
+
+    bool setAuxiliaryCoolingDesignFlowRate(double auxiliaryCoolingDesignFlowRate);
+    void resetAuxiliaryCoolingDesignFlowRate();
+
+    bool setEndUseSubcategory(const std::string& endUseSubcategory);
+    void resetEndUseSubcategory();
+
+    //@}
+    /** @name Other */
+    //@{
+
+    boost::optional<double> autosizedRatedCapacity();
+
+    boost::optional<double> autosizedChilledWaterMaximumRequestedFlowRate();
+
+    boost::optional<double> autosizedCondenserMaximumRequestedFlowRate();
+
+    /** Convenience Function to return the Chilled Water Loop (chiller on supply) **/
+    boost::optional<PlantLoop> chilledWaterLoop() const;
+    // Same as supplyInletModelObject, but cast to a Node
+    boost::optional<Node> chilledWaterInletNode() const;
+    boost::optional<Node> chilledWaterOutletNode() const;
+
+    /** Convenience Function to return the Condenser Water Loop (chiller on demand side) **/
+    boost::optional<PlantLoop> condenserWaterLoop() const;
+    boost::optional<Node> condenserInletNode() const;
+    boost::optional<Node> condenserOutletNode() const;
+
+    // Not implemented in E+ 22.2.0, but reserved as a Tertiary Loop for now
+    boost::optional<PlantLoop> heatRecoveryLoop() const;
+    boost::optional<Node> heatRecoveryInletNode() const;
+    boost::optional<Node> heatRecoveryOutletNode() const;
+
+    unsigned oilCoolerInletPort() const;
+    boost::optional<ModelObject> oilCoolerInletModelObject() const;
+    boost::optional<Node> oilCoolerInletNode() const;
+    unsigned oilCoolerOutletPort() const;
+    boost::optional<ModelObject> oilCoolerOutletModelObject() const;
+    boost::optional<Node> oilCoolerOutletNode() const;
+    boost::optional<PlantLoop> oilCoolerLoop() const;
+    bool addDemandBranchOnOilCoolerLoop(PlantLoop& plantLoop);
+    bool addToOilCoolerLoopNode(Node& node);
+    bool removeFromOilCoolerLoop();
+
+    unsigned auxiliaryInletPort() const;
+    boost::optional<ModelObject> auxiliaryInletModelObject() const;
+    boost::optional<Node> auxiliaryInletNode() const;
+    unsigned auxiliaryOutletPort() const;
+    boost::optional<ModelObject> auxiliaryOutletModelObject() const;
+    boost::optional<Node> auxiliaryOutletNode() const;
+    bool addDemandBranchOnAuxiliaryLoop(PlantLoop& plantLoop);
+    bool addToAuxiliaryLoopNode(Node& node);
+    bool removeFromAuxiliaryLoop();
+    boost::optional<PlantLoop> auxiliaryLoop() const;
+
+    //@}
+   protected:
+    /// @cond
+    using ImplType = detail::ChillerElectricASHRAE205_Impl;
+
+    explicit ChillerElectricASHRAE205(std::shared_ptr<detail::ChillerElectricASHRAE205_Impl> impl);
+
+    friend class detail::ChillerElectricASHRAE205_Impl;
+    friend class Model;
+    friend class IdfObject;
+    friend class openstudio::detail::IdfObject_Impl;
+    /// @endcond
+   private:
+    REGISTER_LOGGER("openstudio.model.ChillerElectricASHRAE205");
+  };
+
+  /** \relates ChillerElectricASHRAE205*/
+  using OptionalChillerElectricASHRAE205 = boost::optional<ChillerElectricASHRAE205>;
+
+  /** \relates ChillerElectricASHRAE205*/
+  using ChillerElectricASHRAE205Vector = std::vector<ChillerElectricASHRAE205>;
+
+}  // namespace model
+}  // namespace openstudio
+
+#endif  // MODEL_CHILLERELECTRICASHRAE205_HPP
diff --git a/src/model/ChillerElectricASHRAE205_Impl.hpp b/src/model/ChillerElectricASHRAE205_Impl.hpp
new file mode 100644
index 00000000000..002ba8d49d5
--- /dev/null
+++ b/src/model/ChillerElectricASHRAE205_Impl.hpp
@@ -0,0 +1,249 @@
+/***********************************************************************************************************************
+*  OpenStudio(R), Copyright (c) 2008-2022, 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.
+***********************************************************************************************************************/
+
+#ifndef MODEL_CHILLERELECTRICASHRAE205_IMPL_HPP
+#define MODEL_CHILLERELECTRICASHRAE205_IMPL_HPP
+
+#include <model/ModelAPI.hpp>
+#include "WaterToWaterComponent_Impl.hpp"
+
+namespace openstudio {
+namespace model {
+
+  class ExternalFile;
+  class Node;
+  class ThermalZone;
+  class Schedule;
+
+  namespace detail {
+
+    /** ChillerElectricASHRAE205_Impl is a WaterToWaterComponent_Impl that is the implementation class for ChillerElectricASHRAE205.*/
+    class MODEL_API ChillerElectricASHRAE205_Impl : public WaterToWaterComponent_Impl
+    {
+     public:
+      /** @name Constructors and Destructors */
+      //@{
+
+      ChillerElectricASHRAE205_Impl(const IdfObject& idfObject, Model_Impl* model, bool keepHandle);
+
+      ChillerElectricASHRAE205_Impl(const openstudio::detail::WorkspaceObject_Impl& other, Model_Impl* model, bool keepHandle);
+
+      ChillerElectricASHRAE205_Impl(const ChillerElectricASHRAE205_Impl& other, Model_Impl* model, bool keepHandle);
+
+      virtual ~ChillerElectricASHRAE205_Impl() = default;
+
+      //@}
+      /** @name Virtual Methods */
+      //@{
+
+      virtual const std::vector<std::string>& outputVariableNames() const override;
+
+      virtual IddObjectType iddObjectType() const override;
+
+      virtual std::vector<ScheduleTypeKey> getScheduleTypeKeys(const Schedule& schedule) const override;
+
+      // chilledWaterLoop
+      virtual boost::optional<PlantLoop> plantLoop() const override;
+      virtual unsigned supplyInletPort() const override;
+      virtual unsigned supplyOutletPort() const override;
+
+      // condenserWaterLoop
+      virtual boost::optional<PlantLoop> secondaryPlantLoop() const override;
+      virtual unsigned demandInletPort() const override;
+      virtual unsigned demandOutletPort() const override;
+
+      // heatRecoveryLoop
+      virtual boost::optional<PlantLoop> tertiaryPlantLoop() const override;
+      virtual unsigned tertiaryInletPort() const override;
+      virtual unsigned tertiaryOutletPort() const override;
+
+      virtual std::vector<HVACComponent> edges(const boost::optional<HVACComponent>& prev) override;
+
+      /** This function will perform a check if trying to add it to a node that is on the demand side of a plant loop.
+       * If:
+       *     - the node is on the demand side of a loop
+       *     - the node isn't on the current condenser water loop itself
+       *     - the chiller doesn't already have a heat recovery (tertiary) loop,
+       * then it tries to add it to the Tertiary loop.
+       * In all other cases, it will call the base class' method WaterToWaterComponent_Impl::addToNode()
+       * If this is connecting to the demand side of a loop (not tertiary), will set the chiller condenserType to WaterCooled
+       */
+      virtual bool addToNode(Node& node) override;
+
+      /* Restricts addToTertiaryNode to a node that is on the demand side of a plant loop (tertiary = Heat Recovery Loop) */
+      virtual bool addToTertiaryNode(Node& node) override;
+
+      virtual ModelObject clone(Model model) const override;
+
+      virtual void autosize() override;
+
+      virtual void applySizingValues() override;
+
+      //@}
+      /** @name Getters */
+      //@{
+
+      ExternalFile representationFile() const;
+
+      std::string performanceInterpolationMethod() const;
+
+      boost::optional<double> ratedCapacity() const;
+      bool isRatedCapacityAutosized() const;
+
+      double sizingFactor() const;
+
+      std::string ambientTemperatureIndicator() const;
+
+      boost::optional<Schedule> ambientTemperatureSchedule() const;
+
+      boost::optional<ThermalZone> ambientTemperatureZone() const;
+
+      boost::optional<std::string> ambientTemperatureOutdoorAirNodeName() const;
+
+      boost::optional<double> chilledWaterMaximumRequestedFlowRate() const;
+      bool isChilledWaterMaximumRequestedFlowRateAutosized() const;
+
+      boost::optional<double> condenserMaximumRequestedFlowRate() const;
+      bool isCondenserMaximumRequestedFlowRateAutosized() const;
+
+      std::string chillerFlowMode() const;
+
+      boost::optional<double> oilCoolerDesignFlowRate() const;
+
+      boost::optional<double> auxiliaryCoolingDesignFlowRate() const;
+
+      std::string endUseSubcategory() const;
+      bool isEndUseSubcategoryDefaulted() const;
+
+      //@}
+      /** @name Setters */
+      //@{
+
+      bool setRepresentationFile(const ExternalFile& externalFile);
+
+      bool setPerformanceInterpolationMethod(const std::string& performanceInterpolationMethod);
+
+      bool setRatedCapacity(double ratedCapacity);
+      void autosizeRatedCapacity();
+
+      bool setSizingFactor(double sizingFactor);
+
+      bool setAmbientTemperatureIndicator(const std::string& ambientTemperatureIndicator);
+
+      bool setAmbientTemperatureSchedule(Schedule& schedule);
+      void resetAmbientTemperatureSchedule();
+
+      bool setAmbientTemperatureZone(const ThermalZone& thermalZone);
+      void resetAmbientTemperatureZone();
+
+      bool setAmbientTemperatureOutdoorAirNodeName(const std::string& ambientTemperatureOutdoorAirNodeName);
+      void resetAmbientTemperatureOutdoorAirNodeName();
+
+      bool setChilledWaterMaximumRequestedFlowRate(double chilledWaterMaximumRequestedFlowRate);
+      void autosizeChilledWaterMaximumRequestedFlowRate();
+
+      bool setCondenserMaximumRequestedFlowRate(double condenserMaximumRequestedFlowRate);
+      void autosizeCondenserMaximumRequestedFlowRate();
+
+      bool setChillerFlowMode(const std::string& chillerFlowMode);
+
+      bool setOilCoolerDesignFlowRate(double oilCoolerDesignFlowRate);
+      void resetOilCoolerDesignFlowRate();
+
+      bool setAuxiliaryCoolingDesignFlowRate(double auxiliaryCoolingDesignFlowRate);
+      void resetAuxiliaryCoolingDesignFlowRate();
+
+      bool setEndUseSubcategory(const std::string& endUseSubcategory);
+      void resetEndUseSubcategory();
+
+      //@}
+      /** @name Other */
+      //@{
+
+      boost::optional<double> autosizedRatedCapacity();
+
+      boost::optional<double> autosizedChilledWaterMaximumRequestedFlowRate();
+
+      boost::optional<double> autosizedCondenserMaximumRequestedFlowRate();
+
+      /** Convenience Function to return the Chilled Water Loop (chiller on supply) **/
+      boost::optional<PlantLoop> chilledWaterLoop() const;
+      // Same as supplyInletModelObject, but cast to a Node
+      boost::optional<Node> chilledWaterInletNode() const;
+      boost::optional<Node> chilledWaterOutletNode() const;
+
+      /** Convenience Function to return the Condenser Water Loop (chiller on demand side) **/
+      boost::optional<PlantLoop> condenserWaterLoop() const;
+      boost::optional<Node> condenserInletNode() const;
+      boost::optional<Node> condenserOutletNode() const;
+
+      // Not implemented in E+ 22.2.0, but reserved as a Tertiary Loop for now
+      boost::optional<PlantLoop> heatRecoveryLoop() const;
+      boost::optional<Node> heatRecoveryInletNode() const;
+      boost::optional<Node> heatRecoveryOutletNode() const;
+
+      /*static*/ unsigned oilCoolerInletPort() const;
+      boost::optional<ModelObject> oilCoolerInletModelObject() const;
+      /*static*/ unsigned oilCoolerOutletPort() const;
+      boost::optional<ModelObject> oilCoolerOutletModelObject() const;
+      boost::optional<PlantLoop> oilCoolerLoop() const;
+      bool addDemandBranchOnOilCoolerLoop(PlantLoop& plantLoop);
+      bool addToOilCoolerLoopNode(Node& node);
+      bool removeFromOilCoolerLoop();
+      boost::optional<Node> oilCoolerInletNode() const;
+      boost::optional<Node> oilCoolerOutletNode() const;
+
+      /*static*/ unsigned auxiliaryInletPort() const;
+      boost::optional<ModelObject> auxiliaryInletModelObject() const;
+      /*static*/ unsigned auxiliaryOutletPort() const;
+      boost::optional<ModelObject> auxiliaryOutletModelObject() const;
+      bool addDemandBranchOnAuxiliaryLoop(PlantLoop& plantLoop);
+      bool addToAuxiliaryLoopNode(Node& node);
+      bool removeFromAuxiliaryLoop();
+      boost::optional<PlantLoop> auxiliaryLoop() const;
+      boost::optional<Node> auxiliaryInletNode() const;
+      boost::optional<Node> auxiliaryOutletNode() const;
+
+      //@}
+     protected:
+     private:
+      REGISTER_LOGGER("openstudio.model.ChillerElectricASHRAE205");
+
+      // Optional getters for use by methods like children() so can remove() if the constructor fails.
+      // There are other ways for the public versions of these getters to fail--perhaps all required
+      // objects should be returned as boost::optionals
+      boost::optional<ExternalFile> optionalRepresentationFile() const;
+    };
+
+  }  // namespace detail
+
+}  // namespace model
+}  // namespace openstudio
+
+#endif  // MODEL_CHILLERELECTRICASHRAE205_IMPL_HPP
diff --git a/src/model/ConcreteModelObjects.hpp b/src/model/ConcreteModelObjects.hpp
index b3e02643484..ee8f6ce1fd3 100644
--- a/src/model/ConcreteModelObjects.hpp
+++ b/src/model/ConcreteModelObjects.hpp
@@ -106,6 +106,7 @@
 #include "ClimateZones.hpp"
 #include "ChillerAbsorption.hpp"
 #include "ChillerAbsorptionIndirect.hpp"
+#include "ChillerElectricASHRAE205.hpp"
 #include "ChillerElectricEIR.hpp"
 #include "ChillerElectricReformulatedEIR.hpp"
 #include "ChillerHeaterPerformanceElectricEIR.hpp"
@@ -639,6 +640,7 @@
 #include "CFactorUndergroundWallConstruction_Impl.hpp"
 #include "ChillerAbsorption_Impl.hpp"
 #include "ChillerAbsorptionIndirect_Impl.hpp"
+#include "ChillerElectricASHRAE205_Impl.hpp"
 #include "ChillerElectricEIR_Impl.hpp"
 #include "ChillerElectricReformulatedEIR_Impl.hpp"
 #include "ChillerHeaterPerformanceElectricEIR_Impl.hpp"
diff --git a/src/model/ExternalFile.cpp b/src/model/ExternalFile.cpp
index a9af885da47..9d3b4d4d4aa 100644
--- a/src/model/ExternalFile.cpp
+++ b/src/model/ExternalFile.cpp
@@ -33,6 +33,9 @@
 #include "Model.hpp"
 #include "ScheduleFile.hpp"
 #include "PythonPluginInstance.hpp"
+#include "PythonPluginInstance_Impl.hpp"
+#include "ChillerElectricASHRAE205.hpp"
+#include "ChillerElectricASHRAE205_Impl.hpp"
 
 #include <utilities/idd/IddFactory.hxx>
 #include <utilities/idd/IddEnums.hxx>
@@ -45,7 +48,6 @@
 
 #include <unordered_map>
 #include "ScheduleFile_Impl.hpp"
-#include "PythonPluginInstance_Impl.hpp"
 
 namespace openstudio {
 namespace model {
@@ -114,6 +116,13 @@ namespace model {
         tmp.insert(tmp.end(), tmp2.begin(), tmp2.end());
       }
 
+      // ChillerElectricASHRAE205
+      std::vector<ChillerElectricASHRAE205> chs = chillerElectricASHRAE205s();
+      for (auto& ch : chs) {
+        std::vector<openstudio::IdfObject> tmp2 = ch.remove();
+        tmp.insert(tmp.end(), tmp2.begin(), tmp2.end());
+      }
+
       std::vector<openstudio::IdfObject> idfObjects = ModelObject_Impl::remove();
       idfObjects.insert(idfObjects.end(), tmp.begin(), tmp.end());
 
@@ -192,6 +201,11 @@ namespace model {
       return result;
     }
 
+    std::vector<ChillerElectricASHRAE205> ExternalFile_Impl::chillerElectricASHRAE205s() const {
+      std::vector<ChillerElectricASHRAE205> result = getObject<ExternalFile>().getModelObjectSources<ChillerElectricASHRAE205>();
+      return result;
+    }
+
   }  // namespace detail
 
   boost::optional<ExternalFile> ExternalFile::getExternalFile(const Model& model, const std::string& filename) {
@@ -313,8 +327,12 @@ namespace model {
     return getImpl<detail::ExternalFile_Impl>()->pythonPluginInstances();
   }
 
+  std::vector<ChillerElectricASHRAE205> ExternalFile::chillerElectricASHRAE205s() const {
+    return getImpl<detail::ExternalFile_Impl>()->chillerElectricASHRAE205s();
+  }
+
   /// @cond
-  ExternalFile::ExternalFile(std::shared_ptr<detail::ExternalFile_Impl> impl) : ResourceObject(impl) {}
+  ExternalFile::ExternalFile(std::shared_ptr<detail::ExternalFile_Impl> impl) : ResourceObject(std::move(impl)) {}
   /// @endcond
 
 }  // namespace model
diff --git a/src/model/ExternalFile.hpp b/src/model/ExternalFile.hpp
index 8f6e525a6bd..399928aaeb1 100644
--- a/src/model/ExternalFile.hpp
+++ b/src/model/ExternalFile.hpp
@@ -41,6 +41,7 @@ namespace model {
 
   class ScheduleFile;
   class PythonPluginInstance;
+  class ChillerElectricASHRAE205;
 
   namespace detail {
 
@@ -94,6 +95,8 @@ namespace model {
 
     std::vector<PythonPluginInstance> pythonPluginInstances() const;
 
+    std::vector<ChillerElectricASHRAE205> chillerElectricASHRAE205s() const;
+
     //@}
    protected:
     /// @cond
diff --git a/src/model/ExternalFile_Impl.hpp b/src/model/ExternalFile_Impl.hpp
index cfcf53cadac..3f12981e6ef 100644
--- a/src/model/ExternalFile_Impl.hpp
+++ b/src/model/ExternalFile_Impl.hpp
@@ -40,6 +40,7 @@ namespace model {
   class ExternalFile;
   class ScheduleFile;
   class PythonPluginInstance;
+  class ChillerElectricASHRAE205;
 
   namespace detail {
 
@@ -101,6 +102,8 @@ namespace model {
 
       std::vector<PythonPluginInstance> pythonPluginInstances() const;
 
+      std::vector<ChillerElectricASHRAE205> chillerElectricASHRAE205s() const;
+
       //@}
      protected:
       bool setFileName(const std::string& fileName);
diff --git a/src/model/Loop.cpp b/src/model/Loop.cpp
index 576d7ff195d..d9287f57bd1 100644
--- a/src/model/Loop.cpp
+++ b/src/model/Loop.cpp
@@ -39,6 +39,8 @@
 #include "Splitter_Impl.hpp"
 #include "Mixer.hpp"
 #include "Mixer_Impl.hpp"
+#include "HVACComponent.hpp"
+#include "HVACComponent_Impl.hpp"
 #include "StraightComponent.hpp"
 #include "StraightComponent_Impl.hpp"
 #include "WaterToAirComponent.hpp"
@@ -106,7 +108,9 @@ namespace model {
       }
 
       boost::optional<HVACComponent> prev;
-      if (visited.size() >= 2u) prev = visited.rbegin()[1];
+      if (visited.size() >= 2u) {
+        prev = visited.rbegin()[1];
+      }
 
       std::vector<HVACComponent> nodes = hvacComponent.getImpl<HVACComponent_Impl>()->edges(prev);
 
@@ -200,7 +204,9 @@ namespace model {
     void findModelObjects(const HVACComponent& sink, std::vector<HVACComponent>& visited, std::vector<HVACComponent>& paths,
                           bool isDemandComponents) {
       boost::optional<HVACComponent> prev;
-      if (visited.size() >= 2u) prev = visited.rbegin()[1];
+      if (visited.size() >= 2u) {
+        prev = visited.rbegin()[1];
+      }
 
       std::vector<HVACComponent> nodes = visited.back().getImpl<HVACComponent_Impl>()->edges(prev);
 
diff --git a/src/model/Model.cpp b/src/model/Model.cpp
index db96379c9c5..6df76e2d05e 100644
--- a/src/model/Model.cpp
+++ b/src/model/Model.cpp
@@ -3873,6 +3873,7 @@ namespace model {
     REGISTER_CONSTRUCTOR(CFactorUndergroundWallConstruction);
     REGISTER_CONSTRUCTOR(ChillerAbsorption);
     REGISTER_CONSTRUCTOR(ChillerAbsorptionIndirect);
+    REGISTER_CONSTRUCTOR(ChillerElectricASHRAE205);
     REGISTER_CONSTRUCTOR(ChillerElectricEIR);
     REGISTER_CONSTRUCTOR(ChillerElectricReformulatedEIR);
     REGISTER_CONSTRUCTOR(ChillerHeaterPerformanceElectricEIR);
@@ -4428,6 +4429,7 @@ namespace model {
     REGISTER_COPYCONSTRUCTORS(ClimateZones);
     REGISTER_COPYCONSTRUCTORS(ChillerAbsorption);
     REGISTER_COPYCONSTRUCTORS(ChillerAbsorptionIndirect);
+    REGISTER_COPYCONSTRUCTORS(ChillerElectricASHRAE205);
     REGISTER_COPYCONSTRUCTORS(ChillerElectricEIR);
     REGISTER_COPYCONSTRUCTORS(ChillerElectricReformulatedEIR);
     REGISTER_COPYCONSTRUCTORS(ChillerHeaterPerformanceElectricEIR);
diff --git a/src/model/ModelHVAC.i b/src/model/ModelHVAC.i
index 91590c33ddd..bb855885ff9 100644
--- a/src/model/ModelHVAC.i
+++ b/src/model/ModelHVAC.i
@@ -164,6 +164,7 @@ MODELOBJECT_TEMPLATES(AirTerminalDualDuctVAVOutdoorAir);
 MODELOBJECT_TEMPLATES(CentralHeatPumpSystem);
 MODELOBJECT_TEMPLATES(CentralHeatPumpSystemModule);
 MODELOBJECT_TEMPLATES(ChillerHeaterPerformanceElectricEIR);
+MODELOBJECT_TEMPLATES(ChillerElectricASHRAE205);
 MODELOBJECT_TEMPLATES(ChillerElectricEIR);
 MODELOBJECT_TEMPLATES(ChillerElectricReformulatedEIR);
 MODELOBJECT_TEMPLATES(CoilCoolingDXMultiSpeedStageData);
@@ -285,6 +286,7 @@ SWIG_MODELOBJECT(AirTerminalDualDuctVAVOutdoorAir, 1);
 SWIG_MODELOBJECT(CentralHeatPumpSystem, 1);
 SWIG_MODELOBJECT(CentralHeatPumpSystemModule, 1);
 SWIG_MODELOBJECT(ChillerHeaterPerformanceElectricEIR, 1);
+SWIG_MODELOBJECT(ChillerElectricASHRAE205, 1);
 SWIG_MODELOBJECT(ChillerElectricEIR, 1);
 SWIG_MODELOBJECT(ChillerElectricReformulatedEIR, 1);
 SWIG_MODELOBJECT(CoilCoolingDXMultiSpeedStageData, 1);
diff --git a/src/model/ScheduleTypeRegistry.cpp b/src/model/ScheduleTypeRegistry.cpp
index c53bd048a06..9796e728454 100644
--- a/src/model/ScheduleTypeRegistry.cpp
+++ b/src/model/ScheduleTypeRegistry.cpp
@@ -171,6 +171,7 @@ namespace model {
       {"AvailabilityManagerScheduledOff", "Availability Manager Scheduled Off", "schedule", false, "Availability", 0.0, 1.0},
       {"CentralHeatPumpSystem", "Ancillary Operation", "ancillaryOperationSchedule", false, "Availability", 0.0, 1.0},
       {"CentralHeatPumpSystemModule", "Chiller Heater Modules Control", "chillerHeaterModulesControlSchedule", false, "Availability", 0.0, 1.0},
+      {"ChillerElectricASHRAE205", "Ambient Temperature", "ambientTemperatureSchedule", true, "Temperature", OptionalDouble(), OptionalDouble()},
       {"ChillerElectricEIR", "Basin Heater Operating", "basinHeaterSchedule", false, "Availability", 0.0, 1.0},
       {"ChillerElectricEIR", "Heat Recovery Inlet High Temperature Limit", "heatRecoveryInletHighTemperatureLimitSchedule", true, "Temperature",
        OptionalDouble(), OptionalDouble()},
diff --git a/src/model/WaterToWaterComponent.cpp b/src/model/WaterToWaterComponent.cpp
index f0a8b6969af..3aaba525816 100644
--- a/src/model/WaterToWaterComponent.cpp
+++ b/src/model/WaterToWaterComponent.cpp
@@ -256,8 +256,8 @@ namespace model {
       if (m_secondaryPlantLoop) {
         return m_secondaryPlantLoop;
       } else {
-        // JM: Same comment as for plantLoop() above, though as of 2018-01-03 I can't think of an actual object
-        // that could be on the demand side of two plant loops
+        // JM: Same comment as for plantLoop() above
+        // Any WaterToWaterComponent that has an Heat Recovery loop could be on the demand side of two plant loops
         boost::optional<PlantLoop> tertiaryPlantLoop = this->tertiaryPlantLoop();
 
         std::vector<PlantLoop> plantLoops = this->model().getConcreteModelObjects<PlantLoop>();
diff --git a/src/model/WaterToWaterComponent_Impl.hpp b/src/model/WaterToWaterComponent_Impl.hpp
index a643d93e846..461e75afa6a 100644
--- a/src/model/WaterToWaterComponent_Impl.hpp
+++ b/src/model/WaterToWaterComponent_Impl.hpp
@@ -109,7 +109,7 @@ namespace model {
   * This method checks for presence of the WaterToWaterComponent on either the supply or demand side of plantLoops
   * and does an extra check for actual node: the tertiaryOutletModelObject has to be on the plant loop too
   */
-      boost::optional<PlantLoop> tertiaryPlantLoop() const;
+      virtual boost::optional<PlantLoop> tertiaryPlantLoop() const;
 
       virtual bool removeFromTertiaryPlantLoop();
 


Test patch:
diff --git a/src/model/test/ChillerElectricASHRAE205_GTest.cpp b/src/model/test/ChillerElectricASHRAE205_GTest.cpp
new file mode 100644
index 00000000000..81b0fb768ab
--- /dev/null
+++ b/src/model/test/ChillerElectricASHRAE205_GTest.cpp
@@ -0,0 +1,720 @@
+/***********************************************************************************************************************
+*  OpenStudio(R), Copyright (c) 2008-2022, 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 "ModelFixture.hpp"
+
+#include "../ChillerElectricASHRAE205.hpp"
+#include "../ChillerElectricASHRAE205_Impl.hpp"
+
+#include "../ExternalFile.hpp"
+#include "../ExternalFile_Impl.hpp"
+
+#include "../ThermalZone.hpp"
+#include "../ThermalZone_Impl.hpp"
+#include "../PlantLoop.hpp"
+#include "../PlantLoop_Impl.hpp"
+#include "../Node.hpp"
+#include "../Node_Impl.hpp"
+#include "../Schedule.hpp"
+#include "../ScheduleConstant.hpp"
+#include "../Mixer.hpp"
+#include "../Splitter.hpp"
+
+#include "../../utilities/core/PathHelpers.hpp"
+#include <utilities/idd/IddEnums.hxx>
+#include <resources.hxx>
+
+using namespace openstudio;
+using namespace openstudio::model;
+
+TEST_F(ModelFixture, ChillerElectricASHRAE205_GettersSetters) {
+  Model m;
+
+  EXPECT_EQ(0, m.getConcreteModelObjects<ExternalFile>().size());
+  EXPECT_EQ(0, m.getConcreteModelObjects<ChillerElectricASHRAE205>().size());
+
+  openstudio::path p = resourcesPath() / toPath("model/A205ExampleChiller.RS0001.a205.cbor");
+  EXPECT_TRUE(exists(p));
+
+  openstudio::path expectedDestDir;
+  std::vector<openstudio::path> absoluteFilePaths = m.workflowJSON().absoluteFilePaths();
+  if (absoluteFilePaths.empty()) {
+    expectedDestDir = m.workflowJSON().absoluteRootDir();
+  } else {
+    expectedDestDir = absoluteFilePaths[0];
+  }
+
+  if (exists(expectedDestDir)) {
+    removeDirectory(expectedDestDir);
+  }
+  ASSERT_FALSE(exists(expectedDestDir));
+  EXPECT_TRUE(exists(p));
+
+  boost::optional<ExternalFile> representationFile = ExternalFile::getExternalFile(m, openstudio::toString(p));
+  ASSERT_TRUE(representationFile);
+
+  EXPECT_EQ(1, m.getConcreteModelObjects<ExternalFile>().size());
+  EXPECT_EQ(0, representationFile->chillerElectricASHRAE205s().size());
+  EXPECT_EQ(openstudio::toString(p.filename()), representationFile->fileName());
+  EXPECT_TRUE(equivalent(expectedDestDir / representationFile->fileName(), representationFile->filePath()));
+  EXPECT_TRUE(exists(representationFile->filePath()));
+  EXPECT_NE(p, representationFile->filePath());
+
+  ChillerElectricASHRAE205 ch(representationFile.get());
+  EXPECT_EQ(1, m.getConcreteModelObjects<ChillerElectricASHRAE205>().size());
+  EXPECT_EQ(1, representationFile->chillerElectricASHRAE205s().size());
+  EXPECT_EQ(representationFile->handle(), ch.representationFile().handle());
+
+  // Representation File Name: Required Object
+  // ExternalFile obj(m);
+  // EXPECT_TRUE(ch.setRepresentationFile(obj));
+  // EXPECT_EQ(obj, ch.representationFile());
+
+  // Performance Interpolation Method: Required String
+  // Ctor default
+  EXPECT_EQ("Linear", ch.performanceInterpolationMethod());
+  EXPECT_TRUE(ch.setPerformanceInterpolationMethod("Cubic"));
+  EXPECT_EQ("Cubic", ch.performanceInterpolationMethod());
+  // Bad Value
+  EXPECT_FALSE(ch.setPerformanceInterpolationMethod("BADENUM"));
+  EXPECT_EQ("Cubic", ch.performanceInterpolationMethod());
+
+  // Rated Capacity: Required Double
+  // Autosize
+  ch.autosizeRatedCapacity();
+  EXPECT_TRUE(ch.isRatedCapacityAutosized());
+  // Set
+  EXPECT_TRUE(ch.setRatedCapacity(0.5));
+  ASSERT_TRUE(ch.ratedCapacity());
+  EXPECT_EQ(0.5, ch.ratedCapacity().get());
+  EXPECT_FALSE(ch.isRatedCapacityAutosized());
+  // Bad Value
+  EXPECT_FALSE(ch.setRatedCapacity(-10.0));
+  ASSERT_TRUE(ch.ratedCapacity());
+  EXPECT_EQ(0.5, ch.ratedCapacity().get());
+  EXPECT_FALSE(ch.isRatedCapacityAutosized());
+
+  // Sizing Factor: Required Double
+  // Ctor default
+  EXPECT_EQ(1.0, ch.sizingFactor());
+  EXPECT_TRUE(ch.setSizingFactor(0.6));
+  EXPECT_EQ(0.6, ch.sizingFactor());
+  // Bad Value
+  EXPECT_FALSE(ch.setSizingFactor(-10.0));
+  EXPECT_EQ(0.6, ch.sizingFactor());
+
+  // Ambient Temperature Indicator: Required String
+  EXPECT_EQ("Outdoors", ch.ambientTemperatureIndicator());
+
+  // EXPECT_TRUE(ch.setAmbientTemperatureIndicator("Schedule"));
+  // EXPECT_EQ("Schedule", ch.ambientTemperatureIndicator());
+  // // Bad Value
+  // EXPECT_FALSE(ch.setAmbientTemperatureIndicator("BADENUM"));
+  // EXPECT_EQ("Schedule", ch.ambientTemperatureIndicator());
+
+  // Ambient Temperature Schedule Name: Optional Object
+  ScheduleConstant tempSch(m);
+  EXPECT_TRUE(ch.setAmbientTemperatureSchedule(tempSch));
+  ASSERT_TRUE(ch.ambientTemperatureSchedule());
+  EXPECT_EQ(tempSch, ch.ambientTemperatureSchedule().get());
+  EXPECT_EQ("Schedule", ch.ambientTemperatureIndicator());
+  ch.resetAmbientTemperatureOutdoorAirNodeName();
+  EXPECT_EQ("Schedule", ch.ambientTemperatureIndicator());
+  ch.resetAmbientTemperatureSchedule();
+  EXPECT_EQ("Outdoors", ch.ambientTemperatureIndicator());
+
+  // Ambient Temperature Zone Name: Optional Object
+  ThermalZone z(m);
+  EXPECT_TRUE(ch.setAmbientTemperatureZone(z));
+  ASSERT_TRUE(ch.ambientTemperatureZone());
+  EXPECT_EQ(z, ch.ambientTemperatureZone().get());
+  EXPECT_EQ("Zone", ch.ambientTemperatureIndicator());
+  ch.resetAmbientTemperatureSchedule();
+  EXPECT_EQ("Zone", ch.ambientTemperatureIndicator());
+  ch.resetAmbientTemperatureZone();
+  EXPECT_EQ("Outdoors", ch.ambientTemperatureIndicator());
+
+  EXPECT_TRUE(ch.setAmbientTemperatureZone(z));
+  EXPECT_EQ("Zone", ch.ambientTemperatureIndicator());
+  ch.resetAmbientTemperatureOutdoorAirNodeName();
+  EXPECT_EQ("Zone", ch.ambientTemperatureIndicator());
+
+  // Ambient Temperature Outdoor Air Node Name: Optional Object
+  EXPECT_TRUE(ch.setAmbientTemperatureOutdoorAirNodeName("My Outdoor Air Node Name"));
+  ASSERT_TRUE(ch.ambientTemperatureOutdoorAirNodeName());
+  EXPECT_EQ("My Outdoor Air Node Name", ch.ambientTemperatureOutdoorAirNodeName().get());
+  EXPECT_EQ("Outdoors", ch.ambientTemperatureIndicator());
+
+  // Chilled Water Maximum Requested Flow Rate: Required Double
+  // Ctor default
+  EXPECT_TRUE(ch.isChilledWaterMaximumRequestedFlowRateAutosized());
+  // Set
+  EXPECT_TRUE(ch.setChilledWaterMaximumRequestedFlowRate(1.3));
+  ASSERT_TRUE(ch.chilledWaterMaximumRequestedFlowRate());
+  EXPECT_EQ(1.3, ch.chilledWaterMaximumRequestedFlowRate().get());
+  // Bad Value
+  EXPECT_FALSE(ch.setChilledWaterMaximumRequestedFlowRate(-10.0));
+  ASSERT_TRUE(ch.chilledWaterMaximumRequestedFlowRate());
+  EXPECT_EQ(1.3, ch.chilledWaterMaximumRequestedFlowRate().get());
+  EXPECT_FALSE(ch.isChilledWaterMaximumRequestedFlowRateAutosized());
+  // Autosize
+  ch.autosizeChilledWaterMaximumRequestedFlowRate();
+  EXPECT_TRUE(ch.isChilledWaterMaximumRequestedFlowRateAutosized());
+
+  // Condenser Maximum Requested Flow Rate: Required Double
+  // Ctor default
+  EXPECT_TRUE(ch.isCondenserMaximumRequestedFlowRateAutosized());
+  // Set
+  EXPECT_TRUE(ch.setCondenserMaximumRequestedFlowRate(1.6));
+  ASSERT_TRUE(ch.condenserMaximumRequestedFlowRate());
+  EXPECT_EQ(1.6, ch.condenserMaximumRequestedFlowRate().get());
+  // Bad Value
+  EXPECT_FALSE(ch.setCondenserMaximumRequestedFlowRate(-10.0));
+  ASSERT_TRUE(ch.condenserMaximumRequestedFlowRate());
+  EXPECT_EQ(1.6, ch.condenserMaximumRequestedFlowRate().get());
+  EXPECT_FALSE(ch.isCondenserMaximumRequestedFlowRateAutosized());
+  // Autosize
+  ch.autosizeCondenserMaximumRequestedFlowRate();
+  EXPECT_TRUE(ch.isCondenserMaximumRequestedFlowRateAutosized());
+
+  // Chiller Flow Mode: Required String
+  EXPECT_TRUE(ch.setChillerFlowMode("ConstantFlow"));
+  EXPECT_EQ("ConstantFlow", ch.chillerFlowMode());
+  // Bad Value
+  EXPECT_FALSE(ch.setChillerFlowMode("BADENUM"));
+  EXPECT_EQ("ConstantFlow", ch.chillerFlowMode());
+
+  // Oil Cooler Design Flow Rate: Optional Double
+  EXPECT_TRUE(ch.setOilCoolerDesignFlowRate(2.0));
+  ASSERT_TRUE(ch.oilCoolerDesignFlowRate());
+  EXPECT_EQ(2.0, ch.oilCoolerDesignFlowRate().get());
+  // Bad Value
+  EXPECT_FALSE(ch.setOilCoolerDesignFlowRate(-10.0));
+  ASSERT_TRUE(ch.oilCoolerDesignFlowRate());
+  EXPECT_EQ(2.0, ch.oilCoolerDesignFlowRate().get());
+
+  // Auxiliary Cooling Design Flow Rate: Optional Double
+  EXPECT_TRUE(ch.setAuxiliaryCoolingDesignFlowRate(2.3));
+  ASSERT_TRUE(ch.auxiliaryCoolingDesignFlowRate());
+  EXPECT_EQ(2.3, ch.auxiliaryCoolingDesignFlowRate().get());
+  // Bad Value
+  EXPECT_FALSE(ch.setAuxiliaryCoolingDesignFlowRate(-10.0));
+  ASSERT_TRUE(ch.auxiliaryCoolingDesignFlowRate());
+  EXPECT_EQ(2.3, ch.auxiliaryCoolingDesignFlowRate().get());
+
+  // End-Use Subcategory: Optional String
+  // Default value from IDD
+  EXPECT_EQ("General", ch.endUseSubcategory());
+  // Set
+  EXPECT_TRUE(ch.setEndUseSubcategory("Chiller"));
+  EXPECT_EQ("Chiller", ch.endUseSubcategory());
+  EXPECT_FALSE(ch.isEndUseSubcategoryDefaulted());
+  // Reset
+  ch.resetEndUseSubcategory();
+  EXPECT_TRUE(ch.isEndUseSubcategoryDefaulted());
+  EXPECT_EQ("General", ch.endUseSubcategory());
+
+  // Removing the ExternalFile removes the Chiller
+  openstudio::path dstPath = representationFile->filePath();
+  EXPECT_TRUE(exists(p));
+  EXPECT_TRUE(exists(dstPath));
+
+  representationFile->remove();
+  EXPECT_EQ(0, m.getConcreteModelObjects<ExternalFile>().size());
+  EXPECT_EQ(0, m.getConcreteModelObjects<ChillerElectricASHRAE205>().size());
+
+  EXPECT_TRUE(exists(p));
+  EXPECT_FALSE(exists(dstPath));
+}
+
+TEST_F(ModelFixture, ChillerElectricASHRAE205_Loops) {
+  Model m;
+
+  EXPECT_EQ(0, m.getConcreteModelObjects<ExternalFile>().size());
+  EXPECT_EQ(0, m.getConcreteModelObjects<ChillerElectricASHRAE205>().size());
+
+  openstudio::path p = resourcesPath() / toPath("model/A205ExampleChiller.RS0001.a205.cbor");
+  EXPECT_TRUE(exists(p));
+
+  openstudio::path expectedDestDir;
+  std::vector<openstudio::path> absoluteFilePaths = m.workflowJSON().absoluteFilePaths();
+  if (absoluteFilePaths.empty()) {
+    expectedDestDir = m.workflowJSON().absoluteRootDir();
+  } else {
+    expectedDestDir = absoluteFilePaths[0];
+  }
+
+  if (exists(expectedDestDir)) {
+    removeDirectory(expectedDestDir);
+  }
+  ASSERT_FALSE(exists(expectedDestDir));
+  EXPECT_TRUE(exists(p));
+
+  boost::optional<ExternalFile> representationFile = ExternalFile::getExternalFile(m, openstudio::toString(p));
+  ASSERT_TRUE(representationFile);
+
+  EXPECT_EQ(1, m.getConcreteModelObjects<ExternalFile>().size());
+  EXPECT_EQ(0, representationFile->chillerElectricASHRAE205s().size());
+  EXPECT_EQ(openstudio::toString(p.filename()), representationFile->fileName());
+  EXPECT_TRUE(equivalent(expectedDestDir / representationFile->fileName(), representationFile->filePath()));
+  EXPECT_TRUE(exists(representationFile->filePath()));
+  EXPECT_NE(p, representationFile->filePath());
+
+  ChillerElectricASHRAE205 ch(representationFile.get());
+  EXPECT_FALSE(ch.chilledWaterLoop());
+  EXPECT_FALSE(ch.chilledWaterInletNode());
+  EXPECT_FALSE(ch.chilledWaterOutletNode());
+
+  EXPECT_FALSE(ch.condenserWaterLoop());
+  EXPECT_FALSE(ch.condenserInletNode());
+  EXPECT_FALSE(ch.condenserOutletNode());
+
+  EXPECT_FALSE(ch.heatRecoveryLoop());
+  EXPECT_FALSE(ch.heatRecoveryInletNode());
+  EXPECT_FALSE(ch.heatRecoveryOutletNode());
+
+  EXPECT_FALSE(ch.oilCoolerLoop());
+  EXPECT_FALSE(ch.oilCoolerInletNode());
+  EXPECT_FALSE(ch.oilCoolerOutletNode());
+
+  EXPECT_FALSE(ch.auxiliaryLoop());
+  EXPECT_FALSE(ch.auxiliaryInletNode());
+  EXPECT_FALSE(ch.auxiliaryOutletNode());
+
+  auto createLoop = [&m](const std::string& prefix) {
+    PlantLoop p(m);
+    static constexpr std::array<std::string_view, 10> compNames = {
+      "Supply Inlet", "Supply Splitter", "Supply Connection Node", "Supply Mixer", "Supply Outlet",
+      "Demand Inlet", "Demand Splitter", "Demand Connection Node", "Demand Mixer", "Demand Outlet",
+    };
+    p.setName(prefix);
+    for (size_t i = 0; auto& comp : p.components()) {
+      comp.setName(prefix + " " + std::string{compNames[i++]});
+    }
+    return p;
+  };
+
+  auto chwLoop = createLoop("chwLoop");
+  auto cndLoop = createLoop("cndLoop");
+  auto hrLoop = createLoop("hrLoop");
+  auto ocLoop = createLoop("ocLoop");
+  auto auxLoop = createLoop("auxLoop");
+
+  // Chilled Water
+  {
+    EXPECT_TRUE(chwLoop.addSupplyBranchForComponent(ch));
+    ASSERT_TRUE(ch.chilledWaterLoop());
+    ASSERT_EQ(chwLoop, ch.chilledWaterLoop().get());
+    EXPECT_TRUE(ch.chilledWaterInletNode());
+    EXPECT_TRUE(ch.chilledWaterOutletNode());
+
+    EXPECT_FALSE(ch.condenserWaterLoop());
+    EXPECT_FALSE(ch.condenserInletNode());
+    EXPECT_FALSE(ch.condenserOutletNode());
+
+    EXPECT_FALSE(ch.heatRecoveryLoop());
+    EXPECT_FALSE(ch.heatRecoveryInletNode());
+    EXPECT_FALSE(ch.heatRecoveryOutletNode());
+
+    EXPECT_FALSE(ch.oilCoolerLoop());
+    EXPECT_FALSE(ch.oilCoolerInletNode());
+    EXPECT_FALSE(ch.oilCoolerOutletNode());
+
+    EXPECT_FALSE(ch.auxiliaryLoop());
+    EXPECT_FALSE(ch.auxiliaryInletNode());
+    EXPECT_FALSE(ch.auxiliaryOutletNode());
+  }
+
+  // Condenser
+  {
+    EXPECT_TRUE(cndLoop.addDemandBranchForComponent(ch));
+    ASSERT_TRUE(ch.chilledWaterLoop());
+    EXPECT_EQ(chwLoop, ch.chilledWaterLoop().get());
+    EXPECT_TRUE(ch.chilledWaterInletNode());
+    EXPECT_EQ(ch.supplyInletModelObject()->handle(), ch.chilledWaterInletNode()->handle());
+    EXPECT_TRUE(ch.chilledWaterOutletNode());
+    EXPECT_EQ(ch.supplyOutletModelObject()->handle(), ch.chilledWaterOutletNode()->handle());
+
+    ASSERT_TRUE(ch.condenserWaterLoop());
+    EXPECT_EQ(cndLoop, ch.condenserWaterLoop().get());
+    ASSERT_TRUE(ch.condenserInletNode());
+    EXPECT_EQ(ch.demandInletModelObject()->handle(), ch.condenserInletNode()->handle());
+    ASSERT_TRUE(ch.condenserOutletNode());
+    EXPECT_EQ(ch.demandOutletModelObject()->handle(), ch.condenserOutletNode()->handle());
+
+    EXPECT_FALSE(ch.heatRecoveryLoop());
+    EXPECT_FALSE(ch.heatRecoveryInletNode());
+    EXPECT_FALSE(ch.heatRecoveryOutletNode());
+
+    EXPECT_FALSE(ch.oilCoolerLoop());
+    EXPECT_FALSE(ch.oilCoolerInletNode());
+    EXPECT_FALSE(ch.oilCoolerOutletNode());
+
+    EXPECT_FALSE(ch.auxiliaryLoop());
+    EXPECT_FALSE(ch.auxiliaryInletNode());
+    EXPECT_FALSE(ch.auxiliaryOutletNode());
+  }
+
+  auto checkHeatRecoveryLoop = [&ch, &hrLoop]() {
+    if constexpr (ChillerElectricASHRAE205::isHeatRecoverySupportedByEnergyplus) {
+
+      ASSERT_TRUE(ch.heatRecoveryLoop());
+      EXPECT_EQ(hrLoop, ch.heatRecoveryLoop().get());
+      ASSERT_TRUE(ch.heatRecoveryInletNode());
+      EXPECT_EQ(ch.tertiaryInletModelObject()->handle(), ch.heatRecoveryInletNode()->handle());
+      ASSERT_TRUE(ch.heatRecoveryOutletNode());
+      EXPECT_EQ(ch.tertiaryOutletModelObject()->handle(), ch.heatRecoveryOutletNode()->handle());
+    } else {
+      EXPECT_FALSE(ch.heatRecoveryLoop());
+      EXPECT_FALSE(ch.heatRecoveryInletNode());
+      EXPECT_FALSE(ch.heatRecoveryOutletNode());
+    }
+  };
+
+  // Heat Recovery
+  {
+    if constexpr (ChillerElectricASHRAE205::isHeatRecoverySupportedByEnergyplus) {
+      EXPECT_TRUE(hrLoop.addDemandBranchForComponent(ch));
+    } else {
+      EXPECT_FALSE(hrLoop.addDemandBranchForComponent(ch));
+    }
+
+    ASSERT_TRUE(ch.chilledWaterLoop());
+    ASSERT_EQ(chwLoop, ch.chilledWaterLoop().get());
+    EXPECT_TRUE(ch.chilledWaterInletNode());
+    EXPECT_EQ(ch.supplyInletModelObject()->handle(), ch.chilledWaterInletNode()->handle());
+    EXPECT_TRUE(ch.chilledWaterOutletNode());
+    EXPECT_EQ(ch.supplyOutletModelObject()->handle(), ch.chilledWaterOutletNode()->handle());
+
+    ASSERT_TRUE(ch.condenserWaterLoop());
+    EXPECT_EQ(cndLoop, ch.condenserWaterLoop().get());
+    ASSERT_TRUE(ch.condenserInletNode());
+    EXPECT_EQ(ch.demandInletModelObject()->handle(), ch.condenserInletNode()->handle());
+    ASSERT_TRUE(ch.condenserOutletNode());
+    EXPECT_EQ(ch.demandOutletModelObject()->handle(), ch.condenserOutletNode()->handle());
+
+    checkHeatRecoveryLoop();
+
+    EXPECT_FALSE(ch.oilCoolerLoop());
+    EXPECT_FALSE(ch.oilCoolerInletNode());
+    EXPECT_FALSE(ch.oilCoolerOutletNode());
+
+    EXPECT_FALSE(ch.auxiliaryLoop());
+    EXPECT_FALSE(ch.auxiliaryInletNode());
+    EXPECT_FALSE(ch.auxiliaryOutletNode());
+  }
+
+  // Oil Cooler Loop
+  {
+    auto ocDemandConnectionNodes = ocLoop.demandComponents(ocLoop.demandSplitter(), ocLoop.demandMixer(), IddObjectType::OS_Node);
+
+    // addToNode
+    {
+      ASSERT_EQ(1, ocDemandConnectionNodes.size());
+      auto ocDemandConnectionNode = ocDemandConnectionNodes[0].cast<Node>();
+      EXPECT_EQ(5, ocLoop.demandComponents().size());
+      EXPECT_TRUE(ch.addToOilCoolerLoopNode(ocDemandConnectionNode));
+      EXPECT_EQ(7, ocLoop.demandComponents().size());
+
+      ASSERT_TRUE(ch.chilledWaterLoop());
+      ASSERT_EQ(chwLoop, ch.chilledWaterLoop().get());
+      EXPECT_TRUE(ch.chilledWaterInletNode());
+      EXPECT_EQ(ch.supplyInletModelObject()->handle(), ch.chilledWaterInletNode()->handle());
+      EXPECT_TRUE(ch.chilledWaterOutletNode());
+      EXPECT_EQ(ch.supplyOutletModelObject()->handle(), ch.chilledWaterOutletNode()->handle());
+
+      ASSERT_TRUE(ch.condenserWaterLoop());
+      EXPECT_EQ(cndLoop, ch.condenserWaterLoop().get());
+      ASSERT_TRUE(ch.condenserInletNode());
+      EXPECT_EQ(ch.demandInletModelObject()->handle(), ch.condenserInletNode()->handle());
+      ASSERT_TRUE(ch.condenserOutletNode());
+      EXPECT_EQ(ch.demandOutletModelObject()->handle(), ch.condenserOutletNode()->handle());
+
+      checkHeatRecoveryLoop();
+
+      ASSERT_TRUE(ch.oilCoolerLoop());
+      EXPECT_EQ(ocLoop, ch.oilCoolerLoop().get());
+      ASSERT_TRUE(ch.oilCoolerInletNode());
+      EXPECT_EQ(ch.oilCoolerInletModelObject()->handle(), ch.oilCoolerInletNode()->handle());
+      ASSERT_TRUE(ch.oilCoolerOutletNode());
+      EXPECT_EQ(ch.oilCoolerOutletModelObject()->handle(), ch.oilCoolerOutletNode()->handle());
+
+      EXPECT_FALSE(ch.auxiliaryLoop());
+      EXPECT_FALSE(ch.auxiliaryInletNode());
+      EXPECT_FALSE(ch.auxiliaryOutletNode());
+    }
+
+    // Try removeFromLoop
+    {
+      ch.removeFromOilCoolerLoop();
+      ASSERT_TRUE(ch.chilledWaterLoop());
+      ASSERT_EQ(chwLoop, ch.chilledWaterLoop().get());
+      EXPECT_TRUE(ch.chilledWaterInletNode());
+      EXPECT_EQ(ch.supplyInletModelObject()->handle(), ch.chilledWaterInletNode()->handle());
+      EXPECT_TRUE(ch.chilledWaterOutletNode());
+      EXPECT_EQ(ch.supplyOutletModelObject()->handle(), ch.chilledWaterOutletNode()->handle());
+
+      ASSERT_TRUE(ch.condenserWaterLoop());
+      EXPECT_EQ(cndLoop, ch.condenserWaterLoop().get());
+      ASSERT_TRUE(ch.condenserInletNode());
+      EXPECT_EQ(ch.demandInletModelObject()->handle(), ch.condenserInletNode()->handle());
+      ASSERT_TRUE(ch.condenserOutletNode());
+      EXPECT_EQ(ch.demandOutletModelObject()->handle(), ch.condenserOutletNode()->handle());
+
+      checkHeatRecoveryLoop();
+
+      EXPECT_FALSE(ch.oilCoolerLoop());
+      EXPECT_FALSE(ch.oilCoolerInletNode());
+      EXPECT_FALSE(ch.oilCoolerOutletNode());
+
+      EXPECT_FALSE(ch.auxiliaryLoop());
+      EXPECT_FALSE(ch.auxiliaryInletNode());
+      EXPECT_FALSE(ch.auxiliaryOutletNode());
+
+      EXPECT_EQ(5, ocLoop.demandComponents().size());
+    }
+    // Try addDemandBranchOnLoop
+    {
+
+      EXPECT_TRUE(ch.addDemandBranchOnOilCoolerLoop(ocLoop));
+      EXPECT_EQ(7, ocLoop.demandComponents().size());
+
+      ASSERT_TRUE(ch.chilledWaterLoop());
+      ASSERT_EQ(chwLoop, ch.chilledWaterLoop().get());
+      EXPECT_TRUE(ch.chilledWaterInletNode());
+      EXPECT_EQ(ch.supplyInletModelObject()->handle(), ch.chilledWaterInletNode()->handle());
+      EXPECT_TRUE(ch.chilledWaterOutletNode());
+      EXPECT_EQ(ch.supplyOutletModelObject()->handle(), ch.chilledWaterOutletNode()->handle());
+
+      ASSERT_TRUE(ch.condenserWaterLoop());
+      EXPECT_EQ(cndLoop, ch.condenserWaterLoop().get());
+      ASSERT_TRUE(ch.condenserInletNode());
+      EXPECT_EQ(ch.demandInletModelObject()->handle(), ch.condenserInletNode()->handle());
+      ASSERT_TRUE(ch.condenserOutletNode());
+      EXPECT_EQ(ch.demandOutletModelObject()->handle(), ch.condenserOutletNode()->handle());
+
+      checkHeatRecoveryLoop();
+
+      ASSERT_TRUE(ch.oilCoolerLoop());
+      EXPECT_EQ(ocLoop, ch.oilCoolerLoop().get());
+      ASSERT_TRUE(ch.oilCoolerInletNode());
+      EXPECT_EQ(ch.oilCoolerInletModelObject()->handle(), ch.oilCoolerInletNode()->handle());
+      ASSERT_TRUE(ch.oilCoolerOutletNode());
+      EXPECT_EQ(ch.oilCoolerOutletModelObject()->handle(), ch.oilCoolerOutletNode()->handle());
+
+      EXPECT_FALSE(ch.auxiliaryLoop());
+      EXPECT_FALSE(ch.auxiliaryInletNode());
+      EXPECT_FALSE(ch.auxiliaryOutletNode());
+    }
+  }
+
+  // Auxiliary Loop
+  {
+    // AddToNode
+    {
+      auto auxDemandConnectionNodes = auxLoop.demandComponents(auxLoop.demandSplitter(), auxLoop.demandMixer(), IddObjectType::OS_Node);
+      ASSERT_EQ(1, auxDemandConnectionNodes.size());
+      auto auxDemandConnectionNode = auxDemandConnectionNodes[0].cast<Node>();
+      EXPECT_EQ(5, auxLoop.demandComponents().size());
+      EXPECT_TRUE(ch.addToAuxiliaryLoopNode(auxDemandConnectionNode));
+      EXPECT_EQ(7, auxLoop.demandComponents().size());
+
+      ASSERT_TRUE(ch.chilledWaterLoop());
+      ASSERT_EQ(chwLoop, ch.chilledWaterLoop().get());
+      ASSERT_TRUE(ch.plantLoop());
+      ASSERT_EQ(chwLoop, ch.plantLoop().get());
+      EXPECT_TRUE(ch.chilledWaterInletNode());
+      EXPECT_EQ(ch.supplyInletModelObject()->handle(), ch.chilledWaterInletNode()->handle());
+      EXPECT_TRUE(ch.chilledWaterOutletNode());
+      EXPECT_EQ(ch.supplyOutletModelObject()->handle(), ch.chilledWaterOutletNode()->handle());
+
+      ASSERT_TRUE(ch.condenserWaterLoop());
+      EXPECT_EQ(cndLoop, ch.condenserWaterLoop().get());
+      ASSERT_TRUE(ch.secondaryPlantLoop());
+      ASSERT_EQ(cndLoop, ch.secondaryPlantLoop().get());
+      ASSERT_TRUE(ch.condenserInletNode());
+      EXPECT_EQ(ch.demandInletModelObject()->handle(), ch.condenserInletNode()->handle());
+      ASSERT_TRUE(ch.condenserOutletNode());
+      EXPECT_EQ(ch.demandOutletModelObject()->handle(), ch.condenserOutletNode()->handle());
+
+      checkHeatRecoveryLoop();
+
+      ASSERT_TRUE(ch.oilCoolerLoop());
+      EXPECT_EQ(ocLoop, ch.oilCoolerLoop().get());
+      ASSERT_TRUE(ch.oilCoolerInletNode());
+      EXPECT_EQ(ch.oilCoolerInletModelObject()->handle(), ch.oilCoolerInletNode()->handle());
+      ASSERT_TRUE(ch.oilCoolerOutletNode());
+      EXPECT_EQ(ch.oilCoolerOutletModelObject()->handle(), ch.oilCoolerOutletNode()->handle());
+    }
+    {
+      // Try removeFromLoop
+      ch.removeFromAuxiliaryLoop();
+      EXPECT_EQ(5, auxLoop.demandComponents().size());
+
+      ASSERT_TRUE(ch.chilledWaterLoop());
+      ASSERT_EQ(chwLoop, ch.chilledWaterLoop().get());
+      EXPECT_TRUE(ch.chilledWaterInletNode());
+      EXPECT_EQ(ch.supplyInletModelObject()->handle(), ch.chilledWaterInletNode()->handle());
+      EXPECT_TRUE(ch.chilledWaterOutletNode());
+      EXPECT_EQ(ch.supplyOutletModelObject()->handle(), ch.chilledWaterOutletNode()->handle());
+
+      ASSERT_TRUE(ch.condenserWaterLoop());
+      EXPECT_EQ(cndLoop, ch.condenserWaterLoop().get());
+      ASSERT_TRUE(ch.condenserInletNode());
+      EXPECT_EQ(ch.demandInletModelObject()->handle(), ch.condenserInletNode()->handle());
+      ASSERT_TRUE(ch.condenserOutletNode());
+      EXPECT_EQ(ch.demandOutletModelObject()->handle(), ch.condenserOutletNode()->handle());
+
+      checkHeatRecoveryLoop();
+
+      ASSERT_TRUE(ch.oilCoolerLoop());
+      EXPECT_EQ(ocLoop, ch.oilCoolerLoop().get());
+      ASSERT_TRUE(ch.oilCoolerInletNode());
+      EXPECT_EQ(ch.oilCoolerInletModelObject()->handle(), ch.oilCoolerInletNode()->handle());
+      ASSERT_TRUE(ch.oilCoolerOutletNode());
+      EXPECT_EQ(ch.oilCoolerOutletModelObject()->handle(), ch.oilCoolerOutletNode()->handle());
+
+      EXPECT_FALSE(ch.auxiliaryLoop());
+      EXPECT_FALSE(ch.auxiliaryInletNode());
+      EXPECT_FALSE(ch.auxiliaryOutletNode());
+      EXPECT_EQ(5, auxLoop.demandComponents().size());
+    }
+
+    {
+      // Try addDemandBranchOnLoop
+      EXPECT_TRUE(ch.addDemandBranchOnAuxiliaryLoop(auxLoop));
+      EXPECT_EQ(7, auxLoop.demandComponents().size());
+
+      ASSERT_TRUE(ch.chilledWaterLoop());
+      ASSERT_EQ(chwLoop, ch.chilledWaterLoop().get());
+      ASSERT_TRUE(ch.plantLoop());
+      ASSERT_EQ(chwLoop, ch.plantLoop().get());
+      EXPECT_TRUE(ch.chilledWaterInletNode());
+      EXPECT_EQ(ch.supplyInletModelObject()->handle(), ch.chilledWaterInletNode()->handle());
+      EXPECT_TRUE(ch.chilledWaterOutletNode());
+      EXPECT_EQ(ch.supplyOutletModelObject()->handle(), ch.chilledWaterOutletNode()->handle());
+
+      ASSERT_TRUE(ch.condenserWaterLoop());
+      EXPECT_EQ(cndLoop, ch.condenserWaterLoop().get());
+      ASSERT_TRUE(ch.secondaryPlantLoop());
+      ASSERT_EQ(cndLoop, ch.secondaryPlantLoop().get());
+      ASSERT_TRUE(ch.condenserInletNode());
+      EXPECT_EQ(ch.demandInletModelObject()->handle(), ch.condenserInletNode()->handle());
+      ASSERT_TRUE(ch.condenserOutletNode());
+      EXPECT_EQ(ch.demandOutletModelObject()->handle(), ch.condenserOutletNode()->handle());
+
+      checkHeatRecoveryLoop();
+
+      ASSERT_TRUE(ch.oilCoolerLoop());
+      EXPECT_EQ(ocLoop, ch.oilCoolerLoop().get());
+      ASSERT_TRUE(ch.oilCoolerInletNode());
+      EXPECT_EQ(ch.oilCoolerInletModelObject()->handle(), ch.oilCoolerInletNode()->handle());
+      ASSERT_TRUE(ch.oilCoolerOutletNode());
+      EXPECT_EQ(ch.oilCoolerOutletModelObject()->handle(), ch.oilCoolerOutletNode()->handle());
+    }
+  }
+
+  // Removing the Chiller doesn't remove the ExternalFile
+  openstudio::path dstPath = representationFile->filePath();
+  EXPECT_TRUE(exists(p));
+  EXPECT_TRUE(exists(dstPath));
+
+  ch.remove();
+  EXPECT_EQ(1, m.getConcreteModelObjects<ExternalFile>().size());
+  EXPECT_EQ(0, m.getConcreteModelObjects<ChillerElectricASHRAE205>().size());
+
+  EXPECT_TRUE(exists(p));
+  EXPECT_TRUE(exists(dstPath));
+}
+
+TEST_F(ModelFixture, ChillerElectricASHRAE205_NotCBORFile) {
+  Model model;
+
+  openstudio::path p = resourcesPath() / toPath("model/7-7_Windows_Complete.osm");
+  EXPECT_TRUE(exists(p));
+
+  boost::optional<ExternalFile> representationFile = ExternalFile::getExternalFile(model, openstudio::toString(p));
+  ASSERT_TRUE(representationFile);
+
+  ASSERT_THROW(ChillerElectricASHRAE205{representationFile.get()}, openstudio::Exception);
+}
+
+TEST_F(ModelFixture, ChillerElectricASHRAE205_Clone) {
+  Model m;
+
+  openstudio::path p = resourcesPath() / toPath("model/A205ExampleChiller.RS0001.a205.cbor");
+  EXPECT_TRUE(exists(p));
+
+  openstudio::path expectedDestDir;
+  std::vector<openstudio::path> absoluteFilePaths = m.workflowJSON().absoluteFilePaths();
+  if (absoluteFilePaths.empty()) {
+    expectedDestDir = m.workflowJSON().absoluteRootDir();
+  } else {
+    expectedDestDir = absoluteFilePaths[0];
+  }
+
+  if (exists(expectedDestDir)) {
+    removeDirectory(expectedDestDir);
+  }
+  ASSERT_FALSE(exists(expectedDestDir));
+  EXPECT_TRUE(exists(p));
+
+  boost::optional<ExternalFile> representationFile = ExternalFile::getExternalFile(m, openstudio::toString(p));
+  ASSERT_TRUE(representationFile);
+
+  ChillerElectricASHRAE205 ch(representationFile.get());
+
+  EXPECT_EQ(1, m.getConcreteModelObjects<ExternalFile>().size());
+  EXPECT_EQ(1, m.getConcreteModelObjects<ChillerElectricASHRAE205>().size());
+  EXPECT_EQ(representationFile->handle(), ch.representationFile().handle());
+  EXPECT_EQ(1, representationFile->chillerElectricASHRAE205s().size());
+
+  {
+    // Another model first, so we don't mess the original one
+    Model m2;
+    auto ch2 = ch.clone(m2).cast<ChillerElectricASHRAE205>();
+
+    ASSERT_EQ(1, m2.getConcreteModelObjects<ExternalFile>().size());
+    auto representationFile2 = m2.getConcreteModelObjects<ExternalFile>().front();
+    EXPECT_EQ(1, m2.getConcreteModelObjects<ChillerElectricASHRAE205>().size());
+    EXPECT_EQ(representationFile2.handle(), ch2.representationFile().handle());
+    EXPECT_NE(representationFile->handle(), ch2.representationFile().handle());
+    EXPECT_EQ(1, representationFile2.chillerElectricASHRAE205s().size());
+  }
+
+  {
+    // Same Model, should point to the same ExternaFile
+    auto ch2 = ch.clone(m).cast<ChillerElectricASHRAE205>();
+    EXPECT_EQ(1, m.getConcreteModelObjects<ExternalFile>().size());
+    EXPECT_EQ(2, m.getConcreteModelObjects<ChillerElectricASHRAE205>().size());
+    EXPECT_EQ(representationFile->handle(), ch.representationFile().handle());
+    EXPECT_EQ(representationFile->handle(), ch2.representationFile().handle());
+    EXPECT_EQ(2, representationFile->chillerElectricASHRAE205s().size());
+  }
+}