honeybee-openstudio 2.9.2 → 2.10.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -2,9 +2,9 @@
2
2
  "openapi": "3.0.2",
3
3
  "servers": [],
4
4
  "info": {
5
- "description": "This is the documentation for Honeybee energy simulation parameter schema.",
6
- "version": "1.36.0",
7
- "title": "Honeybee Energy Simulation Parameter Schema",
5
+ "description": "Honeybee simulation-parameter schema.",
6
+ "version": "1.39.12",
7
+ "title": "Honeybee Simulation Parameter Schema",
8
8
  "contact": {
9
9
  "name": "Ladybug Tools",
10
10
  "email": "info@ladybug.tools",
@@ -186,7 +186,6 @@
186
186
  "readOnly": true
187
187
  },
188
188
  "reporting_frequency": {
189
- "title": "Reporting Frequency",
190
189
  "default": "Hourly",
191
190
  "allOf": [
192
191
  {
@@ -327,7 +326,6 @@
327
326
  }
328
327
  },
329
328
  "start_day_of_week": {
330
- "title": "Start Day Of Week",
331
329
  "description": "Text for the day of the week on which the simulation starts.",
332
330
  "default": "Sunday",
333
331
  "allOf": [
@@ -456,7 +454,6 @@
456
454
  "readOnly": true
457
455
  },
458
456
  "solar_distribution": {
459
- "title": "Solar Distribution",
460
457
  "default": "FullExteriorWithReflections",
461
458
  "allOf": [
462
459
  {
@@ -465,7 +462,6 @@
465
462
  ]
466
463
  },
467
464
  "calculation_method": {
468
- "title": "Calculation Method",
469
465
  "description": "Text noting whether CPU-based polygon clipping method orGPU-based pixel counting method should be used. For low numbers of shadingsurfaces (less than ~200), PolygonClipping requires less runtime thanPixelCounting. However, PixelCounting runtime scales significantlybetter at higher numbers of shading surfaces. PixelCounting also hasno limitations related to zone concavity when used with any\u201cFullInterior\u201d solar distribution options.",
470
466
  "default": "PolygonClipping",
471
467
  "allOf": [
@@ -475,7 +471,6 @@
475
471
  ]
476
472
  },
477
473
  "calculation_update_method": {
478
- "title": "Calculation Update Method",
479
474
  "description": "Text describing how often the solar and shading calculations are updated with respect to the flow of time in the simulation.",
480
475
  "default": "Periodic",
481
476
  "allOf": [
@@ -515,7 +510,6 @@
515
510
  "Wednesday",
516
511
  "Thursday",
517
512
  "Friday",
518
- "Saturday",
519
513
  "Holiday",
520
514
  "CustomDay1",
521
515
  "CustomDay2"
@@ -573,12 +567,7 @@
573
567
  "type": "object",
574
568
  "properties": {
575
569
  "humidity_type": {
576
- "title": "Humidity Type",
577
- "allOf": [
578
- {
579
- "$ref": "#/components/schemas/HumidityTypes"
580
- }
581
- ]
570
+ "$ref": "#/components/schemas/HumidityTypes"
582
571
  },
583
572
  "humidity_value": {
584
573
  "title": "Humidity Value",
@@ -766,12 +755,7 @@
766
755
  "type": "string"
767
756
  },
768
757
  "day_type": {
769
- "title": "Day Type",
770
- "allOf": [
771
- {
772
- "$ref": "#/components/schemas/DesignDayTypes"
773
- }
774
- ]
758
+ "$ref": "#/components/schemas/DesignDayTypes"
775
759
  },
776
760
  "dry_bulb_condition": {
777
761
  "title": "Dry Bulb Condition",
@@ -956,7 +940,6 @@
956
940
  "format": "double"
957
941
  },
958
942
  "terrain_type": {
959
- "title": "Terrain Type",
960
943
  "description": "Text for the terrain in which the model sits. This is used to determine the wind profile over the height of the rooms.",
961
944
  "default": "City",
962
945
  "allOf": [
@@ -0,0 +1,42 @@
1
+ # *******************************************************************************
2
+ # Honeybee OpenStudio Gem, Copyright (c) 2020, Alliance for Sustainable
3
+ # Energy, LLC, Ladybug Tools LLC and other contributors. All rights reserved.
4
+ #
5
+ # Redistribution and use in source and binary forms, with or without
6
+ # modification, are permitted provided that the following conditions are met:
7
+ #
8
+ # (1) Redistributions of source code must retain the above copyright notice,
9
+ # this list of conditions and the following disclaimer.
10
+ #
11
+ # (2) Redistributions in binary form must reproduce the above copyright notice,
12
+ # this list of conditions and the following disclaimer in the documentation
13
+ # and/or other materials provided with the distribution.
14
+ #
15
+ # (3) Neither the name of the copyright holder nor the names of any contributors
16
+ # may be used to endorse or promote products derived from this software without
17
+ # specific prior written permission from the respective party.
18
+ #
19
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND ANY CONTRIBUTORS
20
+ # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21
+ # THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22
+ # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S), ANY CONTRIBUTORS, THE
23
+ # UNITED STATES GOVERNMENT, OR THE UNITED STATES DEPARTMENT OF ENERGY, NOR ANY OF
24
+ # THEIR EMPLOYEES, BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25
+ # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
26
+ # OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27
+ # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
28
+ # STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29
+ # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
+ # *******************************************************************************
31
+
32
+ require 'honeybee/model_object'
33
+
34
+ module Honeybee
35
+ class ServiceHotWaterAbridged < ModelObject
36
+
37
+ def defaults
38
+ @@schema[:components][:schemas][:ServiceHotWaterAbridged][:properties]
39
+ end
40
+
41
+ end #ServiceHotWaterAbridged
42
+ end #Honeybee
@@ -72,6 +72,7 @@ require 'to_openstudio/load/people'
72
72
  require 'to_openstudio/load/lighting'
73
73
  require 'to_openstudio/load/electric_equipment'
74
74
  require 'to_openstudio/load/gas_equipment'
75
+ require 'to_openstudio/load/service_hot_water'
75
76
  require 'to_openstudio/load/infiltration'
76
77
  require 'to_openstudio/load/ventilation'
77
78
  require 'to_openstudio/load/setpoint_thermostat'
@@ -269,6 +269,13 @@ module Honeybee
269
269
  os_custom_gas_equipment.setSpaceType(unique_program) # assign the new load definition
270
270
  end
271
271
 
272
+ # assign service hot water if it exists
273
+ if @hash[:properties][:energy][:service_hot_water]
274
+ shw_space = ServiceHotWaterAbridged.new(@hash[:properties][:energy][:service_hot_water])
275
+ os_shw_space = shw_space.to_openstudio(openstudio_model, os_space)
276
+ $shw_for_plant = shw_space
277
+ end
278
+
272
279
  # assign infiltration if it exists
273
280
  if @hash[:properties][:energy][:infiltration] && $use_simple_vent # only use infiltration with simple ventilation
274
281
  unique_program = get_unique_space_type(openstudio_model, os_space)
@@ -37,7 +37,7 @@ module Honeybee
37
37
  class ElectricEquipmentAbridged
38
38
 
39
39
  def find_existing_openstudio_object(openstudio_model)
40
- model_electric_equipment = openstudio_model.getElectricEquipmentDefinitionByName(@hash[:identifier])
40
+ model_electric_equipment = openstudio_model.getElectricEquipmentByName(@hash[:identifier])
41
41
  return model_electric_equipment.get unless model_electric_equipment.empty?
42
42
  nil
43
43
  end
@@ -37,7 +37,7 @@ module Honeybee
37
37
  class GasEquipmentAbridged
38
38
 
39
39
  def find_existing_openstudio_object(openstudio_model)
40
- model_gas_equipment = openstudio_model.getGasEquipmentDefinitionByName(@hash[:identifier])
40
+ model_gas_equipment = openstudio_model.getGasEquipmentByName(@hash[:identifier])
41
41
  return model_gas_equipment.get unless model_gas_equipment.empty?
42
42
  nil
43
43
  end
@@ -37,7 +37,7 @@ module Honeybee
37
37
  class LightingAbridged
38
38
 
39
39
  def find_existing_openstudio_object(openstudio_model)
40
- model_lights = openstudio_model.getLightsDefinitionByName(@hash[:identifier])
40
+ model_lights = openstudio_model.getLightsByName(@hash[:identifier])
41
41
  return model_lights.get unless model_lights.empty?
42
42
  nil
43
43
  end
@@ -37,7 +37,7 @@ module Honeybee
37
37
  class PeopleAbridged
38
38
 
39
39
  def find_existing_openstudio_object(openstudio_model)
40
- model_people = openstudio_model.getPeopleDefinitionByName(@hash[:identifier])
40
+ model_people = openstudio_model.getPeopleByName(@hash[:identifier])
41
41
  return model_people.get unless model_people.empty?
42
42
  nil
43
43
  end
@@ -0,0 +1,170 @@
1
+ # *******************************************************************************
2
+ # Honeybee OpenStudio Gem, Copyright (c) 2020, Alliance for Sustainable
3
+ # Energy, LLC, Ladybug Tools LLC and other contributors. All rights reserved.
4
+ #
5
+ # Redistribution and use in source and binary forms, with or without
6
+ # modification, are permitted provided that the following conditions are met:
7
+ #
8
+ # (1) Redistributions of source code must retain the above copyright notice,
9
+ # this list of conditions and the following disclaimer.
10
+ #
11
+ # (2) Redistributions in binary form must reproduce the above copyright notice,
12
+ # this list of conditions and the following disclaimer in the documentation
13
+ # and/or other materials provided with the distribution.
14
+ #
15
+ # (3) Neither the name of the copyright holder nor the names of any contributors
16
+ # may be used to endorse or promote products derived from this software without
17
+ # specific prior written permission from the respective party.
18
+ #
19
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND ANY CONTRIBUTORS
20
+ # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21
+ # THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22
+ # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S), ANY CONTRIBUTORS, THE
23
+ # UNITED STATES GOVERNMENT, OR THE UNITED STATES DEPARTMENT OF ENERGY, NOR ANY OF
24
+ # THEIR EMPLOYEES, BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25
+ # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
26
+ # OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27
+ # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
28
+ # STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29
+ # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
+ # *******************************************************************************
31
+
32
+ require 'honeybee/load/service_hot_water'
33
+
34
+ require 'to_openstudio/model_object'
35
+
36
+ module Honeybee
37
+ class ServiceHotWaterAbridged
38
+ @@max_target_temp = 60
39
+ @@max_temp_schedule = nil
40
+ @@shw_connections = []
41
+
42
+ def find_existing_openstudio_object(openstudio_model)
43
+ model_shw = openstudio_model.getWaterUseEquipmentByName(@hash[:identifier])
44
+ return model_shw.get unless model_shw.empty?
45
+ nil
46
+ end
47
+
48
+ def add_district_hot_water_plant(openstudio_model)
49
+ # add a defaul district hot water system to supply all of the shw_connections
50
+ # create the plant loop
51
+ hot_water_plant = OpenStudio::Model::PlantLoop.new(openstudio_model)
52
+ hot_water_plant.setName('Service Hot Water Loop')
53
+ hot_water_plant.setMaximumLoopTemperature(@@max_target_temp)
54
+ hot_water_plant.setMinimumLoopTemperature(10) # default value in C from OpenStudio Application
55
+
56
+ # edit the sizing information to be for a hot water loop
57
+ loop_sizing = hot_water_plant.sizingPlant()
58
+ loop_sizing.setLoopType('Heating')
59
+ loop_sizing.setDesignLoopExitTemperature(@@max_target_temp)
60
+ loop_sizing.setLoopDesignTemperatureDifference(5) # default value in C from OpenStudio Application
61
+
62
+ # add a setpoint manager for the loop
63
+ hot_sch = @@max_temp_schedule
64
+ if @@max_temp_schedule.nil?
65
+ hot_sch_name = @@max_target_temp.to_s + 'C Hot Water'
66
+ hot_sch = create_constant_schedule(openstudio_model, hot_sch_name, @@max_target_temp)
67
+ end
68
+ sp_manager = OpenStudio::Model::SetpointManagerScheduled.new(openstudio_model, hot_sch)
69
+ sp_manager.addToNode(hot_water_plant.supplyOutletNode())
70
+
71
+ # add a constant speed pump for the loop
72
+ hot_water_pump = OpenStudio::Model::PumpConstantSpeed.new(openstudio_model)
73
+ hot_water_pump.setName('Service Hot Water Pump')
74
+ hot_water_pump.setRatedPumpHead(29891) # default value in Pa from OpenStudio Application
75
+ hot_water_pump.setMotorEfficiency(0.9) # default value from OpenStudio Application
76
+ hot_water_pump.addToNode(hot_water_plant.supplyInletNode())
77
+
78
+ # add a district heating system to supply the heat for the loop
79
+ district_hw = OpenStudio::Model::DistrictHeating.new(openstudio_model)
80
+ district_hw.setName('Service Hot Water District Heat')
81
+ district_hw.setNominalCapacity(1000000)
82
+ hot_water_plant.addSupplyBranchForComponent(district_hw)
83
+
84
+ # add all of the water use connections to the loop
85
+ @@shw_connections.each do |shw_conn|
86
+ hot_water_plant.addDemandBranchForComponent(shw_conn)
87
+ end
88
+
89
+ hot_water_plant
90
+ end
91
+
92
+ def to_openstudio(openstudio_model, os_space)
93
+ # create water use equipment + connection and set identifier
94
+ os_shw_def = OpenStudio::Model::WaterUseEquipmentDefinition.new(openstudio_model)
95
+ os_shw = OpenStudio::Model::WaterUseEquipment.new(os_shw_def)
96
+ unique_id = @hash[:identifier] + '..' + os_space.nameString
97
+ os_shw_def.setName(unique_id)
98
+ os_shw.setName(unique_id)
99
+
100
+ # assign the flow of water
101
+ total_flow = (@hash[:flow_per_area].to_f * os_space.floorArea) / 3600000
102
+ os_shw_def.setPeakFlowRate(total_flow)
103
+ os_shw_def.setEndUseSubcategory('General')
104
+
105
+ # assign schedule
106
+ shw_schedule = openstudio_model.getScheduleByName(@hash[:schedule])
107
+ unless shw_schedule.empty?
108
+ shw_schedule_object = shw_schedule.get
109
+ os_shw.setFlowRateFractionSchedule(shw_schedule_object)
110
+ end
111
+
112
+ # assign the hot water temperature
113
+ target_temp = defaults[:target_temperature][:default]
114
+ if @hash[:target_temperature]
115
+ target_temp = @hash[:target_temperature]
116
+ end
117
+ target_sch_name = target_temp.to_s + 'C Hot Water'
118
+ target_water_sch = create_constant_schedule(openstudio_model, target_sch_name, target_temp)
119
+ os_shw_def.setTargetTemperatureSchedule(target_water_sch)
120
+
121
+ # create the hot water connection with same temperature as target temperature
122
+ os_shw_conn = OpenStudio::Model::WaterUseConnections.new(openstudio_model)
123
+ os_shw_conn.addWaterUseEquipment(os_shw)
124
+ os_shw_conn.setHotWaterSupplyTemperatureSchedule(target_water_sch)
125
+ if target_temp > @@max_target_temp
126
+ @@max_target_temp = target_temp
127
+ @@max_temp_schedule = target_water_sch
128
+ end
129
+ @@shw_connections << os_shw_conn
130
+
131
+ # assign sensible fraction if it exists
132
+ sens_fract = defaults[:sensible_fraction][:default]
133
+ if @hash[:sensible_fraction]
134
+ sens_fract = @hash[:sensible_fraction]
135
+ end
136
+ sens_sch_name = sens_fract.to_s + ' Hot Water Sensible Fraction'
137
+ sens_fract_sch = create_constant_schedule(openstudio_model, sens_sch_name, sens_fract)
138
+ os_shw_def.setSensibleFractionSchedule(sens_fract_sch)
139
+
140
+ # assign latent fraction if it exists
141
+ lat_fract = defaults[:latent_fraction][:default]
142
+ if @hash[:latent_fraction]
143
+ lat_fract = @hash[:latent_fraction]
144
+ end
145
+ lat_sch_name = lat_fract.to_s + ' Hot Water Latent Fraction'
146
+ lat_fract_sch = create_constant_schedule(openstudio_model, lat_sch_name, lat_fract)
147
+ os_shw_def.setLatentFractionSchedule(lat_fract_sch)
148
+
149
+ # assign the service hot water to the space
150
+ os_shw.setSpace(os_space)
151
+
152
+ os_shw
153
+ end
154
+
155
+ private
156
+
157
+ def create_constant_schedule(openstudio_model, schedule_name, value)
158
+ # check if a constant schedule already exists and, if not, create it
159
+ exist_schedule = openstudio_model.getScheduleByName(schedule_name)
160
+ if exist_schedule.empty? # create the schedule
161
+ os_sch_ruleset = OpenStudio::Model::ScheduleRuleset.new(openstudio_model, value)
162
+ os_sch_ruleset.setName(schedule_name)
163
+ else
164
+ os_sch_ruleset = exist_schedule.get
165
+ end
166
+ os_sch_ruleset
167
+ end
168
+
169
+ end #ServiceHotWaterAbridged
170
+ end #Honeybee
@@ -86,8 +86,10 @@ module Honeybee
86
86
  $gas_gap_hash = Hash.new # hash to track gas gaps in case they are split by shades
87
87
  $air_boundary_hash = Hash.new # hash to track any air boundary constructions
88
88
  $window_shade_hash = Hash.new # hash to track any window constructions with shade
89
+ $programtype_shw_hash = Hash.new # hash to track ServiceHotWater objects
89
90
  $programtype_setpoint_hash = Hash.new # hash to track Setpoint objects
90
91
  $interior_afn_srf_hash = Hash.new # track whether an adjacent surface is already in the AFN
92
+ $shw_for_plant = nil # track whether a hot water plant is needed
91
93
 
92
94
  # create all of the non-geometric model elements
93
95
  if log_report # schedules are used by all other objects and come first
@@ -151,6 +153,7 @@ module Honeybee
151
153
  puts 'Translating HVAC Systems'
152
154
  end
153
155
  create_hvacs
156
+ create_hot_water_plant
154
157
 
155
158
  if log_report
156
159
  puts 'Translating Context Shade Geometry'
@@ -361,6 +364,17 @@ module Honeybee
361
364
  room_object = Room.new(room)
362
365
  openstudio_room = room_object.to_openstudio(@openstudio_model)
363
366
 
367
+ # for rooms with hot water objects definied in the ProgramType, make a new WaterUse:Equipment
368
+ if room[:properties][:energy][:program_type] && !room[:properties][:energy][:service_hot_water]
369
+ program_type_id = room[:properties][:energy][:program_type]
370
+ shw_hash = $programtype_shw_hash[program_type_id]
371
+ unless shw_hash.nil?
372
+ shw_object = ServiceHotWaterAbridged.new(shw_hash)
373
+ openstudio_shw = shw_object.to_openstudio(@openstudio_model, openstudio_room)
374
+ $shw_for_plant = shw_object
375
+ end
376
+ end
377
+
364
378
  # for rooms with setpoint objects definied in the ProgramType, make a new thermostat
365
379
  if room[:properties][:energy][:program_type] && !room[:properties][:energy][:setpoint]
366
380
  thermal_zone = openstudio_room.thermalZone()
@@ -368,7 +382,7 @@ module Honeybee
368
382
  thermal_zone_object = thermal_zone.get
369
383
  program_type_id = room[:properties][:energy][:program_type]
370
384
  setpoint_hash = $programtype_setpoint_hash[program_type_id]
371
- if not setpoint_hash.nil? # program type has no setpoint
385
+ unless setpoint_hash.nil? # program type has no setpoint
372
386
  thermostat_object = SetpointThermostat.new(setpoint_hash)
373
387
  openstudio_thermostat = thermostat_object.to_openstudio(@openstudio_model)
374
388
  thermal_zone_object.setThermostatSetpointDualSetpoint(openstudio_thermostat)
@@ -467,6 +481,13 @@ module Honeybee
467
481
  end
468
482
  end
469
483
 
484
+ def create_hot_water_plant
485
+ # create a hot water plant if there's any service hot water in the model
486
+ unless $shw_for_plant.nil?
487
+ $shw_for_plant.add_district_hot_water_plant(@openstudio_model)
488
+ end
489
+ end
490
+
470
491
  def create_orphaned_shades
471
492
  if @hash[:orphaned_shades]
472
493
  shading_surface_group = OpenStudio::Model::ShadingSurfaceGroup.new(@openstudio_model)
@@ -75,6 +75,11 @@ module Honeybee
75
75
  os_gas_equipment.setSpaceType(os_space_type)
76
76
  end
77
77
 
78
+ # add hot water from to a global hash that will be used to assign them to rooms
79
+ if @hash[:service_hot_water]
80
+ $programtype_shw_hash[@hash[:identifier]] = @hash[:service_hot_water]
81
+ end
82
+
78
83
  # assign infiltration
79
84
  if @hash[:infiltration] && $use_simple_vent # only use infiltration with simple ventilation
80
85
  infiltration = InfiltrationAbridged.new(@hash[:infiltration])
@@ -237,6 +237,10 @@ module Honeybee
237
237
  if @hash[:terrain_type]
238
238
  os_site.setTerrain(@hash[:terrain_type])
239
239
  end
240
+
241
+ # ensure water mains temperatures are written
242
+ os_water_mains = @openstudio_model.getSiteWaterMainsTemperature
243
+ os_water_mains.setCalculationMethod('CorrelationFromWeatherFile')
240
244
  end
241
245
 
242
246
  end #SimulationParameter