Amesos2 - Direct Sparse Solver Interfaces  Version of the Day
Amesos2_KLU2_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 
00052 #ifndef AMESOS2_KLU2_DEF_HPP
00053 #define AMESOS2_KLU2_DEF_HPP
00054 
00055 #include <Teuchos_Tuple.hpp>
00056 #include <Teuchos_ParameterList.hpp>
00057 #include <Teuchos_StandardParameterEntryValidators.hpp>
00058 
00059 #include "Amesos2_SolverCore_def.hpp"
00060 #include "Amesos2_KLU2_decl.hpp"
00061 
00062 namespace Amesos2 {
00063 
00064 
00065 template <class Matrix, class Vector>
00066 KLU2<Matrix,Vector>::KLU2(
00067   Teuchos::RCP<const Matrix> A,
00068   Teuchos::RCP<Vector>       X,
00069   Teuchos::RCP<const Vector> B )
00070   : SolverCore<Amesos2::KLU2,Matrix,Vector>(A, X, B)
00071   , nzvals_()                   // initialize to empty arrays
00072   , rowind_()
00073   , colptr_()
00074 {
00075   ::KLU2::klu_defaults<scalar_type, local_ordinal_type> (&(data_.common_)) ;
00076   data_.symbolic_ = NULL;
00077   data_.numeric_ = NULL;
00078 
00079   // Override some default options
00080   // TODO: use data_ here to init
00081 }
00082 
00083 
00084 template <class Matrix, class Vector>
00085 KLU2<Matrix,Vector>::~KLU2( )
00086 {
00087   /* Free KLU2 data_types
00088    * - Matrices
00089    * - Vectors
00090    * - Other data
00091    */
00092   if (data_.symbolic_ != NULL)
00093       ::KLU2::klu_free_symbolic<scalar_type, local_ordinal_type>
00094                          (&(data_.symbolic_), &(data_.common_)) ;
00095   if (data_.numeric_ != NULL)
00096       ::KLU2::klu_free_numeric<scalar_type, local_ordinal_type>
00097                          (&(data_.numeric_), &(data_.common_)) ;
00098 
00099   // Storage is initialized in numericFactorization_impl()
00100   //if ( data_.A.Store != NULL ){
00101       // destoy
00102   //}
00103 
00104   // only root allocated these SuperMatrices.
00105   //if ( data_.L.Store != NULL ){ // will only be true for this->root_
00106       // destroy ..
00107   //}
00108 }
00109 
00110 template<class Matrix, class Vector>
00111 int
00112 KLU2<Matrix,Vector>::preOrdering_impl()
00113 {
00114   /* TODO: Define what it means for KLU2
00115    */
00116 #ifdef HAVE_AMESOS2_TIMERS
00117     Teuchos::TimeMonitor preOrderTimer(this->timers_.preOrderTime_);
00118 #endif
00119 
00120   return(0);
00121 }
00122 
00123 
00124 template <class Matrix, class Vector>
00125 int
00126 KLU2<Matrix,Vector>::symbolicFactorization_impl()
00127 {
00128   data_.symbolic_ = ::KLU2::klu_analyze<scalar_type, local_ordinal_type>
00129                 ((local_ordinal_type)this->globalNumCols_, colptr_.getRawPtr(),
00130                  rowind_.getRawPtr(), &(data_.common_)) ;
00131 
00132 #ifdef HAVE_AMESOS2_DEBUG
00133     // TODO ": This should move to symbolic
00134     TEUCHOS_TEST_FOR_EXCEPTION( data_.A.ncol != as<int>(this->globalNumCols_),
00135     std::runtime_error,
00136     "Error in converting to KLU2 : wrong number of global columns." );
00137     TEUCHOS_TEST_FOR_EXCEPTION( data_.A.nrow != as<int>(this->globalNumRows_),
00138     std::runtime_error,
00139     "Error in converting to KLU2 SuperMatrix: wrong number of global rows." );
00140 #endif
00141 
00142   return(0);
00143 }
00144 
00145 
00146 template <class Matrix, class Vector>
00147 int
00148 KLU2<Matrix,Vector>::numericFactorization_impl()
00149 {
00150   using Teuchos::as;
00151 
00152   // Cleanup old L and U matrices if we are not reusing a symbolic
00153   // factorization.  Stores and other data will be allocated in gstrf.
00154   // Only rank 0 has valid pointers, TODO: for KLU2
00155 
00156 
00157   int info = 0;
00158   if ( this->root_ ){
00159 
00160     { // Do factorization
00161 #ifdef HAVE_AMESOS2_TIMERS
00162       Teuchos::TimeMonitor numFactTimer(this->timers_.numFactTime_);
00163 #endif
00164 
00165 #ifdef HAVE_AMESOS2_VERBOSE_DEBUG
00166       std::cout << "KLU2:: Before numeric factorization" << std::endl;
00167       std::cout << "nzvals_ : " << nzvals_.toString() << std::endl;
00168       std::cout << "rowind_ : " << rowind_.toString() << std::endl;
00169       std::cout << "colptr_ : " << colptr_.toString() << std::endl;
00170 #endif
00171 
00172     data_.numeric_ = ::KLU2::klu_factor<scalar_type, local_ordinal_type>
00173                 (colptr_.getRawPtr(), rowind_.getRawPtr(), nzvals_.getRawPtr(),
00174                 data_.symbolic_, &(data_.common_)) ;
00175 
00176     }
00177 
00178     // Set the number of non-zero values in the L and U factors // TODO
00179     //this->setNnzLU( as<size_t>(((SLU::SCformat*)data_.L.Store)->nnz +
00180                                //((SLU::NCformat*)data_.U.Store)->nnz) );
00181   }
00182 
00183   /* All processes should have the same error code */
00184   Teuchos::broadcast(*(this->matrixA_->getComm()), 0, &info);
00185 
00186   global_size_type info_st = as<global_size_type>(info);
00187   /* TODO : Proper error messages
00188   TEUCHOS_TEST_FOR_EXCEPTION( (info_st > 0) && (info_st <= this->globalNumCols_),
00189     std::runtime_error,
00190     "Factorization complete, but matrix is singular. Division by zero eminent");
00191   TEUCHOS_TEST_FOR_EXCEPTION( (info_st > 0) && (info_st > this->globalNumCols_),
00192     std::runtime_error,
00193     "Memory allocation failure in KLU2 factorization");*/
00194 
00195   //data_.options.Fact = SLU::FACTORED;
00196   //same_symbolic_ = true;
00197 
00198   return(info);
00199 }
00200 
00201 
00202 template <class Matrix, class Vector>
00203 int
00204 KLU2<Matrix,Vector>::solve_impl(
00205  const Teuchos::Ptr<MultiVecAdapter<Vector> >  X,
00206  const Teuchos::Ptr<const MultiVecAdapter<Vector> > B) const
00207 {
00208   using Teuchos::as;
00209 
00210   const global_size_type ld_rhs = this->root_ ? X->getGlobalLength() : 0;
00211   const size_t nrhs = X->getGlobalNumVectors();
00212 
00213   const size_t val_store_size = as<size_t>(ld_rhs * nrhs);
00214   Teuchos::Array<slu_type> bValues(val_store_size);
00215 
00216   {                             // Get values from RHS B
00217 #ifdef HAVE_AMESOS2_TIMERS
00218     Teuchos::TimeMonitor mvConvTimer(this->timers_.vecConvTime_);
00219     Teuchos::TimeMonitor redistTimer( this->timers_.vecRedistTime_ );
00220 #endif
00221     Util::get_1d_copy_helper<MultiVecAdapter<Vector>,
00222                              slu_type>::do_get(B, bValues(),
00223                                                as<size_t>(ld_rhs),
00224                                                ROOTED);
00225   }
00226 
00227 
00228   int ierr = 0; // returned error code
00229 
00230   magnitude_type rpg, rcond;
00231   if ( this->root_ ) {
00232 
00233     //local_ordinal_type i_ld_rhs = as<local_ordinal_type>(ld_rhs);
00234 
00235     {                           // Do solve!
00236 #ifdef HAVE_AMESOS2_TIMERS
00237     Teuchos::TimeMonitor solveTimer(this->timers_.solveTime_);
00238 #endif
00239     ::KLU2::klu_solve<scalar_type, local_ordinal_type>
00240                 (data_.symbolic_, data_.numeric_,
00241                 (local_ordinal_type)this->globalNumCols_, 
00242                 (local_ordinal_type)nrhs,
00243                 bValues.getRawPtr(),  &(data_.common_)) ;
00244 
00245     }
00246 
00247   }
00248 
00249   /* All processes should have the same error code */
00250   Teuchos::broadcast(*(this->getComm()), 0, &ierr);
00251 
00252   global_size_type ierr_st = as<global_size_type>(ierr);
00253   // TODO
00254   //TEUCHOS_TEST_FOR_EXCEPTION( ierr < 0,
00255                       //std::invalid_argument,
00256                       //"Argument " << -ierr << " to KLU2 xgssvx had illegal value" );
00257   //TEUCHOS_TEST_FOR_EXCEPTION( ierr > 0 && ierr_st <= this->globalNumCols_,
00258                       //std::runtime_error,
00259                       //"Factorization complete, but U is exactly singular" );
00260   //TEUCHOS_TEST_FOR_EXCEPTION( ierr > 0 && ierr_st > this->globalNumCols_ + 1,
00261                       //std::runtime_error,
00262                       //"KLU2 allocated " << ierr - this->globalNumCols_ << " bytes of "
00263                       //"memory before allocation failure occured." );
00264 
00265   /* Update X's global values */
00266   {
00267 #ifdef HAVE_AMESOS2_TIMERS
00268     Teuchos::TimeMonitor redistTimer(this->timers_.vecRedistTime_);
00269 #endif
00270 
00271     Util::put_1d_data_helper<
00272       MultiVecAdapter<Vector>,slu_type>::do_put(X, bValues(),
00273                                          as<size_t>(ld_rhs),
00274                                          ROOTED);
00275   }
00276 
00277 
00278   return(ierr);
00279 }
00280 
00281 
00282 template <class Matrix, class Vector>
00283 bool
00284 KLU2<Matrix,Vector>::matrixShapeOK_impl() const
00285 {
00286   // The KLU2 factorization routines can handle square as well as
00287   // rectangular matrices, but KLU2 can only apply the solve routines to
00288   // square matrices, so we check the matrix for squareness.
00289   return( this->matrixA_->getGlobalNumRows() == this->matrixA_->getGlobalNumCols() );
00290 }
00291 
00292 
00293 template <class Matrix, class Vector>
00294 void
00295 KLU2<Matrix,Vector>::setParameters_impl(const Teuchos::RCP<Teuchos::ParameterList> & parameterList )
00296 {
00297   using Teuchos::RCP;
00298   using Teuchos::getIntegralValue;
00299   using Teuchos::ParameterEntryValidator;
00300 
00301   RCP<const Teuchos::ParameterList> valid_params = getValidParameters_impl();
00302 
00303   // The KLU2 transpose option can override the Amesos2 option
00304   //if( parameterList->isParameter("Trans") ){
00305     //RCP<const ParameterEntryValidator> trans_validator = valid_params->getEntry("Trans").validator();
00306     //parameterList->getEntry("Trans").setValidator(trans_validator);
00307 
00308     //data_.options.Trans = getIntegralValue<SLU::trans_t>(*parameterList, "Trans");
00309   //}
00310 
00311 }
00312 
00313 
00314 template <class Matrix, class Vector>
00315 Teuchos::RCP<const Teuchos::ParameterList>
00316 KLU2<Matrix,Vector>::getValidParameters_impl() const
00317 {
00318   using Teuchos::ParameterList;
00319 
00320   static Teuchos::RCP<const Teuchos::ParameterList> valid_params;
00321 
00322   if( is_null(valid_params) ){
00323     Teuchos::RCP<Teuchos::ParameterList> pl = Teuchos::parameterList();
00324 
00325     pl->set("Equil", true, "Whether to equilibrate the system before solve, does nothing now");
00326 
00327     valid_params = pl;
00328   }
00329 
00330   return valid_params;
00331 }
00332 
00333 
00334 template <class Matrix, class Vector>
00335 bool
00336 KLU2<Matrix,Vector>::loadA_impl(EPhase current_phase)
00337 {
00338   using Teuchos::as;
00339 
00340 #ifdef HAVE_AMESOS2_TIMERS
00341   Teuchos::TimeMonitor convTimer(this->timers_.mtxConvTime_);
00342 #endif
00343 
00344   // Only the root image needs storage allocated
00345   if( this->root_ ){
00346     nzvals_.resize(this->globalNumNonZeros_);
00347     rowind_.resize(this->globalNumNonZeros_);
00348     colptr_.resize(this->globalNumCols_ + 1);
00349   }
00350 
00351   local_ordinal_type nnz_ret = 0;
00352   {
00353 #ifdef HAVE_AMESOS2_TIMERS
00354     Teuchos::TimeMonitor mtxRedistTimer( this->timers_.mtxRedistTime_ );
00355 #endif
00356 
00357     Util::get_ccs_helper<
00358     MatrixAdapter<Matrix>,slu_type,local_ordinal_type,local_ordinal_type>
00359     ::do_get(this->matrixA_.ptr(), nzvals_(), rowind_(), colptr_(),
00360              nnz_ret, ROOTED, ARBITRARY);
00361   }
00362 
00363 
00364   if( this->root_ ){
00365   std::cout << "nnz=" << nnz_ret << "gnnz" << this->globalNumNonZeros_ << std::endl;
00366     TEUCHOS_TEST_FOR_EXCEPTION( nnz_ret != as<local_ordinal_type>(this->globalNumNonZeros_),
00367                         std::runtime_error,
00368                         "Did not get the expected number of non-zero vals");
00369   }
00370 
00371   return true;
00372 }
00373 
00374 
00375 template<class Matrix, class Vector>
00376 const char* KLU2<Matrix,Vector>::name = "KLU2";
00377   
00378 
00379 } // end namespace Amesos2
00380 
00381 #endif  // AMESOS2_KLU2_DEF_HPP