feat: AR-Shipdesign initial commit
This commit is contained in:
@@ -22,6 +22,19 @@ from arshipdesign.core.hull import Hull
|
||||
from arshipdesign.core.offsets import OffsetsTable
|
||||
|
||||
|
||||
def _standard_sheer_z(
|
||||
x_sta: np.ndarray, lpp: float, depth: float,
|
||||
fwd_rise_frac: float = 0.04, aft_rise_frac: float = 0.020,
|
||||
) -> np.ndarray:
|
||||
"""Línea de cubierta parabólica: mínimo en cuaderna maestra, sube hacia proa/popa."""
|
||||
xi = x_sta / lpp # 0=AP, 1=FP, 0.5=midship
|
||||
return np.where(
|
||||
xi >= 0.5,
|
||||
depth * (1.0 + fwd_rise_frac * ((xi - 0.5) / 0.5) ** 2),
|
||||
depth * (1.0 + aft_rise_frac * ((0.5 - xi) / 0.5) ** 2),
|
||||
)
|
||||
|
||||
|
||||
def make_merchant_hull(
|
||||
name: str = "Buque Mercante / Supply",
|
||||
lpp: float = 20.0,
|
||||
@@ -49,9 +62,10 @@ def make_merchant_hull(
|
||||
flat_bottom_frac : float
|
||||
Ancho del fondo plano / manga (0.85–0.94).
|
||||
"""
|
||||
x_sta = np.linspace(0.0, lpp, n_stations)
|
||||
z_wl = np.linspace(0.0, draft, n_waterlines)
|
||||
xi = (x_sta / lpp - 0.5) * 2.0
|
||||
x_sta = np.linspace(0.0, lpp, n_stations)
|
||||
sheer_z = _standard_sheer_z(x_sta, lpp, depth, fwd_rise_frac=0.04, aft_rise_frac=0.020)
|
||||
z_wl = np.linspace(0.0, float(sheer_z.max()), n_waterlines)
|
||||
xi = (x_sta / lpp - 0.5) * 2.0
|
||||
|
||||
lcb_shift = 2.0 * (lcb_frac - 0.5)
|
||||
f_plan = _merchant_plan_form(xi, cb, lcb_shift)
|
||||
@@ -91,7 +105,8 @@ def make_merchant_hull(
|
||||
lpp=lpp, beam=beam, draft=draft,
|
||||
)
|
||||
return Hull(
|
||||
name=name, lpp=lpp, beam=beam, depth=depth, draft=draft, offsets=offsets
|
||||
name=name, lpp=lpp, beam=beam, depth=depth, draft=draft,
|
||||
offsets=offsets, sheer_z=sheer_z,
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -23,6 +23,19 @@ from arshipdesign.core.hull import Hull
|
||||
from arshipdesign.core.offsets import OffsetsTable
|
||||
|
||||
|
||||
def _standard_sheer_z(
|
||||
x_sta: np.ndarray, lpp: float, depth: float,
|
||||
fwd_rise_frac: float = 0.055, aft_rise_frac: float = 0.025,
|
||||
) -> np.ndarray:
|
||||
"""Línea de cubierta parabólica: mínimo en cuaderna maestra, sube hacia proa/popa."""
|
||||
xi = x_sta / lpp # 0=AP, 1=FP, 0.5=midship
|
||||
return np.where(
|
||||
xi >= 0.5,
|
||||
depth * (1.0 + fwd_rise_frac * ((xi - 0.5) / 0.5) ** 2),
|
||||
depth * (1.0 + aft_rise_frac * ((0.5 - xi) / 0.5) ** 2),
|
||||
)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Forma de sección — carena redonda tipo desplazamiento
|
||||
# ---------------------------------------------------------------------------
|
||||
@@ -77,9 +90,10 @@ def make_displacement_hull(
|
||||
cm : float
|
||||
Coeficiente de cuaderna maestra (0.82–0.92).
|
||||
"""
|
||||
x_sta = np.linspace(0.0, lpp, n_stations)
|
||||
z_wl = np.linspace(0.0, draft, n_waterlines)
|
||||
xi = (x_sta / lpp - 0.5) * 2.0 # ∈ [−1, 1], 0=midship
|
||||
x_sta = np.linspace(0.0, lpp, n_stations)
|
||||
sheer_z = _standard_sheer_z(x_sta, lpp, depth, fwd_rise_frac=0.055, aft_rise_frac=0.025)
|
||||
z_wl = np.linspace(0.0, float(sheer_z.max()), n_waterlines)
|
||||
xi = (x_sta / lpp - 0.5) * 2.0 # ∈ [−1, 1], 0=midship
|
||||
|
||||
# ── Plan form (semi-manga en flotación) ────────────────────────────
|
||||
# LCB desplazado del midship
|
||||
@@ -111,7 +125,8 @@ def make_displacement_hull(
|
||||
lpp=lpp, beam=beam, draft=draft,
|
||||
)
|
||||
return Hull(
|
||||
name=name, lpp=lpp, beam=beam, depth=depth, draft=draft, offsets=offsets
|
||||
name=name, lpp=lpp, beam=beam, depth=depth, draft=draft,
|
||||
offsets=offsets, sheer_z=sheer_z,
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -23,6 +23,19 @@ from arshipdesign.core.hull import Hull
|
||||
from arshipdesign.core.offsets import OffsetsTable
|
||||
|
||||
|
||||
def _standard_sheer_z(
|
||||
x_sta: np.ndarray, lpp: float, depth: float,
|
||||
fwd_rise_frac: float = 0.03, aft_rise_frac: float = 0.015,
|
||||
) -> np.ndarray:
|
||||
"""Línea de cubierta parabólica: mínimo en cuaderna maestra, sube hacia proa/popa."""
|
||||
xi = x_sta / lpp # 0=AP, 1=FP, 0.5=midship
|
||||
return np.where(
|
||||
xi >= 0.5,
|
||||
depth * (1.0 + fwd_rise_frac * ((xi - 0.5) / 0.5) ** 2),
|
||||
depth * (1.0 + aft_rise_frac * ((0.5 - xi) / 0.5) ** 2),
|
||||
)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# API pública
|
||||
# ---------------------------------------------------------------------------
|
||||
@@ -56,9 +69,10 @@ def make_planing_hull(
|
||||
flare : float
|
||||
Fracción de ensanchamiento por encima del chine (0 = sin ensanche).
|
||||
"""
|
||||
x_sta = np.linspace(0.0, lpp, n_stations)
|
||||
z_wl = np.linspace(0.0, draft, n_waterlines)
|
||||
xi = (x_sta / lpp - 0.5) * 2.0 # normalizado ∈ [−1, 1], 0=midship
|
||||
x_sta = np.linspace(0.0, lpp, n_stations)
|
||||
sheer_z = _standard_sheer_z(x_sta, lpp, depth, fwd_rise_frac=0.03, aft_rise_frac=0.015)
|
||||
z_wl = np.linspace(0.0, float(sheer_z.max()), n_waterlines)
|
||||
xi = (x_sta / lpp - 0.5) * 2.0 # normalizado ∈ [−1, 1], 0=midship
|
||||
|
||||
# ── Plan form: ancho en línea de agua por estación ─────────────────
|
||||
# El planeador tiene popa muy ancha y proa más estrecha
|
||||
@@ -105,7 +119,8 @@ def make_planing_hull(
|
||||
lpp=lpp, beam=beam, draft=draft,
|
||||
)
|
||||
return Hull(
|
||||
name=name, lpp=lpp, beam=beam, depth=depth, draft=draft, offsets=offsets
|
||||
name=name, lpp=lpp, beam=beam, depth=depth, draft=draft,
|
||||
offsets=offsets, sheer_z=sheer_z,
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -24,6 +24,19 @@ from arshipdesign.core.hull import Hull
|
||||
from arshipdesign.core.offsets import OffsetsTable
|
||||
|
||||
|
||||
def _standard_sheer_z(
|
||||
x_sta: np.ndarray, lpp: float, depth: float,
|
||||
fwd_rise_frac: float = 0.08, aft_rise_frac: float = 0.04,
|
||||
) -> np.ndarray:
|
||||
"""Línea de cubierta parabólica: mínimo en cuaderna maestra, sube hacia proa/popa."""
|
||||
xi = x_sta / lpp # 0=AP, 1=FP, 0.5=midship
|
||||
return np.where(
|
||||
xi >= 0.5,
|
||||
depth * (1.0 + fwd_rise_frac * ((xi - 0.5) / 0.5) ** 2),
|
||||
depth * (1.0 + aft_rise_frac * ((0.5 - xi) / 0.5) ** 2),
|
||||
)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Forma de sección — velero (V-fondo + cuerpo redondeado)
|
||||
# ---------------------------------------------------------------------------
|
||||
@@ -45,6 +58,8 @@ def _sailing_section(
|
||||
"""
|
||||
if y_wl < 1e-9 or T < 1e-9:
|
||||
return 0.0
|
||||
if z >= T:
|
||||
return y_wl # plumb topside above design waterline
|
||||
t_full = min(1.0, max(0.0, z / T))
|
||||
if t_full < 1e-12:
|
||||
return 0.0
|
||||
@@ -97,9 +112,10 @@ def make_sailing_hull(
|
||||
deadrise_mid : float
|
||||
Ángulo de astilla muerta en cuaderna maestra [°].
|
||||
"""
|
||||
x_sta = np.linspace(0.0, lpp, n_stations)
|
||||
z_wl = np.linspace(0.0, draft, n_waterlines)
|
||||
xi = (x_sta / lpp - 0.5) * 2.0
|
||||
x_sta = np.linspace(0.0, lpp, n_stations)
|
||||
sheer_z = _standard_sheer_z(x_sta, lpp, depth, fwd_rise_frac=0.08, aft_rise_frac=0.04)
|
||||
z_wl = np.linspace(0.0, float(sheer_z.max()), n_waterlines)
|
||||
xi = (x_sta / lpp - 0.5) * 2.0
|
||||
|
||||
lcb_shift = 2.0 * (lcb_frac - 0.5)
|
||||
|
||||
@@ -131,7 +147,8 @@ def make_sailing_hull(
|
||||
lpp=lpp, beam=beam, draft=draft,
|
||||
)
|
||||
return Hull(
|
||||
name=name, lpp=lpp, beam=beam, depth=depth, draft=draft, offsets=offsets
|
||||
name=name, lpp=lpp, beam=beam, depth=depth, draft=draft,
|
||||
offsets=offsets, sheer_z=sheer_z,
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -22,6 +22,21 @@ from arshipdesign.core.hull import Hull
|
||||
from arshipdesign.core.offsets import OffsetsTable
|
||||
|
||||
|
||||
def _standard_sheer_z(
|
||||
x_sta: np.ndarray, lpp: float, depth: float,
|
||||
fwd_rise_frac: float = 0.05, aft_rise_frac: float = 0.025,
|
||||
) -> np.ndarray:
|
||||
"""Línea de cubierta parabólica: mínimo en cuaderna maestra, sube hacia proa/popa.
|
||||
El puntal de trazado (depth) es el valor en cuaderna maestra.
|
||||
"""
|
||||
xi = x_sta / lpp # 0=AP, 1=FP, 0.5=midship
|
||||
return np.where(
|
||||
xi >= 0.5,
|
||||
depth * (1.0 + fwd_rise_frac * ((xi - 0.5) / 0.5) ** 2),
|
||||
depth * (1.0 + aft_rise_frac * ((0.5 - xi) / 0.5) ** 2),
|
||||
)
|
||||
|
||||
|
||||
def make_workboat_hull(
|
||||
name: str = "Workboat / Supply",
|
||||
lpp: float = 15.0,
|
||||
@@ -44,9 +59,10 @@ def make_workboat_hull(
|
||||
flat_bottom_frac : float
|
||||
Anchura del fondo plano como fracción de la manga (0.80–0.92).
|
||||
"""
|
||||
x_sta = np.linspace(0.0, lpp, n_stations)
|
||||
z_wl = np.linspace(0.0, draft, n_waterlines)
|
||||
xi = (x_sta / lpp - 0.5) * 2.0
|
||||
x_sta = np.linspace(0.0, lpp, n_stations)
|
||||
sheer_z = _standard_sheer_z(x_sta, lpp, depth, fwd_rise_frac=0.035, aft_rise_frac=0.020)
|
||||
z_wl = np.linspace(0.0, float(sheer_z.max()), n_waterlines)
|
||||
xi = (x_sta / lpp - 0.5) * 2.0
|
||||
|
||||
lcb_shift = 2.0 * (lcb_frac - 0.5)
|
||||
|
||||
@@ -91,7 +107,8 @@ def make_workboat_hull(
|
||||
lpp=lpp, beam=beam, draft=draft,
|
||||
)
|
||||
return Hull(
|
||||
name=name, lpp=lpp, beam=beam, depth=depth, draft=draft, offsets=offsets
|
||||
name=name, lpp=lpp, beam=beam, depth=depth, draft=draft,
|
||||
offsets=offsets, sheer_z=sheer_z,
|
||||
)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user