123#ifdef HAVE_AMESOS2_TIMERS
124 Teuchos::TimeMonitor symbFactTimer( this->timers_.symFactTime_ );
127 solver_scalar_type bdummy, xdummy;
128 if( pardiso_initialized_){
130 function_map::pardiso( pt_,
const_cast<int_t*
>(&maxfct_),
131 const_cast<int_t*
>(&mnum_), &mtype_, &phase, &n_,
132 nzvals_view_.data(), rowptr_view_.data(),
133 colind_view_.data(), perm_.getRawPtr(), &nrhs_, iparm_,
134 const_cast<int_t*
>(&msglvl_), as<void*>(&bdummy), as<void*>(&xdummy), &error );
135 if (msglvl_ > 0 && error != 0) {
137 std::cout <<
" PardisoMKL::symbolicFactorization: clean-up failed with " << error << std::endl;
139 std::cout <<
" PardisoMKL::symbolicFactorization: cleaned-up before calling symbolic" << error;
142 pardiso_initialized_ =
false;
145 function_map::pardiso( pt_,
const_cast<int_t*
>(&maxfct_),
146 const_cast<int_t*
>(&mnum_), &mtype_, &phase, &n_,
147 nzvals_view_.data(), rowptr_view_.data(),
148 colind_view_.data(), perm_.getRawPtr(), &nrhs_, iparm_,
149 const_cast<int_t*
>(&msglvl_), as<void*>(&bdummy), as<void*>(&xdummy), &error );
150 pardiso_initialized_ =
true;
152 check_pardiso_mkl_error(Amesos2::SYMBFACT, error);
154 if (msglvl_ > 0 && this->root_) {
155 std::cout <<
" PardisoMKL::symbolicFactorization done:" << std::endl;
156#ifdef HAVE_AMESOS2_TIMERS
157 std::cout <<
" * Time : " << this->timers_.symFactTime_.totalElapsedTime() << std::endl;
159 std::cout <<
" * Time : not enabled" << std::endl;
166 this->setNnzLU(iparm_[17]);
180#ifdef HAVE_AMESOS2_TIMERS
181 Teuchos::TimeMonitor numFactTimer( this->timers_.numFactTime_ );
185 solver_scalar_type bdummy;
186 solver_scalar_type *xdummy = schur_out_.data();
187 function_map::pardiso( pt_,
const_cast<int_t*
>(&maxfct_),
188 const_cast<int_t*
>(&mnum_), &mtype_, &phase, &n_,
189 nzvals_view_.data(), rowptr_view_.data(),
190 colind_view_.data(), perm_.getRawPtr(), &nrhs_, iparm_,
191 const_cast<int_t*
>(&msglvl_), as<void*>(&bdummy), as<void*>(xdummy), &error );
193 if (error == 0 && partial_facto_ != 0) {
194 if (schur_out_ptr_ !=
nullptr) {
198 for (
size_t i = 0; i < schur_size_; i++) {
199 for (
size_t j = 0; j < schur_size_; j++) {
200 schur_out_ptr_[i+j*schur_size_] = as<scalar_type>(schur_out_[j+i*schur_size_]);
206 check_pardiso_mkl_error(Amesos2::NUMFACT, error);
208 if (msglvl_ > 0 && this->root_) {
209 std::cout <<
" PardisoMKL::numericFactorization done:" << std::endl;
210#ifdef HAVE_AMESOS2_TIMERS
211 std::cout <<
" * Time : " << this->timers_.numFactTime_.totalElapsedTime() << std::endl;
213 std::cout <<
" * Time : not enabled" << std::endl;
231 const global_size_type ld_rhs = this->root_ ? X->getGlobalLength() : 0;
232 nrhs_ = as<int_t>(X->getGlobalNumVectors());
233 if (debug_level_ > 0) {
234 if (this->root_) std::cout <<
"\n == Amesos2_PardisoMKL::solve_impl ==" << std::endl;
235 if (debug_level_ == 1) {
238 Teuchos::RCP<Teuchos::FancyOStream> fancy = Teuchos::fancyOStream(Teuchos::rcpFromRef(std::cout));
239 if (!is_null(B->getMap())) B->getMap()->describe(*fancy, Teuchos::VERB_EXTREME);
240 std::cout << std::endl;
241 B->describe(*fancy, Teuchos::VERB_EXTREME);
246#ifdef HAVE_AMESOS2_TIMERS
247 Teuchos::TimeMonitor mvConvTimer( this->timers_.vecConvTime_ );
248 Teuchos::TimeMonitor redistTimer( this->timers_.vecRedistTime_ );
251 const bool initialize_data =
true;
252 const bool do_not_initialize_data =
false;
253 Util::get_1d_copy_helper_kokkos_view<MultiVecAdapter<Vector>,
254 host_solver_scalar_view>::do_get(initialize_data, B, bvals_,
257 this->rowIndexBase_);
258 Util::get_1d_copy_helper_kokkos_view<MultiVecAdapter<Vector>,
259 host_solver_scalar_view>::do_get(do_not_initialize_data, X, xvals_,
262 this->rowIndexBase_);
266#ifdef HAVE_AMESOS2_TIMERS
267 Teuchos::TimeMonitor solveTimer( this->timers_.solveTime_ );
271 if (only_forward_solve_) {
274 if (wvals_.extent(0) != n_ || wvals_.extent(1) != nrhs_) {
275 Kokkos::resize(wvals_, n_, nrhs_);
277 }
else if (only_backward_solve_) {
280 if (wvals_.extent(0) != n_ || wvals_.extent(1) != nrhs_) {
281 Kokkos::resize(wvals_, n_, nrhs_);
287 size_t n2 = this->globalNumCols_-schur_size_;
288 for (global_size_type i=0; i<n_; i++) {
289 if (schur_part_(i) == 1) {
290 for (
size_t j=0; j<nrhs_; j++) {
291 wvals_(i,j) = bvals_(n2,j);
295 for (
size_t j=0; j<nrhs_; j++) {
296 wvals_(i,j) = bvals_(n1,j);
302 solver_scalar_type *b_in = (only_backward_solve_ ? wvals_.data() : bvals_.data());
303 solver_scalar_type *x_out = (only_forward_solve_ ? wvals_.data() : xvals_.data());
304 function_map::pardiso( pt_,
305 const_cast<int_t*
>(&maxfct_),
306 const_cast<int_t*
>(&mnum_),
307 const_cast<int_t*
>(&mtype_),
308 const_cast<int_t*
>(&phase),
309 const_cast<int_t*
>(&n_),
310 const_cast<solver_scalar_type*
>(nzvals_view_.data()),
311 const_cast<int_t*
>(rowptr_view_.data()),
312 const_cast<int_t*
>(colind_view_.data()),
313 const_cast<int_t*
>(perm_.getRawPtr()),
315 const_cast<int_t*
>(iparm_),
316 const_cast<int_t*
>(&msglvl_),
318 as<void*>(x_out), &error );
319 if (only_forward_solve_) {
324 size_t n2 = this->globalNumCols_-schur_size_;
325 for (global_size_type i=0; i<n_; i++) {
326 if (schur_part_(i) == 1) {
327 for (
size_t j=0; j<nrhs_; j++) {
328 xvals_(n2,j) = wvals_(i,j);
332 for (
size_t j=0; j<nrhs_; j++) {
333 xvals_(n1,j) = wvals_(i,j);
340 check_pardiso_mkl_error(Amesos2::SOLVE, error);
344#ifdef HAVE_AMESOS2_TIMERS
345 Teuchos::TimeMonitor redistTimer(this->timers_.vecRedistTime_);
348 Util::put_1d_data_helper_kokkos_view<
352 this->rowIndexBase_);
354 if (debug_level_ > 0) {
355 if (debug_level_ == 1) {
358 Teuchos::RCP<Teuchos::FancyOStream> fancy = Teuchos::fancyOStream(Teuchos::rcpFromRef(std::cout));
359 if (!is_null(X->getMap())) X->getMap()->describe(*fancy, Teuchos::VERB_EXTREME);
360 std::cout << std::endl;
361 X->describe(*fancy, Teuchos::VERB_EXTREME);
364 if (msglvl_ > 0 && this->root_) {
365 std::cout <<
" PardisoMKL::solve done:" << std::endl;
366#ifdef HAVE_AMESOS2_TIMERS
367 std::cout <<
" * Time : " << this->timers_.vecRedistTime_.totalElapsedTime()
368 <<
" + " << this->timers_.solveTime_.totalElapsedTime() << std::endl;
370 std::cout <<
" * Time : not enabled" << std::endl;
392 using Teuchos::getIntegralValue;
393 using Teuchos::ParameterEntryValidator;
395 RCP<const Teuchos::ParameterList> valid_params = getValidParameters_impl();
398 if( parameterList->isParameter(
"IPARM(2)") )
400 RCP<const ParameterEntryValidator> fillin_validator = valid_params->getEntry(
"IPARM(2)").validator();
401 parameterList->getEntry(
"IPARM(2)").setValidator(fillin_validator);
402 iparm_[1] = getIntegralValue<int>(*parameterList,
"IPARM(2)");
406 if( parameterList->isParameter(
"IPARM(4)") )
408 RCP<const ParameterEntryValidator> prec_validator = valid_params->getEntry(
"IPARM(4)").validator();
409 parameterList->getEntry(
"IPARM(4)").setValidator(prec_validator);
410 iparm_[3] = getIntegralValue<int>(*parameterList,
"IPARM(4)");
414 if( parameterList->isParameter(
"IPARM(8)") )
416 RCP<const ParameterEntryValidator> refine_validator = valid_params->getEntry(
"IPARM(8)").validator();
417 parameterList->getEntry(
"IPARM(8)").setValidator(refine_validator);
418 iparm_[7] = getIntegralValue<int>(*parameterList,
"IPARM(8)");
422 if( parameterList->isParameter(
"IPARM(10)") )
424 RCP<const ParameterEntryValidator> pivot_perturb_validator = valid_params->getEntry(
"IPARM(10)").validator();
425 parameterList->getEntry(
"IPARM(10)").setValidator(pivot_perturb_validator);
426 iparm_[9] = getIntegralValue<int>(*parameterList,
"IPARM(10)");
430 if( parameterList->isParameter(
"IPARM(11)") )
432 RCP<const ParameterEntryValidator> mwm_validator = valid_params->getEntry(
"IPARM(11)").validator();
433 parameterList->getEntry(
"IPARM(11)").setValidator(mwm_validator);
434 iparm_[10] = getIntegralValue<int>(*parameterList,
"IPARM(11)");
439 iparm_[11] = this->control_.useTranspose_ ? 2 : 0;
442 if( parameterList->isParameter(
"IPARM(12)") )
444 RCP<const ParameterEntryValidator> trans_validator = valid_params->getEntry(
"IPARM(12)").validator();
445 parameterList->getEntry(
"IPARM(12)").setValidator(trans_validator);
446 iparm_[11] = getIntegralValue<int>(*parameterList,
"IPARM(12)");
450 if( parameterList->isParameter(
"IPARM(13)") )
452 RCP<const ParameterEntryValidator> trans_validator = valid_params->getEntry(
"IPARM(13)").validator();
453 parameterList->getEntry(
"IPARM(13)").setValidator(trans_validator);
454 iparm_[12] = getIntegralValue<int>(*parameterList,
"IPARM(13)");
458 if( parameterList->isParameter(
"IPARM(18)") )
460 RCP<const ParameterEntryValidator> report_validator = valid_params->getEntry(
"IPARM(18)").validator();
461 parameterList->getEntry(
"IPARM(18)").setValidator(report_validator);
462 iparm_[17] = getIntegralValue<int>(*parameterList,
"IPARM(18)");
466 if( parameterList->isParameter(
"IPARM(24)") )
468 RCP<const ParameterEntryValidator> par_fact_validator = valid_params->getEntry(
"IPARM(24)").validator();
469 parameterList->getEntry(
"IPARM(24)").setValidator(par_fact_validator);
470 iparm_[23] = getIntegralValue<int>(*parameterList,
"IPARM(24)");
474 if( parameterList->isParameter(
"IPARM(25)") )
476 RCP<const ParameterEntryValidator> par_fbsolve_validator = valid_params->getEntry(
"IPARM(25)").validator();
477 parameterList->getEntry(
"IPARM(25)").setValidator(par_fbsolve_validator);
478 iparm_[24] = getIntegralValue<int>(*parameterList,
"IPARM(25)");
482 if( parameterList->isParameter(
"IPARM(27)") )
484 RCP<const ParameterEntryValidator> check_validator = valid_params->getEntry(
"IPARM(27)").validator();
485 parameterList->getEntry(
"IPARM(27)").setValidator(check_validator);
486 iparm_[26] = getIntegralValue<int>(*parameterList,
"IPARM(27)");
490 if( parameterList->isParameter(
"IPARM(60)") )
492 RCP<const ParameterEntryValidator> ooc_validator = valid_params->getEntry(
"IPARM(60)").validator();
493 parameterList->getEntry(
"IPARM(60)").setValidator(ooc_validator);
494 iparm_[59] = getIntegralValue<int>(*parameterList,
"IPARM(60)");
500 if(parameterList->isParameter(
"PartialFacto")) {
501 partial_facto_ = parameterList->get<
int>(
"PartialFacto");
502 if (partial_facto_ == 1)
504 else if (partial_facto_ == 2)
507 if(parameterList->isParameter(
"SchurPart")) {
509 auto schur_part_ptr = parameterList->get<
const local_ordinal_type*>(
"SchurPart");
510 Kokkos::resize(schur_part_, this->globalNumCols_);
513 for (global_size_type i=0; i<this->globalNumCols_; i++) {
514 schur_part_(i) = schur_part_ptr[i];
515 perm_[i] = schur_part_ptr[i];
516 if (perm_[i] == 1) schur_size_ ++;
519 size_t schur_size_2 = schur_size_*schur_size_;
520 Kokkos::resize(schur_out_, (schur_size_2 > 0 ? schur_size_2 : 1));
523 if(parameterList->isParameter(
"SchurOut")) {
525 schur_out_ptr_ = parameterList->get<scalar_type*>(
"SchurOut");
527 if(parameterList->isParameter(
"OnlyForwardSolve")) {
528 only_forward_solve_ = parameterList->get<
bool>(
"OnlyForwardSolve");
530 if(parameterList->isParameter(
"OnlyBackwardSolve")) {
531 only_backward_solve_ = parameterList->get<
bool>(
"OnlyBackwardSolve");
535 if( parameterList->isParameter(
"IsContiguous") ){
536 is_contiguous_ = parameterList->get<
bool>(
"IsContiguous");
538 if( parameterList->isParameter(
"MessageLevel") ){
539 msglvl_ = parameterList->get<
int>(
"MessageLevel");
541 if(parameterList->isParameter(
"verbose")){
542 bool verbose = parameterList->get<
bool>(
"verbose");
543 if (verbose) msglvl_ = 1;
545 if( parameterList->isParameter(
"DebugLevel") ){
546 debug_level_ = parameterList->get<
int>(
"DebugLevel");
578 using Teuchos::tuple;
579 using Teuchos::toString;
580 using Teuchos::EnhancedNumberValidator;
581 using Teuchos::setStringToIntegralParameter;
582 using Teuchos::anyNumberParameterEntryValidator;
584 static Teuchos::RCP<const Teuchos::ParameterList> valid_params;
586 if( is_null(valid_params) ){
587 Teuchos::RCP<Teuchos::ParameterList> pl = Teuchos::parameterList();
591 PMKL::_INTEGER_t mtype_temp = mtype_;
592 PMKL::_INTEGER_t iparm_temp[64];
593 PMKL::pardisoinit(pt_dummy,
594 const_cast<PMKL::_INTEGER_t*
>(&mtype_temp),
595 const_cast<PMKL::_INTEGER_t*
>(iparm_temp));
597 setStringToIntegralParameter<int>(
"IPARM(2)", toString(iparm_temp[1]),
598 "Fill-in reducing ordering for the input matrix",
599 tuple<string>(
"0",
"2",
"3"),
600 tuple<string>(
"The minimum degree algorithm",
601 "Nested dissection algorithm from METIS",
602 "OpenMP parallel nested dissection algorithm"),
606 Teuchos::RCP<EnhancedNumberValidator<int> > iparm_4_validator
607 = Teuchos::rcp(
new EnhancedNumberValidator<int>() );
608 iparm_4_validator->setMin(0);
609 pl->set(
"IPARM(4)" , as<int>(iparm_temp[3]) ,
"Preconditioned CGS/CG",
612 setStringToIntegralParameter<int>(
"IPARM(12)", toString(iparm_temp[11]),
613 "Solve with transposed or conjugate transposed matrix A",
614 tuple<string>(
"0",
"1",
"2"),
615 tuple<string>(
"Non-transposed",
616 "Conjugate-transposed",
621 setStringToIntegralParameter<int>(
"IPARM(13)", toString(iparm_temp[12]),
622 "Use weighted matching",
623 tuple<string>(
"0",
"1"),
624 tuple<string>(
"No matching",
"Use matching"),
628 setStringToIntegralParameter<int>(
"IPARM(24)", toString(iparm_temp[23]),
629 "Parallel factorization control",
630 tuple<string>(
"0",
"1"),
631 tuple<string>(
"PARDISO uses the previous algorithm for factorization",
632 "PARDISO uses the new two-level factorization algorithm"),
636 setStringToIntegralParameter<int>(
"IPARM(25)", toString(iparm_temp[24]),
637 "Parallel forward/backward solve control",
638 tuple<string>(
"0",
"1"),
639 tuple<string>(
"PARDISO uses the parallel algorithm for the solve step",
640 "PARDISO uses the sequential forward and backward solve"),
644 setStringToIntegralParameter<int>(
"IPARM(60)", toString(iparm_temp[59]),
645 "PARDISO mode (OOC mode)",
646 tuple<string>(
"0",
"2"),
647 tuple<string>(
"In-core PARDISO",
648 "Out-of-core PARDISO. The OOC PARDISO can solve very "
649 "large problems by holding the matrix factors in files "
650 "on the disk. Hence the amount of RAM required by OOC "
651 "PARDISO is significantly reduced."),
655 Teuchos::AnyNumberParameterEntryValidator::EPreferredType preferred_int =
656 Teuchos::AnyNumberParameterEntryValidator::PREFER_INT;
658 Teuchos::AnyNumberParameterEntryValidator::AcceptedTypes accept_int(
false );
659 accept_int.allowInt(
true );
661 pl->set(
"IPARM(8)" , as<int>(iparm_temp[7]) ,
"Iterative refinement step",
662 anyNumberParameterEntryValidator(preferred_int, accept_int));
664 pl->set(
"IPARM(10)", as<int>(iparm_temp[9]) ,
"Pivoting perturbation",
665 anyNumberParameterEntryValidator(preferred_int, accept_int));
666 pl->set(
"IPARM(11)", as<int>(iparm_temp[10]) ,
"Scaling vectors",
667 anyNumberParameterEntryValidator(preferred_int, accept_int));
669 pl->set(
"IPARM(18)", as<int>(iparm_temp[17]),
"Report the number of non-zero elements in the factors",
670 anyNumberParameterEntryValidator(preferred_int, accept_int));
672 pl->set(
"IPARM(27)", as<int>(iparm_temp[26]) ,
"Check input matrix",
673 anyNumberParameterEntryValidator(preferred_int, accept_int));
675 scalar_type *dummy_scalar_ptr;
676 const local_ordinal_type *dummy_ordinal_ptr;
677 pl->set(
"PartialFacto", 0,
678 "Perform partial factorization to extract dense Schur complement (0: no, 1: form + factor Schur, 2: ony form");
679 pl->set(
"SchurPart", dummy_ordinal_ptr,
680 "Specify rows/columns belonging to Schur complement for partial factorization");
681 pl->set(
"SchurOut", dummy_scalar_ptr,
682 "Store output Schur complement from partial factorization");
683 pl->set(
"OnlyForwardSolve",
false,
684 "Perform only the forward substitution");
685 pl->set(
"OnlyBackwardSolve",
false,
686 "Perform only the backward substitution");
688 pl->set(
"IsContiguous",
true,
"Whether GIDs contiguous");
689 pl->set(
"MessageLevel", 0,
"PardisoMKL message level (0 to turn off message, and 1 to turn on message");
690 pl->set(
"verbose",
false,
"Set PardisoMKL message level to be 1");
691 pl->set(
"DebugLevel", 0,
"Debug message level (0 for no message, and >0 for more message");
705#ifdef HAVE_AMESOS2_TIMERS
706 Teuchos::TimeMonitor convTimer(this->timers_.mtxConvTime_);
708 if (debug_level_ > 0) {
710 std::cout <<
"\n == Amesos2_PardisoMKL::loadA_impl";
711 if (current_phase == PREORDERING) std::cout <<
"(PreOrder)";
712 if (current_phase == SYMBFACT) std::cout <<
"(SymFact)";
713 if (current_phase == NUMFACT) std::cout <<
"(NumFact)";
714 std::cout <<
" ==" << std::endl;
716 Teuchos::RCP<Teuchos::FancyOStream> fancy = Teuchos::fancyOStream(Teuchos::rcpFromRef(std::cout));
717 this->matrixA_->describe(*fancy, (debug_level_ == 1 ? Teuchos::VERB_LOW : Teuchos::VERB_EXTREME));
721 if( current_phase == PREORDERING )
return(
false );
724 Kokkos::resize(nzvals_view_, this->globalNumNonZeros_);
725 Kokkos::resize(colind_view_, this->globalNumNonZeros_);
726 Kokkos::resize(rowptr_view_, this->globalNumRows_ + 1);
729#ifdef HAVE_AMESOS2_TIMERS
730 Teuchos::TimeMonitor mtxRedistTimer( this->timers_.mtxRedistTime_ );
736 host_value_type_array, host_ordinal_type_array, host_size_type_array>::do_get(
737 this->matrixA_.ptr(),
738 nzvals_view_, colind_view_, rowptr_view_, nnz_ret,
741 this->rowIndexBase_);
751 const Teuchos::EVerbosityLevel verbLevel)
const
753 out <<
" PardisoMKL current parameters:" << std::endl;
754 out <<
" > IPARM(2) = " << iparm_[1] << std::endl;
755 out <<
" > IPARM(4) = " << iparm_[3] << std::endl;
756 out <<
" > IPARM(8) = " << iparm_[7] << std::endl;
757 out <<
" > IPARM(10) = " << iparm_[9] << std::endl;
758 out <<
" > IPARM(11) = " << iparm_[10] << std::endl;
759 out <<
" > IPARM(12) = " << iparm_[11] << std::endl;
760 out <<
" > IPARM(13) = " << iparm_[12] << std::endl;
761 out <<
" > IPARM(18) = " << iparm_[17] << std::endl;
762 out <<
" > IPARM(24) = " << iparm_[23] << std::endl;
763 out <<
" > IPARM(25) = " << iparm_[24] << std::endl;
764 out <<
" > IPARM(27) = " << iparm_[26] << std::endl;
765 out <<
" > IPARM(60) = " << iparm_[59] << std::endl;
766 out <<
" > PartialFacto = " << partial_facto_;
767 if (partial_facto_ == 0)
768 out <<
" (no partial factorization)" << std::endl;
769 if (partial_facto_ == 1)
770 out <<
" (compute and factor schur complement : iparam_[35] = 2)" << std::endl;
771 if (partial_facto_ == 2)
772 out <<
" (only compute schur complement : iparam_[35] = 1)" << std::endl;
773 out <<
" > IsContiguous = " << (is_contiguous_ ?
"YES" :
"NO") << std::endl;
774 out <<
" > MessageLevel = " << msglvl_ << std::endl;
775 out <<
" > DebugLevel = " << debug_level_ << std::endl;