From 1947bff6d93b8dc1fe80e7d3a558a911de9e83dc Mon Sep 17 00:00:00 2001 From: astronobri Date: Thu, 30 Jan 2025 01:58:13 -0500 Subject: [PATCH] derUtilityCost: Removed Refrigerators; Added ongoing and one-time subsidies for all devices; reorganized all financial inputs into financial input section. --- omf/models/derUtilityCost.html | 147 +++++++++++++-------------------- omf/models/derUtilityCost.py | 140 +++++++++++++++++-------------- 2 files changed, 138 insertions(+), 149 deletions(-) diff --git a/omf/models/derUtilityCost.html b/omf/models/derUtilityCost.html index cdc829c97..3476f5355 100644 --- a/omf/models/derUtilityCost.html +++ b/omf/models/derUtilityCost.html @@ -105,17 +105,70 @@
- - + + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ +
- - + +
- - + +
+
@@ -209,14 +262,6 @@
-
- - -
-
- - -
@@ -259,63 +304,6 @@ -
- - -
-
- - -
- - -
-

Home Refrigerator Device Inputs

-
-
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
@@ -357,23 +345,6 @@
-
- - -
-
- - -
- - - - - - - - - diff --git a/omf/models/derUtilityCost.py b/omf/models/derUtilityCost.py index 9b3754095..d42dc1cc9 100644 --- a/omf/models/derUtilityCost.py +++ b/omf/models/derUtilityCost.py @@ -145,18 +145,16 @@ def work(modelDir, inputDict): } ## Define thermal variables that change depending on the thermal technology - thermal_suffixes = ['_hp', '_ac', '_rf', '_wh'] ## heat pump, air conditioner, refrigerator, water heater - (Add more suffixes here after establishing inputs in the defaultInputs and derUtilityCost.html) - thermal_variables=['load_type','number_devices','power','capacitance','resistance','cop','setpoint','deadband','TESS_operationalCosts_ongoing','TESS_operationalCosts_onetime'] + thermal_suffixes = ['_hp', '_ac', '_wh'] ## heat pump, air conditioner, water heater - (Add more suffixes here after establishing inputs in the defaultInputs and derUtilityCost.html) + thermal_variables=['load_type','number_devices','power','capacitance','resistance','cop','setpoint','deadband', + 'TESS_operationalCosts_ongoing','TESS_operationalCosts_onetime','TESS_subsidy_ongoing','TESS_subsidy_onetime'] all_device_suffixes = [] single_device_results = {} for suffix in thermal_suffixes: - print('$$$$$$$$$$$$ suffix = ', suffix) - print(float(inputDict['load_type'+suffix])) ## Include only the thermal devices specified by the user if float(inputDict['load_type'+suffix]) > 0 and float(inputDict['number_devices'+suffix]) > 0: - print('$$$$$$$$$$$$ suffix passed test = ', suffix) all_device_suffixes.append(suffix) ## Add the appropriate thermal device variables to the inputDict_vbatDispatch @@ -173,9 +171,11 @@ def work(modelDir, inputDict): with open(pJoin(newDir, 'vbatResults.json'), 'w') as jsonFile: json.dump(vbatResults, jsonFile) - ## Update the vbatResults to include operational costs + ## Update the vbatResults to include operational costs and subsidies vbatResults['TESS_operationalCosts_ongoing'] = inputDict_vbatDispatch['TESS_operationalCosts_ongoing'] vbatResults['TESS_operationalCosts_onetime'] = inputDict_vbatDispatch['TESS_operationalCosts_onetime'] + vbatResults['TESS_subsidy_onetime'] = inputDict_vbatDispatch['TESS_subsidy_onetime'] + vbatResults['TESS_subsidy_ongoing'] = inputDict_vbatDispatch['TESS_subsidy_ongoing'] ## Store the results in all_device_results dictionary single_device_results['vbatResults'+suffix] = vbatResults @@ -206,6 +206,8 @@ def work(modelDir, inputDict): 'energyCostAdjustedTESS':[0]*12, 'combinedTESS_operationalCosts_ongoing': 0, 'combinedTESS_operationalCosts_onetime': 0, + 'combinedTESS_subsidy_ongoing': 0, + 'combinedTESS_subsidy_onetime': 0, } ## Combine all thermal device variable data for plotting @@ -231,25 +233,11 @@ def work(modelDir, inputDict): combined_device_results['energyCostAdjustedTESS'] = [sum(x) for x in zip(combined_device_results['energyCostAdjustedTESS'], single_device_results[device_result]['energyCostAdjusted'])] combined_device_results['combinedTESS_operationalCosts_ongoing'] += float(single_device_results[device_result]['TESS_operationalCosts_ongoing']) combined_device_results['combinedTESS_operationalCosts_onetime'] += float(single_device_results[device_result]['TESS_operationalCosts_onetime']) + combined_device_results['combinedTESS_subsidy_ongoing'] += float(single_device_results[device_result]['TESS_subsidy_ongoing']) + combined_device_results['combinedTESS_subsidy_onetime'] += float(single_device_results[device_result]['TESS_subsidy_onetime']) - ## Update ouData with newly combined TESS results - ## TODO: Bri - compare these with the manually calculated variables at bottom - #outData.update(combined_device_results) + ## TODO: Bri - compare these with the manually calculated variables at bottom - ## Calculate the subsidies - projectionLength = int(inputDict['projectionLength']) - subsidyUpfront = float(inputDict['subsidyUpfront']) - subsidyMonthly = float(inputDict['subsidyRecurring']) - - subsidyRecurring_1year_total = subsidyMonthly * 12. - subsidyRecurring_allyears_array = np.full(projectionLength, subsidyMonthly) - subsidyRecurring_allyears_total = subsidyRecurring_1year_total * projectionLength - - total_subsidy_1year = subsidyUpfront + subsidyRecurring_1year_total - total_subsidy_1year_array = np.full(12, subsidyMonthly) - total_subsidy_1year_array[0] += subsidyUpfront - total_subsidy_allyears_array = np.full(projectionLength, subsidyRecurring_1year_total) - total_subsidy_allyears_array[0] += subsidyUpfront ## NOTE: temporarily comment out the two derConsumer runs to run the code quicker """ @@ -787,7 +775,8 @@ def work(modelDir, inputDict): #################################################################################### ## Calculate the financial benefit of controlling member-consumer DERs #################################################################################### - + projectionLength = int(inputDict['projectionLength']) + ## Calculate residential BESS installation costs installed_cost_per_kw = 20 installed_cost_per_kwh = 80 @@ -795,7 +784,42 @@ def work(modelDir, inputDict): total_kwh_installed_costs = installed_cost_per_kwh * total_kwh_residential_BESS #total_installed_costs = ## TODO: How do we deal with both costs per kw and kWh? - ## Total combined (TESS+BESS) ongoing and onetime operational costs (e.g. utility costs from API calls) + ## Calculate the BESS subsidy for year 1 and the projection length (all years) + ## Year 1 includes the onetime subsidy, but subsequent years do not. + BESS_subsidy_ongoing = float(inputDict['BESS_subsidy_ongoing']) + BESS_subsidy_onetime = float(inputDict['BESS_subsidy_onetime']) + BESS_subsidy_year1_total = BESS_subsidy_onetime + (BESS_subsidy_ongoing*12.0) + BESS_subsidy_allyears_array = np.full(projectionLength, BESS_subsidy_ongoing*12.0) + BESS_subsidy_allyears_array[0] += BESS_subsidy_onetime + + ## Calculate Generator Subsidy for year 1 and the projection length (all years) + ## Year 1 includes the onetime subsidy, but subsequent years do not. + GEN_subsidy_ongoing = float(inputDict['GEN_subsidy_ongoing']) + GEN_subsidy_onetime = float(inputDict['GEN_subsidy_onetime']) + GEN_subsidy_year1_total = GEN_subsidy_onetime + (GEN_subsidy_ongoing*12.0) + GEN_subsidy_allyears_array = np.full(projectionLength, GEN_subsidy_ongoing*12.0) + GEN_subsidy_allyears_array[0] += GEN_subsidy_onetime + + ## Calculate the total TESS subsidies for year 1 and the projection length (all years) + ## Year 1 includes the onetime subsidy, but subsequent years do not. + combinedTESS_subsidy_year1_total = combined_device_results['combinedTESS_subsidy_onetime'] + (combined_device_results['combinedTESS_subsidy_ongoing']*12.0) + combinedTESS_subsidy_allyears_array = np.full(projectionLength, combined_device_results['combinedTESS_subsidy_ongoing']*12.0) + combinedTESS_subsidy_allyears_array[0] += combined_device_results['combinedTESS_subsidy_onetime'] + + ## Calculate the total TESS+BESS+generator subsidies for year 1 and the projection length (all years) + ## Year 1 includes the onetime subsidy, but subsequent years do not. + allDevices_subsidy_ongoing = GEN_subsidy_ongoing + BESS_subsidy_ongoing + combined_device_results['combinedTESS_subsidy_ongoing'] + allDevices_subsidy_onetime = GEN_subsidy_onetime + BESS_subsidy_onetime + combined_device_results['combinedTESS_subsidy_onetime'] + allDevices_subsidy_year1_total = allDevices_subsidy_onetime + (allDevices_subsidy_ongoing*12.0) + allDevices_subsidy_year1_array = np.full(12, allDevices_subsidy_ongoing) + allDevices_subsidy_year1_array[0] += allDevices_subsidy_onetime + allDevices_subsidy_allyears_array = np.full(projectionLength, allDevices_subsidy_ongoing*12.0) + allDevices_subsidy_allyears_array[0] += allDevices_subsidy_onetime + + ## Calculate the utility's ongoing and onetime operational costs for each device + ## This includes costs for things like API calls to control the DERs + + ## Total combined (TESS+BESS) ongoing and onetime operational costs operationalCosts_ongoing_BESS = float(inputDict['BESS_operationalCosts_ongoing']) operationalCosts_ongoing_TESS = float(combined_device_results['combinedTESS_operationalCosts_ongoing']) operationalCosts_ongoing_total = operationalCosts_ongoing_BESS + operationalCosts_ongoing_TESS @@ -804,31 +828,29 @@ def work(modelDir, inputDict): operationalCosts_onetime_total = operationalCosts_onetime_BESS + operationalCosts_onetime_TESS ## Total combined (TESS+BESS) operational costs for 1 year (float value) - operationalCosts_BESS_1year_total = operationalCosts_onetime_BESS + operationalCosts_ongoing_BESS*12 - operationalCosts_TESS_1year_total = operationalCosts_onetime_TESS + operationalCosts_ongoing_TESS*12 - operationalCosts_1year_total = operationalCosts_BESS_1year_total + operationalCosts_TESS_1year_total + operationalCosts_BESS_year1_total = operationalCosts_onetime_BESS + (operationalCosts_ongoing_BESS*12.0) + operationalCosts_TESS_year1_total = operationalCosts_onetime_TESS + (operationalCosts_ongoing_TESS*12.0) + operationalCosts_1year_total = operationalCosts_BESS_year1_total + operationalCosts_TESS_year1_total ## Total combined (TESS+BESS) operational costs for 1 year (monthly values for 1 year) - operationalCosts_BESS_1year_array = np.full(12, operationalCosts_ongoing_BESS) - operationalCosts_TESS_1year_array = np.full(12, operationalCosts_ongoing_TESS) - operationalCosts_BESS_1year_array[0] += operationalCosts_onetime_BESS - operationalCosts_TESS_1year_array[0] += operationalCosts_onetime_TESS - operationalCosts_1year_array = operationalCosts_BESS_1year_array + operationalCosts_TESS_1year_array + operationalCosts_BESS_year1_array = np.full(12, operationalCosts_ongoing_BESS) + operationalCosts_TESS_year1_array = np.full(12, operationalCosts_ongoing_TESS) + operationalCosts_BESS_year1_array[0] += operationalCosts_onetime_BESS + operationalCosts_TESS_year1_array[0] += operationalCosts_onetime_TESS + operationalCosts_year1_array = operationalCosts_BESS_year1_array + operationalCosts_TESS_year1_array ## Total operational costs for BESS and TESS for all years of analysis (yearly values for projectionLength duration) operationalCosts_yearly_total = operationalCosts_ongoing_total + operationalCosts_onetime_total operationalCosts_BESS_allyears_array = np.full(projectionLength, operationalCosts_ongoing_BESS*12.0) operationalCosts_TESS_allyears_array = np.full(projectionLength, operationalCosts_ongoing_TESS*12.0) - #operationalCosts_BESS_onetime_allyears_array = np.full(projectionLength, 0.0) - #operationalCosts_TESS_onetime_allyears_array = np.full(projectionLength, 0.0) operationalCosts_BESS_allyears_array[0] += operationalCosts_onetime_BESS operationalCosts_TESS_allyears_array[0] += operationalCosts_onetime_TESS ## Calculating total utility costs - utilityCosts_1year_total = operationalCosts_1year_total + total_subsidy_1year + total_residential_BESS_compensation + utilityCosts_1year_total = operationalCosts_1year_total + allDevices_subsidy_year1_total + total_residential_BESS_compensation ## NOTE: utilityCosts_allyears_total (below) assumes that the REopt BESS array will be the same for every year of the entire projectionLength (entire analysis) - utilityCosts_allyears_total = utilityCosts_1year_total + (projectionLength-1)*(operationalCosts_ongoing_total+subsidyRecurring_1year_total+total_residential_BESS_compensation) - utilityCosts_1year_array = list(np.array(operationalCosts_1year_array) + np.array(total_subsidy_1year_array) + np.array(BESS_monthly_compensation_to_consumer)) + utilityCosts_allyears_total = utilityCosts_1year_total + (projectionLength-1)*(operationalCosts_ongoing_total+allDevices_subsidy_year1_total+total_residential_BESS_compensation) + utilityCosts_1year_array = list(np.array(operationalCosts_year1_array) + np.array(allDevices_subsidy_year1_array) + np.array(BESS_monthly_compensation_to_consumer)) ## Calculating total utility savings utilitySavings_1year_total = np.sum(utilitySavings_from_BESS_TESS) @@ -851,8 +873,7 @@ def work(modelDir, inputDict): #outData['totalCost_annual'] = list((outData['totalCost_TESS'] + np.array(utilityCosts_1year_array))) # + np.array(outData['energyCostAdjusted_gridCharging'] + np.array(outData['demandChargeAdjusted_total']))) #outData['totalCost_annual'] = list((outData['totalCost_TESS'] + np.array(utilityCosts_1year_array)) + np.array(outData['energyCostAdjusted_total']) + np.array(outData['demandChargeAdjusted_total'])) outData['totalCost_annual'] = list(np.array(utilityCosts_1year_array)) - outData['totalCost_paidToConsumer'] = list(BESS_monthly_compensation_to_consumer + total_subsidy_1year_array) - + outData['totalCost_paidToConsumer'] = list(BESS_monthly_compensation_to_consumer + allDevices_subsidy_year1_array) outData['NPV'] = npv(float(inputDict['discountRate'])/100., utilityNetSavings_allyears_array) if utilitySavings_1year_total == 0: outData['SPP'] = 0. @@ -873,7 +894,7 @@ def work(modelDir, inputDict): outData['savingsAllYears'] = list(utilitySavings_allyears_array) ## Show the costs to the utility as negative values in the Cash Flow Projection plot (costs to the utility) - outData['subsidies'] = list(total_subsidy_allyears_array*-1.) + outData['subsidies'] = list(allDevices_subsidy_allyears_array*-1.) outData['BESS_compensation_to_consumer_allyears'] = list(BESS_allyears_compensation_to_consumer_array*-1.) outData['operationalCosts_BESS_allyears'] = list(operationalCosts_BESS_allyears_array*-1.) outData['operationalCosts_TESS_allyears'] = list(operationalCosts_TESS_allyears_array*-1.) @@ -926,8 +947,22 @@ def new(modelDir): 'projectionLength': '25', 'electricityCost': '0.04', 'rateCompensation': '0.02', ## unit: $/kWh - 'subsidyUpfront': '100.0', - 'subsidyRecurring': '24.0', + 'TESS_subsidy_onetime_ac': '5.0', + 'TESS_subsidy_ongoing_ac': '1.0', + 'TESS_subsidy_onetime_hp': '10.0', + 'TESS_subsidy_ongoing_hp': '2.0', + 'TESS_subsidy_onetime_wh': '15.0', + 'TESS_subsidy_ongoing_wh': '3.0', + 'BESS_subsidy_onetime': '30.0', + 'BESS_subsidy_ongoing': '4.0', + 'GEN_subsidy_onetime': '35.0', + 'GEN_subsidy_ongoing': '5.0', + 'TESS_operationalCosts_ongoing_hp': '10.0', + 'TESS_operationalCosts_onetime_hp': '1000', + 'TESS_operationalCosts_ongoing_ac': '10.0', + 'TESS_operationalCosts_onetime_ac': '1000', + 'TESS_operationalCosts_ongoing_wh': '10.0', + 'TESS_operationalCosts_onetime_wh': '1000', 'discountRate': '2', ## Home Air Conditioner inputs (vbatDispatch): @@ -939,8 +974,6 @@ def new(modelDir): 'cop_ac': '2.5', 'setpoint_ac': '22.5', 'deadband_ac': '0.625', - 'TESS_operationalCosts_ongoing_ac': '10.0', - 'TESS_operationalCosts_onetime_ac': '1000', ## Home Heat Pump inputs (vbatDispatch): 'load_type_hp': '2', @@ -951,20 +984,6 @@ def new(modelDir): 'cop_hp': '3.5', 'setpoint_hp': '19.5', 'deadband_hp': '0.625', - 'TESS_operationalCosts_ongoing_hp': '10.0', - 'TESS_operationalCosts_onetime_hp': '1000', - - ## Home Refrigerator inputs (vbatDispatch): - 'load_type_rf': '3', - 'number_devices_rf': '2000', - 'power_rf': '0.3', - 'capacitance_rf': '0.6', - 'resistance_rf': '90.0', - 'cop_rf': '2', - 'setpoint_rf': '2.5', - 'deadband_rf': '1.5', - 'TESS_operationalCosts_ongoing_rf': '10.0', - 'TESS_operationalCosts_onetime_rf': '1000', ## Home Water Heater inputs (vbatDispatch): 'load_type_wh': '4', @@ -975,8 +994,7 @@ def new(modelDir): 'cop_wh': '1', 'setpoint_wh': '48.5', 'deadband_wh': '3', - 'TESS_operationalCosts_ongoing_wh': '10.0', - 'TESS_operationalCosts_onetime_wh': '1000', + }