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).
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.
Les exemples suivants peuvent être lancés à partir du répertoire demos
:
ou si l’on utilise une invite de commande MS-DOS :
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 :
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.
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.
Le fichier YAML comprend quatre sections de haut niveau :
rotations convention
définit la convention d’angles utilisée,environmental constants
donne les valeurs de la gravité et la densité de l’eau,environment models
,bodies
décrit les corps simulés.On retrouve fréquemment dans le fichier YAML des lignes du type :
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:
sera vu par xdyn comme:
masse = 4.5359237;
L’exemple précédent :
aurait tout aussi bien pu être écrit :
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.
La spécification des sorties se fait au moyen de la section output
, à la racine du fichier YAML, dont voici un exemple :
format
: csv
pour un fichier texte dont les colonnes sont séparées par une virgule ou hdf5
pour le format des fichiers .mat de MatLab (HDF5)filename
: nom du fichier de sortiedata
: liste des colonnes à écrire. Le temps est noté t
, et les états sont x(body)
, y(body)
z(body)
, u(body)
, v(body)
, w(body)
, p(body)
, q(body)
, r(body)
, qr(body)
, qi(body)
, qj(body)
, qk(body)
. body
doit être remplacé par le nom du corps (ball
dans l’exemple ci-dessus). Les sorties d’effort sont Fx(modèle,corps,repère)
, Fy(modèle,corps,repère)
, Fz(modèle,corps,repère)
, Mx(modèle,corps,repère)
, My(modèle,corps,repère)
, Mz(modèle,corps,repère)
où modèle
est le nom du modèle d’effort (renseigné dans la clef modèle
de chaque modèle d’effort), corps
est le nom du corps sur lequel agit l’effort et repère
est le repère d’expression (qui ne peut être que NED
ou le nom du corps). Les sorties de houle sont notées waves
et leur contenu est décrit dans la section Modèle de houle/Sorties. La somme des efforts appliqués à un corps est accessible par Fx(sum of forces,corps,repère)
(resp. Fy, Fz, Mx, My, Mz).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
.
xdyn_run
exécute xdyn
depuis MatLab
.xdyn_loadResultsFromHdf5File
permet de charger les résultats d’une simulation dans MatLab
.xdyn_postProcess
lance l’ensemble des post-traitements disponibles.xdyn_plotStates
permet de tracer les états, à partir de résultats de simulations. Cela comprend les positions et les vitesses de chaque corps.xdyn_plotPositions
permet de tracer les positions et les orientations de chaque corps.xdyn_plotVelocities
permet de tracer les vitesses de translation et de rotation de chaque corps dans le repère de chaque repère.xdyn_animate3d
permet de lancer une animation 3d d’une simulation avec les objets simulés et le champ de vagues lorsque celui-ci est exporté.xdyn_extractMatLabScript
permet d’extraire les scripts MatLab
de dépouillement intégrés dans le fichier de sortie hdf5.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
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 :
Pour utiliser l’image xdyn
avec son environnement de post-traitement, on récupérera l’image sirehna/xweave
en exécutant :
Une fois l’image chargée par la commande précédente, on peut lancer :
-v $(pwd):/work
permet de faire correspondre le répertoire courant avec le répertoire /work
du conteneur,-w /work
précise que le répertoire de travail du conteneur (celui depuis lequel sera exécuté xdyn) est /work
,sirehna/xdyn
correspond au nom de l’image Docker,Si l’on souhaite lancer une simulation, on ajoute les arguments d’xdyn à la suite :
Cette fonctionnalité n’est accessible qu’en utilisant le conteneur Docker sirehna/xweave
.
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.
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
) contient les arguments passés à Docker pour partager le dossier courant avec le containeur et créer les fichiers de sortie avec les permissions de l’utilisateur courant.sirehna/xweave
contient les arguments passés à pweave. Une liste complète de ces arguments peut être obtenue en exécutant docker run --rm -it -v $(pwd):/work -w /work -u $(id -u):$(id -g) --entrypoint /usr/bin/xdyn-weave sirehna/xweave -h
ou en consultant la documentation de Pweave.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 :
Par rapport à Pweave “classique”, on a inclus quelques fonctions Python pour simplifier le travail avec xdyn.
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.
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')
```
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
# 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')
```
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 ). Dans le cas “model exchange”, le serveur renvoie la dérivée des états .
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).
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 :
où --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.
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 :
où --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.
Le navigateur Chrome dispose d’une extension websocket Simple Websocket Client qui permet de faire quelques tests de bon fonctionnement.
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.
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.
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.
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.
Le repère NED
(North-East-Down) est utilisé comme repère de référence, avec un point de référence et une base pointant les directions Nord-Est-Bas. Il sert à exprimer les déplacements des corps de la simulation.
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.
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 ( 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)”.
L’attitude d’un corps permet de connaître son orientation par rapport à un repère. La position est donnée par le triplet et l’orientation par un triplet d’angles . L’interprétation de ce triplet en termes de rotations autour des axes , , 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).
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 .
Pour définir la composition de rotations donnant l’orientation d’un élément dans l’espace à partir d’un triplet d’angles , plusieurs éléments doivent être définis:
Si on choisit une convention d’angles, alors chaque angle du triplet définit respectivement une rotation autour d’un axe , ou . 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: , , , , ,. Par exemple la rotation appliquée au triplet s’interprétera comme une rotation de , suivie de la rotation , et terminée par la rotation .
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, sera valide, mais pas . Par exemple, une convention ZXY définit une composition de rotations. Il est possible de définir 12 conventions d’axes: , , , , , , , , , , , . Par exemple la rotation appliquée au triplet s’interprétera comme une rotation de , suivie de la rotation , et terminée par la rotation .
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.
Les deux tableaux suivants présentent les 36 conventions possibles :
id | Ordre | Convention | Composition | Matrice de rotation | Remarques |
---|---|---|---|---|---|
1 | angle | x y z | Extrinsic | ||
2 | angle | x z y | Extrinsic | ||
3 | angle | y x z | Extrinsic | ||
4 | angle | y z x | Extrinsic | ||
5 | angle | z x y | Extrinsic | ||
6 | angle | z y x | Extrinsic | ||
7 | angle | x y’ z’’ | Intrinsic | ||
8 | angle | x z’ y’’ | Intrinsic | ||
9 | angle | y x’ z’’ | Intrinsic | ||
10 | angle | y z’ x’’ | Intrinsic | ||
11 | angle | z x’ y’’ | Intrinsic | ||
12 | angle | z y’ x’’ | Intrinsic |
id | Ordre | Convention | Composition | Matrice de rotation | Remarques |
---|---|---|---|---|---|
13 | axis | x y x | Extrinsic | Euler | |
14 | axis | x y z | Extrinsic | Cardan - Tait - Bryan | |
15 | axis | x z x | Extrinsic | Euler | |
16 | axis | x z y | Extrinsic | Cardan - Tait - Bryan | |
17 | axis | y x y | Extrinsic | Euler | |
18 | axis | y x z | Extrinsic | Cardan - Tait - Bryan | |
19 | axis | y z x | Extrinsic | Euler | |
20 | axis | y z y | Extrinsic | Cardan - Tait - Bryan | |
21 | axis | z x y | Extrinsic | Euler | |
22 | axis | z x z | Extrinsic | Cardan - Tait - Bryan | |
23 | axis | z y x | Extrinsic | Euler | |
24 | axis | z y z | Extrinsic | Cardan - Tait - Bryan | |
25 | axis | x y’ x’’ | Intrinsic | Euler | |
26 | axis | x y’ z’’ | Intrinsic | Cardan - Tait - Bryan | |
27 | axis | x z’ x’’ | Intrinsic | Euler | |
28 | axis | x z’ y’’ | Intrinsic | Cardan - Tait - Bryan | |
29 | axis | y x’ y’’ | Intrinsic | Euler | |
30 | axis | y x’ z’’ | Intrinsic | Cardan - Tait - Bryan | |
31 | axis | y z’ x’’ | Intrinsic | Euler | |
32 | axis | y z’ y’’ | Intrinsic | Cardan - Tait - Bryan | |
33 | axis | z x’ y’’ | Intrinsic | Euler | |
34 | axis | z x’ z’’ | Intrinsic | Cardan - Tait - Bryan | |
35 | axis | z y’ x’’ | Intrinsic | Euler | |
36 | axis | z y’ z’’ | Intrinsic | Cardan - Tait - Bryan |
où les matrices de rotation autour des trois axes , et s’écrivent
Parmi l’ensemble des conventions possibles, certaines sont plus utilisées que d’autres.
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 , suivie d’une rotation de l’angle d’assiette autour du nouvel axe suivie d’une rotation de l’angle de roulis autour du nouvel axe .
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
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 autour de l’axe , suivie d’une rotation autour du nouvel axe et finalement d’une rotation autour du nouvel axe .
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.
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 :
La section bodies
du fichier YAML contient une liste de corps, chacun commençant par un tiret :
Chaque corps comprend :
name
)mesh
)position of body frame relative to mesh
)initial position of body frame relative to NED
et initial velocity of body frame relative to NED
)dynamics
)external forces
et controlled forces
).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
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.
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.
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 :
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, peuvent définir la position du centre de gravité dans le repère maillage et 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}
dynamics
La section dynamics
permet de décrire l’inertie du solide. Elle est composée de cinq sous-sections :
hydrodynamic forces calculation point in body frame
est le point de calcul des efforts hydrodynamiquescentre of inertia
(si le repère “body” n’est pas au centre de masse)mass
contenant la masse du corps considérérigid body inertia matrix at the center of gravity and projected in the body frame
définissant la matrice d’inertieadded mass matrix at the center of gravity and projected in the body frame
pour les masses ajoutées.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é.
La section mass
contient la masse du solide, utilisée notamment pour le modèle de gravité :
Attention : si l’on spécifie ton
, le système utilisera la tonne britannique qui vaut 907.185 kg.
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 de la matrice d’inertie sont en unité SI, c’est-à-dire:
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
(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).
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.
state
: nom de l’état à forcer. u, v, w, p, q ou r.Si les valeurs des états sont dans le YAML :
value
: Valeur de l’état forcé pour chaque instant (dans l’exemple ci-dessus, u=5 pour t 4.2).t
: instants auxquels est défini l’étatinterpolation
: type d’interpolation à réaliser. piecewise constant
, linear
ou spline
.Si les valeurs sont lues depuis un fichier CSV :
filename
: nom du fichier contenant les valeurs forcées. Le chemin du fichier s’entend relativement à l’endroit d’où est lancé le simulateur.value
: nom de la colonne contenant les valeurs à liret
: nom de la colonne contenant le tempsinterpolation
: type d’interpolation à réaliser. piecewise constant
, linear
ou spline
.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
(6.2)
Pour ce faire, on utilise dans la section ‘output’ les clefs suivantes (si le corps s’appelle ’TestShip):
Fx(blocked states,TestShip,TestShip)
Fy(blocked states,TestShip,TestShip)
Fz(blocked states,TestShip,TestShip)
Mx(blocked states,TestShip,TestShip)
My(blocked states,TestShip,TestShip)
Mz(blocked states,TestShip,TestShip)
Il est à noter que ces efforts sont exprimés dans le repère BODY.
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 :
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 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+ :
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 autour de l’axe ) pour les mettre dans le repère d’xdyn (z vers le bas). La matrice de changement de base est :
(6.3)
(6.4)
(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.
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
(6.6)
la matrice du produit vectoriel par :
Pour effectuer un transport d’une matrice 6x6 en coordonnées généralisées (masse, masse ajoutée ou amortissement) d’un point vers un point , on utilise :
(6.7)
Cette formule est une généralisation de la formule de Huygens.
En combinant avec un changement de base (de la base vers la base ) par la matrice de rotation de vers on obtient l’expression plus générale :
(6.8)
Cette formule permet d’effectuer à la fois le transport d’une matrice d’inertie généralisée 6x6 d’un point à un point et le changement de son repère d’expression de vers .
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 :
(6.9)
En prenant la notation
(6.10)
on obtient :
(6.11)
Pour les torseurs, on obtient le changement suivant :
(6.12)
(6.13)
Cf. SimBody Theory Manual, Release 3.1, March, 2013, page 137, §12.3.1, Rigid body shift of rigid body spatial inertia
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).
[SOFT] AQUA+
[FORWARD_SPEED] 0.00
[List_calculated_periods]
4.00
64.00
125.00
[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
[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
[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
Les sections du HDB actuellement utilisées par xdyn sont :
Added_mass_Radiation_Damping
pour les amortissements de radiation et les matrices de masses ajoutées,DIFFRACTION_FORCES_AND_MOMENTS
pour les RAO des efforts de diffraction.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 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. 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.
La convention de rotation permet de retrouver la matrice de rotation d’un repère par rapport à un autre, étant donné un triplet . La convention utilisée est décrite dans la section rotations
:
Cette ligne s’interprète de la façon suivante : étant donné un triplet , on construit les matrices de rotation en effectuant d’abord une rotation d’angle autour de l’axe Z, ensuite une rotation d’angle autour de l’axe Y du repère précédemment transformé, puis une rotation d’angle autour de l’axe X du repère ainsi obtenu.
Si l’on avait noté :
on aurait d’abord une rotation d’angle autour de l’axe Z, puis une rotation d’angle autour du nouvel axe Y, puis une rotation 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 , tangage , roulis ), se définit de la façon suivante :
La convention d’orientation utilisée dans le logiciel ParaView est donnée par :
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
le nom du repère connu,x
,y
,z
: le triplet de position où chaque position est définie par le dictionnaire des clés value
et unit
,phi
,theta
,psi
, le triplet d’orientation dont l’interprétation en termes de matrices de rotations dépend de la convention d’orientation choisie 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
).
xdyn utilise la convention vers le bas pour l’amplitude. L’azimuth ou la direction de houle que l’on note 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 :
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).
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 :
Pour simuler une surface libre parfaitement plane, on opère de la façon suivante :
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.
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.
Soit la vitesse du fluide au point de coordonnées (dans le repère NED) et à l’instant .
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 . Par définition, la vitesse en tout point de l’écoulement est donc donnée par :
(7.1)
La pression vérifie l’équation de Bernoulli :
(7.2)
où est une fonction du temps arbitraire, donc l’équation est en particulier valable pour (pression atmosphérique à la surface) :
(7.3)
soit
(7.4)
Le terme représente la pression hydrostatique et le terme est la pression dynamique.
Il s’agit de la première condition de surface libre.
On peut définir la fonction
Pour une particule sur la surface libre, ce qui implique que sa dérivée particulaire est nulle :
(7.5)
soit
sur .
C’est la deuxième condition de surface libre.
En linéarisant ces deux conditions de surface libre, on obtient :
(7.6)
(7.7)
Par ailleurs, l’eau étant supposée incompressible,
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 :
(7.8)
qui est le potentiel utilisé par le logiciel AQUA+.
Il existe une relation entre et , appelée relation de dispersion, et qui s’écrit :
(7.9)
où désigne la profondeur d’eau et l’accélération de la pesanteur.
En profondeur infinie (), cette relation tend vers :
(7.10)
L’élévation de la houle découle de la deuxième condition de surface libre :
où désigne la direction de provenance de la houle, définie à la section convention de houle.
L’élévation de la houle en un point est un signal temporel . Par définition du plan (élévation moyenne de la houle), ce signal est centré. On le suppose également stationnaire, ce qui implique que sa fonction d’auto-corrélation ne dépend que de :
(7.11)
La densité spectrale de puissance de est égale à la transformée de Fourier de sa fonction d’auto-corrélation . Comme est paire et réelle, aussi et on ne considère usuellement que la partie positive (one-sided) en définissant la densité spectrale telle que :
(7.12)
On a :
(7.13)
or on a également :
(7.14)
d’où, par identification :
(7.15)
On peut généraliser cette formulation en faisant intervenir l’étalement directionnel de la houle :
(7.16)
On obtient, en définitive :
(7.17)
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 et son expression se déduit de la première condition de surface libre linéarisée :
(7.18)
soit
(7.19)
Lorsque la profondeur est très grande devant , les cosinus hyperboliques sont équivalents à des exponentielles :
(7.20)
on obtient donc :
(7.21)
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 :
(7.22)
Sous la surface libre, c’est-à-dire pour , on a donc
(7.23)
donc
(7.24)
or pour le calcul, on considère toujours la partie immergée de la coque donc , d’où (7.25)
Au-dessus de la surface libre, on a donc et
(7.26)
Or
(7.27)
Comme
(7.28)
et (on est sous l’eau),
(7.29)
et donc
(7.30)
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
(7.31)
le potentiel de houle irrégulière s’écrit:
(7.32)
On en déduit l’expression de l’élévation :
(7.33)
ainsi que l’expression de la pression dynamique :
(7.34)
La vitesse orbitale de la houle est définie par :
(7.35)
(7.36)
(7.37)
Lorsque , les cosinus hyperboliques peuvent être considérés comme équivalents à des exponentielles (erreur relative inférieure à ). On peut donc utiliser l’approximation suivante:
(7.38)
(7.39)
(7.40)
L’expression de l’élévation de la surface libre contient un terme en sinus. Les vitesses orbitales en et en contiennent des termes en cosinus et sont donc déphasées par rapport à l’élévation. La composante 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) :
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
model
: actuellement, ne peut valoir qu’airy
.stretching
: voir le paragraphe ci-dessous.depth
: profondeur (distance entre le fond et la surface). 0 pour l’approximation “profondeur infinie”. Utilisé pour le calcul du nombre d’onde et donc pour le calcul de l’élévation de la surface libre, des pressions dynamiques et des vitesses orbitales.seed of the random data generator
: germe utilisé pour la génération des phases aléatoires. Si l’on donne none
comme valeur toutes les phases aléatoires seront nulles (utilisé principalement pour les tests).directional spreading
: étalement directionnel. Cf. infra.spectral density
: densité spectrale de puissance. Cf. infra.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.
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 :
(7.41)
est la pulsation (en Rad/s) de la houle.
Le signal temporel correspondant a l’allure suivante :
Le paramétrage de ce spectre est :
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.
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 :
(7.42)
Aujourd’hui, on préfère une formulation fréquentielle :
(7.43)
Le moment d’ordre 0 permet d’obtenir une relation entre et :
(7.44)
d’où
(7.45)
Par ailleurs, la dérivée première du spectre s’annule pour une période :
(7.46)
d’où
(7.47)
et
(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 et, sous cette hypothèse, la hauteur de houle correspondant à deux écarts-types est :
(7.49)
En outre,
On peut ainsi exprimer et en fonction de et :
(7.50)
(7.51)
Ce spectre a l’allure suivante :
Sa paramétrisation dans xdyn est réalisée au moyen du YAML suivant :
À 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 :
(7.52)
où désigne la constante de Phillips, l’accélération de la gravité terrestre, la vitesse du vent à 19.5 mètres au-dessus du niveau de la mer et vaut 0.74.
Ce spectre est un cas particulier du spectre de Bretschneider en prenant
(7.53)
et
(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 :
(7.55)
d’où
(7.56)
On peut obtenir une expression de la période de pic uniquement en fonction de 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:
(7.57)
d’où
(7.58)
(7.59)
soit
(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 :
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.
(7.61)
avec
(7.62)
et
(7.63)
Ce spectre a l’allure suivante :
Sa paramétrisation dans xdyn est réalisée au moyen du YAML suivant :
Lorsque cet étalement est choisi, la houle est mono-directionnelle.
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).
L’étalement est donné par :
(7.64)
où 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 :
La direction de propagation est donnée par waves propagating to
.
La formulation d’Airy n’est pas valable au-dessus du plan . 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 . Les modèles de stretching sont une solution de contournement qui consiste à prendre comme référence non pas le plan mais la surface libre déformée.
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:
h: {value: 0, unit: m}
et delta: 1
. Non-recommandé dès lors qu’on utilise des modèles faisant appel aux vitesses orbitales (pour des raisons évoquées ci-après),depth
et ,depth
et ,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 du repère BODY) s’écrit :
(7.65)
qui, en profondeur infinie, s’écrit :
(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 est inférieure à 1 pour les points en-dessous du niveau moyen (surface ), 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 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 à et l’autre à , 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 à et fortement atténuées pour le point à . 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 (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).
Outre l’absence de stretching, le modèle le plus simple revient à bloquer la vitesse orbitale au-dessus du niveau de la mer :
(7.67)
On obtient ainsi une rupture du profil de vitesse peu physique. Ce modèle n’est pas implémenté dans xdyn.
Ce modèle revient à prolonger le modèle de vitesse par une tangente :
(7.68)
Ce modèle peut être utilisé dans xdyn en fixant h
à la profondeur d’eau depth
et delta: 1
.
La vitesse orbitale s’écrit :
(7.69)
avec
(7.70)
On souhaite après stretching retrouver les valeurs de vitesse orbitales données par à la surface (en xi, désignant la hauteur d’eau donnée par le modèle de houle) et au fond (en ):
On cherche donc une fonction telle que :
(7.71)
(7.72)
On peut construire une telle fonction en prenant
(7.73)
avec et .
On peut par exemple choisir une fonction linéaire :
(7.74)
ce qui donne le profil de vitesse (projetée ici sur l’axe du repère body) :
(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 à la profondeur de l’eau depth
et delta: 0
.
Dans ce modèle, on n’agit que sur la profondeur d’eau au dénominateur de la fonction
(7.76)
On remplace par . Sur l’axe du repère body, par exemple, on obtient ainsi le profil :
(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.
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 . Les auteurs de ce modèle, Rodenbusch et Forristal, ajoutent deux paramètres au modèle de Wheeler :
varie de à lorsque varie de à .
On prend donc :
Pour ,
Pour ,
Pour et , il n’y a pas de stretching.
Si vaut la profondeur depth
et , on retrouve le modèle de Wheeler.
Avec valant depth
et on obtient l’extrapolation linéaire.
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).
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 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 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
n
: nombre de points (nombre de fréquences ou nombre de directions)omega min
: pulsation minimale (incluse)omega max
: pulsation maximale (incluse)energy fraction
: les produits de spectre de puissance et d’étalement directionnel sont classés par ordre décroissant. On calcule la somme cumulative et l’on s’arrête lorsque l’énergie accumulée vaut energy fraction
de l’énergie totale.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
frame of reference
: nom du repère dans lequel sont exprimées les coordonnées des points du maillage.xmin
, xmax
, nx
: définition de la discrétisation de l’axe x. Les valeurs vont de xmin
(inclus) à xmax
(inclus) et il y a nx
valeurs au total.ymin
, ymax
, ny
: comme pour x.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]
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.
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.
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.
Un modèle sans paramètre tournant sur un serveur accessible à l’adresse http://localhost:50001 est paramétré comme suit :
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
Le tutoriel 9 détaille la mise en oeuvre de la simulation.
(définitions valables dans ce chapitre)
Le métacentre 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é d’un navire et son métacentre , notée , permet de caractériser la stabilité d’un navire :
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 d’une valeur d spécifiée en paramètre puis approche GM par
(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}
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.
Si l’on considère deux positions du navire 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 et 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 et ) et le centre de gravité est vertical puisque est à la verticale de . 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 . 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 :
(8.2) où désigne l’angle de la rotation isocarène.
Lorsque l’angle d’inclinaison tend vers 0, le point métacentrique tend vers un point appelé métacentre.
Plan de la surface libre du liquide au repos
Intersection du flotteur et du plan de flottaison
Périmètre de la flottaison
Centre de gravité de la flottaison
Partie immergée du flotteur, située au-dessous du plan de flottaison. Son centre de gravité est appelé “centre de carène”. C’est le point d’application des efforts hydrostatiques.
Flottaisons limitant des carènes de même volume. On peut démontrer qu’il existe une flottaison isocarène.
Intersection de deux flottaisons isocarènes infiniment voisines.
Enveloppe de la famille des plans constitués de toutes les flottaisons isocarènes.
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.
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.
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.
Pour toute position de navire, il existe une position isocarène.
Soit en effet et deux paramètres de flottaison tels que et . Soit le volume de la carène lorsque le navire est totalement immergé. On note l’intervalle .
On note l’application partielle . étant continue par hypothèse, l’est aussi. Par ailleurs, on sait que et donc d’après le théorème des valeurs intermédiaires, ce qui signifie que et sont isocarènes.
Le couple de rappel est par définition :
(8.3)
Pour de petites variations isocarènes de , le volume ne variant pas, est constante donc
(8.4)
or
(8.5)
d’où
(8.6)
Comme est constant,
(8.7)
donc
(8.8)
On a également le théorème de Bouguer :
(8.9)
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) :
(8.10)
Le donne donc une indication sur le taux de variation du couple de rappel hydrostatique : plus le est important pour un volume de carène donné, plus le moment de rappel aura tendance à varier rapidement pour de faibles changements d’inclinaison .
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é est délimité par une surface appelée “carène” (ou surface mouillée) et notée . On appelle “flottaison” et l’on note l’intersection du volume du navire avec le plan de la surface libre. On a donc . On note le centre de gravité du navire et le centre de (appelé “centre de carène”).
Les axes et du repère “body” sont notés respectivement et . La situation peut être représentée par la figure suivante :
La distance algébrique 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 soit situé au-dessus du centre de gravité . Le point est à l’intersection de la droite et de la droite .
Pour calculer , il faut connaître la position du centre de carène pour une position d’équilibre à un angle de gîte . On commence donc par calculer la position d’équilibre pour une gîte donnée, puis on calcule le centre de carène et est ensuite donné par .
Soit l’état du système. On suppose le navire soumis aux seuls efforts de la gravité et de l’hydrostatique. On note la fonction qui à associe la somme des efforts appliqués au système :
(9.1)
où désigne la masse du système et est le vecteur accélération de la pesanteur.
Lorsque le système est à l’équilibre, on a :
(9.2)
Pour résoudre cette équation, on peut par exemple utiliser la méthode de Newton-Raphson :
(9.3)
On note (9.4)
(9.5)
La matrice est estimée numériquement en linéarisant autour de . Soit un petit déplacement autour de et la variation d’effort correspondante.
(9.6)
Pour .
Si le petit déplacement que l’on considère s’effectue exclusivement suivant l’axe , on trouve :
donc
(9.7)
En pratique, pour évaluer les termes de la matrice , on considère séparément trois petits déplacements autour de (un par axe) et l’on utilise la formule précédente pour évaluer les termes trois par trois.
Une simplification possible est de considérer que la matrice varie peu et donc de ne l’évaluer qu’une seule fois (plutôt qu’à chaque étape de l’algorithme de Newton-Raphson).
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 les trois sommets d’un des triangles. Le volume élémentaire associé à ce triangle est le déterminant des vecteurs :
(9.8)
Les coordonnées du centre (par rapport à l’origine choisie pour les tétraèdres) sont données par :
(9.9)
(9.10)
(9.11)
Une méthode plus simple car ne nécessitant pas le calcul explicite du centre de carène est de projeter le vecteur sur le vecteur du plan vertical attaché au corps :
(9.12)
or
où désigne les coordonnées du vecteur du repère body, exprimées dans le repère NED et les coordonnées du vecteur 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 du vecteur GB. En effet,
où est le moment en de l’effort hydrostatique et la résultante de l’effort hydrostatique.
On pose
(9.13)
Dans le repère NED, on a :
(9.14)
(9.15)
donc
(9.16)
où l’on a noté
(9.17)
d’où
soit, avec les conventions de rotation usuelles :
(9.18)
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 .
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
Au cœur du simulateur, le solveur réalise l’intégration temporelle des équations différentielles ordinaires.
Soit , , . On appelle modèle une fonction
(10.1)
Une fonction dérivable 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).
sont les entrées du système (par exemple des commandes).
sont les paramètres du système, c’est-à-dire les constantes.
L’équation différentielle que l’on souhaite intégrer est :
(10.2)
Le solveur comprend cinq éléments :
La figure suivante illustre les interactions entre ces composants.
Les steppers réalisent l’intégration de sur un pas de temps. Actuellement, trois steppers sont implémentés :
(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 , alors la solution numérique est instable lorsque le produit est en-dehors de la région . En pratique, il n’est utilisé que pour des tests car les autres steppers montrent de meilleures performances.
(10.4)
avec
(10.5)
(10.6)
(10.7)
(10.8)
C’est un stepper très utilisé dans l’ingénierie.
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.
L’erreur commise est approchée par la relation suivante
avec
(10.9)
(10.10)
(10.11)
(10.12)
(10.13)
(10.14)
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.
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 . Par définition, la vitesse en tout point de l’écoulement est donc donnée par :
(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 ce potentiel. On a en effet :
avec :
où désigne le nombre d’onde, la pulsation de la houle, la profondeur d’eau, la double amplitude (ou creux) et l’accélération de la pesanteur.
On pose :
(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 à être une fonction harmonique du temps de pulsation :
(11.3)
Le potentiel inconnu doit satisfaire les conditions suivantes :
Si l’on suppose l’obstacle fixe, la condition (5) s’écrit :
(11.4)
Cette condition traduit la réflexion (ou diffraction) de la houle incidente sur l’obstacle fixe. Un potentiel 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 -ème degré de liberté, la condition (5) s’écrit : . Un potentiel vérifiant les conditions (1) à (4) et cette condition-ci est appelé -è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 du problème de diffraction-radiation obtenue par superposition de la solution “obstacle fixe” et des solutions oscillatoires élémentaires peut s’écrire :
(11.5)
en adoptant les notations suivantes :
On pose
Les efforts hydrodynamiques s’écrivent :
(11.6)
(11.7)
On appelle “efforts de Froude-Krylov” et “efforts de diffraction”. Ensemble ils constituent les efforts d’excitation de la houle . Les efforts sont nommés “efforts de radiation” et sont désignés par . On a donc :
(11.8)
On a, pour l’axe :
(11.9)
(11.10)
(11.11)
On décompose en sa partie réelle et sa partie imaginaire :
On a alors :
(11.12)
On remarque que
(11.13)
donc
(11.14)
On pose
Or d’après la condition (5) écrite pour les potentiels élémentaires de radiation,
(11.15)
On a donc :
(11.16)
On pose :
(11.17)
(11.18)
On appelle matrice des masses ajoutées (qui vient de ce que le solide déplace le fluide) et 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 :
En prenant , on obtient une formulation vectorielle des efforts dans le domaine fréquentiel :
On peut montrer en utilisant la deuxième identité de Green, que les matrices et obtenues précédemment sont symétriques et que la matrices est définie positive : on peut donc considérer comme une matrice d’inertie que l’on appelle “inertie ajoutée”. On peut aussi retrouver l’expression de de l’évaluation de l’énergie cinétique du fluide :
Lorsque l’on écrit le bilan des efforts appliqués au solide, on a :
(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 de l’écoulement lors d’une réponse impulsionnelle suivant l’axe et le décompose en deux composantes :
On a donc, pour une excitation impulsionnelle de l’axe :
(11.20)
Le potentiel de vitesse dû à un mouvement arbitraire suivant l’axe s’écrit alors :
(11.21)
Les efforts agissant sur la carène suivant l’axe du fait d’une excitation de l’axe peuvent s’exprimer en fonction de la pression dynamique de l’écoulement :
(11.22)
Or par définition,
En dérivant sous le signe intégral on obtient :
Il en découle :
On pose :
(11.23)
(11.24)
On a alors :
La formulation fréquentielle s’écrit :
(11.25)
La formulation temporelle est :
Les codes potentiels fournissent les matrices et à n’importe quelle fréquence, mais qu’en est-il des matrices et utilisées par la formulation temporelle ?
Deux ans après Cummins, en 1964, Ogilvie propose une méthode pour déterminer les matrices et en fonction des matrices et . Pour ce faire, il considère que le mouvement du solide est oscillant de pulsation :
En substituant dans la formulation fréquentielle, on obtient :
En ce qui concerne la formulation temporelle, on a :
En effectuant le changement de variable on a :
En développant on obtient :
Les relations suivantes doivent donc être valables pour tout :
(11.26)
En faisant tendre vers l’infini, on a :
(11.27)
est obtenu en prenant la transformée de Fourier inverse de :
(11.28)
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 :
(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 :
(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”.
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 pour différentes périodes. Comme l’indique la documentation, les étapes suivantes sont réalisées :
hdb
.type of quadrature for cos tranform
. Les types d’intégration connus sont : rectangle
, trapezoidal
, simpson
, gauss-kronrod
, clenshaw-curtis
, filon
et burcher
. Les bornes d’intégration sont spécifiées par omega min
et omega max
. Si ces bornes ne sont pas incluses dans l’intervalle , un message d’avertissement s’affiche (car dans ce cas l’intégration se poursuit hors du domaine de définition des fonctions de retard qui sont alors extrapolées).nb of points for retardation function discretization
.type of quadrature for convolution
, qui peut prendre les mêmes valeurs que type of quadrature for cos transform
.output Br and K
à true
. Sinon on la met à false
.- 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
C’est la méthode la plus simple qui consiste à interpoler la fonction à intégrer par une fonction constante (polynôme de degré 0).
Si est le point d’interpolation, la formule est la suivante :
(11.31)
Le choix de influence l’erreur : - Si ou , l’erreur est donnée par C’est la ‘’méthode du rectangle’’ qui est d’ordre 0. - Si , l’erreur est donnée par . 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 ) 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.
En interpolant par un polynôme de degré 1, les deux points d’interpolation et 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 : :
L’erreur est donnée par:
Conformément aux expressions de l’erreur, la méthode des trapèzes est souvent moins performante que celle du point milieu.
En interpolant 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 , , et celle choisie en leur milieu . 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 : :
L’erreur globale est donnée par :
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.
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 en schéma d’ordre en ajoutant aux points de la quadrature de Gauss zéros des polylônmes de Stieltjes-Wigert. Les polynômes de Stieltjes-Wigert sont des polynômes orthogonaux pour la fonction de poids :
(11.32)
On pose
(11.33)
Les polynômes de Stieltjes-Wigert s’écrivent alors :
(11.34)
et
où
(11.35)
(11.36)
avec le symbole de Pochhammer
(coefficient -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’-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).
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 ), 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.
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
:
Le poids est donné dans le repère NED par :
où désigne la masse du navire (en kg), l’accélération de la pesanteur (en m/s^2) et le vecteur unitaire vertical, exprimé dans le repère dans lequel on veut projeter la force.
Pour soumettre un solide à la gravité, on écrit :
La valeur de utilisée est celle définie dans la section environmental constants
et pour la masse on prend le coeffient (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.
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 exercée par l’eau sur la carène doit être calculée comme l’intégrale de la pression hydrostatique sur la surface immergée totale :
(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.
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 , 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 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 :
(12.2)
donc l’erreur que l’on commet peut s’écrire sous la forme :
(12.3)
où désigne le nombre d’onde et la dimension caractéristique de la maille.
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 et les coordonnées du point d’application des efforts dans le plan () et et les coordonnées du centroïde de la facette dans ce même repère. Le repère () est centré au centroïde de la facette.
Les efforts hydrostatiques s’écrivent :
(12.4)
avec
d’où
(12.5)
Or
d’où
(12.6)
doit vérifier :
(12.7)
soit
(12.8)
Or donc
où est le second moment d’inertie de la surface par rapport à l’axe parallèle à et passant par .
On a donc :
(12.9)
De même, on trouve :
(12.10)
or par définition du repère , donc
(12.11)
En pratique, on constate lors de simulations que les deux modèles sont assez proches sur l’axe 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 ) d’un cube maillé par six triangles rectangles : on obtient pour le modèle fast
des déplacements parasites suivant 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
).
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 :
(12.12)
Ce modèle a l’avantage de forcer la résultante à être suivant .
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)
.
Pour utiliser le modèle rapide, on écrit :
pour le modèle précis :
et pour le nouveau modèle :
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.
Introduction à la mécanique des fluides - CVG 2516, Statique des Fluides, Ioan NISTOR
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 :
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 :
Pour utiliser ce modèle, on insère la ligne suivante dans la section external forces
:
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.
Les RAO d’efforts sont lues à partir d’un fichier HDB. Cette table donne, une fois interpolée, deux fonctions RAO par axe
(12.13)
(12.14)
Pour calculer les efforts et les moments, pour une houle de direction de propagation , on somme les RAO comme pour le calcul de l’élévation de la surface libre en suivant la convention AQUA+ :
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 :
(12.16)
(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.
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 et , quitte à la symétriser par rapport à l’axe (Ox) pour obtenir les points entre et . En pratique, cela signifie que l’on prend si et que mirror for 180 to 360
vaut true
.
On suppose la propulsion rectiligne, d’intensité et de direction constantes et située dans le plan (, ) 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 la force nécessaire pour remorquer le navire à cette vitesse en eau calme.
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 ). 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 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 :
(12.18)
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 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 du repère body.
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.
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 :
On définit :
(12.19)
(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) :
(12.21)
où est la matrice d’amortissement linéaire lue depuis le fichier de paramètres.
Pour les amortissements quadratiques :
(12.22)
où
les étant les coefficients de la matrice d’amortissement quadratique lue depuis le fichier de paramètres.
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 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 décrite dans la documentation.
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 :
(12.23)
où est la distance entre deux points de mesure.
Le torseur d’effort est donné dans le repère NED par :
sont les valeurs d’équilibre renseignées dans le fichier de 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 sont données dans le repère body. Les coefficients de la matrice sont donnés en unité SI.
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.
- 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.
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.
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 , alors rpm=4000. Pour , rpm=3000.
Les commandes attendues pour ce modèle sont :
rpm
.P/D
.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]}
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
reference frame
: Définit la transformation permettant de passer d’un repère connu (dont le nom est donné par frame
) au repère dans lequel sont exprimés les efforts. Le torseur est automatiquement déplacé au centre de gravité (point (0,0,0) du repère “body”).commands
: optionnel. Le modèle de manœuvrabilité peut accepter des commandes externes. Il peut aussi utiliser les commandes de n’importe quel autre modèle d’effort (mais il faut pour cela bien renseigner le nom complet de la commande, soit par exemple PropRudd(rpm)
)X
, Y
, Z
, K
, M
, N
: coordonnées du torseur d’effort (dans le repère body), exprimé au point d’application défini ci-dessus.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 :
tau max
) et, éventuellement, les efforts de manoeuvrabilitié, lorsque l’on utilise des variables retardées telles que x(t-23)
. Dans ce cas, la durée maximale d’historique nécessaire est obtenue en analysant l’expression formelle : par exemple, M: 1E6*(x(t-6) + command1*x(t-5) + 2*b*y(t-4) + z(t-3)/a)
nécessitera au moins 6 secondes d’historique pour x
, 4 pour y
et 3 pour z
.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 | '_')*
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.
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 positif ou nul).
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 :
(13.1)
En effectuant l’analyse dimensionnelle pour exprimer , et en fonction des autres coefficients, on trouve :
(13.2)
Soit, en regroupant les termes de même puissance :
(13.3)
On définit le coefficient de poussée :
(13.4)
Le coefficient d’avance est défini par :
(13.5)
Le nombre de Reynolds s’exprime ici :
(13.6)
et le nombre de cavitation est :
(13.7)
donc il existe une fonction telle que
(13.8)
De même, pour le couple , on définit le coefficient de couple par :
(13.9)
Le modèle en eau libre consiste à expliciter les fonctions et , dont on peut ensuite dériver la poussée et le couple.
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 n’est pas égale (en valeur absolue) à la vitesse du navire par rapport à l’eau , autrement dit . La vitesse d’avance 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 (pour “wake”, soit “sillage” en anglais) tel que :
(13.10)
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 tel que :
(13.11)
où est la résistance de remorquage (en N) à une vitesse , sans hélice, et est la somme des poussées des hélices (également en N) lorsque le navire va à la vitesse en utilisant l’hélice.
La poussée réelle est alors définie par :
(13.12)
et le couple réel est
(13.13)
où est appelé rendement d’adaptation
(13.14)
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 , où désigne l’aire des pales (en m^2) et est l’aire du disque circonscrit à l’hélice. Les séries sont valables pour .
On définit également le pas 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 et l’on suppose que .
On note le nombre de pales de l’hélice.
Les coefficients des polynômes pour et sont notés et respectivement, où est un entier tel que . , , , , , , et sont des exposants entre 0 et 6.
Les coefficients et sont définis pour un nombre de Reynolds , mais le modèle a été étendu pour des nombres de Reynolds entre et en introduisant des termes et supplémentaires :
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 et 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 se situe hors de l’intervalle , un message d’avertissement est affiché et est saturé pour être ramené dans l’intervalle :
La condition sur le pas 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é.
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 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 positifs (donc vers l’avant du navire). Autrement dit, l’axe de rotation de l’hélice est non pas mais . 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 :
(13.15)
(13.16)
(13.17)
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.
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}
name
: nom du composant. Défini par l’utilisateur. Doit correspondre à celui renseigné dans le fichier de commandes attendues.model
: nom du modèle. Doit être wageningen B-series
pour utiliser ce modèle.position of propeller frame
: définition du repère de l’hélice.frame
: repère dans lequel sont exprimés x
,y
,z
,phi
,theta
et psi
.x
,y
,z
: projection de la position du centre de poussée de l’hélice par rapport au centre du repère attaché au maillage et projeté sur ce dernier.phi
, theta
, psi
: définition de la rotation permettant de passer du repère attaché au maillage au repère attaché à l’hélice, en suivant la convention d’angle choisie.wake coefficient
: coefficient de sillage traduisant la perturbation de l’écoulement par la coque du navire. Entre 0 et 1.relative rotative efficiency
: rendement d’adaptation.thrust deduction factor t
: coefficient de succion.rotation
définition du sens de rotation pour générer une poussée positive. Utilisé pour calculer le signe du moment généré par l’hélice sur le navire. Les valeurs possibles sont clockwise
et anti-clockwise
. Si on choisit clockwise
, l’hélice tournera dans le sens horaire (en se plaçant à l’arrière du navire et en regardant vers la proue) et génèrera un moment négatif sur le navire (dans le repère de l’hélice). Voir la documentation.number of blades
: nombre de pales de l’hélice.blade area ratio AE/A0
: fraction de surface de l’hélice.diameter
: diamètre de l’hélice.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.
Le moment généré est où désigne le moment d’inertie total (inertie propre et inertie ajoutée) autour de l’axe .
Dans le domaine de Laplace, l’équation du contrôleur s’écrit :
(13.18)
ou encore, sous forme canonique :
(13.19)
d’où
et
On peut exprimer ces gains en fonction de l’amortissement et du temps de réponse donné par .
(13.20)
(13.21)
Le cap est donné dans le repère NED. Si l’on suppose que , pour , le moment généré doit être positif, donc . Par conséquent, . De même, en prenant et , le moment généré doit être positif pour contrer la vitesse , donc , d’où .
controlled forces:
- name: controller
model: simple heading controller
ksi: 0.9
Tp: {value: 4, unit: s}
name
: nom du contrôleur (si l’on en utilise plusieurs)model
: simple heading controller
pour ce modèleksi
: coefficient d’amortissement de la loi de commandeTp
: temps de réponse (système du second ordre).Ce modèle n’a qu’une seule commande, le cap psi_co
:
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.
L’effort généré suivant l’axe X est où désigne le moment d’inertie total (inertie propre et inertie ajoutée) autour de l’axe . L’effort généré suivant l’axe Y est où désigne le moment d’inertie total (inertie propre et inertie ajoutée) autour de l’axe . Le moment généré est où désigne le moment d’inertie total (inertie propre et inertie ajoutée) autour de l’axe .
Dans le domaine de Laplace, les équations du contrôleur s’écrivent :
(13.22)
(13.23)
(13.24)
ou encore, sous forme canonique :
(13.25)
(13.26)
(13.27)
d’où
et
et
et
On peut exprimer ces gains en fonction de l’amortissement et du temps de réponse donné par .
(13.28)
(13.29)
(13.30)
(13.31)
(13.32)
(13.33)
Le cap est donné dans le repère NED. Si l’on suppose que , pour , le moment généré doit être positif, donc . Par conséquent, . De même, en prenant et , le moment généré doit être positif pour contrer la vitesse , donc , d’où .
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}
name
: nom du contrôleur (si l’on en utilise plusieurs)model
: simple heading controller
pour ce modèleksi_*
: coefficient d’amortissement de la loi de commandeT_*
: temps de réponse (système du second ordre).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]}
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)
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 :
(13.34)
L’expression du torseur 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 le torseur au point R.
La modélisation choisie sépare les efforts dus au safran en deux parties :
(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 et de cette résultantes s’expriment sous la forme :
(13.36)
(13.37)
La vitesse et l’aire 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é et est défini par rapport à l’angle d’incidence du fluide (dans le repère NED) et l’angle du safran :
(13.38)
(13.39)
(13.40)
Le coefficient permet de réduire l’efficacité du gouvernail lorsque devient important.
Dans la suite, nous détaillerons le calcul de , , et pour la partie hors sillage et la partie interne sillage.
Les notations utilisées figurent sur le schéma ci-dessus. La poussée générée par l’hélice est égale à la variation de la quantité de mouvement :
(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 :
(13.42)
On écrit l’équation de Bernoulli en amont du safran, entre et , puis en aval du safran, entre et :
(13.43)
(13.44)
d’où
(13.45)
(13.46)
puis
(13.47)
Les pressions et 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 :
(13.48)
(équation 3.32 Marine Rudders & Control Surfaces p. 49)
On en déduit l’expression de :
(13.49)
La vitesse au niveau du safran peut être déduite de l’égalité de deux expressions de :
On en déduit :
(13.50)
Les calculs de et de étant fait en régime stationnaire, cette expression de la vitesse 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 appelé “facteur de contraction” (cf. Marine Rudders & Control Surfaces eq. 3.37 p.51). On obtient ainsi une vitesse telle que :
(13.51)
avec
(13.52)
désigne la distance entre l’hélide et le safran (suivant l’axe ) et est le diamètre de l’hélice.
Afin de factoriser cette expression, on peut exprimer la vitesse en fonction de la vitesse :
(13.53)
or une autre expression de peut être donnée à partir du modèle de Wageningen :
(13.54)
(13.55) mais le paramètre d’avance s’écrit :
(13.56)
donc
(13.57)
d’où
(13.58)
On pose
(13.59)
(13.60)
Cette vitesse a été calculée en faisant les hypothèses suivantes :
On constate en pratique des écarts peuvent atteindre 30% entre et les mesures réalisées lors d’essais. C’est pourquoi on multiplie la vitesse par un facteur appelé “facteur de réduction” (cf. eq 11.1 p.? 371 Marine Rudders & Control Surfaces) :
(13.61)
La vitesse dans le sillage de l’hélice s’exprime donc (dans le repère “body”) :
(13.62)
La vitesse hors du sillage est simplement :
(13.63)
où , désignant le coefficient de sillage.
On introduit le rapport de forme (cf. Manoeuvring Technical Manual p. 76)
(13.64)
où 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) :
(13.65)
On utilise la formule suivante (cf. Maneuvering Technical Manual, p. 78 eq. 1.2.9)
(13.66)
Le coefficient de résistance vaut :
(13.67)
(cf. Maneuvering Technical Manual, p. 78 (§ for Cd0))
est un coefficient ITTC que l’on trouve par exemple dans Marine rudders and Control Surfaces, p.31 éq. 3.18 :
(13.68)
Le nombre de Reynolds du safran est donné par (cf. Maneuvering Technical Manual, p. 78 éq. 1.2.12) :
(13.69)
où la corde du safran vaut :
(13.70)
On sépare l’aire 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 et la partie à l’extérieur en faisant la différence avec .
(13.71)
(13.72)
où est la corde calculée ci-dessus.
Le diamètre du sillage est défini par :
(13.73)
(13.74)
(13.75)
d’où
(13.76)
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 :
model
: propeller+rudder
pour ce modèle,rudder area
: ,rudder height
: ,effective aspect ratio
: Paramètre dans le calcul du rapport de forme (pour la formule de Soeding) ci-dessus,lift tuning coefficient
: dans les formules ci-dessus,drag tuning coefficient
: dans les formules ci-dessus,position of rudder in body frame
: coordonnées du point (cf. schéma ci-dessus), projetées dans le repère “body”.Ce modèle a trois commandes :
rpm
,P/D
,beta
.- 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]}
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 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 du repère NED.
Le but de ce modèle est de spécifier des courbes d’effort d’hélice et en fonction du coefficient d’avance uniquement. Hormis le calcul de et , 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 :
(13.77)
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]
name
: Nom du composant. Défini par l’utilisateur. Doit correspondre à celui renseigné dans le fichier de commandes attendues,model
: Nom du modèle. Doit être wageningen B-series
pour utiliser ce modèle,position of propeller frame
: Définition du repère de l’hélice,frame
: repère dans lequel sont exprimés x
,y
,z
,phi
,theta
et psi
.x
,y
,z
: projection de la position du centre de poussée de l’hélice par rapport au centre du repère attaché au maillage et projeté sur ce dernier,phi
,theta
,psi
: Définition de la rotation permettant de passer du repère attaché au maillage au repère attaché à l’hélice, en suivant la convention d’angle choisie,wake coefficient
: coefficient de sillage traduisant la perturbation de l’écoulement par la coque du navire. Entre 0 et 1,relative rotative efficiency etaR
: rendement d’adaptation,thrust deduction factor t
: coefficient de succion,rotation
définition du sens de rotation pour générer une poussée positive. Utilisé pour calculer le signe du moment généré par l’hélice sur le navire. Les valeurs possibles sont clockwise
et anti-clockwise
. Si on choisit clockwise
, l’hélice tournera dans le sens horaire (en se plaçant à l’arrière du navire et en regardant vers la proue) et génèrera un moment négatif sur le navire (dans le repère de l’hélice). Voir la documentation,diameter
: diamètre de l’hélice (en m),J
: coefficient d’avance. Correspond aux listes Kt et Kq,Kt
: coefficient de poussée en fonction de J
,Kq
: coefficient de moment en fonction de J
.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 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 du repère NED.
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.
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.
Dans la section controlled forces
, on ajoute une section de la forme suivante :
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.
}
Le tutoriel 10 détaille
On commence par définir les conventions de rotation :
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 :
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 :
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)']
La simulation peut s’exécuter comme suit :
Pour avoir des sorties sur la console, on peut faire :
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) :
On peut choisir le solveur :
La liste de toutes les options est disponible en exécutant :
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.
Voici un tracé de l’élévation au cours du temps :
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)
.
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.
Nous documentons ici uniquement les changements par rapport au tutoriel 1.
L’environnement est défini de la façon suivante :
Comme décrit dans la documentation du fichier d’entrée, ceci signifie que la surface libre est parfaitement plane et horizontale, à la hauteur 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 :
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''
La simulation peut maintenant être lancée comme suit :
Voici les résultats :
On peut également représenter les déplacements suivant l’axe :
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.
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).
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
La simulation peut maintenant être lancée comme suit :
Le fichier de résultat est ici tutorial_03_results.h5
.
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.
Jusqu’ici nous n’avons simulé que des efforts environnementaux. Dans ce tutoriel, nous simulons un propulseur.
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.
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''
La simulation peut maintenant être lancée comme suit :
Voici l’évolution temporelle de la vitesse pour la cas 1D :
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.
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.
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''
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())
On commence par récupérer l’exemple de modèle de houle :
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 :
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 :
par
On peut alors lancer xdyn normalement :
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.
Pour ce tutoriel, on a besoin :
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 :
model: grpc
indique à xdyn qu’il s’agit d’un modèle d’effort distanturl: force-model:9902
donne l’adresse réseau à laquelle le modèle d’effort peut être atteint. L’utilisation de docker-compose
nous permet ici de spécifier une adresse égale au nom du modèlename: parametric oscillator
est un nom arbitraire que l’utilisateur donne dans son fichier YAML afin de pouvoir faire correspondre d’éventuelles commandes (section commands
du fichier YAML) à ce modèle d’effort.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 et dont la valeur est donnée une fois pour toutes au début de la simulation.
Il s’agit ici d’un modèle d’oscillateur harmonique amorti:
(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())
On commence par récupérer l’exemple de modèle de houle :
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 :
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 :
par
On peut alors lancer xdyn normalement :