openstudio-standards 0.2.15.pre.rc1 → 0.2.16.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (94) hide show
  1. checksums.yaml +4 -4
  2. data/data/geometry/ASHRAEHighriseApartment.osm +0 -27
  3. data/data/standards/OpenStudio_Standards-ashrae_90_1.xlsx +0 -0
  4. data/data/standards/OpenStudio_Standards-ashrae_90_1_28Jan2022.xlsx +0 -0
  5. data/data/standards/test_performance_expected_dd_results.csv +710 -710
  6. data/lib/openstudio-standards/btap/btap_result.rb +2 -2
  7. data/lib/openstudio-standards/btap/reporting.rb +2 -2
  8. data/lib/openstudio-standards/btap/simmanager.rb +2 -2
  9. data/lib/openstudio-standards/hvac_sizing/Siz.ControllerOutdoorAir.rb +0 -54
  10. data/lib/openstudio-standards/hvac_sizing/Siz.HeatingCoolingFuels.rb +11 -1
  11. data/lib/openstudio-standards/hvac_sizing/Siz.Model.rb +1 -1
  12. data/lib/openstudio-standards/prototypes/common/buildings/Prototype.College.rb +26 -5
  13. data/lib/openstudio-standards/prototypes/common/objects/Prototype.CoilCoolingWaterToAirHeatPumpEquationFit.rb +35 -16
  14. data/lib/openstudio-standards/prototypes/common/objects/Prototype.CoilHeatingWaterToAirHeatPumpEquationFit.rb +23 -10
  15. data/lib/openstudio-standards/prototypes/common/objects/Prototype.Model.rb +36 -0
  16. data/lib/openstudio-standards/prototypes/common/objects/Prototype.ServiceWaterHeating.rb +6 -6
  17. data/lib/openstudio-standards/prototypes/common/objects/Prototype.hvac_systems.rb +0 -3
  18. data/lib/openstudio-standards/standards/Standards.AirLoopHVAC.rb +2 -2
  19. data/lib/openstudio-standards/standards/Standards.CoilCoolingWaterToAirHeatPumpEquationFit.rb +9 -3
  20. data/lib/openstudio-standards/standards/Standards.CoilHeatingGas.rb +2 -0
  21. data/lib/openstudio-standards/standards/Standards.Construction.rb +12 -6
  22. data/lib/openstudio-standards/standards/Standards.Model.rb +38 -7
  23. data/lib/openstudio-standards/standards/Standards.Space.rb +4 -4
  24. data/lib/openstudio-standards/standards/Standards.SpaceType.rb +7 -0
  25. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2004/ashrae_90_1_2004.Model.rb +32 -11
  26. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2004/data/ashrae_90_1_2004.construction_properties.json +22 -742
  27. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2004/data/ashrae_90_1_2004.construction_sets.json +2 -2
  28. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2004/data/ashrae_90_1_2004.prototype_inputs.json +12 -12
  29. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2004/data/ashrae_90_1_2004.spc_typ.json +81 -9
  30. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2007/data/ashrae_90_1_2007.construction_properties.json +19 -559
  31. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2007/data/ashrae_90_1_2007.construction_sets.json +2 -2
  32. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2007/data/ashrae_90_1_2007.prototype_inputs.json +12 -12
  33. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2007/data/ashrae_90_1_2007.spc_typ.json +80 -8
  34. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2010/data/ashrae_90_1_2010.construction_properties.json +19 -559
  35. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2010/data/ashrae_90_1_2010.construction_sets.json +2 -2
  36. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2010/data/ashrae_90_1_2010.prototype_inputs.json +14 -14
  37. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2010/data/ashrae_90_1_2010.spc_typ.json +81 -137
  38. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2013/data/ashrae_90_1_2013.construction_properties.json +19 -559
  39. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2013/data/ashrae_90_1_2013.construction_sets.json +2 -2
  40. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2013/data/ashrae_90_1_2013.prototype_inputs.json +15 -15
  41. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2013/data/ashrae_90_1_2013.spc_typ.json +80 -136
  42. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2016/data/ashrae_90_1_2016.construction_properties.json +370 -910
  43. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2016/data/ashrae_90_1_2016.construction_sets.json +2 -2
  44. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2016/data/ashrae_90_1_2016.prototype_inputs.json +15 -15
  45. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2016/data/ashrae_90_1_2016.refrigeration_system.json +0 -8
  46. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2016/data/ashrae_90_1_2016.spc_typ.json +428 -344
  47. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.AirLoopHVAC.rb +19 -6
  48. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/data/ashrae_90_1_2019.construction_properties.json +2380 -1300
  49. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/data/ashrae_90_1_2019.construction_sets.json +2 -2
  50. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/data/ashrae_90_1_2019.prototype_inputs.json +15 -15
  51. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/data/ashrae_90_1_2019.refrigeration_system.json +0 -8
  52. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/data/ashrae_90_1_2019.spc_typ.json +428 -344
  53. data/lib/openstudio-standards/standards/ashrae_90_1/data/ashrae_90_1.constructions.json +140 -0
  54. data/lib/openstudio-standards/standards/ashrae_90_1/data/ashrae_90_1.schedules.json +1176 -312
  55. data/lib/openstudio-standards/standards/ashrae_90_1/doe_ref_1980_2004/data/doe_ref_1980_2004.construction_properties.json +172 -1132
  56. data/lib/openstudio-standards/standards/ashrae_90_1/doe_ref_1980_2004/data/doe_ref_1980_2004.construction_sets.json +14 -14
  57. data/lib/openstudio-standards/standards/ashrae_90_1/doe_ref_1980_2004/data/doe_ref_1980_2004.prototype_inputs.json +15 -15
  58. data/lib/openstudio-standards/standards/ashrae_90_1/doe_ref_1980_2004/data/doe_ref_1980_2004.spc_typ.json +83 -11
  59. data/lib/openstudio-standards/standards/ashrae_90_1/doe_ref_pre_1980/data/doe_ref_pre_1980.construction_properties.json +180 -1140
  60. data/lib/openstudio-standards/standards/ashrae_90_1/doe_ref_pre_1980/data/doe_ref_pre_1980.construction_sets.json +14 -14
  61. data/lib/openstudio-standards/standards/ashrae_90_1/doe_ref_pre_1980/data/doe_ref_pre_1980.prototype_inputs.json +15 -15
  62. data/lib/openstudio-standards/standards/ashrae_90_1/doe_ref_pre_1980/data/doe_ref_pre_1980.spc_typ.json +84 -12
  63. data/lib/openstudio-standards/standards/ashrae_90_1/nrel_zne_ready_2017/data/nrel_zne_ready_2017.construction_properties.json +9 -9
  64. data/lib/openstudio-standards/standards/ashrae_90_1/ze_aedg_multifamily/data/ze_aedg_multifamily.construction_properties.json +9 -9
  65. data/lib/openstudio-standards/standards/necb/BTAPPRE1980/hvac_system_3_and_8_single_speed.rb +12 -6
  66. data/lib/openstudio-standards/standards/necb/BTAPPRE1980/hvac_system_4.rb +12 -6
  67. data/lib/openstudio-standards/standards/necb/BTAPPRE1980/hvac_system_6.rb +16 -8
  68. data/lib/openstudio-standards/standards/necb/ECMS/ecms.rb +10 -20
  69. data/lib/openstudio-standards/standards/necb/ECMS/hvac_systems.rb +209 -37
  70. data/lib/openstudio-standards/standards/necb/ECMS/loads.rb +1 -0
  71. data/lib/openstudio-standards/standards/necb/ECMS/pv_ground.rb +8 -6
  72. data/lib/openstudio-standards/standards/necb/NECB2011/autozone.rb +16 -9
  73. data/lib/openstudio-standards/standards/necb/NECB2011/data/geometry/HighriseApartment.osm +1 -1
  74. data/lib/openstudio-standards/standards/necb/NECB2011/data/geometry/LowriseApartment.osm +1 -1
  75. data/lib/openstudio-standards/standards/necb/NECB2011/data/geometry/MidriseApartment.osm +1 -1
  76. data/lib/openstudio-standards/standards/necb/NECB2011/hvac_system_1_multi_speed.rb +9 -5
  77. data/lib/openstudio-standards/standards/necb/NECB2011/hvac_system_1_single_speed.rb +10 -6
  78. data/lib/openstudio-standards/standards/necb/NECB2011/hvac_system_2_and_5.rb +9 -5
  79. data/lib/openstudio-standards/standards/necb/NECB2011/hvac_system_3_and_8_multi_speed.rb +14 -8
  80. data/lib/openstudio-standards/standards/necb/NECB2011/hvac_system_3_and_8_single_speed.rb +14 -8
  81. data/lib/openstudio-standards/standards/necb/NECB2011/hvac_system_4.rb +13 -6
  82. data/lib/openstudio-standards/standards/necb/NECB2011/hvac_system_6.rb +12 -6
  83. data/lib/openstudio-standards/standards/necb/NECB2011/hvac_systems.rb +4 -2
  84. data/lib/openstudio-standards/standards/necb/NECB2011/necb_2011.rb +38 -19
  85. data/lib/openstudio-standards/standards/necb/NECB2011/qaqc/necb_qaqc.rb +2 -2
  86. data/lib/openstudio-standards/standards/necb/NECB2011/service_water_heating.rb +15 -4
  87. data/lib/openstudio-standards/standards/necb/NECB2020/building_envelope.rb +10 -651
  88. data/lib/openstudio-standards/standards/necb/NECB2020/necb_2020.rb +8 -38
  89. data/lib/openstudio-standards/standards/necb/NECB2020/service_water_heating.rb +159 -0
  90. data/lib/openstudio-standards/standards/necb/common/btap_data.rb +41 -43
  91. data/lib/openstudio-standards/standards/necb/common/btap_datapoint.rb +7 -4
  92. data/lib/openstudio-standards/version.rb +1 -1
  93. data/lib/openstudio-standards.rb +1 -0
  94. metadata +4 -2
@@ -34,8 +34,10 @@ class BTAPPRE1980
34
34
  # zone data
35
35
  system_data[:max_system_supply_air_temperature] = 43.0
36
36
  system_data[:min_system_supply_air_temperature] = 13.0
37
- system_data[:ZoneCoolingDesignSupplyAirTemperature] = 13.0
38
- system_data[:ZoneHeatingDesignSupplyAirTemperature] = 43.0
37
+ system_data[:ZoneCoolingDesignSupplyAirTemperatureInputMethod] = 'TemperatureDifference'
38
+ system_data[:ZoneCoolingDesignSupplyAirTemperatureDifference] = 11.0
39
+ system_data[:ZoneHeatingDesignSupplyAirTemperatureInputMethod] = 'TemperatureDifference'
40
+ system_data[:ZoneHeatingDesignSupplyAirTemperatureDifference] = 21.0
39
41
  system_data[:ZoneCoolingSizingFactor] = 1.1
40
42
  system_data[:ZoneHeatingSizingFactor] = 1.3
41
43
  system_data[:ZoneVAVMinFlowFactorPerFloorArea] = 0.002
@@ -115,8 +117,10 @@ class BTAPPRE1980
115
117
  (BTAP::Geometry::BuildingStoreys.get_zones_from_storey(story) & zones).each do |zone|
116
118
  # Zone sizing parameters
117
119
  sizing_zone = zone.sizingZone
118
- sizing_zone.setZoneCoolingDesignSupplyAirTemperature(system_data[:ZoneCoolingDesignSupplyAirTemperature])
119
- sizing_zone.setZoneHeatingDesignSupplyAirTemperature(system_data[:ZoneHeatingDesignSupplyAirTemperature])
120
+ sizing_zone.setZoneCoolingDesignSupplyAirTemperatureInputMethod(system_data[:ZoneCoolingDesignSupplyAirTemperatureInputMethod])
121
+ sizing_zone.setZoneCoolingDesignSupplyAirTemperatureDifference(system_data[:ZoneCoolingDesignSupplyAirTemperatureDifference])
122
+ sizing_zone.setZoneHeatingDesignSupplyAirTemperatureInputMethod(system_data[:ZoneHeatingDesignSupplyAirTemperatureInputMethod])
123
+ sizing_zone.setZoneHeatingDesignSupplyAirTemperatureDifference(system_data[:ZoneHeatingDesignSupplyAirTemperatureDifference])
120
124
  sizing_zone.setZoneCoolingSizingFactor(system_data[:ZoneCoolingSizingFactor])
121
125
  sizing_zone.setZoneHeatingSizingFactor(system_data[:ZoneHeatingSizingFactor])
122
126
 
@@ -197,8 +201,10 @@ class BTAPPRE1980
197
201
  # zone data
198
202
  system_6_data[:max_system_supply_air_temperature] = 43.0
199
203
  system_6_data[:min_system_supply_air_temperature] = 13.0
200
- system_6_data[:ZoneCoolingDesignSupplyAirTemperature] = 13.0
201
- system_6_data[:ZoneHeatingDesignSupplyAirTemperature] = 43.0
204
+ system_6_data[:ZoneCoolingDesignSupplyAirTemperatureInputMethod] = 'TemperatureDifference'
205
+ system_6_data[:ZoneCoolingDesignSupplyAirTemperatureDifference] = 11.0
206
+ system_6_data[:ZoneHeatingDesignSupplyAirTemperatureInputMethod] = 'TemperatureDifference'
207
+ system_6_data[:ZoneHeatingDesignSupplyAirTemperatureDifference] = 21.0
202
208
  system_6_data[:ZoneCoolingSizingFactor] = 1.1
203
209
  system_6_data[:ZoneHeatingSizingFactor] = 1.3
204
210
  system_6_data[:ZoneVAVMinFlowFactorPerFloorArea] = 0.002
@@ -285,8 +291,10 @@ class BTAPPRE1980
285
291
  (BTAP::Geometry::BuildingStoreys.get_zones_from_storey(story) & zones).each do |zone|
286
292
  # Zone sizing parameters
287
293
  sizing_zone = zone.sizingZone
288
- sizing_zone.setZoneCoolingDesignSupplyAirTemperature(system_data[:ZoneCoolingDesignSupplyAirTemperature])
289
- sizing_zone.setZoneHeatingDesignSupplyAirTemperature(system_data[:ZoneHeatingDesignSupplyAirTemperature])
294
+ sizing_zone.setZoneCoolingDesignSupplyAirTemperatureInputMethod(system_data[:ZoneCoolingDesignSupplyAirTemperatureInputMethod])
295
+ sizing_zone.setZoneCoolingDesignSupplyAirTemperatureDifference(system_data[:ZoneCoolingDesignSupplyAirTemperatureDifference])
296
+ sizing_zone.setZoneHeatingDesignSupplyAirTemperatureInputMethod(system_data[:ZoneHeatingDesignSupplyAirTemperatureInputMethod])
297
+ sizing_zone.setZoneHeatingDesignSupplyAirTemperatureDifference(system_data[:ZoneHeatingDesignSupplyAirTemperatureDifference])
290
298
  sizing_zone.setZoneCoolingSizingFactor(system_data[:ZoneCoolingSizingFactor])
291
299
  sizing_zone.setZoneHeatingSizingFactor(system_data[:ZoneHeatingSizingFactor])
292
300
 
@@ -39,42 +39,32 @@ class ECMS < NECB2011
39
39
  @standards_data['curves'] = standards_data['tables']['curves']['table']
40
40
  end
41
41
 
42
- def apply_system_ecm(model:, ecm_system_name: nil, template_standard:, runner: nil, primary_heating_fuel: nil)
42
+ def apply_system_ecm(model:, ecm_system_name: nil, template_standard:, runner: nil, primary_heating_fuel: nil, ecm_system_zones_map_option: 'NECB_Default')
43
43
  # Do nothing if nil or other usual suspects.. covering all bases for now.
44
44
  return if ecm_system_name.nil? || ecm_system_name == 'none' || ecm_system_name == 'NECB_Default'
45
+ ecm_system_zones_map_option = 'NECB_Default' if ecm_system_zones_map_option.nil? || ecm_system_zones_map_option == 'none'
45
46
 
46
47
  ecm_std = Standard.build('ECMS')
47
48
  systems = model.getAirLoopHVACs
48
49
  map_system_to_zones, system_doas_flags = ecm_std.get_map_systems_to_zones(systems)
49
- zone_clg_eqpt_type = ecm_std.get_zone_clg_eqpt_type(model)
50
- # when the ecm is associated with adding a new HVAC system, then remove existing system components and loops
51
50
  ecm_add_method_name = "add_ecm_#{ecm_system_name.downcase}"
52
51
 
53
52
  raise("the method #{ecm_add_method_name} does not exist in the ECM class. Please verify that this should be called.") unless ecm_std.respond_to? ecm_add_method_name
54
53
 
54
+ # when the ecm is associated with adding a new HVAC system, then remove existing system components and loops
55
55
  ecm_std.remove_all_zone_eqpt(systems)
56
56
  ecm_std.remove_air_loops(model)
57
57
  ecm_std.remove_hw_loops(model)
58
58
  ecm_std.remove_chw_loops(model)
59
59
  ecm_std.remove_cw_loops(model)
60
60
 
61
- # Rather than go through every add_ecm class to add 'the primary_heating_fuel' argument I added this statement to
62
- # only include it when it is used (for now in the add_ecm_remove_airloops_add_zone_baseboards method).
63
- if ecm_add_method_name == 'add_ecm_remove_airloops_add_zone_baseboards'
64
- ecm_std.send(ecm_add_method_name,
65
- model: model,
66
- system_zones_map: map_system_to_zones,
67
- system_doas_flags: system_doas_flags,
68
- zone_clg_eqpt_type: zone_clg_eqpt_type,
69
- standard: template_standard,
70
- primary_heating_fuel: primary_heating_fuel)
71
- else
72
- ecm_std.send(ecm_add_method_name,
73
- model: model,
74
- system_zones_map: map_system_to_zones,
75
- system_doas_flags: system_doas_flags)
76
- end
77
- # ecm_std.add_ecm_hs09_ccashpsys(model:model,system_zones_map:,system_doas_flags:,zone_clg_eqpt_type: nil,standard:,baseboard_flag: true)
61
+ ecm_std.send(ecm_add_method_name,
62
+ model: model,
63
+ system_zones_map: map_system_to_zones,
64
+ system_doas_flags: system_doas_flags,
65
+ ecm_system_zones_map_option: ecm_system_zones_map_option,
66
+ standard: template_standard,
67
+ heating_fuel: primary_heating_fuel)
78
68
  end
79
69
 
80
70
  def apply_system_efficiencies_ecm(model:, ecm_system_name: nil)
@@ -309,7 +309,7 @@ class ECMS
309
309
 
310
310
  # =============================================================================================================================
311
311
  # Method to determine whether zone can have terminal vrf equipment. Zones with no vrf terminal equipment are characterized by
312
- # transient occupancy such is the case for corridors, stairwells, storage, etc ...
312
+ # transient occupancy such is the case for corridors, stairwells, storage, ...
313
313
  def zone_with_no_vrf_eqpt?(zone)
314
314
  space_types_to_skip = {}
315
315
  space_types_to_skip['NECB2011'] = ['Atrium - H < 13m',
@@ -413,6 +413,56 @@ class ECMS
413
413
  end
414
414
  end
415
415
 
416
+ #=============================================================================================================================
417
+ # Get building storey for a zone
418
+ def get_zone_storey(zone)
419
+ zone_storey = nil
420
+ zone.model.getBuildingStorys.each do |storey|
421
+ storey.spaces.each do |space|
422
+ if space.thermalZone.get.name.to_s == zone.name.to_s
423
+ zone_storey = storey
424
+ break
425
+ end
426
+ end
427
+ break if !zone_storey.nil?
428
+ end
429
+ return zone_storey
430
+ end
431
+
432
+ #==============================================================================================================================
433
+ # Get a map of bldg storeys and zones
434
+ def get_storey_zones_map(system_zones_map)
435
+ storey_zones_map = {}
436
+ system_zones_map.each do |sys,zones|
437
+ zones.each do |zone|
438
+ storey = get_zone_storey(zone)
439
+ storey_zones_map[storey.name.to_s] = [] if !storey_zones_map.has_key? storey.name.to_s
440
+ storey_zones_map[storey.name.to_s] << zone
441
+ end
442
+ end
443
+ return storey_zones_map
444
+ end
445
+
446
+ #==============================================================================================================================
447
+ # Update the map between systems and zones
448
+ def update_system_zones_map(model,system_zones_map,system_zones_map_option,system_key)
449
+ updated_system_zones_map = {}
450
+ if system_zones_map_option == 'one_sys_per_bldg'
451
+ system_zones_map.each do |sname,zones|
452
+ updated_system_zones_map[system_key] = [] if !updated_system_zones_map.has_key? system_key
453
+ updated_system_zones_map[system_key] += zones
454
+ end
455
+ elsif system_zones_map_option == 'one_sys_per_floor'
456
+ storey_zones_map = get_storey_zones_map(system_zones_map)
457
+ storey_zones_map.each do |storey_name,zones|
458
+ sys_name = "#{system_key}_#{storey_name.gsub(' ','_')}"
459
+ updated_system_zones_map[sys_name] = [] if !updated_system_zones_map.has_key? sys_name
460
+ updated_system_zones_map[sys_name] += zones
461
+ end
462
+ end
463
+ return updated_system_zones_map
464
+ end
465
+
416
466
  # =============================================================================================================================
417
467
  # Add equipment for ECM 'hs08_ccashp_vrf':
418
468
  # -Constant-volume DOAS with air-source heat pump for heating and cooling and electric backup
@@ -422,24 +472,45 @@ class ECMS
422
472
  model:,
423
473
  system_zones_map:,
424
474
  system_doas_flags:,
425
- air_sys_eqpt_type: 'ccashp'
426
- )
475
+ ecm_system_zones_map_option:,
476
+ heating_fuel:,
477
+ standard:,
478
+ air_sys_eqpt_type: 'ccashp')
479
+
480
+ # Update system zones map if needed
481
+ if ecm_system_zones_map_option != 'NECB_Default'
482
+ system_zones_map = update_system_zones_map(model,system_zones_map,ecm_system_zones_map_option,'sys_1')
483
+ else
484
+ updated_system_zones_map = {}
485
+ system_zones_map.each {|sname,zones| updated_system_zones_map["sys_1#{sname[5..]}"] = zones} # doas unit is an NECB sys_1
486
+ system_zones_map = updated_system_zones_map
487
+ end
427
488
  # Add outdoor VRF unit
428
489
  outdoor_vrf_unit = add_outdoor_vrf_unit(model: model, ecm_name: 'hs08_ccashp_vrf')
429
490
  # Update system doas flags
430
- system_doas_flags.keys.each { |sname| system_doas_flags[sname] = true }
491
+ system_doas_flags = {}
492
+ system_zones_map.keys.each { |sname| system_doas_flags[sname] = true }
493
+ # Set heating fuel
494
+ updated_heating_fuel = heating_fuel
495
+ if heating_fuel == 'DefaultFuel'
496
+ epw = BTAP::Environment::WeatherFile.new(model.weatherFile.get.path.get)
497
+ updated_heating_fuel = standard.standards_data['regional_fuel_use'].detect { |fuel_sources| fuel_sources['state_province_regions'].include?(epw.state_province_region) }['fueltype_set']
498
+ end
499
+ raise("Heating fuel for ECM 'HS08_CCASHP_VRF' is neither Electricity nor NaturalGas") if ((updated_heating_fuel != 'Electricity') && (updated_heating_fuel != 'NaturalGas'))
431
500
  # use system zones map and generate new air system and zonal equipment
432
501
  system_zones_map.sort.each do |sys_name, zones|
433
502
  sys_info = air_sys_comps_assumptions(sys_name: sys_name,
434
503
  zones: zones,
435
504
  system_doas_flags: system_doas_flags)
505
+ sys_supp_htg_eqpt_type = 'coil_electric'
506
+ sys_supp_htg_eqpt_type = 'coil_gas' if updated_heating_fuel == 'NaturalGas'
436
507
  airloop, return_fan = add_air_system(model: model,
437
508
  zones: zones,
438
509
  sys_abbr: sys_info['sys_abbr'],
439
510
  sys_vent_type: sys_info['sys_vent_type'],
440
511
  sys_heat_rec_type: sys_info['sys_heat_rec_type'],
441
512
  sys_htg_eqpt_type: air_sys_eqpt_type,
442
- sys_supp_htg_eqpt_type: 'coil_electric',
513
+ sys_supp_htg_eqpt_type: sys_supp_htg_eqpt_type,
443
514
  sys_clg_eqpt_type: air_sys_eqpt_type,
444
515
  sys_supp_fan_type: sys_info['sys_supp_fan_type'],
445
516
  sys_ret_fan_type: sys_info['sys_ret_fan_type'],
@@ -477,7 +548,7 @@ class ECMS
477
548
  zone_supp_htg_eqpt_type: 'none',
478
549
  zone_clg_eqpt_type: 'vrf',
479
550
  zone_fan_type: 'On_Off')
480
- # add electric unit heaters fpr backup
551
+ # add electric baseboards for backup
481
552
  add_zone_eqpt(model: model,
482
553
  airloop: airloop,
483
554
  zones: zones,
@@ -486,7 +557,7 @@ class ECMS
486
557
  zone_htg_eqpt_type: 'baseboard_electric',
487
558
  zone_supp_htg_eqpt_type: 'none',
488
559
  zone_clg_eqpt_type: 'none',
489
- zone_fan_type: 'none') # OS doesn't support onoff fans for unit heaters
560
+ zone_fan_type: 'none')
490
561
  # Now we can find and apply maximum horizontal and vertical distances between outdoor vrf unit and zones with vrf terminal units
491
562
  max_hor_pipe_length, max_vert_pipe_length = get_max_vrf_pipe_lengths(model)
492
563
  outdoor_vrf_unit.setEquivalentPipingLengthusedforPipingCorrectionFactorinCoolingMode(max_hor_pipe_length)
@@ -636,6 +707,9 @@ class ECMS
636
707
  when 'coil_electric'
637
708
  htg_eqpt = OpenStudio::Model::CoilHeatingElectric.new(model, always_on)
638
709
  htg_eqpt.setName('CoilHeatingElectric')
710
+ when 'coil_gas'
711
+ htg_eqpt = OpenStudio::Model::CoilHeatingGas.new(model, always_on)
712
+ htg_eqpt.setName('CoilHeatingGas')
639
713
  when 'ashp'
640
714
  htg_eqpt = OpenStudio::Model::CoilHeatingDXSingleSpeed.new(model)
641
715
  htg_eqpt.setName('CoilHeatingDXSingleSpeed_ASHP')
@@ -931,14 +1005,27 @@ class ECMS
931
1005
  # -Electric baseboards
932
1006
  def add_ecm_hs09_ccashp_baseboard(model:,
933
1007
  system_zones_map:, # hash of ailoop names as keys and array of zones as values
934
- system_doas_flags:) # hash of system names as keys and flag for DOAS as values
935
-
1008
+ system_doas_flags:, # hash of system names as keys and flag for DOAS as values
1009
+ ecm_system_zones_map_option:,
1010
+ heating_fuel:,
1011
+ standard:)
1012
+
1013
+ # Set heating fuel
1014
+ updated_heating_fuel = heating_fuel
1015
+ if heating_fuel == 'DefaultFuel'
1016
+ epw = BTAP::Environment::WeatherFile.new(model.weatherFile.get.path.get)
1017
+ updated_heating_fuel = standard.standards_data['regional_fuel_use'].detect { |fuel_sources| fuel_sources['state_province_regions'].include?(epw.state_province_region)}['fueltype_set']
1018
+ end
1019
+ raise("Heating fuel for ECM 'HS09_CCASHP_Baseboard' is neither Electricity nor NaturalGas") if ((updated_heating_fuel != 'Electricity') && (updated_heating_fuel != 'NaturalGas'))
1020
+ # Set supplemental heating for air loop
1021
+ sys_supp_htg_eqpt_type = 'coil_electric'
1022
+ sys_supp_htg_eqpt_type = 'coil_gas' if updated_heating_fuel == 'NaturalGas'
936
1023
  systems = []
937
1024
  system_zones_map.sort.each do |sys_name, zones|
938
1025
  sys_info = air_sys_comps_assumptions(sys_name: sys_name,
939
1026
  zones: zones,
940
1027
  system_doas_flags: system_doas_flags)
941
- # add air loop and its equipment
1028
+ # add airloop and its equipment
942
1029
  airloop, return_fan = add_air_system(
943
1030
  model: model,
944
1031
  zones: zones,
@@ -946,7 +1033,7 @@ class ECMS
946
1033
  sys_vent_type: sys_info['sys_vent_type'],
947
1034
  sys_heat_rec_type: sys_info['sys_heat_rec_type'],
948
1035
  sys_htg_eqpt_type: 'ccashp',
949
- sys_supp_htg_eqpt_type: 'coil_electric',
1036
+ sys_supp_htg_eqpt_type: sys_supp_htg_eqpt_type,
950
1037
  sys_clg_eqpt_type: 'ccashp',
951
1038
  sys_supp_fan_type: sys_info['sys_supp_fan_type'],
952
1039
  sys_ret_fan_type: sys_info['sys_ret_fan_type'],
@@ -1016,6 +1103,8 @@ class ECMS
1016
1103
  htg_dx_coil = icomp.to_CoilHeatingDXVariableSpeed.get
1017
1104
  elsif icomp.to_CoilHeatingElectric.is_initialized
1018
1105
  backup_coil = icomp.to_CoilHeatingElectric.get
1106
+ elsif icomp.to_CoilHeatingGas.is_initialized
1107
+ backup_coil = icomp.to_CoilHeatingGas.get
1019
1108
  elsif icomp.to_FanConstantVolume.is_initialized
1020
1109
  fans << icomp.to_FanConstantVolume.get
1021
1110
  elsif icomp.to_FanVariableVolume.is_initialized
@@ -1034,16 +1123,40 @@ class ECMS
1034
1123
  supply_fan = fan # assume supply fan has higher pressure drop
1035
1124
  end
1036
1125
  end
1037
- fan_power = supply_fan.autosizedMaximumFlowRate.to_f * max_pd / supply_fan.fanTotalEfficiency.to_f
1126
+ # There is an error in EnergyPlus in the estimated capacity of the coil "CoilCoolingDXVariableSpeed".
1127
+ # Here the capacity reported by OS is adjusted to estimate an appropriate capacity for the cooling coil.
1128
+ # The autosized capacity is corrected for the actual fan flow rate and fan power.
1129
+ if supply_fan.autosizedMaximumFlowRate.is_initialized
1130
+ fan_max_afr = supply_fan.autosizedMaximumFlowRate.to_f
1131
+ elsif supply_fan.maximumFlowRate.is_initialized
1132
+ fan_max_afr = supply_fan.maximumFlowRate.to_f
1133
+ else
1134
+ raise "Fan flow rate is undefined for fan #{supply_fan.name.to_s}"
1135
+ end
1136
+ if clg_dx_coil.autosizedRatedAirFlowRateAtSelectedNominalSpeedLevel.is_initialized
1137
+ clg_dx_coil_afr = clg_dx_coil.autosizedRatedAirFlowRateAtSelectedNominalSpeedLevel.to_f
1138
+ elsif clg_dx_coil.ratedAirFlowRateAtSelectedNominalSpeedLevel.is_initialized
1139
+ clg_dx_coil_afr = clg_dx_coil.ratedAirFlowRateAtSelectedNominalSpeedLevel.to_f
1140
+ else
1141
+ raise "Rated air flow rate at selected nominal speed level is undefined for coil #{clg_dx_coil.name.to_s}"
1142
+ end
1143
+ fan_power = fan_max_afr * max_pd / supply_fan.fanTotalEfficiency.to_f
1038
1144
  clg_dx_coil_cap = clg_dx_coil.autosizedGrossRatedTotalCoolingCapacityAtSelectedNominalSpeedLevel.to_f *
1039
- supply_fan.autosizedMaximumFlowRate.to_f / clg_dx_coil.autosizedRatedAirFlowRateAtSelectedNominalSpeedLevel.to_f +
1040
- fan_power / clg_dx_coil.speeds.last.referenceUnitGrossRatedSensibleHeatRatio.to_f
1041
- else
1145
+ fan_max_afr / clg_dx_coil_afr + fan_power / clg_dx_coil.speeds.last.referenceUnitGrossRatedSensibleHeatRatio.to_f
1146
+ elsif clg_dx_coil.grossRatedTotalCoolingCapacityAtSelectedNominalSpeedLevel.is_initialized
1042
1147
  clg_dx_coil_cap = clg_dx_coil.grossRatedTotalCoolingCapacityAtSelectedNominalSpeedLevel.to_f
1148
+ else
1149
+ raise "Rated total cooling capacity at selected nominal speed is undefined for coil #{clg_dx_coil.name.to_s}"
1043
1150
  end
1044
1151
  htg_dx_coil_init_name = get_hvac_comp_init_name(htg_dx_coil, false)
1045
1152
  htg_dx_coil.setName(htg_dx_coil_init_name)
1046
- backup_coil_cap = backup_coil.autosizedNominalCapacity.to_f
1153
+ if backup_coil.autosizedNominalCapacity.is_initialized
1154
+ backup_coil_cap = backup_coil.autosizedNominalCapacity.to_f
1155
+ elsif backup_coil.nominalCapacity.is_initialized
1156
+ backup_coil_cap = backup_coil.nominalCapacity.to_f
1157
+ else
1158
+ raise "Nominal capacity is undefiled for coil #{backup_coil.name.to_s}"
1159
+ end
1047
1160
  # Set the DX capacities to the maximum of the fraction of the backup coil capacity or the cooling capacity needed
1048
1161
  dx_cap = fr_backup_coil_cap_as_dx_coil_cap * backup_coil_cap
1049
1162
  if dx_cap < clg_dx_coil_cap then dx_cap = clg_dx_coil_cap end
@@ -1063,10 +1176,32 @@ class ECMS
1063
1176
  # -Packaged-Terminal air-source heat pumps with electric backup
1064
1177
  def add_ecm_hs11_ashp_pthp(model:,
1065
1178
  system_zones_map:,
1066
- system_doas_flags:)
1067
-
1179
+ system_doas_flags:,
1180
+ ecm_system_zones_map_option:,
1181
+ standard:,
1182
+ heating_fuel:)
1183
+
1184
+ # Set heating fuel
1185
+ updated_heating_fuel = heating_fuel
1186
+ if heating_fuel == 'DefaultFuel'
1187
+ epw = BTAP::Environment::WeatherFile.new(model.weatherFile.get.path.get)
1188
+ updated_heating_fuel = standard.standards_data['regional_fuel_use'].detect { |fuel_sources| fuel_sources['state_province_regions'].include?(epw.state_province_region)}['fueltype_set']
1189
+ end
1190
+ raise("Heating fuel for ECM 'HS11_ASHP_PTHP' is neither Electricity nor NaturalGas") if ((updated_heating_fuel != 'Electricity') && (updated_heating_fuel != 'NaturalGas'))
1191
+ # Set supplemental heaing for airloop
1192
+ sys_supp_htg_eqpt_type = 'coil_electric'
1193
+ sys_supp_htg_eqpt_type = 'coil_gas' if updated_heating_fuel == 'NaturalGas'
1194
+ # Update system zones map if needed
1195
+ if ecm_system_zones_map_option != 'NECB_Default'
1196
+ system_zones_map = update_system_zones_map(model,system_zones_map,ecm_system_zones_map_option,'sys_1')
1197
+ else
1198
+ updated_system_zones_map = {}
1199
+ system_zones_map.each {|sname,zones| updated_system_zones_map["sys_1#{sname[5..]}"] = zones}
1200
+ system_zones_map = updated_system_zones_map
1201
+ end
1068
1202
  # Update system doas flags
1069
- system_doas_flags.keys.each { |sname| system_doas_flags[sname] = true }
1203
+ system_doas_flags = {}
1204
+ system_zones_map.keys.each { |sname| system_doas_flags[sname] = true }
1070
1205
  # use system zones map and generate new air system and zonal equipment
1071
1206
  systems = []
1072
1207
  system_zones_map.sort.each do |sys_name, zones|
@@ -1079,7 +1214,7 @@ class ECMS
1079
1214
  sys_vent_type: sys_info['sys_vent_type'],
1080
1215
  sys_heat_rec_type: sys_info['sys_heat_rec_type'],
1081
1216
  sys_htg_eqpt_type: 'ashp',
1082
- sys_supp_htg_eqpt_type: 'coil_electric',
1217
+ sys_supp_htg_eqpt_type: sys_supp_htg_eqpt_type,
1083
1218
  sys_clg_eqpt_type: 'ashp',
1084
1219
  sys_supp_fan_type: sys_info['sys_supp_fan_type'],
1085
1220
  sys_ret_fan_type: sys_info['sys_ret_fan_type'],
@@ -1161,12 +1296,20 @@ class ECMS
1161
1296
  clg_dx_coil.setName(clg_dx_coil_init_name)
1162
1297
  if clg_dx_coil.autosizedRatedTotalCoolingCapacity.is_initialized
1163
1298
  clg_dx_coil_cap = clg_dx_coil.autosizedRatedTotalCoolingCapacity.to_f
1164
- else
1299
+ elsif clg_dx_coil.ratedTotalCoolingCapacity.is_initialized
1165
1300
  clg_dx_coil_cap = clg_dx_coil.ratedTotalCoolingCapacity.to_f
1301
+ else
1302
+ raise "The total cooling capacity is undefined for coil #{clg_dx_coil_cap.name.to_s}"
1166
1303
  end
1167
1304
  htg_dx_coil_init_name = get_hvac_comp_init_name(htg_dx_coil, true)
1168
1305
  htg_dx_coil.setName(htg_dx_coil_init_name)
1169
- backup_coil_cap = backup_coil.autosizedNominalCapacity.to_f
1306
+ if backup_coil.autosizedNominalCapacity.is_initialized
1307
+ backup_coil_cap = backup_coil.autosizedNominalCapacity.to_f
1308
+ elsif backup_coil.nominalCapacity.is_initialized
1309
+ backup_coil_cap = backup_coil.nominalCapacity.to_f
1310
+ else
1311
+ raise "The nominal capacity is undefined for coil #{backup_coil.name.to_s}"
1312
+ end
1170
1313
  # Set the DX capacities to the maximum of the fraction of the backup coil capacity or the cooling capacity needed
1171
1314
  dx_cap = fr_backup_coil_cap_as_dx_coil_cap * backup_coil_cap
1172
1315
  if dx_cap < clg_dx_coil_cap then dx_cap = clg_dx_coil_cap end
@@ -1193,8 +1336,21 @@ class ECMS
1193
1336
  # -Electric baseboards
1194
1337
  def add_ecm_hs12_ashp_baseboard(model:,
1195
1338
  system_zones_map:,
1196
- system_doas_flags:)
1197
-
1339
+ system_doas_flags:,
1340
+ ecm_system_zones_map_option:,
1341
+ standard:,
1342
+ heating_fuel:)
1343
+
1344
+ # Set heating fuel
1345
+ updated_heating_fuel = heating_fuel
1346
+ if heating_fuel == 'DefaultFuel'
1347
+ epw = BTAP::Environment::WeatherFile.new(model.weatherFile.get.path.get)
1348
+ updated_heating_fuel = standard.standards_data['regional_fuel_use'].detect { |fuel_sources| fuel_sources['state_province_regions'].include?(epw.state_province_region)}['fueltype_set']
1349
+ end
1350
+ raise("Heating fuel for ECM 'HS12_ASHP_Baseboard' is neither Electricity nor NaturalGas") if ((updated_heating_fuel != 'Electricity') && (updated_heating_fuel != 'NaturalGas'))
1351
+ # Set supplemental heating fuel for airloop
1352
+ sys_supp_htg_eqpt_type = 'coil_electric'
1353
+ sys_supp_htg_eqpt_type = 'coil_gas' if updated_heating_fuel == 'NaturalGas'
1198
1354
  systems = []
1199
1355
  system_zones_map.sort.each do |sys_name, zones|
1200
1356
  sys_info = air_sys_comps_assumptions(sys_name: sys_name,
@@ -1207,7 +1363,7 @@ class ECMS
1207
1363
  sys_vent_type: sys_info['sys_vent_type'],
1208
1364
  sys_heat_rec_type: sys_info['sys_heat_rec_type'],
1209
1365
  sys_htg_eqpt_type: 'ashp',
1210
- sys_supp_htg_eqpt_type: 'coil_electric',
1366
+ sys_supp_htg_eqpt_type: sys_supp_htg_eqpt_type,
1211
1367
  sys_clg_eqpt_type: 'ashp',
1212
1368
  sys_supp_fan_type: sys_info['sys_supp_fan_type'],
1213
1369
  sys_ret_fan_type: sys_info['sys_ret_fan_type'],
@@ -1290,6 +1446,8 @@ class ECMS
1290
1446
  htg_dx_coil = icomp.to_CoilHeatingDXSingleSpeed.get
1291
1447
  elsif icomp.to_CoilHeatingElectric.is_initialized
1292
1448
  backup_coil = icomp.to_CoilHeatingElectric.get
1449
+ elsif icomp.to_CoilHeatingGas.is_initialized
1450
+ backup_coil = icomp.to_CoilHeatingGas.get
1293
1451
  end
1294
1452
  end
1295
1453
  if clg_dx_coil && htg_dx_coil && backup_coil
@@ -1298,12 +1456,20 @@ class ECMS
1298
1456
  clg_dx_coil.setName(clg_dx_coil_init_name)
1299
1457
  if clg_dx_coil.autosizedRatedTotalCoolingCapacity.is_initialized
1300
1458
  clg_dx_coil_cap = clg_dx_coil.autosizedRatedTotalCoolingCapacity.to_f
1301
- else
1459
+ elsif clg_dx_coil.ratedTotalCoolingCapacity.is_initialized
1302
1460
  clg_dx_coil_cap = clg_dx_coil.ratedTotalCoolingCapacity.to_f
1461
+ else
1462
+ raise "Rated total cooling capacity is undefined for coil #{clg_dx_coil.name.to_s}"
1303
1463
  end
1304
1464
  htg_dx_coil_init_name = get_hvac_comp_init_name(htg_dx_coil, true)
1305
1465
  htg_dx_coil.setName(htg_dx_coil_init_name)
1306
- backup_coil_cap = backup_coil.autosizedNominalCapacity.to_f
1466
+ if backup_coil.autosizedNominalCapacity.is_initialized
1467
+ backup_coil_cap = backup_coil.autosizedNominalCapacity.to_f
1468
+ elsif backup_coil.nominalCapacity.is_initialized
1469
+ backup_coil_cap = backup_coil.nominalCapacity.to_f
1470
+ else
1471
+ raise "Nominal capacity is undefined for coil #{backup_coil.name.to_s}"
1472
+ end
1307
1473
  # set the DX capacities to the maximum of the fraction of the backup coil capacity or the cooling capacity needed
1308
1474
  dx_cap = fr_backup_coil_cap_as_dx_coil_cap * backup_coil_cap
1309
1475
  if dx_cap < clg_dx_coil_cap then dx_cap = clg_dx_coil_cap end
@@ -1323,11 +1489,17 @@ class ECMS
1323
1489
  # -Zonal VRF terminal units for heating and cooling with electric baseboards
1324
1490
  def add_ecm_hs13_ashp_vrf(model:,
1325
1491
  system_zones_map:,
1326
- system_doas_flags:)
1492
+ system_doas_flags:,
1493
+ ecm_system_zones_map_option:,
1494
+ standard:,
1495
+ heating_fuel:)
1327
1496
  # call method for ECM hs08 with ASHP in the air system
1328
1497
  add_ecm_hs08_ccashp_vrf(model: model,
1329
1498
  system_zones_map: system_zones_map,
1330
1499
  system_doas_flags: system_doas_flags,
1500
+ ecm_system_zones_map_option: ecm_system_zones_map_option,
1501
+ standard: standard,
1502
+ heating_fuel: heating_fuel,
1331
1503
  air_sys_eqpt_type: 'ashp')
1332
1504
  end
1333
1505
 
@@ -2451,7 +2623,7 @@ class ECMS
2451
2623
  else
2452
2624
  eff_measure_name = eff['name']
2453
2625
  end
2454
- new_boiler_name = boiler_primacy + eff_measure_name + " #{boiler_size_kbtu_per_hour.round(0)}kBtu/hr #{component.nominalThermalEfficiency} Thermal Eff"
2626
+ new_boiler_name = (boiler_primacy + eff_measure_name + " #{boiler_size_kbtu_per_hour.round(0)}kBtu/hr #{component.nominalThermalEfficiency} Thermal Eff").strip
2455
2627
  component.setName(new_boiler_name)
2456
2628
  end
2457
2629
 
@@ -2532,7 +2704,7 @@ class ECMS
2532
2704
  ecm_package_name = eff['name']
2533
2705
  end
2534
2706
  furnace_num = component.name.to_s.gsub(/[^0-9]/, '')
2535
- new_furnace_name = ecm_package_name + " #{furnace_num}"
2707
+ new_furnace_name = (ecm_package_name + " #{furnace_num}").strip
2536
2708
  component.setName(new_furnace_name)
2537
2709
  end
2538
2710
 
@@ -2629,7 +2801,7 @@ class ECMS
2629
2801
  else
2630
2802
  shw_ecm_package_name = eff['name']
2631
2803
  end
2632
- shw_name = "#{shw_vol_gal} Gal #{shw_ecm_package_name} Water Heater - #{shw_capacity_kBtu_hr}kBtu/hr #{eff['efficiency']} Therm Eff"
2804
+ shw_name = ("#{shw_vol_gal} Gal #{shw_ecm_package_name} Water Heater - #{shw_capacity_kBtu_hr}kBtu/hr #{eff['efficiency']} Therm Eff").strip
2633
2805
  component.setName(shw_name)
2634
2806
  end
2635
2807
 
@@ -2729,19 +2901,19 @@ class ECMS
2729
2901
  def add_ecm_remove_airloops_add_zone_baseboards(model:,
2730
2902
  system_zones_map:,
2731
2903
  system_doas_flags: nil,
2732
- zone_clg_eqpt_type: nil,
2904
+ ecm_system_zones_map_option:,
2733
2905
  standard:,
2734
- primary_heating_fuel:)
2906
+ heating_fuel:)
2735
2907
  # Set the primary fuel set to default to to specific fuel type.
2736
2908
  standards_info = standard.standards_data
2737
2909
 
2738
- if primary_heating_fuel == 'DefaultFuel'
2910
+ if heating_fuel == 'DefaultFuel'
2739
2911
  epw = BTAP::Environment::WeatherFile.new(model.weatherFile.get.path.get)
2740
- primary_heating_fuel = standards_info['regional_fuel_use'].detect { |fuel_sources| fuel_sources['state_province_regions'].include?(epw.state_province_region) }['fueltype_set']
2912
+ heating_fuel = standards_info['regional_fuel_use'].detect { |fuel_sources| fuel_sources['state_province_regions'].include?(epw.state_province_region) }['fueltype_set']
2741
2913
  end
2742
2914
  # Get fuelset.
2743
- system_fuel_defaults = standards_info['fuel_type_sets'].detect { |fuel_type_set| fuel_type_set['name'] == primary_heating_fuel }
2744
- raise("fuel_type_sets named #{primary_heating_fuel} not found in fuel_type_sets table.") if system_fuel_defaults.nil?
2915
+ system_fuel_defaults = standards_info['fuel_type_sets'].detect { |fuel_type_set| fuel_type_set['name'] == heating_fuel }
2916
+ raise("fuel_type_sets named #{heating_fuel} not found in fuel_type_sets table.") if system_fuel_defaults.nil?
2745
2917
 
2746
2918
  # Assign fuel sources.
2747
2919
  boiler_fueltype = system_fuel_defaults['boiler_fueltype']
@@ -90,4 +90,5 @@ class ECMS
90
90
  end
91
91
  end
92
92
  end
93
+
93
94
  end
@@ -69,7 +69,9 @@ class ECMS
69
69
  dc_system_capacity = pv_number_panels * pv_watt
70
70
  generator = OpenStudio::Model::GeneratorPVWatts.new(model, dc_system_capacity)
71
71
  generator.setModuleType(pv_ground_module_type)
72
- generator.setArrayType('OneAxis') # Note: "tilt and azimuth are fixed" for this array type (see E+ I/O Reference). This array type has been chosen as per Mike Lubun's costing spec.
72
+ # generator.setArrayType('OneAxis') # Note: "tilt and azimuth are fixed" for this array type (see E+ I/O Reference). This array type has been chosen as per Mike Lubun's costing spec.
73
+ generator.setArrayType('FixedOpenRack') # Note: The 'FixedOpenRack' array type has been used instead of 'OneAxis' since the 'OneAxis' array type did not allow to have a non-zero tilt angle in OpenStudio 3.2.1.
74
+ # (As per E+ I/O Reference: 'FixedOpenRack' is used for ground mounted arrays, assumes air flows freely around the array.)
73
75
  generator.setTiltAngle(pv_ground_tilt_angle)
74
76
  generator.setAzimuthAngle(pv_ground_azimuth_angle)
75
77
 
@@ -78,11 +80,11 @@ class ECMS
78
80
  inverter.setDCToACSizeRatio(1.1) # Note: This is EnergyPlus' default value; This default value has been chosen for ground-mounted PV, assuming no storage as per Mike Lubun's costing spec.
79
81
  inverter.setInverterEfficiency(0.96) # Note: This is EnergyPlus' default value; This default value has been chosen as per Mike Lubun's costing spec.
80
82
 
81
- ##### Get distribution systems and set relevant parameters
82
- model.getElectricLoadCenterDistributions.sort.each do |elc_distribution|
83
- elc_distribution.setInverter(inverter)
84
- elc_distribution.setGeneratorOperationSchemeType('Baseload') # E+ I/O Reference: "The Baseload scheme requests all generators scheduled ON (available) to operate, even if the amount of electric power generated exceeds the total facility electric power demand." This scheme type has been chosen as per Mike Lubun's costing spec.
85
- end
83
+ ##### Add distribution systems, set relevant parameters, and add created generator to it
84
+ elc_distribution = OpenStudio::Model::ElectricLoadCenterDistribution.new(model)
85
+ elc_distribution.setInverter(inverter)
86
+ elc_distribution.setGeneratorOperationSchemeType('Baseload') # E+ I/O Reference: "The Baseload scheme requests all generators scheduled ON (available) to operate, even if the amount of electric power generated exceeds the total facility electric power demand." This scheme type has been chosen as per Mike Lubun's costing spec.
87
+ elc_distribution.addGenerator(generator)
86
88
  end
87
89
 
88
90
  # Method for calculating footprint of the building model
@@ -93,7 +93,7 @@ class NECB2011
93
93
 
94
94
  # Organizes Zones and assigns them to appropriate systems according to NECB 2011-17 systems spacetype rules in Sec 8.
95
95
  # requires requires fuel type to be assigned for each system aspect. Defaults to gas hydronic.
96
- def apply_systems(model:, primary_heating_fuel:, sizing_run_dir:)
96
+ def apply_systems(model:, primary_heating_fuel:, sizing_run_dir:, shw_scale:, baseline_system_zones_map_option:)
97
97
  raise('validation of model failed.') unless validate_initial_model(model)
98
98
 
99
99
  # Check to see if model is using another vintage of spacetypes. If so overwrite the @standards for the object with the
@@ -151,7 +151,8 @@ class NECB2011
151
151
  heating_coil_type_sys6: heating_coil_type_sys6,
152
152
  mau_cooling_type: mau_cooling_type,
153
153
  mau_heating_coil_type: mau_heating_coil_type,
154
- mau_type: mau_type)
154
+ mau_type: mau_type,
155
+ baseline_system_zones_map_option: baseline_system_zones_map_option)
155
156
 
156
157
  # Assign a single system 4 for all wet spaces.. and assign the control zone to the one with the largest load.
157
158
  auto_system_wet_spaces(baseboard_type: baseboard_type,
@@ -181,8 +182,9 @@ class NECB2011
181
182
  heating_coil_type_sys6: heating_coil_type_sys6,
182
183
  mau_cooling_type: mau_cooling_type,
183
184
  mau_heating_coil_type: mau_heating_coil_type,
184
- mau_type: mau_type)
185
- model_add_swh(model: model, swh_fueltype: system_fuel_defaults['swh_fueltype'])
185
+ mau_type: mau_type
186
+ )
187
+ model_add_swh(model: model, swh_fueltype: system_fuel_defaults['swh_fueltype'], shw_scale: shw_scale)
186
188
  model_apply_sizing_parameters(model)
187
189
  # set a larger tolerance for unmet hours from default 0.2 to 1.0C
188
190
  model.getOutputControlReportingTolerances.setToleranceforTimeHeatingSetpointNotMet(1.0)
@@ -1000,8 +1002,8 @@ class NECB2011
1000
1002
  zones: zones)
1001
1003
  end
1002
1004
 
1003
- # This methos will ensure that all dwelling units are assigned to a system 1 or 3. There is an option to have a shared
1004
- # AHU or not. Currently set to false. So by default all dwelling units will have their own AHU.
1005
+ # This method will ensure that all dwelling units are assigned to a system 1 or 3.
1006
+ # There is an option to have a shared AHU or not.
1005
1007
 
1006
1008
  def auto_system_dwelling_units(baseboard_type:,
1007
1009
  boiler_fueltype:,
@@ -1014,11 +1016,16 @@ class NECB2011
1014
1016
  mau_cooling_type:,
1015
1017
  mau_heating_coil_type:,
1016
1018
  mau_type:,
1017
- model:)
1019
+ model:,
1020
+ baseline_system_zones_map_option:)
1018
1021
 
1019
1022
  system_zones_hash = {}
1020
- # Detemine if dwelling units have a shared AHU. If user entered building stories > 4 then set to true.
1021
- dwelling_shared_ahu = model.getBuilding.standardsNumberOfAboveGroundStories.get > 4
1023
+ # Determine if dwelling units have a shared AHU. If user entered building stories > 4 then set to true.
1024
+ if baseline_system_zones_map_option == 'one_sys_per_dwelling_unit'
1025
+ dwelling_shared_ahu = false
1026
+ elsif baseline_system_zones_map_option == 'one_sys_per_bldg' || baseline_system_zones_map_option == 'NECB_Default' || baseline_system_zones_map_option == 'none' || baseline_system_zones_map_option == nil
1027
+ dwelling_shared_ahu = true
1028
+ end
1022
1029
  # store dwelling zones into array
1023
1030
  zones = []
1024
1031
  model.getSpaces.select { |space| is_a_necb_dwelling_unit?(space) }.each do |space|