From d60cb87f010b3740e46e46f16408e02f12941d57 Mon Sep 17 00:00:00 2001 From: jarchambault Date: Fri, 13 Dec 2024 13:27:16 +0100 Subject: [PATCH] Add getter and setter for static field knitroParameters Signed-off-by: jarchambault --- .../knitro/solver/KnitroSolver.java | 105 +++++++++++++----- 1 file changed, 79 insertions(+), 26 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/knitro/solver/KnitroSolver.java b/src/main/java/com/powsybl/openloadflow/knitro/solver/KnitroSolver.java index 5846e5f..e6683b3 100644 --- a/src/main/java/com/powsybl/openloadflow/knitro/solver/KnitroSolver.java +++ b/src/main/java/com/powsybl/openloadflow/knitro/solver/KnitroSolver.java @@ -40,11 +40,33 @@ public class KnitroSolver extends AbstractAcSolver { protected static KnitroSolverParameters knitroParameters = new KnitroSolverParameters(); - public KnitroSolver(LfNetwork network, KnitroSolverParameters knitroParameters, - EquationSystem equationSystem, JacobianMatrix j, - TargetVector targetVector, EquationVector equationVector, - boolean detailedReport) { + public KnitroSolver( + LfNetwork network, + KnitroSolverParameters knitroParameters, + EquationSystem equationSystem, + JacobianMatrix j, + TargetVector targetVector, + EquationVector equationVector, + boolean detailedReport) { + super(network, equationSystem, j, targetVector, equationVector, detailedReport); + + // Initialize static parameters only if it hasn't been set + if (KnitroSolver.knitroParameters == null) { + KnitroSolver.knitroParameters = knitroParameters; + } else { + LOGGER.warn("knitroParameters is already set and will not be overwritten."); + } + } + + // Getter for accessing knitroParameters + public static KnitroSolverParameters getKnitroParameters() { + return knitroParameters; + } + + // Setter for modification + public static synchronized void setKnitroParameters(KnitroSolverParameters knitroParameters) { + LOGGER.info("Setting new knitroParameters."); KnitroSolver.knitroParameters = knitroParameters; } @@ -116,13 +138,15 @@ public class VariableBounds { private final List lowerBounds; private final List upperBounds; - public VariableBounds(List> sortedVariables, KnitroSolverParameters knitroParameters) { + public VariableBounds(List> sortedVariables) { this.lowerBounds = new ArrayList<>(); this.upperBounds = new ArrayList<>(); - setBounds(sortedVariables, knitroParameters); + setBounds(sortedVariables); } - private void setBounds(List> sortedVariables, KnitroSolverParameters knitroParameters) { + private void setBounds(List> sortedVariables) { + KnitroSolverParameters knitroParameters = KnitroSolver.getKnitroParameters(); + double loBndV = knitroParameters.getLowerVoltageBound(); double upBndV = knitroParameters.getUpperVoltageBound(); @@ -208,9 +232,9 @@ public void addConstraint(int equationId, KnitroProblem knitroProblem, List listVar = solverUtils.getLinearConstraint(typeEq, equationId, terms).getListIdVar(); + List listVar = solverUtils.getLinearConstraint(typeEq, terms).getListIdVar(); - List listCoef = solverUtils.getLinearConstraint(typeEq, equationId, terms).getListCoef(); + List listCoef = solverUtils.getLinearConstraint(typeEq, terms).getListCoef(); for (int i = 0; i < listVar.size(); i++) { knitroProblem.addConstraintLinearPart(equationId, listVar.get(i), listCoef.get(i)); @@ -243,19 +267,31 @@ public void setJacobianMatrix(KnitroProblem knitroProblem, LfNetwork lfNetwork, List> sortedEquationsToSolve, List listNonLinearConsts, List listNonZerosCtsDense, List listNonZerosVarsDense, List listNonZerosCtsSparse, List listNonZerosVarsSparse) throws KNException { + + // Fetch the shared knitroParameters instance + KnitroSolverParameters knitroParameters = KnitroSolver.getKnitroParameters(); + int numVar = equationSystem.getVariableSet().getVariables().size(); if (knitroParameters.getGradientComputationMode() == 1) { // User routine to compute the Jacobian if (knitroParameters.getGradientUserRoutine() == 1) { - // Dense method : when computing the Jacobian matrix, all non-linear constraints are considered as a function of all variables. + // Dense method: all non-linear constraints are considered as a function of all variables. buildDenseJacobianMatrix(numVar, listNonLinearConsts, listNonZerosCtsDense, listNonZerosVarsDense); knitroProblem.setJacNnzPattern(listNonZerosCtsDense, listNonZerosVarsDense); } else if (knitroParameters.getGradientUserRoutine() == 2) { - // Sparse method : when computing the Jacobian matrix, non-linear constraints derivates are evaluated only with respect to variables the constraints really depend off. + // Sparse method: compute Jacobian only for variables the constraints depend on. buildSparseJacobianMatrix(sortedEquationsToSolve, listNonLinearConsts, listNonZerosCtsSparse, listNonZerosVarsSparse); knitroProblem.setJacNnzPattern(listNonZerosCtsSparse, listNonZerosVarsSparse); } - // If the user decided to directly pass the Jacobian to the solver, we set the callback for gradient evaluations. - knitroProblem.setGradEvalCallback(new KnitroProblem.CallbackEvalG(jacobianMatrix, listNonZerosCtsDense, listNonZerosVarsDense, listNonZerosCtsSparse, listNonZerosVarsSparse, lfNetwork, equationSystem)); + // Set the callback for gradient evaluations if the user directly passes the Jacobian to the solver. + knitroProblem.setGradEvalCallback(new KnitroProblem.CallbackEvalG( + jacobianMatrix, + listNonZerosCtsDense, + listNonZerosVarsDense, + listNonZerosCtsSparse, + listNonZerosVarsSparse, + lfNetwork, + equationSystem + )); } } @@ -379,12 +415,16 @@ public void evaluateGA(final List x, final List objGrad, final L equationSystem.getStateVector().set(toArray(x)); AcSolverUtil.updateNetwork(network, equationSystem); oldMatrix.forceUpdate(); + // For sparse matrix, get values, row and column structure SparseMatrix sparseOldMatrix = oldMatrix.getMatrix().toSparse(); int[] columnStart = sparseOldMatrix.getColumnStart(); int[] rowIndices = sparseOldMatrix.getRowIndices(); double[] values = sparseOldMatrix.getValues(); + // Dynamically fetch Knitro parameters + KnitroSolverParameters knitroParameters = KnitroSolver.getKnitroParameters(); + // Number of constraints evaluated in callback int numCbCts = 0; if (knitroParameters.getGradientUserRoutine() == 1) { @@ -422,7 +462,11 @@ public void evaluateGA(final List x, final List objGrad, final L } jac.set(index, valueSparse); } catch (Exception e) { - LOGGER.error("Exception found while trying to add Jacobian term {} in non-linear constraint n° {}", listNonZerosVarsSparse.get(index), listNonZerosCtsSparse.get(index)); + LOGGER.error( + "Exception found while trying to add Jacobian term {} in non-linear constraint n° {}", + listNonZerosVarsSparse.get(index), + listNonZerosCtsSparse.get(index) + ); LOGGER.error(e.getMessage()); } } @@ -446,7 +490,7 @@ public void evaluateH(final List x, final double sigma, final List equationSystem, TargetVector targetVector, VoltageInitializer voltageInitializer, JacobianMatrix jacobianMatrix, KnitroSolverParameters knitroParameters) throws KNException { + private KnitroProblem(LfNetwork lfNetwork, EquationSystem equationSystem, TargetVector targetVector, VoltageInitializer voltageInitializer, JacobianMatrix jacobianMatrix) throws KNException { // =============== Variables =============== // Defining variables @@ -462,7 +506,7 @@ private KnitroProblem(LfNetwork lfNetwork, EquationSystem constraintValues = solver.getConstraintValues(); acStatus = KnitroStatus.fromStatusCode(solution.getStatus()).toAcSolverStatus(); - logKnitroStatus(KnitroStatus.fromStatusCode(solution.getStatus())); // convert and log Knitro's status + logKnitroStatus(KnitroStatus.fromStatusCode(solution.getStatus())); nbIter = solver.getNumberIters(); // Log solution @@ -581,15 +633,15 @@ public AcSolverResult run(VoltageInitializer voltageInitializer, ReportNode repo LOGGER.debug(" violation[{}] = {} ", i, solver.getConViol(i)); } - // Load results in the network + // Update the network if required if (acStatus == AcSolverStatus.CONVERGED || knitroParameters.isAlwaysUpdateNetwork()) { - equationSystem.getStateVector().set(toArray(solution.getX())); //update equation system - for (Equation equation : equationSystem.getEquations()) { //update terms + equationSystem.getStateVector().set(toArray(solution.getX())); // update equation system + for (Equation equation : equationSystem.getEquations()) { // update terms for (EquationTerm term : equation.getTerms()) { term.setStateVector(equationSystem.getStateVector()); } } - AcSolverUtil.updateNetwork(network, equationSystem); //update network + AcSolverUtil.updateNetwork(network, equationSystem); // update network } } catch (KNException e) { @@ -599,4 +651,5 @@ public AcSolverResult run(VoltageInitializer voltageInitializer, ReportNode repo double slackBusActivePowerMismatch = network.getSlackBuses().stream().mapToDouble(LfBus::getMismatchP).sum(); return new AcSolverResult(acStatus, nbIter, slackBusActivePowerMismatch); } + }