0/ Préparation

Tous les travaux pratiques et le projet se feront en Python. Avant de commencer les TPs d’implémentation, vérifions que l’installation Python à disposition (dans les salles de TP ou sur une machine personnelle) est suffisante :

Consigne
  1. Vérifiez que Spyder et/ou Jupyter est bien installé sur votre machine de travail
  2. Vérifiez que les librairies numpy et matplotlib sont bien présentes (import numpy; import matplotlib.pyplot)
  3. Pour la visualisation des résulats de simulation, on utilisera Ovito. Sur la page de téléchargement, vous trouverez des versions pour chaque OS qui n’ont pas besoin d’installation (pour Windows, la version ovito-basic-3.10.1-win64.zip, et non la .exe).

Sur les ordinateurs des salles de TP il n’est pas possible de lancer Ovito depuis le navigateur de fichiers. Il faut donc télécharger le script suivant run_ovito.ps1 et l’exécuter (clic droit > “Exécuter avec Powershell”) après avoir extrait l’archive zip de Ovito dans le dossier “Téléchargements”.

Pour la rédaction du rapport, il est recommandé d’utiliser LaTeX, le Wikibook LaTeX est une excellente ressource, et Overleaf une bonne solution d’édition, qui évite d’installer LaTeX et permet facilement la collaboration.

Afin de se refamiliariser avec Python, il est fortement recommandé de faire les exercices corrigés de code du chapitre sur l’intégration numérique des équations différentielles ordinaires.

Installation de paquets Python

Sur les ordinateurs de TP, il est possible d’installer des paquets Python avec la commande :

pip install --proxy http://proxyweb.upmc.fr:3128 <paquet>

Dans Spyder, on pourra exécuter cette commande dans la console IPython en la précédant d’un point d’exclamation, par exemple :

In[1]: !pip install --proxy http://proxyweb.upmc.fr:3128 matscipy

Quelques erreurs communes en Python et Numpy

Création vs. mise-à-jour de la valeur d’une variable

N = 10

velocities = np.zeros([2, N])

velocities[:] = 1
print(f"`velocities[:] = 1` donne :\n{velocities}\n")

velocities = 2
print(f"`velocities = 2` donne :\n{velocities}")
1
On crée des vitesses 2D pour chaque particule
2
On assigne une valeur à chaque composante du vecteur velocities
3
On crée une nouvelle variable qui vient effacer la première
`velocities[:] = 1` donne :
[[1. 1. 1. 1. 1. 1. 1. 1. 1. 1.]
 [1. 1. 1. 1. 1. 1. 1. 1. 1. 1.]]

`velocities = 2` donne :
2

Le code velocities[:] = 1 permet d’assigner la valeur 1 à toutes les valeurs du tableau velocities, qui est un “Numpy array”. En revanche, quand on écrit velocities = 2, on crée en réalité une nouvelle variable qui vient détruire l’ancienne variable. velocities est donc maintenant un entier qui vaut 2.

Valeur de retour d’une fonction

def forward_euler1(position, velocity, dt):
    return position + velocity * dt

def forward_euler2(position, velocity, dt):
    position += velocity * dt

La première fonction retourne la position après une itération d’Euler explicite. On doit donc l’utiliser comme ceci, en assignant la valeur de retour de la fonction :

position, velocity = 1, 0.1
dt = 0.1

position = forward_euler1(position, velocity, dt)
print(position)
1.01

La seconde fonction ne retourne aucune valeur. À la place, elle met à jour la valeur de l’argument position, et doit être utilisée comme ceci :

positions, velocity = 1, 0.1
dt = 0.1

forward_euler2(positions, velocity, dt)
print(position)
1.01

Notez que si on utilise forward_euler2 comme forward_euler1, on change complètement la variable position, qui devient None :

position = forward_euler2(position, velocity, dt)

print(position, type(position))
None <class 'NoneType'>

Cela peut facilement causer des erreurs dans le reste du code, par exemple :

position += 1.0
TypeError: unsupported operand type(s) for +=: 'NoneType' and 'float'