Beispielprogramme zu Feldern in F90

(alles, was der F90 Anfänger -- bis auf Pointer = Zeiger -- wissen muss)

3 Programme zum Herunterladen und Spielen

Wir benutzen hier eine teilweise implizite Deklaration, d.h. alle nicht spezifizierten Variablen/Funktionen
mit Anfangsbuchstaben I-N sind vom

(4-Byte) Integer-typ, alle restlichen vom
(4-Byte) Real-typ.

Implizite Deklaration ist schnell, aber aeusserst fehleranfaellig!
Laesst sich nur durch die

IMPLICIT NONE

Anweisung verbieten! Dies sollte immer die erste Anweisung nach den USE-Anweisungen sein.

Falls nicht anders spezifiziert, haben INTEGER-Variablen

eine 4 Byte (= 32 bit) Darstellung, d.h. insgesamt koennen 2^32-1 verschiedene Integers (neg, 0, pos) erzeugt werden.
Bereich: [-2^31+1...0,..2^31-1], 2^31-1=2147483647 approx 2.14e9

Fuer die REAL-Variablen wird eine 4 Byte Gleitkommadarstellung angenommen, wobei die ersten 6 Stellen genau dargestellt werden (meistens die ersten 7)
Bereich: [-0.3402823e39...-0.117549e-37,0.,0.117549e-37,0.3402823e39]

Falls man einen groesseren Bereich abdecken will, braucht man auf jeden Fall eine explizite Deklaration des Typparameters (KIND)


Es existieren folgende Arten von Feldern (Pointer = Zeiger spaeter)

statische Felder


automatische Felder (immer mit expliziter Gestalt, nur in Unterprogrammen)

dynamische Felder (allocatable)

!
!========================================================================
!
program feldexp
! Beispielprogramm fuer Felder mit expliziter Gestalt

integer, parameter :: m=3
integer, parameter :: n=2

integer,dimension(m,n) :: ifeldexp=(/1,2,3, 4,5,6/) !expl. Gestalt

! Gesamtzahl der Feldelemente des naechsten Feldes = 6*4=24
real,dimension(-3:2,7:10) :: rfeldexp=(/(float(i),i=1,24)/)

real,dimension(6,4) :: rfeldexp_1=(/((float(i),i=j,24,4),j=1,4)/)
!implizite DO-Schleife, entspricht
! 1,5, 9,13,17,21, (j=1)
! 2,6,10,14,18,22, (j=2)
! 3,7,11,15,19,23, (j=3)
! 4,8,12,16,20,24, (j=4)

do i=1,m !fuer alle Zeilen
print*,'Zeile',i,':',ifeldexp(i,:) !fuer alle Spalten
enddo

print* !Leerzeile

do i=-3,2
print*,'Zeile',i,':',rfeldexp(i,:)
enddo

print*

! Jetzt rueckwarts
do i=2,-3,-1
print*,'Zeile',i,':',(rfeldexp(i,j),j=10,7,-1) !implizite DO-Schleife
enddo

print*

do i=1,6
print*,'Zeile',i,':',rfeldexp_1(i,:)
enddo

call sub(ifeldexp,rfeldexp,rfeldexp,rfeldexp_1,m,n,6,4)

end program feldexp

!--------------------------------------------------------------------------

subroutine sub(iarr,r1,r2,r_1,m,n,dim1,dim2)

integer,intent(in) :: dim1,dim2 ! Muss explizit erklaert werden, da sonst
!als REAL angenommen

integer,dimension(m,n) :: iarr !Dimension haengt von Formalparametern m,n ab

!Indizes starten jeweils bei 1, 2. Dimension kuerzer als im Orginal
real ,dimension(dim1,dim2-1) :: r1
! 1. Dimension kuerzer als im Orginal
real ,dimension(dim1-1,dim2) :: r2

!r_1 explizit mit gleicher Dimension (aber versch. Grenzen)
!wie im Hauptprogramm dimensioniert
real ,dimension(-3:2,7:10) :: r_1, newarr !lokales Feld newarr

integer,dimension(m,n) :: auto !Automatisches Feld, da Dimensionierung
!nicht konstant

!Man beachte den Unterschied vom lokalen zum automatischen Feld.

! Addition von 5 zum gesamten Feld!

print*
print*,'in sub'
print*

auto=iarr
newarr=r_1+5.

do i=1,m
print*,'Zeile',i,':',auto(i,:)
enddo

print* !Leerzeile

do i=1,dim1
print*,'Zeile',i,':',r1(i,:)
enddo

print*

do i=1,dim1-1
print*,'Zeile',i,':',r2(i,:)
enddo

print*
print*,'Merke also:!!'
print*,'Felder werden immer in der Reihenfolge der im Hauptprogramm'
print*,'definierten Speicherplaetze (1. Index laeuft zuerst),'
print*,'bis zur im Unterprogram def. Gesamtlaenge (dim1*dim2*..) uebergeben!'
print*

do i=-3,2
print*,'Zeile',i,':',r_1(i,:)
enddo

print*

do i=-3,2
print*,'Zeile',i,':',newarr(i,:)
enddo

return
end subroutine sub

!========================================================================
!
! Beachte: Interfaces unbedingt notwendig, entweder in einem Modul, das
! mit Use angesprochen wird, oder im rufenden Programm
!
!
! Beachte des weiteren: Uebernommene Gestalt sollte Standardprogrammiertechnik
! sein, uebernommene Groesse sehr komplex, wenn moeglich zu vermeiden!
!
module my_inter
interface
subroutine sub1(iarr1,iarr2,iarr3)
integer,dimension(:,:) :: iarr1
integer,dimension(3,0:*) :: iarr2
integer,dimension(-13:*) :: iarr3
end subroutine sub1
end interface
end module my_inter

program feldass
!
! Beispielprogramm fuer Felder mit uebernommener Gestalt / Groesse
!
use my_inter

interface
subroutine sub(iarr)
integer,dimension(:,:) :: iarr
end subroutine sub
end interface

integer, parameter :: m=3,n=2

integer,dimension(m,n) :: ifeld=(/1,2,3, 4,5,6/) !expl. Gestalt
integer,dimension(0:1,3:5) :: ifeld_1=(/1,2, 3,4, 5,6/) !expl. Gestalt
integer,dimension(2,4) :: ifeld_2=(/1,1,2,2,3,3,4,4/) !expl. Gestalt

call sub(ifeld)
call sub1(ifeld_1,ifeld_2,ifeld_2)

end program feldass

!--------------------------------------------------------------------------

subroutine sub(iarr)

integer,dimension(:,:) :: iarr !Uebernommene Gestalt:
!Zahl + Groesse der Dim. bleiben gleich

print*
print*,'in sub'
print*


do i=1,3
print*,'Zeile',i,':',iarr(i,:)
enddo

return
end subroutine sub

!--------------------------------------------------------------------------

subroutine sub1(iarr1,iarr2,iarr3)

integer,dimension(:,:) :: iarr1 !Uebernommene Gestalt
integer,dimension(3,0:*) :: iarr2 !Uebernommene Groesse:
!Gesamtgroesse des aktuell uebergebenenen Feldesbleibt erhalten)
integer,dimension(-13:*) :: iarr3 !Uebernommene Groesse

! Beachte:
!Nur letzte Dimension darf variabel sein, Untergrenze muss spezifiziert werden,
!Obergrenze mit *
m=size(iarr1,1)
n=size(iarr1,2)

print*
print*,'in sub1, m = ',m,' n = ',n
print*


do i=1,m
print*,'Zeile',i,':',iarr1(i,:)
enddo

print*

m=size(iarr2,1) ! Beachte: 2. Index kann nicht berechnet werden
do i=1,m
print*,'Zeile',i,':',iarr2(i,0:3) ! 2. Index muss explizit angeben werden
enddo

print*

do i=-13,-6
print*,'Zeile',i,':',iarr3(i)
enddo

return
end subroutine sub1

!========================================================================

!
! Dieses Programm zeigt, wie man voellig dimensionsunabhaengig programmiert!
!
! Im Hauptprogramm sind alle Felder allokierbar, waehrend die Unterprogramme
! dann assumed shape arrays verwenden!


program felddyn

!
! Beispielprogramm fuer dynamische Felder: Allokieren und Statusabfrage
!

interface
subroutine sub(ife)
integer, dimension(:,:) :: ife ! Beachte: Nur ife (assumed shape array)
! muss im interface angegeben werden
end subroutine sub
end interface

integer, dimension(:,:), allocatable :: ifeld

Bigloop: do

print*,'Give in first and 2nd dimension of ifeld(m,n); (m=0 ==> Exit)'
read*,m,n
print*,'Input was ',m,n

if(m == 0) exit

if (.not. allocated(ifeld) ) then
allocate(ifeld(m,n),stat =ifehler)
else
deallocate(ifeld)
allocate(ifeld(m,n),stat =ifehler)
endif

if (allocated(ifeld) ) then
print*,' ifeld successfully allocated'
else
stop' Error in allocation'
endif

! Alternativ dazu (nach erfolgreichem Allokieren stat => 0, sonst pos)

if (ifehler == 0 ) then
print*,' ifeld successfully allocated'
else
stop' Error in allocation'
endif

iz=0
do i=1,m
do j=1,n
iz=iz+1
ifeld(i,j)=iz
enddo
enddo

print*,'Size(ifeld) = ',size(ifeld,1),size(ifeld,2)

do i=1,m
print*,'Zeile ',i,':',ifeld(i,:)
enddo

call sub(ifeld)

enddo Bigloop

end program felddyn

subroutine sub(ife)
integer, dimension(:,:) :: ife
integer, dimension(:,:), allocatable:: i1

m=size(ife,1)
n=size(ife,2)

allocate(i1(m,n))
i1=ife

print*
print*,'in sub'
print*

do i=1,m
print*,'Zeile ',i,':',i1(i,:)
enddo

deallocate(i1)
return
end subroutine sub