Ifpack2 Templated Preconditioning Package  Version 1.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends
Ifpack2_Details_DenseSolver_def.hpp
00001 /*@HEADER
00002 // ***********************************************************************
00003 //
00004 //       Ifpack2: Templated Object-Oriented Algebraic Preconditioner Package
00005 //                 Copyright (2009) Sandia Corporation
00006 //
00007 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
00008 // license for use of this work by or on behalf of the U.S. Government.
00009 //
00010 // Redistribution and use in source and binary forms, with or without
00011 // modification, are permitted provided that the following conditions are
00012 // met:
00013 //
00014 // 1. Redistributions of source code must retain the above copyright
00015 // notice, this list of conditions and the following disclaimer.
00016 //
00017 // 2. Redistributions in binary form must reproduce the above copyright
00018 // notice, this list of conditions and the following disclaimer in the
00019 // documentation and/or other materials provided with the distribution.
00020 //
00021 // 3. Neither the name of the Corporation nor the names of the
00022 // contributors may be used to endorse or promote products derived from
00023 // this software without specific prior written permission.
00024 //
00025 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
00026 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00027 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00028 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
00029 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00030 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00031 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00032 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00033 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00034 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00035 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00036 //
00037 // Questions? Contact Michael A. Heroux (maherou@sandia.gov)
00038 //
00039 // ***********************************************************************
00040 //@HEADER
00041 */
00042 
00043 #ifndef IFPACK2_DETAILS_DENSESOLVER_DEF_HPP
00044 #define IFPACK2_DETAILS_DENSESOLVER_DEF_HPP
00045 
00046 #include "Ifpack2_Condest.hpp"
00047 #include "Ifpack2_LocalFilter.hpp"
00048 #include "Teuchos_LAPACK.hpp"
00049 
00050 #ifdef HAVE_MPI
00051 #  include <mpi.h>
00052 #  include "Teuchos_DefaultMpiComm.hpp"
00053 #else
00054 #  include "Teuchos_DefaultSerialComm.hpp"
00055 #endif // HAVE_MPI
00056 
00057 
00058 namespace Ifpack2 {
00059 namespace Details {
00060 
00062 // Non-stub (full) implementation
00064 
00065 template<class MatrixType>
00066 DenseSolver<MatrixType, false>::
00067 DenseSolver (const ::Teuchos::RCP<const row_matrix_type>& A) :
00068   A_ (A),
00069   initializeTime_ (0.0),
00070   computeTime_ (0.0),
00071   applyTime_ (0.0),
00072   numInitialize_ (0),
00073   numCompute_ (0),
00074   numApply_ (0),
00075   isInitialized_ (false),
00076   isComputed_ (false)
00077 {}
00078 
00079 
00080 template<class MatrixType>
00081 ::Teuchos::RCP<const typename DenseSolver<MatrixType, false>::map_type>
00082 DenseSolver<MatrixType, false>::getDomainMap () const {
00083   TEUCHOS_TEST_FOR_EXCEPTION(
00084     A_.is_null (), std::runtime_error, "Ifpack2::Details::DenseSolver::"
00085     "getDomainMap: The input matrix A is null.  Please call setMatrix() with a "
00086     "nonnull input matrix before calling this method.");
00087   // For an input matrix A, DenseSolver solves Ax=b for x.
00088   // Thus, its Maps are reversed from those of the input matrix.
00089   return A_->getRangeMap ();
00090 }
00091 
00092 
00093 template<class MatrixType>
00094 ::Teuchos::RCP<const typename DenseSolver<MatrixType, false>::map_type>
00095 DenseSolver<MatrixType, false>::getRangeMap () const {
00096   TEUCHOS_TEST_FOR_EXCEPTION(
00097     A_.is_null (), std::runtime_error, "Ifpack2::Details::DenseSolver::"
00098     "getRangeMap: The input matrix A is null.  Please call setMatrix() with a "
00099     "nonnull input matrix before calling this method.");
00100   // For an input matrix A, DenseSolver solves Ax=b for x.
00101   // Thus, its Maps are reversed from those of the input matrix.
00102   return A_->getDomainMap ();
00103 }
00104 
00105 
00106 template<class MatrixType>
00107 void
00108 DenseSolver<MatrixType, false>::
00109 setParameters (const ::Teuchos::ParameterList& params) {
00110   (void) params; // this preconditioner doesn't currently take any parameters
00111 }
00112 
00113 
00114 template<class MatrixType>
00115 bool
00116 DenseSolver<MatrixType, false>::isInitialized () const {
00117   return isInitialized_;
00118 }
00119 
00120 
00121 template<class MatrixType>
00122 bool
00123 DenseSolver<MatrixType, false>::isComputed () const {
00124   return isComputed_;
00125 }
00126 
00127 
00128 template<class MatrixType>
00129 int
00130 DenseSolver<MatrixType, false>::getNumInitialize () const {
00131   return numInitialize_;
00132 }
00133 
00134 
00135 template<class MatrixType>
00136 int
00137 DenseSolver<MatrixType, false>::getNumCompute () const {
00138   return numCompute_;
00139 }
00140 
00141 
00142 template<class MatrixType>
00143 int
00144 DenseSolver<MatrixType, false>::getNumApply () const {
00145   return numApply_;
00146 }
00147 
00148 
00149 template<class MatrixType>
00150 double
00151 DenseSolver<MatrixType, false>::getInitializeTime () const {
00152   return initializeTime_;
00153 }
00154 
00155 
00156 template<class MatrixType>
00157 double
00158 DenseSolver<MatrixType, false>::getComputeTime () const {
00159   return computeTime_;
00160 }
00161 
00162 
00163 template<class MatrixType>
00164 double
00165 DenseSolver<MatrixType, false>::getApplyTime () const {
00166   return applyTime_;
00167 }
00168 
00169 
00170 template<class MatrixType>
00171 typename DenseSolver<MatrixType, false>::magnitude_type
00172 DenseSolver<MatrixType, false>::
00173 computeCondEst (CondestType type,
00174                 local_ordinal_type maxIters,
00175                 magnitude_type tol,
00176                 const ::Teuchos::Ptr<const row_matrix_type>& matrix)
00177 {
00178   return Ifpack2::Condest (*this, type, maxIters, tol, matrix);
00179 }
00180 
00181 
00182 template<class MatrixType>
00183 typename DenseSolver<MatrixType, false>::magnitude_type
00184 DenseSolver<MatrixType, false>::getCondEst () const {
00185   TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Not implemented");
00186 }
00187 
00188 
00189 template<class MatrixType>
00190 ::Teuchos::RCP<const typename DenseSolver<MatrixType, false>::row_matrix_type>
00191 DenseSolver<MatrixType, false>::getMatrix () const {
00192   return A_;
00193 }
00194 
00195 
00196 template<class MatrixType>
00197 void DenseSolver<MatrixType, false>::
00198 reset ()
00199 {
00200   isInitialized_ = false;
00201   isComputed_ = false;
00202   A_local_ = ::Teuchos::null;
00203   A_local_dense_.reshape (0, 0);
00204   ipiv_.resize (0);
00205 }
00206 
00207 
00208 template<class MatrixType>
00209 void DenseSolver<MatrixType, false>::
00210 setMatrix (const ::Teuchos::RCP<const row_matrix_type>& A)
00211 {
00212   // It's legitimate to call setMatrix() with a null input.  This has
00213   // the effect of resetting the preconditioner's internal state.
00214   if (! A_.is_null ()) {
00215     const global_size_t numRows = A->getRangeMap ()->getGlobalNumElements ();
00216     const global_size_t numCols = A->getDomainMap ()->getGlobalNumElements ();
00217     TEUCHOS_TEST_FOR_EXCEPTION(
00218       numRows != numCols, std::invalid_argument, "Ifpack2::Details::DenseSolver::"
00219       "setMatrix: Input matrix must be (globally) square.  "
00220       "The matrix you provided is " << numRows << " by " << numCols << ".");
00221   }
00222   // Clear any previously computed objects.
00223   reset ();
00224 
00225   // Now that we've cleared the state, we can keep the matrix.
00226   A_ = A;
00227 }
00228 
00229 
00230 template<class MatrixType>
00231 void DenseSolver<MatrixType, false>::initialize ()
00232 {
00233   using ::Teuchos::Comm;
00234   using ::Teuchos::null;
00235   using ::Teuchos::RCP;
00236   using ::Teuchos::rcp;
00237   using ::Teuchos::Time;
00238   using ::Teuchos::TimeMonitor;
00239   const std::string timerName ("Ifpack2::Details::DenseSolver::initialize");
00240 
00241   RCP<Time> timer = TimeMonitor::lookupCounter (timerName);
00242   if (timer.is_null ()) {
00243     timer = TimeMonitor::getNewCounter (timerName);
00244   }
00245 
00246   { // Begin timing here.
00247     ::Teuchos::TimeMonitor timeMon (*timer);
00248 
00249     TEUCHOS_TEST_FOR_EXCEPTION(
00250       A_.is_null (), std::runtime_error, "Ifpack2::Details::DenseSolver::"
00251       "initialize: The input matrix A is null.  Please call setMatrix() "
00252       "with a nonnull input before calling this method.");
00253 
00254     TEUCHOS_TEST_FOR_EXCEPTION(
00255       ! A_->hasColMap (), std::invalid_argument, "Ifpack2::Details::DenseSolver: "
00256       "The constructor's input matrix must have a column Map, "
00257       "so that it has local indices.");
00258 
00259     // Clear any previously computed objects.
00260     reset ();
00261 
00262     // Make the local filter of the input matrix A.
00263     if (A_->getComm ()->getSize () > 1) {
00264       A_local_ = rcp (new LocalFilter<MatrixType> (A_));
00265     } else {
00266       A_local_ = A_;
00267     }
00268 
00269     TEUCHOS_TEST_FOR_EXCEPTION(
00270       A_local_.is_null (), std::logic_error, "Ifpack2::Details::DenseSolver::"
00271       "initialize: A_local_ is null after it was supposed to have been "
00272       "initialized.  Please report this bug to the Ifpack2 developers.");
00273 
00274     // Allocate the dense local matrix and the pivot array.
00275     const size_t numRows = A_local_->getNodeNumRows ();
00276     const size_t numCols = A_local_->getNodeNumCols ();
00277     TEUCHOS_TEST_FOR_EXCEPTION(
00278       numRows != numCols, std::logic_error, "Ifpack2::Details::DenseSolver::"
00279       "initialize: Local filter matrix is not square.  This should never happen.  "
00280       "Please report this bug to the Ifpack2 developers.");
00281     A_local_dense_.reshape (numRows, numCols);
00282     ipiv_.resize (std::min (numRows, numCols));
00283     std::fill (ipiv_.begin (), ipiv_.end (), 0);
00284 
00285     isInitialized_ = true;
00286     ++numInitialize_;
00287   }
00288 
00289   // timer->totalElapsedTime() returns the total time over all timer
00290   // calls.  Thus, we use = instead of +=.
00291   initializeTime_ = timer->totalElapsedTime ();
00292 }
00293 
00294 
00295 template<class MatrixType>
00296 DenseSolver<MatrixType, false>::~DenseSolver()
00297 {}
00298 
00299 
00300 template<class MatrixType>
00301 void DenseSolver<MatrixType, false>::compute ()
00302 {
00303   using ::Teuchos::RCP;
00304   const std::string timerName ("Ifpack2::Details::DenseSolver::compute");
00305 
00306   RCP<::Teuchos::Time> timer = ::Teuchos::TimeMonitor::lookupCounter (timerName);
00307   if (timer.is_null ()) {
00308     timer = ::Teuchos::TimeMonitor::getNewCounter (timerName);
00309   }
00310 
00311   // Begin timing here.
00312   {
00313     ::Teuchos::TimeMonitor timeMon (*timer);
00314     TEUCHOS_TEST_FOR_EXCEPTION(
00315       A_.is_null (), std::runtime_error, "Ifpack2::Details::DenseSolver::"
00316       "compute: The input matrix A is null.  Please call setMatrix() with a "
00317       "nonnull input, then call initialize(), before calling this method.");
00318 
00319     TEUCHOS_TEST_FOR_EXCEPTION(
00320       A_local_.is_null (), std::logic_error, "Ifpack2::Details::DenseSolver::"
00321       "compute: A_local_ is null.  Please report this bug to the Ifpack2 "
00322       "developers.");
00323 
00324     isComputed_ = false;
00325     if (! this->isInitialized ()) {
00326       this->initialize ();
00327     }
00328     extract (A_local_dense_, *A_local_); // extract the dense local matrix
00329     factor (A_local_dense_, ipiv_ ()); // factor the dense local matrix
00330 
00331     isComputed_ = true;
00332     ++numCompute_;
00333   }
00334   // timer->totalElapsedTime() returns the total time over all timer
00335   // calls.  Thus, we use = instead of +=.
00336   computeTime_ = timer->totalElapsedTime ();
00337 }
00338 
00339 template<class MatrixType>
00340 void DenseSolver<MatrixType, false>::
00341 factor (::Teuchos::SerialDenseMatrix<int, scalar_type>& A,
00342         const ::Teuchos::ArrayView<int>& ipiv)
00343 {
00344   // Fill the LU permutation array with zeros.
00345   std::fill (ipiv.begin (), ipiv.end (), 0);
00346 
00347   ::Teuchos::LAPACK<int, scalar_type> lapack;
00348   int INFO = 0;
00349   lapack.GETRF (A.numRows (), A.numCols (), A.values (), A.stride (),
00350                 ipiv.getRawPtr (), &INFO);
00351   // INFO < 0 is a bug.
00352   TEUCHOS_TEST_FOR_EXCEPTION(
00353     INFO < 0, std::logic_error, "Ifpack2::Details::DenseSolver::factor: "
00354     "LAPACK's _GETRF (LU factorization with partial pivoting) was called "
00355     "incorrectly.  INFO = " << INFO << " < 0.  "
00356     "Please report this bug to the Ifpack2 developers.");
00357   // INFO > 0 means the matrix is singular.  This is probably an issue
00358   // either with the choice of rows the rows we extracted, or with the
00359   // input matrix itself.
00360   TEUCHOS_TEST_FOR_EXCEPTION(
00361     INFO > 0, std::runtime_error, "Ifpack2::Details::DenseSolver::factor: "
00362     "LAPACK's _GETRF (LU factorization with partial pivoting) reports that the "
00363     "computed U factor is exactly singular.  U(" << INFO << "," << INFO << ") "
00364     "(one-based index i) is exactly zero.  This probably means that the input "
00365     "matrix has a singular diagonal block.");
00366 }
00367 
00368 
00369 template<class MatrixType>
00370 void DenseSolver<MatrixType, false>::
00371 applyImpl (const MV& X,
00372            MV& Y,
00373            const ::Teuchos::ETransp mode,
00374            const scalar_type alpha,
00375            const scalar_type beta) const
00376 {
00377   using ::Teuchos::ArrayRCP;
00378   using ::Teuchos::RCP;
00379   using ::Teuchos::rcp;
00380   using ::Teuchos::rcpFromRef;
00381   using ::Teuchos::CONJ_TRANS;
00382   using ::Teuchos::TRANS;
00383 
00384   const int numVecs = static_cast<int> (X.getNumVectors ());
00385   if (alpha == STS::zero ()) { // don't need to solve the linear system
00386     if (beta == STS::zero ()) {
00387       // Use BLAS AXPY semantics for beta == 0: overwrite, clobbering
00388       // any Inf or NaN values in Y (rather than multiplying them by
00389       // zero, resulting in NaN values).
00390       Y.putScalar (STS::zero ());
00391     }
00392     else { // beta != 0
00393       Y.scale (STS::zero ());
00394     }
00395   }
00396   else { // alpha != 0; must solve the linear system
00397     ::Teuchos::LAPACK<int, scalar_type> lapack;
00398     // If beta is nonzero, Y is not constant stride, or alpha != 1, we
00399     // have to use a temporary output multivector Y_tmp.  It gets a
00400     // copy of alpha*X, since GETRS overwrites its (multi)vector input
00401     // with its output.
00402     RCP<MV> Y_tmp;
00403     if (beta == STS::zero () && Y.isConstantStride () && alpha == STS::one ()) {
00404       deep_copy (Y, X);
00405       Y_tmp = rcpFromRef (Y);
00406     }
00407     else {
00408       Y_tmp = rcp (new MV (X, ::Teuchos::Copy)); // constructor copies X
00409       if (alpha != STS::one ()) {
00410         Y_tmp->scale (alpha);
00411       }
00412     }
00413     const int Y_stride = static_cast<int> (Y_tmp->getStride ());
00414     ArrayRCP<scalar_type> Y_view = Y_tmp->get1dViewNonConst ();
00415     scalar_type* const Y_ptr = Y_view.getRawPtr ();
00416     int INFO = 0;
00417     const char trans =
00418       (mode == CONJ_TRANS ? 'C' : (mode == TRANS ? 'T' : 'N'));
00419     lapack.GETRS (trans, A_local_dense_.numRows (), numVecs,
00420                   A_local_dense_.values (), A_local_dense_.stride (),
00421                   ipiv_.getRawPtr (), Y_ptr, Y_stride, &INFO);
00422     TEUCHOS_TEST_FOR_EXCEPTION(
00423       INFO != 0, std::runtime_error, "Ifpack2::Details::DenseSolver::"
00424       "applyImpl: LAPACK's _GETRS (solve using LU factorization with "
00425       "partial pivoting) failed with INFO = " << INFO << " != 0.");
00426 
00427     if (beta != STS::zero ()) {
00428       Y.update (alpha, *Y_tmp, beta);
00429     }
00430     else if (! Y.isConstantStride ()) {
00431       deep_copy (Y, *Y_tmp);
00432     }
00433   }
00434 }
00435 
00436 
00437 template<class MatrixType>
00438 void DenseSolver<MatrixType, false>::
00439 apply (const Tpetra::MultiVector<scalar_type,local_ordinal_type,global_ordinal_type,node_type>& X,
00440        Tpetra::MultiVector<scalar_type,local_ordinal_type,global_ordinal_type,node_type>& Y,
00441        ::Teuchos::ETransp mode,
00442        scalar_type alpha,
00443        scalar_type beta) const
00444 {
00445   using ::Teuchos::ArrayView;
00446   using ::Teuchos::as;
00447   using ::Teuchos::RCP;
00448   using ::Teuchos::rcp;
00449   using ::Teuchos::rcpFromRef;
00450 
00451   const std::string timerName ("Ifpack2::Details::DenseSolver::apply");
00452   RCP<::Teuchos::Time> timer = ::Teuchos::TimeMonitor::lookupCounter (timerName);
00453   if (timer.is_null ()) {
00454     timer = ::Teuchos::TimeMonitor::getNewCounter (timerName);
00455   }
00456 
00457   // Begin timing here.
00458   {
00459     ::Teuchos::TimeMonitor timeMon (*timer);
00460 
00461     TEUCHOS_TEST_FOR_EXCEPTION(
00462       ! isComputed_, std::runtime_error, "Ifpack2::Details::DenseSolver::apply: "
00463       "You must have called the compute() method before you may call apply().  "
00464       "You may call the apply() method as many times as you want after calling "
00465       "compute() once, but you must have called compute() at least once.");
00466 
00467     const size_t numVecs = X.getNumVectors ();
00468 
00469     TEUCHOS_TEST_FOR_EXCEPTION(
00470       numVecs != Y.getNumVectors (), std::runtime_error,
00471       "Ifpack2::Details::DenseSolver::apply: X and Y have different numbers "
00472       "of vectors.  X has " << X.getNumVectors () << ", but Y has "
00473       << X.getNumVectors () << ".");
00474 
00475     if (numVecs == 0) {
00476       return; // done! nothing to do
00477     }
00478 
00479     // Set up "local" views of X and Y.
00480     RCP<const MV> X_local;
00481     RCP<MV> Y_local;
00482     const bool multipleProcs = (A_->getRowMap ()->getComm ()->getSize () >= 1);
00483     if (multipleProcs) {
00484       // Interpret X and Y as "local" multivectors, that is, in the
00485       // local filter's domain resp. range Maps.  "Interpret" means that
00486       // we create views with different Maps; we don't have to copy.
00487       X_local = X.offsetView (A_local_->getDomainMap (), 0);
00488       Y_local = Y.offsetViewNonConst (A_local_->getRangeMap (), 0);
00489     }
00490     else { // only one process in A_'s communicator
00491       // X and Y are already "local"; no need to set up local views.
00492       X_local = rcpFromRef (X);
00493       Y_local = rcpFromRef (Y);
00494     }
00495 
00496     // Apply the local operator:
00497     // Y_local := beta*Y_local + alpha*M^{-1}*X_local
00498     this->applyImpl (*X_local, *Y_local, mode, alpha, beta);
00499 
00500     ++numApply_; // We've successfully finished the work of apply().
00501   }
00502 
00503   // timer->totalElapsedTime() returns the total time over all timer
00504   // calls.  Thus, we use = instead of +=.
00505   applyTime_ = timer->totalElapsedTime ();
00506 }
00507 
00508 
00509 template<class MatrixType>
00510 std::string
00511 DenseSolver<MatrixType, false>::description () const
00512 {
00513   std::ostringstream out;
00514 
00515   // Output is a valid YAML dictionary in flow style.  If you don't
00516   // like everything on a single line, you should call describe()
00517   // instead.
00518   out << "\"Ifpack2::Details::DenseSolver\": ";
00519   out << "{";
00520   if (this->getObjectLabel () != "") {
00521     out << "Label: \"" << this->getObjectLabel () << "\", ";
00522   }
00523   out << "Initialized: " << (isInitialized () ? "true" : "false") << ", "
00524       << "Computed: " << (isComputed () ? "true" : "false") << ", ";
00525 
00526   if (A_.is_null ()) {
00527     out << "Matrix: null";
00528   }
00529   else {
00530     out << "Matrix: not null"
00531         << ", Global matrix dimensions: ["
00532         << A_->getGlobalNumRows () << ", " << A_->getGlobalNumCols () << "]";
00533   }
00534 
00535   out << "}";
00536   return out.str ();
00537 }
00538 
00539 
00540 template<class MatrixType>
00541 void DenseSolver<MatrixType, false>::
00542 describeLocal (::Teuchos::FancyOStream& out,
00543                const ::Teuchos::EVerbosityLevel verbLevel) const
00544 {
00545   using ::Teuchos::FancyOStream;
00546   using ::Teuchos::OSTab;
00547   using ::Teuchos::RCP;
00548   using ::Teuchos::rcpFromRef;
00549   using std::endl;
00550 
00551   if (verbLevel == ::Teuchos::VERB_NONE) {
00552     return;
00553   }
00554   else {
00555     RCP<FancyOStream> ptrOut = rcpFromRef (out);
00556     OSTab tab1 (ptrOut);
00557     if (this->getObjectLabel () != "") {
00558       out << "label: " << this->getObjectLabel () << endl;
00559     }
00560     out << "initialized: " << (isInitialized_ ? "true" : "false") << endl
00561         << "computed: " << (isComputed_ ? "true" : "false") << endl
00562         << "number of initialize calls: " << numInitialize_ << endl
00563         << "number of compute calls: " << numCompute_ << endl
00564         << "number of apply calls: " << numApply_ << endl
00565         << "total time in seconds in initialize: " << initializeTime_ << endl
00566         << "total time in seconds in compute: " << computeTime_ << endl
00567         << "total time in seconds in apply: " << applyTime_ << endl;
00568     if (verbLevel >= ::Teuchos::VERB_EXTREME) {
00569       out << "A_local_dense_:" << endl;
00570       {
00571         OSTab tab2 (ptrOut);
00572         out << "[";
00573         for (int i = 0; i < A_local_dense_.numRows (); ++i) {
00574           for (int j = 0; j < A_local_dense_.numCols (); ++j) {
00575             out << A_local_dense_(i,j);
00576             if (j + 1 < A_local_dense_.numCols ()) {
00577               out << ", ";
00578             }
00579           }
00580           if (i + 1 < A_local_dense_.numRows ()) {
00581             out << ";" << endl;
00582           }
00583         }
00584         out << "]" << endl;
00585       }
00586       out << "ipiv_: " << ::Teuchos::toString (ipiv_) << endl;
00587     }
00588   }
00589 }
00590 
00591 
00592 template<class MatrixType>
00593 void DenseSolver<MatrixType, false>::
00594 describe (::Teuchos::FancyOStream& out,
00595           const ::Teuchos::EVerbosityLevel verbLevel) const
00596 {
00597   using ::Teuchos::FancyOStream;
00598   using ::Teuchos::OSTab;
00599   using ::Teuchos::RCP;
00600   using ::Teuchos::rcpFromRef;
00601   using std::endl;
00602 
00603   RCP<FancyOStream> ptrOut = rcpFromRef (out);
00604   OSTab tab0 (ptrOut);
00605   if (A_.is_null ()) {
00606     // If A_ is null, we don't have a communicator, so we can't
00607     // safely print local data on all processes.  Just print the
00608     // local data without arbitration between processes, and hope
00609     // for the best.
00610     if (verbLevel > ::Teuchos::VERB_NONE) {
00611       out << "Ifpack2::Details::DenseSolver:" << endl;
00612     }
00613     describeLocal (out, verbLevel);
00614   }
00615   else {
00616     // If A_ is not null, we have a communicator, so we can
00617     // arbitrate among all processes to print local data.
00618     const ::Teuchos::Comm<int>& comm = * (A_->getRowMap ()->getComm ());
00619     const int myRank = comm.getRank ();
00620     const int numProcs = comm.getSize ();
00621     if (verbLevel > ::Teuchos::VERB_NONE && myRank == 0) {
00622       out << "Ifpack2::Details::DenseSolver:" << endl;
00623     }
00624     OSTab tab1 (ptrOut);
00625     for (int p = 0; p < numProcs; ++p) {
00626       if (myRank == p) {
00627         out << "Process " << myRank << ":" << endl;
00628         describeLocal (out, verbLevel);
00629       }
00630       comm.barrier ();
00631       comm.barrier ();
00632       comm.barrier ();
00633     } // for p = 0 .. numProcs-1
00634   }
00635 }
00636 
00637 
00638 template<class MatrixType>
00639 void DenseSolver<MatrixType, false>::
00640 extract (::Teuchos::SerialDenseMatrix<int, scalar_type>& A_local_dense,
00641          const row_matrix_type& A_local)
00642 {
00643   using ::Teuchos::Array;
00644   using ::Teuchos::ArrayView;
00645   typedef local_ordinal_type LO;
00646   typedef typename ::Teuchos::ArrayView<LO>::size_type size_type;
00647 
00648   // Fill the local dense matrix with zeros.
00649   A_local_dense.putScalar (STS::zero ());
00650 
00651   //
00652   // Map both row and column indices to local indices.  We can use the
00653   // row Map's local indices for row indices, and the column Map's
00654   // local indices for column indices.  It doesn't really matter;
00655   // either way is just a permutation of rows and columns.
00656   //
00657   const map_type& rowMap = * (A_local.getRowMap ());
00658 
00659   // Temporary arrays to hold the indices and values of the entries in
00660   // each row of A_local.
00661   const size_type maxNumRowEntries =
00662     static_cast<size_type> (A_local.getNodeMaxNumRowEntries ());
00663   Array<LO> localIndices (maxNumRowEntries);
00664   Array<scalar_type> values (maxNumRowEntries);
00665 
00666   const LO numLocalRows = static_cast<LO> (rowMap.getNodeNumElements ());
00667   const LO minLocalRow = rowMap.getMinLocalIndex ();
00668   // This slight complication of computing the upper loop bound avoids
00669   // issues if the row Map has zero entries on the calling process.
00670   const LO maxLocalRow = minLocalRow + numLocalRows; // exclusive bound
00671   for (LO localRow = minLocalRow; localRow < maxLocalRow; ++localRow) {
00672     // The LocalFilter automatically excludes "off-process" entries.
00673     // That means all the column indices in this row belong to the
00674     // domain Map.  We can, therefore, just use the local row and
00675     // column indices to put each entry directly in the dense matrix.
00676     // It's OK if the column Map puts the local indices in a different
00677     // order; the Import will bring them into the correct order.
00678     const size_type numEntriesInRow =
00679       static_cast<size_type> (A_local.getNumEntriesInLocalRow (localRow));
00680     size_t numEntriesOut = 0; // ignored
00681     A_local.getLocalRowCopy (localRow,
00682                              localIndices (0, numEntriesInRow),
00683                              values (0, numEntriesInRow),
00684                              numEntriesOut);
00685     for (LO k = 0; k < numEntriesInRow; ++k) {
00686       const LO localCol = localIndices[k];
00687       const scalar_type val = values[k];
00688       // We use += instead of =, in case there are duplicate entries
00689       // in the row.  There should not be, but why not be general?
00690       A_local_dense(localRow, localCol) += val;
00691     }
00692   }
00693 }
00694 
00696 // Stub implementation
00698 
00699 template<class MatrixType>
00700 DenseSolver<MatrixType, true>::
00701 DenseSolver (const ::Teuchos::RCP<const row_matrix_type>& A) {
00702   TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Not implemented");
00703 }
00704 
00705 
00706 template<class MatrixType>
00707 ::Teuchos::RCP<const typename DenseSolver<MatrixType, true>::map_type>
00708 DenseSolver<MatrixType, true>::getDomainMap () const {
00709   TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Not implemented");
00710 }
00711 
00712 
00713 template<class MatrixType>
00714 ::Teuchos::RCP<const typename DenseSolver<MatrixType, true>::map_type>
00715 DenseSolver<MatrixType, true>::getRangeMap () const {
00716   TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Not implemented");
00717 }
00718 
00719 
00720 template<class MatrixType>
00721 void
00722 DenseSolver<MatrixType, true>::
00723 setParameters (const ::Teuchos::ParameterList& params) {
00724   TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Not implemented");
00725 }
00726 
00727 
00728 template<class MatrixType>
00729 bool
00730 DenseSolver<MatrixType, true>::isInitialized () const {
00731   TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Not implemented");
00732 }
00733 
00734 
00735 template<class MatrixType>
00736 bool
00737 DenseSolver<MatrixType, true>::isComputed () const {
00738   TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Not implemented");
00739 }
00740 
00741 
00742 template<class MatrixType>
00743 int
00744 DenseSolver<MatrixType, true>::getNumInitialize () const {
00745   TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Not implemented");
00746 }
00747 
00748 
00749 template<class MatrixType>
00750 int
00751 DenseSolver<MatrixType, true>::getNumCompute () const {
00752   TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Not implemented");
00753 }
00754 
00755 
00756 template<class MatrixType>
00757 int
00758 DenseSolver<MatrixType, true>::getNumApply () const {
00759   TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Not implemented");
00760 }
00761 
00762 
00763 template<class MatrixType>
00764 double
00765 DenseSolver<MatrixType, true>::getInitializeTime () const {
00766   TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Not implemented");
00767 }
00768 
00769 
00770 template<class MatrixType>
00771 double
00772 DenseSolver<MatrixType, true>::getComputeTime () const {
00773   TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Not implemented");
00774 }
00775 
00776 
00777 template<class MatrixType>
00778 double
00779 DenseSolver<MatrixType, true>::getApplyTime () const {
00780   TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Not implemented");
00781 }
00782 
00783 
00784 template<class MatrixType>
00785 typename DenseSolver<MatrixType, true>::magnitude_type
00786 DenseSolver<MatrixType, true>::
00787 computeCondEst (CondestType CT,
00788                 local_ordinal_type MaxIters,
00789                 magnitude_type Tol,
00790                 const ::Teuchos::Ptr<const row_matrix_type>& Matrix)
00791 {
00792   TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Not implemented");
00793 }
00794 
00795 
00796 template<class MatrixType>
00797 typename DenseSolver<MatrixType, true>::magnitude_type
00798 DenseSolver<MatrixType, true>::getCondEst () const {
00799   TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Not implemented");
00800 }
00801 
00802 
00803 template<class MatrixType>
00804 ::Teuchos::RCP<const typename DenseSolver<MatrixType, true>::row_matrix_type>
00805 DenseSolver<MatrixType, true>::getMatrix () const {
00806   TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Not implemented");
00807 }
00808 
00809 
00810 template<class MatrixType>
00811 void DenseSolver<MatrixType, true>::
00812 setMatrix (const ::Teuchos::RCP<const row_matrix_type>& A)
00813 {
00814   TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Not implemented");
00815 }
00816 
00817 
00818 template<class MatrixType>
00819 void DenseSolver<MatrixType, true>::initialize ()
00820 {
00821   TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Not implemented");
00822 }
00823 
00824 
00825 template<class MatrixType>
00826 DenseSolver<MatrixType, true>::~DenseSolver ()
00827 {
00828   // Destructors should never throw exceptions.
00829 }
00830 
00831 
00832 template<class MatrixType>
00833 void DenseSolver<MatrixType, true>::compute ()
00834 {
00835   TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Not implemented");
00836 }
00837 
00838 
00839 template<class MatrixType>
00840 void DenseSolver<MatrixType, true>::
00841 apply (const Tpetra::MultiVector<scalar_type,local_ordinal_type,global_ordinal_type,node_type>& X,
00842        Tpetra::MultiVector<scalar_type,local_ordinal_type,global_ordinal_type,node_type>& Y,
00843        ::Teuchos::ETransp mode,
00844        scalar_type alpha,
00845        scalar_type beta) const
00846 {
00847   TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Not implemented");
00848 }
00849 
00850 
00851 template<class MatrixType>
00852 std::string
00853 DenseSolver<MatrixType, true>::description () const
00854 {
00855   TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Not implemented");
00856 }
00857 
00858 
00859 template<class MatrixType>
00860 void DenseSolver<MatrixType, true>::
00861 describe (::Teuchos::FancyOStream& out,
00862           const ::Teuchos::EVerbosityLevel verbLevel) const
00863 {
00864   TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Not implemented");
00865 }
00866 
00867 
00868 } // namespace Details
00869 } // namespace Ifpack2
00870 
00871 #define IFPACK2_DETAILS_DENSESOLVER_INSTANT(S,LO,GO,N)                  \
00872   template class Ifpack2::Details::DenseSolver< Tpetra::CrsMatrix<S, LO, GO, N> >; \
00873   template class Ifpack2::Details::DenseSolver< Tpetra::RowMatrix<S, LO, GO, N> >;
00874 
00875 #endif // IFPACK2_DETAILS_DENSESOLVER_HPP
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends