And same comment that I have already made before:
in EDO you do not assign any value to E and V. Maybe There are other issues, but you have to fix this one first.
If you don’t take into account the comments, we are going nowhere…
And same comment that I have already made before:
in EDO you do not assign any value to E and V. Maybe There are other issues, but you have to fix this one first.
If you don’t take into account the comments, we are going nowhere…
The comments about making sure to post code that actually reproduces your issue aside, I did spot an issue in the code you posted. yyout
declared in your program, and the yyout
declared in several of your other procedures are different variables. You’re declaring it as a local variable in several of the procedures instead of passing it as an argument.
Sorry, I have deleted this COMMON since it wasn’t doing anything. My EDO subroutine now looks like this
SUBROUTINE EDO(nequ, x, yin, dyout)
IMPLICIT NONE
DOUBLE PRECISION:: x, yin(nequ), dyout(nequ), E, V
INTEGER:: nequ
dyout(1)= yin(2)
dyout(2) = 2D0*(V-E)* yin(1) !Correspon a la segona derivada que ens dona l'equació de Schrodinger
END SUBROUTINE EDO
I do define V and E1, E2 at my main program.
Hi, thank you for the response. I think I know what you mean but I don’t fully understand. I only define it as a local variable in integrate because it’s necessary for the Runge Kutta method. I don’t see how I can make it an argument.
Again my issue when executing is that I added a write
in the integrate
routine and the results are always the initial ones I declare on my main program.
I post once again my current code:
PROGRAM PREPA8
IMPLICIT NONE
DOUBLE PRECISION:: V, E, dx, E1, E2, E3, error, pi, grav, longitud, a, b
INTEGER:: N, i, iter
INTEGER, PARAMETER:: nequ=2
DOUBLE PRECISION:: yyin(nequ), yyout(nequ), phi(200), phi_f(2)
EXTERNAL:: EDO, pendolSimple
COMMON/DADES/V, pi
OPEN(10, file='prepa8.dat')
!Dades ctts::
V=-2.4d0
pi=4d0*atan(1d0)
yyin(1)=0.02d0
yyin(2)=0.0d0
E1 = 1d0
E2= 1.1d0
error=10-5d0
call tir(nequ, E1, E2, error, 0d0,1d0,500, yyin)
CLOSE(10)
END PROGRAM PREPA8
!SUBRUTINE RUNGE-KUTTA D'ORDRE 4
SUBROUTINE RungeKutta4order(nequ, dx, yyin, yyout, func)
IMPLICIT NONE
INTEGER:: nequ, i
DOUBLE PRECISION, DIMENSION(nequ):: yyin, yyout, k1, k2, k3, k4, yaux
DOUBLE PRECISION:: x, dx
call func(nequ, x, yyin, k1) !k1 = f(x0, y0)
yaux=yyin+(dx*k1/2d0)
x=x+0.5d0*dx
call func(nequ, x, yaux, k2) !k2
yaux=yyin +(dx*k2/2d0)
x=x+0.5d0*dx
call func(nequ, x, yaux, k3) !k3
yaux=yyin+(dx*k3)
x=x+0.5d0*dx
call func(nequ, x+dx, yaux, k4) !k4
yyout=yyin+(dx/6d0)*(k1+k2*2d0+2d0*k3+k4)
END SUBROUTINE RungeKutta4order
!L'edos en aquest cas és equivalent a la del pèndol simple en aproximacions petites.
!yin=(phi, dphi/dx)
!dyout=(dphi/dx, d^2phi/dx^2)
SUBROUTINE EDO(nequ, x, yin, dyout)
IMPLICIT NONE
DOUBLE PRECISION:: x, yin(nequ), dyout(nequ), E, V
INTEGER:: nequ
dyout(1)= yin(2)
dyout(2) = 2D0*(V-E)* yin(1) !Correspon a la segona derivada que ens dona l'equació de Schrodinger
END SUBROUTINE EDO
SUBROUTINE integrate(nequ, E0, a, b, N, yyin, phi)
IMPLICIT NONE
DOUBLE PRECISION:: E0, phi, a, b
DOUBLE PRECISION:: dx, yyin(nequ), yyout(nequ)
INTEGER:: nequ, i, N
EXTERNAL:: EDO
dx=(b-a)/N
DO i = 1, N
call RungeKutta4order(nequ, dx, yyin, yyout, edo)
write(*,*) dx*i, yyout
yyin=yyout
ENDDO
phi=yyin(1)
END SUBROUTINE integrate
SUBROUTINE secant(E1, E2, phi1, phi2, E3)
IMPLICIT NONE
DOUBLE PRECISION:: E1, E2, phi1, phi2, E3
E3=(E1 * phi2 - E2 * phi1) / (phi2 - phi1)
END SUBROUTINE secant
SUBROUTINE tir(nequ, E1, E2, error, a,b,N, yyin)
IMPLICIT NONE
DOUBLE PRECISION:: E1, E2, E3, a, b
DOUBLE PRECISION:: phi1, phi2, phi3, dx, x, error, yyin(nequ)
INTEGER:: i, nequ, N, iter
i=0 !incialitzo
iter=500
!Pas 1 i 2
do i = 1, iter
call integrate(nequ, E1, a, b, N,yyin, phi1)
call integrate(nequ, E2, a, b, N, yyin, phi2)
print*, phi1, phi2
call secant(E1, E2, phi1, phi2, E3)
call integrate(nequ, E3, a, b, N,yyin, phi3)
if (abs(phi3).LT.error) then
write(*,*) 'Ha convergit', i, E3
exit
else
E1 = E2
E2 = E3
end if
end do
END SUBROUTINE tir
````
After a few prints i rwalized maybe EDO or Runge-Kutta aren't properly defined.
And again, the E and V variables in the EDO routine are not assigned with any value!
I see the problem now.
I tried to define E but now i’m having a memory problem.
Program received signal SIGSEGV: Segmentation fault - invalid memory reference.
Backtrace for this error:
#0 0x109523afe
#1 0x109522cdd
#2 0x7fff20939d7c
#3 0x10950d7e4
#4 0x10950d4e2
#5 0x10950d29a
#6 0x10950cf31
#7 0x10950d975
#8 0x10950d9f0
zsh: segmentation fault ./A.out
PROGRAM PREPA8
IMPLICIT NONE
DOUBLE PRECISION:: V, E, dx, E1, E2, E3, error, pi, grav, longitud, a, b, x, T, w_n
INTEGER:: N, i, iter
INTEGER, PARAMETER:: nequ=2
DOUBLE PRECISION:: yyin(nequ), yyout(nequ),
EXTERNAL:: EDO, pendolSimple
OPEN(10, file='prepa8.dat')
!Dades ctts::
V=-2.4d0
pi=4d0*atan(1d0)
yyin(1)=0.02d0
yyin(2)=0.0d0
E1= 1d0
E2= 1.1d0
error=10-5d0
E=2.0d0
dx=0.001
call edo(nequ, x, E, V, yyin, yyout)
!!print*, yyout
!do i = 1, 10
!call RungeKutta4order(nequ, dx, yyin, yyout, edo)
!print*, yyout
!yyin=yyout
!enddo
call tir(nequ, E1, E2, V, error, 0d0,1d0,500, yyin)
END PROGRAM PREPA8
!SUBRUTINE RUNGE-KUTTA D'ORDRE 4
SUBROUTINE RungeKutta4order(nequ, dx, yyin, yyout, func)
IMPLICIT NONE
INTEGER, INTENT(IN) :: nequ
DOUBLE PRECISION, DIMENSION(nequ), INTENT(IN) :: yyin
DOUBLE PRECISION, DIMENSION(nequ), INTENT(OUT) :: yyout
DOUBLE PRECISION, DIMENSION(nequ) :: k1, k2, k3, k4, yaux
DOUBLE PRECISION :: x, dx
call func(nequ, x, yyin, k1) !k1 = f(x0, y0)
yaux = yyin + (dx * k1 / 2.0d0)
x = x + 0.5d0 * dx
call func(nequ, x, yaux, k2) !k2
yaux = yyin + (dx * k2 / 2.0d0)
x = x + 0.5d0 * dx
call func(nequ, x, yaux, k3) !k3
yaux = yyin + (dx * k3)
x = x + 0.5d0 * dx
call func(nequ, x + dx, yaux, k4) !k4
yyout = yyin + (dx / 6.0d0) * (k1 + 2.0d0 * k2 + 2.0d0 * k3 + k4)
!print*, yyout
END SUBROUTINE RungeKutta4order
!L'edos en aquest cas és equivalent a la del pèndol simple en aproximacions petites.
!yin=(phi, dphi/dx)
!dyout=(dphi/dx, d^2phi/dx^2)
SUBROUTINE EDO(nequ, x, E, V, yin, dyout)
IMPLICIT NONE
DOUBLE PRECISION:: x, yin(nequ), dyout(nequ), E, V
INTEGER:: nequ
dyout(1)= yin(2)
dyout(2) = 2D0*(V-E)* yin(1) !Correspon a la segona derivada que ens dona l'equació de Schrodinger
END SUBROUTINE EDO
SUBROUTINE integrate(nequ, E, V, a, b, N, yyin, phi)
IMPLICIT NONE
DOUBLE PRECISION:: E, phi, a, b, V
DOUBLE PRECISION:: dx, yyin(nequ), yyout(nequ)
INTEGER:: nequ, i, N
EXTERNAL:: EDO
print*, yyin
dx=(b-a)/N
DO i = 1, N
call RungeKutta4order(nequ, dx, yyin, yyout, edo)
!write(*,*) dx*i, yyout
yyin=yyout
ENDDO
phi=yyin(1)
END SUBROUTINE integrate
SUBROUTINE secant(E1, E2, phi1, phi2, E3)
IMPLICIT NONE
DOUBLE PRECISION:: E1, E2, phi1, phi2, E3
E3=(E1 * phi2 - E2 * phi1) / (phi2 - phi1)
END SUBROUTINE secant
SUBROUTINE tir(nequ, E1, E2, V, error, a,b,N, yyin)
IMPLICIT NONE
DOUBLE PRECISION:: E1, E2, E3, a, b, V
DOUBLE PRECISION:: phi1, phi2, phi3, dx, x, error, yyin(nequ)
INTEGER:: i, nequ, N, iter
i=0 !incialitzo
iter=500
!Pas 1 i 2
do i = 1, iter
call integrate(nequ, E1, V, a, b, N,yyin, phi1)
call integrate(nequ, E2, V, a, b, N, yyin, phi2)
!print*, phi1, phi2
call secant(E1, E2, phi1, phi2, E3)
call integrate(nequ, E3, V, a, b, N,yyin, phi3)
if (abs(phi3).LT.error) then
write(*,*) 'Ha convergit', i, E3
exit
else
E1 = E2
E2 = E3
end if
end do
END SUBROUTINE tir
The only solution i thought was adding an E parameter at my runge-kutta subroutine, but it wasn’t specified that i had to do so, so i think there can be another way
you may perhaps assign to variables named E
, or V
in the main program, but those do not have any effect here, be because the E
and V
variables declared here are local and different variables from the ones declared in the main program.
Hi, thank you for the answer. In my previous reply I realised that was the issue but I am having trouble fixing it. I have made E and V an argument of the subroutines, but I haven’t changed the Runge-Kutta subroutine. I’m having a memory error when executing.
The Fortran standard and Fortran manuals often use words such as “define” with a specific meaning that may be unfamiliar to you. I suspect that when you say “define” you mean “declare”. In Fortran, a variable is said to be “defined” when the variable has had a value assigned to it, by assigning to it the value of an expression, or by reading a value into it using a READ statement. A variable can become “undefined” when it goes “out of scope”. A local variable in a subroutine is undefined outside that subroutine.
Please clarify what you mean, and state which compiler/OS you are using.
I believe the error exists when the subroutine Runge-Kutta calls EDO because it doesn’t recognise E and V. If I pass these variables as arguments of the subroutine Runge-Kutta I have a memory error. What can be done to fix this?
I would really appreciate some help this is very desesperating.
PROGRAM PREPA8
IMPLICIT NONE
DOUBLE PRECISION:: V, E, dx, E1, E2, E3, error, pi, grav, longitud, a, b, x, T, w_n
INTEGER:: N, i, iter
INTEGER, PARAMETER:: nequ=2
DOUBLE PRECISION:: yyin(nequ), yyout(nequ), phi(200), phi_f(2)
EXTERNAL:: EDO, pendolSimple
OPEN(10, file='prepa8.dat')
!Dades ctts::
V=-2.4d0
pi=4d0*atan(1d0)
yyin(1)=0.02d0
yyin(2)=0.0d0
E1= 1d0
E2= 1.1d0
error=10-5d0
E=1.0d0
dx=0.001
call EDO(nequ, x, yyin, yyout,E, V)
!print*, yyout
!do i = 1, 10
call RungeKutta4order(nequ, dx, yyin, yyout, edo)
!print*, yyout
!yyin=yyout
!enddo
!call tir(nequ, E1, E2, V, error, 0d0,1d0,500, yyin)
!!!PROVA USANT PÈNDOL SIMPLE
!N=1300
!w_n = sqrt(grav/longitud)
!T= 2d0*pi/w_n
!grav = 3.71d0 !m/s^2
!longitud = 0.45d0 !m
!dx=6*T/n
!yy0(1)=0.02d0
!yy0(2)=0.0d0
!DO i = 1, N
! CALL RungeKutta4order(nequ, dx, yy0, yyout, pendolSimple)
! write(*,*) dx*i, yyout
! yy0=yyout
!ENDDO
CLOSE(10)
END PROGRAM PREPA8
!SUBRUTINE RUNGE-KUTTA D'ORDRE 4
SUBROUTINE RungeKutta4order(nequ, dx, yyin, yyout, func)
IMPLICIT NONE
INTEGER, INTENT(IN) :: nequ
DOUBLE PRECISION, DIMENSION(nequ), INTENT(IN) :: yyin
DOUBLE PRECISION, DIMENSION(nequ), INTENT(OUT) :: yyout
DOUBLE PRECISION, DIMENSION(nequ) :: k1, k2, k3, k4, yaux
DOUBLE PRECISION :: x, dx, E, V
call func(nequ, x, yyin, k1) !k1 = f(x0, y0)
!print*, k1
yaux = yyin + (dx * k1 / 2.0d0)
x = x + 0.5d0 * dx
call func(nequ, x, yaux, k2) !k2
yaux = yyin + (dx * k2 / 2.0d0)
x = x + 0.5d0 * dx
call func(nequ, x, yaux, k3) !k3
yaux = yyin + (dx * k3)
x = x + 0.5d0 * dx
call func(nequ, x + dx, yaux, k4) !k4
yyout = yyin + (dx / 6.0d0) * (k1 + 2.0d0 * k2 + 2.0d0 * k3 + k4)
!print*, yyout
END SUBROUTINE RungeKutta4order
!L'edos en aquest cas és equivalent a la del pèndol simple en aproximacions petites.
!yin=(phi, dphi/dx)
!dyout=(dphi/dx, d^2phi/dx^2)
SUBROUTINE EDO(nequ, x, yin, dyout,E, V)
IMPLICIT NONE
DOUBLE PRECISION:: x, yin(nequ), dyout(nequ), E, V
INTEGER:: nequ
print*, E, V
dyout(1)= yin(2)
dyout(2) = 2D0*(V-E)* yin(1) !Correspon a la segona derivada que ens dona l'equació de Schrodinger
print*, dyout
END SUBROUTINE EDO
````
Examine your RungeKutta4order subroutine. In it, you have this line:
x = x + 0.5d0 * dx
Has x
been given a value earlier? Where? Or is x
undefined?
x is irrelevant since I don’t need it to solve the equation. I can initialize it but it doesn’t make a difference…
You should really do something to give your procedures explicit interfaces. It will catch many of the errors you’re encountering at compile time.
here you’re passing edo
(a procedure) as an argument to RungeKutta4order
. That’s all well and good, but inside RungeKutta4order
you’re calling it like
and not passing all the arguments like you did in the main program.
Thank you very much, that was very helpful. I believe I now have a well functioning Runge-Kutta method for this problem.
I thought it was correct but I wrote the values given E1 and E2 corresponding to excited levels of energy of a particle and all my results were Nan’s or infinity. Is there ans issue with tir
and integrate
?
PROGRAM PREPA8
IMPLICIT NONE
DOUBLE PRECISION:: V, E, dx, E1, E2, E3, error, pi, grav, longitud, a, b, x, T, w_n, phi
INTEGER:: N, i, iter
INTEGER, PARAMETER:: nequ=2
DOUBLE PRECISION:: yyin(nequ), yyout(nequ)
EXTERNAL:: EDO, pendolSimple
COMMON/ENERGIA/E, V
OPEN(10, file='prepa8.dat')
!Dades ctts::
V=-2.4d0
pi=4d0*atan(1d0)
yyin(1)=0.02d0
yyin(2)=0.0d0
E1= (pi**2/2d0 +V)
E2= ((2d0*pi)**2/2d0 +V)
error=10-5d0
N=500
a=0.0d0
b=1.0d0
!call EDO(nequ, x, yyin, yyout,E, V)
!print*, yyout
!do i = 1, 10
!call integrate(nequ, E, V, a, b, N, yyin, phi)
!print*, yyout
!yyin=yyout
!enddo
call tir(nequ, E1, E2, V, error, 0d0,1d0,500, yyin)
END PROGRAM PREPA8
SUBROUTINE integrate(nequ, E, V, a, b, N, yyin, phi)
IMPLICIT NONE
DOUBLE PRECISION:: E, phi, a, b, V
DOUBLE PRECISION:: dx, yyin(nequ), yyout(nequ)
INTEGER:: nequ, i, N
EXTERNAL:: EDO
dx=(b-a)/dble(N)
DO i = 1, N
!print*, i
call RungeKutta4order(nequ, dx, yyin, yyout, edo, E, V)
!write(*,*) dx*i, yyout
yyin=yyout
ENDDO
phi=yyin(1)
END SUBROUTINE integrate
SUBROUTINE secant(E1, E2, phi1, phi2, E3)
IMPLICIT NONE
DOUBLE PRECISION:: E1, E2, phi1, phi2, E3
E3=(E1 * phi2 - E2 * phi1) / (phi2 - phi1)
END SUBROUTINE secant
SUBROUTINE tir(nequ, E1, E2, V, error, a,b,N, yyin)
IMPLICIT NONE
DOUBLE PRECISION:: E1, E2, E3, a, b, V
DOUBLE PRECISION:: phi1, phi2, phi3, dx, x, error, yyin(nequ)
INTEGER:: i, nequ, N, iter
i=0 !incialitzo
iter=500
!Pas 1 i 2
do i = 1, iter
call integrate(nequ, E1, V, a, b, N,yyin, phi1)
call integrate(nequ, E2, V, a, b, N, yyin, phi2)
!print*, phi1, phi2
call secant(E1, E2, phi1, phi2, E3)
call integrate(nequ, E3, V, a, b, N,yyin, phi3)
if (abs(phi3).LT.error) then
write(*,*) 'Ha convergit', i, E3
exit
else
E1 = E2
E2 = E3
end if
end do
END SUBROUTINE tir
Again, thank you for the help, and would really appreciate the thoughts on this last error.
It looks like I’ve arrived too late to help you. But before you run off, I wanted to suggest something. Am I right to assume that you are using the GFortran compiler? When you compile, use the -Wall
flag.
$ gfortran example.f90 -o example -Wall
That flag instructs GFortran to print out all the warnings. It will warn you about things that look wrong or suspicious in your code. For example, your code has 13 unused variables.
This looks like it evaluates to 5. Perhaps you meant 1.0d-5
as 1 \times 10^{-5} instead.
Hi, thought it worked well because for energies E1=1.0 and E2= 1.1 it seemed fine. I have inputted the energies given to me for this specific program and now I have as results Nans. It seems it already fails at Runge-Kutta. Does anyone have any ideas on how I can fix and have a well functioning code?
PROGRAM PREPA8
IMPLICIT NONE
DOUBLE PRECISION:: V, E, dx, E1, E2, E3, error, pi, grav, longitud, a, b, x, T, w_n, phi
INTEGER:: N, i, iter
INTEGER, PARAMETER:: nequ=2
DOUBLE PRECISION:: yyin(nequ), yyout(nequ)
EXTERNAL:: EDO, pendolSimple
OPEN(10, file='prepa8.dat')
!Dades ctts::
V=-2.4d0
pi=4d0*atan(1d0)
yyin(1)=0.02d0
yyin(2)=0.0d0
E1= (pi**2/2d0 +V)
E2= ((2d0*pi)**2/2d0 +V)
error=1.0d-5
N=500
a=0.0d0
b=1.0d0
!call EDO(nequ, x, yyin, yyout,E, V)
!print*, yyout
!do i = 1, 10
!call integrate(nequ, E, V, a, b, N, yyin, phi)
!print*, yyout
!yyin=yyout
!enddo
call tir(nequ, E1, E2, V, error, 0d0,1d0,500, yyin)
END PROGRAM
!SUBRUTINE RUNGE-KUTTA D'ORDRE 4
SUBROUTINE RungeKutta4order(nequ, dx, yyin, yyout, func, E, V)
IMPLICIT NONE
INTEGER, INTENT(IN) :: nequ
DOUBLE PRECISION, DIMENSION(nequ), INTENT(IN) :: yyin
DOUBLE PRECISION, DIMENSION(nequ), INTENT(OUT) :: yyout
DOUBLE PRECISION, DIMENSION(nequ) :: k1, k2, k3, k4, yaux
DOUBLE PRECISION :: x, dx, E, V
call func(nequ, x, yyin, k1, E, V) !k1 = f(x0, y0)
!print*, k1
yaux = yyin + (dx * k1 / 2.0d0)
x = x + 0.5d0 * dx
call func(nequ, x, yaux, k2, E, V) !k2
yaux = yyin + (dx * k2 / 2.0d0)
x = x + 0.5d0 * dx
call func(nequ, x, yaux, k3, E, V) !k3
yaux = yyin + (dx * k3)
x = x + 0.5d0 * dx
call func(nequ, x + dx, yaux, k4, E, V) !k4
yyout = yyin + (dx / 6.0d0) * (k1 + 2.0d0 * k2 + 2.0d0 * k3 + k4)
print*, yyout
END SUBROUTINE RungeKutta4order
!L'edos en aquest cas és equivalent a la del pèndol simple en aproximacions petites.
!yin=(phi, dphi/dx)
!dyout=(dphi/dx, d^2phi/dx^2)
SUBROUTINE EDO(nequ, x, yin, dyout, E, V)
IMPLICIT NONE
DOUBLE PRECISION:: x, yin(nequ), dyout(nequ), E, V
INTEGER:: nequ
dyout(1)= yin(2)
dyout(2) = 2D0*(V-E)* yin(1) !Correspon a la segona derivada que ens dona l'equació de Schrodinger
END SUBROUTINE EDO
SUBROUTINE integrate(nequ, E, V, a, b, N, yyin, phi)
IMPLICIT NONE
DOUBLE PRECISION:: E, phi, a, b, V
DOUBLE PRECISION:: dx, yyin(nequ), yyout(nequ)
INTEGER:: nequ, i, N
EXTERNAL:: EDO
dx=(b-a)/dble(N)
DO i = 1, N
call RungeKutta4order(nequ, dx, yyin, yyout, edo, E, V)
!write(*,*) dx*i, yyout
yyin=yyout
ENDDO
phi=yyin(1)
END SUBROUTINE integrate
SUBROUTINE secant(E1, E2, phi1, phi2, E3)
IMPLICIT NONE
DOUBLE PRECISION:: E1, E2, phi1, phi2, E3
E3=(E1 * phi2 - E2 * phi1) / (phi2 - phi1)
END SUBROUTINE secant
SUBROUTINE tir(nequ, E1, E2, V, error, a,b,N, yyin)
IMPLICIT NONE
DOUBLE PRECISION:: E1, E2, E3, a, b, V
DOUBLE PRECISION:: phi1, phi2, phi3, dx, x, error, yyin(nequ)
INTEGER:: i, nequ, N, iter
i=0 !incialitzo
iter=500
!Pas 1 i 2
do i = 1, iter
call integrate(nequ, E1, V, a, b, N,yyin, phi1)
call integrate(nequ, E2, V, a, b, N, yyin, phi2)
!print*, phi1, phi2
call secant(E1, E2, phi1, phi2, E3)
call integrate(nequ, E3, V, a, b, N,yyin, phi3)
if (abs(phi3).LT.error) then
!write(*,*) 'Ha convergit', i, E3
exit
else
E1 = E2
E2 = E3
end if
end do
END SUBROUTINE tir
````
I would use 1d-5 instead of 10-5d0 because it is a standard-conforming way to get a double precision value equal to 10.0d0**(-5) and involves less typing.
That’s what I wrote, or are we talking about the decimal separator dot?