Installazione di un compilatore gfortran - nau.unimore.it · Installazione di un compilatore Per...

50
Installazione di un compilatore Per installare un compilatore Fortran, ad esempio il compilatore gfortran, si procede come segue. Sui computer su cui ` e installato il sistema operativo Unix/Linux o per i computer MAC di Apple: collegarsi al sito web gcc.gnu.org/wiki/GFortranBinaries e scegliere (“cliccando”) la versione del compilatore gfortran per il sistema operativo adottato alle sezioni MacOS e GNU/Linux. Ad esempio, per il sistema operativo MacOS scegliere una delle versioni del compilatore in base alla versione del sistema operativo. Per le versioni pi` u recenti scegliere Yosemite. Perch´ e il compilatore possa essere eseguito ` e necessario che sul computer sia presente l’applicazione Xcode. Se non ` e presente (o se non sono installati i command line tools), “cliccare” su detailed instructions can be found here per un’installazione guidata (scaricare da AppStore il file Xcode, poi “aprire” Xcode, “andare” in preferenze poi in downloads e poi in command line tools e “cliccare” su install). sistema operativo Windows: collegarsi al sito web www.equation.com/servlet/equation.cmd?fa=fortran e scegliere (“cliccando”) gcc-5.1.0-64.exe oppure gcc-5.1.0-32.exe se il tipo di sistema ` e a 64 o a 32 bit (per Windows7, si veda: pannello di controllo > sistema e sicurezza > sistema). Il compilatore gfortran compila file scritti in Fortran77, 90, 95 e 2003 con estensione .f Il compilatore gfortran ha, ad esempio, le opzioni: -c per compilare senza creare i collegamenti (crea il file oggetto ma non il file eseguibile); -o per rinominare il file eseguibile Su Unix/Linux di default il file eseguibile si chiama a.out mentre su windows a.exe Ad esempio, si crea un file Fortran 77 oppure Fortran 90 (95, 2003) oppure scritto in modo misto che viene salvato con il nome nome.f (la scrittura del file avviene con l’esecuzione di un editor, ad esempio: vi, wordpad, edit, winedt, ...). Per l’esecuzione del compilatore (compilazione del programma), si “apre” il prompt dei comandi e, dal direttorio dove ` e presente il file nome.f, si scrive nella linea dei comandi gfortran -o nome nome.f e viene creato il file eseguibile (codice tradotto in linguaggio macchina con la libreria del linguaggio inclusa) che si chiama nome Si esegue allora il file eseguibile, digitando dalla linea dei comandi nome Su Unix/Linux l’esecuzione avviene digitando ./nome Se ad esempio, in un file salvato con il nome file1.f ` e scritto un codice che contiene il programma principale ed alcuni sottoprogrammi chiamati dal programma principale stesso e, in un altro file, che si chiama file2.f sono scritti altri sottoprogrammi richiamati comunque dal programma principale (che ` e scritto in file1.f), allora la compilazione deve creare un unico file eseguibile contenente le traduzioni in linguaggio macchina di entrambi i file file1.f e file2.f. La creazione di questo file eseguibile, chiamato ad esempio file1, avviene con il comando 1

Transcript of Installazione di un compilatore gfortran - nau.unimore.it · Installazione di un compilatore Per...

Installazione di un compilatore

Per installare un compilatore Fortran, ad esempio il compilatore gfortran, si procede come segue.Sui computer su cui e installato il

sistema operativo Unix/Linux o per i computer MAC di Apple: collegarsi al sito web

gcc.gnu.org/wiki/GFortranBinaries

e scegliere (“cliccando”) la versione del compilatore gfortran per il sistema operativo adottato allesezioni MacOS e GNU/Linux.

Ad esempio, per il sistema operativo MacOS scegliere una delle versioni del compilatore in base allaversione del sistema operativo. Per le versioni piu recenti scegliere Yosemite.

Perche il compilatore possa essere eseguito e necessario che sul computer sia presente l’applicazioneXcode. Se non e presente (o se non sono installati i command line tools), “cliccare” su detailedinstructions can be found here per un’installazione guidata (scaricare da AppStore il file Xcode, poi“aprire” Xcode, “andare” in preferenze poi in downloads e poi in command line tools e “cliccare” suinstall).

sistema operativo Windows: collegarsi al sito web

www.equation.com/servlet/equation.cmd?fa=fortran

e scegliere (“cliccando”) gcc-5.1.0-64.exe oppure gcc-5.1.0-32.exe se il tipo di sistema e a 64 oa 32 bit (per Windows7, si veda: pannello di controllo > sistema e sicurezza > sistema).

Il compilatore gfortran compila file scritti in Fortran77, 90, 95 e 2003 con estensione .fIl compilatore gfortran ha, ad esempio, le opzioni:

-c per compilare senza creare i collegamenti (crea il file oggetto ma non il file eseguibile);

-o per rinominare il file eseguibile

Su Unix/Linux di default il file eseguibile si chiama a.out mentre su windows a.exe

Ad esempio, si crea un file Fortran 77 oppure Fortran 90 (95, 2003) oppure scritto in modo misto cheviene salvato con il nome nome.f (la scrittura del file avviene con l’esecuzione di un editor, ad esempio:vi, wordpad, edit, winedt, ...).Per l’esecuzione del compilatore (compilazione del programma), si “apre” il prompt dei comandi e, daldirettorio dove e presente il file nome.f, si scrive nella linea dei comandi

gfortran -o nome nome.f

e viene creato il file eseguibile (codice tradotto in linguaggio macchina con la libreria del linguaggioinclusa) che si chiama nome

Si esegue allora il file eseguibile, digitando dalla linea dei comandi

nome

Su Unix/Linux l’esecuzione avviene digitando ./nome

Se ad esempio, in un file salvato con il nome file1.f e scritto un codice che contiene il programmaprincipale ed alcuni sottoprogrammi chiamati dal programma principale stesso e, in un altro file, che sichiama file2.f sono scritti altri sottoprogrammi richiamati comunque dal programma principale (che escritto in file1.f), allora la compilazione deve creare un unico file eseguibile contenente le traduzioni inlinguaggio macchina di entrambi i file file1.f e file2.f.La creazione di questo file eseguibile, chiamato ad esempio file1, avviene con il comando

1

gfortran -o file1 file1.f file2.f

Se e presente un modulo (sia di dati o di sottoprogrammi o di dati e di sottoprogrammi insieme) chee stato salvato nel file denominato miomodulo.f, si deve prima compilare il modulo con l’opzione -cmediante il comando (dalla linea dei comandi, nel direttorio che comprende il file miomodulo.f)

gfortran -c miomodulo.f

e poi, si devono compilare i file contenenti il programma principale e i sottoprogrammi che usano ilmodulo memorizzato nel file miomodulo.f. Ad esempio se il file fileXX.f usa il modulo memorizzatonel file miomodulo.f, dopo il comando di compilazione del modulo si deve eseguire il comando

gfortran -o fileXX fileXX.f miomodulo.f

che crea il file eseguibile fileXX che usa il modulo scritto nel file miomodulo.f. Eseguire dunque

fileXX

Due testi di riferimento per il linguaggio Fortran, rispettivamente nelle versioni 77 e 90/95 sono, adesempio:

• Comincioli V.: Fortran 77: Introduzione e Applicazioni Numeriche, McGraw–Hill, Milano, 1991.

• Chapman S.J.: Fortran 90/95: Guida alla Programmazione, Seconda Edizione, McGraw–Hill, Mi-lano, 2004.

2

LINGUAGGIO DI PROGRAMMAZIONE

FORTRAN

FORTRAN = FORmula TRANSlation

• John Backus sviluppa il linguaggio Fortran per il calcolatore IBM 704 (1954).

• Linguaggio di programmazione vicino alla notazione matematica =⇒ Linguaggio del Calcolo Sci-entifico.

• Versioni Fortran: Fortran I (1957), Fortran II e Fortran III (1958), Fortran IV (1961), Fortran66 (1966), Fortran 77 (1977), Fortran 90 (1990), Fortran 95 (1995), Fortran 2003 (2003), Fortran2008 (2008).

• Programma Fortran composto da un programma principale (detto Main) e da uno o piu sottopro-grammi (Function e/o Subroutine).

• Il programma principale e ciascun sottoprogramma e detto unita di programma.

• Il programma principale con (o senza) i sottoprogrammi richiamati dal programma principale, econtenuto in un file identificato da un nome.estensione.

• il compilatore Fortran riconosce come file scritti in linguaggio Fortran (e dunque da tradurre inlinguaggio macchina) quelli con una particolare estensione. Generalmente i compilatori Fortranriconoscono, come file Fortran nelle diverse versioni, i file con estensione .f .F .for .FOR .f77 .F77.f90 .F90 .f95 .F95 .f03 .F03 .f08 .F08

• Tutti o alcuni sottoprogrammi richiamati da un programma principale possono essere scritti in unfile Fortran che viene compilato insieme al file Fortran che contiene il programma principale percreare un unico eseguibile contenente il programma principale e i sottoprogrammi.

• I compilatori delle versioni 90–2008 del Fortran devono compilare codici in cui sono presenti tutteo alcune istruzioni scritte in Fortran 77.

Nel seguito si indica con Fortran le regole e le istruzioni comuni alle versioni Fortran 77 e Fortran90/95/2003; con F77 le istruzioni solo per la versione Fortran 77 e con F90 le istruzioni solo per leversioni Fortran 90/95/2003.

Due testi di riferimento per il linguaggio Fortran, rispettivamente nelle versioni 77 e 90/95 sono, adesempio:

3

• Comincioli V.: Fortran 77: Introduzione e Applicazioni Numeriche, McGraw–Hill, Milano, 1991.

• Chapman S.J.: Fortran 90/95: Guida alla Programmazione, Seconda Edizione, McGraw–Hill, Mi-lano, 2004.

4

Struttura di un programma

Un programma principale in Fortran e strutturato come segue:

program nomeistruzioni dichiarative di variabili e costantiistruzioni eseguibili (statements)end

• program ed end sono parole chiave;

• end e l’istruzione di fine; e obbligatoria e deve essere presente una sola volta in ogni unita diprogramma come ultima istruzione;

• program nome e l’istruzione che assegna al programma un nome simbolico:

– il nome del programma non ha nessuna relazione con il nome del file contenente il programmastesso;

– il nome del programma deve essere diverso dal nome delle variabili, delle costanti e dellefunction presenti nel programma;

– l’istruzione program nome e opzionale;

– in F90: l’istruzione end puo essere sostituita dall’istruzione

end program

oppure daend program nome

Queste due istruzioni rendono obbligatoria l’istruzione program nome.

In Fortran:

• tutte le istruzioni dichiarative devono essere scritte prima della prima istruzione eseguibile;

• le istruzioni eseguibili possono essere etichettate:

– l’etichetta (label) e identificata da una a cinque cifre scritte consecutivamente, la prima diversada 0 (ovvero sono numeri interi da 1 a 99999):

– l’etichetta si ha solo per le istruzioni eseguibili;

– non si possono avere piu istruzioni con la stessa etichetta;

– piu istruzioni possono rimandare (con l’istruzione goto label) ad un’istruzione etichettata;

– etichettare solo le istruzioni necessarie (quelle destinazioni di salti incondizionati);

– l’ordine numerico delle etichette non ha significato (i.e. una istruzione puo essere etichettatacon 10 e quella successiva con 5, quella dopo ancora con 12 e cosı via);

• i nomi di variabili, costanti o del programma:

– devono essere scritti con le lettere dell’alfabeto inglese (maiuscole e minuscole sono viste comelo stesso carattere), le cifre (da 0 a 9) e il carattere (sottolineatura); le lettere e le cifre sichiamano anche caratteri alfanumerici e versioni non recenti di compilatori F77 riconoscono inomi solo costituiti dai caratteri alfanumerici;

– devono iniziare con una lettera;

5

– non possono essere piu lunghi di 31 caratteri (versioni non recenti di compilatori F77 ri-conoscono solo nomi con al massimo 6 caratteri);

– non possono essere uguali a parole chiave;

• nelle istruzioni, non vi e distinzione tra lettere maiuscole e minuscole;

• il carattere di spaziatura (blank) puo essere usato per migliorare la leggibilita di un programma; ilcompilatore ignora il carattere di spaziatura.1

In F77 ogni riga in un’unita di programma deve essere conforme alle seguenti regole di posizione dellacolonna:

• colonne 1–5: riservate alle etichette;

• colonna 1: la presenza dei caratteri c, C oppure * indica che la riga e una riga di commento; questariga non viene processata dal compilatore;

• colonna 6: la presenza di un carattere (eccetto 0 e la spaziatura) indica che sulla riga c’e la con-tinuazione dell’istruzione della riga precedente. Ovvero la linea di codice e scritta su due righe. Sipuo scrivere una linea di codice su 19 righe al massimo;

• colonne 7–72: riservate alla scrittura delle istruzioni;

• colonne 73–80: qualsiasi carattere scritto viene ignorato. Utile per scrivere commenti o numerarele linee di codice.

In F90:

• l’istruzione puo iniziare da colonna 1 (in poi);

• le etichette possono iniziare da colonna 1 (in poi) e l’istruzione sottointesa dall’etichetta puo iniziaredal carattere subito dopo la fine dell’etichetta;

• il carattere & a fine riga indica che la linea di codice prosegue nella riga successiva;

• su una riga, cio che e scritto dal carattere ! in poi viene ignorato dal compilatore; in generale, da! in poi si scrivono i commenti (questa regola viene anche riconosciuta nei piu recenti compilatoriF77);

• nelle istruzioni dichiarative ed eseguibili il carattere ; (punto e virgola) separa istruzioni scrittesulla stessa riga.

1Ovviamente il carattere di spaziatura non viene ignorato dal compilatore, che anzi segnala errore, se esso e posizionatointernamente a un nome, ad una parola chiave o ad una etichetta.

6

Costanti e Variabili

In Fortran le costanti e le variabili che hanno nome la cui prima lettera e una delle seguenti sei lettere

i j k l m n

sono implicitamente dichiarate intere.Le costanti e le variabili che hanno nome la cui prima lettera non e i,j,k,l,m,n, ovvero tutte le letteredell’alfabeto inglese dalla a alla h e dalla o alla z, sono implicitamente dichiarate reali in precisionesemplice.

Se si vogliono dichiarare costanti e variabili altrimenti, esse devono essere dichiarate esplicitamente.

Costanti

In Fortran le costanti sono identificate da un valore e da un tipo (il tipo del valore).Vi sono costanti numeriche (di tipo intero, reale in precisione semplice, reale in precisione doppia, com-plesso), di tipo carattere o stringa e di tipo logico o booleano. Ad esempio sono:

• costanti intere: 2 -5 21458934;

• le costanti reali in precisione semplice (2, 0.002, 2, 2 · 102, 3 · 105, 2 · 10−4):

2. 0.002 2.0 2.e02 3e+05 2.e-4

• le costanti reali in precisione doppia (4, 3 · 10−90, 0.5 · 10289):4.0d0 3d-90 0.50d289

• costante complessa, ovvero coppia di numeri reali in precisione semplice: (6e-2, 4.03)

• costanti booleane: .true. .false.

• costanti carattere, ovvero stringhe scritte tra apici:

’dato=’ ’il valore e’’=’ ’non c’’e’’’

Nella scrittura di costanti numeriche in Fortran, dopo il carattere e o d si prevedono, rispettivamente,al massimo 3 o 4 cifre. La prima e riservata al segno (opzionale se positivo) e le altre all’esponente delnumero (espresso in base 10) che per i numeri in precisione semplice, ovvero memorizzati su 32 bit, almassimo e 38 mentre per i numeri in precisione doppia, ovvero memorizzati su 64 bit e 308.

In Fortran, nella stringa ’il valore e’’=’, il terzo apice, scritto subito dopo il secondo apice, servead indicare che il secondo apice non e il carattere di fine stringa ma e un carattere da scivere; il quartoapice e il carattere di fine stringa. Il risultato delle stringa e

il valore e’=In F90 le costanti di tipo carattere possono essere racchiuse da doppio apice ". Gli esempi sopra si

scrivono: "dato=", "il valore e’’=", "non c’’e’’". Ovviamente, stringhe che hanno apici di inizio edi fine stringa diversi non sono corrette (e.g., ’dato=").

In Fortran si possono dichiarare costanti con nome.Le istruzioni dichiarative in F77 sono ad esempio:

real pi,eps

integer c

parameter(pi=3.1415, c=200)

parameter(eps=1.e-7)

oppure, sfruttando la dichiarazione implicita del Fortran

parameter(pi=3.1415, ic=200)

parameter(eps=1.e-7)

7

In F90 le stesse istruzioni si scrivono

real, parameter :: pi=3.1415, eps=1.e-7

integer, parameter :: c=200

oppure, sfruttando la dichiarazione implicita del Fortran

parameter :: pi=3.1415, ic=200

parameter :: eps=1.e-7

Si osserva che in F77 le istruzioniparameter(pi=3.1415)

real pi

non sono corrette, in quanto viene assegnato il valore 3.1415 alla variabile pi che viene implicitamentedichiarata intera e, con l’istruzione di dichiarazione successiva, la costante pi viene dichiarata esplicita-mente. Il compilatore segnala una doppia dichiarazione.In Fortran e possibile assegnare il valore ad una costante mediante espressioni aritmetiche, designatoridi funzioni matematiche elementari e mediante l’utilizzo di costanti assegnate in precedenza. Ad esempiosono possibili le istruzioni, rispettivamente in F77 e F90

parameter(pi=4*atan(1)) parameter :: pi=4*atan(1)

parameter(pi2=2*pi) parameter :: pi2=2*pi

parameter(nx=100,nx2=nx*2) parameter :: nx=100,nx2=nx*2

Variabili semplici

In Fortran le variabili semplici si dichiarano implicitamente (come specificato all’inizio) oppure esplicita-mente. Per la dichiarazione esplicita si usano le 6 parole chiave di tipo e si elencano i nomi delle variabiliseparate da una virgola.Ad esempio in F77 e F90 rispettivamente, in una unita di programma, si possono avere le seguentiistruzioni dichiarative:

real a,b real*4 :: a,b

real c real :: c

integer d,it integer :: d,it

double precision r1 real*8 r1

complex z complex :: z

logical z1 logical :: z1

character iniziale character :: iniziale

character*10 prima character(len=10) :: prima, ultima

character ultima*10 character(15) :: id

character*15 id

• In F90 per le variabili di tipo reale in precisione semplice si usa indistintamente la parola chiavereal o real*4 (4 sta per 4 byte). La parola chiave real*4 e comunque riconosciuta anche dai piurecenti compilatori F77.

• In F90 la parola chiave double precision del F77 viene sostituita con real*8 (8 sta per 8 byte).La parola chiave real*8 e comunque riconosciuta anche dai piu recenti compilatori F77.

• In F90 e possibile assegnare variabili intere su 16 bit (2 byte) con l’istruzione dichiarativa2

integer*2 :: x,y

2In F90 e anche possibile impostare la precisione in modo indipendente dal processore mediante le istruzioni kind eselect real kind. Si veda

• Chapman S.J.: Fortran 90/95: Guida alla Programmazione, Seconda Edizione, McGraw–Hill, Milano, 2004.

8

• In F90 per l’assegnazione di variabili, i caratteri :: (due volte due punti) sono opzionali.

• Nell’esempio, le variabili carattere definite sono: una variabile carattere (di nome iniziale) com-posta da un carattere (8 bit), due variabili carattere (di nome prima e ultima) composte da 10caratteri ciascuna e una variabile (di nome id) di 15 caratteri.

• len e una parola chiave che sta per length (lunghezza).

• Nell’esempio, utilizzando la dichiarazione implicita del Fortran, le istruzioni di dichiarazioni dellevariabili reali a, b e c e della variabile intera it si possono omettere.

• In Fortran una variabile deve essere dichiarata una volta sola.

• In Fortran si possono avere piu di una parola chiave per tipo in un’unita di programma. Nell’esempiole parole chiave real e character sono ripetute per dichiarare variabili diverse.

In F90 si puo assegnare il valore (iniziale) di una variabile nell’istruzione di dichiarazione (esplicita). Adesempio se si vuole inizializzare le variabili reali a, b a zero e non la variabile c3 l’istruzione si scrive

real :: a=0, b=0, c

In Fortran e possibile rendere inattiva la dichiarazione implicita inserendo, come prima istruzione di-chiarativa, l’istruzione

implcit none

In tal caso ogni variabile (semplice o con indice) e costante con nome dovra essere dichiarata esplicita-mente.L’istruzione implicit puo essere usata per dichiarare implicitamente alcune variabili. Ad esempio, leistruzioni in F77 e F90 rispettivamente

implicit integer(a) implicit, integer :: a

real a1 real :: a1

producono il risultato che, sono intere tutte le variabili (semplici o con indice) che iniziano per a, adeccezione della variabile semplice a1 che e dichiarata reale in precisione semplice.Ad esempio, per dichiarare implicitamente in doppia precisione il tipo di tutte le variabili (semplici o conindice) che iniziano per le lettere dell’alfabeto inglese dalla a alla d e dalla o alla z e con la lettera g, leistruzioni in F77 e F90 rispettivamente sono

implicit double precision(a-d,g,o-z) implicit, real*8 ::a-d,g,o-z

oppurre “spezzando” l’istruzione, ad esempio

implicit double precision(a-d,o-z) implicit, real*8 ::a-d,o-z

implicit double precision(g) implicit, real*8 ::g

3E una “buona norma” inizializzare a zero tutte le aree di memoria da utilizzare in un codice.

9

Variabili con indice

Le variabili con indice (o array o variabili strutturate) sono un insieme omogeneo e ordinato di dati esono definite mediante la dichiarazione di tipo e di dimensione.

• Quando si dichiara una variabile strutturata il compilatore assegna lo spazio sufficiente per memo-rizzarne tutte le componenti.

• L’allocazione in memoria delle componenti dell’array crea un insieme di locazioni contigue, il cuinumero e definito dalle dichiarazioni di tipo e di dimensione.

La dichiarazione completa (tipo e dimensione) degli array in un programma principale prevede la specificadel tipo e della dimensione. Indicando con tipo1 e tipo2 una parola chiave tra quelle di specifica del tipo(integer, real, ...) come per la dichiarazione di una variabile semplice, in F77 e in F90 la dichiarazionedi variabili con indice si scrive rispettivamente

tipo1 nome1 tipo1, dimension(e1 : e2) :: nome1tipo2 nome2 tipo2, dimension(e3 : e4, e5 : e6) :: nome2dimension nome1(e1:e2),nome2(e3:e4,e5:e6)

dove e1, e2, e3, e4, e5, e6 sono costanti intere o valori interi di espressioni.

• Si ha e1≤e2, e3≤e4 e e5≤e6.

• Se e1 o e3 o e5 sono uguali ad 1, sono opzionali.

Le variabili nome1 e nome2 sono rispettivamente composte da e2–e1+1 e da (e4 –e3+1)· (e6–e5+1)elementi.Se si hanno piu variabili dello stesso tipo (in F77) o dello stesso tipo e stessa dimensione (in F90), questepossono essere elencate nella stessa istruzione dichiarativa separate da virgola.

Si riportano alcuni esempi di specifica di tipo e di dimensione che possono presentarsi nelle istruzionidichiarative di un programma principale:

integer imax integer,parameter::imax=70

parameter(imax=70) real,dimension(100)::a,b

real a, b, x, a1 real,dimension(0:50)::x

real b1 real,dimension(0:imax-1,imax)::a1

integer c real,dimension(10,10)::b1

character*4 car integer,dimension(imax)::c

dimension a(100),x(0:50),c(imax),a1(0:imax-1,imax) character(len=4),dimension(-10,10)::car

dimension b(100),b1(10,10),car(-10:10)

Utilizzando la dichiarazione implicita del Fortran (modificando il nome della variabile intera c in ic),queste stesse istruzioni dichiarative si semplificano in

parameter(imax=70) parameter::imax=70

dimension a(100),x(0:50),a1(0:imax-1,imax) dimension(100)::a,b

character*4 car dimension(0:50)::x

dimension b(100),b1(10,10),car(-10:10) dimension(0:imax-1,imax)::a1

dimension ic(imax) dimension(10,10)::b1

dimension(imax)::ic

character(len=4),dimension(-10,10)::car

Il Fortran permette un’ulteriore semplificazione delle istruzioni dichiarative specificando, nella dichiarazionedi tipo, la dimensione della variabile nel nome. Dunque, queste ultime istruzioni si scrivono

parameter(imax=70) parameter::imax=70

real a(100),x(0:50), a1(0:imax-1,imax) real::a(100),b(100),x(0:50),b1(10,10)

character*4 car(−10 : 10) real::a1(0:imax-1,imax)

real b(100),b1(10,10) integer::ic(imax)

integer ic(imax) character(len=4)::car(-10,10)

10

• In Fortran, come per le variabili semplici, una variabile con indice deve essere dichiarata una voltasola.

• In Fortran, come per le variabili semplici, si possono avere piu di una parola chiave per tipo inun’unita di programma (la parola chiave real nell’esempio).

• In F77 la sequenza di istruzionidimension a(100)

real a

non e corretta; il compilatore segnala una doppia dichiarazione.

• In F90, come per le variabili semplici, per l’assegnazione di variabili con indice, i caratteri :: (duevolte due punti) sono opzionali.

• In F90, come per le variabili semplici, e possibile assegnare valori alle variabili (inizializzare) nelleistruzioni dichiarative. Ad esempio si possono avere le seguenti istruzioni dichiarative

real,dimension(100)::a=0

integer,dimension(0:5)::b=(/0,1,2,3,4,5/)

real,dimension(10,10)::mat=1

che assegnano valori a tutte4 le componenti delle variabili: alle componenti degli array ad unadimensione a e b vengono asssegnati i valori 0 per le componenti a(i) di a con i=1,...,100, e i valori0,1,2,3,4,5 per le componenti b(i) di b con i=0,...,5; agli elementi mat(i,j), i=1,...,5, j=1,...,5,dell’array a due dimensioni mat viene assegnato il valore 1.

Le stesse istruzioni dichiarative per gli array a e b si possono scrivere

real,dimension(100)::a(/0,i=1,100/)

integer,dimension(0:5)::b=(/i,i=0,5/)

real,dimension(10,10)::mat=1

Indirizzo degli elementi dell’array

In Fortran la posizione in memoria del generico elemento v(i) di un array ad una dimensione e a(i,j)di un array a due dimensioni e specificata come segue:

1. si indichi con tipo una parola chiave di specifica di tipo (e.g., real, integer,...), e con l il numerodi bit necessari per un valore di tipo (e.g. l = 32 se tipo e integer o real*4, l = 64 se tipo ereal*8,...);

2. siano le variabili v e a dichiarate, ad esempio con la scrittura in F77, come segue

real v(i0:N)

real a(i0:LD,j0:M)

allora se si indicano conIND[v(i0)] e IND[a(i0,j0)]

gli indirizzi in memoria della prima componente, rispettivamente dell’array v e a, allora gli indirizzi inmemoria delle componenti v(i) e a(i,j) sono

IND[v(i)] = IND[v(i0)] + (i-i0) ∗ lIND[a(i,j)] = IND[a(i0,j0)] + (j-j0)*LD ∗ l + (i-i0) ∗ l

ovvero l’array a di due dimensioni “non esiste”, ma esiste come un “lungo” array colonna di (LD-i0+1)·(M-j0+1)elementi dove gli elementi della seconda colonna (j=2) sono disposti “sotto” quelli della prima (j=1), quellidella terza (j=3) sono “sotto” quelli della seconda (j=2) e cosı via. Ovvero, il Fortran, memorizza idati di un array per colonna. Il valore LD e detto leading.

4In F90 non si puo inizializzare un numero di componenti di un array inferiore al numero delle componenti allocate.

11

Variabili allocabili con indice in F90

Il processo di memorizzazione degli array visto in precedenza in cui si deve specificare quanta memoriabisogna allocare per memorizzare un determinato array, si chiama allocazione statica della memoria.Il F90 prevede anche una allocazione dinamica della memoria.Il programma imposta dinamicamente la dimensione dell’array ogni volta che viene eseguito in mododa essere “sufficientemente grande” per risolvere il problema corrente. In tal modo non c’e spreco dimemoria e consente che il programma sia eseguito da calcolatori che hanno poca o molta memoria diRAM indistintamente.Un array che utilizza la memoria in modo dinamico viene dichiarato allocabile e viene allocato, medianteun’istruzione eseguibile, prima di essere utilizzato.L’istruzione dichiarativa per dichiarare allocabili due array x ed y ad una dimensione e un array a a duedimensioni, ad esempio reali, e la seguente

real, allocatable, dimension(:):: x,y

real, allocatable, dimension(:,:):: a

• i due punti : sono dei segnaposto; non si conosce quanto e grande l’array;5

• array allocabili non possono essere inizializzati ad un valore nell’istruzione dichiarativa;

• un array dichiarato con i due punti : e detto array a forma differita; per contro un array le cuidimensioni sono dichiarate esplicitamente in un’istruzione di dichiarazione e detto array di formaesplicita.

Se si vuole, ad esempio, che la dimensione dell’array x sia 101, con indice delle componenti da 0 a 100,dell’array y sia n, dove n ha un valore calcolato o letto in una precedente istruzione eseguibile e, dell’arraya sia 1000× 1000, allora con le istruzioni eseguibili che dimensionano gli array si scrivono

allocate(x(0:100),stat=infox)

allocate(y(n),stat=infoy)

allocate(a(1000,1000),stat=infoa)

che possono essere scritte anche in una o due istruzioni eseguibili elencando tra le parentesi gli array daallocare, e.g.

allocate(x(0:100),y(n),a(1000,1000),stat=info)

dunque il numero di componenti dell’array con l’indice iniziale e finale viene stabilito mediante un’istruzioneeseguibile. Essi possono essere costanti intere con o senza nome, variabili intere di cui e noto il valore almomento dell’allocazione o, in generale, espressioni che danno come risultato un numero intero.

• La clausola stat= in qualsiasi istruzione allocate, assegna alla variabile intera a destra dell’uguale(nell’esempio a infox o infoy o infoa o info) il valore 0 se l’allocazione ha avuto successo, oppureun valore intero positivo (dipende dal compilatore) se l’allocazione non ha avuto successo, ovverosi richiede troppa memoria rispetto a quella messa a disposizione dal compilatore quando abbiamodichiarato l’array allocabile.

Alla fine del processo in cui si usano array allocabili si “rilascia” la memoria con l’istruzione di “deallo-cazione”; ad esempio se si “dealloca” l’array a, l’istruzione e

deallocate(a,stat=info)

e se la variabile intera info e uguale a zero, allora la “deallocazione” di a ha avuto successo. Se non epresente l’istruzione di “deallocazione”, essa avviene quando si esegue l’istruzione di fine (end).

5Il compilatore riserva un’area di memoria la cui grandezza e sconosciuta al programmatore.

12

Funzioni intrinseche

In Fortran esistono piu di 40 funzioni intrinseche. Sono funzioni intrinseche le funzioni matematicheelementari e le funzioni di conversioni di tipo. Le funzioni intrinseche si scrivono con un designatore difunzione e l’argomento (o gli argomenti separati da virgola) tra parentesi tonde.Si elencano alcune funzioni intrinseche che, in generale, forniscono un risultato del tipo del o degli argo-menti.Per abbreviazione, si indica in tabella con I, R, D, C, Z rispettivamente il tipo intero, reale in precisionesemplice, reale in precisione doppia, carattere e complesso dell’argomento x e del risultato. Ad esempiotra le funzioni matematiche elementari vi sono

funzione tipo dell’argomento tipo del risultato definizione

abs(x) IRDZ IRDR |x|sqrt(x) RDZ RDZ

√x

mod(x,y) I I resto di x/ysign(x) IRD I segno di xexp(x) RDZ RDZ ex

log(x) RDZ RDZ logexlog10(x) RD RD log10xsin(x) RDZ RDZ sinxcos(x) RDZ RDZ cosxtan(x) RD RD tanxasin(x) RD RD arcsinxacos(x) RD RD arccosxatan(x) RD RD arctanxsinh(x) RD RD sinhxcosh(x) RD RD coshxtanh(x) RD RD tanhx

Le funzioni di conversione di tipo sono:

funzione tipo dell’argomento tipo del risultato

int(x) IRD Ireal(x) IRD Rdble(x) IRD Dichar(x) C Ichar(x) I C

e convertono rispettivamente l’argomento in numero intero (si considera la parte intera dell’argomento),in reale in precisione semplice, in reale in precisione doppia, nell’intero corrispondente al codice ASCIIdell’argomento carattere e nel carattere ASCII del corrispondente valore intero dell’argomento.

In Fortran l’argomento di una funzione puo essere una costante, una variabile, un’espressione o anche ilrisultato di un’altra funzione. Ad esempio sono valide le seguenti istruzioni di assegnazione alla variabiley del valore della funzione sin:

y=sin(3.141593)

y=sin(x)

y=sin(pi*x)

y=sin(sqrt(x))

13

Istruzione di elaborazione di espressioni

In Fortran un’istruzione di elaborazione di un’espressione si scrive nel modo seguente

x =espressione

ovvero il risultato dell’espressione a destra del segno uguale viene assegnato alla variabile x a sinistra delsegno uguale. In Fortran si hanno le seguenti

• espressione aritmetica:

– operatori aritmetici+ − ∗ / ∗ ∗

– operandi aritmetici sono le espressioni aritmetiche.

Definizione di espressione aritmetica:6

1. ogni variabile IRDZ e un’espressione aritmetica, rispettivamente IRDZ;

2. ogni costante, con o senza nome, IRDZ e un’espressione aritmetica, rispettivamente IRDZ;

3. ogni funzione intrinseca con risultato IRDZ e un’espressione aritmetica rispettivamenteIRDZ;

4. se X e un’espressione aritmetica, anche (X) e un’espressione aritmetica;

5. se X ed Y sono due espressioni aritmetiche, anche X + Y , X − Y , X ∗ Y , X/Y e X ∗ ∗Ysono espressioni aritmetiche;

6. se applichiamo un numero finito di volte le regole 1–5 si ottiene un’espressione aritmetica;

– priorita: parentesi piu interne fino alle piu esterne, valutazione di funzioni, elevamento apotenza, divisione/moltiplicazione, addizione/sottrazione. A parita di livello di parentesi, leoperazioni si svolgono da sinistra verso destra tranne l’elevamento a potenza che si svolge dadestra verso sinistra;

– espressione aritmetica tra operandi di tipo diverso7

x I I I R R Dy I R D R D D

x⊗ y I R D R D D

Si osservi il risultato delle seguenti istruzioni, supponendo di usare la dichiarazione implicitadi variabili:

i=2/3 risultato: i=0i=2./3 risultato: i=0x=2/3 risultato: x=0x=2./3 risultato: x=0.6i=2; j=3; x=i/j risultato: x=0i=2; j=3; x=real(i)/j risultato: x=0.6

• espressione relazionale:

– operatori relazionali

.lt. .le. .eq. .ne. .ge. .gt. in F77

< <= == /= >= > in F90

– operandi relazionali sono le espressioni aritmetiche.

– Il risultato di un’espressione relazionale e un valore logico.

6Per abbreviazione, si indica con I, R, D, Z rispettivamente il tipo intero, reale in precisione semplice, reale in precisionedoppia e complesso.

7Con il simbolo ⊗ si indica un qualsiasi operatore aritmetico.

14

• espressione logica:

– operatori logici.and. .or. .not. .eqv. .xor.

– operandi logici sono le espressioni logiche.

Definizione di espressione logica:8

1. ogni variabile di tipo logico e un’espressione logica;

2. ogni costante con o senza nome di tipo logico e un’espressione logica;

3. ogni espressione relazionale e un’espressione logica;

4. se X e un’espressione logica, anche (X) e un’espressione logica;

5. se X ed Y sono due espressioni logiche, anche X opl Y e un’espressione logica;

6. se applichiamo un numero finito di volte le regole 1–5 si ottiene un’espressione logica.

– priorita: parentesi piu interne fino alle piu esterne, operatori aritmetici, operatori relazionali,.not., .and., .or., .eqv./.xor..

Istruzione di salto incondizionato

L’istruzione eseguibile di salto incondizionato in Fortran si scrive con la parola chiave go to oppuregoto seguita da un’etichetta che sottointende all’istruzione eseguibile successiva. Ad esempio l’istruzione

goto 10

rimanda all’istruzione etichettata con 10.

Istruzione di salto condizionato

In Fortran e presente l’istruzione di salto condizionato altrimento detta di if aritmetico. Questaistruzione si scrive

if(E)l1, l2, l3

dove E indica un’espressione aritmetica ed l1, l2 ed l3 sono tre etichette.

• Se l’espressione E assume un valore negativo allora si “salta” all’istruzione con etichetta l1.

• Se l’espressione E assume un valore nullo allora si “salta” all’istruzione con etichetta l2.

• Se l’espressione E assume un valore positivo allora si “salta” all’istruzione con etichetta l3.

◦ Se, ad esempio l1 = l2, allora si “salta” all’istruzione con etichetta l1 se l’espressione E e minore ouguale a 0.

◦ Se l1 = l2 = l3, l’istruzione e equivalente all’istruzione di salto incondizionato goto l1

Ad esempio, supponendo che x e y siano due variabili e 10, 20, 30 siano tre etichette, un’istruzione disalto condizionato e la seguente:

if(x-y)10,20,30

Istruzione di arresto

L’istruzione eseguibile di arresto in Fortran si scrive con la parola chiave stop. Questa istruzione non vaconfusa con l’istruzione di fine programma (end) che non e un’istruzione eseguibile. Ci possono essere piuistruzioni eseguibili di arresto stop ma, per ogni unita di programma ci deve essere una sola istruzionedi fine programma end.Se un’istruzione di arresto non e presente nel programma, il programma si arresta quando trova l’istruzionedi fine programma end.

8Si indica con opl un qualsiasi operatore logico.

15

Istruzione di condizione

In Fortran e prevista l’istruzione di condizione o di if logico. Se si indica con C un’espressione logical’istruzione di condizione ha la forma

if (C) thenistruzione/i

endif

oppureif (C) then

istruzione/i 1else

istruzione/i 2endif

Nel primo caso (costrutto if–then) si eseguono le istruzioni se l’espressione logica C e vera, nel secondocaso (scelta dicotomica o costrutto if–then–else) si eseguono le istruzioni 1 se l’espressione logicaC e vera e le istruzioni 2 se l’espressione logica C e falsa.Nel caso in cui ci sia una sola istruzione da eseguire se l’espressione logica C e vera, in Fortran si prevedeanche la scrittura dell’istruzione di condizione in un’unica riga (istruzione di if)

if (C) istruzione

In Fortran vi e anche il costrutto elseif che si presenta nella seguente forma9

if (C1) thenistruzione/i 1

elseif (C2) thenistruzione/i 2else

istruzione/i 3endif

Il risultato e l’esecuzione dell’istruzione/i 1 se C1 e vera, dell’istruzione/i 2 se C1 e falsa e C2 e vera edell’istruzione/i 3 se C1 e C2 sono entrambe false.Il costrutto si puo ampliare introducendo altre condizione di elseif. Ad esempio

if (C1) thenistruzione/i 1

elseif (C2) thenistruzione/i 2

elseif (C3) thenistruzione/i 3else

istruzione/i 4endif

In tal caso l’istruzione/i 1 e eseguita se C1 e vera, l’istruzione/i 2 e eseguita se C1 e falsa e C2 e vera,l’istruzione/i 3 e eseguita se C1 e C2 sono false e C3 e vera e l’istruzione/i 4 e eseguita se C1, C2 e C3sono false.

Le parole if, then, else, elseif e endif sono parole chiave.

9Si indicano con C1, C2 e C3 tre differenti espressioni logiche.

16

L’istruzione continue in F77

L’istruzione continue presente in F77, costituita dalla sola parola continue su una riga

continue

permette di evidenziare un punto del programma; essa ha il solo effetto di far proseguire sequenzialmentel’esecuzione del programma.Si puo verificare che il costrutto if–then–else puo essere ottenuto mediante le istruzioni if, goto econtinue.continue e una parola chiave.

Il ciclo do

Il ciclo do (do–loops) e il costrutto del linguaggio Fortran per eseguire una o piu istruzioni (nucleo delciclo) un numero di volte noto a priori.

Se si indica con l un’etichetta, il ciclo do in F77 ha la seguente forma

do l, c = e1, e2, e3istruzione/i

l continue

Il ciclo do in F90 ha la seguente forma (costrutto do–enddo)

do c = e1, e2, e3istruzione/i

enddo

dove, in Fortran:

• do e enddo sono parole chiave;

• c e la variabile contatore, preferibilmente intera;

• e1 e una variabile, una costante o, in generale, un’espressione aritmetica, preferibilmente intera,che indica il valore di inizio ciclo ed e il primo valore che assume il contatore c;

• e2 e una variabile, una costante o, in generale, un’espressione aritmetica, preferibilmente intera,che indica il valore di fine ciclo;

• e3 e una variabile, una costante o, in generale, un’espressione aritmetica, preferibilmente intera ecomunque non nulla, che indica il valore del passo del ciclo. E opzionale se uguale ad 1.

Il nucleo del ciclo viene eseguito per ogni valore del contatore c che varia da e1 a e2 con passo e3.

◦ Se e3 e positivo, le istruzioni che costituiscono il nucleo del ciclo sono eseguite se e2≥e1.

◦ Se e3 e negativo (ciclo a ritroso), le istruzioni che costituiscono il nucleo del ciclo sono eseguite see1≥e2.

Per quanto concerne le regole del ciclo sopra descritto:

• non e possibile modificare il valore della variabile contatore c o di e1 o di e2 o di e3 medianteun’istruzione del nucleo del ciclo;

• non e possibile “saltare dentro al ciclo” ad un’istruzione etichettata del nucleo del ciclo mediantel’istruzione (fuori dal ciclo) di salto incondizionato goto;

17

• e possibile “uscire” dal ciclo mediante un’istruzione di condizione e di salto incondizionato (o diarresto) presenti nel nucleo del ciclo (ciclo incompleto).

In F77:

• la virgola dopo l’etichetta l e opzionale;

• e possibile omettere l’istruzione continue, mettendo l’etichetta l sull’ultima istruzione del ciclo:

do l, c = e1, e2, e3istruzione 1...

l istruzione k

• l’etichetta l non puo stare su una linea di codice di do, goto, if, elseif, endif, return, stop eend;

• vi sono casi in cui e necessaria l’istruzione continue. Ad esempio, se C e un’espressione logica,

do l, c = e1, e2, e3istruzione 1...

if (C) goto l...

istruzione kl continue

non e infatti possibile scrivere il ciclo nel modo seguente

do l, c = e1, e2, e3istruzione 1...

if (C) continue...

istruzione kl continue

Deve presentarsi una sola istruzione continue per ogni do;

• i compilatori piu recenti del F77 riconoscono il ciclo do con il costrutto do–enddo.

In Fortran c’e la possibilita di fare cicli annidati (nested) a due o piu indici. Ad esempio in F90 unciclo annidato a due indici ha la forma

do i = i1, i2, i3istruzione/i 1do j = j1, j2, j3istruzione/i 2

enddo

enddo

In F77 un ciclo annidato puo avere la seguente forma

do 10, i = i1, i2, i3istruzione/i 1do 20, j = j1, j2, j3istruzione/i 2

20 continue

10 continue

18

• Le etichette 10 e 20 possono sottointendere anche le ultime istruzioni del corpo del ciclo di i e delciclo j rispettivamente.

• E errato “chiudere” prima il ciclo esterno di quello interno; ovvero non e corretto

do 10, i = i1, i2, i3istruzione/i 1do 20, j = j1, j2, j3istruzione/i 2

10 continue

20 continue

Questo errore e evitato se si usa il costrutto do–enddo.

• Se, come in questo esempio, non vi sono istruzioni tra le due istruzioni continue che chiudono idue cicli interno ed esterno, allora si puo scrivere

do 10, i = i1, i2, i3istruzione/i 1do 10, j = j1, j2, j3

istruzione/i 210 continue

oppure

do 10, i = i1, i2, i3istruzione/i 1do 10, j = j1, j2, j3istruzione/i 2

10 ultima istruzione 2

Il ciclo while

Il ciclo while (while–loops),

mentre la condizione e vera esegui le istruzioni

e un ciclo in cui non e noto a priori quante volte si devono eseguire una o piu istruzioni.In Fortran il ciclo while si puo “simulare” con il costrutto if–then e l’istruzione goto.Se si indica con C un’espressione logica e con l un’etichetta, si hanno le istruzioni

l if (C) then

istruzione/igoto l

endif

Il ciclo until

Il ciclo until (until–loops),

ripeti le istruzioni finche la condizione non diventa vera

e un ciclo in cui non e noto a priori quante volte si devono eseguire una o piu istruzioni.In Fortran il ciclo until si “simula” con il costrutto if–then e l’istruzione goto.Se si indica con C un’espressione logica e con l un’etichetta, si hanno le istruzioni

l prima istruzionealtra/e istruzione/iif (.not. C) goto l

19

Istruzioni di lettura e scrittura

In Fortran le istruzioni di lettura e di scrittura si implementano con le parole chiave read e write seguitedalle variabili o dalle costanti o in generale dalle espressioni, separate da virgola, che si vogliono scriveree leggere.Le istruzioni di lettura e di scrittura si scrivono rispettivamente

read(*,*) write(*,*)

• il primo asterisco * specifica che l’unita di ingresso (lettura) o di uscita (lettura) e quella di default;cioe la tastiera per unita di ingresso e il video per unita di uscita;

• il secondo asterisco * indica che il formato per leggere o per scrivere utilizzato e quello di default,ovvero il formato libero.

Il do implicito

In Fortran e possibile per la lettura o la scrittura di array il do implicito.Ad esempio si suppone di dover scrivere l’array

x =

123

la scrittura, ad esempio in F90,

do i=1,3

write(*,*) x(i)

enddo

visualizza123

mentre la scrittura Fortran

write(*,*) (x(i),i=1,3) visualizza 1 2 3

Se si suppone di dover scrivere l’array bidimensionale

a =

1 2 34 5 67 8 9

La scrittura, ad esempio in F90,

do i=1,3

do j=1,3

write(*,*) a(i,j)

enddo

enddo

visualizza

123456789

mentre la scrittura, ad esempio in F90,

do i=1,3

write(*,*)(a(i,j),j=1,3)

enddo

visualizza1 2 34 5 67 8 9

ed ancora la scrittura in Fortran

write(*,*) ((a(i,j),j=1,3),i=1,3) visualizza 1 2 3 4 5 6 7 8 9

L’istruzione read segue la stessa sequenza di dati come per l’istruzione write, ad eccezione che, quando idati sono introdotti direttamente da tastiera, puo essere premuto il tasto invio (tasto enter) opzionalmentedopo l’ingresso di ogni dato.

20

Il ridirezionamento dei dati in ingresso e in uscita

In Fortran e possibile ridirezionare i dati in lettura e in scrittura, quando questi sono letti dall’unita didefault mediante i sistemi operativi windows dal prompt dei comandi o unix/linux dalla linea di comandodel terminale.Ad esempio se il file eseguibile esempio e il file compilato del file Fortran esempio.f in cui sono presentile seguenti istruzioni di lettura e di scritura da e su l’unita di default

read(*,*)n

read(*,*)(x(i),i=1,n)

write(*,*)’matrice da vettore’

do i=1,n

write(*,*)(x(i)*x(j),j=1,n)

enddo

allora, il comando eseguito dal prompt dei comandi o dalla linea di comando del terminale

esempio<in>out

prevede che esista un file di dati che abbiamo chiamato in10 contenente, ad esempio dei dati disposti inquesto modo e con questi valori

31 0 2

e produce un file di dati che abbiamo chiamato out in cui c’e scritto

matrice da vettore

1 0 20 0 02 0 4

Se il file di dati in non e stato creato, l’esecuzione di esempio non puo avvenire.E ovviamente possibile produrre solo un file di uscita dati inserendo i dati in lettura da tastiera come in

esempio>out

oppure inserire i dati di ingresso da file e visualizzare i dati di uscita su video come in

esempio<in

10Ovviamente il nome del file di ingresso dati e del file di uscita dati e scelto dal programmatore.

21

Lettura e scrittura mediante file

In Fortran e possibile leggere e scrivere dati da e su file con istruzioni eseguibili dell’unita di programmae non soltanto da sistema operativo. E necessario in questo caso “aprire il file” e questo avviene conl’istruzione open.L’istruzione eseguibile open si scrive nel modo seguente:

open(unit=..., file=..., status=..., form=..., action=..., access=..., iostat=...)

dove soltanto unit e file sono obbligatori.Al posto dei puntini ...:

• unit=numero intero positivo; e.g. unit=8

I numeri 5 e 6 indicano la tastiera e il video, i.e. read(5,*) e read(*,*) indicano la stessa unitadi ingresso dati e write(6,*) e write(*,*) indicano la stessa unita di uscita dati;

• file=nome del file. Ad esempio se chiamiamo out il file su cui vogliamo scrivere i risultati allora

file=’out’

Se il nome del file e una variabile carattere, ad esempio in F90

character(len=10)::dati

allorafile=dati

• status=’old’ se il file specificato dal nome esiste gia;

status=’new’ se il file specificato dal nome non esiste11;

status=’unknown’ se non e noto se esiste il file specificato dal nome12; se non e specificato lo statodel file allora il file si considera unknown;

status=’replace’ se si vuole aprire un nuovo file (di uscita) con il nome specificato o se tale fileesiste, sostituirlo;

status=’scratch’ se si vuole creare un file temporaneo da eliminare quando si “chiude” il file.13.Se si usa la clausola status=’scratch’ non si deve specificare la clausola action=.

• form=’formatted’ se il file e formattato (leggibile) altrimenti la clausola e form=’unformatted’.Per file non formattati le istruzioni di lettura e scrittura da e su file14 si scrivono

read(8)x,y,z write(8)x,y,z

Se non si specifica se il file e formattato o meno, il file viene considerato formattato.

• action=’read’ se il file e di sola lettura;

action=’write’ se il file e di sola scrittura;

action=’readwrite’ se il file e di lettura e scrittura. Se non e specificato se il file e di lettura oscrittura si considera sia di lettura che di scrittura.

• access=’sequential’ se il file viene esaminato sequenzialmente (questa e anche la procedura senon e specificato diversamente nella clausola di accesso al file); access=’direct’ se l’accesso al filee diretto.

11Ovviamente si intende un file non esistente nel direttorio in cui si esegue il file eseguibile. Se il file specificato dal nomeesiste allora viene segnalato errore in esecuzione.

12Se il file esiste allora status=’unknown’ e come status=’old’, se il file non esiste e come status=’new’.13Utile quando si vogliono salvare risultati intermedi ma non per registare dati che devono essere salvati alla fine del

programma.14Si suppone, ad esempio, che nell’istruzione open si sia posto unit=8.

22

• iostat=variabile intera; il valore della variabile intera e 0 se l’apertura del file ha avuto successo,altrimenti la variabile assume un valore diverso da zero15.

L’istruzione di chiusura del file eclose(...)

dove al posto dei puntini c’e il numero intero positivo specificato nella clausola unit=.Se l’istruzione close non e presente, il file si chiude quando trova l’istruzione di fine programma end.

Si possono aprire contemporaneamente piu file, purche diversi, ovvero con diversa clausola file=.

Ad esempio si vuole leggere dei dati dal file che si chiama in e scrivere i dati elaborati su un file chechiamiamo out. Il file in ha, ad esempio, questa disposizione di valori

31 0 2

Nel punto dell’unita di programma Fortran in cui si vuole leggere i dati si “apre” il file in e si scrivonole seguenti istruzioni eseguibili

open(unit=8,file=’in’,status=’old’,form=’formatted’,action=’read’,access=’sequential’,iostat=ierr)

read(8,*)n

read(8,*)(x(i),i=1,n)

if(ierr.ne.0)stop

close(8)

Quando si vogliono scrivere i dati sul file out, successivamente alle istruzioni di lettura del file in, allorasi scrivono le seguenti istruzioni eseguibili

open(unit=8,file=’out’,status=’new’,form=’formatted’,action=’write’,access=’sequential’,iostat=ierr)

write(8,*)’matrice da vettore’

do i=1,n

write(8,*)(x(i)*x(j),j=1,n)

enddo

if(ierr.ne.0)stop

close(8)

Il file out risulta esserematrice da vettore

1 0 20 0 02 0 4

15Il valore diverso da zero dipende dal compilatore.

23

L’istruzione format

In Fortran, la lettura o la scrittura dei dati con formato puo essere fatta mediante la specifica di formatonell’istruzione read o write oppure mediante l’istruzione eseguibile format.Ci limitiamo ad alcuni esempi.

• Sono equivalenti i seguenti segmenti di programma supponendo di utilizzare la dichiarazione im-plicita del Fortran.

read(*,’2I6’)i,j read(*,100)i,j

read(*,’3I6’)i1,12,i3 read(*,200)i1,12,i3

read(*,’2I6’)ip,jp read(*,100)ip,jp

100 format(2I6)

200 format(I6,I6,I6)

3I6, sia interno all’istruzione read che nell’istruzione format, significa che vengono letti tre (3)numeri interi (I) ciascuno che occupa sei (6) caratteri, incluso il segno. Se il numero occupa menodi 6 caratteri, esso viene scritto da destra lasciando spazi bianchi per il completamento dei caratteri.Si osserva che il numero -123456 non puo essere letto con tale formato. Analogamente se si usal’istruzione write.

• I numeri reali possono essere letti o scritti sia in forma posizionale (fixed) che esponenziale.

read(*,10)x,y

read(*,20)u,v

10 format(F7.1,F6.3)

20 format(E9.1,E103)

I numeri reali x e y sono scritti in “forma fissa” ed occupano rispettivamente 7 caratteri (incluso ilsegno16 e il punto radice) di cui 1 per la cifra dopo il punto radice e sei caratteri (incluso il segno eil punto radice) di cui 3 dopo il punto radice.

Ad esempio valori di x e y che rispettano i campi stabiliti dal formato sono

−123.4 12.456

In generale la forma Fi.j dovrebbe soddisfare i≥j+2 perche uno spazio ciascuno si deve riservareal punto radice e all’eventuale segno. La scrittura F.j indica che non si specificano caratteri pervalori a sinistra del punto radice, i.e., si intendono leggere o scrivere valori come 0.123.

I numeri reali u e v sono scritti in “forma esponenziale” ed occupano rispettivamente 9 caratteri dicui 1 per una cifra dopo il punto radice e 10 caratteri di cui 3 per tre cifre dopo il punto radice. Trai 9 e i 10 caratteri si deve tenere conto dell’eventuale segno e dei 4 caratteri della parte esponenzialeeSXX dove S indica il carattere riservato al segno e XX sono due cifre da 0 a 38. Ad esempio valoridi u e v che rispettano i campi stabiliti dal formato sono

−123.4e− 2 123.456e2

Allora in generale la forma Ei.j dovrebbe soddisfare i≥j+5.Nel caso di lettura o scrittura di numeri in precisione doppia, la notazione esponenziale diventa, adesempio, D9.1; in questo caso la forma Di.j dovrebbe soddisfare i≥j+6.Le stesse istruzioni possono essere incluse all’interno dell’istruzione read o write, se le variabili daleggere o da scrivere elencate successivamente all’istruzione stessa sono dello stesso tipo e soggetteallo stesso formato.

16Se positivo e ovviamente opzionale.

24

• I valori di tipo carattere possono essere letti o scritti, ad esempio, nel modo seguente

read(*,10)c

10 format(A8)

dove la variabile carattere c deve avere al massimo 8 caratteri.

• Nei formati di scrittura sono possibili caratteri come / che causa una linea bianca di stampa, oppureun numero naturale dopo il carattere X, e.g., 1X o 10X che indica che deve essere saltato un certonumero di spazi (nell’esempio, uno o dieci spazi); ad esempio

write(*,101)

write(*,100)x,y,i

101 format(1X,’calcolo eseguito’)

100 format(2X,’x= ’,F8.3,2X,’y= ’,F.4,2X,’i= ’,I5)

L’istruzione eseguibile format puo trovarsi in qualsiasi punto dell’programma. In generale tutte leistruzioni �format sono posizionate in fondo al programma prima dell’istruzione di fine programma end.

25

Operazioni globali su array in F90

In F90 e possibile eseguire operazioni su variabili con indice come se fossero operazioni su variabilisemplici.Ad esempio si scrivono le seguenti istruzioni dichiarative per array ad una e a due dimensioni e per scalari.Gli array ad una dimensione devono avere la stessa lunghezza e gli array a due dimensioni devono averelo stesso numero di righe e lo stesso numero di colonne:

integer,parameter::na=100,nx=30

real,dimension(na,na)::a,b,c

real,dimension(nx)::x,y,z

real ::s

sono possibili le seguenti istruzioni eseguibile che svolgono operazioni globali:

y=s*x e equivalente ado i=1,nx

y(i)=s*x(i)

enddo

y=s+x e equivalente ado i=1,nx

y(i)=s+x(i)

enddo

b=s*a e equivalente a

do i=1,na

do j=1,na

b(i,j)=s*a(i,j)

enddo

enddo

b=s+a e equivalente a

do i=1,na

do j=1,na

b(i,j)=s+a(i,j)

enddo

enddo

z=x+y e equivalente ado i=1,nx

z(i)=x(i)+y(i)

enddo

c=a+b e equivalente a

do i=1,na

do j=1,na

c(i,j)=a(i,j)+b(i,j)

enddo

enddo

In F90 molte funzioni intrinseche che sono utilizzate con valori scalari accettano anche gli array comeargomenti di ingresso e restituiscono un array in uscita.Ad esempio, se x e un array, allora sin(x) restituisce un array delle dimensioni di x avente per componentiil valore della funzione seno calcolata nella corrispondente componente dell’array x; i.e., se x e un arrayad una dimensione, la i–esima componente dell’array sin(x) e sin(x(i)).

Si nota che la scrittura write(*,*)x o write(*,*)a, dove si suppone che la variabile x sia un arrayad una dimensione e a sia un array a due dimensioni, comporta la stampa “per colonna” di tutti glielementi dell’array.Analogamente con read(*,*)x o read(*,*)a vengono letti “per colonna” gli elementi degli array.

26

Indicizzazione di array con triplette in F90

Nelle istruzioni esguibili in F90 e possibile indicare le componenti di un array17 ad una dimensione nonsoltanto con un solo indice x(i) ma anche con una tripletta di indici.Ad esempio le scritture x(1:5:2) e x(1:4) indicano che si stanno considerando rispettivamente le com-ponenti x(1), x(3) e x(5) per la prima scrittura e le componenti x(1), x(2), x(3) e x(4) per la secondascrittura.Dunque, se si suppone che la variabile con indice x sia dichiarata nel modo seguente

integer,parameter::nx=100

real,dimension(nx)::x

la scrittura

x(i1:i2:i3) indica che si considerano le componenti con indice da i1 a i2 con passo i3

x(i1:i2) indica che si considerano le componenti con indice da i1 a i2 con passo 1x(i1:) indica che si considerano le componenti con indice da i1 a nx

x(i1::i3) indica che si considerano le componenti con indice da i1 a nx con passo i3

x(:i2) indica che si considerano le componenti con indice da 1 a i2 con passo 1x(:i2:i3) indica che si considerano le componenti con indice da 1 a i2 con passo i3

x(:) indica che si considerano le componenti con indice da 1 a nx con passo 1x(::i3) indica che si considerano le componenti con indice da 1 a nx con passo i3

17Sia che esse siano utilizzate in espressioni e sia che esse siano variabili a cui assegnare il valore di un’espressione.

27

Altre istruzioni di F90

Le istruzioni cycle ed exit

In F90 sono presenti le istruzioni cycle ed exit. Ne vediamo il loro signifato con un esempio diprogramma.Esempio per l’istruzione cycle (si usa la dichiarazione di tipo implicita del Fortran):

program testcycle

do i=1,5

if(i==3)cycle

write(*,*) i

endddo

write(*,*)’fine ciclo’

stop

end program testcycle

L’esecuzione di questo programma scrive

1245fine ciclo

Esempio per l’istruzione exit (si usa la dichiarazione di tipo implicita del Fortran):

program testexit

do i=1,5

if(i==3)exit

write(*,*) i

endddo

write(*,*)’fine ciclo’

stop

end program testexit

L’esecuzione di questo programma scrive

12fine ciclo

• L’istruzione exit all’interno di un ciclo do arresta il ciclo; da non confondere con l’istruzione diarresto stop che invece arresta l’intero programma.

28

L’istruzione select case

In F90 e presente il costrutto di select case. Il costrutto ha la seguente forma:

nome: select case(E)case (selettore1)istruzioni 1case (selettore2)istruzioni 2...case default

altre istruzioniend select case nome

• Con E si indica un’espressione aritmetica.

• Se il valore dell’espressione aritmetica E e compreso nell’intervallo del selettore 1 allora si eseguonole istruzioni 1, se e compreso nell’intervallo del selettore 2 allora si eseguono le istruzioni 2 e cosıvia; se il valore di E non e con e compreso in nessun intervallo specificato dai selettori allora e il“caso default” e si eseguono le altre istruzioni.

• Il bloccocase default

altre istruzioni

e opzionale; se il valore dell’espressione aritmetica E non e compreso in nessun intervallo specificatodai selettori e non e presente il “blocco di default” allora il costrutto select case non vieneeseguito.

• Il nome del costrutto select case e opzionale.

Esempio 1 (si usa la dichiarazione di tipo implicita del Fortran):

select case(itemp)

case (:-1)

write(*,*)’valore ’’temp’’ minore di -1 ’

case (0)

write(*,*)’valore ’’temp’’ nullo ’

case (1:20)

write(*,*)’valore ’’temp’’ da 1 a 20 ’

case (21:)

write(*,*)’valore ’’temp’’ maggiore di 21 ’

end select case

Esempio 2 (si usa la dichiarazione di tipo implicita del Fortran):

select case(ivalore)

case (1,3,5,7,9)

write(*,*)’valore dispari da 1 a 10 ’

case (2,4,6,8)

write(*,*)’valore pari da 1 a 10 ’

case (11:)

write(*,*)’valore maggiore di 11 ’

case default

write(*,*)’valore negativo ’

end select case

29

Il ciclo do con nome

In F90 c’e la possibilita di assegnare un nome al ciclo do inserendo il nome seguito da : (due punti) primadella parola chiave do e dopo la parola chiave enddo. Con un esempio di un segmento di programma sene vede l’utilita.Se scrivo

do i=1,3

do j=1,3

if(j==2)cycle

ij=i*j

write(*,*)i,j,ij

enddo

enddo

come per l’esempio dell’istruzione cycle, il segmento di programma fornisce la scrittura

1 1 11 3 32 1 22 3 63 1 33 3 9

Se, ad esempio, si assegna un nome al ciclo esterno

esterno: do i=1,3

do j=1,3

if(j==2)cycle esterno

ij=i*j

write(*,*)i,j,ij

enddo

enddo esterno

allora si ha la scrittura di1 1 12 1 23 1 3

30

Il ciclo while/until in F90

In F90 e possibile scrivere il ciclo while o il ciclo di until utilizzando l’istruzione exit nel blocco diistruzioni comprese tra do ed enddo nel modo seguente:

do

istruzioni 1if(E) exit

istruzioni 2enddo

dove E e un’espressione logica. Le istruzioni 1 e le istruzioni 2 vengono eseguite finche l’espressione E efalsa. Se, dopo l’esecuzione delle istruzioni 1, l’espressione logica E diventa vera, allora si esegue, comeistruzione successiva, quella scritta sotto enddo.

Il costrutto do while

In F90 e possibile utilizzare il costrutto do while per la costruzione del ciclo while. Il costrutto do whileha la seguente forma:

do while (E)istruzione 1...istruzione kenddo

Se l’espressione logica E e vera, le istruzioni (istruzione 1,..., istruzione k) vengono eseguite; dopol’istruzione enddo si esegue l’istruzione do while e se l’espressione logica E e ancora vera, vengonoeseguite nuovamente le istruzioni (istruzione 1,..., istruzione k). Questo processo viene eseguito fino aquando l’espressione logica E diventa falsa; in tal caso la successiva istruzione da eseguire e quella scrittanella riga sotto enddo.Questo costrutto e meno flessibile del costrutto

do

...if(E) exit

...enddo

in quanto l’istruzione di condizione deve essere posizionata come prima istruzione del ciclo.

31

Il costrutto e l’istruzione where

In F90 e possibile assegnare dei valori ad un array mediante una maschera. Ad esempio, siano a e b duearray bidimensionali dichiarati nel modo seguente

integer, parameter::nd1=100, nd2=200

real, dimension(nd1,nd2) :: a,b

Supponiamo che siano stati assegnati dei valori reali a tutte le componenti dell’array a. Si vuole calcolarel’array b le cui componenti abbiano valore uguale alle rispettive componenti di a se queste sono positive,oppure siano nulle se le rispettive componenti di a sono nulle o negative. Questo si esegue con il segmentodi programma seguente

do i=1,nd1

do j=1,nd2

if(a(i,j) > 0) then

b(i,j)=a(i,j)

else

b(i,j)=0

endif

enddo

enddo

Queste istruzioni in F90 possono essere sostituite dal costrutto where definito nel modo seguente

nome: where(E1)istruzioni 1elsewhere(E2) nomeistruzioni 2...elsewhere nomealtre istruzioniend where nome

• E1, E2, ... sono array logici della stessa dimensione dell’array da “manipolare”;

• il nome del costrutto e opzionale.

Nell’esempio, il costrutto where si scrivewhere(a>0)

b=a

elsewhere

b=0

end where

Se nell’esempio l’array b e “inizializzato” a zero (ad esempio nell’istruzione dichiarativa), il costruttowhere puo essere sostituito dall’istruzione where nel modo seguente

where(a>0) b=a

32

Il costrutto forall

In F90 e possibile il costrutto forall cosı definito:

nome: forall (i1=n1:m1:l1, i2=n2:m2:l2, ..., E)istruzione 1...istruzione kend forall nome

oppure, se si deve eseguire una sola istruzione

forall (i1=n1:m1:l1, i2=n2:m2:l2, ..., E)istruzione

• i1, i2, ... sono contatori (variabili intere) che variano rispettivamente da n1, n2,... a m1, m2,... conpasso l1, l2,...; i passi sono opzionali se valgono 1.

• E e un’espressione logica; l’espressione logica puo essere opzionale.

Ad esempio, sia a un array bidimensionale dichiarato nel modo seguente

integer, parameter::nd1=100, nd2=200

real, dimension(nd1,nd2) :: a

e si suppone che siano stati assegnati dei valori reali a tutte le componenti dell’array a. Si vuole sovrascri-vere sull’elemento a(i,j) con valore diverso da zero, il suo valore reciproco. Questo calcolo si puo eseguirecon un ciclo do nel modo seguente

do i=1,nd1

do j=1,nd2

if(a(i,j) /= 0)

enddo

enddo

Lo stesso risultato lo si puo ottenere con l’istruzione forall

forall (i=1:nd1, j=1:nd2, a(i,j)/=0) a(i,j)=1.0/a(i,j)

Il ciclo do elabora gli elementi nell’ordine stabilito dal ciclo o dai cicli se essi sono annidati. Il costruttoforall elebora gli elementi nell’ordine selezionato dal processore. Ad esempio, siano a e b due arraybidimensionali e siano stati assegnati valori non nulli agli elementi a(i,j) per i e j a valori da 1 ad n,con n variabile assegnata. Le istruzioni

forall (i=1:n, j=1:n)

a(i,j)=sqrt(a(i,j))

b(i,j)=1.0/a(i,j)

end forall

comportano che tutti i valori a(i,j), (i.e., a(1,1),...,a(n,n)) vengono calcolati prima di calcolare ilprimo elemento b(1,1).

I puntatori

In F90 e possibile definire un puntatore, ovvero una variabile contenente nessun dato ma indirizzi dimemoria di un’altra variabile dove sono memorizzati i dati. Si veda per una trattazione delle variabilipuntatori il Cap. 11 del libro di Chapman, Fortran 90/95: Guida alla Programmazione, McGraw–Hill,2004.

33

Il sottoprogramma function

In Fortran sono possibili i sottoprogrammi funzione (function).Sottoprogrammi funzione sono le funzioni intrinseche del linguaggio e le funzioni definite dall’utente.Sia funz una funzione definita dall’utente.

Il nome della funzione e una variabile e contiene il valore della funzione stessa.

La funzione funz ha una definizione come segue:

tipo function funz(argomenti separati da virgola)istruzioni dichiarativeistruzione eseguibile 1...istruzione eseguibile kfunz=espressionereturn

end

Supponiamo che la funzione funz sia di tipo reale e che gli argomenti della funzione funz siano le variabilix, y e z. La prima istruzione della funzione si scrive allora

real function funz(x,y,z)

oppure, utilizzando la dichiarazione implicita del Fortran

function funz(x,y,z)

Il programma principale (in generale un’unita di programma) si avvale della function funz medianteun’istruzione eseguibile come

y=funz(a,s,x)

dove a, s e x sono tre variabili allocate.L’argomento x della function funz “legge” il valore memorizzato nel programma principale dalla varia-bile a, l’argomento y della function funz “legge” il valore memorizzato nel programma principale dallavariabile s e l’argomento z della function funz “legge” il valore memorizzato nel programma principaledalla variabile x.Gli unici dati memorizzati sono quelli del programma principale, gli argomenti x, y e z della function

funz e in generale di un sottoprogramma, sono parametri formali che leggono, utilizzano ed eventualmentemodificano le aree di memoria dove sono memorizzati i dati ai quali vengono indirizzati con la “chiamata”alla funzione o al sottoprogramma.Una function e in generale un sottoprogramma puo essere chiamato dall’unita di programma chiamantepiu di una volta con dati diversi. Ad esempio sono valide le chiamate

...y1=funz(x,5,4*atan(1))

...y=funz(y,y,z)

• Gli argomenti separati da virgola sono le variabili globali della function;

• gli argomenti possono essere di tipo e di dimensioni diversi tra di loro;

• gli argomenti devono coincidere per numero e tipo con i valori indicati nella chiamata;

• nella function possono essere utilizzate anche variabili locali;

34

• nella function, le istruzioni di dichiarazione di variabili semplici, globali e locali, seguono le stesse re-gole della dichiarazioni di variabili semplici nel programma principale; vale ovviamente la dichiarazioneimplicita di tipo del Fortran;

• gli argomenti della function sono variabili di ingresso, l’unica variabile di uscita e il nome dellafunction;

• e possibile modificare i valori degli argomenti all’interno della function; ovviamente la modifica siha anche a livello dell’unita di programma chiamante.

Una modifica degli argomenti di una function non ha molto senso, in tal caso si usa una subroutine.Per ovviare a questo, il F90 ha un’istruzione opzionale di specifica per indicare quali variabili sonodi ingresso, quali di uscita e quali di ingresso e uscita.

Nell’esempio della function funz, la dichiarazione delle variabili globali (che si suppone sianoreali) x, y e z in F90 puo essere scritta

real, intent(in)::x,y,z

oppure, utilizzando la dichiarazione implicita del Fortran

intent(in)::x,y,z

In tal caso, la presenza nella function di un’istruzione eseguibile di modifica di un argomento comex=... provoca una segnalazione di errore in fase di compilazione;

• in F90 l’istruzione di fine, end, puo scriversi anche nei modi

end function end function nome funzione

• in ogni function, l’istruzione end e presente una sola volta;

• l’istruzione eseguibile return e l’istruzione di arresto di un sottoprogramma che significa “ritornare”al programma chiamante. Ci possono essere piu di una istruzione return all’interno di un sottopro-gramma. L’istruzione stop all’interno di un sottoprogramma provoca l’arresto dell’intero processo.

Se l’istruzione return non e presente nel sottoprogramma o non viene mai eseguita, il “ritorno” alprogramma chiamante avviene quando si incontra l’istruzione di fine sottoprogramma end.

Si consideri il seguente esempio che crea la funzione che calcola il fattoriale di un numero. Si utilizza ladichiarazione implicita di tipo del Fortran. La variabile contatore i e una variabile locale.

function ifatt(n)

ifatt=1

do i=2,n

ifatt=ifatt*i

enddo

return

end

In Fortran, una function puo avere la lista degli argomenti vuota. Ad esempio, la funzione che calcolala precisione di macchina si scrive

real function eps()

eps=1

5 if (eps+1.gt.1)then

eps=eps/2

goto 5

endif

eps=eps*2

return

end

35

Il sottoprogramma subroutine

In Fortran sono possibili i sottoprogrammi (subroutine).Sia sub1 una subroutine definita dall’utente. La subroutine sub1 ha una definizione come segue:

subroutine sub1(argomenti separati da virgola)istruzioni dichiarativeistruzione eseguibile 1...istruzione eseguibile kreturn

end

Supponiamo che gli argomenti della subroutine siano, nell’ordine, le variabili reali x, y e z. Il programmaprincipale (in generale un’unita di programma) si avvale della subroutine sub1 mediante un’istruzioneeseguibile come

call sub1(a,s,x)

dove a, s e x sono tre variabili allocate.L’argomento x della subroutine sub1 “legge” il valore memorizzato nel programma principale dalla va-riabile a, l’argomento y della subroutine sub1 “legge” il valore memorizzato nel programma principaledalla variabile s e l’argomento z della subroutine sub1 “legge” il valore memorizzato nel programmaprincipale dalla variabile x.Gli unici dati memorizzati sono quelli del programma principale, gli argomenti x, y e z della subroutine

sub1 e in generale di un sottoprogramma, sono parametri formali che leggono, utilizzano ed eventualmentemodificano le aree di memoria dove sono memorizzati i dati ai quali vengono indirizzati con la “chiamata”alla subroutine o al sottoprogramma.Una subroutine e in generale un sottoprogramma puo essere chiamato dall’unita di programma chiamantepiu di una volta con dati diversi. Ad esempio sono valide le chiamate

...call sub1(x,5,4*atan(1))

...call sub1(y,y,z)

• Gli argomenti separati da virgola sono le variabili globali della subroutine;

• gli argomenti possono essere di tipo e di dimensioni diversi tra di loro;

• gli argomenti devono coincidere per numero e tipo con i valori indicati nella chiamata;

• nella subroutine possono essere utilizzate anche variabili locali;

• nella subroutine, le istruzioni di dichiarazione di variabili semplici, globali e locali, seguono lestesse regole della dichiarazioni di variabili semplici nel programma principale; vale ovviamentela dichiarazione implicita di tipo del Fortran;

• gli argomenti della subroutine sono variabili di ingresso e di uscita. Se un argomento non vienemodificato all’interno della subroutine allora quell’argomento puo essere visto come una variabiledi solo ingresso; il F90 ha un’istruzione opzionale di specifica per indicare quali variabili sono diingresso, quali di uscita e quali di ingresso e uscita. Ad esempio se x e di ingresso, y e di uscita ez e di ingresso e uscita, allora le istruzioni di dichiarazione delle variabili x, y e z, nella subroutine,si possono scrivere:

real, intent(in)::x

real, intent(out)::y

real, intent(inout)::z

Le stesse istruzioni possono essere scritte omettendo la parola chiave real utilizzando la dichiarazioneimplicita di tipo del Fortran.

36

• in F90 l’istruzione di fine, end, puo scriversi anche nei modi

end subroutine end subroutine nome subroutine

• in ogni subroutine, l’istruzione end e presente una sola volta;

• l’istruzione eseguibile return e l’istruzione di arresto di un sottoprogramma che significa “ritornare”al programma chiamante. Ci possono essere piu di una istruzione return all’interno di un sottopro-gramma. L’istruzione stop all’interno di un sottoprogramma provoca l’arresto dell’intero processo.

Se l’istruzione return non e presente nel sottoprogramma o non viene mai eseguita, il “ritorno” alprogramma chiamante avviene quando si incontra l’istruzione di fine sottoprogramma end;

• ogni function puo essere scritta come una subroutine.

37

L’istruzione external

Nella scrittura di un programma principale puo capitare di passare una o piu function come argomentodi un sottoprogramma, senza che questa o queste function siano chiamate direttamente dal programmaprincipale in altri punti del codice.In questo caso la function, passata come argomento a un sottoprogramma, nel programma principaledeve essere dichiarata esterna. La stessa dichiarazione deve essere fatta nel sottoprogramma che legge echiama direttamente la function.Nell’istruzione dichiarativa, la parola chiave per dichiarare esterna una funzione e external.Ad esempio, supponiamo che un programma principale passi alla subroutine sub1 la funzione reale f1

mediante una chiamata della subroutine e la funzione reale f2 mediante una seconda chiamata dellasubroutine; ovvero nel programma principale si hanno le istruzioni dichiarative ed eseguibili

program nome programmaexternal f1,f2

...

...call sub1(..., f1, ...)

...call sub1(..., f2, ...)

...stop

end

f1 e f2 sono due function reali, ad esempio di due argomenti reali

real function f1(a,b)

...f1=...return

end

real function f2(a,b)

...f2=...return

end

Allora, la subroutine sub1 ha questa forma

subroutine sub1(..., f, ...)

external f

...

...z=f(x,y)

...return

end

Se nel programma principale una function passata come argomento di un sottoprogramma viene anche“chiamata” direttamente, allora essa non e piu external.

38

Ad esempio si puo avere la situazione

program nome programmaexternal f2

...

...call sub1(..., f1, ...)

...t=f1(r,s)

...call sub1(..., f2, ...)

...stop

end

L’istruzione contains in F90

I sottoprogrammi possono essere “contenuti” nel programma principale con l’istruzione contains.

• In un sottoprogramma “contenuto” nel programma principale, le variabili globali, ovvero quellepassate come argomenti sono trattate come in un sottoprogramma “non contenuto” nel programmaprincipale.

• In un sottoprogramma “contenuto” nel programma principale, le variabili non passate come argo-menti sono: locali se dichiarate esplicitamente nel sottoprogramma oppure globali se non dichiarateesplicitamente nel sottoprogramma.

Si osservi il codice Fortran descritto sotto

program test

real x,y,z

x=1; y=10; z=20

v=100; w=200

call sub1(x,y,w,x)

write(*,*)’ stampa dopo sub1 ’

write(*,*)’x = ’,x

write(*,*)’y = ’,y

write(*,*)’z = ’,z

write(*,*)’v = ’,v

write(*,*)’w = ’,w

write(*,*)’ ’

! ri-inizializzazione

x=1; y=10; z=20

v=100; w=200

call sub2(x,y,w,x)

write(*,*)’ stampa dopo sub2 ’

write(*,*)’x = ’,x

write(*,*)’y = ’,y

write(*,*)’z = ’,z

write(*,*)’v = ’,v

write(*,*)’w = ’,w

stop

39

contains

subroutine sub1(x1,y1,w1,x)

real x1,y1,x

real v

x1=x1+1

y1=y1+1

z=z+1

y=y+1

v=v+1

w1=w1+1

x=x+1

write(*,*)’ stampa di prova in sub1 ’

write(*,*)’x1 (x) = ’,x1

write(*,*)’y1 (y) = ’,y1

write(*,*)’z = ’,z

write(*,*)’y = ’,y

write(*,*)’v = ’,v

write(*,*)’w1 (w) = ’,w1

write(*,*)’x (x) = ’,x

return

end subroutine sub1

end program

subroutine sub2(x2,y2,w2,x)

real x2,y2,x

real v

x2=x2+1

y2=y2+1

z=z+1

y=y+1

v=v+1

w2=w2+1

x=x+1

write(*,*)’ stampa di prova in sub2 ’

write(*,*)’x2 (x) = ’,x2

write(*,*)’y2 (y) = ’,y2

write(*,*)’z = ’,z

write(*,*)’y = ’,y

write(*,*)’v = ’,v

write(*,*)’w2 (w) = ’,w2

write(*,*)’x (x) = ’,x

return

end subroutine sub2

40

che fornisce i seguenti risultatistampa di prova in sub1

x1 (x) = 3.0000000

y1 (y) = 12.000000

z = 21.000000

y = 12.000000

v = 1.00000000

w1 (w) = 201.00000

x (x) = 3.0000000

stampa dopo sub1

x = 3.0000000

y = 12.000000

z = 21.000000

v = 100.000000

w = 201.00000

stampa di prova in sub2

x2 (x) = 3.0000000

y2 (y) = 11.000000

z = 1.00000000

y = 1.00000000

v = 1.00000000

w2 (w) = 201.00000

x (x) = 3.0000000

stampa dopo sub2

x = 3.0000000

y = 11.000000

z = 20.000000

v = 100.000000

w = 201.00000

41

Il modulo in F90

In F90 e possibile definire il modulo. Il modulo (module) e un’unita di programma compilata a parte econtiene dichiarazioni e inizializzazioni di variabili e costanti che possono essere condivise da altre unitadi programma.Il modulo inizia con l’istruzione module nomemodulo e termina con l’istruzione end module nomemodulo.Un esempio di modulo e il seguente:

module dati

integer, parameter :: num=50

real, dimension(num) :: v=0,w=0

character(len=10) :: car

end module dati

L’unita di programma che utilizza tutte o in parte le variabili e le costanti allocate e/o inizializzate nelmodulo, specifica, come prima istruzione dichiarativa, che “utilizza” il modulo mediante la parolachiave use ed ha, ad esempio, la forma seguente

program nomep

use dati

...

write(*,*)’inserisci n<’,num

read(*,*)n

do i=1,n

v(i)=...

enddo

...

stop

end program

• il nome del modulo non ha nessuna relazione con il nome del file contenente il modulo;

• scrivere le istruzioni dichiarative nel modulo e come scriverle nell’unita di programma che usa ilmodulo; ovvero la scrittura seguente e equivalente ai due segmenti di programma sopra

program nomep

integer, parameter :: num=50

real, dimension(num) :: v=0,w=0

character(len=10) :: car

...

write(*,*)’inserisci n<’,num

read(*,*)n

do i=1,n

v(i)=...

enddo

...

stop

end program

• e possibile dichiarare variabili allocabili nei moduli; le variabili vengono allocate e deallocate nelleunita di programma che usano i moduli.

42

Un modulo puo contenere anche subroutine e function (procedure di modulo). La parola chiavecontains indica al compilatore che i sottoprogrammi successivi sono procedure di modulo.Ad esempio un modulo puo essere il seguente:

module miesub

contains

subroutine sub1(argomenti separati da virgola)istruzioni dichiarativeistruzioni eseguibiliend subroutine sub1

subroutine sub2(argomenti separati da virgola)istruzioni dichiarativeistruzioni eseguibiliend subroutine sub2

tipo funzione function f(argomenti separati da virgola)istruzioni dichiarativeistruzioni eseguibiliend function

end module miesub

Le unita di programma che utilizzano tutti o alcuni dei sottoprogrammi contenuti nel module miesub

dovranno specificare di “usare” il modulo mediante la parola chiave use. Ad esempio un programmaprincipale che usa il modulo miesub puo avere la forma seguente

program main

use miesub

...

call sub1(...)

...

stop

end program

Il vantaggio dell’uso di un sottoprogramma di modulo e dovuto al fatto che il compilatore controllagli argomenti del sottoprogramma. Vengono controllati, oltre al numero degli argomenti, al tipo e alloscopo (intent) come per i sottoprogrammi “non di modulo”, anche le dimensioni degli array “passati”al sottoprogramma (vedi la sezione Passaggio di array a sottoprogrammi).L’uso dei sottoprogrammi di modulo viene anche detto interfaccia esplicita, mentre per i sottoprogrammi“non di modulo” si parla di interfaccia implicita.

I moduli possono contenere sia dichiarazioni e inizializzazioni che sottoprogrammi. Ad esempio, unmodulo puo avere la forma:

module miesub

dichiarazioni e/o inizializzazionicontains

subroutine sub1(argomenti separati da virgola)istruzioni dichiarativeistruzioni eseguibiliend subroutine sub1

end module miesub

43

Passaggio di array a sottoprogrammi

In Fortran l’uso di array e flessibile. Si pensi ad esempio che, in un programma principale in cui unarray x e dichiarato

real x(10)

e possibile utilizzare componenti di x maggiori di 10. Ad esempio la scrittura

write(*,*)x(12)

e lecita e produce come risultato il numero reale memorizzato sui 32 bit successivi a partire da IND[x(1)]+12 ∗ 32 dove IND[x(1)] e l’indirizzo della prima componente allocata dell’array x.

Supponiamo di avere i seguenti array dichiarati nel programma principale in F77:

parameter(nx=10,ld=10,md=8)

real a(ld,md),x(nx),y(0:nx),z(nx*2)

e in F90:integer,parameter:: nx=10,ld=10,md=8

real,dimension(ld,md) :: a=0

real,dimension(nx) :: x=0

real,dimension(0:nx) :: y=0

real,dimension(nx*2) :: z=0

Supponiamo inoltre di avere le seguenti istruzioni eseguibili in Fortran di assegnazione di valori agliarray

do i=1,3

do j=1,3

a(i,j)=(i-1)*3+j

enddo

enddo

do i=1,3

x(i)=i*10

enddo

do i=0,8

y(i)=(i+1)*5

enddo

Gli array risultano avere questi valori:

a =

1 2 3 0 0 0 0 04 5 6 0 0 0 0 07 8 9 0 0 0 0 00 0 0 0 0 0 0 00 0 0 0 0 0 0 00 0 0 0 0 0 0 00 0 0 0 0 0 0 00 0 0 0 0 0 0 00 0 0 0 0 0 0 00 0 0 0 0 0 0 0

x =

1020300000000

y =

5101520253035404500

Si consideri una subroutine, chiamata submv2, che calcola il prodotto di una matrice per un vettore a cuiviene sommato un altro vettore di elementi pari al numero di righe della matrice.Ad esempio si vogliono calcolare le seguenti operazioni z(1)

z(2)

z(3)

=

1 2 34 5 67 8 9

102030

+

51015

44

e z(4)

z(5)

z(6)

=

1 2 34 5 67 8 9

102030

+

202530

e z(7)

z(8)

z(9)

=

1 2 34 5 67 8 9

102030

+

354045

In Fortran cio avviene con tre chiamate alla subroutine submv2

call submv2(a,ld,x,y,z,3,3)

call submv2(a,ld,x,y(3),z(4),3,3)

call submv2(a,ld,x,y(6),z(7),3,3)

Nelle tre chiamate alla subroutine, la scrittura del primo argomento a e equivalente alla scrittura a(1,1)

che indica che la chiamata “passa” l’indirizzo della prima componente dell’array.Nella prima chiamata della subroutine, la scrittura degli argomenti x, y, z indicano che la chiamata“passa” l’indirizzo della prima componente x(1), y(0) e z(1) dei rispettivi array; la prima chiamata allasubroutine si puo allora anche scrivere

call submv2(a(1,1),ld,x(1),y(0),z(1),3,3)

Nella seconda e terza chiamata, le scritture degli argomenti y(3), y(6), z(4) e z(7) indicano che lachiamata alla subroutine “passa” gli indirizzi specificati degli array y e z.

Utilizzando la dichiarazione implicita di tipo del Fortran, in F77, la parte dichiarativa della subroutinesubmv2 si puo scrivere in uno dei due modi seguenti

subroutine submv2(as,ls,xs,ys,zs,m,n)

real as(ls,*),xs(*),ys(*),zs(*)

subroutine submv2(as,ls,xs,ys,zs,m,n)

dimension as(ls,*),xs(*),ys(*),zs(*)

e in F90 in uno dei due modi seguenti

subroutine submv2(as,ls,xs,ys,zs,m,n)

real,intent(in),dimension(ls,*):: as

real,intent(in),dimension(*):: xs,ys

real,intent(inout),dimension(*):: zs

subroutine submv2(as,ls,xs,ys,zs,m,n)

real,intent(in):: as(ls,*),xs(*),ys(*)

real,intent(inout):: zs(*)

dove, in queste ultime istruzioni, se si utilizza la dichiarazione implicita di tipo del Fortran la parolachiave real puo essere omessa.In Fortran le istruzioni eseguibili e l’istruzione di fine della subroutine submv2 si scrivono

do i=1,m

zs(i)=0

enddo

do i=1,m

do j=1,n

zs(i)=zs(i)+as(i,j)*xs(j)

enddo

do i=1,m

zs(i)=zs(i)+ys(i)

enddo

return

end

Per quanto concerne il passaggio di array monodimensionali:

45

• il parametro formale xs, in tutte le chiamate della subroutine “legge” il valore memorizzato nelprogramma principale nell’array x a partire da x(1); ovvero xs(1) “legge” x(1), xs(2) “legge”x(2) e cosı via.

Il parametro formale ys, nella prima chiamata della subroutine, “legge” il valore memorizzato nelprogramma principale nell’array y a partire da y(0); ovvero ys(1) “legge” y(0), ys(2) “legge”y(1) e cosı via; nella seconda chiamata ys(1) “legge” y(3), ys(2) “legge” y(4) e cosı via; nellaterza chiamata ys(1) “legge” y(6), ys(2) “legge” y(7) e cosı via.

Il parametro formale zs, nella prima chiamata della subroutine, “legge” il valore memorizzato nelprogramma principale nell’array z a partire da z(1); ovvero zs(1) “legge” z(1), zs(2) “legge”z(2) e cosı via; nella seconda chiamata zs(1) “legge” z(4), zs(2) “legge” z(5) e cosı via; nellaterza chiamata zs(1) “legge” z(7), zs(1) “legge” z(8) e cosı via;

• se ad esempio, per la variabile zs la dichiarazione nella subroutine e

real zs(0:*)

allora nella prima chiamata della subroutine, zs(0) “legge” z(1), zs(1) “legge” z(2) e cosı via;nella seconda chiamata zs(0) “legge” z(4), zs(1) “legge” z(5) e cosı via; nella terza chiamatazs(0) “legge” z(7), zs(1) “legge” z(8) e cosı via;

• il simbolo * (asterisco) nella dichiarazione dell’array monodimensionale e un segnaposto; analoga-mente al posto del simbolo * (asterisco) si puo indicare 1, 2, n o altre costanti o variabili globali.

Per quanto concerne il passaggio di array bidimensionali:

• il parametro formale as in tutte le chiamate della subroutine “legge” il valore memorizzato nelprogramma principale nell’array a a partire da a(1 1); ovvero as(1 1) “legge” a(1 1), as(2 1)

“legge” a(2 1) e cosı via lungo le colonne dell’array a;

• poiche il Fortran memorizza gli elementi di un array bidimensionale “per colonne”, al sottopro-gramma deve essere noto il numero di righe dell’array bidimensionale memorizzato nel programmaprincipale chiamante, ovvero la grandezza leading. In questo modo, come nell’esempio, l’elementoas(1 2) del parametro formale as “legge” il valore memorizzato in a(1 2);

• il simbolo * (asterisco) nella seconda posizione nella dichiarazione dell’array bidimensionale e unsegnaposto; analogamente al posto del simbolo * (asterisco) si puo indicare 1, 2, n o altre costantio variabili globali.

• consideriamo ad esempio, la seguente chiamata alla subroutine

call submv2(a,x,y,z,3,3)

con la seguente parte della subroutine riguardante l’array as

subroutine submv2(as,xs,ys,zs,m,n)

real as(m,n)

allora, in questo caso l’elemento as(1 1) “legge” a(1 1), as(2 1) “legge” a(2 1), as(3 1) “legge”a(3 1), as(1 2) “legge” a(4 1), as(2 2) “legge” a(5 1), e cosı via; ovvero gli elementi di a chevengono utilizzati nella subroutine sono 1 0 0

4 0 07 0 0

Se si vuole che l’elemento as(i,j) “legga” l’elemento a(i,j), questa dichiarazione comporta una“lettura non corretta”;

46

• consideriamo ad esempio, la seguente chiamata alla subroutine

call submv2(a,x,y,z,3,3)

con la seguente parte della subroutine riguardante l’array as

subroutine submv2(as,xs,ys,zs,m,n)

parameter(ns=10)

real as(ns,ns)

in questo caso l’array as “legge correttamente” i corrispondenti elementi dell’array a.

Questa scrittura e fortemente sconsigliata in quanto vincola la “corretta lettura” dell’array bidi-mensionale ad una costante locale (in questo caso ns) che deve essere uguale alla grandezza leadingdell’array bidimensionale memorizzato nel programma principale; una chiamata allo stesso sotto-programma con un altro array con grandezza leading differente provocherebbe una “lettura noncorretta”.

Passaggio di array allocati dinamicamente

Si consideri la subroutine che calcola il prodotto matrice per vettore

subroutine mv(a,v,w,n,m,ld)

real, dimension(ld,*)::a

real, dimension(*)::v,w

do i=1,m

w(i)=0

do j=1,n

w(i)=w(i)+a(i,j)*v(j)

enddo

enddo

return

end

Il programma seguente calcola mediante la subroutine mv il prodotto matrice per vettore; gli arrayutilizzati sono allocati dinamicante.

program arrayallocabili

real,allocatable,dimension(:,:)::a

real,allocatable,dimension(:)::x,y

read(*,*)n

allocate(a(n,n),x(n),y(n))

do i=1,n

read(*,*)(a(i,j),j=1,n)

enddo

read(*,*)(x(i),i=1,n)

call mv(a,x,y,n,n,n)

write(*,*)(y(i),i=1,n)

stop

end

In questo caso il numero di righe dell’array a del programma principale e n e dunque, per avere una“corretta lettura”, la chiamata alla subroutine deve “passare” n come grandezza leading.

47

Operazioni globali e inizializzazioni all’interno di un sottoprogramma

Si consideri il seguente sottoprogramma in F90 che esegue la somma di due array

subroutine sub1(x,y,z,n)

real, dimension(*)::x,y,z

do i=1,n

z(i)=x(i)+y(i)

enddo

return

end

Il simbolo * (asterisco) come segnaposto non permette l’utilizzo delle operazioni globali. Per poter utiliz-zare l’operazione globale z=x+y per sommare le prime n componenti di x e y, si modifica il sottoprogrammain

subroutine sub1(x,y,z,n)

real, dimension(n)::x,y,z

z=x+y

return

end

Analogamente se si vuole inizilizzare un array all’interno di un sottoprogramma in F90, non si deveutilizzare il simbolo * (asterisco) come segnaposto. Ad esempio il seguente segmento di parte dichiarativadi un sottoprogramma

subroutine sub1(a,ld,v,w,n)

real,intent(out),dimension(ld,n)::a=0

real,intent(out),dimension(n)::w=0

real,intent(in),dimension(*)::v

inizializza a zero le variabili di uscita a e w rispettivamente nelle componenti a(i,j), i=1,ld, j=1,n ew(i), i=1,n.

Variabili mute (dummy)

Le variabili semplici locali di un sottoprogramma sono usualmente contatori di cicli, indici di componentidi array globali o variabili di “appoggio” per operazioni come lo scambio (swap).L’utilizzo di array locali e fortemente sconsigliato. Ad esempio, supponiamo di avere il seguente segmentodi programma principale in cui gli array sono allocati staticamente

program prova

real v(1000)

...

n=200

do i=1,n

v(i)=1/(i+1)

enddo

...

call sub1(v,n,...)

...

end

e di avere il segmento di subroutine sub1 in cui si ha necessita di salvare i valori di v in un array locale

subroutine sub1(x,m,...)

real x(*),w(100)

...

do i=1,m

w(i)=x(i)

enddo

...

end

48

Poiche il parametro formale m “legge” il valore 200, il ciclo dentro la subroutine viene eseguito ma nonc’ e controllo dove sono stati memorizzati i valori letti da x(101),...,x(200). E preferibile rendere mutol’array w considerandolo globale. Ovvero si modifica il programma principale e la subroutine nel modoseguente

program prova

real v(1000),work(1000)

...

n=200

do i=1,n

v(i)=1/(i+1)

enddo

...

call sub1(v,n,work...)

...

end

subroutine sub1(x,m,w,...)

real x(*),w(*)

...

do i=1,m

w(i)=x(i)

enddo

...

end

Tutte le considerazioni viste su passaggi di array a sottoprogrammi valgono ovviamente anche se i sotto-programmi sono function oppure procedure di modulo.

Alternativamente, in F90 si puo allocare dinamicamente l’array w scrivendo il codice nel modo seguente

subroutine sub1(x,m,w,...)

real, allocatable, dimension(:):: w

real x(*)

...

allocate(w(m))

do i=1,m

w(i)=x(i)

enddo

...

deallocate(w)

end

Passaggio di array con dimensioni diverse

Si consideri la subroutine mv che calcola il prodotto matrice per vettore vista in precedenza. Utilizziamoquesta subroutine per calcolare il prodotto scalare tra due vettori e per calcolare il prodotto matrice permatrice.Per la scrittura di un programma principale che calcola il prodotto scalare tra vettori, sia la partedichiarativa di due array monodimensionali scritta come segue

paramter(ix=100)

real x(ix),y(ix)

Supponendo che il programma principale legga o calcoli due vettori di lunghezza n memorizzati negliarray x e y, la chiamata

call mv(x,y,s,n,1,1)

49

restituisce nella variabile reale s il valore del prodotto scalare tra i due vettori.Per la scrittura di un programma principale che calcola il prodotto tra due matrici, sia la parte dichiarativadi tre array bidimensionali scritta come segue

paramter(ix=100,jx=50)

real a(ix,jx),b(ix,jx),c(ix,jx)

Supponendo che il programma principale legga o calcoli due matrici quadrate di ordine n memorizzatenegli array a e b, le chiamate

do j=1,n

call mv(a,b(1,j),c(1,j),n,n,ix)

enddo

restituiscono nell’array c il prodotto tra le due matrici memorizzate in a e b. Si nota che la matriceottenuta dal prodotto di due matrici ha per colonne i vettori risultanti dal prodotto della prima matriceper le rispettive colonne della seconda.Si osserva che, in entrambi i casi, non c’ e corrispondenza delle dimensioni degli array tra gli argomentidella chiamata e i parametri formali della subroutine. Ad esempio, nell’ultimo caso il secondo argomentodella chiamata e l’indirizzo di un array bidimensionale che viene “letto” da un parametro formale con unsolo indice.Questi passaggi di array non corrispondenti di dimensione possono anche essere effettuati a sottopro-grammi function ma non si possono eseguire se il sottoprogramma e una procedura di modulo.

50