sandialabs / WecOptTool

WEC Design Optimization Toolbox
https://sandialabs.github.io/WecOptTool/
GNU General Public License v3.0
13 stars 22 forks source link

BUG: WEC.solve does not work if p_max and v_max are too small. #298

Open En-Lo opened 11 months ago

En-Lo commented 11 months ago

Describe the bug by setting PTO force, position and velocity as constraints, I am trying to graph the mechanical power as a function of f_max, p_max, and v_max. I set the range of f_max from 500 to 2000, p_max from 0.01 to 0.05, and v_max from 0.01 to 0.1. But it seems like 0.01 is too small a value for the algorithm to run and the error says "Positive directional derivative for linesearch"

To Reproduce f= np.linspace(500, 2000, 4) p = np.linspace(0.01, 0.05, 4) v_ = np.linspace(0.01, 0.1, 4)

The following are the values that I set for the waves: f1 = 0.05 nfreq = 20 wavefreq = 0.3 amplitude = 1 phase = 30 wavedir = 0

and the scaling: options = {'maxiter': 200} scale_x_wec = 1e1 scale_x_opt = 1e-3 scale_obj = 1e-2

Expected behavior I hoped to produced a graph like this with the mechanical power dependent on f_max, p_max, and v_max:

Screenshot 2023-11-11 at 4 06 58 PM

Observed behavior the error:

Screenshot 2023-11-20 at 4 13 22 PM

System:

Additional information Thank you for helping out!

rebeccamccabe commented 11 months ago

Some additional context: the body is RM3, and the small values of pmax and vmax are being tried because the unsaturated values are this small: p of 0.04 m and v of 0.08 m/s. The unsaturated solve works fine.

ryancoe commented 11 months ago

If I understand correctly you're constraining force, position, and velocity at different levels and looking at the effect on mechanical power for the RM3. If you want to provide your full notebook/script I might be able to say more... is it possible that you're asking for an infeasible solution (see, e.g., https://doi.org/10.1016/j.oceaneng.2013.03.011)?

rebeccamccabe commented 11 months ago

That’s a good point, it’s probably infeasible. Our intent was that the position limit could be enforced with a force that is not coming from the generator and is therefore not constrained by the force limit, ie from a spring loaded bumpstop or a brake, but we would need to implement this as a separate f_add to actually avoid the infeasibility, right now there is no f_add. We will add that and update whether the error resolves. Thanks

rebeccamccabe commented 11 months ago

Like position, the velocity constraint is potentially infeasible when combined with the force constraint. It doesn't make as much physical sense to assume a f_add that brakes the wec when it goes too fast, like it could for position. So we are considering to enforce a different constraint, which limits the velocity at which the PTO can produce force, rather than the velocity itself. This better matches what a generator can do given its torque-speed curve (assuming that the power electronics can handle the extra back emf). This constraint would be conditional (disjunctive): $Fp = 0$ if $\dot{x} \geq \dot{x}\{max}$, and $Fp \leq F{max}$ otherwise.

The can be implemented by introducing a discrete auxiliary variable $a$ and imposing the four linear constraints (using the "big M" disjunction trick):

M a \geq \dot{x} - \dot{x}_{max}
M (1 -a) \geq \dot{x}_{max} - \dot{x}
F_p \leq F_{max} + a
F_p \leq M_2 (1 - a)

for sufficiently large constants $M$ and $M_2$.

We would want to add the auxiliary variable $a$ to x_opt, as in tutorial 4. However, $a$ is binary / discrete, and scipy.optimize doesn't support mixed integer programs except for linear problems. Are there any cases where you have successfully included a binary decision variable in the optimization vector? We can try a continuous relaxation but the big-M constraints are known for having poor continuous relaxations so it might not work.

If this isn't possible, I think we can express the constraints nonlinearly using a continuous auxiliary variable. Or, there is something called the hull reformulation which could keep the constraints linear, but I don't fully understand it yet. Hull reformulation still requires a discrete auxiliary variable, but the continuous relaxation is tighter.

ryancoe commented 11 months ago

We have not, to my knowledge, run a problem like this before. It looks like IPOPT, which we're planning to investigate soon (see #12) might support this type of problem.

However, I don't quite follow why you think it'd be impractical to apply a braking force to control velocity and as with position - this seems perfectly reasonable to me.

rebeccamccabe commented 10 months ago

Sorry for the long delay in reply. I didn't mean that you can't use a brake if you are trying to limit the max speed, since yes that does make sense. I meant that the more realistic constraint is not to limit the max speed, but to limit the max speed at which the generator is applying torque. Generators can generally handle being externally spun at higher than their datasheet "max speed" (up to a point), and the datasheet "max speed" generally refers to the speed at which no more torque can be produced. The true max speed would be set by something else (bearings, vibration, or voltage limit of the drive), and would be higher than the datasheet "max speed" of the generator.

Right now, we are implementing the constraint nonlinearly with a continuous auxiliary variable and still getting the same error, and will update if we find a way to solve it.