# Exploring the static force model in Seaman


```python
%load_ext autoreload
%autoreload 2
%matplotlib inline
```


```python
import sympy as sp
from sympy.plotting import plot as plot
from sympy.plotting import plot3d as plot3d
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

import seaman.helpers
import seaman_symbol as ss
import total_equations as equations
import total_lambda_functions as lambda_functions

sp.init_printing()
```

## Coordinate system
In the static force model forces and moments are referred to a righthanded
coordinate system with 4 degrees of freedom (surge, sway,roll, yaw) with origin in L/2, in the centre line of the ship and
vertically in the mean water line:

$\left[\frac{L}{2},0,t_m\right]$

* X : forces in ship heading direction
* Y : forces perpendicular to ship heading direction on the water plane. 
**Note!** Y direction is not changing with roll.
* P : moment around X
* N : moment around Z

Ship motions in time domain simulations are however referred to CG.



## Nomenclature
The following symbols are used in this documentation:


```python
import seaman_symbols
from IPython.core.display import HTML
```


```python
symbols = [item for key,item in seaman_symbols.__dict__.items()]
```


```python
HTML(ss.create_html_table(symbols=symbols))
```

## Bis system
The bis system is used in Seaman to make physical quantities nondimensional. The denominators in the table below is used. The quantities are denoted with a '' sign when they are in bis units, otherwise they are in SI units.    


```python
from bis_system import BisSystem
```


```python

HTML(BisSystem.html_table())
```

## Bis example
Suppose that we have a force $Y''$ that can be calculated from linear velocity $x''$ multiplied with some kind of nondimensional coefficient $C$:


```python
l = ss.Symbol('l')
m = ss.Symbol('m')
C = ss.Coefficient('C')

x = ss.Bis('x',denominator=BisSystem.linear_velocity)
Y = ss.Bis('Y',denominator=BisSystem.force)

eq = sp.Eq(Y.bis,C*x.bis**2)
```


```python
eq
```

Relation between $Y$ (SI force [N]) and $Y''$ (bis force):


```python
Y.bis_eq
```

Relation between $x$ (SI linear velocity [m/s]) and $x''$ (bis linear velocity):


```python
x.bis_eq
```

**Note!** Linear velocity in bis system is the same thing as Froude Number.

The equation can be written in SI units by substitution of the bis relations above:


```python
eq3 = ss.expand_bis(equation = eq)
eq3
```

## Total forces
The total forces on the ship can be expressed as described below. 
The underlying equations are explained in:
### Hull
* [Surge hull equations](05_seaman_surge_hull_equation.ipynb)
* [Sway hull equations](02_seaman_sway_hull_equation.ipynb)
* [Yaw hull equations](03_seaman_yaw_hull_equation.ipynb)

### Rudder:
* [Rudder equations](04_seaman_rudder_equation.ipynb)



## Surge


```python
equations.surge_equation
```

Expanding the surge equation (using equations for hull and rudder) and converting to SI units:


```python
equations.surge_equation_expanded_SI
```

## Sway


```python
equations.sway_equation
```


```python
equations.sway_equation_expanded_SI
```

## Yaw


```python
equations.yaw_equation
```


```python
equations.yaw_equation_expanded_SI
```

## Roll


```python
equations.roll_equation
```


```python
equations.roll_equation_expanded_SI
```


```python
import surge_hull_equations as surge_hull_equations
import sway_hull_equations as sway_hull_equations
import yaw_hull_equations as yaw_hull_equations
import roll_hull_equations as roll_hull_equations
import rudder_equations as rudder_equations
```


```python
from seaman_symbols import *
```

## Real seaman++
Run real seaman in C++ to verify that the documented model is correct. 


```python
import generate_input
shipdict = seaman.ShipDict.load('../../tests/test_ship.ship')
import run_real_seaman

```

### Surge


```python
%connect_info
```


```python
df = pd.DataFrame()
df['v_w'] = np.linspace(-3,3,20)
df['delta'] = 0
df['T'] = 0
df['rho'] = 1025.0
df['g'] = 9.81
df['u_w'] = 5.0
df['r_w'] = 0.0
df['X_res'] = -np.interp(df['u_w'],shipdict.res_data['vres'],shipdict.res_data['res'])


result_comparison = run_real_seaman.compare_with_seaman(lambda_function=lambda_functions.total_surge_function,
                                                        shipdict = shipdict,
                                                        df = df,
                                                        label = 'fx',
                                                        seaman_function=run_real_seaman.calculate_static_ship
                                                       )

fig,ax = plt.subplots()
result_comparison.plot(x = 'v_w',y = ['fx','fx_seaman'],ax = ax)
ax.set_title('Drift angle variation');
```

Real seaman has a maximum effective rudder angle 0.61 rad for the rudder drag, which is why seaman gives different result for really large drift angles or yaw rates:


```python
df = pd.DataFrame()
df['delta'] = np.deg2rad(np.linspace(-45,45,50))
df['r_w'] = 0
df['T'] = 0
df['rho'] = 1025.0
df['g'] = 9.81
df['u_w'] = 5.0
df['v_w'] = 0.0
df['X_res'] = -np.interp(df['u_w'],shipdict.res_data['vres'],shipdict.res_data['res'])

result_comparison = run_real_seaman.compare_with_seaman(lambda_function=lambda_functions.total_surge_function,
                                                        shipdict = shipdict,
                                                        df = df,
                                                        label = 'fx',
                                                        seaman_function=run_real_seaman.calculate_static_ship
                                                       )

fig,ax = plt.subplots()
result_comparison.plot(x = 'delta',y = ['fx','fx_seaman'],ax = ax)
ax.set_title('Rudder angle variation');
```


```python
df = pd.DataFrame()
df['r_w'] = np.linspace(-0.05,0.05,20)
df['delta'] = 0
df['T'] = 0
df['rho'] = 1025.0
df['g'] = 9.81
df['u_w'] = 5.0
df['v_w'] = 0.0
df['X_res'] = -np.interp(df['u_w'],shipdict.res_data['vres'],shipdict.res_data['res'])

shipdict2 = shipdict.copy()
#shipdict2.design_particulars['lcg'] = 0.0  


df_input = generate_input.add_shipdict_inputs(lambda_function=lambda_functions.total_surge_function,
                                                  shipdict=shipdict2,
                                                  df=df)



result_comparison = run_real_seaman.compare_with_seaman(lambda_function=lambda_functions.total_surge_function,
                                                        shipdict = shipdict2,
                                                        df = df,
                                                        label = 'fx',
                                                        seaman_function=run_real_seaman.calculate_static_ship
                                                       )

fig,ax = plt.subplots()
result_comparison.plot(x = 'r_w',y = ['fx','fx_seaman'],ax = ax)
ax.set_title('Yaw rate variation');
```


```python
result_comparison['fx']
```


```python
df_input.head()
```

### Sway


```python
df = pd.DataFrame()
df['v_w'] = np.linspace(-6,6,20)
df['delta'] = 0
df['T'] = 0
df['rho'] = 1025.0
df['g'] = 9.81
df['u_w'] = 5.0
df['r_w'] = 0.0

result_comparison = run_real_seaman.compare_with_seaman(lambda_function=lambda_functions.total_sway_function,
                                                        shipdict = shipdict,
                                                        df = df,
                                                        label = 'fy',
                                                        seaman_function=run_real_seaman.calculate_static_ship
                                                       )

fig,ax = plt.subplots()
result_comparison.plot(x = 'v_w',y = ['fy','fy_seaman'],ax = ax)
ax.set_title('Drift angle variation');
```


```python
%connect_info
```


```python
df = pd.DataFrame()
df['r_w'] = np.linspace(-0.1,0.1,20)
df['delta'] = 0
df['T'] = 0
df['rho'] = 1025.0
df['g'] = 9.81
df['u_w'] = 5.0
df['v_w'] = 0.0

shipdict2 = shipdict.copy()
#shipdict2.design_particulars['lcg'] = 0  # Something strange with lcg in Seaman?

result_comparison = run_real_seaman.compare_with_seaman(lambda_function=lambda_functions.total_sway_function,
                                                        shipdict = shipdict2,
                                                        df = df,
                                                        label = 'fy',
                                                        seaman_function=run_real_seaman.calculate_static_ship
                                                       )

fig,ax = plt.subplots()
result_comparison.plot(x = 'r_w',y = ['fy','fy_seaman'],ax = ax)
ax.set_title('Yaw rate variation');

fig,ax = plt.subplots()
result_comparison.plot(x = 'r_w',y = ['fy_rudders_seaman'],ax = ax)
ax.set_title('Yaw rate variation Rudder');



```


```python
df = pd.DataFrame()
df['delta'] = np.deg2rad(np.linspace(-45,45,20))
df['r_w'] = 0
df['T'] = 0
df['rho'] = 1025.0
df['g'] = 9.81
df['u_w'] = 5.0
df['v_w'] = 0.0

shipdict2 = shipdict.copy()
#shipdict2.rudder_coeff_data['s'] = 0

result_comparison = run_real_seaman.compare_with_seaman(lambda_function=lambda_functions.total_sway_function,
                                                        shipdict = shipdict2,
                                                        df = df,
                                                        label = 'fy',
                                                        seaman_function=run_real_seaman.calculate_static_ship
                                                       )

fig,ax = plt.subplots()
result_comparison.plot(x = 'delta',y = ['fy','fy_seaman'],ax = ax)
ax.set_title('Rudder angle variation');
```

### Yaw


```python
df = pd.DataFrame()
df['v_w'] = np.linspace(-2,2,20)
df['delta'] = 0
df['T'] = 0
df['rho'] = 1025.0
df['g'] = 9.81
df['u_w'] = 5.0
df['r_w'] = 0.0
df['Cd_lever'] = 0.0
shipdict2 = shipdict.copy()
#shipdict2.rudder_coeff_data['s'] = 0

result_comparison = run_real_seaman.compare_with_seaman(lambda_function=lambda_functions.total_yaw_function,
                                                        shipdict = shipdict2,
                                                        df = df,
                                                        label = 'mz',
                                                        seaman_function=run_real_seaman.calculate_static_ship
                                                       )

fig,ax = plt.subplots()
result_comparison.plot(x = 'v_w',y = ['mz','mz_seaman'],ax = ax)
ax.set_title('Drift angle variation');
ax.grid()
```


```python
df = pd.DataFrame()
df['delta'] = np.deg2rad(np.linspace(-20,20,20))
df['v_w'] = 0
df['T'] = 0
df['rho'] = 1025.0
df['g'] = 9.81
df['u_w'] = 5.0
df['r_w'] = 0.0
df['Cd_lever'] = 0

result_comparison = run_real_seaman.compare_with_seaman(lambda_function=lambda_functions.total_yaw_function,
                                                        shipdict = shipdict,
                                                        df = df,
                                                        label = 'mz',
                                                        seaman_function=run_real_seaman.calculate_static_ship
                                                       )

fig,ax = plt.subplots()
result_comparison.plot(x = 'delta',y = ['mz','mz_seaman'],ax = ax)
ax.set_title('Rudder angle variation');
```

### Roll


```python
%connect_info
```


```python
df = pd.DataFrame()
df['delta'] = np.deg2rad(np.linspace(-5,5,20))
df['v_w'] = 0
df['T'] = 0
df['rho'] = 1025.0
df['g'] = 9.81
df['u_w'] = 5.0
df['r_w'] = 0.0
df['p'] = 0
df['Cd_lever'] = 0

result_comparison = run_real_seaman.compare_with_seaman(lambda_function=lambda_functions.total_roll_function,
                                                        shipdict = shipdict,
                                                        df = df,
                                                        label = 'mx',
                                                        seaman_function=run_real_seaman.calculate_static_ship
                                                       )

fig,ax = plt.subplots()
result_comparison.plot(x = 'delta',y = ['mx','mx_seaman'],ax = ax)
ax.set_title('Rudder angle variation');
```


```python
df = pd.DataFrame()
df['beta'] = np.deg2rad(np.linspace(-20,20,20))
df['V'] = V = 5.0
df['u_w'] = V*np.cos(df['beta'])
df['v_w'] = -V*np.sin(df['beta'])
 
df['delta'] = 0
df['T'] = 0
df['rho'] = 1025.0
df['g'] = 9.81
df['r_w'] = 0.0
df['p'] = 0
df['Cd_lever'] = 0

shipdict2 = shipdict.copy()
#shipdict2.rudder_coeff_data['s'] = 0
#shipdict2.non_lin_coeff_data['cd'] = 3


result_comparison = run_real_seaman.compare_with_seaman(lambda_function=lambda_functions.total_roll_function,
                                                        shipdict = shipdict2,
                                                        df = df,
                                                        label = 'mx',
                                                        seaman_function=run_real_seaman.calculate_static_ship
                                                       )

fig,ax = plt.subplots()
result_comparison.plot(x = 'v_w',y = ['mx','mx_seaman'],ax = ax)
ax.set_title('Drift angle variation');
```


```python

```

386d93e32d3faa20f11fced8aa1cb03416d6488b
ipynb
Jupyter Notebook
docs/seaman/01.1_seaman_matematical_model.ipynb
martinlarsalbert/wPCC
16e0d4cc850d503247916c9f5bd9f0ddb07f8930
MIT
docs/seaman/01.1_seaman_matematical_model.ipynb
martinlarsalbert/wPCC
16e0d4cc850d503247916c9f5bd9f0ddb07f8930
MIT
docs/seaman/01.1_seaman_matematical_model.ipynb
martinlarsalbert/wPCC
16e0d4cc850d503247916c9f5bd9f0ddb07f8930
MIT
Qwen/Qwen-72B
1. YES
2. YES