void EntrywiseMap ( const DistMultiVec<S>& A, DistMultiVec<T>& B, function<T(S)> func ) { DEBUG_CSE B.SetComm( A.Comm() ); B.Resize( A.Height(), A.Width() ); EntrywiseMap( A.LockedMatrix(), B.Matrix(), func ); }
Int NumOutside( const DistMultiVec<Real>& A ) { EL_DEBUG_CSE const Int localHeight = A.LocalHeight(); const Int width = A.Width(); const Real* ABuf = A.LockedMatrix().LockedBuffer(); const Int ALDim = A.LockedMatrix().LDim(); Int numLocalNonPos = 0; for( Int iLoc=0; iLoc<localHeight; ++iLoc ) for( Int j=0; j<width; ++j ) if( ABuf[iLoc+j*ALDim] <= Real(0) ) ++numLocalNonPos; return mpi::AllReduce( numLocalNonPos, A.Comm() ); }
inline void DistNodalMultiVec<F>::Pull ( const DistMap& inverseMap, const DistSymmInfo& info, const DistMultiVec<F>& X ) { DEBUG_ONLY(CallStackEntry cse("DistNodalMultiVec::Pull")) height_ = X.Height(); width_ = X.Width(); // Traverse our part of the elimination tree to see how many indices we need int numRecvInds=0; const int numLocal = info.localNodes.size(); for( int s=0; s<numLocal; ++s ) numRecvInds += info.localNodes[s].size; const int numDist = info.distNodes.size(); for( int s=1; s<numDist; ++s ) numRecvInds += info.distNodes[s].multiVecMeta.localSize; // Fill the set of indices that we need to map to the original ordering int off=0; std::vector<int> mappedInds( numRecvInds ); for( int s=0; s<numLocal; ++s ) { const SymmNodeInfo& nodeInfo = info.localNodes[s]; for( int t=0; t<nodeInfo.size; ++t ) mappedInds[off++] = nodeInfo.off+t; } for( int s=1; s<numDist; ++s ) { const DistSymmNodeInfo& nodeInfo = info.distNodes[s]; const Grid& grid = *nodeInfo.grid; const int gridSize = grid.Size(); const int gridRank = grid.VCRank(); const int alignment = 0; const int shift = Shift( gridRank, alignment, gridSize ); for( int t=shift; t<nodeInfo.size; t+=gridSize ) mappedInds[off++] = nodeInfo.off+t; } DEBUG_ONLY( if( off != numRecvInds ) LogicError("mappedInds was filled incorrectly"); )
void QP ( const DistSparseMatrix<Real>& A, const DistMultiVec<Real>& B, DistMultiVec<Real>& X, const qp::direct::Ctrl<Real>& ctrl ) { DEBUG_CSE const Int m = A.Height(); const Int n = A.Width(); const Int k = B.Width(); mpi::Comm comm = A.Comm(); DistSparseMatrix<Real> Q(comm), AHat(comm); DistMultiVec<Real> bHat(comm), c(comm); Herk( LOWER, ADJOINT, Real(1), A, Q ); MakeHermitian( LOWER, Q ); Zeros( AHat, 0, n ); Zeros( bHat, 0, 1 ); Zeros( X, n, k ); DistMultiVec<Real> q(comm), y(comm), z(comm); auto& qLoc = q.Matrix(); auto& XLoc = X.Matrix(); auto& BLoc = B.LockedMatrix(); for( Int j=0; j<k; ++j ) { auto xLoc = XLoc( ALL, IR(j) ); auto bLoc = BLoc( ALL, IR(j) ); Zeros( c, n, 1 ); Zeros( q, m, 1 ); qLoc = bLoc; Multiply( ADJOINT, Real(-1), A, q, Real(0), c ); Zeros( q, n, 1 ); qLoc = xLoc; El::QP( Q, AHat, bHat, c, q, y, z, ctrl ); xLoc = qLoc; } }
void Tikhonov ( Orientation orientation, const DistSparseMatrix<F>& A, const DistMultiVec<F>& B, const DistSparseMatrix<F>& G, DistMultiVec<F>& X, const LeastSquaresCtrl<Base<F>>& ctrl ) { DEBUG_CSE mpi::Comm comm = A.Comm(); // Explicitly form W := op(A) // ========================== DistSparseMatrix<F> W(comm); if( orientation == NORMAL ) W = A; else if( orientation == TRANSPOSE ) Transpose( A, W ); else Adjoint( A, W ); const Int m = W.Height(); const Int n = W.Width(); const Int numRHS = B.Width(); // Embed into a higher-dimensional problem via appending regularization // ==================================================================== DistSparseMatrix<F> WEmb(comm); if( m >= n ) VCat( W, G, WEmb ); else HCat( W, G, WEmb ); DistMultiVec<F> BEmb(comm); Zeros( BEmb, WEmb.Height(), numRHS ); if( m >= n ) { // BEmb := [B; 0] // -------------- const Int mLocB = B.LocalHeight(); BEmb.Reserve( mLocB*numRHS ); for( Int iLoc=0; iLoc<mLocB; ++iLoc ) { const Int i = B.GlobalRow(iLoc); for( Int j=0; j<numRHS; ++j ) BEmb.QueueUpdate( i, j, B.GetLocal(iLoc,j) ); } BEmb.ProcessQueues(); } else BEmb = B; // Solve the higher-dimensional problem // ==================================== DistMultiVec<F> XEmb(comm); LeastSquares( NORMAL, WEmb, BEmb, XEmb, ctrl ); // Extract the solution // ==================== if( m >= n ) X = XEmb; else GetSubmatrix( XEmb, IR(0,n), IR(0,numRHS), X ); }