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