Amesos2 - Direct Sparse Solver Interfaces  Version of the Day
Amesos2_Superlu_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_SUPERLU_DEF_HPP
54 #define AMESOS2_SUPERLU_DEF_HPP
55 
56 #include <Teuchos_Tuple.hpp>
57 #include <Teuchos_ParameterList.hpp>
58 #include <Teuchos_StandardParameterEntryValidators.hpp>
59 
61 #include "Amesos2_Superlu_decl.hpp"
62 
63 namespace Amesos2 {
64 
65 
66 template <class Matrix, class Vector>
68  Teuchos::RCP<const Matrix> A,
69  Teuchos::RCP<Vector> X,
70  Teuchos::RCP<const Vector> B )
71  : SolverCore<Amesos2::Superlu,Matrix,Vector>(A, X, B)
72  , nzvals_() // initialize to empty arrays
73  , rowind_()
74  , colptr_()
75  , is_contiguous_(true)
76 {
77  // ilu_set_default_options is called later in set parameter list if required.
78  // This is not the ideal way, but the other option to always call
79  // ilu_set_default_options here and assuming it won't have any side effect
80  // in the TPL is more dangerous. It is not a good idea to rely on external
81  // libraries' internal "features".
82  SLU::set_default_options(&(data_.options));
83  // Override some default options
84  data_.options.PrintStat = SLU::NO;
85 
86  SLU::StatInit(&(data_.stat));
87 
88  data_.perm_r.resize(this->globalNumRows_);
89  data_.perm_c.resize(this->globalNumCols_);
90  data_.etree.resize(this->globalNumCols_);
91  data_.R.resize(this->globalNumRows_);
92  data_.C.resize(this->globalNumCols_);
93 
94  data_.relax = SLU::sp_ienv(2); // Query optimal relax param from superlu
95  data_.panel_size = SLU::sp_ienv(1); // Query optimal panel size
96 
97  data_.equed = 'N'; // No equilibration
98  data_.A.Store = NULL;
99  data_.L.Store = NULL;
100  data_.U.Store = NULL;
101  data_.X.Store = NULL;
102  data_.B.Store = NULL;
103 
104  ILU_Flag_=false; // default: turn off ILU
105 }
106 
107 
108 template <class Matrix, class Vector>
110 {
111  /* Free Superlu data_types
112  * - Matrices
113  * - Vectors
114  * - Stat object
115  */
116  SLU::StatFree( &(data_.stat) ) ;
117 
118  // Storage is initialized in numericFactorization_impl()
119  if ( data_.A.Store != NULL ){
120  SLU::Destroy_SuperMatrix_Store( &(data_.A) );
121  }
122 
123  // only root allocated these SuperMatrices.
124  if ( data_.L.Store != NULL ){ // will only be true for this->root_
125  SLU::Destroy_SuperNode_Matrix( &(data_.L) );
126  SLU::Destroy_CompCol_Matrix( &(data_.U) );
127  }
128 }
129 
130 template <class Matrix, class Vector>
131 std::string
133 {
134  std::ostringstream oss;
135  oss << "SuperLU solver interface";
136  if (ILU_Flag_) {
137  oss << ", \"ILUTP\" : {";
138  oss << "drop tol = " << data_.options.ILU_DropTol;
139  oss << ", fill factor = " << data_.options.ILU_FillFactor;
140  oss << ", fill tol = " << data_.options.ILU_FillTol;
141  switch(data_.options.ILU_MILU) {
142  case SLU::SMILU_1 :
143  oss << ", MILU 1";
144  break;
145  case SLU::SMILU_2 :
146  oss << ", MILU 2";
147  break;
148  case SLU::SMILU_3 :
149  oss << ", MILU 3";
150  break;
151  case SLU::SILU :
152  default:
153  oss << ", regular ILU";
154  }
155  switch(data_.options.ILU_Norm) {
156  case SLU::ONE_NORM :
157  oss << ", 1-norm";
158  break;
159  case SLU::TWO_NORM :
160  oss << ", 2-norm";
161  break;
162  case SLU::INF_NORM :
163  default:
164  oss << ", infinity-norm";
165  }
166  oss << "}";
167  } else {
168  oss << ", direct solve";
169  }
170  return oss.str();
171  /*
172 
173  // ILU parameters
174  if( parameterList->isParameter("RowPerm") ){
175  RCP<const ParameterEntryValidator> rowperm_validator = valid_params->getEntry("RowPerm").validator();
176  parameterList->getEntry("RowPerm").setValidator(rowperm_validator);
177  data_.options.RowPerm = getIntegralValue<SLU::rowperm_t>(*parameterList, "RowPerm");
178  }
179 
180 
181  */
182 }
183 
184 template<class Matrix, class Vector>
185 int
187 {
188  /*
189  * Get column permutation vector perm_c[], according to permc_spec:
190  * permc_spec = NATURAL: natural ordering
191  * permc_spec = MMD_AT_PLUS_A: minimum degree on structure of A'+A
192  * permc_spec = MMD_ATA: minimum degree on structure of A'*A
193  * permc_spec = COLAMD: approximate minimum degree column ordering
194  * permc_spec = MY_PERMC: the ordering already supplied in perm_c[]
195  */
196  int permc_spec = data_.options.ColPerm;
197  if ( permc_spec != SLU::MY_PERMC && this->root_ ){
198 #ifdef HAVE_AMESOS2_TIMERS
199  Teuchos::TimeMonitor preOrderTimer(this->timers_.preOrderTime_);
200 #endif
201 
202  SLU::get_perm_c(permc_spec, &(data_.A), data_.perm_c.getRawPtr());
203  }
204 
205  return(0);
206 }
207 
208 
209 template <class Matrix, class Vector>
210 int
212 {
213  /*
214  * SuperLU performs symbolic factorization and numeric factorization
215  * together, but does leave some options for reusing symbolic
216  * structures that have been created on previous factorizations. If
217  * our Amesos2 user calls this function, that is an indication that
218  * the symbolic structure of the matrix is no longer valid, and
219  * SuperLU should do the factorization from scratch.
220  *
221  * This can be accomplished by setting the options.Fact flag to
222  * DOFACT, as well as setting our own internal flag to false.
223  */
224  same_symbolic_ = false;
225  data_.options.Fact = SLU::DOFACT;
226 
227  return(0);
228 }
229 
230 
231 template <class Matrix, class Vector>
232 int
234 {
235  using Teuchos::as;
236 
237  // Cleanup old L and U matrices if we are not reusing a symbolic
238  // factorization. Stores and other data will be allocated in gstrf.
239  // Only rank 0 has valid pointers
240  if ( !same_symbolic_ && data_.L.Store != NULL ){
241  SLU::Destroy_SuperNode_Matrix( &(data_.L) );
242  SLU::Destroy_CompCol_Matrix( &(data_.U) );
243  data_.L.Store = NULL;
244  data_.U.Store = NULL;
245  }
246 
247  if( same_symbolic_ ) data_.options.Fact = SLU::SamePattern_SameRowPerm;
248 
249  int info = 0;
250  if ( this->root_ ){
251 
252 #ifdef HAVE_AMESOS2_DEBUG
253  TEUCHOS_TEST_FOR_EXCEPTION( data_.A.ncol != as<int>(this->globalNumCols_),
254  std::runtime_error,
255  "Error in converting to SuperLU SuperMatrix: wrong number of global columns." );
256  TEUCHOS_TEST_FOR_EXCEPTION( data_.A.nrow != as<int>(this->globalNumRows_),
257  std::runtime_error,
258  "Error in converting to SuperLU SuperMatrix: wrong number of global rows." );
259 #endif
260 
261  if( data_.options.Equil == SLU::YES ){
262  magnitude_type rowcnd, colcnd, amax;
263  int info2 = 0;
264 
265  // calculate row and column scalings
266  function_map::gsequ(&(data_.A), data_.R.getRawPtr(),
267  data_.C.getRawPtr(), &rowcnd, &colcnd,
268  &amax, &info2);
269  TEUCHOS_TEST_FOR_EXCEPTION
270  (info2 < 0, std::runtime_error,
271  "SuperLU's gsequ function returned with status " << info2 << " < 0."
272  " This means that argument " << (-info2) << " given to the function"
273  " had an illegal value.");
274  if (info2 > 0) {
275  if (info2 <= data_.A.nrow) {
276  TEUCHOS_TEST_FOR_EXCEPTION
277  (true, std::runtime_error, "SuperLU's gsequ function returned with "
278  "info = " << info2 << " > 0, and info <= A.nrow = " << data_.A.nrow
279  << ". This means that row " << info2 << " of A is exactly zero.");
280  }
281  else if (info2 > data_.A.ncol) {
282  TEUCHOS_TEST_FOR_EXCEPTION
283  (true, std::runtime_error, "SuperLU's gsequ function returned with "
284  "info = " << info2 << " > 0, and info > A.ncol = " << data_.A.ncol
285  << ". This means that column " << (info2 - data_.A.nrow) << " of "
286  "A is exactly zero.");
287  }
288  else {
289  TEUCHOS_TEST_FOR_EXCEPTION
290  (true, std::runtime_error, "SuperLU's gsequ function returned "
291  "with info = " << info2 << " > 0, but its value is not in the "
292  "range permitted by the documentation. This should never happen "
293  "(it appears to be SuperLU's fault).");
294  }
295  }
296 
297  // apply row and column scalings if necessary
298  function_map::laqgs(&(data_.A), data_.R.getRawPtr(),
299  data_.C.getRawPtr(), rowcnd, colcnd,
300  amax, &(data_.equed));
301 
302  // // check what types of equilibration was actually done
303  // data_.rowequ = (data_.equed == 'R') || (data_.equed == 'B');
304  // data_.colequ = (data_.equed == 'C') || (data_.equed == 'B');
305  }
306 
307  // Apply the column permutation computed in preOrdering. Place the
308  // column-permuted matrix in AC
309  SLU::sp_preorder(&(data_.options), &(data_.A), data_.perm_c.getRawPtr(),
310  data_.etree.getRawPtr(), &(data_.AC));
311 
312  { // Do factorization
313 #ifdef HAVE_AMESOS2_TIMERS
314  Teuchos::TimeMonitor numFactTimer(this->timers_.numFactTime_);
315 #endif
316 
317 #ifdef HAVE_AMESOS2_VERBOSE_DEBUG
318  std::cout << "Superlu:: Before numeric factorization" << std::endl;
319  std::cout << "nzvals_ : " << nzvals_.toString() << std::endl;
320  std::cout << "rowind_ : " << rowind_.toString() << std::endl;
321  std::cout << "colptr_ : " << colptr_.toString() << std::endl;
322 #endif
323 
324  if(ILU_Flag_==false) {
325  function_map::gstrf(&(data_.options), &(data_.AC),
326  data_.relax, data_.panel_size, data_.etree.getRawPtr(),
327  NULL, 0, data_.perm_c.getRawPtr(), data_.perm_r.getRawPtr(),
328  &(data_.L), &(data_.U),
329 #ifdef HAVE_AMESOS2_SUPERLU5_API
330  &(data_.lu),
331 #endif
332  &(data_.stat), &info);
333  }
334  else {
335  function_map::gsitrf(&(data_.options), &(data_.AC),
336  data_.relax, data_.panel_size, data_.etree.getRawPtr(),
337  NULL, 0, data_.perm_c.getRawPtr(), data_.perm_r.getRawPtr(),
338  &(data_.L), &(data_.U),
339 #ifdef HAVE_AMESOS2_SUPERLU5_API
340  &(data_.lu),
341 #endif
342  &(data_.stat), &info);
343  }
344 
345  }
346  // Cleanup. AC data will be alloc'd again for next factorization (if at all)
347  SLU::Destroy_CompCol_Permuted( &(data_.AC) );
348 
349  // Set the number of non-zero values in the L and U factors
350  this->setNnzLU( as<size_t>(((SLU::SCformat*)data_.L.Store)->nnz +
351  ((SLU::NCformat*)data_.U.Store)->nnz) );
352  }
353 
354  /* All processes should have the same error code */
355  Teuchos::broadcast(*(this->matrixA_->getComm()), 0, &info);
356 
357  global_size_type info_st = as<global_size_type>(info);
358  TEUCHOS_TEST_FOR_EXCEPTION( (info_st > 0) && (info_st <= this->globalNumCols_),
359  std::runtime_error,
360  "Factorization complete, but matrix is singular. Division by zero eminent");
361  TEUCHOS_TEST_FOR_EXCEPTION( (info_st > 0) && (info_st > this->globalNumCols_),
362  std::runtime_error,
363  "Memory allocation failure in Superlu factorization");
364 
365  data_.options.Fact = SLU::FACTORED;
366  same_symbolic_ = true;
367 
368  return(info);
369 }
370 
371 
372 template <class Matrix, class Vector>
373 int
375  const Teuchos::Ptr<const MultiVecAdapter<Vector> > B) const
376 {
377  using Teuchos::as;
378 
379  const global_size_type ld_rhs = this->root_ ? X->getGlobalLength() : 0;
380  const size_t nrhs = X->getGlobalNumVectors();
381 
382  const size_t val_store_size = as<size_t>(ld_rhs * nrhs);
383  Teuchos::Array<slu_type> xValues(val_store_size);
384  Teuchos::Array<slu_type> bValues(val_store_size);
385 
386  { // Get values from RHS B
387 #ifdef HAVE_AMESOS2_TIMERS
388  Teuchos::TimeMonitor mvConvTimer(this->timers_.vecConvTime_);
389  Teuchos::TimeMonitor redistTimer( this->timers_.vecRedistTime_ );
390 #endif
391  if ( is_contiguous_ == true ) {
393  slu_type>::do_get(B, bValues(),
394  as<size_t>(ld_rhs),
395  ROOTED, this->rowIndexBase_);
396  }
397  else {
399  slu_type>::do_get(B, bValues(),
400  as<size_t>(ld_rhs),
401  CONTIGUOUS_AND_ROOTED, this->rowIndexBase_);
402  }
403  }
404 
405  int ierr = 0; // returned error code
406 
407  magnitude_type rpg, rcond;
408  if ( this->root_ ) {
409  data_.ferr.resize(nrhs);
410  data_.berr.resize(nrhs);
411 
412  {
413 #ifdef HAVE_AMESOS2_TIMERS
414  Teuchos::TimeMonitor mvConvTimer(this->timers_.vecConvTime_);
415 #endif
416  SLU::Dtype_t dtype = type_map::dtype;
417  int i_ld_rhs = as<int>(ld_rhs);
418  function_map::create_Dense_Matrix(&(data_.B), i_ld_rhs, as<int>(nrhs),
419  bValues.getRawPtr(), i_ld_rhs,
420  SLU::SLU_DN, dtype, SLU::SLU_GE);
421  function_map::create_Dense_Matrix(&(data_.X), i_ld_rhs, as<int>(nrhs),
422  xValues.getRawPtr(), i_ld_rhs,
423  SLU::SLU_DN, dtype, SLU::SLU_GE);
424  }
425 
426  // Note: the values of B and X (after solution) are adjusted
427  // appropriately within gssvx for row and column scalings.
428 
429  { // Do solve!
430 #ifdef HAVE_AMESOS2_TIMERS
431  Teuchos::TimeMonitor solveTimer(this->timers_.solveTime_);
432 #endif
433 
434  if(ILU_Flag_==false) {
435  function_map::gssvx(&(data_.options), &(data_.A),
436  data_.perm_c.getRawPtr(), data_.perm_r.getRawPtr(),
437  data_.etree.getRawPtr(), &(data_.equed), data_.R.getRawPtr(),
438  data_.C.getRawPtr(), &(data_.L), &(data_.U), NULL, 0, &(data_.B),
439  &(data_.X), &rpg, &rcond, data_.ferr.getRawPtr(),
440  data_.berr.getRawPtr(),
441 #ifdef HAVE_AMESOS2_SUPERLU5_API
442  &(data_.lu),
443 #endif
444  &(data_.mem_usage), &(data_.stat), &ierr);
445  }
446  else {
447  function_map::gsisx(&(data_.options), &(data_.A),
448  data_.perm_c.getRawPtr(), data_.perm_r.getRawPtr(),
449  data_.etree.getRawPtr(), &(data_.equed), data_.R.getRawPtr(),
450  data_.C.getRawPtr(), &(data_.L), &(data_.U), NULL, 0, &(data_.B),
451  &(data_.X), &rpg, &rcond,
452 #ifdef HAVE_AMESOS2_SUPERLU5_API
453  &(data_.lu),
454 #endif
455  &(data_.mem_usage), &(data_.stat), &ierr);
456  }
457 
458  }
459 
460  // Cleanup X and B stores
461  SLU::Destroy_SuperMatrix_Store( &(data_.X) );
462  SLU::Destroy_SuperMatrix_Store( &(data_.B) );
463  data_.X.Store = NULL;
464  data_.B.Store = NULL;
465  }
466 
467  /* All processes should have the same error code */
468  Teuchos::broadcast(*(this->getComm()), 0, &ierr);
469 
470  global_size_type ierr_st = as<global_size_type>(ierr);
471  TEUCHOS_TEST_FOR_EXCEPTION( ierr < 0,
472  std::invalid_argument,
473  "Argument " << -ierr << " to SuperLU xgssvx had illegal value" );
474  TEUCHOS_TEST_FOR_EXCEPTION( ierr > 0 && ierr_st <= this->globalNumCols_,
475  std::runtime_error,
476  "Factorization complete, but U is exactly singular" );
477  TEUCHOS_TEST_FOR_EXCEPTION( ierr > 0 && ierr_st > this->globalNumCols_ + 1,
478  std::runtime_error,
479  "SuperLU allocated " << ierr - this->globalNumCols_ << " bytes of "
480  "memory before allocation failure occured." );
481 
482  /* Update X's global values */
483  {
484 #ifdef HAVE_AMESOS2_TIMERS
485  Teuchos::TimeMonitor redistTimer(this->timers_.vecRedistTime_);
486 #endif
487 
488  if ( is_contiguous_ == true ) {
490  MultiVecAdapter<Vector>,slu_type>::do_put(X, xValues(),
491  as<size_t>(ld_rhs),
492  ROOTED, this->rowIndexBase_);
493  }
494  else {
496  MultiVecAdapter<Vector>,slu_type>::do_put(X, xValues(),
497  as<size_t>(ld_rhs),
498  CONTIGUOUS_AND_ROOTED, this->rowIndexBase_);
499  }
500  }
501 
502 
503  return(ierr);
504 }
505 
506 
507 template <class Matrix, class Vector>
508 bool
510 {
511  // The Superlu factorization routines can handle square as well as
512  // rectangular matrices, but Superlu can only apply the solve routines to
513  // square matrices, so we check the matrix for squareness.
514  return( this->matrixA_->getGlobalNumRows() == this->matrixA_->getGlobalNumCols() );
515 }
516 
517 
518 template <class Matrix, class Vector>
519 void
520 Superlu<Matrix,Vector>::setParameters_impl(const Teuchos::RCP<Teuchos::ParameterList> & parameterList )
521 {
522  using Teuchos::RCP;
523  using Teuchos::getIntegralValue;
524  using Teuchos::ParameterEntryValidator;
525 
526  RCP<const Teuchos::ParameterList> valid_params = getValidParameters_impl();
527 
528  ILU_Flag_ = parameterList->get<bool>("ILU_Flag",false);
529  if (ILU_Flag_) {
530  SLU::ilu_set_default_options(&(data_.options));
531  // Override some default options
532  data_.options.PrintStat = SLU::NO;
533  }
534 
535  data_.options.Trans = this->control_.useTranspose_ ? SLU::TRANS : SLU::NOTRANS;
536  // The SuperLU transpose option can override the Amesos2 option
537  if( parameterList->isParameter("Trans") ){
538  RCP<const ParameterEntryValidator> trans_validator = valid_params->getEntry("Trans").validator();
539  parameterList->getEntry("Trans").setValidator(trans_validator);
540 
541  data_.options.Trans = getIntegralValue<SLU::trans_t>(*parameterList, "Trans");
542  }
543 
544  if( parameterList->isParameter("IterRefine") ){
545  RCP<const ParameterEntryValidator> refine_validator = valid_params->getEntry("IterRefine").validator();
546  parameterList->getEntry("IterRefine").setValidator(refine_validator);
547 
548  data_.options.IterRefine = getIntegralValue<SLU::IterRefine_t>(*parameterList, "IterRefine");
549  }
550 
551  if( parameterList->isParameter("ColPerm") ){
552  RCP<const ParameterEntryValidator> colperm_validator = valid_params->getEntry("ColPerm").validator();
553  parameterList->getEntry("ColPerm").setValidator(colperm_validator);
554 
555  data_.options.ColPerm = getIntegralValue<SLU::colperm_t>(*parameterList, "ColPerm");
556  }
557 
558  data_.options.DiagPivotThresh = parameterList->get<double>("DiagPivotThresh", 1.0);
559 
560  bool equil = parameterList->get<bool>("Equil", true);
561  data_.options.Equil = equil ? SLU::YES : SLU::NO;
562 
563  bool symmetric_mode = parameterList->get<bool>("SymmetricMode", false);
564  data_.options.SymmetricMode = symmetric_mode ? SLU::YES : SLU::NO;
565 
566  // ILU parameters
567  if( parameterList->isParameter("RowPerm") ){
568  RCP<const ParameterEntryValidator> rowperm_validator = valid_params->getEntry("RowPerm").validator();
569  parameterList->getEntry("RowPerm").setValidator(rowperm_validator);
570  data_.options.RowPerm = getIntegralValue<SLU::rowperm_t>(*parameterList, "RowPerm");
571  }
572 
573  /*if( parameterList->isParameter("ILU_DropRule") ) {
574  RCP<const ParameterEntryValidator> droprule_validator = valid_params->getEntry("ILU_DropRule").validator();
575  parameterList->getEntry("ILU_DropRule").setValidator(droprule_validator);
576  data_.options.ILU_DropRule = getIntegralValue<SLU::rule_t>(*parameterList, "ILU_DropRule");
577  }*/
578 
579  data_.options.ILU_DropTol = parameterList->get<double>("ILU_DropTol", 0.0001);
580 
581  data_.options.ILU_FillFactor = parameterList->get<double>("ILU_FillFactor", 10.0);
582 
583  if( parameterList->isParameter("ILU_Norm") ) {
584  RCP<const ParameterEntryValidator> norm_validator = valid_params->getEntry("ILU_Norm").validator();
585  parameterList->getEntry("ILU_Norm").setValidator(norm_validator);
586  data_.options.ILU_Norm = getIntegralValue<SLU::norm_t>(*parameterList, "ILU_Norm");
587  }
588 
589  if( parameterList->isParameter("ILU_MILU") ) {
590  RCP<const ParameterEntryValidator> milu_validator = valid_params->getEntry("ILU_MILU").validator();
591  parameterList->getEntry("ILU_MILU").setValidator(milu_validator);
592  data_.options.ILU_MILU = getIntegralValue<SLU::milu_t>(*parameterList, "ILU_MILU");
593  }
594 
595  data_.options.ILU_FillTol = parameterList->get<double>("ILU_FillTol", 0.01);
596 
597  if( parameterList->isParameter("IsContiguous") ){
598  is_contiguous_ = parameterList->get<bool>("IsContiguous");
599  }
600 }
601 
602 
603 template <class Matrix, class Vector>
604 Teuchos::RCP<const Teuchos::ParameterList>
606 {
607  using std::string;
608  using Teuchos::tuple;
609  using Teuchos::ParameterList;
610  using Teuchos::EnhancedNumberValidator;
611  using Teuchos::setStringToIntegralParameter;
612  using Teuchos::stringToIntegralParameterEntryValidator;
613 
614  static Teuchos::RCP<const Teuchos::ParameterList> valid_params;
615 
616  if( is_null(valid_params) ){
617  Teuchos::RCP<Teuchos::ParameterList> pl = Teuchos::parameterList();
618 
619  setStringToIntegralParameter<SLU::trans_t>("Trans", "NOTRANS",
620  "Solve for the transpose system or not",
621  tuple<string>("TRANS","NOTRANS","CONJ"),
622  tuple<string>("Solve with transpose",
623  "Do not solve with transpose",
624  "Solve with the conjugate transpose"),
625  tuple<SLU::trans_t>(SLU::TRANS,
626  SLU::NOTRANS,
627  SLU::CONJ),
628  pl.getRawPtr());
629 
630  setStringToIntegralParameter<SLU::IterRefine_t>("IterRefine", "NOREFINE",
631  "Type of iterative refinement to use",
632  tuple<string>("NOREFINE", "SLU_SINGLE", "SLU_DOUBLE"),
633  tuple<string>("Do not use iterative refinement",
634  "Do single iterative refinement",
635  "Do double iterative refinement"),
636  tuple<SLU::IterRefine_t>(SLU::NOREFINE,
637  SLU::SLU_SINGLE,
638  SLU::SLU_DOUBLE),
639  pl.getRawPtr());
640 
641  // Note: MY_PERMC not yet supported
642  setStringToIntegralParameter<SLU::colperm_t>("ColPerm", "COLAMD",
643  "Specifies how to permute the columns of the "
644  "matrix for sparsity preservation",
645  tuple<string>("NATURAL", "MMD_AT_PLUS_A",
646  "MMD_ATA", "COLAMD"),
647  tuple<string>("Natural ordering",
648  "Minimum degree ordering on A^T + A",
649  "Minimum degree ordering on A^T A",
650  "Approximate minimum degree column ordering"),
651  tuple<SLU::colperm_t>(SLU::NATURAL,
652  SLU::MMD_AT_PLUS_A,
653  SLU::MMD_ATA,
654  SLU::COLAMD),
655  pl.getRawPtr());
656 
657  Teuchos::RCP<EnhancedNumberValidator<double> > diag_pivot_thresh_validator
658  = Teuchos::rcp( new EnhancedNumberValidator<double>(0.0, 1.0) );
659  pl->set("DiagPivotThresh", 1.0,
660  "Specifies the threshold used for a diagonal entry to be an acceptable pivot",
661  diag_pivot_thresh_validator); // partial pivoting
662 
663  pl->set("Equil", true, "Whether to equilibrate the system before solve");
664 
665  pl->set("SymmetricMode", false,
666  "Specifies whether to use the symmetric mode. "
667  "Gives preference to diagonal pivots and uses "
668  "an (A^T + A)-based column permutation.");
669 
670  // ILU parameters
671 
672  setStringToIntegralParameter<SLU::rowperm_t>("RowPerm", "LargeDiag",
673  "Type of row permutation strategy to use",
674  tuple<string>("NOROWPERM","LargeDiag","MY_PERMR"),
675  tuple<string>("Use natural ordering",
676  "Use weighted bipartite matching algorithm",
677  "Use the ordering given in perm_r input"),
678  tuple<SLU::rowperm_t>(SLU::NOROWPERM,
679  SLU::LargeDiag,
680  SLU::MY_PERMR),
681  pl.getRawPtr());
682 
683  /*setStringToIntegralParameter<SLU::rule_t>("ILU_DropRule", "DROP_BASIC",
684  "Type of dropping strategy to use",
685  tuple<string>("DROP_BASIC","DROP_PROWS",
686  "DROP_COLUMN","DROP_AREA",
687  "DROP_DYNAMIC","DROP_INTERP"),
688  tuple<string>("ILUTP(t)","ILUTP(p,t)",
689  "Variant of ILUTP(p,t) for j-th column",
690  "Variant of ILUTP to control memory",
691  "Dynamically adjust threshold",
692  "Compute second dropping threshold by interpolation"),
693  tuple<SLU::rule_t>(SLU::DROP_BASIC,SLU::DROP_PROWS,SLU::DROP_COLUMN,
694  SLU::DROP_AREA,SLU::DROP_DYNAMIC,SLU::DROP_INTERP),
695  pl.getRawPtr());*/
696 
697  pl->set("ILU_DropTol", 0.0001, "ILUT drop tolerance");
698 
699  pl->set("ILU_FillFactor", 10.0, "ILUT fill factor");
700 
701  setStringToIntegralParameter<SLU::norm_t>("ILU_Norm", "INF_NORM",
702  "Type of norm to use",
703  tuple<string>("ONE_NORM","TWO_NORM","INF_NORM"),
704  tuple<string>("1-norm","2-norm","inf-norm"),
705  tuple<SLU::norm_t>(SLU::ONE_NORM,SLU::TWO_NORM,SLU::INF_NORM),
706  pl.getRawPtr());
707 
708  setStringToIntegralParameter<SLU::milu_t>("ILU_MILU", "SILU",
709  "Type of modified ILU to use",
710  tuple<string>("SILU","SMILU_1","SMILU_2","SMILU_3"),
711  tuple<string>("Regular ILU","MILU 1","MILU 2","MILU 3"),
712  tuple<SLU::milu_t>(SLU::SILU,SLU::SMILU_1,SLU::SMILU_2,
713  SLU::SMILU_3),
714  pl.getRawPtr());
715 
716  pl->set("ILU_FillTol", 0.01, "ILUT fill tolerance");
717 
718  pl->set("ILU_Flag", false, "ILU flag: if true, run ILU routines");
719 
720  pl->set("IsContiguous", true, "Whether GIDs contiguous");
721 
722  valid_params = pl;
723  }
724 
725  return valid_params;
726 }
727 
728 
729 template <class Matrix, class Vector>
730 bool
732 {
733  using Teuchos::as;
734 
735 #ifdef HAVE_AMESOS2_TIMERS
736  Teuchos::TimeMonitor convTimer(this->timers_.mtxConvTime_);
737 #endif
738 
739  // SuperLU does not need the matrix at symbolicFactorization()
740  if( current_phase == SYMBFACT ) return false;
741 
742  // Cleanup old store memory if it's non-NULL (should only ever be non-NULL at root_)
743  if( data_.A.Store != NULL ){
744  SLU::Destroy_SuperMatrix_Store( &(data_.A) );
745  data_.A.Store = NULL;
746  }
747 
748  // Only the root image needs storage allocated
749  if( this->root_ ){
750  nzvals_.resize(this->globalNumNonZeros_);
751  rowind_.resize(this->globalNumNonZeros_);
752  colptr_.resize(this->globalNumCols_ + 1);
753  }
754 
755  int nnz_ret = 0;
756  {
757 #ifdef HAVE_AMESOS2_TIMERS
758  Teuchos::TimeMonitor mtxRedistTimer( this->timers_.mtxRedistTime_ );
759 #endif
760 
761  TEUCHOS_TEST_FOR_EXCEPTION( this->rowIndexBase_ != this->columnIndexBase_,
762  std::runtime_error,
763  "Row and column maps have different indexbase ");
764 
765  if ( is_contiguous_ == true ) {
767  MatrixAdapter<Matrix>,slu_type,int,int>::do_get(this->matrixA_.ptr(),
768  nzvals_(), rowind_(),
769  colptr_(), nnz_ret, ROOTED,
770  ARBITRARY,
771  this->rowIndexBase_);
772  }
773  else {
775  MatrixAdapter<Matrix>,slu_type,int,int>::do_get(this->matrixA_.ptr(),
776  nzvals_(), rowind_(),
777  colptr_(), nnz_ret, CONTIGUOUS_AND_ROOTED,
778  ARBITRARY,
779  this->rowIndexBase_);
780  }
781  }
782 
783  // Get the SLU data type for this type of matrix
784  SLU::Dtype_t dtype = type_map::dtype;
785 
786  if( this->root_ ){
787  TEUCHOS_TEST_FOR_EXCEPTION( nnz_ret != as<int>(this->globalNumNonZeros_),
788  std::runtime_error,
789  "Did not get the expected number of non-zero vals");
790 
791  function_map::create_CompCol_Matrix( &(data_.A),
792  this->globalNumRows_, this->globalNumCols_,
793  nnz_ret,
794  nzvals_.getRawPtr(),
795  rowind_.getRawPtr(),
796  colptr_.getRawPtr(),
797  SLU::SLU_NC, dtype, SLU::SLU_GE);
798  }
799 
800  return true;
801 }
802 
803 
804 template<class Matrix, class Vector>
805 const char* Superlu<Matrix,Vector>::name = "SuperLU";
806 
807 
808 } // end namespace Amesos2
809 
810 #endif // AMESOS2_SUPERLU_DEF_HPP
Amesos2::SolverCore: A templated interface for interaction with third-party direct sparse solvers...
Definition: Amesos2_SolverCore_decl.hpp:105
bool loadA_impl(EPhase current_phase)
Reads matrix data into internal structures.
Definition: Amesos2_Superlu_def.hpp:731
EPhase
Used to indicate a phase in the direct solution.
Definition: Amesos2_TypeDecl.hpp:65
int numericFactorization_impl()
Superlu specific numeric factorization.
Definition: Amesos2_Superlu_def.hpp:233
global_size_type globalNumCols_
Number of global columns in matrixA_.
Definition: Amesos2_SolverCore_decl.hpp:478
~Superlu()
Destructor.
Definition: Amesos2_Superlu_def.hpp:109
global_size_type globalNumRows_
Number of global rows in matrixA_.
Definition: Amesos2_SolverCore_decl.hpp:475
Amesos2 Superlu declarations.
bool matrixShapeOK_impl() const
Determines whether the shape of the matrix is OK for this solver.
Definition: Amesos2_Superlu_def.hpp:509
Helper class for getting 1-D copies of multivectors.
Definition: Amesos2_MultiVecAdapter_decl.hpp:266
Superlu(Teuchos::RCP< const Matrix > A, Teuchos::RCP< Vector > X, Teuchos::RCP< const Vector > B)
Initialize from Teuchos::RCP.
Definition: Amesos2_Superlu_def.hpp:67
Teuchos::RCP< const Teuchos::ParameterList > getValidParameters_impl() const
Definition: Amesos2_Superlu_def.hpp:605
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
Superlu specific solve.
Definition: Amesos2_Superlu_def.hpp:374
A Matrix adapter interface for Amesos2.
Definition: Amesos2_MatrixAdapter_decl.hpp:76
void setParameters_impl(const Teuchos::RCP< Teuchos::ParameterList > &parameterList)
Definition: Amesos2_Superlu_def.hpp:520
int preOrdering_impl()
Performs pre-ordering on the matrix to increase efficiency.
Definition: Amesos2_Superlu_def.hpp:186
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
std::string description() const
Returns a short description of this Solver.
Definition: Amesos2_Superlu_def.hpp:132
int symbolicFactorization_impl()
Perform symbolic factorization of the matrix using Superlu.
Definition: Amesos2_Superlu_def.hpp:211
Amesos2 interface to the SuperLU package.
Definition: Amesos2_Superlu_decl.hpp:73