Amesos2 - Direct Sparse Solver Interfaces  Version of the Day
Amesos2_MUMPS_def.hpp
Go to the documentation of this file.
1 // @HEADER
2 // *****************************************************************************
3 // Amesos2: Templated Direct Sparse Solver Package
4 //
5 // Copyright 2011 NTESS and the Amesos2 contributors.
6 // SPDX-License-Identifier: BSD-3-Clause
7 // *****************************************************************************
8 // @HEADER
9 
18 #ifndef AMESOS2_MUMPS_DEF_HPP
19 #define AMESOS2_MUMPS_DEF_HPP
20 
21 #include <Teuchos_Tuple.hpp>
22 #include <Teuchos_ParameterList.hpp>
23 #include <Teuchos_StandardParameterEntryValidators.hpp>
24 
25 #ifdef HAVE_MPI
26 #include <Teuchos_DefaultMpiComm.hpp>
27 #endif
28 
29 #include <limits>
30 
32 #include "Amesos2_MUMPS_decl.hpp"
33 
34 namespace Amesos2
35 {
36 
37 
38  template <class Matrix, class Vector>
39  MUMPS<Matrix,Vector>::MUMPS(
40  Teuchos::RCP<const Matrix> A,
41  Teuchos::RCP<Vector> X,
42  Teuchos::RCP<const Vector> B )
43  : SolverCore<Amesos2::MUMPS,Matrix,Vector>(A, X, B)
44  , is_contiguous_(true)
45  {
46 
47  typedef FunctionMap<MUMPS,scalar_type> function_map;
48 
49  MUMPS_MATRIX_LOAD = false;
50  MUMPS_STRUCT = false;
51  MUMPS_MATRIX_LOAD_PREORDERING = false;
52 
53  #ifdef HAVE_MPI
54  using Teuchos::Comm;
55  using Teuchos::MpiComm;
56  using Teuchos::RCP;
57  using Teuchos::rcp;
58  using Teuchos::rcp_dynamic_cast;
59 
60  //Comm
61  mumps_par.comm_fortran = -987654;
62  RCP<const Comm<int> > matComm = this->matrixA_->getComm();
63  //Add Exception Checking
64  TEUCHOS_TEST_FOR_EXCEPTION(
65  matComm.is_null(), std::logic_error, "Amesos2::Comm");
66  RCP<const MpiComm<int> > matMpiComm =
67  rcp_dynamic_cast<const MpiComm<int> >(matComm);
68  //Add Exception Checking
69  TEUCHOS_TEST_FOR_EXCEPTION(
70  matMpiComm->getRawMpiComm().is_null(),
71  std::logic_error, "Amesos2::MPI");
72  MPI_Comm rawMpiComm = (* (matMpiComm->getRawMpiComm()) )();
73  mumps_par.comm_fortran = (int) MPI_Comm_c2f(rawMpiComm);
74  #endif
75 
76  mumps_par.job = -1;
77  mumps_par.par = 1;
78  mumps_par.sym = 0;
79 
80  function_map::mumps_c(&(mumps_par)); //init
81  MUMPS_ERROR();
82 
83  mumps_par.n = this->globalNumCols_;
84 
85  /*Default parameters*/
86  mumps_par.icntl[0] = -1; // Turn off error messages
87  mumps_par.icntl[1] = -1; // Turn off diagnositic printing
88  mumps_par.icntl[2] = -1; // Turn off global information messages
89  mumps_par.icntl[3] = 1; // No messages
90  mumps_par.icntl[4] = 0; // Matrix given in assembled (Triplet) form
91  mumps_par.icntl[5] = 7; // Choose column permuation automatically
92  mumps_par.icntl[6] = 7; // Choose ordering methods automatically
93  mumps_par.icntl[7] = 7; // Choose scaling automatically
94  mumps_par.icntl[8] = 1; // Compuate Ax = b;
95  mumps_par.icntl[9] = 0; // iterative refinement
96  mumps_par.icntl[10] = 0; //Do not collect statistics
97  mumps_par.icntl[11] = 0; // Automatic choice of ordering strategy
98  mumps_par.icntl[12] = 0; //Use ScaLAPACK for root node
99  mumps_par.icntl[13] = 20; // Increase memory allocation 20% at a time
100  mumps_par.icntl[17] = 0;
101  mumps_par.icntl[18] = 0; // do not provide back the Schur complement
102  mumps_par.icntl[19] = 0; // RHS is given in dense form
103  mumps_par.icntl[20] = 0; //RHS is in dense form
104  mumps_par.icntl[21] = 0; // Do all compuations in-core
105  mumps_par.icntl[22] = 0; // No max MB for work
106  mumps_par.icntl[23] = 0; // Do not perform null pivot detection
107  mumps_par.icntl[24] = 0; // No null space basis compuation
108  mumps_par.icntl[25] = 0; // Do not condense/reduce Schur RHS
109  mumps_par.icntl[27] = 1; // sequential analysis
110  mumps_par.icntl[28] = 0; //
111  mumps_par.icntl[29] = 0; //
112  mumps_par.icntl[30] = 0; //
113  mumps_par.icntl[31] = 0;
114  mumps_par.icntl[32] = 0;
115 
116  }
117 
118  template <class Matrix, class Vector>
119  MUMPS<Matrix,Vector>::~MUMPS( )
120  {
121  /* Clean up the struc*/
122  typedef FunctionMap<MUMPS,scalar_type> function_map;
123 
124  if(MUMPS_STRUCT == true)
125  {
126  free(mumps_par.a);
127  free(mumps_par.jcn);
128  free(mumps_par.irn);
129  }
130  mumps_par.job = -2;
131  if (this->rank_ < this->nprocs_) {
132  function_map::mumps_c(&(mumps_par));
133  }
134 
135  }
136 
137  template<class Matrix, class Vector>
138  int
140  {
141  /* TODO: Define what it means for MUMPS
142  */
143  #ifdef HAVE_AMESOS2_TIMERS
144  Teuchos::TimeMonitor preOrderTimer(this->timers_.preOrderTime_);
145  #endif
146 
147  return(0);
148  }//end preOrdering_impl()
149 
150  template <class Matrix, class Vector>
151  int
153  {
154 
155  typedef FunctionMap<MUMPS,scalar_type> function_map;
156 
157  mumps_par.par = 1;
158  mumps_par.job = 1; // sym factor
159  function_map::mumps_c(&(mumps_par));
160  MUMPS_ERROR();
161 
162  return(0);
163  }//end symblicFactortion_impl()
164 
165 
166  template <class Matrix, class Vector>
167  int
169  {
170  using Teuchos::as;
171  typedef FunctionMap<MUMPS,scalar_type> function_map;
172 
173  if ( this->root_ )
174  {
175  { // Do factorization
176  #ifdef HAVE_AMESOS2_TIMERS
177  Teuchos::TimeMonitor numFactTimer(this->timers_.numFactTime_);
178  #endif
179  }
180  }
181  mumps_par.job = 2;
182  function_map::mumps_c(&(mumps_par));
183  MUMPS_ERROR();
184 
185  return(0);
186  }//end numericFactorization_impl()
187 
188 
189  template <class Matrix, class Vector>
190  int
192  const Teuchos::Ptr<MultiVecAdapter<Vector> > X,
193  const Teuchos::Ptr<const MultiVecAdapter<Vector> > B) const
194  {
195 
196  typedef FunctionMap<MUMPS,scalar_type> function_map;
197 
198  using Teuchos::as;
199 
200  const global_size_type ld_rhs = this->root_ ? X->getGlobalLength() : 0;
201  const size_t nrhs = X->getGlobalNumVectors();
202 
203  const size_t val_store_size = as<size_t>(ld_rhs * nrhs);
204 
205  xvals_.resize(val_store_size);
206  bvals_.resize(val_store_size);
207 
208  #ifdef HAVE_AMESOS2_TIMERS
209  Teuchos::TimeMonitor mvConvTimer(this->timers_.vecConvTime_);
210  Teuchos::TimeMonitor redistTimer( this->timers_.vecRedistTime_ );
211  #endif
212 
214  mumps_type>::do_get(B, bvals_(),
215  as<size_t>(ld_rhs),
216  (is_contiguous_ == true) ? ROOTED : CONTIGUOUS_AND_ROOTED,
217  this->rowIndexBase_);
218 
219  int ierr = 0; // returned error code
220  mumps_par.nrhs = nrhs;
221  mumps_par.lrhs = mumps_par.n;
222  mumps_par.job = 3;
223 
224  if ( this->root_ )
225  {
226  mumps_par.rhs = bvals_.getRawPtr();
227  }
228 
229  #ifdef HAVE_AMESOS2_TIMERS
230  Teuchos::TimeMonitor solveTimer(this->timers_.solveTime_);
231  #endif
232 
233  function_map::mumps_c(&(mumps_par));
234  MUMPS_ERROR();
235 
236 
237  #ifdef HAVE_AMESOS2_TIMERS
238  Teuchos::TimeMonitor redistTimer2(this->timers_.vecRedistTime_);
239  #endif
240 
242  MultiVecAdapter<Vector>,mumps_type>::do_put(X, bvals_(),
243  as<size_t>(ld_rhs),
244  (is_contiguous_ == true) ? ROOTED : CONTIGUOUS_AND_ROOTED);
245 
246  // ch: see function loadA_impl()
247  MUMPS_MATRIX_LOAD_PREORDERING = false;
248  return(ierr);
249  }//end solve()
250 
251 
252  template <class Matrix, class Vector>
253  bool
255  {
256  // The MUMPS can only handle square for right now
257  return( this->globalNumRows_ == this->globalNumCols_ );
258  }
259 
260 
261  template <class Matrix, class Vector>
262  void
263  MUMPS<Matrix,Vector>::setParameters_impl(const Teuchos::RCP<Teuchos::ParameterList> & parameterList )
264  {
265  using Teuchos::RCP;
266  using Teuchos::getIntegralValue;
267  using Teuchos::ParameterEntryValidator;
268 
269  RCP<const Teuchos::ParameterList> valid_params = getValidParameters_impl();
270  /*To Do --- add support for parameters */
271  if(parameterList->isParameter("ICNTL(1)")){
272  mumps_par.icntl[0] = parameterList->get<int>("ICNTL(1)", -1);
273  }
274  if(parameterList->isParameter("ICNTL(2)")){
275  mumps_par.icntl[1] = parameterList->get<int>("ICNTL(2)", -1);
276  }
277  if(parameterList->isParameter("ICNTL(3)")){
278  mumps_par.icntl[2] = parameterList->get<int>("ICNTL(3)", -1);
279  }
280  if(parameterList->isParameter("ICNTL(4)")){
281  mumps_par.icntl[3] = parameterList->get<int>("ICNTL(4)", 1);
282  }
283  if(parameterList->isParameter("ICNTL(6)")){
284  mumps_par.icntl[5] = parameterList->get<int>("ICNTL(6)", 0);
285  }
286  if(parameterList->isParameter("ICNTL(7)")){
287  mumps_par.icntl[6] = parameterList->get<int>("ICNTL(7)", 7);
288  }
289  if(parameterList->isParameter("ICNTL(9)")){
290  mumps_par.icntl[8] = parameterList->get<int>("ICNTL(9)", 1);
291  }
292  if(parameterList->isParameter("ICNTL(11)")){
293  mumps_par.icntl[10] = parameterList->get<int>("ICNTL(11)", 0);
294  }
295  if(parameterList->isParameter("ICNTL(14)")){
296  mumps_par.icntl[13] = parameterList->get<int>("ICNTL(14)", 20);
297  }
298  if( parameterList->isParameter("IsContiguous") ){
299  is_contiguous_ = parameterList->get<bool>("IsContiguous");
300  }
301  }//end set parameters()
302 
303 
304  template <class Matrix, class Vector>
305  Teuchos::RCP<const Teuchos::ParameterList>
307  {
308  using Teuchos::ParameterList;
309 
310  static Teuchos::RCP<const Teuchos::ParameterList> valid_params;
311 
312  if( is_null(valid_params) ){
313  Teuchos::RCP<Teuchos::ParameterList> pl = Teuchos::parameterList();
314 
315  pl->set("ICNTL(1)", -1, "See Manual" );
316  pl->set("ICNTL(2)", -1, "See Manual" );
317  pl->set("ICNTL(3)", -1, "See Manual" );
318  pl->set("ICNTL(4)", 1, "See Manual" );
319  pl->set("ICNTL(6)", 0, "See Manual" );
320  pl->set("ICNTL(9)", 1, "See Manual" );
321  pl->set("ICNTL(11)", 0, "See Manual" );
322  pl->set("ICNTL(14)", 20, "See Manual" );
323  pl->set("IsContiguous", true, "Whether GIDs contiguous");
324 
325  valid_params = pl;
326  }
327 
328  return valid_params;
329  }//end getValidParmaeters_impl()
330 
331 
332  template <class Matrix, class Vector>
333  bool
335  {
336  using Teuchos::as;
337 
338  #ifdef HAVE_AMESOS2_TIMERS
339  Teuchos::TimeMonitor convTimer(this->timers_.mtxConvTime_);
340  #endif
341  if(MUMPS_MATRIX_LOAD == false || (current_phase==NUMFACT && !MUMPS_MATRIX_LOAD_PREORDERING))
342  {
343  // Only the root image needs storage allocated
344  if( !MUMPS_MATRIX_LOAD && this->root_ ){
345  Kokkos::resize(host_nzvals_view_, this->globalNumNonZeros_);
346  Kokkos::resize(host_rows_view_, this->globalNumNonZeros_);
347  Kokkos::resize(host_col_ptr_view_, this->globalNumRows_ + 1);
348  }
349 
350  local_ordinal_type nnz_ret = 0;
351 
352  #ifdef HAVE_AMESOS2_TIMERS
353  Teuchos::TimeMonitor mtxRedistTimer( this->timers_.mtxRedistTime_ );
354  #endif
355 
357  MatrixAdapter<Matrix>,host_value_type_view,host_ordinal_type_view,host_ordinal_type_view>
358  ::do_get(this->matrixA_.ptr(), host_nzvals_view_, host_rows_view_, host_col_ptr_view_, nnz_ret,
359  (is_contiguous_ == true) ? ROOTED : CONTIGUOUS_AND_ROOTED,
360  ARBITRARY,
361  this->rowIndexBase_);
362 
363  if( this->root_ ){
364  TEUCHOS_TEST_FOR_EXCEPTION( nnz_ret != as<local_ordinal_type>(this->globalNumNonZeros_),
365  std::runtime_error,
366  "Did not get the expected number of non-zero vals");
367  }
368 
369 
370  if( this->root_ ){
371  ConvertToTriplet();
372  }
373  /* ch: In general, the matrix is loaded during the preordering phase.
374  However, if the matrix pattern has not changed during consecutive calls of numeric factorizations
375  we can reuse the previous symbolic factorization. In this case, the matrix is not loaded in the preordering phase,
376  because it is not called. Therefore, we need to load the matrix in the numeric factorization phase.
377  */
378  if (current_phase==PREORDERING){
379  MUMPS_MATRIX_LOAD_PREORDERING = true;
380  }
381  }
382 
383 
384 
385  MUMPS_MATRIX_LOAD = true;
386  return (true);
387  }//end loadA_impl()
388 
389  template <class Matrix, class Vector>
390  int
392  {
393  if ( !MUMPS_STRUCT ) {
394  MUMPS_STRUCT = true;
395  mumps_par.n = this->globalNumCols_;
396  mumps_par.nz = this->globalNumNonZeros_;
397  mumps_par.a = (mumps_type*)malloc(mumps_par.nz * sizeof(mumps_type));
398  mumps_par.irn = (MUMPS_INT*)malloc(mumps_par.nz *sizeof(MUMPS_INT));
399  mumps_par.jcn = (MUMPS_INT*)malloc(mumps_par.nz * sizeof(MUMPS_INT));
400  }
401  if((mumps_par.a == NULL) || (mumps_par.irn == NULL)
402  || (mumps_par.jcn == NULL))
403  {
404  return -1;
405  }
406  /* Going from full CSC to full Triplet */
407  /* Will have to add support for symmetric case*/
408  local_ordinal_type tri_count = 0;
409  local_ordinal_type i,j;
410  local_ordinal_type max_local_ordinal = 0;
411 
412  for(i = 0; i < (local_ordinal_type)this->globalNumCols_; i++)
413  {
414  for( j = host_col_ptr_view_(i); j < host_col_ptr_view_(i+1)-1; j++)
415  {
416  mumps_par.jcn[tri_count] = (MUMPS_INT)i+1; //Fortran index
417  mumps_par.irn[tri_count] = (MUMPS_INT)host_rows_view_(j)+1; //Fortran index
418  mumps_par.a[tri_count] = host_nzvals_view_(j);
419 
420  tri_count++;
421  }
422 
423  j = host_col_ptr_view_(i+1)-1;
424  mumps_par.jcn[tri_count] = (MUMPS_INT)i+1; //Fortran index
425  mumps_par.irn[tri_count] = (MUMPS_INT)host_rows_view_(j)+1; //Fortran index
426  mumps_par.a[tri_count] = host_nzvals_view_(j);
427 
428  tri_count++;
429 
430  if(host_rows_view_(j) > max_local_ordinal)
431  {
432  max_local_ordinal = host_rows_view_(j);
433  }
434  }
435  TEUCHOS_TEST_FOR_EXCEPTION(std::numeric_limits<MUMPS_INT>::max() <= max_local_ordinal,
436  std::runtime_error,
437  "Matrix index larger than MUMPS_INT");
438 
439  return 0;
440  }//end Convert to Trip()
441 
442  template<class Matrix, class Vector>
443  void
444  MUMPS<Matrix,Vector>::MUMPS_ERROR()const
445  {
446  using Teuchos::Comm;
447  using Teuchos::RCP;
448  bool Wrong = ((mumps_par.info[0] != 0) || (mumps_par.infog[0] != 0)) && (this->rank_ < this->nprocs_);
449  if(Wrong){
450  if (this->rank_==0) {
451  std::cerr << "Amesos_Mumps : ERROR" << std::endl;
452  std::cerr << "Amesos_Mumps : INFOG(1) = " << mumps_par.infog[0] << std::endl;
453  std::cerr << "Amesos_Mumps : INFOG(2) = " << mumps_par.infog[1] << std::endl;
454  }
455  if (mumps_par.info[0] != 0 && Wrong) {
456  std::cerr << "Amesos_Mumps : On process " << this->matrixA_->getComm()->getRank()
457  << ", INFO(1) = " << mumps_par.info[0] << std::endl;
458  std::cerr << "Amesos_Mumps : On process " << this->matrixA_->getComm()->getRank()
459  << ", INFO(2) = " << mumps_par.info[1] << std::endl;
460  }
461 
462 
463  }
464  // Throw on all ranks
465  int WrongInt = Wrong;
466  RCP<const Comm<int> > matComm = this->matrixA_->getComm();
467  Teuchos::broadcast<int,int>(*matComm,0,1,&WrongInt);
468  TEUCHOS_TEST_FOR_EXCEPTION(WrongInt>0,
469  std::runtime_error,
470  "MUMPS error");
471 
472  }//end MUMPS_ERROR()
473 
474 
475  template<class Matrix, class Vector>
476  const char* MUMPS<Matrix,Vector>::name = "MUMPS";
477 
478 } // end namespace Amesos2
479 
480 #endif // AMESOS2_MUMPS_DEF_HPP
A generic helper class for getting a CCS representation of a Matrix.
Definition: Amesos2_Util.hpp:614
int numericFactorization_impl()
MUMPS specific numeric factorization.
Definition: Amesos2_MUMPS_def.hpp:168
EPhase
Used to indicate a phase in the direct solution.
Definition: Amesos2_TypeDecl.hpp:31
global_size_type globalNumCols_
Number of global columns in matrixA_.
Definition: Amesos2_SolverCore_decl.hpp:445
Amesos2 MUMPS declarations.
Helper class for getting 1-D copies of multivectors.
Definition: Amesos2_MultiVecAdapter_decl.hpp:233
int preOrdering_impl()
Performs pre-ordering on the matrix to increase efficiency.
Definition: Amesos2_MUMPS_def.hpp:139
int solve_impl(const Teuchos::Ptr< MultiVecAdapter< Vector > > X, const Teuchos::Ptr< const MultiVecAdapter< Vector > > B) const
MUMPS specific solve.
Definition: Amesos2_MUMPS_def.hpp:191
bool matrixShapeOK_impl() const
Determines whether the shape of the matrix is OK for this solver.
Definition: Amesos2_MUMPS_def.hpp:254
bool loadA_impl(EPhase current_phase)
Reads matrix data into internal structures.
Definition: Amesos2_MUMPS_def.hpp:334
Amesos2 interface to the MUMPS package.
Definition: Amesos2_MUMPS_decl.hpp:50
A Matrix adapter interface for Amesos2.
Definition: Amesos2_MatrixAdapter_decl.hpp:42
Teuchos::RCP< const Teuchos::ParameterList > getValidParameters_impl() const
Definition: Amesos2_MUMPS_def.hpp:306
void setParameters_impl(const Teuchos::RCP< Teuchos::ParameterList > &parameterList)
Definition: Amesos2_MUMPS_def.hpp:263
Passes functions to TPL functions based on type.
Definition: Amesos2_FunctionMap.hpp:42
Helper class for putting 1-D data arrays into multivectors.
Definition: Amesos2_MultiVecAdapter_decl.hpp:339
A templated MultiVector class adapter for Amesos2.
Definition: Amesos2_MultiVecAdapter_decl.hpp:142
Teuchos::RCP< const MatrixAdapter< Matrix > > matrixA_
The LHS operator.
Definition: Amesos2_SolverCore_decl.hpp:421