0

I want to find the values of board_trim and lm that will give me the lowest (closest to 0) value for Board_Moments.

For this I use scipy.optimize.minimize, but it does not converge. I really can't figure it out.

with Parameters:

displacement = 70

b = 6.5

deadrise = 20

LCG = 10

Vs_ms = 23.15 #ms

rho = 1025

mu = 1.19e-6

def Board_Moments(params):

    board_trim, lm = params

    displacement_N = displacement * 9.81 #kN  

    lp = Lp(Vs_ms, b, lm)
    N = displacement_N * cos(d2r(board_trim))             #Drag Forces Perpendicular to the keel

    #Taking moments about transom at height of CG

    deltaM = (displacement_N * LCG) - (N * lp) #equilibrium condition
    return deltaM

where lp:

def Lp(Vs_ms, b, lm):

    cv = Cv(Vs_ms, b)
    Lambda = Lambda_(lm, b)
    Cp = 0.75 - (1 / (5.21 * (cv / Lambda)**2 + 2.39))
    lp = Cp * lm
    return lp

and

def Cv(Vs_ms, b):

    cv = Vs_ms / (9.81 * b)**0.5 
    return cv

and

def Lambda_(lm, b):

    lambda_ = lm / b
    return lambda_

the optimization is done with:

board_trim = 2 #initial estimate

lm = 17.754 #initial estimate

x0 = [board_trim, lm]

Deltam = minimize(Board_Moments, x0, method = 'Nelder-Mead')
print(Deltam)

The error I get:

   final_simplex: (array([[ 1.36119237e+01,  3.45635965e+23],
   [-1.36046725e+01,  3.08439110e+23],
   [ 2.07268577e+01,  2.59841956e+23]]), array([-7.64916992e+25, 
   -6.82618616e+25, -5.53373709e+25]))

       fun: -7.649169916342451e+25

   message: 'Maximum number of function evaluations has been exceeded.'

      nfev: 401

       nit: 220

    status: 1

   success: False

         x: array([1.36119237e+01, 3.45635965e+23])

Any help would be much appreciated, thanks

1 Answers1

0

You mention

that will give me the lowest (closest to 0) value for Board_Moments.

But minimize will search the absolute minimum. If you print the intermediate values for deltaM (which you should have done to debug your problem), you'll find they just get smaller and smaller, below zero (so -10, -100, -500 etc. That kind of progression).

To get as close to zero as possible, the solution is simply: return the absolute value of deltaM from Board_Moments:

def Board_Moments(params):
    # code as before ...
    deltaM = (displacement_N * LCG) - (N * lp) #equilibrium condition
    
    # This print function would have shown the problem immediately
    #print(deltaM)

    # Use absolute (the built-in `abs` or `np.abs`; 
    # doesn't really matter for a single value)
    # to get close to zero
    return np.abs(deltaM)

For this particular case and fix, the result I get is:

final_simplex: (array([[ 2.32386388, 15.3390523 ],
       [ 2.32394414, 15.33905343],
       [ 2.32390145, 15.33905283]]), array([5.33445927e-08, 7.27723091e-08, 1.09428584e-07]))
           fun: 5.334459274308756e-08
       message: 'Optimization terminated successfully.'
          nfev: 107
           nit: 59
        status: 0
       success: True
             x: array([ 2.32386388, 15.3390523 ])

(and if you comment out the print function, you'll see it easily converge towards zero.)

9769953
  • 10,344
  • 3
  • 26
  • 37