Ifpack2 Templated Preconditioning Package  Version 1.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends
Ifpack2_Details_TriDiSolver_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_TRIDISOLVER_DEF_HPP
00044 #define IFPACK2_DETAILS_TRIDISOLVER_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 TriDiSolver<MatrixType, false>::
00067 TriDiSolver (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 TriDiSolver<MatrixType, false>::map_type>
00082 TriDiSolver<MatrixType, false>::getDomainMap () const {
00083   TEUCHOS_TEST_FOR_EXCEPTION(
00084     A_.is_null (), std::runtime_error, "Ifpack2::Details::TriDiSolver::"
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, TriDiSolver 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 TriDiSolver<MatrixType, false>::map_type>
00095 TriDiSolver<MatrixType, false>::getRangeMap () const {
00096   TEUCHOS_TEST_FOR_EXCEPTION(
00097     A_.is_null (), std::runtime_error, "Ifpack2::Details::TriDiSolver::"
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, TriDiSolver 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 TriDiSolver<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 TriDiSolver<MatrixType, false>::isInitialized () const {
00117   return isInitialized_;
00118 }
00119 
00120 
00121 template<class MatrixType>
00122 bool
00123 TriDiSolver<MatrixType, false>::isComputed () const {
00124   return isComputed_;
00125 }
00126 
00127 
00128 template<class MatrixType>
00129 int
00130 TriDiSolver<MatrixType, false>::getNumInitialize () const {
00131   return numInitialize_;
00132 }
00133 
00134 
00135 template<class MatrixType>
00136 int
00137 TriDiSolver<MatrixType, false>::getNumCompute () const {
00138   return numCompute_;
00139 }
00140 
00141 
00142 template<class MatrixType>
00143 int
00144 TriDiSolver<MatrixType, false>::getNumApply () const {
00145   return numApply_;
00146 }
00147 
00148 
00149 template<class MatrixType>
00150 double
00151 TriDiSolver<MatrixType, false>::getInitializeTime () const {
00152   return initializeTime_;
00153 }
00154 
00155 
00156 template<class MatrixType>
00157 double
00158 TriDiSolver<MatrixType, false>::getComputeTime () const {
00159   return computeTime_;
00160 }
00161 
00162 
00163 template<class MatrixType>
00164 double
00165 TriDiSolver<MatrixType, false>::getApplyTime () const {
00166   return applyTime_;
00167 }
00168 
00169 
00170 template<class MatrixType>
00171 typename TriDiSolver<MatrixType, false>::magnitude_type
00172 TriDiSolver<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 TriDiSolver<MatrixType, false>::magnitude_type
00184 TriDiSolver<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 TriDiSolver<MatrixType, false>::row_matrix_type>
00191 TriDiSolver<MatrixType, false>::getMatrix () const {
00192   return A_;
00193 }
00194 
00195 
00196 template<class MatrixType>
00197 void TriDiSolver<MatrixType, false>::
00198 reset ()
00199 {
00200   isInitialized_ = false;
00201   isComputed_ = false;
00202   A_local_ = Teuchos::null;
00203   A_local_tridi_.reshape (0);
00204   ipiv_.resize (0);
00205 }
00206 
00207 
00208 template<class MatrixType>
00209 void TriDiSolver<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::TriDiSolver::"
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 TriDiSolver<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::TriDiSolver::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::TriDiSolver::"
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::TriDiSolver: "
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::TriDiSolver::"
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 TriDi 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::TriDiSolver::"
00279       "initialize: Local filter matrix is not square.  This should never happen.  "
00280       "Please report this bug to the Ifpack2 developers.");
00281     A_local_tridi_.reshape (numRows);
00282     ipiv_.resize (numRows);
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 TriDiSolver<MatrixType, false>::~TriDiSolver()
00297 {}
00298 
00299 
00300 template<class MatrixType>
00301 void TriDiSolver<MatrixType, false>::compute ()
00302 {
00303   using Teuchos::RCP;
00304   const std::string timerName ("Ifpack2::Details::TriDiSolver::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::TriDiSolver::"
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::TriDiSolver::"
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_tridi_, *A_local_); // extract the tridi local matrix
00329 
00330     factor (A_local_tridi_, ipiv_ ()); // factor the tridi local matrix
00331 
00332     isComputed_ = true;
00333     ++numCompute_;
00334   }
00335   // timer->totalElapsedTime() returns the total time over all timer
00336   // calls.  Thus, we use = instead of +=.
00337   computeTime_ = timer->totalElapsedTime ();
00338 }
00339 
00340 template<class MatrixType>
00341 void TriDiSolver<MatrixType, false>::factor (Teuchos::SerialTriDiMatrix<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.GTTRF (A.numRowsCols (),
00350     A.DL(),
00351     A.D(),
00352     A.DU(),
00353     A.DU2(),
00354                 ipiv.getRawPtr (), &INFO);
00355   // INFO < 0 is a bug.
00356   TEUCHOS_TEST_FOR_EXCEPTION(
00357     INFO < 0, std::logic_error, "Ifpack2::Details::TriDiSolver::factor: "
00358     "LAPACK's _GETRF (LU factorization with partial pivoting) was called "
00359     "incorrectly.  INFO = " << INFO << " < 0.  "
00360     "Please report this bug to the Ifpack2 developers.");
00361   // INFO > 0 means the matrix is singular.  This is probably an issue
00362   // either with the choice of rows the rows we extracted, or with the
00363   // input matrix itself.
00364   TEUCHOS_TEST_FOR_EXCEPTION(
00365     INFO > 0, std::runtime_error, "Ifpack2::Details::TriDiSolver::factor: "
00366     "LAPACK's _GETRF (LU factorization with partial pivoting) reports that the "
00367     "computed U factor is exactly singular.  U(" << INFO << "," << INFO << ") "
00368     "(one-based index i) is exactly zero.  This probably means that the input "
00369     "matrix has a singular diagonal block.");
00370 }
00371 
00372 
00373 template<class MatrixType>
00374 void TriDiSolver<MatrixType, false>::
00375 applyImpl (const MV& X,
00376            MV& Y,
00377            const Teuchos::ETransp mode,
00378            const scalar_type alpha,
00379            const scalar_type beta) const
00380 {
00381   using Teuchos::ArrayRCP;
00382   using Teuchos::RCP;
00383   using Teuchos::rcp;
00384   using Teuchos::rcpFromRef;
00385   using Teuchos::CONJ_TRANS;
00386   using Teuchos::TRANS;
00387 
00388   const int numVecs = static_cast<int> (X.getNumVectors ());
00389   if (alpha == STS::zero ()) { // don't need to solve the linear system
00390     if (beta == STS::zero ()) {
00391       // Use BLAS AXPY semantics for beta == 0: overwrite, clobbering
00392       // any Inf or NaN values in Y (rather than multiplying them by
00393       // zero, resulting in NaN values).
00394       Y.putScalar (STS::zero ());
00395     }
00396     else { // beta != 0
00397       Y.scale (STS::zero ());
00398     }
00399   }
00400   else { // alpha != 0; must solve the linear system
00401     Teuchos::LAPACK<int, scalar_type> lapack;
00402     // If beta is nonzero, Y is not constant stride, or alpha != 1, we
00403     // have to use a temporary output multivector Y_tmp.  It gets a
00404     // copy of alpha*X, since GETRS overwrites its (multi)vector input
00405     // with its output.
00406     RCP<MV> Y_tmp;
00407     if (beta == STS::zero () && Y.isConstantStride () && alpha == STS::one ()) {
00408       deep_copy(Y, X);
00409       Y_tmp = rcpFromRef (Y);
00410     }
00411     else {
00412       Y_tmp = rcp (new MV (createCopy(X))); // constructor copies X
00413       if (alpha != STS::one ()) {
00414         Y_tmp->scale (alpha);
00415       }
00416     }
00417     const int Y_stride = static_cast<int> (Y_tmp->getStride ());
00418     ArrayRCP<scalar_type> Y_view = Y_tmp->get1dViewNonConst ();
00419     scalar_type* const Y_ptr = Y_view.getRawPtr ();
00420     int INFO = 0;
00421     const char trans =
00422       (mode == CONJ_TRANS ? 'C' : (mode == TRANS ? 'T' : 'N'));
00423     lapack.GTTRS (trans, A_local_tridi_.numRowsCols(), numVecs,
00424       A_local_tridi_.DL(),
00425       A_local_tridi_.D(),
00426       A_local_tridi_.DU(),
00427       A_local_tridi_.DU2(),    
00428                   ipiv_.getRawPtr (), Y_ptr, Y_stride, &INFO);
00429     TEUCHOS_TEST_FOR_EXCEPTION(
00430       INFO != 0, std::runtime_error, "Ifpack2::Details::TriDiSolver::"
00431       "applyImpl: LAPACK's _GTTRS (solve using LU factorization with "
00432       "partial pivoting) failed with INFO = " << INFO << " != 0.");
00433 
00434     if (beta != STS::zero ()) {
00435       Y.update (alpha, *Y_tmp, beta);
00436     }
00437     else if (! Y.isConstantStride ()) {
00438       deep_copy(Y, *Y_tmp);
00439     }
00440   }
00441 }
00442 
00443 
00444 template<class MatrixType>
00445 void TriDiSolver<MatrixType, false>::
00446 apply (const Tpetra::MultiVector<scalar_type,local_ordinal_type,global_ordinal_type,node_type>& X,
00447        Tpetra::MultiVector<scalar_type,local_ordinal_type,global_ordinal_type,node_type>& Y,
00448        Teuchos::ETransp mode,
00449        scalar_type alpha,
00450        scalar_type beta) const
00451 {
00452   using Teuchos::ArrayView;
00453   using Teuchos::as;
00454   using Teuchos::RCP;
00455   using Teuchos::rcp;
00456   using Teuchos::rcpFromRef;
00457 
00458   const std::string timerName ("Ifpack2::Details::TriDiSolver::apply");
00459   RCP<Teuchos::Time> timer = Teuchos::TimeMonitor::lookupCounter (timerName);
00460   if (timer.is_null ()) {
00461     timer = Teuchos::TimeMonitor::getNewCounter (timerName);
00462   }
00463 
00464   // Begin timing here.
00465   {
00466     Teuchos::TimeMonitor timeMon (*timer);
00467 
00468     TEUCHOS_TEST_FOR_EXCEPTION(
00469       ! isComputed_, std::runtime_error, "Ifpack2::Details::TriDiSolver::apply: "
00470       "You must have called the compute() method before you may call apply().  "
00471       "You may call the apply() method as many times as you want after calling "
00472       "compute() once, but you must have called compute() at least once.");
00473 
00474     const size_t numVecs = X.getNumVectors ();
00475 
00476     TEUCHOS_TEST_FOR_EXCEPTION(
00477       numVecs != Y.getNumVectors (), std::runtime_error,
00478       "Ifpack2::Details::TriDiSolver::apply: X and Y have different numbers "
00479       "of vectors.  X has " << X.getNumVectors () << ", but Y has "
00480       << X.getNumVectors () << ".");
00481 
00482     if (numVecs == 0) {
00483       return; // done! nothing to do
00484     }
00485 
00486     // Set up "local" views of X and Y.
00487     RCP<const MV> X_local;
00488     RCP<MV> Y_local;
00489     const bool multipleProcs = (A_->getRowMap ()->getComm ()->getSize () >= 1);
00490     if (multipleProcs) {
00491       // Interpret X and Y as "local" multivectors, that is, in the
00492       // local filter's domain resp. range Maps.  "Interpret" means that
00493       // we create views with different Maps; we don't have to copy.
00494       X_local = X.offsetView (A_local_->getDomainMap (), 0);
00495       Y_local = Y.offsetViewNonConst (A_local_->getRangeMap (), 0);
00496     }
00497     else { // only one process in A_'s communicator
00498       // X and Y are already "local"; no need to set up local views.
00499       X_local = rcpFromRef (X);
00500       Y_local = rcpFromRef (Y);
00501     }
00502 
00503     // Apply the local operator:
00504     // Y_local := beta*Y_local + alpha*M^{-1}*X_local
00505     this->applyImpl (*X_local, *Y_local, mode, alpha, beta);
00506 
00507     ++numApply_; // We've successfully finished the work of apply().
00508   }
00509 
00510   // timer->totalElapsedTime() returns the total time over all timer
00511   // calls.  Thus, we use = instead of +=.
00512   applyTime_ = timer->totalElapsedTime ();
00513 }
00514 
00515 
00516 template<class MatrixType>
00517 std::string TriDiSolver<MatrixType, false>::description () const
00518 {
00519   std::ostringstream out;
00520 
00521   // Output is a valid YAML dictionary in flow style.  If you don't
00522   // like everything on a single line, you should call describe()
00523   // instead.
00524   out << "\"Ifpack2::Details::TriDiSolver\": ";
00525   out << "{";
00526   if (this->getObjectLabel () != "") {
00527     out << "Label: \"" << this->getObjectLabel () << "\", ";
00528   }
00529   out << "Initialized: " << (isInitialized () ? "true" : "false") << ", "
00530       << "Computed: " << (isComputed () ? "true" : "false") << ", ";
00531 
00532   if (A_.is_null ()) {
00533     out << "Matrix: null";
00534   }
00535   else {
00536     out << "Matrix: not null"
00537         << ", Global matrix dimensions: ["
00538         << A_->getGlobalNumRows () << ", " << A_->getGlobalNumCols () << "]";
00539   }
00540 
00541   out << "}";
00542   return out.str ();
00543 }
00544 
00545 
00546 template<class MatrixType>
00547 void TriDiSolver<MatrixType, false>::describeLocal (Teuchos::FancyOStream& out, 
00548                 const Teuchos::EVerbosityLevel verbLevel) const {
00549   using Teuchos::FancyOStream;
00550   using Teuchos::OSTab;
00551   using Teuchos::RCP;
00552   using Teuchos::rcpFromRef;
00553   using std::endl;
00554 
00555   if (verbLevel == Teuchos::VERB_NONE) {
00556     return;
00557   }
00558   else {
00559     RCP<FancyOStream> ptrOut = rcpFromRef (out);
00560     OSTab tab1 (ptrOut);
00561     if (this->getObjectLabel () != "") {
00562       out << "label: " << this->getObjectLabel () << endl;
00563     }
00564     out << "initialized: " << (isInitialized_ ? "true" : "false") << endl
00565         << "computed: " << (isComputed_ ? "true" : "false") << endl
00566         << "number of initialize calls: " << numInitialize_ << endl
00567         << "number of compute calls: " << numCompute_ << endl
00568         << "number of apply calls: " << numApply_ << endl
00569         << "total time in seconds in initialize: " << initializeTime_ << endl
00570         << "total time in seconds in compute: " << computeTime_ << endl
00571         << "total time in seconds in apply: " << applyTime_ << endl;
00572     if (verbLevel >= Teuchos::VERB_EXTREME) {
00573       out << "A_local_tridi_:" << endl;
00574       A_local_tridi_.print(out);
00575       }
00576       out << "ipiv_: " << Teuchos::toString (ipiv_) << endl;
00577     }
00578 }
00579 
00580 template<class MatrixType>
00581 void TriDiSolver<MatrixType, false>::describe (Teuchos::FancyOStream& out,
00582           const Teuchos::EVerbosityLevel verbLevel) const
00583 {
00584   using Teuchos::FancyOStream;
00585   using Teuchos::OSTab;
00586   using Teuchos::RCP;
00587   using Teuchos::rcpFromRef;
00588   using std::endl;
00589 
00590   RCP<FancyOStream> ptrOut = rcpFromRef (out);
00591   OSTab tab0 (ptrOut);
00592   if (A_.is_null ()) {
00593     // If A_ is null, we don't have a communicator, so we can't
00594     // safely print local data on all processes.  Just print the
00595     // local data without arbitration between processes, and hope
00596     // for the best.
00597     if (verbLevel > Teuchos::VERB_NONE) {
00598       out << "Ifpack2::Details::TriDiSolver:" << endl;
00599     }
00600     describeLocal (out, verbLevel);
00601   }
00602   else {
00603     // If A_ is not null, we have a communicator, so we can
00604     // arbitrate among all processes to print local data.
00605     const Teuchos::Comm<int>& comm = * (A_->getRowMap ()->getComm ());
00606     const int myRank = comm.getRank ();
00607     const int numProcs = comm.getSize ();
00608     if (verbLevel > Teuchos::VERB_NONE && myRank == 0) {
00609       out << "Ifpack2::Details::TriDiSolver:" << endl;
00610     }
00611     OSTab tab1 (ptrOut);
00612     for (int p = 0; p < numProcs; ++p) {
00613       if (myRank == p) {
00614         out << "Process " << myRank << ":" << endl;
00615         describeLocal (out, verbLevel);
00616       }
00617       comm.barrier ();
00618       comm.barrier ();
00619       comm.barrier ();
00620     } // for p = 0 .. numProcs-1
00621   }
00622 }
00623 
00624 template<class MatrixType>
00625 void TriDiSolver<MatrixType, false>::extract (Teuchos::SerialTriDiMatrix<int, scalar_type>& A_local_tridi,
00626          const row_matrix_type& A_local)
00627 {
00628   using Teuchos::Array;
00629   using Teuchos::ArrayView;
00630   typedef local_ordinal_type LO;
00631   typedef typename Teuchos::ArrayView<LO>::size_type size_type;
00632 
00633   // Fill the local tridi matrix with zeros.
00634   A_local_tridi.putScalar (STS::zero ());
00635 
00636   //
00637   // Map both row and column indices to local indices.  We can use the
00638   // row Map's local indices for row indices, and the column Map's
00639   // local indices for column indices.  It doesn't really matter;
00640   // either way is just a permutation of rows and columns.
00641   //
00642   const map_type& rowMap = * (A_local.getRowMap ());
00643 
00644   // Temporary arrays to hold the indices and values of the entries in
00645   // each row of A_local.
00646   const size_type maxNumRowEntries =
00647     static_cast<size_type> (A_local.getNodeMaxNumRowEntries ());
00648   Array<LO> localIndices (maxNumRowEntries);
00649   Array<scalar_type> values (maxNumRowEntries);
00650 
00651   const LO numLocalRows = static_cast<LO> (rowMap.getNodeNumElements ());
00652   const LO minLocalRow = rowMap.getMinLocalIndex ();
00653   // This slight complication of computing the upper loop bound avoids
00654   // issues if the row Map has zero entries on the calling process.
00655   const LO maxLocalRow = minLocalRow + numLocalRows; // exclusive bound
00656   for (LO localRow = minLocalRow; localRow < maxLocalRow; ++localRow) {
00657     // The LocalFilter automatically excludes "off-process" entries.
00658     // That means all the column indices in this row belong to the
00659     // domain Map.  We can, therefore, just use the local row and
00660     // column indices to put each entry directly in the tridi matrix.
00661     // It's OK if the column Map puts the local indices in a different
00662     // order; the Import will bring them into the correct order.
00663     const size_type numEntriesInRow =
00664       static_cast<size_type> (A_local.getNumEntriesInLocalRow (localRow));
00665     size_t numEntriesOut = 0; // ignored
00666     A_local.getLocalRowCopy (localRow,
00667                              localIndices (0, numEntriesInRow),
00668                              values (0, numEntriesInRow),
00669                              numEntriesOut);
00670     for (LO k = 0; k < numEntriesInRow; ++k) {
00671       const LO localCol = localIndices[k];
00672       const scalar_type val = values[k];
00673       // We use += instead of =, in case there are duplicate entries
00674       // in the row.  There should not be, but why not be general?
00675       // NOTE: we only extract the TriDi part of the row matrix. Do not extract DU2
00676       if( localCol >= localRow-1 && localCol <= localRow+1 ) 
00677   A_local_tridi(localRow, localCol) += val;
00678     }
00679   }
00680 }
00681 
00683 // Stub implementation
00685 
00686 template<class MatrixType>
00687 TriDiSolver<MatrixType, true>::TriDiSolver (const Teuchos::RCP<const row_matrix_type>& A) {
00688   TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Not implemented");
00689 }
00690 
00691 
00692 template<class MatrixType>
00693 Teuchos::RCP<const typename TriDiSolver<MatrixType, true>::map_type>
00694 TriDiSolver<MatrixType, true>::getDomainMap () const {
00695   TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Not implemented");
00696 }
00697 
00698 
00699 template<class MatrixType>
00700 Teuchos::RCP<const typename TriDiSolver<MatrixType, true>::map_type>
00701 TriDiSolver<MatrixType, true>::getRangeMap () const {
00702   TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Not implemented");
00703 }
00704 
00705 
00706 template<class MatrixType>
00707 void
00708 TriDiSolver<MatrixType, true>::setParameters (const Teuchos::ParameterList& params) {
00709   TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Not implemented");
00710 }
00711 
00712 
00713 template<class MatrixType>
00714 bool
00715 TriDiSolver<MatrixType, true>::isInitialized () const {
00716   TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Not implemented");
00717 }
00718 
00719 
00720 template<class MatrixType>
00721 bool
00722 TriDiSolver<MatrixType, true>::isComputed () const {
00723   TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Not implemented");
00724 }
00725 
00726 
00727 template<class MatrixType>
00728 int
00729 TriDiSolver<MatrixType, true>::getNumInitialize () const {
00730   TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Not implemented");
00731 }
00732 
00733 
00734 template<class MatrixType>
00735 int
00736 TriDiSolver<MatrixType, true>::getNumCompute () const {
00737   TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Not implemented");
00738 }
00739 
00740 
00741 template<class MatrixType>
00742 int
00743 TriDiSolver<MatrixType, true>::getNumApply () const {
00744   TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Not implemented");
00745 }
00746 
00747 
00748 template<class MatrixType>
00749 double
00750 TriDiSolver<MatrixType, true>::getInitializeTime () const {
00751   TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Not implemented");
00752 }
00753 
00754 
00755 template<class MatrixType>
00756 double
00757 TriDiSolver<MatrixType, true>::getComputeTime () const {
00758   TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Not implemented");
00759 }
00760 
00761 
00762 template<class MatrixType>
00763 double
00764 TriDiSolver<MatrixType, true>::getApplyTime () const {
00765   TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Not implemented");
00766 }
00767 
00768 
00769 template<class MatrixType>
00770 typename TriDiSolver<MatrixType, true>::magnitude_type
00771 TriDiSolver<MatrixType, true>::computeCondEst (CondestType CT,
00772                 local_ordinal_type MaxIters,
00773                 magnitude_type Tol,
00774                 const Teuchos::Ptr<const row_matrix_type>& Matrix)
00775 {
00776   TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Not implemented");
00777 }
00778 
00779 
00780 template<class MatrixType>
00781 typename TriDiSolver<MatrixType, true>::magnitude_type
00782 TriDiSolver<MatrixType, true>::getCondEst () const {
00783   TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Not implemented");
00784 }
00785 
00786 
00787 template<class MatrixType>
00788 Teuchos::RCP<const typename TriDiSolver<MatrixType, true>::row_matrix_type>
00789 TriDiSolver<MatrixType, true>::getMatrix () const {
00790   TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Not implemented");
00791 }
00792 
00793 
00794 template<class MatrixType>
00795 void TriDiSolver<MatrixType, true>::setMatrix (const Teuchos::RCP<const row_matrix_type>& A)
00796 {
00797   TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Not implemented");
00798 }
00799 
00800 
00801 template<class MatrixType>
00802 void TriDiSolver<MatrixType, true>::initialize ()
00803 {
00804   TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Not implemented");
00805 }
00806 
00807 
00808 template<class MatrixType>
00809 TriDiSolver<MatrixType, true>::~TriDiSolver ()
00810 {
00811   // Destructors should never throw exceptions.
00812 }
00813 
00814 
00815 template<class MatrixType>
00816 void TriDiSolver<MatrixType, true>::compute ()
00817 {
00818   TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Not implemented");
00819 }
00820 
00821 
00822 template<class MatrixType>
00823 void TriDiSolver<MatrixType, true>::apply (
00824        const Tpetra::MultiVector<scalar_type,local_ordinal_type,global_ordinal_type,node_type>& X,
00825        Tpetra::MultiVector<scalar_type,local_ordinal_type,global_ordinal_type,node_type>& Y,
00826        Teuchos::ETransp mode,
00827        scalar_type alpha,
00828        scalar_type beta) const
00829 {
00830   TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Not implemented");
00831 }
00832 
00833 
00834 template<class MatrixType>
00835 std::string
00836 TriDiSolver<MatrixType, true>::description () const
00837 {
00838   TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Not implemented");
00839 }
00840 
00841 
00842 template<class MatrixType>
00843 void TriDiSolver<MatrixType, true>::describe(Teuchos::FancyOStream& out,
00844                                               const Teuchos::EVerbosityLevel verbLevel) const
00845 {
00846   TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Not implemented");
00847 }
00848 
00849 }// namespace Details
00850 } // namespace Ifpack2
00851 
00852 #define IFPACK2_DETAILS_TRIDISOLVER_INSTANT(S,LO,GO,N)                  \
00853   template class Ifpack2::Details::TriDiSolver< Tpetra::CrsMatrix<S, LO, GO, N> >; \
00854   template class Ifpack2::Details::TriDiSolver< Tpetra::RowMatrix<S, LO, GO, N> >;
00855 
00856 #endif // IFPACK2_DETAILS_TRIDISOLVER_HPP
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends