boost::optional<IdfObject> ForwardTranslator::translateAirTerminalSingleDuctConstantVolumeFourPipeInduction( AirTerminalSingleDuctConstantVolumeFourPipeInduction & modelObject )
{
  OptionalString s;
  OptionalDouble d;
  OptionalModelObject temp;

  IdfObject _airDistributionUnit(openstudio::IddObjectType::ZoneHVAC_AirDistributionUnit);
  _airDistributionUnit.setName(modelObject.name().get() + " Air Distribution Unit");
  m_idfObjects.push_back(_airDistributionUnit);

  // Name
  IdfObject idfObject = createRegisterAndNameIdfObject(openstudio::IddObjectType::AirTerminal_SingleDuct_ConstantVolume_FourPipeInduction, modelObject);

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

  // Maximum Total Air Flow Rate
  if( (d = modelObject.maximumTotalAirFlowRate()) )
  {
    idfObject.setDouble(AirTerminal_SingleDuct_ConstantVolume_FourPipeInductionFields::MaximumTotalAirFlowRate,d.get());
  }
  else if( modelObject.isMaximumTotalAirFlowRateAutosized() )
  {
    idfObject.setString(AirTerminal_SingleDuct_ConstantVolume_FourPipeInductionFields::MaximumTotalAirFlowRate,"Autosize");
  }

  // Induction Ratio
  if( (d = modelObject.inductionRatio()) )
  {
    idfObject.setDouble(AirTerminal_SingleDuct_ConstantVolume_FourPipeInductionFields::InductionRatio,d.get());
  }

  // Supply Air Inlet Node Name
  if( auto node = modelObject.inletModelObject() ) {
    idfObject.setString(AirTerminal_SingleDuct_ConstantVolume_FourPipeInductionFields::SupplyAirInletNodeName,node->name().get());
  }

  // Induced Air Inlet Node Name
  if( auto node = modelObject.inducedAirInletNode() ) {
    idfObject.setString(AirTerminal_SingleDuct_ConstantVolume_FourPipeInductionFields::InducedAirInletNodeName,node->name().get());
  }

  // Air Outlet Node Name
  if( auto node = modelObject.outletModelObject() ) {
    idfObject.setString(AirTerminal_SingleDuct_ConstantVolume_FourPipeInductionFields::AirOutletNodeName,node->name().get());
  }

  // Hot Water Inlet Node Name
  // deprecated

  // Cold Water Inlet Node Name
  //deprecated

  // Heating Coil Object Type
  // Heating Coil Name
  boost::optional<IdfObject> _heatingCoil;
  {
    auto heatingCoil = modelObject.heatingCoil();
    if( (_heatingCoil = translateAndMapModelObject(heatingCoil)) ) {
      idfObject.setString(AirTerminal_SingleDuct_ConstantVolume_FourPipeInductionFields::HeatingCoilObjectType,_heatingCoil->iddObject().name());
      idfObject.setString(AirTerminal_SingleDuct_ConstantVolume_FourPipeInductionFields::HeatingCoilName,_heatingCoil->name().get());
    }
  }

  // Maximum Hot Water Flow Rate
  if( (d = modelObject.maximumHotWaterFlowRate()) )
  {
    idfObject.setDouble(AirTerminal_SingleDuct_ConstantVolume_FourPipeInductionFields::MaximumHotWaterFlowRate,d.get());
  }
  else if( modelObject.isMaximumHotWaterFlowRateAutosized() )
  {
    idfObject.setString(AirTerminal_SingleDuct_ConstantVolume_FourPipeInductionFields::MaximumHotWaterFlowRate,"Autosize");
  }

  // Minimum Hot Water Flow Rate
  if( (d = modelObject.minimumHotWaterFlowRate()) )
  {
    idfObject.setDouble(AirTerminal_SingleDuct_ConstantVolume_FourPipeInductionFields::MinimumHotWaterFlowRate,d.get());
  }

  // Heating Convergence Tolerance
  if( (d = modelObject.heatingConvergenceTolerance()) )
  {
    idfObject.setDouble(AirTerminal_SingleDuct_ConstantVolume_FourPipeInductionFields::HeatingConvergenceTolerance,d.get());
  }

  // Cooling Coil Object Type
  // Cooling Coil Name
  boost::optional<IdfObject> _coolingCoil;
  if( auto coolingCoil = modelObject.coolingCoil() ) {
    if( (_coolingCoil = translateAndMapModelObject(coolingCoil.get())) ) {
      idfObject.setString(AirTerminal_SingleDuct_ConstantVolume_FourPipeInductionFields::CoolingCoilObjectType,_coolingCoil->iddObject().name());
      idfObject.setString(AirTerminal_SingleDuct_ConstantVolume_FourPipeInductionFields::CoolingCoilName,_coolingCoil->name().get());
    }
  }
  
  // Maximum Cold Water Flow Rate
  if( (d = modelObject.maximumColdWaterFlowRate()) )
  {
    idfObject.setDouble(AirTerminal_SingleDuct_ConstantVolume_FourPipeInductionFields::MaximumColdWaterFlowRate,d.get());
  }
  else if( modelObject.isMaximumColdWaterFlowRateAutosized() )
  {
    idfObject.setString(AirTerminal_SingleDuct_ConstantVolume_FourPipeInductionFields::MaximumColdWaterFlowRate,"Autosize");
  }

  // Minimum Cold Water Flow Rate
  if( (d = modelObject.minimumColdWaterFlowRate()) )
  {
    idfObject.setDouble(AirTerminal_SingleDuct_ConstantVolume_FourPipeInductionFields::MinimumColdWaterFlowRate,d.get());
  }

  // Cooling Convergence Tolerance
  if( (d = modelObject.coolingConvergenceTolerance()) )
  {
    idfObject.setDouble(AirTerminal_SingleDuct_ConstantVolume_FourPipeInductionFields::CoolingConvergenceTolerance,d.get());
  }

  // Zone Mixer Name
  IdfObject _mixer(IddObjectType::AirLoopHVAC_ZoneMixer);
  _mixer.setName(modelObject.name().get() + " Mixer");
  m_idfObjects.push_back(_mixer);
  _mixer.clearExtensibleGroups();
  idfObject.setString(AirTerminal_SingleDuct_ConstantVolume_FourPipeInductionFields::ZoneMixerName,_mixer.name().get());

  std::string baseName = modelObject.name().get();

  std::string heatingCoilInlet;
  std::string heatingCoilOutlet;
  std::string coolingCoilInlet;
  std::string coolingCoilOutlet;
  std::string mixerAirSystemInlet;
  std::string mixerInducedInlet;
  std::string mixerOutlet;

  if( auto inducedAirInletNode = modelObject.inducedAirInletNode() ) {
    heatingCoilInlet = inducedAirInletNode->name().get();
  }
  heatingCoilOutlet = baseName + " Heating Coil Outlet";

  if( _coolingCoil ) {
    coolingCoilInlet = heatingCoilOutlet;
    coolingCoilOutlet = baseName + " Cooling Coil Outlet";

    mixerInducedInlet = coolingCoilOutlet;
  } else {
    mixerInducedInlet = heatingCoilOutlet;
  }

  if( auto node = modelObject.inletModelObject() ) {
    mixerAirSystemInlet = node->name().get();
  }
  if( auto node = modelObject.outletModelObject() ) {
    mixerOutlet = node->name().get();
  }

  if( _heatingCoil && (_heatingCoil->iddObject().type() == IddObjectType::Coil_Heating_Water) ) {
    _heatingCoil->setString(Coil_Heating_WaterFields::AirInletNodeName,heatingCoilInlet);
    _heatingCoil->setString(Coil_Heating_WaterFields::AirOutletNodeName,heatingCoilOutlet);
  }

  if( _coolingCoil && (_coolingCoil->iddObject().type() == IddObjectType::Coil_Cooling_Water) ) {
    _coolingCoil->setString(Coil_Cooling_WaterFields::AirInletNodeName,coolingCoilInlet);
    _coolingCoil->setString(Coil_Cooling_WaterFields::AirOutletNodeName,coolingCoilOutlet);
  }

  _mixer.setString(AirLoopHVAC_ZoneMixerFields::OutletNodeName,mixerOutlet);
  IdfExtensibleGroup eg = _mixer.pushExtensibleGroup();
  eg.setString(AirLoopHVAC_ZoneMixerExtensibleFields::InletNodeName,mixerAirSystemInlet);
  eg = _mixer.pushExtensibleGroup();
  eg.setString(AirLoopHVAC_ZoneMixerExtensibleFields::InletNodeName,mixerInducedInlet);

  if( auto node = modelObject.outletModelObject() ) {
    _airDistributionUnit.setString(ZoneHVAC_AirDistributionUnitFields::AirDistributionUnitOutletNodeName,node->name().get());
  }
  _airDistributionUnit.setString(ZoneHVAC_AirDistributionUnitFields::AirTerminalObjectType,idfObject.iddObject().name());
  _airDistributionUnit.setString(ZoneHVAC_AirDistributionUnitFields::AirTerminalName,idfObject.name().get());

  return _airDistributionUnit;
}
boost::optional<IdfObject> ForwardTranslator::translateAirTerminalSingleDuctParallelPIUReheat( AirTerminalSingleDuctParallelPIUReheat & modelObject )
{
  OptionalModelObject temp;
  OptionalString optS;
  boost::optional<std::string> s;
  boost::optional<double> value;

  IdfObject _airDistributionUnit(openstudio::IddObjectType::ZoneHVAC_AirDistributionUnit);
  _airDistributionUnit.setName(modelObject.name().get() + " Air Distribution Unit");
  m_idfObjects.push_back(_airDistributionUnit);

  IdfObject idfObject(openstudio::IddObjectType::AirTerminal_SingleDuct_ParallelPIU_Reheat);
  idfObject.setName(modelObject.name().get());
  m_idfObjects.push_back(idfObject);

  HVACComponent coil = modelObject.reheatCoil();

  boost::optional<IdfObject> _reheatCoil = translateAndMapModelObject(coil);

  HVACComponent fan = modelObject.fan();

  boost::optional<IdfObject> _fan = translateAndMapModelObject(fan);

  std::string fanOutletNodeName = modelObject.name().get() + " Fan Outlet";

  std::string mixerOutletNodeName = modelObject.name().get() + " Mixer Outlet";

  boost::optional<std::string> inletNodeName;
  boost::optional<std::string> secondaryAirInletNodeName;
  boost::optional<std::string> outletNodeName;

  if( boost::optional<ModelObject> inletModelObject = modelObject.inletModelObject() )
  {
    if( boost::optional<Node> inletNode = inletModelObject->optionalCast<Node>() )
    {
      inletNodeName = inletNode->name().get();
    }
  }

  if( boost::optional<ModelObject> outletModelObject = modelObject.outletModelObject() )
  {
    if( boost::optional<Node> outletNode = outletModelObject->optionalCast<Node>() )
    {
      outletNodeName = outletNode->name().get();
    }
  }

  if( boost::optional<Node> secondaryInletNode = modelObject.secondaryAirInletNode() )
  {
    if( secondaryInletNode )
    {
      secondaryAirInletNodeName = secondaryInletNode->name().get();
    }
  }

  if( outletNodeName )
  {
    idfObject.setString(AirTerminal_SingleDuct_ParallelPIU_ReheatFields::OutletNodeName,outletNodeName.get());
  }

  if( inletNodeName )
  {
    idfObject.setString(AirTerminal_SingleDuct_ParallelPIU_ReheatFields::SupplyAirInletNodeName,inletNodeName.get());
  }

  if( secondaryAirInletNodeName )
  {
    idfObject.setString(AirTerminal_SingleDuct_ParallelPIU_ReheatFields::SecondaryAirInletNodeName,secondaryAirInletNodeName.get());
  }

  // Populate fields for AirDistributionUnit
  if( outletNodeName )
  {
    _airDistributionUnit.setString(ZoneHVAC_AirDistributionUnitFields::AirDistributionUnitOutletNodeName,outletNodeName.get());
  }
  _airDistributionUnit.setString(ZoneHVAC_AirDistributionUnitFields::AirTerminalObjectType,idfObject.iddObject().name());
  _airDistributionUnit.setString(ZoneHVAC_AirDistributionUnitFields::AirTerminalName,idfObject.name().get());

  // MixerName
  IdfObject _mixer(IddObjectType::AirLoopHVAC_ZoneMixer);
  _mixer.setName(modelObject.name().get() + " Mixer");
  m_idfObjects.push_back(_mixer);
  _mixer.clearExtensibleGroups();

  _mixer.setString(AirLoopHVAC_ZoneMixerFields::OutletNodeName,mixerOutletNodeName);

  IdfExtensibleGroup eg = _mixer.pushExtensibleGroup();
  eg.setString(AirLoopHVAC_ZoneMixerExtensibleFields::InletNodeName,fanOutletNodeName);

  if( inletNodeName )
  {
    eg = _mixer.pushExtensibleGroup();
    eg.setString(AirLoopHVAC_ZoneMixerExtensibleFields::InletNodeName,inletNodeName.get());
  }

  idfObject.setString(AirTerminal_SingleDuct_ParallelPIU_ReheatFields::ZoneMixerName,_mixer.name().get());

  // FanName
  if( _fan || _fan->name() )
  {
    idfObject.setString(AirTerminal_SingleDuct_ParallelPIU_ReheatFields::FanName,_fan->name().get());

    if( secondaryAirInletNodeName )
    {
      _fan->setString(Fan_ConstantVolumeFields::AirInletNodeName,secondaryAirInletNodeName.get());
    }

    _fan->setString(Fan_ConstantVolumeFields::AirOutletNodeName,fanOutletNodeName);
  }

  // ReheatCoilName
  if( _reheatCoil && _reheatCoil->name() )
  {
    // Reheat Coil Name
    idfObject.setString(AirTerminal_SingleDuct_ParallelPIU_ReheatFields::ReheatCoilName,_reheatCoil->name().get());

    // Reheat Coil Type
    idfObject.setString(AirTerminal_SingleDuct_ParallelPIU_ReheatFields::ReheatCoilObjectType,_reheatCoil->iddObject().name());

    idfObject.setString(AirTerminal_SingleDuct_ParallelPIU_ReheatFields::ReheatCoilAirInletNodeName,mixerOutletNodeName);

    if( outletNodeName && inletNodeName )
    {
      if( _reheatCoil->iddObject().type() == IddObjectType::Coil_Heating_Fuel )
      {
        _reheatCoil->setString(Coil_Heating_FuelFields::AirInletNodeName,mixerOutletNodeName);
        _reheatCoil->setString(Coil_Heating_FuelFields::AirOutletNodeName,outletNodeName.get());
      }
      else if( _reheatCoil->iddObject().type() == IddObjectType::Coil_Heating_Electric )
      {
        _reheatCoil->setString(Coil_Heating_ElectricFields::AirInletNodeName,mixerOutletNodeName);
        _reheatCoil->setString(Coil_Heating_ElectricFields::AirOutletNodeName,outletNodeName.get());
      }
      else if( _reheatCoil->iddObject().type() == IddObjectType::Coil_Heating_Water )
      {
        _reheatCoil->setString(Coil_Heating_WaterFields::AirInletNodeName,mixerOutletNodeName);
        _reheatCoil->setString(Coil_Heating_WaterFields::AirOutletNodeName,outletNodeName.get());
      }
    }
  }

  // AvailabilityScheduleName
  Schedule availabilitySchedule = modelObject.availabilitySchedule();

  boost::optional<IdfObject> _availabilitySchedule = translateAndMapModelObject(availabilitySchedule);

  if( _availabilitySchedule && _availabilitySchedule->name() )
  {
    idfObject.setString(AirTerminal_SingleDuct_ParallelPIU_ReheatFields::AvailabilityScheduleName,_availabilitySchedule->name().get());
  }

  // MaximumPrimaryAirFlowRate
  if( modelObject.isMaximumPrimaryAirFlowRateAutosized() )
  {
    idfObject.setString(AirTerminal_SingleDuct_ParallelPIU_ReheatFields::MaximumPrimaryAirFlowRate,"Autosize");
  }
  else if( (value = modelObject.maximumPrimaryAirFlowRate()) )
  {
    idfObject.setDouble(AirTerminal_SingleDuct_ParallelPIU_ReheatFields::MaximumPrimaryAirFlowRate,value.get());
  }

  // MaximumSecondaryAirFlowRate
  if( modelObject.isMaximumSecondaryAirFlowRateAutosized() )
  {
    idfObject.setString(AirTerminal_SingleDuct_ParallelPIU_ReheatFields::MaximumSecondaryAirFlowRate,"Autosize");
  }
  else if( (value = modelObject.maximumSecondaryAirFlowRate()) )
  {
    idfObject.setDouble(AirTerminal_SingleDuct_ParallelPIU_ReheatFields::MaximumSecondaryAirFlowRate,value.get());
  }

  // MinimumPrimaryAirFlowFraction
  if( modelObject.isMinimumPrimaryAirFlowFractionAutosized() )
  {
    idfObject.setString(AirTerminal_SingleDuct_ParallelPIU_ReheatFields::MinimumPrimaryAirFlowFraction,"Autosize");
  }
  else if( (value = modelObject.minimumPrimaryAirFlowFraction()) )
  {
    idfObject.setDouble(AirTerminal_SingleDuct_ParallelPIU_ReheatFields::MinimumPrimaryAirFlowFraction,value.get());
  }

  // FanOnFlowFraction
  if( modelObject.isFanOnFlowFractionAutosized() )
  {
    idfObject.setString(AirTerminal_SingleDuct_ParallelPIU_ReheatFields::FanOnFlowFraction,"Autosize");
  }
  else if( (value = modelObject.fanOnFlowFraction()) )
  {
    idfObject.setDouble(AirTerminal_SingleDuct_ParallelPIU_ReheatFields::FanOnFlowFraction,value.get());
  }

  // MaximumHotWaterorSteamFlowRate
  if( modelObject.isMaximumHotWaterorSteamFlowRateAutosized() )
  {
    idfObject.setString(AirTerminal_SingleDuct_ParallelPIU_ReheatFields::MaximumHotWaterorSteamFlowRate,"Autosize");
  }
  else if( (value = modelObject.maximumHotWaterorSteamFlowRate()) )
  {
    idfObject.setDouble(AirTerminal_SingleDuct_ParallelPIU_ReheatFields::MaximumHotWaterorSteamFlowRate,value.get());
  }

  // MinimumHotWaterorSteamFlowRate
  if( (value = modelObject.minimumHotWaterorSteamFlowRate()) )
  {
    idfObject.setDouble(AirTerminal_SingleDuct_ParallelPIU_ReheatFields::MinimumHotWaterorSteamFlowRate,value.get());
  }

  // ConvergenceTolerance
  if( (value = modelObject.convergenceTolerance()) )
  {
    idfObject.setDouble(AirTerminal_SingleDuct_ParallelPIU_ReheatFields::ConvergenceTolerance,value.get());
  }

  return _airDistributionUnit;
}