lib/from_honeybee/simulation/parameter.rb in honeybee-openstudio-1.8.1 vs lib/from_honeybee/simulation/parameter.rb in honeybee-openstudio-1.8.2
- old
+ new
@@ -1,277 +1,277 @@
-# *******************************************************************************
-# 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.
-# *******************************************************************************
-
-require 'from_honeybee/model_object'
-require 'from_honeybee/simulation/extension'
-require 'from_honeybee/simulation/designday'
-
-require 'openstudio'
-
-module FromHoneybee
- class SimulationParameter
- attr_reader :errors, :warnings
-
- # Read Simulation Parameter 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
-
- SimulationParameter.new(hash)
- end
-
- # Load ModelObject from symbolized hash
- def initialize(hash)
- # initialize class variable @@extension only once
- @@extension = ExtensionSimulationParameter.new
- @@schema = nil
- File.open(@@extension.schema_file) do |f|
- @@schema = JSON.parse(f.read, symbolize_names: true)
- end
-
- @hash = hash
- @type = @hash[:type]
- raise 'Unknown model type' if @type.nil?
- raise "Incorrect model type for SimulationParameter '#{@type}'" unless @type == 'SimulationParameter'
- 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]
- end
-
- # convert to openstudio model, clears errors and warnings
- def to_openstudio_model(openstudio_model=nil, log_report=false)
- @errors = []
- @warnings = []
-
- if log_report
- puts 'Starting SimulationParameter translation from Honeybee to OpenStudio'
- end
- @openstudio_model = if openstudio_model
- openstudio_model
- else
- OpenStudio::Model::Model.new
- end
-
- create_openstudio_objects
-
- if log_report
- puts 'Done with SimulationParameter translation!'
- end
-
- @openstudio_model
- end
-
- def create_openstudio_objects
- # get the defaults for each sub-object
- simct_defaults = defaults[:SimulationControl][:properties]
- shdw_defaults = defaults[:ShadowCalculation][:properties]
- siz_defaults = defaults[:SizingParameter][:properties]
- out_defaults = defaults[:SimulationOutput][:properties]
- runper_defaults = defaults[:RunPeriod][:properties]
- simpar_defaults = defaults[:SimulationParameter][:properties]
-
- # set defaults for the Model's SimulationControl object
- os_sim_control = @openstudio_model.getSimulationControl
- os_sim_control.setDoZoneSizingCalculation(simct_defaults[:do_zone_sizing][:default])
- os_sim_control.setDoSystemSizingCalculation(simct_defaults[:do_system_sizing][:default])
- os_sim_control.setDoPlantSizingCalculation(simct_defaults[:do_plant_sizing][:default])
- os_sim_control.setRunSimulationforWeatherFileRunPeriods(simct_defaults[:run_for_run_periods][:default])
- os_sim_control.setRunSimulationforSizingPeriods(simct_defaults[:run_for_sizing_periods][:default])
- os_sim_control.setSolarDistribution(shdw_defaults[:solar_distribution][:default])
-
- # override any SimulationControl defaults with lodaded JSON
- if @hash[:simulation_control]
- unless @hash[:simulation_control][:do_zone_sizing].nil?
- os_sim_control.setDoZoneSizingCalculation(@hash[:simulation_control][:do_zone_sizing])
- end
- unless @hash[:simulation_control][:do_system_sizing].nil?
- os_sim_control.setDoSystemSizingCalculation(@hash[:simulation_control][:do_system_sizing])
- end
- unless @hash[:simulation_control][:do_plant_sizing].nil?
- os_sim_control.setDoPlantSizingCalculation(@hash[:simulation_control][:do_plant_sizing])
- end
- unless @hash[:simulation_control][:run_for_run_periods].nil?
- os_sim_control.setRunSimulationforWeatherFileRunPeriods(@hash[:simulation_control][:run_for_run_periods])
- end
- unless @hash[:simulation_control][:run_for_sizing_periods].nil?
- os_sim_control.setRunSimulationforSizingPeriods(@hash[:simulation_control][:run_for_sizing_periods])
- end
- end
-
- # set defaults for the Model's ShadowCalculation object
- os_shadow_calc = @openstudio_model.getShadowCalculation
- os_shadow_calc.setCalculationFrequency(shdw_defaults[:calculation_frequency][:default])
- os_shadow_calc.setMaximumFiguresInShadowOverlapCalculations(shdw_defaults[:maximum_figures][:default])
- os_shadow_calc.setCalculationMethod(shdw_defaults[:calculation_method][:default])
-
- # override any ShadowCalculation defaults with lodaded JSON
- if @hash[:shadow_calculation]
- if @hash[:shadow_calculation][:calculation_frequency]
- os_shadow_calc.setCalculationFrequency(@hash[:shadow_calculation][:calculation_frequency])
- end
- if @hash[:shadow_calculation][:maximum_figures]
- os_shadow_calc.setMaximumFiguresInShadowOverlapCalculations(@hash[:shadow_calculation][:maximum_figures])
- end
- if @hash[:shadow_calculation][:calculation_method]
- os_shadow_calc.setCalculationMethod(@hash[:shadow_calculation][:calculation_method])
- end
- if @hash[:shadow_calculation][:solar_distribution]
- os_sim_control.setSolarDistribution(@hash[:shadow_calculation][:solar_distribution])
- end
- end
-
- # set defaults for the Model's SizingParameter object
- os_sizing_par = @openstudio_model.getSizingParameters
- os_sizing_par.setHeatingSizingFactor(siz_defaults[:heating_factor][:default])
- os_sizing_par.setCoolingSizingFactor(siz_defaults[:cooling_factor][:default])
-
- # override any SizingParameter defaults with lodaded JSON
- if @hash[:sizing_parameter]
- if @hash[:sizing_parameter][:heating_factor]
- os_sizing_par.setHeatingSizingFactor(@hash[:sizing_parameter][:heating_factor])
- end
- if @hash[:sizing_parameter][:cooling_factor]
- os_sizing_par.setCoolingSizingFactor(@hash[:sizing_parameter][:cooling_factor])
- end
- # set any design days
- if @hash[:sizing_parameter][:design_days]
- @hash[:sizing_parameter][:design_days].each do |des_day|
- des_day_object = DesignDay.new(des_day)
- os_des_day = des_day_object.to_openstudio(@openstudio_model)
- end
- end
- end
-
- # set Outputs for the simulation
- if @hash[:output]
- if @hash[:output][:outputs]
- @hash[:output][:outputs].each do |output|
- os_output = OpenStudio::Model::OutputVariable.new(output, @openstudio_model)
- if @hash[:output][:reporting_frequency]
- os_output.setReportingFrequency(@hash[:output][:reporting_frequency])
- else
- os_output.setReportingFrequency(out_defaults[:reporting_frequency][:default])
- end
- end
- end
- if @hash[:output][:summary_reports]
- begin
- os_report = OpenStudio::Model::OutputTableSummaryReports.new(@openstudio_model)
- rescue NameError
- end
- @hash[:output][:summary_reports].each do |report|
- begin
- os_report.addSummaryReport(report)
- rescue NoMethodError
- end
- end
- end
- end
-
- # set defaults for the year description
- year_description = @openstudio_model.getYearDescription
- year_description.setDayofWeekforStartDay(runper_defaults[:start_day_of_week][:default])
-
- # set up the simulation RunPeriod
- if @hash[:run_period]
- # set the leap year
- if @hash[:run_period][:leap_year]
- year_description.setIsLeapYear(@hash[:run_period][:leap_year])
- end
-
- # set the start day of the week
- if @hash[:run_period][:start_day_of_week]
- year_description.setDayofWeekforStartDay(@hash[:run_period][:start_day_of_week])
- end
-
- # set the run preiod start and end dates
- openstudio_runperiod = @openstudio_model.getRunPeriod
- openstudio_runperiod.setBeginMonth(@hash[:run_period][:start_date][0])
- openstudio_runperiod.setBeginDayOfMonth(@hash[:run_period][:start_date][1])
- openstudio_runperiod.setEndMonth(@hash[:run_period][:end_date][0])
- openstudio_runperiod.setEndDayOfMonth(@hash[:run_period][:end_date][1])
-
- # set the daylight savings time
- if @hash[:run_period][:daylight_saving_time]
- os_dl_saving = @openstudio_model.getRunPeriodControlDaylightSavingTime
- os_dl_saving.setStartDate(
- OpenStudio::MonthOfYear.new(@hash[:run_period][:daylight_saving_time][:start_date][0]),
- @hash[:run_period][:daylight_saving_time][:start_date][1])
- os_dl_saving.setEndDate(
- OpenStudio::MonthOfYear.new(@hash[:run_period][:daylight_saving_time][:end_date][0]),
- @hash[:run_period][:daylight_saving_time][:end_date][1])
- end
-
- # TODO: set the holidays once they are available in OpenStudio SDK
- end
-
- # set the simulation timestep
- os_timestep = @openstudio_model.getTimestep
- if @hash[:timestep]
- os_timestep.setNumberOfTimestepsPerHour(@hash[:timestep])
- else
- os_timestep.setNumberOfTimestepsPerHour(simpar_defaults[:timestep][:default])
- end
-
- # assign the north
- if @hash[:north_angle]
- @openstudio_model.getBuilding.setNorthAxis(-@hash[:north_angle])
- end
-
- # assign the terrain
- os_site = @openstudio_model.getSite
- os_site.setTerrain(simpar_defaults[:terrain_type][:default])
- if @hash[:terrain_type]
- os_site.setTerrain(@hash[:terrain_type])
- end
- end
-
- end #SimulationParameter
-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.
+# *******************************************************************************
+
+require 'from_honeybee/model_object'
+require 'from_honeybee/simulation/extension'
+require 'from_honeybee/simulation/designday'
+
+require 'openstudio'
+
+module FromHoneybee
+ class SimulationParameter
+ attr_reader :errors, :warnings
+
+ # Read Simulation Parameter 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
+
+ SimulationParameter.new(hash)
+ end
+
+ # Load ModelObject from symbolized hash
+ def initialize(hash)
+ # initialize class variable @@extension only once
+ @@extension = ExtensionSimulationParameter.new
+ @@schema = nil
+ File.open(@@extension.schema_file) do |f|
+ @@schema = JSON.parse(f.read, symbolize_names: true)
+ end
+
+ @hash = hash
+ @type = @hash[:type]
+ raise 'Unknown model type' if @type.nil?
+ raise "Incorrect model type for SimulationParameter '#{@type}'" unless @type == 'SimulationParameter'
+ 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]
+ end
+
+ # convert to openstudio model, clears errors and warnings
+ def to_openstudio_model(openstudio_model=nil, log_report=false)
+ @errors = []
+ @warnings = []
+
+ if log_report
+ puts 'Starting SimulationParameter translation from Honeybee to OpenStudio'
+ end
+ @openstudio_model = if openstudio_model
+ openstudio_model
+ else
+ OpenStudio::Model::Model.new
+ end
+
+ create_openstudio_objects
+
+ if log_report
+ puts 'Done with SimulationParameter translation!'
+ end
+
+ @openstudio_model
+ end
+
+ def create_openstudio_objects
+ # get the defaults for each sub-object
+ simct_defaults = defaults[:SimulationControl][:properties]
+ shdw_defaults = defaults[:ShadowCalculation][:properties]
+ siz_defaults = defaults[:SizingParameter][:properties]
+ out_defaults = defaults[:SimulationOutput][:properties]
+ runper_defaults = defaults[:RunPeriod][:properties]
+ simpar_defaults = defaults[:SimulationParameter][:properties]
+
+ # set defaults for the Model's SimulationControl object
+ os_sim_control = @openstudio_model.getSimulationControl
+ os_sim_control.setDoZoneSizingCalculation(simct_defaults[:do_zone_sizing][:default])
+ os_sim_control.setDoSystemSizingCalculation(simct_defaults[:do_system_sizing][:default])
+ os_sim_control.setDoPlantSizingCalculation(simct_defaults[:do_plant_sizing][:default])
+ os_sim_control.setRunSimulationforWeatherFileRunPeriods(simct_defaults[:run_for_run_periods][:default])
+ os_sim_control.setRunSimulationforSizingPeriods(simct_defaults[:run_for_sizing_periods][:default])
+ os_sim_control.setSolarDistribution(shdw_defaults[:solar_distribution][:default])
+
+ # override any SimulationControl defaults with lodaded JSON
+ if @hash[:simulation_control]
+ unless @hash[:simulation_control][:do_zone_sizing].nil?
+ os_sim_control.setDoZoneSizingCalculation(@hash[:simulation_control][:do_zone_sizing])
+ end
+ unless @hash[:simulation_control][:do_system_sizing].nil?
+ os_sim_control.setDoSystemSizingCalculation(@hash[:simulation_control][:do_system_sizing])
+ end
+ unless @hash[:simulation_control][:do_plant_sizing].nil?
+ os_sim_control.setDoPlantSizingCalculation(@hash[:simulation_control][:do_plant_sizing])
+ end
+ unless @hash[:simulation_control][:run_for_run_periods].nil?
+ os_sim_control.setRunSimulationforWeatherFileRunPeriods(@hash[:simulation_control][:run_for_run_periods])
+ end
+ unless @hash[:simulation_control][:run_for_sizing_periods].nil?
+ os_sim_control.setRunSimulationforSizingPeriods(@hash[:simulation_control][:run_for_sizing_periods])
+ end
+ end
+
+ # set defaults for the Model's ShadowCalculation object
+ os_shadow_calc = @openstudio_model.getShadowCalculation
+ os_shadow_calc.setCalculationFrequency(shdw_defaults[:calculation_frequency][:default])
+ os_shadow_calc.setMaximumFiguresInShadowOverlapCalculations(shdw_defaults[:maximum_figures][:default])
+ os_shadow_calc.setCalculationMethod(shdw_defaults[:calculation_method][:default])
+
+ # override any ShadowCalculation defaults with lodaded JSON
+ if @hash[:shadow_calculation]
+ if @hash[:shadow_calculation][:calculation_frequency]
+ os_shadow_calc.setCalculationFrequency(@hash[:shadow_calculation][:calculation_frequency])
+ end
+ if @hash[:shadow_calculation][:maximum_figures]
+ os_shadow_calc.setMaximumFiguresInShadowOverlapCalculations(@hash[:shadow_calculation][:maximum_figures])
+ end
+ if @hash[:shadow_calculation][:calculation_method]
+ os_shadow_calc.setCalculationMethod(@hash[:shadow_calculation][:calculation_method])
+ end
+ if @hash[:shadow_calculation][:solar_distribution]
+ os_sim_control.setSolarDistribution(@hash[:shadow_calculation][:solar_distribution])
+ end
+ end
+
+ # set defaults for the Model's SizingParameter object
+ os_sizing_par = @openstudio_model.getSizingParameters
+ os_sizing_par.setHeatingSizingFactor(siz_defaults[:heating_factor][:default])
+ os_sizing_par.setCoolingSizingFactor(siz_defaults[:cooling_factor][:default])
+
+ # override any SizingParameter defaults with lodaded JSON
+ if @hash[:sizing_parameter]
+ if @hash[:sizing_parameter][:heating_factor]
+ os_sizing_par.setHeatingSizingFactor(@hash[:sizing_parameter][:heating_factor])
+ end
+ if @hash[:sizing_parameter][:cooling_factor]
+ os_sizing_par.setCoolingSizingFactor(@hash[:sizing_parameter][:cooling_factor])
+ end
+ # set any design days
+ if @hash[:sizing_parameter][:design_days]
+ @hash[:sizing_parameter][:design_days].each do |des_day|
+ des_day_object = DesignDay.new(des_day)
+ os_des_day = des_day_object.to_openstudio(@openstudio_model)
+ end
+ end
+ end
+
+ # set Outputs for the simulation
+ if @hash[:output]
+ if @hash[:output][:outputs]
+ @hash[:output][:outputs].each do |output|
+ os_output = OpenStudio::Model::OutputVariable.new(output, @openstudio_model)
+ if @hash[:output][:reporting_frequency]
+ os_output.setReportingFrequency(@hash[:output][:reporting_frequency])
+ else
+ os_output.setReportingFrequency(out_defaults[:reporting_frequency][:default])
+ end
+ end
+ end
+ if @hash[:output][:summary_reports]
+ begin
+ os_report = OpenStudio::Model::OutputTableSummaryReports.new(@openstudio_model)
+ rescue NameError
+ end
+ @hash[:output][:summary_reports].each do |report|
+ begin
+ os_report.addSummaryReport(report)
+ rescue NoMethodError
+ end
+ end
+ end
+ end
+
+ # set defaults for the year description
+ year_description = @openstudio_model.getYearDescription
+ year_description.setDayofWeekforStartDay(runper_defaults[:start_day_of_week][:default])
+
+ # set up the simulation RunPeriod
+ if @hash[:run_period]
+ # set the leap year
+ if @hash[:run_period][:leap_year]
+ year_description.setIsLeapYear(@hash[:run_period][:leap_year])
+ end
+
+ # set the start day of the week
+ if @hash[:run_period][:start_day_of_week]
+ year_description.setDayofWeekforStartDay(@hash[:run_period][:start_day_of_week])
+ end
+
+ # set the run preiod start and end dates
+ openstudio_runperiod = @openstudio_model.getRunPeriod
+ openstudio_runperiod.setBeginMonth(@hash[:run_period][:start_date][0])
+ openstudio_runperiod.setBeginDayOfMonth(@hash[:run_period][:start_date][1])
+ openstudio_runperiod.setEndMonth(@hash[:run_period][:end_date][0])
+ openstudio_runperiod.setEndDayOfMonth(@hash[:run_period][:end_date][1])
+
+ # set the daylight savings time
+ if @hash[:run_period][:daylight_saving_time]
+ os_dl_saving = @openstudio_model.getRunPeriodControlDaylightSavingTime
+ os_dl_saving.setStartDate(
+ OpenStudio::MonthOfYear.new(@hash[:run_period][:daylight_saving_time][:start_date][0]),
+ @hash[:run_period][:daylight_saving_time][:start_date][1])
+ os_dl_saving.setEndDate(
+ OpenStudio::MonthOfYear.new(@hash[:run_period][:daylight_saving_time][:end_date][0]),
+ @hash[:run_period][:daylight_saving_time][:end_date][1])
+ end
+
+ # TODO: set the holidays once they are available in OpenStudio SDK
+ end
+
+ # set the simulation timestep
+ os_timestep = @openstudio_model.getTimestep
+ if @hash[:timestep]
+ os_timestep.setNumberOfTimestepsPerHour(@hash[:timestep])
+ else
+ os_timestep.setNumberOfTimestepsPerHour(simpar_defaults[:timestep][:default])
+ end
+
+ # assign the north
+ if @hash[:north_angle]
+ @openstudio_model.getBuilding.setNorthAxis(-@hash[:north_angle])
+ end
+
+ # assign the terrain
+ os_site = @openstudio_model.getSite
+ os_site.setTerrain(simpar_defaults[:terrain_type][:default])
+ if @hash[:terrain_type]
+ os_site.setTerrain(@hash[:terrain_type])
+ end
+ end
+
+ end #SimulationParameter
+end #FromHoneybee