openstudio-standards 0.6.3 → 0.7.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/data/standards/OpenStudio_Standards-ashrae_90_1.xlsx +0 -0
- data/data/standards/manage_OpenStudio_Standards.rb +2 -49
- data/data/standards/openstudio_standards_duplicates_log.csv +1 -7962
- data/data/standards/test_performance_expected_dd_results.csv +2005 -97
- data/lib/openstudio-standards/create_typical/space_type_ratios.rb +47 -57
- data/lib/openstudio-standards/geometry/create.rb +1 -1
- data/lib/openstudio-standards/geometry/create_bar.rb +6 -3
- data/lib/openstudio-standards/geometry/create_shape.rb +1 -1
- data/lib/openstudio-standards/geometry/group.rb +1 -1
- data/lib/openstudio-standards/geometry/information.rb +1 -1
- data/lib/openstudio-standards/geometry/modify.rb +53 -1
- data/lib/openstudio-standards/infiltration/nist_infiltration.rb +1 -1
- data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2016/ashrae_90_1_2016.Model.rb +11 -11
- data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.Model.rb +11 -11
- data/lib/openstudio-standards/prototypes/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.hvac_systems.rb +2 -2
- data/lib/openstudio-standards/prototypes/common/buildings/Prototype.SuperTallBuilding.rb +44 -47
- data/lib/openstudio-standards/prototypes/common/buildings/Prototype.TallBuilding.rb +43 -48
- data/lib/openstudio-standards/prototypes/common/objects/Prototype.CentralAirSourceHeatPump.rb +1 -1
- data/lib/openstudio-standards/prototypes/common/objects/Prototype.hvac_systems.rb +44 -24
- data/lib/openstudio-standards/prototypes/common/objects/Prototype.refrigeration.rb +24 -24
- data/lib/openstudio-standards/schedules/parametric.rb +1 -1
- data/lib/openstudio-standards/service_water_heating/create_piping_losses.rb +152 -0
- data/lib/openstudio-standards/service_water_heating/create_water_heater.rb +544 -0
- data/lib/openstudio-standards/service_water_heating/create_water_heating_loop.rb +303 -0
- data/lib/openstudio-standards/service_water_heating/create_water_use.rb +95 -0
- data/lib/openstudio-standards/space/space.rb +1 -1
- data/lib/openstudio-standards/standards/Standards.AirLoopHVAC.rb +65 -70
- data/lib/openstudio-standards/standards/Standards.CoilCoolingWaterToAirHeatPumpEquationFit.rb +12 -14
- data/lib/openstudio-standards/standards/Standards.CoilHeatingDXSingleSpeed.rb +16 -5
- data/lib/openstudio-standards/standards/Standards.Model.rb +2 -2
- data/lib/openstudio-standards/standards/Standards.PlanarSurface.rb +10 -2
- data/lib/openstudio-standards/{prototypes/common/objects/Prototype.Model.swh.rb → standards/Standards.ServiceWaterHeating.rb} +209 -139
- data/lib/openstudio-standards/standards/Standards.Surface.rb +1 -1
- data/lib/openstudio-standards/standards/Standards.ZoneHVACComponent.rb +4 -8
- data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2004/ashrae_90_1_2004.Model.rb +2 -2
- data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2004/data/ashrae_90_1_2004.construction_properties.json +22251 -12963
- data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2004/data/ashrae_90_1_2004.construction_sets.json +91 -91
- data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2007/data/ashrae_90_1_2007.construction_properties.json +8981 -5228
- data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2010/data/ashrae_90_1_2010.construction_properties.json +8935 -5182
- data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2013/data/ashrae_90_1_2013.construction_properties.json +7281 -5391
- data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2013/data/ashrae_90_1_2013.construction_sets.json +91 -91
- data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2016/data/ashrae_90_1_2016.construction_properties.json +9005 -15215
- data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2016/data/ashrae_90_1_2016.construction_sets.json +136 -136
- data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/ashrae_90_1_2019.AirLoopHVAC.rb +1 -1
- data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/data/ashrae_90_1_2019.construction_properties.json +8717 -17168
- data/lib/openstudio-standards/standards/ashrae_90_1/ashrae_90_1_2019/data/ashrae_90_1_2019.construction_sets.json +136 -136
- data/lib/openstudio-standards/standards/ashrae_90_1/data/ashrae_90_1.constructions.json +1941 -651
- data/lib/openstudio-standards/standards/ashrae_90_1/doe_ref_1980_2004/data/doe_ref_1980_2004.construction_properties.json +135 -135
- data/lib/openstudio-standards/standards/ashrae_90_1/doe_ref_pre_1980/data/doe_ref_pre_1980.construction_properties.json +135 -135
- data/lib/openstudio-standards/standards/ashrae_90_1/nrel_zne_ready_2017/data/nrel_zne_ready_2017.construction_properties.json +36 -36
- data/lib/openstudio-standards/standards/ashrae_90_1/ze_aedg_multifamily/data/ze_aedg_multifamily.construction_properties.json +36 -36
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.PlantLoop.rb +377 -99
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm.SpaceType.rb +2 -2
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/ashrae_90_1_prm_2019.Model.rb +3 -3
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/data/ashrae_90_1_prm_2019.construction_properties.json +6889 -4044
- data/lib/openstudio-standards/standards/ashrae_90_1_prm/ashrae_90_1_prm_2019/data/ashrae_90_1_prm_2019.prm_constructions.json +108 -108
- data/lib/openstudio-standards/standards/cbes/cbes_pre_1978/data/cbes_pre_1978.construction_properties.json +16 -16
- data/lib/openstudio-standards/standards/cbes/cbes_t24_1978/data/cbes_t24_1978.construction_properties.json +16 -16
- data/lib/openstudio-standards/standards/cbes/cbes_t24_1992/data/cbes_t24_1992.construction_properties.json +16 -16
- data/lib/openstudio-standards/standards/cbes/cbes_t24_2001/data/cbes_t24_2001.construction_properties.json +16 -16
- data/lib/openstudio-standards/standards/cbes/cbes_t24_2005/data/cbes_t24_2005.construction_properties.json +16 -16
- data/lib/openstudio-standards/standards/cbes/cbes_t24_2008/data/cbes_t24_2008.construction_properties.json +16 -16
- data/lib/openstudio-standards/standards/cbes/data/cbes.constructions.json +142 -142
- data/lib/openstudio-standards/standards/deer/data/deer.constructions.json +5 -1551
- data/lib/openstudio-standards/standards/deer/data/deer.materials.json +40 -0
- data/lib/openstudio-standards/standards/deer/deer_1985/data/deer_1985.motors.json +88 -8
- data/lib/openstudio-standards/standards/deer/deer_1996/data/deer_1996.motors.json +88 -8
- data/lib/openstudio-standards/standards/deer/deer_2003/data/deer_2003.motors.json +88 -8
- data/lib/openstudio-standards/standards/deer/deer_2007/data/deer_2007.motors.json +88 -8
- data/lib/openstudio-standards/standards/deer/deer_2011/data/deer_2011.motors.json +88 -8
- data/lib/openstudio-standards/standards/deer/deer_2014/data/deer_2014.motors.json +88 -8
- data/lib/openstudio-standards/standards/deer/deer_2015/data/deer_2015.motors.json +88 -8
- data/lib/openstudio-standards/standards/deer/deer_2017/data/deer_2017.motors.json +88 -8
- data/lib/openstudio-standards/standards/deer/deer_2020/data/deer_2020.motors.json +88 -8
- data/lib/openstudio-standards/standards/deer/deer_2025/data/deer_2025.motors.json +88 -8
- data/lib/openstudio-standards/standards/deer/deer_2030/data/deer_2030.motors.json +88 -8
- data/lib/openstudio-standards/standards/deer/deer_2035/data/deer_2035.motors.json +88 -8
- data/lib/openstudio-standards/standards/deer/deer_2040/data/deer_2040.motors.json +88 -8
- data/lib/openstudio-standards/standards/deer/deer_2045/data/deer_2045.motors.json +88 -8
- data/lib/openstudio-standards/standards/deer/deer_2050/data/deer_2050.motors.json +88 -8
- data/lib/openstudio-standards/standards/deer/deer_2055/data/deer_2055.motors.json +88 -8
- data/lib/openstudio-standards/standards/deer/deer_2060/data/deer_2060.motors.json +88 -8
- data/lib/openstudio-standards/standards/deer/deer_2065/data/deer_2065.motors.json +88 -8
- data/lib/openstudio-standards/standards/deer/deer_2070/data/deer_2070.motors.json +88 -8
- data/lib/openstudio-standards/standards/deer/deer_2075/data/deer_2075.motors.json +88 -8
- data/lib/openstudio-standards/standards/deer/deer_pre_1975/data/deer_pre_1975.motors.json +88 -8
- data/lib/openstudio-standards/standards/necb/BTAPPRE1980/btap_pre1980.rb +17 -0
- data/lib/openstudio-standards/standards/necb/BTAPPRE1980/hvac_systems.rb +2 -1
- data/lib/openstudio-standards/standards/necb/ECMS/ecms.rb +4 -4
- data/lib/openstudio-standards/standards/necb/ECMS/hvac_systems.rb +61 -88
- data/lib/openstudio-standards/standards/necb/NECB2011/autozone.rb +3 -2
- data/lib/openstudio-standards/standards/necb/NECB2011/data/boiler_fuel_type_sets.json +54 -0
- data/lib/openstudio-standards/standards/necb/NECB2011/data/geometry/LEEPMidriseApartment.osm +1 -1
- data/lib/openstudio-standards/standards/necb/NECB2011/data/geometry/LEEPMultiTower.osm +1 -1
- data/lib/openstudio-standards/standards/necb/NECB2011/data/geometry/LEEPPointTower.osm +1 -1
- data/lib/openstudio-standards/standards/necb/NECB2011/data/geometry/LEEPTownHouse.osm +1 -1
- data/lib/openstudio-standards/standards/necb/NECB2011/data/geometry/NorthernEducation.osm +4 -4
- data/lib/openstudio-standards/standards/necb/NECB2011/data/geometry/NorthernHealthCare.osm +4 -4
- data/lib/openstudio-standards/standards/necb/NECB2011/hvac_systems.rb +32 -24
- data/lib/openstudio-standards/standards/necb/NECB2011/necb_2011.rb +89 -15
- data/lib/openstudio-standards/standards/necb/NECB2011/qaqc/necb_qaqc.rb +5 -1
- data/lib/openstudio-standards/standards/necb/NECB2011/service_water_heating.rb +22 -65
- data/lib/openstudio-standards/standards/necb/NECB2011/system_fuels.rb +19 -0
- data/lib/openstudio-standards/standards/necb/common/btap_data.rb +56 -2
- data/lib/openstudio-standards/standards/necb/common/btap_datapoint.rb +3 -1
- data/lib/openstudio-standards/standards/necb/common/construction_defaults.osm +2 -2
- data/lib/openstudio-standards/standards/necb/docs/air_system_names_method.md +127 -0
- data/lib/openstudio-standards/thermal_zone/thermal_zone.rb +1 -1
- data/lib/openstudio-standards/utilities/template_measure/resources/BTAPMeasureHelper.rb +1 -1
- data/lib/openstudio-standards/version.rb +1 -1
- data/lib/openstudio-standards/weather/information.rb +61 -5
- data/lib/openstudio-standards/weather/modify.rb +1 -1
- data/lib/openstudio-standards.rb +5 -3
- metadata +12 -63
- data/data/standards/OpenStudio_Standards-deer.xlsx +0 -0
- data/lib/openstudio-standards/prototypes/common/objects/Prototype.ServiceWaterHeating.rb +0 -1100
- data/lib/openstudio-standards/service_water_heating/component.rb +0 -189
@@ -0,0 +1,303 @@
|
|
1
|
+
module OpenstudioStandards
|
2
|
+
# The ServiceWaterHeating module provides methods to create, modify, and get information about service water heating
|
3
|
+
module ServiceWaterHeating
|
4
|
+
# @!group Create Loop
|
5
|
+
# Methods to add service water heating loops
|
6
|
+
|
7
|
+
# Creates a service water heating loop.
|
8
|
+
#
|
9
|
+
# @param model [OpenStudio::Model::Model] OpenStudio model object
|
10
|
+
# @param system_name [String] the name of the system. nil results in the default.
|
11
|
+
# @param service_water_temperature [Double] water heater temperature, in degrees C. Default is 60 C / 140 F.
|
12
|
+
# @param service_water_pump_head [Double] service water pump head, in Pa. Default is 29861 Pa / 10 ft.
|
13
|
+
# @param service_water_pump_motor_efficiency [Double] service water pump motor efficiency, as decimal.
|
14
|
+
# @param water_heater_capacity [Double] water heater capacity, in W. Defaults to 58.6 kW / 200 kBtu/hr
|
15
|
+
# @param water_heater_volume [Double] water heater volume, in m^3. Defaults to 0.378 m^3 / 100 gal
|
16
|
+
# @param water_heater_fuel [String] water heating fuel. Valid choices are 'NaturalGas', 'Electricity', 'FuelOilNo2', 'SimpleHeatPump', 'HeatPump', or 'None'.
|
17
|
+
# If 'None', no water heater will be added.
|
18
|
+
# @param on_cycle_parasitic_fuel_consumption_rate [Double] water heater on cycle parasitic fuel consumption rate, in W
|
19
|
+
# @param off_cycle_parasitic_fuel_consumption_rate [Double] water heater off cycle parasitic fuel consumption rate, in W
|
20
|
+
# @param water_heater_thermal_zone [OpenStudio::Model::ThermalZone] Thermal zone for ambient heat loss.
|
21
|
+
# If nil, will assume 71.6 F / 22 C ambient air temperature.
|
22
|
+
# @param number_of_water_heaters [Integer] the number of water heaters represented by the capacity and volume inputs.
|
23
|
+
# Used to modify efficiencies for water heaters based on individual component size while avoiding having to model lots of individual water heaters (for runtime sake).
|
24
|
+
# @param add_piping_losses [Boolean] if true, add piping and associated heat losses to system. If false, add no pipe heat losses.
|
25
|
+
# @param pipe_insulation_thickness [Double] the thickness of the pipe insulation, in m. Default is 0.0127 m / 0.5 inches.
|
26
|
+
# @param floor_area [Double] the area of building served by the service water heating loop, in m^2
|
27
|
+
# If nil, will use the total building floor area. Only used if piping losses is true and the system is circulating.
|
28
|
+
# @param number_of_stories [Integer] the number of stories served by the service water heating loop
|
29
|
+
# If nil, will use the total building number of stories. Only used if piping losses is true and the system is circulating.
|
30
|
+
# @return [OpenStudio::Model::PlantLoop] OpenStudio PlantLoop object of the service water loop
|
31
|
+
def self.create_service_water_heating_loop(model,
|
32
|
+
system_name: 'Service Water Loop',
|
33
|
+
service_water_temperature: 60.0,
|
34
|
+
service_water_pump_head: 29861.0,
|
35
|
+
service_water_pump_motor_efficiency: 0.3,
|
36
|
+
water_heater_capacity: nil,
|
37
|
+
water_heater_volume: nil,
|
38
|
+
water_heater_fuel: 'Electricity',
|
39
|
+
on_cycle_parasitic_fuel_consumption_rate: 0.0,
|
40
|
+
off_cycle_parasitic_fuel_consumption_rate: 0.0,
|
41
|
+
water_heater_thermal_zone: nil,
|
42
|
+
number_of_water_heaters: 1,
|
43
|
+
add_piping_losses: false,
|
44
|
+
pipe_insulation_thickness: 0.0127,
|
45
|
+
floor_area: nil,
|
46
|
+
number_of_stories: nil)
|
47
|
+
|
48
|
+
# create service water heating loop
|
49
|
+
service_water_loop = OpenStudio::Model::PlantLoop.new(model)
|
50
|
+
service_water_loop.setMinimumLoopTemperature(10.0)
|
51
|
+
if service_water_temperature > 60.0
|
52
|
+
service_water_loop.setMaximumLoopTemperature(service_water_temperature)
|
53
|
+
else
|
54
|
+
service_water_loop.setMaximumLoopTemperature(60.0)
|
55
|
+
end
|
56
|
+
|
57
|
+
if system_name.nil?
|
58
|
+
system_name = 'Service Water Loop'
|
59
|
+
end
|
60
|
+
service_water_loop.setName(system_name)
|
61
|
+
|
62
|
+
# service water heating loop controls
|
63
|
+
swh_temp_f = OpenStudio.convert(service_water_temperature, 'C', 'F').get
|
64
|
+
swh_delta_t_r = 9.0 # 9F delta-T
|
65
|
+
swh_delta_t_k = OpenStudio.convert(swh_delta_t_r, 'R', 'K').get
|
66
|
+
swh_temp_sch = OpenstudioStandards::Schedules.create_constant_schedule_ruleset(model,
|
67
|
+
service_water_temperature,
|
68
|
+
name: "Service Water Loop Temp - #{swh_temp_f.round}F",
|
69
|
+
schedule_type_limit: 'Temperature')
|
70
|
+
swh_stpt_manager = OpenStudio::Model::SetpointManagerScheduled.new(model, swh_temp_sch)
|
71
|
+
swh_stpt_manager.setName('Service hot water setpoint manager')
|
72
|
+
swh_stpt_manager.addToNode(service_water_loop.supplyOutletNode)
|
73
|
+
sizing_plant = service_water_loop.sizingPlant
|
74
|
+
sizing_plant.setLoopType('Heating')
|
75
|
+
sizing_plant.setDesignLoopExitTemperature(service_water_temperature)
|
76
|
+
sizing_plant.setLoopDesignTemperatureDifference(swh_delta_t_k)
|
77
|
+
|
78
|
+
# determine if circulating or non-circulating based on supplied head pressure
|
79
|
+
if service_water_pump_head.nil? || service_water_pump_head <= 1
|
80
|
+
# set pump head pressure to near zero if there is no circulation pump
|
81
|
+
service_water_pump_head = 0.001
|
82
|
+
service_water_pump_motor_efficiency = 1
|
83
|
+
circulating = false
|
84
|
+
else
|
85
|
+
circulating = true
|
86
|
+
end
|
87
|
+
|
88
|
+
# add pump
|
89
|
+
if circulating
|
90
|
+
swh_pump = OpenStudio::Model::PumpConstantSpeed.new(model)
|
91
|
+
swh_pump.setName("#{service_water_loop.name} Circulator Pump")
|
92
|
+
swh_pump.setPumpControlType('Intermittent')
|
93
|
+
else
|
94
|
+
swh_pump = OpenStudio::Model::PumpVariableSpeed.new(model)
|
95
|
+
swh_pump.setName("#{service_water_loop.name} Water Mains Pressure Driven")
|
96
|
+
swh_pump.setPumpControlType('Continuous')
|
97
|
+
end
|
98
|
+
swh_pump.setRatedPumpHead(service_water_pump_head.to_f)
|
99
|
+
swh_pump.setMotorEfficiency(service_water_pump_motor_efficiency)
|
100
|
+
swh_pump.addToNode(service_water_loop.supplyInletNode)
|
101
|
+
|
102
|
+
# add water heater
|
103
|
+
case water_heater_fuel
|
104
|
+
when 'None'
|
105
|
+
# don't add a water heater
|
106
|
+
when 'HeatPump'
|
107
|
+
OpenstudioStandards::ServiceWaterHeating.create_heatpump_water_heater(model,
|
108
|
+
water_heater_capacity: water_heater_capacity,
|
109
|
+
water_heater_volume: water_heater_volume,
|
110
|
+
on_cycle_parasitic_fuel_consumption_rate: on_cycle_parasitic_fuel_consumption_rate,
|
111
|
+
off_cycle_parasitic_fuel_consumption_rate: off_cycle_parasitic_fuel_consumption_rate,
|
112
|
+
service_water_temperature: service_water_temperature,
|
113
|
+
service_water_temperature_schedule: swh_temp_sch,
|
114
|
+
set_peak_use_flowrate: false,
|
115
|
+
peak_flowrate: 0.0,
|
116
|
+
flowrate_schedule: nil,
|
117
|
+
water_heater_thermal_zone: water_heater_thermal_zone,
|
118
|
+
service_water_loop: service_water_loop,
|
119
|
+
use_ems_control: false)
|
120
|
+
else
|
121
|
+
OpenstudioStandards::ServiceWaterHeating.create_water_heater(model,
|
122
|
+
water_heater_capacity: water_heater_capacity,
|
123
|
+
water_heater_volume: water_heater_volume,
|
124
|
+
water_heater_fuel: water_heater_fuel,
|
125
|
+
on_cycle_parasitic_fuel_consumption_rate: on_cycle_parasitic_fuel_consumption_rate,
|
126
|
+
off_cycle_parasitic_fuel_consumption_rate: off_cycle_parasitic_fuel_consumption_rate,
|
127
|
+
service_water_temperature: service_water_temperature,
|
128
|
+
service_water_temperature_schedule: swh_temp_sch,
|
129
|
+
set_peak_use_flowrate: false,
|
130
|
+
peak_flowrate: 0.0,
|
131
|
+
flowrate_schedule: nil,
|
132
|
+
water_heater_thermal_zone: water_heater_thermal_zone,
|
133
|
+
number_of_water_heaters: number_of_water_heaters,
|
134
|
+
service_water_loop: service_water_loop)
|
135
|
+
end
|
136
|
+
|
137
|
+
# add pipe losses if requested
|
138
|
+
if add_piping_losses
|
139
|
+
OpenstudioStandards::ServiceWaterHeating.create_service_water_heating_piping_losses(model,
|
140
|
+
service_water_loop,
|
141
|
+
circulating: circulating,
|
142
|
+
pipe_insulation_thickness: pipe_insulation_thickness,
|
143
|
+
floor_area: floor_area,
|
144
|
+
number_of_stories: number_of_stories)
|
145
|
+
end
|
146
|
+
|
147
|
+
# service water heating loop bypass pipes
|
148
|
+
water_heater_bypass_pipe = OpenStudio::Model::PipeAdiabatic.new(model)
|
149
|
+
service_water_loop.addSupplyBranchForComponent(water_heater_bypass_pipe)
|
150
|
+
coil_bypass_pipe = OpenStudio::Model::PipeAdiabatic.new(model)
|
151
|
+
service_water_loop.addDemandBranchForComponent(coil_bypass_pipe)
|
152
|
+
supply_outlet_pipe = OpenStudio::Model::PipeAdiabatic.new(model)
|
153
|
+
supply_outlet_pipe.addToNode(service_water_loop.supplyOutletNode)
|
154
|
+
demand_outlet_pipe = OpenStudio::Model::PipeAdiabatic.new(model)
|
155
|
+
demand_outlet_pipe.addToNode(service_water_loop.demandOutletNode)
|
156
|
+
|
157
|
+
if circulating
|
158
|
+
OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.ServiceWaterHeating', "Added circulating SWH loop called #{service_water_loop.name}")
|
159
|
+
else
|
160
|
+
OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.ServiceWaterHeating', "Added non-circulating SWH loop called #{service_water_loop.name}")
|
161
|
+
end
|
162
|
+
|
163
|
+
return service_water_loop
|
164
|
+
end
|
165
|
+
|
166
|
+
# Creates a booster water heater on its own loop and attaches it to the main service water heating loop.
|
167
|
+
#
|
168
|
+
# @param model [OpenStudio::Model::Model] OpenStudio model object
|
169
|
+
# @param water_heater_capacity [Double] water heater capacity, in W. Defaults to 8 kW / 27.283 kBtu/hr
|
170
|
+
# @param water_heater_volume [Double] water heater volume, in m^3. Defaults to 0.0227 m^3 / 6 gal
|
171
|
+
# @param water_heater_fuel [String] water heating fuel. Valid choices are 'NaturalGas', 'Electricity'.
|
172
|
+
# @param on_cycle_parasitic_fuel_consumption_rate [Double] water heater on cycle parasitic fuel consumption rate, in W
|
173
|
+
# @param off_cycle_parasitic_fuel_consumption_rate [Double] water heater off cycle parasitic fuel consumption rate, in W
|
174
|
+
# @param service_water_temperature [Double] water heater temperature, in degrees C. Default is 82.2 C / 180 F.
|
175
|
+
# @param service_water_temperature_schedule [OpenStudio::Model::Schedule] the service water heating schedule.
|
176
|
+
# If nil, will be defaulted to a constant temperature schedule based on the service_water_temperature
|
177
|
+
# @param water_heater_thermal_zone [OpenStudio::Model::ThermalZone] Thermal zone for ambient heat loss.
|
178
|
+
# If nil, will assume 71.6 F / 22 C ambient air temperature.
|
179
|
+
# @param service_water_loop [OpenStudio::Model::PlantLoop] if provided, add the water heater to this loop
|
180
|
+
# @return [OpenStudio::Model::PlantLoop] The booster water loop OpenStudio PlantLoop object
|
181
|
+
def self.create_booster_water_heating_loop(model,
|
182
|
+
water_heater_capacity: 8000.0,
|
183
|
+
water_heater_volume: OpenStudio.convert(6.0, 'gal', 'm^3').get,
|
184
|
+
water_heater_fuel: 'Electricity',
|
185
|
+
on_cycle_parasitic_fuel_consumption_rate: 0.0,
|
186
|
+
off_cycle_parasitic_fuel_consumption_rate: 0.0,
|
187
|
+
service_water_temperature: 82.2,
|
188
|
+
service_water_temperature_schedule: nil,
|
189
|
+
water_heater_thermal_zone: nil,
|
190
|
+
service_water_loop: nil)
|
191
|
+
if service_water_loop.nil?
|
192
|
+
OpenStudio.logFree(OpenStudio::Error, 'openstudio.standards.ServiceWaterHeating', "#{_method_} requires the service_water_loop argument to couple the booster water heating loop with a heat exchanger.")
|
193
|
+
return nil
|
194
|
+
else
|
195
|
+
OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.ServiceWaterHeating', "Adding booster water heater to #{service_water_loop.name}")
|
196
|
+
end
|
197
|
+
|
198
|
+
water_heater_volume_gal = OpenStudio.convert(water_heater_volume, 'm^3', 'gal').get
|
199
|
+
water_heater_capacity_kbtu_per_hr = OpenStudio.convert(water_heater_capacity, 'W', 'kBtu/hr').get
|
200
|
+
|
201
|
+
# Booster water heating loop
|
202
|
+
booster_service_water_loop = OpenStudio::Model::PlantLoop.new(model)
|
203
|
+
booster_service_water_loop.setName('Booster Service Water Loop')
|
204
|
+
|
205
|
+
# create and add booster water heater to loop
|
206
|
+
booster_water_heater = OpenstudioStandards::ServiceWaterHeating.create_water_heater(model,
|
207
|
+
water_heater_capacity: water_heater_capacity,
|
208
|
+
water_heater_volume: water_heater_volume,
|
209
|
+
water_heater_fuel: water_heater_fuel,
|
210
|
+
on_cycle_parasitic_fuel_consumption_rate: on_cycle_parasitic_fuel_consumption_rate,
|
211
|
+
off_cycle_parasitic_fuel_consumption_rate: off_cycle_parasitic_fuel_consumption_rate,
|
212
|
+
service_water_temperature: service_water_temperature,
|
213
|
+
service_water_temperature_schedule: service_water_temperature_schedule,
|
214
|
+
water_heater_thermal_zone: water_heater_thermal_zone,
|
215
|
+
service_water_loop: booster_service_water_loop)
|
216
|
+
booster_water_heater.setName("#{water_heater_volume_gal}gal #{water_heater_fuel} Booster Water Heater - #{water_heater_capacity_kbtu_per_hr.round}kBtu/hr")
|
217
|
+
booster_water_heater.setEndUseSubcategory('Booster')
|
218
|
+
|
219
|
+
# Service water heating loop controls
|
220
|
+
swh_temp_f = OpenStudio.convert(service_water_temperature, 'C', 'F').get
|
221
|
+
swh_delta_t_r = 9.0 # 9F delta-T
|
222
|
+
swh_delta_t_k = OpenStudio.convert(swh_delta_t_r, 'R', 'K').get
|
223
|
+
swh_temp_sch = OpenstudioStandards::Schedules.create_constant_schedule_ruleset(model,
|
224
|
+
service_water_temperature,
|
225
|
+
name: "Service Water Booster Temp - #{swh_temp_f.round}F",
|
226
|
+
schedule_type_limit: 'Temperature')
|
227
|
+
swh_stpt_manager = OpenStudio::Model::SetpointManagerScheduled.new(model, swh_temp_sch)
|
228
|
+
swh_stpt_manager.setName('Hot water booster setpoint manager')
|
229
|
+
swh_stpt_manager.addToNode(booster_service_water_loop.supplyOutletNode)
|
230
|
+
sizing_plant = booster_service_water_loop.sizingPlant
|
231
|
+
sizing_plant.setLoopType('Heating')
|
232
|
+
sizing_plant.setDesignLoopExitTemperature(service_water_temperature)
|
233
|
+
sizing_plant.setLoopDesignTemperatureDifference(swh_delta_t_k)
|
234
|
+
|
235
|
+
# Booster water heating pump
|
236
|
+
swh_pump = OpenStudio::Model::PumpVariableSpeed.new(model)
|
237
|
+
swh_pump.setName('Booster Water Loop Pump')
|
238
|
+
swh_pump.setRatedPumpHead(0.0) # As if there is no circulation pump
|
239
|
+
swh_pump.setRatedPowerConsumption(0.0) # As if there is no circulation pump
|
240
|
+
swh_pump.setMotorEfficiency(1)
|
241
|
+
swh_pump.setPumpControlType('Continuous')
|
242
|
+
swh_pump.setMinimumFlowRate(0.0)
|
243
|
+
swh_pump.addToNode(booster_service_water_loop.supplyInletNode)
|
244
|
+
|
245
|
+
# Service water heating loop bypass pipes
|
246
|
+
water_heater_bypass_pipe = OpenStudio::Model::PipeAdiabatic.new(model)
|
247
|
+
booster_service_water_loop.addSupplyBranchForComponent(water_heater_bypass_pipe)
|
248
|
+
coil_bypass_pipe = OpenStudio::Model::PipeAdiabatic.new(model)
|
249
|
+
booster_service_water_loop.addDemandBranchForComponent(coil_bypass_pipe)
|
250
|
+
supply_outlet_pipe = OpenStudio::Model::PipeAdiabatic.new(model)
|
251
|
+
supply_outlet_pipe.addToNode(booster_service_water_loop.supplyOutletNode)
|
252
|
+
demand_inlet_pipe = OpenStudio::Model::PipeAdiabatic.new(model)
|
253
|
+
demand_inlet_pipe.addToNode(booster_service_water_loop.demandInletNode)
|
254
|
+
demand_outlet_pipe = OpenStudio::Model::PipeAdiabatic.new(model)
|
255
|
+
demand_outlet_pipe.addToNode(booster_service_water_loop.demandOutletNode)
|
256
|
+
|
257
|
+
# Heat exchanger to supply the booster water heater with normal hot water from the main service water loop
|
258
|
+
hx = OpenStudio::Model::HeatExchangerFluidToFluid.new(model)
|
259
|
+
hx.setName('Booster Water Heating Heat Exchanger')
|
260
|
+
hx.setHeatExchangeModelType('Ideal')
|
261
|
+
hx.setControlType('UncontrolledOn')
|
262
|
+
hx.setHeatTransferMeteringEndUseType('LoopToLoop')
|
263
|
+
|
264
|
+
# Add the HX to the supply side of the booster loop
|
265
|
+
hx.addToNode(booster_service_water_loop.supplyInletNode)
|
266
|
+
|
267
|
+
# Add the HX to the demand side of the main service water loop
|
268
|
+
service_water_loop.addDemandBranchForComponent(hx)
|
269
|
+
|
270
|
+
# Add a plant component temperature source to the demand outlet
|
271
|
+
# of the HX to represent the fact that the water used by the booster
|
272
|
+
# would in reality be at the mains temperature.
|
273
|
+
mains_src = OpenStudio::Model::PlantComponentTemperatureSource.new(model)
|
274
|
+
mains_src.setName('Mains Water Makeup for SWH Booster')
|
275
|
+
mains_src.addToNode(hx.demandOutletModelObject.get.to_Node.get)
|
276
|
+
|
277
|
+
# use the site water mains temperature schedule if available,
|
278
|
+
# otherwise use the annual average outdoor air temperature
|
279
|
+
site_water_mains = model.getSiteWaterMainsTemperature
|
280
|
+
if site_water_mains.temperatureSchedule.is_initialized
|
281
|
+
water_mains_temp_sch = site_water_mains.temperatureSchedule.get
|
282
|
+
elsif site_water_mains.annualAverageOutdoorAirTemperature.is_initialized
|
283
|
+
mains_src_temp_c = site_water_mains.annualAverageOutdoorAirTemperature.get
|
284
|
+
mains_src.setSourceTemperature(mains_src_temp_c)
|
285
|
+
water_mains_temp_sch = OpenStudio::Model::ScheduleConstant.new(model)
|
286
|
+
water_mains_temp_sch.setName('Booster Water Makeup Temperature')
|
287
|
+
water_mains_temp_sch.setValue(mains_src_temp_c)
|
288
|
+
else # assume 50F
|
289
|
+
mains_src_temp_c = OpenStudio.convert(50.0, 'F', 'C').get
|
290
|
+
mains_src.setSourceTemperature(mains_src_temp_c)
|
291
|
+
water_mains_temp_sch = OpenStudio::Model::ScheduleConstant.new(model)
|
292
|
+
water_mains_temp_sch.setName('Booster Water Makeup Temperature')
|
293
|
+
water_mains_temp_sch.setValue(mains_src_temp_c)
|
294
|
+
end
|
295
|
+
mains_src.setTemperatureSpecificationType('Scheduled')
|
296
|
+
mains_src.setSourceTemperatureSchedule(water_mains_temp_sch)
|
297
|
+
|
298
|
+
return booster_service_water_loop
|
299
|
+
end
|
300
|
+
|
301
|
+
# @!endgroup Create Loop
|
302
|
+
end
|
303
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
module OpenstudioStandards
|
2
|
+
# The ServiceWaterHeating module provides methods to create, modify, and get information about service water heating
|
3
|
+
module ServiceWaterHeating
|
4
|
+
# @!group Create Water Use
|
5
|
+
# Methods to add service water uses
|
6
|
+
|
7
|
+
# Creates a water use and attaches it to a service water loop and a space, if provided
|
8
|
+
#
|
9
|
+
# @param model [OpenStudio::Model::Model] OpenStudio model object
|
10
|
+
# @param name [String] Use name of the water use object, e.g. main or laundry
|
11
|
+
# @param flow_rate [Double] the peak flow rate of the water use in m^3/s
|
12
|
+
# @param flow_rate_fraction_schedule [OpenStudio::Model::Schedule] the flow rate fraction schedule
|
13
|
+
# @param water_use_temperature [Double] mixed water use temperature at the fixture, in degrees C. Default is 43.3 C / 110 F.
|
14
|
+
# @param water_use_temperature_schedule [OpenStudio::Model::Schedule] water use temperature schedule.
|
15
|
+
# If nil, will be defaulted to a constant temperature schedule based on the water_use_temperature
|
16
|
+
# @param sensible_fraction [Double] the water use equipment sensible fraction to the space
|
17
|
+
# @param latent_fraction [Double] the water use equipment latent fraction to the space
|
18
|
+
# @param service_water_loop [OpenStudio::Model::PlantLoop] if provided, add the water use fixture to this loop
|
19
|
+
# @param space [OpenStudio::Model::Space] OpenStudio Space object
|
20
|
+
# @return [OpenStudio::Model::WaterUseEquipment] OpenStudio WaterUseEquipment object
|
21
|
+
def self.create_water_use(model,
|
22
|
+
name: 'Main Water Use',
|
23
|
+
flow_rate: 0.0,
|
24
|
+
flow_rate_fraction_schedule: nil,
|
25
|
+
water_use_temperature: 43.3,
|
26
|
+
water_use_temperature_schedule: nil,
|
27
|
+
sensible_fraction: 0.2,
|
28
|
+
latent_fraction: 0.05,
|
29
|
+
service_water_loop: nil,
|
30
|
+
space: nil)
|
31
|
+
# IP conversions for naming
|
32
|
+
flow_rate_gpm = OpenStudio.convert(flow_rate, 'm^3/s', 'gal/min').get
|
33
|
+
water_use_temperature_f = OpenStudio.convert(water_use_temperature, 'C', 'F').get
|
34
|
+
|
35
|
+
# default name
|
36
|
+
name = 'Main Water Use' if name.nil?
|
37
|
+
|
38
|
+
# water use definition
|
39
|
+
water_use_def = OpenStudio::Model::WaterUseEquipmentDefinition.new(model)
|
40
|
+
|
41
|
+
# set sensible and latent fractions
|
42
|
+
water_use_sensible_frac_sch = OpenstudioStandards::Schedules.create_constant_schedule_ruleset(model,
|
43
|
+
sensible_fraction,
|
44
|
+
name: "Fraction Sensible - #{sensible_fraction}",
|
45
|
+
schedule_type_limit: 'Fractional')
|
46
|
+
water_use_latent_frac_sch = OpenstudioStandards::Schedules.create_constant_schedule_ruleset(model,
|
47
|
+
latent_fraction,
|
48
|
+
name: "Fraction Latent - #{latent_fraction}",
|
49
|
+
schedule_type_limit: 'Fractional')
|
50
|
+
water_use_def.setSensibleFractionSchedule(water_use_sensible_frac_sch)
|
51
|
+
water_use_def.setLatentFractionSchedule(water_use_latent_frac_sch)
|
52
|
+
water_use_def.setPeakFlowRate(flow_rate)
|
53
|
+
water_use_def.setName("#{name} #{flow_rate_gpm.round(2)}gpm #{water_use_temperature_f.round}F")
|
54
|
+
|
55
|
+
# target mixed water temperature
|
56
|
+
if water_use_temperature_schedule.nil?
|
57
|
+
water_use_temperature_schedule = OpenstudioStandards::Schedules.create_constant_schedule_ruleset(model,
|
58
|
+
water_use_temperature,
|
59
|
+
name: "Mixed Water At Faucet Temp - #{water_use_temperature_f.round}F",
|
60
|
+
schedule_type_limit: 'Temperature')
|
61
|
+
end
|
62
|
+
water_use_def.setTargetTemperatureSchedule(water_use_temperature_schedule)
|
63
|
+
|
64
|
+
# create water use equipment
|
65
|
+
water_fixture = OpenStudio::Model::WaterUseEquipment.new(water_use_def)
|
66
|
+
water_fixture.setFlowRateFractionSchedule(flow_rate_fraction_schedule)
|
67
|
+
|
68
|
+
# create water use connection
|
69
|
+
swh_connection = OpenStudio::Model::WaterUseConnections.new(model)
|
70
|
+
swh_connection.addWaterUseEquipment(water_fixture)
|
71
|
+
|
72
|
+
# add to the space if provided
|
73
|
+
if space.nil?
|
74
|
+
water_fixture.setName("#{name} Service Water Use #{flow_rate_gpm.round(2)}gpm #{water_use_temperature_f.round}F")
|
75
|
+
swh_connection.setName("#{name} WUC #{flow_rate_gpm.round(2)}gpm #{water_use_temperature_f.round}F")
|
76
|
+
else
|
77
|
+
water_fixture.setName("#{space.name} Service Water Use #{flow_rate_gpm.round(2)}gpm #{water_use_temperature_f.round}F")
|
78
|
+
swh_connection.setName("#{space.name} WUC #{flow_rate_gpm.round(2)}gpm #{water_use_temperature_f.round}F")
|
79
|
+
water_fixture.setSpace(space)
|
80
|
+
end
|
81
|
+
|
82
|
+
# add to the service water loop if provided
|
83
|
+
unless service_water_loop.nil?
|
84
|
+
service_water_loop.addDemandBranchForComponent(swh_connection)
|
85
|
+
OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.ServiceWaterHeating', "Adding water fixture to #{service_water_loop.name}.")
|
86
|
+
end
|
87
|
+
|
88
|
+
OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.ServiceWaterHeating', "Added #{water_fixture.name}.")
|
89
|
+
|
90
|
+
return water_fixture
|
91
|
+
end
|
92
|
+
|
93
|
+
# @!endgroup Create Water Use
|
94
|
+
end
|
95
|
+
end
|