Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
60 commits
Select commit Hold shift + click to select a range
a6c74d0
initial commit
Jan 7, 2025
bb9cbfb
Merge branch 'develop' into bess-export
Feb 7, 2025
3cebd7e
start adding inputs
Feb 10, 2025
1575a9b
Merge branch 'develop' into bess-export
adfarth May 27, 2025
b211b44
rm can_grid_charge
adfarth May 27, 2025
e065d2f
set up framework
adfarth May 28, 2025
a8b2dca
Merge branch 'develop' into bess-export
adfarth May 30, 2025
52f036b
update electric_utility_constraints
adfarth May 30, 2025
47bfc79
make discharge from storage total discharge
adfarth May 30, 2025
8d9be52
update results
adfarth May 30, 2025
b897e47
fix reopt_inputs
adfarth Jun 2, 2025
946f8a0
Merge branch 'develop' into bess-export
adfarth Jun 2, 2025
5ac4c84
fix indexing
adfarth Jun 2, 2025
a302d7f
Update inputs.jl
adfarth Jun 2, 2025
ae2f872
add todo
hdunham Jun 4, 2025
f823ae4
Update CHANGELOG.md
hdunham Jun 10, 2025
9322adf
condense 4 constraints into 1
hdunham Jun 10, 2025
1e0b211
Update storage_constraints.jl
hdunham Jun 10, 2025
7743683
rm commented out refs to can_export_to_grid
hdunham Jun 10, 2025
48c270d
rm resolved TODOs on defining dvStorageToGrid
hdunham Jun 10, 2025
041d759
rmv extra constraint
adfarth Jun 11, 2025
cd67b3f
updt CUR to EXC
adfarth Jun 11, 2025
42a4937
rmv todos and infos
adfarth Jun 11, 2025
827647a
add todos, rm unneeded if
hdunham Jun 12, 2025
547d1bd
MPC storage export
hdunham Jun 12, 2025
daf8d1d
Merge branch 'bess-export' of https://github.com/NREL/REopt.jl into b…
hdunham Jun 12, 2025
7da2839
replace NEM_techs & WHL_techs w techs_by_exportbin elem, same for sto…
hdunham Jun 12, 2025
e19efe6
remove infos
hdunham Jun 16, 2025
61aba35
Revert "replace NEM_techs & WHL_techs w techs_by_exportbin elem, same…
hdunham Jun 16, 2025
1d05bec
rm todo
hdunham Jun 16, 2025
335acee
reformat RE sums/comments for clarity
hdunham Jun 16, 2025
056106f
fix MPC convert error
hdunham Jun 16, 2025
fae0ff8
combine 2 tests
hdunham Jun 17, 2025
5c31eeb
correct constraint (4d) loop
hdunham Jun 17, 2025
f45fe81
Update runtests.jl
hdunham Jun 17, 2025
55ce586
start bess export testing
hdunham Jun 17, 2025
0a7c831
update bess export testing
hdunham Jun 17, 2025
d522d0f
add comment to clarify bound
hdunham Jun 17, 2025
dbb5b17
update bess export testing
hdunham Jun 18, 2025
cbecb6b
ex update
adfarth Jun 25, 2025
1b5e9eb
export in emissions
adfarth Jun 25, 2025
63a214b
Update emissions_constraints.jl
adfarth Jul 3, 2025
0026738
bigM_hourly_load_plus_battery
adfarth Jul 3, 2025
875cbd2
Update electric_storage.jl
adfarth Jul 3, 2025
e689e0f
try multi_node
adfarth Jul 3, 2025
adc7828
Merge branch 'develop' into bess-export
adfarth Jul 3, 2025
6336466
t to b
adfarth Jul 3, 2025
ee1a4f1
Update electric_storage.jl
adfarth Jul 7, 2025
3adec5b
Merge branch 'fixed-bess-soc' into bess-export
adfarth Jul 7, 2025
e1a504d
updt soc_init and add tol input
adfarth Jul 9, 2025
dfe1ed0
output name
adfarth Jul 17, 2025
809f079
initial add of grid cost
adfarth Aug 6, 2025
e8793c7
updt documentation
adfarth Aug 6, 2025
027fb3a
Update utils.jl
adfarth Aug 21, 2025
8c996cd
Merge branch 'develop' into bess-export
adfarth Sep 5, 2025
f5f5d21
Merge branch 'develop' into bess-export
adfarth Nov 17, 2025
07e8a3f
Merge branch 'develop' into bess-export
lixiangk1 Mar 12, 2026
d89dda1
Merge branch 'develop' into bess-export
adfarth May 5, 2026
a974c66
rm grid cost
adfarth May 5, 2026
5557084
rm grid cost
adfarth May 5, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ Classify the change according to the following categories:
### Deprecated
### Removed

## bess-export
### Added
- Add decision variable **dvStorageToGrid** and **ElectricStorage** input options for grid export: `can_net_meter`, `can_wholesale`, `can_export_beyond_nem_limit`

## v0.59.0
### Added
- Added two new size classes for **SteamTurbine** tech with new tech size ranges.
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 @@ -40,7 +40,7 @@ end
The set maps are best explained with an example. The `techs_by_exportbin` map uses each technology'sattributes (eg. `PV`) to map each technology to which export bins that technology can access. The export bins include:
1. `:NEM` (Net Energy Metering)
2. `:WHL` (Wholesale)
3. `:EXC` (Excess, beyond NEM))
3. `:EXC` (Excess, beyond NEM)
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(
Expand Down
102 changes: 72 additions & 30 deletions src/constraints/electric_utility_constraints.jl
Original file line number Diff line number Diff line change
Expand Up @@ -22,31 +22,40 @@ function add_export_constraints(m, p; _n="")
WHL_benefit = 0
NEM_techs = String[t for t in p.techs.elec if :NEM in p.export_bins_by_tech[t]]
WHL_techs = String[t for t in p.techs.elec if :WHL in p.export_bins_by_tech[t]]
NEM_storage = String[b for b in p.s.storage.types.elec if :NEM in p.export_bins_by_storage[b]]
Copy link
Copy Markdown
Collaborator

@hdunham hdunham Jun 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't really about what you added, but isn't NEM_techs just equal to techs_by_exportbins[:NEM]? Same with WHL_techs, NEM_storage, WHL_storage. Do you agree? If so idk why we are recreating it.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes I just double checked and I agree. We could probably replace all instances of NEM_techs and WHL_techs with their techs_by_export bin equivalent

Copy link
Copy Markdown
Collaborator Author

@adfarth adfarth Jul 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@hdunham it looks like you made this change and then reverted it. I'm assuming it broke some things and if so can I resolve this convo?

WHL_storage = String[b for b in p.s.storage.types.elec if :WHL in p.export_bins_by_storage[b]]

if !isempty(NEM_techs)
if !isempty(vcat(NEM_techs, NEM_storage))
# Constraint (9c): Net metering only -- can't sell more than you purchase
# hours_per_time_step is cancelled on both sides, but used for unit consistency (convert power to energy)
@constraint(m,
p.hours_per_time_step * sum( m[Symbol("dvProductionToGrid"*_n)][t, :NEM, ts]
for t in NEM_techs, ts in p.time_steps)
p.hours_per_time_step * (
sum( m[Symbol("dvProductionToGrid"*_n)][t, :NEM, ts] for t in NEM_techs, ts in p.time_steps) +
sum( m[Symbol("dvStorageToGrid"*_n)][b, :NEM, ts] for b in NEM_storage, ts in p.time_steps)
)
<= p.hours_per_time_step * sum( m[Symbol("dvGridPurchase"*_n)][ts, tier]
for ts in p.time_steps, tier in 1:p.s.electric_tariff.n_energy_tiers)
)
Comment on lines +28 to 38

if p.s.electric_utility.net_metering_limit_kw == p.s.electric_utility.interconnection_limit_kw && isempty(WHL_techs)
if p.s.electric_utility.net_metering_limit_kw == p.s.electric_utility.interconnection_limit_kw && isempty(vcat(WHL_techs, WHL_storage))
# no need for binNEM nor binWHL
binNEM = 1
# Note: BESS can export but is not included in interconnection limit.
@constraint(m,
sum(m[Symbol("dvSize"*_n)][t] for t in NEM_techs) <= p.s.electric_utility.interconnection_limit_kw
)
NEM_benefit = @expression(m, p.pwf_e * p.hours_per_time_step *
sum( sum(p.s.electric_tariff.export_rates[:NEM][ts] * m[Symbol("dvProductionToGrid"*_n)][t, :NEM, ts]
for t in p.techs_by_exportbin[:NEM]) for ts in p.time_steps)
sum(p.s.electric_tariff.export_rates[:NEM][ts] * (
sum( m[Symbol("dvProductionToGrid"*_n)][t, :NEM, ts] for t in p.techs_by_exportbin[:NEM]) +
sum( m[Symbol("dvStorageToGrid"*_n)][b, :NEM, ts] for b in p.storage_by_exportbin[:NEM])
) for ts in p.time_steps)
)
if :EXC in p.s.electric_tariff.export_bins
EXC_benefit = @expression(m, p.pwf_e * p.hours_per_time_step *
sum( sum(p.s.electric_tariff.export_rates[:EXC][ts] * m[Symbol("dvProductionToGrid"*_n)][t, :EXC, ts]
for t in p.techs_by_exportbin[:EXC]) for ts in p.time_steps)
sum(p.s.electric_tariff.export_rates[:EXC][ts] * (
sum( m[Symbol("dvProductionToGrid"*_n)][t, :EXC, ts] for t in p.techs_by_exportbin[:EXC]) +
sum( m[Symbol("dvStorageToGrid"*_n)][b, :EXC, ts] for b in p.storage_by_exportbin[:EXC])
) for ts in p.time_steps)
)
end
else
Expand All @@ -63,6 +72,7 @@ function add_export_constraints(m, p; _n="")
NEM_benefit = @variable(m, lower_bound = max_bene)

# If choosing to take advantage of NEM, must have total capacity less than net_metering_limit_kw
# Note: BESS can export but is not included in net_metering_limit_kw or interconnection_limit_kw.
if solver_is_compatible_with_indicator_constraints(p.s.settings.solver_name)
@constraint(m,
binNEM => {sum(m[Symbol("dvSize"*_n)][t] for t in NEM_techs) <= p.s.electric_utility.net_metering_limit_kw}
Expand Down Expand Up @@ -93,57 +103,81 @@ function add_export_constraints(m, p; _n="")
if solver_is_compatible_with_indicator_constraints(p.s.settings.solver_name)
@constraint(m,
binNEM => {NEM_benefit >= p.pwf_e * p.hours_per_time_step *
sum( sum(p.s.electric_tariff.export_rates[:NEM][ts] * m[Symbol("dvProductionToGrid"*_n)][t, :NEM, ts]
for t in p.techs_by_exportbin[:NEM]) for ts in p.time_steps)
sum(p.s.electric_tariff.export_rates[:NEM][ts] * (
sum( m[Symbol("dvProductionToGrid"*_n)][t, :NEM, ts] for t in p.techs_by_exportbin[:NEM]) +
sum( m[Symbol("dvStorageToGrid"*_n)][b, :NEM, ts] for b in p.storage_by_exportbin[:NEM])
) for ts in p.time_steps
)
}
)
@constraint(m, !binNEM => {NEM_benefit >= 0})
@constraint(m,[ts in p.time_steps_with_grid, t in p.techs_by_exportbin[:NEM]],
!binNEM => { m[Symbol("dvProductionToGrid"*_n)][t, :NEM, ts] == 0
}
)
@constraint(m,[ts in p.time_steps_with_grid, b in p.storage_by_exportbin[:NEM]],
!binNEM => { m[Symbol("dvStorageToGrid"*_n)][b, :NEM, ts] == 0
}
)
else
@constraint(m,
NEM_benefit >= p.pwf_e * p.hours_per_time_step *
sum( sum(p.s.electric_tariff.export_rates[:NEM][ts] * m[Symbol("dvProductionToGrid"*_n)][t, :NEM, ts]
for t in p.techs_by_exportbin[:NEM]) for ts in p.time_steps)
sum(p.s.electric_tariff.export_rates[:NEM][ts] * (
sum( m[Symbol("dvProductionToGrid"*_n)][t, :NEM, ts] for t in p.techs_by_exportbin[:NEM]) +
sum( m[Symbol("dvStorageToGrid"*_n)][b, :NEM, ts] for b in p.storage_by_exportbin[:NEM])
) for ts in p.time_steps
)
)
@constraint(m, NEM_benefit >= max_bene * binNEM)
@constraint(m,[ts in p.time_steps_with_grid, t in p.techs_by_exportbin[:NEM]],
m[Symbol("dvProductionToGrid"*_n)][t, :NEM, ts] <= binNEM * sum(p.s.electric_load.loads_kw)
)
@constraint(m,[ts in p.time_steps_with_grid, b in p.storage_by_exportbin[:NEM]],
m[Symbol("dvStorageToGrid"*_n)][b, :NEM, ts] <= binNEM * sum(p.s.electric_load.loads_kw)
)
end

EXC_benefit = 0
if :EXC in p.s.electric_tariff.export_bins
EXC_benefit = @variable(m, lower_bound = max_bene)
EXC_benefit = @variable(m, lower_bound = max_bene) #lower bound because the benefit is treated as a negative cost
if solver_is_compatible_with_indicator_constraints(p.s.settings.solver_name)
@constraint(m,
binNEM => {EXC_benefit >= p.pwf_e * p.hours_per_time_step *
sum( sum(p.s.electric_tariff.export_rates[:EXC][ts] * m[Symbol("dvProductionToGrid"*_n)][t, :EXC, ts]
for t in p.techs_by_exportbin[:EXC]) for ts in p.time_steps)
sum( p.s.electric_tariff.export_rates[:EXC][ts] * (
sum( m[Symbol("dvProductionToGrid"*_n)][t, :EXC, ts] for t in p.techs_by_exportbin[:EXC]) +
sum( m[Symbol("dvStorageToGrid"*_n)][b, :EXC, ts] for b in p.storage_by_exportbin[:EXC])
) for ts in p.time_steps
)
}
)


@constraint(m, !binNEM => {EXC_benefit >= 0})
else
@constraint(m,
EXC_benefit >= p.pwf_e * p.hours_per_time_step *
sum( sum(p.s.electric_tariff.export_rates[:EXC][ts] * m[Symbol("dvProductionToGrid"*_n)][t, :EXC, ts]
for t in p.techs_by_exportbin[:EXC]) for ts in p.time_steps)
sum( p.s.electric_tariff.export_rates[:EXC][ts] * (
sum( m[Symbol("dvProductionToGrid"*_n)][t, :EXC, ts] for t in p.techs_by_exportbin[:EXC]) +
sum( m[Symbol("dvStorageToGrid"*_n)][b, :EXC, ts] for b in p.storage_by_exportbin[:EXC])
) for ts in p.time_steps
)
)
@constraint(m, EXC_benefit >= max_bene * binNEM)
end
end
end
end

if !isempty(WHL_techs)
if !isempty(vcat(WHL_techs, WHL_storage))

if typeof(binNEM) <: Real # no need for wholesale binary
binWHL = 1
WHL_benefit = @expression(m, p.pwf_e * p.hours_per_time_step *
sum( sum(p.s.electric_tariff.export_rates[:WHL][ts] * m[Symbol("dvProductionToGrid"*_n)][t, :WHL, ts]
for t in p.techs_by_exportbin[:WHL]) for ts in p.time_steps)
sum( p.s.electric_tariff.export_rates[:WHL][ts] * (
sum(m[Symbol("dvProductionToGrid"*_n)][t, :WHL, ts] for t in p.techs_by_exportbin[:WHL]) +
sum(m[Symbol("dvStorageToGrid"*_n)][b, :WHL, ts] for b in p.storage_by_exportbin[:WHL])
) for ts in p.time_steps
)
)
else
binWHL = @variable(m, binary = true)
Expand All @@ -155,16 +189,22 @@ function add_export_constraints(m, p; _n="")
if solver_is_compatible_with_indicator_constraints(p.s.settings.solver_name)
@constraint(m,
binWHL => {WHL_benefit >= p.pwf_e * p.hours_per_time_step *
sum( sum(p.s.electric_tariff.export_rates[:WHL][ts] * m[Symbol("dvProductionToGrid"*_n)][t, :WHL, ts]
for t in p.techs_by_exportbin[:WHL]) for ts in p.time_steps)
sum(p.s.electric_tariff.export_rates[:WHL][ts] * (
sum(m[Symbol("dvProductionToGrid"*_n)][t, :WHL, ts] for t in p.techs_by_exportbin[:WHL]) +
sum(m[Symbol("dvStorageToGrid"*_n)][b, :WHL, ts] for b in p.storage_by_exportbin[:WHL])
) for ts in p.time_steps
)
}
)
@constraint(m, !binWHL => {WHL_benefit >= 0})
else
@constraint(m,
WHL_benefit >= p.pwf_e * p.hours_per_time_step *
sum( sum(p.s.electric_tariff.export_rates[:WHL][ts] * m[Symbol("dvProductionToGrid"*_n)][t, :WHL, ts]
for t in p.techs_by_exportbin[:WHL]) for ts in p.time_steps)
sum(p.s.electric_tariff.export_rates[:WHL][ts] * (
sum(m[Symbol("dvProductionToGrid"*_n)][t, :WHL, ts] for t in p.techs_by_exportbin[:WHL]) +
sum(m[Symbol("dvStorageToGrid"*_n)][b, :WHL, ts] for b in p.storage_by_exportbin[:WHL])
) for ts in p.time_steps
)
)
@constraint(m, WHL_benefit >= max_bene * binWHL)
end
Expand Down Expand Up @@ -196,7 +236,6 @@ function add_monthly_peak_constraint(m, p; _n="")
sum(p.production_factor[t, ts] * p.levelization_factor[t] * m[Symbol("dvRatedProduction"*_n)][t, ts] for t in p.techs.chp) -
sum(sum(m[Symbol("dvProductionToStorage"*_n)][b, t, ts] for b in p.s.storage.types.elec) for t in p.techs.chp) -
sum(sum(m[Symbol("dvProductionToGrid")][t,u,ts] for u in p.export_bins_by_tech[t]) for t in p.techs.chp)

)
else
@constraint(m, [mth in p.months, ts in p.s.electric_tariff.time_steps_monthly[mth]],
Expand Down Expand Up @@ -287,17 +326,20 @@ function add_simultaneous_export_import_constraint(m, p; _n="")
)
@constraint(m, ExportOnlyAfterSiteLoadMetCon[ts in p.time_steps],
!m[Symbol("binNoGridPurchases"*_n)][ts] => {
sum(m[Symbol("dvProductionToGrid"*_n)][t,u,ts] for t in p.techs.elec, u in p.export_bins_by_tech[t]) <= 0
sum(m[Symbol("dvProductionToGrid"*_n)][t,u,ts] for t in p.techs.elec, u in p.export_bins_by_tech[t]) +
sum(m[Symbol("dvStorageToGrid"*_n)][b, u, ts] for b in p.s.storage.types.elec, u in p.export_bins_by_storage[b]) <= 0
}
)
else
bigM_hourly_load = maximum(p.s.electric_load.loads_kw)+maximum(p.s.space_heating_load.loads_kw)+maximum(p.s.process_heat_load.loads_kw)+maximum(p.s.dhw_load.loads_kw)+maximum(p.s.cooling_load.loads_kw_thermal)
Comment thread
adfarth marked this conversation as resolved.
bigM_hourly_load_plus_battery = maximum(p.s.electric_load.loads_kw)+maximum(p.s.space_heating_load.loads_kw)+maximum(p.s.process_heat_load.loads_kw)+maximum(p.s.dhw_load.loads_kw)+maximum(p.s.cooling_load.loads_kw_thermal)+sum(Real[p.s.storage.attr[b].max_kw for b in p.s.storage.types.elec])
@constraint(m, NoGridPurchasesBinary[ts in p.time_steps],
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) <= bigM_hourly_load*(1-m[Symbol("binNoGridPurchases"*_n)][ts])
sum(m[Symbol("dvGridToStorage"*_n)][b, ts] for b in p.s.storage.types.elec) <= bigM_hourly_load_plus_battery*(1-m[Symbol("binNoGridPurchases"*_n)][ts])
)
@constraint(m, ExportOnlyAfterSiteLoadMetCon[ts in p.time_steps],
sum(m[Symbol("dvProductionToGrid"*_n)][t,u,ts] for t in p.techs.elec, u in p.export_bins_by_tech[t]) <= bigM_hourly_load * m[Symbol("binNoGridPurchases"*_n)][ts]
sum(m[Symbol("dvProductionToGrid"*_n)][t,u,ts] for t in p.techs.elec, u in p.export_bins_by_tech[t]) +
sum(m[Symbol("dvStorageToGrid"*_n)][b, u, ts] for b in p.s.storage.types.elec, u in p.export_bins_by_storage[b])
<= bigM_hourly_load_plus_battery * m[Symbol("binNoGridPurchases"*_n)][ts]
)
end
end
Expand Down Expand Up @@ -391,7 +433,7 @@ end
function add_elec_utility_expressions(m, p; _n="")

if !isempty(p.s.electric_tariff.export_bins) && !isempty(p.techs.all)
# NOTE: levelization_factor is baked into dvProductionToGrid
# NOTE: levelization_factor is baked into dvProductionToGrid and dvStorageToGrid
m[Symbol("TotalExportBenefit"*_n)] = m[Symbol("NEM_benefit"*_n)] + m[Symbol("WHL_benefit"*_n)] +
m[Symbol("EXC_benefit"*_n)]
else
Expand Down
29 changes: 20 additions & 9 deletions src/constraints/emissions_constraints.jl
Original file line number Diff line number Diff line change
Expand Up @@ -120,24 +120,35 @@ function calc_yr1_emissions_offset_from_elec_exports(m, p)
return 0.0, 0.0, 0.0, 0.0
end
yr1_emissions_offset_from_elec_exports_lbs_CO2 = @expression(m, p.hours_per_time_step *
sum(m[:dvProductionToGrid][t,u,ts] * (p.s.electric_utility.emissions_factor_series_lb_CO2_per_kwh[ts])
for t in p.techs.elec, ts in p.time_steps, u in p.export_bins_by_tech[t])
sum( p.s.electric_utility.emissions_factor_series_lb_CO2_per_kwh[ts] * (
sum(m[:dvProductionToGrid][t,u,ts] for t in p.techs.elec, u in p.export_bins_by_tech[t])
+ sum(m[:dvStorageToGrid][b, u, ts] for b in p.s.storage.types.elec, u in p.export_bins_by_storage[b])
) for ts in p.time_steps
)
)
# if battery ends up being able to discharge to grid, need to incorporate here- might require complex tracking of what's charging battery

yr1_emissions_offset_from_elec_exports_lbs_NOx = @expression(m, p.hours_per_time_step *
sum(m[:dvProductionToGrid][t,u,ts] * (p.s.electric_utility.emissions_factor_series_lb_NOx_per_kwh[ts])
for t in p.techs.elec, ts in p.time_steps, u in p.export_bins_by_tech[t])
sum( p.s.electric_utility.emissions_factor_series_lb_NOx_per_kwh[ts] * (
sum(m[:dvProductionToGrid][t,u,ts] for t in p.techs.elec, u in p.export_bins_by_tech[t])
+ sum(m[:dvStorageToGrid][b, u, ts] for b in p.s.storage.types.elec, u in p.export_bins_by_storage[b])
) for ts in p.time_steps
)
)

yr1_emissions_offset_from_elec_exports_lbs_SO2 = @expression(m, p.hours_per_time_step *
sum(m[:dvProductionToGrid][t,u,ts] * (p.s.electric_utility.emissions_factor_series_lb_SO2_per_kwh[ts])
for t in p.techs.elec, ts in p.time_steps, u in p.export_bins_by_tech[t])
sum( p.s.electric_utility.emissions_factor_series_lb_SO2_per_kwh[ts] * (
sum(m[:dvProductionToGrid][t,u,ts] for t in p.techs.elec, u in p.export_bins_by_tech[t])
+ sum(m[:dvStorageToGrid][b, u, ts] for b in p.s.storage.types.elec, u in p.export_bins_by_storage[b])
) for ts in p.time_steps
)
)

yr1_emissions_offset_from_elec_exports_lbs_PM25 = @expression(m, p.hours_per_time_step *
sum(m[:dvProductionToGrid][t,u,ts] * (p.s.electric_utility.emissions_factor_series_lb_PM25_per_kwh[ts])
for t in p.techs.elec, ts in p.time_steps, u in p.export_bins_by_tech[t])
sum( p.s.electric_utility.emissions_factor_series_lb_PM25_per_kwh[ts] * (
sum(m[:dvProductionToGrid][t,u,ts] for t in p.techs.elec, u in p.export_bins_by_tech[t])
+ sum(m[:dvStorageToGrid][b, u, ts] for b in p.s.storage.types.elec, u in p.export_bins_by_storage[b])
) for ts in p.time_steps
)
)

return yr1_emissions_offset_from_elec_exports_lbs_CO2,
Expand Down
Loading
Loading