From 8ba357e48c31fc2c629c7eaa5c62e787f43cd875 Mon Sep 17 00:00:00 2001 From: Tucker Oddleifson Date: Fri, 7 Apr 2023 16:10:31 -0600 Subject: [PATCH 01/10] Modifications to reopt_inputs file to map user-defined PV locations to the pv_to_location variable --- src/core/reopt_inputs.jl | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/core/reopt_inputs.jl b/src/core/reopt_inputs.jl index f170918c2..a3775e1ad 100644 --- a/src/core/reopt_inputs.jl +++ b/src/core/reopt_inputs.jl @@ -311,8 +311,23 @@ function setup_tech_inputs(s::AbstractScenario) seg_yint = Dict{String, Dict{Int, Real}}() # PV specific arrays + # Section to extract the location of the PV arrays from the input s + pv_assignedlocations = Symbol[] + for pv in s.pvs + if pv.location == "roof" + pvlocationvalue = :roof + elseif pv.location == "ground" + pvlocationvalue = :ground + elseif pv.location == "both" + pvlocationvalue = :both + else + throw(@error("A provided PV location is not valid")) + end + push!(pv_assignedlocations, pvlocationvalue) + end + pvlocations = [:roof, :ground, :both] - pv_to_location = Dict(t => Dict(loc => 0) for (t, loc) in zip(techs.pv, pvlocations)) + pv_to_location = Dict(t => Dict(loc => 0) for (t, loc) in zip(techs.pv, pv_assignedlocations)) maxsize_pv_locations = DenseAxisArray([1.0e5, 1.0e5, 1.0e5], pvlocations) # default to large max size per location. Max size by roof, ground, both From 4d1f9e53ee92e9fbdf0bf3209075098253e2f53d Mon Sep 17 00:00:00 2001 From: adfarth Date: Wed, 12 Apr 2023 17:12:02 -0600 Subject: [PATCH 02/10] update pv_to_location nested dict --- src/core/reopt_inputs.jl | 24 +++++------------------- 1 file changed, 5 insertions(+), 19 deletions(-) diff --git a/src/core/reopt_inputs.jl b/src/core/reopt_inputs.jl index a3775e1ad..53173191d 100644 --- a/src/core/reopt_inputs.jl +++ b/src/core/reopt_inputs.jl @@ -310,24 +310,9 @@ function setup_tech_inputs(s::AbstractScenario) seg_max_size = Dict{String, Dict{Int, Real}}() seg_yint = Dict{String, Dict{Int, Real}}() - # PV specific arrays - # Section to extract the location of the PV arrays from the input s - pv_assignedlocations = Symbol[] - for pv in s.pvs - if pv.location == "roof" - pvlocationvalue = :roof - elseif pv.location == "ground" - pvlocationvalue = :ground - elseif pv.location == "both" - pvlocationvalue = :both - else - throw(@error("A provided PV location is not valid")) - end - push!(pv_assignedlocations, pvlocationvalue) - end - pvlocations = [:roof, :ground, :both] - pv_to_location = Dict(t => Dict(loc => 0) for (t, loc) in zip(techs.pv, pv_assignedlocations)) + d = Dict(loc => 0 for loc in pvlocations) + pv_to_location = Dict(t => copy(d) for t in techs.pv) maxsize_pv_locations = DenseAxisArray([1.0e5, 1.0e5, 1.0e5], pvlocations) # default to large max size per location. Max size by roof, ground, both @@ -486,11 +471,12 @@ function setup_pv_inputs(s::AbstractScenario, max_sizes, min_sizes, roof_existing_pv_kw, ground_existing_pv_kw, both_existing_pv_kw = 0.0, 0.0, 0.0 roof_max_kw, land_max_kw = 1.0e5, 1.0e5 - for pv in s.pvs + for pv in s.pvs production_factor[pv.name, :] = get_production_factor(pv, s.site.latitude, s.site.longitude; time_steps_per_hour=s.settings.time_steps_per_hour) for location in pvlocations - if pv.location == location + + if pv.location == String(location) # Must convert symbol to string pv_to_location[pv.name][location] = 1 else pv_to_location[pv.name][location] = 0 From a511d342301f98a5198714bcce346045d949ea0e Mon Sep 17 00:00:00 2001 From: adfarth Date: Mon, 17 Apr 2023 08:04:42 -0600 Subject: [PATCH 03/10] update maxsize_pv_locations to align with default PV max_kw both are now 1.0e9 --- src/core/reopt_inputs.jl | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/core/reopt_inputs.jl b/src/core/reopt_inputs.jl index 53173191d..d402b409c 100644 --- a/src/core/reopt_inputs.jl +++ b/src/core/reopt_inputs.jl @@ -313,7 +313,7 @@ function setup_tech_inputs(s::AbstractScenario) pvlocations = [:roof, :ground, :both] d = Dict(loc => 0 for loc in pvlocations) pv_to_location = Dict(t => copy(d) for t in techs.pv) - maxsize_pv_locations = DenseAxisArray([1.0e5, 1.0e5, 1.0e5], pvlocations) + maxsize_pv_locations = DenseAxisArray([1.0e9, 1.0e9, 1.0e9], pvlocations) # default to large max size per location. Max size by roof, ground, both if !isempty(techs.pv) @@ -475,7 +475,6 @@ function setup_pv_inputs(s::AbstractScenario, max_sizes, min_sizes, production_factor[pv.name, :] = get_production_factor(pv, s.site.latitude, s.site.longitude; time_steps_per_hour=s.settings.time_steps_per_hour) for location in pvlocations - if pv.location == String(location) # Must convert symbol to string pv_to_location[pv.name][location] = 1 else From 6f445713d3c5dff05b82c6df9dec37e6175993e3 Mon Sep 17 00:00:00 2001 From: adfarth Date: Mon, 17 Apr 2023 13:35:39 -0600 Subject: [PATCH 04/10] Update CHANGELOG.md --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index db595a72f..71e5f1c64 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,9 @@ Classify the change according to the following categories: ### Deprecated ### Removed +## Develop - 2023-04-17 +### Fixed +- Fixed bug in multiple PVs pv_to_location dictionary creation. ## v0.30.0 ### Added - `Generator` input **fuel_higher_heating_value_kwh_per_gal**, which defaults to the constant KWH_PER_GAL_DIESEL From c6395cb4bf9de00033979aad9cb2aa2444762bea Mon Sep 17 00:00:00 2001 From: hdunham <70401017+hdunham@users.noreply.github.com> Date: Fri, 5 May 2023 14:18:56 -0600 Subject: [PATCH 05/10] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index effef96b3..692e4e7c0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,7 +26,7 @@ Classify the change according to the following categories: ## Develop - 2023-04-17 ### Fixed - Fixed bug in multiple PVs pv_to_location dictionary creation. -## Develop 2023-04-18 + ## v0.32.1 ### Fixed - In `backup_reliability.jl`: From 0a78798b1a15b2101d69bdbed79b941e5ebdd4dc Mon Sep 17 00:00:00 2001 From: zolanaj Date: Sat, 20 May 2023 22:39:38 -0600 Subject: [PATCH 06/10] add `1:` to references to n_energy_tiers, n_tou_demand_tiers in for-loops --- src/constraints/electric_utility_constraints.jl | 2 +- src/results/electric_utility.jl | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/constraints/electric_utility_constraints.jl b/src/constraints/electric_utility_constraints.jl index c6942d542..c4893ef66 100644 --- a/src/constraints/electric_utility_constraints.jl +++ b/src/constraints/electric_utility_constraints.jl @@ -356,7 +356,7 @@ function add_elec_utility_expressions(m, p; _n="") if !isempty(p.s.electric_tariff.tou_demand_rates) m[Symbol("DemandTOUCharges"*_n)] = @expression(m, p.pwf_e * sum( p.s.electric_tariff.tou_demand_rates[r] * m[Symbol("dvPeakDemandTOU"*_n)][r, tier] - for r in p.ratchets, tier in p.s.electric_tariff.n_tou_demand_tiers) + for r in p.ratchets, tier in 1:p.s.electric_tariff.n_tou_demand_tiers) ) else m[Symbol("DemandTOUCharges"*_n)] = 0 diff --git a/src/results/electric_utility.jl b/src/results/electric_utility.jl index 7eb0ef6ee..328de62da 100644 --- a/src/results/electric_utility.jl +++ b/src/results/electric_utility.jl @@ -59,17 +59,17 @@ function add_electric_utility_results(m::JuMP.AbstractModel, p::AbstractInputs, r = Dict{String, Any}() Year1UtilityEnergy = p.hours_per_time_step * sum(m[Symbol("dvGridPurchase"*_n)][ts, tier] - for ts in p.time_steps, tier in p.s.electric_tariff.n_energy_tiers) + for ts in p.time_steps, tier in 1:p.s.electric_tariff.n_energy_tiers) r["annual_energy_supplied_kwh"] = round(value(Year1UtilityEnergy), digits=2) if !isempty(p.s.storage.types.elec) - GridToLoad = (sum(m[Symbol("dvGridPurchase"*_n)][ts, tier] for tier in p.s.electric_tariff.n_energy_tiers) + GridToLoad = (sum(m[Symbol("dvGridPurchase"*_n)][ts, tier] for tier in 1:p.s.electric_tariff.n_energy_tiers) - sum(m[Symbol("dvGridToStorage"*_n)][b, ts] for b in p.s.storage.types.elec) for ts in p.time_steps) GridToBatt = (sum(m[Symbol("dvGridToStorage"*_n)][b, ts] for b in p.s.storage.types.elec) for ts in p.time_steps) else - GridToLoad = (sum(m[Symbol("dvGridPurchase"*_n)][ts, tier] for tier in p.s.electric_tariff.n_energy_tiers) + GridToLoad = (sum(m[Symbol("dvGridPurchase"*_n)][ts, tier] for tier in 1:p.s.electric_tariff.n_energy_tiers) for ts in p.time_steps) GridToBatt = zeros(length(p.time_steps)) end @@ -107,7 +107,7 @@ function add_electric_utility_results(m::JuMP.AbstractModel, p::MPCInputs, d::Di Year1UtilityEnergy = p.hours_per_time_step * sum(m[Symbol("dvGridPurchase"*_n)][ts, tier] for ts in p.time_steps, - tier in p.s.electric_tariff.n_energy_tiers) + tier in 1:p.s.electric_tariff.n_energy_tiers) r["energy_supplied_kwh"] = round(value(Year1UtilityEnergy), digits=2) if p.s.storage.attr["ElectricStorage"].size_kwh > 0 @@ -119,7 +119,7 @@ function add_electric_utility_results(m::JuMP.AbstractModel, p::MPCInputs, d::Di GridToBatt = zeros(length(p.time_steps)) end GridToLoad = @expression(m, [ts in p.time_steps], - sum(m[Symbol("dvGridPurchase"*_n)][ts, tier] for tier in p.s.electric_tariff.n_energy_tiers) - + sum(m[Symbol("dvGridPurchase"*_n)][ts, tier] for tier in 1:p.s.electric_tariff.n_energy_tiers) - GridToBatt[ts] ) r["to_load_series_kw"] = round.(value.(GridToLoad), digits=3).data From d868552dc6eb433a4951f2898d0bfcb932f06548 Mon Sep 17 00:00:00 2001 From: zolanaj Date: Sat, 20 May 2023 22:41:02 -0600 Subject: [PATCH 07/10] add results test to Tiered Energy testset --- test/test_with_xpress.jl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/test_with_xpress.jl b/test/test_with_xpress.jl index 1f5529f71..3189e795c 100644 --- a/test/test_with_xpress.jl +++ b/test/test_with_xpress.jl @@ -566,6 +566,8 @@ end m = Model(optimizer_with_attributes(Xpress.Optimizer, "OUTPUTLOG" => 0)) results = run_reopt(m, "./scenarios/tiered_rate.json") @test results["ElectricTariff"]["year_one_energy_cost_before_tax"] ≈ 2342.88 + @test results["ElectricUtility"]["annual_energy_supplied_kwh"] ≈ 24000.0 atol=0.1 + @test results["ElectricLoad"]["annual_calculated_kwh"] ≈ 24000.0 atol=0.1 end @testset "Lookback Demand Charges" begin From f6d8dc0d6ebeabadfd3c7ffa9dc30714065fdfbb Mon Sep 17 00:00:00 2001 From: Alex Zolan Date: Mon, 22 May 2023 08:22:53 -0600 Subject: [PATCH 08/10] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 692e4e7c0..8690596fb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,6 +26,7 @@ Classify the change according to the following categories: ## Develop - 2023-04-17 ### Fixed - Fixed bug in multiple PVs pv_to_location dictionary creation. +- Fixed bug in reporting of grid purchase results when multiple energy tiers are present. ## v0.32.1 ### Fixed From 1f378ba7d31f0ae3d863caa212875722514ea3b8 Mon Sep 17 00:00:00 2001 From: Alex Zolan Date: Mon, 22 May 2023 09:30:48 -0600 Subject: [PATCH 09/10] Update CHANGELOG.md --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8690596fb..cb2d063fd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,10 +23,11 @@ Classify the change according to the following categories: ### Deprecated ### Removed -## Develop - 2023-04-17 +## Develop - 2023-05-22 ### Fixed - Fixed bug in multiple PVs pv_to_location dictionary creation. - Fixed bug in reporting of grid purchase results when multiple energy tiers are present. +- Fixed bug in TOU demand charge calculation when multiple demand tiers are present. ## v0.32.1 ### Fixed From 4155a22670d8d05a43b7b7b5ca3e71e5122e81b2 Mon Sep 17 00:00:00 2001 From: adfarth Date: Fri, 26 May 2023 12:07:18 -0700 Subject: [PATCH 10/10] Update Changelog and Project.toml with version num --- CHANGELOG.md | 2 +- Project.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cb2d063fd..dce32addd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,7 +23,7 @@ Classify the change according to the following categories: ### Deprecated ### Removed -## Develop - 2023-05-22 +## v0.32.2 ### Fixed - Fixed bug in multiple PVs pv_to_location dictionary creation. - Fixed bug in reporting of grid purchase results when multiple energy tiers are present. diff --git a/Project.toml b/Project.toml index 691553501..64f51da9a 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "REopt" uuid = "d36ad4e8-d74a-4f7a-ace1-eaea049febf6" authors = ["Nick Laws", "Hallie Dunham ", "Bill Becker ", "Bhavesh Rathod ", "Alex Zolan ", "Amanda Farthing "] -version = "0.32.1" +version = "0.32.2" [deps] ArchGDAL = "c9ce4bd3-c3d5-55b8-8973-c0e20141b8c3"