计算Fortran 90中两个向量的叉积

时间:2011-06-28 18:58:41

标签: function fortran cross-product

我想计算Fortran 90中两个向量的叉积。例如,在单词中,(1,2,3)和(4,5,6)的叉积结果为(-3) ,笛卡尔坐标系中的,6,-3)。我编写了以下代码(主程序后跟函数定义):

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

但是,我收到一条错误消息:

crosstest.f90:10.9:

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

第10行是r=cross(m,n)。似乎我必须错误地指定维度。以下是我的一些想法:

  1. 也许主程序中函数cross的声明应该只是一个整数变量,而不是1by3整数数组。所以我尝试删除主程序中, DIMENSION(3)行中的INTEGER, DIMENSION(3) :: cross。但是我收到一条错误消息:

    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
    

    所以这可能更糟糕。

  2. Web上的一些(但不是全部)Fortran函数示例在主程序中的函数声明之后放置EXTERNAL语句。所以我尝试在主程序中的声明块之后放置一行EXTERNAL cross。我收到一条错误消息:

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

    所以这看起来也不正确。

  3. Web上的一些(但不是全部)Fortran函数示例在函数定义的倒数第二行放置RETURN语句。我试过这个,但是我得到了原来的排名不匹配错误:

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

    所以这不能解决问题。

  4. 你可以帮我看看我的错误吗?

3 个答案:

答案 0 :(得分:20)

最佳做法是将程序(子程序和函数)放在模块中,然后从主程序或其他程序中“使用”该模块。您不需要从同一模块的其他过程“使用”该模块。这将使过程的接口显式化,以便调用程序或过程“知道”参数的特征...它允许编译器检查双方参数之间的一致性...调用者和被调用者...这消除了很多错误。

在语言标准之外,但在实践中是必要的:如果您使用一个文件,请将模块放在使用它的主程序之前。否则编译器将不知道它。这样:

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

答案 1 :(得分:6)

这是一个迟到的答案,但由于我偶然发现了这个问题并且没有真正解释为什么你的错误发生了,我想我会为偶然发现这个问题的其他人添加一个解释:< / p>

在你的程序中,你定义了一个名为cross的数组,它的等级为1.然后你调用你进一步定义的cross函数。由于cross函数没有显式接口(参见M.S.B。的回答),编译器此时并不知道它。它所知道的是你声明的数组。如果编写r = cross(m, n),编译器会认为您要访问数组cross的位置(m,n)处的元素。由于此数组的等级为1,但您提供了两个参数,因此会出现错误

rank mismatch in array reference at (1) (2/1)

这意味着当编译器期望一个时,你提供了两个坐标。

答案 2 :(得分:1)

您可以将程序中使用的子例程放在程序中的 contains 关键字之后。这消除了创建模块或添加接口定义的需要。

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)

  print *, r

CONTAINS

PURE 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 PROGRAM crosstest