wikipaom2016:lab5
Differenze
Queste sono le differenze tra la revisione selezionata e la versione attuale della pagina.
Entrambe le parti precedenti la revisioneRevisione precedenteProssima revisione | Revisione precedente | ||
wikipaom2016:lab5 [2016/04/19 15:15] – 182648 | wikipaom2016:lab5 [2016/06/17 15:29] (versione attuale) – [Subroutine Prodmat] ebertocchi | ||
---|---|---|---|
Linea 1: | Linea 1: | ||
+ | ======Programma agli elementi finiti triangolari====== | ||
+ | =====Dimensionamento===== | ||
+ | |||
+ | La prima parte del programma si occupa della __dichiarazione__ delle variabili necessarie per definire la struttura; | ||
+ | |||
+ | PARAMETER (NODES=9) | ||
+ | PARAMETER (NELEMS=8) | ||
+ | PARAMETER (IFMAX=3, | ||
+ | DIMENSION XY(2, | ||
+ | ICNXY(2, | ||
+ | FORCE(2*NODES), | ||
+ | |||
+ | **NODES**: numero di nodi\\ | ||
+ | **NELEMS**: numero degli elementi\\ | ||
+ | **IFMAX**: numero di nodi caricati\\ | ||
+ | **ICNMAX**: numero di nodi vincolati\\ | ||
+ | |||
+ | La stringa " | ||
+ | |||
+ | **XY**: matrice formata da due righe e NODES colonne, contiene nella prima riga l' | ||
+ | |||
+ | {{ : | ||
+ | |||
+ | **NVERT**: matrice formata da tre righe e NELEMS colonne, contiene in ogni colonna il numero (label o etichetta) di ogni nodo che compone l' | ||
+ | |||
+ | {{ : | ||
+ | |||
+ | Con i dati indicati in precedenza è possibile disegnare sul piano la struttura per capire meglio di cosa stiamo parlando. | ||
+ | |||
+ | {{ : | ||
+ | |||
+ | **IFXY**: vettore formato da IFMAX componenti, contiene i nomi (label) dei nodi caricati\\ | ||
+ | **FXY**: matrice formata da due righe e IFMAX colonne, contiene nella prima riga le componenti lungo x delle forze applicate al nodo e nella seconda le componenti lungo y\\ | ||
+ | |||
+ | L' | ||
+ | |||
+ | {{ : | ||
+ | |||
+ | **ICNXY**: matrice formata da due righe e ICNMAX colonne, contiene nella prima riga i nomi (label) dei nodi vincolati e nella seconda il tipo di vincolamento secondo il seguente schema:\\ | ||
+ | * spostamento in direzione x associato al numero 1 | ||
+ | * spostamento in direzione y associato al numero 2 | ||
+ | * spostamento in direzione x e y associato al numero 3 | ||
+ | |||
+ | {{ : | ||
+ | |||
+ | {{ : | ||
+ | |||
+ | **CNXY**: matrice formata da due righe e ICNMAX colonne, contiene nella prima riga il valore dello spostamento imposto lungo x e nella seconda lungo y\\ | ||
+ | |||
+ | {{ : | ||
+ | |||
+ | Notare che la scrittura " | ||
+ | |||
+ | {{ : | ||
+ | |||
+ | **STRUTK**: matrice di rigidezza dell' | ||
+ | |||
+ | **FORCE**: vettore delle forze imposte\\ | ||
+ | |||
+ | **UV**: vettore spostamenti nodali\\ | ||
+ | |||
+ | |||
+ | DIMENSION D(3, | ||
+ | DELTAEL(6), | ||
+ | |||
+ | Dopo il dimensionamento degli elementi variabili si termina l' | ||
+ | |||
+ | **D**: matrice di legame costitutivo (legge di Hooke), lavorando in 3D diventa una matrice 6x6\\ | ||
+ | **B**: matrice che lega spostamenti e deformazione\\ | ||
+ | **BT**: trasposta di B\\ | ||
+ | **DB**: prodotto tra matrice D e B (matrice temporanea)\\ | ||
+ | **ELK**: matrice di rigidezza degli elementi (aggiornata per ogni elemento, evitando così di avere un array in tre dimensioni 6x6xNELEMS)\\ | ||
+ | **IPOINT**: mappatura dei gdl globali e locali per ogni elemento. Ad esempio per l' | ||
+ | |||
+ | {{ : | ||
+ | |||
+ | **DELTAEL**: | ||
+ | **SIGMAEL**: | ||
+ | |||
+ | =====MAIN===== | ||
+ | |||
+ | OPEN(1, | ||
+ | OPEN(2, | ||
+ | CALL READIN(YM, | ||
+ | ICNMAX, | ||
+ | CALL ECHO(YM, | ||
+ | ICNXY,CNXY) | ||
+ | CALL CLEAR(2*NODES, | ||
+ | CALL CLEAR(2*NODES, | ||
+ | C CALL CLEAR(3, | ||
+ | C CALL CLEAR(6, | ||
+ | CALL DMAT(YM, | ||
+ | |||
+ | **mesh_tria_comp.dat**: | ||
+ | **mesh_tria_comp.3.txt**: | ||
+ | |||
+ | Se il comando OPEN è dato nel modo descritto sopra, il codice cerca il file all' | ||
+ | ====Subroutine Readin===== | ||
+ | Sfruttando più cicli DO per estendere la lettura ad ogni nodo, questa subroutine va a leggere dalla prima riga del file precedentemente aperto e definito come 1 (mesh_tria_comp.dat) rispettivamente il modulo di Young (YM), il modulo di Poisson (PR) e l' | ||
+ | |||
+ | | ||
+ | FXY, | ||
+ | DIMENSION XY(2, | ||
+ | ICNXY(2, | ||
+ | C | ||
+ | READ(1, | ||
+ | C | ||
+ | DO 10, | ||
+ | READ(1, | ||
+ | IF(I10.NE.NODE)THEN | ||
+ | write(*,*) ' | ||
+ | stop | ||
+ | END IF | ||
+ | 10 CONTINUE | ||
+ | C | ||
+ | DO 20, | ||
+ | READ(1, | ||
+ | IF(I20.NE.NELEM)THEN | ||
+ | write(*,*) ' | ||
+ | stop | ||
+ | END IF | ||
+ | 20 CONTINUE | ||
+ | C | ||
+ | DO 30, | ||
+ | READ(1, | ||
+ | 30 CONTINUE | ||
+ | C | ||
+ | DO 40, | ||
+ | READ(1, | ||
+ | 40 CONTINUE | ||
+ | RETURN | ||
+ | END | ||
+ | |||
+ | Per ogni ciclo DO presente nella subroutine il programma esegue un controllo di sequenzialità dei parametri (coordianate nodali, spostamenti e forze applicate) dei file di input.\\ Si dice che durante questa operazione di lettura le variabili sono " | ||
+ | |||
+ | ====Subroutine Echo==== | ||
+ | Subroutine che scrive nel file 2 (mesh_tria_comp.3.txt) tutto quello che è stato eseguito nella subroutine READIN, si nota infatti che la struttura delle due è identica con l' | ||
+ | |||
+ | | ||
+ | ICNMAX, | ||
+ | DIMENSION XY(2, | ||
+ | ICNXY(2, | ||
+ | C | ||
+ | WRITE(2, | ||
+ | WRITE(2, | ||
+ | C | ||
+ | IF(ITDP.EQ.0)THEN | ||
+ | WRITE(2, | ||
+ | END IF | ||
+ | IF(ITDP.EQ.1)THEN | ||
+ | WRITE(2, | ||
+ | END IF | ||
+ | C | ||
+ | WRITE(2, | ||
+ | DO 10, | ||
+ | WRITE(2, | ||
+ | 10 CONTINUE | ||
+ | C | ||
+ | WRITE(2, | ||
+ | DO 20, | ||
+ | WRITE(2, | ||
+ | 20 CONTINUE | ||
+ | C | ||
+ | WRITE(2, | ||
+ | DO 30, | ||
+ | WRITE(2, | ||
+ | 30 CONTINUE | ||
+ | C | ||
+ | WRITE(2, | ||
+ | DO 40, | ||
+ | WRITE(2, | ||
+ | 40 CONTINUE | ||
+ | RETURN | ||
+ | END | ||
+ | | ||
+ | ====Subroutine Clear==== | ||
+ | Inizializzazione a zero degli elementi di una matrice servendosi di due cicli DO nidificati (uno all' | ||
+ | |||
+ | | ||
+ | DIMENSION A(K1,K2) | ||
+ | DO 10,I10=1,K1 | ||
+ | DO 20,I20=1,K2 | ||
+ | A(I10, | ||
+ | 20 CONTINUE | ||
+ | 10 CONTINUE | ||
+ | RETURN | ||
+ | END | ||
+ | |||
+ | ====Subroutine Dmat==== | ||
+ | Costruzione della matrice D di applicazione del legame Hookeano tra tensioni e deformazioni: | ||
+ | |||
+ | | ||
+ | DIMENSION D(3,3) | ||
+ | IF(ITDP.EQ.0)GO TO 100 | ||
+ | IF(ITDP.EQ.1)GO TO 200 | ||
+ | C Per Stato di Tensione Piana: | ||
+ | 100 CONTINUE | ||
+ | CTP=YM/ | ||
+ | G=YM/ | ||
+ | C | ||
+ | C | 1*CTP PR*CTP | ||
+ | C D = | PR*CTP | ||
+ | C | 0 0 G | | ||
+ | D(1,1)=1. | ||
+ | D(1,2)=PR | ||
+ | D(2,1)=PR | ||
+ | D(2,2)=1. | ||
+ | DO 10,I10=1,2 | ||
+ | DO 20,I20=1,2 | ||
+ | D(I10, | ||
+ | 20 CONTINUE | ||
+ | 10 CONTINUE | ||
+ | D(1,3)=0. | ||
+ | D(2,3)=0. | ||
+ | D(3,1)=0. | ||
+ | D(3,2)=0. | ||
+ | D(3,3)=G | ||
+ | GOTO 300 | ||
+ | C Per Stato di Deformazione Piana: | ||
+ | 200 CONTINUE | ||
+ | CDP=YM*(1-PR)/ | ||
+ | CPR=PR/ | ||
+ | G=YM/ | ||
+ | C | ||
+ | C | 1*CDP | ||
+ | C D = | CDP*CPR | ||
+ | C | 0 0 G | | ||
+ | D(1,1)=1. | ||
+ | D(1,2)=CPR | ||
+ | D(2,1)=CPR | ||
+ | D(2,2)=1. | ||
+ | DO 30,I30=1,2 | ||
+ | DO 40,I40=1,2 | ||
+ | D(I30, | ||
+ | 40 CONTINUE | ||
+ | 30 CONTINUE | ||
+ | D(1,3)=0. | ||
+ | D(2,3)=0. | ||
+ | D(3,1)=0. | ||
+ | D(3,2)=0. | ||
+ | D(3,3)=G | ||
+ | GOTO 300 | ||
+ | 300 CONTINUE | ||
+ | RETURN | ||
+ | END | ||
+ | |||
+ | Per decidere il tipo di legame costitutivo da applicare per la generazione della matrice D, la subroutine legge il valore di ITDP attraverso due costrutti IF: questo genere di approccio potrebbe portare ad errore nel caso in cui ITDP fosse uguale a qualunque altro numero che non sia zero o uno, in quanto la subroutine continuerebbe con l' | ||
+ | |||
+ | =====MAIN===== | ||
+ | |||
+ | Al termine della subroutine precedente ho definito la matrice D e torno al programma principale e attivo un DO che va da 1 a NELEMS (numero elementi). Queste istruzioni vengono ripetute una volta per elemento e I10 è lo specifico numero dell' | ||
+ | |||
+ | DO 10, | ||
+ | XI=XY(1, | ||
+ | YI=XY(2, | ||
+ | XJ=XY(1, | ||
+ | YJ=XY(2, | ||
+ | XK=XY(1, | ||
+ | YK=XY(2, | ||
+ | CALL AREA(XI, | ||
+ | CALL KELMAT(XI, | ||
+ | C | ||
+ | CALL POINTVT(NELEMS, | ||
+ | CALL ASSEMBL(ELK, | ||
+ | 10 CONTINUE | ||
+ | |||
+ | Per ogni elemento prendo il nome dei nodi che gli appartengono dalla matrice NVERT. Scelto il nodo, prendo le coordinate x e y all' | ||
+ | |||
+ | ====Subroutine Area==== | ||
+ | |||
+ | |||
+ | Calcolo della superficie DEL di ciascun elemento finito triangolare a partire dalle coordinate nodali dei vertici. Controllo di dimensioni e segno dell' | ||
+ | |||
+ | SUBROUTINE AREA(XI, | ||
+ | TWODEL=XJ*YK+XK*YI+XI*YJ-(XK*YJ+XI*YK+XJ*YI) | ||
+ | AREAMIN=1.E-6 | ||
+ | C | ||
+ | IF(ABS((TWODEL/ | ||
+ | WRITE(*, | ||
+ | WRITE(*, | ||
+ | WRITE(*, | ||
+ | END IF | ||
+ | C | ||
+ | IF((TWODEL/ | ||
+ | WRITE(*, | ||
+ | WRITE(*, | ||
+ | WRITE(*, | ||
+ | END IF | ||
+ | RETURN | ||
+ | END | ||
+ | |||
+ | |||
+ | ====Subroutine Kelmat==== | ||
+ | |||
+ | Costruzione della matrice di rigidezza ELK (6x6, reale) di ciascun elemento finito triangolare attraverso la formula: F = ELK * DELTA => ELK = A * (BT * D * B). Le coordinate nodali vengono prese, come di consueto, in verso antiorario. Gli input sono le coordinate nodali dei nodi, il determinante, | ||
+ | |||
+ | SUBROUTINE KELMAT(XI, | ||
+ | DIMENSION B(3, | ||
+ | CALL CLEAR(3, | ||
+ | CALL BMAT(XI, | ||
+ | CALL PRODMAT(3, | ||
+ | CALL TRSPMAT(3, | ||
+ | CALL PRODMAT(6, | ||
+ | DEL=TWODEL/ | ||
+ | DO 10,I10=1,6 | ||
+ | DO 20,I20=1,6 | ||
+ | ELK(I10, | ||
+ | 20 CONTINUE | ||
+ | 10 CONTINUE | ||
+ | RETURN | ||
+ | END | ||
+ | | ||
+ | La matrice D, passata dal main, viene allocata in memoria al lancio della subroutine, mentre la matrice B (locale) richiede un allocamento all' | ||
+ | |||
+ | ====Subroutine Pointvt==== | ||
+ | |||
+ | Costruzione del vettore puntatore IPOINT necessario ad effettuare l' | ||
+ | Nelle celle di IPOINT viene scritto quale è il relativo grado di libertà in numerazione globale, viene riportato l' | ||
+ | |||
+ | SUBROUTINE POINTVT(NELEMS, | ||
+ | DIMENSION NVERT(3, | ||
+ | IPOINT(1)=NVERT(1, | ||
+ | IPOINT(2)=NVERT(1, | ||
+ | IPOINT(3)=NVERT(2, | ||
+ | IPOINT(4)=NVERT(2, | ||
+ | IPOINT(5)=NVERT(3, | ||
+ | IPOINT(6)=NVERT(3, | ||
+ | RETURN | ||
+ | END | ||
+ | | ||
+ | Come input prende il numero di elementi (per sapere la lunghezza di NVERT), lo specifico elemento (per sapere la colonna di NVERT da consultare), | ||
+ | Viene trovato poi il grado di libertà locale associato che riempie il vettore IPOINT che viene poi passato alla chiamante con il comando RETURN. La chiamante lo passa poi pari pari alla subroutine ASSEMBL. | ||
+ | ====Subroutine Assembl==== | ||
+ | |||
+ | Assemblaggio della matrice ELK di rigidezza di ciascun elemento finito triangolare nella matrice STRUTK di rigidezza globale della struttura.\\ | ||
+ | La matrice STRUTK viene inzializzata a zero nel MAIN PROGRAM, pertanto si ritiene superflua la sua inizializzazione in questa subroutine. | ||
+ | |||
+ | SUBROUTINE ASSEMBL(ELK, | ||
+ | DIMENSION ELK(6, | ||
+ | DO 10,I10=1,6 | ||
+ | DO 20,I20=1,6 | ||
+ | IND10=IPOINT(I10) | ||
+ | IND20=IPOINT(I20) | ||
+ | STRUTK(IND10, | ||
+ | 20 CONTINUE | ||
+ | 10 CONTINUE | ||
+ | RETURN | ||
+ | END | ||
+ | | ||
+ | Nota: il vettore NODES viene utilizzato unicamente per il dimensionamento della matrice STRUTK. | ||
+ | La riga fondamentale della sub è quella che associa ad un valore della matrice di rigidezza globale della struttura il suo vecchio valore + il valore da aggiungere dovuto al nodo considerato, | ||
+ | |||
+ | |||
+ | =====MAIN===== | ||
+ | |||
+ | C Per il Caricamento si richiama questa sub | ||
+ | CALL FORCES(IFMAX, | ||
+ | | ||
+ | ====Subroutine Forces==== | ||
+ | |||
+ | Riempimento del vettore globale delle forze nodali FORCE. | ||
+ | |||
+ | SUBROUTINE FORCES(IFMAX, | ||
+ | DIMENSION IFXY(IFMAX), | ||
+ | DO 10, | ||
+ | INDX=IFXY(I10)*2-1 | ||
+ | INDY=IFXY(I10)*2 | ||
+ | FORCE(INDX)=FXY(1, | ||
+ | FORCE(INDY)=FXY(2, | ||
+ | 10 CONTINUE | ||
+ | RETURN | ||
+ | END | ||
+ | | ||
+ | Dove la sub importa dal main il numero di nodi caricati (IFMAX), il vettore contenente il nome dei nodi caricati (IFXY) e la matrice contenente i valori delle forze lungo x e y per ogni singolo nodo. Il ciclo DO legge i nodi caricati e salva i valori delle forze nel vettore dei termini noti. | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | =====MAIN===== | ||
+ | |||
+ | | ||
+ | ====Subroutine Bmat==== | ||
+ | |||
+ | Costruzione della matrice B di collegamento tra gli spostamenti nodali e le deformazioni di ciascun elemento finito triangolare attraverso la formula: EPSILON = B * DELTA.\\ | ||
+ | Le coordinate nodali vengono prese, come di consueto, in verso antiorario.\\ | ||
+ | Infine, poiché i termini nulli, sempre nelle stesse posizioni, vengono gi
inizializzati a zero inizialmente, | ||
+ | |||
+ | SUBROUTINE BMAT(XI, | ||
+ | DIMENSION B(3,6) | ||
+ | AI=XJ*YK-XK*YJ | ||
+ | AJ=XK*YI-XI*YK | ||
+ | AK=XI*YJ-XJ*YI | ||
+ | BI=YJ-YK | ||
+ | BJ=YK-YI | ||
+ | BK=YI-YJ | ||
+ | CI=XK-XJ | ||
+ | CJ=XI-XK | ||
+ | CK=XJ-XI | ||
+ | B(1,1)=BI | ||
+ | B(1,2)=0. | ||
+ | B(1,3)=BJ | ||
+ | B(1,4)=0. | ||
+ | B(1,5)=BK | ||
+ | B(1,6)=0. | ||
+ | B(2,1)=0. | ||
+ | B(2,2)=CI | ||
+ | B(2,3)=0. | ||
+ | B(2,4)=CJ | ||
+ | B(2,5)=0. | ||
+ | B(2,6)=CK | ||
+ | B(3,1)=CI | ||
+ | B(3,2)=BI | ||
+ | B(3,3)=CJ | ||
+ | B(3,4)=BJ | ||
+ | B(3,5)=CK | ||
+ | B(3,6)=BK | ||
+ | TWODEL=AI+AJ+AK | ||
+ | DO 10,I10=1,3 | ||
+ | DO 20,I20=1,6 | ||
+ | B(I10, | ||
+ | 20 CONTINUE | ||
+ | 10 CONTINUE | ||
+ | RETURN | ||
+ | END | ||
+ | | ||
+ | ====Subroutine Prodmat==== | ||
+ | |||
+ | Esecuzione del prodotto AB di due matrici A e B; prende in input il numero di righe della prima matrice, il numero di colonne della prima matrice (uguale alle righe della seconda) e numero di colonne della seconda matrice. | ||
+ | |||
+ | SUBROUTINE PRODMAT(K1, | ||
+ | DIMENSION A(K1, | ||
+ | DO 10,I10=1,K1 | ||
+ | DO 30,I30=1,K3 | ||
+ | AB(I10, | ||
+ | DO 20,I20=1,K2 | ||
+ | AB(I10, | ||
+ | 20 CONTINUE | ||
+ | 30 CONTINUE | ||
+ | 10 CONTINUE | ||
+ | RETURN | ||
+ | END | ||
+ | | ||
+ | Il prodotto è una operazione computazionalmente molto costosa: date due matrici quadrate di ordine " | ||
+ | I due cicli più esterni (I10 e I30) scorrono sugli elementi della matrice prodotto e, per ogni elemento della matrice prodotto si fa una sommatoria fra la I10-esima riga della matrice del primo fattore e la colonna I30 del secondo fattore di cui fai il prodotto scalare.\\ La sommatoria ha bisogno di una variabile di accumulo che appunto è la cella della matrice di destinazione, | ||
+ | |||
+ | |||
+ | |||
+ | {{: | ||
+ | |||
+ | ~~DISCUSSION~~ |