From 518d9507a215ceb10f75a61d7d6a34d6238919d7 Mon Sep 17 00:00:00 2001 From: "Rathod, Bhavesh" Date: Mon, 29 Sep 2025 13:26:55 -0400 Subject: [PATCH 01/18] Updated model with outputs for testing --- reoptjl/models.py | 152 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 152 insertions(+) diff --git a/reoptjl/models.py b/reoptjl/models.py index 2d48782ea..f1a3e925b 100644 --- a/reoptjl/models.py +++ b/reoptjl/models.py @@ -1506,6 +1506,24 @@ class ElectricLoadOutputs(BaseModel, models.Model): null=True, blank=True, help_text="Annual energy consumption calculated by summing up load_series_kw. Does not include electric load for any new heating or cooling techs." ) + monthly_calculated_kwh = ArrayField( + models.FloatField( + null=True, blank=True + ), + default=list, + help_text="Monthly energy consumption calculated by summing up load_series_kw. Does not include electric load for any new heating or cooling techs." + ) + monthly_peak_kw = ArrayField( + models.FloatField( + null=True, blank=True + ), + default=list, + help_text="Monthly peak energy demand determined from load_series_kw. Does not include electric load for any new heating or cooling techs." + ) + annual_peak_kw = models.FloatField( + null=True, blank=True, + help_text="Annual peak energy demand determined from load_series_kw. Does not include electric load for any new heating or cooling techs." + ) annual_electric_load_with_thermal_conversions_kwh = models.FloatField( null=True, blank=True, help_text="Total end-use electrical load, including electrified heating and cooling end-use load." @@ -2563,6 +2581,140 @@ class ElectricTariffOutputs(BaseModel, models.Model): related_name="ElectricTariffOutputs", primary_key=True ) + year_one_monthly_fixed_cost = ArrayField( + models.FloatField( + null=True, blank=True + ), + default=list, + help_text="Year one fixed utility costs for each month." + ) + + year_one_electric_to_load_energy_cost_series_before_tax = ArrayField( + models.FloatField( + null=True, blank=True + ), + default=list, + help_text="Series of cost of power purchased from grid to serve load in each timestep." + ) + monthly_electric_to_load_energy_cost_series_before_tax = ArrayField( + models.FloatField( + null=True, blank=True + ), + default=list, + help_text="Series of monthly cost of power purchased from grid to serve loads." + ) + year_one_electric_to_storage_energy_cost_series_before_tax = ArrayField( + models.FloatField( + null=True, blank=True + ), + default=list, + help_text="Series of cost of power purchased from grid to charge battery storage system in each timestep." + ) + monthly_electric_to_storage_energy_cost_series_before_tax = ArrayField( + models.FloatField( + null=True, blank=True + ), + default=list, + help_text="Series of monthly cost of power purchased from grid to charge battery storage system." + ) + monthly_facility_demand_cost_series_before_tax = ArrayField( + models.FloatField( + null=True, blank=True + ), + default=list, + help_text="Series of total monthly facility demand charges by month." + ) + monthly_gross_tou_demand_cost_series_before_tax = ArrayField( + models.FloatField( + null=True, blank=True + ), + default=list, + help_text="Series of total time of use demand charges by month." + ) + NEM_export_rate_series = ArrayField( + models.FloatField( + null=True, blank=True + ), + default=list, + help_text="Series of compensation rate in each timestep for exporting power to grid using systems sized up to net metering limit." + ) + NEM_electric_to_grid_series_kw = ArrayField( + models.FloatField( + null=True, blank=True + ), + default=list, + help_text="Series of power exports to the grid up to net metering limit for each timestep." + ) + NEM_monthly_export_series_kwh = ArrayField( + models.FloatField( + null=True, blank=True + ), + default=list, + help_text="Year one cost of electricity consumed in each month." + ) + NEM_monthly_export_cost_benefit_before_tax = ArrayField( + models.FloatField( + null=True, blank=True + ), + default=list, + help_text="Year one cost of electricity consumed in each month." + ) + WHL_export_rate_series = ArrayField( + models.FloatField( + null=True, blank=True + ), + default=list, + help_text="Series of compensation rate in each timestep for exporting power to grid for wholesale." + ) + WHL_electric_to_grid_series_kw = ArrayField( + models.FloatField( + null=True, blank=True + ), + default=list, + help_text="Series of power exports to the grid for wholesale in each timestep." + ) + WHL_monthly_export_series_kwh = ArrayField( + models.FloatField( + null=True, blank=True + ), + default=list, + help_text="Series of monthly energy exports to grid under wholesale benefit." + ) + WHL_monthly_export_cost_benefit_before_tax = ArrayField( + models.FloatField( + null=True, blank=True + ), + default=list, + help_text="Series of monthly monetary benefit from exporting power to grid at wholesale rate." + ) + EXC_export_rate_series = ArrayField( + models.FloatField( + null=True, blank=True + ), + default=list, + help_text="Series of compensation rate in each timestep for exporting power to grid beyond net metering limit." + ) + EXC_electric_to_grid_series_kw = ArrayField( + models.FloatField( + null=True, blank=True + ), + default=list, + help_text="Series of power exports to the grid above net metering limit for each timestep." + ) + EXC_monthly_export_series_kwh = ArrayField( + models.FloatField( + null=True, blank=True + ), + default=list, + help_text="Series of monthly energy exports to grid above net metering limit." + ) + EXC_monthly_export_cost_benefit_before_tax = ArrayField( + models.FloatField( + null=True, blank=True + ), + default=list, + help_text="Series of monthly monetary benefit from exporting power to grid above net metering limit." + ) year_one_energy_cost_before_tax = models.FloatField( null=True, blank=True, help_text="Optimal year one utility energy cost" From ea88d75f73f42b42e9a0efce1938fc35b87af24b Mon Sep 17 00:00:00 2001 From: "Rathod, Bhavesh" Date: Tue, 30 Sep 2025 12:25:09 -0400 Subject: [PATCH 02/18] Update julia version and make migrations --- julia_src/Manifest.toml | 6 +- ...tricloadoutputs_annual_peak_kw_and_more.py | 124 ++++++++++++++++++ 2 files changed, 128 insertions(+), 2 deletions(-) create mode 100644 reoptjl/migrations/0093_electricloadoutputs_annual_peak_kw_and_more.py diff --git a/julia_src/Manifest.toml b/julia_src/Manifest.toml index 499e0c00a..e0ad46b68 100644 --- a/julia_src/Manifest.toml +++ b/julia_src/Manifest.toml @@ -922,9 +922,11 @@ uuid = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb" [[deps.REopt]] deps = ["ArchGDAL", "CSV", "CoolProp", "DataFrames", "Dates", "DelimitedFiles", "HTTP", "JLD", "JSON", "JuMP", "LinDistFlow", "LinearAlgebra", "Logging", "MathOptInterface", "Requires", "Roots", "Statistics", "TestEnv"] -git-tree-sha1 = "4db74039055f6084d8bd45304de9de856462d917" +git-tree-sha1 = "1283214f265ecc53d02b4bc9318676a9f02dadcb" +repo-rev = "elec_util_usage" +repo-url = "https://github.com/NREL/REopt.jl.git" uuid = "d36ad4e8-d74a-4f7a-ace1-eaea049febf6" -version = "0.53.2" +version = "0.54.0" [[deps.Random]] deps = ["SHA"] diff --git a/reoptjl/migrations/0093_electricloadoutputs_annual_peak_kw_and_more.py b/reoptjl/migrations/0093_electricloadoutputs_annual_peak_kw_and_more.py new file mode 100644 index 000000000..42a5beb83 --- /dev/null +++ b/reoptjl/migrations/0093_electricloadoutputs_annual_peak_kw_and_more.py @@ -0,0 +1,124 @@ +# Generated by Django 4.0.7 on 2025-09-30 14:52 + +import django.contrib.postgres.fields +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('reoptjl', '0092_merge_20250613_0525'), + ] + + operations = [ + migrations.AddField( + model_name='electricloadoutputs', + name='annual_peak_kw', + field=models.FloatField(blank=True, help_text='Annual peak energy demand determined from load_series_kw. Does not include electric load for any new heating or cooling techs.', null=True), + ), + migrations.AddField( + model_name='electricloadoutputs', + name='monthly_calculated_kwh', + field=django.contrib.postgres.fields.ArrayField(base_field=models.FloatField(blank=True, null=True), default=list, help_text='Monthly energy consumption calculated by summing up load_series_kw. Does not include electric load for any new heating or cooling techs.', size=None), + ), + migrations.AddField( + model_name='electricloadoutputs', + name='monthly_peak_kw', + field=django.contrib.postgres.fields.ArrayField(base_field=models.FloatField(blank=True, null=True), default=list, help_text='Monthly peak energy demand determined from load_series_kw. Does not include electric load for any new heating or cooling techs.', size=None), + ), + migrations.AddField( + model_name='electrictariffoutputs', + name='EXC_electric_to_grid_series_kw', + field=django.contrib.postgres.fields.ArrayField(base_field=models.FloatField(blank=True, null=True), default=list, help_text='Series of power exports to the grid above net metering limit for each timestep.', size=None), + ), + migrations.AddField( + model_name='electrictariffoutputs', + name='EXC_export_rate_series', + field=django.contrib.postgres.fields.ArrayField(base_field=models.FloatField(blank=True, null=True), default=list, help_text='Series of compensation rate in each timestep for exporting power to grid beyond net metering limit.', size=None), + ), + migrations.AddField( + model_name='electrictariffoutputs', + name='EXC_monthly_export_cost_benefit_before_tax', + field=django.contrib.postgres.fields.ArrayField(base_field=models.FloatField(blank=True, null=True), default=list, help_text='Series of monthly monetary benefit from exporting power to grid above net metering limit.', size=None), + ), + migrations.AddField( + model_name='electrictariffoutputs', + name='EXC_monthly_export_series_kwh', + field=django.contrib.postgres.fields.ArrayField(base_field=models.FloatField(blank=True, null=True), default=list, help_text='Series of monthly energy exports to grid above net metering limit.', size=None), + ), + migrations.AddField( + model_name='electrictariffoutputs', + name='NEM_electric_to_grid_series_kw', + field=django.contrib.postgres.fields.ArrayField(base_field=models.FloatField(blank=True, null=True), default=list, help_text='Series of power exports to the grid up to net metering limit for each timestep.', size=None), + ), + migrations.AddField( + model_name='electrictariffoutputs', + name='NEM_export_rate_series', + field=django.contrib.postgres.fields.ArrayField(base_field=models.FloatField(blank=True, null=True), default=list, help_text='Series of compensation rate in each timestep for exporting power to grid using systems sized up to net metering limit.', size=None), + ), + migrations.AddField( + model_name='electrictariffoutputs', + name='NEM_monthly_export_cost_benefit_before_tax', + field=django.contrib.postgres.fields.ArrayField(base_field=models.FloatField(blank=True, null=True), default=list, help_text='Year one cost of electricity consumed in each month.', size=None), + ), + migrations.AddField( + model_name='electrictariffoutputs', + name='NEM_monthly_export_series_kwh', + field=django.contrib.postgres.fields.ArrayField(base_field=models.FloatField(blank=True, null=True), default=list, help_text='Year one cost of electricity consumed in each month.', size=None), + ), + migrations.AddField( + model_name='electrictariffoutputs', + name='WHL_electric_to_grid_series_kw', + field=django.contrib.postgres.fields.ArrayField(base_field=models.FloatField(blank=True, null=True), default=list, help_text='Series of power exports to the grid for wholesale in each timestep.', size=None), + ), + migrations.AddField( + model_name='electrictariffoutputs', + name='WHL_export_rate_series', + field=django.contrib.postgres.fields.ArrayField(base_field=models.FloatField(blank=True, null=True), default=list, help_text='Series of compensation rate in each timestep for exporting power to grid for wholesale.', size=None), + ), + migrations.AddField( + model_name='electrictariffoutputs', + name='WHL_monthly_export_cost_benefit_before_tax', + field=django.contrib.postgres.fields.ArrayField(base_field=models.FloatField(blank=True, null=True), default=list, help_text='Series of monthly monetary benefit from exporting power to grid at wholesale rate.', size=None), + ), + migrations.AddField( + model_name='electrictariffoutputs', + name='WHL_monthly_export_series_kwh', + field=django.contrib.postgres.fields.ArrayField(base_field=models.FloatField(blank=True, null=True), default=list, help_text='Series of monthly energy exports to grid under wholesale benefit.', size=None), + ), + migrations.AddField( + model_name='electrictariffoutputs', + name='monthly_electric_to_load_energy_cost_series_before_tax', + field=django.contrib.postgres.fields.ArrayField(base_field=models.FloatField(blank=True, null=True), default=list, help_text='Series of monthly cost of power purchased from grid to serve loads.', size=None), + ), + migrations.AddField( + model_name='electrictariffoutputs', + name='monthly_electric_to_storage_energy_cost_series_before_tax', + field=django.contrib.postgres.fields.ArrayField(base_field=models.FloatField(blank=True, null=True), default=list, help_text='Series of monthly cost of power purchased from grid to charge battery storage system.', size=None), + ), + migrations.AddField( + model_name='electrictariffoutputs', + name='monthly_facility_demand_cost_series_before_tax', + field=django.contrib.postgres.fields.ArrayField(base_field=models.FloatField(blank=True, null=True), default=list, help_text='Series of total monthly facility demand charges by month.', size=None), + ), + migrations.AddField( + model_name='electrictariffoutputs', + name='monthly_gross_tou_demand_cost_series_before_tax', + field=django.contrib.postgres.fields.ArrayField(base_field=models.FloatField(blank=True, null=True), default=list, help_text='Series of total time of use demand charges by month.', size=None), + ), + migrations.AddField( + model_name='electrictariffoutputs', + name='year_one_electric_to_load_energy_cost_series_before_tax', + field=django.contrib.postgres.fields.ArrayField(base_field=models.FloatField(blank=True, null=True), default=list, help_text='Series of cost of power purchased from grid to serve load in each timestep.', size=None), + ), + migrations.AddField( + model_name='electrictariffoutputs', + name='year_one_electric_to_storage_energy_cost_series_before_tax', + field=django.contrib.postgres.fields.ArrayField(base_field=models.FloatField(blank=True, null=True), default=list, help_text='Series of cost of power purchased from grid to charge battery storage system in each timestep.', size=None), + ), + migrations.AddField( + model_name='electrictariffoutputs', + name='year_one_monthly_fixed_cost', + field=django.contrib.postgres.fields.ArrayField(base_field=models.FloatField(blank=True, null=True), default=list, help_text='Year one fixed utility costs for each month.', size=None), + ), + ] From 08a9ccf13e2af054663c678b2a65b0a843a609a6 Mon Sep 17 00:00:00 2001 From: Rathod Date: Thu, 2 Oct 2025 14:35:57 -0400 Subject: [PATCH 03/18] Remove migration 0093 and add billed energy rate field Deleted the migration file 0093_electricloadoutputs_annual_peak_kw_and_more.py and added the year_one_billed_energy_rate_series ArrayField to the ElectricTariffOutputs model. This change likely reflects a schema update and migration reset to accommodate the new field. --- ...tricloadoutputs_annual_peak_kw_and_more.py | 124 ------------------ reoptjl/models.py | 9 ++ 2 files changed, 9 insertions(+), 124 deletions(-) delete mode 100644 reoptjl/migrations/0093_electricloadoutputs_annual_peak_kw_and_more.py diff --git a/reoptjl/migrations/0093_electricloadoutputs_annual_peak_kw_and_more.py b/reoptjl/migrations/0093_electricloadoutputs_annual_peak_kw_and_more.py deleted file mode 100644 index 42a5beb83..000000000 --- a/reoptjl/migrations/0093_electricloadoutputs_annual_peak_kw_and_more.py +++ /dev/null @@ -1,124 +0,0 @@ -# Generated by Django 4.0.7 on 2025-09-30 14:52 - -import django.contrib.postgres.fields -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('reoptjl', '0092_merge_20250613_0525'), - ] - - operations = [ - migrations.AddField( - model_name='electricloadoutputs', - name='annual_peak_kw', - field=models.FloatField(blank=True, help_text='Annual peak energy demand determined from load_series_kw. Does not include electric load for any new heating or cooling techs.', null=True), - ), - migrations.AddField( - model_name='electricloadoutputs', - name='monthly_calculated_kwh', - field=django.contrib.postgres.fields.ArrayField(base_field=models.FloatField(blank=True, null=True), default=list, help_text='Monthly energy consumption calculated by summing up load_series_kw. Does not include electric load for any new heating or cooling techs.', size=None), - ), - migrations.AddField( - model_name='electricloadoutputs', - name='monthly_peak_kw', - field=django.contrib.postgres.fields.ArrayField(base_field=models.FloatField(blank=True, null=True), default=list, help_text='Monthly peak energy demand determined from load_series_kw. Does not include electric load for any new heating or cooling techs.', size=None), - ), - migrations.AddField( - model_name='electrictariffoutputs', - name='EXC_electric_to_grid_series_kw', - field=django.contrib.postgres.fields.ArrayField(base_field=models.FloatField(blank=True, null=True), default=list, help_text='Series of power exports to the grid above net metering limit for each timestep.', size=None), - ), - migrations.AddField( - model_name='electrictariffoutputs', - name='EXC_export_rate_series', - field=django.contrib.postgres.fields.ArrayField(base_field=models.FloatField(blank=True, null=True), default=list, help_text='Series of compensation rate in each timestep for exporting power to grid beyond net metering limit.', size=None), - ), - migrations.AddField( - model_name='electrictariffoutputs', - name='EXC_monthly_export_cost_benefit_before_tax', - field=django.contrib.postgres.fields.ArrayField(base_field=models.FloatField(blank=True, null=True), default=list, help_text='Series of monthly monetary benefit from exporting power to grid above net metering limit.', size=None), - ), - migrations.AddField( - model_name='electrictariffoutputs', - name='EXC_monthly_export_series_kwh', - field=django.contrib.postgres.fields.ArrayField(base_field=models.FloatField(blank=True, null=True), default=list, help_text='Series of monthly energy exports to grid above net metering limit.', size=None), - ), - migrations.AddField( - model_name='electrictariffoutputs', - name='NEM_electric_to_grid_series_kw', - field=django.contrib.postgres.fields.ArrayField(base_field=models.FloatField(blank=True, null=True), default=list, help_text='Series of power exports to the grid up to net metering limit for each timestep.', size=None), - ), - migrations.AddField( - model_name='electrictariffoutputs', - name='NEM_export_rate_series', - field=django.contrib.postgres.fields.ArrayField(base_field=models.FloatField(blank=True, null=True), default=list, help_text='Series of compensation rate in each timestep for exporting power to grid using systems sized up to net metering limit.', size=None), - ), - migrations.AddField( - model_name='electrictariffoutputs', - name='NEM_monthly_export_cost_benefit_before_tax', - field=django.contrib.postgres.fields.ArrayField(base_field=models.FloatField(blank=True, null=True), default=list, help_text='Year one cost of electricity consumed in each month.', size=None), - ), - migrations.AddField( - model_name='electrictariffoutputs', - name='NEM_monthly_export_series_kwh', - field=django.contrib.postgres.fields.ArrayField(base_field=models.FloatField(blank=True, null=True), default=list, help_text='Year one cost of electricity consumed in each month.', size=None), - ), - migrations.AddField( - model_name='electrictariffoutputs', - name='WHL_electric_to_grid_series_kw', - field=django.contrib.postgres.fields.ArrayField(base_field=models.FloatField(blank=True, null=True), default=list, help_text='Series of power exports to the grid for wholesale in each timestep.', size=None), - ), - migrations.AddField( - model_name='electrictariffoutputs', - name='WHL_export_rate_series', - field=django.contrib.postgres.fields.ArrayField(base_field=models.FloatField(blank=True, null=True), default=list, help_text='Series of compensation rate in each timestep for exporting power to grid for wholesale.', size=None), - ), - migrations.AddField( - model_name='electrictariffoutputs', - name='WHL_monthly_export_cost_benefit_before_tax', - field=django.contrib.postgres.fields.ArrayField(base_field=models.FloatField(blank=True, null=True), default=list, help_text='Series of monthly monetary benefit from exporting power to grid at wholesale rate.', size=None), - ), - migrations.AddField( - model_name='electrictariffoutputs', - name='WHL_monthly_export_series_kwh', - field=django.contrib.postgres.fields.ArrayField(base_field=models.FloatField(blank=True, null=True), default=list, help_text='Series of monthly energy exports to grid under wholesale benefit.', size=None), - ), - migrations.AddField( - model_name='electrictariffoutputs', - name='monthly_electric_to_load_energy_cost_series_before_tax', - field=django.contrib.postgres.fields.ArrayField(base_field=models.FloatField(blank=True, null=True), default=list, help_text='Series of monthly cost of power purchased from grid to serve loads.', size=None), - ), - migrations.AddField( - model_name='electrictariffoutputs', - name='monthly_electric_to_storage_energy_cost_series_before_tax', - field=django.contrib.postgres.fields.ArrayField(base_field=models.FloatField(blank=True, null=True), default=list, help_text='Series of monthly cost of power purchased from grid to charge battery storage system.', size=None), - ), - migrations.AddField( - model_name='electrictariffoutputs', - name='monthly_facility_demand_cost_series_before_tax', - field=django.contrib.postgres.fields.ArrayField(base_field=models.FloatField(blank=True, null=True), default=list, help_text='Series of total monthly facility demand charges by month.', size=None), - ), - migrations.AddField( - model_name='electrictariffoutputs', - name='monthly_gross_tou_demand_cost_series_before_tax', - field=django.contrib.postgres.fields.ArrayField(base_field=models.FloatField(blank=True, null=True), default=list, help_text='Series of total time of use demand charges by month.', size=None), - ), - migrations.AddField( - model_name='electrictariffoutputs', - name='year_one_electric_to_load_energy_cost_series_before_tax', - field=django.contrib.postgres.fields.ArrayField(base_field=models.FloatField(blank=True, null=True), default=list, help_text='Series of cost of power purchased from grid to serve load in each timestep.', size=None), - ), - migrations.AddField( - model_name='electrictariffoutputs', - name='year_one_electric_to_storage_energy_cost_series_before_tax', - field=django.contrib.postgres.fields.ArrayField(base_field=models.FloatField(blank=True, null=True), default=list, help_text='Series of cost of power purchased from grid to charge battery storage system in each timestep.', size=None), - ), - migrations.AddField( - model_name='electrictariffoutputs', - name='year_one_monthly_fixed_cost', - field=django.contrib.postgres.fields.ArrayField(base_field=models.FloatField(blank=True, null=True), default=list, help_text='Year one fixed utility costs for each month.', size=None), - ), - ] diff --git a/reoptjl/models.py b/reoptjl/models.py index f1a3e925b..f58eb3cf0 100644 --- a/reoptjl/models.py +++ b/reoptjl/models.py @@ -2715,6 +2715,15 @@ class ElectricTariffOutputs(BaseModel, models.Model): default=list, help_text="Series of monthly monetary benefit from exporting power to grid above net metering limit." ) + + year_one_billed_energy_rate_series = ArrayField( + models.FloatField( + null=True, blank=True + ), + default=list, + help_text="Series of billed energy rates for each timestep in year one." + ) + year_one_energy_cost_before_tax = models.FloatField( null=True, blank=True, help_text="Optimal year one utility energy cost" From 39c7b2b4bff250c920e3e788377fc9a2f5be2554 Mon Sep 17 00:00:00 2001 From: "Rathod, Bhavesh" Date: Wed, 8 Oct 2025 19:44:40 -0400 Subject: [PATCH 04/18] Add new electric load and tariff output fields Introduces multiple new fields to ElectricLoadOutputs and ElectricTariffOutputs models for tracking annual peak kW, monthly energy and peak demand, export series, and various billed rate series. Updates Julia HTTP handler to log processing steps and ensures certain result matrices are converted to vectors before response. --- julia_src/http.jl | 5 + ...tricloadoutputs_annual_peak_kw_and_more.py | 164 ++++++++++++++++++ reoptjl/models.py | 39 ++++- 3 files changed, 206 insertions(+), 2 deletions(-) create mode 100644 reoptjl/migrations/0106_electricloadoutputs_annual_peak_kw_and_more.py diff --git a/julia_src/http.jl b/julia_src/http.jl index 8e4b0a4fc..a25671938 100644 --- a/julia_src/http.jl +++ b/julia_src/http.jl @@ -56,6 +56,7 @@ function reopt(req::HTTP.Request) # Catch handled/unhandled exceptions in data pre-processing, JuMP setup try model_inputs = reoptjl.REoptInputs(d) + @info "Successfully processed REopt inputs." catch e @error "Something went wrong during REopt inputs processing!" exception=(e, catch_backtrace()) error_response["error"] = sprint(showerror, e) @@ -67,6 +68,7 @@ function reopt(req::HTTP.Request) # Catch handled/unhandled exceptions in optimization try results = reoptjl.run_reopt(ms, model_inputs) + @info "Successfully ran REopt optimization." inputs_with_defaults_from_easiur = [ :NOx_grid_cost_per_tonne, :SO2_grid_cost_per_tonne, :PM25_grid_cost_per_tonne, :NOx_onsite_fuelburn_cost_per_tonne, :SO2_onsite_fuelburn_cost_per_tonne, :PM25_onsite_fuelburn_cost_per_tonne, @@ -185,6 +187,9 @@ function reopt(req::HTTP.Request) if isempty(error_response) @info "REopt model solved with status $(results["status"])." + # these are matrices that need to be vector. + results["ElectricTariff"]["year_one_electric_to_load_energy_cost_series_before_tax"] = results["ElectricTariff"]["year_one_electric_to_load_energy_cost_series_before_tax"][:,1] + results["ElectricTariff"]["monthly_facility_demand_cost_series_before_tax"] = results["ElectricTariff"]["monthly_facility_demand_cost_series_before_tax"][:,1] response = Dict( "results" => results, "reopt_version" => string(pkgversion(reoptjl)) diff --git a/reoptjl/migrations/0106_electricloadoutputs_annual_peak_kw_and_more.py b/reoptjl/migrations/0106_electricloadoutputs_annual_peak_kw_and_more.py new file mode 100644 index 000000000..8add1d9cb --- /dev/null +++ b/reoptjl/migrations/0106_electricloadoutputs_annual_peak_kw_and_more.py @@ -0,0 +1,164 @@ +# Generated by Django 4.2.24 on 2025-10-06 17:06 + +import django.contrib.postgres.fields +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('reoptjl', '0105_alter_chpoutputs_initial_capital_costs_and_more'), + ] + + operations = [ + migrations.AddField( + model_name='electricloadoutputs', + name='annual_peak_kw', + field=models.FloatField(blank=True, help_text='Annual peak energy demand determined from load_series_kw. Does not include electric load for any new heating or cooling techs.', null=True), + ), + migrations.AddField( + model_name='electricloadoutputs', + name='monthly_calculated_kwh', + field=django.contrib.postgres.fields.ArrayField(base_field=models.FloatField(blank=True, null=True), default=list, help_text='Monthly energy consumption calculated by summing up load_series_kw. Does not include electric load for any new heating or cooling techs.', size=None), + ), + migrations.AddField( + model_name='electricloadoutputs', + name='monthly_peak_kw', + field=django.contrib.postgres.fields.ArrayField(base_field=models.FloatField(blank=True, null=True), default=list, help_text='Monthly peak energy demand determined from load_series_kw. Does not include electric load for any new heating or cooling techs.', size=None), + ), + migrations.AddField( + model_name='electrictariffoutputs', + name='EXC_electric_to_grid_series_kw', + field=django.contrib.postgres.fields.ArrayField(base_field=models.FloatField(blank=True, null=True), default=list, help_text='Series of power exports to the grid above net metering limit for each timestep.', size=None), + ), + migrations.AddField( + model_name='electrictariffoutputs', + name='EXC_export_rate_series', + field=django.contrib.postgres.fields.ArrayField(base_field=models.FloatField(blank=True, null=True), default=list, help_text='Series of compensation rate in each timestep for exporting power to grid beyond net metering limit.', size=None), + ), + migrations.AddField( + model_name='electrictariffoutputs', + name='EXC_monthly_export_cost_benefit_before_tax', + field=django.contrib.postgres.fields.ArrayField(base_field=models.FloatField(blank=True, null=True), default=list, help_text='Series of monthly monetary benefit from exporting power to grid above net metering limit.', size=None), + ), + migrations.AddField( + model_name='electrictariffoutputs', + name='EXC_monthly_export_series_kwh', + field=django.contrib.postgres.fields.ArrayField(base_field=models.FloatField(blank=True, null=True), default=list, help_text='Series of monthly energy exports to grid above net metering limit.', size=None), + ), + migrations.AddField( + model_name='electrictariffoutputs', + name='NEM_electric_to_grid_series_kw', + field=django.contrib.postgres.fields.ArrayField(base_field=models.FloatField(blank=True, null=True), default=list, help_text='Series of power exports to the grid up to net metering limit for each timestep.', size=None), + ), + migrations.AddField( + model_name='electrictariffoutputs', + name='NEM_export_rate_series', + field=django.contrib.postgres.fields.ArrayField(base_field=models.FloatField(blank=True, null=True), default=list, help_text='Series of compensation rate in each timestep for exporting power to grid using systems sized up to net metering limit.', size=None), + ), + migrations.AddField( + model_name='electrictariffoutputs', + name='NEM_monthly_export_cost_benefit_before_tax', + field=django.contrib.postgres.fields.ArrayField(base_field=models.FloatField(blank=True, null=True), default=list, help_text='Year one cost of electricity consumed in each month.', size=None), + ), + migrations.AddField( + model_name='electrictariffoutputs', + name='NEM_monthly_export_series_kwh', + field=django.contrib.postgres.fields.ArrayField(base_field=models.FloatField(blank=True, null=True), default=list, help_text='Year one cost of electricity consumed in each month.', size=None), + ), + migrations.AddField( + model_name='electrictariffoutputs', + name='WHL_electric_to_grid_series_kw', + field=django.contrib.postgres.fields.ArrayField(base_field=models.FloatField(blank=True, null=True), default=list, help_text='Series of power exports to the grid for wholesale in each timestep.', size=None), + ), + migrations.AddField( + model_name='electrictariffoutputs', + name='WHL_export_rate_series', + field=django.contrib.postgres.fields.ArrayField(base_field=models.FloatField(blank=True, null=True), default=list, help_text='Series of compensation rate in each timestep for exporting power to grid for wholesale.', size=None), + ), + migrations.AddField( + model_name='electrictariffoutputs', + name='WHL_monthly_export_cost_benefit_before_tax', + field=django.contrib.postgres.fields.ArrayField(base_field=models.FloatField(blank=True, null=True), default=list, help_text='Series of monthly monetary benefit from exporting power to grid at wholesale rate.', size=None), + ), + migrations.AddField( + model_name='electrictariffoutputs', + name='WHL_monthly_export_series_kwh', + field=django.contrib.postgres.fields.ArrayField(base_field=models.FloatField(blank=True, null=True), default=list, help_text='Series of monthly energy exports to grid under wholesale benefit.', size=None), + ), + migrations.AddField( + model_name='electrictariffoutputs', + name='monthly_electric_to_load_energy_cost_series_before_tax', + field=django.contrib.postgres.fields.ArrayField(base_field=models.FloatField(blank=True, null=True), default=list, help_text='Series of monthly cost of power purchased from grid to serve loads.', size=None), + ), + migrations.AddField( + model_name='electrictariffoutputs', + name='monthly_electric_to_storage_energy_cost_series_before_tax', + field=django.contrib.postgres.fields.ArrayField(base_field=models.FloatField(blank=True, null=True), default=list, help_text='Series of monthly cost of power purchased from grid to charge battery storage system.', size=None), + ), + migrations.AddField( + model_name='electrictariffoutputs', + name='monthly_facility_demand_cost_series_before_tax', + field=django.contrib.postgres.fields.ArrayField(base_field=models.FloatField(blank=True, null=True), default=list, help_text='Series of total monthly facility demand charges by month.', size=None), + ), + migrations.AddField( + model_name='electrictariffoutputs', + name='monthly_gross_tou_demand_cost_series_before_tax', + field=django.contrib.postgres.fields.ArrayField(base_field=models.FloatField(blank=True, null=True), default=list, help_text='Series of total time of use demand charges by month.', size=None), + ), + migrations.AddField( + model_name='electrictariffoutputs', + name='monthly_tou_demand_cost_series_before_tax', + field=django.contrib.postgres.fields.ArrayField(base_field=models.FloatField(blank=True, null=True), default=list, help_text='Series of total time of use demand charges for each month.', size=None), + ), + migrations.AddField( + model_name='electrictariffoutputs', + name='tou_demand_metrics', + field=models.JSONField(blank=True, null=True), + ), + migrations.AddField( + model_name='electrictariffoutputs', + name='year_one_billed_demand_rate_series', + field=models.JSONField(blank=True, null=True), + ), + migrations.AddField( + model_name='electrictariffoutputs', + name='year_one_billed_energy_rate_series', + field=models.JSONField(blank=True, help_text='Series of billed energy rates for each timestep in year one.', null=True), + ), + migrations.AddField( + model_name='electrictariffoutputs', + name='year_one_billed_energy_rate_tier_limits', + field=models.JSONField(blank=True, null=True), + ), + migrations.AddField( + model_name='electrictariffoutputs', + name='year_one_billed_facilitydemand_monthly_rate_series', + field=models.JSONField(blank=True, null=True), + ), + migrations.AddField( + model_name='electrictariffoutputs', + name='year_one_billed_facilitydemand_monthly_rate_tier_limits', + field=models.JSONField(blank=True, null=True), + ), + migrations.AddField( + model_name='electrictariffoutputs', + name='year_one_billed_tou_demand_rate_tier_limits', + field=models.JSONField(blank=True, null=True), + ), + migrations.AddField( + model_name='electrictariffoutputs', + name='year_one_electric_to_load_energy_cost_series_before_tax', + field=django.contrib.postgres.fields.ArrayField(base_field=models.FloatField(blank=True, null=True), default=list, help_text='Series of cost of power purchased from grid to serve load in each timestep.', size=None), + ), + migrations.AddField( + model_name='electrictariffoutputs', + name='year_one_electric_to_storage_energy_cost_series_before_tax', + field=django.contrib.postgres.fields.ArrayField(base_field=models.FloatField(blank=True, null=True), default=list, help_text='Series of cost of power purchased from grid to charge battery storage system in each timestep.', size=None), + ), + migrations.AddField( + model_name='electrictariffoutputs', + name='year_one_monthly_fixed_cost', + field=django.contrib.postgres.fields.ArrayField(base_field=models.FloatField(blank=True, null=True), default=list, help_text='Year one fixed utility costs for each month.', size=None), + ), + ] diff --git a/reoptjl/models.py b/reoptjl/models.py index 0229e0026..c068360d1 100644 --- a/reoptjl/models.py +++ b/reoptjl/models.py @@ -2716,12 +2716,47 @@ class ElectricTariffOutputs(BaseModel, models.Model): help_text="Series of monthly monetary benefit from exporting power to grid above net metering limit." ) - year_one_billed_energy_rate_series = ArrayField( + year_one_billed_energy_rate_series = models.JSONField( + null=True, blank=True, + help_text="Series of billed energy rates for each timestep in year one." + ) + + monthly_tou_demand_cost_series_before_tax = ArrayField( models.FloatField( null=True, blank=True ), default=list, - help_text="Series of billed energy rates for each timestep in year one." + help_text="Series of total time of use demand charges for each month." + ) + + tou_demand_metrics = models.JSONField( + null=True, blank=True, + help_text="" + ) + + year_one_billed_facilitydemand_monthly_rate_tier_limits = models.JSONField( + null=True, blank=True, + help_text="" + ) + + year_one_billed_facilitydemand_monthly_rate_series = models.JSONField( + null=True, blank=True, + help_text="" + ) + + year_one_billed_tou_demand_rate_tier_limits = models.JSONField( + null=True, blank=True, + help_text="" + ) + + year_one_billed_energy_rate_tier_limits = models.JSONField( + null=True, blank=True, + help_text="" + ) + + year_one_billed_demand_rate_series = models.JSONField( + null=True, blank=True, + help_text="" ) year_one_energy_cost_before_tax = models.FloatField( From 84956395b6706938e6bd2228616afa7556a6c951 Mon Sep 17 00:00:00 2001 From: "Rathod, Bhavesh" Date: Thu, 16 Oct 2025 16:54:49 -0400 Subject: [PATCH 05/18] Add URDB fields to ElectricTariffOutputs model Added multiple new fields to the ElectricTariffOutputs model and migration to store URDB-related metadata, including label, rate name, utility, effective date, voltage level, rate description, peak kW capacity min/max, additional info, energy and demand comments, and URL link. These changes support enhanced storage and retrieval of utility rate information. --- ...ffoutputs_urdb_demand_comments_and_more.py | 73 +++++++++++++++++++ reoptjl/models.py | 49 +++++++++++++ 2 files changed, 122 insertions(+) create mode 100644 reoptjl/migrations/0107_electrictariffoutputs_urdb_demand_comments_and_more.py diff --git a/reoptjl/migrations/0107_electrictariffoutputs_urdb_demand_comments_and_more.py b/reoptjl/migrations/0107_electrictariffoutputs_urdb_demand_comments_and_more.py new file mode 100644 index 000000000..7dddf6eb4 --- /dev/null +++ b/reoptjl/migrations/0107_electrictariffoutputs_urdb_demand_comments_and_more.py @@ -0,0 +1,73 @@ +# Generated by Django 4.2.24 on 2025-10-16 20:43 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('reoptjl', '0106_electricloadoutputs_annual_peak_kw_and_more'), + ] + + operations = [ + migrations.AddField( + model_name='electrictariffoutputs', + name='urdb_demand_comments', + field=models.TextField(blank=True, help_text='Business as usual life cycle utility minimum charge adder, after-tax', null=True), + ), + migrations.AddField( + model_name='electrictariffoutputs', + name='urdb_energy_comments', + field=models.TextField(blank=True, help_text='Business as usual life cycle utility minimum charge adder, after-tax', null=True), + ), + migrations.AddField( + model_name='electrictariffoutputs', + name='urdb_label', + field=models.TextField(blank=True, help_text='Business as usual life cycle utility minimum charge adder, after-tax', null=True), + ), + migrations.AddField( + model_name='electrictariffoutputs', + name='urdb_peak_kw_capacity_max', + field=models.FloatField(blank=True, help_text='Business as usual life cycle utility minimum charge adder, after-tax', null=True), + ), + migrations.AddField( + model_name='electrictariffoutputs', + name='urdb_peak_kw_capacity_min', + field=models.FloatField(blank=True, help_text='Business as usual life cycle utility minimum charge adder, after-tax', null=True), + ), + migrations.AddField( + model_name='electrictariffoutputs', + name='urdb_rate_additional_info', + field=models.TextField(blank=True, help_text='Business as usual life cycle utility minimum charge adder, after-tax', null=True), + ), + migrations.AddField( + model_name='electrictariffoutputs', + name='urdb_rate_description', + field=models.TextField(blank=True, help_text='Business as usual life cycle utility minimum charge adder, after-tax', null=True), + ), + migrations.AddField( + model_name='electrictariffoutputs', + name='urdb_rate_effective_date', + field=models.TextField(blank=True, help_text='Business as usual life cycle utility minimum charge adder, after-tax', null=True), + ), + migrations.AddField( + model_name='electrictariffoutputs', + name='urdb_rate_name', + field=models.TextField(blank=True, help_text='Business as usual life cycle utility minimum charge adder, after-tax', null=True), + ), + migrations.AddField( + model_name='electrictariffoutputs', + name='urdb_url_link', + field=models.TextField(blank=True, help_text='Business as usual life cycle utility minimum charge adder, after-tax', null=True), + ), + migrations.AddField( + model_name='electrictariffoutputs', + name='urdb_utility', + field=models.TextField(blank=True, help_text='Business as usual life cycle utility minimum charge adder, after-tax', null=True), + ), + migrations.AddField( + model_name='electrictariffoutputs', + name='urdb_voltage_level', + field=models.TextField(blank=True, help_text='Business as usual life cycle utility minimum charge adder, after-tax', null=True), + ), + ] diff --git a/reoptjl/models.py b/reoptjl/models.py index c068360d1..d6c421075 100644 --- a/reoptjl/models.py +++ b/reoptjl/models.py @@ -2759,6 +2759,55 @@ class ElectricTariffOutputs(BaseModel, models.Model): help_text="" ) + urdb_label = models.TextField( + null=True, blank=True, + help_text="Business as usual life cycle utility minimum charge adder, after-tax" + ) + urdb_rate_name = models.TextField( + null=True, blank=True, + help_text="Business as usual life cycle utility minimum charge adder, after-tax" + ) + urdb_utility = models.TextField( + null=True, blank=True, + help_text="Business as usual life cycle utility minimum charge adder, after-tax" + ) + urdb_rate_effective_date = models.TextField( + null=True, blank=True, + help_text="Business as usual life cycle utility minimum charge adder, after-tax" + ) + urdb_voltage_level = models.TextField( + null=True, blank=True, + help_text="Business as usual life cycle utility minimum charge adder, after-tax" + ) + urdb_rate_description = models.TextField( + null=True, blank=True, + help_text="Business as usual life cycle utility minimum charge adder, after-tax" + ) + urdb_peak_kw_capacity_min = models.FloatField( + null=True, blank=True, + help_text="Business as usual life cycle utility minimum charge adder, after-tax" + ) + urdb_peak_kw_capacity_max = models.FloatField( + null=True, blank=True, + help_text="Business as usual life cycle utility minimum charge adder, after-tax" + ) + urdb_rate_additional_info = models.TextField( + null=True, blank=True, + help_text="Business as usual life cycle utility minimum charge adder, after-tax" + ) + urdb_energy_comments = models.TextField( + null=True, blank=True, + help_text="Business as usual life cycle utility minimum charge adder, after-tax" + ) + urdb_demand_comments = models.TextField( + null=True, blank=True, + help_text="Business as usual life cycle utility minimum charge adder, after-tax" + ) + urdb_url_link = models.TextField( + null=True, blank=True, + help_text="Business as usual life cycle utility minimum charge adder, after-tax" + ) + year_one_energy_cost_before_tax = models.FloatField( null=True, blank=True, help_text="Optimal year one utility energy cost" From aebd41ffd88fe8494670a322f8d66d6d7c2fd367 Mon Sep 17 00:00:00 2001 From: bill-becker Date: Wed, 22 Oct 2025 12:16:36 -0600 Subject: [PATCH 06/18] Update REopt#elec_util_usage after develop merge --- julia_src/Manifest.toml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/julia_src/Manifest.toml b/julia_src/Manifest.toml index 196aae6bd..794ce8c5e 100644 --- a/julia_src/Manifest.toml +++ b/julia_src/Manifest.toml @@ -948,9 +948,11 @@ version = "1.11.0" [[deps.REopt]] deps = ["ArchGDAL", "CSV", "CoolProp", "DataFrames", "Dates", "DelimitedFiles", "HTTP", "JLD", "JSON", "JuMP", "LinDistFlow", "LinearAlgebra", "Logging", "MathOptInterface", "Requires", "Roots", "Statistics", "TestEnv"] -git-tree-sha1 = "103761fa0f7447377726347af656cde6ab1160cc" +git-tree-sha1 = "dc4c262d7bab3c195154f48daa92451cf8769fea" +repo-rev = "elec_util_usage" +repo-url = "https://github.com/NREL/REopt.jl.git" uuid = "d36ad4e8-d74a-4f7a-ace1-eaea049febf6" -version = "0.55.1" +version = "0.55.0" [[deps.Random]] deps = ["SHA"] From a7fdea9b9f1fcc3125aa55a57b9e9cefbbcc6f24 Mon Sep 17 00:00:00 2001 From: bill-becker Date: Wed, 22 Oct 2025 12:17:05 -0600 Subject: [PATCH 07/18] Migration --merge after merging develop --- reoptjl/migrations/0110_merge_20251022_1752.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 reoptjl/migrations/0110_merge_20251022_1752.py diff --git a/reoptjl/migrations/0110_merge_20251022_1752.py b/reoptjl/migrations/0110_merge_20251022_1752.py new file mode 100644 index 000000000..cb76a4e89 --- /dev/null +++ b/reoptjl/migrations/0110_merge_20251022_1752.py @@ -0,0 +1,14 @@ +# Generated by Django 4.2.25 on 2025-10-22 17:52 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('reoptjl', '0107_electrictariffoutputs_urdb_demand_comments_and_more'), + ('reoptjl', '0109_remove_ghpoutputs_iterations_auto_guess_and_more'), + ] + + operations = [ + ] From 19d2bb2e1ca3527e4f47f12b19d63baf7aaf7377 Mon Sep 17 00:00:00 2001 From: bill-becker Date: Wed, 22 Oct 2025 17:08:40 -0600 Subject: [PATCH 08/18] Move urdb_metadata into ElectricTariffInputs and group into single json field instead of separate --- ...ffoutputs_urdb_demand_comments_and_more.py | 66 +++++++++++++++++++ reoptjl/models.py | 53 ++------------- 2 files changed, 70 insertions(+), 49 deletions(-) create mode 100644 reoptjl/migrations/0111_remove_electrictariffoutputs_urdb_demand_comments_and_more.py diff --git a/reoptjl/migrations/0111_remove_electrictariffoutputs_urdb_demand_comments_and_more.py b/reoptjl/migrations/0111_remove_electrictariffoutputs_urdb_demand_comments_and_more.py new file mode 100644 index 000000000..f4eeb281d --- /dev/null +++ b/reoptjl/migrations/0111_remove_electrictariffoutputs_urdb_demand_comments_and_more.py @@ -0,0 +1,66 @@ +# Generated by Django 4.2.25 on 2025-10-22 22:17 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('reoptjl', '0110_merge_20251022_1752'), + ] + + operations = [ + migrations.RemoveField( + model_name='electrictariffoutputs', + name='urdb_demand_comments', + ), + migrations.RemoveField( + model_name='electrictariffoutputs', + name='urdb_energy_comments', + ), + migrations.RemoveField( + model_name='electrictariffoutputs', + name='urdb_label', + ), + migrations.RemoveField( + model_name='electrictariffoutputs', + name='urdb_peak_kw_capacity_max', + ), + migrations.RemoveField( + model_name='electrictariffoutputs', + name='urdb_peak_kw_capacity_min', + ), + migrations.RemoveField( + model_name='electrictariffoutputs', + name='urdb_rate_additional_info', + ), + migrations.RemoveField( + model_name='electrictariffoutputs', + name='urdb_rate_description', + ), + migrations.RemoveField( + model_name='electrictariffoutputs', + name='urdb_rate_effective_date', + ), + migrations.RemoveField( + model_name='electrictariffoutputs', + name='urdb_rate_name', + ), + migrations.RemoveField( + model_name='electrictariffoutputs', + name='urdb_url_link', + ), + migrations.RemoveField( + model_name='electrictariffoutputs', + name='urdb_utility', + ), + migrations.RemoveField( + model_name='electrictariffoutputs', + name='urdb_voltage_level', + ), + migrations.AddField( + model_name='electrictariffinputs', + name='urdb_metadata', + field=models.JSONField(blank=True, help_text='Utility rate meta data from Utility Rate Database API', null=True), + ), + ] diff --git a/reoptjl/models.py b/reoptjl/models.py index 38ec9f3be..5e01d86f5 100644 --- a/reoptjl/models.py +++ b/reoptjl/models.py @@ -1738,6 +1738,10 @@ class ElectricTariffInputs(BaseModel, models.Model): help_text=("Optional coincident peak demand charge that is applied to the max load during the time_steps " "specified in coincident_peak_load_active_time_steps") ) + urdb_metadata = models.JSONField( + null=True, blank=True, + help_text=("Utility rate meta data from Utility Rate Database API") + ) def clean(self): error_messages = {} @@ -2799,55 +2803,6 @@ class ElectricTariffOutputs(BaseModel, models.Model): help_text="" ) - urdb_label = models.TextField( - null=True, blank=True, - help_text="Business as usual life cycle utility minimum charge adder, after-tax" - ) - urdb_rate_name = models.TextField( - null=True, blank=True, - help_text="Business as usual life cycle utility minimum charge adder, after-tax" - ) - urdb_utility = models.TextField( - null=True, blank=True, - help_text="Business as usual life cycle utility minimum charge adder, after-tax" - ) - urdb_rate_effective_date = models.TextField( - null=True, blank=True, - help_text="Business as usual life cycle utility minimum charge adder, after-tax" - ) - urdb_voltage_level = models.TextField( - null=True, blank=True, - help_text="Business as usual life cycle utility minimum charge adder, after-tax" - ) - urdb_rate_description = models.TextField( - null=True, blank=True, - help_text="Business as usual life cycle utility minimum charge adder, after-tax" - ) - urdb_peak_kw_capacity_min = models.FloatField( - null=True, blank=True, - help_text="Business as usual life cycle utility minimum charge adder, after-tax" - ) - urdb_peak_kw_capacity_max = models.FloatField( - null=True, blank=True, - help_text="Business as usual life cycle utility minimum charge adder, after-tax" - ) - urdb_rate_additional_info = models.TextField( - null=True, blank=True, - help_text="Business as usual life cycle utility minimum charge adder, after-tax" - ) - urdb_energy_comments = models.TextField( - null=True, blank=True, - help_text="Business as usual life cycle utility minimum charge adder, after-tax" - ) - urdb_demand_comments = models.TextField( - null=True, blank=True, - help_text="Business as usual life cycle utility minimum charge adder, after-tax" - ) - urdb_url_link = models.TextField( - null=True, blank=True, - help_text="Business as usual life cycle utility minimum charge adder, after-tax" - ) - year_one_energy_cost_before_tax = models.FloatField( null=True, blank=True, help_text="Optimal year one utility energy cost" From b2a3b6bebbb1c31ce576bb8955893f92cf0cb71b Mon Sep 17 00:00:00 2001 From: bill-becker Date: Wed, 22 Oct 2025 17:11:06 -0600 Subject: [PATCH 09/18] Rename export types to whole words --- ...et_metering_electric_to_grid_series_kw_.py | 73 +++++++++++++++++++ reoptjl/models.py | 24 +++--- 2 files changed, 85 insertions(+), 12 deletions(-) create mode 100644 reoptjl/migrations/0112_rename_nem_electric_to_grid_series_kw_electrictariffoutputs_net_metering_electric_to_grid_series_kw_.py diff --git a/reoptjl/migrations/0112_rename_nem_electric_to_grid_series_kw_electrictariffoutputs_net_metering_electric_to_grid_series_kw_.py b/reoptjl/migrations/0112_rename_nem_electric_to_grid_series_kw_electrictariffoutputs_net_metering_electric_to_grid_series_kw_.py new file mode 100644 index 000000000..5b99f0d3c --- /dev/null +++ b/reoptjl/migrations/0112_rename_nem_electric_to_grid_series_kw_electrictariffoutputs_net_metering_electric_to_grid_series_kw_.py @@ -0,0 +1,73 @@ +# Generated by Django 4.2.25 on 2025-10-22 22:21 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('reoptjl', '0111_remove_electrictariffoutputs_urdb_demand_comments_and_more'), + ] + + operations = [ + migrations.RenameField( + model_name='electrictariffoutputs', + old_name='NEM_electric_to_grid_series_kw', + new_name='net_metering_electric_to_grid_series_kw', + ), + migrations.RenameField( + model_name='electrictariffoutputs', + old_name='EXC_electric_to_grid_series_kw', + new_name='net_metering_excess_electric_to_grid_series_kw', + ), + migrations.RenameField( + model_name='electrictariffoutputs', + old_name='EXC_export_rate_series', + new_name='net_metering_excess_export_rate_series', + ), + migrations.RenameField( + model_name='electrictariffoutputs', + old_name='EXC_monthly_export_cost_benefit_before_tax', + new_name='net_metering_excess_monthly_export_cost_benefit_before_tax', + ), + migrations.RenameField( + model_name='electrictariffoutputs', + old_name='EXC_monthly_export_series_kwh', + new_name='net_metering_excess_monthly_export_series_kwh', + ), + migrations.RenameField( + model_name='electrictariffoutputs', + old_name='NEM_export_rate_series', + new_name='net_metering_export_rate_series', + ), + migrations.RenameField( + model_name='electrictariffoutputs', + old_name='NEM_monthly_export_cost_benefit_before_tax', + new_name='net_metering_monthly_export_cost_benefit_before_tax', + ), + migrations.RenameField( + model_name='electrictariffoutputs', + old_name='NEM_monthly_export_series_kwh', + new_name='net_metering_monthly_export_series_kwh', + ), + migrations.RenameField( + model_name='electrictariffoutputs', + old_name='WHL_electric_to_grid_series_kw', + new_name='wholesale_electric_to_grid_series_kw', + ), + migrations.RenameField( + model_name='electrictariffoutputs', + old_name='WHL_export_rate_series', + new_name='wholesale_export_rate_series', + ), + migrations.RenameField( + model_name='electrictariffoutputs', + old_name='WHL_monthly_export_cost_benefit_before_tax', + new_name='wholesale_monthly_export_cost_benefit_before_tax', + ), + migrations.RenameField( + model_name='electrictariffoutputs', + old_name='WHL_monthly_export_series_kwh', + new_name='wholesale_monthly_export_series_kwh', + ), + ] diff --git a/reoptjl/models.py b/reoptjl/models.py index 5e01d86f5..59786030a 100644 --- a/reoptjl/models.py +++ b/reoptjl/models.py @@ -2675,84 +2675,84 @@ class ElectricTariffOutputs(BaseModel, models.Model): default=list, help_text="Series of total time of use demand charges by month." ) - NEM_export_rate_series = ArrayField( + net_metering_export_rate_series = ArrayField( models.FloatField( null=True, blank=True ), default=list, help_text="Series of compensation rate in each timestep for exporting power to grid using systems sized up to net metering limit." ) - NEM_electric_to_grid_series_kw = ArrayField( + net_metering_electric_to_grid_series_kw = ArrayField( models.FloatField( null=True, blank=True ), default=list, help_text="Series of power exports to the grid up to net metering limit for each timestep." ) - NEM_monthly_export_series_kwh = ArrayField( + net_metering_monthly_export_series_kwh = ArrayField( models.FloatField( null=True, blank=True ), default=list, help_text="Year one cost of electricity consumed in each month." ) - NEM_monthly_export_cost_benefit_before_tax = ArrayField( + net_metering_monthly_export_cost_benefit_before_tax = ArrayField( models.FloatField( null=True, blank=True ), default=list, help_text="Year one cost of electricity consumed in each month." ) - WHL_export_rate_series = ArrayField( + wholesale_export_rate_series = ArrayField( models.FloatField( null=True, blank=True ), default=list, help_text="Series of compensation rate in each timestep for exporting power to grid for wholesale." ) - WHL_electric_to_grid_series_kw = ArrayField( + wholesale_electric_to_grid_series_kw = ArrayField( models.FloatField( null=True, blank=True ), default=list, help_text="Series of power exports to the grid for wholesale in each timestep." ) - WHL_monthly_export_series_kwh = ArrayField( + wholesale_monthly_export_series_kwh = ArrayField( models.FloatField( null=True, blank=True ), default=list, help_text="Series of monthly energy exports to grid under wholesale benefit." ) - WHL_monthly_export_cost_benefit_before_tax = ArrayField( + wholesale_monthly_export_cost_benefit_before_tax = ArrayField( models.FloatField( null=True, blank=True ), default=list, help_text="Series of monthly monetary benefit from exporting power to grid at wholesale rate." ) - EXC_export_rate_series = ArrayField( + net_metering_excess_export_rate_series = ArrayField( models.FloatField( null=True, blank=True ), default=list, help_text="Series of compensation rate in each timestep for exporting power to grid beyond net metering limit." ) - EXC_electric_to_grid_series_kw = ArrayField( + net_metering_excess_electric_to_grid_series_kw = ArrayField( models.FloatField( null=True, blank=True ), default=list, help_text="Series of power exports to the grid above net metering limit for each timestep." ) - EXC_monthly_export_series_kwh = ArrayField( + net_metering_excess_monthly_export_series_kwh = ArrayField( models.FloatField( null=True, blank=True ), default=list, help_text="Series of monthly energy exports to grid above net metering limit." ) - EXC_monthly_export_cost_benefit_before_tax = ArrayField( + net_metering_excess_monthly_export_cost_benefit_before_tax = ArrayField( models.FloatField( null=True, blank=True ), From 1a3e4fd84dada8ab012ee2fcffca42a52621d134 Mon Sep 17 00:00:00 2001 From: bill-becker Date: Wed, 22 Oct 2025 17:24:28 -0600 Subject: [PATCH 10/18] Update ElectricTariffInputs urdb_metadata from Julia in process_results --- julia_src/Manifest.toml | 4 ++-- julia_src/http.jl | 11 ++++++++++- reoptjl/src/process_results.py | 5 ++++- 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/julia_src/Manifest.toml b/julia_src/Manifest.toml index 794ce8c5e..88fc351af 100644 --- a/julia_src/Manifest.toml +++ b/julia_src/Manifest.toml @@ -948,11 +948,11 @@ version = "1.11.0" [[deps.REopt]] deps = ["ArchGDAL", "CSV", "CoolProp", "DataFrames", "Dates", "DelimitedFiles", "HTTP", "JLD", "JSON", "JuMP", "LinDistFlow", "LinearAlgebra", "Logging", "MathOptInterface", "Requires", "Roots", "Statistics", "TestEnv"] -git-tree-sha1 = "dc4c262d7bab3c195154f48daa92451cf8769fea" +git-tree-sha1 = "18d4e3f1c74fa7804716f9fedf53f9c0755c7248" repo-rev = "elec_util_usage" repo-url = "https://github.com/NREL/REopt.jl.git" uuid = "d36ad4e8-d74a-4f7a-ace1-eaea049febf6" -version = "0.55.0" +version = "0.55.1" [[deps.Random]] deps = ["SHA"] diff --git a/julia_src/http.jl b/julia_src/http.jl index 817b8837d..4674fd24e 100644 --- a/julia_src/http.jl +++ b/julia_src/http.jl @@ -237,6 +237,14 @@ function reopt(req::HTTP.Request) high_temp_storage_dict = Dict(key=>getfield(model_inputs.s.storage.attr["HighTempThermalStorage"], key) for key in inputs_with_defaults_from_julia_high_temp_storage) else high_temp_storage_dict = Dict() + end + if haskey(d, "ElectricTariff") && !isempty(get(d["ElectricTariff"], "urdb_metadata", Dict())) + inputs_from_julia_electric_tariff = [ + :urdb_metadata + ] + electric_tariff_dict = Dict(key=>getfield(model_inputs.s.electric_tariff, key) for key in inputs_from_julia_electric_tariff) + else + electric_tariff_dict = Dict() end inputs_with_defaults_set_in_julia = Dict( "Financial" => Dict(key=>getfield(model_inputs.s.financial, key) for key in inputs_with_defaults_from_julia_financial), @@ -253,7 +261,8 @@ function reopt(req::HTTP.Request) "ElectricStorage" => electric_storage_dict, "ColdThermalStorage" => cold_storage_dict, "HotThermalStorage" => hot_storage_dict, - "HighTempThermalStorage" => high_temp_storage_dict + "HighTempThermalStorage" => high_temp_storage_dict, + "ElectricTariff" => electric_tariff_dict ) catch e @error "Something went wrong in REopt optimization!" exception=(e, catch_backtrace()) diff --git a/reoptjl/src/process_results.py b/reoptjl/src/process_results.py index 20b26e209..22bf0a292 100644 --- a/reoptjl/src/process_results.py +++ b/reoptjl/src/process_results.py @@ -9,7 +9,7 @@ SteamTurbineOutputs, GHPInputs, GHPOutputs, ExistingChillerInputs, \ ElectricHeaterOutputs, ASHPSpaceHeaterOutputs, ASHPWaterHeaterOutputs, \ SiteInputs, ASHPSpaceHeaterInputs, ASHPWaterHeaterInputs, CSTInputs, CSTOutputs, PVInputs, \ - HighTempThermalStorageInputs, HighTempThermalStorageOutputs + HighTempThermalStorageInputs, HighTempThermalStorageOutputs, ElectricTariffInputs import numpy as np import sys import traceback as tb @@ -179,6 +179,9 @@ def update_inputs_in_database(inputs_to_update: dict, run_uuid: str) -> None: if inputs_to_update.get("HighTempThermalStorage") is not None: prune_update_fields(HighTempThermalStorageInputs, inputs_to_update["HighTempThermalStorage"]) HighTempThermalStorageInputs.objects.filter(meta__run_uuid=run_uuid).update(**inputs_to_update["HighTempThermalStorage"]) + if inputs_to_update.get("ElectricTariff"): + prune_update_fields(ElectricTariffInputs, inputs_to_update["ElectricTariff"]) + ElectricTariffInputs.objects.filter(meta__run_uuid=run_uuid).update(**inputs_to_update["ElectricTariff"]) except Exception as e: exc_type, exc_value, exc_traceback = sys.exc_info() debug_msg = "exc_type: {}; exc_value: {}; exc_traceback: {}".format( From 242dede222411baeefdc5ccdc67e1b8db39cb1d9 Mon Sep 17 00:00:00 2001 From: bill-becker Date: Wed, 22 Oct 2025 20:37:18 -0600 Subject: [PATCH 11/18] Avoid error handling breakdown if ElectricTariff is not present, and fix check for urdb_metadata --- julia_src/http.jl | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/julia_src/http.jl b/julia_src/http.jl index 4674fd24e..b59e8f418 100644 --- a/julia_src/http.jl +++ b/julia_src/http.jl @@ -238,7 +238,7 @@ function reopt(req::HTTP.Request) else high_temp_storage_dict = Dict() end - if haskey(d, "ElectricTariff") && !isempty(get(d["ElectricTariff"], "urdb_metadata", Dict())) + if haskey(d, "ElectricTariff") && !isempty(model_inputs.s.electric_tariff.urdb_metadata) inputs_from_julia_electric_tariff = [ :urdb_metadata ] @@ -283,9 +283,11 @@ function reopt(req::HTTP.Request) if isempty(error_response) @info "REopt model solved with status $(results["status"])." - # these are matrices that need to be vector. - results["ElectricTariff"]["year_one_electric_to_load_energy_cost_series_before_tax"] = results["ElectricTariff"]["year_one_electric_to_load_energy_cost_series_before_tax"][:,1] - results["ElectricTariff"]["monthly_facility_demand_cost_series_before_tax"] = results["ElectricTariff"]["monthly_facility_demand_cost_series_before_tax"][:,1] + # These are matrices that need to be vector. + if haskey(results, "ElectricTariff") + results["ElectricTariff"]["year_one_electric_to_load_energy_cost_series_before_tax"] = results["ElectricTariff"]["year_one_electric_to_load_energy_cost_series_before_tax"][:,1] + results["ElectricTariff"]["monthly_facility_demand_cost_series_before_tax"] = results["ElectricTariff"]["monthly_facility_demand_cost_series_before_tax"][:,1] + end response = Dict( "results" => results, "reopt_version" => string(pkgversion(reoptjl)) From 8260d010970ea1d98c659d2857c0f0e34d3a7f3a Mon Sep 17 00:00:00 2001 From: bill-becker Date: Wed, 22 Oct 2025 20:37:52 -0600 Subject: [PATCH 12/18] Update to latest REopt#elec_util_usage --- julia_src/Manifest.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/julia_src/Manifest.toml b/julia_src/Manifest.toml index 88fc351af..a9dd913a1 100644 --- a/julia_src/Manifest.toml +++ b/julia_src/Manifest.toml @@ -948,7 +948,7 @@ version = "1.11.0" [[deps.REopt]] deps = ["ArchGDAL", "CSV", "CoolProp", "DataFrames", "Dates", "DelimitedFiles", "HTTP", "JLD", "JSON", "JuMP", "LinDistFlow", "LinearAlgebra", "Logging", "MathOptInterface", "Requires", "Roots", "Statistics", "TestEnv"] -git-tree-sha1 = "18d4e3f1c74fa7804716f9fedf53f9c0755c7248" +git-tree-sha1 = "0a5d1d2a086cd400d9b0e4758b34da51a07d6dbd" repo-rev = "elec_util_usage" repo-url = "https://github.com/NREL/REopt.jl.git" uuid = "d36ad4e8-d74a-4f7a-ace1-eaea049febf6" From 60d90fe9c5430b8b01a6a0f5c23de85625ba6661 Mon Sep 17 00:00:00 2001 From: bill-becker Date: Wed, 22 Oct 2025 20:38:53 -0600 Subject: [PATCH 13/18] Reduce complexity of long-solving sector defaults test --- reoptjl/test/posts/sector_defaults_post.json | 40 +++++--------------- reoptjl/test/test_job_endpoint.py | 2 - 2 files changed, 10 insertions(+), 32 deletions(-) diff --git a/reoptjl/test/posts/sector_defaults_post.json b/reoptjl/test/posts/sector_defaults_post.json index 1df5abbae..ca174468f 100644 --- a/reoptjl/test/posts/sector_defaults_post.json +++ b/reoptjl/test/posts/sector_defaults_post.json @@ -23,44 +23,24 @@ "ExistingBoiler": { "fuel_cost_per_mmbtu": 10.0 }, - "CHP": { - "prime_mover": "recip_engine", - "max_kw": 100, - "fuel_cost_per_mmbtu": 10.0, - "can_supply_steam_turbine": true - }, "PV": { "min_kw": 1000.0, "max_kw": 1000.0, "federal_itc_fraction": 0.2 }, - "SteamTurbine":{ - "min_kw": 100, - "max_kw": 100 - }, - "HighTempThermalStorage": { - "min_kwh": 10, - "max_kwh": 10, - "thermal_decay_rate_fraction": 0.0 - }, "Wind": { "min_kw": 100, "max_kw": 100 }, - "GHP": { - "require_ghp_purchase": true, - "building_sqft": 50000.0, - "can_serve_dhw": false, - "space_heating_efficiency_thermal_factor": 0.85, - "cooling_efficiency_thermal_factor": 0.6, - "ghpghx_inputs": [{ - "borehole_depth_ft": 400.0, - "simulation_years": 20, - "solver_eft_tolerance_f": 2.0, - "ghx_model": "TESS", - "tess_ghx_minimum_timesteps_per_hour": 1, - "max_sizing_iterations": 10, - "init_sizing_factor_ft_per_peak_ton": 300.0 - }] + "ElectricStorage": { + "min_kw": 50, + "max_kw": 50, + "min_kwh": 100, + "max_kwh": 100 + }, + "Boiler": { + "fuel_cost_per_mmbtu": 10.0, + "min_mmbtu_per_hour": 0.5, + "max_mmbtu_per_hour": 0.5 } } \ No newline at end of file diff --git a/reoptjl/test/test_job_endpoint.py b/reoptjl/test/test_job_endpoint.py index 6f74663aa..f880ba921 100644 --- a/reoptjl/test/test_job_endpoint.py +++ b/reoptjl/test/test_job_endpoint.py @@ -178,8 +178,6 @@ def test_sector_defaults_from_julia(self): self.assertEqual(saved_model_inputs.get(input_key), post[model_name][input_key]) else: # Check that default got assigned consistent with /sector_defaults - if model_name == "SteamTurbine" and input_key == "federal_itc_fraction": - continue #ST doesn't have federal_itc_fraction input self.assertEqual(saved_model_inputs.get(input_key), default_input_val) def test_chp_defaults_from_julia(self): From 6cadf5b798c41dfcd7cf615f2837707eae434c8f Mon Sep 17 00:00:00 2001 From: bill-becker Date: Thu, 23 Oct 2025 16:35:33 -0600 Subject: [PATCH 14/18] Make output.ElectricLoad.monthly_peak_kw consistent with upcoming new input monthly_peaks_kw --- ..._kw_electricloadoutputs_monthly_peaks_kw.py | 18 ++++++++++++++++++ reoptjl/models.py | 2 +- 2 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 reoptjl/migrations/0113_rename_monthly_peak_kw_electricloadoutputs_monthly_peaks_kw.py diff --git a/reoptjl/migrations/0113_rename_monthly_peak_kw_electricloadoutputs_monthly_peaks_kw.py b/reoptjl/migrations/0113_rename_monthly_peak_kw_electricloadoutputs_monthly_peaks_kw.py new file mode 100644 index 000000000..625c6323c --- /dev/null +++ b/reoptjl/migrations/0113_rename_monthly_peak_kw_electricloadoutputs_monthly_peaks_kw.py @@ -0,0 +1,18 @@ +# Generated by Django 4.2.25 on 2025-10-23 22:33 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('reoptjl', '0112_rename_nem_electric_to_grid_series_kw_electrictariffoutputs_net_metering_electric_to_grid_series_kw_'), + ] + + operations = [ + migrations.RenameField( + model_name='electricloadoutputs', + old_name='monthly_peak_kw', + new_name='monthly_peaks_kw', + ), + ] diff --git a/reoptjl/models.py b/reoptjl/models.py index 59786030a..b46c33482 100644 --- a/reoptjl/models.py +++ b/reoptjl/models.py @@ -1553,7 +1553,7 @@ class ElectricLoadOutputs(BaseModel, models.Model): default=list, help_text="Monthly energy consumption calculated by summing up load_series_kw. Does not include electric load for any new heating or cooling techs." ) - monthly_peak_kw = ArrayField( + monthly_peaks_kw = ArrayField( models.FloatField( null=True, blank=True ), From 08f8e1e12fcfee902bf7d7d2ac93f65bc4da5231 Mon Sep 17 00:00:00 2001 From: bill-becker Date: Thu, 23 Oct 2025 19:01:49 -0600 Subject: [PATCH 15/18] Update REopt#elec_util_usage for updated monthly_peaks_kw name --- julia_src/Manifest.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/julia_src/Manifest.toml b/julia_src/Manifest.toml index a9dd913a1..16e510202 100644 --- a/julia_src/Manifest.toml +++ b/julia_src/Manifest.toml @@ -948,7 +948,7 @@ version = "1.11.0" [[deps.REopt]] deps = ["ArchGDAL", "CSV", "CoolProp", "DataFrames", "Dates", "DelimitedFiles", "HTTP", "JLD", "JSON", "JuMP", "LinDistFlow", "LinearAlgebra", "Logging", "MathOptInterface", "Requires", "Roots", "Statistics", "TestEnv"] -git-tree-sha1 = "0a5d1d2a086cd400d9b0e4758b34da51a07d6dbd" +git-tree-sha1 = "277df4545cd30a5fc227bf982897ef65d5ea3520" repo-rev = "elec_util_usage" repo-url = "https://github.com/NREL/REopt.jl.git" uuid = "d36ad4e8-d74a-4f7a-ace1-eaea049febf6" From 34a980a5f0162f2cf6e2f6ddaf1e68a0a6f03a4c Mon Sep 17 00:00:00 2001 From: bill-becker Date: Tue, 28 Oct 2025 11:55:21 -0600 Subject: [PATCH 16/18] ElectricTariffOuputs Updates --- reoptjl/models.py | 155 +++++++++++++++------------------------------- 1 file changed, 49 insertions(+), 106 deletions(-) diff --git a/reoptjl/models.py b/reoptjl/models.py index b46c33482..a56a34318 100644 --- a/reoptjl/models.py +++ b/reoptjl/models.py @@ -2625,184 +2625,127 @@ class ElectricTariffOutputs(BaseModel, models.Model): related_name="ElectricTariffOutputs", primary_key=True ) - year_one_monthly_fixed_cost = ArrayField( - models.FloatField( - null=True, blank=True - ), - default=list, - help_text="Year one fixed utility costs for each month." - ) - year_one_electric_to_load_energy_cost_series_before_tax = ArrayField( - models.FloatField( - null=True, blank=True - ), - default=list, - help_text="Series of cost of power purchased from grid to serve load in each timestep." - ) - monthly_electric_to_load_energy_cost_series_before_tax = ArrayField( - models.FloatField( - null=True, blank=True - ), - default=list, - help_text="Series of monthly cost of power purchased from grid to serve loads." - ) - year_one_electric_to_storage_energy_cost_series_before_tax = ArrayField( + monthly_fixed_cost = ArrayField( models.FloatField( null=True, blank=True ), default=list, - help_text="Series of cost of power purchased from grid to charge battery storage system in each timestep." - ) - monthly_electric_to_storage_energy_cost_series_before_tax = ArrayField( - models.FloatField( - null=True, blank=True - ), - default=list, - help_text="Series of monthly cost of power purchased from grid to charge battery storage system." - ) - monthly_facility_demand_cost_series_before_tax = ArrayField( - models.FloatField( - null=True, blank=True - ), - default=list, - help_text="Series of total monthly facility demand charges by month." - ) - monthly_gross_tou_demand_cost_series_before_tax = ArrayField( - models.FloatField( - null=True, blank=True - ), - default=list, - help_text="Series of total time of use demand charges by month." + help_text="Year one fixed utility costs for each month." ) - net_metering_export_rate_series = ArrayField( + monthly_fixed_cost_bau = ArrayField( models.FloatField( null=True, blank=True ), default=list, - help_text="Series of compensation rate in each timestep for exporting power to grid using systems sized up to net metering limit." + help_text="Business as usual year one fixed utility costs for each month." ) - net_metering_electric_to_grid_series_kw = ArrayField( - models.FloatField( - null=True, blank=True - ), - default=list, - help_text="Series of power exports to the grid up to net metering limit for each timestep." + energy_cost_series_before_tax = models.JSONField( + null=True, blank=True, + help_text="Series of cost of power purchased from grid to serve load in each timestep, by Tier_i." ) - net_metering_monthly_export_series_kwh = ArrayField( - models.FloatField( - null=True, blank=True - ), - default=list, - help_text="Year one cost of electricity consumed in each month." + energy_cost_series_before_tax_bau = models.JSONField( + null=True, blank=True, + help_text="Business as usual series of cost of power purchased from grid to serve load in each timestep, by Tier_i." ) - net_metering_monthly_export_cost_benefit_before_tax = ArrayField( + monthly_energy_cost_series_before_tax = ArrayField( models.FloatField( null=True, blank=True ), default=list, - help_text="Year one cost of electricity consumed in each month." + help_text="Series of monthly cost of power purchased from grid to serve loads." ) - wholesale_export_rate_series = ArrayField( + monthly_energy_cost_series_before_tax_bau = ArrayField( models.FloatField( null=True, blank=True ), default=list, - help_text="Series of compensation rate in each timestep for exporting power to grid for wholesale." + help_text="Business as usual series of monthly cost of power purchased from grid to serve loads." ) - wholesale_electric_to_grid_series_kw = ArrayField( + monthly_facility_demand_cost_series_before_tax = ArrayField( models.FloatField( null=True, blank=True ), default=list, - help_text="Series of power exports to the grid for wholesale in each timestep." + help_text="Series of total (all tiers) monthly facility demand charges by month." ) - wholesale_monthly_export_series_kwh = ArrayField( + monthly_facility_demand_cost_series_before_tax_bau = ArrayField( models.FloatField( null=True, blank=True ), default=list, - help_text="Series of monthly energy exports to grid under wholesale benefit." + help_text="Business as usual series of total (all tiers) monthly facility demand charges by month." ) - wholesale_monthly_export_cost_benefit_before_tax = ArrayField( - models.FloatField( - null=True, blank=True - ), - default=list, - help_text="Series of monthly monetary benefit from exporting power to grid at wholesale rate." + energy_rate_series = models.JSONField( + null=True, blank=True, + help_text="Series of billed energy rates for each timestep in year one." ) - net_metering_excess_export_rate_series = ArrayField( + energy_rate_average_series = ArrayField( models.FloatField( null=True, blank=True ), default=list, - help_text="Series of compensation rate in each timestep for exporting power to grid beyond net metering limit." + help_text="Series of average (across tiers) energy rates for each timestep in year one." ) - net_metering_excess_electric_to_grid_series_kw = ArrayField( + monthly_tou_demand_cost_series_before_tax = ArrayField( models.FloatField( null=True, blank=True ), default=list, - help_text="Series of power exports to the grid above net metering limit for each timestep." + help_text="Series of total time-of-use demand charges for each month." ) - net_metering_excess_monthly_export_series_kwh = ArrayField( + monthly_tou_demand_cost_series_before_tax_bau = ArrayField( models.FloatField( null=True, blank=True ), default=list, - help_text="Series of monthly energy exports to grid above net metering limit." + help_text="Business as usual series of total time-of-use demand charges for each month." ) - net_metering_excess_monthly_export_cost_benefit_before_tax = ArrayField( + monthly_demand_cost_series_before_tax = ArrayField( models.FloatField( null=True, blank=True ), default=list, - help_text="Series of monthly monetary benefit from exporting power to grid above net metering limit." + help_text="Series of total (facility and TOU for all tiers) monthly demand charges for each month." ) - - year_one_billed_energy_rate_series = models.JSONField( - null=True, blank=True, - help_text="Series of billed energy rates for each timestep in year one." - ) - - monthly_tou_demand_cost_series_before_tax = ArrayField( + monthly_demand_cost_series_before_tax_bau = ArrayField( models.FloatField( null=True, blank=True ), default=list, - help_text="Series of total time of use demand charges for each month." + help_text="Business as usual series of total (facility and TOU for all tiers) monthly demand charges for each month." ) - tou_demand_metrics = models.JSONField( null=True, blank=True, - help_text="" + help_text="Dictionary of TOU demand metrics, including month, tier, demand_rate, measured_tou_peak_demand, and demand_charge_before_tax" ) - - year_one_billed_facilitydemand_monthly_rate_tier_limits = models.JSONField( + facility_demand_monthly_rate_tier_limits = models.JSONField( null=True, blank=True, - help_text="" + help_text="Facility (not dependent on TOU) demand charge tier limits" ) - - year_one_billed_facilitydemand_monthly_rate_series = models.JSONField( + facility_demand_monthly_rate_series = models.JSONField( null=True, blank=True, - help_text="" + help_text="Facility (not dependent on TOU) demand charge rates by Tier_i" ) - - year_one_billed_tou_demand_rate_tier_limits = models.JSONField( + tou_demand_rate_tier_limits = models.JSONField( null=True, blank=True, - help_text="" + help_text="TOU demand rate tier limits" ) - - year_one_billed_energy_rate_tier_limits = models.JSONField( + energy_rate_tier_limits = models.JSONField( null=True, blank=True, - help_text="" + help_text="Energy rate tier limits" ) - - year_one_billed_demand_rate_series = models.JSONField( + tou_demand_rate_series = models.JSONField( null=True, blank=True, - help_text="" + help_text="Series of demand rates by Tier_i for each timestep." + ) + demand_rate_average_series = ArrayField( + models.FloatField( + null=True, blank=True + ), + default=list, + help_text="Series of average (across tiers) demand rates for each timestep in year one." ) - year_one_energy_cost_before_tax = models.FloatField( null=True, blank=True, help_text="Optimal year one utility energy cost" From 06f761eabac8fad43b3cd40ac1aebb5a28ba7ca2 Mon Sep 17 00:00:00 2001 From: bill-becker Date: Tue, 28 Oct 2025 11:56:09 -0600 Subject: [PATCH 17/18] Remove separate migrations for ElectricTariff --- ...tricloadoutputs_annual_peak_kw_and_more.py | 164 ------------------ ...ffoutputs_urdb_demand_comments_and_more.py | 73 -------- .../migrations/0110_merge_20251022_1752.py | 14 -- ...ffoutputs_urdb_demand_comments_and_more.py | 66 ------- ...et_metering_electric_to_grid_series_kw_.py | 73 -------- ...kw_electricloadoutputs_monthly_peaks_kw.py | 18 -- 6 files changed, 408 deletions(-) delete mode 100644 reoptjl/migrations/0106_electricloadoutputs_annual_peak_kw_and_more.py delete mode 100644 reoptjl/migrations/0107_electrictariffoutputs_urdb_demand_comments_and_more.py delete mode 100644 reoptjl/migrations/0110_merge_20251022_1752.py delete mode 100644 reoptjl/migrations/0111_remove_electrictariffoutputs_urdb_demand_comments_and_more.py delete mode 100644 reoptjl/migrations/0112_rename_nem_electric_to_grid_series_kw_electrictariffoutputs_net_metering_electric_to_grid_series_kw_.py delete mode 100644 reoptjl/migrations/0113_rename_monthly_peak_kw_electricloadoutputs_monthly_peaks_kw.py diff --git a/reoptjl/migrations/0106_electricloadoutputs_annual_peak_kw_and_more.py b/reoptjl/migrations/0106_electricloadoutputs_annual_peak_kw_and_more.py deleted file mode 100644 index 8add1d9cb..000000000 --- a/reoptjl/migrations/0106_electricloadoutputs_annual_peak_kw_and_more.py +++ /dev/null @@ -1,164 +0,0 @@ -# Generated by Django 4.2.24 on 2025-10-06 17:06 - -import django.contrib.postgres.fields -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('reoptjl', '0105_alter_chpoutputs_initial_capital_costs_and_more'), - ] - - operations = [ - migrations.AddField( - model_name='electricloadoutputs', - name='annual_peak_kw', - field=models.FloatField(blank=True, help_text='Annual peak energy demand determined from load_series_kw. Does not include electric load for any new heating or cooling techs.', null=True), - ), - migrations.AddField( - model_name='electricloadoutputs', - name='monthly_calculated_kwh', - field=django.contrib.postgres.fields.ArrayField(base_field=models.FloatField(blank=True, null=True), default=list, help_text='Monthly energy consumption calculated by summing up load_series_kw. Does not include electric load for any new heating or cooling techs.', size=None), - ), - migrations.AddField( - model_name='electricloadoutputs', - name='monthly_peak_kw', - field=django.contrib.postgres.fields.ArrayField(base_field=models.FloatField(blank=True, null=True), default=list, help_text='Monthly peak energy demand determined from load_series_kw. Does not include electric load for any new heating or cooling techs.', size=None), - ), - migrations.AddField( - model_name='electrictariffoutputs', - name='EXC_electric_to_grid_series_kw', - field=django.contrib.postgres.fields.ArrayField(base_field=models.FloatField(blank=True, null=True), default=list, help_text='Series of power exports to the grid above net metering limit for each timestep.', size=None), - ), - migrations.AddField( - model_name='electrictariffoutputs', - name='EXC_export_rate_series', - field=django.contrib.postgres.fields.ArrayField(base_field=models.FloatField(blank=True, null=True), default=list, help_text='Series of compensation rate in each timestep for exporting power to grid beyond net metering limit.', size=None), - ), - migrations.AddField( - model_name='electrictariffoutputs', - name='EXC_monthly_export_cost_benefit_before_tax', - field=django.contrib.postgres.fields.ArrayField(base_field=models.FloatField(blank=True, null=True), default=list, help_text='Series of monthly monetary benefit from exporting power to grid above net metering limit.', size=None), - ), - migrations.AddField( - model_name='electrictariffoutputs', - name='EXC_monthly_export_series_kwh', - field=django.contrib.postgres.fields.ArrayField(base_field=models.FloatField(blank=True, null=True), default=list, help_text='Series of monthly energy exports to grid above net metering limit.', size=None), - ), - migrations.AddField( - model_name='electrictariffoutputs', - name='NEM_electric_to_grid_series_kw', - field=django.contrib.postgres.fields.ArrayField(base_field=models.FloatField(blank=True, null=True), default=list, help_text='Series of power exports to the grid up to net metering limit for each timestep.', size=None), - ), - migrations.AddField( - model_name='electrictariffoutputs', - name='NEM_export_rate_series', - field=django.contrib.postgres.fields.ArrayField(base_field=models.FloatField(blank=True, null=True), default=list, help_text='Series of compensation rate in each timestep for exporting power to grid using systems sized up to net metering limit.', size=None), - ), - migrations.AddField( - model_name='electrictariffoutputs', - name='NEM_monthly_export_cost_benefit_before_tax', - field=django.contrib.postgres.fields.ArrayField(base_field=models.FloatField(blank=True, null=True), default=list, help_text='Year one cost of electricity consumed in each month.', size=None), - ), - migrations.AddField( - model_name='electrictariffoutputs', - name='NEM_monthly_export_series_kwh', - field=django.contrib.postgres.fields.ArrayField(base_field=models.FloatField(blank=True, null=True), default=list, help_text='Year one cost of electricity consumed in each month.', size=None), - ), - migrations.AddField( - model_name='electrictariffoutputs', - name='WHL_electric_to_grid_series_kw', - field=django.contrib.postgres.fields.ArrayField(base_field=models.FloatField(blank=True, null=True), default=list, help_text='Series of power exports to the grid for wholesale in each timestep.', size=None), - ), - migrations.AddField( - model_name='electrictariffoutputs', - name='WHL_export_rate_series', - field=django.contrib.postgres.fields.ArrayField(base_field=models.FloatField(blank=True, null=True), default=list, help_text='Series of compensation rate in each timestep for exporting power to grid for wholesale.', size=None), - ), - migrations.AddField( - model_name='electrictariffoutputs', - name='WHL_monthly_export_cost_benefit_before_tax', - field=django.contrib.postgres.fields.ArrayField(base_field=models.FloatField(blank=True, null=True), default=list, help_text='Series of monthly monetary benefit from exporting power to grid at wholesale rate.', size=None), - ), - migrations.AddField( - model_name='electrictariffoutputs', - name='WHL_monthly_export_series_kwh', - field=django.contrib.postgres.fields.ArrayField(base_field=models.FloatField(blank=True, null=True), default=list, help_text='Series of monthly energy exports to grid under wholesale benefit.', size=None), - ), - migrations.AddField( - model_name='electrictariffoutputs', - name='monthly_electric_to_load_energy_cost_series_before_tax', - field=django.contrib.postgres.fields.ArrayField(base_field=models.FloatField(blank=True, null=True), default=list, help_text='Series of monthly cost of power purchased from grid to serve loads.', size=None), - ), - migrations.AddField( - model_name='electrictariffoutputs', - name='monthly_electric_to_storage_energy_cost_series_before_tax', - field=django.contrib.postgres.fields.ArrayField(base_field=models.FloatField(blank=True, null=True), default=list, help_text='Series of monthly cost of power purchased from grid to charge battery storage system.', size=None), - ), - migrations.AddField( - model_name='electrictariffoutputs', - name='monthly_facility_demand_cost_series_before_tax', - field=django.contrib.postgres.fields.ArrayField(base_field=models.FloatField(blank=True, null=True), default=list, help_text='Series of total monthly facility demand charges by month.', size=None), - ), - migrations.AddField( - model_name='electrictariffoutputs', - name='monthly_gross_tou_demand_cost_series_before_tax', - field=django.contrib.postgres.fields.ArrayField(base_field=models.FloatField(blank=True, null=True), default=list, help_text='Series of total time of use demand charges by month.', size=None), - ), - migrations.AddField( - model_name='electrictariffoutputs', - name='monthly_tou_demand_cost_series_before_tax', - field=django.contrib.postgres.fields.ArrayField(base_field=models.FloatField(blank=True, null=True), default=list, help_text='Series of total time of use demand charges for each month.', size=None), - ), - migrations.AddField( - model_name='electrictariffoutputs', - name='tou_demand_metrics', - field=models.JSONField(blank=True, null=True), - ), - migrations.AddField( - model_name='electrictariffoutputs', - name='year_one_billed_demand_rate_series', - field=models.JSONField(blank=True, null=True), - ), - migrations.AddField( - model_name='electrictariffoutputs', - name='year_one_billed_energy_rate_series', - field=models.JSONField(blank=True, help_text='Series of billed energy rates for each timestep in year one.', null=True), - ), - migrations.AddField( - model_name='electrictariffoutputs', - name='year_one_billed_energy_rate_tier_limits', - field=models.JSONField(blank=True, null=True), - ), - migrations.AddField( - model_name='electrictariffoutputs', - name='year_one_billed_facilitydemand_monthly_rate_series', - field=models.JSONField(blank=True, null=True), - ), - migrations.AddField( - model_name='electrictariffoutputs', - name='year_one_billed_facilitydemand_monthly_rate_tier_limits', - field=models.JSONField(blank=True, null=True), - ), - migrations.AddField( - model_name='electrictariffoutputs', - name='year_one_billed_tou_demand_rate_tier_limits', - field=models.JSONField(blank=True, null=True), - ), - migrations.AddField( - model_name='electrictariffoutputs', - name='year_one_electric_to_load_energy_cost_series_before_tax', - field=django.contrib.postgres.fields.ArrayField(base_field=models.FloatField(blank=True, null=True), default=list, help_text='Series of cost of power purchased from grid to serve load in each timestep.', size=None), - ), - migrations.AddField( - model_name='electrictariffoutputs', - name='year_one_electric_to_storage_energy_cost_series_before_tax', - field=django.contrib.postgres.fields.ArrayField(base_field=models.FloatField(blank=True, null=True), default=list, help_text='Series of cost of power purchased from grid to charge battery storage system in each timestep.', size=None), - ), - migrations.AddField( - model_name='electrictariffoutputs', - name='year_one_monthly_fixed_cost', - field=django.contrib.postgres.fields.ArrayField(base_field=models.FloatField(blank=True, null=True), default=list, help_text='Year one fixed utility costs for each month.', size=None), - ), - ] diff --git a/reoptjl/migrations/0107_electrictariffoutputs_urdb_demand_comments_and_more.py b/reoptjl/migrations/0107_electrictariffoutputs_urdb_demand_comments_and_more.py deleted file mode 100644 index 7dddf6eb4..000000000 --- a/reoptjl/migrations/0107_electrictariffoutputs_urdb_demand_comments_and_more.py +++ /dev/null @@ -1,73 +0,0 @@ -# Generated by Django 4.2.24 on 2025-10-16 20:43 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('reoptjl', '0106_electricloadoutputs_annual_peak_kw_and_more'), - ] - - operations = [ - migrations.AddField( - model_name='electrictariffoutputs', - name='urdb_demand_comments', - field=models.TextField(blank=True, help_text='Business as usual life cycle utility minimum charge adder, after-tax', null=True), - ), - migrations.AddField( - model_name='electrictariffoutputs', - name='urdb_energy_comments', - field=models.TextField(blank=True, help_text='Business as usual life cycle utility minimum charge adder, after-tax', null=True), - ), - migrations.AddField( - model_name='electrictariffoutputs', - name='urdb_label', - field=models.TextField(blank=True, help_text='Business as usual life cycle utility minimum charge adder, after-tax', null=True), - ), - migrations.AddField( - model_name='electrictariffoutputs', - name='urdb_peak_kw_capacity_max', - field=models.FloatField(blank=True, help_text='Business as usual life cycle utility minimum charge adder, after-tax', null=True), - ), - migrations.AddField( - model_name='electrictariffoutputs', - name='urdb_peak_kw_capacity_min', - field=models.FloatField(blank=True, help_text='Business as usual life cycle utility minimum charge adder, after-tax', null=True), - ), - migrations.AddField( - model_name='electrictariffoutputs', - name='urdb_rate_additional_info', - field=models.TextField(blank=True, help_text='Business as usual life cycle utility minimum charge adder, after-tax', null=True), - ), - migrations.AddField( - model_name='electrictariffoutputs', - name='urdb_rate_description', - field=models.TextField(blank=True, help_text='Business as usual life cycle utility minimum charge adder, after-tax', null=True), - ), - migrations.AddField( - model_name='electrictariffoutputs', - name='urdb_rate_effective_date', - field=models.TextField(blank=True, help_text='Business as usual life cycle utility minimum charge adder, after-tax', null=True), - ), - migrations.AddField( - model_name='electrictariffoutputs', - name='urdb_rate_name', - field=models.TextField(blank=True, help_text='Business as usual life cycle utility minimum charge adder, after-tax', null=True), - ), - migrations.AddField( - model_name='electrictariffoutputs', - name='urdb_url_link', - field=models.TextField(blank=True, help_text='Business as usual life cycle utility minimum charge adder, after-tax', null=True), - ), - migrations.AddField( - model_name='electrictariffoutputs', - name='urdb_utility', - field=models.TextField(blank=True, help_text='Business as usual life cycle utility minimum charge adder, after-tax', null=True), - ), - migrations.AddField( - model_name='electrictariffoutputs', - name='urdb_voltage_level', - field=models.TextField(blank=True, help_text='Business as usual life cycle utility minimum charge adder, after-tax', null=True), - ), - ] diff --git a/reoptjl/migrations/0110_merge_20251022_1752.py b/reoptjl/migrations/0110_merge_20251022_1752.py deleted file mode 100644 index cb76a4e89..000000000 --- a/reoptjl/migrations/0110_merge_20251022_1752.py +++ /dev/null @@ -1,14 +0,0 @@ -# Generated by Django 4.2.25 on 2025-10-22 17:52 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('reoptjl', '0107_electrictariffoutputs_urdb_demand_comments_and_more'), - ('reoptjl', '0109_remove_ghpoutputs_iterations_auto_guess_and_more'), - ] - - operations = [ - ] diff --git a/reoptjl/migrations/0111_remove_electrictariffoutputs_urdb_demand_comments_and_more.py b/reoptjl/migrations/0111_remove_electrictariffoutputs_urdb_demand_comments_and_more.py deleted file mode 100644 index f4eeb281d..000000000 --- a/reoptjl/migrations/0111_remove_electrictariffoutputs_urdb_demand_comments_and_more.py +++ /dev/null @@ -1,66 +0,0 @@ -# Generated by Django 4.2.25 on 2025-10-22 22:17 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('reoptjl', '0110_merge_20251022_1752'), - ] - - operations = [ - migrations.RemoveField( - model_name='electrictariffoutputs', - name='urdb_demand_comments', - ), - migrations.RemoveField( - model_name='electrictariffoutputs', - name='urdb_energy_comments', - ), - migrations.RemoveField( - model_name='electrictariffoutputs', - name='urdb_label', - ), - migrations.RemoveField( - model_name='electrictariffoutputs', - name='urdb_peak_kw_capacity_max', - ), - migrations.RemoveField( - model_name='electrictariffoutputs', - name='urdb_peak_kw_capacity_min', - ), - migrations.RemoveField( - model_name='electrictariffoutputs', - name='urdb_rate_additional_info', - ), - migrations.RemoveField( - model_name='electrictariffoutputs', - name='urdb_rate_description', - ), - migrations.RemoveField( - model_name='electrictariffoutputs', - name='urdb_rate_effective_date', - ), - migrations.RemoveField( - model_name='electrictariffoutputs', - name='urdb_rate_name', - ), - migrations.RemoveField( - model_name='electrictariffoutputs', - name='urdb_url_link', - ), - migrations.RemoveField( - model_name='electrictariffoutputs', - name='urdb_utility', - ), - migrations.RemoveField( - model_name='electrictariffoutputs', - name='urdb_voltage_level', - ), - migrations.AddField( - model_name='electrictariffinputs', - name='urdb_metadata', - field=models.JSONField(blank=True, help_text='Utility rate meta data from Utility Rate Database API', null=True), - ), - ] diff --git a/reoptjl/migrations/0112_rename_nem_electric_to_grid_series_kw_electrictariffoutputs_net_metering_electric_to_grid_series_kw_.py b/reoptjl/migrations/0112_rename_nem_electric_to_grid_series_kw_electrictariffoutputs_net_metering_electric_to_grid_series_kw_.py deleted file mode 100644 index 5b99f0d3c..000000000 --- a/reoptjl/migrations/0112_rename_nem_electric_to_grid_series_kw_electrictariffoutputs_net_metering_electric_to_grid_series_kw_.py +++ /dev/null @@ -1,73 +0,0 @@ -# Generated by Django 4.2.25 on 2025-10-22 22:21 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('reoptjl', '0111_remove_electrictariffoutputs_urdb_demand_comments_and_more'), - ] - - operations = [ - migrations.RenameField( - model_name='electrictariffoutputs', - old_name='NEM_electric_to_grid_series_kw', - new_name='net_metering_electric_to_grid_series_kw', - ), - migrations.RenameField( - model_name='electrictariffoutputs', - old_name='EXC_electric_to_grid_series_kw', - new_name='net_metering_excess_electric_to_grid_series_kw', - ), - migrations.RenameField( - model_name='electrictariffoutputs', - old_name='EXC_export_rate_series', - new_name='net_metering_excess_export_rate_series', - ), - migrations.RenameField( - model_name='electrictariffoutputs', - old_name='EXC_monthly_export_cost_benefit_before_tax', - new_name='net_metering_excess_monthly_export_cost_benefit_before_tax', - ), - migrations.RenameField( - model_name='electrictariffoutputs', - old_name='EXC_monthly_export_series_kwh', - new_name='net_metering_excess_monthly_export_series_kwh', - ), - migrations.RenameField( - model_name='electrictariffoutputs', - old_name='NEM_export_rate_series', - new_name='net_metering_export_rate_series', - ), - migrations.RenameField( - model_name='electrictariffoutputs', - old_name='NEM_monthly_export_cost_benefit_before_tax', - new_name='net_metering_monthly_export_cost_benefit_before_tax', - ), - migrations.RenameField( - model_name='electrictariffoutputs', - old_name='NEM_monthly_export_series_kwh', - new_name='net_metering_monthly_export_series_kwh', - ), - migrations.RenameField( - model_name='electrictariffoutputs', - old_name='WHL_electric_to_grid_series_kw', - new_name='wholesale_electric_to_grid_series_kw', - ), - migrations.RenameField( - model_name='electrictariffoutputs', - old_name='WHL_export_rate_series', - new_name='wholesale_export_rate_series', - ), - migrations.RenameField( - model_name='electrictariffoutputs', - old_name='WHL_monthly_export_cost_benefit_before_tax', - new_name='wholesale_monthly_export_cost_benefit_before_tax', - ), - migrations.RenameField( - model_name='electrictariffoutputs', - old_name='WHL_monthly_export_series_kwh', - new_name='wholesale_monthly_export_series_kwh', - ), - ] diff --git a/reoptjl/migrations/0113_rename_monthly_peak_kw_electricloadoutputs_monthly_peaks_kw.py b/reoptjl/migrations/0113_rename_monthly_peak_kw_electricloadoutputs_monthly_peaks_kw.py deleted file mode 100644 index 625c6323c..000000000 --- a/reoptjl/migrations/0113_rename_monthly_peak_kw_electricloadoutputs_monthly_peaks_kw.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 4.2.25 on 2025-10-23 22:33 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('reoptjl', '0112_rename_nem_electric_to_grid_series_kw_electrictariffoutputs_net_metering_electric_to_grid_series_kw_'), - ] - - operations = [ - migrations.RenameField( - model_name='electricloadoutputs', - old_name='monthly_peak_kw', - new_name='monthly_peaks_kw', - ), - ] From 3916cde0f17f568de083257e1b7565355b4d6722 Mon Sep 17 00:00:00 2001 From: bill-becker Date: Tue, 28 Oct 2025 15:10:30 -0600 Subject: [PATCH 18/18] Update squashed migration after outputs refactor --- ...tricloadoutputs_annual_peak_kw_and_more.py | 139 ++++++++++++++++++ 1 file changed, 139 insertions(+) create mode 100644 reoptjl/migrations/0110_electricloadoutputs_annual_peak_kw_and_more.py diff --git a/reoptjl/migrations/0110_electricloadoutputs_annual_peak_kw_and_more.py b/reoptjl/migrations/0110_electricloadoutputs_annual_peak_kw_and_more.py new file mode 100644 index 000000000..54bd6b56f --- /dev/null +++ b/reoptjl/migrations/0110_electricloadoutputs_annual_peak_kw_and_more.py @@ -0,0 +1,139 @@ +# Generated by Django 4.2.25 on 2025-10-28 18:05 + +import django.contrib.postgres.fields +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('reoptjl', '0109_remove_ghpoutputs_iterations_auto_guess_and_more'), + ] + + operations = [ + migrations.AddField( + model_name='electricloadoutputs', + name='annual_peak_kw', + field=models.FloatField(blank=True, help_text='Annual peak energy demand determined from load_series_kw. Does not include electric load for any new heating or cooling techs.', null=True), + ), + migrations.AddField( + model_name='electricloadoutputs', + name='monthly_calculated_kwh', + field=django.contrib.postgres.fields.ArrayField(base_field=models.FloatField(blank=True, null=True), default=list, help_text='Monthly energy consumption calculated by summing up load_series_kw. Does not include electric load for any new heating or cooling techs.', size=None), + ), + migrations.AddField( + model_name='electricloadoutputs', + name='monthly_peaks_kw', + field=django.contrib.postgres.fields.ArrayField(base_field=models.FloatField(blank=True, null=True), default=list, help_text='Monthly peak energy demand determined from load_series_kw. Does not include electric load for any new heating or cooling techs.', size=None), + ), + migrations.AddField( + model_name='electrictariffinputs', + name='urdb_metadata', + field=models.JSONField(blank=True, help_text='Utility rate meta data from Utility Rate Database API', null=True), + ), + migrations.AddField( + model_name='electrictariffoutputs', + name='demand_rate_average_series', + field=django.contrib.postgres.fields.ArrayField(base_field=models.FloatField(blank=True, null=True), default=list, help_text='Series of average (across tiers) demand rates for each timestep in year one.', size=None), + ), + migrations.AddField( + model_name='electrictariffoutputs', + name='energy_cost_series_before_tax', + field=models.JSONField(blank=True, help_text='Series of cost of power purchased from grid to serve load in each timestep, by Tier_i.', null=True), + ), + migrations.AddField( + model_name='electrictariffoutputs', + name='energy_cost_series_before_tax_bau', + field=models.JSONField(blank=True, help_text='Business as usual series of cost of power purchased from grid to serve load in each timestep, by Tier_i.', null=True), + ), + migrations.AddField( + model_name='electrictariffoutputs', + name='energy_rate_average_series', + field=django.contrib.postgres.fields.ArrayField(base_field=models.FloatField(blank=True, null=True), default=list, help_text='Series of average (across tiers) energy rates for each timestep in year one.', size=None), + ), + migrations.AddField( + model_name='electrictariffoutputs', + name='energy_rate_series', + field=models.JSONField(blank=True, help_text='Series of billed energy rates for each timestep in year one.', null=True), + ), + migrations.AddField( + model_name='electrictariffoutputs', + name='energy_rate_tier_limits', + field=models.JSONField(blank=True, help_text='Energy rate tier limits', null=True), + ), + migrations.AddField( + model_name='electrictariffoutputs', + name='facility_demand_monthly_rate_series', + field=models.JSONField(blank=True, help_text='Facility (not dependent on TOU) demand charge rates by Tier_i', null=True), + ), + migrations.AddField( + model_name='electrictariffoutputs', + name='facility_demand_monthly_rate_tier_limits', + field=models.JSONField(blank=True, help_text='Facility (not dependent on TOU) demand charge tier limits', null=True), + ), + migrations.AddField( + model_name='electrictariffoutputs', + name='monthly_demand_cost_series_before_tax', + field=django.contrib.postgres.fields.ArrayField(base_field=models.FloatField(blank=True, null=True), default=list, help_text='Series of total (facility and TOU for all tiers) monthly demand charges for each month.', size=None), + ), + migrations.AddField( + model_name='electrictariffoutputs', + name='monthly_demand_cost_series_before_tax_bau', + field=django.contrib.postgres.fields.ArrayField(base_field=models.FloatField(blank=True, null=True), default=list, help_text='Business as usual series of total (facility and TOU for all tiers) monthly demand charges for each month.', size=None), + ), + migrations.AddField( + model_name='electrictariffoutputs', + name='monthly_energy_cost_series_before_tax', + field=django.contrib.postgres.fields.ArrayField(base_field=models.FloatField(blank=True, null=True), default=list, help_text='Series of monthly cost of power purchased from grid to serve loads.', size=None), + ), + migrations.AddField( + model_name='electrictariffoutputs', + name='monthly_energy_cost_series_before_tax_bau', + field=django.contrib.postgres.fields.ArrayField(base_field=models.FloatField(blank=True, null=True), default=list, help_text='Business as usual series of monthly cost of power purchased from grid to serve loads.', size=None), + ), + migrations.AddField( + model_name='electrictariffoutputs', + name='monthly_facility_demand_cost_series_before_tax', + field=django.contrib.postgres.fields.ArrayField(base_field=models.FloatField(blank=True, null=True), default=list, help_text='Series of total (all tiers) monthly facility demand charges by month.', size=None), + ), + migrations.AddField( + model_name='electrictariffoutputs', + name='monthly_facility_demand_cost_series_before_tax_bau', + field=django.contrib.postgres.fields.ArrayField(base_field=models.FloatField(blank=True, null=True), default=list, help_text='Business as usual series of total (all tiers) monthly facility demand charges by month.', size=None), + ), + migrations.AddField( + model_name='electrictariffoutputs', + name='monthly_fixed_cost', + field=django.contrib.postgres.fields.ArrayField(base_field=models.FloatField(blank=True, null=True), default=list, help_text='Year one fixed utility costs for each month.', size=None), + ), + migrations.AddField( + model_name='electrictariffoutputs', + name='monthly_fixed_cost_bau', + field=django.contrib.postgres.fields.ArrayField(base_field=models.FloatField(blank=True, null=True), default=list, help_text='Business as usual year one fixed utility costs for each month.', size=None), + ), + migrations.AddField( + model_name='electrictariffoutputs', + name='monthly_tou_demand_cost_series_before_tax', + field=django.contrib.postgres.fields.ArrayField(base_field=models.FloatField(blank=True, null=True), default=list, help_text='Series of total time-of-use demand charges for each month.', size=None), + ), + migrations.AddField( + model_name='electrictariffoutputs', + name='monthly_tou_demand_cost_series_before_tax_bau', + field=django.contrib.postgres.fields.ArrayField(base_field=models.FloatField(blank=True, null=True), default=list, help_text='Business as usual series of total time-of-use demand charges for each month.', size=None), + ), + migrations.AddField( + model_name='electrictariffoutputs', + name='tou_demand_metrics', + field=models.JSONField(blank=True, help_text='Dictionary of TOU demand metrics, including month, tier, demand_rate, measured_tou_peak_demand, and demand_charge_before_tax', null=True), + ), + migrations.AddField( + model_name='electrictariffoutputs', + name='tou_demand_rate_series', + field=models.JSONField(blank=True, help_text='Series of demand rates by Tier_i for each timestep.', null=True), + ), + migrations.AddField( + model_name='electrictariffoutputs', + name='tou_demand_rate_tier_limits', + field=models.JSONField(blank=True, help_text='TOU demand rate tier limits', null=True), + ), + ]