note per il corso linguaggi di programmazione per il ...seghini/fortran/pdf/note-lezioni.pdf ·...

90
Università degli Studi di Roma "La Sapienza" Corso di laurea in Matematica Note per il corso Linguaggi di programmazione per il calcolo scientifico Introduzione alla programmazione in linguaggio fortran Alessandra Seghini

Upload: lytuong

Post on 14-Feb-2019

219 views

Category:

Documents


0 download

TRANSCRIPT

Università degli Studi di Roma "La Sapienza"

Corso di laurea in Matematica

Note per il corso

Linguaggi di programmazione per il calcolo scientifico

Introduzione alla programmazione in linguaggio fortran

Alessandra Seghini

Introduzione alla programmazione in linguaggio fortran

Indice: (per stampare, utilizzare le note del corso in formato PDF)

Introduzione

Variabili e costanti scalari

Operatori ed espressioni

Scelte e decisioni

Cicli

Foglio esercizi 1

Array

Foglio esercizi 2

Tipi derivati

Inizializzazione aree di memoria

Procedure:

Subroutine

Function

Foglio esercizi 3

Intent e Interface

Foglio esercizi 4

Foglio esercizi 5

Ricorsività

Procedure come argomenti

Foglio esercizi 6

Variabili globali

Funzioni di tipo array e di tipo derivato

Istruzioni di input/output

Gestione dei file

Foglio esercizi 7

Foglio esercizi 8

Puntatori

Foglio esercizi 9

Limiti del F77

Note per l'utilizzo del compilatore fortran in ambiente linux

Bibliografia:

S. J. Chapman, Fortran 90/95 - Guida alla programmazione, Mc Graw Hill

T.M.R. Ellis, Programmazione Strutturata in Fortran 77 con elementi di Fortran 90, Zanichellli

M. Metcalf, J. Reid, Fortran 90 Explained, Oxford University Press

Nota: queste pagine forniscono una traccia degli argomenti svolti nel corso "Linguaggi di programmazione per il calcolo scientifico"

Alessandra Seghini

LINGUAGGI AD ALTO LIVELLO

Codice macchina (codice binario specifico per ogni tipo di computer)

Linguaggio assemblatore (forma mnemonica del codice macchina)

Linguaggio ad alto livello (Fortan, Pascal, C, Ada, Cobol, etc.)

Linguaggio ad alto livello ---(compilatore)---> Codice macchina

Compilatore:

controlla la sintassi delle istruzioni e produce informazioni

diagnostiche che permettono di correggere eventuali errori.

traduce il programma in codice macchina

Lo stesso programma ad alto livello può essere eseguito su computer

completamente diversi compilando con compilatori diversi che siano in grado di

interpretare la stessa sequenza di input (istruzione in linguaggio ad alto livello) e

tradurre nel codice macchina specifico per quel computer.

Il FORTRAN è stato il primo linguaggio ad alto livello ed è ancora largamente usato

per scopi tecnici e scientifici. Nasce intorno alla metà degli anni '50 col nome di:

IBM FORmula TRANslation System

Il FORTRAN 66 è stato il primo standard ufficiale.

Standard successivi largamente diffusi sono stati il FORTRAN 77 ed il FORTRAN

90.

PROGETTARE ... PROGRAMMARE... VERIFICARE

Progettare

Tracciare il percorso logico del programma costruendo una mappa di

sviluppo che riporti la struttura generale a vari livelli di dettaglio.

1.

Programmare

Nella costruzione del programma saranno necessari i seguenti strumenti:

editor

----->

programma sorgente (.f90, .f77, .for)

compilatore

----->

modulo oggetto (.o, .obj, .lis, .err, etc.)

linker

----->

programma eseguibile (.exe)

Un ambiente di sviluppo integrato è un insieme di applicazioni (editor,

2.

compilatore, linker, debugger) per scrivere, compilare e testare un

programma. Per molti linguaggi sono disponibili pacchetti che dispongono

di tali ambienti di sviluppo (es. Borland Pascal, Microsoft Fortran, etc.)

Verificare

Individuazione e correzione degli errori:

errori sintattici (o grammaticali)

individuati dal compilatore e (normalmente) facili da correggere

errori semantici (o logici)

talvolta difficili da trovare. Per evitare errori logici e per poterli

individuare più facilmente è necessario pianificare la costruzione

del programma ed utilizzare tecniche di programmazione

strutturata, con uso di subroutine o gruppi di subroutine, che

possano essere costruite e testate in modo indipendente.

L'individuazione degli errori logici può essere facilitata dall'utilizzo

di appositi programmi di debugging.

FORMATO DI UNA RIGA DI PROGRAMMA

Il formato dei programmi scritti con il vecchio standard fortran 77 era molto

rigido. Tale rigidità è un retaggio dell'epoca in cui si usavano ancora le schede

perforate: ogni singola riga di programma usava solo le prime 72 colonne (le

colonne 73-80 erano usate per la numerazione delle schede):

Num.colonna significato

1

2

3

4

5

la lettera C o il carattere * in col.1 indicano "commento"

Col.1-5: label istruzione (sempre di tipo numerico)

6

qualsiasi carattere diverso da 0 indica "continuazione della riga

precedente"

7

8

.

.

72

ISTRUZIONE FORTRAN

Questa rigidità di formato è superata nel fortran 90:

non ci sono più colonne riservate

3.

possono esserci più istruzioni sulla stessa riga (separate da ;)

possono esserci commenti sulla stessa riga dell'istruzione (il commento

inizia con !)

il carattere & in fondo ad una riga indica che l'istruzione prosegue sulla

riga successiva.

Nel fortran 77 i nomi dei programmi e/o delle variabili, possono essere costituiti al

max da 6 lettere e/o cifre e devono sempre iniziare con una lettera. Gli spazi bianchi

non sono considerati, quindi le 3 istruzioni seguenti sono uguali:

PROGRAM ESEMPIO , PROGRAMESEMPIO , P R O G R A M E S E M P I O

Il fortran 90 riconosce fino a 31 caratteri ed ammette anche alcuni caratteri

speciali come _ e $. Attribuisce un significato allo spazio bianco.

SCHEMA DI UN "MAIN PROGRAM"

[PROGRAM nome-programma]

Istruzione opzionale, ma raccomandata

Direttive per il compilatore

dichiarazione e dimensionamento variabili, etc.

non danno luogo a codice macchina

Istruzioni eseguibili

END [PROGRAM [nome-programma]]

Sottopogrammi

(subroutine e function)

Esempio:

Program norma_euclidea

! Calcolo della norma euclidea di un vettore

! DIRETTIVE PER IL COMPILATORE! ============================! dichiarazione variabili integer:: n,i real, dimension(100):: x real:: s

! ISTRUZIONI ESEGUIBILI! =====================! input dei dati do print *, 'n =?' read *, n if ((n.gt.0).and.(n.le.100)) exit end do read *, (x(i), i=1,n)

! calcolo della norma s=0. do i=1,n s = s + x(i)**2 end do s = sqrt(s)

! output del risultato print *, s

stop end program norma_euclidea

I 6 TIPI DI DATI INTRINSECI

INTEGER(kind=4), o INTEGER

Numeri interi. Sono rappresentati esattamente nella memoria del computer all'interno di

un determinato intervallo di definizione (range), che dipende dalla dimensione della

locazione di memoria utilizzata: se la locazione di memoria è di n bit, l'intervallo di

definizione dei numeri interi andrà da -2

n-1

a 2

n-1

-1.

Un intero con kind=4 è memorizzato in 4 byte.

REAL(kind=4), o REAL

Numeri reali in singola precisione. Sono rappresentati nella memoria del computer in

maniera approssimata utilizzando la tecnica di memorizzazione in virgola mobile, o

floating point: viene specificata una base (mantissa) e un esponente, che indica la

potenza di 10 per la quale la base deve essere moltiplicata.

Un reale con kind=4 è memorizzato in 4 bytes. Un numero prefissato di bit è destinato

alla mantissa (che definisce la precisione, ovvero il numero di cifre significative) e un

numero prefissato di bit è destinato all'esponente (che definisce il range, ovvero

l'ordine di grangezza). Per numeri reali in singola precisione si hanno 6 cifre

significative con range da 10

-37

a 10

+37

.

Es.: 1. , -27.315 , 0. , 7.5E+02 , 5.E-07

REAL(kind=8), o DOUBLE PRECISION

Numeri reali in doppia precisione. Sono memorizzati utilizzando una locazione di

memoria di dimensione doppia rispetto alla locazione di memoria utilizzata per

memorizzare i numeri reali in singola precisione. Un reale con kind=8 è memorizzato in

8 bytes, ha 15 cifre significative e range da 10

-307

a 10

+307

.

Es.: -1D-7 , 8.45D4 , -15.7685D0

COMPLEX

Numeri complessi, rappresentati da una coppia ordinata di numeri reali.

Es.: (3.5 , -3.) , (2.76E4 , -25E-2)

LOGICAL

Variabili logiche. Possono assumere i valori .TRUE. o .FALSE.

CHARACTER(len=n) (o CHARACTER*n)

Stringhe di caratteri alfanumerici. Ogni carattere viene memorizzato secondo il suo

codice ASCII ed occupa 1 byte.

Es.: CHARACTER(len=5) NOME ; NOME = 'Carla'

Le funzioni KIND, HUGE, RANGE, PRECISION

Program interi_e_reali! VARIABILI INTEGER

print *, "Per il tipo INTEGER" ! numero di byte occupati in memoria print *, "KIND = ", kind(1) ! valore max print *, "HUGE = ", huge(1) print *

! VARIABILI REAL print *, "Per il tipo REAL" ! numero di byte occupati in memoria print *, "KIND = ",kind(1.0) ! valore max print *, "HUGE = ", huge(1.0) ! numero di cifre significative e range print *, "PRECISION = ",precision(1.0) print *, "RANGE = ",range(1.0) print *

! VARIABILI DOUBLE PRECISION print *, "Per il tipo DOUBLE PRECISION"! numero di byte occupati in memoria print *, "KIND = ",kind(1.d0) ! valore max print *, "HUGE = ", huge(1.d0) ! numero di cifre significative e range print *, "PRECISION =",precision(1.d0) print *, "RANGE = ",range(1.d0)end program interi_e_reali

Output del programma Per il tipo INTEGER KIND = 4 HUGE = 2147483647

Per il tipo REAL KIND = 4 HUGE = 3.402823E+38 PRECISION = 6 RANGE = 37

Per il tipo DOUBLE PRECISION KIND = 8 HUGE = 1.79769313486232D+308 PRECISION = 15 RANGE = 307

DICHIARAZIONE DI VARIABILI SCALARI DI TIPO

INTRINSECO

Dichiarazione esplicita

TIPO:: lista variabili

ESEMPIO: INTEGER :: i,j REAL :: a,bCHARACTER(len=5):: nomeCHARACTER(len=4):: idLOGICAL:: condizione

o anche INTEGER i,jREAL a,betc.

Dichiarazione implicita

in mancanza di una dichiarazione esplicita di variabile, il compilatore fortran

applica la così detta "regola del nome", assumendo che la variabile sia intera

se il suo nome inizia con una lettera compresa in (I-N) e che sia reale altrimenti.

La "regola del nome" può essere modificata definendo una nuova serie di tipi

impliciti per mezzo della direttiva IMPLICIT.

Ad esempio utilizzando la direttiva:

IMPLICIT REAL(A-D,W), INTEGER(H-L), LOGICAL(M-P)

si potranno utilizzare le seguenti variabili di tipo implicito:

ALE, WORK, C di tipo REALH, LEN di tipo INTEGERMAI di tipo LOGICAL

La direttiva IMPLICIT deve comparire prima di qualunque altra dichiarazione

esplicita.

È consigliabile dichiarare esplicitamente tutte le variabili, utilizzando la direttiva

IMPLICIT NONE da mettere prima di tutte le altre dichiarazioni esplicite di variabili.

DEFINIZIONE DI COSTANTI

Un'altra importante direttiva per il compilatore è la direttiva PARAMETER che

permette la definizioni delle costanti. La sintassi dell'istruzione è la seguente:

TIPO, PARAMETER:: nome = espressione

ESEMPI: REAL, PARAMETER:: zero = 1.E-7INTEGER, PARAMETER:: N=100REAL, PARAMETER:: PI=acos(-1.), P34=3*PI/4

La definizione di una costante tramite la direttiva PARAMETER presenta alcune

fondamentali differenze rispetto ad una normale istruzione di assegnazione (ad es.

N = 100):

il valore assegnato con una istruzione PARAMETER non occupa spazio in

memoria (non viene memorizzato in una variabile), ma viene utilizzato

direttamente dal compilatore nella traduzione del programma sorgente in

codice binario;

il valore assegnato ad una costante con una istruzione PARAMETER non può

essere modificato né con una istruzione di assegnazione né con un'altra

istruzione PARAMETER;

le costanti definite con una istruzione PARAMETER possono essere utilizzate

per dimensionare array non rilocabili.

TIPI DI DATI PARAMETRIZZATI

Il programmatore può definire numeri reali con una precisione e/o un range diversi

da quella dei reali in singola e in doppia precisione tramite la funzione

SELECTED_REAL_KIND. Questa funzione restituisce in output il numero di byte

(KIND) necessario per memorizzare un tipo reale con la precisione ed il range

richiesti.

Se ad esempio, si vuole lavorare con almeno 18 cifre sigificative in un range in

valore assoluto compreso fra 10

-30

e 10

30

si potranno utilizzare le seguenti

dichiarazioni:

INTEGER, PARAMETER :: mio_reale = SELECTED_REAL_KIND (18,30) REAL(KIND=mio_reale):: a,b,c

Anche per gli INTEGER è possibile ridefinire l'intervallo di ammissibilità tramite la

funzione SELECTED_INT_KIND.

Se ad esempio si desidera lavorare con numeri interi fino a 12 cifre, ovvero

compresi nell'intervallo [-999999999999, +999999999999], si potranno utilizzare le

seguenti dichiarazioni:

INTEGER, PARAMETER :: mio_intero = SELECTED_INT_KIND(12) INTEGER(KIND=mio_intero):: i,j

OPERATORI

Operatore di assegnazione (nome = espressione )

ESEMPIO: S=A+B ; C=C+1 ; A=20

Operatori aritmetici

** elevamento a potenza priorità alta

* moltiplicazione priorità media

/ divisione priorità media

+ addizione priorità bassa

- sottrazione priorità bassa

a parità di priorità ed in mancanza di parentesi le operazioni sono

eseguite da sinistra a destra, ad eccezione dell'operazione di elevamento

a potenza:

A**B**C equivale a A**(B**C)

se un operatore aritmetico opera su operandi di tipo diverso, prima del

calcolo dell'espressiome, tutti gli operandi vengono convertiti nel tipo di

"ordine maggiore" (integer -> real -> double precision -> complex)

nella divisione fra interi il risultato viene troncato

un'espressione reale memorizzata in una variabile intera viene troncata

(esempio: I = 5.6*2 --> I=11)

Operatori di relazione

.EQ. .NE. .LT. .LE. .GT. .GE.

== /= o <> < <= > >=

Operatori logici

.NOT. .AND. .OR.

Operatore di concatenazione stringhe (solo in fortran 90): //

ESEMPIO:Program esempio_concatenazione_stringhe implicit none character(len=20):: nome, ext, nome_file nome='myprog'; ext='f90'! la funzione trim() riporta la stringa senza gli spazi finali nome_file=trim(nome)//'.'//trim(ext) print *, nome_fileend program esempio_concatenazione_stringhe

ESPRESSIONI

aritmetiche

costanti o variabili numeriche separate da operatori aritmetici

di relazione

costanti o variabili di qualsiasi tipo separate da operatori di relazione

logiche

costanti o variabili logiche separate da operatori logici

In mancanza di parentesi vengono prima calcolate le espressioni aritmetiche,

quindi quelle di relazione ed infine quelle logiche.

ESEMPIO:REAL:: a,b,cLOGICAL:: cond1, cond2, trovato

cond1 = (a*b) .EQ. ccond2 = (.NOT.(a == b)) .AND. (b < c)IF ((cond1) .AND. (.NOT.cond2)) .......

....................................IF ((.NOT.tovato).AND.(a > b)) .......

ESEMPIO:Program esempio_uso_logical implicit none integer:: a,b logical:: AmaggioreB

print *, "inserisci a, b" read *, a,b AmaggioreB = a.gt.b print *, "a>b ? ", AmaggioreBend program esempio_uso_logical

SCELTE E DECISIONI

1. IF LOGICO

IF statement

IF (espressione logica) istruzione

ESEMPI: IF (x<0) x=0IF (.not.condizione) GOTO 10IF (condizione.OR.((a.GT.b).AND.(b.LE.0))) a=a+1

IF construct

IF (condizione) THEN

blocco istruzioni

END IF

IF (condizione) THEN

blocco_1

ELSE

blocco_2

END IF

IF (condizione1) THEN

blocco_1

ELSE IF (condizione2) THEN

blocco_2

ELSE IF ......

........

ELSE

blocco_n

END IF

ESEMPIO 1: ! f(x)= funzione caratteristica dell'intervallo [a,b]

IF ((x>=a).AND.(x<=b)) THEN f=1ELSE f=0END IF

ESEMPIO 2: ! f(x)= segno(x) (-1 per x<0, 0 per x=0, 1 per x>0)

IF (x<0) THEN f=-1ELSE IF (x=0) THEN f=0ELSE f=1END IF

2. IF ARITMETICO

IF (espressione aritmetica) label

1

, label

2

, label

3

Il controllo del programma salterà a label

1

se l'espressione aritmetica è negativa, a

label

2

se l'espressione aritmetica è nulla, a label

3

se l'espressione aritmetica è

positiva.

Sintassi obsoleta tipica del fortran 77.

ESEMPI: IF (x) 10,20,30 IF (A-B) 10,10,50

Utilizzando un IF aritmetico, la funzione caratteristica dell'intervallo [a,b] diventa:

C f(x)= funzione caratteristica dell'intervallo [a,b] IF ((x-a)*(b-x)) 10,20,2010 f=0 GOTO 2120 f=121 .......

3. CASE

Il costrutto CASE permette di scegliere fra diverse opzioni. La sintassi è la

seguente:

SELECT CASE (espressione)CASE (scelta_1)

blocco_1..CASE (scelta_n)

blocco_n

END SELECT

L'espressione che appare nell'istruzione SELECT CASE deve essere uno

scalare di tipo INTEGER, CHARACTER o LOGICAL.

Nel caso di espressioni di tipo INTEGER o CHARACTER i valori scelta_1 ...

scelta_n nelle selezioni CASE possono essere degli intervalli espressi nella

forma (valore_min : valore_max) se valore_min è assente vengono selezionati

tutti i valori minori o uguali a valore_max; se valore_max è assente vengono

selezionati tutti i valori maggiori o uguali a valore_min.

la forma generale dei selettori scelta_1 ... scelta_n è una lista di valori e di

intervalli dello stesso tipo, senza sovrapposizioni, come ad esempio

(3, 7, 9:15, 20, 30:)

L'espressione CASE DEFAULT serve a selezionare tutti i valori non inclusi

nelle altre selezioni CASE

ESEMPIO 1:SELECT CASE (I)CASE (:-1) ! I <= -1 segno = -1CASE (0) ! I = 0 segno = 0CASE (1:) ! I >= +1 segno = 1END SELECT

ESEMPIO 2:PROGRAM CARATTERECHARACTER:: CHARCHARACTER(len=10):: TIPO_CHAR

READ *, CHARSELECT CASE (CHAR)CASE (0:9) TIPO_CHAR = 'numerico'CASE (a:z)

TIPO_CHAR = 'minuscolo'CASE (A:Z)

TIPO_CHAR = 'maiuscolo'CASE DEFAULT

TIPO_CHAR = 'altro'END SELECTPRINT *, TIPO_CHAR

STOP END

ESEMPIO 3:Program esempio_uso_case implicit none character(len=25):: domanda,nome character(len=10):: lingua character (len=13):: risposta

print *,"scegli la lingua (inglese,italiano, spagnolo,francese)" read *, lingua select case (lingua) case ('italiano') domanda = 'come ti chiami?' risposta = 'Salve ' case ('spagnolo') domanda ='Como te llamas?' risposta = 'Buenos dias ' case ('francese') domanda ='comment t''appelles-tu?' risposta = 'Bonjour ' case default domanda ='what is your name?' risposta = 'Good Morning ' end select print *, domanda read *, nome ; print *,risposta, nome stopend program esempio_uso_case

ESECUZIONI CICLICHE

1. CICLO con contatore

La forma generale di un ciclo con contatore in fortran 90 è:

DO contatore=val_iniziale, val_finale [,step]

. . . . .

. . . . .

blocco istruzioni

. . . . .

. . . . .

END DO

contatore è una variabile di tipo integer;

val_iniziale, val_finale, step sono variabili/costanti/espressioni di tipo

integer;

step è opzionale (se non c'è, si assume step=1)

ESEMPIO: do i=1,n print *, i end do

In fortran 77 non si usa l'istruzione END DO.

L'istruzione di apertura di un ciclo con contatore diventa:

DO label_fine_ciclo contatore=valore_iniziale, valore_finale [,step]

label_fine_ciclo è l'etichetta che identifica l'ultima istruzione del ciclo.

ESEMPIO: do 10 i=1,n print *, i 10 continue

Alcune osservazioni:

non si può saltare all'interno di un ciclo DO senza eseguire l'istruzione di

apertura del ciclo;

la variabile DO (il contatore) non può essere modificata all'interno del

ciclo DO;

quando non si usa END DO, l'ultima istruzione del ciclo deve essere

"compiuta" in se stessa e non deve bloccare l'esecuzione del programma.

Non sono quindi ammesse le istruzioni: STOP, END, PROGRAM, DO.

Spesso per chiudere un ciclo (in fortran 77) viene usata l'istruzione CONTINUE;

è possibile costruire cicli DO annidati; il ciclo DO aperto "internamente"

deve essere chiuso prima (o insieme) al ciclo DO aperto "esternamente";

in un ciclo DO si possono utilizzare le istruzioni:

EXIT permette di uscire dal ciclo, trasferendo il controllo alla prima

istuzione dopo END DO;

CYCLE trasferisce il controllo all'istruzione END DO e, se il ciclo non è

giunto al termine, inizia una nuova iterazione;

è possibile etichettare l'istruzione di apertura di un ciclo

ESEMPIO 1:ciclo1: do i=1,n ..... istruzioniciclo2: do j=1,m ..... istruzioni if (condizione) exit --> esce da ciclo2 ..... istruzioni end do ciclo2 ..... istruzioni end do ciclo1

ESEMPIO 2:ciclo1: do i=1,n ..... istruzioniciclo2: do j=1,m ..... istruzioni if (condizione) exit ciclo1--> esce da ciclo1 ..... istruzioni end do ciclo2 ..... istruzioni end do ciclo1

2. CICLO con uscita su condizione

! ciclo di tipo while

DO WHILE (condizione)

. . . . .

blocco istruzioni

. . . . .

END DO

! ciclo di tipo repeat ... until

DO

. . . . .

blocco istruzioni

. . . . .

IF (condizione) EXIT

END DO

Nel ciclo while il blocco di istruzioni, che viene ripetuto fintanto che la

condizione resta vera, potrebbe non essere mai eseguito.

Nel ciclo repeat ... until il blocco di istruzioni, che viene ripetuto fintanto

che la condizione resta falsa, è sempre eseguito almeno una volta.

ESEMPIO ciclo di tipo while: LOGICAL:: convergenza DO WHILE (.NOT.convergenza) ........ | ........ | blocco istruzioni da ripetere ........ | END DO

ESEMPIO ciclo di tipo repeat ... until LOGICAL:: convergenza DO ........ | ........ | blocco istruzioni da ripetere ........ | IF (convergenza) EXIT END DO

In fortran 77 l'istruzione DO WHILE non esiste.

Il ciclo while può essere implementato utilizzando la seguente sintassi:

label1 IF (.NOT.condizione) GO TO label2 ...... blocco istruzioni ......GO TO label1

label2 ........

In fortran 77 l'istruzione DO ... EXIT non esiste.

Il ciclo repeat ... until può essere implementato utilizzando la seguente

sintassi:

label1 ...... blocco istruzioni ......IF (.NOT.condizione) GO TO label1.........

Foglio esercizi n.1

Leggere in input la misura di un angolo in radianti e convertirla in gradi. Stampare a

video il risultato.

1.

Leggere un intero n>=0 e calcolare n!. Stampare a video il risultato.2.

Leggere due interi n, k con 0<=k<=n e calcolare il coefficiente binomiale (n,k) = n!/(k!*

(n-k)!). Stampare a video il risultato.

3.

Leggere un intero n>0 e stampare i primi n termini della successione di fibonacci:

f(1)=1 ; f(2)=1 ; f(i) = f(i-1)+f(i-2), per i=3,...,n

4.

Svolgimento

Program rad2gr! Questo programma converte la misura di un angolo da radianti a gradi implicit none real, parameter :: Pi = acos(-1.0) real :: gradi, radianti print *, "Misura dell'angolo in radianti? " read *, radianti gradi = 180.*radianti/Pi print *, radianti, " radianti = ",gradi," gradi"end program rad2gr

1.

Program fattoriale! attenzione dichiarando la variabile utilizzata per memorizzare! n! come INTEGER, il programma funziona solo con n <= 12, poiche'! per n>13 risulta n! > huge(n) implicit none integer:: n,i,f do print *, 'Calcolo di n! per n = ? (n>=0)' read *,n if (n.ge.0) exit end do f = 1 do i=2,n f= f*i end do print *, 'n! = ',f stop end program fattoriale

2.

Program coefficiente_binomiale! calcola il coefficiente binomiale (n,k) utilizzando! lo schema iterativo:! (n,0) = 1! (n,i) = (n,i-1)*(n-i+1)/i per i=1,...,k implicit none integer:: n,k,bin integer:: i do print *, 'n, k = ? (n>=0, k>=0, n>=k)' read *,n,k if ((k.ge.0).and.(n.ge.k)) exit end do

3.

bin = 1 do i=1,k bin = (bin*(n-i+1))/i end do print *, bin stop end program coefficiente_binomiale

Program fibonacci! Legge in input un intero n>0 e stampa i primi! n termini della successione di fibonacci:! f(1)=1 ; f(2)=1 ; f(i) = f(i-1)+f(i-2), per i=3,...,n implicit none integer:: n, i, f, fm1, fm2 do print *,"Inserire n: (n>0)" read *, n if (n>0) exit end do f=1 ; fm1=0 do i=1,n print *, f fm2=fm1; fm1=f f=fm1+fm2 end do stopend program fibonacci

4.

GLI ARRAY

L'array è una tabella di elementi tutti dello stesso tipo (vettori e matrici fino a 7

dimensioni). Per utilizzare un array è necessario dichiararne il tipo e la dimensione.

La dimensione può essere dichiarata con la direttiva DIMENSION, oppure

direttamente nella dichiarazione di tipo.

ESEMPI: REAL, DIMENSION(50):: X, YLOGICAL, DIMENSION (10,5):: MATINTEGER, PARAMETER :: NMAX=100REAL, DIMENSION(0:NMAX) :: VETREAL a,bINTEGER cDIMENSION a(100), b(10,20), c(15)DOUBLE PRECISION p(-5:5,6,2:11)

Nel dimensionare un array è necessario specificare i valori min e max per gli indici.

Se il valore min non è indicato esplicitamente si assume che questo sia 1. Per riferirsi

ad un elemento dell'array si utilizza il nome dell'array seguito dagli indici, chiusi in

parentesi tonda e separati da virgola. Gli indici possono essere: costanti intere,

variabili intere o espressioni che forniscono un risultato intero.

ESEMPIO: a(I+3), b(5,J*4), p(-3,N,I-2)

ESEMPI di lettura della matrice MAT(10,5):1) read *, MAT <----legge la matrice MAT per colonne2) read *, (MAT(i,j), j=1,5), i=1,10)

3) do i=1,10 read *, (MAT(i,j), j=1,5)

end do

L'array è l'unico tipo di dato "strutturato" disponibile in fortran 77. In fortran 77 tutte

le operazioni sugli array devono essere eseguite elemento per elemento, in fortan 90

invece possono essere eseguite globalmente sull'intero array. Ad esempio, dichiarate

le seguenti matrici

REAL a(10,20), b(10,20), s(10,20)

le seguenti righe di codice fortran 77

DO 10 j=1,20 DO 10 i=1,10 s(i,j) = a(i,j)+b(i,j)

10 CONTINUE

in fortan 90 si riducono alla sola istruzione: s=a+b

In fortran 90 esistono inoltre molte funzioni intrinseche che lavorano sugli array (es.

MAXVAL(x), MINVAL(x), SUM(x), DOT_PRODUCT(x,y), MATMUL(matrix1,matrix2))

GLI ARRAY DINAMICI

Il fortan 90 permette l'utilizzo di ARRAY DINAMICI, tramite l'introduzione dell'attributo

ALLOCATABLE.

ESEMPIO 1: INTEGER n,mREAL, DIMENSION (:,:), ALLOCATABLE :: a..

READ *, n,mALLOCATE (a(n*2,n+m))..DEALLOCATE (a)

.

ESEMPIO 2: Program intervallo ! legge gli estremi di un intervallo [a,b] ! e lo divide in n parti implicit none real:: a,b, com, h real, dimension(:), allocatable:: x integer:: n,i

print *,'Legge gli estremi di un intervallo e', & ' lo divide in n parti'

do print *, 'dammi gli estremi dell''intervallo' read *, a,b if (a.ne.b) exit end do if (a>b) then com=a; a=b; b=com end if do print *, 'n=? (n>0)' read *,n if (n>0) exit end do allocate (x(0:n)) h = (b-a)/n; x(0) = a; print *, a do i=1,n x(i) = x(i-1) + h print *, x(i) end do stop end program

Vedi anche un esempio di utilizzo di funzioni che operano su array

program

arr

ay

implicit none

real, dimension(:,:), allocatable :: mat

integer n,m, i,j

print *

print *, "

ES

EM

PI

DI

UT

ILIZ

ZO

DI

AL

CU

NE

FU

NZ

ION

E C

HE

OP

ER

AN

O S

U A

RR

AY"

print *

print *, "

uti

lizi

amo l

a m

atri

ce m

at(n

,m)"

do

print *, "

n, m

= ?"

read *, n, m

if ((n>0).and.(m>0)) exit

end do

allocate (mat(n,m))

print *, "

ele

men

ti d

ella

mat

rice

per

colo

nna:"

read *, mat

do i=1,n

print *, (mat(i,j), j=1,m)

end do

print *

print *, "

ES

EM

PI

UT

ILIZ

ZO

DI

sum"

print *, "

som

ma

di

tutt

i gli

ele

men

ti d

ell’

arra

y (

scal

are)

:" print *, "

s

um

(mat

) =", sum(mat)

print *, "

som

ma

per

colo

nne

(vet

tore

di

m e

lem

enti

):"

print *, "

s

um

(mat

,1)=", sum(mat,1)

print *, "

som

ma

per

rig

he

(vet

tore

di

n e

lem

enti

):"

print *, "

s

um

(mat

,2)=", sum(mat,2)

print *, "

som

ma

elem

enti

sull

a ri

ga

1 (

scal

are)

:"

print *, "

s

um

(mat

(1,1

:m))

=", sum(mat(1,1:m))

print *, "

som

ma

elem

enti

sull

a co

lonna

3 (

scal

are)

:"

print *, "

s

um

(mat

(1:n

,3))

=", sum(mat(1:n,3))

print *, "

som

ma

elem

enti

posi

tivi

(sca

lare

):"

print *, "

s

um

(mat

,mat

>0)=", sum(mat,mat>0)

print *

print *, "

ES

EM

PI

UT

ILIZ

ZO

DI

pro

duct"

print *, "

pro

dott

o d

i tu

tti

gli

ele

men

ti d

ell’

arra

y (

scal

are)

:" print *, "

p

roduct

(mat

) =", product(mat)

print *, "

pro

dott

o p

er c

olo

nne

(vet

tore

di

m e

lem

enti

):"

print *, "

p

roduct

(mat

,1)=", product(mat,1)

print *, "

pro

dott

o p

er r

ighe

(vet

tore

di

n e

lem

enti

):"

print *, "

p

roduct

(mat

,2)=", product(mat,2)

print *, "

pro

dott

o e

lem

enti

posi

tivi

(sca

lare

):"

print *, "

p

roduct

(mat

,mat

>0)=", product(mat,mat>0)

print *

print *, "

ES

EM

PI

UT

ILIZ

ZO

DI

max

val

e m

axlo

c" print *, "

max

fra

tutt

i gli

ele

men

ti d

ell’

arra

y (

scal

are)

:" print *, "

m

axval

(mat

) =", maxval(mat)

print *, "

max

sull

e co

lonne

(vet

tore

di

m e

lem

enti

):"

print *, "

m

axval

(mat

,1)=",maxval(mat,1)

print *, "

max

sull

e ri

ghe

(vet

tore

di

m e

lem

enti

):"

print *, "

m

axval

(mat

,2)=",maxval(mat,2)

print *, "

indic

i del

max

:" print *, "

m

axlo

c(m

at)=", maxloc(mat)

print *, "

indic

e del

la r

iga

corr

isponden

te a

l m

ax p

er o

gni

colo

nna:"

print *, "

m

axlo

c(m

at,1

)=",maxloc(mat,1)

print *, "

indic

e del

la c

olo

nna

corr

isponden

te a

l m

ax p

er o

gni

riga:"

print *, "

m

axlo

c(m

at,2

)=",maxloc(mat,2)

stop

endMar

11, 10 1

6:3

4P

age 1

/2arr

ay.f

90

OUTPUT DEL PROGRAMMA array.f90

==============================

ESEMPI DI UTILIZZO DI ALCUNE FUNZIONE CHE OPERANO SU ARRAY

utiliziamo la matrice mat(n,m)

n, m = ?

2 3

<−−−−−− DATI IN INPUT

elementi della matrice per colonna:

−1 3

<−−−−−− DATI IN INPUT

2 −4

<−−−−−− DATI IN INPUT

1 5

<−−−−−− DATI IN INPUT

−1.00000000 2.0000000 1.00000000

3.0000000 −4.0000000 5.0000000

ESEMPI UTILIZZO DI sum

somma di tutti gli elementi dell’

arra

y (

scal

are)

: su

m(m

at)

= 6

.0000000

som

ma

per

colo

nne

(vet

tore

di

m e

lem

enti

): su

m(m

at,1

)= 2

.0000000 −

2.0

000000 6

.0000000

som

ma

per

rig

he

(vet

tore

di

n e

lem

enti

): su

m(m

at,2

)= 2

.0000000 4

.0000000

som

ma

elem

enti

sull

a ri

ga

1 (

scal

are)

: su

m(m

at(1

,1:m

))=

2

.0000000

som

ma

elem

enti

sull

a co

lonna

3 (

scal

are)

: su

m(m

at(1

:n,3

))=

6

.0000000

som

ma

elem

enti

posi

tivi

(sca

lare

): su

m(m

at,m

at>

0)=

1

1.0

00000

ES

EM

PI

UT

ILIZ

ZO

DI

pro

duct

pro

dott

o d

i tu

tti

gli

ele

men

ti d

ell’array (scalare):

product(mat) = 120.00000

prodotto per colonne (vettore di m elementi):

product(mat,1)= −3.0000000 −8.0000000 5.0000000

prodotto per righe (vettore di n elementi):

product(mat,2)= −2.0000000 −60.000000

prodotto elementi positivi (scalare):

product(mat,mat>0)= 30.000000

ESEMPI UTILIZZO DI maxval e maxloc

max fra tutti gli elementi dell’

arra

y (

scal

are)

: m

axval

(mat

) =

5

.0000000

max

sull

e co

lonne

(vet

tore

di

m e

lem

enti

): m

axval

(mat

,1)=

3

.0000000 2

.0000000 5

.0000000

max

sull

e ri

ghe

(vet

tore

di

m e

lem

enti

): m

axval

(mat

,2)=

2

.0000000 5

.0000000

indic

i del

max

: m

axlo

c(m

at)=

2

3

indic

e del

la r

iga

corr

isponden

te a

l m

ax p

er o

gni

colo

nna:

m

axlo

c(m

at,1

)= 2

1

2

indic

e del

la c

olo

nna

corr

isponden

te a

l m

ax p

er o

gni

riga:

m

axlo

c(m

at,2

)= 2

3

Mar

11, 10 1

6:3

4P

age 2

/2a

rra

y.f

90

Printe

d b

y A

lessandra

Seghin

i

Thurs

day M

arc

h 1

1, 2010

1/1

arr

ay.f90

Foglio esercizi n.2

Leggere un numero n>=2 e stampare tutti i numeri primi <=n (per trovare i numeri

primi utilizzare il 'crivello di Eratostene').

1.

Leggere un numero n>=0 e stampare le prime (n+1) righe del triangolo di Tartaglia.2.

Esercizio 1 della prova d'esame 3/2007 (senza subroutine e con stampa a video)3.

Esercizio 1 della prova d'esame 3/2004 (senza subroutine e con stampa a video)4.

Svolgimento

Program crivello_eratostene!! Utilizzando il "crivello di Eratostene" stampa tutti i numeri primi <= n.! Il "crivello di Eratostene" fornisce un algoritmo efficiente per l'individuazione ! dei numeri primi: partendo da 2 (primo) si eliminano tutti i multipli di 2.! Quindi si prende il primo numero non eliminato, 3 (primo), e si eliminano tutti i ! multipli di 3 e cosi` via.!implicit noneinteger:: n,i,j,maxfattlogical, dimension (:),allocatable:: primoprint *,"Stampiamo tutti i numeri primi minori di n, n>=2"do print *, "Inserire n: (n>=2)" read *,n if (n.ge.2) exitend doallocate (primo(2:n))primo=.true.maxfatt=int(sqrt(real(n)))do i=2,maxfatt if (.not.primo(i)) cycle do j=i+i, n, i primo(j)=.false. end doend dodo i=2,n if (primo(i)) print *, iend dostop end program crivello_eratostene

1.

Vengono proposte due diverse soluzioni:

-------------------------- soluzione 1 --------------------------program tartaglia1! Stampa delle prime (n+1) righe del triangolo di Tartaglia! si usa un vettore per memorizzare la riga i-esima del triangolo, ! ma non viene sfruttata la simmetria del triangolo di tartaglia!implicit noneinteger, dimension(:), allocatable :: tinteger :: i, j, nprint *, "Stampa delle prime (n+1) righe del triangolo di Tartaglia"do print *, "n=? (n>=0"

2.

read *,n if (n.ge.0) exitend doallocate (t(0:n)); t=0do i=0,n t(i) = 1 do j=i-1, 1, -1 t(j) = t(j)+t(j-1) end do print *, (t(j), j=0,i)end doend program tartaglia1

-------------------------- soluzione 2 --------------------------program tartaglia2! Stampa delle prime (n+1) righe del triangolo di Tartaglia! si usa un vettore per memorizzare la riga i-esima del triangolo! e si sfrutta la simmetria del triangolo!implicit noneinteger, dimension(:), allocatable :: tinteger :: i, j, n, imezzi, im1mezziprint *, "Stampa delle prime (n+1) righe del triangolo di Tartaglia"do print *, "n=? (n>=0)" read *,n if (n.ge.0) exitend doallocate (t(0:n/2)); t=0t(0)=1; print *, t(0)do i=1,n imezzi=i/2; im1mezzi = (i-1)/2 if (mod(i,2)==0) t(imezzi) = t(imezzi-1)*2 do j= im1mezzi, 1, -1 t(j) = t(j)+t(j-1) end do print *, (t(j), j=0,imezzi), (t(j), j=im1mezzi,0,-1) print *, end doend program tartaglia2

TIPI DI DATI DERIVATI

Il fortan 90 consente la definizione di nuovi tipi di dati derivati da combinazione

dei tipi già esistenti.

ESEMPIO 1: ! definizione del tipo persona type persona

character(len=20) cognome, nome integer eta end type persona

! dichiarazione della var studente di tipo persona type (persona):: studente

studente%cognome='Rossi'

studente%nome='Mario' studente%eta=20 oppure studente = persona('Rossi','Mario',20)

read *, studente%cognome, studente%nome, studente%eta oppure read *, studente

ESEMPIO 2: type punto ! definizione del tipo punto real x,y end type punto

type cerchio ! definizione del tipo cerchio type (punto) c real r end type cerchio

! dichiarazione della var gamma di tipo cerchio type (cerchio):: gamma

! gamma e' il cerchio di centro l'origine e raggio 1 gamma%c%x = 0.; gamma%c%y = 0.; gamma%r = 1.

oppure gamma = cerchio(punto(0.,0.), 1.)

ESEMPIO 3: program esempio_tipi_derivati implicit none

type punto real x,y end type punto

type cerchio type (punto) c real r end type cerchio

type rettangolo type (punto) downleft real base, altezza end type rettangolo

type (punto) :: P type (cerchio) :: c1,c2,c3 type (rettangolo):: r real diag

print *, 'Coordinate del punto P?' ! read *, P%x, P%y !..... o piu` brevemente read *, P print *, 'punto P', P

print *, 'Cerchio c1:' print *, 'coordinate del centro?'; read *, c1%c%x, c1%c%y print *, 'lunghezza del raggio?'; read *, c1%r print *, 'centro e raggio di c1', c1

print *, 'Cerchio c2:' print *, 'coordinate del centro e raggio?'; read *, c2 print *, 'centro e raggio di c2', c2

c3 = cerchio(punto(-1,1), 10.) print *, 'centro e raggio di c3', c3

r = rettangolo(punto(0,2),3,4) diag = sqrt(r%base**2 + r%altezza**2) print *, 'rettangolo estremo sinistro: ',r%downleft print *, 'base, altezza e diagonale', & r%base, r%altezza, diag

stop end program esempio_tipi_derivati

INIZIALIZZAZIONE AREE DI MEMORIA

Su alcuni sistemi tutte le variabili vengono azzerate automaticamente al

caricamento del programma. Per inizializzare opportunamente le aree di memoria

utilizzate si può utilizzare la direttiva DATA.

DATA lista variabili/lista valori/,lista variabili/lista valori/,..

ovviamente ci deve essere "coerenza" in numero, ordine e tipo fra la lista delle

variabili e la lista dei valori assegnati.

ESEMPI:

REAL a,b,cDATA a,b,c/ 3.2, 5.7, -.5E-4/ o analogamenteDATA a/3.2/,b/5.7/,c/-5.E-4/

REAL sum(10), alfa(3), INTEGER m(5,5)CHARACTER(len=10) nomeDATA sum/10*0./, nome/'giulia'/DATA (alfa(i), i=1,3)/10,20,30/ DATA ((m(i,j), i=1,5), j=1,5)/25*0/

L'istruzione DATA viene eseguita al caricamento in memoria del programma prima

dell'inizio dell'esecuzione. È consigliabile collocarla alla fine della parte dichiarativa,

prima delle istruzioni eseguibili.

PROCEDURE: SOTTOPROGRAMMI E FUNZIONI

1. UTILIZZO DI SUBROUTINES

SUBROUTINE nome [(lista parametriformali)]

Direttive per il compilatore

dichiarazionepar.formali,var.locali, var.globali

Istruzioni eseguibili

RETURN

END [SUBROUTINE [nome]]

Nel programma chiamante: CALL nome [(lista parametri attuali)]

Coerenza in numero, ordine e tipo fra la lista dei parametriformali e la lista dei parametri attuali.

Se nella lista dei parametri ci sono vettori, di norma, vienepassata anche la dimensione fra gli argomenti.

ESEMPIO:subroutine dividi_intervallo(p,q,m,y)! divide l'intervallo [p,q] in m parti e restituisce! nel vettore y(0:m) le cordinate degli (m+1) nodi implicit none real:: p, q, y(0:m) integer:: m real:: h integer:: i h = (q-p)/m do i=0,m y(i) = p +i*h end do returnend subroutine dividi_intervallo

..... nel programma chiamante .....

Program intervallo implicit none real:: a,b real, dimension(:), allocatable:: x integer n

........ legge a,b,n

allocate (x(0:n)) call dividi_intervallo(a,b,n,x) print *, xend program intervallo

2. UTILIZZO DI FUNZIONI

[tipo] FUNCTION nome [(lista parametri formali)]

Direttive per il compilatore

Istruzioni eseguibili

RETURN

END [FUNCTION [nome]]

Le funzioni restituiscono al programma chiamante un solovalore.Il tipo della funzione è il tipo della variabile di ritorno. Questa èuna variabile speciale, il cui nome coincide con il nome dellafunzione.Nella sezione eseguibile di una funzione deve sempre esserciun'istruzione del tipo

nome = espressionecon la quale viene assegnato il valore da restituire alprogramma chiamante.

ESEMPIO:

real function distanza (a, b) implicit none real:: a(2),b(2) distanza = sqrt((a(1)-b(1))**2 + (a(2)-b(2))**2) returnend function distanza

..... nel programma chiamante .....

Program esempio_uso_function implicit none real:: p(2),q(2), delta real:: distanza

........ legge p, q

delta = distanza (p,q) print *, deltaend program esempio_uso_function

In fortran 77 Le funzioni costituite da una singola istruzionepossono essere definite come macro-istruzioni utilizzando laseguente sintassi (obsoleta in fortran 90):

nome-funzione(lista parametri formali) = espressione

ESEMPIO: REAL a(2), b(2) REAL distanza distanza(a,b)=sqrt((a(1)-b(1))**2+(a(2)-b(2))**2)

Si chiamano funzioni intrinseche quelle procedure che nondevono essere scritte dal programmatore, ma che già fannoparte del linguaggio stesso. Fra di esse sono comprese tutte leprincipali funzioni matematiche (max, abs, sqrt, exp, sin, cos,etc.). Per una descrizione delle procedure intrinseche, vederead esempio Expanded description of Fortran 90/95 intrinsicprocedures, supplemento al testo "Introduction to Fortran90/95" di S. J. Chapman.

ESEMPI: 1) program calcolo_volume_cilindro implicit none real:: r,h, volume_cil print *, "r,h=?" read *, r,h print *, volume_cil(r,h) stop

end program calcolo_volume_cilindro

real function volume_cil(r,h) implicit none real:: r,h real, parameter :: pi=acos(-1.0) volume_cil=pi*r**2*h return end function volume_cil

2) program controlla_primi ! riceve in input numeri interi e controlla se sono primi implicit none integer:: n logical:: primo do print *, "Inserire n (n<=1 per terminare)" read *,n if (n.le.1) exit if (primo(n)) then print *, n," e` primo" else print *, n," non e` primo" end if end do stop end program controlla_primi

logical function primo(n) implicit none integer:: n integer:: i, maxfatt primo = .true. ! se n e` fattorizzabile, almeno uno dei fattori ! deve essere <= sqrt(n) maxfatt = int(sqrt(real(n))) do i=2,maxfatt if (mod(n,i).eq.0) then primo =.false. exit end if end do return end function primo

3) program norma_di_frobenius_di_una_matrice implicit none

integer:: n real, dimension (:,:), allocatable :: a real:: frobenius_norm do print *, "Inserisci n:" read *,n if (n.gt.0) exit end do allocate (a(n,n)) print *, "Inserisci la matrice a per colonne:" read *,a print *, "Norma di Frobenius di a: ",frobenius_norm(n,a) stop end program norma_di_frobenius_di_una_matrice

real function frobenius_norm(n,a) implicit none integer:: n real, dimension(n,n) :: a integer:: i,j real:: s s = 0. do i=1,n do j=1,n s = s + a(i,j)*a(i,j) end do end do frobenius_norm = sqrt(s)! o piu' brevemente, avendo dichiarato ! real, dimension(n,n) :: b! b=a*a; frobenius_norm=sqrt(sum(b)) return end function frobenius_norm

Vedi Foglio esercizi 3

3. L'ATTRIBUTO INTENT ED IL BLOCCO INTERFACE

Per ciascuno dei parametri formali che una procedura scambia conil programma chiamante, è possibile utilizzare l'attributo INTENTper specificare se il parametro è di input INTENT(in), di outputINTENT(out) o di input/output INTENT(inout).Un parametro con attributo INTENT(in) non può essere modificatodalla procedura. Un parametro con attributo INTENT(out) assumeun valore non definito al momento della chiamata alla procedura.

Tramite la direttiva INTERFACE è possibile fornire ad una unità di

programma un blocco di interfaccia, contenente le informazionirelative alle procedure da esso richiamate.

ESEMPI:1) program lati_triangolo ! Riceve in input le coordinate dei 3 vertici di ! un triangolo e stampa la lunghezza dei 3 lati. implicit none real A(2),B(2),C(2) ! coordinate dei 3 vertici real l1,l2,l3 ! lunghezze dei 3 lati interface subroutine calcola_lati(A,B,C,l1,l2,l3) real, intent(IN) :: A(2), B(2), C(2) real, intent(OUT) :: l1,l2,l3 end subroutine calcola_lati end interface print *, 'dammi le coordinate dei 3 vertici' read *, A, B, C call calcola_lati(A,B,C,l1,l2,l3) print *, l1,l2,l3 end program lati_triangolo

subroutine calcola_lati(A,B,C,l1,l2,l3) implicit none real, intent(IN) :: A(2), B(2), C(2) real, intent(OUT) :: l1,l2,l3 interface real function distanza (P,Q) real, intent(IN) :: P(2),Q(2) end function distanza end interface l1 = distanza(A,B) l2 = distanza(B,C) l3 = distanza(C,A) return end subroutine calcola_lati

2) Vedi svolgimento esercizio 1 del foglio n.3 (area triangolo) con utilizzo di INTENT e INTERFACE.

Vedi Foglio esercizi 4 e Foglio esercizi 5

Foglio esercizi n.3

Scrivere un programma che legga le coordinate di 3 punti del piano, verifichi tramite

un'apposita logical function che i 3 punti non siano allineati e calcoli tramite

un'apposita function l'area del triangolo.

Se i 3 punti sono allineati, mandare un messaggio a schermo.

Suggerimenti:

- condizione di allineamento per 3 punti A=(a1,a2), B=(b1,b2), C=(c1,c2)

(a1-b1)*(c2-b2)=(a2-b2)*(c1-b1)

- formula di Erone per il calcolo dell'area di un triangolo

Area = sqrt(p*(p-l1)*(p-l2)*(p-l3)), con p = semiperimetro, l1,l2,l3 = lati del

triangolo

- per calcolare la lunghezza dei lati scrivere una funzione che calcoli la distanza fra

due punti del piano.

1.

Leggere un intero n>=2 e stampare a video la sua scomposizione in fattori primi

(prima di iniziare la scomposizione, richiamare un'apposita subroutine per individuare

tramite il 'crivello di Eratostene' tutti i numeri primi <= n).

2.

Data una matrice reale A(n,m), scrivere una logical function per verificare che per ogni

riga della matrice A, gli elementi sulla riga siano tutti distinti. Scrivere il main program

per testare la function.

3.

Esercizio 2 della prova d'esame 3/20054.

Esercizio 1 della prova d'esame 2/2006 (con stampa a video)5.

Esercizio 1 della prova d'esame 1/20076.

Svolgimento

Program area_triangolo! Dati 3 punti A,B, C verifica che i 3 punti non siano allineati ! e calcola l'area del triangolo ABC utilizzando la formula di Erone! Area = sqrt(P*(P-L1)*(P-L2)*(P-L3))! con P = semiperimetro, L1,L2,L3 = lati del triangoloimplicit nonereal:: a(2),b(2),c(2), arealogical:: allineatiprint *, 'coordinate del I vertice'; read *, aprint *, 'coordinate del II vertice'; read *, bprint *, 'coordinate del III vertice'; read *, cif (.not.allineati(a,b,c)) then print *, 'area = ', area(a,b,c)else print *, 'punti allineati'end ifstopend program area_triangolo

logical function allineati(a,b,c) implicit none real a(2),b(2),c(2) real com allineati=.false.

1.

com = (a(1)-b(1))*(c(2)-b(2))-(a(2)-b(2))*(c(1)-b(1)) if (com.eq.0) allineati=.true. returnend function allineati

real function area(a,b,c) implicit none real a(2),b(2),c(2) real l1,l2,l3, p real distanza l1 = distanza(a,b) ; l2 = distanza(a,c) ; l3 = distanza(b,c) p =(l1+l2+l3)/2 area = sqrt(p*(p-l1)*(p-l2)*(p-l3)) returnend function area

real function distanza(x,y) implicit none real x(2),y(2) distanza = sqrt((x(1)-y(1))**2 + (x(2)-y(2))**2) returnend function distanza

Vedi anche una soluzione dell'esercizio 1 in cui si utilizzano le direttive INTENT e INTERFACE.

Program scomponi_in_fattori_primi! Legge un intero n>=2 e lo scompone in fattori primi.! Prima di iniziare a scomporre n, si utilizza il crivello di eratostene ! per individuare tutti i numeri primi <= n. implicit noneinteger:: n, m, i, maxfattlogical, dimension(:), allocatable:: primo do print *, 'n = ? (n>=2)' read *, n if (n>=2) exitend doallocate (primo(2:n))call eratostene(n,primo) ! individua tutti i numeri primi <= n if (primo(n)) then print *, n, " e' un numero primo"else print *, 'scomposizione in fattori primi di n = ', n m = n maxfatt=int(n/2) do i=2,maxfatt if (.not.primo(i)) cycle do while (mod(m,i).eq.0) print *, i m = m/i end do if (m.eq.1) exit end doend ifend program scomponi_in_fattori_primi

subroutine eratostene(n,primo) implicit none integer n logical primo(2:n) integer i,j,maxfatt

2.

primo=.true. maxfatt = int(sqrt(real(n))) do i=2,maxfatt if (.not.primo(i)) cycle do j=i+i,n,i primo(j)=.false. end do end do returnend subroutine eratostene

Program controlla_matrice! Controlla che su ogni riga della matrice A, gli elementi siano! tutti distinti implicit none integer:: n,m,i,j real, dimension(:,:), allocatable :: a logical:: elementi_righe_distinti do print *, "dammi n e m (n>0, m>0)" read *, n, m if ((n>0).and.(m>0)) exit print *, "immettere n e m positivi" end do allocate (a(n,m)) print *, "elementi della matrice A per riga" do i=1,n read *, (a(i,j), j=1,m) end do if (elementi_righe_distinti(n,m,a)) then print *, "su ogni riga, gli elementi sono tutti distinti" else print *, "ci sono righe con elementi non tutti distinti" endif stopend program controlla_matrice

logical function elementi_righe_distinti(n,m,a) implicit none integer n,m,i,j,k,mm1 real, dimension(n,m) :: a real ele mm1=m-1 elementi_righe_distinti=.false. do i=1,n do j=1,mm1 ele = a(i,j) do k=j+1,m if (ele == a(i,k)) return end do end do end do elementi_righe_distinti=.true. returnend

3.

Esempio di utilizzo INTENT e INTERFACE

Si propone una soluzione dell'esercizio 1 del foglio n.3 con utilizzo di INTENT e

INTERFACE.

Esercizio

Scrivere un programma che legga le coordinate di 3 punti del piano, verifichi tramite

un'apposita logical function che i 3 punti non siano allineati e calcoli tramite

un'apposita function l'area del triangolo.

Se i 3 punti sono allineati, mandare un messaggio a schermo.

Suggerimenti:

- condizione di allineamento per 3 punti A=(a1,a2), B=(b1,b2), C=(c1,c2)

(a1-b1)*(c2-b2)=(a2-b2)*(c1-b1)

- formula di Erone per il calcolo dell'area di un triangolo

Area = sqrt(p*(p-l1)*(p-l2)*(p-l3)), con p = semiperimetro, l1,l2,l3 = lati del

triangolo

- per calcolare la lunghezza dei lati scrivere una funzione che calcoli la distanza fra

due punti del piano.

Svolgimento

Program area_triangolo! Dati 3 punti A,B, C verifica che i 3 punti non siano allineati ! e calcola l'area del triangolo ABC utilizzando la formula di Erone! Area = sqrt(P*(P-L1)*(P-L2)*(P-L3))! con P = semiperimetro, L1,L2,L3 = lati del triangolo!! Nel programma si utilizzano le direttive INTENT e INTERFACEimplicit nonereal:: a(2),b(2),c(2)interface function allineati(a,b,c) logical:: allineati real, intent(in) :: a(2),b(2),c(2) end function allineati

function area(p1,p2,p3) real:: area real, intent(in):: p1(2),p2(2),p3(2) end function area end interface

print *, 'coordinate del primo vertice:'; read *, aprint *, 'coordinate del secondo vertice:'; read *, bprint *, 'coordinate del terzo vertice:'; read *, cif (allineati(a,b,c)) then print *, 'I punti sono allineati'else print *, 'Area totale = ', area(a,b,c)end ifstopend program area_triangolo

function allineati(a,b,c) implicit none logical:: allineati real, intent(in) :: a(2),b(2),c(2) real:: prova allineati=.false. prova=(c(1)-a(1))*(b(2)-a(2))-(c(2)-a(2))*(b(1)-a(1)) if (prova==0) allineati=.true. returnend function allineati

function area(p1,p2,p3) implicit none real:: area real, intent(in):: p1(2),p2(2),p3(2) real:: l1,l2,l3,semip interface function distanza (p1,p2) implicit none real :: distanza real, intent(in) :: p1(2), p2(2) end function distanza end interface l1=distanza(p1,p2) l2=distanza(p2,p3) l3=distanza(p3,p1) semip=(l1+l2+l3)/2 area = sqrt(semip*(semip-l1)*(semip-l2)*(semip-l3)) returnend function area

function distanza(p,q) implicit none real:: distanza real, intent(in):: p(2),q(2) distanza=sqrt(((p(1)-q(1))**2)+(p(2)-q(2))**2) returnend function distanza

Foglio esercizi n.4

Dato un polinomio di grado n a coefficienti reali

P(x) = p

n

x

n

+ p

n-1

x

n-1

+ ....... + p

1

x + p

o

scrivere una function che calcoli il valore del polinomio P(x) in un punto assegnato x

o

;1.

scrivere una function che calcoli la derivata del polinomio P(x) in un punto assegnato x

o

;2.

scrivere una function che calcoli l'integrale definito del polinomio P(x) in un intervallo [a,b].3.

Scrivere il main program per testare le function.

Per calcolare il valore del polinomio in un punto, utilizzare il metodo di Horner:

P(x) = ((((p

n

x + p

n-1

)x + p

n-2

)x + ....... + p

1

)x + p

o

Svolgimento

real function Polinomio (n,P,x)! calcola il valore del polinomio P di grado n nel punto x! utilizzando il metodo di Horner! P(x) = ((((P[n]x+P[n-1])x+P[n-2])x+ .....)x+P[0] implicit none integer:: n real, dimension(0:n):: P real:: x integer i,nm1 Polinomio = P(n) nm1= n-1 do i=nm1,0,-1 Polinomio = Polinomio*x+P(i) end do returnend function Polinomio

1.

Vengono proposte due diverse soluzioni:

---------------------------- soluzione 1 ----------------------------real function Derivata1 (n,P,x)! calcola la derivata del polinomio P di grado n nel punto x, ! utilizzando il metodo di Horner sul polinomio ottenuto derivando P! dP(x) = ((((nP[n]x+(n-1)P[n-1])x+ .....)x+P[1] implicit none integer:: n real, dimension(0:n):: P real:: x integer i,nm1 Derivata1 = n*P(n) nm1= n-1 do i=nm1,1,-1 Derivata1 = Derivata1*x+i*P(i) end do returnend function Derivata1

---------------------------- soluzione 2 ----------------------------real function Derivata2 (n,P,x)! calcola la derivata del polinomio P di grado n nel punto x, ! calcolando i coefficienti del polinomio ottenuto derivando P

2.

! e poi richiamando la function Polinomio() implicit none integer:: n real, dimension(0:n):: P real:: x integer i,nm1,ip1 real DP(0:n-1), Polinomio nm1=n-1 do i=0,nm1 ip1= i+1 DP(i) = P(ip1)*ip1 end do Derivata2 = Polinomio(nm1,DP,x) returnend function Derivata2

Vengono proposte due diverse soluzioni:

---------------------------- soluzione 1 ----------------------------real function Integrale1 (n,P,a,b)! calcola l'integrale definito in [a,b] del polinomio P di grado n,! utilzzando il metodo di Horner sul polinomio ottenuto integrando! IntP(x) = (((P[n]/(n+1))x+P[n-1]/n)x+....+P[0])x! Integrale = IntP(b) - IntP(a) implicit none integer:: n real, dimension(0:n):: P real:: a,b integer i, nm1 real Inta,Intb, com Inta = P(n)/(n+1) ; Intb = Inta nm1=n-1 do i=nm1,0,-1 com = P(i)/(i+1) Inta = Inta*a + com Intb = Intb*b + com end do Inta = Inta*a ; Intb = Intb*b Integrale1 = Intb - Inta returnend function Integrale1

---------------------------- soluzione 2 ----------------------------real function Integrale2 (n,P,a,b)! calcola l'integrale definito in [a,b] del polinomio P di grado n,! calcolando i coefficienti del polinomio ottenuto integrando P! e poi richiamando la function Polinomio() implicit none integer:: n real, dimension(0:n):: P real:: a,b integer i, np1 real IntP(0:n+1), Polinomio np1= n+1 IntP(0) = 0. do i=1,np1 IntP(i) = P(i-1)/i end do Integrale2 = Polinomio(np1,IntP,b) - Polinomio(np1,IntP,a) returnend function Integrale2

3.

Foglio esercizi n.5

Esercizio 1 della prova d'esame 3/2005 (con stampa a video)1.

Esercizio 1 della prova d'esame 1/2006 (con stampa a video)2.

Esercizio 1 della prova d'esame 2/2007 (con stampa a video)3.

Esercizio 1 della prova d'esame 1/2008

Suggerimento: per generare una matrice A(n,n) di numeri interi random compresi fra 0 e

100, usare le seguenti istruzioni (A è dichiarata come matrice intera di ordine n e B come

matrice reale di ordine n):

call random_seed() ! imposta il seed call random_number(B) ! genera una matrice B di numeri random ! compresi fra 0 e 1 A = int(100*B)

4.

Svolgimento

Le soluzioni sono disponibili sulla pagina delle passate prove d'esame.

4. RICORSIVITÀ

In fortran 90 è possibile utilizzare procedure ricorsive, ovvero procedure che

richiamano se stesse, o che richiamano procedure dalle quali sono a loro volta

richiamate.

L'istruzione di apertura di una subroutine ricorsiva dovrà essere:

RECURSIVE SUBROUTINE nome [(lista parametri formali)]

L'istruzione di apertura di una funzione ricorsiva dovrà essere:

RECURSIVE [tipo] FUNCTION nome [(lista parametri formali)] RESULT (nome-risultato)

In fortran 77 non è ammessa la ricorsività.

ESEMPI:1) Funzione per il calcolo di n!

con procedimento iterativointeger function fatt(n) implicit none integer n,i fatt = 1 do i=2,n fatt = fatt*i end do returnend function

con procedimento ricorsivorecursive function fatt1(n) result (f) implicit none integer n, f if (n <= 1) then f = 1 else f = fatt1(n-1)*n end if returnend function

2) Funzione per il calcolo del coefficiente binomiale

con procedimento iterativointeger function bin(n,k) implicit none integer n,k,i bin = 1 do i=1,k bin = bin*(n-i+1)/i end do returnend function

con procedimento ricorsivorecursive function bin1(n,k) result (binomio) implicit none integer n,k, binomio if (k == 0) then binomio = 1 else binomio = bin1(n,k-1)*(n-k+1)/k end if returnend function

5. PROCEDURE COME ARGOMENTI

Un programma chiamante può passare ad una subroutine, per mezzo dei suoi

argomenti, i nomi di altre procedure.

In questo caso il nome della subroutine, della funzione esterna o della funzione

intrinseca passato come parametro deve comparire nella sezione dichiarativa del

programma chiamante con l'attributo EXTERNAL o INTRINSIC, oppure deve

essere dichiarato in un blocco INTERFACE.

La direttiva:

EXTERNAL nome1,nome2,...

dichiara un elenco di procedure (subroutine e/o function) che potranno essere

utilizzate come argomenti attuali (ovvero come parametri di input per altre

procedure).

La direttiva:

INTRINSIC fun1,fun2,...

dichiara un elenco di funzioni intrinseche che potranno essere utilizzate come

argomenti attuali (ovvero come parametri di input per altre procedure).

ESEMPIO: Program esempio integer:: n real:: x

real, external:: fattoriale intrinsic cos

.... .... CALL SUB1 (n,x,cos,fattoriale) .... .... stop end program esempio

SUBROUTINE SUB1 (m,y,f1,f2) integer:: m

real:: y real, external:: f1,f2

....

Vedi due esempi di sottoprogrammi che ricevono una funzione tra i parametri di

input (formula di quadratura dei trapezi e metodo di bisezione per il calcolo degli zeri di

una funzione).

Vedi Foglio esercizi 6

Esempi di sottoprogrammi che ricevono una funzione fra i parametri

di input

Function per il calcolo del valore approssimato dell'integrale di una funzione tramite la

formula composita dei trapezi.

real function IntTrap(a,b,n,f)! Formula di quadratura del trapezio:! [a,b] intervallo di integrazione! h = (b-a)/n passo di integrazione! x(i) = a+i*h , i=1,...,n-1! IntTrap = h*[f(a)/2+f(x(1))+....+f(x(n-1))+f(b)/2] implicit none real a,b ! estremi dell'intervallo integer n real, external:: f real h,x integer i,nm1 h =(b-a)/n IntTrap = (f(a)+f(b))/2 nm1 = n-1 x=a do i = 1,nm1 x = x+h IntTrap = IntTrap + f(x) end do IntTrap = IntTrap*h returnend function IntTrap(a,b,n,f)

Main program che richiama la funzione IntTrap per calcolare l'integrale approssimato

delle funzioni 3*x^2 e cos(x), utilizzando le direttive EXTERNAL e INTRINSIC.

Program test1_trapezio implicit none real a,b integer n real IntTrap real, external :: g ! o anche real g; external g real, intrinsic :: cos ! o anche intrinsic cos print *, 'calcolo dell''integrale fra a e b della funzione g(x)=3*x^2' print *, 'a,b=?' read *, a,b print *, 'n=?' read *,n print *, IntTrap(a,b,n,g) print * print *, 'calcolo dell''integrale fra a e b della funzione cos(x)' print *, 'a,b=?' read *, a,b print *, 'n=?' read *,n print *, IntTrap(a,b,n,cos) stopend program test1_trapezio

real function g(x) implicit none

1.

real, intent(in) :: x g = 3*x*x returnend function g

Main program che richiama la funzione IntTrap per calcolare l'integrale approssimato

delle funzioni 3*x^2 e cos(x), utilizzando le direttive EXTERNAL e INTRINSIC e il

blocco INTERFACE.

Program test2_trapezio implicit none real a,b integer n intrinsic cos interface real function IntTrap(a,b,n,f) real, intent(in):: a,b integer, intent(in):: n real, external :: f end function IntTrap real function g(x) real, intent(in) :: x end function g end interface print *, 'calcolo dell''integrale fra a e b della funzione g(x)=3*x^2' print *, 'a,b=?' read *, a,b print *, 'n=?' read *,n print *, IntTrap(a,b,n,g) print * print *, 'calcolo dell''integrale fra a e b della funzione cos(x)' print *, 'a,b=?' read *, a,b print *, 'n=?' read *,n print *, IntTrap(a,b,n,cos) stopend program test2_trapezio

real function g(x) implicit none real, intent(in) :: x g = 3*x*x returnend function g

Subroutine che utilizza il metodo di bisezione per il calcolo della radice di una

funzione in un intervallo [a,b] (la funzione f deve essere continua in [a,b] con

f(a)*f(b)<0).

Subroutine bisezione(a,b,tol,nmax,f,radice,trovato)! Metodo di bisezione per il calcolo della radice di una! funzione continua in [a,b] con f(a)*f(b) <0!! QUALCHE COMMENTO SUL METODO DI BISEZIONE! ========================================! CRITERIO DI ARRESTO:! il metodo iterativo si arresta quando l'ampiezza dell'intervallo nel

2.

! quale si cerca la radice e` minore di una tolleranza fissata.!! CONVERGENZA E NUMERO DI ITERAZIONI:! sia [a,b] l'intervallo di partenza entro il quale si cerca la radice,! dopo n iterazioni l'ampiezza dell'intervallo sara` (b-a)/2^n! quindi num.iterazioni = int[log_2((b-a)/tol)]+1.! Il metodo converge quindi sempre in un numero di iterazioni finito! e prevedibile, ma in generale converge lentamente. Una delle cause! e` che il metodo non usa tutte le informazioni disponibili, infatti! usa solo il segno della f agli estremi dell'intervallo e non il valore. !! LIMITI:! l'intervallo di partenza deve contenere una radice;! la convergenza e` lenta (vedi osservazione precedente).! implicit none! dichiarazione parametri formali real a,b ! estremi dell'intervallo contenente la radice real tol ! tolleranza nel calcolo della radice integer nmax ! numero max di iterazioni real, external:: f ! funzione esterna di cui si vuole calcolare la radice real radice logical trovato! dichiarazione variabili locali real sinistra, destra real fs,fd,frad integer i

! inizializzazione variabili trovato = .false. sinistra = a ; destra = b fs = f(sinistra); fd = f(destra) ! controlla che l'intervallo [a,b] contenga una radice if ((fs*fd).gt.0.) return

do i = 1,nmax radice = (sinistra+destra)* 0.5 ; frad = f(radice) if ((radice-sinistra).le.tol) then trovato = .true. ; exit end if if ((fs*frad).gt.0.) then sinistra = radice ; fs = frad else destra = radice ; fd = frad end if end do

returnend subroutine bisezione

Foglio esercizi n.6

Scrivere un programma che legga da tastiera due numeri interi positivi e calcoli il MCD con il

metodo di Euclide basato sulle divisioni successive (implementare il metodo di Euclide in maniera

ricorsiva).

1.

Scrivere una subroutine che riceva in input

due numeri reali a,b

un numero intero positivo n

una funzione reale f

e stampi a video la seguente tabella:

x

o

f(x

o

)

x

1

f(x

1

)

..... .....

..... .....

x

n

f(x

n

)

con x

0

=a, h=(b-a)/n, x

i+1

=x

i

+h, per i=0,.....,n-1.

Testare la subroutine tramite un programma che:

permetta di scegliere fra le seguenti funzioni:

- real external function f1(x) = |x

2

sin(x)|

- real intrinsic function cos(x)

- real external function f2(x) = exp(-x

2

)

a.

legga in input a, b reali con a<b e un intero positivo n;b.

richiami la subroutine per stampare la tabella relativa alla funzione selezionata.c.

2.

Implementazione delle formule composite del punto medio, dei trapezi e di Cavalieri-Simpson per

il calcolo del valore approssimato dell'integrale di una funzione: vedi formule di quadratura ed

esempio implementazione formule di quadratura.

3.

Esercizio 2 della prova d'esame 1/2004 (con stampa a video)4.

Svolgimento

! Calcolo MCD(a,b) con algoritmo di Euclide per divisioni successive ! L'algoritmo si basa sulla seguente proprietà:! dati due interi positivi a,b con a>=b e a=b*q+r! se r=0 => b=MCD(a,b)! se r<>0 => MCD(a,b) = MCD(b,r)

Program Calcola_MCD implicit none integer:: a,b,com integer:: mcd print *, 'Calcolo MCD(a,b)' print *, 'dammi due interi positivi a,b' read *, a,b! se necessario aggiusta i dati in input a=abs(a); b=abs(b) if (a.lt.b) then; com=a; a=b; b=com; end if print *, "MCD = ", mcd(a,b)end program

1.

recursive function mcd(a,b) result (m) implicit none integer:: m, a, b, r r = mod(a,b) if (r==0) then m=b else m=mcd(b,r) end if returnend function

Per completezza si presenta anche un'implementazione del metodo con schema iterativo:

function mcd(a,b) result (m) integer:: m, a, b, r do r=mod(a,b) if (r==0) then m=b; exit else a=b; b=r end if end do returnend function

program stampa_funzione_in_tabella implicit none integer n real a,b real, external:: f1 real, external:: f2 intrinsic cos integer esempio print *, 'Funzione test:' print *, ' [1] abs(x*x*sin(x))' print *, ' [2] cos(x)' print *, ' [3] exp(-x*x)' do print *, 'Scegli la funzione test:' read *, esempio if ((esempio>=1).and.(esempio<=3)) exit end do do print *, "estremi dell'intervallo (a,b):" read *, a,b if (a.lt.b) exit print *, "immettere a<b" end do do print *, "n=? (n>0)" read *, n if (n>0) exit print *, "immettere n>0" end do select case(esempio) case(1) call stampa_tabella(a,b,n,f1) case(2) call stampa_tabella(a,b,n,cos) case(3) call stampa_tabella(a,b,n,f2) end selectstopend program stampa_funzione_in_tabella

2.

subroutine stampa_tabella(a,b,n,f) implicit none real a,b integer n real, external:: f real h,x integer i h=(b-a)/n x=a do i=0,n print *, x, f(x) x=x+h end do returnend subroutine stampa_tabella

real function f1(x) implicit none real x f1= abs(x*x*sin(x)) returnend function f1

real function f2(x) implicit none real x f2= exp(-x*x) returnend function f2

Linguaggi di Programmazione per il calcolo scientifico

Formule di quadratura

Problema: Data la funzione f : [a, b]→ IR continua, calcolare il valore dell’integrale∫ b

a

f(x)dx

Siano assegnati in INPUT:

• f , funzione da integrare;

• a, b, estremi dell’intervallo;

• n, numero di suddivisioni dell’intervallo [a, b];

e sia

• h = (b− a)/n

• xi = a+ ih, i = 0, . . . , n

una formula di quadratura ci permette di ottenere un valore approssimato dell’integraledella funzione a partire dai valori di f nei nodi xi, i = 0, . . . , n

Formula composita del punto medio

Int(f, a, b, n) = hn∑i=1

f

(xi−1 + xi

2

)

Formula composita dei trapezi

Int(f, a, b, n) = h

(f(a)

2+

n−1∑i=1

f(xi) +f(b)

2

)

Formula composita di Cavalieri-Simpson

Int(f, a, b, n) =h

6

(f(a) + 2

n−1∑i=1

f(xi) + 4n∑i=1

f

(xi−1 + xi

2

)+ f(b)

)

1

Scrivere una function che calcoli il valore approssimato dell’integrale di una funzionemediante le formule composite del punto medio, dei trapezi e di Cavalieri-Simpson.La function quadratura deve ricevere in INPUT

• a,b estremi dell’intervallo;

• n numero degli intervalli di suddivisione;

• f funzione da integrare;

• metodo (1 punto medio, 2 trapezi 3 cavalieri-simpson)

Testare la function quadratura sui seguenti esempi

1.

∫ π/2

0

cos(x)dx = 1

2.

∫ 2

1

3x2dx = 7

3.

∫ 1

0

xex = 1

2

!! E

sem

pio

di p

rog

ram

ma

zio

ne

in f

90

:!!

pro

gra

mm

a p

er

test

are

i m

eto

di d

i qu

ad

ratu

ra.

!! L

a f

un

ctio

n q

ua

dra

tura

imp

lem

en

ta le

fo

rmu

le c

om

po

site

!!

de

l pu

nto

me

dio

, d

ei t

rap

ezi

e d

i Ca

valie

ri−

Sim

pso

n.

!! I

l ma

in p

rog

ram

te

sta

la f

un

ctio

n q

ua

dra

tura

ca

lco

lan

do

!! g

li in

teg

rali

ap

pro

ssim

ati

di a

lcu

ne

fu

nzi

on

i di p

rova

!! e

co

nfr

on

tan

do

co

n le

so

luzi

on

i esa

tte

.!! !!

!!!!

!!!!

FU

NZ

ION

I T

ES

T !

!!!!

!!!!

!function

f(

x,e

sem

pio

)

implicit

none

real

(kind

=8

)::

f,x

integer

ese

mp

io

select case

(e

sem

pio

)

case

(1)

f=cos

(x)

case

(2)

f=3

*x*x

case

(3)

f=x*

exp

(x)

end

se

lect

return

end

function

f

!!!!

!!!!

!! M

AIN

PR

OG

RA

M !

!!!!

!!!!

!Program

te

st_q

uad

ratu

ra

implicit

none

real

(kind

=8

)::

a,b

integer

:: n

real

(kind

=8

),

external

::

f

integer

me

tod

o,

ese

mp

io

interface

function

q

uad

ratu

ra(a

,b,n

,f,m

eto

do

,ese

mp

io)

real

(kind

=8

)::

qu

ad

ratu

ra real

(kind

=8

)::

a,b

integer

:: n

real

(kind

=8

),

external

:: f

integer

:: m

eto

do

, e

sem

pio

end

function

q

uad

ratu

ra

end

interface

real

(kind

=8

) q

ua

d,s

ol_

esa

tta

,err

character

ris

po

sta

integer

, parameter

:: n

um

_m

eto

di=

3

integer

, parameter

:: n

um

_te

st=

3

character

(len

=4

0),

dimension

(nu

m_

me

tod

i) :

: d

ef_

me

tod

o

data

de

f_m

eto

do

/’

form

ula

com

posi

ta d

el p

unto

med

io’, &

form

ula

com

posi

ta d

ei tr

apez

i’,&

form

ula

com

posi

ta d

i Cav

alie

ri−S

imps

on’/

real

(kind

=8

),

parameter

:: p

ime

zzi=

asin

(1.)

print

*,

"C

alco

lo d

ell’i

nteg

rale

def

inito

di f

(x)

in [a

,b],

tram

ite fo

rmul

e di

qua

drat

ura

"

sel_

ese

mp

io:

do

print

*,

"S

celta

del

la fu

nzio

ne te

st:

"

print

*,

"1)

f(x)

=co

s(x)

co

n [a

,b]=

[0,p

i/2]

(sol

uzio

ne e

satta

= 1

)"

print

*,

"2)

f(x)

=3*

x^2

co

n [a

,b]=

[1,2

]

(sol

uzio

ne e

satta

= 7

)"

print

*,

"3)

f(x)

=x*

exp(

x) c

on [a

,b]=

[0,1

]

(sol

uzio

ne e

satta

= 1

)"

do

read

*,

ese

mp

io

if

((e

sem

pio

.ge.

1).and.

(ese

mp

io.le.

nu

m_

test

))

exit

print

*,

"S

celta

err

ata.

Inse

risci

un

valo

re fr

a 1

e ",

nu

m_

test

end

do

select case

(e

sem

pio

)

case

(1)

a=

0;

b=

pim

ezz

i; so

l_e

satt

a=

1.

case

(2)

a=

1;

b=

2;

sol_

esa

tta

=7

.

case

(3)

a=

0;

b=

1;

sol_

esa

tta

=1

.

end

se

lect

sel_

n:

do

do

print

*,

’n=

?’

read

*,n

if

(n

>0

) exit

end

do

do

me

tod

o=

1,n

um

_m

eto

di

print

*

print

*,

de

f_m

eto

do

(me

tod

o)

Jun

25, 1

2 11

:57

Pag

e 1/

2q

uad

ratu

ra.f

90

qu

ad

= q

ua

dra

tura

(a,b

,n,f

,me

tod

o,e

sem

pio

)

e

rr =

abs

(so

l_e

satt

a−

qu

ad

)

print

*,

"In

tegr

ale

appr

ossi

mat

o =", q

ua

d,

" e

rror

e=",

err

end

do

print

*

print

*,

"V

uoi r

ipet

ere

con

un a

ltro

valo

re d

i n?

"

read

*,

risp

ost

a

if

(risp

ost

a=

="

n")

exit

end

do

se

l_n

print

*,

"V

uoi c

ambi

are

esem

pio?

(s/

n)"

read

*,

risp

ost

a

if

(risp

ost

a=

="

n")

exit

end

do

se

l_e

sem

pio

stop

end

pro

gra

m

!!!!

!!!!

!! F

UN

CT

ION

QU

AD

RA

TU

RA

!!!

!!!!

!!!

function

q

uad

ratu

ra(a

,b,n

,f,m

eto

do

,ese

mp

io)

!!

[a

,b]

inte

rva

llo d

i in

teg

razi

on

e!!

h

= (

b−

a)/

np

ass

o d

i in

teg

razi

on

e!!

x

(i)

=

a+

i*h

,

i=1

,...

,n−

1 implicit

none

real

(kind

=8

)::

qu

ad

ratu

ra real

(kind

=8

)::

a,b

integer

:: n

real

(kind

=8

),

external

:: f

integer

:: m

eto

do

, e

sem

pio

real

(kind

=8

) h

,x integer

i,n

m1

real

(kind

=8

) xm

,s,s

m

h=

(b−

a)/

n

nm

1 =

n−

1

x=a

select case

(me

tod

o)

case

(1

)!

form

ula

co

mp

osi

ta d

el p

un

to m

ed

io

!

in o

gn

i in

terv

allo

[X

(i),

X(i+

1)]

si a

pp

ross

ima

l’in

teg

rale

co

n

!

la f

orm

ula

Q(f

) =

h *

f(

(X(i)+

X(i+

1))

/2 )

! si

ott

ien

e c

osi

’ la

fo

rmu

la c

om

po

sita

de

l pu

nto

me

dio

! h

*[f(

(X(0

)+X

(1))

/2)

+ f

((X

(1)+

X(2

))/2

) +

...

+f(

(X(n

−1

)+X

(n))

/2)]

x

m=

a+

h/2

; sm

=f(

xm,e

sem

pio

)

do

i =

1,n

m1

xm

=xm

+h

; sm

=sm

+f(

xm,e

sem

pio

)

end

do

q

ua

dra

tura

= h

*sm

case

(2

)!

form

ula

co

mp

osi

ta d

ei t

rap

ezi

! in

og

ni i

nte

rva

llo [

X(i),

X(i+

1)]

si a

pp

ross

ima

l’in

teg

rale

co

n

!

la f

orm

ula

Q(f

) =

h/2

* (

f(X

(i))

+ f

(X(i+

1))

! si

ott

ien

e c

osi

’ la

fo

rmu

la c

om

po

sita

de

i tra

pe

zi

!

h*[

f(a

)/2

+f(

X(1

))+

....

+f(

X(n

−1

))+

f(b

)/2

]

qu

ad

ratu

ra =

(f(

a,e

sem

pio

)+f(

b,e

sem

pio

))/2

do

i =

1,n

m1

x

= x

+h

q

ua

dra

tura

= q

ua

dra

tura

+ f

(x,e

sem

pio

)

end

do

q

ua

dra

tura

= q

ua

dra

tura

*h

case

(3

)!

form

ula

co

mp

osi

ta d

i Ca

valie

ri−

Sim

pso

n

!

in o

gn

i in

terv

allo

[X

(i),

X(i+

1)]

si a

pp

ross

ima

l’in

teg

rale

co

n

!

la f

orm

ula

Q(f

) =

h/6

* (

f(X

(i))

+ 4

f(

(X(i)+

X(i+

1))

/2 )

+ f

(X(i+

1))

! si

ott

ien

e c

osi

’ la

fo

rmu

la c

om

po

sita

di C

ava

lieri−

Sim

pso

n

!

h/6

*[f(

a)+

4f(

(X(0

)+X

(1))

/2)

+ 2

f(X

(1))

+ 4

f((X

(1)+

X(2

))/2

) +

2f(

X(2

)) +

!

+

...

. 2

f(X

(n−

1)

)+ 4

f((X

(n−

1)+

X(n

))/2

) +

f(x

(n))

]

xm

=a

+h

/2

s=

0;

sm=

f(xm

,ese

mp

io)

do

i =

1,n

m1

x=

x+h

;

s=s+

f(x,

ese

mp

io)

xm

=xm

+h

; sm

=sm

+f(

xm,e

sem

pio

)

end

do

q

ua

dra

tura

= h

*(f(

a,e

sem

pio

)+4

*sm

+2

*s+

f(b

,ese

mp

io))

/6.

end

se

lect

return

end

function

q

uad

ratu

ra

Jun

25, 1

2 11

:57

Pag

e 2/

2q

uad

ratu

ra.f

90P

rinte

d by

Seg

hini

Mon

day

June

25,

201

21/

1qu

adra

tura

.f90

6. LE VARIABILI GLOBALI

Il passaggio di "informazioni" tra una subroutine ed il

programma chiamante avviene tramite la lista dei parametri

passati come argomenti, o attraverso le variabili globali.

In fortran 90 la condivisione delle variabili fra più unità di

programma si può realizzare utilizzando i MODULI.

ESEMPIO: module dati_condivisi type persona

character(len=20) cognome, nome integer eta end type persona

integer, parameter:: nmax=1000 type(persona), dimension(nmax):: gruppo real p,q END MODULE dati_condivisi

Qualsiasi unità di programma (main program, subroutine,

function) che voglia utilizzare il tipo persona, la costante

nmax, le variabili gruppo, p e q dovrà semplicemente

utilizzare il comando:

USE dati_condivisi

Questa direttiva deve essere inserita all'inizio della sezione

dichiarativa dell'unità di programma, prima di eventuali

direttive IMPLICIT o di qualsiasi dichiarazione esplicita di

variabili.

Vedi esempio di utilizzo di MODULE per la condivisione di

variabili fra main e sottoprogrammi e esercizio1 del foglio

esercizi 7

In fortran 77 l'unità di programma MODULE non esiste.

In questo caso, per poter disporre di blocchi di memoria

condivisi da più unità di programma, si utilizzano le aree

COMMON. Le aree COMMON vengono dichiarate nella

sezione dichiarativa del programma con la seguente sintassi:

COMMON /area1/lista variabili

COMMON /area2/lista variabili

Un'area COMMON è identificata da un unico nome globale al

quale devono riferirsi tutte le unità di programma che

vogliono accedervi.

Se nel programma si utilizza una sola area COMMON, il nome

può essere omesso:

COMMON lista variabili

L'accesso alle variabili contenute nell'area COMMON avviene

in base alla locazione di memoria all'interno del blocco:

differenti unità di programma possono utilizzare nomi diversi

per le variabili all'interno del blocco pur di rispettarne il tipo,

l'ordine ed il numero.

ESEMPIO: REAL X,Y,Z,A(10) <---- nel main COMMON /area/X,Y,Z,A

REAL P,Q(12) <---- nella subroutine COMMON /area/P,Q

Variabili di tipo numerico e di tipo character devono essere

dichiarate in aree COMMON diverse.

In fortran 90, l'area COMMON definita nell'esempio

precedente può essere realizzata utilizzando un MODULE:

MODULE area REAL x,y,z,a(10)END MODULE area

Qualsiasi unità di programma che voglia utilizzare le variabili

x, y, z, a dovrà includere la direttiva:

USE area

Esempio di utilizzo MODULE

Si propone esempio di utilizzo dell'unità di programma MODULE per la condivisione di variabili

fra main e sottoprogrammi.

Esercizio

Scrivere un programma che legga un numero dispari positivo n <=79 e disegni un triangolo

isoscele di base n. Ad esempio per n=7 il programma dovrà disegnare:

* *** ***** *******

Svolgimento

Module dati integer, parameter :: maxbase = 79 integer n character, dimension(maxbase):: lineaend module dati

Program esempio_uso_module use dati implicit none call leggi_len_base call disegna_triangolo stopend program esempio_uso_module

Subroutine leggi_len_base use dati implicit none do print 100, maxbase100 format('Base del triangolo = ? (numero dispari positivo <= ', i2,')') read *, n if ((n.gt.0).and.(n.le.maxbase).and.(mod(n,2).eq.1)) exit end do returnend subroutine leggi_len_base

Subroutine disegna_triangolo use dati implicit none integer num,i,j do i=1,n,2 linea= ' ' num = (n-i)/2 linea(num+1:num+i)='*' print *, linea ! o anche "print *, (linea(j), j=1,n)" end do returnend subroutine disegna_triangolo

7. FUNZIONI DI TIPO ARRAY E DI TIPO DERIVATO

Una function può restituire al programma chiamante non soltantouno scalare, ma anche un array (array valued function) o unavariabile di tipo derivato, come nei seguenti esempi.

ESEMPIO 1: funzione di tipo array !! Dato un punto p0=(x0,y0) e una retta r: y = m*x + q calcolare ! la proiezione ortogonale di p0 su r !! La proiezione p1 si calcola come intersezione della retta r e ! della retta r1, perpendicolare a r passante per p0! r1: y = -1/m*(x-x0) + y0 !! La proiezione p1 e' il punto di coordinate! x1 = (x0-m*q+m*y0)/(m2+1)! y1 = m*x1 + q!function proiezione(p0,m,q) result(p1) real, dimension(2):: p0,p1 real m,q p1(1) = (p0(1) - q*m + m*p0(2))/(m*m+1) p1(2) = m*p1(1) + q returnend function proiezione

program esempio_uso_array_valued_function implicit none real, dimension(2):: p real:: m,q interface function proiezione(p0,m,q) result(p1) real, dimension(2):: p0,p1 real m,q end function proiezione end interface

print *, 'coordinate del punto P ?' read *, p print *, 'retta su r cui proiettare: m? q?' read *, m,q print *, 'Proiezione di P su r: ', proiezione(p,m,q)end program

ESEMPIO 2: funzione di tipo derivato !! Dato un punto p0=(x0,y0) e una retta r: y = m*x + q calcolare ! la proiezione ortogonale di p0 su r !! La proiezione p1 si calcola come intersezione della retta r e ! della retta r1, perpendicolare a r passante per p0! r1: y = -1/m*(x-x0) + y0 !! La proiezione p1 e' il punto di coordinate! x1 = (x0-m*q+m*y0)/(m2+1)! y1 = m*x1 + q!module MieDef type punto real x,y end type punto contains function proiezione(p0,m,q) result(p1) type (punto):: p0,p1 real m,q p1%x = (p0%x - q*m + m*p0%y)/(m*m+1) p1%y = m*p1%x + q return end function proiezioneend module

program esempio_uso_funzione_tipo_derivato use MieDef implicit none type(punto):: p real:: m,q

print *, 'coordinate del punto P ?' read *, p print *, 'retta su r cui proiettare: m? q?' read *, m,q print *, 'Proiezione di P su r: ', proiezione(p,m,q)end program

ISTRUZIONI DI INPUT/OUTPUT

Le istruzioni di I/O più semplici sono:

READ *, lista di input

PRINT *, lista di output

In queste istruzioni le unità di ingresso/uscita sono le unità standard,normalmente la tastiera in input ed il video in output. Il formato diingresso/uscita è guidato da lista: in input i dati devono essere separati dauno spazio o da una virgola, in output viene utilizzato un "formatoragionevole" per il tipo di dati da stampare, ma non è possibile controllarnein maniera precisa la disposizione. Se si desidera utilizzare un formatodefinito dal programmatore, è necessario specificare nell'istruzione di I/Ola label di un'istruzione FORMAT:

READ label, lista di input

PRINT label, lista di output

Nelle istruzioni di I/O è inoltre possibile indicare altri controlli chepermettono di specificare unità di ingresso/uscita diverse dalle unitàstandard e di gestire eventuali errori.In questo caso la sintassi delle instruzioni di I/O diventa:

READ (lista controlli) lista di input

WRITE (lista controlli) lista di output

Vediamo più in dettaglio le possibili varianti delle istuzioni READ , PRINT ,WRITE e la sintassi dell'istruzione FORMAT

1. ISTRUZIONE READ

READ *, lista di inputlettura da unità standard (di solito la tastiera) con formato diretto dalista (indicato dall'asterisco *)

ESEMPIO: READ *, A, B, C

READ label, lista di inputlettura da unità standard con formato guidato dall'istruzioneFORMAT individuata dall'etichetta label

ESEMPIO: READ 100, A, B, C 100 FORMAT ( ..... )

READ ([UNIT=] u, [FMT=] label1, ERR=label2, END=label3, IOSTAT=ios,...) lista diinput

UNIT = u individua il dispositivo di inputu = * unità di ingresso standard (normalmente latastiera)la tastiera è normalmente indicata anche da u = 5altri numeri di dispositivo possono essere associati afile esterni aperti con un'istruzione OPEN ([UNIT=] u,...).

FMT = label1 label1 identifica l'istruzione FORMAT che guida ilformato dei dati in ingresso (FMT = * indica formatoguidato da lista).

ERR = label2 qualora si verifichi un errore in input, l'esecuzione delprogramma salta all'istruzione con etichetta label2.

END = label3 qualora si incontri il marcatore di EOF (End Of File),l'esecuzione del programma salta all'istruzione conetichetta label3.

IOSTAT = ios ios è una variabile intera nella quale vienememorizzato il risultato dell'operazione di input:ios=0 non ci sono errori e non si incontra EOF

>0 si è verificato un errore<0 in caso di EOF senza errori

ESEMPIO: READ (5,100) A, B, C READ (*,*) P,Q ! lettura di un array con DO implicito READ (3,200,err=20,end=30) (x(i), i=1,n) READ (1,150, IOSTAT=I) Y,Z IF (I .LT. 0) THEN ! fine del file . . ELSE IF (I .GT. 0) THEN ! errore in input . . END IF . . STOP 100 FORMAT ( ..... ) 150 FORMAT ( ..... ) 200 FORMAT ( ..... )

2. ISTRUZIONI PRINT e WRITE

PRINT *, lista di outputscrittura su unità standard (di solito il video) con formato diretto dalista (indicato dall'asterisco *)

ESEMPIO: PRINT *, A, B, C

PRINT label, lista di outputscrittura su unità standard con formato guidato dall'istruzioneFORMAT individuata dall'etichetta label

ESEMPIO: PRINT 200, A, B, C . . 200 FORMAT ( ..... )

WRITE ([UNIT=] u,[FMT=] label) lista di outputUNIT = u individua il dispositivo di output

u = * unità di uscita standard (normalmente il video)la stampante è normalmente indicata da u = 6altri numeri di dispositivo possono essere associati a fileesterni aperti con un'istruzione OPEN ([UNIT=] u, ...).

FMT = label label identifica l'istruzione FORMAT che guida il formatodei dati in uscita (FMT = * corrisponde a formatoguidato da lista).

ESEMPIO: WRITE (*,300) A, B, C 300 FORMAT ( ..... )

! scrittura di una matrice con un DO implicito WRITE (*,*) ((Y(I,J), J=1,M), I=1,N)

3. ISTRUZIONE FORMAT

L'istruzione FORMAT permette di controllare il formato dei dati iningresso/uscita. È un'istruzione non eseguibile, utilizzata da un'altraistruzione (READ o PRINT/WRITE) che la identifica tramite la sua label(deve quindi essere sempre preceduta da una label). Può trovarsi inqualsiasi punto del programma, purchè prima dell'END. Normalmente leistruzioni FORMAT si trovano subito dopo l'istruzione di I/O che leutilizza, oppure tutte in fondo al programma, generalmente dopo loSTOP.La sintassi dell'istruzione è la seguente:

label FORMAT (lista descrittori di formato)

ESEMPIO: WRITE (*,300) J,A 300 FORMAT ('J=', I3, 5X, 'A=', F10.3)

Riportiamo alcuni fra i decrittori di formato usati più comunemente:Iw numero intero con un "campo" di w caratteriFw.d numero reale con un "campo" di w caratteri (compreso segno e virgola) e d cifre

decimaliEs. -15.53478 si può rappresentare con un formato F9.5

Ew.d

numero reale con un "campo" di w caratteri, con d cifre decimali per la mantissa e 4caratteri per l'esponente Es. 3.1416 scitto in formato E12.5 diventa 0.31416E+01 ( = 0.31416*10)

nX lascia n spazi bianchi in output, o ignora n caratteri in input.Tc il prossimo carattere da leggere/scrivere è in colonna cAw variabile di tipo character in un "campo" di w caratteri'...' le stringe devono essere inserite fra apici. Per scrivere il carattere apostrofo (')

usare due apici consecutivi ('')./ sposta alla riga successiva.$ continua sulla stessa riga.

ESEMPI: WRITE (*,400) I,J,IPJ 400 FORMAT ('La somma di ',I3,' e di',I3,' e'' ',I5) WRITE (*,100) soluzione 100 FORMAT (3X, 'la soluzione e'' ',F12.5) WRITE (*,300) j,x(j) 300 FORMAT (5X, 'x(', I3, ')=', F10.3) WRITE (*,350) i, A(i), B(i) 350 FORMAT (T6, I4, T15, F12.5, T30, F12.5) PRINT 380, eps 380 FORMAT ('eps=',e10.3)

! esempi di ripetizione di formato WRITE (*,120) I,J,K 120 FORMAT (3I5) WRITE (*,200) (I, A(I), I=1,10) 200 FORMAT (10(I3, 2X, F10.3, 5X)) WRITE (*,250) (j, x(j), j=1,3) 250 FORMAT (T3, 3(I3, 2X, F15.5, 5X))

! esempio di richiesta di input, senza andare a riga nuova PRINT "('dammi n: ',$)" READ *, n

GESTIONE DEI FILE

Un file è una sequenza di record.

Quando si memorizzano dati in un file, questi possono essereconvertiti dalla loro "rappresentazione interna", in un formasimile a quella usata a video o sulla stampante. In questocaso il file è formato da record formattati.Se i dati sono lasciati nella loro "rappresentazione interna" ilfile è formato da record non formattati. In questo caso il file èessenzialmente una copia della memoria ed i dati vengonoscritti in una forma dipendente dal processore. I file nonformattati possono quindi essere utilizzati da programmi chegirano sullo stesso computer o su computer identici.Se i dati devono essere trasferiti su computer diversi, èpreferibile utilizzare file formattati.

Nei file formattati, ogni record è una sequenza formattata dicaratteri e la lunghezza dei record è misurata in caratteri.Nei file non formattati, ogni record è una sequenza nonformattata di valori e la lunghezza dei record è misurata inbyte o word.

ESEMPIO: le due istruzioni seguenti:WRITE (9,200) (I,A(I),B(I), I=1,N)

200 FORMAT(I3,2F10.4)

producono record formattati di lunghezza 23 caratteri.

L'istruzione WRITE (8) X,Y,Z nella quale non viene specificato il formato,

produce un record non formattato.

I file possono essere di tipo sequenziale o ad accesso diretto.In un file di tipo sequenziale, la scrittura di un record provocala perdita di tutte le informazioni successive.I file ad accesso diretto sono utili quando è necessarioscrivere o leggere record in ordine casuale o quando si vuolesovrascrivere un singolo record. Nei file ad accesso diretto ènecessario che tutti i record abbiano la stessa lunghezza.

Per collegare un file esterno ad una unità di I/O:

OPEN (lista specificatori di apertura)

ESEMPIO: OPEN (9,FILE='risultati.dat',STATUS='old',ERR=50)

Riportiamo alcuni fra i più comuni specificatori di apertura:UNIT=u è l'unico specificatore indispensabile (tutti gli

altri sono facoltativi). Individua il numero diunità di I/O associata al file. La stringa"UNIT=" può essere omessa.

FILE='nome' indica il nome del file

STATUS='st' dove st è una stringa di caratteri che puòassumere uno dei seguenti valori:oldnewreplacescratch il file viene automaticamente cancellato al termine

dell'esecuzione del programma.unknown usato come default in mancanza di specificazione

esplicita.

ACCESS='acc' dove acc è una stringa di caratteri che puòassumere uno dei seguenti valori:sequential l'accesso al file è di tipo sequenziale. Questo tipo di

accesso è usato come default in mancanza dispecificazione esplicita.

direct l'accesso al file è di tipo diretto. In questo caso ènecessario che tutti i record abbiano una lungezzache non superi quella indicata con lo specificatoredi apertura RECL.

RECL=lun indica la lunghezza dei record contenuti nelfile. La lunghezza dei record formattati èmisurata in caratteri. Quella dei record nonformattati è misurata in byte o word.

FORM='fm' dove fm è una stringa di caratteri che puòassumere uno dei seguenti valori:formatted formato di default per i file di tipo sequenziale.unformatted formato di default per i file ad accesso diretto.

ERR = label qualora si verifichi un errore, l'esecuzione delprogramma salta all'istruzione con etichettalabel.

Per scollegare un file esterno, prima del termine

dell'esecuzione del programma:

CLOSE (lista specificatori di chiusura)

ESEMPIO: CLOSE (9, STATUS='keep',ERR=50)

Gli specificatori di chiusura normalmente utilizzati sono:UNIT=u è l'unico specificatore indispensabile (tutti gli

altri sono facoltativi). Individua il numero diunità di I/O associata al file. La stringa"UNIT=" può essere omessa.

STATUS='st' dove st è una stringa di caratteri che puòassumere uno dei seguenti valori:delete il file viene cancellato ed il programma non potrà più

accedervi.keep il file continua ad esistere anche dopo essere stato

scollegato dal programma.

In mancanza di specificazione un file vienechiuso con STATUS='keep', a meno che non siastato aperto con STATUS='scratch', nel qualcaso la chiusura avviene necessariamente conSTATUS='delete'

ERR = label qualora si verifichi un errore, l'esecuzione delprogramma salta all'istruzione con etichettalabel.

Per posizionare il file all'inizio del record precedente:

BACKSPACE u

Per posizionare il file all'inizio del primo record:

REWIND u

Per inserire il record di fine-file (EOF) e posizionare il filedopo quel record:

ENDFILE u

ESEMPI:

1) Inserimento di nuove informazioni in fondo ad un file sequenziale scritto in precedenza

! leggere fino a EOF DO

READ (9, ERR=50, END=21) END DO

! inserire nuove informazioni21 WRITE (9) ......

..........

..........

! chiudere il file con EOFENDFILE 9

2) Scrittura su un file formattato ad accesso diretto

OPEN(7,ACCESS='direct',FORM='formatted',RECL=60)............................................................................

WRITE (7,150,REC=20) (X(I), I=1,50)150 FORMAT (5(F10.3,2X))

Vengono scritti 10 record, ciascuno contenente 5 numeri reali. I record saranno numerati da 20 a 29 e avranno lunghezza pari a 60 caratteri.

Per avere tutte le informazioni relative alle caratteristiche diun file (formattazione, accesso, lunghezza record, etc.):

INQUIRE (lista specificatori)

ESEMPIO 1: INQUIRE (9, ACCESS=acc, FORM=fm, RECL=len)

Nell' esempio 1 si richiedono informazioni sul file associatoall'unità 9.acc e fm sono variabili di tipo carattere, che riporterannorispettivamente i valori 'sequential' o 'direct', per la variabileacc, e 'formatted' o 'unformatted, per la variabile fm. Sesull'unità 9 non è aperto nessun file le due variabiliresteranno indefinite.len è una variabile intera: se sull'unità 9 è aperto un file ad

accesso diretto, len riporterà la lunghezza del record,altrimenti diventerà indefinita.

ESEMPIO 2: INQUIRE (FILE='dati',OPENED=op,NUMBER=n)

Nell'esempio 2 si richiedono informazioni sul file "dati".op è una variabile logica che riporterà il valore .TRUE. se ilfile è collegato ad una certa unità e .FALSE. altrimenti. Ilnumero di unità collegata al file "dati" verrà assegnato allavariabile intera n.

ESEMPIO 3: INQUIRE (FILE='dati',OPENED=op,NUMBER=n) IF (.NOT.op) THEN

OPEN (8,FILE='dati')n = 8

END IF READ (n, ERR=20, END=21) ...... ...............................

Foglio esercizi n.7

Esercizio su tipi derivati e di variabili condivise tramite MODULE:

un magazzino gestisce n prodotti diversi. Ciascun prodotto è identificato dal codice

(integer), dalla descrizione (stringa di 15 caratteri) e dal prezzo (real). Il magazzino,

periodicamente stabilisce una cifra massima (budget) utilizzabile per l'acquisto di

ciascun singolo prodotto (il budget è uguale per tutti i prodotti; se ad esempio il

budget fissato è pari a 100 €, allora per l'acquisto di ciascun tipo di prodotto non si

potranno superare i 100 € di spesa).

Scrivere un'unità di programma di tipo MODULE contenente:

- una direttiva TYPE che definisca una struttura dati idonea a descrivere un

prodotto,

- una variabile reale, rappresentante il budget.

a.

Scrivere un programma che legga in input:

- un intero positivo n

- codice, descrizione e prezzo di n prodotti

- il budget

e poi, tramite un'apposita subroutine, stampi a video una tabella contenente

per ciascun prodotto codice, descrizione, prezzo e numero di pezzi

acquistabili con il budget fissato.

b.

1.

Esercizio 1 della prova d'esame 2/20052.

Fattorizzazione LU di una matrice quadrata con il metodo di Crout (vedi schema

numerico con testo dell'esercizio e svolgimento)

3.

Polinomio interpolante nella forma di Newton (vedi schema numerico con testo

dell'esercizio e svolgimento)

4.

Svolgimento

module dati_comuni type prodotto integer code character(len=15) descrizione real prezzo end type prodotto real budgetend module

Program esempio use dati_comuni implicit none integer n type (prodotto), dimension(:), allocatable :: magazzino integer i

1.

do print *, 'numero dei prodotti contenuti in magazzino ?' read *, n if (n>0) exit print *, 'devi darmi un numero positivo!' end do allocate(magazzino(n)) do i=1,n print *, 'codice, descrizione e prezzo del prodotto ', i read *, magazzino(i) end do do print *, 'budget ?' read *, budget if (budget>0) exit print *, 'il budget deve essere positivo!' end do call stampa_elenco(n,magazzino) stopend program esempio

subroutine stampa_elenco (n, magazzino) use dati_comuni implicit none integer n type (prodotto), dimension(n) :: magazzino integer i, numpezzi do i=1,n numpezzi = budget/magazzino(i)%prezzo print *, magazzino(i), numpezzi end do returnend subroutine stampa_elenco

Linguaggi di Programmazione per il calcolo scientifico

Fattorizzazione LU di una matrice quadrata

Esercizio

Sia A ∈ Rnxn una matrice non singolare che ammette fattorizzazione LU .Calcolare la fattorizzazione LU di A tramite il metodo di Crout:

per i = 1, . . . , n

calcolo i-esima colonna di Llji = aji −i−1∑k=1

ljkuki

j = i, . . . , n

calcolo i-esima riga di Uuii = 1

uij =1

lii(aij −

i−1∑k=1

likukj)

j = i + 1, . . . , n

Scrivere una subroutine in linguaggio fortran che riceva in input un intero n ed unamatrice A ∈ Rnxn non singolare e restituisca al programma chiamante le matrici L e Uottenute con la fattorizzazione di Crout.

Scrivere un main program che

• legga in input un intero n > 0 (controllare che in input sia immesso n > 0);

• legga in input la matrice A ∈ Rnxn (si richiede di leggere la matrice A per righe);

• richiami la subroutine Crout per calcolare le matrici L e U ;

• stampi su file la matrice A e le matrici L e U .

Per testare il programma, utilizzare le matrici

A =

5 0 11 1 11 0 2

da cui L =

5 0 01 1 01 0 9/5

U =

1 0 1/50 1 4/50 0 1

A =

3 0 1−1 2 02 −1 4

da cui L =

3 0 0−1 2 02 −1 7/2

U =

1 0 1/30 1 1/60 0 1

A =

5 0 1 21 3 1 02 0 8 20 1 1 4

da cui L =

5 0 0 01 3 0 02 0 38/5 00 1 11/15 229/57

U =

1 0 1/5 2/50 1 4/15 −2/150 0 1 3/190 0 0 1

Lavorare in doppia precisione e dichiarare le tutte matrici con l’attributo allocatable.

program

te

st_c

rout

integer

n,i,

j

real

(kind

=8

),

dimension

(:,:

),

allocatable

:: A

,L,U

character

:: r

isp

ost

a

print

*,

’C

alco

lo d

ella

fatto

rizza

zion

e di

Cro

ut d

i una

mat

rice

A(n

,n)

’open

(3

, fil

e=

"ris

ulta

ti.tx

t")

iniz

io_

test

: do

do

print

"(’n

>0,

n=

? ’,$

)"; read

*,

n

if

(n

>0

) exit

end

do

allocate

(A

(n,n

), L

(n,n

), U

(n,n

))

L=

0

print

*,

"C

oeffi

cien

ti de

lla m

atric

e A

, per

rig

a"

do

i=1

,n

read

*,

(a(i,j)

, j=

1,n

)

end

do

call

cr

out (

n,A

,L,U

)

write

(3

,*)

"m

atric

e A"

; call

st

ampa

_mat

rice(

n,A

)

write

(3

,*)

"m

atric

e L"

; call

st

ampa

_mat

rice(

n,L

)

write

(3

,*)

"m

atric

e U"

; call

st

ampa

_mat

rice(

n,U

)

write

(3

,20

0)

! o

utp

ut

risu

ltati

de

l te

st c

om

ple

tato

print

"(’v

uoi f

are

un a

ltro

test

(y/

n)?’

,$)"; read

*,

risp

ost

a

if

(risp

ost

a =

= ’

n’)

exit

deallocate

(A

,L,U

)end

do

iniz

io_

test

close

(3

)stop

20

0 format

(/,

’−

−−

−−

−−

−−

−−

−−

−−

−−

−−

−−

−−

−−

−−

−−

−−

−−

−−

−−

−−

−−

−−

−−

−−

−−

−−

−−’,/)

end

pro

gra

m

Subroutine

cr

out

(n,A

,L,U

)

implicit

none

! d

ich

iara

zio

ne

pa

ram

etr

i fo

rma

li

integer

:: n

real

(kind

=8

),

dimension

(n,n

)::

A,L

,U!

dic

hia

razi

on

i va

ria

bili

loca

li

integer

i,j,k

,im1

real

(kind

=8

)::

s

L

=0

; U

=0

do

i=1

,n

im1

=i−

1

! ca

lco

lo d

ella

i−e

sim

a c

olo

nn

a d

i L

do

j=i,n

s=0

do

k=

1,im

1;

s=s+

l(j,k

)*u

(k,i)

; end

do

l(j,i

)=a

(j,i)

−s

end

do

!

calc

olo

de

lla i−

esi

ma

rig

a d

i U

u

(i,i)

=1

do

j=i+

1,n

s=0

do

k=

1,im

1;

s=s+

l(i,k

)*u

(k,j)

end

do

u(i,j)

= (

a(i,j)

−s)

/l(i,i

)

end

do

end

do

return

mag

05,

15

17:0

1P

age

1/2

solu

zion

e−es

erci

zio−

crou

t.f90

end

su

bro

utin

e

subroutine

st

ampa

_mat

rice

(n

,M)

implicit

none

integer

:: n

integer

:: i,

j

real

(kind

=8

),

dimension

(n,n

)::

M

do

i=1

,n

do

j=1

,n;

write

(3

,10

0)

m(i,j)

; end

do

write

(3

,*)

end

do

10

0 format

(f9

.5,$

)return

end

su

bro

utin

e

ma

tric

e A

5

.00

00

0

0.0

00

00

1

.00

00

0

1.0

00

00

1

.00

00

0

1.0

00

00

1

.00

00

0

0.0

00

00

2

.00

00

0 m

atr

ice

L

5.0

00

00

0

.00

00

0

0.0

00

00

1

.00

00

0

1.0

00

00

0

.00

00

0

1.0

00

00

0

.00

00

0

1.8

00

00

ma

tric

e U

1

.00

00

0

0.0

00

00

0

.20

00

0

0.0

00

00

1

.00

00

0

0.8

00

00

0

.00

00

0

0.0

00

00

1

.00

00

0

−−

−−

−−

−−

−−

−−

−−

−−

−−

−−

−−

−−

−−

−−

−−

−−

−−

−−

−−

−−

−−

−−

−−

−−

−−

−−

ma

tric

e A

3

.00

00

0

0.0

00

00

1

.00

00

0 −

1.0

00

00

2

.00

00

0

0.0

00

00

2

.00

00

0 −

1.0

00

00

4

.00

00

0 m

atr

ice

L

3.0

00

00

0

.00

00

0

0.0

00

00

−1

.00

00

0

2.0

00

00

0

.00

00

0

2.0

00

00

−1

.00

00

0

3.5

00

00

ma

tric

e U

1

.00

00

0

0.0

00

00

0

.33

33

3

0.0

00

00

1

.00

00

0

0.1

66

67

0

.00

00

0

0.0

00

00

1

.00

00

0

−−

−−

−−

−−

−−

−−

−−

−−

−−

−−

−−

−−

−−

−−

−−

−−

−−

−−

−−

−−

−−

−−

−−

−−

−−

−−

ma

tric

e A

5

.00

00

0

0.0

00

00

1

.00

00

0

2.0

00

00

1

.00

00

0

3.0

00

00

1

.00

00

0

0.0

00

00

2

.00

00

0

0.0

00

00

8

.00

00

0

2.0

00

00

0

.00

00

0

1.0

00

00

1

.00

00

0

4.0

00

00

ma

tric

e L

5

.00

00

0

0.0

00

00

0

.00

00

0

0.0

00

00

1

.00

00

0

3.0

00

00

0

.00

00

0

0.0

00

00

2

.00

00

0

0.0

00

00

7

.60

00

0

0.0

00

00

0

.00

00

0

1.0

00

00

0

.73

33

3

4.0

17

54

ma

tric

e U

1

.00

00

0

0.0

00

00

0

.20

00

0

0.4

00

00

0

.00

00

0

1.0

00

00

0

.26

66

7 −

0.1

33

33

0

.00

00

0

0.0

00

00

1

.00

00

0

0.1

57

89

0

.00

00

0

0.0

00

00

0

.00

00

0

1.0

00

00

−−

−−

−−

−−

−−

−−

−−

−−

−−

−−

−−

−−

−−

−−

−−

−−

−−

−−

−−

−−

−−

−−

−−

−−

−−

−−

mag

05,

15

17:0

1P

age

2/2

solu

zion

e−es

erci

zio−

crou

t.f90

Prin

ted

by S

tude

nte

(sen

za p

assw

ord)

mar

tedÃ

¬ m

aggi

o 05

, 201

51/

1so

luzi

one−

eser

cizi

o−cr

out.f

90

Linguaggi di Programmazione per il calcolo scientifico

Interpolazione polinomiale

Dato un insieme di n + 1 nodi t0, t1, . . . , tn appartenenti ad un intervallo [a, b] e i campionamenti yi = f(ti) di unafunzione f calcolata sui nodi ti, i = 0, . . . , n, si vuole trovare una funzione f che approssimi la funzione f , tale dasoddisfare le condizioni di interpolazione f(ti) = yi, i = 0, . . . , n.In particolare, dati i valori (ti, yi), i = 0, . . . , n, con

ti, i = 0, . . . , n nodi di interpolazioneyi, i = 0, . . . , n campionamenti sui nodi in interpolazione

si vuole costruire il polinomio interpolante di grado n che approssima la funzione f .

Polinomio interpolante nella forma di Lagrange

• li(x) =

n∏j=0,j 6=i

x− tjti − tj

, i = 0, . . . , n polinomi elementari di Lagrange

• pn(x) =

n∑i=0

li(x)yi polinomio interpolante di grado n

Polinomio interpolante nella forma di Newton

• di = f [t0, t1, ..., ti], i = 0, . . . , n differenza divisa di ordine i

• pn(x) = d0+(x−t0)d1+(x−t0)(x−t1)d2+ ...+(x−t0)(x−t1)...(x−tn−1)dn polinomio interpolante di grado n

Per costruire il polinomio interpolante nella forma di Newton e prima necessario calcolare il vettore delle dif-ferenze divise.d0 = f [t0] = y0 differenza divisa di ordine zero di f relativa al nodo t0

d1 = f [t0, t1] =f [t1]− f [t0]

t1 − t0differenza divisa di ordine uno di f relativa ai nodi t0, t1

.....

dn = f [t0, ..., tn] =f [t1, ..., tn]− f [t0, ..., tn−1]

tn − t0differenza divisa di ordine n di f relativa ai nodi t0, ..., tn

Per calcolare il vettore d si parte dalla tabella delle differenze divise

f [t0] ↘f [t1] → f [t0, t1] ↘f [t2] f [t1, t2] → f [t0, t1, t2] ↘f [t3] f [t2, t3] f [t1, t2, t3] → f [t0, t1, t2, t3] ↘. . . . .. . . . .. . . . .

f [tn] f [tn−1, tn] . → f [t0, t1, ..., tn]

con f [tj ] = f(tj) e f [tj , tj+1, ..., tk] =f [tj+1, ..., tk]− f [tj , ..., tk−1]

tk − tj

e si utilizza il seguente schema che restituisce in output la diagonale della tabella, ovvero il vettore d:

Calcolo del vettore delle differenze diviseper i = 0, 1, ..., n

di = yiendper i = 1, 2, ..., n

per k = n, n− 1, ..., idk = (dk − dk−1)/(tk − tk−i)

endend

Una volta calcolato il vettore d, il valore del polinomio interpolante nella forma di Newton in un punto x puoessere ottenuto con lo schema di Horner:

Schema di Horner per il calcolo del polinomio interpolante in xP = dnper i = n− 1, n− 2, ..., 0

P = di + (x− ti) ∗ Pend

ESERCIZIO

Scrivere in linguaggio fortran la function differenze divise che riceve dal programma chiamante:• n grado del polinomio interpolante• t vettore dei nodi di interpolazione t0, t1, . . . , tn• y vettore dei campionamenti y0, y1, . . . , yn

e restituisce il vettore delle differenze divise.

Scrivere in linguaggio fortran la function poli newton che riceve dal programma chiamante:• n grado del polinomio interpolante• t vettore dei nodi di interpolazione t0, t1, . . . , tn• d vettore delle differenze divise d0, d1, . . . , dn• x punto sul quale calcolare il valore del polinomio interpolante

e restituisce il valore del polinomio interpolante calcolato in x.

Scrivere in linguaggio fortran un programma che:

1. legge in input a, b estremi dell’intervallo di interpolazione ed n grado del polinomio interpolante

2. calcola i nodi ti = a+ i h, i = 0, . . . , n, con h = (b− a)/n

3. calcola i valori yi = f(ti), i = 0, . . . , n, con f external function

4. utilizzando la function differenze divise, calcola il vettore delle differenze divise

5. utilizzando la function poli newton, calcola il valore del polinomio interpolante su una griglia di (10n+ 1) punti,salva il risultato su file e restituisce la norma infinito della differenza fra f e poli sui punti della griglia.Piu in dettaglio:per j = 0, . . . ,m, con m = 10n e k = (b− a)/m- calcola xj = a+ j k e pj valore del polinomio interpolante in xj- stampa su file xj , pj , f(xj)Al termine del ciclo, stampa a video il max dell’errore |pj − f(xj)| con j = 0, . . . ,mSuggerimento: non servono vettori, tutto in un unico ciclo con xj e pj scalari

6. richiama il programma gnuplot per disegnare il grafico della funzione f e del polinomio interpolante

Testare il programma sulla funzione f(x) = exp(x) sin(2π x)

Lavorare in doppia precisione e dichiarare tutti gli array come allocatable.Nella funzione test f , definire π come costante di valore pari a arcos(−1).Utilizzare le seguenti funzioni intrinseche:

per calcolare arcos(−1) in doppia precisione dacos(−1.d0)per calcolare exp(x) in doppia precisione dexp(x)per calcolare sin(x) in doppia precisione dsin(x)per calcolare |x| (valore assoluto) in doppia precisione dabs(x)

function

di

ffere

nze_

divi

se (

n,t,y

) result

(d

)! C

alc

ola

il v

etto

re d

elle

diff

ere

nze

div

ise

d(i)=

f[t0

,t1

,...,ti],

i=0

...n

implicit

none

integer

, intent

(IN

):: n

! g

rad

o d

el p

olin

om

io in

terp

ola

nte

real

(kind

=8

),

dimension

(0:n

):: t

! ve

tto

re d

ei n

od

i di i

nte

rpo

lazi

on

e real

(kind

=8

),

dimension

(0:n

):: y

! ve

tto

re d

ei c

am

pio

na

me

nti

ne

i no

di

real

(kind

=8

),

dimension

(0:n

):: d

! ve

tto

re d

elle

diff

ere

nze

div

ise

integer

:: i,

k d

=y

do

i=1

,n

do

k=

n,i,

−1

d

(k)=

(d(k

)−d

(k−

1))

/(t(

k)−

t(k−

i))

end

do

end

do

return

end

fu

nct

ion

function

po

li_ne

wto

n (

n,t,d

,x)

result

(p

)! C

alc

ola

ne

l pu

nto

x il

va

lore

de

l po

lino

mio

inte

rpo

lan

te

! d

i gra

do

n c

ost

ruito

su

i no

di t

_i,

i=0

...n

, co

n! t ve

tto

re d

ei n

od

i di i

nte

rpo

lazi

on

e! d

ve

tto

re d

elle

diff

ere

nze

div

ise

! Il

po

lino

mio

inte

rpo

lan

te s

i esp

rim

e n

ella

fo

rma

di N

ew

ton

! P

(x)

= d

0+

d1

*(x−

t0)+

d2

*(x−

t0)(

x−t1

)+ ...+

dn

*(x−

t0)(

x−t1

)...(x

−t_

n−

1)

! P

er

valu

tare

il v

alo

re d

el p

olin

om

io in

un

pu

nto

, si

util

izza

lo s

che

ma

di H

orn

er

implicit

none

integer

, intent

(IN

):: n

! g

rad

o d

el p

olin

om

io in

terp

ola

nte

real

(kind

=8

),

dimension

(0:n

):: t

! ve

tto

re d

ei n

od

i di i

nte

rpo

lazi

on

e real

(kind

=8

),

dimension

(0:n

):: d

! ve

tto

re d

elle

diff

ere

nze

div

ise

real

(kind

=8

):: x

! p

un

to in

cu

i va

luta

re il

po

lino

mio

real

(kind

=8

):: p

! p

olin

om

io in

terp

ola

nte

ca

lco

lato

in x

integer

:: i

p

=d

(n)

do

i=n

−1

,0,−

1 p

=p

*(x−

t(i))+

d(i)

end

do

return

end

fu

nct

ion

Program

in

terp

ola

! p

rog

ram

ma

pe

r te

sta

re la

"fu

nct

ion

po

li_n

ew

ton

" ! Il

pro

gra

mm

a ....

! −

co

no

sce

f fu

nzi

on

e te

st! −

ric

eve

in in

pu

t! [a

,b] in

terv

allo

di i

nte

rpo

lazi

on

e! n

gra

do

de

l po

lino

mio

inte

rpo

lan

te! −

ca

lco

la! t ve

tto

re d

ei n

od

i di i

nte

rpo

lazi

on

e! y

vetto

re d

ei c

am

pio

na

me

nti

y_i=

f(t_

i), i=

0...n

! d

ve

tto

re d

elle

diff

ere

nze

div

ise

d_

i=f[t_

0,t_

1,...,t_

i], i=

0...n

! −

dis

eg

na

il g

rafic

o d

el p

olin

om

io in

terp

ola

nte

e d

ella

fu

nzi

on

e te

st! su

un

a g

rig

lia d

i m=

10

n+

1 p

un

ti, e

ca

lco

la la

no

rma

infin

ito d

ell’

err

ore

! (d

iffe

ren

za fra

f e

po

li_n

ew

ton

) n

ei p

un

ti d

ella

grig

lia implicit

none

integer

:: n

! g

rad

o d

el p

olin

om

io in

terp

ola

nte

real

(kind

=8

):: a

,b

! e

stre

mi i

nte

rva

llo in

terp

ola

zio

ne

real

(kind

=8

),dimension

(:),

allocatable

:: t

! ve

tto

re d

ei n

od

i di i

nte

rpo

lazi

on

e real

(kind

=8

),dimension

(:),

allocatable

:: y

! ve

tto

re d

ei v

alo

ri y

= f(t

) real

(kind

=8

),dimension

(:),

allocatable

:: d

! ve

tto

re d

elle

diff

ere

nze

div

ise

real

(kind

=8

),external

:: f

! fu

nzi

on

e te

st

interface

function

di

ffere

nze_

divi

se (

n,t,y

) result

(d)

integer

, intent

(IN

):: n

! g

rad

o d

el p

olin

om

io in

terp

ola

nte

real

(kind

=8

),

dimension

(0:n

):: t

! ve

tto

re d

ei n

od

i di i

nte

rpo

lazi

on

e

real

(kind

=8

),

dimension

(0:n

):: y

! ve

tto

re d

ei c

am

pio

na

me

nti

ne

i no

di

real

(kind

=8

),

dimension

(0:n

):: d

! ve

tto

re d

elle

diff

ere

nze

div

ise

end

fu

nct

ion

end

interface

real

(kind

=8

),external

:: p

oli_

ne

wto

n real

(kind

=8

):: x,

h,p

,v,e

rr,c

om

integer

:: i,

j,m character

:: r

isp

ost

a

apr

05, 1

8 13

:33

Pag

e 1/

2in

terp

olaz

ione

−new

ton−

v0.f9

0print

*, "

Cal

colo

del

pol

inom

io in

terp

olan

te n

ella

form

a di

New

ton

"print

*, "

per

la fu

nzio

ne te

st e

xp(x

)*si

n(2p

igre

co*x

)"

s

el_

inte

rva

llo:

do

do

print

’("

estr

emi i

nter

vallo

di i

nter

pola

zion

e [a

,b]?

",$

)’;

read

*, a

,b

if

(a

>b

) then

co

m =

a; a

=b

; b

=co

m;

exit

elseif

(a

<b

) then

exit

end

if

end

do

sel_

gra

do

: do

do

print

’("

grad

o de

l pol

inom

io in

terp

olan

te (

n>0)

? ",

$)’; read

*, n

if

(n

>0

) exit

end

do

allocate

(t(

0:n

), y

(0:n

), d

(0:n

))

h

=(b

−a

)/n

do

i=0

,n; t(

i) =

a+

i*h

; y

(i)

= f(t

(i))

; end

do

! C

alc

ola

le d

iffe

ren

ze d

ivis

e

d

= d

iffe

ren

ze_

div

ise

(n,t,y

)

! D

ise

gn

a il

gra

fico

de

l po

lino

mio

inte

rpo

lan

te e

de

lla fu

nzi

on

e te

st

m

= 1

0*n

! m

+1

nu

me

ro d

i pu

nti

da

util

izza

re p

er

dis

eg

na

re il

gra

fico

h

= (

b−

a)/

m; x=

a;

err

= 0

.d0

open

(3, fil

e=

’gr

afic

o.tx

t’)

do

i=0

,m

x=

a+

i*h

; p

=p

oli_

ne

wto

n(n

,t,d

,x);

v=

f(x)

write

(3

,*)

x, p

, v

err

= max

(err

, dabs

(p−

v))

end

do

close

(3

)

print

*, "

erro

re m

ax n

ei p

unti

utili

zzat

i per

dis

egna

re il

gra

fico

", e

rr

call

pl

ot(’

graf

ico.

txt’)

deallocate

(t, y

, d

)

print

’("

vuoi

cam

biar

e il

grad

o de

l pol

inom

io in

terp

olan

te?

(s/n

) [n

] ",$

)’

read

*, risp

ost

a

if

((r

isp

ost

a.ne.

"s"

).and.

(ris

po

sta

.ne.

"S"

))

exit

end

do

se

l_g

rad

o

print

’("

vuoi

cam

biar

e in

terv

allo

di i

nter

pola

zion

e? (

s/n)

[n] "

,$)

read

*, risp

ost

a

if

((r

isp

ost

a.ne.

"s"

).and.

(ris

po

sta

.ne.

"S"

))

exit

end

do

se

l_in

terv

allo

end

pro

gra

m

subroutine

pl

ot(f

ile_

gra

fico

) implicit

none

character

(len

=*)

:: file

_g

rafic

o

! sc

rive

su

l file

"fil

e_

com

an

di_

gn

up

lot"

i co

ma

nd

i ch

e g

nu

plo

t d

ovr

a’ e

seg

uire

open

(3

,file

="

file_

com

andi

_gnu

plot"

) write

(3

,*)

’se

t titl

e "I

nter

pola

zion

e ne

lla fo

rma

di N

ewto

n"’ write

(3

,*)

’pl

ot "

’,file

_g

rafic

o,’

" w

ith li

nes,

"’,file

_g

rafic

o,’

" us

ing

1:3

with

poi

nts;’

! rich

iam

a g

nu

plo

t call

sy

stem

("

gnup

lot −

pers

ist f

ile_c

oman

di_g

nupl

ot") close

(3,s

tatu

s="

dele

te")

end

su

bro

utin

e

function

f(

x) implicit

none

real

(kind

=8

):: x,

f real

(kind

=8

),

parameter

:: p

i2 =

2.d

0*

dacos

(−1

.d0

) f =

dexp

(x)*

dsin

(pi2

*x)

end

fu

nct

ion

apr

05, 1

8 13

:33

Pag

e 2/

2in

terp

olaz

ione

−new

ton−

v0.f9

0P

rinte

d by

Ale

ssan

dra

giov

edÃ

¬ a

prile

05,

201

81/

1in

terp

olaz

ione

−ne

wto

n−v0

.f90

Foglio esercizi n.8

Implementazione dei metodi numerici espliciti ad un passo per EDO in R

1

1.

Implementazione dei metodi numerici espliciti ad un passo per EDO in R

2

2.

Vedi Metodi numerici espliciti ad un passo per EDO, Esercizio sul metodo di

Runge-Kutta in R

1

(testo e svolgimento).

Linguaggi di Programmazione per il calcolo scientifico

Metodi numerici espliciti ad un passo per EDO

Approssimazione numerica del problema di Cauchy{y′(t) = f(t, y(t)) t ∈ I, y ∈ IRn

y(t0) = y0

Siano assegnati in INPUT:

• f , funzione che descrive il campo vettoriale;

• t0, y0, condizione iniziale;

• tf , tempo finale;

• n, numero di passi;

e sia h = (tf − t0)/n.

Metodo di Eulero per i = 0, . . . , n− 1

yi+1 = yi + hf(ti, yi)

ti+1 = ti + h

Metodo di Eulero modificato (Collatz)per i = 0, . . . , n− 1

yi+1 = yi + hf(ti + h2, yi + h

2f(ti, yi))

ti+1 = ti + h

Metodo di Heunper i = 0, . . . , n− 1

yi+1 = yi + h2(f(ti, yi) + f(ti+1, yi + hf(ti, yi))

ti+1 = ti + h

1

Metodo di Runge Kutta

per i = 0, . . . , n− 1

k1 = f(ti, yi)

k2 = f(ti + h2, yi + h

2k1)

k3 = f(ti + h2, yi + h

2k2)

k4 = f(ti + h, yi + hk3)

yi+1 = yi + h6(k1 + 2k2 + 2k3 + k4)

ti+1 = ti + h

• per y ∈ IR1

Scrivere un programma che calcoli l’approssimazione numerica del problema diCauchy utilizzando i metodi ad un passo espliciti di Eulero in avanti, Eulero modi-ficato, Heun e Runge-Kutta (4 ordine).Si vuole avere in OUTPUT:

– grafico nel piano (t, y) della soluzione approssimata e, quando nota, dellasoluzione esatta;

– la norma infinito del vettore degli errori, quando e nota la soluzione esatta,calcolati sui tempi discreti ti = t0 + hi, i = 0, . . . , n, h = (tf − t0)/n;

Alcuni esempi in IR1 su cui testare il programma.

1. y′ = cos(t), y(0) = 0 sol. esatta: y(t) = sin(t)

2. y′ = −ylny, y(0) = 0.5, sol. esatta: y(t) = e−e(lnln2−t)

3. y′ = −e−(t+y), y(0) = 1, sol. esatta: y(t) = ln(e + e−t − 1)

4. y′ = y(1− y), y(0) = 0.5, sol. esatta: y(t) = et/(1 + et)

5. y′ = 16y(1−y), y(0) = 1/1024, sol. esatta: y(t) = e16t−ln1023/(1+e16t−ln1023)

6. y′ = Ry(1− y/k), y(0) = x0 > 0equazione logistica con tasso di crescita R e termine asintotico K,sol. esatta y(t) = k/(1 + q e−rt), con q = (K − x0)/x0.

• per y ∈ IR2

Scrivere un programma che calcoli l’approssimazione numerica del problema diCauchy utilizzando il metodo di Runge-Kutta (4 ordine).Si vuole avere in OUTPUT il grafico della traiettoria approssimata nel piano dellefasi (x, y).

Alcuni esempi in IR2 su cui testare il programma.

1. x′ = −y, y′ = x

2. x′ = −0.05x− y, y′ = x− 0.05y

3. x′ = y, y′ = −4x

2

Linguaggi di Programmazione per il calcolo scientifico

Esercizio

Scrivere una programma in linguaggio fortran che calcoli l’approssimazione numerica del problema diCauchy {

y′(t) = f(t, y) t ∈ [t0, tf ], y ∈ IR1

y(0) = y0

utilizzando il metodo di Runge Kutta.Testare il programma sul seguente esempio:y′(t) =

et − y cos(t)sin(t)

t ∈ [π

2, 3], y ∈ IR1

y(π2 ) = eπ2

Nota la soluzione esatta y(t) =et

sin(t), si vuole avere in OUTPUT:

• grafico nel piano (t, y) della soluzione approssimata e della soluzione esatta;

• la norma infinito del vettore degli errori calcolati sui tempi discretiti = t0 + i h, i = 0, . . . , ncon n numero di passi e h = (tf − t0)/n passo di discretizzazione nel tempo.

Piu in dettaglio il main program dovra:

a) conoscere

• f(t, y) = (et − y cos(t))/sin(t), funzione che descrive il campo vettoriale;

• t0 = π/2, y0 = eπ2 , condizione iniziale;

• tf ∈ [π/2, 3], tempo finale;

• n, numero di passi;

• sol(t) = et/sin(t), soluzione esatta;

b) calcolare h = (tf − t0)/n

c) richiamare un’apposita subroutine per calcolare la traiettoria approssimata utilizzando il metododi Runge-Kutta. La subroutine dovra ricevere in input t0, y0, n, h, f e dovra restituire in output ilvettore {yi, i = 0, . . . , n}, dove yi rappresenta la posizione all’istante ti.

d) salvare su file la seguente tabella:t0 y0 sol(t0)t1 y1 sol(t1)... ... ...... ... ...tn yn sol(tn)

Calcolare e stampare a video l’errore in norma infinito.

Lavorare in doppia precisione e definire π come costante di valore pari a arcos(−1) (utilizzare la funzioneintrinseca acos).

Per disegnare il grafico della soluzione approssimata e della soluzione esatta nel piano (t, y), utilizzarel’utility gnuplot ed inviare il comando:

gnuplot> plot ”traiettoria.out” with lines, ”traiettoria.out” using 1:3 with points;

dove traiettoria.out e il nome del file sul quale e stata salvata la tabella con la soluzione approssimata ela soluzione esatta.

Program

E

DO

implicit

none

real

(kind

=8

)::

t0,t

f,h

,t,

y0

integer

:: n

real

(kind

=8

),

dimension

(:),

allocatable

::

y

real

(kind

=8

),

external

::

f

integer

i

real

(kind

=8

) ::

so

luzi

on

e,

sol,

err

real

(kind

=8

),

parameter

:: p

igre

co =

acos

(−1

.)

print

*,

"S

oluz

ione

del

pro

blem

a di

Cau

chy:

"

print

*,

"dy

/dt =

(ex

p(t)

−y*

cos(

t))/

sin(

t)

co

n y(

pigr

eco/

2)=

exp(

pigr

eco/

2)"

! scelta della posizione

t0=

pig

reco

/2;

y0 =

exp

(pig

reco

/2)

print

*

print

*,

"S

celta

dei

par

amet

ri di

inpu

t:"

do

print

*,

’tf=

? c

on tf

in [p

igre

co/2

,3]’;

read

*,

tf

if

((t

f <

= 3

.d0

).and.

(tf

>=

pig

reco

/2))

exit

end

do

print

*,

’nu

mer

o di

pas

si, n

=?’;

read

*,n

allocate

(y(

0:n

))

y(

0)

= y

0

h

= (

tf−

t0)/

n

! Calcolo della traiettoria approssimata

call

ru

ngek

utta

(t0

,n,h

,y,f

)

! Salva su file la soluzione approssimata e la soluzione esatta

! e calcola l’errore in norma infinito

open

(3

,file

=’

trai

etto

ria.d

at’,s

tatu

s=’

unkn

own’)

t=t0

err

= 0

.

do

i=0

,n

so

l = s

olu

zio

ne

(t)

write

(3,2

00

) t,

y(i),s

ol

err

= max

(err

,dabs

(y(i)−

sol))

t

=t+

h

end

do

close

(3

)

print

*,

"er

rore

max

nei

nod

i",

err

! Richiama gnuplot per disegnare il grafico

call

pl

ot(’

trai

etto

ria.d

at’)

deallocate

(y)

stop

20

0 format

(3

(f3

0.1

5,2

x))

end

subroutine

ru

ngek

utta

(t0

,n,h

,y,f

) implicit

none

integer

n real

(kind

=8

) t0

, h

, y(

0:n

) real

(kind

=8

),

external

::f

integer

i, n

m1

real

(kind

=8

) t,

hm

ezz

i,ym

ezz

i,tm

ezz

i,t1

,k1

,k2

,k3

,k4

t=

t0 ;

nm

1=

n−

1;

hm

ezz

i = h

/2 do

i=0

,nm

1

t

me

zzi=

t+h

me

zzi;

t1=

t+h

k1

= f

(t,y

(i))

k2

= f

(tm

ezz

i,y(i)+

hm

ezz

i*k1

)

k

3 =

f(t

me

zzi,y

(i)+

hm

ezz

i*k2

)

k

4 =

f(t

1,y

(i)+

h*k

3)

y(i+

1)=

y(i)+

h*(

k1+

2*k

2+

2*k

3+

k4)/

6

t

=t1

May

09,

13

20:1

3P

age

1/2

solu

zion

e−es

erci

zio−

rung

e−ku

tta−R

1.f9

0 end

do

return

end

subroutine

ru

ngek

utta

subroutine

pl

ot(f

ile_

tra

iett

oria

) implicit

none

character

(len

=*)

:: f

ile_

tra

iett

oria

character

(len

=*)

, parameter

:: c

om

ma

nd

= "

/usr

/bin

/gnu

plot

−pe

rsis

t com

andi

_gnu

plot

"! scrive su file i comandi che gnuplot dovra’ eseguire

open

(3

,file

="

com

andi

_gnu

plot"

) write

(3

,*)

’se

t titl

e "T

raie

ttoria

"’ write

(3

,*)

’pl

ot "

’, fil

e_

tra

iett

oria

, ’

" w

ith li

nes,

"’,&

fil

e_

tra

iett

oria

,’"

usin

g 1:

3 w

ith p

oint

s;’

! richiama gnuplot

call

sy

stem

(co

mm

an

d)

close

(3

, st

atu

s="

dele

te")

end

su

bro

utin

e

function

f

(t,x

)! campo vettoriale

implicit

none

real

(kind

=8

)::

f,t,

x

f

= (

exp

(t)−

x*cos

(t))

/sin

(t)

return

end

function

f

function

so

luzi

one

(t)

! soluzione esatta

implicit

none

real

(kind

=8

)::

solu

zio

ne

, t

solu

zio

ne

=

exp

(t)/

sin

(t)

return

end

function

so

luzi

one

May

09,

13

20:1

3P

age

2/2

solu

zion

e−es

erci

zio−

rung

e−ku

tta−R

1.f9

0

Prin

ted

by S

eghi

ni

Thu

rsda

y M

ay 0

9, 2

013

1/1

solu

zion

e−es

erci

zio−

rung

e−ku

tta−

R1.

f90

PUNTATORI

Il fortran 90 introduce il concetto di puntatore, come attributo di un dato. I puntatori

permettono di gestire strutture dati come liste lineari, alberi e grafi.

Esempio di dichiarazione di puntatori:

! PT è il puntatore ad una variabile di tipo realeREAL, POINTER :: PT

! p è il puntatore ad una variabile di tipo "persona"TYPE (persona), POINTER :: p

! c è il puntatore ad una variabile di tipo "cerchio"TYPE (cerchio), POINTER :: c

Su una variabile con attributo pointer si possono utilizzare le seguenti istruzioni:

ALLOCATE (PT)

alloca uno spazio in memoria per una variabile del tipo puntato da PT; lo stato

del puntatore diventa associated.

DEALLOCATE (PT)

rilascia lo spazio in memoria puntato da PT; lo stato del puntatore diventa

disassociated.

NULLIFY (PT)

disassocia il puntatore dal target, lo spazio in memoria non viene rilasciato.

Questa istruzione può essere utilizzata anche per assegnare lo stato

disassociated ad un puntatore con stato indefinito.

ASSOCIATED (PT)

"inquiry intrinsic function" che riporta il valore .TRUE. se il puntatore PT è

associato, il valore .FALSE. altrimenti.

PT2 => PT1

operazione di assegnazione fra puntatori.

È importante tener presente che in un programma fortran lo stesso nome è utilizzato sia

per indicare il puntatore ad una variabile sia per indicare il valore della variabile puntata,

come si vede nel seguente esempio:

1) real, pointer:: p1, p22) real:: c3) allocate(p1)4) p1 = 4.55) p2 => p16) c = p1 + p2

Cosa fanno queste poche righe di codice?

riga 3) viene allocato in memoria uno spazio adatto a memorizzare una variabile reale in singola

precisione (4 byte) e il puntatore p1 viene associato alla locazione di memoria (operazione sul

puntatore p1);

riga 4)

nella locazione di memoria puntata da p1 viene scritto il valore 4.5 (operazione sulla variabile

puntata da p1);

riga 5) il puntatore p2 viene associato alla stessa locazione di memoria alla quale è associato p1; quindi

entrambi i puntatori punteranno alla "casella" di memoria contenente il valore 4.5 (operazione sui

puntatori p1 e p2);

riga 6) alla variabile reale c viene assegnato il valore dato dalla somma dei valori contenuti nelle locazioni

di memoria puntate da p1 e p2 (operazioni sulle variabili puntate da p1 e p2)

LE LISTE LINEARI

Una lista lineare è una successione ordinata di elementi omogenei (tutti dello stesso

tipo), ma, diversamente da un array, gli elementi che compongono la lista non occupano

locazioni di memoria consecutive, ma posizioni qualsiasi, è quindi necessario che ogni

elemento della lista contenga un puntatore che lo colleghi all'elemento successivo.

Un'altra importante differenza fra array e liste è che, mentre la dimensione di un array

deve essere nota a priori e non può essere modificata, la dimensione della lista cambia

dinamicamente ogni volta che si aggiunge o si cancella un elemento.

Un elemento della lista conterrà uno o più campi informazione ed il puntatore

all'elemento successivo, sarà quindi necessario definire un tipo derivato che descriva il

generico elemento della lista:

ESEMPI:1) Elemento di una lista di numeri interi type item integer :: index type (item), pointer :: next end type item

2) Elemento di una lista di punti nel piano R^2 type punto real :: x,y type (punto), pointer :: next end type punto

3) Elemento di una lista di persone type persona character(len=20) cognome, nome integer eta type (persona), pointer :: next end type persona

Una lista lineare è ben costruita e tutti gli elementi sono accessibili se:

si conosce il puntatore al primo elemento;1.

ogni elemento è collegato al successivo tramite il suo campo "puntatore al

successivo" (negli esempi sopra, campo next);

2.

il campo "puntatore al successivo" dell'ultimo elemento punta a NULL e così chiude

la lista.

3.

Riportatiamo di seguito un primo esempio per la costruzione di una lista di numeri interi.

Altri esempi sono disponibili in laboratorio nella cartella /corsi/seghini/LPCS.

ESEMPIO:! Esempio di costruzione e scorrimento di una lista! Costruzione lista "aggiungendo in testa"

Module definizione_lista implicit none

type item integer :: index type (item), pointer :: next end type itemend module definizione_lista

Program lista use definizione_lista implicit none type (item), pointer :: first interface subroutine costruisci_lista (first) use definizione_lista type (item), pointer :: first end subroutine costruisci_lista subroutine stampa_lista (first) use definizione_lista type (item), pointer :: first end subroutine stampa_lista end interface call costruisci_lista(first) call stampa_lista (first) stopend program lista

subroutine costruisci_lista(first) ! costruisce la lista, aggiungendo in testa use definizione_lista implicit none type (item), pointer :: first, current integer key nullify(first) ! inizializza a NULL la testa della lista do print *, 'dammi un elemento della lista (stop per terminare)' read (*,*, ERR=99) key allocate (current) current = item(key,first) ! current%index=key ; current%next => first first => current end do99 returnend subroutine costruisci_lista

subroutine stampa_lista (first) ! scorre e stampa la lista use definizione_lista implicit none type (item), pointer :: first, current current => first do while (associated(current)) print *, current%index current => current%next end do returnend subroutine stampa_lista

La subroutine "costruisci_lista" dell'esempio precedente potrebbe anche essere

strutturata nel seguente modo:

subroutine costruisci_lista(first) use definizione_lista implicit none type (item), pointer :: first integer key interface subroutine aggiungi_in_testa (first,key) use definizione_lista type (item), pointer :: first integer key end subroutine aggiungi_in_testa end interface nullify(first) ! inizializza a NULL la testa della lista do print *, 'dammi un elemento della lista (stop per terminare)' read (*,*,ERR=99) key call aggiungi_in_testa (first,key) end do99 returnend subroutine costruisci_lista

subroutine aggiungi_in_testa(first,key) use definizione_lista implicit none type (item), pointer :: first, current integer key allocate (current) current = item(key,first) ! current%index=key ; current%next => first first => current returnend subroutine aggiungi_in_testa

Foglio esercizi n.9

Alcune operazioni che dovreste saper fare sulle liste:

costruire la lista:

- aggiungere un elemento in testa

- aggiungere un elemento in coda

- inserire un nuovo elemento rispettando un criterio di ordinamento

- costruire la lista con metodo ricorsivo

1.

scorrere la lista per fare un'operazione su ogni elemento della lista (ad esempio

stampare ogni elemento della lista);

2.

eliminare un elemento dalla lista:

- eliminare il primo elemento

- eliminare l'ultimo elemento

- eliminare il primo elemento con una 'chiave' fissata

- eliminare tutti gli elementi con una 'chiave' fissata

3.

invertire una lista;4.

ordinare gli elementi di una lista.5.

Le soluzioni sono disponibli in laboratorio nella cartella /corsi/seghini/LPCS.

PRINCIPALI LIMITI DEL F77 RISPETTO AL F90/F95

rigidità del formato di una riga di programma;

nomi di variabili, procedure, etc. max 6 caratteri;

per variabili e costanti scalari solo i 6 tipi intrinseci.

Non sono ammessi real ed integer di tipo parametrizzato;

dati di tipo strutturato: solo array con gestione "statica" della

memoria. Non sono ammessi array rilocabili, puntatori, tipi di

dati derivati;

non ci sono le istruzioni: case, end do, exit, cycle, do while;

non è ammessa la ricorsività

non ci sono l'unità di programma module e la direttiva use.

NOTE PER UTILIZZO COMPILATORE FORTRAN CON LINUX

Queste pagine sono estratte dalle note del corso "Abilità Informatiche: Introduzione a Unix", Alessandra Seghini

Per stampare questo documento si consiglia di utilizzare la versione in formato PDF.

Alcuni termini da conoscere

FilesystemSu un sistema UNIX i file sono suddivisi in directory (cartelle). Le directory sono organizzategerarchicamente in una struttura ad albero che prende il nome di filesystem. La directory radice èindicata con il simbolo / e prende il nome di root directory.

Home directoryAl login ogni utente si trova posizionato sulla propria home directory.È possibile riferirsi alla home directory di un utente con "~nome_utente", ad esempio ~studente può essereutilizzato per indicare la directory /home/studente/. Ogni utente può riferirsi alla propria home directory semplicemente con il carattere ~, senza specificare lousername.

Directory correnteLa directory corrente di lavoro è quella sulla quale si è posizionati. È possibile conoscere il nome delladirectory corrente, utilizzando il comando pwd. Al login, la directory corrente di un utente è la sua homedirectory.La directory corrente è indicata con il simbolo "."La directory "genitore" della directory corrente è indicata con il simbolo ".."

PathnamePer individuare un file sul sistema, è necessario conoscere il suo pathname, costituito dal nome del file,preceduto dal nome della directory che lo contiene.

/____ .... |__ .... |__ home/ ____ .... | |__ giulia/ ___ .... | | |__ immagini/ ____ .... | | | |__ foto.jpg | | | |__ .... | | |__ .... | |__ paolo/ | |__ .... |__ ... |__ ...

Ad esempio, il nome completo del file foto.jpg contenuto nella directory /home/giulia/immagini/ è/home/giulia/immagini/foto.jpg. Abbiamo così specificato il percorso assoluto, che permette diraggiungere il file foto.jpg a partire dalla radice (/) del filesystem e che, pertanto, è valido qualunque siala directory corrente.È possibile individuare un file anche specificando il percorso relativo, rispetto alla directory sulla quale ci sitrova posizionati, ovvero rispetto alla directory corrente. Se ad esempio siamo sulla directory/home/giulia/, possiamo riferirci al file /home/giulia/immagini/foto.jpg semplicemente indicandoimmagini/foto.jpg (senza il carattere / iniziale). In questo caso, il percorso per raggiungere il filefoto.jpg non parte dalla radice del filesystem, ma dalla directory corrente e, pertanto, è valido solo se ladirectory corrente è /home/giulia/. Nello specificare il pathname di un file, si possono utilizzare i caratteri . , .. e ~ per indicare rispettivamentela directory corrente, la directory di livello superiore rispetto alla directory corrente e la home directory diun utente. Ad esempio, un percorso assoluto per individuare il nostro solito file foto.jpg, è anche~giulia/immagini/foto.jpg.Se la directory corrente è la home directory dell'utente paolo /home/paolo/ (o ~paolo), il percorso relativoper individuare il file foto.jpg sarà ../giulia/immagini/foto.jpg.

Alcuni comandi utili

ls [nome-dir]riporta l'elenco dei file contenuti nella directory nome-dir. Se non è specificato il nome di una directory,riporta l'elenco dei file contenuti nella directory corrente.

archimede%lsMail bookmarks.html help help-alex lq

Qualche opzione del comando ls (è possibile combinare insieme più opzioni):

ls -a [nome-dir]riporta l'elenco di tutti (all) i file contenuti nella directory nome-dir, compresi i file nascosti il cui nomeinizia con il carattere ".". Nell'elenco sono compresi anche i file . e .. , che indicano rispettivamente, ladirectory corrente e la directory "genitore" della directory corrente.

archimede%ls -a. .Mathematica .history bookmarks.html help-alex.. .cshrc Mail help lq

ls -l [nome-dir]riporta l'elenco dei file contenuti nella directory nome-dir, in formato esteso (long).

archimede%ls -latotal 84drwxr-xr-x 5 giulia users 512 Jan 26 08:52 .drwxr-xr-x 31 root root 2560 Jan 26 09:11 ..drwxr-xr-x 8 giulia users 512 Jun 7 2004 .Mathematica-rw-r--r-- 1 giulia users 1487 Nov 29 08:52 .cshrc-rw------- 1 giulia users 2607 Jan 25 15:23 .historydrwx------ 2 giulia users 512 Apr 13 2000 Mail-rw------- 1 giulia users 28244 Jul 17 2002 bookmarks.htmldrwxr-xr-x 2 giulia users 512 Jan 12 2004 helplrwxrwxrwx 1 giulia users 15 Jan 26 08:52 help-alex -> /home/alex/help-rwxr-xr-x 1 giulia users 280 Jun 15 2004 lq

mkdir nome-dircrea una nuova directory

rmdir nome-dirrimuove la directory specificata (deve essere vuota)

cd [nome-dir]cambia directory, spostandosi nella directory indicata. Se nome-dir non è specificato, si sposta nella homedirectory dell'utente

cp file1 file2copia il file file1 sul file file2. Se file2 non esiste, crea un nuovo file, altrimenti lo sovrascrive. Nell'indicare file1 e file2 è necessario specificare, ove necessario, il pathname completo.

mv file1 file2sposta il file file1 sul file file2. Se file2 non esiste, crea un nuovo file, altrimenti lo sovrascrive. Questocomando può essere utilizzato per cambiare il nome di un file o per spostarlo in un'altra directory. Nell'indicare file1 e file2 è necessario specificare, ove necessario, il pathname completo.

rm file1 [file2 file3 ...]elimina il/i file indicati.

more nome-filevisualizza sul terminale il contenuto di un file di testo, mostrando una schermata alla volta. Per scorrereall'interno del documento utilizzare i tasti:

[INVIO] - avanza di una rigabarra spaziatrice - avanza di una schermata

b - torna indietro di una schermataq - esce

Stampa di un file

Il comando lpr nome-file invia il file nome-file alla stampante principale collegata al sistema.Se il file da stampare è un file in formato testo, come ad esempio il sorgente di un programma C o fortran, potràessere necessario trasformare il file in formato postscript, prima di mandarlo in stampa. Ad esempio, perstampare il file mioprog.f90, si potrà utilizzare la sequenza di comandi:

a2ps mioprog.f90 -o mioprog.pslpr mioprog.ps

Il comando a2ps trasforma il file testo ricevuto in input in formato postscript. Se non vengono specificate opzioni,i fogli del file di output saranno orientati in senzo orizzontale e su ogni foglio saranno stampate due pagine. Se sidesidera che il file di output abbia i fogli orientati in senso verticale e che su ogni foglio venga stampata una solapagina, si dovrà utilizzare il comando:

a2ps mioprog.f90 -o mioprog.ps --chars-per-line=80 --columns=1 --portrait

Prima di inviare in stampa il file mioprog.ps, è possibile visualizzarlo a schermo utilizzando il comando:

gv mioprog.ps &

Cenni sull'utilizzo dell'editor emacs

Per editare un file con emacs, inviare il comando:

emacs nome-file &

Il file nome-file sarà caricato nella finestra di editing.

Per uscire da emacs, selezionare "Exit Emacs" alla voce "Files" del pop menù, oppure digitare la sequenza di tasti<CTRL>x <CTRL>c. Se sono state apportate modifiche al file aperto, emacs chiederà la conferma, prima disalvare il file.

Per salvare le modifiche, senza uscire dall'editor, selezionare "Save Buffer" alla voce "Files" del pop menù, oppuredigitare la sequenza di tasti <CTRL>x <CTRL>s.

emacs è un editor di facile utilizzo. Tutto funziona in maniera molto semplice. Il testo viene inseritoautomaticamente nel punto in cui si trova posizionato il cursore. È possibile spostarsi nel testo utilizzando sia ilmouse sia la tastiera. Dai pop menù sono disponibili la maggior parte dei comandi tipici dei programmi di editing(copy, cut, paste, search, etc.)Per maggiori informazioni si rimanda all'help in linea, richiamabile dal pop menù di emacs alla voce "Help".

Editare, compilare ed eseguire un programma fortran

La creazione di un programma scritto in un linguaggio ad alto livello, come il C ed il fortran, prevede diversefasi per arrivare ad ottenere un codice eseguibile:

Creazione del codice sorgente, ovvero scrittura, tramite un editor, del/dei files contenenti le istruzioniche il programma dovrà eseguire.

Compilazione del codice sorgente. In questa fase, il compilatore individua e segnala gli eventuali errori disintassi. È allora necessario utilizzare l'editor per correggere gli errori, salvare il file corretto e quindiricompilare il programma. Una volta eliminati tutti gli errori, il compilatore traduce il codice sorgente incodice oggetto.

Linking (collegamento) di tutti i file oggetto e delle librerie che concorrono a formare il programmaeseguibile.

A questo punto, sarà possibile eseguire il programma.

Vediamo un esempio.

1. Utilizzando un editor creare il file rad2gr.f90, contenente le seguenti righe di codice sorgente:

! Questo programma converte la misura di un angolo da radianti a gradiProgram rad2gr implicit none real, parameter :: Pi = 3.14159 real :: gradi, radianti print *, "Misura dell'angolo in radianti? " read *, radianti gradi = 180.*radianti/Pi print *, radianti, " radianti = ",gradi," gradi"end program rad2gr

Può essere conveniente aprire la finestra di editing in background, utilizzando, ad esempio, il comando

emacs rad2gr.f90&

In questo modo, la shell resterà attiva e sullo schermo saranno disponibili due finestre: la finestra diediting, per correggere gli errori e salvare il file modificato e la shell per compilare.

2. Per compilare, inviare il comando:

gfortran rad2gr.f90

Verranno segnalati eventuali errori, che dovranno essere corretti.f90 eseguirà quindi le operazioni di compilazione e di linking e salverà il programma eseguibile nel filea.out.È possibile assegnare un nome diverso da a.out al programma eseguibile, utilizzando l'opzione -o(output) nel comando di compilazione:

gfortran rad2gr.f90 -o rad2gr

In questo caso, il programma eseguibile verrà salvato nel file rad2gr.

3. Per eseguire il programma, digitare il nome del file completo del percorso:

./rad2gr

Riepilogo delle operazioni da effettuare per l'esercitazione in laboratorio

L'esercitazione si svolge nel Laboratorio didattico di Calcolo, utilizzando il GNU Fortran Compiler in ambienteLinux.

OPERAZIONI INZIALI

1. Accendere il computer, attivare il s.o. linux e collegarsi al sistema.Aprire una shell, ovvero una finestra nella quale è attivo l'interprete dei comandi (shell) checonsente di interagire con il sistema operativo.

2. Creare sull'hard disk una directory di lavoro e posizionarcisi:

mkdir miadir cd miadir

3. Se necessario, montare la pendrive usb e copiare il sorgente del programma sul quale si develavorare sulla directory di lavoro miadir:

cp /media/nome_usb_device/mioprog.f90 .

ESERCITAZIONE

4. Editare, compilare ed eseguire il programma:

emacs mioprog.f90 & per editare

gfortran mioprog.f90 -o mioprog per compilare

./mioprog per eseguire

Attenzione: ogni volta che si modifica il sorgente con l'editor, è necessario salvare il file modificato epoi ricompilare.

OPERAZIONI FINALI

5. Se necessario, copiare il sorgente del programma sul quale si è lavorato, dalla directory di lavoro allapendrive usb:

cp mioprog.f90 /media/nome_usb_device

Per salvare il file sulla pendrive usb, assegnandogli un nuovo nome:

cp mioprog.f90 /media/nome_usb_device/newprog.f90

Per copiare tutti i file con estensione .f90 dalla directory di lavoro alla pendrive usb:

cp *.f90 /media/nome_usb_device

6. Prima di estrarre la pendrive usb smontarla dal filesystem: con il tasto destro del mouse cliccaresull'icona della pendrive che si trova sul desktop e selezionare la voce Eject.

7. Spegnere il computer utilizzando l'apposito bottone che appare sulla barra nella parte bassa delmonitor.