From a747f61978c891477587057de8a2d27cfe081a46 Mon Sep 17 00:00:00 2001 From: adfarth Date: Tue, 19 Aug 2025 16:36:53 -0600 Subject: [PATCH 01/12] all updates --- CHANGELOG.md | 21 +++++++++++++++++++++ reoptjl/models.py | 42 +++++++++++++++++++++--------------------- 2 files changed, 42 insertions(+), 21 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4cee93ce4..8442a61dc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,6 +26,27 @@ Classify the change according to the following categories: ##### Removed ### Patches +## misc-defaults +### Minor Updates +#### Changed +Update the following inputs from the previous --> new values: +- `Financial.offtaker_discount_rate_fraction`: 0.0638 --> 0.0624 +- `Financial.owner_discount_rate_fraction`: 0.0638 --> 0.0624 +- `Financial.elec_cost_escalation_rate_fraction`: 0.017 --> 0.0166 +- `Financial.existing_boiler_fuel_cost_escalation_rate_fraction `: 0.015 --> 0.0348 +- `Financial.boiler_fuel_cost_escalation_rate_fraction `: 0.015 --> 0.0348 +- `Financial.chp_fuel_cost_escalation_rate_fraction `: 0.015 --> 0.0348 +- `Financial.generator_fuel_cost_escalation_rate_fraction `: 0.012 --> 0.0197 +- `Generator.fuel_cost_per_gallon`: 3.61 --> 2.25 +- `CHP.federal_itc_fraction`: 0.3 --> 0.0 +- For all technologies eligible for first year bonus depreciation: `macrs_bonus_fraction`: 0.6 --> 0.4 (assuming 2025 implementation) +- `Wind.om_cost_per_kw`: 36.0 --> 42.0 +- `Wind.size_class_to_installed_cost` = Dict( + "residential"=> 6339.0, --> 7692.0 + "commercial"=> 4760.0, --> 5776.0 + "medium"=> 3137.0, --> 3807.0 + "large"=> 2386.0 --> 2896.0) + ## v3.13.0 ### Minor Updates #### Added diff --git a/reoptjl/models.py b/reoptjl/models.py index 2d48782ea..a8884d3f0 100644 --- a/reoptjl/models.py +++ b/reoptjl/models.py @@ -76,10 +76,10 @@ class MACRS_YEARS_CHOICES(models.IntegerChoices): } WIND_COST_DEFAULTS = { # size_class_to_installed_cost - "residential" : 6339.0, - "commercial" : 4760.0, - "medium" : 3137.0, - "large" : 2386.0 + "residential" : 7692.0, + "commercial" : 5776.0, + "medium" : 3807.0, + "large" : 2896.0 } def at_least_one_set(model, possible_sets): @@ -677,7 +677,7 @@ class FinancialInputs(BaseModel, models.Model): help_text="Analysis period in years. Must be integer." ) elec_cost_escalation_rate_fraction = models.FloatField( - default=0.017, + default=0.0166, validators=[ MinValueValidator(-1), MaxValueValidator(1) @@ -686,7 +686,7 @@ class FinancialInputs(BaseModel, models.Model): help_text="Annual nominal utility electricity cost escalation rate." ) offtaker_discount_rate_fraction = models.FloatField( - default=0.0638, + default=0.0624, validators=[ MinValueValidator(0), MaxValueValidator(1) @@ -714,7 +714,7 @@ class FinancialInputs(BaseModel, models.Model): help_text="Annual nominal O&M cost escalation rate" ) owner_discount_rate_fraction = models.FloatField( - default=0.0638, + default=0.0624, validators=[ MinValueValidator(0), MaxValueValidator(1) @@ -906,7 +906,7 @@ class FinancialInputs(BaseModel, models.Model): help_text=("Annual nominal escalation rate of the public health cost of 1 tonne of PM2.5 emissions (as a decimal). The default value is calculated from the EASIUR model for a height of 150m.") ) generator_fuel_cost_escalation_rate_fraction = models.FloatField( - default=0.012, + default=0.0197, validators=[ MinValueValidator(-1), MaxValueValidator(1) @@ -915,7 +915,7 @@ class FinancialInputs(BaseModel, models.Model): help_text=("Annual nominal boiler fuel cost escalation rate") ) existing_boiler_fuel_cost_escalation_rate_fraction = models.FloatField( - default=0.015, + default=0.0348, validators=[ MinValueValidator(-1), MaxValueValidator(1) @@ -924,7 +924,7 @@ class FinancialInputs(BaseModel, models.Model): help_text=("Annual nominal existing boiler fuel cost escalation rate") ) boiler_fuel_cost_escalation_rate_fraction = models.FloatField( - default=0.015, + default=0.0348, validators=[ MinValueValidator(-1), MaxValueValidator(1) @@ -933,7 +933,7 @@ class FinancialInputs(BaseModel, models.Model): help_text=("Annual nominal boiler fuel cost escalation rate") ) chp_fuel_cost_escalation_rate_fraction = models.FloatField( - default=0.015, + default=0.0348, validators=[ MinValueValidator(-1), MaxValueValidator(1) @@ -2785,7 +2785,7 @@ class PV_LOCATION_CHOICES(models.TextChoices): help_text="Duration over which accelerated depreciation will occur. Set to zero to disable" ) macrs_bonus_fraction = models.FloatField( - default=0.6, + default=0.4, validators=[ MinValueValidator(0), MaxValueValidator(1) @@ -3214,7 +3214,7 @@ class WIND_SIZE_CLASS_CHOICES(models.TextChoices): help_text="Installed cost in $/kW. Default cost is determined based on size_class." ) om_cost_per_kw = models.FloatField( - default=36, + default=42, validators=[ MinValueValidator(0), MaxValueValidator(1.0e3) @@ -3229,7 +3229,7 @@ class WIND_SIZE_CLASS_CHOICES(models.TextChoices): help_text="Duration over which accelerated depreciation will occur. Set to zero to disable" ) macrs_bonus_fraction = models.FloatField( - default=0.6, + default=0.4, validators=[ MinValueValidator(0), MaxValueValidator(1) @@ -3648,7 +3648,7 @@ class ElectricStorageInputs(BaseModel, models.Model): help_text="Duration over which accelerated depreciation will occur. Set to zero to disable" ) macrs_bonus_fraction = models.FloatField( - default=0.6, + default=0.4, validators=[ MinValueValidator(0), MaxValueValidator(1) @@ -3809,7 +3809,7 @@ class GeneratorInputs(BaseModel, models.Model): help_text="Diesel generator per unit production (variable) operations and maintenance costs in $/kWh" ) fuel_cost_per_gallon = models.FloatField( - default=3.0, + default=2.25, validators=[ MinValueValidator(0.0), MaxValueValidator(1.0e2) @@ -4438,7 +4438,7 @@ class CHPInputs(BaseModel, models.Model): help_text="Duration over which accelerated depreciation will occur. Set to zero to disable" ) macrs_bonus_fraction = models.FloatField( - default=0.6, + default=0.4, validators=[ MinValueValidator(0), MaxValueValidator(1) @@ -4456,7 +4456,7 @@ class CHPInputs(BaseModel, models.Model): help_text="Percent of the ITC value by which depreciable basis is reduced" ) federal_itc_fraction = models.FloatField( - default=0.3, + default=0.0, validators=[ MinValueValidator(0), MaxValueValidator(1) @@ -6900,7 +6900,7 @@ class HotThermalStorageInputs(BaseModel, models.Model): help_text="Duration over which accelerated depreciation will occur. Set to zero to disable" ) macrs_bonus_fraction = models.FloatField( - default=0.6, + default=0.4, validators=[ MinValueValidator(0), MaxValueValidator(1) @@ -7104,7 +7104,7 @@ class ColdThermalStorageInputs(BaseModel, models.Model): help_text="Duration over which accelerated depreciation will occur. Set to zero to disable" ) macrs_bonus_fraction = models.FloatField( - default=0.6, + default=0.4, validators=[ MinValueValidator(0), MaxValueValidator(1) @@ -8405,7 +8405,7 @@ class GHPInputs(BaseModel, models.Model): help_text="Duration over which accelerated depreciation will occur. Set to zero to disable" ) macrs_bonus_fraction = models.FloatField( - default=0.6, + default=0.4, validators=[ MinValueValidator(0), MaxValueValidator(1) From ab9eea8b904ef0ce53a730c6535a4c8dc7906a50 Mon Sep 17 00:00:00 2001 From: adfarth Date: Thu, 21 Aug 2025 08:15:59 -0600 Subject: [PATCH 02/12] update tests --- reoptjl/test/posts/outage.json | 3 ++- reoptjl/test/test_validator.py | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/reoptjl/test/posts/outage.json b/reoptjl/test/posts/outage.json index 5658437c5..b7a501c47 100644 --- a/reoptjl/test/posts/outage.json +++ b/reoptjl/test/posts/outage.json @@ -34,7 +34,8 @@ "min_kw": 150.0, "max_kw": 150.0, "macrs_bonus_fraction": 0.8, - "macrs_option_years": 0 + "macrs_option_years": 0, + "federal_itc_fraction": 0.3 }, "PV": { "min_kw": 282.3629, diff --git a/reoptjl/test/test_validator.py b/reoptjl/test/test_validator.py index 8e0c1c6d3..2e9d5c24b 100644 --- a/reoptjl/test/test_validator.py +++ b/reoptjl/test/test_validator.py @@ -102,7 +102,7 @@ def test_off_grid_defaults_overrides(self): self.assertAlmostEqual(validator.models["Wind"].operating_reserve_required_fraction, 0.5) self.assertAlmostEqual(validator.models["PV"].operating_reserve_required_fraction, 0.25) - self.assertEqual(validator.models["Wind"].installed_cost_per_kw, 4760.0) # set based on size_class + self.assertEqual(validator.models["Wind"].installed_cost_per_kw, 5776.0) # set based on size_class (commercial) self.assertAlmostEqual(validator.models["ElectricLoad"].operating_reserve_required_fraction, 0.1) self.assertAlmostEqual(validator.models["ElectricLoad"].critical_load_fraction, 1.0) From 51a02e02ef04d2b31212a5f05f8b6653ebeff8fa Mon Sep 17 00:00:00 2001 From: adfarth Date: Thu, 21 Aug 2025 08:28:16 -0600 Subject: [PATCH 03/12] point to feature branch --- julia_src/Manifest.toml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/julia_src/Manifest.toml b/julia_src/Manifest.toml index 499e0c00a..fb7eca19a 100644 --- a/julia_src/Manifest.toml +++ b/julia_src/Manifest.toml @@ -922,7 +922,9 @@ 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 = "7152b01634998853fac6b0fd386d46d22b83c474" +repo-rev = "misc-defaults" +repo-url = "https://github.com/NREL/REopt.jl.git" uuid = "d36ad4e8-d74a-4f7a-ace1-eaea049febf6" version = "0.53.2" From a4cd4b8bfdadaa67f1419375df029e4a05e4aea8 Mon Sep 17 00:00:00 2001 From: adfarth Date: Thu, 21 Aug 2025 09:20:07 -0600 Subject: [PATCH 04/12] Update test_http_endpoints.py --- reoptjl/test/test_http_endpoints.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reoptjl/test/test_http_endpoints.py b/reoptjl/test/test_http_endpoints.py index 8104a6197..23303c196 100644 --- a/reoptjl/test/test_http_endpoints.py +++ b/reoptjl/test/test_http_endpoints.py @@ -35,7 +35,7 @@ def test_chp_defaults(self): self.assertEqual(http_response["prime_mover"], "combustion_turbine") self.assertEqual(http_response["size_class"], 2) self.assertGreater(http_response["chp_elec_size_heuristic_kw"], 3500.0) - self.assertEqual(http_response["default_inputs"]["federal_itc_fraction"], 0.3) + self.assertEqual(http_response["default_inputs"]["federal_itc_fraction"], 0.0) inputs = { "prime_mover": "micro_turbine", From a33581334c162af165b53aef6737788a2362f6cb Mon Sep 17 00:00:00 2001 From: adfarth Date: Thu, 21 Aug 2025 10:13:53 -0600 Subject: [PATCH 05/12] Update test_http_endpoints.py --- reoptjl/test/test_http_endpoints.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reoptjl/test/test_http_endpoints.py b/reoptjl/test/test_http_endpoints.py index 23303c196..14771a2c3 100644 --- a/reoptjl/test/test_http_endpoints.py +++ b/reoptjl/test/test_http_endpoints.py @@ -50,7 +50,7 @@ def test_chp_defaults(self): http_response = response.json() # Check the endpoint logic with the expected selection - self.assertEqual(http_response["default_inputs"]["federal_itc_fraction"], 0.3) + self.assertEqual(http_response["default_inputs"]["federal_itc_fraction"], 0.0) inputs = { "prime_mover": "combustion_turbine", From 8fb8c342b0f38cfa59b4697a1557c9097a34d818 Mon Sep 17 00:00:00 2001 From: adfarth Date: Fri, 22 Aug 2025 14:56:00 -0600 Subject: [PATCH 06/12] update macrs --- CHANGELOG.md | 3 ++- reoptjl/models.py | 16 ++++++++-------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8442a61dc..bb8f07c56 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -38,8 +38,9 @@ Update the following inputs from the previous --> new values: - `Financial.chp_fuel_cost_escalation_rate_fraction `: 0.015 --> 0.0348 - `Financial.generator_fuel_cost_escalation_rate_fraction `: 0.012 --> 0.0197 - `Generator.fuel_cost_per_gallon`: 3.61 --> 2.25 +- `ColdThermalStorage`, `HotThermalStorage`, `ElectricStorage` `macrs_option_years` 7 --> 5 +- `ColdThermalStorage`, `HotThermalStorage`, `ElectricStorage`, `PV`, `Wind` `macrs_bonus_fraction` 0.6 --> 1.0 - `CHP.federal_itc_fraction`: 0.3 --> 0.0 -- For all technologies eligible for first year bonus depreciation: `macrs_bonus_fraction`: 0.6 --> 0.4 (assuming 2025 implementation) - `Wind.om_cost_per_kw`: 36.0 --> 42.0 - `Wind.size_class_to_installed_cost` = Dict( "residential"=> 6339.0, --> 7692.0 diff --git a/reoptjl/models.py b/reoptjl/models.py index a8884d3f0..ac991675b 100644 --- a/reoptjl/models.py +++ b/reoptjl/models.py @@ -2785,7 +2785,7 @@ class PV_LOCATION_CHOICES(models.TextChoices): help_text="Duration over which accelerated depreciation will occur. Set to zero to disable" ) macrs_bonus_fraction = models.FloatField( - default=0.4, + default=1.0, validators=[ MinValueValidator(0), MaxValueValidator(1) @@ -3229,7 +3229,7 @@ class WIND_SIZE_CLASS_CHOICES(models.TextChoices): help_text="Duration over which accelerated depreciation will occur. Set to zero to disable" ) macrs_bonus_fraction = models.FloatField( - default=0.4, + default=1.0, validators=[ MinValueValidator(0), MaxValueValidator(1) @@ -3642,13 +3642,13 @@ class ElectricStorageInputs(BaseModel, models.Model): help_text="Annual O&M cost as a fraction of installed cost." ) macrs_option_years = models.IntegerField( - default=MACRS_YEARS_CHOICES.SEVEN, + default=MACRS_YEARS_CHOICES.FIVE, choices=MACRS_YEARS_CHOICES.choices, blank=True, help_text="Duration over which accelerated depreciation will occur. Set to zero to disable" ) macrs_bonus_fraction = models.FloatField( - default=0.4, + default=1.0, validators=[ MinValueValidator(0), MaxValueValidator(1) @@ -6894,13 +6894,13 @@ class HotThermalStorageInputs(BaseModel, models.Model): help_text="Thermal energy-based cost of TES (e.g. volume of the tank)" ) macrs_option_years = models.IntegerField( - default=MACRS_YEARS_CHOICES.SEVEN, + default=MACRS_YEARS_CHOICES.FIVE, choices=MACRS_YEARS_CHOICES.choices, blank=True, help_text="Duration over which accelerated depreciation will occur. Set to zero to disable" ) macrs_bonus_fraction = models.FloatField( - default=0.4, + default=1.0, validators=[ MinValueValidator(0), MaxValueValidator(1) @@ -7098,13 +7098,13 @@ class ColdThermalStorageInputs(BaseModel, models.Model): help_text="Thermal energy-based cost of TES (e.g. volume of the tank)" ) macrs_option_years = models.IntegerField( - default=MACRS_YEARS_CHOICES.SEVEN, + default=MACRS_YEARS_CHOICES.FIVE, choices=MACRS_YEARS_CHOICES.choices, blank=True, help_text="Duration over which accelerated depreciation will occur. Set to zero to disable" ) macrs_bonus_fraction = models.FloatField( - default=0.4, + default=1.0, validators=[ MinValueValidator(0), MaxValueValidator(1) From 7b2bf06d3e7afccf9cb866a6930668a5fa0a66fd Mon Sep 17 00:00:00 2001 From: adfarth Date: Tue, 2 Sep 2025 16:15:39 -0600 Subject: [PATCH 07/12] CHP and GHP MACRS --- CHANGELOG.md | 2 ++ reoptjl/models.py | 8 ++++---- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bb8f07c56..07d2a7d64 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -41,6 +41,8 @@ Update the following inputs from the previous --> new values: - `ColdThermalStorage`, `HotThermalStorage`, `ElectricStorage` `macrs_option_years` 7 --> 5 - `ColdThermalStorage`, `HotThermalStorage`, `ElectricStorage`, `PV`, `Wind` `macrs_bonus_fraction` 0.6 --> 1.0 - `CHP.federal_itc_fraction`: 0.3 --> 0.0 +- `CHP.macrs_bonus_fraction` and `GHP.macrs_bonus_fraction`: 0.4 --> 0.0 +- `CHP.macrs_option_years` and `GHP.macrs_option_years`: 5 --> 0 - `Wind.om_cost_per_kw`: 36.0 --> 42.0 - `Wind.size_class_to_installed_cost` = Dict( "residential"=> 6339.0, --> 7692.0 diff --git a/reoptjl/models.py b/reoptjl/models.py index ac991675b..2f203843e 100644 --- a/reoptjl/models.py +++ b/reoptjl/models.py @@ -4432,13 +4432,13 @@ class CHPInputs(BaseModel, models.Model): #Financial and emissions macrs_option_years = models.IntegerField( - default=MACRS_YEARS_CHOICES.FIVE, + default=MACRS_YEARS_CHOICES.ZERO, choices=MACRS_YEARS_CHOICES.choices, blank=True, help_text="Duration over which accelerated depreciation will occur. Set to zero to disable" ) macrs_bonus_fraction = models.FloatField( - default=0.4, + default=0.0, validators=[ MinValueValidator(0), MaxValueValidator(1) @@ -8399,13 +8399,13 @@ class GHPInputs(BaseModel, models.Model): ) macrs_option_years = models.IntegerField( - default=MACRS_YEARS_CHOICES.FIVE, + default=MACRS_YEARS_CHOICES.ZERO, choices=MACRS_YEARS_CHOICES.choices, blank=True, help_text="Duration over which accelerated depreciation will occur. Set to zero to disable" ) macrs_bonus_fraction = models.FloatField( - default=0.4, + default=0.0, validators=[ MinValueValidator(0), MaxValueValidator(1) From dd7c320664af0b224b47b69c3db65a3f165b4d87 Mon Sep 17 00:00:00 2001 From: adfarth Date: Wed, 3 Sep 2025 10:21:02 -0600 Subject: [PATCH 08/12] Create 0093_alter_chpinputs_federal_itc_fraction_and_more.py --- ...chpinputs_federal_itc_fraction_and_more.py | 124 ++++++++++++++++++ 1 file changed, 124 insertions(+) create mode 100644 reoptjl/migrations/0093_alter_chpinputs_federal_itc_fraction_and_more.py diff --git a/reoptjl/migrations/0093_alter_chpinputs_federal_itc_fraction_and_more.py b/reoptjl/migrations/0093_alter_chpinputs_federal_itc_fraction_and_more.py new file mode 100644 index 000000000..354937af6 --- /dev/null +++ b/reoptjl/migrations/0093_alter_chpinputs_federal_itc_fraction_and_more.py @@ -0,0 +1,124 @@ +# Generated by Django 4.0.7 on 2025-09-03 16:20 + +import django.core.validators +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('reoptjl', '0092_merge_20250613_0525'), + ] + + operations = [ + migrations.AlterField( + model_name='chpinputs', + name='federal_itc_fraction', + field=models.FloatField(blank=True, default=0.0, help_text='Percentage of capital costs that are credited towards federal taxes', validators=[django.core.validators.MinValueValidator(0), django.core.validators.MaxValueValidator(1)]), + ), + migrations.AlterField( + model_name='chpinputs', + name='macrs_bonus_fraction', + field=models.FloatField(blank=True, default=0.0, help_text='Percent of upfront project costs to depreciate in year one in addition to scheduled depreciation', validators=[django.core.validators.MinValueValidator(0), django.core.validators.MaxValueValidator(1)]), + ), + migrations.AlterField( + model_name='chpinputs', + name='macrs_option_years', + field=models.IntegerField(blank=True, choices=[(0, 'Zero'), (5, 'Five'), (7, 'Seven')], default=0, help_text='Duration over which accelerated depreciation will occur. Set to zero to disable'), + ), + migrations.AlterField( + model_name='coldthermalstorageinputs', + name='macrs_bonus_fraction', + field=models.FloatField(blank=True, default=1.0, help_text='Percent of upfront project costs to depreciate in year one in addition to scheduled depreciation', validators=[django.core.validators.MinValueValidator(0), django.core.validators.MaxValueValidator(1)]), + ), + migrations.AlterField( + model_name='coldthermalstorageinputs', + name='macrs_option_years', + field=models.IntegerField(blank=True, choices=[(0, 'Zero'), (5, 'Five'), (7, 'Seven')], default=5, help_text='Duration over which accelerated depreciation will occur. Set to zero to disable'), + ), + migrations.AlterField( + model_name='electricstorageinputs', + name='macrs_bonus_fraction', + field=models.FloatField(blank=True, default=1.0, help_text='Percent of upfront project costs to depreciate in year one in addition to scheduled depreciation', validators=[django.core.validators.MinValueValidator(0), django.core.validators.MaxValueValidator(1)]), + ), + migrations.AlterField( + model_name='electricstorageinputs', + name='macrs_option_years', + field=models.IntegerField(blank=True, choices=[(0, 'Zero'), (5, 'Five'), (7, 'Seven')], default=5, help_text='Duration over which accelerated depreciation will occur. Set to zero to disable'), + ), + migrations.AlterField( + model_name='financialinputs', + name='boiler_fuel_cost_escalation_rate_fraction', + field=models.FloatField(blank=True, default=0.0348, help_text='Annual nominal boiler fuel cost escalation rate', validators=[django.core.validators.MinValueValidator(-1), django.core.validators.MaxValueValidator(1)]), + ), + migrations.AlterField( + model_name='financialinputs', + name='chp_fuel_cost_escalation_rate_fraction', + field=models.FloatField(blank=True, default=0.0348, help_text='Annual nominal chp fuel cost escalation rate', validators=[django.core.validators.MinValueValidator(-1), django.core.validators.MaxValueValidator(1)]), + ), + migrations.AlterField( + model_name='financialinputs', + name='elec_cost_escalation_rate_fraction', + field=models.FloatField(blank=True, default=0.0166, help_text='Annual nominal utility electricity cost escalation rate.', validators=[django.core.validators.MinValueValidator(-1), django.core.validators.MaxValueValidator(1)]), + ), + migrations.AlterField( + model_name='financialinputs', + name='existing_boiler_fuel_cost_escalation_rate_fraction', + field=models.FloatField(blank=True, default=0.0348, help_text='Annual nominal existing boiler fuel cost escalation rate', validators=[django.core.validators.MinValueValidator(-1), django.core.validators.MaxValueValidator(1)]), + ), + migrations.AlterField( + model_name='financialinputs', + name='generator_fuel_cost_escalation_rate_fraction', + field=models.FloatField(blank=True, default=0.0197, help_text='Annual nominal boiler fuel cost escalation rate', validators=[django.core.validators.MinValueValidator(-1), django.core.validators.MaxValueValidator(1)]), + ), + migrations.AlterField( + model_name='financialinputs', + name='offtaker_discount_rate_fraction', + field=models.FloatField(blank=True, default=0.0624, help_text='Nominal energy offtaker discount rate. In single ownership model the offtaker is also the generation owner.', validators=[django.core.validators.MinValueValidator(0), django.core.validators.MaxValueValidator(1)]), + ), + migrations.AlterField( + model_name='financialinputs', + name='owner_discount_rate_fraction', + field=models.FloatField(blank=True, default=0.0624, help_text='Nominal generation owner discount rate. Used for two party financing model. In two party ownership model the offtaker does not own the generator(s).', validators=[django.core.validators.MinValueValidator(0), django.core.validators.MaxValueValidator(1)]), + ), + migrations.AlterField( + model_name='generatorinputs', + name='fuel_cost_per_gallon', + field=models.FloatField(blank=True, default=2.25, help_text='Diesel cost in $/gallon', validators=[django.core.validators.MinValueValidator(0.0), django.core.validators.MaxValueValidator(100.0)]), + ), + migrations.AlterField( + model_name='ghpinputs', + name='macrs_bonus_fraction', + field=models.FloatField(blank=True, default=0.0, help_text='Percent of upfront project costs to depreciate in year one in addition to scheduled depreciation', validators=[django.core.validators.MinValueValidator(0), django.core.validators.MaxValueValidator(1)]), + ), + migrations.AlterField( + model_name='ghpinputs', + name='macrs_option_years', + field=models.IntegerField(blank=True, choices=[(0, 'Zero'), (5, 'Five'), (7, 'Seven')], default=0, help_text='Duration over which accelerated depreciation will occur. Set to zero to disable'), + ), + migrations.AlterField( + model_name='hotthermalstorageinputs', + name='macrs_bonus_fraction', + field=models.FloatField(blank=True, default=1.0, help_text='Percent of upfront project costs to depreciate in year one in addition to scheduled depreciation', validators=[django.core.validators.MinValueValidator(0), django.core.validators.MaxValueValidator(1)]), + ), + migrations.AlterField( + model_name='hotthermalstorageinputs', + name='macrs_option_years', + field=models.IntegerField(blank=True, choices=[(0, 'Zero'), (5, 'Five'), (7, 'Seven')], default=5, help_text='Duration over which accelerated depreciation will occur. Set to zero to disable'), + ), + migrations.AlterField( + model_name='pvinputs', + name='macrs_bonus_fraction', + field=models.FloatField(blank=True, default=1.0, help_text='Percent of upfront project costs to depreciate in year one in addition to scheduled depreciation', validators=[django.core.validators.MinValueValidator(0), django.core.validators.MaxValueValidator(1)]), + ), + migrations.AlterField( + model_name='windinputs', + name='macrs_bonus_fraction', + field=models.FloatField(blank=True, default=1.0, help_text='Percent of upfront project costs to depreciate in year one in addition to scheduled depreciation', validators=[django.core.validators.MinValueValidator(0), django.core.validators.MaxValueValidator(1)]), + ), + migrations.AlterField( + model_name='windinputs', + name='om_cost_per_kw', + field=models.FloatField(blank=True, default=42, help_text='Annual operations and maintenance costs in $/kW', validators=[django.core.validators.MinValueValidator(0), django.core.validators.MaxValueValidator(1000.0)]), + ), + ] From cfc9b22d806fa46025e8236f5a5ad82f830b86f3 Mon Sep 17 00:00:00 2001 From: adfarth Date: Fri, 5 Sep 2025 10:09:23 -0600 Subject: [PATCH 09/12] chp and steamturbine macrs --- CHANGELOG.md | 10 ++++++---- reoptjl/models.py | 8 ++++---- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 07d2a7d64..09bc917a5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -38,11 +38,13 @@ Update the following inputs from the previous --> new values: - `Financial.chp_fuel_cost_escalation_rate_fraction `: 0.015 --> 0.0348 - `Financial.generator_fuel_cost_escalation_rate_fraction `: 0.012 --> 0.0197 - `Generator.fuel_cost_per_gallon`: 3.61 --> 2.25 -- `ColdThermalStorage`, `HotThermalStorage`, `ElectricStorage` `macrs_option_years` 7 --> 5 -- `ColdThermalStorage`, `HotThermalStorage`, `ElectricStorage`, `PV`, `Wind` `macrs_bonus_fraction` 0.6 --> 1.0 +- `ColdThermalStorage`, `HotThermalStorage`, `ElectricStorage` `macrs_option_years`: 7 --> 5 +- `CHP`, `ColdThermalStorage`, `HotThermalStorage`, `ElectricStorage`, `PV`, `Wind` `macrs_bonus_fraction` 0.6 --> 1.0 +- `GHP.macrs_bonus_fraction`: 0.4 --> 0.0 +- `GHP.macrs_option_years`: 5 --> 0 +- `SteamTurbine.macrs_bonus_fraction`: 0 --> 1.0 +- `SteamTurbine.macrs_option_years`: 0 --> 5 (in order for 100% bonus depr to apply) - `CHP.federal_itc_fraction`: 0.3 --> 0.0 -- `CHP.macrs_bonus_fraction` and `GHP.macrs_bonus_fraction`: 0.4 --> 0.0 -- `CHP.macrs_option_years` and `GHP.macrs_option_years`: 5 --> 0 - `Wind.om_cost_per_kw`: 36.0 --> 42.0 - `Wind.size_class_to_installed_cost` = Dict( "residential"=> 6339.0, --> 7692.0 diff --git a/reoptjl/models.py b/reoptjl/models.py index 2f203843e..b128ff11f 100644 --- a/reoptjl/models.py +++ b/reoptjl/models.py @@ -4432,13 +4432,13 @@ class CHPInputs(BaseModel, models.Model): #Financial and emissions macrs_option_years = models.IntegerField( - default=MACRS_YEARS_CHOICES.ZERO, + default=MACRS_YEARS_CHOICES.FIVE, choices=MACRS_YEARS_CHOICES.choices, blank=True, help_text="Duration over which accelerated depreciation will occur. Set to zero to disable" ) macrs_bonus_fraction = models.FloatField( - default=0.0, + default=1.0, validators=[ MinValueValidator(0), MaxValueValidator(1) @@ -6693,7 +6693,7 @@ class SIZE_CLASS_LIST(models.IntegerChoices): ) macrs_option_years = models.IntegerField( - default=MACRS_YEARS_CHOICES.ZERO, + default=MACRS_YEARS_CHOICES.FIVE, choices=MACRS_YEARS_CHOICES.choices, null=True, blank=True, @@ -6701,7 +6701,7 @@ class SIZE_CLASS_LIST(models.IntegerChoices): ) macrs_bonus_fraction = models.FloatField( - default=0.0, + default=1.0, validators=[ MinValueValidator(0), MaxValueValidator(1) From aa07560aed1111ddad8a4f971862cf470b7c2ae0 Mon Sep 17 00:00:00 2001 From: adfarth Date: Fri, 5 Sep 2025 11:56:06 -0600 Subject: [PATCH 10/12] Create 0094_alter_chpinputs_macrs_bonus_fraction_and_more.py --- ...chpinputs_macrs_bonus_fraction_and_more.py | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 reoptjl/migrations/0094_alter_chpinputs_macrs_bonus_fraction_and_more.py diff --git a/reoptjl/migrations/0094_alter_chpinputs_macrs_bonus_fraction_and_more.py b/reoptjl/migrations/0094_alter_chpinputs_macrs_bonus_fraction_and_more.py new file mode 100644 index 000000000..2af077603 --- /dev/null +++ b/reoptjl/migrations/0094_alter_chpinputs_macrs_bonus_fraction_and_more.py @@ -0,0 +1,34 @@ +# Generated by Django 4.0.7 on 2025-09-05 17:55 + +import django.core.validators +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('reoptjl', '0093_alter_chpinputs_federal_itc_fraction_and_more'), + ] + + operations = [ + migrations.AlterField( + model_name='chpinputs', + name='macrs_bonus_fraction', + field=models.FloatField(blank=True, default=1.0, help_text='Percent of upfront project costs to depreciate in year one in addition to scheduled depreciation', validators=[django.core.validators.MinValueValidator(0), django.core.validators.MaxValueValidator(1)]), + ), + migrations.AlterField( + model_name='chpinputs', + name='macrs_option_years', + field=models.IntegerField(blank=True, choices=[(0, 'Zero'), (5, 'Five'), (7, 'Seven')], default=5, help_text='Duration over which accelerated depreciation will occur. Set to zero to disable'), + ), + migrations.AlterField( + model_name='steamturbineinputs', + name='macrs_bonus_fraction', + field=models.FloatField(blank=True, default=1.0, help_text='Percent of upfront project costs to depreciate in year one in addition to scheduled depreciation', null=True, validators=[django.core.validators.MinValueValidator(0), django.core.validators.MaxValueValidator(1)]), + ), + migrations.AlterField( + model_name='steamturbineinputs', + name='macrs_option_years', + field=models.IntegerField(blank=True, choices=[(0, 'Zero'), (5, 'Five'), (7, 'Seven')], default=5, help_text='Duration over which accelerated depreciation will occur. Set to zero to disable', null=True), + ), + ] From 1896ae21a9d051643c9a25b4331220f3a7f082dc Mon Sep 17 00:00:00 2001 From: adfarth Date: Fri, 5 Sep 2025 16:40:42 -0600 Subject: [PATCH 11/12] Update Manifest.toml --- julia_src/Manifest.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/julia_src/Manifest.toml b/julia_src/Manifest.toml index fb7eca19a..51fb10779 100644 --- a/julia_src/Manifest.toml +++ b/julia_src/Manifest.toml @@ -922,8 +922,8 @@ 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 = "7152b01634998853fac6b0fd386d46d22b83c474" -repo-rev = "misc-defaults" +git-tree-sha1 = "facf03d9eb09c6b03e0ec56f7d22dbedc7e3ca23" +repo-rev = "develop" repo-url = "https://github.com/NREL/REopt.jl.git" uuid = "d36ad4e8-d74a-4f7a-ace1-eaea049febf6" version = "0.53.2" From fb23f3775c8076e74d460baf4e55fc9c6fe1e7ca Mon Sep 17 00:00:00 2001 From: adfarth Date: Tue, 16 Sep 2025 15:26:14 -0600 Subject: [PATCH 12/12] update REopt version --- julia_src/Manifest.toml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/julia_src/Manifest.toml b/julia_src/Manifest.toml index 51fb10779..756844116 100644 --- a/julia_src/Manifest.toml +++ b/julia_src/Manifest.toml @@ -922,11 +922,9 @@ 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 = "facf03d9eb09c6b03e0ec56f7d22dbedc7e3ca23" -repo-rev = "develop" -repo-url = "https://github.com/NREL/REopt.jl.git" +git-tree-sha1 = "f9fd5a8419a3a1c057403fb34fd4f47c15afe28e" uuid = "d36ad4e8-d74a-4f7a-ace1-eaea049febf6" -version = "0.53.2" +version = "0.54.0" [[deps.Random]] deps = ["SHA"]