Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update electric_storage.jl and doc strings #106

Open
wants to merge 3,089 commits into
base: develop
Choose a base branch
from
Open

Update electric_storage.jl and doc strings #106

wants to merge 3,089 commits into from

Conversation

rathod-b
Copy link
Collaborator

@rathod-b rathod-b commented Jul 26, 2022

Update default degradation parameters per updated parameters.

Also update several doc strings for input descriptions.

@rathod-b rathod-b requested a review from zolanaj July 26, 2022 18:39
@adfarth
Copy link
Collaborator

adfarth commented Jul 28, 2022

I piggy backed on this PR to include a few minor updates to doc strings!

@adfarth adfarth changed the title Update electric_storage.jl Update electric_storage.jl and doc strings Aug 1, 2022
Copy link
Collaborator

@zolanaj zolanaj left a comment

Choose a reason for hiding this comment

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

@rathod-b Looks good, thanks for these updates: A few comments beyond the in-line ones:

  • The docs for the degradation model still need to be updated; there are TODOs in the code but we might want that as an open issue just so we don't forget it.
  • It would be good to make a more robust collection of tests. We can use the new file degradation_tests.json for this since it's not currently used. We should include a test case for replacement (which we already have, but please add an assertion for the number of replacements or a new degradation-specific measure) and a test case for augmentation (which we don't have yet).

Let me know if you want help with any of these. Thanks!
Alex

src/core/energy_storage/electric_storage.jl Show resolved Hide resolved
test/scenarios/degradation_tests.json Outdated Show resolved Hide resolved
src/constraints/battery_degradation.jl Outdated Show resolved Hide resolved
src/results/electric_storage.jl Show resolved Hide resolved
@variable(m, bmth[months], Bin) # track which month SOH indicator drops to < 80%
@variable(m, 0 <= bmth_BkWh[months]) # track the kwh replacement value

M = 10*maximum(p.s.electric_load.loads_kw) # the big M
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Note: Current big-M. This value seems to be giving good consistent results. Rationale is that a battery wont be larger than the peak load so 10x peak load is large enough. Even this value might be larger than expected. @zolanaj should we sweep across a range of big M values (i.e. 0.1x, 1.0x, 10x peak load) to fine tune this parameter?

Copy link
Collaborator

Choose a reason for hiding this comment

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

@rathod-b I checked the API and we never introduced a practical maximum size for batteries because they didn't have integer variables involved prior to the introduction of degradation.

One heuristic would be power = 2x peak load, and energy = 12x peak load (i.e., allowing you to charge for half the day, and discharge for the other half of the day). This precludes long-term storage systems, but we can probably include a user setting for long-term storage.

Related: I'll check our issues for importing big-M's from the API Julia code and add that issue if it's not there.

Copy link
Collaborator

Choose a reason for hiding this comment

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

big-M issue is here: #114

Copy link
Collaborator

Choose a reason for hiding this comment

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

Actually, a system that has oversized PV to power the site load might need more. just do 24x peak load for both power and energy, that should be enough.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Updated big-M to be set based on max_kwh. Is it normal for changes in big-M to change the results? I see slight differences in electric storage results.

@@ -400,6 +400,44 @@ check to make sure that PV does NOT export unless the site load is met first for
if results["PV"]["year_one_to_grid_series_kw"][i] > 0)
end

@testset "Battery degradation replacement strategy" begin
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@zolanaj I added this test to test the outputs as well as model expression values. Since solve time is not an issue I am sticking with a simple LargeOffice load profile.

I had to change the result JSON tests to inequalities because we get different results on github action than those when testing this scenario by itself.

Copy link
Collaborator

Choose a reason for hiding this comment

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

@rathod-b some values like the SOH indicator at the end are going to be stable while a lot of these others will change with solver settings. We can construct a more unit-test-like load profile to incentivize a certain behavior and make the solution more stable (something like a flat load with hourly cost that oscillates from very expensive to free every other period.)

@rathod-b
Copy link
Collaborator Author

@rathod-b Looks good, thanks for these updates: A few comments beyond the in-line ones:

  • The docs for the degradation model still need to be updated; there are TODOs in the code but we might want that as an open issue just so we don't forget it.
  • It would be good to make a more robust collection of tests. We can use the new file degradation_tests.json for this since it's not currently used. We should include a test case for replacement (which we already have, but please add an assertion for the number of replacements or a new degradation-specific measure) and a test case for augmentation (which we don't have yet).

Let me know if you want help with any of these. Thanks! Alex

Hi Alex, thanks for your comments on the PR! Its been a while and I am picking this back up. I have removed the many TODOs from the code documentation which were initially added as reminders for me. If you see any more of them, do let me know.

I have also updated the replacement strategy testset to validate some degradation specific parameters to ensure the results make sense and DVs arent switching between 0 and 1 as they were when we were testing this back in Fall 2022. Let me know if there are any comments on that.

Lastly, I have an open question for you. At present, we add the SOC incentive to the objective function in run_reopt.jl without any consideration for BESS degradation. I was wondering if we wanted to handle that programmatically, or handle it via a warning to a user and have then set the add_soc_incentive to false when running degradation?

@rathod-b
Copy link
Collaborator Author

@rathod-b Looks good, thanks for these updates: A few comments beyond the in-line ones:

  • The docs for the degradation model still need to be updated; there are TODOs in the code but we might want that as an open issue just so we don't forget it.
  • It would be good to make a more robust collection of tests. We can use the new file degradation_tests.json for this since it's not currently used. We should include a test case for replacement (which we already have, but please add an assertion for the number of replacements or a new degradation-specific measure) and a test case for augmentation (which we don't have yet).

Let me know if you want help with any of these. Thanks! Alex

Hi Alex, thanks for your comments on the PR! Its been a while and I am picking this back up. I have removed the many TODOs from the code documentation which were initially added as reminders for me. If you see any more of them, do let me know.

I have also updated the replacement strategy testset to validate some degradation specific parameters to ensure the results make sense and DVs arent switching between 0 and 1 as they were when we were testing this back in Fall 2022. Let me know if there are any comments on that.

Lastly, I have an open question for you. At present, we add the SOC incentive to the objective function in run_reopt.jl without any consideration for BESS degradation. I was wondering if we wanted to handle that programmatically, or handle it via a warning to a user and have then set the add_soc_incentive to false when running degradation?

I could also use some help in fixing the rendering of a formula in documentation. Line 145 in electric_storage.jl has the broken formula for residual value.

Comment on lines 166 to 176
residual_factor = 1 - (p.s.financial.analysis_years*12/mth - floor(p.s.financial.analysis_years*12/mth))
residual_value = p.s.storage.attr[b].degradation.maintenance_cost_per_kwh[end]*residual_factor
s[mth] = residual_value

end

#=
-> linearize the product of bmth & m[:dvStorageEnergy][b]
For all months
0 <= bmth_BkWh <= dvStorageEnergy <= M (when bmth is true)

if bmth is 0, bmth_BkWh = 0. if bmth is 1, bmth_BkWh can equal m[:dvStorageEnergy][b]
=#
M = p.s.storage.attr[b].max_kwh # the big M
@variable(m, 0 <= bmth_BkWh[months])
@constraint(m, [mth in months], bmth_BkWh[mth] <= m[:dvStorageEnergy][b])
@constraint(m, [mth in months], bmth_BkWh[mth] <= M * bmth[mth])
@constraint(m, [mth in months], bmth_BkWh[mth] >= m[:dvStorageEnergy][b] - M*(1-bmth[mth]))

# add replacment cost to objective
# create replacement cost expression for objective
@expression(m, degr_cost, sum(c[mth] * bmth_BkWh[mth] for mth in months))

# create salvage value expression for objective
@expression(m, salv_value, sum(s[mth] * bmth_BkWh[mth] for mth in months))
# create residual value expression for objective
@expression(m, residual_value, sum(s[mth] * bmth_BkWh[mth] for mth in months))
Copy link
Collaborator

Choose a reason for hiding this comment

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

is maintenance_cost_per_kwh actually a replacement cost? we may want to rename it for clarity (so itn's not confused with O&M costs).

@@ -400,6 +400,44 @@ check to make sure that PV does NOT export unless the site load is met first for
if results["PV"]["year_one_to_grid_series_kw"][i] > 0)
end

@testset "Battery degradation replacement strategy" begin
Copy link
Collaborator

Choose a reason for hiding this comment

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

@rathod-b some values like the SOH indicator at the end are going to be stable while a lot of these others will change with solver settings. We can construct a more unit-test-like load profile to incentivize a certain behavior and make the solution more stable (something like a flat load with hourly cost that oscillates from very expensive to free every other period.)

@zolanaj
Copy link
Collaborator

zolanaj commented Jun 2, 2023

@rathod-b Looks good, thanks for these updates: A few comments beyond the in-line ones:

  • The docs for the degradation model still need to be updated; there are TODOs in the code but we might want that as an open issue just so we don't forget it.
  • It would be good to make a more robust collection of tests. We can use the new file degradation_tests.json for this since it's not currently used. We should include a test case for replacement (which we already have, but please add an assertion for the number of replacements or a new degradation-specific measure) and a test case for augmentation (which we don't have yet).

Let me know if you want help with any of these. Thanks! Alex

Hi Alex, thanks for your comments on the PR! Its been a while and I am picking this back up. I have removed the many TODOs from the code documentation which were initially added as reminders for me. If you see any more of them, do let me know.
I have also updated the replacement strategy testset to validate some degradation specific parameters to ensure the results make sense and DVs arent switching between 0 and 1 as they were when we were testing this back in Fall 2022. Let me know if there are any comments on that.
Lastly, I have an open question for you. At present, we add the SOC incentive to the objective function in run_reopt.jl without any consideration for BESS degradation. I was wondering if we wanted to handle that programmatically, or handle it via a warning to a user and have then set the add_soc_incentive to false when running degradation?

I could also use some help in fixing the rendering of a formula in documentation. Line 145 in electric_storage.jl has the broken formula for residual value.

Lastly, I have an open question for you. At present, we add the SOC incentive to the objective function in run_reopt.jl without any consideration for BESS degradation. I was wondering if we wanted to handle that programmatically, or handle it via a warning to a user and have then set the add_soc_incentive to false when running degradation?

A warning should be fine here - these different objectives can be handled by the solver.

@zolanaj zolanaj self-requested a review June 16, 2023 15:48
Copy link
Collaborator

@zolanaj zolanaj left a comment

Choose a reason for hiding this comment

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

@rathod-b I made the degradation test a bit simpler and did some renaming of parameters and variables for style and clarity. If you agree with these and tests pass, I think this can be merged. (The HiGHS tests are timing out but I think everything else is passing.)

zolanaj and others added 25 commits December 11, 2023 17:45
Add execute permissions to ssc.dll for Wind on Windows
Migrate Xpress tests to HiGHS, Fix Wind on Windows OS
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants