Amesos2 - Direct Sparse Solver Interfaces Version of the Day
Amesos2_CssMKL_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
10
19#ifndef AMESOS2_CSSMKL_DEF_HPP
20#define AMESOS2_CSSMKL_DEF_HPP
21
22#include <map>
23
24#include <Teuchos_Tuple.hpp>
25#include <Teuchos_toString.hpp>
26#include <Teuchos_StandardParameterEntryValidators.hpp>
27
30
31
32namespace Amesos2 {
33
34 namespace PMKL {
35# include <mkl.h>
36# include <mkl_pardiso.h>
37 }
38
39 template <class Matrix, class Vector>
40 CssMKL<Matrix,Vector>::CssMKL(Teuchos::RCP<const Matrix> A,
41 Teuchos::RCP<Vector> X,
42 Teuchos::RCP<const Vector> B)
43 : SolverCore<Amesos2::CssMKL,Matrix,Vector>(A, X, B) // instantiate superclass
44 , n_(Teuchos::as<int_t>(this->globalNumRows_))
45 , perm_(this->globalNumRows_)
46 , nrhs_(0)
47 , css_initialized_(false)
48 , is_contiguous_(true)
49 , msglvl_(0)
50 {
51 // Matrix info
52 Teuchos::RCP<const Teuchos::Comm<int> > matComm = this->matrixA_->getComm ();
53 const global_ordinal_type indexBase = this->matrixA_->getRowMap ()->getIndexBase ();
54 const local_ordinal_type nrows = this->matrixA_->getLocalNumRows();
55
56 // rowmap for loadA (to have locally contiguous)
57 css_rowmap_ =
58 Teuchos::rcp (new map_type (this->globalNumRows_, nrows, indexBase, matComm));
59 css_contig_rowmap_ = Teuchos::rcp (new map_type (0, 0, indexBase, matComm));
60 css_contig_colmap_ = Teuchos::rcp (new map_type (0, 0, indexBase, matComm));
61
62 // set the default matrix type
64 set_css_mkl_default_parameters(pt_, iparm_);
65
66 // index base
67 iparm_[34] = (indexBase == 0 ? 1 : 0); /* Use one or zero-based indexing */
68 // 1D block-row distribution (using Contiguous map)
69 auto frow = css_rowmap_->getMinGlobalIndex();
70 iparm_[39] = 2; /* Matrix input format. */
71 iparm_[40] = frow; /* > Beginning of input domain. */
72 iparm_[41] = frow+nrows-1; /* > End of input domain. */
73
74 // get MPI Comm
75 TEUCHOS_TEST_FOR_EXCEPTION(
76 matComm.is_null (), std::logic_error, "Amesos2::CssMKL "
77 "constructor: The matrix's communicator is null!");
78 Teuchos::RCP<const Teuchos::MpiComm<int> > matMpiComm =
79 Teuchos::rcp_dynamic_cast<const Teuchos::MpiComm<int> > (matComm);
80 TEUCHOS_TEST_FOR_EXCEPTION(
81 matMpiComm.is_null (), std::logic_error, "Amesos2::CssMKL "
82 "constructor: The matrix's communicator is not an MpiComm!");
83 TEUCHOS_TEST_FOR_EXCEPTION(
84 matMpiComm->getRawMpiComm ().is_null (), std::logic_error, "Amesos2::"
85 "CssMKL constructor: The matrix's communicator claims to be a "
86 "Teuchos::MpiComm<int>, but its getRawPtrComm() method returns "
87 "Teuchos::null! This means that the underlying MPI_Comm doesn't even "
88 "exist, which likely implies that the Teuchos::MpiComm was constructed "
89 "incorrectly. It means something different than if the MPI_Comm were "
90 "MPI_COMM_NULL.");
91 MPI_Comm CssComm = *(matMpiComm->getRawMpiComm ());
92 CssComm_ = MPI_Comm_c2f(CssComm);
93 }
94
95
96 template <class Matrix, class Vector>
98 {
99 /*
100 * Free any memory allocated by the CssMKL library functions
101 */
102 int_t error = 0;
103 if (css_initialized_)
104 {
105 int_t phase = -1; // release all internal solver memory
106 void *bdummy, *xdummy;
107 const MPI_Fint CssComm = CssComm_;
108 function_map::cluster_sparse_solver( pt_, const_cast<int_t*>(&maxfct_),
109 const_cast<int_t*>(&mnum_), &mtype_, &phase, &n_,
110 nzvals_view_.data(), rowptr_view_.data(),
111 colind_view_.data(), perm_.getRawPtr(), &nrhs_, iparm_,
112 const_cast<int_t*>(&msglvl_), &bdummy, &xdummy, &CssComm, &error );
113 css_initialized_ = false;
114 }
115 check_css_mkl_error(Amesos2::CLEAN, error);
116 }
117
118
119 template<class Matrix, class Vector>
120 int
122 {
123 // preOrdering done during "Analysis" (aka symbolic
124 // factorization) phase
125 return(0);
126 }
127
128
129 template <class Matrix, class Vector>
130 int
132 {
133 if (msglvl_ > 0 && this->matrixA_->getComm()->getRank() == 0) {
134 std::cout << " CssMKL::symbolicFactorization:\n" << std::endl;
135 for (int i=0; i < 64; i++) std::cout << " * IPARM[" << i << "] = " << iparm_[i] << std::endl;
136 }
137 int_t error = 0;
138 {
139#ifdef HAVE_AMESOS2_TIMERS
140 Teuchos::TimeMonitor symbFactTimer( this->timers_.symFactTime_ );
141#endif
142
143 if (css_initialized_)
144 {
145 int_t phase = -1; // release all internal solver memory
146 void *bdummy, *xdummy;
147 const MPI_Fint CssComm = CssComm_;
148 function_map::cluster_sparse_solver( pt_, const_cast<int_t*>(&maxfct_),
149 const_cast<int_t*>(&mnum_), &mtype_, &phase, &n_,
150 nzvals_view_.data(), rowptr_view_.data(),
151 colind_view_.data(), perm_.getRawPtr(), &nrhs_, iparm_,
152 const_cast<int_t*>(&msglvl_), &bdummy, &xdummy, &CssComm, &error );
153 css_initialized_ = false;
154 if (msglvl_ > 0 && error != 0 && this->matrixA_->getComm()->getRank() == 0) {
155 std::cout << " CssMKL::symbolicFactorization: clean-up failed with " << error << std::endl;
156 }
157 }
158
159 error = 0;
160 int_t phase = 11; // Analysis
161 void *bdummy, *xdummy;
162 const MPI_Fint CssComm = CssComm_;
163 function_map::cluster_sparse_solver( pt_, const_cast<int_t*>(&maxfct_),
164 const_cast<int_t*>(&mnum_), &mtype_, &phase, &n_,
165 nzvals_view_.data(), rowptr_view_.data(),
166 colind_view_.data(), perm_.getRawPtr(), &nrhs_, iparm_,
167 const_cast<int_t*>(&msglvl_), &bdummy, &xdummy, &CssComm, &error );
168 }
169 check_css_mkl_error(Amesos2::SYMBFACT, error);
170 if (msglvl_ > 0 && this->matrixA_->getComm()->getRank() == 0) {
171 std::cout << " CssMKL::symbolicFactorization done:" << std::endl;
172#ifdef HAVE_AMESOS2_TIMERS
173 std::cout << " * Time : " << this->timers_.symFactTime_.totalElapsedTime() << std::endl;
174#else
175 std::cout << " * Time : not enabled" << std::endl;
176#endif
177 }
178
179 // CSS only lets you retrieve the total number of factor
180 // non-zeros, not for each individually. We should document how
181 // such a situation is reported.
182 this->setNnzLU(iparm_[17]);
183 css_initialized_ = true;
184 return(0);
185 }
186
187
188 template <class Matrix, class Vector>
189 int
191 {
192 if (msglvl_ > 0 && this->matrixA_->getComm()->getRank() == 0) {
193 std::cout << " CssMKL::numericFactorization:\n" << std::endl;
194 }
195 int_t error = 0;
196 {
197#ifdef HAVE_AMESOS2_TIMERS
198 Teuchos::TimeMonitor numFactTimer( this->timers_.numFactTime_ );
199#endif
200
201 //int_t phase = 12; // Analysis, numerical factorization
202 int_t phase = 22; // Numerical factorization
203 void *bdummy, *xdummy;
204 const MPI_Fint CssComm = CssComm_;
205 function_map::cluster_sparse_solver( pt_, const_cast<int_t*>(&maxfct_),
206 const_cast<int_t*>(&mnum_), &mtype_, &phase, &n_,
207 nzvals_view_.data(), rowptr_view_.data(),
208 colind_view_.data(), perm_.getRawPtr(), &nrhs_, iparm_,
209 const_cast<int_t*>(&msglvl_), &bdummy, &xdummy, &CssComm, &error );
210 }
211 check_css_mkl_error(Amesos2::NUMFACT, error);
212 if (msglvl_ > 0 && this->matrixA_->getComm()->getRank() == 0) {
213 std::cout << " CssMKL::numericFactorization done:" << std::endl;
214#ifdef HAVE_AMESOS2_TIMERS
215 std::cout << " * Time : " << this->timers_.numFactTime_.totalElapsedTime() << std::endl;
216#else
217 std::cout << " * Time : not enabled" << std::endl;
218#endif
219 }
220
221 return( 0 );
222 }
223
224
225 template <class Matrix, class Vector>
226 int
228 const Teuchos::Ptr<const MultiVecAdapter<Vector> > B) const
229 {
230 using Teuchos::as;
231
232 // Get B data
233 const local_ordinal_type ld_rhs = this->matrixA_->getLocalNumRows();
234 nrhs_ = as<int_t>(X->getGlobalNumVectors());
235
236 const size_t val_store_size = as<size_t>(ld_rhs * nrhs_);
237 xvals_.resize(val_store_size);
238 bvals_.resize(val_store_size);
239 {
240#ifdef HAVE_AMESOS2_TIMERS
241 Teuchos::TimeMonitor mvConvTimer( this->timers_.vecConvTime_ );
242 Teuchos::TimeMonitor redistTimer( this->timers_.vecRedistTime_ );
243#endif
244
247 solver_scalar_type>::do_get(B, bvals_(),
248 as<size_t>(ld_rhs),
249 Teuchos::ptrInArg(*css_rowmap_));
250 }
251
252 int_t error = 0;
253 {
254#ifdef HAVE_AMESOS2_TIMERS
255 Teuchos::TimeMonitor solveTimer( this->timers_.solveTime_ );
256#endif
257
258 const int_t phase = 33; // Solve, iterative refinement
259 const MPI_Fint CssComm = CssComm_;
260 function_map::cluster_sparse_solver( pt_,
261 const_cast<int_t*>(&maxfct_),
262 const_cast<int_t*>(&mnum_),
263 const_cast<int_t*>(&mtype_),
264 const_cast<int_t*>(&phase),
265 const_cast<int_t*>(&n_),
266 const_cast<solver_scalar_type*>(nzvals_view_.data()),
267 const_cast<int_t*>(rowptr_view_.data()),
268 const_cast<int_t*>(colind_view_.data()),
269 const_cast<int_t*>(perm_.getRawPtr()),
270 &nrhs_,
271 const_cast<int_t*>(iparm_),
272 const_cast<int_t*>(&msglvl_),
273 as<void*>(bvals_.getRawPtr()),
274 as<void*>(xvals_.getRawPtr()), &CssComm, &error );
275 }
276 check_css_mkl_error(Amesos2::SOLVE, error);
277
278 /* Get values to X */
279 {
280#ifdef HAVE_AMESOS2_TIMERS
281 Teuchos::TimeMonitor redistTimer(this->timers_.vecRedistTime_);
282#endif
283
286 solver_scalar_type>::do_put(X, xvals_(),
287 as<size_t>(ld_rhs),
288 Teuchos::ptrInArg(*css_rowmap_));
289 }
290 if (msglvl_ > 0 && this->matrixA_->getComm()->getRank() == 0) {
291 std::cout << " CssMKL::solve done:" << std::endl;
292#ifdef HAVE_AMESOS2_TIMERS
293 std::cout << " * Time : " << this->timers_.vecRedistTime_.totalElapsedTime()
294 << " + " << this->timers_.solveTime_.totalElapsedTime() << std::endl;
295#else
296 std::cout << " * Time : not enabled" << std::endl;
297#endif
298 }
299
300 return( 0 );
301 }
302
303
304 template <class Matrix, class Vector>
305 bool
307 {
308 // CssMKL supports square matrices
309 return( this->globalNumRows_ == this->globalNumCols_ );
310 }
311
312
313 template <class Matrix, class Vector>
314 void
315 CssMKL<Matrix,Vector>::setParameters_impl(const Teuchos::RCP<Teuchos::ParameterList> & parameterList )
316 {
317 using Teuchos::RCP;
318 using Teuchos::getIntegralValue;
319 using Teuchos::ParameterEntryValidator;
320
321 RCP<const Teuchos::ParameterList> valid_params = getValidParameters_impl();
322
323 // 2: Fill-in reordering from METIS, 3: thread dissection, 10: MPI version of the nested dissection
324 if( parameterList->isParameter("IPARM(2)") )
325 {
326 RCP<const ParameterEntryValidator> fillin_validator = valid_params->getEntry("IPARM(2)").validator();
327 parameterList->getEntry("IPARM(2)").setValidator(fillin_validator);
328 iparm_[1] = getIntegralValue<int>(*parameterList, "IPARM(2)");
329 }
330
331 // Max numbers of iterative refinement steps
332 if( parameterList->isParameter("IPARM(8)") )
333 {
334 RCP<const ParameterEntryValidator> refine_validator = valid_params->getEntry("IPARM(8)").validator();
335 parameterList->getEntry("IPARM(8)").setValidator(refine_validator);
336 iparm_[7] = getIntegralValue<int>(*parameterList, "IPARM(8)");
337 }
338
339 // Perturb the pivot elements
340 if( parameterList->isParameter("IPARM(10)") )
341 {
342 RCP<const ParameterEntryValidator> pivot_perturb_validator = valid_params->getEntry("IPARM(10)").validator();
343 parameterList->getEntry("IPARM(10)").setValidator(pivot_perturb_validator);
344 iparm_[9] = getIntegralValue<int>(*parameterList, "IPARM(10)");
345 }
346
347 // First check if the control object requests a transpose solve.
348 // Then solver specific options can override this.
349 iparm_[11] = this->control_.useTranspose_ ? 2 : 0;
350 // Normal solve (0), or a transpose solve (1)
351 if( parameterList->isParameter("IPARM(12)") )
352 {
353 RCP<const ParameterEntryValidator> trans_validator = valid_params->getEntry("IPARM(12)").validator();
354 parameterList->getEntry("IPARM(12)").setValidator(trans_validator);
355 iparm_[11] = getIntegralValue<int>(*parameterList, "IPARM(12)");
356 }
357
358 // (Non-)symmetric matchings : detault 1 for nonsymmetric and 0 for symmetric matrix (default is nonsymmetric)
359 if( parameterList->isParameter("IPARM(13)") )
360 {
361 RCP<const ParameterEntryValidator> trans_validator = valid_params->getEntry("IPARM(13)").validator();
362 parameterList->getEntry("IPARM(13)").setValidator(trans_validator);
363 iparm_[12] = getIntegralValue<int>(*parameterList, "IPARM(13)");
364 }
365
366 // Output: Number of nonzeros in the factor LU
367 if( parameterList->isParameter("IPARM(18)") )
368 {
369 RCP<const ParameterEntryValidator> report_validator = valid_params->getEntry("IPARM(18)").validator();
370 parameterList->getEntry("IPARM(18)").setValidator(report_validator);
371 iparm_[17] = getIntegralValue<int>(*parameterList, "IPARM(18)");
372 }
373
374 // Check input matrix is sorted
375 if( parameterList->isParameter("IPARM(27)") )
376 {
377 RCP<const ParameterEntryValidator> report_validator = valid_params->getEntry("IPARM(27)").validator();
378 parameterList->getEntry("IPARM(27)").setValidator(report_validator);
379 iparm_[26] = getIntegralValue<int>(*parameterList, "IPARM(27)");
380 }
381
382 if( parameterList->isParameter("IsContiguous") ){
383 is_contiguous_ = parameterList->get<bool>("IsContiguous");
384 }
385
386 if( parameterList->isParameter("verbose") ){
387 msglvl_ = parameterList->get<int>("verbose");
388 }
389 }
390
391
392/*
393 * TODO: It would be nice if the parameters could be expressed as
394 * either all string or as all integers. I see no way of doing this
395 * at present with the standard validators. However, we could create
396 * our own validators or kindly ask the Teuchos team to add some
397 * features for use.
398 *
399 * The issue is that with the current validators we cannot specify
400 * arbitrary sets of numbers that are the only allowed parameters.
401 * For example the IPARM(2) parameter can take only the values 0, 2,
402 * and 3. The EnhancedNumberValidator can take a min value, and max
403 * value, and a step size, but with those options there is no way to
404 * specify the needed set.
405 *
406 * Another missing feature is the ability to give docstrings for such
407 * numbers. For example IPARM(25) can take on the values 0 and 1.
408 * This would be easy enough to accomplish with just a number
409 * validator, but then have no way to document the effect of each
410 * value.
411 */
412template <class Matrix, class Vector>
413Teuchos::RCP<const Teuchos::ParameterList>
415{
416 using std::string;
417 using Teuchos::as;
418 using Teuchos::RCP;
419 using Teuchos::tuple;
420 using Teuchos::toString;
421 using Teuchos::EnhancedNumberValidator;
422 using Teuchos::setStringToIntegralParameter;
423 using Teuchos::anyNumberParameterEntryValidator;
424
425 static Teuchos::RCP<const Teuchos::ParameterList> valid_params;
426
427 if( is_null(valid_params) ){
428 Teuchos::RCP<Teuchos::ParameterList> pl = Teuchos::parameterList();
429
430 void* pt_temp[64];
431 int_t iparm_temp[64];
432 set_css_mkl_default_parameters(pt_temp, iparm_temp);
433 setStringToIntegralParameter<int>("IPARM(2)", toString(iparm_temp[1]),
434 "Fill-in reducing ordering for the input matrix",
435 tuple<string>("2", "3", "10"),
436 tuple<string>("Nested dissection algorithm from METIS",
437 "Parallel version of the nested dissection algorithm",
438 "MPI version of the nested dissection and symbolic factorization algorithms"),
439 tuple<int>(2, 3, 10),
440 pl.getRawPtr());
441
442 setStringToIntegralParameter<int>("IPARM(12)", toString(iparm_temp[11]),
443 "Solve with transposed or conjugate transposed matrix A",
444 tuple<string>("0", "1", "2"),
445 tuple<string>("Non-transposed",
446 "Conjugate-transposed",
447 "Transposed"),
448 tuple<int>(0, 1, 2),
449 pl.getRawPtr());
450
451 setStringToIntegralParameter<int>("IPARM(13)", toString(iparm_temp[12]),
452 "Use weighted matching",
453 tuple<string>("0", "1"),
454 tuple<string>("No matching", "Use matching"),
455 tuple<int>(0, 1),
456 pl.getRawPtr());
457
458 Teuchos::AnyNumberParameterEntryValidator::EPreferredType preferred_int =
459 Teuchos::AnyNumberParameterEntryValidator::PREFER_INT;
460
461 Teuchos::AnyNumberParameterEntryValidator::AcceptedTypes accept_int( false );
462 accept_int.allowInt( true );
463
464 pl->set("IPARM(8)" , as<int>(iparm_temp[7]) , "Iterative refinement step",
465 anyNumberParameterEntryValidator(preferred_int, accept_int));
466
467 pl->set("IPARM(10)", as<int>(iparm_temp[9]) , "Pivoting perturbation",
468 anyNumberParameterEntryValidator(preferred_int, accept_int));
469
470 pl->set("IPARM(18)", as<int>(iparm_temp[17]), "Report the number of non-zero elements in the factors",
471 anyNumberParameterEntryValidator(preferred_int, accept_int));
472
473 pl->set("IPARM(28)", as<int>(iparm_temp[27]), "Check input matrix is sorted",
474 anyNumberParameterEntryValidator(preferred_int, accept_int));
475
476 pl->set("IsContiguous", true, "Whether GIDs contiguous");
477
478 pl->set("verbose", 0, "Verbosity Message Level");
479
480 valid_params = pl;
481 }
482
483 return valid_params;
484}
485
486
487
488template <class Matrix, class Vector>
489bool
491{
492#ifdef HAVE_AMESOS2_TIMERS
493 Teuchos::TimeMonitor convTimer(this->timers_.mtxConvTime_);
494#endif
495
496 // CssMKL does not need matrix data in the pre-ordering phase
497 if( current_phase == PREORDERING ) return( false );
498
499 // is_contiguous : input is contiguous
500 // CONTIGUOUS_AND_ROOTED : input is not contiguous, so make output contiguous
501 EDistribution dist_option = (iparm_[39] != 0 ? DISTRIBUTED_NO_OVERLAP : ((is_contiguous_ == true) ? ROOTED : CONTIGUOUS_AND_ROOTED));
502 if (dist_option == DISTRIBUTED_NO_OVERLAP && !is_contiguous_) {
503 // Neeed to form contiguous matrix
504 #if 1
505 // Only reinex GIDs
506 css_rowmap_ = this->matrixA_->getRowMap(); // use original map to redistribute vectors in solve
507 Teuchos::RCP<const MatrixAdapter<Matrix> > contig_mat = this->matrixA_->reindex(css_contig_rowmap_, css_contig_colmap_, current_phase);
508 #else
509 // Redistribued matrixA into contiguous GIDs
510 Teuchos::RCP<const MatrixAdapter<Matrix> > contig_mat = this->matrixA_->get(ptrInArg(*css_rowmap_));
511 //css_rowmap_ = contig_mat->getRowMap(); // use new map to redistribute vectors in solve
512 #endif
513 // Copy into local views
514 if (current_phase == SYMBFACT) {
515 Kokkos::resize(nzvals_temp_, contig_mat->getLocalNNZ());
516 Kokkos::resize(nzvals_view_, contig_mat->getLocalNNZ());
517 Kokkos::resize(colind_view_, contig_mat->getLocalNNZ());
518 Kokkos::resize(rowptr_view_, contig_mat->getLocalNumRows() + 1);
519 }
520 int_t nnz_ret = 0;
521 {
522#ifdef HAVE_AMESOS2_TIMERS
523 Teuchos::TimeMonitor mtxRedistTimer( this->timers_.mtxRedistTime_ );
524#endif
526 host_value_type_array,host_ordinal_type_array, host_size_type_array >::do_get(
527 contig_mat.ptr(),
528 nzvals_temp_, colind_view_, rowptr_view_,
529 nnz_ret,
530 ptrInArg(*(contig_mat->getRowMap())),
531 #if 1
533 #else
534 ROOTED,
535 #endif
537 Kokkos::deep_copy(nzvals_view_, nzvals_temp_);
538 }
539 } else {
540 if (current_phase == SYMBFACT) {
541 if (dist_option == DISTRIBUTED_NO_OVERLAP) {
542 Kokkos::resize(nzvals_temp_, this->matrixA_->getLocalNNZ());
543 Kokkos::resize(nzvals_view_, this->matrixA_->getLocalNNZ());
544 Kokkos::resize(colind_view_, this->matrixA_->getLocalNNZ());
545 Kokkos::resize(rowptr_view_, this->matrixA_->getLocalNumRows() + 1);
546 } else {
547 if( this->root_ ) {
548 Kokkos::resize(nzvals_temp_, this->matrixA_->getGlobalNNZ());
549 Kokkos::resize(nzvals_view_, this->matrixA_->getGlobalNNZ());
550 Kokkos::resize(colind_view_, this->matrixA_->getGlobalNNZ());
551 Kokkos::resize(rowptr_view_, this->matrixA_->getGlobalNumRows() + 1);
552 } else {
553 Kokkos::resize(nzvals_temp_, 0);
554 Kokkos::resize(nzvals_view_, 0);
555 Kokkos::resize(colind_view_, 0);
556 Kokkos::resize(rowptr_view_, 0);
557 }
558 }
559 }
560 int_t nnz_ret = 0;
561 {
562#ifdef HAVE_AMESOS2_TIMERS
563 Teuchos::TimeMonitor mtxRedistTimer( this->timers_.mtxRedistTime_ );
564#endif
566 host_value_type_array,host_ordinal_type_array, host_size_type_array >::do_get(
567 this->matrixA_.ptr(),
568 nzvals_temp_, colind_view_, rowptr_view_,
569 nnz_ret,
570 ptrInArg(*(this->matrixA_->getRowMap())),
571 dist_option,
573 Kokkos::deep_copy(nzvals_view_, nzvals_temp_);
574 }
575 }
576 return( true );
577}
578
579
580template <class Matrix, class Vector>
581void
583 int_t error) const
584{
585 int error_i = error;
586 Teuchos::broadcast(*(this->getComm()), 0, &error_i); // We only care about root's value
587
588 if( error == 0 ) return; // No error
589
590 std::string errmsg = "Other error";
591 switch( error ){
592 case -1:
593 errmsg = "CssMKL reported error: 'Input inconsistent'";
594 break;
595 case -2:
596 errmsg = "CssMKL reported error: 'Not enough memory'";
597 break;
598 case -3:
599 errmsg = "CssMKL reported error: 'Reordering problem'";
600 break;
601 case -4:
602 errmsg =
603 "CssMKL reported error: 'Zero pivot, numerical "
604 "factorization or iterative refinement problem'";
605 break;
606 case -5:
607 errmsg = "CssMKL reported error: 'Unclassified (internal) error'";
608 break;
609 case -6:
610 errmsg = "CssMKL reported error: 'Reordering failed'";
611 break;
612 case -7:
613 errmsg = "CssMKL reported error: 'Diagonal matrix is singular'";
614 break;
615 case -8:
616 errmsg = "CssMKL reported error: '32-bit integer overflow problem'";
617 break;
618 case -9:
619 errmsg = "CssMKL reported error: 'Not enough memory for OOC'";
620 break;
621 case -10:
622 errmsg = "CssMKL reported error: 'Problems with opening OOC temporary files'";
623 break;
624 case -11:
625 errmsg = "CssMKL reported error: 'Read/write problem with OOC data file'";
626 break;
627 }
628 errmsg += (" at phase = "+std::to_string(phase));
629
630 TEUCHOS_TEST_FOR_EXCEPTION( true, std::runtime_error, errmsg );
631}
632
633
634template <class Matrix, class Vector>
635void
637{
638 if( mtype == 0 ){
639 if( complex_ ){
640 mtype_ = 13; // complex, unsymmetric
641 } else {
642 mtype_ = 11; // real, unsymmetric
643 }
644 } else {
645 switch( mtype ){
646 case 11:
647 TEUCHOS_TEST_FOR_EXCEPTION( complex_,
648 std::invalid_argument,
649 "Cannot set a real CSS matrix type with scalar type complex" );
650 mtype_ = 11; break;
651 case 13:
652 TEUCHOS_TEST_FOR_EXCEPTION( !complex_,
653 std::invalid_argument,
654 "Cannot set a complex CSS matrix type with non-complex scalars" );
655 mtype_ = 13; break;
656 default:
657 TEUCHOS_TEST_FOR_EXCEPTION( true,
658 std::invalid_argument,
659 "Symmetric matrices are not yet supported by the Amesos2 interface" );
660 }
661 }
662}
663
664template <class Matrix, class Vector>
665void
666CssMKL<Matrix,Vector>::set_css_mkl_default_parameters(void* pt[], int_t iparm[]) const
667{
668 for( int i = 0; i < 64; ++i ){
669 pt[i] = nullptr;
670 iparm[i] = 0;
671 }
672 iparm[0] = 1; /* No solver default */
673 // Reset some of the default parameters
674 iparm[1] = 10; /* 2: Fill-in reordering from METIS, 3: thread dissection, 10: MPI version of the nested dissection and symbolic factorization*/
675 iparm[7] = 0; /* Max numbers of iterative refinement steps */
676 iparm[10] = 0; /* Disable nonsymmetric permutation and scaling MPS */
677 iparm[11] = 0; /* Normal solve (0), or a transpose solve (1) */
678 iparm[12] = 0; /* Do not use (non-)symmetric matchings */
679 iparm[17] = -1; /* Output: Number of nonzeros in the factor LU */
680 iparm[20] = 1; /* Pivoting for symmetric indefinite matrices */
681 iparm[26] = 1; /* Check input matrix is sorted */
682
683 // diagonal pertubation
684 if (mtype_ == -2 || mtype_ == -4) {
685 // symmetric indefinite
686 iparm[9] = 8; /* Perturb the pivot elements with 1E-8 */
687 } else {
688 // non-symmetric
689 iparm[9] = 13; /* Perturb the pivot elements with 1E-13 */
690 }
691
692 // set single or double precision
693 if constexpr ( std::is_same_v<solver_magnitude_type, PMKL::_REAL_t> ) {
694 iparm[27] = 1; // single-precision
695 } else {
696 iparm[27] = 0; // double-precision
697 }
698 iparm[34] = 1; /* Use zero-based indexing */
699}
700
701
702template <class Matrix, class Vector>
703const char* CssMKL<Matrix,Vector>::name = "CSSMKL";
704
705template <class Matrix, class Vector>
706const typename CssMKL<Matrix,Vector>::int_t
707CssMKL<Matrix,Vector>::maxfct_ = 1;
708
709template <class Matrix, class Vector>
710const typename CssMKL<Matrix,Vector>::int_t
711CssMKL<Matrix,Vector>::mnum_ = 1;
712
713
714} // end namespace Amesos
715
716#endif // AMESOS2_CSSMKL_DEF_HPP
A template class that does nothing useful besides show developers what, in general,...
EDistribution
Definition Amesos2_TypeDecl.hpp:89
@ DISTRIBUTED_NO_OVERLAP
Definition Amesos2_TypeDecl.hpp:91
@ ROOTED
Definition Amesos2_TypeDecl.hpp:93
@ CONTIGUOUS_AND_ROOTED
Definition Amesos2_TypeDecl.hpp:94
@ SORTED_INDICES
Definition Amesos2_TypeDecl.hpp:108
Amesos2 interface to the CssMKL package.
Definition Amesos2_CssMKL_decl.hpp:50
void * pt_[64]
CssMKL internal data address pointer.
Definition Amesos2_CssMKL_decl.hpp:274
bool loadA_impl(EPhase current_phase)
Reads matrix data into internal structures.
Definition Amesos2_CssMKL_def.hpp:490
~CssMKL()
Destructor.
Definition Amesos2_CssMKL_def.hpp:97
void check_css_mkl_error(EPhase phase, int_t error) const
Throws an appropriate runtime error in the event that error < 0 .
Definition Amesos2_CssMKL_def.hpp:582
static const char * name
The name of this solver interface.
Definition Amesos2_CssMKL_decl.hpp:57
int preOrdering_impl()
Performs pre-ordering on the matrix to increase efficiency.
Definition Amesos2_CssMKL_def.hpp:121
int numericFactorization_impl()
CssMKL specific numeric factorization.
Definition Amesos2_CssMKL_def.hpp:190
int symbolicFactorization_impl()
Perform symbolic factorization of the matrix using CssMKL.
Definition Amesos2_CssMKL_def.hpp:131
bool matrixShapeOK_impl() const
Determines whether the shape of the matrix is OK for this solver.
Definition Amesos2_CssMKL_def.hpp:306
int solve_impl(const Teuchos::Ptr< MultiVecAdapter< Vector > > X, const Teuchos::Ptr< const MultiVecAdapter< Vector > > B) const
CssMKL specific solve.
Definition Amesos2_CssMKL_def.hpp:227
Teuchos::RCP< const Teuchos::ParameterList > getValidParameters_impl() const
Definition Amesos2_CssMKL_def.hpp:414
int_t iparm_[64]
Definition Amesos2_CssMKL_decl.hpp:292
void set_css_mkl_matrix_type(int_t mtype=0)
Definition Amesos2_CssMKL_def.hpp:636
void setParameters_impl(const Teuchos::RCP< Teuchos::ParameterList > &parameterList)
Definition Amesos2_CssMKL_def.hpp:315
CssMKL(Teuchos::RCP< const Matrix > A, Teuchos::RCP< Vector > X, Teuchos::RCP< const Vector > B)
Initialize from Teuchos::RCP.
Definition Amesos2_CssMKL_def.hpp:40
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_
The LHS operator.
Definition Amesos2_SolverCore_decl.hpp:421
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 globalNumRows_
Number of global rows in matrixA_.
Definition Amesos2_SolverCore_decl.hpp:442
EPhase
Used to indicate a phase in the direct solution.
Definition Amesos2_TypeDecl.hpp:31
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
Similar to get_ccs_helper , but used to get a CRS representation of the given matrix.
Definition Amesos2_Util.hpp:600
Helper class for putting 1-D data arrays into multivectors.
Definition Amesos2_MultiVecAdapter_decl.hpp:339