FORTRAN 90 Ruch planet Janusz Andrzejewski 30/04/13
Algorytm Verleta (podstawowy) x[n+1] = 2x[n] x[n 1] + dt^2 F[n]/m + O(dt^4 ) v[n] = (x[n+1] x[n 1] )/(2dt ) + O(dt^3 ) x[1] = x[0] + v[0] τ + (F[0]/m)dt^2 /2 + O(dt^3 ) 2
Ruch Planet Stała (nieruchoma) planeta o masie M Dwie planety które mogą się poruszać, o masach dużo mniejszych niż M Wszystkie planety oddziałują siłą grawitacyjną Program wylicza tzw całki ruchu (energie całkowitą i moment pędu calkowity) 3
Podstawowy typ danych TYPE wspolrzedne REAL(dp) :: x, y END TYPE wspolrzedne TYPE OpisCzastki REAL(dp) :: m TYPE(wspolrzedne) :: pol, pred END TYPE OpisCzastki! Stała grawitacyjna REAL(dp), PARAMETER :: G=1.0 TYPE(OpisCzastki) :: czm 4
Obliczanie siły SUBROUTINE Force(cz1, cz2, F1, F2) TYPE(OpisCzastki), INTENT(IN) :: cz1, cz2 TYPE(wspolrzedne), INTENT(OUT) :: F1, F2 SUBROUTINE Force(cz1, cz2, F1, F2) TYPE(OpisCzastki), INTENT(IN) :: cz1, cz2 TYPE(wspolrzedne), INTENT(OUT) :: F1, F2 F1%x=0.0_dp; F1%y=0.0_dp CALL silagrawitacji(czm, cz1, F1) CALL silagrawitacji(cz2, cz1, F1) F1%x=0.0_dp; F1%y=0.0_dp CALL silagrawitacji(czm, cz1, F1) CALL silagrawitacji(cz2, cz1, F1) F2%x=0.0_dp; F2%y=0.0_dp CALL silagrawitacji(czm, cz2, F2) CALL silagrawitacji(cz1, cz2, F2) F2%x=0.0_dp; F2%y=0.0_dp CALL silagrawitacji(czm, cz2, F2) CALL silagrawitacji(cz1, cz2, F2) END SUBROUTINE Force END SUBROUTINE Force 5
Obliczanie energii i momentu pędu SUBROUTINE EL(cz1, cz2, E, L) TYPE(OpisCzastki), INTENT(IN) :: cz1, cz2 REAL(dp), INTENT(OUT) :: E, L E=EnergiaMechaniczna(cz1)+ EnergiaMechaniczna(cz2)+ EnePotencjalna(cz1, cz2) L=MomentPedu(cz1)+MomentPedu(cz2) END SUBROUTINE EL REAL(dp) FUNCTION EnergiaMechaniczna(cz) TYPE(OpisCzastki), INTENT(IN) :: cz REAL(dp) :: v1s v1s=modul(cz%pred)**2 EnergiaMechaniczna= cz%m*v1s/2.0_dp+enepotencjalna(czm, cz) END FUNCTION EnergiaMechaniczna REAL(dp) FUNCTION EnePotencjalna(cz1, cz2) TYPE(OpisCzastki), INTENT(IN) :: cz1, cz2 REAL(dp) :: r r=modulroznica(cz1%pol, cz2%pol) EnePotencjalna=-G*cz1%m*cz2%m/r END FUNCTION EnePotencjalna REAL(dp) FUNCTION MomentPedu(cz) TYPE(OpisCzastki), INTENT(IN) :: cz MomentPedu=cz%m*(cz%pol%x*cz%pred%ycz%pol%y*cz%pred%x) END FUNCTION MomentPedu 6
Pomocnicze rzeczy REAL(dp) FUNCTION modul(pol) TYPE(wspolrzedne), INTENT(IN) :: pol modul=sqrt(pol%x**2+pol%y**2) END FUNCTION modul SUBROUTINE pods(lewa, prawa) TYPE(OpisCzastki), INTENT(OUT) :: lewa TYPE(OpisCzastki), INTENT(IN) :: prawa REAL(dp) FUNCTION modulroznica(pol1, pol2) TYPE(wspolrzedne), INTENT(IN) :: pol1, pol2 TYPE(wspolrzedne) :: pom pom%x=pol1%x-pol2%x pom%y=pol1%y-pol2%y lewa%m=prawa%m lewa%pol%x=prawa%pol%x lewa%pol%y=prawa%pol%y lewa%pred%x=prawa%pred%x lewa%pred%y=prawa%pred%y modulroznica=modul(pom) END FUNCTION modulroznica END SUBROUTINE pods 7
Główny procedura SUBROUTINE Verlet(cz, cztm1, cztm2, sila, dt) TYPE(OpisCzastki), INTENT(OUT) :: cz TYPE(OpisCzastki), INTENT(INOUT) :: cztm1 TYPE(OpisCzastki), INTENT(IN) :: cztm2 TYPE(wspolrzedne), INTENT(IN) :: sila REAL(dp), INTENT(IN) :: dt cz%m=cztm1%m! Masa sie nie zmienia?? cz%pol%x=2.0_dp*cztm1%pol%x-cztm2%pol%x+dt*dt*sila%x/cz%m cz%pol%y=2.0_dp*cztm1%pol%y-cztm2%pol%y+dt*dt*sila%y/cz%m cz%pred%x=0.0_dp cz%pred%y=0.0_dp cztm1%pred%x=(cz%pol%x-cztm2%pol%x)/(2.0_dp*dt) cztm1%pred%y=(cz%pol%y-cztm2%pol%y)/(2.0_dp*dt) END SUBROUTINE Verlet 8
Dodatkowy modul MODULE VERLETutility IMPLICIT NONE CONTAINS SUBROUTINE zapisz(iunit, cz1, cz2, t, E, L) USE VERLETmodul INTEGER, INTENT(IN) :: iunit TYPE(OpisCZastki), INTENT(IN) :: cz1, cz2 REAL(dp), INTENT(IN) :: t, E, L write(iunit,'(11e13.5)') & t,cz1%pol%x,cz1%pol%y,cz2%pol%x,cz2%pol%y,cz1%pred%x,cz1%pred%y,cz2%pred %x,cz2%pred%y,e,l END SUBROUTINE zapisz END MODULE VERLETutility 9
Główny segment 1 PROGRAM Planets USE VERLETmodul USE VERLETutility IMPLICIT NONE REAL(dp) :: dt,te REAL(dp) :: t, E, L TYPE(OpisCzastki) :: cz1, cz2, cz1tm1, cz2tm1, cz1tm2, cz2tm2 TYPE(wspolrzedne) :: F1, F2 INTEGER :: Np, n czm%m=100.0! Parametry dla masy M czm%pol%x=0.0_dp czm%pol%y=0.0_dp czm%pred%x=0.0_dp czm%pred%y=0.0_dp 10
Główny segment 2 open(10,file='planets.inp',status='unknown') open(11,file='planets.out',status='unknown') read(10,*)cz1tm2%m,cz2tm2%m,te,np read(10,*)cz1tm2%pol%x,cz1tm2%pol%y,cz2tm2%pol%x,cz2tm2%pol%y, & cz1tm2%pred%x,cz1tm2%pred%y,cz2tm2%pred%x,cz2tm2%pred%y dt=(te-0.0)/np CALL Force(cz1Tm2, cz2tm2, F1, F2) CALL EL(cz1Tm2, cz2tm2, E, L) t=0.0_dp CALL zapisz(11, cz1tm2, cz2tm2, t, E, L) 11
Przygotowanie danych!policz dla czasu +dt cz1tm1%m=cz1tm2%m cz1tm1%pol%x=cz1tm2%pol%x+cz1tm2%pred%x*dt+0.5_dp*(f1%x/cz1tm1%m)*dt*dt cz1tm1%pol%y=cz1tm2%pol%y+cz1tm2%pred%y*dt+0.5_dp*(f1%y/cz1tm1%m)*dt*dt cz2tm1%m=cz2tm2%m cz2tm1%pol%x=cz2tm2%pol%x+cz2tm2%pred%x*dt+0.5_dp*(f2%x/cz2tm1%m)*dt*dt cz2tm1%pol%y=cz2tm2%pol%y+cz2tm2%pred%y*dt+0.5_dp*(f2%y/cz2tm1%m)*dt*dt 12
Główna część DO n=1,np-1 t=0.0+n*dt CALL Force(cz1Tm1, cz2tm1, F1, F2) CALL Verlet(cz1, cz1tm1, cz1tm2, F1, dt) CALL Verlet(cz2, cz2tm1, cz2tm2, F2, dt) CALL EL(cz1Tm1, cz2tm1, E, L) CALL zapisz(11, cz1tm1, cz2tm1, t, E, L) CALL pods(cz1tm2, cz1tm1) CALL pods(cz1tm1, cz1) CALL pods(cz2tm2, cz2tm1) CALL pods(cz2tm1, cz2) END DO 13
Dziękuję za uwagę 14