Reputation: 1
PROGRAM MPI
IMPLICIT NONE
INTEGER, PARAMETER :: nn=100
DOUBLE PRECISION h, L
DOUBLE PRECISION, DIMENSION (2*nn) :: y, ynew
DOUBLE PRECISION, DIMENSION (nn) :: qnew,vnew
DOUBLE PRECISION, DIMENSION (2*nn) :: k1,k2,k3,k4
INTEGER j, k
INTEGER i
INTEGER n
n=100 !particles
L=2.0d0
h=1.0d0/n
y(1)=1.0d0
DO k=1,2*n ! time loop
CALL RHS(y,k1)
CALL RHS(y+(h/2.0d0)*k1,k2)
CALL RHS(y+(h/2.0d0)*k2,k3)
CALL RHS(y+h*k3,k4)
ynew(1:2*n)=y(1:2*n) + (k1 + 2.0d0*(k2 + k3) + k4)*h/6.0d0
END DO
qnew(1:n)=ynew(1:n)
vnew(1:n)=ynew(n+1:2*n)
DO i=1,n
IF (qnew(i).GT. L) THEN
qnew(i) = qnew(i) - L
ENDIF
END DO
write(*,*) 'qnew=', qnew(1:n)
write(*,*) 'vnew=', vnew(1:n)
END PROGRAM MPI
!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
! Right hand side of the ODE
!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
SUBROUTINE RHS(y,z)
IMPLICIT NONE
INTEGER, PARAMETER :: nn=100
DOUBLE PRECISION, DIMENSION (2*nn) :: y
DOUBLE PRECISION, DIMENSION (2*nn) :: z
DOUBLE PRECISION, DIMENSION (nn) :: F
DOUBLE PRECISION, DIMENSION (nn) :: g
INTEGER n
INTEGER m
n=100
m=1/n
z(1:n)=y(n+1:2*n)
CAll FORCE(g,F)
z(n+1:2*n)=F(1:n)/m
RETURN
END
!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
! Force acting on each particle
!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
SUBROUTINE FORCE(g,F)
IMPLICIT NONE
INTEGER, PARAMETER :: nn=100
DOUBLE PRECISION, DIMENSION (nn) :: F
DOUBLE PRECISION, DIMENSION (nn) :: q
DOUBLE PRECISION, DIMENSION (nn) :: g
DOUBLE PRECISION u
INTEGER j, e
INTEGER n
n=100
e=1/n
DO j=2,n+1
CALL deriv((abs(q(j)-q(j-1)))/e,u)
g(j-1)=((y(j)-y(j-1))/(abs(y(j)-y(j-1))))*u
CALL deriv((abs(q(j)-q(j+1)))/e,u)
g(j+1)=((y(j)-y(j+1))/(abs(y(j)-y(j+1))))*u
F(j)=g(j-1)+g(j+1)
END DO
RETURN
END
SUBROUTINE deriv(c,u,n)
IMPLICIT NONE
INTEGER, INTENT(in) :: n
DOUBLE PRECISION, DIMENSION(n), INTENT(IN) :: c
DOUBLE PRECISION, DIMENSION(n), INTENT(OUT) :: u
INTEGER, PARAMETER :: p=2
INTEGER, PARAMETER :: cr=100
INTEGER :: i
DOUBLE PRECISION L
L=2.0d0
DO i= 1,n
IF (c(i) .LE. L) THEN
u(i)=cr*(L*(c(i)**(-p))-L**(1-p))
ELSE IF (c(i) .GT. L) THEN
u(i)=0
END IF
END DO
RETURN
END SUBROUTINE deriv
I am only getting one same error on line 85 and 87. It says:
y has no implicit type at y(j-1) ans at y(j+1).
Upvotes: 0
Views: 1306
Reputation: 50947
There's a lot wrong here. We can point out some of the things, but you're going to have to sit down with a book and learn about programming, starting with smaller programs and getting them right, then building up.
Let's look at the last routine in the code you posted above. I've changed the syntax of some of the variable declarations just to make it shorter so more fits on screen at once.
SUBROUTINE deriv(c,u)
IMPLICIT NONE
DOUBLE PRECISION :: deriv, c, u
INTEGER :: p, x, cr, n
L=2.0d0
cr=100
p=2
n=100
DO i= 1,n
IF (c(i).LE. L) THEN
u(c)=cr*(L*c^(-p)-L^(1-p))
ELSE IF (c(i) .GT. L) THEN
u(c)=0
END IF
RETURN
END
So you've made deriv a double precision variable, but it's also the name of the subroutine. That's an error; maybe you meant to make this a function which returns a double precision value; then you're almost there, you'd need to change the procedure header to FUNCTION DERIV(c,u)
-- but you never set deriv anywhere. So likely that should just be left out. So let's just get rid of that DOUBLE PRECISION deriv
declaration. Also, L, which is used, is never declared, and x, which isn't, is declared.
Then you pass in to this subroutine two variables, c and u, which you define to be double precision. So far so good, but then you start indexing them: eg, c(i)
. So they should be arrays of double precisions, not just scalars. Looking at the do loop, I'm guessing they should both be of size n
-- which should be passed in, presumably? . Also, the do loop is never terminated; there should be an end do
after the end if
.
Further, the ^
operator you're using I'm assuming you're using for exponentiation -- but in Fortran, that's **
, not ^
. And that c^(-p)
should (I'm guessing here) be c(i)**(-p)
?
Finally, you're setting u(c)
-- but that's not very sensible, as c is an array of double precision numbers. Even u(c(i)) wouldn't make sense -- you can't index an array with a double precision number. Presumably, and I'm just guessing here, you mean the value of u
corresponding to the just-calculated value of c
-- eg, u(i)
, not u(c)
?
So given the above, we'd expect the deriv subroutine to look like this:
SUBROUTINE deriv(c,u,n)
IMPLICIT NONE
INTEGER, INTENT(in) :: n
DOUBLE PRECISION, DIMENSION(n), intent(IN) :: c
DOUBLE PRECISION, DIMENSION(n), intent(OUT) :: u
INTEGER, PARAMETER :: p=2, cr=100
DOUBLE PRECISION, PARAMETER :: L=2.0
INTEGER :: i
DO i= 1,n
IF (c(i) .LE. L) THEN
u(i)=cr*(L*c(i)**(-p)-L**(1-p))
ELSE IF (c(i) .GT. L) THEN
u(i)=0
END IF
END DO
RETURN
END SUBROUTINE deriv
Note that in modern fortran, the do loop can be replaced with a where statement, and also you don't need to explicitly pass in the size; so then you could get away with the clearer and shorter:
SUBROUTINE DERIV(c,u)
IMPLICIT NONE
DOUBLE PRECISION, DIMENSION(:), intent(IN) :: c
DOUBLE PRECISION, DIMENSION(size(c,1)), intent(OUT) :: u
INTEGER, PARAMETER :: p=2, cr=100
DOUBLE PRECISION, PARAMETER :: L=2.0
WHERE (c <= L)
u=cr*(L*c**(-p)-L**(1-p))
ELSEWHERE
u=0
ENDWHERE
RETURN
END SUBROUTINE DERIV
But notice that I've already had to guess three times what you meant in this section of code, and this is only about 1/4th of the total of the code. Having us try to divine your intention in the whole thing and rewrite accordingly probably isn't the best use of anyone's time; why don't you proceed from here working on one particular thing and ask another question if you have a specific problem.
Upvotes: 5