2011-06-28 12 views
5

Chciałbym obliczyć krzyż iloczyn dwóch wektorów w Fortran 90. Na przykład słowami, iloczyn krzyżowy (1, 2, 3) i (4, 5 , 6) okazuje się być (-3, 6, -3) we współrzędnych kartezjańskich. Napisałem następujący kod (program główny następnie definicji funkcji):Obliczanie iloczynu krzyżowego dwóch wektorów w Fortranie 90

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 

Ale otrzymuję komunikat o błędzie:

crosstest.f90:10.9: 

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

gdzie linia 10 jest r=cross(m,n). Wydaje się, że muszę niepoprawnie określić wymiar. Oto kilka pomysłów mam:

  1. Być deklaracja funkcji cross w programie głównym powinien być po prostu zmienną całkowitą, a nie tablica 1by3 całkowitą. Tak więc próbowałem usunąć , DIMENSION(3) w linii INTEGER, DIMENSION(3) :: cross w programie głównym. Ale pojawia się komunikat o błędzie:

    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 
    

    to prawdopodobnie jeszcze gorsze.

  2. Niektóre (ale nie wszystkie) przykłady funkcji Fortran na stronie internetowej oświadczenie EXTERNAL po deklaracji funkcji w programie głównym. Próbowałem więc umieścić wiersz EXTERNAL cross po bloku deklaracji w programie głównym. Pojawia się komunikat o błędzie:

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

    To również wydaje się nieprawidłowe.

  3. Niektóre (ale nie wszystkie) przykłady funkcji fortuna na stronie internetowej oświadczenie RETURN od drugiej do ostatniej linii definicji funkcji. Próbowałem tego, ale dostaję oryginalny błąd niedopasowania rang:

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

    To nie rozwiązuje problemu.

Czy możesz mi pomóc zobaczyć mój błąd?

Odpowiedz

19

Najlepszą praktyką jest umieszczenie procedur (podprogramów i funkcji) w module, a następnie "użycie" tego modułu z głównego programu lub innych procedur. Nie musisz "używać" modułu z innych procedur tego samego modułu. Spowoduje to, że interfejs procedury będzie jawny, tak że program wywołujący lub procedura "zna" charakterystykę argumentów ... umożliwia kompilatorowi sprawdzenie spójności między argumentami po obu stronach ... wywołującego i wywołującego. eliminuje wiele błędów.

Poza standardem językowym, ale w praktyce jest to konieczne: jeśli korzystasz z jednego pliku, umieść moduł przed programem głównym, który go używa. W przeciwnym razie kompilator nie będzie tego wiedział. tak:

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 
+0

Wielkie dzięki za poświęcony czas! – Andrew

+3

+1 za użycie '[1, 2, 3]' zamiast (im bardziej brzydki) '(\ 1, 2, 3 \)'. –

5

Jest to rodzaj późnym odpowiedź, ale ponieważ natknąłem się na to i nie ma jeszcze realne wyjaśnienie dlaczego doszło Twój błąd, pomyślałem dodam wyjaśnienie dla każdego, kto natyka to pytanie:

W swoim programie definiujesz tablicę o nazwie cross, która ma 1. pozycję. Następnie wywołujesz funkcję cross zdefiniowaną dalej.Ponieważ funkcja cross nie ma jawnego interfejsu (patrz odpowiedź M.S.B.), kompilator nie wie o tym w tym momencie. To, o czym wie, to tablica, którą zadeklarowałeś. Jeśli napiszesz r = cross(m, n), kompilator myśli, że chcesz uzyskać dostęp do elementu na pozycji (m, n) tablicy cross. Ponieważ ta tablica ma rangę 1, ale w zestawie dwa argumenty, to pojawia się błąd

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

co oznacza, że ​​w zestawie dwie współrzędne, gdy kompilator oczekiwał jeden.

+0

Dzięki. To ma sens. Odpowiednio zredagowałem odpowiedź. – toster

Powiązane problemy