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
16
17
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
33
34namespace 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
152 MUMPS<Matrix,Vector>::symbolicFactorization_impl()
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
391 MUMPS<Matrix,Vector>::ConvertToTriplet()
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
Amesos2 MUMPS declarations.
@ ROOTED
Definition Amesos2_TypeDecl.hpp:93
@ CONTIGUOUS_AND_ROOTED
Definition Amesos2_TypeDecl.hpp:94
@ ARBITRARY
Definition Amesos2_TypeDecl.hpp:109
Amesos2 interface to the MUMPS package.
Definition Amesos2_MUMPS_decl.hpp:51
Teuchos::Array< mumps_type > xvals_
Persisting 1D store for X.
Definition Amesos2_MUMPS_decl.hpp:189
host_ordinal_type_view host_rows_view_
Stores the location in Ai_ and Aval_ that starts row j.
Definition Amesos2_MUMPS_decl.hpp:184
bool loadA_impl(EPhase current_phase)
Reads matrix data into internal structures.
Definition Amesos2_MUMPS_def.hpp:334
bool matrixShapeOK_impl() const
Determines whether the shape of the matrix is OK for this solver.
Definition Amesos2_MUMPS_def.hpp:254
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
host_value_type_view host_nzvals_view_
Stores the values of the nonzero entries for MUMPS.
Definition Amesos2_MUMPS_decl.hpp:182
host_ordinal_type_view host_col_ptr_view_
Stores the row indices of the nonzero entries.
Definition Amesos2_MUMPS_decl.hpp:186
int numericFactorization_impl()
MUMPS specific numeric factorization.
Definition Amesos2_MUMPS_def.hpp:168
int preOrdering_impl()
Performs pre-ordering on the matrix to increase efficiency.
Definition Amesos2_MUMPS_def.hpp:139
Teuchos::RCP< const Teuchos::ParameterList > getValidParameters_impl() const
Definition Amesos2_MUMPS_def.hpp:306
Teuchos::Array< mumps_type > bvals_
Persisting 1D store for B.
Definition Amesos2_MUMPS_decl.hpp:191
void setParameters_impl(const Teuchos::RCP< Teuchos::ParameterList > &parameterList)
Definition Amesos2_MUMPS_def.hpp:263
A Matrix adapter interface for Amesos2.
Definition Amesos2_MatrixAdapter_decl.hpp:42
Amesos2::SolverCore: A templated interface for interaction with third-party direct sparse solvers.
Definition Amesos2_SolverCore_decl.hpp:72
Teuchos::RCP< const MatrixAdapter< Matrix > > matrixA_
Definition Amesos2_SolverCore_decl.hpp:421
bool root_
Definition Amesos2_SolverCore_decl.hpp:472
global_size_type rowIndexBase_
Definition Amesos2_SolverCore_decl.hpp:451
global_size_type globalNumCols_
Definition Amesos2_SolverCore_decl.hpp:445
Timers timers_
Definition Amesos2_SolverCore_decl.hpp:463
Teuchos::RCP< const Teuchos::Comm< int > > getComm() const override
Returns a pointer to the Teuchos::Comm communicator with this operator.
Definition Amesos2_SolverCore_decl.hpp:329
global_size_type globalNumNonZeros_
Definition Amesos2_SolverCore_decl.hpp:448
global_size_type globalNumRows_
Definition Amesos2_SolverCore_decl.hpp:442
EPhase
Used to indicate a phase in the direct solution.
Definition Amesos2_TypeDecl.hpp:31
Passes functions to TPL functions based on type.
Definition Amesos2_FunctionMap.hpp:43
A templated MultiVector class adapter for Amesos2.
Definition Amesos2_MultiVecAdapter_decl.hpp:142
Helper class for getting 1-D copies of multivectors.
Definition Amesos2_MultiVecAdapter_decl.hpp:233
A generic helper class for getting a CCS representation of a Matrix.
Definition Amesos2_Util.hpp:615
Helper class for putting 1-D data arrays into multivectors.
Definition Amesos2_MultiVecAdapter_decl.hpp:339