lib/openstudio-standards/standards/Standards.Model.rb in openstudio-standards-0.6.0.rc2 vs lib/openstudio-standards/standards/Standards.Model.rb in openstudio-standards-0.6.3
- old
+ new
@@ -1,11 +1,10 @@
require 'csv'
require 'date'
class Standard
- attr_accessor :space_multiplier_map
- attr_accessor :standards_data
+ attr_accessor :space_multiplier_map, :standards_data
# returns the space multiplier map
# @return [Hash] space multiplier map
def define_space_multiplier
@@ -121,13 +120,12 @@
'Simulation on proposed model failed. Baseline generation is stopped.')
end
end
if create_proposed_model
# Make the run directory if it doesn't exist
- unless Dir.exist?(sizing_run_dir)
- FileUtils.mkdir_p(sizing_run_dir)
- end
+ FileUtils.mkdir_p(sizing_run_dir)
+
# Save proposed model
proposed_model.save(OpenStudio::Path.new("#{sizing_run_dir}/proposed_final.osm"), true)
forward_translator = OpenStudio::EnergyPlus::ForwardTranslator.new
idf = forward_translator.translateModel(proposed_model)
idf_path = OpenStudio::Path.new("#{sizing_run_dir}/proposed_final.idf")
@@ -824,11 +822,11 @@
# (and for Xcel Energy CO EDA)
# fossilandelectric
zones = model_zones_with_occ_and_fuel_type(model, custom)
# Ensure that there is at least one conditioned zone
- if zones.size.zero?
+ if zones.empty?
OpenStudio.logFree(OpenStudio::Warn, 'openstudio.standards.Model', 'The building does not appear to have any conditioned zones. Make sure zones have thermostat with appropriate heating and cooling setpoint schedules.')
return []
end
# Group the zones by occupancy type
@@ -1153,15 +1151,15 @@
# Note: testing showed that the fan object schedule is not used by OpenStudio
# Instead, get the fan schedule from the air_loop_hvac object
# fan_object = nil
# fan_object = get_fan_object_for_airloop(model, air_loop_hvac)
fan_object = 'nothing'
- if !fan_object.nil?
+ if fan_object.nil?
+ OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.Model', "Failed to retreive fan object for AirLoop #{air_loop_hvac.name}")
+ else
# fan_schedule = fan_object.availabilitySchedule
fan_schedule = air_loop_hvac.availabilitySchedule
- else
- OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.Model', "Failed to retreive fan object for AirLoop #{air_loop_hvac.name}")
end
fan_schedule_8760 = OpenstudioStandards::Schedules.schedule_get_hourly_values(fan_schedule)
end
# Assign this schedule to each zone on this air loop
@@ -1197,13 +1195,11 @@
# @author Doug Maddox, PNNL
# @param model [object]
# @param air_loop [object]
# @return [object] supply fan of zone equipment component
def get_fan_object_for_airloop(model, air_loop)
- if !air_loop.supplyFan.empty?
- fan_component = air_loop.supplyFan.get
- else
+ if air_loop.supplyFan.empty?
# Check if system has unitary wrapper
air_loop.supplyComponents.each do |component|
# Get the object type, getting the internal coil
# type if inside a unitary system.
obj_type = component.iddObjectType.valueName.to_s
@@ -1225,10 +1221,12 @@
if !fan_component.nil?
break
end
end
+ else
+ fan_component = air_loop.supplyFan.get
end
# Get the fan object for this fan
fan_obj_type = fan_component.iddObjectType.valueName.to_s
case fan_obj_type
@@ -2360,11 +2358,11 @@
# @param volume [Double] Equipment storage capacity in gallons.
# @param capacity_per_volume [Double] Equipment capacity per storage capacity in Btu/h/gal.
# @return [Array] returns an array of hashes, one hash per object. Array is empty if no results.
# @example Find all the schedule rules that match the name
# rules = model_find_objects(standards_data['schedules'], 'name' => schedule_name)
- # if rules.size.zero?
+ # if rules.empty?
# OpenStudio.logFree(OpenStudio::Error, 'openstudio.standards.Model', "Cannot find data for schedule: #{schedule_name}, will not be created.")
# return false
# end
def model_find_objects(hash_of_objects, search_criteria, capacity = nil, date = nil, area = nil, num_floors = nil, fan_motor_bhp = nil, volume = nil, capacity_per_volume = nil)
matching_objects = []
@@ -2401,22 +2399,21 @@
matching_objects = matching_objects.reject { |object| !object.key?('minimum_capacity') || !object.key?('maximum_capacity') }
# Skip objects that don't have values specified for minimum_capacity and maximum_capacity
matching_objects = matching_objects.reject { |object| object['minimum_capacity'].nil? || object['maximum_capacity'].nil? }
- # Round up if capacity is an integer
- if capacity == capacity.round
- capacity += (capacity * 0.01)
- end
+ # Convert to a float in case not already
+ capacity = capacity.to_f
+
# Skip objects whose the minimum capacity is below or maximum capacity above the specified capacity
- matching_capacity_objects = matching_objects.reject { |object| capacity.to_f <= object['minimum_capacity'].to_f || capacity.to_f > object['maximum_capacity'].to_f }
+ matching_capacity_objects = matching_objects.reject { |object| capacity <= object['minimum_capacity'].to_f || capacity > object['maximum_capacity'].to_f }
# If no object was found, round the capacity down in case the number fell between the limits in the json file.
- if matching_capacity_objects.size.zero?
+ if matching_capacity_objects.empty?
capacity *= 0.99
# Skip objects whose minimum capacity is below or maximum capacity above the specified capacity
- matching_objects = matching_objects.reject { |object| capacity.to_f <= object['minimum_capacity'].to_f || capacity.to_f > object['maximum_capacity'].to_f }
+ matching_objects = matching_objects.reject { |object| capacity <= object['minimum_capacity'].to_f || capacity > object['maximum_capacity'].to_f }
else
matching_objects = matching_capacity_objects
end
end
@@ -2430,11 +2427,11 @@
# Skip objects whose the minimum volume is below or maximum volume above the specified volume
matching_volume_objects = matching_objects.reject { |object| volume.to_f < object['minimum_storage'].to_f || volume.to_f > object['maximum_storage'].to_f }
# If no object was found, round the volume down in case the number fell between the limits in the json file.
- if matching_volume_objects.size.zero?
+ if matching_volume_objects.empty?
volume *= 0.99
# Skip objects whose minimum volume is below or maximum volume above the specified volume
matching_objects = matching_objects.reject { |object| volume.to_f <= object['minimum_storage'].to_f || volume.to_f >= object['maximum_storage'].to_f }
else
matching_objects = matching_volume_objects
@@ -2451,11 +2448,11 @@
# Skip objects whose the minimum capacity_per_volume is below or maximum capacity_per_volume above the specified capacity_per_volume
matching_capacity_per_volume_objects = matching_objects.reject { |object| capacity_per_volume.to_f <= object['minimum_capacity_per_storage'].to_f || capacity_per_volume.to_f >= object['maximum_capacity_per_storage'].to_f }
# If no object was found, round the volume down in case the number fell between the limits in the json file.
- if matching_capacity_per_volume_objects.size.zero?
+ if matching_capacity_per_volume_objects.empty?
capacity_per_volume *= 0.99
# Skip objects whose minimum capacity_per_volume is below or maximum capacity_per_volume above the specified capacity_per_volume
matching_objects = matching_objects.reject { |object| capacity_per_volume.to_f <= object['minimum_capacity_per_storage'].to_f || capacity_per_volume.to_f >= object['maximum_capacity_per_storage'].to_f }
else
matching_objects = matching_capacity_per_volume_objects
@@ -2475,11 +2472,11 @@
# Filter based on motor type
matching_capacity_objects = matching_capacity_objects.select { |object| object['type'].downcase == search_criteria['type'].downcase } if search_criteria.keys.include?('type')
# If no object was found, round the fan_motor_bhp down in case the number fell between the limits in the json file.
- if matching_capacity_objects.size.zero?
+ if matching_capacity_objects.empty?
fan_motor_bhp *= 0.99
# Skip objects whose minimum capacity is below or maximum capacity above the specified fan_motor_bhp
matching_objects = matching_objects.reject { |object| fan_motor_bhp.to_f <= object['minimum_capacity'].to_f || fan_motor_bhp.to_f > object['maximum_capacity'].to_f }
else
matching_objects = matching_capacity_objects
@@ -2521,11 +2518,11 @@
# Skip objects whose minimum floors is below or maximum floors is above num_floors
matching_objects = matching_objects.reject { |object| num_floors.to_f < object['minimum_floors'].to_f || num_floors.to_f > object['maximum_floors'].to_f }
end
# Check the number of matching objects found
- if matching_objects.size.zero?
+ if matching_objects.empty?
OpenStudio.logFree(OpenStudio::Debug, 'openstudio.standards.Model', "Find objects search criteria returned no results. Search criteria: #{search_criteria}. Called from #{caller(0)[1]}.")
end
return matching_objects
end
@@ -2553,11 +2550,11 @@
# motor_properties = self.model.find_object(motors, search_criteria, capacity: 2.5)
def model_find_object(hash_of_objects, search_criteria, capacity = nil, date = nil, area = nil, num_floors = nil, fan_motor_bhp = nil, volume = nil, capacity_per_volume = nil)
matching_objects = model_find_objects(hash_of_objects, search_criteria, capacity, date, area, num_floors, fan_motor_bhp, volume, capacity_per_volume)
# Check the number of matching objects found
- if matching_objects.size.zero?
+ if matching_objects.empty?
desired_object = nil
OpenStudio.logFree(OpenStudio::Debug, 'openstudio.standards.Model', "Find object search criteria returned no results. Search criteria: #{search_criteria}. Called from #{caller(0)[1]}")
elsif matching_objects.size == 1
desired_object = matching_objects[0]
else
@@ -2582,11 +2579,11 @@
# @param num_floors [Double] capacity of the object in question. If num_floors is supplied,
# the objects will only be returned if the specified num_floors is between the minimum_floors and maximum_floors values.
# @return [Array] returns an array of hashes, one hash per object. Array is empty if no results.
# @example Find all the schedule rules that match the name
# rules = model_find_objects(standards_data['schedules'], 'name' => schedule_name)
- # if rules.size.zero?
+ # if rules.empty?
# OpenStudio.logFree(OpenStudio::Error, 'openstudio.standards.Model', "Cannot find data for schedule: #{schedule_name}, will not be created.")
# return false
# end
def standards_lookup_table_many(table_name:, search_criteria: {}, capacity: nil, date: nil, area: nil, num_floors: nil)
desired_object = nil
@@ -2631,19 +2628,18 @@
matching_objects = matching_objects.reject { |object| !object.key?('minimum_capacity') || !object.key?('maximum_capacity') }
# Skip objects that don't have values specified for minimum_capacity and maximum_capacity
matching_objects = matching_objects.reject { |object| object['minimum_capacity'].nil? || object['maximum_capacity'].nil? }
- # Round up if capacity is an integer
- if capacity == capacity.round
- capacity += (capacity * 0.01)
- end
+ # Convert to a float in case not already
+ capacity = capacity.to_f
+
# Skip objects whose the minimum capacity is below or maximum capacity above the specified capacity
- matching_capacity_objects = matching_objects.reject { |object| capacity.to_f <= object['minimum_capacity'].to_f || capacity.to_f > object['maximum_capacity'].to_f }
+ matching_capacity_objects = matching_objects.reject { |object| capacity <= object['minimum_capacity'].to_f || capacity > object['maximum_capacity'].to_f }
# If no object was found, round the capacity down in case the number fell between the limits in the json file.
- if matching_capacity_objects.size.zero?
+ if matching_capacity_objects.empty?
capacity *= 0.99
search_criteria_matching_objects.each do |object|
# Skip objects that don't have fields for minimum_capacity and maximum_capacity
next if !object.key?('minimum_capacity') || !object.key?('maximum_capacity')
# Skip objects that don't have values specified for minimum_capacity and maximum_capacity
@@ -2698,11 +2694,11 @@
# Skip objects whose minimum floors is below or maximum floors is above num_floors
matching_objects = matching_objects.reject { |object| num_floors.to_f < object['minimum_floors'].to_f || num_floors.to_f > object['maximum_floors'].to_f }
end
# Check the number of matching objects found
- if matching_objects.size.zero?
+ if matching_objects.empty?
OpenStudio.logFree(OpenStudio::Debug, 'openstudio.standards.Model', "Find objects search criteria returned no results. Search criteria: #{search_criteria}. Called from #{caller(0)[1]}.")
end
return matching_objects
end
@@ -2730,11 +2726,11 @@
search_criteria: search_criteria,
capacity: capacity,
date: date)
# Check the number of matching objects found
- if matching_objects.size.zero?
+ if matching_objects.empty?
desired_object = nil
OpenStudio.logFree(OpenStudio::Debug, 'openstudio.standards.Model', "Find object search criteria returned no results. Search criteria: #{search_criteria}. Called from #{caller(0)[1]}")
elsif matching_objects.size == 1
desired_object = matching_objects[0]
else
@@ -2766,11 +2762,11 @@
# OpenStudio::logFree(OpenStudio::Info, 'openstudio.standards.Model', "Adding schedule: #{schedule_name}")
# Find all the schedule rules that match the name
rules = model_find_objects(standards_data['schedules'], 'name' => schedule_name)
- if rules.size.zero?
+ if rules.empty?
OpenStudio.logFree(OpenStudio::Error, 'openstudio.standards.Model', "Cannot find data for schedule: #{schedule_name}, will not be created.")
return model.alwaysOnDiscreteSchedule
end
# Make a schedule ruleset
@@ -2789,28 +2785,43 @@
# Default
if day_types.include?('Default')
day_sch = sch_ruleset.defaultDaySchedule
day_sch.setName("#{schedule_name} Default")
model_add_vals_to_sch(model, day_sch, sch_type, values)
+ if model.version < OpenStudio::VersionString.new('3.8.0')
+ day_sch.setInterpolatetoTimestep(false)
+ else
+ day_sch.setInterpolatetoTimestep('No')
+ end
end
# Winter Design Day
if day_types.include?('WntrDsn')
day_sch = OpenStudio::Model::ScheduleDay.new(model)
sch_ruleset.setWinterDesignDaySchedule(day_sch)
day_sch = sch_ruleset.winterDesignDaySchedule
day_sch.setName("#{schedule_name} Winter Design Day")
model_add_vals_to_sch(model, day_sch, sch_type, values)
+ if model.version < OpenStudio::VersionString.new('3.8.0')
+ day_sch.setInterpolatetoTimestep(false)
+ else
+ day_sch.setInterpolatetoTimestep('No')
+ end
end
# Summer Design Day
if day_types.include?('SmrDsn')
day_sch = OpenStudio::Model::ScheduleDay.new(model)
sch_ruleset.setSummerDesignDaySchedule(day_sch)
day_sch = sch_ruleset.summerDesignDaySchedule
day_sch.setName("#{schedule_name} Summer Design Day")
model_add_vals_to_sch(model, day_sch, sch_type, values)
+ if model.version < OpenStudio::VersionString.new('3.8.0')
+ day_sch.setInterpolatetoTimestep(false)
+ else
+ day_sch.setInterpolatetoTimestep('No')
+ end
end
# Other days (weekdays, weekends, etc)
if day_types.include?('Wknd') ||
day_types.include?('Wkdy') ||
@@ -2825,10 +2836,15 @@
# Make the Rule
sch_rule = OpenStudio::Model::ScheduleRule.new(sch_ruleset)
day_sch = sch_rule.daySchedule
day_sch.setName("#{schedule_name} #{day_types} Day")
model_add_vals_to_sch(model, day_sch, sch_type, values)
+ if model.version < OpenStudio::VersionString.new('3.8.0')
+ day_sch.setInterpolatetoTimestep(false)
+ else
+ day_sch.setInterpolatetoTimestep('No')
+ end
# Set the dates when the rule applies
sch_rule.setStartDate(OpenStudio::Date.new(OpenStudio::MonthOfYear.new(start_date.month.to_i), start_date.day.to_i))
sch_rule.setEndDate(OpenStudio::Date.new(OpenStudio::MonthOfYear.new(end_date.month.to_i), end_date.day.to_i))
@@ -2882,21 +2898,22 @@
u_factor = nil
shgc = nil
vt = nil
material_name.split.each_with_index do |item, i|
prop_value = material_name.split[i + 1].to_f
- if item == 'U'
+ case item
+ when 'U'
unless u_factor.nil?
OpenStudio.logFree(OpenStudio::Warn, 'openstudio.standards.Model', "Multiple U-Factor values have been identified for #{material_name}: previous = #{u_factor}, new = #{prop_value}. Please check the material name. New U-Factor will be used.")
end
u_factor = prop_value
- elsif item == 'SHGC'
+ when 'SHGC'
unless shgc.nil?
OpenStudio.logFree(OpenStudio::Warn, 'openstudio.standards.Model', "Multiple SHGC values have been identified for #{material_name}: previous = #{shgc}, new = #{prop_value}. Please check the material name. New SHGC will be used.")
end
shgc = prop_value
- elsif item == 'VT'
+ when 'VT'
unless vt.nil?
OpenStudio.logFree(OpenStudio::Warn, 'openstudio.standards.Model', "Multiple VT values have been identified for #{material_name}: previous = #{vt}, new = #{prop_value}. Please check the material name. New SHGC will be used.")
end
vt = prop_value
end
@@ -2929,11 +2946,12 @@
end
material_type = data['material_type']
end
material = nil
- if material_type == 'StandardOpaqueMaterial'
+ case material_type
+ when 'StandardOpaqueMaterial'
material = OpenStudio::Model::StandardOpaqueMaterial.new(model)
material.setName(material_name)
material.setRoughness(data['roughness'].to_s)
material.setThickness(OpenStudio.convert(data['thickness'].to_f, 'in', 'm').get)
@@ -2942,41 +2960,41 @@
material.setSpecificHeat(OpenStudio.convert(data['specific_heat'].to_f, 'Btu/lb*R', 'J/kg*K').get)
material.setThermalAbsorptance(data['thermal_absorptance'].to_f)
material.setSolarAbsorptance(data['solar_absorptance'].to_f)
material.setVisibleAbsorptance(data['visible_absorptance'].to_f)
- elsif material_type == 'MasslessOpaqueMaterial'
+ when 'MasslessOpaqueMaterial'
material = OpenStudio::Model::MasslessOpaqueMaterial.new(model)
material.setName(material_name)
material.setThermalResistance(OpenStudio.convert(data['resistance'].to_f, 'hr*ft^2*R/Btu', 'm^2*K/W').get)
material.setThermalConductivity(OpenStudio.convert(data['conductivity'].to_f, 'Btu*in/hr*ft^2*R', 'W/m*K').get)
material.setThermalAbsorptance(data['thermal_absorptance'].to_f)
material.setSolarAbsorptance(data['solar_absorptance'].to_f)
material.setVisibleAbsorptance(data['visible_absorptance'].to_f)
- elsif material_type == 'AirGap'
+ when 'AirGap'
material = OpenStudio::Model::AirGap.new(model)
material.setName(material_name)
material.setThermalResistance(OpenStudio.convert(data['resistance'].to_f, 'hr*ft^2*R/Btu*in', 'm*K/W').get)
- elsif material_type == 'Gas'
+ when 'Gas'
material = OpenStudio::Model::Gas.new(model)
material.setName(material_name)
material.setThickness(OpenStudio.convert(data['thickness'].to_f, 'in', 'm').get)
material.setGasType(data['gas_type'].to_s)
- elsif material_type == 'SimpleGlazing'
+ when 'SimpleGlazing'
material = OpenStudio::Model::SimpleGlazing.new(model)
material.setName(material_name)
material.setUFactor(OpenStudio.convert(u_factor.to_f, 'Btu/hr*ft^2*R', 'W/m^2*K').get)
material.setSolarHeatGainCoefficient(shgc.to_f)
material.setVisibleTransmittance(vt.to_f)
- elsif material_type == 'StandardGlazing'
+ when 'StandardGlazing'
material = OpenStudio::Model::StandardGlazing.new(model)
material.setName(material_name)
material.setOpticalDataType(data['optical_data_type'].to_s)
material.setThickness(OpenStudio.convert(data['thickness'].to_f, 'in', 'm').get)
@@ -3849,57 +3867,52 @@
# @param model [OpenStudio::Model::Model] OpenStudio model object
# @param building_type [String] the building type
# @return [Double] floor area (m^2) of prototype building for building type passed in.
# Returns nil if unexpected building type
def model_find_prototype_floor_area(model, building_type)
- if building_type == 'FullServiceRestaurant' # 5502 ft^2
+ case building_type
+ when 'FullServiceRestaurant' # 5502 ft^2
result = 511
- elsif building_type == 'Hospital' # 241,410 ft^2 (including basement)
+ when 'Hospital' # 241,410 ft^2 (including basement)
result = 22_422
- elsif building_type == 'LargeHotel' # 122,132 ft^2
+ when 'LargeHotel' # 122,132 ft^2
result = 11_345
- elsif building_type == 'LargeOffice' # 498,600 ft^2
+ when 'LargeOffice', 'LargeOfficeDetailed' # 498,600 ft^2
result = 46_320
- elsif building_type == 'MediumOffice' # 53,600 ft^2
+ when 'MediumOffice', 'MediumOfficeDetailed' # 53,600 ft^2
result = 4982
- elsif building_type == 'LargeOfficeDetailed' # 498,600 ft^2
- result = 46_320
- elsif building_type == 'MediumOfficeDetailed' # 53,600 ft^2
- result = 4982
- elsif building_type == 'MidriseApartment' # 33,700 ft^2
+ when 'MidriseApartment' # 33,700 ft^2
result = 3135
- elsif building_type == 'Office'
+ when 'Office'
result = nil
# @todo there shouldn't be a prototype building for this
OpenStudio.logFree(OpenStudio::Error, 'openstudio.standards.Model', 'Measures calling this should choose between SmallOffice, MediumOffice, and LargeOffice')
- elsif building_type == 'Outpatient' # 40.950 ft^2
+ when 'Outpatient' # 40.950 ft^2
result = 3804
- elsif building_type == 'PrimarySchool' # 73,960 ft^2
+ when 'PrimarySchool' # 73,960 ft^2
result = 6871
- elsif building_type == 'QuickServiceRestaurant' # 2500 ft^2
+ when 'QuickServiceRestaurant' # 2500 ft^2
result = 232
- elsif building_type == 'Retail' # 24,695 ft^2
+ when 'Retail' # 24,695 ft^2
result = 2294
- elsif building_type == 'SecondarySchool' # 210,900 ft^2
+ when 'SecondarySchool' # 210,900 ft^2
result = 19_592
- elsif building_type == 'SmallHotel' # 43,200 ft^2
+ when 'SmallHotel' # 43,200 ft^2
result = 4014
- elsif building_type == 'SmallOffice' # 5500 ft^2
+ when 'SmallOffice', 'SmallOfficeDetailed' # 5500 ft^2
result = 511
- elsif building_type == 'SmallOfficeDetailed' # 5500 ft^2
- result = 511
- elsif building_type == 'StripMall' # 22,500 ft^2
+ when 'StripMall' # 22,500 ft^2
result = 2090
- elsif building_type == 'SuperMarket' # 45,002 ft2 (from legacy reference idf file)
+ when 'SuperMarket' # 45,002 ft2 (from legacy reference idf file)
result = 4181
- elsif building_type == 'Warehouse' # 49,495 ft^2 (legacy ref shows 52,045, but I wil calc using 49,495)
+ when 'Warehouse' # 49,495 ft^2 (legacy ref shows 52,045, but I wil calc using 49,495)
result = 4595
- elsif building_type == 'SmallDataCenterLowITE' || building_type == 'SmallDataCenterHighITE' # 600 ft^2
+ when 'SmallDataCenterLowITE', 'SmallDataCenterHighITE' # 600 ft^2
result = 56
- elsif building_type == 'LargeDataCenterLowITE' || building_type == 'LargeDataCenterHighITE' # 6000 ft^2
+ when 'LargeDataCenterLowITE', 'LargeDataCenterHighITE' # 6000 ft^2
result = 557
- elsif building_type == 'Laboratory' # 90000 ft^2
+ when 'Laboratory' # 90000 ft^2
result = 8361
else
OpenStudio.logFree(OpenStudio::Error, 'openstudio.standards.Model', "Didn't find expected building type. As a result can't determine floor prototype floor area")
result = nil
end
@@ -4195,11 +4208,11 @@
surfaces_to_modify.sort.each do |surf|
prev_created_consts = planar_surface_apply_standard_construction(surf, climate_zone, prev_created_consts, wwr_building_type, wwr_info, surface_category[surf])
end
# List the unique array of constructions
- if prev_created_consts.size.zero?
+ if prev_created_consts.empty?
OpenStudio.logFree(OpenStudio::Warn, 'openstudio.standards.Model', 'None of the constructions in your proposed model have both Intended Surface Type and Standards Construction Type')
else
prev_created_consts.each do |surf_type, construction|
OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.Model', "For #{surf_type.join(' ')}, applied #{construction.name}.")
end
@@ -4309,11 +4322,13 @@
space.additionalProperties.setFeature('building_type_for_wwr', std_spc_type)
end
# Initialize intermediate variables if space type hasn't
# been encountered yet
- if !bat_win_wall_info.key?(std_spc_type)
+ if bat_win_wall_info.key?(std_spc_type)
+ bat = bat_win_wall_info[std_spc_type]
+ else
bat_win_wall_info[std_spc_type] = {}
bat = bat_win_wall_info[std_spc_type]
# Loop through all spaces in the model, and
# per the PNNL PRM Reference Manual, find the areas
@@ -4331,12 +4346,10 @@
bat.store('sh_fene_only_wall_m2', 0.001)
bat.store('sh_wind_m2', 0)
bat.store('sh_plenum_wall_m2', 0.001)
bat.store('total_wall_m2', 0.001)
bat.store('total_plenum_m2', 0.001)
- else
- bat = bat_win_wall_info[std_spc_type]
end
# Loop through all surfaces in this space
wall_area_m2 = 0
wind_area_m2 = 0
@@ -4533,11 +4546,11 @@
if red < 0.0
# surface with fenestration to its maximum but adjusted by door areas when need to add windows in surfaces no fenestration
# turn negative to positive to get the correct adjustment factor.
red = -red
surface_wwr = OpenstudioStandards::Geometry.surface_get_window_to_wall_ratio(surface)
- residual_fene += (0.9 - red * surface_wwr) * surface.grossArea
+ residual_fene += (0.9 - (red * surface_wwr)) * surface.grossArea
end
surface_adjust_fenestration_in_a_surface(surface, red, model)
end
if residual_fene > 0.0
@@ -4725,13 +4738,11 @@
end
# Air loops
model.getAirLoopHVACs.each do |air_loop|
# Don't remove airloops representing non-mechanically cooled systems
- if !air_loop.additionalProperties.hasFeature('non_mechanically_cooled')
- air_loop.remove
- else
+ if air_loop.additionalProperties.hasFeature('non_mechanically_cooled')
# Remove heating coil on
air_loop.supplyComponents.each do |supply_comp|
# Remove standalone heating coils
if supply_comp.iddObjectType.valueName.to_s.include?('OS_Coil_Heating')
supply_comp.remove
@@ -4744,10 +4755,12 @@
unitary_system.resetCoolingCoil
htg_coil.remove
end
end
end
+ else
+ air_loop.remove
end
end
# Zone equipment
model.getThermalZones.sort.each do |zone|
@@ -4840,44 +4853,33 @@
# get building type
building_data = model_get_building_properties(model)
building_type = building_data['building_type']
result = []
- if building_type == 'FullServiceRestaurant'
+ case building_type
+ when 'FullServiceRestaurant'
result << { units: 'meal', block: nil, max_hourly: 1.5, max_daily: 11.0, avg_day_unit: 2.4 }
- elsif building_type == 'Hospital'
+ when 'Hospital', 'Outpatient', 'Retail', 'StripMall', 'SuperMarket', 'Warehouse', 'SmallDataCenterLowITE', 'SmallDataCenterHighITE', 'LargeDataCenterLowITE', 'LargeDataCenterHighITE', 'Laboratory'
OpenStudio.logFree(OpenStudio::Error, 'openstudio.standards.Model', "No SWH rules of thumbs for #{building_type}.")
- elsif ['LargeHotel', 'SmallHotel'].include? building_type
+ when 'LargeHotel', 'SmallHotel'
result << { units: 'unit', block: 20, max_hourly: 6.0, max_daily: 35.0, avg_day_unit: 24.0 }
result << { units: 'unit', block: 60, max_hourly: 5.0, max_daily: 25.0, avg_day_unit: 14.0 }
result << { units: 'unit', block: 100, max_hourly: 4.0, max_daily: 15.0, avg_day_unit: 10.0 }
- elsif building_type == 'MidriseApartment'
+ when 'MidriseApartment'
result << { units: 'unit', block: 20, max_hourly: 12.0, max_daily: 80.0, avg_day_unit: 42.0 }
result << { units: 'unit', block: 50, max_hourly: 10.0, max_daily: 73.0, avg_day_unit: 40.0 }
result << { units: 'unit', block: 75, max_hourly: 8.5, max_daily: 66.0, avg_day_unit: 38.0 }
result << { units: 'unit', block: 100, max_hourly: 7.0, max_daily: 60.0, avg_day_unit: 37.0 }
result << { units: 'unit', block: 200, max_hourly: 5.0, max_daily: 50.0, avg_day_unit: 35.0 }
- elsif ['Office', 'LargeOffice', 'MediumOffice', 'SmallOffice', 'LargeOfficeDetailed', 'MediumOfficeDetailed', 'SmallOfficeDetailed'].include? building_type
+ when 'Office', 'LargeOffice', 'MediumOffice', 'SmallOffice', 'LargeOfficeDetailed', 'MediumOfficeDetailed', 'SmallOfficeDetailed'
result << { units: 'person', block: nil, max_hourly: 0.4, max_daily: 2.0, avg_day_unit: 1.0 }
- elsif building_type == 'Outpatient'
- OpenStudio.logFree(OpenStudio::Error, 'openstudio.standards.Model', "No SWH rules of thumbs for #{building_type}.")
- elsif building_type == 'PrimarySchool'
+ when 'PrimarySchool'
result << { units: 'student', block: nil, max_hourly: 0.6, max_daily: 1.5, avg_day_unit: 0.6 }
- elsif building_type == 'QuickServiceRestaurant'
+ when 'QuickServiceRestaurant'
result << { units: 'meal', block: nil, max_hourly: 0.7, max_daily: 6.0, avg_day_unit: 0.7 }
- elsif building_type == 'Retail'
- OpenStudio.logFree(OpenStudio::Error, 'openstudio.standards.Model', "No SWH rules of thumbs for #{building_type}.")
- elsif building_type == 'SecondarySchool'
+ when 'SecondarySchool'
result << { units: 'student', block: nil, max_hourly: 1.0, max_daily: 3.6, avg_day_unit: 1.8 }
- elsif building_type == 'StripMall'
- OpenStudio.logFree(OpenStudio::Error, 'openstudio.standards.Model', "No SWH rules of thumbs for #{building_type}.")
- elsif building_type == 'SuperMarket'
- OpenStudio.logFree(OpenStudio::Error, 'openstudio.standards.Model', "No SWH rules of thumbs for #{building_type}.")
- elsif building_type == 'Warehouse'
- OpenStudio.logFree(OpenStudio::Error, 'openstudio.standards.Model', "No SWH rules of thumbs for #{building_type}.")
- elsif ['SmallDataCenterLowITE', 'SmallDataCenterHighITE', 'LargeDataCenterLowITE', 'LargeDataCenterHighITE', 'Laboratory'].include? building_type
- OpenStudio.logFree(OpenStudio::Error, 'openstudio.standards.Model', "No SWH rules of thumbs for #{building_type}.")
else
OpenStudio.logFree(OpenStudio::Error, 'openstudio.standards.Model', "Didn't find expected building type. As a result can't determine hot water demand recommendations")
end
return result
@@ -4915,17 +4917,17 @@
# get climate zone value
climate_zone = OpenstudioStandards::Weather.model_get_climate_zone(model)
internal_loads = {}
- internal_loads['mech_vent_cfm'] = units_per_bldg * (0.01 * conditioned_floor_area + 7.5 * (bedrooms_per_unit + 1.0))
+ internal_loads['mech_vent_cfm'] = units_per_bldg * ((0.01 * conditioned_floor_area) + (7.5 * (bedrooms_per_unit + 1.0)))
internal_loads['infiltration_ach'] = if ['1A', '1B', '2A', '2B'].include? climate_zone_value
5.0
else
3.0
end
- internal_loads['igain_btu_per_day'] = units_per_bldg * (17_900.0 + 23.8 * conditioned_floor_area + 4104.0 * bedrooms_per_unit)
+ internal_loads['igain_btu_per_day'] = units_per_bldg * (17_900.0 + (23.8 * conditioned_floor_area) + (4104.0 * bedrooms_per_unit))
internal_loads['internal_mass_lbs'] = total_floor_area * 8.0
return internal_loads
end
@@ -4940,59 +4942,60 @@
climate_zone = climate_zone.gsub('ClimateZone ', 'CZ')
if climate_zone == 'CZ1-8'
climate_zone = ''
end
- if building_type == 'FullServiceRestaurant'
+ case building_type
+ when 'FullServiceRestaurant'
building_type = 'FullSrvRest'
- elsif building_type == 'Hospital'
+ when 'Hospital'
building_type = 'Hospital'
- elsif building_type == 'LargeHotel'
+ when 'LargeHotel'
building_type = 'LrgHotel'
- elsif building_type == 'LargeOffice'
+ when 'LargeOffice'
building_type = 'LrgOffice'
- elsif building_type == 'MediumOffice'
+ when 'MediumOffice'
building_type = 'MedOffice'
- elsif building_type == 'MidriseApartment'
+ when 'MidriseApartment'
building_type = 'MidApt'
- elsif building_type == 'HighriseApartment'
+ when 'HighriseApartment'
building_type = 'HighApt'
- elsif building_type == 'Office'
+ when 'Office'
building_type = 'Office'
- elsif building_type == 'Outpatient'
+ when 'Outpatient'
building_type = 'Outpatient'
- elsif building_type == 'PrimarySchool'
+ when 'PrimarySchool'
building_type = 'PriSchl'
- elsif building_type == 'QuickServiceRestaurant'
+ when 'QuickServiceRestaurant'
building_type = 'QckSrvRest'
- elsif building_type == 'Retail'
+ when 'Retail'
building_type = 'Retail'
- elsif building_type == 'SecondarySchool'
+ when 'SecondarySchool'
building_type = 'SecSchl'
- elsif building_type == 'SmallHotel'
+ when 'SmallHotel'
building_type = 'SmHotel'
- elsif building_type == 'SmallOffice'
+ when 'SmallOffice'
building_type = 'SmOffice'
- elsif building_type == 'StripMall'
+ when 'StripMall'
building_type = 'StMall'
- elsif building_type == 'SuperMarket'
+ when 'SuperMarket'
building_type = 'SpMarket'
- elsif building_type == 'Warehouse'
+ when 'Warehouse'
building_type = 'Warehouse'
- elsif building_type == 'SmallDataCenterLowITE'
+ when 'SmallDataCenterLowITE'
building_type = 'SmDCLowITE'
- elsif building_type == 'SmallDataCenterHighITE'
+ when 'SmallDataCenterHighITE'
building_type = 'SmDCHighITE'
- elsif building_type == 'LargeDataCenterLowITE'
+ when 'LargeDataCenterLowITE'
building_type = 'LrgDCLowITE'
- elsif building_type == 'LargeDataCenterHighITE'
+ when 'LargeDataCenterHighITE'
building_type = 'LrgDCHighITE'
- elsif building_type == 'Laboratory'
+ when 'Laboratory'
building_type = 'Laboratory'
- elsif building_type == 'TallBuilding'
+ when 'TallBuilding'
building_type = 'TallBldg'
- elsif building_type == 'SuperTallBuilding'
+ when 'SuperTallBuilding'
building_type = 'SpTallBldg'
end
parts = [template]
@@ -5028,11 +5031,11 @@
possible_climate_zone_sets << climate_zone_set['name']
end
end
# Check the results
- if possible_climate_zone_sets.size.zero?
+ if possible_climate_zone_sets.empty?
OpenStudio.logFree(OpenStudio::Error, 'openstudio.standards.Model', "Cannot find a climate zone set containing #{climate_zone}. Make sure to use ASHRAE standards with ASHRAE climate zones and DEER or CA Title 24 standards with CEC climate zones.")
elsif possible_climate_zone_sets.size > 2
OpenStudio.logFree(OpenStudio::Error, 'openstudio.standards.Model', "Found more than 2 climate zone sets containing #{climate_zone}; will return last matching climate zone set.")
end
@@ -5281,21 +5284,19 @@
avg_unit_size = OpenStudio.convert(354.2, 'ft^2', 'm^2').get # calculated from prototype
num_units = floor_area / avg_unit_size
end
# determine number of beds
- if stds_bldg_type == 'Hospital' && ['PatRoom', 'ICU_PatRm', 'ICU_Open'].include?(stds_space_type)
+ if ((stds_bldg_type == 'Hospital') && ['PatRoom', 'ICU_PatRm', 'ICU_Open'].include?(stds_space_type)) ||
+ ((stds_bldg_type == 'Hsp') && ['PatientRoom', 'HspSurgOutptLab', 'HspNursing'].include?(stds_space_type))
num_beds = num_people
- elsif stds_bldg_type == 'Hsp' && ['PatientRoom', 'HspSurgOutptLab', 'HspNursing'].include?(stds_space_type)
- num_beds = num_people
end
# determine number of students
- if ['PrimarySchool', 'SecondarySchool'].include?(stds_bldg_type) && stds_space_type == 'Classroom'
+ if ['PrimarySchool', 'SecondarySchool', 'EPr', 'ESe', 'ERC', 'EUn', 'ECC'].include?(stds_bldg_type) &&
+ (stds_space_type == 'Classroom')
num_students += num_people * ((typical_class_size - 1.0) / typical_class_size)
- elsif ['EPr', 'ESe', 'ERC', 'EUn', 'ECC'].include?(stds_bldg_type) && stds_space_type == 'Classroom'
- num_students += num_people * ((typical_class_size - 1.0) / typical_class_size)
end
space_type_hash[space_type] = {}
space_type_hash[space_type][:stds_bldg_type] = stds_bldg_type
space_type_hash[space_type][:stds_space_type] = stds_space_type
@@ -5460,14 +5461,15 @@
# @param model [OpenStudio::Model::Model] OpenStudio model object
# @return [String] the ventilation method, either Sum or Maximum
def model_ventilation_method(model)
building_data = model_get_building_properties(model)
building_type = building_data['building_type']
- if building_type != 'Laboratory' # Laboratory has multiple criteria on ventilation, pick the greatest
- ventilation_method = 'Sum'
- else
+ if building_type == 'Laboratory'
+ # Laboratory has multiple criteria on ventilation, pick the greatest
ventilation_method = 'Maximum'
+ else
+ ventilation_method = 'Sum'
end
return ventilation_method
end
@@ -5953,27 +5955,25 @@
# Determine return configuration
if (heating_equipment_type == 'ZoneHVACComponent') && (cooling_equipment_type == 'ZoneHVACComponent')
return_air_type = 'ducted_return_or_direct_to_unit'
else
# Check heating air loop first
- unless heating_equipment.nil?
- if heating_equipment.to_StraightComponent.is_initialized
- air_loop = heating_equipment.to_StraightComponent.get.airLoopHVAC.get
- return_plenum = air_loop_hvac_return_air_plenum(air_loop)
- return_air_type = return_plenum.nil? ? 'ducted_return_or_direct_to_unit' : 'return_plenum'
- return_plenum = return_plenum.nil? ? nil : return_plenum.name.to_s
- end
+ if !heating_equipment.nil? && heating_equipment.to_StraightComponent.is_initialized
+ air_loop = heating_equipment.to_StraightComponent.get.airLoopHVAC.get
+ return_plenum = air_loop_hvac_return_air_plenum(air_loop)
+ return_air_type = return_plenum.nil? ? 'ducted_return_or_direct_to_unit' : 'return_plenum'
+ return_plenum = return_plenum.nil? ? nil : return_plenum.name.to_s
end
# Check cooling air loop second; Assume that return air plenum is the dominant case
- unless cooling_equipment.nil?
- if (return_air_type != 'return_plenum') && cooling_equipment.to_StraightComponent.is_initialized
- air_loop = cooling_equipment.to_StraightComponent.get.airLoopHVAC.get
- return_plenum = air_loop_hvac_return_air_plenum(air_loop)
- return_air_type = return_plenum.nil? ? 'ducted_return_or_direct_to_unit' : 'return_plenum'
- return_plenum = return_plenum.nil? ? nil : return_plenum.name.to_s
- end
+ if !cooling_equipment.nil? &&
+ (return_air_type != 'return_plenum') &&
+ cooling_equipment.to_StraightComponent.is_initialized
+ air_loop = cooling_equipment.to_StraightComponent.get.airLoopHVAC.get
+ return_plenum = air_loop_hvac_return_air_plenum(air_loop)
+ return_air_type = return_plenum.nil? ? 'ducted_return_or_direct_to_unit' : 'return_plenum'
+ return_plenum = return_plenum.nil? ? nil : return_plenum.name.to_s
end
end
# Catch all
if return_air_type.nil?
@@ -6042,10 +6042,10 @@
if zone_return_air_type[return_type] > return_air_types_score
return_air_type = return_type
return_air_types_score = zone_return_air_type[return_type]
end
if return_air_type == 'return_plenum'
- zone_return_air_type['plenum'].keys.each do |p|
+ zone_return_air_type['plenum'].each_key do |p|
if zone_return_air_type['plenum'][p] > plenum_score
plenum = p
plenum_score = zone_return_air_type['plenum'][p]
end
end