Skip to content

Commit

Permalink
Merge branch 'develop' into ev
Browse files Browse the repository at this point in the history
  • Loading branch information
Bill-Becker committed Feb 25, 2023
2 parents 71c3cc1 + c8bbeac commit f885baf
Show file tree
Hide file tree
Showing 35 changed files with 429 additions and 282 deletions.
123 changes: 94 additions & 29 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,45 @@ Classify the change according to the following categories:
### Deprecated
### Removed

## dev
## Develop - 2023-02-02
### Added
- Constraint on wind sizing based on Site.land_acres
- New Wind input **acres_per_kw**, defaults to 0.03

### Changed
- Changed default **year** in ElectricLoad to be 2017 if using a CRB model and 2022 otherwise.
- Removed default year in URDBrate() functions, since year is always supplied to this function.
## Develop
### Fixed
- Fixed calculation of ["Financial"]["lifecycle_om_costs_before_tax_bau"] (was previously showing after tax result)
- Added **bau_annual_emissions_tonnes_SO2** to the bau_outputs dict in results.jl and removed duplicate **bau_annual_emissions_tonnes_NOx** result
### Added
- Descriptions/help text for many inputs and outputs

## Develop - 2023-02-01
## v0.25.0
### Added
- multi-node MPC modeling capability
- more MPC outputs (e.g. Costs, ElectricStorage.to_load_series_kw)
- throw error if outage_durations and outage_probabilities not the same length
- throw error if length of outage_probabilities is >= 1 and sum of outage_probabilities is not equal to 1
- small incentive to minimize unserved load in each outage, not just the max over outage start times (makes expected outage results more realist and fixes same inputs giving different results)
- add `Outages` output **generator_fuel_used_per_outage** which is the sum over backup generators
### Changed
- remove _series from non-timeseries outage output names
- make the use of _ in multiple outages output names consistent
- updates multiple outage test values that changed due to fixing timestep bug
- Updated the following default values:
- PV, Wind, Storage, CHP, GHP, Hot Water Storage, Cold Water Storage, Electric Storage: **federal_itc_fraction(PV,Wind, CHP,GHP)** and **total_itc_fraction(Hot Water Storage, Cold Water Storage, Electric Storage)** to 0.3 (30%)
- PV, Wind, Storage, CHP, GHP, Hot Water Storage, Cold Water Storage, Electric Storage: **macrs_bonus_fraction** to 0.8 (80%)
- Hot Water Storage and Cold Water Storage: **macrs_itc_reduction** to 0.5 (50%)
- Hot Water Storage and Cold Water Storage: **macrs_option_years** to 7 years
### Fixed
- PV results for all multi-node scenarios
- MPC objective definition w/o ElectricStorage
- fixed mulitple outages timestep off-by-one bug
### Removed
- Wind ITC no longer determined based on size class. Removed all size class dependencies from wind.jl

## v0.24.0
### Changed
Expand Down Expand Up @@ -151,108 +183,137 @@ The following name changes were made:
- Bug fix to report accurate wind ["year_one_to_load_series_kw"] in results/wind.jl (was previously not accounting for curtailed wind)

## v0.16.2
### Changed
- Update PV defaults to tilt=10 for rooftop, tilt = abs(lat) for ground mount, azimuth = 180 for northern lats, azimuth = 0 for southern lats.
### Fixed
- bug fix for Generator inputs to allow for time_steps_per_hour > 1
- change various `Float64` types to `Real` to allow integers too

## v0.16.1
### Fixed
- bug fix for outage simulator when `microgrid_only=true`

## v0.16.0
### Added
Allows users to model "off-grid" systems as a year-long outage:
- add flag to "turn on" off-grid modeling `Settings.off_grid_flag`
- when `off_grid_flag` is "true", adjust default values in core/ `electric_storage`, `electric_load`, `financial`, `generator`, `pv`
- add operating reserve requirement inputs, outputs, and constraints based on load and PV generation
- add minimum load met percent input and constraint
- add generator replacement year and cost (for off-grid and on-grid)
- add off-grid additional annual costs (tax deductible) and upfront capital costs (depreciable via straight line depreciation)

### Changed
Name changes:
- consistently append `_before_tax` and `_after_tax` to results names
- change all instances of `timestep` to `time_step` and `timesteps` to `time_steps`

Other changes:
- report previously missing lcc breakdown components, all reported in `results/financial.jl`
- change variable types from Float to Real to allow users to enter Ints (where applicable)
- `year_one_coincident_peak_cost_after_tax` is now correctly multiplied by `(1 - p.s.financial.offtaker_tax_pct)`

## v0.15.2
### Fixed
- bug fix for 15 & 30 minute electric, heating, and cooling loads
- bug fix for URDB fixed charges
- bug fix for default `Wind` `installed_cost_per_kw` and `federal_itc_pct`

## v0.15.1
### Added
- add `AbsorptionChiller` technology
- add `ElectricStorage.minimum_avg_soc_fraction` input and constraint

## v0.15.0
### Fixed
- bug fix in outage_simulator
### Changed
- allow Real Generator inputs (not just Float64)
- add "_series" to "Outages" outputs that are arrays [breaking]

## v0.14.0
### Changed
- update default values from v2 of API [breaking]
### Added
- add ElectricStorage degradation accounting and maintenance strategies
- finish cooling loads

## v0.13.0
- fix bugs for time_steps_per_hour != 1
### Added
- add FlexibleHVAC model (still testing)
- start thermal energy storage modeling
- refactor `Storage` as `ElectricStorage`
- add `ExistingBoiler` and `ExistingChiller`
- add `MPCLimits` inputs:
- `grid_draw_limit_kw_by_time_step`
- `export_limit_kw_by_time_step`
### Changed
- refactor `Storage` as `ElectricStorage`
### Fixed
- fix bugs for time_steps_per_hour != 1


## v0.12.4
### Removed
- rm "Lite" from docs
### Changed
- prioritize `urdb_response` over `urdb_label` in `ElectricTariff`

## v0.12.3
### Added
- add utils for PVwatts: `get_ambient_temperature` and `get_pvwatts_prodfactor`

## v0.12.2
### Added
- add CHP technology, including supplementary firing
- add URDB "sell" value from `energyratestructure` to wholesale rate
- update docs
### Changed
- allow annual or monthly energy rate w/o demand rate
- allow integer latitude/longitude

## v0.12.1
### Added
- add ExistingBoiler and CRB heating loads

## v0.12.0
### Changed
- change all output keys starting with "total_" or "net_" to "lifecycle_" (except "net_present_cost")
- bug fix in urdb.jl when rate_name not found
- update pv results for single PV in an array
### Fixed
- bug fix in urdb.jl when rate_name not found

## v0.11.0
### Added
- add ElectricLoad.blended_doe_reference_names & blended_doe_reference_percents
- add ElectricLoad.monthly_totals_kwh builtin profile scaling
- add ElectricTariff inputs: `add_monthly_rates_to_urdb_rate`, `tou_energy_rates_per_kwh`,
`add_tou_energy_rates_to_urdb_rate`, `coincident_peak_load_charge_per_kw`, `coincident_peak_load_active_time_steps`
### Fixed
- handle multiple PV outputs

## v0.10.0
### Added
- add modeling capability for tiered rates (energy, TOU demand, and monthly demand charges)
- all of these tiered rates require binaries, which are conditionally added to the model
- add modeling capability for lookback demand charges
- removed "_us_dollars" from all names and generally aligned names with API
- add more outputs from the API (eg. `initial_capital_costs`)
- add option to run Business As Usual scenario in parallel with optimal scenario (default is `true`)
- add incentives (and cost curves) to `Wind` and `Generator`
- fixed bug in URDB fixed charges
### Changed
- removed "_us_dollars" from all names and generally aligned names with API
- renamed `outage_start(end)_time_step` to `outage_start(end)_time_step`
### Fixed
- fixed bug in URDB fixed charges

## v0.9.0
### Changed
- `ElectricTariff.NEM` boolean is now determined by `ElectricUtility.net_metering_limit_kw` (true if limit > 0)
### Added
- add `ElectricUtility` inputs for `net_metering_limit_kw` and `interconnection_limit_kw`
- add binary choice for net metering vs. wholesale export
- add `ElectricTariff.export_rate_beyond_net_metering_limit` input (scalar or vector allowed)
- add `can_net_meter`, `can_wholesale`, `can_export_beyond_nem_limit` tech inputs (`PV`, `Wind`, `Generator`)

## v0.8.0
### Added
- add `Wind` module, relying on System Advisor Model Wind module for production factors and Wind Toolkit for resource data
- new `ElectricTariff` input options:
- `urdb_utility_name` and `urdb_rate_name`
Expand All @@ -261,73 +322,76 @@ Other changes:
- tax, production, and capacity incentives for PV (compatible with any energy generation technology)
- technology cost curve modeling capability
- both of these capabilities are only used for the technologies that require them (based on input values), unlike the API which always models these capabilities (and therefore always includes the binary variables).
- Three new tests: Wind, Blended Tariff and Complex Incentives (which aligns with API results)
### Changed
- `cost_per_kw[h]` input fields are now `installed_cost_per_kw[h]` to distinguish it from other costs like `om_cost_per_kw[h]`
- Financial input field refactored: `two_party_ownership` -> `third_party_ownership`
- `total_itc_pct` -> `federal_itc_pct` on technology inputs
- Three new tests: Wind, Blended Tariff and Complex Incentives (which aligns with API results)

## v0.7.3
##### bug fixes
### Fixed
- outage results processing would fail sometimes when an integer variable was not exact (e.g. 1.000000001)
- fixed `simulate_outages` for revised results formats (key names changed to align with the REopt API)

## v0.7.2
#### Improvements
### Added
- add PV.production_factor_series input (can skip PVWatts call)
- add `run_mpc` capability, which dispatches DER for minimum energy cost over an arbitrary time horizon

## v0.7.1
##### bug fixes
### Fixed
- ElectricLoad.city default is empty string, must be filled in before annual_kwh look up

## v0.7.0
#### Improvements
### Removed
- removed Storage.can_grid_export
### Added
- add optional integer constraint to prevent simultaneous export and import of power
- add warnings when adding integer variables
- add ability to add LinDistFlow constraints to multinode models
### Changed
- no longer require `ElectricLoad.city` input (look up ASHRAE climate zone from lat/lon)
- compatible with Julia 1.6

## v0.6.0
#### Improvements
### Added
- add multi-node (site) capability for PV and Storage
- started documentation process using Github Pages and Documenter.jl
### Changed
- restructured outputs to align with the input structure, for example top-level keys added for `ElectricTariff` and `PV` in the outputs

## v0.5.3
#### Improvements
### Changed
- compatible with Julia 1.5

## v0.5.2
#### bug fixes
### Fixed
- outage_simulator.jl had bug with summing over empty `Any[]`

#### Improvements
### Added
- add optional `microgrid_only` arg to simulate_outages

## v0.5.1
#### Improvements
### Added
- added outage dispatch outputs and speed up their derivation
### Removed
- removed redundant generator minimum turn down constraint

## v0.5.0
#### bug fixes
### Fixed
- handle missing input key for `year_one_soc_series_pct` in `outage_simulator`
- remove erroneous `total_unserved_load = 0` output
- `dvUnservedLoad` definition was allowing microgrid production to storage and curtailment to be double counted towards meeting critical load

#### Improvements
#### Added
- add `unserved_load_per_outage` output

## v0.4.1
#### bug fixes
### Fixed
- removed `total_unserved_load` output because it can take hours to generate and can error out when outage indices are not consecutive
#### Improvements
### Added
- add @info for time spent processing results

## v0.4.0
#### Improvements
### Added
- add `simulate_outages` function (similar to REopt API outage simulator)
- removed MutableArithmetics package from Project.toml (since JuMP now has method for `value(::MutableArithmetics.Zero)`)
- add outage related outputs:
Expand All @@ -338,27 +402,28 @@ Other changes:
- mg_storage_upgrade_cost
- dvUnservedLoad array
- max_outage_cost_per_outage_duration
### Changed
- allow value_of_lost_load_per_kwh values to be subtype of Real (rather than only Real)
- add `run_reopt` method for scenario Dict

## v0.3.0
#### Improvements
### Added
- add separate decision variables and constraints for microgrid tech capacities
- new Site input `mg_tech_sizes_equal_grid_sizes` (boolean), when `false` the microgrid tech capacities are constrained to be <= the grid connected tech capacities
#### bug fixes
### Fixed
- allow non-integer `outage_probabilities`
- correct `total_unserved_load` output
- don't `add_min_hours_crit_ld_met_constraint` unless `min_resil_time_steps <= length(elecutil.outage_time_steps)`

## v0.2.0
#### Improvements
### Added
- add support for custom ElectricLoad `loads_kw` input
- include existing capacity in microgrid upgrade cost
- previously only had to pay to upgrade new capacity
- implement ElectricLoad `loads_kw_is_net` and `critical_loads_kw_is_net`
- add existing PV production to raw load profile if `true`
- add `min_resil_time_steps` input and optional constraint for minimum time_steps that critical load must be met in every outage
#### bug fixes
### Fixed
- enforce storage cannot grid charge

## v0.1.1 Fix build.jl
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.24.0"
version = "0.25.0"

[deps]
ArchGDAL = "c9ce4bd3-c3d5-55b8-8973-c0e20141b8c3"
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# REopt Julia package
This package is currently under development, but it now has **most** of capabilities of the REopt model used in the [REopt API](https://github.com/NREL/REopt_API). We expect to have the first stable release by Fall 2022.
This package is currently under development, but it now has all of the capabilities of the REopt model used in the [REopt API](https://github.com/NREL/REopt_API). We expect to have the first stable release by Summer 2023.

For more information please see the documentation:
<!-- [![](https://img.shields.io/badge/docs-stable-blue.svg)](https://nrel.github.io/REopt.jl/stable) -->
Expand Down
2 changes: 1 addition & 1 deletion docs/src/developer/inputs.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ The set maps are best explained with an example. The `techs_by_exportbin` map us
1. `:NEM` (Net Energy Metering)
2. `:WHL` (Wholesale)
3. `:EXC` (Excess, beyond NEM))
The bins that a technolgy can access are determined by the technologies attributes `can_net_meter`, `can_wholesale`, and `can_export_beyond_nem_limit`. So if `PV.can_net_meter = true`, `Wind.can_net_meter = true` and all the other attributes are `false` then the `techs_by_exportbin` will only have one non-empty key:
The bins that a technology can access are determined by the technologies attributes `can_net_meter`, `can_wholesale`, and `can_export_beyond_nem_limit`. So if `PV.can_net_meter = true`, `Wind.can_net_meter = true` and all the other attributes are `false` then the `techs_by_exportbin` will only have one non-empty key:
```julia
techs_by_exportbin = Dict(
:NEM => ["PV", "Wind"],
Expand Down
10 changes: 5 additions & 5 deletions src/constraints/outage_constraints.jl
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@
function add_dv_UnservedLoad_constraints(m,p)
# effective load balance (with slack in dvUnservedLoad)
@constraint(m, [s in p.s.electric_utility.scenarios, tz in p.s.electric_utility.outage_start_time_steps, ts in p.s.electric_utility.outage_time_steps],
m[:dvUnservedLoad][s, tz, ts] >= p.s.electric_load.critical_loads_kw[tz+ts]
- sum( m[:dvMGRatedProduction][t, s, tz, ts] * p.production_factor[t, tz+ts] * p.levelization_factor[t]
m[:dvUnservedLoad][s, tz, ts] >= p.s.electric_load.critical_loads_kw[tz+ts-1]
- sum( m[:dvMGRatedProduction][t, s, tz, ts] * p.production_factor[t, tz+ts-1] * p.levelization_factor[t]
- m[:dvMGProductionToStorage][t, s, tz, ts] - m[:dvMGCurtail][t, s, tz, ts]
for t in p.techs.elec
)
Expand All @@ -50,7 +50,7 @@ end

function add_outage_cost_constraints(m,p)
@constraint(m, [s in p.s.electric_utility.scenarios, tz in p.s.electric_utility.outage_start_time_steps],
m[:dvMaxOutageCost][s] >= p.pwf_e * sum(p.value_of_lost_load_per_kwh[tz+ts] * m[:dvUnservedLoad][s, tz, ts] for ts in 1:p.s.electric_utility.outage_durations[s])
m[:dvMaxOutageCost][s] >= p.pwf_e * sum(p.value_of_lost_load_per_kwh[tz+ts-1] * m[:dvUnservedLoad][s, tz, ts] for ts in 1:p.s.electric_utility.outage_durations[s])
)

@expression(m, ExpectedOutageCost,
Expand Down Expand Up @@ -98,7 +98,7 @@ function add_MG_production_constraints(m,p)
# Electrical production sent to storage or export must be less than technology's rated production
@constraint(m, [t in p.techs.elec, s in p.s.electric_utility.scenarios, tz in p.s.electric_utility.outage_start_time_steps, ts in p.s.electric_utility.outage_time_steps],
m[:dvMGProductionToStorage][t, s, tz, ts] + m[:dvMGCurtail][t, s, tz, ts] <=
p.production_factor[t, tz+ts] * p.levelization_factor[t] * m[:dvMGRatedProduction][t, s, tz, ts]
p.production_factor[t, tz+ts-1] * p.levelization_factor[t] * m[:dvMGRatedProduction][t, s, tz, ts]
)

@constraint(m, [t in p.techs.elec, s in p.s.electric_utility.scenarios, tz in p.s.electric_utility.outage_start_time_steps, ts in p.s.electric_utility.outage_time_steps],
Expand All @@ -115,7 +115,7 @@ function add_MG_fuel_burn_constraints(m,p)
# Define dvMGFuelUsed by summing over outage time_steps.
@constraint(m, [t in p.techs.gen, s in p.s.electric_utility.scenarios, tz in p.s.electric_utility.outage_start_time_steps],
m[:dvMGFuelUsed][t, s, tz] == p.s.generator.fuel_slope_gal_per_kwh * p.hours_per_time_step * p.levelization_factor[t] *
sum( p.production_factor[t, tz+ts] * m[:dvMGRatedProduction][t, s, tz, ts] for ts in 1:p.s.electric_utility.outage_durations[s])
sum( p.production_factor[t, tz+ts-1] * m[:dvMGRatedProduction][t, s, tz, ts] for ts in 1:p.s.electric_utility.outage_durations[s])
+ p.s.generator.fuel_intercept_gal_per_hr * p.hours_per_time_step *
sum( m[:binMGGenIsOnInTS][s, tz, ts] for ts in 1:p.s.electric_utility.outage_durations[s])
)
Expand Down
Loading

0 comments on commit f885baf

Please sign in to comment.