From 8f6196b2fa723a8326cf5cac6bb0240ec7a9470c Mon Sep 17 00:00:00 2001 From: Alex Lee Date: Mon, 2 Jun 2025 18:26:22 -0400 Subject: [PATCH 1/9] Add src and inputs folders and a sample input file --- inputs/bldg0000072-up00.xml | 1258 +++++++++++++++++++++++++++++++++++ 1 file changed, 1258 insertions(+) create mode 100644 inputs/bldg0000072-up00.xml diff --git a/inputs/bldg0000072-up00.xml b/inputs/bldg0000072-up00.xml new file mode 100644 index 0000000..811fde8 --- /dev/null +++ b/inputs/bldg0000072-up00.xml @@ -0,0 +1,1258 @@ + + + + HPXML + BuildResidentialHPXML + 2024-08-11T08:38:34-06:00 + create + + + ResStock + 3.2.0 + + + 15 + 1 + 1 + 12 + 31 + 2018 + 1.0 + + + + LRMER_LowRECost_15 + CO2e + + electricity + kg/MWh + /lib/resources/data/cambium/2022/LRMER_LowRECost_15/RFCEc.csv + 0 + 1 + + + natural gas + lb/MBtu + 147.3 + + + + LRMER_MidCase_15 + CO2e + + electricity + kg/MWh + /lib/resources/data/cambium/2022/LRMER_MidCase_15/RFCEc.csv + 0 + 1 + + + natural gas + lb/MBtu + 147.3 + + + + LRMER_HighRECost_15 + CO2e + + electricity + kg/MWh + /lib/resources/data/cambium/2022/LRMER_HighRECost_15/RFCEc.csv + 0 + 1 + + + natural gas + lb/MBtu + 147.3 + + + + LRMER_MidCase_25 + CO2e + + electricity + kg/MWh + /lib/resources/data/cambium/2022/LRMER_MidCase_25/RFCEc.csv + 0 + 1 + + + natural gas + lb/MBtu + 147.3 + + + + + + Utility Rates - Fixed + Variable + + electricity + 12.0 + 0.15102236286919832 + + + natural gas + 11.25 + 0.827375004 + + + propane + 0.0 + 3.440384615 + + + fuel oil + 0.0 + 3.247884615 + + + + + + + + + +
+ NJ + 07960 +
+ + -5.0 + true + + 3 + 12 + 11 + 5 + + +
+ + proposed workscope + + + + + suburban + stand-alone + no units above or below + normal + 225 + + 1.1 + + 0.02288 + + + + + + northwest + 315 + 15.0 + + + southeast + 135 + 15.0 + + + + + + 2.0 + + 0.061, 0.061, 0.061, 0.061, 0.061, 0.061, 0.061, 0.053, 0.025, 0.015, 0.015, 0.015, 0.015, 0.015, 0.015, 0.015, 0.018, 0.033, 0.054, 0.054, 0.054, 0.061, 0.061, 0.061 + 0.061, 0.061, 0.061, 0.061, 0.061, 0.061, 0.061, 0.053, 0.025, 0.015, 0.015, 0.015, 0.015, 0.015, 0.015, 0.015, 0.018, 0.033, 0.054, 0.054, 0.054, 0.061, 0.061, 0.061 + 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0 + + + + 1940 + single-family detached + 1 + 1.0 + 1.0 + 8.0 + 4 + 2 + 1228.0 + 9824.0 + + + + ACCA + false + + 14.54 + 89.78 + 70.0 + 75.0 + 0.5 + 2400.0 + 0.0 + 5 + + + 3 + + 5 + 1 + 9 + 30 + + + 38 + + /var/simdata/openstudio/run/schedules.csv + + + + + 2006 + 5A + + + + G3400270 + + ../../../weather/G3400270.epw + + + + + + + + 50.0 + + ACH + 30.0 + + 9824.0 + 8.0 + + + false + + + + + + + + true + + + + SLA + 0.003333 + + + + + + + + + + + + + + true + + + + SLA + 0.006667 + + + + + + + + + + + + + + + + + attic - vented + 686.5 + northeast + 45 + asphalt or fiberglass shingles + medium + 0.85 + 0.9 + + none + + 6.0 + false + + + 2.3 + + + + + attic - vented + 686.5 + southwest + 225 + asphalt or fiberglass shingles + medium + 0.85 + 0.9 + + none + + 6.0 + false + + + 2.3 + + + + + + + outside + crawlspace - vented + 36.2 + northeast + 45 + vinyl siding + light + 0.5 + 0.9 + + + 3.1 + + + + + outside + crawlspace - vented + 20.1 + southeast + 135 + vinyl siding + light + 0.5 + 0.9 + + + 3.1 + + + + + outside + crawlspace - vented + 36.2 + southwest + 225 + vinyl siding + light + 0.5 + 0.9 + + + 3.1 + + + + + outside + crawlspace - vented + 20.1 + northwest + 315 + vinyl siding + light + 0.5 + 0.9 + + + 3.1 + + + + + + + outside + conditioned space + + + + 376.1 + northeast + 45 + vinyl siding + light + 0.5 + 0.9 + + gypsum board + 0.5 + + false + + + 4.0 + + + + + outside + conditioned space + + + + 209.0 + southeast + 135 + vinyl siding + light + 0.5 + 0.9 + + gypsum board + 0.5 + + false + + + 4.0 + + + + + outside + conditioned space + + + + 376.1 + southwest + 225 + vinyl siding + light + 0.5 + 0.9 + + gypsum board + 0.5 + + false + + + 4.0 + + + + + outside + conditioned space + + + + 209.0 + northwest + 315 + vinyl siding + light + 0.5 + 0.9 + + gypsum board + 0.5 + + false + + + 4.0 + + + + + outside + attic - vented + gable + + + + 85.3 + southeast + 135 + vinyl siding + light + 0.5 + 0.9 + + none + + false + + + 4.0 + + + + + outside + attic - vented + gable + + + + 85.3 + northwest + 315 + vinyl siding + light + 0.5 + 0.9 + + none + + false + + + 4.0 + + + + + + + ground + crawlspace - vented + solid concrete + 4.0 + 188.1 + northeast + 45 + 8.0 + 3.0 + + none + + + + + continuous - exterior + 0.0 + 0.0 + 4.0 + + + continuous - interior + 0.0 + 0.0 + 4.0 + + + + + + ground + crawlspace - vented + solid concrete + 4.0 + 104.5 + southeast + 135 + 8.0 + 3.0 + + none + + + + + continuous - exterior + 0.0 + 0.0 + 4.0 + + + continuous - interior + 0.0 + 0.0 + 4.0 + + + + + + ground + crawlspace - vented + solid concrete + 4.0 + 188.1 + southwest + 225 + 8.0 + 3.0 + + none + + + + + continuous - exterior + 0.0 + 0.0 + 4.0 + + + continuous - interior + 0.0 + 0.0 + 4.0 + + + + + + ground + crawlspace - vented + solid concrete + 4.0 + 104.5 + northwest + 315 + 8.0 + 3.0 + + none + + + + + continuous - exterior + 0.0 + 0.0 + 4.0 + + + continuous - interior + 0.0 + 0.0 + 4.0 + + + + + + + + crawlspace - vented + conditioned space + floor + + + + 1228.0 + + none + + false + + + 5.3 + + + + + attic - vented + conditioned space + ceiling + + + + 1228.0 + + gypsum board + 0.5 + + false + + + 39.6 + + + + + + + crawlspace - vented + 1228.0 + 0.0 + 146.3 + + + + 0.0 + 0.0 + + + + + + 0.0 + 0.0 + + + + 0.0 + 0.0 + + + + + + + 112.8 + 45 + northeast + 0.38 + 0.44 + + + 1.0 + 1.0 + + + + 0.7 + 0.85 + + + 2.0 + 1.0000000000000009 + 4.9 + + 0.67 + + + + + 62.7 + 135 + southeast + 0.38 + 0.44 + + + 1.0 + 1.0 + + + + 0.7 + 0.85 + + + 2.0 + 1.0000000000000009 + 4.7 + + 0.67 + + + + + 112.8 + 225 + southwest + 0.38 + 0.44 + + + 1.0 + 1.0 + + + + 0.7 + 0.85 + + + 2.0 + 1.0000000000000009 + 4.9 + + 0.67 + + + + + 62.7 + 315 + northwest + 0.38 + 0.44 + + + 1.0 + 1.0 + + + + 0.7 + 0.85 + + + 2.0 + 1.0000000000000009 + 4.7 + + 0.67 + + + + + + + + 20.0 + 225 + southwest + 5.0 + + + + + 1.0 + + gypsum board + 0.5 + + + + 0.4 + light-weight + + + + + + + + + + + + + crawlspace - vented + + + + false + + + natural gas + 66458.0 + + AFUE + 0.8 + + 1.0 + + 0.5 + 0.0 + 1209.0 + + + + + crawlspace - vented + + central air conditioner + electricity + 34552.0 + single stage + 1.0 + + SEER + 13.0 + + 0.73 + + 0.0 + 0.0 + 0.5 + 1167.0 + 50.0 + + + + + + 66458.0 + 17699.0 + 7397.0 + 0.0 + 222.0 + 11081.0 + 0.0 + 6780.0 + 0.0 + 1720.0 + 21559.0 + + + 26949.0 + 4953.0 + 8492.0 + 0.0 + 103.0 + 3892.0 + 0.0 + 1807.0 + 0.0 + 1234.0 + 2918.0 + 3550.0 + + + 6215.0 + 937.0 + 4277.0 + 1000.0 + + + + + + + + 1 + 1 + 12 + 31 + + + 1 + 1 + 12 + 31 + + + 0.0 + 68.0, 68.0, 68.0, 68.0, 68.0, 68.0, 68.0, 68.0, 68.0, 68.0, 68.0, 68.0, 68.0, 68.0, 68.0, 68.0, 68.0, 68.0, 68.0, 68.0, 68.0, 68.0, 68.0, 68.0 + 68.0, 68.0, 68.0, 68.0, 68.0, 68.0, 68.0, 68.0, 68.0, 68.0, 68.0, 68.0, 68.0, 68.0, 68.0, 68.0, 68.0, 68.0, 68.0, 68.0, 68.0, 68.0, 68.0, 68.0 + 68.0, 68.0, 68.0, 68.0, 68.0, 68.0, 68.0, 68.0, 68.0, 68.0, 68.0, 68.0, 68.0, 68.0, 68.0, 68.0, 68.0, 68.0, 68.0, 68.0, 68.0, 68.0, 68.0, 68.0 + 68.0, 68.0, 68.0, 68.0, 68.0, 68.0, 68.0, 68.0, 68.0, 68.0, 68.0, 68.0, 68.0, 68.0, 68.0, 68.0, 68.0, 68.0, 68.0, 68.0, 68.0, 68.0, 68.0, 68.0 + + + + + + + regular velocity + + supply + + Percent + 0.067 + to outside + + + + return + + Percent + 0.033 + to outside + + + + + supply + 0.0 + not buried + 1.7 + crawlspace - vented + 1.0 + 331.56 + + 1.0 + + + + + return + 0.0 + not buried + 1.7 + crawlspace - vented + 1.0 + 61.400000000000006 + + 1.0 + + + 1 + + + 1228.0 + + + + + + + 1 + 100.0 + 1.0 + kitchen + true + 30.0 + + 16 + + + + + 2 + 50.0 + 1.0 + bath + true + 15.0 + + 17 + + + + + + + + natural gas + instantaneous water heater + conditioned space + false + 0.92 + 1.0 + 0.82 + 125.0 + + + + + + 80.08566187174092 + + + + 0.0 + + + + + shower head + false + + + + faucet + false + + + 0.5 + 0.012, 0.006, 0.004, 0.005, 0.010, 0.034, 0.078, 0.087, 0.080, 0.067, 0.056, 0.047, 0.040, 0.035, 0.033, 0.031, 0.039, 0.051, 0.060, 0.060, 0.055, 0.048, 0.038, 0.026 + 0.012, 0.006, 0.004, 0.005, 0.010, 0.034, 0.078, 0.087, 0.080, 0.067, 0.056, 0.047, 0.040, 0.035, 0.033, 0.031, 0.039, 0.051, 0.060, 0.060, 0.055, 0.048, 0.038, 0.026 + 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0 + + + + + + + false + conditioned space + 2.07 + 123.0 + 0.1065 + 1.218 + 9.0 + 7.538462 + 3.68 + + 0.8 + 0.009, 0.007, 0.004, 0.004, 0.007, 0.011, 0.022, 0.049, 0.073, 0.086, 0.084, 0.075, 0.067, 0.060, 0.049, 0.052, 0.050, 0.049, 0.049, 0.049, 0.049, 0.047, 0.032, 0.017 + 0.009, 0.007, 0.004, 0.004, 0.007, 0.011, 0.022, 0.049, 0.073, 0.086, 0.084, 0.075, 0.067, 0.060, 0.049, 0.052, 0.050, 0.049, 0.049, 0.049, 0.049, 0.047, 0.032, 0.017 + 1.011, 1.002, 1.022, 1.020, 1.022, 0.996, 0.999, 0.999, 0.996, 0.964, 0.959, 1.011 + + + + + false + conditioned space + natural gas + 2.39 + true + 100.0 + + 0.8 + 0.010, 0.006, 0.004, 0.002, 0.004, 0.006, 0.016, 0.032, 0.048, 0.068, 0.078, 0.081, 0.074, 0.067, 0.057, 0.061, 0.055, 0.054, 0.051, 0.051, 0.052, 0.054, 0.044, 0.024 + 0.010, 0.006, 0.004, 0.002, 0.004, 0.006, 0.016, 0.032, 0.048, 0.068, 0.078, 0.081, 0.074, 0.067, 0.057, 0.061, 0.055, 0.054, 0.051, 0.051, 0.052, 0.054, 0.044, 0.024 + 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0 + + + + + false + conditioned space + 290.0 + 12 + 0.12 + 1.09 + 23.0 + 4.0 + + 0.8 + 0.015, 0.007, 0.005, 0.003, 0.003, 0.010, 0.020, 0.031, 0.058, 0.065, 0.056, 0.048, 0.041, 0.046, 0.036, 0.038, 0.038, 0.049, 0.087, 0.111, 0.090, 0.067, 0.044, 0.031 + 0.015, 0.007, 0.005, 0.003, 0.003, 0.010, 0.020, 0.031, 0.058, 0.065, 0.056, 0.048, 0.041, 0.046, 0.036, 0.038, 0.038, 0.049, 0.087, 0.111, 0.090, 0.067, 0.044, 0.031 + 1.097, 1.097, 0.991, 0.987, 0.991, 0.890, 0.896, 0.896, 0.890, 1.085, 1.085, 1.097 + + + + + conditioned space + 433.0 + true + + 0.95 + 0.040, 0.039, 0.038, 0.037, 0.036, 0.036, 0.038, 0.040, 0.041, 0.041, 0.040, 0.040, 0.042, 0.042, 0.042, 0.041, 0.044, 0.048, 0.050, 0.048, 0.047, 0.046, 0.044, 0.041 + 0.040, 0.039, 0.038, 0.037, 0.036, 0.036, 0.038, 0.040, 0.041, 0.041, 0.040, 0.040, 0.042, 0.042, 0.042, 0.041, 0.044, 0.048, 0.050, 0.048, 0.047, 0.046, 0.044, 0.041 + 0.837, 0.835, 1.084, 1.084, 1.084, 1.096, 1.096, 1.096, 1.096, 0.931, 0.925, 0.837 + + + + + conditioned space + natural gas + false + + 0.8 + 0.007, 0.007, 0.004, 0.004, 0.007, 0.011, 0.025, 0.042, 0.046, 0.048, 0.042, 0.050, 0.057, 0.046, 0.057, 0.044, 0.092, 0.150, 0.117, 0.060, 0.035, 0.025, 0.016, 0.011 + 0.007, 0.007, 0.004, 0.004, 0.007, 0.011, 0.025, 0.042, 0.046, 0.048, 0.042, 0.050, 0.057, 0.046, 0.057, 0.044, 0.092, 0.150, 0.117, 0.060, 0.035, 0.025, 0.016, 0.011 + 1.097, 1.097, 0.991, 0.987, 0.991, 0.890, 0.896, 0.896, 0.890, 1.085, 1.085, 1.097 + + + + + false + + + + + + interior + 0.0 + + + + + + + interior + 0.0 + + + + + + + interior + 1.0 + + + + + + + exterior + 0.0 + + + + + + + exterior + 0.0 + + + + + + + exterior + 1.0 + + + + + + + + medium + 70.4 + + 1 + + 0.057, 0.057, 0.057, 0.057, 0.057, 0.057, 0.057, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.057, 0.057, 0.057, 0.057, 0.057, 0.057 + 0.057, 0.057, 0.057, 0.057, 0.057, 0.057, 0.057, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.057, 0.057, 0.057, 0.057, 0.057, 0.057 + 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0 + + + + 1.0 + 1.0 + 1.0 + 0.046, 0.046, 0.046, 0.046, 0.046, 0.037, 0.035, 0.034, 0.033, 0.028, 0.022, 0.015, 0.012, 0.011, 0.011, 0.012, 0.019, 0.037, 0.049, 0.065, 0.091, 0.105, 0.091, 0.063 + 0.046, 0.046, 0.045, 0.045, 0.046, 0.045, 0.044, 0.041, 0.036, 0.03, 0.024, 0.016, 0.012, 0.011, 0.011, 0.012, 0.019, 0.038, 0.048, 0.06, 0.083, 0.098, 0.085, 0.059 + 1.248, 1.257, 0.993, 0.989, 0.993, 0.827, 0.821, 0.821, 0.827, 0.99, 0.987, 1.248 + + + + + + other + + kWh/year + 2109.23 + + + 0.93 + 0.021 + 0.505 + 0.035, 0.033, 0.032, 0.031, 0.032, 0.033, 0.037, 0.042, 0.043, 0.043, 0.043, 0.044, 0.045, 0.045, 0.044, 0.046, 0.048, 0.052, 0.053, 0.05, 0.047, 0.045, 0.04, 0.036 + 0.035, 0.033, 0.032, 0.031, 0.032, 0.033, 0.037, 0.042, 0.043, 0.043, 0.043, 0.044, 0.045, 0.045, 0.044, 0.046, 0.048, 0.052, 0.053, 0.05, 0.047, 0.045, 0.04, 0.036 + 1.248, 1.257, 0.993, 0.989, 0.993, 0.827, 0.821, 0.821, 0.827, 0.99, 0.987, 1.248 + + + + +
+
\ No newline at end of file From 4c21cb43875eb5176361603cc5071a49a691c9fd Mon Sep 17 00:00:00 2001 From: Alex Lee Date: Mon, 2 Jun 2025 18:30:35 -0400 Subject: [PATCH 2/9] Add baseline ochre script --- src/run_baseline.py | 121 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 121 insertions(+) create mode 100644 src/run_baseline.py diff --git a/src/run_baseline.py b/src/run_baseline.py new file mode 100644 index 0000000..e65e244 --- /dev/null +++ b/src/run_baseline.py @@ -0,0 +1,121 @@ +import os +import sys +import xmltodict +import click +import pandas as pd +from datetime import datetime, timedelta +import shutil +from ochre import Dwelling +from constants import dict_sim_params + +""" +Code for running simulations on OCHRE. + +Author: Alex Lee (alexlee5124@gmail.com) +Date: 4/19/2025 + +""" + + +# Set up input arguments for dwelling +HOUSE_DEFAULT_ARGS = { +# Timing parameters +'start_time': dict_sim_params['start_time'], +'time_res': dict_sim_params['time_step'], +'duration': dict_sim_params['duration'], +'initialization_time': timedelta(days=7), +'ext_time_res': dict_sim_params['freq_hems'], #HEMS model aggregates data to this timestep. Should be greater than house frequency + +# Output settings +'save_results': True, +'output_path': dict_sim_params['baseline_output_path'], +'verbosity': 9, # verbosity of results file (0-9); 8: include envelope; 9: include water heater +'metrics_verbosity': 7, +} + +# Function for extracting weather station name from an HPXML file +def extract_weather_station(file_path): + try: + with open(file_path, 'r', encoding='utf-8') as file: + buildingXML = xmltodict.parse(file.read()) + weather_station_name = buildingXML['HPXML']['Building']['BuildingDetails']['ClimateandRiskZones']['WeatherStation']['Name'] + except Exception as e: + print(f"Error parsing XML {file_path}: {e}") + + return weather_station_name + +def remove_directory(path): + if os.path.exists(path): + try: + shutil.rmtree(path) + except Exception as e: + print(f"Error deleting {path}: {e}") + else: + print(f"The filepath does not exist: {path}") + +@click.command() +@click.argument('building_id', type=int) +@click.argument('upgrade_id', type=int) +def simulate_dwelling( + building_id:int, + upgrade_id:int + ): + """ + simulate: This function runs an OCHRE simulation for a building. It filters the building by the + building id, upgrade id, state, year, and version of the building XML file. You need to have already + downloaded the building XML file prior to running this function. + + Input simulation parameters, such as duration, start date, simulation timestep size, etc. + + Author: Alex Lee (alexlee5124@gmail.com) + Date: 3/29/2025 + """ + + # Update dwelling arguments + house_id = f"bldg{building_id:07}-up{upgrade_id:02}" + house_args = HOUSE_DEFAULT_ARGS.copy() + house_row = dict_sim_params['df_house_args'].loc[house_id] + house_args.update(house_row) + house_args['name'] = f"bldg{building_id:07}-up{upgrade_id:02}" + + # Update input files + # HPXML file + house_args['hpxml_file'] = os.path.join( + dict_sim_params['ochre_input_path'], + dict_sim_params['location'], + house_id, + house_args['hpxml_file'] + ) + if not os.path.exists(house_args['hpxml_file']): + print(f"HPXML file does not exist: {house_args['hpxml_file']}") + sys.exit(1) + + # Schedule file + house_args['hpxml_schedule_file'] = os.path.join( + dict_sim_params['ochre_input_path'], + dict_sim_params['location'], + house_id, + house_args['hpxml_schedule_file'] + ) + if not os.path.exists(house_args['hpxml_schedule_file']): + print(f"HPXML file does not exist: {house_args['hpxml_schedule_file']}") + sys.exit(1) + # Weather File + house_args['weather_file'] = os.path.join( + dict_sim_params['ochre_input_path'], + dict_sim_params['location'], + house_id, + house_args['weather_file'] + ) + if not os.path.exists(house_args['weather_file']): + print(f"HPXML file does not exist: {house_args['weather_file']}") + sys.exit(1) + + try: + dwelling = Dwelling(**house_args) + dwelling.simulate() + except Exception as e: + print(f"Simulation failed for bldg{building_id:07}-up{upgrade_id:02}: {e}") + +if __name__ == '__main__': + simulate_dwelling() \ No newline at end of file From 92c7ee348f246e77447a9153d62b623961dcd5c2 Mon Sep 17 00:00:00 2001 From: Alex Lee Date: Mon, 2 Jun 2025 18:31:37 -0400 Subject: [PATCH 3/9] Add constants file --- constants.py | 123 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 123 insertions(+) create mode 100644 constants.py diff --git a/constants.py b/constants.py new file mode 100644 index 0000000..a69fb64 --- /dev/null +++ b/constants.py @@ -0,0 +1,123 @@ +import os +import pandas as pd +from datetime import datetime, timedelta +from calendar import month_abbr + + +base_path = os.path.abspath(os.path.join(os.path.dirname(__file__))) + +def str_to_bool(val, default=False): + if isinstance(val, str) and (val in os.environ): + return True if os.environ[val] == 'True' else False + else: + return default + +# Scenario setup +location = 'NY' +multi_home_sim = False # whether doing cosim on more than 1 home +if not multi_home_sim: + house_number = 1 + house_number_list = None + scenario_name = location + '_house_' + str(house_number) +else: + house_number = None + house_number_list = [1] + scenario_name = location + '_multi_home_sim' + + +# COsim date range, and timestep +year = 2007 +month = "Aug" # enumeration Jan, May, or Aug +month_num = list(month_abbr).index(month) +start_date = 25 +start_time = datetime(year, month_num, start_date, 0, 0) # (Year, Month, Day, Hour, Min) +duration = timedelta(days=7) +time_step = timedelta(minutes = 1) +end_time = start_time + duration +sim_times = pd.date_range(start=start_time, end=end_time, freq=time_step)[:-1] # timestamps of cosim + + +# What Agents are included? Agents for ochre house model and hems +include_house = True +include_hems = True + +# Frequency of Updates +freq_house = timedelta(minutes=1) +freq_hems = timedelta(minutes=15) #HEMS model aggregates data to this timestep. Should be greater than house frequency +freq_save_results = timedelta(minutes=5) + +# Time offsets for communication order +offset_house_run = timedelta(seconds=0) +offset_hems_to_house = timedelta(seconds=60) +offset_house_to_hems = timedelta(seconds=60) +offset_save_results = timedelta(0) + +# House Variables +house_battery_schedule = 'TOU' + +# HEMS Variables +hems_scenario = 'foresee' +hems_horizon = timedelta(hours=12) # 12 hours / 15 min frequency = 180 time steps + +# Input/Output file paths +input_path = os.path.join(base_path, "inputs") +output_path = os.path.join(base_path, "outputs") +baseline_output_path = os.path.join(base_path, "outputs", location) + +ochre_input_path = os.path.join(input_path, "ochre") +foresee_input_path = os.path.join(input_path, "foresee") + + +house_args_file_name = location + '_houses.xlsx' +house_args_file = os.path.join(input_path, 'house_args', house_args_file_name) + +# Output file locations +house_results_path = os.path.join(output_path, location, 'ochre') +house_results_file = os.path.join(house_results_path, '{}_out.csv') +hems_results_path = os.path.join(output_path, location, 'foresee') + +# Load house args spread sheed +df_house_args = pd.read_excel(house_args_file, skiprows= 1, index_col='Bldg_ID') +if not multi_home_sim: + house_id = 'house_' + str(house_number) +in_real_time = str_to_bool(['REAL_TIME']) +debug = False + +#store all sim parameters in dictionary +dict_sim_params = { + 'base_path': base_path, + 'in_real_time': in_real_time, + 'debug': debug, + 'location': location, + 'multi_home_sim': multi_home_sim, + 'house_number': house_number, + 'house_number_list': house_number_list, + 'scenario_name': scenario_name, + 'month': month, + 'start_time': start_time, + 'end_time': end_time, + 'duration': duration, + 'time_step': time_step, + 'sim_times': sim_times, + 'include_house': include_house, + 'include_hems': include_hems, + 'freq_house': freq_house, + 'freq_hems': freq_hems, + 'freq_save_results': freq_save_results, + 'offset_house_run': offset_house_run, + 'offset_hems_to_house': offset_hems_to_house, + 'offset_house_to_hems': offset_house_to_hems, + 'offset_save_results': offset_save_results, + 'house_battery_schedule': house_battery_schedule, + 'hems_scenario': hems_scenario, + 'hems_horizon': hems_horizon, + 'input_path': input_path, + 'output_path': output_path, + 'baseline_output_path': baseline_output_path, + 'ochre_input_path': ochre_input_path, + 'foresee_input_path': foresee_input_path, + 'house_results_path': house_results_path, + 'house_results_file': house_results_file, + 'hems_results_path': hems_results_path, + 'df_house_args': df_house_args, +} \ No newline at end of file From 8b4ed7676de6a78651ae1e51f1af6706410f5028 Mon Sep 17 00:00:00 2001 From: Alex Lee Date: Mon, 2 Jun 2025 18:50:36 -0400 Subject: [PATCH 4/9] Add run_baseline.py script --- src/run_baseline.py | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/src/run_baseline.py b/src/run_baseline.py index e65e244..b7d361e 100644 --- a/src/run_baseline.py +++ b/src/run_baseline.py @@ -1,5 +1,6 @@ import os import sys +sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))) import xmltodict import click import pandas as pd @@ -82,8 +83,6 @@ def simulate_dwelling( # HPXML file house_args['hpxml_file'] = os.path.join( dict_sim_params['ochre_input_path'], - dict_sim_params['location'], - house_id, house_args['hpxml_file'] ) if not os.path.exists(house_args['hpxml_file']): @@ -93,22 +92,19 @@ def simulate_dwelling( # Schedule file house_args['hpxml_schedule_file'] = os.path.join( dict_sim_params['ochre_input_path'], - dict_sim_params['location'], - house_id, house_args['hpxml_schedule_file'] ) if not os.path.exists(house_args['hpxml_schedule_file']): - print(f"HPXML file does not exist: {house_args['hpxml_schedule_file']}") + print(f"Schedule file does not exist: {house_args['hpxml_schedule_file']}") sys.exit(1) # Weather File + weather_station = f"{extract_weather_station(house_args['hpxml_file'])}.epw" house_args['weather_file'] = os.path.join( dict_sim_params['ochre_input_path'], - dict_sim_params['location'], - house_id, - house_args['weather_file'] + weather_station ) if not os.path.exists(house_args['weather_file']): - print(f"HPXML file does not exist: {house_args['weather_file']}") + print(f"Weather file does not exist: {house_args['weather_file']}") sys.exit(1) try: From 6b7b18ca2c42205d750ff73435178348abb3a7bb Mon Sep 17 00:00:00 2001 From: Alex Lee Date: Sun, 8 Jun 2025 16:13:42 -0400 Subject: [PATCH 5/9] Test running ochre_baseline --- __pycache__/constants.cpython-311.pyc | Bin 0 -> 4533 bytes inputs/house_args/NY_houses.xlsx | Bin 0 -> 12820 bytes inputs/house_args/~$NY_houses.xlsx | Bin 0 -> 165 bytes inputs/{ => ochre}/bldg0000072-up00.xml | 0 outputs/NY/bldg0000072-up00_complete | 0 5 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 __pycache__/constants.cpython-311.pyc create mode 100644 inputs/house_args/NY_houses.xlsx create mode 100644 inputs/house_args/~$NY_houses.xlsx rename inputs/{ => ochre}/bldg0000072-up00.xml (100%) create mode 100644 outputs/NY/bldg0000072-up00_complete diff --git a/__pycache__/constants.cpython-311.pyc b/__pycache__/constants.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8bccd78a65d101e69832a0432df95e3620780651 GIT binary patch literal 4533 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 D{vV`K literal 0 HcmV?d00001 diff --git a/inputs/house_args/NY_houses.xlsx b/inputs/house_args/NY_houses.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..70d109cda70c528b3c47835690055aef9ee6264c GIT binary patch literal 12820 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 literal 0 HcmV?d00001 diff --git a/inputs/house_args/~$NY_houses.xlsx b/inputs/house_args/~$NY_houses.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..df038b45172264438d6cf131c01d830345e79a3d GIT binary patch literal 165 zcmWgiNln#JaLh@qQ1GZM&CAWqQy>NiGWam00-+9r0)rz%4v*L;6-xjB literal 0 HcmV?d00001 diff --git a/inputs/bldg0000072-up00.xml b/inputs/ochre/bldg0000072-up00.xml similarity index 100% rename from inputs/bldg0000072-up00.xml rename to inputs/ochre/bldg0000072-up00.xml diff --git a/outputs/NY/bldg0000072-up00_complete b/outputs/NY/bldg0000072-up00_complete new file mode 100644 index 0000000..e69de29 From 04105e79a3f12aeb62b11828e136af24cc282b71 Mon Sep 17 00:00:00 2001 From: Alex Lee Date: Sun, 8 Jun 2025 16:15:10 -0400 Subject: [PATCH 6/9] Create HP swap file --- src/swap_HP.py | 117 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 117 insertions(+) create mode 100644 src/swap_HP.py diff --git a/src/swap_HP.py b/src/swap_HP.py new file mode 100644 index 0000000..79f3d9e --- /dev/null +++ b/src/swap_HP.py @@ -0,0 +1,117 @@ +import os +import sys +sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))) +import xmltodict +import click +import pandas as pd +from datetime import datetime, timedelta +import shutil +from ochre import Dwelling +from constants import dict_sim_params + +""" +Code for running simulations on OCHRE. + +Author: Alex Lee (alexlee5124@gmail.com) +Date: 4/19/2025 + +""" + + +# Set up input arguments for dwelling +HOUSE_DEFAULT_ARGS = { +# Timing parameters +'start_time': dict_sim_params['start_time'], +'time_res': dict_sim_params['time_step'], +'duration': dict_sim_params['duration'], +'initialization_time': timedelta(days=7), +'ext_time_res': dict_sim_params['freq_hems'], #HEMS model aggregates data to this timestep. Should be greater than house frequency + +# Output settings +'save_results': True, +'output_path': dict_sim_params['baseline_output_path'], +'verbosity': 9, # verbosity of results file (0-9); 8: include envelope; 9: include water heater +'metrics_verbosity': 7, +} + +# Function for extracting weather station name from an HPXML file +def extract_weather_station(file_path): + try: + with open(file_path, 'r', encoding='utf-8') as file: + buildingXML = xmltodict.parse(file.read()) + weather_station_name = buildingXML['HPXML']['Building']['BuildingDetails']['ClimateandRiskZones']['WeatherStation']['Name'] + except Exception as e: + print(f"Error parsing XML {file_path}: {e}") + + return weather_station_name + +def remove_directory(path): + if os.path.exists(path): + try: + shutil.rmtree(path) + except Exception as e: + print(f"Error deleting {path}: {e}") + else: + print(f"The filepath does not exist: {path}") + +@click.command() +@click.argument('building_id', type=int) +@click.argument('upgrade_id', type=int) +def swap_HP( + building_id:int, + upgrade_id:int + ): + """ + simulate: This function runs an OCHRE simulation for a building. It filters the building by the + building id, upgrade id, state, year, and version of the building XML file. You need to have already + downloaded the building XML file prior to running this function. + + Input simulation parameters, such as duration, start date, simulation timestep size, etc. + + Author: Alex Lee (alexlee5124@gmail.com) + Date: 3/29/2025 + """ + + # Update dwelling arguments + house_id = f"bldg{building_id:07}-up{upgrade_id:02}" + house_args = HOUSE_DEFAULT_ARGS.copy() + house_row = dict_sim_params['df_house_args'].loc[house_id] + house_args.update(house_row) + house_args['name'] = f"bldg{building_id:07}-up{upgrade_id:02}" + + # Update input files + # HPXML file + house_args['hpxml_file'] = os.path.join( + dict_sim_params['ochre_input_path'], + house_args['hpxml_file'] + ) + if not os.path.exists(house_args['hpxml_file']): + print(f"HPXML file does not exist: {house_args['hpxml_file']}") + sys.exit(1) + + # Schedule file + house_args['hpxml_schedule_file'] = os.path.join( + dict_sim_params['ochre_input_path'], + house_args['hpxml_schedule_file'] + ) + if not os.path.exists(house_args['hpxml_schedule_file']): + print(f"Schedule file does not exist: {house_args['hpxml_schedule_file']}") + sys.exit(1) + # Weather File + weather_station = f"{extract_weather_station(house_args['hpxml_file'])}.epw" + house_args['weather_file'] = os.path.join( + dict_sim_params['ochre_input_path'], + weather_station + ) + if not os.path.exists(house_args['weather_file']): + print(f"Weather file does not exist: {house_args['weather_file']}") + sys.exit(1) + + try: + dwelling = Dwelling(**house_args) + dwelling.simulate() + except Exception as e: + print(f"Simulation failed for bldg{building_id:07}-up{upgrade_id:02}: {e}") + +if __name__ == '__main__': + swap_HP() \ No newline at end of file From 17fc110420ac8cbc04d9d35039cd2cfe300bd066 Mon Sep 17 00:00:00 2001 From: Alex Lee Date: Sun, 8 Jun 2025 17:57:01 -0400 Subject: [PATCH 7/9] Add HP json files --- src/HP.json | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 src/HP.json diff --git a/src/HP.json b/src/HP.json new file mode 100644 index 0000000..1b558f0 --- /dev/null +++ b/src/HP.json @@ -0,0 +1,67 @@ +{ + "ASHP": [ + { + "id": 1, + "fuel_type": "electricity", + "cooling_capacity": 40000, + "heating_capacity": 40000, + "fraction_heating_load_served": 1, + "fraction_cooling_load_served": 1, + "annual_cooling_efficiency_units": "SEER", + "annual_cooling_efficiency": 16.0, + "annual_heating_efficiency_units": "HSPF", + "annual_heating_efficiency": 9.2, + "heat_pump_type": "air-to-air", + "compressor_type": "variable speed", + "sensible_heat_ratio": 0.78, + "fan_power_Watts_per_CFM": 0.375, + "backup_heat_fuel_type": "electricity", + "backup_heat_efficiency": 1, + "backup_heat_capacity": 30000, + "compressor_lockout_temperature": 0, + "backupt_heat_lockout_temperature": 40 + }, + { + "id": 2, + "fuel_type": "electricity", + "cooling_capacity": 40000, + "heating_capacity": 40000, + "fraction_heating_load_served": 1, + "fraction_cooling_load_served": 1, + "annual_cooling_efficiency_units": "SEER", + "annual_cooling_efficiency": 16.0, + "annual_heating_efficiency_units": "HSPF", + "annual_heating_efficiency": 9.2, + "heat_pump_type": "air-to-air", + "compressor_type": "variable speed", + "sensible_heat_ratio": 0.78, + "fan_power_Watts_per_CFM": 0.375, + "backup_heat_fuel_type": "electricity", + "backup_heat_efficiency": 1, + "backup_heat_capacity": 30000, + "compressor_lockout_temperature": 0, + "backupt_heat_lockout_temperature": 40 + }, + { + "id": 3, + "fuel_type": "electricity", + "cooling_capacity": 40000, + "heating_capacity": 40000, + "fraction_heating_load_served": 1, + "fraction_cooling_load_served": 1, + "annual_cooling_efficiency_units": "SEER", + "annual_cooling_efficiency": 16.0, + "annual_heating_efficiency_units": "HSPF", + "annual_heating_efficiency": 9.2, + "heat_pump_type": "air-to-air", + "compressor_type": "variable speed", + "sensible_heat_ratio": 0.78, + "fan_power_Watts_per_CFM": 0.375, + "backup_heat_fuel_type": "electricity", + "backup_heat_efficiency": 1, + "backup_heat_capacity": 30000, + "compressor_lockout_temperature": 0, + "backupt_heat_lockout_temperature": 40 + } + ] +} From 267280709e7a9b89062d426bf68b6f680d3b6591 Mon Sep 17 00:00:00 2001 From: Alex Lee Date: Sun, 8 Jun 2025 19:34:24 -0400 Subject: [PATCH 8/9] Add create HP method --- outputs/NY/bldg0000072-up00_complete | 0 src/swap_HP.py | 76 ++++++++++++++++++++++++++-- 2 files changed, 73 insertions(+), 3 deletions(-) delete mode 100644 outputs/NY/bldg0000072-up00_complete diff --git a/outputs/NY/bldg0000072-up00_complete b/outputs/NY/bldg0000072-up00_complete deleted file mode 100644 index e69de29..0000000 diff --git a/src/swap_HP.py b/src/swap_HP.py index 79f3d9e..4221cd0 100644 --- a/src/swap_HP.py +++ b/src/swap_HP.py @@ -8,7 +8,8 @@ import shutil from ochre import Dwelling from constants import dict_sim_params - +import json +from ochre.utils import convert, OCHREException """ Code for running simulations on OCHRE. @@ -54,12 +55,81 @@ def remove_directory(path): else: print(f"The filepath does not exist: {path}") +def get_HP_info(HP_id:int): + with open('HP.json', 'r') as file: + HP_info = json.load(file) + return HP_info[HP_id] + +def create_HP_equipment(HP_info:dict, hvac_type:str): + name = HP_info['heat_pump_type'] + fuel = HP_info['fuel_type'] + capacity = HP_info[f'{hvac_type.lower()}_capacity'] + space_fraction = HP_info[f'fraction_{hvac_type.lower()}_load_served'] + efficiency = HP_info[f'annual_{hvac_type.lower()}_efficiency'] + efficiency_string = (f"{HP_info[f'annual_{hvac_type.lower()}_efficiency']} " + f"{HP_info[f'annual_{hvac_type.lower()}_efficiency_units']}") + if HP_info[f'annual_{hvac_type.lower()}_efficiency_units'] in ['Percent', 'AFUE']: + eir = 1 / efficiency + if HP_info[f'annual_{hvac_type.lower()}_efficiency_units'] == 'Percent': + efficiency *= 100 + elif HP_info[f'annual_{hvac_type.lower()}_efficiency_units'] in ['EER', 'SEER', 'HSPF']: + eir = 1 / convert(efficiency, 'Btu/hour', 'W') + else: + raise OCHREException(f'Unknown inputs for HVAC {hvac_type} efficiency: {efficiency}') + + # Get number of speeds + speed_options = { + 'single stage': 1, + 'two stage': 2, + 'variable speed': 4, + } + if name == 'mini-split': + number_of_speeds = 4 # MSHP always variable speed + elif HP_info['compressor_type'] in speed_options: + number_of_speeds = speed_options[HP_info['compressor_type']] + elif convert(1 / eir, 'W', 'Btu/hour') <= 15: + number_of_speeds = 1 # Single-speed for SEER <= 15 + elif convert(1 / eir, 'W', 'Btu/hour') <= 21: + number_of_speeds = 2 # Two-speed for 15 < SEER <= 21 + else: + number_of_speeds = 4 # Variable speed for SEER > 21 + + is_heater = hvac_type == 'Heating' + if is_heater: + shr = None + else: + shr = HP_info['sensible_heat_ratio'] + + if "fan_power_Watts_per_CFM" in HP_info: + # Note: air flow rate is only used for non-dymanic HVAC models with fans, e.g., furnaces + # airflow_cfm = hvac_ext.get(f'{hvac_type}AirflowCFM', 0) + cfm_per_ton = 350 if is_heater else 312 + power_per_cfm = HP_info["fan_power_Watts_per_CFM"] + aux_power = power_per_cfm * cfm_per_ton * convert(capacity, 'W', 'refrigeration_ton') + + HP = { + 'Equipment Name': name, + 'Fuel': fuel.capitalize(), + 'Capacity (W)': capacity, + 'EIR (-)': eir, + 'Rated Efficiency': efficiency_string, + 'SHR (-)': shr, + 'Conditioned Space Fraction (-)': space_fraction, + 'Number of Speeds (-)': number_of_speeds, + 'Rated Auxiliary Power (W)': aux_power, + } + + return HP + + @click.command() @click.argument('building_id', type=int) @click.argument('upgrade_id', type=int) +@click.argument('hp_id', type=int) def swap_HP( building_id:int, - upgrade_id:int + upgrade_id:int, + hp_id:int ): """ simulate: This function runs an OCHRE simulation for a building. It filters the building by the @@ -109,7 +179,7 @@ def swap_HP( try: dwelling = Dwelling(**house_args) - dwelling.simulate() + print(dwelling.equipment['Air Conditioner']) except Exception as e: print(f"Simulation failed for bldg{building_id:07}-up{upgrade_id:02}: {e}") From 68dfe531463325df1d1188c666fe4159f2f2556d Mon Sep 17 00:00:00 2001 From: Alex Lee Date: Sun, 8 Jun 2025 20:17:52 -0400 Subject: [PATCH 9/9] WIP add logic for changing to HP --- outputs/NY/bldg0000072-up00_complete | 0 src/HP.json | 67 ---------------------------- src/swap_HP.py | 43 +++++++++++++++--- 3 files changed, 38 insertions(+), 72 deletions(-) create mode 100644 outputs/NY/bldg0000072-up00_complete delete mode 100644 src/HP.json diff --git a/outputs/NY/bldg0000072-up00_complete b/outputs/NY/bldg0000072-up00_complete new file mode 100644 index 0000000..e69de29 diff --git a/src/HP.json b/src/HP.json deleted file mode 100644 index 1b558f0..0000000 --- a/src/HP.json +++ /dev/null @@ -1,67 +0,0 @@ -{ - "ASHP": [ - { - "id": 1, - "fuel_type": "electricity", - "cooling_capacity": 40000, - "heating_capacity": 40000, - "fraction_heating_load_served": 1, - "fraction_cooling_load_served": 1, - "annual_cooling_efficiency_units": "SEER", - "annual_cooling_efficiency": 16.0, - "annual_heating_efficiency_units": "HSPF", - "annual_heating_efficiency": 9.2, - "heat_pump_type": "air-to-air", - "compressor_type": "variable speed", - "sensible_heat_ratio": 0.78, - "fan_power_Watts_per_CFM": 0.375, - "backup_heat_fuel_type": "electricity", - "backup_heat_efficiency": 1, - "backup_heat_capacity": 30000, - "compressor_lockout_temperature": 0, - "backupt_heat_lockout_temperature": 40 - }, - { - "id": 2, - "fuel_type": "electricity", - "cooling_capacity": 40000, - "heating_capacity": 40000, - "fraction_heating_load_served": 1, - "fraction_cooling_load_served": 1, - "annual_cooling_efficiency_units": "SEER", - "annual_cooling_efficiency": 16.0, - "annual_heating_efficiency_units": "HSPF", - "annual_heating_efficiency": 9.2, - "heat_pump_type": "air-to-air", - "compressor_type": "variable speed", - "sensible_heat_ratio": 0.78, - "fan_power_Watts_per_CFM": 0.375, - "backup_heat_fuel_type": "electricity", - "backup_heat_efficiency": 1, - "backup_heat_capacity": 30000, - "compressor_lockout_temperature": 0, - "backupt_heat_lockout_temperature": 40 - }, - { - "id": 3, - "fuel_type": "electricity", - "cooling_capacity": 40000, - "heating_capacity": 40000, - "fraction_heating_load_served": 1, - "fraction_cooling_load_served": 1, - "annual_cooling_efficiency_units": "SEER", - "annual_cooling_efficiency": 16.0, - "annual_heating_efficiency_units": "HSPF", - "annual_heating_efficiency": 9.2, - "heat_pump_type": "air-to-air", - "compressor_type": "variable speed", - "sensible_heat_ratio": 0.78, - "fan_power_Watts_per_CFM": 0.375, - "backup_heat_fuel_type": "electricity", - "backup_heat_efficiency": 1, - "backup_heat_capacity": 30000, - "compressor_lockout_temperature": 0, - "backupt_heat_lockout_temperature": 40 - } - ] -} diff --git a/src/swap_HP.py b/src/swap_HP.py index 4221cd0..3935a5a 100644 --- a/src/swap_HP.py +++ b/src/swap_HP.py @@ -9,7 +9,9 @@ from ochre import Dwelling from constants import dict_sim_params import json -from ochre.utils import convert, OCHREException +from ochre.utils import convert, OCHREException, nested_update, load_schedule, update_equipment_properties +from ochre.utils.hpxml import parse_hpxml_occupancy, parse_hpxml_envelope, parse_hpxml_equipment, import_hpxml, load_hpxml +from ochre.Models import Envelope """ Code for running simulations on OCHRE. @@ -25,7 +27,7 @@ 'start_time': dict_sim_params['start_time'], 'time_res': dict_sim_params['time_step'], 'duration': dict_sim_params['duration'], -'initialization_time': timedelta(days=7), +'initialization_time': timedelta(days=1), 'ext_time_res': dict_sim_params['freq_hems'], #HEMS model aggregates data to this timestep. Should be greater than house frequency # Output settings @@ -56,9 +58,13 @@ def remove_directory(path): print(f"The filepath does not exist: {path}") def get_HP_info(HP_id:int): - with open('HP.json', 'r') as file: + with open('inputs/equipments/HP.json', 'r') as file: HP_info = json.load(file) - return HP_info[HP_id] + # Find the heat pump with matching id in the ASHP array + for hp in HP_info['ASHP']: + if hp['id'] == HP_id: + return hp + raise ValueError(f"No heat pump found with id {HP_id}") def create_HP_equipment(HP_info:dict, hvac_type:str): name = HP_info['heat_pump_type'] @@ -178,8 +184,35 @@ def swap_HP( sys.exit(1) try: + # Baseline simulation dwelling = Dwelling(**house_args) - print(dwelling.equipment['Air Conditioner']) + + # Load properties from HPXML file + properties, weather_station = load_hpxml(**house_args) + # Load occupancy schedule and weather files + schedule, location = load_schedule( + properties, weather_station=weather_station, **house_args + ) + properties["location"] = location + # Update args for initializing Envelope and Equipment + sim_args = { + **house_args, + "start_time": dwelling.start_time, # updates time zone if necessary + "schedule": schedule, + "initial_schedule": schedule.loc[dwelling.start_time].to_dict(), + "output_path": dwelling.output_path, + } + # initial_schedule.update(self.envelope.get_main_states()) + sim_args["envelope_model"] = dwelling.envelope + HP1 = create_HP_equipment(get_HP_info(1), 'Cooling') + properties['equipment']['HVAC Cooling'].update(HP1) + + # Add detailed equipment properties, including ZIP parameters + equipment_dict = update_equipment_properties(properties, **sim_args) + #print(equipment_dict) + # continue at Dwelling line 139 + + dwelling.simulate() except Exception as e: print(f"Simulation failed for bldg{building_id:07}-up{upgrade_id:02}: {e}")