DistMultiVec<T> DistMultiVec<T>::operator()( const vector<Int>& I, const vector<Int>& J ) const { DEBUG_ONLY(CSE cse("DistMultiVec::operator()")) DistMultiVec<T> ASub(this->Comm()); GetSubmatrix( *this, I, J, ASub ); return ASub; }
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 ); }