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

Adding SOC extended DistFlow (BFM) formulation #229

Merged
merged 21 commits into from
Apr 6, 2018
Merged

Adding SOC extended DistFlow (BFM) formulation #229

merged 21 commits into from
Apr 6, 2018

Conversation

frederikgeth
Copy link
Collaborator

I'm working on an implementation of the extended DistFlow formulation.

Before I continue, I'm wondering what you think of the following issues:

  • Adding a line index i to constraint_voltage_angle_difference(pm, n, *i*, f_bus, t_bus, buspair["angmin"], buspair["angmax"])
  • Name of the formulation, as it uses W variables but not WR/WI but squared current magnitude instead. Currently it is named AbstractWIForm, to refer to the 'W' voltage variables and current variables 'I', but I don't think it is an ideal name.
  • Place in the type hierarchy: AbstractWForms = Union{AbstractWRForms, AbstractWIForm}
  • As it is a BFM, one equation defines both the to and from side active/reactive power flow. So the call to constraint_ohms_yt_to(pm, i) in this formulation does nothing. Should the problem definitions be changed, where a call constraint_ohms(pm, i) for BIM-type models itself calls constraint_ohms_yt_from(pm, i) and constraint_ohms_yt_to(pm, i)?
  • The line power equations are prepared with support for asymmetric line shunts and shunt conductance.
  • There's still something wrong with constraint_voltage_angle_difference though, as the test case 24 (with SAD) returns an objective value which is too low, I'll take a deeper look hopefully sometime the coming week.

any other comments are welcome of course :)

Copy link
Member

@ccoffrin ccoffrin left a comment

Choose a reason for hiding this comment

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

Looks like a good start. Detailed comments to follow.



"variable: `0 <= i[l] <= (Imax)^2` for `l` in `branch`es"
function variable_series_current_magnitude_sqr(pm::GenericPowerModel, n::Int=pm.cnw; bounded = true)
Copy link
Member

Choose a reason for hiding this comment

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

I don't think you need this constraint. You can move this implementation into this shared variable space,

https://github.com/lanl-ansi/PowerModels.jl/blob/master/src/form/wr.jl#L399

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

ok, great approach, hadn't noticed this before :)

src/form/wi.jl Outdated
"""
Creates Ohms constraints (yt post fix indicates that Y and T values are in rectangular form)
"""
function constraint_ohms_yt_from(pm::GenericPowerModel{T}, n::Int, f_bus, t_bus, f_idx, t_idx, g, b, c, tr, ti, tm) where T <: AbstractWIForm
Copy link
Member

Choose a reason for hiding this comment

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

I agree this does not make a lot of sense. I think this formulation needs a new OPF formulation that better reflect its construction.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

ok, I agree, made a proposal that still allows you to use BIM formulations in the BFM problem type and vice-versa.

src/form/wi.jl Outdated
w_fr = pm.var[:nw][n][:w][f_bus]
w_to = pm.var[:nw][n][:w][t_bus]
l = f_idx[1]
i = pm.var[:nw][n][:i][l]
Copy link
Member

Choose a reason for hiding this comment

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

Have a look at the QC model for variable naming conventions. I have been using cm so far.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

ok, cm it is.

@ccoffrin
Copy link
Member

Based on your recommendation lets adopt the name BranchFlow (i.e. bf) for this variant of the model.

Because the equations in the base formulation are quite different, I think we need to add a new problem name for this variant of the model, I am thinking opf_bf, pf_bf and so on. The primary differences will be the addition of branch current variables and different constraints that are stated on the branches; these should be called something like constraint_power_losses and constraint_voltage_magnitude_difference. In this case, we can re-use the existing formulation names (for example SOCWR and ACP) for different variants of this new problem, which will make re-using the shared functions simple.

Concerning constraint_voltage_angle_difference and constraint_voltage_magnitude_difference, for consistency we should make both of them branch-wise constraints, similar to https://github.com/lanl-ansi/PowerModels.jl/blob/master/src/core/constraint_template.jl#L316. This means passing in arc_from in addition to f_bus and t_bus.

Concerning, the inconsistency on test case 24. My guess is that it is due to the fact that the BF formulation does not implement this constraint, https://github.com/lanl-ansi/PowerModels.jl/blob/master/src/form/wr.jl#L516 To the best of my knowledge, the constraint has never been projected into the BF space. I would be happy to do the derivation, in due course. For now I would confirm that this is the issue and then integrate the case 24 test with a different objective value.

@codecov
Copy link

codecov bot commented Mar 26, 2018

Codecov Report

Merging #229 into master will increase coverage by 0.21%.
The diff coverage is 97.87%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #229      +/-   ##
==========================================
+ Coverage   93.53%   93.74%   +0.21%     
==========================================
  Files          36       39       +3     
  Lines        4115     4335     +220     
==========================================
+ Hits         3849     4064     +215     
- Misses        266      271       +5
Impacted Files Coverage Δ
src/form/wr.jl 99.43% <ø> (ø) ⬆️
src/PowerModels.jl 100% <ø> (ø) ⬆️
src/form/acp.jl 39.49% <ø> (ø) ⬆️
src/form/acr.jl 95.58% <ø> (ø) ⬆️
src/form/shared.jl 100% <ø> (ø) ⬆️
src/core/constraint.jl 92.5% <0%> (-2.38%) ⬇️
src/core/constraint_template.jl 93.35% <100%> (+0.85%) ⬆️
src/form/act.jl 100% <100%> (ø) ⬆️
src/form/df.jl 100% <100%> (ø)
test/opf.jl 100% <100%> (ø) ⬆️
... and 9 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update b33773e...fe44804. Read the comment docs.

@frederikgeth
Copy link
Collaborator Author

Thank you very much for your feedback. Further commits forthcoming.

I'll make the opf_bf, pf_bfproblem types. The suggested name constraint_power_losses makes a lot of sense. However, I'm not sure the formulation itself should be called bf as this is just an example of a BFM formulation. I'm partial to DistFlow (the nonconvex quadratic one in p, q, vm), convexified DistFlow (the SOC one in p, q, w, (cm)^2), linearized DistFlow (LP in p, q, w). What do you think? How would you abbreviate?

Concerning constraint_voltage_angle_difference and constraint_voltage_magnitude_difference, I think the passing arc_from is a good solution.

I will confirm soon that the difference between the current SOC-BIM and SOC-BFM is due to the missing lifted nonlinear cuts. For now I changed the objective value in the SOC-BFM tests.

frederikgeth added 2 commits March 26, 2018 14:48
- new problem type
- code for using BFM in opf and BIM in opf_bf
- new tests
@frederikgeth
Copy link
Collaborator Author

Updated the naming of the current variable, now also documented here for future reference. Is this what you expect cfr #26?

opf_pf is now defined, including some code for compatibility of formulations between opfand opf_bfin shared. pf_bfis still a todo.

The results of SOCWR and DistFlow for opf and opf_bf are not yet consistent for case 24, even after playing with inclusion/exclusion of constraint_voltage_angle_difference and cut_complex_product_and_angle_difference, I'll need to dig deeper to figure this out, sometime later this week.

@ccoffrin
Copy link
Member

Concerning the problem name. We need a generic problem name which will then take different forms. As an example, the abstract problem opf_xyz will become DistFlow with APowerModel, ConvexDistFlow with BPowerModel, and LinDistFlow with CPowerModel.

I am inclined to call the abstract problem as opf_bf (for branch flow) because it sounds more formulation agnostic to me than DistFlow, but I am open to other proposals.

The variable name docs looks good to me. I like the cc notation for current magnitude squared. It is more consistent with standard.

@frederikgeth
Copy link
Collaborator Author

frederikgeth commented Mar 26, 2018

Ok, great, let me confirm. So, the problem types are named opf_bfand pf_bf, with corresponding filenames and function names.

Currently, the convex relaxation of the (balanced) DistFlow formulation (shorthand DF) is type SOCDFPowerModel, contained in df.jl. If we eventually implement the nonconvex formulation it could be called DFPowerModel and the linearized version could be LinDFPowerModel.

The BFM-equivalent constraints of BIM-style constraint_ohms_yt_from and constraint_ohms_yt_to are currently conceived as:

  • constraint_branch_flow_losses: defining the relationship between p_fr, p_to and the total line loss (and equivalent for q)
  • constraint_branch_kvl: defining the relationship between the complex voltages at the from and the to side, whether in normal (complex) variables, or squared variables
  • constraint_branch_current: defining how the branch current relates to the (complex) power flow and the (complex) voltage variables

Copy link
Member

@ccoffrin ccoffrin left a comment

Choose a reason for hiding this comment

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

Looking better, comments inline.

constraint_branch_kvl(pm, i)
constraint_branch_current(pm, i)

#constraint_voltage_angle_difference(pm, i)
Copy link
Member

Choose a reason for hiding this comment

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

Why is this commented out?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

forgot to remove after trying to find the source of the issue with case24 optimality BIM vs BFM

function post_opf_bf(pm::GenericPowerModel)
variable_voltage(pm)
variable_generation(pm)
variable_branch_flow(pm)
Copy link
Member

Choose a reason for hiding this comment

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

We should add branch current variables as well, right?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

current is also a flow variable, so I had put the initialization of the current variables at the same level as the calls to the active and reactive power initialization. will be addressed

end

for i in ids(pm, :branch)
constraint_branch_flow_losses(pm, i)
Copy link
Member

Choose a reason for hiding this comment

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

constraint_branch feels redundant given that losses are only defined on branches. How about constraint_flow_losses?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

ok


for i in ids(pm, :branch)
constraint_branch_flow_losses(pm, i)
constraint_branch_kvl(pm, i)
Copy link
Member

Choose a reason for hiding this comment

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

kvl is a property of cycles on the network, correct? I don't see how it connects to this constraint. I think voltage_magnitude_difference is accurate and consistent with the constraints already defined.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Maybe it should refer to Ohm's law, as it relates two voltages through impedance. But that may create confusion w.r.t. BIM-style OPF problem formulation.

for i in ids(pm, :branch)
constraint_branch_flow_losses(pm, i)
constraint_branch_kvl(pm, i)
constraint_branch_current(pm, i)
Copy link
Member

Choose a reason for hiding this comment

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

This is probably the exception to the rule. Here I think it makes sense to keep branch explicit, because there are so many possibilities for different currents.

Also I will have to think about how to unify this with constraint_voltage, but I will leave that for future issue that is outside the scope of this PR.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

ok


objective_min_fuel_cost(pm)

constraint_voltage(pm)
Copy link
Member

Choose a reason for hiding this comment

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

It is not immediately clear to me if this is needed in problem definition. It might help you to comment it out for now.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

ok, removed

# https://docs.julialang.org/en/release-0.6/manual/style-guide/#Avoid-strange-type-Unions-1
# and should be used with discretion.
#
# If you are about to add a union type,
# first double check if a different type hierarchy can resolve the issue
# instead.
#
AbstractBIMForms = Union{AbstractACPForm, AbstractACTForm, AbstractDCPForm, AbstractWRForm, AbstractWRMForm}
Copy link
Member

Choose a reason for hiding this comment

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

Note that type unions are discouraged in Julia. So for now, I would recommend removing this collection and simply say that the opf_bf problem does not yet support these forms and defining new forms just for BFMs.

Later on after this PR, I will consider unification of both forms.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

ok, unification code removed

@@ -439,11 +439,12 @@ function constraint_voltage_angle_difference(pm::GenericPowerModel, n::Int, i::I
branch = ref(pm, n, :branch, i)
f_bus = branch["f_bus"]
t_bus = branch["t_bus"]
arc_from = (i, f_bus, t_bus)
pair = (f_bus, t_bus)
buspair = ref(pm, n, :buspairs, pair)

if buspair["branch"] == i
Copy link
Member

Choose a reason for hiding this comment

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

This might also be the issue of inconsistent on case 24. You might be to post this constraint for all branches in the BFM models.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

In the end, this was not the problem, just a typo in the DistFlow equation for constraint_voltage_angle_difference

@frederikgeth
Copy link
Collaborator Author

Results are now identical between SOCWRForm and SOCDFForm, for both opf and pf problem types, including for case24. Unit tests are added for opf_bf and pf_bf for SOCWRForm and problem definition documentation is updated.

Copy link
Member

@ccoffrin ccoffrin left a comment

Choose a reason for hiding this comment

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

We are close now. Proposed a few ways to further simplify things and a few questions about the math.

src/form/df.jl Outdated
end

""
function variable_branch_flow(pm::GenericPowerModel{T}, n::Int=pm.cnw; kwargs...) where T <: AbstractDFForm
Copy link
Member

Choose a reason for hiding this comment

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

I think this function can be omitted. The most generic version works for all GenericPowerModels.

https://github.com/lanl-ansi/PowerModels.jl/blob/master/src/core/variable.jl#L223

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

indeed

src/form/df.jl Outdated
end

"do nothing, this model does not have complex voltage constraints"
function constraint_voltage(pm::GenericPowerModel{T}, n::Int) where T <: AbstractDFForm
Copy link
Member

Choose a reason for hiding this comment

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

This implementation can be provided without any constraint on T and can be placed in core/constraint.jl

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

ok


#define series flow expressions to simplify Ohm's law
p_fr_s = p_fr - g_sh_fr*(w_fr/tm^2)
q_fr_s = q_fr + b_sh_fr*(w_fr/tm^2)
Copy link
Member

Choose a reason for hiding this comment

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

It's not immediately obvious to me that this is correct. Did you double check? Until we have an asymmetrical network test this will not be checked by unit tests.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

The derivation goes as follows. Branches are modeled with an ideal transformer and a pi-section in series.

As the ideal transformer is located at the from side, the voltage after the transformer, i.e. at the from side of the pi-element following it, is actually (w_fr/tm^2). Furthermore, as this transformer is ideal, it is lossless. Moreover, as we'll be doing the DistFlow derivation, which performs the angle relaxation, transformer phase shift does not influence the power flow (except for constraint_voltage_angle_difference.)

We observe that a a branch's power flow balance with asymmetrical shunts is composed of three loss contributions: p_fr + p_to = p_sh_loss_fr + p_s_loss + p_sh_loss_to, q_fr + q_to = q_sh_loss_fr + q_s_loss + q_sh_loss_to, where x_sh_loss_fr, x_sh_loss_to are the to from and to side shunt losses, and x_s_loss is the series flow loss. We can further define the flow only through the series impedance as p_fr_s + p_to_s = p_s_loss, q_fr_s + q_to_s = q_s_loss.

The pi-section loss terms, expressed in the w and ccm variables therefore are:

  • p_sh_loss_fr = g_sh_fr*(w_fr/tm^2)
  • q_sh_loss_fr = -b_sh_fr*(w_fr/tm^2)
  • p_s = r*ccm
  • p_s = x*ccm
  • p_sh_loss_to = g_sh_to*(w_to)
  • q_sh_loss_to = -b_sh_to*(w_to)

Ohm's law only relates the voltage magnitude and the series current and series impedance of the pi-element. Therefore, after performing the DistFlow derivation (v_j = v_i - z_ij *I_ij_s, with RHS and LHS multiplied by their complex conjugated) and the subsititution of the squared node voltage magnitude, (with w and squared branch series current magnitude, with ccm), you obtain expressions in the series complex power flow variables p_fr_s, q_fr_s. Furthermore, in these variables p_fr_s^2 +q_fr_s^2 == (w_fr/tm^2)*ccm is a valid expression, which is then relaxed.

I can add this somewhere in the documentation.

I haven't found the time to rederive constraint_voltage_angle_difference to confirm its current implementation though.


#define series flow expressions to simplify constraint
p_fr_s = p_fr - g_sh_fr*(w_fr/tm^2)
q_fr_s = q_fr + b_sh_fr*(w_fr/tm^2)
Copy link
Member

Choose a reason for hiding this comment

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

Same as above, it's not immediately obvious to me that this is correct. Did you double check? Especially because in my derivation the shunt value did not occur in this constraint.



"variable: `0 <= i[l] <= (Imax)^2` for `l` in `branch`es"
function variable_branch_series_current_magnitude_sqr(pm::GenericPowerModel, n::Int=pm.cnw; bounded = true)
Copy link
Member

Choose a reason for hiding this comment

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

Can we replace this function with the one that is already defined here, https://github.com/lanl-ansi/PowerModels.jl/blob/master/src/form/wr.jl#L399? If so, that function can move to core/variable.jl because it is generally applicable.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

These constraints have different meaning: bounding series current in this BFM derivation vs bounding total current magnitude in QC. Anyway, I updated the series current upper bound with a compensation term for the current contribution of the shunts.


## DistFlow derivation

### For an asymmetric pi section
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

here's the derivation, @ccoffrin

@ccoffrin
Copy link
Member

The implementation looks reasonable. I would like to understand the math a bit better before we merge this in. Can we setup a VC to go over it?

@ccoffrin
Copy link
Member

@frederikgeth, fixed merge conflict so that travis would run.

@ccoffrin
Copy link
Member

ccoffrin commented Apr 3, 2018

@frederikgeth seems there are still a few updates needed to bring thus up to date with master.

@ccoffrin ccoffrin added this to the v0.6.0 milestone Apr 6, 2018
@ccoffrin ccoffrin merged commit 57c3299 into lanl-ansi:master Apr 6, 2018
@ccoffrin
Copy link
Member

ccoffrin commented Apr 6, 2018

Thanks!

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.

2 participants