计算Fortran 90中两个向量的叉积 [英] Computing the cross product of two vectors in Fortran 90
问题描述
程序交叉测试
隐式无
INTEGER,DIMENSION(3):: m,n
INTEGER,DIMENSION(3):: cross
INTEGER,DIMENSION(3):: r
m = (/ 1,2,3 /)
n =(/ 4,5,6)
r =交叉(m,n)
结束程序交叉测试
函数cross(a,b)
INTEGER,DIMENSION(3):: cross
INTEGER,DIMENSION(3),INTENT(IN):: a,b
$ b $ (1)= a(2)* b(3)-a(3)* b(2)
cross(2)= a(3)* b (3)
cross(3)= a(1)* b(2) - a(2)* b(1)
结束功能cross
但是,我收到错误消息:
交叉测试(1)(2/1)
$错误: / code>
其中第10行是 r = cross(m,n)
。看来我必须错误地指定尺寸。以下是我的一些想法:
-
函数
cross $ c主程序中的$ c>应该只是一个整型变量,而不是一个1by3整型数组。所以我试着在
INTEGER,DIMENSION(3):: cross
行中删除,DIMENSION(3)
主程序。但我收到一条错误消息:
crosstest.f90:10.4:
r = cross(m, n)
1
错误:在(1)中对函数'cross'的引用要么需要
显式的INTERFACE,要么等级不正确
所以这可能更糟糕。
- 有些(但不是全部)Fortran在Web上的函数示例在主程序的函数声明后放置
EXTERNAL
语句。所以我试着在主程序的声明块后放置一行EXTERNAL cross
。我收到一条错误消息:
crosstest.f90:8.16:
EXTERNAL cross
1
错误:EXTERNAL属性在(1)处与DIMENSION属性冲突
在网上的一些(但不是全部)Fortran函数示例上放置了一个
RETURN
语句函数定义的倒数第二行。我试过这个,但是我得到了原来的排名不匹配错误: crosstest.f90:10.9:
$ b $ (1)(2/1)
所以这并不能解决问题。
帮我看看我的错误?
最好的做法是将你的程序(子程序和函数)放入一个模块中,然后从你的使用主程序或其他程序。您无需从同一模块的其他程序中使用该模块。这将使过程的接口显式化,以便调用程序或过程知道参数的特性......它允许编译器检查两边参数之间的一致性......调用者和被调用者... this消除了很多错误。
在语言标准之外,但在实践中是必要的:如果您使用一个文件,请将模块放在使用它的主程序之前。否则编译器将不知道它。所以:
module my_subs
隐式无
包含
函数cross(a,b)
INTEGER,DIMENSION(3):: cross
INTEGER,DIMENSION(3),INTENT(IN):: a,b
$ (1)= a(2)* b(3)-a(3)* b(2)
cross(2)= a(3)* b(1) * b(3)
交叉(3)= a(1)* b(2) - a(2)* b(1)
结束功能cross
end module my_subs
程序交叉测试
使用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交叉测试
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:
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 theINTEGER, 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.
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 lineEXTERNAL 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.
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?
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
这篇关于计算Fortran 90中两个向量的叉积的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!