Fortran 1/2

Da CdM_unimore.

Lezione 10-11

Cos'è il Fortran ?

Il FORTRAN è un linguaggio di programmazione standardizzato che nasce dall'esigenza di avere un interprete che faccia da tramite tra macchina e operatore. Esso rappresenta il primo tentativo di scrivere un linguaggio standard formalizzato, che tutte le macchine possano riconoscere indipendentemente dalla diversità della CPU, ossia, indipendentemente dai diversi linguaggi macchina. Ad esempio, un processore INTEL ha un linguaggio macchina differente da un processore basato su architettura ARM. Dunque, con il linguaggio di programmazione l'utente non scrive direttamente in linguaggio macchina (che cambia da tipo a tipo di processore), ma scrive in un linguaggio tale da essere traducibile in linguaggio macchina.

In particolare, il Fortran 77 è stata la prima versione di questo linguaggio ad essere sviluppata e, nonostante la sua estrema semplicità, costituisce la base su cui sono programmati svariati solutori artificiali come , ad esempio, il software ad elementi finiti MSC Marc. Utilizzeremo la versione del Fortran 77 in quanto è la più utilizzata e leggibile anche dai fortran successivi.

Introduzione all'utilizzo del FORTRAN

Per scrivere il programma abbiamo bisogno di un editor di testo. gedit permette di scrivere file di testo non formattati. Posso scrivere come se avessi righe e colonne (ad esempio la lettera m è larga quanto la lettera i). Per salvare un file scritto con gedit come programma Fortran dobbiamo salvarlo con estensione .for. Una delle peculiarità del Fortran è quella di non essere "case sensitive", ossia, di non fare alcuna distinzione tra lettere maiuscole e minuscole. Per compilare il programma vi sono delle convenzioni da conoscere:

  • Il compilatore utilizza solo le prime 72 colonne di ogni riga, ciò significa che tutti i caratteri dalla 73° colonna in poi saranno ignorati e, pertanto, non eseguiti.
  • La prima colonna è riservata all'informazione riguardo la riga,ovvero, il carattere della prima colonna stabilisce se la riga è una riga di comando o di commento. Nel caso in cui si voglia inserire una riga di commento, bisogna inserire la lettera " C " o il carattere " * " in modo che la riga stessa venga "bypassata" dal compilatore e, quindi, non eseguita. Una versione più recente di commento non presente in Fortran 77, ma solitamente accettata dal compilatore è il "!" nella prima colonna seguito dal commento.
  • La 2°,3°,4° e 5° colonna sono spazi riservati per l'identificazione della riga di comando. Infatti, è possibile assegnare un'etichetta o "label" ad una data riga di comando con un massimo di quattro caratteri. Questo può risultare utile nella scrittura del programma nel caso in cui si voglia fare riferimento ad una data riga o rimandare il programma all'esecuzione della stessa.
ATTENZIONE: non è obbligatorio dare un'etichetta a tutte le righe del codice ma non ci possono essere due etichette aventi 
stesso nome all'interno dello stesso blocco ( program-end, subroutine-end). Inoltre, se il "nome" delle righe è numerico,
 l'identificazione delle stesse non deve essere necessariamente crescente, ossia, una riga che segue un'altra può essere   
identificata da un  numero minore di quella che la precede.
  • La 6° colonna è riservata alla simbologia di continuazione di comando. Questo serve per " portare a capo un'istruzione ", nel caso in cui una sola riga non basti per esaurire un'istruzione, causa il raggiungimento della 72° colonna del codice. E' possibile, quindi, continuare l'istruzione sulla riga successiva, indicando la stessa come continuazione della precedente, inserendo un qualsiasi simbolo FORTRAN eccetto lo spazio e lo 0 in corrispondenza della 6° colonna. Per fare questo, si potrebbe, per esempio, utilizzare il dollaro "$".
  • Dalla 7° alla 72° colonna vi è l'istruzione che il compilatore deve eseguire.

Linee guida per la compilazione corretta del programma

Visto quanto detto sopra, è buona regola di programmazione iniziare il programma con una riga che metta in evidenza lo spazio a nostra disposizione per scrivere le istruzioni e identifichi le colonne adibite a funzioni specifiche. Quindi, volendo è possibile identificare le prime 7 colonne con il proprio indice colonna, in modo da mettere in evidenza le colonne con le funzionalità precedentemente descritte, le colonne dalla 8° alla 71° con un simbolo generico, come ad esempio "=", per identificare lo spazio a disposizione e la 72° con il carattere "!", in modo da avere uno "warning" della fine dello spazio disponibile. Per poter compilare adeguatamente il programma, è bene concepirlo inizialmente come un insieme funzionale di blocchi, nel modo seguente:

  1. Nome del programma. Si indica il nome mediante il comando PROGRAM "nome del programma"
  2. Dichiariamo le variabili. Il FORTRAN utilizza un' allocazione di memoria statica, ossia, dichiarando le variabili indichiamo esplicitamente la totalità della memoria necessaria per l'esecuzione di tutto il programma. Questo è importante perché, in fase di esecuzione ("Run Time"), il programma non potrà richiedere alcuna memoria aggiuntiva. Se avessimo la possibilità di richiedere di utilizzare più memoria durante il programma si parlerebbe di allocazione dinamica. Le variabili possono essere, essenzialmente, dei seguenti 6 tipi:
    • INTEGER - La variabile indica un numero intero.
    • REAL - La variabile indica un numero reale, in virgola mobile con o senza segno, in singola precisione (7 cifre significative).
    • DOUBLE PRECISION - La variabile indica un numero REAL, sempre con la virgola, ma con doppia precisione (circa 15 cifre significative).
    • COMPLEX - Indica un numero complesso, quindi, si devono indicare parte reale e parte immaginaria.
    • LOGICAL - Memorizza solo due valori: ".true." e ".false.".
    • CHARACTER - Memorizza una stringa completa di tipo "caratteri".
  3. Corpo del programma . E' un listato di comandi che il compilatore esegue, effettuando operazioni tra le variabili indicate nella dichiarazione. ATTENZIONE: il listato deve terminare con un comando del tipo STOP.
  4. END. E' il comando che termina l'esecuzione del programma.

Per far girare correttamente il file editor appena creato, esso dovrà essere salvato tramite il comando SAVE AS inserendo il nomefile.for. In questo modo, il file potrà essere letto ed eseguito correttamente dal terminale della macchina sulla quale si sta lavorando.

Nel caso in cui il terminale dovesse dare un errore di file inesistente è necessario assicurarsi di aver salvato il file in cygwin -> home -> nome utente

Una volta salvato il file, si deve aprire il terminale ed inserire il seguente comando.

  • Nel caso in cui si lavori in ambiente LINUX:
gfortran nomefile.for &&./a.out
  • Nel caso in cui si lavori in ambiente WINDOWS:
gfortran nomefile.for &&./a.exe

dove a.out (o a.exe) sono gli eseguibili creati con la compilazione e sono sostanzialmente la traduzione del codice Fortran in linguaggio macchina, per l’architettura specifica. Do sia il comando di compilazione che di esecuzione accodati tramite il doppio &&, se la compilazione va a buon fine eseguo altrimenti no. Il costrutto "./a.out" si può "tradurre" con: "lancia il file a.out in questa cartella", dove il punto prima della barra (./) indica "questa cartella", la barra indica "dentro".

osservazione: cosa vuol dire single o double precision? Allora, secondo lo standard IEEE 754 la struttura di un numero (in virgola mobile) è rappresentato su "parole" di 32bit (single precision) o 64 bit (double precision). Tali bit possono essere suddivisi in 3 parti:

  • per i single precision (32 bit)
  1. ) un bit di segno
  2. ) 8 bit per l'esponente
  3. ) 23 bit per la mantissa (dove posso scrivere 2^23 numeri)
1    8              23                -> lunghezza in bit
+-+--------+----------------------+
31 30      22                     0    -> indice dei bit
  • per i double precision (64 bit)
  1. ) un bit di segno
  2. ) 11 bit per l'esponente
  3. ) 52 bit per la mantissa (dove posso scrivere 2^52 numeri)
1    8              52                 -> lunghezza in bit
+-+--------+----------------------+
63 62      51                     0    -> indice dei bit

ESEMPI DI PROGRAMMI

Hello World

Un primo approccio alla programmazione è stato la compilazione del programma Hello World.

- Hello World -
c234567===============================================================!      
      program HeLLow
      write(*,*) 'HelloWorld!!!'
      end

Questo programma, una volta eseguito, stampa il testo "HelloWorld!!!". Questa è la prima occasione in cui vediamo il comando WRITE(*,*). Tale comando valuta una lista di istruzioni e le esegue con formato standard (indicato da "*"). Il primo posto all'interno del WRITE serve per indicare l'UNITA' mentre il secondo indica il FORMATO. Con l'* si intende l'unità o il formato standard. Quindi letteralmente WRITE(*,*) significa "scrivi quello che segue in output sull'unità standard (video) con formato standard". Un'altra soluzione, potrebbe essere l'utilizzo del comando PRINT*,. L'* accanto al PRINT indica l'unità, utilizzando questo comando non è possibile definire il formato. Possiamo accodare dei file in output separandoli con una virgola. In questo modo, senza richiamare più volte il comando su righe successive, è possibile scrivere più stringhe, una in sequenza all'altra nel modo seguente:

write(*,*)‘stringa_1’ , ‘stringa_2’

Nel caso in cui il comando fosse troppo lungo, poichè oltrepassante la 72° colonna, lo si può spezzare andando a capo e scrivendo, in corrispondenza della sesta colonna della riga siccessiva, un qualsivoglia carattere come un "$" o un "+", ma non uno spazio:

c234567==============================================================!
      write(*,*) 'HelloWorlddddddddddddddddddddddddddddddddddddddddddd
     $dddddddddddddddddd!'

Area Corona Circolare

Ricordiamo, che l'area della corona circolare di raggio generico esterno ed interno: re , ri, si calcola come:

Circle.png


Una volta scritto il codice, salviamo il file con il nome circle.for.

ATTENZIONE: SALVARE SEMPRE IL FILE.FOR, altrimenti il terminale non leggerà nulla.

Come si può notare, la dichiarazione delle variabili è stata fatta in un'unica riga, ma può esser fatta anche in più righe successive.

Avendo dichiarato variabili di calcolo "double precision", abbiamo richiesto la "doppia precisione". Se calcoliamo in singola precisione una variabile che è stata definita in doppia, allora otteniamo un risultato sbagliato perché vengono inseriti numeri a caso nei punti che la doppia precisione ha in più rispetto alla singola. Inoltre, nella formula è presente il numero π. FORTRAN non ha una libreria che richiami delle costanti note, quindi, per poter utilizzare il π, bisogna dichiararlo come costante nel blocco delle variabili, tramite l'istruzione PARAMETER(.....),o numericamente:

parameter( pi=3.141592 )

altrimenti, attraverso l'arcoseno:

pi=asin(1.0d0)*2.0d0
parameter(pi=asin(1.0d0)*2.0d0)

Dove, con 1.0 consideriamo l'1 un numero reale, viceversa il solo 1 sarebbe stato l'1 intero e con la dicitura d0 specifichiamo numeri in doppia precisione. Se, invece, si vuole considerare il numero in singola precisione bisogna scrivere e0. Un prodotto misto ad esempio:

asin(1.0d0)*2.0

da' come risultato un numero in doppia precisione, inoltre, se effettuo un calcolo in singola precisione, ma la variabile assegnata è in doppia, i decimali mancanti vengono sostituiti da numeri casuali.

Per un approfondimento sul calcolo numerico si veda il link seguente:

http://it.wikipedia.org/wiki/IEEE_754


ATTENZIONE: le DICHIARAZIONI vanno nettamente separate dall’INIZIO DEL PROGRAMMA, non si possono mischiare, nel senso che non è possibile dare un comando e poi dichiarare una variabile!!


Se nel programma circle fosse stato commesso un errore di battitura, ad esempio:

areaa = (re**2-ri**2)*3.14159

il compilatore non avrebbe dato errore, ma avrebbe restituito un valore "strano" ( un'area negativa ). La variabile areaa è stata ritenuta valida, altrimenti, non l’avrebbe restituita. Infatti, in Fortran esiste il concetto di DICHIARAZIONE IMPLICITA, ovvero, se la variabile inizia con una lettera compresa fra i ed n (i, j, k, l, m, n) essa viene intesa come un numero INTERO. Se, invece, inizia con una qualsiasi altra lettera viene vista dal compilatore come un numero REALE. E' buon uso dichiarare sempre le variabili!!!

Dunque, viene allocato in memoria spazio per 4 variabili, anche se la variabile areaa non è stata dichiarata. Il compilatore stampa a video un numero non prevedibile a priori, che corrisponde sostanzialmente alla traduzione in numeri reali in singola precisione di quel che c'era nell'indirizzo di memoria assegnato ad areaa in precedenza. Bisogna fare attenzione, poiché il programma potrebbe restituire un valore che per noi può essere corretto ma, in realtà, non lo è affatto.

ATTENZIONE: Per evitare questi errori, che possono capitare ad esempio per un semplice errore di battitura, è consigliabile compilare con alcune specifiche righe di compilazione:

gfortran -g -fbounds-check -fbacktrace -finit-real=nan -finit-integer=-123456 nome_file.for  && ./a.out

Questa stringa, in parole povere, "dice al compilatore in fase di allocazione di non lasciare l'indirizzo di memoria così com'è ma di riempirla di numeri o comunque di valori riconoscibili". Quindi, si compila il codice e si va ad allocare la memoria. Il costrutto:

gfortran-finit-real=nan

permette di riempire la memoria reale con nan (not a number), cioè si inizializza un reale a not a number, mentre non esiste un equivalente per le variabili intere per cui si inserisce il costrutto:

-finit-integer=-123456

e si va ad inizializzare un intero con un numero negativo elevato. Inoltre possiamo dire che il not a number sia "virale", nel senso che qualsiasi operazione che coinvolge not a number da come risultato un NaN, rendendolo visibile, posso così evitare di scrivere aree di memoria senza accorgermene.

L'istruzione:

-fbounds-check

serve invece per limitare i confini. Se, per esempio, si vuole eseguire un ciclo do per scrivere una matrice A di 100 elementi, mentre A è stata limitata a 15 elementi, inserendo il -fbounds-check il programma rileva l'incompatibilità e lo comunica.

Un altro metodo per disattivare la funzionalità del Fortran di assegnare automaticamente tipi alle variabili in base ai loro nomi, consiste nello scrivere all'inizio del blocco delle dichiarazioni la seguente riga di comando:

implicit none

passando questa direttiva, non viene dichiarata implicitamente nessuna variabile. In questo modo se abbiamo una variabile che non è stata dichiarata (ad esempio come conseguenza di un errore di battitura) il programma mi dà errore. Questa istruzione rimane valida solo nel blocco di codice tra program ed end. Quindi, va richiamata in ogni eventuale subroutine.

Equazione di secondo grado

Di seguito, si crea un programma in grado di risolvere un'equazione di secondo grado, ci si avvale del costrutto IF-THEN-ELSEIF-ELSE, utile ad individuare il tipo di soluzione:

Equazione secondo grado.png

c234567================================================================!
      program eqsecgrad
      double precision a,b,c,delta, x1, x2
      parameter(eps=1.0d-12)
      write(*,*) 'Immettere i coefficienti a,b,c dellequazione:'
      write(*,*) ' a*x**2 + b*x + c=0'
      read(*,*) a,b,c
      delta= b**2-4*a*c
c== costrutto IF - THEN - ELSEIF - ELSE
      if (delta .GT. eps) then 
      x1= (-b+sqrt(delta))/2.0d0/a
      x2= (-b-sqrt(delta))/2.0d0/a
      write(*,*) 'radici reali distinte', x1,x2    
      elseif (delta.LT. -eps) then
      x1= -b/2.0d0/a
      x2= sqrt(-delta)/2.0d0/a
      write(*,*) 'radici complesse coniugate' , x1, '[+/-]', x2, 'i'
      else 
      x1=-b/2.0d0/a
      write(*,*) 'radice reale doppia', x1 
      endif
      stop
      end

Qui, è possibile vedere come implementare ed utilizzare il costrutto IF, THEN, ELSEIF, ELSE. Una volta fissata la condizione con il primo if, essa deve essere posta tra parentesi tonde a seguito dell'if e deve essere seguita da then. Dopo il then si scriveranno le azioni da eseguire nel caso sia soddisfatta la condizione, oppure in caso contrario, si procede con il comando else. Il comando Elseif può essere utilizzato quando si devono mettere più di due condizioni, come nel caso del programma precedente dove dobbiamo riconsiderare il metodo di soluzione tre volte. Il costrutto if, then, elseif, else deve poi essere completato digitando il comando endif o end if, la scelta dell'uno o dell'altro è del tutto indifferente in quanto fortran non considera gli spazi.

Da notare che il nome delle variabili non dovrebbe essere lungo più di 6 caratteri, anche se alcuni compilatori potrebbero accettare anche più di 6 caratteri. Per questo abbiamo utilizzato la variabile delta invece di discriminante.

Da questo programma si evince anche il problema dello 0 nel calcolo numerico. Ad esempio se compio l'operazione (4-1)-3 il calcolatore non mi restituisce lo 0 preciso, ma un valore vicinissimo a 0. Per questo non è possibile discriminare con il valore 0 ma si deve prendere in considerazione un valore finito, diverso da 0, che però può essere numericamente associato ad esso, va cioè inserita una tolleranza eps. Nell'esempio abbiamo:

parameter(eps=1.0d-12)

cioè un ordine di tolleranza pari a e^-12 con precisione in doppia cifra.

Si introduce, di seguito, una tabella di rapido accesso con gli operatori matematici standard e le relative rappresentazioni in Fortran:

Maggiore          ----> .GT.                                   Negazione         ----> .NOT.          

Minore            ----> .LT.                                   E logico          ----> .AND.

Uguale            ----> .EQ.                                   O logico          ----> .OR. (NON esclusivo, ovvero o uno o 
                                                                                              l'altro o anche tutti e due)
Maggiore uguale   ----> .GE.                                   O logico          ----> .OUT. (esclusivo)

Minore uguale     ----> .LE.

Diverso           ----> .NE.

Prodotto matrice-vettore e ciclo do

In questa prova, si fa uso di una struttura chiamata "array" (dall'inglese: ordine, disposizione, schieramento). Gli "array" sono fissi in dimensione, devono essere omogenei, quindi gli elementi al loro interno devono essere tutti interi o reali e tutti in singola o doppia precisione. Matrici e vettori, in sostanza, sono degli array.

Di seguito, è riportato il programma che calcola il prodotto fra una matrice e un vettore, basato sull'utilizzo del ciclo do. Va ricordato, che il nome del programma può coincidere o meno con il nome del file senza che questo influisca sull'esecuzione dell'elaborato, inoltre, nella fase iniziale, va prima dichiarata la natura delle variabili e, successivamente, le rispettive dimensioni.


L'i-esimo elemento del vettore c è formato dal prodotto della i-esima riga della matrice A per il vettore b:

c234567================================================================!
       program provavettori
c===  calcolo del prodotto tra una matrice e un vettore
       implicit none 

c===  definisco variabili intere
      
       integer irow,icol, nrow, ncol
c===  tra le variabili intere, nrow e ncol sono inizializzate 
c===  e bloccate ai valori di inizializzazione (named constants) per
c===  dare al programma, informazioni complete su quanta memoria allocare
      
       parameter(nrow=5,ncol=3)

c===  formato alternativo 1
      
       double precision a,b
       dimension a(nrow,ncol),b(ncol),c(nrow)

c===  formato alternativo 2
      
       double precision c(nrow)

c===  fine dichiarazioni
c===  inizio istruzioni
     
c===  input matrice a      
      
       do irow=1,nrow
         read(*,*) ( a(irow,icol) , icol=1,ncol )
       enddo

c===  output di controllo matrice a
      
       do irow=1,nrow
         write(*,*) ( a(irow,icol) , icol=1,ncol )
       enddo

c=== l'utilizzo di un unico do ci permette di scrivere (e di vedere
c=== stampata la matrice) in forma di matrice vera e propria,
c=== l'utilizzo di un doppio do (uno per l'indice di riga ed uno
c=== per l'indice di colonna) avrebbe salvato e stampato la matrice
c=== su un'unica colonna
c=== input vettore b
      
      read(*,*) ( b(icol) , icol=1,ncol )

c=== output di controllo vettore b
     
      write(*,*) ( b(icol) , icol=1,ncol )

c=== calcolo prodotto matrice per vettore
      do irow=1,nrow
        c(irow)=0.0d0
        do icol=1,ncol
          c(irow) = c(irow) + a(irow,icol) * b(icol)
        enddo
       enddo

c=== output vettore c
       do irow=1,nrow
         write(*,*) c(irow)
       enddo

       stop
       end

Carico una versione del programma funzionante e più dettagliata, con una parte di visualizzazione a video migliore; i comandi sono gli stessi usati nel programma precedente.

c234567================================================================!

     program prodmatrix
     implicit none
     integer K1,K2,i,j
     parameter (K1=2,K2=3)
     double precision A,B,C
     dimension A(K1,K2),B(K2),C(K1)
     print*, 'matrice A '
     do i=1,K1
     print*, 'inserisci gli elementi della riga ',i
     read*, (A(i,j),j=1,K2)
     enddo
     print*, 'matrice B '
     do j=1,K2
     print*, 'inserisci gli elementi della riga ',j
     read*, B(j)
     enddo
     do i=1,K1
     C(i)=0.0d0
      do j=1,K2
      C(i)=C(i)+A(i,j)*B(j)
      enddo
     enddo     
     write(*,*), 'la matrice A è '
     do i=1,K1
     write(*,*) (A(i,j), j=1,K2)
     enddo
     write(*,*), 'la matrice B è '
     do j=1,K2
     write(*,*), B(j)
     enddo      
     write(*,*) 'la matrice C è '
     write(*,*) (C(i),i=1,K1)
    
     stop
     end

riga di comando per compilazione ed esecuzione:

gfortran provavettori.for  &&  ./a.out  < input.txt  > output.txt

con la stringa > output.txt i risultati vengono sovrascritti sul file output.txt, mentre se avessi inserito >> output.txt' i dati sarebbero stati accodati all'interno del file.

Il file input.txt è così definito:

1 2 3
4 5 6
7 8 9
10 11 12
13 14 15
1.0d0 1.0d-3 1.0d-6

Per non inserire ogni volta che eseguiamo tutti i dati abbiamo creato un file di testo dove sono stati inseriti una sola volta.

File di output corretto:

   1.0000000000000000        2.0000000000000000        3.0000000000000000     
   4.0000000000000000        5.0000000000000000        6.0000000000000000     
   7.0000000000000000        8.0000000000000000        9.0000000000000000     
   10.000000000000000        11.000000000000000        12.000000000000000     
   13.000000000000000        14.000000000000000        15.000000000000000     
   1.0000000000000000       1.00000000000000002E-003  9.99999999999999955E-007
   1.0020030000000000     
   4.0050059999999998     
   7.0080090000000004     
   10.011011999999999     
   13.014014999999999


ATTENZIONE: per attribuire i valori di nrow e ncol, si deve utilizzare il comando:

parameter(nrow=5,ncol=3) 

e NON:

Nrow=5 , Ncol=4

perché sarebbero delle istruzioni e non vanno mischiate con il blocco delle dichiarazioni.


Per l'output di controllo delle matrici, è stato utilizzato il costrutto del write con ciclo interno (o implicito) che permette di stampare gli elementi di una riga della matrice uno a fianco all'altro e non incolonnati, per una più semplice lettura della stessa. Nel caso della matrice a:

do irow=1,nrow
  write(*,*) ( a(irow,icol) , icol=1, ncol )
enddo

Il parametro da stampare a video (in questo caso a), è funzione di irow che scorre esternamente e di icol che scorre internamente. Questo oggetto viene stampato per icol da 1 a ncol senza andar a capo; in pratica viene inserito il ciclo all'interno del write stesso. In alternativa si possono utilizzare i due do in sequenza e gli elementi vengono stampati su un'unica colonna:

do irow=1,nrow
  do icol=1,ncol 
    write(*,*) (a(irow,icol)
  enddo
enddo

La medesima scrittura funziona con il comando read ovviamente.

Lo stesso ciclo do consta, inoltre, di un'altra forma meno utilizzata ma altrettanto valida del tipo:

  do 10, irow=1,nrow
    do 20, icol=1,ncol 
      write(*,*) (a(irow,icol)
10 continue
20 continue

Invece di scrivere tutti gli elementi della matrice e del vettore, si può creare un file del tipo ".txt" e farlo leggere come file di input, cioè si usa il file input.txt come eseguibile nel file a.out

gfortran prodmatvet&&./a.out <input.txt>

Così come per il file di input, si può creare un file di output, in modo che il programma anzichè scrivere l'output (in questo caso il risultato del prodotto matrice-vettore) sulla schermata del terminale, lo scrive in un file esterno output.txt:

gfortran prodmatvet&&./a.out <input.txt> output.txt

In questo modo, ogni volta che si scrive il file di output si sovrascrivono i risultati, se si preferiscono accodare si usa la doppia freccia ">>", come segue:

 gfortran prodmatvet&&./a.out <input.txt>> output.txt

Note Fortran

Tutorial per linguaggio Fortran

Tutorial corso Introduction to Fortran taught at Stanford University

http://www.stanford.edu/class/me200c/tutorial_77/

Ne ho caricata una copia in singolo file (html, pdf) più comoda per la stampa.

User notes on Fortran Programming, ibiblio.org

Entra in dettaglio su alcuni argomenti, buon complemento per l'approfondimento.

http://www.ibiblio.org/pub/languages/fortran/unfp.html

Professional Programmer's guide to Fortran 77

Guida piuttosto dettagliata, sempre a scopo di approfondimento. Formati html e pdf

Passaggio al Fortran 90 (non trattato nel corso)

Fortran 90 for Fortran 77 programmers

Compilazione su macchine unix con gfortran

Riga di comando con opzioni consigliate di compilazione con gfortran

gfortran -g -fbounds-check -fbacktrace -finit-real=nan -finit-integer=-123456 nomefile.for  && ./a.out

Note fortran: costrutti obsoleti

ARITHMETIC IF

While we are on the subject of IF's, you should be aware of one archaic form called the arithmetic IF. I introduce this only because some of you will be asked to improve an existing program. You should not use this in any new programming. There is a good chance that it will be dropped from some future Fortran standard. The arithmetic IF can be recognized by the fact that the expression within the parentheses results in a numerical result, not a logical (true, false) result. The other give-away is the string of three integers (statement label references) after the right parenthesis.

c234567
      if ( b**2-4*a*c) 100,200,300
  100    print *, 'Roots are Complex'
      go to 400
  200    print *, 'Single Real Root' 
      go to 400
  300    print *, 'Two Real Roots'
  400 continue

If the arithmetic expression produces a value less than zero, execution branches to the first label in the list. If it is zero, control branches to the second label, and if the value is greater than zero the program branches to the third label. Repetition of label numbers is permitted in the IF's label list. Note that I must include extra "GO TO" statements to prevent execution of some of the PRINT statements after the initial branch to another PRINT. """

[da http://www.personal.psu.edu/jhm/f90/fortran.html ]

Installazione di compilatore fortran 77 su pc windows

Installazione ambiente Unix Cygwin, con compilatore gfortran (Metodo consigliato)

Andare al sito Cygwin/X. Scaricare i file di avvio installazione 32 bit o 64 bit, a seconda della versione di windows installata.

Avviare l'installer, scegliere "Install from Internet", utilizzare le cartelle proposte di default. Scegliere un Download site non troppo distante, tipo http://mirror.switch.ch.

L'installer propone quindi una selezione di pacchetti base e opzionali. Cercare quindi fortran e selezionare il pacchetto gcc-fortran per l'installazione.

Selezione pacchetto gcc-fortran

Selezionare per l'installazione anche i pacchetti opzionali

  • lapack e liblapack-devel, utili librerie per il calcolo numerico;
  • openssh, shell di accesso remoto ssh, RICHIESTO PER PONTE LICENSE MSC.MARC

Non vedo nella selezione pacchetti cygwin un editor grafico normale quindi procederemo a parte con l'installazione di notepad++.

Procedere con Next fino all'effettivo scaricamento dei pacchetti e all'installazione.

Una volta terminata l'installazione, sarà disponibile dal menu programmi il Cygwin Terminal, terminale testuale similare a quello disponibile sulle macchine dei laboratori didattici.

Cygwin Terminal

Procedere quindi all'installazione di un editor di testo. Io mi trovo bene con Notepad++, che potete scaricare dal sito, sezione Downloads. Qualunque altro editor di testo (escluso forse notepad.exe, non gestisce correttamente gli a capo unix) dovrebbe andare comunque bene.

NB: se usate notepad++ per editare codice fortran 77 **disattivate** l'opzione di indentazione automatica dal menu

Configurazione -> Preferenze -> Varie -> Indentazione automatica

L'indentazione automatica inserisce tabulazioni e non gli spazi richiesti dal fortran 77.

Editor alternativi che si possono consigliare sono AkelPad Editor e SciTe; in quest'ultimo conviene utilizzare il carattere *monospaced* dal menu

Options -> Use Monospaced Fonts

Per testare l'installazione, copiaincollate il seguente codice

c234567
      program hello
         print *, "Hello World!"
      end program hello

e salvarlo con nome hellow.for entro la cartella di lavoro di cygwin.

Tale cartella è nel caso della mia installazione windows xp è C:\cygwin\home\NOMEUTENTE, ove NOMEUTENTE è il l'utente windows che state utilizzando; ho notato che su installazioni windows 7 coincide con la normale cartella home dell'utente, quindi C:\Users\NOMEUTENTE.

Per verificare il percorso corretto aprire il terminale cygwin e battere il comando dove mi trovo

pwd

Salvare entro il percorso restituito in output da tale comando, sostituendo nel caso la stringa "/cygdrive/c" con "C:"; ad esempio se pwd restituisce "/cygdrive/c/Users/EDOARDO" la cartella di lavoro di default è "C:\Users\EDOARDO", ossia la normale cartella home dell'utente EDOARDO sotto windows.. In ogni caso è possibile spostarsi di cartella in cartella con il comando "cd".

Cygwin Terminal

Passate quindi al terminale cygwin, e battete

gfortran hellow.for && ./a.exe

che avvia la compilazione del programma hellow.for, e, nel caso tale operazione termini con esito positivo (concatenazione con &&), lancia il programma appena compilato (a.exe nei sistemi win, a.out nei sistemi unix).

Cygwin Terminal

Ogni ulteriore modifica del codice dall'editor di testo deve essere salvata (si aggiorna la versione del file presente su disco) prima di lanciare una nuova compilazione.

Fortran IDE per windows/linux

Code Blocks

www.codeblocks.org http://sourceforge.net/projects/codeblocks/files -> binaries -> sistema operativo [Windows] -> ultima versione [12.11] -> scaricare installer contenente il compilatore MINGW (gcc suite per windows)

Force IDE

http://force.lepsch.com/p/download.html


Rivisto da 190818