BE Python
BE Python
BE Python
On veut connaître la température en régime stationnaire dans une barre (Voir premier
cours).
Système à résoudre :
On prendra une barre de longueur 2 mètres. Le coefficient alpha sera égal à a=0.002
et la fonction f sera une fonction dépendant de x (la coordonnée du point sur la barre)
avec f(x)=0.1* x.
Tg sera égale à 0 °C et Td à 100 ° C.
Attention :
* Il est important de s'habituer à la gestion des fichiers : il faut savoir dans quel
dossier on range les fichiers pour pouvoir les retrouver, les modifier éventuellement et
les exécuter par la suite. Une fois qu'on a écrit un programme il faut le sauvegarder :
on choisit par exemple « save as » et le nom du fichier qui doit nécessairement avoir
l'extension « .py » : Windows reconnaitra par la suite cette extension lorsqu'on lui
demandera l'exécution du « script ».
On appelle « script python » un fichier texte dont le nom se termine par l'extension
« .py ». Un script définit à lui seul un programme informatique.
Exemple à faire :
Dans la racine de votre espace de travail (Z:) créer un fichier texte (clic droit →
nouveau → fichier texte) nommé exemple.py puis ouvrez le avec un éditeur
quelconque (“Edit with Notepad++ est proposé par défaut). Vous reproduirez les lignes
ci-dessous (code identifié par la couleur bleu).
Les commentaires signalés par des « # » permettent de commenter le programme avec
du texte qui sera ignoré à l'exécution du script. Lorsque vous écrirez vos propres
programmes il est conseillé de commenter abondamment.
Sauvegardez le fichier (ctrl+s).
from numpy import * # module d'algèbre linéaire de base (array,
# linspace,...)
import matplotlib.pyplot as plt # pour le tracé de courbes (plt.plot(…) )
L'option “-i“ indique une exécution en mode interactif. Après exécution on reste dans
l’interpréteur python. Sans cette option (tester par vous même ipython
exemple.py) python exécute le script et se referme immédiatement.
Il est aussi possible de lancer l’interpréteur seul par la commande « ipython », puis
dans l’interpréteur “run test.py”.
Fenêtres de spyder
A gauche : fenêtre interactive. A droite, le fichier sauvegardé par la commande plt.savefig("fig1.png")
Retour à notre problème stationnaire
Nous allons élaborer le programme via plusieurs exercices.
Exercice 1 :
Écrire le script créant toutes les variables nécessaires à la résolution du système. On
prendra comme variable initiale le nombre d'intervalles n (que l'on prendra égal à 100)
du découpage par différences finies. Le pas d'espace et la dimension du système à
résoudre seront calculés à partir de cette variable n.
Créer un vecteur contenant les coordonnées des points du découpage différences finies.
Créer un vecteur de taille adaptée pour contenir le second membre.
Chaîne de caractères:
>>> titre="un titre”
Nombre entier :
>>> N=20
Nombre réel :
>>> x=1.32 #instancie la variable et affecte la valeur
>>> y=2.5*pi #instancie la variable et affecte le résultat
>>> z=2. #un point quand on veut une variable réelle, ou
>>> z=2.0 #équivalent
Attention, la division de deux nombres entiers ne donne par forcément un entier en
python 3 contrairement à la version 2:
>>> 2/3
1.5
Attention!
Les variables python sont des noms, ou «références», donnés aux valeurs stockées en
mémoire (comme des pointeurs en C). Dans le cas général le signe «=» entre deux
variables signifie une identité plutôt qu'une affectation de valeur. «a=b» a le sens «a
est b».
La nuance est importante et peut conduire à des résultats contre-intuitifs. Exemple
avec deux (ou un?) vecteurs:
>>> from numpy import * #sera expliqué plus loin
>>> a=zeros(3) #un vecteur à trois composantes nulles
>>> b=a #définit «b» en lui affectant «a»
>>> b[0]=7 #affectation de la valeur 7 à la 1ère composante de «b»
>>> a=zeros(3)
>>> b=array(a)
>>> b[0]=7 # affectation de la valeur 7
# à la première composante
>>> print (a,b)
[ 0. 0. 0.] [ 7. 0. 0.]
Remarque: ce problème ne se pose pas si l'on affecte le résultat d'une opération.
Evidemment si l'on écrit «a=b+c», a n'est ni b ni c. Si l'on écrit a=pi*b, a n'est pas b.
Par conséquent l'opération suivante a le même effet qu'un appel au constructeur
d'array:
>>> a=zeros(3)
>>> b=1*a
>>> b[0]=7
>>> print (a,b)
[ 0. 0. 0.] [ 7. 0. 0.]
>>> a=100
>>> b=a
>>> b=50
>>> print (a,b)
100 50
List
Python permet de définir des listes génériques. Elles sont définies par des éléments
entre crochets séparés par des virgules, et peuvent contenir des types hétérogènes.
>>> L=[1,2,3,4]
On peut utiliser des opérateurs logiques pour créer une liste, ex :
>>> M=[cos(x) for x in L if x>=3 ] #cosinus des éléments de L
supérieurs #ou égaux à 3
>>> M
[-0.98999249660044542, -0.65364362086361194]
Une liste souvent utile est celle générée par « range() », qui contient N entiers
consécutifs. Attention, la séquence commence à zéro et se termine donc à N-1 :
>>> range(5)
[0, 1, 2, 3, 4]
ou des entiers consécutifs entre deux limites (attention à nouveau : la liste s'arrête au
nombre entier inférieur à la seconde borne) :
>>> range(2,5)
[2, 3, 4]
On accède aux éléments d'une liste par leur indice entre crochets. Les indices
commencent à zéro, comme en langage C.
>>> a=range(2,5)
>>> a[0]
2
Array
Les listes ne permettent pas, ou peu, d'opérations mathématiques. Pour les calculs
d'algèbre linéaire on utilisera le type array (vecteur), qui est fourni par le module
«numpy». Pour cela il faut importer le module:
>>> import numpy
Plutôt que :
>>> import numpy
>>> numpy.cos(numpy.pi*numpy.sqrt(5))
D'une manière générale, un module contient des variables (ex. pi), des fonctions (ex.
sqrt()), et des sous modules (ex. numpy.linalg sera évoqué plus loin). L'instruction
« import » rend accessible les variables et fonctions mais pas les sous-modules. Nous
serons amenés dans la suite à importer spécifiquement le sous-module « linalg ».
Opérations sur les « arrays »
Comme la somme :
>>> u+u
array([0, 2, 4, 6, 8])
Attention : certaines opérations de base ont des effets très différents sur les listes et
les arrays :
>>> L+L #concaténation de listes
[0, 1, 2, 3, 4, 5, 4, 3, 2, 1, 0, 0, 1, 2, 3, 4, 5, 4, 3, 2, 1, 0]
>>> A+A #additions de deux vecteurs
array([ 0, 2, 4, 6, 8, 10, 8, 6, 4, 2, 0])
Exercice 2 :
Créer et remplir la matrice intervenant dans le système à résoudre en fonction du
nombre d'intervalles choisi n.
On accède aux composantes de cet array par leurs indices entre crochets. Rappel : les
indices commencent à zéro.
>>> M=zeros([5,4])
>>> M[2,2]=5
>>> M
array([[ 0., 0., 0., 0.],
[ 0., 0., 0., 0.],
[ 0., 0., 5., 0.],
[ 0., 0., 0., 0.],
[ 0., 0., 0., 0.]])
On accède à toutes les composantes d'une ligne ou d'une colonne (i.e. vecteur ligne ou
vecteur colonne) en remplaçant un des index par « : »:
>>> M[:,2]
array([ 0., 0., 5., 0., 0.])
Quelques remarques :
Les vecteurs ne sont finalement que des matrices particulières dont une des
dimensions vaut 1. Les opérations d'addition, multiplication, fonctions appliquées par
composantes,… expliquées précédemment pour les vecteurs fonctionnent de la même
manière pour les matrices.
Il y a encore beaucoup d'autres fonctions disponibles dans numpy et ses sous-modules
pour faire des opérations avancées.
Certaines fonctions sont accessibles comme fonctions de l'array. Pour voir ce qui est
accessible, si « m » est un array, écrire « m. »+TAB. Notamment :
>>> m.diagonal() #Vecteur des composantes diagonales
>>> m.trace() #Trace de m
Une autre fonction utile est diag(), qui construit une matrice à partir de son vecteur
diagonal, ou un vecteur diagonal à partir d'une matrice.
>>> m=diag([1,2,1])
>>> m
array([[1, 0, 0],
[0, 2, 0],
[0, 0, 1]])
>>> diag(m)
array([1, 2, 1])
Condition : if et else
Pour exécuter des commandes de manière conditionnelle on utilise « if », et
éventuellement « else ».
Syntaxe (notez l'indentation ! Il peut être plus simple de saisir cet exemple dans le
script plutôt que dans la ligne de commande, l'indentation dans un fichier étant plus
simple).
>>> i=4
>>> if sqrt(i)>7:
... print ("sqrt(i)>7 (", sqrt(i),")")
... else:
... print ("sqrt(i)<=7 (", sqrt(i),")")
...
sqrt(i)<=7 ( 2.0 )
Quand un bloc d'instruction tient sur une seule ligne on peut en réalité mettre la
condition et l'instruction sur la même ligne :
>>> if sqrt(i)>7: print ("sqrt(i)>7 (", sqrt(i),")")
>>> else: print ("sqrt(i)<=7 (", sqrt(i),")")
On combine les expressions logiques avec « and » et « or », on peut utiliser la négation
« not », et on peut tester la présence d'un élément dans une séquence avec « in » . On
utilise les parenthèses s'il faut lever des ambiguités :
>>> x=80
>>> x>100 and sqrt(x)>7
False
>>> x>100 or sqrt(x)>7
True
>>> (x>100 or sqrt(x)>7) and not "i" in "chaine de caractère avec i"
False
Opérateurs de comparaison Description
a<b est strictement inférieur
a>b est strictement supérieur
a <= b est inférieur ou égal
a >= b est supérieur ou égal
a == b est égal
a != b est différent
Boucle FOR : répète une opération pour chaque élément d'une liste
Une première possibilité pour exécuter une séquence d'instructions de manière
répétée consiste à effectuer une boucle pour les valeurs d'une variable prise dans une
séquence. Ce processus est mis en œuvre par la boucle for. Notez les « : » après FOR.
>>> A=zeros([4,4])
>>> for i in range(4):
... print (i)
... A[i,i]= i
...
0
1
2
3
>>> print (A)
[[ 0. 0. 0. 0.]
[ 0. 1. 0. 0.]
[ 0. 0. 2. 0.]
[ 0. 0. 0. 3.]]
While est souvent associé à une instruction « break » conditionnelle, exemple pour le
plus petit entier dont la racine est supérieure à 7:
i=0
while True : #d'après cette ligne on pourrait boucler indéfiniment
i=i+1
if sqrt(i)>7: break
Ici on pourrait tout aussi bien utiliser « sqrt(i)>7 » comme condition du while, mais
dans bien des cas la prise de décision dépend d'opérations plus complexes qui sont plus
difficiles à inclure dans une condition simple (ex. une condition de convergence qui ne
peut être testée avant d'avoir effectivement fait des calculs).
Exercice 3 :
Résoudre le système en calculant le vecteur T contenant la solution approchée. Tracer
le diagramme donnant la température approchée en fonction de x.
Pour y parvenir :
Module linalg
Le module « linalg » (linear algebra) est un sous-module de numpy qui offre des
fonctions avancées pour des opérations telles que la diagonalisation, l'inversion de
matrice, la résolution de systèmes linéaires,…
On ne saurait trop recommander de consulter la documentation de linalg en ligne.
Les fonctions qui peuvent nous intéresser dans l'immédiat sont l'inversion de matrice
(linalg.inv) et la résolution de système (linalg.solve). Exemple pour la résolution de
Mx=b:
Sans surprise multiplier b par M-1 ou utiliser la fonction de résolution (en pratique
factorisation LU) produit le même résultat. La principale différence est le temps
d'exécution pour des problèmes d'une taille suffisante :
>>> from numpy import *
>>> from numpy import linalg
>>> M=eye(10000)+ones([10000,10000]) #ones() retourne une matrice pleine
de 1
>>> b=ones(10000)
Testez les deux méthodes pour le problème de départ avec différentes valeurs de N.
Remarquez ci-dessus l'utilisation du module « time » pour mesurer le temps
d'exécution, et les points virgules qui permettent d'enchainer plusieurs instructions en
une ligne de commande.
Module « matplotlib » :
Comme vu dans l'exemple de départ, ce module fournit les fonctionnalités essentielles
pour représenter les résultats sous forme graphique, on se contentera de quelques
fonctions de base. Le module matplotlib.pyplot couvrira l'essentiel des besoins (pour
usage avancé: https://matplotlib.org/gallery/index.html).
Exemple:
import matplotlib.pyplot as plt
plt.plot([0,1],[0,1]) #trace le segment allant de (0,0) à (1,1)
plt.plot([0,1],[0,2]) #puis le segment allant de (0,0) à (1,2)
plt.show() #affiche la fenêtre
Une figure sans titre, sans noms d'axes et sans légende étant un non-sens ajoutons
aux commandes qui précèdent celles qui définissent les axes, les légendes, et celle qui
permet d'enregistrer le graphe dans un fichier sans passer par une copie d'écran.
La structure de la commande plot est la suivante: plt.plot(x,y,[style],
[légende])
Le style est défini par une chaîne de caractères représentant une couleur (‘r': red,
‘c':cyan, ‘g': green, ‘k': black,…) suivie d'un symbole (‘.': petit point, ‘o': cercle, ‘x': croix,
‘*': étoile,…) et d'un style de ligne (‘-': ligne continue, ‘--': pointillée, si rien pas de
ligne). Par exemple plt.plot(x,y,”go--”) tracera une ligne discontinue verte avec
les points matérialisés par des cercles.
Liste plus complète des conventions ici.
“label” est l'étiquette qui sera affichée dans la légende. La légende ne s'affiche que si
on exécute la commande “plt.legend()”.
import matplotlib.pyplot as plt
plt.plot([0,1],[0,1],"ro-",label="courbe1") #trace segment de (0,0)
à (1,1)
plt.plot([0,1],[0,2],"g+--") #puis segment de (0,0) à
(1,2)
plt.xlabel("titre x")
plt.ylabel("titre y")
plt.legend()
plt.savefig("fig.png") #sauvegarde fichier image dans le répertoire
courant
plt.show() #affiche la fenêtre
Pour information :
(invalide à Greener en 2019/2020 car latex n’est plus installé)
Ce qui suit illustre la saisie d'expressions complexes ou caractères grecs (pas besoin de
le tester maintenant). Dans la commande plt.xlabel(r'$... $ [-]',
fontsize=20) les codes entre les dollars suivent les conventions LaTeX
(https://fr.wikipedia.org/wiki/LaTeX). La taille de police est augmentée pour rendre les
titres d'axes plus lisibles.
Il peut être nécessaire d'ajuster manuellement les marges de la fenêtre graphique.
plt.xlabel(r'$\alpha$ ou $\pi$', fontsize=20) #équation (syntaxe LaTeX)
plt.ylabel(r'$\frac{d}{dt} \int_0^t\sqrt{cos(t)^2}dt$ [-]',fontsize=20) #plus
chaud
plt.savefig("fig2.png")
Exercice 4 :
Modifier le script pour obtenir les solutions avec n=100 et n=4.
Tracer les solutions sur 2 figures séparées pour voir l'influence de n.
Exercice 5 :
Tracer les solutions pour n=100 et n=4 sur une même figure pour mieux les comparer.
Pour cela on introduira une fonction, réutilisant le code déjà écrit.
Définition de fonction
La syntaxe pour définir une fonction Python est :
def nomDeLaFonction(paramètres1,paramètre2,...):
ligne 1
ligne 2
…
return résultat
Comme pour les conditions et les boucles, c'est l'indentation qui détermine le début et
la fin du corps de la fonction.
Il est possible de retourner plusieurs résultats, et ce sera utile dans la suite.
Exemple :
>>> def cos_et_sin(t):
... y=cos(t)
... z=sin(t)
... return y,z
>>> a,b=cos_et_sin(0.3) #affecte directement à deux variables a et b
Pour pouvoir tracer simplement les solutions obtenues avec plusieurs valeurs de n le
principe est le suivant. Schématiquement, le script actuel ressemble en principe à :
n=100
[ exécution des calculs pour n fixé ]
plt.plot(x,t)
plt.show()
x1,t1=solution(4)
x2,t2=solution(100)
plt.plot(x1,t1)
plt.plot(x2,t2)
plt.show()