diff --git a/README.md b/README.md index 92682dc..dcdf1a6 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,7 @@ NavalToolbox is built as a **Rust library** (`navaltoolbox`) with optional Pytho - **Stability**: GZ curve calculation with trim optimization and downflooding detection - **Complete stability analysis**: Combines hydrostatics, GZ curve, and wind heeling data - **Tanks**: Fill level management, free surface effects +- **Loading Conditions**: Aggregate mass items and tank fill overrides for operational profiles - **Silhouettes**: Wind heeling calculations (DXF/VTK support) - **Verification**: Rhai scripting engine for custom stability criteria (IMO, localized rules) - **Visualization**: Interactive 3D visualization using Plotly (Vessel, Tanks, Opening, Hydrostatics) @@ -72,12 +73,21 @@ print(f"Draft: {state_disp.draft:.3f} m") state_drafts = calc.from_drafts(draft_ap=6.0, draft_fp=4.0) print(f"Trim: {state_drafts.trim:.2f}°") -# Calculate GZ curve +# Loading Condition +from navaltoolbox import LoadingCondition, MassCategory + +lc = LoadingCondition("Departure") +lc.add_mass_simple("Lightship", 5000000.0, (40.0, 0.0, 5.0), MassCategory.lightship()) +lc.apply(vessel) +disp, combined_cog = lc.resolve(vessel) +item_disp, item_cog = lc.resolve_items() + +# Calculate GZ curve (pass only the mass items, tanks are auto-included by StabilityCalculator) stab = StabilityCalculator(vessel, water_density=1025.0) heels = [0, 10, 20, 30, 40, 50, 60] curve = stab.gz_curve( - displacement_mass=1000000, - cog=(50.0, 0.0, 5.0), + displacement_mass=item_disp, + cog=item_cog, heels=heels ) for heel, gz in zip(curve.heels(), curve.values()): @@ -85,8 +95,8 @@ for heel, gz in zip(curve.heels(), curve.values()): # Complete stability analysis (hydrostatics + GZ + wind data) result = stab.complete_stability( - displacement_mass=1000000, - cog=(50.0, 0.0, 5.0), + displacement_mass=item_disp, + cog=item_cog, heels=heels ) print(f"GM0: {result.gm0:.3f}m") diff --git a/docs/source/api/python/index.rst b/docs/source/api/python/index.rst index 96e9c05..9daf4fb 100644 --- a/docs/source/api/python/index.rst +++ b/docs/source/api/python/index.rst @@ -8,6 +8,7 @@ Python API hydrostatics stability tanks + loading plotting visualization scripting diff --git a/docs/source/api/python/loading.rst b/docs/source/api/python/loading.rst new file mode 100644 index 0000000..969588a --- /dev/null +++ b/docs/source/api/python/loading.rst @@ -0,0 +1,220 @@ +Loading Conditions +================== + +Classes for managing mass inventories and tank fill overrides to define operational profiles. + +MassCategory +------------ + + .. py:class:: MassCategory + + Category of a mass item. + + .. py:staticmethod:: lightship() + + Creates a Lightship category. + + .. py:staticmethod:: deadweight() + + Creates a Deadweight category. + + .. py:staticmethod:: other() + + Creates an Other category (default). + + +MassItem +-------- + + .. py:class:: MassItem(name, mass, cog, category=None) + + A single mass item with name, mass, position, and optional category. + + :param name: Identifier for the mass item. + :param mass: Mass in kg. + :param cog: Center of gravity (lcg, tcg, vcg) in meters. + :param category: Optional MassCategory (default: Other). + + .. py:method:: __init__(name, mass, cog, category=None) + + Creates a MassItem. + + **Properties** + + .. py:attribute:: name + :type: str + :no-index: + + .. py:attribute:: mass + :type: float + + .. py:attribute:: cog + :type: tuple[float, float, float] + + .. py:attribute:: category + :type: MassCategory + +LoadingCondition +---------------- + + .. py:class:: LoadingCondition(name) + + A complete loading condition with mass items and tank fill overrides. + + :param name: Name of the loading condition. + + .. py:method:: __init__(name) + + Creates a LoadingCondition. + + **Properties** + + .. py:attribute:: name + :type: str + :no-index: + + Name of the loading condition. + + **Mass Management** + + .. py:method:: add_mass(item) + + Add a MassItem. + + :param item: A MassItem instance. + + .. py:method:: add_mass_simple(name, mass, cog, category=None) + + Add a mass item by parameters (convenience). + + :param name: Identifier for the mass item. + :param mass: Mass in kg. + :param cog: Center of gravity (lcg, tcg, vcg) in meters. + :param category: Optional MassCategory (default: Other). + + .. py:method:: remove_mass(name) + + Remove a mass item by name. + + :param name: Name of the mass. + :returns: True if found and removed. + :rtype: bool + + .. py:method:: get_masses() + + Returns all mass items. + + :rtype: list[MassItem] + + .. py:method:: num_masses() + + Returns the number of mass items. + + :rtype: int + + **Tank Fill Overrides** + + .. py:method:: set_tank_fill(tank_name, fill_level) + + Set a tank fill override by fill level (0.0 to 1.0). + + .. py:method:: set_tank_fill_percent(tank_name, fill_percent) + + Set a tank fill override by percentage (0 to 100). + + .. py:method:: remove_tank_fill(tank_name) + + Remove a tank fill override. + + :returns: True if found and removed. + :rtype: bool + + .. py:method:: num_tank_overrides() + + Returns the number of tank fill overrides. + + :rtype: int + + .. py:method:: get_tank_fills() + + Returns tank fill overrides as a dictionary. + + :returns: {name: fill_level} + :rtype: dict[str, float] + + **Application & Calculation** + + .. py:method:: apply(vessel) + + Apply tank fill overrides to the vessel's tanks. Only tanks listed in overrides are modified. Other tanks keep their current fill level. + + :param vessel: Vessel instance. + + .. py:method:: total_displacement(vessel) + + Returns the total displacement (masses + tank fluid masses) in kg. Must be called after apply(). + + :param vessel: Vessel instance. + :rtype: float + + .. py:method:: total_cog(vessel) + + Returns the combined center of gravity in meters. Must be called after apply(). + + :param vessel: Vessel instance. + :returns: (lcg, tcg, vcg) + :rtype: tuple[float, float, float] + + .. py:method:: resolve(vessel) + + Returns (total_displacement, (lcg, tcg, vcg)) in a single call. Must be called after apply(). + + :param vessel: Vessel instance. + :rtype: tuple[float, tuple[float, float, float]] + + .. py:method:: item_displacement() + + Returns the displacement of mass items only (excluding tank fluids) in kg. + + :rtype: float + + .. py:method:: item_cog() + + Returns the center of gravity of mass items only (lcg, tcg, vcg) in meters. + + :rtype: tuple[float, float, float] + + .. py:method:: resolve_items() + + Returns (item_displacement, (lcg, tcg, vcg)) in a single call. Use this for stability calculations to avoid double-counting tank masses. + + :rtype: tuple[float, tuple[float, float, float]] + + **Serialization and Copying** + + .. py:method:: to_json() + + Serialize to JSON string. + + :rtype: str + + .. py:staticmethod:: from_json(json_str) + + Deserialize from JSON string. + + :rtype: LoadingCondition + + .. py:method:: save_json(path) + + Save to JSON file. + + .. py:staticmethod:: load_json(path) + + Load from JSON file. + + .. py:method:: copy(name=None) + + Create a copy, optionally with a new name. + + :param name: New name + :rtype: LoadingCondition diff --git a/docs/source/api/python/tanks.rst b/docs/source/api/python/tanks.rst index 064b66d..fa12f70 100644 --- a/docs/source/api/python/tanks.rst +++ b/docs/source/api/python/tanks.rst @@ -50,6 +50,7 @@ Tank .. py:attribute:: name :type: str + :no-index: Tank name. diff --git a/docs/source/index.rst b/docs/source/index.rst index 18e24e0..74e252a 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -38,6 +38,10 @@ Key Features

📐 Complete

Hull, Vessel, Tanks, Hydrostatics, Stability modules. Supports multi-hull configurations.

+
+

⚖️ Loading Conditions

+

Compose mass inventories and tank overrides to build operational profiles.

+
Quick Example diff --git a/python/README.md b/python/README.md index cc7c15c..337b7e0 100644 --- a/python/README.md +++ b/python/README.md @@ -18,6 +18,7 @@ NavalToolbox provides fast and accurate naval architecture calculations through - ⚖️ **Stability Analysis**: GZ curve calculation with automatic trim optimization - 🌊 **Downflooding Detection**: Automatic detection of submerged openings - 🛢️ **Tank Management**: Fill levels, free surface effects, sounding tables +- ⚖️ **Loading Conditions**: Compose mass inventories and tank overrides to build operational profiles - 💨 **Wind Heeling**: Silhouette-based wind calculations (DXF/VTK support) - 📝 **Scriptable Verification**: Rhai scripting engine for custom stability criteria - 🧊 **3D Visualization**: Interactive vessel and hydrostatic visualization with Plotly @@ -112,6 +113,33 @@ max_heel = heels[max_idx] print(f"\nMax GZ: {max_gz:.3f}m at {max_heel}°") ``` +### Loading Conditions + +```python +from navaltoolbox import Hull, Vessel, Tank, LoadingCondition, MassCategory + +# Create vessel with a tank +vessel = Vessel(Hull("ship.stl")) +vessel.add_tank(Tank.from_box("FO_1", 20.0, 30.0, -5.0, 5.0, 0.0, 2.0, 1000.0)) + +# Define loading condition +lc = LoadingCondition("Arrival") +lc.add_mass_simple("Lightship", 5000000.0, (40.0, 0.0, 5.0), MassCategory.lightship()) +lc.set_tank_fill_percent("FO_1", 50.0) + +# Apply and resolve +lc.apply(vessel) +disp, cog = lc.resolve(vessel) +item_disp, item_cog = lc.resolve_items() + +print(f"Total Combined Displacement: {disp:.0f} kg") +print(f"Combined COG: {cog}") +print(f"Solid items only: {item_disp:.0f} kg at {item_cog}") + +# Use item_disp and item_cog for stability calculations +# as the StabilityCalculator handles tanks intrinsically. +``` + ## Documentation For more detailed documentation, examples, and API reference, visit: