boost::optional<IdfObject> ForwardTranslator::translateAvailabilityManagerScheduledOff(
    AvailabilityManagerScheduledOff & modelObject)
{
  IdfObject idfObject = createRegisterAndNameIdfObject(IddObjectType::AvailabilityManager_ScheduledOff, modelObject);

  // Schedule
  {
    Schedule sch = modelObject.schedule();
    idfObject.setString(AvailabilityManager_ScheduledOffFields::ScheduleName, sch.name().get());
  }
  return idfObject;
}
boost::optional<IdfObject> ForwardTranslator::translateZoneHVACBaseboardConvectiveElectric(
    ZoneHVACBaseboardConvectiveElectric & modelObject )
{
  // Makes sure the modelObject gets put in the map, and that the new idfObject gets put in 
  // the final file. Also set's the idfObject's name.
  IdfObject idfObject = createRegisterAndNameIdfObject(IddObjectType::ZoneHVAC_Baseboard_Convective_Electric,modelObject);

  boost::optional<std::string> s;
  boost::optional<double> value;
  boost::optional<ModelObject> temp;
  
  // AvailabilityScheduleName
  Schedule availabilitySchedule = modelObject.availabilitySchedule();
  translateAndMapModelObject(availabilitySchedule);
  idfObject.setString(ZoneHVAC_Baseboard_Convective_ElectricFields::AvailabilityScheduleName,
                      availabilitySchedule.name().get() );

  // NominalCapacity

  if( modelObject.isNominalCapacityAutosized() )
  {
    idfObject.setString(ZoneHVAC_Baseboard_Convective_ElectricFields::NominalCapacity,"Autosize");
  }
  else if( value = modelObject.nominalCapacity() )
  {
    idfObject.setDouble(ZoneHVAC_Baseboard_Convective_ElectricFields::NominalCapacity,value.get());
  }

  // Efficiency

  if( value = modelObject.efficiency() )
  {
    idfObject.setDouble(ZoneHVAC_Baseboard_Convective_ElectricFields::Efficiency,value.get());
  }

  return idfObject;
}
boost::optional<IdfObject> ForwardTranslator::translateZoneHVACBaseboardConvectiveWater(
    ZoneHVACBaseboardConvectiveWater & modelObject )
{
  // Makes sure the modelObject gets put in the map, and that the new idfObject gets put in 
  // the final file. Also set's the idfObject's name.
  IdfObject idfObject = createRegisterAndNameIdfObject(IddObjectType::ZoneHVAC_Baseboard_Convective_Water,modelObject);

  boost::optional<std::string> s;
  boost::optional<double> value;
  boost::optional<ModelObject> temp;
  //get the heating coil as a straight component, cast it to optional HT coil, if cast is successful, 
  //get the object of class CoilHeatingWaterBaseboard
  StraightComponent coilStraight = modelObject.heatingCoil();
  boost::optional<CoilHeatingWaterBaseboard>  coilOptionalHeatBBConvWater = coilStraight.optionalCast<CoilHeatingWaterBaseboard>();
  
  // AvailabilityScheduleName
  Schedule availabilitySchedule = modelObject.availabilitySchedule();
  translateAndMapModelObject(availabilitySchedule);
  idfObject.setString(ZoneHVAC_Baseboard_Convective_WaterFields::AvailabilityScheduleName,
                      availabilitySchedule.name().get() );

  if (coilOptionalHeatBBConvWater){
    CoilHeatingWaterBaseboard coilHeatBBConvWater = *coilOptionalHeatBBConvWater;

    // Inlet Node Name 
    temp = coilHeatBBConvWater.inletModelObject();
    if(temp)
    {
      s = temp->name();
      if(s)
      {
        idfObject.setString(openstudio::ZoneHVAC_Baseboard_Convective_WaterFields::InletNodeName,*s);
      }
    }

    // Outlet Node Name 
    temp = coilHeatBBConvWater.outletModelObject();
    if(temp)
    {
      s = temp->name();
      if(s)
      {
        idfObject.setString(openstudio::ZoneHVAC_Baseboard_Convective_WaterFields::OutletNodeName,*s);
      }
    }

    // UFactorTimesAreaValue
    if(coilHeatBBConvWater.isUFactorTimesAreaValueAutosized())
    {
      idfObject.setString(ZoneHVAC_Baseboard_Convective_WaterFields::UFactorTimesAreaValue,"Autosize");
    }
    else if( value = coilHeatBBConvWater.uFactorTimesAreaValue() )
    {
      idfObject.setDouble(ZoneHVAC_Baseboard_Convective_WaterFields::UFactorTimesAreaValue,value.get());
    }

   // MaximumWaterFlowRate

    if(coilHeatBBConvWater.isMaximumWaterFlowRateAutosized() )
    {
      idfObject.setString(ZoneHVAC_Baseboard_Convective_WaterFields::MaximumWaterFlowRate,"Autosize");
    }
    else if( value = coilHeatBBConvWater.maximumWaterFlowRate() )
    {
      idfObject.setDouble(ZoneHVAC_Baseboard_Convective_WaterFields::MaximumWaterFlowRate,value.get());
    }

   // Convergence Tolerance

    if( coilHeatBBConvWater.isConvergenceToleranceDefaulted())
    {
      idfObject.setDouble(ZoneHVAC_Baseboard_Convective_WaterFields::ConvergenceTolerance,0.001);
    }
    else if( value = coilHeatBBConvWater.convergenceTolerance())
    {
      idfObject.setDouble(ZoneHVAC_Baseboard_Convective_WaterFields::ConvergenceTolerance,value.get());
    }
  }
 return idfObject;
}
boost::optional<IdfObject> ForwardTranslator::translateFanVariableVolume( FanVariableVolume& modelObject )
{
  OptionalString s;
  OptionalDouble d;
  OptionalModelObject temp;

  // Create a new IddObjectType::Fan_VariableVolume
  IdfObject idfObject(IddObjectType::Fan_VariableVolume);

  m_idfObjects.push_back(idfObject);

  // Field: Name ////////////////////////////////////////////////////////////
  s = modelObject.name();
  if(s)
  {
    idfObject.setName(*s);
  }

  // AvailabilityScheduleName

  if( boost::optional<model::AirLoopHVAC> airLoopHVAC = modelObject.airLoopHVAC() )
  {
    Schedule sched = airLoopHVAC->availabilitySchedule();
    boost::optional<IdfObject> schedIdf = translateAndMapModelObject(sched);
    if( schedIdf )
    {
      idfObject.setString(Fan_VariableVolumeFields::AvailabilityScheduleName,schedIdf->name().get());
    }
  }
  else
  {
    Schedule sched = modelObject.availabilitySchedule();
    translateAndMapModelObject(sched);
    idfObject.setString(Fan_VariableVolumeFields::AvailabilityScheduleName,sched.name().get());
  }

  // Fan Efficiency /////////////////////////////////////////////////////////
  idfObject.setDouble(openstudio::Fan_VariableVolumeFields::FanTotalEfficiency,modelObject.fanEfficiency());

  // Pressure Rise //////////////////////////////////////////////////////////
  idfObject.setDouble(openstudio::Fan_VariableVolumeFields::PressureRise,modelObject.pressureRise());

  // Maximum Flow Rate //////////////////////////////////////////////////////
  if( modelObject.isMaximumFlowRateAutosized() )
  {
    idfObject.setString(openstudio::Fan_VariableVolumeFields::MaximumFlowRate,"AutoSize");
  }
  else if( (d = modelObject.maximumFlowRate()) )
  {
    idfObject.setDouble(openstudio::Fan_VariableVolumeFields::MaximumFlowRate,d.get());
  }

  // FanPowerMinimumFlowRateInputMethod
  if( (s = modelObject.fanPowerMinimumFlowRateInputMethod()) )
  {
    idfObject.setString(Fan_VariableVolumeFields::FanPowerMinimumFlowRateInputMethod,s.get());
  }

  // FanPowerMinimumFlowFraction
  if( (d = modelObject.fanPowerMinimumFlowFraction()) )
  {
    idfObject.setDouble(Fan_VariableVolumeFields::FanPowerMinimumFlowFraction,d.get());
  }

  // FanPowerMinimumAirFlowRate

  if( (d = modelObject.fanPowerMinimumAirFlowRate()) )
  {
    idfObject.setDouble(Fan_VariableVolumeFields::FanPowerMinimumAirFlowRate,d.get());
  }

  // Motor Efficiency ///////////////////////////////////////////////////////
  idfObject.setDouble(openstudio::Fan_VariableVolumeFields::MotorEfficiency,modelObject.motorEfficiency());

  // FanPowerCoefficient1

  if( (d = modelObject.fanPowerCoefficient1()) )
  {
    idfObject.setDouble(Fan_VariableVolumeFields::FanPowerCoefficient1,d.get());
  }

  // FanPowerCoefficient2

  if( (d = modelObject.fanPowerCoefficient2()) )
  {
    idfObject.setDouble(Fan_VariableVolumeFields::FanPowerCoefficient2,d.get());
  }

  // FanPowerCoefficient3

  if( (d = modelObject.fanPowerCoefficient3()) )
  {
    idfObject.setDouble(Fan_VariableVolumeFields::FanPowerCoefficient3,d.get());
  }

  // FanPowerCoefficient4

  if( (d = modelObject.fanPowerCoefficient4()) )
  {
    idfObject.setDouble(Fan_VariableVolumeFields::FanPowerCoefficient4,d.get());
  }

  // FanPowerCoefficient5

  if( (d = modelObject.fanPowerCoefficient5()) )
  {
    idfObject.setDouble(Fan_VariableVolumeFields::FanPowerCoefficient5,d.get());
  }

  // Motor In Airstream Fraction ////////////////////////////////////////////
  idfObject.setDouble(openstudio::Fan_VariableVolumeFields::MotorInAirstreamFraction,modelObject.motorInAirstreamFraction());

  // Air Inlet Node Name ////////////////////////////////////////////////////
  temp = modelObject.inletModelObject();
  if(temp)
  {
    s = temp->name();
    if(s)
    {
      idfObject.setString(openstudio::Fan_VariableVolumeFields::AirInletNodeName,*s);
    }
  }

  // Air Outlet Node Name ///////////////////////////////////////////////////
  temp = modelObject.outletModelObject();
  if(temp)
  {
    s = temp->name();
    if(s)
    {
      idfObject.setString(openstudio::Fan_VariableVolumeFields::AirOutletNodeName,*s);
    }
  }

  return idfObject;
}
boost::optional<IdfObject> ForwardTranslator::translateZoneHVACFourPipeFanCoil(
    ZoneHVACFourPipeFanCoil & modelObject )
{
  boost::optional<std::string> s;
  boost::optional<double> value;

  IdfObject idfObject(IddObjectType::ZoneHVAC_FourPipeFanCoil);

  // Get model object name and define node names for future use
  // Model Name
  std::string baseName = modelObject.name().get();
  // Node Names
  std::string mixedAirNodeName = baseName + " Mixed Air Node";
  std::string fanOutletNodeName = baseName + " Fan Outlet Node";
  std::string coolingCoilOutletNodeName = baseName + " Cooling Coil Outlet Node";
  std::string reliefAirNodeName = baseName + " Relief Air Node";
  std::string oaNodeName = baseName + " OA Node";

  boost::optional<AirLoopHVAC> t_airLoopHVAC = modelObject.airLoopHVAC();

  // AirInletNodeName
  boost::optional<std::string> airInletNodeName;
  if( boost::optional<Node> node = modelObject.inletNode() )
  {
    if( (s = node->name()) )
    {
      airInletNodeName = s;
      idfObject.setString(ZoneHVAC_FourPipeFanCoilFields::AirInletNodeName,s.get() );
    }
  }
  // AirOutletNodeName
  boost::optional<std::string> airOutletNodeName;
  if( boost::optional<Node> node = modelObject.outletNode() )
  {
    if( (s = node->name()) )
    {
      airOutletNodeName = s;
      idfObject.setString(ZoneHVAC_FourPipeFanCoilFields::AirOutletNodeName,s.get() );
    }
  }

  // hook up required objects
  try {
    // AvailabilityScheduleName
    Schedule availabilitySchedule = modelObject.availabilitySchedule();
    translateAndMapModelObject(availabilitySchedule);
    idfObject.setString(ZoneHVAC_FourPipeFanCoilFields::AvailabilityScheduleName,
                        availabilitySchedule.name().get() );

    // Supply Air Fan
    HVACComponent supplyAirFan = modelObject.supplyAirFan();
    if( boost::optional<IdfObject> _supplyAirFan = translateAndMapModelObject(supplyAirFan) )
    {
      // SupplyAirFanObjectType
      idfObject.setString(ZoneHVAC_FourPipeFanCoilFields::SupplyAirFanObjectType,_supplyAirFan->iddObject().name() );

      // SupplyAirFanName
      idfObject.setString(ZoneHVAC_FourPipeFanCoilFields::SupplyAirFanName,_supplyAirFan->name().get() );
      // Supply Air Fan Inlet and Outlet Nodes
      if( airOutletNodeName && airInletNodeName )
      {
        // If there is an AirLoopHVAC then we provide no mixer
        std::string fanInletNodeName;
        if( t_airLoopHVAC ) {
          fanInletNodeName = airInletNodeName.get();
        } else {
          fanInletNodeName = mixedAirNodeName;
        }

        if( _supplyAirFan->iddObject().type() == IddObjectType::Fan_ConstantVolume )
        {
          _supplyAirFan->setString(Fan_ConstantVolumeFields::AirInletNodeName,fanInletNodeName );
          _supplyAirFan->setString(Fan_ConstantVolumeFields::AirOutletNodeName,fanOutletNodeName );
        }
        else if( _supplyAirFan->iddObject().type() == IddObjectType::Fan_OnOff )
        {
          
          _supplyAirFan->setString(Fan_OnOffFields::AirInletNodeName,fanInletNodeName );
          _supplyAirFan->setString(Fan_OnOffFields::AirOutletNodeName,fanOutletNodeName );
        }
        else if( _supplyAirFan->iddObject().type() == IddObjectType::Fan_VariableVolume )
        {
          _supplyAirFan->setString(Fan_VariableVolumeFields::AirInletNodeName,fanInletNodeName );
          _supplyAirFan->setString(Fan_VariableVolumeFields::AirOutletNodeName,fanOutletNodeName );
        }
      }
    }

    // Cooling Coil
    HVACComponent coolingCoil = modelObject.coolingCoil();
    if( boost::optional<IdfObject> _coolingCoil = translateAndMapModelObject(coolingCoil) )
    {
      // CoolingCoilObjectType
      idfObject.setString(ZoneHVAC_FourPipeFanCoilFields::CoolingCoilObjectType,_coolingCoil->iddObject().name() );
      // CoolingCoilName
      idfObject.setString(ZoneHVAC_FourPipeFanCoilFields::CoolingCoilName,_coolingCoil->name().get() );
      // Cooling Coil Inlet and Outlet Nodes
      if( _coolingCoil->iddObject().type() == IddObjectType::Coil_Cooling_Water )
      {
        _coolingCoil->setString(Coil_Cooling_WaterFields::AirInletNodeName,fanOutletNodeName );
        _coolingCoil->setString(Coil_Cooling_WaterFields::AirOutletNodeName,coolingCoilOutletNodeName );
      }
    }

    // Heating Coil
    HVACComponent heatingCoil = modelObject.heatingCoil();
    if( boost::optional<IdfObject> _heatingCoil = translateAndMapModelObject(heatingCoil) )
    {
      // HeatingCoilObjectType
      idfObject.setString(ZoneHVAC_FourPipeFanCoilFields::HeatingCoilObjectType,_heatingCoil->iddObject().name() );
      // HeatingCoilName
      idfObject.setString(ZoneHVAC_FourPipeFanCoilFields::HeatingCoilName,_heatingCoil->name().get() );
      // Heating Coil Inlet and Outlet Nodes
      if( _heatingCoil->iddObject().type() == IddObjectType::Coil_Heating_Water )
      {
        _heatingCoil->setString(Coil_Heating_WaterFields::AirInletNodeName,coolingCoilOutletNodeName );
        _heatingCoil->setString(Coil_Heating_WaterFields::AirOutletNodeName,airOutletNodeName.get() );
      }
    }
  }
  catch (std::exception& e) {
    LOG(Error,"Could not translate " << modelObject.briefDescription() << ", because "
        << e.what() << ".");
    return boost::none;
  }

  m_idfObjects.push_back(idfObject);

  // Name
  idfObject.setName(baseName);

  // CapacityControlMethod
  idfObject.setString(ZoneHVAC_FourPipeFanCoilFields::CapacityControlMethod,
                      modelObject.capacityControlMethod());

  // MaximumSupplyAirFlowRate
  if( modelObject.isMaximumSupplyAirFlowRateAutosized() )
  {
    idfObject.setString(ZoneHVAC_FourPipeFanCoilFields::MaximumSupplyAirFlowRate,"Autosize");
  }
  else if( (value = modelObject.maximumSupplyAirFlowRate()) )
  {
    idfObject.setDouble(ZoneHVAC_FourPipeFanCoilFields::MaximumSupplyAirFlowRate,value.get());
  }

  // LowSpeedSupplyAirFlowRatio
  if(! modelObject.isLowSpeedSupplyAirFlowRatioDefaulted() )
  {
    idfObject.setDouble(ZoneHVAC_FourPipeFanCoilFields::LowSpeedSupplyAirFlowRatio,modelObject.lowSpeedSupplyAirFlowRatio() );
  }

  // MediumSpeedSupplyAirFlowRatio
  if(! (modelObject.isMediumSpeedSupplyAirFlowRatioDefaulted()) )
  {
    idfObject.setDouble(ZoneHVAC_FourPipeFanCoilFields::MediumSpeedSupplyAirFlowRatio,modelObject.mediumSpeedSupplyAirFlowRatio() );
  }

  // MaximumOutdoorAirFlowRate
  if( modelObject.isMaximumOutdoorAirFlowRateAutosized() )
  {
    idfObject.setString(ZoneHVAC_FourPipeFanCoilFields::MaximumOutdoorAirFlowRate,"Autosize");
  }
  else if( (value = modelObject.maximumOutdoorAirFlowRate()) )
  {
    idfObject.setDouble(ZoneHVAC_FourPipeFanCoilFields::MaximumOutdoorAirFlowRate,value.get());
  }

  // OutdoorAirScheduleName
  if( boost::optional<Schedule> schedule = modelObject.outdoorAirSchedule() )
  {
    if( boost::optional<IdfObject> _schedule = translateAndMapModelObject(schedule.get()) )
    {
      idfObject.setString(ZoneHVAC_FourPipeFanCoilFields::OutdoorAirScheduleName,_schedule->name().get());
    }
  }

  if( ! t_airLoopHVAC ) {
    // OutdoorAirMixerObjectType
    idfObject.setString(ZoneHVAC_FourPipeFanCoilFields::OutdoorAirMixerObjectType,
                        modelObject.outdoorAirMixerObjectType());

    // OutdoorAirMixerName
    std::string oaMixerName = modelObject.name().get() + " OA Mixer";
    idfObject.setString(ZoneHVAC_FourPipeFanCoilFields::OutdoorAirMixerName,oaMixerName);

    // Create Outdoor Air Mixer
    IdfObject _outdoorAirMixer(IddObjectType::OutdoorAir_Mixer);
    _outdoorAirMixer.setName(oaMixerName);
    m_idfObjects.push_back(_outdoorAirMixer);

    _outdoorAirMixer.setString(OutdoorAir_MixerFields::MixedAirNodeName,mixedAirNodeName);
    _outdoorAirMixer.setString(OutdoorAir_MixerFields::OutdoorAirStreamNodeName,oaNodeName);
    _outdoorAirMixer.setString(OutdoorAir_MixerFields::ReliefAirStreamNodeName,reliefAirNodeName);
    if(airInletNodeName)
    {
      _outdoorAirMixer.setString(OutdoorAir_MixerFields::ReturnAirStreamNodeName,airInletNodeName.get());
    }

    // Create Outdoor Air Node List
    IdfObject _oaNodeList(openstudio::IddObjectType::OutdoorAir_NodeList);
    _oaNodeList.setString(0,oaNodeName);
    m_idfObjects.push_back(_oaNodeList);
  }

  // MaximumColdWaterFlowRate
  if( modelObject.isMaximumColdWaterFlowRateAutosized() )
  {
    idfObject.setString(ZoneHVAC_FourPipeFanCoilFields::MaximumColdWaterFlowRate,"Autosize");
  }
  else if( (value = modelObject.maximumColdWaterFlowRate()) )
  {
    idfObject.setDouble(ZoneHVAC_FourPipeFanCoilFields::MaximumColdWaterFlowRate,value.get());
  }

  // MinimumColdWaterFlowRate
  if(! modelObject.isMinimumColdWaterFlowRateDefaulted() )
  {
    idfObject.setDouble(ZoneHVAC_FourPipeFanCoilFields::MinimumColdWaterFlowRate,modelObject.minimumColdWaterFlowRate() );
  }

  // CoolingConvergenceTolerance
  if(! modelObject.isCoolingConvergenceToleranceDefaulted() )
  {
    idfObject.setDouble(ZoneHVAC_FourPipeFanCoilFields::CoolingConvergenceTolerance,modelObject.coolingConvergenceTolerance() );
  }

  // MaximumHotWaterFlowRate
  if( modelObject.isMaximumHotWaterFlowRateAutosized() )
  {
    idfObject.setString(ZoneHVAC_FourPipeFanCoilFields::MaximumHotWaterFlowRate,"Autosize");
  }
  else if( (value = modelObject.maximumHotWaterFlowRate()) )
  {
    idfObject.setDouble(ZoneHVAC_FourPipeFanCoilFields::MaximumHotWaterFlowRate,value.get());
  }

  // MinimumHotWaterFlowRate
  if(! modelObject.isMinimumHotWaterFlowRateDefaulted() )
  {
    idfObject.setDouble(ZoneHVAC_FourPipeFanCoilFields::MinimumHotWaterFlowRate,modelObject.minimumHotWaterFlowRate() );
  }

  // HeatingConvergenceTolerance
  if(! modelObject.isHeatingConvergenceToleranceDefaulted() )
  {
    idfObject.setDouble(ZoneHVAC_FourPipeFanCoilFields::HeatingConvergenceTolerance,modelObject.heatingConvergenceTolerance() );
  }

  return idfObject;
}
boost::optional<IdfObject> ForwardTranslator::translateCoilCoolingDXTwoSpeedWithoutUnitary( model::CoilCoolingDXTwoSpeed & modelObject )
{
  //setup two boost optionals to use to store get method returns
  boost::optional<std::string> s;
  boost::optional<double> d;

  //create the IdfObject that will be the coil
  IdfObject idfObject(IddObjectType::Coil_Cooling_DX_TwoSpeed);

  //Name
  m_idfObjects.push_back(idfObject);
  s = modelObject.name();
  if( s )
  {
    idfObject.setName(*s);
  }

  //  A2 , \field Availability Schedule Name
  Schedule sched = modelObject.getAvailabilitySchedule();
  translateAndMapModelObject(sched);
  idfObject.setString(Coil_Cooling_DX_TwoSpeedFields::AvailabilityScheduleName,
                      sched.name().get() );

  //  N1 , \field Rated High Speed Total Cooling Capacity
  d = modelObject.getRatedHighSpeedTotalCoolingCapacity();
  if( d )
  {
    idfObject.setDouble(Coil_Cooling_DX_TwoSpeedFields::RatedHighSpeedTotalCoolingCapacity,*d);
  }
  else
  {
    idfObject.setString(Coil_Cooling_DX_TwoSpeedFields::RatedHighSpeedTotalCoolingCapacity,"Autosize");
  }

  //  N2 , \field Rated High Speed Sensible Heat Ratio
  d = modelObject.getRatedHighSpeedSensibleHeatRatio();
  if( d )
  {
    idfObject.setDouble(Coil_Cooling_DX_TwoSpeedFields::RatedHighSpeedSensibleHeatRatio,*d);
  }
  else
  {
    idfObject.setString(Coil_Cooling_DX_TwoSpeedFields::RatedHighSpeedSensibleHeatRatio,"Autosize");
  }

  //  N3 , \field Rated High Speed COP
  d = modelObject.getRatedHighSpeedCOP();
  if( d )
  {
    idfObject.setDouble(Coil_Cooling_DX_TwoSpeedFields::RatedHighSpeedCOP,*d);
  }

  //  N4 , \field Rated High Speed Air Flow Rate
  d = modelObject.getRatedHighSpeedAirFlowRate();
  if( d )
  {
    idfObject.setDouble(Coil_Cooling_DX_TwoSpeedFields::RatedHighSpeedAirFlowRate,*d);
  }
  else
  {
    idfObject.setString(Coil_Cooling_DX_TwoSpeedFields::RatedHighSpeedAirFlowRate,"Autosize");
  }

  //A3 , \field Air Inlet Node Name
  OptionalModelObject omo = modelObject.inletModelObject();
  if( omo )
  {
    translateAndMapModelObject(*omo);
    s = omo->name();
    if(s)
    {
      idfObject.setString(Coil_Cooling_DX_TwoSpeedFields::AirInletNodeName,*s );
    }
  }

  //A4 , \field Air Outlet Node Name
  omo= modelObject.outletModelObject();
  if( omo )
  {
    translateAndMapModelObject(*omo);
    s = omo->name();
    if(s)
    {
      idfObject.setString(Coil_Cooling_DX_TwoSpeedFields::AirOutletNodeName,*s);
    }
  }

  //  A5 , \field Total Cooling Capacity Function of Temperature Curve Name
  Curve cb =  modelObject.getTotalCoolingCapacityFunctionOfTemperatureCurve();
  translateAndMapModelObject(cb);
  idfObject.setString(Coil_Cooling_DX_TwoSpeedFields::TotalCoolingCapacityFunctionofTemperatureCurveName,
                     cb.name().get());

  //  A6 , \field Total Cooling Capacity Function of Flow Fraction Curve Name
  cb =  modelObject.getTotalCoolingCapacityFunctionOfFlowFractionCurve();
  translateAndMapModelObject(cb);
  idfObject.setString(Coil_Cooling_DX_TwoSpeedFields::TotalCoolingCapacityFunctionofFlowFractionCurveName,
                     cb.name().get());

  //  A7 , \field Energy Input Ratio Function of Temperature Curve Name
  cb =modelObject.getEnergyInputRatioFunctionOfTemperatureCurve();
  translateAndMapModelObject(cb);
  idfObject.setString(Coil_Cooling_DX_TwoSpeedFields::EnergyInputRatioFunctionofTemperatureCurveName,
                      cb.name().get());

  //  A8 , \field Energy Input Ratio Function of Flow Fraction Curve Name
  Curve cq = modelObject.getEnergyInputRatioFunctionOfFlowFractionCurve();
  translateAndMapModelObject(cq);
  idfObject.setString(Coil_Cooling_DX_TwoSpeedFields::EnergyInputRatioFunctionofFlowFractionCurveName,
                      cq.name().get());

  //  A9 , \field Part Load Fraction Correlation Curve Name
  cq = modelObject.getPartLoadFractionCorrelationCurve();
  translateAndMapModelObject(cq);
  idfObject.setString(Coil_Cooling_DX_TwoSpeedFields::PartLoadFractionCorrelationCurveName,
                      cq.name().get());

  //  N5 , \field Rated Low Speed Total Cooling Capacity
  d = modelObject.getRatedLowSpeedTotalCoolingCapacity();
  if( d )
  {
    idfObject.setDouble(Coil_Cooling_DX_TwoSpeedFields::RatedLowSpeedTotalCoolingCapacity,*d);
  }
  else
  {
    idfObject.setString(Coil_Cooling_DX_TwoSpeedFields::RatedLowSpeedTotalCoolingCapacity,"Autosize");
  }

  //  N6 , \field Rated Low Speed Sensible Heat Ratio
  d = modelObject.getRatedLowSpeedSensibleHeatRatio();
  if( d )
  {
    idfObject.setDouble(Coil_Cooling_DX_TwoSpeedFields::RatedLowSpeedSensibleHeatRatio,*d);
  }
  else
  {
    idfObject.setString(Coil_Cooling_DX_TwoSpeedFields::RatedLowSpeedSensibleHeatRatio,"Autosize");
  }

  //  N7 , \field Rated Low Speed COP
  d = modelObject.getRatedLowSpeedCOP();
  if( d )
  {
    idfObject.setDouble(Coil_Cooling_DX_TwoSpeedFields::RatedLowSpeedCOP,*d);
  }

  //  N8 , \field Rated Low Speed Air Flow Rate
  d = modelObject.getRatedLowSpeedAirFlowRate();
  if( d )
  {
    idfObject.setDouble(Coil_Cooling_DX_TwoSpeedFields::RatedLowSpeedAirFlowRate,*d);
  }
  else
  {
    idfObject.setString(Coil_Cooling_DX_TwoSpeedFields::RatedLowSpeedAirFlowRate,"Autosize");
  }

  //  A10, \field Low Speed Total Cooling Capacity Function of Temperature Curve Name
  cq = modelObject.getLowSpeedTotalCoolingCapacityFunctionOfTemperatureCurve();
  translateAndMapModelObject(cq);
  idfObject.setString(Coil_Cooling_DX_TwoSpeedFields::LowSpeedTotalCoolingCapacityFunctionofTemperatureCurveName,
                      cq.name().get());

  //  A11, \field Low Speed Energy Input Ratio Function of Temperature Curve Name
  cq = modelObject.getLowSpeedEnergyInputRatioFunctionOfTemperatureCurve();
  translateAndMapModelObject(cq);
  idfObject.setString(Coil_Cooling_DX_TwoSpeedFields::LowSpeedEnergyInputRatioFunctionofTemperatureCurveName,
                      cq.name().get());

  //  A12, \field Condenser Air Inlet Node Name
  s=modelObject.getCondenserAirInletNodeName();
  if(s)
  {
    idfObject.setString(Coil_Cooling_DX_TwoSpeedFields::CondenserAirInletNodeName,*s);
  }

  //  A13, \field Condenser Type
  idfObject.setString(Coil_Cooling_DX_TwoSpeedFields::CondenserType,modelObject.getCondenserType());

  //   N9, \field High Speed Evaporative Condenser Effectiveness
  d=modelObject.getHighSpeedEvaporativeCondenserEffectiveness();
  if(d)
  {
    idfObject.setDouble(Coil_Cooling_DX_TwoSpeedFields::HighSpeedEvaporativeCondenserEffectiveness,*d);
  }

  //  N10, \field High Speed Evaporative Condenser Air Flow Rate
  d=modelObject.getHighSpeedEvaporativeCondenserAirFlowRate();
  if(d)
  {
    idfObject.setDouble(Coil_Cooling_DX_TwoSpeedFields::HighSpeedEvaporativeCondenserAirFlowRate,*d);
  }

  //  N11, \field High Speed Evaporative Condenser Pump Rated Power Consumption
  d=modelObject.getHighSpeedEvaporativeCondenserPumpRatedPowerConsumption();
  if(d)
  {
    idfObject.setDouble(Coil_Cooling_DX_TwoSpeedFields::HighSpeedEvaporativeCondenserPumpRatedPowerConsumption,*d);
  }

  //  N12, \field Low Speed Evaporative Condenser Effectiveness
  d=modelObject.getLowSpeedEvaporativeCondenserEffectiveness();
  if(d)
  {
    idfObject.setDouble(Coil_Cooling_DX_TwoSpeedFields::LowSpeedEvaporativeCondenserEffectiveness,*d);
  }

  //  N13, \field Low Speed Evaporative Condenser Air Flow Rate
  d=modelObject.getLowSpeedEvaporativeCondenserAirFlowRate();
  if(d)
  {
    idfObject.setDouble(Coil_Cooling_DX_TwoSpeedFields::LowSpeedEvaporativeCondenserAirFlowRate,*d);
  }

  //  N14, \field Low Speed Evaporative Condenser Pump Rated Power Consumption
  d=modelObject.getLowSpeedEvaporativeCondenserPumpRatedPowerConsumption();
  if(d)
  {
    idfObject.setDouble(Coil_Cooling_DX_TwoSpeedFields::LowSpeedEvaporativeCondenserPumpRatedPowerConsumption,*d);
  }

  //TODO
  //  A14, \field Supply Water Storage Tank Name
  //getSupplyWaterStorageTankName

  //TODO
  //  A15, \field Condensate Collection Water Storage Tank Name
  //getCondensateCollectionWaterStorageTankName

  //  N15, \field Basin Heater Capacity
  d=modelObject.getBasinHeaterCapacity();
  if(d)
  {
    idfObject.setDouble(Coil_Cooling_DX_TwoSpeedFields::BasinHeaterCapacity,*d);
  }

  //  N16, \field Basin Heater Setpoint Temperature
  d=modelObject.getBasinHeaterSetpointTemperature();
  if(d)
  {
    idfObject.setDouble(Coil_Cooling_DX_TwoSpeedFields::BasinHeaterSetpointTemperature,*d);
  }

  //  A16; \field Basin Heater Operating Schedule Name
  OptionalSchedule os = modelObject.getBasinHeaterOperatingSchedule();
  if( os )
  {
    translateAndMapModelObject(*os);
    idfObject.setString(Coil_Cooling_DX_TwoSpeedFields::BasinHeaterOperatingScheduleName,
                        os->name().get() );
  }

  return idfObject;
}
boost::optional<IdfObject> ForwardTranslator::translateCoilCoolingDXTwoSpeed( CoilCoolingDXTwoSpeed& modelObject )
{
  IdfObject coilSystemCoolingDXIdf(IddObjectType::CoilSystem_Cooling_DX);
    
  m_idfObjects.push_back(coilSystemCoolingDXIdf);

  boost::optional<IdfObject> oIdfObject = translateCoilCoolingDXTwoSpeedWithoutUnitary(modelObject);

  if( ! oIdfObject ) { return boost::none; }

  IdfObject idfObject = oIdfObject.get();

  OptionalString s;

  s = modelObject.name();
  if( s )
  {
    coilSystemCoolingDXIdf.setString(CoilSystem_Cooling_DXFields::CoolingCoilObjectType,idfObject.iddObject().name());

    coilSystemCoolingDXIdf.setString(CoilSystem_Cooling_DXFields::CoolingCoilName,*s);

    coilSystemCoolingDXIdf.setName(*s + " CoilSystem");
  }

  Schedule sched = modelObject.getAvailabilitySchedule();
  translateAndMapModelObject(sched);

  coilSystemCoolingDXIdf.setString(CoilSystem_Cooling_DXFields::AvailabilityScheduleName,sched.name().get());

  OptionalModelObject omo = modelObject.inletModelObject();
  if( omo )
  {
    translateAndMapModelObject(*omo);
    s = omo->name();
    if(s)
    {
      coilSystemCoolingDXIdf.setString(CoilSystem_Cooling_DXFields::DXCoolingCoilSystemInletNodeName,*s);
    }
  }

  omo= modelObject.outletModelObject();
  if( omo )
  {
    translateAndMapModelObject(*omo);
    s = omo->name();
    if(s)
    {
      coilSystemCoolingDXIdf.setString(CoilSystem_Cooling_DXFields::DXCoolingCoilSystemOutletNodeName,*s);

      coilSystemCoolingDXIdf.setString(CoilSystem_Cooling_DXFields::DXCoolingCoilSystemSensorNodeName,*s);
    }
  }

  return coilSystemCoolingDXIdf;
}
boost::optional<IdfObject> ForwardTranslator::translateZoneHVACUnitHeater(
    ZoneHVACUnitHeater & modelObject )
{
  // Make sure the modelObject gets ut into the map, and the new idfObject gets put into the final file.
  // Also sets the idfObjects name

  IdfObject idfObject = createRegisterAndNameIdfObject(IddObjectType::ZoneHVAC_UnitHeater,modelObject);
  
  
  boost::optional<std::string> s;
  boost::optional<double> value;
  boost::optional<Node> node;
  
  // Get model object name and define node names for future use
  
  // Model Name
  std::string baseName = modelObject.name().get();
  
  // Node Names
  std::string fanOutletNodeName = baseName + " Fan Outlet Node";
  
  // Field: Availability Schedule Name

  Schedule availabilitySchedule = modelObject.availabilitySchedule();
  translateAndMapModelObject(availabilitySchedule);
  
  s = availabilitySchedule.name();
  
  if(s)
  {
    idfObject.setString(ZoneHVAC_UnitHeaterFields::AvailabilityScheduleName,*s);
  }

  // Field: Air Inlet Node Name
  
  node = modelObject.inletNode();
  
  if(node)
  {
    s = node->name();

    if(s)
    {
      idfObject.setString(ZoneHVAC_UnitHeaterFields::AirInletNodeName,*s);
    }
  }

  // Field: Air Outlet Node Name
  
  node = modelObject.outletNode();

  if(node)
  {
    s = node->name();

    if(s)
    {
      idfObject.setString(ZoneHVAC_UnitHeaterFields::AirOutletNodeName,*s);
    }
  }

  //Field: Supply Air Fan Object Type

  HVACComponent supplyAirFan = modelObject.supplyAirFan();

  if(boost::optional<IdfObject> _supplyAirFan = translateAndMapModelObject(supplyAirFan)) 
  {
    idfObject.setString(ZoneHVAC_UnitHeaterFields::SupplyAirFanObjectType,_supplyAirFan->iddObject().name());
  }

  // Field: Supply Air Fan Name
  
  s = modelObject.supplyAirFan().name();
   

  if(s)

  {
    idfObject.setString(ZoneHVAC_UnitHeaterFields::SupplyAirFanName,*s);
  }

  // Supply Air Fan Inlet and Outlet Nodes
  
  node = modelObject.inletNode();
  
  if(boost::optional<IdfObject> _supplyAirFan = translateAndMapModelObject(supplyAirFan))
  {
  
    if(node)
    {
      s = node->name();

      if( _supplyAirFan->iddObject().type() == IddObjectType::Fan_ConstantVolume)
      {
        _supplyAirFan->setString(Fan_ConstantVolumeFields::AirInletNodeName,*s);
        _supplyAirFan->setString(Fan_ConstantVolumeFields::AirOutletNodeName,fanOutletNodeName);
      }
      else if( _supplyAirFan->iddObject().type() == IddObjectType::Fan_VariableVolume )
      {
        _supplyAirFan->setString(Fan_VariableVolumeFields::AirInletNodeName,*s);
        _supplyAirFan->setString(Fan_VariableVolumeFields::AirOutletNodeName,fanOutletNodeName);
      }
    }
  }

  // Field Maximum Supply Air Flow Rate

  if( modelObject.isMaximumSupplyAirFlowRateAutosized())
  {
    idfObject.setString(ZoneHVAC_UnitHeaterFields::MaximumSupplyAirFlowRate,"Autosize");
  }

  else if ( (value = modelObject.maximumSupplyAirFlowRate()) )
  {
    idfObject.setDouble(ZoneHVAC_UnitHeaterFields::MaximumSupplyAirFlowRate,*value);
  }

  // Field: Fan Control Type

   idfObject.setString(ZoneHVAC_UnitHeaterFields::FanControlType,modelObject.fanControlType());

   // Field: Heating Coil Object Type

  HVACComponent heatingCoil = modelObject.heatingCoil();

  if( boost::optional<IdfObject> _heatingCoil = translateAndMapModelObject(heatingCoil))
  {
    idfObject.setString(ZoneHVAC_UnitHeaterFields::HeatingCoilObjectType,_heatingCoil->iddObject().name());
  }

   // Field: Heating Coil Name

  s = modelObject.heatingCoil().name();
   
  if(s)
  {
    idfObject.setString(ZoneHVAC_UnitHeaterFields::HeatingCoilName,*s);
  }

  // Heating coil inlet and outlet node names

  node = modelObject.outletNode();
  
  if(boost::optional<IdfObject> _heatingCoil = translateAndMapModelObject(heatingCoil))
  {
    if(node)
    {
      s = node->name();

      if( _heatingCoil->iddObject().type() == IddObjectType::Coil_Heating_Electric)
      {
        _heatingCoil->setString(Coil_Heating_ElectricFields::AirInletNodeName,fanOutletNodeName);
        _heatingCoil->setString(Coil_Heating_ElectricFields::AirOutletNodeName,*s);
      }
      else if( _heatingCoil->iddObject().type() == IddObjectType::Coil_Heating_Gas )
      {
        _heatingCoil->setString(Coil_Heating_GasFields::AirInletNodeName,fanOutletNodeName);
        _heatingCoil->setString(Coil_Heating_GasFields::AirOutletNodeName,*s);
      }
      else if( _heatingCoil->iddObject().type() == IddObjectType::Coil_Heating_Water )
      {
        _heatingCoil->setString(Coil_Heating_WaterFields::AirInletNodeName,fanOutletNodeName);
        _heatingCoil->setString(Coil_Heating_WaterFields::AirOutletNodeName,*s);
      }
    }
  }

  // Field Maximum Hot Water [or Steam] Flow Rate

  if( modelObject.isMaximumHotWaterFlowRateAutosized())
  
  {
    idfObject.setString(ZoneHVAC_UnitHeaterFields::MaximumHotWaterorSteamFlowRate,"Autosize");
  }

  else if ( (value = modelObject.maximumHotWaterFlowRate()) )
  {
     idfObject.setDouble(ZoneHVAC_UnitHeaterFields::MaximumHotWaterorSteamFlowRate,*value);
  }

  // Field: Minimum Hot Water [or Steam] Flow Rate

  idfObject.setDouble(ZoneHVAC_UnitHeaterFields::MinimumHotWaterorSteamFlowRate,modelObject.minimumHotWaterFlowRate());

 // Field: Heating Convergence Tolerance

  idfObject.setDouble(ZoneHVAC_UnitHeaterFields::HeatingConvergenceTolerance,modelObject.heatingConvergenceTolerance());

  // Field: Availability Manager List Name: Ignored?

  return idfObject;
}
boost::optional<IdfObject> ForwardTranslator::translateCoilHeatingGas( CoilHeatingGas & modelObject )
{
  OptionalString s;
  OptionalModelObject temp;

  // Create a new IddObjectType::Fan_OnOff
  IdfObject idfObject(IddObjectType::Coil_Heating_Gas);

  ///////////////////////////////////////////////////////////////////////////
  // Field: Name ////////////////////////////////////////////////////////////
  s = modelObject.name();
  if( s )
  {
    idfObject.setName(*s);
  }
  ///////////////////////////////////////////////////////////////////////////

  // hook up required objects
  try {
    Schedule sched = modelObject.availableSchedule();
    translateAndMapModelObject(sched);
    idfObject.setString(Coil_Heating_GasFields::AvailabilityScheduleName,
                        sched.name().get() );
  }
  catch (std::exception& e) {
    LOG(Error,"Could not translate " << modelObject.briefDescription() << ", because " 
        << e.what() << ".");
    return boost::none;
  }

  ///////////////////////////////////////////////////////////////////////////
  // Field: Gas Burner Efficiency ///////////////////////////////////////////
  idfObject.setDouble(openstudio::Coil_Heating_GasFields::GasBurnerEfficiency,modelObject.gasBurnerEfficiency());
  ///////////////////////////////////////////////////////////////////////////

  ///////////////////////////////////////////////////////////////////////////
  // Field: Nominal Capacity ////////////////////////////////////////////////
  OptionalDouble d=modelObject.nominalCapacity();
  if(d)
  {
    idfObject.setDouble(openstudio::Coil_Heating_GasFields::NominalCapacity,*d);
  }
  else
  {
    idfObject.setString(openstudio::Coil_Heating_GasFields::NominalCapacity,"AutoSize");
  }
  ///////////////////////////////////////////////////////////////////////////
  idfObject.setDouble(openstudio::Coil_Heating_GasFields::ParasiticElectricLoad,modelObject.parasiticElectricLoad());
  idfObject.setDouble(openstudio::Coil_Heating_GasFields::ParasiticGasLoad,modelObject.parasiticGasLoad());


  ///////////////////////////////////////////////////////////////////////////
  // Field: Air Inlet Node Name /////////////////////////////////////////////
  temp = modelObject.inletModelObject();
  if(temp)
  {
    s=temp->name();
    if( s )
    {
      idfObject.setString(openstudio::Coil_Heating_GasFields::AirInletNodeName,*s);
    }
  }
  ///////////////////////////////////////////////////////////////////////////

  ///////////////////////////////////////////////////////////////////////////
  // Field: Air Outlet Node Name ////////////////////////////////////////////
  temp = modelObject.outletModelObject();
  if(temp)
  {
    s=temp->name();
    if( s)
    {
      idfObject.setString(openstudio::Coil_Heating_GasFields::AirOutletNodeName,*s);
      idfObject.setString(openstudio::Coil_Heating_GasFields::TemperatureSetpointNodeName,*s);
    }
  }
  ///////////////////////////////////////////////////////////////////////////

  m_idfObjects.push_back(idfObject);

  // Part Load Fraction Correlation Curve 
  if( boost::optional<model::Curve> curve = modelObject.partLoadFractionCorrelationCurve() )
  {
    if( boost::optional<IdfObject> _curve = translateAndMapModelObject(curve.get()) )
    {
      idfObject.setString(Coil_Heating_GasFields::PartLoadFractionCorrelationCurveName,_curve->name().get()); 
    }
  }

  return boost::optional<IdfObject>(idfObject);
}
boost::optional<IdfObject> ForwardTranslator::translateCoilCoolingDXSingleSpeedWithoutUnitary( model::CoilCoolingDXSingleSpeed & modelObject )
{
  OptionalString s;
  IdfObject idfObject(IddObjectType::Coil_Cooling_DX_SingleSpeed);

  s = modelObject.name();
  if( s )
  {
    idfObject.setName(*s);
  }

  // hook up required objects
  try {
    Schedule sched = modelObject.getAvailabilitySchedule();
    translateAndMapModelObject(sched);
    idfObject.setString(Coil_Cooling_DX_SingleSpeedFields::AvailabilityScheduleName,
                        sched.name().get() );

    Curve cb =  modelObject.getTotalCoolingCapacityFunctionOfTemperatureCurve();
    translateAndMapModelObject(cb);
    idfObject.setString(Coil_Cooling_DX_SingleSpeedFields::TotalCoolingCapacityFunctionofTemperatureCurveName,
                       cb.name().get());

    Curve cq = modelObject.getTotalCoolingCapacityFunctionOfFlowFractionCurve();
    translateAndMapModelObject(cq);
    idfObject.setString(Coil_Cooling_DX_SingleSpeedFields::TotalCoolingCapacityFunctionofFlowFractionCurveName,
                        cq.name().get());

    cb =modelObject.getEnergyInputRatioFunctionOfTemperatureCurve();
    translateAndMapModelObject(cb);
    idfObject.setString(Coil_Cooling_DX_SingleSpeedFields::EnergyInputRatioFunctionofTemperatureCurveName,
                        cb.name().get());

    cq=modelObject.getEnergyInputRatioFunctionOfFlowFractionCurve();
    translateAndMapModelObject(cq);
    idfObject.setString(Coil_Cooling_DX_SingleSpeedFields::EnergyInputRatioFunctionofFlowFractionCurveName,
                        cq.name().get());

    cq=modelObject.getPartLoadFractionCorrelationCurve();
    translateAndMapModelObject(cq);
    idfObject.setString(Coil_Cooling_DX_SingleSpeedFields::PartLoadFractionCorrelationCurveName,
                        cq.name().get());
  }
  catch (std::exception& e) {
    LOG(Error,"Could not translate " << modelObject.briefDescription() << ", because " 
        << e.what() << ".");
    return boost::none;
  }

  OptionalDouble d = modelObject.ratedTotalCoolingCapacity();
  if( d )
  {
    idfObject.setDouble(Coil_Cooling_DX_SingleSpeedFields::GrossRatedTotalCoolingCapacity,*d);
  }
  else
  {
    idfObject.setString(Coil_Cooling_DX_SingleSpeedFields::GrossRatedTotalCoolingCapacity,"Autosize");
  }

  d = modelObject.ratedSensibleHeatRatio();
  if( d )
  {
    idfObject.setDouble(Coil_Cooling_DX_SingleSpeedFields::GrossRatedSensibleHeatRatio,*d);
  }
  else
  {
    idfObject.setString(Coil_Cooling_DX_SingleSpeedFields::GrossRatedSensibleHeatRatio,"Autosize");
  }

  d = modelObject.getRatedCOP();
  if( d )
  {
    idfObject.setDouble(Coil_Cooling_DX_SingleSpeedFields::GrossRatedCoolingCOP,*d);
  }

  d = modelObject.ratedAirFlowRate();
  if( d )
  {
    idfObject.setDouble(Coil_Cooling_DX_SingleSpeedFields::RatedAirFlowRate,*d);
  }
  else
  {
    idfObject.setString(Coil_Cooling_DX_SingleSpeedFields::RatedAirFlowRate,"Autosize");
  }

  d = modelObject.getRatedEvaporatorFanPowerPerVolumeFlowRate();
  if( d )
  {
    idfObject.setDouble(Coil_Cooling_DX_SingleSpeedFields::RatedEvaporatorFanPowerPerVolumeFlowRate,*d);
  }

  OptionalModelObject omo = modelObject.inletModelObject();
  if( omo )
  {
    translateAndMapModelObject(*omo);
    s = omo->name();
    if(s)
    {
      idfObject.setString(Coil_Cooling_DX_SingleSpeedFields::AirInletNodeName,*s );
    }
  }

  omo= modelObject.outletModelObject();
  if( omo )
  {
    translateAndMapModelObject(*omo);
    s = omo->name();
    if(s)
    {
      idfObject.setString(Coil_Cooling_DX_SingleSpeedFields::AirOutletNodeName,*s);
    }
  }

  d=modelObject.getNominalTimeForCondensateRemovalToBegin();
  if(d)
  {
    idfObject.setDouble(Coil_Cooling_DX_SingleSpeedFields::NominalTimeforCondensateRemovaltoBegin,*d);
  }

  d=modelObject.getRatioOfInitialMoistureEvaporationRateAndSteadyStateLatentCapacity();
  if(d)
  {
    idfObject.setDouble(Coil_Cooling_DX_SingleSpeedFields::RatioofInitialMoistureEvaporationRateandSteadyStateLatentCapacity,*d);
  }

  d=modelObject.getMaximumCyclingRate();
  if(d)
  {
    idfObject.setDouble(Coil_Cooling_DX_SingleSpeedFields::MaximumCyclingRate,*d);
  }

  d=modelObject.getLatentCapacityTimeConstant();
  if(d)
  {
    idfObject.setDouble(Coil_Cooling_DX_SingleSpeedFields::LatentCapacityTimeConstant,*d);
  }

  s=modelObject.getCondenserAirInletNodeName();
  if(s)
  {
    idfObject.setString(Coil_Cooling_DX_SingleSpeedFields::CondenserAirInletNodeName,*s);
  }

  idfObject.setString(Coil_Cooling_DX_SingleSpeedFields::CondenserType,modelObject.getCondenserType());

  d=modelObject.getEvaporativeCondenserEffectiveness();
  if(d)
  {
    idfObject.setDouble(Coil_Cooling_DX_SingleSpeedFields::EvaporativeCondenserEffectiveness,*d);
  }

  d=modelObject.getEvaporativeCondenserAirFlowRate();
  if(d)
  {
    idfObject.setDouble(Coil_Cooling_DX_SingleSpeedFields::EvaporativeCondenserAirFlowRate,*d);
  }

  d=modelObject.getEvaporativeCondenserPumpRatedPowerConsumption();
  if(d)
  {
    idfObject.setDouble(Coil_Cooling_DX_SingleSpeedFields::EvaporativeCondenserPumpRatedPowerConsumption,*d);
  }

  d=modelObject.getCrankcaseHeaterCapacity();
  if(d)
  {
    idfObject.setDouble(Coil_Cooling_DX_SingleSpeedFields::CrankcaseHeaterCapacity,*d);
  }

  d=modelObject.getMaximumOutdoorDryBulbTemperatureForCrankcaseHeaterOperation();
  if(d)
  {
    idfObject.setDouble(Coil_Cooling_DX_SingleSpeedFields::MaximumOutdoorDryBulbTemperatureforCrankcaseHeaterOperation,*d);
  }

  //TODO
  //getSupplyWaterStorageTankName
  //getCondensateCollectionWaterStorageTankName

  d=modelObject.getBasinHeaterCapacity();
  if(d)
  {
    idfObject.setDouble(Coil_Cooling_DX_SingleSpeedFields::BasinHeaterCapacity,*d);
  }

  d=modelObject.getBasinHeaterSetpointTemperature();
  if(d)
  {
    idfObject.setDouble(Coil_Cooling_DX_SingleSpeedFields::BasinHeaterSetpointTemperature,*d);
  }

  OptionalSchedule os = modelObject.getBasinHeaterOperatingSchedule();
  if( os )
  {
    translateAndMapModelObject(*os);
    idfObject.setString(Coil_Cooling_DX_SingleSpeedFields::BasinHeaterOperatingScheduleName,
                        os->name().get() );
  }

  m_idfObjects.push_back(idfObject);
  return idfObject;
}
boost::optional<IdfObject> ForwardTranslator::translateHeatExchangerAirToAirSensibleAndLatent( HeatExchangerAirToAirSensibleAndLatent & modelObject )
{
  OptionalString s;
  OptionalDouble d;
  OptionalModelObject temp;

  IdfObject idfObject(IddObjectType::HeatExchanger_AirToAir_SensibleAndLatent);

  m_idfObjects.push_back(idfObject);

  // Name
  s = modelObject.name();
  if(s)
  {
    idfObject.setName(*s);
  }

  // AvailabilityScheduleName
  Schedule sched = modelObject.availabilitySchedule();
  translateAndMapModelObject(sched);
  idfObject.setString(HeatExchanger_AirToAir_SensibleAndLatentFields::AvailabilityScheduleName,sched.name().get());

  // NominalSupplyAirFlowRate
  if( modelObject.isNominalSupplyAirFlowRateAutosized() )
  {
    idfObject.setString(HeatExchanger_AirToAir_SensibleAndLatentFields::NominalSupplyAirFlowRate,"Autosize");
  }
  else
  {
    d = modelObject.nominalSupplyAirFlowRate();
    if( d )
    {
      idfObject.setDouble(HeatExchanger_AirToAir_SensibleAndLatentFields::NominalSupplyAirFlowRate,d.get());
    }
  }

  // SensibleEffectivenessat100_HeatingAirFlow
  d = modelObject.sensibleEffectivenessat100HeatingAirFlow();
  if( d )
  {
    idfObject.setDouble(HeatExchanger_AirToAir_SensibleAndLatentFields::SensibleEffectivenessat100_HeatingAirFlow,d.get());
  }

  // LatentEffectivenessat100_HeatingAirFlow
  d = modelObject.latentEffectivenessat100HeatingAirFlow();
  if( d )
  {
    idfObject.setDouble(HeatExchanger_AirToAir_SensibleAndLatentFields::LatentEffectivenessat100_HeatingAirFlow,d.get());
  }

  // SensibleEffectivenessat75_HeatingAirFlow
  d = modelObject.sensibleEffectivenessat75HeatingAirFlow();
  if( d )
  {
    idfObject.setDouble(HeatExchanger_AirToAir_SensibleAndLatentFields::SensibleEffectivenessat75_HeatingAirFlow,d.get());
  }

  // LatentEffectivenessat75_HeatingAirFlow
  d = modelObject.latentEffectivenessat75HeatingAirFlow();
  if( d )
  {
    idfObject.setDouble(HeatExchanger_AirToAir_SensibleAndLatentFields::LatentEffectivenessat75_HeatingAirFlow,d.get());
  }

  // SensibleEffectivenessat100_CoolingAirFlow
  d = modelObject.sensibleEffectivenessat100CoolingAirFlow();
  if( d )
  {
    idfObject.setDouble(HeatExchanger_AirToAir_SensibleAndLatentFields::SensibleEffectivenessat100_CoolingAirFlow,d.get());
  }

  // LatentEffectivenessat100_CoolingAirFlow
  d = modelObject.latentEffectivenessat100CoolingAirFlow();
  if( d )
  {
    idfObject.setDouble(HeatExchanger_AirToAir_SensibleAndLatentFields::LatentEffectivenessat100_CoolingAirFlow,d.get());
  }

  // SensibleEffectivenessat75_CoolingAirFlow
  d = modelObject.sensibleEffectivenessat75CoolingAirFlow();
  if( d )
  {
    idfObject.setDouble(HeatExchanger_AirToAir_SensibleAndLatentFields::SensibleEffectivenessat75_CoolingAirFlow,d.get());
  }

  // LatentEffectivenessat75_CoolingAirFlow
  d = modelObject.latentEffectivenessat75CoolingAirFlow();
  if( d )
  {
    idfObject.setDouble(HeatExchanger_AirToAir_SensibleAndLatentFields::LatentEffectivenessat75_CoolingAirFlow,d.get());
  }

  // SupplyAirInletNodeName
  temp = modelObject.primaryAirInletModelObject();
  if(temp)
  {
    s = temp->name();
    if(s)
    {
      idfObject.setString(HeatExchanger_AirToAir_SensibleAndLatentFields::SupplyAirInletNodeName,*s);
    }
  }

  // SupplyAirOutletNodeName
  temp = modelObject.primaryAirOutletModelObject();
  if(temp)
  {
    s = temp->name();
    if(s)
    {
      idfObject.setString(HeatExchanger_AirToAir_SensibleAndLatentFields::SupplyAirOutletNodeName,*s);
    }
  }

  // ExhaustAirInletNodeName
  temp = modelObject.secondaryAirInletModelObject();
  if(temp)
  {
    s = temp->name();
    if(s)
    {
      idfObject.setString(HeatExchanger_AirToAir_SensibleAndLatentFields::ExhaustAirInletNodeName,*s);
    }
  }

  // ExhaustAirOutletNodeName
  temp = modelObject.secondaryAirOutletModelObject();
  if(temp)
  {
    s = temp->name();
    if(s)
    {
      idfObject.setString(HeatExchanger_AirToAir_SensibleAndLatentFields::ExhaustAirOutletNodeName,*s);
    }
  }

  // NominalElectricPower
  d = modelObject.nominalElectricPower();
  if( d )
  {
    idfObject.setDouble(HeatExchanger_AirToAir_SensibleAndLatentFields::NominalElectricPower,*d);
  }

  // SupplyAirOutletTemperatureControl
  if( modelObject.supplyAirOutletTemperatureControl() )
  {
    idfObject.setString(HeatExchanger_AirToAir_SensibleAndLatentFields::SupplyAirOutletTemperatureControl,"Yes");
  }
  else
  {
    idfObject.setString(HeatExchanger_AirToAir_SensibleAndLatentFields::SupplyAirOutletTemperatureControl,"No");
  }

  // HeatExchangerType
  s = modelObject.heatExchangerType();
  if( s )
  {
    idfObject.setString(HeatExchanger_AirToAir_SensibleAndLatentFields::HeatExchangerType,*s);
  }

  // FrostControlType 
  s = modelObject.frostControlType();  
  if( s )
  {
    idfObject.setString(HeatExchanger_AirToAir_SensibleAndLatentFields::FrostControlType,*s);
  }

  // ThresholdTemperature
  d = modelObject.thresholdTemperature();
  if( d )
  {
    idfObject.setDouble(HeatExchanger_AirToAir_SensibleAndLatentFields::ThresholdTemperature,*d);
  }

  // InitialDefrostTimeFraction
  d = modelObject.initialDefrostTimeFraction();
  if( d )
  {
    idfObject.setDouble(HeatExchanger_AirToAir_SensibleAndLatentFields::InitialDefrostTimeFraction,*d);
  }

  // RateofDefrostTimeFractionIncrease
  d = modelObject.rateofDefrostTimeFractionIncrease();
  if( d )
  {
    idfObject.setDouble(HeatExchanger_AirToAir_SensibleAndLatentFields::RateofDefrostTimeFractionIncrease,*d);
  }

  // EconomizerLockout
  if( modelObject.economizerLockout() )
  {
    idfObject.setString(HeatExchanger_AirToAir_SensibleAndLatentFields::EconomizerLockout,"Yes");
  }
  else
  {
    idfObject.setString(HeatExchanger_AirToAir_SensibleAndLatentFields::EconomizerLockout,"No");
  }

  return idfObject;
}
boost::optional<IdfObject> ForwardTranslator::translateEvaporativeCoolerDirectResearchSpecial( EvaporativeCoolerDirectResearchSpecial & modelObject )
{
  OptionalString s;
  OptionalDouble d;
  OptionalModelObject temp;
  double value;

  IdfObject idfObject(IddObjectType::EvaporativeCooler_Direct_ResearchSpecial);

  m_idfObjects.push_back(idfObject);

  // Name
  s = modelObject.name();
  if(s)
  {
    idfObject.setName(*s);
  }

  // AvailabilityScheduleName
  Schedule sched = modelObject.availableSchedule();
  translateAndMapModelObject(sched);
  idfObject.setString(EvaporativeCooler_Direct_ResearchSpecialFields::AvailabilityScheduleName,sched.name().get());

  // CoolerEffectiveness
  value = modelObject.coolerEffectiveness();
  idfObject.setDouble(EvaporativeCooler_Direct_ResearchSpecialFields::CoolerEffectiveness,value);

  // RecirculatingWaterPumpPowerConsumption
  value = modelObject.recirculatingWaterPumpPowerConsumption();
  idfObject.setDouble(EvaporativeCooler_Direct_ResearchSpecialFields::RecirculatingWaterPumpPowerConsumption,value);

  // AirInletNodeName
  temp = modelObject.inletModelObject();
  if(temp)
  {
    s = temp->name();
    if(s)
    {
      idfObject.setString(EvaporativeCooler_Direct_ResearchSpecialFields::AirInletNodeName,*s);
    }
  }

  // AirOutletNodeName
  temp = modelObject.outletModelObject();
  if(temp)
  {
    s = temp->name();
    if(s)
    {
      idfObject.setString(EvaporativeCooler_Direct_ResearchSpecialFields::AirOutletNodeName,*s);
    }
  }

  // SensorNodeName
  temp = modelObject.sensorNode();
  if(temp)
  {
    s = temp->name();
    if(s)
    {
      idfObject.setString(EvaporativeCooler_Direct_ResearchSpecialFields::SensorNodeName,*s);
    }
  }

  // DriftLossFraction
  value = modelObject.driftLossFraction();
  idfObject.setDouble(EvaporativeCooler_Direct_ResearchSpecialFields::DriftLossFraction,value);

  // BlowdownConcentrationRatio
  value = modelObject.blowdownConcentrationRatio();
  if( value < 2 )
  {
    idfObject.setDouble(EvaporativeCooler_Direct_ResearchSpecialFields::BlowdownConcentrationRatio,2.0);
  }
  else
  {
    idfObject.setDouble(EvaporativeCooler_Direct_ResearchSpecialFields::BlowdownConcentrationRatio,value);
  }

  return boost::optional<IdfObject>(idfObject);
}
boost::optional<IdfObject> ForwardTranslator::translateFanOnOff( FanOnOff & modelObject )
{
  //setup boost optionals to use to store get method returns
  boost::optional<std::string> s;
  boost::optional<double> value;
  boost::optional<Node> node;
  OptionalModelObject mo;
  
  // Make sure the modelObject gets ut into the map, and the new idfObject gets put into the final file.
  // Also sets the idfObjects name

  IdfObject idfObject = createRegisterAndNameIdfObject(IddObjectType::Fan_OnOff,modelObject);
  
  // Model Name
  std::string baseName = modelObject.name().get();

  //  A3 ,Field Availability Schedule Name
  
  Schedule availabilitySchedule = modelObject.availabilitySchedule();
  translateAndMapModelObject(availabilitySchedule);
  
  s = availabilitySchedule.name();
  
  if(s)
  {
				idfObject.setString(Fan_OnOffFields::AvailabilityScheduleName,*s);
  }
  
  //  N1 ,Field Fan Efficiency
  
  value = modelObject.fanEfficiency();
  
  if( value )
  {
    idfObject.setDouble(Fan_OnOffFields::FanEfficiency,*value);
  }
  
  //  N2 Pressure Rise
  
  value = modelObject.pressureRise();
  
  if( value )
  {
    idfObject.setDouble(Fan_OnOffFields::PressureRise,*value);
  }
  
  // N3,  Field Maximum Flow Rate
  
  value = modelObject.maximumFlowRate();
  
  if( value )
  {
    idfObject.setDouble(Fan_OnOffFields::MaximumFlowRate,*value);
  }
  
  else
  {
    idfObject.setString(Fan_OnOffFields::MaximumFlowRate,"Autosize");
  }
  
  // N4,  Field Motor Efficiency
  
  value = modelObject.motorEfficiency();
  
  if( value )
  {
    idfObject.setDouble(Fan_OnOffFields::MotorEfficiency,*value);
  }
  
  //   N5, Field Motor In Airstream Fraction

  value = modelObject.motorInAirstreamFraction();
  
  if( value )
  {
    idfObject.setDouble(Fan_OnOffFields::MotorInAirstreamFraction,*value);
  }
  
  // A4 Air Inlet Node Name
  
  mo = modelObject.inletModelObject();
  if(mo)
  {
    s = mo->name();
    if(s)
    {
      idfObject.setString(openstudio::Fan_OnOffFields::AirInletNodeName,*s);
    }
  }

  // A5 , Field Air Outlet Node Name
  
  mo = modelObject.outletModelObject();
  if(mo)
  {
    s = mo->name();
    if(s)
    {
      idfObject.setString(openstudio::Fan_OnOffFields::AirOutletNodeName,*s);
    }
  }

  // A6 , Field Fan Power Ratio Function of Speed Ratio Curve Name
  
  Curve cb1 =  modelObject.fanPowerRatioFunctionofSpeedRatioCurve();
  
  translateAndMapModelObject(cb1);
  
  idfObject.setString(Fan_OnOffFields::FanPowerRatioFunctionofSpeedRatioCurveName,cb1.name().get());
  
  // A7 , Field Fan Efficiency Ratio Function of Speed Ratio Curve Name
  
  Curve cb2 =  modelObject.fanEfficiencyRatioFunctionofSpeedRatioCurve();
  
  translateAndMapModelObject(cb2);
  
  idfObject.setString(Fan_OnOffFields::FanEfficiencyRatioFunctionofSpeedRatioCurveName,cb2.name().get());
  
  
  // A8 , Field End-Use Subcategory

   idfObject.setString(Fan_OnOffFields::EndUseSubcategory,modelObject.endUseSubcategory());

  return idfObject;
}
boost::optional<IdfObject> ForwardTranslator::translateFanConstantVolume( FanConstantVolume& modelObject )
{
  OptionalString s;
  OptionalDouble d;
  OptionalModelObject temp;

  // Create a new IddObjectType::Fan_ConstantVolume
  IdfObject idfObject(IddObjectType::Fan_ConstantVolume);

  ///////////////////////////////////////////////////////////////////////////
  // Field: Name ////////////////////////////////////////////////////////////
  s = modelObject.name();
  if(s)
  {
    idfObject.setName(*s);
  }
  ///////////////////////////////////////////////////////////////////////////


  // hook up required objects
  try {
    if( boost::optional<model::AirLoopHVAC> airLoopHVAC = modelObject.airLoopHVAC() )
    {
      Schedule sched = airLoopHVAC->availabilitySchedule();
      boost::optional<IdfObject> schedIdf = translateAndMapModelObject(sched);
      if( schedIdf )
      {
        idfObject.setString(Fan_ConstantVolumeFields::AvailabilityScheduleName,schedIdf->name().get());
      }
    }
    else
    {
      Schedule sched = modelObject.availabilitySchedule();
      translateAndMapModelObject(sched);
      idfObject.setString(Fan_ConstantVolumeFields::AvailabilityScheduleName,sched.name().get());
    }
  }
  catch (std::exception& e) {
    LOG(Error,"Could not translate " << modelObject.briefDescription() << ", because " 
        << e.what() << ".");
    return boost::none;
  }


  ///////////////////////////////////////////////////////////////////////////
  // Fan Efficiency /////////////////////////////////////////////////////////
  idfObject.setDouble(openstudio::Fan_ConstantVolumeFields::FanTotalEfficiency,modelObject.fanEfficiency());
  ///////////////////////////////////////////////////////////////////////////

  ///////////////////////////////////////////////////////////////////////////
  // Pressure Rise //////////////////////////////////////////////////////////
  idfObject.setDouble(openstudio::Fan_ConstantVolumeFields::PressureRise,modelObject.pressureRise());
  ///////////////////////////////////////////////////////////////////////////

  ///////////////////////////////////////////////////////////////////////////
  // Maximum Flow Rate //////////////////////////////////////////////////////
  d = modelObject.maximumFlowRate();
  if(d)
  {
    idfObject.setDouble(openstudio::Fan_ConstantVolumeFields::MaximumFlowRate,*d);
  }
  else
  {
    idfObject.setString(openstudio::Fan_ConstantVolumeFields::MaximumFlowRate,"AutoSize");
  }
  ///////////////////////////////////////////////////////////////////////////

  ///////////////////////////////////////////////////////////////////////////
  // Motor Efficiency ///////////////////////////////////////////////////////
  idfObject.setDouble(openstudio::Fan_ConstantVolumeFields::MotorEfficiency,modelObject.motorEfficiency());
  ///////////////////////////////////////////////////////////////////////////

  ///////////////////////////////////////////////////////////////////////////
  // Motor In Airstream Fraction ////////////////////////////////////////////
  idfObject.setDouble(openstudio::Fan_ConstantVolumeFields::MotorInAirstreamFraction,modelObject.motorInAirstreamFraction());
  ///////////////////////////////////////////////////////////////////////////

  ///////////////////////////////////////////////////////////////////////////
  // Air Inlet Node Name ////////////////////////////////////////////////////
  temp = modelObject.inletModelObject();
  if(temp)
  {
    s = temp->name();
    if(s)
    {
      idfObject.setString(openstudio::Fan_ConstantVolumeFields::AirInletNodeName,*s);
    }
  }
  ///////////////////////////////////////////////////////////////////////////

  ///////////////////////////////////////////////////////////////////////////
  // Air Outlet Node Name ///////////////////////////////////////////////////
  temp = modelObject.outletModelObject();
  if(temp)
  {
    s = temp->name();
    if(s)
    {
      idfObject.setString(openstudio::Fan_ConstantVolumeFields::AirOutletNodeName,*s);
    }
  }
  ///
  ////////////////////////////////////////////////////////////////////////

  m_idfObjects.push_back(idfObject);
  return boost::optional<IdfObject>(idfObject);
}
boost::optional<IdfObject> ForwardTranslator::translateZoneMixing( ZoneMixing & modelObject )
{
  // Makes sure the modelObject gets put in the map, and that the new idfObject gets put in 
  // the final file. Also set's the idfObject's name.
  IdfObject idfObject = createRegisterAndNameIdfObject(IddObjectType::ZoneMixing, modelObject);

  boost::optional<double> value;

  // ZoneName 
  ThermalZone zone = modelObject.zone();
  translateAndMapModelObject(zone);
  idfObject.setString(ZoneMixingFields::ZoneName, zone.name().get());

  // ScheduleName 
  Schedule schedule = modelObject.schedule();
  translateAndMapModelObject(schedule);
  idfObject.setString(ZoneMixingFields::ScheduleName, schedule.name().get());

  // DesignFlowRateCalculationMethod
  idfObject.setString(ZoneMixingFields::DesignFlowRateCalculationMethod, modelObject.designFlowRateCalculationMethod());

  // DesignFlowRate
  value = modelObject.designFlowRate();
  if (value){
    idfObject.setDouble(ZoneMixingFields::DesignFlowRate, *value);
  }

  // FlowRateperZoneFloorArea
  value = modelObject.flowRateperZoneFloorArea();
  if (value){
    idfObject.setDouble(ZoneMixingFields::FlowRateperZoneFloorArea, *value);
  }

  // FlowRateperPerson
  value = modelObject.flowRateperPerson();
  if (value){
    idfObject.setDouble(ZoneMixingFields::FlowRateperPerson, *value);
  }

  // AirChangesperHour
  value = modelObject.airChangesperHour();
  if (value){
    idfObject.setDouble(ZoneMixingFields::AirChangesperHour, *value);
  }

  // SourceZone
  boost::optional<ThermalZone> sourceZone = modelObject.sourceZone();
  if (sourceZone){
    // DLM: do not translate source zone now, it will be translated at the right time
    idfObject.setString(ZoneMixingFields::SourceZoneName, sourceZone->name().get());
  }

  // DeltaTemperature
  value = modelObject.deltaTemperature();
  if (value){
    idfObject.setDouble(ZoneMixingFields::DeltaTemperature, *value);
  }

  // DeltaTemperatureScheduleName
  boost::optional<Schedule> optSchedule = modelObject.deltaTemperatureSchedule();
  if (optSchedule){
    translateAndMapModelObject(*optSchedule);
    idfObject.setString(ZoneMixingFields::DeltaTemperatureScheduleName, optSchedule->name().get());
  }
  
  // MinimumZoneTemperatureScheduleName
  optSchedule = modelObject.minimumZoneTemperatureSchedule();
  if (optSchedule){
    translateAndMapModelObject(*optSchedule);
    idfObject.setString(ZoneMixingFields::MinimumZoneTemperatureScheduleName, optSchedule->name().get());
  }

  // MaximumZoneTemperatureScheduleName
  optSchedule = modelObject.maximumZoneTemperatureSchedule();
  if (optSchedule){
    translateAndMapModelObject(*optSchedule);
    idfObject.setString(ZoneMixingFields::MaximumZoneTemperatureScheduleName, optSchedule->name().get());
  }

  // MinimumSourceZoneTemperatureScheduleName
  optSchedule = modelObject.minimumSourceZoneTemperatureSchedule();
  if (optSchedule){
    translateAndMapModelObject(*optSchedule);
    idfObject.setString(ZoneMixingFields::MinimumSourceZoneTemperatureScheduleName, optSchedule->name().get());
  }

  // MaximumSourceZoneTemperatureScheduleName
  optSchedule = modelObject.maximumSourceZoneTemperatureSchedule();
  if (optSchedule){
    translateAndMapModelObject(*optSchedule);
    idfObject.setString(ZoneMixingFields::MaximumSourceZoneTemperatureScheduleName, optSchedule->name().get());
  }

  // MinimumOutdoorTemperatureScheduleName
  optSchedule = modelObject.minimumOutdoorTemperatureSchedule();
  if (optSchedule){
    translateAndMapModelObject(*optSchedule);
    idfObject.setString(ZoneMixingFields::MinimumOutdoorTemperatureScheduleName, optSchedule->name().get());
  }

  // MaximumOutdoorTemperatureScheduleName
  optSchedule = modelObject.maximumOutdoorTemperatureSchedule();
  if (optSchedule){
    translateAndMapModelObject(*optSchedule);
    idfObject.setString(ZoneMixingFields::MaximumOutdoorTemperatureScheduleName, optSchedule->name().get());
  }

  return idfObject;
}
boost::optional<IdfObject> ForwardTranslator::translatePlantEquipmentOperationSchemes( PlantLoop & plantLoop )
{
  IdfObject operationSchemes(IddObjectType::PlantEquipmentOperationSchemes);
  m_idfObjects.push_back(operationSchemes);

  operationSchemes.setName(plantLoop.name().get() + " Operation Schemes");

  // Lambda does what the name suggests, create setpoint operation schemes.
  // This is for any component that has a setpoint manager on its outlet node
  auto createSetpointOperationScheme = [&](PlantLoop & plantLoop) {
    const auto & t_setpointComponents = setpointComponents(plantLoop);
    if( ! t_setpointComponents.empty() ) {
      Schedule alwaysOn = plantLoop.model().alwaysOnDiscreteSchedule();

      IdfObject setpointOperation(IddObjectType::PlantEquipmentOperation_ComponentSetpoint);
      setpointOperation.setName(plantLoop.name().get() + " Setpoint Operation Scheme");
      m_idfObjects.push_back(setpointOperation);
      setpointOperation.clearExtensibleGroups();

      IdfExtensibleGroup eg = operationSchemes.pushExtensibleGroup();
      eg.setString(PlantEquipmentOperationSchemesExtensibleFields::ControlSchemeObjectType,setpointOperation.iddObject().name());
      eg.setString(PlantEquipmentOperationSchemesExtensibleFields::ControlSchemeName,setpointOperation.name().get());
      eg.setString(PlantEquipmentOperationSchemesExtensibleFields::ControlSchemeScheduleName,alwaysOn.name().get());

      for( auto setpointComponent : t_setpointComponents )
      {
        boost::optional<IdfObject> _idfObject = translateAndMapModelObject(setpointComponent);
        OS_ASSERT(_idfObject);

        IdfExtensibleGroup eg = setpointOperation.pushExtensibleGroup();
        eg.setString(PlantEquipmentOperation_ComponentSetpointExtensibleFields::EquipmentObjectType,_idfObject->iddObject().name());
        eg.setString(PlantEquipmentOperation_ComponentSetpointExtensibleFields::EquipmentName,_idfObject->name().get());
        if( const auto & t_inletNode = inletNode(plantLoop,setpointComponent) ) {
          eg.setString(PlantEquipmentOperation_ComponentSetpointExtensibleFields::DemandCalculationNodeName,t_inletNode->name().get());
        }
        if( const auto & t_outletNode = outletNode(plantLoop,setpointComponent) ) {
          eg.setString(PlantEquipmentOperation_ComponentSetpointExtensibleFields::SetpointNodeName,t_outletNode->name().get());
        }
        if( auto value = flowrate(setpointComponent) ) {
          eg.setDouble(PlantEquipmentOperation_ComponentSetpointExtensibleFields::ComponentFlowRate,value.get());
        } else {
          eg.setString(PlantEquipmentOperation_ComponentSetpointExtensibleFields::ComponentFlowRate,"Autosize");
        }
        auto t_componentType = componentType(setpointComponent);
        switch(t_componentType)
        {
          case ComponentType::HEATING :
            eg.setString(PlantEquipmentOperation_ComponentSetpointExtensibleFields::OperationType,"Heating");
            break;
          case ComponentType::COOLING :
            eg.setString(PlantEquipmentOperation_ComponentSetpointExtensibleFields::OperationType,"Cooling");
            break;
          default :
            eg.setString(PlantEquipmentOperation_ComponentSetpointExtensibleFields::OperationType,"Dual");
            break;
        }
      }
    }
  };

  Schedule alwaysOn = plantLoop.model().alwaysOnDiscreteSchedule();
  bool applyDefault = true;

  // If any operation schemes are defined in the model then don't apply default operation schemes

  if( auto coolingLoadScheme = plantLoop.plantEquipmentOperationCoolingLoad() ) {
    auto _scheme = translateAndMapModelObject(coolingLoadScheme.get());
    OS_ASSERT(_scheme);
    auto eg = operationSchemes.pushExtensibleGroup();
    eg.setString(PlantEquipmentOperationSchemesExtensibleFields::ControlSchemeObjectType,_scheme->iddObject().name());
    eg.setString(PlantEquipmentOperationSchemesExtensibleFields::ControlSchemeName,_scheme->name().get());
    eg.setString(PlantEquipmentOperationSchemesExtensibleFields::ControlSchemeScheduleName,alwaysOn.name().get());

    applyDefault = false;
  } 

  if( auto heatingLoadScheme = plantLoop.plantEquipmentOperationHeatingLoad() ) {
    auto _scheme = translateAndMapModelObject(heatingLoadScheme.get());
    OS_ASSERT(_scheme);
    auto eg = operationSchemes.pushExtensibleGroup();
    eg.setString(PlantEquipmentOperationSchemesExtensibleFields::ControlSchemeObjectType,_scheme->iddObject().name());
    eg.setString(PlantEquipmentOperationSchemesExtensibleFields::ControlSchemeName,_scheme->name().get());
    eg.setString(PlantEquipmentOperationSchemesExtensibleFields::ControlSchemeScheduleName,alwaysOn.name().get());

    applyDefault = false;
  }

  if( auto primaryScheme = plantLoop.primaryPlantEquipmentOperationScheme() ) {
    auto _scheme = translateAndMapModelObject(primaryScheme.get());
    OS_ASSERT(_scheme);
    auto eg = operationSchemes.pushExtensibleGroup();
    eg.setString(PlantEquipmentOperationSchemesExtensibleFields::ControlSchemeObjectType,_scheme->iddObject().name());
    eg.setString(PlantEquipmentOperationSchemesExtensibleFields::ControlSchemeName,_scheme->name().get());
    eg.setString(PlantEquipmentOperationSchemesExtensibleFields::ControlSchemeScheduleName,alwaysOn.name().get());

    createSetpointOperationScheme(plantLoop);
    applyDefault = false;
  }

  if( applyDefault ) {
    // If we get here then there must not be any operation schemes defined in the model 
    // and we should go ahead and create default schemes.
    const auto & t_heatingComponents = heatingComponents( plantLoop );
    if( ! t_heatingComponents.empty() ) {
      IdfObject heatingOperation(IddObjectType::PlantEquipmentOperation_HeatingLoad);
      heatingOperation.setName(plantLoop.name().get() + " Heating Operation Scheme");
      m_idfObjects.push_back(heatingOperation);
      heatingOperation.clearExtensibleGroups();

      IdfObject plantEquipmentList(IddObjectType::PlantEquipmentList);
      plantEquipmentList.setName(plantLoop.name().get() + " Heating Equipment List");
      plantEquipmentList.clearExtensibleGroups();
      m_idfObjects.push_back(plantEquipmentList);

      IdfExtensibleGroup eg = heatingOperation.pushExtensibleGroup();
      eg.setDouble(PlantEquipmentOperation_HeatingLoadExtensibleFields::LoadRangeLowerLimit,0.0);
      eg.setDouble(PlantEquipmentOperation_HeatingLoadExtensibleFields::LoadRangeUpperLimit,1E9);
      eg.setString(PlantEquipmentOperation_HeatingLoadExtensibleFields::RangeEquipmentListName,plantEquipmentList.name().get());

      eg = operationSchemes.pushExtensibleGroup();
      eg.setString(PlantEquipmentOperationSchemesExtensibleFields::ControlSchemeObjectType,heatingOperation.iddObject().name());
      eg.setString(PlantEquipmentOperationSchemesExtensibleFields::ControlSchemeName,heatingOperation.name().get());
      eg.setString(PlantEquipmentOperationSchemesExtensibleFields::ControlSchemeScheduleName,alwaysOn.name().get());

      for( auto heatingComponent : t_heatingComponents ) {
        if( const auto & idfObject = translateAndMapModelObject(heatingComponent) ) {
          IdfExtensibleGroup eg = plantEquipmentList.pushExtensibleGroup();
          eg.setString(PlantEquipmentListExtensibleFields::EquipmentObjectType,idfObject->iddObject().name());
          eg.setString(PlantEquipmentListExtensibleFields::EquipmentName,idfObject->name().get());
        }
      }
    }

    const auto & t_coolingComponents = coolingComponents( plantLoop );
    if( ! t_coolingComponents.empty() ) {
      IdfObject coolingOperation(IddObjectType::PlantEquipmentOperation_CoolingLoad);
      coolingOperation.setName(plantLoop.name().get() + " Cooling Operation Scheme");
      m_idfObjects.push_back(coolingOperation);
      coolingOperation.clearExtensibleGroups();

      IdfObject plantEquipmentList(IddObjectType::PlantEquipmentList);
      plantEquipmentList.setName(plantLoop.name().get() + " Cooling Equipment List");
      plantEquipmentList.clearExtensibleGroups();
      m_idfObjects.push_back(plantEquipmentList);

      IdfExtensibleGroup eg = coolingOperation.pushExtensibleGroup();
      eg.setDouble(PlantEquipmentOperation_CoolingLoadExtensibleFields::LoadRangeLowerLimit,0.0);
      eg.setDouble(PlantEquipmentOperation_CoolingLoadExtensibleFields::LoadRangeUpperLimit,1E9);
      eg.setString(PlantEquipmentOperation_CoolingLoadExtensibleFields::RangeEquipmentListName,plantEquipmentList.name().get());

      eg = operationSchemes.pushExtensibleGroup();
      eg.setString(PlantEquipmentOperationSchemesExtensibleFields::ControlSchemeObjectType,coolingOperation.iddObject().name());
      eg.setString(PlantEquipmentOperationSchemesExtensibleFields::ControlSchemeName,coolingOperation.name().get());
      eg.setString(PlantEquipmentOperationSchemesExtensibleFields::ControlSchemeScheduleName,alwaysOn.name().get());

      for( auto coolingComponent : t_coolingComponents ) {
        if( const auto & idfObject = translateAndMapModelObject(coolingComponent) ) {
          IdfExtensibleGroup eg = plantEquipmentList.pushExtensibleGroup();
          eg.setString(PlantEquipmentListExtensibleFields::EquipmentObjectType,idfObject->iddObject().name());
          eg.setString(PlantEquipmentListExtensibleFields::EquipmentName,idfObject->name().get());
        }
      }
    }

    const auto & t_uncontrolledComponents = uncontrolledComponents( plantLoop );
    if( ! t_uncontrolledComponents.empty() ) {

      IdfObject uncontrolledOperation(IddObjectType::PlantEquipmentOperation_Uncontrolled);
      uncontrolledOperation.setName(plantLoop.name().get() + " Uncontrolled Operation Scheme");
      m_idfObjects.push_back(uncontrolledOperation);
      uncontrolledOperation.clearExtensibleGroups();

      IdfObject plantEquipmentList(IddObjectType::PlantEquipmentList);
      plantEquipmentList.setName(plantLoop.name().get() + " Uncontrolled Equipment List");
      plantEquipmentList.clearExtensibleGroups();
      m_idfObjects.push_back(plantEquipmentList);

      uncontrolledOperation.setString(PlantEquipmentOperation_UncontrolledFields::EquipmentListName,plantEquipmentList.name().get());

      auto eg = operationSchemes.pushExtensibleGroup();
      eg.setString(PlantEquipmentOperationSchemesExtensibleFields::ControlSchemeObjectType,uncontrolledOperation.iddObject().name());
      eg.setString(PlantEquipmentOperationSchemesExtensibleFields::ControlSchemeName,uncontrolledOperation.name().get());
      eg.setString(PlantEquipmentOperationSchemesExtensibleFields::ControlSchemeScheduleName,alwaysOn.name().get());

      for( auto uncontrolledComponent : t_uncontrolledComponents ) {
        if( const auto & idfObject = translateAndMapModelObject(uncontrolledComponent) ) {
          IdfExtensibleGroup eg = plantEquipmentList.pushExtensibleGroup();
          eg.setString(PlantEquipmentListExtensibleFields::EquipmentObjectType,idfObject->iddObject().name());
          eg.setString(PlantEquipmentListExtensibleFields::EquipmentName,idfObject->name().get());
        }
      }
    }

    createSetpointOperationScheme(plantLoop);
  }

  return operationSchemes;
}
boost::optional<IdfObject> ForwardTranslator::translateEvaporativeCoolerDirectResearchSpecial( EvaporativeCoolerDirectResearchSpecial & modelObject )
{
  OptionalString s;
  OptionalDouble d;
  OptionalModelObject temp;
  double value;

  IdfObject idfObject(IddObjectType::EvaporativeCooler_Direct_ResearchSpecial);

  m_idfObjects.push_back(idfObject);

  // Name
  s = modelObject.name();
  if(s)
  {
    idfObject.setName(*s);
  }

  // AvailabilityScheduleName
  Schedule sched = modelObject.availableSchedule();
  translateAndMapModelObject(sched);
  idfObject.setString(EvaporativeCooler_Direct_ResearchSpecialFields::AvailabilityScheduleName,sched.name().get());

  // CoolerEffectiveness
  value = modelObject.coolerEffectiveness();
  idfObject.setDouble(EvaporativeCooler_Direct_ResearchSpecialFields::CoolerDesignEffectiveness,value);

  // RecirculatingWaterPumpPowerConsumption
  if ( modelObject.isRecirculatingWaterPumpPowerConsumptionAutosized() ) {
    idfObject.setString(EvaporativeCooler_Direct_ResearchSpecialFields::RecirculatingWaterPumpDesignPower,"autosize");
  } else if( (d = modelObject.recirculatingWaterPumpPowerConsumption()) ) {
    idfObject.setDouble(EvaporativeCooler_Direct_ResearchSpecialFields::RecirculatingWaterPumpDesignPower,d.get());
  }

  // AirInletNodeName
  temp = modelObject.inletModelObject();
  if(temp)
  {
    s = temp->name();
    if(s)
    {
      idfObject.setString(EvaporativeCooler_Direct_ResearchSpecialFields::AirInletNodeName,*s);
    }
  }

  // AirOutletNodeName
  temp = modelObject.outletModelObject();
  if(temp)
  {
    s = temp->name();
    if(s)
    {
      idfObject.setString(EvaporativeCooler_Direct_ResearchSpecialFields::AirOutletNodeName,*s);
    }
  }

  // SensorNodeName
  temp = modelObject.sensorNode();
  if(temp)
  {
    s = temp->name();
    if(s)
    {
      idfObject.setString(EvaporativeCooler_Direct_ResearchSpecialFields::SensorNodeName,*s);
    }
  }

  // DriftLossFraction
  value = modelObject.driftLossFraction();
  idfObject.setDouble(EvaporativeCooler_Direct_ResearchSpecialFields::DriftLossFraction,value);

  // BlowdownConcentrationRatio
  value = modelObject.blowdownConcentrationRatio();
  if( value < 2 )
  {
    idfObject.setDouble(EvaporativeCooler_Direct_ResearchSpecialFields::BlowdownConcentrationRatio,2.0);
  }
  else
  {
    idfObject.setDouble(EvaporativeCooler_Direct_ResearchSpecialFields::BlowdownConcentrationRatio,value);
  }

  // EffectivenessFlowRatioModifierCurveName
  if( auto curve = modelObject.effectivenessFlowRatioModifierCurve() ) {
    auto _curve = translateAndMapModelObject(curve.get());
    OS_ASSERT(_curve);
    idfObject.setString(EvaporativeCooler_Direct_ResearchSpecialFields::EffectivenessFlowRatioModifierCurveName,_curve->name().get());
  }

  // WaterPumpPowerSizingFactor
  value = modelObject.waterPumpPowerSizingFactor();
  idfObject.setDouble(EvaporativeCooler_Direct_ResearchSpecialFields::WaterPumpPowerSizingFactor,value);

  // WaterPumpPowerModifierCurveName
  if( auto curve = modelObject.waterPumpPowerModifierCurve() ) {
    auto _curve = translateAndMapModelObject(curve.get());
    OS_ASSERT(_curve);
    idfObject.setString(EvaporativeCooler_Direct_ResearchSpecialFields::WaterPumpPowerModifierCurveName,_curve->name().get());
  } 

  return boost::optional<IdfObject>(idfObject);
}