# Fortran subroutine solving for the velocity and displacement of a spring

• Fortran

## Main Question or Discussion Point

I have a simple Fortran code for solving velocity and displacement of spring, the code works fine when writing all together without using a subroutine. but as I am learning Fortran I tried to do it using subroutine, but I keep getting errors

Fortran:
program msd
implicit none
real, parameter :: tstop=100.
integer i
real, dimension(2000) :: t,y,v

open (2, file = "test.txt")

!v(1)=0.0
!y(1)=1.0
!t(1)=0.0

do i=1,1000

call deriv(v,y,t)

write (2,*) v(i),y(i),t(i)

end do

close(2)
end program msd

!******************************************************

subroutine deriv(v,y,t)
implicit none
real, parameter :: m=1.,b=0.2,k=1., dt=0.1
real, dimension(2000) :: t,y,v
integer i

v(1)=0.0
y(1)=1.0
t(1)=0.0

v(i+1) = v(i) +(-(b/m)*v(i)-(k/m)*y(i))*dt
y(i+1) = y(i) + v(i)*dt
t(i+1) = t(i)+dt

v(i)=v(i+1)
y(i)=y(i+1)
t(i)=t(i+1)

end subroutine deriv

Last edited by a moderator:

Related Programming and Computer Science News on Phys.org
jtbell
Mentor
but I keep getting errors
What are the error messages, exactly? Do they refer to specific lines of code?

I see an issue which may or may not be related to your error messages.

In the main program, the first pass of your do-loop sets its variable i to 1. Then it calls the subroutine.

The subroutine also has a variable named i, but this is separate and independent of the variable i in the main program. You did not make i an argument of the subroutine, nor did you put it in a 'common' block that is shared by the main program and subroutine.

When you first use i in the subroutine, v(i+1) = ... you have not yet set it to a specific value, therefore it contains a "garbage" value which is effectively random. Therefore v(i) and v(i+i) do not refer to the memory locations that you probably want them to refer to.

Last edited:
FactChecker
Gold Member
Does your subroutine have the same value of i as your main program?
You may want to pass that as a parameter also.

Thank you very much jtbell and FactChecker, the issue was not passing i. I really appreciate your help.

FactChecker
Gold Member
the issue was not passing i.
I don't see how it could work the way you have it, but I will not argue with success.

Dear FactChecker the following is the corrected version that works with your helps :), Thanks

Fortran:
======================================================================
program msd
implicit none
real, parameter :: tstop=100.
integer i
real, dimension(2000) :: t,y,v

open (2, file = "test.txt")

do i=1,1000

call deriv(v,y,t,i)

write (2,*) t(i),y(i),v(i)

end do

close(2)
end program msd

!******************************************************
subroutine deriv(v,y,t,i)
implicit none
real, parameter :: m=1.,b=0.2,k=1., dt=0.1
real, dimension(2000) :: t,y,v
integer i

v(1)=0.0
y(1)=1.0
t(1)=0.0

v(i+1) = v(i) +(-(b/m)*v(i)-(k/m)*y(i))*dt
y(i+1) = y(i) + v(i)*dt
t(i+1) = t(i)+dt

v(i)=v(i+1)
y(i)=y(i+1)
t(i)=t(i+1)

end subroutine deriv

Last edited by a moderator:
FactChecker
Mark44
Mentor
the code works fine when writing all together without using a subroutine. but as I am learning Fortran I tried to do it using subroutine
Since you now have both programming styles working, it might be interesting to compare running times for each. I suspect that the code that uses a subroutine to calculate the derivative will be quite a bit slower than when you do the calculation inline, as in your first attempt. The loop in the main program runs 1000 times, and each iteration incurs the overhead of a subroutine call, something that doesn't happen when the derivative calculation is inline in the main program.

As you're new to programming, optimization is less important than just getting something to run. Also, because modern computers have processors that run in the GHz range, there probably won't be much perceptible difference between the two techniques, but it's something to keep in mind for future programs that spend a lot of time on calculations.

FactChecker