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

[WIP] Improve NR line search algo #781

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
75 changes: 70 additions & 5 deletions src/main/java/com/powsybl/openloadflow/OpenLoadFlowParameters.java
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,12 @@ public class OpenLoadFlowParameters extends AbstractExtension<LoadFlowParameters

private static final String ASYMMETRICAL_PARAM_NAME = "asymmetrical";

private static final String LINE_SEARCH_STATE_VECTOR_SCALING_MAX_ITERATIONS_PARAM_NAME = "lineSearchStateVectorScalingMaxIterations";

private static final String LINE_SEARCH_STATE_VECTOR_SCALING_STEP_FOLD_PARAM_NAME = "lineSearchStateVectorScalingStepFold";

private static final String LINE_SEARCH_STATE_VECTOR_SCALING_NORM_DECREASE_UPPER_BOUND_FUNCTION_TYPE_PARAM_NAME = "lineSearchStateVectorScalingNormDecreaseUpperBoundFunctionType";

private static <E extends Enum<E>> List<Object> getEnumPossibleValues(Class<E> enumClass) {
return EnumSet.allOf(enumClass).stream().map(Enum::name).collect(Collectors.toList());
}
Expand Down Expand Up @@ -232,7 +238,11 @@ private static <E extends Enum<E>> List<Object> getEnumPossibleValues(Class<E> e
new Parameter(MOST_MESHED_SLACK_BUS_SELECTOR_MAX_NOMINAL_VOLTAGE_PERCENTILE_PARAM_NAME, ParameterType.DOUBLE, "In case of most meshed slack bus selection, the max nominal voltage percentile", MostMeshedSlackBusSelector.MAX_NOMINAL_VOLTAGE_PERCENTILE_DEFAULT_VALUE), new Parameter(REPORTED_FEATURES_PARAM_NAME, ParameterType.STRING_LIST, "List of extra reported features to be added to report", null, getEnumPossibleValues(ReportedFeatures.class)),
new Parameter(SLACK_BUS_COUNTRY_FILTER_PARAM_NAME, ParameterType.STRING_LIST, "Slac bus selection country filter (no filtering if empty)", new ArrayList<>(LfNetworkParameters.SLACK_BUS_COUNTRY_FILTER_DEFAULT_VALUE)),
new Parameter(ACTIONABLE_SWITCHES_IDS_PARAM_NAME, ParameterType.STRING_LIST, "List of actionable switches IDs (used with fast restart)", new ArrayList<>(ACTIONABLE_SWITCH_IDS_DEFAULT_VALUE)),
new Parameter(ASYMMETRICAL_PARAM_NAME, ParameterType.BOOLEAN, "Asymmetrical calculation", LfNetworkParameters.ASYMMETRICAL_DEFAULT_VALUE)
new Parameter(ASYMMETRICAL_PARAM_NAME, ParameterType.BOOLEAN, "Asymmetrical calculation", LfNetworkParameters.ASYMMETRICAL_DEFAULT_VALUE),
new Parameter(ACTIONABLE_SWITCHES_IDS_PARAM_NAME, ParameterType.STRING_LIST, "List of actionable switches IDs (used with fast restart)", new ArrayList<>(ACTIONABLE_SWITCH_IDS_DEFAULT_VALUE)),
new Parameter(LINE_SEARCH_STATE_VECTOR_SCALING_MAX_ITERATIONS_PARAM_NAME, ParameterType.INTEGER, "Maximum number of iterations for the line search state vector scaling ", LineSearchStateVectorScaling.MAX_ITERATION_DEFAULT_VALUE),
new Parameter(LINE_SEARCH_STATE_VECTOR_SCALING_STEP_FOLD_PARAM_NAME, ParameterType.DOUBLE, "Step size folding per iteration for the line search state vector scaling ", LineSearchStateVectorScaling.STEP_FOLD_DEFAULT_VALUE),
new Parameter(LINE_SEARCH_STATE_VECTOR_SCALING_NORM_DECREASE_UPPER_BOUND_FUNCTION_TYPE_PARAM_NAME, ParameterType.STRING, "NR norm decrease upper bound function type for the line search state vector scaling ", LineSearchStateVectorScaling.NORM_DECREASE_UPPER_BOUND_FUNCTION_TYPE_DEFAULT_VALUE.name(), getEnumPossibleValues(LineSearchStateVectorScaling.NormDecreaseUpperBoundFunctionType.class))
);

public enum VoltageInitModeOverride {
Expand Down Expand Up @@ -362,6 +372,13 @@ public enum ReactiveRangeCheckMode {

private boolean asymmetrical = LfNetworkParameters.ASYMMETRICAL_DEFAULT_VALUE;

private int lineSearchStateVectorScalingMaxIterations = LineSearchStateVectorScaling.MAX_ITERATION_DEFAULT_VALUE;

private double lineSearchStateVectorScalingStepFold = LineSearchStateVectorScaling.STEP_FOLD_DEFAULT_VALUE;

private LineSearchStateVectorScaling.NormDecreaseUpperBoundFunctionType lineSearchStateVectorScalingNormDecreaseUpperBoundFunctionType
= LineSearchStateVectorScaling.NORM_DECREASE_UPPER_BOUND_FUNCTION_TYPE_DEFAULT_VALUE;

@Override
public String getName() {
return "open-load-flow-parameters";
Expand Down Expand Up @@ -805,6 +822,33 @@ public OpenLoadFlowParameters setAsymmetrical(boolean asymmetrical) {
return this;
}

public int getLineSearchStateVectorScalingMaxIterations() {
return lineSearchStateVectorScalingMaxIterations;
}

public OpenLoadFlowParameters setLineSearchStateVectorScalingMaxIterations(int lineSearchStateVectorScalingMaxIterations) {
this.lineSearchStateVectorScalingMaxIterations = lineSearchStateVectorScalingMaxIterations;
return this;
}

public double getLineSearchStateVectorScalingStepFold() {
return lineSearchStateVectorScalingStepFold;
}

public OpenLoadFlowParameters setLineSearchStateVectorScalingStepFold(double lineSearchStateVectorScalingStepFold) {
this.lineSearchStateVectorScalingStepFold = lineSearchStateVectorScalingStepFold;
return this;
}

public LineSearchStateVectorScaling.NormDecreaseUpperBoundFunctionType getLineSearchStateVectorScalingNormDecreaseUpperBoundFunctionType() {
return lineSearchStateVectorScalingNormDecreaseUpperBoundFunctionType;
}

public OpenLoadFlowParameters setLineSearchStateVectorScalingNormDecreaseUpperBoundFunctionType(LineSearchStateVectorScaling.NormDecreaseUpperBoundFunctionType lineSearchStateVectorScalingNormDecreaseUpperBoundFunctionType) {
this.lineSearchStateVectorScalingNormDecreaseUpperBoundFunctionType = Objects.requireNonNull(lineSearchStateVectorScalingNormDecreaseUpperBoundFunctionType);
return this;
}

public static OpenLoadFlowParameters load() {
return load(PlatformConfig.defaultConfig());
}
Expand Down Expand Up @@ -860,6 +904,9 @@ public static OpenLoadFlowParameters load(PlatformConfig platformConfig) {
.setSlackBusCountryFilter(config.getEnumSetProperty(SLACK_BUS_COUNTRY_FILTER_PARAM_NAME, Country.class, LfNetworkParameters.SLACK_BUS_COUNTRY_FILTER_DEFAULT_VALUE))
.setActionableSwitchesIds(new HashSet<>(config.getStringListProperty(ACTIONABLE_SWITCHES_IDS_PARAM_NAME, new ArrayList<>(ACTIONABLE_SWITCH_IDS_DEFAULT_VALUE))))
.setAsymmetrical(config.getBooleanProperty(ASYMMETRICAL_PARAM_NAME, LfNetworkParameters.ASYMMETRICAL_DEFAULT_VALUE))
.setLineSearchStateVectorScalingMaxIterations(config.getIntProperty(LINE_SEARCH_STATE_VECTOR_SCALING_MAX_ITERATIONS_PARAM_NAME, LineSearchStateVectorScaling.MAX_ITERATION_DEFAULT_VALUE))
.setLineSearchStateVectorScalingStepFold(config.getDoubleProperty(LINE_SEARCH_STATE_VECTOR_SCALING_STEP_FOLD_PARAM_NAME, LineSearchStateVectorScaling.STEP_FOLD_DEFAULT_VALUE))
.setLineSearchStateVectorScalingNormDecreaseUpperBoundFunctionType(config.getEnumProperty(LINE_SEARCH_STATE_VECTOR_SCALING_NORM_DECREASE_UPPER_BOUND_FUNCTION_TYPE_PARAM_NAME, LineSearchStateVectorScaling.NormDecreaseUpperBoundFunctionType.class, LineSearchStateVectorScaling.NORM_DECREASE_UPPER_BOUND_FUNCTION_TYPE_DEFAULT_VALUE))
);
return parameters;
}
Expand Down Expand Up @@ -964,11 +1011,17 @@ public OpenLoadFlowParameters update(Map<String, String> properties) {
.ifPresent(prop -> this.setActionableSwitchesIds(new HashSet<>(parseStringListProp(prop))));
Optional.ofNullable(properties.get(ASYMMETRICAL_PARAM_NAME))
.ifPresent(prop -> this.setAsymmetrical(Boolean.parseBoolean(prop)));
Optional.ofNullable(properties.get(LINE_SEARCH_STATE_VECTOR_SCALING_MAX_ITERATIONS_PARAM_NAME))
.ifPresent(prop -> this.setLineSearchStateVectorScalingMaxIterations(Integer.parseInt(prop)));
Optional.ofNullable(properties.get(LINE_SEARCH_STATE_VECTOR_SCALING_STEP_FOLD_PARAM_NAME))
.ifPresent(prop -> this.setLineSearchStateVectorScalingStepFold(Double.parseDouble(prop)));
Optional.ofNullable(properties.get(LINE_SEARCH_STATE_VECTOR_SCALING_NORM_DECREASE_UPPER_BOUND_FUNCTION_TYPE_PARAM_NAME))
.ifPresent(prop -> this.setLineSearchStateVectorScalingNormDecreaseUpperBoundFunctionType(LineSearchStateVectorScaling.NormDecreaseUpperBoundFunctionType.valueOf(prop)));
return this;
}

public Map<String, Object> toMap() {
Map<String, Object> map = new LinkedHashMap<>(44);
Map<String, Object> map = new LinkedHashMap<>(46);
map.put(SLACK_BUS_SELECTION_MODE_PARAM_NAME, slackBusSelectionMode);
map.put(SLACK_BUSES_IDS_PARAM_NAME, slackBusesIds);
map.put(THROWS_EXCEPTION_IN_CASE_OF_SLACK_DISTRIBUTION_FAILURE_PARAM_NAME, throwsExceptionInCaseOfSlackDistributionFailure);
Expand Down Expand Up @@ -1013,6 +1066,9 @@ public Map<String, Object> toMap() {
map.put(SLACK_BUS_COUNTRY_FILTER_PARAM_NAME, slackBusCountryFilter);
map.put(ACTIONABLE_SWITCHES_IDS_PARAM_NAME, actionableSwitchesIds);
map.put(ASYMMETRICAL_PARAM_NAME, asymmetrical);
map.put(LINE_SEARCH_STATE_VECTOR_SCALING_MAX_ITERATIONS_PARAM_NAME, lineSearchStateVectorScalingMaxIterations);
map.put(LINE_SEARCH_STATE_VECTOR_SCALING_STEP_FOLD_PARAM_NAME, lineSearchStateVectorScalingStepFold);
map.put(LINE_SEARCH_STATE_VECTOR_SCALING_NORM_DECREASE_UPPER_BOUND_FUNCTION_TYPE_PARAM_NAME, lineSearchStateVectorScalingNormDecreaseUpperBoundFunctionType);
return map;
}

Expand Down Expand Up @@ -1180,7 +1236,10 @@ public static AcLoadFlowParameters createAcParameters(LoadFlowParameters paramet
.setMinRealisticVoltage(parametersExt.getMinRealisticVoltage())
.setMaxRealisticVoltage(parametersExt.getMaxRealisticVoltage())
.setStateVectorScalingMode(parametersExt.getStateVectorScalingMode())
.setAlwaysUpdateNetwork(parametersExt.isAlwaysUpdateNetwork());
.setAlwaysUpdateNetwork(parametersExt.isAlwaysUpdateNetwork())
.setLineSearchStateVectorScalingMaxIterations(parametersExt.getLineSearchStateVectorScalingMaxIterations())
.setLineSearchStateVectorScalingStepFold(parametersExt.getLineSearchStateVectorScalingStepFold())
.setLineSearchStateVectorScalingNormDecreaseUpperBoundFunctionType(parametersExt.getLineSearchStateVectorScalingNormDecreaseUpperBoundFunctionType());

AcOuterLoopConfig outerLoopConfig = AcOuterLoopConfig.findOuterLoopConfig(new DefaultAcOuterLoopConfig());
List<AcOuterLoop> outerLoops = outerLoopConfig.configure(parameters, parametersExt);
Expand Down Expand Up @@ -1321,7 +1380,10 @@ public static boolean equals(LoadFlowParameters parameters1, LoadFlowParameters
extension1.getReportedFeatures().equals(extension2.getReportedFeatures()) &&
extension1.getSlackBusCountryFilter().equals(extension2.getSlackBusCountryFilter()) &&
extension1.getActionableSwitchesIds().equals(extension2.getActionableSwitchesIds()) &&
extension1.isAsymmetrical() == extension2.isAsymmetrical();
extension1.isAsymmetrical() == extension2.isAsymmetrical() &&
extension1.getLineSearchStateVectorScalingMaxIterations() == extension2.getLineSearchStateVectorScalingMaxIterations() &&
extension1.getLineSearchStateVectorScalingStepFold() == extension2.getLineSearchStateVectorScalingStepFold() &&
extension1.getLineSearchStateVectorScalingNormDecreaseUpperBoundFunctionType() == extension2.getLineSearchStateVectorScalingNormDecreaseUpperBoundFunctionType();
}

public static LoadFlowParameters clone(LoadFlowParameters parameters) {
Expand Down Expand Up @@ -1383,7 +1445,10 @@ public static LoadFlowParameters clone(LoadFlowParameters parameters) {
.setReportedFeatures(extension.getReportedFeatures())
.setSlackBusCountryFilter(new HashSet<>(extension.getSlackBusCountryFilter()))
.setActionableSwitchesIds(new HashSet<>(extension.getActionableSwitchesIds()))
.setAsymmetrical(extension.isAsymmetrical());
.setAsymmetrical(extension.isAsymmetrical())
.setLineSearchStateVectorScalingMaxIterations(extension.getLineSearchStateVectorScalingMaxIterations())
.setLineSearchStateVectorScalingStepFold(extension.getLineSearchStateVectorScalingStepFold())
.setLineSearchStateVectorScalingNormDecreaseUpperBoundFunctionType(extension.getLineSearchStateVectorScalingNormDecreaseUpperBoundFunctionType());
if (extension2 != null) {
parameters2.addExtension(OpenLoadFlowParameters.class, extension2);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,60 @@ public class LineSearchStateVectorScaling implements StateVectorScaling {

private static final Logger LOGGER = LoggerFactory.getLogger(LineSearchStateVectorScaling.class);

private static final int MAX_ITERATION = 10;
private static final double STEP_FOLD = 4d / 3;
public enum NormDecreaseUpperBoundFunctionType {
CONSTANT,
EXPONENTIAL
}

interface NormDecreaseUpperBoundFunction {

double getUpperBound(double previousNorm, double stepSize);

static NormDecreaseUpperBoundFunction find(NormDecreaseUpperBoundFunctionType type) {
switch (type) {
case CONSTANT:
return new ConstantNormDecreaseUpperBound();
case EXPONENTIAL:
return new ExpNormDecreaseUpperBound();
default:
throw new IllegalStateException("Unknown norm upper bound function type: " + type);
}
}
}

static class ConstantNormDecreaseUpperBound implements NormDecreaseUpperBoundFunction {

@Override
public double getUpperBound(double previousNorm, double stepSize) {
return previousNorm;
}
}

static class ExpNormDecreaseUpperBound implements NormDecreaseUpperBoundFunction {

@Override
public double getUpperBound(double previousNorm, double stepSize) {
return previousNorm * Math.exp(-stepSize);
}
}

public static final int MAX_ITERATION_DEFAULT_VALUE = 5;
public static final double STEP_FOLD_DEFAULT_VALUE = 4d;
public static final NormDecreaseUpperBoundFunctionType NORM_DECREASE_UPPER_BOUND_FUNCTION_TYPE_DEFAULT_VALUE = NormDecreaseUpperBoundFunctionType.EXPONENTIAL;

private final int maxIterations;
private final double stepFold;
private final NormDecreaseUpperBoundFunction normDecreaseUpperBoundFunction;

private double[] lastDx;

private NewtonRaphsonStoppingCriteria.TestResult lastTestResult;

public LineSearchStateVectorScaling(NewtonRaphsonStoppingCriteria.TestResult initialTestResult) {
public LineSearchStateVectorScaling(int maxIterations, double stepFold, NormDecreaseUpperBoundFunctionType normDecreaseUpperBoundFunctionType,
NewtonRaphsonStoppingCriteria.TestResult initialTestResult) {
this.maxIterations = maxIterations;
this.stepFold = stepFold;
this.normDecreaseUpperBoundFunction = NormDecreaseUpperBoundFunction.find(normDecreaseUpperBoundFunctionType);
this.lastTestResult = Objects.requireNonNull(initialTestResult);
}

Expand Down Expand Up @@ -60,7 +106,8 @@ public NewtonRaphsonStoppingCriteria.TestResult applyAfter(EquationSystem<AcVari
NewtonRaphsonStoppingCriteria.TestResult currentTestResult = testResult;
double[] x = null;
int iteration = 1;
while (currentTestResult.getNorm() >= lastTestResult.getNorm() && iteration <= MAX_ITERATION) {
while (currentTestResult.getNorm() >= normDecreaseUpperBoundFunction.getUpperBound(lastTestResult.getNorm(), stepSize)
&& iteration <= maxIterations) {
if (x == null) {
x = stateVector.get();
}
Expand All @@ -70,7 +117,7 @@ public NewtonRaphsonStoppingCriteria.TestResult applyAfter(EquationSystem<AcVari
// x(i+1)' = x(i) - dx * mu
// x(i+1)' = x(i+1) + dx (1 - mu)
double[] newX = x.clone();
stepSize = 1 / Math.pow(STEP_FOLD, iteration);
stepSize = 1 / Math.pow(stepFold, iteration);
Vectors.plus(newX, lastDx, 1 - stepSize);
stateVector.set(newX);
// equation vector has been updated
Expand All @@ -84,7 +131,11 @@ public NewtonRaphsonStoppingCriteria.TestResult applyAfter(EquationSystem<AcVari
iteration++;
}
lastTestResult = currentTestResult;
LOGGER.debug("Step size: {}", stepSize);
if (iteration > maxIterations) {
LOGGER.warn("Minimal step size have been reached with max number of iterations: {}", stepSize);
} else {
LOGGER.debug("Step size: {}", stepSize);
}
}
return lastTestResult;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,7 @@ public NewtonRaphsonResult run(VoltageInitializer voltageInitializer, Reporter r
Vectors.minus(equationVector.getArray(), targetVector.getArray());

NewtonRaphsonStoppingCriteria.TestResult initialTestResult = parameters.getStoppingCriteria().test(equationVector.getArray(), equationSystem);
StateVectorScaling svScaling = StateVectorScaling.fromMode(parameters.getStateVectorScalingMode(), initialTestResult);
StateVectorScaling svScaling = StateVectorScaling.create(parameters, initialTestResult);

LOGGER.debug("|f(x0)|={}", initialTestResult.getNorm());

Expand Down
Loading