Laboratorio di Calcolo. 2019/20.

Esercitazione n. 6


  1. Modificare il programma per l' oscillatore armonico dell' esercitazione precedente in modo che possa trattare l' oscillatore armonico bidimensionale.  Introdurre array di rango uno per rappresentare posizioni,  velocità  e  forze.  Massa e costante elastica restano scalari. Usando la sintassi delle operazioni su array, le uniche modifiche, a parte la dichiarazione degli array, dovrebbero riguardare il calcolo delle energie cinetica e potenziale. Per la verifica della conservazione dell'  energia può  esser utile scrivere su file,  oltre all' energia cinetica totale,  anche quella relativa a solo una  delle componenti della velocità. Attenzione al fatto che nei file di output il significato dei dati nelle diverse colonne cambia se pos e vel sono degli array. Aggiungere poi anche il calcolo del  momento angolare,  usando la formula per le componenti cartesiane (nel presente problema basta la componente z)
    Lz = m ( x vy - y vx)
    e  verificare come questo dipende dall' intervallo di integrazione (dt).
    Può  essere utile ricordare che le function intrinseche SUM(x) e  DOT_PRODUCT(x,y)   rispettivamente sommano le componenti dell' array  x  ed eseguono il prodotto scalare degli array x e y. Non esiste invece una funzione intrinseca per il prodotto vettoriale. 


  2. Modificare il programma per l' oscillatore armonico bidimensionale in modo da lavorare con due costanti elastiche diverse lungo le direzioni x e y. Attenzione a come si scrive l'  energia potenziale in questo caso. Dovrebbe essere la somma delle energie potenziali di due oscillatori indipendenti,  uno lungo l'  asse x con  costante kx  e  l'  altro lungo y con costante  ky. Provare a studiare il comportamento della traiettoria nel piano x y  in funzione del rapporto tra le frequenze del moto lungo x  e lungo y  (cosa succede se il rapporto tra le frequenze (cioè tra le radici quadrate delle costanti elastiche)  è  un numero razionale ?   E   se  è  irrazionale ?  Ma  cosa sono i numeri irrazionali sul computer ?).


  3. La dimensione di un  array  può anche essere dichiarata a run time , quando cioè il programma  viene eseguito. In tal caso andrà specificato l' aggettivo allocatable  nella dichiarazione dell' array, senza dare esplicitamente la dimensione  come ad esempio in

    real, dimension(:,:), allocatable    :: A

    Nell' attributo dimension si indicherà il numero di indici, il rango dell' array, mediante un corrispondente numero di "due punti" (:) separati da virgole. Per far sì che venga riservata la memoria (RAM) per A sarà necessario che, una volta note le estensioni e i limiti sugli indici, si esegua l' istruzione di allocazione. Per esempio le istruzioni:

             read*,N
             allocate(W(-N:N,N),P(N), stat=error)
    acquisiscono il valore di N al momento dell'esecuzione del programma , e poi, una volta noto il valore numerico di N, il processo richiede memoria al sistema operativo per una matrice W (2 indici) in cui il primo indice varia tra -N e N e il secondo tra 1 e N e per un array (vettore) P (1 indice). error rappresenta una variabile intera il cui valore se diverso da zero indica che non è  stato possibile allocare la memoria richiesta. Attenzione: stat=error può essere assente. In tal caso, se non c'è disponibilità della memoria richiesta il programma termina con errore. Se invece si inserisce il modificatore stat=error ci si sta impegnando a gestire esplicitamente nel programma cosa fare in caso di errore e quindi si è tenuti ad aggiungere una verifica del valore di error, terminando il programma in caso di valori diversi da zero. Per far terminare l' esecuzione del programma è sufficiente dare l' istruzione STOP. Quando la memoria allocata non serve più  la si può  rilasciare al sistema operativo mediante il comando  

          deallocate(W,P)

    Quando un programma termina di essere eseguito tutta la corrispondente memoria viene liberata in automatico per cui non è necessario deallocare esplicitamente la memoria alla fine del programma. Se un array allocabile appare a sinistra del segno di uguale in un' istruzione di assegnazione e a destra appare un'espressione corrispondente ad un array dello stesso rango l' array viene automaticamente allocato con la stessa forma del membro a destra. Se era già allocato, viene automaticamente riallocato.

    Modificare il programma per il calcolo del prodotto scalare dell' esercitazione n.5 in modo da usare array allocabili e che il numero di componenti dei vettori sia dato in input di volta in volta.


Esercizi che possono essere svolti autonomamente.


  1. Scrivere un programma   che dichiari  un array x a 4  componenti ed una  matrice  a   2x4   e  legga le componenti  di entrambi gli array  con le istruzioni read*,x    e read*,a.  Dopo di che il programma  dovrebbe scrivere su schermo l' array x e la matrice a.     Attenzione, il Fortran considera contigue le locazioni di una matrice secondo un ordinamento per colonne: in una matrice 2x4 l' ordine degli elementi è   11,21,12,22,13,23,14,24. Per scrivere la matrice in modo da visualizzarne la struttura in righe e colonne  occorre ricordare che ad ogni istruzione print*,...  corrisponde una riga su schermo. Può  risultare utile usare le sezioni di array, ricordando che a(i,:) è la sezione corrispondente all' i-esima riga. In generale, una matrice B, reale NxM , viene dichiarata mediante l' istruzione:
    real,dimension(N,M) :: B


  2. Scrivere un programma  che accetti in input 8 cifre 0 o 1 e le inserisca in un array  di interi di nome a. Se le consideriamo come le cifre della rappresentazione binaria di un intero (positivo) vogliamo che il programma fornisca in output il valore decimale corrispondente. La cifra più significativa sia a(1) e la meno significativa a(8).



  3. L' istruzione REAL, DIMENSION... permette di definire qualsiasi insieme di interi contigui come insieme di variabilità  per l' indice di un vettore. Per esempio, l' istruzione
  4.             REAL, DIMENSION(-3:10)      :: A
    definisce A come array di 14 componenti (indice variabile tra -3 e 10, 0 compreso)

    Scrivere un programma   che legga interi (con segno) e scriva quante volte è  stato immesso ogni intero tra -5 e 5 (ogni intero può essere immesso un numero arbitrario di volte). In pratica si sta chiedendo di realizzare l' istogramma dei numeri immessi nell' intervallo predefinito.

    Esempio:  a fronte dell'  input:  -3  15  3  4   2  1  2  2  -3  22,  il programma dovrebbe  scrivere:

    -5 0
    -4 0
    -3 2
    -2 0
    -1 0
    0 0
    1 1
    2 3
    3 1
    4 1
    5 0

  5. La subroutine di libreria  random_number(x),  in cui l'  argomento x può  essere sia uno scalare sia un array di dimensione N,  ritorna uno o una  N-pla di numeri real  compresi tra 0 e 1 distribuiti statisticamente in modo uniforme.  Questo significa che il valor medio di  una  sequenza infinita sarebbe 0.5. 

    Costruire un programma, anche riutilizzando programmi delle esercitazioni precedenti, che chiami la subroutine  con  argomento scalare  M  volte (mediante un ciclo do)  e valuti il valor medio  della sequenza di numeri casuali,  scrivendolo alla fine. Verificare di quanto occorre aumentare M per migliorare di una cifra decimale l' accordo con il risultato esatto. Verificare anche se, per valori molto alti di M, non compaia qualche risultato inatteso.

    Si  ricordi che per chiamare una subroutine l' istruzione è:
    CALL nomeSubroutine(arg1,...)

    L' algoritmo per la generazione dei numeri casuali è in realtà deterministico.  Quindi ogni nuova esecuzione del programma darà  la stessa sequenza di numeri.  Vedremo pià avanti come modificare questo comportamento.