Amesos2 - Direct Sparse Solver Interfaces  Version of the Day
Amesos2_Cholmod_def.hpp
Go to the documentation of this file.
1 // @HEADER
2 //
3 // ***********************************************************************
4 //
5 // Amesos2: Templated Direct Sparse Solver Package
6 // Copyright 2011 Sandia Corporation
7 //
8 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
9 // the U.S. Government retains certain rights in this software.
10 //
11 // Redistribution and use in source and binary forms, with or without
12 // modification, are permitted provided that the following conditions are
13 // met:
14 //
15 // 1. Redistributions of source code must retain the above copyright
16 // notice, this list of conditions and the following disclaimer.
17 //
18 // 2. Redistributions in binary form must reproduce the above copyright
19 // notice, this list of conditions and the following disclaimer in the
20 // documentation and/or other materials provided with the distribution.
21 //
22 // 3. Neither the name of the Corporation nor the names of the
23 // contributors may be used to endorse or promote products derived from
24 // this software without specific prior written permission.
25 //
26 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
27 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
30 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
31 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
32 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
36 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 //
38 // Questions? Contact Michael A. Heroux (maherou@sandia.gov)
39 //
40 // ***********************************************************************
41 //
42 // @HEADER
43 
53 #ifndef AMESOS2_CHOLMOD_DEF_HPP
54 #define AMESOS2_CHOLMOD_DEF_HPP
55 
56 #include <Teuchos_Tuple.hpp>
57 #include <Teuchos_ParameterList.hpp>
58 #include <Teuchos_StandardParameterEntryValidators.hpp>
59 
61 #include "Amesos2_Cholmod_decl.hpp"
62 
63 
64 namespace Amesos2 {
65 
66 
67 template <class Matrix, class Vector>
69  Teuchos::RCP<const Matrix> A,
70  Teuchos::RCP<Vector> X,
71  Teuchos::RCP<const Vector> B )
72  : SolverCore<Amesos2::Cholmod,Matrix,Vector>(A, X, B)
73  , nzvals_() // initialize to empty arrays
74  , rowind_()
75  , colptr_()
76  , firstsolve(true)
77  , map()
78  , is_contiguous_(true)
79 {
80  CHOL::cholmod_start(&data_.c);
81  (&data_.c)->nmethods=9;
82  (&data_.c)->quick_return_if_not_posdef=1;
83 
84  //(&data_.c)->method[0].ordering=CHOLMOD_NATURAL;
85  //(&data_.c)->print=5;
86  data_.Y = NULL;
87  data_.E = NULL;
88 }
89 
90 
91 template <class Matrix, class Vector>
93 {
94  CHOL::cholmod_free_factor (&(data_.L), &(data_.c));
95 
96  CHOL::cholmod_free_dense(&(data_.Y), &data_.c);
97  CHOL::cholmod_free_dense(&(data_.E), &data_.c);
98 
99  CHOL::cholmod_finish(&(data_.c));
100 }
101 
102 template<class Matrix, class Vector>
103 int
105 {
106  #ifdef HAVE_AMESOS2_TIMERS
107  Teuchos::TimeMonitor preOrderTimer(this->timers_.preOrderTime_);
108 #endif
109  data_.L = CHOL::cholmod_analyze (&data_.A, &(data_.c));
110  //data_.L->is_super=1;
111  data_.L->is_ll=1;
112 
113  skip_symfact = true;
114 
115  return(0);
116 }
117 
118 
119 template <class Matrix, class Vector>
120 int
122 {
123  if ( !skip_symfact ){
124 #ifdef HAVE_AMESOS2_TIMERS
125  Teuchos::TimeMonitor symFactTimer(this->timers_.symFactTime_);
126 #endif
127  CHOL::cholmod_resymbol (&data_.A, NULL, 0, true, data_.L, &(data_.c));
128  } else {
129  /*
130  * Symbolic factorization has already occured in preOrdering_impl,
131  * but if the user calls this routine directly later, we need to
132  * redo the symbolic factorization.
133  */
134  skip_symfact = false;
135  }
136 
137  return(0);
138 }
139 
140 
141 template <class Matrix, class Vector>
142 int
144 {
145  using Teuchos::as;
146 
147  int info = 0;
148 
149 #ifdef HAVE_AMESOS2_DEBUG
150  TEUCHOS_TEST_FOR_EXCEPTION(data_.A.ncol != as<size_t>(this->globalNumCols_),
151  std::runtime_error,
152  "Error in converting to cholmod_sparse: wrong number of global columns." );
153  TEUCHOS_TEST_FOR_EXCEPTION(data_.A.nrow != as<size_t>(this->globalNumRows_),
154  std::runtime_error,
155  "Error in converting to cholmod_sparse: wrong number of global rows." );
156 #endif
157 
158  { // Do factorization
159 #ifdef HAVE_AMESOS2_TIMERS
160  Teuchos::TimeMonitor numFactTimer(this->timers_.numFactTime_);
161 #endif
162 
163 #ifdef HAVE_AMESOS2_VERBOSE_DEBUG
164  std::cout << "Cholmod:: Before numeric factorization" << std::endl;
165  std::cout << "nzvals_ : " << nzvals_.toString() << std::endl;
166  std::cout << "rowind_ : " << rowind_.toString() << std::endl;
167  std::cout << "colptr_ : " << colptr_.toString() << std::endl;
168 #endif
169  //cholmod_print_sparse(data_.A,"A",&(data_.c));
170  CHOL::cholmod_factorize(&data_.A, data_.L, &(data_.c));
171  //cholmod_print_factor(data_.L,"L",&(data_.c));
172  info = (&data_.c)->status;
173 
174  }
175 
176 
177 
178  /* All processes should have the same error code */
179  Teuchos::broadcast(*(this->matrixA_->getComm()), 0, &info);
180 
181  TEUCHOS_TEST_FOR_EXCEPTION(info == 2,
182  std::runtime_error,
183  "Memory allocation failure in Cholmod factorization");
184 
185  return(info);
186 }
187 
188 
189 template <class Matrix, class Vector>
190 int
192  const Teuchos::Ptr<const MultiVecAdapter<Vector> > B) const
193 {
194  using Teuchos::as;
195 
196  const global_size_type ld_rhs = X->getGlobalLength();
197  const size_t nrhs = X->getGlobalNumVectors();
198 
199  Teuchos::RCP<const Tpetra::Map<local_ordinal_type,
200  global_ordinal_type, node_type> > map2;
201 
202  const size_t val_store_size = as<size_t>(ld_rhs * nrhs);
203  Teuchos::Array<chol_type> xValues(val_store_size);
204  Teuchos::Array<chol_type> bValues(val_store_size);
205 
206  { // Get values from RHS B
207 #ifdef HAVE_AMESOS2_TIMERS
208  Teuchos::TimeMonitor mvConvTimer(this->timers_.vecConvTime_);
209  Teuchos::TimeMonitor redistTimer( this->timers_.vecRedistTime_ );
210 #endif
211  if ( is_contiguous_ == true ) {
213  chol_type>::do_get(B, bValues(),
214  as<size_t>(ld_rhs),
215  ROOTED, this->rowIndexBase_);
216  }
217  else {
219  chol_type>::do_get(B, bValues(),
220  as<size_t>(ld_rhs),
221  CONTIGUOUS_AND_ROOTED, this->rowIndexBase_);
222  }
223 
224  }
225 
226 
227  int ierr = 0; // returned error code
228 
229  {
230 #ifdef HAVE_AMESOS2_TIMERS
231  Teuchos::TimeMonitor mvConvTimer(this->timers_.vecConvTime_);
232 #endif
233 
234  function_map::cholmod_init_dense(as<int>(this->globalNumRows_),
235  as<int>(nrhs), as<int>(ld_rhs),
236  bValues.getRawPtr(), &data_.b);
237  function_map::cholmod_init_dense(as<int>(this->globalNumRows_),
238  as<int>(nrhs), as<int>(ld_rhs),
239  xValues.getRawPtr(), &data_.x);
240  }
241 
242 
243  { // Do solve!
244 #ifdef HAVE_AMESOS2_TIMERS
245  Teuchos::TimeMonitor solveTimer(this->timers_.solveTime_);
246 #endif
247 
248  CHOL::cholmod_dense *xtemp = &(data_.x);
249 
250  CHOL::cholmod_solve2(CHOLMOD_A, data_.L, &data_.b, NULL,
251  &xtemp, NULL, &data_.Y, &data_.E, &data_.c);
252 
253  ierr = (&data_.c)->status;
254  }
255 
256 
257 
258  /* All processes should have the same error code */
259  Teuchos::broadcast(*(this->getComm()), 0, &ierr);
260 
261  TEUCHOS_TEST_FOR_EXCEPTION(ierr == -2, std::runtime_error, "Ran out of memory" );
262 
263  /* Update X's global values */
264  {
265 #ifdef HAVE_AMESOS2_TIMERS
266  Teuchos::TimeMonitor redistTimer(this->timers_.vecRedistTime_);
267 #endif
268 
269  if ( is_contiguous_ == true ) {
271  MultiVecAdapter<Vector>,chol_type>::do_put(X, xValues(),
272  as<size_t>(ld_rhs),
273  ROOTED, this->rowIndexBase_);
274  }
275  else {
277  MultiVecAdapter<Vector>,chol_type>::do_put(X, xValues(),
278  as<size_t>(ld_rhs),
279  CONTIGUOUS_AND_ROOTED, this->rowIndexBase_);
280  }
281 
282  }
283 
284 
285  return(ierr);
286 }
287 
288 
289 template <class Matrix, class Vector>
290 bool
292 {
293  return( this->matrixA_->getGlobalNumRows() == this->matrixA_->getGlobalNumCols() );
294 }
295 
296 
297 template <class Matrix, class Vector>
298 void
299 Cholmod<Matrix,Vector>::setParameters_impl(const Teuchos::RCP<Teuchos::ParameterList> & parameterList )
300 {
301  using Teuchos::RCP;
302  using Teuchos::getIntegralValue;
303  using Teuchos::ParameterEntryValidator;
304 
305  RCP<const Teuchos::ParameterList> valid_params = getValidParameters_impl();
306 
307 
308  if( parameterList->isParameter("Trans") ){
309  RCP<const ParameterEntryValidator> trans_validator = valid_params->getEntry("Trans").validator();
310  parameterList->getEntry("Trans").setValidator(trans_validator);
311 
312  }
313 
314  if( parameterList->isParameter("IterRefine") ){
315  RCP<const ParameterEntryValidator> refine_validator = valid_params->getEntry("IterRefine").validator();
316  parameterList->getEntry("IterRefine").setValidator(refine_validator);
317 
318 
319  }
320 
321  if( parameterList->isParameter("ColPerm") ){
322  RCP<const ParameterEntryValidator> colperm_validator = valid_params->getEntry("ColPerm").validator();
323  parameterList->getEntry("ColPerm").setValidator(colperm_validator);
324 
325  if( parameterList->isParameter("IsContiguous") ){
326  is_contiguous_ = parameterList->get<bool>("IsContiguous");
327  }
328 
329  }
330 
331  (&data_.c)->dbound = parameterList->get<double>("dbound", 0.0);
332 
333  bool prefer_upper = parameterList->get<bool>("PreferUpper", true);
334 
335  (&data_.c)->prefer_upper = prefer_upper ? 1 : 0;
336 
337  (&data_.c)->print = parameterList->get<int>("print",3);
338 
339  (&data_.c)->nmethods = parameterList->get<int>("nmethods",0);
340 
341 }
342 
343 
344 template <class Matrix, class Vector>
345 Teuchos::RCP<const Teuchos::ParameterList>
347 {
348  using std::string;
349  using Teuchos::tuple;
350  using Teuchos::ParameterList;
351  using Teuchos::EnhancedNumberValidator;
352  using Teuchos::setStringToIntegralParameter;
353  using Teuchos::stringToIntegralParameterEntryValidator;
354 
355  static Teuchos::RCP<const Teuchos::ParameterList> valid_params;
356 
357  if( is_null(valid_params) ){
358  Teuchos::RCP<Teuchos::ParameterList> pl = Teuchos::parameterList();
359 
360 
361  Teuchos::RCP<EnhancedNumberValidator<int> > print_validator
362  = Teuchos::rcp( new EnhancedNumberValidator<int>(0,5));
363 
364  Teuchos::RCP<EnhancedNumberValidator<int> > nmethods_validator
365  = Teuchos::rcp( new EnhancedNumberValidator<int>(0,9));
366 
367  pl->set("nmethods", 0, "Specifies the number of different ordering methods to try", nmethods_validator);
368 
369  pl->set("print", 3, "Specifies the verbosity of the print statements", print_validator);
370 
371  pl->set("dbound", 0.0,
372  "Specifies the smallest absolute value on the diagonal D for the LDL' factorization");
373 
374 
375  pl->set("Equil", true, "Whether to equilibrate the system before solve");
376 
377  pl->set("PreferUpper", true,
378  "Specifies whether the matrix will be "
379  "stored in upper triangular form.");
380 
381  pl->set("IsContiguous", true, "Whether GIDs contiguous");
382 
383  valid_params = pl;
384  }
385 
386  return valid_params;
387 }
388 
389 
390 template <class Matrix, class Vector>
391 bool
393 {
394  using Teuchos::as;
395 
396 #ifdef HAVE_AMESOS2_TIMERS
397  Teuchos::TimeMonitor convTimer(this->timers_.mtxConvTime_);
398 #endif
399 
400  // Only the root image needs storage allocated
401 
402  nzvals_.resize(this->globalNumNonZeros_);
403  rowind_.resize(this->globalNumNonZeros_);
404  colptr_.resize(this->globalNumCols_ + 1);
405 
406 
407  int nnz_ret = 0;
408  {
409 #ifdef HAVE_AMESOS2_TIMERS
410  Teuchos::TimeMonitor mtxRedistTimer( this->timers_.mtxRedistTime_ );
411 #endif
412 
413  TEUCHOS_TEST_FOR_EXCEPTION(this->rowIndexBase_ != this->columnIndexBase_,
414  std::runtime_error,
415  "Row and column maps have different indexbase ");
416  if ( is_contiguous_ == true ) {
418  MatrixAdapter<Matrix>,chol_type,int,int>::do_get(this->matrixA_.ptr(),
419  nzvals_(), rowind_(),
420  colptr_(), nnz_ret, ROOTED,
421  ARBITRARY,
422  this->rowIndexBase_);
423  }
424  else {
426  MatrixAdapter<Matrix>,chol_type,int,int>::do_get(this->matrixA_.ptr(),
427  nzvals_(), rowind_(),
428  colptr_(), nnz_ret, CONTIGUOUS_AND_ROOTED,
429  ARBITRARY,
430  this->rowIndexBase_);
431  }
432  }
433 
434 
435  TEUCHOS_TEST_FOR_EXCEPTION(nnz_ret != as<int>(this->globalNumNonZeros_),
436  std::runtime_error,
437  "Did not get the expected number of non-zero vals");
438 
439  function_map::cholmod_init_sparse(as<size_t>(this->globalNumRows_),
440  as<size_t>(this->globalNumCols_),
441  as<size_t>(this->globalNumNonZeros_),
442  0,
443  colptr_.getRawPtr(),
444  nzvals_.getRawPtr(),
445  rowind_.getRawPtr(),
446  &(data_.A));
447 
448 
449  return true;
450 }
451 
452 
453 template<class Matrix, class Vector>
454 const char* Cholmod<Matrix,Vector>::name = "Cholmod";
455 
456 
457 } // end namespace Amesos2
458 
459 #endif // AMESOS2_CHOLMOD_DEF_HPP
~Cholmod()
Destructor.
Definition: Amesos2_Cholmod_def.hpp:92
int preOrdering_impl()
Performs pre-ordering on the matrix to increase efficiency.
Definition: Amesos2_Cholmod_def.hpp:104
Amesos2::SolverCore: A templated interface for interaction with third-party direct sparse solvers...
Definition: Amesos2_SolverCore_decl.hpp:105
EPhase
Used to indicate a phase in the direct solution.
Definition: Amesos2_TypeDecl.hpp:65
Teuchos::RCP< const Teuchos::ParameterList > getValidParameters_impl() const
Definition: Amesos2_Cholmod_def.hpp:346
Helper class for getting 1-D copies of multivectors.
Definition: Amesos2_MultiVecAdapter_decl.hpp:266
bool matrixShapeOK_impl() const
Determines whether the shape of the matrix is OK for this solver.
Definition: Amesos2_Cholmod_def.hpp:291
Cholmod(Teuchos::RCP< const Matrix > A, Teuchos::RCP< Vector > X, Teuchos::RCP< const Vector > B)
Initialize from Teuchos::RCP.
Definition: Amesos2_Cholmod_def.hpp:68
A generic helper class for getting a CCS representation of a Matrix.
Definition: Amesos2_Util.hpp:654
int solve_impl(const Teuchos::Ptr< MultiVecAdapter< Vector > > X, const Teuchos::Ptr< const MultiVecAdapter< Vector > > B) const
CHOLMOD specific solve.
Definition: Amesos2_Cholmod_def.hpp:191
void setParameters_impl(const Teuchos::RCP< Teuchos::ParameterList > &parameterList)
Definition: Amesos2_Cholmod_def.hpp:299
Amesos2 CHOLMOD declarations.
A Matrix adapter interface for Amesos2.
Definition: Amesos2_MatrixAdapter_decl.hpp:76
bool loadA_impl(EPhase current_phase)
Reads matrix data into internal structures.
Definition: Amesos2_Cholmod_def.hpp:392
int symbolicFactorization_impl()
Perform symbolic factorization of the matrix using CHOLMOD.
Definition: Amesos2_Cholmod_def.hpp:121
Amesos2 interface to the SuperLU package.
Definition: Amesos2_Cholmod_decl.hpp:73
Helper class for putting 1-D data arrays into multivectors.
Definition: Amesos2_MultiVecAdapter_decl.hpp:322
A templated MultiVector class adapter for Amesos2.
Definition: Amesos2_MultiVecAdapter_decl.hpp:176
int numericFactorization_impl()
CHOLMOD specific numeric factorization.
Definition: Amesos2_Cholmod_def.hpp:143