
com.powsybl.openloadflow.equations.EquationSystemIndex Maven / Gradle / Ivy
/**
* Copyright (c) 2022, RTE (http://www.rte-france.com)
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
* SPDX-License-Identifier: MPL-2.0
*/
package com.powsybl.openloadflow.equations;
import org.apache.commons.lang3.mutable.MutableInt;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.*;
import java.util.stream.Collectors;
/**
* @author Geoffroy Jamgotchian {@literal }
*/
public class EquationSystemIndex & Quantity, E extends Enum & Quantity>
implements EquationSystemListener {
private static final Logger LOGGER = LoggerFactory.getLogger(EquationSystemIndex.class);
private final Set> equationsToSolve = new HashSet<>();
// variable reference counting in equation terms
private final Map, MutableInt> variablesToFindRefCount = new HashMap<>();
private List> sortedEquationsToSolve = Collections.emptyList();
private List> sortedVariablesToFind = Collections.emptyList();
private boolean equationsIndexValid = false;
private boolean variablesIndexValid = false;
private final List> listeners = new ArrayList<>();
public EquationSystemIndex(EquationSystem equationSystem) {
Objects.requireNonNull(equationSystem).addListener(this);
}
public void addListener(EquationSystemIndexListener listener) {
listeners.add(Objects.requireNonNull(listener));
}
public void removeListener(EquationSystemIndexListener listener) {
listeners.remove(Objects.requireNonNull(listener));
}
private void notifyEquationChange(Equation equation, EquationSystemIndexListener.ChangeType changeType) {
listeners.forEach(listener -> listener.onEquationChange(equation, changeType));
}
private void notifyVariableChange(Variable variable, EquationSystemIndexListener.ChangeType changeType) {
listeners.forEach(listener -> listener.onVariableChange(variable, changeType));
}
private void notifyEquationTermChange(EquationTerm term) {
listeners.forEach(listener -> listener.onEquationTermChange(term));
}
private void update() {
if (!equationsIndexValid) {
sortedEquationsToSolve = equationsToSolve.stream().sorted().collect(Collectors.toList());
int columnCount = 0;
for (Equation equation : sortedEquationsToSolve) {
equation.setColumn(columnCount++);
}
equationsIndexValid = true;
LOGGER.debug("Equations index updated ({} columns)", columnCount);
}
if (!variablesIndexValid) {
sortedVariablesToFind = variablesToFindRefCount.keySet().stream().sorted().collect(Collectors.toList());
int rowCount = 0;
for (Variable variable : sortedVariablesToFind) {
variable.setRow(rowCount++);
}
variablesIndexValid = true;
LOGGER.debug("Variables index updated ({} rows)", rowCount);
}
}
private void addTerm(EquationTerm term) {
notifyEquationTermChange(term);
for (Variable variable : term.getVariables()) {
MutableInt variableRefCount = variablesToFindRefCount.get(variable);
if (variableRefCount == null) {
variableRefCount = new MutableInt(1);
variablesToFindRefCount.put(variable, variableRefCount);
variablesIndexValid = false;
notifyVariableChange(variable, EquationSystemIndexListener.ChangeType.ADDED);
} else {
variableRefCount.increment();
}
}
}
private void addEquation(Equation equation) {
equationsToSolve.add(equation);
equationsIndexValid = false;
for (EquationTerm term : equation.getTerms()) {
if (term.isActive()) {
addTerm(term);
}
}
notifyEquationChange(equation, EquationSystemIndexListener.ChangeType.ADDED);
}
private void removeTerm(EquationTerm term) {
notifyEquationTermChange(term);
for (Variable variable : term.getVariables()) {
MutableInt variableRefCount = variablesToFindRefCount.get(variable);
if (variableRefCount != null) {
variableRefCount.decrement();
if (variableRefCount.intValue() == 0) {
variable.setRow(-1);
variablesToFindRefCount.remove(variable);
variablesIndexValid = false;
notifyVariableChange(variable, EquationSystemIndexListener.ChangeType.REMOVED);
}
}
}
}
private void removeEquation(Equation equation) {
equation.setColumn(-1);
equationsToSolve.remove(equation);
equationsIndexValid = false;
for (EquationTerm term : equation.getTerms()) {
if (term.isActive()) {
removeTerm(term);
}
}
notifyEquationChange(equation, EquationSystemIndexListener.ChangeType.REMOVED);
}
@Override
public void onEquationChange(Equation equation, EquationEventType eventType) {
switch (eventType) {
case EQUATION_REMOVED:
if (equation.isActive()) {
removeEquation(equation);
}
break;
case EQUATION_DEACTIVATED:
removeEquation(equation);
break;
case EQUATION_CREATED:
if (equation.isActive()) {
addEquation(equation);
}
break;
case EQUATION_ACTIVATED:
addEquation(equation);
break;
default:
throw new IllegalStateException("Event type not supported: " + eventType);
}
}
@Override
public void onEquationTermChange(EquationTerm term, EquationTermEventType eventType) {
if (term.getEquation().isActive()) {
switch (eventType) {
case EQUATION_TERM_ADDED:
if (term.isActive()) {
addTerm(term);
}
break;
case EQUATION_TERM_ACTIVATED:
addTerm(term);
break;
case EQUATION_TERM_DEACTIVATED:
removeTerm(term);
break;
default:
throw new IllegalStateException("Event type not supported: " + eventType);
}
}
}
public List> getSortedEquationsToSolve() {
update();
return sortedEquationsToSolve;
}
public List> getSortedVariablesToFind() {
update();
return sortedVariablesToFind;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy