# ******************************************************************************* # Honeybee OpenStudio Gem, Copyright (c) 2020, Alliance for Sustainable # Energy, LLC, Ladybug Tools LLC and other contributors. All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # (1) Redistributions of source code must retain the above copyright notice, # this list of conditions and the following disclaimer. # # (2) Redistributions in binary form must reproduce the above copyright notice, # this list of conditions and the following disclaimer in the documentation # and/or other materials provided with the distribution. # # (3) Neither the name of the copyright holder nor the names of any contributors # may be used to endorse or promote products derived from this software without # specific prior written permission from the respective party. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND ANY CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, # THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S), ANY CONTRIBUTORS, THE # UNITED STATES GOVERNMENT, OR THE UNITED STATES DEPARTMENT OF ENERGY, NOR ANY OF # THEIR EMPLOYEES, BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT # OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, # STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # ******************************************************************************* require 'honeybee/construction/windowshade' require 'to_openstudio/model_object' module Honeybee class WindowConstructionShadeAbridged attr_reader :construction, :shade_construction, :shade_location, :shade_material, :control_type, :setpoint, :schedule def find_existing_openstudio_object(openstudio_model) object = openstudio_model.getConstructionByName(@hash[:identifier]) return object.get if object.is_initialized nil end def to_openstudio(openstudio_model) # write the shaded and unsaded versions of the construction into the model # reverse the shaded and unshaded identifiers so unshaded one is assigned to apertures unshd_id = @hash[:identifier] shd_id = @hash[:window_construction][:identifier] @hash[:window_construction][:identifier] = unshd_id @hash[:identifier] = shd_id # create the unshaded construction unshd_constr_obj = WindowConstructionAbridged.new(@hash[:window_construction]) @construction = unshd_constr_obj.to_openstudio(openstudio_model) # create the shaded construction @shade_construction = OpenStudio::Model::Construction.new(openstudio_model) @shade_construction.setName(shd_id) unless @hash[:display_name].nil? @shade_construction.setDisplayName(@hash[:display_name]) end # create the layers of the unshaded construction into which we will insert the shade os_materials = [] if @hash.key?(:layers) mat_key = :layers else mat_key = :materials end @hash[:window_construction][mat_key].each do |material_identifier| material = openstudio_model.getMaterialByName(material_identifier) unless material.empty? os_material = material.get os_materials << os_material end end # figure out where to insert the shade material and insert it if @hash[:shade_location] @shade_location = @hash[:shade_location] else @shade_location = defaults[:shade_location][:default] end # insert the shade material shd_mat_name = openstudio_model.getMaterialByName(@hash[:shade_material]) unless shd_mat_name.empty? @shade_material = shd_mat_name.get obj_type = @shade_material.iddObject.name.to_s end unless @shade_material.nil? if obj_type == 'OS:WindowMaterial:StandardGlazing' || obj_type == 'OS:WindowMaterial:Glazing' if @shade_location == 'Interior' os_materials[-1] = @shade_material elsif @shade_location == 'Exterior' || os_materials.length < 2 os_materials[0] = @shade_material else # middle glass pane os_materials[-3] = @shade_material end else if @shade_location == 'Interior' os_materials << @shade_material elsif @shade_location == 'Exterior' os_materials.unshift(@shade_material) else # between glass shade/blind split_gap = split_gas_gap(openstudio_model, os_materials[-2], @shade_material) os_materials[-2] = split_gap os_materials.insert(-2, @shade_material) os_materials.insert(-2, split_gap) end end end # assign the layers to the shaded construction os_materials_vec = OpenStudio::Model::MaterialVector.new os_materials.each do |mat| os_materials_vec << mat end @shade_construction.setLayers(os_materials) # set defaults for control type, setpoint, and schedule if @hash[:control_type] @control_type = @hash[:control_type] else @control_type = defaults[:control_type][:default] end if @hash[:setpoint] @setpoint = @hash[:setpoint] else @setpoint = defaults[:setpoint][:default] end unless @hash[:schedule].nil? schedule_ref = openstudio_model.getScheduleByName(@hash[:schedule]) unless schedule_ref.empty? @schedule = schedule_ref.get if @control_type == 'AlwaysOn' @control_type = 'OnIfScheduleAllows' end end end @shade_construction end def to_openstudio_shading_control(openstudio_model) # add a WindowShadingControl object to a model for a given aperture and room os_shade_control = OpenStudio::Model::ShadingControl.new(@shade_construction) # figure out the shading type unless @shade_material.nil? obj_type = @shade_material.iddObject.name.to_s end if obj_type == 'OS:WindowMaterial:StandardGlazing' || obj_type == 'OS:WindowMaterial:Glazing' shd_type = 'SwitchableGlazing' elsif obj_type == 'OS:WindowMaterial:Blind' if @shade_location == 'Between' shd_type = 'BetweenGlassBlind' else shd_type = @shade_location + 'Blind' end else if @shade_location == 'Between' shd_type = 'BetweenGlassShade' else shd_type = @shade_location + 'Shade' end end os_shade_control.setShadingType(shd_type) # set the shade control type and schedule os_shade_control.setShadingControlType(@control_type) unless @setpoint.nil? os_shade_control.setSetpoint(@setpoint) end unless @schedule.nil? os_shade_control.setSchedule(@schedule) end os_shade_control end def split_gas_gap(openstudio_model, original_gap, shade_material) # split a gas gap material in two when it is interrupeted by a shade/blind if shade_material.is_a? OpenStudio::Model::Blind shd_thick = 0 else shd_thick = shade_material.thickness end gap_thick = (original_gap.thickness - shd_thick) / 2 gap_thick = gap_thick.round(4) if gap_thick.to_s.end_with?('5') gap_thick = gap_thick + 0.0005 end gap_thick = gap_thick.round(3) gap_id_start = original_gap.name.get + '_Split' + gap_thick.to_s new_gap_init = openstudio_model.getMaterialByName(gap_id_start) if new_gap_init.is_initialized new_gap = new_gap_init.get else gap_obj = $gas_gap_hash[original_gap.name.get] new_gap = gap_obj.to_openstudio(openstudio_model) new_gap.setName(original_gap.name.get + gap_thick.to_s) new_gap.setThickness(gap_thick) end new_gap end end #WindowConstructionShadeAbridged end #Honeybee