void dotproduct(DistMatrix<R> &A,DistMatrix<R> &B){ if(A.Height() != B.Height()){ //ERROR! } if(A.Width() != B.Width()){ //ERROR! } double temp,temp1; const int colShift = A.ColShift(); // first row we own const int rowShift = A.RowShift(); // first col we own const int colStride = A.ColStride(); const int rowStride = A.RowStride(); const int localHeight = A.LocalHeight(); const int localWidth = A.LocalWidth(); for( int iLocal=0; iLocal<localHeight; ++iLocal ){ for( int jLocal=0; jLocal<localWidth; ++jLocal ){ const int i = colShift + iLocal*colStride; const int j = rowShift + jLocal*rowStride; temp = A.GetLocal(iLocal, jLocal); temp1 = B.GetLocal(iLocal,jLocal); B.SetLocal(iLocal, jLocal, (temp*temp1)); } } }
void calc_x_else(const R alpha, const R beta,const R c, const R delta, DistMatrix<R> &x, DistMatrix<R> &phi,DistMatrix<R> &w){ R bphi; R temp; R temp2; const R pi = 4*atan(1); const int colShift = x.ColShift(); // first row we own const int rowShift = x.RowShift(); // first col we own const int colStride = x.ColStride(); const int rowStride = x.RowStride(); const int localHeight = x.LocalHeight(); const int localWidth = x.LocalWidth(); for( int iLocal=0; iLocal<localHeight; ++iLocal ){ for( int jLocal=0; jLocal<localWidth; ++jLocal ){ const int i = colShift + iLocal*colStride; const int j = rowShift + jLocal*rowStride; temp = phi.GetLocal(0,jLocal);//phi temp2 = w.GetLocal(0,jLocal); //w bphi = (pi/2) + beta * temp; //cout<< (delta + c * (((2/pi) * (bphi * tan(temp) - beta * log((pi/2) * temp2 * cos(temp) / bphi))) + (beta * tan (pi *alpha/2))))<<endl; x.SetLocal(iLocal, jLocal, (-1* sqrt(abs(delta + c * (((2/pi) * (bphi * tan(temp) - beta * log((pi/2) * temp2 * cos(temp) / bphi))) + (beta * tan (pi *alpha/2))))))); } } }
inline typename Base<F>::type HermitianEntrywiseOneNorm( UpperOrLower uplo, const DistMatrix<F>& A ) { #ifndef RELEASE PushCallStack("HermitianEntrywiseOneNorm"); #endif if( A.Height() != A.Width() ) throw std::logic_error("Hermitian matrices must be square."); const int r = A.Grid().Height(); const int c = A.Grid().Width(); const int colShift = A.ColShift(); const int rowShift = A.RowShift(); typedef typename Base<F>::type R; R localSum = 0; const int localWidth = A.LocalWidth(); if( uplo == UPPER ) { for( int jLocal=0; jLocal<localWidth; ++jLocal ) { int j = rowShift + jLocal*c; int numUpperRows = Length(j+1,colShift,r); for( int iLocal=0; iLocal<numUpperRows; ++iLocal ) { int i = colShift + iLocal*r; const R alpha = Abs(A.GetLocal(iLocal,jLocal)); if( i ==j ) localSum += alpha; else localSum += 2*alpha; } } } else { for( int jLocal=0; jLocal<localWidth; ++jLocal ) { int j = rowShift + jLocal*c; int numStrictlyUpperRows = Length(j,colShift,r); for( int iLocal=numStrictlyUpperRows; iLocal<A.LocalHeight(); ++iLocal ) { int i = colShift + iLocal*r; const R alpha = Abs(A.GetLocal(iLocal,jLocal)); if( i ==j ) localSum += alpha; else localSum += 2*alpha; } } } R norm; mpi::AllReduce( &localSum, &norm, 1, mpi::SUM, A.Grid().VCComm() ); #ifndef RELEASE PopCallStack(); #endif return norm; }
void calc_x_if(const R alpha,const R beta,const R c, const R delta,DistMatrix<R> &x, DistMatrix<R> &phi,DistMatrix<R> &w){ R temp; // phi R temp2; // w R aphi; R a1phi; const R pi = 4*atan(1); const R zeta = beta * tan(pi * alpha/2); const int colShift = x.ColShift(); // first row we own const int rowShift = x.RowShift(); // first col we own const int colStride = x.ColStride(); const int rowStride = x.RowStride(); const int localHeight = x.LocalHeight(); const int localWidth = x.LocalWidth(); for( int iLocal=0; iLocal<localHeight; ++iLocal ){ for( int jLocal=0; jLocal<localWidth; ++jLocal ){ const int i = colShift + iLocal*colStride; const int j = rowShift + jLocal*rowStride; temp = phi.GetLocal(iLocal,jLocal);//phi temp2 = w.GetLocal(iLocal,jLocal); //w aphi = alpha * temp; a1phi = (1-alpha)*temp; x.SetLocal(iLocal, jLocal, (-1 * sqrt(abs(delta + c *( ( (sin(aphi)+zeta * cos(aphi))/ cos(temp)) * -1 * pow( abs( ((cos(a1phi) + zeta * sin(a1phi))/ (temp2 * cos(temp))) ) ,((1-alpha)/alpha) ) + beta * tan(pi * alpha/2) )))) ); } } }
inline typename Base<F>::type HermitianMaxNorm( UpperOrLower uplo, const DistMatrix<F>& A ) { #ifndef RELEASE PushCallStack("internal::HermitianMaxNorm"); #endif typedef typename Base<F>::type R; if( A.Height() != A.Width() ) throw std::logic_error("Hermitian matrices must be square."); const int r = A.Grid().Height(); const int c = A.Grid().Width(); const int colShift = A.ColShift(); const int rowShift = A.RowShift(); R localMaxAbs = 0; const int localWidth = A.LocalWidth(); if( uplo == UPPER ) { for( int jLocal=0; jLocal<localWidth; ++jLocal ) { int j = rowShift + jLocal*c; int numUpperRows = LocalLength(j+1,colShift,r); for( int iLocal=0; iLocal<numUpperRows; ++iLocal ) { const R thisAbs = Abs(A.GetLocal(iLocal,jLocal)); localMaxAbs = std::max( localMaxAbs, thisAbs ); } } } else { for( int jLocal=0; jLocal<localWidth; ++jLocal ) { int j = rowShift + jLocal*c; int numStrictlyUpperRows = LocalLength(j,colShift,r); for( int iLocal=numStrictlyUpperRows; iLocal<A.LocalHeight(); ++iLocal ) { const R thisAbs = Abs(A.GetLocal(iLocal,jLocal)); localMaxAbs = std::max( localMaxAbs, thisAbs ); } } } R maxAbs; mpi::AllReduce( &localMaxAbs, &maxAbs, 1, mpi::MAX, A.Grid().VCComm() ); #ifndef RELEASE PopCallStack(); #endif return maxAbs; }
void GetMappedDiagonal ( const DistMatrix<T,U,V,BLOCK>& A, AbstractDistMatrix<S>& d, function<S(const T&)> func, Int offset ) { EL_DEBUG_CSE EL_DEBUG_ONLY(AssertSameGrids( A, d )) // TODO(poulson): Make this more efficient const Int diagLength = A.DiagonalLength(offset); d.Resize( diagLength, 1 ); Zero( d ); if( d.Participating() && A.RedundantRank() == 0 ) { const Int iStart = Max(-offset,0); const Int jStart = Max( offset,0); for( Int k=0; k<diagLength; ++k ) { if( A.IsLocal(iStart+k,jStart+k) ) { const Int iLoc = A.LocalRow(iStart+k); const Int jLoc = A.LocalCol(jStart+k); d.QueueUpdate(k,0,func(A.GetLocal(iLoc,jLoc))); } } } d.ProcessQueues(); }
InfinityNorm( const DistMatrix<F,U,V>& A ) { #ifndef RELEASE CallStackEntry entry("InfinityNorm"); #endif // Compute the partial row sums defined by our local matrix, A[U,V] typedef BASE(F) R; const Int localHeight = A.LocalHeight(); const Int localWidth = A.LocalWidth(); std::vector<R> myPartialRowSums( localHeight ); for( Int iLoc=0; iLoc<localHeight; ++iLoc ) { myPartialRowSums[iLoc] = 0; for( Int jLoc=0; jLoc<localWidth; ++jLoc ) myPartialRowSums[iLoc] += Abs(A.GetLocal(iLoc,jLoc)); } // Sum our partial row sums to get the row sums over A[U,* ] std::vector<R> myRowSums( localHeight ); mpi::Comm rowComm = ReduceRowComm<U,V>( A.Grid() ); mpi::AllReduce( &myPartialRowSums[0], &myRowSums[0], localHeight, rowComm ); // Find the maximum out of the row sums R myMaxRowSum = 0; for( Int iLoc=0; iLoc<localHeight; ++iLoc ) myMaxRowSum = std::max( myMaxRowSum, myRowSums[iLoc] ); // Find the global maximum row sum by searching over the U team mpi::Comm colComm = ReduceColComm<U,V>( A.Grid() ); return mpi::AllReduce( myMaxRowSum, mpi::MAX, colComm ); }
int Corrupt( DistMatrix<F>& A, double probCorrupt ) { #ifndef RELEASE CallStackEntry entry("Corrupt"); #endif typedef BASE(F) Real; Int numLocalCorrupt = 0; const Int localHeight = A.LocalHeight(); const Int localWidth = A.LocalWidth(); for( Int jLocal=0; jLocal<localWidth; ++jLocal ) { for( Int iLocal=0; iLocal<localHeight; ++iLocal ) { if( Uniform<Real>() <= probCorrupt ) { ++numLocalCorrupt; const F perturb = SampleBall<F>(); A.SetLocal( iLocal, jLocal, A.GetLocal(iLocal,jLocal)+perturb ); } } } Int numCorrupt; mpi::AllReduce ( &numLocalCorrupt, &numCorrupt, 1, mpi::SUM, A.Grid().VCComm() ); return numCorrupt; }
inline bool PivotParity( const DistMatrix<int,VC,STAR>& p, int pivotOffset ) { #ifndef RELEASE PushCallStack("PivotParity"); if( p.Width() != 1 ) throw std::logic_error("p must be a column vector"); if( pivotOffset < 0 ) throw std::logic_error("pivot offset cannot be negative"); #endif const int mLocal = p.LocalHeight(); const Grid& g = p.Grid(); bool isLocallyOdd = false; const int colShift = p.ColShift(); const int gridSize = g.Size(); for( int iLocal=0; iLocal<mLocal; ++iLocal ) { const int i = colShift + iLocal*gridSize; if( p.GetLocal(iLocal,0) != i+pivotOffset ) isLocallyOdd = !isLocallyOdd; } int localContribution = isLocallyOdd; int globalContribution; mpi::AllReduce ( &localContribution, &globalContribution, 1, MPI_SUM, g.VCComm() ); globalContribution = globalContribution % 2; bool isOdd = globalContribution; #ifndef RELEASE PopCallStack(); #endif return isOdd; }
inline typename Base<F>::type FrobeniusNorm( const DistMatrix<F,U,V>& A ) { #ifndef RELEASE PushCallStack("internal::FrobeniusNorm"); #endif typedef typename Base<F>::type R; mpi::Comm comm = NormComm( A ); R localScale = 0; R localScaledSquare = 1; const int localHeight = A.LocalHeight(); const int localWidth = A.LocalWidth(); for( int jLocal=0; jLocal<localWidth; ++jLocal ) { for( int iLocal=0; iLocal<localHeight; ++iLocal ) { const R alphaAbs = Abs(A.GetLocal(iLocal,jLocal)); if( alphaAbs != 0 ) { if( alphaAbs <= localScale ) { const R relScale = alphaAbs/localScale; localScaledSquare += relScale*relScale; } else { const R relScale = localScale/alphaAbs; localScaledSquare = localScaledSquare*relScale*relScale + 1; localScale = alphaAbs; } } } } // Find the maximum relative scale R scale; mpi::AllReduce( &localScale, &scale, 1, mpi::MAX, comm ); R norm = 0; if( scale != 0 ) { // Equilibrate our local scaled sum to the maximum scale R relScale = localScale/scale; localScaledSquare *= relScale*relScale; // The scaled square is now simply the sum of the local contributions R scaledSquare; mpi::AllReduce( &localScaledSquare, &scaledSquare, 1, mpi::SUM, comm ); norm = scale*Sqrt(scaledSquare); } #ifndef RELEASE PopCallStack(); #endif return norm; }
void NormalizeEntries( DistMatrix<F,U,V>& A ) { const Int localHeight = A.LocalHeight(); const Int localWidth = A.LocalWidth(); for( Int jLocal=0; jLocal<localWidth; ++jLocal ) { for( Int iLocal=0; iLocal<localHeight; ++iLocal ) { const F alpha = A.GetLocal( iLocal, jLocal ); A.SetLocal( iLocal, jLocal, alpha/Abs(alpha) ); } } }
inline void HermitianSVD ( UpperOrLower uplo, DistMatrix<F>& A, DistMatrix<BASE(F),VR,STAR>& s, DistMatrix<F>& U, DistMatrix<F>& V ) { #ifndef RELEASE CallStackEntry entry("HermitianSVD"); #endif #ifdef HAVE_PMRRR typedef BASE(F) R; // Grab an eigenvalue decomposition of A HermitianEig( uplo, A, s, V ); // Redistribute the singular values into an [MR,* ] distribution const Grid& grid = A.Grid(); DistMatrix<R,MR,STAR> s_MR_STAR( grid ); s_MR_STAR.AlignWith( V.DistData() ); s_MR_STAR = s; // Set the singular values to the absolute value of the eigenvalues const Int numLocalVals = s.LocalHeight(); for( Int iLoc=0; iLoc<numLocalVals; ++iLoc ) { const R sigma = s.GetLocal(iLoc,0); s.SetLocal(iLoc,0,Abs(sigma)); } // Copy V into U (flipping the sign as necessary) U.AlignWith( V ); U.ResizeTo( V.Height(), V.Width() ); const Int localHeight = V.LocalHeight(); const Int localWidth = V.LocalWidth(); for( Int jLoc=0; jLoc<localWidth; ++jLoc ) { const R sigma = s_MR_STAR.GetLocal( jLoc, 0 ); F* UCol = U.Buffer( 0, jLoc ); const F* VCol = V.LockedBuffer( 0, jLoc ); if( sigma >= 0 ) for( Int iLoc=0; iLoc<localHeight; ++iLoc ) UCol[iLoc] = VCol[iLoc]; else for( Int iLoc=0; iLoc<localHeight; ++iLoc ) UCol[iLoc] = -VCol[iLoc]; } #else U = A; MakeHermitian( uplo, U ); SVD( U, s, V ); #endif // ifdef HAVE_PMRRR }
FrobeniusNorm( const DistMatrix<F,U,V>& A ) { #ifndef RELEASE CallStackEntry entry("FrobeniusNorm"); #endif typedef BASE(F) R; R localScale = 0; R localScaledSquare = 1; const Int localHeight = A.LocalHeight(); const Int localWidth = A.LocalWidth(); for( Int jLoc=0; jLoc<localWidth; ++jLoc ) { for( Int iLoc=0; iLoc<localHeight; ++iLoc ) { const R alphaAbs = Abs(A.GetLocal(iLoc,jLoc)); if( alphaAbs != 0 ) { if( alphaAbs <= localScale ) { const R relScale = alphaAbs/localScale; localScaledSquare += relScale*relScale; } else { const R relScale = localScale/alphaAbs; localScaledSquare = localScaledSquare*relScale*relScale + 1; localScale = alphaAbs; } } } } // Find the maximum relative scale mpi::Comm comm = ReduceComm<U,V>( A.Grid() ); const R scale = mpi::AllReduce( localScale, mpi::MAX, comm ); R norm = 0; if( scale != 0 ) { // Equilibrate our local scaled sum to the maximum scale R relScale = localScale/scale; localScaledSquare *= relScale*relScale; // The scaled square is now simply the sum of the local contributions const R scaledSquare = mpi::AllReduce( localScaledSquare, comm ); norm = scale*Sqrt(scaledSquare); } return norm; }
inline void HermitianSVD ( UpperOrLower uplo, DistMatrix<F>& A, DistMatrix<typename Base<F>::type,VR,STAR>& s, DistMatrix<F>& U, DistMatrix<F>& V ) { #ifndef RELEASE PushCallStack("HermitianSVD"); #endif typedef typename Base<F>::type R; // Grab an eigenvalue decomposition of A HermitianEig( uplo, A, s, V ); // Redistribute the singular values into an [MR,* ] distribution const Grid& grid = A.Grid(); DistMatrix<R,MR,STAR> s_MR_STAR( grid ); s_MR_STAR.AlignWith( V ); s_MR_STAR = s; // Set the singular values to the absolute value of the eigenvalues const int numLocalVals = s.LocalHeight(); for( int iLocal=0; iLocal<numLocalVals; ++iLocal ) { const R sigma = s.GetLocal(iLocal,0); s.SetLocal(iLocal,0,Abs(sigma)); } // Copy V into U (flipping the sign as necessary) U.AlignWith( V ); U.ResizeTo( V.Height(), V.Width() ); const int localHeight = V.LocalHeight(); const int localWidth = V.LocalWidth(); for( int jLocal=0; jLocal<localWidth; ++jLocal ) { const R sigma = s_MR_STAR.GetLocal( jLocal, 0 ); F* UCol = U.LocalBuffer( 0, jLocal ); const F* VCol = V.LockedLocalBuffer( 0, jLocal ); if( sigma >= 0 ) for( int iLocal=0; iLocal<localHeight; ++iLocal ) UCol[iLocal] = VCol[iLocal]; else for( int iLocal=0; iLocal<localHeight; ++iLocal ) UCol[iLocal] = -VCol[iLocal]; } #ifndef RELEASE PopCallStack(); #endif }
void repmat_as2(DistMatrix<R> &vector, DistMatrix<R> &repmatrix){ //old 1 x d //new nSim x d //Must set dimensions of New before being passed to function double temp; const int colShift = repmatrix.ColShift(); // first row we own const int rowShift = repmatrix.RowShift(); // first col we own const int colStride = repmatrix.ColStride(); const int rowStride = repmatrix.RowStride(); const int localHeight = repmatrix.LocalHeight(); const int localWidth = repmatrix.LocalWidth(); for( int iLocal=0; iLocal<localHeight; ++iLocal ){ for( int jLocal=0; jLocal<localWidth; ++jLocal ){ const int i = colShift + iLocal*colStride; const int j = rowShift + jLocal*rowStride; temp = vector.GetLocal(jLocal, 0); repmatrix.SetLocal(iLocal, jLocal, temp); } } }
inline typename Base<F>::type OneNorm( const DistMatrix<F,U,V>& A ) { #ifndef RELEASE PushCallStack("internal::OneNorm"); #endif typedef typename Base<F>::type R; mpi::Comm colComm = NormColComm( A ); mpi::Comm rowComm = NormRowComm( A ); // Compute the partial column sums defined by our local matrix, A[U,V] const int localHeight = A.LocalHeight(); const int localWidth = A.LocalWidth(); std::vector<R> myPartialColSums( localWidth ); for( int jLocal=0; jLocal<localWidth; ++jLocal ) { myPartialColSums[jLocal] = 0; for( int iLocal=0; iLocal<localHeight; ++iLocal ) myPartialColSums[jLocal] += Abs(A.GetLocal(iLocal,jLocal)); } // Sum our partial column sums to get the column sums over A[* ,V] std::vector<R> myColSums( localWidth ); mpi::AllReduce ( &myPartialColSums[0], &myColSums[0], localWidth, mpi::SUM, colComm ); // Find the maximum out of the column sums R myMaxColSum = 0; for( int jLocal=0; jLocal<localWidth; ++jLocal ) myMaxColSum = std::max( myMaxColSum, myColSums[jLocal] ); // Find the global maximum column sum by searching over the MR team R maxColSum = 0; mpi::AllReduce( &myMaxColSum, &maxColSum, 1, mpi::MAX, rowComm ); #ifndef RELEASE PopCallStack(); #endif return maxColSum; }
inline typename Base<F>::type EntrywiseOneNorm( const DistMatrix<F,U,V>& A ) { #ifndef RELEASE PushCallStack("EntrywiseOneNorm"); #endif typedef typename Base<F>::type R; R localSum = 0; const int localHeight = A.LocalHeight(); const int localWidth = A.LocalWidth(); for( int jLocal=0; jLocal<localWidth; ++jLocal ) for( int iLocal=0; iLocal<localHeight; ++iLocal ) localSum += Abs(A.GetLocal(iLocal,jLocal)); R norm; mpi::Comm comm = ReduceComm<U,V>( A.Grid() ); mpi::AllReduce( &localSum, &norm, 1, mpi::SUM, comm ); #ifndef RELEASE PopCallStack(); #endif return norm; }
inline void HermitianSingularValues ( UpperOrLower uplo, DistMatrix<F>& A, DistMatrix<typename Base<F>::type,VR,STAR>& s ) { #ifndef RELEASE PushCallStack("HermitianSingularValues"); #endif typedef typename Base<F>::type R; // Grab an eigenvalue decomposition of A HermitianEig( uplo, A, s ); // Replace the eigenvalues with their absolute values const int numLocalVals = s.LocalHeight(); for( int iLocal=0; iLocal<numLocalVals; ++iLocal ) { const R sigma = s.GetLocal(iLocal,0); s.SetLocal(iLocal,0,Abs(sigma)); } #ifndef RELEASE PopCallStack(); #endif }
inline void HermitianSVD ( UpperOrLower uplo, DistMatrix<F>& A, DistMatrix<BASE(F),VR,STAR>& s ) { #ifndef RELEASE CallStackEntry entry("HermitianSVD"); #endif #ifdef HAVE_PMRRR typedef BASE(F) R; // Grab the eigenvalues of A HermitianEig( uplo, A, s ); // Replace the eigenvalues with their absolute values const Int numLocalVals = s.LocalHeight(); for( Int iLoc=0; iLoc<numLocalVals; ++iLoc ) { const R sigma = s.GetLocal(iLoc,0); s.SetLocal(iLoc,0,Abs(sigma)); } #else MakeHermitian( uplo, A ); SVD( A, s ); #endif // ifdef HAVE_PMRRR }
inline typename Base<F>::type HermitianFrobeniusNorm ( UpperOrLower uplo, const DistMatrix<F>& A ) { #ifndef RELEASE PushCallStack("internal::HermitianFrobeniusNorm"); #endif typedef typename Base<F>::type R; if( A.Height() != A.Width() ) throw std::logic_error("Hermitian matrices must be square."); const int r = A.Grid().Height(); const int c = A.Grid().Width(); const int colShift = A.ColShift(); const int rowShift = A.RowShift(); R localScale = 0; R localScaledSquare = 1; const int localWidth = A.LocalWidth(); if( uplo == UPPER ) { for( int jLocal=0; jLocal<localWidth; ++jLocal ) { int j = rowShift + jLocal*c; int numUpperRows = LocalLength(j+1,colShift,r); for( int iLocal=0; iLocal<numUpperRows; ++iLocal ) { int i = colShift + iLocal*r; const R alphaAbs = Abs(A.GetLocal(iLocal,jLocal)); if( alphaAbs != 0 ) { if( alphaAbs <= localScale ) { const R relScale = alphaAbs/localScale; if( i != j ) localScaledSquare += 2*relScale*relScale; else localScaledSquare += relScale*relScale; } else { const R relScale = localScale/alphaAbs; if( i != j ) localScaledSquare = localScaledSquare*relScale*relScale + 2; else localScaledSquare = localScaledSquare*relScale*relScale + 1; localScale = alphaAbs; } } } } } else { for( int jLocal=0; jLocal<localWidth; ++jLocal ) { int j = rowShift + jLocal*c; int numStrictlyUpperRows = LocalLength(j,colShift,r); for( int iLocal=numStrictlyUpperRows; iLocal<A.LocalHeight(); ++iLocal ) { int i = colShift + iLocal*r; const R alphaAbs = Abs(A.GetLocal(iLocal,jLocal)); if( alphaAbs != 0 ) { if( alphaAbs <= localScale ) { const R relScale = alphaAbs/localScale; if( i != j ) localScaledSquare += 2*relScale*relScale; else localScaledSquare += relScale*relScale; } else { const R relScale = localScale/alphaAbs; if( i != j ) localScaledSquare = localScaledSquare*relScale*relScale + 2; else localScaledSquare = localScaledSquare*relScale*relScale + 1; localScale = alphaAbs; } } } } } // Find the maximum relative scale R scale; mpi::AllReduce( &localScale, &scale, 1, mpi::MAX, A.Grid().VCComm() ); R norm = 0; if( scale != 0 ) { // Equilibrate our local scaled sum to the maximum scale R relScale = localScale/scale; localScaledSquare *= relScale*relScale; // The scaled square is now simply the sum of the local contributions R scaledSquare; mpi::AllReduce ( &localScaledSquare, &scaledSquare, 1, mpi::SUM, A.Grid().VCComm() ); norm = scale*Sqrt(scaledSquare); } #ifndef RELEASE PopCallStack(); #endif return norm; }
const DistMatrix<T,STAR,STAR>& DistMatrix<T,STAR,STAR>::operator=( const DistMatrix<T,STAR,STAR>& A ) { #ifndef RELEASE CallStackEntry entry("[* ,* ] = [* ,* ]"); this->AssertNotLocked(); #endif this->ResizeTo( A.Height(), A.Width() ); if( this->Grid() == A.Grid() ) { this->matrix_ = A.LockedMatrix(); } else { // TODO: Remember why I wrote this... if( !mpi::CongruentComms( A.Grid().ViewingComm(), this->Grid().ViewingComm() ) ) LogicError ("Redistributing between nonmatching grids currently requires" " the viewing communicators to match."); // Compute and allocate the amount of required memory Int requiredMemory = 0; if( A.Grid().VCRank() == 0 ) requiredMemory += A.Height()*A.Width(); if( this->Participating() ) requiredMemory += A.Height()*A.Width(); T* buffer = this->auxMemory_.Require( requiredMemory ); Int offset = 0; T* sendBuf = &buffer[offset]; if( A.Grid().VCRank() == 0 ) offset += A.Height()*A.Width(); T* bcastBuffer = &buffer[offset]; // Send from the root of A to the root of this matrix's grid mpi::Request sendRequest; if( A.Grid().VCRank() == 0 ) { for( Int j=0; j<A.Width(); ++j ) for( Int i=0; i<A.Height(); ++i ) sendBuf[i+j*A.Height()] = A.GetLocal(i,j); const Int recvViewingRank = this->Grid().VCToViewingMap(0); mpi::ISend ( sendBuf, A.Height()*A.Width(), recvViewingRank, this->Grid().ViewingComm(), sendRequest ); } // Receive on the root of this matrix's grid and then broadcast // over this matrix's owning communicator if( this->Participating() ) { if( this->Grid().VCRank() == 0 ) { const Int sendViewingRank = A.Grid().VCToViewingMap(0); mpi::Recv ( bcastBuffer, A.Height()*A.Width(), sendViewingRank, this->Grid().ViewingComm() ); } mpi::Broadcast ( bcastBuffer, A.Height()*A.Width(), 0, this->Grid().VCComm() ); for( Int j=0; j<A.Width(); ++j ) for( Int i=0; i<A.Height(); ++i ) this->SetLocal(i,j,bcastBuffer[i+j*A.Height()]); } if( A.Grid().VCRank() == 0 ) mpi::Wait( sendRequest ); this->auxMemory_.Release(); } return *this; }
HermitianFrobeniusNorm( UpperOrLower uplo, const DistMatrix<F>& A ) { #ifndef RELEASE CallStackEntry entry("HermitianFrobeniusNorm"); #endif if( A.Height() != A.Width() ) LogicError("Hermitian matrices must be square."); const Int r = A.Grid().Height(); const Int c = A.Grid().Width(); const Int colShift = A.ColShift(); const Int rowShift = A.RowShift(); typedef BASE(F) R; R localScale = 0; R localScaledSquare = 1; const Int localWidth = A.LocalWidth(); if( uplo == UPPER ) { for( Int jLoc=0; jLoc<localWidth; ++jLoc ) { Int j = rowShift + jLoc*c; Int numUpperRows = Length(j+1,colShift,r); for( Int iLoc=0; iLoc<numUpperRows; ++iLoc ) { Int i = colShift + iLoc*r; const R alphaAbs = Abs(A.GetLocal(iLoc,jLoc)); if( alphaAbs != 0 ) { if( alphaAbs <= localScale ) { const R relScale = alphaAbs/localScale; if( i != j ) localScaledSquare += 2*relScale*relScale; else localScaledSquare += relScale*relScale; } else { const R relScale = localScale/alphaAbs; if( i != j ) localScaledSquare = localScaledSquare*relScale*relScale + 2; else localScaledSquare = localScaledSquare*relScale*relScale + 1; localScale = alphaAbs; } } } } } else { for( Int jLoc=0; jLoc<localWidth; ++jLoc ) { Int j = rowShift + jLoc*c; Int numStrictlyUpperRows = Length(j,colShift,r); for( Int iLoc=numStrictlyUpperRows; iLoc<A.LocalHeight(); ++iLoc ) { Int i = colShift + iLoc*r; const R alphaAbs = Abs(A.GetLocal(iLoc,jLoc)); if( alphaAbs != 0 ) { if( alphaAbs <= localScale ) { const R relScale = alphaAbs/localScale; if( i != j ) localScaledSquare += 2*relScale*relScale; else localScaledSquare += relScale*relScale; } else { const R relScale = localScale/alphaAbs; if( i != j ) localScaledSquare = localScaledSquare*relScale*relScale + 2; else localScaledSquare = localScaledSquare*relScale*relScale + 1; localScale = alphaAbs; } } } } } // Find the maximum relative scale const R scale = mpi::AllReduce( localScale, mpi::MAX, A.Grid().VCComm() ); R norm = 0; if( scale != 0 ) { // Equilibrate our local scaled sum to the maximum scale R relScale = localScale/scale; localScaledSquare *= relScale*relScale; // The scaled square is now simply the sum of the local contributions const R scaledSquare = mpi::AllReduce( localScaledSquare, A.Grid().VCComm() ); norm = scale*Sqrt(scaledSquare); } return norm; }
int main( int argc, char* argv[] ) { Initialize( argc, argv ); try { const Int matType = Input("--matType","0:uniform,1:Haar,2:Lotkin,3:Grcar,4:FoxLi," "5:HelmholtzPML1D,6:HelmholtzPML2D",5); const Int n = Input("--size","height of matrix",100); const Real realCenter = Input("--realCenter","real center",0.); const Real imagCenter = Input("--imagCenter","imag center",0.); const Real xWidth = Input("--xWidth","x width of image",0.); const Real yWidth = Input("--yWidth","y width of image",0.); const Int xSize = Input("--xSize","number of x samples",100); const Int ySize = Input("--ySize","number of y samples",100); const bool lanczos = Input("--lanczos","use Lanczos?",true); const Int krylovSize = Input("--krylovSize","num Lanczos vectors",10); const bool reorthog = Input("--reorthog","reorthog basis?",true); const bool deflate = Input("--deflate","deflate converged?",true); const Int maxIts = Input("--maxIts","maximum two-norm iter's",1000); const Real tol = Input("--tol","tolerance for norm estimates",1e-6); const Int numBands = Input("--numBands","num bands for Grcar",3); const Real omega = Input("--omega","frequency for Fox-Li/Helm",16*M_PI); const Int mx = Input("--mx","number of x points for HelmholtzPML",30); const Int my = Input("--my","number of y points for HelmholtzPML",30); const Int numPmlPoints = Input("--numPml","num PML points for Helm",5); const double sigma = Input("--sigma","PML amplitude",1.5); const double pmlExp = Input("--pmlExp","PML takeoff exponent",3.); const bool progress = Input("--progress","print progress?",true); const bool display = Input("--display","display matrices?",false); const bool write = Input("--write","write matrices?",false); const bool writePseudo = Input("--writePs","write pseudospec.",false); const Int formatInt = Input("--format","write format",2); const Int colorMapInt = Input("--colorMap","color map",0); ProcessInput(); PrintInputReport(); if( formatInt < 1 || formatInt >= FileFormat_MAX ) LogicError("Invalid file format integer, should be in [1,", FileFormat_MAX,")"); FileFormat format = static_cast<FileFormat>(formatInt); ColorMap colorMap = static_cast<ColorMap>(colorMapInt); SetColorMap( colorMap ); C center(realCenter,imagCenter); DistMatrix<C> A; switch( matType ) { case 0: Uniform( A, n, n ); break; case 1: Haar( A, n ); break; case 2: Lotkin( A, n ); break; case 3: Grcar( A, n, numBands ); break; case 4: FoxLi( A, n, omega ); break; case 5: HelmholtzPML ( A, n, C(omega), numPmlPoints, sigma, pmlExp ); break; case 6: HelmholtzPML ( A, mx, my, C(omega), numPmlPoints, sigma, pmlExp ); break; default: LogicError("Invalid matrix type"); } if( display ) Display( A, "A" ); if( write ) Write( A, "A", format ); // Visualize the pseudospectrum by evaluating ||inv(A-sigma I)||_2 // for a grid of complex sigma's. DistMatrix<Real> invNormMap; DistMatrix<Int> itCountMap; if( xWidth != 0. && yWidth != 0. ) itCountMap = Pseudospectrum ( A, invNormMap, center, xWidth, yWidth, xSize, ySize, lanczos, krylovSize, reorthog, deflate, maxIts, tol, progress ); else itCountMap = Pseudospectrum ( A, invNormMap, center, xSize, ySize, lanczos, krylovSize, reorthog, deflate, maxIts, tol, progress ); const Int numIts = MaxNorm( itCountMap ); if( mpi::WorldRank() == 0 ) std::cout << "num iterations=" << numIts << std::endl; if( display ) { Display( invNormMap, "invNormMap" ); Display( itCountMap, "itCountMap" ); } if( write || writePseudo ) { Write( invNormMap, "invNormMap", format ); Write( itCountMap, "itCountMap", format ); } // Take the element-wise log const Int mLocal = invNormMap.LocalHeight(); const Int nLocal = invNormMap.LocalWidth(); for( Int jLoc=0; jLoc<nLocal; ++jLoc ) for( Int iLoc=0; iLoc<mLocal; ++iLoc ) invNormMap.SetLocal ( iLoc, jLoc, Log(invNormMap.GetLocal(iLoc,jLoc)) ); if( display ) { Display( invNormMap, "logInvNormMap" ); if( GetColorMap() != GRAYSCALE_DISCRETE ) { auto colorMap = GetColorMap(); SetColorMap( GRAYSCALE_DISCRETE ); Display( invNormMap, "discreteLogInvNormMap" ); SetColorMap( colorMap ); } } if( write || writePseudo ) { Write( invNormMap, "logInvNormMap", format ); if( GetColorMap() != GRAYSCALE_DISCRETE ) { auto colorMap = GetColorMap(); SetColorMap( GRAYSCALE_DISCRETE ); Write( invNormMap, "discreteLogInvNormMap", format ); SetColorMap( colorMap ); } } } catch( exception& e ) { ReportException(e); } Finalize(); return 0; }
void TestCorrectness ( bool print, UpperOrLower uplo, const DistMatrix<F>& A, const DistMatrix<Base<F>,VR,STAR>& w, const DistMatrix<F>& Z, const DistMatrix<F>& AOrig ) { typedef Base<F> Real; const Grid& g = A.Grid(); const Int n = Z.Height(); const Int k = Z.Width(); if( g.Rank() == 0 ) { cout << " Gathering computed eigenvalues..."; cout.flush(); } DistMatrix<Real,MR,STAR> w_MR_STAR(true,Z.RowAlign(),g); w_MR_STAR = w; if( g.Rank() == 0 ) cout << "DONE" << endl; if( g.Rank() == 0 ) cout << " Testing orthogonality of eigenvectors..." << endl; DistMatrix<F> X(g); Identity( X, k, k ); Herk( uplo, ADJOINT, F(-1), Z, F(1), X ); Real oneNormOfError = OneNorm( X ); Real infNormOfError = InfinityNorm( X ); Real frobNormOfError = FrobeniusNorm( X ); if( g.Rank() == 0 ) { cout << " ||Z^H Z - I||_1 = " << oneNormOfError << "\n" << " ||Z^H Z - I||_oo = " << infNormOfError << "\n" << " ||Z^H Z - I||_F = " << frobNormOfError << "\n\n" << " Testing for deviation of AZ from ZW..." << endl; } // X := AZ X.AlignWith( Z ); Zeros( X, n, k ); Hemm( LEFT, uplo, F(1), AOrig, Z, F(0), X ); // Find the residual ||X-ZW||_oo = ||AZ-ZW||_oo for( Int jLoc=0; jLoc<X.LocalWidth(); ++jLoc ) { const Real omega = w_MR_STAR.GetLocal(jLoc,0); for( Int iLoc=0; iLoc<X.LocalHeight(); ++iLoc ) { const F chi = X.GetLocal(iLoc,jLoc); const F zeta = Z.GetLocal(iLoc,jLoc); X.SetLocal(iLoc,jLoc,chi-omega*zeta); } } // Find the infinity norms of A, Z, and AZ-ZW Real infNormOfA = HermitianInfinityNorm( uplo, AOrig ); Real frobNormOfA = HermitianFrobeniusNorm( uplo, AOrig ); Real oneNormOfZ = OneNorm( Z ); Real infNormOfZ = InfinityNorm( Z ); Real frobNormOfZ = FrobeniusNorm( Z ); oneNormOfError = OneNorm( X ); infNormOfError = InfinityNorm( X ); frobNormOfError = FrobeniusNorm( X ); if( g.Rank() == 0 ) { cout << " ||A||_1 = ||A||_oo = " << infNormOfA << "\n" << " ||A||_F = " << frobNormOfA << "\n" << " ||Z||_1 = " << oneNormOfZ << "\n" << " ||Z||_oo = " << infNormOfZ << "\n" << " ||Z||_F = " << frobNormOfZ << "\n" << " ||A Z - Z W||_1 = " << oneNormOfError << "\n" << " ||A Z - Z W||_oo = " << infNormOfError << "\n" << " ||A Z - Z W||_F = " << frobNormOfError << endl; } }
int main( int argc, char* argv[] ) { Initialize( argc, argv ); mpi::Comm comm = mpi::COMM_WORLD; const int commRank = mpi::CommRank( comm ); try { const int n = Input("--size","size of matrix",10); const bool print = Input("--print","print matrices?",true); #ifdef HAVE_QT5 const bool display = Input("--display","display matrices?",true); #endif ProcessInput(); PrintInputReport(); // Create a circulant matrix DistMatrix<Complex<double> > A; std::vector<Complex<double> > a( n ); for( int j=0; j<n; ++j ) a[j] = j; Circulant( A, a ); if( print ) A.Print("Circulant matrix:"); #ifdef HAVE_QT5 if( display ) Display( A, "Circulant" ); #endif // Create a discrete Fourier matrix, which can be used to diagonalize // circulant matrices DistMatrix<Complex<double> > F; DiscreteFourier( F, n ); if( print ) F.Print("DFT matrix (F):"); #ifdef HAVE_QT5 if( display ) Display( F, "Discrete Fourier" ); #endif // Form B := A F DistMatrix<Complex<double> > B; Zeros( B, n, n ); Gemm( NORMAL, NORMAL, Complex<double>(1), A, F, Complex<double>(0), B ); // Form A := F^H B = F^H \hat A F Gemm( ADJOINT, NORMAL, Complex<double>(1), F, B, Complex<double>(0), A ); if( print ) A.Print("A := F^H A F"); #ifdef HAVE_QT5 if( display ) Display( A, "F^H A F" ); #endif // Form the thresholded result const int localHeight = A.LocalHeight(); const int localWidth = A.LocalWidth(); for( int jLocal=0; jLocal<localWidth; ++jLocal ) { for( int iLocal=0; iLocal<localHeight; ++iLocal ) { const double absValue = Abs(A.GetLocal(iLocal,jLocal)); if( absValue < 1e-13 ) A.SetLocal(iLocal,jLocal,0); } } if( print ) A.Print("A with values below 1e-13 removed"); #ifdef HAVE_QT5 if( display ) Display( A, "Thresholded (1e-13) A" ); #endif } catch( ArgException& e ) { // There is nothing to do } catch( std::exception& e ) { std::ostringstream os; os << "Process " << commRank << " caught error message:\n" << e.what() << std::endl; std::cerr << os.str(); #ifndef RELEASE DumpCallStack(); #endif } Finalize(); return 0; }
inline R Row( DistMatrix<R>& chi, DistMatrix<R>& x ) { #ifndef RELEASE PushCallStack("reflector::Row"); if( chi.Grid() != x.Grid() ) throw std::logic_error ("chi and x must be distributed over the same grid"); if( chi.Height() != 1 || chi.Width() != 1 ) throw std::logic_error("chi must be a scalar"); if( x.Height() != 1 ) throw std::logic_error("x must be a row vector"); if( chi.Grid().Row() != chi.ColAlignment() ) throw std::logic_error("Reflecting with incorrect row of processes"); if( x.Grid().Row() != x.ColAlignment() ) throw std::logic_error("Reflecting with incorrect row of processes"); #endif const Grid& grid = x.Grid(); mpi::Comm rowComm = grid.RowComm(); const int gridCol = grid.Col(); const int gridWidth = grid.Width(); const int rowAlignment = chi.RowAlignment(); std::vector<R> localNorms(gridWidth); R localNorm = Nrm2( x.LockedMatrix() ); mpi::AllGather( &localNorm, 1, &localNorms[0], 1, rowComm ); R norm = blas::Nrm2( gridWidth, &localNorms[0], 1 ); if( norm == 0 ) { if( gridCol == rowAlignment ) chi.SetLocal(0,0,-chi.GetLocal(0,0)); #ifndef RELEASE PopCallStack(); #endif return R(2); } R alpha; if( gridCol == rowAlignment ) alpha = chi.GetLocal(0,0); mpi::Broadcast( &alpha, 1, rowAlignment, rowComm ); R beta; if( alpha <= 0 ) beta = lapack::SafeNorm( alpha, norm ); else beta = -lapack::SafeNorm( alpha, norm ); const R one = 1; const R safeMin = lapack::MachineSafeMin<R>(); const R epsilon = lapack::MachineEpsilon<R>(); const R safeInv = safeMin/epsilon; int count = 0; if( Abs(beta) < safeInv ) { R invOfSafeInv = one/safeInv; do { ++count; Scale( invOfSafeInv, x ); alpha *= invOfSafeInv; beta *= invOfSafeInv; } while( Abs(beta) < safeInv ); localNorm = Nrm2( x.LockedMatrix() ); mpi::AllGather( &localNorm, 1, &localNorms[0], 1, rowComm ); norm = blas::Nrm2( gridWidth, &localNorms[0], 1 ); if( alpha <= 0 ) beta = lapack::SafeNorm( alpha, norm ); else beta = -lapack::SafeNorm( alpha, norm ); } R tau = (beta-alpha)/beta; Scale( one/(alpha-beta), x ); for( int j=0; j<count; ++j ) beta *= safeInv; if( gridCol == rowAlignment ) chi.SetLocal(0,0,beta); #ifndef RELEASE PopCallStack(); #endif return tau; }
inline void PanelLU ( DistMatrix<F, STAR,STAR>& A, DistMatrix<F, MC, STAR>& B, DistMatrix<int,STAR,STAR>& p, int pivotOffset ) { #ifndef RELEASE PushCallStack("internal::PanelLU"); if( A.Grid() != p.Grid() || p.Grid() != B.Grid() ) throw std::logic_error ("Matrices must be distributed over the same grid"); if( A.Width() != B.Width() ) throw std::logic_error("A and B must be the same width"); if( A.Height() != p.Height() || p.Width() != 1 ) throw std::logic_error("p must be a vector that conforms with A"); #endif const Grid& g = A.Grid(); const int r = g.Height(); const int colShift = B.ColShift(); const int colAlignment = B.ColAlignment(); // Matrix views DistMatrix<F,STAR,STAR> ATL(g), ATR(g), A00(g), a01(g), A02(g), ABL(g), ABR(g), a10(g), alpha11(g), a12(g), A20(g), a21(g), A22(g); DistMatrix<F,MC,STAR> BL(g), BR(g), B0(g), b1(g), B2(g); const int width = A.Width(); const int numBytes = (width+1)*sizeof(F)+sizeof(int); std::vector<byte> sendData(numBytes); std::vector<byte> recvData(numBytes); // Extract pointers to send and recv data // TODO: Think of how to make this safer with respect to alignment issues F* sendBufFloat = (F*)&sendData[0]; F* recvBufFloat = (F*)&recvData[0]; int* sendBufInt = (int*)&sendData[(width+1)*sizeof(F)]; int* recvBufInt = (int*)&recvData[(width+1)*sizeof(F)]; // Start the algorithm PushBlocksizeStack( 1 ); PartitionDownDiagonal ( A, ATL, ATR, ABL, ABR, 0 ); PartitionRight( B, BL, BR, 0 ); while( ATL.Height() < A.Height() ) { RepartitionDownDiagonal ( ATL, /**/ ATR, A00, /**/ a01, A02, /*************/ /**********************/ /**/ a10, /**/ alpha11, a12, ABL, /**/ ABR, A20, /**/ a21, A22 ); RepartitionRight ( BL, /**/ BR, B0, /**/ b1, B2 ); //--------------------------------------------------------------------// const int currentRow = a01.Height(); // Store the index/value of the pivot candidate in A F pivot = alpha11.GetLocal(0,0); int pivotRow = currentRow; for( int i=0; i<a21.Height(); ++i ) { F value = a21.GetLocal(i,0); if( FastAbs(value) > FastAbs(pivot) ) { pivot = value; pivotRow = currentRow + i + 1; } } // Update the pivot candidate to include local data from B for( int i=0; i<B.LocalHeight(); ++i ) { F value = b1.GetLocal(i,0); if( FastAbs(value) > FastAbs(pivot) ) { pivot = value; pivotRow = A.Height() + colShift + i*r; } } // Fill the send buffer with: // [ pivotValue | pivot row data | pivotRow ] if( pivotRow < A.Height() ) { sendBufFloat[0] = A.GetLocal(pivotRow,a10.Width()); const int ALDim = A.LocalLDim(); const F* ABuffer = A.LocalBuffer(pivotRow,0); for( int j=0; j<width; ++j ) sendBufFloat[j+1] = ABuffer[j*ALDim]; } else { const int localRow = ((pivotRow-A.Height())-colShift)/r; sendBufFloat[0] = b1.GetLocal(localRow,0); const int BLDim = B.LocalLDim(); const F* BBuffer = B.LocalBuffer(localRow,0); for( int j=0; j<width; ++j ) sendBufFloat[j+1] = BBuffer[j*BLDim]; } *sendBufInt = pivotRow; // Communicate to establish the pivot information mpi::AllReduce ( &sendData[0], &recvData[0], numBytes, PivotOp<F>(), g.ColComm() ); // Update the pivot vector pivotRow = *recvBufInt; p.SetLocal(currentRow,0,pivotRow+pivotOffset); // Copy the current row into the pivot row if( pivotRow < A.Height() ) { const int ALDim = A.LocalLDim(); F* ASetBuffer = A.LocalBuffer(pivotRow,0); const F* AGetBuffer = A.LocalBuffer(currentRow,0); for( int j=0; j<width; ++j ) ASetBuffer[j*ALDim] = AGetBuffer[j*ALDim]; } else { const int ownerRank = (colAlignment+(pivotRow-A.Height())) % r; if( g.Row() == ownerRank ) { const int localRow = ((pivotRow-A.Height())-colShift) / r; const int ALDim = A.LocalLDim(); const int BLDim = B.LocalLDim(); F* BBuffer = B.LocalBuffer(localRow,0); const F* ABuffer = A.LocalBuffer(currentRow,0); for( int j=0; j<width; ++j ) BBuffer[j*BLDim] = ABuffer[j*ALDim]; } } // Copy the pivot row into the current row { F* ABuffer = A.LocalBuffer(currentRow,0); const int ALDim = A.LocalLDim(); for( int j=0; j<width; ++j ) ABuffer[j*ALDim] = recvBufFloat[j+1]; } // Now we can perform the update of the current panel const F alpha = alpha11.GetLocal(0,0); if( alpha == F(0) ) throw SingularMatrixException(); const F alpha11Inv = F(1) / alpha; Scale( alpha11Inv, a21.LocalMatrix() ); Scale( alpha11Inv, b1.LocalMatrix() ); Geru( F(-1), a21.LocalMatrix(), a12.LocalMatrix(), A22.LocalMatrix() ); Geru( F(-1), b1.LocalMatrix(), a12.LocalMatrix(), B2.LocalMatrix() ); //--------------------------------------------------------------------// SlidePartitionDownDiagonal ( ATL, /**/ ATR, A00, a01, /**/ A02, /**/ a10, alpha11, /**/ a12, /*************/ /**********************/ ABL, /**/ ABR, A20, a21, /**/ A22 ); SlidePartitionRight ( BL, /**/ BR, B0, b1, /**/ B2 ); } PopBlocksizeStack(); #ifndef RELEASE PopCallStack(); #endif }
int main( int argc, char* argv[] ) { Initialize( argc, argv ); try { const Int matType = Input("--matType","0:uniform,1:Haar,2:Lotkin,3:Grcar,4:FoxLi" "5:HelmholtzPML1D,6:HelmholtzPML2D",5); const Int n = Input("--size","height of matrix",100); const Real realCenter = Input("--realCenter","real center",0.); const Real imagCenter = Input("--imagCenter","imag center",0.); Real xWidth = Input("--xWidth","x width of image",0.); Real yWidth = Input("--yWidth","y width of image",0.); const Real nx = Input("--nx","num x chunks",2); const Real ny = Input("--ny","num y chunks",2); const Int xSize = Input("--xSize","number of x samples",100); const Int ySize = Input("--ySize","number of y samples",100); const bool lanczos = Input("--lanczos","use Lanczos?",true); const Int krylovSize = Input("--krylovSize","num Lanczos vectors",10); const bool reorthog = Input("--reorthog","reorthog basis?",true); const bool deflate = Input("--deflate","deflate converged?",true); const Int maxIts = Input("--maxIts","maximum two-norm iter's",1000); const Real tol = Input("--tol","tolerance for norm estimates",1e-6); const Int cutoff = Input("--cutoff","problem size for QR",256); const Int maxInnerIts = Input("--maxInnerIts","SDC limit",2); const Int maxOuterIts = Input("--maxOuterIts","SDC limit",10); const bool random = Input("--random","Random RRQR in SDC",true); const Real signTol = Input("--signTol","Sign tolerance for SDC",1e-9); const Real relTol = Input("--relTol","Rel. tol. for SDC",1e-6); const Real spreadFactor = Input("--spreadFactor","median pert.",1e-6); const Int numBands = Input("--numBands","num bands for Grcar",3); const Real omega = Input("--omega","frequency for Fox-Li/Helm",16*M_PI); const Int mx = Input("--mx","number of x points for HelmholtzPML",30); const Int my = Input("--my","number of y points for HelmholtzPML",30); const Int numPmlPoints = Input("--numPml","num PML points for Helm",5); const double sigma = Input("--sigma","PML amplitude",1.5); const double pmlExp = Input("--pmlExp","PML takeoff exponent",3.); const bool progress = Input("--progress","print progress?",true); const bool display = Input("--display","display matrices?",false); const bool write = Input("--write","write matrices?",false); const bool writePseudo = Input("--writePs","write pseudospec.",false); const Int formatInt = Input("--format","write format",2); const Int colorMapInt = Input("--colorMap","color map",0); ProcessInput(); PrintInputReport(); if( formatInt < 1 || formatInt >= FileFormat_MAX ) LogicError("Invalid file format integer, should be in [1,", FileFormat_MAX,")"); FileFormat format = static_cast<FileFormat>(formatInt); ColorMap colorMap = static_cast<ColorMap>(colorMapInt); SetColorMap( colorMap ); C center(realCenter,imagCenter); DistMatrix<C> A; switch( matType ) { case 0: Uniform( A, n, n ); break; case 1: Haar( A, n ); break; case 2: Lotkin( A, n ); break; case 3: Grcar( A, n, numBands ); break; case 4: FoxLi( A, n, omega ); break; case 5: HelmholtzPML ( A, n, C(omega), numPmlPoints, sigma, pmlExp ); break; case 6: HelmholtzPML ( A, mx, my, C(omega), numPmlPoints, sigma, pmlExp ); break; default: LogicError("Invalid matrix type"); } if( display ) Display( A, "A" ); if( write ) Write( A, "A", format ); // Begin by computing the Schur decomposition Timer timer; DistMatrix<C> X; DistMatrix<C,VR,STAR> w; mpi::Barrier( mpi::COMM_WORLD ); timer.Start(); const bool formATR = true; schur::SDC ( A, w, X, formATR, cutoff, maxInnerIts, maxOuterIts, signTol, relTol, spreadFactor, random, progress ); mpi::Barrier( mpi::COMM_WORLD ); const double sdcTime = timer.Stop(); if( mpi::WorldRank() == 0 ) std::cout << "SDC took " << sdcTime << " seconds" << std::endl; // Find a window if none is specified if( xWidth == 0. || yWidth == 0. ) { const Real radius = MaxNorm( w ); const Real oneNorm = OneNorm( A ); Real width; if( oneNorm == 0. && radius == 0. ) { width = 1; if( mpi::WorldRank() == 0 ) std::cout << "Setting width to 1 to handle zero matrix" << std::endl; } else if( radius >= 0.2*oneNorm ) { width = 2.5*radius; if( mpi::WorldRank() == 0 ) std::cout << "Setting width to " << width << " based on the spectral radius, " << radius << std::endl; } else { width = 0.8*oneNorm; if( mpi::WorldRank() == 0 ) std::cout << "Setting width to " << width << " based on the one norm, " << oneNorm << std::endl; } xWidth = width; yWidth = width; } // Visualize/write the pseudospectrum within each window DistMatrix<Real> invNormMap; DistMatrix<Int> itCountMap; const Int xBlock = xSize / nx; const Int yBlock = ySize / ny; const Int xLeftover = xSize - (nx-1)*xBlock; const Int yLeftover = ySize - (ny-1)*yBlock; const Real xStep = xWidth/(xSize-1); const Real yStep = yWidth/(ySize-1); const C corner = center - C(xWidth/2,yWidth/2); for( Int xChunk=0; xChunk<nx; ++xChunk ) { const Int xChunkSize = ( xChunk==nx-1 ? xLeftover : xBlock ); const Real xChunkWidth = xStep*xChunkSize; for( Int yChunk=0; yChunk<ny; ++yChunk ) { const Int yChunkSize = ( yChunk==ny-1 ? yLeftover : yBlock ); const Real yChunkWidth = yStep*yChunkSize; const C chunkCorner = corner + C(xStep*xChunk*xBlock,yStep*yChunk*yBlock); const C chunkCenter = chunkCorner + 0.5*C(xStep*xChunkSize,yStep*yChunkSize); mpi::Barrier( mpi::COMM_WORLD ); timer.Start(); itCountMap = TriangularPseudospectrum ( A, invNormMap, chunkCenter, xChunkWidth, yChunkWidth, xChunkSize, yChunkSize, lanczos, krylovSize, reorthog, deflate, maxIts, tol, progress ); mpi::Barrier( mpi::COMM_WORLD ); const double pseudoTime = timer.Stop(); const Int numIts = MaxNorm( itCountMap ); if( mpi::WorldRank() == 0 ) { std::cout << "num seconds=" << pseudoTime << "\n" << "num iterations=" << numIts << std::endl; } std::ostringstream chunkStream; chunkStream << "_" << xChunk << "_" << yChunk; const std::string chunkTag = chunkStream.str(); if( display ) { Display( invNormMap, "invNormMap"+chunkTag ); Display( itCountMap, "itCountMap"+chunkTag ); } if( write || writePseudo ) { Write( invNormMap, "invNormMap"+chunkTag, format ); Write( itCountMap, "itCountMap"+chunkTag, format ); } // Take the element-wise log const Int mLocal = invNormMap.LocalHeight(); const Int nLocal = invNormMap.LocalWidth(); for( Int jLoc=0; jLoc<nLocal; ++jLoc ) for( Int iLoc=0; iLoc<mLocal; ++iLoc ) invNormMap.SetLocal ( iLoc, jLoc, Log(invNormMap.GetLocal(iLoc,jLoc)) ); if( display ) { Display( invNormMap, "logInvNormMap"+chunkTag ); if( GetColorMap() != GRAYSCALE_DISCRETE ) { auto colorMap = GetColorMap(); SetColorMap( GRAYSCALE_DISCRETE ); Display( invNormMap, "discreteLogInvNormMap"+chunkTag ); SetColorMap( colorMap ); } } if( write || writePseudo ) { Write( invNormMap, "logInvNormMap"+chunkTag, format ); if( GetColorMap() != GRAYSCALE_DISCRETE ) { auto colorMap = GetColorMap(); SetColorMap( GRAYSCALE_DISCRETE ); Write ( invNormMap, "discreteLogInvNormMap"+chunkTag, format ); SetColorMap( colorMap ); } } } } } catch( exception& e ) { ReportException(e); } Finalize(); return 0; }
int main( int argc, char* argv[] ) { Environment env( argc, argv ); try { const Int n = Input("--size","size of matrix",10); const bool display = Input("--display","display matrices?",false); const bool print = Input("--print","print matrices?",true); ProcessInput(); PrintInputReport(); // Create a circulant matrix vector<C> a( n ); for( Int j=0; j<n; ++j ) a[j] = j; DistMatrix<C> A; Circulant( A, a ); if( display ) Display( A, "Circulant" ); if( print ) Print( A, "Circulant matrix:" ); // Create a Fourier matrix, which can be used to diagonalize circulant // matrices DistMatrix<C> F; Fourier( F, n ); if( display ) Display( F, "DFT matrix" ); if( print ) Print( F, "DFT matrix:" ); // Form B := A F DistMatrix<C> B; Zeros( B, n, n ); Gemm( NORMAL, NORMAL, C(1), A, F, C(0), B ); // Form A := F^H B = F^H \hat A F Gemm( ADJOINT, NORMAL, C(1), F, B, C(0), A ); if( display ) Display( A, "F^H A F" ); if( print ) Print( A, "A := F^H A F" ); // Form the thresholded result const Int localHeight = A.LocalHeight(); const Int localWidth = A.LocalWidth(); for( Int jLoc=0; jLoc<localWidth; ++jLoc ) { for( Int iLoc=0; iLoc<localHeight; ++iLoc ) { const double absValue = Abs(A.GetLocal(iLoc,jLoc)); if( absValue < 1e-13 ) A.SetLocal(iLoc,jLoc,0); } } if( display ) Display( A, "Thresholded (1e-13) A" ); if( print ) Print( A, "A with values below 1e-13 removed" ); } catch( exception& e ) { ReportException(e); } return 0; }
void TestCorrectness ( bool print, UpperOrLower uplo, const DistMatrix<double>& A, const DistMatrix<double,VR,STAR>& w, const DistMatrix<double>& Z, const DistMatrix<double>& AOrig ) { const Grid& g = A.Grid(); const int n = Z.Height(); const int k = Z.Width(); if( g.Rank() == 0 ) { cout << " Gathering computed eigenvalues..."; cout.flush(); } DistMatrix<double,MR,STAR> w_MR_STAR(g); w_MR_STAR.AlignWith( Z ); w_MR_STAR = w; if( g.Rank() == 0 ) cout << "DONE" << endl; if( g.Rank() == 0 ) cout << " Testing orthogonality of eigenvectors..." << endl; DistMatrix<double> X(g); Identity( X, k, k ); Herk( uplo, ADJOINT, -1., Z, 1., X ); double oneNormOfError = OneNorm( X ); double infNormOfError = InfinityNorm( X ); double frobNormOfError = FrobeniusNorm( X ); if( g.Rank() == 0 ) { cout << " ||Z^H Z - I||_1 = " << oneNormOfError << "\n" << " ||Z^H Z - I||_oo = " << infNormOfError << "\n" << " ||Z^H Z - I||_F = " << frobNormOfError << "\n\n" << " Testing for deviation of AZ from ZW..." << endl; } // Set X := AZ X.AlignWith( Z ); Zeros( X, n, k ); Hemm( LEFT, uplo, 1., AOrig, Z, 0., X ); // Set X := X - ZW = AZ - ZW for( int jLocal=0; jLocal<X.LocalWidth(); ++jLocal ) { const double omega = w_MR_STAR.GetLocal(jLocal,0); for( int iLocal=0; iLocal<X.LocalHeight(); ++iLocal ) { const double chi = X.GetLocal(iLocal,jLocal); const double zeta = Z.GetLocal(iLocal,jLocal); X.SetLocal(iLocal,jLocal,chi-omega*zeta); } } // Find the infinity norms of A, Z, and AZ-ZW double infNormOfA = HermitianInfinityNorm( uplo, AOrig ); double frobNormOfA = HermitianFrobeniusNorm( uplo, AOrig ); double oneNormOfZ = OneNorm( Z ); double infNormOfZ = InfinityNorm( Z ); double frobNormOfZ = FrobeniusNorm( Z ); oneNormOfError = OneNorm( X ); infNormOfError = InfinityNorm( X ); frobNormOfError = FrobeniusNorm( X ); if( g.Rank() == 0 ) { cout << " ||A||_1 = ||A||_oo = " << infNormOfA << "\n" << " ||A||_F = " << frobNormOfA << "\n" << " ||Z||_1 = " << oneNormOfZ << "\n" << " ||Z||_oo = " << infNormOfZ << "\n" << " ||Z||_F = " << frobNormOfZ << "\n" << " ||A Z - Z W||_1 = " << oneNormOfError << "\n" << " ||A Z - Z W||_oo = " << infNormOfError << "\n" << " ||A Z - Z W||_F = " << frobNormOfError << endl; } }