HessenbergSchurInfo HessenbergSchur ( AbstractDistMatrix<F>& HPre, AbstractDistMatrix<Complex<Base<F>>>& wPre, AbstractDistMatrix<F>& ZPre, const HessenbergSchurCtrl& ctrl ) { EL_DEBUG_CSE typedef Base<F> Real; DistMatrixReadWriteProxy<F,F,MC,MR,BLOCK> HProx( HPre ); auto& H = HProx.Get(); DistMatrixWriteProxy<Complex<Real>,Complex<Real>,STAR,STAR> wProx( wPre ); auto& w = wProx.Get(); ProxyCtrl proxCtrl; proxCtrl.colConstrain = true; proxCtrl.rowConstrain = true; proxCtrl.colAlign = H.ColAlign(); proxCtrl.rowAlign = H.RowAlign(); proxCtrl.colCut = H.ColCut(); proxCtrl.rowCut = H.RowCut(); // Technically, the 'Read' portion of the proxy is only needed if // ctrl.accumulateSchurVecs is true. DistMatrixReadWriteProxy<F,F,MC,MR,BLOCK> ZProx( ZPre, proxCtrl ); auto& Z = ZProx.Get(); const Int n = H.Height(); auto ctrlMod( ctrl ); ctrlMod.winBeg = ( ctrl.winBeg==END ? n : ctrl.winBeg ); ctrlMod.winEnd = ( ctrl.winEnd==END ? n : ctrl.winEnd ); ctrlMod.wantSchurVecs = true; if( !ctrl.accumulateSchurVecs ) { Identity( Z, n, n ); ctrlMod.accumulateSchurVecs = true; } if( ctrlMod.scalapack ) { #ifdef EL_HAVE_SCALAPACK if( IsBlasScalar<F>::value ) return hess_schur::ScaLAPACKHelper( H, w, Z, ctrlMod ); else Output("Warning: ScaLAPACK is not supported for this datatype"); #else Output("Warning: Elemental was not configured with ScaLAPACK support"); #endif } if( ctrl.alg == HESSENBERG_SCHUR_AED ) { return hess_schur::AED( H, w, Z, ctrlMod ); } else { return hess_schur::MultiBulge( H, w, Z, ctrlMod ); } }
void NesterovTodd ( const ElementalMatrix<Real>& sPre, const ElementalMatrix<Real>& zPre, ElementalMatrix<Real>& wPre ) { DEBUG_CSE ElementalProxyCtrl ctrl; ctrl.colConstrain = true; ctrl.colAlign = 0; DistMatrixReadProxy<Real,Real,VC,STAR> sProx( sPre, ctrl ), zProx( zPre, ctrl ); DistMatrixWriteProxy<Real,Real,VC,STAR> wProx( wPre, ctrl ); auto& s = sProx.GetLocked(); auto& z = zProx.GetLocked(); auto& w = wProx.Get(); w.Resize( s.Height(), 1 ); const Int localHeight = w.LocalHeight(); const Real* sBuf = s.LockedBuffer(); const Real* zBuf = z.LockedBuffer(); Real* wBuf = w.Buffer(); for( Int iLoc=0; iLoc<localHeight; ++iLoc ) wBuf[iLoc] = Sqrt(sBuf[iLoc]/zBuf[iLoc]); }
HessenbergSchurInfo ScaLAPACKHelper ( AbstractDistMatrix<F>& HPre, AbstractDistMatrix<Complex<Base<F>>>& wPre, AbstractDistMatrix<F>& ZPre, const HessenbergSchurCtrl& ctrl ) { EL_DEBUG_CSE typedef Base<F> Real; AssertScaLAPACKSupport(); HessenbergSchurInfo info; ProxyCtrl proxyCtrl; proxyCtrl.colConstrain = true; proxyCtrl.rowConstrain = true; proxyCtrl.blockHeight = ctrl.blockHeight; proxyCtrl.blockWidth = ctrl.blockHeight; proxyCtrl.colAlign = 0; proxyCtrl.rowAlign = 0; proxyCtrl.colCut = 0; proxyCtrl.rowCut = 0; DistMatrixReadWriteProxy<F,F,MC,MR,BLOCK> HProx( HPre, proxyCtrl ); auto& H = HProx.Get(); const Int n = H.Height(); DistMatrixReadWriteProxy<F,F,MC,MR,BLOCK> ZProx( ZPre, proxyCtrl ); auto& Z = ZProx.Get(); if( !ctrl.accumulateSchurVecs ) Identity( Z, n, n ); DistMatrixWriteProxy<Complex<Real>,Complex<Real>,STAR,STAR> wProx( wPre ); auto& w = wProx.Get(); #ifdef EL_HAVE_SCALAPACK bool accumulateSchurVecs=true; bool useAED = ( ctrl.alg == HESSENBERG_SCHUR_AED ); auto descH = FillDesc( H ); scalapack::HessenbergSchur ( n, H.Buffer(), descH.data(), w.Buffer(), Z.Buffer(), descH.data(), ctrl.fullTriangle, accumulateSchurVecs, useAED ); // TODO(poulson): Find a way to fill in info? #endif return info; }
void HermitianFromEVD ( UpperOrLower uplo, AbstractDistMatrix<F>& APre, const AbstractDistMatrix<Base<F>>& wPre, const AbstractDistMatrix<F>& ZPre ) { DEBUG_CSE typedef Base<F> Real; DistMatrixWriteProxy<F,F,MC,MR> AProx( APre ); DistMatrixReadProxy<Real,Real,VR,STAR> wProx( wPre ); DistMatrixReadProxy<F,F,MC,MR> ZProx( ZPre ); auto& A = AProx.Get(); auto& w = wProx.GetLocked(); auto& Z = ZProx.GetLocked(); const Grid& g = A.Grid(); DistMatrix<F,MC, STAR> Z1_MC_STAR(g); DistMatrix<F,VR, STAR> Z1_VR_STAR(g); DistMatrix<F,STAR,MR > Z1Adj_STAR_MR(g); const Int m = Z.Height(); const Int n = Z.Width(); A.Resize( m, m ); if( uplo == LOWER ) MakeTrapezoidal( UPPER, A, 1 ); else MakeTrapezoidal( LOWER, A, -1 ); const Int bsize = Blocksize(); for( Int k=0; k<n; k+=bsize ) { const Int nb = Min(bsize,n-k); auto Z1 = Z( ALL, IR(k,k+nb) ); auto w1 = w( IR(k,k+nb), ALL ); Z1_MC_STAR.AlignWith( A ); Z1_MC_STAR = Z1; Z1_VR_STAR.AlignWith( A ); Z1_VR_STAR = Z1_MC_STAR; DiagonalScale( RIGHT, NORMAL, w1, Z1_VR_STAR ); Z1Adj_STAR_MR.AlignWith( A ); Adjoint( Z1_VR_STAR, Z1Adj_STAR_MR ); LocalTrrk( uplo, F(1), Z1_MC_STAR, Z1Adj_STAR_MR, F(1), A ); } }
void PushPairInto ( ElementalMatrix<Real>& sPre, ElementalMatrix<Real>& zPre, const ElementalMatrix<Real>& wPre, const ElementalMatrix<Int>& ordersPre, const ElementalMatrix<Int>& firstIndsPre, Real wMaxNormLimit, Int cutoff ) { DEBUG_ONLY(CSE cse("soc::PushPairInto")) AssertSameGrids( sPre, zPre, wPre, ordersPre, firstIndsPre ); ElementalProxyCtrl ctrl; ctrl.colConstrain = true; ctrl.colAlign = 0; DistMatrixReadWriteProxy<Real,Real,VC,STAR> sProx( sPre, ctrl ), zProx( zPre, ctrl ); DistMatrixReadProxy<Real,Real,VC,STAR> wProx( wPre, ctrl ); DistMatrixReadProxy<Int,Int,VC,STAR> ordersProx( ordersPre, ctrl ), firstIndsProx( firstIndsPre, ctrl ); auto& s = sProx.Get(); auto& z = zProx.Get(); auto& w = wProx.GetLocked(); auto& orders = ordersProx.GetLocked(); auto& firstInds = firstIndsProx.GetLocked(); DistMatrix<Real,VC,STAR> sLower(s.Grid()), zLower(z.Grid()); soc::LowerNorms( s, sLower, orders, firstInds, cutoff ); soc::LowerNorms( z, zLower, orders, firstInds, cutoff ); const Int localHeight = s.LocalHeight(); for( Int iLoc=0; iLoc<localHeight; ++iLoc ) { const Int i = s.GlobalRow(iLoc); const Real w0 = w.GetLocal(iLoc,0); if( i == firstInds.GetLocal(iLoc,0) && w0 > wMaxNormLimit ) { // TODO: Switch to a non-adhoc modification s.UpdateLocal( iLoc, 0, Real(1)/wMaxNormLimit ); z.UpdateLocal( iLoc, 0, Real(1)/wMaxNormLimit ); } } }
HessenbergSchurInfo HessenbergSchur ( AbstractDistMatrix<F>& HPre, AbstractDistMatrix<Complex<Base<F>>>& wPre, const HessenbergSchurCtrl& ctrl ) { EL_DEBUG_CSE typedef Base<F> Real; DistMatrixReadWriteProxy<F,F,MC,MR,BLOCK> HProx( HPre ); auto& H = HProx.Get(); DistMatrixWriteProxy<Complex<Real>,Complex<Real>,STAR,STAR> wProx( wPre ); auto& w = wProx.Get(); DistMatrix<F,MC,MR,BLOCK> Z(H.Grid()); Z.AlignWith( H ); const Int n = H.Height(); auto ctrlMod( ctrl ); ctrlMod.winBeg = ( ctrl.winBeg==END ? n : ctrl.winBeg ); ctrlMod.winEnd = ( ctrl.winEnd==END ? n : ctrl.winEnd ); ctrlMod.wantSchurVecs = false; if( ctrlMod.scalapack ) { #ifdef EL_HAVE_SCALAPACK if( IsBlasScalar<F>::value ) return hess_schur::ScaLAPACKHelper( H, w, ctrlMod ); else Output("Warning: ScaLAPACK is not supported for this datatype"); #else Output("Warning: Elemental was not configured with ScaLAPACK support"); #endif } if( ctrl.alg == HESSENBERG_SCHUR_AED ) { return hess_schur::AED( H, w, Z, ctrlMod ); } else { return hess_schur::MultiBulge( H, w, Z, ctrlMod ); } }
void SortAndFilter ( AbstractDistMatrix<Real>& wPre, const HermitianTridiagEigCtrl<Real>& ctrl ) { DEBUG_CSE DistMatrixReadWriteProxy<Real,Real,STAR,STAR> wProx( wPre ); auto& w = wProx.Get(); const Int n = w.Height(); const Grid& g = w.Grid(); if( ctrl.subset.indexSubset ) { Sort( w, ctrl.sort ); DistMatrix<Real,STAR,STAR> wCopy( w ); w = wCopy(IR(ctrl.subset.lowerIndex,ctrl.subset.upperIndex+1),ALL); } else if( ctrl.subset.rangeSubset ) { Int numValid = 0; for( Int j=0; j<n; ++j ) if( w.GetLocal(j,0) > ctrl.subset.lowerBound && w.GetLocal(j,0) <= ctrl.subset.upperBound ) ++numValid; DistMatrix<Real,STAR,STAR> wFilter(numValid,1,g); numValid = 0; for( Int j=0; j<n; ++j ) if( w.GetLocal(j,0) > ctrl.subset.lowerBound && w.GetLocal(j,0) <= ctrl.subset.upperBound ) wFilter.SetLocal( numValid++, 0, w.GetLocal(j,0) ); w = wFilter; Sort( w, ctrl.sort ); } else { Sort( w, ctrl.sort ); } }
void SortAndFilter ( AbstractDistMatrix<Base<F>>& wPre, AbstractDistMatrix<F>& QPre, const HermitianTridiagEigCtrl<Base<F>>& ctrl ) { DEBUG_CSE typedef Base<F> Real; DistMatrixReadWriteProxy<Real,Real,STAR,STAR> wProx( wPre ); DistMatrixReadWriteProxy<F,F,VC,STAR> QProx( QPre ); auto& w = wProx.Get(); auto& Q = QProx.Get(); const Int n = w.Height(); const Grid& g = w.Grid(); if( ctrl.subset.indexSubset ) { auto sortPairs = TaggedSort( w, ctrl.sort ); for( Int j=0; j<n; ++j ) w.SetLocal( j, 0, sortPairs[j].value ); ApplyTaggedSortToEachRow( sortPairs, Q ); DistMatrix<Real,STAR,STAR> wCopy( w ); DistMatrix<F,VC,STAR> QCopy( Q ); w = wCopy(IR(ctrl.subset.lowerIndex,ctrl.subset.upperIndex+1),ALL); Q = QCopy(ALL,IR(ctrl.subset.lowerIndex,ctrl.subset.upperIndex+1)); } else if( ctrl.subset.rangeSubset ) { Int numValid = 0; for( Int j=0; j<n; ++j ) if( w.GetLocal(j,0) > ctrl.subset.lowerBound && w.GetLocal(j,0) <= ctrl.subset.upperBound ) ++numValid; DistMatrix<Real,STAR,STAR> wFilter(numValid,1,g); DistMatrix<F,VC,STAR> QFilter(n,numValid,g); numValid = 0; for( Int j=0; j<n; ++j ) { if( w.GetLocal(j,0) > ctrl.subset.lowerBound && w.GetLocal(j,0) <= ctrl.subset.upperBound ) { wFilter.SetLocal( numValid, 0, w.GetLocal(j,0) ); auto qFilterCol = QFilter(ALL,IR(numValid)); qFilterCol = Q(ALL,IR(j)); ++numValid; } } w = wFilter; Q = QFilter; auto sortPairs = TaggedSort( w, ctrl.sort ); for( Int j=0; j<numValid; ++j ) w.SetLocal( j, 0, sortPairs[j].value ); ApplyTaggedSortToEachRow( sortPairs, Q ); } else { auto sortPairs = TaggedSort( w, ctrl.sort ); for( Int j=0; j<n; ++j ) w.SetLocal( j, 0, sortPairs[j].value ); ApplyTaggedSortToEachRow( sortPairs, Q ); } }