Skip to content

Asymmetric line flow (Refined); READY FOR REVIEW !!!#789

Open
sambuddhac wants to merge 52 commits intodevelopfrom
asymmetric_line_flow
Open

Asymmetric line flow (Refined); READY FOR REVIEW !!!#789
sambuddhac wants to merge 52 commits intodevelopfrom
asymmetric_line_flow

Conversation

@sambuddhac
Copy link
Collaborator

@sambuddhac sambuddhac commented Nov 13, 2024

Description

This PR attempts to introduce bidirectional asymmetric transmission lines into the system. Such lines have different values of MW flow limits, loss percentage, and capacity expansion limits along the two directions. While doing so, this PR also ensures that there are also symmetric lines present in the system along with the asymmetric lines and modifies the code in such a way that backwards compatibility is maintained with the existing cases.

What type of PR is this? (check all applicable)

  • Feature
  • Bug Fix
  • Documentation Update
  • Code Refactor
  • Performance Improvements

Related Tickets & Documents

Checklist

  • Code changes are sufficiently documented; i.e. new functions contain docstrings and .md files under /docs/src have been updated if necessary.
  • The latest changes on the target branch have been incorporated, so that any conflicts are taken care of before merging. This can be accomplished either by merging in the target branch (e.g. 'git merge develop') or by rebasing on top of the target branch (e.g. 'git rebase develop'). Please do not hesitate to reach out to the GenX development team if you need help with this.
  • Code has been tested to ensure all functionality works as intended.
  • CHANGELOG.md has been updated (if this is a 'notable' change).
  • I consent to the release of this PR's code under the GNU General Public license.

How this can be tested

Post-approval checklist for GenX core developers

After the PR is approved

  • Check that the latest changes on the target branch are incorporated, either via merge or rebase
  • Remember to squash and merge if incorporating into develop

@lbonaldo lbonaldo added the enhancement New feature or request label Dec 3, 2024
@lbonaldo lbonaldo force-pushed the asymmetric_line_flow branch from 0002caf to 0e224c5 Compare December 3, 2024 23:31
@lbonaldo lbonaldo added this to the v0.4.2 milestone Dec 4, 2024
@sambuddhac sambuddhac changed the title Asymmetric line flow (Refined) #Work in Progress; DO NOT MERGE YET !!! Asymmetric line flow (Refined) #Work in Progress; READY FOR REVIEW !!! Dec 17, 2024
@sambuddhac
Copy link
Collaborator Author

sambuddhac commented Dec 17, 2024

Hi @JesseJenkins and @lbonaldo , I have pushed all the modifications to the code base for this PR. Few things to note: First of all, as you will see, it's way more lengthy and complicated than what Jesse suggested to me previously. I first tried with the simpler version. But, was getting bidirectional flows on the asymmetric lines with Qian's example case even when we restricted the flow limits to zero in one of the directions for the asymmetric lines.

With some pondering, I realized that I was doing wrong indexing on the constraints and decision variables. So, I had to do a bit more digging and refining the code. The fundamental reasons for which the code is so much lengthier are: 1) I have both symmetric as well as asymmetric lines in a system and 2) In order to maintain backward compatibility with the existing example cases (As you will observe, I had to go to lengths to split the data-frame into two parts and assign separate variables and constraint names so that things stay clean and correct. I could not find an easier way to do this. I'll highly appreciate any feedback on this).

We tested with @qluo0320github 's example cases and it seems the results are sensible (?) However, I still get discrepancies when I benchmark against an actually symmetric system versus a "simulated" symmetric system (in which the asymmetric lines have the same flow limits, loss percentages, and transmission buildout in both directions). I am attaching hereby all the relevant flow comparison
Flow_Comparisons.xlsx
result file (the names should be self-explanatory) here for you to take a look.

I scrutinized the code several times, but couldn't spot any flaw so far. I would appreciate if you could point some obvious bug (if at all) that I might have missed. Also, I would appreciate taking a look at the quadratic loss formulation. I believe I did it right, but am not totally certain. Thank you so much !!! I have also updated most of the doc pages; I will wrap up parts of the transmission.jl doc page and make another push to close this.

@sambuddhac sambuddhac marked this pull request as ready for review December 17, 2024 15:02
@sambuddhac sambuddhac changed the title Asymmetric line flow (Refined) #Work in Progress; READY FOR REVIEW !!! Asymmetric line flow (Refined); READY FOR REVIEW !!! Dec 18, 2024
Copy link
Contributor

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

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

Remaining comments which cannot be posted as a review comment to avoid GitHub Rate Limit

JuliaFormatter

[JuliaFormatter] reported by reviewdog 🐶

if setup["asymmetrical_trans_flow_limit"] ==1


[JuliaFormatter] reported by reviewdog 🐶

cMaxFlow_out_asym[l = 1:L_asym, t = 1:T], vFLOW[(l+L_sym), t] <= EP[:eAvail_Trans_Cap_Pos][l] #Change these with Auxiliary
cMaxFlow_in_asym[l = 1:L_asym, t = 1:T], vFLOW[(l+L_sym), t] >= -EP[:eAvail_Trans_Cap_Neg][l] #Change these with Auxiliary


[JuliaFormatter] reported by reviewdog 🐶

begin
cMaxFlow_out[l = 1:L, t = 1:T], vFLOW[l, t] <= EP[:eAvail_Trans_Cap][l]
cMaxFlow_in[l = 1:L, t = 1:T], vFLOW[l, t] >= -EP[:eAvail_Trans_Cap][l]
end)


[JuliaFormatter] reported by reviewdog 🐶


[JuliaFormatter] reported by reviewdog 🐶

if setup["asymmetrical_trans_flow_limit"] ==1


[JuliaFormatter] reported by reviewdog 🐶

inputs["pPercent_Loss_Pos"][l] * (vTAUX_POS_ASYM[l, t]) + inputs["pPercent_Loss_Neg"][l] * (vTAUX_NEG_ASYM[l, t])


[JuliaFormatter] reported by reviewdog 🐶

vTAUX_POS_ASYM[l, t] - vTAUX_NEG_ASYM[l, t] == vFLOW[(l+L_sym), t]


[JuliaFormatter] reported by reviewdog 🐶

vTAUX_POS_ASYM[l, t] + vTAUX_NEG_ASYM[l, t] <= min(EP[:eAvail_Trans_Cap_Pos][l], EP[:eAvail_Trans_Cap_Neg][l])


[JuliaFormatter] reported by reviewdog 🐶

vTAUX_NEG[l, t] <= EP[:eAvail_Trans_Cap][l] - vPROD_TRANSCAP_ON[l, t]


[JuliaFormatter] reported by reviewdog 🐶

vTAUX_NEG_ASYM[l, t] <= EP[:eAvail_Trans_Cap_Neg][l] - vPROD_TRANSCAP_ON_NEG_ASYM[l, t]


[JuliaFormatter] reported by reviewdog 🐶

vTAUX_POS_ASYM[l, t] <= EP[:eAvail_Trans_Cap_Pos][l] - vPROD_TRANSCAP_ON_POS_ASYM[l, t]


[JuliaFormatter] reported by reviewdog 🐶

(1 - vTAUX_POS_ON_POS_ASYM[l, t]) * inputs["pTrans_Max_Possible_Pos"][l]


[JuliaFormatter] reported by reviewdog 🐶

(1 - vTAUX_POS_ON_NEG_ASYM[l, t]) * inputs["pTrans_Max_Possible_Neg"][l]


[JuliaFormatter] reported by reviewdog 🐶

vTAUX_NEG[l, t] <= EP[:eAvail_Trans_Cap][l] - vPROD_TRANSCAP_ON[l, t]


[JuliaFormatter] reported by reviewdog 🐶

if setup["asymmetrical_trans_flow_limit"] ==1


[JuliaFormatter] reported by reviewdog 🐶

sum((2 * s - 1) * (inputs["pTrans_Max_Possible"][l] / TRANS_LOSS_SEGS) *
vTAUX_POS[l, s, t] for s in 1:TRANS_LOSS_SEGS)) +


[JuliaFormatter] reported by reviewdog 🐶

sum((2 * s - 1) * (inputs["pTrans_Max_Possible"][l] / TRANS_LOSS_SEGS) *
vTAUX_NEG[l, s, t] for s in 1:TRANS_LOSS_SEGS)))


[JuliaFormatter] reported by reviewdog 🐶

sum(vTAUX_POS[l, s, t] for s in 1:TRANS_LOSS_SEGS) - vTAUX_POS[l, 0, t] ==


[JuliaFormatter] reported by reviewdog 🐶

sum(vTAUX_NEG[l, s, t] for s in 1:TRANS_LOSS_SEGS) - vTAUX_NEG[l, 0, t] ==


[JuliaFormatter] reported by reviewdog 🐶

cTAuxOrderPos2[l in LOSS_LINES_SYM, s = 1:(TRANS_LOSS_SEGS - 1), t = 1:T],


[JuliaFormatter] reported by reviewdog 🐶

cTAuxOrderNeg2[l in LOSS_LINES_SYM, s = 1:(TRANS_LOSS_SEGS - 1), t = 1:T],


[JuliaFormatter] reported by reviewdog 🐶

sum((2 * s - 1) * (inputs["pTrans_Max_Possible_Pos"][l] / TRANS_LOSS_SEGS) *
vTAUX_POS_ASYM[l, s, t] for s in 1:TRANS_LOSS_SEGS)) +


[JuliaFormatter] reported by reviewdog 🐶

sum((2 * s - 1) * (inputs["pTrans_Max_Possible_Neg"][l] / TRANS_LOSS_SEGS) *
vTAUX_NEG_ASYM[l, s, t] for s in 1:TRANS_LOSS_SEGS)))


[JuliaFormatter] reported by reviewdog 🐶

sum(vTAUX_POS_ASYM[l, s, t] for s in 1:TRANS_LOSS_SEGS) - vTAUX_POS_ASYM[l, 0, t] ==
vFLOW[(l+L_sym), t]


[JuliaFormatter] reported by reviewdog 🐶

sum(vTAUX_NEG_ASYM[l, s, t] for s in 1:TRANS_LOSS_SEGS) - vTAUX_NEG_ASYM[l, 0, t] ==
-vFLOW[(l+L_sym), t]


[JuliaFormatter] reported by reviewdog 🐶

cTAuxMaxNeg_asym[l in LOSS_LINES_ASYM, s = 1:TRANS_LOSS_SEGS, t = 1:T],


[JuliaFormatter] reported by reviewdog 🐶

cTAuxOrderPos1_asym[l in LOSS_LINES_ASYM, s = 1:TRANS_LOSS_SEGS, t = 1:T],


[JuliaFormatter] reported by reviewdog 🐶

cTAuxOrderNeg1_asym[l in LOSS_LINES_ASYM, s = 1:TRANS_LOSS_SEGS, t = 1:T],


[JuliaFormatter] reported by reviewdog 🐶

cTAuxOrderPos2_asym[l in LOSS_LINES_ASYM, s = 1:(TRANS_LOSS_SEGS - 1), t = 1:T],


[JuliaFormatter] reported by reviewdog 🐶

cTAuxOrderNeg2_asym[l in LOSS_LINES_ASYM, s = 1:(TRANS_LOSS_SEGS - 1), t = 1:T],


[JuliaFormatter] reported by reviewdog 🐶

inputs["pTrans_Max_Possible_Pos"][l] * (1 - vTAUX_POS_ON_ASYM[l, 1, t])


[JuliaFormatter] reported by reviewdog 🐶

inputs["pTrans_Max_Possible_Neg"][l] * (1 - vTAUX_NEG_ON_ASYM[l, 1, t])


[JuliaFormatter] reported by reviewdog 🐶

sum((2 * s - 1) * (inputs["pTrans_Max_Possible"][l] / TRANS_LOSS_SEGS) *
vTAUX_POS[l, s, t] for s in 1:TRANS_LOSS_SEGS)) +


[JuliaFormatter] reported by reviewdog 🐶

sum((2 * s - 1) * (inputs["pTrans_Max_Possible"][l] / TRANS_LOSS_SEGS) *
vTAUX_NEG[l, s, t] for s in 1:TRANS_LOSS_SEGS)))


[JuliaFormatter] reported by reviewdog 🐶

sum(vTAUX_POS[l, s, t] for s in 1:TRANS_LOSS_SEGS) - vTAUX_POS[l, 0, t] ==


[JuliaFormatter] reported by reviewdog 🐶

sum(vTAUX_NEG[l, s, t] for s in 1:TRANS_LOSS_SEGS) - vTAUX_NEG[l, 0, t] ==


[JuliaFormatter] reported by reviewdog 🐶

cTAuxOrderPos2[l in LOSS_LINES, s = 1:(TRANS_LOSS_SEGS - 1), t = 1:T],


[JuliaFormatter] reported by reviewdog 🐶

cTAuxOrderNeg2[l in LOSS_LINES, s = 1:(TRANS_LOSS_SEGS - 1), t = 1:T],

Copy link
Contributor

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

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

Remaining comments which cannot be posted as a review comment to avoid GitHub Rate Limit

JuliaFormatter

[JuliaFormatter] reported by reviewdog 🐶

cTAuxOrderNeg2_asym[l in LOSS_LINES_ASYM, s = 1:(TRANS_LOSS_SEGS - 1), t = 1:T],


[JuliaFormatter] reported by reviewdog 🐶

inputs["pTrans_Max_Possible_Pos"][l] * (1 - vTAUX_POS_ON_ASYM[l, 1, t])


[JuliaFormatter] reported by reviewdog 🐶

inputs["pTrans_Max_Possible_Neg"][l] * (1 - vTAUX_NEG_ON_ASYM[l, 1, t])


[JuliaFormatter] reported by reviewdog 🐶

sum((2 * s - 1) * (inputs["pTrans_Max_Possible"][l] / TRANS_LOSS_SEGS) *
vTAUX_POS[l, s, t] for s in 1:TRANS_LOSS_SEGS)) +


[JuliaFormatter] reported by reviewdog 🐶

sum((2 * s - 1) * (inputs["pTrans_Max_Possible"][l] / TRANS_LOSS_SEGS) *
vTAUX_NEG[l, s, t] for s in 1:TRANS_LOSS_SEGS)))


[JuliaFormatter] reported by reviewdog 🐶

sum(vTAUX_POS[l, s, t] for s in 1:TRANS_LOSS_SEGS) - vTAUX_POS[l, 0, t] ==


[JuliaFormatter] reported by reviewdog 🐶

sum(vTAUX_NEG[l, s, t] for s in 1:TRANS_LOSS_SEGS) - vTAUX_NEG[l, 0, t] ==


[JuliaFormatter] reported by reviewdog 🐶

cTAuxOrderPos2[l in LOSS_LINES, s = 1:(TRANS_LOSS_SEGS - 1), t = 1:T],


[JuliaFormatter] reported by reviewdog 🐶

cTAuxOrderNeg2[l in LOSS_LINES, s = 1:(TRANS_LOSS_SEGS - 1), t = 1:T],

@GenXProject GenXProject modified the milestones: v0.4.2, v0.4.3 Jan 16, 2025
@lbonaldo lbonaldo force-pushed the asymmetric_line_flow branch from 1d3943a to 6fc5330 Compare January 17, 2025 15:11
Copy link
Collaborator

@lbonaldo lbonaldo left a comment

Choose a reason for hiding this comment

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

First round of review. Thanks @sambuddhac for this PR. In your opinion, which example case should we keep? The branch is now rebased with the latest develop.

sambuddhac and others added 17 commits January 6, 2026 12:41
…al flag is turned on but the corresponding columns are not provided in the Networks.csv
…xpansion lines in network load file to speed up computation
…ample cases to test multistage asymmetric builds
Add warning for potential issues with asymmetric flow in multistage capacity expansion.
@lbonaldo lbonaldo force-pushed the asymmetric_line_flow branch from 6e87ae1 to 5e7bdac Compare January 7, 2026 18:55
Copy link
Collaborator Author

@sambuddhac sambuddhac left a comment

Choose a reason for hiding this comment

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

Reviewed and approved !!!

@sambuddhac
Copy link
Collaborator Author

This now looks good. However, I cannot view the change requested @lbonaldo , as I mentioned earlier. Can you please let me know at your earliest convenience? Otherwise, now it looks all good. Can be merged. I also resolved one conflict on the CHANGELOG. Thanks !!!

Comment on lines +9 to +10
OverwriteResults: 1
AsymmetricalTransFlowLimit: 1 No newline at end of file
Copy link
Collaborator

@lbonaldo lbonaldo Jan 27, 2026

Choose a reason for hiding this comment

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

I probably wouldn't modify the precompile case. Do we have a specific reason for this change?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Thanks for the feedback, Luca. I think the reason I was doing it initially, is because I wasn't sure if the changes would impact the precompile. But, we can surely have the original precompile.

L = inputs["L"]

NetworkExpansion = setup["NetworkExpansion"]
MultiStage = setup["MultiStage"]
Copy link
Collaborator

Choose a reason for hiding this comment

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

Is this line being used?

Comment on lines +7 to +10
L_sym = inputs["L_sym"] # Number of transmission lines with symmetrical bidirectional flow
L_asym = inputs["L_asym"] #Default number of asymmetrical lines
# Number of lines in the network
L = L_sym + L_asym
Copy link
Collaborator

@lbonaldo lbonaldo Jan 27, 2026

Choose a reason for hiding this comment

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

Are L_sym and L_asym being used in other places other than at this line? If not, we could keep using L.

"PoliciesFolder" => "policies",
"ObjScale" => 1)
"ObjScale" => 1,
"AsymmetricalTransFlowLimit" => 0
Copy link
Collaborator

Choose a reason for hiding this comment

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

We need to update the documentation with this new settings key.

Copy link
Collaborator

@lbonaldo lbonaldo left a comment

Choose a reason for hiding this comment

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

Hi @sambuddhac, thank you for your recent changes to this PR. I’m doing a more comprehensive review, but in the meantime, I added a few more comments.
Do we want to keep all the new example cases? Right now we have 8 example cases for single stage, and 4 for multi-stage.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants