From e287a65a6b82d5aa380a60a8cb21d09d7f268e9a Mon Sep 17 00:00:00 2001 From: Joe Robertson Date: Tue, 13 Aug 2019 09:38:25 -0600 Subject: [PATCH 01/11] Add argument spec for timeseries measure. --- buildstockbatch/schemas/v0.1.yaml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/buildstockbatch/schemas/v0.1.yaml b/buildstockbatch/schemas/v0.1.yaml index 10dae077..781471f4 100644 --- a/buildstockbatch/schemas/v0.1.yaml +++ b/buildstockbatch/schemas/v0.1.yaml @@ -7,7 +7,7 @@ eagle: include('hpc-spec', required=False) output_directory: str(required=False) sys_image_dir: str(required=False) baseline: include('sim-spec', required=True) -timeseries_csv_export: map(required=False) +timeseries_csv_export: include('timeseries-csv-export-spec', required=False) upgrades: list(include('upgrade-spec'), required=False) downselect: include('downselect-spec',required=False) postprocessing: include('postprocessing-spec', required=False) @@ -85,4 +85,8 @@ residential-simulation-spec: begin_day_of_month: int(required=False) end_month: int(required=False) end_day_of_month: int(required=False) - calendar_year: int(required=False) \ No newline at end of file + calendar_year: int(required=False) +timeseries-csv-export-spec: + reporting_frequency: str(required=False) + include_enduse_subcategories: bool(required=False) + output_variables: list(required=False) From 37dfeda9230ccbc543f45de25b18df6da7dee4ad Mon Sep 17 00:00:00 2001 From: Joe Robertson Date: Tue, 13 Aug 2019 09:39:22 -0600 Subject: [PATCH 02/11] Add validation for measure existence and arguments. --- buildstockbatch/base.py | 85 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) diff --git a/buildstockbatch/base.py b/buildstockbatch/base.py index cd0f253e..2c5385be 100644 --- a/buildstockbatch/base.py +++ b/buildstockbatch/base.py @@ -284,6 +284,7 @@ def cleanup_sim_dir(sim_dir): def validate_project(project_file): assert(BuildStockBatchBase.validate_project_schema(project_file)) assert(BuildStockBatchBase.validate_xor_schema_keys(project_file)) + assert(BuildStockBatchBase.validate_measures_and_arguments(project_file)) assert(BuildStockBatchBase.validate_options_lookup(project_file)) logger.info('Base Validation Successful') return True @@ -324,6 +325,90 @@ def validate_xor_schema_keys(project_file): raise ValueError('Both/neither n_datapoints and buildstock_csv found in yaml baseline key') return True + def validate_measures_and_arguments(project_file): + import xml.etree.ElementTree as ET + + cfg = BuildStockBatchBase.get_project_configuration(project_file) + buildstock_dir = os.path.join(os.path.dirname(project_file), cfg["buildstock_directory"]) + measures_dir = f'{buildstock_dir}/measures' + type_map = {'Integer': int, 'Boolean': bool, 'String': str, 'Double': float} + + measure_names = { + 'ResidentialSimulationControls': 'residential_simulation_controls', + 'BuildExistingModel': 'baseline', + 'SimulationOutputReport': 'simulation_output_report', + 'ServerDirectoryCleanup': None, + 'ApplyUpgrade': 'upgrades', + 'TimeseriesCSVExport': 'timeseries_csv_export' + } + for reporting_measure in cfg['reporting_measures']: + measure_names[reporting_measure] = 'reporting_measures' + + def get_measure_xml(xml_path): + tree = ET.parse(xml_path) + root = tree.getroot() + return root + + error_msgs = '' + for measure_name in measure_names.keys(): + measure_path = os.path.join(measures_dir, measure_name) + + if measure_names[measure_name] in cfg.keys(): + if not os.path.exists(measure_path): + error_msgs += f"* {measure_name} does not exist in {buildstock_dir}. \n" + + if measure_name in ['ResidentialSimulationControls', 'TimeseriesCSVExport']: + root = get_measure_xml(os.path.join(measure_path, 'measure.xml')) + + expected_arguments = {} + for argument in root.findall('./arguments/argument'): + for name in argument.findall('./name'): + expected_arguments[name.text] = [] + + if argument.find('./type').text == 'Choice': + for choice in argument.findall('./choices/choice'): + for value in choice.findall('./value'): + expected_arguments[name.text].append(value.text) + else: + expected_arguments[name.text].append(argument.find('./type').text) + + for actual_argument_key in cfg[measure_names[measure_name]].keys(): + if actual_argument_key not in expected_arguments.keys(): + error_msgs += f"* Found unexpected argument key {actual_argument_key} for \ + {measure_names[measure_name]} in yaml file. \n" + + actual_argument_value = cfg[measure_names[measure_name]][actual_argument_key] + + if actual_argument_key in expected_arguments.keys(): + expected_argument_type = expected_arguments[actual_argument_key] + + try: + if type(actual_argument_value) != list: + if not isinstance(actual_argument_value, type_map[expected_argument_type[0]]): + error_msgs += f"* Wrong argument value type for {actual_argument_key} for \ + {measure_names[measure_name]} in yaml file. \n" + else: + for actual_argument_val in actual_argument_value: + if not isinstance(actual_argument_val, type_map[expected_argument_type[0]]): + error_msgs += f"* Wrong argument value type for {actual_argument_key} for \ + {measure_names[measure_name]} in yaml file. \n" + + except KeyError: + if len(expected_argument_type) > 1: # Choice + if actual_argument_value not in expected_argument_type: + error_msgs += f"* Found unexpected argument value {actual_argument_value} for \ + {measure_names[measure_name]} in yaml file. \n" + else: + print(f"Found an unexpected argument value type: {expected_argument_type[0]}.") + + if not error_msgs: + return True + else: + logger.error(error_msgs) + raise ValueError(error_msgs) + + return True + @staticmethod def validate_options_lookup(project_file): """ From 6bbffde87038ba466c09cfd68e30fcb74f3e6b01 Mon Sep 17 00:00:00 2001 From: Joe Robertson Date: Tue, 13 Aug 2019 09:39:37 -0600 Subject: [PATCH 03/11] Add tests for measure validation. --- .../enforce-validate-measures-bad.yml | 33 + .../enforce-validate-measures-good.yml | 35 + .../measures/ApplyUpgrade/measure.rb | 329 ++ .../measures/ApplyUpgrade/measure.xml | 4735 +++++++++++++++++ .../measures/BuildExistingModel/measure.rb | 225 + .../measures/BuildExistingModel/measure.xml | 79 + .../ResidentialSimulationControls/measure.rb | 148 + .../ResidentialSimulationControls/measure.xml | 99 + .../ServerDirectoryCleanup/measure.rb | 83 + .../ServerDirectoryCleanup/measure.xml | 43 + .../SimulationOutputReport/measure.rb | 1115 ++++ .../SimulationOutputReport/measure.xml | 694 +++ .../measures/TimeseriesCSVExport/measure.rb | 778 +++ .../measures/TimeseriesCSVExport/measure.xml | 103 + buildstockbatch/test/test_validation.py | 24 + 15 files changed, 8523 insertions(+) create mode 100644 buildstockbatch/test/test_inputs/enforce-validate-measures-bad.yml create mode 100644 buildstockbatch/test/test_inputs/enforce-validate-measures-good.yml create mode 100644 buildstockbatch/test/test_inputs/test_openstudio_buildstock/measures/ApplyUpgrade/measure.rb create mode 100644 buildstockbatch/test/test_inputs/test_openstudio_buildstock/measures/ApplyUpgrade/measure.xml create mode 100644 buildstockbatch/test/test_inputs/test_openstudio_buildstock/measures/BuildExistingModel/measure.rb create mode 100644 buildstockbatch/test/test_inputs/test_openstudio_buildstock/measures/BuildExistingModel/measure.xml create mode 100644 buildstockbatch/test/test_inputs/test_openstudio_buildstock/measures/ResidentialSimulationControls/measure.rb create mode 100644 buildstockbatch/test/test_inputs/test_openstudio_buildstock/measures/ResidentialSimulationControls/measure.xml create mode 100644 buildstockbatch/test/test_inputs/test_openstudio_buildstock/measures/ServerDirectoryCleanup/measure.rb create mode 100644 buildstockbatch/test/test_inputs/test_openstudio_buildstock/measures/ServerDirectoryCleanup/measure.xml create mode 100644 buildstockbatch/test/test_inputs/test_openstudio_buildstock/measures/SimulationOutputReport/measure.rb create mode 100644 buildstockbatch/test/test_inputs/test_openstudio_buildstock/measures/SimulationOutputReport/measure.xml create mode 100644 buildstockbatch/test/test_inputs/test_openstudio_buildstock/measures/TimeseriesCSVExport/measure.rb create mode 100644 buildstockbatch/test/test_inputs/test_openstudio_buildstock/measures/TimeseriesCSVExport/measure.xml diff --git a/buildstockbatch/test/test_inputs/enforce-validate-measures-bad.yml b/buildstockbatch/test/test_inputs/enforce-validate-measures-bad.yml new file mode 100644 index 00000000..366e8f22 --- /dev/null +++ b/buildstockbatch/test/test_inputs/enforce-validate-measures-bad.yml @@ -0,0 +1,33 @@ +buildstock_directory: test_openstudio_buildstock +project_directory: project_singlefamilydetached +baseline: + n_datapoints: 30 + n_buildings_represented: 81221016 +residential_simulation_controls: + timesteps_per_hr: 4 + begin_month: 1 + begin_day_of_month: 1.5 + end_month: 12 + end_day_of_month: 31 +upgrades: + - upgrade_name: good upgrade + options: + - option: Vintage|<1940 + apply_logic: + - or: + - Insulation Slab|Good Option + - Insulation Slab|None + - not: Insulation Wall|Good Option + - and: + - Vintage|1960s||Vintage|1960s + - Vintage|1980s + - option: Insulation Finished Basement|Good Option + apply_logic: + - Insulation Unfinished Basement|Extra Argument +timeseries_csv_export: + reporting_frequency: Huorly + include_enduse_subcategories: true + output_variable: + - Zone Mean Air Temperature +reporting_measures: + - ReportingMeasure2 diff --git a/buildstockbatch/test/test_inputs/enforce-validate-measures-good.yml b/buildstockbatch/test/test_inputs/enforce-validate-measures-good.yml new file mode 100644 index 00000000..edc5bd12 --- /dev/null +++ b/buildstockbatch/test/test_inputs/enforce-validate-measures-good.yml @@ -0,0 +1,35 @@ +buildstock_directory: test_openstudio_buildstock +project_directory: project_singlefamilydetached +baseline: + n_datapoints: 30 + n_buildings_represented: 81221016 +residential_simulation_controls: + timesteps_per_hr: 4 + begin_month: 1 + begin_day_of_month: 1 + end_month: 12 + end_day_of_month: 31 + calendar_year: 2016 +upgrades: + - upgrade_name: good upgrade + options: + - option: Vintage|<1940 + apply_logic: + - or: + - Insulation Slab|Good Option + - Insulation Slab|None + - not: Insulation Wall|Good Option + - and: + - Vintage|1960s||Vintage|1960s + - Vintage|1980s + - option: Insulation Finished Basement|Good Option + apply_logic: + - Insulation Unfinished Basement|Extra Argument + package_apply_logic: Vintage|1960s||Vintage|1940s +timeseries_csv_export: + reporting_frequency: Timestep + include_enduse_subcategories: true + output_variables: + - Zone Mean Air Temperature +reporting_measures: + - ReportingMeasure1 diff --git a/buildstockbatch/test/test_inputs/test_openstudio_buildstock/measures/ApplyUpgrade/measure.rb b/buildstockbatch/test/test_inputs/test_openstudio_buildstock/measures/ApplyUpgrade/measure.rb new file mode 100644 index 00000000..8aa70287 --- /dev/null +++ b/buildstockbatch/test/test_inputs/test_openstudio_buildstock/measures/ApplyUpgrade/measure.rb @@ -0,0 +1,329 @@ +# see the URL below for information on how to write OpenStudio measures +# http://nrel.github.io/OpenStudio-user-documentation/measures/measure_writing_guide/ + +# Adapted from Measure Picker measure +# https://github.com/NREL/OpenStudio-measures/blob/develop/NREL%20working%20measures/measure_picker/measure.rb + +require 'csv' +require 'openstudio' + +require 'openstudio' +if File.exists? File.absolute_path(File.join(File.dirname(__FILE__), "../../lib/resources/measures/HPXMLtoOpenStudio/resources")) # Hack to run ResStock on AWS + resources_path = File.absolute_path(File.join(File.dirname(__FILE__), "../../lib/resources/measures/HPXMLtoOpenStudio/resources")) +elsif File.exists? File.absolute_path(File.join(File.dirname(__FILE__), "../../resources/measures/HPXMLtoOpenStudio/resources")) # Hack to run ResStock unit tests locally + resources_path = File.absolute_path(File.join(File.dirname(__FILE__), "../../resources/measures/HPXMLtoOpenStudio/resources")) +elsif File.exists? File.join(OpenStudio::BCLMeasure::userMeasuresDir.to_s, "HPXMLtoOpenStudio/resources") # Hack to run measures in the OS App since applied measures are copied off into a temporary directory + resources_path = File.join(OpenStudio::BCLMeasure::userMeasuresDir.to_s, "HPXMLtoOpenStudio/resources") +else + resources_path = File.absolute_path(File.join(File.dirname(__FILE__), "../HPXMLtoOpenStudio/resources")) +end +require File.join(resources_path, "constants") + +# start the measure +class ApplyUpgrade < OpenStudio::Ruleset::ModelUserScript + # human readable name + def name + return "Apply Upgrade" + end + + # human readable description + def description + return "Measure that applies an upgrade (one or more child measures) to a building model based on the specified logic." + end + + # human readable description of modeling approach + def modeler_description + return "Determines if the upgrade should apply to a given building model. If so, calls one or more child measures with the appropriate arguments." + end + + def num_options + return Constants.NumApplyUpgradeOptions # Synced with SimulationOutputReport measure + end + + def num_costs_per_option + return Constants.NumApplyUpgradesCostsPerOption # Synced with SimulationOutputReport measure + end + + # define the arguments that the user will input + def arguments(model) + args = OpenStudio::Ruleset::OSArgumentVector.new + + # Make string arg for upgrade name + upgrade_name = OpenStudio::Ruleset::OSArgument::makeStringArgument("upgrade_name", true) + upgrade_name.setDisplayName("Upgrade Name") + upgrade_name.setDescription("User-specificed name that describes the upgrade.") + upgrade_name.setDefaultValue("My Upgrade") + args << upgrade_name + + for option_num in 1..num_options + + # Option name argument + option = OpenStudio::Ruleset::OSArgument.makeStringArgument("option_#{option_num}", (option_num == 1)) + option.setDisplayName("Option #{option_num}") + option.setDescription("Specify the parameter|option as found in resources\\options_lookup.tsv.") + args << option + + # Option Apply Logic argument + option_apply_logic = OpenStudio::Ruleset::OSArgument.makeStringArgument("option_#{option_num}_apply_logic", false) + option_apply_logic.setDisplayName("Option #{option_num} Apply Logic") + option_apply_logic.setDescription("Logic that specifies if the Option #{option_num} upgrade will apply based on the existing building's options. Specify one or more parameter|option as found in resources\\options_lookup.tsv. When multiple are included, they must be separated by '||' for OR and '&&' for AND, and using parentheses as appropriate. Prefix an option with '!' for not.") + args << option_apply_logic + + for cost_num in 1..num_costs_per_option + + # Option Cost Value argument + cost_value = OpenStudio::Ruleset::OSArgument.makeDoubleArgument("option_#{option_num}_cost_#{cost_num}_value", false) + cost_value.setDisplayName("Option #{option_num} Cost #{cost_num} Value") + cost_value.setDescription("Total option #{option_num} cost is the sum of all: (Cost N Value) x (Cost N Multiplier).") + cost_value.setUnits("$") + args << cost_value + + # Option Cost Multiplier argument + choices = [ + "", + "Fixed (1)", + "Wall Area, Above-Grade, Conditioned (ft^2)", + "Wall Area, Above-Grade, Exterior (ft^2)", + "Wall Area, Below-Grade (ft^2)", + "Floor Area, Conditioned (ft^2)", + "Floor Area, Attic (ft^2)", + "Floor Area, Lighting (ft^2)", + "Roof Area (ft^2)", + "Window Area (ft^2)", + "Door Area (ft^2)", + "Duct Surface Area (ft^2)", + "Size, Heating System (kBtu/h)", + "Size, Cooling System (kBtu/h)", + "Size, Water Heater (gal)", + ] + cost_multiplier = OpenStudio::Ruleset::OSArgument.makeChoiceArgument("option_#{option_num}_cost_#{cost_num}_multiplier", choices, false) + cost_multiplier.setDisplayName("Option #{option_num} Cost #{cost_num} Multiplier") + cost_multiplier.setDescription("Total option #{option_num} cost is the sum of all: (Cost N Value) x (Cost N Multiplier).") + cost_multiplier.setDefaultValue(choices[0]) + args << cost_multiplier + + end + + # Option Lifetime argument + option_lifetime = OpenStudio::Ruleset::OSArgument.makeDoubleArgument("option_#{option_num}_lifetime", false) + option_lifetime.setDisplayName("Option #{option_num} Lifetime") + option_lifetime.setDescription("The option lifetime.") + option_lifetime.setUnits("years") + args << option_lifetime + + end + + # Package Apply Logic argument + package_apply_logic = OpenStudio::Ruleset::OSArgument.makeStringArgument("package_apply_logic", false) + package_apply_logic.setDisplayName("Package Apply Logic") + package_apply_logic.setDescription("Logic that specifies if the entire package upgrade (all options) will apply based on the existing building's options. Specify one or more parameter|option as found in resources\\options_lookup.tsv. When multiple are included, they must be separated by '||' for OR and '&&' for AND, and using parentheses as appropriate. Prefix an option with '!' for not.") + args << package_apply_logic + + # Make integer arg to run measure [1 is run, 0 is no run] + run_measure = OpenStudio::Ruleset::OSArgument::makeIntegerArgument("run_measure", true) + run_measure.setDisplayName("Run Measure") + run_measure.setDescription("integer argument to run measure [1 is run, 0 is no run]") + run_measure.setDefaultValue(1) + args << run_measure + + return args + end + + # define what happens when the measure is run + def run(model, runner, user_arguments) + super(model, runner, user_arguments) + + # use the built-in error checking + if !runner.validateUserArguments(arguments(model), user_arguments) + return false + end + + # Return N/A if not selected to run + run_measure = runner.getIntegerArgumentValue("run_measure", user_arguments) + if run_measure == 0 + runner.registerAsNotApplicable("Run Measure set to #{run_measure}.") + return true + end + + upgrade_name = runner.getStringArgumentValue("upgrade_name", user_arguments) + + # Retrieve Option X argument values + options = {} + for option_num in 1..num_options + if option_num == 1 + arg = runner.getStringArgumentValue("option_#{option_num}", user_arguments) + else + arg = runner.getOptionalStringArgumentValue("option_#{option_num}", user_arguments) + next if not arg.is_initialized + + arg = arg.get + end + next if arg.strip.size == 0 + + if not arg.include?('|') + runner.registerError("Option #{option_num} is missing the '|' delimiter.") + return false + end + options[option_num] = arg.strip + end + + # Retrieve Option X Apply Logic argument values + options_apply_logic = {} + for option_num in 1..num_options + arg = runner.getOptionalStringArgumentValue("option_#{option_num}_apply_logic", user_arguments) + next if not arg.is_initialized + + arg = arg.get + next if arg.strip.size == 0 + + if not arg.include?('|') + runner.registerError("Option #{option_num} Apply Logic is missing the '|' delimiter.") + return false + end + if not options.keys.include?(option_num) + runner.registerError("Option #{option_num} Apply Logic was provided, but a corresponding Option #{option_num} was not provided.") + return false + end + options_apply_logic[option_num] = arg.strip + end + + # Retrieve Package Apply Logic argument value + arg = runner.getOptionalStringArgumentValue("package_apply_logic", user_arguments) + if not arg.is_initialized + package_apply_logic = nil + else + arg = arg.get + if arg.strip.size == 0 + package_apply_logic = nil + else + if not arg.include?('|') + runner.registerError("Package Apply Logic is missing the '|' delimiter.") + return false + end + package_apply_logic = arg.strip + end + end + + # Get file/dir paths + resources_dir = File.absolute_path(File.join(File.dirname(__FILE__), "..", "..", "lib", "resources")) # Should have been uploaded per 'Additional Analysis Files' in PAT + check_dir_exists(resources_dir, runner) + characteristics_dir = File.absolute_path(File.join(File.dirname(__FILE__), "..", "..", "lib", "housing_characteristics")) # Should have been uploaded per 'Additional Analysis Files' in PAT + check_dir_exists(characteristics_dir, runner) + buildstock_file = File.join(resources_dir, "buildstock.rb") + measures_dir = File.join(resources_dir, "measures") + lookup_file = File.join(resources_dir, "options_lookup.tsv") + + # Load buildstock_file + require File.join(File.dirname(buildstock_file), File.basename(buildstock_file, File.extname(buildstock_file))) + + # Retrieve workflow_json from BuildExistingModel measure if provided + workflow_json = get_value_from_runner_past_results(runner, "workflow_json", "build_existing_model", false) + if not workflow_json.nil? + workflow_json = File.join(resources_dir, workflow_json) + end + + # Process package apply logic if provided + apply_package_upgrade = true + if not package_apply_logic.nil? + # Apply this package? + apply_package_upgrade = evaluate_logic(package_apply_logic, runner) + if apply_package_upgrade.nil? + return false + end + end + + measures = {} + if apply_package_upgrade + + # Obtain measures and arguments to be called + # Process options apply logic if provided + options.each do |option_num, option| + parameter_name, option_name = option.split('|') + + # Apply this option? + apply_option_upgrade = true + if options_apply_logic.include?(option_num) + apply_option_upgrade = evaluate_logic(options_apply_logic[option_num], runner) + if apply_option_upgrade.nil? + return false + end + end + + if not apply_option_upgrade + runner.registerInfo("Parameter #{parameter_name}, Option #{option_name} will not be applied.") + next + end + + # Register this option so that it replaces the existing building option in the results csv file + print_option_assignment(parameter_name, option_name, runner) + register_value(runner, parameter_name, option_name) + + # Register cost values/multipliers/lifetime for applied options; used by the SimulationOutputReport measure + for cost_num in 1..num_costs_per_option + cost_value = runner.getOptionalDoubleArgumentValue("option_#{option_num}_cost_#{cost_num}_value", user_arguments) + if cost_value.nil? + cost_value = 0.0 + end + cost_mult = runner.getStringArgumentValue("option_#{option_num}_cost_#{cost_num}_multiplier", user_arguments) + register_value(runner, "option_#{option_num}_cost_#{cost_num}_value_to_apply", cost_value.to_s) + register_value(runner, "option_#{option_num}_cost_#{cost_num}_multiplier_to_apply", cost_mult) + end + lifetime = runner.getOptionalDoubleArgumentValue("option_#{option_num}_lifetime", user_arguments) + if lifetime.nil? + lifetime = 0.0 + end + register_value(runner, "option_#{option_num}_lifetime_to_apply", lifetime.to_s) + + # Check file/dir paths exist + check_file_exists(lookup_file, runner) + + # Get measure name and arguments associated with the option + options_measure_args = get_measure_args_from_option_names(lookup_file, [option_name], parameter_name, runner) + options_measure_args[option_name].each do |measure_subdir, args_hash| + update_args_hash(measures, measure_subdir, args_hash, add_new = false) + end + end + + # Add measure arguments from existing building if needed + parameters = get_parameters_ordered_from_options_lookup_tsv(lookup_file, characteristics_dir) + measures.keys.each do |measure_subdir| + parameters.each do |parameter_name| + existing_option_name = get_value_from_runner_past_results(runner, parameter_name, "build_existing_model") + + options_measure_args = get_measure_args_from_option_names(lookup_file, [existing_option_name], parameter_name, runner) + options_measure_args[existing_option_name].each do |measure_subdir2, args_hash| + next if measure_subdir != measure_subdir2 + + # Append any new arguments + new_args_hash = {} + args_hash.each do |k, v| + next if measures[measure_subdir][0].has_key?(k) + + new_args_hash[k] = v + end + update_args_hash(measures, measure_subdir, new_args_hash, add_new = false) + end + end + end + + if not apply_measures(measures_dir, measures, runner, model, workflow_json, "measures-upgrade.osw", true) + return false + end + + end # apply_package_upgrade + + # Register the upgrade name + register_value(runner, "upgrade_name", upgrade_name) + + if measures.size == 0 + # Upgrade not applied; don't re-run existing home simulation + runner.haltWorkflow('Invalid') + return false + end + + return true + end +end + +# register the measure to be used by the application +ApplyUpgrade.new.registerWithApplication diff --git a/buildstockbatch/test/test_inputs/test_openstudio_buildstock/measures/ApplyUpgrade/measure.xml b/buildstockbatch/test/test_inputs/test_openstudio_buildstock/measures/ApplyUpgrade/measure.xml new file mode 100644 index 00000000..ae690f2c --- /dev/null +++ b/buildstockbatch/test/test_inputs/test_openstudio_buildstock/measures/ApplyUpgrade/measure.xml @@ -0,0 +1,4735 @@ + + 3.0 + apply_upgrade + 33f1654c-f734-43d1-b35d-9d2856e41b5a + 48b4badc-12ca-411c-ad2c-97e10ec5e7f3 + 20190715T223325Z + 9339BE01 + ApplyUpgrade + Apply Upgrade + Measure that applies an upgrade (one or more child measures) to a building model based on the specified logic. + Determines if the upgrade should apply to a given building model. If so, calls one or more child measures with the appropriate arguments. + + + upgrade_name + Upgrade Name + User-specificed name that describes the upgrade. + String + true + false + My Upgrade + + + option_1 + Option 1 + Specify the parameter|option as found in resources\options_lookup.tsv. + String + true + false + + + option_1_apply_logic + Option 1 Apply Logic + Logic that specifies if the Option 1 upgrade will apply based on the existing building's options. Specify one or more parameter|option as found in resources\options_lookup.tsv. When multiple are included, they must be separated by '||' for OR and '&&' for AND, and using parentheses as appropriate. Prefix an option with '!' for not. + String + false + false + + + option_1_cost_1_value + Option 1 Cost 1 Value + Total option 1 cost is the sum of all: (Cost N Value) x (Cost N Multiplier). + Double + $ + false + false + + + option_1_cost_1_multiplier + Option 1 Cost 1 Multiplier + Total option 1 cost is the sum of all: (Cost N Value) x (Cost N Multiplier). + Choice + false + false + + + + + + + + Fixed (1) + Fixed (1) + + + Wall Area, Above-Grade, Conditioned (ft^2) + Wall Area, Above-Grade, Conditioned (ft^2) + + + Wall Area, Above-Grade, Exterior (ft^2) + Wall Area, Above-Grade, Exterior (ft^2) + + + Wall Area, Below-Grade (ft^2) + Wall Area, Below-Grade (ft^2) + + + Floor Area, Conditioned (ft^2) + Floor Area, Conditioned (ft^2) + + + Floor Area, Attic (ft^2) + Floor Area, Attic (ft^2) + + + Floor Area, Lighting (ft^2) + Floor Area, Lighting (ft^2) + + + Roof Area (ft^2) + Roof Area (ft^2) + + + Window Area (ft^2) + Window Area (ft^2) + + + Door Area (ft^2) + Door Area (ft^2) + + + Duct Surface Area (ft^2) + Duct Surface Area (ft^2) + + + Size, Heating System (kBtu/h) + Size, Heating System (kBtu/h) + + + Size, Cooling System (kBtu/h) + Size, Cooling System (kBtu/h) + + + Size, Water Heater (gal) + Size, Water Heater (gal) + + + + + option_1_cost_2_value + Option 1 Cost 2 Value + Total option 1 cost is the sum of all: (Cost N Value) x (Cost N Multiplier). + Double + $ + false + false + + + option_1_cost_2_multiplier + Option 1 Cost 2 Multiplier + Total option 1 cost is the sum of all: (Cost N Value) x (Cost N Multiplier). + Choice + false + false + + + + + + + + Fixed (1) + Fixed (1) + + + Wall Area, Above-Grade, Conditioned (ft^2) + Wall Area, Above-Grade, Conditioned (ft^2) + + + Wall Area, Above-Grade, Exterior (ft^2) + Wall Area, Above-Grade, Exterior (ft^2) + + + Wall Area, Below-Grade (ft^2) + Wall Area, Below-Grade (ft^2) + + + Floor Area, Conditioned (ft^2) + Floor Area, Conditioned (ft^2) + + + Floor Area, Attic (ft^2) + Floor Area, Attic (ft^2) + + + Floor Area, Lighting (ft^2) + Floor Area, Lighting (ft^2) + + + Roof Area (ft^2) + Roof Area (ft^2) + + + Window Area (ft^2) + Window Area (ft^2) + + + Door Area (ft^2) + Door Area (ft^2) + + + Duct Surface Area (ft^2) + Duct Surface Area (ft^2) + + + Size, Heating System (kBtu/h) + Size, Heating System (kBtu/h) + + + Size, Cooling System (kBtu/h) + Size, Cooling System (kBtu/h) + + + Size, Water Heater (gal) + Size, Water Heater (gal) + + + + + option_1_lifetime + Option 1 Lifetime + The option lifetime. + Double + years + false + false + + + option_2 + Option 2 + Specify the parameter|option as found in resources\options_lookup.tsv. + String + false + false + + + option_2_apply_logic + Option 2 Apply Logic + Logic that specifies if the Option 2 upgrade will apply based on the existing building's options. Specify one or more parameter|option as found in resources\options_lookup.tsv. When multiple are included, they must be separated by '||' for OR and '&&' for AND, and using parentheses as appropriate. Prefix an option with '!' for not. + String + false + false + + + option_2_cost_1_value + Option 2 Cost 1 Value + Total option 2 cost is the sum of all: (Cost N Value) x (Cost N Multiplier). + Double + $ + false + false + + + option_2_cost_1_multiplier + Option 2 Cost 1 Multiplier + Total option 2 cost is the sum of all: (Cost N Value) x (Cost N Multiplier). + Choice + false + false + + + + + + + + Fixed (1) + Fixed (1) + + + Wall Area, Above-Grade, Conditioned (ft^2) + Wall Area, Above-Grade, Conditioned (ft^2) + + + Wall Area, Above-Grade, Exterior (ft^2) + Wall Area, Above-Grade, Exterior (ft^2) + + + Wall Area, Below-Grade (ft^2) + Wall Area, Below-Grade (ft^2) + + + Floor Area, Conditioned (ft^2) + Floor Area, Conditioned (ft^2) + + + Floor Area, Attic (ft^2) + Floor Area, Attic (ft^2) + + + Floor Area, Lighting (ft^2) + Floor Area, Lighting (ft^2) + + + Roof Area (ft^2) + Roof Area (ft^2) + + + Window Area (ft^2) + Window Area (ft^2) + + + Door Area (ft^2) + Door Area (ft^2) + + + Duct Surface Area (ft^2) + Duct Surface Area (ft^2) + + + Size, Heating System (kBtu/h) + Size, Heating System (kBtu/h) + + + Size, Cooling System (kBtu/h) + Size, Cooling System (kBtu/h) + + + Size, Water Heater (gal) + Size, Water Heater (gal) + + + + + option_2_cost_2_value + Option 2 Cost 2 Value + Total option 2 cost is the sum of all: (Cost N Value) x (Cost N Multiplier). + Double + $ + false + false + + + option_2_cost_2_multiplier + Option 2 Cost 2 Multiplier + Total option 2 cost is the sum of all: (Cost N Value) x (Cost N Multiplier). + Choice + false + false + + + + + + + + Fixed (1) + Fixed (1) + + + Wall Area, Above-Grade, Conditioned (ft^2) + Wall Area, Above-Grade, Conditioned (ft^2) + + + Wall Area, Above-Grade, Exterior (ft^2) + Wall Area, Above-Grade, Exterior (ft^2) + + + Wall Area, Below-Grade (ft^2) + Wall Area, Below-Grade (ft^2) + + + Floor Area, Conditioned (ft^2) + Floor Area, Conditioned (ft^2) + + + Floor Area, Attic (ft^2) + Floor Area, Attic (ft^2) + + + Floor Area, Lighting (ft^2) + Floor Area, Lighting (ft^2) + + + Roof Area (ft^2) + Roof Area (ft^2) + + + Window Area (ft^2) + Window Area (ft^2) + + + Door Area (ft^2) + Door Area (ft^2) + + + Duct Surface Area (ft^2) + Duct Surface Area (ft^2) + + + Size, Heating System (kBtu/h) + Size, Heating System (kBtu/h) + + + Size, Cooling System (kBtu/h) + Size, Cooling System (kBtu/h) + + + Size, Water Heater (gal) + Size, Water Heater (gal) + + + + + option_2_lifetime + Option 2 Lifetime + The option lifetime. + Double + years + false + false + + + option_3 + Option 3 + Specify the parameter|option as found in resources\options_lookup.tsv. + String + false + false + + + option_3_apply_logic + Option 3 Apply Logic + Logic that specifies if the Option 3 upgrade will apply based on the existing building's options. Specify one or more parameter|option as found in resources\options_lookup.tsv. When multiple are included, they must be separated by '||' for OR and '&&' for AND, and using parentheses as appropriate. Prefix an option with '!' for not. + String + false + false + + + option_3_cost_1_value + Option 3 Cost 1 Value + Total option 3 cost is the sum of all: (Cost N Value) x (Cost N Multiplier). + Double + $ + false + false + + + option_3_cost_1_multiplier + Option 3 Cost 1 Multiplier + Total option 3 cost is the sum of all: (Cost N Value) x (Cost N Multiplier). + Choice + false + false + + + + + + + + Fixed (1) + Fixed (1) + + + Wall Area, Above-Grade, Conditioned (ft^2) + Wall Area, Above-Grade, Conditioned (ft^2) + + + Wall Area, Above-Grade, Exterior (ft^2) + Wall Area, Above-Grade, Exterior (ft^2) + + + Wall Area, Below-Grade (ft^2) + Wall Area, Below-Grade (ft^2) + + + Floor Area, Conditioned (ft^2) + Floor Area, Conditioned (ft^2) + + + Floor Area, Attic (ft^2) + Floor Area, Attic (ft^2) + + + Floor Area, Lighting (ft^2) + Floor Area, Lighting (ft^2) + + + Roof Area (ft^2) + Roof Area (ft^2) + + + Window Area (ft^2) + Window Area (ft^2) + + + Door Area (ft^2) + Door Area (ft^2) + + + Duct Surface Area (ft^2) + Duct Surface Area (ft^2) + + + Size, Heating System (kBtu/h) + Size, Heating System (kBtu/h) + + + Size, Cooling System (kBtu/h) + Size, Cooling System (kBtu/h) + + + Size, Water Heater (gal) + Size, Water Heater (gal) + + + + + option_3_cost_2_value + Option 3 Cost 2 Value + Total option 3 cost is the sum of all: (Cost N Value) x (Cost N Multiplier). + Double + $ + false + false + + + option_3_cost_2_multiplier + Option 3 Cost 2 Multiplier + Total option 3 cost is the sum of all: (Cost N Value) x (Cost N Multiplier). + Choice + false + false + + + + + + + + Fixed (1) + Fixed (1) + + + Wall Area, Above-Grade, Conditioned (ft^2) + Wall Area, Above-Grade, Conditioned (ft^2) + + + Wall Area, Above-Grade, Exterior (ft^2) + Wall Area, Above-Grade, Exterior (ft^2) + + + Wall Area, Below-Grade (ft^2) + Wall Area, Below-Grade (ft^2) + + + Floor Area, Conditioned (ft^2) + Floor Area, Conditioned (ft^2) + + + Floor Area, Attic (ft^2) + Floor Area, Attic (ft^2) + + + Floor Area, Lighting (ft^2) + Floor Area, Lighting (ft^2) + + + Roof Area (ft^2) + Roof Area (ft^2) + + + Window Area (ft^2) + Window Area (ft^2) + + + Door Area (ft^2) + Door Area (ft^2) + + + Duct Surface Area (ft^2) + Duct Surface Area (ft^2) + + + Size, Heating System (kBtu/h) + Size, Heating System (kBtu/h) + + + Size, Cooling System (kBtu/h) + Size, Cooling System (kBtu/h) + + + Size, Water Heater (gal) + Size, Water Heater (gal) + + + + + option_3_lifetime + Option 3 Lifetime + The option lifetime. + Double + years + false + false + + + option_4 + Option 4 + Specify the parameter|option as found in resources\options_lookup.tsv. + String + false + false + + + option_4_apply_logic + Option 4 Apply Logic + Logic that specifies if the Option 4 upgrade will apply based on the existing building's options. Specify one or more parameter|option as found in resources\options_lookup.tsv. When multiple are included, they must be separated by '||' for OR and '&&' for AND, and using parentheses as appropriate. Prefix an option with '!' for not. + String + false + false + + + option_4_cost_1_value + Option 4 Cost 1 Value + Total option 4 cost is the sum of all: (Cost N Value) x (Cost N Multiplier). + Double + $ + false + false + + + option_4_cost_1_multiplier + Option 4 Cost 1 Multiplier + Total option 4 cost is the sum of all: (Cost N Value) x (Cost N Multiplier). + Choice + false + false + + + + + + + + Fixed (1) + Fixed (1) + + + Wall Area, Above-Grade, Conditioned (ft^2) + Wall Area, Above-Grade, Conditioned (ft^2) + + + Wall Area, Above-Grade, Exterior (ft^2) + Wall Area, Above-Grade, Exterior (ft^2) + + + Wall Area, Below-Grade (ft^2) + Wall Area, Below-Grade (ft^2) + + + Floor Area, Conditioned (ft^2) + Floor Area, Conditioned (ft^2) + + + Floor Area, Attic (ft^2) + Floor Area, Attic (ft^2) + + + Floor Area, Lighting (ft^2) + Floor Area, Lighting (ft^2) + + + Roof Area (ft^2) + Roof Area (ft^2) + + + Window Area (ft^2) + Window Area (ft^2) + + + Door Area (ft^2) + Door Area (ft^2) + + + Duct Surface Area (ft^2) + Duct Surface Area (ft^2) + + + Size, Heating System (kBtu/h) + Size, Heating System (kBtu/h) + + + Size, Cooling System (kBtu/h) + Size, Cooling System (kBtu/h) + + + Size, Water Heater (gal) + Size, Water Heater (gal) + + + + + option_4_cost_2_value + Option 4 Cost 2 Value + Total option 4 cost is the sum of all: (Cost N Value) x (Cost N Multiplier). + Double + $ + false + false + + + option_4_cost_2_multiplier + Option 4 Cost 2 Multiplier + Total option 4 cost is the sum of all: (Cost N Value) x (Cost N Multiplier). + Choice + false + false + + + + + + + + Fixed (1) + Fixed (1) + + + Wall Area, Above-Grade, Conditioned (ft^2) + Wall Area, Above-Grade, Conditioned (ft^2) + + + Wall Area, Above-Grade, Exterior (ft^2) + Wall Area, Above-Grade, Exterior (ft^2) + + + Wall Area, Below-Grade (ft^2) + Wall Area, Below-Grade (ft^2) + + + Floor Area, Conditioned (ft^2) + Floor Area, Conditioned (ft^2) + + + Floor Area, Attic (ft^2) + Floor Area, Attic (ft^2) + + + Floor Area, Lighting (ft^2) + Floor Area, Lighting (ft^2) + + + Roof Area (ft^2) + Roof Area (ft^2) + + + Window Area (ft^2) + Window Area (ft^2) + + + Door Area (ft^2) + Door Area (ft^2) + + + Duct Surface Area (ft^2) + Duct Surface Area (ft^2) + + + Size, Heating System (kBtu/h) + Size, Heating System (kBtu/h) + + + Size, Cooling System (kBtu/h) + Size, Cooling System (kBtu/h) + + + Size, Water Heater (gal) + Size, Water Heater (gal) + + + + + option_4_lifetime + Option 4 Lifetime + The option lifetime. + Double + years + false + false + + + option_5 + Option 5 + Specify the parameter|option as found in resources\options_lookup.tsv. + String + false + false + + + option_5_apply_logic + Option 5 Apply Logic + Logic that specifies if the Option 5 upgrade will apply based on the existing building's options. Specify one or more parameter|option as found in resources\options_lookup.tsv. When multiple are included, they must be separated by '||' for OR and '&&' for AND, and using parentheses as appropriate. Prefix an option with '!' for not. + String + false + false + + + option_5_cost_1_value + Option 5 Cost 1 Value + Total option 5 cost is the sum of all: (Cost N Value) x (Cost N Multiplier). + Double + $ + false + false + + + option_5_cost_1_multiplier + Option 5 Cost 1 Multiplier + Total option 5 cost is the sum of all: (Cost N Value) x (Cost N Multiplier). + Choice + false + false + + + + + + + + Fixed (1) + Fixed (1) + + + Wall Area, Above-Grade, Conditioned (ft^2) + Wall Area, Above-Grade, Conditioned (ft^2) + + + Wall Area, Above-Grade, Exterior (ft^2) + Wall Area, Above-Grade, Exterior (ft^2) + + + Wall Area, Below-Grade (ft^2) + Wall Area, Below-Grade (ft^2) + + + Floor Area, Conditioned (ft^2) + Floor Area, Conditioned (ft^2) + + + Floor Area, Attic (ft^2) + Floor Area, Attic (ft^2) + + + Floor Area, Lighting (ft^2) + Floor Area, Lighting (ft^2) + + + Roof Area (ft^2) + Roof Area (ft^2) + + + Window Area (ft^2) + Window Area (ft^2) + + + Door Area (ft^2) + Door Area (ft^2) + + + Duct Surface Area (ft^2) + Duct Surface Area (ft^2) + + + Size, Heating System (kBtu/h) + Size, Heating System (kBtu/h) + + + Size, Cooling System (kBtu/h) + Size, Cooling System (kBtu/h) + + + Size, Water Heater (gal) + Size, Water Heater (gal) + + + + + option_5_cost_2_value + Option 5 Cost 2 Value + Total option 5 cost is the sum of all: (Cost N Value) x (Cost N Multiplier). + Double + $ + false + false + + + option_5_cost_2_multiplier + Option 5 Cost 2 Multiplier + Total option 5 cost is the sum of all: (Cost N Value) x (Cost N Multiplier). + Choice + false + false + + + + + + + + Fixed (1) + Fixed (1) + + + Wall Area, Above-Grade, Conditioned (ft^2) + Wall Area, Above-Grade, Conditioned (ft^2) + + + Wall Area, Above-Grade, Exterior (ft^2) + Wall Area, Above-Grade, Exterior (ft^2) + + + Wall Area, Below-Grade (ft^2) + Wall Area, Below-Grade (ft^2) + + + Floor Area, Conditioned (ft^2) + Floor Area, Conditioned (ft^2) + + + Floor Area, Attic (ft^2) + Floor Area, Attic (ft^2) + + + Floor Area, Lighting (ft^2) + Floor Area, Lighting (ft^2) + + + Roof Area (ft^2) + Roof Area (ft^2) + + + Window Area (ft^2) + Window Area (ft^2) + + + Door Area (ft^2) + Door Area (ft^2) + + + Duct Surface Area (ft^2) + Duct Surface Area (ft^2) + + + Size, Heating System (kBtu/h) + Size, Heating System (kBtu/h) + + + Size, Cooling System (kBtu/h) + Size, Cooling System (kBtu/h) + + + Size, Water Heater (gal) + Size, Water Heater (gal) + + + + + option_5_lifetime + Option 5 Lifetime + The option lifetime. + Double + years + false + false + + + option_6 + Option 6 + Specify the parameter|option as found in resources\options_lookup.tsv. + String + false + false + + + option_6_apply_logic + Option 6 Apply Logic + Logic that specifies if the Option 6 upgrade will apply based on the existing building's options. Specify one or more parameter|option as found in resources\options_lookup.tsv. When multiple are included, they must be separated by '||' for OR and '&&' for AND, and using parentheses as appropriate. Prefix an option with '!' for not. + String + false + false + + + option_6_cost_1_value + Option 6 Cost 1 Value + Total option 6 cost is the sum of all: (Cost N Value) x (Cost N Multiplier). + Double + $ + false + false + + + option_6_cost_1_multiplier + Option 6 Cost 1 Multiplier + Total option 6 cost is the sum of all: (Cost N Value) x (Cost N Multiplier). + Choice + false + false + + + + + + + + Fixed (1) + Fixed (1) + + + Wall Area, Above-Grade, Conditioned (ft^2) + Wall Area, Above-Grade, Conditioned (ft^2) + + + Wall Area, Above-Grade, Exterior (ft^2) + Wall Area, Above-Grade, Exterior (ft^2) + + + Wall Area, Below-Grade (ft^2) + Wall Area, Below-Grade (ft^2) + + + Floor Area, Conditioned (ft^2) + Floor Area, Conditioned (ft^2) + + + Floor Area, Attic (ft^2) + Floor Area, Attic (ft^2) + + + Floor Area, Lighting (ft^2) + Floor Area, Lighting (ft^2) + + + Roof Area (ft^2) + Roof Area (ft^2) + + + Window Area (ft^2) + Window Area (ft^2) + + + Door Area (ft^2) + Door Area (ft^2) + + + Duct Surface Area (ft^2) + Duct Surface Area (ft^2) + + + Size, Heating System (kBtu/h) + Size, Heating System (kBtu/h) + + + Size, Cooling System (kBtu/h) + Size, Cooling System (kBtu/h) + + + Size, Water Heater (gal) + Size, Water Heater (gal) + + + + + option_6_cost_2_value + Option 6 Cost 2 Value + Total option 6 cost is the sum of all: (Cost N Value) x (Cost N Multiplier). + Double + $ + false + false + + + option_6_cost_2_multiplier + Option 6 Cost 2 Multiplier + Total option 6 cost is the sum of all: (Cost N Value) x (Cost N Multiplier). + Choice + false + false + + + + + + + + Fixed (1) + Fixed (1) + + + Wall Area, Above-Grade, Conditioned (ft^2) + Wall Area, Above-Grade, Conditioned (ft^2) + + + Wall Area, Above-Grade, Exterior (ft^2) + Wall Area, Above-Grade, Exterior (ft^2) + + + Wall Area, Below-Grade (ft^2) + Wall Area, Below-Grade (ft^2) + + + Floor Area, Conditioned (ft^2) + Floor Area, Conditioned (ft^2) + + + Floor Area, Attic (ft^2) + Floor Area, Attic (ft^2) + + + Floor Area, Lighting (ft^2) + Floor Area, Lighting (ft^2) + + + Roof Area (ft^2) + Roof Area (ft^2) + + + Window Area (ft^2) + Window Area (ft^2) + + + Door Area (ft^2) + Door Area (ft^2) + + + Duct Surface Area (ft^2) + Duct Surface Area (ft^2) + + + Size, Heating System (kBtu/h) + Size, Heating System (kBtu/h) + + + Size, Cooling System (kBtu/h) + Size, Cooling System (kBtu/h) + + + Size, Water Heater (gal) + Size, Water Heater (gal) + + + + + option_6_lifetime + Option 6 Lifetime + The option lifetime. + Double + years + false + false + + + option_7 + Option 7 + Specify the parameter|option as found in resources\options_lookup.tsv. + String + false + false + + + option_7_apply_logic + Option 7 Apply Logic + Logic that specifies if the Option 7 upgrade will apply based on the existing building's options. Specify one or more parameter|option as found in resources\options_lookup.tsv. When multiple are included, they must be separated by '||' for OR and '&&' for AND, and using parentheses as appropriate. Prefix an option with '!' for not. + String + false + false + + + option_7_cost_1_value + Option 7 Cost 1 Value + Total option 7 cost is the sum of all: (Cost N Value) x (Cost N Multiplier). + Double + $ + false + false + + + option_7_cost_1_multiplier + Option 7 Cost 1 Multiplier + Total option 7 cost is the sum of all: (Cost N Value) x (Cost N Multiplier). + Choice + false + false + + + + + + + + Fixed (1) + Fixed (1) + + + Wall Area, Above-Grade, Conditioned (ft^2) + Wall Area, Above-Grade, Conditioned (ft^2) + + + Wall Area, Above-Grade, Exterior (ft^2) + Wall Area, Above-Grade, Exterior (ft^2) + + + Wall Area, Below-Grade (ft^2) + Wall Area, Below-Grade (ft^2) + + + Floor Area, Conditioned (ft^2) + Floor Area, Conditioned (ft^2) + + + Floor Area, Attic (ft^2) + Floor Area, Attic (ft^2) + + + Floor Area, Lighting (ft^2) + Floor Area, Lighting (ft^2) + + + Roof Area (ft^2) + Roof Area (ft^2) + + + Window Area (ft^2) + Window Area (ft^2) + + + Door Area (ft^2) + Door Area (ft^2) + + + Duct Surface Area (ft^2) + Duct Surface Area (ft^2) + + + Size, Heating System (kBtu/h) + Size, Heating System (kBtu/h) + + + Size, Cooling System (kBtu/h) + Size, Cooling System (kBtu/h) + + + Size, Water Heater (gal) + Size, Water Heater (gal) + + + + + option_7_cost_2_value + Option 7 Cost 2 Value + Total option 7 cost is the sum of all: (Cost N Value) x (Cost N Multiplier). + Double + $ + false + false + + + option_7_cost_2_multiplier + Option 7 Cost 2 Multiplier + Total option 7 cost is the sum of all: (Cost N Value) x (Cost N Multiplier). + Choice + false + false + + + + + + + + Fixed (1) + Fixed (1) + + + Wall Area, Above-Grade, Conditioned (ft^2) + Wall Area, Above-Grade, Conditioned (ft^2) + + + Wall Area, Above-Grade, Exterior (ft^2) + Wall Area, Above-Grade, Exterior (ft^2) + + + Wall Area, Below-Grade (ft^2) + Wall Area, Below-Grade (ft^2) + + + Floor Area, Conditioned (ft^2) + Floor Area, Conditioned (ft^2) + + + Floor Area, Attic (ft^2) + Floor Area, Attic (ft^2) + + + Floor Area, Lighting (ft^2) + Floor Area, Lighting (ft^2) + + + Roof Area (ft^2) + Roof Area (ft^2) + + + Window Area (ft^2) + Window Area (ft^2) + + + Door Area (ft^2) + Door Area (ft^2) + + + Duct Surface Area (ft^2) + Duct Surface Area (ft^2) + + + Size, Heating System (kBtu/h) + Size, Heating System (kBtu/h) + + + Size, Cooling System (kBtu/h) + Size, Cooling System (kBtu/h) + + + Size, Water Heater (gal) + Size, Water Heater (gal) + + + + + option_7_lifetime + Option 7 Lifetime + The option lifetime. + Double + years + false + false + + + option_8 + Option 8 + Specify the parameter|option as found in resources\options_lookup.tsv. + String + false + false + + + option_8_apply_logic + Option 8 Apply Logic + Logic that specifies if the Option 8 upgrade will apply based on the existing building's options. Specify one or more parameter|option as found in resources\options_lookup.tsv. When multiple are included, they must be separated by '||' for OR and '&&' for AND, and using parentheses as appropriate. Prefix an option with '!' for not. + String + false + false + + + option_8_cost_1_value + Option 8 Cost 1 Value + Total option 8 cost is the sum of all: (Cost N Value) x (Cost N Multiplier). + Double + $ + false + false + + + option_8_cost_1_multiplier + Option 8 Cost 1 Multiplier + Total option 8 cost is the sum of all: (Cost N Value) x (Cost N Multiplier). + Choice + false + false + + + + + + + + Fixed (1) + Fixed (1) + + + Wall Area, Above-Grade, Conditioned (ft^2) + Wall Area, Above-Grade, Conditioned (ft^2) + + + Wall Area, Above-Grade, Exterior (ft^2) + Wall Area, Above-Grade, Exterior (ft^2) + + + Wall Area, Below-Grade (ft^2) + Wall Area, Below-Grade (ft^2) + + + Floor Area, Conditioned (ft^2) + Floor Area, Conditioned (ft^2) + + + Floor Area, Attic (ft^2) + Floor Area, Attic (ft^2) + + + Floor Area, Lighting (ft^2) + Floor Area, Lighting (ft^2) + + + Roof Area (ft^2) + Roof Area (ft^2) + + + Window Area (ft^2) + Window Area (ft^2) + + + Door Area (ft^2) + Door Area (ft^2) + + + Duct Surface Area (ft^2) + Duct Surface Area (ft^2) + + + Size, Heating System (kBtu/h) + Size, Heating System (kBtu/h) + + + Size, Cooling System (kBtu/h) + Size, Cooling System (kBtu/h) + + + Size, Water Heater (gal) + Size, Water Heater (gal) + + + + + option_8_cost_2_value + Option 8 Cost 2 Value + Total option 8 cost is the sum of all: (Cost N Value) x (Cost N Multiplier). + Double + $ + false + false + + + option_8_cost_2_multiplier + Option 8 Cost 2 Multiplier + Total option 8 cost is the sum of all: (Cost N Value) x (Cost N Multiplier). + Choice + false + false + + + + + + + + Fixed (1) + Fixed (1) + + + Wall Area, Above-Grade, Conditioned (ft^2) + Wall Area, Above-Grade, Conditioned (ft^2) + + + Wall Area, Above-Grade, Exterior (ft^2) + Wall Area, Above-Grade, Exterior (ft^2) + + + Wall Area, Below-Grade (ft^2) + Wall Area, Below-Grade (ft^2) + + + Floor Area, Conditioned (ft^2) + Floor Area, Conditioned (ft^2) + + + Floor Area, Attic (ft^2) + Floor Area, Attic (ft^2) + + + Floor Area, Lighting (ft^2) + Floor Area, Lighting (ft^2) + + + Roof Area (ft^2) + Roof Area (ft^2) + + + Window Area (ft^2) + Window Area (ft^2) + + + Door Area (ft^2) + Door Area (ft^2) + + + Duct Surface Area (ft^2) + Duct Surface Area (ft^2) + + + Size, Heating System (kBtu/h) + Size, Heating System (kBtu/h) + + + Size, Cooling System (kBtu/h) + Size, Cooling System (kBtu/h) + + + Size, Water Heater (gal) + Size, Water Heater (gal) + + + + + option_8_lifetime + Option 8 Lifetime + The option lifetime. + Double + years + false + false + + + option_9 + Option 9 + Specify the parameter|option as found in resources\options_lookup.tsv. + String + false + false + + + option_9_apply_logic + Option 9 Apply Logic + Logic that specifies if the Option 9 upgrade will apply based on the existing building's options. Specify one or more parameter|option as found in resources\options_lookup.tsv. When multiple are included, they must be separated by '||' for OR and '&&' for AND, and using parentheses as appropriate. Prefix an option with '!' for not. + String + false + false + + + option_9_cost_1_value + Option 9 Cost 1 Value + Total option 9 cost is the sum of all: (Cost N Value) x (Cost N Multiplier). + Double + $ + false + false + + + option_9_cost_1_multiplier + Option 9 Cost 1 Multiplier + Total option 9 cost is the sum of all: (Cost N Value) x (Cost N Multiplier). + Choice + false + false + + + + + + + + Fixed (1) + Fixed (1) + + + Wall Area, Above-Grade, Conditioned (ft^2) + Wall Area, Above-Grade, Conditioned (ft^2) + + + Wall Area, Above-Grade, Exterior (ft^2) + Wall Area, Above-Grade, Exterior (ft^2) + + + Wall Area, Below-Grade (ft^2) + Wall Area, Below-Grade (ft^2) + + + Floor Area, Conditioned (ft^2) + Floor Area, Conditioned (ft^2) + + + Floor Area, Attic (ft^2) + Floor Area, Attic (ft^2) + + + Floor Area, Lighting (ft^2) + Floor Area, Lighting (ft^2) + + + Roof Area (ft^2) + Roof Area (ft^2) + + + Window Area (ft^2) + Window Area (ft^2) + + + Door Area (ft^2) + Door Area (ft^2) + + + Duct Surface Area (ft^2) + Duct Surface Area (ft^2) + + + Size, Heating System (kBtu/h) + Size, Heating System (kBtu/h) + + + Size, Cooling System (kBtu/h) + Size, Cooling System (kBtu/h) + + + Size, Water Heater (gal) + Size, Water Heater (gal) + + + + + option_9_cost_2_value + Option 9 Cost 2 Value + Total option 9 cost is the sum of all: (Cost N Value) x (Cost N Multiplier). + Double + $ + false + false + + + option_9_cost_2_multiplier + Option 9 Cost 2 Multiplier + Total option 9 cost is the sum of all: (Cost N Value) x (Cost N Multiplier). + Choice + false + false + + + + + + + + Fixed (1) + Fixed (1) + + + Wall Area, Above-Grade, Conditioned (ft^2) + Wall Area, Above-Grade, Conditioned (ft^2) + + + Wall Area, Above-Grade, Exterior (ft^2) + Wall Area, Above-Grade, Exterior (ft^2) + + + Wall Area, Below-Grade (ft^2) + Wall Area, Below-Grade (ft^2) + + + Floor Area, Conditioned (ft^2) + Floor Area, Conditioned (ft^2) + + + Floor Area, Attic (ft^2) + Floor Area, Attic (ft^2) + + + Floor Area, Lighting (ft^2) + Floor Area, Lighting (ft^2) + + + Roof Area (ft^2) + Roof Area (ft^2) + + + Window Area (ft^2) + Window Area (ft^2) + + + Door Area (ft^2) + Door Area (ft^2) + + + Duct Surface Area (ft^2) + Duct Surface Area (ft^2) + + + Size, Heating System (kBtu/h) + Size, Heating System (kBtu/h) + + + Size, Cooling System (kBtu/h) + Size, Cooling System (kBtu/h) + + + Size, Water Heater (gal) + Size, Water Heater (gal) + + + + + option_9_lifetime + Option 9 Lifetime + The option lifetime. + Double + years + false + false + + + option_10 + Option 10 + Specify the parameter|option as found in resources\options_lookup.tsv. + String + false + false + + + option_10_apply_logic + Option 10 Apply Logic + Logic that specifies if the Option 10 upgrade will apply based on the existing building's options. Specify one or more parameter|option as found in resources\options_lookup.tsv. When multiple are included, they must be separated by '||' for OR and '&&' for AND, and using parentheses as appropriate. Prefix an option with '!' for not. + String + false + false + + + option_10_cost_1_value + Option 10 Cost 1 Value + Total option 10 cost is the sum of all: (Cost N Value) x (Cost N Multiplier). + Double + $ + false + false + + + option_10_cost_1_multiplier + Option 10 Cost 1 Multiplier + Total option 10 cost is the sum of all: (Cost N Value) x (Cost N Multiplier). + Choice + false + false + + + + + + + + Fixed (1) + Fixed (1) + + + Wall Area, Above-Grade, Conditioned (ft^2) + Wall Area, Above-Grade, Conditioned (ft^2) + + + Wall Area, Above-Grade, Exterior (ft^2) + Wall Area, Above-Grade, Exterior (ft^2) + + + Wall Area, Below-Grade (ft^2) + Wall Area, Below-Grade (ft^2) + + + Floor Area, Conditioned (ft^2) + Floor Area, Conditioned (ft^2) + + + Floor Area, Attic (ft^2) + Floor Area, Attic (ft^2) + + + Floor Area, Lighting (ft^2) + Floor Area, Lighting (ft^2) + + + Roof Area (ft^2) + Roof Area (ft^2) + + + Window Area (ft^2) + Window Area (ft^2) + + + Door Area (ft^2) + Door Area (ft^2) + + + Duct Surface Area (ft^2) + Duct Surface Area (ft^2) + + + Size, Heating System (kBtu/h) + Size, Heating System (kBtu/h) + + + Size, Cooling System (kBtu/h) + Size, Cooling System (kBtu/h) + + + Size, Water Heater (gal) + Size, Water Heater (gal) + + + + + option_10_cost_2_value + Option 10 Cost 2 Value + Total option 10 cost is the sum of all: (Cost N Value) x (Cost N Multiplier). + Double + $ + false + false + + + option_10_cost_2_multiplier + Option 10 Cost 2 Multiplier + Total option 10 cost is the sum of all: (Cost N Value) x (Cost N Multiplier). + Choice + false + false + + + + + + + + Fixed (1) + Fixed (1) + + + Wall Area, Above-Grade, Conditioned (ft^2) + Wall Area, Above-Grade, Conditioned (ft^2) + + + Wall Area, Above-Grade, Exterior (ft^2) + Wall Area, Above-Grade, Exterior (ft^2) + + + Wall Area, Below-Grade (ft^2) + Wall Area, Below-Grade (ft^2) + + + Floor Area, Conditioned (ft^2) + Floor Area, Conditioned (ft^2) + + + Floor Area, Attic (ft^2) + Floor Area, Attic (ft^2) + + + Floor Area, Lighting (ft^2) + Floor Area, Lighting (ft^2) + + + Roof Area (ft^2) + Roof Area (ft^2) + + + Window Area (ft^2) + Window Area (ft^2) + + + Door Area (ft^2) + Door Area (ft^2) + + + Duct Surface Area (ft^2) + Duct Surface Area (ft^2) + + + Size, Heating System (kBtu/h) + Size, Heating System (kBtu/h) + + + Size, Cooling System (kBtu/h) + Size, Cooling System (kBtu/h) + + + Size, Water Heater (gal) + Size, Water Heater (gal) + + + + + option_10_lifetime + Option 10 Lifetime + The option lifetime. + Double + years + false + false + + + option_11 + Option 11 + Specify the parameter|option as found in resources\options_lookup.tsv. + String + false + false + + + option_11_apply_logic + Option 11 Apply Logic + Logic that specifies if the Option 11 upgrade will apply based on the existing building's options. Specify one or more parameter|option as found in resources\options_lookup.tsv. When multiple are included, they must be separated by '||' for OR and '&&' for AND, and using parentheses as appropriate. Prefix an option with '!' for not. + String + false + false + + + option_11_cost_1_value + Option 11 Cost 1 Value + Total option 11 cost is the sum of all: (Cost N Value) x (Cost N Multiplier). + Double + $ + false + false + + + option_11_cost_1_multiplier + Option 11 Cost 1 Multiplier + Total option 11 cost is the sum of all: (Cost N Value) x (Cost N Multiplier). + Choice + false + false + + + + + + + + Fixed (1) + Fixed (1) + + + Wall Area, Above-Grade, Conditioned (ft^2) + Wall Area, Above-Grade, Conditioned (ft^2) + + + Wall Area, Above-Grade, Exterior (ft^2) + Wall Area, Above-Grade, Exterior (ft^2) + + + Wall Area, Below-Grade (ft^2) + Wall Area, Below-Grade (ft^2) + + + Floor Area, Conditioned (ft^2) + Floor Area, Conditioned (ft^2) + + + Floor Area, Attic (ft^2) + Floor Area, Attic (ft^2) + + + Floor Area, Lighting (ft^2) + Floor Area, Lighting (ft^2) + + + Roof Area (ft^2) + Roof Area (ft^2) + + + Window Area (ft^2) + Window Area (ft^2) + + + Door Area (ft^2) + Door Area (ft^2) + + + Duct Surface Area (ft^2) + Duct Surface Area (ft^2) + + + Size, Heating System (kBtu/h) + Size, Heating System (kBtu/h) + + + Size, Cooling System (kBtu/h) + Size, Cooling System (kBtu/h) + + + Size, Water Heater (gal) + Size, Water Heater (gal) + + + + + option_11_cost_2_value + Option 11 Cost 2 Value + Total option 11 cost is the sum of all: (Cost N Value) x (Cost N Multiplier). + Double + $ + false + false + + + option_11_cost_2_multiplier + Option 11 Cost 2 Multiplier + Total option 11 cost is the sum of all: (Cost N Value) x (Cost N Multiplier). + Choice + false + false + + + + + + + + Fixed (1) + Fixed (1) + + + Wall Area, Above-Grade, Conditioned (ft^2) + Wall Area, Above-Grade, Conditioned (ft^2) + + + Wall Area, Above-Grade, Exterior (ft^2) + Wall Area, Above-Grade, Exterior (ft^2) + + + Wall Area, Below-Grade (ft^2) + Wall Area, Below-Grade (ft^2) + + + Floor Area, Conditioned (ft^2) + Floor Area, Conditioned (ft^2) + + + Floor Area, Attic (ft^2) + Floor Area, Attic (ft^2) + + + Floor Area, Lighting (ft^2) + Floor Area, Lighting (ft^2) + + + Roof Area (ft^2) + Roof Area (ft^2) + + + Window Area (ft^2) + Window Area (ft^2) + + + Door Area (ft^2) + Door Area (ft^2) + + + Duct Surface Area (ft^2) + Duct Surface Area (ft^2) + + + Size, Heating System (kBtu/h) + Size, Heating System (kBtu/h) + + + Size, Cooling System (kBtu/h) + Size, Cooling System (kBtu/h) + + + Size, Water Heater (gal) + Size, Water Heater (gal) + + + + + option_11_lifetime + Option 11 Lifetime + The option lifetime. + Double + years + false + false + + + option_12 + Option 12 + Specify the parameter|option as found in resources\options_lookup.tsv. + String + false + false + + + option_12_apply_logic + Option 12 Apply Logic + Logic that specifies if the Option 12 upgrade will apply based on the existing building's options. Specify one or more parameter|option as found in resources\options_lookup.tsv. When multiple are included, they must be separated by '||' for OR and '&&' for AND, and using parentheses as appropriate. Prefix an option with '!' for not. + String + false + false + + + option_12_cost_1_value + Option 12 Cost 1 Value + Total option 12 cost is the sum of all: (Cost N Value) x (Cost N Multiplier). + Double + $ + false + false + + + option_12_cost_1_multiplier + Option 12 Cost 1 Multiplier + Total option 12 cost is the sum of all: (Cost N Value) x (Cost N Multiplier). + Choice + false + false + + + + + + + + Fixed (1) + Fixed (1) + + + Wall Area, Above-Grade, Conditioned (ft^2) + Wall Area, Above-Grade, Conditioned (ft^2) + + + Wall Area, Above-Grade, Exterior (ft^2) + Wall Area, Above-Grade, Exterior (ft^2) + + + Wall Area, Below-Grade (ft^2) + Wall Area, Below-Grade (ft^2) + + + Floor Area, Conditioned (ft^2) + Floor Area, Conditioned (ft^2) + + + Floor Area, Attic (ft^2) + Floor Area, Attic (ft^2) + + + Floor Area, Lighting (ft^2) + Floor Area, Lighting (ft^2) + + + Roof Area (ft^2) + Roof Area (ft^2) + + + Window Area (ft^2) + Window Area (ft^2) + + + Door Area (ft^2) + Door Area (ft^2) + + + Duct Surface Area (ft^2) + Duct Surface Area (ft^2) + + + Size, Heating System (kBtu/h) + Size, Heating System (kBtu/h) + + + Size, Cooling System (kBtu/h) + Size, Cooling System (kBtu/h) + + + Size, Water Heater (gal) + Size, Water Heater (gal) + + + + + option_12_cost_2_value + Option 12 Cost 2 Value + Total option 12 cost is the sum of all: (Cost N Value) x (Cost N Multiplier). + Double + $ + false + false + + + option_12_cost_2_multiplier + Option 12 Cost 2 Multiplier + Total option 12 cost is the sum of all: (Cost N Value) x (Cost N Multiplier). + Choice + false + false + + + + + + + + Fixed (1) + Fixed (1) + + + Wall Area, Above-Grade, Conditioned (ft^2) + Wall Area, Above-Grade, Conditioned (ft^2) + + + Wall Area, Above-Grade, Exterior (ft^2) + Wall Area, Above-Grade, Exterior (ft^2) + + + Wall Area, Below-Grade (ft^2) + Wall Area, Below-Grade (ft^2) + + + Floor Area, Conditioned (ft^2) + Floor Area, Conditioned (ft^2) + + + Floor Area, Attic (ft^2) + Floor Area, Attic (ft^2) + + + Floor Area, Lighting (ft^2) + Floor Area, Lighting (ft^2) + + + Roof Area (ft^2) + Roof Area (ft^2) + + + Window Area (ft^2) + Window Area (ft^2) + + + Door Area (ft^2) + Door Area (ft^2) + + + Duct Surface Area (ft^2) + Duct Surface Area (ft^2) + + + Size, Heating System (kBtu/h) + Size, Heating System (kBtu/h) + + + Size, Cooling System (kBtu/h) + Size, Cooling System (kBtu/h) + + + Size, Water Heater (gal) + Size, Water Heater (gal) + + + + + option_12_lifetime + Option 12 Lifetime + The option lifetime. + Double + years + false + false + + + option_13 + Option 13 + Specify the parameter|option as found in resources\options_lookup.tsv. + String + false + false + + + option_13_apply_logic + Option 13 Apply Logic + Logic that specifies if the Option 13 upgrade will apply based on the existing building's options. Specify one or more parameter|option as found in resources\options_lookup.tsv. When multiple are included, they must be separated by '||' for OR and '&&' for AND, and using parentheses as appropriate. Prefix an option with '!' for not. + String + false + false + + + option_13_cost_1_value + Option 13 Cost 1 Value + Total option 13 cost is the sum of all: (Cost N Value) x (Cost N Multiplier). + Double + $ + false + false + + + option_13_cost_1_multiplier + Option 13 Cost 1 Multiplier + Total option 13 cost is the sum of all: (Cost N Value) x (Cost N Multiplier). + Choice + false + false + + + + + + + + Fixed (1) + Fixed (1) + + + Wall Area, Above-Grade, Conditioned (ft^2) + Wall Area, Above-Grade, Conditioned (ft^2) + + + Wall Area, Above-Grade, Exterior (ft^2) + Wall Area, Above-Grade, Exterior (ft^2) + + + Wall Area, Below-Grade (ft^2) + Wall Area, Below-Grade (ft^2) + + + Floor Area, Conditioned (ft^2) + Floor Area, Conditioned (ft^2) + + + Floor Area, Attic (ft^2) + Floor Area, Attic (ft^2) + + + Floor Area, Lighting (ft^2) + Floor Area, Lighting (ft^2) + + + Roof Area (ft^2) + Roof Area (ft^2) + + + Window Area (ft^2) + Window Area (ft^2) + + + Door Area (ft^2) + Door Area (ft^2) + + + Duct Surface Area (ft^2) + Duct Surface Area (ft^2) + + + Size, Heating System (kBtu/h) + Size, Heating System (kBtu/h) + + + Size, Cooling System (kBtu/h) + Size, Cooling System (kBtu/h) + + + Size, Water Heater (gal) + Size, Water Heater (gal) + + + + + option_13_cost_2_value + Option 13 Cost 2 Value + Total option 13 cost is the sum of all: (Cost N Value) x (Cost N Multiplier). + Double + $ + false + false + + + option_13_cost_2_multiplier + Option 13 Cost 2 Multiplier + Total option 13 cost is the sum of all: (Cost N Value) x (Cost N Multiplier). + Choice + false + false + + + + + + + + Fixed (1) + Fixed (1) + + + Wall Area, Above-Grade, Conditioned (ft^2) + Wall Area, Above-Grade, Conditioned (ft^2) + + + Wall Area, Above-Grade, Exterior (ft^2) + Wall Area, Above-Grade, Exterior (ft^2) + + + Wall Area, Below-Grade (ft^2) + Wall Area, Below-Grade (ft^2) + + + Floor Area, Conditioned (ft^2) + Floor Area, Conditioned (ft^2) + + + Floor Area, Attic (ft^2) + Floor Area, Attic (ft^2) + + + Floor Area, Lighting (ft^2) + Floor Area, Lighting (ft^2) + + + Roof Area (ft^2) + Roof Area (ft^2) + + + Window Area (ft^2) + Window Area (ft^2) + + + Door Area (ft^2) + Door Area (ft^2) + + + Duct Surface Area (ft^2) + Duct Surface Area (ft^2) + + + Size, Heating System (kBtu/h) + Size, Heating System (kBtu/h) + + + Size, Cooling System (kBtu/h) + Size, Cooling System (kBtu/h) + + + Size, Water Heater (gal) + Size, Water Heater (gal) + + + + + option_13_lifetime + Option 13 Lifetime + The option lifetime. + Double + years + false + false + + + option_14 + Option 14 + Specify the parameter|option as found in resources\options_lookup.tsv. + String + false + false + + + option_14_apply_logic + Option 14 Apply Logic + Logic that specifies if the Option 14 upgrade will apply based on the existing building's options. Specify one or more parameter|option as found in resources\options_lookup.tsv. When multiple are included, they must be separated by '||' for OR and '&&' for AND, and using parentheses as appropriate. Prefix an option with '!' for not. + String + false + false + + + option_14_cost_1_value + Option 14 Cost 1 Value + Total option 14 cost is the sum of all: (Cost N Value) x (Cost N Multiplier). + Double + $ + false + false + + + option_14_cost_1_multiplier + Option 14 Cost 1 Multiplier + Total option 14 cost is the sum of all: (Cost N Value) x (Cost N Multiplier). + Choice + false + false + + + + + + + + Fixed (1) + Fixed (1) + + + Wall Area, Above-Grade, Conditioned (ft^2) + Wall Area, Above-Grade, Conditioned (ft^2) + + + Wall Area, Above-Grade, Exterior (ft^2) + Wall Area, Above-Grade, Exterior (ft^2) + + + Wall Area, Below-Grade (ft^2) + Wall Area, Below-Grade (ft^2) + + + Floor Area, Conditioned (ft^2) + Floor Area, Conditioned (ft^2) + + + Floor Area, Attic (ft^2) + Floor Area, Attic (ft^2) + + + Floor Area, Lighting (ft^2) + Floor Area, Lighting (ft^2) + + + Roof Area (ft^2) + Roof Area (ft^2) + + + Window Area (ft^2) + Window Area (ft^2) + + + Door Area (ft^2) + Door Area (ft^2) + + + Duct Surface Area (ft^2) + Duct Surface Area (ft^2) + + + Size, Heating System (kBtu/h) + Size, Heating System (kBtu/h) + + + Size, Cooling System (kBtu/h) + Size, Cooling System (kBtu/h) + + + Size, Water Heater (gal) + Size, Water Heater (gal) + + + + + option_14_cost_2_value + Option 14 Cost 2 Value + Total option 14 cost is the sum of all: (Cost N Value) x (Cost N Multiplier). + Double + $ + false + false + + + option_14_cost_2_multiplier + Option 14 Cost 2 Multiplier + Total option 14 cost is the sum of all: (Cost N Value) x (Cost N Multiplier). + Choice + false + false + + + + + + + + Fixed (1) + Fixed (1) + + + Wall Area, Above-Grade, Conditioned (ft^2) + Wall Area, Above-Grade, Conditioned (ft^2) + + + Wall Area, Above-Grade, Exterior (ft^2) + Wall Area, Above-Grade, Exterior (ft^2) + + + Wall Area, Below-Grade (ft^2) + Wall Area, Below-Grade (ft^2) + + + Floor Area, Conditioned (ft^2) + Floor Area, Conditioned (ft^2) + + + Floor Area, Attic (ft^2) + Floor Area, Attic (ft^2) + + + Floor Area, Lighting (ft^2) + Floor Area, Lighting (ft^2) + + + Roof Area (ft^2) + Roof Area (ft^2) + + + Window Area (ft^2) + Window Area (ft^2) + + + Door Area (ft^2) + Door Area (ft^2) + + + Duct Surface Area (ft^2) + Duct Surface Area (ft^2) + + + Size, Heating System (kBtu/h) + Size, Heating System (kBtu/h) + + + Size, Cooling System (kBtu/h) + Size, Cooling System (kBtu/h) + + + Size, Water Heater (gal) + Size, Water Heater (gal) + + + + + option_14_lifetime + Option 14 Lifetime + The option lifetime. + Double + years + false + false + + + option_15 + Option 15 + Specify the parameter|option as found in resources\options_lookup.tsv. + String + false + false + + + option_15_apply_logic + Option 15 Apply Logic + Logic that specifies if the Option 15 upgrade will apply based on the existing building's options. Specify one or more parameter|option as found in resources\options_lookup.tsv. When multiple are included, they must be separated by '||' for OR and '&&' for AND, and using parentheses as appropriate. Prefix an option with '!' for not. + String + false + false + + + option_15_cost_1_value + Option 15 Cost 1 Value + Total option 15 cost is the sum of all: (Cost N Value) x (Cost N Multiplier). + Double + $ + false + false + + + option_15_cost_1_multiplier + Option 15 Cost 1 Multiplier + Total option 15 cost is the sum of all: (Cost N Value) x (Cost N Multiplier). + Choice + false + false + + + + + + + + Fixed (1) + Fixed (1) + + + Wall Area, Above-Grade, Conditioned (ft^2) + Wall Area, Above-Grade, Conditioned (ft^2) + + + Wall Area, Above-Grade, Exterior (ft^2) + Wall Area, Above-Grade, Exterior (ft^2) + + + Wall Area, Below-Grade (ft^2) + Wall Area, Below-Grade (ft^2) + + + Floor Area, Conditioned (ft^2) + Floor Area, Conditioned (ft^2) + + + Floor Area, Attic (ft^2) + Floor Area, Attic (ft^2) + + + Floor Area, Lighting (ft^2) + Floor Area, Lighting (ft^2) + + + Roof Area (ft^2) + Roof Area (ft^2) + + + Window Area (ft^2) + Window Area (ft^2) + + + Door Area (ft^2) + Door Area (ft^2) + + + Duct Surface Area (ft^2) + Duct Surface Area (ft^2) + + + Size, Heating System (kBtu/h) + Size, Heating System (kBtu/h) + + + Size, Cooling System (kBtu/h) + Size, Cooling System (kBtu/h) + + + Size, Water Heater (gal) + Size, Water Heater (gal) + + + + + option_15_cost_2_value + Option 15 Cost 2 Value + Total option 15 cost is the sum of all: (Cost N Value) x (Cost N Multiplier). + Double + $ + false + false + + + option_15_cost_2_multiplier + Option 15 Cost 2 Multiplier + Total option 15 cost is the sum of all: (Cost N Value) x (Cost N Multiplier). + Choice + false + false + + + + + + + + Fixed (1) + Fixed (1) + + + Wall Area, Above-Grade, Conditioned (ft^2) + Wall Area, Above-Grade, Conditioned (ft^2) + + + Wall Area, Above-Grade, Exterior (ft^2) + Wall Area, Above-Grade, Exterior (ft^2) + + + Wall Area, Below-Grade (ft^2) + Wall Area, Below-Grade (ft^2) + + + Floor Area, Conditioned (ft^2) + Floor Area, Conditioned (ft^2) + + + Floor Area, Attic (ft^2) + Floor Area, Attic (ft^2) + + + Floor Area, Lighting (ft^2) + Floor Area, Lighting (ft^2) + + + Roof Area (ft^2) + Roof Area (ft^2) + + + Window Area (ft^2) + Window Area (ft^2) + + + Door Area (ft^2) + Door Area (ft^2) + + + Duct Surface Area (ft^2) + Duct Surface Area (ft^2) + + + Size, Heating System (kBtu/h) + Size, Heating System (kBtu/h) + + + Size, Cooling System (kBtu/h) + Size, Cooling System (kBtu/h) + + + Size, Water Heater (gal) + Size, Water Heater (gal) + + + + + option_15_lifetime + Option 15 Lifetime + The option lifetime. + Double + years + false + false + + + option_16 + Option 16 + Specify the parameter|option as found in resources\options_lookup.tsv. + String + false + false + + + option_16_apply_logic + Option 16 Apply Logic + Logic that specifies if the Option 16 upgrade will apply based on the existing building's options. Specify one or more parameter|option as found in resources\options_lookup.tsv. When multiple are included, they must be separated by '||' for OR and '&&' for AND, and using parentheses as appropriate. Prefix an option with '!' for not. + String + false + false + + + option_16_cost_1_value + Option 16 Cost 1 Value + Total option 16 cost is the sum of all: (Cost N Value) x (Cost N Multiplier). + Double + $ + false + false + + + option_16_cost_1_multiplier + Option 16 Cost 1 Multiplier + Total option 16 cost is the sum of all: (Cost N Value) x (Cost N Multiplier). + Choice + false + false + + + + + + + + Fixed (1) + Fixed (1) + + + Wall Area, Above-Grade, Conditioned (ft^2) + Wall Area, Above-Grade, Conditioned (ft^2) + + + Wall Area, Above-Grade, Exterior (ft^2) + Wall Area, Above-Grade, Exterior (ft^2) + + + Wall Area, Below-Grade (ft^2) + Wall Area, Below-Grade (ft^2) + + + Floor Area, Conditioned (ft^2) + Floor Area, Conditioned (ft^2) + + + Floor Area, Attic (ft^2) + Floor Area, Attic (ft^2) + + + Floor Area, Lighting (ft^2) + Floor Area, Lighting (ft^2) + + + Roof Area (ft^2) + Roof Area (ft^2) + + + Window Area (ft^2) + Window Area (ft^2) + + + Door Area (ft^2) + Door Area (ft^2) + + + Duct Surface Area (ft^2) + Duct Surface Area (ft^2) + + + Size, Heating System (kBtu/h) + Size, Heating System (kBtu/h) + + + Size, Cooling System (kBtu/h) + Size, Cooling System (kBtu/h) + + + Size, Water Heater (gal) + Size, Water Heater (gal) + + + + + option_16_cost_2_value + Option 16 Cost 2 Value + Total option 16 cost is the sum of all: (Cost N Value) x (Cost N Multiplier). + Double + $ + false + false + + + option_16_cost_2_multiplier + Option 16 Cost 2 Multiplier + Total option 16 cost is the sum of all: (Cost N Value) x (Cost N Multiplier). + Choice + false + false + + + + + + + + Fixed (1) + Fixed (1) + + + Wall Area, Above-Grade, Conditioned (ft^2) + Wall Area, Above-Grade, Conditioned (ft^2) + + + Wall Area, Above-Grade, Exterior (ft^2) + Wall Area, Above-Grade, Exterior (ft^2) + + + Wall Area, Below-Grade (ft^2) + Wall Area, Below-Grade (ft^2) + + + Floor Area, Conditioned (ft^2) + Floor Area, Conditioned (ft^2) + + + Floor Area, Attic (ft^2) + Floor Area, Attic (ft^2) + + + Floor Area, Lighting (ft^2) + Floor Area, Lighting (ft^2) + + + Roof Area (ft^2) + Roof Area (ft^2) + + + Window Area (ft^2) + Window Area (ft^2) + + + Door Area (ft^2) + Door Area (ft^2) + + + Duct Surface Area (ft^2) + Duct Surface Area (ft^2) + + + Size, Heating System (kBtu/h) + Size, Heating System (kBtu/h) + + + Size, Cooling System (kBtu/h) + Size, Cooling System (kBtu/h) + + + Size, Water Heater (gal) + Size, Water Heater (gal) + + + + + option_16_lifetime + Option 16 Lifetime + The option lifetime. + Double + years + false + false + + + option_17 + Option 17 + Specify the parameter|option as found in resources\options_lookup.tsv. + String + false + false + + + option_17_apply_logic + Option 17 Apply Logic + Logic that specifies if the Option 17 upgrade will apply based on the existing building's options. Specify one or more parameter|option as found in resources\options_lookup.tsv. When multiple are included, they must be separated by '||' for OR and '&&' for AND, and using parentheses as appropriate. Prefix an option with '!' for not. + String + false + false + + + option_17_cost_1_value + Option 17 Cost 1 Value + Total option 17 cost is the sum of all: (Cost N Value) x (Cost N Multiplier). + Double + $ + false + false + + + option_17_cost_1_multiplier + Option 17 Cost 1 Multiplier + Total option 17 cost is the sum of all: (Cost N Value) x (Cost N Multiplier). + Choice + false + false + + + + + + + + Fixed (1) + Fixed (1) + + + Wall Area, Above-Grade, Conditioned (ft^2) + Wall Area, Above-Grade, Conditioned (ft^2) + + + Wall Area, Above-Grade, Exterior (ft^2) + Wall Area, Above-Grade, Exterior (ft^2) + + + Wall Area, Below-Grade (ft^2) + Wall Area, Below-Grade (ft^2) + + + Floor Area, Conditioned (ft^2) + Floor Area, Conditioned (ft^2) + + + Floor Area, Attic (ft^2) + Floor Area, Attic (ft^2) + + + Floor Area, Lighting (ft^2) + Floor Area, Lighting (ft^2) + + + Roof Area (ft^2) + Roof Area (ft^2) + + + Window Area (ft^2) + Window Area (ft^2) + + + Door Area (ft^2) + Door Area (ft^2) + + + Duct Surface Area (ft^2) + Duct Surface Area (ft^2) + + + Size, Heating System (kBtu/h) + Size, Heating System (kBtu/h) + + + Size, Cooling System (kBtu/h) + Size, Cooling System (kBtu/h) + + + Size, Water Heater (gal) + Size, Water Heater (gal) + + + + + option_17_cost_2_value + Option 17 Cost 2 Value + Total option 17 cost is the sum of all: (Cost N Value) x (Cost N Multiplier). + Double + $ + false + false + + + option_17_cost_2_multiplier + Option 17 Cost 2 Multiplier + Total option 17 cost is the sum of all: (Cost N Value) x (Cost N Multiplier). + Choice + false + false + + + + + + + + Fixed (1) + Fixed (1) + + + Wall Area, Above-Grade, Conditioned (ft^2) + Wall Area, Above-Grade, Conditioned (ft^2) + + + Wall Area, Above-Grade, Exterior (ft^2) + Wall Area, Above-Grade, Exterior (ft^2) + + + Wall Area, Below-Grade (ft^2) + Wall Area, Below-Grade (ft^2) + + + Floor Area, Conditioned (ft^2) + Floor Area, Conditioned (ft^2) + + + Floor Area, Attic (ft^2) + Floor Area, Attic (ft^2) + + + Floor Area, Lighting (ft^2) + Floor Area, Lighting (ft^2) + + + Roof Area (ft^2) + Roof Area (ft^2) + + + Window Area (ft^2) + Window Area (ft^2) + + + Door Area (ft^2) + Door Area (ft^2) + + + Duct Surface Area (ft^2) + Duct Surface Area (ft^2) + + + Size, Heating System (kBtu/h) + Size, Heating System (kBtu/h) + + + Size, Cooling System (kBtu/h) + Size, Cooling System (kBtu/h) + + + Size, Water Heater (gal) + Size, Water Heater (gal) + + + + + option_17_lifetime + Option 17 Lifetime + The option lifetime. + Double + years + false + false + + + option_18 + Option 18 + Specify the parameter|option as found in resources\options_lookup.tsv. + String + false + false + + + option_18_apply_logic + Option 18 Apply Logic + Logic that specifies if the Option 18 upgrade will apply based on the existing building's options. Specify one or more parameter|option as found in resources\options_lookup.tsv. When multiple are included, they must be separated by '||' for OR and '&&' for AND, and using parentheses as appropriate. Prefix an option with '!' for not. + String + false + false + + + option_18_cost_1_value + Option 18 Cost 1 Value + Total option 18 cost is the sum of all: (Cost N Value) x (Cost N Multiplier). + Double + $ + false + false + + + option_18_cost_1_multiplier + Option 18 Cost 1 Multiplier + Total option 18 cost is the sum of all: (Cost N Value) x (Cost N Multiplier). + Choice + false + false + + + + + + + + Fixed (1) + Fixed (1) + + + Wall Area, Above-Grade, Conditioned (ft^2) + Wall Area, Above-Grade, Conditioned (ft^2) + + + Wall Area, Above-Grade, Exterior (ft^2) + Wall Area, Above-Grade, Exterior (ft^2) + + + Wall Area, Below-Grade (ft^2) + Wall Area, Below-Grade (ft^2) + + + Floor Area, Conditioned (ft^2) + Floor Area, Conditioned (ft^2) + + + Floor Area, Attic (ft^2) + Floor Area, Attic (ft^2) + + + Floor Area, Lighting (ft^2) + Floor Area, Lighting (ft^2) + + + Roof Area (ft^2) + Roof Area (ft^2) + + + Window Area (ft^2) + Window Area (ft^2) + + + Door Area (ft^2) + Door Area (ft^2) + + + Duct Surface Area (ft^2) + Duct Surface Area (ft^2) + + + Size, Heating System (kBtu/h) + Size, Heating System (kBtu/h) + + + Size, Cooling System (kBtu/h) + Size, Cooling System (kBtu/h) + + + Size, Water Heater (gal) + Size, Water Heater (gal) + + + + + option_18_cost_2_value + Option 18 Cost 2 Value + Total option 18 cost is the sum of all: (Cost N Value) x (Cost N Multiplier). + Double + $ + false + false + + + option_18_cost_2_multiplier + Option 18 Cost 2 Multiplier + Total option 18 cost is the sum of all: (Cost N Value) x (Cost N Multiplier). + Choice + false + false + + + + + + + + Fixed (1) + Fixed (1) + + + Wall Area, Above-Grade, Conditioned (ft^2) + Wall Area, Above-Grade, Conditioned (ft^2) + + + Wall Area, Above-Grade, Exterior (ft^2) + Wall Area, Above-Grade, Exterior (ft^2) + + + Wall Area, Below-Grade (ft^2) + Wall Area, Below-Grade (ft^2) + + + Floor Area, Conditioned (ft^2) + Floor Area, Conditioned (ft^2) + + + Floor Area, Attic (ft^2) + Floor Area, Attic (ft^2) + + + Floor Area, Lighting (ft^2) + Floor Area, Lighting (ft^2) + + + Roof Area (ft^2) + Roof Area (ft^2) + + + Window Area (ft^2) + Window Area (ft^2) + + + Door Area (ft^2) + Door Area (ft^2) + + + Duct Surface Area (ft^2) + Duct Surface Area (ft^2) + + + Size, Heating System (kBtu/h) + Size, Heating System (kBtu/h) + + + Size, Cooling System (kBtu/h) + Size, Cooling System (kBtu/h) + + + Size, Water Heater (gal) + Size, Water Heater (gal) + + + + + option_18_lifetime + Option 18 Lifetime + The option lifetime. + Double + years + false + false + + + option_19 + Option 19 + Specify the parameter|option as found in resources\options_lookup.tsv. + String + false + false + + + option_19_apply_logic + Option 19 Apply Logic + Logic that specifies if the Option 19 upgrade will apply based on the existing building's options. Specify one or more parameter|option as found in resources\options_lookup.tsv. When multiple are included, they must be separated by '||' for OR and '&&' for AND, and using parentheses as appropriate. Prefix an option with '!' for not. + String + false + false + + + option_19_cost_1_value + Option 19 Cost 1 Value + Total option 19 cost is the sum of all: (Cost N Value) x (Cost N Multiplier). + Double + $ + false + false + + + option_19_cost_1_multiplier + Option 19 Cost 1 Multiplier + Total option 19 cost is the sum of all: (Cost N Value) x (Cost N Multiplier). + Choice + false + false + + + + + + + + Fixed (1) + Fixed (1) + + + Wall Area, Above-Grade, Conditioned (ft^2) + Wall Area, Above-Grade, Conditioned (ft^2) + + + Wall Area, Above-Grade, Exterior (ft^2) + Wall Area, Above-Grade, Exterior (ft^2) + + + Wall Area, Below-Grade (ft^2) + Wall Area, Below-Grade (ft^2) + + + Floor Area, Conditioned (ft^2) + Floor Area, Conditioned (ft^2) + + + Floor Area, Attic (ft^2) + Floor Area, Attic (ft^2) + + + Floor Area, Lighting (ft^2) + Floor Area, Lighting (ft^2) + + + Roof Area (ft^2) + Roof Area (ft^2) + + + Window Area (ft^2) + Window Area (ft^2) + + + Door Area (ft^2) + Door Area (ft^2) + + + Duct Surface Area (ft^2) + Duct Surface Area (ft^2) + + + Size, Heating System (kBtu/h) + Size, Heating System (kBtu/h) + + + Size, Cooling System (kBtu/h) + Size, Cooling System (kBtu/h) + + + Size, Water Heater (gal) + Size, Water Heater (gal) + + + + + option_19_cost_2_value + Option 19 Cost 2 Value + Total option 19 cost is the sum of all: (Cost N Value) x (Cost N Multiplier). + Double + $ + false + false + + + option_19_cost_2_multiplier + Option 19 Cost 2 Multiplier + Total option 19 cost is the sum of all: (Cost N Value) x (Cost N Multiplier). + Choice + false + false + + + + + + + + Fixed (1) + Fixed (1) + + + Wall Area, Above-Grade, Conditioned (ft^2) + Wall Area, Above-Grade, Conditioned (ft^2) + + + Wall Area, Above-Grade, Exterior (ft^2) + Wall Area, Above-Grade, Exterior (ft^2) + + + Wall Area, Below-Grade (ft^2) + Wall Area, Below-Grade (ft^2) + + + Floor Area, Conditioned (ft^2) + Floor Area, Conditioned (ft^2) + + + Floor Area, Attic (ft^2) + Floor Area, Attic (ft^2) + + + Floor Area, Lighting (ft^2) + Floor Area, Lighting (ft^2) + + + Roof Area (ft^2) + Roof Area (ft^2) + + + Window Area (ft^2) + Window Area (ft^2) + + + Door Area (ft^2) + Door Area (ft^2) + + + Duct Surface Area (ft^2) + Duct Surface Area (ft^2) + + + Size, Heating System (kBtu/h) + Size, Heating System (kBtu/h) + + + Size, Cooling System (kBtu/h) + Size, Cooling System (kBtu/h) + + + Size, Water Heater (gal) + Size, Water Heater (gal) + + + + + option_19_lifetime + Option 19 Lifetime + The option lifetime. + Double + years + false + false + + + option_20 + Option 20 + Specify the parameter|option as found in resources\options_lookup.tsv. + String + false + false + + + option_20_apply_logic + Option 20 Apply Logic + Logic that specifies if the Option 20 upgrade will apply based on the existing building's options. Specify one or more parameter|option as found in resources\options_lookup.tsv. When multiple are included, they must be separated by '||' for OR and '&&' for AND, and using parentheses as appropriate. Prefix an option with '!' for not. + String + false + false + + + option_20_cost_1_value + Option 20 Cost 1 Value + Total option 20 cost is the sum of all: (Cost N Value) x (Cost N Multiplier). + Double + $ + false + false + + + option_20_cost_1_multiplier + Option 20 Cost 1 Multiplier + Total option 20 cost is the sum of all: (Cost N Value) x (Cost N Multiplier). + Choice + false + false + + + + + + + + Fixed (1) + Fixed (1) + + + Wall Area, Above-Grade, Conditioned (ft^2) + Wall Area, Above-Grade, Conditioned (ft^2) + + + Wall Area, Above-Grade, Exterior (ft^2) + Wall Area, Above-Grade, Exterior (ft^2) + + + Wall Area, Below-Grade (ft^2) + Wall Area, Below-Grade (ft^2) + + + Floor Area, Conditioned (ft^2) + Floor Area, Conditioned (ft^2) + + + Floor Area, Attic (ft^2) + Floor Area, Attic (ft^2) + + + Floor Area, Lighting (ft^2) + Floor Area, Lighting (ft^2) + + + Roof Area (ft^2) + Roof Area (ft^2) + + + Window Area (ft^2) + Window Area (ft^2) + + + Door Area (ft^2) + Door Area (ft^2) + + + Duct Surface Area (ft^2) + Duct Surface Area (ft^2) + + + Size, Heating System (kBtu/h) + Size, Heating System (kBtu/h) + + + Size, Cooling System (kBtu/h) + Size, Cooling System (kBtu/h) + + + Size, Water Heater (gal) + Size, Water Heater (gal) + + + + + option_20_cost_2_value + Option 20 Cost 2 Value + Total option 20 cost is the sum of all: (Cost N Value) x (Cost N Multiplier). + Double + $ + false + false + + + option_20_cost_2_multiplier + Option 20 Cost 2 Multiplier + Total option 20 cost is the sum of all: (Cost N Value) x (Cost N Multiplier). + Choice + false + false + + + + + + + + Fixed (1) + Fixed (1) + + + Wall Area, Above-Grade, Conditioned (ft^2) + Wall Area, Above-Grade, Conditioned (ft^2) + + + Wall Area, Above-Grade, Exterior (ft^2) + Wall Area, Above-Grade, Exterior (ft^2) + + + Wall Area, Below-Grade (ft^2) + Wall Area, Below-Grade (ft^2) + + + Floor Area, Conditioned (ft^2) + Floor Area, Conditioned (ft^2) + + + Floor Area, Attic (ft^2) + Floor Area, Attic (ft^2) + + + Floor Area, Lighting (ft^2) + Floor Area, Lighting (ft^2) + + + Roof Area (ft^2) + Roof Area (ft^2) + + + Window Area (ft^2) + Window Area (ft^2) + + + Door Area (ft^2) + Door Area (ft^2) + + + Duct Surface Area (ft^2) + Duct Surface Area (ft^2) + + + Size, Heating System (kBtu/h) + Size, Heating System (kBtu/h) + + + Size, Cooling System (kBtu/h) + Size, Cooling System (kBtu/h) + + + Size, Water Heater (gal) + Size, Water Heater (gal) + + + + + option_20_lifetime + Option 20 Lifetime + The option lifetime. + Double + years + false + false + + + option_21 + Option 21 + Specify the parameter|option as found in resources\options_lookup.tsv. + String + false + false + + + option_21_apply_logic + Option 21 Apply Logic + Logic that specifies if the Option 21 upgrade will apply based on the existing building's options. Specify one or more parameter|option as found in resources\options_lookup.tsv. When multiple are included, they must be separated by '||' for OR and '&&' for AND, and using parentheses as appropriate. Prefix an option with '!' for not. + String + false + false + + + option_21_cost_1_value + Option 21 Cost 1 Value + Total option 21 cost is the sum of all: (Cost N Value) x (Cost N Multiplier). + Double + $ + false + false + + + option_21_cost_1_multiplier + Option 21 Cost 1 Multiplier + Total option 21 cost is the sum of all: (Cost N Value) x (Cost N Multiplier). + Choice + false + false + + + + + + + + Fixed (1) + Fixed (1) + + + Wall Area, Above-Grade, Conditioned (ft^2) + Wall Area, Above-Grade, Conditioned (ft^2) + + + Wall Area, Above-Grade, Exterior (ft^2) + Wall Area, Above-Grade, Exterior (ft^2) + + + Wall Area, Below-Grade (ft^2) + Wall Area, Below-Grade (ft^2) + + + Floor Area, Conditioned (ft^2) + Floor Area, Conditioned (ft^2) + + + Floor Area, Attic (ft^2) + Floor Area, Attic (ft^2) + + + Floor Area, Lighting (ft^2) + Floor Area, Lighting (ft^2) + + + Roof Area (ft^2) + Roof Area (ft^2) + + + Window Area (ft^2) + Window Area (ft^2) + + + Door Area (ft^2) + Door Area (ft^2) + + + Duct Surface Area (ft^2) + Duct Surface Area (ft^2) + + + Size, Heating System (kBtu/h) + Size, Heating System (kBtu/h) + + + Size, Cooling System (kBtu/h) + Size, Cooling System (kBtu/h) + + + Size, Water Heater (gal) + Size, Water Heater (gal) + + + + + option_21_cost_2_value + Option 21 Cost 2 Value + Total option 21 cost is the sum of all: (Cost N Value) x (Cost N Multiplier). + Double + $ + false + false + + + option_21_cost_2_multiplier + Option 21 Cost 2 Multiplier + Total option 21 cost is the sum of all: (Cost N Value) x (Cost N Multiplier). + Choice + false + false + + + + + + + + Fixed (1) + Fixed (1) + + + Wall Area, Above-Grade, Conditioned (ft^2) + Wall Area, Above-Grade, Conditioned (ft^2) + + + Wall Area, Above-Grade, Exterior (ft^2) + Wall Area, Above-Grade, Exterior (ft^2) + + + Wall Area, Below-Grade (ft^2) + Wall Area, Below-Grade (ft^2) + + + Floor Area, Conditioned (ft^2) + Floor Area, Conditioned (ft^2) + + + Floor Area, Attic (ft^2) + Floor Area, Attic (ft^2) + + + Floor Area, Lighting (ft^2) + Floor Area, Lighting (ft^2) + + + Roof Area (ft^2) + Roof Area (ft^2) + + + Window Area (ft^2) + Window Area (ft^2) + + + Door Area (ft^2) + Door Area (ft^2) + + + Duct Surface Area (ft^2) + Duct Surface Area (ft^2) + + + Size, Heating System (kBtu/h) + Size, Heating System (kBtu/h) + + + Size, Cooling System (kBtu/h) + Size, Cooling System (kBtu/h) + + + Size, Water Heater (gal) + Size, Water Heater (gal) + + + + + option_21_lifetime + Option 21 Lifetime + The option lifetime. + Double + years + false + false + + + option_22 + Option 22 + Specify the parameter|option as found in resources\options_lookup.tsv. + String + false + false + + + option_22_apply_logic + Option 22 Apply Logic + Logic that specifies if the Option 22 upgrade will apply based on the existing building's options. Specify one or more parameter|option as found in resources\options_lookup.tsv. When multiple are included, they must be separated by '||' for OR and '&&' for AND, and using parentheses as appropriate. Prefix an option with '!' for not. + String + false + false + + + option_22_cost_1_value + Option 22 Cost 1 Value + Total option 22 cost is the sum of all: (Cost N Value) x (Cost N Multiplier). + Double + $ + false + false + + + option_22_cost_1_multiplier + Option 22 Cost 1 Multiplier + Total option 22 cost is the sum of all: (Cost N Value) x (Cost N Multiplier). + Choice + false + false + + + + + + + + Fixed (1) + Fixed (1) + + + Wall Area, Above-Grade, Conditioned (ft^2) + Wall Area, Above-Grade, Conditioned (ft^2) + + + Wall Area, Above-Grade, Exterior (ft^2) + Wall Area, Above-Grade, Exterior (ft^2) + + + Wall Area, Below-Grade (ft^2) + Wall Area, Below-Grade (ft^2) + + + Floor Area, Conditioned (ft^2) + Floor Area, Conditioned (ft^2) + + + Floor Area, Attic (ft^2) + Floor Area, Attic (ft^2) + + + Floor Area, Lighting (ft^2) + Floor Area, Lighting (ft^2) + + + Roof Area (ft^2) + Roof Area (ft^2) + + + Window Area (ft^2) + Window Area (ft^2) + + + Door Area (ft^2) + Door Area (ft^2) + + + Duct Surface Area (ft^2) + Duct Surface Area (ft^2) + + + Size, Heating System (kBtu/h) + Size, Heating System (kBtu/h) + + + Size, Cooling System (kBtu/h) + Size, Cooling System (kBtu/h) + + + Size, Water Heater (gal) + Size, Water Heater (gal) + + + + + option_22_cost_2_value + Option 22 Cost 2 Value + Total option 22 cost is the sum of all: (Cost N Value) x (Cost N Multiplier). + Double + $ + false + false + + + option_22_cost_2_multiplier + Option 22 Cost 2 Multiplier + Total option 22 cost is the sum of all: (Cost N Value) x (Cost N Multiplier). + Choice + false + false + + + + + + + + Fixed (1) + Fixed (1) + + + Wall Area, Above-Grade, Conditioned (ft^2) + Wall Area, Above-Grade, Conditioned (ft^2) + + + Wall Area, Above-Grade, Exterior (ft^2) + Wall Area, Above-Grade, Exterior (ft^2) + + + Wall Area, Below-Grade (ft^2) + Wall Area, Below-Grade (ft^2) + + + Floor Area, Conditioned (ft^2) + Floor Area, Conditioned (ft^2) + + + Floor Area, Attic (ft^2) + Floor Area, Attic (ft^2) + + + Floor Area, Lighting (ft^2) + Floor Area, Lighting (ft^2) + + + Roof Area (ft^2) + Roof Area (ft^2) + + + Window Area (ft^2) + Window Area (ft^2) + + + Door Area (ft^2) + Door Area (ft^2) + + + Duct Surface Area (ft^2) + Duct Surface Area (ft^2) + + + Size, Heating System (kBtu/h) + Size, Heating System (kBtu/h) + + + Size, Cooling System (kBtu/h) + Size, Cooling System (kBtu/h) + + + Size, Water Heater (gal) + Size, Water Heater (gal) + + + + + option_22_lifetime + Option 22 Lifetime + The option lifetime. + Double + years + false + false + + + option_23 + Option 23 + Specify the parameter|option as found in resources\options_lookup.tsv. + String + false + false + + + option_23_apply_logic + Option 23 Apply Logic + Logic that specifies if the Option 23 upgrade will apply based on the existing building's options. Specify one or more parameter|option as found in resources\options_lookup.tsv. When multiple are included, they must be separated by '||' for OR and '&&' for AND, and using parentheses as appropriate. Prefix an option with '!' for not. + String + false + false + + + option_23_cost_1_value + Option 23 Cost 1 Value + Total option 23 cost is the sum of all: (Cost N Value) x (Cost N Multiplier). + Double + $ + false + false + + + option_23_cost_1_multiplier + Option 23 Cost 1 Multiplier + Total option 23 cost is the sum of all: (Cost N Value) x (Cost N Multiplier). + Choice + false + false + + + + + + + + Fixed (1) + Fixed (1) + + + Wall Area, Above-Grade, Conditioned (ft^2) + Wall Area, Above-Grade, Conditioned (ft^2) + + + Wall Area, Above-Grade, Exterior (ft^2) + Wall Area, Above-Grade, Exterior (ft^2) + + + Wall Area, Below-Grade (ft^2) + Wall Area, Below-Grade (ft^2) + + + Floor Area, Conditioned (ft^2) + Floor Area, Conditioned (ft^2) + + + Floor Area, Attic (ft^2) + Floor Area, Attic (ft^2) + + + Floor Area, Lighting (ft^2) + Floor Area, Lighting (ft^2) + + + Roof Area (ft^2) + Roof Area (ft^2) + + + Window Area (ft^2) + Window Area (ft^2) + + + Door Area (ft^2) + Door Area (ft^2) + + + Duct Surface Area (ft^2) + Duct Surface Area (ft^2) + + + Size, Heating System (kBtu/h) + Size, Heating System (kBtu/h) + + + Size, Cooling System (kBtu/h) + Size, Cooling System (kBtu/h) + + + Size, Water Heater (gal) + Size, Water Heater (gal) + + + + + option_23_cost_2_value + Option 23 Cost 2 Value + Total option 23 cost is the sum of all: (Cost N Value) x (Cost N Multiplier). + Double + $ + false + false + + + option_23_cost_2_multiplier + Option 23 Cost 2 Multiplier + Total option 23 cost is the sum of all: (Cost N Value) x (Cost N Multiplier). + Choice + false + false + + + + + + + + Fixed (1) + Fixed (1) + + + Wall Area, Above-Grade, Conditioned (ft^2) + Wall Area, Above-Grade, Conditioned (ft^2) + + + Wall Area, Above-Grade, Exterior (ft^2) + Wall Area, Above-Grade, Exterior (ft^2) + + + Wall Area, Below-Grade (ft^2) + Wall Area, Below-Grade (ft^2) + + + Floor Area, Conditioned (ft^2) + Floor Area, Conditioned (ft^2) + + + Floor Area, Attic (ft^2) + Floor Area, Attic (ft^2) + + + Floor Area, Lighting (ft^2) + Floor Area, Lighting (ft^2) + + + Roof Area (ft^2) + Roof Area (ft^2) + + + Window Area (ft^2) + Window Area (ft^2) + + + Door Area (ft^2) + Door Area (ft^2) + + + Duct Surface Area (ft^2) + Duct Surface Area (ft^2) + + + Size, Heating System (kBtu/h) + Size, Heating System (kBtu/h) + + + Size, Cooling System (kBtu/h) + Size, Cooling System (kBtu/h) + + + Size, Water Heater (gal) + Size, Water Heater (gal) + + + + + option_23_lifetime + Option 23 Lifetime + The option lifetime. + Double + years + false + false + + + option_24 + Option 24 + Specify the parameter|option as found in resources\options_lookup.tsv. + String + false + false + + + option_24_apply_logic + Option 24 Apply Logic + Logic that specifies if the Option 24 upgrade will apply based on the existing building's options. Specify one or more parameter|option as found in resources\options_lookup.tsv. When multiple are included, they must be separated by '||' for OR and '&&' for AND, and using parentheses as appropriate. Prefix an option with '!' for not. + String + false + false + + + option_24_cost_1_value + Option 24 Cost 1 Value + Total option 24 cost is the sum of all: (Cost N Value) x (Cost N Multiplier). + Double + $ + false + false + + + option_24_cost_1_multiplier + Option 24 Cost 1 Multiplier + Total option 24 cost is the sum of all: (Cost N Value) x (Cost N Multiplier). + Choice + false + false + + + + + + + + Fixed (1) + Fixed (1) + + + Wall Area, Above-Grade, Conditioned (ft^2) + Wall Area, Above-Grade, Conditioned (ft^2) + + + Wall Area, Above-Grade, Exterior (ft^2) + Wall Area, Above-Grade, Exterior (ft^2) + + + Wall Area, Below-Grade (ft^2) + Wall Area, Below-Grade (ft^2) + + + Floor Area, Conditioned (ft^2) + Floor Area, Conditioned (ft^2) + + + Floor Area, Attic (ft^2) + Floor Area, Attic (ft^2) + + + Floor Area, Lighting (ft^2) + Floor Area, Lighting (ft^2) + + + Roof Area (ft^2) + Roof Area (ft^2) + + + Window Area (ft^2) + Window Area (ft^2) + + + Door Area (ft^2) + Door Area (ft^2) + + + Duct Surface Area (ft^2) + Duct Surface Area (ft^2) + + + Size, Heating System (kBtu/h) + Size, Heating System (kBtu/h) + + + Size, Cooling System (kBtu/h) + Size, Cooling System (kBtu/h) + + + Size, Water Heater (gal) + Size, Water Heater (gal) + + + + + option_24_cost_2_value + Option 24 Cost 2 Value + Total option 24 cost is the sum of all: (Cost N Value) x (Cost N Multiplier). + Double + $ + false + false + + + option_24_cost_2_multiplier + Option 24 Cost 2 Multiplier + Total option 24 cost is the sum of all: (Cost N Value) x (Cost N Multiplier). + Choice + false + false + + + + + + + + Fixed (1) + Fixed (1) + + + Wall Area, Above-Grade, Conditioned (ft^2) + Wall Area, Above-Grade, Conditioned (ft^2) + + + Wall Area, Above-Grade, Exterior (ft^2) + Wall Area, Above-Grade, Exterior (ft^2) + + + Wall Area, Below-Grade (ft^2) + Wall Area, Below-Grade (ft^2) + + + Floor Area, Conditioned (ft^2) + Floor Area, Conditioned (ft^2) + + + Floor Area, Attic (ft^2) + Floor Area, Attic (ft^2) + + + Floor Area, Lighting (ft^2) + Floor Area, Lighting (ft^2) + + + Roof Area (ft^2) + Roof Area (ft^2) + + + Window Area (ft^2) + Window Area (ft^2) + + + Door Area (ft^2) + Door Area (ft^2) + + + Duct Surface Area (ft^2) + Duct Surface Area (ft^2) + + + Size, Heating System (kBtu/h) + Size, Heating System (kBtu/h) + + + Size, Cooling System (kBtu/h) + Size, Cooling System (kBtu/h) + + + Size, Water Heater (gal) + Size, Water Heater (gal) + + + + + option_24_lifetime + Option 24 Lifetime + The option lifetime. + Double + years + false + false + + + option_25 + Option 25 + Specify the parameter|option as found in resources\options_lookup.tsv. + String + false + false + + + option_25_apply_logic + Option 25 Apply Logic + Logic that specifies if the Option 25 upgrade will apply based on the existing building's options. Specify one or more parameter|option as found in resources\options_lookup.tsv. When multiple are included, they must be separated by '||' for OR and '&&' for AND, and using parentheses as appropriate. Prefix an option with '!' for not. + String + false + false + + + option_25_cost_1_value + Option 25 Cost 1 Value + Total option 25 cost is the sum of all: (Cost N Value) x (Cost N Multiplier). + Double + $ + false + false + + + option_25_cost_1_multiplier + Option 25 Cost 1 Multiplier + Total option 25 cost is the sum of all: (Cost N Value) x (Cost N Multiplier). + Choice + false + false + + + + + + + + Fixed (1) + Fixed (1) + + + Wall Area, Above-Grade, Conditioned (ft^2) + Wall Area, Above-Grade, Conditioned (ft^2) + + + Wall Area, Above-Grade, Exterior (ft^2) + Wall Area, Above-Grade, Exterior (ft^2) + + + Wall Area, Below-Grade (ft^2) + Wall Area, Below-Grade (ft^2) + + + Floor Area, Conditioned (ft^2) + Floor Area, Conditioned (ft^2) + + + Floor Area, Attic (ft^2) + Floor Area, Attic (ft^2) + + + Floor Area, Lighting (ft^2) + Floor Area, Lighting (ft^2) + + + Roof Area (ft^2) + Roof Area (ft^2) + + + Window Area (ft^2) + Window Area (ft^2) + + + Door Area (ft^2) + Door Area (ft^2) + + + Duct Surface Area (ft^2) + Duct Surface Area (ft^2) + + + Size, Heating System (kBtu/h) + Size, Heating System (kBtu/h) + + + Size, Cooling System (kBtu/h) + Size, Cooling System (kBtu/h) + + + Size, Water Heater (gal) + Size, Water Heater (gal) + + + + + option_25_cost_2_value + Option 25 Cost 2 Value + Total option 25 cost is the sum of all: (Cost N Value) x (Cost N Multiplier). + Double + $ + false + false + + + option_25_cost_2_multiplier + Option 25 Cost 2 Multiplier + Total option 25 cost is the sum of all: (Cost N Value) x (Cost N Multiplier). + Choice + false + false + + + + + + + + Fixed (1) + Fixed (1) + + + Wall Area, Above-Grade, Conditioned (ft^2) + Wall Area, Above-Grade, Conditioned (ft^2) + + + Wall Area, Above-Grade, Exterior (ft^2) + Wall Area, Above-Grade, Exterior (ft^2) + + + Wall Area, Below-Grade (ft^2) + Wall Area, Below-Grade (ft^2) + + + Floor Area, Conditioned (ft^2) + Floor Area, Conditioned (ft^2) + + + Floor Area, Attic (ft^2) + Floor Area, Attic (ft^2) + + + Floor Area, Lighting (ft^2) + Floor Area, Lighting (ft^2) + + + Roof Area (ft^2) + Roof Area (ft^2) + + + Window Area (ft^2) + Window Area (ft^2) + + + Door Area (ft^2) + Door Area (ft^2) + + + Duct Surface Area (ft^2) + Duct Surface Area (ft^2) + + + Size, Heating System (kBtu/h) + Size, Heating System (kBtu/h) + + + Size, Cooling System (kBtu/h) + Size, Cooling System (kBtu/h) + + + Size, Water Heater (gal) + Size, Water Heater (gal) + + + + + option_25_lifetime + Option 25 Lifetime + The option lifetime. + Double + years + false + false + + + package_apply_logic + Package Apply Logic + Logic that specifies if the entire package upgrade (all options) will apply based on the existing building's options. Specify one or more parameter|option as found in resources\options_lookup.tsv. When multiple are included, they must be separated by '||' for OR and '&&' for AND, and using parentheses as appropriate. Prefix an option with '!' for not. + String + false + false + + + run_measure + Run Measure + integer argument to run measure [1 is run, 0 is no run] + Integer + true + false + 1 + + + + + + Whole Building.Space Types + + + + Intended Software Tool + Apply Measure Now + string + + + Intended Software Tool + OpenStudio Application + string + + + Intended Software Tool + Parametric Analysis Tool + string + + + Intended Software Tool + Apply Measure Now + string + + + Intended Software Tool + OpenStudio Application + string + + + Intended Software Tool + Parametric Analysis Tool + string + + + Measure Type + ModelMeasure + string + + + Intended Software Tool + Apply Measure Now + string + + + Intended Software Tool + OpenStudio Application + string + + + Intended Software Tool + Parametric Analysis Tool + string + + + + + + OpenStudio + 1.9.0 + 1.9.0 + + measure.rb + rb + script + 8E1786F4 + + + diff --git a/buildstockbatch/test/test_inputs/test_openstudio_buildstock/measures/BuildExistingModel/measure.rb b/buildstockbatch/test/test_inputs/test_openstudio_buildstock/measures/BuildExistingModel/measure.rb new file mode 100644 index 00000000..db4b4b0d --- /dev/null +++ b/buildstockbatch/test/test_inputs/test_openstudio_buildstock/measures/BuildExistingModel/measure.rb @@ -0,0 +1,225 @@ +# see the URL below for information on how to write OpenStudio measures +# http://nrel.github.io/OpenStudio-user-documentation/measures/measure_writing_guide/ + +require 'csv' +require 'openstudio' +if File.exists? File.absolute_path(File.join(File.dirname(__FILE__), "../../lib/resources/measures/HPXMLtoOpenStudio/resources")) # Hack to run ResStock on AWS + resources_path = File.absolute_path(File.join(File.dirname(__FILE__), "../../lib/resources/measures/HPXMLtoOpenStudio/resources")) +elsif File.exists? File.absolute_path(File.join(File.dirname(__FILE__), "../../resources/measures/HPXMLtoOpenStudio/resources")) # Hack to run ResStock unit tests locally + resources_path = File.absolute_path(File.join(File.dirname(__FILE__), "../../resources/measures/HPXMLtoOpenStudio/resources")) +elsif File.exists? File.join(OpenStudio::BCLMeasure::userMeasuresDir.to_s, "HPXMLtoOpenStudio/resources") # Hack to run measures in the OS App since applied measures are copied off into a temporary directory + resources_path = File.join(OpenStudio::BCLMeasure::userMeasuresDir.to_s, "HPXMLtoOpenStudio/resources") +else + resources_path = File.absolute_path(File.join(File.dirname(__FILE__), "../HPXMLtoOpenStudio/resources")) +end +require File.join(resources_path, "weather") + +# start the measure +class BuildExistingModel < OpenStudio::Measure::ModelMeasure + # human readable name + def name + return "Build Existing Model" + end + + # human readable description + def description + return "Builds the OpenStudio Model for an existing building." + end + + # human readable description of modeling approach + def modeler_description + return "Builds the OpenStudio Model using the sampling csv file, which contains the specified parameters for each existing building. Based on the supplied building number, those parameters are used to run the OpenStudio measures with appropriate arguments and build up the OpenStudio model." + end + + # define the arguments that the user will input + def arguments(model) + args = OpenStudio::Ruleset::OSArgumentVector.new + + building_id = OpenStudio::Ruleset::OSArgument.makeIntegerArgument("building_id", true) + building_id.setDisplayName("Building ID") + building_id.setDescription("The building number (between 1 and the number of samples).") + args << building_id + + workflow_json = OpenStudio::Ruleset::OSArgument.makeStringArgument("workflow_json", false) + workflow_json.setDisplayName("Workflow JSON") + workflow_json.setDescription("The name of the JSON file (in the resources dir) that dictates the order in which measures are to be run. If not provided, the order specified in resources/options_lookup.tsv will be used.") + args << workflow_json + + number_of_buildings_represented = OpenStudio::Ruleset::OSArgument.makeIntegerArgument("number_of_buildings_represented", false) + number_of_buildings_represented.setDisplayName("Number of Buildings Represented") + number_of_buildings_represented.setDescription("The total number of buildings represented by the existing building models.") + args << number_of_buildings_represented + + sample_weight = OpenStudio::Ruleset::OSArgument.makeDoubleArgument("sample_weight", false) + sample_weight.setDisplayName("Sample Weight of Simulation") + sample_weight.setDescription("Number of buildings this simulation represents.") + args << sample_weight + + downselect_logic = OpenStudio::Ruleset::OSArgument.makeStringArgument("downselect_logic", false) + downselect_logic.setDisplayName("Downselect Logic") + downselect_logic.setDescription("Logic that specifies the subset of the building stock to be considered in the analysis. Specify one or more parameter|option as found in resources\\options_lookup.tsv. When multiple are included, they must be separated by '||' for OR and '&&' for AND, and using parentheses as appropriate. Prefix an option with '!' for not.") + args << downselect_logic + + return args + end + + # define what happens when the measure is run + def run(model, runner, user_arguments) + super(model, runner, user_arguments) + + # use the built-in error checking + if !runner.validateUserArguments(arguments(model), user_arguments) + return false + end + + building_id = runner.getIntegerArgumentValue("building_id", user_arguments) + workflow_json = runner.getOptionalStringArgumentValue("workflow_json", user_arguments) + number_of_buildings_represented = runner.getOptionalIntegerArgumentValue("number_of_buildings_represented", user_arguments) + sample_weight = runner.getOptionalDoubleArgumentValue("sample_weight", user_arguments) + downselect_logic = runner.getOptionalStringArgumentValue("downselect_logic", user_arguments) + sample_weight = runner.getOptionalDoubleArgumentValue("sample_weight", user_arguments) + + # Get file/dir paths + resources_dir = File.absolute_path(File.join(File.dirname(__FILE__), "..", "..", "lib", "resources")) # Should have been uploaded per 'Additional Analysis Files' in PAT + characteristics_dir = File.absolute_path(File.join(File.dirname(__FILE__), "..", "..", "lib", "housing_characteristics")) # Should have been uploaded per 'Additional Analysis Files' in PAT + buildstock_file = File.join(resources_dir, "buildstock.rb") + measures_dir = File.join(resources_dir, "measures") + lookup_file = File.join(resources_dir, "options_lookup.tsv") + buildstock_csv = File.absolute_path(File.join(characteristics_dir, "buildstock.csv")) # Should have been generated by the Worker Initialization Script (run_sampling.rb) or provided by the project + if workflow_json.is_initialized + workflow_json = File.join(resources_dir, workflow_json.get) + else + workflow_json = nil + end + + # Load buildstock_file + require File.join(File.dirname(buildstock_file), File.basename(buildstock_file, File.extname(buildstock_file))) + + # Check file/dir paths exist + check_dir_exists(measures_dir, runner) + check_file_exists(lookup_file, runner) + check_file_exists(buildstock_csv, runner) + + # Retrieve all data associated with sample number + bldg_data = get_data_for_sample(buildstock_csv, building_id, runner) + + # Retrieve order of parameters to run + parameters_ordered = get_parameters_ordered_from_options_lookup_tsv(lookup_file, characteristics_dir) + + # Obtain measures and arguments to be called + measures = {} + parameters_ordered.each do |parameter_name| + # Get measure name and arguments associated with the option + option_name = bldg_data[parameter_name] + register_value(runner, parameter_name, option_name) + end + + # Do the downselecting + if downselect_logic.is_initialized + + downselect_logic = downselect_logic.get + downselect_logic = downselect_logic.strip + downselected = evaluate_logic(downselect_logic, runner, past_results = false) + + if downselected.nil? + return false + end + + unless downselected + # Not in downselection; don't run existing home simulation + runner.registerInfo("Sample is not in downselected parameters; will be registered as invalid.") + runner.haltWorkflow('Invalid') + return false + end + + end + + parameters_ordered.each do |parameter_name| + option_name = bldg_data[parameter_name] + print_option_assignment(parameter_name, option_name, runner) + options_measure_args = get_measure_args_from_option_names(lookup_file, [option_name], parameter_name, runner) + options_measure_args[option_name].each do |measure_subdir, args_hash| + update_args_hash(measures, measure_subdir, args_hash, add_new = false) + end + end + + # FIXME: Hack to run the correct ResStock geometry measure + if ["Single-Family Detached", "Mobile Home"].include? bldg_data["Geometry Building Type"] + measures.delete("ResidentialGeometryCreateSingleFamilyAttached") + measures.delete("ResidentialGeometryCreateMultifamily") + elsif bldg_data["Geometry Building Type"] == "Single-Family Attached" + measures.delete("ResidentialGeometryCreateSingleFamilyDetached") + measures.delete("ResidentialGeometryCreateMultifamily") + elsif ["Multi-Family with 2 - 4 Units", "Multi-Family with 5+ Units"].include? bldg_data["Geometry Building Type"] + measures.delete("ResidentialGeometryCreateSingleFamilyDetached") + measures.delete("ResidentialGeometryCreateSingleFamilyAttached") + end + + if not apply_measures(measures_dir, measures, runner, model, workflow_json, "measures.osw", true) + return false + end + + # Report some additional location and model characteristics + weather = WeatherProcess.new(model, runner) + if !weather.error? + register_value(runner, "location_city", weather.header.City) + register_value(runner, "location_state", weather.header.State) + register_value(runner, "location_latitude", "#{weather.header.Latitude}") + register_value(runner, "location_longitude", "#{weather.header.Longitude}") + climate_zone_ba = Location.get_climate_zone_ba(weather.header.Station) + climate_zone_iecc = Location.get_climate_zone_iecc(weather.header.Station) + unless climate_zone_ba.nil? + register_value(runner, "climate_zone_ba", climate_zone_ba) + end + unless climate_zone_iecc.nil? + register_value(runner, "climate_zone_iecc", climate_zone_iecc) + end + if climate_zone_ba.nil? and climate_zone_iecc.nil? + runner.registerInfo("The weather station WMO has not been set appropriately in the EPW weather file header.") + end + end + register_value(runner, "units_represented", "#{model.getBuilding.additionalProperties.getFeatureAsInteger("Total Units Represented").get}") + register_value(runner, "units_modeled", "#{model.getBuilding.additionalProperties.getFeatureAsInteger("Total Units Modeled").get}") + + # Determine weight + if number_of_buildings_represented.is_initialized + total_samples = nil + runner.analysis[:analysis][:problem][:workflow].each do |wf| + next if wf[:name] != 'build_existing_model' + + wf[:variables].each do |v| + next if v[:argument][:name] != 'building_id' + + total_samples = v[:maximum].to_f + end + end + if total_samples.nil? + runner.registerError("Could not retrieve value for number_of_buildings_represented.") + return false + end + weight = number_of_buildings_represented.get / total_samples + register_value(runner, "weight", weight.to_s) + end + + if sample_weight.is_initialized + register_value(runner, "weight", sample_weight.get.to_s) + end + + return true + end + + def get_data_for_sample(buildstock_csv, building_id, runner) + CSV.foreach(buildstock_csv, headers: true) do |sample| + next if sample["Building"].to_i != building_id + + return sample + end + # If we got this far, couldn't find the sample # + msg = "Could not find row for #{building_id.to_s} in #{File.basename(buildstock_csv).to_s}." + runner.registerError(msg) + fail msg + end +end + +# register the measure to be used by the application +BuildExistingModel.new.registerWithApplication diff --git a/buildstockbatch/test/test_inputs/test_openstudio_buildstock/measures/BuildExistingModel/measure.xml b/buildstockbatch/test/test_inputs/test_openstudio_buildstock/measures/BuildExistingModel/measure.xml new file mode 100644 index 00000000..41b0ce05 --- /dev/null +++ b/buildstockbatch/test/test_inputs/test_openstudio_buildstock/measures/BuildExistingModel/measure.xml @@ -0,0 +1,79 @@ + + 3.0 + build_existing_model + dedf59bb-3b88-4f16-8755-2c1ff5519cbf + f9175b4b-d4c5-42e5-8773-ccb9ee6ff90c + 20190530T151539Z + 2C38F48B + BuildExistingModel + Build Existing Model + Builds the OpenStudio Model for an existing building. + Builds the OpenStudio Model using the sampling csv file, which contains the specified parameters for each existing building. Based on the supplied building number, those parameters are used to run the OpenStudio measures with appropriate arguments and build up the OpenStudio model. + + + building_id + Building ID + The building number (between 1 and the number of samples). + Integer + true + false + + + workflow_json + Workflow JSON + The name of the JSON file (in the resources dir) that dictates the order in which measures are to be run. If not provided, the order specified in resources/options_lookup.tsv will be used. + String + false + false + + + number_of_buildings_represented + Number of Buildings Represented + The total number of buildings represented by the existing building models. + Integer + false + false + + + sample_weight + Sample Weight of Simulation + Number of buildings this simulation represents. + Double + false + false + + + downselect_logic + Downselect Logic + Logic that specifies the subset of the building stock to be considered in the analysis. Specify one or more parameter|option as found in resources\options_lookup.tsv. When multiple are included, they must be separated by '||' for OR and '&&' for AND, and using parentheses as appropriate. Prefix an option with '!' for not. + String + false + false + + + + + + Whole Building.Space Types + + + + Measure Type + ModelMeasure + string + + + + + + OpenStudio + 2.6.1 + 2.6.1 + + measure.rb + rb + script + DDA682AD + + + diff --git a/buildstockbatch/test/test_inputs/test_openstudio_buildstock/measures/ResidentialSimulationControls/measure.rb b/buildstockbatch/test/test_inputs/test_openstudio_buildstock/measures/ResidentialSimulationControls/measure.rb new file mode 100644 index 00000000..d2078a21 --- /dev/null +++ b/buildstockbatch/test/test_inputs/test_openstudio_buildstock/measures/ResidentialSimulationControls/measure.rb @@ -0,0 +1,148 @@ +# insert your copyright here + +# see the URL below for information on how to write OpenStudio measures +# http://nrel.github.io/OpenStudio-user-documentation/reference/measure_writing_guide/ + +if File.exists? File.absolute_path(File.join(File.dirname(__FILE__), "../../lib/resources/measures/HPXMLtoOpenStudio/resources")) # Hack to run ResStock on AWS + resources_path = File.absolute_path(File.join(File.dirname(__FILE__), "../../lib/resources/measures/HPXMLtoOpenStudio/resources")) +elsif File.exists? File.absolute_path(File.join(File.dirname(__FILE__), "../../resources/measures/HPXMLtoOpenStudio/resources")) # Hack to run ResStock unit tests locally + resources_path = File.absolute_path(File.join(File.dirname(__FILE__), "../../resources/measures/HPXMLtoOpenStudio/resources")) +elsif File.exists? File.join(OpenStudio::BCLMeasure::userMeasuresDir.to_s, "HPXMLtoOpenStudio/resources") # Hack to run measures in the OS App since applied measures are copied off into a temporary directory + resources_path = File.join(OpenStudio::BCLMeasure::userMeasuresDir.to_s, "HPXMLtoOpenStudio/resources") +else + resources_path = File.absolute_path(File.join(File.dirname(__FILE__), "../HPXMLtoOpenStudio/resources")) +end +require File.join(resources_path, "constants") +require File.join(resources_path, "simulation") + +# start the measure +class ResidentialSimulationControls < OpenStudio::Measure::ModelMeasure + # human readable name + def name + # Measure name should be the title case of the class name. + return 'Set Residential Simulation Controls' + end + + # human readable description + def description + return 'Set the simulation timesteps per hour, the run period begin month/day and end month/day, and the calendar year (for start day of week).' + end + + # human readable description of modeling approach + def modeler_description + return 'Set the simulation timesteps per hour on the Timestep object, the run period begin month/day and end month/day on the RunPeriod object, and the calendar year on the YearDescription object.' + end + + # define the arguments that the user will input + def arguments(model) + args = OpenStudio::Measure::OSArgumentVector.new + + # make an argument for the simulation timesteps per hour + arg = OpenStudio::Measure::OSArgument::makeIntegerArgument("timesteps_per_hr", true) + arg.setDisplayName("Simulation Timesteps Per Hour") + arg.setDescription("The value entered here is the number of (zone) timesteps to use within an hour. For example a value of 6 entered here directs the program to use a zone timestep of 10 minutes and a value of 60 means a 1 minute timestep.") + arg.setDefaultValue(6) + args << arg + + # make an argument for the run period begin month + arg = OpenStudio::Measure::OSArgument::makeIntegerArgument("begin_month", true) + arg.setDisplayName("Run Period Begin Month") + arg.setDescription("This numeric field should contain the starting month number (1 = January, 2 = February, etc.) for the annual run period desired.") + arg.setDefaultValue(1) + args << arg + + # make an argument for the run period begin day of month + arg = OpenStudio::Measure::OSArgument::makeIntegerArgument("begin_day_of_month", true) + arg.setDisplayName("Run Period Begin Day of Month") + arg.setDescription("This numeric field should contain the starting day of the starting month (must be valid for month) for the annual run period desired.") + arg.setDefaultValue(1) + args << arg + + # make an argument for the run period end month + arg = OpenStudio::Measure::OSArgument::makeIntegerArgument("end_month", true) + arg.setDisplayName("Run Period End Month") + arg.setDescription("This numeric field should contain the ending month number (1 = January, 2 = February, etc.) for the annual run period desired.") + arg.setDefaultValue(12) + args << arg + + # make an argument for the run period end day of month + arg = OpenStudio::Measure::OSArgument::makeIntegerArgument("end_day_of_month", true) + arg.setDisplayName("Run Period End Day of Month") + arg.setDescription("This numeric field should contain the ending day of the ending month (must be valid for month) for the annual run period desired.") + arg.setDefaultValue(31) + args << arg + + # make an argument for the calendar year; this determines the day of week for start day + arg = OpenStudio::Measure::OSArgument::makeIntegerArgument("calendar_year", true) + arg.setDisplayName("Calendar Year") + arg.setDescription("This numeric field should contain the calendar year that determines the start day of week. If you are running simulations using AMY weather files, the value entered for calendar year will not be used; it will be overridden by the actual year found in the AMY weather file.") + arg.setDefaultValue(2007) + args << arg + + return args + end + + # define what happens when the measure is run + def run(model, runner, user_arguments) + super(model, runner, user_arguments) + + # use the built-in error checking + if !runner.validateUserArguments(arguments(model), user_arguments) + return false + end + + timesteps_per_hr = runner.getIntegerArgumentValue("timesteps_per_hr", user_arguments) + begin_month = runner.getIntegerArgumentValue("begin_month", user_arguments) + begin_day_of_month = runner.getIntegerArgumentValue("begin_day_of_month", user_arguments) + end_month = runner.getIntegerArgumentValue("end_month", user_arguments) + end_day_of_month = runner.getIntegerArgumentValue("end_day_of_month", user_arguments) + calendar_year = runner.getIntegerArgumentValue("calendar_year", user_arguments) + + # Error checking + if timesteps_per_hr < 1 or timesteps_per_hr > 60 + runner.registerError("User-entered #{timesteps_per_hr} timesteps per hour must be between 1 and 60.") + return false + end + + if 60 % timesteps_per_hr != 0 + runner.registerError("User-entered #{timesteps_per_hr} timesteps per hour does not divide evenly into 60.") + return false + end + + if not (1..12).to_a.include? begin_month or not (1..12).to_a.include? end_month + runner.registerError("Invalid begin month (#{begin_month}) and/or end month (#{end_month}) entered.") + return false + end + + { begin_month => begin_day_of_month, end_month => end_day_of_month }.each_with_index do |(month, day), i| + leap_day = 0 + leap_day += 1 if month == 2 # february + day_of_month_valid = (1..Constants.NumDaysInMonths[month - 1] + leap_day).to_a.include? day # accommodate leap day + unless day_of_month_valid + if i == 0 + runner.registerError("Invalid begin day of month (#{begin_day_of_month}) entered.") + elsif i == 1 + runner.registerError("Invalid end day of month (#{end_day_of_month}) entered.") + end + return false + end + end + + if calendar_year < 1600 or calendar_year > 9999 + runner.registerError("Your calendar year value of #{calendar_year} is not in the range 1600-9999.") + return false + end + + success = Simulation.apply(model, runner, timesteps_per_hr, min_system_timestep_mins = nil, begin_month, begin_day_of_month, end_month, end_day_of_month, calendar_year) + return false if not success + + runner.registerInfo("Set the simulation timesteps per hour to #{timesteps_per_hr}.") + runner.registerInfo("Set the run period begin and end month/day to #{begin_month}/#{begin_day_of_month} and #{end_month}/#{end_day_of_month}, respectively.") + runner.registerInfo("Set the calendar year to #{model.getYearDescription.calendarYear} and the start day of week to #{model.getYearDescription.dayofWeekforStartDay}; if you are running with AMY, this will be overridden by the AMY year.") + + return true + end +end + +# register the measure to be used by the application +ResidentialSimulationControls.new.registerWithApplication diff --git a/buildstockbatch/test/test_inputs/test_openstudio_buildstock/measures/ResidentialSimulationControls/measure.xml b/buildstockbatch/test/test_inputs/test_openstudio_buildstock/measures/ResidentialSimulationControls/measure.xml new file mode 100644 index 00000000..c6059e9f --- /dev/null +++ b/buildstockbatch/test/test_inputs/test_openstudio_buildstock/measures/ResidentialSimulationControls/measure.xml @@ -0,0 +1,99 @@ + + 3.0 + residential_simulation_controls + 874f921e-8f3c-458a-a82f-01b7d51a547e + b9258fa8-94ae-4f8e-b4f3-af203eae89cc + 20190709T162534Z + 2C38F48B + ResidentialSimulationControls + Set Residential Simulation Controls + Set the simulation timesteps per hour, the run period begin month/day and end month/day, and the calendar year (for start day of week). + Set the simulation timesteps per hour on the Timestep object, the run period begin month/day and end month/day on the RunPeriod object, and the calendar year on the YearDescription object. + + + timesteps_per_hr + Simulation Timesteps Per Hour + The value entered here is the number of (zone) timesteps to use within an hour. For example a value of 6 entered here directs the program to use a zone timestep of 10 minutes and a value of 60 means a 1 minute timestep. + Integer + true + false + 6 + + + begin_month + Run Period Begin Month + This numeric field should contain the starting month number (1 = January, 2 = February, etc.) for the annual run period desired. + Integer + true + false + 1 + + + begin_day_of_month + Run Period Begin Day of Month + This numeric field should contain the starting day of the starting month (must be valid for month) for the annual run period desired. + Integer + true + false + 1 + + + end_month + Run Period End Month + This numeric field should contain the ending month number (1 = January, 2 = February, etc.) for the annual run period desired. + Integer + true + false + 12 + + + end_day_of_month + Run Period End Day of Month + This numeric field should contain the ending day of the ending month (must be valid for month) for the annual run period desired. + Integer + true + false + 31 + + + calendar_year + Calendar Year + This numeric field should contain the calendar year that determines the start day of week. If you are running simulations using AMY weather files, the value entered for calendar year will not be used; it will be overridden by the actual year found in the AMY weather file. + Integer + true + false + 2007 + + + + + + Whole Building.Space Types + + + + Measure Type + ModelMeasure + string + + + + + set_simulation_controls_test.rb + rb + test + 056A2C0C + + + + OpenStudio + 2.6.0 + 2.6.0 + + measure.rb + rb + script + 0036CB06 + + + diff --git a/buildstockbatch/test/test_inputs/test_openstudio_buildstock/measures/ServerDirectoryCleanup/measure.rb b/buildstockbatch/test/test_inputs/test_openstudio_buildstock/measures/ServerDirectoryCleanup/measure.rb new file mode 100644 index 00000000..087f101e --- /dev/null +++ b/buildstockbatch/test/test_inputs/test_openstudio_buildstock/measures/ServerDirectoryCleanup/measure.rb @@ -0,0 +1,83 @@ +# start the measure +class ServerDirectoryCleanup < OpenStudio::Measure::ReportingMeasure + # define the name that a user will see, this method may be deprecated as + # the display name in PAT comes from the name field in measure.xml + def name + "Server Directory Cleanup" + end + + # define the arguments that the user will input + def arguments() + args = OpenStudio::Ruleset::OSArgumentVector.new + end # end the arguments method + + # define what happens when the measure is run + def run(runner, user_arguments) + super(runner, user_arguments) + + # use the built-in error checking + unless runner.validateUserArguments(arguments, user_arguments) + false + end + + initial_string = "The following files were in the local run directory prior to the execution of this measure: " + Dir.entries("./../").each do |f| + initial_string << "#{f}, " + end + initial_string = initial_string[0..(initial_string.length - 3)] + "." + runner.registerInitialCondition(initial_string) + + Dir.glob("./../*.sql").each do |f| + File.delete(f) + runner.registerInfo("Deleted #{f} from the run directory.") if !File.exist?(f) + end + Dir.glob("./../*.audit").each do |f| + File.delete(f) + runner.registerInfo("Deleted #{f} from the run directory.") if !File.exist?(f) + end + Dir.glob("./../in.osm").each do |f| + File.delete(f) + runner.registerInfo("Deleted #{f} from the run directory.") if !File.exist?(f) + end + Dir.glob("./../../in.osm").each do |f| + File.delete(f) + runner.registerInfo("Deleted #{f} from the run directory.") if !File.exist?(f) + end + Dir.glob("./../*.bnd").each do |f| + File.delete(f) + runner.registerInfo("Deleted #{f} from the run directory.") if !File.exist?(f) + end + Dir.glob("./../*.eio").each do |f| + File.delete(f) + runner.registerInfo("Deleted #{f} from the run directory.") if !File.exist?(f) + end + Dir.glob("./../*.shd").each do |f| + File.delete(f) + runner.registerInfo("Deleted #{f} from the run directory.") if !File.exist?(f) + end + Dir.glob("./../*.mdd").each do |f| + File.delete(f) + runner.registerInfo("Deleted #{f} from the run directory.") if !File.exist?(f) + end + Dir.glob("./../*.eso").each do |f| + File.delete(f) + runner.registerInfo("Deleted #{f} from the run directory.") if !File.exist?(f) + end + Dir.glob("./../pre-preprocess.idf").each do |f| + File.delete(f) + runner.registerInfo("Deleted #{f} from the run directory.") if !File.exist?(f) + end + + final_string = "The following files were in the local run directory following the execution of this measure: " + Dir.entries("./..").each do |f| + final_string << "#{f}, " + end + final_string = final_string[0..(final_string.length - 3)] + "." + runner.registerFinalCondition(final_string) + + true + end # end the run method +end # end the measure + +# this allows the measure to be use by the application +ServerDirectoryCleanup.new.registerWithApplication diff --git a/buildstockbatch/test/test_inputs/test_openstudio_buildstock/measures/ServerDirectoryCleanup/measure.xml b/buildstockbatch/test/test_inputs/test_openstudio_buildstock/measures/ServerDirectoryCleanup/measure.xml new file mode 100644 index 00000000..dee78103 --- /dev/null +++ b/buildstockbatch/test/test_inputs/test_openstudio_buildstock/measures/ServerDirectoryCleanup/measure.xml @@ -0,0 +1,43 @@ + + 3.0 + server_directory_cleanup + ec7d04ad-0b7b-495b-825a-e1b6d28d1d3f + c9dc043c-2ea2-4960-b281-37b9cb49c491 + 20190409T200600Z + 5F1EDF75 + ServerDirectoryCleanup + Server Directory Cleanup + Removes a significant portion of the saved results from each run, helping to alleviate memory problems. + Use during large server runs, when individual sequel files and the like will not be needed. + + + + + Calibration + + + + Measure Type + ReportingMeasure + string + + + Uses SketchUp API + false + boolean + + + + + + OpenStudio + 1.11.5 + 1.11.5 + + measure.rb + rb + script + 12635A5E + + + diff --git a/buildstockbatch/test/test_inputs/test_openstudio_buildstock/measures/SimulationOutputReport/measure.rb b/buildstockbatch/test/test_inputs/test_openstudio_buildstock/measures/SimulationOutputReport/measure.rb new file mode 100644 index 00000000..7a5140e8 --- /dev/null +++ b/buildstockbatch/test/test_inputs/test_openstudio_buildstock/measures/SimulationOutputReport/measure.rb @@ -0,0 +1,1115 @@ +require 'openstudio' +if File.exists? File.absolute_path(File.join(File.dirname(__FILE__), "../../lib/resources/measures/HPXMLtoOpenStudio/resources")) # Hack to run ResStock on AWS + resources_path = File.absolute_path(File.join(File.dirname(__FILE__), "../../lib/resources/measures/HPXMLtoOpenStudio/resources")) +elsif File.exists? File.absolute_path(File.join(File.dirname(__FILE__), "../../resources/measures/HPXMLtoOpenStudio/resources")) # Hack to run ResStock unit tests locally + resources_path = File.absolute_path(File.join(File.dirname(__FILE__), "../../resources/measures/HPXMLtoOpenStudio/resources")) +elsif File.exists? File.join(OpenStudio::BCLMeasure::userMeasuresDir.to_s, "HPXMLtoOpenStudio/resources") # Hack to run measures in the OS App since applied measures are copied off into a temporary directory + resources_path = File.join(OpenStudio::BCLMeasure::userMeasuresDir.to_s, "HPXMLtoOpenStudio/resources") +else + resources_path = File.absolute_path(File.join(File.dirname(__FILE__), "../HPXMLtoOpenStudio/resources")) +end +require File.join(resources_path, "unit_conversions") +require File.join(resources_path, "waterheater") + +# start the measure +class SimulationOutputReport < OpenStudio::Measure::ReportingMeasure + # define the name that a user will see, this method may be deprecated as + # the display name in PAT comes from the name field in measure.xml + def name + return "Simulation Output Report" + end + + def description + return "Reports simulation outputs of interest." + end + + def num_options + return Constants.NumApplyUpgradeOptions # Synced with SimulationOutputReport measure + end + + def num_costs_per_option + return Constants.NumApplyUpgradesCostsPerOption # Synced with SimulationOutputReport measure + end + + # define the arguments that the user will input + def arguments + args = OpenStudio::Ruleset::OSArgumentVector.new + + return args + end # end the arguments method + + # return a vector of IdfObject's to request EnergyPlus objects needed by the run method + def energyPlusOutputRequests(runner, user_arguments) + super(runner, user_arguments) + + return OpenStudio::IdfObjectVector.new if runner.halted + + # get the last model and sql file + model = runner.lastOpenStudioModel + if model.empty? + runner.registerError("Cannot find last model.") + return false + end + model = model.get + + results = OutputMeters.create_custom_building_unit_meters(model, runner, "RunPeriod") + return results + end + + def outputs + buildstock_outputs = [ + "total_site_energy_mbtu", + "total_site_electricity_kwh", + "total_site_natural_gas_therm", + "total_site_fuel_oil_mbtu", + "total_site_propane_mbtu", + "net_site_energy_mbtu", # Incorporates PV + "net_site_electricity_kwh", # Incorporates PV + "electricity_heating_kwh", + "electricity_central_system_heating_kwh", + "electricity_cooling_kwh", + "electricity_central_system_cooling_kwh", + "electricity_interior_lighting_kwh", + "electricity_exterior_lighting_kwh", + "electricity_interior_equipment_kwh", + "electricity_fans_heating_kwh", + "electricity_fans_cooling_kwh", + "electricity_pumps_heating_kwh", + "electricity_central_system_pumps_heating_kwh", + "electricity_pumps_cooling_kwh", + "electricity_central_system_pumps_cooling_kwh", + "electricity_water_systems_kwh", + "electricity_pv_kwh", + "natural_gas_heating_therm", + "natural_gas_central_system_heating_therm", + "natural_gas_interior_equipment_therm", + "natural_gas_water_systems_therm", + "fuel_oil_heating_mbtu", + "fuel_oil_central_system_heating_mbtu", + "fuel_oil_interior_equipment_mbtu", + "fuel_oil_water_systems_mbtu", + "propane_heating_mbtu", + "propane_central_system_heating_mbtu", + "propane_interior_equipment_mbtu", + "propane_water_systems_mbtu", + "hours_heating_setpoint_not_met", + "hours_cooling_setpoint_not_met", + "hvac_cooling_capacity_w", + "hvac_heating_capacity_w", + "hvac_heating_supp_capacity_w", + "upgrade_name", + "upgrade_cost_usd" + ] + for option_num in 1..num_options + buildstock_outputs << "upgrade_option_%02d_cost_usd" % option_num + buildstock_outputs << "upgrade_option_%02d_lifetime_yrs" % option_num + end + buildstock_outputs << "weight" + + result = OpenStudio::Measure::OSOutputVector.new + buildstock_outputs.each do |output| + result << OpenStudio::Measure::OSOutput.makeDoubleOutput(output) + end + return result + end + + # define what happens when the measure is run + def run(runner, user_arguments) + super(runner, user_arguments) + + # use the built-in error checking + if not runner.validateUserArguments(arguments(), user_arguments) + return false + end + + # get the last model and sql file + model = runner.lastOpenStudioModel + if model.empty? + runner.registerError("Cannot find last model.") + return false + end + model = model.get + + sqlFile = runner.lastEnergyPlusSqlFile + if sqlFile.empty? + runner.registerError("Cannot find last sql file.") + return false + end + sqlFile = sqlFile.get + model.setSqlFile(sqlFile) + + ann_env_pd = nil + sqlFile.availableEnvPeriods.each do |env_pd| + env_type = sqlFile.environmentType(env_pd) + if env_type.is_initialized + if env_type.get == OpenStudio::EnvironmentType.new("WeatherRunPeriod") + ann_env_pd = env_pd + end + end + end + if ann_env_pd == false + runner.registerError("Can't find a weather runperiod, make sure you ran an annual simulation, not just the design days.") + return false + end + + env_period_ix_query = "SELECT EnvironmentPeriodIndex FROM EnvironmentPeriods WHERE EnvironmentName='#{ann_env_pd}'" + env_period_ix = sqlFile.execAndReturnFirstInt(env_period_ix_query).get + + # Load buildstock_file + resources_dir = File.absolute_path(File.join(File.dirname(__FILE__), "..", "..", "lib", "resources")) # Should have been uploaded per 'Other Library Files' in analysis spreadsheet + buildstock_file = File.join(resources_dir, "buildstock.rb") + require File.join(File.dirname(buildstock_file), File.basename(buildstock_file, File.extname(buildstock_file))) + + total_site_units = "MBtu" + elec_site_units = "kWh" + gas_site_units = "therm" + other_fuel_site_units = "MBtu" + + # Get meters that aren't tied to units (i.e., are metered at the building level) + modeledCentralElectricityHeating = 0.0 + modeledCentralElectricityCooling = 0.0 + modeledCentralElectricityExteriorLighting = 0.0 + modeledCentralElectricityExteriorHolidayLighting = 0.0 + modeledCentralElectricityPumpsHeating = 0.0 + modeledCentralElectricityPumpsCooling = 0.0 + modeledCentralElectricityInteriorEquipment = 0.0 + modeledCentralNaturalGasHeating = 0.0 + modeledCentralNaturalGasInteriorEquipment = 0.0 + modeledCentralFuelOilHeating = 0.0 + modeledCentralFuelOilInteriorEquipment = 0.0 + modeledCentralPropaneHeating = 0.0 + modeledCentralPropaneInteriorEquipment = 0.0 + + central_electricity_heating_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('CENTRAL:ELECTRICITYHEATING') AND ReportingFrequency='Run Period' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" + unless sqlFile.execAndReturnFirstDouble(central_electricity_heating_query).empty? + modeledCentralElectricityHeating = sqlFile.execAndReturnFirstDouble(central_electricity_heating_query).get.round(2) + end + + central_electricity_cooling_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('CENTRAL:ELECTRICITYCOOLING') AND ReportingFrequency='Run Period' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" + unless sqlFile.execAndReturnFirstDouble(central_electricity_cooling_query).empty? + modeledCentralElectricityCooling = sqlFile.execAndReturnFirstDouble(central_electricity_cooling_query).get.round(2) + end + + central_electricity_exterior_lighting_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('CENTRAL:ELECTRICITYEXTERIORLIGHTING') AND ReportingFrequency='Run Period' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" + unless sqlFile.execAndReturnFirstDouble(central_electricity_exterior_lighting_query).empty? + modeledCentralElectricityExteriorLighting = sqlFile.execAndReturnFirstDouble(central_electricity_exterior_lighting_query).get.round(2) + end + + central_electricity_exterior_holiday_lighting_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('CENTRAL:ELECTRICITYEXTERIORHOLIDAYLIGHTING') AND ReportingFrequency='Run Period' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" + unless sqlFile.execAndReturnFirstDouble(central_electricity_exterior_holiday_lighting_query).empty? + modeledCentralElectricityExteriorHolidayLighting = sqlFile.execAndReturnFirstDouble(central_electricity_exterior_holiday_lighting_query).get.round(2) + end + + central_electricity_pumps_heating_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('CENTRAL:ELECTRICITYPUMPSHEATING') AND ReportingFrequency='Run Period' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" + unless sqlFile.execAndReturnFirstDouble(central_electricity_pumps_heating_query).empty? + modeledCentralElectricityPumpsHeating = sqlFile.execAndReturnFirstDouble(central_electricity_pumps_heating_query).get.round(2) + end + + central_electricity_pumps_cooling_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('CENTRAL:ELECTRICITYPUMPSCOOLING') AND ReportingFrequency='Run Period' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" + unless sqlFile.execAndReturnFirstDouble(central_electricity_pumps_cooling_query).empty? + modeledCentralElectricityPumpsCooling = sqlFile.execAndReturnFirstDouble(central_electricity_pumps_cooling_query).get.round(2) + end + + central_electricity_interior_equipment_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('CENTRAL:ELECTRICITYINTERIOREQUIPMENT') AND ReportingFrequency='Run Period' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" + unless sqlFile.execAndReturnFirstDouble(central_electricity_interior_equipment_query).empty? + modeledCentralElectricityInteriorEquipment = sqlFile.execAndReturnFirstDouble(central_electricity_interior_equipment_query).get.round(2) + end + + central_natural_gas_heating_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('CENTRAL:NATURALGASHEATING') AND ReportingFrequency='Run Period' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" + unless sqlFile.execAndReturnFirstDouble(central_natural_gas_heating_query).empty? + modeledCentralNaturalGasHeating = sqlFile.execAndReturnFirstDouble(central_natural_gas_heating_query).get.round(2) + end + + central_natural_gas_interior_equipment_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('CENTRAL:NATURALGASINTERIOREQUIPMENT') AND ReportingFrequency='Run Period' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" + unless sqlFile.execAndReturnFirstDouble(central_natural_gas_interior_equipment_query).empty? + modeledCentralNaturalGasInteriorEquipment = sqlFile.execAndReturnFirstDouble(central_natural_gas_interior_equipment_query).get.round(2) + end + + central_fuel_oil_heating_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('CENTRAL:FUELOILHEATING') AND ReportingFrequency='Run Period' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" + unless sqlFile.execAndReturnFirstDouble(central_fuel_oil_heating_query).empty? + modeledCentralFuelOilHeating = sqlFile.execAndReturnFirstDouble(central_fuel_oil_heating_query).get.round(2) + end + + central_fuel_oil_interior_equipment_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('CENTRAL:FUELOILINTERIOREQUIPMENT') AND ReportingFrequency='Run Period' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" + unless sqlFile.execAndReturnFirstDouble(central_fuel_oil_interior_equipment_query).empty? + modeledCentralFuelOilInteriorEquipment = sqlFile.execAndReturnFirstDouble(central_fuel_oil_interior_equipment_query).get.round(2) + end + + central_propane_heating_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('CENTRAL:PROPANEHEATING') AND ReportingFrequency='Run Period' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" + unless sqlFile.execAndReturnFirstDouble(central_propane_heating_query).empty? + modeledCentralPropaneHeating = sqlFile.execAndReturnFirstDouble(central_propane_heating_query).get.round(2) + end + + central_propane_interior_equipment_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('CENTRAL:PROPANEINTERIOREQUIPMENT') AND ReportingFrequency='Run Period' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" + unless sqlFile.execAndReturnFirstDouble(central_propane_interior_equipment_query).empty? + modeledCentralPropaneInteriorEquipment = sqlFile.execAndReturnFirstDouble(central_propane_interior_equipment_query).get.round(2) + end + + # Initialize variables to check against sql file totals + modeledElectricityFansHeating = 0.0 + modeledElectricityFansCooling = 0.0 + modeledElectricityPumpsHeating = modeledCentralElectricityPumpsHeating + modeledElectricityPumpsCooling = modeledCentralElectricityPumpsCooling + + # Separate these from non central systems + centralElectricityHeating = 0.0 + centralElectricityCooling = 0.0 + centralElectricityPumpsHeating = 0.0 + centralElectricityPumpsCooling = 0.0 + centralNaturalGasHeating = 0.0 + centralFuelOilHeating = 0.0 + centralPropaneHeating = 0.0 + + # Get meters that are tied to units, and apportion building level meters to these + electricityTotalEndUses = 0.0 + electricityHeating = 0.0 + electricityCooling = 0.0 + electricityInteriorLighting = 0.0 + electricityExteriorLighting = 0.0 + electricityExteriorHolidayLighting = modeledCentralElectricityExteriorHolidayLighting + electricityInteriorEquipment = 0.0 + electricityFansHeating = 0.0 + electricityFansCooling = 0.0 + electricityPumpsHeating = 0.0 + electricityPumpsCooling = 0.0 + electricityWaterSystems = 0.0 + naturalGasTotalEndUses = 0.0 + naturalGasHeating = 0.0 + naturalGasInteriorEquipment = 0.0 + naturalGasWaterSystems = 0.0 + fuelOilTotalEndUses = 0.0 + fuelOilHeating = 0.0 + fuelOilInteriorEquipment = 0.0 + fuelOilWaterSystems = 0.0 + propaneTotalEndUses = 0.0 + propaneHeating = 0.0 + propaneInteriorEquipment = 0.0 + propaneWaterSystems = 0.0 + hoursHeatingSetpointNotMet = 0.0 + hoursCoolingSetpointNotMet = 0.0 + + # Get building units + units = Geometry.get_building_units(model, runner) + if units.nil? + return false + end + + total_units_represented = 0 + units.each do |unit| + unit_name = unit.name.to_s.upcase + + thermal_zones = [] + unit.spaces.each do |space| + thermal_zone = space.thermalZone.get + unless thermal_zones.include? thermal_zone + thermal_zones << thermal_zone + end + end + + units_represented = 1 + if unit.additionalProperties.getFeatureAsInteger("Units Represented").is_initialized + units_represented = unit.additionalProperties.getFeatureAsInteger("Units Represented").get + end + total_units_represented += units_represented + + electricity_heating_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:ELECTRICITYHEATING') AND ReportingFrequency='Run Period' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" + unless sqlFile.execAndReturnFirstDouble(electricity_heating_query).empty? + electricityHeating += units_represented * sqlFile.execAndReturnFirstDouble(electricity_heating_query).get.round(2) + end + + centralElectricityHeating += units_represented * (modeledCentralElectricityHeating / units.length) + + electricity_cooling_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:ELECTRICITYCOOLING') AND ReportingFrequency='Run Period' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" + unless sqlFile.execAndReturnFirstDouble(electricity_cooling_query).empty? + electricityCooling += units_represented * sqlFile.execAndReturnFirstDouble(electricity_cooling_query).get.round(2) + end + + centralElectricityCooling += units_represented * (modeledCentralElectricityCooling / units.length) + + electricity_interior_lighting_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:ELECTRICITYINTERIORLIGHTING') AND ReportingFrequency='Run Period' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" + unless sqlFile.execAndReturnFirstDouble(electricity_interior_lighting_query).empty? + electricityInteriorLighting += units_represented * sqlFile.execAndReturnFirstDouble(electricity_interior_lighting_query).get.round(2) + end + + electricityExteriorLighting += units_represented * (modeledCentralElectricityExteriorLighting / units.length) + + electricity_interior_equipment_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:ELECTRICITYINTERIOREQUIPMENT') AND ReportingFrequency='Run Period' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" + unless sqlFile.execAndReturnFirstDouble(electricity_interior_equipment_query).empty? + electricityInteriorEquipment += units_represented * sqlFile.execAndReturnFirstDouble(electricity_interior_equipment_query).get.round(2) + end + electricityInteriorEquipment += units_represented * (modeledCentralElectricityInteriorEquipment / units.length) + + electricity_fans_heating_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:ELECTRICITYFANSHEATING') AND ReportingFrequency='Run Period' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" + unless sqlFile.execAndReturnFirstDouble(electricity_fans_heating_query).empty? + electricityFansHeating += units_represented * sqlFile.execAndReturnFirstDouble(electricity_fans_heating_query).get.round(2) + modeledElectricityFansHeating += sqlFile.execAndReturnFirstDouble(electricity_fans_heating_query).get.round(2) + end + + electricity_fans_cooling_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:ELECTRICITYFANSCOOLING') AND ReportingFrequency='Run Period' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" + unless sqlFile.execAndReturnFirstDouble(electricity_fans_cooling_query).empty? + electricityFansCooling += units_represented * sqlFile.execAndReturnFirstDouble(electricity_fans_cooling_query).get.round(2) + modeledElectricityFansCooling += sqlFile.execAndReturnFirstDouble(electricity_fans_cooling_query).get.round(2) + end + + electricity_pumps_heating_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:ELECTRICITYPUMPSHEATING') AND ReportingFrequency='Run Period' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" + unless sqlFile.execAndReturnFirstDouble(electricity_pumps_heating_query).empty? + electricityPumpsHeating += units_represented * sqlFile.execAndReturnFirstDouble(electricity_pumps_heating_query).get.round(2) + modeledElectricityPumpsHeating += sqlFile.execAndReturnFirstDouble(electricity_pumps_heating_query).get.round(2) + end + + centralElectricityPumpsHeating += units_represented * (modeledCentralElectricityPumpsHeating / units.length) + + electricity_pumps_cooling_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:ELECTRICITYPUMPSCOOLING') AND ReportingFrequency='Run Period' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" + unless sqlFile.execAndReturnFirstDouble(electricity_pumps_cooling_query).empty? + electricityPumpsCooling += units_represented * sqlFile.execAndReturnFirstDouble(electricity_pumps_cooling_query).get.round(2) + modeledElectricityPumpsCooling += sqlFile.execAndReturnFirstDouble(electricity_pumps_cooling_query).get.round(2) + end + + centralElectricityPumpsCooling += units_represented * (modeledCentralElectricityPumpsCooling / units.length) + + electricity_water_systems_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:ELECTRICITYWATERSYSTEMS') AND ReportingFrequency='Run Period' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" + unless sqlFile.execAndReturnFirstDouble(electricity_water_systems_query).empty? + electricityWaterSystems += units_represented * sqlFile.execAndReturnFirstDouble(electricity_water_systems_query).get.round(2) + end + + natural_gas_heating_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:NATURALGASHEATING') AND ReportingFrequency='Run Period' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" + unless sqlFile.execAndReturnFirstDouble(natural_gas_heating_query).empty? + naturalGasHeating += units_represented * sqlFile.execAndReturnFirstDouble(natural_gas_heating_query).get.round(2) + end + + centralNaturalGasHeating += units_represented * (modeledCentralNaturalGasHeating / units.length) + + natural_gas_interior_equipment_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:NATURALGASINTERIOREQUIPMENT') AND ReportingFrequency='Run Period' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" + unless sqlFile.execAndReturnFirstDouble(natural_gas_interior_equipment_query).empty? + naturalGasInteriorEquipment += units_represented * sqlFile.execAndReturnFirstDouble(natural_gas_interior_equipment_query).get.round(2) + end + naturalGasInteriorEquipment += units_represented * (modeledCentralNaturalGasInteriorEquipment / units.length) + + natural_gas_water_systems_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:NATURALGASWATERSYSTEMS') AND ReportingFrequency='Run Period' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" + unless sqlFile.execAndReturnFirstDouble(natural_gas_water_systems_query).empty? + naturalGasWaterSystems += units_represented * sqlFile.execAndReturnFirstDouble(natural_gas_water_systems_query).get.round(2) + end + + fuel_oil_heating_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:FUELOILHEATING') AND ReportingFrequency='Run Period' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" + unless sqlFile.execAndReturnFirstDouble(fuel_oil_heating_query).empty? + fuelOilHeating += units_represented * sqlFile.execAndReturnFirstDouble(fuel_oil_heating_query).get.round(2) + end + + centralFuelOilHeating += units_represented * (modeledCentralFuelOilHeating / units.length) + + fuel_oil_interior_equipment_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:FUELOILINTERIOREQUIPMENT') AND ReportingFrequency='Run Period' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" + unless sqlFile.execAndReturnFirstDouble(fuel_oil_interior_equipment_query).empty? + fuelOilInteriorEquipment += units_represented * sqlFile.execAndReturnFirstDouble(fuel_oil_interior_equipment_query).get.round(2) + end + fuelOilInteriorEquipment += units_represented * (modeledCentralFuelOilInteriorEquipment / units.length) + + fuel_oil_water_systems_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:FUELOILWATERSYSTEMS') AND ReportingFrequency='Run Period' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" + unless sqlFile.execAndReturnFirstDouble(fuel_oil_water_systems_query).empty? + fuelOilWaterSystems += units_represented * sqlFile.execAndReturnFirstDouble(fuel_oil_water_systems_query).get.round(2) + end + + propane_heating_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:PROPANEHEATING') AND ReportingFrequency='Run Period' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" + unless sqlFile.execAndReturnFirstDouble(propane_heating_query).empty? + propaneHeating += units_represented * sqlFile.execAndReturnFirstDouble(propane_heating_query).get.round(2) + end + + centralPropaneHeating += units_represented * (modeledCentralPropaneHeating / units.length) + + propane_interior_equipment_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:PROPANEINTERIOREQUIPMENT') AND ReportingFrequency='Run Period' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" + unless sqlFile.execAndReturnFirstDouble(propane_interior_equipment_query).empty? + propaneInteriorEquipment += units_represented * sqlFile.execAndReturnFirstDouble(propane_interior_equipment_query).get.round(2) + end + propaneInteriorEquipment += units_represented * (modeledCentralPropaneInteriorEquipment / units.length) + + propane_water_systems_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:PROPANEWATERSYSTEMS') AND ReportingFrequency='Run Period' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" + unless sqlFile.execAndReturnFirstDouble(propane_water_systems_query).empty? + propaneWaterSystems += units_represented * sqlFile.execAndReturnFirstDouble(propane_water_systems_query).get.round(2) + end + + thermal_zones.each do |thermal_zone| + thermal_zone_name = thermal_zone.name.to_s.upcase + hours_heating_setpoint_not_met_query = "SELECT Value FROM TabularDataWithStrings WHERE (ReportName='SystemSummary') AND (ReportForString='Entire Facility') AND (TableName='Time Setpoint Not Met') AND (RowName = '#{thermal_zone_name}') AND (ColumnName='During Heating') AND (Units = 'hr')" + unless sqlFile.execAndReturnFirstDouble(hours_heating_setpoint_not_met_query).empty? + hoursHeatingSetpointNotMet += units_represented * sqlFile.execAndReturnFirstDouble(hours_heating_setpoint_not_met_query).get + end + + hours_cooling_setpoint_not_met_query = "SELECT Value FROM TabularDataWithStrings WHERE (ReportName='SystemSummary') AND (ReportForString='Entire Facility') AND (TableName='Time Setpoint Not Met') AND (RowName = '#{thermal_zone_name}') AND (ColumnName='During Cooling') AND (Units = 'hr')" + unless sqlFile.execAndReturnFirstDouble(hours_cooling_setpoint_not_met_query).empty? + hoursCoolingSetpointNotMet += units_represented * sqlFile.execAndReturnFirstDouble(hours_cooling_setpoint_not_met_query).get + end + end + end + + # ELECTRICITY + + # Get PV electricity produced + pv_query = "SELECT -1*Value FROM TabularDataWithStrings WHERE ReportName='AnnualBuildingUtilityPerformanceSummary' AND ReportForString='Entire Facility' AND TableName='Electric Loads Satisfied' AND RowName='Total On-Site Electric Sources' AND ColumnName='Electricity' AND Units='GJ'" + pv_val = 0.0 + unless sqlFile.execAndReturnFirstDouble(pv_query).empty? + pv_val = sqlFile.execAndReturnFirstDouble(pv_query).get + end + report_sim_output(runner, "electricity_pv_kwh", pv_val, "GJ", elec_site_units) + + electricityTotalEndUses = electricityHeating + centralElectricityHeating + electricityCooling + centralElectricityCooling + electricityInteriorLighting + electricityExteriorLighting + electricityExteriorHolidayLighting + electricityInteriorEquipment + electricityFansHeating + electricityFansCooling + electricityPumpsHeating + centralElectricityPumpsHeating + electricityPumpsCooling + centralElectricityPumpsCooling + electricityWaterSystems + + report_sim_output(runner, "total_site_electricity_kwh", electricityTotalEndUses, "GJ", elec_site_units) + report_sim_output(runner, "net_site_electricity_kwh", electricityTotalEndUses + pv_val, "GJ", elec_site_units) + report_sim_output(runner, "electricity_heating_kwh", electricityHeating, "GJ", elec_site_units) + report_sim_output(runner, "electricity_central_system_heating_kwh", centralElectricityHeating, "GJ", elec_site_units) + report_sim_output(runner, "electricity_cooling_kwh", electricityCooling, "GJ", elec_site_units) + report_sim_output(runner, "electricity_central_system_cooling_kwh", centralElectricityCooling, "GJ", elec_site_units) + report_sim_output(runner, "electricity_interior_lighting_kwh", electricityInteriorLighting, "GJ", elec_site_units) + report_sim_output(runner, "electricity_exterior_lighting_kwh", electricityExteriorLighting + electricityExteriorHolidayLighting, "GJ", elec_site_units) + report_sim_output(runner, "electricity_interior_equipment_kwh", electricityInteriorEquipment, "GJ", elec_site_units) + electricityFans = 0.0 + unless sqlFile.electricityFans.empty? + electricityFans = sqlFile.electricityFans.get + end + err = (modeledElectricityFansHeating + modeledElectricityFansCooling) - electricityFans + if err.abs > 0.2 + runner.registerError("Disaggregated fan energy (#{modeledElectricityFansHeating + modeledElectricityFansCooling} GJ) relative to building fan energy (#{electricityFans} GJ): #{err} GJ.") + return false + end + report_sim_output(runner, "electricity_fans_heating_kwh", electricityFansHeating, "GJ", elec_site_units) + report_sim_output(runner, "electricity_fans_cooling_kwh", electricityFansCooling, "GJ", elec_site_units) + electricityPumps = 0.0 + unless sqlFile.electricityPumps.empty? + electricityPumps = sqlFile.electricityPumps.get + end + err = (modeledElectricityPumpsHeating + modeledElectricityPumpsCooling) - electricityPumps + if err.abs > 0.2 + runner.registerError("Disaggregated pump energy (#{modeledElectricityPumpsHeating + modeledElectricityPumpsCooling} GJ) relative to building pump energy (#{electricityPumps} GJ): #{err} GJ.") + return false + end + report_sim_output(runner, "electricity_pumps_heating_kwh", electricityPumpsHeating, "GJ", elec_site_units) + report_sim_output(runner, "electricity_central_system_pumps_heating_kwh", centralElectricityPumpsHeating, "GJ", elec_site_units) + report_sim_output(runner, "electricity_pumps_cooling_kwh", electricityPumpsCooling, "GJ", elec_site_units) + report_sim_output(runner, "electricity_central_system_pumps_cooling_kwh", centralElectricityPumpsCooling, "GJ", elec_site_units) + report_sim_output(runner, "electricity_water_systems_kwh", electricityWaterSystems, "GJ", elec_site_units) + + # NATURAL GAS + + naturalGasTotalEndUses = naturalGasHeating + centralNaturalGasHeating + naturalGasInteriorEquipment + naturalGasWaterSystems + + report_sim_output(runner, "total_site_natural_gas_therm", naturalGasTotalEndUses, "GJ", gas_site_units) + report_sim_output(runner, "natural_gas_heating_therm", naturalGasHeating, "GJ", gas_site_units) + report_sim_output(runner, "natural_gas_central_system_heating_therm", centralNaturalGasHeating, "GJ", gas_site_units) + report_sim_output(runner, "natural_gas_interior_equipment_therm", naturalGasInteriorEquipment, "GJ", gas_site_units) + report_sim_output(runner, "natural_gas_water_systems_therm", naturalGasWaterSystems, "GJ", gas_site_units) + + # FUEL OIL + + fuelOilTotalEndUses = fuelOilHeating + centralFuelOilHeating + fuelOilInteriorEquipment + fuelOilWaterSystems + + report_sim_output(runner, "total_site_fuel_oil_mbtu", fuelOilTotalEndUses, "GJ", other_fuel_site_units) + report_sim_output(runner, "fuel_oil_heating_mbtu", fuelOilHeating, "GJ", other_fuel_site_units) + report_sim_output(runner, "fuel_oil_central_system_heating_mbtu", centralFuelOilHeating, "GJ", other_fuel_site_units) + report_sim_output(runner, "fuel_oil_interior_equipment_mbtu", fuelOilInteriorEquipment, "GJ", other_fuel_site_units) + report_sim_output(runner, "fuel_oil_water_systems_mbtu", fuelOilWaterSystems, "GJ", other_fuel_site_units) + + # PROPANE + + propaneTotalEndUses = propaneHeating + centralPropaneHeating + propaneInteriorEquipment + propaneWaterSystems + + report_sim_output(runner, "total_site_propane_mbtu", propaneTotalEndUses, "GJ", other_fuel_site_units) + report_sim_output(runner, "propane_heating_mbtu", propaneHeating, "GJ", other_fuel_site_units) + report_sim_output(runner, "propane_central_system_heating_mbtu", centralPropaneHeating, "GJ", other_fuel_site_units) + report_sim_output(runner, "propane_interior_equipment_mbtu", propaneInteriorEquipment, "GJ", other_fuel_site_units) + report_sim_output(runner, "propane_water_systems_mbtu", propaneWaterSystems, "GJ", other_fuel_site_units) + + # TOTAL + + totalSiteEnergy = electricityTotalEndUses + naturalGasTotalEndUses + fuelOilTotalEndUses + propaneTotalEndUses + + if units.length == total_units_represented + err = totalSiteEnergy - sqlFile.totalSiteEnergy.get + if err.abs > 0.5 + runner.registerError("Disaggregated total site energy (#{totalSiteEnergy} GJ) relative to building total site energy (#{sqlFile.totalSiteEnergy.get} GJ): #{err} GJ.") + return false + end + end + report_sim_output(runner, "total_site_energy_mbtu", totalSiteEnergy, "GJ", total_site_units) + report_sim_output(runner, "net_site_energy_mbtu", totalSiteEnergy + pv_val, "GJ", total_site_units) + + # LOADS NOT MET + + report_sim_output(runner, "hours_heating_setpoint_not_met", hoursHeatingSetpointNotMet, nil, nil) + report_sim_output(runner, "hours_cooling_setpoint_not_met", hoursCoolingSetpointNotMet, nil, nil) + + # HVAC CAPACITIES + + conditioned_zones = get_conditioned_zones(model) + hvac_cooling_capacity_kbtuh = get_cost_multiplier("Size, Cooling System (kBtu/h)", model, runner, conditioned_zones) + return false if hvac_cooling_capacity_kbtuh.nil? + + report_sim_output(runner, "hvac_cooling_capacity_w", hvac_cooling_capacity_kbtuh, "kBtu/hr", "W") + hvac_heating_capacity_kbtuh = get_cost_multiplier("Size, Heating System (kBtu/h)", model, runner, conditioned_zones) + return false if hvac_heating_capacity_kbtuh.nil? + + report_sim_output(runner, "hvac_heating_capacity_w", hvac_heating_capacity_kbtuh, "kBtu/hr", "W") + hvac_heating_supp_capacity_kbtuh = get_cost_multiplier("Size, Heating Supplemental System (kBtu/h)", model, runner, conditioned_zones) + return false if hvac_heating_supp_capacity_kbtuh.nil? + + report_sim_output(runner, "hvac_heating_supp_capacity_w", hvac_heating_supp_capacity_kbtuh, "kBtu/hr", "W") + + sqlFile.close() + + # WEIGHT + + weight = get_value_from_runner_past_results(runner, "weight", "build_existing_model", false) + if not weight.nil? + runner.registerValue("weight", weight.to_f) + runner.registerInfo("Registering #{weight} for weight.") + end + + # UPGRADE NAME + upgrade_name = get_value_from_runner_past_results(runner, "upgrade_name", "apply_upgrade", false) + if upgrade_name.nil? + upgrade_name = "" + end + runner.registerValue("upgrade_name", upgrade_name) + runner.registerInfo("Registering #{upgrade_name} for upgrade_name.") + + # UPGRADE COSTS + + upgrade_cost_name = "upgrade_cost_usd" + + # Get upgrade cost value/multiplier pairs and lifetimes from the upgrade measure + has_costs = false + option_cost_pairs = {} + option_lifetimes = {} + for option_num in 1..num_options # Sync with ApplyUpgrade measure + option_cost_pairs[option_num] = [] + option_lifetimes[option_num] = nil + for cost_num in 1..num_costs_per_option # Sync with ApplyUpgrade measure + cost_value = get_value_from_runner_past_results(runner, "option_#{option_num}_cost_#{cost_num}_value_to_apply", "apply_upgrade", false) + next if cost_value.nil? + + cost_mult_type = get_value_from_runner_past_results(runner, "option_#{option_num}_cost_#{cost_num}_multiplier_to_apply", "apply_upgrade", false) + next if cost_mult_type.nil? + + has_costs = true + option_cost_pairs[option_num] << [cost_value.to_f, cost_mult_type] + end + lifetime = get_value_from_runner_past_results(runner, "option_#{option_num}_lifetime_to_apply", "apply_upgrade", false) + next if lifetime.nil? + + option_lifetimes[option_num] = lifetime.to_f + end + + if not has_costs + runner.registerValue(upgrade_cost_name, "") + runner.registerInfo("Registering (blank) for #{upgrade_cost_name}.") + return true + end + + # Obtain cost multiplier values and calculate upgrade costs + upgrade_cost = 0.0 + option_cost_pairs.keys.each do |option_num| + option_cost = 0.0 + option_cost_pairs[option_num].each do |cost_value, cost_mult_type| + cost_mult = get_cost_multiplier(cost_mult_type, model, runner, conditioned_zones) + if cost_mult.nil? + return false + end + + total_cost = cost_value * cost_mult + option_cost += total_cost + runner.registerInfo("Upgrade cost addition: $#{cost_value} x #{cost_mult} [#{cost_mult_type}] = #{total_cost}.") + end + upgrade_cost += option_cost + + # Save option cost/lifetime to results.csv + if option_cost != 0 + option_num_str = option_num.to_s.rjust(2, '0') + option_cost_str = option_cost.round(2).to_s + option_cost_name = "upgrade_option_#{option_num_str}_cost_usd" + runner.registerValue(option_cost_name, option_cost_str) + runner.registerInfo("Registering #{option_cost_str} for #{option_cost_name}.") + if not option_lifetimes[option_num].nil? and option_lifetimes[option_num] != 0 + lifetime_str = option_lifetimes[option_num].round(2).to_s + option_lifetime_name = "upgrade_option_#{option_num_str}_lifetime_yrs" + runner.registerValue(option_lifetime_name, lifetime_str) + runner.registerInfo("Registering #{lifetime_str} for #{option_lifetime_name}.") + end + end + end + upgrade_cost_str = upgrade_cost.round(2).to_s + runner.registerValue(upgrade_cost_name, upgrade_cost_str) + runner.registerInfo("Registering #{upgrade_cost_str} for #{upgrade_cost_name}.") + + runner.registerFinalCondition("Report generated successfully.") + + return true + end # end the run method + + def report_sim_output(runner, name, total_val, os_units, desired_units, percent_of_val = 1.0) + total_val = total_val * percent_of_val + if os_units.nil? or desired_units.nil? or os_units == desired_units + valInUnits = total_val + else + valInUnits = UnitConversions.convert(total_val, os_units, desired_units) + end + runner.registerValue(name, valInUnits) + runner.registerInfo("Registering #{valInUnits.round(2)} for #{name}.") + end + + def get_cost_multiplier(cost_mult_type, model, runner, conditioned_zones) + cost_mult = 0.0 + + if cost_mult_type == "Fixed (1)" + cost_mult = 1.0 + + elsif cost_mult_type == "Wall Area, Above-Grade, Conditioned (ft^2)" + # Walls between conditioned space and 1) outdoors or 2) unconditioned space + model.getSurfaces.each do |surface| + next if surface.surfaceType.downcase != "wall" + next if not surface.space.is_initialized + next if not is_space_conditioned(surface.space.get, conditioned_zones) + + adjacent_space = get_adjacent_space(surface) + if surface.outsideBoundaryCondition.downcase == "outdoors" + cost_mult += UnitConversions.convert(surface.grossArea, "m^2", "ft^2") + elsif !adjacent_space.nil? and not is_space_conditioned(adjacent_space, conditioned_zones) + cost_mult += UnitConversions.convert(surface.grossArea, "m^2", "ft^2") + end + end + + elsif cost_mult_type == "Wall Area, Above-Grade, Exterior (ft^2)" + # Walls adjacent to outdoors + model.getSurfaces.each do |surface| + next if surface.surfaceType.downcase != "wall" + next if surface.outsideBoundaryCondition.downcase != "outdoors" + + cost_mult += UnitConversions.convert(surface.grossArea, "m^2", "ft^2") + end + + elsif cost_mult_type == "Wall Area, Below-Grade (ft^2)" + # Walls adjacent to ground + model.getSurfaces.each do |surface| + next if surface.surfaceType.downcase != "wall" + next if surface.outsideBoundaryCondition.downcase != "ground" and surface.outsideBoundaryCondition.downcase != "foundation" + + cost_mult += UnitConversions.convert(surface.grossArea, "m^2", "ft^2") + end + + elsif cost_mult_type == "Floor Area, Conditioned (ft^2)" + # Floors of conditioned zone + model.getSurfaces.each do |surface| + next if surface.surfaceType.downcase != "floor" + next if not surface.space.is_initialized + next if not is_space_conditioned(surface.space.get, conditioned_zones) + + cost_mult += UnitConversions.convert(surface.grossArea, "m^2", "ft^2") + end + + elsif cost_mult_type == "Floor Area, Attic (ft^2)" + # Floors under sloped surfaces and above conditioned space + model.getSurfaces.each do |surface| + next if surface.surfaceType.downcase != "floor" + next if not surface.space.is_initialized + + space = surface.space.get + next if not has_sloped_roof_surfaces(space) + + adjacent_space = get_adjacent_space(surface) + next if adjacent_space.nil? + next if not is_space_conditioned(adjacent_space, conditioned_zones) + + cost_mult += UnitConversions.convert(surface.grossArea, "m^2", "ft^2") + end + + elsif cost_mult_type == "Floor Area, Lighting (ft^2)" + # Floors with lighting objects + model.getSurfaces.each do |surface| + next if surface.surfaceType.downcase != "floor" + next if not surface.space.is_initialized + next if surface.space.get.lights.size == 0 + + cost_mult += UnitConversions.convert(surface.grossArea, "m^2", "ft^2") + end + + elsif cost_mult_type == "Roof Area (ft^2)" + # Roofs adjacent to outdoors + model.getSurfaces.each do |surface| + next if surface.surfaceType.downcase != "roofceiling" + next if surface.outsideBoundaryCondition.downcase != "outdoors" + + cost_mult += UnitConversions.convert(surface.grossArea, "m^2", "ft^2") + end + + elsif cost_mult_type == "Window Area (ft^2)" + # Window subsurfaces + model.getSurfaces.each do |surface| + next if surface.surfaceType.downcase != "wall" + + surface.subSurfaces.each do |sub_surface| + next if not sub_surface.subSurfaceType.downcase.include? "window" + + cost_mult += UnitConversions.convert(sub_surface.grossArea, "m^2", "ft^2") + end + end + + elsif cost_mult_type == "Door Area (ft^2)" + # Door subsurfaces + model.getSurfaces.each do |surface| + next if surface.surfaceType.downcase != "wall" + + surface.subSurfaces.each do |sub_surface| + next if not sub_surface.subSurfaceType.downcase.include? "door" + + cost_mult += UnitConversions.convert(sub_surface.grossArea, "m^2", "ft^2") + end + end + + elsif cost_mult_type == "Duct Surface Area (ft^2)" + # Duct supply+return surface area + model.getBuildingUnits.each do |unit| + next if unit.spaces.size == 0 + + if cost_mult > 0 + runner.registerError("Multiple building units found. This code should be reevaluated for correctness.") + return nil + end + supply_area = unit.getFeatureAsDouble("SizingInfoDuctsSupplySurfaceArea") + if supply_area.is_initialized + cost_mult += supply_area.get + end + return_area = unit.getFeatureAsDouble("SizingInfoDuctsReturnSurfaceArea") + if return_area.is_initialized + cost_mult += return_area.get + end + end + + elsif cost_mult_type == "Size, Heating System (kBtu/h)" + # Heating system capacity + + all_conditioned_zones = conditioned_zones + + model.getBuildingUnits.each do |unit| + next if unit.spaces.empty? + + conditioned_zones = [] + unit.spaces.each do |space| + zone = space.thermalZone.get + next unless all_conditioned_zones.include? zone + next if conditioned_zones.include? zone + + conditioned_zones << zone + end + + units_represented = 1 + if unit.additionalProperties.getFeatureAsInteger("Units Represented").is_initialized + units_represented = unit.additionalProperties.getFeatureAsInteger("Units Represented").get + end + + component = nil + + # Unit heater? + if component.nil? + conditioned_zones.each do |zone| + zone.equipment.each do |equipment| + next unless equipment.to_AirLoopHVACUnitarySystem.is_initialized + + sys = equipment.to_AirLoopHVACUnitarySystem.get + next unless conditioned_zones.include? sys.controllingZoneorThermostatLocation.get + next if not sys.heatingCoil.is_initialized + + component = sys.heatingCoil.get + next if not component.to_CoilHeatingGas.is_initialized + + coil = component.to_CoilHeatingGas.get + next if not coil.nominalCapacity.is_initialized + + cost_mult += UnitConversions.convert(coil.nominalCapacity.get, "W", "kBtu/hr") + end + end + end + + # Unitary system? + if component.nil? + model.getAirLoopHVACUnitarySystems.each do |sys| + next unless conditioned_zones.include? sys.controllingZoneorThermostatLocation.get + next if not sys.heatingCoil.is_initialized + + if not component.nil? + runner.registerError("Multiple heating systems found. This code should be reevaluated for correctness.") + return nil + end + component = sys.heatingCoil.get + end + if not component.nil? + if component.to_CoilHeatingDXSingleSpeed.is_initialized + coil = component.to_CoilHeatingDXSingleSpeed.get + if coil.ratedTotalHeatingCapacity.is_initialized + cost_mult += UnitConversions.convert(coil.ratedTotalHeatingCapacity.get, "W", "kBtu/hr") + end + elsif component.to_CoilHeatingDXMultiSpeed.is_initialized + coil = component.to_CoilHeatingDXMultiSpeed.get + if coil.stages.size > 0 + stage = coil.stages[coil.stages.size - 1] + capacity_ratio = get_highest_stage_capacity_ratio(model, "SizingInfoHVACCapacityRatioCooling") + if stage.grossRatedHeatingCapacity.is_initialized + cost_mult += UnitConversions.convert(stage.grossRatedHeatingCapacity.get / capacity_ratio, "W", "kBtu/hr") + end + end + elsif component.to_CoilHeatingGas.is_initialized + coil = component.to_CoilHeatingGas.get + if coil.nominalCapacity.is_initialized + cost_mult += UnitConversions.convert(coil.nominalCapacity.get, "W", "kBtu/hr") + end + elsif component.to_CoilHeatingElectric.is_initialized + coil = component.to_CoilHeatingElectric.get + if coil.nominalCapacity.is_initialized + cost_mult += UnitConversions.convert(coil.nominalCapacity.get, "W", "kBtu/hr") + end + elsif component.to_CoilHeatingWaterToAirHeatPumpEquationFit.is_initialized + coil = component.to_CoilHeatingWaterToAirHeatPumpEquationFit.get + if coil.ratedHeatingCapacity.is_initialized + cost_mult += UnitConversions.convert(coil.ratedHeatingCapacity.get, "W", "kBtu/hr") + end + end + end + end + + # Electric baseboard? + if component.nil? + max_value = 0.0 + model.getZoneHVACBaseboardConvectiveElectrics.each do |sys| + next unless conditioned_zones.include? sys.thermalZone.get + + component = sys + next if not component.nominalCapacity.is_initialized + + cost_mult += UnitConversions.convert(component.nominalCapacity.get, "W", "kBtu/hr") + end + end + + # Boiler? + if component.nil? + max_value = 0.0 + model.getPlantLoops.each do |pl| + pl.components.each do |plc| + next if not plc.to_BoilerHotWater.is_initialized + + component = plc.to_BoilerHotWater.get + next if not component.nominalCapacity.is_initialized + next if component.nominalCapacity.get <= max_value + + max_value = component.nominalCapacity.get + end + end + cost_mult += UnitConversions.convert(max_value, "W", "kBtu/hr") + end + + cost_mult *= units_represented + end + + elsif cost_mult_type == "Size, Heating Supplemental System (kBtu/h)" + # Supplemental heating system capacity + + all_conditioned_zones = conditioned_zones + + model.getBuildingUnits.each do |unit| + next if unit.spaces.empty? + + conditioned_zones = [] + unit.spaces.each do |space| + zone = space.thermalZone.get + next unless all_conditioned_zones.include? zone + next if conditioned_zones.include? zone + + conditioned_zones << zone + end + + units_represented = 1 + if unit.additionalProperties.getFeatureAsInteger("Units Represented").is_initialized + units_represented = unit.additionalProperties.getFeatureAsInteger("Units Represented").get + end + + component = nil + + # Unitary system? + if component.nil? + model.getAirLoopHVACUnitarySystems.each do |sys| + next unless conditioned_zones.include? sys.controllingZoneorThermostatLocation.get + next if not sys.supplementalHeatingCoil.is_initialized + + if not component.nil? + runner.registerError("Multiple supplemental heating systems found. This code should be reevaluated for correctness.") + return nil + end + component = sys.supplementalHeatingCoil.get + end + if not component.nil? + if component.to_CoilHeatingElectric.is_initialized + coil = component.to_CoilHeatingElectric.get + if coil.nominalCapacity.is_initialized + cost_mult += UnitConversions.convert(coil.nominalCapacity.get, "W", "kBtu/hr") + end + end + end + end + + cost_mult *= units_represented + end + + elsif cost_mult_type == "Size, Cooling System (kBtu/h)" + # Cooling system capacity + + all_conditioned_zones = conditioned_zones + + model.getBuildingUnits.each do |unit| + next if unit.spaces.empty? + + conditioned_zones = [] + unit.spaces.each do |space| + zone = space.thermalZone.get + next unless all_conditioned_zones.include? zone + next if conditioned_zones.include? zone + + conditioned_zones << zone + end + + units_represented = 1 + if unit.additionalProperties.getFeatureAsInteger("Units Represented").is_initialized + units_represented = unit.additionalProperties.getFeatureAsInteger("Units Represented").get + end + + component = nil + + # Unitary system? + if component.nil? + model.getAirLoopHVACUnitarySystems.each do |sys| + next unless conditioned_zones.include? sys.controllingZoneorThermostatLocation.get + next if not sys.coolingCoil.is_initialized + + if not component.nil? + runner.registerError("Multiple cooling systems found. This code should be reevaluated for correctness.") + return nil + end + component = sys.coolingCoil.get + end + if not component.nil? + if component.to_CoilCoolingDXSingleSpeed.is_initialized + coil = component.to_CoilCoolingDXSingleSpeed.get + if coil.ratedTotalCoolingCapacity.is_initialized + cost_mult += UnitConversions.convert(coil.ratedTotalCoolingCapacity.get, "W", "kBtu/hr") + end + elsif component.to_CoilCoolingDXMultiSpeed.is_initialized + coil = component.to_CoilCoolingDXMultiSpeed.get + if coil.stages.size > 0 + stage = coil.stages[coil.stages.size - 1] + capacity_ratio = get_highest_stage_capacity_ratio(model, "SizingInfoHVACCapacityRatioCooling") + if stage.grossRatedTotalCoolingCapacity.is_initialized + cost_mult += UnitConversions.convert(stage.grossRatedTotalCoolingCapacity.get / capacity_ratio, "W", "kBtu/hr") + end + end + elsif component.to_CoilCoolingWaterToAirHeatPumpEquationFit.is_initialized + coil = component.to_CoilCoolingWaterToAirHeatPumpEquationFit.get + if coil.ratedTotalCoolingCapacity.is_initialized + cost_mult += UnitConversions.convert(coil.ratedTotalCoolingCapacity.get, "W", "kBtu/hr") + end + end + end + end + + # PTAC? + if component.nil? + model.getZoneHVACPackagedTerminalAirConditioners.each do |sys| + next unless conditioned_zones.include? sys.thermalZone.get + + component = sys.coolingCoil + if not component.nil? + if component.to_CoilCoolingDXSingleSpeed.is_initialized + coil = component.to_CoilCoolingDXSingleSpeed.get + if coil.ratedTotalCoolingCapacity.is_initialized + cost_mult += UnitConversions.convert(coil.ratedTotalCoolingCapacity.get, "W", "kBtu/hr") + end + end + end + end + end + + cost_mult *= units_represented + end + + elsif cost_mult_type == "Size, Water Heater (gal)" + # Water heater tank volume + (model.getWaterHeaterMixeds + model.getWaterHeaterHeatPumpWrappedCondensers).each do |wh| + if wh.to_WaterHeaterHeatPumpWrappedCondenser.is_initialized + wh = wh.tank.to_WaterHeaterStratified.get + end + if wh.tankVolume.is_initialized + volume = UnitConversions.convert(wh.tankVolume.get, "m^3", "gal") + if volume >= 1.0 # skip tankless + # FIXME: Remove actual->nominal size logic by storing nominal size in the OSM + if wh.heaterFuelType.downcase == "electricity" + cost_mult += volume / 0.9 + else + cost_mult += volume / 0.95 + end + end + end + end + + elsif cost_mult_type != "" + runner.registerError("Unhandled cost multiplier: #{cost_mult_type.to_s}. Aborting...") + return nil + end + + return cost_mult + end + + def get_conditioned_zones(model) + conditioned_zones = [] + model.getThermalZones.each do |zone| + next if not zone.thermostat.is_initialized + + conditioned_zones << zone + end + return conditioned_zones + end + + def get_adjacent_space(surface) + return nil if not surface.adjacentSurface.is_initialized + return nil if not surface.adjacentSurface.get.space.is_initialized + + return surface.adjacentSurface.get.space.get + end + + def is_space_conditioned(adjacent_space, conditioned_zones) + conditioned_zones.each do |zone| + return true if zone.spaces.include? adjacent_space + end + return false + end + + def has_sloped_roof_surfaces(space) + space.surfaces.each do |surface| + next if surface.surfaceType.downcase != "roofceiling" + next if surface.outsideBoundaryCondition.downcase != "outdoors" + next if surface.tilt == 0 + + return true + end + return false + end + + def get_highest_stage_capacity_ratio(model, property_str) + capacity_ratio = 1.0 + + # Override capacity ratio for residential multispeed systems + model.getAirLoopHVACUnitarySystems.each do |sys| + capacity_ratio_str = sys.additionalProperties.getFeatureAsString(property_str) + next if not capacity_ratio_str.is_initialized + + capacity_ratio = capacity_ratio_str.get.split(",").map(&:to_f)[-1] + end + + return capacity_ratio + end +end # end the measure + +# this allows the measure to be use by the application +SimulationOutputReport.new.registerWithApplication diff --git a/buildstockbatch/test/test_inputs/test_openstudio_buildstock/measures/SimulationOutputReport/measure.xml b/buildstockbatch/test/test_inputs/test_openstudio_buildstock/measures/SimulationOutputReport/measure.xml new file mode 100644 index 00000000..00fdf883 --- /dev/null +++ b/buildstockbatch/test/test_inputs/test_openstudio_buildstock/measures/SimulationOutputReport/measure.xml @@ -0,0 +1,694 @@ + + 3.0 + simulation_output_report + fc337100-8634-404e-8966-01243d292a79 + 31197f88-2524-4f81-9e0a-2c37bec1ac15 + 20190715T223325Z + 2C8A3EEF + SimulationOutputReport + Simulation Output Report + Reports simulation outputs of interest. + Change me + + + + total_site_energy_mbtu + total_site_energy_mbtu + total_site_energy_mbtu + Double + false + + + total_site_electricity_kwh + total_site_electricity_kwh + total_site_electricity_kwh + Double + false + + + total_site_natural_gas_therm + total_site_natural_gas_therm + total_site_natural_gas_therm + Double + false + + + total_site_fuel_oil_mbtu + total_site_fuel_oil_mbtu + total_site_fuel_oil_mbtu + Double + false + + + total_site_propane_mbtu + total_site_propane_mbtu + total_site_propane_mbtu + Double + false + + + net_site_energy_mbtu + net_site_energy_mbtu + net_site_energy_mbtu + Double + false + + + net_site_electricity_kwh + net_site_electricity_kwh + net_site_electricity_kwh + Double + false + + + electricity_heating_kwh + electricity_heating_kwh + electricity_heating_kwh + Double + false + + + electricity_central_system_heating_kwh + electricity_central_system_heating_kwh + electricity_central_system_heating_kwh + Double + false + + + electricity_cooling_kwh + electricity_cooling_kwh + electricity_cooling_kwh + Double + false + + + electricity_central_system_cooling_kwh + electricity_central_system_cooling_kwh + electricity_central_system_cooling_kwh + Double + false + + + electricity_interior_lighting_kwh + electricity_interior_lighting_kwh + electricity_interior_lighting_kwh + Double + false + + + electricity_exterior_lighting_kwh + electricity_exterior_lighting_kwh + electricity_exterior_lighting_kwh + Double + false + + + electricity_interior_equipment_kwh + electricity_interior_equipment_kwh + electricity_interior_equipment_kwh + Double + false + + + electricity_fans_heating_kwh + electricity_fans_heating_kwh + electricity_fans_heating_kwh + Double + false + + + electricity_fans_cooling_kwh + electricity_fans_cooling_kwh + electricity_fans_cooling_kwh + Double + false + + + electricity_pumps_heating_kwh + electricity_pumps_heating_kwh + electricity_pumps_heating_kwh + Double + false + + + electricity_central_system_pumps_heating_kwh + electricity_central_system_pumps_heating_kwh + electricity_central_system_pumps_heating_kwh + Double + false + + + electricity_pumps_cooling_kwh + electricity_pumps_cooling_kwh + electricity_pumps_cooling_kwh + Double + false + + + electricity_central_system_pumps_cooling_kwh + electricity_central_system_pumps_cooling_kwh + electricity_central_system_pumps_cooling_kwh + Double + false + + + electricity_water_systems_kwh + electricity_water_systems_kwh + electricity_water_systems_kwh + Double + false + + + electricity_pv_kwh + electricity_pv_kwh + electricity_pv_kwh + Double + false + + + natural_gas_heating_therm + natural_gas_heating_therm + natural_gas_heating_therm + Double + false + + + natural_gas_central_system_heating_therm + natural_gas_central_system_heating_therm + natural_gas_central_system_heating_therm + Double + false + + + natural_gas_interior_equipment_therm + natural_gas_interior_equipment_therm + natural_gas_interior_equipment_therm + Double + false + + + natural_gas_water_systems_therm + natural_gas_water_systems_therm + natural_gas_water_systems_therm + Double + false + + + fuel_oil_heating_mbtu + fuel_oil_heating_mbtu + fuel_oil_heating_mbtu + Double + false + + + fuel_oil_central_system_heating_mbtu + fuel_oil_central_system_heating_mbtu + fuel_oil_central_system_heating_mbtu + Double + false + + + fuel_oil_interior_equipment_mbtu + fuel_oil_interior_equipment_mbtu + fuel_oil_interior_equipment_mbtu + Double + false + + + fuel_oil_water_systems_mbtu + fuel_oil_water_systems_mbtu + fuel_oil_water_systems_mbtu + Double + false + + + propane_heating_mbtu + propane_heating_mbtu + propane_heating_mbtu + Double + false + + + propane_central_system_heating_mbtu + propane_central_system_heating_mbtu + propane_central_system_heating_mbtu + Double + false + + + propane_interior_equipment_mbtu + propane_interior_equipment_mbtu + propane_interior_equipment_mbtu + Double + false + + + propane_water_systems_mbtu + propane_water_systems_mbtu + propane_water_systems_mbtu + Double + false + + + hours_heating_setpoint_not_met + hours_heating_setpoint_not_met + hours_heating_setpoint_not_met + Double + false + + + hours_cooling_setpoint_not_met + hours_cooling_setpoint_not_met + hours_cooling_setpoint_not_met + Double + false + + + hvac_cooling_capacity_w + hvac_cooling_capacity_w + hvac_cooling_capacity_w + Double + false + + + hvac_heating_capacity_w + hvac_heating_capacity_w + hvac_heating_capacity_w + Double + false + + + hvac_heating_supp_capacity_w + hvac_heating_supp_capacity_w + hvac_heating_supp_capacity_w + Double + false + + + upgrade_name + upgrade_name + upgrade_name + Double + false + + + upgrade_cost_usd + upgrade_cost_usd + upgrade_cost_usd + Double + false + + + upgrade_option_01_cost_usd + upgrade_option_01_cost_usd + upgrade_option_01_cost_usd + Double + false + + + upgrade_option_01_lifetime_yrs + upgrade_option_01_lifetime_yrs + upgrade_option_01_lifetime_yrs + Double + false + + + upgrade_option_02_cost_usd + upgrade_option_02_cost_usd + upgrade_option_02_cost_usd + Double + false + + + upgrade_option_02_lifetime_yrs + upgrade_option_02_lifetime_yrs + upgrade_option_02_lifetime_yrs + Double + false + + + upgrade_option_03_cost_usd + upgrade_option_03_cost_usd + upgrade_option_03_cost_usd + Double + false + + + upgrade_option_03_lifetime_yrs + upgrade_option_03_lifetime_yrs + upgrade_option_03_lifetime_yrs + Double + false + + + upgrade_option_04_cost_usd + upgrade_option_04_cost_usd + upgrade_option_04_cost_usd + Double + false + + + upgrade_option_04_lifetime_yrs + upgrade_option_04_lifetime_yrs + upgrade_option_04_lifetime_yrs + Double + false + + + upgrade_option_05_cost_usd + upgrade_option_05_cost_usd + upgrade_option_05_cost_usd + Double + false + + + upgrade_option_05_lifetime_yrs + upgrade_option_05_lifetime_yrs + upgrade_option_05_lifetime_yrs + Double + false + + + upgrade_option_06_cost_usd + upgrade_option_06_cost_usd + upgrade_option_06_cost_usd + Double + false + + + upgrade_option_06_lifetime_yrs + upgrade_option_06_lifetime_yrs + upgrade_option_06_lifetime_yrs + Double + false + + + upgrade_option_07_cost_usd + upgrade_option_07_cost_usd + upgrade_option_07_cost_usd + Double + false + + + upgrade_option_07_lifetime_yrs + upgrade_option_07_lifetime_yrs + upgrade_option_07_lifetime_yrs + Double + false + + + upgrade_option_08_cost_usd + upgrade_option_08_cost_usd + upgrade_option_08_cost_usd + Double + false + + + upgrade_option_08_lifetime_yrs + upgrade_option_08_lifetime_yrs + upgrade_option_08_lifetime_yrs + Double + false + + + upgrade_option_09_cost_usd + upgrade_option_09_cost_usd + upgrade_option_09_cost_usd + Double + false + + + upgrade_option_09_lifetime_yrs + upgrade_option_09_lifetime_yrs + upgrade_option_09_lifetime_yrs + Double + false + + + upgrade_option_10_cost_usd + upgrade_option_10_cost_usd + upgrade_option_10_cost_usd + Double + false + + + upgrade_option_10_lifetime_yrs + upgrade_option_10_lifetime_yrs + upgrade_option_10_lifetime_yrs + Double + false + + + upgrade_option_11_cost_usd + upgrade_option_11_cost_usd + upgrade_option_11_cost_usd + Double + false + + + upgrade_option_11_lifetime_yrs + upgrade_option_11_lifetime_yrs + upgrade_option_11_lifetime_yrs + Double + false + + + upgrade_option_12_cost_usd + upgrade_option_12_cost_usd + upgrade_option_12_cost_usd + Double + false + + + upgrade_option_12_lifetime_yrs + upgrade_option_12_lifetime_yrs + upgrade_option_12_lifetime_yrs + Double + false + + + upgrade_option_13_cost_usd + upgrade_option_13_cost_usd + upgrade_option_13_cost_usd + Double + false + + + upgrade_option_13_lifetime_yrs + upgrade_option_13_lifetime_yrs + upgrade_option_13_lifetime_yrs + Double + false + + + upgrade_option_14_cost_usd + upgrade_option_14_cost_usd + upgrade_option_14_cost_usd + Double + false + + + upgrade_option_14_lifetime_yrs + upgrade_option_14_lifetime_yrs + upgrade_option_14_lifetime_yrs + Double + false + + + upgrade_option_15_cost_usd + upgrade_option_15_cost_usd + upgrade_option_15_cost_usd + Double + false + + + upgrade_option_15_lifetime_yrs + upgrade_option_15_lifetime_yrs + upgrade_option_15_lifetime_yrs + Double + false + + + upgrade_option_16_cost_usd + upgrade_option_16_cost_usd + upgrade_option_16_cost_usd + Double + false + + + upgrade_option_16_lifetime_yrs + upgrade_option_16_lifetime_yrs + upgrade_option_16_lifetime_yrs + Double + false + + + upgrade_option_17_cost_usd + upgrade_option_17_cost_usd + upgrade_option_17_cost_usd + Double + false + + + upgrade_option_17_lifetime_yrs + upgrade_option_17_lifetime_yrs + upgrade_option_17_lifetime_yrs + Double + false + + + upgrade_option_18_cost_usd + upgrade_option_18_cost_usd + upgrade_option_18_cost_usd + Double + false + + + upgrade_option_18_lifetime_yrs + upgrade_option_18_lifetime_yrs + upgrade_option_18_lifetime_yrs + Double + false + + + upgrade_option_19_cost_usd + upgrade_option_19_cost_usd + upgrade_option_19_cost_usd + Double + false + + + upgrade_option_19_lifetime_yrs + upgrade_option_19_lifetime_yrs + upgrade_option_19_lifetime_yrs + Double + false + + + upgrade_option_20_cost_usd + upgrade_option_20_cost_usd + upgrade_option_20_cost_usd + Double + false + + + upgrade_option_20_lifetime_yrs + upgrade_option_20_lifetime_yrs + upgrade_option_20_lifetime_yrs + Double + false + + + upgrade_option_21_cost_usd + upgrade_option_21_cost_usd + upgrade_option_21_cost_usd + Double + false + + + upgrade_option_21_lifetime_yrs + upgrade_option_21_lifetime_yrs + upgrade_option_21_lifetime_yrs + Double + false + + + upgrade_option_22_cost_usd + upgrade_option_22_cost_usd + upgrade_option_22_cost_usd + Double + false + + + upgrade_option_22_lifetime_yrs + upgrade_option_22_lifetime_yrs + upgrade_option_22_lifetime_yrs + Double + false + + + upgrade_option_23_cost_usd + upgrade_option_23_cost_usd + upgrade_option_23_cost_usd + Double + false + + + upgrade_option_23_lifetime_yrs + upgrade_option_23_lifetime_yrs + upgrade_option_23_lifetime_yrs + Double + false + + + upgrade_option_24_cost_usd + upgrade_option_24_cost_usd + upgrade_option_24_cost_usd + Double + false + + + upgrade_option_24_lifetime_yrs + upgrade_option_24_lifetime_yrs + upgrade_option_24_lifetime_yrs + Double + false + + + upgrade_option_25_cost_usd + upgrade_option_25_cost_usd + upgrade_option_25_cost_usd + Double + false + + + upgrade_option_25_lifetime_yrs + upgrade_option_25_lifetime_yrs + upgrade_option_25_lifetime_yrs + Double + false + + + weight + weight + weight + Double + false + + + + + Reporting.QAQC + + + + Measure Type + ReportingMeasure + string + + + Uses SketchUp API + false + boolean + + + + + simulation_output_report_test.rb + rb + test + D0ED64E4 + + + + OpenStudio + 1.1.2 + 1.1.2 + + measure.rb + rb + script + 0A9FF470 + + + diff --git a/buildstockbatch/test/test_inputs/test_openstudio_buildstock/measures/TimeseriesCSVExport/measure.rb b/buildstockbatch/test/test_inputs/test_openstudio_buildstock/measures/TimeseriesCSVExport/measure.rb new file mode 100644 index 00000000..9f31b62d --- /dev/null +++ b/buildstockbatch/test/test_inputs/test_openstudio_buildstock/measures/TimeseriesCSVExport/measure.rb @@ -0,0 +1,778 @@ +# see the URL below for information on how to write OpenStudio measures +# http://nrel.github.io/OpenStudio-user-documentation/reference/measure_writing_guide/ + +require 'csv' +if File.exists? File.absolute_path(File.join(File.dirname(__FILE__), "../../lib/resources/measures/HPXMLtoOpenStudio/resources")) # Hack to run ResStock on AWS + resources_path = File.absolute_path(File.join(File.dirname(__FILE__), "../../lib/resources/measures/HPXMLtoOpenStudio/resources")) +elsif File.exists? File.absolute_path(File.join(File.dirname(__FILE__), "../../resources/measures/HPXMLtoOpenStudio/resources")) # Hack to run ResStock unit tests locally + resources_path = File.absolute_path(File.join(File.dirname(__FILE__), "../../resources/measures/HPXMLtoOpenStudio/resources")) +elsif File.exists? File.join(OpenStudio::BCLMeasure::userMeasuresDir.to_s, "HPXMLtoOpenStudio/resources") # Hack to run measures in the OS App since applied measures are copied off into a temporary directory + resources_path = File.join(OpenStudio::BCLMeasure::userMeasuresDir.to_s, "HPXMLtoOpenStudio/resources") +else + resources_path = File.absolute_path(File.join(File.dirname(__FILE__), "../HPXMLtoOpenStudio/resources")) +end +require File.join(resources_path, "weather") +require File.join(resources_path, "unit_conversions") +require File.join(resources_path, "geometry") +require File.join(resources_path, "hvac") +require File.join(resources_path, "waterheater") + +# start the measure +class TimeseriesCSVExport < OpenStudio::Measure::ReportingMeasure + # human readable name + def name + return "Timeseries CSV Export" + end + + # human readable description + def description + return "Exports timeseries output data to csv." + end + + def reporting_frequency_map # idf => osm + return { "Timestep" => "Zone Timestep", "Hourly" => "Hourly", "Daily" => "Daily", "Monthly" => "Monthly", "Runperiod" => "Run Period" } + end + + # define the arguments that the user will input + def arguments() + args = OpenStudio::Measure::OSArgumentVector.new + + # make an argument for the frequency + reporting_frequency_chs = OpenStudio::StringVector.new + reporting_frequency_map.keys.each do |reporting_frequency_ch| + reporting_frequency_chs << reporting_frequency_ch + end + arg = OpenStudio::Measure::OSArgument::makeChoiceArgument("reporting_frequency", reporting_frequency_chs, true) + arg.setDisplayName("Reporting Frequency") + arg.setDescription("The frequency at which to report timeseries output data.") + arg.setDefaultValue("Hourly") + args << arg + + # make an argument for including optional end use subcategories + arg = OpenStudio::Measure::OSArgument::makeBoolArgument("include_enduse_subcategories", true) + arg.setDisplayName("Include End Use Subcategories") + arg.setDescription("Whether to report end use subcategories: appliances, plug loads, fans, large uncommon loads.") + arg.setDefaultValue(false) + args << arg + + # make an argument for optional output variables + arg = OpenStudio::Measure::OSArgument::makeStringArgument("output_variables", false) + arg.setDisplayName("Output Variables") + arg.setDescription("Specify a comma-separated list of output variables to report. (See EnergyPlus's rdd file for available output variables.)") + args << arg + + return args + end + + # return a vector of IdfObject's to request EnergyPlus objects needed by the run method + def energyPlusOutputRequests(runner, user_arguments) + super(runner, user_arguments) + + return OpenStudio::IdfObjectVector.new if runner.halted + + reporting_frequency = runner.getStringArgumentValue("reporting_frequency", user_arguments) + include_enduse_subcategories = runner.getBoolArgumentValue("include_enduse_subcategories", user_arguments) + output_variables = runner.getOptionalStringArgumentValue("output_variables", user_arguments) + output_vars = [] + if output_variables.is_initialized + output_vars = output_variables.get + output_vars = output_vars.split(",") + output_vars = output_vars.collect { |x| x.strip } + end + + # get the last model and sql file + model = runner.lastOpenStudioModel + if model.empty? + runner.registerError("Cannot find last model.") + return false + end + model = model.get + + results = OutputMeters.create_custom_building_unit_meters(model, runner, reporting_frequency, include_enduse_subcategories) + output_vars.each do |output_var| + results << OpenStudio::IdfObject.load("Output:Variable,*,#{output_var},#{reporting_frequency};").get + end + results << OpenStudio::IdfObject.load("Output:Meter,Electricity:Facility,#{reporting_frequency};").get + + return results + end + + # define what happens when the measure is run + def run(runner, user_arguments) + super(runner, user_arguments) + + # use the built-in error checking + if not runner.validateUserArguments(arguments(), user_arguments) + return false + end + + # Assign the user inputs to variables + reporting_frequency = runner.getStringArgumentValue("reporting_frequency", user_arguments) + include_enduse_subcategories = runner.getBoolArgumentValue("include_enduse_subcategories", user_arguments) + output_variables = runner.getOptionalStringArgumentValue("output_variables", user_arguments) + output_vars = [] + if output_variables.is_initialized + output_vars = output_variables.get + output_vars = output_vars.split(",") + output_vars = output_vars.collect { |x| x.strip } + end + + # Get the last model and sql file + model = runner.lastOpenStudioModel + if model.empty? + runner.registerError("Cannot find last model.") + return false + end + model = model.get + + sqlFile = runner.lastEnergyPlusSqlFile + if sqlFile.empty? + runner.registerError("Cannot find last sql file.") + return false + end + sqlFile = sqlFile.get + model.setSqlFile(sqlFile) + + # Get datetimes + ann_env_pd = nil + sqlFile.availableEnvPeriods.each do |env_pd| + env_type = sqlFile.environmentType(env_pd) + if env_type.is_initialized + if env_type.get == OpenStudio::EnvironmentType.new("WeatherRunPeriod") + ann_env_pd = env_pd + end + end + end + if ann_env_pd == false + runner.registerError("Can't find a weather runperiod, make sure you ran an annual simulation, not just the design days.") + return false + end + + env_period_ix_query = "SELECT EnvironmentPeriodIndex FROM EnvironmentPeriods WHERE EnvironmentName='#{ann_env_pd}'" + env_period_ix = sqlFile.execAndReturnFirstInt(env_period_ix_query).get + + datetimes = [] + timeseries = sqlFile.timeSeries(ann_env_pd, reporting_frequency_map[reporting_frequency], "Electricity:Facility", "").get # assume every house consumes some electricity + timeseries.dateTimes.each do |datetime| + datetimes << format_datetime(datetime.to_s) + end + num_ts = datetimes.length + + total_site_units = "MBtu" + elec_site_units = "kWh" + gas_site_units = "therm" + other_fuel_site_units = "MBtu" + + # Get meters that aren't tied to units (i.e., are metered at the building level) + modeledCentralElectricityHeating = [0] * num_ts + modeledCentralElectricityCooling = [0] * num_ts + modeledCentralElectricityExteriorLighting = [0] * num_ts + modeledCentralElectricityExteriorHolidayLighting = [0] * num_ts + modeledCentralElectricityPumpsHeating = [0] * num_ts + modeledCentralElectricityPumpsCooling = [0] * num_ts + modeledCentralElectricityInteriorEquipment = [0] * num_ts + modeledCentralElectricityPhotovoltaics = [0] * num_ts + modeledCentralElectricityExtraRefrigerator = [0] * num_ts + modeledCentralElectricityFreezer = [0] * num_ts + modeledCentralElectricityGarageLighting = [0] * num_ts + modeledCentralNaturalGasHeating = [0] * num_ts + modeledCentralNaturalGasInteriorEquipment = [0] * num_ts + modeledCentralNaturalGasGrill = [0] * num_ts + modeledCentralNaturalGasLighting = [0] * num_ts + modeledCentralNaturalGasFireplace = [0] * num_ts + modeledCentralFuelOilHeating = [0] * num_ts + modeledCentralPropaneHeating = [0] * num_ts + + central_electricity_heating_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('CENTRAL:ELECTRICITYHEATING') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" + unless sqlFile.execAndReturnVectorOfDouble(central_electricity_heating_query).get.empty? + modeledCentralElectricityHeating = sqlFile.execAndReturnVectorOfDouble(central_electricity_heating_query).get + end + + central_electricity_cooling_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('CENTRAL:ELECTRICITYCOOLING') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" + unless sqlFile.execAndReturnVectorOfDouble(central_electricity_cooling_query).get.empty? + modeledCentralElectricityCooling = sqlFile.execAndReturnVectorOfDouble(central_electricity_cooling_query).get + end + + central_electricity_exterior_lighting_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('CENTRAL:ELECTRICITYEXTERIORLIGHTING') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" + unless sqlFile.execAndReturnVectorOfDouble(central_electricity_exterior_lighting_query).get.empty? + modeledCentralElectricityExteriorLighting = sqlFile.execAndReturnVectorOfDouble(central_electricity_exterior_lighting_query).get + end + + central_electricity_exterior_holiday_lighting_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('CENTRAL:ELECTRICITYEXTERIORHOLIDAYLIGHTING') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" + unless sqlFile.execAndReturnVectorOfDouble(central_electricity_exterior_holiday_lighting_query).get.empty? + modeledCentralElectricityExteriorHolidayLighting = sqlFile.execAndReturnVectorOfDouble(central_electricity_exterior_holiday_lighting_query).get + end + + central_electricity_pumps_heating_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('CENTRAL:ELECTRICITYPUMPSHEATING') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" + unless sqlFile.execAndReturnVectorOfDouble(central_electricity_pumps_heating_query).get.empty? + modeledCentralElectricityPumpsHeating = sqlFile.execAndReturnVectorOfDouble(central_electricity_pumps_heating_query).get + end + + central_electricity_pumps_cooling_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('CENTRAL:ELECTRICITYPUMPSCOOLING') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" + unless sqlFile.execAndReturnVectorOfDouble(central_electricity_pumps_cooling_query).get.empty? + modeledCentralElectricityPumpsCooling = sqlFile.execAndReturnVectorOfDouble(central_electricity_pumps_cooling_query).get + end + + central_electricity_interior_equipment_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('CENTRAL:ELECTRICITYINTERIOREQUIPMENT') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" + unless sqlFile.execAndReturnVectorOfDouble(central_electricity_interior_equipment_query).get.empty? + modeledCentralElectricityInteriorEquipment = sqlFile.execAndReturnVectorOfDouble(central_electricity_interior_equipment_query).get + end + + central_electricity_photovoltaics_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('CENTRAL:ELECTRICITYPHOTOVOLTAICS') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" + unless sqlFile.execAndReturnVectorOfDouble(central_electricity_photovoltaics_query).get.empty? + modeledCentralElectricityPhotovoltaics = sqlFile.execAndReturnVectorOfDouble(central_electricity_photovoltaics_query).get + end + + central_electricity_extra_refrigerator_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('CENTRAL:ELECTRICITYEXTRAREFRIGERATOR') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" + unless sqlFile.execAndReturnVectorOfDouble(central_electricity_extra_refrigerator_query).get.empty? + modeledCentralElectricityExtraRefrigerator = sqlFile.execAndReturnVectorOfDouble(central_electricity_extra_refrigerator_query).get + end + + central_electricity_freezer_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('CENTRAL:ELECTRICITYFREEZER') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" + unless sqlFile.execAndReturnVectorOfDouble(central_electricity_freezer_query).get.empty? + modeledCentralElectricityFreezer = sqlFile.execAndReturnVectorOfDouble(central_electricity_freezer_query).get + end + + central_electricity_garage_lighting_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('CENTRAL:ELECTRICITYGARAGELIGHTING') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" + unless sqlFile.execAndReturnVectorOfDouble(central_electricity_garage_lighting_query).get.empty? + modeledCentralElectricityGarageLighting = sqlFile.execAndReturnVectorOfDouble(central_electricity_garage_lighting_query).get + end + + central_natural_gas_heating_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('CENTRAL:NATURALGASHEATING') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" + unless sqlFile.execAndReturnVectorOfDouble(central_natural_gas_heating_query).get.empty? + modeledCentralNaturalGasHeating = sqlFile.execAndReturnVectorOfDouble(central_natural_gas_heating_query).get + end + + central_natural_gas_interior_equipment_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('CENTRAL:NATURALGASINTERIOREQUIPMENT') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" + unless sqlFile.execAndReturnVectorOfDouble(central_natural_gas_interior_equipment_query).get.empty? + modeledCentralNaturalGasInteriorEquipment = sqlFile.execAndReturnVectorOfDouble(central_natural_gas_interior_equipment_query).get + end + + central_natural_gas_grill_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('CENTRAL:NATURALGASGRILL') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" + unless sqlFile.execAndReturnVectorOfDouble(central_natural_gas_grill_query).get.empty? + modeledCentralNaturalGasGrill = sqlFile.execAndReturnVectorOfDouble(central_natural_gas_grill_query).get + end + + central_natural_gas_lighting_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('CENTRAL:NATURALGASLIGHTING') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" + unless sqlFile.execAndReturnVectorOfDouble(central_natural_gas_lighting_query).get.empty? + modeledCentralNaturalGasLighting = sqlFile.execAndReturnVectorOfDouble(central_natural_gas_lighting_query).get + end + + central_natural_gas_fireplace_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('CENTRAL:NATURALGASFIREPLACE') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" + unless sqlFile.execAndReturnVectorOfDouble(central_natural_gas_fireplace_query).get.empty? + modeledCentralNaturalGasFireplace = sqlFile.execAndReturnVectorOfDouble(central_natural_gas_fireplace_query).get + end + + central_fuel_oil_heating_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('CENTRAL:FUELOILHEATING') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" + unless sqlFile.execAndReturnVectorOfDouble(central_fuel_oil_heating_query).get.empty? + modeledCentralFuelOilHeating = sqlFile.execAndReturnVectorOfDouble(central_fuel_oil_heating_query).get + end + + central_propane_heating_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('CENTRAL:PROPANEHEATING') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" + unless sqlFile.execAndReturnVectorOfDouble(central_propane_heating_query).get.empty? + modeledCentralPropaneHeating = sqlFile.execAndReturnVectorOfDouble(central_propane_heating_query).get + end + + # Separate these from non central systems + centralElectricityHeating = [0] * num_ts + centralElectricityCooling = [0] * num_ts + centralElectricityPumpsHeating = [0] * num_ts + centralElectricityPumpsCooling = [0] * num_ts + centralNaturalGasHeating = [0] * num_ts + centralFuelOilHeating = [0] * num_ts + centralPropaneHeating = [0] * num_ts + + # Get meters that are tied to units, and apportion building level meters to these + electricityTotalEndUses = [0] * num_ts + electricityHeating = [0] * num_ts + electricityCooling = [0] * num_ts + electricityInteriorLighting = [0] * num_ts + electricityExteriorLighting = [0] * num_ts + electricityExteriorHolidayLighting = modeledCentralElectricityExteriorHolidayLighting + electricityInteriorEquipment = [0] * num_ts + electricityFansHeating = [0] * num_ts + electricityFansCooling = [0] * num_ts + electricityPumpsHeating = [0] * num_ts + electricityPumpsCooling = [0] * num_ts + electricityWaterSystems = [0] * num_ts + electricityPhotovoltaics = [0] * num_ts + naturalGasTotalEndUses = [0] * num_ts + naturalGasHeating = [0] * num_ts + naturalGasInteriorEquipment = [0] * num_ts + naturalGasWaterSystems = [0] * num_ts + fuelOilTotalEndUses = [0] * num_ts + fuelOilHeating = [0] * num_ts + fuelOilInteriorEquipment = [0] * num_ts + fuelOilWaterSystems = [0] * num_ts + propaneTotalEndUses = [0] * num_ts + propaneHeating = [0] * num_ts + propaneInteriorEquipment = [0] * num_ts + propaneWaterSystems = [0] * num_ts + electricityRefrigerator = [0] * num_ts + electricityClothesWasher = [0] * num_ts + electricityClothesDryer = [0] * num_ts + naturalGasClothesDryer = [0] * num_ts + propaneClothesDryer = [0] * num_ts + electricityCookingRange = [0] * num_ts + naturalGasCookingRange = [0] * num_ts + propaneCookingRange = [0] * num_ts + electricityDishwasher = [0] * num_ts + electricityPlugLoads = [0] * num_ts + electricityHouseFan = [0] * num_ts + electricityRangeFan = [0] * num_ts + electricityBathFan = [0] * num_ts + electricityCeilingFan = [0] * num_ts + electricityExtraRefrigerator = [0] * num_ts + electricityFreezer = [0] * num_ts + electricityPoolHeater = [0] * num_ts + naturalGasPoolHeater = [0] * num_ts + electricityPoolPump = [0] * num_ts + electricityHotTubHeater = [0] * num_ts + naturalGasHotTubHeater = [0] * num_ts + electricityHotTubPump = [0] * num_ts + electricityWellPump = [0] * num_ts + electricityGarageLighting = [0] * num_ts + naturalGasGrill = [0] * num_ts + naturalGasLighting = [0] * num_ts + naturalGasFireplace = [0] * num_ts + + # Get building units + units = Geometry.get_building_units(model, runner) + if units.nil? + return false + end + + units.each do |unit| + unit_name = unit.name.to_s.upcase + + units_represented = 1 + if unit.additionalProperties.getFeatureAsInteger("Units Represented").is_initialized + units_represented = unit.additionalProperties.getFeatureAsInteger("Units Represented").get + end + + electricity_heating_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:ELECTRICITYHEATING') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" + unless sqlFile.execAndReturnVectorOfDouble(electricity_heating_query).get.empty? + electricityHeating = array_sum(electricityHeating, sqlFile.execAndReturnVectorOfDouble(electricity_heating_query).get, units_represented) + end + + centralElectricityHeating = array_sum(centralElectricityHeating, modeledCentralElectricityHeating, units_represented, units.length) + + electricity_cooling_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:ELECTRICITYCOOLING') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" + unless sqlFile.execAndReturnVectorOfDouble(electricity_cooling_query).get.empty? + electricityCooling = array_sum(electricityCooling, sqlFile.execAndReturnVectorOfDouble(electricity_cooling_query).get, units_represented) + end + + centralElectricityCooling = array_sum(centralElectricityCooling, modeledCentralElectricityCooling, units_represented, units.length) + + electricity_interior_lighting_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:ELECTRICITYINTERIORLIGHTING') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" + unless sqlFile.execAndReturnVectorOfDouble(electricity_interior_lighting_query).get.empty? + electricityInteriorLighting = array_sum(electricityInteriorLighting, sqlFile.execAndReturnVectorOfDouble(electricity_interior_lighting_query).get, units_represented) + end + + electricityExteriorLighting = array_sum(electricityExteriorLighting, modeledCentralElectricityExteriorLighting, units_represented, units.length) + + electricity_interior_equipment_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:ELECTRICITYINTERIOREQUIPMENT') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" + unless sqlFile.execAndReturnVectorOfDouble(electricity_interior_equipment_query).get.empty? + electricityInteriorEquipment = array_sum(electricityInteriorEquipment, sqlFile.execAndReturnVectorOfDouble(electricity_interior_equipment_query).get, units_represented) + end + electricityInteriorEquipment = array_sum(electricityInteriorEquipment, modeledCentralElectricityInteriorEquipment, units_represented, units.length) + + electricity_fans_heating_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:ELECTRICITYFANSHEATING') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" + unless sqlFile.execAndReturnVectorOfDouble(electricity_fans_heating_query).get.empty? + electricityFansHeating = array_sum(electricityFansHeating, sqlFile.execAndReturnVectorOfDouble(electricity_fans_heating_query).get, units_represented) + end + + electricity_fans_cooling_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:ELECTRICITYFANSCOOLING') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" + unless sqlFile.execAndReturnVectorOfDouble(electricity_fans_cooling_query).get.empty? + electricityFansCooling = array_sum(electricityFansCooling, sqlFile.execAndReturnVectorOfDouble(electricity_fans_cooling_query).get, units_represented) + end + + electricity_pumps_heating_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:ELECTRICITYPUMPSHEATING') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" + unless sqlFile.execAndReturnVectorOfDouble(electricity_pumps_heating_query).get.empty? + electricityPumpsHeating = array_sum(electricityPumpsHeating, sqlFile.execAndReturnVectorOfDouble(electricity_pumps_heating_query).get, units_represented) + end + + centralElectricityPumpsHeating = array_sum(centralElectricityPumpsHeating, modeledCentralElectricityPumpsHeating, units_represented, units.length) + + electricity_pumps_cooling_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:ELECTRICITYPUMPSCOOLING') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" + unless sqlFile.execAndReturnVectorOfDouble(electricity_pumps_cooling_query).get.empty? + electricityPumpsCooling = array_sum(electricityPumpsCooling, sqlFile.execAndReturnVectorOfDouble(electricity_pumps_cooling_query).get, units_represented) + end + + centralElectricityPumpsCooling = array_sum(centralElectricityPumpsCooling, modeledCentralElectricityPumpsCooling, units_represented, units.length) + + electricity_water_systems_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:ELECTRICITYWATERSYSTEMS') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" + unless sqlFile.execAndReturnVectorOfDouble(electricity_water_systems_query).get.empty? + electricityWaterSystems = array_sum(electricityWaterSystems, sqlFile.execAndReturnVectorOfDouble(electricity_water_systems_query).get, units_represented) + end + + natural_gas_heating_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:NATURALGASHEATING') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" + unless sqlFile.execAndReturnVectorOfDouble(natural_gas_heating_query).get.empty? + naturalGasHeating = array_sum(naturalGasHeating, sqlFile.execAndReturnVectorOfDouble(natural_gas_heating_query).get, units_represented) + end + + centralNaturalGasHeating = array_sum(centralNaturalGasHeating, modeledCentralNaturalGasHeating, units_represented, units.length) + + natural_gas_interior_equipment_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:NATURALGASINTERIOREQUIPMENT') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" + unless sqlFile.execAndReturnVectorOfDouble(natural_gas_interior_equipment_query).get.empty? + naturalGasInteriorEquipment = array_sum(naturalGasInteriorEquipment, sqlFile.execAndReturnVectorOfDouble(natural_gas_interior_equipment_query).get, units_represented) + end + naturalGasInteriorEquipment = array_sum(naturalGasInteriorEquipment, modeledCentralNaturalGasInteriorEquipment, units_represented, units.length) + + natural_gas_water_systems_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:NATURALGASWATERSYSTEMS') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" + unless sqlFile.execAndReturnVectorOfDouble(natural_gas_water_systems_query).get.empty? + naturalGasWaterSystems = array_sum(naturalGasWaterSystems, sqlFile.execAndReturnVectorOfDouble(natural_gas_water_systems_query).get, units_represented) + end + + fuel_oil_heating_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:FUELOILHEATING') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" + unless sqlFile.execAndReturnVectorOfDouble(fuel_oil_heating_query).get.empty? + fuelOilHeating = array_sum(fuelOilHeating, sqlFile.execAndReturnVectorOfDouble(fuel_oil_heating_query).get, units_represented) + end + + centralFuelOilHeating = array_sum(centralFuelOilHeating, modeledCentralFuelOilHeating, units_represented, units.length) + + fuel_oil_interior_equipment_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:FUELOILINTERIOREQUIPMENT') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" + unless sqlFile.execAndReturnVectorOfDouble(fuel_oil_interior_equipment_query).get.empty? + fuelOilInteriorEquipment = array_sum(fuelOilInteriorEquipment, sqlFile.execAndReturnVectorOfDouble(fuel_oil_interior_equipment_query).get, units_represented) + end + + fuel_oil_water_systems_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:FUELOILWATERSYSTEMS') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" + unless sqlFile.execAndReturnVectorOfDouble(fuel_oil_water_systems_query).get.empty? + fuelOilWaterSystems = array_sum(fuelOilWaterSystems, sqlFile.execAndReturnVectorOfDouble(fuel_oil_water_systems_query).get, units_represented) + end + + propane_heating_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:PROPANEHEATING') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" + unless sqlFile.execAndReturnVectorOfDouble(propane_heating_query).get.empty? + propaneHeating = array_sum(propaneHeating, sqlFile.execAndReturnVectorOfDouble(propane_heating_query).get, units_represented) + end + + centralPropaneHeating = array_sum(centralPropaneHeating, modeledCentralPropaneHeating, units_represented, units.length) + + propane_interior_equipment_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:PROPANEINTERIOREQUIPMENT') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" + unless sqlFile.execAndReturnVectorOfDouble(propane_interior_equipment_query).get.empty? + propaneInteriorEquipment = array_sum(propaneInteriorEquipment, sqlFile.execAndReturnVectorOfDouble(propane_interior_equipment_query).get, units_represented) + end + + propane_water_systems_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:PROPANEWATERSYSTEMS') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" + unless sqlFile.execAndReturnVectorOfDouble(propane_water_systems_query).get.empty? + propaneWaterSystems = array_sum(propaneWaterSystems, sqlFile.execAndReturnVectorOfDouble(propane_water_systems_query).get, units_represented) + end + + if include_enduse_subcategories + electricity_refrgerator_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:ELECTRICITYREFRIGERATOR') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" + unless sqlFile.execAndReturnVectorOfDouble(electricity_refrgerator_query).get.empty? + electricityRefrigerator = array_sum(electricityRefrigerator, sqlFile.execAndReturnVectorOfDouble(electricity_refrgerator_query).get, units_represented) + end + + electricity_clothes_washer_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:ELECTRICITYCLOTHESWASHER') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" + unless sqlFile.execAndReturnVectorOfDouble(electricity_clothes_washer_query).get.empty? + electricityClothesWasher = array_sum(electricityClothesWasher, sqlFile.execAndReturnVectorOfDouble(electricity_clothes_washer_query).get, units_represented) + end + + electricity_clothes_dryer_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:ELECTRICITYCLOTHESDRYER') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" + unless sqlFile.execAndReturnVectorOfDouble(electricity_clothes_dryer_query).get.empty? + electricityClothesDryer = array_sum(electricityClothesDryer, sqlFile.execAndReturnVectorOfDouble(electricity_clothes_dryer_query).get, units_represented) + end + + natural_gas_clothes_dryer_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:NATURALGASCLOTHESDRYER') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" + unless sqlFile.execAndReturnVectorOfDouble(natural_gas_clothes_dryer_query).get.empty? + naturalGasClothesDryer = array_sum(naturalGasClothesDryer, sqlFile.execAndReturnVectorOfDouble(natural_gas_clothes_dryer_query).get, units_represented) + end + + propane_clothes_dryer_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:PROPANECLOTHESDRYER') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" + unless sqlFile.execAndReturnVectorOfDouble(propane_clothes_dryer_query).get.empty? + propaneClothesDryer = array_sum(propaneClothesDryer, sqlFile.execAndReturnVectorOfDouble(propane_clothes_dryer_query).get, units_represented) + end + + electricity_cooking_range_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:ELECTRICITYCOOKINGRANGE') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" + unless sqlFile.execAndReturnVectorOfDouble(electricity_cooking_range_query).get.empty? + electricityCookingRange = array_sum(electricityCookingRange, sqlFile.execAndReturnVectorOfDouble(electricity_cooking_range_query).get, units_represented) + end + + natural_gas_cooking_range_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:NATURALGASCOOKINGRANGE') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" + unless sqlFile.execAndReturnVectorOfDouble(natural_gas_cooking_range_query).get.empty? + naturalGasCookingRange = array_sum(naturalGasCookingRange, sqlFile.execAndReturnVectorOfDouble(natural_gas_cooking_range_query).get, units_represented) + end + + propane_cooking_range_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:PROPANECOOKINGRANGE') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" + unless sqlFile.execAndReturnVectorOfDouble(propane_cooking_range_query).get.empty? + propaneCookingRange = array_sum(propaneCookingRange, sqlFile.execAndReturnVectorOfDouble(propane_cooking_range_query).get, units_represented) + end + + electricity_dishwasher_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:ELECTRICITYDISHWASHER') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" + unless sqlFile.execAndReturnVectorOfDouble(electricity_dishwasher_query).get.empty? + electricityDishwasher = array_sum(electricityDishwasher, sqlFile.execAndReturnVectorOfDouble(electricity_dishwasher_query).get, units_represented) + end + + electricity_plug_loads_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:ELECTRICITYPLUGLOADS') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" + unless sqlFile.execAndReturnVectorOfDouble(electricity_plug_loads_query).get.empty? + electricityPlugLoads = array_sum(electricityPlugLoads, sqlFile.execAndReturnVectorOfDouble(electricity_plug_loads_query).get, units_represented) + end + + electricity_house_fan_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:ELECTRICITYHOUSEFAN') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" + unless sqlFile.execAndReturnVectorOfDouble(electricity_house_fan_query).get.empty? + electricityHouseFan = array_sum(electricityHouseFan, sqlFile.execAndReturnVectorOfDouble(electricity_house_fan_query).get, units_represented) + end + + electricity_range_fan_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:ELECTRICITYRANGEFAN') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" + unless sqlFile.execAndReturnVectorOfDouble(electricity_range_fan_query).get.empty? + electricityRangeFan = array_sum(electricityRangeFan, sqlFile.execAndReturnVectorOfDouble(electricity_range_fan_query).get, units_represented) + end + + electricity_bath_fan_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:ELECTRICITYBATHFAN') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" + unless sqlFile.execAndReturnVectorOfDouble(electricity_bath_fan_query).get.empty? + electricityBathFan = array_sum(electricityBathFan, sqlFile.execAndReturnVectorOfDouble(electricity_bath_fan_query).get, units_represented) + end + + electricity_ceiling_fan_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:ELECTRICITYCEILINGFAN') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" + unless sqlFile.execAndReturnVectorOfDouble(electricity_ceiling_fan_query).get.empty? + electricityCeilingFan = array_sum(electricityCeilingFan, sqlFile.execAndReturnVectorOfDouble(electricity_ceiling_fan_query).get, units_represented) + end + + electricity_extra_refrigerator_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:ELECTRICITYEXTRAREFRIGERATOR') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" + unless sqlFile.execAndReturnVectorOfDouble(electricity_extra_refrigerator_query).get.empty? + electricityExtraRefrigerator = array_sum(electricityExtraRefrigerator, sqlFile.execAndReturnVectorOfDouble(electricity_extra_refrigerator_query).get, units_represented) + end + electricityExtraRefrigerator = array_sum(electricityExtraRefrigerator, modeledCentralElectricityExtraRefrigerator, units_represented, units.length) + + electricity_freezer_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:ELECTRICITYFREEZER') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" + unless sqlFile.execAndReturnVectorOfDouble(electricity_freezer_query).get.empty? + electricityFreezer = array_sum(electricityFreezer, sqlFile.execAndReturnVectorOfDouble(electricity_freezer_query).get, units_represented) + end + electricityFreezer = array_sum(electricityFreezer, modeledCentralElectricityFreezer, units_represented, units.length) + + electricity_pool_heater_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:ELECTRICITYPOOLHEATER') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" + unless sqlFile.execAndReturnVectorOfDouble(electricity_pool_heater_query).get.empty? + electricityPoolHeater = array_sum(electricityPoolHeater, sqlFile.execAndReturnVectorOfDouble(electricity_pool_heater_query).get, units_represented) + end + + electricity_pool_pump_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:ELECTRICITYPOOLPUMP') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" + unless sqlFile.execAndReturnVectorOfDouble(electricity_pool_pump_query).get.empty? + electricityPoolPump = array_sum(electricityPoolPump, sqlFile.execAndReturnVectorOfDouble(electricity_pool_pump_query).get, units_represented) + end + + electricity_hot_tub_heater_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:ELECTRICITYHOTTUBHEATER') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" + unless sqlFile.execAndReturnVectorOfDouble(electricity_hot_tub_heater_query).get.empty? + electricityHotTubHeater = array_sum(electricityHotTubHeater, sqlFile.execAndReturnVectorOfDouble(electricity_hot_tub_heater_query).get, units_represented) + end + + electricity_hot_tub_pump_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:ELECTRICITYHOTTUBPUMP') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" + unless sqlFile.execAndReturnVectorOfDouble(electricity_hot_tub_pump_query).get.empty? + electricityHotTubPump = array_sum(electricityHotTubPump, sqlFile.execAndReturnVectorOfDouble(electricity_hot_tub_pump_query).get, units_represented) + end + + electricity_well_pump_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:ELECTRICITYWELLPUMP') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" + unless sqlFile.execAndReturnVectorOfDouble(electricity_well_pump_query).get.empty? + electricityWellPump = array_sum(electricityWellPump, sqlFile.execAndReturnVectorOfDouble(electricity_well_pump_query).get, units_represented) + end + + electricityGarageLighting = array_sum(electricityGarageLighting, modeledCentralElectricityGarageLighting, units_represented, units.length) + + natural_gas_pool_heater_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:NATURALGASPOOLHEATER') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" + unless sqlFile.execAndReturnVectorOfDouble(natural_gas_pool_heater_query).get.empty? + naturalGasPoolHeater = array_sum(naturalGasPoolHeater, sqlFile.execAndReturnVectorOfDouble(natural_gas_pool_heater_query).get, units_represented) + end + + natural_gas_hot_tub_heater_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:NATURALGASHOTTUBHEATER') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" + unless sqlFile.execAndReturnVectorOfDouble(natural_gas_hot_tub_heater_query).get.empty? + naturalGasHotTubHeater = array_sum(naturalGasHotTubHeater, sqlFile.execAndReturnVectorOfDouble(natural_gas_hot_tub_heater_query).get, units_represented) + end + + natural_gas_grill_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:NATURALGASGRILL') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" + unless sqlFile.execAndReturnVectorOfDouble(natural_gas_grill_query).get.empty? + naturalGasGrill = array_sum(naturalGasGrill, sqlFile.execAndReturnVectorOfDouble(natural_gas_grill_query).get, units_represented) + end + naturalGasGrill = array_sum(naturalGasGrill, modeledCentralNaturalGasGrill, units_represented, units.length) + + natural_gas_lighting_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:NATURALGASLIGHTING') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" + unless sqlFile.execAndReturnVectorOfDouble(natural_gas_lighting_query).get.empty? + naturalGasLighting = array_sum(naturalGasLighting, sqlFile.execAndReturnVectorOfDouble(natural_gas_lighting_query).get, units_represented) + end + naturalGasLighting = array_sum(naturalGasLighting, modeledCentralNaturalGasLighting, units_represented, units.length) + + natural_gas_fireplace_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:NATURALGASFIREPLACE') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" + unless sqlFile.execAndReturnVectorOfDouble(natural_gas_fireplace_query).get.empty? + naturalGasFireplace = array_sum(naturalGasFireplace, sqlFile.execAndReturnVectorOfDouble(natural_gas_fireplace_query).get, units_represented) + end + naturalGasFireplace = array_sum(naturalGasFireplace, modeledCentralNaturalGasFireplace, units_represented, units.length) + end + end + + # Get the timestamps for actual year epw file, and the number of intervals per hour + weather = WeatherProcess.new(model, runner) + if weather.error? + return false + end + + actual_year_timestamps = weather.actual_year_timestamps(reporting_frequency) + + # Initialize timeseries hash which will be exported to csv + timeseries = {} + timeseries["Time"] = datetimes # timestamps from the sqlfile (TMY) + unless actual_year_timestamps.empty? + timeseries["Time"] = actual_year_timestamps # timestamps constructed using run period and Time class (AMY) + end + if timeseries["Time"].length != num_ts + runner.registerError("The timestamps array length does not equal that of the sqlfile timeseries. You may be ignoring leap days in your AMY weather file.") + return false + end + + # ELECTRICITY + + electricityTotalEndUses = [electricityHeating, centralElectricityHeating, electricityCooling, centralElectricityCooling, electricityInteriorLighting, electricityExteriorLighting, electricityExteriorHolidayLighting, electricityInteriorEquipment, electricityFansHeating, electricityFansCooling, electricityPumpsHeating, centralElectricityPumpsHeating, electricityPumpsCooling, centralElectricityPumpsCooling, electricityWaterSystems].transpose.map { |e| e.reduce(:+) } + + report_ts_output(runner, timeseries, "total_site_electricity_kwh", electricityTotalEndUses, "GJ", elec_site_units) + report_ts_output(runner, timeseries, "net_site_electricity_kwh", [electricityTotalEndUses, modeledCentralElectricityPhotovoltaics].transpose.collect { |e1, e2| e1 - e2 }, "GJ", elec_site_units) + report_ts_output(runner, timeseries, "electricity_heating_kwh", electricityHeating, "GJ", elec_site_units) + report_ts_output(runner, timeseries, "electricity_central_system_heating_kwh", centralElectricityHeating, "GJ", elec_site_units) + report_ts_output(runner, timeseries, "electricity_cooling_kwh", electricityCooling, "GJ", elec_site_units) + report_ts_output(runner, timeseries, "electricity_central_system_cooling_kwh", centralElectricityCooling, "GJ", elec_site_units) + report_ts_output(runner, timeseries, "electricity_interior_lighting_kwh", electricityInteriorLighting, "GJ", elec_site_units) + report_ts_output(runner, timeseries, "electricity_exterior_lighting_kwh", [electricityExteriorLighting, electricityExteriorHolidayLighting].transpose.map { |e| e.reduce(:+) }, "GJ", elec_site_units) + report_ts_output(runner, timeseries, "electricity_interior_equipment_kwh", electricityInteriorEquipment, "GJ", elec_site_units) + report_ts_output(runner, timeseries, "electricity_fans_heating_kwh", electricityFansHeating, "GJ", elec_site_units) + report_ts_output(runner, timeseries, "electricity_fans_cooling_kwh", electricityFansCooling, "GJ", elec_site_units) + report_ts_output(runner, timeseries, "electricity_pumps_heating_kwh", electricityPumpsHeating, "GJ", elec_site_units) + report_ts_output(runner, timeseries, "electricity_central_system_pumps_heating_kwh", centralElectricityPumpsHeating, "GJ", elec_site_units) + report_ts_output(runner, timeseries, "electricity_pumps_cooling_kwh", electricityPumpsCooling, "GJ", elec_site_units) + report_ts_output(runner, timeseries, "electricity_central_system_pumps_cooling_kwh", centralElectricityPumpsCooling, "GJ", elec_site_units) + report_ts_output(runner, timeseries, "electricity_water_systems_kwh", electricityWaterSystems, "GJ", elec_site_units) + report_ts_output(runner, timeseries, "electricity_pv_kwh", modeledCentralElectricityPhotovoltaics, "GJ", elec_site_units) + + # NATURAL GAS + + naturalGasTotalEndUses = [naturalGasHeating, centralNaturalGasHeating, naturalGasInteriorEquipment, naturalGasWaterSystems].transpose.map { |n| n.reduce(:+) } + + report_ts_output(runner, timeseries, "total_site_natural_gas_therm", naturalGasTotalEndUses, "GJ", gas_site_units) + report_ts_output(runner, timeseries, "natural_gas_heating_therm", naturalGasHeating, "GJ", gas_site_units) + report_ts_output(runner, timeseries, "natural_gas_central_system_heating_therm", centralNaturalGasHeating, "GJ", gas_site_units) + report_ts_output(runner, timeseries, "natural_gas_interior_equipment_therm", naturalGasInteriorEquipment, "GJ", gas_site_units) + report_ts_output(runner, timeseries, "natural_gas_water_systems_therm", naturalGasWaterSystems, "GJ", gas_site_units) + + # FUEL OIL + + fuelOilTotalEndUses = [fuelOilHeating, centralFuelOilHeating, fuelOilInteriorEquipment, fuelOilWaterSystems].transpose.map { |f| f.reduce(:+) } + + report_ts_output(runner, timeseries, "total_site_fuel_oil_mbtu", fuelOilTotalEndUses, "GJ", other_fuel_site_units) + report_ts_output(runner, timeseries, "fuel_oil_heating_mbtu", fuelOilHeating, "GJ", other_fuel_site_units) + report_ts_output(runner, timeseries, "fuel_oil_central_system_heating_mbtu", centralFuelOilHeating, "GJ", other_fuel_site_units) + report_ts_output(runner, timeseries, "fuel_oil_interior_equipment_mbtu", fuelOilInteriorEquipment, "GJ", other_fuel_site_units) + report_ts_output(runner, timeseries, "fuel_oil_water_systems_mbtu", fuelOilWaterSystems, "GJ", other_fuel_site_units) + + # PROPANE + + propaneTotalEndUses = [propaneHeating, centralPropaneHeating, propaneInteriorEquipment, propaneWaterSystems].transpose.map { |p| p.reduce(:+) } + + report_ts_output(runner, timeseries, "total_site_propane_mbtu", propaneTotalEndUses, "GJ", other_fuel_site_units) + report_ts_output(runner, timeseries, "propane_heating_mbtu", propaneHeating, "GJ", other_fuel_site_units) + report_ts_output(runner, timeseries, "propane_central_system_heating_mbtu", centralPropaneHeating, "GJ", other_fuel_site_units) + report_ts_output(runner, timeseries, "propane_interior_equipment_mbtu", propaneInteriorEquipment, "GJ", other_fuel_site_units) + report_ts_output(runner, timeseries, "propane_water_systems_mbtu", propaneWaterSystems, "GJ", other_fuel_site_units) + + # TOTAL + + totalSiteEnergy = [electricityTotalEndUses, naturalGasTotalEndUses, fuelOilTotalEndUses, propaneTotalEndUses].transpose.map { |t| t.reduce(:+) } + + report_ts_output(runner, timeseries, "total_site_energy_mbtu", totalSiteEnergy, "GJ", total_site_units) + report_ts_output(runner, timeseries, "net_site_energy_mbtu", [totalSiteEnergy, modeledCentralElectricityPhotovoltaics].transpose.collect { |e1, e2| e1 - e2 }, "GJ", total_site_units) + + # END USE SUBCATEGORIES + + if include_enduse_subcategories + report_ts_output(runner, timeseries, "electricity_refrigerator_kwh", electricityRefrigerator, "GJ", elec_site_units) + report_ts_output(runner, timeseries, "electricity_clothes_washer_kwh", electricityClothesWasher, "GJ", elec_site_units) + report_ts_output(runner, timeseries, "electricity_clothes_dryer_kwh", electricityClothesDryer, "GJ", elec_site_units) + report_ts_output(runner, timeseries, "natural_gas_clothes_dryer_therm", naturalGasClothesDryer, "GJ", gas_site_units) + report_ts_output(runner, timeseries, "propane_clothes_dryer_mbtu", propaneClothesDryer, "GJ", other_fuel_site_units) + report_ts_output(runner, timeseries, "electricity_cooking_range_kwh", electricityCookingRange, "GJ", elec_site_units) + report_ts_output(runner, timeseries, "natural_gas_cooking_range_therm", naturalGasCookingRange, "GJ", gas_site_units) + report_ts_output(runner, timeseries, "propane_cooking_range_mbtu", propaneCookingRange, "GJ", other_fuel_site_units) + report_ts_output(runner, timeseries, "electricity_dishwasher_kwh", electricityDishwasher, "GJ", elec_site_units) + report_ts_output(runner, timeseries, "electricity_plug_loads_kwh", electricityPlugLoads, "GJ", elec_site_units) + report_ts_output(runner, timeseries, "electricity_house_fan_kwh", electricityHouseFan, "GJ", elec_site_units) + report_ts_output(runner, timeseries, "electricity_range_fan_kwh", electricityRangeFan, "GJ", elec_site_units) + report_ts_output(runner, timeseries, "electricity_bath_fan_kwh", electricityBathFan, "GJ", elec_site_units) + report_ts_output(runner, timeseries, "electricity_ceiling_fan_kwh", electricityCeilingFan, "GJ", elec_site_units) + report_ts_output(runner, timeseries, "electricity_extra_refrigerator_kwh", electricityExtraRefrigerator, "GJ", elec_site_units) + report_ts_output(runner, timeseries, "electricity_freezer_kwh", electricityFreezer, "GJ", elec_site_units) + report_ts_output(runner, timeseries, "electricity_pool_heater_kwh", electricityPoolHeater, "GJ", elec_site_units) + report_ts_output(runner, timeseries, "natural_gas_pool_heater_therm", naturalGasPoolHeater, "GJ", gas_site_units) + report_ts_output(runner, timeseries, "electricity_pool_pump_kwh", electricityPoolPump, "GJ", elec_site_units) + report_ts_output(runner, timeseries, "electricity_hot_tub_heater_kwh", electricityHotTubHeater, "GJ", elec_site_units) + report_ts_output(runner, timeseries, "natural_gas_hot_tub_heater_therm", naturalGasHotTubHeater, "GJ", gas_site_units) + report_ts_output(runner, timeseries, "electricity_hot_tub_pump_kwh", electricityHotTubPump, "GJ", elec_site_units) + report_ts_output(runner, timeseries, "natural_gas_grill_therm", naturalGasGrill, "GJ", gas_site_units) + report_ts_output(runner, timeseries, "natural_gas_lighting_therm", naturalGasLighting, "GJ", gas_site_units) + report_ts_output(runner, timeseries, "natural_gas_fireplace_therm", naturalGasFireplace, "GJ", gas_site_units) + report_ts_output(runner, timeseries, "electricity_well_pump_kwh", electricityWellPump, "GJ", elec_site_units) + report_ts_output(runner, timeseries, "electricity_garage_lighting_kwh", electricityGarageLighting, "GJ", elec_site_units) + report_ts_output(runner, timeseries, "electricity_exterior_holiday_lighting_kwh", electricityExteriorHolidayLighting, "GJ", elec_site_units) + end + + output_vars.each do |output_var| + sqlFile.availableKeyValues(ann_env_pd, reporting_frequency_map[reporting_frequency], output_var).each do |key_value| + request = sqlFile.timeSeries(ann_env_pd, reporting_frequency_map[reporting_frequency], output_var, key_value) + next if request.empty? + + request = request.get + vals = request.values + old_units = request.units + new_units = old_units + if old_units == "C" + new_units = "F" + end + name = "#{output_var.upcase} (#{key_value})" + unless new_units.empty? + name += " [#{new_units}]" + end + report_ts_output(runner, timeseries, name, vals, old_units, new_units) + end + end + + sqlFile.close() + + csv_path = File.expand_path("../enduse_timeseries.csv") + CSV.open(csv_path, "wb") do |csv| + csv << timeseries.keys + rows = timeseries.values.transpose + rows.each do |row| + csv << row + end + end + + return true + end # end the run method + + def report_ts_output(runner, timeseries, name, vals, os_units, desired_units) + timeseries[name] = [] + timeseries["Time"].each_with_index do |ts, i| + timeseries[name] << UnitConversions.convert(vals[i], os_units, desired_units) + end + runner.registerInfo("Exporting #{name}.") + end + + def format_datetime(date_time) + date_time.gsub!("-", "/") + date_time.gsub!("Jan", "01") + date_time.gsub!("Feb", "02") + date_time.gsub!("Mar", "03") + date_time.gsub!("Apr", "04") + date_time.gsub!("May", "05") + date_time.gsub!("Jun", "06") + date_time.gsub!("Jul", "07") + date_time.gsub!("Aug", "08") + date_time.gsub!("Sep", "09") + date_time.gsub!("Oct", "10") + date_time.gsub!("Nov", "11") + date_time.gsub!("Dec", "12") + return date_time + end + + def array_sum(array1, array2, units_represented = 1, num_units = 1) + array = [array1, array2].transpose.collect { |a1, a2| a1 + units_represented * (a2 / num_units) } + return array + end +end + +# register the measure to be used by the application +TimeseriesCSVExport.new.registerWithApplication diff --git a/buildstockbatch/test/test_inputs/test_openstudio_buildstock/measures/TimeseriesCSVExport/measure.xml b/buildstockbatch/test/test_inputs/test_openstudio_buildstock/measures/TimeseriesCSVExport/measure.xml new file mode 100644 index 00000000..1e66a32c --- /dev/null +++ b/buildstockbatch/test/test_inputs/test_openstudio_buildstock/measures/TimeseriesCSVExport/measure.xml @@ -0,0 +1,103 @@ + + 3.0 + timeseries_csv_export + 2a3442c1-944d-4e91-9e11-11e0cf368c64 + b75af608-82c7-466b-9a63-7d0366d216c9 + 20190708T154332Z + 15BF4E57 + TimeseriesCSVExport + Timeseries CSV Export + Exports timeseries output data to csv. + Exports all available timeseries enduses, subcategories, and output variables to csv file(s). + + + reporting_frequency + Reporting Frequency + The frequency at which to report timeseries output data. + Choice + true + false + Hourly + + + Timestep + Timestep + + + Hourly + Hourly + + + Daily + Daily + + + Monthly + Monthly + + + Runperiod + Runperiod + + + + + include_enduse_subcategories + Include End Use Subcategories + Whether to report end use subcategories: appliances, plug loads, fans, large uncommon loads. + Boolean + true + false + false + + + true + true + + + false + false + + + + + output_variables + Output Variables + Specify a comma-separated list of output variables to report. (See EnergyPlus's rdd file for available output variables.) + String + false + false + + + + + + Reporting.QAQC + + + + Measure Type + ReportingMeasure + string + + + + + timeseries_csv_export_test.rb + rb + test + D08DBB75 + + + + OpenStudio + 2.0.5 + 2.0.5 + + measure.rb + rb + script + D894BB75 + + + diff --git a/buildstockbatch/test/test_validation.py b/buildstockbatch/test/test_validation.py index 254b5da1..8740e73e 100644 --- a/buildstockbatch/test/test_validation.py +++ b/buildstockbatch/test/test_validation.py @@ -89,6 +89,30 @@ def test_validation_integration(project_file, expected): assert(BuildStockBatchBase.validate_project(project_file)) +@pytest.mark.parametrize("project_file", [ + os.path.join(example_yml_dir, 'enforce-validate-measures-bad.yml') +]) +def test_bad_measures(project_file): + try: + BuildStockBatchBase.validate_measures_and_arguments(project_file) + except ValueError as er: + er = str(er) + assert "ReportingMeasure2 does not exist" in er + assert "Wrong argument value type for begin_day_of_month" in er + assert "Found unexpected argument key output_variable" in er + assert "Found unexpected argument value Huorly" in er + + else: + raise Exception("measures_and_arguments was supposed to raise ValueError for enforce-validate-measures-bad.yml") + + +@pytest.mark.parametrize("project_file", [ + os.path.join(example_yml_dir, 'enforce-validate-measures-good.yml'), +]) +def test_good_measures(project_file): + assert BuildStockBatchBase.validate_measures_and_arguments(project_file) + + @pytest.mark.parametrize("project_file", [ os.path.join(example_yml_dir, 'enforce-validate-options-wrong-path.yml'), ]) From 33f4fb0bd463bc0086a37efe6f0cd28fa8f5e170 Mon Sep 17 00:00:00 2001 From: Joe Robertson Date: Tue, 13 Aug 2019 10:00:50 -0600 Subject: [PATCH 04/11] Some patching so other tests still pass. --- buildstockbatch/base.py | 5 +++-- buildstockbatch/test/conftest.py | 2 +- buildstockbatch/test/test_eagle.py | 4 +++- buildstockbatch/test/test_validation.py | 3 ++- 4 files changed, 9 insertions(+), 5 deletions(-) diff --git a/buildstockbatch/base.py b/buildstockbatch/base.py index 5d2e1ac9..82cdb3a3 100644 --- a/buildstockbatch/base.py +++ b/buildstockbatch/base.py @@ -341,8 +341,9 @@ def validate_measures_and_arguments(project_file): 'ApplyUpgrade': 'upgrades', 'TimeseriesCSVExport': 'timeseries_csv_export' } - for reporting_measure in cfg['reporting_measures']: - measure_names[reporting_measure] = 'reporting_measures' + if 'reporting_measures' in cfg.keys(): + for reporting_measure in cfg['reporting_measures']: + measure_names[reporting_measure] = 'reporting_measures' def get_measure_xml(xml_path): tree = ET.parse(xml_path) diff --git a/buildstockbatch/test/conftest.py b/buildstockbatch/test/conftest.py index 3ae777f4..98d39667 100644 --- a/buildstockbatch/test/conftest.py +++ b/buildstockbatch/test/conftest.py @@ -32,7 +32,7 @@ def _basic_residential_project_file(update_args={}): }, 'timeseries_csv_export': { 'reporting_frequency': 'Hourly', - 'include_enduse_subcategories': 'true' + 'include_enduse_subcategories': True }, 'eagle': { 'sampling': { diff --git a/buildstockbatch/test/test_eagle.py b/buildstockbatch/test/test_eagle.py index 81ec4a36..241d09f3 100644 --- a/buildstockbatch/test/test_eagle.py +++ b/buildstockbatch/test/test_eagle.py @@ -7,9 +7,11 @@ from buildstockbatch.eagle import user_cli, EagleBatch +@patch('buildstockbatch.base.BuildStockBatchBase.validate_measures_and_arguments') @patch('buildstockbatch.base.BuildStockBatchBase.validate_options_lookup') @patch('buildstockbatch.eagle.subprocess') -def test_user_cli(mock_subprocess, mock_validate_options, basic_residential_project_file): +def test_user_cli(mock_subprocess, mock_validate_options, mock_validate_measures, basic_residential_project_file): + mock_validate_measures.return_value = True mock_validate_options.return_value = True project_filename, results_dir = basic_residential_project_file() diff --git a/buildstockbatch/test/test_validation.py b/buildstockbatch/test/test_validation.py index 8740e73e..35a066f4 100644 --- a/buildstockbatch/test/test_validation.py +++ b/buildstockbatch/test/test_validation.py @@ -81,7 +81,8 @@ def test_xor_violations_fail(project_file): ]) def test_validation_integration(project_file, expected): # patch the validate_options_lookup function to always return true for this case - with patch.object(BuildStockBatchBase, 'validate_options_lookup', lambda _: True): + with patch.object(BuildStockBatchBase, 'validate_measures_and_arguments', lambda _: True), \ + patch.object(BuildStockBatchBase, 'validate_options_lookup', lambda _: True): if expected is not True: with pytest.raises(expected): BuildStockBatchBase.validate_project(project_file) From 5eda61d0aa5c21940fe22d9008c6062a0fcae388 Mon Sep 17 00:00:00 2001 From: Joe Robertson Date: Tue, 13 Aug 2019 10:07:09 -0600 Subject: [PATCH 05/11] Push empty files so folder exists. --- .../measures/ReportingMeasure1/measure.rb | 0 .../measures/ReportingMeasure1/measure.xml | 0 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 buildstockbatch/test/test_inputs/test_openstudio_buildstock/measures/ReportingMeasure1/measure.rb create mode 100644 buildstockbatch/test/test_inputs/test_openstudio_buildstock/measures/ReportingMeasure1/measure.xml diff --git a/buildstockbatch/test/test_inputs/test_openstudio_buildstock/measures/ReportingMeasure1/measure.rb b/buildstockbatch/test/test_inputs/test_openstudio_buildstock/measures/ReportingMeasure1/measure.rb new file mode 100644 index 00000000..e69de29b diff --git a/buildstockbatch/test/test_inputs/test_openstudio_buildstock/measures/ReportingMeasure1/measure.xml b/buildstockbatch/test/test_inputs/test_openstudio_buildstock/measures/ReportingMeasure1/measure.xml new file mode 100644 index 00000000..e69de29b From 8433e89c330b338884be12800e1f74c267685fc4 Mon Sep 17 00:00:00 2001 From: Noel Merket Date: Fri, 20 Sep 2019 10:28:01 -0600 Subject: [PATCH 06/11] reverting schema changes. --- buildstockbatch/schemas/v0.1.yaml | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/buildstockbatch/schemas/v0.1.yaml b/buildstockbatch/schemas/v0.1.yaml index 6f20ed2c..07e2be3c 100644 --- a/buildstockbatch/schemas/v0.1.yaml +++ b/buildstockbatch/schemas/v0.1.yaml @@ -7,7 +7,7 @@ eagle: include('hpc-spec', required=False) output_directory: str(required=False) sys_image_dir: str(required=False) baseline: include('sim-spec', required=True) -timeseries_csv_export: include('timeseries-csv-export-spec', required=False) +timeseries_csv_export: map(required=False) upgrades: list(include('upgrade-spec'), required=False) downselect: include('downselect-spec',required=False) postprocessing: include('postprocessing-spec', required=False) @@ -87,8 +87,4 @@ residential-simulation-spec: begin_day_of_month: int(required=False) end_month: int(required=False) end_day_of_month: int(required=False) - calendar_year: int(required=False) -timeseries-csv-export-spec: - reporting_frequency: str(required=False) - include_enduse_subcategories: bool(required=False) - output_variables: list(required=False) + calendar_year: int(required=False) \ No newline at end of file From c84af52aed948897265d97e9659fe924825a6038 Mon Sep 17 00:00:00 2001 From: Noel Merket Date: Fri, 20 Sep 2019 10:30:46 -0600 Subject: [PATCH 07/11] removing ruby measures from testing directory because they're not necessary for testing --- .../measures/ApplyUpgrade/measure.rb | 329 ----- .../measures/BuildExistingModel/measure.rb | 225 ---- .../measures/ReportingMeasure1/measure.rb | 0 .../ResidentialSimulationControls/measure.rb | 148 --- .../ServerDirectoryCleanup/measure.rb | 83 -- .../SimulationOutputReport/measure.rb | 1115 ----------------- .../measures/TimeseriesCSVExport/measure.rb | 778 ------------ 7 files changed, 2678 deletions(-) delete mode 100644 buildstockbatch/test/test_inputs/test_openstudio_buildstock/measures/ApplyUpgrade/measure.rb delete mode 100644 buildstockbatch/test/test_inputs/test_openstudio_buildstock/measures/BuildExistingModel/measure.rb delete mode 100644 buildstockbatch/test/test_inputs/test_openstudio_buildstock/measures/ReportingMeasure1/measure.rb delete mode 100644 buildstockbatch/test/test_inputs/test_openstudio_buildstock/measures/ResidentialSimulationControls/measure.rb delete mode 100644 buildstockbatch/test/test_inputs/test_openstudio_buildstock/measures/ServerDirectoryCleanup/measure.rb delete mode 100644 buildstockbatch/test/test_inputs/test_openstudio_buildstock/measures/SimulationOutputReport/measure.rb delete mode 100644 buildstockbatch/test/test_inputs/test_openstudio_buildstock/measures/TimeseriesCSVExport/measure.rb diff --git a/buildstockbatch/test/test_inputs/test_openstudio_buildstock/measures/ApplyUpgrade/measure.rb b/buildstockbatch/test/test_inputs/test_openstudio_buildstock/measures/ApplyUpgrade/measure.rb deleted file mode 100644 index 8aa70287..00000000 --- a/buildstockbatch/test/test_inputs/test_openstudio_buildstock/measures/ApplyUpgrade/measure.rb +++ /dev/null @@ -1,329 +0,0 @@ -# see the URL below for information on how to write OpenStudio measures -# http://nrel.github.io/OpenStudio-user-documentation/measures/measure_writing_guide/ - -# Adapted from Measure Picker measure -# https://github.com/NREL/OpenStudio-measures/blob/develop/NREL%20working%20measures/measure_picker/measure.rb - -require 'csv' -require 'openstudio' - -require 'openstudio' -if File.exists? File.absolute_path(File.join(File.dirname(__FILE__), "../../lib/resources/measures/HPXMLtoOpenStudio/resources")) # Hack to run ResStock on AWS - resources_path = File.absolute_path(File.join(File.dirname(__FILE__), "../../lib/resources/measures/HPXMLtoOpenStudio/resources")) -elsif File.exists? File.absolute_path(File.join(File.dirname(__FILE__), "../../resources/measures/HPXMLtoOpenStudio/resources")) # Hack to run ResStock unit tests locally - resources_path = File.absolute_path(File.join(File.dirname(__FILE__), "../../resources/measures/HPXMLtoOpenStudio/resources")) -elsif File.exists? File.join(OpenStudio::BCLMeasure::userMeasuresDir.to_s, "HPXMLtoOpenStudio/resources") # Hack to run measures in the OS App since applied measures are copied off into a temporary directory - resources_path = File.join(OpenStudio::BCLMeasure::userMeasuresDir.to_s, "HPXMLtoOpenStudio/resources") -else - resources_path = File.absolute_path(File.join(File.dirname(__FILE__), "../HPXMLtoOpenStudio/resources")) -end -require File.join(resources_path, "constants") - -# start the measure -class ApplyUpgrade < OpenStudio::Ruleset::ModelUserScript - # human readable name - def name - return "Apply Upgrade" - end - - # human readable description - def description - return "Measure that applies an upgrade (one or more child measures) to a building model based on the specified logic." - end - - # human readable description of modeling approach - def modeler_description - return "Determines if the upgrade should apply to a given building model. If so, calls one or more child measures with the appropriate arguments." - end - - def num_options - return Constants.NumApplyUpgradeOptions # Synced with SimulationOutputReport measure - end - - def num_costs_per_option - return Constants.NumApplyUpgradesCostsPerOption # Synced with SimulationOutputReport measure - end - - # define the arguments that the user will input - def arguments(model) - args = OpenStudio::Ruleset::OSArgumentVector.new - - # Make string arg for upgrade name - upgrade_name = OpenStudio::Ruleset::OSArgument::makeStringArgument("upgrade_name", true) - upgrade_name.setDisplayName("Upgrade Name") - upgrade_name.setDescription("User-specificed name that describes the upgrade.") - upgrade_name.setDefaultValue("My Upgrade") - args << upgrade_name - - for option_num in 1..num_options - - # Option name argument - option = OpenStudio::Ruleset::OSArgument.makeStringArgument("option_#{option_num}", (option_num == 1)) - option.setDisplayName("Option #{option_num}") - option.setDescription("Specify the parameter|option as found in resources\\options_lookup.tsv.") - args << option - - # Option Apply Logic argument - option_apply_logic = OpenStudio::Ruleset::OSArgument.makeStringArgument("option_#{option_num}_apply_logic", false) - option_apply_logic.setDisplayName("Option #{option_num} Apply Logic") - option_apply_logic.setDescription("Logic that specifies if the Option #{option_num} upgrade will apply based on the existing building's options. Specify one or more parameter|option as found in resources\\options_lookup.tsv. When multiple are included, they must be separated by '||' for OR and '&&' for AND, and using parentheses as appropriate. Prefix an option with '!' for not.") - args << option_apply_logic - - for cost_num in 1..num_costs_per_option - - # Option Cost Value argument - cost_value = OpenStudio::Ruleset::OSArgument.makeDoubleArgument("option_#{option_num}_cost_#{cost_num}_value", false) - cost_value.setDisplayName("Option #{option_num} Cost #{cost_num} Value") - cost_value.setDescription("Total option #{option_num} cost is the sum of all: (Cost N Value) x (Cost N Multiplier).") - cost_value.setUnits("$") - args << cost_value - - # Option Cost Multiplier argument - choices = [ - "", - "Fixed (1)", - "Wall Area, Above-Grade, Conditioned (ft^2)", - "Wall Area, Above-Grade, Exterior (ft^2)", - "Wall Area, Below-Grade (ft^2)", - "Floor Area, Conditioned (ft^2)", - "Floor Area, Attic (ft^2)", - "Floor Area, Lighting (ft^2)", - "Roof Area (ft^2)", - "Window Area (ft^2)", - "Door Area (ft^2)", - "Duct Surface Area (ft^2)", - "Size, Heating System (kBtu/h)", - "Size, Cooling System (kBtu/h)", - "Size, Water Heater (gal)", - ] - cost_multiplier = OpenStudio::Ruleset::OSArgument.makeChoiceArgument("option_#{option_num}_cost_#{cost_num}_multiplier", choices, false) - cost_multiplier.setDisplayName("Option #{option_num} Cost #{cost_num} Multiplier") - cost_multiplier.setDescription("Total option #{option_num} cost is the sum of all: (Cost N Value) x (Cost N Multiplier).") - cost_multiplier.setDefaultValue(choices[0]) - args << cost_multiplier - - end - - # Option Lifetime argument - option_lifetime = OpenStudio::Ruleset::OSArgument.makeDoubleArgument("option_#{option_num}_lifetime", false) - option_lifetime.setDisplayName("Option #{option_num} Lifetime") - option_lifetime.setDescription("The option lifetime.") - option_lifetime.setUnits("years") - args << option_lifetime - - end - - # Package Apply Logic argument - package_apply_logic = OpenStudio::Ruleset::OSArgument.makeStringArgument("package_apply_logic", false) - package_apply_logic.setDisplayName("Package Apply Logic") - package_apply_logic.setDescription("Logic that specifies if the entire package upgrade (all options) will apply based on the existing building's options. Specify one or more parameter|option as found in resources\\options_lookup.tsv. When multiple are included, they must be separated by '||' for OR and '&&' for AND, and using parentheses as appropriate. Prefix an option with '!' for not.") - args << package_apply_logic - - # Make integer arg to run measure [1 is run, 0 is no run] - run_measure = OpenStudio::Ruleset::OSArgument::makeIntegerArgument("run_measure", true) - run_measure.setDisplayName("Run Measure") - run_measure.setDescription("integer argument to run measure [1 is run, 0 is no run]") - run_measure.setDefaultValue(1) - args << run_measure - - return args - end - - # define what happens when the measure is run - def run(model, runner, user_arguments) - super(model, runner, user_arguments) - - # use the built-in error checking - if !runner.validateUserArguments(arguments(model), user_arguments) - return false - end - - # Return N/A if not selected to run - run_measure = runner.getIntegerArgumentValue("run_measure", user_arguments) - if run_measure == 0 - runner.registerAsNotApplicable("Run Measure set to #{run_measure}.") - return true - end - - upgrade_name = runner.getStringArgumentValue("upgrade_name", user_arguments) - - # Retrieve Option X argument values - options = {} - for option_num in 1..num_options - if option_num == 1 - arg = runner.getStringArgumentValue("option_#{option_num}", user_arguments) - else - arg = runner.getOptionalStringArgumentValue("option_#{option_num}", user_arguments) - next if not arg.is_initialized - - arg = arg.get - end - next if arg.strip.size == 0 - - if not arg.include?('|') - runner.registerError("Option #{option_num} is missing the '|' delimiter.") - return false - end - options[option_num] = arg.strip - end - - # Retrieve Option X Apply Logic argument values - options_apply_logic = {} - for option_num in 1..num_options - arg = runner.getOptionalStringArgumentValue("option_#{option_num}_apply_logic", user_arguments) - next if not arg.is_initialized - - arg = arg.get - next if arg.strip.size == 0 - - if not arg.include?('|') - runner.registerError("Option #{option_num} Apply Logic is missing the '|' delimiter.") - return false - end - if not options.keys.include?(option_num) - runner.registerError("Option #{option_num} Apply Logic was provided, but a corresponding Option #{option_num} was not provided.") - return false - end - options_apply_logic[option_num] = arg.strip - end - - # Retrieve Package Apply Logic argument value - arg = runner.getOptionalStringArgumentValue("package_apply_logic", user_arguments) - if not arg.is_initialized - package_apply_logic = nil - else - arg = arg.get - if arg.strip.size == 0 - package_apply_logic = nil - else - if not arg.include?('|') - runner.registerError("Package Apply Logic is missing the '|' delimiter.") - return false - end - package_apply_logic = arg.strip - end - end - - # Get file/dir paths - resources_dir = File.absolute_path(File.join(File.dirname(__FILE__), "..", "..", "lib", "resources")) # Should have been uploaded per 'Additional Analysis Files' in PAT - check_dir_exists(resources_dir, runner) - characteristics_dir = File.absolute_path(File.join(File.dirname(__FILE__), "..", "..", "lib", "housing_characteristics")) # Should have been uploaded per 'Additional Analysis Files' in PAT - check_dir_exists(characteristics_dir, runner) - buildstock_file = File.join(resources_dir, "buildstock.rb") - measures_dir = File.join(resources_dir, "measures") - lookup_file = File.join(resources_dir, "options_lookup.tsv") - - # Load buildstock_file - require File.join(File.dirname(buildstock_file), File.basename(buildstock_file, File.extname(buildstock_file))) - - # Retrieve workflow_json from BuildExistingModel measure if provided - workflow_json = get_value_from_runner_past_results(runner, "workflow_json", "build_existing_model", false) - if not workflow_json.nil? - workflow_json = File.join(resources_dir, workflow_json) - end - - # Process package apply logic if provided - apply_package_upgrade = true - if not package_apply_logic.nil? - # Apply this package? - apply_package_upgrade = evaluate_logic(package_apply_logic, runner) - if apply_package_upgrade.nil? - return false - end - end - - measures = {} - if apply_package_upgrade - - # Obtain measures and arguments to be called - # Process options apply logic if provided - options.each do |option_num, option| - parameter_name, option_name = option.split('|') - - # Apply this option? - apply_option_upgrade = true - if options_apply_logic.include?(option_num) - apply_option_upgrade = evaluate_logic(options_apply_logic[option_num], runner) - if apply_option_upgrade.nil? - return false - end - end - - if not apply_option_upgrade - runner.registerInfo("Parameter #{parameter_name}, Option #{option_name} will not be applied.") - next - end - - # Register this option so that it replaces the existing building option in the results csv file - print_option_assignment(parameter_name, option_name, runner) - register_value(runner, parameter_name, option_name) - - # Register cost values/multipliers/lifetime for applied options; used by the SimulationOutputReport measure - for cost_num in 1..num_costs_per_option - cost_value = runner.getOptionalDoubleArgumentValue("option_#{option_num}_cost_#{cost_num}_value", user_arguments) - if cost_value.nil? - cost_value = 0.0 - end - cost_mult = runner.getStringArgumentValue("option_#{option_num}_cost_#{cost_num}_multiplier", user_arguments) - register_value(runner, "option_#{option_num}_cost_#{cost_num}_value_to_apply", cost_value.to_s) - register_value(runner, "option_#{option_num}_cost_#{cost_num}_multiplier_to_apply", cost_mult) - end - lifetime = runner.getOptionalDoubleArgumentValue("option_#{option_num}_lifetime", user_arguments) - if lifetime.nil? - lifetime = 0.0 - end - register_value(runner, "option_#{option_num}_lifetime_to_apply", lifetime.to_s) - - # Check file/dir paths exist - check_file_exists(lookup_file, runner) - - # Get measure name and arguments associated with the option - options_measure_args = get_measure_args_from_option_names(lookup_file, [option_name], parameter_name, runner) - options_measure_args[option_name].each do |measure_subdir, args_hash| - update_args_hash(measures, measure_subdir, args_hash, add_new = false) - end - end - - # Add measure arguments from existing building if needed - parameters = get_parameters_ordered_from_options_lookup_tsv(lookup_file, characteristics_dir) - measures.keys.each do |measure_subdir| - parameters.each do |parameter_name| - existing_option_name = get_value_from_runner_past_results(runner, parameter_name, "build_existing_model") - - options_measure_args = get_measure_args_from_option_names(lookup_file, [existing_option_name], parameter_name, runner) - options_measure_args[existing_option_name].each do |measure_subdir2, args_hash| - next if measure_subdir != measure_subdir2 - - # Append any new arguments - new_args_hash = {} - args_hash.each do |k, v| - next if measures[measure_subdir][0].has_key?(k) - - new_args_hash[k] = v - end - update_args_hash(measures, measure_subdir, new_args_hash, add_new = false) - end - end - end - - if not apply_measures(measures_dir, measures, runner, model, workflow_json, "measures-upgrade.osw", true) - return false - end - - end # apply_package_upgrade - - # Register the upgrade name - register_value(runner, "upgrade_name", upgrade_name) - - if measures.size == 0 - # Upgrade not applied; don't re-run existing home simulation - runner.haltWorkflow('Invalid') - return false - end - - return true - end -end - -# register the measure to be used by the application -ApplyUpgrade.new.registerWithApplication diff --git a/buildstockbatch/test/test_inputs/test_openstudio_buildstock/measures/BuildExistingModel/measure.rb b/buildstockbatch/test/test_inputs/test_openstudio_buildstock/measures/BuildExistingModel/measure.rb deleted file mode 100644 index db4b4b0d..00000000 --- a/buildstockbatch/test/test_inputs/test_openstudio_buildstock/measures/BuildExistingModel/measure.rb +++ /dev/null @@ -1,225 +0,0 @@ -# see the URL below for information on how to write OpenStudio measures -# http://nrel.github.io/OpenStudio-user-documentation/measures/measure_writing_guide/ - -require 'csv' -require 'openstudio' -if File.exists? File.absolute_path(File.join(File.dirname(__FILE__), "../../lib/resources/measures/HPXMLtoOpenStudio/resources")) # Hack to run ResStock on AWS - resources_path = File.absolute_path(File.join(File.dirname(__FILE__), "../../lib/resources/measures/HPXMLtoOpenStudio/resources")) -elsif File.exists? File.absolute_path(File.join(File.dirname(__FILE__), "../../resources/measures/HPXMLtoOpenStudio/resources")) # Hack to run ResStock unit tests locally - resources_path = File.absolute_path(File.join(File.dirname(__FILE__), "../../resources/measures/HPXMLtoOpenStudio/resources")) -elsif File.exists? File.join(OpenStudio::BCLMeasure::userMeasuresDir.to_s, "HPXMLtoOpenStudio/resources") # Hack to run measures in the OS App since applied measures are copied off into a temporary directory - resources_path = File.join(OpenStudio::BCLMeasure::userMeasuresDir.to_s, "HPXMLtoOpenStudio/resources") -else - resources_path = File.absolute_path(File.join(File.dirname(__FILE__), "../HPXMLtoOpenStudio/resources")) -end -require File.join(resources_path, "weather") - -# start the measure -class BuildExistingModel < OpenStudio::Measure::ModelMeasure - # human readable name - def name - return "Build Existing Model" - end - - # human readable description - def description - return "Builds the OpenStudio Model for an existing building." - end - - # human readable description of modeling approach - def modeler_description - return "Builds the OpenStudio Model using the sampling csv file, which contains the specified parameters for each existing building. Based on the supplied building number, those parameters are used to run the OpenStudio measures with appropriate arguments and build up the OpenStudio model." - end - - # define the arguments that the user will input - def arguments(model) - args = OpenStudio::Ruleset::OSArgumentVector.new - - building_id = OpenStudio::Ruleset::OSArgument.makeIntegerArgument("building_id", true) - building_id.setDisplayName("Building ID") - building_id.setDescription("The building number (between 1 and the number of samples).") - args << building_id - - workflow_json = OpenStudio::Ruleset::OSArgument.makeStringArgument("workflow_json", false) - workflow_json.setDisplayName("Workflow JSON") - workflow_json.setDescription("The name of the JSON file (in the resources dir) that dictates the order in which measures are to be run. If not provided, the order specified in resources/options_lookup.tsv will be used.") - args << workflow_json - - number_of_buildings_represented = OpenStudio::Ruleset::OSArgument.makeIntegerArgument("number_of_buildings_represented", false) - number_of_buildings_represented.setDisplayName("Number of Buildings Represented") - number_of_buildings_represented.setDescription("The total number of buildings represented by the existing building models.") - args << number_of_buildings_represented - - sample_weight = OpenStudio::Ruleset::OSArgument.makeDoubleArgument("sample_weight", false) - sample_weight.setDisplayName("Sample Weight of Simulation") - sample_weight.setDescription("Number of buildings this simulation represents.") - args << sample_weight - - downselect_logic = OpenStudio::Ruleset::OSArgument.makeStringArgument("downselect_logic", false) - downselect_logic.setDisplayName("Downselect Logic") - downselect_logic.setDescription("Logic that specifies the subset of the building stock to be considered in the analysis. Specify one or more parameter|option as found in resources\\options_lookup.tsv. When multiple are included, they must be separated by '||' for OR and '&&' for AND, and using parentheses as appropriate. Prefix an option with '!' for not.") - args << downselect_logic - - return args - end - - # define what happens when the measure is run - def run(model, runner, user_arguments) - super(model, runner, user_arguments) - - # use the built-in error checking - if !runner.validateUserArguments(arguments(model), user_arguments) - return false - end - - building_id = runner.getIntegerArgumentValue("building_id", user_arguments) - workflow_json = runner.getOptionalStringArgumentValue("workflow_json", user_arguments) - number_of_buildings_represented = runner.getOptionalIntegerArgumentValue("number_of_buildings_represented", user_arguments) - sample_weight = runner.getOptionalDoubleArgumentValue("sample_weight", user_arguments) - downselect_logic = runner.getOptionalStringArgumentValue("downselect_logic", user_arguments) - sample_weight = runner.getOptionalDoubleArgumentValue("sample_weight", user_arguments) - - # Get file/dir paths - resources_dir = File.absolute_path(File.join(File.dirname(__FILE__), "..", "..", "lib", "resources")) # Should have been uploaded per 'Additional Analysis Files' in PAT - characteristics_dir = File.absolute_path(File.join(File.dirname(__FILE__), "..", "..", "lib", "housing_characteristics")) # Should have been uploaded per 'Additional Analysis Files' in PAT - buildstock_file = File.join(resources_dir, "buildstock.rb") - measures_dir = File.join(resources_dir, "measures") - lookup_file = File.join(resources_dir, "options_lookup.tsv") - buildstock_csv = File.absolute_path(File.join(characteristics_dir, "buildstock.csv")) # Should have been generated by the Worker Initialization Script (run_sampling.rb) or provided by the project - if workflow_json.is_initialized - workflow_json = File.join(resources_dir, workflow_json.get) - else - workflow_json = nil - end - - # Load buildstock_file - require File.join(File.dirname(buildstock_file), File.basename(buildstock_file, File.extname(buildstock_file))) - - # Check file/dir paths exist - check_dir_exists(measures_dir, runner) - check_file_exists(lookup_file, runner) - check_file_exists(buildstock_csv, runner) - - # Retrieve all data associated with sample number - bldg_data = get_data_for_sample(buildstock_csv, building_id, runner) - - # Retrieve order of parameters to run - parameters_ordered = get_parameters_ordered_from_options_lookup_tsv(lookup_file, characteristics_dir) - - # Obtain measures and arguments to be called - measures = {} - parameters_ordered.each do |parameter_name| - # Get measure name and arguments associated with the option - option_name = bldg_data[parameter_name] - register_value(runner, parameter_name, option_name) - end - - # Do the downselecting - if downselect_logic.is_initialized - - downselect_logic = downselect_logic.get - downselect_logic = downselect_logic.strip - downselected = evaluate_logic(downselect_logic, runner, past_results = false) - - if downselected.nil? - return false - end - - unless downselected - # Not in downselection; don't run existing home simulation - runner.registerInfo("Sample is not in downselected parameters; will be registered as invalid.") - runner.haltWorkflow('Invalid') - return false - end - - end - - parameters_ordered.each do |parameter_name| - option_name = bldg_data[parameter_name] - print_option_assignment(parameter_name, option_name, runner) - options_measure_args = get_measure_args_from_option_names(lookup_file, [option_name], parameter_name, runner) - options_measure_args[option_name].each do |measure_subdir, args_hash| - update_args_hash(measures, measure_subdir, args_hash, add_new = false) - end - end - - # FIXME: Hack to run the correct ResStock geometry measure - if ["Single-Family Detached", "Mobile Home"].include? bldg_data["Geometry Building Type"] - measures.delete("ResidentialGeometryCreateSingleFamilyAttached") - measures.delete("ResidentialGeometryCreateMultifamily") - elsif bldg_data["Geometry Building Type"] == "Single-Family Attached" - measures.delete("ResidentialGeometryCreateSingleFamilyDetached") - measures.delete("ResidentialGeometryCreateMultifamily") - elsif ["Multi-Family with 2 - 4 Units", "Multi-Family with 5+ Units"].include? bldg_data["Geometry Building Type"] - measures.delete("ResidentialGeometryCreateSingleFamilyDetached") - measures.delete("ResidentialGeometryCreateSingleFamilyAttached") - end - - if not apply_measures(measures_dir, measures, runner, model, workflow_json, "measures.osw", true) - return false - end - - # Report some additional location and model characteristics - weather = WeatherProcess.new(model, runner) - if !weather.error? - register_value(runner, "location_city", weather.header.City) - register_value(runner, "location_state", weather.header.State) - register_value(runner, "location_latitude", "#{weather.header.Latitude}") - register_value(runner, "location_longitude", "#{weather.header.Longitude}") - climate_zone_ba = Location.get_climate_zone_ba(weather.header.Station) - climate_zone_iecc = Location.get_climate_zone_iecc(weather.header.Station) - unless climate_zone_ba.nil? - register_value(runner, "climate_zone_ba", climate_zone_ba) - end - unless climate_zone_iecc.nil? - register_value(runner, "climate_zone_iecc", climate_zone_iecc) - end - if climate_zone_ba.nil? and climate_zone_iecc.nil? - runner.registerInfo("The weather station WMO has not been set appropriately in the EPW weather file header.") - end - end - register_value(runner, "units_represented", "#{model.getBuilding.additionalProperties.getFeatureAsInteger("Total Units Represented").get}") - register_value(runner, "units_modeled", "#{model.getBuilding.additionalProperties.getFeatureAsInteger("Total Units Modeled").get}") - - # Determine weight - if number_of_buildings_represented.is_initialized - total_samples = nil - runner.analysis[:analysis][:problem][:workflow].each do |wf| - next if wf[:name] != 'build_existing_model' - - wf[:variables].each do |v| - next if v[:argument][:name] != 'building_id' - - total_samples = v[:maximum].to_f - end - end - if total_samples.nil? - runner.registerError("Could not retrieve value for number_of_buildings_represented.") - return false - end - weight = number_of_buildings_represented.get / total_samples - register_value(runner, "weight", weight.to_s) - end - - if sample_weight.is_initialized - register_value(runner, "weight", sample_weight.get.to_s) - end - - return true - end - - def get_data_for_sample(buildstock_csv, building_id, runner) - CSV.foreach(buildstock_csv, headers: true) do |sample| - next if sample["Building"].to_i != building_id - - return sample - end - # If we got this far, couldn't find the sample # - msg = "Could not find row for #{building_id.to_s} in #{File.basename(buildstock_csv).to_s}." - runner.registerError(msg) - fail msg - end -end - -# register the measure to be used by the application -BuildExistingModel.new.registerWithApplication diff --git a/buildstockbatch/test/test_inputs/test_openstudio_buildstock/measures/ReportingMeasure1/measure.rb b/buildstockbatch/test/test_inputs/test_openstudio_buildstock/measures/ReportingMeasure1/measure.rb deleted file mode 100644 index e69de29b..00000000 diff --git a/buildstockbatch/test/test_inputs/test_openstudio_buildstock/measures/ResidentialSimulationControls/measure.rb b/buildstockbatch/test/test_inputs/test_openstudio_buildstock/measures/ResidentialSimulationControls/measure.rb deleted file mode 100644 index d2078a21..00000000 --- a/buildstockbatch/test/test_inputs/test_openstudio_buildstock/measures/ResidentialSimulationControls/measure.rb +++ /dev/null @@ -1,148 +0,0 @@ -# insert your copyright here - -# see the URL below for information on how to write OpenStudio measures -# http://nrel.github.io/OpenStudio-user-documentation/reference/measure_writing_guide/ - -if File.exists? File.absolute_path(File.join(File.dirname(__FILE__), "../../lib/resources/measures/HPXMLtoOpenStudio/resources")) # Hack to run ResStock on AWS - resources_path = File.absolute_path(File.join(File.dirname(__FILE__), "../../lib/resources/measures/HPXMLtoOpenStudio/resources")) -elsif File.exists? File.absolute_path(File.join(File.dirname(__FILE__), "../../resources/measures/HPXMLtoOpenStudio/resources")) # Hack to run ResStock unit tests locally - resources_path = File.absolute_path(File.join(File.dirname(__FILE__), "../../resources/measures/HPXMLtoOpenStudio/resources")) -elsif File.exists? File.join(OpenStudio::BCLMeasure::userMeasuresDir.to_s, "HPXMLtoOpenStudio/resources") # Hack to run measures in the OS App since applied measures are copied off into a temporary directory - resources_path = File.join(OpenStudio::BCLMeasure::userMeasuresDir.to_s, "HPXMLtoOpenStudio/resources") -else - resources_path = File.absolute_path(File.join(File.dirname(__FILE__), "../HPXMLtoOpenStudio/resources")) -end -require File.join(resources_path, "constants") -require File.join(resources_path, "simulation") - -# start the measure -class ResidentialSimulationControls < OpenStudio::Measure::ModelMeasure - # human readable name - def name - # Measure name should be the title case of the class name. - return 'Set Residential Simulation Controls' - end - - # human readable description - def description - return 'Set the simulation timesteps per hour, the run period begin month/day and end month/day, and the calendar year (for start day of week).' - end - - # human readable description of modeling approach - def modeler_description - return 'Set the simulation timesteps per hour on the Timestep object, the run period begin month/day and end month/day on the RunPeriod object, and the calendar year on the YearDescription object.' - end - - # define the arguments that the user will input - def arguments(model) - args = OpenStudio::Measure::OSArgumentVector.new - - # make an argument for the simulation timesteps per hour - arg = OpenStudio::Measure::OSArgument::makeIntegerArgument("timesteps_per_hr", true) - arg.setDisplayName("Simulation Timesteps Per Hour") - arg.setDescription("The value entered here is the number of (zone) timesteps to use within an hour. For example a value of 6 entered here directs the program to use a zone timestep of 10 minutes and a value of 60 means a 1 minute timestep.") - arg.setDefaultValue(6) - args << arg - - # make an argument for the run period begin month - arg = OpenStudio::Measure::OSArgument::makeIntegerArgument("begin_month", true) - arg.setDisplayName("Run Period Begin Month") - arg.setDescription("This numeric field should contain the starting month number (1 = January, 2 = February, etc.) for the annual run period desired.") - arg.setDefaultValue(1) - args << arg - - # make an argument for the run period begin day of month - arg = OpenStudio::Measure::OSArgument::makeIntegerArgument("begin_day_of_month", true) - arg.setDisplayName("Run Period Begin Day of Month") - arg.setDescription("This numeric field should contain the starting day of the starting month (must be valid for month) for the annual run period desired.") - arg.setDefaultValue(1) - args << arg - - # make an argument for the run period end month - arg = OpenStudio::Measure::OSArgument::makeIntegerArgument("end_month", true) - arg.setDisplayName("Run Period End Month") - arg.setDescription("This numeric field should contain the ending month number (1 = January, 2 = February, etc.) for the annual run period desired.") - arg.setDefaultValue(12) - args << arg - - # make an argument for the run period end day of month - arg = OpenStudio::Measure::OSArgument::makeIntegerArgument("end_day_of_month", true) - arg.setDisplayName("Run Period End Day of Month") - arg.setDescription("This numeric field should contain the ending day of the ending month (must be valid for month) for the annual run period desired.") - arg.setDefaultValue(31) - args << arg - - # make an argument for the calendar year; this determines the day of week for start day - arg = OpenStudio::Measure::OSArgument::makeIntegerArgument("calendar_year", true) - arg.setDisplayName("Calendar Year") - arg.setDescription("This numeric field should contain the calendar year that determines the start day of week. If you are running simulations using AMY weather files, the value entered for calendar year will not be used; it will be overridden by the actual year found in the AMY weather file.") - arg.setDefaultValue(2007) - args << arg - - return args - end - - # define what happens when the measure is run - def run(model, runner, user_arguments) - super(model, runner, user_arguments) - - # use the built-in error checking - if !runner.validateUserArguments(arguments(model), user_arguments) - return false - end - - timesteps_per_hr = runner.getIntegerArgumentValue("timesteps_per_hr", user_arguments) - begin_month = runner.getIntegerArgumentValue("begin_month", user_arguments) - begin_day_of_month = runner.getIntegerArgumentValue("begin_day_of_month", user_arguments) - end_month = runner.getIntegerArgumentValue("end_month", user_arguments) - end_day_of_month = runner.getIntegerArgumentValue("end_day_of_month", user_arguments) - calendar_year = runner.getIntegerArgumentValue("calendar_year", user_arguments) - - # Error checking - if timesteps_per_hr < 1 or timesteps_per_hr > 60 - runner.registerError("User-entered #{timesteps_per_hr} timesteps per hour must be between 1 and 60.") - return false - end - - if 60 % timesteps_per_hr != 0 - runner.registerError("User-entered #{timesteps_per_hr} timesteps per hour does not divide evenly into 60.") - return false - end - - if not (1..12).to_a.include? begin_month or not (1..12).to_a.include? end_month - runner.registerError("Invalid begin month (#{begin_month}) and/or end month (#{end_month}) entered.") - return false - end - - { begin_month => begin_day_of_month, end_month => end_day_of_month }.each_with_index do |(month, day), i| - leap_day = 0 - leap_day += 1 if month == 2 # february - day_of_month_valid = (1..Constants.NumDaysInMonths[month - 1] + leap_day).to_a.include? day # accommodate leap day - unless day_of_month_valid - if i == 0 - runner.registerError("Invalid begin day of month (#{begin_day_of_month}) entered.") - elsif i == 1 - runner.registerError("Invalid end day of month (#{end_day_of_month}) entered.") - end - return false - end - end - - if calendar_year < 1600 or calendar_year > 9999 - runner.registerError("Your calendar year value of #{calendar_year} is not in the range 1600-9999.") - return false - end - - success = Simulation.apply(model, runner, timesteps_per_hr, min_system_timestep_mins = nil, begin_month, begin_day_of_month, end_month, end_day_of_month, calendar_year) - return false if not success - - runner.registerInfo("Set the simulation timesteps per hour to #{timesteps_per_hr}.") - runner.registerInfo("Set the run period begin and end month/day to #{begin_month}/#{begin_day_of_month} and #{end_month}/#{end_day_of_month}, respectively.") - runner.registerInfo("Set the calendar year to #{model.getYearDescription.calendarYear} and the start day of week to #{model.getYearDescription.dayofWeekforStartDay}; if you are running with AMY, this will be overridden by the AMY year.") - - return true - end -end - -# register the measure to be used by the application -ResidentialSimulationControls.new.registerWithApplication diff --git a/buildstockbatch/test/test_inputs/test_openstudio_buildstock/measures/ServerDirectoryCleanup/measure.rb b/buildstockbatch/test/test_inputs/test_openstudio_buildstock/measures/ServerDirectoryCleanup/measure.rb deleted file mode 100644 index 087f101e..00000000 --- a/buildstockbatch/test/test_inputs/test_openstudio_buildstock/measures/ServerDirectoryCleanup/measure.rb +++ /dev/null @@ -1,83 +0,0 @@ -# start the measure -class ServerDirectoryCleanup < OpenStudio::Measure::ReportingMeasure - # define the name that a user will see, this method may be deprecated as - # the display name in PAT comes from the name field in measure.xml - def name - "Server Directory Cleanup" - end - - # define the arguments that the user will input - def arguments() - args = OpenStudio::Ruleset::OSArgumentVector.new - end # end the arguments method - - # define what happens when the measure is run - def run(runner, user_arguments) - super(runner, user_arguments) - - # use the built-in error checking - unless runner.validateUserArguments(arguments, user_arguments) - false - end - - initial_string = "The following files were in the local run directory prior to the execution of this measure: " - Dir.entries("./../").each do |f| - initial_string << "#{f}, " - end - initial_string = initial_string[0..(initial_string.length - 3)] + "." - runner.registerInitialCondition(initial_string) - - Dir.glob("./../*.sql").each do |f| - File.delete(f) - runner.registerInfo("Deleted #{f} from the run directory.") if !File.exist?(f) - end - Dir.glob("./../*.audit").each do |f| - File.delete(f) - runner.registerInfo("Deleted #{f} from the run directory.") if !File.exist?(f) - end - Dir.glob("./../in.osm").each do |f| - File.delete(f) - runner.registerInfo("Deleted #{f} from the run directory.") if !File.exist?(f) - end - Dir.glob("./../../in.osm").each do |f| - File.delete(f) - runner.registerInfo("Deleted #{f} from the run directory.") if !File.exist?(f) - end - Dir.glob("./../*.bnd").each do |f| - File.delete(f) - runner.registerInfo("Deleted #{f} from the run directory.") if !File.exist?(f) - end - Dir.glob("./../*.eio").each do |f| - File.delete(f) - runner.registerInfo("Deleted #{f} from the run directory.") if !File.exist?(f) - end - Dir.glob("./../*.shd").each do |f| - File.delete(f) - runner.registerInfo("Deleted #{f} from the run directory.") if !File.exist?(f) - end - Dir.glob("./../*.mdd").each do |f| - File.delete(f) - runner.registerInfo("Deleted #{f} from the run directory.") if !File.exist?(f) - end - Dir.glob("./../*.eso").each do |f| - File.delete(f) - runner.registerInfo("Deleted #{f} from the run directory.") if !File.exist?(f) - end - Dir.glob("./../pre-preprocess.idf").each do |f| - File.delete(f) - runner.registerInfo("Deleted #{f} from the run directory.") if !File.exist?(f) - end - - final_string = "The following files were in the local run directory following the execution of this measure: " - Dir.entries("./..").each do |f| - final_string << "#{f}, " - end - final_string = final_string[0..(final_string.length - 3)] + "." - runner.registerFinalCondition(final_string) - - true - end # end the run method -end # end the measure - -# this allows the measure to be use by the application -ServerDirectoryCleanup.new.registerWithApplication diff --git a/buildstockbatch/test/test_inputs/test_openstudio_buildstock/measures/SimulationOutputReport/measure.rb b/buildstockbatch/test/test_inputs/test_openstudio_buildstock/measures/SimulationOutputReport/measure.rb deleted file mode 100644 index 7a5140e8..00000000 --- a/buildstockbatch/test/test_inputs/test_openstudio_buildstock/measures/SimulationOutputReport/measure.rb +++ /dev/null @@ -1,1115 +0,0 @@ -require 'openstudio' -if File.exists? File.absolute_path(File.join(File.dirname(__FILE__), "../../lib/resources/measures/HPXMLtoOpenStudio/resources")) # Hack to run ResStock on AWS - resources_path = File.absolute_path(File.join(File.dirname(__FILE__), "../../lib/resources/measures/HPXMLtoOpenStudio/resources")) -elsif File.exists? File.absolute_path(File.join(File.dirname(__FILE__), "../../resources/measures/HPXMLtoOpenStudio/resources")) # Hack to run ResStock unit tests locally - resources_path = File.absolute_path(File.join(File.dirname(__FILE__), "../../resources/measures/HPXMLtoOpenStudio/resources")) -elsif File.exists? File.join(OpenStudio::BCLMeasure::userMeasuresDir.to_s, "HPXMLtoOpenStudio/resources") # Hack to run measures in the OS App since applied measures are copied off into a temporary directory - resources_path = File.join(OpenStudio::BCLMeasure::userMeasuresDir.to_s, "HPXMLtoOpenStudio/resources") -else - resources_path = File.absolute_path(File.join(File.dirname(__FILE__), "../HPXMLtoOpenStudio/resources")) -end -require File.join(resources_path, "unit_conversions") -require File.join(resources_path, "waterheater") - -# start the measure -class SimulationOutputReport < OpenStudio::Measure::ReportingMeasure - # define the name that a user will see, this method may be deprecated as - # the display name in PAT comes from the name field in measure.xml - def name - return "Simulation Output Report" - end - - def description - return "Reports simulation outputs of interest." - end - - def num_options - return Constants.NumApplyUpgradeOptions # Synced with SimulationOutputReport measure - end - - def num_costs_per_option - return Constants.NumApplyUpgradesCostsPerOption # Synced with SimulationOutputReport measure - end - - # define the arguments that the user will input - def arguments - args = OpenStudio::Ruleset::OSArgumentVector.new - - return args - end # end the arguments method - - # return a vector of IdfObject's to request EnergyPlus objects needed by the run method - def energyPlusOutputRequests(runner, user_arguments) - super(runner, user_arguments) - - return OpenStudio::IdfObjectVector.new if runner.halted - - # get the last model and sql file - model = runner.lastOpenStudioModel - if model.empty? - runner.registerError("Cannot find last model.") - return false - end - model = model.get - - results = OutputMeters.create_custom_building_unit_meters(model, runner, "RunPeriod") - return results - end - - def outputs - buildstock_outputs = [ - "total_site_energy_mbtu", - "total_site_electricity_kwh", - "total_site_natural_gas_therm", - "total_site_fuel_oil_mbtu", - "total_site_propane_mbtu", - "net_site_energy_mbtu", # Incorporates PV - "net_site_electricity_kwh", # Incorporates PV - "electricity_heating_kwh", - "electricity_central_system_heating_kwh", - "electricity_cooling_kwh", - "electricity_central_system_cooling_kwh", - "electricity_interior_lighting_kwh", - "electricity_exterior_lighting_kwh", - "electricity_interior_equipment_kwh", - "electricity_fans_heating_kwh", - "electricity_fans_cooling_kwh", - "electricity_pumps_heating_kwh", - "electricity_central_system_pumps_heating_kwh", - "electricity_pumps_cooling_kwh", - "electricity_central_system_pumps_cooling_kwh", - "electricity_water_systems_kwh", - "electricity_pv_kwh", - "natural_gas_heating_therm", - "natural_gas_central_system_heating_therm", - "natural_gas_interior_equipment_therm", - "natural_gas_water_systems_therm", - "fuel_oil_heating_mbtu", - "fuel_oil_central_system_heating_mbtu", - "fuel_oil_interior_equipment_mbtu", - "fuel_oil_water_systems_mbtu", - "propane_heating_mbtu", - "propane_central_system_heating_mbtu", - "propane_interior_equipment_mbtu", - "propane_water_systems_mbtu", - "hours_heating_setpoint_not_met", - "hours_cooling_setpoint_not_met", - "hvac_cooling_capacity_w", - "hvac_heating_capacity_w", - "hvac_heating_supp_capacity_w", - "upgrade_name", - "upgrade_cost_usd" - ] - for option_num in 1..num_options - buildstock_outputs << "upgrade_option_%02d_cost_usd" % option_num - buildstock_outputs << "upgrade_option_%02d_lifetime_yrs" % option_num - end - buildstock_outputs << "weight" - - result = OpenStudio::Measure::OSOutputVector.new - buildstock_outputs.each do |output| - result << OpenStudio::Measure::OSOutput.makeDoubleOutput(output) - end - return result - end - - # define what happens when the measure is run - def run(runner, user_arguments) - super(runner, user_arguments) - - # use the built-in error checking - if not runner.validateUserArguments(arguments(), user_arguments) - return false - end - - # get the last model and sql file - model = runner.lastOpenStudioModel - if model.empty? - runner.registerError("Cannot find last model.") - return false - end - model = model.get - - sqlFile = runner.lastEnergyPlusSqlFile - if sqlFile.empty? - runner.registerError("Cannot find last sql file.") - return false - end - sqlFile = sqlFile.get - model.setSqlFile(sqlFile) - - ann_env_pd = nil - sqlFile.availableEnvPeriods.each do |env_pd| - env_type = sqlFile.environmentType(env_pd) - if env_type.is_initialized - if env_type.get == OpenStudio::EnvironmentType.new("WeatherRunPeriod") - ann_env_pd = env_pd - end - end - end - if ann_env_pd == false - runner.registerError("Can't find a weather runperiod, make sure you ran an annual simulation, not just the design days.") - return false - end - - env_period_ix_query = "SELECT EnvironmentPeriodIndex FROM EnvironmentPeriods WHERE EnvironmentName='#{ann_env_pd}'" - env_period_ix = sqlFile.execAndReturnFirstInt(env_period_ix_query).get - - # Load buildstock_file - resources_dir = File.absolute_path(File.join(File.dirname(__FILE__), "..", "..", "lib", "resources")) # Should have been uploaded per 'Other Library Files' in analysis spreadsheet - buildstock_file = File.join(resources_dir, "buildstock.rb") - require File.join(File.dirname(buildstock_file), File.basename(buildstock_file, File.extname(buildstock_file))) - - total_site_units = "MBtu" - elec_site_units = "kWh" - gas_site_units = "therm" - other_fuel_site_units = "MBtu" - - # Get meters that aren't tied to units (i.e., are metered at the building level) - modeledCentralElectricityHeating = 0.0 - modeledCentralElectricityCooling = 0.0 - modeledCentralElectricityExteriorLighting = 0.0 - modeledCentralElectricityExteriorHolidayLighting = 0.0 - modeledCentralElectricityPumpsHeating = 0.0 - modeledCentralElectricityPumpsCooling = 0.0 - modeledCentralElectricityInteriorEquipment = 0.0 - modeledCentralNaturalGasHeating = 0.0 - modeledCentralNaturalGasInteriorEquipment = 0.0 - modeledCentralFuelOilHeating = 0.0 - modeledCentralFuelOilInteriorEquipment = 0.0 - modeledCentralPropaneHeating = 0.0 - modeledCentralPropaneInteriorEquipment = 0.0 - - central_electricity_heating_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('CENTRAL:ELECTRICITYHEATING') AND ReportingFrequency='Run Period' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" - unless sqlFile.execAndReturnFirstDouble(central_electricity_heating_query).empty? - modeledCentralElectricityHeating = sqlFile.execAndReturnFirstDouble(central_electricity_heating_query).get.round(2) - end - - central_electricity_cooling_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('CENTRAL:ELECTRICITYCOOLING') AND ReportingFrequency='Run Period' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" - unless sqlFile.execAndReturnFirstDouble(central_electricity_cooling_query).empty? - modeledCentralElectricityCooling = sqlFile.execAndReturnFirstDouble(central_electricity_cooling_query).get.round(2) - end - - central_electricity_exterior_lighting_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('CENTRAL:ELECTRICITYEXTERIORLIGHTING') AND ReportingFrequency='Run Period' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" - unless sqlFile.execAndReturnFirstDouble(central_electricity_exterior_lighting_query).empty? - modeledCentralElectricityExteriorLighting = sqlFile.execAndReturnFirstDouble(central_electricity_exterior_lighting_query).get.round(2) - end - - central_electricity_exterior_holiday_lighting_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('CENTRAL:ELECTRICITYEXTERIORHOLIDAYLIGHTING') AND ReportingFrequency='Run Period' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" - unless sqlFile.execAndReturnFirstDouble(central_electricity_exterior_holiday_lighting_query).empty? - modeledCentralElectricityExteriorHolidayLighting = sqlFile.execAndReturnFirstDouble(central_electricity_exterior_holiday_lighting_query).get.round(2) - end - - central_electricity_pumps_heating_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('CENTRAL:ELECTRICITYPUMPSHEATING') AND ReportingFrequency='Run Period' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" - unless sqlFile.execAndReturnFirstDouble(central_electricity_pumps_heating_query).empty? - modeledCentralElectricityPumpsHeating = sqlFile.execAndReturnFirstDouble(central_electricity_pumps_heating_query).get.round(2) - end - - central_electricity_pumps_cooling_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('CENTRAL:ELECTRICITYPUMPSCOOLING') AND ReportingFrequency='Run Period' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" - unless sqlFile.execAndReturnFirstDouble(central_electricity_pumps_cooling_query).empty? - modeledCentralElectricityPumpsCooling = sqlFile.execAndReturnFirstDouble(central_electricity_pumps_cooling_query).get.round(2) - end - - central_electricity_interior_equipment_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('CENTRAL:ELECTRICITYINTERIOREQUIPMENT') AND ReportingFrequency='Run Period' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" - unless sqlFile.execAndReturnFirstDouble(central_electricity_interior_equipment_query).empty? - modeledCentralElectricityInteriorEquipment = sqlFile.execAndReturnFirstDouble(central_electricity_interior_equipment_query).get.round(2) - end - - central_natural_gas_heating_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('CENTRAL:NATURALGASHEATING') AND ReportingFrequency='Run Period' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" - unless sqlFile.execAndReturnFirstDouble(central_natural_gas_heating_query).empty? - modeledCentralNaturalGasHeating = sqlFile.execAndReturnFirstDouble(central_natural_gas_heating_query).get.round(2) - end - - central_natural_gas_interior_equipment_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('CENTRAL:NATURALGASINTERIOREQUIPMENT') AND ReportingFrequency='Run Period' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" - unless sqlFile.execAndReturnFirstDouble(central_natural_gas_interior_equipment_query).empty? - modeledCentralNaturalGasInteriorEquipment = sqlFile.execAndReturnFirstDouble(central_natural_gas_interior_equipment_query).get.round(2) - end - - central_fuel_oil_heating_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('CENTRAL:FUELOILHEATING') AND ReportingFrequency='Run Period' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" - unless sqlFile.execAndReturnFirstDouble(central_fuel_oil_heating_query).empty? - modeledCentralFuelOilHeating = sqlFile.execAndReturnFirstDouble(central_fuel_oil_heating_query).get.round(2) - end - - central_fuel_oil_interior_equipment_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('CENTRAL:FUELOILINTERIOREQUIPMENT') AND ReportingFrequency='Run Period' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" - unless sqlFile.execAndReturnFirstDouble(central_fuel_oil_interior_equipment_query).empty? - modeledCentralFuelOilInteriorEquipment = sqlFile.execAndReturnFirstDouble(central_fuel_oil_interior_equipment_query).get.round(2) - end - - central_propane_heating_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('CENTRAL:PROPANEHEATING') AND ReportingFrequency='Run Period' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" - unless sqlFile.execAndReturnFirstDouble(central_propane_heating_query).empty? - modeledCentralPropaneHeating = sqlFile.execAndReturnFirstDouble(central_propane_heating_query).get.round(2) - end - - central_propane_interior_equipment_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('CENTRAL:PROPANEINTERIOREQUIPMENT') AND ReportingFrequency='Run Period' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" - unless sqlFile.execAndReturnFirstDouble(central_propane_interior_equipment_query).empty? - modeledCentralPropaneInteriorEquipment = sqlFile.execAndReturnFirstDouble(central_propane_interior_equipment_query).get.round(2) - end - - # Initialize variables to check against sql file totals - modeledElectricityFansHeating = 0.0 - modeledElectricityFansCooling = 0.0 - modeledElectricityPumpsHeating = modeledCentralElectricityPumpsHeating - modeledElectricityPumpsCooling = modeledCentralElectricityPumpsCooling - - # Separate these from non central systems - centralElectricityHeating = 0.0 - centralElectricityCooling = 0.0 - centralElectricityPumpsHeating = 0.0 - centralElectricityPumpsCooling = 0.0 - centralNaturalGasHeating = 0.0 - centralFuelOilHeating = 0.0 - centralPropaneHeating = 0.0 - - # Get meters that are tied to units, and apportion building level meters to these - electricityTotalEndUses = 0.0 - electricityHeating = 0.0 - electricityCooling = 0.0 - electricityInteriorLighting = 0.0 - electricityExteriorLighting = 0.0 - electricityExteriorHolidayLighting = modeledCentralElectricityExteriorHolidayLighting - electricityInteriorEquipment = 0.0 - electricityFansHeating = 0.0 - electricityFansCooling = 0.0 - electricityPumpsHeating = 0.0 - electricityPumpsCooling = 0.0 - electricityWaterSystems = 0.0 - naturalGasTotalEndUses = 0.0 - naturalGasHeating = 0.0 - naturalGasInteriorEquipment = 0.0 - naturalGasWaterSystems = 0.0 - fuelOilTotalEndUses = 0.0 - fuelOilHeating = 0.0 - fuelOilInteriorEquipment = 0.0 - fuelOilWaterSystems = 0.0 - propaneTotalEndUses = 0.0 - propaneHeating = 0.0 - propaneInteriorEquipment = 0.0 - propaneWaterSystems = 0.0 - hoursHeatingSetpointNotMet = 0.0 - hoursCoolingSetpointNotMet = 0.0 - - # Get building units - units = Geometry.get_building_units(model, runner) - if units.nil? - return false - end - - total_units_represented = 0 - units.each do |unit| - unit_name = unit.name.to_s.upcase - - thermal_zones = [] - unit.spaces.each do |space| - thermal_zone = space.thermalZone.get - unless thermal_zones.include? thermal_zone - thermal_zones << thermal_zone - end - end - - units_represented = 1 - if unit.additionalProperties.getFeatureAsInteger("Units Represented").is_initialized - units_represented = unit.additionalProperties.getFeatureAsInteger("Units Represented").get - end - total_units_represented += units_represented - - electricity_heating_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:ELECTRICITYHEATING') AND ReportingFrequency='Run Period' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" - unless sqlFile.execAndReturnFirstDouble(electricity_heating_query).empty? - electricityHeating += units_represented * sqlFile.execAndReturnFirstDouble(electricity_heating_query).get.round(2) - end - - centralElectricityHeating += units_represented * (modeledCentralElectricityHeating / units.length) - - electricity_cooling_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:ELECTRICITYCOOLING') AND ReportingFrequency='Run Period' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" - unless sqlFile.execAndReturnFirstDouble(electricity_cooling_query).empty? - electricityCooling += units_represented * sqlFile.execAndReturnFirstDouble(electricity_cooling_query).get.round(2) - end - - centralElectricityCooling += units_represented * (modeledCentralElectricityCooling / units.length) - - electricity_interior_lighting_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:ELECTRICITYINTERIORLIGHTING') AND ReportingFrequency='Run Period' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" - unless sqlFile.execAndReturnFirstDouble(electricity_interior_lighting_query).empty? - electricityInteriorLighting += units_represented * sqlFile.execAndReturnFirstDouble(electricity_interior_lighting_query).get.round(2) - end - - electricityExteriorLighting += units_represented * (modeledCentralElectricityExteriorLighting / units.length) - - electricity_interior_equipment_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:ELECTRICITYINTERIOREQUIPMENT') AND ReportingFrequency='Run Period' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" - unless sqlFile.execAndReturnFirstDouble(electricity_interior_equipment_query).empty? - electricityInteriorEquipment += units_represented * sqlFile.execAndReturnFirstDouble(electricity_interior_equipment_query).get.round(2) - end - electricityInteriorEquipment += units_represented * (modeledCentralElectricityInteriorEquipment / units.length) - - electricity_fans_heating_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:ELECTRICITYFANSHEATING') AND ReportingFrequency='Run Period' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" - unless sqlFile.execAndReturnFirstDouble(electricity_fans_heating_query).empty? - electricityFansHeating += units_represented * sqlFile.execAndReturnFirstDouble(electricity_fans_heating_query).get.round(2) - modeledElectricityFansHeating += sqlFile.execAndReturnFirstDouble(electricity_fans_heating_query).get.round(2) - end - - electricity_fans_cooling_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:ELECTRICITYFANSCOOLING') AND ReportingFrequency='Run Period' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" - unless sqlFile.execAndReturnFirstDouble(electricity_fans_cooling_query).empty? - electricityFansCooling += units_represented * sqlFile.execAndReturnFirstDouble(electricity_fans_cooling_query).get.round(2) - modeledElectricityFansCooling += sqlFile.execAndReturnFirstDouble(electricity_fans_cooling_query).get.round(2) - end - - electricity_pumps_heating_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:ELECTRICITYPUMPSHEATING') AND ReportingFrequency='Run Period' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" - unless sqlFile.execAndReturnFirstDouble(electricity_pumps_heating_query).empty? - electricityPumpsHeating += units_represented * sqlFile.execAndReturnFirstDouble(electricity_pumps_heating_query).get.round(2) - modeledElectricityPumpsHeating += sqlFile.execAndReturnFirstDouble(electricity_pumps_heating_query).get.round(2) - end - - centralElectricityPumpsHeating += units_represented * (modeledCentralElectricityPumpsHeating / units.length) - - electricity_pumps_cooling_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:ELECTRICITYPUMPSCOOLING') AND ReportingFrequency='Run Period' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" - unless sqlFile.execAndReturnFirstDouble(electricity_pumps_cooling_query).empty? - electricityPumpsCooling += units_represented * sqlFile.execAndReturnFirstDouble(electricity_pumps_cooling_query).get.round(2) - modeledElectricityPumpsCooling += sqlFile.execAndReturnFirstDouble(electricity_pumps_cooling_query).get.round(2) - end - - centralElectricityPumpsCooling += units_represented * (modeledCentralElectricityPumpsCooling / units.length) - - electricity_water_systems_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:ELECTRICITYWATERSYSTEMS') AND ReportingFrequency='Run Period' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" - unless sqlFile.execAndReturnFirstDouble(electricity_water_systems_query).empty? - electricityWaterSystems += units_represented * sqlFile.execAndReturnFirstDouble(electricity_water_systems_query).get.round(2) - end - - natural_gas_heating_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:NATURALGASHEATING') AND ReportingFrequency='Run Period' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" - unless sqlFile.execAndReturnFirstDouble(natural_gas_heating_query).empty? - naturalGasHeating += units_represented * sqlFile.execAndReturnFirstDouble(natural_gas_heating_query).get.round(2) - end - - centralNaturalGasHeating += units_represented * (modeledCentralNaturalGasHeating / units.length) - - natural_gas_interior_equipment_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:NATURALGASINTERIOREQUIPMENT') AND ReportingFrequency='Run Period' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" - unless sqlFile.execAndReturnFirstDouble(natural_gas_interior_equipment_query).empty? - naturalGasInteriorEquipment += units_represented * sqlFile.execAndReturnFirstDouble(natural_gas_interior_equipment_query).get.round(2) - end - naturalGasInteriorEquipment += units_represented * (modeledCentralNaturalGasInteriorEquipment / units.length) - - natural_gas_water_systems_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:NATURALGASWATERSYSTEMS') AND ReportingFrequency='Run Period' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" - unless sqlFile.execAndReturnFirstDouble(natural_gas_water_systems_query).empty? - naturalGasWaterSystems += units_represented * sqlFile.execAndReturnFirstDouble(natural_gas_water_systems_query).get.round(2) - end - - fuel_oil_heating_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:FUELOILHEATING') AND ReportingFrequency='Run Period' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" - unless sqlFile.execAndReturnFirstDouble(fuel_oil_heating_query).empty? - fuelOilHeating += units_represented * sqlFile.execAndReturnFirstDouble(fuel_oil_heating_query).get.round(2) - end - - centralFuelOilHeating += units_represented * (modeledCentralFuelOilHeating / units.length) - - fuel_oil_interior_equipment_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:FUELOILINTERIOREQUIPMENT') AND ReportingFrequency='Run Period' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" - unless sqlFile.execAndReturnFirstDouble(fuel_oil_interior_equipment_query).empty? - fuelOilInteriorEquipment += units_represented * sqlFile.execAndReturnFirstDouble(fuel_oil_interior_equipment_query).get.round(2) - end - fuelOilInteriorEquipment += units_represented * (modeledCentralFuelOilInteriorEquipment / units.length) - - fuel_oil_water_systems_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:FUELOILWATERSYSTEMS') AND ReportingFrequency='Run Period' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" - unless sqlFile.execAndReturnFirstDouble(fuel_oil_water_systems_query).empty? - fuelOilWaterSystems += units_represented * sqlFile.execAndReturnFirstDouble(fuel_oil_water_systems_query).get.round(2) - end - - propane_heating_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:PROPANEHEATING') AND ReportingFrequency='Run Period' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" - unless sqlFile.execAndReturnFirstDouble(propane_heating_query).empty? - propaneHeating += units_represented * sqlFile.execAndReturnFirstDouble(propane_heating_query).get.round(2) - end - - centralPropaneHeating += units_represented * (modeledCentralPropaneHeating / units.length) - - propane_interior_equipment_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:PROPANEINTERIOREQUIPMENT') AND ReportingFrequency='Run Period' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" - unless sqlFile.execAndReturnFirstDouble(propane_interior_equipment_query).empty? - propaneInteriorEquipment += units_represented * sqlFile.execAndReturnFirstDouble(propane_interior_equipment_query).get.round(2) - end - propaneInteriorEquipment += units_represented * (modeledCentralPropaneInteriorEquipment / units.length) - - propane_water_systems_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:PROPANEWATERSYSTEMS') AND ReportingFrequency='Run Period' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" - unless sqlFile.execAndReturnFirstDouble(propane_water_systems_query).empty? - propaneWaterSystems += units_represented * sqlFile.execAndReturnFirstDouble(propane_water_systems_query).get.round(2) - end - - thermal_zones.each do |thermal_zone| - thermal_zone_name = thermal_zone.name.to_s.upcase - hours_heating_setpoint_not_met_query = "SELECT Value FROM TabularDataWithStrings WHERE (ReportName='SystemSummary') AND (ReportForString='Entire Facility') AND (TableName='Time Setpoint Not Met') AND (RowName = '#{thermal_zone_name}') AND (ColumnName='During Heating') AND (Units = 'hr')" - unless sqlFile.execAndReturnFirstDouble(hours_heating_setpoint_not_met_query).empty? - hoursHeatingSetpointNotMet += units_represented * sqlFile.execAndReturnFirstDouble(hours_heating_setpoint_not_met_query).get - end - - hours_cooling_setpoint_not_met_query = "SELECT Value FROM TabularDataWithStrings WHERE (ReportName='SystemSummary') AND (ReportForString='Entire Facility') AND (TableName='Time Setpoint Not Met') AND (RowName = '#{thermal_zone_name}') AND (ColumnName='During Cooling') AND (Units = 'hr')" - unless sqlFile.execAndReturnFirstDouble(hours_cooling_setpoint_not_met_query).empty? - hoursCoolingSetpointNotMet += units_represented * sqlFile.execAndReturnFirstDouble(hours_cooling_setpoint_not_met_query).get - end - end - end - - # ELECTRICITY - - # Get PV electricity produced - pv_query = "SELECT -1*Value FROM TabularDataWithStrings WHERE ReportName='AnnualBuildingUtilityPerformanceSummary' AND ReportForString='Entire Facility' AND TableName='Electric Loads Satisfied' AND RowName='Total On-Site Electric Sources' AND ColumnName='Electricity' AND Units='GJ'" - pv_val = 0.0 - unless sqlFile.execAndReturnFirstDouble(pv_query).empty? - pv_val = sqlFile.execAndReturnFirstDouble(pv_query).get - end - report_sim_output(runner, "electricity_pv_kwh", pv_val, "GJ", elec_site_units) - - electricityTotalEndUses = electricityHeating + centralElectricityHeating + electricityCooling + centralElectricityCooling + electricityInteriorLighting + electricityExteriorLighting + electricityExteriorHolidayLighting + electricityInteriorEquipment + electricityFansHeating + electricityFansCooling + electricityPumpsHeating + centralElectricityPumpsHeating + electricityPumpsCooling + centralElectricityPumpsCooling + electricityWaterSystems - - report_sim_output(runner, "total_site_electricity_kwh", electricityTotalEndUses, "GJ", elec_site_units) - report_sim_output(runner, "net_site_electricity_kwh", electricityTotalEndUses + pv_val, "GJ", elec_site_units) - report_sim_output(runner, "electricity_heating_kwh", electricityHeating, "GJ", elec_site_units) - report_sim_output(runner, "electricity_central_system_heating_kwh", centralElectricityHeating, "GJ", elec_site_units) - report_sim_output(runner, "electricity_cooling_kwh", electricityCooling, "GJ", elec_site_units) - report_sim_output(runner, "electricity_central_system_cooling_kwh", centralElectricityCooling, "GJ", elec_site_units) - report_sim_output(runner, "electricity_interior_lighting_kwh", electricityInteriorLighting, "GJ", elec_site_units) - report_sim_output(runner, "electricity_exterior_lighting_kwh", electricityExteriorLighting + electricityExteriorHolidayLighting, "GJ", elec_site_units) - report_sim_output(runner, "electricity_interior_equipment_kwh", electricityInteriorEquipment, "GJ", elec_site_units) - electricityFans = 0.0 - unless sqlFile.electricityFans.empty? - electricityFans = sqlFile.electricityFans.get - end - err = (modeledElectricityFansHeating + modeledElectricityFansCooling) - electricityFans - if err.abs > 0.2 - runner.registerError("Disaggregated fan energy (#{modeledElectricityFansHeating + modeledElectricityFansCooling} GJ) relative to building fan energy (#{electricityFans} GJ): #{err} GJ.") - return false - end - report_sim_output(runner, "electricity_fans_heating_kwh", electricityFansHeating, "GJ", elec_site_units) - report_sim_output(runner, "electricity_fans_cooling_kwh", electricityFansCooling, "GJ", elec_site_units) - electricityPumps = 0.0 - unless sqlFile.electricityPumps.empty? - electricityPumps = sqlFile.electricityPumps.get - end - err = (modeledElectricityPumpsHeating + modeledElectricityPumpsCooling) - electricityPumps - if err.abs > 0.2 - runner.registerError("Disaggregated pump energy (#{modeledElectricityPumpsHeating + modeledElectricityPumpsCooling} GJ) relative to building pump energy (#{electricityPumps} GJ): #{err} GJ.") - return false - end - report_sim_output(runner, "electricity_pumps_heating_kwh", electricityPumpsHeating, "GJ", elec_site_units) - report_sim_output(runner, "electricity_central_system_pumps_heating_kwh", centralElectricityPumpsHeating, "GJ", elec_site_units) - report_sim_output(runner, "electricity_pumps_cooling_kwh", electricityPumpsCooling, "GJ", elec_site_units) - report_sim_output(runner, "electricity_central_system_pumps_cooling_kwh", centralElectricityPumpsCooling, "GJ", elec_site_units) - report_sim_output(runner, "electricity_water_systems_kwh", electricityWaterSystems, "GJ", elec_site_units) - - # NATURAL GAS - - naturalGasTotalEndUses = naturalGasHeating + centralNaturalGasHeating + naturalGasInteriorEquipment + naturalGasWaterSystems - - report_sim_output(runner, "total_site_natural_gas_therm", naturalGasTotalEndUses, "GJ", gas_site_units) - report_sim_output(runner, "natural_gas_heating_therm", naturalGasHeating, "GJ", gas_site_units) - report_sim_output(runner, "natural_gas_central_system_heating_therm", centralNaturalGasHeating, "GJ", gas_site_units) - report_sim_output(runner, "natural_gas_interior_equipment_therm", naturalGasInteriorEquipment, "GJ", gas_site_units) - report_sim_output(runner, "natural_gas_water_systems_therm", naturalGasWaterSystems, "GJ", gas_site_units) - - # FUEL OIL - - fuelOilTotalEndUses = fuelOilHeating + centralFuelOilHeating + fuelOilInteriorEquipment + fuelOilWaterSystems - - report_sim_output(runner, "total_site_fuel_oil_mbtu", fuelOilTotalEndUses, "GJ", other_fuel_site_units) - report_sim_output(runner, "fuel_oil_heating_mbtu", fuelOilHeating, "GJ", other_fuel_site_units) - report_sim_output(runner, "fuel_oil_central_system_heating_mbtu", centralFuelOilHeating, "GJ", other_fuel_site_units) - report_sim_output(runner, "fuel_oil_interior_equipment_mbtu", fuelOilInteriorEquipment, "GJ", other_fuel_site_units) - report_sim_output(runner, "fuel_oil_water_systems_mbtu", fuelOilWaterSystems, "GJ", other_fuel_site_units) - - # PROPANE - - propaneTotalEndUses = propaneHeating + centralPropaneHeating + propaneInteriorEquipment + propaneWaterSystems - - report_sim_output(runner, "total_site_propane_mbtu", propaneTotalEndUses, "GJ", other_fuel_site_units) - report_sim_output(runner, "propane_heating_mbtu", propaneHeating, "GJ", other_fuel_site_units) - report_sim_output(runner, "propane_central_system_heating_mbtu", centralPropaneHeating, "GJ", other_fuel_site_units) - report_sim_output(runner, "propane_interior_equipment_mbtu", propaneInteriorEquipment, "GJ", other_fuel_site_units) - report_sim_output(runner, "propane_water_systems_mbtu", propaneWaterSystems, "GJ", other_fuel_site_units) - - # TOTAL - - totalSiteEnergy = electricityTotalEndUses + naturalGasTotalEndUses + fuelOilTotalEndUses + propaneTotalEndUses - - if units.length == total_units_represented - err = totalSiteEnergy - sqlFile.totalSiteEnergy.get - if err.abs > 0.5 - runner.registerError("Disaggregated total site energy (#{totalSiteEnergy} GJ) relative to building total site energy (#{sqlFile.totalSiteEnergy.get} GJ): #{err} GJ.") - return false - end - end - report_sim_output(runner, "total_site_energy_mbtu", totalSiteEnergy, "GJ", total_site_units) - report_sim_output(runner, "net_site_energy_mbtu", totalSiteEnergy + pv_val, "GJ", total_site_units) - - # LOADS NOT MET - - report_sim_output(runner, "hours_heating_setpoint_not_met", hoursHeatingSetpointNotMet, nil, nil) - report_sim_output(runner, "hours_cooling_setpoint_not_met", hoursCoolingSetpointNotMet, nil, nil) - - # HVAC CAPACITIES - - conditioned_zones = get_conditioned_zones(model) - hvac_cooling_capacity_kbtuh = get_cost_multiplier("Size, Cooling System (kBtu/h)", model, runner, conditioned_zones) - return false if hvac_cooling_capacity_kbtuh.nil? - - report_sim_output(runner, "hvac_cooling_capacity_w", hvac_cooling_capacity_kbtuh, "kBtu/hr", "W") - hvac_heating_capacity_kbtuh = get_cost_multiplier("Size, Heating System (kBtu/h)", model, runner, conditioned_zones) - return false if hvac_heating_capacity_kbtuh.nil? - - report_sim_output(runner, "hvac_heating_capacity_w", hvac_heating_capacity_kbtuh, "kBtu/hr", "W") - hvac_heating_supp_capacity_kbtuh = get_cost_multiplier("Size, Heating Supplemental System (kBtu/h)", model, runner, conditioned_zones) - return false if hvac_heating_supp_capacity_kbtuh.nil? - - report_sim_output(runner, "hvac_heating_supp_capacity_w", hvac_heating_supp_capacity_kbtuh, "kBtu/hr", "W") - - sqlFile.close() - - # WEIGHT - - weight = get_value_from_runner_past_results(runner, "weight", "build_existing_model", false) - if not weight.nil? - runner.registerValue("weight", weight.to_f) - runner.registerInfo("Registering #{weight} for weight.") - end - - # UPGRADE NAME - upgrade_name = get_value_from_runner_past_results(runner, "upgrade_name", "apply_upgrade", false) - if upgrade_name.nil? - upgrade_name = "" - end - runner.registerValue("upgrade_name", upgrade_name) - runner.registerInfo("Registering #{upgrade_name} for upgrade_name.") - - # UPGRADE COSTS - - upgrade_cost_name = "upgrade_cost_usd" - - # Get upgrade cost value/multiplier pairs and lifetimes from the upgrade measure - has_costs = false - option_cost_pairs = {} - option_lifetimes = {} - for option_num in 1..num_options # Sync with ApplyUpgrade measure - option_cost_pairs[option_num] = [] - option_lifetimes[option_num] = nil - for cost_num in 1..num_costs_per_option # Sync with ApplyUpgrade measure - cost_value = get_value_from_runner_past_results(runner, "option_#{option_num}_cost_#{cost_num}_value_to_apply", "apply_upgrade", false) - next if cost_value.nil? - - cost_mult_type = get_value_from_runner_past_results(runner, "option_#{option_num}_cost_#{cost_num}_multiplier_to_apply", "apply_upgrade", false) - next if cost_mult_type.nil? - - has_costs = true - option_cost_pairs[option_num] << [cost_value.to_f, cost_mult_type] - end - lifetime = get_value_from_runner_past_results(runner, "option_#{option_num}_lifetime_to_apply", "apply_upgrade", false) - next if lifetime.nil? - - option_lifetimes[option_num] = lifetime.to_f - end - - if not has_costs - runner.registerValue(upgrade_cost_name, "") - runner.registerInfo("Registering (blank) for #{upgrade_cost_name}.") - return true - end - - # Obtain cost multiplier values and calculate upgrade costs - upgrade_cost = 0.0 - option_cost_pairs.keys.each do |option_num| - option_cost = 0.0 - option_cost_pairs[option_num].each do |cost_value, cost_mult_type| - cost_mult = get_cost_multiplier(cost_mult_type, model, runner, conditioned_zones) - if cost_mult.nil? - return false - end - - total_cost = cost_value * cost_mult - option_cost += total_cost - runner.registerInfo("Upgrade cost addition: $#{cost_value} x #{cost_mult} [#{cost_mult_type}] = #{total_cost}.") - end - upgrade_cost += option_cost - - # Save option cost/lifetime to results.csv - if option_cost != 0 - option_num_str = option_num.to_s.rjust(2, '0') - option_cost_str = option_cost.round(2).to_s - option_cost_name = "upgrade_option_#{option_num_str}_cost_usd" - runner.registerValue(option_cost_name, option_cost_str) - runner.registerInfo("Registering #{option_cost_str} for #{option_cost_name}.") - if not option_lifetimes[option_num].nil? and option_lifetimes[option_num] != 0 - lifetime_str = option_lifetimes[option_num].round(2).to_s - option_lifetime_name = "upgrade_option_#{option_num_str}_lifetime_yrs" - runner.registerValue(option_lifetime_name, lifetime_str) - runner.registerInfo("Registering #{lifetime_str} for #{option_lifetime_name}.") - end - end - end - upgrade_cost_str = upgrade_cost.round(2).to_s - runner.registerValue(upgrade_cost_name, upgrade_cost_str) - runner.registerInfo("Registering #{upgrade_cost_str} for #{upgrade_cost_name}.") - - runner.registerFinalCondition("Report generated successfully.") - - return true - end # end the run method - - def report_sim_output(runner, name, total_val, os_units, desired_units, percent_of_val = 1.0) - total_val = total_val * percent_of_val - if os_units.nil? or desired_units.nil? or os_units == desired_units - valInUnits = total_val - else - valInUnits = UnitConversions.convert(total_val, os_units, desired_units) - end - runner.registerValue(name, valInUnits) - runner.registerInfo("Registering #{valInUnits.round(2)} for #{name}.") - end - - def get_cost_multiplier(cost_mult_type, model, runner, conditioned_zones) - cost_mult = 0.0 - - if cost_mult_type == "Fixed (1)" - cost_mult = 1.0 - - elsif cost_mult_type == "Wall Area, Above-Grade, Conditioned (ft^2)" - # Walls between conditioned space and 1) outdoors or 2) unconditioned space - model.getSurfaces.each do |surface| - next if surface.surfaceType.downcase != "wall" - next if not surface.space.is_initialized - next if not is_space_conditioned(surface.space.get, conditioned_zones) - - adjacent_space = get_adjacent_space(surface) - if surface.outsideBoundaryCondition.downcase == "outdoors" - cost_mult += UnitConversions.convert(surface.grossArea, "m^2", "ft^2") - elsif !adjacent_space.nil? and not is_space_conditioned(adjacent_space, conditioned_zones) - cost_mult += UnitConversions.convert(surface.grossArea, "m^2", "ft^2") - end - end - - elsif cost_mult_type == "Wall Area, Above-Grade, Exterior (ft^2)" - # Walls adjacent to outdoors - model.getSurfaces.each do |surface| - next if surface.surfaceType.downcase != "wall" - next if surface.outsideBoundaryCondition.downcase != "outdoors" - - cost_mult += UnitConversions.convert(surface.grossArea, "m^2", "ft^2") - end - - elsif cost_mult_type == "Wall Area, Below-Grade (ft^2)" - # Walls adjacent to ground - model.getSurfaces.each do |surface| - next if surface.surfaceType.downcase != "wall" - next if surface.outsideBoundaryCondition.downcase != "ground" and surface.outsideBoundaryCondition.downcase != "foundation" - - cost_mult += UnitConversions.convert(surface.grossArea, "m^2", "ft^2") - end - - elsif cost_mult_type == "Floor Area, Conditioned (ft^2)" - # Floors of conditioned zone - model.getSurfaces.each do |surface| - next if surface.surfaceType.downcase != "floor" - next if not surface.space.is_initialized - next if not is_space_conditioned(surface.space.get, conditioned_zones) - - cost_mult += UnitConversions.convert(surface.grossArea, "m^2", "ft^2") - end - - elsif cost_mult_type == "Floor Area, Attic (ft^2)" - # Floors under sloped surfaces and above conditioned space - model.getSurfaces.each do |surface| - next if surface.surfaceType.downcase != "floor" - next if not surface.space.is_initialized - - space = surface.space.get - next if not has_sloped_roof_surfaces(space) - - adjacent_space = get_adjacent_space(surface) - next if adjacent_space.nil? - next if not is_space_conditioned(adjacent_space, conditioned_zones) - - cost_mult += UnitConversions.convert(surface.grossArea, "m^2", "ft^2") - end - - elsif cost_mult_type == "Floor Area, Lighting (ft^2)" - # Floors with lighting objects - model.getSurfaces.each do |surface| - next if surface.surfaceType.downcase != "floor" - next if not surface.space.is_initialized - next if surface.space.get.lights.size == 0 - - cost_mult += UnitConversions.convert(surface.grossArea, "m^2", "ft^2") - end - - elsif cost_mult_type == "Roof Area (ft^2)" - # Roofs adjacent to outdoors - model.getSurfaces.each do |surface| - next if surface.surfaceType.downcase != "roofceiling" - next if surface.outsideBoundaryCondition.downcase != "outdoors" - - cost_mult += UnitConversions.convert(surface.grossArea, "m^2", "ft^2") - end - - elsif cost_mult_type == "Window Area (ft^2)" - # Window subsurfaces - model.getSurfaces.each do |surface| - next if surface.surfaceType.downcase != "wall" - - surface.subSurfaces.each do |sub_surface| - next if not sub_surface.subSurfaceType.downcase.include? "window" - - cost_mult += UnitConversions.convert(sub_surface.grossArea, "m^2", "ft^2") - end - end - - elsif cost_mult_type == "Door Area (ft^2)" - # Door subsurfaces - model.getSurfaces.each do |surface| - next if surface.surfaceType.downcase != "wall" - - surface.subSurfaces.each do |sub_surface| - next if not sub_surface.subSurfaceType.downcase.include? "door" - - cost_mult += UnitConversions.convert(sub_surface.grossArea, "m^2", "ft^2") - end - end - - elsif cost_mult_type == "Duct Surface Area (ft^2)" - # Duct supply+return surface area - model.getBuildingUnits.each do |unit| - next if unit.spaces.size == 0 - - if cost_mult > 0 - runner.registerError("Multiple building units found. This code should be reevaluated for correctness.") - return nil - end - supply_area = unit.getFeatureAsDouble("SizingInfoDuctsSupplySurfaceArea") - if supply_area.is_initialized - cost_mult += supply_area.get - end - return_area = unit.getFeatureAsDouble("SizingInfoDuctsReturnSurfaceArea") - if return_area.is_initialized - cost_mult += return_area.get - end - end - - elsif cost_mult_type == "Size, Heating System (kBtu/h)" - # Heating system capacity - - all_conditioned_zones = conditioned_zones - - model.getBuildingUnits.each do |unit| - next if unit.spaces.empty? - - conditioned_zones = [] - unit.spaces.each do |space| - zone = space.thermalZone.get - next unless all_conditioned_zones.include? zone - next if conditioned_zones.include? zone - - conditioned_zones << zone - end - - units_represented = 1 - if unit.additionalProperties.getFeatureAsInteger("Units Represented").is_initialized - units_represented = unit.additionalProperties.getFeatureAsInteger("Units Represented").get - end - - component = nil - - # Unit heater? - if component.nil? - conditioned_zones.each do |zone| - zone.equipment.each do |equipment| - next unless equipment.to_AirLoopHVACUnitarySystem.is_initialized - - sys = equipment.to_AirLoopHVACUnitarySystem.get - next unless conditioned_zones.include? sys.controllingZoneorThermostatLocation.get - next if not sys.heatingCoil.is_initialized - - component = sys.heatingCoil.get - next if not component.to_CoilHeatingGas.is_initialized - - coil = component.to_CoilHeatingGas.get - next if not coil.nominalCapacity.is_initialized - - cost_mult += UnitConversions.convert(coil.nominalCapacity.get, "W", "kBtu/hr") - end - end - end - - # Unitary system? - if component.nil? - model.getAirLoopHVACUnitarySystems.each do |sys| - next unless conditioned_zones.include? sys.controllingZoneorThermostatLocation.get - next if not sys.heatingCoil.is_initialized - - if not component.nil? - runner.registerError("Multiple heating systems found. This code should be reevaluated for correctness.") - return nil - end - component = sys.heatingCoil.get - end - if not component.nil? - if component.to_CoilHeatingDXSingleSpeed.is_initialized - coil = component.to_CoilHeatingDXSingleSpeed.get - if coil.ratedTotalHeatingCapacity.is_initialized - cost_mult += UnitConversions.convert(coil.ratedTotalHeatingCapacity.get, "W", "kBtu/hr") - end - elsif component.to_CoilHeatingDXMultiSpeed.is_initialized - coil = component.to_CoilHeatingDXMultiSpeed.get - if coil.stages.size > 0 - stage = coil.stages[coil.stages.size - 1] - capacity_ratio = get_highest_stage_capacity_ratio(model, "SizingInfoHVACCapacityRatioCooling") - if stage.grossRatedHeatingCapacity.is_initialized - cost_mult += UnitConversions.convert(stage.grossRatedHeatingCapacity.get / capacity_ratio, "W", "kBtu/hr") - end - end - elsif component.to_CoilHeatingGas.is_initialized - coil = component.to_CoilHeatingGas.get - if coil.nominalCapacity.is_initialized - cost_mult += UnitConversions.convert(coil.nominalCapacity.get, "W", "kBtu/hr") - end - elsif component.to_CoilHeatingElectric.is_initialized - coil = component.to_CoilHeatingElectric.get - if coil.nominalCapacity.is_initialized - cost_mult += UnitConversions.convert(coil.nominalCapacity.get, "W", "kBtu/hr") - end - elsif component.to_CoilHeatingWaterToAirHeatPumpEquationFit.is_initialized - coil = component.to_CoilHeatingWaterToAirHeatPumpEquationFit.get - if coil.ratedHeatingCapacity.is_initialized - cost_mult += UnitConversions.convert(coil.ratedHeatingCapacity.get, "W", "kBtu/hr") - end - end - end - end - - # Electric baseboard? - if component.nil? - max_value = 0.0 - model.getZoneHVACBaseboardConvectiveElectrics.each do |sys| - next unless conditioned_zones.include? sys.thermalZone.get - - component = sys - next if not component.nominalCapacity.is_initialized - - cost_mult += UnitConversions.convert(component.nominalCapacity.get, "W", "kBtu/hr") - end - end - - # Boiler? - if component.nil? - max_value = 0.0 - model.getPlantLoops.each do |pl| - pl.components.each do |plc| - next if not plc.to_BoilerHotWater.is_initialized - - component = plc.to_BoilerHotWater.get - next if not component.nominalCapacity.is_initialized - next if component.nominalCapacity.get <= max_value - - max_value = component.nominalCapacity.get - end - end - cost_mult += UnitConversions.convert(max_value, "W", "kBtu/hr") - end - - cost_mult *= units_represented - end - - elsif cost_mult_type == "Size, Heating Supplemental System (kBtu/h)" - # Supplemental heating system capacity - - all_conditioned_zones = conditioned_zones - - model.getBuildingUnits.each do |unit| - next if unit.spaces.empty? - - conditioned_zones = [] - unit.spaces.each do |space| - zone = space.thermalZone.get - next unless all_conditioned_zones.include? zone - next if conditioned_zones.include? zone - - conditioned_zones << zone - end - - units_represented = 1 - if unit.additionalProperties.getFeatureAsInteger("Units Represented").is_initialized - units_represented = unit.additionalProperties.getFeatureAsInteger("Units Represented").get - end - - component = nil - - # Unitary system? - if component.nil? - model.getAirLoopHVACUnitarySystems.each do |sys| - next unless conditioned_zones.include? sys.controllingZoneorThermostatLocation.get - next if not sys.supplementalHeatingCoil.is_initialized - - if not component.nil? - runner.registerError("Multiple supplemental heating systems found. This code should be reevaluated for correctness.") - return nil - end - component = sys.supplementalHeatingCoil.get - end - if not component.nil? - if component.to_CoilHeatingElectric.is_initialized - coil = component.to_CoilHeatingElectric.get - if coil.nominalCapacity.is_initialized - cost_mult += UnitConversions.convert(coil.nominalCapacity.get, "W", "kBtu/hr") - end - end - end - end - - cost_mult *= units_represented - end - - elsif cost_mult_type == "Size, Cooling System (kBtu/h)" - # Cooling system capacity - - all_conditioned_zones = conditioned_zones - - model.getBuildingUnits.each do |unit| - next if unit.spaces.empty? - - conditioned_zones = [] - unit.spaces.each do |space| - zone = space.thermalZone.get - next unless all_conditioned_zones.include? zone - next if conditioned_zones.include? zone - - conditioned_zones << zone - end - - units_represented = 1 - if unit.additionalProperties.getFeatureAsInteger("Units Represented").is_initialized - units_represented = unit.additionalProperties.getFeatureAsInteger("Units Represented").get - end - - component = nil - - # Unitary system? - if component.nil? - model.getAirLoopHVACUnitarySystems.each do |sys| - next unless conditioned_zones.include? sys.controllingZoneorThermostatLocation.get - next if not sys.coolingCoil.is_initialized - - if not component.nil? - runner.registerError("Multiple cooling systems found. This code should be reevaluated for correctness.") - return nil - end - component = sys.coolingCoil.get - end - if not component.nil? - if component.to_CoilCoolingDXSingleSpeed.is_initialized - coil = component.to_CoilCoolingDXSingleSpeed.get - if coil.ratedTotalCoolingCapacity.is_initialized - cost_mult += UnitConversions.convert(coil.ratedTotalCoolingCapacity.get, "W", "kBtu/hr") - end - elsif component.to_CoilCoolingDXMultiSpeed.is_initialized - coil = component.to_CoilCoolingDXMultiSpeed.get - if coil.stages.size > 0 - stage = coil.stages[coil.stages.size - 1] - capacity_ratio = get_highest_stage_capacity_ratio(model, "SizingInfoHVACCapacityRatioCooling") - if stage.grossRatedTotalCoolingCapacity.is_initialized - cost_mult += UnitConversions.convert(stage.grossRatedTotalCoolingCapacity.get / capacity_ratio, "W", "kBtu/hr") - end - end - elsif component.to_CoilCoolingWaterToAirHeatPumpEquationFit.is_initialized - coil = component.to_CoilCoolingWaterToAirHeatPumpEquationFit.get - if coil.ratedTotalCoolingCapacity.is_initialized - cost_mult += UnitConversions.convert(coil.ratedTotalCoolingCapacity.get, "W", "kBtu/hr") - end - end - end - end - - # PTAC? - if component.nil? - model.getZoneHVACPackagedTerminalAirConditioners.each do |sys| - next unless conditioned_zones.include? sys.thermalZone.get - - component = sys.coolingCoil - if not component.nil? - if component.to_CoilCoolingDXSingleSpeed.is_initialized - coil = component.to_CoilCoolingDXSingleSpeed.get - if coil.ratedTotalCoolingCapacity.is_initialized - cost_mult += UnitConversions.convert(coil.ratedTotalCoolingCapacity.get, "W", "kBtu/hr") - end - end - end - end - end - - cost_mult *= units_represented - end - - elsif cost_mult_type == "Size, Water Heater (gal)" - # Water heater tank volume - (model.getWaterHeaterMixeds + model.getWaterHeaterHeatPumpWrappedCondensers).each do |wh| - if wh.to_WaterHeaterHeatPumpWrappedCondenser.is_initialized - wh = wh.tank.to_WaterHeaterStratified.get - end - if wh.tankVolume.is_initialized - volume = UnitConversions.convert(wh.tankVolume.get, "m^3", "gal") - if volume >= 1.0 # skip tankless - # FIXME: Remove actual->nominal size logic by storing nominal size in the OSM - if wh.heaterFuelType.downcase == "electricity" - cost_mult += volume / 0.9 - else - cost_mult += volume / 0.95 - end - end - end - end - - elsif cost_mult_type != "" - runner.registerError("Unhandled cost multiplier: #{cost_mult_type.to_s}. Aborting...") - return nil - end - - return cost_mult - end - - def get_conditioned_zones(model) - conditioned_zones = [] - model.getThermalZones.each do |zone| - next if not zone.thermostat.is_initialized - - conditioned_zones << zone - end - return conditioned_zones - end - - def get_adjacent_space(surface) - return nil if not surface.adjacentSurface.is_initialized - return nil if not surface.adjacentSurface.get.space.is_initialized - - return surface.adjacentSurface.get.space.get - end - - def is_space_conditioned(adjacent_space, conditioned_zones) - conditioned_zones.each do |zone| - return true if zone.spaces.include? adjacent_space - end - return false - end - - def has_sloped_roof_surfaces(space) - space.surfaces.each do |surface| - next if surface.surfaceType.downcase != "roofceiling" - next if surface.outsideBoundaryCondition.downcase != "outdoors" - next if surface.tilt == 0 - - return true - end - return false - end - - def get_highest_stage_capacity_ratio(model, property_str) - capacity_ratio = 1.0 - - # Override capacity ratio for residential multispeed systems - model.getAirLoopHVACUnitarySystems.each do |sys| - capacity_ratio_str = sys.additionalProperties.getFeatureAsString(property_str) - next if not capacity_ratio_str.is_initialized - - capacity_ratio = capacity_ratio_str.get.split(",").map(&:to_f)[-1] - end - - return capacity_ratio - end -end # end the measure - -# this allows the measure to be use by the application -SimulationOutputReport.new.registerWithApplication diff --git a/buildstockbatch/test/test_inputs/test_openstudio_buildstock/measures/TimeseriesCSVExport/measure.rb b/buildstockbatch/test/test_inputs/test_openstudio_buildstock/measures/TimeseriesCSVExport/measure.rb deleted file mode 100644 index 9f31b62d..00000000 --- a/buildstockbatch/test/test_inputs/test_openstudio_buildstock/measures/TimeseriesCSVExport/measure.rb +++ /dev/null @@ -1,778 +0,0 @@ -# see the URL below for information on how to write OpenStudio measures -# http://nrel.github.io/OpenStudio-user-documentation/reference/measure_writing_guide/ - -require 'csv' -if File.exists? File.absolute_path(File.join(File.dirname(__FILE__), "../../lib/resources/measures/HPXMLtoOpenStudio/resources")) # Hack to run ResStock on AWS - resources_path = File.absolute_path(File.join(File.dirname(__FILE__), "../../lib/resources/measures/HPXMLtoOpenStudio/resources")) -elsif File.exists? File.absolute_path(File.join(File.dirname(__FILE__), "../../resources/measures/HPXMLtoOpenStudio/resources")) # Hack to run ResStock unit tests locally - resources_path = File.absolute_path(File.join(File.dirname(__FILE__), "../../resources/measures/HPXMLtoOpenStudio/resources")) -elsif File.exists? File.join(OpenStudio::BCLMeasure::userMeasuresDir.to_s, "HPXMLtoOpenStudio/resources") # Hack to run measures in the OS App since applied measures are copied off into a temporary directory - resources_path = File.join(OpenStudio::BCLMeasure::userMeasuresDir.to_s, "HPXMLtoOpenStudio/resources") -else - resources_path = File.absolute_path(File.join(File.dirname(__FILE__), "../HPXMLtoOpenStudio/resources")) -end -require File.join(resources_path, "weather") -require File.join(resources_path, "unit_conversions") -require File.join(resources_path, "geometry") -require File.join(resources_path, "hvac") -require File.join(resources_path, "waterheater") - -# start the measure -class TimeseriesCSVExport < OpenStudio::Measure::ReportingMeasure - # human readable name - def name - return "Timeseries CSV Export" - end - - # human readable description - def description - return "Exports timeseries output data to csv." - end - - def reporting_frequency_map # idf => osm - return { "Timestep" => "Zone Timestep", "Hourly" => "Hourly", "Daily" => "Daily", "Monthly" => "Monthly", "Runperiod" => "Run Period" } - end - - # define the arguments that the user will input - def arguments() - args = OpenStudio::Measure::OSArgumentVector.new - - # make an argument for the frequency - reporting_frequency_chs = OpenStudio::StringVector.new - reporting_frequency_map.keys.each do |reporting_frequency_ch| - reporting_frequency_chs << reporting_frequency_ch - end - arg = OpenStudio::Measure::OSArgument::makeChoiceArgument("reporting_frequency", reporting_frequency_chs, true) - arg.setDisplayName("Reporting Frequency") - arg.setDescription("The frequency at which to report timeseries output data.") - arg.setDefaultValue("Hourly") - args << arg - - # make an argument for including optional end use subcategories - arg = OpenStudio::Measure::OSArgument::makeBoolArgument("include_enduse_subcategories", true) - arg.setDisplayName("Include End Use Subcategories") - arg.setDescription("Whether to report end use subcategories: appliances, plug loads, fans, large uncommon loads.") - arg.setDefaultValue(false) - args << arg - - # make an argument for optional output variables - arg = OpenStudio::Measure::OSArgument::makeStringArgument("output_variables", false) - arg.setDisplayName("Output Variables") - arg.setDescription("Specify a comma-separated list of output variables to report. (See EnergyPlus's rdd file for available output variables.)") - args << arg - - return args - end - - # return a vector of IdfObject's to request EnergyPlus objects needed by the run method - def energyPlusOutputRequests(runner, user_arguments) - super(runner, user_arguments) - - return OpenStudio::IdfObjectVector.new if runner.halted - - reporting_frequency = runner.getStringArgumentValue("reporting_frequency", user_arguments) - include_enduse_subcategories = runner.getBoolArgumentValue("include_enduse_subcategories", user_arguments) - output_variables = runner.getOptionalStringArgumentValue("output_variables", user_arguments) - output_vars = [] - if output_variables.is_initialized - output_vars = output_variables.get - output_vars = output_vars.split(",") - output_vars = output_vars.collect { |x| x.strip } - end - - # get the last model and sql file - model = runner.lastOpenStudioModel - if model.empty? - runner.registerError("Cannot find last model.") - return false - end - model = model.get - - results = OutputMeters.create_custom_building_unit_meters(model, runner, reporting_frequency, include_enduse_subcategories) - output_vars.each do |output_var| - results << OpenStudio::IdfObject.load("Output:Variable,*,#{output_var},#{reporting_frequency};").get - end - results << OpenStudio::IdfObject.load("Output:Meter,Electricity:Facility,#{reporting_frequency};").get - - return results - end - - # define what happens when the measure is run - def run(runner, user_arguments) - super(runner, user_arguments) - - # use the built-in error checking - if not runner.validateUserArguments(arguments(), user_arguments) - return false - end - - # Assign the user inputs to variables - reporting_frequency = runner.getStringArgumentValue("reporting_frequency", user_arguments) - include_enduse_subcategories = runner.getBoolArgumentValue("include_enduse_subcategories", user_arguments) - output_variables = runner.getOptionalStringArgumentValue("output_variables", user_arguments) - output_vars = [] - if output_variables.is_initialized - output_vars = output_variables.get - output_vars = output_vars.split(",") - output_vars = output_vars.collect { |x| x.strip } - end - - # Get the last model and sql file - model = runner.lastOpenStudioModel - if model.empty? - runner.registerError("Cannot find last model.") - return false - end - model = model.get - - sqlFile = runner.lastEnergyPlusSqlFile - if sqlFile.empty? - runner.registerError("Cannot find last sql file.") - return false - end - sqlFile = sqlFile.get - model.setSqlFile(sqlFile) - - # Get datetimes - ann_env_pd = nil - sqlFile.availableEnvPeriods.each do |env_pd| - env_type = sqlFile.environmentType(env_pd) - if env_type.is_initialized - if env_type.get == OpenStudio::EnvironmentType.new("WeatherRunPeriod") - ann_env_pd = env_pd - end - end - end - if ann_env_pd == false - runner.registerError("Can't find a weather runperiod, make sure you ran an annual simulation, not just the design days.") - return false - end - - env_period_ix_query = "SELECT EnvironmentPeriodIndex FROM EnvironmentPeriods WHERE EnvironmentName='#{ann_env_pd}'" - env_period_ix = sqlFile.execAndReturnFirstInt(env_period_ix_query).get - - datetimes = [] - timeseries = sqlFile.timeSeries(ann_env_pd, reporting_frequency_map[reporting_frequency], "Electricity:Facility", "").get # assume every house consumes some electricity - timeseries.dateTimes.each do |datetime| - datetimes << format_datetime(datetime.to_s) - end - num_ts = datetimes.length - - total_site_units = "MBtu" - elec_site_units = "kWh" - gas_site_units = "therm" - other_fuel_site_units = "MBtu" - - # Get meters that aren't tied to units (i.e., are metered at the building level) - modeledCentralElectricityHeating = [0] * num_ts - modeledCentralElectricityCooling = [0] * num_ts - modeledCentralElectricityExteriorLighting = [0] * num_ts - modeledCentralElectricityExteriorHolidayLighting = [0] * num_ts - modeledCentralElectricityPumpsHeating = [0] * num_ts - modeledCentralElectricityPumpsCooling = [0] * num_ts - modeledCentralElectricityInteriorEquipment = [0] * num_ts - modeledCentralElectricityPhotovoltaics = [0] * num_ts - modeledCentralElectricityExtraRefrigerator = [0] * num_ts - modeledCentralElectricityFreezer = [0] * num_ts - modeledCentralElectricityGarageLighting = [0] * num_ts - modeledCentralNaturalGasHeating = [0] * num_ts - modeledCentralNaturalGasInteriorEquipment = [0] * num_ts - modeledCentralNaturalGasGrill = [0] * num_ts - modeledCentralNaturalGasLighting = [0] * num_ts - modeledCentralNaturalGasFireplace = [0] * num_ts - modeledCentralFuelOilHeating = [0] * num_ts - modeledCentralPropaneHeating = [0] * num_ts - - central_electricity_heating_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('CENTRAL:ELECTRICITYHEATING') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" - unless sqlFile.execAndReturnVectorOfDouble(central_electricity_heating_query).get.empty? - modeledCentralElectricityHeating = sqlFile.execAndReturnVectorOfDouble(central_electricity_heating_query).get - end - - central_electricity_cooling_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('CENTRAL:ELECTRICITYCOOLING') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" - unless sqlFile.execAndReturnVectorOfDouble(central_electricity_cooling_query).get.empty? - modeledCentralElectricityCooling = sqlFile.execAndReturnVectorOfDouble(central_electricity_cooling_query).get - end - - central_electricity_exterior_lighting_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('CENTRAL:ELECTRICITYEXTERIORLIGHTING') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" - unless sqlFile.execAndReturnVectorOfDouble(central_electricity_exterior_lighting_query).get.empty? - modeledCentralElectricityExteriorLighting = sqlFile.execAndReturnVectorOfDouble(central_electricity_exterior_lighting_query).get - end - - central_electricity_exterior_holiday_lighting_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('CENTRAL:ELECTRICITYEXTERIORHOLIDAYLIGHTING') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" - unless sqlFile.execAndReturnVectorOfDouble(central_electricity_exterior_holiday_lighting_query).get.empty? - modeledCentralElectricityExteriorHolidayLighting = sqlFile.execAndReturnVectorOfDouble(central_electricity_exterior_holiday_lighting_query).get - end - - central_electricity_pumps_heating_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('CENTRAL:ELECTRICITYPUMPSHEATING') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" - unless sqlFile.execAndReturnVectorOfDouble(central_electricity_pumps_heating_query).get.empty? - modeledCentralElectricityPumpsHeating = sqlFile.execAndReturnVectorOfDouble(central_electricity_pumps_heating_query).get - end - - central_electricity_pumps_cooling_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('CENTRAL:ELECTRICITYPUMPSCOOLING') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" - unless sqlFile.execAndReturnVectorOfDouble(central_electricity_pumps_cooling_query).get.empty? - modeledCentralElectricityPumpsCooling = sqlFile.execAndReturnVectorOfDouble(central_electricity_pumps_cooling_query).get - end - - central_electricity_interior_equipment_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('CENTRAL:ELECTRICITYINTERIOREQUIPMENT') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" - unless sqlFile.execAndReturnVectorOfDouble(central_electricity_interior_equipment_query).get.empty? - modeledCentralElectricityInteriorEquipment = sqlFile.execAndReturnVectorOfDouble(central_electricity_interior_equipment_query).get - end - - central_electricity_photovoltaics_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('CENTRAL:ELECTRICITYPHOTOVOLTAICS') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" - unless sqlFile.execAndReturnVectorOfDouble(central_electricity_photovoltaics_query).get.empty? - modeledCentralElectricityPhotovoltaics = sqlFile.execAndReturnVectorOfDouble(central_electricity_photovoltaics_query).get - end - - central_electricity_extra_refrigerator_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('CENTRAL:ELECTRICITYEXTRAREFRIGERATOR') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" - unless sqlFile.execAndReturnVectorOfDouble(central_electricity_extra_refrigerator_query).get.empty? - modeledCentralElectricityExtraRefrigerator = sqlFile.execAndReturnVectorOfDouble(central_electricity_extra_refrigerator_query).get - end - - central_electricity_freezer_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('CENTRAL:ELECTRICITYFREEZER') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" - unless sqlFile.execAndReturnVectorOfDouble(central_electricity_freezer_query).get.empty? - modeledCentralElectricityFreezer = sqlFile.execAndReturnVectorOfDouble(central_electricity_freezer_query).get - end - - central_electricity_garage_lighting_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('CENTRAL:ELECTRICITYGARAGELIGHTING') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" - unless sqlFile.execAndReturnVectorOfDouble(central_electricity_garage_lighting_query).get.empty? - modeledCentralElectricityGarageLighting = sqlFile.execAndReturnVectorOfDouble(central_electricity_garage_lighting_query).get - end - - central_natural_gas_heating_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('CENTRAL:NATURALGASHEATING') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" - unless sqlFile.execAndReturnVectorOfDouble(central_natural_gas_heating_query).get.empty? - modeledCentralNaturalGasHeating = sqlFile.execAndReturnVectorOfDouble(central_natural_gas_heating_query).get - end - - central_natural_gas_interior_equipment_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('CENTRAL:NATURALGASINTERIOREQUIPMENT') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" - unless sqlFile.execAndReturnVectorOfDouble(central_natural_gas_interior_equipment_query).get.empty? - modeledCentralNaturalGasInteriorEquipment = sqlFile.execAndReturnVectorOfDouble(central_natural_gas_interior_equipment_query).get - end - - central_natural_gas_grill_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('CENTRAL:NATURALGASGRILL') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" - unless sqlFile.execAndReturnVectorOfDouble(central_natural_gas_grill_query).get.empty? - modeledCentralNaturalGasGrill = sqlFile.execAndReturnVectorOfDouble(central_natural_gas_grill_query).get - end - - central_natural_gas_lighting_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('CENTRAL:NATURALGASLIGHTING') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" - unless sqlFile.execAndReturnVectorOfDouble(central_natural_gas_lighting_query).get.empty? - modeledCentralNaturalGasLighting = sqlFile.execAndReturnVectorOfDouble(central_natural_gas_lighting_query).get - end - - central_natural_gas_fireplace_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('CENTRAL:NATURALGASFIREPLACE') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" - unless sqlFile.execAndReturnVectorOfDouble(central_natural_gas_fireplace_query).get.empty? - modeledCentralNaturalGasFireplace = sqlFile.execAndReturnVectorOfDouble(central_natural_gas_fireplace_query).get - end - - central_fuel_oil_heating_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('CENTRAL:FUELOILHEATING') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" - unless sqlFile.execAndReturnVectorOfDouble(central_fuel_oil_heating_query).get.empty? - modeledCentralFuelOilHeating = sqlFile.execAndReturnVectorOfDouble(central_fuel_oil_heating_query).get - end - - central_propane_heating_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('CENTRAL:PROPANEHEATING') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" - unless sqlFile.execAndReturnVectorOfDouble(central_propane_heating_query).get.empty? - modeledCentralPropaneHeating = sqlFile.execAndReturnVectorOfDouble(central_propane_heating_query).get - end - - # Separate these from non central systems - centralElectricityHeating = [0] * num_ts - centralElectricityCooling = [0] * num_ts - centralElectricityPumpsHeating = [0] * num_ts - centralElectricityPumpsCooling = [0] * num_ts - centralNaturalGasHeating = [0] * num_ts - centralFuelOilHeating = [0] * num_ts - centralPropaneHeating = [0] * num_ts - - # Get meters that are tied to units, and apportion building level meters to these - electricityTotalEndUses = [0] * num_ts - electricityHeating = [0] * num_ts - electricityCooling = [0] * num_ts - electricityInteriorLighting = [0] * num_ts - electricityExteriorLighting = [0] * num_ts - electricityExteriorHolidayLighting = modeledCentralElectricityExteriorHolidayLighting - electricityInteriorEquipment = [0] * num_ts - electricityFansHeating = [0] * num_ts - electricityFansCooling = [0] * num_ts - electricityPumpsHeating = [0] * num_ts - electricityPumpsCooling = [0] * num_ts - electricityWaterSystems = [0] * num_ts - electricityPhotovoltaics = [0] * num_ts - naturalGasTotalEndUses = [0] * num_ts - naturalGasHeating = [0] * num_ts - naturalGasInteriorEquipment = [0] * num_ts - naturalGasWaterSystems = [0] * num_ts - fuelOilTotalEndUses = [0] * num_ts - fuelOilHeating = [0] * num_ts - fuelOilInteriorEquipment = [0] * num_ts - fuelOilWaterSystems = [0] * num_ts - propaneTotalEndUses = [0] * num_ts - propaneHeating = [0] * num_ts - propaneInteriorEquipment = [0] * num_ts - propaneWaterSystems = [0] * num_ts - electricityRefrigerator = [0] * num_ts - electricityClothesWasher = [0] * num_ts - electricityClothesDryer = [0] * num_ts - naturalGasClothesDryer = [0] * num_ts - propaneClothesDryer = [0] * num_ts - electricityCookingRange = [0] * num_ts - naturalGasCookingRange = [0] * num_ts - propaneCookingRange = [0] * num_ts - electricityDishwasher = [0] * num_ts - electricityPlugLoads = [0] * num_ts - electricityHouseFan = [0] * num_ts - electricityRangeFan = [0] * num_ts - electricityBathFan = [0] * num_ts - electricityCeilingFan = [0] * num_ts - electricityExtraRefrigerator = [0] * num_ts - electricityFreezer = [0] * num_ts - electricityPoolHeater = [0] * num_ts - naturalGasPoolHeater = [0] * num_ts - electricityPoolPump = [0] * num_ts - electricityHotTubHeater = [0] * num_ts - naturalGasHotTubHeater = [0] * num_ts - electricityHotTubPump = [0] * num_ts - electricityWellPump = [0] * num_ts - electricityGarageLighting = [0] * num_ts - naturalGasGrill = [0] * num_ts - naturalGasLighting = [0] * num_ts - naturalGasFireplace = [0] * num_ts - - # Get building units - units = Geometry.get_building_units(model, runner) - if units.nil? - return false - end - - units.each do |unit| - unit_name = unit.name.to_s.upcase - - units_represented = 1 - if unit.additionalProperties.getFeatureAsInteger("Units Represented").is_initialized - units_represented = unit.additionalProperties.getFeatureAsInteger("Units Represented").get - end - - electricity_heating_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:ELECTRICITYHEATING') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" - unless sqlFile.execAndReturnVectorOfDouble(electricity_heating_query).get.empty? - electricityHeating = array_sum(electricityHeating, sqlFile.execAndReturnVectorOfDouble(electricity_heating_query).get, units_represented) - end - - centralElectricityHeating = array_sum(centralElectricityHeating, modeledCentralElectricityHeating, units_represented, units.length) - - electricity_cooling_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:ELECTRICITYCOOLING') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" - unless sqlFile.execAndReturnVectorOfDouble(electricity_cooling_query).get.empty? - electricityCooling = array_sum(electricityCooling, sqlFile.execAndReturnVectorOfDouble(electricity_cooling_query).get, units_represented) - end - - centralElectricityCooling = array_sum(centralElectricityCooling, modeledCentralElectricityCooling, units_represented, units.length) - - electricity_interior_lighting_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:ELECTRICITYINTERIORLIGHTING') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" - unless sqlFile.execAndReturnVectorOfDouble(electricity_interior_lighting_query).get.empty? - electricityInteriorLighting = array_sum(electricityInteriorLighting, sqlFile.execAndReturnVectorOfDouble(electricity_interior_lighting_query).get, units_represented) - end - - electricityExteriorLighting = array_sum(electricityExteriorLighting, modeledCentralElectricityExteriorLighting, units_represented, units.length) - - electricity_interior_equipment_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:ELECTRICITYINTERIOREQUIPMENT') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" - unless sqlFile.execAndReturnVectorOfDouble(electricity_interior_equipment_query).get.empty? - electricityInteriorEquipment = array_sum(electricityInteriorEquipment, sqlFile.execAndReturnVectorOfDouble(electricity_interior_equipment_query).get, units_represented) - end - electricityInteriorEquipment = array_sum(electricityInteriorEquipment, modeledCentralElectricityInteriorEquipment, units_represented, units.length) - - electricity_fans_heating_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:ELECTRICITYFANSHEATING') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" - unless sqlFile.execAndReturnVectorOfDouble(electricity_fans_heating_query).get.empty? - electricityFansHeating = array_sum(electricityFansHeating, sqlFile.execAndReturnVectorOfDouble(electricity_fans_heating_query).get, units_represented) - end - - electricity_fans_cooling_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:ELECTRICITYFANSCOOLING') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" - unless sqlFile.execAndReturnVectorOfDouble(electricity_fans_cooling_query).get.empty? - electricityFansCooling = array_sum(electricityFansCooling, sqlFile.execAndReturnVectorOfDouble(electricity_fans_cooling_query).get, units_represented) - end - - electricity_pumps_heating_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:ELECTRICITYPUMPSHEATING') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" - unless sqlFile.execAndReturnVectorOfDouble(electricity_pumps_heating_query).get.empty? - electricityPumpsHeating = array_sum(electricityPumpsHeating, sqlFile.execAndReturnVectorOfDouble(electricity_pumps_heating_query).get, units_represented) - end - - centralElectricityPumpsHeating = array_sum(centralElectricityPumpsHeating, modeledCentralElectricityPumpsHeating, units_represented, units.length) - - electricity_pumps_cooling_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:ELECTRICITYPUMPSCOOLING') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" - unless sqlFile.execAndReturnVectorOfDouble(electricity_pumps_cooling_query).get.empty? - electricityPumpsCooling = array_sum(electricityPumpsCooling, sqlFile.execAndReturnVectorOfDouble(electricity_pumps_cooling_query).get, units_represented) - end - - centralElectricityPumpsCooling = array_sum(centralElectricityPumpsCooling, modeledCentralElectricityPumpsCooling, units_represented, units.length) - - electricity_water_systems_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:ELECTRICITYWATERSYSTEMS') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" - unless sqlFile.execAndReturnVectorOfDouble(electricity_water_systems_query).get.empty? - electricityWaterSystems = array_sum(electricityWaterSystems, sqlFile.execAndReturnVectorOfDouble(electricity_water_systems_query).get, units_represented) - end - - natural_gas_heating_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:NATURALGASHEATING') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" - unless sqlFile.execAndReturnVectorOfDouble(natural_gas_heating_query).get.empty? - naturalGasHeating = array_sum(naturalGasHeating, sqlFile.execAndReturnVectorOfDouble(natural_gas_heating_query).get, units_represented) - end - - centralNaturalGasHeating = array_sum(centralNaturalGasHeating, modeledCentralNaturalGasHeating, units_represented, units.length) - - natural_gas_interior_equipment_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:NATURALGASINTERIOREQUIPMENT') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" - unless sqlFile.execAndReturnVectorOfDouble(natural_gas_interior_equipment_query).get.empty? - naturalGasInteriorEquipment = array_sum(naturalGasInteriorEquipment, sqlFile.execAndReturnVectorOfDouble(natural_gas_interior_equipment_query).get, units_represented) - end - naturalGasInteriorEquipment = array_sum(naturalGasInteriorEquipment, modeledCentralNaturalGasInteriorEquipment, units_represented, units.length) - - natural_gas_water_systems_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:NATURALGASWATERSYSTEMS') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" - unless sqlFile.execAndReturnVectorOfDouble(natural_gas_water_systems_query).get.empty? - naturalGasWaterSystems = array_sum(naturalGasWaterSystems, sqlFile.execAndReturnVectorOfDouble(natural_gas_water_systems_query).get, units_represented) - end - - fuel_oil_heating_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:FUELOILHEATING') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" - unless sqlFile.execAndReturnVectorOfDouble(fuel_oil_heating_query).get.empty? - fuelOilHeating = array_sum(fuelOilHeating, sqlFile.execAndReturnVectorOfDouble(fuel_oil_heating_query).get, units_represented) - end - - centralFuelOilHeating = array_sum(centralFuelOilHeating, modeledCentralFuelOilHeating, units_represented, units.length) - - fuel_oil_interior_equipment_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:FUELOILINTERIOREQUIPMENT') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" - unless sqlFile.execAndReturnVectorOfDouble(fuel_oil_interior_equipment_query).get.empty? - fuelOilInteriorEquipment = array_sum(fuelOilInteriorEquipment, sqlFile.execAndReturnVectorOfDouble(fuel_oil_interior_equipment_query).get, units_represented) - end - - fuel_oil_water_systems_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:FUELOILWATERSYSTEMS') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" - unless sqlFile.execAndReturnVectorOfDouble(fuel_oil_water_systems_query).get.empty? - fuelOilWaterSystems = array_sum(fuelOilWaterSystems, sqlFile.execAndReturnVectorOfDouble(fuel_oil_water_systems_query).get, units_represented) - end - - propane_heating_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:PROPANEHEATING') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" - unless sqlFile.execAndReturnVectorOfDouble(propane_heating_query).get.empty? - propaneHeating = array_sum(propaneHeating, sqlFile.execAndReturnVectorOfDouble(propane_heating_query).get, units_represented) - end - - centralPropaneHeating = array_sum(centralPropaneHeating, modeledCentralPropaneHeating, units_represented, units.length) - - propane_interior_equipment_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:PROPANEINTERIOREQUIPMENT') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" - unless sqlFile.execAndReturnVectorOfDouble(propane_interior_equipment_query).get.empty? - propaneInteriorEquipment = array_sum(propaneInteriorEquipment, sqlFile.execAndReturnVectorOfDouble(propane_interior_equipment_query).get, units_represented) - end - - propane_water_systems_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:PROPANEWATERSYSTEMS') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" - unless sqlFile.execAndReturnVectorOfDouble(propane_water_systems_query).get.empty? - propaneWaterSystems = array_sum(propaneWaterSystems, sqlFile.execAndReturnVectorOfDouble(propane_water_systems_query).get, units_represented) - end - - if include_enduse_subcategories - electricity_refrgerator_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:ELECTRICITYREFRIGERATOR') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" - unless sqlFile.execAndReturnVectorOfDouble(electricity_refrgerator_query).get.empty? - electricityRefrigerator = array_sum(electricityRefrigerator, sqlFile.execAndReturnVectorOfDouble(electricity_refrgerator_query).get, units_represented) - end - - electricity_clothes_washer_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:ELECTRICITYCLOTHESWASHER') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" - unless sqlFile.execAndReturnVectorOfDouble(electricity_clothes_washer_query).get.empty? - electricityClothesWasher = array_sum(electricityClothesWasher, sqlFile.execAndReturnVectorOfDouble(electricity_clothes_washer_query).get, units_represented) - end - - electricity_clothes_dryer_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:ELECTRICITYCLOTHESDRYER') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" - unless sqlFile.execAndReturnVectorOfDouble(electricity_clothes_dryer_query).get.empty? - electricityClothesDryer = array_sum(electricityClothesDryer, sqlFile.execAndReturnVectorOfDouble(electricity_clothes_dryer_query).get, units_represented) - end - - natural_gas_clothes_dryer_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:NATURALGASCLOTHESDRYER') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" - unless sqlFile.execAndReturnVectorOfDouble(natural_gas_clothes_dryer_query).get.empty? - naturalGasClothesDryer = array_sum(naturalGasClothesDryer, sqlFile.execAndReturnVectorOfDouble(natural_gas_clothes_dryer_query).get, units_represented) - end - - propane_clothes_dryer_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:PROPANECLOTHESDRYER') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" - unless sqlFile.execAndReturnVectorOfDouble(propane_clothes_dryer_query).get.empty? - propaneClothesDryer = array_sum(propaneClothesDryer, sqlFile.execAndReturnVectorOfDouble(propane_clothes_dryer_query).get, units_represented) - end - - electricity_cooking_range_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:ELECTRICITYCOOKINGRANGE') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" - unless sqlFile.execAndReturnVectorOfDouble(electricity_cooking_range_query).get.empty? - electricityCookingRange = array_sum(electricityCookingRange, sqlFile.execAndReturnVectorOfDouble(electricity_cooking_range_query).get, units_represented) - end - - natural_gas_cooking_range_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:NATURALGASCOOKINGRANGE') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" - unless sqlFile.execAndReturnVectorOfDouble(natural_gas_cooking_range_query).get.empty? - naturalGasCookingRange = array_sum(naturalGasCookingRange, sqlFile.execAndReturnVectorOfDouble(natural_gas_cooking_range_query).get, units_represented) - end - - propane_cooking_range_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:PROPANECOOKINGRANGE') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" - unless sqlFile.execAndReturnVectorOfDouble(propane_cooking_range_query).get.empty? - propaneCookingRange = array_sum(propaneCookingRange, sqlFile.execAndReturnVectorOfDouble(propane_cooking_range_query).get, units_represented) - end - - electricity_dishwasher_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:ELECTRICITYDISHWASHER') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" - unless sqlFile.execAndReturnVectorOfDouble(electricity_dishwasher_query).get.empty? - electricityDishwasher = array_sum(electricityDishwasher, sqlFile.execAndReturnVectorOfDouble(electricity_dishwasher_query).get, units_represented) - end - - electricity_plug_loads_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:ELECTRICITYPLUGLOADS') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" - unless sqlFile.execAndReturnVectorOfDouble(electricity_plug_loads_query).get.empty? - electricityPlugLoads = array_sum(electricityPlugLoads, sqlFile.execAndReturnVectorOfDouble(electricity_plug_loads_query).get, units_represented) - end - - electricity_house_fan_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:ELECTRICITYHOUSEFAN') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" - unless sqlFile.execAndReturnVectorOfDouble(electricity_house_fan_query).get.empty? - electricityHouseFan = array_sum(electricityHouseFan, sqlFile.execAndReturnVectorOfDouble(electricity_house_fan_query).get, units_represented) - end - - electricity_range_fan_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:ELECTRICITYRANGEFAN') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" - unless sqlFile.execAndReturnVectorOfDouble(electricity_range_fan_query).get.empty? - electricityRangeFan = array_sum(electricityRangeFan, sqlFile.execAndReturnVectorOfDouble(electricity_range_fan_query).get, units_represented) - end - - electricity_bath_fan_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:ELECTRICITYBATHFAN') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" - unless sqlFile.execAndReturnVectorOfDouble(electricity_bath_fan_query).get.empty? - electricityBathFan = array_sum(electricityBathFan, sqlFile.execAndReturnVectorOfDouble(electricity_bath_fan_query).get, units_represented) - end - - electricity_ceiling_fan_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:ELECTRICITYCEILINGFAN') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" - unless sqlFile.execAndReturnVectorOfDouble(electricity_ceiling_fan_query).get.empty? - electricityCeilingFan = array_sum(electricityCeilingFan, sqlFile.execAndReturnVectorOfDouble(electricity_ceiling_fan_query).get, units_represented) - end - - electricity_extra_refrigerator_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:ELECTRICITYEXTRAREFRIGERATOR') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" - unless sqlFile.execAndReturnVectorOfDouble(electricity_extra_refrigerator_query).get.empty? - electricityExtraRefrigerator = array_sum(electricityExtraRefrigerator, sqlFile.execAndReturnVectorOfDouble(electricity_extra_refrigerator_query).get, units_represented) - end - electricityExtraRefrigerator = array_sum(electricityExtraRefrigerator, modeledCentralElectricityExtraRefrigerator, units_represented, units.length) - - electricity_freezer_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:ELECTRICITYFREEZER') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" - unless sqlFile.execAndReturnVectorOfDouble(electricity_freezer_query).get.empty? - electricityFreezer = array_sum(electricityFreezer, sqlFile.execAndReturnVectorOfDouble(electricity_freezer_query).get, units_represented) - end - electricityFreezer = array_sum(electricityFreezer, modeledCentralElectricityFreezer, units_represented, units.length) - - electricity_pool_heater_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:ELECTRICITYPOOLHEATER') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" - unless sqlFile.execAndReturnVectorOfDouble(electricity_pool_heater_query).get.empty? - electricityPoolHeater = array_sum(electricityPoolHeater, sqlFile.execAndReturnVectorOfDouble(electricity_pool_heater_query).get, units_represented) - end - - electricity_pool_pump_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:ELECTRICITYPOOLPUMP') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" - unless sqlFile.execAndReturnVectorOfDouble(electricity_pool_pump_query).get.empty? - electricityPoolPump = array_sum(electricityPoolPump, sqlFile.execAndReturnVectorOfDouble(electricity_pool_pump_query).get, units_represented) - end - - electricity_hot_tub_heater_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:ELECTRICITYHOTTUBHEATER') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" - unless sqlFile.execAndReturnVectorOfDouble(electricity_hot_tub_heater_query).get.empty? - electricityHotTubHeater = array_sum(electricityHotTubHeater, sqlFile.execAndReturnVectorOfDouble(electricity_hot_tub_heater_query).get, units_represented) - end - - electricity_hot_tub_pump_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:ELECTRICITYHOTTUBPUMP') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" - unless sqlFile.execAndReturnVectorOfDouble(electricity_hot_tub_pump_query).get.empty? - electricityHotTubPump = array_sum(electricityHotTubPump, sqlFile.execAndReturnVectorOfDouble(electricity_hot_tub_pump_query).get, units_represented) - end - - electricity_well_pump_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:ELECTRICITYWELLPUMP') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" - unless sqlFile.execAndReturnVectorOfDouble(electricity_well_pump_query).get.empty? - electricityWellPump = array_sum(electricityWellPump, sqlFile.execAndReturnVectorOfDouble(electricity_well_pump_query).get, units_represented) - end - - electricityGarageLighting = array_sum(electricityGarageLighting, modeledCentralElectricityGarageLighting, units_represented, units.length) - - natural_gas_pool_heater_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:NATURALGASPOOLHEATER') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" - unless sqlFile.execAndReturnVectorOfDouble(natural_gas_pool_heater_query).get.empty? - naturalGasPoolHeater = array_sum(naturalGasPoolHeater, sqlFile.execAndReturnVectorOfDouble(natural_gas_pool_heater_query).get, units_represented) - end - - natural_gas_hot_tub_heater_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:NATURALGASHOTTUBHEATER') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" - unless sqlFile.execAndReturnVectorOfDouble(natural_gas_hot_tub_heater_query).get.empty? - naturalGasHotTubHeater = array_sum(naturalGasHotTubHeater, sqlFile.execAndReturnVectorOfDouble(natural_gas_hot_tub_heater_query).get, units_represented) - end - - natural_gas_grill_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:NATURALGASGRILL') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" - unless sqlFile.execAndReturnVectorOfDouble(natural_gas_grill_query).get.empty? - naturalGasGrill = array_sum(naturalGasGrill, sqlFile.execAndReturnVectorOfDouble(natural_gas_grill_query).get, units_represented) - end - naturalGasGrill = array_sum(naturalGasGrill, modeledCentralNaturalGasGrill, units_represented, units.length) - - natural_gas_lighting_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:NATURALGASLIGHTING') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" - unless sqlFile.execAndReturnVectorOfDouble(natural_gas_lighting_query).get.empty? - naturalGasLighting = array_sum(naturalGasLighting, sqlFile.execAndReturnVectorOfDouble(natural_gas_lighting_query).get, units_represented) - end - naturalGasLighting = array_sum(naturalGasLighting, modeledCentralNaturalGasLighting, units_represented, units.length) - - natural_gas_fireplace_query = "SELECT VariableValue/1000000000 FROM ReportMeterData WHERE ReportMeterDataDictionaryIndex IN (SELECT ReportMeterDataDictionaryIndex FROM ReportMeterDataDictionary WHERE VariableType='Sum' AND VariableName IN ('#{unit_name}:NATURALGASFIREPLACE') AND ReportingFrequency='#{reporting_frequency_map[reporting_frequency]}' AND VariableUnits='J') AND TimeIndex IN (SELECT TimeIndex FROM Time WHERE EnvironmentPeriodIndex='#{env_period_ix}')" - unless sqlFile.execAndReturnVectorOfDouble(natural_gas_fireplace_query).get.empty? - naturalGasFireplace = array_sum(naturalGasFireplace, sqlFile.execAndReturnVectorOfDouble(natural_gas_fireplace_query).get, units_represented) - end - naturalGasFireplace = array_sum(naturalGasFireplace, modeledCentralNaturalGasFireplace, units_represented, units.length) - end - end - - # Get the timestamps for actual year epw file, and the number of intervals per hour - weather = WeatherProcess.new(model, runner) - if weather.error? - return false - end - - actual_year_timestamps = weather.actual_year_timestamps(reporting_frequency) - - # Initialize timeseries hash which will be exported to csv - timeseries = {} - timeseries["Time"] = datetimes # timestamps from the sqlfile (TMY) - unless actual_year_timestamps.empty? - timeseries["Time"] = actual_year_timestamps # timestamps constructed using run period and Time class (AMY) - end - if timeseries["Time"].length != num_ts - runner.registerError("The timestamps array length does not equal that of the sqlfile timeseries. You may be ignoring leap days in your AMY weather file.") - return false - end - - # ELECTRICITY - - electricityTotalEndUses = [electricityHeating, centralElectricityHeating, electricityCooling, centralElectricityCooling, electricityInteriorLighting, electricityExteriorLighting, electricityExteriorHolidayLighting, electricityInteriorEquipment, electricityFansHeating, electricityFansCooling, electricityPumpsHeating, centralElectricityPumpsHeating, electricityPumpsCooling, centralElectricityPumpsCooling, electricityWaterSystems].transpose.map { |e| e.reduce(:+) } - - report_ts_output(runner, timeseries, "total_site_electricity_kwh", electricityTotalEndUses, "GJ", elec_site_units) - report_ts_output(runner, timeseries, "net_site_electricity_kwh", [electricityTotalEndUses, modeledCentralElectricityPhotovoltaics].transpose.collect { |e1, e2| e1 - e2 }, "GJ", elec_site_units) - report_ts_output(runner, timeseries, "electricity_heating_kwh", electricityHeating, "GJ", elec_site_units) - report_ts_output(runner, timeseries, "electricity_central_system_heating_kwh", centralElectricityHeating, "GJ", elec_site_units) - report_ts_output(runner, timeseries, "electricity_cooling_kwh", electricityCooling, "GJ", elec_site_units) - report_ts_output(runner, timeseries, "electricity_central_system_cooling_kwh", centralElectricityCooling, "GJ", elec_site_units) - report_ts_output(runner, timeseries, "electricity_interior_lighting_kwh", electricityInteriorLighting, "GJ", elec_site_units) - report_ts_output(runner, timeseries, "electricity_exterior_lighting_kwh", [electricityExteriorLighting, electricityExteriorHolidayLighting].transpose.map { |e| e.reduce(:+) }, "GJ", elec_site_units) - report_ts_output(runner, timeseries, "electricity_interior_equipment_kwh", electricityInteriorEquipment, "GJ", elec_site_units) - report_ts_output(runner, timeseries, "electricity_fans_heating_kwh", electricityFansHeating, "GJ", elec_site_units) - report_ts_output(runner, timeseries, "electricity_fans_cooling_kwh", electricityFansCooling, "GJ", elec_site_units) - report_ts_output(runner, timeseries, "electricity_pumps_heating_kwh", electricityPumpsHeating, "GJ", elec_site_units) - report_ts_output(runner, timeseries, "electricity_central_system_pumps_heating_kwh", centralElectricityPumpsHeating, "GJ", elec_site_units) - report_ts_output(runner, timeseries, "electricity_pumps_cooling_kwh", electricityPumpsCooling, "GJ", elec_site_units) - report_ts_output(runner, timeseries, "electricity_central_system_pumps_cooling_kwh", centralElectricityPumpsCooling, "GJ", elec_site_units) - report_ts_output(runner, timeseries, "electricity_water_systems_kwh", electricityWaterSystems, "GJ", elec_site_units) - report_ts_output(runner, timeseries, "electricity_pv_kwh", modeledCentralElectricityPhotovoltaics, "GJ", elec_site_units) - - # NATURAL GAS - - naturalGasTotalEndUses = [naturalGasHeating, centralNaturalGasHeating, naturalGasInteriorEquipment, naturalGasWaterSystems].transpose.map { |n| n.reduce(:+) } - - report_ts_output(runner, timeseries, "total_site_natural_gas_therm", naturalGasTotalEndUses, "GJ", gas_site_units) - report_ts_output(runner, timeseries, "natural_gas_heating_therm", naturalGasHeating, "GJ", gas_site_units) - report_ts_output(runner, timeseries, "natural_gas_central_system_heating_therm", centralNaturalGasHeating, "GJ", gas_site_units) - report_ts_output(runner, timeseries, "natural_gas_interior_equipment_therm", naturalGasInteriorEquipment, "GJ", gas_site_units) - report_ts_output(runner, timeseries, "natural_gas_water_systems_therm", naturalGasWaterSystems, "GJ", gas_site_units) - - # FUEL OIL - - fuelOilTotalEndUses = [fuelOilHeating, centralFuelOilHeating, fuelOilInteriorEquipment, fuelOilWaterSystems].transpose.map { |f| f.reduce(:+) } - - report_ts_output(runner, timeseries, "total_site_fuel_oil_mbtu", fuelOilTotalEndUses, "GJ", other_fuel_site_units) - report_ts_output(runner, timeseries, "fuel_oil_heating_mbtu", fuelOilHeating, "GJ", other_fuel_site_units) - report_ts_output(runner, timeseries, "fuel_oil_central_system_heating_mbtu", centralFuelOilHeating, "GJ", other_fuel_site_units) - report_ts_output(runner, timeseries, "fuel_oil_interior_equipment_mbtu", fuelOilInteriorEquipment, "GJ", other_fuel_site_units) - report_ts_output(runner, timeseries, "fuel_oil_water_systems_mbtu", fuelOilWaterSystems, "GJ", other_fuel_site_units) - - # PROPANE - - propaneTotalEndUses = [propaneHeating, centralPropaneHeating, propaneInteriorEquipment, propaneWaterSystems].transpose.map { |p| p.reduce(:+) } - - report_ts_output(runner, timeseries, "total_site_propane_mbtu", propaneTotalEndUses, "GJ", other_fuel_site_units) - report_ts_output(runner, timeseries, "propane_heating_mbtu", propaneHeating, "GJ", other_fuel_site_units) - report_ts_output(runner, timeseries, "propane_central_system_heating_mbtu", centralPropaneHeating, "GJ", other_fuel_site_units) - report_ts_output(runner, timeseries, "propane_interior_equipment_mbtu", propaneInteriorEquipment, "GJ", other_fuel_site_units) - report_ts_output(runner, timeseries, "propane_water_systems_mbtu", propaneWaterSystems, "GJ", other_fuel_site_units) - - # TOTAL - - totalSiteEnergy = [electricityTotalEndUses, naturalGasTotalEndUses, fuelOilTotalEndUses, propaneTotalEndUses].transpose.map { |t| t.reduce(:+) } - - report_ts_output(runner, timeseries, "total_site_energy_mbtu", totalSiteEnergy, "GJ", total_site_units) - report_ts_output(runner, timeseries, "net_site_energy_mbtu", [totalSiteEnergy, modeledCentralElectricityPhotovoltaics].transpose.collect { |e1, e2| e1 - e2 }, "GJ", total_site_units) - - # END USE SUBCATEGORIES - - if include_enduse_subcategories - report_ts_output(runner, timeseries, "electricity_refrigerator_kwh", electricityRefrigerator, "GJ", elec_site_units) - report_ts_output(runner, timeseries, "electricity_clothes_washer_kwh", electricityClothesWasher, "GJ", elec_site_units) - report_ts_output(runner, timeseries, "electricity_clothes_dryer_kwh", electricityClothesDryer, "GJ", elec_site_units) - report_ts_output(runner, timeseries, "natural_gas_clothes_dryer_therm", naturalGasClothesDryer, "GJ", gas_site_units) - report_ts_output(runner, timeseries, "propane_clothes_dryer_mbtu", propaneClothesDryer, "GJ", other_fuel_site_units) - report_ts_output(runner, timeseries, "electricity_cooking_range_kwh", electricityCookingRange, "GJ", elec_site_units) - report_ts_output(runner, timeseries, "natural_gas_cooking_range_therm", naturalGasCookingRange, "GJ", gas_site_units) - report_ts_output(runner, timeseries, "propane_cooking_range_mbtu", propaneCookingRange, "GJ", other_fuel_site_units) - report_ts_output(runner, timeseries, "electricity_dishwasher_kwh", electricityDishwasher, "GJ", elec_site_units) - report_ts_output(runner, timeseries, "electricity_plug_loads_kwh", electricityPlugLoads, "GJ", elec_site_units) - report_ts_output(runner, timeseries, "electricity_house_fan_kwh", electricityHouseFan, "GJ", elec_site_units) - report_ts_output(runner, timeseries, "electricity_range_fan_kwh", electricityRangeFan, "GJ", elec_site_units) - report_ts_output(runner, timeseries, "electricity_bath_fan_kwh", electricityBathFan, "GJ", elec_site_units) - report_ts_output(runner, timeseries, "electricity_ceiling_fan_kwh", electricityCeilingFan, "GJ", elec_site_units) - report_ts_output(runner, timeseries, "electricity_extra_refrigerator_kwh", electricityExtraRefrigerator, "GJ", elec_site_units) - report_ts_output(runner, timeseries, "electricity_freezer_kwh", electricityFreezer, "GJ", elec_site_units) - report_ts_output(runner, timeseries, "electricity_pool_heater_kwh", electricityPoolHeater, "GJ", elec_site_units) - report_ts_output(runner, timeseries, "natural_gas_pool_heater_therm", naturalGasPoolHeater, "GJ", gas_site_units) - report_ts_output(runner, timeseries, "electricity_pool_pump_kwh", electricityPoolPump, "GJ", elec_site_units) - report_ts_output(runner, timeseries, "electricity_hot_tub_heater_kwh", electricityHotTubHeater, "GJ", elec_site_units) - report_ts_output(runner, timeseries, "natural_gas_hot_tub_heater_therm", naturalGasHotTubHeater, "GJ", gas_site_units) - report_ts_output(runner, timeseries, "electricity_hot_tub_pump_kwh", electricityHotTubPump, "GJ", elec_site_units) - report_ts_output(runner, timeseries, "natural_gas_grill_therm", naturalGasGrill, "GJ", gas_site_units) - report_ts_output(runner, timeseries, "natural_gas_lighting_therm", naturalGasLighting, "GJ", gas_site_units) - report_ts_output(runner, timeseries, "natural_gas_fireplace_therm", naturalGasFireplace, "GJ", gas_site_units) - report_ts_output(runner, timeseries, "electricity_well_pump_kwh", electricityWellPump, "GJ", elec_site_units) - report_ts_output(runner, timeseries, "electricity_garage_lighting_kwh", electricityGarageLighting, "GJ", elec_site_units) - report_ts_output(runner, timeseries, "electricity_exterior_holiday_lighting_kwh", electricityExteriorHolidayLighting, "GJ", elec_site_units) - end - - output_vars.each do |output_var| - sqlFile.availableKeyValues(ann_env_pd, reporting_frequency_map[reporting_frequency], output_var).each do |key_value| - request = sqlFile.timeSeries(ann_env_pd, reporting_frequency_map[reporting_frequency], output_var, key_value) - next if request.empty? - - request = request.get - vals = request.values - old_units = request.units - new_units = old_units - if old_units == "C" - new_units = "F" - end - name = "#{output_var.upcase} (#{key_value})" - unless new_units.empty? - name += " [#{new_units}]" - end - report_ts_output(runner, timeseries, name, vals, old_units, new_units) - end - end - - sqlFile.close() - - csv_path = File.expand_path("../enduse_timeseries.csv") - CSV.open(csv_path, "wb") do |csv| - csv << timeseries.keys - rows = timeseries.values.transpose - rows.each do |row| - csv << row - end - end - - return true - end # end the run method - - def report_ts_output(runner, timeseries, name, vals, os_units, desired_units) - timeseries[name] = [] - timeseries["Time"].each_with_index do |ts, i| - timeseries[name] << UnitConversions.convert(vals[i], os_units, desired_units) - end - runner.registerInfo("Exporting #{name}.") - end - - def format_datetime(date_time) - date_time.gsub!("-", "/") - date_time.gsub!("Jan", "01") - date_time.gsub!("Feb", "02") - date_time.gsub!("Mar", "03") - date_time.gsub!("Apr", "04") - date_time.gsub!("May", "05") - date_time.gsub!("Jun", "06") - date_time.gsub!("Jul", "07") - date_time.gsub!("Aug", "08") - date_time.gsub!("Sep", "09") - date_time.gsub!("Oct", "10") - date_time.gsub!("Nov", "11") - date_time.gsub!("Dec", "12") - return date_time - end - - def array_sum(array1, array2, units_represented = 1, num_units = 1) - array = [array1, array2].transpose.collect { |a1, a2| a1 + units_represented * (a2 / num_units) } - return array - end -end - -# register the measure to be used by the application -TimeseriesCSVExport.new.registerWithApplication From f4a41cf7aa5395c18502743d07fc6ac90ddd724b Mon Sep 17 00:00:00 2001 From: Joe Robertson Date: Fri, 20 Sep 2019 11:56:40 -0600 Subject: [PATCH 08/11] Check measures exist only for residential. Only check arguments for measures in cfg. --- buildstockbatch/base.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/buildstockbatch/base.py b/buildstockbatch/base.py index 0f174d8a..9a15d98e 100644 --- a/buildstockbatch/base.py +++ b/buildstockbatch/base.py @@ -26,6 +26,7 @@ import zipfile import csv from collections import defaultdict +import xml.etree.ElementTree as ET from buildstockbatch.__version__ import __schema_version__ from .workflow_generator import ResidentialDefaultWorkflowGenerator, CommercialDefaultWorkflowGenerator @@ -338,9 +339,10 @@ def validate_xor_schema_keys(project_file): return True def validate_measures_and_arguments(project_file): - import xml.etree.ElementTree as ET - cfg = BuildStockBatchBase.get_project_configuration(project_file) + if cfg['stock_type'] != 'residential': # FIXME: add comstock logic + return True + buildstock_dir = os.path.join(os.path.dirname(project_file), cfg["buildstock_directory"]) measures_dir = f'{buildstock_dir}/measures' type_map = {'Integer': int, 'Boolean': bool, 'String': str, 'Double': float} @@ -366,10 +368,12 @@ def get_measure_xml(xml_path): for measure_name in measure_names.keys(): measure_path = os.path.join(measures_dir, measure_name) - if measure_names[measure_name] in cfg.keys(): + if measure_names[measure_name] in cfg.keys() or measure_names[measure_name] == 'residential_simulation_controls': + # if they exist in the cfg, make sure they exist in the buildstock checkout if not os.path.exists(measure_path): error_msgs += f"* {measure_name} does not exist in {buildstock_dir}. \n" + # check argument value types for residential simulation controls and timeseries csv export measures if measure_name in ['ResidentialSimulationControls', 'TimeseriesCSVExport']: root = get_measure_xml(os.path.join(measure_path, 'measure.xml')) @@ -385,6 +389,9 @@ def get_measure_xml(xml_path): else: expected_arguments[name.text].append(argument.find('./type').text) + # check only if that measure exists in cfg + if measure_names[measure_name] not in cfg.keys(): + continue for actual_argument_key in cfg[measure_names[measure_name]].keys(): if actual_argument_key not in expected_arguments.keys(): error_msgs += f"* Found unexpected argument key {actual_argument_key} for \ From 1bef4340adea6be7dbdd4a069f2fd972efac4468 Mon Sep 17 00:00:00 2001 From: Joe Robertson Date: Fri, 20 Sep 2019 11:57:39 -0600 Subject: [PATCH 09/11] Update good yml test by removing sim controls measure. --- .../test/test_inputs/enforce-validate-measures-good-2.yml | 7 ------- 1 file changed, 7 deletions(-) diff --git a/buildstockbatch/test/test_inputs/enforce-validate-measures-good-2.yml b/buildstockbatch/test/test_inputs/enforce-validate-measures-good-2.yml index edc5bd12..03102098 100644 --- a/buildstockbatch/test/test_inputs/enforce-validate-measures-good-2.yml +++ b/buildstockbatch/test/test_inputs/enforce-validate-measures-good-2.yml @@ -3,13 +3,6 @@ project_directory: project_singlefamilydetached baseline: n_datapoints: 30 n_buildings_represented: 81221016 -residential_simulation_controls: - timesteps_per_hr: 4 - begin_month: 1 - begin_day_of_month: 1 - end_month: 12 - end_day_of_month: 31 - calendar_year: 2016 upgrades: - upgrade_name: good upgrade options: From 603cc68fb3182b935575b9c0d06116c10a9ff558 Mon Sep 17 00:00:00 2001 From: Joe Robertson Date: Fri, 20 Sep 2019 12:04:40 -0600 Subject: [PATCH 10/11] Add required stock type to measures exist yml test files. --- .../test/test_inputs/enforce-validate-measures-bad-2.yml | 1 + .../test/test_inputs/enforce-validate-measures-good-2.yml | 1 + 2 files changed, 2 insertions(+) diff --git a/buildstockbatch/test/test_inputs/enforce-validate-measures-bad-2.yml b/buildstockbatch/test/test_inputs/enforce-validate-measures-bad-2.yml index 366e8f22..0abf7821 100644 --- a/buildstockbatch/test/test_inputs/enforce-validate-measures-bad-2.yml +++ b/buildstockbatch/test/test_inputs/enforce-validate-measures-bad-2.yml @@ -1,3 +1,4 @@ +stock_type: residential buildstock_directory: test_openstudio_buildstock project_directory: project_singlefamilydetached baseline: diff --git a/buildstockbatch/test/test_inputs/enforce-validate-measures-good-2.yml b/buildstockbatch/test/test_inputs/enforce-validate-measures-good-2.yml index 03102098..47fb56f0 100644 --- a/buildstockbatch/test/test_inputs/enforce-validate-measures-good-2.yml +++ b/buildstockbatch/test/test_inputs/enforce-validate-measures-good-2.yml @@ -1,3 +1,4 @@ +stock_type: residential buildstock_directory: test_openstudio_buildstock project_directory: project_singlefamilydetached baseline: From bd980674605360a43265f0bf50c5263d52159b79 Mon Sep 17 00:00:00 2001 From: Joe Robertson Date: Fri, 20 Sep 2019 12:10:08 -0600 Subject: [PATCH 11/11] Failed style check, line too long. --- buildstockbatch/base.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/buildstockbatch/base.py b/buildstockbatch/base.py index 9a15d98e..53552dc5 100644 --- a/buildstockbatch/base.py +++ b/buildstockbatch/base.py @@ -368,7 +368,8 @@ def get_measure_xml(xml_path): for measure_name in measure_names.keys(): measure_path = os.path.join(measures_dir, measure_name) - if measure_names[measure_name] in cfg.keys() or measure_names[measure_name] == 'residential_simulation_controls': + if measure_names[measure_name] in cfg.keys() or \ + measure_names[measure_name] == 'residential_simulation_controls': # if they exist in the cfg, make sure they exist in the buildstock checkout if not os.path.exists(measure_path): error_msgs += f"* {measure_name} does not exist in {buildstock_dir}. \n"