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

Equation system index optimization #435

Merged
merged 92 commits into from
Jun 3, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
92 commits
Select commit Hold shift + click to select a range
b256e52
Equation system index optimization
geofjamg Jan 24, 2022
f835c28
Cleanup
geofjamg Jan 24, 2022
1b68601
Cleanup
geofjamg Jan 24, 2022
e22f720
Rename cache to index
geofjamg Jan 24, 2022
f89104d
Refactoring
geofjamg Jan 24, 2022
027b5ca
Refactoring
geofjamg Jan 24, 2022
4995298
Refactoring
geofjamg Jan 24, 2022
efcd8b3
Refactoring
geofjamg Jan 25, 2022
82d077f
Refactoring
geofjamg Jan 25, 2022
d15e5a9
Fix Sonar issues
geofjamg Jan 25, 2022
bf455a5
Add index listener
geofjamg Jan 25, 2022
1635df6
Add remove listener
geofjamg Jan 25, 2022
d8e8ee1
Improve
geofjamg Jan 25, 2022
fcc8bc2
Reset column and row
geofjamg Jan 27, 2022
e94a4d9
Refactoring
geofjamg Jan 27, 2022
5174749
Fix
geofjamg Jan 28, 2022
628fb9f
Sort contingencies to improve performances
geofjamg Jan 28, 2022
a10e9d0
Merge branch 'main' into eq_sys_cache_optim
geofjamg Jan 28, 2022
fe63173
Fix
geofjamg Jan 29, 2022
18922e4
Fix
geofjamg Jan 30, 2022
79a1c7c
Merge branch 'main' into eq_sys_cache_optim
geofjamg Feb 4, 2022
40f99f1
Merge remote-tracking branch 'origin/eq_sys_cache_optim' into eq_sys_…
geofjamg Feb 4, 2022
337d804
Merge branch 'main' into eq_sys_cache_optim
geofjamg Feb 28, 2022
6041dca
Fix merge
geofjamg Feb 28, 2022
8d423cf
Add javadoc
geofjamg Feb 28, 2022
5de2e0d
Fix test
geofjamg Feb 28, 2022
996fe2d
Merge branch 'main' into eq_sys_cache_optim
geofjamg Mar 3, 2022
9d13961
Fix indent
geofjamg Mar 3, 2022
dbd6ecb
Merge branch 'main' into eq_sys_cache_optim
geofjamg Mar 12, 2022
358220b
Fix merge
geofjamg Mar 12, 2022
b6109b6
Refactoring
geofjamg Mar 13, 2022
26e0d57
Add unit test
geofjamg Mar 13, 2022
2e1869e
Cleanup
geofjamg Mar 13, 2022
0bf6b20
Add new element notif
geofjamg Mar 14, 2022
095bfce
Refactoring
geofjamg Mar 14, 2022
2bb7652
Refactoring
geofjamg Mar 14, 2022
0f562a1
Revert to work on 4.7.0
geofjamg Mar 16, 2022
527e2fd
Fix comment
geofjamg Mar 16, 2022
8c0a69e
Merge branch 'main' into eq_sys_cache_optim
geofjamg Mar 16, 2022
f256d8f
Merge branch 'main' into eq_sys_cache_optim
geofjamg Mar 16, 2022
0bf8c0e
Merge branch 'main' into eq_sys_cache_optim
geofjamg Mar 16, 2022
1a04702
Merge remote-tracking branch 'origin/eq_sys_cache_optim' into eq_sys_…
geofjamg Mar 16, 2022
914dad9
Merge branch 'main' into eq_sys_cache_optim
geofjamg Mar 20, 2022
fd33a72
Merge branch 'main' into eq_sys_cache_optim
annetill Mar 23, 2022
67ed6b5
Merge branch 'main' into eq_sys_cache_optim
geofjamg Mar 24, 2022
ae99626
Merge branch 'main' into eq_sys_cache_optim
geofjamg Mar 31, 2022
ffdc5ad
Merge branch 'main' into eq_sys_cache_optim
geofjamg Apr 2, 2022
79b1ff0
incremental factorization
geofjamg Apr 2, 2022
42e8eb1
Merge branch 'main' into eq_sys_cache_optim
annetill Apr 4, 2022
06cf0cc
Merge remote-tracking branch 'origin/eq_sys_cache_optim' into eq_sys_…
geofjamg Apr 4, 2022
add5423
Equation system index optimization
geofjamg Jan 24, 2022
6ea4850
Cleanup
geofjamg Jan 24, 2022
507946d
Cleanup
geofjamg Jan 24, 2022
0c047a8
Rename cache to index
geofjamg Jan 24, 2022
3eafeaa
Refactoring
geofjamg Jan 24, 2022
37fa914
Refactoring
geofjamg Jan 24, 2022
25cc3ed
Refactoring
geofjamg Jan 24, 2022
0958ce0
Refactoring
geofjamg Jan 25, 2022
efe0206
Refactoring
geofjamg Jan 25, 2022
8c013f2
Fix Sonar issues
geofjamg Jan 25, 2022
c7b6ff6
Add index listener
geofjamg Jan 25, 2022
fcca5b6
Add remove listener
geofjamg Jan 25, 2022
b9034d3
Improve
geofjamg Jan 25, 2022
2272a6c
Reset column and row
geofjamg Jan 27, 2022
457539f
Refactoring
geofjamg Jan 27, 2022
fb3d745
Fix
geofjamg Jan 28, 2022
44f91bf
Sort contingencies to improve performances
geofjamg Jan 28, 2022
28c7351
Fix
geofjamg Jan 29, 2022
e3a02a1
Fix
geofjamg Jan 30, 2022
ddeda3a
Add javadoc
geofjamg Feb 28, 2022
426a51b
Fix test
geofjamg Feb 28, 2022
3381a7b
Fix merge
geofjamg Mar 12, 2022
f3f6dfc
Refactoring
geofjamg Mar 13, 2022
ec67bc7
Add unit test
geofjamg Mar 13, 2022
4634d9a
Cleanup
geofjamg Mar 13, 2022
b6c8dc1
Add new element notif
geofjamg Mar 14, 2022
59fa064
Refactoring
geofjamg Mar 14, 2022
bee378a
Refactoring
geofjamg Mar 14, 2022
821b3ae
Revert to work on 4.7.0
geofjamg Mar 16, 2022
438d4ef
Fix comment
geofjamg Mar 16, 2022
87b4ae9
incremental factorization
geofjamg Apr 2, 2022
e3d2717
Fix merge
geofjamg Apr 23, 2022
44be9e8
Fix merge
geofjamg Apr 23, 2022
d03b226
Merge branch 'main' into eq_sys_cache_optim
geofjamg May 16, 2022
c6afc39
Fix
geofjamg May 16, 2022
2edb91c
Refactoring
geofjamg May 16, 2022
e67143b
Merge branch 'main' into eq_sys_cache_optim
geofjamg May 17, 2022
4be6171
Merge branch 'main' into eq_sys_cache_optim
annetill May 18, 2022
b8ac544
Merge branch 'main' into eq_sys_cache_optim
annetill Jun 1, 2022
a04fdc0
Merge remote-tracking branch 'origin/eq_sys_cache_optim' into eq_sys_…
geofjamg Jun 2, 2022
ed1d8e9
Merge branch 'main' into eq_sys_cache_optim
geofjamg Jun 2, 2022
b08306b
Revert
geofjamg Jun 2, 2022
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
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ public void prepare(LfNetwork network) {

j.solveTransposed(targets);

for (Variable<InitVmVariableType> variable : equationSystem.getSortedVariablesToFind()) {
for (Variable<InitVmVariableType> variable : equationSystem.getIndex().getSortedVariablesToFind()) {
LfBus bus = network.getBus(variable.getElementNum());
bus.setV(targets[variable.getRow()]);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,8 @@ private NewtonRaphsonStatus runIteration(double[] fx) {
}

public static void initStateVector(LfNetwork network, EquationSystem<AcVariableType, AcEquationType> equationSystem, VoltageInitializer initializer) {
double[] x = new double[equationSystem.getSortedVariablesToFind().size()];
for (Variable<AcVariableType> v : equationSystem.getSortedVariablesToFind()) {
double[] x = new double[equationSystem.getIndex().getSortedVariablesToFind().size()];
for (Variable<AcVariableType> v : equationSystem.getIndex().getSortedVariablesToFind()) {
switch (v.getType()) {
case BUS_V:
x[v.getRow()] = initializer.getMagnitude(network.getBus(v.getElementNum()));
Expand Down Expand Up @@ -131,7 +131,7 @@ public static void initStateVector(LfNetwork network, EquationSystem<AcVariableT
public void updateNetwork() {
// update state variable
StateVector stateVector = equationSystem.getStateVector();
for (Variable<AcVariableType> v : equationSystem.getSortedVariablesToFind()) {
for (Variable<AcVariableType> v : equationSystem.getIndex().getSortedVariablesToFind()) {
switch (v.getType()) {
case BUS_V:
network.getBus(v.getElementNum()).setV(stateVector.get(v.getRow()));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,8 @@ private DcLoadFlowResult run(Reporter reporter, LfNetwork network) {
}

public static void initStateVector(LfNetwork network, EquationSystem<DcVariableType, DcEquationType> equationSystem, VoltageInitializer initializer) {
double[] x = new double[equationSystem.getSortedVariablesToFind().size()];
for (Variable<DcVariableType> v : equationSystem.getSortedVariablesToFind()) {
double[] x = new double[equationSystem.getIndex().getSortedVariablesToFind().size()];
for (Variable<DcVariableType> v : equationSystem.getIndex().getSortedVariablesToFind()) {
switch (v.getType()) {
case BUS_PHI:
x[v.getRow()] = Math.toRadians(initializer.getAngle(network.getBus(v.getElementNum())));
Expand All @@ -104,7 +104,7 @@ public static void initStateVector(LfNetwork network, EquationSystem<DcVariableT

public static void updateNetwork(LfNetwork network, EquationSystem<DcVariableType, DcEquationType> equationSystem, double[] x) {
// update state variable
for (Variable<DcVariableType> v : equationSystem.getSortedVariablesToFind()) {
for (Variable<DcVariableType> v : equationSystem.getIndex().getSortedVariablesToFind()) {
switch (v.getType()) {
case BUS_PHI:
network.getBus(v.getElementNum()).setAngle(Math.toDegrees(x[v.getRow()]));
Expand Down
165 changes: 17 additions & 148 deletions src/main/java/com/powsybl/openloadflow/equations/EquationSystem.java
Original file line number Diff line number Diff line change
Expand Up @@ -39,145 +39,14 @@ public class EquationSystem<V extends Enum<V> & Quantity, E extends Enum<E> & Qu

private final Map<Pair<ElementType, Integer>, List<EquationTerm<V, E>>> equationTermsByElement = new HashMap<>();

private class EquationCache implements EquationSystemListener<V, E> {

private final NavigableMap<Equation<V, E>, NavigableMap<Variable<V>, List<EquationTerm<V, E>>>> sortedEquationsToSolve = new TreeMap<>();

private final NavigableMap<Variable<V>, Set<Equation<V, E>>> sortedVariablesToFind = new TreeMap<>();

private final Set<Equation<V, E>> equationsToRemove = new HashSet<>();

private final Set<Equation<V, E>> equationsToAdd = new HashSet<>();

private void update() {
if (reIndex()) {
Stopwatch stopwatch = Stopwatch.createStarted();

int columnCount = 0;
for (Equation<V, E> equation : sortedEquationsToSolve.keySet()) {
equation.setColumn(columnCount++);
}

int rowCount = 0;
for (Variable<V> variable : sortedVariablesToFind.keySet()) {
variable.setRow(rowCount++);
}

LOGGER.debug("Equation system indexed in {} us", stopwatch.elapsed(TimeUnit.MICROSECONDS));
}
}

private boolean reIndex() {
if (equationsToAdd.isEmpty() && equationsToRemove.isEmpty()) {
return false;
}

// index derivatives per variable then per equation

// equations to remove
for (Equation<V, E> equation : equationsToRemove) {
sortedEquationsToSolve.remove(equation);
for (EquationTerm<V, E> equationTerm : equation.getTerms()) {
for (Variable<V> variable : equationTerm.getVariables()) {
Set<Equation<V, E>> equationsUsingThisVariable = sortedVariablesToFind.get(variable);
if (equationsUsingThisVariable != null) {
equationsUsingThisVariable.remove(equation);
if (equationsUsingThisVariable.isEmpty()) {
sortedVariablesToFind.remove(variable);
}
}
}
}
}

// equations to add
for (Equation<V, E> equation : equationsToAdd) {
// do not use equations that would be updated only after NR
if (equation.isActive()) {
// check we have at least one equation term active
boolean atLeastOneTermIsValid = false;
for (EquationTerm<V, E> equationTerm : equation.getTerms()) {
if (equationTerm.isActive()) {
atLeastOneTermIsValid = true;
for (Variable<V> variable : equationTerm.getVariables()) {
sortedEquationsToSolve.computeIfAbsent(equation, k -> new TreeMap<>())
.computeIfAbsent(variable, k -> new ArrayList<>())
.add(equationTerm);
sortedVariablesToFind.computeIfAbsent(variable, k -> new TreeSet<>())
.add(equation);
}
}
}
if (!atLeastOneTermIsValid) {
throw new IllegalStateException("Equation " + equation + " is active but all of its terms are inactive");
}
}
}

equationsToRemove.clear();
equationsToAdd.clear();

return true;
}

@Override
public void onEquationChange(Equation<V, E> equation, EquationEventType eventType) {
switch (eventType) {
case EQUATION_REMOVED:
case EQUATION_DEACTIVATED:
if (!sortedEquationsToSolve.isEmpty()) { // not need to remove if not already indexed
equationsToRemove.add(equation);
}
equationsToAdd.remove(equation);
break;

case EQUATION_CREATED:
case EQUATION_ACTIVATED:
// no need to remove first because activated event means it was not already activated
equationsToAdd.add(equation);
break;

default:
throw new IllegalStateException("Event type not supported: " + eventType);
}
}

@Override
public void onEquationTermChange(EquationTerm<V, E> term, EquationTermEventType eventType) {
switch (eventType) {
case EQUATION_TERM_ADDED:
case EQUATION_TERM_ACTIVATED:
case EQUATION_TERM_DEACTIVATED:
if (!sortedEquationsToSolve.isEmpty()) { // not need to remove if not already indexed
equationsToRemove.add(term.getEquation());
}
equationsToAdd.add(term.getEquation());
break;

default:
throw new IllegalStateException("Event type not supported: " + eventType);
}
}

private NavigableMap<Equation<V, E>, NavigableMap<Variable<V>, List<EquationTerm<V, E>>>> getSortedEquationsToSolve() {
update();
return sortedEquationsToSolve;
}

private NavigableSet<Variable<V>> getSortedVariablesToFind() {
update();
return sortedVariablesToFind.navigableKeySet();
}
}

private final EquationCache equationCache = new EquationCache();

private final List<EquationSystemListener<V, E>> listeners = new ArrayList<>();

private final VariableSet<V> variableSet;

private final StateVector stateVector = new StateVector();

private final EquationSystemIndex<V, E> index;

public EquationSystem() {
this(false);
}
Expand All @@ -189,7 +58,7 @@ public EquationSystem(boolean indexTerms) {
public EquationSystem(VariableSet<V> variableSet, boolean indexTerms) {
this.variableSet = Objects.requireNonNull(variableSet);
this.indexTerms = indexTerms;
addListener(equationCache);
index = new EquationSystemIndex<>(this);
}

public VariableSet<V> getVariableSet() {
Expand All @@ -204,6 +73,14 @@ public StateVector getStateVector() {
return stateVector;
}

public EquationSystemIndex<V, E> getIndex() {
return index;
}

public Collection<Equation<V, E>> getEquations() {
return equations.values();
}

void addEquationTerm(EquationTerm<V, E> equationTerm) {
if (indexTerms) {
Objects.requireNonNull(equationTerm);
Expand Down Expand Up @@ -283,41 +160,33 @@ public void attach(EquationTerm<V, E> term) {
term.setStateVector(stateVector);
}

public SortedSet<Variable<V>> getSortedVariablesToFind() {
return equationCache.getSortedVariablesToFind();
}

public NavigableMap<Equation<V, E>, NavigableMap<Variable<V>, List<EquationTerm<V, E>>>> getSortedEquationsToSolve() {
return equationCache.getSortedEquationsToSolve();
}

public List<String> getRowNames(LfNetwork network) {
return getSortedVariablesToFind().stream()
return index.getSortedVariablesToFind().stream()
.map(eq -> network.getBus(eq.getElementNum()).getId() + "/" + eq.getType())
.collect(Collectors.toList());
}

public List<String> getColumnNames(LfNetwork network) {
return getSortedEquationsToSolve().navigableKeySet().stream()
return index.getSortedEquationsToSolve().stream()
.map(v -> network.getBus(v.getElementNum()).getId() + "/" + v.getType())
.collect(Collectors.toList());
}

public double[] createEquationVector() {
double[] fx = new double[equationCache.getSortedEquationsToSolve().size()];
double[] fx = new double[index.getSortedEquationsToSolve().size()];
updateEquationVector(fx);
return fx;
}

public void updateEquationVector(double[] fx) {
if (fx.length != equationCache.getSortedEquationsToSolve().size()) {
if (fx.length != index.getSortedEquationsToSolve().size()) {
throw new IllegalArgumentException("Bad equation vector length: " + fx.length);
}

Stopwatch stopwatch = Stopwatch.createStarted();

Arrays.fill(fx, 0);
for (Equation<V, E> equation : equationCache.getSortedEquationsToSolve().keySet()) {
for (Equation<V, E> equation : index.getSortedEquationsToSolve()) {
fx[equation.getColumn()] = equation.eval();
}

Expand Down Expand Up @@ -380,7 +249,7 @@ public String writeToString() {
}

public List<Pair<Equation<V, E>, Double>> findLargestMismatches(double[] mismatch, int count) {
return getSortedEquationsToSolve().keySet().stream()
return index.getSortedEquationsToSolve().stream()
.map(equation -> Pair.of(equation, mismatch[equation.getColumn()]))
.filter(e -> Math.abs(e.getValue()) > Math.pow(10, -7))
.sorted(Comparator.comparingDouble((Map.Entry<Equation<V, E>, Double> e) -> Math.abs(e.getValue())).reversed())
Expand Down
Loading