void ConsistentlyComputeDecomposition
(       DistMatrix<Field,MC,MR,BLOCK>& H,
        DistMatrix<Complex<Base<Field>>,STAR,STAR>& w,
        Matrix<Field>& Z,
  const HessenbergSchurCtrl& ctrl=HessenbergSchurCtrl() )
{
    EL_DEBUG_CSE
    // Because double-precision floating-point computation is often
    // non-deterministic due to extra-precision computation being frequent but
    // not guaranteed, we must be careful to not allow this non-determinism to
    // be amplified by the forward instability of Francis sweeps.
    const Grid& grid = H.Grid();
    const int owner = H.Owner(0,0);

    DistMatrix<Field,CIRC,CIRC> H_CIRC_CIRC( grid, owner );
    H_CIRC_CIRC = H;
    w.Resize( H.Height(), 1 );
    if( H_CIRC_CIRC.CrossRank() == H_CIRC_CIRC.Root() )
        HessenbergSchur( H_CIRC_CIRC.Matrix(), w.Matrix(), Z, ctrl );
    else
        Z.Resize( H.Height(), H.Height() );
    H = H_CIRC_CIRC;
    El::Broadcast( w.Matrix(), H_CIRC_CIRC.CrossComm(), H_CIRC_CIRC.Root() );
    El::Broadcast( Z, H_CIRC_CIRC.CrossComm(), H_CIRC_CIRC.Root() );
}
示例#2
0
AEDInfo NibbleHelper
( Matrix<Real>& H,
  Real& spikeValue,
  Matrix<Complex<Real>>& w,
  Matrix<Real>& V,
  const HessenbergSchurCtrl& ctrl )
{
    EL_DEBUG_CSE
    const Int n = H.Height();
    AEDInfo info;

    const Real zero(0);
    const Real ulp = limits::Precision<Real>();
    const Real safeMin = limits::SafeMin<Real>();
    const Real smallNum = safeMin*(Real(n)/ulp);

    Zeros( V, 0, 0 );
    if( n == 1 )
    {
        w(0) = H(0,0);
        if( Abs(spikeValue) <= Max( smallNum, ulp*Abs(w(0).real()) ) )
        {
            // The offdiagonal entry was small enough to deflate
            info.numDeflated = 1;
            spikeValue = zero;
        }
        else
        {
            // The offdiagonal entry was too large to deflate
            info.numShiftCandidates = 1;
        }
        return info;
    }

    // NOTE(poulson): We could only copy the upper-Hessenberg portion of H
    auto T( H ); // TODO(poulson): Reuse this matrix?
    Identity( V, n, n );
    auto ctrlSub( ctrl );
    ctrlSub.winBeg = 0;
    ctrlSub.winEnd = n;
    ctrlSub.fullTriangle = true;
    ctrlSub.wantSchurVecs = true;
    ctrlSub.demandConverged = false;
    ctrlSub.alg = ( ctrl.recursiveAED ? HESSENBERG_SCHUR_AED
                                      : HESSENBERG_SCHUR_MULTIBULGE );
    auto infoSub = HessenbergSchur( T, w, V, ctrlSub );
    EL_DEBUG_ONLY(
      if( infoSub.numUnconverged != 0 )
          Output(infoSub.numUnconverged," eigenvalues did not converge");
    )
示例#3
0
AEDInfo Nibble
( Matrix<Real>& H,
  Int deflationSize,
  Matrix<Complex<Real>>& w,
  Matrix<Real>& Z,
  const HessenbergSchurCtrl& ctrl )
{
    DEBUG_CSE
    const Int n = H.Height();
    Int winBeg = ( ctrl.winBeg==END ? n : ctrl.winBeg );
    Int winEnd = ( ctrl.winEnd==END ? n : ctrl.winEnd );
    AEDInfo info;

    const Real zero(0);
    const Real ulp = limits::Precision<Real>();
    const Real safeMin = limits::SafeMin<Real>();
    const Real smallNum = safeMin*(Real(n)/ulp);

    if( winBeg > winEnd )
        return info;
    if( deflationSize < 1 )
        return info;

    Int blockSize = Min( deflationSize, winEnd-winBeg );
    const Int deflateBeg = winEnd-blockSize;

    // If the deflation window touches the beginning of the full window,
    // then there is no spike
    Real spikeValue =
      ( deflateBeg==winBeg ? zero : H(deflateBeg,deflateBeg-1) );

    if( blockSize == 1 )
    {
        w(deflateBeg) = H(deflateBeg,deflateBeg);
        if( Abs(spikeValue) <= Max( smallNum, ulp*Abs(w(deflateBeg).real()) ) )
        {
            // The offdiagonal entry was small enough to deflate
            info.numDeflated = 1;
            if( deflateBeg > winBeg )
            {
                // Explicitly deflate by zeroing the offdiagonal entry
                H(deflateBeg,deflateBeg-1) = zero;
            }
        }
        else
        {
            // The offdiagonal entry was too large to deflate
            info.numShiftCandidates = 1;
        }
        return info;
    }

    auto deflateInd = IR(deflateBeg,winEnd);
    auto H11 = H( deflateInd, deflateInd );

    // NOTE(poulson): We could only copy the upper-Hessenberg portion of H11
    auto T( H11 ); // TODO(poulson): Reuse this matrix?
    auto w1 = w( deflateInd, ALL );
    Matrix<Real> V;
    Identity( V, blockSize, blockSize );
    auto ctrlSub( ctrl );
    ctrlSub.winBeg = 0;
    ctrlSub.winEnd = blockSize;
    ctrlSub.fullTriangle = true;
    ctrlSub.wantSchurVecs = true;
    ctrlSub.demandConverged = false;
    ctrlSub.alg = ( ctrl.recursiveAED ? HESSENBERG_SCHUR_AED
                                      : HESSENBERG_SCHUR_MULTIBULGE );
    
    auto infoSub = HessenbergSchur( T, w1, V, ctrlSub );
    DEBUG_ONLY(
      if( infoSub.numUnconverged != 0 )
          Output(infoSub.numUnconverged," eigenvalues did not converge");
    )