# -*- coding: utf-8 -*-
"""
Hydrodynamic models for the linear wave-to-motion **transfer functions of ship responses**.
.. dropdown:: Copyright (C) 2023-2026 Technical University of Denmark, R.E.G. Mounet
:color: primary
:icon: law
*This code is part of the NetSSE software.*
NetSSE is free software: you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation, either version 3 of the License, or (at your
option) any later version.
NetSSE is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License along
with this program. If not, see https://www.gnu.org/licenses/.
To credit the author, users are encouraged to use below reference:
.. code-block:: text
Mounet, R. E. G., & Nielsen, U. D. NetSSE: An open-source Python package
for network-based sea state estimation from ships, buoys, and other
observation platforms (version 2.3). Technical University of Denmark,
GitLab. July 2026. https://doi.org/10.11583/DTU.26379811.
*Last updated on 05-06-2026 by R.E.G. Mounet*
"""
import warnings
import numpy as np
from scipy.optimize import fsolve
from netsse.config import config
from netsse.dataset import load_keras_model_from_url
from netsse.model.envir_cond import lin_disprel
from netsse.tools.misc_func import re_range
# import warnings
[docs]
def heaveCF(om0, beta_deg, U, L, B0, T, C_B=1, gravity=None):
"""Computes the heave transfer function amplitude, using the closed-form
expressions proposed by Jensen et al. (2004), for a box-shaped uniformly-loaded
**monohull ship**.
Parameters
----------
om0 : array_like of shape (Nom0,)
Vector of absolute wave frequencies [rad/s].
beta_deg : array_like of shape (Nbeta,)
Vector of heading angles [deg].
U : float
Vessel forward speed [m/s].
L : float
Length of the ship [m].
B0 : float
Breadth of the ship [m].
T : float
Draft of the ship [m].
C_B : float, default 1
Block coefficient of the ship [-].
gravity : float, optional
Gravitational acceleration [m/s^2]. If None, the default value from the NetSSE configuration is used.
Returns
-------
heave : numpy.ndarray of shape (Nom0,Nbeta)
Coefficients of the heave transfer function amplitude [m/m].
See Also
--------
pitchCF, rollCF : Computes the pitch/roll transfer function amplitude
using closed-form expressions.
References
----------
Jensen, J. J., Mansour, A. E., & Olsen, A. S. (2004). Estimation of ship
motions using closed-form expressions. Ocean Engineering, 31(1), 61–85.
https://doi.org/10.1016/S0029-8018(03)00108-2
Example
-------
>>> heave = heaveCF(om0,beta_deg,U,L,B0,T,C_B=1)
"""
# warnings.filterwarnings("ignore", category=RuntimeWarning)
# Gravitational acceleration [m/s^2]:
g = gravity if gravity is not None else config.gravity
beta = np.array(beta_deg * np.pi / 180).reshape((-1, 1))
Fn = U / np.sqrt(g * L)
k = np.square(om0) / g
k[np.where(k < 1e-9)] = 1e-9
B = B0 * C_B # correction of the breadth B0 for shape effect of the hull geometry
heave = np.zeros((len(om0), len(beta)))
for i, beta_i in enumerate(beta):
alpha = 1 - Fn * np.sqrt(k * L) * np.cos(beta_i)
ome = om0 - k * U * np.cos(beta_i)
A = 2 * np.sin(np.square(ome) * B / (2 * g)) * np.exp(-np.square(ome) * T / g)
ke = np.abs(k * np.cos(beta_i))
f = np.sqrt((1 - k * T) ** 2 + (A**2 / (k * B * alpha**3)) ** 2)
kappa = np.exp(-k * T)
F = kappa * f * 2 / (ke * L) * np.sin(ke * L / 2)
eta = 1 / np.sqrt(
(1 - 2 * k * T * alpha**2) ** 2 + (A**2 / (k * B * alpha**2)) ** 2
)
heave[:, i] = np.reshape(eta * np.abs(F), (-1,))
# warnings.filterwarnings("default", category=RuntimeWarning)
return heave
[docs]
def pitchCF(om0, beta_deg, U, L, B0, T, C_B=1, gravity=None):
"""Computes the pitch transfer function amplitude, using the closed-form
expressions proposed by Jensen et al. (2004), for a box-shaped uniformly-loaded
**monohull ship**.
Parameters
----------
om0 : array_like of shape (Nom0,)
Vector of absolute wave frequency [rad/s].
beta_deg : array_like of shape (Nbeta,)
Vector of heading angle [deg].
U : float
Vessel forward speed [m/s].
L : float
Length of the ship [m].
B0 : float
Breadth of the ship [m].
T : float
Draft of the ship [m].
C_B : float, default 1
Block coefficient of the ship [-].
gravity : float, optional
Gravitational acceleration [m/s^2]. If None, the default value from the NetSSE configuration is used.
Returns
-------
pitch : numpy.ndarray of shape (Nom0,Nbeta)
Coefficients of the pitch transfer function amplitude [rad/m].
See Also
--------
heaveCF, rollCF : Computes the heave/roll transfer function amplitude using
closed-form expressions.
References
----------
Jensen, J. J., Mansour, A. E., & Olsen, A. S. (2004). Estimation of ship
motions using closed-form expressions. Ocean Engineering, 31(1), 61–85.
https://doi.org/10.1016/S0029-8018(03)00108-2
Example
-------
>>> pitch = pitchCF(om0,beta_deg,U,L,B0,T,C_B=1)
"""
# warnings.filterwarnings("ignore", category=RuntimeWarning)
# Gravitational acceleration [m/s^2]:
g = gravity if gravity is not None else config.gravity
beta = np.array(beta_deg * np.pi / 180).reshape((-1, 1))
Fn = U / np.sqrt(g * L)
k = np.square(om0) / g
k[np.where(k < 1e-9)] = 1e-9
B = B0 * C_B # correction of the breadth B0 for shape effect of the hull geometry
pitch = np.zeros((len(om0), len(beta)))
for i, beta_i in enumerate(beta):
# In case beta==90 deg or 270 deg, the amplitude of pitch is taken as
# 10% of the amplitude at beta==100 deg (would be zero otherwise):
# if (beta_i+np.pi/2)%np.pi == 0.:
# beta_i += np.pi/180
# eta = 1.0
# else:
# eta = 1.0
alpha = 1 - Fn * np.sqrt(k * L) * np.cos(beta_i)
ome = om0 - k * U * np.cos(beta_i)
A = 2 * np.sin(np.square(ome) * B / (2 * g)) * np.exp(-np.square(ome) * T / g)
ke = np.abs(k * np.cos(beta_i))
f = np.sqrt((1 - k * T) ** 2 + (A**2 / (k * B * alpha**3)) ** 2)
kappa = np.exp(-k * T)
G = (
kappa
* f
* 24
/ ((ke * L) ** 2 * L)
* (np.sin(ke * L / 2) - ke * L / 2 * np.cos(ke * L / 2))
)
eta = 1 / np.sqrt(
(1 - 2 * k * T * alpha**2) ** 2 + (A**2 / (k * B * alpha**2)) ** 2
)
pitch[:, i] = np.reshape(eta * np.abs(G), (-1,))
# warnings.filterwarnings("default", category=RuntimeWarning)
return pitch
[docs]
def rollCF(
om0,
beta_deg,
U,
L,
B0,
T,
C_B,
C_WP,
GM_T,
kappa,
mu,
T_N=0,
gravity=None,
rho=None,
):
"""Computes the roll transfer function amplitude, using the closed-form
expressions proposed by Jensen et al. (2004), for a **monohull ship**.
Parameters
----------
om0 : array_like of shape (Nom0,)
Vector of absolute wave frequencies [rad/s].
beta_deg : array_like of shape (Nbeta,)
Vector of heading angles [deg].
U : float
Vessel forward speed [m/s].
L : float
Length of the ship [m].
B0 : float
Breadth of the ship [m].
T : float
Draft of the ship [m].
C_B : float
Block coefficient of the ship [-].
C_WP : float
Waterplane area coefficient of the ship [-].
GM_T : float
Transverse metacentric height [m].
kappa : float
Custom parameter (chosen between 0 and ``C_WP``) representing the ratio
between the length of the aft beam and the whole ship length in the
simplified ship model for roll.
mu : float, default 0
Ratio between added viscous damping and critical damping.
T_N : float, optional
Roll natural period [s].
.. note::
If not specified as input, ``T_N`` is calculated using empirical
formulas from ADA147598.
gravity : float, optional
Gravitational acceleration [m/s^2]. If None, the default value from the NetSSE configuration is used.
rho : float, optional
Density of seawater [kg/m^3]. If None, the default value from the NetSSE configuration is used.
Returns
-------
roll : numpy.ndarray of shape (Nom0,Nbeta)
Coefficients of the roll transfer function amplitude [rad/m].
See Also
--------
heaveCF, pitchCF : Computes the heave/pitch transfer function amplitude using
closed-form expressions.
References
----------
1. Jensen, J. J., Mansour, A. E., & Olsen, A. S. (2004). Estimation of ship
motions using closed-form expressions. Ocean Engineering, 31(1), 61–85.
https://doi.org/10.1016/S0029-8018(03)00108-2
2. ADA147598, 1973. Code of Safety for Fishermen and Fishing Vessels.
Part B. Safety and Health Requirements for the Construction and Equipment
of Fishing Vessels. Inter-Governmental Maritime Consultative Organization,
London, England.
Example
-------
>>> roll = rollCF(om0,beta_deg,U,L,B0,T,C_B,C_WP,GM_T,kappa,mu,T_N=0)
"""
# warnings.filterwarnings("ignore", category=RuntimeWarning)
# Physical quantities:
# - Gravitational acceleration [m/s^2]:
g = gravity if gravity is not None else config.gravity
# - Density of seawater [kg/m^3]:
rho = rho if rho is not None else config.rho
roll = np.zeros((len(om0), len(beta_deg)))
if om0[0,] == 0.0:
om0 = om0[1:,]
start_om = int(1)
else:
start_om = int(0)
beta = np.radians(beta_deg)
k = om0**2 / g
k[np.where(k < 1e-100)] = 1e-100
delta = np.amax((C_WP - kappa, 0))
gamma = np.amax((kappa / (1 - delta), 1 / 6))
B1 = gamma * B0
# The ship draught T should be less than B0 and B1, and should not be
# lower than B0/6 and B1/6:
T = np.amax((np.amin((T, B0, B1)), B0 / 6, B1 / 6))
Delta = L * B0 * T * C_B * rho # Displacement [kg]
# Roll natural period [s]:
if T_N == 0:
# Select the factor for the rolling period (found in IMO A.685(17)
# resolution and ADA147598):
if L < 45:
f = 0.4
else:
f = 0.373 + 0.023 * (B0 / T) - 0.043 * (L / 100)
T_N = 2 * f * B0 / np.sqrt(GM_T)
C44 = g * Delta * GM_T # Restoring moment coefficient
B44_crit = C44 * T_N / np.pi # Critical roll damping
A0 = C_B * B0 * T / (delta + gamma * (1 - delta))
A1 = gamma * A0
if (B0 / T >= 3) & (B0 / T <= 6):
aBT0 = 0.256 * B0 / T - 0.286
bBT0 = -0.11 * B0 / T - 2.55
dBT0 = 0.033 * B0 / T - 1.419
elif (B0 / T >= 0.99) & (B0 / T < 3):
aBT0 = -3.94 * B0 / T + 13.69
bBT0 = -2.12 * B0 / T - 1.89
dBT0 = 1.16 * B0 / T - 7.97
if (B1 / T >= 3) & (B1 / T <= 6):
aBT1 = 0.256 * B1 / T - 0.286
bBT1 = -0.11 * B1 / T - 2.55
dBT1 = 0.033 * B1 / T - 1.419
elif (B1 / T >= 0.99) & (B1 / T < 3):
aBT1 = -3.94 * B1 / T + 13.69
bBT1 = -2.12 * B1 / T - 1.89
dBT1 = 1.16 * B1 / T - 7.97
for i, beta_i in enumerate(beta):
ome = np.abs(om0 - k * U * np.cos(beta_i))
ome[np.where(ome < 1e-100)] = 1e-100
ke = np.abs(k * np.cos(beta_i))
ke[np.where(ke < 1e-100)] = 1e-100
b44_0 = (
rho
* A0
* B0**2
* np.sqrt(2 * g / B0)
* aBT0
* np.exp(bBT0 * ome ** (-1.3))
* ome**dBT0
)
b44_0[np.where(b44_0 < 1e-100)] = 1e-100
b44_1 = (
rho
* A1
* B1**2
* np.sqrt(2 * g / B1)
* aBT1
* np.exp(bBT1 * ome ** (-1.3))
* ome**dBT1
)
kappa = np.sqrt(1 + (b44_1 - b44_0) / b44_0)
B44_invisc = (
L * b44_0 * (delta + kappa**2 * (1 - delta))
) # Roll hydrodynamic damping
B44_tot = B44_invisc + mu * B44_crit
# Amplitude of the roll excitation moment:
M_abs = (
np.abs(np.sin(beta_i))
* np.sqrt(rho * g**2 / ome)
* 2
/ ke
* np.sqrt(b44_0)
* np.sqrt(
np.sin(0.5 * delta * L * ke) ** 2
+ kappa**2 * np.sin(0.5 * (1 - delta) * L * ke) ** 2
+ 2
* kappa
* np.sin(0.5 * delta * L * ke)
* np.sin(0.5 * (1 - delta) * L * ke)
* np.cos(0.5 * L * ke)
)
)
roll[start_om:, i] = M_abs / np.sqrt(
(-(ome**2) * (T_N / (2 * np.pi)) ** 2 + 1) ** 2 * C44**2
+ ome**2 * B44_tot**2
)
# warnings.filterwarnings("default", category=RuntimeWarning)
return roll
[docs]
def heaveST(om0, beta_deg, U, L, B0, T, C_B):
"""Computes the heave transfer function amplitude and phase, using an ANN-based surrogate model of a strip theory code.
The ANN was trained on data from a linear strip theory solver, the so-called New Strip Method (Takagi and Ganno, 1967), in which the Lewis form approximation of ship cross-sections is adopted. Further details of the implementation can be found in Takami et al. (2026).
Parameters
----------
om0 : array_like of shape (Nom0,)
Vector of absolute wave frequencies [rad/s].
beta_deg : array_like of shape (Nbeta,)
Vector of relative wave heading angles [deg].
U : float
Vessel forward speed [m/s].
L : float
Length of the ship [m].
B0 : float
Breadth of the ship [m].
T : float
Draft of the ship [m].
C_B : float, default 1
Block coefficient of the ship [-].
Returns
-------
heave_amp : numpy.ndarray of shape (Nom0,Nbeta)
Coefficients of the heave transfer function amplitude [m/m].
heave_phase : numpy.ndarray of shape (Nom0,Nbeta)
Coefficients of the heave transfer function phase [rad].
Raises
------
warnings.warn
If any of the input parameters are outside the valid ranges for the ANN model.
See Also
--------
pitchST, vbmST : Computes the pitch/vbm transfer function amplitude and phase using
strip theory expressions.
format_ANN_input_data : Prepares the input data for the ANN models based on the ship parameters
and wave conditions.
References
----------
Takagi, M. & Ganno, M. (1967). On the Accuracy of the Strip Theory, Used for a Calculation of Ship Motions in Waves. Journal of Zosen Kiokai, 121, pp. 48–61. https://doi.org/10.2534/jjasnaoe1952.1967.48.
Takami, T., Nielsen, U. D., Mounet, R. E. G., Jensen, J. J., Mori, R., & Komoriyama, Y. (2026). Blind identification of incident waves and response transfer functions of a marine vessel based on measured responses. Expert Systems With Applications, 296, 129236. https://doi.org/10.1016/j.eswa.2025.129236.
Example
-------
>>> heave_amp, heave_phase = heaveST(om0, beta_deg, U, L, B0, T, C_B)
"""
# Min&max amplitude of the response transfer functions (RAOs) for the ANN models:
hmax = 2.0
hmin = 0.0
# Prepare the input data for the ANN models:
Nom0 = np.shape(np.array(om0).reshape(-1, 1))[0]
Nbeta = np.shape(np.array(beta_deg).reshape(-1, 1))[0]
ANN_input_data = format_ANN_input_data(om0, beta_deg, U, L, B0, T, C_B)
# Load the .keras files for the ANN-based strip theory models:
ANN_url_base = "https://github.com/Tomoki-Tak/ANN-for-ship-transfer-functions/raw/refs/heads/main/"
print("Loading ANN models from: " + ANN_url_base[:61])
modelha = load_keras_model_from_url(ANN_url_base + "my_model_heaveamp.keras")
modelhp = load_keras_model_from_url(ANN_url_base + "my_model_heavephase.keras")
# Estimation of the vessel's RAOs using the ANN models:
y_pred_ha = modelha.predict(ANN_input_data)
y_pred_hp = modelhp.predict(ANN_input_data)
# Heave amplitude [m/m]:
hamp = (y_pred_ha + 1.0) * (hmax - hmin) / 2.0 + hmin
hamp[hamp < 0] = 0
hamp[np.abs(ANN_input_data[:, 6]) >= 1] = 0
hamp[ANN_input_data[:, 6] >= 1] = 1
# Heave phase [rad]:
hphase = np.arctan2(y_pred_hp[:, 1], y_pred_hp[:, 0])
heave_amp = np.reshape(hamp, (Nbeta, Nom0)).T
heave_phase = np.reshape(hphase, (Nbeta, Nom0)).T
return heave_amp, heave_phase
[docs]
def pitchST(om0, beta_deg, U, L, B0, T, C_B):
"""Computes the pitch transfer function amplitude and phase, using an ANN-based surrogate model of a strip theory code.
The ANN was trained on data from a linear strip theory solver, the so-called New Strip Method (Takagi and Ganno, 1967), in which the Lewis form approximation of ship cross-sections is adopted. Further details of the implementation can be found in Takami et al. (2026).
Parameters
----------
om0 : array_like of shape (Nom0,)
Vector of absolute wave frequencies [rad/s].
beta_deg : array_like of shape (Nbeta,)
Vector of relative wave heading angles [deg].
U : float
Vessel forward speed [m/s].
L : float
Length of the ship [m].
B0 : float
Breadth of the ship [m].
T : float
Draft of the ship [m].
C_B : float, default 1
Block coefficient of the ship [-].
Returns
-------
pitch_amp : numpy.ndarray of shape (Nom0,Nbeta)
Coefficients of the pitch transfer function amplitude [deg/m].
pitch_phase : numpy.ndarray of shape (Nom0,Nbeta)
Coefficients of the pitch transfer function phase [rad].
Raises
------
warnings.warn
If any of the input parameters are outside the valid ranges for the ANN model.
See Also
--------
heaveST, vbmST : Computes the heave/vbm transfer function amplitude and phase using
strip theory expressions.
format_ANN_input_data : Prepares the input data for the ANN models based on the ship parameters
and wave conditions.
References
----------
Takagi, M. & Ganno, M. (1967). On the Accuracy of the Strip Theory, Used for a Calculation of Ship Motions in Waves. Journal of Zosen Kiokai, 121, pp. 48–61. https://doi.org/10.2534/jjasnaoe1952.1967.48.
Takami, T., Nielsen, U. D., Mounet, R. E. G., Jensen, J. J., Mori, R., & Komoriyama, Y. (2026). Blind identification of incident waves and response transfer functions of a marine vessel based on measured responses. Expert Systems With Applications, 296, 129236. https://doi.org/10.1016/j.eswa.2025.129236.
Example
-------
>>> pitch_amp, pitch_phase = pitchST(om0, beta_deg, U, L, B0, T, C_B)
"""
# Min&max amplitude of the response transfer functions (RAOs) for the ANN models:
pmax = 1.0
pmin = 0.0
# Prepare the input data for the ANN models:
Nom0 = np.shape(np.array(om0).reshape(-1, 1))[0]
Nbeta = np.shape(np.array(beta_deg).reshape(-1, 1))[0]
ANN_input_data = format_ANN_input_data(om0, beta_deg, U, L, B0, T, C_B)
# Load the .keras files for the ANN-based strip theory models:
ANN_url_base = "https://github.com/Tomoki-Tak/ANN-for-ship-transfer-functions/raw/refs/heads/main/"
print("Loading ANN models from: " + ANN_url_base[:61])
modelpa = load_keras_model_from_url(ANN_url_base + "my_model_pitchamp.keras")
modelpp = load_keras_model_from_url(ANN_url_base + "my_model_pitchphase.keras")
# Estimation of the vessel's RAOs using the ANN models:
y_pred_pa = modelpa.predict(ANN_input_data)
y_pred_pp = modelpp.predict(ANN_input_data)
# Pitch amplitude [deg/m]:
pamp = (y_pred_pa + 1.0) * (pmax - pmin) / 2.0 + pmin
pamp[pamp < 0] = 0
pamp[np.abs(ANN_input_data[:, 6]) >= 1] = 0
# Pitch phase [rad]:
pphase = np.arctan2(y_pred_pp[:, 1], y_pred_pp[:, 0])
pitch_amp = np.reshape(pamp, (Nbeta, Nom0)).T
pitch_phase = np.reshape(pphase, (Nbeta, Nom0)).T
return pitch_amp, pitch_phase
[docs]
def vbmST(om0, beta_deg, U, L, B0, T, C_B, gravity=None):
"""Computes the Vertical Bending Moment (VBM) transfer function amplitude and phase, using an ANN-based surrogate model of a strip theory code.
The ANN was trained on data from a linear strip theory solver, the so-called New Strip Method (Takagi and Ganno, 1967), in which the Lewis form approximation of ship cross-sections is adopted. Further details of the implementation can be found in Takami et al. (2026).
Parameters
----------
om0 : array_like of shape (Nom0,)
Vector of absolute wave frequencies [rad/s].
beta_deg : array_like of shape (Nbeta,)
Vector of relative wave heading angles [deg].
U : float
Vessel forward speed [m/s].
L : float
Length of the ship [m].
B0 : float
Breadth of the ship [m].
T : float
Draft of the ship [m].
C_B : float, default 1
Block coefficient of the ship [-].
gravity : float, optional
Gravitational acceleration [m/s^2]. If None, the default value from the NetSSE configuration is used.
Returns
-------
vbm_amp : numpy.ndarray of shape (Nom0,Nbeta)
Coefficients of the VBM transfer function amplitude [kNm/m].
vbm_phase : numpy.ndarray of shape (Nom0,Nbeta)
Coefficients of the VBM transfer function phase [rad].
Raises
------
warnings.warn
If any of the input parameters are outside the valid ranges for the ANN model.
See Also
--------
heaveST, pitchST : Computes the heave/pitch transfer function amplitude and phase using
strip theory expressions.
format_ANN_input_data : Prepares the input data for the ANN models based on the ship parameters
and wave conditions.
References
----------
Takagi, M. & Ganno, M. (1967). On the Accuracy of the Strip Theory, Used for a Calculation of Ship Motions in Waves. Journal of Zosen Kiokai, 121, pp. 48–61. https://doi.org/10.2534/jjasnaoe1952.1967.48.
Takami, T., Nielsen, U. D., Mounet, R. E. G., Jensen, J. J., Mori, R., & Komoriyama, Y. (2026). Blind identification of incident waves and response transfer functions of a marine vessel based on measured responses. Expert Systems With Applications, 296, 129236. https://doi.org/10.1016/j.eswa.2025.129236.
Example
-------
>>> vbm_amp, vbm_phase = vbmST(om0, beta_deg, U, L, B0, T, C_B)
"""
# Gravitational acceleration [m/s^2]:
g = gravity if gravity is not None else config.gravity
# Min&max amplitude of the response transfer functions (RAOs) for the ANN models:
vmax = 0.25
vmin = 0.0
# Prepare the input data for the ANN models:
Nom0 = np.shape(np.array(om0).reshape(-1, 1))[0]
Nbeta = np.shape(np.array(beta_deg).reshape(-1, 1))[0]
ANN_input_data = format_ANN_input_data(om0, beta_deg, U, L, B0, T, C_B)
# Load the .keras files for the ANN-based strip theory models:
ANN_url_base = "https://github.com/Tomoki-Tak/ANN-for-ship-transfer-functions/raw/refs/heads/main/"
print("Loading ANN models from: " + ANN_url_base[:61])
modelva = load_keras_model_from_url(ANN_url_base + "my_model_vbmamp.keras")
modelvp = load_keras_model_from_url(ANN_url_base + "my_model_vbmphase.keras")
# Estimation of the vessel's RAOs using the ANN models:
y_pred_va = modelva.predict(ANN_input_data)
y_pred_vp = modelvp.predict(ANN_input_data)
# VBM amplitude [kNm/m]:
vamptmp = (y_pred_va + 1.0) * (vmax - vmin) / 2.0 + vmin
vamptmp_flat = vamptmp.flatten()
vamp = (
vamptmp_flat**2
* g
* ((ANN_input_data[:, 1] + 1.0) * (50.0 - 10.0) / 2.0 + 10.0)
* ((ANN_input_data[:, 0] + 1.0) * (400.0 - 100.0) / 2.0 + 100.0) ** 2
/ 1000.0
)
vamp[np.abs(ANN_input_data[:, 6]) >= 1] = 0
vamp[vamp < 0] = 0
# VBM phase [rad]:
vphase = np.arctan2(y_pred_vp[:, 1], y_pred_vp[:, 0])
vbm_amp = np.reshape(vamp, (Nbeta, Nom0)).T
vbm_phase = np.reshape(vphase, (Nbeta, Nom0)).T
return vbm_amp, vbm_phase
[docs]
def Lewis_param(C_B):
"""Computes the Lewis form parameter for a ship, based on its block coefficient.
Parameters
----------
C_B : float
Block coefficient of the ship [-].
Returns
-------
gamma : float
Lewis form parameter for the ship [-].
See Also
--------
format_ANN_input_data : Prepares the input data for the ANN models based on the ship parameters and wave conditions.
References
----------
Takami, T., Nielsen, U. D., Mounet, R. E. G., Jensen, J. J., Mori, R., Komoriyama, Y. (2026). Blind identification of incident waves and response transfer functions of a marine vessel based on measured responses. Expert Systems With Applications, 296, 129236. https://doi.org/10.1016/j.eswa.2025.129236.
Example
-------
>>> gamma = Lewis_param(C_B)
"""
if C_B <= 0 or C_B > 1:
raise ValueError("Block coefficient C_B must be in the range (0, 1).")
x = np.linspace(-0.5, 0.5, 1000)
func = lambda gamma: ( # noqa: E731
C_B - np.trapezoid(np.exp(-2 * x**2 / 10 ** (2 * gamma - 2)), x)
)
gamma = fsolve(func, 1)[0] # Initial guess of gamma is 1
return gamma