openstudio-standards 0.8.3 → 0.8.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. checksums.yaml +4 -4
  2. data/lib/openstudio-standards/btap/costing/README.md +502 -0
  3. data/lib/openstudio-standards/btap/costing/btap_costing.rb +473 -0
  4. data/lib/openstudio-standards/btap/costing/btap_measure_helper.rb +359 -0
  5. data/lib/openstudio-standards/btap/costing/btap_workflow.rb +117 -0
  6. data/lib/openstudio-standards/btap/costing/common_paths.rb +78 -0
  7. data/lib/openstudio-standards/btap/costing/common_resources/ConstructionProperties.csv +52 -0
  8. data/lib/openstudio-standards/btap/costing/common_resources/Constructions.csv +37 -0
  9. data/lib/openstudio-standards/btap/costing/common_resources/construction_sets.csv +1270 -0
  10. data/lib/openstudio-standards/btap/costing/common_resources/constructions_glazing.csv +61 -0
  11. data/lib/openstudio-standards/btap/costing/common_resources/constructions_opaque.csv +2256 -0
  12. data/lib/openstudio-standards/btap/costing/common_resources/costs.csv +1904 -0
  13. data/lib/openstudio-standards/btap/costing/common_resources/costs_local_factors.csv +2315 -0
  14. data/lib/openstudio-standards/btap/costing/common_resources/hvac_vent_ahu.csv +925 -0
  15. data/lib/openstudio-standards/btap/costing/common_resources/lighting.csv +364 -0
  16. data/lib/openstudio-standards/btap/costing/common_resources/lighting_sets.csv +2667 -0
  17. data/lib/openstudio-standards/btap/costing/common_resources/locations.csv +75 -0
  18. data/lib/openstudio-standards/btap/costing/common_resources/materials_glazing.csv +35 -0
  19. data/lib/openstudio-standards/btap/costing/common_resources/materials_hvac.csv +1699 -0
  20. data/lib/openstudio-standards/btap/costing/common_resources/materials_lighting.csv +267 -0
  21. data/lib/openstudio-standards/btap/costing/common_resources/materials_opaque.csv +164 -0
  22. data/lib/openstudio-standards/btap/costing/copy_test_results_files_to_expected_results.rb +11 -0
  23. data/lib/openstudio-standards/btap/costing/cost_building_from_file.rb +136 -0
  24. data/lib/openstudio-standards/btap/costing/costing_database_wrapper.rb +177 -0
  25. data/lib/openstudio-standards/btap/costing/daylighting_sensor_control_costing.rb +353 -0
  26. data/lib/openstudio-standards/btap/costing/dcv_costing.rb +314 -0
  27. data/lib/openstudio-standards/btap/costing/dummy.epw +8768 -0
  28. data/lib/openstudio-standards/btap/costing/dummy.osm +5320 -0
  29. data/lib/openstudio-standards/btap/costing/envelope_costing.rb +284 -0
  30. data/lib/openstudio-standards/btap/costing/heating_cooling_costing.rb +2584 -0
  31. data/lib/openstudio-standards/btap/costing/led_lighting_costing.rb +155 -0
  32. data/lib/openstudio-standards/btap/costing/lighting_costing.rb +209 -0
  33. data/lib/openstudio-standards/btap/costing/mech_sizing.json +502 -0
  34. data/lib/openstudio-standards/btap/costing/neb_end_use_prices.csv +42 -0
  35. data/lib/openstudio-standards/btap/costing/necb_2011_spacetype_info.csv +225 -0
  36. data/lib/openstudio-standards/btap/costing/necb_reference_runs.csv +28705 -0
  37. data/lib/openstudio-standards/btap/costing/nv_costing.rb +547 -0
  38. data/lib/openstudio-standards/btap/costing/parallel_tests.rb +92 -0
  39. data/lib/openstudio-standards/btap/costing/pv_ground_costing.rb +687 -0
  40. data/lib/openstudio-standards/btap/costing/shw_costing.rb +705 -0
  41. data/lib/openstudio-standards/btap/costing/test_list.txt +17 -0
  42. data/lib/openstudio-standards/btap/costing/test_run_all_test_locally.rb +26 -0
  43. data/lib/openstudio-standards/btap/costing/test_run_costing_tests.rb +80 -0
  44. data/lib/openstudio-standards/btap/costing/ventilation_costing.rb +2616 -0
  45. data/lib/openstudio-standards/constructions/modify.rb +2 -1
  46. data/lib/openstudio-standards/standards/Standards.Model.rb +39 -9
  47. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.Model.rb +2 -2
  48. data/lib/openstudio-standards/standards/ashrae_90_1_prm/userdata_csv/ashrae_90_1_prm.UserData.rb +6 -1
  49. data/lib/openstudio-standards/standards/necb/BTAPPRE1980/btap_pre1980.rb +2 -27
  50. data/lib/openstudio-standards/standards/necb/BTAPPRE1980/hvac_system_3_and_8_single_speed.rb +68 -27
  51. data/lib/openstudio-standards/standards/necb/BTAPPRE1980/hvac_system_4.rb +64 -25
  52. data/lib/openstudio-standards/standards/necb/BTAPPRE1980/hvac_system_6.rb +9 -14
  53. data/lib/openstudio-standards/standards/necb/ECMS/hvac_systems.rb +46 -20
  54. data/lib/openstudio-standards/standards/necb/NECB2011/autozone.rb +635 -248
  55. data/lib/openstudio-standards/standards/necb/NECB2011/data/constants.json +43 -7
  56. data/lib/openstudio-standards/standards/necb/NECB2011/data/fuel_type_sets.json +7 -1
  57. data/lib/openstudio-standards/standards/necb/NECB2011/data/geometry/HighriseApartmentMult.osm +14272 -0
  58. data/lib/openstudio-standards/standards/necb/NECB2011/data/necb_2015_table_c1.json +1 -1
  59. data/lib/openstudio-standards/standards/necb/NECB2011/data/space_types.json +437 -437
  60. data/lib/openstudio-standards/standards/necb/NECB2011/data/systems.json +516 -0
  61. data/lib/openstudio-standards/standards/necb/NECB2011/data/systems_including_sys5.json +588 -0
  62. data/lib/openstudio-standards/standards/necb/NECB2011/hvac_namer.rb +489 -0
  63. data/lib/openstudio-standards/standards/necb/NECB2011/hvac_system_1_single_speed.rb +16 -6
  64. data/lib/openstudio-standards/standards/necb/NECB2011/hvac_system_2_and_5.rb +48 -5
  65. data/lib/openstudio-standards/standards/necb/NECB2011/hvac_system_3_and_8_multi_speed.rb +2 -2
  66. data/lib/openstudio-standards/standards/necb/NECB2011/hvac_system_3_and_8_single_speed.rb +35 -27
  67. data/lib/openstudio-standards/standards/necb/NECB2011/hvac_system_4.rb +34 -23
  68. data/lib/openstudio-standards/standards/necb/NECB2011/hvac_system_6.rb +8 -6
  69. data/lib/openstudio-standards/standards/necb/NECB2011/hvac_systems.rb +42 -13
  70. data/lib/openstudio-standards/standards/necb/NECB2011/necb_2011.rb +214 -25
  71. data/lib/openstudio-standards/standards/necb/NECB2011/system_fuels.rb +61 -1
  72. data/lib/openstudio-standards/standards/necb/NECB2015/data/space_types.json +636 -636
  73. data/lib/openstudio-standards/standards/necb/NECB2015/data/unitary_acs.json +38 -38
  74. data/lib/openstudio-standards/standards/necb/NECB2015/hvac_systems.rb +15 -6
  75. data/lib/openstudio-standards/standards/necb/NECB2017/data/space_types.json +636 -636
  76. data/lib/openstudio-standards/standards/necb/NECB2020/data/chillers.json +71 -71
  77. data/lib/openstudio-standards/standards/necb/README.md +343 -0
  78. data/lib/openstudio-standards/standards/necb/common/btap_data.rb +190 -28
  79. data/lib/openstudio-standards/standards/necb/common/btap_datapoint.rb +14 -5
  80. data/lib/openstudio-standards/standards/necb/common/eccc_electric_grid_intensity_20250311.csv +14 -0
  81. data/lib/openstudio-standards/standards/necb/common/nir_gas_grid_intensity_20250311.csv +14 -0
  82. data/lib/openstudio-standards/standards/necb/common/system_types.yaml +0 -0
  83. data/lib/openstudio-standards/utilities/logging.rb +18 -14
  84. data/lib/openstudio-standards/version.rb +1 -1
  85. data/lib/openstudio-standards/weather/modify.rb +2 -2
  86. data/lib/openstudio-standards.rb +12 -0
  87. metadata +53 -2
@@ -347,7 +347,8 @@ module OpenstudioStandards
347
347
  return false
348
348
  end
349
349
  # Change construction name
350
- construction.setName("#{construction.name}_#{surface.name}_#{target_f_factor_ip}")
350
+ construction_name = "Foundation F #{f_factor_si.round(2)}W/m*K Perim #{perimeter.round(2)}m Area #{area.round(2)}m2"
351
+ construction.setName(construction_name)
351
352
  construction.setFFactor(f_factor_si)
352
353
  construction.setArea(area)
353
354
  construction.setPerimeterExposed(perimeter)
@@ -555,7 +555,7 @@ class Standard
555
555
  # the PRM-RM; Note that the PRM-RM only suggest to increase
556
556
  # air zone air flow, but the zone sizing factor in EnergyPlus
557
557
  # increase both air flow and load.
558
- umlh = OpenstudioStandards::SqlFile.model_get_annual_occupied_unmet_hours(proposed_model)
558
+ umlh = OpenstudioStandards::SqlFile.model_get_annual_occupied_unmet_hours(model)
559
559
  if umlh > 300
560
560
  model.getThermalZones.each do |thermal_zone|
561
561
  # Cooling adjustments
@@ -3054,11 +3054,24 @@ if !applicable_zones.nil? && !applicable_zones.include?(zone)
3054
3054
  # @return [OpenStudio::Model::Construction] construction object
3055
3055
  # @todo make return an OptionalConstruction
3056
3056
  def model_add_construction(model, construction_name, construction_props = nil, surface = nil)
3057
+ intended_surface_type = construction_props&.[]('intended_surface_type') || ''
3058
+
3057
3059
  # First check model and return construction if it already exists
3058
3060
  model.getConstructions.sort.each do |construction|
3059
3061
  if construction.name.get.to_s == construction_name
3060
3062
  OpenStudio.logFree(OpenStudio::Debug, 'openstudio.standards.Model', "Already added construction: #{construction_name}")
3061
- return construction
3063
+ valid = true
3064
+ if !surface.nil?
3065
+ if intended_surface_type == 'GroundContactFloor' && construction.iddObjectType.valueName != 'OS_Construction_FfactorGroundFloor'
3066
+ valid = false
3067
+ elsif intended_surface_type == 'GroundContactWall' && construction.iddObjectType.valueName != 'OS_Construction_CfactorUndergroundWall'
3068
+ valid = false
3069
+ end
3070
+ end
3071
+ if valid
3072
+ return construction
3073
+ end
3074
+ OpenStudio.logFree(OpenStudio::Warn, 'openstudio.standards.Model', "Already added construction: '#{construction_name}' but its type '#{construction.iddObjectType.valueName}' is not valid for the intended surface type '#{intended_surface_type}'. A new construction will be created.")
3062
3075
  end
3063
3076
  end
3064
3077
 
@@ -3076,12 +3089,31 @@ if !applicable_zones.nil? && !applicable_zones.include?(zone)
3076
3089
  return OpenStudio::Model::OptionalConstruction.new
3077
3090
  end
3078
3091
 
3092
+ intended_surface_type = data["intended_surface_type"]
3093
+ intended_surface_type ||= ''
3094
+
3079
3095
  # Make a new construction and set the standards details
3080
- if data['intended_surface_type'] == 'GroundContactFloor' && !surface.nil?
3081
- construction = OpenStudio::Model::FFactorGroundFloorConstruction.new(model)
3082
- elsif data['intended_surface_type'] == 'GroundContactWall' && !surface.nil?
3083
- construction = OpenStudio::Model::CFactorUndergroundWallConstruction.new(model)
3084
- else
3096
+ is_layered_construction = true
3097
+
3098
+ if intended_surface_type == 'GroundContactFloor' && !surface.nil?
3099
+ if construction_props
3100
+ construction = OpenStudio::Model::FFactorGroundFloorConstruction.new(model)
3101
+ is_layered_construction = false
3102
+ else
3103
+ OpenStudio.logFree(OpenStudio::Warn, 'openstudio.standards.Model', "Construction properties not specified for '#{construction_name}', cannot create F-Factor Ground Floor Construction. A regular construction will be created instead, and Surface '#{surface.name}' will be set to use the 'Ground' outside boundary condition (previously '#{surface.outsideBoundaryCondition}').")
3104
+ surface.setOutsideBoundaryCondition('Ground')
3105
+ end
3106
+ elsif intended_surface_type == 'GroundContactWall' && !surface.nil?
3107
+ if construction_props
3108
+ construction = OpenStudio::Model::CFactorUndergroundWallConstruction.new(model)
3109
+ is_layered_construction = false
3110
+ else
3111
+ OpenStudio.logFree(OpenStudio::Warn, 'openstudio.standards.Model', "Construction properties not specified for '#{construction_name}', cannot create C-Factor Underground Wall Construction. A regular construction will be created instead, and Surface '#{surface.name}' will be set to use the 'Ground' outside boundary condition (previously '#{surface.outsideBoundaryCondition}').")
3112
+ surface.setOutsideBoundaryCondition('Ground')
3113
+ end
3114
+ end
3115
+
3116
+ if is_layered_construction
3085
3117
  construction = OpenStudio::Model::Construction.new(model)
3086
3118
  # Add the material layers to the construction
3087
3119
  layers = OpenStudio::Model::MaterialVector.new
@@ -3096,8 +3128,6 @@ if !applicable_zones.nil? && !applicable_zones.include?(zone)
3096
3128
  construction.setName(construction_name)
3097
3129
  standards_info = construction.standardsInformation
3098
3130
 
3099
- intended_surface_type = data['intended_surface_type']
3100
- intended_surface_type ||= ''
3101
3131
  standards_info.setIntendedSurfaceType(intended_surface_type)
3102
3132
 
3103
3133
  standards_construction_type = data['standards_construction_type']
@@ -2071,7 +2071,8 @@ class ASHRAE901PRM < Standard
2071
2071
 
2072
2072
  if surfaces_with_fc_factor_boundary
2073
2073
  # Remove existing FCFactor temperature profile
2074
- model.getSiteGroundTemperatureFCfactorMethod.remove
2074
+ ground_temp = model.getSiteGroundTemperatureFCfactorMethod
2075
+ ground_temp.resetAllMonths
2075
2076
 
2076
2077
  # Get path to weather file specified in the model
2077
2078
  weather_file_path = prm_get_optional_handler(model.getWeatherFile, @sizing_run_dir, 'path').to_s
@@ -2089,7 +2090,6 @@ class ASHRAE901PRM < Standard
2089
2090
  stat_file_path = OpenstudioStandards::Weather.get_standards_weather_file_path(weather_file).sub('.epw', '.stat').to_s
2090
2091
  end
2091
2092
 
2092
- ground_temp = OpenStudio::Model::SiteGroundTemperatureFCfactorMethod.new(model)
2093
2093
  stat_file = OpenstudioStandards::Weather::StatFile.load(stat_file_path)
2094
2094
  ground_temperatures = stat_file.monthly_lagged_dry_bulb
2095
2095
  unless ground_temperatures.empty?
@@ -6,6 +6,7 @@ class UserDataCSV
6
6
  def initialize(model, save_dir)
7
7
  @model = model
8
8
  @component_name = nil
9
+ @unique_model_object = false
9
10
  unless Dir.exist?(save_dir)
10
11
  raise ArgumentError "Saving directory #{save_dir} does not exist!"
11
12
  end
@@ -70,6 +71,9 @@ class UserDataCSV
70
71
  # subclass shall determine what data group to extract from a modle.
71
72
  # @return [Array] array of OpenStudio components.
72
73
  def load_component
74
+ if @unique_model_object
75
+ return [@model.public_send("get#{@component_name}")]
76
+ end
73
77
  return @model.public_send("get#{@component_name}")
74
78
  end
75
79
  end
@@ -145,6 +149,7 @@ class UserDataCSVBuilding < UserDataCSV
145
149
  def initialize(model, save_dir)
146
150
  super
147
151
  @component_name = 'Building'
152
+ @unique_model_object = true
148
153
  @file_name = UserDataFiles::BUILDING
149
154
  end
150
155
 
@@ -274,7 +279,7 @@ class UserDataWaterUseConnection < UserDataCSV
274
279
  # @param save_dir [String] directory to save user data files
275
280
  def initialize(model, save_dir)
276
281
  super
277
- @component_name = 'WaterUseConnections'
282
+ @component_name = 'WaterUseConnectionss'
278
283
  @file_name = UserDataFiles::WATERUSE_CONNECTIONS
279
284
  end
280
285
 
@@ -64,10 +64,10 @@ class BTAPPRE1980 < NECB2011
64
64
  end
65
65
 
66
66
  def apply_standard_efficiencies(model:, sizing_run_dir:, dcv_type: 'NECB_Default', necb_reference_hp:false)
67
- raise('validation of model failed.') unless validate_initial_model(model)
67
+ # Do a sizing run
68
+ try_sizing_run(model: model, sizing_run_dir: sizing_run_dir, sizing_run_subdir: 'plant_loops')
68
69
 
69
70
  climate_zone = 'NECB HDD Method'
70
- raise("sizing run 1 failed! check #{sizing_run_dir}") if model_run_sizing_run(model, "#{sizing_run_dir}/plant_loops") == false
71
71
 
72
72
  # This is needed for NECB2011 as a workaround for sizing the reheat boxes
73
73
  model.getAirTerminalSingleDuctVAVReheats.each { |iobj| air_terminal_single_duct_vav_reheat_set_heating_cap(iobj) }
@@ -86,29 +86,4 @@ class BTAPPRE1980 < NECB2011
86
86
  return true
87
87
  end
88
88
 
89
- # This method sets the primary heating fuel to either NaturalGas or Electricity if a HP fuel type is set.
90
- def validate_primary_heating_fuel(primary_heating_fuel:, model:)
91
- if primary_heating_fuel.to_s.downcase == 'defaultfuel' || primary_heating_fuel.to_s.downcase == 'necb_default'
92
- epw = OpenStudio::EpwFile.new(model.weatherFile.get.path.get)
93
- default_fuel = @standards_data['regional_fuel_use'].detect { |fuel_sources| fuel_sources['state_province_regions'].include?(epw.stateProvinceRegion) }['fueltype_set']
94
- if default_fuel.nil?
95
- OpenStudio.logFree(OpenStudio::Warn, 'openstudio.standards.swh', "Could not find a default fuel for #{epw.stateProvinceRegion}. Using Electricity as the fuel type instead.")
96
- return 'Electricity'
97
- end
98
- return default_fuel
99
- end
100
- return primary_heating_fuel unless primary_heating_fuel == 'NaturalGasHPGasBackup' || primary_heating_fuel == 'NaturalGasHPElecBackupMixed' || primary_heating_fuel == 'ElectricityHPElecBackup' || primary_heating_fuel == 'ElectricityHPGasBackupMixed'
101
- case primary_heating_fuel
102
- when "NaturalGasHPGasBackup"
103
- primary_heating_fuel = 'NaturalGas'
104
- when "NaturalGasHPElecBackupMixed"
105
- primary_heating_fuel = 'NaturalGas'
106
- when "ElectricityHPElecBackup"
107
- primary_heating_fuel = 'Electricity'
108
- when "ElectricityHPGasBackupMixed"
109
- primary_heating_fuel = 'Electricity'
110
- end
111
- OpenStudio.logFree(OpenStudio::Info, 'openstudio.Standards.Model', "Attemted to apply an NECB HP primary_heating_fuel to a vintage building type. Replacing the selected primary_heating_fuel with #{primary_heating_fuel}.")
112
- return primary_heating_fuel
113
- end
114
89
  end
@@ -52,7 +52,10 @@ class BTAPPRE1980
52
52
  air_loop = add_system_3_and_8_airloop(heating_coil_type,
53
53
  model,
54
54
  system_data,
55
- determine_control_zone(zones))
55
+ determine_control_zone(zones),
56
+ necb_reference_hp: necb_reference_hp,
57
+ necb_reference_hp_supp_fuel: necb_reference_hp_supp_fuel,
58
+ hw_loop: hw_loop)
56
59
  # Add Zone equipment
57
60
  zones.each do |zone| # Zone sizing temperature
58
61
  sizing_zone = zone.sizingZone
@@ -60,8 +63,13 @@ class BTAPPRE1980
60
63
  sizing_zone.setZoneCoolingDesignSupplyAirTemperatureDifference(system_data[:ZoneCoolingDesignSupplyAirTemperatureDifference])
61
64
  sizing_zone.setZoneHeatingDesignSupplyAirTemperatureInputMethod(system_data[:ZoneHeatingDesignSupplyAirTemperatureInputMethod])
62
65
  sizing_zone.setZoneHeatingDesignSupplyAirTemperatureDifference(system_data[:ZoneHeatingDesignSupplyAirTemperatureDifference])
63
- sizing_zone.setZoneCoolingSizingFactor(system_data[:ZoneCoolingSizingFactor])
64
- sizing_zone.setZoneHeatingSizingFactor(system_data[:ZoneHeatingSizingFactor])
66
+ if necb_reference_hp
67
+ sizing_zone.setZoneCoolingSizingFactor(system_data[:ZoneDXCoolingSizingFactor])
68
+ sizing_zone.setZoneHeatingSizingFactor(system_data[:ZoneDXHeatingSizingFactor])
69
+ else
70
+ sizing_zone.setZoneCoolingSizingFactor(system_data[:ZoneCoolingSizingFactor])
71
+ sizing_zone.setZoneHeatingSizingFactor(system_data[:ZoneHeatingSizingFactor])
72
+ end
65
73
  add_sys3_and_8_zone_equip(air_loop,
66
74
  baseboard_type,
67
75
  hw_loop,
@@ -70,7 +78,7 @@ class BTAPPRE1980
70
78
  end
71
79
  else
72
80
  zones.each do |zone|
73
- air_loop = add_system_3_and_8_airloop(heating_coil_type, model, system_data, zone)
81
+ air_loop = add_system_3_and_8_airloop(heating_coil_type, model, system_data, zone, necb_reference_hp: necb_reference_hp, necb_reference_hp_supp_fuel: necb_reference_hp_supp_fuel, hw_loop: hw_loop)
74
82
  add_sys3_and_8_zone_equip(air_loop,
75
83
  baseboard_type,
76
84
  hw_loop,
@@ -83,19 +91,22 @@ class BTAPPRE1980
83
91
  sys_name_pars = {}
84
92
  sys_name_pars['sys_hr'] = 'none'
85
93
  sys_name_pars['sys_clg'] = 'dx'
94
+ sys_name_pars['sys_clg'] = 'ashp' if necb_reference_hp
86
95
  sys_name_pars['sys_htg'] = heating_coil_type
96
+ sys_name_pars['sys_htg'] = 'ashp>c-g' if necb_reference_hp && (necb_reference_hp_supp_fuel == "NaturalGas" || necb_reference_hp_supp_fuel == "Gas")
97
+ sys_name_pars['sys_htg'] = 'ashp>c-e' if necb_reference_hp && (necb_reference_hp_supp_fuel == "Electricity" || necb_reference_hp_supp_fuel == "Electric" || necb_reference_hp_supp_fuel == "FuelOilNo2")
98
+ sys_name_pars['sys_htg'] = 'ashp>c-hw' if necb_reference_hp && (necb_reference_hp_supp_fuel == "Hot Water" || necb_reference_hp_supp_fuel == "HotWater")
87
99
  sys_name_pars['sys_sf'] = 'cv'
88
100
  sys_name_pars['zone_htg'] = baseboard_type
89
101
  sys_name_pars['zone_clg'] = 'none'
90
102
  sys_name_pars['sys_rf'] = 'none'
91
- assign_base_sys_name(air_loop,
103
+ return assign_base_sys_name(air_loop: air_loop,
92
104
  sys_abbr: 'sys_3',
93
105
  sys_oa: 'mixed',
94
106
  sys_name_pars: sys_name_pars)
95
- return true
96
107
  end
97
108
 
98
- def add_system_3_and_8_airloop(heating_coil_type, model, system_data, control_zone)
109
+ def add_system_3_and_8_airloop(heating_coil_type, model, system_data, control_zone, necb_reference_hp:false, necb_reference_hp_supp_fuel:'DefaultFuel', necb_reference_hp_fancoil: false, hw_loop: nil)
99
110
  # System Type 3: PSZ-AC
100
111
  # This measure creates:
101
112
  # -a constant volume packaged single-zone A/C unit
@@ -118,25 +129,43 @@ class BTAPPRE1980
118
129
  sizing_zone.setZoneCoolingDesignSupplyAirTemperatureDifference(system_data[:ZoneCoolingDesignSupplyAirTemperatureDifference])
119
130
  sizing_zone.setZoneHeatingDesignSupplyAirTemperatureInputMethod(system_data[:ZoneHeatingDesignSupplyAirTemperatureInputMethod])
120
131
  sizing_zone.setZoneHeatingDesignSupplyAirTemperatureDifference(system_data[:ZoneHeatingDesignSupplyAirTemperatureDifference])
121
- sizing_zone.setZoneCoolingSizingFactor(system_data[:ZoneCoolingSizingFactor])
122
- sizing_zone.setZoneHeatingSizingFactor(system_data[:ZoneHeatingSizingFactor])
132
+ if necb_reference_hp
133
+ sizing_zone.setZoneCoolingSizingFactor(system_data[:ZoneDXCoolingSizingFactor])
134
+ sizing_zone.setZoneHeatingSizingFactor(system_data[:ZoneDXHeatingSizingFactor])
135
+ else
136
+ sizing_zone.setZoneCoolingSizingFactor(system_data[:ZoneCoolingSizingFactor])
137
+ sizing_zone.setZoneHeatingSizingFactor(system_data[:ZoneHeatingSizingFactor])
138
+ end
123
139
 
124
140
  fan = OpenStudio::Model::FanConstantVolume.new(model, always_on)
125
141
 
142
+ # Set up DX coil
143
+ if necb_reference_hp #NECB curve characteristics
144
+ clg_coil = add_onespeed_DX_coil(model, always_on)
145
+ clg_coil.setName('CoilCoolingDXSingleSpeed_ashp')
146
+ else
147
+ clg_coil = OpenStudio::Model::CoilCoolingDXSingleSpeed.new(model) #sets default OS curve (but will be replaced with NECB curves later)
148
+ clg_coil.setName('CoilCoolingDXSingleSpeed_dx')
149
+ end
126
150
  # Create a return fan for BTAPPRE1980 system 3 systems
127
151
  return_fan = OpenStudio::Model::FanConstantVolume.new(model, always_on)
128
152
  return_fan.setName('Sys3 Return Fan')
129
153
  return_fan.setEndUseSubcategory('Return_Fan')
130
154
 
155
+ raise("Flag 'necb_reference_hp' is set to true while parameter 'heating_coil_type' is not set to DX") if (necb_reference_hp && (heating_coil_type != 'DX'))
131
156
  case heating_coil_type
132
- when 'Electric' # electric coil
157
+ when 'Electric', 'Electricity', "FuelOilNo2" # electric coil
133
158
  htg_coil = OpenStudio::Model::CoilHeatingElectric.new(model, always_on)
134
- when 'Gas'
159
+ when 'Gas', 'NaturalGas'
135
160
  htg_coil = OpenStudio::Model::CoilHeatingGas.new(model, always_on)
161
+ when 'Hot Water', 'HotWater'
162
+ htg_coil = OpenStudio::Model::CoilHeatingWater.new(model, always_on)
163
+ hw_loop.addDemandBranchForComponent(htg_coil)
136
164
  when 'DX'
137
- htg_coil = OpenStudio::Model::CoilHeatingDXSingleSpeed.new(model)
138
- supplemental_htg_coil = OpenStudio::Model::CoilHeatingElectric.new(model, always_on)
165
+ #create main DX heating coil
166
+ htg_coil = add_onespeed_htg_DX_coil(model, always_on)
139
167
  htg_coil.setMinimumOutdoorDryBulbTemperatureforCompressorOperation(system_data[:MinimumOutdoorDryBulbTemperatureforCompressorOperation])
168
+ htg_coil.setName('CoilHeatingDXSingleSpeed_ashp')
140
169
  sizing_zone.setZoneHeatingSizingFactor(system_data[:ZoneDXHeatingSizingFactor])
141
170
  sizing_zone.setZoneCoolingSizingFactor(system_data[:ZoneDXCoolingSizingFactor])
142
171
  else
@@ -145,9 +174,7 @@ class BTAPPRE1980
145
174
 
146
175
  # TO DO: other fuel-fired heating coil types? (not available in OpenStudio/E+ - may need to play with efficiency to mimic other fuel types)
147
176
 
148
- # Set up DX coil with NECB performance curve characteristics;
149
- clg_coil = OpenStudio::Model::CoilCoolingDXSingleSpeed.new(model)
150
- clg_coil.setName('CoilCoolingDXSingleSpeed_dx')
177
+
151
178
 
152
179
  # oa_controller
153
180
  oa_controller = OpenStudio::Model::ControllerOutdoorAir.new(model)
@@ -163,17 +190,31 @@ class BTAPPRE1980
163
190
  # Add the components to the air loop
164
191
  # in order from closest to zone to furthest from zone
165
192
  supply_inlet_node = air_loop.supplyInletNode
166
- if heating_coil_type == 'DX'
167
- air_to_air_heatpump = OpenStudio::Model::AirLoopHVACUnitaryHeatPumpAirToAir.new(model, always_on, fan, htg_coil, clg_coil, supplemental_htg_coil)
168
- air_to_air_heatpump.setName("#{control_zone.name} ASHP")
169
- air_to_air_heatpump.setControllingZone(control_zone)
170
- air_to_air_heatpump.setSupplyAirFanOperatingModeSchedule(always_on)
171
- air_to_air_heatpump.addToNode(supply_inlet_node)
172
- else
173
- fan.addToNode(supply_inlet_node)
174
- htg_coil.addToNode(supply_inlet_node)
175
- clg_coil.addToNode(supply_inlet_node)
193
+ fan.addToNode(supply_inlet_node)
194
+ if necb_reference_hp
195
+ #create supplemental heating coil based on default regional fuel type
196
+ if necb_reference_hp_supp_fuel == 'DefaultFuel'
197
+ epw = OpenStudio::EpwFile.new(model.weatherFile.get.path.get)
198
+ necb_reference_hp_supp_fuel = @standards_data['regional_fuel_use'].detect { |fuel_sources| fuel_sources['state_province_regions'].include?(epw.stateProvinceRegion) }['fueltype_set']
199
+ end
200
+ if necb_reference_hp_supp_fuel == 'NaturalGas' || necb_reference_hp_supp_fuel == 'Gas'
201
+ supplemental_htg_coil = OpenStudio::Model::CoilHeatingGas.new(model, always_on)
202
+ elsif necb_reference_hp_supp_fuel == 'Electricity' || necb_reference_hp_supp_fuel == 'Electric' || necb_reference_hp_supp_fuel == 'FuelOilNo2'
203
+ supplemental_htg_coil = OpenStudio::Model::CoilHeatingElectric.new(model, always_on)
204
+ elsif necb_reference_hp_supp_fuel == 'Hot Water' || necb_reference_hp_supp_fuel == "HotWater"
205
+ supplemental_htg_coil = OpenStudio::Model::CoilHeatingWater.new(model, always_on)
206
+ hw_loop.addDemandBranchForComponent(supplemental_htg_coil)
207
+ else
208
+ raise('Invalid fuel type selected for heat pump supplemental coil')
209
+ end
210
+ #air_to_air_heatpump.setName("#{control_zone.name} ASHP")
211
+ #air_to_air_heatpump.setControllingZone(control_zone)
212
+ #air_to_air_heatpump.setSupplyAirFanOperatingModeSchedule(always_on)
213
+ #air_to_air_heatpump.addToNode(supply_inlet_node)
214
+ supplemental_htg_coil.addToNode(supply_inlet_node)
176
215
  end
216
+ htg_coil.addToNode(supply_inlet_node)
217
+ clg_coil.addToNode(supply_inlet_node)
177
218
  oa_system.addToNode(supply_inlet_node)
178
219
 
179
220
  # Find return air node and add a return air fan to it for BTAPPRE1980 system 3 airloops.
@@ -195,8 +236,8 @@ class BTAPPRE1980
195
236
  hw_loop, model,
196
237
  zone)
197
238
  always_on = model.alwaysOnDiscreteSchedule
239
+ add_zone_baseboards(baseboard_type: baseboard_type, hw_loop: hw_loop, model: model, zone: zone)
198
240
  diffuser = OpenStudio::Model::AirTerminalSingleDuctUncontrolled.new(model, always_on)
199
241
  air_loop.addBranchForZone(zone, diffuser.to_StraightComponent)
200
- add_zone_baseboards(baseboard_type: baseboard_type, hw_loop: hw_loop, model: model, zone: zone)
201
242
  end
202
243
  end
@@ -37,6 +37,9 @@ class BTAPPRE1980
37
37
  system_data[:ZoneCoolingDesignSupplyAirTemperatureDifference] = 11.0
38
38
  system_data[:ZoneHeatingDesignSupplyAirTemperatureInputMethod] = 'TemperatureDifference'
39
39
  system_data[:ZoneHeatingDesignSupplyAirTemperatureDifference] = 21.0
40
+ system_data[:ZoneHeatingDesignSupplyAirTemperature] = 43.0
41
+ system_data[:ZoneDXCoolingSizingFactor] = 1.0
42
+ system_data[:ZoneDXHeatingSizingFactor] = 1.3
40
43
  system_data[:ZoneCoolingSizingFactor] = 1.1
41
44
  system_data[:ZoneHeatingSizingFactor] = 1.3
42
45
 
@@ -53,9 +56,7 @@ class BTAPPRE1980
53
56
  # NOTE: This is the same as system type 3 (single zone make-up air unit and single zone rooftop unit are both PSZ systems)
54
57
  # SHOULD WE COMBINE sys3 and sys4 into one script?
55
58
  #
56
- # control_zone = determine_control_zone(zones)
57
- # Todo change this when control zone method is working.
58
- control_zone = zones.first
59
+ control_zone = determine_control_zone(zones)
59
60
 
60
61
  always_on = model.alwaysOnDiscreteSchedule
61
62
 
@@ -73,27 +74,37 @@ class BTAPPRE1980
73
74
  sizing_zone.setZoneCoolingDesignSupplyAirTemperatureInputMethod(system_data[:ZoneCoolingDesignSupplyAirTemperatureInputMethod])
74
75
  sizing_zone.setZoneCoolingDesignSupplyAirTemperatureDifference(system_data[:ZoneCoolingDesignSupplyAirTemperatureDifference])
75
76
  sizing_zone.setZoneHeatingDesignSupplyAirTemperatureInputMethod(system_data[:ZoneHeatingDesignSupplyAirTemperatureInputMethod])
76
- sizing_zone.setZoneHeatingDesignSupplyAirTemperatureDifference(system_data[:ZoneHeatingDesignSupplyAirTemperatureDifference])
77
- sizing_zone.setZoneCoolingSizingFactor(system_data[:ZoneCoolingSizingFactor])
78
- sizing_zone.setZoneHeatingSizingFactor(system_data[:ZoneHeatingSizingFactor])
77
+ sizing_zone.setZoneCoolingDesignSupplyAirTemperatureDifference(system_data[:ZoneHeatingDesignSupplyAirTemperatureDifference])
78
+ if necb_reference_hp
79
+ sizing_zone.setZoneCoolingSizingFactor(system_data[:ZoneDXCoolingSizingFactor])
80
+ sizing_zone.setZoneHeatingSizingFactor(system_data[:ZoneDXHeatingSizingFactor])
81
+ else
82
+ sizing_zone.setZoneCoolingSizingFactor(system_data[:ZoneCoolingSizingFactor])
83
+ sizing_zone.setZoneHeatingSizingFactor(system_data[:ZoneHeatingSizingFactor])
84
+ end
79
85
 
80
86
  fan = OpenStudio::Model::FanConstantVolume.new(model, always_on)
81
87
 
82
- if heating_coil_type == 'Electric' # electric coil
83
- htg_coil = OpenStudio::Model::CoilHeatingElectric.new(model, always_on)
84
- end
88
+ # Set up DX coil with NECB performance curve characteristics;
89
+ clg_coil = add_onespeed_DX_coil(model, always_on)
90
+ clg_coil.setName('CoilCoolingDXSingleSpeed_dx')
91
+ clg_coil.setName('CoilCoolingDXSingleSpeed_ashp') if necb_reference_hp
85
92
 
86
- if heating_coil_type == 'Gas'
93
+ raise("Flag 'necb_reference_hp' is set to true while parameter 'heating_coil_type' is not set to DX") if (necb_reference_hp && (heating_coil_type != 'DX'))
94
+ if heating_coil_type == 'Electric' || heating_coil_type == 'FuelOilNo2' # electric coil
95
+ htg_coil = OpenStudio::Model::CoilHeatingElectric.new(model, always_on)
96
+ elsif heating_coil_type == 'Gas'
87
97
  htg_coil = OpenStudio::Model::CoilHeatingGas.new(model, always_on)
98
+ elsif heating_coil_type == 'DX'
99
+ htg_coil = add_onespeed_htg_DX_coil(model, always_on)
100
+ htg_coil.setName('CoilHeatingDXSingleSpeed_ashp')
101
+ elsif heating_coil_type == 'Hot Water'
102
+ htg_coil = OpenStudio::Model::CoilHeatingWater.new(model, always_on)
103
+ hw_loop.addDemandBranchForComponent(htg_coil)
88
104
  end
89
105
 
90
106
  # TO DO: other fuel-fired heating coil types? (not available in OpenStudio/E+ - may need to play with efficiency to mimic other fuel types)
91
107
 
92
- # Set up DX coil with NECB performance curve characteristics;
93
-
94
- clg_coil = add_onespeed_DX_coil(model, always_on)
95
- clg_coil.setName('CoilCoolingDXSingleSpeed_dx')
96
-
97
108
  # oa_controller
98
109
  oa_controller = OpenStudio::Model::ControllerOutdoorAir.new(model)
99
110
  oa_controller.autosizeMinimumOutdoorAirFlowRate
@@ -109,10 +120,33 @@ class BTAPPRE1980
109
120
  # in order from closest to zone to furthest from zone
110
121
  supply_inlet_node = air_loop.supplyInletNode
111
122
  fan.addToNode(supply_inlet_node)
123
+ if necb_reference_hp
124
+ #create supplemental heating coil based on default regional fuel type
125
+ if necb_reference_hp_supp_fuel == 'DefaultFuel'
126
+ epw = OpenStudio::EpwFile.new(model.weatherFile.get.path.get)
127
+ necb_reference_hp_supp_fuel = @standards_data['regional_fuel_use'].detect { |fuel_sources| fuel_sources['state_province_regions'].include?(epw.stateProvinceRegion) }['fueltype_set']
128
+ end
129
+ if necb_reference_hp_supp_fuel == 'NaturalGas'
130
+ supplemental_htg_coil = OpenStudio::Model::CoilHeatingGas.new(model, always_on)
131
+ elsif necb_reference_hp_supp_fuel == 'Electricity' or necb_reference_hp_supp_fuel == 'FuelOilNo2'
132
+ supplemental_htg_coil = OpenStudio::Model::CoilHeatingElectric.new(model, always_on)
133
+ elsif necb_reference_hp_supp_fuel == 'Hot Water'
134
+ supplemental_htg_coil = OpenStudio::Model::CoilHeatingWater.new(model, always_on)
135
+ hw_loop.addDemandBranchForComponent(supplemental_htg_coil)
136
+ else
137
+ raise('Invalid fuel type selected for heat pump supplemental coil')
138
+ end
139
+ supplemental_htg_coil.addToNode(supply_inlet_node)
140
+ # This method will seem like an error in number of args..but this is due to swig voodoo.
141
+ #air_to_air_heatpump = OpenStudio::Model::AirLoopHVACUnitaryHeatPumpAirToAir.new(model, always_on, fan, htg_coil, clg_coil, supplemental_htg_coil)
142
+ #air_to_air_heatpump.setName("#{control_zone.name} ASHP")
143
+ #air_to_air_heatpump.setControllingZone(control_zone)
144
+ #air_to_air_heatpump.setSupplyAirFanOperatingModeSchedule(always_on)
145
+ #air_to_air_heatpump.addToNode(supply_inlet_node)
146
+ end
112
147
  htg_coil.addToNode(supply_inlet_node)
113
148
  clg_coil.addToNode(supply_inlet_node)
114
149
  oa_system.addToNode(supply_inlet_node)
115
-
116
150
  # Add a setpoint manager single zone reheat to control the
117
151
  # supply air temperature based on the needs of this zone
118
152
  setpoint_mgr_single_zone_reheat = OpenStudio::Model::SetpointManagerSingleZoneReheat.new(model)
@@ -144,34 +178,39 @@ class BTAPPRE1980
144
178
  sizing_zone.setZoneCoolingDesignSupplyAirTemperatureDifference(system_data[:ZoneCoolingDesignSupplyAirTemperatureDifference])
145
179
  sizing_zone.setZoneHeatingDesignSupplyAirTemperatureInputMethod(system_data[:ZoneHeatingDesignSupplyAirTemperatureInputMethod])
146
180
  sizing_zone.setZoneHeatingDesignSupplyAirTemperatureDifference(system_data[:ZoneHeatingDesignSupplyAirTemperatureDifference])
147
- sizing_zone.setZoneCoolingSizingFactor(system_data[:ZoneCoolingSizingFactor])
148
- sizing_zone.setZoneHeatingSizingFactor(system_data[:ZoneHeatingSizingFactor])
181
+ if necb_reference_hp
182
+ sizing_zone.setZoneCoolingSizingFactor(system_data[:ZoneDXCoolingSizingFactor])
183
+ sizing_zone.setZoneHeatingSizingFactor(system_data[:ZoneDXHeatingSizingFactor])
184
+ else
185
+ sizing_zone.setZoneCoolingSizingFactor(system_data[:ZoneCoolingSizingFactor])
186
+ sizing_zone.setZoneHeatingSizingFactor(system_data[:ZoneHeatingSizingFactor])
187
+ end
149
188
  # Create a diffuser and attach the zone/diffuser pair to the air loop
150
189
  # diffuser = OpenStudio::Model::AirTerminalSingleDuctUncontrolled.new(model,always_on)
151
- diffuser = OpenStudio::Model::AirTerminalSingleDuctUncontrolled.new(model, always_on)
152
- air_loop.addBranchForZone(zone, diffuser.to_StraightComponent)
153
190
  add_zone_baseboards(baseboard_type: baseboard_type,
154
191
  hw_loop: hw_loop,
155
192
  model: model,
156
193
  zone: zone)
157
194
  add_exhaust_fan(zone: zone, model: model, name: exhaust_fan_name)
195
+ diffuser = OpenStudio::Model::AirTerminalSingleDuctUncontrolled.new(model, always_on)
196
+ air_loop.addBranchForZone(zone, diffuser.to_StraightComponent)
158
197
  end
159
- # zone loop
160
-
161
- # Modifying airloop name
162
198
  sys_name_pars = {}
163
199
  sys_name_pars['sys_hr'] = 'none'
164
200
  sys_name_pars['sys_clg'] = 'dx'
201
+ sys_name_pars['sys_clg'] = 'ashp' if necb_reference_hp
165
202
  sys_name_pars['sys_htg'] = heating_coil_type
203
+ sys_name_pars['sys_htg'] = 'ashp>c-g' if necb_reference_hp and necb_reference_hp_supp_fuel == "NaturalGas"
204
+ sys_name_pars['sys_htg'] = 'ashp>c-e' if necb_reference_hp and necb_reference_hp_supp_fuel == "Electricity"
205
+ sys_name_pars['sys_htg'] = 'ashp>c-hw' if necb_reference_hp and necb_reference_hp_supp_fuel == "Hot Water"
166
206
  sys_name_pars['sys_sf'] = 'cv'
167
207
  sys_name_pars['zone_htg'] = baseboard_type
168
208
  sys_name_pars['zone_clg'] = 'none'
169
209
  sys_name_pars['sys_rf'] = 'none'
170
- assign_base_sys_name(air_loop,
210
+ return assign_base_sys_name(air_loop: air_loop,
171
211
  sys_abbr: 'sys_4',
172
212
  sys_oa: 'mixed',
173
213
  sys_name_pars: sys_name_pars)
174
214
 
175
- return true
176
215
  end
177
216
  end
@@ -131,18 +131,18 @@ class BTAPPRE1980
131
131
  reheat_coil = OpenStudio::Model::CoilHeatingElectric.new(model, always_on)
132
132
  end
133
133
 
134
+ # Set zone baseboards
135
+ add_zone_baseboards(model: model,
136
+ zone: zone,
137
+ baseboard_type: baseboard_type,
138
+ hw_loop: hw_loop)
139
+
134
140
  vav_terminal = OpenStudio::Model::AirTerminalSingleDuctVAVReheat.new(model, always_on, reheat_coil)
135
141
  air_loop.addBranchForZone(zone, vav_terminal.to_StraightComponent)
136
142
  # NECB2011 minimum zone airflow setting
137
143
  vav_terminal.setFixedMinimumAirFlowRate(system_data[:ZoneVAVMinFlowFactorPerFloorArea] * zone.floorArea)
138
144
  vav_terminal.setMaximumReheatAirTemperature(system_data[:ZoneVAVMaxReheatTemp])
139
145
  vav_terminal.setDamperHeatingAction(system_data[:ZoneVAVDamperAction])
140
-
141
- # Set zone baseboards
142
- add_zone_baseboards(model: model,
143
- zone: zone,
144
- baseboard_type: baseboard_type,
145
- hw_loop: hw_loop)
146
146
  end
147
147
 
148
148
  # Modifying airloop name.
@@ -154,17 +154,15 @@ class BTAPPRE1980
154
154
  sys_name_pars['zone_htg'] = baseboard_type
155
155
  sys_name_pars['zone_clg'] = 'none'
156
156
  sys_name_pars['sys_rf'] = 'vv'
157
- assign_base_sys_name(air_loop,
157
+ assign_base_sys_name(air_loop: air_loop,
158
158
  sys_abbr: 'sys_6',
159
159
  sys_oa: 'mixed',
160
160
  sys_name_pars: sys_name_pars)
161
161
  end
162
+ # next story
162
163
  end
163
- # next story
164
-
165
164
  # for debugging
166
165
  # puts "end add_sys6_multi_zone_built_up_with_baseboard_heating"
167
-
168
166
  return true
169
167
  end
170
168
 
@@ -227,7 +225,6 @@ class BTAPPRE1980
227
225
  # Make a Packaged VAV w/ PFP Boxes for each story of the building
228
226
  model.getBuildingStorys.sort.each do |story|
229
227
  unless (OpenstudioStandards::Geometry.building_story_get_thermal_zones(story) & zones).empty?
230
-
231
228
  air_loop = common_air_loop(model: model, system_data: system_data)
232
229
  air_loop.setName(system_data[:name])
233
230
  air_loop_sizing = air_loop.sizingSystem
@@ -323,12 +320,10 @@ class BTAPPRE1980
323
320
  hw_loop: hw_loop)
324
321
  end
325
322
  end
323
+ # next story
326
324
  end
327
- # next story
328
-
329
325
  # for debugging
330
326
  # puts "end add_sys6_multi_zone_built_up_with_baseboard_heating"
331
-
332
327
  return true
333
328
  end
334
329
  end