"""Testing Holtrop."""
import math
import numpy as np
import pytest
import matplotlib.pyplot as plt
from astropy import units as u # type: ignore
from astropy.units import imperial as ui # type: ignore
from astropy.units.quantity import Quantity # type: ignore
from berhoel.holtrop import Holtrop, ship, hydro
__date__ = "2024/08/01 21:17:03 hoel"
__author__ = "Berthold Höllmann"
__copyright__ = "Copyright © 2019,2025 by Berthold Höllmann"
__credits__ = ["Berthold Höllmann"]
__maintainer__ = "Berthold Höllmann"
__email__ = "berhoel@gmail.com"
u.imperial.enable()
[docs]
class TestHoltrop:
"""example from [4], page 275"""
[docs]
@pytest.fixture()
def probe(self):
return Holtrop(
L=Quantity(50.00, "m"),
B=Quantity(12.00, "m"),
T_F=Quantity(3.10, "m"),
T_A=Quantity(3.30, "m"),
h_b=Quantity(0.0, "m"),
Nab=Quantity(900.0, "m3"),
S_app=[Quantity(50.0, "m2")],
S=Quantity(584.9, "m2"),
k_2=[3.0], # 1 + k_2
C_Stern=0.0,
A_BT=Quantity(0.0, "m2"),
i_E=Quantity(25.0, "deg"),
C_M=0.78,
lcb=-4.5, # L aft of 1/2 L
A_T=Quantity(10.0, "m2"),
C_WP=0.80,
# Related coefficients
C_P=0.60096,
C_B=0.46875,
)
[docs]
def test_C_P(self, probe):
assert (
probe.Nab / (probe.L * probe.B * probe.T * probe.C_M)
).value == pytest.approx(0.60096, 1e-5)
[docs]
def test_C_B(self, probe):
assert (probe.Nab / (probe.L * probe.B * probe.T)).value == pytest.approx(
0.46875,
1e-5,
)
[docs]
def test_L_R(self, probe):
assert probe.L_R.value == pytest.approx(14.1728, 1e-5)
assert probe.L_R.unit == u.m
[docs]
def test_S_calc(self, probe):
assert probe.S.value == pytest.approx(584.9, 1e-5)
assert probe.S.unit == u.m**2
[docs]
def test_k_1(self, probe):
assert probe.k_1 == pytest.approx(1.297, 1e-5) # 1 + k_1
[docs]
def test_C_A(self, probe):
assert pytest.approx(0.00064, 1e-1) == probe.C_A
[docs]
def test_c_17(self, probe):
assert probe.c_17 == pytest.approx(1.4133, 1e-5)
[docs]
def test_m_3(self, probe):
assert probe.m_3 == pytest.approx(-2.0298, 1e-5)
[docs]
def test_rest(self, probe):
assert probe.c_2 == pytest.approx(1.0, 1e-5)
[docs]
def test_c_5(self, probe):
assert probe.c_5 == pytest.approx(0.7329, 1e-5)
[docs]
def test_lambda(self, probe):
assert probe.λ == pytest.approx(0.7440, 1e-4)
[docs]
def test_C_15(self, probe):
assert probe.c_15 == pytest.approx(-1.69385, 1e-5)
[docs]
def test_i_E(self, probe):
assert probe.calc_i_E.value == pytest.approx(26.3978, 1e-5)
ref = {
25: [0.3279, -3.31, 475, 21, 25, 662],
27: [0.182, -3.0883, 512, 24, 16, 715],
29: [0.0409, -2.8962, 539, 28, 2, 756],
31: [-0.0834, -2.7274, 564, 31, 0, 807],
33: [-0.1876, -2.578, 590, 35, 0, 864],
35: [-0.273, -2.4453, 618, 39, 0, 925],
}
f_string = "{:3.0f} {:7.4f} {:7.4f} {:7.4f} {:5.0f} {:5.0f} {:5.0f} {:5.0f}"
for speed in range(25, 36, 2):
print(" V F_n m_4 m_3 R_W R_app R_TR R")
V = (speed * ui.knot).si
print(
f_string.format(
speed,
hydro.F_n(V, probe.L),
ref[speed][0],
ref[speed][1],
ref[speed][2],
ref[speed][3],
ref[speed][4],
ref[speed][5],
),
)
print(
f_string.format(
speed,
hydro.F_n(V, probe.L),
probe.m_4(V)
* math.cos(probe.λ * math.pow(hydro.F_n(V, probe.L), -2.0)),
probe.m_3 * math.pow(hydro.F_n(V, probe.L), probe.d),
probe.R_W(V).to(u.N).value / 1000.0,
probe.R_app(V).to(u.N).value / 1000.0,
probe.R_TR(V).to(u.N).value / 1000.0,
probe.R(V).to(u.N).value / 1000.0,
),
)
[docs]
def plot():
example = ship.Ship( # Main particulars
L=Quantity(50.00, "m"),
B=Quantity(12.00, "m"),
T_F=Quantity(3.10, "m"),
T_A=Quantity(3.30, "m"),
h_b=Quantity(0.0, "m"),
Nab=Quantity(900.0, "m3"),
S_app=[Quantity(50.0, "m2")],
k_2=[3.0], # 1 + k_2
C_Stern=0.0,
A_BT=Quantity(0.1, "m2"),
i_E=Quantity(25.0, "deg"),
C_M=0.78,
lcb=-4.5, # %L aft of 1/2 L
A_T=Quantity(10.0, "m2"),
C_WP=0.80,
# Related coefficients
C_P=0.60096,
C_B=0.46875,
)
data = np.array(
[
(speed.value, example.R(speed).to(u.N).value / 1000.0)
for speed in (np.arange(0.1, 35.0, 0.5) * u.m / u.s)
],
)
plt.plot(data[:, 0], data[:, 1])
plt.show()
[docs]
def prau():
S_app = 0.01 * u.m**2
k_2 = 0.01 # 1 + k_2
Prau = ship.Ship( # Main particulars
L=Quantity(30.564, "m"),
B=Quantity(12.65, "m"),
T=Quantity(4.50, "m"),
h_b=Quantity(0.0, "m"),
Nab=Quantity(741.0, "m3"),
App=[(S_app, k_2)],
C_Stern=0.0,
A_BT=Quantity(0.01, "m2"),
i_E=Quantity(25.0, "deg"),
C_M=0.744,
lcb=50 - 49.881, # %L aft of 1/2 L
A_T=0.01 * u.m**2,
A_WP=271.597 * u.m**2, #: Waterplane area
L_WP=30.564 * u.m, #: Waterline length
B_WP=12.430 * u.m, #: Waterlien beam
# Related coefficients
C_P=0.583,
C_B=0.434,
)
data = np.array(
[
(V, Prau.R(V * u.m / u.s, Prau).to(u.N).value / 1000.0)
for V in np.arange(2.0, 7.0, 0.1)
],
)
plt.plot(data[:, 0], data[:, 1])
plt.show()
[docs]
def prop():
_ = ship.Ship( # Main particulars
L=50.00 * u.m,
B=12.00 * u.m,
T_F=3.10 * u.m,
T_A=3.30 * u.m,
h_b=0.0 * u.m,
Nab=900.0 * u.m**3,
S_app=[50.0 * u.m**2],
k_2=[3.0], # 1 + k_2
C_Stern=0.0,
A_BT=0.1 * u.m**2,
i_E=25.0 * u.deg,
C_M=0.78,
lcb=-4.5, # %L aft of 1/2 L
A_T=10.0 * u.m**2,
C_WP=0.80,
# Related coefficients
C_P=0.60096,
C_B=0.46875,
# propeller related coefficents:
t=0.054,
w=0.039,
eta_R=0.980,
D=3.231 * u.m,
# c_P_D == P/D
c_P_D=1.136,
# A_E_0 = A_E / A_0
A_E_0=0.763,
eta_0=0.705,
) # (30 knots)
[docs]
def Poehls_Soeding():
probe = ship.Ship( # Main particulars
L=214.00 * u.m,
B=28.50 * u.m,
T_F=10.50 * u.m,
T_A=10.50 * u.m,
h_b=8.25 * u.m,
# Nab = 900. * u.m**3,
S_app=[89.88 * u.m**2],
k_2=[1.3], # 1 + k_2
C_Stern=0.0,
A_BT=0.1 * u.m**2,
# i_E = 25. , 'deg'),
# C_M = .78,
lcb=1.5, # %L aft of 1/2 L
A_T=10.0 * u.m**2,
C_WP=0.875,
# # Related coefficients
# C_P = .60096,
C_B=0.813,
C_M=0.995,
# # propeller related coefficents:
# t = .054,
# w = .039,
# eta_R = .980,
# D = 3.231, 'u.m'),
# # c_P_D == P/D
# c_P_D = 1.136,
# # A_E_0 = A_E / A_0
# A_E_0 = .763,
# eta_0 = .705
)
from numpy import arange
f_string = "{:3.0f} {:7.4f} {:7.4f} {:7.2f} {:7.2f} {:5.0f} {:5.0f} {:5.0f} {:5.0f}"
for speed in arange(5.716, 10, 1):
print(" V V[kn] F_n m_4 m_3 R_W R_app R_TR R")
V = speed * u.m / u.s
print(
f_string.format(
speed,
V.to(ui.knot).value,
hydro.F_n(V, probe.L),
probe.m_4(V, probe)
* math.cos(probe.λ * math.pow(hydro.F_n(V, probe.L), -2.0)),
probe.m_3 * math.pow(hydro.F_n(V, probe.L), probe.d()),
(probe.R_W(V) / 1000.0).value,
(probe.R_app(V) / 1000.0).value,
(probe.R_TR(V) / 1000.0).value,
(probe.R(V) / 1000.0).value,
),
)