Indice
file fortran postazione cattedra
Costruzione di una Matrice/Vettore
In questa prova, si fa uso di una struttura chiamata Array (dall'inglese: ordine, disposizione, schieramento). Gli “array” servono a dichiarare matrici e vettori. Possono essere, ad esempio, del tipo:
real a(20)
dove si dichiara un vettore ad elementi reali di 20 elementi allocati nella memoria a 32 bit uno dietro l'altro. Essi 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.
Di seguito, è riportato il programma che costruisce una matrice o 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.
Inizializzo le colonne utilizzabili su Fortran77 (72 colonne) in questa maniera:
c234567================================================================|
Definisco il nome del programma
program tmat
Inserisco un implicit none in modo da dover esplicitare completamente tutte le variabili evitando di cadere in errori di programmazione
implicit none
Definisco due costanti nrow, ncol e dichiaro (alloco) matrice A
integer nrow,ncol parameter( nrow = 3 , ncol = 5 ) real A(nrow,ncol)
Definisco due indici
integer irow,icol
Fine Dichiarazioni ed Inizio Istruzioni
INPUT matrice A da standard input (stdin)
do irow = 1,nrow write(*,*) 'inserire riga',irow,'di',nrow
Adesso dobbiamo scegliere tra due alternative di utilizzo del ciclo do
do interno al read
read(*,*) ( A(irow,icol), icol=1,ncol )
do esterno al read
do icol = 1 , ncol write(*,*) 'col',icol read(*,*) A(irow,icol) enddo enddo
OUTPUT matrice A su stdout
do irow = 1,nrow write(*,*) 'riga',irow,'di',nrow
Adesso in base alla scelta fatta in input bisogna in maniera coerente scegliere il tipo di ciclo do in output
do interno al write
write(*,*) ( A(irow,icol), icol=1,ncol )
do esterno al write
do icol = 1 , ncol write(*,*) 'col',icol,A(irow,icol) enddo enddo
stop end
NOTA BENE: questo programma consente la costruzione della matrice immettendo gli elementi da tastiera uno alla volta (Metodo scomodo)
Prodotto Matrice/Vettore
Di seguito, è riportato un metodo di costruzione della matrice, che assegna gli elementi leggendo in automatico un file .txt in cui sono già stati elencati i valori degli elementi desiderati. Tale programma inoltre serve a eseguire il prodotto tra matrici/vettori (A*B=C) utilizzando il ciclo do.
$$\begin{vmatrix}a_{1,1} & a_{1,2} & a_{1,3} & a_{1,4} & a_{1,5}\\a_{2,1} & a_{2,2} & a_{2,3} & a_{2,4} & a_{2,5}\\a_{3,1} & a_{3,2} & a_{3,3} & a_{3,4} & a_{3,5}\end{vmatrix} * \begin{vmatrix}b_{1,1} & b_{1,2}\\b_{2,1} & b_{2,2}\\b_{3,1} & b_{3,2}\\b_{4,1} & b_{4,2}\\b_{5,1} & b_{5,2}\end{vmatrix} = \begin{vmatrix}c_{1,1} & c_{1,2}\\c_{2,1} & c_{2,2}\\c_{3,1} & c_{3,2}\end{vmatrix}$$
L'algoritmo che descrive l'operazione che esegue il programma è il seguente:
$$ C_{irow,icol}= \sum_{isum=1}^n A_{irow,isum}*B_{isum,icol} $$
Definisco il nome del programma
program tmat_v1 implicit none
Definisco due costanti nrow, ncol e dichiaro (alloco) le matrici A B C
integer nArow,nAcol integer nBrow,nBcol integer nCrow,nCcol
parameter( nArow = 3 , nAcol = 5 ) parameter( nBrow = 5 , nBcol = 2 ) parameter( nCrow = 3 , nCcol = 2 )
real A(nArow,nAcol) real B(nBrow,nBcol) real C(nCrow,nCcol)
Definisco due indici per scorrere le matrici, più uno di sommatoria
integer irow,icol,isum,nsum
Fine Dichiarazioni ed Inizio Istruzioni
INPUT matrice A da standard input (stdin)
do irow = 1,nArow read(*,*) ( A(irow,icol), icol=1,nAcol ) enddo
INPUT matrice B da standard input (stdin)
do irow = 1,nBrow read(*,*) ( B(irow,icol), icol=1,nBcol ) enddo
Inizio CALCOLO DEL PRODOTTO
call prodmat(nArow,nAcol,nBcol,A,B,C)
Fine CALCOLO DEL PRODOTTO
OUTPUT matrice C su stdout
do irow = 1,nCrow write(*,*) ( C(irow,icol), icol=1,nCcol ) enddo
stop end
Adesso creo un sottoprogramma 'subroutine', che viene poi richiamato tramite il comando 'call'
subroutine prodmat(nAArow,nAAcol,nBBcol,AA,BB,CC) implicit none
INPUT Dimensionamento matrici per prodotto
integer nAArow, nAAcol, nBBcol
Datrici per prodotto
real AA( nAArow, nAAcol ) real BB( nAAcol, nBBcol )
OUTPUT Matrice su cui scrivere il risultato del prodotto
real CC( nAArow, nBBcol )
IN/OUT , UPDATE, MODIFICA area dedicata a variabili a cui si accede in INPUT/OUTPUT
VARIABILI LOCALI Dichiaro gli indici di scorrimento riga/colonna su CC e di somma
integer irow, icol, isum
Fine Dichiarazioni ed Inizio Istruzioni
do irow = 1,nAArow do icol = 1, nBBcol CC(irow,icol)= 0.0 do isum = 1, nAAcol CC(irow,icol)=CC(irow,icol) + AA(irow,isum)*BB(isum,icol) enddo enddo enddo
return end
Riga di comando per compilazione ed esecuzione:
gfortran tmat_v1.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.
0.1 0.2
0.3 0.4
0.5 0.6
0.7 0.8
0.9 1.0
Cos'è un Sottoprogramma (Subroutine)?
Il linguaggio di programmazione FORTRAN consente di suddividere le operazioni tramite sottoprogrammi che ritornano un risultato al programma chiamante, sviluppando un approccio top-down. L'utilizzo dei sottoprogrammi è molto utile quando si deve ripetere una stessa operazione più volte, evitando così tutte le volte di copiare e incollare nel programma principale la stessa operazione. Questi sottoprogrammi possono essere del tipo FUNZIONI oppure SUBROUTINE. Funzioni e subroutine devono avere nome univoco e per il resto sono indipendenti dal programma che le ha richiamate. Il costrutto FUNZIONE restituisce un singolo valore scalare, motivo per cui spesso si ricorre al costrutto SUBROUTINE. A differenza dei programmi che terminano con “ stop end”, i sottoprogrammi terminano con “return end”. Nel sottoprogramma le etichette sono autonome perciò per dichiarare le variabili locali, si possono utilizzare etichette aventi stesso nome e tipologia di quelle già dichiarate nel programma principale (MAIN). Programma e sottoprogramma comunicano inviandosi indirizzi di memoria perciò è fondamentale che comunichino con la stessa tipologia di elementi: in particolare il programma invia i parametri passati al sottoprogramma che restituisce un valore.
Creiamo adesso un sottoprogramma che determina il:
Vincolamento di una matrice di Rigidezza
Si vuole vincolare la matrice di rigidezza della struttura STRUTK ai termini noti o forze applicate sulla struttura (FORCE) e agli spostamenti che in realtà sono incogniti. Così si opera direttamente con una subroutine:
subroutine vincola(N,STRUTK,FORCE,I,V) implicit none
INPUT
integer N integer I real V
INOUT
real STRUTK(N,N) real FORCE(N)
LOCALI
integer J
Fine Dichiarazioni ed Inizio Istruzioni
Affinché la matrice possa essere simmetrica e definita positiva,azzero la riga I-esima della matrice STRUTK
do J = 1,N STRUTK( I , J ) = 0.0 enddo
ma si sa anche che l'elemento della i-esima riga e i-esima colonna non vale zero. Scrivo 1.0 sul termine diagonale di tale riga
STRUTK(I,I) = 1.0
Definisco il valore imposto V a termine noto, elemento I-esimo
FORCE(I) = V
Ora bisogna recuperare la simmetria della matrice annullando i termini della i-esima colonna, perciò creo due blocchi di matrice che vanno da 1 a I-1 e da I+1 ad N
do J = 1 , I-1 FORCE(J) = FORCE(J) - STRUTK(J,I) * V STRUTK(J,I) = 0.0 enddo
Salto caso J=I, legato alla diagonale che già era stato impostato in precedenza e si ottiene:
do J = I+1 , N FORCE(J) = FORCE(J) - STRUTK(J,I) * V STRUTK(J,I) = 0.0 enddo
Basta chiudere la subroutine e il main e si ottiene il codice di vincolamento.
return end
Note di redazione
nell'inserimento di codice fortran 77 è possibile utilizzare o prependere 2 spazi in più, utilizzati da dokuwiki per riconoscere il codice
oppure utilizzare il costrutto <code> ... </nocode> , senza modifica della spaziatura
Il risultato è il medesimo, forse il secondo metodo è più comodo da scrivere.