Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

I would like to compute the cross product of two vectors in Fortran 90. For example, in words, the cross product of (1, 2, 3) and (4, 5, 6) turns out to be (-3, 6, -3) in Cartesian coordinates. I wrote the following code (main program followed by function definition):

PROGRAM crosstest
  IMPLICIT NONE

  INTEGER, DIMENSION(3) :: m, n
  INTEGER, DIMENSION(3) :: cross
  INTEGER, DIMENSION(3) :: r

  m=(/1, 2, 3/)
  n=(/4, 5, 6/)
  r=cross(m,n)

END PROGRAM crosstest

FUNCTION cross(a, b)
  INTEGER, DIMENSION(3) :: cross
  INTEGER, DIMENSION(3), INTENT(IN) :: a, b

  cross(1) = a(2) * b(3) - a(3) * b(2)
  cross(2) = a(3) * b(1) - a(1) * b(3)
  cross(3) = a(1) * b(2) - a(2) * b(1)
END FUNCTION cross

But, I get an error message:

crosstest.f90:10.9:

  r=cross(m,n)
         1
Error: Rank mismatch in array reference at (1) (2/1)

where line 10 is r=cross(m,n). It seems that I must be specifying a dimension incorrectly. Here are a few ideas I have:

  1. Perhaps the declaration of the function cross in the main program should be simply an integer variable, rather than a 1by3 integer array. So I tried deleting the , DIMENSION(3) in the INTEGER, DIMENSION(3) :: cross line in the main program. But I get an error message:

    crosstest.f90:10.4:
    
      r=cross(m,n)
        1
    Error: The reference to function 'cross' at (1) either needs an
    explicit INTERFACE or the rank is incorrect
    

    so this is even worse, probably.

  2. Some (but not all) Fortran function examples on the web place an EXTERNAL statement after the function declaration in the main program. So I tried placing a line EXTERNAL cross after the declaration block in the main program. I get an error message:

    crosstest.f90:8.16:
    
      EXTERNAL cross
                    1
    Error: EXTERNAL attribute conflicts with DIMENSION attribute at (1)
    

    So this seems incorrect also.

  3. Some (but not all) Fortran function examples on the web place a RETURN statement on the second-to-last line of the function definition. I tried this, but I get the original rank mismatch error:

    crosstest.f90:10.9:
    
      r=cross(m,n)
             1
    Error: Rank mismatch in array reference at (1) (2/1)
    

    So this does not fix the problem.

Can you please help me see my error?

Question&Answers:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
907 views
Welcome To Ask or Share your Answers For Others

1 Answer

The best practice is to place your procedures (subroutines and functions) in a module and then "use" that module from your main program or other procedures. You don't need to "use" the module from other procedures of the same module. This will make the interface of the procedure explicit so that the calling program or procedure "knows" the characteristics of the arguments ... it allows the compiler to check for consistency between the arguments on both sides ... caller and callee .. this eliminates a lot of bugs.

Outside of the language standard, but in practice necessary: if you use one file, place the module before the main program that uses it. Otherwise the compiler will be unaware of it. so:

module my_subs

implicit none

contains

FUNCTION cross(a, b)
  INTEGER, DIMENSION(3) :: cross
  INTEGER, DIMENSION(3), INTENT(IN) :: a, b

  cross(1) = a(2) * b(3) - a(3) * b(2)
  cross(2) = a(3) * b(1) - a(1) * b(3)
  cross(3) = a(1) * b(2) - a(2) * b(1)
END FUNCTION cross

end module my_subs


PROGRAM crosstest
  use my_subs
  IMPLICIT NONE

  INTEGER, DIMENSION(3) :: m, n
  INTEGER, DIMENSION(3) :: r

  m= [ 1, 2, 3 ]
  n= [ 4, 5, 6 ]
  r=cross(m,n)
  write (*, *) r

END PROGRAM crosstest

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...