ldl Subroutine

private subroutine ldl(n, a, z, sigma, w)

- rank-one - update

Purpose:

Updates the factors of matrix by rank-one matrix .

Reference

History

  • D. Kraft, DFVLR - institut fuer dynamik der flugsysteme d-8031 oberpfaffenhofen
  • Status: 15. january 1980

Arguments

Type IntentOptional Attributes Name
integer, intent(in) :: n

order of the coefficient matrix a

real(kind=wp), intent(inout), dimension(*) :: a

In: positive definite matrix of dimension n; only the lower triangle is used and is stored column by column as one dimensional array of dimension n*(n+1)/2.

Out: updated factors

real(kind=wp), intent(inout), dimension(*) :: z

vector of dimension n of updating elements.

real(kind=wp), intent(in) :: sigma

scalar factor by which the modifying dyade is multiplied.

real(kind=wp), intent(inout), dimension(*) :: w

working array of dimension n (used only if ).


Called by

proc~~ldl~~CalledByGraph proc~ldl slsqp_core::ldl proc~slsqpb slsqp_core::slsqpb proc~slsqpb->proc~ldl proc~slsqp slsqp_core::slsqp proc~slsqp->proc~slsqpb proc~slsqp_wrapper slsqp_module::slsqp_solver%slsqp_wrapper proc~slsqp_wrapper->proc~slsqp

Source Code

    subroutine ldl(n,a,z,sigma,w)

    implicit none

    integer,intent(in)                  :: n     !! order of the coefficient matrix `a`
    real(wp),intent(in)                 :: sigma !! scalar factor by which the modifying dyade \(z z^T\) is multiplied.
    real(wp),dimension(*),intent(inout) :: a     !! ***In:*** positive definite matrix of dimension `n`;
                                                 !! only the lower triangle is used and is stored column by
                                                 !! column as one dimensional array of dimension `n*(n+1)/2`.
                                                 !!
                                                 !! ***Out:*** updated \(LDL^T\) factors
    real(wp),dimension(*),intent(inout) :: w     !! working array of dimension `n` (used only if \( \sigma \lt 0 \) ).
    real(wp),dimension(*),intent(inout) :: z     !! vector of dimension `n` of updating elements.

    integer :: i , ij , j
    real(wp) :: t , v , u , tp , beta , alpha , delta , gamma

    if ( abs(sigma)>zero ) then
        ij = 1
        t = one/sigma
        if ( sigma<=zero ) then
            ! prepare negative update
            do i = 1 , n
                w(i) = z(i)
            end do
            do i = 1 , n
                v = w(i)
                t = t + v*v/a(ij)
                do j = i + 1 , n
                    ij = ij + 1
                    w(j) = w(j) - v*a(ij)
                end do
                ij = ij + 1
            end do
            if ( t>=zero ) t = epmach/sigma
            do i = 1 , n
                j = n + 1 - i
                ij = ij - i
                u = w(j)
                w(j) = t
                t = t - u*u/a(ij)
            end do
        end if
        ! here updating begins
        do i = 1 , n
            v = z(i)
            delta = v/a(ij)
            if ( sigma<zero ) tp = w(i)
            if ( sigma>zero ) tp = t + delta*v
            alpha = tp/t
            a(ij) = alpha*a(ij)
            if ( i==n ) return
            beta = delta/tp
            if ( alpha>four ) then
                gamma = t/tp
                do j = i + 1 , n
                    ij = ij + 1
                    u = a(ij)
                    a(ij) = gamma*u + beta*z(j)
                    z(j) = z(j) - v*u
                end do
            else
                do j = i + 1 , n
                    ij = ij + 1
                    z(j) = z(j) - v*a(ij)
                    a(ij) = a(ij) + beta*z(j)
                end do
            end if
            ij = ij + 1
            t = tp
        end do
    end if

    end subroutine ldl