Table des matières PDFPython

Package DYNODE pour Python

1. Introduction

DYNODE est un Package d'interface avec des solveurs d'équations différentielles ordinaires. Il comporte des équations prédéfinies de systèmes dynamiques physiques. Il permet également de définir les équations différentielles par une fonction Python.

Les intersections des trajectoires avec des surfaces de l'espace des phases peuvent être obtenues pendant l'intégration, ce qui permet d'obtenir les sections de Poincaré.

DYNODE comporte 3 modules :

2. Compilation

La compilation nécessite les bibliothèques suivantes :

La bibliothèque pthread est toujours présente sous Linux (threads POSIX)

3. Installation

4. Interface pour le solveur CVODE

4.a. Description

CVODE est un solveur d'équations différentielles ordinaires faisant partie de la bibliothèque SUNDIALS. Il utilise une méthode à pas multiples à ordre variable explicite (Adams) ou implicite (BDF).

L'interface est fournie par la classe CVOde définie dans le module dynode.main.

Remarque : il est possibles de créer plusieurs instances de CVOde pour effectuer des calculs en parallèle (maximum 100) sur les processeurs multicœurs.

Remarque : cette fonction permet de lancer des calculs pour plusieurs instances de CVOde en parallèle. Ceci permet de maximiser l'utilisation des processeurs multicœurs.

5. Module graphique 3D

5.a. Description

Le module graphique plot est accessible par différentes classes définies dans dynode.main.

La classe Plot (une seule instance) contrôle l'ouverture du module et le lancement de la boucle de rendu.

La classe Figure permet de définir une figure, c'est-à-dire une fenêtre graphique. Les figures apparaissent lorsque la fonction Plot.show est appelée. Le nombre de figures est illimitée.

Les fonctions suivantes de type set_xxx doivent être appelées avant le lancement de la boucle de rendu.

Les 3 fonctions suivantes permettent d'obtenir une copie de la figure sous forme d'une image pixmap générée lorsque l'utilisateur appuie sur la touche s. Une seule image peut être générée par figure. Si l'utilisateur n'utilise pas la touche s, l'image est générée à partir du dernier état de la figure (lorsque l'utilisateur appuie sur la touche q). Ces fonctions doivent être appelées après la fermeture de la boucle de rendu, i.e. après l'appel de Plot.wait.

img=Figure.get_image()

Fournit une instance de la classe Image du module PIL (si celui-ci est installé).

  • img (Image)  :  instance de la classe Image.

L'image peut être ensuite enregistrée sous forme PNG par :

img.save("figure.png","PNG")

Les classes suivantes permettent de créer des objets graphiques dans une figure. Les instances doivent être créées avant l'exécution de Plot.show().

La classe Grid représente une grille de repérage, perpendiculaire à un des axes X,Y, ou Z.

La classe Plot3d permet de tracer des points dans l'espace, éventuellement reliés par des traits pour former une courbe.

La classe Plot2d génère des points dans le plan z=0.

Les classes suivantes génèrent des objets graphiques qui peuvent être déplacés (pour animation) pendant la boucle de rendu.

5.b. Exemple

On reprend les données calculées plus haut (système de Lorenz) pour tracer la trajectoire dans l'espace X,Y,Z et la section de Poincaré z=27.

plot=dyn.Plot()
fig1=dyn.Figure()
fig1.set_camera(300)
fig2=dyn.Figure()
a=50.0
b=40.0
fig1.viewbox(-a,a,-a,a,-a,a)
fig2.viewbox(-a,a,-a,a,-a,a)
g1=dyn.Grid(fig1,-b,b,10,-b,b,10,0,ticks=1,rgb=[1.0,0.5,1.0])
p1=dyn.Plot3d(fig1,data1[1],data1[2],data1[3],style=dyn.PlotStyleLines,rgb=[0,0,1.0],width=1.0)
g2=dyn.Grid(fig2,-b,b,10,-b,b,10,0,ticks=1,rgb=[1.0,0.5,1.0])
p1=dyn.Plot3d(fig2,data2[1],data2[2],data2[3],style=dyn.PlotStylePoints,rgb=[0,0,1.0],width=2.0)
plot.show()
plot.wait()
path="../../../../figures/numerique/dynode/pydynode/"
img=fig1.get_image()
img.save(path+"plot3.png","PNG")
img=fig2.get_image()
img.save(path+"plot4.png","PNG")
plot.close()
                
Trajectoire Section Z=27

6. Solveur de systèmes hamiltoniens

6.a. Description

Le module verlet est un solveur symplectique pour systèmes hamiltoniens utilisant la méthode de Stormer-verlet. Il traite les systèmes à hamiltoniens séparables, éventuellement dépendant du temps. Un champ magnétique (ou une force de Coriolis) peut être ajouté (système hamiltonien à champ magnétique).

Les sytèmes physiques concernés sont ceux dont les forces internes ne dépendent que des coordonnées, avec un champ extérieur dépendant éventuellement du temps.

L'interface avec le solveur est fournie par la classe Verlet, définie dans le module dynode.main.

Remarque : il est possibles de créer plusieurs instances de la classe Verlet pour effectuer des calculs en parallèle (maximum 100) sur les processeurs multicœurs.

Remarque : cette fonction permet de lancer des calculs pour plusieurs instances de Verlet en parallèle. Ceci permet de maximiser l'utilisation des processeurs multicœurs.

Voici un exemple de système défini par des fonctions : une particule (3 coordonnées cartésiennes) est soumise à une force centrale élastique.

def dKinetic(t,p):
    dq = p
    return dq
  
def dPotential(t,q):
    dp = [0,0,0]
    dp[0] = q[0]
    dp[1] = q[1]
    dp[2] = q[2]
    return dp

def energy(t,q,p):
    return 0.5*(p[0]*p[0]+p[1]*p[1]+p[2]*p[2])+0.5*(q[0]*q[0]+q[1]*q[1]+q[2]*q[2]);
                

Lorsque le champ est uniforme, il doit être colinéaire à l'axe z. Voici par exemple une fonction définissant un champ magnétique uniforme :

def bfield(t,x):
    return [0,0,-1]
                
def rootfn(t,q,p):
    return [q[0],q[2]]
                

6.b. Exemple

L'exemple reprend les fonctions définies ci-dessus pour définir le système (oscillateur dans un champ magnétique uniforme).

import dynode.main as dyn
solver=dyn.Verlet(0)
solver.set_eqn(3,dKinetic,dPotential,energy)
solver.set_bfield(dyn.BFieldUniform,bfield)
solver.set_rootfn(2,rootfn)
solver.init(0.0,[1.0,0.0,0.0],[0.0,1.0,1],0.01)
data=solver.solve(0.1,100)
t=data[0]
x=data[1]
y=data[2]
z=data[3]
e=data[7]
                

Recherche des racines sur une durée plus longue :

solver.root_find(1,0,1e-3)
data=solver.solve(1.0,1000)
roots1=solver.get_roots(0)
roots2=solver.get_roots(1)
solver.close()
                

Tracé de la trajectoire et des racines :

plot=dyn.Plot()
fig1=dyn.Figure()
fig1.set_camera(10)
fig1.viewbox(-2.0,2.0,-2.0,2.0,-2.0,2.0)
g1=dyn.Grid(fig1,-1.0,1.0,10,-1.0,1.0,10,0,ticks=1)
p1=dyn.Plot3d(fig1,x,y,z,style=dyn.PlotStyleLines)
fig2=dyn.Figure()
fig2.set_camera(10)
fig2.viewbox(-2.0,2.0,-2.0,2.0,-2.0,2.0)
g2=dyn.Grid(fig2,-1.0,1.0,10,-1.0,1.0,10,0,ticks=1)
p2=dyn.Plot3d(fig2,roots1[1],roots1[2],roots1[3],style=dyn.PlotStylePoints,width=2.0)
p3=dyn.Plot3d(fig2,roots2[1],roots2[2],roots2[3],style=dyn.PlotStylePoints,width=2.0)
plot.show()
plot.wait()
path="../../../../figures/numerique/dynode/pydynode/"
img=fig1.get_image()
img.save(path+"plot5.png","PNG")
img=fig2.get_image()
img.save(path+"plot6.png","PNG")
plot.close()
                
Trajectoire Racines
Creative Commons LicenseTextes et figures sont mis à disposition sous contrat Creative Commons.