bool SteamEquipment_Impl::hardSize() {
    OptionalSpace space = this->space();
    if (!space) {
        return false;
    }

    makeUnique();

    SteamEquipmentDefinition definition = steamEquipmentDefinition();
    for (LifeCycleCost cost : definition.lifeCycleCosts()) {
        cost.convertToCostPerEach();
    }

    if (definition.designLevel()) {
        return true;
    }
    if (OptionalDouble areaDensity = definition.wattsperSpaceFloorArea()) {
        return definition.setDesignLevel(*areaDensity * space->floorArea());
    }
    if (OptionalDouble peopleDensity = definition.wattsperPerson()) {
        return definition.setDesignLevel(*peopleDensity * space->numberOfPeople());
    }

    OS_ASSERT(false);
    return false;
}
Exemple #2
0
 double Building_Impl::exteriorSurfaceArea() const {
   double result(0.0);
   for (const Surface& surface : model().getModelObjects<Surface>()) {
     OptionalSpace space = surface.space();
     std::string outsideBoundaryCondition = surface.outsideBoundaryCondition();
     if (space && openstudio::istringEqual(outsideBoundaryCondition, "Outdoors")) {
       result += surface.grossArea() * space->multiplier();
     }
   }
   return result;
 }
TEST_F(ModelFixture, ShadingSurfaceGroup_Space_Hierarchy)
{
  Model model;

  // add a space
  Space space(model);

  // add a shading surface group
  ShadingSurfaceGroup group(model);
  EXPECT_EQ("Building", group.shadingSurfaceType());
  EXPECT_TRUE(group.setSpace(space));
  EXPECT_EQ("Space", group.shadingSurfaceType());
  ASSERT_TRUE(group.space());
  EXPECT_EQ(space.handle(), group.space()->handle());

  // make a new shading surface
  Point3dVector points;
  points.push_back(Point3d(0, 2, 0));
  points.push_back(Point3d(0, 0, 0));
  points.push_back(Point3d(1, 0, 0));
  ShadingSurface surface(points, model);
  EXPECT_TRUE(surface.setShadingSurfaceGroup(group));
  ASSERT_TRUE(surface.shadingSurfaceGroup());
  EXPECT_EQ(group.handle(), surface.shadingSurfaceGroup()->handle());

  // check children from group
  ASSERT_EQ(static_cast<unsigned>(1), group.children().size());
  EXPECT_EQ(surface.handle(), group.children()[0].handle());

  // now check children from space
  ASSERT_EQ(static_cast<unsigned>(1), space.children().size());
  EXPECT_EQ(group.handle(), space.children()[0].handle());

  // check parent from group
  ASSERT_TRUE(group.parent());
  EXPECT_EQ(space.handle(), group.parent()->handle());

  // check parent from surface
  ASSERT_TRUE(surface.parent());
  EXPECT_EQ(group.handle(), surface.parent()->handle());

  // clone the space
  ModelObject clone = space.clone(model);
  OptionalSpace spaceClone = clone.optionalCast<Space>();
  ASSERT_TRUE(spaceClone);
  ASSERT_EQ(static_cast<unsigned>(1), spaceClone->children().size());
  EXPECT_NE(group.handle(), spaceClone->children()[0].handle());
  OptionalShadingSurfaceGroup cloneChild = spaceClone->children()[0].optionalCast<ShadingSurfaceGroup>();
  ASSERT_TRUE(cloneChild);
  ASSERT_EQ(static_cast<unsigned>(1), cloneChild->children().size());
  EXPECT_NE(surface.handle(), cloneChild->children()[0].handle());
}
boost::optional<Schedule> SteamEquipment_Impl::schedule() const {
    OptionalSchedule result = getObject<SteamEquipment>().getModelObjectTarget<Schedule>(OS_SteamEquipmentFields::ScheduleName);
    if (!result) {
        // search upwards
        OptionalSpace space = this->space();
        OptionalSpaceType spaceType = this->spaceType();
        if (space) {
            result = space->getDefaultSchedule(DefaultScheduleType::SteamEquipmentSchedule);
        } else if (spaceType) {
            result = spaceType->getDefaultSchedule(DefaultScheduleType::SteamEquipmentSchedule);
        }
    }
    return result;
}
 boost::optional<Schedule> SpaceInfiltrationEffectiveLeakageArea_Impl::schedule() const
 {
   boost::optional<Schedule> result = getObject<ModelObject>().getModelObjectTarget<Schedule>(OS_SpaceInfiltration_EffectiveLeakageAreaFields::ScheduleName);
   if (!result){
     // search upwards
     OptionalSpace space = this->space();
     OptionalSpaceType spaceType = this->spaceType();
     if (space){
       result = space->getDefaultSchedule(DefaultScheduleType::InfiltrationSchedule);
     }else if (spaceType){
       result = spaceType->getDefaultSchedule(DefaultScheduleType::InfiltrationSchedule);
     }
   }
   return result;
 }
Exemple #6
0
 boost::optional<Schedule> Lights_Impl::schedule() const
 {
   boost::optional<Schedule> result = getObject<ModelObject>().getModelObjectTarget<Schedule>(OS_LightsFields::ScheduleName);
   if (!result){
     // search upwards
     OptionalSpace space = this->space();
     OptionalSpaceType spaceType = this->spaceType();
     if (space){
       result = space->getDefaultSchedule(DefaultScheduleType::LightingSchedule);
     }else if (spaceType){
       result = spaceType->getDefaultSchedule(DefaultScheduleType::LightingSchedule);
     }
   }
   return result;
 }
TEST_F(ModelFixture, InteriorPartitionSurface_Hierarchy)
{
  Model model;

  Space space(model);

  // add a interior partition surface group
  InteriorPartitionSurfaceGroup group(model);
  EXPECT_FALSE(group.space());
  EXPECT_TRUE(group.setSpace(space));
  ASSERT_TRUE(group.space());
  EXPECT_EQ(space.handle(), group.space()->handle());

  // make a new interior partition surface
  Point3dVector points;
  points.push_back(Point3d(0, 2, 0));
  points.push_back(Point3d(0, 0, 0));
  points.push_back(Point3d(1, 0, 0));
  InteriorPartitionSurface surface(points, model);
  EXPECT_FALSE(surface.interiorPartitionSurfaceGroup());
  EXPECT_TRUE(surface.setInteriorPartitionSurfaceGroup(group));
  ASSERT_TRUE(surface.interiorPartitionSurfaceGroup());
  EXPECT_EQ(group.handle(), surface.interiorPartitionSurfaceGroup()->handle());

  // check children from group
  ASSERT_EQ(static_cast<unsigned>(1), group.children().size());
  EXPECT_EQ(surface.handle(), group.children()[0].handle());

  // now check children from space
  ASSERT_EQ(static_cast<unsigned>(1), space.children().size());
  EXPECT_EQ(group.handle(), space.children()[0].handle());

  // check parent from group
  ASSERT_TRUE(group.parent());
  EXPECT_EQ(space.handle(), group.parent()->handle());

  // check parent from surface
  ASSERT_TRUE(surface.parent());
  EXPECT_EQ(group.handle(), surface.parent()->handle());

  // clone the space
  ModelObject clone = space.clone(model);
  OptionalSpace spaceClone = clone.optionalCast<Space>();
  ASSERT_TRUE(spaceClone);
  ASSERT_EQ(static_cast<unsigned>(1), spaceClone->children().size());
  EXPECT_NE(group.handle(), spaceClone->children()[0].handle());
}
OptionalModelObject ReverseTranslator::translateDaylightingControls( const WorkspaceObject & workspaceObject )
{
  if( workspaceObject.iddObject().type() != IddObjectType::Daylighting_Controls ){
    LOG(Error, "WorkspaceObject is not IddObjectType: Daylighting:Controls");
    return boost::none;
  }

  DaylightingControl daylightingControl(m_model);

  OptionalThermalZone thermalZone;
  OptionalSpace space;
  OptionalWorkspaceObject target = workspaceObject.getTarget(Daylighting_ControlsFields::ZoneName);
  if (target){
    OptionalModelObject modelObject = translateAndMapWorkspaceObject(*target);
    if (modelObject){
      if (modelObject->optionalCast<Space>()){
        space = modelObject->cast<Space>();
        thermalZone = space->thermalZone();
      }
    }
  }

  if (space){
    daylightingControl.setSpace(*space);
  }

  if (thermalZone){
    thermalZone->setPrimaryDaylightingControl(daylightingControl);
  }

  OptionalDouble d = workspaceObject.getDouble(Daylighting_ControlsFields::XCoordinateofFirstReferencePoint);
  if (d){
    daylightingControl.setPositionXCoordinate(*d);
  }

  d = workspaceObject.getDouble(Daylighting_ControlsFields::YCoordinateofFirstReferencePoint);
  if (d){
    daylightingControl.setPositionYCoordinate(*d);
  }

  d = workspaceObject.getDouble(Daylighting_ControlsFields::ZCoordinateofFirstReferencePoint);
  if (d){
    daylightingControl.setPositionZCoordinate(*d);
  }

  d = workspaceObject.getDouble(Daylighting_ControlsFields::FractionofZoneControlledbyFirstReferencePoint);
  if (d && thermalZone){
    thermalZone->setFractionofZoneControlledbyPrimaryDaylightingControl(*d);
  }

  d = workspaceObject.getDouble(Daylighting_ControlsFields::IlluminanceSetpointatFirstReferencePoint);
  if (d){
    daylightingControl.setIlluminanceSetpoint(*d);
  }

  OptionalInt i = workspaceObject.getInt(Daylighting_ControlsFields::LightingControlType);
  if (i){
    switch (*i){
      case 1:
        daylightingControl.setLightingControlType("Continuous");
        break;
      case 2:
        daylightingControl.setLightingControlType("Stepped");
        break;
      case 3:
        daylightingControl.setLightingControlType("Continuous/Off");
        break;
      default:
        ;
    }
  }

  d = workspaceObject.getDouble(Daylighting_ControlsFields::GlareCalculationAzimuthAngleofViewDirectionClockwisefromZoneyAxis);
  if (d){
    daylightingControl.setThetaRotationAroundYAxis( -degToRad(*d) );
  }

  d = workspaceObject.getDouble(Daylighting_ControlsFields::MaximumAllowableDiscomfortGlareIndex);
  if (d){
    daylightingControl.setMaximumAllowableDiscomfortGlareIndex(*d);
  }

  d = workspaceObject.getDouble(Daylighting_ControlsFields::MinimumInputPowerFractionforContinuousDimmingControl);
  if (d){
    daylightingControl.setMinimumInputPowerFractionforContinuousDimmingControl(*d);
  }

  d = workspaceObject.getDouble(Daylighting_ControlsFields::MinimumLightOutputFractionforContinuousDimmingControl);
  if (d){
    daylightingControl.setMinimumLightOutputFractionforContinuousDimmingControl(*d);
  }

  i = workspaceObject.getInt(Daylighting_ControlsFields::NumberofSteppedControlSteps);
  if (i){
    daylightingControl.setNumberofSteppedControlSteps(*i);
  }

  d = workspaceObject.getDouble(Daylighting_ControlsFields::ProbabilityLightingwillbeResetWhenNeededinManualSteppedControl);
  if (d){
    daylightingControl.setProbabilityLightingwillbeResetWhenNeededinManualSteppedControl(*d);
  }

  i = workspaceObject.getInt(Daylighting_ControlsFields::TotalDaylightingReferencePoints);
  if (i){
    if (*i == 1){
      return daylightingControl;
    }
  }else{
    return daylightingControl;
  }

  DaylightingControl daylightingControl2(m_model);

  if (space){
    daylightingControl2.setSpace(*space);
  }

  if (thermalZone){
    thermalZone->setSecondaryDaylightingControl(daylightingControl2);
  }

  d = workspaceObject.getDouble(Daylighting_ControlsFields::XCoordinateofSecondReferencePoint);
  if (d){
    daylightingControl2.setPositionXCoordinate(*d);
  }

  d = workspaceObject.getDouble(Daylighting_ControlsFields::YCoordinateofSecondReferencePoint);
  if (d){
    daylightingControl2.setPositionYCoordinate(*d);
  }

  d = workspaceObject.getDouble(Daylighting_ControlsFields::ZCoordinateofSecondReferencePoint);
  if (d){
    daylightingControl2.setPositionZCoordinate(*d);
  }

  d = workspaceObject.getDouble(Daylighting_ControlsFields::FractionofZoneControlledbySecondReferencePoint);
  if (d && thermalZone){
    thermalZone->setFractionofZoneControlledbySecondaryDaylightingControl(*d);
  }

  d = workspaceObject.getDouble(Daylighting_ControlsFields::IlluminanceSetpointatSecondReferencePoint);
  if (d){
    daylightingControl2.setIlluminanceSetpoint(*d);
  }

  i = workspaceObject.getInt(Daylighting_ControlsFields::LightingControlType);
  if (i){
    switch (*i){
      case 1:
        daylightingControl2.setLightingControlType("Continuous");
        break;
      case 2:
        daylightingControl2.setLightingControlType("Stepped");
        break;
      case 3:
        daylightingControl2.setLightingControlType("Continuous/Off");
        break;
      default:
        ;
    }
  }

  d = workspaceObject.getDouble(Daylighting_ControlsFields::GlareCalculationAzimuthAngleofViewDirectionClockwisefromZoneyAxis);
  if (d){
    daylightingControl2.setThetaRotationAroundYAxis( -degToRad(*d) );
  }

  d = workspaceObject.getDouble(Daylighting_ControlsFields::MaximumAllowableDiscomfortGlareIndex);
  if (d){
    daylightingControl2.setMaximumAllowableDiscomfortGlareIndex(*d);
  }

  d = workspaceObject.getDouble(Daylighting_ControlsFields::MinimumInputPowerFractionforContinuousDimmingControl);
  if (d){
    daylightingControl2.setMinimumInputPowerFractionforContinuousDimmingControl(*d);
  }

  d = workspaceObject.getDouble(Daylighting_ControlsFields::MinimumLightOutputFractionforContinuousDimmingControl);
  if (d){
    daylightingControl2.setMinimumLightOutputFractionforContinuousDimmingControl(*d);
  }

  i = workspaceObject.getInt(Daylighting_ControlsFields::NumberofSteppedControlSteps);
  if (i){
    daylightingControl2.setNumberofSteppedControlSteps(*i);
  }

  d = workspaceObject.getDouble(Daylighting_ControlsFields::ProbabilityLightingwillbeResetWhenNeededinManualSteppedControl);
  if (d){
    daylightingControl2.setProbabilityLightingwillbeResetWhenNeededinManualSteppedControl(*d);
  }

  return daylightingControl;
}
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;
}