Procédures : subroutines et fonctions
Subroutines et fonctions
Procédure : subroutine ou function
SUBROUTINE identificateur(arguments)
déclarations arguments et variables locales
instructions exécutables
END SUBROUTINE identificateur
PURE type FUNCTION identificateur(arguments)
déclarations arguments et variables locales
instructions exécutables
END FUNCTION identificateur
Exemples :
SUBROUTINE PLOUF(A, B)
déclarations arguments a et b
déclarations variables locales
instructions exécutables
END SUBROUTINE PLOUF
PURE REAL FUNCTION F(X)
déclaration argument x
déclarations variables locales
instructions exécutables
END FUNCTION F
Les trois modes de communication d'un argument
Donnée de la procédure :
- attribut
intent(in)
- non modifiable
- obligatoire pour chaque argument d'une fonction pure
Résultat de la procédure :
- attribut
intent(out)
- valeur initiale indéterminée
Donnée-résultat :
- attribut
intent(inout)
- la valeur initiale vient de l'argument effectif
- modifiable
Exemple :
pure real function foeew(t)
real, intent(in):: t
real, parameter:: r3les = 17.269
real, parameter:: r4les = 35.86
real, parameter:: rtt = 273.16
!-----------------
foeew = exp(r3les \* (t - rtt) / (t - r4les))
end function foeew
Correspondance arguments effectif et muet
Le type d'un argument effectif doit être le même que celui de l’argument muet correspondant.
Variables locales
- Ce sont les variables déclarées dans une procédure, autres que les arguments.
- Elles sont inaccessibles à l'extérieur de la procédure.
- La valeur d'une variable locale est perdue d'un appel de la procédure à l'appel suivant. Une variable locale est donc non définie au début de chaque exécution de la procédure.
Appel d'une procédure
- Pour une subroutine :
CALL identificateur(arguments effectifs)
- Pour une fonction :
identificateur(arguments effectifs)
apparaît à l'intérieur d'une expression. Exemple :
print *, foeew(273.) * 100.
Modules
- Placer chaque procédure dans un "module".
- Choisir un nom pour le module (forcément différent du nom de la procédure).
Exemple :
module plouf_m
implicit none
contains
subroutine plouf(…)
…
end subroutine plouf
end module plouf_m
Déclarer implicit none
au niveau du module plutôt que dans la procédure.
Utilisation d'une procédure de module : déclaration use
.
USE nom de module, ONLY: nom de procédure
use
avant les autres déclarations.
Argument tableau
- Dans la procédure, seul le rang de l'argument muet tableau est
déclaré. Un caractère
:
par dimension. Le profil est imposé par l'argument effectif.
subroutine foo(a)
real, intent(…):: a(:, :, :)
- À l'appel : correspondance obligatoire du rang entre arguments effectif et muet.
- Rappel : correspondance obligatoire du type entre arguments effectif et muet (pour les arguments tableaux comme pour les arguments scalaires).
- Possibilité dans la procédure de connaître la taille dans chaque
dimension de l'argument avec la fonction
size
. Exemples :
real, intent(…):: x(:)
size(x)
real, intent(…):: a(:, :)
size(a, 1)
et size(a, 2)
Exemple d'utilisation de size
: fonction calculant le déterminant
d'une matrice.
real, intent(in):: a(:, :)
if (size(a, 1) /= size(a, 2)) then
print *, "erreur"
stop 1
end if
- Et si le profil du tableau est « logiquement connu » à l’écriture de
la procédure ? Si le profil est contraint par la signification du
tableau, déclarer quand même seulement le rang avec les caractères
:
et, éventuellement, programmer la contrainte en utilisant les fonctionssize
oushape
.
Exemple : argument tableau contenant une valeur mensuelle pour chaque mois de l'année.
integer, intent(…): ave_temper(:) ! (12)
! moyenne mensuelle de température
Éventuellement :
if (size(ave_temper) /= 12) then
print *, "erreur"
stop 1
end if
Argument tableau de taille inconnue à l'appel
- Comment programmer une procédure qui a en argument un tableau dont la taille est déterminée à l'intérieur de la procédure elle-même ?
- Exemple : une procédure qui lit dans un fichier un tableau de taille quelconque et renvoie ce tableau en argument.
- Attribut
allocatable
pour l’’argument muet (et toujours un caractère “ : ” par dimension). Exemple :
real, allocatable, intent(…):: a(:,:)
- L’argument effectif correspondant doit aussi avoir l’attribut
allocatable
. - Si l’argument muet a l’attribut
intent(out)
alors il est dans l’état « non alloué » au début de la procédure.
Argument optionnel
Attribut optional
dans la déclaration de l'argument muet. Dans la
procédure, on test si l'argument a été fourni avec la fonction
intrinsèque present
. Exemple :
pure real function spline(x, y, yp1, ypn)
! interpolation par spline cubique
real, intent(in):: x(:), y(:)
real, intent(in), optional:: yp1, ypn
! yp1 et ypn : dérivées aux bords
! Si une dérivée au bord est absente :
! dérivée seconde nulle
…
if (present(yp1)) then
…
end function spline
Appel d'une procédure avec argument optionnel :
- Rappel : nous avons vu jusqu'à maintenant la correspondance par position entre argument effectif et argument muet. Exemple :
print *, spline(u, v, 4, 8)
- Autre possibilité : la correspondance par “mot-clef” entre argument effectif et argument muet. Elle permet de sauter un argument effectif optionnel. Le mot-clef est le nom de l'argument muet. Exemple :
print *, spline(u, v, ypn=8)
Argument procédure
Un argument d'une procédure peut être lui-même une procédure.
Exemple : fonction cherchant le zéro d'une fonction quelconque.
function rtsafe(funcd, x1, x2, xacc)
Le résultat rtsafe
est la valeur de x qui annule funcd
.
Déclarer l'interface de l'argument muet procédure : ses propres
arguments, les propriétés du résultat si c'est une fonction. Entre
interface
et end interface
. Exemple :
function rtsafe(funcd, x1, x2, xacc)
interface
real function funcd(x)
real, intent(in):: x
end function funcd
end interface
real, intent(in):: x1, x2, xacc
real rtsafe
…