From f9f145eec13172530fcc1fc08015a7f962611f70 Mon Sep 17 00:00:00 2001 From: bill-becker Date: Tue, 14 Jan 2025 12:07:13 -0700 Subject: [PATCH 01/13] Temp change REopt.jl to develop branch which will be v0.50.0 --- 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 6e28604ac..1affd53ed 100644 --- a/julia_src/Manifest.toml +++ b/julia_src/Manifest.toml @@ -929,7 +929,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 = "67eade881254923d75cf80aac40ca8da2f17351e" +git-tree-sha1 = "cf7477d695777d464d991b21b23f82708fcc7881" +repo-rev = "develop" +repo-url = "https://github.com/NREL/REopt.jl.git" uuid = "d36ad4e8-d74a-4f7a-ace1-eaea049febf6" version = "0.49.1" From 7847fd13140eb119b1d1b5a1da30babb7c95a9f3 Mon Sep 17 00:00:00 2001 From: bill-becker Date: Tue, 14 Jan 2025 14:59:22 -0700 Subject: [PATCH 02/13] Add migration file for GhpGhx defaults updates --- ...ghpghxinputs_borehole_depth_ft_and_more.py | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 ghpghx/migrations/0019_alter_ghpghxinputs_borehole_depth_ft_and_more.py diff --git a/ghpghx/migrations/0019_alter_ghpghxinputs_borehole_depth_ft_and_more.py b/ghpghx/migrations/0019_alter_ghpghxinputs_borehole_depth_ft_and_more.py new file mode 100644 index 000000000..6740a733f --- /dev/null +++ b/ghpghx/migrations/0019_alter_ghpghxinputs_borehole_depth_ft_and_more.py @@ -0,0 +1,44 @@ +# Generated by Django 4.0.7 on 2025-01-14 21:50 + +import django.core.validators +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('ghpghx', '0018_ghpghxinputs_wwhp_cooling_pump_fluid_flow_rate_gpm_per_ton_and_more'), + ] + + operations = [ + migrations.AlterField( + model_name='ghpghxinputs', + name='borehole_depth_ft', + field=models.FloatField(blank=True, default=443.0, help_text='Vertical depth of each borehole [ft]', validators=[django.core.validators.MinValueValidator(10.0), django.core.validators.MaxValueValidator(600.0)]), + ), + migrations.AlterField( + model_name='ghpghxinputs', + name='borehole_diameter_inch', + field=models.FloatField(blank=True, default=6.0, help_text='Diameter of the borehole/well drilled in the ground [in]', validators=[django.core.validators.MinValueValidator(0.25), django.core.validators.MaxValueValidator(24.0)]), + ), + migrations.AlterField( + model_name='ghpghxinputs', + name='ghx_header_depth_ft', + field=models.FloatField(blank=True, default=6.6, help_text='Depth under the ground of the GHX header pipe [ft]', validators=[django.core.validators.MinValueValidator(0.1), django.core.validators.MaxValueValidator(50.0)]), + ), + migrations.AlterField( + model_name='ghpghxinputs', + name='ghx_pipe_thermal_conductivity_btu_per_hr_ft_f', + field=models.FloatField(blank=True, default=0.23, help_text='Thermal conductivity of the GHX pipe [Btu/(hr-ft-degF)]', validators=[django.core.validators.MinValueValidator(0.01), django.core.validators.MaxValueValidator(10.0)]), + ), + migrations.AlterField( + model_name='ghpghxinputs', + name='ghx_shank_space_inch', + field=models.FloatField(blank=True, default=1.27, help_text='Distance between the centerline of the upwards and downwards u-tube legs [in]', validators=[django.core.validators.MinValueValidator(0.5), django.core.validators.MaxValueValidator(100.0)]), + ), + migrations.AlterField( + model_name='ghpghxinputs', + name='grout_thermal_conductivity_btu_per_hr_ft_f', + field=models.FloatField(blank=True, default=0.75, help_text='Thermal conductivity of the grout material in a borehole [Btu/(hr-ft-degF)]', validators=[django.core.validators.MinValueValidator(0.01), django.core.validators.MaxValueValidator(10.0)]), + ), + ] From 0cb9ad7189ef16e39a86fd799d29d91872076b59 Mon Sep 17 00:00:00 2001 From: bill-becker Date: Tue, 14 Jan 2025 15:00:08 -0700 Subject: [PATCH 03/13] Remove default load year --- .../0075_coolingloadinputs_year_and_more.py | 39 +++++++++++++++++++ reoptjl/models.py | 35 +++++++---------- 2 files changed, 54 insertions(+), 20 deletions(-) create mode 100644 reoptjl/migrations/0075_coolingloadinputs_year_and_more.py diff --git a/reoptjl/migrations/0075_coolingloadinputs_year_and_more.py b/reoptjl/migrations/0075_coolingloadinputs_year_and_more.py new file mode 100644 index 000000000..9576cbe59 --- /dev/null +++ b/reoptjl/migrations/0075_coolingloadinputs_year_and_more.py @@ -0,0 +1,39 @@ +# Generated by Django 4.0.7 on 2025-01-14 19:46 + +import django.core.validators +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('reoptjl', '0074_alter_domestichotwaterloadinputs_normalize_and_scale_load_profile_input_and_more'), + ] + + operations = [ + migrations.AddField( + model_name='coolingloadinputs', + name='year', + field=models.IntegerField(blank=True, help_text="Year of Custom Load Profile. If a custom load profile is uploaded via the thermal_loads_ton parameter, it is important that this year correlates with the electric load profile so that weekdays/weekends are determined correctly for the utility rate tariff. If a DOE Reference Building profile (aka 'simulated' profile) is used, the year is set to 2017 since the DOE profiles start on a Sunday.", null=True, validators=[django.core.validators.MinValueValidator(1), django.core.validators.MaxValueValidator(9999)]), + ), + migrations.AlterField( + model_name='domestichotwaterloadinputs', + name='year', + field=models.IntegerField(blank=True, help_text="Year of Custom Load Profile. If a custom load profile is uploaded via the fuel_loads_mmbtu_per_hour parameter, it is important that this year correlates with the electric load profile so that weekdays/weekends are determined correctly for the utility rate tariff. If a DOE Reference Building profile (aka 'simulated' profile) is used, the year is set to 2017 since the DOE profiles start on a Sunday.", null=True, validators=[django.core.validators.MinValueValidator(1), django.core.validators.MaxValueValidator(9999)]), + ), + migrations.AlterField( + model_name='electricloadinputs', + name='year', + field=models.IntegerField(blank=True, help_text="Year of Custom Load Profile. If a custom load profile is uploaded via the loads_kw parameter, it is important that this year correlates with the load profile so that weekdays/weekends are determined correctly for the utility rate tariff. If a DOE Reference Building profile (aka 'simulated' profile) is used, the year is set to 2017 since the DOE profiles start on a Sunday.", null=True, validators=[django.core.validators.MinValueValidator(1), django.core.validators.MaxValueValidator(9999)]), + ), + migrations.AlterField( + model_name='processheatloadinputs', + name='year', + field=models.IntegerField(blank=True, help_text="Year of Custom Load Profile. If a custom load profile is uploaded via the fuel_loads_mmbtu_per_hour parameter, it is important that this year correlates with the electric load profile so that weekdays/weekends are determined correctly for the utility rate tariff. If a Industrial Reference Building profile (aka 'simulated' profile) is used, the year is set to 2017 to be consistent with the DOE reference building year which starts on a Sunday.", null=True, validators=[django.core.validators.MinValueValidator(1), django.core.validators.MaxValueValidator(9999)]), + ), + migrations.AlterField( + model_name='spaceheatingloadinputs', + name='year', + field=models.IntegerField(blank=True, help_text="Year of Custom Load Profile. If a custom load profile is uploaded via the fuel_loads_mmbtu_per_hour parameter, it is important that this year correlates with the electric load profile so that weekdays/weekends are determined correctly for the utility rate tariff. If a DOE Reference Building profile (aka 'simulated' profile) is used, the year is set to 2017 since the DOE profiles start on a Sunday.", null=True, validators=[django.core.validators.MinValueValidator(1), django.core.validators.MaxValueValidator(9999)]), + ), + ] diff --git a/reoptjl/models.py b/reoptjl/models.py index f29d43060..e05a6d263 100644 --- a/reoptjl/models.py +++ b/reoptjl/models.py @@ -1213,7 +1213,6 @@ class ElectricLoadInputs(BaseModel, models.Model): "https://energy.gov/eere/buildings/commercial-reference-buildings") ) year = models.IntegerField( - default=2022, validators=[ MinValueValidator(1), MaxValueValidator(9999) @@ -4664,6 +4663,18 @@ class CoolingLoadInputs(BaseModel, models.Model): ) ) + year = models.IntegerField( + validators=[ + MinValueValidator(1), + MaxValueValidator(9999) + ], + null=True, blank=True, + help_text=("Year of Custom Load Profile. If a custom load profile is uploaded via the thermal_loads_ton parameter, it " + "is important that this year correlates with the electric load profile so that weekdays/weekends are " + "determined correctly for the utility rate tariff. If a DOE Reference Building profile (aka " + "'simulated' profile) is used, the year is set to 2017 since the DOE profiles start on a Sunday.") + ) + annual_fraction_of_electric_load = models.FloatField( validators=[ MinValueValidator(0), @@ -6908,7 +6919,6 @@ class SpaceHeatingLoadInputs(BaseModel, models.Model): ) year = models.IntegerField( - default=2022, validators=[ MinValueValidator(1), MaxValueValidator(9999) @@ -7088,7 +7098,6 @@ class DomesticHotWaterLoadInputs(BaseModel, models.Model): ) year = models.IntegerField( - default=2022, validators=[ MinValueValidator(1), MaxValueValidator(9999) @@ -7242,7 +7251,6 @@ class ProcessHeatLoadInputs(BaseModel, models.Model): ) year = models.IntegerField( - default=2022, validators=[ MinValueValidator(1), MaxValueValidator(9999) @@ -7250,28 +7258,15 @@ class ProcessHeatLoadInputs(BaseModel, models.Model): null=True, blank=True, help_text=("Year of Custom Load Profile. If a custom load profile is uploaded via the fuel_loads_mmbtu_per_hour parameter, it " "is important that this year correlates with the electric load profile so that weekdays/weekends are " - "determined correctly for the utility rate tariff. If a DOE Reference Building profile (aka " - "'simulated' profile) is used, the year is set to 2017 since the DOE profiles start on a Sunday.") + "determined correctly for the utility rate tariff. If a Industrial Reference Building profile (aka " + "'simulated' profile) is used, the year is set to 2017 to be consistent with the DOE reference building year which starts on a Sunday.") ) normalize_and_scale_load_profile_input = models.BooleanField( blank=True, default=False, help_text=("Takes the input fuel_loads_mmbtu_per_hour and normalizes and scales it to annual or monthly energy inputs.") - ) - - year = models.IntegerField( - default=2022, - validators=[ - MinValueValidator(1), - MaxValueValidator(9999) - ], - null=True, blank=True, - help_text=("Year of Custom Load Profile. If a custom load profile is uploaded via the fuel_loads_mmbtu_per_hour parameter, it " - "is important that this year correlates with the electric load profile so that weekdays/weekends are " - "determined correctly for the utility rate tariff. If a DOE Reference Building profile (aka " - "'simulated' profile) is used, the year is set to 2017 since the DOE profiles start on a Sunday.") - ) + ) blended_industrial_reference_names = ArrayField( models.TextField( From 1c1bc31b3bf49b454eae43fb35e458b8c80413db Mon Sep 17 00:00:00 2001 From: bill-becker Date: Wed, 15 Jan 2025 10:08:51 -0700 Subject: [PATCH 04/13] Remove clean() assignment of load year for heating and cooling, keep electric Since heating and cooling loads will now use whatever load year is input for electric, if not otherwise input, we don't want to assign 2017 year for heating and cooling loads, even if they are using CRBs --- reoptjl/models.py | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/reoptjl/models.py b/reoptjl/models.py index e05a6d263..930743186 100644 --- a/reoptjl/models.py +++ b/reoptjl/models.py @@ -4725,10 +4725,6 @@ def clean(self): "The number of blended_doe_reference_names must equal the number of blended_doe_reference_percents." if not math.isclose(sum(self.blended_doe_reference_percents), 1.0): error_messages["blended_doe_reference_percents"] = "Sum must = 1.0." - - if self.doe_reference_name != "" or \ - len(self.blended_doe_reference_names) > 0: - self.year = 2017 # the validator provides an "info" message regarding this) if len(self.monthly_fractions_of_electric_load) > 0: if len(self.monthly_fractions_of_electric_load) != 12: @@ -6989,10 +6985,6 @@ def clean(self): "The number of blended_doe_reference_names must equal the number of blended_doe_reference_percents." if not math.isclose(sum(self.blended_doe_reference_percents), 1.0): error_messages["blended_doe_reference_percents"] = "Sum must = 1.0." - - if self.doe_reference_name != "" or \ - len(self.blended_doe_reference_names) > 0: - self.year = 2017 # the validator provides an "info" message regarding this) if self.addressable_load_fraction == None: self.addressable_load_fraction = list([1.0]) # should not convert to timeseries, in case it is to be used with monthly_mmbtu or annual_mmbtu @@ -7168,10 +7160,6 @@ def clean(self): "The number of blended_doe_reference_names must equal the number of blended_doe_reference_percents." if not math.isclose(sum(self.blended_doe_reference_percents), 1.0): error_messages["blended_doe_reference_percents"] = "Sum must = 1.0." - - if self.doe_reference_name != "" or \ - len(self.blended_doe_reference_names) > 0: - self.year = 2017 # the validator provides an "info" message regarding this) if self.addressable_load_fraction == None: self.addressable_load_fraction = list([1.0]) # should not convert to timeseries, in case it is to be used with monthly_mmbtu or annual_mmbtu @@ -7322,10 +7310,6 @@ def clean(self): "The number of blended_industrial_reference_names must equal the number of blended_industrial_reference_percents." if not math.isclose(sum(self.blended_industrial_reference_percents), 1.0): error_messages["blended_industrial_reference_percents"] = "Sum must = 1.0." - - if self.industrial_reference_name != "" or \ - len(self.blended_industrial_reference_names) > 0: - self.year = 2017 # the validator provides an "info" message regarding this) if self.addressable_load_fraction == None: self.addressable_load_fraction = list([1.0]) # should not convert to timeseries, in case it is to be used with monthly_mmbtu or annual_mmbtu From 522080d59b20609f93866c7bfd84e04e932742d8 Mon Sep 17 00:00:00 2001 From: bill-becker Date: Fri, 17 Jan 2025 15:28:46 -0700 Subject: [PATCH 05/13] Add optional year input for GET requests to /simulated_load To shift CRB profiles to the calendar year of the input --- reoptjl/views.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/reoptjl/views.py b/reoptjl/views.py index 534e0445f..3dc915bc1 100644 --- a/reoptjl/views.py +++ b/reoptjl/views.py @@ -538,6 +538,9 @@ def simulated_load(request): inputs["longitude"] = float(request.GET['longitude']) # Optional load_type - will default to "electric" inputs["load_type"] = request.GET.get('load_type') + # Optional year parameter to shift the CRB profile from 2017 (also 2023) to the input year + if 'year' in request.GET: + inputs["year"] = int(request.GET['year']) if inputs["load_type"] == 'process_heat': expected_reference_name = 'industrial_reference_name' From 5a55caeaa31b09c17ac8670e2be012e6b2f87d12 Mon Sep 17 00:00:00 2001 From: bill-becker Date: Fri, 17 Jan 2025 21:07:33 -0700 Subject: [PATCH 06/13] Add force_dispatch input for ASHP Techs --- ...aceheaterinputs_force_dispatch_and_more.py | 45 +++++++++++++++++++ reoptjl/models.py | 20 +++++++-- 2 files changed, 61 insertions(+), 4 deletions(-) create mode 100644 reoptjl/migrations/0076_ashpspaceheaterinputs_force_dispatch_and_more.py diff --git a/reoptjl/migrations/0076_ashpspaceheaterinputs_force_dispatch_and_more.py b/reoptjl/migrations/0076_ashpspaceheaterinputs_force_dispatch_and_more.py new file mode 100644 index 000000000..a4135ef47 --- /dev/null +++ b/reoptjl/migrations/0076_ashpspaceheaterinputs_force_dispatch_and_more.py @@ -0,0 +1,45 @@ +# Generated by Django 4.0.7 on 2025-01-18 04:04 + +import django.contrib.postgres.fields +import django.core.validators +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('reoptjl', '0075_coolingloadinputs_year_and_more'), + ] + + operations = [ + migrations.AddField( + model_name='ashpspaceheaterinputs', + name='force_dispatch', + field=models.BooleanField(default=True, help_text='Boolean indicator if ASHP space heater is forced to its maximize output if true', null=True), + ), + migrations.AddField( + model_name='ashpwaterheaterinputs', + name='force_dispatch', + field=models.BooleanField(default=True, help_text='Boolean indicator if ASHP water heater is forced to its maximize output if true', null=True), + ), + migrations.AlterField( + model_name='ashpwaterheaterinputs', + name='force_into_system', + field=models.BooleanField(blank=True, help_text='Boolean indicator if ASHP water heater serves compatible thermal loads exclusively in optimized scenario', null=True), + ), + migrations.AlterField( + model_name='ashpwaterheaterinputs', + name='heating_cf_reference', + field=django.contrib.postgres.fields.ArrayField(base_field=models.FloatField(blank=True, null=True, validators=[django.core.validators.MinValueValidator(0), django.core.validators.MaxValueValidator(20.0)]), blank=True, default=list, help_text='Reference points for ASHP water heating system heating capacity factor(ratio of heating thermal power to rated capacity)', size=None), + ), + migrations.AlterField( + model_name='ashpwaterheaterinputs', + name='heating_cop_reference', + field=django.contrib.postgres.fields.ArrayField(base_field=models.FloatField(blank=True, null=True, validators=[django.core.validators.MinValueValidator(0), django.core.validators.MaxValueValidator(20.0)]), blank=True, default=list, help_text='Reference points for ASHP water heating system heating coefficient of performance (COP) (ratio of usable heating thermal energy produced per unit electric energy consumed)', size=None), + ), + migrations.AlterField( + model_name='ashpwaterheaterinputs', + name='heating_reference_temps_degF', + field=django.contrib.postgres.fields.ArrayField(base_field=models.FloatField(blank=True, null=True, validators=[django.core.validators.MinValueValidator(-275.0), django.core.validators.MaxValueValidator(200.0)]), blank=True, default=list, help_text="Reference temperatures for ASHP water heating system's heating COP and CF [Fahrenheit]", size=None), + ), + ] diff --git a/reoptjl/models.py b/reoptjl/models.py index 930743186..93985bc6e 100644 --- a/reoptjl/models.py +++ b/reoptjl/models.py @@ -5477,6 +5477,12 @@ class ASHPSpaceHeaterInputs(BaseModel, models.Model): help_text="Boolean indicator if ASHP space heater serves compatible thermal loads exclusively in optimized scenario" ) + force_dispatch = models.BooleanField( + null=True, + default=True, + help_text="Boolean indicator if ASHP space heater is forced to its maximize output if true" + ) + avoided_capex_by_ashp_present_value = models.FloatField( validators=[ MinValueValidator(0), @@ -5708,7 +5714,7 @@ class ASHPWaterHeaterInputs(BaseModel, models.Model): ), default=list, blank=True, - help_text=(("Reference points for ASHP space heating system heating coefficient of performance (COP) " + help_text=(("Reference points for ASHP water heating system heating coefficient of performance (COP) " "(ratio of usable heating thermal energy produced per unit electric energy consumed)")) ) @@ -5722,7 +5728,7 @@ class ASHPWaterHeaterInputs(BaseModel, models.Model): ), default=list, blank=True, - help_text=(("Reference points for ASHP space heating system heating capac)ity factor" + help_text=(("Reference points for ASHP water heating system heating capacity factor" "(ratio of heating thermal power to rated capacity)")) ) @@ -5736,7 +5742,7 @@ class ASHPWaterHeaterInputs(BaseModel, models.Model): ), default=list, blank=True, - help_text=(("Reference temperatures for ASHP space heating system's heating COP and CF [Fahrenheit]")) + help_text=(("Reference temperatures for ASHP water heating system's heating COP and CF [Fahrenheit]")) ) avoided_capex_by_ashp_present_value = models.FloatField( @@ -5763,7 +5769,13 @@ class ASHPWaterHeaterInputs(BaseModel, models.Model): force_into_system = models.BooleanField( null=True, blank=True, - help_text="Boolean indicator if ASHP space heater serves compatible thermal loads exclusively in optimized scenario" + help_text="Boolean indicator if ASHP water heater serves compatible thermal loads exclusively in optimized scenario" + ) + + force_dispatch = models.BooleanField( + null=True, + default=True, + help_text="Boolean indicator if ASHP water heater is forced to its maximize output if true" ) def clean(self): From 4e83a834ffaf3431be2650805665382bf66089a8 Mon Sep 17 00:00:00 2001 From: bill-becker Date: Fri, 17 Jan 2025 21:08:19 -0700 Subject: [PATCH 07/13] Update REopt.jl#develop with ASHP force_dispatch --- 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 1affd53ed..c9b6265bb 100644 --- a/julia_src/Manifest.toml +++ b/julia_src/Manifest.toml @@ -929,7 +929,7 @@ 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 = "cf7477d695777d464d991b21b23f82708fcc7881" +git-tree-sha1 = "1bb53a050ed0b7b317f33d0c5cfc8f1df67450b8" repo-rev = "develop" repo-url = "https://github.com/NREL/REopt.jl.git" uuid = "d36ad4e8-d74a-4f7a-ace1-eaea049febf6" From 99449f860196e53c7985eeb50ad0ef3987f30700 Mon Sep 17 00:00:00 2001 From: bill-becker Date: Fri, 17 Jan 2025 22:36:38 -0700 Subject: [PATCH 08/13] Add force_dispatch to all_inputs_test.json --- reoptjl/test/posts/all_inputs_test.json | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/reoptjl/test/posts/all_inputs_test.json b/reoptjl/test/posts/all_inputs_test.json index 4da22063c..fbc26998a 100644 --- a/reoptjl/test/posts/all_inputs_test.json +++ b/reoptjl/test/posts/all_inputs_test.json @@ -368,7 +368,8 @@ "can_serve_cooling": true, "force_into_system": false, "avoided_capex_by_ashp_present_value": 0, - "back_up_temp_threshold_degF": -10.0 + "back_up_temp_threshold_degF": -10.0, + "force_dispatch": false }, "ASHPWaterHeater": { "min_ton": 10.0, @@ -385,6 +386,7 @@ "heating_reference_temps_degF": [-5, 17, 47], "force_into_system": false, "avoided_capex_by_ashp_present_value": 0, - "back_up_temp_threshold_degF": -10.0 + "back_up_temp_threshold_degF": -10.0, + "force_dispatch": false } } \ No newline at end of file From ebf58102e0edd9381784bd175d8ef7041d01b153 Mon Sep 17 00:00:00 2001 From: bill-becker Date: Tue, 21 Jan 2025 09:18:24 -0700 Subject: [PATCH 09/13] Change default min_allowable_peak_capacity_fraction to 0.25, from 0.5 --- reoptjl/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reoptjl/models.py b/reoptjl/models.py index 93985bc6e..a74475f63 100644 --- a/reoptjl/models.py +++ b/reoptjl/models.py @@ -5781,7 +5781,7 @@ class ASHPWaterHeaterInputs(BaseModel, models.Model): def clean(self): error_messages = {} if self.dict.get("min_allowable_ton") in [None, "", []] and self.dict.get("min_allowable_peak_capacity_fraction") in [None, "", []]: - self.min_allowable_peak_capacity_fraction = 0.5 + self.min_allowable_peak_capacity_fraction = 0.25 if self.dict.get("min_allowable_ton") not in [None, "", []] and self.dict.get("min_allowable_peak_capacity_fraction") not in [None, "", []]: error_messages["bad inputs"] = "At most one of min_allowable_ton and min_allowable_peak_capacity_fraction may be input to model {}".format(self.key) From edbb74fe424498f4f46c35e6236da2564256939f Mon Sep 17 00:00:00 2001 From: bill-becker Date: Tue, 21 Jan 2025 11:17:19 -0700 Subject: [PATCH 10/13] Update REopt.jl#develop prior to registering --- 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 c9b6265bb..262c4475a 100644 --- a/julia_src/Manifest.toml +++ b/julia_src/Manifest.toml @@ -929,7 +929,7 @@ 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 = "1bb53a050ed0b7b317f33d0c5cfc8f1df67450b8" +git-tree-sha1 = "541c260a6f1ad1c36a02b662fa959a27b4d759a7" repo-rev = "develop" repo-url = "https://github.com/NREL/REopt.jl.git" uuid = "d36ad4e8-d74a-4f7a-ace1-eaea049febf6" From ade3ec7dd87697a8c8d31e39bab9ca3a18d0a3df Mon Sep 17 00:00:00 2001 From: Zolan Date: Tue, 21 Jan 2025 12:49:45 -0700 Subject: [PATCH 11/13] minor updates to ASHP forced dispatch notes --- .../0076_ashpspaceheaterinputs_force_dispatch_and_more.py | 4 ++-- reoptjl/models.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/reoptjl/migrations/0076_ashpspaceheaterinputs_force_dispatch_and_more.py b/reoptjl/migrations/0076_ashpspaceheaterinputs_force_dispatch_and_more.py index a4135ef47..ba9831f00 100644 --- a/reoptjl/migrations/0076_ashpspaceheaterinputs_force_dispatch_and_more.py +++ b/reoptjl/migrations/0076_ashpspaceheaterinputs_force_dispatch_and_more.py @@ -15,12 +15,12 @@ class Migration(migrations.Migration): migrations.AddField( model_name='ashpspaceheaterinputs', name='force_dispatch', - field=models.BooleanField(default=True, help_text='Boolean indicator if ASHP space heater is forced to its maximize output if true', null=True), + field=models.BooleanField(default=True, help_text='Boolean indicator that ASHP space heater outputs either maximum capacity or site load if true', null=True), ), migrations.AddField( model_name='ashpwaterheaterinputs', name='force_dispatch', - field=models.BooleanField(default=True, help_text='Boolean indicator if ASHP water heater is forced to its maximize output if true', null=True), + field=models.BooleanField(default=True, help_text='Boolean indicator that ASHP water heater outputs either maximum capacity or site load if true', null=True), ), migrations.AlterField( model_name='ashpwaterheaterinputs', diff --git a/reoptjl/models.py b/reoptjl/models.py index a74475f63..97dbfd835 100644 --- a/reoptjl/models.py +++ b/reoptjl/models.py @@ -5480,7 +5480,7 @@ class ASHPSpaceHeaterInputs(BaseModel, models.Model): force_dispatch = models.BooleanField( null=True, default=True, - help_text="Boolean indicator if ASHP space heater is forced to its maximize output if true" + help_text="Boolean indicator that ASHP space heater outputs either maximum capacity or site load if true" ) avoided_capex_by_ashp_present_value = models.FloatField( @@ -5775,7 +5775,7 @@ class ASHPWaterHeaterInputs(BaseModel, models.Model): force_dispatch = models.BooleanField( null=True, default=True, - help_text="Boolean indicator if ASHP water heater is forced to its maximize output if true" + help_text="Boolean indicator that ASHP water heater outputs either maximum capacity or site load if true" ) def clean(self): From f96e037c0687adb5847047be7ae06c39c7c1df73 Mon Sep 17 00:00:00 2001 From: bill-becker Date: Wed, 22 Jan 2025 12:31:09 -0700 Subject: [PATCH 12/13] Update REopt.jl to registered v0.50.0 --- 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 262c4475a..1803c1732 100644 --- a/julia_src/Manifest.toml +++ b/julia_src/Manifest.toml @@ -929,11 +929,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 = "541c260a6f1ad1c36a02b662fa959a27b4d759a7" -repo-rev = "develop" -repo-url = "https://github.com/NREL/REopt.jl.git" +git-tree-sha1 = "324394f21cb7e2db3d9e7ebde19c4e83c5a64e0f" uuid = "d36ad4e8-d74a-4f7a-ace1-eaea049febf6" -version = "0.49.1" +version = "0.50.0" [[deps.Random]] deps = ["SHA"] From 259ce15de6a5e71a33258e5919818d6d517bdb13 Mon Sep 17 00:00:00 2001 From: Bill Becker <42586683+Bill-Becker@users.noreply.github.com> Date: Wed, 22 Jan 2025 14:04:52 -0700 Subject: [PATCH 13/13] Update CHANGELOG.md --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f6e33c1d1..95a227b61 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,6 +26,14 @@ Classify the change according to the following categories: ##### Removed ### Patches +## v3.11.0 +### Minor Updates +##### Changed +- Require `year` for all custom 8760/35040 load profile inputs +- Truncate the last day of the year instead of the leap day for leap years +##### Added +- Option for ASHP to `force_dispatch` (default = true) which maximizes ASHP thermal output + ## v3.10.2 ### Minor Updates ##### Changed