lib/from_honeybee/model.rb in honeybee-openstudio-1.8.1 vs lib/from_honeybee/model.rb in honeybee-openstudio-1.8.2
- old
+ new
@@ -1,434 +1,434 @@
-# *******************************************************************************
-# Honeybee OpenStudio Gem, Copyright (c) 2020, Alliance for Sustainable
-# Energy, LLC, Ladybug Tools LLC and other contributors. All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are met:
-#
-# (1) Redistributions of source code must retain the above copyright notice,
-# this list of conditions and the following disclaimer.
-#
-# (2) Redistributions in binary form must reproduce the above copyright notice,
-# this list of conditions and the following disclaimer in the documentation
-# and/or other materials provided with the distribution.
-#
-# (3) Neither the name of the copyright holder nor the names of any contributors
-# may be used to endorse or promote products derived from this software without
-# specific prior written permission from the respective party.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND ANY CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S), ANY CONTRIBUTORS, THE
-# UNITED STATES GOVERNMENT, OR THE UNITED STATES DEPARTMENT OF ENERGY, NOR ANY OF
-# THEIR EMPLOYEES, BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
-# OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
-# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-# *******************************************************************************
-
-# import the core objects from which everything inherits
-require 'from_honeybee/extension'
-require 'from_honeybee/model_object'
-
-# import the compound objects that house the other objects
-require 'from_honeybee/construction_set'
-require 'from_honeybee/program_type'
-
-# import the geometry objects
-require 'from_honeybee/geometry/shade'
-require 'from_honeybee/geometry/door'
-require 'from_honeybee/geometry/aperture'
-require 'from_honeybee/geometry/face'
-require 'from_honeybee/geometry/room'
-
-# import the HVAC objects
-require 'from_honeybee/hvac/ideal_air'
-
-# import the construction objects
-require 'from_honeybee/construction/opaque'
-require 'from_honeybee/construction/window'
-require 'from_honeybee/construction/shade'
-require 'from_honeybee/construction/air'
-
-# import the material objects
-require 'from_honeybee/material/opaque'
-require 'from_honeybee/material/opaque_no_mass'
-require 'from_honeybee/material/window_gas'
-require 'from_honeybee/material/window_gas_mixture'
-require 'from_honeybee/material/window_gas_custom'
-require 'from_honeybee/material/window_blind'
-require 'from_honeybee/material/window_glazing'
-require 'from_honeybee/material/window_shade'
-require 'from_honeybee/material/window_simpleglazsys'
-
-# import the schedule objects
-require 'from_honeybee/schedule/type_limit'
-require 'from_honeybee/schedule/fixed_interval'
-require 'from_honeybee/schedule/ruleset'
-
-# import the load objects
-require 'from_honeybee/load/setpoint_thermostat'
-require 'from_honeybee/load/setpoint_humidistat'
-
-require 'openstudio'
-
-
-module FromHoneybee
- class Model
- attr_reader :errors, :warnings
-
- # Read Ladybug Energy Model JSON from disk
- def self.read_from_disk(file)
- hash = nil
- File.open(File.join(file), 'r') do |f|
- hash = JSON.parse(f.read, symbolize_names: true)
- end
- Model.new(hash)
- end
-
- # Load ModelObject from symbolized hash
- def initialize(hash)
- # initialize class variable @@extension only once
- @@extension ||= Extension.new
- @@schema ||= @@extension.schema
-
- @hash = hash
- @type = @hash[:type]
- raise 'Unknown model type' if @type.nil?
- raise "Incorrect model type '#{@type}'" unless @type == 'Model'
-
- end
-
- # check if the model is valid
- def valid?
- if Gem.loaded_specs.has_key?("json-schema")
- return validation_errors.empty?
- else
- return true
- end
- end
-
- # return detailed model validation errors
- def validation_errors
- if Gem.loaded_specs.has_key?("json-schema")
- require 'json-schema'
- JSON::Validator.fully_validate(@@schema, @hash)
- end
- end
-
- def defaults
- @@schema[:components][:schemas][:ModelEnergyProperties][:properties]
- end
-
- # convert to openstudio model, clears errors and warnings
- def to_openstudio_model(openstudio_model=nil, log_report=true)
- @errors = []
- @warnings = []
-
- if log_report
- puts 'Starting Model translation from Honeybee to OpenStudio'
- end
-
- @openstudio_model = if openstudio_model
- openstudio_model
- else
- OpenStudio::Model::Model.new
- end
-
- # create all openstudio objects in the model
- create_openstudio_objects(log_report)
-
- if log_report
- puts 'Done with Model translation!'
- end
-
- @openstudio_model
- end
-
- private
-
- # create OpenStudio objects in the OpenStudio model
- def create_openstudio_objects(log_report=true)
- # assign a standards building type so that David's measures can run
- building = @openstudio_model.getBuilding
- building.setStandardsBuildingType('MediumOffice')
-
- # create all of the non-geometric model elements
- if log_report
- puts 'Translating Materials'
- end
- create_materials
-
- if log_report
- puts 'Translating Constructions'
- end
- create_constructions
-
- if log_report
- puts 'Translating ConstructionSets'
- end
- create_construction_set
- create_global_construction_set
-
- if log_report
- puts 'Translating Schedules'
- end
- create_schedule_type_limits
- create_schedules
-
- if log_report
- puts 'Translating ProgramTypes'
- end
- create_program_types
-
- # create all of the model geometry
- if log_report
- puts 'Translating Room Geometry'
- end
- create_rooms
-
- if log_report
- puts 'Translating Context Shade Geometry'
- end
- create_orphaned_shades
- create_orphaned_faces
- create_orphaned_apertures
- create_orphaned_doors
-
- # create the hvac systems
- if log_report
- puts 'Translating HVAC Systems'
- end
- create_hvacs
- end
-
- def create_materials
- @hash[:properties][:energy][:materials].each do |material|
- material_type = material[:type]
-
- case material_type
- when 'EnergyMaterial'
- material_object = EnergyMaterial.new(material)
- when 'EnergyMaterialNoMass'
- material_object = EnergyMaterialNoMass.new(material)
- when 'EnergyWindowMaterialGas'
- material_object = EnergyWindowMaterialGas.new(material)
- when 'EnergyWindowMaterialGasCustom'
- material_object = EnergyWindowMaterialGasCustom.new(material)
- when 'EnergyWindowMaterialSimpleGlazSys'
- material_object = EnergyWindowMaterialSimpleGlazSys.new(material)
- when 'EnergyWindowMaterialBlind'
- material_object = EnergyWindowMaterialBlind.new(material)
- when 'EnergyWindowMaterialGlazing'
- material_object = EnergyWindowMaterialGlazing.new(material)
- when 'EnergyWindowMaterialShade'
- material_object = EnergyWindowMaterialShade.new(material)
- else
- raise "Unknown material type #{material_type}"
- end
- material_object.to_openstudio(@openstudio_model)
- end
- end
-
- def create_constructions
- $air_boundary_hash = Hash.new # hash to track any air boundary constructions
-
- @hash[:properties][:energy][:constructions].each do |construction|
- identifier = construction[:identifier]
- construction_type = construction[:type]
-
- case construction_type
- when 'OpaqueConstructionAbridged'
- construction_object = OpaqueConstructionAbridged.new(construction)
- when 'WindowConstructionAbridged'
- construction_object = WindowConstructionAbridged.new(construction)
- when 'ShadeConstruction'
- construction_object = ShadeConstruction.new(construction)
- when 'AirBoundaryConstructionAbridged'
- construction_object = AirBoundaryConstructionAbridged.new(construction)
- $air_boundary_hash[construction[:identifier]] = construction
- else
- raise "Unknown construction type #{construction_type}."
- end
- construction_object.to_openstudio(@openstudio_model)
- end
- end
-
- def create_construction_set
- if @hash[:properties][:energy][:construction_sets]
- @hash[:properties][:energy][:construction_sets].each do |construction_set|
- construction_set_object = ConstructionSetAbridged.new(construction_set)
- construction_set_object.to_openstudio(@openstudio_model)
- end
- end
- end
-
- def create_global_construction_set
- if @hash[:properties][:energy][:global_construction_set]
- construction_id = @hash[:properties][:energy][:global_construction_set]
- construction = @openstudio_model.getDefaultConstructionSetByName(construction_id)
- unless construction.empty?
- openstudio_construction = construction.get
- end
- @openstudio_model.getBuilding.setDefaultConstructionSet(openstudio_construction)
- end
- end
-
- def create_schedule_type_limits
- if @hash[:properties][:energy][:schedule_type_limits]
- @hash[:properties][:energy][:schedule_type_limits].each do |schedule_type_limit|
- schedule_type_limit_object = ScheduleTypeLimit.new(schedule_type_limit)
- schedule_type_limit_object.to_openstudio(@openstudio_model)
- end
- end
- end
-
- def create_schedules
- if @hash[:properties][:energy][:schedules]
- @hash[:properties][:energy][:schedules].each do |schedule|
- schedule_type = schedule[:type]
-
- case schedule_type
- when 'ScheduleRulesetAbridged'
- schedule_object = ScheduleRulesetAbridged.new(schedule)
- when 'ScheduleFixedIntervalAbridged'
- schedule_object = ScheduleFixedIntervalAbridged.new(schedule)
- else
- raise("Unknown schedule type #{schedule_type}.")
- end
- schedule_object.to_openstudio(@openstudio_model)
-
- end
- end
- end
-
- def create_program_types
- if @hash[:properties][:energy][:program_types]
- $programtype_setpoint_hash = Hash.new # hash to track Setpoint objects
- @hash[:properties][:energy][:program_types].each do |space_type|
- space_type_object = ProgramTypeAbridged.new(space_type)
- space_type_object.to_openstudio(@openstudio_model)
- end
- end
- end
-
- def create_rooms
- if @hash[:rooms]
- $air_mxing_array = [] # list to track any air mixing between Rooms
-
- @hash[:rooms].each do |room|
- room_object = Room.new(room)
- openstudio_room = room_object.to_openstudio(@openstudio_model)
-
- # for rooms with setpoint objects definied in the ProgramType, make a new thermostat
- if room[:properties][:energy][:program_type] && !room[:properties][:energy][:setpoint]
- thermal_zone = openstudio_room.thermalZone()
- unless thermal_zone.empty?
- thermal_zone_object = thermal_zone.get
- program_type_id = room[:properties][:energy][:program_type]
- setpoint_hash = $programtype_setpoint_hash[program_type_id]
- if not setpoint_hash.nil? # program type has no setpoint
- thermostat_object = SetpointThermostat.new(setpoint_hash)
- openstudio_thermostat = thermostat_object.to_openstudio(@openstudio_model)
- thermal_zone_object.setThermostatSetpointDualSetpoint(openstudio_thermostat)
- if setpoint_hash[:humidifying_schedule] or setpoint_hash[:dehumidifying_schedule]
- humidistat_object = ZoneControlHumidistat.new(setpoint_hash)
- openstudio_humidistat = humidistat_object.to_openstudio(@openstudio_model)
- thermal_zone_object.setZoneControlHumidistat(openstudio_humidistat)
- end
- end
- end
- end
- end
-
- # Create mixing objects between Rooms
- $air_mxing_array.each do |air_mix_props|
- zone_mixing = OpenStudio::Model::ZoneMixing.new(air_mix_props[0])
- zone_mixing.setDesignFlowRate(air_mix_props[1])
- flow_sch_ref = @openstudio_model.getScheduleByName(air_mix_props[2])
- unless flow_sch_ref.empty?
- flow_sched = flow_sch_ref.get
- zone_mixing.setSchedule(flow_sched)
- end
- source_zone_ref = @openstudio_model.getThermalZoneByName(air_mix_props[3])
- unless source_zone_ref.empty?
- source_zone = source_zone_ref.get
- zone_mixing.setSourceZone(source_zone)
- end
- end
- end
- end
-
-
- def create_orphaned_shades
- if @hash[:orphaned_shades]
- shading_surface_group = OpenStudio::Model::ShadingSurfaceGroup.new(@openstudio_model)
- shading_surface_group.setShadingSurfaceType('Building')
- @hash[:orphaned_shades].each do |shade|
- shade_object = Shade.new(shade)
- openstudio_shade = shade_object.to_openstudio(@openstudio_model)
- openstudio_shade.setShadingSurfaceGroup(shading_surface_group)
- end
- end
- end
-
- def create_orphaned_faces
- if @hash[:orphaned_faces]
- raise "Orphaned Faces are not translatable to OpenStudio."
- end
- end
-
- def create_orphaned_apertures
- if @hash[:orphaned_apertures]
- raise "Orphaned Apertures are not translatable to OpenStudio."
- end
- end
-
- def create_orphaned_doors
- if @hash[:orphaned_doors]
- raise "Orphaned Doors are not translatable to OpenStudio."
- end
- end
-
- def create_hvacs
- if @hash[:properties][:energy][:hvacs]
- # gather all of the hashes of the HVACs
- hvac_hashes = Hash.new
- @hash[:properties][:energy][:hvacs].each do |hvac|
- hvac_hashes[hvac[:identifier]] = hvac
- hvac_hashes[hvac[:identifier]]['rooms'] = []
- end
- # loop through the rooms and trach which are assigned to each HVAC
- if @hash[:rooms]
- @hash[:rooms].each do |room|
- if room[:properties][:energy][:hvac]
- hvac_hashes[room[:properties][:energy][:hvac]]['rooms'] << room[:identifier]
- end
- end
- end
-
- hvac_hashes.each_value do |hvac|
- system_type = hvac[:type]
- case system_type
- when 'IdealAirSystemAbridged'
- ideal_air_system = IdealAirSystemAbridged.new(hvac)
- os_ideal_air_system = ideal_air_system.to_openstudio(@openstudio_model)
- hvac['rooms'].each do |room_id|
- zone_get = @openstudio_model.getThermalZoneByName(room_id)
- unless zone_get.empty?
- os_thermal_zone = zone_get.get
- os_ideal_air_system.addToThermalZone(os_thermal_zone)
- end
- end
- end
- end
- end
- end
-
- #TODO: create runlog for errors.
-
- end # Model
-end # FromHoneybee
+# *******************************************************************************
+# Honeybee OpenStudio Gem, Copyright (c) 2020, Alliance for Sustainable
+# Energy, LLC, Ladybug Tools LLC and other contributors. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# (1) Redistributions of source code must retain the above copyright notice,
+# this list of conditions and the following disclaimer.
+#
+# (2) Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+#
+# (3) Neither the name of the copyright holder nor the names of any contributors
+# may be used to endorse or promote products derived from this software without
+# specific prior written permission from the respective party.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND ANY CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S), ANY CONTRIBUTORS, THE
+# UNITED STATES GOVERNMENT, OR THE UNITED STATES DEPARTMENT OF ENERGY, NOR ANY OF
+# THEIR EMPLOYEES, BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+# OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+# *******************************************************************************
+
+# import the core objects from which everything inherits
+require 'from_honeybee/extension'
+require 'from_honeybee/model_object'
+
+# import the compound objects that house the other objects
+require 'from_honeybee/construction_set'
+require 'from_honeybee/program_type'
+
+# import the geometry objects
+require 'from_honeybee/geometry/shade'
+require 'from_honeybee/geometry/door'
+require 'from_honeybee/geometry/aperture'
+require 'from_honeybee/geometry/face'
+require 'from_honeybee/geometry/room'
+
+# import the HVAC objects
+require 'from_honeybee/hvac/ideal_air'
+
+# import the construction objects
+require 'from_honeybee/construction/opaque'
+require 'from_honeybee/construction/window'
+require 'from_honeybee/construction/shade'
+require 'from_honeybee/construction/air'
+
+# import the material objects
+require 'from_honeybee/material/opaque'
+require 'from_honeybee/material/opaque_no_mass'
+require 'from_honeybee/material/window_gas'
+require 'from_honeybee/material/window_gas_mixture'
+require 'from_honeybee/material/window_gas_custom'
+require 'from_honeybee/material/window_blind'
+require 'from_honeybee/material/window_glazing'
+require 'from_honeybee/material/window_shade'
+require 'from_honeybee/material/window_simpleglazsys'
+
+# import the schedule objects
+require 'from_honeybee/schedule/type_limit'
+require 'from_honeybee/schedule/fixed_interval'
+require 'from_honeybee/schedule/ruleset'
+
+# import the load objects
+require 'from_honeybee/load/setpoint_thermostat'
+require 'from_honeybee/load/setpoint_humidistat'
+
+require 'openstudio'
+
+
+module FromHoneybee
+ class Model
+ attr_reader :errors, :warnings
+
+ # Read Ladybug Energy Model JSON from disk
+ def self.read_from_disk(file)
+ hash = nil
+ File.open(File.join(file), 'r') do |f|
+ hash = JSON.parse(f.read, symbolize_names: true)
+ end
+ Model.new(hash)
+ end
+
+ # Load ModelObject from symbolized hash
+ def initialize(hash)
+ # initialize class variable @@extension only once
+ @@extension ||= Extension.new
+ @@schema ||= @@extension.schema
+
+ @hash = hash
+ @type = @hash[:type]
+ raise 'Unknown model type' if @type.nil?
+ raise "Incorrect model type '#{@type}'" unless @type == 'Model'
+
+ end
+
+ # check if the model is valid
+ def valid?
+ if Gem.loaded_specs.has_key?("json-schema")
+ return validation_errors.empty?
+ else
+ return true
+ end
+ end
+
+ # return detailed model validation errors
+ def validation_errors
+ if Gem.loaded_specs.has_key?("json-schema")
+ require 'json-schema'
+ JSON::Validator.fully_validate(@@schema, @hash)
+ end
+ end
+
+ def defaults
+ @@schema[:components][:schemas][:ModelEnergyProperties][:properties]
+ end
+
+ # convert to openstudio model, clears errors and warnings
+ def to_openstudio_model(openstudio_model=nil, log_report=true)
+ @errors = []
+ @warnings = []
+
+ if log_report
+ puts 'Starting Model translation from Honeybee to OpenStudio'
+ end
+
+ @openstudio_model = if openstudio_model
+ openstudio_model
+ else
+ OpenStudio::Model::Model.new
+ end
+
+ # create all openstudio objects in the model
+ create_openstudio_objects(log_report)
+
+ if log_report
+ puts 'Done with Model translation!'
+ end
+
+ @openstudio_model
+ end
+
+ private
+
+ # create OpenStudio objects in the OpenStudio model
+ def create_openstudio_objects(log_report=true)
+ # assign a standards building type so that David's measures can run
+ building = @openstudio_model.getBuilding
+ building.setStandardsBuildingType('MediumOffice')
+
+ # create all of the non-geometric model elements
+ if log_report
+ puts 'Translating Materials'
+ end
+ create_materials
+
+ if log_report
+ puts 'Translating Constructions'
+ end
+ create_constructions
+
+ if log_report
+ puts 'Translating ConstructionSets'
+ end
+ create_construction_set
+ create_global_construction_set
+
+ if log_report
+ puts 'Translating Schedules'
+ end
+ create_schedule_type_limits
+ create_schedules
+
+ if log_report
+ puts 'Translating ProgramTypes'
+ end
+ create_program_types
+
+ # create all of the model geometry
+ if log_report
+ puts 'Translating Room Geometry'
+ end
+ create_rooms
+
+ if log_report
+ puts 'Translating Context Shade Geometry'
+ end
+ create_orphaned_shades
+ create_orphaned_faces
+ create_orphaned_apertures
+ create_orphaned_doors
+
+ # create the hvac systems
+ if log_report
+ puts 'Translating HVAC Systems'
+ end
+ create_hvacs
+ end
+
+ def create_materials
+ @hash[:properties][:energy][:materials].each do |material|
+ material_type = material[:type]
+
+ case material_type
+ when 'EnergyMaterial'
+ material_object = EnergyMaterial.new(material)
+ when 'EnergyMaterialNoMass'
+ material_object = EnergyMaterialNoMass.new(material)
+ when 'EnergyWindowMaterialGas'
+ material_object = EnergyWindowMaterialGas.new(material)
+ when 'EnergyWindowMaterialGasCustom'
+ material_object = EnergyWindowMaterialGasCustom.new(material)
+ when 'EnergyWindowMaterialSimpleGlazSys'
+ material_object = EnergyWindowMaterialSimpleGlazSys.new(material)
+ when 'EnergyWindowMaterialBlind'
+ material_object = EnergyWindowMaterialBlind.new(material)
+ when 'EnergyWindowMaterialGlazing'
+ material_object = EnergyWindowMaterialGlazing.new(material)
+ when 'EnergyWindowMaterialShade'
+ material_object = EnergyWindowMaterialShade.new(material)
+ else
+ raise "Unknown material type #{material_type}"
+ end
+ material_object.to_openstudio(@openstudio_model)
+ end
+ end
+
+ def create_constructions
+ $air_boundary_hash = Hash.new # hash to track any air boundary constructions
+
+ @hash[:properties][:energy][:constructions].each do |construction|
+ identifier = construction[:identifier]
+ construction_type = construction[:type]
+
+ case construction_type
+ when 'OpaqueConstructionAbridged'
+ construction_object = OpaqueConstructionAbridged.new(construction)
+ when 'WindowConstructionAbridged'
+ construction_object = WindowConstructionAbridged.new(construction)
+ when 'ShadeConstruction'
+ construction_object = ShadeConstruction.new(construction)
+ when 'AirBoundaryConstructionAbridged'
+ construction_object = AirBoundaryConstructionAbridged.new(construction)
+ $air_boundary_hash[construction[:identifier]] = construction
+ else
+ raise "Unknown construction type #{construction_type}."
+ end
+ construction_object.to_openstudio(@openstudio_model)
+ end
+ end
+
+ def create_construction_set
+ if @hash[:properties][:energy][:construction_sets]
+ @hash[:properties][:energy][:construction_sets].each do |construction_set|
+ construction_set_object = ConstructionSetAbridged.new(construction_set)
+ construction_set_object.to_openstudio(@openstudio_model)
+ end
+ end
+ end
+
+ def create_global_construction_set
+ if @hash[:properties][:energy][:global_construction_set]
+ construction_id = @hash[:properties][:energy][:global_construction_set]
+ construction = @openstudio_model.getDefaultConstructionSetByName(construction_id)
+ unless construction.empty?
+ openstudio_construction = construction.get
+ end
+ @openstudio_model.getBuilding.setDefaultConstructionSet(openstudio_construction)
+ end
+ end
+
+ def create_schedule_type_limits
+ if @hash[:properties][:energy][:schedule_type_limits]
+ @hash[:properties][:energy][:schedule_type_limits].each do |schedule_type_limit|
+ schedule_type_limit_object = ScheduleTypeLimit.new(schedule_type_limit)
+ schedule_type_limit_object.to_openstudio(@openstudio_model)
+ end
+ end
+ end
+
+ def create_schedules
+ if @hash[:properties][:energy][:schedules]
+ @hash[:properties][:energy][:schedules].each do |schedule|
+ schedule_type = schedule[:type]
+
+ case schedule_type
+ when 'ScheduleRulesetAbridged'
+ schedule_object = ScheduleRulesetAbridged.new(schedule)
+ when 'ScheduleFixedIntervalAbridged'
+ schedule_object = ScheduleFixedIntervalAbridged.new(schedule)
+ else
+ raise("Unknown schedule type #{schedule_type}.")
+ end
+ schedule_object.to_openstudio(@openstudio_model)
+
+ end
+ end
+ end
+
+ def create_program_types
+ if @hash[:properties][:energy][:program_types]
+ $programtype_setpoint_hash = Hash.new # hash to track Setpoint objects
+ @hash[:properties][:energy][:program_types].each do |space_type|
+ space_type_object = ProgramTypeAbridged.new(space_type)
+ space_type_object.to_openstudio(@openstudio_model)
+ end
+ end
+ end
+
+ def create_rooms
+ if @hash[:rooms]
+ $air_mxing_array = [] # list to track any air mixing between Rooms
+
+ @hash[:rooms].each do |room|
+ room_object = Room.new(room)
+ openstudio_room = room_object.to_openstudio(@openstudio_model)
+
+ # for rooms with setpoint objects definied in the ProgramType, make a new thermostat
+ if room[:properties][:energy][:program_type] && !room[:properties][:energy][:setpoint]
+ thermal_zone = openstudio_room.thermalZone()
+ unless thermal_zone.empty?
+ thermal_zone_object = thermal_zone.get
+ program_type_id = room[:properties][:energy][:program_type]
+ setpoint_hash = $programtype_setpoint_hash[program_type_id]
+ if not setpoint_hash.nil? # program type has no setpoint
+ thermostat_object = SetpointThermostat.new(setpoint_hash)
+ openstudio_thermostat = thermostat_object.to_openstudio(@openstudio_model)
+ thermal_zone_object.setThermostatSetpointDualSetpoint(openstudio_thermostat)
+ if setpoint_hash[:humidifying_schedule] or setpoint_hash[:dehumidifying_schedule]
+ humidistat_object = ZoneControlHumidistat.new(setpoint_hash)
+ openstudio_humidistat = humidistat_object.to_openstudio(@openstudio_model)
+ thermal_zone_object.setZoneControlHumidistat(openstudio_humidistat)
+ end
+ end
+ end
+ end
+ end
+
+ # Create mixing objects between Rooms
+ $air_mxing_array.each do |air_mix_props|
+ zone_mixing = OpenStudio::Model::ZoneMixing.new(air_mix_props[0])
+ zone_mixing.setDesignFlowRate(air_mix_props[1])
+ flow_sch_ref = @openstudio_model.getScheduleByName(air_mix_props[2])
+ unless flow_sch_ref.empty?
+ flow_sched = flow_sch_ref.get
+ zone_mixing.setSchedule(flow_sched)
+ end
+ source_zone_ref = @openstudio_model.getThermalZoneByName(air_mix_props[3])
+ unless source_zone_ref.empty?
+ source_zone = source_zone_ref.get
+ zone_mixing.setSourceZone(source_zone)
+ end
+ end
+ end
+ end
+
+
+ def create_orphaned_shades
+ if @hash[:orphaned_shades]
+ shading_surface_group = OpenStudio::Model::ShadingSurfaceGroup.new(@openstudio_model)
+ shading_surface_group.setShadingSurfaceType('Building')
+ @hash[:orphaned_shades].each do |shade|
+ shade_object = Shade.new(shade)
+ openstudio_shade = shade_object.to_openstudio(@openstudio_model)
+ openstudio_shade.setShadingSurfaceGroup(shading_surface_group)
+ end
+ end
+ end
+
+ def create_orphaned_faces
+ if @hash[:orphaned_faces]
+ raise "Orphaned Faces are not translatable to OpenStudio."
+ end
+ end
+
+ def create_orphaned_apertures
+ if @hash[:orphaned_apertures]
+ raise "Orphaned Apertures are not translatable to OpenStudio."
+ end
+ end
+
+ def create_orphaned_doors
+ if @hash[:orphaned_doors]
+ raise "Orphaned Doors are not translatable to OpenStudio."
+ end
+ end
+
+ def create_hvacs
+ if @hash[:properties][:energy][:hvacs]
+ # gather all of the hashes of the HVACs
+ hvac_hashes = Hash.new
+ @hash[:properties][:energy][:hvacs].each do |hvac|
+ hvac_hashes[hvac[:identifier]] = hvac
+ hvac_hashes[hvac[:identifier]]['rooms'] = []
+ end
+ # loop through the rooms and trach which are assigned to each HVAC
+ if @hash[:rooms]
+ @hash[:rooms].each do |room|
+ if room[:properties][:energy][:hvac]
+ hvac_hashes[room[:properties][:energy][:hvac]]['rooms'] << room[:identifier]
+ end
+ end
+ end
+
+ hvac_hashes.each_value do |hvac|
+ system_type = hvac[:type]
+ case system_type
+ when 'IdealAirSystemAbridged'
+ ideal_air_system = IdealAirSystemAbridged.new(hvac)
+ os_ideal_air_system = ideal_air_system.to_openstudio(@openstudio_model)
+ hvac['rooms'].each do |room_id|
+ zone_get = @openstudio_model.getThermalZoneByName(room_id)
+ unless zone_get.empty?
+ os_thermal_zone = zone_get.get
+ os_ideal_air_system.addToThermalZone(os_thermal_zone)
+ end
+ end
+ end
+ end
+ end
+ end
+
+ #TODO: create runlog for errors.
+
+ end # Model
+end # FromHoneybee