Calculando el producto cruzado de dos vectores en Fortran 90

Me gustaría calcular el producto cruzado de dos vectores en Fortran 90. Por ejemplo, en palabras, el producto cruzado de (1, 2, 3) y (4, 5, 6) resulta ser (-3, 6, -3) en coordenadas cartesianas. Escribí el siguiente código (progtwig principal seguido de la definición de la función):

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 

Pero recibo un mensaje de error:

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

donde la línea 10 es r=cross(m,n) . Parece que debo especificar una dimensión incorrectamente. Aquí hay algunas ideas que tengo:

  1. Quizás la statement de la función cross en el progtwig principal debería ser simplemente una variable entera, en lugar de una matriz de enteros 1by3. Así que traté de borrar la , DIMENSION(3) en la línea INTEGER, DIMENSION(3) :: cross en el progtwig principal. Pero recibo un mensaje de error:

     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 

    así que esto es aún peor, probablemente.

  2. Algunos (pero no todos) los ejemplos de la función Fortran en la web colocan una instrucción EXTERNAL después de la statement de la función en el progtwig principal. Así que traté de colocar una línea EXTERNAL cross después del bloque de statement en el progtwig principal. Aparece un mensaje de error:

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

    Entonces esto parece incorrecto también

  3. Algunos (pero no todos) los ejemplos de la función Fortran en la web colocan una statement RETURN en la penúltima línea de la definición de la función. Intenté esto, pero obtengo el error de desajuste de rango original:

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

    Entonces esto no soluciona el problema.

¿Puedes ayudarme a ver mi error?

La mejor práctica es colocar sus procedimientos (subrutinas y funciones) en un módulo y luego “usar” ese módulo desde su progtwig principal u otros procedimientos. No necesita “usar” el módulo de otros procedimientos del mismo módulo. Esto hará que la interfaz del procedimiento sea explícita para que el progtwig o procedimiento de llamada “conozca” las características de los argumentos … permite al comstackdor verificar la coherencia entre los argumentos de ambos lados … llamador y destinatario … esto elimina muchos errores.

Fuera del estándar de idioma, pero en la práctica es necesario: si usa un archivo, coloque el módulo antes del progtwig principal que lo usa. De lo contrario, el comstackdor no lo tendrá en cuenta. asi que:

 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 es una especie de respuesta tardía, pero como me encontré con esto y todavía no hay una explicación real de por qué ocurrió su error, pensé que agregaría una explicación para todos los que tropiecen con esta pregunta:

En su progtwig, usted define una matriz llamada cross , que es de rango 1. Luego llama a la función cross que define más abajo. Como la función cross no tiene una interfaz explícita (ver la respuesta de MSB), el comstackdor no sabe nada al respecto. Lo que sí sabe es la matriz que declaraste. Si escribe r = cross(m, n) , el comstackdor cree que quiere acceder al elemento en la posición (m, n) de la matriz de cross . Como este conjunto es de rango 1, pero proporcionó dos argumentos, obtiene el error

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

lo que significa que proporcionó dos coordenadas cuando el comstackdor esperaba una.

Intereting Posts