Strumenti Utente

Strumenti Sito


wikipaom2015:lez08

Differenze

Queste sono le differenze tra la revisione selezionata e la versione attuale della pagina.

Link a questa pagina di confronto

Entrambe le parti precedenti la revisioneRevisione precedente
Prossima revisione
Revisione precedente
wikipaom2015:lez08 [2015/03/16 16:32] ebertocchiwikipaom2015:lez08 [2015/06/25 07:51] (versione attuale) – [Vincolamento di una matrice di Rigidezza] 163359
Linea 1: Linea 1:
  
 +{{:wikipaom2015:prove_fortran.zip|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
 +       
 +       
 +~~DISCUSSION|Note di redazione~~