lib/openstudio-standards/standards/Standards.Model.rb in openstudio-standards-0.2.10 vs lib/openstudio-standards/standards/Standards.Model.rb in openstudio-standards-0.2.11.rc1

- old
+ new

@@ -1,9 +1,7 @@ require 'csv' - - class Standard attr_accessor :space_multiplier_map attr_accessor :standards_data def define_space_multiplier @@ -88,10 +86,13 @@ sys_groups = model_prm_baseline_system_groups(model, custom) # Remove all HVAC from model, excluding service water heating model_remove_prm_hvac(model) + # Remove all EMS objects from the model + model_remove_prm_ems_objects(model) + # Modify the service water heating loops per the baseline rules OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.Model', '*** Cleaning up Service Water Heating Loops ***') model_apply_baseline_swh_loops(model, building_type) # Determine the baseline HVAC system type for each of the groups of zones and add that system type. @@ -1243,11 +1244,11 @@ array_of_zones.delete_at(biggest_delta_i) # Call method recursively if something was eliminated array_of_zones = model_eliminate_outlier_zones(model, array_of_zones, key_to_inspect, tolerance, field_name, units) else zn_name = array_of_zones[biggest_delta_i]['zone'].name.get.to_s - OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.Model', "For zone #{zn_name}, the #{field_name} #{worst.round(2)} #{units} - average #{field_name} #{avg.round(2)} #{units} = #{biggest_delta.round(2)} #{units} < tolerance of #{tolerance} #{units}, stopping elimination process.") + OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.Model', "For zone #{zn_name}, the #{field_name} #{worst.round(2)} #{units} - average #{field_name} #{avg.round(2)} #{units} = #{biggest_delta.round(2)} #{units} less than the tolerance of #{tolerance} #{units}, stopping elimination process.") end return array_of_zones end @@ -1259,11 +1260,11 @@ # on the system by more than 10 Btu/hr*ft^2. # # @return [Hash] A hash of two arrays of ThermalZones, # where the keys are 'primary' and 'secondary' def model_differentiate_primary_secondary_thermal_zones(model, zones) - OpenStudio.logFree(OpenStudio::Info, 'openstudio.Standards.Model', 'Determining which zones are served by the primary vs. secondary HVAC system.') + OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.Model', 'Determining which zones are served by the primary vs. secondary HVAC system.') # Determine the operational hours (proxy is annual # full load lighting hours) for all zones zone_data_1 = [] zones.each do |zone| @@ -1363,14 +1364,14 @@ end end # Report out the primary vs. secondary zones unless pri_zone_names.empty? - OpenStudio.logFree(OpenStudio::Info, 'openstudio.Standards.Model', "Primary system zones = #{pri_zone_names.join(', ')}.") + OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.Model', "Primary system zones = #{pri_zone_names.join(', ')}.") end unless sec_zone_names.empty? - OpenStudio.logFree(OpenStudio::Info, 'openstudio.Standards.Model', "Secondary system zones = #{sec_zone_names.join(', ')}.") + OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.Model', "Secondary system zones = #{sec_zone_names.join(', ')}.") end return { 'primary' => pri_zones, 'secondary' => sec_zones } end @@ -1389,11 +1390,11 @@ all_zones_on_story = [] spaces.each do |space| if space.thermalZone.is_initialized all_zones_on_story << space.thermalZone.get else - OpenStudio.logFree(OpenStudio::Warn, 'openstudio.Standards.Model', "Space #{space.name} has no thermal zone, it is not included in the simulation.") + OpenStudio.logFree(OpenStudio::Warn, 'openstudio.standards.Model', "Space #{space.name} has no thermal zone, it is not included in the simulation.") end end # Find zones in the list that are on this story zones_on_story = [] @@ -1447,11 +1448,11 @@ space_obj = space[0] space_minz = space[1] if space_obj.buildingStory.empty? story = model_get_story_for_nominal_z_coordinate(model, space_minz) space_obj.setBuildingStory(story) - OpenStudio.logFree(OpenStudio::Warn, 'openstudio.Standards.Model', "Space #{space[0].name} was not assigned to a story by the user. It has been assigned to #{story.name}.") + OpenStudio.logFree(OpenStudio::Warn, 'openstudio.standards.Model', "Space #{space[0].name} was not assigned to a story by the user. It has been assigned to #{story.name}.") end end return true end @@ -1471,11 +1472,11 @@ # Applies the HVAC parts of the template to all objects in the model using the the template specified in the model. def model_apply_hvac_efficiency_standard(model, climate_zone, apply_controls: true) sql_db_vars_map = {} - OpenStudio.logFree(OpenStudio::Info, 'openstudio.model.Model', 'Started applying HVAC efficiency standards.') + OpenStudio.logFree(OpenStudio::Info, 'openstudio.model.Model', "Started applying HVAC efficiency standards for #{template} template.") # Air Loop Controls if apply_controls.nil? || apply_controls == true model.getAirLoopHVACs.sort.each { |obj| air_loop_hvac_apply_standard_controls(obj, climate_zone) } end @@ -1501,11 +1502,11 @@ model.getHeaderedPumpsConstantSpeeds.sort.each { |obj| pump_apply_standard_minimum_motor_efficiency(obj) } model.getHeaderedPumpsVariableSpeeds.sort.each { |obj| pump_apply_standard_minimum_motor_efficiency(obj) } # Unitary HPs # set DX HP coils before DX clg coils because when DX HP coils need to first - # pull the capacities of their paried DX clg coils, and this does not work + # pull the capacities of their paired DX clg coils, and this does not work # correctly if the DX clg coil efficiencies have been set because they are renamed. model.getCoilHeatingDXSingleSpeeds.sort.each { |obj| sql_db_vars_map = coil_heating_dx_single_speed_apply_efficiency_and_curves(obj, sql_db_vars_map) } # Unitary ACs model.getCoilCoolingDXTwoSpeeds.sort.each { |obj| sql_db_vars_map = coil_cooling_dx_two_speed_apply_efficiency_and_curves(obj, sql_db_vars_map) } @@ -3158,11 +3159,11 @@ int_surfs.empty? || gnd_surfs.empty? || ext_subsurfs.empty? || int_subsurfs.empty? - OpenStudio.logFree(OpenStudio::Error, 'openstudio.model.Space', "Default construction set #{const_set.name} is incomplete; contructions from this set will not be reported.") + OpenStudio.logFree(OpenStudio::Error, 'openstudio.model.Space', "Default construction set #{const_set.name} is incomplete; constructions from this set will not be reported.") next end ext_surfs = ext_surfs.get int_surfs = int_surfs.get @@ -3776,10 +3777,30 @@ model.getAirConditionerVariableRefrigerantFlows.each(&:remove) return true end + # Remove EMS objects that may be orphaned from removing HVAC + # + # @return [Bool] true if successful, false if not + def model_remove_prm_ems_objects(model) + model.getEnergyManagementSystemActuators(&:remove) + model.getEnergyManagementSystemConstructionIndexVariables(&:remove) + model.getEnergyManagementSystemCurveOrTableIndexVariables(&:remove) + model.getEnergyManagementSystemGlobalVariables(&:remove) + model.getEnergyManagementSystemInternalVariables(&:remove) + model.getEnergyManagementSystemMeteredOutputVariables(&:remove) + model.getEnergyManagementSystemOutputVariables(&:remove) + model.getEnergyManagementSystemPrograms(&:remove) + model.getEnergyManagementSystemProgramCallingManagers(&:remove) + model.getEnergyManagementSystemSensors(&:remove) + model.getEnergyManagementSystemSubroutines(&:remove) + model.getEnergyManagementSystemTrendVariables(&:remove) + + return true + end + # Remove external shading devices. Site shading will not be impacted. # @return [Bool] returns true if successful, false if not. def model_remove_external_shading_devices(model) shading_surfaces_removed = 0 model.getShadingSurfaceGroups.sort.each do |shade_group| @@ -4015,21 +4036,21 @@ end end # Check the results if possible_climate_zone_sets.size.zero? - OpenStudio.logFree(OpenStudio::Error, 'openstudio.standards.Model', "Cannot find a climate zone set containing #{clim}") + OpenStudio.logFree(OpenStudio::Error, 'openstudio.standards.Model', "Cannot find a climate zone set containing #{clim}. Make sure to use ASHRAE standards with ASHRAE climate zones and DEER or CA Title 24 standards with CEC climate zones.") elsif possible_climate_zone_sets.size > 2 - OpenStudio.logFree(OpenStudio::Error, 'openstudio.standards.Model', "Found more than 2 climate zone sets containing #{clim}; will return last matching cliimate zone set.") + OpenStudio.logFree(OpenStudio::Error, 'openstudio.standards.Model', "Found more than 2 climate zone sets containing #{clim}; will return last matching climate zone set.") end # Get the climate zone from the possible set climate_zone_set = model_get_climate_zone_set_from_list(model, possible_climate_zone_sets) # Check that a climate zone set was found if climate_zone_set.nil? - OpenStudio.logFree(OpenStudio::Error, 'openstudio.standards.Model', "Cannot find a climate zone set when #{template}") + OpenStudio.logFree(OpenStudio::Error, 'openstudio.standards.Model', "Cannot find a climate zone set in standard #{template}") end return climate_zone_set end @@ -4286,11 +4307,11 @@ OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.Model', "For #{space_type.name}, number of students = #{num_students}.") unless num_students == 0.0 OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.Model', "For #{space_type.name}, number of beds = #{num_beds}.") unless num_beds == 0.0 OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.Model', "For #{space_type.name}, number of meals = #{num_meals}.") unless num_meals.nil? else - OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.Model', "Cannot identify standards buidling type and space type for #{space_type.name}, it won't be added to space_type_hash.") + OpenStudio.logFree(OpenStudio::Info, 'openstudio.standards.Model', "Cannot identify standards building type and space type for #{space_type.name}, it won't be added to space_type_hash.") end end return space_type_hash.sort.to_h end @@ -4501,11 +4522,11 @@ model.getSpaces.sort.each do |space| @space_multiplier_map[space.name.get] = space.multiplier if space.multiplier > 1 end OpenStudio.logFree(OpenStudio::Info, 'openstudio.model.Model', 'Finished adding geometry') unless @space_multiplier_map.empty? - OpenStudio.logFree(OpenStudio::Info, 'openstudio.model.Model', "Found mulitpliers for space #{@space_multiplier_map}") + OpenStudio.logFree(OpenStudio::Info, 'openstudio.model.Model', "Found multipliers for space #{@space_multiplier_map}") end return is_valid end # Determines how ventilation for the standard is specified. @@ -4895,11 +4916,11 @@ model.getScheduleRulesets.sort.each do |sch| if !sch.hasAdditionalProperties or !sch.additionalProperties.hasFeature("param_sch_ver") # for now don't look at schedules without targets, in future can alter these by looking at building level hours of operation next if not sch.directUseCount > 0 # won't catch if used for space type load instance, but that space type isn't used # todo - address schedules that fall into this category, if they are used in the model - OpenStudio.logFree(OpenStudio::Warn, 'openstudio.standards.ScheduleRuleset', "For #{sch.sources.first.name}, #{sch.name} is not setup as parametric schedule. It has #{sch.sources.size} sources.") + OpenStudio.logFree(OpenStudio::Warn, 'openstudio.standards.Model', "For #{sch.sources.first.name}, #{sch.name} is not setup as parametric schedule. It has #{sch.sources.size} sources.") next end # apply parametric inputs schedule_apply_parametric_inputs(sch,ramp_frequency,infer_hoo_for_non_assigned_objects,error_on_out_of_order,parametric_inputs) @@ -5368,10 +5389,10 @@ daily_flh = day_schedule_equivalent_full_load_hrs(schedule_day) percent_change = ((daily_flh - est_daily_flh)/daily_flh) * 100.0 if percent_change.abs > 0.05 # todo - this estimation can have flaws. Fix or remove it, make sure to update for secondary logic (if we implement that here) # post application checks compares against actual instead of estimated values - OpenStudio.logFree(OpenStudio::Debug, 'openstudio.standards.ScheduleRuleset', "For day schedule #{schedule_day.name} in #{sch.name} there was a #{percent_change.round(4)}% change. Expected full load hours is #{daily_flh.round(4)}, but estimated value is #{est_daily_flh.round(4)}") + OpenStudio.logFree(OpenStudio::Debug, 'openstudio.standards.Model', "For day schedule #{schedule_day.name} in #{sch.name} there was a #{percent_change.round(4)}% change. Expected full load hours is #{daily_flh.round(4)}, but estimated value is #{est_daily_flh.round(4)}") end raw_string = [] par_val_time_hash.sort.each do |time,value_array|