410 likes | 657 Views
Il linguaggio Fortran 90: 4. Array: Vettori e Matrici. Vettori. Gruppi di variabili dello stesso tipo memorizzate in locazioni contigue di memoria. La i -esima posizione dell’array a è indicata con a(i) Gli elementi di un array sono normali variabili. Dichiarazione di variabili vettore.
E N D
Vettori • Gruppi di variabili dello stesso tipo memorizzate in locazioni contigue di memoria. • La i-esima posizione dell’array a è indicata con a(i) • Gli elementi di un array sono normali variabili
Dichiarazione di variabili vettore • REAL, DIMENSION (20) :: a L’attributo DIMENSION serve per dichiarare la lunghezza del vettore • CHARACTER(len=20), DIMENSION (50) :: cognome Indica un vettore di 50 elementi ognuno dei quali è una stringa di 20 caratteri • Costanti di tipo array: (/ 1, 2, 3, 4, 5 /) • Inizializzazione di un array: INTEGER, DIMENSION (5) :: a = (/ 1, 2, 3, 4, 5 /) • DO i=1, 5 a(i)=i END DO • Il range di variabilità può essere fissato altrimenti: REAL DIMENSION (inf : sup) :: a
Somma di due vettori ! File: somvett1.for ! Scopo: esempio di uso di array PROGRAM somma_vettori ! Questo programma calcola la somma di due vettori a 3 componenti ! *** SEZIONE DICHIARATIVA *** ! IMPLICIT NONE INTEGER, PARAMETER :: dimensione = 3 INTEGER, DIMENSION(dimensione) :: v1, v2 ! i due vettori letti INTEGER, DIMENSION(dimensione) :: somma ! il vettore somma INTEGER :: i ! indice di ciclo per scandire le componenti dei vettori ! *** SEZIONE ESECUTIVA *** ! ! lettura primo vettore WRITE(*,*) 'Immetti il primo vettore!' DO i = 1, dimensione ! leggiamo il vettore una componente alla volta WRITE(*,*) 'Componente ', i, ' ? ' READ (*,*) v1(i) END DO
Somma di due vettori (cont.) ! lettura secondo vettore WRITE(*,*) 'Immetti il secondo vettore!' DO i = 1, dimensione ! leggiamo il vettore una componente alla volta WRITE(*,*) 'Componente ', i, ' ? ' READ (*,*) v2(i) END DO ! calcolo vettore somma DO i = 1, dimensione somma(i) = v1(i) + v2(i) ! N.B. si potrebbe fare direttamente somma = v1 + v2 END DO ! stampa del vettore somma WRITE(*,*) 'Il vettore somma e'':' DO i = 1, dimensione WRITE(*,*) 'Componente ', i, ' : ', somma(i) END DO STOP END PROGRAM somma_vettori
Passaggio di Parametri Vettore • Array fittizi di forma presunta Una procedura non conosce in generale la dimensione dei parametri effettivi array passati alla procedura • Array fittizi non specificano la dimensione dell’array • REAL, DIMENSION (:) :: a INTEGER :: i DO i = LBOUND (a,1), UBOUND (a,1) a (i) = 0 END DO • In alternativa occorre passare come parametro la dimensione degli array
Passaggio di Parametri di Tipo Vettore ! File: util-vet.for MODULE operazioni_su_vettori ! Questo modulo contiene alcune unita‘ che effettuano operazioni su ! Vettori: ! - leggi_vettore : subroutine per la lettura di un vettore di interi ! di lunghezza arbitraria ! - stampa_vettore : subroutine per la stampa di un vettore di interi ! di lunghezza arbitraria ! - somma_vettori : funzione per la somma vettoriale di due vettori di ! interi di lunghezza arbitraria (passata come parametro) ! - somma_vettori_sub : subroutine per la somma vettoriale di due ! vettori di interi di lunghezza arbitraria. Analoga alla precedente ! ma non e' necessario passare la lunghezza. CONTAINS
Passaggio di Parametri di Tipo Vettore (cont.) SUBROUTINE leggi_vettore (vet) IMPLICIT NONE ! ** DICHIARAZIONE ARGOMENTI FITTIZI INTEGER, INTENT(IN OUT), DIMENSION(:) :: vet ! il vettore di input ! ** DICHIARAZIONE VARIABILI LOCALI INTEGER :: i ! indice di ciclo DO i = LBOUND(vet,1), UBOUND(vet,1) WRITE(*,*) 'Componente ', i, ' ? ' READ (*,*) vet(i) END DO RETURN END SUBROUTINE leggi_vettore
Passaggio di Parametri di Tipo Vettore (cont.) SUBROUTINE stampa_vettore (vet) ! DICHIARAZIONE ARGOMENTI FITTIZI INTEGER, DIMENSION(:), INTENT(IN) :: vet ! Vettore di input ! DICHIARAZIONE VARIABILI LOCALI INTEGER :: i ! indice del ciclo DO i = LBOUND(vet,1), UBOUND(vet,1) WRITE(*,*) 'Componente ', i, ':', vet(i) END DO RETURN END SUBROUTINE stampa_vettore
Passaggio di Parametri di Tipo Vettore (cont.) FUNCTION somma_vettori (vet1, vet2, dim) IMPLICIT NONE ! ** DICHIARAZIONE ARGOMENTI FITTIZI INTEGER, DIMENSION(:), INTENT(IN) :: vet1, vet2 ! i vettori di input INTEGER, INTENT(IN) :: dim ! la lunghezza dei vettori ! ** DICHIARAZIONE TIPO FUNZIONE INTEGER, DIMENSION(dim) :: somma_vettori ! ** DICHIARAZIONE VARIABILI LOCALI INTEGER :: i ! indice del ciclo DO i = LBOUND(vet1,1), UBOUND(vet1,1) somma_vettori(i) = vet1(i) + vet2(i) END DO RETURN END FUNCTION somma_vettori
Passaggio di Parametri di Tipo Vettore (cont.) SUBROUTINE somma_vettori_sub (vet1, vet2, ris) IMPLICIT NONE ! ** DICHIARAZIONE ARGOMENTI FITTIZI INTEGER, DIMENSION(:), INTENT(IN) :: vet1, vet2 ! i vettori di input INTEGER, DIMENSION(:), INTENT(OUT) :: ris ! il vettore di output INTEGER :: i ! indice del ciclo ! *** SEZIONE ESECUTIVA DO i = LBOUND(vet1,1), UBOUND(vet1,1) ris(i) = vet1(i) + vet2(i) END DO RETURN END SUBROUTINE somma_vettori_sub
Passaggio di Parametri di Tipo Vettore (cont.) ! File: somvett2.for ! Scopo: Uso di sottoprogrammi che manipolano array unidimensionali di ! due vettori a 3 componenti, usando le SUBROUTINE PROGRAM somma_vettori_2 ! *** SEZIONE DICHIARATIVA *** ! USE operazioni_su_vettori IMPLICIT NONE INTEGER, PARAMETER :: dimensione = 3 INTEGER, DIMENSION(dimensione) :: v1, v2 ! i due vettori letti INTEGER, DIMENSION(dimensione) :: somma ! il vettore somma
Passaggio di Parametri di Tipo Vettore (cont.) ! *** SEZIONE ESECUTIVA *** ! WRITE(*,*) 'Immetti il primo vettore!' CALL leggi_vettore(v1) ! lettura secondo vettore WRITE(*,*) 'Immetti il secondo vettore!' CALL leggi_vettore(v2) ! calcolo vettore somma con la funzione somma = somma_vettori(v1,v2,dimensione) ! stampa del vettore somma WRITE(*,*) 'Il vettore somma e'':' CALL stampa_vettore(somma) ! calcolo vettore somma con la subroutine CALL somma_vettori_sub(v1,v2,somma) ! stampa del vettore somma WRITE(*,*) 'Il vettore somma (calcolato in altra maniera) e'':' CALL stampa_vettore(somma) STOP END PROGRAM somma_vettori_2
Ordinamento di un Vettore • Ordinare un vettore di n interi in modo non decrescente.
Algoritmo di Ordinamento loop1: DO i=1, n-1 “Tova la posizione k_min del minimo intero nelle posizioni da i a n” “Scambia l’elemento nella posizione i con l’elemento nella posizione k_min” END DO loop1
Ordinamento di un Vettore (Cont.) “Trova la posizione k_min del minimo intero nelle posizioni da i a n” k_min = i loop2: DO j=i+1, n IF (a(j) < a(k_min)) k_min = j END DO loop2 “Scambia l’elemento nella posizione i con l’elemento nella posizione k_min” tmp = a(i) a(i) = a(kmin) a(kmin) = tmp
Ordinamento di un Vettore (Cont.) SUBROUTINE ordinavett(v) ! Scopo: ordinamento di un vettore di interi IMPLICIT NONE ! Dichiarazione parametri formali INTEGER, DIMENSION (:), INTENT (IN OUT) :: v ! Dichiarazione variabili locali INTEGER :: i, j, k_min, i_min, i_max, tmp i_min = LBOUND(v,1) i_max = UBOUND(v,1) loop1: DO i=i_min, (i_max - 1) k_min = i loop2: DO j=i+1, i_max IF (v(j) < v(k_min)) k_min = j END DO loop2 tmp = v(i) v(i) = v(k_min) v(k_min) = tmp END DO loop1 RETURN END SUBROUTINE ordinavett
Ordinamento di un Vettore (Cont.) ! File: test_ordinavett.for ! Scopo: testare la subroutine ordinavett(v) che ordina un vettore di interi PROGRAM test_ordinavett USE operazioni_su_vettori IMPLICIT NONE INTEGER, PARAMETER :: dimensione = 3 INTEGER, DIMENSION(dimensione) :: v ! vettore da leggere e ordinare WRITE(*,*) 'Immetti il vettore di interi da ordinare ' CALL leggi_vettore(v) ! stampa del vettore inserito WRITE(*,*) 'Vettore inserito: ' CALL stampa_vettore(v) ! ordino il vettore somma con la funzione ordinavett(v) CALL ordinavett(v) ! stampa del vettore ordinato WRITE(*,*) 'Vettore ordinato: ' CALL stampa_vettore(v) STOP END PROGRAM test_ordinavett
Matrici • Vettori a due dimensioni • Ogni elemento è indicato da un indice di riga ed un indice di colonna • L’elemento della matrice di indice di riga i ed indice di colonna j è indicato con a(i,j)
Dichiarazione di Matrici • INTEGER, DIMENSION (5,10) :: a • REAL, DIMENSION (0:100, 5:20) :: valori • Inizializzazione di una Matrice INTEGER, DIMENSION (7,10) :: mat DO i=1, 7 DO j=1, 10 mat(i,j) = 0 END DO END DO
Gestione delle matrici ! File: mod_matr.for MODULE modulo_matrici ! Questo modulo contiene alcune unita‘ che effettuano operazioni su ! matrici: ! - leggi_matrice : subroutine per la lettura di una matrice ! bidimensionale di interi di forma arbitraria ! - stampa_matrice : subroutine per la stampa di una matrice ! bidimensionale di interi di forma arbitraria ! - somma_matrici : funzione per la somma vettoriale di due matrici ! bidimensionali di interi di forma arbitraria ! - prodotto_matrici : funzione che calcola il prodotto di due ! matrici di interi CONTAINS
Gestione delle matrici (cont) SUBROUTINE leggi_matrice (mat) IMPLICIT NONE ! ** DICHIARAZIONE ARGOMENTI FITTIZI INTEGER, INTENT(IN OUT), DIMENSION(:,:) :: mat ! matrice di input ! ** DICHIARAZIONE VARIABILI LOCALI INTEGER :: i, j, r_min, r_max, c_min, c_max r_min = LBOUND (mat,1) r_max = UBOUND (mat,1) c_min = LBOUND (mat,2) c_max = UBOUND (mat,2) WRITE(*,*) 'Inserisci matrice', (r_max-r_min+1), ' *',(c_max-c_min+1) DO i = r_min, r_max DO j = c_min, c_max WRITE(*,*) 'componente ', i, j, ' : ' READ (*,*) mat(i,j) END DO END DO RETURN END SUBROUTINE leggi_matrice
Gestione delle matrici (cont) SUBROUTINE stampa_matrice (mat) IMPLICIT NONE ! ** DICHIARAZIONE ARGOMENTI FITTIZI INTEGER, INTENT(IN), DIMENSION(:,:) :: mat ! matrice di input ! ** DICHIARAZIONE VARIABILI LOCALI INTEGER :: i, j, r_min, r_max, c_min, c_max r_min = LBOUND (mat,1) r_max = UBOUND (mat,1) c_min = LBOUND (mat,2) c_max = UBOUND (mat,2) DO i = r_min, r_max WRITE(*,*) 'riga', i DO j = c_min, c_max WRITE(*,*) ' col.', j, ' =', mat(i,j) END DO END DO RETURN END SUBROUTINE stampa_matrice
Somma di Matrici SUBROUTINE somma_matrici(a, b, c) IMPLICIT NONE ! Dichiarazioni parametri fittizi INTEGER, DIMENSION(:,:), INTENT (IN) :: a, b INTEGER, DIMENSION (:,:),INTENT (OUT) :: c ! Dichiarazione variabili locali INTEGER :: i, j, r_min, r_max, c_min, c_max r_min = LBOUND (a,1) r_max = UBOUND (a,1) c_min = LBOUND (a,2) c_max = UBOUND (a,2) DO i = r_min, r_max DO j = c_min, c_max c(i,j) = a (i,j) + b (i,j) END DO END DO RETURN END SUBROUTINE somma_matrici
Moltiplicazione tra Matrici • Date due matrici a(n:m) e b(m:p) calcolare la matrice prodotto c(n:p). DO i=1, n DO j=1, p END DO END DO
Moltiplicazione tra Matrici (cont.) SUBROUTINE prodotto_matrici (a,b,c,n,m,p) IMPLICIT NONE ! Dichiarazioni parametri formali INTEGER, INTENT(IN) :: n, m, p INTEGER, DIMENSION (n,m), INTENT (IN) :: a INTEGER, DIMENSION (m,p), INTENT (IN) :: b INTEGER, DIMENSION (n,p), INTENT (OUT) :: c ! Dichiarazione variabili locali INTEGER :: i, j, k DO i = 1, n DO j = 1, p c(i,j) = 0 DO k = 1, m c(i,j) = c(i,j) + a(i,k) * b(k,j) END DO END DO END DO RETURN END SUBROUTINE prodotto_matrici
Calcolo del minimo locale • Data una matrice a(n:m) calcolare per ogni elemento a(i,j) il minimo tra a(i,j) e gli elementi adiacenti.
Calcolo del minimo locale (cont.) SUBROUTINE minimo_locale(a,b,n,m) IMPLICIT NONE INTEGER, INTENT(IN) :: n, m INTEGER, DIMENSION(n,m), INTENT (IN) :: a INTEGER, DIMENSION (n,m),INTENT (OUT) :: b ! Dichiarazione variabili locali INTEGER :: i, j, k, l, i1,i2, j1, j2,min IF ((n < 2) .OR. (m < 2)) THEN b = a ELSE loop1: DO i = 1, n loop2: DO j = 1, m “Calcolo del minimo locale nell’intorno di a(i,j) ed assegnazione a b(i,j)” END DO loop2 END DO loop1 END IF RETURN END SUBROUTINE minimo_locale END MODULE modulo_matrici
Calcolo del minimo locale (cont.) “Calcolo del minimo locale nell’intorno di a(i,j)”: IF (i == 1) THEN i1 = 1 ELSE i1 = i-1 END IF IF (i == n) THEN i2 = n ELSE i2 = i+1 END IF IF (j == 1) THEN j1 = 1 ELSE j1 = j-1 END IF IF (j == m) THEN j2 = m ELSE j2 = j+1 END IF
Calcolo del minimo locale (cont.) min = a(i,j) loop3: DO k = i1, i2 loop4: DO l = j1, j2 IF (a(k,l) < min) min = a(k,l) END DO loop4 END DO loop3 b(i,j) = min
Potenza elettrica erogata • Per ogni istante di tempo si conosce la potenza elettrica erogata da n generatori. • L’osservazione delle potenza erogata prosegue per m istanti di tempo • Scrivere una SUBROUTINE che calcoli la potenza media erogata da ogni generatore lungo gli m istanti di tempo ed una SUBROUTINE che calcoli la potenza totale erogata dagli n generatori ad ogni istante di tempo
Potenza elettrica erogata(cont.) • I dati di input alla procedura sono rappresentati in una matrice di reali erogati(n,m) di n righe ed m colonne. • I dati di output sono rappresentati in un vettore media(n) ed un vettore totale(m)
Potenza elettrica erogata(cont.) • Esempio: 4 generatori, 5 istanti di tempo
Potenza elettrica erogata(cont.)Calcolo della potenza media SUBROUTINE pot_media (erogati, n, m, media) ! Scopo: calcolo della potenza media erogata da ogni generatore ! *** SEZIONE DICHIARATIVA *** ! IMPLICIT NONE ! Dichiarazione parametri formali REAL, DIMENSION(:,:), INTENT(IN) :: erogati INTEGER, INTENT(IN) :: n, m REAL, DIMENSION(:), INTENT(OUT) :: media ! Dichiarazione variabili locali INTEGER :: i,j REAL ::temp
Potenza elettrica erogata(cont.)Calcolo della potenza media ! *** SEZIONE ESECUTIVA *** ! DO i=1, n ! Calcola la potenza media del generatore i temp = 0. DO j=1, m ! Scandisci gli m istanti di tempo temp = temp + erogati(i,j) END DO media(i) = temp / m END DO RETURN END SUBROUTINE pot_media
Potenza elettrica erogata(cont.)Calcolo della potenza totale SUBROUTINE pot_totale (erogati, n, m, totale) ! Scopo: calcolo della potenza totale erogata da ogni generatore ! *** SEZIONE DICHIARATIVA *** ! IMPLICIT NONE ! Dichiarazione parametri formali REAL, DIMENSION(:,:), INTENT(IN) :: erogati INTEGER, INTENT(IN) :: n, m REAL, DIMENSION(:), INTENT(OUT) :: totale ! Dichiarazione variabili locali INTEGER :: i,j REAL ::temp
Potenza elettrica erogata(cont.)Calcolo della potenza totale ! *** SEZIONE ESECUTIVA *** ! DO i=1, m ! Calcola la potenza totale erogata al tempo i temp = 0. DO j=1, n ! Scandisci gli n generatori temp = temp + erogati(j,i) END DO totale(i) = temp END DO RETURN END SUBROUTINE pot_totale
Calcolo dei prodotti scalari • Una matrice x(n:m) memorizza le componenti di n vettori ad m dimensioni • Scrivere una SUBROUTINE che calcoli il prodotto scalare tra tutte le coppie di vettori • Il risultato e’ formato di n**2 prodotti scalari che memorizziamo in una matrice prod (n:n)
Calcolo dei prodotti scalari EX: m=3 v1 = x(1,1) i + x(1,2) j+ x(1,3) k v2 = x(2,1) i + x(2,2) j+ x(2,3) k v1 v2 = x(1,1) * x(2,1) + x(1,2) * x(2,2) + x(1,3) * x(2,3)
Calcolo dei prodotti scalari (cont.) SUBROUTINE prodotto_scalare (x, n, m, prod) ! Scopo: calcolo dei prodotti scalari tra tutte le coppie di n righe ! di una matrice x(n,m). ! Ritorna la matrice dei prodotti scalari prod(n,n) ! *** SEZIONE DICHIARATIVA *** ! IMPLICIT NONE !Dichiarazione parametri formali INTEGER, INTENT(IN) :: n, m REAL, DIMENSION(:,:), INTENT(IN) :: x ! x(i,j) memorizza la j-ma componente dell’i-mo vettore REAL, DIMENSION(:,:), INTENT(OUT) :: prod ! Prod(i,j) memorizza il prodotto scalare tra il vettore i ed il ! vettore j !Dichiarazione variabili locali INTEGER :: i, j, k REAL :: tmp
Calcolo dei prodotti scalari (cont.) ! *** SEZIONE ESECUTIVA *** ! DO i = 1, n DO j = 1, n tmp = 0.0 DO k = 1, m tmp = tmp + x(i,k) * x(j,k) END DO WRITE(*,*)'prod(',i,j,') = ',tmp prod (i,j) = tmp END DO END DO RETURN END SUBROUTINE prodotto_scalare