lib/openstudio-standards/standards/Standards.Construction.rb in openstudio-standards-0.2.2 vs lib/openstudio-standards/standards/Standards.Construction.rb in openstudio-standards-0.2.3

- old
+ new

@@ -1,6 +1,5 @@ - class Standard # @!group Construction # Sets the U-value of a construction to a specified value # by modifying the thickness of the insulation layer. @@ -30,12 +29,11 @@ # Make sure an insulation layer was specified if insulation_layer_name.nil? && target_u_value_ip == 0.0 # Do nothing if the construction already doesn't have an insulation layer elsif insulation_layer_name.nil? - OpenStudio.logFree(OpenStudio::Error, 'openstudio.standards.ConstructionBase', "Requested U-value of #{target_u_value_ip} for #{construction.name}, but this construction has no insulation layer specified. Requested U-value will not be set.") - return false + insulation_layer_name = self.find_and_set_insulaton_layer(construction).name end # Remove the insulation layer if the specified U-value is zero. if target_u_value_ip == 0.0 layer_index = 0 @@ -429,6 +427,245 @@ OpenStudio.logFree(OpenStudio::Error, 'openstudio.standards.Construction', 'Model has no sql file containing results, cannot lookup data.') end return u_factor_w_per_m2_k end + + def find_and_set_insulation_layer(construction) + #skip if already has an insulation layer set. + if construction.insulation.empty? + #find insulation layer + min_conductance = 100.0 + #loop through Layers + construction.layers.each do |layer| + #try casting the layer to an OpaqueMaterial. + material = nil + material = layer.to_OpaqueMaterial.get unless layer.to_OpaqueMaterial.empty? + material = layer.to_FenestrationMaterial.get unless layer.to_FenestrationMaterial.empty? + #check if the cast was successful, then find the insulation layer. + unless nil == material + + if BTAP::Resources::Envelope::Materials::get_conductance(material) < min_conductance + #Keep track of the highest thermal resistance value. + min_conductance = BTAP::Resources::Envelope::Materials::get_conductance(material) + return_material = material + unless material.to_OpaqueMaterial.empty? + construction.setInsulation(material) + end + end + end + end + if construction.insulation.empty? and construction.isOpaque + raise () + OpenStudio.logFree(OpenStudio::Error, 'openstudio.standards.ConstructionBase', "This construction has no insulation layer specified. Construction #{construction.name.get.to_s} insulation layer could not be set!. This occurs when a insulation layer is duplicated in the construction.") + end + else + return construction.insulation.get + end + end + + def change_construction_properties_in_model(model, values, is_percentage = false) + puts JSON.pretty_generate(values) + #copy orginal model for reporting. + before_measure_model = BTAP::FileIO.deep_copy(model) + #report change as Info + info = "" + outdoor_surfaces = BTAP::Geometry::Surfaces::filter_by_boundary_condition(model.getSurfaces(), "Outdoors") + outdoor_subsurfaces = BTAP::Geometry::Surfaces::get_subsurfaces_from_surfaces(outdoor_surfaces) + ground_surfaces = BTAP::Geometry::Surfaces::filter_by_boundary_condition(model.getSurfaces(), "Ground") + ext_windows = BTAP::Geometry::Surfaces::filter_subsurfaces_by_types(outdoor_subsurfaces, ["FixedWindow", "OperableWindow"]) + ext_skylights = BTAP::Geometry::Surfaces::filter_subsurfaces_by_types(outdoor_subsurfaces, ["Skylight", "TubularDaylightDiffuser", "TubularDaylightDome"]) + ext_doors = BTAP::Geometry::Surfaces::filter_subsurfaces_by_types(outdoor_subsurfaces, ["Door"]) + ext_glass_doors = BTAP::Geometry::Surfaces::filter_subsurfaces_by_types(outdoor_subsurfaces, ["GlassDoor"]) + ext_overhead_doors = BTAP::Geometry::Surfaces::filter_subsurfaces_by_types(outdoor_subsurfaces, ["OverheadDoor"]) + + #Ext and Ground Surfaces + (outdoor_surfaces + ground_surfaces).sort.each do |surface| + ecm_cond_name = "#{surface.outsideBoundaryCondition.downcase}_#{surface.surfaceType.downcase}_conductance" + apply_changes_to_surface_construction(model, + surface, + values[ecm_cond_name], + nil, + nil, + is_percentage) + #report change as Info + surface_conductance = BTAP::Geometry::Surfaces.get_surface_construction_conductance(surface) + before_measure_surface_conductance = BTAP::Geometry::Surfaces.get_surface_construction_conductance(OpenStudio::Model::getSurfaceByName(before_measure_model, surface.name.to_s).get) + if before_measure_surface_conductance.round(3) != surface_conductance.round(3) + info << "#{surface.outsideBoundaryCondition.downcase}_#{surface.surfaceType.downcase}_conductance for #{surface.name.to_s} changed from #{before_measure_surface_conductance.round(3)} to #{surface_conductance.round(3)}." + end + end + #Subsurfaces + (ext_doors + ext_overhead_doors + ext_windows + ext_glass_doors +ext_skylights).sort.each do |surface| + ecm_cond_name = "#{surface.outsideBoundaryCondition.downcase}_#{surface.subSurfaceType.downcase}_conductance" + ecm_shgc_name = "#{surface.outsideBoundaryCondition.downcase}_#{surface.subSurfaceType.downcase}_shgc" + ecm_tvis_name = "#{surface.outsideBoundaryCondition.downcase}_#{surface.subSurfaceType.downcase}_tvis" + apply_changes_to_surface_construction(model, + surface, + values[ecm_cond_name], + values[ecm_shgc_name], + values[ecm_tvis_name]) + + + surface_conductance = BTAP::Geometry::Surfaces.get_surface_construction_conductance(surface) + before_surface = OpenStudio::Model::getSubSurfaceByName(before_measure_model, surface.name.to_s).get + before_measure_surface_conductance = BTAP::Geometry::Surfaces.get_surface_construction_conductance(before_surface) + if before_measure_surface_conductance.round(3) != surface_conductance.round(3) + info << "#{surface.outsideBoundaryCondition.downcase}_#{surface.subSurfaceType.downcase}_conductance for #{surface.name.to_s} changed from #{before_measure_surface_conductance.round(3)} to #{surface_conductance.round(3)}." + end + end + info << JSON.pretty_generate(BTAP::FileIO.compare_osm_files(before_measure_model, model)) + return info + end + + def apply_changes_to_surface_construction(model, surface, conductance = nil, shgc = nil, tvis = nil, is_percentage = false) + #If user has no changes...do nothing and return true. + return true if conductance.nil? and shgc.nil? and tvis.nil? + standard = Standard.new() + construction = OpenStudio::Model::getConstructionByName(surface.model, surface.construction.get.name.to_s).get + + #set initial targets + target_u_value_si = conductance + target_shgc = shgc + target_tvis = tvis + #Mulitply by percentages if required. + if true == is_percentage + target_u_value_si = target_u_value_si / 100.0 * BTAP::Resources::Envelope::Constructions.get_conductance(construction) unless conductance.nil? + if true == standard.construction_simple_glazing?(construction) + target_shgc = target_shgc / 100.0 * construction.layers.first.to_SimpleGlazing.get.getSolarHeatGainCoefficient() unless target_shgc.nil? + target_tvis = target_tvis / 100.0 * construction.layers.first.to_SimpleGlazing.get.setVisibleTransmittance() unless target_tvis.nil? + end + end + + new_construction_name_suffix = ":{" + new_construction_name_suffix << " \"cond\"=>#{target_u_value_si.round(3)}" unless target_u_value_si.nil? + new_construction_name_suffix << " \"shgc\"=>#{target_shgc.round(3)}" unless target_shgc.nil? + new_construction_name_suffix << " \"tvis\"=>#{target_tvis.round(3)}" unless target_tvis.nil? + new_construction_name_suffix << "}" + + + new_construction_name = "#{surface.construction.get.name.to_s}-#{new_construction_name_suffix}" + new_construction = OpenStudio::Model::getConstructionByName(surface.model, new_construction_name) + + + if new_construction.empty? + #create new construction. + #create a copy + target_u_value_ip = OpenStudio.convert(target_u_value_si.to_f, 'W/m^2*K', 'Btu/ft^2*hr*R').get unless target_u_value_si.nil? + new_construction = self.construction_deep_copy(model, construction) + case surface.outsideBoundaryCondition + when 'Outdoors' + if standard.construction_simple_glazing?(new_construction) + standard.construction_set_glazing_u_value(new_construction, + target_u_value_ip.to_f, + nil, + false, + false + ) unless conductance.nil? + standard.construction_set_glazing_shgc(new_construction, + shgc + ) unless shgc.nil? + construction_set_glazing_tvis(new_construction, + tvis + ) unless tvis.nil? + + + else + standard.construction_set_u_value(new_construction, + target_u_value_ip.to_f, + find_and_set_insulation_layer( + new_construction).name.get, + intended_surface_type = nil, + false, + false + ) unless conductance.nil? + end + when 'Ground' + case surface.surfaceType + when 'Wall' + standard.construction_set_u_value(new_construction, + target_u_value_ip.to_f, + find_and_set_insulation_layer( + new_construction).name.get, + intended_surface_type = nil, + false, + false + ) unless conductance.nil? +=begin + standard.construction_set_underground_wall_c_factor(new_construction, + target_u_value_ip.to_f, + find_and_set_insulaton_layer(model, + new_construction).name.get) +=end + when 'RoofCeiling', 'Floor' + standard.construction_set_u_value(new_construction, + target_u_value_ip.to_f, + find_and_set_insulation_layer(new_construction).name.get, + intended_surface_type = nil, + false, + false + ) unless conductance.nil? +=begin + standard.construction_set_slab_f_factor(new_construction, + target_u_value_ip.to_f, + find_and_set_insulaton_layer(model, + new_construction).name.get) +=end + end + end + new_construction.setName(new_construction_name) + else + new_construction = new_construction.get + end + surface.setConstruction(new_construction) + end + + #This will create a deep copy of the construction + #@author Phylroy A. Lopez <plopez@nrcan.gc.ca> + #@param model [OpenStudio::Model::Model] + #@param construction <String> + #@return [String] new_construction + def construction_deep_copy(model, construction) + construction = BTAP::Common::validate_array(model, construction, "Construction").first + new_construction = construction.clone.to_Construction.get + #interating through layers." + (0..new_construction.layers.length-1).each do |layernumber| + #cloning material" + cloned_layer = new_construction.getLayer(layernumber).clone.to_Material.get + #"setting material to new construction." + new_construction.setLayer(layernumber, cloned_layer) + end + return new_construction + end + + + # Sets the T-vis of a simple glazing construction to a specified value + # by modifying the thickness of the insulation layer. + # + # @param target_tvis [Double] Visible Transmittance + # @return [Bool] returns true if successful, false if not + def construction_set_glazing_tvis(construction, target_tvis) + if target_tvis >= 1.0 + OpenStudio.logFree(OpenStudio::Error, 'openstudio.standards.ConstructionBase', "Can only set the Tvis can only be set to less than 1.0. #{target_tvis} is > 1.0") + return false + end + + OpenStudio.logFree(OpenStudio::Debug, 'openstudio.standards.ConstructionBase', "Setting TVis for #{construction.name} to #{target_tvis}") + standard = Standard.new() + # Skip layer-by-layer fenestration constructions + unless standard.construction_simple_glazing?(construction) + OpenStudio.logFree(OpenStudio::Error, 'openstudio.standards.ConstructionBase', "Can only set the Tvis of simple glazing. #{construction.name} is not simple glazing.") + return false + end + + # Set the Tvis + glass_layer = construction.layers.first.to_SimpleGlazing.get + glass_layer.setVisibleTransmittance(target_tvis) + glass_layer.setName("#{glass_layer.name} TVis #{target_tvis.round(3)}") + + # Modify the construction name + construction.setName("#{construction.name} TVis #{target_tvis.round(2)}") + return true + end + + end