Amesos2 - Direct Sparse Solver Interfaces  Version of the Day
Amesos2_Cholmod_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_CHOLMOD_DEF_HPP
00054 #define AMESOS2_CHOLMOD_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_Cholmod_decl.hpp"
00062 
00063 
00064 namespace Amesos2 {
00065 
00066 
00067 template <class Matrix, class Vector>
00068 Cholmod<Matrix,Vector>::Cholmod(
00069   Teuchos::RCP<const Matrix> A,
00070   Teuchos::RCP<Vector>       X,
00071   Teuchos::RCP<const Vector> B )
00072   : SolverCore<Amesos2::Cholmod,Matrix,Vector>(A, X, B)
00073   , nzvals_()                   // initialize to empty arrays
00074   , rowind_()
00075   , colptr_()
00076   , firstsolve(true)
00077   , map()
00078 {
00079   CHOL::cholmod_start(&data_.c);
00080   (&data_.c)->nmethods=9;
00081   (&data_.c)->quick_return_if_not_posdef=1;
00082 
00083   //(&data_.c)->method[0].ordering=CHOLMOD_NATURAL;
00084   //(&data_.c)->print=5;
00085   data_.Y = NULL;
00086   data_.E = NULL;
00087 }
00088 
00089 
00090 template <class Matrix, class Vector>
00091 Cholmod<Matrix,Vector>::~Cholmod( )
00092 {
00093   CHOL::cholmod_free_factor (&(data_.L), &(data_.c));
00094 
00095   CHOL::cholmod_free_dense(&(data_.Y), &data_.c);
00096   CHOL::cholmod_free_dense(&(data_.E), &data_.c);
00097 
00098   CHOL::cholmod_finish(&(data_.c));
00099 }
00100 
00101 template<class Matrix, class Vector>
00102 int
00103 Cholmod<Matrix,Vector>::preOrdering_impl()
00104 {
00105  #ifdef HAVE_AMESOS2_TIMERS
00106     Teuchos::TimeMonitor preOrderTimer(this->timers_.preOrderTime_);
00107 #endif
00108     data_.L = CHOL::cholmod_analyze (&data_.A, &(data_.c));
00109     //data_.L->is_super=1;
00110     data_.L->is_ll=1;
00111 
00112     skip_symfact = true;
00113   
00114   return(0);
00115 }
00116 
00117 
00118 template <class Matrix, class Vector>
00119 int
00120 Cholmod<Matrix,Vector>::symbolicFactorization_impl()
00121 {
00122   if ( !skip_symfact ){
00123 #ifdef HAVE_AMESOS2_TIMERS
00124       Teuchos::TimeMonitor symFactTimer(this->timers_.symFactTime_);
00125 #endif
00126       CHOL::cholmod_resymbol (&data_.A, NULL, 0, true, data_.L, &(data_.c));
00127     } else {
00128       /*
00129        * Symbolic factorization has already occured in preOrdering_impl,
00130        * but if the user calls this routine directly later, we need to
00131        * redo the symbolic factorization.
00132        */
00133       skip_symfact = false;
00134     }
00135   
00136   return(0);
00137 }
00138 
00139 
00140 template <class Matrix, class Vector>
00141 int
00142 Cholmod<Matrix,Vector>::numericFactorization_impl()
00143 {
00144   using Teuchos::as;
00145 
00146   int info = 0;
00147   
00148 #ifdef HAVE_AMESOS2_DEBUG
00149     TEUCHOS_TEST_FOR_EXCEPTION(data_.A.ncol != as<size_t>(this->globalNumCols_),
00150              std::runtime_error,
00151              "Error in converting to cholmod_sparse: wrong number of global columns." );
00152     TEUCHOS_TEST_FOR_EXCEPTION(data_.A.nrow != as<size_t>(this->globalNumRows_),
00153              std::runtime_error,
00154              "Error in converting to cholmod_sparse: wrong number of global rows." );
00155 #endif
00156 
00157     { // Do factorization
00158 #ifdef HAVE_AMESOS2_TIMERS
00159       Teuchos::TimeMonitor numFactTimer(this->timers_.numFactTime_);
00160 #endif
00161 
00162 #ifdef HAVE_AMESOS2_VERBOSE_DEBUG
00163       std::cout << "Cholmod:: Before numeric factorization" << std::endl;
00164       std::cout << "nzvals_ : " << nzvals_.toString() << std::endl;
00165       std::cout << "rowind_ : " << rowind_.toString() << std::endl;
00166       std::cout << "colptr_ : " << colptr_.toString() << std::endl;
00167 #endif
00168       //cholmod_print_sparse(data_.A,"A",&(data_.c));
00169       CHOL::cholmod_factorize(&data_.A, data_.L, &(data_.c));
00170       //cholmod_print_factor(data_.L,"L",&(data_.c));
00171       info = (&data_.c)->status;
00172       
00173     }
00174     
00175   
00176 
00177   /* All processes should have the same error code */
00178   Teuchos::broadcast(*(this->matrixA_->getComm()), 0, &info);
00179 
00180   TEUCHOS_TEST_FOR_EXCEPTION(info == 2,
00181            std::runtime_error,
00182            "Memory allocation failure in Cholmod factorization");
00183 
00184   return(info);
00185 }
00186 
00187 
00188 template <class Matrix, class Vector>
00189 int
00190 Cholmod<Matrix,Vector>::solve_impl(const Teuchos::Ptr<MultiVecAdapter<Vector> >       X,
00191                                    const Teuchos::Ptr<const MultiVecAdapter<Vector> > B) const
00192 {
00193   using Teuchos::as;
00194 
00195   const global_size_type ld_rhs = X->getGlobalLength();
00196   const size_t nrhs = X->getGlobalNumVectors();
00197   
00198   Teuchos::RCP<const Tpetra::Map<local_ordinal_type,
00199     global_ordinal_type, node_type> > map2;
00200 
00201   const size_t val_store_size = as<size_t>(ld_rhs * nrhs);
00202   Teuchos::Array<chol_type> xValues(val_store_size);
00203   Teuchos::Array<chol_type> bValues(val_store_size);
00204 
00205   {                             // Get values from RHS B
00206 #ifdef HAVE_AMESOS2_TIMERS
00207     Teuchos::TimeMonitor mvConvTimer(this->timers_.vecConvTime_);
00208     Teuchos::TimeMonitor redistTimer( this->timers_.vecRedistTime_ );
00209 #endif
00210     Util::get_1d_copy_helper<MultiVecAdapter<Vector>,
00211                              chol_type>::do_get(B, bValues(),
00212             as<size_t>(ld_rhs),
00213             ROOTED, this->rowIndexBase_);
00214       
00215   }
00216 
00217   
00218   int ierr = 0; // returned error code
00219 
00220     {
00221 #ifdef HAVE_AMESOS2_TIMERS
00222       Teuchos::TimeMonitor mvConvTimer(this->timers_.vecConvTime_);
00223 #endif
00224 
00225       function_map::cholmod_init_dense(as<int>(this->globalNumRows_),
00226                as<int>(nrhs), as<int>(ld_rhs),
00227                bValues.getRawPtr(), &data_.b);
00228       function_map::cholmod_init_dense(as<int>(this->globalNumRows_),
00229                as<int>(nrhs), as<int>(ld_rhs),
00230                xValues.getRawPtr(), &data_.x);
00231     }
00232 
00233 
00234     {                           // Do solve!
00235 #ifdef HAVE_AMESOS2_TIMERS
00236       Teuchos::TimeMonitor solveTimer(this->timers_.solveTime_);
00237 #endif
00238 
00239       CHOL::cholmod_dense *xtemp = &(data_.x);
00240       
00241       CHOL::cholmod_solve2(CHOLMOD_A, data_.L, &data_.b, NULL,
00242          &xtemp, NULL, &data_.Y, &data_.E, &data_.c);
00243       
00244       ierr = (&data_.c)->status;
00245     }
00246   
00247 
00248   
00249   /* All processes should have the same error code */
00250   Teuchos::broadcast(*(this->getComm()), 0, &ierr);
00251 
00252   TEUCHOS_TEST_FOR_EXCEPTION(ierr == -2, std::runtime_error, "Ran out of memory" );
00253 
00254   /* Update X's global values */
00255   {
00256 #ifdef HAVE_AMESOS2_TIMERS
00257     Teuchos::TimeMonitor redistTimer(this->timers_.vecRedistTime_);
00258 #endif
00259     
00260     Util::put_1d_data_helper<
00261       MultiVecAdapter<Vector>,chol_type>::do_put(X, xValues(),
00262              as<size_t>(ld_rhs),
00263              ROOTED, this->rowIndexBase_);
00264     
00265   }
00266 
00267   
00268   return(ierr);
00269 }
00270 
00271 
00272 template <class Matrix, class Vector>
00273 bool
00274 Cholmod<Matrix,Vector>::matrixShapeOK_impl() const
00275 {
00276   return( this->matrixA_->getGlobalNumRows() == this->matrixA_->getGlobalNumCols() );
00277 }
00278 
00279 
00280 template <class Matrix, class Vector>
00281 void
00282 Cholmod<Matrix,Vector>::setParameters_impl(const Teuchos::RCP<Teuchos::ParameterList> & parameterList )
00283 {
00284   using Teuchos::RCP;
00285   using Teuchos::getIntegralValue;
00286   using Teuchos::ParameterEntryValidator;
00287 
00288   RCP<const Teuchos::ParameterList> valid_params = getValidParameters_impl();
00289 
00290 
00291   if( parameterList->isParameter("Trans") ){
00292     RCP<const ParameterEntryValidator> trans_validator = valid_params->getEntry("Trans").validator();
00293     parameterList->getEntry("Trans").setValidator(trans_validator);
00294 
00295   }
00296 
00297   if( parameterList->isParameter("IterRefine") ){
00298     RCP<const ParameterEntryValidator> refine_validator = valid_params->getEntry("IterRefine").validator();
00299     parameterList->getEntry("IterRefine").setValidator(refine_validator);
00300 
00301 
00302   }
00303 
00304   if( parameterList->isParameter("ColPerm") ){
00305     RCP<const ParameterEntryValidator> colperm_validator = valid_params->getEntry("ColPerm").validator();
00306     parameterList->getEntry("ColPerm").setValidator(colperm_validator);
00307 
00308 
00309   }
00310 
00311   (&data_.c)->dbound = parameterList->get<double>("dbound", 0.0);
00312 
00313   bool prefer_upper = parameterList->get<bool>("PreferUpper", true);
00314   
00315   (&data_.c)->prefer_upper = prefer_upper ? 1 : 0;
00316 
00317   (&data_.c)->print = parameterList->get<int>("print",3);
00318 
00319   (&data_.c)->nmethods = parameterList->get<int>("nmethods",0);
00320 
00321 }
00322 
00323 
00324 template <class Matrix, class Vector>
00325 Teuchos::RCP<const Teuchos::ParameterList>
00326 Cholmod<Matrix,Vector>::getValidParameters_impl() const
00327 {
00328   using std::string;
00329   using Teuchos::tuple;
00330   using Teuchos::ParameterList;
00331   using Teuchos::EnhancedNumberValidator;
00332   using Teuchos::setStringToIntegralParameter;
00333   using Teuchos::stringToIntegralParameterEntryValidator;
00334 
00335   static Teuchos::RCP<const Teuchos::ParameterList> valid_params;
00336 
00337   if( is_null(valid_params) ){
00338     Teuchos::RCP<Teuchos::ParameterList> pl = Teuchos::parameterList();
00339 
00340 
00341     Teuchos::RCP<EnhancedNumberValidator<int> > print_validator
00342       = Teuchos::rcp( new EnhancedNumberValidator<int>(0,5));
00343 
00344     Teuchos::RCP<EnhancedNumberValidator<int> > nmethods_validator
00345       = Teuchos::rcp( new EnhancedNumberValidator<int>(0,9));
00346 
00347     pl->set("nmethods", 0, "Specifies the number of different ordering methods to try", nmethods_validator);
00348 
00349     pl->set("print", 3, "Specifies the verbosity of the print statements", print_validator);
00350 
00351     pl->set("dbound", 0.0,
00352             "Specifies the smallest absolute value on the diagonal D for the LDL' factorization");
00353 
00354 
00355     pl->set("Equil", true, "Whether to equilibrate the system before solve");
00356 
00357     pl->set("PreferUpper", true,
00358             "Specifies whether the matrix will be " 
00359             "stored in upper triangular form.");
00360 
00361     valid_params = pl;
00362   }
00363 
00364   return valid_params;
00365 }
00366 
00367 
00368 template <class Matrix, class Vector>
00369 bool
00370 Cholmod<Matrix,Vector>::loadA_impl(EPhase current_phase)
00371 {
00372   using Teuchos::as;
00373 
00374 #ifdef HAVE_AMESOS2_TIMERS
00375   Teuchos::TimeMonitor convTimer(this->timers_.mtxConvTime_);
00376 #endif
00377 
00378   // Only the root image needs storage allocated
00379   
00380   nzvals_.resize(this->globalNumNonZeros_);
00381   rowind_.resize(this->globalNumNonZeros_);
00382   colptr_.resize(this->globalNumCols_ + 1);
00383     
00384 
00385   int nnz_ret = 0;
00386   {
00387 #ifdef HAVE_AMESOS2_TIMERS
00388     Teuchos::TimeMonitor mtxRedistTimer( this->timers_.mtxRedistTime_ );
00389 #endif
00390 
00391     TEUCHOS_TEST_FOR_EXCEPTION(this->rowIndexBase_ != this->columnIndexBase_,
00392              std::runtime_error,
00393              "Row and column maps have different indexbase ");
00394     Util::get_ccs_helper<
00395     MatrixAdapter<Matrix>,chol_type,int,int>::do_get(this->matrixA_.ptr(),
00396                                                     nzvals_(), rowind_(),
00397                                                     colptr_(), nnz_ret, ROOTED,
00398                                                     ARBITRARY,
00399                                                     this->rowIndexBase_);
00400   }
00401   
00402   
00403   TEUCHOS_TEST_FOR_EXCEPTION(nnz_ret != as<int>(this->globalNumNonZeros_),
00404            std::runtime_error,
00405            "Did not get the expected number of non-zero vals");
00406 
00407   function_map::cholmod_init_sparse(as<size_t>(this->globalNumRows_),
00408             as<size_t>(this->globalNumCols_),
00409             as<size_t>(this->globalNumNonZeros_),
00410             0,
00411             colptr_.getRawPtr(),
00412             nzvals_.getRawPtr(),
00413             rowind_.getRawPtr(),
00414             &(data_.A));
00415   
00416   
00417   return true;
00418 }
00419 
00420 
00421 template<class Matrix, class Vector>
00422 const char* Cholmod<Matrix,Vector>::name = "Cholmod";
00423   
00424 
00425 } // end namespace Amesos2
00426 
00427 #endif  // AMESOS2_CHOLMOD_DEF_HPP