Vous êtes sur la page 1sur 50

Programmation

pour le calcul scientifique

UE 2A005 – 2nd semestre 2018-19


Sorbonne Université

Responsable :
Ivan Delbende
Ivan.Delbende@sorbonne-universite.fr

Fin cours 5 : Fonctions (1/2)


Fonctions intrinsèques
concernant les tableaux (4)
Type de la Nom de la fonction La fonction retourne : Type de
fonction l'argument
INTEGER SIZE (tab, dim) l'étendue du tableau tab <any_type>,
suivant la dimension dim DIMENSION
LBOUND (tab, dim) le premier indice de tab (…) :: tab
suivant la dimension dim
UBOUND (tab, dim) le dernier indice de tab INTEGER ::
suivant la dimension dim dim
LOGICAL ALLOCATED (tab) .TRUE. si le tableau tab est <any type>,
déjà alloué DIMENSION
(…) :: tab
INTEGER, SHAPE (tab) le vecteur profil du tableau LOGICAL,
DIMENSION(:)
tab DIMENSION
(…) :: tab

➢ SIZE (tab, 1) retourne le nombre de lignes de tab,


➢ SIZE (tab, 2) retourne le nombre de colonnes de tab, etc.
➢ ATTENTION ! SIZE (tab) avec un seul argument tableau
2
retourne la taille totale de tab (le nombre total d'éléments)
La fonction intrinsèque
DOT_PRODUCT (vec1, vec2)
Elle retourne le produit scalaire de deux
vecteurs vec1 et vec2 conformants :
➢ Si vec1 et vec2 sont des vecteurs d'entiers ou de réels,
l'expression est équivalente à SUM ( vec1 * vec2 )
➢ Si vec1 et vec2 sont des vecteurs complexes, elle est
équivalente à SUM ( CONJG (vec1) * vec2 )
➢ Si vec1 et vec2 sont des vecteurs de booléens, elle est
équivalente à ANY (vec1 .AND. vec2)
REAL, DIMENSION (3) :: vec1 = (/ 1., -0.5, 2. /), vec2 = (/ 2., 2., -0.5 /)
PRINT *, 'Produit scalaire = ', DOT_PRODUCT (vec1, vec2)
IF (ABS(DOT_PRODUCT (vec1, vec2)) < 1.E-7) THEN
PRINT *, 'Les vecteurs sont orthogonaux !'
END IF

norme2 = SQRT ( DOT_PRODUCT (vec, vec) )


! fonctionne pour des vecteurs réels mais aussi complexes 3
La fonction intrinsèque
MATMUL (mat1, mat2)
Elle retourne le produit matriciel de deux
matrices mat1 et mat2
➢ Le nombre de colonnes de mat1 doit être égal au
nombre de lignes de mat2, etc...
INTEGER, PARAMETER :: n1 = 10, n2 = 5, n3 = 8
REAL, DIMENSION (n1, n2) :: mat1
REAL, DIMENSION (n2, n3) :: mat2
REAL, DIMENSION (n1, n3) :: mat3
DO i = 1, n1 mat3 = MATMUL (mat1, mat2)
DO j = 1, n3
mat3 (i, j) = 0.
DO k = 1, n2
mat3 (i, j) = mat3 (i, j) + mat1 (i, k) * mat2 (k, j)
END DO
END DO
4
END DO
NE PAS CONFONDRE
PRODUIT MATRICIEL
A = MATMUL (B, C)
où l'on a des contraintes sur
les profils de A, B et C
et
PRODUIT ELEMENT
PAR ELEMENT A = B * C
où A, B et C sont conformants 5
Fonctions intrinsèques
concernant les tableaux (5)
Type de la Nom de la fonction La fonction Type de l'argument
fonction retourne :
REAL DOT_PRODUCT le produit scalaire REAL or COMPLEX,
(vec1, vec2) ou hermitien de DIMENSION(:) :: vec1,
vec1 et vec2 vec2

<any_type>, MATMUL (tab1, le produit matriciel <any_type>,


DIMENSION tab2) de tab1 et tab2 DIMENSION (:,:)
(:,:) or (:) or (:) :: tab1, tab2
avec condition de
compatibilité des
dimensions

6
Fonctions intrinsèques
concernant les tableaux (6)
Type de la Nom de la fonction La fonction retourne : Type de
fonction l'argument
INTEGER, MAXLOC (tab) la position relative de la INTEGER or
DIMENSION plus grande valeur du REAL,
(rang_tab) tableau tab DIMENSION
MINLOC (tab) la position relative de la (…) :: tab
plus petite valeur du
tableau tab

<any_type>, TRANSPOSE (tab) la transposée de la <any_type>,


DIMENSION matrice contenue dans le DIMENSION
( :, :) tableau tab de rang 2 ( :, :) :: tab

<any_type>, RESHAPE (vec, Un tableau de profil prof <any_type>,


DIMENSION prof) formé des éléments du DIMENSION
(…) vecteur vec (:) :: vec
INTEGER,
DIMENSION
(:) :: prof
7
Programmation
pour le calcul scientifique

UE 2A005 – 2nd semestre 2018-19


Sorbonne Université

Responsable :
Ivan Delbende
Ivan.Delbende@sorbonne-universite.fr

Cours 6a : Fonctions (2/2)


Fonctions définies par
le programmeur

● Recette pour créer ses propres fonctions :


➢ choisir un nom (original de préférence)
➢ déteminer le type du résultat renvoyé par la
fonction
➢ déterminer les arguments que la fonction va
utiliser pour calculer ce résultat

● Exemple : on souhaite écrire une fonction qui


renvoie l'ordre de grandeur d'un réel x.
➢ Nom : ordre_grandeur (par exemple)
➢ Résultat : type entier
➢ Argument : ici un seul, le réel x
9
Fonctions définies par
le programmeur (2)

INTEGER FUNCTION ordre_grandeur ( x )


REAL, INTENT ( IN ) :: x

ordre_grandeur = FLOOR ( LOG10 ( ABS(x) ) )


END FUNCTION ordre_grandeur

● Remarques
➢ Le résultat renvoyé par la fonction est contenu
dans une variable de même nom que la fonction
➢ Les arguments de la fonction sont appelés des
arguments muets (dummy). Ils doivent tous être
déclarés, ils ont un attribut supplémentaire :
INTENT (IN) … nous y reviendrons plus loin. 10
Fonctions définies par
le programmeur (3)
L'appel à la fonction INTEGER FUNCTION ordre_grandeur ( x )
REAL, INTENT ( IN ) :: x
ordre_grandeur = FLOOR ( LOG10 ( ABS(x) ) )
END FUNCTION ordre_grandeur

depuis le programme principal ou


depuis une autre procédure :

REAL :: x = 1.5E10, y = -2.3E-7


INTEGER :: odg

PRINT *, '' L'odg de 2*pi est '', ordre_grandeur ( 2*ACOS(-1.) )


PRINT *, '' L'odg de '', x, ''est '', ordre_grandeur ( x )
PRINT *, '' L'odg de '', y, ''est '', ordre_grandeur ( y )
odg = ordre_grandeur (x*y)
Important : l'argument muet x de la fonction et la
11
variable x du programme appelant sont indépendants
Fonctions définies par
le programmeur (3)
L'appel à la fonction INTEGER FUNCTION ordre_grandeur ( x )
REAL, INTENT ( IN ) :: x
ordre_grandeur = FLOOR ( LOG10 ( ABS(x) ) )
END FUNCTION ordre_grandeur

depuis le programme principal ou


depuis une autre procédure :

REAL :: x = 1.5E10, y = -2.3E-7


INTEGER :: odg

PRINT *, '' L'odg de 2*pi est '', ordre_grandeur ( 2*ACOS(-1.) )


PRINT *, '' L'odg de '', x, ''est '', ordre_grandeur ( x )
PRINT *, '' L'odg de '', y, ''est '', ordre_grandeur ( y )
odg = ordre_grandeur (x*y)
Important : l'argument muet x de la fonction et la
12
variable x du programme appelant sont indépendants
Fonctions définies par
le programmeur (3)
L'appel à la fonction INTEGER FUNCTION ordre_grandeur ( x )
REAL, INTENT ( IN ) :: x
ordre_grandeur = FLOOR ( LOG10 ( ABS(x) ) )
END FUNCTION ordre_grandeur

depuis le programme principal ou


depuis une autre procédure :

REAL :: x = 1.5E10, y = -2.3E-7 début de


INTEGER :: odg l'appel

PRINT *, '' L'odg de 2*pi est '', ordre_grandeur ( 2*ACOS(-1.) )


PRINT *, '' L'odg de '', x, ''est '', ordre_grandeur ( x )
PRINT *, '' L'odg de '', y, ''est '', ordre_grandeur ( y )
odg = ordre_grandeur (x*y)
Important : l'argument muet x de la fonction et la
13
variable x du programme appelant sont indépendants
Fonctions définies par
le programmeur (3)
L'appel à la fonction INTEGER FUNCTION ordre_grandeur ( x )
REAL, INTENT ( IN ) :: x
ordre_grandeur = FLOOR ( LOG10 ( ABS(x) ) )
END FUNCTION ordre_grandeur

depuis le programme principal ou


depuis une autre procédure :

REAL :: x = 1.5E10, y = -2.3E-7 début de


INTEGER :: odg l'appel

PRINT *, '' L'odg de 2*pi est '', ordre_grandeur ( 2*ACOS(-1.) )


PRINT *, '' L'odg de '', x, ''est '', ordre_grandeur ( x )
PRINT *, '' L'odg de '', y, ''est '', ordre_grandeur ( y )
odg = ordre_grandeur (x*y)
Important : l'argument muet x de la fonction et la
14
variable x du programme appelant sont indépendants
Fonctions définies par
le programmeur (3)
L'appel à la fonction INTEGER FUNCTION ordre_grandeur ( x )
REAL, INTENT ( IN ) :: x
ordre_grandeur = FLOOR ( LOG10 ( ABS(x) ) )
END FUNCTION ordre_grandeur

depuis le programme principal ou


depuis une autre procédure :

REAL :: x = 1.5E10, y = -2.3E-7 début de


INTEGER :: odg renvoi de fin l'appel

PRINT *, '' L'odg de 2*pi est '', ordre_grandeur ( 2*ACOS(-1.) )


PRINT *, '' L'odg de '', x, ''est '', ordre_grandeur ( x )
PRINT *, '' L'odg de '', y, ''est '', ordre_grandeur ( y )
odg = ordre_grandeur (x*y)
Important : l'argument muet x de la fonction et la
15
variable x du programme appelant sont indépendants
Fonctions définies par
le programmeur (3)
L'appel à la fonction INTEGER FUNCTION ordre_grandeur ( x )
REAL, INTENT ( IN ) :: x
ordre_grandeur = FLOOR ( LOG10 ( ABS(x) ) )
END FUNCTION ordre_grandeur

depuis le programme principal ou


depuis une autre procédure :

REAL :: x = 1.5E10, y = -2.3E-7 début de


INTEGER :: odg renvoi de fin l'appel

PRINT *, '' L'odg de 2*pi est '', ordre_grandeur ( 2*ACOS(-1.) )


PRINT *, '' L'odg de '', x, ''est '', ordre_grandeur ( x )
PRINT *, '' L'odg de '', y, ''est '', ordre_grandeur ( y )
odg = ordre_grandeur (x*y)
Important : l'argument muet x de la fonction et la
16
variable x du programme appelant sont indépendants
Fonctions définies par
le programmeur (4)
● Des variables autres que les arguments peuvent
être déclarées dans une procédure :
➢ ces variables sont « locales » à la procédure
➢ elles n'ont pas l'attribut INTENT.
● Exemple :
REAL FUNCTION lit_reel (x, y)
REAL, INTENT (IN) :: x, y ! arguments muets de la fonction
REAL :: r ! variable r locale à la fonction
DO
READ *, r
IF (r >= x .AND. r <= y) THEN ! Appel depuis le programme principal
lit_reel = r ; EXIT REAL :: my_real
END IF PRINT *, 'Entrez un réel entre 0 et 10'
END DO my_real = lit_reel (0., 10.)
END FUNCTION lit_reel
17
Fonctions définies par
le programmeur (5)

On sait maintenant
définir nos propres
fonctions…

… mais où doit-on le
faire ??
18
Le MODULE et la directive USE
MODULE lecture ! Module placé avant le programme appelant
IMPLICIT NONE

CONTAINS
REAL FUNCTION lit_reel (x, y)
REAL, INTENT (IN) :: x, y
PRINT *, ' Entrez un reel compris entre ', x, ' et ', y
DO
READ *, lit_reel
IF (lit_reel >= x .AND. lit_reel <= y) EXIT
PRINT *, ' Faites un nouvel essai ! '
END DO
END FUNCTION lit_reel
END MODULE lecture

PROGRAM exemple ! Programme appelant placé après le module


USE lecture ! USE : utilisation du module lecture
IMPLICIT NONE ! doit se faire avant IMPLICIT NONE
REAL, PARAMETER :: rmin = 0., rmax = 9.8
REAL :: r
r = lit_reel (rmin, rmax); PRINT *, ' r = ', r
END PROGRAM exemple 19
Le MODULE
● On place les fonctions dans un ou plusieurs modules
● Un module est une unité de compilation autonome
qui peut contenir
➢ des déclarations de variables, de types
➢ des définitions de procédures.
● Il est encadré par les instructions MODULE
nom_module et END MODULE nom_module
● En 2A005, il contiendra obligatoirement l'instruction
IMPLICIT NONE
● Les procédures sont placées en fin de module après
l'instruction CONTAINS
● Le programme appelant (principal) a une visibilité sur
le module grâce à la directive USE nom_module
20
Le MODULE et la directive USE
MODULE lecture ! Module placé avant le programme appelant
IMPLICIT NONE

CONTAINS
REAL FUNCTION lit_reel (x, y)
REAL, INTENT (IN) :: x, y
PRINT *, ' Entrez un reel compris entre ', x, ' et ', y
DO
READ *, lit_reel
IF (lit_reel >= x .AND. lit_reel <= y) EXIT
PRINT *, ' Faites un nouvel essai ! '
END DO
END FUNCTION lit_reel
END MODULE lecture

PROGRAM exemple ! Programme appelant placé après le module


USE lecture ! USE : utilisation du module lecture
IMPLICIT NONE ! doit se faire avant IMPLICIT NONE
REAL, PARAMETER :: rmin = 0., rmax = 9.8
REAL :: r
r = lit_reel (rmin, rmax); PRINT *, ' r = ', r
END PROGRAM exemple 21
Argument de type tableau (1)

● Le profil d'un tableau passé en argument est


transmis implicitement en Fortran 90
 tableau de profil implicite
● Lors de la déclaration des arguments muets de la
procédure, les dimensions du tableau ne sont pas
précisées (symbole « : » à la place), mais le rang
du tableau doit être fixé !
● Exemple : calcul de la trace d'une matrice « mat »

REAL FUNCTION trace ( mat )


REAL, DIMENSION(:, :), INTENT(IN) :: mat
...
END FUNCTION trace
22
Argument de type tableau (2)
● Remarque : le premier indice du tableau « mat »
déclaré ci-dessous est 1 dans chaque dimension.
REAL, DIMENSION(:, :), INTENT(IN) :: mat

● Comment connaître les étendues du tableau passé


en argument ?
● Utilisation de la fonction intrinsèque SIZE :
SIZE ( mat, 1 ) et SIZE ( mat, 2 )
● Les étendues de « mat » dans la fonction sont
donc ici, quelles que soient celles du tableau
passé en argument depuis le prgm appelant :
(1:SIZE(mat,1), 1:SIZE(mat,2))
● LBOUND (mat, 1) et LBOUND (mat, 2) donnent 1 !!
23
Argument de type tableau (3)
MODULE proc
IMPLICIT NONE
CONTAINS
REAL FUNCTION trace ( mat )
REAL, DIMENSION(:, :), INTENT(IN) :: mat
INTEGER :: i, n_lgn, n_col ! Variables locales
n_lgn = SIZE(mat, 1) ; n_col = SIZE(mat, 2)
IF (n_lgn /= n_col) STOP ''Matrice non carree !''
trace = 0.
DO i = 1, n_lgn ; trace = trace + mat(i, i) ; END DO
END FUNCTION trace
END MODULE proc

PROGRAM calcul_trace
USE proc
IMPLICIT NONE
REAL, DIMENSION (0:5, 0:5) :: A = 1.
PRINT *, 'Trace de A = ', trace (A) ! Donne 6
24
END PROGRAM calcul_trace
Argument de type tableau (4)

● Comment indiquer un premier indice différent


de 1 dans les dimensions d'un tableau
argument muet ?
REAL FUNCTION trace ( mat )
REAL, DIMENSION(0:, 0:), INTENT(IN) :: mat
INTEGER :: i
IF (SIZE(mat, 1) /= SIZE(mat, 2)) STOP ''Matrice non carree !''
trace=0.
DO i = 0, SIZE(mat, 1) – 1
trace = trace + mat(i, i)
END DO
END FUNCTION trace

ou encore, DO i = LBOUND(mat, 1), UBOUND(mat, 1)


trace = trace + mat(i, i)
pour la boucle : END DO 25
Programmation
pour le calcul scientifique

UE 2A005 – 2nd semestre 2018-19


Sorbonne Université

Responsable :
Ivan Delbende
Ivan.Delbende@sorbonne-universite.fr

Cours 6b : Sous-programmes (subroutine)


Qu'est ce qu'un sous-programme
ou SUBROUTINE ?
● Le sous-programme est l'autre type de procédure
que le FORTRAN possède (avec la fonction).
● Contrairement à FUNCTION, la SUBROUTINE ne
possède pas de valeur, pas de type, elle ne
retourne pas directement de résultat
● Son appel ne peut donc pas apparaître dans une
expression (comme a=... ou bien PRINT *, …)

● L'appel d'une SUBROUTINE s'effectue à l'aide de


l'instruction :

CALL nom_subroutine (arguments d'appel)


2
Exemple de SUBROUTINE
● Sous-programme affichant la matrice passée en
argument (placée dans un module après CONTAINS)
SUBROUTINE affiche ( mat )
REAL, DIMENSION (:, :), INTENT (IN) :: mat ! déclaration des arg. muets
INTEGER :: nb_lgn, i ! déclaration des var. locales

nb_lgn = SIZE (mat, 1) ! instructions


DO i = 1, nb_lgn
PRINT '(1000F12.6)', mat (i, :) ! affichage avec format
END DO
PRINT *
END SUBROUTINE affiche

● Appel depuis le programme principal


INTEGER, PARAMETER :: nA = 5, mB = 4, nB = 2
REAL, DIMENSION (nA, nA) :: A = 1.
REAL, DIMENSION (mB, nB) :: B = 2.

PRINT *, ' Matrice A : '


CALL affiche ( A )
PRINT *, ' Matrice B : '
CALL affiche ( B ) 3
SUBROUTINE (1)

● La SUBROUTINE ne possède pas de valeur, pas


de type mais, lors de son appel, elle peut
modifier la valeur de certains arguments
passés dans la liste d'appel

Exemple : sous-programme de conversion


coordonnées cartésiennes → coordonnées polaires
SUBROUTINE cart_to_polar (x, y, r, theta)
REAL, INTENT ( IN ) :: x, y
REAL, INTENT ( OUT ) :: r, theta

r = SQRT (x**2 + y**2)


theta = ATAN2 (y, x)
END SUBROUTINE cart_to_polar
4
SUBROUTINE (2)
L'appel au sous- SUBROUTINE cart_to_polar ( x, y, r, theta )
REAL, INTENT (IN) :: x, y
programme REAL, INTENT (OUT) :: r, theta

r = SQRT (x**2 + y**2)


depuis le programme principal theta = ATAN2 (y, x)
ou depuis une autre procédure : END SUBROUTINE

REAL :: xA = 2.5, yA = -1.3


REAL :: rA, thA, rB, thB

CALL cart_to_polar ( xA, yA, rA, thA )


PRINT *, ' rA = ', rA, ' thA = ', thA

CALL cart_to_polar (ACOS(-1.), 0., rB, thB)


PRINT *, ' rB = ', rB, ' thB = ', thB
CALL cart_to_polar (1., 2., 3., 3.5) ! Incorrect car 3. et 3.5 ne sont
5
! pas des variables
SUBROUTINE (2)
L'appel au sous- SUBROUTINE cart_to_polar ( x, y, r, theta )
REAL, INTENT (IN) :: x, y
programme REAL, INTENT (OUT) :: r, theta

r = SQRT (x**2 + y**2)


depuis le programme principal theta = ATAN2 (y, x)
ou depuis une autre procédure : END SUBROUTINE

REAL :: xA = 2.5, yA = -1.3


REAL :: rA, thA, rB, thB

CALL cart_to_polar ( xA, yA, rA, thA )


PRINT *, ' rA = ', rA, ' thA = ', thA

CALL cart_to_polar (ACOS(-1.), 0., rB, thB)


PRINT *, ' rB = ', rB, ' thB = ', thB
CALL cart_to_polar (1., 2., 3., 3.5) ! Incorrect car 3. et 3.5 ne sont
6
! pas des variables
SUBROUTINE (2)
L'appel au sous- SUBROUTINE cart_to_polar ( x, y, r, theta )
REAL, INTENT (IN) :: x, y
programme REAL, INTENT (OUT) :: r, theta

r = SQRT (x**2 + y**2)


depuis le programme principal theta = ATAN2 (y, x)
ou depuis une autre procédure : END SUBROUTINE

REAL :: xA = 2.5, yA = -1.3 début de


REAL :: rA, thA, rB, thB l'appel
CALL cart_to_polar ( xA, yA, rA, thA )
PRINT *, ' rA = ', rA, ' thA = ', thA

CALL cart_to_polar (ACOS(-1.), 0., rB, thB)


PRINT *, ' rB = ', rB, ' thB = ', thB
CALL cart_to_polar (1., 2., 3., 3.5) ! Incorrect car 3. et 3.5 ne sont
7
! pas des variables
SUBROUTINE (2)
L'appel au sous- SUBROUTINE cart_to_polar ( x, y, r, theta )
REAL, INTENT (IN) :: x, y
programme REAL, INTENT (OUT) :: r, theta

r = SQRT (x**2 + y**2)


depuis le programme principal theta = ATAN2 (y, x)
ou depuis une autre procédure : END SUBROUTINE

REAL :: xA = 2.5, yA = -1.3 début de


REAL :: rA, thA, rB, thB l'appel
CALL cart_to_polar ( xA, yA, rA, thA )
PRINT *, ' rA = ', rA, ' thA = ', thA

CALL cart_to_polar (ACOS(-1.), 0., rB, thB)


PRINT *, ' rB = ', rB, ' thB = ', thB
CALL cart_to_polar (1., 2., 3., 3.5) ! Incorrect car 3. et 3.5 ne sont
8
! pas des variables
SUBROUTINE (2)
L'appel au sous- SUBROUTINE cart_to_polar ( x, y, r, theta )
REAL, INTENT (IN) :: x, y
programme REAL, INTENT (OUT) :: r, theta

r = SQRT (x**2 + y**2)


depuis le programme principal theta = ATAN2 (y, x)
ou depuis une autre procédure : END SUBROUTINE

REAL :: xA = 2.5, yA = -1.3 début de


REAL :: rA, thA, rB, thB l'appel
CALL cart_to_polar ( xA, yA, rA, thA )
PRINT *, ' rA = ', rA, ' thA = ', thA

CALL cart_to_polar (ACOS(-1.), 0., rB, thB)


PRINT *, ' rB = ', rB, ' thB = ', thB
CALL cart_to_polar (1., 2., 3., 3.5) ! Incorrect car 3. et 3.5 ne sont
9
! pas des variables
SUBROUTINE (2)
L'appel au sous- SUBROUTINE cart_to_polar ( x, y, r, theta )
REAL, INTENT (IN) :: x, y
programme REAL, INTENT (OUT) :: r, theta

r = SQRT (x**2 + y**2)


depuis le programme principal theta = ATAN2 (y, x) fin d'appel
ou depuis une autre procédure : END SUBROUTINE

REAL :: xA = 2.5, yA = -1.3 début de


REAL :: rA, thA, rB, thB l'appel
CALL cart_to_polar ( xA, yA, rA, thA )
PRINT *, ' rA = ', rA, ' thA = ', thA

CALL cart_to_polar (ACOS(-1.), 0., rB, thB)


PRINT *, ' rB = ', rB, ' thB = ', thB
CALL cart_to_polar (1., 2., 3., 3.5) ! Incorrect car 3. et 3.5 ne sont
10
! pas des variables
SUBROUTINE (2)
L'appel au sous- SUBROUTINE cart_to_polar ( x, y, r, theta )
REAL, INTENT (IN) :: x, y
programme REAL, INTENT (OUT) :: r, theta

r = SQRT (x**2 + y**2)


depuis le programme principal theta = ATAN2 (y, x) fin d'appel
ou depuis une autre procédure : END SUBROUTINE

REAL :: xA = 2.5, yA = -1.3 début de


REAL :: rA, thA, rB, thB l'appel
CALL cart_to_polar ( xA, yA, rA, thA )
PRINT *, ' rA = ', rA, ' thA = ', thA

CALL cart_to_polar (ACOS(-1.), 0., rB, thB)


PRINT *, ' rB = ', rB, ' thB = ', thB
CALL cart_to_polar (1., 2., 3., 3.5) ! Incorrect car 3. et 3.5 ne sont
11
! pas des variables
SUBROUTINE (2)
L'appel au sous- SUBROUTINE cart_to_polar ( x, y, r, theta )
REAL, INTENT (IN) :: x, y
programme REAL, INTENT (OUT) :: r, theta

r = SQRT (x**2 + y**2)


depuis le programme principal theta = ATAN2 (y, x) fin d'appel
ou depuis une autre procédure : END SUBROUTINE

REAL :: xA = 2.5, yA = -1.3 début de


REAL :: rA, thA, rB, thB l'appel
CALL cart_to_polar ( xA, yA, rA, thA )
PRINT *, ' rA = ', rA, ' thA = ', thA

CALL cart_to_polar (ACOS(-1.), 0., rB, thB)


PRINT *, ' rB = ', rB, ' thB = ', thB
CALL cart_to_polar (1., 2., 3., 3.5) ! Incorrect car 3. et 3.5 ne sont
12
! pas des variables
Attribut INTENT
dans une procédure (1)
● L'attribut INTENT ajoute un contrôle sur
l'utilisation des arguments muets
➢ INTENT (IN) : entrée seulement
l'argument ne peut être modifié au sein de
la procédure
➢ INTENT (OUT) : sortie seulement
 l'argument doit être défini dans la
procédure (avant son utilisation éventuelle
par la suite)
➢ INTENT (INOUT) : entrée et sortie
 l'argument peut être utilisé, et doit être
modifié, dans la procédure
13
Attribut INTENT
dans une procédure (2)
● Exemple d'utilisation de l'attribut INTENT(INOUT)
sous-programme qui échange deux réels
SUBROUTINE echange_deux_reels ( a, b )
REAL, INTENT ( INOUT ) :: a, b
REAL :: tmp

tmp = a
a=b début de
fin d'appel
b = tmp l'appel
END SUBROUTINE
● Appel :
REAL :: x = 1., y = 4.5
CALL echange_deux_reels ( x, y )
PRINT *, ' x = ', x, ' y = ', y
14
CALL echange_deux_reels (1., x) ! Incorrect car 1. n'est pas une var.
Attribut INTENT
dans une procédure (3)
● Conséquences sur les arguments d'appel :
➢ avec INTENT(IN) : l'argument d'appel peut être une
variable, une expression ou une constante
➢ avec INTENT(OUT) et INTENT(INOUT) : l'argument d'appel
ne peut être qu'une variable
● Dans une FUNCTION les arguments sont en général
utilisés avec INTENT(IN), même si on peut utiliser
d'autres attributs INTENT (à éviter)
● L'attribut INTENT n'est pas obligatoire mais vivement
recommandé car il évite des erreurs.
Attribut INTENT obligatoire en 2A005
(INTENT ne concerne que les
arguments muets des procédures) 15
Instruction RETURN
● L'instruction RETURN permet de quitter la
procédure avant END FUNCTION/SUBROUTINE
● Dans le cas d'une FUNCTION, il faudra s'assurer
que la valeur à retourner est correctement
positionnée avant RETURN.
REAL FUNCTION maximum (x, y)
REAL, INTENT(IN) :: x, y
IF (x < y) THEN
maximum = y
RETURN
ELSE
maximum = x
RETURN
END IF
! des instructions situées ici ne seraient jamais exécutées

END FUNCTION maximum 16


Utilisation des procédures

● Besoin d'effectuer un même traitement plusieurs


fois
➢ avec des valeurs différentes
➢ à différents instants au cours de l'exécution du
programme
● Besoin de limiter la taille des unités de programme
(1 ou 2 pages maximum) → lisibilité du code
● Besoin de réutiliser du code déjà écrit
● La solution est de définir ce traitement une seule
fois à l'aide d'une procédure
➢ SUBROUTINE (sous-programme)
➢ FUNCTION (fonction)
17
Structure simplifiée d'un
programme Fortran
PROGRAMME PRINCIPAL MODULE

PROGRAM mon_prog MODULE mon_module


USE mon_module USE …
IMPLICIT NONE
IMPLICIT NONE ! Déclarations de types
! Déclarations ! et de variables
REAL :: var, x INTEGER :: var_glob
...
CONTAINS
REAL FUNCTION ma_fnct(x)
! Instructions REAL, INTENT(IN) :: x
var = ma_fnct(var) + ma_fnct(var_glob) ! variables locales
CALL ma_sub(x) REAL :: var_loc

ma_f = var_glob + x
END PROGRAM mon_prog END FUNCTION ma_fnct

SUBROUTINE ma_sub(…)
END SUBROUTINE ma_sub
END MODULE mon_module 18
Portée et durée de vie
d’une variable
● Portée : partie du code au sein de laquelle la
variable est accessible
➢ Par défaut, la portée est limitée à l'unité de programme
dans laquelle la variable a été déclarée

19
Structure simplifiée d'un
programme Fortran
PROGRAMME PRINCIPAL MODULE

PROGRAM mon_prog MODULE mon_module


USE mon_module USE …
IMPLICIT NONE
IMPLICIT NONE ! Déclarations de types
! Déclarations ! et de variables
REAL :: var, x INTEGER :: var_glob
...
CONTAINS
REAL FUNCTION ma_fnct(x)
var ! Instructions REAL, INTENT(IN) :: x
x var_glob
var = ma_fnct(var) + ma_fnct(var_glob) ! variables locales
CALL ma_sub(x) REAL :: var_loc
x

ma_f = var_glob + x var_loc


END PROGRAM mon_prog END FUNCTION ma_fnct

SUBROUTINE ma_sub(…)
END SUBROUTINE ma_sub
END MODULE mon_module 20
Portée et durée de vie
d’une variable
● Portée : partie du code au sein de laquelle la
variable est accessible
➢ Par défaut, la portée est limitée à l'unité de programme
dans laquelle la variable a été déclarée
● Durée de vie : temps pendant lequel la variable
existe en mémoire
➢ Par défaut, la durée de vie est limitée à la durée de vie
de l'unité de programme dans laquelle la variable a été
déclarée
 les variables locales « disparaissent » lorsque
la procédure se termine
 la valeur des variables locales n'est pas
conservée d'un appel à l'autre ……. sauf si …..

21
Variable statique (1)
L'attribut SAVE permet de prolonger la durée de vie
d'une variable locale à celle de l'exécutable.
 variable statique
REAL FUNCTION maximum (x, y)
IMPLICIT NONE
REAL, INTENT(IN) :: x, y
INTEGER, SAVE :: compteur = 0

compteur = compteur + 1
PRINT *, ' Cette fonction a été appelée ', compteur, ' fois '

IF (x < y) THEN
maximum = y
ELSE
maximum = x
END IF
END FUNCTION maximum
22
Variable statique (2)

Attention : en Fortran 90, toute variable locale


initialisée lors de sa déclaration est considérée
comme statique !
→ SAVE est donc facultatif dans l'exemple précédent :
REAL FUNCTION maximum(x,y)
IMPLICIT NONE
REAL, INTENT(IN) :: x,y
INTEGER :: compteur = 0 ! SAVE facultatif, variable statique

compteur = compteur + 1
PRINT *, 'Cette fonction a été appelée ', compteur, 'fois'

IF (x<y) THEN
maximum = y
ELSE
maximum = x
END IF
23
END FUNCTION maximum
Variable statique (3)

Attention : en Fortran 90, toute variable locale


initialisée lors de sa déclaration est considérée
comme statique !
→ Gros risque d'erreur quand une somme ou un produit est
initialisé au moment de sa déclaration dans une procédure
INTEGER FUNCTION factorielle ( n )
IMPLICIT NONE
INTEGER, INTENT( IN ) :: n
INTEGER :: i, produit = 1 ! INCORRECT car produit ne sera
! mis à 1 que lors du 1er appel
DO i = 2, n
produit = produit * i
END DO
factorielle = produit
END FUNCTION factorielle

Le premier appel PRINT *, factorielle (2) donnera 2


Le second appel PRINT *, factorielle (2) donnera 4 !!! 24
Variable statique (4)

NE JAMAIS INITIALISER UNE SOMME OU


UN PRODUIT AU NIVEAU DE LA
DECLARATION DANS UNE PROCEDURE
INTEGER FUNCTION factorielle ( n )
IMPLICIT NONE
INTEGER, INTENT( IN ) :: n
INTEGER :: i, produit

produit = 1 ! Correct
DO i = 2, n
produit = produit * i
END DO
factorielle = produit
END FUNCTION factorielle

Ici, tous les appels à factorielle (2) retourneront 2 ! 25

Vous aimerez peut-être aussi