openstudio-standards 0.2.17.rc1 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/data/standards/OpenStudio_Standards-ashrae_90_1.xlsx +0 -0
  3. data/data/standards/openstudio_standards_duplicates_log.csv +5 -0
  4. data/lib/openstudio-standards/btap/btap_result.rb +138 -138
  5. data/lib/openstudio-standards/btap/economics.rb +58 -53
  6. data/lib/openstudio-standards/btap/envelope.rb +1 -1
  7. data/lib/openstudio-standards/btap/fileio.rb +12 -12
  8. data/lib/openstudio-standards/btap/measures.rb +63 -59
  9. data/lib/openstudio-standards/btap/vintagizer.rb +1 -1
  10. data/lib/openstudio-standards/prototypes/common/objects/Prototype.Model.exterior_lights.rb +7 -7
  11. data/lib/openstudio-standards/prototypes/common/objects/Prototype.Model.rb +5 -1
  12. data/lib/openstudio-standards/prototypes/common/objects/Prototype.ServiceWaterHeating.rb +8 -0
  13. data/lib/openstudio-standards/prototypes/common/objects/Prototype.SizingSystem.rb +9 -3
  14. data/lib/openstudio-standards/prototypes/common/objects/Prototype.hvac_systems.rb +53 -23
  15. data/lib/openstudio-standards/standards/Standards.AirLoopHVAC.rb +15 -1
  16. data/lib/openstudio-standards/standards/Standards.Construction.rb +1 -1
  17. data/lib/openstudio-standards/standards/Standards.Model.rb +18 -18
  18. data/lib/openstudio-standards/standards/Standards.PlanarSurface.rb +1 -1
  19. data/lib/openstudio-standards/standards/Standards.ThermalZone.rb +1 -1
  20. data/lib/openstudio-standards/standards/Standards.WaterHeaterMixed.rb +5 -5
  21. data/lib/openstudio-standards/standards/Standards.ZoneHVACComponent.rb +3 -2
  22. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.AirLoopHVAC.rb +43 -40
  23. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.ZoneHVACComponent.rb +2 -1
  24. data/lib/openstudio-standards/standards/ashrae_90_1/data/ashrae_90_1.entryways.json +19 -8
  25. data/lib/openstudio-standards/standards/ashrae_90_1/data/ashrae_90_1.parking.json +13 -4
  26. data/lib/openstudio-standards/standards/ashrae_90_1/doe_ref_1980_2004/doe_ref_1980_2004.AirLoopHVAC.rb +11 -0
  27. data/lib/openstudio-standards/standards/ashrae_90_1/doe_ref_pre_1980/doe_ref_pre_1980.AirLoopHVAC.rb +11 -0
  28. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.AirLoopHVAC.rb +1 -1
  29. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.Model.rb +9 -9
  30. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.PlanarSurface.rb +1 -1
  31. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.PlantLoop.rb +5 -1
  32. data/lib/openstudio-standards/standards/necb/BTAPPRE1980/hvac_system_6.rb +5 -1
  33. data/lib/openstudio-standards/standards/necb/ECMS/hvac_systems.rb +8 -4
  34. data/lib/openstudio-standards/standards/necb/ECMS/nv.rb +8 -2
  35. data/lib/openstudio-standards/standards/necb/NECB2011/hvac_systems.rb +7 -3
  36. data/lib/openstudio-standards/standards/necb/NECB2011/qaqc/necb_qaqc.rb +4 -4
  37. data/lib/openstudio-standards/standards/necb/NECB2011/service_water_heating.rb +1 -1
  38. data/lib/openstudio-standards/standards/necb/NECB2020/service_water_heating.rb +1 -1
  39. data/lib/openstudio-standards/version.rb +1 -1
  40. data/lib/openstudio-standards/weather/Weather.Model.rb +5 -0
  41. metadata +4 -2
@@ -24,28 +24,28 @@ require "#{File.dirname(__FILE__)}/btap"
24
24
 
25
25
  class OSMArg
26
26
  ARGUMENT_TYPES = [
27
- "BOOL",
28
- "STRING",
29
- "INTEGER",
30
- "FLOAT",
27
+ "BOOL",
28
+ "STRING",
29
+ "INTEGER",
30
+ "FLOAT",
31
31
  "STRINGCHOICE",
32
- "WSCHOICE"
32
+ "WSCHOICE"
33
33
  ]
34
-
35
-
36
-
37
- attr_accessor :runner,
38
- :variable_name,
34
+
35
+
36
+
37
+ attr_accessor :runner,
38
+ :variable_name,
39
39
  :type,
40
- :required,
40
+ :required,
41
41
  :model_dependant,
42
- :display_name,
43
- :default_value,
44
- :min_value,
45
- :max_value,
46
- :string_choice_array,
42
+ :display_name,
43
+ :default_value,
44
+ :min_value,
45
+ :max_value,
46
+ :string_choice_array,
47
47
  :os_object_type
48
-
48
+
49
49
  def self.bool( variable_name,display_name,required,default_value )
50
50
  raise "#{default_value} defaut value is not a bool." unless default_value.is_a?(Bool)
51
51
  default_value.respond_to?(:to_s)
@@ -53,47 +53,47 @@ class OSMArg
53
53
  arg.default_value = default_value
54
54
  return arg
55
55
  end
56
-
56
+
57
57
  def self.string( variable_name,display_name,required,default_value )
58
58
  raise "#{default_value} defaut value is not a string." unless default_value.respond_to?(:to_s)
59
59
  arg = OSMArg.new( "STRING", variable_name, display_name, required)
60
60
  arg.default_value = default_value
61
61
  return arg
62
62
  end
63
-
63
+
64
64
  def self.integer( variable_name,display_name,required,default_value,min_value,max_value )
65
65
  raise "#{default_value} defaut value is not a integer." unless default_value.respond_to?(:to_i)
66
66
  arg = OSMArg.new( "INTEGER", variable_name, display_name, required)
67
67
  arg.default_value = default_value
68
68
  arg.min_value = min_value
69
69
  arg.max_value = max_value
70
- return arg
70
+ return arg
71
71
  end
72
-
72
+
73
73
  def self.float( variable_name, display_name, required,default_value,min_value, max_value )
74
74
  raise "#{default_value} defaut value is not a float." unless default_value.respond_to?(:to_f)
75
75
  arg = OSMArg.new( "INTEGER", variable_name, display_name, required)
76
76
  arg.default_value = default_value
77
77
  arg.min_value = min_value
78
78
  arg.max_value = max_value
79
- return arg
79
+ return arg
80
80
  end
81
-
81
+
82
82
  def self.choice(variable_name,display_name,required,default_value,string_choice_array)
83
- raise "#{default_value} defaut value is not an array." unless default_value.is_a?(Array)
83
+ raise "#{default_value} defaut value is not an array." unless default_value.is_a?(Array)
84
84
  arg = OSMArg.new( "STRINGCHOICE", variable_name, display_name, required)
85
85
  arg.default_value = default_value
86
86
  arg.string_choice_array = string_choice_array
87
87
  return arg
88
88
  end
89
-
89
+
90
90
  def self.wschoice( variable_name, display_name, required, default_value, os_object_type)
91
91
  arg = OSMArg.new( "WSCHOICE", variable_name, display_name, required )
92
92
  arg.default_value = default_value
93
93
  arg.os_object_type = os_object_type
94
- return arg
94
+ return arg
95
95
  end
96
-
96
+
97
97
  def initialize( type, variable_name, display_name, required )
98
98
  self.type = type
99
99
  self.variable_name = variable_name
@@ -106,9 +106,9 @@ class OSMArg
106
106
  self.model_dependant = false
107
107
  end
108
108
  return self
109
- end
109
+ end
110
110
  end
111
-
111
+
112
112
 
113
113
 
114
114
 
@@ -116,10 +116,10 @@ end
116
116
  module BTAP
117
117
  module Measures
118
118
  module OSMeasures
119
-
120
-
121
-
122
-
119
+
120
+
121
+
122
+
123
123
  class BTAPModelUserScript < OpenStudio::Ruleset::ModelUserScript
124
124
  #if and E+ measure replace OpenStudio::Ruleset::ModelUserScript with OpenStudio::Ruleset::WorkspaceUserScript
125
125
  #Array containing information of all inputs required by measure.
@@ -134,8 +134,8 @@ module BTAP
134
134
  "BTAPModelUserScript"
135
135
  OSMArgument.new
136
136
  end
137
-
138
- #this method will output the ruby macro to perform the change.
137
+
138
+ #this method will output the ruby macro to perform the change.
139
139
  def generate_ruby_macro(model,runner)
140
140
  if @file == nil or @file == ""
141
141
  @file = "Enter_Path_To_#{self.class.name}_measure.rb_File!"
@@ -190,8 +190,8 @@ module BTAP
190
190
  if not runner.validateUserArguments(self.arguments(model),user_arguments)
191
191
  return false
192
192
  end
193
-
194
- #Set argument to instance variables.
193
+
194
+ #Set argument to instance variables.
195
195
  self.argument_getter(model, runner,user_arguments)
196
196
  #will run the childs method measure_code
197
197
  result = self.measure_code(model,runner)
@@ -201,7 +201,7 @@ module BTAP
201
201
 
202
202
  def argument_setter(model,args)
203
203
  #***boilerplate code starts. Do not edit...
204
-
204
+
205
205
 
206
206
  #iterate through array of hashes and make arguments based on type and set
207
207
  # max and min values where applicable.
@@ -247,7 +247,7 @@ module BTAP
247
247
  unless @argument_array == nil
248
248
  @argument_array.each do |row|
249
249
  name = row.variable_name
250
-
250
+
251
251
  case row.type
252
252
  when "BOOL"
253
253
  value = runner.getBoolArgumentValue(name, user_arguments)
@@ -269,7 +269,7 @@ module BTAP
269
269
  value = runner.getDoubleArgumentValue(name, user_arguments)
270
270
  instance_variable_set("@#{name}",value)
271
271
  @arg_table << [name,value]
272
-
272
+
273
273
  if ( not row.min_value.nil? and instance_variable_get("@#{name}") < row.min_value ) or ( not row.max_value.nil? and instance_variable_get("@#{name}") > row.max_value )
274
274
  runner.registerError("#{row.display_name} must be greater than or equal to #{row.min_value} and less than or equal to #{row.max_value}. You entered #{instance_variable_get("@#{name}")}.")
275
275
  return false
@@ -288,10 +288,10 @@ module BTAP
288
288
  end #end do
289
289
  end
290
290
  return @arg_table
291
- end
292
-
291
+ end
292
+
293
293
  end
294
- #Measure Template simplified.
294
+ #Measure Template simplified.
295
295
  class TemplateModelMeasure < BTAPModelUserScript
296
296
 
297
297
  def name
@@ -391,14 +391,14 @@ module BTAP
391
391
  def run(model, runner, user_arguments)
392
392
  #run the super
393
393
  parent_method_is_true = super(model, runner, user_arguments)
394
-
395
-
394
+
395
+
396
396
  ###############
397
-
398
- #Set Archetype name in runner.
397
+
398
+ #Set Archetype name in runner.
399
399
  runner.registerValue('archetype_name',@archetype_name)
400
-
401
- #Set path to OSM files.
400
+
401
+ #Set path to OSM files.
402
402
  alternative_model_path = OpenStudio::Path.new("#{File.dirname(__FILE__)}/#{@archetype_name}.osm")
403
403
  #load model and test.
404
404
  translator = OpenStudio::OSVersion::VersionTranslator.new
@@ -561,7 +561,7 @@ module BTAP
561
561
  model = self.load_base_model_building()
562
562
  self.set_weather_file(model)
563
563
  self.set_hourly_output(model)
564
-
564
+
565
565
  model,log = self.apply_ecms(model,@csv_data)
566
566
  BTAP::FileIO::save_osm( model, "#{output_folder}/#{BTAP::FileIO::get_name(model)}.osm") unless output_folder.nil?
567
567
  File.open("#{output_folder}/#{BTAP::FileIO::get_name(model)}.log", 'w') { |file| file.write(log) } unless output_folder.nil?
@@ -621,7 +621,7 @@ module BTAP
621
621
  "cost_per_building"
622
622
  ]
623
623
  self.set_instance_variables( measure_values )
624
-
624
+
625
625
  #cost per building and building area
626
626
  building = model.building.get
627
627
  raise ("you did not enter a cost for measure #{@measure_id}. All measures must have a cost of at least 0.0 . Please add a cost_per_building field.") if @cost_per_building.nil?
@@ -753,7 +753,7 @@ module BTAP
753
753
  @total_building_construction_set_cost
754
754
  )
755
755
 
756
- #Give adiabatic surfaces a construction. Does not matter what. This is a bug in Openstudio that leave these surfaces unassigned by the default construction set.
756
+ #Give adiabatic surfaces a construction. Does not matter what. This is a bug in OpenStudio that leave these surfaces unassigned by the default construction set.
757
757
  all_adiabatic_surfaces = BTAP::Geometry::Surfaces::filter_by_boundary_condition(model.getSurfaces, "Adiabatic")
758
758
  unless all_adiabatic_surfaces.empty?
759
759
  BTAP::Geometry::Surfaces::set_surfaces_construction( all_adiabatic_surfaces, model.building.get.defaultConstructionSet.get.defaultInteriorSurfaceConstructions.get.wallConstruction.get)
@@ -772,7 +772,7 @@ module BTAP
772
772
  "infiltration_flow_per_exterior_area",
773
773
  "infiltration_air_changes_per_hour"
774
774
  ]
775
-
775
+
776
776
  #Set all the above instance variables to the @csv_data values or, if not set or == 'na', to nil.
777
777
  self.set_instance_variables(measure_values)
778
778
 
@@ -811,7 +811,7 @@ module BTAP
811
811
  fan.setMotorEfficiency( @fan_motor_eff ) unless @fan_motor_eff.nil?
812
812
  log << fan.name.get.to_s << ",#{fan.fanEfficiency},#{fan.motorEfficiency}\n"
813
813
  end
814
-
814
+
815
815
  end
816
816
 
817
817
  case @fan_volume_type
@@ -975,7 +975,9 @@ module BTAP
975
975
  model.getCoilCoolingDXSingleSpeeds.sort.each do |cooling_coil|
976
976
  cooling_coil.setRatedCOP( OpenStudio::OptionalDouble.new( @cop ) ) unless @cop.nil?
977
977
  cop = "NA"
978
- cop = cooling_coil.ratedCOP.get unless cooling_coil.ratedCOP.empty?
978
+ # Prior to 3.5.0, it was an optional double, now it's a double
979
+ cop_ = OpenStudio::OptionalDouble.new(cooling_coil.ratedCOP)
980
+ cop = cop_.get unless cop_.empty?
979
981
  log << cooling_coil.name.get.to_s << ",#{cop}\n"
980
982
 
981
983
  end
@@ -987,9 +989,11 @@ module BTAP
987
989
  cooling_coil.setRatedHighSpeedCOP( @cop ) unless @cop.nil?
988
990
  cooling_coil.setRatedLowSpeedCOP( @cop ) unless @cop.nil?
989
991
  cop_high = "NA"
990
- cop_high = cooling_coil.ratedHighSpeedCOP.get unless cooling_coil.ratedHighSpeedCOP.empty?
992
+ cop_ = OpenStudio::OptionalDouble.new(cooling_coil.ratedHighSpeedCOP)
993
+ cop_high = cop_.get unless cop_.empty?
991
994
  cop_low = "NA"
992
- cop_low = cooling_coil.ratedLowSpeedCOP.get unless cooling_coil.ratedLowSpeedCOP.empty?
995
+ cop_ = OpenStudio::OptionalDouble.new(cooling_coil.ratedLowSpeedCOP)
996
+ cop_low = cop_.get unless cop_.empty?
993
997
  log << cooling_coil.name.get.to_s << ",#{cop_high},#{cop_low}\n"
994
998
  end
995
999
  end
@@ -1296,8 +1300,8 @@ module BTAP
1296
1300
  @erv_nominal_electric_power,
1297
1301
  @erv_economizer_lockout.to_bool
1298
1302
  ).each { |erv| log << erv.to_s }
1299
-
1300
-
1303
+
1304
+
1301
1305
  #Add setpoint manager to all OA object in airloops.
1302
1306
  model.getHeatExchangerAirToAirSensibleAndLatents.sort.each do |erv|
1303
1307
 
@@ -99,7 +99,7 @@ class Vintagizer
99
99
  new_construction_set.setName(construction_id)
100
100
  constructions_model.building.get.setDefaultConstructionSet( new_construction_set.clone( constructions_model ).to_DefaultConstructionSet.get )
101
101
 
102
- #Give adiabatic surfaces a construction. Does not matter what. This is a bug in Openstudio that leave these surfaces unassigned by the default construction set.
102
+ #Give adiabatic surfaces a construction. Does not matter what. This is a bug in OpenStudio that leave these surfaces unassigned by the default construction set.
103
103
  all_adiabatic_surfaces = BTAP::Geometry::Surfaces::filter_by_boundary_condition(constructions_model.getSurfaces, "Adiabatic")
104
104
  BTAP::Geometry::Surfaces::set_surfaces_construction( all_adiabatic_surfaces, constructions_model.building.get.defaultConstructionSet.get.defaultInteriorSurfaceConstructions.get.wallConstruction.get)
105
105
 
@@ -59,7 +59,7 @@ class Standard
59
59
  end
60
60
 
61
61
  # add exterior lights for parking area
62
- if area_length_count_hash[:parking_area_and_drives_area] > 0
62
+ if !area_length_count_hash[:parking_area_and_drives_area].nil? && area_length_count_hash[:parking_area_and_drives_area] > 0
63
63
 
64
64
  # lighting values
65
65
  multiplier = area_length_count_hash[:parking_area_and_drives_area] * onsite_parking_fraction
@@ -86,7 +86,7 @@ class Standard
86
86
  end
87
87
 
88
88
  # add exterior lights for facades
89
- if area_length_count_hash[:building_facades] > 0
89
+ if !area_length_count_hash[:building_facades].nil? && area_length_count_hash[:building_facades] > 0
90
90
 
91
91
  # lighting values
92
92
  multiplier = area_length_count_hash[:building_facades]
@@ -113,7 +113,7 @@ class Standard
113
113
  end
114
114
 
115
115
  # add exterior lights for main entries
116
- if area_length_count_hash[:main_entries] > 0
116
+ if !area_length_count_hash[:main_entries].nil? && area_length_count_hash[:main_entries] > 0
117
117
 
118
118
  # lighting values
119
119
  multiplier = area_length_count_hash[:main_entries]
@@ -140,7 +140,7 @@ class Standard
140
140
  end
141
141
 
142
142
  # add exterior lights for other doors
143
- if area_length_count_hash[:other_doors] > 0
143
+ if !area_length_count_hash[:other_doors].nil? && area_length_count_hash[:other_doors] > 0
144
144
 
145
145
  # lighting values
146
146
  multiplier = area_length_count_hash[:other_doors]
@@ -167,7 +167,7 @@ class Standard
167
167
  end
168
168
 
169
169
  # add exterior lights for entry canopies
170
- if area_length_count_hash[:canopy_entry_area] > 0
170
+ if !area_length_count_hash[:canopy_entry_area].nil? && area_length_count_hash[:canopy_entry_area] > 0
171
171
 
172
172
  # lighting values
173
173
  multiplier = area_length_count_hash[:canopy_entry_area]
@@ -194,7 +194,7 @@ class Standard
194
194
  end
195
195
 
196
196
  # add exterior lights for emergency canopies
197
- if area_length_count_hash[:canopy_emergency_area] > 0
197
+ if !area_length_count_hash[:canopy_emergency_area].nil? && area_length_count_hash[:canopy_emergency_area] > 0
198
198
 
199
199
  # lighting values
200
200
  multiplier = area_length_count_hash[:canopy_emergency_area]
@@ -221,7 +221,7 @@ class Standard
221
221
  end
222
222
 
223
223
  # add exterior lights for drive through windows
224
- if area_length_count_hash[:drive_through_windows] > 0
224
+ if !area_length_count_hash[:drive_through_windows].nil? && area_length_count_hash[:drive_through_windows] > 0
225
225
 
226
226
  # lighting values
227
227
  multiplier = area_length_count_hash[:drive_through_windows]
@@ -2721,7 +2721,11 @@ Standard.class_eval do
2721
2721
  end
2722
2722
  end
2723
2723
  end
2724
- return window_area / wall_area * 100 if wwr
2724
+
2725
+ # check wall area is non-zero
2726
+ if wwr && wall_area > 0
2727
+ return window_area / wall_area * 100
2728
+ end
2725
2729
 
2726
2730
  # else
2727
2731
  return window_area
@@ -546,6 +546,14 @@ class Standard
546
546
  default_water_heater_ambient_temp_sch = model_add_constant_schedule_ruleset(model,
547
547
  OpenStudio.convert(70.0, 'F', 'C').get,
548
548
  name = 'Water Heater Ambient Temp Schedule - 70F')
549
+ if temp_sch_type_limits.nil?
550
+ temp_sch_type_limits = model_add_schedule_type_limits(model,
551
+ name: 'Temperature Schedule Type Limits',
552
+ lower_limit_value: 0.0,
553
+ upper_limit_value: 100.0,
554
+ numeric_type: 'Continuous',
555
+ unit_type: 'Temperature')
556
+ end
549
557
  default_water_heater_ambient_temp_sch.setScheduleTypeLimits(temp_sch_type_limits)
550
558
  tank.setAmbientTemperatureIndicator('Schedule')
551
559
  tank.setAmbientTemperatureSchedule(default_water_heater_ambient_temp_sch)
@@ -57,14 +57,20 @@ class Standard
57
57
  end
58
58
 
59
59
  sizing_system = air_loop_hvac.sizingSystem
60
- sizing_system.setSystemOutdoorAirMethod('VentilationRateProcedure')
61
- # Set the minimum zone ventilation efficiency to be 0.6
60
+ if air_loop_hvac.model.version < OpenStudio::VersionString.new('3.3.0')
61
+ sizing_system.setSystemOutdoorAirMethod('VentilationRateProcedure')
62
+ else
63
+ sizing_system.setSystemOutdoorAirMethod('Standard62.1VentilationRateProcedure')
64
+ end
65
+
66
+ # Set the minimum zone ventilation efficiency
67
+ min_ventilation_efficiency = air_loop_hvac_minimum_zone_ventilation_efficiency(air_loop_hvac)
62
68
  air_loop_hvac.thermalZones.sort.each do |zone|
63
69
  sizing_zone = zone.sizingZone
64
70
  if air_loop_hvac.model.version < OpenStudio::VersionString.new('3.0.0')
65
71
  OpenStudio.logFree(OpenStudio::Warn, 'openstudio.prototype.SizingSystem', "The design minimum zone ventilation efficiency cannot be set for #{sizing_system.name}. It can only be set OpenStudio 3.0.0 and later.")
66
72
  else
67
- sizing_zone.setDesignMinimumZoneVentilationEfficiency(0.6)
73
+ sizing_zone.setDesignMinimumZoneVentilationEfficiency(min_ventilation_efficiency)
68
74
  end
69
75
  end
70
76
 
@@ -1757,13 +1757,21 @@ class Standard
1757
1757
  # set air loop availability controls and night cycle manager, after oa system added
1758
1758
  air_loop.setAvailabilitySchedule(hvac_op_sch)
1759
1759
  air_loop.setNightCycleControlType('CycleOnAny')
1760
- avail_mgr = air_loop.availabilityManager
1761
- if avail_mgr.is_initialized
1762
- avail_mgr = avail_mgr.get
1763
- if avail_mgr.to_AvailabilityManagerNightCycle.is_initialized
1764
- avail_mgr = avail_mgr.to_AvailabilityManagerNightCycle.get
1765
- avail_mgr.setCyclingRunTime(1800)
1766
- end
1760
+
1761
+ if model.version < OpenStudio::VersionString.new('3.5.0')
1762
+ avail_mgr = air_loop.availabilityManager
1763
+ if avail_mgr.is_initialized
1764
+ avail_mgr = avail_mgr.get
1765
+ else
1766
+ avail_mgr = nil
1767
+ end
1768
+ else
1769
+ avail_mgr = air_loop.availabilityManagers[0]
1770
+ end
1771
+
1772
+ if !avail_mgr.nil? && avail_mgr.to_AvailabilityManagerNightCycle.is_initialized
1773
+ avail_mgr = avail_mgr.to_AvailabilityManagerNightCycle.get
1774
+ avail_mgr.setCyclingRunTime(1800)
1767
1775
  end
1768
1776
 
1769
1777
  # hook the VAV system to each zone
@@ -2113,13 +2121,21 @@ class Standard
2113
2121
  # set air loop availability controls and night cycle manager, after oa system added
2114
2122
  air_loop.setAvailabilitySchedule(hvac_op_sch)
2115
2123
  air_loop.setNightCycleControlType('CycleOnAny')
2116
- avail_mgr = air_loop.availabilityManager
2117
- if avail_mgr.is_initialized
2118
- avail_mgr = avail_mgr.get
2119
- if avail_mgr.to_AvailabilityManagerNightCycle.is_initialized
2120
- avail_mgr = avail_mgr.to_AvailabilityManagerNightCycle.get
2121
- avail_mgr.setCyclingRunTime(1800)
2122
- end
2124
+
2125
+ if model.version < OpenStudio::VersionString.new('3.5.0')
2126
+ avail_mgr = air_loop.availabilityManager
2127
+ if avail_mgr.is_initialized
2128
+ avail_mgr = avail_mgr.get
2129
+ else
2130
+ avail_mgr = nil
2131
+ end
2132
+ else
2133
+ avail_mgr = air_loop.availabilityManagers[0]
2134
+ end
2135
+
2136
+ if !avail_mgr.nil? && avail_mgr.to_AvailabilityManagerNightCycle.is_initialized
2137
+ avail_mgr = avail_mgr.to_AvailabilityManagerNightCycle.get
2138
+ avail_mgr.setCyclingRunTime(1800)
2123
2139
  end
2124
2140
 
2125
2141
  # attach the VAV system to each zone
@@ -2727,13 +2743,21 @@ class Standard
2727
2743
  # set air loop availability controls and night cycle manager, after oa system added
2728
2744
  air_loop.setAvailabilitySchedule(hvac_op_sch)
2729
2745
  air_loop.setNightCycleControlType('CycleOnAny')
2730
- avail_mgr = air_loop.availabilityManager
2731
- if avail_mgr.is_initialized
2732
- avail_mgr = avail_mgr.get
2733
- if avail_mgr.to_AvailabilityManagerNightCycle.is_initialized
2734
- avail_mgr = avail_mgr.to_AvailabilityManagerNightCycle.get
2735
- avail_mgr.setCyclingRunTime(1800)
2736
- end
2746
+
2747
+ if model.version < OpenStudio::VersionString.new('3.5.0')
2748
+ avail_mgr = air_loop.availabilityManager
2749
+ if avail_mgr.is_initialized
2750
+ avail_mgr = avail_mgr.get
2751
+ else
2752
+ avail_mgr = nil
2753
+ end
2754
+ else
2755
+ avail_mgr = air_loop.availabilityManagers[0]
2756
+ end
2757
+
2758
+ if !avail_mgr.nil? && avail_mgr.to_AvailabilityManagerNightCycle.is_initialized
2759
+ avail_mgr = avail_mgr.to_AvailabilityManagerNightCycle.get
2760
+ avail_mgr.setCyclingRunTime(1800)
2737
2761
  end
2738
2762
 
2739
2763
  # create a diffuser and attach the zone/diffuser pair to the air loop
@@ -3240,7 +3264,9 @@ class Standard
3240
3264
  # To solve the issue, add economizer here for cold climates
3241
3265
  # select the climate zones with winter design temperature lower than -20C (for safer)
3242
3266
  cold_climates = ['ASHRAE 169-2006-6A', 'ASHRAE 169-2006-6B', 'ASHRAE 169-2006-7A',
3243
- 'ASHRAE 169-2006-7B', 'ASHRAE 169-2006-8A', 'ASHRAE 169-2006-8B']
3267
+ 'ASHRAE 169-2006-7B', 'ASHRAE 169-2006-8A', 'ASHRAE 169-2006-8B',
3268
+ 'ASHRAE 169-2013-6A', 'ASHRAE 169-2013-6B', 'ASHRAE 169-2013-7A',
3269
+ 'ASHRAE 169-2013-7B', 'ASHRAE 169-2013-8A', 'ASHRAE 169-2013-8B']
3244
3270
  if cold_climates.include? climate_zone
3245
3271
  # Determine the economizer type in the prototype buildings, which depends on climate zone.
3246
3272
  economizer_type = model_economizer_type(model, climate_zone)
@@ -5080,7 +5106,11 @@ class Standard
5080
5106
  name: "#{air_loop.name} heating coil",
5081
5107
  type: 'Residential Central Air Source HP',
5082
5108
  cop: hspf_to_cop_heating_no_fan(hspf))
5083
- htg_coil.setRatedSupplyFanPowerPerVolumeFlowRate(ac_w_per_cfm / OpenStudio.convert(1.0, 'cfm', 'm^3/s').get)
5109
+ if model.version < OpenStudio::VersionString.new('3.5.0')
5110
+ htg_coil.setRatedSupplyFanPowerPerVolumeFlowRate(ac_w_per_cfm / OpenStudio.convert(1.0, 'cfm', 'm^3/s').get)
5111
+ else
5112
+ htg_coil.setRatedSupplyFanPowerPerVolumeFlowRate2017(ac_w_per_cfm / OpenStudio.convert(1.0, 'cfm', 'm^3/s').get)
5113
+ end
5084
5114
  htg_coil.setMinimumOutdoorDryBulbTemperatureforCompressorOperation(OpenStudio.convert(min_hp_oat_f, 'F', 'C').get)
5085
5115
  htg_coil.setMaximumOutdoorDryBulbTemperatureforDefrostOperation(OpenStudio.convert(40.0, 'F', 'C').get)
5086
5116
  htg_coil.setCrankcaseHeaterCapacity(crank_case_heat_w)
@@ -1895,7 +1895,11 @@ class Standard
1895
1895
  oa_system = air_loop_hvac.airLoopHVACOutdoorAirSystem.get
1896
1896
  controller_oa = oa_system.getControllerOutdoorAir
1897
1897
  controller_mv = controller_oa.controllerMechanicalVentilation
1898
- controller_mv.setSystemOutdoorAirMethod('VentilationRateProcedure')
1898
+ if air_loop_hvac.model.version < OpenStudio::VersionString.new('3.3.0')
1899
+ controller_mv.setSystemOutdoorAirMethod('VentilationRateProcedure')
1900
+ else
1901
+ controller_mv.setSystemOutdoorAirMethod('Standard62.1VentilationRateProcedureWithLimit')
1902
+ end
1899
1903
  # Change the min flow rate in the controller outdoor air
1900
1904
  controller_oa.setMinimumOutdoorAirFlowRate(0.0)
1901
1905
  else
@@ -1924,6 +1928,16 @@ class Standard
1924
1928
  end
1925
1929
  end
1926
1930
 
1931
+ # Determine minimum ventilation efficiency for zones.
1932
+ # This is used to decrease the overall system minimum OA flow rate
1933
+ # such that a few zones do not drive the overall system OA flow rate too
1934
+ # high.
1935
+ def air_loop_hvac_minimum_zone_ventilation_efficiency(air_loop_hvac)
1936
+ min_ventilation_efficiency = 0.6
1937
+
1938
+ return min_ventilation_efficiency
1939
+ end
1940
+
1927
1941
  # Set the minimum VAV damper positions.
1928
1942
  #
1929
1943
  # @param air_loop_hvac [OpenStudio::Model::AirLoopHVAC] air loop
@@ -529,7 +529,7 @@ class Standard
529
529
  # Calculate the fenestration U-Factor base on the glass, frame,
530
530
  # and divider performance and area calculated by EnergyPlus.
531
531
  #
532
- # @param [OpenStudio:Model:Construction] Openstudio Construction object
532
+ # @param [OpenStudio:Model:Construction] OpenStudio Construction object
533
533
  #
534
534
  # @return [Double] the U-Factor in W/m^2*K
535
535
  def construction_calculated_fenestration_u_factor_w_frame(construction)