From 87c9f0570e88de55217e0103529689089a973889 Mon Sep 17 00:00:00 2001 From: james <81617086+je-cook@users.noreply.github.com> Date: Fri, 14 Aug 2026 09:06:30 +0100 Subject: [PATCH 1/3] Re-remove accidentally readded exit conditions --- process/core/solver/solver.py | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/process/core/solver/solver.py b/process/core/solver/solver.py index 269177e338..513bebeafa 100644 --- a/process/core/solver/solver.py +++ b/process/core/solver/solver.py @@ -325,11 +325,6 @@ def verror(self): "A feasible solution may be difficult to achieve.", "Try changing or adding variables to IXC.", ), - 4: ( - "An uphill search direction was found.", - "Try changing the equations in ICC, or", - "adding new variables to IXC.", - ), SolverOutputCondition.NO_SOLUTION: ( "The quadratic programming technique was unable to", "find a feasible point.\n", @@ -337,13 +332,6 @@ def verror(self): "their initial values (especially if only 1 optimisation", "iteration was performed).", ), - 6: ( - "The quadratic programming technique was restricted", - "by an artificial bound, or failed due to a singular", - "matrix.", - "Try changing the equations in ICC, or", - "adding new variables to IXC.", - ), }.get(self.info, "Unknown Error code") ) From 9f129e3bcdd092e870b3c7d2c520be5e7ebb8a12 Mon Sep 17 00:00:00 2001 From: james <81617086+je-cook@users.noreply.github.com> Date: Fri, 14 Aug 2026 09:10:24 +0100 Subject: [PATCH 2/3] failed rebase missing extra --- process/core/solver/solver_handler.py | 55 ++++++++++++++------------- 1 file changed, 28 insertions(+), 27 deletions(-) diff --git a/process/core/solver/solver_handler.py b/process/core/solver/solver_handler.py index 4901d5983a..1a672a03cd 100644 --- a/process/core/solver/solver_handler.py +++ b/process/core/solver/solver_handler.py @@ -1,6 +1,7 @@ """Module containing solver handler routines""" import logging +from contextlib import contextmanager from tabulate import tabulate @@ -50,14 +51,9 @@ def run(self): # Initialise iteration variables and bounds in Python: relies on Fortran # iteration variables being defined above # Trim maximum size arrays down to actually used size - n = self.data.numerics.nvar - x = self.data.numerics.xcm[:n] - bndl = self.data.numerics.itv_scaled_lower_bounds[:n] - bndu = self.data.numerics.itv_scaled_upper_bounds[:n] - - # Define total number of constraints and equality constraints - m = self.data.numerics.neqns + self.data.numerics.nineqns - meq = self.data.numerics.neqns + x = self.data.numerics.xcm[: self.data.numerics.nvar] + bndl = self.data.numerics.itv_scaled_lower_bounds[: self.data.numerics.nvar] + bndu = self.data.numerics.itv_scaled_upper_bounds[: self.data.numerics.nvar] # Evaluators() calculates the objective and constraint functions and # their gradients for a given vector x @@ -68,31 +64,21 @@ def run(self): self.solver.set_evaluators(evaluators) self.solver.set_bounds(bndl, bndu) self.solver.set_opt_params(x) - self.solver.set_constraints(m, meq) + # Define total number of constraints and equality constraints + self.solver.set_constraints( + m=self.data.numerics.neqns + self.data.numerics.nineqns, + meq=self.data.numerics.neqns, + ) ifail = self.solver.solve() # If VMCON optimisation has failed then try altering value of epsfcn if self.solver_name == "vmcon": if ifail != SolverOutputCondition.CONVERGED: - print("Trying again with new epsfcn") - # epsfcn is only used in evaluators.Evaluators() - # TODO epsfcn could be set in Evaluators instance now, don't need to - # set/unset in self.data.numerics module - self.data.numerics.epsfcn *= 10 # try new larger value - print("new epsfcn = ", self.data.numerics.epsfcn) - - ifail = self.solver.solve() - # First solution attempt failed - # (ifail != SolverOutputCondition.CONVERGED): supply ifail value - # to next attempt - self.data.numerics.epsfcn /= 10 # reset value - + with epsfcn_context(self.data.numerics, 10): + ifail = self.solver.solve() if ifail != SolverOutputCondition.CONVERGED: - print("Trying again with new epsfcn") - self.data.numerics.epsfcn /= 10 # try new smaller value - print("new epsfcn = ", self.data.numerics.epsfcn) - ifail = self.solver.solve() - self.data.numerics.epsfcn *= 10 # reset value + with epsfcn_context(self.data.numerics, 0.1): + ifail = self.solver.solve() # If VMCON has exited with error code 5 # (ifail = SolverOutputCondition.NO_SOLUTION) try another run using a @@ -346,3 +332,18 @@ def _optimisation_parameters_output(self): numalign="left", ), ) + + +@contextmanager +def epsfcn_context(numerics, factor=10): + """Set and then reset epsfcn value""" + print("Trying again with new epsfcn") + # epsfcn is only used in evaluators.Evaluators() + # TODO epsfcn could be set in Evaluators instance now, don't need to + # set/unset in numerics module + numerics.epsfcn *= factor # try new larger value + print("new epsfcn = ", numerics.epsfcn) + try: + yield + finally: + numerics.epsfcn /= factor # reset value From 56a703c22746119a5079ea2b4766db1ae8c9596b Mon Sep 17 00:00:00 2001 From: james <81617086+je-cook@users.noreply.github.com> Date: Fri, 14 Aug 2026 09:54:14 +0100 Subject: [PATCH 3/3] remove default factor --- process/core/solver/solver_handler.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/process/core/solver/solver_handler.py b/process/core/solver/solver_handler.py index 1a672a03cd..ecd5059493 100644 --- a/process/core/solver/solver_handler.py +++ b/process/core/solver/solver_handler.py @@ -335,7 +335,7 @@ def _optimisation_parameters_output(self): @contextmanager -def epsfcn_context(numerics, factor=10): +def epsfcn_context(numerics, factor): """Set and then reset epsfcn value""" print("Trying again with new epsfcn") # epsfcn is only used in evaluators.Evaluators()