bool WaterToAirComponent_Impl::removeFromAirLoopHVAC()
{
    if( auto t_oaSystem = airLoopHVACOutdoorAirSystem() ) {
        if( t_oaSystem->oaComponent(handle()) ) {
            return HVACComponent_Impl::removeFromLoop(t_oaSystem->outboardOANode().get(),
                    t_oaSystem.get(),
                    airInletPort(),
                    airOutletPort());
        } else if( t_oaSystem->reliefComponent(handle()) ) {
            return HVACComponent_Impl::removeFromLoop(t_oaSystem.get(),
                    t_oaSystem->outboardReliefNode().get(),
                    airInletPort(),
                    airOutletPort());
        }
    } else if( auto t_airLoop = airLoopHVAC() ) {
        if( t_airLoop->supplyComponent(handle()) ) {
            return HVACComponent_Impl::removeFromLoop(t_airLoop->supplyInletNode(),
                    t_airLoop->supplyOutletNode(),
                    airInletPort(),
                    airOutletPort());
        }
    }

    return false;
}
  void ZoneHVACComponent_Impl::removeFromAirLoopHVAC()
  {
    if( boost::optional<AirLoopHVAC> t_airLoopHVAC = airLoopHVAC() ) {
      boost::optional<Node> t_inletNode = inletNode();
      OS_ASSERT(t_inletNode);
      boost::optional<Node> t_outletNode = outletNode();
      OS_ASSERT(t_outletNode);

      unsigned targetPort = t_outletNode->connectedObjectPort(t_outletNode->outletPort()).get();
      ModelObject targetModelObject = t_outletNode->connectedObject(t_outletNode->outletPort()).get();
      t_outletNode->disconnect();
      t_outletNode->remove();

      Model t_model = model();
      t_model.connect( t_inletNode.get(), t_inletNode->outletPort(),
                       targetModelObject, targetPort );

      std::vector<AirTerminalSingleDuctInletSideMixer> terminalMixers = 
        subsetCastVector<AirTerminalSingleDuctInletSideMixer>(t_airLoopHVAC->demandComponents(t_airLoopHVAC->demandInletNode(),t_inletNode.get()));
      if( ! terminalMixers.empty() ) {
        if( boost::optional<Node> secondaryNode = terminalMixers.front().secondaryAirInletNode() ) {
          secondaryNode->disconnect();
          secondaryNode->remove();
        }
      }

    }
  }
Exemple #3
0
bool Mixer_Impl::isRemovable() const
{
    if( airLoopHVAC() || plantLoop() )
    {
        return false;
    }
    else
    {
        return true;
    }
}
  std::vector<ThermalZone> AirLoopHVACZoneSplitter_Impl::thermalZones()
  {
    std::vector<ThermalZone> zones;
    std::vector<ModelObject> modelObjects;
    std::vector<ModelObject> _outletModelObjects = outletModelObjects();

    OptionalAirLoopHVAC _airLoopHVAC = airLoopHVAC();
    OptionalNode demandOutletNode;
    OptionalNode demandInletNode;
    if( _airLoopHVAC )
    {
      demandOutletNode = _airLoopHVAC->demandOutletNode();
      demandInletNode = _airLoopHVAC->demandInletNode();
    }
    else
    {
      return zones;
    }

    modelObjects = _airLoopHVAC->demandComponents( demandInletNode.get(),
                                                   demandOutletNode.get(),
                                                   ThermalZone::iddObjectType() );

    for( std::vector<ModelObject>::iterator it = modelObjects.begin();
    it < modelObjects.end();
    it++ )
    {
      OptionalThermalZone zone;
      zone = it->optionalCast<ThermalZone>();
      if( zone )
      {
        zones.push_back(*zone);
      }
    }

    return zones;
  }
bool WaterToAirComponent_Impl::removeFromAirLoopHVAC()
{
    Model _model = model();
    ModelObject thisObject = getObject<ModelObject>();

    if( boost::optional<AirLoopHVAC> airLoop = airLoopHVAC() )
    {
        if( airOutletModelObject().get() == airLoop->supplyOutletNodes().front() &&
                airInletModelObject().get() == airLoop->supplyInletNode() )
        {
            ModelObject sourceModelObject = airInletModelObject().get();
            unsigned sourcePort = connectedObjectPort( airInletPort() ).get();
            ModelObject targetModelObject = airOutletModelObject().get();
            unsigned targetPort = connectedObjectPort( airOutletPort() ).get();

            model().disconnect(thisObject,airOutletPort());
            model().disconnect(thisObject,airInletPort());

            _model.connect( sourceModelObject, sourcePort,
                            targetModelObject, targetPort );
            return true;
        }
        else if( airOutletModelObject().get() == airLoop->supplyOutletNodes().front() )
        {
            Node sourceModelObject = airInletModelObject()->optionalCast<Node>().get();
            ModelObject targetModelObject = airOutletModelObject().get();
            unsigned targetPort = connectedObjectPort( airOutletPort() ).get();
            ModelObject source2ModelObject = sourceModelObject.inletModelObject().get();
            unsigned source2Port = sourceModelObject.connectedObjectPort( sourceModelObject.inletPort() ).get();

            model().disconnect(thisObject,airOutletPort());
            model().disconnect(thisObject,airInletPort());

            _model.connect( source2ModelObject, source2Port,
                            targetModelObject, targetPort );

            sourceModelObject.remove();

            return true;
        }
        else
        {
            ModelObject sourceModelObject = airInletModelObject().get();
            unsigned sourcePort = connectedObjectPort( airInletPort() ).get();
            Node targetModelObject = airOutletModelObject()->optionalCast<Node>().get();
            ModelObject target2ModelObject = targetModelObject.outletModelObject().get();
            unsigned target2Port = targetModelObject.connectedObjectPort( targetModelObject.outletPort() ).get();

            model().disconnect(thisObject,airOutletPort());
            model().disconnect(thisObject,airInletPort());


            _model.connect( sourceModelObject, sourcePort,
                            target2ModelObject, target2Port );

            targetModelObject.remove();

            return true;
        }
    }

    return false;
}
bool WaterToAirComponent_Impl::addToNode(Node & node)
{
    Model _model = node.model();
    ModelObject thisModelObject = getObject<ModelObject>();
    boost::optional<AirLoopHVACOutdoorAirSystem> oaSystem = node.airLoopHVACOutdoorAirSystem();

    if( node.airLoopHVAC() && ! oaSystem )
    {
        AirLoopHVAC airLoop = node.airLoopHVAC().get();
        if( airLoop.demandComponent( node.handle() ) )
        {
            return false;
        }
        else
        {
            if( airLoopHVAC() )
            {
                removeFromAirLoopHVAC();
            }

            if( node == airLoop.supplyOutletNode() &&
                    node.inletModelObject().get() == airLoop.supplyInletNode() )
            {
                unsigned oldOutletPort = node.connectedObjectPort( node.inletPort() ).get();
                unsigned oldInletPort = node.inletPort();
                ModelObject oldSourceModelObject = node.connectedObject( node.inletPort() ).get();
                ModelObject oldTargetModelObject = node;

                _model.connect( oldSourceModelObject, oldOutletPort,
                                thisModelObject, airInletPort() );
                _model.connect( thisModelObject, airOutletPort(),
                                oldTargetModelObject, oldInletPort );
                return true;
            }
            if( node == airLoop.supplyInletNode() &&
                    node.outletModelObject().get() == airLoop.supplyOutletNode() )
            {
                unsigned oldOutletPort = node.outletPort();
                unsigned oldInletPort = node.connectedObjectPort( node.outletPort() ).get();
                ModelObject oldSourceModelObject = node;
                ModelObject oldTargetModelObject = node.outletModelObject().get();

                _model.connect( oldSourceModelObject, oldOutletPort,
                                thisModelObject, airInletPort() );
                _model.connect( thisModelObject, airOutletPort(),
                                oldTargetModelObject, oldInletPort );
                return true;
            }
            else if( node == airLoop.supplyOutletNode() )
            {
                unsigned oldOutletPort = node.connectedObjectPort( node.inletPort() ).get();
                unsigned oldInletPort = node.inletPort();
                ModelObject oldSourceModelObject = node.connectedObject( node.inletPort() ).get();
                ModelObject oldTargetModelObject = node;

                Node newNode( _model );
                _model.connect( oldSourceModelObject, oldOutletPort,
                                newNode, newNode.inletPort() );
                _model.connect( newNode, newNode.outletPort(),
                                thisModelObject, airInletPort() );
                _model.connect( thisModelObject, airOutletPort(),
                                oldTargetModelObject, oldInletPort );
                return true;
            }
            else
            {
                unsigned oldOutletPort = node.outletPort();
                unsigned oldInletPort = node.connectedObjectPort( node.outletPort() ).get();
                ModelObject oldSourceModelObject = node;
                ModelObject oldTargetModelObject = node.connectedObject( node.outletPort() ).get();

                Node newNode( _model );
                _model.connect( oldSourceModelObject, oldOutletPort,
                                thisModelObject, airInletPort() );
                _model.connect( thisModelObject, airOutletPort(),
                                newNode, newNode.inletPort() );
                _model.connect( newNode, newNode.outletPort(),
                                oldTargetModelObject, oldInletPort );
                return true;
            }
        }
    }
    else if( node.plantLoop() )
    {
        PlantLoop _plantLoop = node.plantLoop().get();
        if( ! _plantLoop.demandComponent( node.handle() ) )
        {
            return false;
        }
        else
        {
            if( plantLoop() )
            {
                removeFromPlantLoop();
            }

            if( node == _plantLoop.demandOutletNode() &&
                    node.inletModelObject().get() == _plantLoop.demandInletNode() )
            {
                unsigned oldOutletPort = node.connectedObjectPort( node.inletPort() ).get();
                unsigned oldInletPort = node.inletPort();
                ModelObject oldSourceModelObject = node.connectedObject( node.inletPort() ).get();
                ModelObject oldTargetModelObject = node;

                _model.connect( oldSourceModelObject, oldOutletPort,
                                thisModelObject, waterInletPort() );
                _model.connect( thisModelObject, waterOutletPort(),
                                oldTargetModelObject, oldInletPort );
                return true;
            }
            else if( node == _plantLoop.demandOutletNode() )
            {
                unsigned oldOutletPort = node.connectedObjectPort( node.inletPort() ).get();
                unsigned oldInletPort = node.inletPort();
                ModelObject oldSourceModelObject = node.connectedObject( node.inletPort() ).get();
                ModelObject oldTargetModelObject = node;

                Node newNode( _model );
                _model.connect( oldSourceModelObject, oldOutletPort,
                                newNode, newNode.inletPort() );
                _model.connect( newNode, newNode.outletPort(),
                                thisModelObject, waterInletPort() );
                _model.connect( thisModelObject, waterOutletPort(),
                                oldTargetModelObject, oldInletPort );
                return true;
            }
            else
            {
                unsigned oldOutletPort = node.outletPort();
                unsigned oldInletPort = node.connectedObjectPort( node.outletPort() ).get();
                ModelObject oldSourceModelObject = node;
                ModelObject oldTargetModelObject = node.connectedObject( node.outletPort() ).get();

                Node newNode( _model );
                _model.connect( oldSourceModelObject, oldOutletPort,
                                thisModelObject, waterInletPort() );
                _model.connect( thisModelObject, waterOutletPort(),
                                newNode, newNode.inletPort() );
                _model.connect( newNode, newNode.outletPort(),
                                oldTargetModelObject, oldInletPort );
                return true;
            }
        }
    }
    else
    {
        return false;
    }
}
  std::vector<IdfObject> AirTerminalSingleDuctInletSideMixer_Impl::remove()
  {
    Model _model = this->model();
    AirTerminalSingleDuctInletSideMixer thisObject = this->getObject<AirTerminalSingleDuctInletSideMixer>();
    boost::optional<ThermalZone> t_thermalZone;
    boost::optional<ZoneHVACComponent> t_zoneComp;

    if( boost::optional<AirLoopHVAC> t_airLoopHVAC = airLoopHVAC() ) {
      std::vector<ZoneHVACComponent> zoneComps = 
        subsetCastVector<ZoneHVACComponent>(t_airLoopHVAC->demandComponents(thisObject,t_airLoopHVAC->demandOutletNode()));
      if( ! zoneComps.empty() ) {
        t_zoneComp = zoneComps.front();
        t_thermalZone = t_zoneComp->thermalZone();
        t_zoneComp->removeFromThermalZone();
      }
    }

    boost::optional<ModelObject> sourceModelObject = this->inletModelObject();
    boost::optional<unsigned> sourcePort = this->connectedObjectPort(this->inletPort());
    
    boost::optional<ModelObject> targetModelObject = this->outletModelObject();
    boost::optional<unsigned> targetPort = this->connectedObjectPort(this->outletPort());

    std::vector<ThermalZone> thermalZones = _model.getConcreteModelObjects<ThermalZone>();
    for( auto & thermalZone : thermalZones )
    {
      std::vector<ModelObject> equipment = thermalZone.equipment();

      if( std::find(equipment.begin(),equipment.end(),thisObject) != equipment.end() )
      {
        thermalZone.removeEquipment(thisObject);

        break;
      }
    }

    if( sourcePort && sourceModelObject
        && targetPort && targetModelObject )
    {
      if( boost::optional<Node> inletNode = sourceModelObject->optionalCast<Node>() )
      {
        if( boost::optional<ModelObject> source2ModelObject = inletNode->inletModelObject() )
        {
          if( boost::optional<unsigned> source2Port = inletNode->connectedObjectPort(inletNode->inletPort()) )
          {
            _model.connect( source2ModelObject.get(),
                            source2Port.get(),
                            targetModelObject.get(),
                            targetPort.get() );

            inletNode->disconnect();
            inletNode->remove();

            std::vector<IdfObject> result =  StraightComponent_Impl::remove();
            if( t_thermalZone ) {
              t_zoneComp->addToThermalZone(t_thermalZone.get());
            }
            return result;
          }
        }
      }
    }

    model().disconnect(getObject<ModelObject>(),inletPort());
    model().disconnect(getObject<ModelObject>(),outletPort());

    return StraightComponent_Impl::remove();
  }
Exemple #8
0
 boost::optional<ModelObject> HVACComponent_Impl::airLoopHVACAsModelObject() const {
   if (OptionalAirLoopHVAC intermediate = airLoopHVAC()) {
     return *intermediate;
   }
   return boost::none;
 }
OptionalModelObject ReverseTranslator::translateAirLoopHVAC( const WorkspaceObject & workspaceObject )
{
  if( workspaceObject.iddObject().type() != IddObjectType::AirLoopHVAC )
  {
     LOG(Error, "WorkspaceObject is not IddObjectType: AirLoopHVAC");
     return boost::none;
  }

  OptionalModelObject result;
  boost::optional<double> val;
  boost::optional<std::string> optionalString;
  Workspace _workspace = workspaceObject.workspace();

  openstudio::model::AirLoopHVAC airLoopHVAC( m_model );

  boost::optional<std::string> supplyInletNodeName = workspaceObject.getString(AirLoopHVACFields::SupplySideInletNodeName);
  boost::optional<std::string> supplyOutletNodeName = workspaceObject.getString(AirLoopHVACFields::SupplySideOutletNodeNames);
  boost::optional<std::string> demandInletNodeName = workspaceObject.getString(AirLoopHVACFields::DemandSideInletNodeNames);
  boost::optional<std::string> demandOutletNodeName = workspaceObject.getString(AirLoopHVACFields::DemandSideOutletNodeName);

  Node supplyInletNode = airLoopHVAC.supplyInletNode();
  Node supplyOutletNode = airLoopHVAC.supplyOutletNode();
  Node demandInletNode = airLoopHVAC.demandInletNode();
  Node demandOutletNode = airLoopHVAC.demandOutletNode();

  if( supplyInletNodeName ) { supplyInletNode.setName(supplyInletNodeName.get()); }
  if( supplyOutletNodeName ) { supplyOutletNode.setName(supplyOutletNodeName.get()); }
  if( demandInletNodeName ) { demandInletNode.setName(demandInletNodeName.get()); }
  if( demandOutletNodeName ) { demandOutletNode.setName(demandOutletNodeName.get()); }

  optionalString = workspaceObject.getString(AirLoopHVACFields::Name);
  if( optionalString )
  {
    airLoopHVAC.setName(optionalString.get());
  }

  optionalString = workspaceObject.getString(AirLoopHVACFields::DesignSupplyAirFlowRate);
  if( optionalString && istringEqual(optionalString.get(),"AutoSize") )
  {
    airLoopHVAC.autosizeDesignSupplyAirFlowRate();
  }
  else if( (val = workspaceObject.getDouble(AirLoopHVACFields::DesignSupplyAirFlowRate)) )
  {
    airLoopHVAC.setDesignSupplyAirFlowRate(val.get());
  }

  // Go find the supply branch.
  // Currently only supporting one supply branch.
  // Dual ducts are not supported.
  OptionalWorkspaceObject _supplyBranchList;
  OptionalWorkspaceObject _supplyBranch;

  _supplyBranchList = workspaceObject.getTarget(AirLoopHVACFields::BranchListName);
  if( _supplyBranchList )
  {
    _supplyBranch = _supplyBranchList->getExtensibleGroup(0).cast<WorkspaceExtensibleGroup>().getTarget(BranchListExtensibleFields::BranchName);
    if( ! _supplyBranch )
    {
      LOG(Error, _supplyBranchList->briefDescription() << ": Missing supply branch");
    }
    else
    {
      // March through the equipment on the supply branch and convert them.
      for( unsigned i = 0; ! _supplyBranch->getExtensibleGroup(i).empty(); i++ )
      {
        WorkspaceExtensibleGroup eg = _supplyBranch->getExtensibleGroup(i).cast<WorkspaceExtensibleGroup>();
        boost::optional<std::string> componentName = eg.getString(BranchExtensibleFields::ComponentName);
        boost::optional<std::string> componentType = eg.getString(BranchExtensibleFields::ComponentObjectType);
        boost::optional<std::string> componentInletNodeName = eg.getString(BranchExtensibleFields::ComponentInletNodeName);
        boost::optional<std::string> componentOutletNodeName = eg.getString(BranchExtensibleFields::ComponentOutletNodeName);
        boost::optional<WorkspaceObject> wo;
        OptionalNode node;
        OptionalModelObject targetModelObject;

        if( componentName && (componentName.get() != "") && componentType && (componentType.get() != "") )
        {
          IddObjectType iddType(componentType.get());
          wo = _workspace.getObjectByTypeAndName(iddType,componentName.get());
        }

        if( wo )
        {
          targetModelObject = translateAndMapWorkspaceObject( wo.get() );
          if( !targetModelObject)
          {
            LOG(Error, "Error importing object: " << wo->briefDescription() );
            continue;
          }

          if( OptionalHVACComponent hvacComponent = targetModelObject->optionalCast<HVACComponent>() )
          {
            Node node = airLoopHVAC.supplyOutletNode();
            if( hvacComponent->addToNode(node) )
            {
              if( boost::optional<StraightComponent> straightComponent = hvacComponent->optionalCast<StraightComponent>() )
              {
                Node outletNode = straightComponent->outletModelObject()->cast<Node>();
                Node inletNode = straightComponent->inletModelObject()->cast<Node>();
                if( componentOutletNodeName )
                {
                  outletNode.setName(componentOutletNodeName.get());
                }
                if( componentInletNodeName )
                {
                  inletNode.setName(componentInletNodeName.get());
                }
              }
              else if( boost::optional<AirLoopHVACOutdoorAirSystem> oaSystem = hvacComponent->optionalCast<AirLoopHVACOutdoorAirSystem>() )
              {
                Node outletNode = oaSystem->mixedAirModelObject()->cast<Node>();
                Node inletNode = oaSystem->returnAirModelObject()->cast<Node>();
                if( componentOutletNodeName )
                {
                  outletNode.setName(componentOutletNodeName.get());
                }
                if( componentInletNodeName )
                {
                  inletNode.setName(componentInletNodeName.get());
                }
              }
            }
          }
        }
        else
        {
          LOG(Error, _supplyBranch->briefDescription() << ": Missing object listed at ComponentName " << i);
        }
      }
    }
  }
  else
  {
    LOG( Error, workspaceObject.briefDescription() << ": Missing supply branch list, "
              << "Supply equipment will be incomplete");
  }

  // March through the zone on the demand side and add branches for them.
  if( demandOutletNodeName )
  {
    // Find the zone mixer for this air loop
    std::vector<WorkspaceObject> _airLoopHVACZoneMixers;
    _airLoopHVACZoneMixers = workspaceObject.workspace().getObjectsByType(IddObjectType::AirLoopHVAC_ZoneMixer);

    boost::optional<WorkspaceObject> _airLoopHVACZoneMixer;
    for( const auto & elem : _airLoopHVACZoneMixers )
    {
      boost::optional<std::string> mixerOutletNodeName;
      mixerOutletNodeName = elem.getString(AirLoopHVAC_ZoneMixerFields::OutletNodeName);

      if( mixerOutletNodeName && mixerOutletNodeName.get() == demandOutletNodeName.get() )
      {
        _airLoopHVACZoneMixer = elem;
        break;
      }
    }
    if( _airLoopHVACZoneMixer )
    {
      for( int i = 2;
           _airLoopHVACZoneMixer->getString(i);
           i++ )
      {

        std::vector<WorkspaceObject> _zoneHVACEquipmentConnections;

        std::string mixerInletNodeName = _airLoopHVACZoneMixer->getString(i).get();

        _zoneHVACEquipmentConnections = _workspace.getObjectsByType(IddObjectType::ZoneHVAC_EquipmentConnections);

        for( const auto & _zoneHVACEquipmentConnection : _zoneHVACEquipmentConnections )
        {

          OptionalString returnAirNodeName = _zoneHVACEquipmentConnection.getString(ZoneHVAC_EquipmentConnectionsFields::ZoneReturnAirNodeName);
          OptionalString inletAirNodeName = _zoneHVACEquipmentConnection.getString(ZoneHVAC_EquipmentConnectionsFields::ZoneAirInletNodeorNodeListName);
          OptionalString zoneName = _zoneHVACEquipmentConnection.getString(ZoneHVAC_EquipmentConnectionsFields::ZoneName);
          OptionalString zoneEquipListName = _zoneHVACEquipmentConnection.getString(ZoneHVAC_EquipmentConnectionsFields::ZoneConditioningEquipmentListName);

          OptionalWorkspaceObject _zone;
          OptionalWorkspaceObject _zoneEquipmentList;
          OptionalWorkspaceObject _zoneEquipment;
          OptionalWorkspaceObject _airTerminal; 

          if( returnAirNodeName &&
              returnAirNodeName.get() == mixerInletNodeName &&
              zoneName &&
              zoneEquipListName )
          {
            _zone = _workspace.getObjectByTypeAndName(IddObjectType::Zone,*zoneName);

            _zoneEquipmentList = _workspace.getObjectByTypeAndName(IddObjectType::ZoneHVAC_EquipmentList,zoneEquipListName.get());

            if( ! _zone )
            {
              LOG( Error, 
                  airLoopHVAC.briefDescription()
                  << " is connected to a zone that does not exist." );

              break;
            }

            if( ! _zoneEquipmentList )
            {
              LOG( Error, 
                  _zone->briefDescription()
                  << " does not have a zone equipment list, but it is attached to a loop." );

              break;
            }

            for( int j = 1; (optionalString = _zoneEquipmentList->getString(j)); j = j + 4 )
            {
              boost::optional<std::string> zoneEquipmentName = _zoneEquipmentList->getString(j+1) ;
              // Possible Zone Equipment
              //
              // ZoneHVAC:AirDistributionUnit
              // AirTerminal:SingleDuct:Uncontrolled
              // ZoneHVAC:EnergyRecoveryVentilator
              // ZoneHVAC:FourPipeFanCoil
              // ZoneHVAC:OutdoorAirUnit
              // ZoneHVAC:PackagedTerminalAirConditioner
              // ZoneHVAC:PackagedTerminalHeatPump
              // ZoneHVAC:UnitHeater
              // ZoneHVAC:UnitVentilator
              // ZoneHVAC:VentilatedSlab
              // ZoneHVAC:WaterToAirHeatPump
              // ZoneHVAC:WindowAirConditioner
              // ZoneHVAC:Baseboard:RadiantConvective:Electric
              // ZoneHVAC:Baseboard:RadiantConvective:Water
              // ZoneHVAC:Baseboard:RadiantConvective:Steam
              // ZoneHVAC:Baseboard:Convective:Electric
              // ZoneHVAC:Baseboard:Convective:Water
              // ZoneHVAC:HighTemperatureRadiant
              // ZoneHVAC:LowTemperatureRadiant:VariableFlow
              // ZoneHVAC:LowTemperatureRadiant:ConstantFlow
              // ZoneHVAC:LowTemperatureRadiant:Electric
              // ZoneHVAC:Dehumidifier:DX
              // ZoneHVAC:IdealLoadsAirSystem
              // Fan:ZoneExhaust
              // WaterHeater:HeatPump
              //
              if( zoneEquipmentName )
              {
                if( istringEqual(optionalString.get(),"AirTerminal:SingleDuct:Uncontrolled") )
                {
                  _airTerminal = _workspace.getObjectByTypeAndName(IddObjectType::AirTerminal_SingleDuct_Uncontrolled,zoneEquipmentName.get());

                  break;
                }
                else if( istringEqual(optionalString.get(),"ZoneHVAC:AirDistributionUnit") )
                {
                  boost::optional<WorkspaceObject> _airDistributionUnit = 
                    _workspace.getObjectByTypeAndName(IddObjectType::ZoneHVAC_AirDistributionUnit,zoneEquipmentName.get());

                  if( _airDistributionUnit )
                  {
                    boost::optional<std::string> airUnitName;
                    boost::optional<std::string> airUnitType;

                    airUnitType = _airDistributionUnit->getString(ZoneHVAC_AirDistributionUnitFields::AirTerminalObjectType);
                    airUnitName = _airDistributionUnit->getString(ZoneHVAC_AirDistributionUnitFields::AirTerminalName);

                    if( airUnitName && airUnitType )
                    {
                      _airTerminal = _workspace.getObjectByTypeAndName(IddObjectType(airUnitType.get()),airUnitName.get());
                    }
                  }

                  break;
                }
              }
            }

            OptionalModelObject airTerminalModelObject;
            OptionalSpace space;
            OptionalStraightComponent straightComponent;
            OptionalThermalZone thermalZone;

            if( _airTerminal )
            {
              airTerminalModelObject = translateAndMapWorkspaceObject( _airTerminal.get() );
            }

            if( _zone )
            {
              if( OptionalModelObject mo = translateAndMapWorkspaceObject( _zone.get() ) )
              {
                space = mo->optionalCast<Space>();
              }
            }

            if( space )
            {
              thermalZone = space->thermalZone();
            }

            if( airTerminalModelObject )
            {
              straightComponent = airTerminalModelObject->optionalCast<StraightComponent>();
            }

            bool success = false;

            if( straightComponent && thermalZone )
            {
              success = airLoopHVAC.addBranchForZone(thermalZone.get(),straightComponent.get());
            }
            else if( thermalZone )
            {
              Model m;

              success = airLoopHVAC.addBranchForZone(thermalZone.get(),boost::none);
            }

            if( success )
            {
              if( inletAirNodeName ) { thermalZone->inletPortList().airLoopHVACModelObject()->cast<Node>().setName(inletAirNodeName.get()); }
              if( returnAirNodeName ) { thermalZone->returnAirModelObject()->cast<Node>().setName(returnAirNodeName.get()); }
            }
          }
        }
      }
    }
  }

  return airLoopHVAC;
}