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

Maintain power factor constant on loads during slack distribution #170

Merged
merged 26 commits into from
Dec 1, 2020
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
f6b82b5
https://github.com/powsybl/powsybl-open-loadflow/issues/110#issuecomm…
frigaux Nov 17, 2020
757364e
Updates and fixes about Pull Request 170. Once run completed in Acloa…
frigaux Nov 18, 2020
1b500df
Checkstyle : fixed checkstyle errors
frigaux Nov 19, 2020
06b19e9
fixed checkstyle indentation error when running mvn validate
frigaux Nov 19, 2020
97e52bb
implement case : « BalanceType = PROPORTIONAL_TO_CONFORM_LOAD » et « …
frigaux Nov 23, 2020
c862ba3
fixed issue with java 11 (used while running Build OS ubuntu-latest ;…
frigaux Nov 23, 2020
f36e241
code style
frigaux Nov 24, 2020
b9cd0bc
Some simplifications and clarifications.
annetill Nov 24, 2020
9abfe0c
Rename method after review.
annetill Nov 24, 2020
ce468d1
Last misses : comment and log
frigaux Nov 24, 2020
2b890d6
Fix.
annetill Nov 24, 2020
5f6d9a4
Merge branch 'power_factor_constant' of https://github.com/powsybl/po…
annetill Nov 24, 2020
e9cf603
Add if for trace.
annetill Nov 24, 2020
64fbdd1
Fix.
annetill Nov 24, 2020
d0708d5
Remove isTraceEnabled at some places.
annetill Nov 25, 2020
9dd5da3
Merge branch 'master' into power_factor_constant
geofjamg Nov 26, 2020
88371cd
Fix authorship and copyright
geofjamg Nov 26, 2020
5bebe97
Merge branch 'master' into power_factor_constant
annetill Nov 27, 2020
c95d352
Fixes after review.
annetill Nov 27, 2020
e9aedff
fix code smell "Refactor this method to reduce its Cognitive Complexi…
frigaux Nov 27, 2020
671e350
Fix.
annetill Nov 30, 2020
8b25121
Power factor is on global P0 and Q0.
annetill Dec 1, 2020
8f16cc5
Merge branch 'master' into power_factor_constant
annetill Dec 1, 2020
a24750b
Merge branch 'power_factor_constant' of https://github.com/powsybl/po…
annetill Dec 1, 2020
ff60ee3
Simplification consecutive to previous commit (power factor on P0, Q0)
flo-dup Dec 1, 2020
d07e80b
Renaming: "constant" instead of "remains constant"
flo-dup Dec 1, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 19 additions & 6 deletions src/main/java/com/powsybl/openloadflow/OpenLoadFlowParameters.java
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ public enum LowImpedanceBranchMode {

private final List<AcLoadFlowObserver> additionalObservers = new ArrayList<>();

private boolean powerFactorConstant = POWER_FACTOR_CONSTANT_DEFAULT_VALUE;

@Override
public String getName() {
return "SimpleLoadFlowParameters";
Expand Down Expand Up @@ -87,6 +89,15 @@ public List<AcLoadFlowObserver> getAdditionalObservers() {
return additionalObservers;
}

public boolean isPowerFactorConstant() {
return powerFactorConstant;
}

public OpenLoadFlowParameters setPowerFactorConstant(boolean powerFactorConstant) {
this.powerFactorConstant = powerFactorConstant;
return this;
}

public static OpenLoadFlowParameters load() {
return new OpenLoadFlowConfigLoader().load(PlatformConfig.defaultConfig());
}
Expand All @@ -100,12 +111,14 @@ public OpenLoadFlowParameters load(PlatformConfig platformConfig) {

platformConfig.getOptionalModuleConfig("open-loadflow-default-parameters")
.ifPresent(config -> {
parameters.setSlackBusSelector(getSlackBusSelector(config));
parameters.setLowImpedanceBranchMode(config.getEnumProperty(LOW_IMPEDANCE_BRANCH_MODE_PARAM_NAME, LowImpedanceBranchMode.class, LOW_IMPEDANCE_BRANCH_MODE_DEFAULT_VALUE));
parameters.setVoltageRemoteControl(config.getBooleanProperty(VOLTAGE_REMOTE_CONTROLE_PARAM_NAME, VOLTAGE_REMOTE_CONTROLE_DEFAULT_VALUE));
parameters.setThrowsExceptionInCaseOfSlackDistributionFailure(
config.getBooleanProperty(THROWS_EXCEPTION_IN_CASE_OF_SLACK_DISTRIBUTION_FAILURE_PARAM_NAME, THROWS_EXCEPTION_IN_CASE_OF_SLACK_DISTRIBUTION_FAILURE_DEFAULT_VALUE)
);
parameters
.setSlackBusSelector(getSlackBusSelector(config))
.setLowImpedanceBranchMode(config.getEnumProperty(LOW_IMPEDANCE_BRANCH_MODE_PARAM_NAME, LowImpedanceBranchMode.class, LOW_IMPEDANCE_BRANCH_MODE_DEFAULT_VALUE))
.setVoltageRemoteControl(config.getBooleanProperty(VOLTAGE_REMOTE_CONTROLE_PARAM_NAME, VOLTAGE_REMOTE_CONTROLE_DEFAULT_VALUE))
.setThrowsExceptionInCaseOfSlackDistributionFailure(
config.getBooleanProperty(THROWS_EXCEPTION_IN_CASE_OF_SLACK_DISTRIBUTION_FAILURE_PARAM_NAME, THROWS_EXCEPTION_IN_CASE_OF_SLACK_DISTRIBUTION_FAILURE_DEFAULT_VALUE)
)
.setPowerFactorConstant(config.getBooleanProperty(POWER_FACTOR_CONSTANT_PARAM_NAME, VOLTAGE_REMOTE_CONTROLE_DEFAULT_VALUE));
});
return parameters;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ public static AcLoadFlowParameters createAcParameters(Network network, MatrixFac
LOGGER.info("Phase control: {}", parameters.isPhaseShifterRegulationOn());
LOGGER.info("Split shunt admittance: {}", parameters.isTwtSplitShuntAdmittance());
LOGGER.info("Direct current: {}", parameters.isDc());
LOGGER.info("Power factor constant: {}", parametersExt.isPowerFactorConstant());

List<OuterLoop> outerLoops = new ArrayList<>();
if (parameters.isDistributedSlack()) {
Expand All @@ -139,10 +140,10 @@ public static AcLoadFlowParameters createAcParameters(Network network, MatrixFac
outerLoops.add(new DistributedSlackOnGenerationOuterLoop(parametersExt.isThrowsExceptionInCaseOfSlackDistributionFailure()));
break;
case PROPORTIONAL_TO_LOAD:
outerLoops.add(new DistributedSlackOnLoadOuterLoop(parametersExt.isThrowsExceptionInCaseOfSlackDistributionFailure(), false));
outerLoops.add(new DistributedSlackOnLoadOuterLoop(parametersExt.isThrowsExceptionInCaseOfSlackDistributionFailure(), false, parametersExt.isPowerFactorConstant()));
break;
case PROPORTIONAL_TO_CONFORM_LOAD:
outerLoops.add(new DistributedSlackOnLoadOuterLoop(parametersExt.isThrowsExceptionInCaseOfSlackDistributionFailure(), true));
outerLoops.add(new DistributedSlackOnLoadOuterLoop(parametersExt.isThrowsExceptionInCaseOfSlackDistributionFailure(), true, parametersExt.isPowerFactorConstant()));
break;
case PROPORTIONAL_TO_GENERATION_P: // to be implemented.
throw new UnsupportedOperationException("Unsupported balance type mode: " + parameters.getBalanceType());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,12 @@ public class DistributedSlackOnLoadOuterLoop extends AbstractDistributedSlackOut
private static final Logger LOGGER = LoggerFactory.getLogger(DistributedSlackOnLoadOuterLoop.class);

private boolean distributedSlackOnConformLoad = false;
private boolean powerFactorConstant = false;
Copy link
Contributor

Choose a reason for hiding this comment

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

These two fields should be final?


public DistributedSlackOnLoadOuterLoop(boolean throwsExceptionInCaseOfFailure, boolean distributedSlackOnConformLoad) {
public DistributedSlackOnLoadOuterLoop(boolean throwsExceptionInCaseOfFailure, boolean distributedSlackOnConformLoad, boolean powerFactorConstant) {
super(throwsExceptionInCaseOfFailure);
this.distributedSlackOnConformLoad = distributedSlackOnConformLoad;
this.powerFactorConstant = powerFactorConstant;
}

@Override
Expand Down Expand Up @@ -63,24 +65,30 @@ public double run(List<ParticipatingElement<LfBus>> participatingElements, int i
LfBus bus = participatingBus.element;
double factor = participatingBus.factor;

double targetP = bus.getLoadTargetP();
double newTargetP = targetP - remainingMismatch * factor;
double loadTargetP = bus.getLoadTargetP();
double newLoadTargetP = loadTargetP - remainingMismatch * factor;

// We stop when the load produces power.
if (newTargetP <= 0) {
newTargetP = 0;
if (newLoadTargetP <= 0) {
newLoadTargetP = 0;
loadsAtMin++;
it.remove();
}

if (newTargetP != targetP) {
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Rescale '{}' active power target: {} -> {}",
bus.getId(), targetP * PerUnit.SB, newTargetP * PerUnit.SB);
if (newLoadTargetP != loadTargetP) {
LOGGER.trace("Rescale '{}' active power target: {} -> {}",
bus.getId(), loadTargetP * PerUnit.SB, newLoadTargetP * PerUnit.SB);
if (powerFactorConstant) { // https://github.com/powsybl/powsybl-open-loadflow/issues/110
Copy link
Contributor

Choose a reason for hiding this comment

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

I think a sentence to explain the purpose of this block of code would be more useful and convenient than a link to the issue lists.

double loadTargetQ = bus.getLoadTargetQ();
// keep power factor constant by using rule of three
double newLoadTargetQ = loadTargetQ * newLoadTargetP / loadTargetP;
LOGGER.trace("Rescale '{}' reactive power target on load: {} -> {}",
bus.getId(), loadTargetQ * PerUnit.SB, newLoadTargetQ * PerUnit.SB);
bus.setLoadTargetQ(newLoadTargetQ);
}

bus.setLoadTargetP(newTargetP);
done += targetP - newTargetP;
bus.setLoadTargetP(newLoadTargetP);
done += loadTargetP - newLoadTargetP;
modifiedBuses++;
}
}
Expand Down
2 changes: 2 additions & 0 deletions src/main/java/com/powsybl/openloadflow/network/LfBus.java
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ public interface LfBus {

double getLoadTargetQ();

void setLoadTargetQ(double loadTargetQ);

double getGenerationTargetP();

double getGenerationTargetQ();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ public abstract class AbstractLfBus implements LfBus {

protected int positiveLoadCount = 0;

protected double initialLoadTargetQ = 0;

protected double loadTargetQ = 0;

protected double generationTargetQ = 0;
Expand Down Expand Up @@ -216,6 +218,7 @@ private List<String> getGeneratorIds() {
void addLoad(Load load) {
loads.add(load);
initialLoadTargetP += load.getP0();
initialLoadTargetQ += load.getQ0();
loadTargetP += load.getP0();
LoadDetail loadDetail = load.getExtension(LoadDetail.class);
if (loadDetail != null) {
Expand All @@ -230,6 +233,7 @@ void addLoad(Load load) {
void addBattery(Battery battery) {
batteries.add(battery);
initialLoadTargetP += battery.getP0();
initialLoadTargetQ += battery.getQ0();
loadTargetP += battery.getP0();
loadTargetQ += battery.getQ0();
}
Expand Down Expand Up @@ -341,6 +345,11 @@ public double getLoadTargetQ() {
return loadTargetQ / PerUnit.SB;
}

@Override
public void setLoadTargetQ(double loadTargetQ) {
this.loadTargetQ = loadTargetQ * PerUnit.SB;
}

private double getLimitQ(ToDoubleFunction<LfGenerator> limitQ) {
return generators.stream()
.mapToDouble(generator -> generator.hasVoltageControl() ? limitQ.applyAsDouble(generator)
Expand Down Expand Up @@ -459,11 +468,12 @@ public void updateState(boolean reactiveLimits, boolean writeSlackBus) {
updateGeneratorsState(voltageControl ? calculatedQ + loadTargetQ : generationTargetQ, reactiveLimits);

// update load power
double factor = initialLoadTargetP != 0 ? loadTargetP / initialLoadTargetP : 1;
double factorP = initialLoadTargetP != 0 ? loadTargetP / initialLoadTargetP : 1;
double factorQ = initialLoadTargetQ != 0 ? loadTargetQ / initialLoadTargetQ : 1;
for (Load load : loads) {
load.getTerminal()
.setP(load.getP0() >= 0 ? factor * load.getP0() : load.getP0())
.setQ(load.getQ0());
.setP(load.getP0() >= 0 ? factorP * load.getP0() : load.getP0())
.setQ(load.getQ0() >= 0 ? factorQ * load.getQ0() : load.getQ0());
Comment on lines +485 to +486
Copy link
Contributor

Choose a reason for hiding this comment

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

@annetill: why do we distinguish positive and negative loads?

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 these tests are not useful, I have to check.

}

// update battery power (which are not part of slack distribution)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,8 @@ private void distributedMismatch(LfNetwork network, double mismatch, LoadFlowPar
case PROPORTIONAL_TO_LOAD:
case PROPORTIONAL_TO_CONFORM_LOAD:
DistributedSlackOnLoadOuterLoop onLoadOuterLoop = new DistributedSlackOnLoadOuterLoop(openLoadFlowParameters.isThrowsExceptionInCaseOfSlackDistributionFailure(),
loadFlowParameters.getBalanceType() == LoadFlowParameters.BalanceType.PROPORTIONAL_TO_CONFORM_LOAD);
loadFlowParameters.getBalanceType() == LoadFlowParameters.BalanceType.PROPORTIONAL_TO_CONFORM_LOAD,
openLoadFlowParameters.isPowerFactorConstant());
onLoadOuterLoop.run(onLoadOuterLoop.getParticipatingElements(network), -1, mismatch);
break;
case PROPORTIONAL_TO_GENERATION_P:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ public final class ParameterConstants {
public static final String LOW_IMPEDANCE_BRANCH_MODE_PARAM_NAME = "lowImpedanceBranchMode";
public static final LowImpedanceBranchMode LOW_IMPEDANCE_BRANCH_MODE_DEFAULT_VALUE = LowImpedanceBranchMode.REPLACE_BY_ZERO_IMPEDANCE_LINE;

public static final String POWER_FACTOR_CONSTANT_PARAM_NAME = "powerFactorConstant";
Copy link
Member

Choose a reason for hiding this comment

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

Do not forget to increase documentation. Our web site is here: https://github.com/powsybl/powsybl.github.io

Copy link
Contributor

Choose a reason for hiding this comment

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

Did you find the related page? it's that one: pages/documentation/simulation/powerflow/openlf.md

public static final boolean POWER_FACTOR_CONSTANT_DEFAULT_VALUE = false;

private ParameterConstants() {
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import com.powsybl.iidm.network.Load;
import com.powsybl.iidm.network.Network;
import com.powsybl.iidm.network.extensions.LoadDetailAdder;
import com.powsybl.iidm.network.test.EurostagTutorialExample1Factory;
import com.powsybl.loadflow.LoadFlow;
import com.powsybl.loadflow.LoadFlowParameters;
import com.powsybl.loadflow.LoadFlowResult;
Expand All @@ -20,7 +21,7 @@
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import static com.powsybl.openloadflow.util.LoadFlowAssert.assertActivePowerEquals;
import static com.powsybl.openloadflow.util.LoadFlowAssert.*;
import static org.junit.jupiter.api.Assertions.assertTrue;

/**
Expand All @@ -37,6 +38,7 @@ class DistributedSlackOnLoadTest {
private Load l6;
private LoadFlow.Runner loadFlowRunner;
private LoadFlowParameters parameters;
private OpenLoadFlowParameters parametersExt;

@BeforeEach
void setUp() {
Expand All @@ -49,8 +51,8 @@ void setUp() {
l6 = network.getLoad("l6");
loadFlowRunner = new LoadFlow.Runner(new OpenLoadFlowProvider(new DenseMatrixFactory()));
parameters = new LoadFlowParameters().setDistributedSlack(true)
.setBalanceType(LoadFlowParameters.BalanceType.PROPORTIONAL_TO_LOAD);
OpenLoadFlowParameters parametersExt = new OpenLoadFlowParameters()
.setBalanceType(LoadFlowParameters.BalanceType.PROPORTIONAL_TO_LOAD);
parametersExt = new OpenLoadFlowParameters()
.setSlackBusSelector(new MostMeshedSlackBusSelector());
parameters.addExtension(OpenLoadFlowParameters.class, parametersExt);
}
Expand Down Expand Up @@ -83,4 +85,24 @@ void testWithLoadDetail() {
assertActivePowerEquals(12.727, l5.getTerminal());
assertActivePowerEquals(-50, l6.getTerminal()); // same as p0 because p0 < 0
}

@Test
void testPowerFactorConstant() {
// given
parameters.setBalanceType(LoadFlowParameters.BalanceType.PROPORTIONAL_TO_CONFORM_LOAD);
Network networkWithoutPowerFactorConstant = EurostagTutorialExample1Factory.create();
Network networkWithPowerFactorConstant = EurostagTutorialExample1Factory.create();

// when
parametersExt.setPowerFactorConstant(false);
LoadFlowResult loadFlowResultWithoutPowerFactorConstant = loadFlowRunner.run(networkWithoutPowerFactorConstant, parameters);

parametersExt.setPowerFactorConstant(true);
LoadFlowResult loadFlowResultWithPowerFactorConstant = loadFlowRunner.run(networkWithPowerFactorConstant, parameters);

// then
assertPowerFactorNotConstant(networkWithoutPowerFactorConstant);
assertPowerFactorConstant(networkWithPowerFactorConstant);
assertBetterLoadFlowResults(loadFlowResultWithoutPowerFactorConstant, loadFlowResultWithPowerFactorConstant);
}
}
60 changes: 58 additions & 2 deletions src/test/java/com/powsybl/openloadflow/util/LoadFlowAssert.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,14 @@
package com.powsybl.openloadflow.util;

import com.powsybl.iidm.network.Bus;
import com.powsybl.iidm.network.Load;
import com.powsybl.iidm.network.Network;
import com.powsybl.iidm.network.Terminal;
import com.powsybl.loadflow.LoadFlowResult;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.util.Iterator;

import static org.junit.jupiter.api.Assertions.*;

/**
* @author Geoffroy Jamgotchian <geoffroy.jamgotchian at rte-france.com>
Expand Down Expand Up @@ -47,4 +51,56 @@ public static void assertUndefinedActivePower(Terminal terminal) {
public static void assertUndefinedReactivePower(Terminal terminal) {
assertTrue(Double.isNaN(terminal.getQ()));
}

private static void assertPowerFactor(Network network, boolean isPowerFactorConstant) {
Iterator<Load> loads = network.getLoads().iterator();
while (loads.hasNext()) {
Load load = loads.next();
load.getTerminal().getQ();
if (isPowerFactorConstant) {
assertEquals(Math.round(1000000 * load.getP0() / load.getQ0()),
Math.round(1000000 * load.getTerminal().getP() / load.getTerminal().getQ()),
"power factor should be a constant value");
} else {
assertNotEquals(Math.round(1000000 * load.getP0() / load.getQ0()),
Math.round(1000000 * load.getTerminal().getP() / load.getTerminal().getQ()),
"power factor should not be a constant value");
}
}

}

public static void assertPowerFactorNotConstant(Network network) {
assertPowerFactor(network, false);
}

public static void assertPowerFactorConstant(Network network) {
assertPowerFactor(network, true);
}

public static void assertBetterLoadFlowResults(LoadFlowResult loadFlowResult, LoadFlowResult loadFlowResultBetter) {
assertTrue(loadFlowResult.isOk(), "results should be ok");
assertTrue(loadFlowResultBetter.isOk(), "results should be ok");
assertEquals(loadFlowResult.getComponentResults().size(),
loadFlowResultBetter.getComponentResults().size(),
"results should have same subnetwork count");
Iterator<LoadFlowResult.ComponentResult> componentResultIterator = loadFlowResult.getComponentResults().iterator();
Iterator<LoadFlowResult.ComponentResult> componentResultIteratorBetter = loadFlowResultBetter.getComponentResults().iterator();
// loop over sub networks
while (componentResultIterator.hasNext()) {
LoadFlowResult.ComponentResult componentResult = componentResultIterator.next();
LoadFlowResult.ComponentResult componentResultBetter = componentResultIteratorBetter.next();
assertEquals(componentResult.getComponentNum(),
componentResultBetter.getComponentNum(),
"this assert has a bug, please fix it");
assertEquals(componentResult.getSlackBusId(),
componentResultBetter.getSlackBusId(),
"this assert has a bug, please fix it");
assertEquals(componentResult.getStatus(),
componentResultBetter.getStatus(),
"status results should be the same");
assertTrue(componentResult.getIterationCount() >= componentResultBetter.getIterationCount(), "iteration count should be the same or lower for improved result");
assertTrue(Math.abs(componentResult.getSlackBusActivePowerMismatch()) >= Math.abs(componentResultBetter.getSlackBusActivePowerMismatch()), "mismatch should be the same or lower for improved result");
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

As @annetill said, I'm not sure to understand this assessment. From my point of view, you should assert that the results are the expected one, not that the results are closed to the other one

}