openstudio-standards 0.1.2 → 0.1.3
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.
- checksums.yaml +4 -4
- data/data/standards/OpenStudio_Standards.xlsx +0 -0
- data/data/standards/OpenStudio_Standards_prototype_inputs.json +9 -9
- data/data/standards/OpenStudio_Standards_space_types.json +11 -67
- data/lib/openstudio-standards/prototypes/Prototype.Model.hvac.rb +5 -5
- data/lib/openstudio-standards/prototypes/Prototype.Model.rb +10 -9
- data/lib/openstudio-standards/prototypes/Prototype.hvac_systems.rb +42 -16
- data/lib/openstudio-standards/prototypes/Prototype.outpatient.rb +166 -23
- data/lib/openstudio-standards/standards/Standards.AirLoopHVAC.rb +74 -10
- data/lib/openstudio-standards/standards/Standards.CoilCoolingDXSingleSpeed.rb +3 -4
- data/lib/openstudio-standards/standards/Standards.CoilHeatingDXSingleSpeed.rb +8 -43
- data/lib/openstudio-standards/standards/Standards.Fan.rb +1 -1
- data/lib/openstudio-standards/utilities/simulation.rb +47 -2
- data/lib/openstudio-standards/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 3b528f4fbfe4f287e792b723a0eca90ab045cd22
|
|
4
|
+
data.tar.gz: 8a5d326de020f16dc1803900c901cdbfbd94b289
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 993958fe7f17a8ee6ec9d5a853889965a39787e7d76fe198773da1d054bc8440712cbb5b938f1c7bff23d73a00ee59112811f18bdc8fd6f236f2a023cde4d324
|
|
7
|
+
data.tar.gz: c7e95e06ca70daafe9aa056ec08ef2a88ce78aee4c4f0d648512979d54c37bfe16f4c35351f6d26bcbb00f3c639ad7f2d1557859ac38b39718183e5d7d069cff
|
|
Binary file
|
|
@@ -712,7 +712,7 @@
|
|
|
712
712
|
"chiller_condenser_type": null,
|
|
713
713
|
"chiller_compressor_type": "Centrifugal",
|
|
714
714
|
"chiller_capacity_guess": 250.0,
|
|
715
|
-
"pszac_cooling_type": "
|
|
715
|
+
"pszac_cooling_type": "Water",
|
|
716
716
|
"pszac_heating_type": "Water",
|
|
717
717
|
"pszac_fan_type": "ConstantVolume",
|
|
718
718
|
"pszac_supplemental_heating_type": "Electricity",
|
|
@@ -740,27 +740,27 @@
|
|
|
740
740
|
"main_service_water_temperature_at_fixture": 140.0,
|
|
741
741
|
"main_service_water_pump_head": 29891.0,
|
|
742
742
|
"main_service_water_pump_motor_efficiency": 0.3,
|
|
743
|
-
"main_service_water_parasitic_fuel_consumption_rate":
|
|
744
|
-
"laundry_water_heater_volume":
|
|
743
|
+
"main_service_water_parasitic_fuel_consumption_rate": 10024.0,
|
|
744
|
+
"laundry_water_heater_volume": 300.0,
|
|
745
745
|
"laundry_water_heater_fuel": "Natural Gas",
|
|
746
|
-
"laundry_water_heater_capacity":
|
|
746
|
+
"laundry_water_heater_capacity": 300000.0,
|
|
747
747
|
"laundry_service_water_temperature": 140.0,
|
|
748
748
|
"laundry_service_water_flowrate_schedule": "Hospital LAUNDRY_SWH_SCH",
|
|
749
749
|
"laundry_service_water_peak_flowrate": 2.8,
|
|
750
750
|
"laundry_water_use_temperature": 180.0,
|
|
751
751
|
"laundry_service_water_temperature_at_fixture": 180.0,
|
|
752
|
-
"laundry_service_water_pump_head":
|
|
753
|
-
"laundry_service_water_pump_motor_efficiency":
|
|
754
|
-
"laundry_service_water_parasitic_fuel_consumption_rate":
|
|
752
|
+
"laundry_service_water_pump_head": null,
|
|
753
|
+
"laundry_service_water_pump_motor_efficiency": null,
|
|
754
|
+
"laundry_service_water_parasitic_fuel_consumption_rate": 0.0,
|
|
755
755
|
"booster_water_heater_volume": 6.0,
|
|
756
756
|
"booster_water_heater_fuel": "Electricity",
|
|
757
|
-
"booster_water_heater_capacity":
|
|
757
|
+
"booster_water_heater_capacity": 10236.0,
|
|
758
758
|
"booster_inlet_water_temperature": 140.0,
|
|
759
759
|
"booster_service_water_flowrate_schedule": "Hospital BLDG_SWH_SCH",
|
|
760
760
|
"booster_service_water_peak_flowrate": 23.7,
|
|
761
761
|
"booster_water_use_temperature": 180.0,
|
|
762
762
|
"booster_water_temperature": 180.0,
|
|
763
|
-
"booster_service_water_parasitic_fuel_consumption_rate":
|
|
763
|
+
"booster_service_water_parasitic_fuel_consumption_rate": 0.0,
|
|
764
764
|
"typical_heating_setpoint": "Hospital Bldg HtgSetp",
|
|
765
765
|
"typical_cooling_setpoint": "Hospital Bldg ClgSetp",
|
|
766
766
|
"ptac_cooling_type": null,
|
|
@@ -7874,7 +7874,7 @@
|
|
|
7874
7874
|
"gas_equipment_fraction_radiant": null,
|
|
7875
7875
|
"gas_equipment_fraction_lost": null,
|
|
7876
7876
|
"gas_equipment_schedule": null,
|
|
7877
|
-
"electric_equipment_per_area":
|
|
7877
|
+
"electric_equipment_per_area": 1.36,
|
|
7878
7878
|
"electric_equipment_fraction_latent": 0.0,
|
|
7879
7879
|
"electric_equipment_fraction_radiant": 0.5,
|
|
7880
7880
|
"electric_equipment_fraction_lost": 0.0,
|
|
@@ -8434,7 +8434,7 @@
|
|
|
8434
8434
|
"gas_equipment_fraction_radiant": null,
|
|
8435
8435
|
"gas_equipment_fraction_lost": null,
|
|
8436
8436
|
"gas_equipment_schedule": null,
|
|
8437
|
-
"electric_equipment_per_area":
|
|
8437
|
+
"electric_equipment_per_area": 4.0,
|
|
8438
8438
|
"electric_equipment_fraction_latent": 0.0,
|
|
8439
8439
|
"electric_equipment_fraction_radiant": 0.5,
|
|
8440
8440
|
"electric_equipment_fraction_lost": 0.0,
|
|
@@ -25686,7 +25686,7 @@
|
|
|
25686
25686
|
"electric_equipment_fraction_latent": 0.0,
|
|
25687
25687
|
"electric_equipment_fraction_radiant": 0.5,
|
|
25688
25688
|
"electric_equipment_fraction_lost": 0.0,
|
|
25689
|
-
"electric_equipment_schedule": "Hospital
|
|
25689
|
+
"electric_equipment_schedule": "Hospital BLDG_EQUIP_EXTD_SCH",
|
|
25690
25690
|
"heating_setpoint_schedule": "Hospital HTGSETP_SCH",
|
|
25691
25691
|
"cooling_setpoint_schedule": "Hospital CLGSETP_SCH",
|
|
25692
25692
|
"service_water_heating_peak_flow_rate": null,
|
|
@@ -25794,7 +25794,7 @@
|
|
|
25794
25794
|
"gas_equipment_fraction_radiant": null,
|
|
25795
25795
|
"gas_equipment_fraction_lost": null,
|
|
25796
25796
|
"gas_equipment_schedule": null,
|
|
25797
|
-
"electric_equipment_per_area":
|
|
25797
|
+
"electric_equipment_per_area": 1.36,
|
|
25798
25798
|
"electric_equipment_fraction_latent": 0.0,
|
|
25799
25799
|
"electric_equipment_fraction_radiant": 0.5,
|
|
25800
25800
|
"electric_equipment_fraction_lost": 0.0,
|
|
@@ -26298,7 +26298,7 @@
|
|
|
26298
26298
|
"gas_equipment_fraction_radiant": null,
|
|
26299
26299
|
"gas_equipment_fraction_lost": null,
|
|
26300
26300
|
"gas_equipment_schedule": null,
|
|
26301
|
-
"electric_equipment_per_area":
|
|
26301
|
+
"electric_equipment_per_area": 1.04,
|
|
26302
26302
|
"electric_equipment_fraction_latent": 0.0,
|
|
26303
26303
|
"electric_equipment_fraction_radiant": 0.5,
|
|
26304
26304
|
"electric_equipment_fraction_lost": 0.0,
|
|
@@ -26354,7 +26354,7 @@
|
|
|
26354
26354
|
"gas_equipment_fraction_radiant": null,
|
|
26355
26355
|
"gas_equipment_fraction_lost": null,
|
|
26356
26356
|
"gas_equipment_schedule": null,
|
|
26357
|
-
"electric_equipment_per_area":
|
|
26357
|
+
"electric_equipment_per_area": 4.0,
|
|
26358
26358
|
"electric_equipment_fraction_latent": 0.0,
|
|
26359
26359
|
"electric_equipment_fraction_radiant": 0.5,
|
|
26360
26360
|
"electric_equipment_fraction_lost": 0.0,
|
|
@@ -26384,7 +26384,7 @@
|
|
|
26384
26384
|
"lighting_standard": "ASHRAE 90.1-2010",
|
|
26385
26385
|
"lighting_primary_space_type": "Office-Enclosed",
|
|
26386
26386
|
"lighting_secondary_space_type": "General",
|
|
26387
|
-
"lighting_per_area": 1.
|
|
26387
|
+
"lighting_per_area": 1.0,
|
|
26388
26388
|
"lighting_per_person": null,
|
|
26389
26389
|
"additional_lighting_per_area": null,
|
|
26390
26390
|
"lighting_fraction_to_return_air": 0.0,
|
|
@@ -26410,7 +26410,7 @@
|
|
|
26410
26410
|
"gas_equipment_fraction_radiant": null,
|
|
26411
26411
|
"gas_equipment_fraction_lost": null,
|
|
26412
26412
|
"gas_equipment_schedule": null,
|
|
26413
|
-
"electric_equipment_per_area": 0
|
|
26413
|
+
"electric_equipment_per_area": 1.0,
|
|
26414
26414
|
"electric_equipment_fraction_latent": 0.0,
|
|
26415
26415
|
"electric_equipment_fraction_radiant": 0.5,
|
|
26416
26416
|
"electric_equipment_fraction_lost": 0.0,
|
|
@@ -26526,7 +26526,7 @@
|
|
|
26526
26526
|
"electric_equipment_fraction_latent": 0.0,
|
|
26527
26527
|
"electric_equipment_fraction_radiant": 0.5,
|
|
26528
26528
|
"electric_equipment_fraction_lost": 0.0,
|
|
26529
|
-
"electric_equipment_schedule": "Hospital
|
|
26529
|
+
"electric_equipment_schedule": "Hospital BLDG_EQUIP_EXTD_SCH",
|
|
26530
26530
|
"heating_setpoint_schedule": "Hospital HTGSETP_SCH",
|
|
26531
26531
|
"cooling_setpoint_schedule": "Hospital CLGSETP_SCH",
|
|
26532
26532
|
"service_water_heating_peak_flow_rate": 1.0,
|
|
@@ -36960,62 +36960,6 @@
|
|
|
36960
36960
|
"balanced_exhaust_fraction_schedule": null,
|
|
36961
36961
|
"is_residential": null
|
|
36962
36962
|
},
|
|
36963
|
-
{
|
|
36964
|
-
"template": "90.1-2013",
|
|
36965
|
-
"building_type": "Office",
|
|
36966
|
-
"space_type": "Attic",
|
|
36967
|
-
"rgb": "120_149_230",
|
|
36968
|
-
"lighting_standard": "ASHRAE 189.1-2009",
|
|
36969
|
-
"lighting_primary_space_type": "Attics",
|
|
36970
|
-
"lighting_secondary_space_type": "General",
|
|
36971
|
-
"lighting_per_area": 0,
|
|
36972
|
-
"lighting_per_person": null,
|
|
36973
|
-
"additional_lighting_per_area": null,
|
|
36974
|
-
"lighting_fraction_to_return_air": null,
|
|
36975
|
-
"lighting_fraction_radiant": null,
|
|
36976
|
-
"lighting_fraction_visible": null,
|
|
36977
|
-
"lighting_schedule": null,
|
|
36978
|
-
"ventilation_standard": null,
|
|
36979
|
-
"ventilation_primary_space_type": null,
|
|
36980
|
-
"ventilation_secondary_space_type": null,
|
|
36981
|
-
"ventilation_per_area": null,
|
|
36982
|
-
"ventilation_per_person": null,
|
|
36983
|
-
"ventilation_air_changes": null,
|
|
36984
|
-
"minimum_total_air_changes": null,
|
|
36985
|
-
"occupancy_per_area": null,
|
|
36986
|
-
"occupancy_schedule": null,
|
|
36987
|
-
"occupancy_activity_schedule": null,
|
|
36988
|
-
"infiltration_per_exterior_area": 0.112,
|
|
36989
|
-
"infiltration_per_exterior_wall_area": null,
|
|
36990
|
-
"infiltration_air_changes": null,
|
|
36991
|
-
"infiltration_schedule": "OfficeMedium INFIL_SCH_PNNL",
|
|
36992
|
-
"gas_equipment_per_area": null,
|
|
36993
|
-
"gas_equipment_fraction_latent": null,
|
|
36994
|
-
"gas_equipment_fraction_radiant": null,
|
|
36995
|
-
"gas_equipment_fraction_lost": null,
|
|
36996
|
-
"gas_equipment_schedule": null,
|
|
36997
|
-
"electric_equipment_per_area": null,
|
|
36998
|
-
"electric_equipment_fraction_latent": null,
|
|
36999
|
-
"electric_equipment_fraction_radiant": null,
|
|
37000
|
-
"electric_equipment_fraction_lost": null,
|
|
37001
|
-
"electric_equipment_schedule": null,
|
|
37002
|
-
"heating_setpoint_schedule": null,
|
|
37003
|
-
"cooling_setpoint_schedule": null,
|
|
37004
|
-
"service_water_heating_peak_flow_rate": null,
|
|
37005
|
-
"service_water_heating_area": null,
|
|
37006
|
-
"service_water_heating_peak_flow_per_area": "",
|
|
37007
|
-
"service_water_heating_target_temperature": null,
|
|
37008
|
-
"service_water_heating_fraction_sensible": null,
|
|
37009
|
-
"service_water_heating_fraction_latent": null,
|
|
37010
|
-
"service_water_heating_schedule": null,
|
|
37011
|
-
"exhaust_fan_efficiency": null,
|
|
37012
|
-
"exhaust_fan_power": null,
|
|
37013
|
-
"exhaust_fan_pressure_rise": null,
|
|
37014
|
-
"exhaust_fan_maximum_flow_rate": null,
|
|
37015
|
-
"exhaust_schedule": null,
|
|
37016
|
-
"balanced_exhaust_fraction_schedule": null,
|
|
37017
|
-
"is_residential": null
|
|
37018
|
-
},
|
|
37019
36963
|
{
|
|
37020
36964
|
"template": "90.1-2013",
|
|
37021
36965
|
"building_type": "Office",
|
|
@@ -60467,7 +60411,7 @@
|
|
|
60467
60411
|
"cooling_setpoint_schedule": "NECB-A-Thermostat Setpoint-Cooling",
|
|
60468
60412
|
"service_water_heating_peak_flow_rate": null,
|
|
60469
60413
|
"service_water_heating_area": null,
|
|
60470
|
-
"service_water_heating_peak_flow_per_area":
|
|
60414
|
+
"service_water_heating_peak_flow_per_area": "",
|
|
60471
60415
|
"service_water_heating_target_temperature": null,
|
|
60472
60416
|
"service_water_heating_fraction_sensible": null,
|
|
60473
60417
|
"service_water_heating_fraction_latent": null,
|
|
@@ -60523,7 +60467,7 @@
|
|
|
60523
60467
|
"cooling_setpoint_schedule": "NECB-A-Thermostat Setpoint-Cooling",
|
|
60524
60468
|
"service_water_heating_peak_flow_rate": null,
|
|
60525
60469
|
"service_water_heating_area": null,
|
|
60526
|
-
"service_water_heating_peak_flow_per_area":
|
|
60470
|
+
"service_water_heating_peak_flow_per_area": null,
|
|
60527
60471
|
"service_water_heating_target_temperature": null,
|
|
60528
60472
|
"service_water_heating_fraction_sensible": null,
|
|
60529
60473
|
"service_water_heating_fraction_latent": null,
|
|
@@ -27,7 +27,7 @@ class OpenStudio::Model::Model
|
|
|
27
27
|
if self.getPlantLoopByName('Hot Water Loop').is_initialized
|
|
28
28
|
hot_water_loop = self.getPlantLoopByName('Hot Water Loop').get
|
|
29
29
|
else
|
|
30
|
-
hot_water_loop = self.add_hw_loop('NaturalGas')
|
|
30
|
+
hot_water_loop = self.add_hw_loop('NaturalGas',building_type)
|
|
31
31
|
end
|
|
32
32
|
|
|
33
33
|
# Retrieve the existing chilled water loop
|
|
@@ -73,7 +73,7 @@ class OpenStudio::Model::Model
|
|
|
73
73
|
if self.getPlantLoopByName('Hot Water Loop').is_initialized
|
|
74
74
|
hot_water_loop = self.getPlantLoopByName('Hot Water Loop').get
|
|
75
75
|
else
|
|
76
|
-
hot_water_loop = self.add_hw_loop('NaturalGas')
|
|
76
|
+
hot_water_loop = self.add_hw_loop('NaturalGas',building_type)
|
|
77
77
|
end
|
|
78
78
|
|
|
79
79
|
# Add the CAV
|
|
@@ -142,7 +142,7 @@ class OpenStudio::Model::Model
|
|
|
142
142
|
elsif building_type == 'MediumOffice'
|
|
143
143
|
hot_water_loop = nil
|
|
144
144
|
else
|
|
145
|
-
hot_water_loop = self.add_hw_loop('NaturalGas')
|
|
145
|
+
hot_water_loop = self.add_hw_loop('NaturalGas',building_type)
|
|
146
146
|
end
|
|
147
147
|
|
|
148
148
|
self.add_pvav(building_vintage,
|
|
@@ -162,7 +162,7 @@ class OpenStudio::Model::Model
|
|
|
162
162
|
if self.getPlantLoopByName('Hot Water Loop').is_initialized
|
|
163
163
|
hot_water_loop = self.getPlantLoopByName('Hot Water Loop').get
|
|
164
164
|
else
|
|
165
|
-
hot_water_loop = self.add_hw_loop('NaturalGas')
|
|
165
|
+
hot_water_loop = self.add_hw_loop('NaturalGas',building_type)
|
|
166
166
|
end
|
|
167
167
|
|
|
168
168
|
# Retrieve the existing chilled water loop
|
|
@@ -204,7 +204,7 @@ class OpenStudio::Model::Model
|
|
|
204
204
|
if self.getPlantLoopByName('Hot Water Loop').is_initialized
|
|
205
205
|
hot_water_loop = self.getPlantLoopByName('Hot Water Loop').get
|
|
206
206
|
else
|
|
207
|
-
hot_water_loop = self.add_hw_loop('NaturalGas')
|
|
207
|
+
hot_water_loop = self.add_hw_loop('NaturalGas',building_type)
|
|
208
208
|
end
|
|
209
209
|
|
|
210
210
|
# Retrieve the existing heat pump loop
|
|
@@ -95,14 +95,6 @@ class OpenStudio::Model::Model
|
|
|
95
95
|
# on the flow rate of the system.
|
|
96
96
|
self.applyPrototypeHVACAssumptions(building_type, building_vintage, climate_zone)
|
|
97
97
|
|
|
98
|
-
# for 90.1-2010 Outpatient, AHU2 set minimum outdoor air flow rate as 0
|
|
99
|
-
# AHU1 doesn't have economizer
|
|
100
|
-
if building_type == "Outpatient"
|
|
101
|
-
self.modify_OAcontroller(building_vintage)
|
|
102
|
-
# For operating room 1&2 in 2010 and 2013, VAV minimum air flow is set by schedule
|
|
103
|
-
self.reset_or_room_vav_minimum_damper(prototype_input, building_vintage)
|
|
104
|
-
end
|
|
105
|
-
|
|
106
98
|
# Apply the HVAC efficiency standard
|
|
107
99
|
self.applyHVACEfficiencyStandard(building_vintage, climate_zone)
|
|
108
100
|
|
|
@@ -115,7 +107,7 @@ class OpenStudio::Model::Model
|
|
|
115
107
|
self.add_daylighting_controls(building_vintage)
|
|
116
108
|
end
|
|
117
109
|
|
|
118
|
-
if building_type == "QuickServiceRestaurant" || building_type == "FullServiceRestaurant"
|
|
110
|
+
if building_type == "QuickServiceRestaurant" || building_type == "FullServiceRestaurant" || building_type == "Outpatient"
|
|
119
111
|
self.update_exhaust_fan_efficiency(building_vintage)
|
|
120
112
|
end
|
|
121
113
|
|
|
@@ -123,6 +115,15 @@ class OpenStudio::Model::Model
|
|
|
123
115
|
self.update_fan_efficiency
|
|
124
116
|
end
|
|
125
117
|
|
|
118
|
+
# for 90.1-2010 Outpatient, AHU2 set minimum outdoor air flow rate as 0
|
|
119
|
+
# AHU1 doesn't have economizer
|
|
120
|
+
if building_type == "Outpatient"
|
|
121
|
+
# remove the controller:mechanical ventilation for AHU1 OA
|
|
122
|
+
self.modify_OAcontroller(building_vintage)
|
|
123
|
+
# For operating room 1&2 in 2010 and 2013, VAV minimum air flow is set by schedule
|
|
124
|
+
self.reset_or_room_vav_minimum_damper(prototype_input, building_vintage)
|
|
125
|
+
end
|
|
126
|
+
|
|
126
127
|
# Add output variables for debugging
|
|
127
128
|
if debug
|
|
128
129
|
self.request_timeseries_outputs
|
|
@@ -42,17 +42,16 @@ class OpenStudio::Model::Model
|
|
|
42
42
|
sizing_plant.setLoopDesignTemperatureDifference(hw_delta_t_k)
|
|
43
43
|
|
|
44
44
|
#hot water pump
|
|
45
|
-
|
|
45
|
+
if building_type == "Outpatient"
|
|
46
|
+
hw_pump = OpenStudio::Model::PumpConstantSpeed.new(self)
|
|
47
|
+
else
|
|
48
|
+
hw_pump = OpenStudio::Model::PumpVariableSpeed.new(self)
|
|
49
|
+
end
|
|
46
50
|
hw_pump.setName('Hot Water Loop Pump')
|
|
47
51
|
hw_pump_head_ft_h2o = 60.0
|
|
48
52
|
hw_pump_head_press_pa = OpenStudio.convert(hw_pump_head_ft_h2o, 'ftH_{2}O','Pa').get
|
|
49
53
|
hw_pump.setRatedPumpHead(hw_pump_head_press_pa)
|
|
50
54
|
hw_pump.setMotorEfficiency(0.9)
|
|
51
|
-
hw_pump.setFractionofMotorInefficienciestoFluidStream(0)
|
|
52
|
-
hw_pump.setCoefficient1ofthePartLoadPerformanceCurve(0)
|
|
53
|
-
hw_pump.setCoefficient2ofthePartLoadPerformanceCurve(1)
|
|
54
|
-
hw_pump.setCoefficient3ofthePartLoadPerformanceCurve(0)
|
|
55
|
-
hw_pump.setCoefficient4ofthePartLoadPerformanceCurve(0)
|
|
56
55
|
hw_pump.setPumpControlType('Intermittent')
|
|
57
56
|
hw_pump.addToNode(hot_water_loop.supplyInletNode)
|
|
58
57
|
|
|
@@ -911,11 +910,7 @@ class OpenStudio::Model::Model
|
|
|
911
910
|
zn_dsn_htg_sa_temp_f = 122 # Design VAV box to reheat to 122F
|
|
912
911
|
rht_rated_air_in_temp_f = 62 # Reheat coils designed to receive 62F
|
|
913
912
|
rht_rated_air_out_temp_f = 90 # Reheat coils designed to supply 90F...but zone expects 122F...?
|
|
914
|
-
|
|
915
|
-
clg_sa_temp_f = 52 # for AHU1 in Outpatient, SAT is 52F
|
|
916
|
-
else
|
|
917
|
-
clg_sa_temp_f = 55 # Central deck clg temp operates at 55F
|
|
918
|
-
end
|
|
913
|
+
clg_sa_temp_f = 55 # Central deck clg temp operates at 55F
|
|
919
914
|
|
|
920
915
|
sys_dsn_prhtg_temp_c = OpenStudio.convert(sys_dsn_prhtg_temp_f,'F','C').get
|
|
921
916
|
sys_dsn_clg_sa_temp_c = OpenStudio.convert(sys_dsn_clg_sa_temp_f,'F','C').get
|
|
@@ -941,12 +936,33 @@ class OpenStudio::Model::Model
|
|
|
941
936
|
end
|
|
942
937
|
air_loop.setAvailabilitySchedule(hvac_op_sch)
|
|
943
938
|
|
|
939
|
+
# Some exceptions for the Outpatient
|
|
940
|
+
if sys_name.include? "PVAV Outpatient F1"
|
|
941
|
+
# Outpatient two AHU1 and AHU2 have different HVAC schedule
|
|
942
|
+
hvac_op_sch = self.add_schedule('OutPatientHealthCare AHU1-Fan_Pre2004')
|
|
943
|
+
# Outpatient has different temperature settings for sizing
|
|
944
|
+
clg_sa_temp_f = 52 # for AHU1 in Outpatient, SAT is 52F
|
|
945
|
+
if standard == 'DOE Ref 1980-2004' || standard == 'DOE Ref Pre-1980'
|
|
946
|
+
sys_dsn_clg_sa_temp_f = 52
|
|
947
|
+
else
|
|
948
|
+
sys_dsn_clg_sa_temp_f = 45
|
|
949
|
+
end
|
|
950
|
+
zn_dsn_clg_sa_temp_f = 52 # zone cooling design SAT
|
|
951
|
+
zn_dsn_htg_sa_temp_f = 104 # zone heating design SAT
|
|
952
|
+
elsif sys_name.include? 'PVAV Outpatient F2 F3'
|
|
953
|
+
hvac_op_sch = self.add_schedule('OutPatientHealthCare AHU2-Fan_Pre2004')
|
|
954
|
+
clg_sa_temp_f = 55 # for AHU2 in Outpatient, SAT is 55F
|
|
955
|
+
sys_dsn_clg_sa_temp_f = 52
|
|
956
|
+
zn_dsn_clg_sa_temp_f = 55 # zone cooling design SAT
|
|
957
|
+
zn_dsn_htg_sa_temp_f = 104 # zone heating design SAT
|
|
958
|
+
end
|
|
959
|
+
|
|
944
960
|
# Air handler controls
|
|
945
961
|
stpt_manager = OpenStudio::Model::SetpointManagerScheduled.new(self,sa_temp_sch)
|
|
946
962
|
stpt_manager.addToNode(air_loop.supplyOutletNode)
|
|
947
963
|
sizing_system = air_loop.sizingSystem
|
|
948
964
|
# sizing_system.setPreheatDesignTemperature(sys_dsn_prhtg_temp_c)
|
|
949
|
-
|
|
965
|
+
sizing_system.setCentralCoolingDesignSupplyAirTemperature(sys_dsn_clg_sa_temp_c)
|
|
950
966
|
sizing_system.setCentralHeatingDesignSupplyAirTemperature(sys_dsn_htg_sa_temp_c)
|
|
951
967
|
sizing_system.setSizingOption('Coincident')
|
|
952
968
|
sizing_system.setAllOutdoorAirinCooling(false)
|
|
@@ -982,10 +998,10 @@ class OpenStudio::Model::Model
|
|
|
982
998
|
|
|
983
999
|
# Outdoor air intake system
|
|
984
1000
|
oa_intake_controller = OpenStudio::Model::ControllerOutdoorAir.new(self)
|
|
985
|
-
oa_intake = OpenStudio::Model::AirLoopHVACOutdoorAirSystem.new(self, oa_intake_controller)
|
|
986
|
-
oa_intake.setName("#{air_loop.name} OA Sys")
|
|
987
1001
|
oa_intake_controller.setMinimumLimitType('FixedMinimum')
|
|
988
1002
|
oa_intake_controller.setMinimumOutdoorAirSchedule(oa_damper_sch)
|
|
1003
|
+
oa_intake = OpenStudio::Model::AirLoopHVACOutdoorAirSystem.new(self, oa_intake_controller)
|
|
1004
|
+
oa_intake.setName("#{air_loop.name} OA Sys")
|
|
989
1005
|
oa_intake.addToNode(air_loop.supplyInletNode)
|
|
990
1006
|
controller_mv = oa_intake_controller.controllerMechanicalVentilation
|
|
991
1007
|
controller_mv.setName("#{air_loop.name} Ventilation Controller")
|
|
@@ -3277,7 +3293,7 @@ class OpenStudio::Model::Model
|
|
|
3277
3293
|
swh_pump_motor_efficiency = 1
|
|
3278
3294
|
end
|
|
3279
3295
|
|
|
3280
|
-
if
|
|
3296
|
+
if standard == 'DOE Ref 1980-2004' || 'template' == 'DOE Ref Pre-1980'
|
|
3281
3297
|
if building_type == 'Medium Office'
|
|
3282
3298
|
swh_pump = OpenStudio::Model::PumpConstantSpeed.new(self)
|
|
3283
3299
|
else
|
|
@@ -4142,7 +4158,17 @@ class OpenStudio::Model::Model
|
|
|
4142
4158
|
fan = OpenStudio::Model::FanZoneExhaust.new(self)
|
|
4143
4159
|
fan.setName("#{zone.name} Exhaust Fan")
|
|
4144
4160
|
fan.setAvailabilitySchedule(self.add_schedule(availability_sch_name))
|
|
4145
|
-
|
|
4161
|
+
# two ways to input the flow rate: Number of Array.
|
|
4162
|
+
# For number: assign directly. For Array: assign each flow rate to each according zone.
|
|
4163
|
+
if flow_rate.is_a? Numeric
|
|
4164
|
+
fan.setMaximumFlowRate(flow_rate)
|
|
4165
|
+
elsif flow_rate.class.to_s == 'Array'
|
|
4166
|
+
index = thermal_zones.index(zone)
|
|
4167
|
+
flow_rate_zone = flow_rate[index]
|
|
4168
|
+
fan.setMaximumFlowRate(flow_rate_zone)
|
|
4169
|
+
else
|
|
4170
|
+
OpenStudio::logFree(OpenStudio::Warn, "openstudio.model.Model", "Wrong format of flow rate")
|
|
4171
|
+
end
|
|
4146
4172
|
unless flow_fraction_schedule_name.nil?
|
|
4147
4173
|
fan.setFlowFractionSchedule(self.add_schedule(flow_fraction_schedule_name))
|
|
4148
4174
|
end
|
|
@@ -102,7 +102,68 @@ class OpenStudio::Model::Model
|
|
|
102
102
|
'Floor 3 Storage 1', 'Floor 3 Storage 2', 'Floor 3 Treatment', 'Floor 3 Undeveloped 1', 'Floor 3 Undeveloped 2',
|
|
103
103
|
'Floor 3 Utility', 'Floor 3 Work', 'NE Stair', 'NW Elevator', 'NW Stair', 'SW Stair'
|
|
104
104
|
]
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
'type' => 'Exhaust Fan',
|
|
108
|
+
'name' => 'Outpatient AHU1 Exhaust Fans',
|
|
109
|
+
'availability_sch_name' => 'OutPatientHealthCare Hours_of_operation',
|
|
110
|
+
'flow_rate' =>
|
|
111
|
+
[
|
|
112
|
+
6.79561743E-02, # Floor 1 Anesthesia
|
|
113
|
+
4.24726077E-02, # Floor 1 Lobby Toilet
|
|
114
|
+
0.1586, # Floor 1 MRI Control Room
|
|
115
|
+
0.4153, # Floor 1 MRI Room
|
|
116
|
+
4.24726077E-02, # Floor 1 MRI Toilet
|
|
117
|
+
4.24726077E-02, # Floor 1 Nurse Toilet
|
|
118
|
+
4.24726077E-02, # Floor 1 Pre-Op Toilet
|
|
119
|
+
9.91027512E-02, # Floor 1 Soil
|
|
120
|
+
4.40456672E-02, # Floor 1 Soil Hold
|
|
121
|
+
1.41575359E-01, # Floor 1 Soil Work
|
|
122
|
+
],
|
|
123
|
+
'flow_fraction_schedule_name' => nil,
|
|
124
|
+
'balanced_exhaust_fraction_schedule_name' => nil,
|
|
125
|
+
'space_names' =>
|
|
126
|
+
[
|
|
127
|
+
'Floor 1 Anesthesia',
|
|
128
|
+
'Floor 1 Lobby Toilet',
|
|
129
|
+
'Floor 1 MRI Control Room',
|
|
130
|
+
'Floor 1 MRI Room',
|
|
131
|
+
'Floor 1 MRI Toilet',
|
|
132
|
+
'Floor 1 Nurse Toilet',
|
|
133
|
+
'Floor 1 Pre-Op Toilet',
|
|
134
|
+
'Floor 1 Soil',
|
|
135
|
+
'Floor 1 Soil Hold',
|
|
136
|
+
'Floor 1 Soil Work'
|
|
137
|
+
]
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
'type' => 'Exhaust Fan',
|
|
141
|
+
'name' => 'Outpatient AHU2&3 Exhaust Fans',
|
|
142
|
+
'availability_sch_name' => 'OutPatientHealthCare BLDG_OA_SCH',
|
|
143
|
+
'flow_rate' =>
|
|
144
|
+
[
|
|
145
|
+
5.03379054E-02, # Floor 2 Conference Toilet
|
|
146
|
+
9.91027512E-02, # Floor 2 Reception Toilet
|
|
147
|
+
4.24726077E-02, # Floor 2 Work Toilet
|
|
148
|
+
0.8495, # Floor 2 X-Ray
|
|
149
|
+
1.51013716E-01, # Floor 3 Lounge Toilet
|
|
150
|
+
4.24726077E-02, # Floor 3 Office Toilet
|
|
151
|
+
6.60685008E-02, # Floor 3 Physical Therapy Toilet
|
|
152
|
+
],
|
|
153
|
+
'flow_fraction_schedule_name' => nil,
|
|
154
|
+
'balanced_exhaust_fraction_schedule_name' => nil,
|
|
155
|
+
'space_names' =>
|
|
156
|
+
[
|
|
157
|
+
'Floor 2 Conference Toilet',
|
|
158
|
+
'Floor 2 Reception Toilet',
|
|
159
|
+
'Floor 2 Work Toilet',
|
|
160
|
+
'Floor 2 X-Ray',
|
|
161
|
+
'Floor 3 Lounge Toilet',
|
|
162
|
+
'Floor 3 Office Toilet',
|
|
163
|
+
'Floor 3 Physical Therapy Toilet',
|
|
164
|
+
]
|
|
105
165
|
}
|
|
166
|
+
|
|
106
167
|
]
|
|
107
168
|
|
|
108
169
|
when 'DOE Ref Pre-1980', 'DOE Ref 1980-2004'
|
|
@@ -140,10 +201,32 @@ class OpenStudio::Model::Model
|
|
|
140
201
|
'Floor 3 Physical Therapy 1', 'Floor 3 Physical Therapy 2',
|
|
141
202
|
'Floor 3 Treatment', 'Floor 3 Work'
|
|
142
203
|
]
|
|
204
|
+
},
|
|
205
|
+
{
|
|
206
|
+
'type' => 'Exhaust Fan',
|
|
207
|
+
'name' => 'Outpatient AHU1 Exhaust Fans',
|
|
208
|
+
'availability_sch_name' => 'OutPatientHealthCare AHU1-Fan_Pre2004',
|
|
209
|
+
'flow_rate' =>
|
|
210
|
+
[
|
|
211
|
+
0.068, # Floor 1 Anesthesia
|
|
212
|
+
0.0793, # Floor 1 MRI Control Room
|
|
213
|
+
0.2077, # Floor 1 MRI Room
|
|
214
|
+
0.0991, # Floor 1 Soil
|
|
215
|
+
0.044, # Floor 1 Soil Hold
|
|
216
|
+
0.1416, # Floor 1 Soil Work
|
|
217
|
+
],
|
|
218
|
+
'flow_fraction_schedule_name' => nil,
|
|
219
|
+
'balanced_exhaust_fraction_schedule_name' => nil,
|
|
220
|
+
'space_names' =>
|
|
221
|
+
[
|
|
222
|
+
'Floor 1 Anesthesia',
|
|
223
|
+
'Floor 1 MRI Control Room',
|
|
224
|
+
'Floor 1 MRI Room',
|
|
225
|
+
'Floor 1 Soil',
|
|
226
|
+
'Floor 1 Soil Hold',
|
|
227
|
+
'Floor 1 Soil Work'
|
|
228
|
+
]
|
|
143
229
|
}
|
|
144
|
-
# {
|
|
145
|
-
# TODO exhaust fans
|
|
146
|
-
# }
|
|
147
230
|
]
|
|
148
231
|
end
|
|
149
232
|
|
|
@@ -165,7 +248,8 @@ class OpenStudio::Model::Model
|
|
|
165
248
|
hot_water_loop = nil
|
|
166
249
|
self.getPlantLoops.each do |loop|
|
|
167
250
|
# If it has a boiler:hotwater, it is the correct loop
|
|
168
|
-
if loop.supplyComponents(
|
|
251
|
+
if loop.supplyComponents(OpenStudio::Model::BoilerHotWater::iddObjectType).size > 0
|
|
252
|
+
# if loop.supplyComponents('OS_Boiler_HotWater'.to_IddObjectType).size > 0 # Another feasible expression way
|
|
169
253
|
hot_water_loop = loop
|
|
170
254
|
end
|
|
171
255
|
end
|
|
@@ -181,6 +265,8 @@ class OpenStudio::Model::Model
|
|
|
181
265
|
self.add_door_infiltration(building_vintage,climate_zone)
|
|
182
266
|
# reset boiler sizing factor to 0.3 (default 1)
|
|
183
267
|
self.reset_boiler_sizing_factor
|
|
268
|
+
# assign the minimum total air changes to the cooling minimum air flow in Sizing:Zone
|
|
269
|
+
self.apply_minimum_total_ach(building_type,building_vintage)
|
|
184
270
|
|
|
185
271
|
OpenStudio::logFree(OpenStudio::Info, 'openstudio.model.Model', 'Finished adding HVAC')
|
|
186
272
|
|
|
@@ -307,14 +393,6 @@ class OpenStudio::Model::Model
|
|
|
307
393
|
end
|
|
308
394
|
end
|
|
309
395
|
|
|
310
|
-
def custom_swh_tweaks(building_type, building_vintage, climate_zone, prototype_input)
|
|
311
|
-
|
|
312
|
-
self.update_waterheater_loss_coefficient(building_vintage)
|
|
313
|
-
|
|
314
|
-
return true
|
|
315
|
-
|
|
316
|
-
end
|
|
317
|
-
|
|
318
396
|
# add humidifier to AHU1 (contains operating room1)
|
|
319
397
|
def add_humidifier(building_vintage, hot_water_loop)
|
|
320
398
|
operatingroom1_space = self.getSpaceByName('Floor 1 Operating Room 1').get
|
|
@@ -361,17 +439,20 @@ class OpenStudio::Model::Model
|
|
|
361
439
|
# AHU1 doesn't have economizer
|
|
362
440
|
def modify_OAcontroller(building_vintage)
|
|
363
441
|
self.getAirLoopHVACs.each do |air_loop|
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
442
|
+
oa_system = air_loop.airLoopHVACOutdoorAirSystem.get
|
|
443
|
+
controller_oa = oa_system.getControllerOutdoorAir
|
|
444
|
+
controller_mv = controller_oa.controllerMechanicalVentilation
|
|
445
|
+
# AHU1 OA doesn't have controller:mechanicalventilation
|
|
446
|
+
if air_loop.name.to_s.include? "Outpatient F1"
|
|
447
|
+
controller_mv.setAvailabilitySchedule(self.alwaysOffDiscreteSchedule)
|
|
448
|
+
# add minimum fraction of outdoor air schedule to AHU1
|
|
449
|
+
controller_oa.setMinimumFractionofOutdoorAirSchedule(self.add_schedule('OutPatientHealthCare AHU-1_OAminOAFracSchedule'))
|
|
450
|
+
# for AHU2, at vintages '90.1-2004', '90.1-2007', '90.1-2010', '90.1-2013', the minimum OA schedule is not the same as
|
|
451
|
+
# airloop availability schedule, but separately assigned.
|
|
452
|
+
elsif building_vintage=='90.1-2004' || building_vintage=='90.1-2007' || building_vintage=='90.1-2010' || building_vintage=='90.1-2013'
|
|
453
|
+
controller_oa.setMinimumOutdoorAirSchedule(self.add_schedule('OutPatientHealthCare BLDG_OA_SCH'))
|
|
454
|
+
# add minimum fraction of outdoor air schedule to AHU2
|
|
455
|
+
controller_oa.setMinimumFractionofOutdoorAirSchedule(self.add_schedule('OutPatientHealthCare BLDG_OA_FRAC_SCH'))
|
|
375
456
|
end
|
|
376
457
|
end
|
|
377
458
|
end
|
|
@@ -397,5 +478,67 @@ class OpenStudio::Model::Model
|
|
|
397
478
|
boiler.setSizingFactor(0.3)
|
|
398
479
|
end
|
|
399
480
|
end
|
|
481
|
+
|
|
482
|
+
def update_exhaust_fan_efficiency(building_vintage)
|
|
483
|
+
case building_vintage
|
|
484
|
+
when '90.1-2004', '90.1-2007', '90.1-2010', '90.1-2013'
|
|
485
|
+
self.getFanZoneExhausts.sort.each do |exhaust_fan|
|
|
486
|
+
fan_name = exhaust_fan.name.to_s
|
|
487
|
+
if (fan_name.include? "X-Ray") || (fan_name.include? "MRI Room")
|
|
488
|
+
exhaust_fan.setFanEfficiency(0.16)
|
|
489
|
+
exhaust_fan.setPressureRise(125)
|
|
490
|
+
else
|
|
491
|
+
exhaust_fan.setFanEfficiency(0.31)
|
|
492
|
+
exhaust_fan.setPressureRise(249)
|
|
493
|
+
end
|
|
494
|
+
end
|
|
495
|
+
when 'DOE Ref Pre-1980', 'DOE Ref 1980-2004'
|
|
496
|
+
self.getFanZoneExhausts.sort.each do |exhaust_fan|
|
|
497
|
+
exhaust_fan.setFanEfficiency(0.338)
|
|
498
|
+
exhaust_fan.setPressureRise(125)
|
|
499
|
+
end
|
|
500
|
+
end
|
|
501
|
+
end
|
|
502
|
+
|
|
503
|
+
# assign the minimum total air changes to the cooling minimum air flow in Sizing:Zone
|
|
504
|
+
def apply_minimum_total_ach(building_type,building_vintage)
|
|
505
|
+
self.getSpaces.each do |space|
|
|
506
|
+
space_type_name = space.spaceType.get.standardsSpaceType.get
|
|
507
|
+
search_criteria = {
|
|
508
|
+
'template' => building_vintage,
|
|
509
|
+
'building_type' => building_type,
|
|
510
|
+
'space_type' => space_type_name
|
|
511
|
+
}
|
|
512
|
+
data = find_object($os_standards['space_types'],search_criteria)
|
|
513
|
+
|
|
514
|
+
# skip space type without minimum total air changes
|
|
515
|
+
next if data['minimum_total_air_changes'].nil?
|
|
516
|
+
|
|
517
|
+
# calculate the minimum total air flow
|
|
518
|
+
minimum_total_ach = data['minimum_total_air_changes'].to_f
|
|
519
|
+
space_volume = space.volume
|
|
520
|
+
space_area = space.floorArea
|
|
521
|
+
minimum_airflow_per_zone = minimum_total_ach * space_volume / 3600
|
|
522
|
+
minimum_airflow_per_zone_floor_area = minimum_airflow_per_zone / space_area
|
|
523
|
+
# add minimum total air flow limit to sizing:zone
|
|
524
|
+
zone = space.thermalZone.get
|
|
525
|
+
sizingzone = zone.sizingZone
|
|
526
|
+
sizingzone.setCoolingDesignAirFlowMethod('DesignDayWithLimit')
|
|
527
|
+
case building_vintage
|
|
528
|
+
when 'DOE Ref Pre-1980', 'DOE Ref 1980-2004'
|
|
529
|
+
sizingzone.setCoolingMinimumAirFlow(minimum_airflow_per_zone)
|
|
530
|
+
when '90.1-2004', '90.1-2007', '90.1-2010', '90.1-2013'
|
|
531
|
+
sizingzone.setCoolingMinimumAirFlowperZoneFloorArea(minimum_airflow_per_zone_floor_area)
|
|
532
|
+
end
|
|
533
|
+
end
|
|
534
|
+
end
|
|
535
|
+
|
|
536
|
+
def custom_swh_tweaks(building_type, building_vintage, climate_zone, prototype_input)
|
|
537
|
+
|
|
538
|
+
self.update_waterheater_loss_coefficient(building_vintage)
|
|
539
|
+
|
|
540
|
+
return true
|
|
541
|
+
|
|
542
|
+
end
|
|
400
543
|
|
|
401
544
|
end
|
|
@@ -17,11 +17,21 @@ class OpenStudio::Model::AirLoopHVAC
|
|
|
17
17
|
return true
|
|
18
18
|
end
|
|
19
19
|
|
|
20
|
+
# First time adjustment:
|
|
20
21
|
# Only applies to multi-zone vav systems
|
|
21
|
-
|
|
22
|
+
# exclusion: for Outpatient: (1) both AHU1 and AHU2 in 'DOE Ref Pre-1980' and 'DOE Ref 1980-2004'
|
|
23
|
+
# (2) AHU1 in 2004-2013
|
|
24
|
+
if self.is_multizone_vav_system && !(self.name.to_s.include? "Outpatient F1")
|
|
22
25
|
self.adjust_minimum_vav_damper_positions
|
|
23
26
|
end
|
|
24
27
|
|
|
28
|
+
# Second time adjustment:
|
|
29
|
+
# Only apply to 2010 and 2013 Outpatient (both AHU1 and AHU2)
|
|
30
|
+
# TODO maybe apply to hospital as well?
|
|
31
|
+
if (self.name.to_s.include? "Outpatient") && (template == '90.1-2010' || template == '90.1-2013')
|
|
32
|
+
self.adjust_minimum_vav_damper_positions_outpatient
|
|
33
|
+
end
|
|
34
|
+
|
|
25
35
|
return true
|
|
26
36
|
|
|
27
37
|
end
|
|
@@ -52,10 +62,13 @@ class OpenStudio::Model::AirLoopHVAC
|
|
|
52
62
|
self.set_vav_damper_action(template)
|
|
53
63
|
|
|
54
64
|
# Multizone VAV Optimization
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
65
|
+
# This rule does not apply to two hospital and one outpatient systems (TODO add hospital two systems as exception)
|
|
66
|
+
if !(self.name.to_s.include? "Outpatient F1")
|
|
67
|
+
if self.is_multizone_vav_optimization_required(template, climate_zone)
|
|
68
|
+
self.enable_multizone_vav_optimization
|
|
69
|
+
else
|
|
70
|
+
self.disable_multizone_vav_optimization
|
|
71
|
+
end
|
|
59
72
|
end
|
|
60
73
|
|
|
61
74
|
# VAV Static Pressure Reset
|
|
@@ -665,6 +678,8 @@ class OpenStudio::Model::AirLoopHVAC
|
|
|
665
678
|
|
|
666
679
|
economizer_required = false
|
|
667
680
|
|
|
681
|
+
return economizer_required if self.name.to_s.include? "Outpatient F1"
|
|
682
|
+
|
|
668
683
|
# A big number of btu per hr as the minimum requirement
|
|
669
684
|
infinity_btu_per_hr = 999999999999
|
|
670
685
|
minimum_capacity_btu_per_hr = infinity_btu_per_hr
|
|
@@ -1335,6 +1350,13 @@ class OpenStudio::Model::AirLoopHVAC
|
|
|
1335
1350
|
# return false
|
|
1336
1351
|
# end
|
|
1337
1352
|
|
|
1353
|
+
erv_required = nil
|
|
1354
|
+
# ERV not applicable for medical AHUs (AHU1 in Outpatient), per AIA 2001 - 7.31.D2.
|
|
1355
|
+
if self.name.to_s.include? "Outpatient F1"
|
|
1356
|
+
erv_required = false
|
|
1357
|
+
return erv_required
|
|
1358
|
+
end
|
|
1359
|
+
|
|
1338
1360
|
# ERV Not Applicable for AHUs that have DCV
|
|
1339
1361
|
# or that have no OA intake.
|
|
1340
1362
|
controller_oa = nil
|
|
@@ -1527,7 +1549,7 @@ class OpenStudio::Model::AirLoopHVAC
|
|
|
1527
1549
|
end
|
|
1528
1550
|
|
|
1529
1551
|
# Determine if an ERV is required
|
|
1530
|
-
erv_required = nil
|
|
1552
|
+
# erv_required = nil
|
|
1531
1553
|
if erv_cfm.nil?
|
|
1532
1554
|
OpenStudio::logFree(OpenStudio::Info, "openstudio.standards.AirLoopHVAC", "For #{self.name}, ERV not required based on #{(pct_oa*100).round}% OA flow, design flow of #{dsn_flow_cfm.round}cfm, and climate zone #{climate_zone}.")
|
|
1533
1555
|
erv_required = false
|
|
@@ -2041,6 +2063,41 @@ class OpenStudio::Model::AirLoopHVAC
|
|
|
2041
2063
|
return true
|
|
2042
2064
|
|
|
2043
2065
|
end
|
|
2066
|
+
|
|
2067
|
+
# For critical zones of Outpatient, if the minimum airflow rate required by the accreditation standard (AIA 2001) is significantly
|
|
2068
|
+
# less than the autosized peak design airflow in any of the three climate zones (Houston, Baltimore and Burlington), the minimum
|
|
2069
|
+
# airflow fraction of the terminal units is reduced to the value: "required minimum airflow rate / autosized peak design flow"
|
|
2070
|
+
# Reference: <Achieving the 30% Goal: Energy and Cost Savings Analysis of ASHRAE Standard 90.1-2010> Page109-111
|
|
2071
|
+
# For implementation purpose, since it is time-consuming to perform autosizing in three climate zones, just use
|
|
2072
|
+
# the results of the current climate zone
|
|
2073
|
+
def adjust_minimum_vav_damper_positions_outpatient
|
|
2074
|
+
self.model.getSpaces.each do |space|
|
|
2075
|
+
zone = space.thermalZone.get
|
|
2076
|
+
sizingZone = zone.sizingZone
|
|
2077
|
+
space_area = space.floorArea
|
|
2078
|
+
if sizingZone.coolingDesignAirFlowMethod == 'DesignDay'
|
|
2079
|
+
next
|
|
2080
|
+
elsif sizingZone.coolingDesignAirFlowMethod == 'DesignDayWithLimit'
|
|
2081
|
+
minimum_airflow_per_zone_floor_area = sizingZone.coolingMinimumAirFlowperZoneFloorArea
|
|
2082
|
+
minimum_airflow_per_zone = minimum_airflow_per_zone_floor_area * space_area
|
|
2083
|
+
# get the autosized maximum air flow of the VAV terminal
|
|
2084
|
+
zone.equipment.each do |equip|
|
|
2085
|
+
if equip.to_AirTerminalSingleDuctVAVReheat.is_initialized
|
|
2086
|
+
vav_terminal = equip.to_AirTerminalSingleDuctVAVReheat.get
|
|
2087
|
+
rated_maximum_flow_rate = vav_terminal.autosizedMaximumAirFlowRate.get
|
|
2088
|
+
# compare the VAV autosized maximum airflow with the minimum airflow rate required by the accreditation standard
|
|
2089
|
+
ratio = minimum_airflow_per_zone / rated_maximum_flow_rate
|
|
2090
|
+
if ratio >= 0.95
|
|
2091
|
+
vav_terminal.setConstantMinimumAirFlowFraction(1)
|
|
2092
|
+
elsif ratio < 0.95
|
|
2093
|
+
vav_terminal.setConstantMinimumAirFlowFraction(ratio)
|
|
2094
|
+
end
|
|
2095
|
+
end
|
|
2096
|
+
end
|
|
2097
|
+
end
|
|
2098
|
+
end
|
|
2099
|
+
return true
|
|
2100
|
+
end
|
|
2044
2101
|
|
|
2045
2102
|
# Determine if demand control ventilation (DCV) is
|
|
2046
2103
|
# required for this air loop.
|
|
@@ -2097,7 +2154,7 @@ class OpenStudio::Model::AirLoopHVAC
|
|
|
2097
2154
|
num_people += space.numberOfPeople
|
|
2098
2155
|
end
|
|
2099
2156
|
end
|
|
2100
|
-
|
|
2157
|
+
|
|
2101
2158
|
# Check the minimum area
|
|
2102
2159
|
area_served_ft2 = OpenStudio.convert(area_served_m2, 'm^2', 'ft^2').get
|
|
2103
2160
|
if area_served_ft2 < min_area_ft2
|
|
@@ -2107,7 +2164,8 @@ class OpenStudio::Model::AirLoopHVAC
|
|
|
2107
2164
|
|
|
2108
2165
|
# Check the minimum occupancy density
|
|
2109
2166
|
occ_per_ft2 = num_people / area_served_ft2
|
|
2110
|
-
occ_per_1000_ft2 = occ_per_ft2*1000
|
|
2167
|
+
occ_per_1000_ft2 = occ_per_ft2*1000
|
|
2168
|
+
|
|
2111
2169
|
if occ_per_1000_ft2 < min_occ_per_1000_ft2
|
|
2112
2170
|
OpenStudio::logFree(OpenStudio::Info, 'openstudio.standards.AirLoopHVAC', "For #{self.name}: DCV is not required since the system occupant density is #{occ_per_1000_ft2.round} people/1000 ft2, but the minimum occupant density is #{min_occ_per_1000_ft2.round} people/1000 ft2.")
|
|
2113
2171
|
return dcv_required
|
|
@@ -2160,7 +2218,7 @@ class OpenStudio::Model::AirLoopHVAC
|
|
|
2160
2218
|
#
|
|
2161
2219
|
# @return [Bool] Returns true if required, false if not.
|
|
2162
2220
|
def enable_demand_control_ventilation()
|
|
2163
|
-
|
|
2221
|
+
|
|
2164
2222
|
# Get the OA intake
|
|
2165
2223
|
controller_oa = nil
|
|
2166
2224
|
controller_mv = nil
|
|
@@ -2447,7 +2505,13 @@ class OpenStudio::Model::AirLoopHVAC
|
|
|
2447
2505
|
def is_motorized_oa_damper_required(template, climate_zone)
|
|
2448
2506
|
|
|
2449
2507
|
motorized_oa_damper_required = false
|
|
2450
|
-
|
|
2508
|
+
|
|
2509
|
+
if self.name.to_s.include? "Outpatient F1"
|
|
2510
|
+
motorized_oa_damper_required = true
|
|
2511
|
+
OpenStudio::logFree(OpenStudio::Info, 'openstudio.standards.AirLoopHVAC', "For #{self.name}: always has a damper, the minimum OA schedule is the same as airloop availability schedule.")
|
|
2512
|
+
return motorized_oa_damper_required
|
|
2513
|
+
end
|
|
2514
|
+
|
|
2451
2515
|
# If the system has an economizer, it must have
|
|
2452
2516
|
# a motorized damper.
|
|
2453
2517
|
if self.has_economizer
|
|
@@ -75,9 +75,9 @@ class OpenStudio::Model::CoilCoolingDXSingleSpeed
|
|
|
75
75
|
|
|
76
76
|
end
|
|
77
77
|
|
|
78
|
-
# Finds capacity in
|
|
78
|
+
# Finds capacity in Btu/hr
|
|
79
79
|
#
|
|
80
|
-
# @return [Double] capacity in
|
|
80
|
+
# @return [Double] capacity in Btu/hr to be used for find object
|
|
81
81
|
def find_capacity()
|
|
82
82
|
|
|
83
83
|
# Get the coil capacity
|
|
@@ -88,8 +88,7 @@ class OpenStudio::Model::CoilCoolingDXSingleSpeed
|
|
|
88
88
|
capacity_w = self.autosizedRatedTotalCoolingCapacity.get
|
|
89
89
|
else
|
|
90
90
|
OpenStudio::logFree(OpenStudio::Warn, 'openstudio.standards.CoilCoolingDXSingleSpeed', "For #{self.name} capacity is not available, cannot apply efficiency standard.")
|
|
91
|
-
|
|
92
|
-
return successfully_set_all_properties
|
|
91
|
+
return false
|
|
93
92
|
end
|
|
94
93
|
|
|
95
94
|
# Convert capacity to Btu/hr
|
|
@@ -22,55 +22,20 @@ class OpenStudio::Model::CoilHeatingDXSingleSpeed
|
|
|
22
22
|
|
|
23
23
|
end
|
|
24
24
|
|
|
25
|
-
# Finds capacity in
|
|
25
|
+
# Finds capacity in Btu/hr
|
|
26
26
|
#
|
|
27
|
-
# @return [Double] capacity in
|
|
27
|
+
# @return [Double] capacity in Btu/hr to be used for find object
|
|
28
28
|
def find_capacity()
|
|
29
29
|
|
|
30
|
-
# Determine supplemental heating type if unitary
|
|
31
|
-
heat_pump = false
|
|
32
|
-
if self.airLoopHVAC.empty?
|
|
33
|
-
if self.containingHVACComponent.is_initialized
|
|
34
|
-
containing_comp = containingHVACComponent.get
|
|
35
|
-
if containing_comp.to_AirLoopHVACUnitaryHeatPumpAirToAir.is_initialized
|
|
36
|
-
heat_pump = true
|
|
37
|
-
end
|
|
38
|
-
end
|
|
39
|
-
end
|
|
40
|
-
|
|
41
30
|
# Get the coil capacity
|
|
42
31
|
capacity_w = nil
|
|
43
|
-
if
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
dxcoil = ccoil.to_CoilCoolingDXSingleSpeed.get
|
|
48
|
-
dxcoil_name = dxcoil.name.to_s
|
|
49
|
-
if sql_db_vars_map
|
|
50
|
-
if sql_db_vars_map[dxcoil_name]
|
|
51
|
-
dxcoil.setName(sql_db_vars_map[dxcoil_name])
|
|
52
|
-
end
|
|
53
|
-
end
|
|
54
|
-
if dxcoil.ratedTotalCoolingCapacity.is_initialized
|
|
55
|
-
capacity_w = dxcoil.ratedTotalCoolingCapacity.get
|
|
56
|
-
elsif dxcoil.autosizedRatedTotalCoolingCapacity.is_initialized
|
|
57
|
-
capacity_w = dxcoil.autosizedRatedTotalCoolingCapacity.get
|
|
58
|
-
else
|
|
59
|
-
OpenStudio::logFree(OpenStudio::Warn, 'openstudio.standards.CoilHeatingDXSingleSpeed', "For #{self.name} capacity is not available, cannot apply efficiency standard.")
|
|
60
|
-
successfully_set_all_properties = false
|
|
61
|
-
return successfully_set_all_properties
|
|
62
|
-
end
|
|
63
|
-
dxcoil.setName(dxcoil_name)
|
|
32
|
+
if self.ratedTotalHeatingCapacity.is_initialized
|
|
33
|
+
capacity_w = self.ratedTotalHeatingCapacity.get
|
|
34
|
+
elsif self.autosizedRatedTotalHeatingCapacity.is_initialized
|
|
35
|
+
capacity_w = self.autosizedRatedTotalHeatingCapacity.get
|
|
64
36
|
else
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
elsif self.autosizedRatedTotalHeatingCapacity.is_initialized
|
|
68
|
-
capacity_w = self.autosizedRatedTotalHeatingCapacity.get
|
|
69
|
-
else
|
|
70
|
-
OpenStudio::logFree(OpenStudio::Warn, 'openstudio.standards.CoilHeatingDXSingleSpeed', "For #{self.name} capacity is not available, cannot apply efficiency standard.")
|
|
71
|
-
successfully_set_all_properties = false
|
|
72
|
-
return successfully_set_all_properties
|
|
73
|
-
end
|
|
37
|
+
OpenStudio::logFree(OpenStudio::Warn, 'openstudio.standards.CoilHeatingDXSingleSpeed', "For #{self.name} capacity is not available, cannot apply efficiency standard.")
|
|
38
|
+
return false
|
|
74
39
|
end
|
|
75
40
|
|
|
76
41
|
# Convert capacity to Btu/hr
|
|
@@ -49,7 +49,7 @@ module Fan
|
|
|
49
49
|
end
|
|
50
50
|
|
|
51
51
|
# Find the motor efficiency
|
|
52
|
-
motor_eff, nominal_hp =
|
|
52
|
+
motor_eff, nominal_hp = standard_minimum_motor_efficiency_and_size(template, allowed_hp)
|
|
53
53
|
|
|
54
54
|
# Calculate the total fan efficiency
|
|
55
55
|
total_fan_eff = fan_impeller_eff * motor_eff
|
|
@@ -74,8 +74,53 @@ class OpenStudio::Model::Model
|
|
|
74
74
|
|
|
75
75
|
OpenStudio::logFree(OpenStudio::Info, 'openstudio.model.Model', 'Finished run.')
|
|
76
76
|
|
|
77
|
-
|
|
78
|
-
OpenStudio::logFree(OpenStudio::Info, 'openstudio.model.Model', 'Running with openstudio-workflow gem.')
|
|
77
|
+
elsif OpenStudio::Workflow::VERSION >= '1.0.0' # Use the OS 2.0 openstudio-workflow gem
|
|
78
|
+
OpenStudio::logFree(OpenStudio::Info, 'openstudio.model.Model', 'Running with OS 2.0 openstudio-workflow gem.')
|
|
79
|
+
|
|
80
|
+
# Write OSW file for the simulation
|
|
81
|
+
require 'JSON'
|
|
82
|
+
osw_hash = {
|
|
83
|
+
run_dir: Dir.pwd,
|
|
84
|
+
seed_model: File.absolute_path(idf_path.to_s),
|
|
85
|
+
weather_file: File.absolute_path(epw_path.to_s),
|
|
86
|
+
steps: []
|
|
87
|
+
}
|
|
88
|
+
osw_path = File.join(Dir.pwd, 'workflow.osw')
|
|
89
|
+
File.open(osw_path, 'wb') { |f| f << JSON.pretty_generate(osw_hash) }
|
|
90
|
+
|
|
91
|
+
# Create local adapters
|
|
92
|
+
adapter_options = {workflow_filename: File.basename(osw_path), output_directory: File.join(Dir.pwd, 'run')}
|
|
93
|
+
input_adapter = OpenStudio::Workflow.load_input_adapter 'local', adapter_options
|
|
94
|
+
output_adapter = OpenStudio::Workflow.load_output_adapter 'local', adapter_options
|
|
95
|
+
|
|
96
|
+
# Run workflow.osw
|
|
97
|
+
run_options = Hash.new
|
|
98
|
+
run_options[:jobs] = [
|
|
99
|
+
{ state: :queued, next_state: :initialization, options: { initial: true } },
|
|
100
|
+
{ state: :initialization, next_state: :preprocess, job: :RunInitialization,
|
|
101
|
+
file: './jobs/run_initialization.rb', options: {} },
|
|
102
|
+
{ state: :preprocess, next_state: :simulation, job: :RunPreprocess,
|
|
103
|
+
file: './jobs/run_preprocess.rb' , options: {} },
|
|
104
|
+
{ state: :simulation, next_state: :finished, job: :RunEnergyPlus,
|
|
105
|
+
file: './jobs/run_energyplus.rb', options: {} },
|
|
106
|
+
{ state: :finished },
|
|
107
|
+
{ state: :errored }
|
|
108
|
+
]
|
|
109
|
+
k = OpenStudio::Workflow::Run.new input_adapter, output_adapter, File.dirname(osw_path), run_options
|
|
110
|
+
final_state = k.run
|
|
111
|
+
|
|
112
|
+
# Check run status and return the sql_path
|
|
113
|
+
if final_state == :finished
|
|
114
|
+
OpenStudio::logFree(OpenStudio::Info, 'openstudio.model.Model', 'Finished run.')
|
|
115
|
+
else
|
|
116
|
+
OpenStudio::logFree(OpenStudio::Info, 'openstudio.model.Model', 'Run completed with errors.')
|
|
117
|
+
end
|
|
118
|
+
sql_path = OpenStudio::Path.new("#{Dir.pwd}/run/eplusout.sql")
|
|
119
|
+
|
|
120
|
+
OpenStudio::logFree(OpenStudio::Info, 'openstudio.model.Model', 'Finished simulation.')
|
|
121
|
+
|
|
122
|
+
else # Use the pre OS 2.0 openstudio-workflow gem
|
|
123
|
+
OpenStudio::logFree(OpenStudio::Info, 'openstudio.model.Model', 'Running with pre OS 2.0 openstudio-workflow gem.')
|
|
79
124
|
|
|
80
125
|
# Copy the weather file to this directory
|
|
81
126
|
FileUtils.copy(epw_path.to_s, run_dir)
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: openstudio-standards
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Andrew Parker
|
|
@@ -20,7 +20,7 @@ authors:
|
|
|
20
20
|
autorequire:
|
|
21
21
|
bindir: bin
|
|
22
22
|
cert_chain: []
|
|
23
|
-
date: 2016-04-
|
|
23
|
+
date: 2016-04-27 00:00:00.000000000 Z
|
|
24
24
|
dependencies:
|
|
25
25
|
- !ruby/object:Gem::Dependency
|
|
26
26
|
name: bundler
|