IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

FAQ Fortran

FAQ FortranConsultez toutes les FAQ

Nombre d'auteurs : 1, nombre de questions : 70, dernière mise à jour : 23 juillet 2021 

 
OuvrirSommaireLe programme principal et les sous programmes

Les function et les subroutine sont littéralement traduits de l'anglais par fonction et sous-programme. Ce sont les deux types de sous programmes disponibles en Fortran.

Les différences majeures entre une fonction et une subroutine sont :
  • Une function est également une variable qui contient le résultat de la fonction alors que le ou les résultats d'une subroutine sont en paramètres. Il s'ensuit qu'une fonction doit être déclarée.
  • Pour appeler une subroutine on utilise la commande call alors qu'une function n'en a pas besoin.
  • Une function doit forcément renvoyer un résultat stocké dans une variable (qui peut être un tableau). Une subroutine peut ne renvoyer aucun résultat et juste réaliser une action (écrire dans un fichier, nettoyer l'écran ...).

Les fonctions

Voyons un exemple simple d'une fonction et de son appel. Une fonction est, par exemple, de la forme f(x) = a*x + b. Voici un programme qui utilise cette fonction :

Un exemple de fonction
Sélectionnez
 PROGRAM test_function
 ! programme principal
 implicit none
 integer::i
 real::f,a,b,x,y

 a = 1.d0
 b = 2.d0

 x=0.d0
 Do i=1,100
    x = x + 0.1d0
    write(*,*)x,f(a,b,x)  ! appel de la fonction
 Enddo

 ! autre exemple
 x=0.d0
 Do i=1,100
    x = x + 0.1d0
    y = f(a,b,x)          ! appel de la fonction 
    write(*,*)x,y 
 Enddo

 END PROGRAM test_function

! * * * * * * * * * * * *

 FUNCTION f(a,b,x)
 implicit none
 real,intent(in)::a,b,x
 real::f     ! dans une fonction son nom est déclaré

 f = a*x + b ! quelque part dans une fonction on doit assigner une valeur à f

 END FUNCTION f

Les subroutines

Pour continuer l'exemple précédent, on peut programmer une sous-routine qui va lire les paramètres a et b de la fonction f(a,b,x).

Un Exemple de subroutine
Sélectionnez
 PROGRAM test_function
 ! programme principal
 ! la subroutine n'est pas déclarée
 implicit none
 integer::i
 real::a,b,f,x
 
 call lec(a,b)   ! on utilise call pour appeler une subroutine
 
 x = 0.d0
 Do i=1,100
    x = x + 0.1d0
    write(*,*)x,f(a,b,x)
 Enddo
 
 END PROGRAM test_function
 
! * * * * * * * * * * * * * *
 
 SUBROUTINE lec(a,b)
 implicit none
 real,intent(out)::a,b   ! on précise que a et b sont des argument de sortie
 
 write(*,*)"entrer a et b"
 read(*,*)a,b
 write(*,*)"a = ",a
 write(*,*)"b = ",b
 
 END SUBROUTINE lec
 
! * * * * * * * * * * * * * *

 FUNCTION f(a,b,x)
 implicit none
 real,intent(in)::a,b,x
 real::f     ! dans une fonction son nom est déclaré
 
 f = a*x + b ! quelque part dans une fonction on doit assigner une valeur à f
 
 END FUNCTION f
Les argument d'une subroutine peuvent être de plusieurs types
  • argument sortant : integer,intent(out)::p1
  • argument entrant : integer,intent(in)::p2
  • argument entrant/sortant : integer,intent(inout)::p3

Les arguments entrants ne peuvent pas être modifiés dans la subroutine. Une subroutine doit assigner une valeur à un argument sortant.

Créé le 22 octobre 2008  par Germain Salvato-Vallverdu

Quand on travaille dans un terminal il arrive souvant qu'on rajoute à la suite d'un programme des paramètres. par exemple : mon_programme.x p1 p2 p3. Pour récupérer p1, p2 et p3 on utilise la subroutine getarg.

Utilisation de la subroutine getarg
Sélectionnez
call getarg( entier , chaîne de caractère)

L'entier correspond à la place de l'argument. Par exemple, dans notre cas, 1 correspond à p1, 2 à p2 et 3 à p3. La valeur 0 permet de récupérer le nom du programme. Ceci peut être mis à profit pour si l'exécutable est enregistré sous des noms différents afin d'avoir une exécution différente selon le nom du programme. Les paramètres p1, p2 ou p3 sont enregistrés dans une variable de type chaîne de caractères. Voici un exemple d'utilisation :

Exemple d'utilisation de getarg
Sélectionnez
 PROGRAM test_getarg
 implicit none
 integer::i,p1,p2,p3
 integer,dimension(3)::p
 character(len=10)::parm,nom

 ! on récupère le nom du programme
 call getarg(0,nom)

 ! on récupère les valeurs des paramètres
 call getarg(1,parm)
 read(parm,*)p1

 call getarg(2,parm)
 read(parm,*)p2

 call getarg(3,parm)
 read(parm,*)p3

 ! on peut faire une boucle
 Do i=1,3
    call getarg(i,parm)
    read(parm,*)p(i)
 Enddo

 END PROGRAM test_getarg
Créé le 22 octobre 2008  par Germain Salvato-Vallverdu

Une variable est une zone mémoire à laquelle on associe un nom pour pouvoir écire ou lire ce qu'elle contient. Lorsqu'on utilise des sous programmes il faut savoir si les variables qu'on utilise sont accessibles par tous les sous programmes (variables globales) ou juste dans le programme ou sous programme dans lequel elles sont déclarées.

En Fortran toutes les variables déclarées au début d'un programme principal, d'une fonction ou d'une subroutine sont des variables locales. Ainsi si l'on déclare un entier i dans 3 sous programme, ces 3 variables i seront associées à 3 zones mémoires différentes et indépendantes.

Pour utiliser des variables globales, communes à plusieurs sous programmes, on utilise les common (FORTRAN77) ou des module (Fortran90).

Créé le 22 octobre 2008  par Germain Salvato-Vallverdu

La méthode la plus simple pour qu'une subroutine et son programme appelant se passent des variables est de les mettre comme arguments de la subroutine. Il faut ensuite préciser s'ils sont entrant (ils viennent du programme appelant et ne doivent pas être modifié), sortant (ils viennent de la subroutine vers le programme appelant et doivent être assignés) ou les deux.

Exemple d'arguments
Sélectionnez
 PROGRAM test_arg
 implicit none
 integer::a,b,c

 a = 2
 c = 1

 call sub(a,b,c)

 END PROGRAM test_arg

! * * * * * * * 

 SUBROUTINE sub(a,b,c)
 ! il n'est pas nécessaire que les arguments aient le même nom, seule la position est importante
 ! mais ça facilite la lecture du programme
 implicit none
 integer,intent(in)::a       ! a n'est pas modifiable
 integer,intent(out)::b      ! b doit être assigné
 integer,intent(inout)::c    ! c peut être modifié

 b = a + c

 c = c + 1

 END SUBROUTINE sub

Il n'est pas obligatoire de préciser l'intent, cela peut cependant éviter certaines erreurs et facilite la lecture du programme.

Créé le 22 octobre 2008  par Germain Salvato-Vallverdu

Le common permet de déclarer un zone mémoire commune dans laquelle seront enregistrées des variables. Elles seront accessibles par tous les sous programmes dans lesquels le common est déclaré. Reprenons l'exemple utilisé par les arguments pour comparer.

Utilisation d'un common pour transferer des variables
Sélectionnez
! * * * *
! syntaxe d'un common
 common /nom de la zone commune/ liste des variables
! * * * * 

 PROGRAM test_arg
 implicit none
 integer::a,b,c
 common /arg/ a,b,c  ! je déclare le common

 a = 2
 c = 1

 call sub

 END PROGRAM test_arg

! * * * * * * * 

 SUBROUTINE sub
 implicit none
 integer::a,b,c
 common /arg/ a,b,c ! j'utilise le common 

 b = a + c

 c = c + 1

 END SUBROUTINE sub

Il n'est plus nécessaire de donner les variables a,b et c en argument de la subroutine sub car elles sont accessibles par l'intermédiaire du common.

Dans ce cas les variables de la zone commune sont toutes modifiables par la subroutine, pour préciser un intent il faut utiliser les paramètres.

Pour ne pas avoir à reécrire dans chaque sous programme le common, il était courant d'inclure un fichier qui contenait les variables du common. Ceci avait également l'avantage de ne pas avoir à modifier tous les common dans tous les sous programmes à chaque modification. Voici un exemple :

Utilisation de include
Sélectionnez
 PROGRAM test_arg
 implicit none
 include "arg"

 a = 2
 c = 1

 call sub

 END PROGRAM test_arg

! * * * * * * * 

 SUBROUTINE sub
 implicit none
 include "arg"

 b = a + c

 c = c + 1

 END SUBROUTINE sub

! * * * * * * * * * * * * * * * 
!contenu du fichier arg
 integer::a,b,c
 common /arg/ a,b,c
Créé le 22 octobre 2008  par Germain Salvato-Vallverdu

Les modules sont la grande nouveauté du Fortran 90 et apporte au Fortran un soupçon de programmation orientée objet. L'utilisation des modules pour partager des variables entre des sous programmes n'est qu'une infime partie de ce qu'ils apportent. Dans ce cas, leur utilisation est similaire à celle du common. On va créer un module, dans lequel seront déclarées des variables qui seront disponibles dans tous les sous programmes qui utilisent le module.

Utilisation d'un common pour transferer des variables
Sélectionnez
 MODULE arg
 implicit none
 integer::a,b,c
 END MODULE arg

! * * * * * * * 

 PROGRAM test_arg
 USE arg
 implicit none

 a = 2
 c = 1

 call sub

 END PROGRAM test_arg

! * * * * * * * 

 SUBROUTINE sub
 USE arg
 implicit none

 b = a + c

 c = c + 1

 END SUBROUTINE sub

L'utilisation d'un module apporte cependant une contrainte. Ils doivent être compilés avant le programme principal. Plusieurs solutions sont possibles :

  • Lors de la compilation placer le nom du module en premier, par exemple : ifort module.f90 program.f90
  • Si le programme est court et que tous les sous programmes et modules sont dans un même fichier, placer les modules en premier, en tête du fichier dans l'ordre qu'ils apparaissent. Puis compiler simplement le fichier comme un programme normal.
  • Compilez à l'avance vos modules (s'arréter à la compilation, création de l'objet). Puis lors de la compilation du programme ajouter les .o des modules.

Pour les compilateurs ifort, g95 ou gFortran, la compilation (création de l'objet) se fait en ajoutant l'option -c.

Il est possible de n'utiliser qu'une partie d'un module avec l'instruction only. On va ainsi sélectionner les variables qui seront accessibles et celles qui ne le seront pas. Voici un exemple :

Utilisation de only
Sélectionnez
 MODULE arg
 implicit none
 integer::a,b,c
 double precision::x
 END MODULE arg

! * * * * * * * 

 PROGRAM test_arg
 USE arg, only : a,c      ! seuls a et c sont utiles
 implicit none

 a = 2
 c = 1

 call sub

 END PROGRAM test_arg

! * * * * * * * 

 SUBROUTINE sub
 USE arg, only : a,b,c    ! seuls a b et c sont utiles
 implicit none

 b = a + c

 c = c + 1

 END SUBROUTINE sub
Créé le 22 octobre 2008  par Germain Salvato-Vallverdu

Copyright © 2008 developpez Developpez LLC. Tous droits réservés Developpez LLC. Aucune reproduction, même partielle, ne peut être faite de ce site ni de l'ensemble de son contenu : textes, documents et images sans l'autorisation expresse de Developpez LLC. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.