diff --git a/src/main/java/com/powsybl/openloadflow/OpenLoadFlowParameters.java b/src/main/java/com/powsybl/openloadflow/OpenLoadFlowParameters.java index 2d337e5fa0..1475616a7a 100644 --- a/src/main/java/com/powsybl/openloadflow/OpenLoadFlowParameters.java +++ b/src/main/java/com/powsybl/openloadflow/OpenLoadFlowParameters.java @@ -120,6 +120,13 @@ public enum SlackDistributionFailureBehavior { protected static final double GENERATOR_VOLTAGE_CONTROL_MIN_NOMINAL_VOLTAGE_DEFAULT_VALUE = -1d; + public enum FictitiousGeneratorVoltageControlMode { + ALWAYS, + NORMAL + }; + + protected static final FictitiousGeneratorVoltageControlMode FICTITIOUS_GENERATOR_VOLTAGE_CONTROL_MODE_DEFAULT_VALUE = FictitiousGeneratorVoltageControlMode.ALWAYS; + public static final String SLACK_BUS_SELECTION_MODE_PARAM_NAME = "slackBusSelectionMode"; public static final String SLACK_BUSES_IDS_PARAM_NAME = "slackBusesIds"; @@ -252,7 +259,9 @@ public enum SlackDistributionFailureBehavior { public static final String GENERATOR_VOLTAGE_CONTROL_MIN_NOMINAL_VOLTAGE_PARAM_NAME = "generatorVoltageControlMinNominalVoltage"; - private static > List getEnumPossibleValues(Class enumClass) { + public static final String FICTITIOUS_GENERATOR_VOLTAGE_CONTROL_MODE = "fictitiousGeneratorVoltageControlMode"; + + public static > List getEnumPossibleValues(Class enumClass) { return EnumSet.allOf(enumClass).stream().map(Enum::name).collect(Collectors.toList()); } @@ -322,7 +331,8 @@ private static > List getEnumPossibleValues(Class e new Parameter(REFERENCE_BUS_SELECTION_MODE_PARAM_NAME, ParameterType.STRING, "Reference bus selection mode", ReferenceBusSelector.DEFAULT_MODE.name(), getEnumPossibleValues(ReferenceBusSelectionMode.class)), new Parameter(WRITE_REFERENCE_TERMINALS_PARAM_NAME, ParameterType.BOOLEAN, "Write Reference Terminals", WRITE_REFERENCE_TERMINALS_DEFAULT_VALUE), new Parameter(VOLTAGE_TARGET_PRIORITIES_PARAM_NAME, ParameterType.STRING_LIST, "Voltage target priorities for voltage controls", LfNetworkParameters.VOLTAGE_CONTROL_PRIORITIES_DEFAULT_VALUE, getEnumPossibleValues(VoltageControl.Type.class)), - new Parameter(GENERATOR_VOLTAGE_CONTROL_MIN_NOMINAL_VOLTAGE_PARAM_NAME, ParameterType.DOUBLE, "Nominal voltage under which generator voltage controls are disabled during transformer voltage control outer loop of mode AFTER_GENERATOR_VOLTAGE_CONTROL, < 0 means automatic detection", OpenLoadFlowParameters.GENERATOR_VOLTAGE_CONTROL_MIN_NOMINAL_VOLTAGE_DEFAULT_VALUE) + new Parameter(GENERATOR_VOLTAGE_CONTROL_MIN_NOMINAL_VOLTAGE_PARAM_NAME, ParameterType.DOUBLE, "Nominal voltage under which generator voltage controls are disabled during transformer voltage control outer loop of mode AFTER_GENERATOR_VOLTAGE_CONTROL, < 0 means automatic detection", OpenLoadFlowParameters.GENERATOR_VOLTAGE_CONTROL_MIN_NOMINAL_VOLTAGE_DEFAULT_VALUE), + new Parameter(FICTITIOUS_GENERATOR_VOLTAGE_CONTROL_MODE, ParameterType.STRING, "Specificies how fictitious generators can voltage. Possible modes are 'always' and 'normal'. 'always', the default, means that voltage is controlled even if targetP is outside of minP and maxP.", OpenLoadFlowParameters.FICTITIOUS_GENERATOR_VOLTAGE_CONTROL_MODE_DEFAULT_VALUE.name(), getEnumPossibleValues(FictitiousGeneratorVoltageControlMode.class)) ); public enum VoltageInitModeOverride { @@ -496,6 +506,8 @@ public enum ReactiveRangeCheckMode { private double generatorVoltageControlMinNominalVoltage = GENERATOR_VOLTAGE_CONTROL_MIN_NOMINAL_VOLTAGE_DEFAULT_VALUE; + private FictitiousGeneratorVoltageControlMode fictitiousGeneratorVoltageControlMode = FICTITIOUS_GENERATOR_VOLTAGE_CONTROL_MODE_DEFAULT_VALUE; + public static double checkParameterValue(double parameterValue, boolean condition, String parameterName) { if (!condition) { throw new IllegalArgumentException("Invalid value for parameter " + parameterName + ": " + parameterValue); @@ -1174,6 +1186,15 @@ public double getGeneratorVoltageControlMinNominalVoltage() { return generatorVoltageControlMinNominalVoltage; } + public FictitiousGeneratorVoltageControlMode getFictitiousGeneratorVoltageControlMode() { + return fictitiousGeneratorVoltageControlMode; + } + + public OpenLoadFlowParameters setFictitiousGeneratorVoltageControlMode(FictitiousGeneratorVoltageControlMode fictitiousGeneratorVoltageControlMode) { + this.fictitiousGeneratorVoltageControlMode = Objects.requireNonNull(fictitiousGeneratorVoltageControlMode); + return this; + } + public static OpenLoadFlowParameters load() { return load(PlatformConfig.defaultConfig()); } @@ -1399,6 +1420,8 @@ public OpenLoadFlowParameters update(Map properties) { .ifPresent(prop -> this.setVoltageTargetPriorities(parseStringListProp(prop))); Optional.ofNullable(properties.get(GENERATOR_VOLTAGE_CONTROL_MIN_NOMINAL_VOLTAGE_PARAM_NAME)) .ifPresent(prop -> this.setGeneratorVoltageControlMinNominalVoltage(Double.parseDouble(prop))); + Optional.ofNullable(properties.get(FICTITIOUS_GENERATOR_VOLTAGE_CONTROL_MODE)) + .ifPresent(prop -> this.setFictitiousGeneratorVoltageControlMode(FictitiousGeneratorVoltageControlMode.valueOf(prop))); return this; } @@ -1470,6 +1493,7 @@ public Map toMap() { map.put(WRITE_REFERENCE_TERMINALS_PARAM_NAME, writeReferenceTerminals); map.put(VOLTAGE_TARGET_PRIORITIES_PARAM_NAME, voltageTargetPriorities); map.put(GENERATOR_VOLTAGE_CONTROL_MIN_NOMINAL_VOLTAGE_PARAM_NAME, generatorVoltageControlMinNominalVoltage); + map.put(FICTITIOUS_GENERATOR_VOLTAGE_CONTROL_MODE, fictitiousGeneratorVoltageControlMode); return map; } @@ -1597,7 +1621,8 @@ static LfNetworkParameters getNetworkParameters(LoadFlowParameters parameters, O .setUseLoadModel(parametersExt.isUseLoadModel()) .setSimulateAutomationSystems(parametersExt.isSimulateAutomationSystems()) .setReferenceBusSelector(ReferenceBusSelector.fromMode(parametersExt.getReferenceBusSelectionMode())) - .setVoltageTargetPriorities(parametersExt.getVoltageTargetPriorities()); + .setVoltageTargetPriorities(parametersExt.getVoltageTargetPriorities()) + .setFictitiousGeneratorVoltageControlMode(parametersExt.getFictitiousGeneratorVoltageControlMode()); } public static AcLoadFlowParameters createAcParameters(Network network, LoadFlowParameters parameters, OpenLoadFlowParameters parametersExt, @@ -1845,7 +1870,8 @@ public static boolean equals(LoadFlowParameters parameters1, LoadFlowParameters extension1.getMaxSusceptanceMismatch() == extension2.getMaxSusceptanceMismatch() && extension1.getNewtonRaphsonStoppingCriteriaType() == extension2.getNewtonRaphsonStoppingCriteriaType() && Objects.equals(extension1.getVoltageTargetPriorities(), extension2.getVoltageTargetPriorities()) && - extension1.getGeneratorVoltageControlMinNominalVoltage() == extension2.getGeneratorVoltageControlMinNominalVoltage(); + extension1.getGeneratorVoltageControlMinNominalVoltage() == extension2.getGeneratorVoltageControlMinNominalVoltage() && + extension1.getFictitiousGeneratorVoltageControlMode() == extension2.getFictitiousGeneratorVoltageControlMode(); } public static LoadFlowParameters clone(LoadFlowParameters parameters) { @@ -1936,7 +1962,8 @@ public static LoadFlowParameters clone(LoadFlowParameters parameters) { .setNewtonRaphsonStoppingCriteriaType(extension.getNewtonRaphsonStoppingCriteriaType()) .setReferenceBusSelectionMode(extension.getReferenceBusSelectionMode()) .setVoltageTargetPriorities(extension.getVoltageTargetPriorities()) - .setGeneratorVoltageControlMinNominalVoltage(extension.getGeneratorVoltageControlMinNominalVoltage()); + .setGeneratorVoltageControlMinNominalVoltage(extension.getGeneratorVoltageControlMinNominalVoltage()) + .setFictitiousGeneratorVoltageControlMode(extension.getFictitiousGeneratorVoltageControlMode()); if (extension2 != null) { parameters2.addExtension(OpenLoadFlowParameters.class, extension2); diff --git a/src/main/java/com/powsybl/openloadflow/network/LfNetworkParameters.java b/src/main/java/com/powsybl/openloadflow/network/LfNetworkParameters.java index cdb1500147..0042f7ad4f 100644 --- a/src/main/java/com/powsybl/openloadflow/network/LfNetworkParameters.java +++ b/src/main/java/com/powsybl/openloadflow/network/LfNetworkParameters.java @@ -138,6 +138,8 @@ public class LfNetworkParameters { private List voltageTargetPriorities = VOLTAGE_CONTROL_PRIORITIES_DEFAULT_VALUE; + private OpenLoadFlowParameters.FictitiousGeneratorVoltageControlMode fictitiousGeneratorVoltageControlMode = OpenLoadFlowParameters.FictitiousGeneratorVoltageControlMode.ALWAYS; + public LfNetworkParameters() { } @@ -181,6 +183,7 @@ public LfNetworkParameters(LfNetworkParameters other) { this.simulateAutomationSystems = other.simulateAutomationSystems; this.referenceBusSelector = other.referenceBusSelector; this.voltageTargetPriorities = new ArrayList<>(other.voltageTargetPriorities); + this.fictitiousGeneratorVoltageControlMode = other.fictitiousGeneratorVoltageControlMode; } public SlackBusSelector getSlackBusSelector() { @@ -420,6 +423,15 @@ public LfNetworkParameters setReactiveRangeCheckMode(OpenLoadFlowParameters.Reac return this; } + public OpenLoadFlowParameters.FictitiousGeneratorVoltageControlMode getFictitiousGeneratorVoltageControlMode() { + return fictitiousGeneratorVoltageControlMode; + } + + public LfNetworkParameters setFictitiousGeneratorVoltageControlMode(OpenLoadFlowParameters.FictitiousGeneratorVoltageControlMode fictitiousGeneratorVoltageControlMode) { + this.fictitiousGeneratorVoltageControlMode = fictitiousGeneratorVoltageControlMode; + return this; + } + public boolean isSvcVoltageMonitoring() { return svcVoltageMonitoring; } @@ -595,6 +607,7 @@ public String toString() { ", simulateAutomationSystems=" + simulateAutomationSystems + ", referenceBusSelector=" + referenceBusSelector.getClass().getSimpleName() + ", voltageTargetPriorities=" + voltageTargetPriorities + + ", fictitiousGeneratorVoltageControlMode" + fictitiousGeneratorVoltageControlMode + ')'; } } diff --git a/src/main/java/com/powsybl/openloadflow/network/impl/LfGeneratorImpl.java b/src/main/java/com/powsybl/openloadflow/network/impl/LfGeneratorImpl.java index c621fa8401..f3dd80b15e 100644 --- a/src/main/java/com/powsybl/openloadflow/network/impl/LfGeneratorImpl.java +++ b/src/main/java/com/powsybl/openloadflow/network/impl/LfGeneratorImpl.java @@ -11,6 +11,7 @@ import com.powsybl.iidm.network.Generator; import com.powsybl.iidm.network.ReactiveLimits; import com.powsybl.iidm.network.extensions.*; +import com.powsybl.openloadflow.OpenLoadFlowParameters; import com.powsybl.openloadflow.network.LfAsymGenerator; import com.powsybl.openloadflow.network.LfNetwork; import com.powsybl.openloadflow.network.LfNetworkParameters; @@ -40,9 +41,12 @@ public final class LfGeneratorImpl extends AbstractLfGenerator { private Double qPercent; + private final boolean voltageControlAlways; + private LfGeneratorImpl(Generator generator, LfNetwork network, LfNetworkParameters parameters, LfNetworkLoadingReport report) { super(network, generator.getTargetP() / PerUnit.SB); this.generatorRef = Ref.create(generator, parameters.isCacheEnabled()); + voltageControlAlways = generator.isFictitious() && parameters.getFictitiousGeneratorVoltageControlMode() == OpenLoadFlowParameters.FictitiousGeneratorVoltageControlMode.ALWAYS; participating = true; droop = DEFAULT_DROOP; @@ -217,14 +221,14 @@ public void updateState(LfNetworkStateUpdateParameters parameters) { @Override protected boolean checkIfGeneratorStartedForVoltageControl(LfNetworkLoadingReport report) { - return getGenerator().isFictitious() ? + return voltageControlAlways ? true : super.checkIfGeneratorStartedForVoltageControl(report); } @Override protected boolean checkIfGeneratorIsInsideActivePowerLimitsForVoltageControl(LfNetworkParameters parameters, LfNetworkLoadingReport report) { - return getGenerator().isFictitious() ? + return voltageControlAlways ? true : super.checkIfGeneratorIsInsideActivePowerLimitsForVoltageControl(parameters, report); } diff --git a/src/test/java/com/powsybl/openloadflow/OpenLoadFlowParametersTest.java b/src/test/java/com/powsybl/openloadflow/OpenLoadFlowParametersTest.java index 166ee44393..ff311d32b3 100644 --- a/src/test/java/com/powsybl/openloadflow/OpenLoadFlowParametersTest.java +++ b/src/test/java/com/powsybl/openloadflow/OpenLoadFlowParametersTest.java @@ -384,7 +384,7 @@ void testCloneParameters() { @Test void testToString() { OpenLoadFlowParameters parameters = new OpenLoadFlowParameters(); - assertEquals("OpenLoadFlowParameters(slackBusSelectionMode=MOST_MESHED, slackBusesIds=[], slackDistributionFailureBehavior=LEAVE_ON_SLACK_BUS, voltageRemoteControl=true, lowImpedanceBranchMode=REPLACE_BY_ZERO_IMPEDANCE_LINE, loadPowerFactorConstant=false, plausibleActivePowerLimit=5000.0, newtonRaphsonStoppingCriteriaType=UNIFORM_CRITERIA, slackBusPMaxMismatch=1.0, maxActivePowerMismatch=0.01, maxReactivePowerMismatch=0.01, maxVoltageMismatch=1.0E-4, maxAngleMismatch=1.0E-5, maxRatioMismatch=1.0E-5, maxSusceptanceMismatch=1.0E-4, voltagePerReactivePowerControl=false, generatorReactivePowerRemoteControl=false, transformerReactivePowerControl=false, maxNewtonRaphsonIterations=15, maxOuterLoopIterations=20, newtonRaphsonConvEpsPerEq=1.0E-4, voltageInitModeOverride=NONE, transformerVoltageControlMode=WITH_GENERATOR_VOLTAGE_CONTROL, shuntVoltageControlMode=WITH_GENERATOR_VOLTAGE_CONTROL, minPlausibleTargetVoltage=0.8, maxPlausibleTargetVoltage=1.2, minRealisticVoltage=0.5, maxRealisticVoltage=2.0, reactiveRangeCheckMode=MAX, lowImpedanceThreshold=1.0E-8, networkCacheEnabled=false, svcVoltageMonitoring=true, stateVectorScalingMode=NONE, maxSlackBusCount=1, debugDir=null, incrementalTransformerRatioTapControlOuterLoopMaxTapShift=3, secondaryVoltageControl=false, reactiveLimitsMaxPqPvSwitch=3, phaseShifterControlMode=CONTINUOUS_WITH_DISCRETISATION, alwaysUpdateNetwork=false, mostMeshedSlackBusSelectorMaxNominalVoltagePercentile=95.0, reportedFeatures=[], slackBusCountryFilter=[], actionableSwitchesIds=[], actionableTransformersIds=[], asymmetrical=false, minNominalVoltageTargetVoltageCheck=20.0, reactivePowerDispatchMode=Q_EQUAL_PROPORTION, outerLoopNames=null, useActiveLimits=true, disableVoltageControlOfGeneratorsOutsideActivePowerLimits=false, lineSearchStateVectorScalingMaxIteration=10, lineSearchStateVectorScalingStepFold=1.3333333333333333, maxVoltageChangeStateVectorScalingMaxDv=0.1, maxVoltageChangeStateVectorScalingMaxDphi=0.17453292519943295, linePerUnitMode=IMPEDANCE, useLoadModel=false, dcApproximationType=IGNORE_R, simulateAutomationSystems=false, acSolverType=NEWTON_RAPHSON, maxNewtonKrylovIterations=100, newtonKrylovLineSearch=false, referenceBusSelectionMode=FIRST_SLACK, writeReferenceTerminals=true, voltageTargetPriorities=[GENERATOR, TRANSFORMER, SHUNT], generatorVoltageControlMinNominalVoltage=-1.0)", + assertEquals("OpenLoadFlowParameters(slackBusSelectionMode=MOST_MESHED, slackBusesIds=[], slackDistributionFailureBehavior=LEAVE_ON_SLACK_BUS, voltageRemoteControl=true, lowImpedanceBranchMode=REPLACE_BY_ZERO_IMPEDANCE_LINE, loadPowerFactorConstant=false, plausibleActivePowerLimit=5000.0, newtonRaphsonStoppingCriteriaType=UNIFORM_CRITERIA, slackBusPMaxMismatch=1.0, maxActivePowerMismatch=0.01, maxReactivePowerMismatch=0.01, maxVoltageMismatch=1.0E-4, maxAngleMismatch=1.0E-5, maxRatioMismatch=1.0E-5, maxSusceptanceMismatch=1.0E-4, voltagePerReactivePowerControl=false, generatorReactivePowerRemoteControl=false, transformerReactivePowerControl=false, maxNewtonRaphsonIterations=15, maxOuterLoopIterations=20, newtonRaphsonConvEpsPerEq=1.0E-4, voltageInitModeOverride=NONE, transformerVoltageControlMode=WITH_GENERATOR_VOLTAGE_CONTROL, shuntVoltageControlMode=WITH_GENERATOR_VOLTAGE_CONTROL, minPlausibleTargetVoltage=0.8, maxPlausibleTargetVoltage=1.2, minRealisticVoltage=0.5, maxRealisticVoltage=2.0, reactiveRangeCheckMode=MAX, lowImpedanceThreshold=1.0E-8, networkCacheEnabled=false, svcVoltageMonitoring=true, stateVectorScalingMode=NONE, maxSlackBusCount=1, debugDir=null, incrementalTransformerRatioTapControlOuterLoopMaxTapShift=3, secondaryVoltageControl=false, reactiveLimitsMaxPqPvSwitch=3, phaseShifterControlMode=CONTINUOUS_WITH_DISCRETISATION, alwaysUpdateNetwork=false, mostMeshedSlackBusSelectorMaxNominalVoltagePercentile=95.0, reportedFeatures=[], slackBusCountryFilter=[], actionableSwitchesIds=[], actionableTransformersIds=[], asymmetrical=false, minNominalVoltageTargetVoltageCheck=20.0, reactivePowerDispatchMode=Q_EQUAL_PROPORTION, outerLoopNames=null, useActiveLimits=true, disableVoltageControlOfGeneratorsOutsideActivePowerLimits=false, lineSearchStateVectorScalingMaxIteration=10, lineSearchStateVectorScalingStepFold=1.3333333333333333, maxVoltageChangeStateVectorScalingMaxDv=0.1, maxVoltageChangeStateVectorScalingMaxDphi=0.17453292519943295, linePerUnitMode=IMPEDANCE, useLoadModel=false, dcApproximationType=IGNORE_R, simulateAutomationSystems=false, acSolverType=NEWTON_RAPHSON, maxNewtonKrylovIterations=100, newtonKrylovLineSearch=false, referenceBusSelectionMode=FIRST_SLACK, writeReferenceTerminals=true, voltageTargetPriorities=[GENERATOR, TRANSFORMER, SHUNT], generatorVoltageControlMinNominalVoltage=-1.0, fictitiousGeneratorVoltageControlMode=ALWAYS)", parameters.toString()); } diff --git a/src/test/java/com/powsybl/openloadflow/OpenLoadFlowProviderTest.java b/src/test/java/com/powsybl/openloadflow/OpenLoadFlowProviderTest.java index 762f4d34a9..0b23cfd444 100644 --- a/src/test/java/com/powsybl/openloadflow/OpenLoadFlowProviderTest.java +++ b/src/test/java/com/powsybl/openloadflow/OpenLoadFlowProviderTest.java @@ -51,7 +51,7 @@ void test() { void testDcParameters() { Network network = Mockito.mock(Network.class); DcLoadFlowParameters dcParameters = OpenLoadFlowParameters.createDcParameters(network, new LoadFlowParameters().setReadSlackBus(true), new OpenLoadFlowParameters(), new DenseMatrixFactory(), new EvenShiloachGraphDecrementalConnectivityFactory<>(), true); - assertEquals("DcLoadFlowParameters(networkParameters=LfNetworkParameters(slackBusSelector=NetworkSlackBusSelector, connectivityFactory=EvenShiloachGraphDecrementalConnectivityFactory, generatorVoltageRemoteControl=false, minImpedance=false, twtSplitShuntAdmittance=false, breakers=false, plausibleActivePowerLimit=5000.0, computeMainConnectedComponentOnly=true, countriesToBalance=[], distributedOnConformLoad=false, phaseControl=false, transformerVoltageControl=false, voltagePerReactivePowerControl=false, generatorReactivePowerRemoteControl=false, transformerReactivePowerControl=false, loadFlowModel=DC, reactiveLimits=false, hvdcAcEmulation=true, minPlausibleTargetVoltage=0.8, maxPlausibleTargetVoltage=1.2, loaderPostProcessorSelection=[], reactiveRangeCheckMode=MAX, lowImpedanceThreshold=1.0E-8, svcVoltageMonitoring=false, maxSlackBusCount=1, debugDir=null, secondaryVoltageControl=false, cacheEnabled=false, asymmetrical=false, minNominalVoltageTargetVoltageCheck=20.0, linePerUnitMode=IMPEDANCE, useLoadModel=false, simulateAutomationSystems=false, referenceBusSelector=ReferenceBusFirstSlackSelector, voltageTargetPriorities=[GENERATOR, TRANSFORMER, SHUNT]), equationSystemCreationParameters=DcEquationSystemCreationParameters(updateFlows=true, forcePhaseControlOffAndAddAngle1Var=true, useTransformerRatio=true, dcApproximationType=IGNORE_R), matrixFactory=DenseMatrixFactory, distributedSlack=true, balanceType=PROPORTIONAL_TO_GENERATION_P_MAX, setVToNan=true, maxOuterLoopIterations=20)", + assertEquals("DcLoadFlowParameters(networkParameters=LfNetworkParameters(slackBusSelector=NetworkSlackBusSelector, connectivityFactory=EvenShiloachGraphDecrementalConnectivityFactory, generatorVoltageRemoteControl=false, minImpedance=false, twtSplitShuntAdmittance=false, breakers=false, plausibleActivePowerLimit=5000.0, computeMainConnectedComponentOnly=true, countriesToBalance=[], distributedOnConformLoad=false, phaseControl=false, transformerVoltageControl=false, voltagePerReactivePowerControl=false, generatorReactivePowerRemoteControl=false, transformerReactivePowerControl=false, loadFlowModel=DC, reactiveLimits=false, hvdcAcEmulation=true, minPlausibleTargetVoltage=0.8, maxPlausibleTargetVoltage=1.2, loaderPostProcessorSelection=[], reactiveRangeCheckMode=MAX, lowImpedanceThreshold=1.0E-8, svcVoltageMonitoring=false, maxSlackBusCount=1, debugDir=null, secondaryVoltageControl=false, cacheEnabled=false, asymmetrical=false, minNominalVoltageTargetVoltageCheck=20.0, linePerUnitMode=IMPEDANCE, useLoadModel=false, simulateAutomationSystems=false, referenceBusSelector=ReferenceBusFirstSlackSelector, voltageTargetPriorities=[GENERATOR, TRANSFORMER, SHUNT], fictitiousGeneratorVoltageControlModeALWAYS), equationSystemCreationParameters=DcEquationSystemCreationParameters(updateFlows=true, forcePhaseControlOffAndAddAngle1Var=true, useTransformerRatio=true, dcApproximationType=IGNORE_R), matrixFactory=DenseMatrixFactory, distributedSlack=true, balanceType=PROPORTIONAL_TO_GENERATION_P_MAX, setVToNan=true, maxOuterLoopIterations=20)", dcParameters.toString()); } @@ -59,7 +59,7 @@ void testDcParameters() { void testAcParameters() { Network network = Mockito.mock(Network.class); AcLoadFlowParameters acParameters = OpenLoadFlowParameters.createAcParameters(network, new LoadFlowParameters().setReadSlackBus(true), new OpenLoadFlowParameters(), new DenseMatrixFactory(), new EvenShiloachGraphDecrementalConnectivityFactory<>(), false, false); - assertEquals("AcLoadFlowParameters(networkParameters=LfNetworkParameters(slackBusSelector=NetworkSlackBusSelector, connectivityFactory=EvenShiloachGraphDecrementalConnectivityFactory, generatorVoltageRemoteControl=true, minImpedance=false, twtSplitShuntAdmittance=false, breakers=false, plausibleActivePowerLimit=5000.0, computeMainConnectedComponentOnly=true, countriesToBalance=[], distributedOnConformLoad=false, phaseControl=false, transformerVoltageControl=false, voltagePerReactivePowerControl=false, generatorReactivePowerRemoteControl=false, transformerReactivePowerControl=false, loadFlowModel=AC, reactiveLimits=true, hvdcAcEmulation=true, minPlausibleTargetVoltage=0.8, maxPlausibleTargetVoltage=1.2, loaderPostProcessorSelection=[], reactiveRangeCheckMode=MAX, lowImpedanceThreshold=1.0E-8, svcVoltageMonitoring=true, maxSlackBusCount=1, debugDir=null, secondaryVoltageControl=false, cacheEnabled=false, asymmetrical=false, minNominalVoltageTargetVoltageCheck=20.0, linePerUnitMode=IMPEDANCE, useLoadModel=false, simulateAutomationSystems=false, referenceBusSelector=ReferenceBusFirstSlackSelector, voltageTargetPriorities=[GENERATOR, TRANSFORMER, SHUNT]), equationSystemCreationParameters=AcEquationSystemCreationParameters(forceA1Var=false), newtonRaphsonParameters=NewtonRaphsonParameters(maxIterations=15, minRealisticVoltage=0.5, maxRealisticVoltage=2.0, stoppingCriteria=DefaultNewtonRaphsonStoppingCriteria, stateVectorScalingMode=NONE, alwaysUpdateNetwork=false, lineSearchStateVectorScalingMaxIteration=10, lineSearchStateVectorScalingStepFold=1.3333333333333333, maxVoltageChangeStateVectorScalingMaxDv=0.1, maxVoltageChangeStateVectorScalingMaxDphi=0.17453292519943295), newtonKrylovParameters=NewtonKrylovParameters(maxIterations=100, lineSearch=false), outerLoops=[DistributedSlackOuterLoop, MonitoringVoltageOuterLoop, ReactiveLimitsOuterLoop], maxOuterLoopIterations=20, matrixFactory=DenseMatrixFactory, voltageInitializer=UniformValueVoltageInitializer, asymmetrical=false, slackDistributionFailureBehavior=LEAVE_ON_SLACK_BUS, solverFactory=NewtonRaphsonFactory, detailedReport=false)", + assertEquals("AcLoadFlowParameters(networkParameters=LfNetworkParameters(slackBusSelector=NetworkSlackBusSelector, connectivityFactory=EvenShiloachGraphDecrementalConnectivityFactory, generatorVoltageRemoteControl=true, minImpedance=false, twtSplitShuntAdmittance=false, breakers=false, plausibleActivePowerLimit=5000.0, computeMainConnectedComponentOnly=true, countriesToBalance=[], distributedOnConformLoad=false, phaseControl=false, transformerVoltageControl=false, voltagePerReactivePowerControl=false, generatorReactivePowerRemoteControl=false, transformerReactivePowerControl=false, loadFlowModel=AC, reactiveLimits=true, hvdcAcEmulation=true, minPlausibleTargetVoltage=0.8, maxPlausibleTargetVoltage=1.2, loaderPostProcessorSelection=[], reactiveRangeCheckMode=MAX, lowImpedanceThreshold=1.0E-8, svcVoltageMonitoring=true, maxSlackBusCount=1, debugDir=null, secondaryVoltageControl=false, cacheEnabled=false, asymmetrical=false, minNominalVoltageTargetVoltageCheck=20.0, linePerUnitMode=IMPEDANCE, useLoadModel=false, simulateAutomationSystems=false, referenceBusSelector=ReferenceBusFirstSlackSelector, voltageTargetPriorities=[GENERATOR, TRANSFORMER, SHUNT], fictitiousGeneratorVoltageControlModeALWAYS), equationSystemCreationParameters=AcEquationSystemCreationParameters(forceA1Var=false), newtonRaphsonParameters=NewtonRaphsonParameters(maxIterations=15, minRealisticVoltage=0.5, maxRealisticVoltage=2.0, stoppingCriteria=DefaultNewtonRaphsonStoppingCriteria, stateVectorScalingMode=NONE, alwaysUpdateNetwork=false, lineSearchStateVectorScalingMaxIteration=10, lineSearchStateVectorScalingStepFold=1.3333333333333333, maxVoltageChangeStateVectorScalingMaxDv=0.1, maxVoltageChangeStateVectorScalingMaxDphi=0.17453292519943295), newtonKrylovParameters=NewtonKrylovParameters(maxIterations=100, lineSearch=false), outerLoops=[DistributedSlackOuterLoop, MonitoringVoltageOuterLoop, ReactiveLimitsOuterLoop], maxOuterLoopIterations=20, matrixFactory=DenseMatrixFactory, voltageInitializer=UniformValueVoltageInitializer, asymmetrical=false, slackDistributionFailureBehavior=LEAVE_ON_SLACK_BUS, solverFactory=NewtonRaphsonFactory, detailedReport=false)", acParameters.toString()); } @@ -87,7 +87,7 @@ void testGetExtendedVoltageInitializer() { @Test void specificParametersTest() { OpenLoadFlowProvider provider = new OpenLoadFlowProvider(); - assertEquals(66, provider.getSpecificParameters().size()); + assertEquals(67, provider.getSpecificParameters().size()); LoadFlowParameters parameters = new LoadFlowParameters(); provider.loadSpecificParameters(Collections.emptyMap()) @@ -110,7 +110,7 @@ void testCreateMapFromSpecificParameters() { OpenLoadFlowParameters parametersExt = new OpenLoadFlowParameters(); OpenLoadFlowProvider provider = new OpenLoadFlowProvider(); Map map = provider.createMapFromSpecificParameters(parametersExt); - assertEquals(66, map.size()); + assertEquals(67, map.size()); assertEquals(provider.getSpecificParameters().size(), map.size()); } diff --git a/src/test/java/com/powsybl/openloadflow/ac/FictitiousGeneratorTest.java b/src/test/java/com/powsybl/openloadflow/ac/FictitiousGeneratorTest.java new file mode 100644 index 0000000000..7914a42179 --- /dev/null +++ b/src/test/java/com/powsybl/openloadflow/ac/FictitiousGeneratorTest.java @@ -0,0 +1,127 @@ +package com.powsybl.openloadflow.ac; + +import com.powsybl.iidm.network.Bus; +import com.powsybl.iidm.network.EnergySource; +import com.powsybl.iidm.network.Network; +import com.powsybl.iidm.network.Substation; +import com.powsybl.iidm.network.TopologyKind; +import com.powsybl.iidm.network.VoltageLevel; +import com.powsybl.loadflow.LoadFlow; +import com.powsybl.loadflow.LoadFlowParameters; +import com.powsybl.loadflow.LoadFlowResult; +import com.powsybl.math.matrix.DenseMatrixFactory; +import com.powsybl.openloadflow.OpenLoadFlowParameters; +import com.powsybl.openloadflow.OpenLoadFlowProvider; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static com.powsybl.openloadflow.util.LoadFlowAssert.assertVoltageEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class FictitiousGeneratorTest { + + Network network; + LoadFlow.Runner runner; + Bus b1; + Bus b2; + + @BeforeEach + public void setUp() { + network = Network.create("fictitiousGeneratorTest", "code"); + Substation s = network.newSubstation() + .setId("s") + .add(); + VoltageLevel vl1 = s.newVoltageLevel() + .setId("vl1") + .setNominalV(220) + .setTopologyKind(TopologyKind.BUS_BREAKER) + .add(); + b1 = vl1.getBusBreakerView().newBus() + .setId("b1") + .add(); + + vl1.newGenerator() + .setId("g1") + .setBus("b1") + .setConnectableBus("b1") + .setEnergySource(EnergySource.THERMAL) + .setMinP(100) + .setMaxP(200) + .setTargetP(100) + .setTargetV(221) + .setVoltageRegulatorOn(true) + .add(); + VoltageLevel vl2 = s.newVoltageLevel() + .setId("vl2") + .setNominalV(220) + .setTopologyKind(TopologyKind.BUS_BREAKER) + .add(); + + b2 = vl2.getBusBreakerView().newBus() + .setId("b2") + .add(); + + vl2.newGenerator() + .setId("g2") + .setBus("b2") + .setConnectableBus("b2") + .setEnergySource(EnergySource.THERMAL) + .setMinP(100) + .setMaxP(200) + .setTargetP(0) + .setTargetV(224) + .setVoltageRegulatorOn(true) + .setFictitious(true) + .add(); + + vl2.newLoad() + .setId("ld2") + .setBus("b2") + .setConnectableBus("b2") + .setP0(99.9) + .setQ0(80) + .add(); + network.newLine() + .setId("l1") + .setConnectableBus1("b1") + .setBus1("b1") + .setConnectableBus2("b2") + .setBus2("b2") + .setR(1) + .setX(1) + .add(); + + runner = new LoadFlow.Runner(new OpenLoadFlowProvider(new DenseMatrixFactory())); + } + + @Test + public void testFictitiousGeneratorWithDefaultParameters() { + + LoadFlowParameters parameters = new LoadFlowParameters(); + OpenLoadFlowParameters olfParams = OpenLoadFlowParameters.create(parameters); + + assertEquals(olfParams.getFictitiousGeneratorVoltageControlMode(), OpenLoadFlowParameters.FictitiousGeneratorVoltageControlMode.ALWAYS); + + LoadFlowResult result = runner.run(network, parameters); + + assertTrue(result.isFullyConverged()); + assertVoltageEquals(221, b1); + assertVoltageEquals(224, b2); + } + + @Test + public void testFictitiousGeneratorNormalMode() { + + LoadFlowParameters parameters = new LoadFlowParameters(); + OpenLoadFlowParameters olfParams = OpenLoadFlowParameters.create(parameters); + + olfParams.setFictitiousGeneratorVoltageControlMode(OpenLoadFlowParameters.FictitiousGeneratorVoltageControlMode.NORMAL); + + LoadFlowResult result = runner.run(network, parameters); + + assertTrue(result.isFullyConverged()); + assertVoltageEquals(221, b1); + assertVoltageEquals(220.18, b2); // No voltage control on bus - voltage decreases with active power transport + } +} diff --git a/src/test/resources/debug-parameters.json b/src/test/resources/debug-parameters.json index dad60d412b..95e9c87bec 100644 --- a/src/test/resources/debug-parameters.json +++ b/src/test/resources/debug-parameters.json @@ -85,7 +85,8 @@ "referenceBusSelectionMode" : "FIRST_SLACK", "writeReferenceTerminals" : true, "voltageTargetPriorities" : [ "GENERATOR", "TRANSFORMER", "SHUNT" ], - "generatorVoltageControlMinNominalVoltage" : -1.0 + "generatorVoltageControlMinNominalVoltage" : -1.0, + "fictitiousGeneratorVoltageControlMode" : "ALWAYS" } } },