diff --git a/CHANGELOG.md b/CHANGELOG.md index 20cdcd28d..10b31d4a0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,6 +26,12 @@ Classify the change according to the following categories: ##### Removed ### Patches +## Develop 2023-10-11 +### Minor Updates +##### Changed +- Updates to CHP cost and performance defaults, from updating REopt.jl +- Changed upper limit on `CHPInputs.size_class` to 7 to reflect changes in CHP defaults. + ## v3.1.1 ### Minor Updates ##### Added diff --git a/julia_src/Manifest.toml b/julia_src/Manifest.toml index 699507bba..136da6cc5 100644 --- a/julia_src/Manifest.toml +++ b/julia_src/Manifest.toml @@ -215,9 +215,9 @@ version = "1.15.1" [[deps.DiskArrays]] deps = ["OffsetArrays"] -git-tree-sha1 = "7a6ada7a039841a8eac8fe22690d55b401f8b52c" +git-tree-sha1 = "1bfa9de80f35ac63c6c381b2d43c590875896a1f" uuid = "3c3547ce-8d99-4f5e-a174-61eb10b00ae3" -version = "0.3.20" +version = "0.3.22" [[deps.DocStringExtensions]] deps = ["LibGit2"] @@ -255,9 +255,9 @@ version = "1.16.1" [[deps.FilePathsBase]] deps = ["Compat", "Dates", "Mmap", "Printf", "Test", "UUIDs"] -git-tree-sha1 = "e27c4ebe80e8699540f2d6c805cc12203b614f12" +git-tree-sha1 = "9f00e42f8d99fdde64d40c8ea5d14269a2e2c1aa" uuid = "48062228-2e41-5def-b9a4-89aafe57970f" -version = "0.9.20" +version = "0.9.21" [[deps.FileWatching]] uuid = "7b1f6079-737a-58dc-b8bc-7a2ca5c1b5ee" @@ -303,9 +303,9 @@ version = "0.4.1" [[deps.GeoInterface]] deps = ["Extents"] -git-tree-sha1 = "bb198ff907228523f3dee1070ceee63b9359b6ab" +git-tree-sha1 = "d53480c0793b13341c40199190f92c611aa2e93c" uuid = "cf35fbd7-0cd7-5166-be24-54bfbe79505f" -version = "1.3.1" +version = "1.3.2" [[deps.GeoInterfaceRecipes]] deps = ["GeoInterface", "RecipesBase"] @@ -389,9 +389,9 @@ uuid = "92d709cd-6900-40b7-9082-c6be49f344b6" version = "0.2.2" [[deps.IterTools]] -git-tree-sha1 = "fa6287a4469f5e048d763df38279ee729fbd44e5" +git-tree-sha1 = "4ced6667f9974fc5c5943fa5e2ef1ca43ea9e450" uuid = "c8e1da08-722c-5040-9ed9-7db0dc04731e" -version = "1.4.0" +version = "1.8.0" [[deps.IteratorInterfaceExtensions]] git-tree-sha1 = "a3f24677c21f5bbe9d2a714f95dcd58337fb2856" @@ -504,9 +504,9 @@ uuid = "56ddb016-857b-54e1-b83d-db4d58db5568" [[deps.LoggingExtras]] deps = ["Dates", "Logging"] -git-tree-sha1 = "0d097476b6c381ab7906460ef1ef1638fbce1d91" +git-tree-sha1 = "c1dd6d7978c12545b4179fb6153b9250c96b0075" uuid = "e6f89c97-d47a-5376-807f-9c37f3926c36" -version = "1.0.2" +version = "1.0.3" [[deps.Lz4_jll]] deps = ["Artifacts", "JLLWrappers", "Libdl"] @@ -566,9 +566,9 @@ version = "2.28.0+0" [[deps.MicrosoftMPI_jll]] deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] -git-tree-sha1 = "a8027af3d1743b3bfae34e54872359fdebb31422" +git-tree-sha1 = "a7023883872e52bc29bcaac74f19adf39347d2d5" uuid = "9237b28f-5490-5468-be7b-bb81f5f5e6cf" -version = "10.1.3+4" +version = "10.1.4+0" [[deps.Missings]] deps = ["DataAPI"] @@ -629,9 +629,9 @@ version = "0.8.1+0" [[deps.OpenMPI_jll]] deps = ["Artifacts", "CompilerSupportLibraries_jll", "JLLWrappers", "LazyArtifacts", "Libdl", "MPIPreferences", "TOML"] -git-tree-sha1 = "f3080f4212a8ba2ceb10a34b938601b862094314" +git-tree-sha1 = "e25c1778a98e34219a00455d6e4384e017ea9762" uuid = "fe0851c0-eecd-5654-98d4-656369965a5c" -version = "4.1.5+0" +version = "4.1.6+0" [[deps.OpenSSL]] deps = ["BitFlags", "Dates", "MozillaCACerts_jll", "OpenSSL_jll", "Sockets"] @@ -717,11 +717,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 = "413b5cbf443cbfe03c94bab45e84a6bd4ad81b97" -repo-rev = "master" +git-tree-sha1 = "c4da4204dfbe8aa06a9f60b8c238c67969f7596b" +repo-rev = "size-class-recalc" repo-url = "https://github.com/NREL/REopt.jl.git" uuid = "d36ad4e8-d74a-4f7a-ace1-eaea049febf6" -version = "0.35.0" +version = "0.36.0" [[deps.Random]] deps = ["SHA", "Serialization"] diff --git a/reoptjl/migrations/0049_alter_chpinputs_size_class.py b/reoptjl/migrations/0049_alter_chpinputs_size_class.py new file mode 100644 index 000000000..b6c0d5005 --- /dev/null +++ b/reoptjl/migrations/0049_alter_chpinputs_size_class.py @@ -0,0 +1,19 @@ +# Generated by Django 4.0.7 on 2023-10-16 21:27 + +import django.core.validators +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('reoptjl', '0048_existingboileroutputs_annual_fuel_consumption_mmbtu_bau_and_more'), + ] + + operations = [ + migrations.AlterField( + model_name='chpinputs', + name='size_class', + field=models.IntegerField(blank=True, help_text='CHP size class. Must be an integer value between 0 and 7', null=True, validators=[django.core.validators.MinValueValidator(0), django.core.validators.MaxValueValidator(7)]), + ), + ] diff --git a/reoptjl/models.py b/reoptjl/models.py index a90a71c71..adfd53b3a 100644 --- a/reoptjl/models.py +++ b/reoptjl/models.py @@ -3895,11 +3895,11 @@ class CHPInputs(BaseModel, models.Model): size_class = models.IntegerField( validators=[ MinValueValidator(0), - MaxValueValidator(6) + MaxValueValidator(7) ], null=True, blank=True, - help_text="CHP size class. Must be an integer value between 0 and 6" + help_text="CHP size class. Must be an integer value between 0 and 7" ) min_kw = models.FloatField( default=0, diff --git a/reoptjl/test/posts/test_thermal_in_results.json b/reoptjl/test/posts/test_thermal_in_results.json index 86993efbc..6e36dc9e3 100644 --- a/reoptjl/test/posts/test_thermal_in_results.json +++ b/reoptjl/test/posts/test_thermal_in_results.json @@ -37,7 +37,7 @@ }, "ExistingBoiler": { "efficiency": 0.72, - "production_type": "steam", + "production_type": "hot_water", "fuel_cost_per_mmbtu": 10 }, "ExistingChiller": { diff --git a/reoptjl/test/test_http_endpoints.py b/reoptjl/test/test_http_endpoints.py index b8410fb91..7f65dcda9 100644 --- a/reoptjl/test/test_http_endpoints.py +++ b/reoptjl/test/test_http_endpoints.py @@ -33,18 +33,8 @@ def test_chp_defaults(self): # Check the endpoint logic with the expected selection self.assertEqual(http_response["prime_mover"], "combustion_turbine") - self.assertEqual(http_response["size_class"], 3) + self.assertEqual(http_response["size_class"], 2) self.assertGreater(http_response["chp_elec_size_heuristic_kw"], 3500.0) - - # Check that size_class logic is the same - # Modify input names for v2 - inputs_v2 = { - "existing_boiler_production_type_steam_or_hw": inputs["hot_water_or_steam"], - "avg_boiler_fuel_load_mmbtu_per_hr": inputs["avg_boiler_fuel_load_mmbtu_per_hour"] - } - resp = self.api_client.get(f'/v2/chp_defaults', data=inputs_v2) - v2_response = json.loads(resp.content) - self.assertEqual(http_response["size_class"], v2_response["size_class"]) def test_steamturbine_defaults(self): @@ -222,7 +212,6 @@ def test_default_existing_chiller_cop(self): # Call to the django view endpoint /get_existing_chiller_default_cop which calls the http.jl endpoint resp = self.api_client.get(f'/v3/get_existing_chiller_default_cop', data=inputs_dict) view_response = json.loads(resp.content) - print(view_response) self.assertEqual(view_response["existing_chiller_cop"], 4.4) @@ -232,7 +221,6 @@ def test_default_existing_chiller_cop(self): # Call to the django view endpoint /get_existing_chiller_default_cop which calls the http.jl endpoint resp = self.api_client.get(f'/v3/get_existing_chiller_default_cop', data=inputs_dict) view_response = json.loads(resp.content) - print(view_response) self.assertEqual(view_response["existing_chiller_cop"], 4.545) @@ -246,7 +234,6 @@ def test_default_existing_chiller_cop(self): # Call to the django view endpoint /get_existing_chiller_default_cop which calls the http.jl endpoint resp = self.api_client.get(f'/v3/get_existing_chiller_default_cop', data=inputs_dict) view_response = json.loads(resp.content) - print(view_response) self.assertEqual(view_response["existing_chiller_cop"], 4.69) @@ -259,7 +246,6 @@ def test_default_existing_chiller_cop(self): # Call to the django view endpoint /get_existing_chiller_default_cop which calls the http.jl endpoint resp = self.api_client.get(f'/v3/get_existing_chiller_default_cop', data=inputs_dict) view_response = json.loads(resp.content) - print(view_response) self.assertEqual(view_response["existing_chiller_cop"], 4.69) @@ -271,7 +257,6 @@ def test_default_existing_chiller_cop(self): # Call to the django view endpoint /get_existing_chiller_default_cop which calls the http.jl endpoint resp = self.api_client.get(f'/v3/get_existing_chiller_default_cop', data=inputs_dict) view_response = json.loads(resp.content) - print(view_response) self.assertEqual(view_response["existing_chiller_cop"], 4.4) diff --git a/reoptjl/test/test_job_endpoint.py b/reoptjl/test/test_job_endpoint.py index d0952650f..cce93b450 100644 --- a/reoptjl/test/test_job_endpoint.py +++ b/reoptjl/test/test_job_endpoint.py @@ -31,8 +31,8 @@ def test_multiple_outages(self): self.assertEqual(np.array(results["Outages"]["chp_fuel_used_per_outage_mmbtu"]).shape, (1,2)) self.assertAlmostEqual(results["Outages"]["expected_outage_cost"], 0.0, places=-2) self.assertAlmostEqual(sum(sum(np.array(results["Outages"]["unserved_load_per_outage_kwh"]))), 0.0, places=0) - self.assertAlmostEqual(results["Outages"]["microgrid_upgrade_capital_cost"], 1927766, places=-2) - self.assertAlmostEqual(results["Financial"]["lcc"], 59658835, places=-3) + self.assertAlmostEqual(results["Outages"]["microgrid_upgrade_capital_cost"], 1971108, places=-2) + self.assertAlmostEqual(results["Financial"]["lcc"], 59865241, places=-3) def test_pv_battery_and_emissions_defaults_from_julia(self): """ diff --git a/reoptjl/views.py b/reoptjl/views.py index c2d5e1d22..aa869c797 100644 --- a/reoptjl/views.py +++ b/reoptjl/views.py @@ -434,7 +434,7 @@ def simulated_load(request): valid_keys = ["doe_reference_name","latitude","longitude","load_type","percent_share","annual_kwh", "monthly_totals_kwh","annual_mmbtu","annual_fraction","annual_tonhour","monthly_tonhour", "monthly_mmbtu","monthly_fraction","max_thermal_factor_on_peak_load","chiller_cop", - "addressable_load_fraction", "cooling_doe_ref_name", "cooling_pct_share"] + "addressable_load_fraction", "cooling_doe_ref_name", "cooling_pct_share", "boiler_efficiency"] for key in request.GET.keys(): k = key if "[" in key: diff --git a/resilience_stats/tests/test_erp.py b/resilience_stats/tests/test_erp.py index 00c38dc29..59996711d 100644 --- a/resilience_stats/tests/test_erp.py +++ b/resilience_stats/tests/test_erp.py @@ -149,9 +149,9 @@ def test_erp_with_reopt_run_uuid(self): resp = self.get_results_sim(erp_run_uuid) results = json.loads(resp.content) - self.assertAlmostEqual(results["outputs"]["mean_cumulative_survival_by_duration"][23], 0.9661, places=3) + self.assertAlmostEqual(results["outputs"]["mean_cumulative_survival_by_duration"][23], 0.9661, delta=0.0015) self.assertAlmostEqual(results["outputs"]["cumulative_survival_final_time_step"][0], 0.962327, places=3) - self.assertAlmostEqual(results["outputs"]["mean_cumulative_survival_final_time_step"], 0.9661, places=3) + self.assertAlmostEqual(results["outputs"]["mean_cumulative_survival_final_time_step"], 0.9661, places=2) def test_erp_with_no_opt(self): """