-
Notifications
You must be signed in to change notification settings - Fork 14
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
base: develop
Are you sure you want to change the base?
Conversation
I piggy backed on this PR to include a few minor updates to doc strings! |
There was a problem hiding this 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
@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 |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.)
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 |
I could also use some help in fixing the rendering of a formula in documentation. Line 145 in |
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)) |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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.)
A warning should be fine here - these different objectives can be handled by the solver. |
There was a problem hiding this 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.)
Update CHP defaults, and update Julia dependencies
…into add-electric-heater
0385d5b
to
e78db43
Compare
b77814e
to
b528862
Compare
e78db43
to
2cffed5
Compare
Update default degradation parameters per updated parameters.
Also update several doc strings for input descriptions.