Simulateur X-Dyn

Sirehna

1 Description

Le présent programme est un simulateur de comportement mécanique de corps solides indéformables dans un environnement fluide. Son objet principal est la résolution des équations de mouvements du ou des corps considérés, dans le domaine temporel. Ces équations de mouvement sont construites sur la base d’efforts extérieurs calculés par des modèles spécifiques inclus dans le logiciel, ou pouvant y être ajoutés. Chaque modèle est associé à un jeu de données spécifique.

Sur le principe, le simulateur permet de traiter n’importe quel problème de mouvement de corps solide. Les premiers modèles d’efforts implémentés et fournis concernent essentiellement le comportement de navires sur houle.

Concernant le mode de fonctionnement du logiciel, il s’agit d’un outil en ligne de commande, c’est-à-dire qu’on le lance depuis un terminal (ou une invite de commande MS DOS).

Le simulateur a été construit pour permettre une utilisation modulaire en ligne de commande. Pour ce faire, les différents domaines à configurer sont séparés : la description du problème physique est faite dans un ou plusieurs fichiers d’entrée et la description de la simulation (pas de temps, solveur…) est faite en ligne de commande. De cette manière, on peut facilement lancer des simulations du même problème avec des solveurs différents et sur des durées différentes, sans toucher au(x) fichier(s) de configuration du problème.

Le fichier de description du problème peut être séparé en autant de fichiers que l’on veut, ce qui permet par exemple de versionner la configuration de l’environnement physique séparément de celle du ou des solides.

En sortie, le simulateur génère un fichier de résultat au format CSV contenant tous les états du ou des solides. Il peut également générer un fichier YAML contenant des hauteurs de houle sur un maillage. La figure suivante résume les entrées et sorties du simulateur :

Parallèlement à la présente documentation utilisateur, il existe également une documentation d’implémentation décrivant l’architecture logicielle et détaillant les API pour faciliter la maintenance du code (correctifs et ajouts de fonctionnalités).

2 Ligne de commande

2.1 Liste des arguments

xdyn <yaml file> [-hd] [-y ARG] [-s ARG] [dt ARG] [--tstart ARG]
[--tend ARG] [-o ARG] [-w ARG]
Options:
  -h [ --help ]              Show this help message
  -y [ --yml ] arg           Name(s) of the YAML file(s)
  -s [ --solver ] arg (=rk4) Name of the solver: euler, rk4, rkck for
Euler,
                             Runge-Kutta 4 & Runge-Kutta-Cash-Karp
                             respectively.
  --dt arg                   Initial time step (or value of the fixed
time step
                             for fixed step solvers)
  --tstart arg (=0)          Date corresponding to the beginning of
the
                             simulation (in seconds)
  --tend arg                 Last time step
  -o [ --output ] arg        Name of the output file where all
computed data
                             will be exported.
                             Possible values/extensions are csv, tsv,
json,
                             hdf5, h5, ws
  -w [ --waves ] arg         Name of the output file where the wave
heights
                             will be stored ('output' section of the
YAML
                             file). In case output is made to a HDF5
file or
                             web sockets, this option appends the wave
height
                             to the main output
  -d [ --debug ]             Used by the application's support team to
help
                             error diagnosis. Allows us to pinpoint
the exact
                             location in code where the error occurred
(do not
                             catch exceptions), eg. for use in a
debugger.

2.2 Exemples

Les exemples suivants peuvent être lancés à partir du répertoire demos:

2.2.1 Simulation avec un solveur Runge-Kutta d’ordre 4 en commençant à t=0

./xdyn tutorial_01_falling_ball.yml --dt 0.1 --tend 1

ou si l’on utilise une invite de commande MS-DOS :

xdyn tutorial_01_falling_ball.yml --dt 0.1 --tend 1

En ajoutant l’option -o csv, les sorties se font sur la sortie standard (le terminal). Ceci permet de chaîner les traitements (pipe UNIX), par exemple :

./xdyn tutorial_01_falling_ball.yml --dt 0.1 --tend 1 -o csv| python plot.py test 0 3

La commande précédente lance la simulation et génère un tracé (format SVG) à l’aide du script python de post-traitement livré avec le simulateur. Des scripts de post-traitement sont livrés avec l’installation du simulateur, pour Matlab, Python.

2.2.2 Simulation avec un solveur Euler en commençant à t=1

./xdyn tutorial_01_falling_ball.yml -s euler --dt 0.1 --tstart 1 --tend 1.2

3 Documentations des données d’entrées du simulateur

Les données d’entrées du simulateur se basent sur un format de fichiers YAML qui fonctionne par clef-valeur.

Ce format présente l’avantage d’être facilement lisible et éditable. Des parsers YAML existent pour de nombreux langages de programmation.

3.1 Vue d’ensemble

3.1.1 Liste des sections

Le fichier YAML comprend quatre sections de haut niveau :

3.1.2 Remarques sur les unités

On retrouve fréquemment dans le fichier YAML des lignes du type :

clef: {value: 65456, unit: km}

Les unités ne sont pas vérifiées par le système : le parser se contente de convertir toutes les entrées en unité du système international avant simulation, sans préjuger de l’homogénéité. Ce décodage est fait en convertissant l’unité en un facteur multiplicatif (en utilisant la liste des unités de l’utilitaire UNIX units) et en multipliant la valeur originale par ce facteur multiplicatif. Par exemple:

masse: {value: 10, unit: lb}

sera vu par xdyn comme:

masse = 4.5359237;

L’exemple précédent :

clef: {value: 65456, unit: km}

aurait tout aussi bien pu être écrit :

clef: {value: 65456, unit: kW}

et on aurait obtenu exactement la même valeur numérique, bien que la grandeur physique ne soit pas la même : on suppose donc que l’utilisateur renseigne des données de façon homogène. En interne, tous les calculs sont faits en unité du système international.

3.2 Sorties

La spécification des sorties se fait au moyen de la section output, à la racine du fichier YAML, dont voici un exemple :

output:
   - format: csv
     filename: test.csv
     data: [t, x(ball), 'Fx(gravity,ball)']

4 Interface MatLab

xdyn peut être appelé depuis le logiciel MatLab. Cela présente l’avantage de disposer dans la foulée d’un environnement graphique pour afficher les résultats de simulation.

Voici les fonctions de base pour travailler avec xdyn.

Enfin, le fichier xdyn_demos.m permet de lancer les différents tutoriels.

Il est également possible d’utiliser l’environnement MatLab pour analyser des simulations déjà réalisées. Par exemple, le script xdyn_demos.m va lire le fichier tutorial_01_falling_ball.h5 qui aura préalablement été généré à partir de la commande :

./xdyn tutorial_01_falling_ball.yml --dt 0.1 --tend 1 -o tutorial_01_falling_ball.h5

5 Interface Docker et génération automatique de rapports

xdyn peut être utilisé sous la forme d’un conteneur Docker ce qui permet de l’exécuter sur n’importe quelle plateforme.

En outre, c’est actuellement le seul moyen d’utiliser le module de génération automatique de rapport décrit ci-après.

Pour utiliser l’image xdyn, il faut d’abord installer Docker puis récupérer l’image sirehna/xdyn en exécutant :

docker pull sirehna/xdyn

Pour utiliser l’image xdyn avec son environnement de post-traitement, on récupérera l’image sirehna/xweave en exécutant :

docker pull sirehna/xweave

5.1 Lancement d’xdyn via l’image docker

Une fois l’image chargée par la commande précédente, on peut lancer :

docker run -it --rm -v $(pwd):/work -w /work sirehna/xdyn

Si l’on souhaite lancer une simulation, on ajoute les arguments d’xdyn à la suite :

docker run -it --rm -v $(pwd):/work -w /work sirehna/xdyn tutorial_01_falling_ball.yml --dt 0.1 --tend 1 -o tsv

5.2 Génération automatique de rapports (X-Weave)

Cette fonctionnalité n’est accessible qu’en utilisant le conteneur Docker sirehna/xweave.

5.2.1 Principe de fonctionnement

On utilise Pweave pour inclure des balises Python dans du texte au format Markdown). Par exemple, la présente documentation est générée en utilisant ce système, y compris les tutoriels et leurs courbes de résultats.

Grâce à ce générateur (appelé “x-weave”), on peut obtenir des rapports dans le format que l’on souhaite (DOCX, PDF, HTML…). Ces rapports peuvent par exemple lancer des simulations xdyn et inclure des courbes à partir de ces résultats.

L’intérêt est que l’on peut gérer le code de ses rapports en configuration (puisque c’est du texte), regarder facilement les différences entre deux versions sans utiliser d’outil propriétaire et regénérer à la demande une nouvelle version du rapport lorsque l’on change les entrées.

X-Weave n’est ni plus ni moins que Pweave dans un containeur Docker avec xdyn pré-installé, ce qui permet de lancer xdyn depuis Pweave.

5.2.2 Ligne de commande

La ligne de commande à utiliser est :

docker run --rm -it -v $(pwd):/work -w /work -u $(id -u):$(id -g) --entrypoint /usr/bin/xdyn-weave sirehna/xweave -f markdown concatenated_doc.pmd -o concatenated_doc.md

On obtient alors un fichier Markdown et (le cas échéant) des images. On peut ensuite utiliser Pandoc pour convertir le Markdown au format de son choix en utilisant le Pandoc installé dans le containeur X-Weave :

docker run --rm -it -v $(shell pwd):/work -w /work -u $(shell id -u):$(shell id -g) --entrypoint /usr/bin/pandoc xweave concatenated_doc_pandoc.md -o doc.html

5.2.3 Commandes Python supplémentaires

Par rapport à Pweave “classique”, on a inclus quelques fonctions Python pour simplifier le travail avec xdyn.

5.2.3.1 Chargement du fichier YAML : load_yaml

L’insertion de la section suivante dans un document X-weave ne génèrera pas de sortie. Par contre, dans les sections python ultérieures, on pourra utiliser les données ainsi chargées.

```python
yaml_data = load_yaml('tutorial_06_1D_propulsion.yml')
```

5.2.3.2 Affichage de l’intégrabilité du YAML : print_yaml

Suite au chargement du YAML, on peut vouloir l’afficher dans le document. Pour cela, on utilise une section python de la forme :

```python
yaml_data = load_yaml('tutorial_06_1D_propulsion.yml')

# Pour afficher l'intégralité du YAML avec de la coloration syntaxique
print_yaml(yaml_data)

# Pour n'afficher qu'une sous-section du YAML
print_yaml(yaml_data, 'bodies/0/controlled forces')
```

5.2.3.3 Exécution d’une simulation

La commande suivante ne produira pas de contenu visible dans le document. En revanche, il sera possible de récupérer et afficher les données ainsi générées.

```python
execCommand('xdyn tutorial_01_falling_ball.yml --dt 0.01 --tend 1 -o out.csv')
```

5.2.3.4 Tracé des résultats

```python
# Récupération des données générées
data = csv('out.csv')

# Définition de la donnée à tracer
plot = prepare_plot_data(data, x = 't', y = 'z(ball)', name='Résultat')

# Définition du type de graph
g = cartesian_graph([plot], x='t (s)', y='Élévation (m)')

# Tracé de la planche
create_layout(g, title='Élévation au cours du temps')
```

5.3 Utilisation de xdyn en serveur websocket

5.3.1 Description

Il est possible de lancer xdyn en tant que serveur, afin de l’intégrer à un autre environnement de simulation. L’utilisation d’un serveur plutôt qu’une MEX-fonction (MATLAB executable - fonction) ou un FMU (Functional Mock-up Unit) permet d’exécuter xdyn sur une autre machine et de l’interroger par plusieurs clients.

Il s’agit d’une utilisation en “model exchange” (au sens de la spécification “Functional Mockup Interface”), par opposition à “xdyn for Co-simulation”. La différence se situe dans l’utilisation du solveur : dans le cas de la co-simulation, on utilise le solveur interne de xdyn (le serveur renvoie les états intégrés au pas suivant X(t+dt)X(t+dt)). Dans le cas “model exchange”, le serveur renvoie la dérivée des états dXdt\frac{dX}{dt}.

5.3.2 Justification technique

L’utilisation des websockets permet des temps de réponse plus courts (puisque c’est un protocole assez léger, comparé au HTTP par exemple). Dans l’implémentation actuelle, les messages envoyés sont en JSON, pour offrir un bon compromis entre la verbosité (moins que du XML mais plus qu’un format binaire) et une utilisation plus aisée qu’un format type Protobuf ou Thrift, quitte à sacrifier un peu de performance (taille des messages, temps d’encodage/décodage).

5.3.3 Lancement du serveur “Model Exchange”

Le serveur est lancé grâce à l’exécutable xdyn-for-me (xdyn for Model Exchange) avec un ou plusieurs fichiers YAML en paramètre : une fois lancé, ce serveur ne simulera donc qu’une seule configuration de l’environnement et du navire. Concrètement, on lance le serveur comme suit :

./xdyn-for-me --port 9002 tutorial_01_falling_ball.yml

--port sert à définir le port sur lequel écoute le serveur websocket.

La liste complète des options avec leur description est obtenue en lançant l’exécutable avec le flag -h.

Ensuite, on peut se connecter à l’adresse du serveur pour l’interroger.

5.3.4 Lancement du serveur “Co-Simulation”

Le serveur est lancé grâce à l’exécutable xdyn-for-cs (xdyn for Co-Simulation) avec un ou plusieurs fichiers YAML en paramètre, un pas de temps et un solveur : une fois lancé, ce serveur ne simulera donc qu’une seule configuration de l’environnement et du navire, en utilisant un solveur et un pas de temps. Concrètement, on lance le serveur comme suit :

./xdyn-for-cs --port 9002 tutorial_01_falling_ball.yml --dt 0.1

--port sert à définir le port sur lequel écoute le serveur websocket.

La liste complète des options avec leur description est obtenue en lançant l’exécutable avec le flag -h.

Ensuite, on peut se connecter à l’adresse du serveur pour l’interroger.

5.3.5 Utilisation avec Chrome

Le navigateur Chrome dispose d’une extension websocket Simple Websocket Client qui permet de faire quelques tests de bon fonctionnement.

5.3.6 Utilisation avec Matlab

On initie une connexion websocket via MATLAB en utilisant par exemple MatlabWebSocket. Il faut également pouvoir encoder et décoder du JSON en MATLAB, par exemple en utilisant les fonctions MATLAB jsondecode et jsonencode.

5.3.7 Description des entrées/sorties pour une utilisation en “Model Exchange” (x -> dx/dt)

Dans ce mode, xdyn calcule uniquement la dérivée des 13 états navire mais n’effectue pas l’intégration numérique, ce qui permet d’utiliser un solveur externe, par exemple Matlab ou Simulink.

Entrées Type Détail
states Liste d’éléments de type « État » Historique des états jusqu’au temps courant t. Si les modèles utilisés ne nécessitent pas d’historique, cette liste peut n’avoir qu’un seul élément.
commands Liste de clefs-valeurs (dictionnaire) État des actionneurs au temps t

Chaque élément de type « État » est composé des éléments suivants:

État Type Détail
t Flottant Temps courant de la simulation
x Flottant Projection sur l’axe X du repère NED du vecteur entre l’origine du repère NED et l’origine du repère body
y Flottant Projection sur l’axe Y du repère NED du vecteur entre l’origine du repère NED et l’origine du repère BODY
z Flottant Projection sur l’axe Z du repère NED du vecteur entre l’origine du repère NED et l’origine du repère BODY
u Flottant Projection sur l’axe X du repère NED du vecteur vitesse du navire par rapport au sol (BODY/NED).
v Flottant Projection sur l’axe Y du repère NED du vecteur vitesse du navire par rapport au sol (BODY/NED).
w Flottant Projection sur l’axe Z du repère NED du vecteur vitesse du navire par rapport au sol (BODY/NED).
p Flottant Projection sur l’axe X du repère NED du vecteur vitesse de rotation du navire par rapport au sol (BODY/NED).
q Flottant Projection sur l’axe Y du repère NED du vecteur vitesse de rotation du navire par rapport au sol (BODY/NED).
r Flottant Projection sur l’axe Z du repère NED du vecteur vitesse de rotation du navire par rapport au sol (BODY/NED).
qr Flottant Partie réelle du quaternion définissant la rotation du navire par rapport au sol (BODY/NED)
qi Flottant Première partie imaginaire du quaternion définissant la rotation du navire par rapport au sol (BODY/NED)
qj Flottant Seconde partie imaginaire du quaternion définissant la rotation du navire par rapport au sol (BODY/NED)
qk Flottant Troisième partie imaginaire du quaternion définissant la rotation du navire par rapport au sol (BODY/NED)

Exemple d’entrée:

{
  "states": [
    {
      "t": 0,
      "x": 0,
      "y": 8,
      "z": 12,
      "u": 1,
      "v": 0,
      "w": 0,
      "p": 0,
      "q": 1,
      "r": 0,
      "qr": 1,
      "qi": 0,
      "qj": 0,
      "qk": 0
    },
    {
      "t": 0.1,
      "x": 0.1,
      "y": -0.156,
      "z": 10,
      "u": 0,
      "v": 0,
      "w": 0,
      "p": 0,
      "q": 0,
      "r": 0,
      "qr": 0,
      "qi": 0,
      "qj": 0,
      "qk": 0,
    }
  ],
  "commands": {
    "beta": 0.1
  }
}

La sortie du “Model Exchange” correspond à la dérivée des états à savoir dx/dt, dy/dt, dz/dt, du/dt, dv/dt, dw/dt, dp/dt, dq/dt, dr/dt, dqr/dt, dqi/dt, dqj/dt, dqk/dt.

Sorties Type Détail
dx/dt Flottant Dérivée par rapport au temps de la projection sur l’axe X du repère NED du vecteur entre l’origine du repère NED et l’origine du repère BODY
dy/dt Flottant Dérivée par rapport au temps de la projection sur l’axe Y du repère NED du vecteur entre l’origine du repère NED et l’origine du repère BODY
dz/dt Flottant Dérivée par rapport au temps de la projection sur l’axe Z du repère NED du vecteur entre l’origine du repère NED et l’origine du repère BODY
du/dt Flottant Dérivée par rapport au temps de la projection sur l’axe X du repère NED du vecteur vitesse du navire par rapport au sol (BODY/NED).
dv/dt Flottant Dérivée par rapport au temps de la projection sur l’axe Y du repère NED du vecteur vitesse du navire par rapport au sol (BODY/NED).
dw/dt Flottant Dérivée par rapport au temps de la projection sur l’axe Z du repère NED du vecteur vitesse du navire par rapport au sol (BODY/NED).
dp/dt Flottant Dérivée par rapport au temps de la projection sur l’axe X du repère NED du vecteur vitesse de rotation du navire par rapport au sol (BODY/NED).
dq/dt Flottant Dérivée par rapport au temps de la projection sur l’axe Y du repère NED du vecteur vitesse de rotation du navire par rapport au sol (BODY/NED).
dr/dt Flottant Dérivée par rapport au temps de la projection sur l’axe Z du repère NED du vecteur vitesse de rotation du navire par rapport au sol (BODY/NED).
dqr/dt Flottant Dérivée par rapport au temps de la partie réelle du quaternion définissant la rotation du navire par rapport au sol (BODY/NED)
dqi/dt Flottant Dérivée par rapport au temps de la première partie imaginaire du quaternion définissant la rotation du navire par rapport au sol (BODY/NED)
dqj/dt Flottant Dérivée par rapport au temps de la seconde partie imaginaire du quaternion définissant la rotation du navire par rapport au sol (BODY/NED)
dqk/dt Flottant Dérivée par rapport au temps de la troisième partie imaginaire du quaternion définissant la rotation du navire par rapport au sol (BODY/NED)

Exemple de sortie:

{
  "dx_dt": 0.1,
  "dy_dt": -0.156,
  "dz_dt": 10,
  "du_dt": 0,
  "dv_dt": 0,
  "dw_dt": 0,
  "dp_dt": 0,
  "dq_dt": 0,
  "dr_dt": 0,
  "dqr_dt": 0,
  "dqi_dt": 0,
  "dqj_dt": 0,
  "dqk_dt": 0
}

La représentation textuelle de ces nombres flottants est faite de façon unique (et non exacte) : cela signifie que si les flottants sont différents (binairement), leur représentation textuelle sera différente. Cela signifie également que si xdyn lit la représentation textuelle et la traduit en binaire, on retrouvera bien la valeur binaire initiale. En d’autres termes, la fonction flottant -> texte est injective. Cela n’implique pas qu’elle soit bijective, puisque si l’on part d’une représentation textuelle, que l’on convertit en binaire pour reconvertir ensuite en texte on ne retrouvera pas nécessairement le texte initial.

5.3.8 Description des entrées/sorties pour une utilisation en “Co-Simulation” (x(t) -> [x(t), …,x(t+Dt)])

Entrées Type Détail
Dt Flottant strictement positif Horizon de simulation (en secondes). La simulation s’effectue de t0 à t0 + Dt, où t0 est la date du dernier élément de la
liste states, par pas de dt, où dt est spécifié sur la ligne de commande. L’état t0 est donc présent à
la fois dans les entrées et dans les sorties, avec la même valeur.
states Liste d’éléments de type « État » Historique des états jusqu’au temps courant t. Si les modèles utilisés ne nécessitent pas d’historique, cette liste peut n’avoir qu’un seul élément.
commands Liste de clefs-valeurs (dictionnaire) État des actionneurs au temps t. Commande au sens de xdyn (modèle d’effort commandé) au temps t0 (début de la
simulation, i.e. date du dernier élément de la liste states). Le plus souvent, correspond à l’état interne
d’un modèle d’actionneur (safran ou hélice par exemple) dans xdyn et dont on souhaite simuler la dynamique
en dehors d’xdyn.

Chaque élément de type « État » est composé des éléments suivants:

État Type Détail
t Flottant Date de l’état
x Flottant Projection sur l’axe X du repère NED du vecteur entre l’origine du repère NED et l’origine du repère BODY
y Flottant Projection sur l’axe Y du repère NED du vecteur entre l’origine du repère NED et l’origine du repère BODY
z Flottant Projection sur l’axe Z du repère NED du vecteur entre l’origine du repère NED et l’origine du repère BODY
u Flottant Projection sur l’axe X du repère NED du vecteur vitesse du navire par rapport au sol (BODY/NED).
v Flottant Projection sur l’axe Y du repère NED du vecteur vitesse du navire par rapport au sol (BODY/NED).
w Flottant Projection sur l’axe Z du repère NED du vecteur vitesse du navire par rapport au sol (BODY/NED).
p Flottant Projection sur l’axe X du repère NED du vecteur vitesse de rotation du navire par rapport au sol (BODY/NED).
q Flottant Projection sur l’axe Y du repère NED du vecteur vitesse de rotation du navire par rapport au sol (BODY/NED).
r Flottant Projection sur l’axe Z du repère NED du vecteur vitesse de rotation du navire par rapport au sol (BODY/NED).
qr Flottant Partie réelle du quaternion définissant la rotation du navire par rapport au sol (BODY/NED)
qi Flottant Première partie imaginaire du quaternion définissant la rotation du navire par rapport au sol (BODY/NED)
qj Flottant Seconde partie imaginaire du quaternion définissant la rotation du navire par rapport au sol (BODY/NED)
qk Flottant Troisième partie imaginaire du quaternion définissant la rotation du navire par rapport au sol (BODY/NED)

Exemple d’entrée:

{
  "Dt": 10,
  "states": [
    {
      "t": 0,
      "x": 0,
      "y": 8,
      "z": 12,
      "u": 1,
      "v": 0,
      "w": 0,
      "p": 0,
      "q": 1,
      "r": 0,
      "qr": 1,
      "qi": 0,
      "qj": 0,
      "qk": 0
    },
    {
      "t": 0,
      "x": 0.1,
      "y": -0.156,
      "z": 10,
      "u": 0,
      "v": 0,
      "w": 0,
      "p": 0,
      "q": 0,
      "r": 0,
      "qr": 0,
      "qi": 0,
      "qj": 0,
      "qk": 0,
    }
  ],
  "commands": {
    "beta": 0.1
  }
}

La sortie est une liste d’éléments de type « État augmenté » contenant l’historique des états de t0 à t0 + Dt par pas de dt.

État Type Détail
t Flottant Date de l’état augmenté
x Flottant Projection sur l’axe X du repère NED du vecteur entre l’origine du repère NED et l’origine du repère BODY
y Flottant Projection sur l’axe Y du repère NED du vecteur entre l’origine du repère NED et l’origine du repère BODY
z Flottant Projection sur l’axe Z du repère NED du vecteur entre l’origine du repère NED et l’origine du repère BODY
u Flottant Projection sur l’axe X du repère NED du vecteur vitesse du navire par rapport au sol (BODY/NED).
v Flottant Projection sur l’axe Y du repère NED du vecteur vitesse du navire par rapport au sol (BODY/NED).
w Flottant Projection sur l’axe Z du repère NED du vecteur vitesse du navire par rapport au sol (BODY/NED).
p Flottant Projection sur l’axe X du repère NED du vecteur vitesse de rotation du navire par rapport au sol (BODY/NED).
q Flottant Projection sur l’axe Y du repère NED du vecteur vitesse de rotation du navire par rapport au sol (BODY/NED).
r Flottant Projection sur l’axe Z du repère NED du vecteur vitesse de rotation du navire par rapport au sol (BODY/NED).
qr Flottant Partie réelle du quaternion définissant la rotation du navire par rapport au sol (BODY/NED)
qi Flottant Première partie imaginaire du quaternion définissant la rotation du navire par rapport au sol (BODY/NED)
qj Flottant Seconde partie imaginaire du quaternion définissant la rotation du navire par rapport au sol (BODY/NED)
qk Flottant Troisième partie imaginaire du quaternion définissant la rotation du navire par rapport au sol (BODY/NED)
phi Flottant Angle d’Euler phi. Lire note ci-après
theta Flottant Angle d’Euler phi. Lire note ci-après
psi Flottant Angle d’Euler phi. Lire note ci-après

La signification exacte des angles d’Euler dépend de la convention d’angle choisie dans le fichier YAML d’entrée de xdyn (voir la section correspondante dans la documentation). Cette sortie est fournie pour faciliter le travail du client du serveur, mais n’est pas utilisée en interne par xdyn.

Exemple de sortie:

[
  {
    "t": 10,
    "x": 0,
    "y": 8,
    "z": 12,
    "u": 1,
    "v": 0,
    "w": 0,
    "p": 0,
    "q": 1,
    "r": 0,
    "qr": 1,
    "qi": 0,
    "qj": 0,
    "qk": 0,
    "phi": 0,
    "theta": 0,
    "psi": 0
  },
  {
    "t": 10.1,
    "x": 0.0999968,
    "y": 8,
    "z": 12.0491,
    "u": 0.897068,
    "v": 0,
    "w": 1.07593,
    "p": 0,
    "q": 1,
    "r": 0,
    "qr": 0.99875,
    "qi": 0,
    "qj": 0.0499792,
    "qk": 0,
    "phi": 0,
    "theta": 0.1,
    "psi": 0
  }
]

Comme pour le “model exchange”, la représentation textuelle de ces nombres flottants est faite de façon unique (et non exacte) : cela signifie que si les flottants sont différents (binairement), leur représentation textuelle sera différente. Cela signifie également que si xdyn lit la représentation textuelle et la traduit en binaire, on retrouvera bien la valeur binaire initiale. En d’autres termes, la fonction flottant -> texte est injective. Cela n’implique pas qu’elle soit bijective, puisque si l’on part d’une représentation textuelle, que l’on convertit en binaire pour reconvertir ensuite en texte on ne retrouvera pas nécessairement le texte initial.

6 Repères et conventions

6.1 Repères

Afin de connaître et décrire l’attitude d’un ou plusieurs corps dans l’espace, il est nécessaire de les placer par rapport à un repère de référence.

6.1.1 Repère de référence (NED)

Le repère NED (North-East-Down) est utilisé comme repère de référence, avec un point de référence OO et une base pointant les directions Nord-Est-Bas. Il sert à exprimer les déplacements des corps de la simulation.

6.1.2 Repère navire (mobile ou “body” ou “repère de résolution”)

Le repère navire correspond au repère attaché au navire lors de la simulation. Le point de référence de ce repère correspond généralement au centre de gravité du navire. Les axes du repère navire sont les suivants:

On résout les équations du mouvement (principe fondamental de la dynamique) à l’origine de ce repère, c’est-à-dire que tous les torseurs d’effort sont déplacés au point (0,0,0) du repère “body”. De même, les matrices d’inertie et de masse ajoutée sont déplacées au point de résolution.

6.1.3 Repère NED local

Lors des exports de champs de vagues, ni le repère NED ni le repère navire ne sont parfaitement adaptés : en effet, si le maillage sur lequel on calcule la houle est lié à NED, le navire finira par sortir de cette zone lorsqu’il se déplacera. Si l’on calcule les hauteurs de vague dans le repère navire, l’aire de la grille vue dans le repère NED va varier en fonction de l’attitude du navire et, à la limite, pour un navire vertical (θ=π/2\theta=\pi/2 par exemple), la projection de la grille est un segment.

On définit donc un NED “local”, c’est-à-dire un repère centré au même point que le repère navire mais simplement translaté par rapport à NED :

Ce repère est nommé “NED(body)”. Ainsi, si le navire s’appelle “nav1”, le repère NED local sera “NED(nav1)”.

6.1.4 Attitude navire

L’attitude d’un corps permet de connaître son orientation par rapport à un repère. La position est donnée par le triplet (X,Y,Z)\left(X,Y,Z\right) et l’orientation par un triplet d’angles (ϕ,θ,ψ)\left(\phi,\theta,\psi\right). L’interprétation de ce triplet en termes de rotations autour des axes xx, yy, zz dépend de la convention de rotation choisie. L’orientation peut également être exprimée de manière différente notamment avec des quaternions (c’est d’ailleurs ainsi qu’elle est exprimée dans le code d’xdyn).

6.2 Conventions d’orientations

Cette section présente les notations utilisées pour définir l’orientation d’un élément dans l’espace à partir d’un triplet d’angles (ϕ,θ,ψ)(\phi,\theta,\psi).

6.2.1 Définition d’une orientation

Pour définir la composition de rotations donnant l’orientation d’un élément dans l’espace à partir d’un triplet d’angles (ϕ,θ,ψ)\left(\phi,\theta,\psi\right), plusieurs éléments doivent être définis:

6.2.2 Énumération des conventions possibles

Si on choisit une convention d’angles, alors chaque angle du triplet définit respectivement une rotation autour d’un axe XX, YY ou ZZ. Les axes ne peuvent être répétés. Il est possible de définir 6 conventions d’angles, qui correspondent à la permutation des trois axes: XYZXYZ ,XZYXZY ,YXZYXZ ,YZXYZX ,ZXYZXY ,ZYXZYX. Par exemple la rotation RYZXR_{YZX} appliquée au triplet (ϕ,θ,ψ)\left(\phi,\theta,\psi\right) s’interprétera comme une rotation de RY(θ)R_{Y}\left(\theta\right), suivie de la rotation RZ(ψ)R_{Z}\left(\psi\right), et terminée par la rotation RX(ϕ)R_{X}\left(\phi\right).

Si on choisit une convention d’axes, alors on modifie l’ordre des axes sur lesquels appliquer successivement les rotations. Des répétitions des axes sont alors possibles, si elles ne se suivent pas. Par exemple, XYXXYX sera valide, mais pas XXYXXY. Par exemple, une convention ZXY définit une composition de rotations. Il est possible de définir 12 conventions d’axes: XYXXYX, XYZXYZ, XZXXZX, XZYXZY, YXYYXY, YXZYXZ, YZXYZX, YZYYZY, ZXYZXY, ZXZZXZ, ZYXZYX, ZYZZYZ. Par exemple la rotation RYZXR_{YZX} appliquée au triplet (ϕ,θ,ψ)\left(\phi,\theta,\psi\right) s’interprétera comme une rotation de RY(ϕ)R_{Y}\left(\phi\right), suivie de la rotation RZ(θ)R_{Z}\left(\theta\right), et terminée par la rotation RX(ψ)R_{X}\left(\psi\right).

Avec ces conventions d’angles et d’axes, il existe déjà 18 combinaisons. Ce nombre est doublé du fait que la composition de rotations peut être interne (intrinsic) ou externe (extrinsic). Si les rotations sont composées par rapport au repère fixe, on parle de composition externe. Si les rotations sont composées par rapport aux repères nouvellement créés, on parle de composition interne. C’est cette dernière qui est utilisée dans la majorité des cas. Au total, ce sont ainsi 36 conventions qu’il est possible de définir.

6.2.3 Synthèse des différentes conventions

Les deux tableaux suivants présentent les 36 conventions possibles :

id Ordre Convention Composition Matrice de rotation Remarques
1 angle x y z Extrinsic RZ(ψ).RY(θ).RX(ϕ)R_Z(\psi).R_Y(\theta).R_X(\phi)
2 angle x z y Extrinsic RY(θ).RZ(ψ).RX(ϕ)R_Y(\theta).R_Z(\psi).R_X(\phi)
3 angle y x z Extrinsic RZ(ψ).RX(ϕ).RY(θ)R_Z(\psi).R_X(\phi).R_Y(\theta)
4 angle y z x Extrinsic RX(ϕ).RZ(ψ).RY(θ)R_X(\phi).R_Z(\psi).R_Y(\theta)
5 angle z x y Extrinsic RY(θ).RX(ϕ).RZ(ψ)R_Y(\theta).R_X(\phi).R_Z(\psi)
6 angle z y x Extrinsic RX(ϕ).RY(θ).RZ(ψ)R_X(\phi).R_Y(\theta).R_Z(\psi)
7 angle x y’ z’’ Intrinsic RX(ϕ).RY(θ).RZ(ψ)R_X(\phi).R_Y(\theta).R_Z(\psi)
8 angle x z’ y’’ Intrinsic RX(ϕ).RZ(ψ).RY(θ)R_X(\phi).R_Z(\psi).R_Y(\theta)
9 angle y x’ z’’ Intrinsic RY(θ).RX(ϕ).RZ(ψ)R_Y(\theta).R_X(\phi).R_Z(\psi)
10 angle y z’ x’’ Intrinsic RY(θ).RZ(ψ).RX(ϕ)R_Y(\theta).R_Z(\psi).R_X(\phi)
11 angle z x’ y’’ Intrinsic RZ(ψ).RX(ϕ).RY(θ)R_Z(\psi).R_X(\phi).R_Y(\theta)
12 angle z y’ x’’ Intrinsic RZ(ψ).RY(θ).RX(ϕ)R_Z(\psi).R_Y(\theta).R_X(\phi)
id Ordre Convention Composition Matrice de rotation Remarques
13 axis x y x Extrinsic RX(ψ).RY(θ).RX(ϕ)R_X(\psi).R_Y(\theta).R_X(\phi) Euler
14 axis x y z Extrinsic RZ(ψ).RY(θ).RX(ϕ)R_Z(\psi).R_Y(\theta).R_X(\phi) Cardan - Tait - Bryan
15 axis x z x Extrinsic RX(ψ).RZ(θ).RX(ϕ)R_X(\psi).R_Z(\theta).R_X(\phi) Euler
16 axis x z y Extrinsic RY(ψ).RZ(θ).RX(ϕ)R_Y(\psi).R_Z(\theta).R_X(\phi) Cardan - Tait - Bryan
17 axis y x y Extrinsic RY(ψ).RX(θ).RY(ϕ)R_Y(\psi).R_X(\theta).R_Y(\phi) Euler
18 axis y x z Extrinsic RZ(ψ).RX(θ).RY(ϕ)R_Z(\psi).R_X(\theta).R_Y(\phi) Cardan - Tait - Bryan
19 axis y z x Extrinsic RX(ψ).RZ(θ).RY(ϕ)R_X(\psi).R_Z(\theta).R_Y(\phi) Euler
20 axis y z y Extrinsic RY(ψ).RZ(θ).RY(ϕ)R_Y(\psi).R_Z(\theta).R_Y(\phi) Cardan - Tait - Bryan
21 axis z x y Extrinsic RY(ψ).RX(θ).RZ(ϕ)R_Y(\psi).R_X(\theta).R_Z(\phi) Euler
22 axis z x z Extrinsic RZ(ψ).RX(θ).RZ(ϕ)R_Z(\psi).R_X(\theta).R_Z(\phi) Cardan - Tait - Bryan
23 axis z y x Extrinsic RX(ψ).RY(θ).RZ(ϕ)R_X(\psi).R_Y(\theta).R_Z(\phi) Euler
24 axis z y z Extrinsic RZ(ψ).RY(θ).RZ(ϕ)R_Z(\psi).R_Y(\theta).R_Z(\phi) Cardan - Tait - Bryan
25 axis x y’ x’’ Intrinsic RX(ϕ).RY(θ).RX(ψ)R_X(\phi).R_Y(\theta).R_X(\psi) Euler
26 axis x y’ z’’ Intrinsic RX(ϕ).RY(θ).RZ(ψ)R_X(\phi).R_Y(\theta).R_Z(\psi) Cardan - Tait - Bryan
27 axis x z’ x’’ Intrinsic RX(ϕ).RZ(θ).RX(ψ)R_X(\phi).R_Z(\theta).R_X(\psi) Euler
28 axis x z’ y’’ Intrinsic RX(ϕ).RZ(θ).RY(ψ)R_X(\phi).R_Z(\theta).R_Y(\psi) Cardan - Tait - Bryan
29 axis y x’ y’’ Intrinsic RY(ϕ).RX(θ).RY(ψ)R_Y(\phi).R_X(\theta).R_Y(\psi) Euler
30 axis y x’ z’’ Intrinsic RY(ϕ).RX(θ).RZ(ψ)R_Y(\phi).R_X(\theta).R_Z(\psi) Cardan - Tait - Bryan
31 axis y z’ x’’ Intrinsic RY(ϕ).RZ(θ).RX(ψ)R_Y(\phi).R_Z(\theta).R_X(\psi) Euler
32 axis y z’ y’’ Intrinsic RY(ϕ).RZ(θ).RY(ψ)R_Y(\phi).R_Z(\theta).R_Y(\psi) Cardan - Tait - Bryan
33 axis z x’ y’’ Intrinsic RZ(ϕ).RX(θ).RY(ψ)R_Z(\phi).R_X(\theta).R_Y(\psi) Euler
34 axis z x’ z’’ Intrinsic RZ(ϕ).RX(θ).RZ(ψ)R_Z(\phi).R_X(\theta).R_Z(\psi) Cardan - Tait - Bryan
35 axis z y’ x’’ Intrinsic RZ(ϕ).RY(θ).RX(ψ)R_Z(\phi).R_Y(\theta).R_X(\psi) Euler
36 axis z y’ z’’ Intrinsic RZ(ϕ).RY(θ).RZ(ψ)R_Z(\phi).R_Y(\theta).R_Z(\psi) Cardan - Tait - Bryan

où les matrices de rotation autour des trois axes XX, YY et ZZ s’écrivent

RX(α)=[1000+cos(α)sin(α)0+sin(α)+cos(α)]R_X \left( \alpha \right) = \left[\begin{array}{ccc} 1 & 0 & 0\\ 0 & +\cos \left( \alpha \right) & -\sin \left( \alpha \right)\\ 0 & +\sin \left( \alpha \right) & +\cos \left( \alpha \right) \end{array}\right]

RY(α)=[+cos(α)0+sin(α)010sin(α)0+cos(α)]R_Y \left( \alpha \right) = \left[\begin{array}{ccc} +\cos\left( \alpha \right) & 0 & +\sin \left( \alpha \right) \\ 0 & 1 & 0 \\ -\sin\left( \alpha \right) & 0 & +\cos \left( \alpha \right) \\ \end{array}\right]

RZ(α)=[+cos(α)sin(α)0+sin(α)+cos(α)0001]R_Z \left( \alpha \right) = \left[\begin{array}{ccc} +\cos \left( \alpha \right) & -\sin \left( \alpha \right) & 0 \\ +\sin \left( \alpha \right) & +\cos \left( \alpha \right) & 0 \\ 0 & 0 & 1 \\ \end{array}\right]

6.3 Conventions couramment utilisées

Parmi l’ensemble des conventions possibles, certaines sont plus utilisées que d’autres.

6.3.1 Convention des angles aéronautiques

La convention des angles aéronautiques (convention de type 2 de la norme AFNOR) exprimée par le triplet (Roulis, Tangage, Lacet) régulièrement utilisée est référencée id=12 dans le tableau ci-dessus.

Elle se comprend de la manière suivante, on effectue une rotation de l’angle de lacet autour de l’axe ZZ, suivie d’une rotation de l’angle d’assiette autour du nouvel axe YY' suivie d’une rotation de l’angle de roulis autour du nouvel axe XX''.

Si on exprime ce triplet de la manière suivante (Lacet, Roulis, Tangage), on obtient id=33 dans le tableau ci-dessus.

La composition de rotations de ces deux conventions est représentée sur la figure suivante

6.3.2 Convention ParaView

La convention d’orientation utilisée dans le logiciel ParaView est identifiée par id=11 dans le tableau ci-dessus.

Cette composition de rotation se comprend comme une rotation ψ\psi autour de l’axe ZZ, suivie d’une rotation θ\theta autour du nouvel axe XX' et finalement d’une rotation ϕ\phi autour du nouvel axe YY''.

6.4 Quaternions

L’utilisation des angles d’Euler pose deux problèmes principaux :

Une manière usuelle de contourner ces problèmes est d’utiliser des quaternions qui, au prix de l’ajout d’un état supplémentaire permettent de définir les rotations sans ambiguïté et de façon unique, quelle que soit la convention d’angle adoptée.

Lors des calculs de tenue à la mer (avec une formulation fréquentielle), on utilise souvent un repère linéarisé. Ce repère, qui peut être impliqué lors du lien avec les bases de données hydrodynamiques issues du fréquentiel, est calculé de la façon suivante. En faisant l’hypothèse que les mouvements sont faibles, on effectue un développement des rotations limité au premier ordre et ainsi elles peuvent être exprimées indépendamment par rapport aux axes principaux liés à la position moyenne du navire, dans n’importe quel ordre. Ce repère n’est pas utilisé dans la version actuelle d’xdyn.

6.5 États navires

Le simulateur est multi-corps en ce sens que plusieurs corps peuvent être simulés en même temps. Ainsi, on peut modéliser plusieurs corps mécaniquement indépendants, avec leurs interactions hydrodynamiques, pourvu que l’on implémente le modèle d’interaction (qui peut venir d’un fichier HDB multicorps). Actuellement, aucun effort d’interaction ni de liaison cinématique ne sont implémentés.

Chaque corps possède des états, permettant de reconstituer exactement son mouvement. Ces états sont les suivants :

6.6 Définition des corps simulés

La section bodies du fichier YAML contient une liste de corps, chacun commençant par un tiret :

bodies:
    - name: ....
      ...
    - name: ....
      ...

Chaque corps comprend :

6.6.1 Exemple complet

bodies: # All bodies have NED as parent frame
  - name: TestShip
    mesh: test_ship.stl
    position of body frame relative to mesh:
        frame: mesh
        x: {value: 9.355, unit: m}
        y: {value: 0, unit: m}
        z: {value: -3.21, unit: m}
        phi: {value: 0, unit: rad}
        theta: {value: 0, unit: rad}
        psi: {value: 0, unit: rad}
    initial position of body frame relative to NED:
        frame: NED
        x: {value: 0, unit: m}
        y: {value: 0, unit: m}
        z: {value: -5, unit: m}
        phi: {value: 0, unit: deg}
        theta: {value: -.0058, unit: rad}
        psi: {value: 0, unit: deg}
    initial velocity of body frame relative to NED:
        frame: TestShip
        u: {value: 0, unit: m/s}
        v: {value: 0, unit: m/s}
        w: {value: 0, unit: m/s}
        p: {value: 0, unit: rad/s}
        q: {value: 0, unit: rad/s}
        r: {value: 0, unit: rad/s}
    dynamics:
        hydrodynamic forces calculation point in body frame:
            x: {value: 0.696, unit: m}
            y: {value: 0, unit: m}
            z: {value: 1.418, unit: m}
        centre of inertia:
            frame: TestShip
            x: {value: 0.258, unit: m}
            y: {value: 0, unit: m}
            z: {value: 0.432, unit: m}
        mass: {value: 253.31, unit: tonne} # Caution: 'ton' is the british ton which is 907.185 kg
        rigid body inertia matrix at the center of gravity and projected in the body frame:
            row 1: [253310,0,0,0,0,0]
            row 2: [0,253310,0,0,0,0]
            row 3: [0,0,253310,0,0,0]
            row 4: [0,0,0,1.522e6,0,0]
            row 5: [0,0,0,0,8.279e6,0]
            row 6: [0,0,0,0,0,7.676e6]
        added mass matrix at the center of gravity and projected in the body frame:
            row 1: [3.519e4,0,0,0,0,0]
            row 2: [0,3.023e5,0,0,0,0]
            row 3: [0,0,1.980e5,0,0,0]
            row 4: [0,0,0,3.189e5,0,0]
            row 5: [0,0,0,0,8.866e6,0]
            row 6: [0,0,0,0,0,6.676e6]
    external forces:
      - model: gravity
      - model: non-linear hydrostatic (fast)
    blocked dof:
       from CSV:
         - state: u
           t: T
           value: PS
           interpolation: spline
           filename: test.csv
       from YAML:
         - state: p
           t: [4.2]
           value: [5]
           interpolation: piecewise constant

6.6.2 Nommage du solide

Le nom du solide a son importance puisqu’en définissant un solide, on définit implicitement le repère qui lui est attaché (le repère “body”, cf. documentation des repères).

On peut ensuite y faire référence, notamment pour les post-traitements.

6.6.3 Utilisation d’un maillage

Pour les efforts intégrés sur la carène (par exemple, les efforts hydrostatiques non-linéaires et les efforts de Froude-Krylov), il est nécessaire de définir un maillage.

6.6.3.1 Définition du fichier de maillage

La section mesh est optionnelle. Si l’on choisit de l’utiliser, elle doit contenir un nom de fichier STL contenant le maillage surfacique du navire. Les formats STL ASCII et STL binaire sont supportés. Ce chemin doit être donné relativement à l’endroit où l’on lance le simulateur.

Par exemple, si l’exécutable du simulateur est dans le répertoire A/B/C, que le maillage m.stl est dans A et qu’on lance l’exécutable depuis B, on écrira :

mesh: ../m.stl

6.6.3.2 Passage du repère maillage au repère body

L’origine du repère “body” (qui est le repère dans lequel est réalisé le bilan des efforts) est spécifiée par rapport au repère du maillage. En pratique, x,y,zx,y,z peuvent définir la position du centre de gravité dans le repère maillage et ϕ,θ,ψ\phi,\theta,\psi définissent la rotation permettant de passer du repère maillage au repère body (suivant la convention choisie dans la section rotations).

position of body frame relative to mesh:
    frame: mesh
    x: {value: 0, unit: m}
    y: {value: 0, unit: m}
    z: {value: -10, unit: m}
    phi: {value: 1, unit: rad}
    theta: {value: 3, unit: rad}
    psi: {value: 2, unit: rad}

6.6.4 Champs dynamics

La section dynamics permet de décrire l’inertie du solide. Elle est composée de cinq sous-sections :

6.6.4.1 Position du centre d’inertie

La section centre of inertia a l’allure suivante :

centre of inertia:
    frame: TestShip
    x: {value: 0, unit: m}
    y: {value: 0, unit: m}
    z: {value: 0, unit: m}

Le champs frame doit contenir soit NED, soit un nom de solide, soit mesh(<nom de solide>) suivant le repère choisi pour exprimer les coordonnées du centre de gravité.

6.6.4.2 Définition de la masse du solide

La section mass contient la masse du solide, utilisée notamment pour le modèle de gravité :

mass: {value: 1000, unit: tonne}

Attention : si l’on spécifie ton, le système utilisera la tonne britannique qui vaut 907.185 kg.

6.6.4.3 Matrice d’inertie

La matrice d’inertie n’est pas normalisée et on n’effectue pas de changement de repère.

rigid body inertia matrix at the center of gravity and projected in the body frame:
    row 1: [253310,0,0,0,0,0]
    row 2: [0,253310,0,0,0,0]
    row 3: [0,0,253310,0,0,0]
    row 4: [0,0,0,1.522e6,0,0]
    row 5: [0,0,0,0,8.279e6,0]
    row 6: [0,0,0,0,0,7.676e6]

Les calculs sont réalisés en supposant que les termes aija_{ij} de la matrice d’inertie sont en unité SI, c’est-à-dire:

6.6.4.4 Inerties ajoutées

La matrice de masse ajoutée est définie de la même façon :

added mass matrix at the center of gravity and projected in the body frame:
    row 1: [3.519e4,0,0,0,0,0]
    row 2: [0,3.023e5,0,0,0,0]
    row 3: [0,0,1.980e5,0,0,0]
    row 4: [0,0,0,3.189e5,0,0]
    row 5: [0,0,0,0,8.866e6,0]
    row 6: [0,0,0,0,0,6.676e6]

Elle figure dans la section dynamics et non dans la section external forces (bien qu’il s’agisse d’un modèle d’effort, proportionnel à l’accélération) parce que ce modèle d’effort fait l’objet d’un traitement particulier : il figure dans le membre de gauche de l’équation fondamentale de la dynamique

MẌ=Fi M\ddot{X} = \sum F_i (6.1) pour des raisons de stabilité numérique (l’effort dépend des accélérations qui doivent justement être calculées par la résolution de l’équation fondamentale de la dynamique). La matrice de masses ajoutées n’est cependant pas équivalente à une masse supplémentaire, car les termes de Coriolis et centripète qui correspondraient ne sont pas pris en compte.

Il est également possible d’extrapoler les masses ajoutées à pulsation infinie à partir d’un fichier HDB. Pour cela, on écrit (pour lire depuis le fichier test_ship.hdb) :

added mass matrix at the center of gravity and projected in the body frame:
    from hdb file: test_ship.hdb

Dans ce cas, il ne faut pas spécifier les clefs frame et row (le programme lance une exception si on le fait). Comme le fichier STL, le chemin du fichier HDB est relatif à l’endroit d’où on lance l’exécutable. La section correspondante dans le fichier HDB est Added_mass_Radiation_Damping. La valeur utilisée est la matrice de masse ajoutée à la période minimale définie dans le fichier HDB (aucune extrapolation n’est faite).

6.6.5 Forçage de degrés de liberté

Il est possible de forcer les valeurs des degrés de liberté suivant : U, V, W, P, Q, R pour chaque corps.

Pour forcer les degrés de liberté, on ajoute la section (facultative) suivante à la section body :

blocked dof:
   from CSV:
     - state: u
       t: T
       value: PS
       interpolation: spline
       filename: test.csv
   from YAML:
     - state: p
       t: [4.2]
       value: [5]
       interpolation: piecewise constant

Soit les états sont donnés directement dans le fichier YAML, soit ils sont lus depuis un fichier CSV.

Si les valeurs des états sont dans le YAML :

Si les valeurs sont lues depuis un fichier CSV :

Pour les valeurs de t hors de l’intervalle [tmin,tmax], l’état est supposé libre (non forcé).

Il est possible de récupérer dans les sorties l’écart entre l’effort réel et l’effort permettant de conserver les forçages, en d’autres termes il est possible de récupérer

(M+Ma)XblockeḋFi (M+M_a)\dot{X_{\textrm{blocked}}} - \sum F_i (6.2)

Pour ce faire, on utilise dans la section ‘output’ les clefs suivantes (si le corps s’appelle ’TestShip):

Il est à noter que ces efforts sont exprimés dans le repère BODY.

6.7 Fichiers HDB issus d’un calcul fréquentiel

Le format HDB (Hydrodynamic DataBase) est le format standard du logiciel Diodore. Le logiciel AQUA+ (développé et utilisé en interne par l’École Centrale de Nantes et SIREHNA, dont des parties ont été reprises dans logiciel NEMOH) dispose également d’une sortie permettant de créer un fichier HDB. Ces fichiers peuvent être utilisés par xdyn pour calculer :

6.7.1 Conventions des fichiers HDB

Les fichiers HDB ne spécifient ni leur repère de calcul, ni les points d’expression. Plutôt que de laisser l’utilisateur la spécifier (avec les risques d’erreur que cela comporte) ou de la détecter automatiquement, on suppose pour xdyn que les fichiers HDB ont été générés avec les conventions du logiciel AQUA+ (convention “z vers le haut”). Le repère dans lequel sont exprimées toutes les matrices de tous les fichiers HDB lus par xdyn est donc : x longitudinal, y vers bâbord et z vers le haut.

Les RAO dépendent des conventions (repère, origine des phases, provenance vs. propagation, signe des angles). Or la convention utilisée ne figure pas dans le format HDB. Comme les RAO que l’on utilise actuellement proviennent exclusivement du logiciel AQUA+, dans la version actuelle xdyn suppose que la convention utilisée est celle d’AQUA+.

La différence entre la convention de xdyn et celle d’AQUA+ est que l’axe zz est ascendant pour AQUA+ et descendant pour xdyn. L’angle de la houle représente bien dans les deux cas une direction de propagation (et non de provenance). Le potentiel des vitesses de la houle est, dans xdyn comme dans AQUA+ :

ϕ(x,y,z,t)=gηaωcosh(k(hz))cosh(kh)cos(k(xcos(γ)+ysin(γ))ωt+ϕ)\phi(x,y,z,t) = -\frac{g\eta_a}{\omega}\frac{\cosh(k\cdot(h-z))} {\cosh(k\cdot h)}\cos(k\cdot(x\cdot \cos(\gamma)+ y\cdot \sin(\gamma))-\omega\cdot t+\phi)

Toutes les données issues des fichiers HDB sont données en convention z vers le haut : par conséquent, il faut effectuer un changement de repère (rotation de π\pi autour de l’axe XX) pour les mettre dans le repère d’xdyn (z vers le bas). La matrice de changement de base est :

RX(π)=[100010001] R_X(\pi)=\left[\begin{array}{ccc} 1 & 0 &0\\0&-1&0\\0&0&-1\end{array}\right] (6.3)

[xdydzd]xdyn=[100010001][xayaza]AQUA+=[xayaza]xdyn \left[\begin{array}{c}x_d\\y_d\\z_d\\\end{array}\right]_{\mbox{xdyn}}=\left[\begin{array}{ccc} 1 & 0 &0\\0&-1&0\\0&0&-1\end{array}\right]\left[\begin{array}{c}x_a\\y_a\\z_a\\\end{array}\right]_{\mbox{AQUA+}} =\left[\begin{array}{c}x_a\\-y_a\\-z_a\\\end{array}\right]_{\mbox{xdyn}} (6.4)

Md=[RX(π)S(AB)RX(π)0RX(π)]M[RX(π)S(AB)RX(π)0RX(π)] M_d = \left[\begin{array}{cc}R_X(\pi)&S(AB)R_X(\pi)\\0&R_X(\pi)\end{array}\right]^\top M \left[\begin{array}{cc}R_X(\pi)&S(AB)R_X(\pi)\\0&R_X(\pi)\end{array}\right] (6.5)

Par conséquent, toutes les matrices lues depuis le fichier HDB (masses ajoutées et amortissement de radiation) subissent un changement de repère décrit au paragraphe suivant.

6.7.2 Transport des matrices d’inertie et d’amortissement lues depuis le fichier HDB

La formule de Huygens permet de translater les inerties du centre de gravité vers un point quelconque. On s’intéresse ici au déplacement et au changement de repère d’une matrice d’inertie généralisée (inerties propres et inerties ajoutées). Par rapport à la formule de Huygens, la différence vient de ce que l’inertie n’est pas identique sur tous les axes (mathématiquement, la matrice peut donc être n’importe quelle forme bilinéaire symétrique, positive et définie).

Soit

S(λ)=[0λ3λ2λ30λ1λ2λ10]0 S(\lambda)=\left[\begin{array}{ccc} 0&-\lambda_3&\lambda_2\\\lambda_3&0&-\lambda_1\\-\lambda_2&\lambda_1&0\end{array}\right]_{\mathcal{R_0}} (6.6)

la matrice du produit vectoriel par λ=[λ1,λ2,λ3]\lambda^\top=[\lambda_1,\lambda_2,\lambda_3] : a0,λ×a=S(λ)a\forall a\in\mathcal{R_0},\lambda\times a = S(\lambda) a

Pour effectuer un transport d’une matrice 6x6 en coordonnées généralisées (masse, masse ajoutée ou amortissement) d’un point AA vers un point BB, on utilise :

MB=[IS(AB)0I]MA[IS(AB)0I] M_B=\left[\begin{array}{cc}I&S(AB)\\0&I\end{array}\right]^\top M_A \left[\begin{array}{cc}I&S(AB)\\0&I\end{array}\right] (6.7)

Cette formule est une généralisation de la formule de Huygens.

En combinant avec un changement de base (de la base aa vers la base bb) par la matrice de rotation aRb{}^a R_b de bb vers aa on obtient l’expression plus générale :

bMB=[aRbS(AB)aRb0aRb]aMA[aRbS(AB)aRb0aRb] {}^bM_B=\left[\begin{array}{cc}{}^a R_b&S(AB){}^a R_b\\0&{}^a R_b\end{array}\right]^\top {}^aM_A \left[\begin{array}{cc}{}^a R_b&S(AB){}^a R_b\\0&{}^a R_b\end{array}\right] (6.8)

Cette formule permet d’effectuer à la fois le transport d’une matrice d’inertie généralisée 6x6 d’un point AA à un point BB et le changement de son repère d’expression de aa vers bb.

La matrice d’inertie est le plus souvent exprimée au centre de gravité. Cependant, rien ne le garantit dans les fichiers HDB. Dans le cas général, il faut donc effectuer un transport, mais on suppose dans xdyn qu’il n’y a pas de transport à faire et donc que la seule opération pour la conversion est le passage d’un repère z vers le haut (HDB) à un repère z vers le bas (xdyn). La formule précédente se simplifie alors en :

bMB=[100000010000001000000100000010000001]aMA[100000010000001000000100000010000001] {}^bM_B=\left[ \begin{array}{cccccc} 1&0&0&0&0&0\\ 0&-1&0&0&0&0\\ 0&0&-1&0&0&0\\ 0&0&0&1&0&0\\ 0&0&0&0&-1&0\\ 0&0&0&0&0&-1\\ \end{array} \right]^\top {}^aM_A \left[ \begin{array}{cccccc} 1&0&0&0&0&0\\ 0&-1&0&0&0&0\\ 0&0&-1&0&0&0\\ 0&0&0&1&0&0\\ 0&0&0&0&-1&0\\ 0&0&0&0&0&-1\\  \end{array} \right] (6.9)

En prenant la notation

MHDB=[m11m12m13m14m15m16m21m22m23m24m25m26m31m32m33m34m35m36m41m42m43m44m45m46m51m52m53m54m55m56m61m62m63m64m65m66] M_{\mbox{HDB}} = \left[ \begin{array}{cccccc} m_{11} & m_{12} & m_{13} & m_{14} & m_{15} & m_{16}\\ m_{21} & m_{22} & m_{23} & m_{24} & m_{25} & m_{26} \\ m_{31} & m_{32} & m_{33} & m_{34} & m_{35} & m_{36} \\ m_{41} & m_{42} & m_{43} & m_{44} & m_{45} & m_{46}\\ m_{51} & m_{52} & m_{53} & m_{54} & m_{55} & m_{56} \\ m_{61} & m_{62} & m_{63} & m_{64} & m_{65} & m_{66} \\ \end{array} \right] (6.10)

on obtient :

Mxdyn=[m11m12m13m14m15m16m21m22m23m24m25m26m31m32m33m34m35m36m41m42m43m44m45m46m51m52m53m54m55m56m61m62m63m64m65m66] M_{\mbox{xdyn}} = \left[ \begin{array}{cccccc} m_{11} & -m_{12} & -m_{13} & m_{14} & -m_{15} & -m_{16}\\ -m_{21} & m_{22} & m_{23} & -m_{24} & m_{25} & m_{26} \\ -m_{31} & m_{32} & m_{33} & -m_{34} & m_{35} & m_{36} \\ m_{41} & -m_{42} & -m_{43} & m_{44} & -m_{45} & -m_{46}\\ -m_{51} & m_{52} & m_{53} & -m_{54} & m_{55} & m_{56} \\ -m_{61} & m_{62} & m_{63} & -m_{64} & m_{65} & m_{66} \\ \end{array} \right] (6.11)

Pour les torseurs, on obtient le changement suivant :

τHDB=[FXFYFZMXMYMZ] \tau_{\mbox{HDB}} = \left[ \begin{array}{c} F_X\\ F_Y\\ F_Z\\ M_X\\ M_Y\\ M_Z\\ \end{array} \right] (6.12)

τxdyn=[FXFYFZMXMYMZ] \tau_{\mbox{xdyn}} = \left[ \begin{array}{c} F_X\\ -F_Y\\ -F_Z\\ M_X\\ -M_Y\\ -M_Z\\ \end{array} \right] (6.13)

Cf. SimBody Theory Manual, Release 3.1, March, 2013, page 137, §12.3.1, Rigid body shift of rigid body spatial inertia

6.7.3 Structure des fichiers HDB

Les fichiers HDB sont des sorties générées par un code Fortran 77. Aucune spécification formelle de ce format n’a été trouvée. Pour pouvoir les importer dans xdyn, leur grammaire EBNF a été déduite de l’analyse de plusieurs fichiers (reverse-engineering). Cette grammaire, qui permet de parser tous les fichiers HDB qui nous ont été fournis jusqu’ici, peut être représentée comme suit (sans garantie d’exhaustivité) :

ast                             = string-key
                                | value-key
                                | vector-section
                                | matrix-section
                                | list-of-matrix-sections
                                | list-of-matrix-sections-with-id;
str                             = character , +extended-char , *" "  , +extended-char;
header                          = "[" , str , "]";
string-key                      = header , str , -eol;
value-key                       = header , double , -eol;
values                          = double_ , +double , -eol;
vector-section                  = header , eol , +(double , eol) , -eol;
matrix-section                  = header , eol , +(*(eol, values)) , -eol;
list-of-matrix-sections         = header , eol , +matrix-section , -eol;
section-with-id                 = header , double , eol , *(eol, values) , -eol;
list-of-matrix-sections-with-id = header , eol , +(header , double , eol , +(*(eol, values)));
character                       = "A" | "B" | "C" | "D" | "E" | "F" | "G"
                                | "H" | "I" | "J" | "K" | "L" | "M" | "N"
                                | "O" | "P" | "Q" | "R" | "S" | "T" | "U"
                                | "V" | "W" | "X" | "Y" | "Z" | "a" | "b"
                                | "c" | "d" | "e" | "f" | "g" | "h" | "i"
                                | "j" | "k" | "l" | "m" | "n" | "O" | "p"
                                | "q" | "r" | "s" | "t" | "u" | "v" | "w"
                                | "x" | "y" | "z" | "_";
extended-char                   = character | "-" | "+"

Les fichiers HDB sont donc constitués d’une liste d’éléments, ces éléments étant pouvant être de type string-key, value-key, vector-section, matrix-section, list-of-matrix-sections ou list-of-matrix-sections-with-id. xdyn ne tient pas compte de l’ordre dans lequel sont ces éléments (mais aucune garantie ne peut être fournie pour d’éventuels autres outils utilisant les HDB).

6.7.3.1 Exemple de “string-key”

 [SOFT] AQUA+

6.7.3.2 Exemple de “value-key”

[FORWARD_SPEED]   0.00

6.7.3.3 Exemple de “vector-section”

 [List_calculated_periods]
   4.00
  64.00
 125.00

6.7.3.4 Exemple de “matrix-section”

[Mass_Inertia_matrix]
 8.635000E+06  0.000000E+00  0.000000E+00  0.000000E+00  0.000000E+000.000000E+00
 0.000000E+00  8.635000E+06  0.000000E+00  0.000000E+00  0.000000E+000.000000E+00
 0.000000E+00  0.000000E+00  8.635000E+06  0.000000E+00  0.000000E+000.000000E+00
 0.000000E+00  0.000000E+00  0.000000E+00  4.149000E+08  0.000000E+000.000000E+00
 0.000000E+00  0.000000E+00  0.000000E+00  0.000000E+00  1.088000E+100.000000E+00
 0.000000E+00  0.000000E+00  0.000000E+00  0.000000E+00  0.000000E+00  1.088000E+10

6.7.3.5 Exemple de “list-of-matrix-sections”

[Added_mass_Radiation_Damping]
[ADDED_MASS_LINE_1]
   4.00  8.770898E+04  0.000000E+00  2.122348E+05  0.000000E+00  1.844677E+07  0.000000E+00
  64.00  2.356385E+05  0.000000E+00  3.063730E+05  0.000000E+00  6.103379E+07  0.000000E+00
 125.00  2.334437E+05  0.000000E+00  3.058729E+05  0.000000E+00  6.044752E+07  0.000000E+00
[ADDED_MASS_LINE_2]
   4.00  0.000000E+00  2.406631E+06  0.000000E+00 -1.298266E+06  0.000000E+00  2.894931E+07
  64.00  0.000000E+00  7.130066E+06  0.000000E+00 -3.516670E+06  0.000000E+00  9.536960E+07
 125.00  0.000000E+00  7.100760E+06  0.000000E+00 -3.493418E+06  0.000000E+00  9.499156E+07

6.7.3.6 Exemple de “list-of-matrix-sections-with-id”

[FROUDE-KRYLOV_FORCES_AND_MOMENTS]
[INCIDENCE_EFM_MOD_001]   0.000000
  4.00  6.452085E+04  0.000000E+00  3.775068E+05  0.000000E+00  2.630894E+07  0.000000E+00
 64.00  8.296234E+04  0.000000E+00  2.098381E+07  0.000000E+00  1.280202E+08  0.000000E+00
125.00  2.179682E+04  0.000000E+00  2.105635E+07  0.000000E+00  1.258710E+08  0.000000E+00
[INCIDENCE_EFM_MOD_001]   30.00000
  4.00  5.988292E+04  3.453055E+04  5.220861E+05  6.375514E+05  2.533077E+07  1.149621E+06
 64.00  7.185571E+04  4.148640E+04  2.098683E+07  7.927488E+04  1.274491E+08  3.394846E+04
125.00  1.887675E+04  1.089865E+04  2.105658E+07  2.081770E+04  1.258309E+08  2.938749E+03
[INCIDENCE_EFM_PH_001]   0.000000
  4.00  5.079494E-01  1.570796E+00  1.171722E+00  1.570796E+00  1.426003E+00  1.570796E+00
 64.00 -3.141362E+00  1.570796E+00 -1.576680E+00  1.570796E+00 -1.768797E+00  1.570796E+00
125.00 -3.141476E+00  1.570796E+00 -1.572334E+00  1.570796E+00 -1.623406E+00  1.570796E+00

6.7.4 Sections utilisées par xdyn

Les sections du HDB actuellement utilisées par xdyn sont :

6.8 Repère de calcul hydrodynamique

Les efforts d’amortissement visqueux et de résistance à l’avancement sont calculés dans un repère appelé repère de calcul hydrodynamique, qui est un repère translaté par rapport au repère body. Le centre de ce repère est un point défini (dans le repère body) de la façon suivante :

Ce point est, en général, distinct du centre de gravité et du centre de volume. Il est défini dans la section dynamics/hydrodynamic forces calculation point in body frame du fichier YAML :

hydrodynamic forces calculation point in body frame:
    x: {value: 0.696, unit: m}
    y: {value: 0, unit: m}
    z: {value: 1.418, unit: m}

On note localTbody{}^{\textrm{local}}T_{\textrm{body}} la transformation permettant de convertir des coordonnées dans le repère body en coordonnées du même point exprimées dans le repère de calcul hydrodynamique. localTNED{}^{\textrm{local}}T_{\textrm{NED}} est celle permettant de convertir des coordonnées dans le repère NED en coordonnées du même point exprimées dans le repère de calcul hydrodynamique.

Il convient de distinguer ce repère de celui utilisé dans la base de données hydrodynamiques (fichiers HDB), utilisé pour l’expression des matrices d’amortissement de radiation, les RAO d’effort (pour le calcul des efforts de diffraction) et les masses ajoutées.

6.9 Rotations et constantes environnementales

6.9.1 Rotations

La convention de rotation permet de retrouver la matrice de rotation d’un repère par rapport à un autre, étant donné un triplet (ϕ,θ,ψ)(\phi, \theta, \psi). La convention utilisée est décrite dans la section rotations :

rotations convention: [psi,theta',phi'']

Cette ligne s’interprète de la façon suivante : étant donné un triplet (ϕ,θ,ψ)(\phi, \theta, \psi), on construit les matrices de rotation en effectuant d’abord une rotation d’angle ψ\psi autour de l’axe Z, ensuite une rotation d’angle θ\theta autour de l’axe Y du repère précédemment transformé, puis une rotation d’angle ϕ\phi autour de l’axe X du repère ainsi obtenu.

Si l’on avait noté :

rotations convention: [z,y',x'']

on aurait d’abord une rotation d’angle ϕ\phi autour de l’axe Z, puis une rotation d’angle θ\theta autour du nouvel axe Y, puis une rotation ψ\psi autour du nouvel axe X.

Des apostrophes sont utilisées pour indiquer des compositions de rotations par rapport au nouveau système d’axes, et donc une composition interne. Ainsi [x,y',z''] désignera une rotation autour X, suivie d’une rotation autour du nouvel axe Y, appelé Y’ et terminée par une rotation autour du nouvel axe Z, appelé Z’’. La double apostrophe fait référence au deuxième repère utilisée pour la composition de rotation.

La liste rotations convention comporte toujours trois éléments. Le deuxième élément est toujours différent du premier. Le troisième est soit différent des deux autres, soit égal au premier.

La convention des angles aéronautiques, fréquemment (et abusivement) dénotée “angles d’Euler” (lacet ψ\psi, tangage θ\theta, roulis ϕ\phi), se définit de la façon suivante :

rotations convention: [psi, theta', phi'']

La convention d’orientation utilisée dans le logiciel ParaView est donnée par :

rotations convention: [psi,phi',theta'']

Pour plus de détails sur les conventions d’angles et d’axes, se référer à la documentation détaillée.

La définition d’un repère dans xdyn s’effectue à partir d’un repère connu (NED ou body). On définit le changement de coordonnées pour passer d’un repère connu à un nouveau repère de la manière suivante dans le fichier YAML :

    frame: NED
    x: {value: 0, unit: m}
    y: {value: 0, unit: m}
    z: {value: 0, unit: m}
    phi: {value: 0, unit: rad}
    theta: {value: 0, unit: rad}
    psi: {value: 0, unit: rad}

Cette description est en particulier utilisée pour définir le changement de coordonnées entre le repère du maillage et le repère du corps (par la clef position of body frame relative to mesh) et la position initiale du corps à simuler (clef initial position of body frame relative to NED).

6.10 Convention de houle

xdyn utilise la convention ZZ vers le bas pour l’amplitude. L’azimuth ou la direction de houle que l’on note γ\gamma représente la direction de propagation de la houle.

Ainsi une direction nulle indique une propagation du sud vers le nord de la houle. Une direction de 90° représente une propagation de l’ouest vers l’est.

Les différentes positions du navire par rapport à la houle sont décrites comme suit :

7 Modèles d’environnement

Les modèles d’environnement sont les modèles de houle (et, à terme, de vent, de courant…) utilisés par xdyn. Actuellement, seuls des modèles de houle sont implémentés. Leur paramétrisation figure dans la section environment du fichier YAML d’entrée. Elle peut être vide (par exemple, lors de la simulation simple du tutoriel 1).

Les modèles de houle interviennent pour le calcul des efforts hydrostatiques non-linéaires (par le truchement de l’élévation de la surface libre), les efforts de Froude-Krylov (par le biais de la pression dynamique), le calcul des efforts de diffraction (via le fréquentiel) et le modèle de safran (prise en compte des vitesses orbitales).

7.1 Constantes environnementales

L’accélération de la pesanteur (dénotée par g), la densité volumique de l’eau (rho) et sa viscosité nu sont des constantes qui interviennent dans plusieurs modèles physiques. Par conséquent, plutôt que d’être renseignées au niveau de chaque modèle et risquer ainsi des incohérences, elles figurent dans la section environmental constants qui a la forme suivante :

environmental constants:
    g: {value: 9.81, unit: m/s^2}
    rho: {value: 1025, unit: kg/m^3}
    nu: {value: 1.18e-6, unit: m^2/s}

Ces trois constantes sont l’ensemble de toutes les constantes environnementales actuellement utilisées par les modèles d’xdyn.

Comme expliqué dans une section précédente, les dimensions physiques ne sont pas vérifiées et simplement converties en unités du système international. Si xdyn rencontre une unité inconnue, il produit un message d’erreur du type :

unknow unit : hhm

7.2 Simulation sans houle

Pour simuler une surface libre parfaitement plane, on opère de la façon suivante :

    environment:
      - model: no waves
        constant sea elevation in NED frame: {value: 0, unit: m}

model: no waves indique que l’on souhaite une surface libre horizontale et constant sea elevation in NED frame représente l’élévation de la surface libre dans le repère NED.

Dans ce cas, les efforts d’excitation (Froude-Krylov et radiation) seront nuls.

7.3 Houle d’Airy

On peut définir une houle comme étant une somme de plusieurs spectres directionnels, c’est-à-dire un spectre de puissance et une dispersion spatiale. Pour dériver l’expression générale d’une houle composée de plusieurs spectres, on commence par le cas d’une houle monochromatique et monodirectionnelle.

7.3.1 Expression du potentiel de vitesse de la houle

Soit V(x,y,z,t)=(u,v,w)V(x,y,z,t)=(u,v,w) la vitesse du fluide au point de coordonnées (x,y,z)(x,y,z) (dans le repère NED) et à l’instant tt.

On suppose l’eau non visqueuse, incompressible, homogène et isotrope et l’on considère un écoulement irrotationnel. Supposer l’écoulement irrotationnel implique (d’après le lemme de Poincaré) que la vitesse dérive d’un potentiel que l’on appelle ϕ:(x,y,z,t)ϕ(x,y,z,t)\phi:(x,y,z,t)\mapsto\phi(x,y,z,t). Par définition, la vitesse en tout point de l’écoulement est donc donnée par :

V(x,y,z,t)=gradϕ(x,y,z,t) V(x,y,z,t) = \textrm{grad}{\phi(x,y,z,t)} (7.1)

La pression pp vérifie l’équation de Bernoulli :

p+ρgzρϕt+ρ2VV=C(t) p + \rho g z -\rho\frac{\partial\phi}{\partial t} + \frac{\rho}{2} V\cdot V = C(t) (7.2)

C:tC(t)C:t\mapsto C(t) est une fonction du temps arbitraire, donc l’équation est en particulier valable pour C(t)=p0C(t)=p_0 (pression atmosphérique à la surface) :

p0+ρgzρϕt+ρ2VV=p0 p_0 + \rho g z -\rho\frac{\partial\phi}{\partial t} + \frac{\rho}{2} V\cdot V = p_0 (7.3)

soit

gzϕt+12VV=0 g z -\frac{\partial\phi}{\partial t} + \frac{1}{2} V\cdot V = 0 (7.4)

Le terme ρgz\rho g z représente la pression hydrostatique et le terme ρϕt-\rho\frac{\partial\phi}{\partial t} est la pression dynamique.

Il s’agit de la première condition de surface libre.

On peut définir la fonction F(x,y,z,t)=zη(x,y,t)F(x,y,z,t)=z-\eta(x,y,t)

Pour une particule sur la surface libre, F(x,y,z,t)=0F(x,y,z,t)=0 ce qui implique que sa dérivée particulaire est nulle :

DFDt=Ft+VF=0 \frac{DF}{Dt} = \frac{\partial F}{\partial t} + V\cdot \nabla F = 0 (7.5)

soit

ηt+ϕxηx+ϕxηyϕz=0\frac{\partial\eta}{\partial t} + \frac{\phi}{\partial x}\frac{\partial \eta}{\partial x} + \frac{\phi}{\partial x}\frac{\partial\eta}{\partial y} - \frac{\partial\phi}{\partial z} = 0 sur z=η(x,y,t)z=\eta(x,y,t).

C’est la deuxième condition de surface libre.

En linéarisant ces deux conditions de surface libre, on obtient :

ηt=ϕz \frac{\partial \eta}{\partial t} = \frac{\partial\phi}{\partial z} (7.6)

gηϕt=0 g\eta - \frac{\partial\phi}{\partial t} = 0 (7.7)

Par ailleurs, l’eau étant supposée incompressible, V=2ϕx2+2ϕy2+2ϕz2=0\nabla\cdot V= \frac{\partial^2\phi}{\partial x^2} + \frac{\partial^2\phi}{\partial y^2} + \frac{\partial^2\phi}{\partial z^2} = 0

Il s’agit d’une équation de Laplace dont la solution s’obtient par la méthode de séparation des variables. Plusieurs potentiels peuvent être solution. Par exemple :

Ici, nous choisissons :

ϕ(x,y,z,t)=gηaωcosh(k(hz))cosh(kh)cos(k(xcos(γ)+ysin(γ))ωt+ϕ) \phi(x,y,z,t) = -\frac{g\eta_a}{\omega}\frac{\cosh(k\cdot(h-z))} {\cosh(k\cdot h)}\cos(k\cdot(x\cdot \cos(\gamma)+ y\cdot \sin(\gamma))-\omega\cdot t+\phi) (7.8)

qui est le potentiel utilisé par le logiciel AQUA+.

7.3.2 Relation entre le nombre d’onde et la pulsation

Il existe une relation entre kk et ω\omega, appelée relation de dispersion, et qui s’écrit :

ω2=gktanh(kh) \omega^2 = g\cdot k \cdot \tanh(k\cdot h) (7.9)

hh désigne la profondeur d’eau et gg l’accélération de la pesanteur.

En profondeur infinie (kh>3k\cdot h > 3), cette relation tend vers :

ω2gk \omega^2 \sim g\cdot k (7.10)

7.3.3 Élévation de la houle

L’élévation de la houle découle de la deuxième condition de surface libre :

η(x,y,t)=+1gϕ(x,y,z=0,t)t=i=1nfreqA(ωi)sin(ki(xcos(γ)+ysin(γ))ωit+ϕi)\eta(x,y,t) = +\frac{1}{g} \frac{\partial\phi(x,y,z=0,t)}{\partial t} =-\sum_{i=1}^{nfreq} A(\omega_i) \sin(k_i\cdot(x\cdot \cos(\gamma)+ y\cdot \sin(\gamma))-\omega_i\cdot t+\phi_{i})

γ\gamma désigne la direction de provenance de la houle, définie à la section convention de houle.

L’élévation η\eta de la houle en un point (x,y)(x,y) est un signal temporel η(t)\eta(t). Par définition du plan z=0z=0 (élévation moyenne de la houle), ce signal η\eta est centré. On le suppose également stationnaire, ce qui implique que sa fonction d’auto-corrélation RR ne dépend que de τ\tau:

R(τ)=𝐄(η(t)η(t+τ)) R(\tau)=\mathbf{E} (\eta(t)\eta(t+\tau)) (7.11)

La densité spectrale de puissance GG de η\eta est égale à la transformée de Fourier de sa fonction d’auto-corrélation RR. Comme RR est paire et réelle, GG aussi et on ne considère usuellement que la partie positive (one-sided) en définissant la densité spectrale SS telle que :

S(ω)={2G(ω),ω00,ω<0 S(\omega)=\left\{\begin{array}{cc}2G(\omega),&\omega\geq 0\\0,&\omega<0\end{array}\right. (7.12)

On a :

R(τ)=12i=1nfreqA(ωi)2cos(ωiτ) R(\tau) = \frac{1}{2} \sum_{i=1}^{nfreq} A(\omega_i)^2 \cos(\omega_i \tau) (7.13)

or on a également :

R(τ)=0S(ω)cos(ωτ)dω R(\tau) = \int_0^\infty S(\omega) \cos(\omega\tau)d\omega (7.14)

d’où, par identification :

A(ωi)2=2S(ωi)dωi A(\omega_i)^2=2 S(\omega_i)d\omega_i (7.15)

On peut généraliser cette formulation en faisant intervenir l’étalement directionnel D(γ)D(\gamma) de la houle :

A(ω,γ)2=2S(ω)dωD(γ)dγ A(\omega,\gamma)^2 = 2 S(\omega)d\omega D(\gamma) d\gamma (7.16)

On obtient, en définitive :

η(x,y,t)=i=1nfreq2S(ωi)dωD(γ)dγsin(ki(xcos(γ)+ysin(γ))ωit+ϕi) \eta(x,y,t) = -\sum_{i=1}^{nfreq} \sqrt{2 S(\omega_i)d\omega D(\gamma) d\gamma} \sin(k_i\cdot(x\cdot \cos(\gamma)+ y\cdot \sin(\gamma))-\omega_i\cdot t+\phi_{i}) (7.17)

7.3.4 Pression dynamique

L’expression de la pression dynamique (champs de pression de la houle incidente), utilisée par le modèle de Froude-Krylov, est définie comme la pression totale moins la pression hydrostatique ρgz\rho g z et son expression se déduit de la première condition de surface libre linéarisée :

pdyn=ρΦ(x,y,z,t)t p_{\textrm{dyn}} = -\rho \frac{\partial \Phi(x,y,z,t)}{\partial t} (7.18)

soit

pdyn=ρgi=1nfreqA(ωi,γ)cosh(ki(hz))cosh(kih)sin(ki(xcos(γ)+ysin(γ))ωit+ϕi) p_{\textrm{dyn}} = \rho\cdot g \sum_{i=1}^{nfreq}A(\omega_i,\gamma) \frac{\cosh(k_i\cdot(h-z))}{\cosh(k_i\cdot h)}\sin(k_i\cdot(x\cdot \cos(\gamma)+ y\cdot \sin(\gamma))-\omega_i\cdot t+\phi_{i}) (7.19)

Lorsque la profondeur hh est très grande devant zz, les cosinus hyperboliques sont équivalents à des exponentielles :

xcoshx=ex2 \mathop {\lim }\limits_{x \to \infty } \cosh x = \frac{{e^x }}{2} (7.20)

on obtient donc :

pdynxρgi=1nfreqA(ωi,γ)ekizsin(ki(xcos(γ)+ysin(γ))ωit+ϕi) p_{\textrm{dyn}}\mathop \approx \limits_{x \to \infty } \rho\cdot g \sum_{i=1}^{nfreq}A(\omega_i,\gamma) e^{-k_i\cdot z}\sin(k_i\cdot(x\cdot\cos(\gamma)+ y\cdot \sin(\gamma))-\omega_i\cdot t+\phi_{i}) (7.21)

7.3.5 Pression totale

On peut démontrer que la pression totale (somme de la pression hydrostatique et de la pression dynamique) est positive.

Le raisonnement s’exprime simplement pour une seule fréquence et une seule direction, mais il est aisément généralisable.

Pour une seule fréquence et une seule direction, on a :

ptot=ρgzρgcosh(k(hz))cosh(kh)η p_{\textrm{tot}} = \rho g z - \rho g \frac{\cosh(k(h-z))}{\cosh(k h)}\eta (7.22)

Sous la surface libre, c’est-à-dire pour z>0z>0, on a hz<hh-z<h donc

0<cosh(k(hz))cosh(kh)1 0<\frac{\cosh(k(h-z))}{\cosh(k h)}\leq 1 (7.23)

donc

ρgzρgcosh(k(hz))cosh(kh)ηρg(zη) \rho g z - \rho g \frac{\cosh(k(h-z))}{\cosh(k h)}\eta \geq \rho g \left(z - \eta\right) (7.24)

or pour le calcul, on considère toujours la partie immergée de la coque donc zηz\geq\eta, d’où ptot0 p_{\textrm{tot}} \geq 0 (7.25)

Au-dessus de la surface libre, on a ηz0\eta\leq z\leq 0 donc hzhh-z\geq h et

cosh(k(hz))cosh(kh)1 \frac{\cosh(k(h-z))}{\cosh(k h)}\geq 1 (7.26)

Or

ptot=ρg(zcosh(k(hz))cosh(kh)η)ρgη(1cosh(k(hz))cosh(kh)) p_{\textrm{tot}} = \rho g \cdot \left(z - \frac{\cosh(k(h-z))}{\cosh(k h)} \eta\right)\geq \rho g \eta \left(1- \frac{\cosh(k(h-z))}{\cosh(k h)}\right) (7.27)

Comme

1cosh(k(hz))cosh(kh)0 1- \frac{\cosh(k(h-z))}{\cosh(k h)} \leq 0 (7.28)

et ηz0\eta\leq z \leq 0 (on est sous l’eau),

η(1cosh(k(hz))cosh(kh))0 \eta \left(1- \frac{\cosh(k(h-z))}{\cosh(k h)}\right)\geq 0 (7.29)

et donc

ptot0 p_{\textrm{tot}}\geq 0 (7.30)

7.3.6 Houle irrégulière

Le potentiel de vitesse de la houle a été jusqu’ici exprimé pour une seule fréquence et une seule direction. On peut le généraliser pour plusieurs fréquences et plusieurs directions.

En notant

ai,j=A(ωi,γj)=2S(ωi)dωD(γj)dγ a_{i,j} = A(\omega_i, \gamma_j) = \sqrt{2 S(\omega_i)d\omega D(\gamma_j)d\gamma} (7.31)

le potentiel de houle irrégulière s’écrit:

ϕ(x,y,z,t)=i=1nfreqj=1ndirai,jgωicosh(k(hz))cosh(kih)cos(ki(xcos(γj)+ysin(γj))ωit+ϕi,j) \phi(x,y,z,t) = -\sum_{i=1}^{nfreq}\sum_{j=1}^{ndir} a_{i,j} \cdot \frac{g}{\omega_i}\frac{\cosh(k\cdot(h-z))} {\cosh(k_i\cdot h)}\cos(k_i\cdot(x\cdot \cos(\gamma_j)+ y\cdot \sin(\gamma_j))-\omega_i\cdot t+\phi_{i,j}) (7.32)

On en déduit l’expression de l’élévation η\eta :

η(x,y,t)=1gϕt=i=1nfreqj=1ndirai,jsin(ki(xcos(γj)+ysin(γj))ωit+ϕi,j) \eta(x,y,t) = \frac{1}{g}\frac{\partial\phi}{\partial t} = - \sum_{i=1}^{nfreq}\sum_{j=1}^{ndir} a_{i,j}\sin(k_i\cdot(x\cdot \cos(\gamma_j) + y\cdot \sin(\gamma_j))-\omega_i\cdot t+\phi_{i,j}) (7.33)

ainsi que l’expression de la pression dynamique pdynp_{\textrm{dyn}} :

pdyn(x,y,z,t)=ρgi=1nfreqj=1ndirai,jcosh(ki(hz))cosh(kih)sin(ki(xcos(γj)+ysin(γj))ωit+ϕi,j) p_{\textrm{dyn}}(x,y,z,t) = \rho\cdot g \sum_{i=1}^{nfreq}\sum_{j=1}^{ndir} a_{i,j}\frac{\cosh(k_i\cdot(h-z))}{\cosh(k_i\cdot h)}\sin(k_i\cdot(x\cdot \cos(\gamma_j)+ y\cdot \sin(\gamma_j))-\omega_i\cdot t+\phi_{i,j}) (7.34)

7.3.7 Vitesse orbitale

7.3.7.1 En profondeur finie

La vitesse V(x,y,z,t)=(u,v,w)V(x,y,z,t) = (u,v,w) orbitale de la houle est définie par :

u=ϕx=gi=1nfreqj=1ndirkiωiai,jcosh(ki(hz))cosh(kih)cos(γj)sin(ki(xcos(γj)+ysin(γj))ωit+ϕi,j) u = \frac{\partial \phi}{\partial x} = g \sum_{i=1}^{nfreq}\sum_{j=1}^{ndir}\frac{k_i}{\omega_i} a_{i,j} \frac{\cosh(k_i\cdot(h-z))}{\cosh(k_i\cdot h)}\cdot\cos(\gamma_j) \sin(k_i\cdot(x\cdot \cos(\gamma_j)+ y\cdot \sin(\gamma_j))-\omega_i\cdot t+\phi_{i,j}) (7.35)

v=ϕy=gi=1nfreqj=1ndirkiωiai,jcosh(ki(hz))cosh(kih)sin(γj)sin(ki(xcos(γj)+ysin(γj))ωit+ϕi,j) v = \frac{\partial \phi}{\partial y} = g \sum_{i=1}^{nfreq}\sum_{j=1}^{ndir}\frac{k_i}{\omega_i} a_{i,j} \frac{\cosh(k_i\cdot(h-z))}{\cosh(k_i\cdot h)}\cdot\sin(\gamma_j) \sin(k_i\cdot(x\cdot \cos(\gamma_j)+ y\cdot \sin(\gamma_j))-\omega_i\cdot t+\phi_{i,j}) (7.36)

w=ϕz=gi=1nfreqj=1ndirkiωiai,jsinh(ki(hz))cosh(kih)cos(ki(xcos(γj)+ysin(γj))ωit+ϕi,j) w = \frac{\partial \phi}{\partial z} = g \sum_{i=1}^{nfreq}\sum_{j=1}^{ndir}\frac{k_i}{\omega_i} a_{i,j} \frac{\sinh(k_i\cdot(h-z))}{\cosh(k_i\cdot h)} \cos(k_i\cdot(x\cdot \cos(\gamma_j)+ y\cdot \sin(\gamma_j))-\omega_i\cdot t+\phi_{i,j}) (7.37)

7.3.7.2 En profondeur infinie

Lorsque kih>3k_i\cdot h >3, les cosinus hyperboliques peuvent être considérés comme équivalents à des exponentielles (erreur relative inférieure à 2.5×1032.5\times 10^{-3}). On peut donc utiliser l’approximation suivante:

u=gi=1nfreqj=1ndirkiωiai,jekizcos(γj)sin(k(xcos(γj)+ysin(γj))ωit+ϕi,j) u = g \sum_{i=1}^{nfreq}\sum_{j=1}^{ndir}\frac{k_i}{\omega_i} a_{i,j} e^{-k_i z} \cdot\cos(\gamma_j) \sin(k\cdot(x\cdot \cos(\gamma_j)+ y\cdot \sin(\gamma_j))-\omega_i\cdot t+\phi_{i,j}) (7.38)

v=gi=1nfreqj=1ndirkiωiai,jekizsin(γj)sin(k(xcos(γj)+ysin(γj))ωit+ϕi,j) v = g \sum_{i=1}^{nfreq}\sum_{j=1}^{ndir}\frac{k_i}{\omega_i} a_{i,j} e^{-k_i z} \cdot\sin(\gamma_j) \sin(k\cdot(x\cdot \cos(\gamma_j)+ y\cdot \sin(\gamma_j))-\omega_i\cdot t+\phi_{i,j}) (7.39)

w=gi=1nfreqj=1ndirkiωiai,jekizcos(k(xcos(γj)+ysin(γj))ωit+ϕi,j) w = g \sum_{i=1}^{nfreq}\sum_{j=1}^{ndir}\frac{k_i}{\omega_i} a_{i,j} e^{-k_i z} \cos(k\cdot(x\cdot \cos(\gamma_j)+ y\cdot \sin(\gamma_j))-\omega_i\cdot t+\phi_{i,j}) (7.40)

7.3.7.3 Évolution de la vitesse orbitale sur la surface libre

L’expression de l’élévation de la surface libre contient un terme en sinus. Les vitesses orbitales en uu et en ww contiennent des termes en cosinus et sont donc déphasées par rapport à l’élévation. La composante vv de la vitesse orbitale, en revanche, est en phase avec l’élévation. Le schéma suivant représente l’élévation de la houle (en vert) avec les vecteurs vitesse orbitale (en bleu) en plusieurs points de la surface libre dans le plan (X,Z) :

7.3.8 Paramétrisation des modèles de houle

Les spectres directionnels de houle d’Airy sont paramétrés de la façon suivante :

- model: airy
  depth: {value: 100, unit: m}
  seed of the random data generator: 0
  stretching:
     delta: 0
     h: 100
  directional spreading:
     type: dirac
     waves propagating to: {value: 90, unit: deg}
  spectral density:
     type: jonswap
     Hs: {value: 5, unit: m}
     Tp: {value: 15, unit: s}
     gamma: 1.2

7.4 Densités spectrales de puissance

La formulation des spectres de houles a été développée de façon semi-empirique depuis les années 50. Suivant le spectre, l’état de mer peut être complètement formé (à la limite, le spectre n’a qu’un seul paramètre) ou une combinaison de la houle (swell) et de la mer du vent (wind sea) à six paramètres.

Le choix du spectre dépend donc à la fois du lieu considéré et de l’état de mer. Ce choix revêt une grande importance pour la prévision des mouvements des plateformes la réponse du navire va varier suivant le type d’état de mer. Il faut noter que l’on ne peut pas faire varier l’état de mer au cours d’une même simulation.

7.4.1 Dirac

La plus simple densité spectrale de puissance est aussi la moins réaliste car elle correspond à une houle monochromatique, c’est-à-dire à une seule fonction sinusoïdale :

ω0+,ω+,S(ω)={0,si ωω01,si ω=ω0 \omega_0\in\mathbb{R}^+,\forall \omega\in\mathbb{R}^+, S(\omega) = \left\{\begin{array}{l}0, \textrm{si }\omega\neq \omega_0\\1, \textrm{si } \omega=\omega_0\end{array}\right. (7.41)

ω0=2πf\omega_0 = 2\pi f est la pulsation (en Rad/s) de la houle.

Le signal temporel correspondant a l’allure suivante :

Le paramétrage de ce spectre est :

spectral density:
    type: dirac
    Hs: {value: 5, unit: m}
    omega0: {value: 15, unit: rad/s}

La hauteur de houle est donnée par Hs et sa pulsation par omega0. L’amplitude de la houle sera égale à Hs/2.

Ce spectre a essentiellement un intérêt pour l’établissement de fonctions de transfert ou la comparaison de réponses sur une houle maitrisée mais il n’est pas représentatif de conditions réelles.

7.4.2 Bretschneider

La fonction analytique la plus souvent utilisée pour représenter des états de mer partiellement ou totalement développés a été proposée en 1959 par Bretschneider. Initialement, la dépendance à la période de la houle était mise en exergue et s’exprimait sous la forme :

S(T)=αT3eβT4 S(T)=\alpha\cdot T^3\cdot e^{-\beta T^4} (7.42)

Aujourd’hui, on préfère une formulation fréquentielle :

S(ω=2πT)=Aω5eBω4 S\left(\omega=\frac{2\pi}{T}\right) = \frac{A}{\omega^5}\cdot e^{-\frac{B}{\omega^4}} (7.43)

Le moment d’ordre 0 permet d’obtenir une relation entre AA et BB :

m0=0S(ω)dω=[eBω4]0=A4B m_0 = \int_0^\infty S(\omega) d\omega = \left[-e^{-\frac{B}{\omega^4}}\right]^\infty_0=\frac{A}{4B} (7.44)

d’où

A=4m0B A=4m_0 B (7.45)

Par ailleurs, la dérivée première du spectre s’annule pour une période ωp\omega_p :

ddωS(ω)=Aω6eBω4(4Bω45) \frac{d}{d\omega}S(\omega) = \frac{A}{\omega^6}e^{-\frac{B}{\omega^4}}\left(\frac{4B}{\omega^4}-5\right) (7.46)

d’où

B=54ωp4 B=\frac{5}{4}\omega_p^4 (7.47)

et

ωp=(45B)1/4 \omega_p=\left(\frac{4}{5}B\right)^{1/4} (7.48)

De plus, on constate empiriquement que les hauteurs de houle sont souvent distribuées suivant une loi de Rayleigh (loi de la norme d’un vecteur dont les deux composantes suivent une loi normale) de variance σ2=4m0\sigma^2=4 m_0 et, sous cette hypothèse, la hauteur de houle HSH_S correspondant à deux écarts-types est :

HS=2σ=4m0 H_S = 2\sigma = 4\sqrt{m_0} (7.49)

En outre, ωp=2πTp\omega_p=\frac{2\pi}{T_p}

On peut ainsi exprimer AA et BB en fonction de HSH_S et TpT_p :

A=5π4HS2Tp4 A=\frac{5\pi^4H_S^2}{T_p^ 4} (7.50)

B=20π4Tp4 B=\frac{20\pi^4}{T_p^4} (7.51)

Ce spectre a l’allure suivante :

Sa paramétrisation dans xdyn est réalisée au moyen du YAML suivant :

spectral density:
    type: bretschneider
    Hs: {value: 5, unit: m}
    Tp: {value: 15, unit: s}

7.4.3 Pierson-Moskowitz

À la fin des années 40, plusieurs navires météorologiques étaient stationnés dans l’océan Pacifique et l’Atlantique Nord. Ces navires notaient la météo quotidiennement sous forme d’un code météo. En 1961, Tucker créa une méthode pour obtenir des estimations quantitatives à partir de ces enregistrements en corrélant la fréquence d’occurrence des différents codes météo avec les observations météo de plusieurs stations à terre. En 1964, Willard Pierson et Lionel Moskowitz à l’université de New York, ont préparé un rapport pour l’U.S. Naval Oceanographic Office analysant un grand nombre d’enregistrements en Atlantique Nord. Seuls les enregistrements pour des mers complètement développées ayant été considérés, c’est un spectre adapté à de tels états de mer. Il s’écrit sous la forme :

S(ω)=αg2ω5exp(β[gU19.5ω]4) S(\omega) = \frac{\alpha\cdot g^2}{\omega^5} \exp{\left(-\beta\left[\frac{g}{U_{19.5}\omega}\right]^4\right)} (7.52)

α=8.1103\alpha = 8.1\cdot 10^{-3} désigne la constante de Phillips, gg l’accélération de la gravité terrestre, U19.5U_{19.5} la vitesse du vent à 19.5 mètres au-dessus du niveau de la mer et β\beta vaut 0.74.

Ce spectre est un cas particulier du spectre de Bretschneider en prenant

A=8.1103g2 A=8.1\cdot 10^{-3}\cdot g^2 (7.53)

et

B=0.74(gU19.5)4 B=0.74\left(\frac{g}{U_{19.5}}\right)^4 (7.54)

Par la suite, les données de Pierson et Moskowitz ont été ré-analysées pour établir la relation empirique suivante entre la vitesse du vent et la pulsation modale de la houle :

0.74(gU19.5)4=54ω04 0.74 \left(\frac{g}{U_{19.5}}\right)^4=\frac{5}{4}\omega_0^4 (7.55)

d’où

ωp=0.877gU19.5 \omega_p=0.877\frac{g}{U_{19.5}} (7.56)

On peut obtenir une expression de la période de pic ωp\omega_p uniquement en fonction de HSH_S en se servant des relations suivantes, établies pour le spectre de Bretschneider :

En supposant que les hauteurs de houle suivent une distribution de Rayleigh, on a:

HS=4m0=4A4B H_S=4\sqrt{m_0}=4\sqrt{\frac{A}{4B}} (7.57)

d’où

B=4AHS2 B=\frac{4 A}{H_S^2} (7.58)

ωp=(45B)1/4=(4A5HS2)1/4=(1658.1103)1/4gHS \omega_p=\left(\frac{4}{5}B\right)^{1/4}=\left(\frac{4A}{5H_S^2}\right)^{1/4}=\left(\frac{16}{5}\cdot 8.1\cdot 10^{-3}\right)^{1/4}\sqrt{\frac{g}{H_S}} (7.59)

soit

ωp=0.4gHS \omega_p=0.4\sqrt{\frac{g}{H_S}} (7.60)

Ce spectre était le spectre de référence pendant de nombreuses années mais il n’est valable que pour des états de mer complètement développés et des mers résultants de vents modérés sur des fetchs très grands. Pour les conditions plus fréquentes de vents forts sur des fetchs courts, notamment en mer du Nord, des spectres à au moins deux paramètres sont plus adaptés.

Ce spectre a l’allure suivante :

Sa paramétrisation dans xdyn est réalisée au moyen du YAML suivant :

spectral density:
    type: pierson-moskowitz
    Hs: {value: 5, unit: m}
    Tp: {value: 15, unit: s}

7.4.4 JONSWAP

Le spectre JONSWAP (Joint North Sea Wave Project) a été proposé en 1973 par Hasselmann et al. après avoir dépouillé des mesures faites lors de la formation de tempêtes en Mer du Nord. Plus de 2000 spectres ont ainsi été mesurés et une méthode des moindres carrés a été utilisée pour obtenir une formulation spectrale. Il est valable pour des fetchs limités et des vitesses de vent uniformes. L’importance de ce spectre vient de ce qu’il prend en compte le développement des vagues sur un fetch limité d’une part, et, d’autre part, l’atténuation des vagues par petits fonds. Ce spectre est souvent utilisé par l’industrie offshore en mer du Nord.

S(ω)=(10.287log(γ))516αωHS2e1.25(ω0ω)4γr S(\omega)=(1-0.287 \log(\gamma))\frac{5}{16}\frac{\alpha}{\omega}H_S^2 e^{-1.25\left(\frac{\omega_0}{\omega}\right)^4}\gamma^r (7.61)

avec

r=e0.5(ωω0σω0)2 r=e^{-0.5\left(\frac{\omega-\omega_0}{\sigma\omega_0}\right)^2} (7.62)

et

σ={0.07,ωω00.09,ω>ω0 \sigma=\left\{\begin{array}{l}0.07,\omega\leq\omega_0\\0.09,\omega>\omega_0\end{array}\right. (7.63)

Ce spectre a l’allure suivante :

Sa paramétrisation dans xdyn est réalisée au moyen du YAML suivant :

spectral density:
    type: jonswap
    Hs: {value: 5, unit: m}
    Tp: {value: 15, unit: s}
    gamma: 1.2

7.5 Étalements directionnels

7.5.1 Dirac

Lorsque cet étalement est choisi, la houle est mono-directionnelle.

directional spreading:
    type: dirac
    waves propagating to: {value: 90, unit: deg}

La direction de propagation est donnée par waves propagating to, dans le repère NED (0° correspond à des vagues se propageant du Sud vers le Nord, 45° à des vagues se propageant du Sud-Ouest au Nord-Est, -90° à des vagues se propageant de l’Est vers l’Ouest). Il n’y a pas de bornes particulières pour cette angle (outre la taille maximale des flottants).

7.5.2 Cos2s

L’étalement est donné par :

γcos2s(γγ0) \gamma\mapsto \cos^{2s}\left({\gamma-\gamma_0}\right) (7.64)

γ0\gamma_0 est la direction de propagation, dans le repère NED (0° correspond à des vagues se propageant du Sud vers le Nord, 45° à des vagues se propageant du Sud-Ouest au Nord-Est, -90° à des vagues se propageant de l’Est vers l’Ouest). Il n’y a pas de bornes particulières pour cet angle (outre la taille maximale des flottants).

Cet étalement est paramétré de la façon suivante :

directional spreading:
    type: cos2s
    s: 2
    waves propagating to: {value: 90, unit: deg}

La direction de propagation γ0\gamma_0 est donnée par waves propagating to.

7.6 Stretching de la houle

7.6.1 Description

La formulation d’Airy n’est pas valable au-dessus du plan z=0z=0. Cela signifie que l’on ne peut pas l’utiliser dans une formulation non-linéaire où l’on cherche à connaître les pressions dynamiques et les vitesses orbitales pour z<0z<0. Les modèles de stretching sont une solution de contournement qui consiste à prendre comme référence non pas le plan z=0z=0 mais la surface libre déformée.

7.6.2 Utilisation dans xdyn

Pour mémoire, la paramétrisation du modèle de houle est effectuée par un YAML du type :

- model: airy
  depth: {value: 100, unit: m}
  seed of the random data generator: 0
  stretching:
     delta: 0
     h: {unit: m, value: 100}
  directional spreading:
     type: dirac
     waves propagating to: {value: 90, unit: deg}
  spectral density:
     type: jonswap
     Hs: {value: 5, unit: m}
     Tp: {value: 15, unit: s}
     gamma: 1.2

Dans xdyn, le stretching est renseigné dans la section stretching des modèles de houle. Le seul modèle de stretching implémenté est le delta-stretching et ses dérivés (absence de stretching, extrapolation linéaire et modèle de Wheeler). La section stretching contient les paramètres h et delta du modèle de delta-stretching:

7.6.3 Justifications théoriques

Sous les hypothèses du modèle de houle irrégulière linéaire détaillées ci-dessus, la vitesse orbitale des particules d’eau par rapport au référentiel NED (projetée sur l’axe XX du repère BODY) s’écrit :

u=gi=1nfreqj=1ndirkiωiai,jcosh(k(hz))cosh(kh)cos(γj)sin(k(xcos(γj)+ysin(γj))ωit+ϕi,j) u = g \sum_{i=1}^{nfreq}\sum_{j=1}^{ndir}\frac{k_i}{\omega_i} a_{i,j} \frac{\cosh(k\cdot(h-z))}{\cosh(k\cdot h)}\cdot\cos(\gamma_j) \sin(k\cdot(x\cdot \cos(\gamma_j)+ y\cdot \sin(\gamma_j))-\omega_i\cdot t+\phi_{i,j}) (7.65)

qui, en profondeur infinie, s’écrit :

u=gi=1nfreqj=1ndirkiωiai,jekizcos(γj)sin(k(xcos(γj)+ysin(γj))ωit+ϕi,j) u = g \sum_{i=1}^{nfreq}\sum_{j=1}^{ndir}\frac{k_i}{\omega_i} a_{i,j} e^{-k_i z} \cdot\cos(\gamma_j) \sin(k\cdot(x\cdot \cos(\gamma_j)+ y\cdot \sin(\gamma_j))-\omega_i\cdot t+\phi_{i,j}) (7.66)

Cette expression est basée sur la théorie linéaire, qui suppose a priori la surface libre plane, y compris pour le calcul de la déformation de surface libre, qui est une grandeur comme les autres (pressions, vitesses, potentiel), résultat de la résolution du problème.

La formulation mathématique du problème qui conduit aux expressions ci-dessus n’est pas valable pour les z>0 (linéarisation de la condition de surface libre). Une difficulté survient quand on veut exploiter cette formule dans une modélisation non-linéaire, c’est-à-à dire en modélisant réellement la déformation de la surface libre. En effet, la valeur du terme ekize^{-k_i z} est inférieure à 1 pour les points en-dessous du niveau moyen (surface z=0z=0), mais elle croît rapidement pour les points situés au-dessus de ce plan , et ce d’autant plus que le nombre d’onde kk est grand, tandis qu’elle décroît en-dessous du niveau moyen de la mer. Ainsi, pour deux points proches sur la surface libre (non-horizontale) l’un à z>0z>0 et l’autre à z<0z<0, la vitesse orbitale sera très différente : les contributions des composantes haute fréquence de la houle seront fortement amplifiées pour le point à z>0z>0 et fortement atténuées pour le point à z<0z<0. Les particules au-dessus du niveau moyen de la mer (notamment sur la crête des vagues) seront ainsi vues comme oscillant à des fréquences élevées tandis que celles dans le creux des vagues oscilleront plus lentement : le niveau moyen de la mer agit donc comme une frontière entre l’amplification et l’atténuation des hautes fréquences, ce qui n’est pas physique (mais cohérent avec la modélisation linéarisée initiale).

Les grandeurs linéaires ne sont donc pas définies dans les zones déformées. Pour pallier cet inconvénient, on peut utiliser des modèles dits de “stretching”, qui permettent de recaler les vitesses orbitales à l’interface eau-air (le sommet ou le creux des vagues) d’une des façons décrites ci-dessous. Certaines de ces méthodes reviennent à étirer l’axe zz (d’où le nom de stretching). Ce qui suit est une présentation non-exhaustive de quelques modèles de stretching (extrapolation linéaire, modèle de Wheeler et delta-stretching).

7.6.3.1 Stretching linéaire sans extrapolation

Outre l’absence de stretching, le modèle le plus simple revient à bloquer la vitesse orbitale au-dessus du niveau de la mer z=0z=0 :

z0,u(x,y,z,t)=u(x,y,0,t) \forall z\leq 0, u(x,y,z,t) = u(x,y,0,t) (7.67)

On obtient ainsi une rupture du profil de vitesse peu physique. Ce modèle n’est pas implémenté dans xdyn.

7.6.3.2 Stretching par extrapolation linéaire

Ce modèle revient à prolonger le modèle de vitesse par une tangente :

u(x,y,z,t)u(x,y,0,t)zuz(x,y,0,t) u(x,y,z,t) \sim u(x,y,0,t) - z\cdot \frac{\partial u}{\partial z} (x,y,0,t) (7.68)

Ce modèle peut être utilisé dans xdyn en fixant h à la profondeur d’eau depth et delta: 1.

7.6.3.3 Stretching de Wheeler

La vitesse orbitale s’écrit :

u=gi=1nfreqj=1ndirkiωiai,jf(z)cos(γj)sin(k(xcos(γj)+ysin(γj))ωit+ϕi,j) u = g \sum_{i=1}^{nfreq}\sum_{j=1}^{ndir}\frac{k_i}{\omega_i} a_{i,j} f(z) \cdot\cos(\gamma_j) \sin(k\cdot(x\cdot \cos(\gamma_j)+ y\cdot \sin(\gamma_j))-\omega_i\cdot t+\phi_{i,j}) (7.69)

avec

f(z)=cosh(k(hz))cosh(kh) f(z)=\frac{\cosh(k\cdot(h-z))}{\cosh(k\cdot h)} (7.70)

On souhaite après stretching retrouver les valeurs de vitesse orbitales données par ff à la surface (en z=ηz=\etaxi, η\eta désignant la hauteur d’eau donnée par le modèle de houle) et au fond (en z=hz=h):

On cherche donc une fonction gg telle que :

g(z=η)=f(0) g(z=\eta)=f(0) (7.71)

g(z=h)=f(h) g(z=h)=f(h) (7.72)

On peut construire une telle fonction en prenant

g(z)=f(z(z)) g(z) = f(z'(z)) (7.73)

avec z(η)=0z'(\eta)=0 et z(h)=hz'(h)=h.

On peut par exemple choisir une fonction zzz\mapsto z' linéaire :

z(z)=hhη(zη) z'(z)=\frac{h}{h-\eta}(z-\eta) (7.74)

ce qui donne le profil de vitesse (projetée ici sur l’axe XX du repère body) :

u=gi=1nfreqj=1ndirkiωiai,jcosh(khhzhη(x,y,t))cosh(kh)cos(γj)sin(k(xcos(γj)+ysin(γj))ωit+ϕi,j) u = g \sum_{i=1}^{nfreq}\sum_{j=1}^{ndir}\frac{k_i}{\omega_i} a_{i,j} \frac{\cosh\left(k\cdot h\frac{h-z}{h-\eta(x,y,t)}\right)}{\cosh(k\cdot h)} \cdot\cos(\gamma_j) \sin(k\cdot(x\cdot \cos(\gamma_j)+ y\cdot \sin(\gamma_j))-\omega_i\cdot t+\phi_{i,j}) (7.75)

La vitesse orbitale sur les autres axes est donnée par des formules similaires.

Dans ce modèle, la masse n’est pas conservée car le laplacien du potentiel de vitesse n’est pas nul. Il n’y a donc pas de justification théorique à ce modèle de stretching. Son utilisation découle plus de son intérêt pratique : on constate expérimentalement que les vitesses orbitales calculées sans stretching sont plus loin des résultats expérimentaux que celles calculées avec stretching.

Dans le cas du modèle de Wheeler, des campagnes d’essais montrent que les vitesses orbitales calculées dans les crêtes sont quelque peu sous-estimées par rapport aux mesures.

Ce modèle étant une forme particulière du modèle de delta-stretching, on peut l’utiliser dans xdyn en fixant hh à la profondeur de l’eau depth et delta: 0.

7.6.3.4 Stretching de Chakrabarti

Dans ce modèle, on n’agit que sur la profondeur d’eau au dénominateur de la fonction ff

f(z)=cosh(k(hz))cosh(kh) f(z)=\frac{\cosh(k\cdot(h-z))}{\cosh(k\cdot h)} (7.76)

On remplace cosh(kh)\cosh(k\cdot h) par cosh(k(h+η(x,y,t)))\cosh(k\cdot (h+\eta(x,y,t))). Sur l’axe XX du repère body, par exemple, on obtient ainsi le profil :

u=gi=1nfreqj=1ndirkiωiai,jcosh(k(hz))cosh(k(h+η(x,y,t)))cos(γj)sin(k(xcos(γj)+ysin(γj))ωit+ϕi,j) u = g \sum_{i=1}^{nfreq}\sum_{j=1}^{ndir}\frac{k_i}{\omega_i} a_{i,j} \frac{\cosh(k\cdot(h-z))}{\cosh(k\cdot (h+\eta(x,y,t)))} \cdot\cos(\gamma_j) \sin(k\cdot(x\cdot \cos(\gamma_j)+ y\cdot \sin(\gamma_j))-\omega_i\cdot t+\phi_{i,j}) (7.77)

La vitesse sur les autres axes est donnée par des formules similaires.

On constate expérimentalement que, tout comme le modèle de Wheeler, le modèle de Chakrabarti sous-estime les vitesses orbitales dans les crêtes.

Ce modèle n’étant pas un dérivé du modèle de delta-stretching, il n’est pas accessible dans xdyn.

7.6.3.5 Delta-stretching

Il s’agit d’une généralisation du modèle de Wheeler qui permet de passer continument de ce dernier au modèle d’extrapolation linéaire. En jouant sur ses paramètres, on peut retrouver trois modèles de stretching (pas de stretching, extrapolation linéaire et modèle de Wheeler) et c’est pour cela qu’il a été choisi comme modèle de référence dans xdyn.

Tout comme le modèle de Wheeler, on souhaite retrouver la vitesse orbitale à la surface au creux et à la crête des vagues, c’est-à-dire en z=ηz=\eta. Les auteurs de ce modèle, Rodenbusch et Forristal, ajoutent deux paramètres au modèle de Wheeler :

zz' varie de hΔh_{\Delta} à Δη\Delta\eta lorsque zz varie de hΔh_{\Delta} à η\eta.

On prend donc :

7.6.3.6 Choix du modèle de stretching

Comme les modèles de stretching n’ont pas vraiment de justification théorique, la seule manière de les choisir est de comparer directement avec les profils de vitesse mesurés. Les campagnes d’essai réalisées jusqu’à présent n’ont pas permis de choisir de façon catégorique un modèle de stretching plutôt qu’un autre. Ceci vient à la fois de la difficulté de réaliser l’expérimentation en conditions contrôlées et d’obtenir une mesure fiable, mais aussi de l’importance des phénomènes non-linéaires, absents des modèles de stretching.

Les trois graphes ci-dessous montrent l’influence du modèle de stretching sur la pression dynamique (et montrent aussi qu’il n’est pas pris en compte dans le calcul de la vitesse orbitale).

7.6.3.6.1 Sans stretching
7.6.3.6.2 Extrapolation linéaire
7.6.3.6.3 Stretching de Wheeler

7.7 Discrétisation des spectres et des étalements

Les étalements et les spectres présentés précédemment sont continus. Afin d’en réaliser l’implémentation informatique, il faut les discrétiser. Si l’on répartit uniformément les pulsations sur un intervalle, on introduit une périodicité temporelle de la houle (cela revient en effet à effectuer une transformée de Fourier inverse, qui donne par construction un résultat périodique). Afin d’être plus représentatif des états de mers réels, on peut souhaiter rompre cette périodicité en discrétisant les pulsations de manière aléatoire. On obtient ainsi un signal apériodique.

La performance de l’implémentation des modèles de houle est cruciale : en effet, la pression dynamique et la pression statique étant intégrées sur toutes les facettes du maillage (dans le cas d’un modèle non-linéaire), ces modèles sont évalués de nombreuses fois par pas de calcul. Comme le nombre de composantes sommées pour calculer les élévations et pressions dynamiques est potentiellement important, on ne sélectionne que les produits S(ωi)D(γj)S(\omega_i)D(\gamma_j) contribuant de manière significative à l’énergie totale. Pour ce faire, on classe ces produits par ordre décroissant et l’on sélectionne les nn premiers de façon à ce que leur somme représente une fraction prédéterminée de la puissance totale. De cette manière, on réduit considérablement les temps de calcul, tout en gardant une bonne représentativité de la physique du problème. Cependant, cette technique n’est pas toujours applicable, suivant la réponse à laquelle on s’intéresse. En effet, un petit corps dans la houle peut avoir une réponse très affectée par les composantes peu énergétiques (en relatif), par exemple pour des problèmes de mouille ou d’impact. De même, les réponses locales d’un grand corps (slamming, efforts sur des appendices, etc.), peuvent être affectées par des composantes peu énergétiques.

La discrétisation est paramétrée de la façon suivante :

discretization:
    n: 128
    omega min: {value: 0.1, unit: rad/s}
    omega max: {value: 6, unit: rad/s}
    energy fraction: 0.999

7.8 Sorties

On peut sortir les hauteurs de houle calculées sur un maillage (défini dans un repère fixe ou mobile). En fait, on peut même choisir de ne faire qu’une simulation de houle, sans corps, tel que décrit dans le tutoriel 3.

On définit un maillage (cartésien) sur lequel sera calculée la houle (dans la section environment/model/output). Par exemple :

output:
    frame of reference: NED
    mesh:
        xmin: {value: 1, unit: m}
        xmax: {value: 5, unit: m}
        nx: 5
        ymin: {value: 1, unit: m}
        ymax: {value: 2, unit: m}
        ny: 2

Dans l’exemple précédent, les coordonnées sont données dans le repère NED. Le maillage comporte 10 points : (1,1),(1,2),(2,1),(2,2),(3,1),(3,2),(4,1),(4,2),(5,1),(5,2).

Les sorties sont écrites dans le fichier et le format spécifiés dans la section output déjà définie à la racine du fichier YAML.

On obtient deux résultats différents, suivant que le repère dans lequel ils sont exprimés est mobile ou fixe par rapport au repère NED. En effet, si le repère est fixe, il est inutile de répéter les coordonnées x et y.

Dans le cas d’un repère fixe, on obtient une sortie de la forme :

waves:
  x: [1,2,3,4,5,1,2,3,4,5]
  y: [1,1,1,1,1,2,2,2,2,2]
  timesteps:
    - t: 0
    - z: [-4.60386,-4.60388,-4.6039,-4.60392,-4.60393,-4.6553,-4.65531,-4.65533,-4.65535,-4.65537]
    - t: 1
    - z: [-3.60794,-3.60793,-3.60793,-3.60792,-3.60791,-3.68851,-3.6885,-3.6885,-3.68849,-3.68849]

x et y désignent les coordonnées (exprimées en mètres) dans le repère choisi (ici il s’agit du NED) des points du maillage. t désigne l’instant auquel les hauteurs de houle ont été calculées. z est la hauteur de houle, c’est-à-dire la distance entre un point de coordonnées (x,y,0) et le même point situé sur la surface libre. Une valeur positive dénote une houle en-dessous de z=0 (creux) et une valeur négative une valeur au-dessus de z=0 (bosse).

Si le repère de sortie est mobile, on obtient plutôt un résultat de la forme :

waves:
  timesteps:
    - t: 0
      x: [1,2,3,4,5,1,2,3,4,5]
      y: [1,1,1,1,1,2,2,2,2,2]
    - z: [-4.60386,-4.60388,-4.6039,-4.60392,-4.60393,-4.6553,-4.65531,-4.65533,-4.65535,-4.65537]
    - t: 1
      x: [2,4,5,6,7,2,4,5,6,7]
      y: [1,1,1,1,1,2,2,2,2,2]
    - z: [-3.60794,-3.60793,-3.60793,-3.60792,-3.60791,-3.68851,-3.6885,-3.6885,-3.68849,-3.68849]

7.9 Utilisation d’un modèle de houle distant

xdyn permet d’utiliser des modèles de houle sur un serveur distant. L’intérêt est que l’on peut ainsi mettre en oeuvre des modèles de houle qui ne sont pas implémentés dans le code d’xdyn. Ces modèles peuvent être implémentés dans le langage informatique que l’on souhaite (Python, Java, Go…) et utilisables comme les modèles de houle “internes” de xdyn.

7.9.1 Technologie utilisée

La technologie utilisée pour ce faire s’appelle “gRPC” et permet de définir rapidement des services en C++, Java, Python, Ruby, Node.js, C#, Go, PHP ou Objective-C. Le code d’interfaçage est généré automatiquement pour des clients écrits dans chacun de ces langages (dans le cas d’xdyn, du C++). On obtient ainsi :

Ainsi, les modèles de houle externes qui respectent cette interface peuvent être utilisés, outre par xdyn, par des applications clientes écrites en Python, en C++, en Java… Par exemple, on pourrait implémenter un modèle de capteur de houle en Java en utilisant un modèle de houle externe écrit, mettons, en Python.

7.9.2 Interface pour les modèles de houle

Le fichier de définition de l’interface des modèles de houle est disponible à l’adresse suivante :

https://gitlab.sirehna.com/sirehna/demo_docker_grpc/blob/master/waves.proto

Ce fichier est nécessaire si l’on souhaite implémenter un modèle de houle distant (un serveur de houle) appelable par xdyn, mais il n’est pas nécessaire pour utiliser depuis xdyn un modèle de houle existant satisfaisant cette interface.

7.9.3 Paramétrage dans xdyn

Un modèle sans paramètre tournant sur un serveur accessible à l’adresse http://localhost:50001 est paramétré comme suit :

- model: grpc
  url: http://localhost:50001

Si le modèle de houle contient des paramètres, ceux-ci doivent figurer à la suite dans le fichier YAML d’xdyn et ils sont transmis directement au serveur sans être interprêtés par xdyn. Par exemple, un modèle d’Airy unidirectionnel avec un spectre de JONSWAP pourrait être paramétré de la façon suivante :

- model: grpc
  url: http://localhost:50001
  Hs: 5
  Tp: 15
  gamma: 1.2
  seed of the random data generator: 0
  waves propagating to: 90

7.9.4 Exemple d’utilisation

Le tutoriel 9 détaille la mise en oeuvre de la simulation.

7.10 Références

8 Métacentre

8.1 Définitions

(définitions valables dans ce chapitre)

Le métacentre MM est un point défini comme l’intersection des axes d’application de la force d’Archimède pour de petites variations d’inclinaison. La distance algébrique entre le centre de gravité GG d’un navire et son métacentre MM, notée GM¯\overline{GM}, permet de caractériser la stabilité d’un navire :

8.2 Utilisation dans xdyn

Le calcul du GM est réalisé par le simulateur à l’aide d’un modèle d’effort particulier appelé “GM”. Ce modèle se contente de calculer GZ pour deux positions voisines pour en déduire GM par dérivation numérique. Il utilise pour le calcul de GZ un modèle hydrostatique (non-linear hydrostatic (fast) ou non-linear hydrostatic (exact)) spécifié en paramètre. Pour éviter de calculer trois fois les efforts hydrostatiques (une fois pour la simulation elle-même et deux fois pour le calcul du GM), il a été choisi de faire du modèle GM un modèle hydrostatique particulier. Ainsi, il doit être utilisé à l’exclusion de tout autre modèle hydrostatique.

Le modèle évalue GZ pour l’état courant et modifie ensuite l’angle θ\theta d’une valeur dθ\theta spécifiée en paramètre puis approche GM par

GM=GZ(θ+dθ)GZ(θ)dθ GM = \frac{GZ(\theta+d\theta)-GZ(\theta)}{d\theta} (8.1)

Voici un exemple de paramétrisation :

external forces:
      - model: GM
        name of hydrostatic force model: non-linear hydrostatic (fast)
        roll step: {value: 1, unit: degree}

8.3 Fondements théoriques

Le métacentre est défini comme l’intersection des axes d’application de la force d’Archimède pour de petites variations d’inclinaison, ou, autrement dit, le point où la résultante de la pression que l’eau exerce sur le navire (gîté, c’est-à-dire incliné) rencontre le plan médian de celui-ci. Pour que cette définition ait un sens, il convient de préciser dans quelles conditions ces axes se coupent.

8.3.1 Preuve d’existence du métacentre

Si l’on considère deux positions du navire X0,X1X_0,X_1 et un plan d’inclinaison quelconque (non-horizontal), on peut calculer la projection de la droite d’action de la résultante des efforts hydrostatiques pour X0X_0 et X1X_1 sur ce plan d’inclinaison. Les droites se coupent en un point appelé point métacentrique. Sans hypothèse supplémentaire, ce point n’a pas d’autre propriété particulière.

Si l’on se place dans les conditions d’applicabilité du théorème d’Euler (positions isocarènes infiniment voisines) et que l’on suppose que l’une des positions est une position d’équilibre, le plan contenant les centres de carène correspondant à ces positions (notés respectivement B0B_0 et B1B_1) et le centre de gravité GG est vertical puisque B0B_0 est à la verticale de GG. En outre, il existe une rotation permettant de passer d’une position à l’autre (d’après le théorème d’Euler). Le plan de cette rotation n’est pas forcément le plan (G,B0,B1)(G,B_0,B_1). Si l’on ajoute une hypothèse de symétrie transversale et longitudinale (coque amphidrome), alors ces deux plans sont nécessairement confondus. Dans ce cas, le point métacentrique est à l’intersection des droites d’action des efforts hydrostatiques (et non plus simplement de leur projection). On peut alors écrire :

GZ=GMsin(α) GZ = GM\sin(\alpha) (8.2)α\alpha désigne l’angle de la rotation isocarène.

Lorsque l’angle d’inclinaison α\alpha tend vers 0, le point métacentrique HH tend vers un point appelé métacentre.

8.3.2 Définitions

8.3.2.1 Plan de flottaison

Plan de la surface libre du liquide au repos

8.3.2.2 Flottaison

Intersection du flotteur et du plan de flottaison

8.3.2.3 Ligne de flottaison

Périmètre de la flottaison

8.3.2.4 Centre de flottaison

Centre de gravité de la flottaison

8.3.2.5 Carène

Partie immergée du flotteur, située au-dessous du plan de flottaison. Son centre de gravité CC est appelé “centre de carène”. C’est le point d’application des efforts hydrostatiques.

8.3.2.6 Flottaisons isocarènes

Flottaisons limitant des carènes de même volume. On peut démontrer qu’il existe une flottaison isocarène.

8.3.2.7 Axe d’inclinaison

Intersection de deux flottaisons isocarènes infiniment voisines.

8.3.2.8 Enveloppe des flottaisons isocarènes

Enveloppe de la famille des plans constitués de toutes les flottaisons isocarènes.

8.3.2.9 Surface des poussées

Lieu des centres de carène correspondant à toutes les flottaisons isocarènes. Si l’on suppose la surface des poussées convexe (ce qui n’est pas forcément le cas, comme le montre Thearle dans Theoretical Naval Architecture), on peut l’approcher localement par une sphère osculatrice dont le rayon est le rayon de courbure de la surface. Le centre de cette sphère est le métacentre.

8.3.3 Caractérisation

8.3.3.1 Caractérisation de la surface de flottaison : théorème d’Euler

Le théorème d’Euler stipule que le centre de flottaison correspondant à une position du flotteur est aussi le centre de flottaison d’une position isocarène infiniment voisine. Un corollaire de ce théorème est que, les flottaisons variant peu et possédant un point fixe (le centre de flottaison), d’après le théorème d’Euler sur les rotations, il existe une rotation permettant de passer de l’une à l’autre.

Le théorème d’Euler fournit aussi une autre caractérisation de la surface de flottaison : les flottaisons isocarènes admettent une surface enveloppe qui est touchée par chacune d’elles au centre de flottaison correspondant. Cette surface enveloppe est la surface de flottaison.

8.3.3.2 Caractérisation de la surface de poussée : théorème de Dupin

Le plan tangent à la surface de poussée au centre de poussée est parallèle à la flottaison correspondante. La poussée hydrostatique est donc normale à la surface de poussée.

Ce théorème fournit une caractérisation de la surface de poussée : les droites d’action des poussées hydrostatiques correspondant à des positions isocarènes sont les normales à une même surface qui est la surface de poussée.

8.3.3.3 Existence d’une position isocarène

Pour toute position de navire, il existe une position isocarène.

Soit en effet X0=(z0,ϕ0,θ0)X_0=(z_0,\phi_0,\theta_0) et X1=(z1,ϕ1,θ1)X_1=(z_1,\phi_1,\theta_1) deux paramètres de flottaison tels que ϕ0ϕ1\phi_0\neq\phi_1 et θ0θ1\theta_0\neq\theta_1. Soit VmaxV_{\textrm{max}} le volume de la carène lorsque le navire est totalement immergé. On note II l’intervalle [0,Vmax][0,V_{\textrm{max}}].

On note VzV_z l’application partielle Vz:zV(z,ϕ1,θ1)V_z:z\mapsto V(z,\phi_1,\theta_1). VV étant continue par hypothèse, VzV_z l’est aussi. Par ailleurs, on sait que Vz()=0V_z(-\infty)=0 et Vz(+)=VmaxV_z(+\infty)=V_{\textrm{max}} donc d’après le théorème des valeurs intermédiaires, V0I,z2:Vz(z2)=V0\forall V_0\in I, \exists z_2:V_z(z_2)=V_0 ce qui signifie que X0=(z0,ϕ0,θ0)X_0=(z_0,\phi_0,\theta_0) et X1=(z2,ϕ1,θ1)X_1=(z_2,\phi_1,\theta_1) sont isocarènes.

8.3.3.4 Couple de rappel et métacentre : théorème de Bouguer

Le couple de rappel MrM_r est par définition :

Mr=FHSGZ=FHSGMsin(θ) M_r = F_{\textrm{HS}} \cdot GZ = F_{\textrm{HS}} \cdot GM\cdot \sin(\theta) (8.3)

Pour de petites variations isocarènes de θ\theta, le volume ne variant pas, FHSF_{\textrm{HS}} est constante donc

dMr=FHS(sin(θ)dGM+GMcos(θ)dθ) dMr = F_{\textrm{HS}}\cdot(\sin(\theta)dGM + GM\cdot\cos(\theta)d\theta) (8.4)

or

dMr=FHSdGZ dMr = F_{\textrm{HS}}\cdot dGZ (8.5)

d’où

dGZ=sin(θ)dGM+GMcos(θ)dθ dGZ = \sin(\theta)dGM + GM\cdot\cos(\theta)d\theta (8.6)

Comme GMGM est constant,

dGZGMdθ dGZ \sim GM d\theta (8.7)

donc

GMdGZdθ GM\sim \frac{dGZ}{d\theta} (8.8)

On a également le théorème de Bouguer :

GMIOxxV GM\sim \frac{I_{Oxx}}{V} (8.9)

8.3.4 Extension : utilisation du GM en dynamique

Pour utiliser le concept de métacentre pour un navire réel sur houle, il faut s’affranchir des hypothèses précédentes (planéité de la surface libre, petites rotations isocarènes, symétries). On pose alors comme définition (et non plus un approximation au premier ordre) :

GM=dGZdθ GM=\frac{dGZ}{d\theta} (8.10)

Le GMGM donne donc une indication sur le taux de variation du couple de rappel hydrostatique : plus le GMGM est important pour un volume de carène donné, plus le moment de rappel aura tendance à varier rapidement pour de faibles changements d’inclinaison θ\theta.

8.4 Bibliographie

9 Courbes de stabilité

9.1 Stabilité en roulis

On s’intéresse ici à la stabilité du navire en roulis qui constitue une condition de base pour la sécurité du navire, et fait l’objet de réglementations strictes.

On considère un navire partiellement immergé en eau calme (la surface libre étant donc plane et horizontale) dont le volume immergé Ω\Omega est délimité par une surface appelée “carène” (ou surface mouillée) et notée 𝒞\mathcal{C}. On appelle “flottaison” et l’on note SS l’intersection du volume du navire avec le plan de la surface libre. On a donc Ω=𝒞S\partial\Omega = \mathcal{C}\cup S. On note GG le centre de gravité du navire et CC le centre de Ω\Omega (appelé “centre de carène”).

Les axes YY et ZZ du repère “body” sont notés respectivement yy et zz. La situation peut être représentée par la figure suivante :

La distance algébrique GZ=yCyGGZ=y_C-y_G est le bras de levier du couple de rappel hydrostatique. Celui-ci doit être suffisant pour redresser le navire. Une condition nécessaire et suffisante pour que le couple de rappel hydrostatique soit un couple de redressement est que le point métacentrique EE soit situé au-dessus du centre de gravité GG. Le point EE est à l’intersection de la droite CzCz et de la droite C0zC_0 z.

9.1.1 Algorithme de calcul de GZGZ

Pour calculer GZ(ϕ)GZ(\phi), il faut connaître la position du centre de carène pour une position d’équilibre à un angle de gîte ϕ\phi. On commence donc par calculer la position d’équilibre pour une gîte donnée, puis on calcule le centre de carène et GZGZ est ensuite donné par GZ(ϕ)=yC(ϕ)yGGZ(\phi)=y_C(\phi)-y_G.

9.1.1.1 Calcul de la position d’équilibre à une gîte donnée

Soit X=(z,ϕ,θ)X=(z,\phi,\theta) l’état du système. On suppose le navire soumis aux seuls efforts de la gravité et de l’hydrostatique. On note ff la fonction qui à XX associe la somme des efforts appliqués au système :

f(X)=Fhs(X)+m𝐠 f(X) = F_{\textrm{hs}}(X) + m\cdot \mathbf{g} (9.1)

mm désigne la masse du système et 𝐠\mathbf{g} est le vecteur accélération de la pesanteur.

Lorsque le système est à l’équilibre, on a :

f(Xeq)=0 f(X_{\textrm{eq}})=0 (9.2)

Pour résoudre cette équation, on peut par exemple utiliser la méthode de Newton-Raphson :

Xn+1=Xnf(Xn)1f(Xn) X_{n+1} = X_n - f'(X_n)^{-1}f(X_n) (9.3)

On note K(X)=fX(X) K(X) = \frac{\partial f}{\partial X}(X) (9.4)

Xn+1=XnK1(Xn)f(Xn) X_{n+1} = X_n - K^{-1}(X_n)f(X_n) (9.5)

La matrice K(Xn)K(X_n) est estimée numériquement en linéarisant ff autour de XnX_n. Soit ΔX\Delta X un petit déplacement autour de XnX_n et ΔF=(ΔFz,ΔMϕ,ΔMθ)\Delta F = (\Delta F_z, \Delta M_{\phi}, \Delta M_{\theta}) la variation d’effort correspondante.

K(Xn)ΔX=ΔF K(X_n) \Delta X = \Delta F (9.6)

Pour 1i3,j=13kijΔxj=ΔFi1\leq i\leq 3, \sum_{j=1}^3 k_{ij} \Delta x_j = \Delta F_i.

Si le petit déplacement que l’on considère s’effectue exclusivement suivant l’axe jj, on trouve :

kijΔxj=ΔFik_{ij}\Delta x_j = \Delta F_i donc

kij=ΔFiΔxj k_{ij} = \frac{\Delta F_i}{\Delta x_j} (9.7)

En pratique, pour évaluer les termes de la matrice K(Xn)K(X_n), on considère séparément trois petits déplacements autour de XnX_n (un par axe) et l’on utilise la formule précédente pour évaluer les termes kijk_{ij} trois par trois.

Une simplification possible est de considérer que la matrice KK varie peu et donc de ne l’évaluer qu’une seule fois (plutôt qu’à chaque étape de l’algorithme de Newton-Raphson).

9.1.1.2 Calcul du centre de carène CC

La carène est discrétisée par des polygones. Pour calculer son centre de volume, on transforme ces polygones en triangles et, pour chaque triangle, on calcule le volume (algébrique) du tétraèdre de base ce triangle et de sommet l’origine.

En effectuant la somme de ces volumes élémentaires on retrouve le volume délimité par le maillage. Le centre de carène est calculé de la façon suivante.

Soit P1,P2,P3P_1,P_2,P_3 les trois sommets d’un des triangles. Le volume élémentaire dVdV associé à ce triangle est le déterminant des vecteurs P1,P2,P3P_1,P_2,P_3 :

dV=det(P1,P2,P3) dV=\textrm{det}(P_1,P_2,P_3) (9.8)

Les coordonnées du centre (par rapport à l’origine choisie pour les tétraèdres) sont données par :

xC=1facetdVfacetx(P1)+x(P2)+x(P3)4dV x_C = \frac{1}{\sum_{\textrm{facet}}dV}\sum_{\textrm{facet}}\frac{x(P_1)+x(P_2)+x(P_3)}{4}dV (9.9)

yC=1facetdVfacety(P1)+y(P2)+y(P3)4dV y_C = \frac{1}{\sum_{\textrm{facet}}dV}\sum_{\textrm{facet}}\frac{y(P_1)+y(P_2)+y(P_3)}{4}dV (9.10)

zC=1facetdVfacetz(P1)+z(P2)+z(P3)4dV z_C = \frac{1}{\sum_{\textrm{facet}}dV}\sum_{\textrm{facet}}\frac{z(P_1)+z(P_2)+z(P_3)}{4}dV (9.11)

9.1.1.3 Autre méthode de calcul

Une méthode plus simple car ne nécessitant pas le calcul explicite du centre de carène est de projeter le vecteur GBGB sur le vecteur yy du plan vertical attaché au corps :

GZ=yGB GZ = y\cdot GB (9.12)

or

y=xbody(ned)×zned(ned)xbody(ned)×zned(ned)y = \frac{x_{\textrm{body}}^{\textrm{(ned)}} \times z_{\textrm{ned}}^{\textrm{(ned)}}}{\left\|x_{\textrm{body}}^{\textrm{(ned)}} \times z_{\textrm{ned}}^{\textrm{(ned)}}\right\|}

xbody(ned)x_{\textrm{body}}^{\textrm{(ned)}} désigne les coordonnées du vecteur xx du repère body, exprimées dans le repère NED et zned(ned)z_{\textrm{ned}}^{\textrm{(ned)}} les coordonnées du vecteur zz du repère NED exprimées dans le repère NED.

Il se trouve qu’il n’est pas nécessaire de connaître la coordonnée zz du vecteur GB. En effet,

λ0𝐑:GB=M×FF+λ0F\exists \lambda_0\in\mathbf{R} : GB = \frac{M\times F}{\left\|F\right\|} + \lambda_0 F

MM est le moment en GG de l’effort hydrostatique et FF la résultante de l’effort hydrostatique.

On pose

GBλ=M×FF+λF GB_{\lambda} = \frac{M\times F}{\left\|F\right\|} + \lambda F (9.13)

Dans le repère NED, on a :

F=[00fz] F = \left[\begin{array}{c}0\\0\\f_z\end{array}\right] (9.14)

M=[mxmymz] M = \left[\begin{array}{c}m_x\\m_y\\m_z\end{array}\right] (9.15)

donc

GBλ=[mfxmfymfz+λF] GB_{\lambda} = \left[\begin{array}{c}mf_x\\mf_y\\mf_z+\lambda F\end{array}\right] (9.16)

où l’on a noté

M×F=[mfxmfymfz] M\times F = \left[\begin{array}{c}mf_x\\mf_y\\mf_z\end{array}\right] (9.17)

GZλ=yGBλ=[xyz]×[001][mfxmfymfz+λF]GZ_{\lambda} = y\cdot GB_{\lambda} = \left[\begin{array}{c}x\\y\\z\end{array}\right]\times \left[\begin{array}{c}0\\0\\1\end{array}\right]\cdot \left[\begin{array}{c}mf_x\\mf_y\\mf_z+\lambda F\end{array}\right]

d’où

λ𝐑,GZλ=xmxfz+ymyfz\forall \lambda\in\mathbf{R}, GZ_{\lambda} = \frac{x m_x}{f_z} + \frac{y m_y}{f_z}

soit, avec les conventions de rotation usuelles :

GZ=cos(ψ)cos(θ)mx+sin(ψ)cos(θ)myfzxbody(ned) GZ = \frac{\cos(\psi)\cdot\cos(\theta)\cdot m_x + \sin(\psi)\cdot\cos(\theta)\cdot m_y}{f_z\left\|x_{\textrm{body}}^{\textrm{(ned)}}\right\|} (9.18)

9.2 Outil de calcul de GZGZ

L’installation d’xdyn contient, outre l’exécutable xdyn, un autre exécutable appelé gz, permettant de calculer des courbes de stabilité statique, aussi communément appelée courbe en “GZ”, en fonction de la gîte ϕ\phi.

Cet outil prend en entrée des paramètres de ligne de commande et un fichier YAML au même format que celui pour le simulateur. Contrairement au simulateur, l’outil gz n’utilise ni les conditions initiales, ni les sorties, ni les efforts extérieurs spécifiés dans le fichier YAML.

gz <yaml file> [-h] [-y ARG] [-s ARG] [--dphi ARG] [--phi_max ARG]
[-c ARG]
Options:
  -h [ --help ]         Show this help message
  -y [ --yml ] arg      Path(s) to the YAML file(s)
  -s [ --stl ] arg      Path to the STL file
  --dphi arg            Roll angle step (in degrees)
  --phi_max arg         Maximum roll angle (in degrees)
  -c [ --csv ] arg      Name of the output CSV file (optional)

Exemple :

gz tuto_execution/test_ship_in_waves.yml -s
tuto_execution/test_ship.stl --dphi 10 --phi_max 40
Phi [deg]       GZ(phi) [m]
-40     -0.617366
-30     -0.434462
-20     -0.26999
-10     -0.129497
0       0.000592286
10      0.130533
20      0.270733
30      0.434837
40      0.617296

9.3 Références

10 Fonctionnement du solveur

Au cœur du simulateur, le solveur réalise l’intégration temporelle des équations différentielles ordinaires.

10.1 Formulation du problème

Soit n𝐍*n\in\mathbf{N}^*, p𝐍p\in\mathbf{N}, m𝐍m\in\mathbf{N}. On appelle modèle une fonction

f:𝐑n×𝐑m×𝐑×𝐑p𝐑n f:\mathbf{R}^n\times\mathbf{R}^m\times\mathbf{R}\times\mathbf{R}^p\rightarrow\mathbf{R}^n (10.1)

Une fonction dérivable X:t𝐑X(t)𝐑nX:t\in\mathbf{R}\mapsto X(t)\in\mathbf{R}^n est appelée vecteur d’états de ce système: ce sont les variables qui résument toutes les informations calculées par le modèle (par exemple, position, attitude, vitesse angulaire et vitesse de rotation).

U𝐑mU\in\mathbf{R}^m sont les entrées du système (par exemple des commandes).

P𝐑pP\in\mathbf{R}^p sont les paramètres du système, c’est-à-dire les constantes.

L’équation différentielle que l’on souhaite intégrer est :

Ẋ=dX(t)dt=f(X,U,t,P) \dot{X} = \frac{dX(t)}{dt} = f(X,U,t,P) (10.2)

10.2 Architecture générale

Le solveur comprend cinq éléments :

La figure suivante illustre les interactions entre ces composants.

10.3 Steppers

Les steppers réalisent l’intégration de ff sur un pas de temps. Actuellement, trois steppers sont implémentés :

10.3.1 Euler

X̂(t+dt)=X(t)+f(X,t,U,P)dt \hat{X}(t+dt) = X(t) + f(X,t,U,P)\cdot dt (10.3)

C’est le stepper le plus rapide, mais aussi le moins stable numériquement : si cette méthode est appliquée à l’équation différentielle y=kyy'=k\cdot y, alors la solution numérique est instable lorsque le produit dtkdt\cdot k est en-dehors de la région {z𝐂:z+11}\left\{z\in\mathbf{C} : \left\|z+1\right\| \leq 1\right\}. En pratique, il n’est utilisé que pour des tests car les autres steppers montrent de meilleures performances.

10.3.2 Runge-Kutta 4

X̂(t+dt)=X(t)+dt6(k1+2k2+2k3+k4) \hat{X}(t+dt) = X(t) + \frac{dt}{6}\left(k_1 + 2k_2 + 2k_3 + k_4\right) (10.4)

avec

k1=f(X,t,U,P) k_1 = f(X, t, U, P) (10.5)

k2=f(X+dt2k1,t+dt2,U,P) k_2 = f\left(X+\frac{dt}{2}\cdot k_1, t + \frac{dt}{2}, U, P\right) (10.6)

k2=f(X+dt2k2,t+dt2,U,P) k_2 = f\left(X+\frac{dt}{2}\cdot k_2, t + \frac{dt}{2}, U, P\right) (10.7)

k4=f(X+dtk3,t+dt,U,P) k_4 = f\left(X+dt\cdot k_3, t+dt, U, P\right) (10.8)

C’est un stepper très utilisé dans l’ingénierie.

10.3.3 Runge-Kutta Cash-Karp

C’est une méthode à pas adaptatif qui permet d’estimer l’erreur d’intégration. L’estimation de l’erreur est utilisée pour contrôler le pas d’intégration du schéma.

X̂(t+dt)=X(t)+37378k1+250621k3+125594k4+5121771k6\hat{X}(t+dt) = X(t) + \frac{37}{378}\cdot k_1 + \frac{250}{621}\cdot k_3 + \frac{125}{594}\cdot k_4 + \frac{512}{1771}\cdot k_6

L’erreur commise est approchée par la relation suivante

e(t+dt)=(37378282527648)k1+(2506211857548384)k3+(1255941352555296)k4+(27714336)k5+(512177114)k6e(t+dt) = \left(\frac{37}{378} - \frac{2825}{27648}\right)\cdot k_1 + \left(\frac{250}{621} - \frac{18575}{48384}\right)\cdot k_3 + \left(\frac{125}{594} - \frac{13525}{55296}\right)\cdot k_4 + \left(- \frac{277}{14336}\right)\cdot k_5 + \left(\frac{512}{1771} - \frac{1}{4}\right)\cdot k_6

avec

k1=dtf(X,t,U,P), k_1 = dt\cdot f\left(X, t, U, P\right), (10.9)

k2=dtf(X+15k1,t+15dt,U,P), k_2 = dt\cdot f\left(X + \frac{1}{5}\cdot k_1, t+\frac{1}{5}\cdot dt, U, P\right), (10.10)

k3=dtf(X+340k1+940k2,t+310dt,U,P), k_3 = dt\cdot f\left(X + \frac{3}{40}\cdot k_1 + \frac{9}{40}\cdot k_2, t+\frac{3}{10}\cdot dt, U, P\right), (10.11)

k4=dtf(X+310k1+910k2+65k3,t+35dt,U,P), k_4 = dt\cdot f\left(X + \frac{3}{10}\cdot k_1 + \frac{-9}{10}\cdot k_2 + \frac{6}{5}\cdot k_3, t+\frac{3}{5}\cdot dt, U, P\right), (10.12)

k5=dtf(X+1154k1+52k2+7027k3+3527k4,t+dt,U,P), k_5 = dt\cdot f\left(X + \frac{-11}{54}\cdot k_1 + \frac{5}{2}\cdot k_2 +\frac{-70}{27}\cdot k_3+ \frac{35}{27}\cdot k_4, t+ dt, U, P\right), (10.13)

k6=dtf(X+163155296k1+175512k2+57513824k3+44275110592k4+2534096k5,t+78dt,U,P), k_6 = dt\cdot f\left(X + \frac{1631}{55296}\cdot k_1 + \frac{175}{512}\cdot k_2 + \frac{575}{13824}\cdot k_3 + \frac{44275}{110592}\cdot k_4 + \frac{253}{4096}\cdot k_5, t+\frac{7}{8}\cdot dt, U, P\right), (10.14)

11 Modélisation des efforts de diffraction et de radiation

Cette section propose une décomposition des efforts hydrodynamiques suivant un schéma classiquement utilisé pour la résolution des problèmes de tenue à la mer. Les efforts hydrodynamiques sont alors supposés constitués de la somme des : - efforts d’excitation résultant des pressions appliquées sur la coque, supposée fixe, par la houle incidente (efforts de Froude-Krylov) et la houle modifiée par le présence du corps (supposé fixe), ou diffraction. - la formulation temporelle considérée ici permet en outre d’aller plus loin dans la modélisation des efforts de Froude-Kryolv, en intégrant les pressions de houle incidente sur la géométrie exacte du corps en mouvement par rapport à la surface libre déformée (houle incidente seulement). - efforts liés aux mouvements du navire en eau initialement calme (sans houle), et à la génération de vagues associée (radiation). Ces efforts sont aux même constitués - de composantes en phase avec l’accélération du corps, et assimilables à des termes inertiels. Ces termes sont d’un ordre de grandeur proche des termes d’inertie mécanique, et doivent être associés à ceux-ci (dans le membre de gauche de l’équation des mouvements à résoudre) afin d’éviter les instabilités numériques qui apparaissent si on les considère comme des efforts extérieurs. - de composantes en phase avec les vitesses du corps, correspondant à des termes d’amortissement. Ces termes peuvent être exprimés dans le domaine temporel à partir de formulations impulsionnelles, faisant appel à des informations issues d’un calcul fréquentiel. - ces termes d’amortissement sont uniquement d’origine potentielle, et ne sont pas suffisant pour représenter la physique des amortissements pour certaines degrés de liberté, correspondant notamment aux résonances mécaniques. Il est alors nécessaire d’ajouter un amortissement d’orignie visqueuse, qui peut être calcul de différentes manières.

11.1 Potentiel d’interaction entre la houle et l’obstacle

On suppose l’eau non visqueuse, incompressible, homogène et isotrope et l’on considère un écoulement irrotationnel. Supposer l’écoulement irrotationnel implique (d’après le lemme de Poincaré) que la vitesse dérive d’un potentiel que l’on appelle ΦT:(x,y,z,t)ΦT(x,y,z,t)\Phi_T:(x,y,z,t)\mapsto\Phi_T(x,y,z,t). Par définition, la vitesse en tout point de l’écoulement est donc donnée par :

V(x,y,z,t)=gradΦT(x,y,z,t) V(x,y,z,t) = \textrm{grad}{\Phi_T(x,y,z,t)} (11.1)

Le potentiel de la houle incidente est connu si l’on se place dans le cadre de la théorie linéaire de Stokes. On désignera par ΦI\Phi_I ce potentiel. On a en effet :

ΦI(y,z,t)=gH2ωcosh(k(zh))cosh(kh)cos(kyωt)\Phi_I(y,z,t) = \frac{g H}{2 \omega} \frac{\cosh(k(z-h))}{\cosh(kh)}\cos(ky-\omega t)

avec : ω2=gktanh(kh)\omega^2 = g\cdot k\cdot \tanh(kh)

kk désigne le nombre d’onde, ω\omega la pulsation de la houle, hh la profondeur d’eau, HH la double amplitude (ou creux) et gg l’accélération de la pesanteur.

On pose :

ΦP:=ΦTΦI \Phi_P := \Phi_T-\Phi_I (11.2)

que l’on nomme “potentiel d’interaction entre la houle et l’obstacle”. C’est ce potentiel qui nous intéresse ici puisque c’est la seule indéterminée.

On contraint ΦP\Phi_P à être une fonction harmonique du temps de pulsation ω\omega :

ΦP(x,y,z,t)=ΨPeiωt \Phi_P(x,y,z,t) = \Re{\Psi_P e^{-i\omega t}} (11.3)

11.2 Conditions satisfaites par le potentiel d’interaction entre la houle et l’obstacle

Le potentiel inconnu ΦP\Phi_P doit satisfaire les conditions suivantes :

  1. Le fluide étant incompressible et l’écoulement irrotationnel, ΦP\Phi_P vérifie l’équation de Laplace ΔΦP=0\Delta \Phi_P = 0.
  2. Si l’on suppose l’obstacle immobile, la condition de surface libre s’écrit : [gΨPz+ω2ΨP](x,y,0,t)=0\left[g\cdot\frac{\partial \Psi_P}{\partial z} + \omega^2 \Psi_P\right](x,y,0,t) = 0
  3. Le potentiel étant indéterminé si l’on n’impose pas une condition sur le sens de propagation de l’énergie, on imposera la condition de radiation de Sommerfeld (phénomène divergent ; l’énergie s’éloigne de l’obstacle) : r|ΨPri|k|ΨP|0\sqrt{r}\lvert{\partial \Psi_P}{\partial r} - i \lvert k\rvert\Psi_P\rvert \rightarrow 0 quand r=x2+y2r=\sqrt{x^2 + y^2}\rightarrow \infty (condition de radiation à l’infini). Cette condition exprime que, au loin, les ondes de diffraction-radiation ont pour nombre d’onde kk, se propagent dans la direction radiale et leur amplitude décroît comme 1/r1/\sqrt{r}.
  4. Le fond étant imperméable, la composante suivant zz de la vitesse y est nulle : Vz(x,y,h,t)=ΦPz(x,y,h,t)=0V_z(x,y,h,t) = \frac{\partial \Phi_P}{\partial z}(x,y,h,t) = 0 et par là même : ΨPz(x,y,h)=0\frac{\partial \Psi_P}{\partial z}(x,y,h) = 0.
  5. L’obstacle étant imperméable, (gradΨP)n=ΨPn=(gradΨI)n+Von(\textrm{grad} \Psi_P) \cdot n = \frac{\partial \Psi_P}{\partial n} = -(\textrm{grad} \Psi_I) \cdot n + V_o \cdot nVoV_o est la vitesse normale de l’obstacle en un point PP et nn est la normale extérieure à l’obstacle.

11.3 Résolution

Si l’on suppose l’obstacle fixe, la condition (5) s’écrit :

ΨPn=ΨIn \frac{\partial \Psi_P}{\partial n} = - \frac{\partial \Psi_I}{\partial n} (11.4)

Cette condition traduit la réflexion (ou diffraction) de la houle incidente sur l’obstacle fixe. Un potentiel ΨPD\Psi_{\textrm{PD}} vérifiant les conditions (1) à (4) et la condition de diffraction est appelé potentiel de diffraction.

Si l’on ne considère qu’on mouvement oscillatoire élémentaire de l’obstacle suivant son jj-ème degré de liberté, la condition (5) s’écrit : ΨPn=nj\frac{\partial \Psi_P}{\partial n} = n_j. Un potentiel ΨPRj\Psi_{PR_j} vérifiant les conditions (1) à (4) et cette condition-ci est appelé jj-ème potentiel élémentaire de radiation et correspond au mouvement engendré par ce mouvement oscillatoire élémentaire de l’obstacle.

En définitive, la solution complète ΦD\Phi_D du problème de diffraction-radiation obtenue par superposition de la solution “obstacle fixe” et des solutions oscillatoires élémentaires peut s’écrire :

ΦD=[ΨPDeiωt+j=16fjΨPRjeiωt] \Phi_D = \Re\left[\Psi_{\textrm{PD}}e^{-i\omega t} + \sum_{j=1}^6 f_j\Psi_{\textrm{PR}_j} e^{-i\omega t}\right] (11.5)

en adoptant les notations suivantes :

11.4 Expression des efforts hydrodynamiques

On pose ΦPR=[j=16fjΨPRjeiωt]\Phi_{\textrm{PR}} = \Re\left[\sum_{j=1}^6 f_j \Psi_{PR_j} e^{-i\omega t}\right]

Les efforts hydrodynamiques s’écrivent :

Fhd=ρddtCΦTdS F_{\textrm{hd}} = \rho \frac{d}{dt} \int_{C}\Phi_T dS (11.6)

=ρddtCΦI+ΦPD+ΦPRdS = \rho \frac{d}{dt} \int_{C}\Phi_I+\Phi_{\textrm{PD}}+\Phi_{\textrm{PR}} dS (11.7)

On appelle FFK=ρddtCΦIdSF_{\textrm{FK}}=\rho \frac{d}{dt} \int_{C}\Phi_I dS “efforts de Froude-Krylov” et FD=ρddtCΦPDdSF_D = \rho \frac{d}{dt} \int_{C}\Phi_{\textrm{PD}} dS “efforts de diffraction”. Ensemble ils constituent les efforts d’excitation de la houle FEF_E. Les efforts ρddtCΦPRdS\rho \frac{d}{dt} \int_{C}\Phi_{\textrm{PR}} dS sont nommés “efforts de radiation” et sont désignés par FRF_R. On a donc :

Fhd=FE+FR F_{\textrm{hd}} = F_E + F_R (11.8)

11.5 Calcul des efforts de radiation

On a, pour l’axe kk :

FRk=ρtCΦPRnkdS F_{\textrm{R}_k} = \rho \frac{\partial}{\partial t} \int_C \Phi_{\textrm{PR}}n_k dS (11.9)

=ρtCjΨPRjfjeiωtnkdS = \rho \frac{\partial}{\partial t} \Re \int_C \sum_j \Psi_{\textrm{PR}_j} f_je^{-i\omega t} n_k dS (11.10)

=ρCjiωΨPRjfjeiωtnkdS = \rho \Re \int_C \sum_j -i\omega \Psi_{\textrm{PR}_j} f_j e^{-i\omega t} n_k dS (11.11)

On décompose ΨPRj\Psi_{\textrm{PR}_j} en sa partie réelle et sa partie imaginaire : ΨPRj=ΨjR+iΨjI\Psi_{\textrm{PR}_j} = \Psi_j^R + i \Psi_j^I

On a alors :

FRk=ρCj(iωΨjR+ωΨjI)fjeiωtnkdS=ρCjiωfjeiωtΨjR+jωfjeiωtΨjInkdS F_{\textrm{R}_k} = \rho \Re \int_C \sum_j \Re(-i\omega \Psi_j^R + \omega \Psi_j^I) f_j e^{-i\omega t} n_k dS = \rho \Re \int_C \sum_j -i\omega f_j e^{-i\omega t} \Psi_j^R + \sum_j \omega f_j e^{-i\omega t} \Psi_j^I n_k dS (11.12)

On remarque que

iωfjeiωtΨjR=t(fjeiωt) -i\omega f_j e^{-i\omega t} \Psi_j^R = \frac{\partial}{\partial t}(f_je^{-i\omega t}) (11.13)

donc

FRk=ρCjωfjeiωtΨjI+jtfjeiωtΨjRnkdS=ρωj(fjeiωt)CΨjInkdS+ρjddt(fjeiωt)CΨjRnkdS F_{\textrm{R}_k} = \rho \Re \int_C \sum_j \omega f_j e^{-i\omega t} \Psi_j^I + \sum_j \frac{\partial}{\partial t} f_j e^{-i\omega t}\Psi_j^R n_k dS = \rho\omega \sum_j\Re (f_j e^{-i\omega t})\int_C \Psi_j^I n_k dS + \rho \sum_j \frac{d}{dt}\Re(f_j e^{-i\omega t})\int_C\Psi_j^R n_k dS (11.14)

On pose Uj=(fjeiωt)U_j=\Re(f_j e^{-i\omega t})

FRk=ρωjUjCΨjInkdS+ρjdUjdtCΨjRnkdSF_{\textrm{R}_k} = \rho\omega \sum_j U_j\int_C\Psi_j^I n_k dS + \rho \sum_j \frac{dU_j}{dt}\int_C \Psi_j^R n_k dS

Or d’après la condition (5) écrite pour les potentiels élémentaires de radiation,

nk=ΨkRn n_k = \frac{\partial \Psi_k^R}{\partial n} (11.15)

On a donc :

FRk=ρωjUjCΨjIΨkRndS+ρjdUjdtCΨjRΨkRndS F_{\textrm{R}_k} = \rho\omega \sum_j U_j\int_C\Psi_j^I \frac{\partial \Psi_k^R}{\partial n} dS + \rho \sum_j \frac{dU_j}{dt}\int_C \Psi_j^R \frac{\partial \Psi_k^R}{\partial n} dS (11.16)

On pose :

MAjk(ω)=ρCΨjRΨkRndS (en kg) {M_A}_{jk}(\omega) = -\rho \int_C \Psi_j^R \frac{\partial \Psi_k^R}{\partial n} dS \textrm{ (en kg)} (11.17)

Brjk(ω)=ρωCΨjIΨkRndS (en kg/s) {B_r}_{jk}(\omega) = -\rho \omega \int_C \Psi_j^I \frac{\partial \Psi_k^R}{\partial n} dS \textrm{ (en kg/s)} (11.18)

On appelle MAM_A matrice des masses ajoutées (qui vient de ce que le solide déplace le fluide) et BrB_r matrice des amortissements dus à la radiation (termes d’amortissement non-visqueux dû à la dispersion d’énergie par les vagues générées par le solide).

On a alors :

FRk=(jUjBrjk(ω)+jdUjdtMAjk(ω))F_{\textrm{R}_k} = -\left(\sum_j U_j {B_r}_{jk}(\omega) + \sum_j \frac{dU_j}{dt} {M_A}_{jk}(\omega)\right)

En prenant U=dη/dtU=d\eta/dt, on obtient une formulation vectorielle des efforts dans le domaine fréquentiel :

FR(t)=(MA(ω)d2η(t)dt2+Br(ω)dη(t)dt)F_{\textrm{R}}(t) = -\left(M_A(\omega)\frac{d^2\eta(t)}{dt^2} + B_r(\omega) \frac{d\eta(t)}{dt}\right)

11.6 Propriétés

On peut montrer en utilisant la deuxième identité de Green, que les matrices MAM_A et BrB_r obtenues précédemment sont symétriques et que la matrices MAM_A est définie positive : on peut donc considérer MAM_A comme une matrice d’inertie que l’on appelle “inertie ajoutée”. On peut aussi retrouver l’expression de MAM_A de l’évaluation de l’énergie cinétique du fluide :

2Ec=ρω(Φ)2dV=ρΩΦΦndS=ρfkflΩΦkΦlndS=ρMAklfkfl2Ec = \rho\int_{\omega} (\nabla \Phi)^2 dV = \rho \int_{\partial \Omega} \Phi \frac{\partial \Phi}{\partial n} dS = \rho f_k f_l \int_{\partial \Omega}\Phi_k \frac{\partial \Phi_l}{\partial n} dS = \rho {M_A}_{kl} f_k f_l

11.7 Écriture en temporel

Lorsque l’on écrit le bilan des efforts appliqués au solide, on a :

(M+MA(ω))Ẍ+Br(ω)Ẋ=Fautres (M+M_A(\omega)) \ddot{X} + B_r(\omega) \dot{X} = F_{\textrm{autres}} (11.19)

Bien que cette équation ressemble à une équation différentielle, il n’en est rien car elle ne décrit que les mouvements en régime établi sinusoïdal : cette équation n’est qu’une représentation de la réponse fréquentielle du navire.

Cette constatation a été faite en 1962 par W. E. Cummins, alors employé par le David Taylor Model Basin de l’armée américaine (The Impulse Response & Ship Motions, Report 1661, October 1962).

Dans ce document, Cummins entreprend d’expliciter les efforts hydrodynamiques dans le domaine temporel. Pour ce faire, il fait l’hypothèse que les mouvements du navire sont un système linéaire à temps invariant et que, par conséquent, on peut déduire la réponse du navire à n’importe quelle excitation de sa réponse impulsionnelle. Il considère le potentiel de vitesse Θj(t)\Theta_j(t) de l’écoulement lors d’une réponse impulsionnelle suivant l’axe jj et le décompose en deux composantes :

On a donc, pour une excitation impulsionnelle de l’axe jj :

Θ=vjΨj+ϕj(t)Δxj \Theta = v_j\Psi_j + \phi_j(t)\Delta x_j (11.20)

Le potentiel de vitesse dû à un mouvement arbitraire suivant l’axe jj s’écrit alors :

Θ=ẋΨj+tϕj(tτ)xj̇(τ)dτ \Theta = \dot{x}\Psi_j + \int_{-\infty}^t \phi_j(t-\tau)\dot{x_j}(\tau)d\tau (11.21)

Les efforts agissant sur la carène suivant l’axe kk du fait d’une excitation de l’axe jj peuvent s’exprimer en fonction de la pression dynamique de l’écoulement :

Fjk=SpjnkdS F_{jk} = -\int_S p_j n_k dS (11.22)

Or par définition, p=Θtp = \frac{\partial \Theta}{\partial t}

En dérivant sous le signe intégral on obtient :

Θt=xj̈Ψj+tϕj(tτ)txj̇(τ)dτ\frac{\partial \Theta}{\partial t} = \ddot{x_j}\Psi_j + \int_{-\infty}^t \frac{\partial \phi_j(t-\tau)}{\partial t}\dot{x_j}(\tau)d\tau

Il en découle :

Fjk=ρCxj̈ψjnkdS+ρtCϕj(tτ)tnkdSxj̇(τ)dτ-F_{jk} = \rho\int_C\ddot{x_j}\psi_j n_k dS + \rho\int_{-\infty}^t\int_C\frac{\partial \phi_j(t-\tau)}{\partial t}n_k dS \dot{x_j}(\tau)d\tau

On pose :

Ajk=ρCψjnkdS (masses ajoutées) A_{jk} = \rho\int_C\psi_j n_k dS \textrm{ (masses ajoutées)} (11.23)

Kjk(t)=ρCϕj(t)tnkdS (fonctions de retard) K_{jk}(t) = \rho\int_C\frac{\partial\phi_j(t)}{\partial t}n_k dS \textrm{ (fonctions de retard)} (11.24)

On a alors :

Fjk=xj̈Ajk+tK(tτ)xj̇(τ)dτ-F_{jk} = \ddot{x_j}A_{jk} + \int_{-\infty}^t K(t-\tau)\dot{x_j}(\tau) d\tau

11.8 Relation entre les formulations temporelle et fréquentielle

La formulation fréquentielle s’écrit :

FR=MA(ω)d2Xdt2+Br(ω)dXdt -F_R = M_A(\omega)\frac{d^2X}{dt^2} + B_r(\omega)\frac{dX}{dt} (11.25)

La formulation temporelle est :

FR=Ad2Xdt2+tK(tτ)dXdt(τ)dτ-F_R = A\frac{d^2X}{dt^2} + \int_{-\infty}^t K(t-\tau)\frac{dX}{dt}(\tau)d\tau

Les codes potentiels fournissent les matrices MA(ω)M_A(\omega) et Br(ω)B_r(\omega) à n’importe quelle fréquence, mais qu’en est-il des matrices AA et KK utilisées par la formulation temporelle ?

Deux ans après Cummins, en 1964, Ogilvie propose une méthode pour déterminer les matrices AA et KK en fonction des matrices MAM_A et BrB_r. Pour ce faire, il considère que le mouvement du solide est oscillant de pulsation ω\omega :

X(t)=cos(ωt)X(t) = \cos(\omega t)

En substituant dans la formulation fréquentielle, on obtient :

FR=ω2MA(ω)cos(ωt)+ωBr(ω)sin(ωt)F_R = \omega^2 M_A(\omega) \cos(\omega t) + \omega B_r(\omega) \sin(\omega t)

En ce qui concerne la formulation temporelle, on a :

FR=ω2Acos(ωt)+ωtK(tτ)sin(ωτ)dτF_R = \omega^2 A \cos(\omega t) + \omega \int_{-\infty}^t K(t-\tau) \sin(\omega\tau)d\tau

En effectuant le changement de variable τtτ\tau\leftarrow t-\tau on a :

FR=ω2Acos(ωt)+ω0+K(τ)sin(ω(tτ))dτF_R = \omega^2 A \cos(\omega t) + \omega \int_0^{+\infty} K(\tau) \sin(\omega(t-\tau))d\tau

En développant sin(ω(tτ)\sin(\omega(t-\tau) on obtient :

FR=ω2[A1ω0K(τ)sin(ωτ)dτ]cos(ωt)+ω0+K(τ)cos(ωτ)dτsin(ωt)F_R = \omega^2\left[A - \frac{1}{\omega}\int_0^{\infty} K(\tau)\sin(\omega\tau)d\tau\right]\cos(\omega t) + \omega\int_0^{+\infty}K(\tau)\cos(\omega\tau)d\tau \sin(\omega t)

Les relations suivantes doivent donc être valables pour tout ω\omega :

MA(ω)=A1ω0+K(τ)sin(ωτ)dτM_A(\omega) = A-\frac{1}{\omega}\int_0^{+\infty}K(\tau)\sin(\omega\tau) d\tau

Br(ω)=0+K(τ)cos(ωτ)dτ B_r(\omega)=\int_0^{+\infty}K(\tau)\cos(\omega\tau)d\tau (11.26)

En faisant tendre ω\omega vers l’infini, on a :

A=MA()=limωMA(ω) A = M_A(\infty) = \lim_{\omega\rightarrow\infty}M_A(\omega) (11.27)

KK est obtenu en prenant la transformée de Fourier inverse de BrB_r :

K(t)=2π0+Br(ω)cos(ωτ)dτ K(t) = \frac{2}{\pi}\int_0^{+\infty} B_r(\omega)\cos(\omega\tau)d\tau (11.28)

11.9 Calcul numérique des amortissements de radiation

En pratique, on utilise en entrée du simulateur les fichiers HDB (convention d’écriture de base hydrodynamique issue originellement de Diodore), qui contiennent les matrices d’amortissement de radiation à différentes pulsations. Ces fichiers sont utilisés dans une table d’interpolation (soit une interpolation linéaire par morceaux, soit des splines) puis on évalue l’intégrale suivante pour différentes valeurs de τ\tau :

Ki,j(τ)=2πωminωmaxBi,j(ω)cos(ωτ)dω K_{i,j}(\tau) = \frac{2}{\pi}\int_{\omega_{\textrm{min}}}^{\omega_{\textrm{max}}}B_{i,j}(\omega)\cdot\cos(\omega\tau)d\omega (11.29)

Cette intégrale est calculée à l’aide d’un schéma d’intégration numérique (méthode des rectangles, des trapèzes, règle de Simpson ou Gauss-Kronrod).

On calcule ensuite les efforts d’amortissement de radiation en prenant en compte l’historique sur une période TT :

Frad(t)0TẊ(tτ)Kr(τ)dτ F_{\textrm{rad}}(t)\sim\int_0^{T}\dot{X}(t-\tau)K_r(\tau)d\tau (11.30)

Il est important de noter que ces efforts sont exprimés dans le repère de calcul hydrodynamique : un changement de repère est nécessaire pour les exprimer dans le repère “body”.

11.9.1 Paramétrage

Pour utiliser ce modèle, on écrit model: radiation damping. Les matrices d’amortissement de radiation sont lues depuis un fichier HDB (format Diodore). Ce fichier contient les matrices BrB_r pour différentes périodes. Comme l’indique la documentation, les étapes suivantes sont réalisées :

- model: radiation damping
  hdb: test_ship.hdb
  type of quadrature for cos transform: simpson
  type of quadrature for convolution: clenshaw-curtis
  nb of points for retardation function discretization: 50
  omega min: {value: 0, unit: rad/s}
  omega max: {value: 30, unit: rad/s}
  tau min: {value: 0.2094395, unit: s}
  tau max: {value: 10, unit: s}
  output Br and K: true

11.9.2 Méthode des rectangles

C’est la méthode la plus simple qui consiste à interpoler la fonction ff à intégrer par une fonction constante (polynôme de degré 0).

Si xix_i est le point d’interpolation, la formule est la suivante :

I(f)=(ba)f(xi) I(f) = (b-a) f(x_i) (11.31)

Le choix de xix_i influence l’erreur E(f)=II(f)E(f) = I - I(f) : - Si xi=ax_i = a ou xi=bx_i = b, l’erreur est donnée par E(f)=(ba)22f(η),η[a,b]E(f) = \frac{(b-a)^2}{2} f'(\eta), \quad \eta \in [a,b] C’est la ‘’méthode du rectangle’’ qui est d’ordre 0. - Si ξ=(a+b)/2\xi = (a+b)/2, l’erreur est donnée par E(f)=(ba)324f(η),η[a,b]E(f) = \frac{(b-a)^3}{24} f''(\eta), \quad \eta \in [a,b]. Il s’agit de la méthode du point médian qui est d’ordre 1.

Ainsi, le choix du point milieu améliore l’ordre de la méthode : celle du rectangle est exacte (c’est-à-dire E(f)=0E(f) = 0) pour les fonctions constantes alors que celle du point milieu est exacte pour les polynômes de degré 1. Ceci s’explique par le fait que l’écart d’intégration de la méthode du point milieu donne lieu à deux erreurs d’évaluation, de valeurs absolues environ égales et de signes opposés.

Source : Wikipedia

Source : Wikipedia

11.9.3 Méthode des trapèzes

En interpolant ff par un polynôme de degré 1, les deux points d’interpolation (a,f(a))(a, f(a)) et (b,f(b))(b, f(b)) suffisent à tracer un segment dont l’intégrale correspond à l’aire d’un trapèze, justifiant le nom de méthode des trapèzes qui est d’ordre 1 : :I(f)=(ba)f(a)+f(b)2I(f) = (b-a) \frac{f(a) + f(b)}{2}

L’erreur est donnée par: E(f)=(ba)312f(η),η[a,b]E(f) = - \frac{(b-a)^3}{12} f''(\eta), \quad \eta \in [a,b]

Conformément aux expressions de l’erreur, la méthode des trapèzes est souvent moins performante que celle du point milieu.

Source : Wikipedia

Source : Wikipedia

11.9.4 Règle de Simpson

En interpolant ff par un polynôme de degré 2 (3 degrés de liberté), 3 points (ou conditions) sont nécessaires pour le caractériser : les valeurs aux extrémités aa, bb, et celle choisie en leur milieu x1/2=(a+b)/2x_{1/2} = (a + b) / 2. La méthode de Simpson est basée sur un polynôme de degré 2 (intégrale d’une parabole), tout en restant exacte pour des polynômes de degré 3 ; elle est donc d’ordre 3 : :I(f)=(ba)6[f(a)+4f(x1/2)+f(b)]I(f) = \frac{(b-a)}{6} [ f(a) + 4 f(x_{1/2}) + f(b) ]

L’erreur globale est donnée par :E(f)=(ba)52880f(4)(η),η[a,b]E(f) = - \frac{(b-a)^5}{2880} f^{(4)}(\eta), \quad \eta \in [a,b]

Remarque : comme la méthode du point médian qui caractérise un polynôme de degré 0 et qui reste exacte pour tout polynôme de degré 1, la méthode de Simpson caractérise un polynôme de degré 2 et reste exacte pour tout polynôme de degré 3. Il s’agit d’une sorte d’“anomalie” où se produisent des compensations bénéfiques à l’ordre de la méthode.

Source : Wikipedia

Source : Wikipedia

11.9.5 Quadrature de Gauss-Kronrod

La formule de quadrature de Gauss-Kronrod est une extension de la quadrature de Gauss. Lorsque l’on calcule une quadrature de Gauss sur un intervalle et que l’on divise cet intervalle en deux partie, on ne peut réutiliser aucun des points (sauf le point médian dans le cas d’un nombre de points impairs). La formule de Gauss-Kronrod, créée dans les années 60 par Alexander Kronrod, permet de transformer un schéma d’ordre nn en schéma d’ordre 3n+13n+1 en ajoutant aux nn points de la quadrature de Gauss n+1n+1 zéros des polylônmes de Stieltjes-Wigert. Les polynômes de Stieltjes-Wigert sont des polynômes orthogonaux pour la fonction de poids :

w(x)=π1/2kxk2log(x),x𝐑+*,k>0 w(x)=\pi^{-1/2}\cdot k\cdot x^{k^2\log(x)},x\in\mathbf{R}_+^*, k>0 (11.32)

On pose

qk=e12k2 q_k=e^{-\frac{1}{2k^2}} (11.33)

Les polynômes de Stieltjes-Wigert s’écrivent alors :

p0(x)=q1/4 p_0(x)=q^{1/4} (11.34)

et pn,k(x)=(1)nqkn2+14(qk;qk)nν=0n[nν]qkν2(qkx)νp_{n,k}(x) = \frac{(-1)^n q_k^{\frac{n}{2} + \frac{1}{4}}}{\sqrt{(q_k;q_k)_n}}\sum_{\nu=0}^n\left[\begin{array}{c}n\\\nu\end{array}\right]q_k^{\nu^2}(-\sqrt{q_k}x)^\nu

k[1,n] k\in[1,n] (11.35)

[nν]=i=0ν11qni1qi+1 \left[\begin{array}{c}n\\\nu\end{array}\right]=\prod_{i=0}^{\nu-1}\frac{1-q^{n-i}}{1-q^{i+1}} (11.36)

avec qq le symbole de Pochhammer

(q;a)n={j=0n1(1qaj),n>01,n=0j=0|n|(1qaj),n<0j=0(1qaj),n=(q;a)_n=\left\{\begin{array}{c} \prod_{j=0}^{n-1}(1-qa^j),n>0\\ 1,n=0\\ \prod_{j=0}^{|n|}(1-qa^j),n<0\\ \prod_{j=0}^{\infty}(1-qa^j),n=\infty \end{array}\right.

(coefficient qq-binomial)

Afin d’accélérer davantage la convergence, on utilise l’intégration de Gauss-Kronrod de manière répétée (puisque cette méthode offre l’avantage de pouvoir réutiliser les points de calcul de l’itération précédente) et l’on applique l’ε\varepsilon-algorithme de Wynn.

Les formules de Gauss-Kronrod sont implémentées dans des bibliothèques numériques standard telles que celles de Netlib (QUADPACK, en particulier la routine DQAGS).

11.10 Calcul des matrices de masse ajoutée

Dans le simulateur, la matrice de masses ajoutées est soit lue directement depuis le fichier YAML, soit extraite et interpolée linéairement à partir d’un fichier HDB. Pour le calcul des efforts d’amortissement de radiation, on a besoin de la masse ajoutée à fréquence infinie. Afin de garantir la symmétrie et le caractère positif et défini de la matrice (les coefficients ont tendance à osciller fortement au voisinage de T=0T=0), on n’extrapole pas les données du fichiers HDB en zéro : on utilise directement les valeurs lues dans le fichier HDB pour la période la plus faible. On suppose que les mailles utilisées pour le calcul des masses ajoutées (résolution du potentiel) sont suffisamment fines pour que le résultat ait un sens.

11.11 Références

12 Modèles d’efforts non-commandés

Les efforts extérieurs (non commandés) sont donnés dans la section external forces sous forme de liste de modèles ayant ou non des paramètres. La seule clef commune à tous les modèles d’effort est model : chaque modèle possède sinon sa propre paramétrisation (éventuellement aucune paramétrisation). Voici un exemple de section external forces :

external forces:
  - model: gravity
  - model: non-linear hydrostatic (fast)

12.1 Efforts de gravité

12.1.1 Description

Le poids est donné dans le repère NED par :

FP=mg𝐮𝐳F_P = m \cdot g \mathbf{u_z}

mm désigne la masse du navire (en kg), gg l’accélération de la pesanteur (en m/s^2) et 𝐮𝐳\mathbf{u_z} le vecteur unitaire vertical, exprimé dans le repère dans lequel on veut projeter la force.

12.1.2 Paramétrage

Pour soumettre un solide à la gravité, on écrit :

- model: gravity

La valeur de gg utilisée est celle définie dans la section environmental constants et pour la masse on prend le coeffient M3,3M_{3,3} (le terme en Z, donc) de la matrice d’inertie.

Un exemple de simulation de solide soumis uniquement à la gravité (chute libre) est disponible dans les tutoriels.

12.1.3 Références

12.2 Efforts hydrostatiques non-linéaires

12.2.1 Description

Les efforts hydrostatiques non-linéaires sont dus à la pression statique (c’est-à-dire indépendante de la vitesse du fluide) s’exerçant sur la carène. L’hypothèse principale est ici la staticité, c’est-à-dire qu’on considère la carène au repos et une surface libre plane. Si cette dernière hypothèse n’est pas vérifiée, il faut ajouter un terme correctif, qui correspond aux efforts d’excitation de Froude-Krylov. En d’autres termes, pour le modèle hydrostatique, il faut effectuer le calcul en supposant la surface libre au repos. La prise en compte de la pression due à la houle est faite par le modèle de Froude-Krylov. La force 𝐅HS\textbf{F}_{\textrm{HS}} exercée par l’eau sur la carène doit être calculée comme l’intégrale de la pression hydrostatique pHSp_{\textrm{HS}} sur la surface immergée totale :

𝐅HS=SpHS(z)𝐧dS \textbf{F}_{\textrm{HS}} = \int_{S}p_{\textrm{HS}}(z)\cdot \textbf{n} dS (12.1)

Le paramétrage des efforts hydrostatiques non-linéaires dans le simulateur est décrit ici.

Un exemple d’utilisation est présenté dans les tutoriels.

12.2.2 Calcul de la résultante des efforts hydrostatiques intégrés sur la coque

Pour évaluer numériquement cette intégrale, il faut discrétiser la carène au moyen d’un maillage surfacique. La définition de ce maillage est faite ici.

Les facettes du maillage peuvent alors être réparties en trois catégories :

On ne choisit pas, pour zGz_G, la hauteur d’eau au-dessus du centroïde : le faire reviendrait à inclure une partie des efforts d’excitations de Froude-Krylov, qui agissent comme une correction si la surface libre n’est pas plane.

Lorsque l’on sépare les facettes partiellement immergées en une sous-facette émergée et une sous-facette immergée, la situation est la suivante :

La surface libre est représentée en bleu. Les vrais points d’intersection sont P’ et Q’, mais comme le calcul de la fonction η\eta représentant l’élévation de la surface libre est coûteux, on calcule les points P et Q, barycentres respectifs des segments [AC] et [BC], affectés des coefficients correspondant à la hauteur d’eau au-dessus d’eux. Cela revient à approcher la surface libre par un plan orthogonal à la facette et passant par P et Q. Cette approximation est d’autant plus juste que les mailles sont petites par rapport à la longueur d’onde puisque pour une surface libre modélisée à l’ordre 1 par une houle monochromatique et monodirectionnelle, on a :

η=sin(ωtkx+ϕ)=kx+o(x) \eta = \sin(\omega\cdot t - k\cdot x + \phi) = -k\cdot x + o(x) (12.2)

donc l’erreur que l’on commet peut s’écrire sous la forme :

ϵ(k,L)1cos(kL2)k2L28 \epsilon(k,L) \sim 1-\cos\left(k\cdot\frac{L}{2}\right) \sim \frac{k^2\cdot L^2}{8} (12.3)

kk désigne le nombre d’onde et LL la dimension caractéristique de la maille.

12.2.3 Calcul du moment hydrostatique

Pour le calcul du moment, il faut connaître le point d’application de chaque force élémentaire qui se situe en général en-dessous du centroïde de la facette (sauf si la pression est uniforme, auquel cas ces deux points sont confondus). On peut soit calculer exactement ce point d’application (on obtient alors le modèle non-linear hydrostatic (exact)), soit faire l’approximation que le point d’application est confondu avec le centroïde (donnant ainsi le modèle non-linear hydrostatic (fast)).

Pour calculer le point d’application, on définit les notations suivantes :

On désigne par tRt_R et uRu_R les coordonnées du point d’application des efforts dans le plan (t,ut,u) et tGt_G et uGu_G les coordonnées du centroïde de la facette dans ce même repère. Le repère (t,ut, u) est centré au centroïde de la facette.

Les efforts hydrostatiques s’écrivent :

𝐅HS=PSρgz(P)𝐝𝐒(P) \textbf{F}_{\textrm{HS}} = \int_{P\in S} \rho\cdot g\cdot z(P) \textbf{dS}(P) (12.4)

avec z(P)=tsinθz(P)=t\cdot\sin\theta

d’où

𝐅HS=ρgsinθ𝐧StdS \textbf{F}_{\textrm{HS}} = \rho\cdot g\cdot \sin\theta \textbf{n} \int_S t dS (12.5)

Or StdS=tdtdu=dutdt=UT22=UTT2=StG\int_S t dS = \int\int t dt du = \int du\int t dt = U\cdot\frac{T^2}{2} = UT\cdot\frac{T}{2} = S\cdot t_G

d’où

𝐅HS=ρgtGS𝐧 \textbf{F}_{\textrm{HS}} = \rho\cdot g\cdot t_G \cdot S \textbf{n} (12.6)

tRt_R doit vérifier :

StdF=FtR \int_S t dF = F\cdot t_R (12.7)

soit

tR=St2dStGS t_R = \frac{\int_S t^2 dS}{t_G S} (12.8)

Or St2dS=It(G)+StG2\int_S t^2 dS = I_t(G) + S\cdot t_G^2 donc

It(G)I_t(G) est le second moment d’inertie de la surface par rapport à l’axe parallèle à tt et passant par GG.

On a donc :

tR=tG+It(G)tGS t_R = t_G + \frac{I_t(G)}{t_G\cdot S} (12.9)

De même, on trouve :

uR=uG+Iu(G)tGS u_R = u_G + \frac{I_u(G)}{t_G\cdot S} (12.10)

or uG=0u_G=0 par définition du repère (t,u)(t,u), donc

uR=Iu(G)tGS u_R = \frac{I_u(G)}{t_G\cdot S} (12.11)

En pratique, on constate lors de simulations que les deux modèles sont assez proches sur l’axe zz puisque l’amplitude de la force est identique dans les deux cas. Les différences se situent plutôt au niveau des moments et sont d’autant plus notables que les mailles sont grandes par rapport au solide (à la limite, quand la surface des facettes tend vers zéro, les deux modèles coïncident). La différence la plus flagrante est obtenue lorsque l’on simule les oscillations en roulis (c’est-à-dire autour de xx) d’un cube maillé par six triangles rectangles : on obtient pour le modèle fast des déplacements parasites suivant yy qui n’apparaissent pas avec le modèle exact.

Néanmoins, le modèle exact impliquant le calcul des matrices d’inertie de chaque maille (en particulier des mailles générées dynamiquement en calculant l’intersection de la carène et de la surface libre), il est très coûteux en temps de calcul (on peut constater un ordre de grandeur par rapport au modèle fast).

12.2.4 Nouveau modèle hydrostatique

Ce modèle utilise une approche différente : au lieu d’intégrer les efforts sur toutes les facettes, on calcule le volume immergé du maillage complet et son centroïde et l’on écrit :

Fhs=ρV𝐠 F_{\textrm{hs}} = \rho\cdot V\cdot \mathbf{g} (12.12)

Ce modèle a l’avantage de forcer la résultante à être suivant zz.

Ce modèle remplacera à terme les modèles non-linear hydrostatic (fast) et non-linear hydrostatic (exact) parce qu’il est à la fois plus précis que non-linear hydrostatic (exact) et aussi rapide que non-linear hydrostatic (fast).

12.2.5 Paramétrage

Pour utiliser le modèle rapide, on écrit :

- model: non-linear hydrostatic (fast)

pour le modèle précis :

- model: non-linear hydrostatic (exact)

et pour le nouveau modèle :

- model: hydrostatic

Le nouveau modèle peut également sortir la position (Bx, By, Bz) du centre de carène (immergé). Il suffit, dans la liste data de la section output, de rajouter Bx et/ou By et/ou Bz.

Un exemple de simulation de solide soumis aux efforts hydrostatiques (oscillations en immersion) est disponible dans les tutoriels.

12.2.6 Références

Introduction à la mécanique des fluides - CVG 2516, Statique des Fluides, Ioan NISTOR

12.3 Efforts de Froude-Krylov

12.3.1 Description

Les efforts de Froude-Krylov constituent une partie des efforts d’excitation dus à la houle. Ils correspondent aux efforts générés par le champ de pression de la houle, en supposant que le navire ne perturbe pas l’écoulement. Ils sont calculés en intégrant la pression dynamique (champ de pression de la houle incidente) sur la carène. En pratique, ils peuvent être négligés dès que le corps est à plus d’une-demi longueur d’onde de profondeur :

𝐅FK(t)=P=(x,y,z)Spdyn(x,y,z,t)dS(P)\mathbf{F}_{\textrm{FK}}(t)=\int_{P=(x,y,z)\in S} p_{\textrm{dyn}}(x,y,z,t)dS(P)

L’expression de la pression dynamique dépend du modèle de houle utilisé et est décrite ici (pour la houle d’Airy).

La pression totale dans le fluide, en un point donné, est la somme de la pression hydrostatique et de la pression dynamique. Lorsque l’on utilise conjointement le modèle hydrostatique et le modèle de Froude-Krylov, on est dans la situation suivante :

12.3.2 Paramétrage

Pour utiliser ce modèle, on insère la ligne suivante dans la section external forces :

- model: non-linear Froude-Krylov

12.3.3 Références

12.4 Efforts de diffraction

12.4.1 Description

Les efforts de diffraction sont dus à la modification du champs de pression du fait de la présence du navire. Ils sont interpolés à partir de tables hydrodynamiques. Comme les efforts de radiation et les efforts de masse ajoutée, ces tables sont calculées en résolvant un problème de condition aux limites pour le potentiel de vitesse : on utilise donc des codes basés sur des méthodes potentielles, tels qu’Aqua+.

Les tables contiennent les fonctions de transfert des efforts (Response Amplitudes Operators ou RAO) et sont paramétrées en pulsation, incidence et vitesse d’avance. Il s’agit de RAO d’efforts du premier ordre). Les efforts de diffraction sont dus à la diffraction de la houle par le corps fixe, tandis que les amortissements de radiation proviennent de la dissipation de l’énergie du corps lors de son mouvement, par la création de vagues. Cette différence se traduit uniquement par une différence de conditions aux limites dans la modélisation potentielle.

12.4.2 Calcul numérique

Les RAO d’efforts sont lues à partir d’un fichier HDB. Cette table donne, une fois interpolée, deux fonctions RAO par axe kk

(u,ω,β)RAOkmodule(u,ω,β) (u,\omega,\beta)\mapsto {RAO^{k}}_{\textrm{module}}(u,\omega,\beta) (12.13)

(u,ω,β)RAOkphase(u,ω,β) (u,\omega,\beta)\mapsto {RAO^{k}}_{\textrm{phase}}(u,\omega,\beta) (12.14)

Pour calculer les efforts et les moments, pour une houle de direction de propagation ψ\psi, on somme les RAO comme pour le calcul de l’élévation de la surface libre en suivant la convention AQUA+ :

Fk(xH,yH,t,u)=i=1nfreqj=1ndirRAOkmodule(u,ωi,ψψj)ai,jsin(k(xHcos(ψj)+yHsin(ψj))ωitRAOkphase(u,ωi,ψψj)+ϕij)F_k(x_H,y_H,t,u) = -\sum_{i=1}^{nfreq}\sum_{j=1}^{ndir} {RAO^{k}}_{\textrm{module}}(u,\omega_i,\psi-\psi_j)\cdot a_{i,j} \cdot\sin(k\cdot(x_H\cdot \cos(\psi_j) + y_H\cdot \sin(\psi_j))-\omega_i\cdot t-{RAO^{k}}_{\textrm{phase}}(u,\omega_i,\psi-\psi_j)+\phi_{ij})

Les RAO lues depuis le fichier n’étant pas modifiées, l’expression précédente donne un torseur d’effort exprimé dans un repère Z vers le haut et au point de calcul de la RAO : pour l’exprimer dans le repère Z vers le bas d’xdyn, on effectue le changement de repère suivant :

τHDB=[FXFYFZMXMYMZ] \tau_{\textrm{HDB}} = \left[ \begin{array}{c} F_X\\ F_Y\\ F_Z\\ M_X\\ M_Y\\ M_Z\\ \end{array} \right] (12.16)

τxdyn=[FXFYFZMXMYMZ] \tau_{\textrm{xdyn}} = \left[ \begin{array}{c} F_X\\ -F_Y\\ -F_Z\\ M_X\\ -M_Y\\ -M_Z\\ \end{array} \right] (12.17)

Le torseur calculé est ensuite déplacé par xdyn du point de calcul des fichiers HDB au point de résolution du bilan des efforts.

12.4.3 Paramétrage

Pour utiliser ce modèle, on écrit model: diffraction. Le seul paramètre de ce modèle est le chemin vers le fichier HDB contenant les RAO d’effort du premier ordre.

- model: diffraction
  hdb: test_ship.hdb
  calculation point in body frame:
      x: {value: 0.696, unit: m}
      y: {value: 0, unit: m}
      z: {value: 1.418, unit: m}
  mirror for 180 to 360: true

La section correspondante dans le fichier HDB est DIFFRACTION_FORCES_AND_MOMENTS. Il est à noter que le point de calcul ne figurant pas dans les fichiers HDB, il doit être renseigné dans le fichier YAML (calculation point in body frame) mais qu’aucune vérification ne peut être faite.

Le point de calcul des efforts de diffraction n’est pas nécessairement le centre de gravité, ni même le point de résolution de l’équation de Newton. En revanche, il s’agit nécessairement d’un point fixe dans le repère du solide.

Le paramètre mirror for 180 to 360 sert à pouvoir ne spécifier que la partie de la RAO entre 00^{\circ} et 180180^{\circ}, quitte à la symétriser par rapport à l’axe (Ox) pour obtenir les points entre 180180^{\circ} et 360360^{\circ}. En pratique, cela signifie que l’on prend RAO(Tp,β)=RAO(Tp,2πβ)RAO(T_p,\beta)=RAO(Tp,2\pi-\beta) si β>π\beta>\pi et que mirror for 180 to 360 vaut true.

12.4.4 Références

12.5 Résistance à l’avancement

12.5.1 Hypothèses

On suppose la propulsion rectiligne, d’intensité et de direction constantes et située dans le plan (xx, yy) du repère NED.

On suppose également qu’il n’y a pas de houle (eau initialement calme), que l’assiette et l’enfoncement du navire sont constants et que sa gite est nulle. Dans le cas contraire, il faudrait interpoler la résistance suivant X en fonction de la vitesse, mais aussi l’effort vertical et le moment de tangage, mais ce modèle ne le permet pas.

On suppose enfin que la résistance à l’avancement est colinéaire à la projection sur le plan horizontal de la force propulsive.

Étant données ces hypothèses, on parle de résistance de remorquage à une vitesse donnée et on note RTR_T la force nécessaire pour remorquer le navire à cette vitesse en eau calme.

12.5.2 Modélisation

Le paradoxe d’Alembert est que lorsque l’on remorque un objet immergé dans un fluide supposé parfait et en milieu infini, sa résistance est nulle. Expérimentalement, bien sûr, on ne constate pas ce phénomène. Cela implique que :

On décompose donc la résistance de remorquage en deux composantes :

En pratique, on effectue une interpolation de la courbe de résistance à l’avancement en fonction de la vitesse du solide par rapport au repère NED projetée sur l’axe X du repère body (que l’on note uu). La courbe de résistance à l’avancement est obtenue au préalable (et non calculée par xdyn) et renseignée dans le fichier YAML.

Si f:uR=f(u)f:u\mapsto R=f(u) désigne la fonction d’interpolation de la courbe de résistance à l’avancement, le torseur des efforts, exprimé au point de calcul hydrodynamique, est :

τres=[XYZKMN]=[f(u)00000] \tau_{\textrm{res}} =\left[\begin{array}{c}X\\Y\\Z\\K\\M\\N\end{array}\right] =\left[\begin{array}{c}-f(u)\\0\\0\\0\\0\\0\end{array}\right] (12.18)

12.5.3 Paramétrage

Ce modèle est accessible par la clef resistance curve.

Les efforts de résistance à l’avancement sont renseignés en fonction de la vitesse d’avance (axe longitudinal uniquement), c’est-à-dire la projection suivant l’axe xx du repère body de la vitesse du navire par rapport au repère NED. L’interpolation est faite en utilisant des splines cubiques.

- model: resistance curve
  speed: {unit: knot, values: [0,1,2,3,4,5,15,20]}
  resistance: {unit: MN, values: [0,1,4,9,16,25,225,400]}

Cet effort est orienté suivant l’axe x-x du repère body.

12.5.4 Références

12.6 Efforts d’amortissement visqueux

12.6.1 Description

Les mouvements d’un solide évoluant dans un fluide sont amortis du fait de l’énergie que ce solide communique au fluide. Ces efforts dissipatifs proviennent d’une part des vagues générées par les mouvements du fluide (et qui correspondent aux amortissements de radiation), et d’autre part des amortissements visqueux dus au cisaillement du fluide sur la coque (apparition d’un sillage tourbillonnaire ou turbulent qui dissipe de l’énergie, essentiellement sur l’axe roulis). Ce sont ces derniers qui nous intéressent dans cette section.

Les amortissements non-visqueux (radiation) sont, du fait de la modélisation utilisée pour les obtenir, linéaires par rapport à la vitesse. Les amortissements visqueux sont, eux, fréquemment modélisés par une loi quadratique de la vitesse. Le modèle d’amortissement linéaire ne doit être utilisé que pour prendre en compte les efforts dissipatifs de radiation, si ceux-ci ne sont pas déjà obtenus par le calcul fréquentiel (par le modèle d’amortissement de radiation qui utilise la base de donnée hydro du fichier HDB). Suivant les axes, certains termes prédominent par rapport aux autres. Pour les mouvements de petites amplitudes, les efforts linéaires sont prépondérant. Pour les grands mouvements, c’est l’inverse.

Outre leur signification physique, les termes amortissements ont également une incidence sur la simulation dans la mesure où ils ont tendance à stabiliser les schémas d’intégration numériques explicites (type Runge-Kutta par exemple).

Lorsque l’on utilise conjointement les modèles d’amortissement en cavalement et de résistance à l’avancement, il convient de prendre des précautions supplémentaires afin de ne pas modéliser deux fois le même phénomène physique. Il faut donc décomposer la vitesse longitudinale en une composante basse fréquence (utilisée par le modèle de résistance à l’avancement) et une composante haute fréquence (pour le modèle d’amortissement). Cette décomposition n’est pas encore implémentée dans xdyn.

12.6.2 Modélisation

Pour une description des notations adoptées ici on pourra se référer à la description du repère de calcul hydrodynamique.

La vitesse du courant (vitesse de l’eau par rapport au repère NED, projetée dans le repère NED) est notée :

Veau/sol=[UcourantVcourant0]V_{\textrm{eau/sol}} = \left[\begin{array}{c}U_{\textrm{courant}}\\V_{\textrm{courant}}\\0\end{array}\right]

On définit :

νlocal=localTbodyνblocalTNEDVeau/sol \nu_{\textrm{local}} = {}^{\textrm{local}}T_{\textrm{body}} \nu_b - {}^{\textrm{local}}T_{\textrm{NED}}V_{\textrm{eau/sol}} (12.19)

ωlocal=localTbodyωnbb \omega_{\textrm{local}} = {}^{\textrm{local}}T_{\textrm{body}}\omega_{nb}^b (12.20)

Si les efforts de radiation ne sont par si ceux-ci sont déjà obtenus par le calcul fréquentiel (par le modèle d’amortissement de radiation qui utilise la base de donnée hydro du fichier HDB), les amortissements linéaires s’écrivent (dans le repère de calcul hydrodynamique) :

Fal=Dl[νlocalωlocal]local F_{\textrm{al}}=-D_l\left[\begin{array}{c}\nu_{\textrm{local}}\\\omega_{\textrm{local}}\end{array}\right]_{\textrm{local}} (12.21)

DlD_l est la matrice d’amortissement linéaire lue depuis le fichier de paramètres.

Pour les amortissements quadratiques :

Faq=Dq(νlocal)[νlocalωlocal]local F_{\textrm{aq}}=-D_q(\nu_{\textrm{local}})\left[\begin{array}{c}\nu_{\textrm{local}}\\\omega_{\textrm{local}}\end{array}\right]_{\textrm{local}} (12.22)

Dq(νlocal)=[d11|ulocal|d12|vlocal|d13|wlocal|d14|plocal|d15|qlocal|d16|rlocal|d21|ulocal|d22|vlocal|d23|wlocal|d24|plocal|d25|qlocal|d26|rlocal|d31|ulocal|d32|vlocal|d33|wlocal|d34|plocal|d35|qlocal|d36|rlocal|d41|ulocal|d42|vlocal|d43|wlocal|d44|plocal|d45|qlocal|d46|rlocal|d51|ulocal|d52|vlocal|d53|wlocal|d54|plocal|d55|qlocal|d56|rlocal|d61|ulocal|d62|vlocal|d63|wlocal|d64|plocal|d65|qlocal|d66|rlocal|]D_q(\nu_{\textrm{local}}) = \left[ \begin{array}{cccccc} d_{11}\cdot|u_{\textrm{local}}| & d_{12}\cdot |v_{\textrm{local}}| & d_{13}\cdot |w_{\textrm{local}}| & d_{14}\cdot |p_{\textrm{local}}| & d_{15}\cdot |q_{\textrm{local}}| & d_{16}\cdot |r_{\textrm{local}}|\\ d_{21}\cdot|u_{\textrm{local}}| & d_{22}\cdot |v_{\textrm{local}}| & d_{23}\cdot |w_{\textrm{local}}| & d_{24}\cdot |p_{\textrm{local}}| & d_{25}\cdot |q_{\textrm{local}}| & d_{26}\cdot |r_{\textrm{local}}|\\ d_{31}\cdot|u_{\textrm{local}}| & d_{32}\cdot |v_{\textrm{local}}| & d_{33}\cdot |w_{\textrm{local}}| & d_{34}\cdot |p_{\textrm{local}}| & d_{35}\cdot |q_{\textrm{local}}| & d_{36}\cdot |r_{\textrm{local}}|\\ d_{41}\cdot|u_{\textrm{local}}| & d_{42}\cdot |v_{\textrm{local}}| & d_{43}\cdot |w_{\textrm{local}}| & d_{44}\cdot |p_{\textrm{local}}| & d_{45}\cdot |q_{\textrm{local}}| & d_{46}\cdot |r_{\textrm{local}}|\\ d_{51}\cdot|u_{\textrm{local}}| & d_{52}\cdot |v_{\textrm{local}}| & d_{53}\cdot |w_{\textrm{local}}| & d_{54}\cdot |p_{\textrm{local}}| & d_{55}\cdot |q_{\textrm{local}}| & d_{56}\cdot |r_{\textrm{local}}|\\ d_{61}\cdot|u_{\textrm{local}}| & d_{62}\cdot |v_{\textrm{local}}| & d_{63}\cdot |w_{\textrm{local}}| & d_{64}\cdot |p_{\textrm{local}}| & d_{65}\cdot |q_{\textrm{local}}| & d_{66}\cdot |r_{\textrm{local}}|\\ \end{array}\right]

les (dij)(d_{ij}) étant les coefficients de la matrice d’amortissement quadratique lue depuis le fichier de paramètres.

12.6.3 Paramétrage

La paramétrisation des efforts d’amortissement linéaires est faite par une matrice renseignée de la façon suivante :

- model: linear damping
  damping matrix at the center of gravity projected in the body frame:
      row 1: [ 0, 0,     0,      0,      0, 0]
      row 2: [ 0, 0,     0,      0,      0, 0]
      row 3: [ 0, 0, 1.9e5,      0,      0, 0]
      row 4: [ 0, 0,     0, 1.74e4,      0, 0]
      row 5: [ 0, 0,     0,      0, 4.67e6, 0]
      row 6: [ 0, 0,     0,      0,      0, 0]

Cette matrice est la matrice DlD_l décrite dans la documentation.

La paramétrisation des efforts d’amortissement quadratiques est faite par une matrice renseignée de la façon suivante :

- model: quadratic damping
  damping matrix at the center of gravity projected in the body frame:
      row 1: [ 0, 0,     0,      0,      0, 0]
      row 2: [ 0, 0,     0,      0,      0, 0]
      row 3: [ 0, 0, 1.9e5,      0,      0, 0]
      row 4: [ 0, 0,     0, 1.74e4,      0, 0]
      row 5: [ 0, 0,     0,      0, 4.67e6, 0]
      row 6: [ 0, 0,     0,      0,      0, 0]

Cette matrice est la matrice (dij)(d_{ij}) décrite dans la documentation.

12.6.4 Références

12.7 Efforts hydrostatiques linéaires

12.7.1 Description

Le modèle d’efforts hydrostatiques linéaires est beaucoup plus rapide à calculer que son homologue non-linéaire. Habituellement, les efforts hydrostatiques linéaires sont juste calculés à partir d’une matrice hydrostatique donnée en entrée (ou éventuellement calculée à partir de la position du centre de gravité et des données géométriques). L’implémentation à quatre points présentée ici est très spécifique.

On utilise les variables suivantes :

z¯=14i=14zih \overline{z} = \frac{1}{4}\sum_{i=1}^4 z_i^h (12.23)

ϕ¯=12(atan(z2hz1h)d12+atan(z4hz3h)d43)\overline{\phi} = \frac{1}{2}\left(\frac{\textrm{atan}(z_2^h-z_1^h)}{d_{12}} + \frac{\textrm{atan}(z_4^h-z_3^h)}{d_{43}}\right) θ¯=12(atan(z2hz4h)d24+atan(z1hz3h)d13)\overline{\theta} = \frac{1}{2}\left(\frac{\textrm{atan}(z_2^h-z_4^h)}{d_{24}} + \frac{\textrm{atan}(z_1^h-z_3^h)}{d_{13}}\right)

dij=(xihxjh)2+(yihyjh)d_{ij} = \sqrt{(x^h_i-x^h_j)^2 + (y^h_i-y^h_j)} est la distance entre deux points de mesure.

Le torseur d’effort est donné dans le repère NED par :

Fhs=K3×3[zz¯zeqθθ¯θeqψψ¯ψeq]F_{\textrm{hs}} = K_{3\times 3} \left[\begin{array}{c}z-\overline{z}-z_{\textrm{eq}}\\\theta-\overline{\theta}-\theta_{\textrm{eq}}\\\psi-\overline{\psi}-\psi_{\textrm{eq}}\end{array}\right]

zeq,θeq,ψeqz_{\textrm{eq}}, \theta_{\textrm{eq}}, \psi_{\textrm{eq}} sont les valeurs d’équilibre renseignées dans le fichier de paramétrage.

12.7.2 Paramétrage

- model: linear hydrostatics
  z eq: {value: 0, unit: m}
  theta eq: {value: 0, unit: deg}
  psi eq: {value: 0, unit: deg}
  K row 1: [1, 0 , 0]
  K row 2: [0, 1 , 0]
  K row 3: [0, 0 , 1]
  x1: {value: 10, unit: m}
  y1: {value: -10, unit: m}
  x2: {value: 10, unit: m}
  y2: {value: 10, unit: m}
  x3: {value: -10, unit: m}
  y3: {value: -10, unit: m}
  x4: {value: -10, unit: m}
  y4: {value: 10, unit: m}

Les coordonnées (xi,yj)(x_i,y_j) sont données dans le repère body. Les coefficients de la matrice KK sont donnés en unité SI.

12.8 Effort constant

12.8.1 Description

Ce modèle permet d’ajouter au bilan d’efforts un effort constant dans le repère choisi. Par exemple, on peut définir un effort constant dans le repère NED pour simuler un effort de vent, ou encore définir un effort constant dans le repère body pour approcher un effort de propulsion.

12.8.2 Paramétrage

- model: constant force
  frame: TestShip
  x: {value: 0, unit: m}
  y: {value: 0, unit: m}
  z: {value: 0, unit: m}
  X: {value: 10, unit: kN}
  Y: {value: 20, unit: kN}
  Z: {value: 30, unit: kN}
  K: {value: 100, unit: kN*m}
  M: {value: 200, unit: kN*m}
  N: {value: 300, unit: kN*m}

Les coordonnées du point d’application de l’effort sont notées x, y et z, exprimées dans le repère désigné par frame. Les coordonnées X, Y, Z, K, M et N du torseur d’effort sont également exprimées dans ce repère.

13 Efforts commandés

13.1 Description

Les efforts commandés correspondent, par exemple, aux efforts de propulsion, de safran et de foil. Ils sont décrits dans la section controlled forces. Les seules clefs YAML communes à tous les efforts commandés sont name (qui est un identifiant choisi par l’utilisateur) et model (qui est une chaîne servant à identifier le type de modèle utilisé).

Les commandes sont spécifiées en YAML, soit dans le même fichier que les modèles d’effort, soit dans un fichier à part (plus modulaire).

Voici un exemple de section efforts commandés, qui correspond au modèle d’hélice décrit ici :

controlled forces:
  - name: port side propeller
    model: wageningen B-series
    position of propeller frame:
        frame: mesh(TestShip)
        x: {value: -4, unit: m}
        y: {value: -2, unit: m}
        z: {value: 2, unit: m}
        phi: {value: 0, unit: rad}
        theta: {value: -10, unit: deg}
        psi: {value: -1, unit: deg}
    wake coefficient w: 0.9
    relative rotative efficiency eta: 1
    thrust deduction factor t: 0.7
    rotation: clockwise
    number of blades: 3
    blade area ratio AE/A0: 0.5
    diameter: {value: 2, unit: m}
  - name: starboard propeller
    model: wageningen B-series
    position of propeller frame:
        frame: mesh(TestShip)
        x: {value: -4, unit: m}
        y: {value: 2, unit: m}
        z: {value: 2, unit: m}
        phi: {value: 0, unit: rad}
        theta: {value: -10, unit: deg}
        psi: {value: 1, unit: deg}
    wake coefficient w: 0.9
    relative rotative efficiency eta: 1
    thrust deduction factor t: 0.7
    rotation: anti-clockwise
    number of blades: 3
    blade area ratio AE/A0: 0.5
    diameter: {value: 2, unit: m}

Les commandes sont définies dans la section commands décrite ci-après.

13.1.1 Syntaxe des commandes

La section commands spécifie de manière statique les commandes reçues par les modèles d’efforts commandés. Les paramètres pouvant être commandés dépendent de chaque modèle d’effort : tous les paramètres ne peuvent pas forcément être commandés. Les commandes à chaque instant sont connues lors du lancement de la simulation.

commands:
  - name: port side propeller
    t: [1,3,10]
    rpm: {unit: rpm, values: [3000, 3000, 4000]}
    P/D: {unit: 1, values: [0.7,0.7,0.8]}
  - name: starboard propeller
    t: [1,3,10]
    rpm: {unit: rpm, values: [3000, 3000, 4000]}
    P/D: {unit: 1, values: [0.7,0.7,0.8]}

Il s’agit ici d’un modèle d’hélice dont la description complète est ici.

La valeur renseignée dans name doit correspondre à l’identifiant utilisé dans la section controlled forces. Pour chaque effort contrôlé (identifié par name), on donne une liste d’instants (en secondes) puis, pour chaque commande, les valeurs à ces instants. Il doit donc y avoir, pour chaque commande, autant de valeurs qu’il y a d’instants et il faut spécifier au moins deux instants distincts. Entre deux instants, les valeurs des commandes sont interpolées linéairement. On peut définir autant de clef qu’on le souhaite : les clefs inutilisées sont simplement ignorées.

Au-delà de la dernière valeur de temps renseignée, la dernière valeur de chaque commande est maintenue. Avant la première valeur de temps, on utilise la première valeur de chaque commande. Ainsi, pour l’exemple présenté ci-dessus, pour toute valeur de t10t\geq 10, alors rpm=4000. Pour t1t\leq 1, rpm=3000.

Les commandes attendues pour ce modèle sont :

Voici un exemple de section commande :

commands:
  - name: port side propeller
    t: [0,1,3,10]
    rpm: {unit: rpm, values: [2500, 3000, 3000, 4000]}
    P/D: {unit: 1, values: [0.7,0.7,0.7,0.7]}

13.2 Modèles de manœuvrabilité

13.2.1 Description

Le but de ce modèle d’effort est de pouvoir écrire un modèle de manœuvrabilité de façon assez générique, sans avoir à recompiler le code source. Des expressions simples des états et du temps peuvent être calculées, par exemple:

- model: maneuvering
  name: test
  reference frame:
      frame: NED
      x: {value: 0.696, unit: m}
      y: {value: 0, unit: m}
      z: {value: 1.418, unit: m}
      phi: {value: 0, unit: deg}
      theta: {value: 0, unit: deg}
      psi: {value: 0, unit: deg}
  commands: [command1, b, a]
  X: 0.5*rho*Vs^2*L^2*X_
  Y: 0.5*rho*Vs^2*L^2*Y_
  Z: 0
  K: 0
  M: 0
  N: 0.5*rho*Vs^2*L^3*N_
  Vs: sqrt(u(t)^2+v(t)^2)
  L: 21.569
  X_: Xu*u_ + Xuu*u_^2 + Xuuu*u_^3 + Xvv*v_^2 + Xrr*r_^2 + Xvr*abs(v_)*abs(r_)
  Y_: Yv*v_ + Yvv*v_*abs(v_) + Yvvv*v_^3 + Yvrr*v_*r_^2 + Yr*r_ + Yrr*r_*abs(r_) + Yrrr*r_^3 + Yrvv*r_*v_^2
  N_: Nv*v_ + Nvv*v_*abs(v_) + Nvvv*v_^3 + Nvrr*v_*r_^2 + Nr*r_ + Nrr*r_*abs(r_) + Nrrr*r_^3 + Nrvv*r_*v_^2
  u_: u(t)/Vs
  v_: v(t)/Vs
  r_: r(t)/Vs*L
  Xu: 0
  Xuu: 0
  Xuuu: 0
  Xvv: -0.041
  Xrr: -0.01
  Xvr: -0.015
  Yv: -0.13
  Yvv: -0.18
  Yvvv: 0
  Yvrr: 0
  Yr: 0.015
  Yrr: 0.021
  Yrrr: 0
  Yrvv: 0
  Nv: -0.37
  Nvv: -0.12
  Nvvv: 0
  Nvrr: 0
  Nr: -0.1
  Nrr: 0.005
  Nrrr: 0
  Nrvv: 0

Voici un exemple (très simplifié) de modèle de manoeuvrabilité qui utilise les commandes d’un modèle d’hélice + safran qui illustre la syntaxe pour utiliser dans un modèle de manoeuvrabilité les commandes d’un autre modèle :

- name: SBPropRudd
  model: propeller+rudder
  position of propeller frame:
      frame: test
      x: {value: -53.155, unit: m}
      y: {value: 3.750, unit: m}
      z: {value: 6.573, unit: m}
      phi: {value: 0, unit: rad}
      theta: {value: 4., unit: deg}
      psi: {value: 0, unit: deg}
  wake coefficient w: 0.066
  relative rotative efficiency etaR: 0.99
  thrust deduction factor t: 0.18
  rotation: anti-clockwise
  number of blades: 4
  blade area ratio AE/A0: 0.809
  diameter: {value: 4.65, unit: m}
  rudder area: {value: 10.8, unit: m^2}
  rudder height: {value: 4.171, unit: m}
  effective aspect ratio factor: 1.7
  lift tuning coefficient: 1.
  drag tuning coefficient: 1.
  position of rudder in body frame:
      x: {value: -57.36, unit: m}
      y: {value: 4.40, unit: m}
      z: {value: 4.26, unit: m}
- model: maneuvering
  name: man
  reference frame:
      frame: fremm
      x: {value: 0, unit: m}
      y: {value: 0, unit: m}
      z: {value: 2.22, unit: m}
      phi: {value: 0, unit: deg}
      theta: {value: 0, unit: deg}
      psi: {value: 0, unit: deg}
  X: 0.5*SBPropRudd(rpm)^2
  Y: 0
  Z: 0
  K: 0
  M: 0
  N: 0

Toutes les valeurs sont supposées en unité du système international. Le modèle nécessite de spécifier X, Y, Z, K, M et N, les autres clefs pouvant être quelconques. Des variables accessoires (telles que tau dans l’exemple ci-dessus) peuvent être utilisées. Le modèle vérifie automatiquement à l’exécution qu’il possède toutes les clefs nécessaires et infère l’ordre d’évaluation, autrement dit, une expression n’est évaluée que lorque toutes les expressions dont elle dépend l’ont été (quel que soit l’ordre dans lequel elles ont été déclarées).

Les expressions g, nu et rho sont utilisables et leurs valeurs sont celles renseignées dans la section environmental constants du fichier YAML.

On peut évaluer ces valeurs retardées des états x,y,z,u,v,w,p,q,r en écrivant x(t-tau) (par exemple) ou tau désigne une expression dont la valeur est positive. t désigne implicitement l’instant courant. La longueur maximale de l’historique est calculée juste après la lecture du fichier YAML d’entrée et avant la simulation, en fonction des modèles d’effort utilisés, de la façon suivante :

13.2.2 Grammaire

De façon plus formelle, les modèles doivent obéir à la grammaire suivante (format “Extended Backus-Naur Form” ou EBNF) :

expr                = term  operator_and_term*
add_operators       = '+' | '-'
mul_operators       = '*' | '/'
operator_and_term   = add_operators term
operator_and_factor = mul_operators factor
term                = factor operator_and_factor*
factor              = base ( '^' exponent)*
base                = ('('  expr ')') | atom
exponent            = base
atom                = function_call | identifier | double
function_call       = identifier '(' expr ')'
identifier          = alpha (alphanum | '_')*

13.3 Hélices Wageningen série B

13.3.1 Description

En 1937, l’ingénieur néerlandais L. Troost, alors employé du Maritime Research Institue Netherlands (MARIN) basé à Wageningen (Pays-Bas), créa les hélices Wageningen série B. Afin d’établir une base pour la conception d’hélices, il publia en 1938 puis en 1940 une série de tests systématiques en eau libre de 120 hélices “série B”, qui sont, à ce jour, les séries de test en eau libre les plus connus, bien que MARIN et d’autres instituts de recherche en aient réalisés d’autres par la suite.

En 1975, Oosterveld et Ossannen utilisèrent une régression statistique pour établir le modèle polynomial des hélices Wageningen présenté ici.

Un tutoriel présente l’utilisation de ce modèle dans le simulateur.

13.3.2 Hypothèses du modèle en eau libre

On adopte les notations suivantes :

Le modèle en eau libre est sujet aux hypothèses suivantes :

L’intérêt de ce modèle est qu’il est paramétrique et permet de représenter les performances de l’hélice sous forme adimensionnelle. On peut ainsi appliquer le même modèle (à un coefficient d’échelle près) à des hélices homothétiques. Une limitation supplémentaire du modèle polynomial en eau libre est que, contrairement au modèle quatre quadrants, il n’est valable qu’en marche avant (c’est-à-dire pour nn positif ou nul).

13.3.3 Dérivation du modèle en eau libre

Le modèle en eau libre est un modèle basé sur des considérations physiques, dont les coefficients peuvent aussi bien être obtenus expérimentalement, que numériquement par résolution des équations de Navier-Stokes. Le postulat est, qu’étant données les hypothèses ci-dessus, on peut s’attendre à ce que la poussée de l’hélice dépende :

On aurait donc :

T0ρaDbVacndμf(p0e)g T_0 \propto \rho^a\cdot D^b\cdot V_a^c \cdot n^d \cdot \mu^f\cdot(p_0-e)^g (13.1)

En effectuant l’analyse dimensionnelle pour exprimer aa, bb et dd en fonction des autres coefficients, on trouve :

T0ρ1fgD4c2fgVacn2cf2gμf(p0e)g T_0 \propto \rho^{1-f-g}\cdot D^{4-c-2f-g}\cdot V_a^c \cdot n^{2-c-f-2g} \cdot \mu^f\cdot(p_0-e)^g (13.2)

Soit, en regroupant les termes de même puissance :

T0ρn2D4(VanD)c(μρnD2)f(p0eρn2D2)g T_0 \propto \rho\cdot n^2\cdot D^4\cdot \left(\frac{V_a}{n\cdot D}\right)^c \cdot\left(\frac{\mu}{\rho\cdot n\cdot D^2}\right)^f\cdot\left(\frac{p_0-e}{\rho\cdot n^2\cdot D^2}\right)^g (13.3)

On définit le coefficient de poussée :

KT=T0ρn2D4 K_T = \frac{T_0}{\rho\cdot n^2\cdot D^4} (13.4)

Le coefficient d’avance JJ est défini par :

J=VanD J=\frac{V_a}{n\cdot D} (13.5)

Le nombre de Reynolds RnR_n s’exprime ici :

Rn=ρnD2μ R_n = \frac{\rho \cdot n\cdot D^2}{\mu} (13.6)

et le nombre de cavitation σ0\sigma_0 est :

σ0=p0e12ρn2D2 \sigma_0=\frac{p_0-e}{\frac{1}{2}\rho\cdot n^2\cdot D^2} (13.7)

donc il existe une fonction ff telle que

KT=f(J,Rn,σ0) K_T = f(J,R_n,\sigma_0) (13.8)

De même, pour le couple QQ, on définit le coefficient de couple KQK_Q par :

KQ=Q0ρn2D5 K_Q = \frac{Q_0}{\rho\cdot n^2\cdot D^5} (13.9)

Le modèle en eau libre consiste à expliciter les fonctions KTK_T et KQK_Q, dont on peut ensuite dériver la poussée et le couple.

13.3.4 Prise en compte des effets de la coque et du sillage

Lorsque l’écoulement au niveau de l’hélice a été perturbé par la coque, la vitesse du fluide au niveau de l’hélice VaV_a n’est pas égale (en valeur absolue) à la vitesse du navire par rapport à l’eau VsV_s, autrement dit VaVsV_a\neq V_s. La vitesse d’avance VaV_a est, en général, très difficile à connaître et l’on suppose qu’elle est proportionnelle à la vitesse du navire. On définit donc un coefficient ww (pour “wake”, soit “sillage” en anglais) tel que :

w=1VaVs w=1-\frac{V_a}{V_s} (13.10)

ww est constant en régime permanent, lorsque l’hélice opère dans les conditions nominales. Des ordres de grandeurs de ce coefficient sont donnés par exemple dans Carlton, pages 70, 72, 73 et 74.

En outre, l’hélice diminue la pression à l’arrière du navire, ce qui accroît sa résistance à l’avancement.

Pour prendre en compte ces phénomènes, on introduit le coefficient de succion tt tel que :

t=1RvTp t = 1 - \frac{R_v}{T_p} (13.11)

RvR_v est la résistance de remorquage (en N) à une vitesse VSV_S, sans hélice, et TpT_p est la somme des poussées des hélices (également en N) lorsque le navire va à la vitesse VSV_S en utilisant l’hélice.

La poussée réelle TbT_b est alors définie par :

Tb=(1t)T0=(1t)ρn2D4KT(J,Rn,σ0) T_b = (1-t)\cdot T_0 = (1-t)\cdot \rho\cdot n^2\cdot D^4 \cdot K_T(J, R_n,\sigma_0) (13.12)

et le couple réel est

Qb=ηRQ0=ηRρn2D5KQ(J,Rn,σ0) Q_b = \eta_R\cdot Q_0 = \eta_R\cdot \rho\cdot n^2\cdot D^5 \cdot K_Q(J, R_n,\sigma_0) (13.13)

ηR\eta_R est appelé rendement d’adaptation

J=VanD=(1w)VsnD J = \frac{V_a}{n\cdot D} = \frac{(1-w)\cdot V_s}{n\cdot D} (13.14)

13.3.5 Expression des coefficients KTK_T et KQK_Q

Afin de rendre les coefficients indépendants de la taille de l’hélice, on définit la fraction de surface de l’hélice AE/A0A_E/A_0, où AEA_E désigne l’aire des pales (en m^2) et A0=πD24A_0= \frac{\pi\cdot D^2}{4} est l’aire du disque circonscrit à l’hélice. Les séries sont valables pour 0.30AE/A01.050.30\leq A_E/A_0\leq 1.05.

On définit également le pas PP de l’hélice, un paramètre géométrique qui traduit la distance théorique parcourue par l’hélice en une révolution. Cette distance varie en fonction de la ligne de référence que l’on choisit. Les séries B de Wageningen utilisent le pas de face, mais il existe d’autres conventions. Les séries sont paramétrés en P/DP/D et l’on suppose que 0.5P/D1.40.5\leq P/D\leq 1.4.

On note 2Z72\leq Z\leq 7 le nombre de pales de l’hélice.

Les coefficients des polynômes pour KTK_T et KQK_Q sont notés CiTC_i^T et CiQC_i^Q respectivement, où ii est un entier tel que 1i471 \leq i \leq 47. s(i)s(i), s(i)s'(i), t(i)t(i), t(i)t'(i), u(i)u(i), u(i)u'(i), v(i)v(i) et v(i)v'(i) sont des exposants entre 0 et 6.

KT(J,P/D,AE/A0,Z,Rn=2×106)=i=147CkTJs(i)(P/D)t(i)(AE/A0)u(i)Zv(i)K_T(J, P/D, A_E/A_0, Z, R_n=2\times 10^6) = \sum_{i=1}^47 C_k^T \cdot J^{s(i)}\cdot (P/D)^{t(i)}\cdot (A_E/A_0)^{u(i)}\cdot Z^{v(i)}

KQ(J,P/D,AE/A0,Z,Rn=2×106)=i=147CkQJs(i)(P/D)t(i)(AE/A0)u(i)Zv(i)K_Q(J, P/D, A_E/A_0, Z, R_n=2\times 10^6) = \sum_{i=1}^47 C_k^Q \cdot J^{s'(i)}\cdot (P/D)^{t'(i)}\cdot (A_E/A_0)^{u'(i)}\cdot Z^{v'(i)}

Les coefficients CkTC_k^T et CkQC_k^Q sont définis pour un nombre de Reynolds Rn=2×106R_n=2\times 10^6, mais le modèle a été étendu pour des nombres de Reynolds entre 2×1062\times 10^6 et 2×1092\times 10^9 en introduisant des termes ΔKT\Delta K_T et ΔKQ\Delta K_Q supplémentaires :

KT(J,P/D,AE/A0,Z,Rn)=KT(J,P/D,AE/A0,Z,2×106)+ΔKT(J,P/D,AE/A0,Z,Rn)K_T(J, P/D, A_E/A_0, Z, R_n) = K_T(J, P/D, A_E/A_0, Z, 2\times 10^6) + \Delta K_T(J, P/D, A_E/A_0, Z, R_n)

KQ(J,P/D,AE/A0,Z,Rn)=KQ(J,P/D,AE/A0,Z,2×106)+ΔKQ(J,P/D,AE/A0,Z,Rn)K_Q(J, P/D, A_E/A_0, Z, R_n) = K_Q(J, P/D, A_E/A_0, Z, 2\times 10^6) + \Delta K_Q(J, P/D, A_E/A_0, Z, R_n)

13.3.6 Domaine de validité

Le modèle des séries B de Wageningen ne devrait être utilisé que lorsque les hypothèses suivantes sont vérifiées :

Les conditions sur ZZ et AEA0\frac{A_E}{A_0} touchant des grandeurs constantes au cours de la simulation, elles sont vérifiées avant le lancement et la simulation ne s’effectuera pas si ces conditions ne sont pas vérifiées.

Si le coefficient d’avance JJ se situe hors de l’intervalle [0,1.5]\left[0,1.5\right], un message d’avertissement est affiché et JJ est saturé pour être ramené dans l’intervalle : Jmin(max(J,0),1.5)J \leftarrow \min(\max(J,0),1.5)

La condition sur le pas PP est vérifiée en cours de simulation et un message d’avertissement est affiché sur la console. Par contre, le pas n’est pas modifié.

13.3.7 Expression des efforts

Les efforts générés par l’hélice sont calculés dans un repère spécifique renseigné dans la section position of propeller frame du fichier YAML. La poussée (c’est-à-dire l’effort généré par l’hélice sur le navire) est faite dans le sens des xx positifs.

Le sens de rotation de l’hélice doit également être spécifié parce qu’il détermine le signe du couple généré par l’hélice sur le navire. On définit ce sens de rotation en se plaçant derrière à l’hélice, en regardant dans la direction des xhélicex_{\textrm{hélice}} positifs (donc vers l’avant du navire). Autrement dit, l’axe de rotation de l’hélice est non pas xhélicex_{\textrm{hélice}} mais xhélice-x_{\textrm{hélice}}. Lorsque l’hélice tourne dans le sens horaire, elle génère un couple dans le sens trigonométrique, soit un couple de signe négatif lorsqu’il est exprimé dans le repère de l’hélice :

Le torseur des efforts générés par l’hélice et subis par le navire (apparaissant donc dans le membre de droite de l’équation fondamentale de la dynamique), exprimé dans le repère de l’hélice, est donc :

τhélice=[XYZKMN]hélice \tau_{\textrm{hélice}} = \left[\begin{array}{c} X\\ Y\\ Z\\ K\\ M\\ N \end{array}\right]_{\textrm{hélice}} (13.15)

=[Tb00κQb00]hélice = \left[\begin{array}{c} T_b\\ 0\\ 0\\ \kappa Q_b\\ 0\\ 0 \end{array}\right]_{\textrm{hélice}} (13.16)

=[(1t)ρn2D4KT(J,AE/A0,Z,P/D)00κηRρn2D5KQ(J,AE/A0,Z,P/D)00]hélice = \left[\begin{array}{c} (1-t)\cdot \rho\cdot n^2\cdot D^4 \cdot K_T(J, A_E/A_0, Z, P/D)\\ 0\\ 0\\ \kappa \cdot \eta_R\cdot \rho\cdot n^2\cdot D^5 \cdot K_Q(J, A_E/A_0, Z, P/D)\\ 0\\ 0\end{array}\right]_{\textrm{hélice}} (13.17)

κ\kappa vaut -1 si l’hélice tourne dans le sens horaire (en se plaçant derrière l’hélice et en regardant vers l’avant du navire) et +1 si elle tourne dans le sens trigonométrique.

Ce torseur est ensuite déplacé (changement de point d’application et changement de coordonnées) dans le repère body afin d’être sommé avec les autres lors du bilan des efforts.

13.3.8 Paramétrage

Voici un exemple de configuration possible :

controlled forces:
  - name: port side propeller
    model: wageningen B-series
    position of propeller frame:
        frame: mesh(TestShip)
        x: {value: -4, unit: m}
        y: {value: -2, unit: m}
        z: {value: 2, unit: m}
        phi: {value: 0, unit: rad}
        theta: {value: -10, unit: deg}
        psi: {value: -1, unit: deg}
    wake coefficient w: 0.9
    relative rotative efficiency eta: 1
    thrust deduction factor t: 0.7
    rotation: clockwise
    number of blades: 3
    blade area ratio AE/A0: 0.5
    diameter: {value: 2, unit: m}

13.3.9 Références

13.4 Contrôleur de cap simplifié

13.4.1 Description

Le but de ce contrôleur est de pouvoir réaliser des simulations sur houle (par exemple pour calculer des RAO de mouvements en post-traitant les résultats temporels d’xdyn) en limitant les variations de cap. Ce contrôleur génère directement un moment au centre de gravité du corps.

13.4.2 Expression des efforts

Le moment généré est Mz=Kψ(ψcoψ)Krr=σzzψ̈M_z = K_{\psi}\cdot (\psi_{\textrm{co}}-\psi) - K_r\cdot r = \sigma_{zz}\ddot{\psi}σzz\sigma_{zz} désigne le moment d’inertie total (inertie propre et inertie ajoutée) autour de l’axe zz.

Dans le domaine de Laplace, l’équation du contrôleur s’écrit :

σzzp2+Krp+Kψ=0 \sigma_{zz}p^2 + K_r p + K_{\psi} = 0 (13.18)

ou encore, sous forme canonique :

p2+2ζω0p+ω02=0 p^2 + 2\zeta\omega_0 p + \omega_0^2 = 0 (13.19)

d’où

Kψ=σzzω02K_{\psi} = \sigma_{zz} \omega_0^2 et Kr=2ζω0σzzK_r= 2\zeta\omega_0\sigma_{zz}

On peut exprimer ces gains en fonction de l’amortissement ζ\zeta et du temps de réponse TpT_p donné par Tp=2πω0T_p=\frac{2\pi}{\omega_0}.

Kψ=σzz(2πTp)2 K_{\psi} = \sigma_{zz}\left(\frac{2\pi}{T_p}\right)^2 (13.20)

Kr=2ζσzz2πTp K_{r} = 2\zeta\sigma_{zz}\frac{2\pi}{T_p} (13.21)

Le cap ψco\psi_{\textrm{co}} est donné dans le repère NED. Si l’on suppose que r=0r=0, pour ψ<ψco\psi<\psi_{\textrm{co}}, le moment généré doit être positif, donc Kψ(ψcoψ)>0K_{\psi}\cdot(\psi_{\textrm{co}}-\psi)>0. Par conséquent, Kψ>0K_{\psi}>0. De même, en prenant r<0r<0 et ψ=ψco\psi=\psi_{\textrm{co}}, le moment généré doit être positif pour contrer la vitesse rr, donc Krr>0-K_r\cdot r>0, d’où Kr>0K_r>0.

13.4.3 Paramétrage

controlled forces:
  - name: controller
    model: simple heading controller
    ksi: 0.9
    Tp: {value: 4, unit: s}

Ce modèle n’a qu’une seule commande, le cap psi_co :

- name: controller
  t: [0,1,3,10]
  psi_co: {unit: deg, values: [25, 30, 40, 0]}

13.5 Contrôleur de position simplifié

13.5.1 Description

Le but de ce contrôleur est de pouvoir réaliser des simulations sur houle (par exemple pour calculer des RAO de mouvement en post-traitant les résultats temporels d’xdyn) en limitant les variations de cap et de position. Ce contrôleur génère directement un moment et un effort au centre de gravité du corps.

13.5.2 Expression des efforts

L’effort généré suivant l’axe X est Fx=Kx(xcox)Kuu=σxxẍF_x = K_{x}\cdot (x_{\textrm{co}}-x) - K_u\cdot u = \sigma_{xx}\ddot{x}σxx\sigma_{xx} désigne le moment d’inertie total (inertie propre et inertie ajoutée) autour de l’axe xx. L’effort généré suivant l’axe Y est Fy=Ky(ycoy)Kvv=σyyÿF_y = K_{y}\cdot (y_{\textrm{co}}-y) - K_v\cdot v = \sigma_{yy}\ddot{y}σyy\sigma_{yy} désigne le moment d’inertie total (inertie propre et inertie ajoutée) autour de l’axe yy. Le moment généré est Mz=Kψ(ψcoψ)Krr=σzzψ̈M_z = K_{\psi}\cdot (\psi_{\textrm{co}}-\psi)-K_r\cdot r = \sigma_{zz}\ddot{\psi}σzz\sigma_{zz} désigne le moment d’inertie total (inertie propre et inertie ajoutée) autour de l’axe zz.

Dans le domaine de Laplace, les équations du contrôleur s’écrivent :

σxxp2+Kup+Kx=0 \sigma_{xx}p^2 + K_u p + K_{x} = 0 (13.22)

σyyp2+Kup+Ky=0 \sigma_{yy}p^2 + K_u p + K_{y} = 0 (13.23)

σzzp2+Krp+Kψ=0 \sigma_{zz}p^2 + K_r p + K_{\psi} = 0 (13.24)

ou encore, sous forme canonique :

p2+2ζxωxp+ωx2=0 p^2 + 2\zeta_x\omega_x p + \omega_x^2 = 0 (13.25)

p2+2ζyωyp+ωy2=0 p^2 + 2\zeta_y\omega_y p + \omega_y^2 = 0 (13.26)

p2+2ζpsiωψp+ωψ2=0 p^2 + 2\zeta_{psi}\omega_{\psi} p + \omega_{\psi}^2 = 0 (13.27)

d’où

Kx=σxxωx2K_{x} = \sigma_{xx} \omega_x^2 et Ku=2ζxωxσxxK_u= 2\zeta_x\omega_x\sigma_{xx}

Ky=σyyωy2K_{y} = \sigma_{yy} \omega_y^2 et Kv=2ζyωyσyyK_v= 2\zeta_y\omega_y\sigma_{yy}

Kψ=σzzωψ2K_{\psi} = \sigma_{zz} \omega_{\psi}^2 et Kr=2ζωψσzzK_r= 2\zeta\omega_{\psi}\sigma_{zz}

On peut exprimer ces gains en fonction de l’amortissement ζ\zeta et du temps de réponse TT donné par T=2πωT=\frac{2\pi}{\omega}.

Kx=σxx(2πTx)2 K_{x} = \sigma_{xx}\left(\frac{2\pi}{T_x}\right)^2 (13.28)

Ku=2ζσxx2πTx K_{u} = 2\zeta\sigma_{xx}\frac{2\pi}{T_x} (13.29)

Ky=σyy(2πTy)2 K_{y} = \sigma_{yy}\left(\frac{2\pi}{T_y}\right)^2 (13.30)

Kv=2ζσyy2πTy K_{v} = 2\zeta\sigma_{yy}\frac{2\pi}{T_y} (13.31)

Kψ=σzz(2πTψ)2 K_{\psi} = \sigma_{zz}\left(\frac{2\pi}{T_{\psi}}\right)^2 (13.32)

Kr=2ζσzz2πTψ K_{r} = 2\zeta\sigma_{zz}\frac{2\pi}{T_{\psi}} (13.33)

Le cap ψco\psi_{\textrm{co}} est donné dans le repère NED. Si l’on suppose que r=0r=0, pour ψ<ψco\psi<\psi_{\textrm{co}}, le moment généré doit être positif, donc Kψ(ψcoψ)>0K_{\psi}\cdot(\psi_{\textrm{co}}-\psi)>0. Par conséquent, Kψ>0K_{\psi}>0. De même, en prenant r<0r<0 et ψ=ψco\psi=\psi_{\textrm{co}}, le moment généré doit être positif pour contrer la vitesse rr, donc Krr>0-K_r\cdot r>0, d’où Kr>0K_r>0.

13.5.3 Paramétrage

controlled forces:
  - name: controller
    model: simple station-keeping controller
    ksi_x: 0.9
    T_x: {value: 2, unit: s}
    ksi_y: 0.85
    T_y: {value: 3, unit: s}
    ksi_psi: 0.8
    T_psi: {value: 4, unit: s}

Ce modèle a trois commandes, le cap psi_co, et la position x_co, y_co (dans le repère NED) :

- name: controller
  t: [0,1,3,10]
  x_co: {unit: m, values: [25, 30, 40, 0]}
  y_co: {unit: m, values: [25, 30, 40, 0]}
  psi_co: {unit: deg, values: [25, 30, 40, 0]}

13.6 Hélice et safran

13.6.1 Description

Ce modèle décrit l’ensemble constitué d’une hélice Wageningen et d’un safran. Les deux sont utilisés ensemble car le modèle de safran utilise le sillage de l’hélice pour calculer les efforts dus au safran (ce modèle fait donc l’hypothèse que le safran est situé en aval de l’hélice)

13.6.2 Expression des efforts

La figure suivante illustre l’ensemble modélisé :

Les efforts sont calculés au point P (de l’hélice) et transportés ensuite au centre de gravité. Ils s’écrivent :

FtotP=FsafranP+FhéliceP F\textrm{tot}_P = F\textrm{safran}_P + F\textrm{hélice}_P (13.34)

L’expression du torseur FhélicePF\textrm{hélice}_P est donnée dans le modèle “Hélices Wageningen série B”.

Les efforts dus au safran seront calculés au point R puis le torseur sera déplacé au centre de gravité. Dans la suite, on notera simplement FsafranF\textrm{safran} le torseur au point R.

La modélisation choisie sépare les efforts dus au safran en deux parties :

Fsafran=Fsafransillage+Fsafranhors sillage F\textrm{safran} = F\textrm{safran}^{\textrm{sillage}} + F\textrm{safran}^{\textrm{hors sillage}} (13.35)

Dans le repère lié au safran, celui-ci ne crée qu’une résultante suivant les axes X et Y (autrement dit, Fz=0 et Mx=My=Mz=0).

Les composantes FxF_x et FyF_y de cette résultantes s’expriment sous la forme :

Fx=Lift(Vs,Cl,α,S)sin(α)Drag(Vs,Cd,α,S)cos(α) F_x = -\textrm{Lift}(V_s, C_l, \alpha, S)\cdot\sin(\alpha) - \textrm{Drag}(V_s, C_d, \alpha, S)\cdot\cos(\alpha) (13.36)

Fy=+Lift(Vs,Cl,α,S)cos(α)Drag(Vs,Cd,α,S)sin(α) F_y = +\textrm{Lift}(V_s, C_l, \alpha, S)\cdot\cos(\alpha) - \textrm{Drag}(V_s, C_d, \alpha, S)\cdot\sin(\alpha) (13.37)

La vitesse VsV_s et l’aire SS sont calculées différemment suivant que l’on considère la partie du gouvernail dans le sillage de l’hélice ou celle à l’extérieur de ce sillage. L’angle d’incidence du fluide par rapport au safran est noté α\alpha et est défini par rapport à l’angle d’incidence aa du fluide (dans le repère NED) et l’angle du safran β\beta :

α=βa(VS)=βatan2(VSx,VSy) \alpha = \beta - a(V_S) = \beta - atan2({V_S}_x, {V_S}_y) (13.38)

Lift(VS,Cl,α,S)=12ρSVS2Cl(α)cos(α)Klift \textrm{Lift}(V_S, C_l, \alpha, S) = \frac{1}{2}\rho S V_S^2 Cl(\alpha)\cos(\alpha) K_{\textrm{lift}} (13.39)

Drag(VS,Cd,α,S)=12ρSVS2Cd(α)cos(α)Kdrag \textrm{Drag}(V_S, C_d, \alpha, S) = \frac{1}{2}\rho S V_S^2 Cd(\alpha)\cos(\alpha) K_{\textrm{drag}} (13.40)

Le coefficient cos(α)\cos(\alpha) permet de réduire l’efficacité du gouvernail lorsque α\alpha devient important.

Dans la suite, nous détaillerons le calcul de VSV_S, ClC_l, CdC_d et SS pour la partie hors sillage et la partie interne sillage.

13.6.2.1 Calcul de VSV_S

Les notations utilisées figurent sur le schéma ci-dessus. La poussée TT générée par l’hélice est égale à la variation de la quantité de mouvement :

T=ρAV1(V2Va) T = \rho\cdot A\cdot V_1\cdot(V_2 - V_a) (13.41)

(équation 3.31 Marine Rudders & Control Surfaces p. 49).

Cette poussée est également égale à la variation de pression multipliée par l’aire du disque :

T=A(P1P1) T = A\cdot(P_1'-P_1) (13.42)

On écrit l’équation de Bernoulli en amont du safran, entre P0P_0 et P1P_1, puis en aval du safran, entre P1P_1' et P2P_2 :

P0+12ρVa2=P1+12ρV12 P_0 + \frac{1}{2}\rho V_a^2 = P_1 + \frac{1}{2}\rho V_1^2 (13.43)

P1+12ρV12=P2+12ρV22 P_1' + \frac{1}{2}\rho V_1^2 = P_2 + \frac{1}{2}\rho V_2^2 (13.44)

d’où

P1=P2+12ρV2212ρV12 P_1' = P_2 + \frac{1}{2}\rho V_2^2 - \frac{1}{2}\rho V_1^2 (13.45)

P1=P0+12ρVa212ρV12 P_1 = P_0 + \frac{1}{2}\rho V_a^2 - \frac{1}{2}\rho V_1^2 (13.46)

puis

P1P1=P2P0+12ρ(V22Va2) P_1'-P_1 = P_2-P_0 + \frac{1}{2}\rho(V_2^2-V_a^2) (13.47)

Les pressions P2P_2 et P0P_0 correspondent à des écoulements non-perturbés (très en amont et très en aval du couple (safran,hélice)). Par conséquent, ces deux pressions sont égales :

T=A(P1P1)=12ρA(V22Va2) T = A\cdot(P_1'-P_1) = \frac{1}{2}\rho A(V_2^2-V_a^2) (13.48)

(équation 3.32 Marine Rudders & Control Surfaces p. 49)

On en déduit l’expression de V2V_2 :

V2=Va2+2TρA V_2 = \sqrt{V_a^2 + \frac{2T}{\rho A}} (13.49)

La vitesse V1V_1 au niveau du safran peut être déduite de l’égalité de deux expressions de TT :

On en déduit :

V1=12(Va+V2)=Va+12(V2Va) V_1 = \frac{1}{2}(V_a + V_2) = V_a + \frac{1}{2}(V_2-V_a) (13.50)

Les calculs de V0V_0 et de V2V_2 étant fait en régime stationnaire, cette expression de la vitesse V1V_1 ne tient pas compte de l’accélération du fluide entre l’hélice et le safran. On modélise l’effet de cette accélération par un facteur KRK_R appelé “facteur de contraction” (cf. Marine Rudders & Control Surfaces eq. 3.37 p.51). On obtient ainsi une vitesse uRSu_{RS} telle que :

uRS=Va+KR(V2Va) u_{RS} = V_a + K_R(V_2-V_a) (13.51)

avec

Kr=0.5+0.51+0.15|ΔxD| Kr = 0.5+\frac{0.5}{1+\frac{0.15}{\left|\frac{\Delta_x}{D}\right|}} (13.52)

Δx\Delta_x désigne la distance entre l’hélide et le safran (suivant l’axe xx) et DD est le diamètre de l’hélice.

Afin de factoriser cette expression, on peut exprimer la vitesse V2V_2 en fonction de la vitesse VaV_a :

V2=Va2+2TρA V_2 = \sqrt{V_a^2 + \frac{2T}{\rho A}} (13.53)

or une autre expression de TT peut être donnée à partir du modèle de Wageningen :

T=ρn2D4KT T = \rho n^2 D^4 K_T (13.54)

2TρA=8πn2D2KT \frac{2T}{\rho A} = \frac{8}{\pi} n^2 D^2 K_T (13.55) mais le paramètre d’avance JJ s’écrit :

J=VanD J = \frac{V_a}{n D} (13.56)

donc

2TρA=8πKTJ2Va2 \frac{2T}{\rho A} = \frac{8}{\pi} \frac{K_T}{J^2} V_a^2 (13.57)

d’où

uRS=Va(1+KR(1+8KTπJ21)) u_{RS} = V_a\left(1 + K_R \left(\sqrt{1 + \frac{8 K_T}{\pi J^2}} - 1\right)\right) (13.58)

On pose

CTh=8πKTJ2 C_{Th} = \frac{8}{\pi} \frac{K_T}{J^2} (13.59)

uRS=Va(1+KR(1+CTh1)) u_{RS} = V_a\left(1 + K_R \left(\sqrt{1 + C_{Th}} - 1\right)\right) (13.60)

Cette vitesse uRSu_{RS} a été calculée en faisant les hypothèses suivantes :

On constate en pratique des écarts peuvent atteindre 30% entre uRSu_{RS} et les mesures réalisées lors d’essais. C’est pourquoi on multiplie la vitesse uRSu_{RS} par un facteur RFRF appelé “facteur de réduction” (cf. eq 11.1 p.? 371 Marine Rudders & Control Surfaces) :

RF=10.135CTh RF = 1-0.135\sqrt{C_{Th}} (13.61)

La vitesse dans le sillage de l’hélice s’exprime donc (dans le repère “body”) :

VS=[RFVa(1+KR(1+CTh1))v0] V_S = \left[\begin{array}{c}RF\cdot V_a\left(1 + K_R \left(\sqrt{1 + C_{Th}} - 1\right)\right)\\ v\\0\end{array}\right] (13.62)

La vitesse hors du sillage est simplement :

VS=[Vav0] V_S = \left[\begin{array}{c}V_a\\ v\\0\end{array}\right] (13.63)

Va=(1w)uV_a = (1-w)\cdot u, ww désignant le coefficient de sillage.

13.6.2.2 Calcul de ClC_l

On introduit le rapport de forme Λ\Lambda (cf. Manoeuvring Technical Manual p. 76)

Λ=KΛb2AR \Lambda = K_{\Lambda}\frac{b^2}{A_R} (13.64)

KΛK_{\Lambda} est un paramètre renseigné par l’utilisateur.

On utilise la formule de Soeding (cf. Manoeuvring Technical Manual, éq. 1.2.8 p.77 et éq. 1.2.48 p.97) :

Cl(α)=2πΛ(Λ+1)(Λ+2)2sin(α) Cl(\alpha) = 2\pi\frac{\Lambda(\Lambda+1)}{(\Lambda+2)^2}\sin(\alpha) (13.65)

13.6.2.3 Calcul de CdC_d

On utilise la formule suivante (cf. Maneuvering Technical Manual, p. 78 eq. 1.2.9)

Cd=1.1Cl2πΛ+Cd0 C_d = 1.1 \frac{Cl^2}{\pi \Lambda} + Cd_0 (13.66)

Le coefficient de résistance Cd0Cd_0 vaut :

Cd0=2.5Cf Cd_0 = 2.5 C_f (13.67)

(cf. Maneuvering Technical Manual, p. 78 (§ for Cd0))

CfC_f est un coefficient ITTC que l’on trouve par exemple dans Marine rudders and Control Surfaces, p.31 éq. 3.18 :

Cf=0.075(log(Rn)log(10.0)2)2 Cf = \frac{0.075}{\left(\frac{\log(R_n)}{log(10.0)}-2\right)^2} (13.68)

Le nombre de Reynolds RnR_n du safran est donné par (cf. Maneuvering Technical Manual, p. 78 éq. 1.2.12) :

Rn=Vscν Rn = Vs \frac{c}{\nu} (13.69)

où la corde cc du safran vaut :

c=ARb c = \frac{A_R}{b} (13.70)

13.6.2.4 Calcul de SS

On sépare l’aire ARA_R du safran en deux parties : une partie à l’intérieur du sillage et une partie à l’extérieur. La partie à l’intérieur du sillage est obtenue en considérant le diamètre du sillage DwD_w et la partie à l’extérieur en faisant la différence avec ARA_R.

Ssillage=min(AR,cDw) S_{\textrm{sillage}} = \min(A_R, c\cdot D_w) (13.71)

Shors sillage=ARSsillage S_{\textrm{hors sillage}} = A_R - S_{\textrm{sillage}} (13.72)

cc est la corde calculée ci-dessus.

Le diamètre DwD_w du sillage est défini par :

DwDhélice=V1uRS \frac{D_w}{D_{\textrm{hélice}}} = \sqrt{\frac{V_1}{u_{RS}}} (13.73)

V1=Va(1+0.5(1+CTh1)) V_1 = V_a\left(1 + 0.5 \left(\sqrt{1 + C_{Th}} - 1\right)\right) (13.74)

uRS=Va(1+KR(1+CTh1)) u_{RS} = V_a\left(1 + K_R \left(\sqrt{1 + C_{Th}} - 1\right)\right) (13.75)

d’où

DwDhélice=1+0.5(1+CTh1)1+KR(1+CTh1) \frac{D_w}{D_{\textrm{hélice}}} = \sqrt{\frac{1+0.5(\sqrt{1+C_{Th}}-1)}{1+K_R(\sqrt{1+C_{Th}}-1)}} (13.76)

13.6.3 Paramétrage

controlled forces:
  - name: Prop. & rudder
    model: propeller+rudder
    position of propeller frame:
        frame: mesh(TestShip)
        x: {value: -4, unit: m}
        y: {value: -2, unit: m}
        z: {value: 2, unit: m}
        phi: {value: 0, unit: rad}
        theta: {value: -10, unit: deg}
        psi: {value: -1, unit: deg}
    wake coefficient w: 0.9
    relative rotative efficiency etaR: 1
    thrust deduction factor t: 0.7
    rotation: clockwise
    number of blades: 3
    blade area ratio AE/A0: 0.5
    diameter: {value: 2, unit: m}
    rudder area: {value: 2.2, unit: m^2}
    rudder height: {value: 2, unit: m^2}
    effective aspect ratio: 1.7
    lift tuning coefficient: 2.1
    drag tuning coefficient: 1
    position of rudder in body frame:
        x: {value: -5.1, unit: m}
        y: {value: -2, unit: m}
        z: {value: 2, unit: m}

On retrouve les paramètres du modèle ‘Wageningen’ qui ne sont pas décrits à nouveau ici (hormis model). On a les paramètres supplémentaires suivants :

Ce modèle a trois commandes :

- name: controller
  t: [1,3,10]
  rpm: {unit: rpm, values: [3000, 3000, 4000]}
  P/D: [0.7,0.7,0.8]
  beta: {unit: deg, values: [10,-15,20]}

13.6.4 Sorties

Pour obtenir les sorties d’effort de ce modèle, on écrit par exemple :

output:
   - format: csv
     filename: propRudd.csv
     data: [t, 'Fx(Prop. & rudder,TestShip,TestShip)', 'Fx(Prop. & rudder,TestShip,NED)']

On obtient dans l’exemple précédent la projection suivant l’axe XX du repère TestShip de l’effort Prop. & rudder (correspondant au nom de l’actionneur renseigné dans la clef name afin de pouvoir définir plusieurs actionneurs du même type) ainsi que la projection de ce même effort suivant l’axe XX du repère NED.

13.6.5 Références

13.7 Modèle Kt(J) & Kq(J)

13.7.1 Description

Le but de ce modèle est de spécifier des courbes d’effort d’hélice KtK_t et KqK_q en fonction du coefficient d’avance JJ uniquement. Hormis le calcul de KtKt et KqKq, ce modèle est identique au modèle d’hélice Wageningen série B décrit ci-dessus. Le torseur des efforts générés par l’hélice et subis par le navire (apparaissant donc dans le membre de droite de l’équation fondamentale de la dynamique), exprimé dans le repère de l’hélice, est donc :

τhélice=[XYZKMN]hélice=[Tb00κQb00]hélice=[(1t)ρn2D4KT(J)00κηRρn2D5KQ(J)00]hélice \tau_{\textrm{hélice}} = \left[\begin{array}{c} X\\ Y\\ Z\\ K\\ M\\ N \end{array}\right]_{\textrm{hélice}} = \left[\begin{array}{c} T_b\\ 0\\ 0\\ \kappa Q_b\\ 0\\ 0 \end{array}\right]_{\textrm{hélice}} = \left[\begin{array}{c} (1-t)\cdot \rho\cdot n^2\cdot D^4 \cdot K_T(J)\\ 0\\ 0\\ \kappa \cdot \eta_R\cdot \rho\cdot n^2\cdot D^5 \cdot K_Q(J)\\ 0\\ 0\end{array}\right]_{\textrm{hélice}} (13.77)

13.7.2 Paramétrage

Voici un exemple de configuration possible :

controlled forces:
  - name: port side propeller
    model: Kt(J) & Kq(J)
    position of propeller frame:
        frame: mesh(TestShip)
        x: {value: -4, unit: m}
        y: {value: -2, unit: m}
        z: {value: 2, unit: m}
        phi: {value: 0, unit: rad}
        theta: {value: -10, unit: deg}
        psi: {value: -1, unit: deg}
    wake coefficient w: 0.9
    relative rotative efficiency etaR: 1
    thrust deduction factor t: 0.7
    rotation: clockwise
    diameter: {value: 2, unit: m}
    J: [-1.00000E+00,-8.00000E-01,-5.00000E-01,-2.50000E-01,-1.00000E-03,1.00000E-03, 2.00000E-01, 4.00000E-01, 6.00000E-01, 7.00000E-01, 8.00000E-01,1.00000E+00]
    Kt: [-4.50000E-01,-2.50000E-01,-1.90000E-01,-2.00000E-01,-2.00000E-01,3.25000E-01, 2.80000E-01, 2.33000E-01, 1.85000E-01, 1.62000E-01,1.36000E-01,8.50000E-02]
    Kq: [-4.80000E-02,-3.30000E-02,-2.20000E-02,-2.50000E-02,-2.80000E-02,3.40000E-02, 3.26000E-02, 2.97000E-02, 2.55000E-02, 2.30000E-02, 2.040000E-02,1.50000E-02]

13.7.3 Sorties

Pour obtenir les sorties d’effort de ce modèle, on écrit par exemple :

output:
   - format: csv
     filename: prop.csv
     data: [t, 'Fx(port side propeller,TestShip,TestShip)', 'Fx(port side propeller,TestShip,NED)']

On obtient dans l’exemple précédent la projection suivant l’axe XX du repère TestShip de l’effort port side propeller (correspondant au nom de l’actionneur renseigné dans la clef name afin de pouvoir définir plusieurs actionneurs du même type) ainsi que la projection de ce même effort suivant l’axe XX du repère NED.

13.8 Modèle d’effort distant

Si l’on souhaite utiliser un modèle d’effort qui n’est pas implémenté dans xdyn, il est possible de l’implémenter séparément et de l’appeler depuis xdyn, sans intervenir sur le code source d’xdyn.

13.8.1 Description

Comme pour les modèles de houle distants, on utilise la technologie “gRPC” : le modèle d’effort sera alors encapsulé dans un service et appelé par xdyn en utilisant des paramètres spécifiés dans le fichier de configuration YAML d’xdyn.

13.8.2 Paramétrage

Dans la section controlled forces, on ajoute une section de la forme suivante :

- model: grpc
  url: http://localhost:50001

Le paramètre model: grpc indique à xdyn qu’il s’agit d’un modèle d’effort distant et url donne l’adresse à laquelle le serveur gRPC peut être joint.

Ces modèles ont accès à toutes les commandes définies dans la simulation. Le point d’application des modèles d’effort gRPC est défini par le modèle d’effort lui-même, et de la même façon que pour le modèle de manœuvrabilité.

Ainsi, les réponses renvoyées à xdyn par le modèle d’effort sont définies par :

message ForceResponse
{
    double Fx = 1;                              // Projection of the force acting on "BODY" on the X-axis of the frame defined by the force model itself and returned by set_parameters.
    double Fy = 2;                              // Projection of the force acting on "BODY" on the Y-axis of the frame defined by the force model itself and returned by set_parameters.
    double Fz = 3;                              // Projection of the force acting on "BODY" on the Z-axis of the frame defined by the force model itself and returned by set_parameters.
    double Mx = 4;                              // Projection of the torque acting on "BODY" on the X-axis of the frame defined by the force model itself and returned by set_parameters, expressed at the origin of that frame.
    double My = 5;                              // Projection of the torque acting on "BODY" on the Y-axis of the frame defined by the force model itself and returned by set_parameters, expressed at the origin of that frame.
    double Mz = 6;                              // Projection of the torque acting on "BODY" on the Z-axis of the frame defined by the force model itself and returned by set_parameters, expressed at the origin of that frame.
    map<string, double> extra_observations = 7; // Anything we wish to serialize. Specific to each force model.
}

13.8.3 Exemple d’utilisation

Le tutoriel 10 détaille

14 Tutoriels

14.1 Tutoriel 1: chute libre

On commence par définir les conventions de rotation :

rotations convention:
    - psi
    - theta'
    - phi''

Puis l’on donne des constantes environnementales :

environmental constants:
    g:
      unit: m/s^2
      value: 9.81
    nu:
      unit: m^2/s
      value: 1.18e-06
    rho:
      unit: kg/m^3
      value: 1000

Aucun modèle d’environnement (houle, vent…) n’est nécessaire pour cette simulation :

environment models:
    []

On définit la position du repère “body” par rapport au maillage :

position of body frame relative to mesh:
    frame: mesh
    phi:
      unit: rad
      value: 1
    psi:
      unit: rad
      value: 2
    theta:
      unit: rad
      value: 3
    x:
      unit: m
      value: 0
    y:
      unit: m
      value: 0
    z:
      unit: m
      value: -10

Les conditions initiales sont décrites comme suit :

initial position of body frame relative to NED:
    frame: NED
    phi:
      unit: rad
      value: 0
    psi:
      unit: rad
      value: 0
    theta:
      unit: rad
      value: 0
    x:
      unit: m
      value: 4
    y:
      unit: m
      value: 8
    z:
      unit: m
      value: 12
initial velocity of body frame relative to NED:
    frame: ball
    p:
      unit: rad/s
      value: 0
    q:
      unit: rad/s
      value: 0
    r:
      unit: rad/s
      value: 0
    u:
      unit: m/s
      value: 1
    v:
      unit: m/s
      value: 0
    w:
      unit: m/s
      value: 0

Les données dynamiques comprennent la masse, la matrice d’inertie, les inerties ajoutées et la position du centre d’inertie :

dynamics:
    added mass matrix at the center of gravity and projected in the body frame:
      row 1:
      - 0
      - 0
      - 0
      - 0
      - 0
      - 0
      row 2:
      - 0
      - 0
      - 0
      - 0
      - 0
      - 0
      row 3:
      - 0
      - 0
      - 0
      - 0
      - 0
      - 0
      row 4:
      - 0
      - 0
      - 0
      - 0
      - 0
      - 0
      row 5:
      - 0
      - 0
      - 0
      - 0
      - 0
      - 0
      row 6:
      - 0
      - 0
      - 0
      - 0
      - 0
      - 0
    centre of inertia:
      frame: ball
      x:
        unit: m
        value: 0
      y:
        unit: m
        value: 0
      z:
        unit: m
        value: 0.5
    hydrodynamic forces calculation point in body frame:
      x:
        unit: m
        value: 0.696
      y:
        unit: m
        value: 0
      z:
        unit: m
        value: 1.418
    rigid body inertia matrix at the center of gravity and projected in the body frame:
      row 1:
      - 1E6
      - 0
      - 0
      - 0
      - 0
      - 0
      row 2:
      - 0
      - 1E6
      - 0
      - 0
      - 0
      - 0
      row 3:
      - 0
      - 0
      - 1E6
      - 0
      - 0
      - 0
      row 4:
      - 0
      - 0
      - 0
      - 1E6
      - 0
      - 0
      row 5:
      - 0
      - 0
      - 0
      - 0
      - 1E6
      - 0
      row 6:
      - 0
      - 0
      - 0
      - 0
      - 0
      - 1E6

Seule la gravité agit sur le solide :

external forces:
    - model: gravity

En définitive, on obtient le fichier suivant :

rotations convention: [psi, theta', phi'']

environmental constants:
    g: {value: 9.81, unit: m/s^2}
    rho: {value: 1000, unit: kg/m^3}
    nu: {value: 1.18e-6, unit: m^2/s}
environment models: []

bodies: # All bodies have NED as parent frame
  - name: ball
    position of body frame relative to mesh:
        frame: mesh
        x: {value: 0, unit: m}
        y: {value: 0, unit: m}
        z: {value: -10, unit: m}
        phi: {value: 1, unit: rad}
        theta: {value: 3, unit: rad}
        psi: {value: 2, unit: rad}
    initial position of body frame relative to NED:
        frame: NED
        x: {value: 4, unit: m}
        y: {value: 8, unit: m}
        z: {value: 12, unit: m}
        phi: {value: 0, unit: rad}
        theta: {value: 0, unit: rad}
        psi: {value: 0, unit: rad}
    initial velocity of body frame relative to NED:
        frame: ball
        u: {value: 1, unit: m/s}
        v: {value: 0, unit: m/s}
        w: {value: 0, unit: m/s}
        p: {value: 0, unit: rad/s}
        q: {value: 0, unit: rad/s}
        r: {value: 0, unit: rad/s}
    dynamics:
        hydrodynamic forces calculation point in body frame:
            x: {value: 0.696, unit: m}
            y: {value: 0, unit: m}
            z: {value: 1.418, unit: m}
        centre of inertia:
            frame: ball
            x: {value: 0, unit: m}
            y: {value: 0, unit: m}
            z: {value: 0.5, unit: m}
        rigid body inertia matrix at the center of gravity and projected in the body frame:
            row 1: [1E6,0,0,0,0,0]
            row 2: [0,1E6,0,0,0,0]
            row 3: [0,0,1E6,0,0,0]
            row 4: [0,0,0,1E6,0,0]
            row 5: [0,0,0,0,1E6,0]
            row 6: [0,0,0,0,0,1E6]
        added mass matrix at the center of gravity and projected in the body frame:
            row 1: [0,0,0,0,0,0]
            row 2: [0,0,0,0,0,0]
            row 3: [0,0,0,0,0,0]
            row 4: [0,0,0,0,0,0]
            row 5: [0,0,0,0,0,0]
            row 6: [0,0,0,0,0,0]
    external forces:
      - model: gravity
output:
   - format: csv
     filename: falling_ball.csv
     data: [x(ball)]
   - format: hdf5
     filename: falling_ball.h5
     data: ['x(ball)','y(ball)','z(ball)','Fz(gravity,ball,ball)']
   - format: json
     filename: falling_ball.json
     data: ['x(ball)','y(ball)','z(ball)','qr(ball)','qi(ball)','qj(ball)','qk(ball)']

14.1.1 Lancement de la simulation

La simulation peut s’exécuter comme suit :

xdyn tutorial_01_falling_ball.yml --dt 0.01 --tend 1 -o out.csv

Pour avoir des sorties sur la console, on peut faire :

xdyn tutorial_01_falling_ball.yml --dt 1 --tend 5 -o tsv

tsv signifie ici “tab-separated values”.

On peut également changer l’instant initial (étant entendu que les conditions initiales définies dans le fichier YAML s’appliquent à cet instant initial, quel qu’il soit, et non pas à t = 0) :

xdyn tutorial_01_falling_ball.yml --dt 0.01 --tstart 2 --tend 3 -o out.csv

On peut choisir le solveur :

xdyn tutorial_01_falling_ball.yml --dt 0.01 --tend 1 -s rk4 -o out.csv

La liste de toutes les options est disponible en exécutant :

xdyn -h
This is a ship simulator created during the project 'Bassin Numerique (IRT Jules Verne)'.
(c) 2014-2015, IRT Jules Verne (https://www.irt-jules-verne.fr/),
               SIREHNA (http://www.sirehna.com/),
               Naval Group (https://www.naval-group.com/en/),
               Bureau Veritas (https://www.bureauveritas.fr/),
               Hydrocean (https://marine-offshore.bureauveritas.com/bvsolutions),
               STX France (http://chantiers-atlantique.com/en/),
               LHEEA (https://lheea.ec-nantes.fr/)
for the initial version.
(c) 2015-2018 SIREHNA & Naval Group for all subsequent versions.

ID: 78575585c0259ecf918db5e96e769cf1ca05caf7
SHA of the SSC used: 0x38848d02b4f1bc34c60f11a5ff69d89dba5d2773


USAGE: xdyn <yaml file> [-hd] [-y ARG] [-s ARG] [dt ARG] [--tstart ARG] [--tend ARG] [-o ARG] [-w ARG] 
Options:
  -h [ --help ]              Show this help message
  -y [ --yml ] arg           Name(s) of the YAML file(s)
  -s [ --solver ] arg (=rk4) Name of the solver: euler, rk4, rkck for Euler, 
                             Runge-Kutta 4 & Runge-Kutta-Cash-Karp 
                             respectively.
  --dt arg                   Initial time step (or value of the fixed time step
                             for fixed step solvers)
  --tstart arg (=0)          Date corresponding to the beginning of the 
                             simulation (in seconds)
  --tend arg                 Last time step
  -o [ --output ] arg        Name of the output file where all computed data 
                             will be exported.
                             Possible values/extensions are csv, tsv, json, 
                             hdf5, h5, ws
  -w [ --waves ] arg         Name of the output file where the wave heights 
                             will be stored ('output' section of the YAML 
                             file). In case output is made to a HDF5 file or 
                             web sockets, this option appends the wave height 
                             to the main output
  -d [ --debug ]             Used by the application's support team to help 
                             error diagnosis. Allows us to pinpoint the exact 
                             location in code where the error occurred (do not 
                             catch exceptions), eg. for use in a debugger.

14.1.2 Résultats

Voici un tracé de l’élévation au cours du temps :

Figure 14.1: Élévation au cours du temps
Figure 14.1: Élévation au cours du temps

14.2 Tutoriel 2 : oscillations en immersion

Ce tutoriel vise à illustrer l’utilisation des modèles hydrostatiques et à comparer succinctement les modèles non-linear hydrostatic (exact) et non-linear hydrostatic (fast).

14.2.1 Description du problème

Dans cet exemple, nous considérons un navire soumis uniquement à la pesanteur et aux efforts hydrostatiques, sans amortissement. Le navire est lâché sans vitesse initiale au-dessus de la surface libre (supposée plane) et va donc réaliser des oscillations non-amorties en immersion.

14.2.2 Écriture du fichier de configuration du simulateur

Nous documentons ici uniquement les changements par rapport au tutoriel 1.

L’environnement est défini de la façon suivante :

environment models:
    - constant sea elevation in NED frame:
        unit: m
        value: 0
      model: no waves

Comme décrit dans la documentation du fichier d’entrée, ceci signifie que la surface libre est parfaitement plane et horizontale, à la hauteur z=0z=0 dans le repère NED.

Par rapport au tutoriel 1, la position du repère “body” par rapport au maillage est ici importante puisque l’on fournit un fichier STL :

position of body frame relative to mesh:
    frame: mesh
    phi:
      unit: rad
      value: 0
    psi:
      unit: rad
      value: 0
    theta:
      unit: rad
      value: 0
    x:
      unit: m
      value: 9.355
    y:
      unit: m
      value: 0
    z:
      unit: m
      value: -3.21

On décrit dans les conditions initiales le fait que le bateau est lâché à 5 m au-dessus du niveau de l’eau (l’axe z du repère NED étant orienté vers le bas, des valeurs négatives correspondent à des points au-dessus de la surface libre) :

initial position of body frame relative to NED:
    frame: NED
    phi:
      unit: deg
      value: 0
    psi:
      unit: deg
      value: 0
    theta:
      unit: rad
      value: -.0058
    x:
      unit: m
      value: 0
    y:
      unit: m
      value: 0
    z:
      unit: m
      value: -5
initial velocity of body frame relative to NED:
    frame: TestShip
    p:
      unit: rad/s
      value: 0
    q:
      unit: rad/s
      value: 0
    r:
      unit: rad/s
      value: 0
    u:
      unit: m/s
      value: 0
    v:
      unit: m/s
      value: 0
    w:
      unit: m/s
      value: 0

Les données dynamiques comprennent la masse, la matrice d’inertie, les inerties ajoutées et la position du centre d’inertie :

dynamics:
    added mass matrix at the center of gravity and projected in the body frame:
      row 1:
      - 3.519e4
      - 0
      - 0
      - 0
      - 0
      - 0
      row 2:
      - 0
      - 3.023e5
      - 0
      - 0
      - 0
      - 0
      row 3:
      - 0
      - 0
      - 1.980e5
      - 0
      - 0
      - 0
      row 4:
      - 0
      - 0
      - 0
      - 3.189e5
      - 0
      - 0
      row 5:
      - 0
      - 0
      - 0
      - 0
      - 8.866e6
      - 0
      row 6:
      - 0
      - 0
      - 0
      - 0
      - 0
      - 6.676e6
    centre of inertia:
      frame: TestShip
      x:
        unit: m
        value: 0.258
      y:
        unit: m
        value: 0
      z:
        unit: m
        value: 0.432
    hydrodynamic forces calculation point in body frame:
      x:
        unit: m
        value: 0.696
      y:
        unit: m
        value: 0
      z:
        unit: m
        value: 1.418
    rigid body inertia matrix at the center of gravity and projected in the body frame:
      row 1:
      - 253310
      - 0
      - 0
      - 0
      - 0
      - 0
      row 2:
      - 0
      - 253310
      - 0
      - 0
      - 0
      - 0
      row 3:
      - 0
      - 0
      - 253310
      - 0
      - 0
      - 0
      row 4:
      - 0
      - 0
      - 0
      - 1.522e6
      - 0
      - 0
      row 5:
      - 0
      - 0
      - 0
      - 0
      - 8.279e6
      - 0
      row 6:
      - 0
      - 0
      - 0
      - 0
      - 0
      - 7.676e6

On utilise dans un premier temps le modèle hydrostatique approché dont la documentation est décrite ici :

external forces:
    - model: gravity
    - model: non-linear hydrostatic (fast)

En définitive, on obtient le fichier suivant :

bodies:
- dynamics:
    added mass matrix at the center of gravity and projected in the body frame:
      row 1:
      - 3.519e4
      - 0
      - 0
      - 0
      - 0
      - 0
      row 2:
      - 0
      - 3.023e5
      - 0
      - 0
      - 0
      - 0
      row 3:
      - 0
      - 0
      - 1.980e5
      - 0
      - 0
      - 0
      row 4:
      - 0
      - 0
      - 0
      - 3.189e5
      - 0
      - 0
      row 5:
      - 0
      - 0
      - 0
      - 0
      - 8.866e6
      - 0
      row 6:
      - 0
      - 0
      - 0
      - 0
      - 0
      - 6.676e6
    centre of inertia:
      frame: TestShip
      x:
        unit: m
        value: 0.258
      y:
        unit: m
        value: 0
      z:
        unit: m
        value: 0.432
    hydrodynamic forces calculation point in body frame:
      x:
        unit: m
        value: 0.696
      y:
        unit: m
        value: 0
      z:
        unit: m
        value: 1.418
    rigid body inertia matrix at the center of gravity and projected in the body frame:
      row 1:
      - 253310
      - 0
      - 0
      - 0
      - 0
      - 0
      row 2:
      - 0
      - 253310
      - 0
      - 0
      - 0
      - 0
      row 3:
      - 0
      - 0
      - 253310
      - 0
      - 0
      - 0
      row 4:
      - 0
      - 0
      - 0
      - 1.522e6
      - 0
      - 0
      row 5:
      - 0
      - 0
      - 0
      - 0
      - 8.279e6
      - 0
      row 6:
      - 0
      - 0
      - 0
      - 0
      - 0
      - 7.676e6
  external forces:
  - model: gravity
  - model: non-linear hydrostatic (fast)
  initial position of body frame relative to NED:
    frame: NED
    phi:
      unit: deg
      value: 0
    psi:
      unit: deg
      value: 0
    theta:
      unit: rad
      value: -.0058
    x:
      unit: m
      value: 0
    y:
      unit: m
      value: 0
    z:
      unit: m
      value: -5
  initial velocity of body frame relative to NED:
    frame: TestShip
    p:
      unit: rad/s
      value: 0
    q:
      unit: rad/s
      value: 0
    r:
      unit: rad/s
      value: 0
    u:
      unit: m/s
      value: 0
    v:
      unit: m/s
      value: 0
    w:
      unit: m/s
      value: 0
  mesh: test_ship.stl
  name: TestShip
  position of body frame relative to mesh:
    frame: mesh
    phi:
      unit: rad
      value: 0
    psi:
      unit: rad
      value: 0
    theta:
      unit: rad
      value: 0
    x:
      unit: m
      value: 9.355
    y:
      unit: m
      value: 0
    z:
      unit: m
      value: -3.21
environment models:
- constant sea elevation in NED frame:
    unit: m
    value: 0
  model: no waves
environmental constants:
  g:
    unit: m/s^2
    value: 9.81
  nu:
    unit: m^2/s
    value: 1.18e-06
  rho:
    unit: kg/m^3
    value: 1025
rotations convention:
- psi
- theta'
- phi''

14.2.3 Lancement de la simulation

La simulation peut maintenant être lancée comme suit :

xdyn tutorial_02_fast_hydrostatic.yml --dt 0.1 --tend 10 -o fast.csv
xdyn tutorial_02_exact_hydrostatic.yml --dt 0.1 --tend 10 -o exact.csv

14.2.4 Résultats

Voici les résultats :

Figure 14.2: Élévation au cours du temps
Figure 14.2: Élévation au cours du temps

On peut également représenter les déplacements suivant l’axe yy :

Figure 14.3: Embardée au cours du temps
Figure 14.3: Embardée au cours du temps

14.3 Tutoriel 3 : génération de houle sur un maillage

Le simulateur a vocation à représenter le comportement de solides dans un environnement fluide, mais il peut aussi servir à simuler un environnement, sans aucun solide. Ce peut être intéressant par exemple pour générer des champs de vague afin de tester des algorithmes de prédiction de mouvement sur houle. Ce tutoriel explique comment utiliser le simulateur pour ce type de simulation.

14.3.1 Description du problème

Dans cet exemple, nous simulerons une houle d’Airy constituée de la somme de deux spectres directionnels :

On suppose en outre avoir 100 m de fond.

On se limite dans cet exemple à deux spectres, mais le simulateur permet d’en sommer autant qu’on le souhaite (on n’est limité que par la mémoire de la machine et par le temps disponible).

14.3.2 Écriture du fichier de configuration du simulateur

La section environment models est nettement plus fournie que pour les tutoriels précédents.

On commence par définir la discrétisation. Actuellement, le nombre de pulsations est égal au nombre de directions : il s’agit d’une limitation du code.

discretization:
    energy fraction: 0.999
    n: 128
    omega max:
      unit: rad/s
      value: 6
    omega min:
      unit: rad/s
      value: 0.1

On va donc sommer 128 pulsations et 128 directions, soit 16384 points. Cependant, la discrétisation spatiale des spectres monochromatiques et des dispersions monodirectionnelles est réduite à un point. On spécifie en outre que l’on veut représenter 99.9 % de l’énergie totale, les autres composantes n’étant pas retenues.

Le premier spectre est défini de la façon suivante :

0:
    depth:
      unit: m
      value: 100
    directional spreading:
      type: dirac
      waves propagating to:
        unit: deg
        value: 90
    model: airy
    seed of the random data generator: 0
    spectral density:
      Hs:
        unit: m
        value: 5
      Tp:
        unit: s
        value: 15
      gamma: 1.2
      type: jonswap
    stretching:
      delta: 1
      h:
        unit: m
        value: 0

Pour le second spectre, on écrit :

1:
    depth:
      unit: m
      value: 100
    directional spreading:
      s: 2
      type: cos2s
      waves propagating to:
        unit: deg
        value: 90
    model: airy
    seed of the random data generator: 10
    spectral density:
      Hs:
        unit: m
        value: 15
      omega0:
        unit: rad/s
        value: 0.05
      type: dirac
    stretching:
      delta: 1
      h:
        unit: m
        value: 0

On définit les sorties de la façon suivante :

output:
    frame of reference: NED
    mesh:
      nx: 5
      ny: 2
      xmax:
        unit: m
        value: 5
      xmin:
        unit: m
        value: 1
      ymax:
        unit: m
        value: 2
      ymin:
        unit: m
        value: 1

En définitive, l’environnement est défini de la façon suivante :

environment models:
    - discretization:
        energy fraction: 0.999
        n: 128
        omega max:
          unit: rad/s
          value: 6
        omega min:
          unit: rad/s
          value: 0.1
      model: waves
      output:
        frame of reference: NED
        mesh:
          nx: 5
          ny: 2
          xmax:
            unit: m
            value: 5
          xmin:
            unit: m
            value: 1
          ymax:
            unit: m
            value: 2
          ymin:
            unit: m
            value: 1
      spectra:
      - depth:
          unit: m
          value: 100
        directional spreading:
          type: dirac
          waves propagating to:
            unit: deg
            value: 90
        model: airy
        seed of the random data generator: 0
        spectral density:
          Hs:
            unit: m
            value: 5
          Tp:
            unit: s
            value: 15
          gamma: 1.2
          type: jonswap
        stretching:
          delta: 1
          h:
            unit: m
            value: 0
      - depth:
          unit: m
          value: 100
        directional spreading:
          s: 2
          type: cos2s
          waves propagating to:
            unit: deg
            value: 90
        model: airy
        seed of the random data generator: 10
        spectral density:
          Hs:
            unit: m
            value: 15
          omega0:
            unit: rad/s
            value: 0.05
          type: dirac
        stretching:
          delta: 1
          h:
            unit: m
            value: 0

Comme on ne simule pas de corps, le fichier d’entrée se réduit à :

rotations convention: [psi, theta', phi'']

environmental constants:
    g: {value: 9.81, unit: m/s^2}
    rho: {value: 1026, unit: kg/m^3}
    nu: {value: 1.18e-6, unit: m^2/s}
environment models:
  - model: waves
    discretization:
       n: 128
       omega min: {value: 0.1, unit: rad/s}
       omega max: {value: 6, unit: rad/s}
       energy fraction: 0.999
    spectra:
      - model: airy
        depth: {value: 100, unit: m}
        seed of the random data generator: 0
        stretching:
          delta: 1
          h: {unit: m, value: 0}
        directional spreading:
           type: dirac
           waves propagating to: {value: 90, unit: deg}
        spectral density:
           type: jonswap
           Hs: {value: 5, unit: m}
           Tp: {value: 15, unit: s}
           gamma: 1.2
      - model: airy
        depth: {value: 100, unit: m}
        seed of the random data generator: 10
        stretching:
          delta: 1
          h: {unit: m, value: 0}
        directional spreading:
           type: cos2s
           s: 2
           waves propagating to: {value: 90, unit: deg}
        spectral density:
           type: dirac
           omega0: {value: 0.05, unit: rad/s}
           Hs: {value: 15, unit: m}
    output:
        frame of reference: NED
        mesh:
            xmin: {value: 1, unit: m}
            xmax: {value: 5, unit: m}
            nx: 5
            ymin: {value: 1, unit: m}
            ymax: {value: 2, unit: m}
            ny: 2

14.3.3 Lancement de la simulation

La simulation peut maintenant être lancée comme suit :

xdyn tutorial_03_waves.yml --dt 1 --tend 1 -w tutorial_03_results.h5

Le fichier de résultat est ici tutorial_03_results.h5.

14.3.4 Résultats

On obtient un fichier hdf5 qui peut être ouvert avec différents logiciels comme HDFView. Dans le groupe “outputs”, on trouve un groupe “waves” qui contient quatre jeux de données nommés t, x, y et z.

La description de ce fichier est faite dans la documentation des fichiers YAML.

On peut obtenir les élévations dans n’importe quel repère de xdyn (NED ou lié à un solide). Si le repère est lié à un solide on obtient des coordonnées x et y changeantes au cours du temps.

14.4 Tutoriel 6 : propulsion

Jusqu’ici nous n’avons simulé que des efforts environnementaux. Dans ce tutoriel, nous simulons un propulseur.

14.4.1 Description du problème

Le navire évolue dans un environnement sans houle. Il est soumis aux cinq efforts suivants :

On peut aussi se contenter des 2 seuls efforts de résistance et de propulsion.

14.4.2 Écriture du fichier de configuration du simulateur

Les changements par rapport au tutoriel 2 sont les ajouts des efforts d’amortissement et de résistance, d’une section controlled forces et d’une section commands.

On commence par définir les caractéristiques du propulseur :

controlled forces:
    - blade area ratio AE/A0: 0.55
      diameter:
        unit: m
        value: 1.925
      model: wageningen B-series
      name: propeller
      number of blades: 4
      position of propeller frame:
        frame: TestShip
        phi:
          unit: rad
          value: 0
        psi:
          unit: deg
          value: 0
        theta:
          unit: deg
          value: 0
        x:
          unit: m
          value: 0
        y:
          unit: m
          value: 0
        z:
          unit: m
          value: 0.432
      relative rotative efficiency etaR: 1
      rotation: clockwise
      thrust deduction factor t: 0
      wake coefficient w: 0

Les commandes sont définies à la racine du YAML:

commands:
    - P/D:
        unit: 1
        values:
        - 1.064935
        - 1.064935
        - 1.064935
        - 1.064935
      name: propeller
      rpm:
        unit: rad/s
        values:
        - 3
        - 30
        - 30
        - 40
      t:
      - 0
      - 1
      - 3
      - 10

En définitive, le fichier d’entrée est :

bodies:
- controlled forces:
  - blade area ratio AE/A0: 0.55
    diameter:
      unit: m
      value: 1.925
    model: wageningen B-series
    name: propeller
    number of blades: 4
    position of propeller frame:
      frame: TestShip
      phi:
        unit: rad
        value: 0
      psi:
        unit: deg
        value: 0
      theta:
        unit: deg
        value: 0
      x:
        unit: m
        value: 0
      y:
        unit: m
        value: 0
      z:
        unit: m
        value: 0.432
    relative rotative efficiency etaR: 1
    rotation: clockwise
    thrust deduction factor t: 0
    wake coefficient w: 0
  dynamics:
    added mass matrix at the center of gravity and projected in the body frame:
      row 1:
      - 3.519e4
      - 0
      - 0
      - 0
      - 0
      - 0
      row 2:
      - 0
      - 3.023e5
      - 0
      - 0
      - 0
      - 0
      row 3:
      - 0
      - 0
      - 1.980e5
      - 0
      - 0
      - 0
      row 4:
      - 0
      - 0
      - 0
      - 3.189e5
      - 0
      - 0
      row 5:
      - 0
      - 0
      - 0
      - 0
      - 8.866e6
      - 0
      row 6:
      - 0
      - 0
      - 0
      - 0
      - 0
      - 6.676e6
    centre of inertia:
      frame: TestShip
      x:
        unit: m
        value: 0.258
      y:
        unit: m
        value: 0
      z:
        unit: m
        value: 0.432
    hydrodynamic forces calculation point in body frame:
      x:
        unit: m
        value: 0.696
      y:
        unit: m
        value: 0
      z:
        unit: m
        value: 1.418
    rigid body inertia matrix at the center of gravity and projected in the body frame:
      row 1:
      - 253310
      - 0
      - 0
      - 0
      - 0
      - 0
      row 2:
      - 0
      - 253310
      - 0
      - 0
      - 0
      - 0
      row 3:
      - 0
      - 0
      - 253310
      - 0
      - 0
      - 0
      row 4:
      - 0
      - 0
      - 0
      - 1.522e6
      - 0
      - 0
      row 5:
      - 0
      - 0
      - 0
      - 0
      - 8.279e6
      - 0
      row 6:
      - 0
      - 0
      - 0
      - 0
      - 0
      - 7.676e6
  external forces:
  - model: resistance curve
    resistance:
      unit: N
      values:
      - 0.0
      - 210.2
      - 772.8
      - 1647.0
      - 2803.0
      - 4230.0
      - 5999.0
      - 8498.0
      - 12730.0
      - 20840.0
      - 27890.0
      - 42380.0
      - 77370.0
      - 144900.0
      - 243900.0
      - 359000.0
      - 474100.0
    speed:
      unit: m/s
      values:
      - 0
      - 0.5
      - 1
      - 1.5
      - 2
      - 2.5
      - 3
      - 3.5
      - 4
      - 4.5
      - 5
      - 5.5
      - 6
      - 6.5
      - 7
      - 7.5
      - 8
  initial position of body frame relative to NED:
    frame: NED
    phi:
      unit: deg
      value: 0
    psi:
      unit: deg
      value: 0
    theta:
      unit: rad
      value: 0
    x:
      unit: m
      value: 0
    y:
      unit: m
      value: 0
    z:
      unit: m
      value: 1
  initial velocity of body frame relative to NED:
    frame: TestShip
    p:
      unit: rad/s
      value: 0
    q:
      unit: rad/s
      value: 0
    r:
      unit: rad/s
      value: 0
    u:
      unit: m/s
      value: 0
    v:
      unit: m/s
      value: 0
    w:
      unit: m/s
      value: 0
  mesh: test_ship.stl
  name: TestShip
  position of body frame relative to mesh:
    frame: mesh
    phi:
      unit: rad
      value: 0
    psi:
      unit: rad
      value: 0
    theta:
      unit: rad
      value: 0
    x:
      unit: m
      value: 9.355
    y:
      unit: m
      value: 0
    z:
      unit: m
      value: -3.21
commands:
- P/D:
    unit: 1
    values:
    - 1.064935
    - 1.064935
    - 1.064935
    - 1.064935
  name: propeller
  rpm:
    unit: rad/s
    values:
    - 3
    - 30
    - 30
    - 40
  t:
  - 0
  - 1
  - 3
  - 10
environment models:
- constant sea elevation in NED frame:
    unit: m
    value: 0
  model: no waves
environmental constants:
  g:
    unit: m/s^2
    value: 9.81
  nu:
    unit: m^2/s
    value: 1.18e-06
  rho:
    unit: kg/m^3
    value: 1025
rotations convention:
- psi
- theta'
- phi''

14.4.3 Lancement de la simulation

La simulation peut maintenant être lancée comme suit :

xdyn tutorial_06_propulsion.yml --dt 0.1 --tend 20 -o out.csv
xdyn tutorial_06_1D_propulsion.yml --dt 0.1 --tend 20 -o out_1D.csv

14.4.4 Résultats

Voici l’évolution temporelle de la vitesse pour la cas 1D :

Figure 14.4: Vitesse d’avance longitudinale
Figure 14.4: Vitesse d’avance longitudinale

14.5 Tutoriel 9 : utilisation d’un modèle de houle distant

Ce tutoriel explique comment utiliser un modèle de houle externe dans xdyn.

Nous utiliserons Docker compose pour lancer le client (xdyn) et le serveur de houle. Ceci n’est pas obligatoire (on peut se passer de Docker et Docker Compose pour faire fonctionner l’ensemble), mais l’utilisation de Docker simplifie grandement la mise en oeuvre.

14.5.1 Vue d’ensemble

Pour ce tutoriel, on a besoin :

Le modèle de houle peut être implémenté en Python. Afin de simplifier sa mise en oeuvre, on peut utiliser le dépôt https://gitlab.sirehna.com/sirehna/demo_docker_grpc qui contient déjà un exemple de serveur de houle en Python.

14.5.2 Mise en donnée xdyn

Dans un fichier YAML (nommé tutorial_09_gRPC_wave_model.yml dans cet exemple) on écrit :

bodies:
- dynamics:
    added mass matrix at the center of gravity and projected in the body frame:
      row 1:
      - 0
      - 0
      - 0
      - 0
      - 0
      - 0
      row 2:
      - 0
      - 0
      - 0
      - 0
      - 0
      - 0
      row 3:
      - 0
      - 0
      - 0
      - 0
      - 0
      - 0
      row 4:
      - 0
      - 0
      - 0
      - 0
      - 0
      - 0
      row 5:
      - 0
      - 0
      - 0
      - 0
      - 0
      - 0
      row 6:
      - 0
      - 0
      - 0
      - 0
      - 0
      - 0
    centre of inertia:
      frame: cube
      x:
        unit: m
        value: 0
      y:
        unit: m
        value: 0
      z:
        unit: m
        value: 0.4
    hydrodynamic forces calculation point in body frame:
      x:
        unit: m
        value: 0.696
      y:
        unit: m
        value: 0
      z:
        unit: m
        value: 1.418
    rigid body inertia matrix at the center of gravity and projected in the body frame:
      row 1:
      - 83.33
      - 0
      - 0
      - 0
      - 0
      - 0
      row 2:
      - 0
      - 83.33
      - 0
      - 0
      - 0
      - 0
      row 3:
      - 0
      - 0
      - 83.33
      - 0
      - 0
      - 0
      row 4:
      - 0
      - 0
      - 0
      - 83.33
      - 0
      - 0
      row 5:
      - 0
      - 0
      - 0
      - 0
      - 83.33
      - 0
      row 6:
      - 0
      - 0
      - 0
      - 0
      - 0
      - 83.33
  external forces:
  - model: gravity
  - model: non-linear hydrostatic (fast)
  initial position of body frame relative to NED:
    frame: NED
    phi:
      unit: deg
      value: 0
    psi:
      unit: rad
      value: 0
    theta:
      unit: deg
      value: 2
    x:
      unit: m
      value: 0
    y:
      unit: m
      value: 0
    z:
      unit: m
      value: 0.25
  initial velocity of body frame relative to NED:
    frame: cube
    p:
      unit: rad/s
      value: 0
    q:
      unit: deg/s
      value: 0
    r:
      unit: rad/s
      value: 0
    u:
      unit: m/s
      value: 0
    v:
      unit: m/s
      value: 0
    w:
      unit: m/s
      value: 0
  mesh: cube.stl
  name: cube
  position of body frame relative to mesh:
    frame: mesh
    phi:
      unit: rad
      value: 0
    psi:
      unit: rad
      value: 0
    theta:
      unit: rad
      value: 0
    x:
      unit: m
      value: 0
    y:
      unit: m
      value: 0
    z:
      unit: m
      value: 0.5
environment models:
- Hs: 5
  Tp: 15
  gamma: 1.2
  model: grpc
  omega:
  - 1
  - 2
  - 3
  url: waves-server:50051
  waves propagating to: 0
environmental constants:
  g:
    unit: m/s^2
    value: 9.81
  nu:
    unit: m^2/s
    value: 1.18e-06
  rho:
    unit: kg/m^3
    value: 1026
rotations convention:
- psi
- theta'
- phi''

14.5.3 Ecriture du modèle de houle

Dans un fichier Python (nommé airy.py dans cet exemple) on écrit :

"""Airy wave model. As implemented in xdyn."""

import math
import yaml
import numpy as np
import waves


def pdyn_factor(k, z, eta):
    return 0 if (eta != 0 and z < eta) else math.exp(-k * z)


class Airy(waves.AbstractWaveModel):
    def __init__(self):
        self.psi0 = None
        self.jonswap_parameters = {'sigma_a': 0.07, 'sigma_b': 0.09}
        self.directional_spectrum = {}

    def set_parameters(self, parameters):
        param = yaml.safe_load(parameters)
        self.jonswap_parameters['t_p'] = param['Tp']
        self.jonswap_parameters['gamma'] = param['gamma']
        self.directional_spectrum['omega'] = param['omega']
        self.directional_spectrum['psi'] = \
            [param['waves propagating to']*math.pi/180]
        self.jonswap_parameters['hs_square'] = param['Hs']*param['Hs']
        self.jonswap_parameters['omega0'] = 2*math.pi/param['Tp']
        self.jonswap_parameters['coeff'] = 1-0.287*math.log(param['gamma'])
        self.directional_spectrum['si'] = [self.jonswap(omega) for omega in
                                           param['omega']]
        self.directional_spectrum['dj'] = [1]
        self.directional_spectrum['psi'] = [1]
        self.directional_spectrum['k'] = [omega*omega/9.81 for omega in
                                          param['omega']]
        phases = np.random.uniform(low=0,
                                   high=2*math.pi,
                                   size=(len(param['omega']),))
        self.directional_spectrum['phase'] = phases

    def jonswap(self, omega):
        sigma_a = self.jonswap_parameters['sigma_a']
        sigma_b = self.jonswap_parameters['sigma_b']
        omega0 = self.jonswap_parameters['omega0']
        hs_square = self.jonswap_parameters['hs_square']
        coeff = self.jonswap_parameters['coeff']
        gamma = self.jonswap_parameters['coeff']
        sigma = sigma_a if omega <= omega0 else sigma_b
        ratio = omega0/omega
        alpha = ratio*ratio*ratio*ratio
        awm_5 = coeff*5.0/16.0*alpha/omega*hs_square
        bwm_4 = 1.25*alpha
        kappa = (omega-omega0)/(sigma*omega0)
        return awm_5*math.exp(-bwm_4)*math.pow(gamma,
                                               math.exp(-0.5*kappa*kappa))

    def elevation(self, x, y, t):
        zeta = 0
        dir_spec = self.directional_spectrum
        psi = dir_spec['psi'][0]
        for s_i, k, omega, phase in zip(dir_spec['si'],
                                        dir_spec['k'],
                                        dir_spec['omega'],
                                        dir_spec['phase']):
            k_x_cos_psi_y_sin_psi = k * (x * math.cos(psi) + y * math.sin(psi))
            zeta -= s_i * math.sin(-omega*t + k_x_cos_psi_y_sin_psi + phase)
        return zeta

    def dynamic_pressure(self, x, y, z, t):
        dir_spec = self.directional_spectrum
        eta = self.elevation(x, y, t)
        acc = 0
        psi = dir_spec['psi'][0]
        for s_i, k, omega, phase in zip(['si'],
                                        dir_spec['k'],
                                        dir_spec['omega'],
                                        dir_spec['phase']):
            k_x_cos_psi_y_sin_psi = k * (x * math.cos(psi)
                                         + y * math.sin(psi))
            acc -= s_i * pdyn_factor(k, z, eta)*math.sin(-omega*t
                                                         + k_x_cos_psi_y_sin_psi
                                                         + phase)
        return 1000*9.81*acc

    def orbital_velocity(self, x, y, z, t):
        dir_spec = self.directional_spectrum
        eta = self.elevation(x, y, t)
        v_x = 0
        v_y = 0
        v_z = 0
        psi = dir_spec['psi'][0]
        for s_i, k, omega, phase in zip(['si'],
                                        dir_spec['k'],
                                        dir_spec['omega'],
                                        dir_spec['phase']):
            pdyn_factor = self.pdyn_factor(k, z, eta)
            pdyn_factor_sh = pdyn_factor
            k_x_cos_psi_y_sin_psi = k * (x * math.cos(psi)
                                         + y * math.sin(psi))
            theta = -omega * t + k_x_cos_psi_y_sin_psi + phase
            cos_theta = math.cos(theta)
            sin_theta = math.sin(theta)
            a_k_omega = s_i * k / omega
            a_k_omega_pdyn_factor_sin_theta = a_k_omega * pdyn_factor \
                * sin_theta
            v_x += a_k_omega_pdyn_factor_sin_theta * math.cos(psi)
            v_y += a_k_omega_pdyn_factor_sin_theta * math.sin(psi)
            v_z += a_k_omega * pdyn_factor_sh * cos_theta

        return {'vx': v_x, 'vy': v_y, 'vz': v_z}

    def angular_frequencies_for_rao(self):
        return self.directional_spectrum['omegas']

    def directions_for_rao(self):
        return self.directional_spectrum['psis']

    def spectrum(self, x, y, t):
        return self.directional_spectrum


if __name__ == '__main__':
    waves.serve(Airy())

14.5.4 Lancement de la simulation

On commence par récupérer l’exemple de modèle de houle :

git clone git@gitlab.sirehna.com:sirehna/demo_docker_grpc.git

On écrit ensuite un fichier docker-compose.yml :

version: '3'
services:
  waves-server:
    build: waves_grpc/python_server
    entrypoint: ["/bin/bash", "/entrypoint.sh", "/work/airy.py"]
    working_dir: /work
    volumes:
    - .:/work
    - ./waves_grpc:/proto
  xdyn:
    image: sirehna/xdyn
    working_dir: /data
    entrypoint: xdyn tutorial_09_gRPC_wave_model.yml --dt 0.1 --tend 1 -o tsv
    volumes:
    - .:/data
    depends_on:
    - waves-server

On peut alors lancer la simulation comme suit :

docker-compose up

14.5.5 Sans Docker

Si l’on utilise pas Docker, il faut lancer le serveur de houle manuellement:

python3 airy.py

Puis il faut éditer le fichier YAML d’entrée de xdyn en remplaçant :

environment models:
  - model: grpc
    url: waves-server:50051

par

environment models:
  - model: grpc
    url: localhost:50051

On peut alors lancer xdyn normalement :

./xdyn tutorial_09_gRPC_wave_model.yml --dt 0.1 --tend 1 -o tsv

14.6 Tutoriel 10 : utilisation d’un modèle d’effort distant

Ce tutoriel explique comment utiliser un modèle d’effort externe dans xdyn.

Nous utiliserons Docker compose pour lancer le client (xdyn) et le serveur (le modèle d’effort). Ceci n’est pas obligatoire (on peut se passer de Docker et Docker Compose pour faire fonctionner l’ensemble), mais l’utilisation de Docker simplifie grandement la mise en oeuvre.

14.6.1 Vue d’ensemble

Pour ce tutoriel, on a besoin :

14.6.2 Mise en donnée xdyn

Dans un fichier YAML (nommé tutorial_10_gRPC_force_model.yml dans cet exemple) on écrit :

bodies:
- controlled forces:
  - c: 1
    k: 60
    model: grpc
    name: parametric oscillator
    url: force-model:9002
  dynamics:
    added mass matrix at the center of gravity and projected in the body frame:
      row 1:
      - 3.519e4
      - 0
      - 0
      - 0
      - 0
      - 0
      row 2:
      - 0
      - 3.023e5
      - 0
      - 0
      - 0
      - 0
      row 3:
      - 0
      - 0
      - 1.980e5
      - 0
      - 0
      - 0
      row 4:
      - 0
      - 0
      - 0
      - 3.189e5
      - 0
      - 0
      row 5:
      - 0
      - 0
      - 0
      - 0
      - 8.866e6
      - 0
      row 6:
      - 0
      - 0
      - 0
      - 0
      - 0
      - 6.676e6
    centre of inertia:
      frame: TestShip
      x:
        unit: m
        value: 0.258
      y:
        unit: m
        value: 0
      z:
        unit: m
        value: 0.432
    hydrodynamic forces calculation point in body frame:
      x:
        unit: m
        value: 0.696
      y:
        unit: m
        value: 0
      z:
        unit: m
        value: 1.418
    rigid body inertia matrix at the center of gravity and projected in the body frame:
      row 1:
      - 253310
      - 0
      - 0
      - 0
      - 0
      - 0
      row 2:
      - 0
      - 253310
      - 0
      - 0
      - 0
      - 0
      row 3:
      - 0
      - 0
      - 253310
      - 0
      - 0
      - 0
      row 4:
      - 0
      - 0
      - 0
      - 1.522e6
      - 0
      - 0
      row 5:
      - 0
      - 0
      - 0
      - 0
      - 8.279e6
      - 0
      row 6:
      - 0
      - 0
      - 0
      - 0
      - 0
      - 7.676e6
  initial position of body frame relative to NED:
    frame: NED
    phi:
      unit: deg
      value: 0
    psi:
      unit: deg
      value: 0
    theta:
      unit: rad
      value: 0
    x:
      unit: m
      value: 5
    y:
      unit: m
      value: 0
    z:
      unit: m
      value: 1
  initial velocity of body frame relative to NED:
    frame: TestShip
    p:
      unit: rad/s
      value: 0
    q:
      unit: rad/s
      value: 0
    r:
      unit: rad/s
      value: 0
    u:
      unit: m/s
      value: 0
    v:
      unit: m/s
      value: 0
    w:
      unit: m/s
      value: 0
  name: TestShip
  position of body frame relative to mesh:
    frame: mesh
    phi:
      unit: rad
      value: 0
    psi:
      unit: rad
      value: 0
    theta:
      unit: rad
      value: 0
    x:
      unit: m
      value: 0
    y:
      unit: m
      value: 0
    z:
      unit: m
      value: 0.5
environment models:
- constant sea elevation in NED frame:
    unit: m
    value: 0
  model: no waves
environmental constants:
  g:
    unit: m/s^2
    value: 9.81
  nu:
    unit: m^2/s
    value: 1.18e-06
  rho:
    unit: kg/m^3
    value: 1025
rotations convention:
- psi
- theta'
- phi''

On crée un fichier contenant les commandes pour le modèle gRPC (tutorial_10_gRPC_force_model_commands.yml dans cet exemple) :

commands:
- name: parametric oscillator
  omega:
    unit: rad/s
    values:
    - 3
    - 30
    - 30
    - 40
  t:
  - 0
  - 1
  - 3
  - 10

La connexion au modèle d’effort distant est définie dans la section suivante :

controlled forces:
    - c: 1
      k: 60
      model: grpc
      name: parametric oscillator
      url: force-model:9002

Toutes les autres lignes sont envoyées au modèle d’effort en tant que paramètre, sans être interprétées par xdyn. Dans le cas présent, le modèle a deux paramètres kk et cc dont la valeur est donnée une fois pour toutes au début de la simulation.

14.6.3 Ecriture du modèle d’effort

Il s’agit ici d’un modèle d’oscillateur harmonique amorti:

Fx=kxcuFy=0Fz=0Mx=0My=0Mz=0 F_x = -k\cdot x - c\cdot u F_y = 0 F_z = 0 M_x = 0 M_y = 0 M_z = 0 (14.1)

Dans un fichier Python (nommé harmonic_oscillator.py dans cet exemple) on écrit :

"""Damped harmonic oscillator model."""

import yaml
import grpcforce


class HarmonicOscillator(grpcforce.Model):
    def __init__(self):
        self.k = None
        self.c = None

    def model_needs_wave_outputs(self):
        return False

    def set_parameters(self, parameters):
        param = yaml.safe_load(parameters)
        self.k = param['k']
        self.c = param['c']

    def force(self, t, states, _, _):
        force = {'Fx': -self.k*states.x(0) - self.c*states.u(0), 'Fy': 0, 'Fz': 0, 'Mx': 0, 'My': 0, 'Mz': 0}
        return {'forces': forces, 'extra outputs': {}}


if __name__ == '__main__':
    grpcforce.serve(HarmonicOscillator())

14.6.4 Lancement de la simulation

On commence par récupérer l’exemple de modèle de houle :

git clone git@gitlab.sirehna.com:root/xdyn.git

On écrit ensuite un fichier docker-compose.yml :

version: '3'
services:
  force-model:
    build: xdyn/grpc_force_python_server
    entrypoint: ["/bin/bash", "/entrypoint.sh", "/work/harmonic_oscillator.py"]
    working_dir: /work
    volumes:
    - .:/work
    - ./xdyn:/proto
  xdyn:
    image: sirehna/xdyn
    working_dir: /data
    entrypoint: xdyn tutorial_10_gRPC_force_model.yml tutorial_10_gRPC_force_model_commands.yml --dt 0.1 --tend 1 -o tsv
    volumes:
    - .:/data
    depends_on:
    - force-model

On peut alors lancer la simulation comme suit :

docker-compose up

14.6.5 Sans Docker

Si l’on n’utilise pas Docker, il faut lancer le serveur de houle manuellement:

python3 harmonic_oscillator.py

Puis il faut éditer le fichier YAML d’entrée de xdyn en remplaçant :

controlled forces:
  - model: grpc
    url: force-model:9002

par

controlled forces:
  - model: grpc
    url: localhost:50051

On peut alors lancer xdyn normalement :

./xdyn tutorial_10_gRPC_force_model.yml tutorial_10_gRPC_force_model_commands.yml --dt 0.1 --tend 1 -o tsv