-
Notifications
You must be signed in to change notification settings - Fork 7
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
[WIP] Area Interchange Control as OuterLoop #1055
base: main
Are you sure you want to change the base?
Conversation
91829f9
to
7bbd807
Compare
Signed-off-by: mguibert <marine.guibert@artelys.com>
7bbd807
to
08e2260
Compare
…e Control Signed-off-by: vmouradian <valentin.mouradian@artelys.com>
Signed-off-by: vmouradian <valentin.mouradian@artelys.com>
Signed-off-by: vmouradian <valentin.mouradian@artelys.com>
Signed-off-by: vmouradian <valentin.mouradian@artelys.com>
Signed-off-by: vmouradian <valentin.mouradian@artelys.com>
Signed-off-by: vmouradian <valentin.mouradian@artelys.com>
Signed-off-by: vmouradian <valentin.mouradian@artelys.com>
Signed-off-by: vmouradian <valentin.mouradian@artelys.com>
Signed-off-by: vmouradian <valentin.mouradian@artelys.com>
@@ -618,6 +630,24 @@ public boolean isVoltagePerReactivePowerControl() { | |||
return voltagePerReactivePowerControl; | |||
} | |||
|
|||
public boolean isAreaInterchangeControl() { |
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.
Move all these new methods above isVoltagePerReactivePowerControl, as isVoltagePerReactivePowerControl and setVoltagePerReactivePowerControl should remain next to each other
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.
Mutliple commits changed this, last one is 42bfe28 and this is fixed now
@@ -1639,6 +1677,7 @@ static LfNetworkParameters getNetworkParameters(LoadFlowParameters parameters, O | |||
.setUseLoadModel(parametersExt.isUseLoadModel()) | |||
.setSimulateAutomationSystems(parametersExt.isSimulateAutomationSystems()) | |||
.setReferenceBusSelector(ReferenceBusSelector.fromMode(parametersExt.getReferenceBusSelectionMode())) | |||
.setAreaInterchangeControlAreaType(parametersExt.getAreaInterchangeControlAreaType()) |
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.
Add the line below above this one:
.setAreaInterchangeControl(parametersExt.isAreaInterchangeControl())
Also, both new lines should probably be mmoved just above the setTransformerVoltageControl call? (Everywhere else, the AIC new parameters/getter/setters are added next to it)
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.
current practice is to put new parameters at the bottom
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.
changed in 743827b
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.
Good to know, thanks!
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.
changed in 743827b
I see you moved the line to follow Damien's instructions but you didn't add the line I asked for.
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.
src/main/java/com/powsybl/openloadflow/network/LfControlArea.java
Outdated
Show resolved
Hide resolved
src/main/java/com/powsybl/openloadflow/network/impl/LfControlAreaImpl.java
Outdated
Show resolved
Hide resolved
src/main/java/com/powsybl/openloadflow/network/impl/LfNetworkLoaderImpl.java
Outdated
Show resolved
Hide resolved
src/main/java/com/powsybl/openloadflow/network/impl/LfNetworkLoaderImpl.java
Outdated
Show resolved
Hide resolved
import com.powsybl.openloadflow.network.BoundaryFactory; | ||
import org.junit.jupiter.api.Test; | ||
|
||
class AICTests { |
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.
Rename to AreaInterchangeControlTest
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.
change in 63eb397
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.
Almost: you wrote TestS instead of Test
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.
😅 fixed in e83f8af
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.
rename to LfArea
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.
renamed in 743827b
src/main/java/com/powsybl/openloadflow/OpenLoadFlowParameters.java
Outdated
Show resolved
Hide resolved
updateControlAreaBoundaryP(branch.getTerminal1(), loadingContext, lfBranch::getP1); | ||
updateControlAreaBoundaryP(branch.getTerminal2(), loadingContext, lfBranch::getP2); |
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.
update
is not the right term, add
instead ?
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.
src/test/java/com/powsybl/openloadflow/ac/AreaInterchangeControlTests.java
Outdated
Show resolved
Hide resolved
Signed-off-by: vmouradian <valentin.mouradian@artelys.com>
Signed-off-by: vmouradian <valentin.mouradian@artelys.com>
return this; | ||
} | ||
|
||
public OpenLoadFlowParameters setVoltagePerReactivePowerControl(boolean voltagePerReactivePowerControl) { |
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.
@vmouradian it looks like you moved this function by error
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.
😅 oups. Changed in 5a29ee9
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.
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.
Do not remember the last commit on this but the diff seems ok now
src/main/java/com/powsybl/openloadflow/network/impl/LfNetworkLoaderImpl.java
Outdated
Show resolved
Hide resolved
src/main/java/com/powsybl/openloadflow/network/impl/LfNetworkLoaderImpl.java
Outdated
Show resolved
Hide resolved
src/main/java/com/powsybl/openloadflow/network/impl/LfNetworkLoaderImpl.java
Outdated
Show resolved
Hide resolved
c4db184
to
26da6ec
Compare
Signed-off-by: vmouradian <valentin.mouradian@artelys.com>
26da6ec
to
5a29ee9
Compare
Signed-off-by: vmouradian <valentin.mouradian@artelys.com>
Signed-off-by: vmouradian <valentin.mouradian@artelys.com>
Signed-off-by: vmouradian <valentin.mouradian@artelys.com>
Signed-off-by: vmouradian <valentin.mouradian@artelys.com>
Signed-off-by: vmouradian <valentin.mouradian@artelys.com>
Signed-off-by: vmouradian <valentin.mouradian@artelys.com>
Signed-off-by: vmouradian <valentin.mouradian@artelys.com>
Signed-off-by: vmouradian <valentin.mouradian@artelys.com>
Signed-off-by: Damien Jeandemange <damien.jeandemange@artelys.com>
@@ -19,13 +21,27 @@ | |||
*/ | |||
abstract class AbstractAcOuterLoopConfig implements AcOuterLoopConfig { |
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.
ExplicitAcOuterLoopConfig
needs also to be modified to include new AreaInterchangeControl OL
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.
I would keep this one unchanged, and make another one extending it specifically for AIC, containing also the details of distributed power per area
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.
@jeandemanged I agree, and this makes me think that we should change AcLoadFlowResult to have distributed active power per area. Is that also what you were thinking about ?
void addBus(LfBus bus); | ||
|
||
void addBoundaryP(Supplier<Evaluable> p); |
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.
addBus and addBoundaryP should not be part of LfArea interface, this is only internal to LfNetworkLoaderImpl
double getSlackInjection(double slackBusActivePowerMismatch); | ||
|
||
void addExternalBusSlackParticipationFactor(LfBus bus, double shareFactor); | ||
|
||
/** | ||
* Some buses are not in the Area, but their slack should be considered for the slack of the Area | ||
* (This happens for example when a bus is connected to multiple Areas but the flow through the bus is not considered for those areas' interchange power flow). | ||
* The slack of this buses can need to be shared with other Areas with a factor for each area. | ||
* @return A map of the external buses considered for the slack of the Area with the share factor of the Area | ||
*/ | ||
Map<LfBus, Double> getExternalBusesSlackParticipationFactors(); |
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.
should not be part of LfArea interface, this is internal to AIC outerloop
src/main/java/com/powsybl/openloadflow/ac/outerloop/AreaInterchangeControlOuterloop.java
Outdated
Show resolved
Hide resolved
|
||
private Map<LfBus, Double> externalBusesSlackParticipationFactors = new HashMap<>(); | ||
|
||
public LfAreaImpl(Area area, LfNetwork network, LfNetworkParameters parameters) { |
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.
protected
@Override | ||
public void addBus(LfBus bus) { | ||
buses.add(bus); | ||
} | ||
|
||
@Override | ||
public void addBoundaryP(Supplier<Evaluable> getP) { | ||
boundariesP.add(getP); | ||
} |
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.
buses and boundaries should be part of constructor/create
@Override | ||
public double getSlackInjection(double slackBusActivePowerMismatch) { | ||
int totalSlackBusCount = (int) getNetwork().getSlackBuses().stream().count(); | ||
int areaSlackBusCount = (int) getBuses().stream().filter(LfBus::isSlack).count(); | ||
double areaExternalSlackBusShare = getExternalBusesSlackParticipationFactors().entrySet().stream().filter(entry -> entry.getKey().isSlack()).mapToDouble(Map.Entry::getValue).sum(); | ||
return totalSlackBusCount == 0 ? 0.0 : slackBusActivePowerMismatch * (areaSlackBusCount + areaExternalSlackBusShare) / totalSlackBusCount; | ||
} | ||
|
||
@Override | ||
public void addExternalBusSlackParticipationFactor(LfBus bus, double shareFactor) { | ||
if (bus != null) { | ||
externalBusesSlackParticipationFactors.put(bus, shareFactor); | ||
} | ||
} | ||
|
||
@Override | ||
public Map<LfBus, Double> getExternalBusesSlackParticipationFactors() { | ||
return externalBusesSlackParticipationFactors; | ||
} |
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.
this logic should not be here, but in the AIC outerloop
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.
to be revised so that LfArea-s are created once with all buses and boundaries without being mutated further, there should not be any addBus or addBoundary method in LfArea or LfAreaImpl
also need to include LfArea to LfNetworkLoaderPostProcessor with a new method
void onAreaAdded(Object element, LfArea lfArea);
List<LfBus> handledBuses = lfNetwork.getAreas().stream().flatMap(area -> | ||
area.getBuses().stream()) | ||
.toList(); | ||
List<LfBus> unhandledBuses = lfNetwork.getBuses().stream().filter(b -> !handledBuses.contains(b)).toList(); |
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.
performance issue here, especially the .filter(b -> !handledBuses.contains(b))
because handledBuses is a List.
changing to a Set could be an option, but we can see here that we need in LfBus a method like
Optional<LfArea> getLfArea()
// If the flow through this bus is considered for the interchange of some of the connected areas, | ||
// then it has already been added to the Area's externalBusesSlackParticipationFactors map with a factor 0.0 | ||
// Here we want to share the slack injection of this bus between the areas that are not considering the flow through this bus for their interchange power flow | ||
Set<LfArea> areasSharingSlack = connectedAreas.stream().filter(area -> !area.getExternalBusesSlackParticipationFactors().containsKey(unhandledBus)).collect(Collectors.toSet()); | ||
if (!areasSharingSlack.isEmpty()) { | ||
areasSharingSlack.forEach(area -> area.addExternalBusSlackParticipationFactor(unhandledBus, 1.0 / areasSharingSlack.size())); | ||
LOGGER.info("Bus {} is not in any Area and is connected to Areas: {} but the flow through this bus is not considered for their interchange flow. For a correct balancing, its slack injection will be shared between those areas", unhandledBus.getId(), connectedAreas.stream().map(LfArea::getId).toList()); | ||
} |
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.
this, and probably the entire method, should be moved outside LfNetworkLoader to be AIC outerloop code (e.g. in init
part)
static void checkDuplicatedAreas(List<LfNetwork> lfNetworks) { | ||
List<String> duplicatedAreas = lfNetworks.stream() | ||
.flatMap(lfNetwork -> lfNetwork.getAreas().stream()) | ||
.collect(Collectors.groupingBy(LfArea::getId, Collectors.counting())) | ||
.entrySet().stream() | ||
.filter(e -> e.getValue() > 1) | ||
.map(Map.Entry::getKey) | ||
.toList(); | ||
if (!duplicatedAreas.isEmpty()) { | ||
throw new PowsyblException("Areas with ids " + duplicatedAreas + " are present in more than one LfNetwork. Load flow computation with area interchange control is not supported in this case."); | ||
} | ||
} |
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.
with this, in practice, you are going to throw for all real case networks which always have small portions here and there.
The correct check is verifying that each area has all its boundaries are in the same LfNetwork.
Also, should not throw, just warn
double distributedActivePower = areaActivePowerMismatch - remainingMismatch; | ||
totalDistributedActivePower += distributedActivePower; | ||
movedBuses |= result.movedBuses(); | ||
totalIterations += result.iteration(); |
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.
I don' think this sum has anything meaningful, only the value per area is meaningful.
public interface LfArea extends PropertyBag { | ||
String getId(); | ||
|
||
double getInterchangeTarget(); |
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.
please prepare also a setter, would be used later on when we will implement area actions
Signed-off-by: vmouradian <valentin.mouradian@artelys.com>
Co-authored-by: jeandemanged <damien.jeandemange@artelys.com> Signed-off-by: Valentin Mouradian <144696437+vmouradian@users.noreply.github.com>
|
Signed-off-by: vmouradian <valentin.mouradian@artelys.com>
Signed-off-by: vmouradian <valentin.mouradian@artelys.com>
…l outerloop Signed-off-by: vmouradian <valentin.mouradian@artelys.com>
Please check if the PR fulfills these requirements
Does this PR already have an issue describing the problem?
Fixes #978
Does this PR introduce a breaking change or deprecate an API?