Skip to content

Commit

Permalink
Merge branch 'develop' into multi-solns
Browse files Browse the repository at this point in the history
  • Loading branch information
Bill-Becker committed Jul 27, 2023
2 parents 9cd4a4d + f82349a commit 1059049
Show file tree
Hide file tree
Showing 15 changed files with 52 additions and 40 deletions.
7 changes: 5 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,18 @@ Classify the change according to the following categories:
### Deprecated
### Removed


## Develop - 2023-06-21
## v0.32.4
### Changed
- Consolidated PVWatts API calls to 1 call (previously 3 separate calls existed). API call occurs in `src/core/utils.jl/call_pvwatts_api()`. This function is called for PV in `src/core/production_factor.jl/get_production_factor(PV)` and for GHP in `src/core/scenario.jl`. If GHP and PV are evaluated together, the GHP PVWatts call for ambient temperature is also used to assign the pv.production_factor_series in Scenario.jl so that the PVWatts API does not get called again downstream in `get_production_factor(PV)`.
- In `src/core/utils.jl/call_pvwatts_api()`, updated NSRDB bounds used in PVWatts query (now includes southern New Zealand)
- Updated PV Watts version from v6 to v8. PVWatts V8 updates the weather data to 2020 TMY data from the NREL NSRDB for locations covered by the database. (The NSRDB weather data used in PVWatts V6 is from around 2015.) See other differences at https://developer.nrel.gov/docs/solar/pvwatts/.
- Made PV struct mutable: This allows for assigning pv.production_factor_series when calling PVWatts for GHP, to avoid a extra PVWatts calls later.
- Changed unit test expected values due to update to PVWatts v8, which slightly changed expected PV production factors.
- Changed **fuel_avail_gal** default to 1e9 for on-grid scenarios (same as off-grid)
### Fixed
- Issue with using a leap year with a URDB rate - the URDB rate was creating energy_rate of length 8784 instead of intended 8760
- Don't double add adjustments to urdb rates with non-standard units
- Corrected `Generator` **installed_cost_per_kw** from 500 to 650 if **only_runs_during_grid_outage** is _true_ or 800 if _false_

## v0.32.3
### Fixed
Expand Down
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "REopt"
uuid = "d36ad4e8-d74a-4f7a-ace1-eaea049febf6"
authors = ["Nick Laws", "Hallie Dunham <[email protected]>", "Bill Becker <[email protected]>", "Bhavesh Rathod <[email protected]>", "Alex Zolan <[email protected]>", "Amanda Farthing <[email protected]>"]
version = "0.32.3"
version = "0.32.4"

[deps]
ArchGDAL = "c9ce4bd3-c3d5-55b8-8973-c0e20141b8c3"
Expand Down
12 changes: 6 additions & 6 deletions src/core/generator.jl
Original file line number Diff line number Diff line change
Expand Up @@ -30,19 +30,19 @@
"""
`Generator` is an optional REopt input with the following keys and default values:
```julia
only_runs_during_grid_outage::Bool = true,
existing_kw::Real = 0,
min_kw::Real = 0,
max_kw::Real = 1.0e6,
installed_cost_per_kw::Real = 500.0,
installed_cost_per_kw::Real = only_runs_during_grid_outage ? 650.0 : 800.0,
om_cost_per_kw::Real = off_grid_flag ? 20.0 : 10.0,
om_cost_per_kwh::Real = 0.0,
fuel_cost_per_gallon::Real = 3.0,
electric_efficiency_full_load::Real = 0.3233,
electric_efficiency_half_load::Real = electric_efficiency_full_load,
fuel_avail_gal::Real = off_grid_flag ? 1.0e9 : 660.0,
fuel_avail_gal::Real = 1.0e9,
fuel_higher_heating_value_kwh_per_gal::Real = 40.7,
min_turn_down_fraction::Real = off_grid_flag ? 0.15 : 0.0,
only_runs_during_grid_outage::Bool = true,
sells_energy_back_to_grid::Bool = false,
can_net_meter::Bool = false,
can_wholesale::Bool = false,
Expand Down Expand Up @@ -125,19 +125,19 @@ struct Generator <: AbstractGenerator
function Generator(;
off_grid_flag::Bool = false,
analysis_years::Int = 25,
only_runs_during_grid_outage::Bool = true,
existing_kw::Real = 0,
min_kw::Real = 0,
max_kw::Real = 1.0e6,
installed_cost_per_kw::Real = 500.0,
installed_cost_per_kw::Real = only_runs_during_grid_outage ? 650.0 : 800.0,
om_cost_per_kw::Real= off_grid_flag ? 20.0 : 10.0,
om_cost_per_kwh::Real = 0.0,
fuel_cost_per_gallon::Real = 3.0,
electric_efficiency_full_load::Real = 0.3233,
electric_efficiency_half_load::Real = electric_efficiency_full_load,
fuel_avail_gal::Real = off_grid_flag ? 1.0e9 : 660.0,
fuel_avail_gal::Real = 1.0e9,
fuel_higher_heating_value_kwh_per_gal::Real = KWH_PER_GAL_DIESEL,
min_turn_down_fraction::Real = off_grid_flag ? 0.15 : 0.0,
only_runs_during_grid_outage::Bool = true,
sells_energy_back_to_grid::Bool = false,
can_net_meter::Bool = false,
can_wholesale::Bool = false,
Expand Down
12 changes: 5 additions & 7 deletions src/core/urdb.jl
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ function URDBrate(urdb_response::Dict, year::Int; time_steps_per_hour=1)
n_monthly_demand_tiers, monthly_demand_tier_limits, monthly_demand_rates,
n_tou_demand_tiers, tou_demand_tier_limits, tou_demand_rates, tou_demand_ratchet_time_steps =
parse_demand_rates(urdb_response, year, time_steps_per_hour=time_steps_per_hour)

energy_rates, energy_tier_limits, n_energy_tiers, sell_rates =
parse_urdb_energy_costs(urdb_response, year; time_steps_per_hour=time_steps_per_hour)

Expand Down Expand Up @@ -293,12 +293,10 @@ function parse_urdb_energy_costs(d::Dict, year::Int; time_steps_per_hour=1, bigM
else
tier_use = tier
end
if non_kwh_units
rate = rate_average
else
rate = get(d["energyratestructure"][period][tier_use], "rate", 0)
end
total_rate = rate + get(d["energyratestructure"][period][tier_use], "adj", 0)
total_rate = non_kwh_units ?
rate_average :
(get(d["energyratestructure"][period][tier_use], "rate", 0) +
get(d["energyratestructure"][period][tier_use], "adj", 0))
sell = get(d["energyratestructure"][period][tier_use], "sell", 0)

for step in range(1, stop=time_steps_per_hour) # repeat hourly rates intrahour
Expand Down
4 changes: 2 additions & 2 deletions src/mpc/structs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,7 @@ function MPCGenerator(;
fuel_cost_per_gallon::Real = 3.0,
electric_efficiency_full_load::Real = 0.3233,
electric_efficiency_half_load::Real = electric_efficiency_full_load,
fuel_avail_gal::Real = 660.0,
fuel_avail_gal::Real = 1.0e9,
fuel_higher_heating_value_kwh_per_gal::Real = KWH_PER_GAL_DIESEL,
min_turn_down_fraction::Real = 0.0, # TODO change this to non-zero value
only_runs_during_grid_outage::Bool = true,
Expand All @@ -310,7 +310,7 @@ struct MPCGenerator <: AbstractGenerator
fuel_cost_per_gallon::Real = 3.0,
electric_efficiency_full_load::Real = 0.3233,
electric_efficiency_half_load::Real = electric_efficiency_full_load,
fuel_avail_gal::Real = 660.0,
fuel_avail_gal::Real = 1.0e9,
fuel_higher_heating_value_kwh_per_gal::Real = KWH_PER_GAL_DIESEL,
min_turn_down_fraction::Real = 0.0, # TODO change this to non-zero value
only_runs_during_grid_outage::Bool = true,
Expand Down
6 changes: 3 additions & 3 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ else # run HiGHS tests
results = run_reopt(model, inputs)

@test results["PV"]["size_kw"] β‰ˆ 68.9323 atol=0.01
@test results["Financial"]["lcc"] β‰ˆ 432672.0 rtol=1e-5 # with levelization_factor hack the LCC is within 5e-5 of REopt API LCC
@test results["Financial"]["lcc"] β‰ˆ 432681.26 rtol=1e-5 # with levelization_factor hack the LCC is within 5e-5 of REopt API LCC
@test all(x == 0.0 for x in results["PV"]["electric_to_load_series_kw"][1:744])
end

Expand All @@ -98,7 +98,7 @@ else # run HiGHS tests
r = run_reopt(model, "./scenarios/pv_storage.json")

@test r["PV"]["size_kw"] β‰ˆ 216.6667 atol=0.01
@test r["Financial"]["lcc"] β‰ˆ 1.239151e7 rtol=1e-5
@test r["Financial"]["lcc"] β‰ˆ 1.2391786e7 rtol=1e-5
@test r["ElectricStorage"]["size_kw"] β‰ˆ 49.0 atol=0.1
@test r["ElectricStorage"]["size_kwh"] β‰ˆ 83.3 atol=0.1
end
Expand All @@ -108,7 +108,7 @@ else # run HiGHS tests
"output_flag" => false, "log_to_console" => false)
)
results = run_reopt(model, "./scenarios/generator.json")
@test results["Generator"]["size_kw"] β‰ˆ 9.53 atol=0.01
@test results["Generator"]["size_kw"] β‰ˆ 9.55 atol=0.01
@test (sum(results["Generator"]["electric_to_load_series_kw"][i] for i in 1:9) +
sum(results["Generator"]["electric_to_load_series_kw"][i] for i in 13:8760)) == 0
p = REoptInputs("./scenarios/generator.json")
Expand Down
2 changes: 2 additions & 0 deletions test/scenarios/backup_reliability_reopt_inputs.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
"federal_rebate_per_kw": 350.0
},
"Generator": {
"installed_cost_per_kw": 500.0,
"fuel_avail_gal": 660,
"min_kw": 200,
"max_kw": 200
},
Expand Down
1 change: 1 addition & 0 deletions test/scenarios/emissions.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
"outage_durations": [10]
},
"Generator": {
"installed_cost_per_kw": 500.0,
"max_kw": 500.0,
"fuel_avail_gal": 125.0,
"min_turn_down_fraction": 0.0,
Expand Down
1 change: 1 addition & 0 deletions test/scenarios/generator.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"outage_end_time_step": 12
},
"Generator": {
"installed_cost_per_kw": 500.0,
"max_kw": 500.0,
"fuel_avail_gal": 125.0,
"min_turn_down_fraction": 0.0,
Expand Down
1 change: 1 addition & 0 deletions test/scenarios/mpc.json
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@
0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05, 0.05]
},
"Generator": {
"fuel_avail_gal": 660,
"size_kw": 30,
"only_runs_during_grid_outage": false
},
Expand Down
2 changes: 2 additions & 0 deletions test/scenarios/nogridcost_minresilhours.json
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@
"critical_load_fraction": 1
},
"Generator": {
"fuel_avail_gal": 660,
"installed_cost_per_kw": 500.0
},
"Financial": {
"value_of_lost_load_per_kwh": 0.001,
Expand Down
2 changes: 2 additions & 0 deletions test/scenarios/nogridcost_multiscenario.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@
"critical_load_fraction": 0.1
},
"Generator": {
"fuel_avail_gal": 660,
"installed_cost_per_kw": 500.0,
"max_kw": 0.0
},
"Financial": {
Expand Down
2 changes: 2 additions & 0 deletions test/scenarios/outage.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
"outage_durations": [10]
},
"Generator": {
"fuel_avail_gal": 660,
"installed_cost_per_kw": 500.0,
"existing_kw": 0.0,
"min_turn_down_fraction": 0.0,
"only_runs_during_grid_outage": true,
Expand Down
2 changes: 1 addition & 1 deletion test/test_with_cplex.jl
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ end
REoptInputs("./scenarios/monthly_rate.json"),
];
results = run_reopt(m, ps)
@test results[3]["Financial"]["lcc"] + results[10]["Financial"]["lcc"] β‰ˆ 1.2830591384e7 rtol=1e-5
@test results[3]["Financial"]["lcc"] + results[10]["Financial"]["lcc"] β‰ˆ 1.2830872235e7 rtol=1e-5
end


Expand Down
36 changes: 18 additions & 18 deletions test/test_with_xpress.jl
Original file line number Diff line number Diff line change
Expand Up @@ -429,7 +429,7 @@ end

@test results["PV"]["size_kw"] β‰ˆ 216.6667 atol=0.01
@test results["PV"]["lcoe_per_kwh"] β‰ˆ 0.0468 atol = 0.001
@test results["Financial"]["lcc"] β‰ˆ 1.239151e7 rtol=1e-5
@test results["Financial"]["lcc"] β‰ˆ 1.239179e7 rtol=1e-5
@test results["Financial"]["lcc_bau"] β‰ˆ 12766397 rtol=1e-5
@test results["ElectricStorage"]["size_kw"] β‰ˆ 49.02 atol=0.1
@test results["ElectricStorage"]["size_kwh"] β‰ˆ 83.3 atol=0.1
Expand Down Expand Up @@ -472,7 +472,7 @@ end
m2 = Model(optimizer_with_attributes(Xpress.Optimizer, "OUTPUTLOG" => 0))
p = REoptInputs("./scenarios/generator.json")
results = run_reopt([m1,m2], p)
@test results["Generator"]["size_kw"] β‰ˆ 9.53 atol=0.01
@test results["Generator"]["size_kw"] β‰ˆ 9.55 atol=0.01
@test (sum(results["Generator"]["electric_to_load_series_kw"][i] for i in 1:9) +
sum(results["Generator"]["electric_to_load_series_kw"][i] for i in 13:8760)) == 0
@test results["ElectricLoad"]["bau_critical_load_met"] == false
Expand Down Expand Up @@ -513,16 +513,16 @@ end
# Scenario with generator, PV, electric storage
m = Model(optimizer_with_attributes(Xpress.Optimizer, "OUTPUTLOG" => 0))
results = run_reopt(m, "./scenarios/outages_gen_pv_stor.json")
@test results["Outages"]["expected_outage_cost"] β‰ˆ 3.5478948132891157e6 atol=10
@test results["Financial"]["lcc"] β‰ˆ 8.64478971865e7 atol=100
@test results["Outages"]["expected_outage_cost"] β‰ˆ 3.54476923e6 atol=10
@test results["Financial"]["lcc"] β‰ˆ 8.6413594727e7 atol=100

# Scenario with generator, PV, wind, electric storage
m = Model(optimizer_with_attributes(Xpress.Optimizer, "OUTPUTLOG" => 0))
results = run_reopt(m, "./scenarios/outages_gen_pv_wind_stor.json")
@test value(m[:binMGTechUsed]["Generator"]) β‰ˆ 1
@test value(m[:binMGTechUsed]["PV"]) β‰ˆ 1
@test value(m[:binMGTechUsed]["Wind"]) β‰ˆ 1
@test results["Outages"]["expected_outage_cost"] β‰ˆ 430157.43 atol=1.0
@test results["Outages"]["expected_outage_cost"] β‰ˆ 446899.75 atol=1.0
@test results["Financial"]["lcc"] β‰ˆ 6.71661825335e7 rtol=0.001
end

Expand All @@ -533,7 +533,7 @@ end
REoptInputs("./scenarios/monthly_rate.json"),
];
results = run_reopt(m, ps)
@test results[3]["Financial"]["lcc"] + results[10]["Financial"]["lcc"] β‰ˆ 1.2830591384e7 rtol=1e-5
@test results[3]["Financial"]["lcc"] + results[10]["Financial"]["lcc"] β‰ˆ 1.2830872235e7 rtol=1e-5
end

@testset "MPC" begin
Expand Down Expand Up @@ -707,9 +707,9 @@ end
@test roof_east["size_kw"] β‰ˆ 4 atol=0.1
@test ground_pv["lifecycle_om_cost_after_tax_bau"] β‰ˆ 782.0 atol=0.1
@test roof_west["lifecycle_om_cost_after_tax_bau"] β‰ˆ 782.0 atol=0.1
@test ground_pv["annual_energy_produced_kwh_bau"] β‰ˆ 8912.06 atol=0.1
@test ground_pv["annual_energy_produced_kwh_bau"] β‰ˆ 8933.09 atol=0.1
@test roof_west["annual_energy_produced_kwh_bau"] β‰ˆ 7656.11 atol=0.1
@test ground_pv["annual_energy_produced_kwh"] β‰ˆ 26735.22 atol=0.1
@test ground_pv["annual_energy_produced_kwh"] β‰ˆ 26799.26 atol=0.1
@test roof_west["annual_energy_produced_kwh"] β‰ˆ 10719.51 atol=0.1
@test roof_east["annual_energy_produced_kwh"] β‰ˆ 6685.95 atol=0.1
end
Expand Down Expand Up @@ -1313,25 +1313,25 @@ end
@test (expected_npv - results["Financial"]["npv"])/expected_npv β‰ˆ 0.0 atol=1e-2
@test results["Site"]["annual_renewable_electricity_kwh"] β‰ˆ 76412.02
@test results["Site"]["renewable_electricity_fraction"] β‰ˆ 0.8
@test results["Site"]["renewable_electricity_fraction_bau"] β‰ˆ 0.147698 atol=1e-4
@test results["Site"]["renewable_electricity_fraction_bau"] β‰ˆ 0.147576 atol=1e-4
@test results["Site"]["total_renewable_energy_fraction"] β‰ˆ 0.8
@test results["Site"]["total_renewable_energy_fraction_bau"] β‰ˆ 0.147698 atol=1e-4
@test results["Site"]["total_renewable_energy_fraction_bau"] β‰ˆ 0.147576 atol=1e-4
@test results["Site"]["lifecycle_emissions_reduction_CO2_fraction"] β‰ˆ 0.616639 atol=1e-4
@test results["Financial"]["breakeven_cost_of_emissions_reduction_per_tonne_CO2"] β‰ˆ 281.6 atol=1
@test results["Site"]["annual_emissions_tonnes_CO2"] β‰ˆ 11.38 atol=1e-2
@test results["Site"]["annual_emissions_tonnes_CO2_bau"] β‰ˆ 32.06 atol=1e-2
@test results["Site"]["annual_emissions_from_fuelburn_tonnes_CO2"] β‰ˆ 7.04
@test results["Site"]["annual_emissions_from_fuelburn_tonnes_CO2_bau"] β‰ˆ 0.0
@test results["Financial"]["lifecycle_emissions_cost_climate"] β‰ˆ 7767.6 atol=1
@test results["Financial"]["lifecycle_emissions_cost_climate_bau"] β‰ˆ 20447.72 atol=1e-1
@test results["Financial"]["lifecycle_emissions_cost_climate_bau"] β‰ˆ 20450.62 atol=1e-1
@test results["Site"]["lifecycle_emissions_tonnes_CO2"] β‰ˆ 217.63
@test results["Site"]["lifecycle_emissions_tonnes_CO2_bau"] β‰ˆ 567.69
@test results["Site"]["lifecycle_emissions_from_fuelburn_tonnes_CO2"] β‰ˆ 140.75
@test results["Site"]["lifecycle_emissions_tonnes_CO2_bau"] β‰ˆ 567.77
@test results["Site"]["lifecycle_emissions_from_fuelburn_tonnes_CO2"] β‰ˆ 140.78
@test results["Site"]["lifecycle_emissions_from_fuelburn_tonnes_CO2_bau"] β‰ˆ 0.0
@test results["ElectricUtility"]["annual_emissions_tonnes_CO2"] β‰ˆ 4.34
@test results["ElectricUtility"]["annual_emissions_tonnes_CO2_bau"] β‰ˆ 32.06
@test results["ElectricUtility"]["lifecycle_emissions_tonnes_CO2"] β‰ˆ 76.88
@test results["ElectricUtility"]["lifecycle_emissions_tonnes_CO2_bau"] β‰ˆ 567.69
@test results["ElectricUtility"]["lifecycle_emissions_tonnes_CO2"] β‰ˆ 76.86
@test results["ElectricUtility"]["lifecycle_emissions_tonnes_CO2_bau"] β‰ˆ 567.77
elseif i == 2
#commented out values are results using same levelization factor as API
@test results["PV"]["size_kw"] β‰ˆ 106.13 atol=1
Expand All @@ -1351,13 +1351,13 @@ end
@test results["Site"]["total_renewable_energy_fraction_bau"] β‰ˆ 0.132118 atol=1e-3 # 0.1354 atol=1e-3
# CO2 emissions - totals β‰ˆ from grid, from fuelburn, ER, $/tCO2 breakeven
@test results["Site"]["lifecycle_emissions_reduction_CO2_fraction"] β‰ˆ 0.8 atol=1e-3 # 0.8
@test results["Financial"]["breakeven_cost_of_emissions_reduction_per_tonne_CO2"] β‰ˆ 374.242 atol=1e-1
@test results["Financial"]["breakeven_cost_of_emissions_reduction_per_tonne_CO2"] β‰ˆ 374.02125 atol=1e-1
@test results["Site"]["annual_emissions_tonnes_CO2"] β‰ˆ 14.2 atol=1
@test results["Site"]["annual_emissions_tonnes_CO2_bau"] β‰ˆ 70.99 atol=1
@test results["Site"]["annual_emissions_from_fuelburn_tonnes_CO2"] β‰ˆ 0.0 atol=1 # 0.0
@test results["Site"]["annual_emissions_from_fuelburn_tonnes_CO2_bau"] β‰ˆ 0.0 atol=1 # 0.0
@test results["Financial"]["lifecycle_emissions_cost_climate"] β‰ˆ 9110.21 atol=1
@test results["Financial"]["lifecycle_emissions_cost_climate_bau"] β‰ˆ 45551.06 atol=1
@test results["Financial"]["lifecycle_emissions_cost_climate_bau"] β‰ˆ 45546.55 atol=1
@test results["Site"]["lifecycle_emissions_tonnes_CO2"] β‰ˆ 252.92 atol=1
@test results["Site"]["lifecycle_emissions_tonnes_CO2_bau"] β‰ˆ 1264.62 atol=1
@test results["Site"]["lifecycle_emissions_from_fuelburn_tonnes_CO2"] β‰ˆ 0.0 atol=1 # 0.0
Expand Down Expand Up @@ -1674,4 +1674,4 @@ end
@test "warnings" ∈ keys(r["Messages"])
@test length(r["Messages"]["errors"]) > 0
@test length(r["Messages"]["warnings"]) > 0
end
end

0 comments on commit 1059049

Please sign in to comment.