boost::optional<IdfObject> ForwardTranslator::translateOutputMeter( OutputMeter & modelObject )
{
  boost::optional<IdfObject> idfObject;

  QString name = toQString(modelObject.name()).replace(QString("FuelOil_"), QString("FuelOil#"));

  if (modelObject.meterFileOnly() && modelObject.cumulative()){
    idfObject = IdfObject (openstudio::IddObjectType::Output_Meter_Cumulative_MeterFileOnly);
    m_idfObjects.push_back(*idfObject);

    idfObject->setString(Output_Meter_Cumulative_MeterFileOnlyFields::KeyName, toString(name));

    if (!modelObject.isReportingFrequencyDefaulted()){
      idfObject->setString(Output_Meter_Cumulative_MeterFileOnlyFields::ReportingFrequency, modelObject.reportingFrequency());
    }

  }else if (modelObject.meterFileOnly()){
    idfObject = IdfObject (openstudio::IddObjectType::Output_Meter_MeterFileOnly);
    m_idfObjects.push_back(*idfObject);

    idfObject->setString(Output_Meter_MeterFileOnlyFields::KeyName, toString(name));

    if (!modelObject.isReportingFrequencyDefaulted()){
      idfObject->setString(Output_Meter_MeterFileOnlyFields::ReportingFrequency, modelObject.reportingFrequency());
    }

  }else if (modelObject.cumulative()){
    idfObject = IdfObject (openstudio::IddObjectType::Output_Meter_Cumulative);
    m_idfObjects.push_back(*idfObject);

    idfObject->setString(Output_Meter_CumulativeFields::KeyName, toString(name));

    if (!modelObject.isReportingFrequencyDefaulted()){
      idfObject->setString(Output_Meter_CumulativeFields::ReportingFrequency, modelObject.reportingFrequency());
    }

  }else{
    idfObject = IdfObject (openstudio::IddObjectType::Output_Meter);
    m_idfObjects.push_back(*idfObject);

    idfObject->setString(Output_MeterFields::KeyName, toString(name));

    if (!modelObject.isReportingFrequencyDefaulted()){
      idfObject->setString(Output_MeterFields::ReportingFrequency, modelObject.reportingFrequency());
    }

  }

  return idfObject;
}
boost::optional<IdfObject> ForwardTranslator::translateAirLoopHVACOutdoorAirSystem( AirLoopHVACOutdoorAirSystem & modelObject )
{
  OptionalString s;
  IdfObject idfObject(IddObjectType::AirLoopHVAC_OutdoorAirSystem);

  m_idfObjects.push_back(idfObject);

  // Name
  std::string name = modelObject.name().get();
  idfObject.setString(openstudio::AirLoopHVAC_OutdoorAirSystemFields::Name,name);
 

  // Controller List
  IdfObject _controllerList(IddObjectType::AirLoopHVAC_ControllerList);
  _controllerList.setName(name + " Controller List");
  _controllerList.clearExtensibleGroups();
  m_idfObjects.push_back(_controllerList);

  ControllerOutdoorAir controllerOutdoorAir = modelObject.getControllerOutdoorAir();
  boost::optional<IdfObject> _controllerOutdoorAir = translateAndMapModelObject(controllerOutdoorAir);
  OS_ASSERT(_controllerOutdoorAir);

  idfObject.setString(openstudio::AirLoopHVAC_OutdoorAirSystemFields::ControllerListName,_controllerList.name().get());

  IdfExtensibleGroup eg = _controllerList.pushExtensibleGroup();
  eg.setString(AirLoopHVAC_ControllerListExtensibleFields::ControllerObjectType,_controllerOutdoorAir->iddObject().name());
  eg.setString(AirLoopHVAC_ControllerListExtensibleFields::ControllerName,_controllerOutdoorAir->name().get());

  std::vector<ModelObject> controllers;
  auto components = modelObject.components();
  for( const auto & component : components ) {
    boost::optional<ControllerWaterCoil> controller;

    if( auto coil = component.optionalCast<CoilCoolingWater>() ) {
      controller = coil->controllerWaterCoil();
    } else if ( auto coil = component.optionalCast<CoilHeatingWater>() ) {
      controller = coil->controllerWaterCoil();
    }

    if( controller ) {
      controllers.push_back(controller.get());
    }
  } 
  
  for( auto & controller: controllers ) {
    auto _controller = translateAndMapModelObject(controller);
    if( _controller ) {
      IdfExtensibleGroup eg = _controllerList.pushExtensibleGroup();
      eg.setString(AirLoopHVAC_ControllerListExtensibleFields::ControllerObjectType,_controller->iddObject().name());
      eg.setString(AirLoopHVAC_ControllerListExtensibleFields::ControllerName,_controller->name().get());
    }
  }

  // Field: Availability Manager List Name //////////////////////////////////
  IdfObject availabilityManagerListIdf(IddObjectType::AvailabilityManagerAssignmentList);
  availabilityManagerListIdf.setName(name + " Availability Manager List");
  m_idfObjects.push_back(availabilityManagerListIdf);

  IdfObject availabilityManagerScheduledIdf = IdfObject(openstudio::IddObjectType::AvailabilityManager_Scheduled);
  availabilityManagerScheduledIdf.setName(name + " Availability Manager");
  m_idfObjects.push_back(availabilityManagerScheduledIdf);

  Schedule alwaysOn = modelObject.model().alwaysOnDiscreteSchedule();
  IdfObject alwaysOnIdf = translateAndMapModelObject(alwaysOn).get();

  s = availabilityManagerListIdf.getString(openstudio::AvailabilityManagerAssignmentListFields::Name);
  if(s)
  {
    idfObject.setString(openstudio::AirLoopHVAC_OutdoorAirSystemFields::AvailabilityManagerListName,*s);
  }

  availabilityManagerListIdf.setString(1 + openstudio::AvailabilityManagerAssignmentListExtensibleFields::AvailabilityManagerObjectType,
                                       availabilityManagerScheduledIdf.iddObject().name());
  availabilityManagerListIdf.setString(1 + openstudio::AvailabilityManagerAssignmentListExtensibleFields::AvailabilityManagerName,
                                       availabilityManagerScheduledIdf.name().get());
  availabilityManagerScheduledIdf.setString(openstudio::AvailabilityManager_ScheduledFields::ScheduleName,alwaysOnIdf.name().get());

  // OA Node List
  s = modelObject.outboardOANode()->name();
  IdfObject oaNodeListIdf(openstudio::IddObjectType::OutdoorAir_NodeList);
  if(s)
  {
    oaNodeListIdf.setString(0,*s);
  }
  m_idfObjects.push_back(oaNodeListIdf);

  ///////////////////////////////////////////////////////////////////////////
  // Field: Outdoor Air Equipment List Name /////////////////////////////////
  IdfObject equipmentListIdf(IddObjectType::AirLoopHVAC_OutdoorAirSystem_EquipmentList);
  equipmentListIdf.setName(name + " Equipment List");

  m_idfObjects.push_back(equipmentListIdf);

  IdfObject outdoorAirMixerIdf(IddObjectType::OutdoorAir_Mixer);
  outdoorAirMixerIdf.setName(name + " Outdoor Air Mixer");
  m_idfObjects.push_back(outdoorAirMixerIdf);

  s = modelObject.mixedAirModelObject()->name();
  if(s)
  {
    outdoorAirMixerIdf.setString(OutdoorAir_MixerFields::MixedAirNodeName,*s);
  }
  s = modelObject.outdoorAirModelObject()->name();
  if(s)
  {
    outdoorAirMixerIdf.setString(OutdoorAir_MixerFields::OutdoorAirStreamNodeName,*s);
  }

  s = modelObject.reliefAirModelObject()->name();
  if(s)
  {
    outdoorAirMixerIdf.setString(OutdoorAir_MixerFields::ReliefAirStreamNodeName,*s);
  }

  s = modelObject.returnAirModelObject()->name();
  if(s)
  {
    outdoorAirMixerIdf.setString(OutdoorAir_MixerFields::ReturnAirStreamNodeName,*s);
  }

  s = outdoorAirMixerIdf.iddObject().name();
  equipmentListIdf.setString(1,*s);
  s = outdoorAirMixerIdf.name();
  equipmentListIdf.setString(2,*s);

  unsigned i = 3;
  ModelObjectVector oaModelObjects = modelObject.oaComponents();
  for( ModelObjectVector::iterator oaIt = oaModelObjects.begin();
       oaIt != oaModelObjects.end();
       ++oaIt )
  {
    if( ! oaIt->optionalCast<Node>() )
    {
      if( boost::optional<IdfObject> idfObject = translateAndMapModelObject(*oaIt) )
      {
        equipmentListIdf.setString(i,idfObject->iddObject().name());
        i++;
        equipmentListIdf.setString(i,idfObject->name().get());
        i++;
      }
    }
  }

  ModelObjectVector reliefModelObjects = modelObject.reliefComponents();
  for( ModelObjectVector::iterator reliefIt = reliefModelObjects.begin();
       reliefIt != reliefModelObjects.end();
       ++reliefIt )
  {
    if( (! reliefIt->optionalCast<Node>()) && (! reliefIt->optionalCast<AirToAirComponent>()) )
    {
      if( boost::optional<IdfObject> idfObject = translateAndMapModelObject(*reliefIt) )
      {
        equipmentListIdf.setString(i,idfObject->iddObject().name());
        i++;
        equipmentListIdf.setString(i,idfObject->name().get());
        i++;
      }
    }
  }

  s = equipmentListIdf.name();
  if(s)
  {
    idfObject.setString(openstudio::AirLoopHVAC_OutdoorAirSystemFields::OutdoorAirEquipmentListName,*s);
  }

  return boost::optional<IdfObject>(idfObject);
}
boost::optional<IdfObject> ForwardTranslator::translateAirLoopHVACOutdoorAirSystem( AirLoopHVACOutdoorAirSystem & modelObject )
{
  OptionalString s;
  IdfObject idfObject(IddObjectType::AirLoopHVAC_OutdoorAirSystem);

  m_idfObjects.push_back(idfObject);

  // Name
  std::string name = modelObject.name().get();
  idfObject.setString(openstudio::AirLoopHVAC_OutdoorAirSystemFields::Name,name);
 

  // Controller List
  IdfObject controllerListIdf(IddObjectType::AirLoopHVAC_ControllerList);
  controllerListIdf.setName(name + " Controller List");
  controllerListIdf.clearExtensibleGroups();

  m_idfObjects.push_back(controllerListIdf);

  ControllerOutdoorAir controllerOutdoorAir = modelObject.getControllerOutdoorAir();
  boost::optional<IdfObject> temp = translateAndMapModelObject(controllerOutdoorAir);

  s = controllerListIdf.name();
  if(s)
  {
    idfObject.setString(openstudio::AirLoopHVAC_OutdoorAirSystemFields::ControllerListName,*s);
  }

  s = temp->iddObject().name();
  StringVector groupFields(2u);
  bool addGroup(false);
  if(s)
  {
    groupFields[0] = *s;
    addGroup = true;
  }

  s = temp->name();
  if(s)
  {
    groupFields[1] = *s;
    addGroup = true;
  }

  if (addGroup) {
    IdfExtensibleGroup eg = controllerListIdf.pushExtensibleGroup(groupFields);
    OS_ASSERT(!eg.empty());
  }

  // Field: Availability Manager List Name //////////////////////////////////
  IdfObject availabilityManagerListIdf(IddObjectType::AvailabilityManagerAssignmentList);
  availabilityManagerListIdf.setName(name + " Availability Manager");
  m_idfObjects.push_back(availabilityManagerListIdf);

  IdfObject availabilityManagerScheduledIdf = IdfObject(openstudio::IddObjectType::AvailabilityManager_Scheduled);
  availabilityManagerScheduledIdf.createName();
  m_idfObjects.push_back(availabilityManagerScheduledIdf);

  Schedule alwaysOn = modelObject.model().alwaysOnDiscreteSchedule();
  IdfObject alwaysOnIdf = translateAndMapModelObject(alwaysOn).get();

  s = availabilityManagerListIdf.getString(openstudio::AvailabilityManagerAssignmentListFields::Name);
  if(s)
  {
    idfObject.setString(openstudio::AirLoopHVAC_OutdoorAirSystemFields::AvailabilityManagerListName,*s);
  }

  availabilityManagerListIdf.setString(1 + openstudio::AvailabilityManagerAssignmentListExtensibleFields::AvailabilityManagerObjectType,
                                       availabilityManagerScheduledIdf.iddObject().name());
  availabilityManagerListIdf.setString(1 + openstudio::AvailabilityManagerAssignmentListExtensibleFields::AvailabilityManagerName,
                                       availabilityManagerScheduledIdf.name().get());
  availabilityManagerScheduledIdf.setString(openstudio::AvailabilityManager_ScheduledFields::ScheduleName,alwaysOnIdf.name().get());

  // OA Node List
  s = modelObject.outboardOANode()->name();
  IdfObject oaNodeListIdf(openstudio::IddObjectType::OutdoorAir_NodeList);
  if(s)
  {
    oaNodeListIdf.setString(0,*s);
  }
  m_idfObjects.push_back(oaNodeListIdf);

  ///////////////////////////////////////////////////////////////////////////
  // Field: Outdoor Air Equipment List Name /////////////////////////////////
  IdfObject equipmentListIdf(IddObjectType::AirLoopHVAC_OutdoorAirSystem_EquipmentList);
  equipmentListIdf.setName(name + " Equipment List");

  m_idfObjects.push_back(equipmentListIdf);

  IdfObject outdoorAirMixerIdf(IddObjectType::OutdoorAir_Mixer);
  outdoorAirMixerIdf.setName(name + " Outdoor Air Mixer");
  m_idfObjects.push_back(outdoorAirMixerIdf);

  s = modelObject.mixedAirModelObject()->name();
  if(s)
  {
    outdoorAirMixerIdf.setString(OutdoorAir_MixerFields::MixedAirNodeName,*s);
  }
  s = modelObject.outdoorAirModelObject()->name();
  if(s)
  {
    outdoorAirMixerIdf.setString(OutdoorAir_MixerFields::OutdoorAirStreamNodeName,*s);
  }

  s = modelObject.reliefAirModelObject()->name();
  if(s)
  {
    outdoorAirMixerIdf.setString(OutdoorAir_MixerFields::ReliefAirStreamNodeName,*s);
  }

  s = modelObject.returnAirModelObject()->name();
  if(s)
  {
    outdoorAirMixerIdf.setString(OutdoorAir_MixerFields::ReturnAirStreamNodeName,*s);
  }

  s = outdoorAirMixerIdf.iddObject().name();
  equipmentListIdf.setString(1,*s);
  s = outdoorAirMixerIdf.name();
  equipmentListIdf.setString(2,*s);

  ModelObjectVector oaModelObjects = modelObject.oaComponents();
  ModelObjectVector::iterator oaIt;
  unsigned i = 3;
  for( oaIt = oaModelObjects.begin();
       oaIt != oaModelObjects.end();
       ++oaIt )
  {
    if( ! oaIt->optionalCast<Node>() )
    {
      s = stripOS2(oaIt->iddObject().name());
      if(s)
        equipmentListIdf.setString(i,*s);
      i++;
      s = oaIt->name();
      if(s)
        equipmentListIdf.setString(i,*s);
      i++;
    }
  }

  s = equipmentListIdf.name();
  if(s)
  {
    idfObject.setString(openstudio::AirLoopHVAC_OutdoorAirSystemFields::OutdoorAirEquipmentListName,*s);
  }

  for( oaIt = oaModelObjects.begin();
       oaIt != oaModelObjects.end();
       ++oaIt )
  {
    translateAndMapModelObject(*oaIt);
  }

  return boost::optional<IdfObject>(idfObject);
}
boost::optional<IdfObject> ForwardTranslator::translateShadingSurface( model::ShadingSurface & modelObject )
{
  boost::optional<IdfObject> idfObject;

  boost::optional<Schedule> transmittanceSchedule = modelObject.transmittanceSchedule();
  Transformation transformation;
  Point3dVector points;

  boost::optional<ShadingSurfaceGroup> shadingSurfaceGroup = modelObject.shadingSurfaceGroup();
  if (shadingSurfaceGroup){

    transformation = shadingSurfaceGroup->transformation();
    points = transformation * modelObject.vertices();

    if (istringEqual("Space", shadingSurfaceGroup->shadingSurfaceType())){

      idfObject = IdfObject(openstudio::IddObjectType::Shading_Zone_Detailed);
      idfObject->setString(Shading_Zone_DetailedFields::Name, modelObject.name().get());

      boost::optional<Space> space = shadingSurfaceGroup->space();
      if (space){
        
        boost::optional<Surface> baseSurface;
        double minDistance = std::numeric_limits<double>::max();

        // at this point zone has one space and internal surfaces have already been combined
        for (const Surface& surface : space->surfaces()){
          if (istringEqual(surface.outsideBoundaryCondition(), "Outdoors")){
            Point3dVector surfaceVertices = surface.vertices();
            for (const Point3d& point : points){
              for (const Point3d& surfaceVertex : surfaceVertices){
                double distance = getDistance(point, surfaceVertex);
                if (distance < minDistance){
                  baseSurface = surface;
                  minDistance = distance;
                }
              }
            }
          }
        }

        if (!baseSurface){
          LOG(Error, "Cannot find appropriate base surface for shading surface '" << modelObject.name().get() << 
                     "', the shading surface will not be translated");
          return boost::none;
        }

        idfObject->setString(Shading_Zone_DetailedFields::BaseSurfaceName, baseSurface->name().get());
      }

      if (transmittanceSchedule){
        idfObject->setString(Shading_Zone_DetailedFields::TransmittanceScheduleName, transmittanceSchedule->name().get());
      }

    }else if (istringEqual("Site", shadingSurfaceGroup->shadingSurfaceType())){

      idfObject = IdfObject(openstudio::IddObjectType::Shading_Site_Detailed);
      idfObject->setString(Shading_Site_DetailedFields::Name, modelObject.name().get());
      
      if (transmittanceSchedule){
        idfObject->setString(Shading_Site_DetailedFields::TransmittanceScheduleName, transmittanceSchedule->name().get());
      }

    }else{
      boost::optional<Building> building = modelObject.model().getUniqueModelObject<Building>();
      if (building){
        transformation = building->transformation().inverse()*transformation;
      }

      idfObject = IdfObject(openstudio::IddObjectType::Shading_Building_Detailed);
      idfObject->setString(Shading_Building_DetailedFields::Name, modelObject.name().get());
      
      if (transmittanceSchedule){
        idfObject->setString(Shading_Building_DetailedFields::TransmittanceScheduleName, transmittanceSchedule->name().get());
      }
    }

  }else{
    idfObject = IdfObject(openstudio::IddObjectType::Shading_Building_Detailed);
    idfObject->setString(Shading_Building_DetailedFields::Name, modelObject.name().get());
    
    if (transmittanceSchedule){
      idfObject->setString(Shading_Building_DetailedFields::TransmittanceScheduleName, transmittanceSchedule->name().get());
    }
  }

  m_idfObjects.push_back(*idfObject);

  idfObject->clearExtensibleGroups();

  for (const Point3d& point : points){
    IdfExtensibleGroup group = idfObject->pushExtensibleGroup();
    OS_ASSERT(group.numFields() == 3);
    group.setDouble(0, point.x());
    group.setDouble(1, point.y());
    group.setDouble(2, point.z());
  }

  // get reflectance properties from construction if possible
  bool addShadingPropertyObject = false;

  IdfObject shadingPropertyObject = IdfObject(openstudio::IddObjectType::ShadingProperty_Reflectance);
  shadingPropertyObject.setString(ShadingProperty_ReflectanceFields::ShadingSurfaceName, modelObject.name().get());

  boost::optional<model::ConstructionBase> constructionBase = modelObject.construction();
  if (constructionBase){
    if (constructionBase->isFenestration()){

      shadingPropertyObject.setDouble(ShadingProperty_ReflectanceFields::FractionofShadingSurfaceThatIsGlazed, 1.0);
      shadingPropertyObject.setString(ShadingProperty_ReflectanceFields::GlazingConstructionName, constructionBase->name().get());
      addShadingPropertyObject = true;

    }else{

      shadingPropertyObject.setDouble(ShadingProperty_ReflectanceFields::FractionofShadingSurfaceThatIsGlazed, 0.0);

      boost::optional<model::Construction> construction = constructionBase->optionalCast<model::Construction>();
      if (construction){

        std::vector<model::Material> layers = construction->layers();

        // we want the outer layer
        if (!layers.empty()){

          if (layers[0].optionalCast<model::StandardOpaqueMaterial>()){
            model::StandardOpaqueMaterial outerMaterial = layers[0].cast<model::StandardOpaqueMaterial>();

            boost::optional<double> solRefl = outerMaterial.solarReflectance();
            if (solRefl){
              shadingPropertyObject.setDouble(ShadingProperty_ReflectanceFields::DiffuseSolarReflectanceofUnglazedPartofShadingSurface, *solRefl);
              addShadingPropertyObject = true;
            }

            boost::optional<double> visRefl = outerMaterial.visibleReflectance();
            if (visRefl){
              shadingPropertyObject.setDouble(ShadingProperty_ReflectanceFields::DiffuseVisibleReflectanceofUnglazedPartofShadingSurface, *visRefl);
              addShadingPropertyObject = true;
            }
          }

          
          if (layers[0].optionalCast<model::MasslessOpaqueMaterial>()){
            model::MasslessOpaqueMaterial outerMaterial = layers[0].cast<model::MasslessOpaqueMaterial>();

            boost::optional<double> solRefl = outerMaterial.solarReflectance();
            if (solRefl){
              shadingPropertyObject.setDouble(ShadingProperty_ReflectanceFields::DiffuseSolarReflectanceofUnglazedPartofShadingSurface, *solRefl);
              addShadingPropertyObject = true;
            }

            boost::optional<double> visRefl = outerMaterial.visibleReflectance();
            if (visRefl){
              shadingPropertyObject.setDouble(ShadingProperty_ReflectanceFields::DiffuseVisibleReflectanceofUnglazedPartofShadingSurface, *visRefl);
              addShadingPropertyObject = true;
            }
          }

        }
      }
    }
  }

  if (addShadingPropertyObject){
    m_idfObjects.push_back(shadingPropertyObject);
  }

  return idfObject;
}
boost::optional<IdfObject> ForwardTranslator::translateDaylightRedirectionDevice(model::DaylightRedirectionDevice & modelObject)
{
  boost::optional<IdfObject> result;

  if (modelObject.daylightRedirectionDeviceType() == "Film"){
    result = IdfObject(openstudio::IddObjectType::WindowMaterial_Blind);

    m_idfObjects.push_back(*result);

    result->setString(WindowMaterial_BlindFields::Name, modelObject.name().get());
    result->setString(WindowMaterial_BlindFields::SlatOrientation, "Horizontal");
    result->setDouble(WindowMaterial_BlindFields::SlatWidth, 0.0508); // 2 in
    result->setDouble(WindowMaterial_BlindFields::SlatSeparation, 0.0254); // 1 in
    result->setDouble(WindowMaterial_BlindFields::SlatThickness, 0.005);
    result->setDouble(WindowMaterial_BlindFields::SlatAngle, 60.0);
    result->setDouble(WindowMaterial_BlindFields::SlatConductivity, 221.0);
    result->setDouble(WindowMaterial_BlindFields::SlatBeamSolarTransmittance, 0.0);
    result->setDouble(WindowMaterial_BlindFields::FrontSideSlatBeamSolarReflectance, 0.9);
    result->setDouble(WindowMaterial_BlindFields::BackSideSlatBeamSolarReflectance, 0.9);
    result->setDouble(WindowMaterial_BlindFields::SlatDiffuseSolarTransmittance, 0.0);
    result->setDouble(WindowMaterial_BlindFields::FrontSideSlatDiffuseSolarReflectance, 0.9);
    result->setDouble(WindowMaterial_BlindFields::BackSideSlatDiffuseSolarReflectance, 0.9);
    result->setDouble(WindowMaterial_BlindFields::SlatBeamVisibleTransmittance, 0.0);
    result->setDouble(WindowMaterial_BlindFields::FrontSideSlatBeamVisibleReflectance, 0.9);
    result->setDouble(WindowMaterial_BlindFields::BackSideSlatBeamVisibleReflectance, 0.9);
    result->setDouble(WindowMaterial_BlindFields::SlatDiffuseVisibleTransmittance, 0.0);
    result->setDouble(WindowMaterial_BlindFields::FrontSideSlatDiffuseVisibleReflectance, 0.9);
    result->setDouble(WindowMaterial_BlindFields::BackSideSlatDiffuseVisibleReflectance, 0.9);
    result->setDouble(WindowMaterial_BlindFields::SlatInfraredHemisphericalTransmittance, 0.0);
    result->setDouble(WindowMaterial_BlindFields::FrontSideSlatInfraredHemisphericalEmissivity, 0.9);
    result->setDouble(WindowMaterial_BlindFields::BackSideSlatInfraredHemisphericalEmissivity, 0.9);
    result->setDouble(WindowMaterial_BlindFields::BlindtoGlassDistance, 0.0254);
    result->setDouble(WindowMaterial_BlindFields::BlindTopOpeningMultiplier, 0.5);
    result->setDouble(WindowMaterial_BlindFields::BlindBottomOpeningMultiplier, 0.0);
    result->setDouble(WindowMaterial_BlindFields::BlindLeftSideOpeningMultiplier, 0.5);
    result->setDouble(WindowMaterial_BlindFields::BlindRightSideOpeningMultiplier, 0.5);
    result->setDouble(WindowMaterial_BlindFields::MinimumSlatAngle, 60);
    result->setDouble(WindowMaterial_BlindFields::MaximumSlatAngle, 60);

  } else if (modelObject.daylightRedirectionDeviceType() == "Louver"){
    result = IdfObject(openstudio::IddObjectType::WindowMaterial_Blind);

    m_idfObjects.push_back(*result);

    result->setString(WindowMaterial_BlindFields::Name, modelObject.name().get());
    result->setString(WindowMaterial_BlindFields::SlatOrientation, "Horizontal");
    result->setDouble(WindowMaterial_BlindFields::SlatWidth, 0.0508); // 2 in
    result->setDouble(WindowMaterial_BlindFields::SlatSeparation, 0.0254); // 1 in
    result->setDouble(WindowMaterial_BlindFields::SlatThickness, 0.005);
    result->setDouble(WindowMaterial_BlindFields::SlatAngle, 60.0);
    result->setDouble(WindowMaterial_BlindFields::SlatConductivity, 221.0);
    result->setDouble(WindowMaterial_BlindFields::SlatBeamSolarTransmittance, 0.0);
    result->setDouble(WindowMaterial_BlindFields::FrontSideSlatBeamSolarReflectance, 0.9);
    result->setDouble(WindowMaterial_BlindFields::BackSideSlatBeamSolarReflectance, 0.9);
    result->setDouble(WindowMaterial_BlindFields::SlatDiffuseSolarTransmittance, 0.0);
    result->setDouble(WindowMaterial_BlindFields::FrontSideSlatDiffuseSolarReflectance, 0.9);
    result->setDouble(WindowMaterial_BlindFields::BackSideSlatDiffuseSolarReflectance, 0.9);
    result->setDouble(WindowMaterial_BlindFields::SlatBeamVisibleTransmittance, 0.0);
    result->setDouble(WindowMaterial_BlindFields::FrontSideSlatBeamVisibleReflectance, 0.9);
    result->setDouble(WindowMaterial_BlindFields::BackSideSlatBeamVisibleReflectance, 0.9);
    result->setDouble(WindowMaterial_BlindFields::SlatDiffuseVisibleTransmittance, 0.0);
    result->setDouble(WindowMaterial_BlindFields::FrontSideSlatDiffuseVisibleReflectance, 0.9);
    result->setDouble(WindowMaterial_BlindFields::BackSideSlatDiffuseVisibleReflectance, 0.9);
    result->setDouble(WindowMaterial_BlindFields::SlatInfraredHemisphericalTransmittance, 0.0);
    result->setDouble(WindowMaterial_BlindFields::FrontSideSlatInfraredHemisphericalEmissivity, 0.9);
    result->setDouble(WindowMaterial_BlindFields::BackSideSlatInfraredHemisphericalEmissivity, 0.9);
    result->setDouble(WindowMaterial_BlindFields::BlindtoGlassDistance, 0.0254);
    result->setDouble(WindowMaterial_BlindFields::BlindTopOpeningMultiplier, 0.5);
    result->setDouble(WindowMaterial_BlindFields::BlindBottomOpeningMultiplier, 0.0);
    result->setDouble(WindowMaterial_BlindFields::BlindLeftSideOpeningMultiplier, 0.5);
    result->setDouble(WindowMaterial_BlindFields::BlindRightSideOpeningMultiplier, 0.5);
    result->setDouble(WindowMaterial_BlindFields::MinimumSlatAngle, 60);
    result->setDouble(WindowMaterial_BlindFields::MaximumSlatAngle, 60);
  }

  return result;
}