Skip to content
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
12 changes: 0 additions & 12 deletions process/core/solver/solver.py
Original file line number Diff line number Diff line change
Expand Up @@ -325,25 +325,13 @@ 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",
"Try changing or adding variables to IXC, or modify",
"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")
)

Expand Down
55 changes: 28 additions & 27 deletions process/core/solver/solver_handler.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"""Module containing solver handler routines"""

import logging
from contextlib import contextmanager

from tabulate import tabulate

Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -346,3 +332,18 @@ def _optimisation_parameters_output(self):
numalign="left",
),
)


@contextmanager
def epsfcn_context(numerics, factor):
"""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
Loading