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

Various performance improvements #745

Merged
merged 3 commits into from
Mar 6, 2023
Merged
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
10 changes: 10 additions & 0 deletions src/main/java/com/powsybl/openloadflow/equations/Equation.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ public class Equation<V extends Enum<V> & Quantity, E extends Enum<E> & Quantity

private final List<EquationTerm<V, E>> terms = new ArrayList<>();

private final Map<Variable<V>, List<EquationTerm<V, E>>> termsByVariable = new TreeMap<>();

Equation(int elementNum, E type, EquationSystem<V, E> equationSystem) {
this.elementNum = elementNum;
this.type = Objects.requireNonNull(type);
Expand Down Expand Up @@ -81,6 +83,10 @@ public Equation<V, E> addTerm(EquationTerm<V, E> term) {
+ term.getEquation());
}
terms.add(term);
for (Variable<V> v : term.getVariables()) {
termsByVariable.computeIfAbsent(v, k -> new ArrayList<>())
.add(term);
}
term.setEquation(this);
equationSystem.addEquationTerm(term);
equationSystem.notifyEquationTermChange(term, EquationTermEventType.EQUATION_TERM_ADDED);
Expand All @@ -99,6 +105,10 @@ public List<EquationTerm<V, E>> getTerms() {
return terms;
}

public Map<Variable<V>, List<EquationTerm<V, E>>> getTermsByVariable() {
return termsByVariable;
}

@Override
public double eval() {
double value = 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import org.slf4j.LoggerFactory;

import java.util.*;
import java.util.stream.Collectors;

/**
* @author Geoffroy Jamgotchian <geoffroy.jamgotchian at rte-france.com>
Expand All @@ -20,10 +21,14 @@ public class EquationSystemIndex<V extends Enum<V> & Quantity, E extends Enum<E>

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

private final TreeSet<Equation<V, E>> sortedEquationsToSolve = new TreeSet<>();
private final Set<Equation<V, E>> equationsToSolve = new HashSet<>();

// variable reference counting in equation terms
private final NavigableMap<Variable<V>, MutableInt> sortedVariablesToFindRefCount = new TreeMap<>();
private final Map<Variable<V>, MutableInt> variablesToFindRefCount = new HashMap<>();

private List<Equation<V, E>> sortedEquationsToSolve = Collections.emptyList();

private List<Variable<V>> sortedVariablesToFind = Collections.emptyList();

private boolean equationsIndexValid = false;

Expand Down Expand Up @@ -57,6 +62,7 @@ private void notifyEquationTermChange(EquationTerm<V, E> term) {

private void update() {
if (!equationsIndexValid) {
sortedEquationsToSolve = equationsToSolve.stream().sorted().collect(Collectors.toList());
int columnCount = 0;
for (Equation<V, E> equation : sortedEquationsToSolve) {
equation.setColumn(columnCount++);
Expand All @@ -66,8 +72,9 @@ private void update() {
}

if (!variablesIndexValid) {
sortedVariablesToFind = variablesToFindRefCount.keySet().stream().sorted().collect(Collectors.toList());
int rowCount = 0;
for (Variable<V> variable : sortedVariablesToFindRefCount.keySet()) {
for (Variable<V> variable : sortedVariablesToFind) {
variable.setRow(rowCount++);
}
variablesIndexValid = true;
Expand All @@ -78,10 +85,10 @@ private void update() {
private void addTerm(EquationTerm<V, E> term) {
notifyEquationTermChange(term);
for (Variable<V> variable : term.getVariables()) {
MutableInt variableRefCount = sortedVariablesToFindRefCount.get(variable);
MutableInt variableRefCount = variablesToFindRefCount.get(variable);
if (variableRefCount == null) {
variableRefCount = new MutableInt(1);
sortedVariablesToFindRefCount.put(variable, variableRefCount);
variablesToFindRefCount.put(variable, variableRefCount);
variablesIndexValid = false;
notifyVariableChange(variable, EquationSystemIndexListener.ChangeType.ADDED);
} else {
Expand All @@ -91,7 +98,7 @@ private void addTerm(EquationTerm<V, E> term) {
}

private void addEquation(Equation<V, E> equation) {
sortedEquationsToSolve.add(equation);
equationsToSolve.add(equation);
equationsIndexValid = false;
for (EquationTerm<V, E> term : equation.getTerms()) {
if (term.isActive()) {
Expand All @@ -104,12 +111,12 @@ private void addEquation(Equation<V, E> equation) {
private void removeTerm(EquationTerm<V, E> term) {
notifyEquationTermChange(term);
for (Variable<V> variable : term.getVariables()) {
MutableInt variableRefCount = sortedVariablesToFindRefCount.get(variable);
MutableInt variableRefCount = variablesToFindRefCount.get(variable);
if (variableRefCount != null) {
variableRefCount.decrement();
if (variableRefCount.intValue() == 0) {
variable.setRow(-1);
sortedVariablesToFindRefCount.remove(variable);
variablesToFindRefCount.remove(variable);
variablesIndexValid = false;
notifyVariableChange(variable, EquationSystemIndexListener.ChangeType.REMOVED);
}
Expand All @@ -119,7 +126,7 @@ private void removeTerm(EquationTerm<V, E> term) {

private void removeEquation(Equation<V, E> equation) {
equation.setColumn(-1);
sortedEquationsToSolve.remove(equation);
equationsToSolve.remove(equation);
equationsIndexValid = false;
for (EquationTerm<V, E> term : equation.getTerms()) {
if (term.isActive()) {
Expand Down Expand Up @@ -181,13 +188,13 @@ public void onEquationTermChange(EquationTerm<V, E> term, EquationTermEventType
}
}

public NavigableSet<Equation<V, E>> getSortedEquationsToSolve() {
public List<Equation<V, E>> getSortedEquationsToSolve() {
update();
return sortedEquationsToSolve;
}

public NavigableSet<Variable<V>> getSortedVariablesToFind() {
public List<Variable<V>> getSortedVariablesToFind() {
update();
return sortedVariablesToFindRefCount.navigableKeySet();
return sortedVariablesToFind;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import org.slf4j.LoggerFactory;

import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;

import static com.powsybl.openloadflow.util.Markers.PERFORMANCE_MARKER;
Expand Down Expand Up @@ -40,6 +41,13 @@ protected double[] createArray() {
return array;
}

private void eval(double[] array, List<Equation<V, E>> equations) {
Arrays.fill(array, 0); // necessary?
for (Equation<V, E> equation : equations) {
array[equation.getColumn()] = equation.eval();
}
}

@Override
protected void updateArray(double[] array) {
Stopwatch stopwatch = Stopwatch.createStarted();
Expand All @@ -50,10 +58,7 @@ protected void updateArray(double[] array) {
throw new IllegalArgumentException("Bad equation vector length: " + array.length);
}

Arrays.fill(array, 0); // necessary?
for (Equation<V, E> equation : equations) {
array[equation.getColumn()] = equation.eval();
}
eval(array, equations);

LOGGER.debug(PERFORMANCE_MARKER, "Equation vector updated in {} us", stopwatch.elapsed(TimeUnit.MICROSECONDS));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,10 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

import static com.powsybl.openloadflow.util.Markers.PERFORMANCE_MARKER;
Expand Down Expand Up @@ -107,25 +110,7 @@ public void onStateUpdate() {
updateStatus(Status.VALUES_INVALID);
}

private void clearLu() {
if (lu != null) {
lu.close();
}
lu = null;
}

private Map<Variable<V>, List<EquationTerm<V, E>>> indexTermsByVariable(Equation<V, E> eq) {
Map<Variable<V>, List<EquationTerm<V, E>>> termsByVariable = new TreeMap<>();
for (EquationTerm<V, E> term : eq.getTerms()) {
for (Variable<V> v : term.getVariables()) {
termsByVariable.computeIfAbsent(v, k -> new ArrayList<>())
.add(term);
}
}
return termsByVariable;
}

private void initMatrix() {
private void initDer() {
Stopwatch stopwatch = Stopwatch.createStarted();

int rowCount = equationSystem.getIndex().getSortedEquationsToSolve().size();
Expand All @@ -141,8 +126,7 @@ private void initMatrix() {

for (Equation<V, E> eq : equationSystem.getIndex().getSortedEquationsToSolve()) {
int column = eq.getColumn();
Map<Variable<V>, List<EquationTerm<V, E>>> termsByVariable = indexTermsByVariable(eq);
for (Map.Entry<Variable<V>, List<EquationTerm<V, E>>> e : termsByVariable.entrySet()) {
for (Map.Entry<Variable<V>, List<EquationTerm<V, E>>> e : eq.getTermsByVariable().entrySet()) {
Variable<V> v = e.getKey();
int row = v.getRow();
if (row != -1) {
Expand All @@ -151,28 +135,28 @@ private void initMatrix() {
// at jacobian update stage without any equation or variable index change
double value = term.isActive() ? term.der(v) : 0;
int elementIndex = matrix.addAndGetIndex(row, column, value);
partialDerivatives.add(new JacobianMatrix.PartialDerivative<>(term, elementIndex, v));
partialDerivatives.add(new PartialDerivative<>(term, elementIndex, v));
}
}
}
}

LOGGER.debug(PERFORMANCE_MARKER, "Jacobian matrix built in {} us", stopwatch.elapsed(TimeUnit.MICROSECONDS));

clearLu();
}

private void updateLu(boolean allowIncrementalUpdate) {
private void clearLu() {
if (lu != null) {
Stopwatch stopwatch = Stopwatch.createStarted();

lu.update(allowIncrementalUpdate);

LOGGER.debug(PERFORMANCE_MARKER, "LU decomposition updated in {} us", stopwatch.elapsed(TimeUnit.MICROSECONDS));
lu.close();
}
lu = null;
}

private void updateValues(boolean allowIncrementalUpdate) {
private void initMatrix() {
initDer();
clearLu();
}

private void updateDer() {
Stopwatch stopwatch = Stopwatch.createStarted();

matrix.reset();
Expand All @@ -187,7 +171,20 @@ private void updateValues(boolean allowIncrementalUpdate) {
}

LOGGER.debug(PERFORMANCE_MARKER, "Jacobian matrix values updated in {} us", stopwatch.elapsed(TimeUnit.MICROSECONDS));
}

private void updateLu(boolean allowIncrementalUpdate) {
if (lu != null) {
Stopwatch stopwatch = Stopwatch.createStarted();

lu.update(allowIncrementalUpdate);

LOGGER.debug(PERFORMANCE_MARKER, "LU decomposition updated in {} us", stopwatch.elapsed(TimeUnit.MICROSECONDS));
}
}

private void updateValues(boolean allowIncrementalUpdate) {
updateDer();
updateLu(allowIncrementalUpdate);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

import com.powsybl.openloadflow.network.*;

import java.util.NavigableSet;
import java.util.List;
import java.util.Objects;

/**
Expand Down Expand Up @@ -75,7 +75,7 @@ public static <V extends Enum<V> & Quantity, E extends Enum<E> & Quantity> doubl
Objects.requireNonNull(network);
Objects.requireNonNull(equationSystem);
Objects.requireNonNull(initializer);
NavigableSet<Equation<V, E>> sortedEquationsToSolve = equationSystem.getIndex().getSortedEquationsToSolve();
List<Equation<V, E>> sortedEquationsToSolve = equationSystem.getIndex().getSortedEquationsToSolve();
double[] array = new double[sortedEquationsToSolve.size()];
for (Equation<V, E> equation : sortedEquationsToSolve) {
initializer.initialize(equation, network, array);
Expand All @@ -90,7 +90,7 @@ protected double[] createArray() {

@Override
protected void updateArray(double[] array) {
NavigableSet<Equation<V, E>> sortedEquationsToSolve = equationSystem.getIndex().getSortedEquationsToSolve();
List<Equation<V, E>> sortedEquationsToSolve = equationSystem.getIndex().getSortedEquationsToSolve();
for (Equation<V, E> equation : sortedEquationsToSolve) {
initializer.initialize(equation, network, array);
}
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 @@ -72,6 +72,8 @@ public interface LfBus extends LfElement {

boolean ensurePowerFactorConstantByLoad();

void invalidateGenerationTargetP();

double getGenerationTargetP();

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

protected double loadTargetQ = 0;

protected Double generationTargetP;

protected double generationTargetQ = 0;

protected final List<LfGenerator> generators = new ArrayList<>();
Expand Down Expand Up @@ -270,9 +272,17 @@ void setShuntCompensators(List<ShuntCompensator> shuntCompensators, LfNetworkPar
}
}

@Override
public void invalidateGenerationTargetP() {
generationTargetP = null;
}

@Override
public double getGenerationTargetP() {
return generators.stream().mapToDouble(LfGenerator::getTargetP).sum();
if (generationTargetP == null) {
generationTargetP = generators.stream().mapToDouble(LfGenerator::getTargetP).sum();
}
return generationTargetP;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ public void setTargetP(double targetP) {
if (newTargetP != this.targetP) {
double oldTargetP = this.targetP;
this.targetP = newTargetP;
bus.invalidateGenerationTargetP();
for (LfNetworkListener listener : bus.getNetwork().getListeners()) {
listener.onGenerationActivePowerTargetChange(this, oldTargetP, newTargetP);
}
Expand Down
Loading