Class: RadiantSlabWithDoas
- Inherits:
-
OpenStudio::Measure::ModelMeasure
- Object
- OpenStudio::Measure::ModelMeasure
- RadiantSlabWithDoas
- Defined in:
- lib/measures/radiant_slab_with_doas/measure.rb
Overview
start the measure
Instance Method Summary collapse
-
#arguments(model) ⇒ Object
define the arguments that the user will input.
-
#description ⇒ Object
human readable description.
-
#modeler_description ⇒ Object
human readable description of modeling approach.
-
#name ⇒ Object
human readable name.
-
#run(model, runner, user_arguments) ⇒ Object
define what happens when the measure is run.
Instance Method Details
#arguments(model) ⇒ Object
define the arguments that the user will input
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 |
# File 'lib/measures/radiant_slab_with_doas/measure.rb', line 39 def arguments(model) args = OpenStudio::Measure::OSArgumentVector.new # make bool argument to remove existing HVAC system remove_existing_hvac = OpenStudio::Measure::OSArgument.makeBoolArgument('remove_existing_hvac', true) remove_existing_hvac.setDisplayName('Remove existing HVAC system (keeps service water heating and zone exhaust fans)') remove_existing_hvac.setDefaultValue(true) args << remove_existing_hvac # make an argument for heating plant type heating_plant_types = OpenStudio::StringVector.new heating_plant_types << 'Air Source Heat Pump' heating_plant_types << 'Boiler' heating_plant_type = OpenStudio::Measure::OSArgument.makeChoiceArgument('heating_plant_type', heating_plant_types, true) heating_plant_type.setDisplayName('Heating Plant Type') heating_plant_type.setDefaultValue('Air Source Heat Pump') args << heating_plant_type # make an argument for cooling plant type cooling_plant_types = OpenStudio::StringVector.new cooling_plant_types << 'Air Cooled Chiller' cooling_plant_types << 'Water Cooled Chiller' cooling_plant_type = OpenStudio::Measure::OSArgument.makeChoiceArgument('cooling_plant_type', cooling_plant_types, true) cooling_plant_type.setDisplayName('Cooling Plant Type') cooling_plant_type.setDefaultValue('Air Cooled Chiller') args << cooling_plant_type # make string argument for water-side economizing if water-cooled chiller economizer_types = OpenStudio::StringVector.new economizer_types << 'none' economizer_types << 'integrated' economizer_types << 'non-integrated' waterside_economizer = OpenStudio::Measure::OSArgument.makeChoiceArgument('waterside_economizer', economizer_types, true) waterside_economizer.setDisplayName('Water-side economizer (water cooled chiller only)') waterside_economizer.setDefaultValue('none') args << waterside_economizer # make an argument for radiant system type radiant_types = OpenStudio::StringVector.new radiant_types << 'floor' radiant_types << 'ceiling' radiant_type = OpenStudio::Measure::OSArgument.makeChoiceArgument('radiant_type', radiant_types, true) radiant_type.setDisplayName('Radiant System Type') radiant_type.setDefaultValue('floor') args << radiant_type # make and argument for adding carpet include_carpet = OpenStudio::Measure::OSArgument.makeBoolArgument('include_carpet', true) include_carpet.setDisplayName('Include carpet over the radiant slab') include_carpet.setDescription('Only applicable in radiant floor systems. This will greatly reduce system effectiveness and controllability.') include_carpet.setDefaultValue(false) args << include_carpet # make an argument for control strategy control_strategys = OpenStudio::StringVector.new control_strategys << 'proportional_control' control_strategy = OpenStudio::Measure::OSArgument.makeChoiceArgument('control_strategy', control_strategys, true) control_strategy.setDisplayName('Control Strategy') control_strategy.setDefaultValue('proportional_control') args << control_strategy # make an argument for proportional gain proportional_gain = OpenStudio::Measure::OSArgument.makeDoubleArgument('proportional_gain', true) proportional_gain.setDisplayName('Proportional Gain') proportional_gain.setDefaultValue(0.3) args << proportional_gain # make an argument for switch over time switch_over_time = OpenStudio::Measure::OSArgument.makeDoubleArgument('switch_over_time', true) switch_over_time.setDisplayName('Switch Over Time') switch_over_time.setDescription('Minimum time limitation for when the system can switch between heating and cooling. Fractional hours allowed, e.g. 30 min = 0.5.') switch_over_time.setDefaultValue(24.0) args << switch_over_time # make and argument for including radiant lockout radiant_lockout = OpenStudio::Measure::OSArgument.makeBoolArgument('radiant_lockout', true) radiant_lockout.setDisplayName('Enable radiant lockout') radiant_lockout.setDescription('Lockout the radiant system to avoid operating during peak hours.') radiant_lockout.setDefaultValue(false) args << radiant_lockout # make an argument for lockout start time lockout_start_time = OpenStudio::Measure::OSArgument.makeDoubleArgument('lockout_start_time', true) lockout_start_time.setDisplayName('Lockout Start Time') lockout_start_time.setDescription('Decimal hour of when radiant lockout starts. Fractional hours allowed, e.g. 30 min = 0.5.') lockout_start_time.setDefaultValue(12.0) args << lockout_start_time # make an argument for lockout end time lockout_end_time = OpenStudio::Measure::OSArgument.makeDoubleArgument('lockout_end_time', true) lockout_end_time.setDisplayName('Lockout End Time') lockout_end_time.setDescription('Decimal hour of when radiant lockout ends. Fractional hours allowed, e.g. 30 min = 0.5.') lockout_end_time.setDefaultValue(20.0) args << lockout_end_time # make and argument for output variables add_output_variables = OpenStudio::Measure::OSArgument.makeBoolArgument('add_output_variables', true) add_output_variables.setDisplayName('Add output variables for radiant system') add_output_variables.setDefaultValue(true) args << add_output_variables # make an argument for standards template standards_templates = OpenStudio::StringVector.new standards_templates << '90.1-2013' standards_templates << 'DEER 2017' standards_templates << 'DEER 2020' standards_template = OpenStudio::Measure::OSArgument.makeChoiceArgument('standards_template', standards_templates, true) standards_template.setDisplayName('Standards Template') standards_template.setDescription('Standards template to use for HVAC equipment efficiencies and controls.') standards_template.setDefaultValue('90.1-2013') args << standards_template return args end |
#description ⇒ Object
human readable description
17 18 19 |
# File 'lib/measures/radiant_slab_with_doas/measure.rb', line 17 def description return 'Adds a radiant slab with DOAS ventilation system to the model.' end |
#modeler_description ⇒ Object
human readable description of modeling approach
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
# File 'lib/measures/radiant_slab_with_doas/measure.rb', line 22 def modeler_description return 'This measure adds either a radiant floor slab or radiant ceiling slab with dedicated outdoor air system to conditioned zones in the model. Radiant systems are comfortable with wider zone air temperature range. Use the CBE Thermal Comfort Tool or other method to set thermostat setpoint temperatures. This measure optionally removes existing HVAC systems (recommended). This measure is dependent on an ASHRAE climate zone to set insulation and design supply temperature levels, so make sure this is set in the site parameters of the model. Plant equipment options are an Air Source Heat Pump or a Boiler for hot water, and an Air Cooled Chiller or Water Cooled Chiller for chilled water. The Air Source Heat Pump object uses a user-defined plant component in EnergyPlus and may not be compatible with several reporting measures, including the *Enable Detailed Output for Each Node in a Loop* measure. If Water Cooled Chiller is selected, the measure will add a condenser loop with a variable speed cooling tower, and optionally enable water-side economizing when wet bulb conditions allow. By default, the slab system does not include carpet. Carpet greatly reduces the heat transfer capacity of the radiant system. If carpet is preferred, a ceiling-type slab and no lockout are recommended to avoid unmet hours. The measure includes several control parameters for radiant system operation. Use the defaults unless you have strong reasons to deviate from them. This measure runs a sizing run to set equipment efficiency values, so it may take up to a few minutes to run. This measure adds many EnergyManagementSystem objects to the model. **DO NOT** change design days after running this measure. Adding additional HVAC measures after applying this measure may break the model. Radiant systems are particularly limited in cooling capacity and the model may have many unmet hours as a result. To reduce unmet hours, use an expanded comfort range as mentioned above, remove carpet, reduce internal loads, reduce solar and envelope gains during peak times, or disable the lockout.' end |
#name ⇒ Object
human readable name
11 12 13 14 |
# File 'lib/measures/radiant_slab_with_doas/measure.rb', line 11 def name # Measure name should be the title case of the class name. return 'Radiant Slab with DOAS' end |
#run(model, runner, user_arguments) ⇒ Object
define what happens when the measure is run
155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 |
# File 'lib/measures/radiant_slab_with_doas/measure.rb', line 155 def run(model, runner, user_arguments) super(model, runner, user_arguments) # use the built-in error checking if !runner.validateUserArguments(arguments(model), user_arguments) return false end # assign user inputs remove_existing_hvac = runner.getBoolArgumentValue('remove_existing_hvac', user_arguments) heating_plant_type = runner.getStringArgumentValue('heating_plant_type', user_arguments) cooling_plant_type = runner.getStringArgumentValue('cooling_plant_type', user_arguments) waterside_economizer = runner.getStringArgumentValue('waterside_economizer', user_arguments) radiant_type = runner.getStringArgumentValue('radiant_type', user_arguments) include_carpet = runner.getBoolArgumentValue('include_carpet', user_arguments) control_strategy = runner.getStringArgumentValue('control_strategy', user_arguments) proportional_gain = runner.getDoubleArgumentValue('proportional_gain', user_arguments) switch_over_time = runner.getDoubleArgumentValue('switch_over_time', user_arguments) radiant_lockout = runner.getBoolArgumentValue('radiant_lockout', user_arguments) lockout_start_time = runner.getDoubleArgumentValue('lockout_start_time', user_arguments) lockout_end_time = runner.getDoubleArgumentValue('lockout_end_time', user_arguments) add_output_variables = runner.getBoolArgumentValue('add_output_variables', user_arguments) standards_template = runner.getStringArgumentValue('standards_template', user_arguments) # standard to access methods in openstudio-standards std = Standard.build(standards_template) # remove existing hvac systems if remove_existing_hvac runner.registerInfo('Removing existing HVAC systems from the model') if std.respond_to?('remove_HVAC') std.remove_HVAC(model) # OpenStuido 3.2.1 and earlierop use this, future versions will use snake_case method else std.remove_hvac(model) end end # exclude plenum zones, zones without thermostats, and zones with no floor area conditioned_zones = [] model.getThermalZones.each do |zone| next if OpenstudioStandards::ThermalZone.thermal_zone_plenum?(zone) next if !OpenstudioStandards::ThermalZone.thermal_zone_heated?(zone) && !OpenstudioStandards::ThermalZone.thermal_zone_cooled?(zone) conditioned_zones << zone end # make sure the model has conditioned zones if conditioned_zones.empty? runner.registerAsNotApplicable('No conditioned zones identified in model. Make sure thermostats are assigned to zones.') return false end # get the climate zone climate_zone_obj = model.getClimateZones.getClimateZone('ASHRAE', 2006) if climate_zone_obj.empty climate_zone_obj = model.getClimateZones.getClimateZone('ASHRAE', 2013) end if climate_zone_obj.empty || climate_zone_obj.value == '' runner.registerError('Please assign an ASHRAE climate zone to the model before running the measure.') return false else climate_zone = climate_zone_obj.value end # get the radiant hot water temperature based on the climate zone case climate_zone when '1' radiant_htg_dsgn_sup_wtr_temp_f = 90.0 when '2', '2A', '2B', 'CEC15' radiant_htg_dsgn_sup_wtr_temp_f = 100.0 when '3', '3A', '3B', '3C', 'CEC3', 'CEC4', 'CEC5', 'CEC6', 'CEC7', 'CEC8', 'CEC9', 'CEC10', 'CEC11', 'CEC12', 'CEC13', 'CEC14' radiant_htg_dsgn_sup_wtr_temp_f = 100.0 when '4', '4A', '4B', '4C', 'CEC1', 'CEC2' radiant_htg_dsgn_sup_wtr_temp_f = 100.0 when '5', '5A', '5B', '5C', 'CEC16' radiant_htg_dsgn_sup_wtr_temp_f = 110.0 when '6', '6A', '6B' radiant_htg_dsgn_sup_wtr_temp_f = 120.0 when '7', '8' radiant_htg_dsgn_sup_wtr_temp_f = 120.0 else # default to 4 radiant_htg_dsgn_sup_wtr_temp_f = 100.0 end runner.registerInitialCondition("This measure will add radiant systems to #{conditioned_zones.size} conditioned zones with a hot water loop served by a #{heating_plant_type} and chilled water loop served by a #{cooling_plant_type}.") runner.registerInfo("Based on model climate zone #{climate_zone}, using #{radiant_htg_dsgn_sup_wtr_temp_f}F heating supply water temperature.") # establish hot water and chilled water loops case heating_plant_type when 'Air Source Heat Pump' boiler_fuel_type = 'ASHP' when 'Boiler' boiler_fuel_type = 'NaturalGas' end hot_water_loop = std.model_add_hw_loop(model, boiler_fuel_type, dsgn_sup_wtr_temp: radiant_htg_dsgn_sup_wtr_temp_f, dsgn_sup_wtr_temp_delt: 10.0) case cooling_plant_type when 'Air Cooled Chiller' # make chilled water loop chilled_water_loop = std.model_add_chw_loop(model, chw_pumping_type: 'const_pri_var_sec', dsgn_sup_wtr_temp: 55.0, dsgn_sup_wtr_temp_delt: 5.0, chiller_cooling_type: 'AirCooled') when 'Water Cooled Chiller' # make condenser water loop fan_type = std.model_cw_loop_cooling_tower_fan_type(model) condenser_water_loop = std.model_add_cw_loop(model, cooling_tower_type: 'Open Cooling Tower', cooling_tower_fan_type: 'Propeller or Axial', cooling_tower_capacity_control: fan_type, number_of_cells_per_tower: 1, number_cooling_towers: 1) # make chilled water loop chilled_water_loop = std.model_add_chw_loop(model, chw_pumping_type: 'const_pri_var_sec', dsgn_sup_wtr_temp: 55.0, dsgn_sup_wtr_temp_delt: 5.0, chiller_cooling_type: 'WaterCooled', condenser_water_loop: condenser_water_loop, waterside_economizer: waterside_economizer) end # add radiant system to conditioned zones radiant_loops = std.model_add_low_temp_radiant(model, conditioned_zones, hot_water_loop, chilled_water_loop, radiant_type: radiant_type, include_carpet: include_carpet, control_strategy: control_strategy, proportional_gain: proportional_gain, switch_over_time: switch_over_time, radiant_lockout: radiant_lockout, radiant_lockout_start_time: lockout_start_time, radiant_lockout_end_time: lockout_end_time) # add DOAS system to conditioned zones std.model_add_doas(model, conditioned_zones) std.rename_air_loop_nodes(model) # set the heating and cooling sizing parameters std.model_apply_prm_sizing_parameters(model) runner.registerInfo("Adjusting HVAC equipment efficiencies and controls to follow template #{standards_template}.") # perform a sizing run if std.model_run_sizing_run(model, "#{Dir.pwd}/radiant_sizing_run") == false runner.registerError('Sizing run failed. See errors in sizing run directory of this measure') return false end # Apply the HVAC efficiency standard building_data = std.model_get_building_properties(model) std.model_apply_hvac_efficiency_standard(model, building_data['climate_zone']) # add output variables vars = [] if add_output_variables # site outdoor drybulb temperature vars << OpenStudio::Model::OutputVariable.new('Site Outdoor Air Drybulb Temperature', model) # zone hvac low temperature radiant system object variables vars << OpenStudio::Model::OutputVariable.new('Zone Radiant HVAC Cooling Energy', model) vars << OpenStudio::Model::OutputVariable.new('Zone Radiant HVAC Heating Energy', model) vars << OpenStudio::Model::OutputVariable.new('Zone Radiant HVAC Inlet Temperature', model) vars << OpenStudio::Model::OutputVariable.new('Zone Radiant HVAC Outlet Temperature', model) vars << OpenStudio::Model::OutputVariable.new('Zone Radiant HVAC Mass Flow Rate', model) # plant loop variables var = OpenStudio::Model::OutputVariable.new('System Node Mass Flow Rate', model) var.setKeyValue('Chilled Water Loop Supply Outlet Node') vars << var var = OpenStudio::Model::OutputVariable.new('System Node Mass Flow Rate', model) var.setKeyValue('Hot Water Loop Supply Outlet Node') vars << var var = OpenStudio::Model::OutputVariable.new('System Node Temperature', model) var.setKeyValue('Chilled Water Loop Supply Outlet Node') vars << var var = OpenStudio::Model::OutputVariable.new('System Node Temperature', model) var.setKeyValue('Hot Water Loop Supply Outlet Node') vars << var var = OpenStudio::Model::OutputVariable.new('System Node Setpoint Temperature', model) var.setKeyValue('Chilled Water Loop Supply Outlet Node') vars << var var = OpenStudio::Model::OutputVariable.new('System Node Setpoint Temperature', model) var.setKeyValue('Hot Water Loop Supply Outlet Node') vars << var conditioned_space_names = [] conditioned_zones.each do |zone| zone.spaces.each { |space| conditioned_space_names << space.name } end # radiant surface temperatures model.getSurfaces.each do |surface| next if radiant_type == 'floor' && surface.surfaceType != 'Floor' next if radiant_type == 'ceiling' && surface.surfaceType != 'RoofCeiling' next unless surface.space.is_initialized surface_space_name = surface.space.get.name.to_s next unless conditioned_space_names.include? surface_space_name var = OpenStudio::Model::OutputVariable.new('Surface Inside Face Temperature', model) var.setKeyValue(surface.name.to_s) vars << var end # set to timestep vars.each { |var| var.setReportingFrequency('Timestep') } end # runner register final condition runner.registerFinalCondition("This measure created #{model.getZoneHVACLowTempRadiantVarFlows.size} radiant #{radiant_type} objects.") return true end |