openstudio-standards 0.8.5 → 0.8.7

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 (174) hide show
  1. checksums.yaml +4 -4
  2. data/data/standards/test_performance_expected_dd_results.csv +90 -90
  3. data/lib/openstudio-standards/btap/activity.rb +858 -61
  4. data/lib/openstudio-standards/btap/attributes.rb +297 -103
  5. data/lib/openstudio-standards/btap/bridging.rb +1335 -593
  6. data/lib/openstudio-standards/btap/btap.rb +60 -181
  7. data/lib/openstudio-standards/btap/carbon/btap_carbon.rb +199 -142
  8. data/lib/openstudio-standards/btap/common/constructions.json +1275 -0
  9. data/lib/openstudio-standards/btap/common/costs.csv +1969 -0
  10. data/lib/openstudio-standards/btap/common/costs_local_factors.csv +2315 -0
  11. data/lib/openstudio-standards/btap/common/materials_glazing.csv +61 -0
  12. data/lib/openstudio-standards/btap/{common_resources → common}/materials_hvac.csv +1685 -1685
  13. data/lib/openstudio-standards/btap/{common_resources → common}/materials_lighting.csv +266 -266
  14. data/lib/openstudio-standards/btap/common/materials_opaque.csv +214 -0
  15. data/lib/openstudio-standards/btap/common/necb_building_types.csv +35 -0
  16. data/lib/openstudio-standards/btap/common/necb_space_types.csv +110 -0
  17. data/lib/openstudio-standards/btap/common/thermal_bridging.csv +73 -0
  18. data/lib/openstudio-standards/btap/costing/btap_costing.rb +346 -429
  19. data/lib/openstudio-standards/btap/costing/database.rb +104 -0
  20. data/lib/openstudio-standards/btap/costing/daylighting_sensor_control_costing.rb +356 -344
  21. data/lib/openstudio-standards/btap/costing/dcv_costing.rb +282 -296
  22. data/lib/openstudio-standards/btap/costing/envelope_costing.rb +179 -192
  23. data/lib/openstudio-standards/btap/costing/heating_cooling_costing.rb +2477 -2316
  24. data/lib/openstudio-standards/btap/costing/led_lighting_costing.rb +127 -142
  25. data/lib/openstudio-standards/btap/costing/lighting_costing.rb +216 -198
  26. data/lib/openstudio-standards/btap/costing/nv_costing.rb +522 -523
  27. data/lib/openstudio-standards/btap/costing/pv_ground_costing.rb +649 -649
  28. data/lib/openstudio-standards/btap/costing/shw_costing.rb +626 -625
  29. data/lib/openstudio-standards/btap/costing/thermal_bridging_costing.rb +72 -0
  30. data/lib/openstudio-standards/btap/costing/ventilation_costing.rb +2363 -2361
  31. data/lib/openstudio-standards/btap/deprecated.rb +1033 -0
  32. data/lib/openstudio-standards/btap/envelope.rb +313 -572
  33. data/lib/openstudio-standards/btap/fileio.rb +152 -1070
  34. data/lib/openstudio-standards/btap/geometry.rb +486 -766
  35. data/lib/openstudio-standards/btap/linear_regression.rb +130 -0
  36. data/lib/openstudio-standards/btap/paths.rb +46 -0
  37. data/lib/openstudio-standards/btap/qaqc/analysis.rb +163 -0
  38. data/lib/openstudio-standards/btap/qaqc/data.rb +2293 -0
  39. data/lib/openstudio-standards/btap/qaqc/datapoint.rb +641 -0
  40. data/lib/openstudio-standards/btap/schedules.rb +11 -611
  41. data/lib/openstudio-standards/btap/structure.rb +574 -189
  42. data/lib/openstudio-standards/constructions/materials/information.rb +1 -1
  43. data/lib/openstudio-standards/create_typical/create_typical.rb +1 -1
  44. data/lib/openstudio-standards/exterior_lighting/create.rb +135 -85
  45. data/lib/openstudio-standards/exterior_lighting/data/typical_exterior_lighting.json +20 -0
  46. data/lib/openstudio-standards/exterior_lighting/information.rb +23 -2
  47. data/lib/openstudio-standards/geometry/create.rb +7 -3
  48. data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2016/ashrae_90_1_2016.Model.rb +3 -2
  49. data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.Model.rb +3 -2
  50. data/lib/openstudio-standards/prototypes/common/data/thermostat_schedule_lookup.json +84 -84
  51. data/lib/openstudio-standards/prototypes/common/objects/Prototype.hvac_systems.rb +4 -4
  52. data/lib/openstudio-standards/refrigeration/create_walkin.rb +45 -5
  53. data/lib/openstudio-standards/refrigeration/data/refrigerated_walkins.csv +75 -75
  54. data/lib/openstudio-standards/schedules/parametric.rb +6 -0
  55. data/lib/openstudio-standards/service_water_heating/create_typical.rb +10 -3
  56. data/lib/openstudio-standards/service_water_heating/create_water_heating_loop.rb +30 -14
  57. data/lib/openstudio-standards/service_water_heating/information.rb +4 -1
  58. data/lib/openstudio-standards/sql_file/unmet_hours.rb +2 -1
  59. data/lib/openstudio-standards/standards/Standards.CoilCoolingDXSingleSpeed.rb +3 -1
  60. data/lib/openstudio-standards/standards/Standards.CoilHeatingDXSingleSpeed.rb +3 -1
  61. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2004/data/ashrae_90_1_2004.boilers.json +12 -0
  62. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2004/data/ashrae_90_1_2004.construction_properties.json +18432 -3072
  63. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2007/data/ashrae_90_1_2007.boilers.json +26 -0
  64. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2007/data/ashrae_90_1_2007.construction_properties.json +8532 -1422
  65. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2010/data/ashrae_90_1_2010.boilers.json +26 -0
  66. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2010/data/ashrae_90_1_2010.construction_properties.json +8532 -1422
  67. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2013/data/ashrae_90_1_2013.boilers.json +16 -0
  68. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2013/data/ashrae_90_1_2013.computer_room_acs.json +30 -30
  69. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2013/data/ashrae_90_1_2013.construction_properties.json +7560 -1260
  70. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2016/ashrae_90_1_2016.PumpVariableSpeed.rb +1 -2
  71. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2016/data/ashrae_90_1_2016.boilers.json +16 -0
  72. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2016/data/ashrae_90_1_2016.construction_properties.json +7560 -1260
  73. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.AirLoopHVAC.rb +3 -3
  74. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.PumpVariableSpeed.rb +1 -2
  75. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/data/ashrae_90_1_2019.boilers.json +22 -0
  76. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/data/ashrae_90_1_2019.construction_properties.json +7236 -1206
  77. data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/data/ashrae_90_1_2019.furnaces.json +223 -19
  78. data/lib/openstudio-standards/standards/ashrae_90_1/data/ashrae_90_1.schedules.json +37 -1
  79. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/data/ashrae_90_1_prm_2019.boilers.json +3 -0
  80. data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/data/ashrae_90_1_prm_2019.construction_properties.json +6900 -1150
  81. data/lib/openstudio-standards/standards/cbes/data/cbes.schedules.json +1 -1
  82. data/lib/openstudio-standards/standards/deer/data/deer.schedules.json +1 -1
  83. data/lib/openstudio-standards/standards/necb/BTAP1980TO2010/data/surface_thermal_transmittance.json +76 -40
  84. data/lib/openstudio-standards/standards/necb/BTAPPRE1980/data/surface_thermal_transmittance.json +76 -40
  85. data/lib/openstudio-standards/standards/necb/ECMS/hvac_systems.rb +6 -4
  86. data/lib/openstudio-standards/standards/necb/NECB2011/NECB2011_QAQC.json +2988 -0
  87. data/lib/openstudio-standards/standards/necb/NECB2011/autozone.rb +25 -3
  88. data/lib/openstudio-standards/standards/necb/NECB2011/building_envelope.rb +672 -534
  89. data/lib/openstudio-standards/standards/necb/NECB2011/data/geometry/Hospital.osm +1791 -1792
  90. data/lib/openstudio-standards/standards/necb/NECB2011/data/geometry/LEEPMultiTower.osm +7 -1
  91. data/lib/openstudio-standards/standards/necb/NECB2011/data/geometry/LEEPTownHouse.osm +7 -1
  92. data/lib/openstudio-standards/standards/necb/NECB2011/data/geometry/LargeHotel.osm +5 -6
  93. data/lib/openstudio-standards/standards/necb/NECB2011/data/geometry/LargeOffice.osm +8 -9
  94. data/lib/openstudio-standards/standards/necb/NECB2011/data/geometry/NorthernEducation.osm +10 -4
  95. data/lib/openstudio-standards/standards/necb/NECB2011/data/geometry/NorthernHealthCare.osm +14 -15
  96. data/lib/openstudio-standards/standards/necb/NECB2011/data/geometry/Outpatient.osm +7 -1
  97. data/lib/openstudio-standards/standards/necb/NECB2011/data/surface_thermal_transmittance.json +76 -40
  98. data/lib/openstudio-standards/standards/necb/NECB2011/hvac_systems.rb +14 -6
  99. data/lib/openstudio-standards/standards/necb/NECB2011/necb_2011.rb +542 -130
  100. data/lib/openstudio-standards/standards/necb/NECB2011/qaqc/necb_qaqc.rb +30 -63
  101. data/lib/openstudio-standards/standards/necb/NECB2011/service_water_heating.rb +7 -2
  102. data/lib/openstudio-standards/standards/necb/NECB2015/data/surface_thermal_transmittance.json +90 -0
  103. data/lib/openstudio-standards/standards/necb/NECB2015/necb_2015.rb +8 -6
  104. data/lib/openstudio-standards/standards/necb/NECB2017/data/surface_thermal_transmittance.json +76 -40
  105. data/lib/openstudio-standards/standards/necb/NECB2017/necb_2017.rb +2 -1
  106. data/lib/openstudio-standards/standards/necb/NECB2020/building_envelope.rb +0 -117
  107. data/lib/openstudio-standards/standards/necb/NECB2020/data/surface_thermal_transmittance.json +76 -45
  108. data/lib/openstudio-standards/standards/necb/NECB2020/necb_2020.rb +218 -0
  109. data/lib/openstudio-standards/standards/necb/common/construction_defaults.osm +12 -7
  110. data/lib/openstudio-standards/standards/standard.rb +1 -1
  111. data/lib/openstudio-standards/version.rb +1 -1
  112. data/lib/openstudio-standards.rb +9 -4
  113. metadata +59 -66
  114. data/data/inventory/thermal_bridging.csv +0 -90
  115. data/data/standards/OpenStudio_Standards-ashrae_90_1-ALL-comstock(space_types).xlsx +0 -0
  116. data/data/standards/openstudio_standards_duplicates_log.csv +0 -7962
  117. data/lib/openstudio-standards/btap/NECB_building_types.csv +0 -35
  118. data/lib/openstudio-standards/btap/NECB_space_types.csv +0 -109
  119. data/lib/openstudio-standards/btap/WeatherData1.json +0 -2110
  120. data/lib/openstudio-standards/btap/WeatherData1.xlsx +0 -0
  121. data/lib/openstudio-standards/btap/btap_result.rb +0 -1144
  122. data/lib/openstudio-standards/btap/btap_test_helper.rb +0 -86
  123. data/lib/openstudio-standards/btap/common_paths.rb +0 -81
  124. data/lib/openstudio-standards/btap/common_resources/ConstructionProperties.csv +0 -52
  125. data/lib/openstudio-standards/btap/common_resources/Constructions.csv +0 -37
  126. data/lib/openstudio-standards/btap/common_resources/construction_sets.csv +0 -1270
  127. data/lib/openstudio-standards/btap/common_resources/constructions_glazing.csv +0 -121
  128. data/lib/openstudio-standards/btap/common_resources/constructions_opaque.csv +0 -2256
  129. data/lib/openstudio-standards/btap/common_resources/costs.csv +0 -1897
  130. data/lib/openstudio-standards/btap/common_resources/costs_local_factors.csv +0 -2315
  131. data/lib/openstudio-standards/btap/common_resources/materials_glazing.csv +0 -35
  132. data/lib/openstudio-standards/btap/common_resources/materials_opaque.csv +0 -164
  133. data/lib/openstudio-standards/btap/costing/btap_measure_helper.rb +0 -359
  134. data/lib/openstudio-standards/btap/costing/btap_workflow.rb +0 -117
  135. data/lib/openstudio-standards/btap/costing/copy_test_results_files_to_expected_results.rb +0 -11
  136. data/lib/openstudio-standards/btap/costing/cost_building_from_file.rb +0 -136
  137. data/lib/openstudio-standards/btap/costing/costing_database_wrapper.rb +0 -173
  138. data/lib/openstudio-standards/btap/costing/dummy.epw +0 -8768
  139. data/lib/openstudio-standards/btap/costing/dummy.osm +0 -5320
  140. data/lib/openstudio-standards/btap/costing/neb_end_use_prices.csv +0 -42
  141. data/lib/openstudio-standards/btap/costing/necb_2011_spacetype_info.csv +0 -225
  142. data/lib/openstudio-standards/btap/costing/necb_reference_runs.csv +0 -28705
  143. data/lib/openstudio-standards/btap/costing/parallel_tests.rb +0 -92
  144. data/lib/openstudio-standards/btap/costing/test_list.txt +0 -15
  145. data/lib/openstudio-standards/btap/costing/test_run_all_test_locally.rb +0 -27
  146. data/lib/openstudio-standards/btap/costing/test_run_costing_tests.rb +0 -80
  147. data/lib/openstudio-standards/btap/necb_2011_spacetype_info.csv +0 -225
  148. data/lib/openstudio-standards/btap/utilities/Add_template_field_to_json.rb +0 -22
  149. data/lib/openstudio-standards/btap/utilities/convert_surfaces_to_adiabatic_necb_8426.rb +0 -204
  150. data/lib/openstudio-standards/btap/utilities/generate_space_types.rb +0 -8
  151. data/lib/openstudio-standards/btap/utilities/necb_to_epw_map.rb +0 -50
  152. data/lib/openstudio-standards/btap/utilities/os_sim_extract.rb +0 -48
  153. data/lib/openstudio-standards/btap/utilities/rename_surfaces.rb +0 -24
  154. data/lib/openstudio-standards/btap/utilities/round_surf_coords.rb +0 -32
  155. data/lib/openstudio-standards/btap/utilities/sched_create.rb +0 -145
  156. data/lib/openstudio-standards/btap/utilities/set_mult_to_adiabatic.rb +0 -53
  157. data/lib/openstudio-standards/btap/utilities/space_type.rb +0 -78
  158. data/lib/openstudio-standards/btap/utilities/weatherData1_xlsx_to_json.rb +0 -56
  159. data/lib/openstudio-standards/btap/vintagizer.rb +0 -161
  160. data/lib/openstudio-standards/btap/visualization.rb +0 -72
  161. data/lib/openstudio-standards/standards/necb/NECB2011/data/necb_2011_spacetype_info.csv +0 -225
  162. data/lib/openstudio-standards/standards/necb/common/btap_analysis.rb +0 -79
  163. data/lib/openstudio-standards/standards/necb/common/btap_data.rb +0 -2656
  164. data/lib/openstudio-standards/standards/necb/common/btap_datapoint.rb +0 -653
  165. data/lib/openstudio-standards/standards/necb/common/necb_reference_runs.csv +0 -28705
  166. data/lib/openstudio-standards/standards/necb/common/utility_pricing_2025-02-20.csv +0 -92
  167. /data/lib/openstudio-standards/btap/{common_resources → common}/carbon_frame.csv +0 -0
  168. /data/lib/openstudio-standards/btap/{common_resources → common}/carbon_glazing.csv +0 -0
  169. /data/lib/openstudio-standards/btap/{common_resources → common}/carbon_opaque.csv +0 -0
  170. /data/lib/openstudio-standards/btap/{common_resources → common}/hvac_vent_ahu.csv +0 -0
  171. /data/lib/openstudio-standards/btap/{common_resources → common}/lighting.csv +0 -0
  172. /data/lib/openstudio-standards/btap/{common_resources → common}/lighting_sets.csv +0 -0
  173. /data/lib/openstudio-standards/btap/{common_resources → common}/locations.csv +0 -0
  174. /data/lib/openstudio-standards/btap/{costing → common}/mech_sizing.json +0 -0
@@ -1,1144 +0,0 @@
1
- module BTAP
2
- def self.perform_qaqc(model)
3
- surfaces = {}
4
- outdoor_surfaces = BTAP::Geometry::Surfaces::filter_by_boundary_condition(model.getSurfaces(), "Outdoors")
5
- outdoor_walls = BTAP::Geometry::Surfaces::filter_by_surface_types(outdoor_surfaces, "Wall")
6
- outdoor_roofs = BTAP::Geometry::Surfaces::filter_by_surface_types(outdoor_surfaces, "RoofCeiling")
7
- outdoor_floors = BTAP::Geometry::Surfaces::filter_by_surface_types(outdoor_surfaces, "Floor")
8
- outdoor_subsurfaces = outdoor_surfaces.flat_map(&:subSurfaces)
9
- ground_surfaces = BTAP::Geometry::Surfaces::filter_by_boundary_condition(model.getSurfaces(), "Ground")
10
- ground_walls = BTAP::Geometry::Surfaces::filter_by_surface_types(ground_surfaces, "Wall")
11
- ground_roofs = BTAP::Geometry::Surfaces::filter_by_surface_types(ground_surfaces, "RoofCeiling")
12
- ground_floors = BTAP::Geometry::Surfaces::filter_by_surface_types(ground_surfaces, "Floor")
13
-
14
- windows = BTAP::Geometry::Surfaces::filter_subsurfaces_by_types(outdoor_subsurfaces, ["FixedWindow" , "OperableWindow" ])
15
- skylights = BTAP::Geometry::Surfaces::filter_subsurfaces_by_types(outdoor_subsurfaces, ["Skylight", "TubularDaylightDiffuser","TubularDaylightDome" ])
16
- doors = BTAP::Geometry::Surfaces::filter_subsurfaces_by_types(outdoor_subsurfaces, ["Door" , "GlassDoor" ])
17
- overhead_doors = BTAP::Geometry::Surfaces::filter_subsurfaces_by_types(outdoor_subsurfaces, ["OverheadDoor" ])
18
- electric_peak = model.sqlFile().get().execAndReturnFirstDouble("SELECT Value FROM tabulardatawithstrings WHERE ReportName='EnergyMeters'" +
19
- " AND ReportForString='Entire Facility' AND TableName='Annual and Peak Values - Electricity' AND RowName='Electricity:Facility'" +
20
- " AND ColumnName='Electricity Maximum Value' AND Units='W'")
21
- natural_gas_peak = model.sqlFile().get().execAndReturnFirstDouble("SELECT Value FROM tabulardatawithstrings WHERE ReportName='EnergyMeters'" +
22
- " AND ReportForString='Entire Facility' AND TableName='Annual and Peak Values - Natural Gas' AND RowName='NaturalGas:Facility'" +
23
- " AND ColumnName='Natural Gas Maximum Value' AND Units='W'")
24
-
25
- # Create hash to store all the collected data.
26
- qaqc = {}
27
- error_warning=[]
28
- # Store Building data.
29
- qaqc[:building] = {}
30
- qaqc[:building][:name] = model.building.get.name.get
31
- qaqc[:building][:conditioned_floor_area_m2]=nil
32
- unless model.building.get.conditionedFloorArea().empty?
33
- qaqc[:building][:conditioned_floor_area_m2] = model.building.get.conditionedFloorArea().get
34
- else
35
- error_warning << "model.building.get.conditionedFloorArea() is empty for #{model.building.get.name.get}"
36
- end
37
- qaqc[:building][:exterior_area_m2] = model.building.get.exteriorSurfaceArea() #m2
38
- qaqc[:building][:volume] = model.building.get.airVolume() #m3
39
- qaqc[:building][:number_of_stories] = model.getBuildingStorys.size
40
- # Store Geography Data
41
- qaqc[:geography] ={}
42
- weather_file_path = model.weatherFile.get.path.get.to_s
43
- stat_file_path = weather_file_path.gsub('.epw', '.stat')
44
- stat_file = OpenstudioStandards::Weather::StatFile.new(stat_file_path)
45
- qaqc[:geography][:hdd] = stat_file.hdd18
46
- qaqc[:geography][:cdd] = stat_file.cdd18
47
- qaqc[:geography][:climate_zone] = NECB2011.new().get_climate_zone_name(qaqc[:geography][:hdd])
48
- qaqc[:geography][:city] = model.getWeatherFile.city
49
- qaqc[:geography][:state_province_region] = model.getWeatherFile.stateProvinceRegion
50
- qaqc[:geography][:country] = model.getWeatherFile.country
51
- qaqc[:geography][:latitude] = model.getWeatherFile.latitude
52
- qaqc[:geography][:longitude] = model.getWeatherFile.longitude
53
-
54
- #Spacetype Breakdown
55
- qaqc[:spacetype_area_breakdown]={}
56
- model.getSpaceTypes.sort.each do |spaceType|
57
- next if spaceType.floorArea == 0
58
-
59
- # data for space type breakdown
60
- display = spaceType.name.get
61
- floor_area_si = 0
62
- # loop through spaces so I can skip if not included in floor area
63
- spaceType.spaces.sort.each do |space|
64
- next if not space.partofTotalFloorArea
65
- floor_area_si += space.floorArea * space.multiplier
66
- end
67
- qaqc[:spacetype_area_breakdown][spaceType.name.get.gsub(/\s+/, "_").downcase.to_sym] = floor_area_si
68
- end
69
-
70
-
71
-
72
- #Economics Section
73
- qaqc[:economics] = {}
74
- costing_rownames = model.sqlFile().get().execAndReturnVectorOfString("SELECT RowName FROM TabularDataWithStrings WHERE ReportName='LEEDsummary' AND ReportForString='Entire Facility' AND TableName='EAp2-7. Energy Cost Summary' AND ColumnName='Total Energy Cost'")
75
- #==> ["Electricity", "Natural Gas", "Additional", "Total"]
76
- costing_rownames = validate_optional(costing_rownames, model, "N/A")
77
- unless costing_rownames == "N/A"
78
- costing_rownames.each do |rowname|
79
- case rowname
80
- when "Electricity"
81
- qaqc[:economics][:electricity_cost] = model.sqlFile().get().execAndReturnFirstDouble("SELECT Value FROM TabularDataWithStrings WHERE ReportName='LEEDsummary' AND ReportForString='Entire Facility' AND TableName='EAp2-7. Energy Cost Summary' AND ColumnName='Total Energy Cost' AND RowName='#{rowname}'").get
82
- qaqc[:economics][:electricity_cost_per_m2]=qaqc[:economics][:electricity_cost]/qaqc[:building][:conditioned_floor_area_m2] unless model.building.get.conditionedFloorArea().empty?
83
- when "Natural Gas"
84
- qaqc[:economics][:natural_gas_cost] = model.sqlFile().get().execAndReturnFirstDouble("SELECT Value FROM TabularDataWithStrings WHERE ReportName='LEEDsummary' AND ReportForString='Entire Facility' AND TableName='EAp2-7. Energy Cost Summary' AND ColumnName='Total Energy Cost' AND RowName='#{rowname}'").get
85
- qaqc[:economics][:natural_gas_cost_per_m2]=qaqc[:economics][:natural_gas_cost]/qaqc[:building][:conditioned_floor_area_m2] unless model.building.get.conditionedFloorArea().empty?
86
-
87
- when "Additional"
88
- qaqc[:economics][:additional_cost] = model.sqlFile().get().execAndReturnFirstDouble("SELECT Value FROM TabularDataWithStrings WHERE ReportName='LEEDsummary' AND ReportForString='Entire Facility' AND TableName='EAp2-7. Energy Cost Summary' AND ColumnName='Total Energy Cost' AND RowName='#{rowname}'").get
89
- qaqc[:economics][:additional_cost_per_m2]=qaqc[:economics][:additional_cost]/qaqc[:building][:conditioned_floor_area_m2] unless model.building.get.conditionedFloorArea().empty?
90
-
91
- when "Total"
92
- qaqc[:economics][:total_cost] = model.sqlFile().get().execAndReturnFirstDouble("SELECT Value FROM TabularDataWithStrings WHERE ReportName='LEEDsummary' AND ReportForString='Entire Facility' AND TableName='EAp2-7. Energy Cost Summary' AND ColumnName='Total Energy Cost' AND RowName='#{rowname}'").get
93
- qaqc[:economics][:total_cost_per_m2]=qaqc[:economics][:total_cost]/qaqc[:building][:conditioned_floor_area_m2] unless model.building.get.conditionedFloorArea().empty?
94
- end
95
- end
96
- else
97
- error_warning << "costing is unavailable because the sql statement is nil RowName FROM TabularDataWithStrings WHERE ReportName='LEEDsummary' AND ReportForString='Entire Facility' AND TableName='EAp2-7. Energy Cost Summary' AND ColumnName='Total Energy Cost'"
98
- end
99
-
100
- #Store end_use data
101
- end_uses = [
102
- 'Heating',
103
- 'Cooling',
104
- 'Interior Lighting',
105
- 'Exterior Lighting',
106
- 'Interior Equipment',
107
- 'Exterior Equipment',
108
- 'Fans',
109
- 'Pumps',
110
- 'Heat Rejection',
111
- 'Humidification',
112
- 'Heat Recovery',
113
- 'Water Systems',
114
- 'Refrigeration',
115
- 'Generators',
116
- 'Total End Uses'
117
- ]
118
-
119
- fuels = [
120
- ['Electricity', 'GJ'],
121
- ['Natural Gas', 'GJ'] ,
122
- ['Additional Fuel', 'GJ'],
123
- ['District Cooling','GJ'],
124
- ['District Heating', 'GJ'],
125
- ]
126
-
127
- qaqc[:end_uses] = {}
128
- qaqc[:end_uses_eui] = {}
129
- end_uses.each do |use_type|
130
- qaqc[:end_uses]["#{use_type.gsub(/\s+/, "_").downcase.to_sym}_gj"] = 0
131
- qaqc[:end_uses_eui]["#{use_type.gsub(/\s+/, "_").downcase.to_sym}_gj_per_m2"] = 0
132
- fuels.each do |fuel_type|
133
- value = model.sqlFile().get().execAndReturnFirstDouble("SELECT Value FROM tabulardatawithstrings WHERE ReportName='AnnualBuildingUtilityPerformanceSummary' AND ReportForString='Entire Facility' AND TableName='End Uses' AND RowName='#{use_type}' AND ColumnName='#{fuel_type[0]}' AND Units='#{fuel_type[1]}'")
134
- if value.empty? or value.get == 0
135
- else
136
- qaqc[:end_uses]["#{use_type.gsub(/\s+/, "_").downcase.to_sym}_gj"] += value.get
137
- unless qaqc[:building][:conditioned_floor_area_m2].nil?
138
- qaqc[:end_uses_eui]["#{use_type.gsub(/\s+/, "_").downcase.to_sym}_gj_per_m2"] += value.get / qaqc[:building][:conditioned_floor_area_m2]
139
- end
140
- end
141
- end
142
- value = model.sqlFile().get().execAndReturnFirstDouble("SELECT Value FROM tabulardatawithstrings WHERE ReportName='AnnualBuildingUtilityPerformanceSummary' AND ReportForString='Entire Facility' AND TableName='End Uses' AND RowName='#{use_type}' AND ColumnName='Water' AND Units='m3'")
143
- if value.empty? or value.get == 0
144
- else
145
- qaqc[:end_uses]["#{use_type.gsub(/\s+/, "_").downcase.to_sym}_water_m3"] = value.get
146
- unless qaqc[:building][:conditioned_floor_area_m2].nil?
147
- qaqc[:end_uses_eui]["#{use_type.gsub(/\s+/, "_").downcase.to_sym}_water_m3_per_m2"] = value.get / qaqc[:building][:conditioned_floor_area_m2]
148
- end
149
- end
150
- end
151
-
152
- # Store Peak Data
153
- qaqc[:meter_peaks] = {}
154
- qaqc[:meter_peaks][:electric_w] = electric_peak.empty? ? "NA" : electric_peak.get
155
- qaqc[:meter_peaks][:natural_gas_w] = natural_gas_peak.empty? ? "NA" : natural_gas_peak.get
156
-
157
-
158
- #Store unmet hour data
159
- qaqc[:unmet_hours] = {}
160
- qaqc[:unmet_hours][:cooling] = model.getFacility.hoursCoolingSetpointNotMet().get unless model.getFacility.hoursCoolingSetpointNotMet().empty?
161
- qaqc[:unmet_hours][:heating] = model.getFacility.hoursHeatingSetpointNotMet().get unless model.getFacility.hoursHeatingSetpointNotMet().empty?
162
-
163
-
164
-
165
-
166
-
167
-
168
- #puts "\n\n\n#{costing_rownames}\n\n\n"
169
- #Padmassun's Code -- Tarrif end
170
-
171
-
172
- #Padmassun's Code -- Service Hotwater Heating *start*
173
- qaqc[:service_water_heating] = {}
174
- qaqc[:service_water_heating][:total_nominal_occupancy]=-1
175
- #qaqc[:service_water_heating][:total_nominal_occupancy]=model.sqlFile().get().execAndReturnVectorOfDouble("SELECT Value FROM TabularDataWithStrings WHERE ReportName='OutdoorAirSummary' AND ReportForString='Entire Facility' AND TableName='Average Outdoor Air During Occupied Hours' AND ColumnName='Nominal Number of Occupants'").get.inject(0, :+)
176
- qaqc[:service_water_heating][:total_nominal_occupancy]=get_total_nominal_capacity(model)
177
-
178
- qaqc[:service_water_heating][:electricity_per_year]=model.sqlFile().get().execAndReturnFirstDouble("SELECT Value FROM TabularDataWithStrings WHERE ReportName='AnnualBuildingUtilityPerformanceSummary' AND ReportForString='Entire Facility' AND TableName='End Uses' AND ColumnName='Electricity' AND RowName='Water Systems'")
179
- qaqc[:service_water_heating][:electricity_per_year]= validate_optional(qaqc[:service_water_heating][:electricity_per_year], model, -1)
180
-
181
- qaqc[:service_water_heating][:electricity_per_day]=qaqc[:service_water_heating][:electricity_per_year]/365.5
182
- qaqc[:service_water_heating][:electricity_per_day_per_occupant]=qaqc[:service_water_heating][:electricity_per_day]/qaqc[:service_water_heating][:total_nominal_occupancy]
183
-
184
-
185
- qaqc[:service_water_heating][:natural_gas_per_year]=model.sqlFile().get().execAndReturnFirstDouble("SELECT Value FROM TabularDataWithStrings WHERE ReportName='AnnualBuildingUtilityPerformanceSummary' AND ReportForString='Entire Facility' AND TableName='End Uses' AND ColumnName='Natural Gas' AND RowName='Water Systems'")
186
- qaqc[:service_water_heating][:natural_gas_per_year]=validate_optional(qaqc[:service_water_heating][:natural_gas_per_year], model, -1)
187
-
188
- qaqc[:service_water_heating][:additional_fuel_per_year]=model.sqlFile().get().execAndReturnFirstDouble("SELECT Value FROM TabularDataWithStrings WHERE ReportName='AnnualBuildingUtilityPerformanceSummary' AND ReportForString='Entire Facility' AND TableName='End Uses' AND ColumnName='Additional Fuel' AND RowName='Water Systems'")
189
- qaqc[:service_water_heating][:additional_fuel_per_year] = validate_optional(qaqc[:service_water_heating][:additional_fuel_per_year], model, -1)
190
-
191
- qaqc[:service_water_heating][:water_m3_per_year]=model.sqlFile().get().execAndReturnFirstDouble("SELECT Value FROM TabularDataWithStrings WHERE ReportName='AnnualBuildingUtilityPerformanceSummary' AND ReportForString='Entire Facility' AND TableName='End Uses' AND ColumnName='Water' AND RowName='Water Systems'")
192
- qaqc[:service_water_heating][:water_m3_per_year]=validate_optional(qaqc[:service_water_heating][:water_m3_per_year], model, -1)
193
-
194
- qaqc[:service_water_heating][:water_m3_per_day]=qaqc[:service_water_heating][:water_m3_per_year]/365.5
195
- qaqc[:service_water_heating][:water_m3_per_day_per_occupant]=qaqc[:service_water_heating][:water_m3_per_day]/qaqc[:service_water_heating][:total_nominal_occupancy]
196
- #puts qaqc[:service_water_heating][:total_nominal_occupancy]
197
- #Padmassun's Code -- Service Hotwater Heating *end*
198
-
199
- #Store Envelope data.
200
- qaqc[:envelope] = {}
201
-
202
- qaqc[:envelope][:outdoor_walls_average_conductance_w_per_m2_k] = OpenstudioStandards::Constructions.surfaces_get_conductance(outdoor_walls).round(4) if outdoor_walls.size > 0
203
- qaqc[:envelope][:outdoor_roofs_average_conductance_w_per_m2_k] = OpenstudioStandards::Constructions.surfaces_get_conductance(outdoor_roofs).round(4) if outdoor_roofs.size > 0
204
- qaqc[:envelope][:outdoor_floors_average_conductance_w_per_m2_k] = OpenstudioStandards::Constructions.surfaces_get_conductance(outdoor_floors).round(4) if outdoor_floors.size > 0
205
- qaqc[:envelope][:ground_walls_average_conductance_w_per_m2_k] = OpenstudioStandards::Constructions.surfaces_get_conductance(ground_walls).round(4) if ground_walls.size > 0
206
- qaqc[:envelope][:ground_roofs_average_conductance_w_per_m2_k] = OpenstudioStandards::Constructions.surfaces_get_conductance(ground_roofs).round(4) if ground_roofs.size > 0
207
- qaqc[:envelope][:ground_floors_average_conductance_w_per_m2_k] = OpenstudioStandards::Constructions.surfaces_get_conductance(ground_floors).round(4) if ground_floors.size > 0
208
- qaqc[:envelope][:windows_average_conductance_w_per_m2_k] = OpenstudioStandards::Constructions.surfaces_get_conductance(windows).round(4) if windows.size > 0
209
- qaqc[:envelope][:skylights_average_conductance_w_per_m2_k] = OpenstudioStandards::Constructions.surfaces_get_conductance(skylights).round(4) if skylights.size > 0
210
- qaqc[:envelope][:doors_average_conductance_w_per_m2_k] = OpenstudioStandards::Constructions.surfaces_get_conductance(doors).round(4) if doors.size > 0
211
- qaqc[:envelope][:overhead_doors_average_conductance_w_per_m2_k] = OpenstudioStandards::Constructions.surfaces_get_conductance(overhead_doors).round(4) if overhead_doors.size > 0
212
- qaqc[:envelope][:fdwr] = (BTAP::Geometry::get_fwdr(model) * 100.0).round(1)
213
- qaqc[:envelope][:srr] = (BTAP::Geometry::get_srr(model) * 100.0).round(1)
214
-
215
-
216
- qaqc[:envelope][:constructions] = {}
217
- qaqc[:envelope][:constructions][:exterior_fenestration] = []
218
- constructions = []
219
- outdoor_subsurfaces.each { |surface| constructions << surface.construction.get }
220
- ext_const_base = Hash.new(0)
221
- constructions.each { |name| ext_const_base[name] += 1 }
222
- #iterate thought each construction and get store data
223
- ext_const_base.sort.each do |construction, count|
224
- construction_info = {}
225
- qaqc[:envelope][:constructions][:exterior_fenestration] << construction_info
226
- construction_info[:name] = construction.name.get
227
- construction_info[:net_area_m2] = construction.getNetArea.round(2)
228
- construction_info[:thermal_conductance_m2_w_per_k] = OpenstudioStandards::Constructions.construction_get_conductance(construction).round(3)
229
- construction_info[:solar_transmittance] = OpenstudioStandards::Constructions.construction_get_solar_transmittance(construction).round(3)
230
- construction_info[:visible_tranmittance] = OpenstudioStandards::Constructions.construction_get_visible_transmittance(construction).round(3)
231
- end
232
-
233
- #Exterior
234
- qaqc[:envelope][:constructions][:exterior_opaque] = []
235
- constructions = []
236
- outdoor_surfaces.each { |surface| constructions << surface.construction.get }
237
- ext_const_base = Hash.new(0)
238
- constructions.each { |name| ext_const_base[name] += 1 }
239
- #iterate thought each construction and get store data
240
- ext_const_base.sort.each do |construction, count|
241
- construction_info = {}
242
- qaqc[:envelope][:constructions][:exterior_opaque] << construction_info
243
- construction_info[:name] = construction.name.get
244
- construction_info[:net_area_m2] = construction.getNetArea.round(2)
245
- construction_info[:thermal_conductance_m2_w_per_k] = construction.thermalConductance.get.round(3) if construction.thermalConductance.is_initialized
246
- construction_info[:net_area_m2] = construction.to_Construction.get.getNetArea.round(2)
247
- construction_info[:solar_absorptance] = construction.to_Construction.get.layers[0].exteriorVisibleAbsorptance.get
248
- end
249
-
250
- #Ground
251
- qaqc[:envelope][:constructions][:ground] = []
252
- constructions = []
253
- ground_surfaces.each { |surface| constructions << surface.construction.get }
254
- ext_const_base = Hash.new(0)
255
- constructions.each { |name| ext_const_base[name] += 1 }
256
- #iterate thought each construction and get store data
257
- ext_const_base.sort.each do |construction, count|
258
- construction_info = {}
259
- qaqc[:envelope][:constructions][:ground] << construction_info
260
- construction_info[:name] = construction.name.get
261
- construction_info[:net_area_m2] = construction.getNetArea.round(2)
262
- construction_info[:thermal_conductance_m2_w_per_k] = construction.thermalConductance.get.round(3) if construction.thermalConductance.is_initialized
263
- construction_info[:net_area_m2] = construction.to_Construction.get.getNetArea.round(2)
264
- construction_info[:solar_absorptance] = construction.to_Construction.get.layers[0].exteriorVisibleAbsorptance.get
265
- end
266
-
267
-
268
- # Store Space data.
269
- qaqc[:spaces] =[]
270
- model.getSpaces.sort.each do |space|
271
- spaceinfo = {}
272
- qaqc[:spaces] << spaceinfo
273
- spaceinfo[:name] = space.name.get #name should be defined test
274
- spaceinfo[:multiplier] = space.multiplier
275
- spaceinfo[:volume] = space.volume # should be greater than zero
276
- spaceinfo[:exterior_wall_area] = space.exteriorWallArea # just for information.
277
- spaceinfo[:space_type_name] = space.spaceType.get.name.get unless space.spaceType.empty? #should have a space types name defined.
278
- spaceinfo[:thermal_zone] = space.thermalZone.get.name.get unless space.thermalZone.empty? # should be assigned a thermalzone name.
279
- #puts space.name.get
280
- #puts space.thermalZone.empty?
281
- spaceinfo[:breathing_zone_outdoor_airflow_vbz] =-1
282
- breathing_zone_outdoor_airflow_vbz= model.sqlFile().get().execAndReturnFirstDouble("SELECT Value FROM TabularDataWithStrings WHERE ReportName='Standard62.1Summary' AND ReportForString='Entire Facility' AND TableName='Zone Ventilation Parameters' AND ColumnName='Breathing Zone Outdoor Airflow - Vbz' AND Units='m3/s' AND RowName='#{spaceinfo[:thermal_zone].to_s.upcase}' ")
283
- spaceinfo[:breathing_zone_outdoor_airflow_vbz] =breathing_zone_outdoor_airflow_vbz.get unless breathing_zone_outdoor_airflow_vbz.empty?
284
- spaceinfo[:infiltration_method] = 'N/A'
285
- spaceinfo[:infiltration_flow_per_m2] =-1.0
286
- unless space.spaceInfiltrationDesignFlowRates[0].nil?
287
- spaceinfo[:infiltration_method] = space.spaceInfiltrationDesignFlowRates[0].designFlowRateCalculationMethod
288
- spaceinfo[:infiltration_flow_per_m2] = "N/A"
289
- spaceinfo[:infiltration_flow_per_m2] = space.spaceInfiltrationDesignFlowRates[0].flowperExteriorSurfaceArea.get.round(5) unless space.spaceInfiltrationDesignFlowRates[0].flowperExteriorSurfaceArea.empty?
290
- else
291
- error_warning << "space.spaceInfiltrationDesignFlowRates[0] is empty for #{spaceinfo[:name]}"
292
- error_warning << "space.spaceInfiltrationDesignFlowRates[0].designFlowRateCalculationMethod is empty for #{spaceinfo[:name]}"
293
- error_warning << "space.spaceInfiltrationDesignFlowRates[0].flowperExteriorSurfaceArea is empty for #{spaceinfo[:name]}"
294
- end
295
-
296
- #the following should have values unless the spacetype is "undefined" other they should be set to the correct NECB values.
297
- unless space.spaceType.empty?
298
- spaceinfo[:occupancy_schedule] = nil
299
- unless (space.spaceType.get.defaultScheduleSet.empty?)
300
- unless space.spaceType.get.defaultScheduleSet.get.numberofPeopleSchedule.empty?
301
- spaceinfo[:occupancy_schedule] = space.spaceType.get.defaultScheduleSet.get.numberofPeopleSchedule.get.name.get #should not empty.
302
- else
303
- error_warning << "space.spaceType.get.defaultScheduleSet.get.numberofPeopleSchedule is empty for #{space.name.get }"
304
- end
305
- else
306
- error_warning << "space.spaceType.get.defaultScheduleSet is empty for #{space.name.get }"
307
- end
308
-
309
- spaceinfo[:occ_per_m2] = space.spaceType.get.people[0].peopleDefinition.peopleperSpaceFloorArea.get.round(3) unless space.spaceType.get.people[0].nil?
310
- unless space.spaceType.get.lights[0].nil?
311
- spaceinfo[:lighting_w_per_m2] = space.spaceType.get.lights[0].lightsDefinition.wattsperSpaceFloorArea#.get.round(3) unless space.spaceType.get.lights[0].nil?
312
- spaceinfo[:lighting_w_per_m2] = validate_optional(spaceinfo[:lighting_w_per_m2], model, -1.0)
313
- unless spaceinfo[:lighting_w_per_m2].nil?
314
- spaceinfo[:lighting_w_per_m2] = spaceinfo[:lighting_w_per_m2].round(3)
315
- end
316
- end
317
- #spaceinfo[:electric_w_per_m2] = space.spaceType.get.electricEquipment[0].electricEquipmentDefinition.wattsperSpaceFloorArea.get.round(3) unless space.spaceType.get.electricEquipment[0].nil?
318
-
319
- unless space.spaceType.get.electricEquipment[0].nil?
320
- unless space.spaceType.get.electricEquipment[0].electricEquipmentDefinition.wattsperSpaceFloorArea.empty?
321
- spaceinfo[:electric_w_per_m2] = space.spaceType.get.electricEquipment[0].electricEquipmentDefinition.wattsperSpaceFloorArea.get.round(3)
322
- end
323
- end
324
- spaceinfo[:shw_m3_per_s] = space.waterUseEquipment[0].waterUseEquipmentDefinition.peakFlowRate.round(3) unless space.waterUseEquipment[0].nil?
325
- spaceinfo[:waterUseEquipment] = []
326
- if !space.waterUseEquipment.empty?
327
- waterUseEquipment_info={}
328
- spaceinfo[:waterUseEquipment] << waterUseEquipment_info
329
- waterUseEquipment_info[:peak_flow_rate]= space.waterUseEquipment[0].waterUseEquipmentDefinition.peakFlowRate
330
- waterUseEquipment_info[:peak_flow_rate_per_area] = waterUseEquipment_info[:peak_flow_rate] / space.floorArea
331
- area_per_occ = space.spaceType.get.people[0].spaceFloorAreaPerPerson.get
332
- # Watt per person = m3/s/m3 * 1000W/kW * (specific heat * dT) * m2/person
333
- waterUseEquipment_info[:shw_watts_per_person] = waterUseEquipment_info[:peak_flow_rate_per_area] * 1000 * (4.19 * 44.4) * 1000 * area_per_occ
334
- #puts waterUseEquipment_info[:shw_watts_per_person]
335
- #puts "\n\n\n"
336
- end
337
- else
338
- error_warning << "space.spaceType is empty for #{space.name.get }"
339
- end
340
- end
341
-
342
- # Store Thermal zone data
343
- qaqc[:thermal_zones] = []
344
- model.getThermalZones.sort.each do |zone|
345
- zoneinfo = {}
346
- qaqc[:thermal_zones] << zoneinfo
347
- zoneinfo[:name] = zone.name.get
348
- zoneinfo[:floor_area] = zone.floorArea
349
- zoneinfo[:multiplier] = zone.multiplier
350
- zoneinfo[:is_conditioned] = "N/A"
351
- unless zone.isConditioned.empty?
352
- zoneinfo[:is_conditioned] = zone.isConditioned.get
353
- else
354
- error_warning << "zone.isConditioned is empty for #{zone.name.get}"
355
- end
356
-
357
- zoneinfo[:is_ideal_air_loads] = zone.useIdealAirLoads
358
- zoneinfo[:heating_sizing_factor] = -1.0
359
- unless zone.sizingZone.zoneHeatingSizingFactor.empty?
360
- zoneinfo[:heating_sizing_factor] = zone.sizingZone.zoneHeatingSizingFactor.get
361
- else
362
- error_warning << "zone.sizingZone.zoneHeatingSizingFactor is empty for #{zone.name.get}"
363
- end
364
-
365
- zoneinfo[:cooling_sizing_factor] = -1.0 #zone.sizingZone.zoneCoolingSizingFactor.get
366
- unless zone.sizingZone.zoneCoolingSizingFactor.empty?
367
- zoneinfo[:cooling_sizing_factor] = zone.sizingZone.zoneCoolingSizingFactor.get
368
- else
369
- error_warning << "zone.sizingZone.zoneCoolingSizingFactor is empty for #{zone.name.get}"
370
- end
371
-
372
- zoneinfo[:zone_heating_design_supply_air_temperature] = zone.sizingZone.zoneHeatingDesignSupplyAirTemperature
373
- zoneinfo[:zone_cooling_design_supply_air_temperature] = zone.sizingZone.zoneCoolingDesignSupplyAirTemperature
374
- zoneinfo[:spaces] = []
375
- zone.spaces.sort.each do |space|
376
- spaceinfo ={}
377
- zoneinfo[:spaces] << spaceinfo
378
- spaceinfo[:name] = space.name.get
379
- spaceinfo[:type] = space.spaceType.get.name.get unless space.spaceType.empty?
380
- end
381
- zoneinfo[:equipment] = []
382
- zone.equipmentInHeatingOrder.each do |equipment|
383
- item = {}
384
- zoneinfo[:equipment] << item
385
- item[:name] = equipment.name.get
386
- if equipment.to_ZoneHVACComponent.is_initialized
387
- item[:type] = 'ZoneHVACComponent'
388
- elsif equipment.to_StraightComponent.is_initialized
389
- item[:type] = 'StraightComponent'
390
- end
391
- end
392
- end #zone
393
- # Store Air Loop Information
394
- qaqc[:air_loops] = []
395
- model.getAirLoopHVACs.sort.each do |air_loop|
396
- air_loop_info = {}
397
- air_loop_info[:name] = air_loop.name.get
398
- air_loop_info[:thermal_zones] = []
399
- air_loop_info[:total_floor_area_served] = 0.0
400
- air_loop_info[:total_breathing_zone_outdoor_airflow_vbz] = 0.0
401
- air_loop.thermalZones.sort.each do |zone|
402
- air_loop_info[:thermal_zones] << zone.name.get
403
- vbz = model.sqlFile().get().execAndReturnFirstDouble("SELECT Value FROM TabularDataWithStrings WHERE ReportName='Standard62.1Summary' AND ReportForString='Entire Facility' AND TableName='Zone Ventilation Parameters' AND ColumnName='Breathing Zone Outdoor Airflow - Vbz' AND Units='m3/s' AND RowName='#{zone.name.get.to_s.upcase}' ")
404
- vbz = validate_optional(vbz, model, 0)
405
- air_loop_info[:total_breathing_zone_outdoor_airflow_vbz] += vbz
406
- air_loop_info[:total_floor_area_served] += zone.floorArea
407
- end
408
- air_loop_info[:area_outdoor_air_rate_m3_per_s_m2] = model.sqlFile().get().execAndReturnFirstDouble("SELECT Value FROM TabularDataWithStrings WHERE ReportName='Standard62.1Summary' AND ReportForString='Entire Facility' AND TableName='System Ventilation Parameters' AND ColumnName='Area Outdoor Air Rate - Ra' AND Units='m3/s-m2' AND RowName='#{air_loop_info[:name].to_s.upcase}' ")
409
- air_loop_info[:area_outdoor_air_rate_m3_per_s_m2] = validate_optional(air_loop_info[:area_outdoor_air_rate_m3_per_s_m2], model, -1.0)
410
-
411
- air_loop_info[:outdoor_air_L_per_s] = -1.0
412
- unless air_loop_info[:area_outdoor_air_rate_m3_per_s_m2] ==-1.0
413
- air_loop_info[:outdoor_air_L_per_s] = air_loop_info[:area_outdoor_air_rate_m3_per_s_m2]*air_loop_info[:total_floor_area_served]*1000
414
- end
415
- #Fan
416
-
417
- unless air_loop.supplyFan.empty?
418
- air_loop_info[:supply_fan] = {}
419
- if air_loop.supplyFan.get.to_FanConstantVolume.is_initialized
420
- air_loop_info[:supply_fan][:type] = 'CV'
421
- fan = air_loop.supplyFan.get.to_FanConstantVolume.get
422
- elsif air_loop.supplyFan.get.to_FanVariableVolume.is_initialized
423
- air_loop_info[:supply_fan][:type] = 'VV'
424
- fan = air_loop.supplyFan.get.to_FanVariableVolume.get
425
- end
426
- air_loop_info[:supply_fan][:name] = fan.name.get
427
- #puts "\n\n\n\n#{fan.name.get}\n\n\n\n"
428
- air_loop_info[:supply_fan][:fan_efficiency] = fan.fanEfficiency
429
- air_loop_info[:supply_fan][:motor_efficiency] = fan.motorEfficiency
430
- air_loop_info[:supply_fan][:pressure_rise] = fan.pressureRise
431
- air_loop_info[:supply_fan][:max_air_flow_rate_m3_per_s] = -1.0
432
-
433
- max_air_flow_info = model.sqlFile().get().execAndReturnVectorOfString("SELECT RowName FROM TabularDataWithStrings WHERE ReportName='EquipmentSummary' AND ReportForString='Entire Facility' AND TableName='Fans' AND ColumnName='Max Air Flow Rate' AND Units='m3/s' ")
434
- max_air_flow_info = validate_optional(max_air_flow_info, model, "N/A")
435
- unless max_air_flow_info == "N/A"
436
- if max_air_flow_info.include? "#{air_loop_info[:supply_fan][:name].to_s.upcase}"
437
- air_loop_info[:supply_fan][:max_air_flow_rate_m3_per_s] = model.sqlFile().get().execAndReturnFirstDouble("SELECT Value FROM TabularDataWithStrings WHERE ReportName='EquipmentSummary' AND ReportForString='Entire Facility' AND TableName='Fans' AND ColumnName='Max Air Flow Rate' AND Units='m3/s' AND RowName='#{air_loop_info[:supply_fan][:name].upcase}' ").get
438
- air_loop_info[:supply_fan][:rated_electric_power_w] = model.sqlFile().get().execAndReturnFirstDouble("SELECT Value FROM TabularDataWithStrings WHERE ReportName='EquipmentSummary' AND ReportForString='Entire Facility' AND TableName='Fans' AND ColumnName='Rated Electric Power' AND Units='W' AND RowName='#{air_loop_info[:supply_fan][:name].upcase}' ").get
439
- else
440
- error_warning << "#{air_loop_info[:supply_fan][:name]} does not exist in sql file WHERE ReportName='EquipmentSummary' AND ReportForString='Entire Facility' AND TableName='Fans' AND ColumnName='Max Air Flow Rate' AND Units='m3/s'"
441
- end
442
- else
443
- error_warning << "max_air_flow_info is nil because the following sql statement returned nil: RowName FROM TabularDataWithStrings WHERE ReportName='EquipmentSummary' AND ReportForString='Entire Facility' AND TableName='Fans' AND ColumnName='Max Air Flow Rate' AND Units='m3/s' "
444
- end
445
- end
446
-
447
- #economizer
448
- air_loop_info[:economizer] = {}
449
- air_loop_info[:economizer][:name] = air_loop.airLoopHVACOutdoorAirSystem.get.getControllerOutdoorAir.name.get
450
- air_loop_info[:economizer][:control_type] = air_loop.airLoopHVACOutdoorAirSystem.get.getControllerOutdoorAir.getEconomizerControlType
451
-
452
- #DX cooling coils
453
- air_loop_info[:cooling_coils] ={}
454
- air_loop_info[:cooling_coils][:dx_single_speed]=[]
455
- air_loop_info[:cooling_coils][:dx_two_speed]=[]
456
-
457
- #Heating Coil
458
- air_loop_info[:heating_coils] = {}
459
- air_loop_info[:heating_coils][:coil_heating_gas] = []
460
- air_loop_info[:heating_coils][:coil_heating_electric]= []
461
- air_loop_info[:heating_coils][:coil_heating_water]= []
462
-
463
- #Heat Excahnger
464
- air_loop_info[:heat_exchanger] = {}
465
-
466
- air_loop.supplyComponents.each do |supply_comp|
467
- if supply_comp.to_CoilHeatingGas.is_initialized
468
- coil={}
469
- air_loop_info[:heating_coils][:coil_heating_gas] << coil
470
- gas = supply_comp.to_CoilHeatingGas.get
471
- coil[:name]=gas.name.get
472
- coil[:type]="Gas"
473
- coil[:efficency] = gas.gasBurnerEfficiency
474
- #coil[:nominal_capacity]= gas.nominalCapacity()
475
- coil[:nominal_capacity]= model.sqlFile().get().execAndReturnFirstDouble("SELECT Value FROM TabularDataWithStrings WHERE ReportName='EquipmentSummary' AND ReportForString='Entire Facility' AND TableName='Heating Coils' AND ColumnName='Nominal Total Capacity' AND RowName='#{coil[:name].to_s.upcase}'")
476
- coil[:nominal_capacity]=validate_optional(coil[:nominal_capacity],model,-1.0 )
477
- end
478
- if supply_comp.to_CoilHeatingElectric.is_initialized
479
- coil={}
480
- air_loop_info[:heating_coils][:coil_heating_electric] << coil
481
- electric = supply_comp.to_CoilHeatingElectric.get
482
- coil[:name]= electric.name.get
483
- coil[:type]= "Electric"
484
- coil[:nominal_capacity]= model.sqlFile().get().execAndReturnFirstDouble("SELECT Value FROM TabularDataWithStrings WHERE ReportName='EquipmentSummary' AND ReportForString='Entire Facility' AND TableName='Heating Coils' AND ColumnName='Nominal Total Capacity' AND RowName='#{coil[:name].to_s.upcase}'")
485
- coil[:nominal_capacity]=validate_optional(coil[:nominal_capacity],model,-1.0 )
486
- end
487
- if supply_comp.to_CoilHeatingWater.is_initialized
488
- coil={}
489
- air_loop_info[:heating_coils][:coil_heating_water] << coil
490
- water = supply_comp.to_CoilHeatingWater.get
491
- coil[:name]= water.name.get
492
- coil[:type]= "Water"
493
- coil[:nominal_capacity]= model.sqlFile().get().execAndReturnFirstDouble("SELECT Value FROM TabularDataWithStrings WHERE ReportName='EquipmentSummary' AND ReportForString='Entire Facility' AND TableName='Heating Coils' AND ColumnName='Nominal Total Capacity' AND RowName='#{coil[:name].to_s.upcase}'")
494
- coil[:nominal_capacity]=validate_optional(coil[:nominal_capacity],model,-1.0 )
495
- end
496
- if supply_comp.to_HeatExchangerAirToAirSensibleAndLatent.is_initialized
497
- heatExchanger = supply_comp.to_HeatExchangerAirToAirSensibleAndLatent.get
498
- air_loop_info[:heat_exchanger][:name] = heatExchanger.name.get
499
- end
500
- end
501
-
502
- #I dont think i need to get the type of heating coil from the sql file, because the coils are differentiated by class, and I have hard coded the information
503
- #model.sqlFile().get().execAndReturnFirstDouble("SELECT Value FROM TabularDataWithStrings WHERE ReportName='EquipmentSummary' AND ReportForString='Entire Facility' AND TableName= 'Heating Coils' AND ColumnName='Type' ").get #padmussen to complete #AND RowName='#{air_loop_info[:heating_coils][:name].upcase}'
504
-
505
-
506
- #Collect all the fans into the the array.
507
- air_loop.supplyComponents.each do |supply_comp|
508
- if supply_comp.to_CoilCoolingDXSingleSpeed.is_initialized
509
- coil = {}
510
- air_loop_info[:cooling_coils][:dx_single_speed] << coil
511
- single_speed = supply_comp.to_CoilCoolingDXSingleSpeed.get
512
- coil[:name] = single_speed.name.get
513
- coil[:cop] = single_speed.ratedCOP.to_f
514
- coil[:nominal_total_capacity_w] = model.sqlFile().get().execAndReturnFirstDouble("SELECT Value FROM TabularDataWithStrings WHERE ReportName='EquipmentSummary' AND ReportForString='Entire Facility' AND TableName='Cooling Coils' AND ColumnName='Nominal Total Capacity' AND RowName='#{coil[:name].upcase}' ")
515
- coil[:nominal_total_capacity_w] = validate_optional(coil[:nominal_total_capacity_w], model, -1.0)
516
- end
517
- if supply_comp.to_CoilCoolingDXTwoSpeed.is_initialized
518
- coil = {}
519
- air_loop_info[:cooling_coils][:dx_two_speed] << coil
520
- two_speed = supply_comp.to_CoilCoolingDXTwoSpeed.get
521
- coil[:name] = two_speed.name.get
522
- coil[:cop_low] = two_speed.ratedLowSpeedCOP.to_f
523
- coil[:cop_high] = two_speed.ratedHighSpeedCOP.to_f
524
- coil[:nominal_total_capacity_w] = model.sqlFile().get().execAndReturnFirstDouble("SELECT Value FROM TabularDataWithStrings WHERE ReportName='EquipmentSummary' AND ReportForString='Entire Facility' AND TableName='Cooling Coils' AND ColumnName='Nominal Total Capacity' AND RowName='#{coil[:name].upcase}' ")
525
- coil[:nominal_total_capacity_w] = validate_optional(coil[:nominal_total_capacity_w] , model,-1.0)
526
- end
527
- end
528
- qaqc[:air_loops] << air_loop_info
529
- end
530
-
531
-
532
- qaqc[:plant_loops] = []
533
- model.getPlantLoops.sort.each do |plant_loop|
534
- plant_loop_info = {}
535
- qaqc[:plant_loops] << plant_loop_info
536
- plant_loop_info[:name] = plant_loop.name.get
537
-
538
- sizing = plant_loop.sizingPlant
539
- plant_loop_info[:design_loop_exit_temperature] = sizing.designLoopExitTemperature
540
- plant_loop_info[:loop_design_temperature_difference] = sizing.loopDesignTemperatureDifference
541
-
542
- #Create Container for plant equipment arrays.
543
- plant_loop_info[:pumps] = []
544
- plant_loop_info[:boilers] = []
545
- plant_loop_info[:chiller_electric_eir] = []
546
- plant_loop_info[:cooling_tower_single_speed] = []
547
- plant_loop_info[:water_heater_mixed] =[]
548
- plant_loop.supplyComponents.each do |supply_comp|
549
-
550
- #Collect Constant Speed
551
- if supply_comp.to_PumpConstantSpeed.is_initialized
552
- pump = supply_comp.to_PumpConstantSpeed.get
553
- pump_info = {}
554
- plant_loop_info[:pumps] << pump_info
555
- pump_info[:name] = pump.name.get
556
- pump_info[:type] = "Pump:ConstantSpeed"
557
- pump_info[:head_pa] = model.sqlFile().get().execAndReturnFirstDouble("SELECT Value FROM TabularDataWithStrings WHERE ReportName='EquipmentSummary' AND ReportForString='Entire Facility' AND TableName='Pumps' AND ColumnName='Head' AND RowName='#{pump_info[:name].upcase}' ")
558
- pump_info[:head_pa] = validate_optional(pump_info[:head_pa], model, -1.0)
559
- pump_info[:water_flow_m3_per_s] = model.sqlFile().get().execAndReturnFirstDouble("SELECT Value FROM TabularDataWithStrings WHERE ReportName='EquipmentSummary' AND ReportForString='Entire Facility' AND TableName='Pumps' AND ColumnName='Water Flow' AND RowName='#{pump_info[:name].upcase}' ")
560
- pump_info[:water_flow_m3_per_s] = validate_optional(pump_info[:water_flow_m3_per_s], model, -1.0)
561
- pump_info[:electric_power_w] = model.sqlFile().get().execAndReturnFirstDouble("SELECT Value FROM TabularDataWithStrings WHERE ReportName='EquipmentSummary' AND ReportForString='Entire Facility' AND TableName='Pumps' AND ColumnName='Electric Power' AND RowName='#{pump_info[:name].upcase}' ")
562
- pump_info[:electric_power_w] = validate_optional(pump_info[:electric_power_w], model, -1.0)
563
- pump_info[:motor_efficency] = pump.motorEfficiency
564
- end
565
-
566
- #Collect Variable Speed
567
- if supply_comp.to_PumpVariableSpeed.is_initialized
568
- pump = supply_comp.to_PumpVariableSpeed.get
569
- pump_info = {}
570
- plant_loop_info[:pumps] << pump_info
571
- pump_info[:name] = pump.name.get
572
- pump_info[:type] = "Pump:VariableSpeed"
573
- pump_info[:head_pa] = model.sqlFile().get().execAndReturnFirstDouble("SELECT Value FROM TabularDataWithStrings WHERE ReportName='EquipmentSummary' AND ReportForString='Entire Facility' AND TableName='Pumps' AND ColumnName='Head' AND RowName='#{pump_info[:name].upcase}' ")
574
- pump_info[:head_pa] = validate_optional(pump_info[:head_pa], model, -1.0)
575
- pump_info[:water_flow_m3_per_s] = model.sqlFile().get().execAndReturnFirstDouble("SELECT Value FROM TabularDataWithStrings WHERE ReportName='EquipmentSummary' AND ReportForString='Entire Facility' AND TableName='Pumps' AND ColumnName='Water Flow' AND RowName='#{pump_info[:name].upcase}' ")
576
- pump_info[:water_flow_m3_per_s] = validate_optional(pump_info[:water_flow_m3_per_s], model, -1.0)
577
- pump_info[:electric_power_w] = model.sqlFile().get().execAndReturnFirstDouble("SELECT Value FROM TabularDataWithStrings WHERE ReportName='EquipmentSummary' AND ReportForString='Entire Facility' AND TableName='Pumps' AND ColumnName='Electric Power' AND RowName='#{pump_info[:name].upcase}' ")
578
- pump_info[:electric_power_w] = validate_optional(pump_info[:electric_power_w], model, -1.0)
579
- pump_info[:motor_efficency] = pump.motorEfficiency
580
- end
581
-
582
- # Collect HotWaterBoilers
583
- if supply_comp.to_BoilerHotWater.is_initialized
584
- boiler = supply_comp.to_BoilerHotWater.get
585
- boiler_info = {}
586
- plant_loop_info[:boilers] << boiler_info
587
- boiler_info[:name] = boiler.name.get
588
- boiler_info[:type] = "Boiler:HotWater"
589
- boiler_info[:fueltype] = boiler.fuelType
590
- boiler_info[:nominal_capacity] = boiler.nominalCapacity
591
- boiler_info[:nominal_capacity] = validate_optional(boiler_info[:nominal_capacity], model, -1.0)
592
- end
593
-
594
- # Collect ChillerElectricEIR
595
- if supply_comp.to_ChillerElectricEIR.is_initialized
596
- chiller = supply_comp.to_ChillerElectricEIR.get
597
- chiller_info = {}
598
- plant_loop_info[:chiller_electric_eir] << chiller_info
599
- chiller_info[:name] = chiller.name.get
600
- chiller_info[:type] = "Chiller:Electric:EIR"
601
- chiller_info[:reference_capacity] = validate_optional(chiller.referenceCapacity, model, -1.0)
602
- chiller_info[:reference_leaving_chilled_water_temperature] =chiller.referenceLeavingChilledWaterTemperature
603
- end
604
-
605
- # Collect CoolingTowerSingleSpeed
606
- if supply_comp.to_CoolingTowerSingleSpeed.is_initialized
607
- coolingTower = supply_comp.to_CoolingTowerSingleSpeed.get
608
- coolingTower_info = {}
609
- plant_loop_info[:cooling_tower_single_speed] << coolingTower_info
610
- coolingTower_info[:name] = coolingTower.name.get
611
- coolingTower_info[:type] = "CoolingTower:SingleSpeed"
612
- coolingTower_info[:fan_power_at_design_air_flow_rate] = validate_optional(coolingTower.fanPoweratDesignAirFlowRate, model, -1.0)
613
-
614
- end
615
-
616
- # Collect WaterHeaterMixed
617
- if supply_comp.to_WaterHeaterMixed.is_initialized
618
- waterHeaterMixed = supply_comp.to_WaterHeaterMixed.get
619
- waterHeaterMixed_info = {}
620
- plant_loop_info[:water_heater_mixed] << waterHeaterMixed_info
621
- waterHeaterMixed_info[:name] = waterHeaterMixed.name.get
622
- waterHeaterMixed_info[:type] = "WaterHeater:Mixed"
623
- waterHeaterMixed_info[:heater_thermal_efficiency] = waterHeaterMixed.heaterThermalEfficiency.get unless waterHeaterMixed.heaterThermalEfficiency.empty?
624
- waterHeaterMixed_info[:heater_fuel_type] = waterHeaterMixed.heaterFuelType
625
- end
626
- end
627
-
628
- qaqc[:eplusout_err] ={}
629
- warnings = model.sqlFile().get().execAndReturnVectorOfString("SELECT ErrorMessage FROM Errors WHERE ErrorType='0' ")
630
- warnings = validate_optional(warnings, model, "N/A")
631
- unless warnings == "N/A"
632
- qaqc[:eplusout_err][:warnings] = model.sqlFile().get().execAndReturnVectorOfString("SELECT ErrorMessage FROM Errors WHERE ErrorType='0' ").get
633
- qaqc[:eplusout_err][:fatal] =model.sqlFile().get().execAndReturnVectorOfString("SELECT ErrorMessage FROM Errors WHERE ErrorType='2' ").get
634
- qaqc[:eplusout_err][:severe] =model.sqlFile().get().execAndReturnVectorOfString("SELECT ErrorMessage FROM Errors WHERE ErrorType='1' ").get
635
- end
636
-
637
- qaqc[:ruby_warnings] = error_warning
638
- end
639
-
640
-
641
- # Perform qaqc
642
- necb_2011_qaqc(qaqc, model) if qaqc[:building][:name].include?("NECB2011") #had to nodify this because this is specifically for "NECB-2011" standard
643
- sanity_check(qaqc)
644
-
645
- qaqc[:information] = qaqc[:information].sort
646
- qaqc[:warnings] = qaqc[:warnings].sort
647
- qaqc[:errors] = qaqc[:errors].sort
648
- qaqc[:unique_errors]= qaqc[:unique_errors].sort
649
-
650
- return qaqc
651
- end
652
- end
653
-
654
- def validate_optional (var, model, return_value = "N/A")
655
- if var.empty?
656
- return return_value
657
- else
658
- return var.get
659
- end
660
- end
661
-
662
- def look_up_csv_data(csv_fname, search_criteria)
663
- options = { :headers => :first_row,
664
- :converters => [ :numeric ] }
665
- unless File.exist?(csv_fname)
666
- raise ("File: [#{csv_fname}] Does not exist")
667
- end
668
- # we'll save the matches here
669
- matches = nil
670
- # save a copy of the headers
671
- headers = nil
672
- CSV.open( csv_fname, "r", options ) do |csv|
673
-
674
- # Since CSV includes Enumerable we can use 'find_all'
675
- # which will return all the elements of the Enumerble for
676
- # which the block returns true
677
-
678
- matches = csv.find_all do |row|
679
- match = true
680
- search_criteria.keys.each do |key|
681
- match = match && ( row[key].strip == search_criteria[key].strip )
682
- end
683
- match
684
- end
685
- headers = csv.headers
686
- end
687
- #puts matches
688
- raise("More than one match") if matches.size > 1
689
- puts "Zero matches found for [#{search_criteria}]" if matches.size == 0
690
- #return matches[0]
691
- return matches[0]
692
- end
693
-
694
-
695
- def necb_section_test(qaqc,result_value,bool_operator,expected_value,necb_section_name,test_text,tolerance = nil)
696
- test = "eval_failed"
697
- command = ''
698
- if tolerance.is_a?(Integer)
699
- command = "#{result_value}.round(#{tolerance}) #{bool_operator} #{expected_value}.round(#{tolerance})"
700
- elsif expected_value.is_a?(String) and result_value.is_a?(String)
701
- command = "'#{result_value}' #{bool_operator} '#{expected_value}'"
702
- else
703
- command = "#{result_value} #{bool_operator} #{expected_value}"
704
- end
705
- test = eval(command)
706
- test == 'true' ? true :false
707
- raise ("Eval command failed #{test}") if !!test != test
708
- if test
709
- qaqc[:information] << "[Info][TEST-PASS][#{necb_section_name}]:#{test_text} result value:#{result_value} #{bool_operator} expected value:#{expected_value}"
710
- else
711
- qaqc[:errors] << "[ERROR][TEST-FAIL][#{necb_section_name}]:#{test_text} expected value:#{expected_value} #{bool_operator} result value:#{result_value}"
712
- unless (expected_value == -1.0 or expected_value == 'N/A')
713
- qaqc[:unique_errors] << "[ERROR][TEST-FAIL][#{necb_section_name}]:#{test_text} expected value:#{expected_value} #{bool_operator} result value:#{result_value}"
714
- end
715
- end
716
- end
717
-
718
- def check_boolean_value (value,varname)
719
- return true if value =~ (/^(true|t|yes|y|1)$/i)
720
- return false if value.empty? || value =~ (/^(false|f|no|n|0)$/i)
721
-
722
- raise ArgumentError.new "invalid value for #{varname}: #{value}"
723
- end
724
-
725
-
726
- def get_total_nominal_capacity (model)
727
- total_nominal_capacity = 0
728
- model.getSpaces.sort.each do |space|
729
- unless space.thermalZone.empty?
730
- zone_name = space.thermalZone.get.name.get.upcase
731
- area = model.sqlFile().get().execAndReturnFirstDouble("SELECT Value FROM TabularDataWithStrings WHERE ReportName='InputVerificationandResultsSummary' AND ReportForString='Entire Facility' AND TableName='Zone Summary' AND ColumnName='Area' AND RowName='#{zone_name}'")
732
- area = validate_optional(area, model, -1)
733
- multiplier = model.sqlFile().get().execAndReturnFirstDouble("SELECT Value FROM TabularDataWithStrings WHERE ReportName='InputVerificationandResultsSummary' AND ReportForString='Entire Facility' AND TableName='Zone Summary' AND ColumnName='Multipliers' AND RowName='#{zone_name}'")
734
- multiplier = validate_optional(multiplier, model, -1)
735
- area_per_person = model.sqlFile().get().execAndReturnFirstDouble("SELECT Value FROM TabularDataWithStrings WHERE ReportName='InputVerificationandResultsSummary' AND ReportForString='Entire Facility' AND TableName='Zone Summary' AND ColumnName='People' AND RowName='#{zone_name}'")
736
- area_per_person = validate_optional(area_per_person, model, -1)
737
- next if area_per_person == 0
738
- puts "area: #{area} multiplier: #{multiplier} area_per_person: #{area_per_person}"
739
- total_nominal_capacity += area*multiplier/area_per_person
740
- end
741
- end
742
- return total_nominal_capacity
743
- end
744
-
745
- def sanity_check(qaqc)
746
- qaqc[:sanity_check] = {}
747
- qaqc[:sanity_check][:fail] = []
748
- qaqc[:sanity_check][:pass] = []
749
- #Padmassun's code for isConditioned start
750
- qaqc[:thermal_zones].each do |zoneinfo|
751
- zoneinfo[:spaces].each do |space|
752
- #skip plenums and undefined spaces/zones
753
- if zoneinfo[:name].to_s.include?"- undefined -"
754
- next
755
- end
756
- if zoneinfo[:space_type_name].to_s.include?"Space Function - undefined -"
757
- if zoneinfo[:is_conditioned].to_s == "No"
758
- qaqc[:sanity_check][:pass] << "[TEST-PASS][SANITY_CHECK-PASS] for [SPACE][#{space[:name]}] and [THERMAL ZONE] [#{zoneinfo[:name]}] where isConditioned is supposed to be [""No""] and found as #{zoneinfo[:is_conditioned]}"
759
- else
760
- qaqc[:sanity_check][:fail] << "[ERROR][SANITY_CHECK-FAIL] for [SPACE][#{space[:name]}] and [THERMAL ZONE] [#{zoneinfo[:name]}] where isConditioned is supposed to be [""No""] but found as #{zoneinfo[:is_conditioned]}"
761
- end
762
- else
763
- if zoneinfo[:is_conditioned].to_s == "Yes"
764
- qaqc[:sanity_check][:pass] << "[TEST-PASS][SANITY_CHECK-PASS] for [SPACE][#{space[:name]}] and [THERMAL ZONE] [#{zoneinfo[:name]}] where isConditioned is supposed to be [""Yes""] and found as #{zoneinfo[:is_conditioned]}"
765
- elsif zoneinfo[:name]
766
- qaqc[:sanity_check][:fail] << "[ERROR][SANITY_CHECK-FAIL] for [SPACE][#{space[:name]}] and [THERMAL ZONE] [#{zoneinfo[:name]}] where isConditioned is supposed to be [""Yes""] but found as #{zoneinfo[:is_conditioned]}"
767
- end
768
- end
769
- end
770
- end
771
- qaqc[:sanity_check][:fail] = qaqc[:sanity_check][:fail].sort
772
- qaqc[:sanity_check][:pass] = qaqc[:sanity_check][:pass].sort
773
- #Padmassun's code for isConditioned end
774
- end
775
-
776
-
777
- def necb_2011_qaqc(qaqc, model)
778
- #Now perform basic QA/QC on items for NECB2011
779
- qaqc[:information] = []
780
- qaqc[:warnings] =[]
781
- qaqc[:errors] = []
782
- qaqc[:unique_errors]=[]
783
-
784
-
785
- # #Padmassun's Code Start
786
- csv_file_name ="#{File.dirname(__FILE__)}/necb_2011_spacetype_info.csv"
787
- puts csv_file_name
788
- qaqc[:spaces].each do |space|
789
- building_type =""
790
- space_type =""
791
- if space[:space_type_name].include? 'Space Function '
792
- space_type = (space[:space_type_name].to_s.rpartition('Space Function '))[2].strip
793
- building_type = 'Space Function'
794
- elsif space[:space_type_name].include? ' WholeBuilding'
795
- space_type = (space[:space_type_name].to_s.rpartition(' WholeBuilding'))[0].strip
796
- building_type = 'WholeBuilding'
797
- end
798
- row = look_up_csv_data(csv_file_name,{2 => space_type, 1 => building_type})
799
- if row.nil?
800
- #raise ("space type of [#{space_type}] and/or building type of [#{building_type}] was not found in the excel sheet for space: [#{space[:name]}]")
801
- qaqc[:ruby_warnings] << "space type of [#{space_type}] and/or building type of [#{building_type}] was not found in the excel sheet for space: [#{space[:name]}]"
802
- puts "space type of [#{space_type}] and/or building type of [#{building_type}] was not found in the excel sheet for space: [#{space[:name]}]"
803
- else
804
- #correct the data from the csv file to include a multiplier of 0.9 for specific space types.
805
-
806
- reduceLPDSpaces = ["Classroom/lecture/training", "Conf./meet./multi-purpose", "Lounge/recreation",
807
- "Washroom-sch-A", "Washroom-sch-B", "Washroom-sch-C", "Washroom-sch-D", "Washroom-sch-E",
808
- "Washroom-sch-F", "Washroom-sch-G", "Washroom-sch-H", "Washroom-sch-I", "Dress./fitt. - performance arts",
809
- "Locker room", "Retail - dressing/fitting","Locker room-sch-A","Locker room-sch-B","Locker room-sch-C",
810
- "Locker room-sch-D","Locker room-sch-E","Locker room-sch-F","Locker room-sch-G","Locker room-sch-H",
811
- "Locker room-sch-I", "Office - open plan - occsens", "Office - enclosed - occsens", "Storage area - occsens",
812
- "Hospital - medical supply - occsens", "Storage area - refrigerated - occsens"]
813
-
814
- if reduceLPDSpaces.include?(space_type)
815
- row[3] = row[3]*0.9
816
- puts "\n============================\nspace_type: #{space_type}\n============================\n"
817
- end
818
-
819
- # Start of Space Compliance
820
- necb_section_name = "NECB2011-Section 8.4.3.6"
821
- data = {}
822
- data[:lighting_per_area] = [ row[3],'==',space[:lighting_w_per_m2] , "Table 4.2.1.6" ,1 ] unless space[:lighting_w_per_m2].nil?
823
- data[:occupancy_per_area] = [ row[4],'==',space[:occ_per_m2] , "Table A-8.4.3.3.1" ,3 ] unless space[:occ_per_m2].nil?
824
- data[:occupancy_schedule] = [ row[5],'==',space[:occupancy_schedule], "Table A-8.4.3.3.1" ,nil ] unless space[:occupancy_schedule].nil?
825
- data[:electric_equipment_per_area] = [ row[6],'==',space[:electric_w_per_m2] , "Table A-8.4.3.3.1" ,1 ] unless space[:electric_w_per_m2].nil?
826
- data.each do |key,value|
827
- #puts key
828
- necb_section_test(
829
- qaqc,
830
- value[0],
831
- value[1],
832
- value[2],
833
- value[3],
834
- "[SPACE][#{space[:name]}]-[TYPE:][#{space_type}]#{key}",
835
- value[4]
836
- )
837
- end
838
- end#space Compliance
839
- end
840
- #Padmassun's Code End
841
-
842
-
843
- # Envelope
844
- necb_section_name = "NECB2011-Section 3.2.1.4"
845
- #store hdd in short form
846
- hdd = qaqc[:geography][:hdd]
847
- #calculate fdwr based on hdd.
848
- fdwr = 0
849
- if hdd < 4000
850
- fdwr = 0.40
851
- elsif hdd >= 4000 and hdd <=7000
852
- fdwr = (2000-0.2 * hdd)/3000
853
- elsif hdd >7000
854
- fdwr = 0.20
855
- end
856
- #hardset srr to 0.05
857
- srr = 0.05
858
- #create table of expected values and results.
859
- data = {}
860
- data[:fenestration_to_door_and_window_percentage] = [ fdwr * 100,qaqc[:envelope][:fdwr].round(3)]
861
- data[:skylight_to_roof_percentage] = [ srr * 100,qaqc[:envelope][:srr].round(3)]
862
- #perform test. result must be less than or equal to.
863
- data.each {|key,value| necb_section_test(
864
- qaqc,
865
- value[0],
866
- '>=',
867
- value[1],
868
- necb_section_name,
869
- "[ENVELOPE]#{key}",
870
- 1 #padmassun added tollerance
871
- )
872
- }
873
-
874
- #Infiltration
875
- necb_section_name = "NECB2011-Section 8.4.3.6"
876
- qaqc[:spaces].each do |spaceinfo|
877
- data = {}
878
- data[:infiltration_method] = [ "Flow/ExteriorArea", spaceinfo[:infiltration_method] , nil ]
879
- data[:infiltration_flow_per_m2] = [ 0.00025, spaceinfo[:infiltration_flow_per_m2], 5 ]
880
- data.each do |key,value|
881
- #puts key
882
- necb_section_test(
883
- qaqc,
884
- value[0],
885
- '==',
886
- value[1],
887
- necb_section_name,
888
- "[SPACE][#{spaceinfo[:name]}]-#{key}",
889
- value[2]
890
- )
891
- end
892
- end
893
- #Exterior Opaque
894
- necb_section_name = "NECB2011-Section 3.2.2.2"
895
- climate_index = NECB2011.new().get_climate_zone_index(qaqc[:geography][:hdd])
896
- result_value_index = 6
897
- round_precision = 3
898
- data = {}
899
- data[:ext_wall_conductances] = [0.315,0.278,0.247,0.210,0.210,0.183,qaqc[:envelope][:outdoor_walls_average_conductance_w_per_m2_k]] unless qaqc[:envelope][:outdoor_walls_average_conductance_w_per_m2_k].nil?
900
- data[:ext_roof_conductances] = [0.227,0.183,0.183,0.162,0.162,0.142,qaqc[:envelope][:outdoor_roofs_average_conductance_w_per_m2_k]] unless qaqc[:envelope][:outdoor_roofs_average_conductance_w_per_m2_k].nil?
901
- data[:ext_floor_conductances] = [0.227,0.183,0.183,0.162,0.162,0.142,qaqc[:envelope][:outdoor_floors_average_conductance_w_per_m2_k]] unless qaqc[:envelope][:outdoor_floors_average_conductance_w_per_m2_k].nil?
902
-
903
- data.each {|key,value| necb_section_test(
904
- qaqc,
905
- value[result_value_index],
906
- '==',
907
- value[climate_index],
908
- necb_section_name,
909
- "[ENVELOPE]#{key}",
910
- round_precision
911
- )
912
- }
913
- #Exterior Fenestration
914
- necb_section_name = "NECB2011-Section 3.2.2.3"
915
- climate_index = NECB2011.new().get_climate_zone_index(qaqc[:geography][:hdd])
916
- result_value_index = 6
917
- round_precision = 3
918
- data = {}
919
- data[:ext_window_conductances] = [2.400,2.200,2.200,2.200,2.200,1.600,qaqc[:envelope][:windows_average_conductance_w_per_m2_k]] unless qaqc[:envelope][:windows_average_conductance_w_per_m2_k].nil?
920
- data[:ext_door_conductances] = [2.400,2.200,2.200,2.200,2.200,1.600,qaqc[:envelope][:doors_average_conductance_w_per_m2_k]] unless qaqc[:envelope][:doors_average_conductance_w_per_m2_k].nil?
921
- data[:ext_overhead_door_conductances] = [2.400,2.200,2.200,2.200,2.200,1.600,qaqc[:envelope][:overhead_doors_average_conductance_w_per_m2_k]] unless qaqc[:envelope][:overhead_doors_average_conductance_w_per_m2_k].nil?
922
- data[:ext_skylight_conductances] = [2.400,2.200,2.200,2.200,2.200,1.600,qaqc[:envelope][:skylights_average_conductance_w_per_m2_k]] unless qaqc[:envelope][:skylights_average_conductance_w_per_m2_k].nil?
923
- data.each do |key,value|
924
-
925
- #puts key
926
- necb_section_test(
927
- qaqc,
928
- value[result_value_index].round(round_precision),
929
- '==',
930
- value[climate_index].round(round_precision),
931
- necb_section_name,
932
- "[ENVELOPE]#{key}",
933
- round_precision
934
- )
935
- end
936
- #Exterior Ground surfaces
937
- necb_section_name = "NECB2011-Section 3.2.3.1"
938
- climate_index = NECB2011.new().get_climate_zone_index(qaqc[:geography][:hdd])
939
- result_value_index = 6
940
- round_precision = 3
941
- data = {}
942
- data[:ground_wall_conductances] = [ 0.568,0.379,0.284,0.284,0.284,0.210, qaqc[:envelope][:ground_walls_average_conductance_w_per_m2_k] ] unless qaqc[:envelope][:ground_walls_average_conductance_w_per_m2_k].nil?
943
- data[:ground_roof_conductances] = [ 0.568,0.379,0.284,0.284,0.284,0.210, qaqc[:envelope][:ground_roofs_average_conductance_w_per_m2_k] ] unless qaqc[:envelope][:ground_roofs_average_conductance_w_per_m2_k].nil?
944
- data[:ground_floor_conductances] = [ 0.757,0.757,0.757,0.757,0.757,0.379, qaqc[:envelope][:ground_floors_average_conductance_w_per_m2_k] ] unless qaqc[:envelope][:ground_floors_average_conductance_w_per_m2_k].nil?
945
- data.each {|key,value| necb_section_test(
946
- qaqc,
947
- value[result_value_index],
948
- '==',
949
- value[climate_index],
950
- necb_section_name,
951
- "[ENVELOPE]#{key}",
952
- round_precision
953
- )
954
- }
955
- #Zone Sizing and design supply temp tests
956
- necb_section_name = "NECB2011-?"
957
- qaqc[:thermal_zones].each do |zoneinfo|
958
- # skipping undefined schedules
959
- if zoneinfo[:name].to_s.include?"- undefined -"
960
- next
961
- end
962
- data = {}
963
- data[:heating_sizing_factor] = [1.3 , zoneinfo[:heating_sizing_factor]]
964
- data[:cooling_sizing_factor] = [1.1 ,zoneinfo[:cooling_sizing_factor]]
965
- data[:heating_design_supply_air_temp] = [43.0, zoneinfo[:zone_heating_design_supply_air_temperature] ] #unless zoneinfo[:zone_heating_design_supply_air_temperature].nil?
966
- data[:cooling_design_supply_temp] = [13.0, zoneinfo[:zone_cooling_design_supply_air_temperature] ]
967
- data.each do |key,value|
968
- #puts key
969
- necb_section_test(
970
- qaqc,
971
- value[0],
972
- '==',
973
- value[1],
974
- necb_section_name,
975
- "[ZONE][#{zoneinfo[:name]}] #{key}",
976
- round_precision
977
- )
978
- end
979
- end
980
- #Air flow sizing check
981
- #determine correct economizer usage according to section 5.2.2.7 of NECB2011
982
- necb_section_name = "NECB2011-5.2.2.7"
983
- qaqc[:air_loops].each do |air_loop_info|
984
- # air_loop_info[:name]
985
- # air_loop_info[:thermal_zones]
986
- # air_loop_info[:total_floor_area_served]
987
- # air_loop_info[:cooling_coils][:dx_single_speed]
988
- # air_loop_info[:cooling_coils][:dx_two_speed]
989
- # air_loop_info[:supply_fan][:max_air_flow_rate]
990
- #
991
- # air_loop_info[:heating_coils][:coil_heating_gas][:nominal_capacity]
992
- # air_loop_info[:heating_coils][:coil_heating_electric][:nominal_capacity]
993
- # air_loop_info[:heating_coils][:coil_heating_water][:nominal_capacity]
994
- #
995
- # air_loop_info[:economizer][:control_type]
996
-
997
- capacity = -1.0
998
-
999
- if !air_loop_info[:cooling_coils][:dx_single_speed][0].nil?
1000
- puts "air_loop_info[:heating_coils][:coil_heating_gas][0][:nominal_capacity]"
1001
- capacity = air_loop_info[:cooling_coils][:dx_single_speed][0][:nominal_total_capacity_w]
1002
- elsif !air_loop_info[:cooling_coils][:dx_two_speed][0].nil?
1003
- puts "capacity = air_loop_info[:heating_coils][:coil_heating_electric]"
1004
- capacity = air_loop_info[:cooling_coils][:dx_two_speed][0][:cop_high]
1005
- end
1006
- puts capacity
1007
- if capacity == -1.0
1008
- #This should not happen
1009
- puts "air_loop_info[:heating_coils] does not have a capacity or the type is not gas/electric/water for #{air_loop_info[:name]}"
1010
- else
1011
- #check for correct economizer usage
1012
- puts "air_loop_info[:supply_fan][:max_air_flow_rate]: #{air_loop_info[:supply_fan][:max_air_flow_rate]}"
1013
- unless air_loop_info[:supply_fan][:max_air_flow_rate_m3_per_s] == -1.0
1014
- #capacity should be in kW
1015
- if capacity > 20000 or air_loop_info[:supply_fan][:max_air_flow_rate_m3_per_s]*1000 >1500
1016
- #diff enth
1017
- #puts "diff"
1018
- necb_section_test(
1019
- qaqc,
1020
- "DifferentialEnthalpy",
1021
- '==',
1022
- air_loop_info[:economizer][:control_type],
1023
- necb_section_name,
1024
- "[AIR LOOP][#{air_loop_info[:name]}][:economizer][:control_type]"
1025
- )
1026
- else
1027
- #no economizer
1028
- #puts "no econ"
1029
- necb_section_test(
1030
- qaqc,
1031
- 'NoEconomizer',
1032
- '==',
1033
- air_loop_info[:economizer][:control_type],
1034
- necb_section_name,
1035
- "[AIR LOOP][#{air_loop_info[:name]}][:economizer][:control_type]"
1036
- )
1037
- end
1038
- end
1039
- end
1040
- end
1041
-
1042
- # @todo ?
1043
- necb_section_name = "NECB2011-5.2.10.1"
1044
- qaqc[:air_loops].each do |air_loop_info|
1045
- unless air_loop_info[:supply_fan][:max_air_flow_rate_m3_per_s] == -1.0
1046
- weather_file_path = model.weatherFile.get.path.get.to_s
1047
- stat_file_path = weather_file_path.gsub('.epw', '.stat')
1048
- stat_file = OpenstudioStandards::Weather::StatFile.new(stat_file_path)
1049
- db990 = stat_file.heating_design_info[2]
1050
- hrv_calc = 0.00123 * air_loop_info[:outdoor_air_L_per_s] * (21 - db990) #=AP46*(21-O$1)
1051
- hrv_reqd = hrv_calc > 150 ? true : false
1052
- #qaqc[:information] << "[Info][TEST-PASS][#{necb_section_name}]:#{test_text} result value:#{result_value} #{bool_operator} expected value:#{expected_value}"
1053
- hrv_present = false
1054
- unless air_loop_info[:heat_exchanger].empty?
1055
- hrv_present = true
1056
- end
1057
- necb_section_test(
1058
- qaqc,
1059
- hrv_reqd,
1060
- '==',
1061
- hrv_present,
1062
- necb_section_name,
1063
- "[AIR LOOP][:heat_exchanger] for [#{air_loop_info[:name]}] is present?"
1064
- )
1065
-
1066
- end
1067
- end
1068
-
1069
- necb_section_name = "NECB2011-5.2.3.3"
1070
- qaqc[:air_loops].each do |air_loop_info|
1071
- #necb_clg_cop = air_loop_info[:cooling_coils][:dx_single_speed][:cop] #*assuming that the cop is defined correctly*
1072
- if air_loop_info[:supply_fan][:max_air_flow_rate_m3_per_s].nil?
1073
- qaqc[:ruby_warnings] << "air_loop_info[:supply_fan][:max_air_flow_rate_m3_per_s] is nil"
1074
- next
1075
- end
1076
- necb_supply_fan_w = (air_loop_info[:supply_fan][:max_air_flow_rate_m3_per_s]*1000*1.6).round(2)
1077
-
1078
- if air_loop_info[:name].include? "PSZ"
1079
- necb_supply_fan_w = (air_loop_info[:supply_fan][:max_air_flow_rate_m3_per_s]*1000*1.6).round(2)
1080
- elsif air_loop_info[:name].include? "VAV"
1081
- necb_supply_fan_w = (air_loop_info[:supply_fan][:max_air_flow_rate_m3_per_s]*1000*2.65).round(2)
1082
- end
1083
-
1084
- if air_loop_info[:supply_fan][:rated_electric_power_w].nil?
1085
- qaqc[:ruby_warnings] << "air_loop_info[:supply_fan][:rated_electric_power_w] is nil"
1086
- next
1087
- end
1088
-
1089
- supply_fan_w = (air_loop_info[:supply_fan][:rated_electric_power_w]).round(3)
1090
- absolute_diff = (necb_supply_fan_w - supply_fan_w).to_f.abs
1091
- if absolute_diff < 10
1092
- #This case should ALWAYS PASS
1093
- necb_section_test(
1094
- qaqc,
1095
- 10,
1096
- '>=',
1097
- absolute_diff,
1098
- necb_section_name,
1099
- "[AIR LOOP][#{air_loop_info[:name]}][:supply_fan][:rated_electric_power_w] [#{supply_fan_w}] Absolute Difference from NECB value [#{necb_supply_fan_w}]"
1100
- )
1101
- next
1102
- else
1103
- #The test should pass if and only if the percent difference is less than 10%
1104
- percent_diff = ((necb_supply_fan_w - supply_fan_w).to_f.abs/necb_supply_fan_w * 100).round(3)
1105
- necb_section_test(
1106
- qaqc,
1107
- 10,
1108
- '>=',
1109
- percent_diff,
1110
- necb_section_name,
1111
- "[AIR LOOP][#{air_loop_info[:name]}][:supply_fan][:rated_electric_power_w] [#{supply_fan_w}] Percent Diff from NECB value [#{necb_supply_fan_w}]"
1112
- )
1113
- end
1114
- end
1115
-
1116
- necb_section_name = "SANITY-??"
1117
- qaqc[:plant_loops].each do |plant_loop_info|
1118
- pump_head = plant_loop_info[:pumps][0][:head_pa]
1119
- flow_rate = plant_loop_info[:pumps][0][:water_flow_m3_per_s]*1000
1120
- hp_check = ((flow_rate*60*60)/1000*1000*9.81*pump_head*0.000101997)/3600000
1121
- puts "\npump_head #{pump_head}"
1122
- puts "name: #{qaqc[:building][:name]}"
1123
- puts "name: #{plant_loop_info[:name]}"
1124
- puts "flow_rate #{flow_rate}"
1125
- puts "hp_check #{hp_check}\n"
1126
- pump_power_hp = plant_loop_info[:pumps][0][:electric_power_w]/1000*0.746
1127
- percent_diff = (hp_check - pump_power_hp).to_f.abs/hp_check * 100
1128
-
1129
- if percent_diff.nan?
1130
- qaqc[:ruby_warnings] << "(hp_check - pump_power_hp).to_f.abs/hp_check * 100 for #{plant_loop_info[:name]} is NaN"
1131
- next
1132
- end
1133
-
1134
- necb_section_test(
1135
- qaqc,
1136
- 20, #diff of 20%
1137
- '>=',
1138
- percent_diff,
1139
- necb_section_name,
1140
- "[PLANT LOOP][#{plant_loop_info[:name]}][:pumps][0][:electric_power_hp] [#{pump_power_hp}] Percent Diff from NECB value [#{hp_check}]"
1141
- )
1142
-
1143
- end
1144
- end