Interfac¸age de Python avec Fortran
Eric Sonnendr ¨ucker
IRMA
Universit ´e Louis Pasteur, Strasbourg
projet CALVI INRIA Lorraine
Journ ´ee Python et Calcul Scientifique, IHP, Paris, 14 d ´ecembre 2006
Pourquoi interfacer Python avec Fortran ?
Python a un certain nombre d’avantages :
Langage interpr ´et ´e Facile `a programmer
Dispose de modules de calcul num ´erique, de visualisation ...
Il est n ´eanmoins trop lent pour un des t ˆaches num ´eriques intensives.
Solution :interfacer avec C ou Fortran
Allie le meilleur des deux mondes.
T ˆaches de pr ´e- et post-traitement en Python. Parties num ´eriques intensives en Fortran (ou C)
Quels outils pour l’interfac¸age Python-Fortran ?
Trois g ´en ´erateurs d’interface sont disponibles.
N ´ecessitent tous d’avoir install ´e le module Numeric
Pyfort, le plus ancien, uniquement Fortran 77 permet aussi
de traiter des fonctions de C structur ´ees comme F77. D ´evelopp ´e parPaul Dubois.
http://sourceforge.net/projects/pyfortran
f2py, Fortran 95 (et C), mais ne permet pas d’interfacer les
types d ´eriv ´es F90. D ´evelopp ´e parPearu Peterson. Bien document ´e.
http://cens.ioc.ee/projects/f2py2e/
Forthon, Fortran 95, y compris interfac¸age des types
d ´eriv ´es. D ´evelopp ´e par Dave Grote. Pas de
documentation autre que des exemples livr ´es avec le code. http://hifweb.lbl.gov/Forthon/
Utilisation de f2py
N ´ecessite l’installation de Numeric (Numpy), scipy distutils (qui g `ere la compilation et les compilateurs fortran)
Trois m ´ethodes sont propos ´ees :
1 Interfacer des subroutines simples sans ´ecrire de code
suppl ´ementaire.
2 Ajouter des directives pour f2py dans le source Fortran
pour un interfac¸age plus complexe.
3 Ecrire un fichier d’interface d ´ecrivant les subroutines et les
donn ´ees `a interfacer. f2py peut g ´en ´erer automatiquement un fichier d’interface simple qu’on peut ensuite ´editer.
De premi `eres interfaces
Le code Fortran subroutine norme ( a , b ) ! C a l c u l e l a norme r e a l ( 8 ) : : a , b r e a l ( 8 ) : : c c= s q r t ( a∗a+b∗b ) p r i n t ∗ , ” l a norme de ( ” , a , ” , ” , b , ” ) e s t ” , c end subroutine normeG ´en ´eration de l’interface python avec f2py dans le shell f2py -c norme.f90 -m vect
Dans Python
>>> import vect >>> vect.norme(3,4)
Ajouter des variables de sortie
Le code Fortran subroutine norme ( a , b , c ) ! C a l c u l e l a norme r e a l ( 8 ) , i n t e n t ( i n ) : : a , b r e a l ( 8 ) , i n t e n t ( out ) : : c c= s q r t ( a∗a+b∗b )end subroutine norme
G ´en ´eration de l’interface python avec f2py dans le shell f2py -c norme.f90 -m vect
Dans Python >>> import vect >>> vect.norme(3,4) 5.0 >>> c=vect.norme(3,4) >>> c 5.0
Documentation des fonctions interfac ´ees
Documentation g ´en ´er ´ee automatiquement par f2py
>>> print norme. doc
norme - Function signature : c = norme(a,b) Required arguments : a : input float b : input float Return objects : c : float
Ajouter des directives f2py dans le source Fortran
subroutine norme ( a , c , n ) i n t e g e r : : n r e a l ( 8 ) , dimension ( n ) , i n t e n t ( i n ) : : a ! f 2 p y o p t i o n a l , depend ( a ) : : n= l e n ( a ) r e a l ( 8 ) , i n t e n t ( out ) : : c r e a l ( 8 ) : : sommec i n t e g e r : : i sommec = 0 do i =1 , n sommec=sommec+a ( i ) ∗ a ( i ) end do c= s q r t ( sommec ) end subroutine normeAppel
>>> from vect import * >>> a=[2,3,4]
>>> norme(a) 5.3851648071345037
>>> from Numeric import * >>> a=arange(2,5)
>>> norme(a) 5.3851648071345037 >>> print norme. doc
norme - Function signature : c = norme(a,[n])
Required arguments :
a : input rank-1 array(’d’) with bounds (n) Optional arguments :
n := len(a) input int Return objects : c : float
Les directives de compilation f2py
Syntaxe des d ´eclarations reprises de f90 avec quelques ajouts
Les d ´eclarations f90 servent donc aussi bien `a f90 qu’ `a f2py
Certaines directives sp ´ecifiques n ´ecessitent d’ ˆetre comment ´ees en f90 !f2py ...
Quelques exemples :
D ´eclaration de types : real, integer, character,.. Attributs f90 : dimension(2,3), intent(in),
intent(out), optional,..
Attributs sp ´ecifiques f2py : intent(hide) : argument cach ´e dans l’appel python, intent(c) : interfac¸age d’une fonction C,..
Utilisation d’un fichier signature
On peut g ´en ´erer automatiquement un fichier signature f2py vecteur.f90 -h vecteur.pyf
contenu de vecteur.pyf ! −∗− f 9 0 −∗− ! Note : t h e c o n t e x t o f t h i s f i l e i s case s e n s i t i v e . subroutine norme ( a , c , n ) ! i n v e c t e u r . f 9 0 r e a l ( kind =8) dimension ( n ) , i n t e n t ( i n ) : : a r e a l ( kind =8) i n t e n t ( out ) : : c
i n t e g e r optional , check ( len ( a)>=n ) , depend ( a ) : : n=len ( a ) end subroutine norme
! T h i s f i l e was auto−generated w i t h f 2 p y ( v e r s i o n : 2 . 4 5 . 2 4 1 \ 1926 ) . ! See h t t p : / / cens . i o c . ee / p r o j e c t s / f2py2e /
Appel de fonctions Python depuis Fortran
subroutine sommef ( f , n , s ) ! C a l c u l e somme ( f ( i ) , i =1 , n ) e x t e r n a l f i n t e g e r , i n t e n t ( i n ) : : n r e a l , i n t e n t ( out ) : : s s =0.0 do i =1 , n s=s+ f ( i ) end doend subroutine sommef
>>>from vect import * >>>def fonction(i) : return(i*i) >>>sommef(fonction,3) 14.0
>>>sommef(lambda x :x**3,3) 36.0
Interfac¸age avec C
Utilisation obligatoire d’un fichier signature (qui n’est en g ´en ´eral pas n ´ecessaire en Fortran o `u les directives f2py sont directement prises des d ´eclarations du Fortran o `u rajout ´ees dans le code source.
Le nom de la fonction doit ˆetre d ´eclar ´e avec intent(c) intent(c)doit ˆetre utilis ´e pour toutes les d ´eclarations de variables, mais peut ˆetre factoris ´e en le mettant sur une ligne seul avant les d ´eclarations de variables.
Commande :
Exemple : les fonctions `a interfacer
void d e p o s i t r h o ( double∗ rho , double∗ f o l d , i n t ∗ i n d x , double∗ depx , i n t ∗
i n d v ,double∗ depv , i n t nx , i n t nv ){ i n t i , j ; double dx , dv ; f o r ( i = 0 ; i < nx ; i ++) rho [ i ] = 0 ; f o r ( i = 0 ; i < nx ; i ++){ f o r ( j = 0 ; j < nv ; j ++){ dx = depx [ i +nx∗ j ] ; dv = depv [ i +nx∗ j ] ; rho [ i n d x [ i +nx∗ j ] ] += (1−dx )∗ f o l d [ i +nx∗ j ] ; rho [ ( i n d x [ i +nx∗ j ]+1)\% nx ] += dx ∗ f o l d [ i +nx∗ j ] ; }}}
void poisson1d\ a x i ( double ∗ ex , double ∗ rho , double xmin , double dx , i n t nx ){ i n t i ; double i n t e g r a l , x i ; i n t e g r a l = 0 ; ex [ nx / 2 ] = 0 ; x i = 0 ; f o r ( i =1+ nx / 2 ; i <nx ; i ++){ x i += dx ;
i n t e g r a l += dx ∗ ( ( x i−dx )∗ rho [ i −1]+ x i ∗rho [ i ] ) / 2 . ; ex [ i ] = i n t e g r a l / x i ;
ex [ nx−i −1] = −ex [ i ] ; }}
Exemple : le fichier signature
python module c f u n c t s i n t e r f a c e
s u b r o u t i n e d e p o s i t r h o ( rho , f o l d , i n d x , depx , i n d v , depv , nx , nv ) i n t e n t ( c ) : : d e p o s i t r h o
i n t e n t ( c )
i n t e g e r , i n t e n t ( i n ) : : nx , nv
r e a l ∗8 , dimension ( nx , nv ) , depend ( nx , nv ) , i n t e n t ( i n ) : : f o l d , depx , depv r e a l ∗8 , dimension ( nx ) , depend ( nx ) , i n t e n t ( o u t ) : : rho
i n t e g e r , dimension ( nx , nv ) , depend ( nx , nv ) , i n t e n t ( i n ) : : i n d x , i n d v end s u b r o u t i n e d e p o s i t r h o s u b r o u t i n e p o i s s o n 1 d a x i ( ex , rho , xmin , dx , nx ) i n t e n t ( c ) : : p o i s s o n 1 d a x i i n t e n t ( c ) i n t e g e r , i n t e n t ( i n ) : : nx r e a l ∗8 , i n t e n t ( i n ) : : xmin , dx r e a l ∗8 , dimension ( nx ) , depend ( nx ) , i n t e n t ( o u t ) : : ex r e a l ∗8 , dimension ( nx ) , depend ( nx ) , i n t e n t ( i n ) : : rho end s u b r o u t i n e p o i s s o n 1 d a x i
end i n t e r f a c e
Interfac¸age d’un module
module v e c t e u r i n t e g e r : : t a i l l e r e a l , a l l o c a t a b l e , dimension ( : ) : : zero , un contains subroutine norme ( a , c , n ) i n t e g e r , i n t e n t ( i n ) : : n ! f 2 p y i n t e n t ( h i d e ) : : n= l e n ( a ) r e a l ( 8 ) , dimension ( n ) , i n t e n t ( i n ) : : a r e a l ( 8 ) , i n t e n t ( out ) : : c r e a l ( 8 ) : : sommec i n t e g e r : : i sommec = 0 do i =1 , n sommec=sommec+a ( i )∗ a ( i ) end do c= s q r t ( sommec )end subroutine norme
subroutine p s c a l ( a , b , c , n ) ! p r o d u i t s c a l a i r e de deux v e c t e u r s i n t e g e r , i n t e n t ( i n ) : : n ! f 2 p y i n t e n t ( h i d e ) : : n= l e n ( a ) r e a l ( 8 ) , dimension ( n ) , i n t e n t ( i n ) : : a , b r e a l ( 8 ) , i n t e n t ( out ) : : c c =0.0 do i =1 , n c = c + a ( i )∗ b ( i ) end do end subroutine p s c a l end module v e c t e u r
Utilisation de Forthon
N ´ecessite l’ ´ecriture d’un fichier signature .v avec un syntaxe pr ´ecise que nous allons d ´ecouvrir `a travers quelques exemples.
Plus orient ´e f90 que les deux autres outils
Permet en particulier l’interfac¸age complet des modules et des types d ´eriv ´es.
Syntaxe
Forthon [options] pkgname [extra Fortran or C files to be compiled or objects to link]
N ´ecessite au moins 2 fichiers : pkgname.f90 (fortran),
pkgname.v(signature)
Exemple
Le code Fortran subroutine s e t s q r t ( y ) Use SimpleModule r e a l ( kind = 8 ) : : y x = s q r t ( y ) r e t u r n end Le fichier signature example ****** SimpleModule:i integer /3/ # Sample integer variable x real # Sample real variable
****** SimpleRoutines:
Quelques remarques sur le fichier signature
Un module ne contenant que des donn ´ees n’a pas besoin d’exister en Fortran. S’il est d ´efini dans la signature, il est cr ´e ´e automatiquement par Forthon
Syntaxe pour la d ´efinition des variables
nomtype [/valeur initiale/][#commentaire]
i integer /3/ # Sample integer variable x real # Sample real variable
Syntaxe pour la d ´efinition des subroutines
nom(arguments :type arg) subroutine [#commentaire]