Runge-Kutta四阶FORTRAN解双摆的解

时间:2014-12-01 18:38:24

标签: fortran numerical-methods runge-kutta

我正试图通过Runge-Kutta四阶数字来解决双摆的问题。

要求解的微分方程式如下:

http://www.myphysicslab.com/dbl_pendulum.html

甚至还有一个显示角度1和2的动画。我想用Runge-Kutta方法解决页面下方出现的方程式。

将这些结果打印到文件中,然后使用gnuplot绘制它们。但是,我的程序没有运行,也找不到原因,希望你能帮助我。

我在Fortran的代码:

PROGRAM MAIN

!In this program the double pendulum is solved by Rugen-Kutta method of order 4

!variables required
INTEGER, PARAMETER:: PREC = SELECTED_REAL_KIND(9,99)
REAL(PREC), DIMENSION(:), ALLOCATABLE :: theta1, theta2, omega1, omega2, t
REAL(PREC) :: LEN1, LEN2, M1, M2, G, PI, DT
!The following variables are for the Runge-Kutta
REAL(PREC) :: K11, K12, K13, K14, K21, K22, K23, K24
REAL(PREC) :: K31, K32, K33, K34, K41, K42, K43, K44
INTEGER :: I, J, N

!Definition of variables needed
PI= 4.*ATAN(1.)
I=0
G=9.8
DT=0.0003 !change over time
T(0)= 0.0 !initial time

!number of repetitions
n=500000
ALLOCATE (theta1(0:n),omega1(0:n),theta2(0:n),omega2(0:n),t(0:n))

!Initials values are given by the user
PRINT*, 'First pendulum'
CALL INICIALIZA(THETA1, OMEGA1, N, LEN1, M1)
PRINT*, ' '
PRINT*, 'Second pendulum'
CALL INICIALIZA(THETA2, OMEGA2, N, LEN2, M2)

!Runge-kutta method
DO

!Runge-Kutta fourth order
    !
    K11 = DT*OMEGA1(I)
    K21 = DT*OMEGA2(I)
    K31 = DT*DOM1(M1, M2, THETA1(I), THETA2(I) & 
    , OMEGA1(I), OMEGA2(I), LEN1, LEN2, G)
    K41 = DT*DOM2(M1, M2, THETA1(I), THETA2(I) & 
    , OMEGA1(I), OMEGA2(I), LEN1, LEN2, G)
    !
    K12 = DT*(OMEGA1(I) + K11/2.0)
    K22 = DT*(OMEGA2(I) + K21/2.0)
    K32 = DT*DOM1(M1, M2, (THETA1(I) + K11/2.0), (THETA2(I) + K21/2.0) & 
    , (OMEGA1(I) + K31/2.0), (OMEGA2(I) + K41/2.0), LEN1, LEN2, G)
    K42 = DT*DOM2(M1, M2, (THETA1(I) + K11/2.0), (THETA2(I) + K21/2.0) & 
    , (OMEGA1(I) + K31/2.0), (OMEGA2(I) + K41/2.0), LEN1, LEN2, G)
    !
    K13 = DT*(OMEGA1(I) + K12/2.0)
    K23 = DT*(OMEGA1(I) + K22/2.0)
    K33 = DT*DOM1(M1, M2, (THETA1(I) + K12/2.0), (THETA2(I) + K22/2.0) & 
    , (OMEGA1(I) + K32/2.0), (OMEGA2(I) + K42/2.0), LEN1, LEN2, G)
    K43 = DT*DOM2(M1, M2, (THETA1(I) + K12/2.0), (THETA2(I) + K22/2.0) & 
    , (OMEGA1(I) + K32/2.0), (OMEGA2(I) + K42/2.0), LEN1, LEN2, G)
    !
    K14 = DT*(OMEGA1(I) + K13)
    K24 = DT*(OMEGA1(I) + K23)
    K34 = DT*DOM1(M1, M2, (THETA1(I) + K13), (THETA2(I) + K23) & 
    , (OMEGA1(I) + K33), (OMEGA2(I) + K43), LEN1, LEN2, G)
    K44 = DT*DOM2(M1, M2, (THETA1(I) + K13), (THETA2(I) + K23) & 
    , (OMEGA1(I) + K33), (OMEGA2(I) + K43), LEN1, LEN2, G)
    !
    THETA1(I+1) = THETA1(I)+((K11+(2.0*(K12+K13))+K14)/6.0)
    THETA2(I+1) = THETA2(I)+((K21+(2.0*(K22+K23))+K24)/6.0)
    OMEGA1(I+1) = OMEGA1(I)+((K31+(2.0*(K32+K33))+K34)/6.0)
    OMEGA2(I+1) = OMEGA2(I)+((K41+(2.0*(K42+K43))+K44)/6.0)
    !
    if (theta1(i+1) > PI ) theta1(i+1)=theta1(i+1)-2.*PI
    if (theta1(i+1) < -PI) theta1(i+1)=theta1(i+1)+2.*PI
    if (theta2(i+1) > PI ) theta2(i+1)=theta2(i+1)-2.*PI
    if (theta2(i+1) < -PI) theta2(i+1)=theta2(i+1)+2.*PI    

    t(i+1) = t(i) + dt

    IF (i >= n-1) EXIT

    i=i+1

ENDDO
!The results are saved in a file
OPEN (UNIT=10,FILE='dou2.dat',STATUS='UNKNOWN')

do j=0,n
    wRITE(10,*) theta1(j),theta2(j),omega1(j),omega2(j),t(j)
end do

CLOSE(10)

END PROGRAM MAIN

!Subroutine to initial values
SUBROUTINE inicializa(theta, omega, n ,length, m)
INTEGER, PARAMETER:: PREC = SELECTED_REAL_KIND(9,99)
INTEGER, INTENT (IN):: n
REAL(PREC), DIMENSION(0:n):: theta, omega
REAL(PREC):: length, m
print*,'starting angle'
read*, theta(0)
print*,'Initial angular velocity'
read*, omega(0)
print*,'Lenght of pendulum'
read*, length
print*, 'Mass pendulum'
read*, m
END SUBROUTINE inicializa

!Functions that determine the derivative of omega (the angular velocity)

REAL FUNCTION DOM1(N1, N2, X1, X2, Y1, Y2, L1, L2, A)
    INTEGER, PARAMETER:: PREC = SELECTED_REAL_KIND(9,99)
    REAL(PREC) :: N1, N2, X1, X2, Y1, Y2, L1, L2, A
    DOM1 = ((-A*((2.0*N1)+N2)*SIN(X1))-(N2*A*SIN(X1-(2.0*X2))) & 
    -(2.0*SIN(X1-X2)*N2*((Y2*Y2*L2)+(Y1*Y1*L1*COS(X1-X2))))) &
    /(L1*((2.0*N1)+N2-(N2*COS((2.0*X1)-(2.0*X2)))))
END FUNCTION DOM1

REAL FUNCTION DOM2(N1, N2, X1, X2, Y1, Y2, L1, L2, A)
    INTEGER, PARAMETER:: PREC = SELECTED_REAL_KIND(9,99)
    REAL(PREC) :: N1, N2, X1, X2, Y1, Y2, L1, L2, A
    DOM2 = (2.0*SIN(X1-X2)*((Y1*Y1*L1*(N1+N2))+(A*(N1+N2)*COS(X1)) &
    +(Y2*Y2*L2*N2*COS(X1-X2))))/(L2*((2.0*N1)+N2 &
    -N2*COS((2.0*X1)-(2.0*X2))))
END FUNCTION DOM2

以下是该方法的一个很好的描述:http://mathworld.wolfram.com/Runge-KuttaMethod.html

运行程序时出现的错误是:

Program received signal SIGSEGV: Segmentation fault - invalid memory reference.
Backtrace for this error:
   #0  0xB763D163
   #1  0xB763D800
   #2  0xB774A3FF
   #3  0x8048F17 in MAIN__ at doupend2.f90:?
 Violación de segmento

0 个答案:

没有答案