Measures/m_10_example_10_plant_loop_override_control/measure.rb
# define what happens when the measure is run
define what happens when the measure is run
define what happens when the measure is run
def run(model, runner, user_arguments)
    super(model, runner, user_arguments)
    if !runner.validateUserArguments(arguments(model), user_arguments)
      return false
    end
    verbose_info_statements = runner.getBoolArgumentValue("verbose_info_statements",user_arguments)
    condensor_plant_loop_objects = runner.getOptionalWorkspaceObjectChoiceValue('condensor_plant_loop_objects', user_arguments, model) 
    oa_db_override_temp = runner.getDoubleArgumentValue("oa_db_override_temp",user_arguments)
    internal_variable_availability_dictionary_reporting = runner.getStringArgumentValue('internal_variable_availability_dictionary_reporting', user_arguments)
    ems_runtime_language_debug_output_level = runner.getStringArgumentValue('ems_runtime_language_debug_output_level', user_arguments)
    actuator_availability_dictionary_reporting = runner.getStringArgumentValue('actuator_availability_dictionary_reporting', user_arguments)
    runner.registerInitialCondition("Measure began with #{model.getEnergyManagementSystemSensors.count} EMS sensors, #{model.getEnergyManagementSystemActuators.count} EMS Actuators, #{model.getEnergyManagementSystemPrograms.count} EMS Programs, #{model.getEnergyManagementSystemSubroutines.count} EMS Subroutines, #{model.getEnergyManagementSystemProgramCallingManagers.count} EMS Program Calling Manager objects")
    high_limit = 50
    low_limit = 30
    if oa_db_override_temp > high_limit
      runner.registerWarning("Value of OA temp of #{oa_db_override_temp} Deg F for loop override is higher then upper warning limit of #{high_limit} Deg F.")
    end
    if oa_db_override_temp < low_limit
      runner.registerWarning("Value of OA temp of #{oa_db_override_temp} Deg F for loop override is lower then lower warning limit of #{low_limit} Deg F.")
    end
    oa_db_override_temp_SI = OpenStudio.convert(oa_db_override_temp,"F","C")
    apply_to_all_plantloops = false
    selected_plantloop = nil
    if condensor_plant_loop_objects.empty?
      handle = runner.getStringArgumentValue('condensor_plant_loop_objects', user_arguments)
      if handle.empty?
        runner.registerError('No plant loop was chosen.')
        return false
      else
        runner.registerError("The selected plant loop with handle '#{handle}' was not found in the model. It may have been removed by another measure.")
        return false
      end
    else
      if !condensor_plant_loop_objects.get.to_PlantLoop.empty?
        selected_plantloop = condensor_plant_loop_objects.get.to_PlantLoop.get
      elsif !condensor_plant_loop_objects.get.to_Building.empty?
        apply_to_all_plantloops = true
      else
        runner.registerError('Script Error - argument not showing up as an air loop.')
        return false
      end
    end
    selected_plantloops = []
    if apply_to_all_plantloops == true
      model.getPlantLoops.each do |each_plantloop|
        if each_plantloop.sizingPlant.loopType == "Condenser"
          show_loop = true
        end  
        if show_loop == true
           selected_plantloops << each_plantloop
        end
      end 
    else 
      selected_plantloops << selected_plantloop
    end
    if selected_plantloops.length == 0
      runner.registerAsNotApplicable("Model contains no 'qualified' PlantLoops for this measure to modify.") 
      return true
    end
    counter = 0
    ems_oa_db_sensor = nil
    ems_control_tower_loop_operation_prgm = nil
    ems_prgm_calling_mngr = nil
    ems_oa_db_sensor = OpenStudio::Model::EnergyManagementSystemSensor.new(model, "Site Outdoor Air Drybulb Temperature")
    ems_oa_db_sensor.setName("OutdoorTemp")
    ems_oa_db_sensor.setKeyName("Environment")
    if verbose_info_statements == true
      runner.registerInfo("EMS Sensor object named #{ems_oa_db_sensor.name} added to the model to represent the 'Site Outdoor Air Drybulb Temperature'.")
    end
    ems_control_tower_loop_operation_prgm = OpenStudio::Model::EnergyManagementSystemProgram.new(model)
    ems_control_tower_loop_operation_prgm.setName("TowerControl")
    if verbose_info_statements == true
      runner.registerInfo("EMS Program object named '#{ems_control_tower_loop_operation_prgm.name}' added to control condensor plant loop operation.") 
    end
    ems_prgm_calling_mngr = OpenStudio::Model::EnergyManagementSystemProgramCallingManager.new(model)
    ems_prgm_calling_mngr.setName("Condenser OnOff Management")
    ems_prgm_calling_mngr.setCallingPoint("InsideHVACSystemIterationLoop")
    ems_prgm_calling_mngr.addProgram(ems_control_tower_loop_operation_prgm) 
    if verbose_info_statements == true
      runner.registerInfo("EMS Program Calling Manager object named '#{ems_prgm_calling_mngr.name}' added to call #{ems_control_tower_loop_operation_prgm.name} EMS program.") 
    end
    selected_plantloops.each do |plantloop|
      pump = nil 
      counter += 1 
      plantloop.supplyComponents.each do |supply_comp|
        if not supply_comp.to_PumpConstantSpeed.empty?
          pump = supply_comp.to_PumpConstantSpeed.get
        end
        if not supply_comp.to_PumpVariableSpeed.empty?
          pump = supply_comp.to_PumpVariableSpeed.get
        end
      end 
      pump_flow_override_report = OpenStudio::Model::EnergyManagementSystemGlobalVariable.new(model, "PumpFlowOverrideReport#{counter}")
      if verbose_info_statements == true
        runner.registerInfo("EMS Global Variable named '#{pump_flow_override_report.name}' to hold a pump flow override report value added to model.") 
      end
      plantloop_ems_actuator = OpenStudio::Model::EnergyManagementSystemActuator.new(plantloop,"Plant Loop Overall","On/Off Supervisory")
      plantloop_ems_actuator.setName("#{plantloop.name}Actuator_Loop#{counter}".gsub("-","_"))
      if verbose_info_statements == true
        runner.registerInfo("An EMS Actuator Object named '#{plantloop_ems_actuator.name}' representing a way to set a plantloop on/off supervisory control status has been added to model.") 
      end
      pump_flow_override_ems_actuator = OpenStudio::Model::EnergyManagementSystemActuator.new(pump,"Pump","Pump Mass Flow Rate")
      pump_flow_override_ems_actuator.setName("#{plantloop.name}PumpFlowOverride#{counter}".gsub("-","_"))
      if verbose_info_statements == true
        runner.registerInfo("An EMS Actuator Object named '#{pump_flow_override_ems_actuator.name}' representing a way to override the condensor loop pump on/off status has been added to model.") 
      end
      ems_cond_flow_override_on_EMS_output_var = OpenStudio::Model::EnergyManagementSystemOutputVariable.new(model,pump_flow_override_report)
      ems_cond_flow_override_on_EMS_output_var.setName("EMS Condenser Flow Override On#{counter}")
      ems_cond_flow_override_on_EMS_output_var.setEMSVariableName("#{pump_flow_override_report.name}")
      ems_cond_flow_override_on_EMS_output_var.setTypeOfDataInVariable("Averaged")
      ems_cond_flow_override_on_EMS_output_var.setUpdateFrequency("SystemTimeStep")
      ems_cond_flow_override_on_EMS_output_var.setUnits("On/Off") 
      ems_control_tower_loop_operation_prgm.addLine("IF (#{ems_oa_db_sensor.name} < 6.0)")
      ems_control_tower_loop_operation_prgm.addLine("SET #{plantloop_ems_actuator.name} = 0.0")
      ems_control_tower_loop_operation_prgm.addLine("SET #{pump_flow_override_ems_actuator.name} = 0.0")
      ems_control_tower_loop_operation_prgm.addLine("SET #{ems_cond_flow_override_on_EMS_output_var.name} = 1.0")
      ems_control_tower_loop_operation_prgm.addLine("ELSE")
      ems_control_tower_loop_operation_prgm.addLine("SET #{plantloop_ems_actuator.name} = Null")
      ems_control_tower_loop_operation_prgm.addLine("SET #{pump_flow_override_ems_actuator.name} = Null")
      ems_control_tower_loop_operation_prgm.addLine("SET #{ems_cond_flow_override_on_EMS_output_var.name} = 0.0")
      ems_control_tower_loop_operation_prgm.addLine("ENDIF")
      output_var = OpenStudio::Model::OutputVariable.new("#{ems_cond_flow_override_on_EMS_output_var.name}", model)
      output_var.setName("#{ems_cond_flow_override_on_EMS_output_var.name}")
      output_var.setKeyValue("*")
      output_var.setReportingFrequency("Hourly")
    end 
    output_EMS = model.getOutputEnergyManagementSystem
    output_EMS.setInternalVariableAvailabilityDictionaryReporting('internal_variable_availability_dictionary_reporting')
    output_EMS.setEMSRuntimeLanguageDebugOutputLevel('ems_runtime_language_debug_output_level')
    output_EMS.setActuatorAvailabilityDictionaryReporting('actuator_availability_dictionary_reporting')
    runner.registerInfo("Output EMS Program Object configured for model.") 
    runner.registerFinalCondition("Measure finished with #{model.getEnergyManagementSystemSensors.count} EMS sensors, #{model.getEnergyManagementSystemActuators.count} EMS Actuators, #{model.getEnergyManagementSystemPrograms.count} EMS Programs, #{model.getEnergyManagementSystemSubroutines.count} EMS Subroutines, #{model.getEnergyManagementSystemProgramCallingManagers.count} EMS Program Calling Manager objects")
  end
def run ( model , runner , user_arguments ) super ( model , runner , user_arguments ) if ! runner . validateUserArguments ( arguments ( model ) , user_arguments ) return false end verbose_info_statements = runner . getBoolArgumentValue ( "verbose_info_statements" , user_arguments ) condensor_plant_loop_objects = runner . getOptionalWorkspaceObjectChoiceValue ( 'condensor_plant_loop_objects' , user_arguments , model ) oa_db_override_temp = runner . getDoubleArgumentValue ( "oa_db_override_temp" , user_arguments ) internal_variable_availability_dictionary_reporting = runner . getStringArgumentValue ( 'internal_variable_availability_dictionary_reporting' , user_arguments ) ems_runtime_language_debug_output_level = runner . getStringArgumentValue ( 'ems_runtime_language_debug_output_level' , user_arguments ) actuator_availability_dictionary_reporting = runner . getStringArgumentValue ( 'actuator_availability_dictionary_reporting' , user_arguments ) runner . registerInitialCondition ( "Measure began with #{model.getEnergyManagementSystemSensors.count} EMS sensors, #{model.getEnergyManagementSystemActuators.count} EMS Actuators, #{model.getEnergyManagementSystemPrograms.count} EMS Programs, #{model.getEnergyManagementSystemSubroutines.count} EMS Subroutines, #{model.getEnergyManagementSystemProgramCallingManagers.count} EMS Program Calling Manager objects" ) high_limit = 50 low_limit = 30 if oa_db_override_temp > high_limit runner . registerWarning ( "Value of OA temp of #{oa_db_override_temp} Deg F for loop override is higher then upper warning limit of #{high_limit} Deg F." ) end if oa_db_override_temp < low_limit runner . registerWarning ( "Value of OA temp of #{oa_db_override_temp} Deg F for loop override is lower then lower warning limit of #{low_limit} Deg F." ) end oa_db_override_temp_SI = OpenStudio . convert ( oa_db_override_temp , "F" , "C" ) apply_to_all_plantloops = false selected_plantloop = nil if condensor_plant_loop_objects . empty? handle = runner . getStringArgumentValue ( 'condensor_plant_loop_objects' , user_arguments ) if handle . empty? runner . registerError ( 'No plant loop was chosen.' ) return false else runner . registerError ( "The selected plant loop with handle '#{handle}' was not found in the model. It may have been removed by another measure." ) return false end else if ! condensor_plant_loop_objects . get . to_PlantLoop . empty? selected_plantloop = condensor_plant_loop_objects . get . to_PlantLoop . get elsif ! condensor_plant_loop_objects . get . to_Building . empty? apply_to_all_plantloops = true else runner . registerError ( 'Script Error - argument not showing up as an air loop.' ) return false end end selected_plantloops = [ ] if apply_to_all_plantloops == true model . getPlantLoops . each do | each_plantloop | if each_plantloop . sizingPlant . loopType == "Condenser" show_loop = true end if show_loop == true selected_plantloops << each_plantloop end end else selected_plantloops << selected_plantloop end if selected_plantloops . length == 0 runner . registerAsNotApplicable ( "Model contains no 'qualified' PlantLoops for this measure to modify." ) return true end counter = 0 ems_oa_db_sensor = nil ems_control_tower_loop_operation_prgm = nil ems_prgm_calling_mngr = nil ems_oa_db_sensor = OpenStudio :: Model :: EnergyManagementSystemSensor . new ( model , "Site Outdoor Air Drybulb Temperature" ) ems_oa_db_sensor . setName ( "OutdoorTemp" ) ems_oa_db_sensor . setKeyName ( "Environment" ) if verbose_info_statements == true runner . registerInfo ( "EMS Sensor object named #{ems_oa_db_sensor.name} added to the model to represent the 'Site Outdoor Air Drybulb Temperature'." ) end ems_control_tower_loop_operation_prgm = OpenStudio :: Model :: EnergyManagementSystemProgram . new ( model ) ems_control_tower_loop_operation_prgm . setName ( "TowerControl" ) if verbose_info_statements == true runner . registerInfo ( "EMS Program object named '#{ems_control_tower_loop_operation_prgm.name}' added to control condensor plant loop operation." ) end ems_prgm_calling_mngr = OpenStudio :: Model :: EnergyManagementSystemProgramCallingManager . new ( model ) ems_prgm_calling_mngr . setName ( "Condenser OnOff Management" ) ems_prgm_calling_mngr . setCallingPoint ( "InsideHVACSystemIterationLoop" ) ems_prgm_calling_mngr . addProgram ( ems_control_tower_loop_operation_prgm ) if verbose_info_statements == true runner . registerInfo ( "EMS Program Calling Manager object named '#{ems_prgm_calling_mngr.name}' added to call #{ems_control_tower_loop_operation_prgm.name} EMS program." ) end selected_plantloops . each do | plantloop | pump = nil counter += 1 plantloop . supplyComponents . each do | supply_comp | if not supply_comp . to_PumpConstantSpeed . empty? pump = supply_comp . to_PumpConstantSpeed . get end if not supply_comp . to_PumpVariableSpeed . empty? pump = supply_comp . to_PumpVariableSpeed . get end end pump_flow_override_report = OpenStudio :: Model :: EnergyManagementSystemGlobalVariable . new ( model , "PumpFlowOverrideReport#{counter}" ) if verbose_info_statements == true runner . registerInfo ( "EMS Global Variable named '#{pump_flow_override_report.name}' to hold a pump flow override report value added to model." ) end plantloop_ems_actuator = OpenStudio :: Model :: EnergyManagementSystemActuator . new ( plantloop , "Plant Loop Overall" , "On/Off Supervisory" ) plantloop_ems_actuator . setName ( "#{plantloop.name}Actuator_Loop#{counter}" . gsub ( "-" , "_" ) ) if verbose_info_statements == true runner . registerInfo ( "An EMS Actuator Object named '#{plantloop_ems_actuator.name}' representing a way to set a plantloop on/off supervisory control status has been added to model." ) end pump_flow_override_ems_actuator = OpenStudio :: Model :: EnergyManagementSystemActuator . new ( pump , "Pump" , "Pump Mass Flow Rate" ) pump_flow_override_ems_actuator . setName ( "#{plantloop.name}PumpFlowOverride#{counter}" . gsub ( "-" , "_" ) ) if verbose_info_statements == true runner . registerInfo ( "An EMS Actuator Object named '#{pump_flow_override_ems_actuator.name}' representing a way to override the condensor loop pump on/off status has been added to model." ) end ems_cond_flow_override_on_EMS_output_var = OpenStudio :: Model :: EnergyManagementSystemOutputVariable . new ( model , pump_flow_override_report ) ems_cond_flow_override_on_EMS_output_var . setName ( "EMS Condenser Flow Override On#{counter}" ) ems_cond_flow_override_on_EMS_output_var . setEMSVariableName ( "#{pump_flow_override_report.name}" ) ems_cond_flow_override_on_EMS_output_var . setTypeOfDataInVariable ( "Averaged" ) ems_cond_flow_override_on_EMS_output_var . setUpdateFrequency ( "SystemTimeStep" ) ems_cond_flow_override_on_EMS_output_var . setUnits ( "On/Off" ) ems_control_tower_loop_operation_prgm . addLine ( "IF (#{ems_oa_db_sensor.name} < 6.0)" ) ems_control_tower_loop_operation_prgm . addLine ( "SET #{plantloop_ems_actuator.name} = 0.0" ) ems_control_tower_loop_operation_prgm . addLine ( "SET #{pump_flow_override_ems_actuator.name} = 0.0" ) ems_control_tower_loop_operation_prgm . addLine ( "SET #{ems_cond_flow_override_on_EMS_output_var.name} = 1.0" ) ems_control_tower_loop_operation_prgm . addLine ( "ELSE" ) ems_control_tower_loop_operation_prgm . addLine ( "SET #{plantloop_ems_actuator.name} = Null" ) ems_control_tower_loop_operation_prgm . addLine ( "SET #{pump_flow_override_ems_actuator.name} = Null" ) ems_control_tower_loop_operation_prgm . addLine ( "SET #{ems_cond_flow_override_on_EMS_output_var.name} = 0.0" ) ems_control_tower_loop_operation_prgm . addLine ( "ENDIF" ) output_var = OpenStudio :: Model :: OutputVariable . new ( "#{ems_cond_flow_override_on_EMS_output_var.name}" , model ) output_var . setName ( "#{ems_cond_flow_override_on_EMS_output_var.name}" ) output_var . setKeyValue ( "*" ) output_var . setReportingFrequency ( "Hourly" ) end output_EMS = model . getOutputEnergyManagementSystem output_EMS . setInternalVariableAvailabilityDictionaryReporting ( 'internal_variable_availability_dictionary_reporting' ) output_EMS . setEMSRuntimeLanguageDebugOutputLevel ( 'ems_runtime_language_debug_output_level' ) output_EMS . setActuatorAvailabilityDictionaryReporting ( 'actuator_availability_dictionary_reporting' ) runner . registerInfo ( "Output EMS Program Object configured for model." ) runner . registerFinalCondition ( "Measure finished with #{model.getEnergyManagementSystemSensors.count} EMS sensors, #{model.getEnergyManagementSystemActuators.count} EMS Actuators, #{model.getEnergyManagementSystemPrograms.count} EMS Programs, #{model.getEnergyManagementSystemSubroutines.count} EMS Subroutines, #{model.getEnergyManagementSystemProgramCallingManagers.count} EMS Program Calling Manager objects" ) end
define what happens when the measure is run
define what happens when the measure is run
# use the built-in error checking # assign the user inputs to variables # model is passed in because of argument type # check the plantloops for existence in model # define selected plantloop(s), depending on user input, add selected plantloop(s) to an array # end loop through plantloops        # declare variables for proper scope #Create new EMS Sensor Object representing Site Outdoor Air Drybulb Temperature # Create a 'stub' object for the EnergyManagementSystem:Program object for actuation of the condensor loops and re-setting pump flows # Create a new EnergyManagementSystem:ProgramCallingManager object configured to call the EMS program # Loop through selected plantloops # get pump object associated with condenser loop # end loop through supply components # Create new EnergyManagementSystem:GlobalVariable object and configure to hold the value for PumpFlowOverrideReport # Create new EMS Actuator Object representing plant loop supervisory on/off control  # Create new EMS Actuator Object representing condenser loop pump flow override (on/off) control # Create new EMS Output Variable Object holding the PumpFlowOverrideReport # Add logic to the EMS program as we iterate through the selected condenser plantloop # end loop through plantloops # create OutputEnergyManagementSystem object (a 'unique' object) and configure to allow EMS reporting # TODO - add 19 additional output variables from the E+ EMS example "EMSPlantLoopOverrideControl.idf", perhaps using boolean measure arguments for adding them.  #1 Site Outdoor Air Drybulb Temperature #2 Cooling Tower Inlet Temperature #3 Cooling Tower Outlet Temperature #4 Cooling Tower Mass Flow Rate #5 Cooling Tower Heat Transfer Rate #6 Cooling Tower Fan Electric Power #7 Zone Air Temperature #8 Pump Electric Power #9 Pump Outlet Temperature #10 Pump Mass Flow Rate #11 Plant Supply Side Cooling Demand Rate #12 Plant Supply Side Heating Demand Rate #13 Plant Supply Side Inlet Mass Flow Rate #14 Plant Supply Side Inlet Temperature #15 Plant Supply Side Outlet Temperature
model
<not_specific>
runner
<not_specific>
user_arguments
<not_specific>