Exemples

Introduction

En stabilité, les règles de Simpson sont employées pour calculer l’aire sous la courbe du bras de levier (GZ) d’un navire. Cette courbe donne la longueur du bras de levier sur lequel la force de flottaison peut agir pour rétablir une gîte. Le GZ est donc en mètres et varie pour divers angles \(\theta\) de gîte.

Cette section se concentre sur l’application des règles de Simpson. Ce n’est donc pas nécessaire de comprendre le GZ davantage pour faire les exercices ci-dessous. Pour la réussite de l’examen, il faut cependant comprendre l’intégralité de la section sur la stabilité statique.

Parce que les tableaux présentent la courbe GZ en fonction des degrés d’inclinaison, l’aire sous la courbe sera en unités de « mètres-degrés » (m-deg). Or, la plupart des critères réglementaires de stabilité sont exprimés en « mètres-radians » (m-rad). Conséquemment, une fois l’intégrale calculée, il faut convertir les degrés en radians avec le facteur \(\frac{2\pi}{360}\approx 0.017453\).

Livret de stabilité du Gypsum Centennial

Le livret présente différentes tables de \(KN\) en fonction de l’angle de gîte. Les tables rapportent ce KN à des angles réguliers. Conséquemment, les règles de Simpson sont parfaitement adaptées.

Exemple 1

Figure 1: Table GZ du Gypsum Centennial en condition #2 (accostage)

La Figure 1 montre la courbe GZ du Gypsum quand il est en condition d’accostage. Cette condition reflète qu’il est vide et que ses ballasts avants sont remplis.

La première ligne du tableau donne l’angle de gîte (« ANGLE »), la deuxième ligne donne le bras de levier (« GZ »), puis la dernière ligne donne l’aire sous la courbe (« GZ AREA ») entre la valeur actuelle et la valeur précédente. On peut ainsi voir que la table va de 2° à 70°. On doit également comprendre la colonne implicite à 0°, ou tout est égal à zéro. Les données sont disponibles au format csv ici.

Calculer l’aire sous la courbe jusqu’à 30°

Les données brutes de 0° jusqu’à 30° sont au Tableau 1 et elles sont représentées graphiquement à la Figure 2. On remarque que la courbe de GZ est répartie entre 16 points entre zéro et 30°.

Voir le code.
import pandas as pd
data = pd.read_csv("files/simpson/stab-cond2-data.csv")
data = data.transpose()
new_row = pd.DataFrame([0, 0, 0])
data.insert(0, -1, [0, 0, 0])
data.columns = [n for n in range(0, 36)]
data.iloc[:,0:16]
Tableau 1
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
Angle 0 2.000 4.000 6.000 8.000 10.000 12.000 14.000 16.000 18.000 20.000 22.000 24.000 26.000 28.000 30.000
GZ 0 0.494 1.003 1.518 2.028 2.523 2.993 3.428 3.820 4.161 4.442 4.658 4.816 4.928 5.004 5.054
GZ_Area 0 0.009 0.035 0.079 0.141 0.220 0.317 0.429 0.555 0.695 0.845 1.004 1.170 1.340 1.513 1.689

Les données de stabilité en condition 2 (accostage).

Voir le code.
import matplotlib.pyplot as plt

import matplotlib.pyplot as plt

# Configuration du style
plt.style.use('seaborn-v0_8-muted') 

# Création de la figure
plt.figure(figsize=(10, 6))

# Extraction des données par LIGNES
x = data.iloc[0]
y = data.iloc[1]

# 1. Tracé de la courbe complète
# La légende est mise à jour ici : label='Courbe GZ'
plt.plot(x, y, marker='o', linestyle='-', color='royalblue', linewidth=2, label='Courbe GZ')

# 2. Ajout de l'aire sous la courbe uniquement entre 0 et 30 degrés
# On crée un masque pour sélectionner les points où 0 <= x <= 30
mask = (x >= 0) & (x <= 30)
plt.fill_between(x[mask], y[mask], color='royalblue', alpha=0.2)

# Ajout du titre et des labels avec support LaTeX
plt.title("Courbe de stabilité du Gypsum centennial dans des conditions d'accostage", fontsize=14, pad=15)
plt.xlabel(r'$\theta$', fontsize=14)
plt.ylabel(r'$GZ(\theta)$', fontsize=14)

# Ajout d'une grille et de la légende
plt.grid(True, linestyle='--', alpha=0.7)
plt.legend()

# Ajustement des marges
plt.tight_layout()

# Affichage du graphique
plt.show()
Figure 2: La courbe de stabilité en condition 2 (accostage): on cherche l’aire représentée en bleu.

De 0 à 30 degreés, il y a 16 intervalles. L’idée est de trouver laquelle des règles de Simpson cadre avec ce nombre 16. On peut prendre la règle 3/8 car elle démarre à 4 et fonctionne par multiple de trois: \(3\cdot 4 + 4 = 16\). La séquence de poids est donc \([1, 3, 3, 2, 3, 3, 2, 3, 3, 2, 3, 3, 2, 3, 3, 1]\).

On peut ainsi calculer la somme complète:

Voir le code.
ex1 = data.iloc[:,0:16].copy()
poids = [1, 3, 3, 2, 3, 3, 2, 3, 3, 2, 3, 3, 2, 3, 3, 1]
seq = pd.DataFrame(poids).transpose()
seq.index = ["Poids"]
seq.head()
ex2 = pd.concat([ex1, seq])
ex2.loc["GZ x poids"] = ex2.loc["Poids"] * ex2.loc["GZ"]
ex2.head()
Tableau 2
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
Angle 0.0 2.000 4.000 6.000 8.000 10.000 12.000 14.000 16.000 18.000 20.000 22.000 24.000 26.000 28.000 30.000
GZ 0.0 0.494 1.003 1.518 2.028 2.523 2.993 3.428 3.820 4.161 4.442 4.658 4.816 4.928 5.004 5.054
GZ_Area 0.0 0.009 0.035 0.079 0.141 0.220 0.317 0.429 0.555 0.695 0.845 1.004 1.170 1.340 1.513 1.689
Poids 1.0 3.000 3.000 2.000 3.000 3.000 2.000 3.000 3.000 2.000 3.000 3.000 2.000 3.000 3.000 1.000
GZ x poids 0.0 1.482 3.009 3.036 6.084 7.569 5.986 10.284 11.460 8.322 13.326 13.974 9.632 14.784 15.012 5.054

Le calcul avec la règle 3/8.

La somme de la dernière ligne est de 129.014 m-deg (mètres degrés). En multipliant par \(\frac{3}{8}\cdot 2\), on obtient 96.76 m-deg.

Puisqu’on s’intéresse à l’aire sous la courbe mesurée en mètres-radians (m-rad), on doit multiplier ce résultat par \(\pi /180\) pour obtenir 1.6888 m-rad.

En somme, l’aire sous la courbe du bras de levier du Gypsum centennial qui est comprise entre 0° et 30° est de 1.6888 mètre-radian dans les conditions d’accostage. On notera que c’est exactement la valeur contenue dans la colonne de 30 degrés, à la ligne « GZ area ».

Exemple 2

Cette fois, on s’intéresse au Gypsum Centennial dans des conditions de plein ballastage (condition 11). On va calculer l’aire sous la courbe de 0° à 10°.

Le bras de levier GZ est reproduit à la Figure 3, au Tableau 3 puis représentée graphiquement à la Figure 4. Au besoin, les données au format csv sont ici.

Figure 3: Table GZ du Gypsum Centennial en condition #11 (plein ballast)
Voir le code.
import pandas as pd
data = pd.read_csv("files/simpson/stab-cond-11.csv")
data = data.transpose()
new_row = pd.DataFrame([0, 0, 0])
data.insert(0, -1, [0, 0, 0])
data.columns = [n for n in range(0, 36)]
data.iloc[:,0:16]
Tableau 3
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
Angle 0 2.000 4.000 6.000 8.000 10.000 12.000 14.000 16.000 18.000 20.000 22.000 24.000 26.000 28.000 30.000
GZ 0 0.233 0.467 0.704 0.946 1.193 1.448 1.712 1.984 2.264 2.554 2.851 3.150 3.443 3.723 3.982
GZ_Area 0 0.004 0.016 0.037 0.066 0.103 0.149 0.204 0.269 0.343 0.427 0.521 0.626 0.741 0.866 1.001

Les données de stabilité en condition 11 (plein ballast).

Voir le code.
import matplotlib.pyplot as plt

import matplotlib.pyplot as plt

# Configuration du style
plt.style.use('seaborn-v0_8-muted') 

# Création de la figure
plt.figure(figsize=(10, 6))

# Extraction des données par LIGNES
x = data.iloc[0]
y = data.iloc[1]

# 1. Tracé de la courbe complète
# La légende est mise à jour ici : label='Courbe GZ'
plt.plot(x, y, marker='o', linestyle='-', color='royalblue', linewidth=2, label='Courbe GZ')

# 2. Ajout de l'aire sous la courbe uniquement entre 0 et 30 degrés
# On crée un masque pour sélectionner les points où 0 <= x <= 20
mask = (x >= 0) & (x <= 20)
plt.fill_between(x[mask], y[mask], color='royalblue', alpha=0.2)

# Ajout du titre et des labels avec support LaTeX
plt.title("Courbe de stabilité du Gypsum centennial en plein ballast", fontsize=14, pad=15)
plt.xlabel(r'$\theta$', fontsize=14)
plt.ylabel(r'$GZ(\theta)$', fontsize=14)

# Ajout d'une grille et de la légende
plt.grid(True, linestyle='--', alpha=0.7)
plt.legend()

# Ajustement des marges
plt.tight_layout()

# Affichage du graphique
plt.show()
Figure 4: La courbe de stabilité en condition 11 (plein ballast): on cherche l’aire représentée en bleu.

Il y a 6 intervalles de 0° à 10°. On ne peut ni employer la règle 1/3 pour faire les calculs, (le plus proche est 5), ni employer la règle 3/8, car elle permet soit quatre, soit sept intervalles.

On peut cependant séparer l’intégrale en deux parties et travailler avec deux règles: \[\begin{align} \int_0^{10}GZ(\theta)d\theta &= \int_0^{8}GZ(\theta)d\theta + \int_8^{10}GZ(\theta)d\theta \end{align}\] La première intégrale est sur cinq points, ce qu’on peut faire avec la règle 1/3. La seconde intégrale ne comprend qu’un seul intervalle, ce qu’on peut faire avec la règle 5/8.

Première partie: 0° à 8°.

Tableau 4: Application de la règle 1/3 à la première intégrale.
\(\theta\) 0° 2° 4° 6° 8°
\(GZ(\theta)\) 0 0.233 0.467 0.704 0.946
\(w\) 1 4 2 4 1
\(wf(w)\) 0 0.9230 0.9340 2.8160 0.9460

La somme des valeurs est 5.6280. En multipliant par \(\frac{2}{3}\), on obtient l’approximation de l’intégrale, soit 3.7520 m-deg. Il faut alors multiplier par \(\pi/180\) pour avoir les unités en m-rad: 0.065485 m-rad. Cela correspond bien à la valeur de « GZ area » dans la table.

Deuxième partie: 8° à 10°.

Pour obtenir l’aire sous la courbe entre 8° et 10°, on applique la règle 5/8 aux valeurs dans la table. Les valeurs importantes sont à 10° (x5), 8° (x8) et 6° (x-1): \[\begin{align} \int_8^{10}GZ(\theta)d\theta\approx \frac{2}{12}\left[5\cdot 2.554+ 8 \cdot 2.264 - 1.984\right] = 4.8163 m-deg. \end{align}\]

Si on convertit en m-rad (\(\times \pi/180\)), on obtient 0.084060 m-rad.

La somme des deux parties nous permet d’obtenir l’intégrale totale, soit \(0.065485 + 0.084060 = 0.1495 m-rad\). C’est également très proche de la valeur « GZ Area » rapportée par le livret de stabilité (0.149).

Livret de stabilité du Atlantic Vision

Exemple 3

La Figure 5 montre le GZ corrigé (GZ-CORR) du Atlantic Vision dans des conditions de plein chargement. (Le GZ corrigé tient compte du fait que les véhicules peuvent se déplacer si la gîte du navire est trop grande.) Les données au format .csv sont ici et la Tableau 5 montre les données.

Figure 5: Table GZ du Atlantic Vision en condition LF6 (Full homogenous loaded).
Voir le code.
import pandas as pd
import matplotlib.pyplot as plt

data = pd.read_csv("files/simpson/stab-vision-lf6.csv", sep=";")
data.iloc[:,:]
Tableau 5
Angle GZ-CORR
0 0 0.000
1 5 0.006
2 10 0.012
3 12 0.014
4 15 0.017
5 20 0.021
6 30 0.027
7 40 0.033
8 50 0.041
9 60 0.050
10 70 0.056

La courbe de stabilité en condition LF6 (chargement complet).

Nous allons calculer l’aire sous la courbe entre 0 et 15°. La Figure 6 montre en bleu l’aire qu’on cherche à approximer.

Voir le code.
# Configuration du style
plt.style.use('seaborn-v0_8-muted') 

# Création de la figure
plt.figure(figsize=(10, 6))

# Extraction des données par LIGNES
x = data["Angle"]
y = data["GZ-CORR"]

# 1. Tracé de la courbe complète
# La légende est mise à jour ici : label='Courbe GZ'
plt.plot(x, y, marker='o', linestyle='-', color='royalblue', linewidth=2, label='Courbe GZ')

# 2. Ajout de l'aire sous la courbe uniquement entre 0 et 30 degrés
# On crée un masque pour sélectionner les points où 0 <= x <= 20
mask = (x >= 0) & (x <= 15)
plt.fill_between(x[mask], y[mask], color='royalblue', alpha=0.2)

# Ajout du titre et des labels avec support LaTeX
plt.title("Courbe de stabilité du Atlantic Vision (LF6)", fontsize=14, pad=15)
plt.xlabel(r'$\theta$', fontsize=14)
plt.ylabel(r'$GZ(\theta)$ (corrigé)', fontsize=14)

# Ajout d'une grille et de la légende
plt.grid(True, linestyle='--', alpha=0.7)
plt.legend()

# Ajustement des marges
plt.tight_layout()

# Affichage du graphique
plt.show()
Figure 6: La courbe de stabilité en condition LF6 (chargement complet).

Pour calculer l’aire sous la courbe, on doit faire le même travail qu’avec les autres courbe. En premier lieu, il faut trouver la règle qui cadre avec le nombre de points réguliers dans cet intervalle. Ici, il faut porter attention au fait qu’on ne doit pas garder la donnée à 12°, car les règles de Simpson fonctionnent seulement pour des intervalles fixes. Conséquemment, on a 4 points, ce qui cadre parfaitement avec la règle 3/8.

Les calculs sont illustrés dans le Tableau 6 ci-dessous.

Voir le calcul.
import pandas as pd
import matplotlib.pyplot as plt

data = pd.read_csv("files/simpson/stab-vision-lf6.csv", sep=";")
data["poids"] = [1, 3, 3, 0, 1, 0, 0, 0, 0, 0, 0]
data["poids x GZ"] = data["poids"] * data["GZ-CORR"]
data.iloc[:,:]
Tableau 6
Angle GZ-CORR poids poids x GZ
0 0 0.000 1 0.000
1 5 0.006 3 0.018
2 10 0.012 3 0.036
3 12 0.014 0 0.000
4 15 0.017 1 0.017
5 20 0.021 0 0.000
6 30 0.027 0 0.000
7 40 0.033 0 0.000
8 50 0.041 0 0.000
9 60 0.050 0 0.000
10 70 0.056 0 0.000

La courbe de stabilité en condition LF6 (chargement complet).

La somme des valeurs pondérées est 0.0710. Il faut multiplier par \(5\frac{3}{8}\frac{\pi}{180}\) pour obtenir la valeur de l’intégrale en m-rad, soit 0.00155 m-rad.

Exemple 4

Calculons l’aire sous la courbe du Atlantic Vision dans les mêmes conditions (plein chargement), mais cette fois pour le cumul de 0° à 40°. On peut choisir 5 intervalles par bon de 10° et directement appliquer la règle 1/3. Les informations sont résumées au tableau Tableau 7.

Voir le calcul.
import pandas as pd
import matplotlib.pyplot as plt

data = pd.read_csv("files/simpson/stab-vision-lf6.csv", sep=";")
data["poids"] = [1, 0, 4, 0, 0, 2, 4, 1, 0, 0, 0]
data["poids x GZ"] = data["poids"] * data["GZ-CORR"]
data.iloc[:,:]
Tableau 7
Angle GZ-CORR poids poids x GZ
0 0 0.000 1 0.000
1 5 0.006 0 0.000
2 10 0.012 4 0.048
3 12 0.014 0 0.000
4 15 0.017 0 0.000
5 20 0.021 2 0.042
6 30 0.027 4 0.108
7 40 0.033 1 0.033
8 50 0.041 0 0.000
9 60 0.050 0 0.000
10 70 0.056 0 0.000

La courbe de stabilité en condition LF6 (chargement complet).

Avec les calculs usuels, on obtient une aire sous la courbe de 0.01343 m-rad.

Conclusion

Les règles de Simpson sont simples et particulièrement adaptées aux intervalles réguliers. Elles sont ainsi faciles d’usage pour les livrets de stabilité. Par « simples », il faut comprendre qu’on peut facilement les mémoriser et facilement les calculer à la main.

À l’ère du numérique, on peut cependant les appliquer les règles de Simpson à l’aide d’outils informatiques tel qu’Excel. Par exemple, le code Python ci-dessous reprend le calcul du premier exemple.

import pandas as pd
import scipy as sp
import math
data = pd.read_csv("files/simpson/stab-cond2-data.csv")
data = data.transpose()
new_row = pd.DataFrame([0, 0, 0])
data.insert(0, -1, [0, 0, 0])
data.columns = [n for n in range(0, 36)]
data.head()
x = data.iloc[0, 0:16].tolist()
y = data.iloc[1, 0:16].tolist()
value = sp.integrate.simpson(y, x)*math.pi/180
print(value)
1.688780584229713

On retrouve la valeur tabulée dans l’exemple.