economia news e media viaggi informatica internet salute e benessere int rattenimento e spettacolo sport tempo libero istruzio ne e formazione arte cultura scienza

Il Sondaggio

Quale versione del fortran utilizzi?

Guarda i risultati

Programmi

Algoritmo di Henderson-Wassyng

A cura di Giuseppe Ciaburro

Pubblicato il 11/08/2007

Soluzione di un sistema lineare di equazioni attraverso l'Algoritmo di Henderson-Wassyng

SUBROUTINE dple(rowk, n, b, c, ierr)

 

! Code converted using TO_F90 by Alan Miller

! Date: 2003-06-16  Time: 12:26:32

 

!     ******************************************************************

!     SOLUTION OF LINEAR EQUATIONS WITH REDUCED STORAGE

!     ******************************************************************

 

! Uses the Henderson-Wassyng partial pivot algorithm.

! Wassyng, A. 'Solving Ax = b: A method with reduced storage requirements',

! SIAM J. Numerical Analysis, vol.19 (1982), pp. 197-204.

 

! The user must provide a routine ROWK to return the requested row of the

! matrix A.

 

! N.B. Arguments D and IP have been removed.

 

IMPLICIT NONE

INTEGER, PARAMETER  :: dp = SELECTED_REAL_KIND(14, 60)

 

INTEGER, INTENT(IN)     :: n

REAL (dp), INTENT(IN)   :: b(n)

REAL (dp), INTENT(OUT)  :: c(n)

INTEGER, INTENT(OUT)    :: ierr

 

! EXTERNAL rowk

INTERFACE

  SUBROUTINE rowk(n, k, r)

    IMPLICIT NONE

    INTEGER, PARAMETER  :: dp = SELECTED_REAL_KIND(14, 60)

    INTEGER, INTENT(IN)     :: n, k

    REAL (dp), INTENT(OUT)  :: r(:)

  END SUBROUTINE rowk

END INTERFACE

 

! Local variables

 

REAL (dp)  :: bk, cj, ck, c1, dkj

REAL (dp), PARAMETER  :: zero = 0.0_dp

REAL (dp)  :: wk(n*n/4 + n + 3)

INTEGER    :: i, iflag, ij, ijold, ik, iwk(n), j, k, kjold, km1, kp1,   &

              last, lastm1, lcol, lcolp1, m, maxwk, mjold, nm1, np1

 

!     SET THE NECESSARY CONSTANTS

 

ierr = 0

maxwk = n * n / 4 + n + 3

np1 = n + 1

k = 1

iflag = -1

 

!     GET THE FIRST COLUMN OF THE TRANSPOSED SYSTEM

 

CALL rowk(n, 1, c)

bk = b(1)

 

IF (n <= 1) THEN

  IF (c(1) == zero) GO TO 130

  c(1) = bk / c(1)

  RETURN

END IF

 

!     FIND THE PIVOT FOR COLUMN 1

 

m = 1

DO  i = 2, n

  IF (ABS(c(m)) < ABS(c(i))) m = i

END DO

 

iwk(1) = m

c1 = c(m)

c(m) = c(1)

c(1) = c1

IF (c(1) /= zero) THEN

 

!     FIND THE FIRST ELEMENTARY MATRIX AND STORE IT IN D

 

  DO  i = 2, n

    wk(i-1) = -c(i) / c(1)

  END DO

  wk(n) = bk / c(1)

 

!     K LOOP - EACH K FOR A NEW COLUMN OF THE TRANSPOSED SYSTEM

 

  DO  k = 2, n

    kp1 = k + 1

    km1 = k - 1

   

!       GET COLUMN K

   

    CALL rowk(n, k, c)

    DO  j = 1, km1

      m = iwk(j)

      cj = c(j)

      c(j) = c(m)

      c(m) = cj

    END DO

    bk = b(k)

   

    iflag = -iflag

    lcol = np1 - k

    lcolp1 = lcol + 1

    lastm1 = 1

    last = maxwk - n + k

    IF (k /= 2) THEN

     

      lastm1 = maxwk - n + km1

      IF (iflag < 0) last = last - n + k - 2

      IF (iflag > 0) lastm1 = lastm1 - n + k - 3

    END IF

   

!     J LOOP - EFFECT OF COLUMNS 1 TO K-1 OF L-INVERSE

   

    DO  j = 1, km1

      cj = c(j)

      ij = (j-1) * lcolp1

      IF (j == km1) ij = lastm1 - 1

     

!     I LOOP - EFFECT OF L-INVERSE ON ROWS K TO N+1

     

      DO  i = k, n

        ij = ij + 1

        c(i) = c(i) + wk(ij) * cj

      END DO

      bk = bk - wk(ij+1) * cj

    END DO

   

!       K=N CASE

   

    m = k

    IF (k >= n) THEN

      IF (c(k) == zero) GO TO 130

      wk(last) = bk / c(k)

    ELSE

     

!     FIND THE PIVOT

     

      DO  i = kp1, n

        IF (ABS(c(m)) < ABS(c(i))) m = i

      END DO

     

      iwk(k) = m

      ck = c(m)

      c(m) = c(k)

      c(k) = ck

      IF (c(k) == zero) GO TO 130

     

!     FIND THE K-TH ELEMENTARY MATRIX

     

      ik = last

      DO  i = kp1, n

        wk(ik) = -c(i) / c(k)

        ik = ik + 1

      END DO

      wk(ik) = bk / c(k)

    END IF

   

!     FORM THE PRODUCT OF THE ELEMENTARY MATRICES

   

    DO  j = 1, km1

      kjold = j * lcolp1 + k - np1

      mjold = kjold + m - k

      ij = (j-1) * lcol

      ijold = ij + j

      IF (j == km1) THEN

       

        kjold = lastm1

        mjold = lastm1 + m - k

        ijold = lastm1

      END IF

     

      ik = last - 1

      dkj = wk(mjold)

      wk(mjold) = wk(kjold)

      DO  i = kp1, np1

        ij = ij + 1

        ijold = ijold + 1

        ik = ik + 1

        wk(ij) = wk(ijold) + wk(ik) * dkj

      END DO

    END DO

  END DO

 

  last = maxwk

  IF (iflag < 0) last = maxwk - 2

  wk(n) = wk(last)

 

!     INSERT THE SOLUTION IN C

 

  c(1:n) = wk(1:n)

 

  nm1 = n - 1

  DO  i = 1, nm1

    k = n - i

    m = iwk(k)

    ck = c(k)

    c(k) = c(m)

    c(m) = ck

  END DO

  RETURN

END IF

 

!     THE SYSTEM IS SINGULAR

 

130 ierr = k

RETURN

END SUBROUTINE dple

 

 

 

SUBROUTINE rowk(n, k, r)

 

IMPLICIT NONE

INTEGER, PARAMETER  :: dp = SELECTED_REAL_KIND(14, 60)

INTEGER, INTENT(IN)     :: n, k

REAL (dp), INTENT(OUT)  :: r(:)

 

INTEGER    :: i

REAL (dp)  :: temp

 

r(k) = 1.0_dp

IF (k > 1) THEN

  temp = 1.0_dp

  DO i = 1, k-1

    temp = 0.99_dp * temp

    r(k-i) = temp

  END DO

END IF

 

IF (k < n) THEN

  temp = 1.0_dp

  DO i = 1, n-k

    temp = 0.99_dp * temp

    r(k+i) = temp

  END DO

END IF

 

RETURN

END SUBROUTINE rowk

 

 

 

PROGRAM Test_DPLE

IMPLICIT NONE

INTEGER, PARAMETER  :: dp = SELECTED_REAL_KIND(14, 60)

 

REAL (dp)  :: a(100), x(100), b(100), error, temp, soln(100)

INTEGER    :: i, ierr, row

 

INTERFACE

  SUBROUTINE dple(rowk, n, b, c, ierr)

    IMPLICIT NONE

    INTEGER, PARAMETER  :: dp = SELECTED_REAL_KIND(14, 60)

    INTEGER, INTENT(IN)     :: n

    REAL (dp), INTENT(IN)   :: b(n)

    REAL (dp), INTENT(OUT)  :: c(n)

    INTEGER, INTENT(OUT)    :: ierr

    INTERFACE

      SUBROUTINE rowk(n, k, r)

        IMPLICIT NONE

        INTEGER, PARAMETER  :: dp = SELECTED_REAL_KIND(14, 60)

        INTEGER, INTENT(IN)     :: n, k

        REAL (dp), INTENT(OUT)  :: r(:)

      END SUBROUTINE rowk

    END INTERFACE

  END SUBROUTINE dple

 

  SUBROUTINE rowk(n, k, r)

    IMPLICIT NONE

    INTEGER, PARAMETER  :: dp = SELECTED_REAL_KIND(14, 60)

    INTEGER, INTENT(IN)     :: n, k

    REAL (dp), INTENT(OUT)  :: r(:)

I link correlati all'argomento

Vuoi essere aggiornato sulle novitą della guida?

Feed RSS XML vostro feed RSS