Ce TP s'intéresse à la modélisation des équations de Maxwell par la méthode aux différences finies de Yee.
Ce TP se compose de plusieurs répertoires :
- consignes : ce dossier contient les consignes du TP
- cpp/sequential : ce dossier contient le fichier source du code séquentiel et le makefile pour le compiler.
- visualization : ce dossier contient des scripts dédiés à la visualisation des résultats.
- scalings : ce dossier contient des scripts permettant d'afficher les courbes de scalabilité
- .extra : ce dossier sert uniquement pour GitHub
Nous nous intéressons dans ce projet à la simulation des équations Maxwell par l'utilisation d'une méthode aux différences finies très connue du nom de FDTD pour Finite-Difference Time-Domain publié par K. Yee dans les années 60 et toujours utilisée aujourd'hui dans les codes de calcul pour sa rapidité et sa simplicité.
On rappelle les équations de Maxwell dans le vide :
Maxwell-Ampère :
Maxwell Faraday :
Maxwell Gauss :
Maxwell Flux :
Dans le cadre de la discrétisation de Yee, on ne s'intéresse qu'à Maxwell-Ampère et Maxwell-Faraday. On commence par normaliser les équations pour éliminer les constantes et réduire l'amplitude des champs (ce qui est toujours préférable en informatique).
En 2D, la discrétisation donne les équations suivantes pour Maxwell Ampère :
Où est l'itération en temps,
et
respectivement la discrétisation en espace suivant les directions
et
.
Puis pour Maxwell Faraday :
Le modèle discrétisé peut être représenté par le schéma suivant :
Ici, les composantes de champ sont représentées par des noeuds colorés :
On remarque que les grilles qui composent les noeuds ne sont pas donc pas toutes superposées mais sont décalées en espace de et/ou
. En anglais, on parle de grille staggered. En 2D, certaines composantes existent à la même position mais ce n'est pas le cas en 3D.
Les champs électriques et magnétiques sont également décalés en temps de
.
La grille représentée par les noeuds rouge du champ est appelée grille duale.
C'est la grille la plus large.
Dans la figure ci-dessous, nous avons représenté la grille définie par les noeuds oranges du champ .
Il s'agit de la grille primale.
Le grille primale est celle qui contient le moins de noeuds.
Par définition, si la grille primale a une taille de alors la grille duale a une taille de
.
Toutes les autres composantes sont une combinaison duale / primale.
Par exemple, la grille définie par les noeuds bleus (composantes et
) est primale dans la direction
mais duale dans la direction
.
Elle a donc une taille
.
De la même manière, la grille définie par les noeuds verts (composante
et
) est au contraire duale dans la direction
et primale dans la direction
.
La figure ci-dessous résume la notion de grille primale et duale :
Il faut maintenant se pencher sur les conditions limites. Les composantes de champs qui nécessitent d'être traitées sont aux bords sont situées sur la ligne violette de la figure ci-dessous :
De plus, les équations nous disent que les inconnus aux bords sont toutes des composantes du champ magnétique. En effet les champs électriques aux bords se calculent à partir des champs magnétiques connus.
Dans le code, on utilise des conditions réfléchissantes (ou conditions de Neumann).
Une façon de générer un champ électromagnétique est de mouvoir une charge dans l'espace On choisit ici de faire osciller une bille le long d'un segment. Il faut alors calculer le courant généré par cette bille et l'ajouter aux équations de Maxwell-Ampère.
Soit l'évolution dans l'espace d'une charge
et donc
sa vitesse.
Le courant est donné par :
Pour le mouvement oscillatoire le long d'une segment, on utilise :
Avec la longueur du segment et
la période d'oscillation.
Le code est écrit en langage C++ mais n'utilise pas de fonctionnalité avancée.
Il ne se compose que d'un unique fichier main.cpp.
Le code se compose d'une phase d'initialisation puis d'une boucle ne temps (main loop) :
for (iteration = 1 ; iteration <= iterations ; iteration++) {
//...
}Dans la partie d'initialisation, on fait dans l'ordre :
- la déclaration des paramètres
- l'initialisation par défaut
- la lecture des arguments en ligne de commande
- l'initialisation des tableaux et des variables internes
- sortie des grilles dans des fichiers au temps 0
Puis dans la boucle en temps :
- résolution des équations de Maxwell-Ampère
- ajout des courants générés par les antennes
- résolution des équations de Maxwell-Faraday
- conditions aux bords
- sortie des fichiers de diagnostique (pour chaque grille)
- affichage dans le terminal de l'état de la simulation
Puis après la boucle en temps :
- l'affichage des timers, c'est à dire le temps passé dans les diverses parties du code
- destruction des tableaux
Ce programme nécessite l'installation d'un compilateur C++.
Vous n'avez besoin que d'une bibliothèque MPI. Sur les postes de travail de l'université, OpenMPI est déjà installé. Pour l'installer sur vos ordinateurs personnels, utilisez les instructions dans le dossier ./documentation.
Pour compiler ce programme, vous pouvez utiliser les commandes suivantes en fonction de vos compilateurs :
Pour g++:
g++ -O3 main.cpp -o exePour Intel (sur Ruche par exemple) :
icpc -O3 main.cpp -o exeLa compilation génère un fichier exécutable du nom de exe.
Vous pouvez lancer le programme en faisant :
./exeIl est possible de changer certains paramètres numériques directement en ligne de commande :
./executable -nx 128 -ny 256 -it 1000-nx: nombre de points pour la grille duale dans la direction x-ny: nombre de points pour la grille duale dans la direction y-it: nombre d'itérations-d: fréquence des sorties de fichier en nombre d'itérations-p: fréquence des affichages dans le terminal en nombre d'itérations
Le code génère des sorties (fichier sur le disque dur) au format binaire contenant les grilles de champs à un temps donné.
Les fichiers sont toujours écrits dans un dossier diags.
Des scripts Python vous sont fournis pour vous aider à visualiser ces données. Vous pouvez aussi utiliser vos propres scripts dans le langage de votre choix. Les scripts sont dans le dossier visualization:
python -i plot_all_fields.py <chemin vers le dossier des diags> <it>python -i plot_binary.py <chemin vers un fichier diag*.bin>Voici un exemple d'image produite par la lecture d'un fichier via le script plot_all_fields.py.
Dans ce TP, vous aurez à modifier un programme séquentiel afin de le rendre parallèle avec le standard MPI. Vous serez ensuite amené à étudier les performances de la version parallèle.
Le TP se compose de 4 sous-sections :
- Sous-section I : il s'agit de la découverte du code séquentiel
- Sous-section II : cette partie concerne la découverte de la machine parallèle
- Sous-section III : cette partie est l'implémentation de la version MPI
- Sous-section IV : cette partie est l'étude de la performance des codes parallèles
- Sous-section V : aide et conseils pour le projet




