'How to find the maximum of a function with bounds in Python with Scipy

I would like to find the maximum of a function that depends on 2 parameters. I tried to use scipy.optimize.minimize, but I'm not getting the desired result. My function isn't perfect but it works.

import math
import numpy as np
from scipy.optimize import minimize

def calculations(x0) -> float:
    # Пустые массивы
    t_T = []  # массив времени
    x = []  # перемещение
    x_zvezd = []  # первая производная по перемещению
    x_zvezd_2 = []  # вторая производная по перемещению
    beta = []  # угол поворота
    beta_zvezd = []  # первая производная по углу поворота
    beta_zvezd_2 = []  # вторая производная по углу поворота
    X = []  # гидродинамическая составляющая силы
    Xi = []  # инерционная составляющая силы
    P = []  # упор
    dA = []  # работа

    # Исходные данные
    J = x0[0]  # поступь
    k = 2 / 0.93  # коэффициент
    k_2 = 1
    v0 = 1  # отнормированная скорость набегающего потока
    e_L = 0.1  # относительная толщина профиля
    a_L = 20  # относительный разбег
    koefficent = x0[1]
    f_L = 0  # кривизна
    dt_T = 0.01  # относительный шаг по времени
    Re = 1e6  # Число Рейнольдса
    Sh = math.pi / J  # число Струхаля
    mu = (0.77 * e_L) / (1 - 0.6 * e_L)  # функция относительной толщины профиля
    A_L = 1 / (2 * (1 + mu ** 2))
    alpha = math.atan(2 * f_L * (1 + mu ** 2))
    R = (1 + mu) / math.cos(alpha)
    r = R / (1 + 2 * mu)

    # Расчет присоединенных масс
    mu_11 = (math.pi / 4) * (A_L ** 2) * (r ** 2 + R ** 2 - 2 * math.cos(2 * alpha))
    mu_22 = (math.pi / 4) * (A_L ** 2) * (r ** 2 + R ** 2 + 2 * math.cos(2 * alpha))
    mu_12 = (math.pi / 4) * (A_L ** 2) * math.sin(alpha)
    mu_16 = (math.pi / 8) * (A_L ** 3) * (r ** 2 + R ** 2 + 4 * (r + R) * math.cos(alpha)) * 
    math.sin(alpha)
    mu_26 = (math.pi / 8) * (A_L ** 3) * (
            r ** 3 + R ** 3 + (r ** 2 + R ** 2) * math.cos(alpha) + 2 * (r + R) * math.cos(2 * 
    alpha))

    # Заполнение массива по времени
    for i in range(0, 105):
        t_T.append(float("{0:.2f}".format(i * dt_T)))

    # Заполнение массива по перемещению
    for t in t_T:
        x.append((a_L * (1 - math.cos(t * 2 * math.pi)) ** k_2) / 2)

    # Заполнение массива первых производных по перемещению
    for j in range(len(x) - 1):
        if j == 0:
            x_zvezd.append(0.0)
        elif j != 0:
            x_zvezd.append((x[j + 1] - x[j - 1]) / (2 * dt_T))

    # Заполнение массива вторых производных по перемещению
    for j in range(len(x_zvezd) - 1):
        if j == 0:
            x_zvezd_2.append(0.0)
        elif j != 0:
            x_zvezd_2.append((x_zvezd[j + 1] - x_zvezd[j - 1]) / (2 * dt_T))

    # Заполнение массива углов поворота
    for i in range(len(t_T) - 1):
        beta.append(0.5 * ((math.pi / 2) + math.atan(v0 - koefficent * x_zvezd[i])))

    # Заполнение массива первых производных по углу поворота
    for j in range(len(beta) - 1):
        if j == 0:
            beta_zvezd.append(0.0)
        elif j != 0:
            beta_zvezd.append((beta[j + 1] - beta[j - 1]) / (2 * dt_T))

    # Заполнение массива вторых производных по углу поворота
    for j in range(len(beta_zvezd) - 1):
        if j == 0:
            beta_zvezd_2.append(0.0)
        elif j != 0:
            beta_zvezd_2.append((beta_zvezd[j + 1] - beta_zvezd[j - 1]) / (2 * dt_T))

    # Расчет гидродинамической составляющей силы
    for i in range(len(x_zvezd)):
        # Коэффициент нормальной силы на пластине (Формула Релея)
        C_n = 2 * math.pi * ((math.sin(abs(beta[i]))) / (4 + math.pi * 
    (math.sin(abs(beta[i]))))) 
    * (
            1 - 0.5 + (1.6 / (abs(beta[i]) * (6 / math.pi)) ** 0.7))
    X.append(k * (-(1 + Sh * x_zvezd[i]) * abs(1 + Sh * x_zvezd[i]) * (C_n * math.sin(beta[i]) 
    + (
            ((2 + 2.4 * e_L + 17 * e_L ** 3) * 0.455) / ((math.log10(Re * abs(1 - 
    x_zvezd[i]))) ** 2.58)))))

    # Расчет инерционной составляющей силы
    for i in range(len(beta_zvezd_2)):
        Xi.append(-1 * (-2 * Sh ** 2 * (
                x_zvezd_2[i] * (mu_12 - mu_11 * (math.cos(beta[i])) ** 2 - mu_22 * 
    (math.sin(beta[i])) ** 2) + x_zvezd[
            i] * beta_zvezd[i] * (math.sin(2 * beta[i]) * (mu_11 - mu_22) + 2 * math.cos(2 * 
    beta[i]) * mu_12) -
                beta_zvezd_2[i] * (math.cos(beta[i]) * mu_16 - math.sin(beta[i]) * mu_26) + 
    beta_zvezd[i] ** 2 * (
                    math.sin(beta[i]) * mu_16 + math.cos(beta[i]) * mu_26))))
    Xi[0] = Xi[-2]
    Xi[1] = Xi[-1]

    # Расчет упора
    for i in range(len(Xi)):
        P.append(Xi[i] + X[i])

    # Расчет КПД
    for i in range(len(P)):
        dA.append(x_zvezd[i] * dt_T * P[i])  # работа

    A = -sum(dA)  # суммарная работа
    P_average = sum(P) * dt_T  # средний по периоду упор
    kpd = P_average / (Sh * A)  # КПД

    return kpd

def main():
    bounds_J = (0, 106)
    bounds_koef = (0, 10)
    bounds = [bounds_J, bounds_koef]

    x = np.array([80, 7])

    result = minimize(lambda x1: -calculations(x), x, method="powell", bounds=bounds)
    print(result)
    print(calculations(result.x))


if __name__ == '__main__':
    main()

My "calculation" function finds the efficiency of one device. It depends on two parameters - J and koef. I know the boundaries in which these parameters should be. But when I run the optimization, I get the following result:

   direc: array([[1., 0.],
   [0., 1.]])
 fun: -0.359067056442705
 message: 'Optimization terminated successfully.'
nfev: 56
 nit: 1
 status: 0
 success: True
   x: array([105.99994303,   9.99994039])
 0.1699093921318917

 Process finished with exit code 0

The problem is that I am absolutely sure that this is the wrong result. Since with the parameters J=80 and koef = 10, I get the result 0.36. And I don't understand why optimization doesn't find the parameters I need.



Solution 1:[1]

I added the <button> element inside the <body> element and gave height to the <body> element so that the onscroll event could be triggered. In this case the <button> works fine when the onscroll event is triggered. The scrollbar must be opened for the onscroll event to be triggered. The page height must be greater than the full screen height for the scrollbar to open.

mybutton = document.getElementById("myBtn");

function scrollFunction() {
  console.log(document.body.scrollTop )
  console.log(document.documentElement.scrollTop)
  
  if (document.body.scrollTop > 20 || document.documentElement.scrollTop > 20) 
    mybutton.style.display = "block";
  else 
    mybutton.style.display = "none";
}

function topFunction() {
  document.body.scrollTop = 0;
  document.documentElement.scrollTop = 0;
}

window.onscroll = function() {
  scrollFunction()
}

scrollFunction();
body{
  height: 804px;
}

#myBtn {
    display: none;
    position: fixed;
    bottom: 20px;
    right: 30px;
    z-index: 99;
    border: none;
    outline: none;
    background-color: red;
    color: white;
    cursor: pointer;
    padding: 15px;
    border-radius: 10px;
    font-size: 18px;
}

#myBtn:hover {
    background-color: #555;
}
<body>
  <button onclick="topFunction()" id="myBtn" title="Go to top">Top</button>
</body>

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1