Computando o produto cruzado de dois vetores em Fortran 90

Eu gostaria de calcular o produto cruzado de dois vetores em Fortran 90. Por exemplo, em palavras, o produto vetorial de (1, 2, 3) e (4, 5, 6) é (-3, 6, -3) em coordenadas cartesianas. Eu escrevi o seguinte código (programa principal seguido por definição de function):

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 

Mas recebo uma mensagem de erro:

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

onde a linha 10 é r=cross(m,n) . Parece que devo estar especificando uma dimensão incorretamente. Aqui estão algumas idéias que tenho:

  1. Talvez a declaração da function cross no programa principal deva ser simplesmente uma variável inteira, em vez de uma matriz inteira 1by3. Então eu tentei deletar o , DIMENSION(3) na linha INTEGER, DIMENSION(3) :: cross no programa principal. Mas recebo uma mensagem de erro:

     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 

    então isso é ainda pior, provavelmente.

  2. Alguns (mas não todos) exemplos de function Fortran na web colocam uma instrução EXTERNAL após a declaração da function no programa principal. Então tentei colocar uma linha EXTERNAL cross após o bloco de declaração no programa principal. Eu recebo uma mensagem de erro:

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

    Então isso parece incorreto também.

  3. Alguns (mas não todos) exemplos de function Fortran na web colocam uma instrução RETURN na segunda à última linha da definição da function. Eu tentei isso, mas recebi o erro de incompatibilidade de sorting original:

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

    Então isso não resolve o problema.

Você pode por favor me ajudar a ver o meu erro?

A melhor prática é colocar seus procedimentos (sub-rotinas e funções) em um módulo e depois “usar” esse módulo a partir do seu programa principal ou de outros procedimentos. Você não precisa “usar” o módulo de outros procedimentos do mesmo módulo. Isso tornará a interface do procedimento explícita para que o programa ou procedimento de chamada “conheça” as características dos argumentos … permite que o compilador verifique a consistência entre os argumentos dos dois lados … chamador e receptor. elimina muitos bugs.

Fora do padrão de idioma, mas na prática é necessário: se você usar um arquivo, coloque o módulo antes do programa principal que o utiliza. Caso contrário, o compilador não terá conhecimento disso. assim:

 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 

Esta é uma espécie de resposta tardia, mas desde que me deparei com isso e não há nenhuma explicação real ainda por que seu erro ocorreu, eu imaginei adicionar uma explicação para todos os outros que se depara com essa questão:

Em seu programa, você define um array chamado cross , que é de rank 1. Então você chama a function cross você define mais abaixo. Como a function cross não possui uma interface explícita (veja a resposta do MSB), o compilador não sabe sobre isso neste momento. O que ele sabe é o array que você declarou. Se você escrever r = cross(m, n) , o compilador pensa que você deseja acessar o elemento na posição (m, n) da matriz cross . Como esta matriz é de rank 1, mas você forneceu dois argumentos, você obtém o erro

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

o que significa que você forneceu duas coordenadas quando o compilador estava esperando uma.