Suche…


Grundnotation

Jeder Typ kann als Array deklariert werden, indem entweder das Dimensionsattribut verwendet wird oder die dimension (en) des Arrays direkt angegeben werden:

! One dimensional array with 4 elements
integer, dimension(4) :: foo

! Two dimensional array with 4 rows and 2 columns
real, dimension(4, 2) :: bar

! Three dimensional array
type(mytype), dimension(6, 7, 8) :: myarray

! Same as above without using the dimension keyword
integer :: foo2(4)
real :: bar2(4, 2)
type(mytype) :: myarray2(6, 7, 8)

Die letztere Art der Deklaration eines mehrdimensionalen Arrays ermöglicht die Deklaration von Arrays mit unterschiedlichem Rang und unterschiedlichen Dimensionen in einer Zeile

real :: pencil(5), plate(3,-2:4), cuboid(0:3,-10:5,6)

Der maximale Rang (Anzahl der Dimensionen) ist in Fortran 2008 Standard 15 und war zuvor 7.

Fortran speichert Arrays in der Reihenfolge der Kolonnen . Das heißt, die Elemente des bar werden wie folgt im Speicher gespeichert:

bar(1, 1), bar(2, 1), bar(3, 1), bar(4, 1), bar(1, 2), bar(2, 2), ...

In Fortran beginnt die Array-Nummerierung standardmäßig mit 1 , im Gegensatz zu C, das mit 0 beginnt. In Fortran können Sie die Ober- und Untergrenze für jede Dimension explizit angeben:

integer, dimension(7:12, -3:-1) :: geese

Dies deklariert ein Array von Shape (6, 3) , dessen erstes Element geese(7, -3) .

Auf die unteren und oberen Grenzen der 2 (oder mehr) Dimensionen kann durch die intrinsischen Funktionen ubound und lbound . In der Tat würden lbound(geese,2) -3 , wohingegen ubound(geese,1) 12 zurückkehren würde.

Größe eines Arrays kann durch intrinsische Funktion zugegriffen werden size . Zum Beispiel gibt size(geese, dim = 1) die Größe der ersten Dimension zurück, die 6 ist.

Zuordenbare Arrays

Arrays können das zuweisbare Attribut haben:

! One dimensional allocatable array
integer, dimension(:), allocatable :: foo
! Two dimensional allocatable array
real, dimension(:,:), allocatable :: bar

Dies deklariert die Variable, reserviert jedoch keinen Platz für sie.

! We can specify the bounds as usual
allocate(foo(3:5))

! It is an error to allocate an array twice
! so check it has not been allocated first
if (.not. allocated(foo)) then
  allocate(bar(10, 2))
end if

Sobald eine Variable nicht mehr benötigt wird, kann sie freigegeben werden :

deallocate(foo)

Wenn eine allocate aus irgendeinem Grund fehlschlägt, wird das Programm angehalten. Dies kann verhindert werden, wenn der Status über das Schlüsselwort stat überprüft wird:

real, dimension(:), allocatable :: geese
integer :: status

allocate(geese(17), stat=status)
if (stat /= 0) then
  print*, "Something went wrong trying to allocate 'geese'"
  stop 1
end if

Die deallocate Anweisung hat auch ein stat Schlüsselwort:

deallocate (geese, stat=status)

status ist eine Ganzzahlvariable, deren Wert 0 ist, wenn die Zuweisung oder Freigabe erfolgreich war.

Array-Konstruktoren

Ein Array-Wert mit Rang 1 kann mithilfe eines Array-Konstruktors mit der Syntax erstellt werden

(/ ... /)
[ ... ]

Die Form wurde [...] 2003 in Fortran eingeführt und wird allgemein als lesbarer angesehen, insbesondere in komplexen Ausdrücken. Dieses Formular wird ausschließlich in diesem Beispiel verwendet.

Die in einem Array-Konstruktor enthaltenen Werte können skalare Werte, Array-Werte oder implied-do-Schleifen sein.

Die Parameter type und type des erstellten Arrays stimmen mit denen der Werte im Array-Konstruktor überein

[1, 2, 3]      ! A rank-1 length-3 array of default integer type
[1., 2., 3.]   ! A rank-1 length-3 array of default real type
["A", "B"]     ! A rank-1 length-2 array of default character type

integer, parameter :: A = [2, 4]
[1, A, 3]      ! A rank-1 length-4 array of default integer type, with A's elements

integer i
[1, (i, i=2, 5), 6]  ! A rank-1 length-6 array of default integer type with an implied-do

In den obigen Formularen müssen alle angegebenen Werte denselben Typ und denselben Typparameter haben. Das Mischen von Typen oder Typparametern ist nicht zulässig. Die folgenden Beispiele sind nicht gültig

[1, 2.]      ! INVALID: Mixing integer and default real
[1e0, 2d0]   ! INVALID: Mixing default real and double precision
[1., 2._dp]  ! INVALID: Allowed only if kind `dp` corresponds to default real
["Hello", "Frederick"]  ! INVALID: Different length parameters

Um ein Array mit verschiedenen Typen zu erstellen, wird eine Typspezifikation für das Array angegeben

[integer :: 1, 2., 3d0]    ! A default integer array
[real(dp) :: 1, 2, 3._sp]  ! A real(dp) array
[character(len=9) :: "Hello", "Frederick"]  ! A length-2 array of length-9 characters

Diese letztere Form für Zeichenarrays ist besonders praktisch, um Leerzeichen wie die Alternative zu vermeiden

["Hello    ", "Frederick"]  ! A length-2 array of length-9 characters

Die Größe eines Arrays mit dem Namen konstant kann vom Array-Konstruktor impliziert werden, der zum Festlegen seines Werts verwendet wird

integer, parameter :: ids(*) = [1, 2, 3, 4]

und für längenparametrierte Typen kann der Längenparameter angenommen werden

character(len=*), parameter :: names(*) = [character(3) :: "Me", "You", "Her"]

Die Typspezifikation ist auch bei der Konstruktion von Arrays mit Nulllänge erforderlich. Von

[ ] ! Not a valid array constructor

Die Parameter type und type können nicht aus dem nicht vorhandenen Wertesatz ermittelt werden. So erstellen Sie ein Standard-Ganzzahl-Array mit Länge Null:

[integer :: ]

Array-Konstruktoren konstruieren nur Rang-1-Arrays. Manchmal, beispielsweise beim Festlegen des Wertes einer benannten Konstante, sind auch Arrays mit höherem Rang in einem Ausdruck erforderlich. Arrays mit höherem Rang können dem Ergebnis der reshape mit einem konstruierten Rang-1-Array entnommen werden

integer, parameter :: multi_rank_ids(2,2) = RESHAPE([1,2,3,4], shape=[2,2])

In einem Arraykonstruktor sind die Werte des Arrays in der Elementreihenfolge, wobei alle Arrays in der Werteliste so aussehen, als würden die einzelnen Elemente in der Arrayelementreihenfolge angegeben. So das vorige Beispiel

integer, parameter :: A = [2, 4]
[1, A, 3]      ! A rank-1 length-4 array of default integer type, with A's elements

ist äquivalent zu

[1, 2, 4, 3]   ! With the array written out in array element order

Im Allgemeinen können die Werte im Konstruktor beliebige Ausdrücke sein, einschließlich geschachtelter Array-Konstruktoren. Damit ein solcher Array-Konstruktor bestimmte Bedingungen erfüllt, z. B. einen Konstanten- oder Spezifikationsausdruck, gelten Einschränkungen für konstituierende Werte.


Obwohl es sich nicht um einen Array-Konstruktor handelt, können bestimmte Array-Werte auch bequem mit der spread Intrinsic-Funktion erstellt werden. Zum Beispiel

[(0, i=1,10)]  ! An array with 10 default integers each of value 0

ist auch das Ergebnis der Funktionsreferenz

SPREAD(0, 1, 10)

Spezifikation der Feldnatur: Rang und Form

Das dimension für ein Objekt gibt an, dass dieses Objekt ein Array ist. In Fortran 2008 gibt es fünf Arten von Feldern: 1

  • explizite Form
  • angenommene Form
  • angenommene Größe
  • zurückgestellte Form
  • implizierte Form

Nehmen Sie die drei Rang-1-Arrays 2

integer a, b, c
dimension(5) a    ! Explicit shape (default lower bound 1), extent 5
dimension(:) b    ! Assumed or deferred shape
dimension(*) c    ! Assumed size or implied shape array

Mit diesen ist ersichtlich, dass ein weiterer Kontext erforderlich ist, um die Art eines Arrays vollständig zu bestimmen.

Explizite Form

Ein explizites Formarray ist immer die Form seiner Deklaration. Wenn das Array nicht als lokal für ein Unterprogramm oder ein block deklariert ist, müssen die die Form definierenden Grenzen konstante Ausdrücke sein. In anderen Fällen kann ein explizites Formarray ein automatisches Objekt sein, das Erweiterungen verwendet, die bei jedem Aufruf eines Unterprogramms oder block variieren können.

subroutine sub(n)
  integer, intent(in) :: n
  integer a(5)   ! A local explicit shape array with constant bound
  integer b(n)   ! A local explicit shape array, automatic object
end subroutine

Angenommene Form

Ein angenommenes Shape-Array ist ein Dummy-Argument ohne das Attribut allocatable oder pointer . Ein solches Array nimmt seine Form von dem tatsächlichen Argument an, mit dem es verbunden ist.

integer a(5), b(10)
call sub(a)   ! In this call the dummy argument is like x(5)
call sub(b)   ! In this call the dummy argument is like x(10)

contains

  subroutine sub(x)
    integer x(:)    ! Assumed shape dummy argument
  end subroutine sub

end

Wenn ein Dummy-Argument die Form angenommen hat, muss der Gültigkeitsbereich, auf den die Prozedur verweist, über eine explizite Schnittstelle für diese Prozedur verfügen.

Angenommene Größe

Ein angenommenes Größenarray ist ein Dummy-Argument, dessen Größe von seinem tatsächlichen Argument angenommen wird.

subroutine sub(x)
  integer x(*)   ! Assumed size array
end subroutine

Angenommene Größenfelder verhalten sich sehr unterschiedlich von angenommenen Formfeldern, und diese Unterschiede werden an anderer Stelle dokumentiert.

Verschobene Form

Ein Array mit verzögerter Form ist ein Array mit dem Attribut " allocatable oder " pointer . Die Form eines solchen Arrays wird durch seine Zuordnung oder Zeigerzuordnung bestimmt.

integer, allocatable :: a(:)
integer, pointer :: b(:)

Angedeutete Form

Ein impliziertes Form-Array ist eine benannte Konstante, die ihre Form von dem Ausdruck nimmt, mit dem der Wert festgelegt wird

integer, parameter :: a(*) = [1,2,3,4]

Die Auswirkungen dieser Array-Deklarationen auf Dummy-Argumente sind an anderer Stelle zu dokumentieren.


1 Eine technische Spezifikation, die Fortran 2008 erweitert, fügt einen sechsten Array-Charakter hinzu: angenommener Rang. Dies wird hier nicht behandelt.

2 Diese können äquivalent als geschrieben werden

integer, dimension(5) :: a
integer, dimension(:) :: b
integer, dimension(*) :: c

oder

integer a(5)
integer b(:)
integer c(*)

Ganze Arrays, Array-Elemente und Array-Abschnitte

Betrachten Sie das als deklarierte Array

real x(10)

Dann haben wir drei Aspekte von Interesse:

  1. Das gesamte Array x ;
  2. Array-Elemente wie x(1) ;
  3. Array-Abschnitte wie x(2:6) .

Ganze Arrays

In den meisten Fällen bezieht sich das gesamte Array x auf alle Elemente des Arrays als eine einzige Entität. Es kann in ausführbaren Anweisungen wie print *, SUM(x) , print *, SIZE(x) oder x=1 .

Ein ganzes Array kann auf Arrays verweisen, die nicht explizit geformt sind (wie z. B. x oben):

function f(y)
  real, intent(out) :: y(:)
  real, allocatable :: z(:)

  y = 1.         ! Intrinsic assignment for the whole array
  z = [1., 2.,]  ! Intrinsic assignment for the whole array, invoking allocation
end function

Ein Array mit angenommener Größe kann auch als gesamtes Array angezeigt werden, jedoch nur unter bestimmten Umständen (an anderer Stelle zu dokumentieren).

Array-Elemente

Ein Array-Element wird als Integer-Index bezeichnet, einer für jeden Rang des Arrays, der die Position im gesamten Array angibt:

real x(5,2)
x(1,1) = 0.2
x(2,4) = 0.3

Ein Array-Element ist ein Skalar.

Array-Abschnitte

Ein Array-Abschnitt ist eine Referenz auf eine Reihe von Elementen (vielleicht nur eines) eines ganzen Arrays, wobei eine Syntax verwendet wird, die Doppelpunkte enthält:

real x(5,2)
x(:,1) = 0.         ! Referring to x(1,1), x(2,1), x(3,1), x(4,1) and x(5,1)
x(2,:) = 0.         ! Referring to x(2,1), x(2,2)
x(2:4,1) = 0.       ! Referring to x(2,1), x(3,1) and x(4,1)
x(2:3,1:2) = 0.     ! Referring to x(2,1), x(3,1), x(2,2) and x(3,2)
x(1:1,1) = 0.       ! Referring to x(1,1)
x([1,3,5],2) = 0.   ! Referring to x(1,2), x(3,2) and x(5,2)

Das letzte Formular oben verwendet einen Vektor-Index . Dies unterliegt einer Reihe von Einschränkungen, die über andere Array-Abschnitte hinausgehen.

Jeder Arrayabschnitt ist selbst ein Array, selbst wenn nur ein Element referenziert wird. Das heißt, x(1:1,1) ist ein Array von Rang 1 und x(1:1,1:1) ist ein Array von Rang 2.

Array-Abschnitte haben im Allgemeinen kein Attribut des gesamten Arrays. Insbesondere wo

real, allocatable :: x(:)
x = [1,2,3]     ! x is allocated as part of the assignment
x = [1,2,3,4]   ! x is dealloacted then allocated to a new shape in the assignment

die Zuordnung

x(:) = [1,2,3,4,5]   ! This is bad when x isn't the same shape as the right-hand side

ist nicht erlaubt: x(:) , obwohl ein Arrayabschnitt mit allen Elementen von x kein zuweisbares Array ist.

x(:) = [5,6,7,8]

ist in Ordnung, wenn x die Form der rechten Seite hat.


Array-Komponenten von Arrays

type t
   real y(5)
end type t

type(t) x(2)

In komplizierteren Einstellungen können wir uns auch auf ganze Arrays, Array-Elemente und Array-Abschnitte beziehen.

Aus dem obigen ist x ein ganzes Array. Wir haben auch

x(1)%y        ! A whole array
x(1)%y(1)     ! An array element
x%y(1)        ! An array section
x(1)%y(:)     ! An array section
x([1,2]%y(1)  ! An array section
x(1)%y(1:1)   ! An array section

In solchen Fällen dürfen wir nicht mehr als einen Teil der Referenz haben, der aus einem Array mit Rang 1 besteht. Die folgenden sind beispielsweise nicht zulässig

x%y             ! Both the x and y parts are arrays
x(1:1)%y(1:1)   ! Recall that each part is still an array section

Array-Operationen

Aufgrund ihrer Berechnungsziele sind mathematische Operationen in Arrays in Fortran unkompliziert.

Addition und Subtraktion

Operationen an Arrays derselben Form und Größe sind der Matrixalgebra sehr ähnlich. Anstatt alle Indizes mit Schleifen zu durchlaufen, können Sie die Addition (und die Subtraktion) schreiben:

real, dimension(2,3) :: A, B, C
real, dimension(5,6,3) :: D
A    = 3.    ! Assigning single value to the whole array
B    = 5.    ! Equivalent writing for assignment
C    = A + B ! All elements of C now have value 8.
D    = A + B ! Compiler will raise an error. The shapes and dimensions are not the same

Arrays von Slicing sind auch gültig:

integer :: i, j
real, dimension(3,2) :: Mat = 0.
real, dimension(3)   :: Vec1 = 0., Vec2 = 0., Vec3 = 0.
i = 0
j = 0
do i = 1,3
  do j = 1,2
    Mat(i,j) = i+j
  enddo
enddo
Vec1 = Mat(:,1)
Vec2 = Mat(:,2)
Vec3 = Mat(1:2,1) + Mat(2:3,2)

Funktion

Auf die gleiche Weise können die meisten intrinsischen Funktionen implizit verwendet werden, wenn eine komponentenweise Operation (jedoch nicht systematisch) vorausgesetzt wird:

real, dimension(2) :: A, B
A(1) = 6
A(2) = 44 ! Random values
B    = sin(A) ! Identical to B(1) = sin(6), B(2) = sin(44).

Multiplikation und Division

Bei Produkt und Division ist Vorsicht geboten: intrinsische Operationen mit den Symbolen * und / sind elementweise:

real, dimension(2) :: A, B, C
A(1) = 2
A(2) = 4
B(1) = 1
B(2) = 3
C = A*B ! Returns C(1) = 2*1 and C(2) = 4*3

Dies darf nicht mit Matrixoperationen verwechselt werden (siehe unten).

Matrixoperationen

Matrixoperationen sind intrinsische Prozeduren. Das Matrixprodukt der Arrays des vorherigen Abschnitts wird beispielsweise wie folgt geschrieben:

real, dimension(2,1) :: A, B
real, dimension(1,1) :: C
A(1) = 2
A(2) = 4
B(1) = 1
B(2) = 3
C = matmul(transpose(A),B) ! Returns the scalar product of vectors A and B

Komplexe Operationen ermöglichen das Einkapseln von Funktionen durch Erstellen temporärer Arrays. Dies wird zwar von einigen Compilern und Kompilierungsoptionen zugelassen, dies wird jedoch nicht empfohlen. Zum Beispiel kann ein Produkt mit einer Matrix-Transponierung geschrieben werden:

real, dimension(3,3) :: A, B, C
A(:) = 4
B(:) = 5
C = matmul(transpose(A),matmul(B,matmul(A,transpose(B)))) ! Equivalent to A^t.B.A.B^T

Erweiterte Array-Abschnitte: Index-Triplets und Vektor-Subskripte

Wie in einem anderen Beispiel erwähnt, kann auf eine Teilmenge der Elemente eines Arrays Bezug genommen werden, die als Arrayabschnitt bezeichnet wird. Von diesem Beispiel können wir haben

real x(10)
x(:)   = 0.
x(2:6) = 1.
x(3:4) = [3., 5.]

Array-Abschnitte können jedoch allgemeiner sein. Sie können die Form von Index-Triplets oder Vektor-Subskripten annehmen.

Subskriptionen

Ein Index-Tripel hat die Form [bound1]:[bound2][:stride] . Zum Beispiel

real x(10)
x(1:10) = ...   ! Elements x(1), x(2), ..., x(10)
x(1:) = ...     ! The omitted second bound is equivalent to the upper, same as above
x(:10) = ...    ! The omitted first bound is equivalent to the lower, same as above
x(1:6:2) = ...  ! Elements x(1), x(3), x(5)
x(5:1) = ...    ! No elements: the lower bound is greater than the upper
x(5:1:-1) = ... ! Elements x(5), x(4), x(3), x(2), x(1)
x(::3) = ...    ! Elements x(1), x(4), x(7), x(10), assuming omitted bounds
x(::-3) = ...   ! No elements: the bounds are assumed with the first the lower, negative stride

Wenn ein Schritt (der nicht Null sein darf) angegeben wird, beginnt die Folge der Elemente mit der ersten angegebenen Bindung. Wenn der Schritt positiv (bzw. negativ) ist, werden die ausgewählten Elemente in einer Folge um den Schritt erhöht (bzw. dekrementiert), bis das letzte Element nicht größer (bzw. kleiner) als die zweite Grenze ist. Wenn der Schritt weggelassen wird, wird er als eins behandelt.

Wenn die erste Grenze größer als die zweite Grenze ist und der Schritt positiv ist, werden keine Elemente angegeben. Wenn die erste Grenze kleiner als die zweite Grenze ist und der Schritt negativ ist, werden keine Elemente angegeben.

Es sollte beachtet werden, dass x(10:1:-1) nicht dasselbe ist wie x(1:10:1) , obwohl jedes Element von x in beiden Fällen erscheint.

Vektor-Indizes

Ein Vektor-Index ist ein ganzzahliges Array mit Rang 1. Dies bezeichnet eine Folge von Elementen, die den Werten des Arrays entsprechen.

real x(10)
integer i
x([1,6,4]) = ...     ! Elements x(1), x(6), x(4)
x([(i,i=2,4)]) = ... ! Elements x(2), x(3) and x(4)
print*, x([2,5,2])   ! Elements x(2), x(5) and x(2)

Ein Array-Abschnitt mit einem Vektor-Index ist in seiner Verwendung eingeschränkt:

  • es darf kein Argument sein, das mit einem Dummy-Argument verknüpft ist, das in der Prozedur definiert ist
  • Es ist möglicherweise nicht das Ziel in einer Zeigerzuweisungsanweisung.
  • Es kann sich nicht um eine interne Datei in einer Datenübertragungsanweisung handeln.

Außerdem erscheint ein solcher Array-Abschnitt möglicherweise nicht in einer Anweisung, die seine Definition beinhaltet, wenn dasselbe Element zweimal ausgewählt wird. Von oben:

print*, x([2,5,2])   ! Elements x(2), x(5) and x(2) are printed
x([2,5,2]) = 1.      ! Not permitted: x(2) appears twice in this definition

Array-Abschnitte mit höherem Rang

real x(5,2)
print*, x(::2,2:1:-1)  ! Elements x(1,2), x(3,2), x(5,2), x(1,1), x(3,1), x(5,1)


Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow