Jak zainicjować tablice dwuwymiarowe w Fortran

W C można łatwo zainicjować tablicę używając składni nawiasów klamrowych, jeśli dobrze pamiętam:

int* a = new int[] { 1, 2, 3, 4 };

Jak można zrobić to samo w Fortran dla tablic dwuwymiarowych, jeśli chcesz zainicjować macierz z określonymi wartościami testowymi dla celów matematycznych? (Bez konieczności podwójnego indeksowania każdego elementu na osobnych instrukcjach)

Tablica jest albo zdefiniowana przez

real, dimension(3, 3) :: a

Lub

real, dimension(:), allocatable :: a
Author: Fludlu McBorry, 2010-09-14

3 answers

Możesz to zrobić używając reshapei shape. Coś w stylu:

INTEGER, DIMENSION(3, 3) :: array
array = reshape((/ 1, 2, 3, 4, 5, 6, 7, 8, 9 /), shape(array))

Ale pamiętaj o kolejności kolumn. Tablica będzie

1   4   7
2   5   8
3   6   9

Po przekształceniu.

Więc dostać:

1   2   3
4   5   6
7   8   9

Potrzebujesz też transponować wewnętrznie:

array = transpose(reshape((/ 1, 2, 3, 4, 5, 6, 7, 8, 9 /), shape(array)))

Dla bardziej ogólnego przykładu (alokowana tablica 2D o różnych wymiarach), trzeba Rozmiar :

PROGRAM main

  IMPLICIT NONE

  INTEGER, DIMENSION(:, :), ALLOCATABLE :: array

  ALLOCATE (array(2, 3))

  array = transpose(reshape((/ 1, 2, 3, 4, 5, 6 /),                            &
    (/ size(array, 2), size(array, 1) /)))

  DEALLOCATE (array)

END PROGRAM main
 44
Author: Wildcat,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-21 19:56:40

Dla tablic wielowymiarowych (rank>1) Sposób inicjalizacji Fortran różni się od rozwiązania C, ponieważ w C tablice wielowymiarowe są tylko tablicami tablic itd.

W Fortran, każda ranga odpowiada innemu atrybutowi zmodyfikowanego typu danych. Ale jest tylko jeden konstruktor tablicy dla tablic rank-1. Z tych dwóch powodów inicjalizacja za pomocą konstruktora tablicy wymaga funkcji intryzycznej RESHAPE.

Oprócz tego, na co już udzielono odpowiedzi, istnieje bardziej bezpośredni sposób wprowadzania wartości macierzy wierszem zamiast kolumną: reshape ma opcjonalny argument ORDER, który może być użyty do zmiany kolejności wypełniania elementu wielowymiarowej tablicy wpisami konstruktora tablicy.

Na przykład w przypadku przykładu w pierwszej odpowiedzi można by napisać:

INTEGER, DIMENSION(3, 3) :: array=reshape( (/ 1, 2, 3, &
                                              4, 5, 6, &
                                              7, 8, 9 /), &
                                           shape(array), order=(/2,1/) )

Uzyskanie wypełnienia macierzy dokładnie w kolejności wskazanej przez linie kodu.

Tablica (/2, 1/) siły indeks Kolumny (2) ma pierwszeństwo przed indeksem wiersza (1), dając pożądany efekt.

 14
Author: GiorgioP,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-10 16:22:06

Inicjalizacja tablicy może być wykonana w samej deklaracji array, jak pokazano poniżej:

program test
 real:: x(3) = (/1,2,3/)
 real:: y(3,3) = reshape((/1,2,3,4,5,6,7,8,9/), (/3,3/))
 integer:: i(3,2,2) = reshape((/1,2,3,4,5,6,7,8,9,10,11,12/), (/3,2,2/))

end program test

Dziwi mnie, że

 real:: y(3,3) = (/(/1,2,3/),(/4,5,6/),(/7,8,9/)/)

Jest nie akceptowane przez kompilator(wypróbowane g95, gfortran). Okazuje się, że shape z (/(/1,2,3/),(/4,5,6/),(/7,8,9/)/) jest 9 a nie 3 3!

 5
Author: Sourav Mukherjee,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-06-23 07:07:49