Belos Version of the Day
Loading...
Searching...
No Matches
BelosPCPGSolMgr.hpp
Go to the documentation of this file.
1// @HEADER
2// *****************************************************************************
3// Belos: Block Linear Solvers Package
4//
5// Copyright 2004-2016 NTESS and the Belos contributors.
6// SPDX-License-Identifier: BSD-3-Clause
7// *****************************************************************************
8// @HEADER
9
10#ifndef BELOS_PCPG_SOLMGR_HPP
11#define BELOS_PCPG_SOLMGR_HPP
12
16
17#include "BelosConfigDefs.hpp"
18#include "BelosTypes.hpp"
21
22#include "BelosPCPGIter.hpp"
26
33#include "Teuchos_LAPACK.hpp"
34#ifdef BELOS_TEUCHOS_TIME_MONITOR
35# include "Teuchos_TimeMonitor.hpp"
36#endif
37#if defined(HAVE_TEUCHOSCORE_CXX11)
38# include <type_traits>
39#endif // defined(HAVE_TEUCHOSCORE_CXX11)
40
48namespace Belos {
49
51
52
62
68 class PCPGSolMgrOrthoFailure : public BelosError {public:
70 {}};
71
78 class PCPGSolMgrLAPACKFailure : public BelosError {public:
80 {}};
81
83
84
105
106 // Partial specialization for complex ScalarType.
107 // This contains a trivial implementation.
108 // See discussion in the class documentation above.
109 //
110 // FIXME (mfh 09 Sep 2015) This also is a stub for types other than
111 // float or double.
112 template<class ScalarType, class MV, class OP, class DM = DefaultDenseMatrix<int,ScalarType>,
113 const bool supportsScalarType =
114 Belos::Details::LapackSupportsScalar<ScalarType>::value &&
115 ! Teuchos::ScalarTraits<ScalarType>::isComplex>
117 public Details::SolverManagerRequiresRealLapack<ScalarType, MV, OP, DM,
118 Belos::Details::LapackSupportsScalar<ScalarType>::value &&
119 ! Teuchos::ScalarTraits<ScalarType>::isComplex>
120 {
121 static const bool scalarTypeIsSupported =
123 ! Teuchos::ScalarTraits<ScalarType>::isComplex;
125 scalarTypeIsSupported> base_type;
126
127 public:
129 base_type ()
130 {}
132 const Teuchos::RCP<Teuchos::ParameterList> &pl) :
133 base_type ()
134 {}
135 virtual ~PCPGSolMgr () {}
136
138 Teuchos::RCP<SolverManager<ScalarType, MV, OP, DM> > clone () const override {
140 }
141 };
142
143 template<class ScalarType, class MV, class OP, class DM>
144 class PCPGSolMgr<ScalarType, MV, OP, DM, true> :
145 public Details::SolverManagerRequiresRealLapack<ScalarType, MV, OP, DM, true> {
146 private:
150 typedef Teuchos::ScalarTraits<ScalarType> SCT;
151 typedef typename Teuchos::ScalarTraits<ScalarType>::magnitudeType MagnitudeType;
152 typedef Teuchos::ScalarTraits<MagnitudeType> MT;
153
154 public:
156
157
164 PCPGSolMgr();
165
202 const Teuchos::RCP<Teuchos::ParameterList> &pl );
203
205 virtual ~PCPGSolMgr() {};
206
208 virtual Teuchos::RCP<SolverManager<ScalarType, MV, OP, DM> > clone () const {
209 return Teuchos::rcp(new PCPGSolMgr<ScalarType,MV,OP,DM>);
210 }
212
214
215
219 return *problem_;
220 }
221
224 Teuchos::RCP<const Teuchos::ParameterList> getValidParameters() const;
225
228 Teuchos::RCP<const Teuchos::ParameterList> getCurrentParameters() const { return params_; }
229
235 Teuchos::Array<Teuchos::RCP<Teuchos::Time> > getTimers() const {
236 return Teuchos::tuple(timerSolve_);
237 }
238
244 MagnitudeType achievedTol() const {
245 return achievedTol_;
246 }
247
249 int getNumIters() const {
250 return numIters_;
251 }
252
255 bool isLOADetected() const { return false; }
256
258
260
261
263 void setProblem( const Teuchos::RCP<LinearProblem<ScalarType,MV,OP,DM> > &problem ) { problem_ = problem; }
264
266 void setParameters( const Teuchos::RCP<Teuchos::ParameterList> &params );
267
269
271
272
276 void reset( const ResetType type ) { if ((type & Belos::Problem) && !Teuchos::is_null(problem_)) problem_->setProblem(); }
278
280
281
299 ReturnType solve();
300
302
305
307 std::string description() const;
308
310
311 private:
312
313 // In the A-inner product, perform an RRQR decomposition without using A unless absolutely necessary. Given
314 // the seed space U and C = A U, find U1 and C1 with span(U1)=span(U) such that C1'U1 = I maintaining C=AU.
315 int ARRQR(int numVecs, int numOrthVecs, const std::vector<ScalarType>& D);
316
317 // Linear problem.
318 Teuchos::RCP<LinearProblem<ScalarType,MV,OP,DM> > problem_;
319
320 // Output manager.
321 Teuchos::RCP<OutputManager<ScalarType> > printer_;
322 Teuchos::RCP<std::ostream> outputStream_;
323
324 // Status test.
325 Teuchos::RCP<StatusTest<ScalarType,MV,OP,DM> > sTest_;
326 Teuchos::RCP<StatusTestMaxIters<ScalarType,MV,OP,DM> > maxIterTest_;
327 Teuchos::RCP<StatusTestGenResNorm<ScalarType,MV,OP,DM> > convTest_;
328 Teuchos::RCP<StatusTestOutput<ScalarType,MV,OP,DM> > outputTest_;
329
330 // Orthogonalization manager.
331 Teuchos::RCP<MatOrthoManager<ScalarType,MV,OP,DM> > ortho_;
332
333 // Current parameter list.
334 Teuchos::RCP<Teuchos::ParameterList> params_;
335
336 // Default solver values.
337 static constexpr int maxIters_default_ = 1000;
338 static constexpr int deflatedBlocks_default_ = 2;
339 static constexpr int savedBlocks_default_ = 16;
340 static constexpr int verbosity_default_ = Belos::Errors;
341 static constexpr int outputStyle_default_ = Belos::General;
342 static constexpr int outputFreq_default_ = -1;
343 static constexpr const char * label_default_ = "Belos";
344 static constexpr const char * orthoType_default_ = "ICGS";
345
346 //
347 // Current solver values.
348 //
349
351 MagnitudeType convtol_;
352
354 MagnitudeType orthoKappa_;
355
357 MagnitudeType achievedTol_;
358
360 int numIters_;
361
363 int maxIters_;
364
365 int deflatedBlocks_, savedBlocks_, verbosity_, outputStyle_, outputFreq_;
366 std::string orthoType_;
367
368 // Recycled subspace, its image and the residual
369 Teuchos::RCP<MV> U_, C_, R_;
370
371 // Actual dimension of current recycling subspace (<= savedBlocks_ )
372 int dimU_;
373
374 // Timers.
375 std::string label_;
376 Teuchos::RCP<Teuchos::Time> timerSolve_;
377
378 // Internal state variables.
379 bool isSet_;
380 };
381
382
383// Empty Constructor
384template<class ScalarType, class MV, class OP, class DM>
386 outputStream_(Teuchos::rcpFromRef(std::cout)),
387 convtol_(DefaultSolverParameters::convTol),
388 orthoKappa_(DefaultSolverParameters::orthoKappa),
389 achievedTol_(Teuchos::ScalarTraits<MagnitudeType>::zero()),
390 numIters_(0),
391 maxIters_(maxIters_default_),
392 deflatedBlocks_(deflatedBlocks_default_),
393 savedBlocks_(savedBlocks_default_),
394 verbosity_(verbosity_default_),
395 outputStyle_(outputStyle_default_),
396 outputFreq_(outputFreq_default_),
397 orthoType_(orthoType_default_),
398 dimU_(0),
399 label_(label_default_),
400 isSet_(false)
401{}
402
403
404// Basic Constructor
405template<class ScalarType, class MV, class OP, class DM>
407 const Teuchos::RCP<LinearProblem<ScalarType,MV,OP,DM> > &problem,
408 const Teuchos::RCP<Teuchos::ParameterList> &pl ) :
409 problem_(problem),
410 outputStream_(Teuchos::rcpFromRef(std::cout)),
411
412 convtol_(DefaultSolverParameters::convTol),
413 orthoKappa_(DefaultSolverParameters::orthoKappa),
414 achievedTol_(Teuchos::ScalarTraits<MagnitudeType>::zero()),
415 numIters_(0),
416 maxIters_(maxIters_default_),
417 deflatedBlocks_(deflatedBlocks_default_),
418 savedBlocks_(savedBlocks_default_),
419 verbosity_(verbosity_default_),
420 outputStyle_(outputStyle_default_),
421 outputFreq_(outputFreq_default_),
422 orthoType_(orthoType_default_),
423 dimU_(0),
424 label_(label_default_),
425 isSet_(false)
426{
428 problem_.is_null (), std::invalid_argument,
429 "Belos::PCPGSolMgr two-argument constructor: "
430 "'problem' is null. You must supply a non-null Belos::LinearProblem "
431 "instance when calling this constructor.");
432
433 if (! pl.is_null ()) {
434 // Set the parameters using the list that was passed in.
435 setParameters (pl);
436 }
437}
438
439
440template<class ScalarType, class MV, class OP, class DM>
441void PCPGSolMgr<ScalarType,MV,OP,DM,true>::setParameters( const Teuchos::RCP<Teuchos::ParameterList> &params )
442{
443 // Create the internal parameter list if ones doesn't already exist.
444 if (params_ == Teuchos::null) {
445 params_ = Teuchos::rcp( new Teuchos::ParameterList(*getValidParameters()) );
446 }
447 else {
448 params->validateParameters(*getValidParameters());
449 }
450
451 // Check for maximum number of iterations
452 if (params->isParameter("Maximum Iterations")) {
453 maxIters_ = params->get("Maximum Iterations",maxIters_default_);
454
455 // Update parameter in our list and in status test.
456 params_->set("Maximum Iterations", maxIters_);
457 if (maxIterTest_!=Teuchos::null)
458 maxIterTest_->setMaxIters( maxIters_ );
459 }
460
461 // Check for the maximum numbers of saved and deflated blocks.
462 if (params->isParameter("Num Saved Blocks")) {
463 savedBlocks_ = params->get("Num Saved Blocks",savedBlocks_default_);
464 TEUCHOS_TEST_FOR_EXCEPTION(savedBlocks_ <= 0, std::invalid_argument,
465 "Belos::PCPGSolMgr: \"Num Saved Blocks\" must be strictly positive.");
466
467 // savedBlocks > number of matrix rows and columns, not known in parameters.
468 //TEUCHOS_TEST_FOR_EXCEPTION(savedBlocks_ >= maxIters_, std::invalid_argument,
469 //"Belos::PCPGSolMgr: \"Num Saved Blocks\" must be less than \"Maximum Iterations\".");
470
471 // Update parameter in our list.
472 params_->set("Num Saved Blocks", savedBlocks_);
473 }
474 if (params->isParameter("Num Deflated Blocks")) {
475 deflatedBlocks_ = params->get("Num Deflated Blocks",deflatedBlocks_default_);
476 TEUCHOS_TEST_FOR_EXCEPTION(deflatedBlocks_ < 0, std::invalid_argument,
477 "Belos::PCPGSolMgr: \"Num Deflated Blocks\" must be positive.");
478
479 TEUCHOS_TEST_FOR_EXCEPTION(deflatedBlocks_ > savedBlocks_, std::invalid_argument,
480 "Belos::PCPGSolMgr: \"Num Deflated Blocks\" must be <= \"Num Saved Blocks\".");
481
482 // Update parameter in our list.
483 // The static_cast is for clang link issues with the constexpr before c++17
484 params_->set("Num Deflated Blocks", static_cast<int>(deflatedBlocks_));
485 }
486
487 // Check to see if the timer label changed.
488 if (params->isParameter("Timer Label")) {
489 std::string tempLabel = params->get("Timer Label", label_default_);
490
491 // Update parameter in our list and solver timer
492 if (tempLabel != label_) {
493 label_ = tempLabel;
494 params_->set("Timer Label", label_);
495 std::string solveLabel = label_ + ": PCPGSolMgr total solve time";
496#ifdef BELOS_TEUCHOS_TIME_MONITOR
497 timerSolve_ = Teuchos::TimeMonitor::getNewCounter(solveLabel);
498#endif
499 if (ortho_ != Teuchos::null) {
500 ortho_->setLabel( label_ );
501 }
502 }
503 }
504
505 // Check for a change in verbosity level
506 if (params->isParameter("Verbosity")) {
507 if (Teuchos::isParameterType<int>(*params,"Verbosity")) {
508 verbosity_ = params->get("Verbosity", verbosity_default_);
509 } else {
510 verbosity_ = (int)Teuchos::getParameter<Belos::MsgType>(*params,"Verbosity");
511 }
512
513 // Update parameter in our list.
514 params_->set("Verbosity", verbosity_);
515 if (printer_ != Teuchos::null)
516 printer_->setVerbosity(verbosity_);
517 }
518
519 // Check for a change in output style
520 if (params->isParameter("Output Style")) {
521 if (Teuchos::isParameterType<int>(*params,"Output Style")) {
522 outputStyle_ = params->get("Output Style", outputStyle_default_);
523 } else {
524 outputStyle_ = (int)Teuchos::getParameter<Belos::OutputType>(*params,"Output Style");
525 }
526
527 // Reconstruct the convergence test if the explicit residual test is not being used.
528 params_->set("Output Style", outputStyle_);
529 outputTest_ = Teuchos::null;
530 }
531
532 // output stream
533 if (params->isParameter("Output Stream")) {
534 outputStream_ = Teuchos::getParameter<Teuchos::RCP<std::ostream> >(*params,"Output Stream");
535
536 // Update parameter in our list.
537 params_->set("Output Stream", outputStream_);
538 if (printer_ != Teuchos::null)
539 printer_->setOStream( outputStream_ );
540 }
541
542 // frequency level
543 if (verbosity_ & Belos::StatusTestDetails) {
544 if (params->isParameter("Output Frequency")) {
545 outputFreq_ = params->get("Output Frequency", outputFreq_default_);
546 }
547
548 // Update parameter in out list and output status test.
549 params_->set("Output Frequency", outputFreq_);
550 if (outputTest_ != Teuchos::null)
551 outputTest_->setOutputFrequency( outputFreq_ );
552 }
553
554 // Create output manager if we need to.
555 if (printer_ == Teuchos::null) {
556 printer_ = Teuchos::rcp( new OutputManager<ScalarType>(verbosity_, outputStream_) );
557 }
558
559 // Check if the orthogonalization changed.
560 bool changedOrthoType = false;
561 if (params->isParameter("Orthogonalization")) {
562 std::string tempOrthoType = params->get("Orthogonalization",orthoType_default_);
563 if (tempOrthoType != orthoType_) {
564 orthoType_ = tempOrthoType;
565 changedOrthoType = true;
566 }
567 }
568 params_->set("Orthogonalization", orthoType_);
569
570 // Check which orthogonalization constant to use.
571 if (params->isParameter("Orthogonalization Constant")) {
572 if (params->isType<MagnitudeType> ("Orthogonalization Constant")) {
573 orthoKappa_ = params->get ("Orthogonalization Constant",
574 static_cast<MagnitudeType> (DefaultSolverParameters::orthoKappa));
575 }
576 else {
577 orthoKappa_ = params->get ("Orthogonalization Constant",
579 }
580
581 // Update parameter in our list.
582 params_->set("Orthogonalization Constant",orthoKappa_);
583 if (orthoType_=="DGKS") {
584 if (orthoKappa_ > 0 && ortho_ != Teuchos::null && !changedOrthoType) {
585 Teuchos::rcp_dynamic_cast<DGKSOrthoManager<ScalarType,MV,OP,DM> >(ortho_)->setDepTol( orthoKappa_ );
586 }
587 }
588 }
589
590 // Create orthogonalization manager if we need to.
591 if (ortho_ == Teuchos::null || changedOrthoType) {
593 Teuchos::RCP<Teuchos::ParameterList> paramsOrtho; // can be null
594 if (orthoType_=="DGKS" && orthoKappa_ > 0) {
595 paramsOrtho = Teuchos::rcp(new Teuchos::ParameterList());
596 paramsOrtho->set ("depTol", orthoKappa_ );
597 }
598
599 ortho_ = factory.makeMatOrthoManager (orthoType_, Teuchos::null, printer_, label_, paramsOrtho);
600 }
601
602 // Convergence
603 typedef Belos::StatusTestCombo<ScalarType,MV,OP,DM> StatusTestCombo_t;
604 typedef Belos::StatusTestGenResNorm<ScalarType,MV,OP,DM> StatusTestResNorm_t;
605
606 // Check for convergence tolerance
607 if (params->isParameter("Convergence Tolerance")) {
608 if (params->isType<MagnitudeType> ("Convergence Tolerance")) {
609 convtol_ = params->get ("Convergence Tolerance",
610 static_cast<MagnitudeType> (DefaultSolverParameters::convTol));
611 }
612 else {
613 convtol_ = params->get ("Convergence Tolerance", DefaultSolverParameters::convTol);
614 }
615
616 // Update parameter in our list and residual tests.
617 params_->set("Convergence Tolerance", convtol_);
618 if (convTest_ != Teuchos::null)
619 convTest_->setTolerance( convtol_ );
620 }
621
622 // Create status tests if we need to.
623
624 // Basic test checks maximum iterations and native residual.
625 if (maxIterTest_ == Teuchos::null)
626 maxIterTest_ = Teuchos::rcp( new StatusTestMaxIters<ScalarType,MV,OP,DM>( maxIters_ ) );
627
628 if (convTest_ == Teuchos::null)
629 convTest_ = Teuchos::rcp( new StatusTestResNorm_t( convtol_, 1 ) );
630
631 sTest_ = Teuchos::rcp( new StatusTestCombo_t( StatusTestCombo_t::OR, maxIterTest_, convTest_ ) );
632
633 // Create the status test output class.
634 // This class manages and formats the output from the status test.
636 outputTest_ = stoFactory.create( printer_, sTest_, outputFreq_, Passed+Failed+Undefined );
637
638 // Set the solver string for the output test
639 std::string solverDesc = " PCPG ";
640 outputTest_->setSolverDesc( solverDesc );
641
642 // Create the timer if we need to.
643 if (timerSolve_ == Teuchos::null) {
644 std::string solveLabel = label_ + ": PCPGSolMgr total solve time";
645#ifdef BELOS_TEUCHOS_TIME_MONITOR
646 timerSolve_ = Teuchos::TimeMonitor::getNewCounter(solveLabel);
647#endif
648 }
649
650 // Inform the solver manager that the current parameters were set.
651 isSet_ = true;
652}
653
654
655template<class ScalarType, class MV, class OP, class DM>
656Teuchos::RCP<const Teuchos::ParameterList>
658{
659 static Teuchos::RCP<const Teuchos::ParameterList> validPL;
660 if (is_null(validPL)) {
661 Teuchos::RCP<Teuchos::ParameterList> pl = Teuchos::parameterList();
662 // Set all the valid parameters and their default values.
663 pl->set("Convergence Tolerance", static_cast<MagnitudeType>(DefaultSolverParameters::convTol),
664 "The relative residual tolerance that needs to be achieved by the\n"
665 "iterative solver in order for the linear system to be declared converged.");
666 pl->set("Maximum Iterations", static_cast<int>(maxIters_default_),
667 "The maximum number of iterations allowed for each\n"
668 "set of RHS solved.");
669 pl->set("Num Deflated Blocks", static_cast<int>(deflatedBlocks_default_),
670 "The maximum number of vectors in the seed subspace." );
671 pl->set("Num Saved Blocks", static_cast<int>(savedBlocks_default_),
672 "The maximum number of vectors saved from old Krylov subspaces." );
673 pl->set("Verbosity", static_cast<int>(verbosity_default_),
674 "What type(s) of solver information should be outputted\n"
675 "to the output stream.");
676 pl->set("Output Style", static_cast<int>(outputStyle_default_),
677 "What style is used for the solver information outputted\n"
678 "to the output stream.");
679 pl->set("Output Frequency", static_cast<int>(outputFreq_default_),
680 "How often convergence information should be outputted\n"
681 "to the output stream.");
682 pl->set("Output Stream", Teuchos::rcpFromRef(std::cout),
683 "A reference-counted pointer to the output stream where all\n"
684 "solver output is sent.");
685 pl->set("Timer Label", static_cast<const char *>(label_default_),
686 "The string to use as a prefix for the timer labels.");
687 pl->set("Orthogonalization", static_cast<const char *>(orthoType_default_),
688 "The type of orthogonalization to use: DGKS, ICGS, IMGS");
689 pl->set("Orthogonalization Constant",static_cast<MagnitudeType>(DefaultSolverParameters::orthoKappa),
690 "The constant used by DGKS orthogonalization to determine\n"
691 "whether another step of classical Gram-Schmidt is necessary.");
692 validPL = pl;
693 }
694 return validPL;
695}
696
697
698// solve()
699template<class ScalarType, class MV, class OP, class DM>
702
703 // Set the current parameters if are not set already.
704 if (!isSet_) { setParameters( params_ ); }
705
706 Teuchos::LAPACK<int,ScalarType> lapack;
707 ScalarType one = Teuchos::ScalarTraits<ScalarType>::one();
708 ScalarType zero = Teuchos::ScalarTraits<ScalarType>::zero();
709
711 "Belos::PCPGSolMgr::solve(): Linear problem is not a valid object.");
712
714 "Belos::PCPGSolMgr::solve(): Linear problem is not ready, setProblem() has not been called.");
715
716 // Create indices for the linear systems to be solved.
717 int numRHS2Solve = MVT::GetNumberVecs( *(problem_->getRHS()) );
718 std::vector<int> currIdx(1);
719 currIdx[0] = 0;
720
721 // Inform the linear problem of the current linear system to solve.
722 problem_->setLSIndex( currIdx ); // block size == 1
723
724 // Assume convergence is achieved, then let any failed convergence set this to false.
725 bool isConverged = true;
726
728 // PCPG iteration parameter list
729 Teuchos::ParameterList plist;
730 plist.set("Saved Blocks", savedBlocks_);
731 plist.set("Block Size", 1);
732 plist.set("Keep Diagonal", true);
733 plist.set("Initialize Diagonal", true);
734
736 // PCPG solver
737
738 Teuchos::RCP<PCPGIter<ScalarType,MV,OP,DM> > pcpg_iter;
739 pcpg_iter = Teuchos::rcp( new PCPGIter<ScalarType,MV,OP,DM>(problem_,printer_,outputTest_,plist) );
740 // Number of iterations required to generate initial recycle space (if needed)
741
742 // Enter solve() iterations
743 {
744#ifdef BELOS_TEUCHOS_TIME_MONITOR
745 Teuchos::TimeMonitor slvtimer(*timerSolve_);
746#endif
747 while ( numRHS2Solve > 0 ) { // test for quick return
748
749 // Reset the status test.
750 outputTest_->reset();
751
752 // Create the first block in the current Krylov basis (residual).
753 if (R_ == Teuchos::null)
754 R_ = MVT::Clone( *(problem_->getRHS()), 1 );
755
756 problem_->computeCurrResVec( &*R_ );
757
758
759 // Hypothesis: if U_ is not null, then neither is C_ and furthermore U'C= I.
760 // TODO: ensure hypothesis right here ... I have to think about use cases.
761
762 if( U_ != Teuchos::null ){
763 // Hypothesis: if U_ is not null, then neither is C_ and furthermore U'C= I.
764
765 // possibly over solved equation ... I want residual norms
766 // relative to the initial residual, not what I am about to compute.
767 Teuchos::RCP<MV> cur_soln_vec = problem_->getCurrLHSVec();
768 std::vector<MagnitudeType> rnorm0(1);
769 MVT::MvNorm( *R_, rnorm0 ); // rnorm0 = norm(R_);
770
771 // Z := U_'*R_; xo += U_*Z ;R_ -= C_*Z
772 printer_->stream(Debug) << "Solver Manager: dimU_ = " << dimU_ << std::endl;
773 Teuchos::RCP<DM> Z = DMT::Create( dimU_, 1 );
774
775 Teuchos::RCP<const MV> Uactive, Cactive;
776 std::vector<int> active_columns( dimU_ );
777 for (int i=0; i < dimU_; ++i) active_columns[i] = i;
778 Uactive = MVT::CloneView(*U_, active_columns);
779 Cactive = MVT::CloneView(*C_, active_columns);
780
781 MVT::MvTransMv( one, *Uactive, *R_, *Z );
782 Teuchos::RCP<MV> tempU = MVT::Clone( *R_, 1 );
783 MVT::MvTimesMatAddMv( one, *Uactive, *Z, zero, *tempU ); // UZ
784 MVT::MvAddMv( one, *tempU, one, *cur_soln_vec, *cur_soln_vec ); // xo += tmp;
785 MVT::MvTimesMatAddMv( one, *Cactive, *Z, zero, *tempU ); // CZ
786 MVT::MvAddMv( -one, *tempU, one, *R_, *R_ ); // R_ -= tmp;
787 std::vector<MagnitudeType> rnorm(1);
788 MVT::MvNorm( *R_, rnorm );
789 if( rnorm[0] < rnorm0[0] * .001 ){ //reorthogonalize
790 MVT::MvTransMv( one, *Uactive, *R_, *Z );
791 MVT::MvTimesMatAddMv( one, *Uactive, *Z, zero, *tempU );
792 MVT::MvAddMv( one, *tempU, one, *cur_soln_vec, *cur_soln_vec ); // xo += UZ;
793 MVT::MvTimesMatAddMv( one, *Cactive, *Z, zero, *tempU );
794 MVT::MvAddMv( -one, *tempU, one, *R_, *R_ ); // R_ -= CZ;
795 }
796 Uactive = Teuchos::null;
797 Cactive = Teuchos::null;
798 tempU = Teuchos::null;
799 }
800 else {
801 dimU_ = 0;
802 }
803
804
805 // Set the new state and initialize the solver.
806 PCPGIterState<ScalarType,MV,DM> pcpgState; // fails if R == null.
807
808 pcpgState.R = R_;
809 if( U_ != Teuchos::null ) pcpgState.U = U_;
810 if( C_ != Teuchos::null ) pcpgState.C = C_;
811 if( dimU_ > 0 ) pcpgState.curDim = dimU_;
812 pcpg_iter->initialize(pcpgState);
813
814 // treat initialize() exceptions here? how to use try-catch-throw? DMD
815
816 // Get the current number of deflated blocks with the PCPG iteration
817 dimU_ = pcpgState.curDim;
818 if( !dimU_ ) printer_->stream(Debug) << " No recycled subspace available for RHS index " << currIdx[0] << std::endl << std::endl;
819 pcpg_iter->resetNumIters();
820
821 if( dimU_ > savedBlocks_ )
822 printer_->stream(Debug) << "Error: dimU_ = " << dimU_ << " > savedBlocks_ = " << savedBlocks_ << std::endl;
823
824 while(1) { // dummy loop for break
825
826 // tell pcpg_iter to iterate
827 try {
828 printer_->stream(Debug) << "********** Calling iterate...\n" << std::endl;
829 pcpg_iter->iterate();
830
832 //
833 // check convergence first
834 //
836 if ( convTest_->getStatus() == Passed ) {
837 // we have convergence
838 break; // break from while(1){pcpg_iter->iterate()}
839 }
841 //
842 // check for maximum iterations
843 //
845 else if ( maxIterTest_->getStatus() == Passed ) {
846 // we don't have convergence
848 isConverged = false;
849 break; // break from while(1){pcpg_iter->iterate()}
850 }
851 else {
852
854 //
855 // we returned from iterate(), but none of our status tests Passed.
856 // Something is wrong, and it is probably the developers fault.
857 //
860 TEUCHOS_TEST_FOR_EXCEPTION(true,std::logic_error,
861 "Belos::PCPGSolMgr::solve(): Invalid return from PCPGIter::iterate().");
862 } // end if
863 } // end try
864 catch (const StatusTestNaNError& e) {
865 // A NaN was detected in the solver. Set the solution to zero and return unconverged.
867 achievedTol_ = MT::one();
868 Teuchos::RCP<MV> X = problem_->getLHS();
869 MVT::MvInit( *X, SCT::zero() );
870 printer_->stream(Warnings) << "Belos::PCPG::solve(): Warning! NaN has been detected!"
871 << std::endl;
872 return retType;
873 }
874 catch (const std::exception &e) {
876 printer_->stream(Errors) << "Error! Caught exception in PCPGIter::iterate() at iteration "
877 << pcpg_iter->getNumIters() << std::endl
878 << e.what() << std::endl;
879 throw;
880 }
881 } // end of while(1)
882
883 // Update the linear problem.
884 Teuchos::RCP<MV> update = pcpg_iter->getCurrentUpdate();
885 problem_->updateSolution( update, true );
886
887 // Inform the linear problem that we are finished with this block linear system.
888 problem_->setCurrLS();
889
890 // Get the state. How did pcpgState die?
892
893 dimU_ = oldState.curDim;
894 int q = oldState.prevUdim;
895
896 printer_->stream(Debug) << "SolverManager: dimU_ " << dimU_ << " prevUdim= " << q << std::endl;
897
898 if( q > deflatedBlocks_ )
899 printer_->stream(Debug) << "SolverManager: Error deflatedBlocks = " << deflatedBlocks_ << std::endl;
900
901 int rank;
902 if( dimU_ > q ){ // Orthogonalize [U;C](:,prevUdim:dimU_)
903 //Given the seed space U and C = A U for some symmetric positive definite A,
904 //find U1 and C1 with span(U1)=span(U) such that C1'U1 = I maintaining C=AU
905
906 U_ = oldState.U; //MVT::MvPrint( *U_, std::cout );
907 C_ = oldState.C; //MVT::MvPrint( *C_, std::cout );
908 rank = ARRQR(dimU_,q, oldState.D );
909 if( rank < dimU_ ) {
910 printer_->stream(Debug) << " rank decreased in ARRQR, something to do? " << std::endl;
911 }
912 dimU_ = rank;
913
914 } // Now U_ and C_ = AU are dual bases.
915
916 if( dimU_ > deflatedBlocks_ ){
917
918 if( !deflatedBlocks_ ){
919 U_ = Teuchos::null;
920 C_ = Teuchos::null;
921 dimU_ = deflatedBlocks_;
922 break;
923 }
924
925 bool Harmonic = false; // (Harmonic) Ritz vectors
926
927 Teuchos::RCP<MV> Uorth;
928
929 std::vector<int> active_cols( dimU_ );
930 for (int i=0; i < dimU_; ++i) active_cols[i] = i;
931
932 if( Harmonic ){
933 Uorth = MVT::CloneCopy(*C_, active_cols);
934 }
935 else{
936 Uorth = MVT::CloneCopy(*U_, active_cols);
937 }
938
939 // Explicitly construct Q and R factors
940 Teuchos::RCP<DM> R = DMT::Create(dimU_,dimU_);
941 rank = ortho_->normalize(*Uorth, R);
942 DMT::SyncDeviceToHost( *R );
943 // TODO: During the previous solve, the matrix that normalizes U(1:q) was computed and discarded.
944 // One might save it, reuse it here, and just normalize columns U(q+1:dimU_) here.
945
946 // throw an error if U is both A-orthonormal and rank deficient
948 "Belos::PCPGSolMgr::solve(): Failed to compute orthonormal basis for initial recycled subspace.");
949
950
951 // R VT' = Ur S,
952 ScalarType *VT=0, *Ur=0; // Not referenced
953 int lwork = 5*dimU_; // minimal, extra computation < 67*dimU_
954 int info = 0; // Hermite
955 int lrwork = 1;
956 if( problem_->isHermitian() ) lrwork = dimU_;
957 std::vector<ScalarType> work(lwork); //
958 std::vector<ScalarType> Svec(dimU_); //
959 std::vector<ScalarType> rwork(lrwork);
960 lapack.GESVD('N', 'O',
961 DMT::GetNumRows(*R), DMT::GetNumCols(*R), DMT::GetRawHostPtr(*R), DMT::GetStride(*R),
962 &Svec[0],
963 Ur,1,
964 VT,1, // Output: VT stored in R
965 &work[0], lwork,
966 &rwork[0], &info);
967
969 "Belos::PCPGSolMgr::solve(): LAPACK _GESVD failed to compute singular values.");
970
971 DMT::SyncHostToDevice( *R );
972
973 if( work[0] != 67. * dimU_ )
974 printer_->stream(Debug) << " SVD " << dimU_ << " lwork " << work[0] << std::endl;
975 for( int i=0; i< dimU_; i++)
976 printer_->stream(Debug) << i << " " << Svec[i] << std::endl;
977
978 Teuchos::RCP<DM> wholeV = DMT::CreateCopy( *R, true );
979
980 int startRow = 0, startCol = 0;
981 if( Harmonic )
982 startCol = dimU_ - deflatedBlocks_;
983
984 Teuchos::RCP<const DM> V = DMT::SubviewConst( *wholeV, DMT::GetNumRows(*wholeV), deflatedBlocks_, startRow, startCol );
985
986 std::vector<int> active_columns( dimU_ );
987 std::vector<int> def_cols( deflatedBlocks_ );
988 for (int i=0; i < dimU_; ++i) active_columns[i] = i;
989 for (int i=0; i < deflatedBlocks_; ++i) def_cols[i] = i;
990
991 Teuchos::RCP<MV> Uactive = MVT::CloneViewNonConst(*U_, def_cols);
992 Teuchos::RCP<MV> Ucopy = MVT::CloneCopy( *U_, active_columns );
993 MVT::MvTimesMatAddMv( one, *Ucopy, *V, zero, *Uactive ); // U:= U*V
994 Teuchos::RCP<MV> Cactive = MVT::CloneViewNonConst(*C_, def_cols);
995 Teuchos::RCP<MV> Ccopy = MVT::CloneCopy( *C_, active_columns );
996 MVT::MvTimesMatAddMv( one, *Ccopy, *V, zero, *Cactive ); // C:= C*V
997 dimU_ = deflatedBlocks_;
998 }
999 printer_->stream(Debug) << " Generated recycled subspace using RHS index " << currIdx[0] << " of dimension " << dimU_ << std::endl << std::endl;
1000
1001 // Inform the linear problem that we are finished with this block linear system.
1002 problem_->setCurrLS();
1003
1004 // Update indices for the linear systems to be solved.
1005 numRHS2Solve -= 1;
1006 if ( numRHS2Solve > 0 ) {
1007 currIdx[0]++;
1008
1009 // Set the next indices.
1010 problem_->setLSIndex( currIdx );
1011 }
1012 else {
1013 currIdx.resize( numRHS2Solve );
1014 }
1015 }// while ( numRHS2Solve > 0 )
1016 }
1017
1018 // print final summary
1019 sTest_->print( printer_->stream(FinalSummary) );
1020
1021 // print timing information
1022#ifdef BELOS_TEUCHOS_TIME_MONITOR
1023 // Calling summarize() can be expensive, so don't call unless the
1024 // user wants to print out timing details. summarize() will do all
1025 // the work even if it's passed a "black hole" output stream.
1026 if (verbosity_ & TimingDetails)
1027 Teuchos::TimeMonitor::summarize( printer_->stream(TimingDetails) );
1028#endif
1029
1030 // Save the convergence test value ("achieved tolerance") for this solve.
1031 {
1032 using Teuchos::rcp_dynamic_cast;
1034 // testValues is nonnull and not persistent.
1035 const std::vector<MagnitudeType>* pTestValues =
1036 rcp_dynamic_cast<conv_test_type>(convTest_)->getTestValue();
1037
1038 TEUCHOS_TEST_FOR_EXCEPTION(pTestValues == NULL, std::logic_error,
1039 "Belos::PCPGSolMgr::solve(): The convergence test's getTestValue() "
1040 "method returned NULL. Please report this bug to the Belos developers.");
1041
1042 TEUCHOS_TEST_FOR_EXCEPTION(pTestValues->size() < 1, std::logic_error,
1043 "Belos::PCPGSolMgr::solve(): The convergence test's getTestValue() "
1044 "method returned a vector of length zero. Please report this bug to the "
1045 "Belos developers.");
1046
1047 // FIXME (mfh 12 Dec 2011) Does pTestValues really contain the
1048 // achieved tolerances for all vectors in the current solve(), or
1049 // just for the vectors from the last deflation?
1050 achievedTol_ = *std::max_element (pTestValues->begin(), pTestValues->end());
1051 }
1052
1053 // get iteration information for this solve
1054 numIters_ = maxIterTest_->getNumIters();
1055
1056 if (!isConverged) {
1057 return retType; // return from PCPGSolMgr::solve()
1058 }
1059 return Converged; // return from PCPGSolMgr::solve()
1060}
1061
1062// A-orthogonalize the Seed Space
1063// Note that Anasazi::GenOrthoManager provides simplified versions of the algorithm,
1064// that are not rank revealing, and are not designed for PCPG in other ways too.
1065template<class ScalarType, class MV, class OP, class DM>
1066int PCPGSolMgr<ScalarType,MV,OP,DM,true>::ARRQR(int p, int q, const std::vector<ScalarType>& D)
1067{
1068 using Teuchos::RCP;
1069 ScalarType one = Teuchos::ScalarTraits<ScalarType>::one();
1070 ScalarType zero = Teuchos::ScalarTraits<ScalarType>::zero();
1071
1072 // Allocate memory for scalars.
1074 Teuchos::RCP<DM> alpha = DMT::Create( 1, 1 );
1075 std::vector<int> curind(1);
1076 std::vector<int> ipiv(p - q); // RRQR Pivot indices
1077 std::vector<ScalarType> Pivots(p); // RRQR Pivots
1078 int i, imax, j, l;
1079 ScalarType rteps = 1.5e-8;
1080
1081 // Scale such that diag( U'C) = I
1082 for( i = q ; i < p ; i++ ){
1083 ipiv[i-q] = i;
1084 curind[0] = i;
1085 RCP<MV> P = MVT::CloneViewNonConst(*U_,curind);
1086 RCP<MV> AP = MVT::CloneViewNonConst(*C_,curind);
1087 anorm = one / Teuchos::ScalarTraits<ScalarType>::squareroot( D[i-q] ) ;
1088 MVT::MvScale( *P, anorm );
1089 MVT::MvScale( *AP, anorm );
1090 Pivots[i] = one;
1091 }
1092
1093 for( i = q ; i < p ; i++ ){
1094 if( q < i && i < p-1 ){ // Find the largest pivot
1095 imax = i;
1096 l = ipiv[imax-q];
1097 for( j = i+1 ; j < p ; j++ ){
1098 const int k = ipiv[j-q];
1099 if( Pivots[k] > Pivots[l] ){
1100 imax = j;
1101 l = k;
1102 }
1103 } // end for
1104 if( imax > i ){
1105 l = ipiv[imax-q]; // swap ipiv( imax ) and ipiv(i+1)
1106 ipiv[imax-q] = ipiv[i-q];
1107 ipiv[i-q] = l;
1108 }
1109 } // largest pivot found
1110 int k = ipiv[i-q];
1111
1112 if( Pivots[k] > 1.5625e-2 ){
1113 anorm = Pivots[k]; // A-norm of u
1114 }
1115 else{ // anorm = sqrt( U(:,k)'*C(:,k) );
1116 curind[0] = k;
1117 RCP<const MV> P = MVT::CloneView(*U_,curind);
1118 RCP<const MV> AP = MVT::CloneView(*C_,curind);
1119 MVT::MvTransMv( one, *P, *AP, *alpha);
1120 DMT::SyncDeviceToHost( *alpha );
1121 anorm = Teuchos::ScalarTraits<ScalarType>::squareroot( DMT::ValueConst(*alpha,0,0) ) ;
1122 }
1123 if( rteps <= anorm && anorm < 9.765625e-4){
1124 /*
1125 C(:,k) = A*U(:,k); % Change C
1126 fixC = U(:, ipiv(1:i-1) )'*C(:,k);
1127 U(:,k) = U(:,k) - U(:, ipiv(1:i-1) )*fixC;
1128 C(:,k) = C(:,k) - C(:, ipiv(1:i-1) )*fixC;
1129 anorm = sqrt( U(:,k)'*C(:,k) );
1130 */
1131 printer_->stream(Errors) << "ARRQR: Bad case not implemented" << std::endl;
1132 }
1133 if( anorm < rteps ){ // rank [U;C] = i-1
1134 printer_->stream(Errors) << "ARRQR : deficient case not implemented " << std::endl;
1135 //U = U(:, ipiv(1:i-1) );
1136 //C = C(:, ipiv(1:i-1) );
1137 p = q + i;
1138 // update curDim_ in State
1139 break;
1140 }
1141 curind[0] = k;
1142 RCP<MV> P = MVT::CloneViewNonConst(*U_,curind);
1143 RCP<MV> AP = MVT::CloneViewNonConst(*C_,curind);
1144 MVT::MvScale( *P, anorm ); // U(:,k) = U(:,k)/anorm;
1145 MVT::MvScale( *AP, anorm ); // C(:,k) = C(:,k)/anorm;
1146 Pivots[k] = one;
1147 for( j = i+1 ; j < p ; j++ ){
1148 l = ipiv[j-q]; // ahhh
1149 curind[0] = l;
1150 RCP<MV> Q = MVT::CloneViewNonConst(*U_,curind); // segmentation fault, j=i+1=5
1151 MVT::MvTransMv( one, *Q, *AP, *alpha); // alpha(0,0) = U(:,l)'*C(:,k);
1152 DMT::SyncDeviceToHost(*alpha);
1153 MVT::MvAddMv( -DMT::ValueConst(*alpha,0,0), *P, one, *Q, *Q ); // U(:,l) -= U(:,k) * alpha(0,0);
1154 RCP<MV> AQ = MVT::CloneViewNonConst(*C_,curind);
1155 MVT::MvAddMv( -DMT::ValueConst(*alpha,0,0), *AP, one, *AQ, *AQ ); // C(:,l) -= C(:,l) - C(:,k) * alpha(0,0);
1156 gamma = ( Pivots[l] - DMT::ValueConst(*alpha,0,0))*( Pivots[l] + DMT::ValueConst(*alpha,0,0));
1157 if( gamma > zero){
1158 Pivots[l] = Teuchos::ScalarTraits<ScalarType>::squareroot( gamma );
1159 }
1160 else {
1161 Pivots[l] = zero; //rank deficiency revealed
1162 }
1163 }
1164 }
1165 return p;
1166}
1167
1168// The method returns a string describing the solver manager.
1169template<class ScalarType, class MV, class OP, class DM>
1171{
1172 std::ostringstream oss;
1173 oss << "Belos::PCPGSolMgr<...,"<<Teuchos::ScalarTraits<ScalarType>::name()<<">";
1174 oss << "{";
1175 oss << "Ortho Type='"<<orthoType_;
1176 oss << "}";
1177 return oss.str();
1178}
1179
1180} // end Belos namespace
1181
1182#endif /* BELOS_PCPG_SOLMGR_HPP */
Belos header file which uses auto-configuration information to include necessary C++ headers.
Full specialization of Belos::DenseMatTraits for Kokkos::DualView with arbitrary scalarType....
Class which describes the linear problem to be solved by the iterative solver.
Class which manages the output and verbosity of the Belos solvers.
Belos concrete class to iterate Preconditioned Conjugate Projected Gradients.
Pure virtual base class which describes the basic interface for a solver manager.
Belos::StatusTest for logically combining several status tests.
Belos::StatusTestResNorm for specifying general residual norm stopping criteria.
Belos::StatusTest class for specifying a maximum number of iterations.
A factory class for generating StatusTestOutput objects.
Full specialization of Belos::DenseMatTraits for Teuchos::SerialDenseMatrix with ordinal type int and...
Collection of types and exceptions used within the Belos solvers.
Parent class to all Belos exceptions.
Type traits class that says whether Teuchos::LAPACK has a valid implementation for the given ScalarTy...
Base class for Belos::SolverManager subclasses which normally can only compile with real ScalarType t...
Alternative run-time polymorphic interface for operators.
Operator()
Default constructor (does nothing).
int getNumIters() const
Get the iteration count for the most recent call to solve().
void setProblem(const Teuchos::RCP< LinearProblem< ScalarType, MV, OP, DM > > &problem)
Set the linear problem that needs to be solved.
const LinearProblem< ScalarType, MV, OP, DM > & getProblem() const
Get current linear problem being solved for in this object.
MagnitudeType achievedTol() const
Tolerance achieved by the last solve() invocation.
Teuchos::Array< Teuchos::RCP< Teuchos::Time > > getTimers() const
Return the timers for this object.
Teuchos::RCP< const Teuchos::ParameterList > getCurrentParameters() const
Get a parameter list containing the current parameters for this object.
virtual Teuchos::RCP< SolverManager< ScalarType, MV, OP, DM > > clone() const
clone for Inverted Injection (DII)
bool isLOADetected() const
Return whether a loss of accuracy was detected by this solver during the most current solve.
void reset(const ResetType type)
Performs a reset of the solver manager specified by the ResetType. This informs the solver manager th...
PCPG iterative linear solver.
Teuchos::RCP< SolverManager< ScalarType, MV, OP, DM > > clone() const override
clone for Inverted Injection (DII)
PCPGSolMgr(const Teuchos::RCP< LinearProblem< ScalarType, MV, OP, DM > > &problem, const Teuchos::RCP< Teuchos::ParameterList > &pl)
PCPGSolMgrLAPACKFailure is thrown when a nonzero value is retuned from an LAPACK call.
PCPGSolMgrLAPACKFailure(const std::string &what_arg)
PCPGSolMgrLinearProblemFailure is thrown when the linear problem is not setup (i.e.
PCPGSolMgrLinearProblemFailure(const std::string &what_arg)
PCPGSolMgrOrthoFailure is thrown when the orthogonalization manager is unable to generate orthonormal...
PCPGSolMgrOrthoFailure(const std::string &what_arg)
@ StatusTestDetails
@ FinalSummary
@ TimingDetails
ReturnType
Whether the Belos solve converged for all linear systems.
@ NaNDetected
@ MaxItersReached
@ NonspecificException
@ InconsistentState
@ Undetermined
ResetType
How to reset the solver.
Default parameters common to most Belos solvers.
static const double convTol
Default convergence tolerance.
static const double orthoKappa
DGKS orthogonalization constant.

Generated for Belos by doxygen 1.9.8