Programmieren in Fortran 90/95


  1. Ergänzende Bemerkungen zu Datenfeldern
  2. Untersuchungsfunktionen für Datenfelder

    In dem Kapitel zu den Datenfeldern wurde bereits erwähnt, dass es Untersuchungsfunktionen (engl. inquiry functions) zu Datenfeldern gibt. Die wichtigsten davon sollen nun nochmal wiederholt werden (Programm
    test_array.f90)

    program test_array
       implicit none
       real, dimension (-5:4,3) :: a = 0.0
       integer, dimension(2) :: lindex, uindex 
       
       write(*,*) 'shape(a)   = ', shape(a)
       write(*,*)
       write(*,*) 'size(a)    = ', size(a)
       write(*,*)
       write(*,*) 'lbound(a)  = ', lbound(a)
       write(*,*)
       write(*,*) 'ubound(a)  = ', ubound(a)
       write(*,*)
       lindex = lbound(a)
       write(*,*) 'Der kleinste Zeilenindex ist: ', lindex(1)
    
    end program test_array
    

    Bildschirmausgabe: test_array.erg)

     shape(a)   =           10           3
     
     size(a)    =           30
     
     lbound(a)  =           -5           1
     
     ubound(a)  =            4           3
     
     Der kleinste Zeilenindex ist:           -5 
    

    Die Bedeutung der einzelnen Funktionen lässt sich direkt aus dem Beispielprogramm ableiten.

    Diese Untersuchungsfunktionen werden benötigt, wenn man mit dem Konzept der assumed-shaped arrays als formale Parameter in Unterprogrammen arbeiten möchte.

    Übergabe von Datenfeldern an Unterprogramme ohne Größenangaben (engl. assumed-shape arrays)

    Beim Prinzip der assumed-shape arrays (in etwas zu übersetzen mit "Datenfelder als formale Parameter mit übernommener Gestalt") werden im Unterprogramm die Datenfelder als formale Parameter ohne Angabe der Indexbereiche in Fortran 90/95 deklariert und formrichtig (gestaltgerecht) an das Unterprogramm übergeben. Dies funktioniert allerdings nur, wenn zusätzlich in der aufrufenden Programmeinheit der interface-Block für das Unterprogramm angeführt wird.

    Anwendungsbeispiel (assumed_shape.f90)

    program assumed_shape
       implicit none
       
       interface
          subroutine maximale_Komponente_suchen(m,v)
            implicit none
            real, intent(in)  :: m(:,:)
            real, intent(out) :: v(:)
          end  subroutine maximale_Komponente_suchen
       end interface
       
    
       integer :: nu, no, mu, mo                    ! Indexbereiche Zeilen/Spalte 
       real, allocatable, dimension(:,:) :: matrix
       real, allocatable, dimension(:)   :: vektor
       integer :: error_alloc, i
    
       write(*,*) 'Das Programm arbeitet mit der Matrix'
       write(*,*) '      matrix(nu:no,mu:mo)' 
       write(*,*)   
       write(*,'(1X,A$)') 'Geben Sie bitte die Zeilenindexwerte an:  (nu,no): '
       read(*,*) nu, no
       write(*,*)   
       write(*,'(1X,A$)') 'Geben Sie bitte die Spaltenindexwerte an: (mu,mo): '
       read(*,*) mu, mo
       write(*,*) 
    
       allocate(matrix(nu:no,mu:mo),stat=error_alloc)
       if (error_alloc /= 0) stop 'Fehler beim Allokieren. Programmabbruch'
       allocate(vektor(nu:no),stat=error_alloc)
       if (error_alloc /= 0) stop 'Fehler beim Allokieren. Programmabbruch'
    
       write(*,*) 'Die Matrix wird nun mit Zufallszahlen vorbelegt'
       call random_seed            ! restart des Zufallsgenerators
       call random_number(matrix)  ! 0 <= Zufallszahlen < 1
     
       write(*,'(/1X,A)') 'Ausgabe der Matrix:'
       write(*,*)
       do i = nu, no
         write(*,*) matrix(i,:)
       end do
    
       write(*,*)
       write(*,*) 
       write(*,*) 'Die Matrix laesst sich beschreiben durch:'
       write(*,*) 
       write(*,*) 'allocated(matrix) = ', allocated(matrix)
       write(*,*) 'shape(matrix)     = ', shape(matrix)
       write(*,*) 'size(matrix)      = ', size(matrix)
       write(*,*) 'lbound(matrix)    = ', lbound(matrix)
       write(*,*) 'ubound(matrix)    = ', ubound(matrix)
       write(*,*)
    
       call maximale_Komponente_suchen(matrix,vektor)
    
       write(*,'(/1X,A)') 'Ausgabe der Matrix:'
       write(*,*)
       do i = nu, no
         write(*,*) matrix(i,:)
       end do
       write(*,'(/1X,A)') 'Ausgabe des Vektors mit den maximalen Zeilenwert :'
       write(*,*)
       do i = nu, no
         write(*,*) vektor(i)
       end do
    
       deallocate(matrix)
       deallocate(vektor)
    end program assumed_shape
    
    
    subroutine maximale_Komponente_suchen(m,v)
       implicit none
       real, intent(in)      :: m(:,:)         ! assumed-shape array           
       real, intent(out)     :: v(:)           ! assumed-shape array 
       integer, dimension(2) :: lindex, uindex
       integer               :: i 
    
       write(*,*) '---------Unterprogrammausgabe--------------'
       write(*,*)
       write(*,*) 'Ausgabe der Strukturfaktoren der Matrix:'
       write(*,*) 
       write(*,*) 'shape(m)     = ', shape(m)
       write(*,*) 'size(m)      = ', size(m)
       write(*,*) 'lbound(m)    = ', lbound(m)
       write(*,*) 'ubound(m)    = ', ubound(m)
       write(*,*)
    
       lindex = lbound(m)
       uindex = ubound(m)
    
       write(*,*) 'lindex = ', lindex
       write(*,*) 'uindex = ', uindex
       write(*,*)
       write(*,*) 'Ende:---------Unterprogrammausgabe--------------'
       
       
       ! den Vektor mit der jeweiligen maximalen Zeilenkomponenten belegen 
       do i = lindex(1), uindex(1) 
          v(i) = maxval(m(i,:))
       end do
    
       return
    end subroutine maximale_Komponente_suchen
    

    Bildschirmausgabe (assumed_shape.erg)

     Das Programm arbeitet mit der Matrix
           matrix(nu:no,mu:mo)
     
     Geben Sie bitte die Zeilenindexwerte an:  (nu,no): -5 2
     
     Geben Sie bitte die Spaltenindexwerte an: (mu,mo): -1 1
     
     Die Matrix wird nun mit Zufallszahlen vorbelegt
    
     Ausgabe der Matrix:
     
      0.6497849      1.6971491E-02  0.9945542    
      0.4926681      0.3747320      0.8816592    
      0.4943366      0.6666107      0.4868176    
      0.2802719      4.6211913E-02  0.5349406    
      0.1138642      0.8848069      0.9732907    
      0.4971006      9.1666177E-02  0.8223150    
      0.1475587      0.4428776      0.5099351    
      0.2241279      0.1590813      0.1290903    
     
     
     Die Matrix laesst sich beschreiben durch:
     
     allocated(matrix) =  T
     shape(matrix)     =            8           3
     size(matrix)      =           24
     lbound(matrix)    =           -5          -1
     ubound(matrix)    =            2           1
     
     ---------Unterprogrammausgabe--------------
     
     Ausgabe der Strukturfaktoren der Matrix:
     
     shape(m)     =            8           3
     size(m)      =           24
     lbound(m)    =            1           1
     ubound(m)    =            8           3
     
     uindex =            8           3
     lindex =            1           1
     
     Ende:---------Unterprogrammausgabe--------------
    
     Ausgabe der Matrix:
     
      0.6497849      1.6971491E-02  0.9945542    
      0.4926681      0.3747320      0.8816592    
      0.4943366      0.6666107      0.4868176    
      0.2802719      4.6211913E-02  0.5349406    
      0.1138642      0.8848069      0.9732907    
      0.4971006      9.1666177E-02  0.8223150    
      0.1475587      0.4428776      0.5099351    
      0.2241279      0.1590813      0.1290903    
    
     Ausgabe des Vektors mit den maximalen Zeilenwert :
     
      0.9945542    
      0.8816592    
      0.6666107    
      0.5349406    
      0.9732907    
      0.8223150    
      0.5099351    
      0.2241279    
    

Datenfelder lassen sich mit dem Prinzip der assumed-shape arrays elegant an Unterprogramme übergeben und dort weiterverarbeiten, solange im Unterprogramm nur mit relativen und nicht mit absoluten Indices auf die einzelnen Komponenten zugegriffen werden muss. Im Beispielprogramm werden die Maximas der Zeilenkomponenten gesucht. In diesem Fall und in vielen anderen Anwendungsbeispielen spielt es keine Rolle, dass nach Übergabe des Datenfeldes als assumed-shape array im Unterprogramm die Indices-Werte mit 1 beginnend gezählt werden.

Zurück zur Vorlesungsseite


Heidrun.Kolinsky@uni-bayreuth.de
(Dr. Heidrun Kolinsky, Rechenzentrum der Universität Bayreuth, Gebäude NW2, Raum 159, Universitätsstraße 30, D-95440 Bayreuth, Tel. 0921/55-2687)