Módulo 1 fixes + Módulo 2 motor hidrostático (Tasks 13–13b)
Fixes Module 1 UI: - wizard_cruiser/sailing/planing: perfiles sin^n calibrados por Cm, V-bottom con ángulo de astilla, corrección zona sobre chine planeador - viewer_3d: buffer hull pendiente para eliminar race condition 500ms - viewer_lines: reescritura completa — waterlines visibles, control points interactivos (drag DelftShip-style), señal offsets_edited - main_window: conecta offsets_edited → slot _on_offsets_edited_from_viewer que propaga cambios a todos los visores, editor, 3D y barra hidrostática Módulo 2 — motor HydrostaticCurves (Task 13): - integrator.py: integrate() (Simpson+trapz), waterplane_strips(), section_areas() - upright.py: UprightHydrostatics (19 campos), compute_upright() single-pass - curves_of_form.py: HydrostaticCurves.compute(), at_draft(), to_csv_lines(), to_dict() - tests/test_module2_hydrostatics.py: 83 tests — Wigley V&V, monotonicidad, CSV export, IACS Rec.34 §4.3–4.5; todos los 224 tests pasan Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,2 +1,95 @@
|
||||
"""Integradores Simpson. Stub — Sprint 2."""
|
||||
raise NotImplementedError("integrator — Sprint 2")
|
||||
"""
|
||||
Integradores numéricos para hidrostáticos navales.
|
||||
|
||||
Regla de Simpson con fallback a trapecios cuando hay menos de 3 puntos.
|
||||
Conforme con IACS Rec.34 §4.2 — métodos de integración numérica.
|
||||
|
||||
Autor: Álvaro Romero
|
||||
Módulo 2 — AR-ShipDesign
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import numpy as np
|
||||
from scipy.integrate import simpson as _scipy_simpson
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Integración 1D
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
def integrate(y: np.ndarray, x: np.ndarray) -> float:
|
||||
"""Integra y(x) usando la regla de Simpson (fallback a trapecios ≤ 2 pts).
|
||||
|
||||
Parameters
|
||||
----------
|
||||
y : array_like, shape (n,)
|
||||
Ordenadas.
|
||||
x : array_like, shape (n,)
|
||||
Abscisas, monótonamente crecientes.
|
||||
|
||||
Returns
|
||||
-------
|
||||
float
|
||||
∫ y dx
|
||||
"""
|
||||
y = np.asarray(y, dtype=float)
|
||||
x = np.asarray(x, dtype=float)
|
||||
n = len(x)
|
||||
if n < 2:
|
||||
return 0.0
|
||||
if n >= 3:
|
||||
return float(_scipy_simpson(y, x=x))
|
||||
return float(np.trapz(y, x))
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Primitivas para plano de flotación y secciones
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
def waterplane_strips(offsets_table, draft: float) -> tuple[np.ndarray, np.ndarray]:
|
||||
"""Devuelve (x_stations, y_half_breadths) en el calado *draft*.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
offsets_table : OffsetsTable
|
||||
Tabla de offsets del casco.
|
||||
draft : float
|
||||
Calado al que se evalúa el plano de flotación [m].
|
||||
|
||||
Returns
|
||||
-------
|
||||
x : np.ndarray, shape (n_sta,)
|
||||
Posiciones longitudinales de las estaciones [m].
|
||||
y : np.ndarray, shape (n_sta,)
|
||||
Semi-mangas en el plano draft [m].
|
||||
"""
|
||||
x = offsets_table.x_stations
|
||||
y = np.array([offsets_table.half_breadth(xi, float(draft)) for xi in x])
|
||||
return x, y
|
||||
|
||||
|
||||
def section_areas_and_centroids(
|
||||
sections: list, draft: float
|
||||
) -> tuple[np.ndarray, np.ndarray, np.ndarray]:
|
||||
"""Devuelve (x, areas, centroides_z) para todas las secciones al calado *draft*.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
sections : list[Section]
|
||||
Lista de secciones del casco.
|
||||
draft : float
|
||||
Calado de cálculo [m].
|
||||
|
||||
Returns
|
||||
-------
|
||||
x : np.ndarray, shape (n_sec,)
|
||||
Posiciones longitudinales [m].
|
||||
areas : np.ndarray, shape (n_sec,)
|
||||
Áreas sumergidas [m²].
|
||||
cz : np.ndarray, shape (n_sec,)
|
||||
Centroides verticales de cada sección [m desde quilla].
|
||||
"""
|
||||
x = np.array([s.x for s in sections])
|
||||
a = np.array([s.area(draft=draft) for s in sections])
|
||||
cz = np.array([s.centroid_z(draft=draft) for s in sections])
|
||||
return x, a, cz
|
||||
|
||||
Reference in New Issue
Block a user