示例#1
0
def test_symmetry_froude_number():
    r"""Froude number symmetry forward and backward.

    Test the froude number is the same for positive and negative speeds with
    the same absolute value

    """
    assert froude_number(speed=0.594, lwl=1.6) == froude_number(speed=-0.594, lwl=1.6)
def holtrop_wave(
        v: float,
        Vc: float,
        lwl: float,
        B: float,
        T: float,
        Cp: float,
        lcb_fraction: float,
        At: float,  # area transom
        Cm: float,
        Cwp: float,  # waterplane area coefficient
        Abt: float,  # Transverse bulb area
        h_B: float,
        Tf: float,  # forward draught of the ship
        rho_water: float = RHO_SEA_WATER_20C,
        gravity: float = GRAVITY_STANDARD) -> Tuple[float, ...]:
    r"""Holtrop wave-making and wave-breaking resistance.

    At : immersed part of the transverse area of the transom  at zero speed

    h_B : position of the centre of the transverse area Abt above the keel line
    Tf : forward draught of the ship

    """
    Fn = froude_number(v, lwl, gravity)
    Lr = _holtrop_Lr(lwl, Cp, lcb_fraction)
    lcb = _lcb_fraction_to_lcb_holtrop(lcb_fraction)

    # The half angle of entrance i_e is the angle of the waterline
    # at bow in degrees with reference to the centreplane
    i_e = 1 + 89 * exp(-(lwl / B)**0.80856 * (1 - Cwp)**0.30484 *
                       (1 - Cp - 0.0225 * lcb)**0.6367 * (Lr / B)**0.34574 *
                       (100 * Vc / lwl**3)**0.16302)

    c7 = 0.229577 * (B / lwl)**0.33333 if B / lwl < 0.11 else 0.5 - 0.0625 * (
        lwl / B) if B / lwl > 0.25 else B / lwl
    c1 = 2223105 * c7**3.78613 * (T / B)**1.07961 * (90 - i_e)**(-1.37565)
    c3 = _c3func(Abt, B, T, Tf, h_B)
    c2 = _c2func(c3)

    # c5 expresses the influence of a transom stern on the resistance
    c5 = 1 - 0.8 * At / (B * T * Cm)

    c16 = 8.07981 * Cp - 13.8673 * Cp**2 + 6.984388 * Cp**3 if Cp < 0.8 else 1.73014 - 0.7067 * Cp
    m1 = 0.0140407 * lwl / T - 1.75254 * Vc**(
        1. / 3) / lwl - 4.79323 * B / lwl - c16
    lambda_ = 1.446 * Cp - 0.03 * (lwl /
                                   B) if lwl / B < 12 else 1.446 * Cp - 0.36
    c15 = -1.69385 if lwl**3 / Vc < 512 else 0. if lwl**3 / Vc > 1727 else -1.69385 + (
        lwl / Vc**(1. / 3) - 8.0) / 2.36
    m2 = c15 * Cp**2 * exp(-0.1 * Fn**(-2))
    d = -0.9
    # TODO: cos ou cos(radians?
    return c1 * c2 * c5 * Vc * rho_water * gravity * exp(
        m1 * Fn**d +
        m2 * cos(lambda_ * Fn**(-2))), c1, c5, c7, c15, m1, m2, lambda_
示例#3
0
def hull_residuary_resistance_mit(
        boatspeed: float,
        Vc: float,
        lwl: float,
        bwl: float,
        Tc: float,
        coe: Union[Tuple[float, float, float], None] = None,
        rho_water: float = RHO_SEA_WATER_20C) -> Force:
    """Hull upright residuary resistance [N] according to the MIT regression.

    boatspeed : boat speed [m/s]
    Vc : Canoe body volume of displaced water [m**3] , must be > 0.
    lwl : Length at Waterline [m] , must be > 0.
    bwl : Beam at Waterline [m] , must be > 0.
    Tc : Canoe body draft [m], must be >= 0
    coe : tuple of 3 floats, optional (default [lwl / 2, 0, -Tc / 3]).
        Represents the x, y, z coordinates of the centre of effort.
        For residuary resistance, the surfacic barycentre of the underwater hull
        is an acceptable estimate.
        x=lwl / 2 , y = 0., z = -Tc/3 is another acceptable estimate.
    rho_water : Water density [kg/m**3], must be >= 0.

    Returns a Force object, representing the residuary resistance [N] on the hull.

    """
    if Vc <= 0:
        raise ValueError("Vc should be strictly positive")
    if lwl <= 0:
        raise ValueError("lwl should be strictly positive")
    if bwl <= 0:
        raise ValueError("bwl should be strictly positive")
    if Tc <= 0:
        raise ValueError("Tc should be strictly positive")
    if not RHO_WATER_MIN < rho_water < RHO_WATER_MAX:
        raise ValueError(f"rho_water should be between"
                         f"{RHO_WATER_MIN} and {RHO_WATER_MAX}")

    coe = (lwl / 2., 0., -Tc / 3.) if coe is None else coe

    interp = _get_hull_residuary_resistance_mit_interpolator(
        Vc, lwl, bwl, Tc, rho_water)

    boatspeed_sign = boatspeed / abs(boatspeed) if boatspeed != 0. else 0.
    froude = froude_number(speed=boatspeed, lwl=lwl)
    if froude <= 0.6168006:
        residuary_resistance = max([0., interp(froude)])
    else:
        at_0_6068006 = interp(0.6068006)
        at_0_6168006 = interp(0.6168006)
        residuary_resistance = (at_0_6168006 + (froude - 0.6168006) *
                                (at_0_6168006 - at_0_6068006) / 0.01)

    return Force(-residuary_resistance * boatspeed_sign, 0., 0., coe[0],
                 coe[1], coe[2])
#!/usr/bin/env python
# coding: utf-8

r"""Holtrop example."""

from ydeos_hydrodynamics.froude import froude_number
from ydeos_hydrodynamics.holtrop_mennen import holtrop_mennen

v = 25  # knots
fn = froude_number(speed=v*(1852/3600), lwl=205.)
(r_friction, one_plus_k1, r_appendages, r_wave, r_bulbous, r_transom, r_a), total = \
    holtrop_mennen(v * (1852 / 3600),  # m/s
                   Vc=37500,
                   lwl=205.,
                   B=32.,
                   T=10.,
                   Cp=0.5833,
                   lcb_fraction=0.5075,
                   afterbody_shape="U",
                   S=7381.45,
                   At=16.,
                   Cm=0.98,
                   Cb=0.45,
                   Cwp=0.75,
                   Abt=20.,
                   h_B=4.0,
                   Tf=10.,
                   S_app=(50.,),
                   d_app=(200.,),
                   k2_app=(.5,))
示例#5
0
def test_known_value_froude_number():
    r"""Test against a known value."""
    target = 0.15
    tolerance = 0.001
    assert target - tolerance <= froude_number(speed=0.594, lwl=1.6) <= target + tolerance
示例#6
0
def test_wrong_input_froude_number():
    r"""Test wrong parameters."""
    with pytest.raises(ZeroDivisionError):
        _ = froude_number(speed=1, lwl=0)
def rm_estimate_gerritsma(
        boatspeed: float,
        heel_angle: float,
        displacement: float,
        lwl: float,
        bwl: float,
        Tc: float,
        Gdwl: float,
        rho_water: float = RHO_SEA_WATER_20C) -> Tuple[Force, Force]:
    """Heeling righting moment estimate, Delft.

    Estimate the righting moment [N.m] from hull shape parameters
    according to the logic published in 1993 by Gerritsma

    boatspeed : boat speed [m/s]
    heel_angle : The heel_angle [degrees], between -90 and 90.
        A negative value represents heel to windward
    displacement : The total yacht displacement [kg], must be > 0.
    lwl : The length at waterline [m], must be > 0.
    bwl : The beam at waterline [m], must be > 0.
    Tc : The canoe body draft [m], must be > 0
    Gdwl : The vertical centre of gravity position relative to datum waterline
        (negative if below waterline)
    rho_water : Water density [kg/m**3],
                must be between RHO_WATER_MIN and RHO_WATER_MAX.

    Returns a list of 2 Force objects, of equal magnitude but of vertical
    and opposite directions representing the righting moment.

    References
    ----------
    http://www.boatdesign.net/forums/attachments/sailboats/
    51748d1293586862-dr-gerritsma-righting-moment-dr.-
                                                  gerritsmas-righting-moment.jpg

    http://www.boatdesign.net/forums/sailboats/
                                         dr-gerritsma-righting-moment-36057.html

    """
    if displacement <= 0:
        raise ValueError("displacement should be strictly positive")
    if lwl <= 0:
        raise ValueError("lwl should be strictly positive")
    if bwl <= 0:
        raise ValueError("bwl should be strictly positive")
    if Tc <= 0:
        raise ValueError("Tc should be strictly positive")
    if not RHO_WATER_MIN < rho_water < RHO_WATER_MAX:
        raise ValueError(f"rho_water should be between "
                         f"{RHO_WATER_MIN} and {RHO_WATER_MAX}")

    D2 = -0.0406 + 0.0109 * (bwl / Tc) - 0.00105 * (bwl / Tc)**2
    D3 = 0.0636 - 0.0196 * (bwl / Tc)

    heel_sign = heel_angle / abs(heel_angle) if heel_angle != 0. else 0.

    froude = froude_number(speed=boatspeed, lwl=lwl)

    # Righting moment at 0 speed (rest)
    static_rm_estimate = (displacement * GRAVITY_STANDARD *
                          ((0.664 * Tc + 0.111 * bwl**2 / Tc - Gdwl) *
                           sin(radians(abs(heel_angle))) + lwl * D3 *
                           (radians(abs(heel_angle)))**2))

    # Righting moment modification due to forward motion
    dynamic_rm_estimate = (displacement * GRAVITY_STANDARD *
                           (lwl * (D2 * (radians(abs(heel_angle))) * froude)))

    rm_estimate = static_rm_estimate + dynamic_rm_estimate
    # return ForceAndMoment([0.,0.,0.],
    #                       [-rm_estimate * heel_sign,0.,0.],[0.,0.,0.])

    # Approximation of the point of application of the righting force:
    # X: 1/2 of lwl
    # Y: - UNIT LENGTH (gives the right moment when multiplied
    #                   by the Z component of the force)
    # Z: 0

    righting_force = Force(0., 0., -rm_estimate * heel_sign, lwl / 2., -1., 0.)
    compensating_force = Force(
        0.,
        0.,
        rm_estimate * heel_sign,
        lwl / 2.,
        0,
        0.,
    )

    return righting_force, compensating_force
示例#8
0
def hull_residuary_resistance_ks_series4(
        boatspeed: float,
        Vc: float,
        lwl: float,
        bwl: float,
        Aw: float,
        Sc: float,
        lcb_fraction: float = 0.53,
        lcf_fraction: float = 0.56,
        Cp: float = 0.56,
        coe: Union[Tuple[float, float, float], None] = None,
        rho_water: float = RHO_SEA_WATER_20C) -> Force:
    """Residuary resistance [N] on the hull, DSYHS Series 4 regression.

    KS stands for Keuning Sonnenberg.
    Keuning and Sonnenberg wrote "Approximation of the Hydrodynamic Forces
    on a Sailing Yacht based on the 'Delft Systematic Yacht Hull Series'"
    in 1998. hull_residuary_resistance_KS uses the results from this publication

    boatspeed : boat speed [m/s]
    Vc : Canoe body volume of displaced water [m**3], must be > 0.
    lwl : Length at Waterline [m], must be > 0.
    bwl : Beam at Waterline [m] , must be > 0.
    Aw : Waterplane area [m**2] , must be > 0.
    Sc : WSAc - Canoe body Wetted Surface Area [m**2], must be >= 0
    lcb_fraction : Longitudinal position of Center of Buoyancy from bow.
        It is in fraction format e.g. 0.560. Must be > 0 and < 1.
        The DSYHS range is 0.500 to 0.582.
    lcf_fraction : Longitudinal position of Center of Flotation from bow.
        It is in fraction format e.g. 0.590. Must be > 0 and < 1.
        The DSYHS range is 0.518 to 0.595.
    Cp : Prismatic Coefficient, Must be > 0 and < 1.
    The DSYHS range is 0.520 to 0.600.
    coe : tuple of 3 floats, optional (default [lwl / 2, 0, 0])
        Represents the x, y, z coordinates of the centre of effort.
        For residuary resistance, the surfacic barycentre of the underwater hull
        is an acceptable estimate.
        x=lwl / 2 , y = 0., z = -Tc/3 is another acceptable estimate.
    rho_water : Water density [kg/m**3], must be >= 0.

    References
    ----------
    Approximation of the Hydrodynamic Forces on a Sailing Yacht
    based on the 'Delft Systematic Yacht Hull Series (by Keuning & Sonnenberg)

    http://radiosailingtechnology.com/index.php/hulls/
                           drag-measurements-on-an-international-one-metre-yacht

    http://klz-resistance.blogspot.fr/

    """
    if Vc <= 0:
        raise ValueError("Vc should be strictly positive")
    if lwl <= 0:
        raise ValueError("lwl should be strictly positive")
    if bwl <= 0:
        raise ValueError("bwl should be strictly positive")
    if Aw <= 0:
        raise ValueError("Aw should be strictly positive")
    if Sc <= 0:
        raise ValueError("Sc should be strictly positive")
    if not 0. < lcb_fraction < 1.:
        raise ValueError("lcb_fraction should be between 0 and 1")
    if not 0. < lcf_fraction < 1.:
        raise ValueError("lcf_fraction should be between 0 and 1")
    if not 0. < Cp < 1.:
        raise ValueError("Cp should be between 0 and 1")
    if not RHO_WATER_MIN < rho_water < RHO_WATER_MAX:
        raise ValueError(f"rho_water should be between "
                         f"{RHO_WATER_MIN} and {RHO_WATER_MAX}")

    # DSYHS checks
    # bwl / Tc cannot be checked here
    # midship area coefficient cannot be checked here
    check_lwl_to_bwl_s4(value=lwl / bwl)
    check_lwl_to_volume_s4(value=lwl / Vc**(1. / 3.))
    check_lcb_fraction_s4(value=lcb_fraction)
    check_lcf_fraction_s4(value=lcf_fraction)
    check_prismatic_s4(value=Cp)
    check_waterplane_to_volume_s4(value=Aw / Vc**(2. / 3.))

    coe = (lwl / 2., 0., 0.) if coe is None else coe

    interp = _get_hull_residuary_resistance_ks_series4_interpolator(
        Vc, lwl, bwl, Aw, Sc, lcb_fraction, lcf_fraction, Cp, rho_water)

    boatspeed_sign = boatspeed / abs(boatspeed) if boatspeed != 0. else 0.

    froude = froude_number(speed=boatspeed, lwl=lwl)
    if froude <= 0.6:
        residuary_resistance = max([0., interp(froude)])
    else:
        # Rough extrapolation using the derivative at the end of the domain
        at_0_59 = interp(0.59)
        at_0_60 = interp(0.60)
        residuary_resistance = at_0_60 + (froude - 0.6) * (at_0_60 -
                                                           at_0_59) / 0.01

    return Force(-residuary_resistance * boatspeed_sign, 0., 0., coe[0],
                 coe[1], coe[2])
示例#9
0
def hull_residuary_resistance_la_series3(
        boatspeed: float,
        Vc: float,
        lwl: float,
        bwl: float,
        Tc: float,
        Aw: float,
        lcb_fraction: float = 0.53,
        Cp: float = 0.56,
        coe: Union[Tuple[float, float, float], None] = None,
        rho_water: float = RHO_SEA_WATER_20C) -> Force:
    """Hull upright residuary resistance (N), DSYHS Series 3 regression.

    Calculates the residuary resistance [N] on the hull.
    LA stands for Larsson, one of the authors of Principles of Yacht Design.
    The calculation is described on pages 75 and 76 of the book
    Principles of Yacht Design

    boatspeed : boat speed [m/s]
    Vc : Canoe body volume of displaced water [m**3] , must be > 0.
    lwl : Length at Waterline [m] , must be > 0.
    bwl : Beam at Waterline [m] , must be > 0.
    Tc : Canoe body draft [m], must be >= 0
    Aw : Waterplane area [m**2] , must be > 0.
    lcb_fraction : Longitudinal position of Center of Buoyancy from bow.
        It is in fraction format: e.g. 0.560. Must be > 0 and < 1.
        The DSYHS range is 0.500 to 0.582.
    Cp : Prismatic Coefficient. Must be > 0 and < 1.
    The DSYHS range is 0.520 to 0.600.
    coe : tuple of 3 floats, optional (default [lwl / 2, 0, -Tc / 3]).
        Represents the x, y, z coordinates of the centre of effort.
        For residuary resistance, the surfacic barycentre of the underwater
        hull is an acceptable estimate.
        x=lwl / 2 , y = 0., z = -Tc/3 is another acceptable estimate.
    rho_water : Water density [kg/m**3], must be >= 0.

    Returns a Force object, representing the residuary resistance [N]
    on the hull.

    References
    ----------
    Principles of Yacht Design - Larsson & Eliasson
    http://radiosailingtechnology.com/index.php/hulls/
                           drag-measurements-on-an-international-one-metre-yacht
    http://klz-resistance.blogspot.fr/

    """
    if Vc <= 0:
        raise ValueError("Vc should be strictly positive")
    if lwl <= 0:
        raise ValueError("lwl should be strictly positive")
    if bwl <= 0:
        raise ValueError("bwl should be strictly positive")
    if Tc <= 0:
        raise ValueError("Tc should be strictly positive")
    if Aw <= 0:
        raise ValueError("Aw should be strictly positive")
    if not 0. < lcb_fraction < 1.:
        raise ValueError("lcb_fraction should be between 0 and 1")
    if not 0. < Cp < 1.:
        raise ValueError("Cp should be between 0 and 1")
    if not RHO_WATER_MIN < rho_water < RHO_WATER_MAX:
        raise ValueError(f"rho_water should be between "
                         f"{RHO_WATER_MIN} and {RHO_WATER_MAX}")

    # DSYHS checks (cf page 74 of principles of yacht design
    check_lwl_to_bwl_s3(value=lwl / bwl)
    check_bwl_to_draft_s3(value=bwl / Tc)
    check_lwl_to_volume_s3(value=lwl / Vc**(1. / 3.))
    check_lcb_fraction_s3(value=lcb_fraction)
    check_prismatic_s3(value=Cp)

    coe = (lwl / 2., 0., -Tc / 3.) if coe is None else coe

    interp = _get_hull_residuary_resistance_la_series3_interpolator(
        Vc, lwl, bwl, Tc, Aw, lcb_fraction, Cp, rho_water)

    boatspeed_sign = boatspeed / abs(boatspeed) if boatspeed != 0. else 0.
    froude = froude_number(speed=boatspeed, lwl=lwl)
    if froude <= 0.75:
        residuary_resistance = max([0., interp(froude)])
    else:
        at_0_74 = interp(0.74)
        at_0_75 = interp(0.75)
        residuary_resistance = (at_0_75 + (froude - 0.75) *
                                (at_0_75 - at_0_74) / 0.01)

    return Force(-residuary_resistance * boatspeed_sign, 0., 0., coe[0],
                 coe[1], coe[2])
示例#10
0
def hull_residuary_resistance_2008(
        boatspeed: float,
        Vc: float,
        lwl: float,
        bwl: float,
        Tc: float,
        Aw: float,
        Cm: float,
        lcb_fraction: float = 0.53,
        lcf_fraction: float = 0.56,
        Cp: float = 0.56,
        coe: Union[Tuple[float, float, float], None] = None,
        rho_water: float = RHO_SEA_WATER_20C) -> Force:
    """Calculate the residuary resistance [N] on the hull.

    Source: p24 of Fossati's Aero-hydrodynamics ...

    boatspeed : boat speed [m/s]
    Vc : Canoe body volume of displaced water [m**3], must be > 0.
    lwl : Length at Waterline [m], must be > 0.
    bwl : Beam at Waterline [m] , must be > 0.
    Aw : Waterplane area [m**2] , must be > 0.
    Cm : Midship section coefficient, must be >= 0
    lcb_fraction : Longitudinal position of Center of Buoyancy from bow.
        It is in fraction format e.g. 0.560. Must be > 0 and < 1.
        The DSYHS range is 0.500 to 0.582.
    lcf_fraction : Longitudinal position of Center of Flotation from bow.
        It is in fraction format e.g. 0.590. Must be > 0 and < 1.
        The DSYHS range is 0.518 to 0.595.
    Cp : Prismatic Coefficient, Must be > 0 and < 1.
         The DSYHS range is 0.520 to 0.600.
    coe : tuple of 3 floats, optional (default [lwl / 2, 0, 0])
        Represents the x, y, z coordinates of the centre of effort.
        For residuary resistance, the surfacic barycentre of the underwater hull
        is an acceptable estimate.
        x=lwl / 2 , y = 0., z = -Tc/3 is another acceptable estimate.
    rho_water : Water density [kg/m**3], must be >= 0.

    References
    ----------
    Aero-hydrodynamics and the performance of sailing yachts. p24

    """
    if Vc <= 0:
        raise ValueError("Vc should be strictly positive")
    if lwl <= 0:
        raise ValueError("lwl should be strictly positive")
    if bwl <= 0:
        raise ValueError("bwl should be strictly positive")
    if Aw <= 0:
        raise ValueError("Aw should be strictly positive")
    if Cm <= 0:
        raise ValueError("Cm should be strictly positive")
    if Tc <= 0:
        raise ValueError("Tc should be strictly positive")
    if not 0. < lcb_fraction < 1.:
        raise ValueError("lcb_fraction should be between 0 and 1")
    if not 0. < lcf_fraction < 1.:
        raise ValueError("lcf_fraction should be between 0 and 1")
    if not 0. < Cp < 1.:
        raise ValueError("Cp should be between 0 and 1")
    if not RHO_WATER_MIN < rho_water < RHO_WATER_MAX:
        raise ValueError(f"rho_water should be between "
                         f"{RHO_WATER_MIN} and {RHO_WATER_MAX}")

    # DSYHS checks
    # bwl / Tc cannot be checked here
    # midship area coefficient cannot be checked here
    check_lwl_to_bwl_2008(value=lwl / bwl)
    check_lwl_to_volume_2008(value=lwl / Vc**(1. / 3.))
    check_lcb_fraction_2008(value=lcb_fraction)
    check_lcf_fraction_2008(value=lcf_fraction)
    check_prismatic_2008(value=Cp)
    check_midship_2008(value=Cm)

    coe = (lwl / 2., 0., 0.) if coe is None else coe

    interp = _get_hull_residuary_resistance_2008_interpolator(
        Vc, lwl, bwl, Tc, Aw, Cm, lcb_fraction, lcf_fraction, Cp, rho_water)

    boatspeed_sign = boatspeed / abs(boatspeed) if boatspeed != 0. else 0.

    froude = froude_number(speed=boatspeed, lwl=lwl)

    if froude <= 0.75:
        residuary_resistance = max([0., interp(froude)])
    else:
        # Rough extrapolation using the derivative at the end of the domain
        at_0_74 = interp(0.74)
        at_0_75 = interp(0.75)
        residuary_resistance = at_0_75 + (froude - 0.75) * (at_0_75 -
                                                            at_0_74) / 0.01

    return Force(-residuary_resistance * boatspeed_sign, 0., 0., coe[0],
                 coe[1], coe[2])
示例#11
0
def hull_residuary_delta_heeled_ks(
        boatspeed: float,
        heel_angle: float,
        Vc: float,
        lwl: float,
        bwl: float,
        Tc: float,
        lcb_fraction: float = 0.53,
        coe: Union[Tuple[float, float, float], None] = None,
        rho_water: float = RHO_SEA_WATER_20C) -> Force:
    """Hull residuary resistance [N] delta at a given heel angle.

    KS stands for Keuning Sonnenberg.
    Keuning and Sonnenberg wrote "Approximation of the Hydrodynamic Forces
    on a Sailing Yacht based on the 'Delft Systematic Yacht Hull Series'"
    in 1998.
    hull_residuary_resistance_delta_heeled_KS uses the results from this publication.

    boatspeed : boat speed [m/s]
    heel_angle : The heel_angle [degrees], between -90 and 90.
    Vc : Canoe body volume of displaced water [m**3] , must be > 0.
    lwl : Length at Waterline [m] , must be > 0.
    bwl : Beam at Waterline [m] , must be > 0.
    Tc : Canoe body draft [m], must be >= 0
    lcb_fraction : Longitudinal position of Center of Buoyancy from bow.
        It is in fraction format: e.g. 0.560. Must be > 0 and < 1.
        The DSYHS range is 0.500 to 0.582.
    coe : tuple of 3 floats, optional (default [lwl / 2, 0, -Tc / 3])
        Represents the x, y, z coordinates of the centre of effort.
        For residuary resistance, the surfacic barycentre of the underwater hull is an acceptable estimate.
        x=lwl / 2 , y = 0., z = -Tc/3 is another acceptable estimate.
    rho_water : float, optional (default RHO_SEA_WATER)
        Water density [kg/m**3], must be >= 0.

    """
    if Vc <= 0:
        raise ValueError("Vc should be strictly positive")
    if lwl <= 0:
        raise ValueError("lwl should be strictly positive")
    if bwl <= 0:
        raise ValueError("bwl should be strictly positive")
    if Tc <= 0:
        raise ValueError("Tc should be strictly positive")
    if not 0. < lcb_fraction < 1.:
        raise ValueError("lcb_fraction should be between 0 and 1")
    if not RHO_WATER_MIN < rho_water < RHO_WATER_MAX:
        raise ValueError(f"rho_water should be between "
                         f"{RHO_WATER_MIN} and {RHO_WATER_MAX}")

    # DSYHS checks
    # midship area coefficient cannot be checked here
    check_lwl_to_bwl(value=lwl / bwl)
    check_bwl_to_draft(value=bwl / Tc)
    check_lwl_to_volume(value=lwl / Vc**(1. / 3.))
    check_lcb_fraction(value=lcb_fraction)

    coe = (lwl / 2., 0., -Tc / 3.) if coe is None else coe

    interp = _get_hull_residuary_delta_heeled_ks_interpolator(
        Vc, lwl, bwl, Tc, lcb_fraction, rho_water)

    boatspeed_sign = boatspeed / abs(boatspeed) if boatspeed != 0. else 0.

    froude = froude_number(speed=boatspeed, lwl=lwl)
    if froude <= 0.55:
        rrh_delta_at_20_deg_heel = max([0., interp(froude)])
        rrh_delta_at_heel_angle = (rrh_delta_at_20_deg_heel * 6.0 *
                                   (radians(abs(heel_angle)))**1.7)
    else:
        at_0_54 = interp(0.54)
        at_0_55 = interp(0.55)
        rrh_delta_at_20_deg_heel = (at_0_55 + (froude - 0.55) *
                                    (at_0_55 - at_0_54) / 0.01)
        rrh_delta_at_heel_angle = (rrh_delta_at_20_deg_heel * 6.0 *
                                   (radians(abs(heel_angle)))**1.7)

    return Force(-rrh_delta_at_heel_angle * boatspeed_sign, 0., 0., coe[0],
                 coe[1], coe[2])
示例#12
0
def keel_residuary_ks(boatspeed: float,
                      Vc: float,
                      Vk: float,
                      Tc: float,
                      T: float,
                      lwl: float,
                      bwl: float,
                      Zcbk: float,
                      coe: Union[Tuple[float, float, float], None] = None,
                      rho_water: float = RHO_SEA_WATER_20C) -> Force:
    """Residuary resistance [N] of the keel at 0° heel.

    KS stands for Keuning Sonnenberg.
    Keuning and Sonnenberg wrote "Approximation of the Hydrodynamic Forces
    on a Sailing Yacht based on the 'Delft Systematic Yacht Hull Series'"
    in 1998.
    keel_residuary_resistance_KS uses the results from this publication.

    boatspeed : boat speed [m/s]
    Vc : Canoe body volume of displaced water [m**3] , must be > 0.
    Vk : Keel volume of displaced water [m**3] , must be > 0.
    Tc : Canoe body draft [m], must be >= 0
    T : Total draft [m], must be >= 0
    lwl : Length at Waterline [m] , must be > 0.
    bwl : Beam at Waterline [m] , must be > 0.
    Zcbk : Distance to the center of buoyancy of the keel [m]n from top of keel.
           Must be > 0.
    coe : tuple of 3 floats, optional (default (lwl / 2, 0, -Tc/3)).
        Represents the x, y, z coordinates of the centre of effort.
        For residuary resistance, the surfacic barycentre of the underwater hull
        is an acceptable estimate.
        x=lwl / 2 , y = 0., z = -Tc/3 is another acceptable estimate.
    rho_water : Water density [kg/m**3], must be >= 0 (default RHO_SEA_WATER)

    Returns a Force object, representing the residuary resistance [N]
    of the keel at 0° heel.

    """
    if Vc <= 0:
        raise ValueError("Vc should be strictly positive")
    if Vk <= 0:
        raise ValueError("Vk should be strictly positive")
    if Tc <= 0:
        raise ValueError("Tc should be strictly positive")
    if T <= 0:
        raise ValueError("T should be strictly positive")
    if lwl <= 0:
        raise ValueError("lwl should be strictly positive")
    if bwl <= 0:
        raise ValueError("bwl should be strictly positive")
    if not RHO_WATER_MIN < rho_water < RHO_WATER_MAX:
        raise ValueError(
            f"rho_water should be between {RHO_WATER_MIN} and {RHO_WATER_MAX}")
    # DSYHS checks
    # midship area coefficient cannot be checked here
    check_lwl_to_bwl(value=lwl / bwl)
    check_bwl_to_draft(value=bwl / Tc)
    check_lwl_to_volume(value=lwl / Vc**(1. / 3.))

    if coe is None:
        coe = (lwl / 2., 0., -Tc / 3.) if coe is None else coe

    interp = _get_keel_residuary_ks_interpolator(Vc, Vk, Tc, T, bwl, Zcbk,
                                                 rho_water)

    boatspeed_sign = boatspeed / abs(boatspeed) if boatspeed != 0. else 0.

    froude = froude_number(speed=boatspeed, lwl=lwl)
    if froude <= 0.6:
        residuary_resistance = max(
            [0., interp(abs(boatspeed / sqrt(GRAVITY_STANDARD * lwl)))])
    else:
        at_0_59 = interp(0.59)
        at_0_60 = interp(0.60)
        residuary_resistance = at_0_60 + \
                               (froude - 0.6) * (at_0_60 - at_0_59) / 0.01

    return Force(-residuary_resistance * boatspeed_sign, 0., 0., coe[0],
                 coe[1], coe[2])
示例#13
0
def keel_residuary_delta_heeled_ks(
        boatspeed: float,
        heel_angle: float,
        Vc: float,
        Vk: float,
        Tc: float,
        T: float,
        lwl: float,
        bwl: float,
        coe: Union[Tuple[float, float, float], None] = None,
        rho_water: float = RHO_SEA_WATER_20C) -> Force:
    """Keel residuary resistance [N] delta at a given heel angle.

    KS stands for Keuning Sonnenberg.
    Keuning and Sonnenberg wrote "Approximation of the Hydrodynamic Forces
    on a Sailing Yacht based on the 'Delft Systematic Yacht Hull Series'" in 1998.
    keel_residuary_resistance_delta_heeled_KS uses the results from this publication.

    boatspeed : boat speed [m/s]
    heel_angle : The heel_angle [degrees], between -90 and 90.
    Vc : Canoe body volume of displaced water [m**3] , must be > 0.
    Vk : Keel volume of displaced water [m**3] , must be > 0.
    Tc : Canoe body draft [m], must be >= 0
    T : Total draft [m], must be >= 0
    lwl : Length at Waterline [m] , must be > 0.
    bwl : Beam at Waterline [m] , must be > 0.
    coe : tuple of 3 floats, optional (default [lwl / 2, 0, -Tc/3]).
        Represents the x, y, z coordinates of the centre of effort.
        For residuary resistance, the surfacic barycentre of the underwater
        hull is an acceptable estimate.
        x=lwl / 2 , y = 0., z = -Tc/3 is another acceptable estimate.
    rho_water :  Water density [kg/m**3], must be >= 0 (default RHO_SEA_WATER)

    Returns a Force object, representing the residuary resistance [N] delta of
    the keel at any heel angle.

    """
    if Vc <= 0:
        raise ValueError("Vc should be strictly positive")
    if Vk <= 0:
        raise ValueError("Vk should be strictly positive")
    if Tc <= 0:
        raise ValueError("Tc should be strictly positive")
    if T <= 0:
        raise ValueError("T should be strictly positive")
    if lwl <= 0:
        raise ValueError("lwl should be strictly positive")
    if bwl <= 0:
        raise ValueError("bwl should be strictly positive")
    if not RHO_WATER_MIN < rho_water < RHO_WATER_MAX:
        raise ValueError(f"rho_water should be "
                         f"between {RHO_WATER_MIN} and {RHO_WATER_MAX}")

    # DSYHS checks
    # midship area coefficient cannot be checked here
    check_lwl_to_bwl(value=lwl / bwl)
    check_bwl_to_draft(value=bwl / Tc)
    check_lwl_to_volume(value=lwl / Vc**(1. / 3.))

    if coe is None:
        coe = (lwl / 2., 0., -Tc / 3.)

    boatspeed_sign = boatspeed / abs(boatspeed) if boatspeed != 0. else 0.

    froude = froude_number(speed=boatspeed, lwl=lwl)

    rrk_delta_at_heel_angle = (Vk * rho_water * GRAVITY_STANDARD) * \
                              (-3.5837 * Tc / T +
                               -0.0518 * bwl / Tc +
                               0.5958 * bwl / T +
                               0.2055 * lwl / Vc ** (1. / 3.)) \
                              * froude ** 2 * radians(abs(heel_angle))

    return Force(-rrk_delta_at_heel_angle * boatspeed_sign, 0., 0., coe[0],
                 coe[1], coe[2])
示例#14
0
plt.plot(fns,
         sysser01_r_orc,
         c="orange",
         label="Sysser01 viscous + residuary (orc)")

plt.plot(
    fns,
    sysser01_r_mit,
    c="black",
    # ls="--",
    label="Sysser01 viscous + residuary (mit)")

if plot_type == "viscous+residuary":
    f = [
        froude_number(speed=v, lwl=Sysser01.lwl) for v in [
            0.396, 0.594, 0.792, 0.99, 1.189, 1.387, 1.585, 1.783, 1.981,
            2.179, 2.377
        ]
    ]

    r = [
        0.257851, 0.616414, 1.1084, 1.88482, 3.01934, 4.75255, 9.79318,
        19.4122, 32.7027, 44.5576, 51.149
    ]

    plt.scatter(f, r, label="Towing tank -Upright")

plt.legend()
plt.grid()
plt.title(f"R [N] - {plot_type}")