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