Amesos2 - Direct Sparse Solver Interfaces  Version of the Day
Amesos2_Superlu_def.hpp
Go to the documentation of this file.
00001 // @HEADER
00002 //
00003 // ***********************************************************************
00004 //
00005 //           Amesos2: Templated Direct Sparse Solver Package
00006 //                  Copyright 2011 Sandia Corporation
00007 //
00008 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
00009 // the U.S. Government retains certain rights in this software.
00010 //
00011 // Redistribution and use in source and binary forms, with or without
00012 // modification, are permitted provided that the following conditions are
00013 // met:
00014 //
00015 // 1. Redistributions of source code must retain the above copyright
00016 // notice, this list of conditions and the following disclaimer.
00017 //
00018 // 2. Redistributions in binary form must reproduce the above copyright
00019 // notice, this list of conditions and the following disclaimer in the
00020 // documentation and/or other materials provided with the distribution.
00021 //
00022 // 3. Neither the name of the Corporation nor the names of the
00023 // contributors may be used to endorse or promote products derived from
00024 // this software without specific prior written permission.
00025 //
00026 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
00027 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00028 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00029 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
00030 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00031 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00032 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00033 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00034 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00035 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00036 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00037 //
00038 // Questions? Contact Michael A. Heroux (maherou@sandia.gov)
00039 //
00040 // ***********************************************************************
00041 //
00042 // @HEADER
00043 
00053 #ifndef AMESOS2_SUPERLU_DEF_HPP
00054 #define AMESOS2_SUPERLU_DEF_HPP
00055 
00056 #include <Teuchos_Tuple.hpp>
00057 #include <Teuchos_ParameterList.hpp>
00058 #include <Teuchos_StandardParameterEntryValidators.hpp>
00059 
00060 #include "Amesos2_SolverCore_def.hpp"
00061 #include "Amesos2_Superlu_decl.hpp"
00062 
00063 namespace Amesos2 {
00064 
00065 
00066 template <class Matrix, class Vector>
00067 Superlu<Matrix,Vector>::Superlu(
00068   Teuchos::RCP<const Matrix> A,
00069   Teuchos::RCP<Vector>       X,
00070   Teuchos::RCP<const Vector> B )
00071   : SolverCore<Amesos2::Superlu,Matrix,Vector>(A, X, B)
00072   , nzvals_()                   // initialize to empty arrays
00073   , rowind_()
00074   , colptr_()
00075 {
00076   // ilu_set_default_options is called later in set parameter list if required.
00077   // This is not the ideal way, but the other option to always call
00078   // ilu_set_default_options here and assuming it won't have any side effect
00079   // in the TPL is more dangerous. It is not a good idea to rely on external
00080   // libraries' internal "features".
00081   SLU::set_default_options(&(data_.options));
00082   // Override some default options
00083   data_.options.PrintStat = SLU::NO;
00084 
00085   SLU::StatInit(&(data_.stat));
00086 
00087   data_.perm_r.resize(this->globalNumRows_);
00088   data_.perm_c.resize(this->globalNumCols_);
00089   data_.etree.resize(this->globalNumCols_);
00090   data_.R.resize(this->globalNumRows_);
00091   data_.C.resize(this->globalNumCols_);
00092 
00093   data_.relax = SLU::sp_ienv(2); // Query optimal relax param from superlu
00094   data_.panel_size = SLU::sp_ienv(1); // Query optimal panel size
00095 
00096   data_.equed = 'N';            // No equilibration
00097   data_.A.Store = NULL;
00098   data_.L.Store = NULL;
00099   data_.U.Store = NULL;
00100   data_.X.Store = NULL;
00101   data_.B.Store = NULL;
00102   
00103   ILU_Flag_=false; // default: turn off ILU
00104 }
00105 
00106 
00107 template <class Matrix, class Vector>
00108 Superlu<Matrix,Vector>::~Superlu( )
00109 {
00110   /* Free Superlu data_types
00111    * - Matrices
00112    * - Vectors
00113    * - Stat object
00114    */
00115   SLU::StatFree( &(data_.stat) ) ;
00116 
00117   // Storage is initialized in numericFactorization_impl()
00118   if ( data_.A.Store != NULL ){
00119     SLU::Destroy_SuperMatrix_Store( &(data_.A) );
00120   }
00121 
00122   // only root allocated these SuperMatrices.
00123   if ( data_.L.Store != NULL ){ // will only be true for this->root_
00124     SLU::Destroy_SuperNode_Matrix( &(data_.L) );
00125     SLU::Destroy_CompCol_Matrix( &(data_.U) );
00126   }
00127 }
00128 
00129 template <class Matrix, class Vector>
00130 std::string
00131 Superlu<Matrix,Vector>::description() const
00132 {
00133   std::ostringstream oss;
00134   oss << "SuperLU solver interface";
00135   if (ILU_Flag_) {
00136     oss << ", \"ILUTP\" : {";
00137     oss << "drop tol = " << data_.options.ILU_DropTol;
00138     oss << ", fill factor = " << data_.options.ILU_FillFactor;
00139     oss << ", fill tol = " << data_.options.ILU_FillTol;
00140     switch(data_.options.ILU_MILU) {
00141       case SLU::SMILU_1 :
00142          oss << ", MILU 1";
00143          break;
00144       case SLU::SMILU_2  :
00145          oss << ", MILU 2";
00146          break;
00147       case SLU::SMILU_3  :
00148          oss << ", MILU 3";
00149          break;
00150       case SLU::SILU     :
00151       default:
00152          oss << ", regular ILU";
00153     }
00154     switch(data_.options.ILU_Norm) {
00155       case SLU::ONE_NORM :
00156          oss << ", 1-norm";
00157          break;
00158       case SLU::TWO_NORM  :
00159          oss << ", 2-norm";
00160          break;
00161       case SLU::INF_NORM  :
00162       default:
00163          oss << ", infinity-norm";
00164     }
00165     oss << "}";
00166   } else {
00167     oss << ", direct solve";
00168   }
00169   return oss.str();
00170   /*
00171 
00172   // ILU parameters
00173   if( parameterList->isParameter("RowPerm") ){
00174     RCP<const ParameterEntryValidator> rowperm_validator = valid_params->getEntry("RowPerm").validator();
00175     parameterList->getEntry("RowPerm").setValidator(rowperm_validator);
00176     data_.options.RowPerm = getIntegralValue<SLU::rowperm_t>(*parameterList, "RowPerm");
00177   }
00178 
00179 
00180   */
00181 }
00182 
00183 template<class Matrix, class Vector>
00184 int
00185 Superlu<Matrix,Vector>::preOrdering_impl()
00186 {
00187   /*
00188    * Get column permutation vector perm_c[], according to permc_spec:
00189    *   permc_spec = NATURAL:  natural ordering
00190    *   permc_spec = MMD_AT_PLUS_A: minimum degree on structure of A'+A
00191    *   permc_spec = MMD_ATA:  minimum degree on structure of A'*A
00192    *   permc_spec = COLAMD:   approximate minimum degree column ordering
00193    *   permc_spec = MY_PERMC: the ordering already supplied in perm_c[]
00194    */
00195   int permc_spec = data_.options.ColPerm;
00196   if ( permc_spec != SLU::MY_PERMC && this->root_ ){
00197 #ifdef HAVE_AMESOS2_TIMERS
00198     Teuchos::TimeMonitor preOrderTimer(this->timers_.preOrderTime_);
00199 #endif
00200 
00201     SLU::get_perm_c(permc_spec, &(data_.A), data_.perm_c.getRawPtr());
00202   }
00203 
00204   return(0);
00205 }
00206 
00207 
00208 template <class Matrix, class Vector>
00209 int
00210 Superlu<Matrix,Vector>::symbolicFactorization_impl()
00211 {
00212   /*
00213    * SuperLU performs symbolic factorization and numeric factorization
00214    * together, but does leave some options for reusing symbolic
00215    * structures that have been created on previous factorizations.  If
00216    * our Amesos2 user calls this function, that is an indication that
00217    * the symbolic structure of the matrix is no longer valid, and
00218    * SuperLU should do the factorization from scratch.
00219    *
00220    * This can be accomplished by setting the options.Fact flag to
00221    * DOFACT, as well as setting our own internal flag to false.
00222    */
00223   same_symbolic_ = false;
00224   data_.options.Fact = SLU::DOFACT;
00225 
00226   return(0);
00227 }
00228 
00229 
00230 template <class Matrix, class Vector>
00231 int
00232 Superlu<Matrix,Vector>::numericFactorization_impl()
00233 {
00234   using Teuchos::as;
00235 
00236   // Cleanup old L and U matrices if we are not reusing a symbolic
00237   // factorization.  Stores and other data will be allocated in gstrf.
00238   // Only rank 0 has valid pointers
00239   if ( !same_symbolic_ && data_.L.Store != NULL ){
00240     SLU::Destroy_SuperNode_Matrix( &(data_.L) );
00241     SLU::Destroy_CompCol_Matrix( &(data_.U) );
00242     data_.L.Store = NULL;
00243     data_.U.Store = NULL;
00244   }
00245 
00246   if( same_symbolic_ ) data_.options.Fact = SLU::SamePattern_SameRowPerm;
00247 
00248   int info = 0;
00249   if ( this->root_ ){
00250 
00251 #ifdef HAVE_AMESOS2_DEBUG
00252     TEUCHOS_TEST_FOR_EXCEPTION( data_.A.ncol != as<int>(this->globalNumCols_),
00253                         std::runtime_error,
00254                         "Error in converting to SuperLU SuperMatrix: wrong number of global columns." );
00255     TEUCHOS_TEST_FOR_EXCEPTION( data_.A.nrow != as<int>(this->globalNumRows_),
00256                         std::runtime_error,
00257                         "Error in converting to SuperLU SuperMatrix: wrong number of global rows." );
00258 #endif
00259 
00260     if( data_.options.Equil == SLU::YES ){
00261       magnitude_type rowcnd, colcnd, amax;
00262       int info2 = 0;
00263 
00264       // calculate row and column scalings
00265       function_map::gsequ(&(data_.A), data_.R.getRawPtr(),
00266                           data_.C.getRawPtr(), &rowcnd, &colcnd,
00267                           &amax, &info2);
00268       TEUCHOS_TEST_FOR_EXCEPTION( info2 != 0,
00269                           std::runtime_error,
00270                           "SuperLU gsequ returned with status " << info2 );
00271 
00272       // apply row and column scalings if necessary
00273       function_map::laqgs(&(data_.A), data_.R.getRawPtr(),
00274                           data_.C.getRawPtr(), rowcnd, colcnd,
00275                           amax, &(data_.equed));
00276 
00277       // // check what types of equilibration was actually done
00278       // data_.rowequ = (data_.equed == 'R') || (data_.equed == 'B');
00279       // data_.colequ = (data_.equed == 'C') || (data_.equed == 'B');
00280     }
00281 
00282     // Apply the column permutation computed in preOrdering.  Place the
00283     // column-permuted matrix in AC
00284     SLU::sp_preorder(&(data_.options), &(data_.A), data_.perm_c.getRawPtr(),
00285                      data_.etree.getRawPtr(), &(data_.AC));
00286 
00287     { // Do factorization
00288 #ifdef HAVE_AMESOS2_TIMERS
00289       Teuchos::TimeMonitor numFactTimer(this->timers_.numFactTime_);
00290 #endif
00291 
00292 #ifdef HAVE_AMESOS2_VERBOSE_DEBUG
00293       std::cout << "Superlu:: Before numeric factorization" << std::endl;
00294       std::cout << "nzvals_ : " << nzvals_.toString() << std::endl;
00295       std::cout << "rowind_ : " << rowind_.toString() << std::endl;
00296       std::cout << "colptr_ : " << colptr_.toString() << std::endl;
00297 #endif
00298 
00299       if(ILU_Flag_==false) {
00300         function_map::gstrf(&(data_.options), &(data_.AC),
00301             data_.relax, data_.panel_size, data_.etree.getRawPtr(),
00302             NULL, 0, data_.perm_c.getRawPtr(), data_.perm_r.getRawPtr(),
00303             &(data_.L), &(data_.U), &(data_.stat), &info);
00304       }
00305       else {
00306         function_map::gsitrf(&(data_.options), &(data_.AC),
00307             data_.relax, data_.panel_size, data_.etree.getRawPtr(),
00308             NULL, 0, data_.perm_c.getRawPtr(), data_.perm_r.getRawPtr(),
00309             &(data_.L), &(data_.U), &(data_.stat), &info);
00310       }
00311 
00312     }
00313     // Cleanup. AC data will be alloc'd again for next factorization (if at all)
00314     SLU::Destroy_CompCol_Permuted( &(data_.AC) );
00315 
00316     // Set the number of non-zero values in the L and U factors
00317     this->setNnzLU( as<size_t>(((SLU::SCformat*)data_.L.Store)->nnz +
00318                                ((SLU::NCformat*)data_.U.Store)->nnz) );
00319   }
00320 
00321   /* All processes should have the same error code */
00322   Teuchos::broadcast(*(this->matrixA_->getComm()), 0, &info);
00323 
00324   global_size_type info_st = as<global_size_type>(info);
00325   TEUCHOS_TEST_FOR_EXCEPTION( (info_st > 0) && (info_st <= this->globalNumCols_),
00326     std::runtime_error,
00327     "Factorization complete, but matrix is singular. Division by zero eminent");
00328   TEUCHOS_TEST_FOR_EXCEPTION( (info_st > 0) && (info_st > this->globalNumCols_),
00329     std::runtime_error,
00330     "Memory allocation failure in Superlu factorization");
00331 
00332   data_.options.Fact = SLU::FACTORED;
00333   same_symbolic_ = true;
00334 
00335   return(info);
00336 }
00337 
00338 
00339 template <class Matrix, class Vector>
00340 int
00341 Superlu<Matrix,Vector>::solve_impl(const Teuchos::Ptr<MultiVecAdapter<Vector> >       X,
00342                                    const Teuchos::Ptr<const MultiVecAdapter<Vector> > B) const
00343 {
00344   using Teuchos::as;
00345 
00346   const global_size_type ld_rhs = this->root_ ? X->getGlobalLength() : 0;
00347   const size_t nrhs = X->getGlobalNumVectors();
00348 
00349   const size_t val_store_size = as<size_t>(ld_rhs * nrhs);
00350   Teuchos::Array<slu_type> xValues(val_store_size);
00351   Teuchos::Array<slu_type> bValues(val_store_size);
00352 
00353   {                             // Get values from RHS B
00354 #ifdef HAVE_AMESOS2_TIMERS
00355     Teuchos::TimeMonitor mvConvTimer(this->timers_.vecConvTime_);
00356     Teuchos::TimeMonitor redistTimer( this->timers_.vecRedistTime_ );
00357 #endif
00358     Util::get_1d_copy_helper<MultiVecAdapter<Vector>,
00359                              slu_type>::do_get(B, bValues(),
00360                                                as<size_t>(ld_rhs),
00361                                                ROOTED, this->rowIndexBase_);
00362   }
00363 
00364   int ierr = 0; // returned error code
00365 
00366   magnitude_type rpg, rcond;
00367   if ( this->root_ ) {
00368     data_.ferr.resize(nrhs);
00369     data_.berr.resize(nrhs);
00370 
00371     {
00372 #ifdef HAVE_AMESOS2_TIMERS
00373       Teuchos::TimeMonitor mvConvTimer(this->timers_.vecConvTime_);
00374 #endif
00375       SLU::Dtype_t dtype = type_map::dtype;
00376       int i_ld_rhs = as<int>(ld_rhs);
00377       function_map::create_Dense_Matrix(&(data_.B), i_ld_rhs, as<int>(nrhs),
00378                                         bValues.getRawPtr(), i_ld_rhs,
00379                                         SLU::SLU_DN, dtype, SLU::SLU_GE);
00380       function_map::create_Dense_Matrix(&(data_.X), i_ld_rhs, as<int>(nrhs),
00381                                         xValues.getRawPtr(), i_ld_rhs,
00382                                         SLU::SLU_DN, dtype, SLU::SLU_GE);
00383     }
00384 
00385     // Note: the values of B and X (after solution) are adjusted
00386     // appropriately within gssvx for row and column scalings.
00387 
00388     {                           // Do solve!
00389 #ifdef HAVE_AMESOS2_TIMERS
00390     Teuchos::TimeMonitor solveTimer(this->timers_.solveTime_);
00391 #endif
00392 
00393     if(ILU_Flag_==false) {
00394       function_map::gssvx(&(data_.options), &(data_.A),
00395           data_.perm_c.getRawPtr(), data_.perm_r.getRawPtr(),
00396           data_.etree.getRawPtr(), &(data_.equed), data_.R.getRawPtr(),
00397           data_.C.getRawPtr(), &(data_.L), &(data_.U), NULL, 0, &(data_.B),
00398           &(data_.X), &rpg, &rcond, data_.ferr.getRawPtr(),
00399           data_.berr.getRawPtr(), &(data_.mem_usage), &(data_.stat), &ierr);
00400     }
00401     else {
00402       function_map::gsisx(&(data_.options), &(data_.A),
00403           data_.perm_c.getRawPtr(), data_.perm_r.getRawPtr(),
00404           data_.etree.getRawPtr(), &(data_.equed), data_.R.getRawPtr(),
00405           data_.C.getRawPtr(), &(data_.L), &(data_.U), NULL, 0, &(data_.B),
00406           &(data_.X), &rpg, &rcond, &(data_.mem_usage), &(data_.stat), &ierr);
00407     }
00408 
00409     }
00410 
00411     // Cleanup X and B stores
00412     SLU::Destroy_SuperMatrix_Store( &(data_.X) );
00413     SLU::Destroy_SuperMatrix_Store( &(data_.B) );
00414     data_.X.Store = NULL;
00415     data_.B.Store = NULL;
00416   }
00417 
00418   /* All processes should have the same error code */
00419   Teuchos::broadcast(*(this->getComm()), 0, &ierr);
00420 
00421   global_size_type ierr_st = as<global_size_type>(ierr);
00422   TEUCHOS_TEST_FOR_EXCEPTION( ierr < 0,
00423                       std::invalid_argument,
00424                       "Argument " << -ierr << " to SuperLU xgssvx had illegal value" );
00425   TEUCHOS_TEST_FOR_EXCEPTION( ierr > 0 && ierr_st <= this->globalNumCols_,
00426                       std::runtime_error,
00427                       "Factorization complete, but U is exactly singular" );
00428   TEUCHOS_TEST_FOR_EXCEPTION( ierr > 0 && ierr_st > this->globalNumCols_ + 1,
00429                       std::runtime_error,
00430                       "SuperLU allocated " << ierr - this->globalNumCols_ << " bytes of "
00431                       "memory before allocation failure occured." );
00432 
00433   /* Update X's global values */
00434   {
00435 #ifdef HAVE_AMESOS2_TIMERS
00436     Teuchos::TimeMonitor redistTimer(this->timers_.vecRedistTime_);
00437 #endif
00438 
00439     Util::put_1d_data_helper<
00440       MultiVecAdapter<Vector>,slu_type>::do_put(X, xValues(),
00441                                          as<size_t>(ld_rhs),
00442                                          ROOTED, this->rowIndexBase_);
00443   }
00444 
00445 
00446   return(ierr);
00447 }
00448 
00449 
00450 template <class Matrix, class Vector>
00451 bool
00452 Superlu<Matrix,Vector>::matrixShapeOK_impl() const
00453 {
00454   // The Superlu factorization routines can handle square as well as
00455   // rectangular matrices, but Superlu can only apply the solve routines to
00456   // square matrices, so we check the matrix for squareness.
00457   return( this->matrixA_->getGlobalNumRows() == this->matrixA_->getGlobalNumCols() );
00458 }
00459 
00460 
00461 template <class Matrix, class Vector>
00462 void
00463 Superlu<Matrix,Vector>::setParameters_impl(const Teuchos::RCP<Teuchos::ParameterList> & parameterList )
00464 {
00465   using Teuchos::RCP;
00466   using Teuchos::getIntegralValue;
00467   using Teuchos::ParameterEntryValidator;
00468 
00469   RCP<const Teuchos::ParameterList> valid_params = getValidParameters_impl();
00470 
00471   ILU_Flag_ = parameterList->get<bool>("ILU_Flag",false);
00472   if (ILU_Flag_) {
00473       SLU::ilu_set_default_options(&(data_.options));
00474       // Override some default options
00475       data_.options.PrintStat = SLU::NO;
00476   }
00477 
00478   data_.options.Trans = this->control_.useTranspose_ ? SLU::TRANS : SLU::NOTRANS;
00479   // The SuperLU transpose option can override the Amesos2 option
00480   if( parameterList->isParameter("Trans") ){
00481     RCP<const ParameterEntryValidator> trans_validator = valid_params->getEntry("Trans").validator();
00482     parameterList->getEntry("Trans").setValidator(trans_validator);
00483 
00484     data_.options.Trans = getIntegralValue<SLU::trans_t>(*parameterList, "Trans");
00485   }
00486 
00487   if( parameterList->isParameter("IterRefine") ){
00488     RCP<const ParameterEntryValidator> refine_validator = valid_params->getEntry("IterRefine").validator();
00489     parameterList->getEntry("IterRefine").setValidator(refine_validator);
00490 
00491     data_.options.IterRefine = getIntegralValue<SLU::IterRefine_t>(*parameterList, "IterRefine");
00492   }
00493 
00494   if( parameterList->isParameter("ColPerm") ){
00495     RCP<const ParameterEntryValidator> colperm_validator = valid_params->getEntry("ColPerm").validator();
00496     parameterList->getEntry("ColPerm").setValidator(colperm_validator);
00497 
00498     data_.options.ColPerm = getIntegralValue<SLU::colperm_t>(*parameterList, "ColPerm");
00499   }
00500 
00501   data_.options.DiagPivotThresh = parameterList->get<double>("DiagPivotThresh", 1.0);
00502 
00503   bool equil = parameterList->get<bool>("Equil", true);
00504   data_.options.Equil = equil ? SLU::YES : SLU::NO;
00505 
00506   bool symmetric_mode = parameterList->get<bool>("SymmetricMode", false);
00507   data_.options.SymmetricMode = symmetric_mode ? SLU::YES : SLU::NO;
00508 
00509   // ILU parameters
00510   if( parameterList->isParameter("RowPerm") ){
00511     RCP<const ParameterEntryValidator> rowperm_validator = valid_params->getEntry("RowPerm").validator();
00512     parameterList->getEntry("RowPerm").setValidator(rowperm_validator);
00513     data_.options.RowPerm = getIntegralValue<SLU::rowperm_t>(*parameterList, "RowPerm");
00514   }
00515 
00516   /*if( parameterList->isParameter("ILU_DropRule") ) {
00517     RCP<const ParameterEntryValidator> droprule_validator = valid_params->getEntry("ILU_DropRule").validator();
00518     parameterList->getEntry("ILU_DropRule").setValidator(droprule_validator);
00519     data_.options.ILU_DropRule = getIntegralValue<SLU::rule_t>(*parameterList, "ILU_DropRule");
00520   }*/
00521 
00522   data_.options.ILU_DropTol = parameterList->get<double>("ILU_DropTol", 0.0001);
00523 
00524   data_.options.ILU_FillFactor = parameterList->get<double>("ILU_FillFactor", 10.0);
00525 
00526   if( parameterList->isParameter("ILU_Norm") ) {
00527     RCP<const ParameterEntryValidator> norm_validator = valid_params->getEntry("ILU_Norm").validator();
00528     parameterList->getEntry("ILU_Norm").setValidator(norm_validator);
00529     data_.options.ILU_Norm = getIntegralValue<SLU::norm_t>(*parameterList, "ILU_Norm");
00530   }
00531 
00532   if( parameterList->isParameter("ILU_MILU") ) {
00533     RCP<const ParameterEntryValidator> milu_validator = valid_params->getEntry("ILU_MILU").validator();
00534     parameterList->getEntry("ILU_MILU").setValidator(milu_validator);
00535     data_.options.ILU_MILU = getIntegralValue<SLU::milu_t>(*parameterList, "ILU_MILU");
00536   }
00537 
00538   data_.options.ILU_FillTol = parameterList->get<double>("ILU_FillTol", 0.01);
00539 
00540 }
00541 
00542 
00543 template <class Matrix, class Vector>
00544 Teuchos::RCP<const Teuchos::ParameterList>
00545 Superlu<Matrix,Vector>::getValidParameters_impl() const
00546 {
00547   using std::string;
00548   using Teuchos::tuple;
00549   using Teuchos::ParameterList;
00550   using Teuchos::EnhancedNumberValidator;
00551   using Teuchos::setStringToIntegralParameter;
00552   using Teuchos::stringToIntegralParameterEntryValidator;
00553 
00554   static Teuchos::RCP<const Teuchos::ParameterList> valid_params;
00555 
00556   if( is_null(valid_params) ){
00557     Teuchos::RCP<Teuchos::ParameterList> pl = Teuchos::parameterList();
00558 
00559     setStringToIntegralParameter<SLU::trans_t>("Trans", "NOTRANS",
00560                                                "Solve for the transpose system or not",
00561                                                tuple<string>("TRANS","NOTRANS","CONJ"),
00562                                                tuple<string>("Solve with transpose",
00563                                                              "Do not solve with transpose",
00564                                                              "Solve with the conjugate transpose"),
00565                                                tuple<SLU::trans_t>(SLU::TRANS,
00566                                                                    SLU::NOTRANS,
00567                                                                    SLU::CONJ),
00568                                                pl.getRawPtr());
00569 
00570     setStringToIntegralParameter<SLU::IterRefine_t>("IterRefine", "NOREFINE",
00571                                                     "Type of iterative refinement to use",
00572                                                     tuple<string>("NOREFINE", "SLU_SINGLE", "SLU_DOUBLE"),
00573                                                     tuple<string>("Do not use iterative refinement",
00574                                                                   "Do single iterative refinement",
00575                                                                   "Do double iterative refinement"),
00576                                                     tuple<SLU::IterRefine_t>(SLU::NOREFINE,
00577                                                                              SLU::SLU_SINGLE,
00578                                                                              SLU::SLU_DOUBLE),
00579                                                     pl.getRawPtr());
00580 
00581     // Note: MY_PERMC not yet supported
00582     setStringToIntegralParameter<SLU::colperm_t>("ColPerm", "COLAMD",
00583                                                  "Specifies how to permute the columns of the "
00584                                                  "matrix for sparsity preservation",
00585                                                  tuple<string>("NATURAL", "MMD_AT_PLUS_A",
00586                                                                "MMD_ATA", "COLAMD"),
00587                                                  tuple<string>("Natural ordering",
00588                                                                "Minimum degree ordering on A^T + A",
00589                                                                "Minimum degree ordering on A^T A",
00590                                                                "Approximate minimum degree column ordering"),
00591                                                  tuple<SLU::colperm_t>(SLU::NATURAL,
00592                                                                        SLU::MMD_AT_PLUS_A,
00593                                                                        SLU::MMD_ATA,
00594                                                                        SLU::COLAMD),
00595                                                  pl.getRawPtr());
00596 
00597     Teuchos::RCP<EnhancedNumberValidator<double> > diag_pivot_thresh_validator
00598       = Teuchos::rcp( new EnhancedNumberValidator<double>(0.0, 1.0) );
00599     pl->set("DiagPivotThresh", 1.0,
00600             "Specifies the threshold used for a diagonal entry to be an acceptable pivot",
00601             diag_pivot_thresh_validator); // partial pivoting
00602 
00603     pl->set("Equil", true, "Whether to equilibrate the system before solve");
00604 
00605     pl->set("SymmetricMode", false,
00606             "Specifies whether to use the symmetric mode. "
00607             "Gives preference to diagonal pivots and uses "
00608             "an (A^T + A)-based column permutation.");
00609 
00610     // ILU parameters
00611 
00612     setStringToIntegralParameter<SLU::rowperm_t>("RowPerm", "LargeDiag",
00613             "Type of row permutation strategy to use",
00614             tuple<string>("NOROWPERM","LargeDiag","MY_PERMR"),
00615             tuple<string>("Use natural ordering",
00616             "Use weighted bipartite matching algorithm",
00617             "Use the ordering given in perm_r input"),
00618             tuple<SLU::rowperm_t>(SLU::NOROWPERM,
00619             SLU::LargeDiag,
00620             SLU::MY_PERMR),
00621             pl.getRawPtr());
00622 
00623     /*setStringToIntegralParameter<SLU::rule_t>("ILU_DropRule", "DROP_BASIC",
00624             "Type of dropping strategy to use",
00625             tuple<string>("DROP_BASIC","DROP_PROWS",
00626             "DROP_COLUMN","DROP_AREA",
00627             "DROP_DYNAMIC","DROP_INTERP"),
00628             tuple<string>("ILUTP(t)","ILUTP(p,t)",
00629             "Variant of ILUTP(p,t) for j-th column",
00630             "Variant of ILUTP to control memory",
00631             "Dynamically adjust threshold",
00632             "Compute second dropping threshold by interpolation"),
00633             tuple<SLU::rule_t>(SLU::DROP_BASIC,SLU::DROP_PROWS,SLU::DROP_COLUMN,
00634             SLU::DROP_AREA,SLU::DROP_DYNAMIC,SLU::DROP_INTERP),
00635             pl.getRawPtr());*/
00636 
00637     pl->set("ILU_DropTol", 0.0001, "ILUT drop tolerance");
00638 
00639     pl->set("ILU_FillFactor", 10.0, "ILUT fill factor");
00640 
00641     setStringToIntegralParameter<SLU::norm_t>("ILU_Norm", "INF_NORM",
00642             "Type of norm to use",
00643             tuple<string>("ONE_NORM","TWO_NORM","INF_NORM"),
00644             tuple<string>("1-norm","2-norm","inf-norm"),
00645             tuple<SLU::norm_t>(SLU::ONE_NORM,SLU::TWO_NORM,SLU::INF_NORM),
00646             pl.getRawPtr());
00647 
00648     setStringToIntegralParameter<SLU::milu_t>("ILU_MILU", "SILU",
00649             "Type of modified ILU to use",
00650             tuple<string>("SILU","SMILU_1","SMILU_2","SMILU_3"),
00651             tuple<string>("Regular ILU","MILU 1","MILU 2","MILU 3"),
00652             tuple<SLU::milu_t>(SLU::SILU,SLU::SMILU_1,SLU::SMILU_2,
00653             SLU::SMILU_3),
00654             pl.getRawPtr());
00655 
00656     pl->set("ILU_FillTol", 0.01, "ILUT fill tolerance");
00657 
00658     pl->set("ILU_Flag", false, "ILU flag: if true, run ILU routines");
00659 
00660     valid_params = pl;
00661   }
00662 
00663   return valid_params;
00664 }
00665 
00666 
00667 template <class Matrix, class Vector>
00668 bool
00669 Superlu<Matrix,Vector>::loadA_impl(EPhase current_phase)
00670 {
00671   using Teuchos::as;
00672 
00673 #ifdef HAVE_AMESOS2_TIMERS
00674   Teuchos::TimeMonitor convTimer(this->timers_.mtxConvTime_);
00675 #endif
00676 
00677   // SuperLU does not need the matrix at symbolicFactorization()
00678   if( current_phase == SYMBFACT ) return false;
00679 
00680   // Cleanup old store memory if it's non-NULL (should only ever be non-NULL at root_)
00681   if( data_.A.Store != NULL ){
00682     SLU::Destroy_SuperMatrix_Store( &(data_.A) );
00683     data_.A.Store = NULL;
00684   }
00685 
00686   // Only the root image needs storage allocated
00687   if( this->root_ ){
00688     nzvals_.resize(this->globalNumNonZeros_);
00689     rowind_.resize(this->globalNumNonZeros_);
00690     colptr_.resize(this->globalNumCols_ + 1);
00691   }
00692 
00693   int nnz_ret = 0;
00694   {
00695 #ifdef HAVE_AMESOS2_TIMERS
00696     Teuchos::TimeMonitor mtxRedistTimer( this->timers_.mtxRedistTime_ );
00697 #endif
00698 
00699     TEUCHOS_TEST_FOR_EXCEPTION( this->rowIndexBase_ != this->columnIndexBase_,
00700                         std::runtime_error,
00701                         "Row and column maps have different indexbase ");
00702     Util::get_ccs_helper<
00703     MatrixAdapter<Matrix>,slu_type,int,int>::do_get(this->matrixA_.ptr(),
00704                                                     nzvals_(), rowind_(),
00705                                                     colptr_(), nnz_ret, ROOTED,
00706                                                     ARBITRARY,
00707                                                     this->rowIndexBase_);
00708   }
00709 
00710   // Get the SLU data type for this type of matrix
00711   SLU::Dtype_t dtype = type_map::dtype;
00712 
00713   if( this->root_ ){
00714     TEUCHOS_TEST_FOR_EXCEPTION( nnz_ret != as<int>(this->globalNumNonZeros_),
00715                         std::runtime_error,
00716                         "Did not get the expected number of non-zero vals");
00717 
00718     function_map::create_CompCol_Matrix( &(data_.A),
00719                                          this->globalNumRows_, this->globalNumCols_,
00720                                          nnz_ret,
00721                                          nzvals_.getRawPtr(),
00722                                          rowind_.getRawPtr(),
00723                                          colptr_.getRawPtr(),
00724                                          SLU::SLU_NC, dtype, SLU::SLU_GE);
00725   }
00726 
00727   return true;
00728 }
00729 
00730 
00731 template<class Matrix, class Vector>
00732 const char* Superlu<Matrix,Vector>::name = "SuperLU";
00733   
00734 
00735 } // end namespace Amesos2
00736 
00737 #endif  // AMESOS2_SUPERLU_DEF_HPP