Verificare che implementi l' algoritmo di Verlet introdotto nell' ultima lezione.
Provare a determinare un valore ottimale per
l' intervallo temporale di integrazione (dt).
Verificare inoltre l' accuratezza dell'
integrazione numerica
confrontando i risultati per la posizione e velocità con i
valori analitici della soluzione (da far
calcolare nel programma ed eventualmente stampare su un altro
file oppure da far calcolare da gnuplot direttamente).Si
suggerisce di usare la forma A
cos(omega t) + B sin(omega t) per la
soluzione analitica in quanto così risulta immediato attribuire
i
valori alle costanti A e B in funzione dei dati iniziali (A=x0,
B=v0/omega).
program harmDa notare che la variabile
implicit none
real :: massa=1.0,kappa=1.0 ! valori di default per massa e cost. elastica
real :: dt,ekin,epot
real :: pos,vel,vel_parziale,f
integer :: nstep,it
write(unit=*,fmt="(a)",advance="no")"delta t : " ! il formato (a) chiede che il dato sia trattato come
read*,dt ! caratteri e advance="no" sopprime l' inserimento del
write(unit=*,fmt="(a)",advance="no")"n.step: " ! caratter "a capo" alla fine della linea per cui
read*,nstep ! la prossima operazione di lettura/scrittura inziera'
write(unit=*,fmt="(a)",advance="no")"massa: " ! sula stessa riga di schermo di quella corrente
read*,massa
write(unit=*,fmt="(a)",advance="no")"kappa: "
read*,kappa
write(unit=*,fmt="(a)",advance="no")"pos(0): "
read*,pos
write(unit=*,fmt="(a)",advance="no")"vel(0): "
read*,vel
it=0 ! step 0 : valori iniziali
write(unit=1,fmt=*)it,it*dt,pos,vel
epot = 0.5 * kappa * pos**2
f = - kappa * pos
ekin = 0.5 * massa * vel**2
write(unit=2,fmt=*)it,dt*it,ekin,epot,ekin+epot
do it = 1,nstep
pos = pos + vel * dt + 0.5* f/massa * dt**2
vel_parziale = vel + 0.5 * dt * f/massa ! prima parte della formula per le velocita'
f = - kappa * pos
epot = 0.5 * kappa * pos**2
vel = vel_parziale + 0.5 * dt * f/massa ! la formula per le velocita' viene completata qui
write(unit=1,fmt=*)it,it*dt,pos,vel
ekin = 0.5 * massa * vel**2
write(unit=2,fmt=*)it,it*dt,ekin,epot,ekin+epot
end do
end program harm
vel_parzialenon è strettamente necessaria. Il valore parziale della velocità potrebbe essere immagazzinato nella stessa variabile vel che poi, dopo il ricalcolo della forza, verrebbe ridefinita:
vel = vel + 0.5 * dt * f/massa
f = - kappa * pos
epot = 0.5 * kappa * pos**2
vel = vel + 0.5 * dt * f/massa
tipo, dimension(N) :: Adove tipo rappresenta il tipo dati dell' array (ovvero real, integer, character, logical, complex) ed N deve essere una costante intera (eventualmente una costante simbolica intera) esprimente il numero di componenti del vettore. Un vettore può esser letto componente per componente con un'istruzione iterata del tipo:
do I=1,Noppure mediante un' unica istruzione:
read*,A(I)
end do
read*,A
o mediante un do implicito, utile quando non si vogliono leggere tutte le componenti dell' array, ma con la possibilità di immettere i dati sulla stessa linea:read*,(A(i),i=1,N-3)
Lo stesso risultato può essere ottenuto mediante l' utilizzo di una sezione di array:read*,A(1:N-3)
Il modulo di un vettore è la
radice quadrata del prodotto
scalare
del vettore con se stesso. Il coseno dell' angolo tra 2 vettori
può essere ottenuto dividendo
il prodotto scalare dei due vettori per il prodotto dei moduli. Il
Fortran dispone di una funzione acos(x) che permette
di ottenere l' ampiezza (in radianti) dell' angolo il cui coseno
è x
(la funzione trigonometrica arccos (x))
Inoltre le funzioni sum(x) e dot_product(x,y) calcolano
la somma delle componenti dell' array x e il prodotto scalare tra i due
array x e y.
Implementare un programma che
L*m*( 0.5*L*vel**2 + g*(1-cos(pos)) )