Travaux dirigés de Fortran – Niveau 2

Transcription

Travaux dirigés de Fortran – Niveau 2
École normale supérieure
L3 sciences de la planète Terre
Travaux dirigés de Fortran – Second semestre
3 octobre 2016
Table des matières
1 Écriture et appel de fonction, programme à deux fichiers
2
2 Écriture et appel de subroutine, argument tableau
2
3 Utilisation d’une procédure de bibliothèque
3
4 Instructions open, write, close ; pseudo-boucle
3
5 Lecture d’un fichier, nombre de lignes connu
4
6 Lecture d’un fichier, nombre de lignes inconnu
5
7 namelist, combinaison Fortran – Bash – visualisation
6
8 Double précision, argument optionnel, trois fichiers
7
9 Supplément : révisions
8
1
Rappel : si vous avez besoin de consulter la norme Fortran 95, par exemple
pour connaître la description d’une procédure intrinsèque, vous pouvez trouvez
sa version quasi-définitive en ligne : http://j3-fortran.org/doc/standing/
archive/007/97-007r2/pdf/97-007r2.pdf.
Des solutions des exercices vous sont proposées dans le répertoire :
~lguez/Documents/Solutions_TD_Fortran_2
1
Écriture et appel de fonction, programme à
deux fichiers
Écrivez un programme qui demande à l’utilisateur d’entrer une suite de trois
caractères et qui indique si les caractères sont dans l’ordre ASCII croissant, décroissant, ou dans le désordre. Le programme redemandera à l’utilisateur d’entrer trois nouveaux caractères jusqu’à ce que l’utilisateur entre trois étoiles :
***. Utilisez une fonction logique qui indique si une suite de caractères est dans
l’ordre croissant. (Solution : Order_3_char.)
2
Écriture et appel de subroutine, argument tableau
Écrivez un programme qui affiche la forme représentée sur la figure (1), à
l’aide de simples caractères, par exemple des étoiles : *. Utilisez une procédure
10
x
10
30
50
70
y
Figure 1 – Dessin de rectangles.
qui ajoute un rectangle unique. (Solution : Draw_rectangles.)
2
3
Utilisation d’une procédure de bibliothèque
La procédure quadrat de la bibliothèque Jumble trouve les racines réelles
d’une équation du second degré à coefficients réels :
ax2 + bx + c = 0
Cf. listing (1). Le module jumble est le module regroupeur de la bibliothèque
Listing 1 – Documentation de la procédure quadrat de la bibliothèque Jumble.
subroutine q u a d r a t ( a , b , c , d e l t a , r o o t )
!
!
!
!
!
This s u b r o u t i n e computes t h e r e a l r o o t s o f a
with r e a l c o e f f i c i e n t s . I f t h e r e i s a d o u b l e
d o u b l e i n t h e ou tp ut a r r a y . I f t h e r e a r e two
t h e y a r e ou tp ut i n a s c e n d i n g o r d e r . I f t h e r e
t h e ou tp ut a r r a y i s u n d e f i n e d .
quadratic equation
root , i t appears in
d i s t i n c t roots ,
i s no r e a l r o o t ,
real , intent ( in ) : : a , b , c
! a x ^2 + b x + c = 0
real , intent ( out ) : : d e l t a ! d i s c r i m i n a n t
real , intent ( out ) : : r o o t ( : ) ! ( 2 )
Jumble. La bibliothèque Jumble se trouve dans le répertoire :
/users/staffs/lguez/Bureau/lib/Jumble
Écrivez un programme qui demande à l’utilisateur des valeurs de a, b et c,
appelle quadrat et écrit les résultats. S’il existe une racine double, le programme
l’indiquera et n’affichera qu’une valeur. (Solution : test_quadrat.f.)
4
Instructions open, write, close ; pseudo-boucle
Dans cet exercice, vous allez écrire quelques statistiques sur les nombres
premiers.
Partez du programme du premier semestre qui trouve la liste des nombres
premiers inférieurs à un entier n, à l’aide du crible d’Ératosthène. Modifiez le
programme pour qu’il écrive :
— le nombre de nombres premiers inférieurs à n ;
— la liste de ces nombres premiers, seulement s’il y en a moins de 30 ;
— l’intervalle moyen entre deux nombres premiers inférieurs à n ;
— un fichier texte, que vous appellerez prime_intervals.txt contenant la
liste des différences entre deux nombres premiers successifs, une valeur
par ligne, sans ligne de titre ;
— un message annonçant la création d’un fichier contenant les intervalles.
Est-il possible de simplement rediriger la sortie standard au lieu de créer un
fichier dans le programme ? Utilisez la procédure new_unit de la bibliothèque
Jumble. Cf. listing (2). Fonctions intrinsèques utiles : count, pack.
Compilez et testez votre programme avec de petites valeurs de n.
Dans le shell, ajoutez les bons arguments aux commandes :
3
Listing 2 – Documentation de la procédure new_unit de la bibliothèque Jumble.
subroutine new_unit ( unit )
! This p r o c e d u r e p r o v i d e s a l i c i t and not a l r e a d y opened e x t e r n a l
! f i l e unit .
integer , intent ( out ) : : unit
sort -n
uniq -c
et combinez ces commandes pour transformer le fichier prime_intervals.txt
en un fichier histogram.txt, contenant un histogramme des intervalles, c’està-dire le nombre d’occurrences de chaque intervalle. (Consultez le man de ces
commandes.) Essayez avec n = 107 , par exemple.
Vous pouvez visualiser le résultat en lançant Gnuplot et en tracant l’histogramme à l’aide des commandes suivantes :
set boxwidth .8
set logscale y
plot "histogram.txt" using 2:1 with boxes fs solid
La ligne avec logscale ci-dessus rend l’axe des ordonnées logarithmique. Vous
devriez alors observer une décroissance linéaire de l’histogramme. Pour revenir
à un axe des ordonnées linéaire :
unset logscale y
(Solution : prime_stat.f.)
5
Lecture d’un fichier, nombre de lignes connu
Le fichier :
/users/staffs/lguez/Documents/Solutions_TD_Fortran_2/recensement.txt
dans votre répertoire. Ce fichier contient pour chaque département (colonne 1)
la population en 1999 (colonne 2) et celle en 1990 (colonne 3) (source INSEE).
Vous pouvez voir que les 95 premiers départements sont numérotés de 1 à 95 et
les 4 derniers de 971 à 974.
1. Écrivez un programme qui enregistre ces données dans deux tableaux :
un vecteur pour les numéros des départements, et un tableau à deux
dimensions pour les valeurs de population. On pourra supposer dans le
programme que le nombre de départements dans recensement.txt est de
99. Le programme affichera le numéro des départments dont l’évolution de
la population entre 1990 et 1999 est soit supérieure à 5 %, soit inférieure
à - 5 %.
Procédure intrinsèque Fortran pouvant vous être utile : abs.
Vous devriez obtenir la liste suivante de départements dont la population
a beaucoup évolué : 1 4 5 15 17 23 26 27 30 31 33 34 35 38 40 44 45 60
66 67 68 73 74 77 83 84 85 86 95 971 972 973 974.
(Solution : population_1.f.)
4
2. Modifiez le programme pour qu’il demande en outre à l’utilisateur de
saisir un numéro de départment et affiche l’évolution de sa population et
son rang en terme de nombre d’habitants en 1999 et 1990. On pourra
supposer dans le programme que les départements apparaissent dans
recensement.txt dans l’ordre croissant de leurs numéros. Est-il toujours possible de simplement rediriger l’entrée standard pour lire le fichier ? Nota bene : le chemin du fichier lu ne doit pas être écrit dans
le programme (c’est un conseil de style de programmation, notamment
pour la portabilité du programme), vous aurez donc à copier le fichier
recensement.txt dans votre répertoire ou à créer un lien symbolique.
Procédure intrinsèque Fortran pouvant vous être utile : count.
(Solution : population_2.f.)
6
Lecture d’un fichier, nombre de lignes inconnu
(Adapté de Holton, 2004, An Introduction to Dynamic Meteorology.)
Copiez le fichier :
~lguez/Documents/Solutions_TD_Fortran_2/Tropical_temp/tropical_temp.csv
dans votre répertoire. Vous pouvez voir le contenu de ce fichier avec par exemple
un tableur comme celui de LibreOffice (ou avec un éditeur de texte quelconque).
Ce fichier contient des valeurs de température T à différents niveaux de pression
p, qui proviennent de sondages atmosphériques dans la région tropicale.
Le but de cet exercice est d’écrire un programme qui calcule à partir de
ces données les profils correspondants de la hauteur de géopotentiel Z, de la
température potentielle θ et du paramètre de stabilité statique :
T
Sp := − ∂p θ
θ
Vous calculerez Z en utilisant l’équation hypsométrique. Le programme demandera à l’utilisateur d’entrer la valeur de Z au niveau de pression le plus élevé.
Rappels. En notant Φ le géopotentiel et R la constante massique des gaz
parfaits pour l’air sec :
R = 287 J K−1 kg−1
l’équation hypsométrique s’écrit :
∂p Φ = −
RT
p
On a :
Z = Φ/g0
avec :
g0 = 9,806 65 m s−2
La température potentielle est :
θ = T (pref /p)κ
5
avec :
pref = 1 000 hPa
κ = 2/7
Indications.
— Pour Z, intégrez l’équation hypsométrique entre deux niveaux de pression
et calculez l’intégrale en supposant que T varie à peu près linéairement
avec le logarithme de la pression entre les deux niveaux de pression.
— Pour Sp , vous approximerez la dérivée de θ au niveau de pression d’indice
i par la différence finie :
(∂p θ)i ≈
θi+1 − θi−1
pi+1 − pi−1
Si le tableau des pressions est indicé de 1 à n, le tableau contenant les
valeurs de Sp aura donc une plage d’indices de 2 à n − 1.
Appelez la procédure count_lines de la bibliothèque Jumble pour compter
le nombre n de couples (p, T ) dans le fichier tropical_temp.csv. Cf. listing (3).
Est-il possible de simplement rediriger l’entrée standard pour lire le fichier ?
Listing 3 – Documentation de la procédure count_lines.
subroutine c o u n t _ l i n e s ( unit , n )
!
!
!
!
!
!
This s u b r o u t i n e c o u n t s t h e number o f l i n e s i n an e x t e r n a l f i l e ,
from t h e c u r r e n t p o s i t i o n , not n e c e s s a r i l y t h e f i r s t r e c o r d o f t h e
file .
On r e t u r n , t h e p o s i t i o n i s a t t h e end o f t h e f i l e .
The f i l e s h o u l d be c o n n e c t e d f o r s e q u e n t i a l a c c e s s .
The r e c o r d s o f t h e f i l e shoud be f o r m a t t e d .
integer , intent ( in ) : : unit ! e x t e r n a l f i l e u n i t
integer , intent ( out ) : : n ! number o f l i n e s
Calculez la température potentielle, en utilisant une affectation de tableau
à tableau (n’utilisez pas de boucle).
Créez un nouveau fichier avec un suffixe .csv contenant les colonnes p, Z, θ
et Sp . Pensez à mettre une première ligne de titres dans le fichier. Séparez les
valeurs par des espaces. Est-il possible de simplement rediriger la sortie standard
pour créer ce fichier ?
Visualisez les résultats avec le logiciel graphique de votre choix (Gnuplot,
Matplotlib, Grace. . .).
(Solution : tropical_temp.f.)
7
namelist, combinaison Fortran – Bash – visualisation
Écrivez un programme qui permette d’enregistrer dans un fichier les termes
de la suite suivante :
xn+1 = byn + f (xn )
yn+1 = −xn + f (xn+1 )
6
avec :
2(1 − a)x2
1 + x2
et les constantes a = −0,6 et b = 0,99. L’utilisateur doit pouvoir choisir à
l’exécution la condition initiale (x0 , y0 ) et l’indice final n. Programmez l’entrée
de ces trois variables dans une namelist. Choisissez x0 = 0,09, y0 = 2,76 et, par
exemple, n = 10, comme valeurs par défaut.
Lancez l’exécution avec les valeurs par défaut de x0 , y0 et n. Utilisez Gnuplot
pour visualiser la position des points (xi , yi ), i = 0, . . . , n dans le plan. Utilisez
l’option de plot :
f (x) = ax +
with points pt 0
pour tracer seulement un pixel par couple (xi , yi ) et pour que les pixels ne soient
pas reliés entre eux.
Écrivez un script en Bash, qui prend en argument n sur la ligne de commande, et qui exécute le programme en Fortran et trace le graphique pour cette
valeur de n. Le script doit donc fournir à l’exécutable Fortran la namelist contenant la valeur de n choisie. Pour le graphique, le script appellera Gnuplot de la
façon suivante :
gnuplot -persist Sans l’option -persist, la figure disparaîtrait immédiatement après avoir été
tracée. Le tiret final dans la commande ci-dessus indique que les commandes de
Gnuplot doivent être lues sur l’entrée standard.
Avec le script, testez des valeurs croissantes de n (essayez par exemple des
puissances de 10 successives). De manière analogue, vous pouvez aussi tester
l’influence des valeurs de x0 et y0 .
Rappel du cours sur Unix. Vous aurez besoin d’enregistrer dans le script ce
qui doit normalement être lu au clavier, pour le programme en Fortran et pour
Gnuplot. Pour cela, vous pouvez par exemple utiliser la technique suivante :
mon_programme <<EOF
ce que j’écrirais normalement au clavier
EOF
(Solution : Attractor.)
8
Double précision, argument optionnel, programme
à trois fichiers
Écrivez un programme qui :
— demande à l’utilisateur sa date de naissance exacte (jour et heure) ;
— retourne à l’écran la durée écoulée depuis sa naissance en jours, heures,
minutes et secondes.
Une solution économique consiste à utiliser la date julienne. La date julienne
est le nombre de jours depuis le 1er janvier 4713 avant J.-C., à 12 h, temps
universel, dans un calendrier proleptique grégorien. (Elle est utilisée en astronomie.) Cf. par exemple http://www.tondering.dk/claus/cal/julperiod.
php#formula.
7
Écrivez une procédure qui reçoit une date quelconque sous la forme année,
mois, jour (nombres entiers) et heure avec fraction d’heure (un nombre réel),
et qui renvoie la date julienne (nombre réel). Vous écrirez aussi une procédure
qui transforme un triplet d’entiers, heures, minutes, secondes en un nombre réel
heure avec fraction d’heure.
Procédures intrinsèques Fortran pouvant vous être utiles : date_and_time,
floor.
(Solution : Age_in_days.)
9
Supplément : révisions
— Écrivez une fonction qui prend en argument un vecteur de réels et qui
renvoie (comme résultat de la fonction) son écart-type.
Rappel. L’écart-type de x est :
s
1 X
(xi − hxi)2
σ=
n−1 i
où n est le nombre de valeurs dans x.
Le fichier :
~lguez/Documents/Solutions_TD_Fortran_2/Test_std/T_surf_equator.csv
contient des températures à la surface, à l’équateur, à une certaine date,
en fonction de la longitude. Regardez le contenu du fichier pour voir
comment il est organisé. Écrivez un programme principal qui lit les températures dans ce fichier, qui appelle la fonction pour calculer l’écarttype des températures, et qui affiche cet écart-type. Vous devriez trouver
1,682 639 8 K.
Procédures intrinsèques utiles : sum, sqrt.
Solution : Test_std.
— Copiez le fichier :
~lguez/Documents/Solutions_TD_Fortran_2/virus.txt
dans votre répertoire.
Une séquence d’ADN est formée d’une succession de nucléotides : l’adénine, la cytosine, la guanine et la thymine. Les symboles de ces nucléotides
sont A, C, G et T. Le fichier virus.txt contient une suite de nucléotides
du virus “alien27”.
Écrivez un programme qui indique le nombre et la position des occurences
du gène constitué par la suite de nucléotides GAG. GAGAG compte pour
une seule occurence de GAG.
Procédure intrinsèque Fortran pouvant vous être utile : all.
Solution : adn_2.f.
8