Category Archives: Fortran

Istruzione READ nel Fortran


FORTRANL’istruzione READ nel Fortran ci consente di leggere uno o più dati dal buffer di input. L’unità nella quale andremo a leggere i dati è specificata dall’apposito numero presente nell’istruzione. Analizziamo nel dettaglio l’esempio che vi propongo:

READ(*,10) var 10 FORMAT (5X, I3)

esso indica di leggere da video (è presente l’asterisco), saltando le prime 5 colonne del buffer di input e utilizzando le seguenti 3 colonne per leggere un numero intero. Al posto dell’asterisco poteva trovarsi ad esempio il numero 1 allora si sarebbe eseguita l’operazione di lettura sull’unità 1.

Il formato dell’istruzione READ è il seguente:

READ(UNIT=u,FMT=f,ERR=e,END=d)lista di variabili

dove  u è un numero intero che assume ha la funzione di specificare l’indirizzamento della scrittura e cioè sul terminale (UNIT=6) oppure sul disco; mentre FMT=f, dove “f” è un numero intero, indica al computer di scrivere i dati con il formato specificato dall’istruzione FORMAT individuata dall’etichetta con il numero “f”;

Le specifiche ERR=e e END=d sono opzionali; in particolare la specifica ERR=e ha la funzione di far continuare l’esecuzione dalla riga etichettata con “e” se avviene un errore in lettura. Nella istruzione READ c’è anche un’ altra possibilità di errore, che capita quando, leggendo nel disco magnetico, si arriva alla fine del file di lettura; se si prova a leggere altri dati, il computer, non sapendo dove prenderli, sospenderà l’esecuzione.

Mentre la specifica END=d indica al computer di continuare l’esecuzione dalla riga etichettata con “d“. In questo modo si evita l’errore che capita quando, leggendo nel disco magnetico, si arriva alla fine del file di lettura; se si prova a leggere altri dati, il computer, non sapendo dove prenderli, sospenderà l’esecuzione.

LINK DI APPROFONDIMENTO PER L’ARGOMENTO:

Istruzione PRINT nel Fortran


FORTRANL’istruzione PRINT nel Fortran è una versione semplificata dell’istruzione WRITE, ed il suo formato è il seguente:

      PRINT f,lista di variabili

dove “f” è un numero intero, indica al computer di scrivere i dati con il formato specificato dall’istruzione FORMAT individuata dall’etichetta con il numero “f”; se “f” viene posto uguale ad un “*” (asterisco), specificheremo di utilizzare un formato “libero”, cioè quello predefinito nel FORTRAN (in questo caso, i valori delle variabili verranno stampati in una sola riga, con 7 decimali se sono variabili R4, 15 se sono R8, ecc.).

Tale istruzione ci permette di scrivere ciò che viene specificato nella lista di variabili direttamente sullo schermo del computer su cui viene eseguito il programma.

Si noti che il comando “print *” è seguito da una virgola, e che le virgole compaiono tra gli elementi successivi da stampare. E’ opportuno osservare anche che le le stringhe devono essere racchiuse da virgolette doppie o singole. Il comando “print *” su una riga da solo e senza virgola  viene utilizzato come un avanzamento riga.

Esempio di utilizzo dell’istruzione print nel Fortran:

program somma
implicit none
integer :: somma, a

print*, "Questo programma esegue una somma. Inserire 0 per terminare la somma."
open(unit=10, file="Somma.DAT")

somma = 0

do
 print*, "Inserisci il numero da sommare:"
 read*, a
 if (a == 0) then
  exit
 else
  somma = somma + a
 end if
 write(10,*) a
end do

print*, "Somma =", somma
write(10,*) "Somma =", somma
close(10)

end

 LINK DI APPROFONDIMENTO PER L’ARGOMENTO:

Istruzione WRITE nel Fortran


FORTRANL’istruzione WRITE nel Fortran permette di scrivere il contenuto di una variabile secondo un preventivato formato. La sintassi dell’istruzione WRITE è la seguente:

 WRITE(UNIT=u,FMT=f,ERR=e) lista di variabili

  •  dove  u è un numero intero che assume ha la funzione di specificare l’indirizzamento della scrittura e cioè sul terminale (UNIT=6) oppure sul disco;
  • FMT=f, dove “f” è un numero intero, indica al computer di scrivere i dati con il formato specificato dall’istruzione FORMAT individuata dall’etichetta con il numero “f”;
  • la specifica (ERR=e) è opzionale e serve per controllare che il processo di scrittura abbia avuto successo.

Le parole chiave “UNIT=” e “FMT=” possono essere omesse, quindi possiamo sintetizzare il comando in  WRITE(u,f,…), assicurandoci però che il numero che si riferisce all’unità di uscita preceda l’etichetta del formato. Se “f” viene posto uguale ad un “*” (asterisco), specificheremo di utilizzare un formato “libero”, cioè quello predefinito nel FORTRAN (in questo caso, i valori delle variabili verranno stampati in una sola riga, con 7 decimali se sono variabili R4, 15 se sono R8, ecc.).

 Se la specifica ERR non è presente e si verifica una condizione di errore  il computer fermerà l’esecuzione. Se invece si è specificato ERR=e, dove “e” è un altro numero di etichetta, quando si verifica una condizione di errore durante la scrittura il computer continuerà l’esecuzione del programma dalla riga etichettata con “e”.

Un esempio dell’utilizzo dell’istruzione WRITE nel Fortran è il seguente:

WRITE (*,10) j,var 10 FORMAT (“L’iterazione”,I3,”ha fornito il seguente risultato”,F7.3)

La parentesi (*,10) indica di scrivere a video (*) con formato 10 (10 è l’etichetta del formato), è importante che tale etichetta non sia stata già utilizzata. Il formato scelto prevede del testo per indicare il significato dei valori e dei descrittori di formato che indicano in che modo devono essere espressi i valori delle variabili.

LINK DI APPROFONDIMENTO PER L’ARGOMENTO:

Cicli a condizione finale nel Fortran


FORTRANIl ciclo a condizione finale nel Fortran, che comunemente viene identificato dal termine repeat-until, esegue il controllo della condizione dopo che le istruzioni presenti nel blocco vengano eseguite, subito prima dell’istruzione END DO. Così le istruzioni del corpo del ciclo verranno sempre eseguite almeno una volta.

La forma generale del costrutto è la seguente:

[nome :] DO
istruzione 1
istruzione 2
........
IF (espressione logica ) EXIT
END DO [nome ]

Riporto di seguito un semplice programma d’esempio che ci permette di capire il funzionamento di un ciclo di questo genere. Si tratta di un programma che dopo aver richiesto di digitare un numero, stampa a video tutti i numeri a parire da 1 fino al numero inserito.

program stampanumeri
implicit none
integer :: i, n
!
! Utilizzo istruzione exit
!
write(*,*)’Digita un intero positivo’
read(*,*)n
i=1
do
      write(*,*)i
      if(i==n)exit
      i=i+1
end do
end program stampanumeri

LINK DI APPROFONDIMENTO PER L’ARGOMENTO:

Cicli a condizione iniziale nel Fortran


FORTRANIl ciclo a condizione iniziale nel Fortran, che comunemente viene identificato dal termine to ciclo while, esegue il controllo della condizione prima che le istruzioni presenti nel blocco sia eseguite. Allora le dichiarazioni presenti nel corpo verranno ripetute fino a quando la condizione specificata risulterà vera.

La forma generale del costrutto è la seguente:

do while (espressione logica)
     istruzione1
     istruzione2
     ………….
end do

L’esecuzione del blocco di istruzioni presente all’interno del ciclo avviene secondo la sequenza di seguito indicata:

  1. viene dapprima valutato il valore dell’espressione logica riportata tra parentesi;
  2. se il corrispondente valore risulta .FALSE., nessuna istruzione del blocco viene eseguita e il controllo passa alla prima istruzione che compare dopo l’istruzione END DO;
  3. se invece tale valore risulta .TRUE., allora viene eseguito il blocco di istruzioni a partire dalla prima istruzione che segue l’istruzione DO WHILE;
  4. nel momento in cui viene raggiunta l’istruzione finale del ciclo, il controllo ritorna all’istruzione DO WHILE; quindi l’espressione logica è valutata nuovamente e il ciclo viene ripetuto.

Di seguito riporto un semplice esempio che effettua un ciclo while per eseguire una valutazione di una certa funzione e ripete tale calcolo fintantoche lo scarto risulta maggiore o uguale della tolleranza. Quando tale valore risulta minore il ciclo si arresta.

do while (scarto.ge.toll)
iter = iter +1
fval=g(fk)
scarto = abs(fval - fk)
fk = fval
end do

LINK DI APPROFONDIMENTO PER L’ARGOMENTO:

Istruzione Select Case nel Fortran


FORTRANL’istruzione Select Case nel Fortran può essere usata per eseguire un insieme di criteri di selezione di multi-alternativa, in questo modo consente al programmatore di selezionare un
particolare blocco di istruzioni da eseguire in funzione del valore assunto da una variabile di
controllo di tipo intero o carattere, o da un’espressione logica. La sintassi del costrutto è la seguente:

nome : SELECT CASE (espressione di CASE)
CASE (selettore 1) nome
istruzione 1
istruzione 2
.......
CASE (selettore 2) nome
istruzione 1
istruzione 2
.......
.....
CASE DEFAULT nome
(selettore 2) nome
istruzione 1
istruzione 2
.......
END SELECT nome

Come già anticipato il selettore può essere un numero intero, un carattere, o un’espressione logica. Così come i blocchi dell’istruzione IF_ELSE, i costrutti CASE possono anche essere etichettati con un nome.

Se il valore della espressione di CASE è compreso nell’intervallo dei valori inseriti nel selettore 1 verranno eseguite le istruzioni del blocco istruzione 1; mentre se il valore della espressione di CASE è compreso nell’intervallo dei valori di selettore 2 verranno eseguite le istruzioni del blocco istruzione 2 , e in modo simile per le altre alternative inserite nel costrutto.

La clausola CASE DEFAULT è opzionale e copre tutti gli altri possibili valori della espressione di CASE non previsti dalle altre istruzioni CASE. Se il blocco DEFAULT viene omesso e il valore di espressione non è compreso in un intervallo dei selettori, non sarà eseguita alcuna istruzione.

LINK DI APPROFONDIMENTO PER L’ARGOMENTO:

Istruzione if nel Fortran


FORTRANL’istruzione if nel Fortran rappresenta una struttura per il controllo del flusso di informazioni che ci permette di valutare un’espressione logica e di eseguire un blocco di programma nell’ipotesi tale espressione risulti vera, mentre l’opzione else ci consente di eseguire un altro blocco di programma  nel caso la condizione imposta da if non si avveri.

La forma più generale del costrutto IF-THEN-ELSE-END IF è la seguente:

IF (espressione-logica) THEN
      blocco1
ELSE
     blocco2
END IF

dove le blocco1 e blocco2 sono sequenze di istruzioni eseguibili, e espressione-logica è ovviamente un’espressione logica. L’esecuzione di questo costrutto va come segue:

  • l’espressione logica viene valutata, ottenendo un valore logico
  • se il risultato è. TRUE., le dichiarazioni contenute nella blocco1 vengono eseguite
  • se il risultato è. FALSE., le dichiarazioni contenute nella blocco 2 sono eseguiti
  • dopo il termine dell’esecuzione di istruzioni in blocco 1 o blocco 2, la seguente dichiarazione END IF viene eseguita.

Esempio di codice fortran
Il seguente codice prima legge un intero e lo deposita in una variabile intera. Poi, se il numero può essere diviso per 2 (cioè, se il numero è un multiplo di 2),  l’istruzione WRITE (*,*) contenuta tra IF e ELSE viene eseguita e dimostra che il numero è pari, altrimenti, l’istruzione WRITE (*, * ) contenuta tra ELSE END IF viene eseguita e mostra che il numero è dispari.

function MOD(x, y)
!calcola il resto di x diviso y.
INTEGER :: Number

READ(*,*) Number
IF (MOD(Number, 2) == 0) THEN
    WRITE(*,*) Number, ‘ pari’
ELSE
    WRITE(*,*) Number, ‘ dispari’
END IF
end function

LINK DI APPROFONDIMENTO PER L’ARGOMENTO:

Le Procedure di Modulo nel Fortran


FORTRANAbbiamo imparato ad usare i moduli nel Fortran, e ne abbiamo apprezzato l’enorme utilità quale deposito di variabili e costanti a cui ogni unità di programma può attingere. Ma i moduli sono ben altro e ci consentono di definire al proprio interno delle vere e proprie procedure che ogni unità di programma che accede al modulo potrà in questo modo utilizzare, facendo uso dell’istruzione USE.

Ricordiamo a tal proposito che un modulo di programma è reso accessibile alle varie unità di programma attraverso l’istruzione USE. Tali procedure vengono, pertanto, chiamate procedure di modulo nel Fortran e vengono compilate come parte del modulo.

 Le procedure che si trovano all’interno di un modulo devono essere posizionate dopo le dichiarazioni dei dati e devono essere precedute dall’istruzione CONTAINS. Questa istruzione indica al compilatore che le istruzioni successive rappresentano delle procedure di modulo.

Di seguito si riporta un programma che fa uso di una procedura di modulo per calcolare il prodotto di una matrice per un vettore.

module OperazioniMatriceVettore
integer, parameter :: N = 3 ! costante globale.
contains

function moltiplicazioneMatriceVettore ( A, b ) result( c )
implicit none
! Definizione delle dimensioni di A e b.
real, dimension( :, : ), intent( in ) :: A
real, dimension( : ), intent( in ) :: b
real, dimension( size( b ) ) :: c
integer N
integer i
N = size( b )
c = 0.0
do i = 1, N
c = c + b( i ) * A( :, i )
end do
end function moltiplicazioneMatriceVettore

end module OperazioniMatriceVettore

program MatriceVettore
use OperazioniMatriceVettore
implicit none
real, dimension( N, N ) :: A
real, dimension( N ) :: b, c
! Riempie A è  b with con numeri random.
call random_number( A )
call random_number( b )
! Calcola il prodotto matrice * vettore, A*b.
c = moltiplicazioneMatriceVettore ( A, b )
print *, ‘Prodotto matrice vettore = ‘, c
end program MatriceVettore

LINK DI APPROFONDIMENTO PER L’ARGOMENTO:

I moduli nel Fortran


FORTRANNelle applicazioni di programmazione ingegneristiche, si incontra spesso il caso di parametri, variabili e sottoprogrammi che devono essere ripartiti in diverse unità di programma. Per risolvere tale problema si possono utilizzare i moduli nel Fortran che rappresentano un’unità  speciale di programma che raccoglie le collezioni di dichiarazioni e di subprograms in modo da poterle importare in altre unità di programma.

La funzionalità dell’unità modulo è simile a quella dell’archivio di intestazione di C. I Moduli semplici vengono definiti attraverso al seguente struttura:

MODULE name
        corpo
END MODULE name

Si noti che questa è la forma più semplice dell’unità del modulo. Esistono forme più generali che ci permettono l’inclusione dei subprograms e delle procedure. Richiameremo soltanto la forma più semplice dell’unità del modulo .

Un modulo di programma è reso accessibile alle varie unità di programma attraverso l’istruzione USE. Per meglio comprendere l’utilizzo dei moduli nel Fortran consideriamo il seguente programma che usa un modulo nel calcolo dell’area d’un cerchio:

MODULE Circle
!---------------------------------------------------------------------
! ! Modulo che contiene le definizioni delle variabili necessarie per 
! il calcolo dell'area di un cerchio noto il raggio !
!---------------------------------------------------------------------
    REAL, PARAMETER :: Pi = 3.1415927
    REAL :: radius
END MODULE Circle
PROGRAM Area
!---------------------------------------------------------------------
! ! Questo programma calcola l'area di un cerchio noto che sia il raggio  
! Uses: MODULE Circle ! FUNCTION Area_Circle (r) !
!---------------------------------------------------------------------
USE Circle, ONLY : radius IMPLICIT NONE
INTERFACE
   FUNCTION Area_Circle (r)
      REAL, INTENT(IN) :: r
   END FUNCTION Area_Circle
END INTERFACE
! Prompt user per il valore del raggio 
write(*, '(A)', ADVANCE ="NO") "Digita il valore del raggio: " 
read(*,*) radius
! Scrive l'area utilizzando la function call 
write(*,100) "Area del cerchio di raggio", radius, " e", &
Area_Circle(radius)
100 format (A, 2x, F6.2, A, 2x, F11.2)
END PROGRAM Area
!-----Area_Circle----------------------------------------------------
! ! Funzione per il calcolo dell'area del cerchio !
!---------------------------------------------------------------------
FUNCTION Area_Circle(r) USE Circle, ONLY : Pi
   IMPLICIT NONE REAL :: Area_Circle REAL, INTENT(IN) :: r
   Area_Circle = Pi * r * r
END FUNCTION Area_Circle

In questo esempio, definiamo un modulo che dichiara il tipo delle due variabili reali pi e raggio. In più, in questo modulo, dichiariamo il valore del parametro pi. Per usare il modulo nel programma principale, impieghiamo l’istruzione USE.

Usiamo poi una forma speciale dell’ istruzione USE che specifica che siamo soltanto interessati al valore del raggio nel programma principale, cioè nel programma del modulo viene utilizzato un solo componente. Similmente, usiamo soltanto il parametro pi nel subprogram Area_Circle attraverso l’istruzione USE che compare in quella procedura.

L’istruzione USE deve comparire all’inizio della parte di dichiarazione dell’unità di programma che usa il modulo!! Deve comparire anche prima dell’istruzione IMPLICIT NONE!

LINK DI APPROFONDIMENTO PER L’ARGOMENTO:

Le procedure ricorsive nel Fortran


FORTRANUna procedura ricorsiva, nel Fortran, rappresenta una costruzione artificiosa che ci consente di utilizzare una funzione in se stessa. Analizziamo come nel liguaggio di programmazione Fortran possa essere gestita una procedura di talke tipo; vediamo allora un semplice esempio di funzione ricorsiva alfine di mettere in evidenza appunto il fatto che la funzione richiama se stessa:

RECURSIVE FUNCTION factorial(n) RESULT(res)
INTEGER res, n
IF(n.EQ.1) THEN
   res = 1
ELSE
   res = n*factorial(n-1)
END IF
END

Analizziamo allora nel dettaglio la funzione che presenta una struttura ramificata. La condizione n == 1 è la base della ricorsione. Questo è l’unico modo che si ha per ottenere che il programma smetta di chiamare se stesso.

La parte contenuta nel costrutto else rappresenta la ricorsione. C’è da notare che la chiamata factorial(n-1) avviene all’interno della funzione che sta definendo factorial(n). La parte essenziale di tutto il procedimento di ricorsione è appunto la chiamata a un valore inferiore, n-1, e tale chiamata continuerà fino a quando non si verificherà un valore di n pari a 0.

Possiamo quindi affermare che una procedura di ricorsione che abbia successo chiamerà sempre un valore inferiore.Ci sono molti pericoli connessi all’utilizzo di un algoritmo di ricorsione. Ad esempio così come accade con i cicli while, è possibile per la funzione di chiamare se stessa all’infinito in modo da non fornire mai una risposta.

Un’altro problema che può nascere dal suo utilizzo è legato al fatto che la ricorsione può causare calcoli ridondanti che, anche se possono essere conclusi, possono richiedere molto tempo. Infine  mentre un programma ricorsivo è in esecuzione ha bisogno di spazio in più per accogliere l’overhead della ricorsione.

LINK DI APPROFONDIMENTO PER L’ARGOMENTO:

Le subroutine nel Fortran


FORTRANUna subroutine nel Fortran rappresenta un tipo di procedura, essa viene richiamata specificandone il nome attraverso l’istruzione CALL che riceve i valori di input e restituisce quelli di output attraverso una lista di argomenti.

Il costrutto nella sua forma generale per definire una subroutine è il seguente:

SUBROUTINE nome_subroutine [(lista_di_argomenti)]
 
    [definizione e dichiarazione delle variabili]
    [corpo della procedura]
[CONTAINS
    procedure interne]
[RETURN]
END [SUBROUTINE [nome_subroutine]]

 

Nella definizione della struttura è possibile identificare il nome della subroutine, che dovrà rispettare le regole per la scelta dei nomi nel Fortran, seguito dall’elenco delle varibili di scambio tra la procedura ed il programma chiamante.

Segue la definizione e la dichiarazione delle variabile che sono utilizzate all’interno della procedura, quindi segue il corpo della procedura cioè le istruzioni che dovrà eseguire nel momento in cui verrà chiamata dal programma principale.

Quando un programma chiama una subroutine, l’esecuzione del programma viene temporaneamente sospesa per consentire l’esecuzione della subroutine. Quando viene raggiunta l’istruzione RETURN o l’istruzione END SUBROUTINE l’esecuzione dell’unità chiamante riprende dalla riga successiva a quel la che ha effettuato la chiamata.

La chiamata avviene attraverso l’istruzione CALL, la cui sintassi è:

CALL nome_subroutine ([lista_di_argomenti])

 

Un esempio di soubroutine di fortran 90 è fornito di seguito:

!TRASFORMATA DI FOURIER DISCRETA
!________________________________
subroutine dft (A,N,E)
implicit none
17
integer :: N !numero di campioni
integer :: E !numero di campinature effettuate
integer :: i,j !indice di riga e di colonna della matrice
complex :: uim !unita' immaginaria
complex,dimension(0:1000,0:1000) :: A !matrice complessa

uim=(0,1)
do i=0, n-1
   do j=0, n-1
     A(i,j)=exp(-(2*3.14*uim*i*j)/n)
   end do
end do
E=N
end

Questa subroutine calcola le trasformate discrete di fourier dato un certo campione.

LINK DI APPROFONDIMENTO PER L’ARGOMENTO: