Vous êtes sur la page 1sur 18

BE1: Initiation à l'utilisation de Python et

programmation de la résolution d'un problème de


thermique stationnaire

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.

Ce problème va nous servir de support pour appliquer les principales commandes


Python. L’importance de certaines parties dépends de votre niveau de pratique du
langage Python :
1. Vous ne connaissez rien au langage Python : ce sujet servira à introduire les
commandes suffisantes pour les BE de méthodes numériques, il est donc d’une
importance majeure et toutes les commandes expliquées ici sont supposées connues
pour la suite.
2. Vous avez un certain niveau de pratique : certaines parties seront
probablement déjà connues, vous pouvez choisir l’éditeur dont vous avez l’habitude si
disponible (à ENSE3 principalement, notepad++, Spyder, Pycharm).

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.

Python est un langage interprété, on ne compile pas le programme pour ensuite


l'exécuter. On tape une ligne de commande et l'interpréteur Python la traduit en
langage machine avant de l'exécuter et de passer à la ligne d'instruction éventuelle
suivante.

Conséquence : en général (le premier exemple ci-dessous fait exception) le programme


ne s' « arrête » pas à la fin de l'exécution. Il attend une nouvelle instruction et conserve
toutes vos variables disponibles pour une nouvelle utilisation. Même s'il a eu un
problème lors d'une exécution, commande incohérente, division par zéro …, vous
gardez la main pour une nouvelle instruction, pour relancer votre commande qui n'a
pas marché (après correction) ou pour voir l'état de vos variables et ainsi comprendre
pourquoi la commande n'a pas marché.
Ceci est primordial pour vous permettre de débugger facilement vos programmes.

Les noms de fichiers ou des répertoires ne doivent pas contenir d'espace ou de


caractères spéciaux (ex. accents). En ce qui vous concerne, vous sauvegarderez les
fichiers dans vos espaces personnels. Les scripts Python ont tous un nom de fichier se
terminant par l'extension .py

Le langage Python est très “modulaire”. La plupart des fonctionnalités avancées ne


sont pas accessibles par défaut, elles font partie de modules qu'il faut importer par la
commande “import nomDuModule”, comme on le verra dans la suite.

Le langage Python et ses modules bénéficient d'une abondante documentation en


ligne et de support sur différents forums de discussion (notamment python-forum, et
StackOverflow) le moyen le plus simple de trouver une réponse à une question sur
Python reste d'écrire la question dans un moteur de recherche (en anglais,
idéalement).

Création et exécution d'un script python

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(…) )

t=linspace(0,200,10) #10 valeurs réparties entre 0 et 200 (inclus)


x=sin(t*pi/100)

print ("t=",t,"\n x=",x) # le caractère "\n" représente un retour à la


ligne

plt.plot(x) # série de valeurs sans série d'abscisse particulière


plt.show() # affiche la figure à l’écran

plt.figure( ) # crée une seconde figure


plt.plot(t,x) # série de valeurs vs. valeurs d'abscisse
plt.xlabel("t [s]")
plt.ylabel("x")
plt.savefig("fig2.png") # sauvegarde la figure comme image (évite la copie
# d’écran môche…)

Il y a au moins deux façons d'exécuter ce programme :

1 - démarrez le programme « Anaconda prompt » puis dans ce terminal allez vers le


répertoire « Z: » par la commande « z : + entrée ». Ecrivez « ipython -i
exemple.py (Note : quand le script n’est pas directement dans le répertoire courant il
faut écrire le chemin complet, il peut être copié dans la barre d’adresse de
l’explorateur, clic-droit + copier en tant que texte, puis collé avec clic droit dans le
terminal, ex. ).
Le script est exécuté, puis l'interpréteur attend les commandes suivantes. Tapez «x +
entrée», le contenu de la variable s'affiche.
Pour sortir de l'interpréteur python et retourner au DOS:
ctrl+D + entrée, ou
quit() + entrée.

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”.

2 – démarrez le programme spyder (anaconda). Pour la suite de ces BE on


suggère l'usage de spyder, un environnement de développement intégré (IDE) qui
permet de programmer dans un environnement convivial en profitant de
fonctionnalités avancées.
On retrouve un éditeur de texte (à gauche dans la figure ci-dessous) et le terminal
d’exécution (en bas à droite), et d'un explorateur de fichiers et de variables. Dans le
terminal vous pouvez taper directement les commandes en langage python – à utiliser
sans modération pour tester les lignes de code avant de les ajouter au script. Vous
pouvez aussi exécuter le fichier courant de l'éditeur.

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.

Très important! (1)


Au fur et à mesure que des commandes sont introduites à la suite des exercices, vous
devez les tester dans l'invite de commande. C'est seulement après avoir testé
toutes les commandes que vous sélectionnerez celles qui sont utiles à la résolution de
l'exercice et que vous les ajouterez à votre script.

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.

Quelques commandes utiles pour cet exercice :

Commandes de création de variable


Il n'y a pas nécessairement de déclaration de type de variable dans Python. Le type et
la création de la variable se font automatiquement lors de l'affectation d'une variable.
Les principaux types de variables utilisés dans ces BEs sont les nombres entiers, les
nombres réels, les chaînes de caractères, les vecteurs et matrices à composantes
réelles. Leur création se fait comme suit.

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

Pour une division entière il faut utiliser l’opérateur //


>>> 2//3
0
Ce qui peut poser problème pour définir la dimension d’un vecteur à partir d’un pas
d’espace ou de temps, un nombre d’itérations dans une boucle… soyez vigilants:
>>> Tmax=2 #temps maximal de la simulation
>>> dt=0.03 #pas de temps
>>> nIter=Tmax/dt
>>> print (nIter) # Le nombre de pas de temps a exécuter
# ne sera pas une valeur entière

On peut convertir un réel en entier :


nIter=int(Tmax/dt)

Remarque : dans la commande ci-dessus, int(Tmax/dt) revient à une déclaration


explicite du type de variable. On dit que int() est un « constructeur » vis à vis du
type « nombre entier».

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»

Avons nous à ce stade deux ou un seul vecteur en mémoire?

>>> print (a)


[ 7. 0. 0.]

Il y en a un seul ! Modifier b revient à modifier a, et inversement, puisque nous avons


déclaré « a est b ».
« a » et « b » sont deux noms différents pour une seule et même variable stockée en
mémoire.

Pour forcer le langage à générer deux vecteurs distincts, modifiables indépendamment


l'un de l'autre, il faut utiliser le constructeur du type visé. Ici la fonction zeros() a créé
au départ une variable de type «array»:

>>> 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.]

Exception à la règle d'affectation : Les types intégraux : entiers, réels, et chaînes de


caractères sont considérés comme des constantes et tout se passe comme si ils pré-
existaient en mémoire.
« x=100 » signifie que x est le nom donné à la constante 100.
« y=x », signifie que y est aussi un nom donné à la constante 100
Si à la suite on écrit « y=50 » plutôt que de modifier la valeur vers laquelle pointe y (ce
qui est impossible puisque 100 est un nombre constant) on fait pointer y vers une
autre constante, désormais « y est 50 » ; tandis que x est toujours 100.

>>> a=100
>>> b=a
>>> b=50
>>> print (a,b)
100 50

Listes, vecteurs et matrices :

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

Contrairement au langage C on peut utiliser des indices négatifs, partant de la fin de


la liste (de même pour les arrays ci-dessous). C'est très utile pour aller chercher le
dernier élément sans se demander quelle est la taille de la liste.
>>> a[-1]
4

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

On peut ensuite utiliser les arrays :


>>> v=numpy.array(range(5)) #constructeur d'array initialisé par
une liste
>>> v
array([0, 1, 2, 3, 4])

Module numpy et import


Important : Ce même module nous donnera accès au nombre p « pi », à la fonction
racine carrée « sqrt() », aux fonctions sinus et cosinus (« sin() », « cos() »), et
d'autres encore. Dans la mesure où les fonctions du module numpy seront utilisées
presque à chaque ligne des programmes en BE, pour éviter de surcharger l'écriture
des expressions mathématiques on fera un import « maximaliste » comme ci-dessous,
rendant accessible toutes les fonctions et variables du module sans le préfixe
« numpy. ».
Il est donc recommandé d'inclure systématiquement cette ligne dans le
préambule de tous vos scripts pour rendre accessibles toutes les fonctions et
variables de numpy dans l'”espace de nommage” principal:

>>> from numpy import * #importe toutes les variables et


fonctions de numpy
>>> cos(pi*sqrt(5))
0.73736887807831963

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 »

Revenons aux arrays.


* Pour créer un array où toutes les valeurs sont initialisées à zéro et avec une taille
donnée on utilise la fonction zeros() (du module numpy, à partir de maintenant on
suppose que ce module est importé).
>>> v=zeros(5)

* Pour des valeurs réelles distribuées entre deux bornes


>>> linspace(2,8,100) #100 valeurs réparties entre 2 et 8 (inclus)

* On accède aux composantes par leur index entre crochets.


Les indices commencent à zéro, comme en C. Donc « v[5] » retournera un message
d'erreur sur l'index.
>>> v=zeros(5)
>>> v[2]
0.0
>>> v[5]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: index out of bounds

* Une opération mathématique sur un array retourne un array de même taille en


appliquant la fonction à chacune des composantes :
>>> u=array(range(5))
>>> u
array([0, 1, 2, 3, 4])
>>> 5.*u #multiplication par un réel
array([ 0, 5, 10, 15, 20])
>>> sqrt(u) #racine carrée des composantes
array([ 0. , 1. , 1.41421356, 1.73205081, 2. ])

De même la multiplication de deux arrays multiplie composante par composante :


>>> u*u
array([ 0, 1, 4, 9, 16])

Comme la somme :
>>> u+u
array([0, 2, 4, 6, 8])

* Le produit au sens de l'algèbre linéaire (produit scalaire de deux vecteurs, ou produit


matrice*vecteur) est exécuté avec la fonction dot(), qui est une fonction de l'array lui
même, d'où la syntaxe « u. » ci-dessous :
>>> u.dot(u) # «u.» donne accès aux fonctions de la variable u
30
Relation entre list et array
Les listes étant parfois plus faciles à manipuler que les arrays, il peut être utile de
construire une liste puis de la convertir en array au moment de faire des calculs. On
utilise pour cela la fonction asarray (« as array ») :
>>> L=[x if x<5 else 10-x for x in range(11)]
>>> L
[0, 1, 2, 3, 4, 5, 4, 3, 2, 1, 0]
>>> A=asarray(L)
>>> A
array([0, 1, 2, 3, 4, 5, 4, 3, 2, 1, 0]) #maintenant utilisable comme un
array

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.

Quelques commandes utiles pour cet exercice :

Création d'une matrice


La fonction zeros() utilisée pour créer un vecteur nul peut aussi créer un tableau de
dimensions arbitraires. Pour un tableau 2D (une matrice) on passe à la fonction une
liste de longueurs dans chaque dimension (on se souvient que les listes sont écrites
avec des crochets) :
>>> zeros(5)
array([ 0.,  0.,  0.,  0.,  0.])
>>> zeros([5,4])
array([[ 0.,  0.,  0.,  0.],
      [ 0.,  0.,  0.,  0.],
      [ 0.,  0.,  0.,  0.],
      [ 0.,  0.,  0.,  0.],
      [ 0.,  0.,  0.,  0.]])

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.])

La commande shape() permet d'obtenir les dimensions d'une matrice M donnée.


>>> shape(M)
(5, 4)
>>> shape(M)[0]
5
>>> shape(M)[1]
4

Les principales fonctions de création de matrices sont listées ci-dessous.


eye(n) #matrice identité de dimension n
ones([m,n]) #matrice à m lignes et n colonnes dont
#tous les éléments valent 1
zeros([m,n]) #matrice à m lignes et n colonnes dont
#tous les éléments valent 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])

Tableaux de taille variable


On peut modifier la taille, ou concaténer, des arrays. Cependant par souci de
simplicité on recommande dans ces situations d'utiliser des listes (ex. pour accumuler
les résultats dans un tableau dont la taille grandit à mesure que l'on calcule). On peut
toujours en refaire un array plus tard si nécessaire.
>>> resultats=[]       
>>> resultats.append([1,2,3])
>>> resultats.append([5,5,5])
>>> resultats
[[1, 2, 3], [5, 5, 5]]
>>> asarray(resultats)
array([[1, 2, 3],
      [5, 5, 5]])
>>> asarray(resultats)[:,1] # 2nd valeur de chaque résultat,
# plus difficile à extraire d'une liste
array([2, 5])

Boucles et conditions en Python


Les instructions de contrôle Python sont très proches de celles existant dans d'autres
langages de programmation.
Par contre, d'une manière générale, le début et la fin d'un bloc d'instructions sont
définis uniquement par l'indentation, une tabulation (non recommandé) car le nombre
d’espace d’une tabulation dépend de l’éditeur utilisé) ou quatre espaces, comme on le
voit ci-dessous. A l'inverse, en langage C on mettrait des accolades { … } pour délimiter
le bloc d’instructions.
Quand on saisit un bloc directement dans le terminal l'invite de commande affiche
« ... » plutôt que le « >>> » habituel, pour terminer le bloc il suffit d'appuyer à
nouveau sur entrée.

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.]]

Boucle WHILE : tant que . . . faire


On itère tant qu'une condition n'est pas vérifiée. On arrête de boucler dès que cette
condition n'est plus satisfaite.
>>> i=0
>>> while i<4:
...     i=i+1
...     print (i)
...  
1
2
3
4

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:

>>> from numpy import *


>>> from numpy import linalg
>>> linalg.solve
<function solve at 0x7fb35c664938>
>>> M=0.5*eye(3)
>>> M
array([[ 0.5,  0. ,  0. ],
      [ 0. ,  0.5,  0. ],
      [ 0. ,  0. ,  0.5]])
>>> invM=linalg.inv(M)
>>> invM
array([[ 2.,  0.,  0.],
      [ 0.,  2.,  0.],
      [ 0.,  0.,  2.]])
>>> b=array([1,1,1])
>>> invM*b
array([[ 2.,  0.,  0.],
      [ 0.,  2.,  0.],
      [ 0.,  0.,  2.]])
>>> invM.dot(b)
array([ 2.,  2.,  2.])
>>> linalg.solve(M,b)
array([ 2.,  2.,  2.])

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)

>>> import time


>>>tStart=time.time();x=linalg.inv(M).dot(b);print ("time=",time.time()-
tStart)
exec time= 18.9800388813
>>> tStart=time.time(); x=linalg.solve(M,b); print ("time=",time.time()-
tStart)
exec time= 5.29851603508

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 créer plusieurs figures indépendantes on utilise “plt.figure()” pour générer


consécutivement plusieurs figures, comme dans l'exemple de départ. Les commandes
plot(), xlabel(), … s'appliquent par défaut à la dernière figure créée.

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")

Expressions LaTeX dans les figures

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()

Après introduction de la fonction il devrait ressembler à (on ajoutera les légendes et


autres éléments utiles) :
def solution(n):
[ exécution des calculs pour n passé en paramètre ]
return x,t

x1,t1=solution(4)
x2,t2=solution(100)
plt.plot(x1,t1)
plt.plot(x2,t2)
plt.show()

Appliquez cette logique pour diverses valeurs de n. Utilisez l'outil « zoom » de la


fenêtre graphique pour distinguer les solutions pour n>>100.

Vous aimerez peut-être aussi