1

I'm using the pyOptSparseDriver and my optimizer is SLSQP. I have a design variable A defined with

ivc = om.IndepVarComp()
ivc.add_output("A", 2.00)
...
prob.model.add_design_var("A", lower=1.6, upper=5.00, ref=1.6)

A represents the aspect ratio of a torus, so it always needs to be larger than 1 to make physical sense; here I've given it a slightly higher 'reasonable' lower bound.

In a component -- actually the first component in the first group in the model -- I see that A is being given negative values in its input, and even nan (which results in errors and eventually halting the code). The component is an ExplicitComponent and the group that it's in does not have a specific solver attached; the n2 shows that it's LN:RUNONCE.

Is this expected behavior? Is there a way to prevent this from happening?

Things I've tried

Changing from pyOptSparseDriver to ScipyOptimizerDriver results in not raising this issue, but I might like to use the former for other reasons.

I have other variables named A elsewhere in the model (but encapsulated within groups) so I suspected this might be a bug related to naming; I tried renaming A to Asp (which is unique in my model) but the issue still occurred.

Why I don't have a MWE

I tried removing parts of the model after this initial group, but in doing so I had to change the objective function. Then, the issue no longer occurred.

Possible hints?

Later in the model I have a group with a NewtonSolver, which I'll call secondsolver. It uses a Armijo linesearch with the default parameters for rho and c.

newton.linesearch = om.ArmijoGoldsteinLS(retry_on_analysis_error=True,
            rho=0.5, c=0.1, method="Armijo", bound_enforcement="vector")

I added a print statement the component's compute function; when I run the code it outputs

...

===========
thirdsolver
===========
NL: Newton 0 ; 6.54500652 1
|  LS: BCHK 0 ; 0.000394994169 6.03504623e-05
NL: Newton 1 ; 4.4408921e-17 6.7851607e-18
NL: Newton Converged
A in compute is [-37490.25190183]
A in compute is [-18743.90453135]
A in compute is [-9370.73084611]
A in compute is [-4684.1440035]
A in compute is [-2340.85058219]
A in compute is [-1169.20387153]
A in compute is [-583.3805162]
A in compute is [-290.46883854]
A in compute is [-144.01299971]
A in compute is [-70.78508029]
A in compute is [-34.17112058]
<test.py>:104: RuntimeWarning: invalid value encountered in power
<problematic line here; it's from the
 analytic derivative of this first component, where A is being raised to a small, constant, nonzero power>
A in compute is [nan]

Here thirdsolver is a NewtonSolver later in the model. Maybe the printing is occurring out-of-order? Anyway, the values for A each differ by a factor of 2 (at least at the higher values), so perhaps that's related to rho=0.5. If I change the parameters rho or c on that linesearch the error no longer occurs.

I can slightly change one of those parameters and move on, but if there's a better explanation for what's going on, I'd like to be able to avoid it in the future.

  • I don't understand the link to the Newtonsolver. If the variable `A` is being converged by a solver, then its not being optimized. perhaps include an XDSM or N2 diagram that shows the layout of the model more clearly? – Justin Gray Mar 11 '21 at 12:59
  • It turns out there probably is no link to the Newtonsolver. `A` is a design variable and the NewtonSolver shouldn't be touching it. I was just grasping at straws. – Jacob Schwartz Mar 11 '21 at 20:25

1 Answers1

1

In older versions of SLSQP, there were bugs in the design variable bounds enforcement. This was fixed in the scipy SLSQP code base, but never in the pyoptsparse one. In other words the SLSQP code in the two code bases is not the same, and has diverged a bit. That explains why ScipyOptimizerDriver is respecting your bounds and pyOptSparseDriver is not (when using SLSQP). If you switch to IPOPT in pyOptSparse, then it would respect your bounds.

Justin Gray
  • 5,605
  • 1
  • 11
  • 16