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; isSet_ = false; }
264
266 void setParameters( const Teuchos::RCP<Teuchos::ParameterList> &params );
267
270 debugStatusTest_ = debugStatusTest;
271 // Force the status-test tree to be rebuilt on the next solve() so the
272 // debug test gets OR-combined into sTest_.
273 isSet_ = false;
274 }
275
277
279
280
284 void reset( const ResetType type ) { if ((type & Belos::Problem) && !Teuchos::is_null(problem_)) problem_->setProblem(); }
286
288
289
307 ReturnType solve();
308
310
313
315 std::string description() const;
316
318
319 private:
320
321 // In the A-inner product, perform an RRQR decomposition without using A unless absolutely necessary. Given
322 // 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.
323 int ARRQR(int numVecs, int numOrthVecs, const std::vector<ScalarType>& D);
324
325 // Linear problem.
326 Teuchos::RCP<LinearProblem<ScalarType,MV,OP,DM> > problem_;
327
328 // Output manager.
329 Teuchos::RCP<OutputManager<ScalarType> > printer_;
330 Teuchos::RCP<std::ostream> outputStream_;
331
332 // Status test.
333 Teuchos::RCP<StatusTest<ScalarType,MV,OP,DM> > sTest_;
334 Teuchos::RCP<StatusTestMaxIters<ScalarType,MV,OP,DM> > maxIterTest_;
335 Teuchos::RCP<StatusTestGenResNorm<ScalarType,MV,OP,DM> > convTest_;
336 Teuchos::RCP<StatusTestOutput<ScalarType,MV,OP,DM> > outputTest_;
337 Teuchos::RCP<StatusTest<ScalarType,MV,OP,DM> > debugStatusTest_;
338
339 // Orthogonalization manager.
340 Teuchos::RCP<MatOrthoManager<ScalarType,MV,OP,DM> > ortho_;
341
342 // Current parameter list.
343 Teuchos::RCP<Teuchos::ParameterList> params_;
344
345 // Default solver values.
346 static constexpr int maxIters_default_ = 1000;
347 static constexpr int deflatedBlocks_default_ = 2;
348 static constexpr int savedBlocks_default_ = 16;
349 static constexpr int verbosity_default_ = Belos::Errors;
350 static constexpr int outputStyle_default_ = Belos::General;
351 static constexpr int outputFreq_default_ = -1;
352 static constexpr const char * label_default_ = "Belos";
353 static constexpr const char * orthoType_default_ = "ICGS";
354
355 //
356 // Current solver values.
357 //
358
360 MagnitudeType convtol_;
361
363 MagnitudeType orthoKappa_;
364
366 MagnitudeType achievedTol_;
367
369 int numIters_;
370
372 int maxIters_;
373
374 int deflatedBlocks_, savedBlocks_, verbosity_, outputStyle_, outputFreq_;
375 std::string orthoType_;
376
377 // Recycled subspace, its image and the residual
378 Teuchos::RCP<MV> U_, C_, R_;
379
380 // Actual dimension of current recycling subspace (<= savedBlocks_ )
381 int dimU_;
382
383 // Timers.
384 std::string label_;
385 Teuchos::RCP<Teuchos::Time> timerSolve_;
386
387 // Internal state variables.
388 bool isSet_;
389 };
390
391
392// Empty Constructor
393template<class ScalarType, class MV, class OP, class DM>
395 outputStream_(Teuchos::rcpFromRef(std::cout)),
396 convtol_(DefaultSolverParameters::convTol),
397 orthoKappa_(DefaultSolverParameters::orthoKappa),
398 achievedTol_(Teuchos::ScalarTraits<MagnitudeType>::zero()),
399 numIters_(0),
400 maxIters_(maxIters_default_),
401 deflatedBlocks_(deflatedBlocks_default_),
402 savedBlocks_(savedBlocks_default_),
403 verbosity_(verbosity_default_),
404 outputStyle_(outputStyle_default_),
405 outputFreq_(outputFreq_default_),
406 orthoType_(orthoType_default_),
407 dimU_(0),
408 label_(label_default_),
409 isSet_(false)
410{}
411
412
413// Basic Constructor
414template<class ScalarType, class MV, class OP, class DM>
416 const Teuchos::RCP<LinearProblem<ScalarType,MV,OP,DM> > &problem,
417 const Teuchos::RCP<Teuchos::ParameterList> &pl ) :
418 problem_(problem),
419 outputStream_(Teuchos::rcpFromRef(std::cout)),
420
421 convtol_(DefaultSolverParameters::convTol),
422 orthoKappa_(DefaultSolverParameters::orthoKappa),
423 achievedTol_(Teuchos::ScalarTraits<MagnitudeType>::zero()),
424 numIters_(0),
425 maxIters_(maxIters_default_),
426 deflatedBlocks_(deflatedBlocks_default_),
427 savedBlocks_(savedBlocks_default_),
428 verbosity_(verbosity_default_),
429 outputStyle_(outputStyle_default_),
430 outputFreq_(outputFreq_default_),
431 orthoType_(orthoType_default_),
432 dimU_(0),
433 label_(label_default_),
434 isSet_(false)
435{
437 problem_.is_null (), std::invalid_argument,
438 "Belos::PCPGSolMgr two-argument constructor: "
439 "'problem' is null. You must supply a non-null Belos::LinearProblem "
440 "instance when calling this constructor.");
441
442 if (! pl.is_null ()) {
443 // Set the parameters using the list that was passed in.
444 setParameters (pl);
445 }
446}
447
448
449template<class ScalarType, class MV, class OP, class DM>
450void PCPGSolMgr<ScalarType,MV,OP,DM,true>::setParameters( const Teuchos::RCP<Teuchos::ParameterList> &params )
451{
452 // Create the internal parameter list if ones doesn't already exist.
453 if (params_ == Teuchos::null) {
454 params_ = Teuchos::rcp( new Teuchos::ParameterList(*getValidParameters()) );
455 }
456 else {
457 params->validateParameters(*getValidParameters());
458 }
459
460 // Check for maximum number of iterations
461 if (params->isParameter("Maximum Iterations")) {
462 maxIters_ = params->get("Maximum Iterations",maxIters_default_);
463
464 // Update parameter in our list and in status test.
465 params_->set("Maximum Iterations", maxIters_);
466 if (maxIterTest_!=Teuchos::null)
467 maxIterTest_->setMaxIters( maxIters_ );
468 }
469
470 // Check for the maximum numbers of saved and deflated blocks.
471 if (params->isParameter("Num Saved Blocks")) {
472 savedBlocks_ = params->get("Num Saved Blocks",savedBlocks_default_);
473 TEUCHOS_TEST_FOR_EXCEPTION(savedBlocks_ <= 0, std::invalid_argument,
474 "Belos::PCPGSolMgr: \"Num Saved Blocks\" must be strictly positive.");
475
476 // savedBlocks > number of matrix rows and columns, not known in parameters.
477 //TEUCHOS_TEST_FOR_EXCEPTION(savedBlocks_ >= maxIters_, std::invalid_argument,
478 //"Belos::PCPGSolMgr: \"Num Saved Blocks\" must be less than \"Maximum Iterations\".");
479
480 // Update parameter in our list.
481 params_->set("Num Saved Blocks", savedBlocks_);
482 }
483 if (params->isParameter("Num Deflated Blocks")) {
484 deflatedBlocks_ = params->get("Num Deflated Blocks",deflatedBlocks_default_);
485 TEUCHOS_TEST_FOR_EXCEPTION(deflatedBlocks_ < 0, std::invalid_argument,
486 "Belos::PCPGSolMgr: \"Num Deflated Blocks\" must be positive.");
487
488 TEUCHOS_TEST_FOR_EXCEPTION(deflatedBlocks_ > savedBlocks_, std::invalid_argument,
489 "Belos::PCPGSolMgr: \"Num Deflated Blocks\" must be <= \"Num Saved Blocks\".");
490
491 // Update parameter in our list.
492 // The static_cast is for clang link issues with the constexpr before c++17
493 params_->set("Num Deflated Blocks", static_cast<int>(deflatedBlocks_));
494 }
495
496 // Check to see if the timer label changed.
497 if (params->isParameter("Timer Label")) {
498 std::string tempLabel = params->get("Timer Label", label_default_);
499
500 // Update parameter in our list and solver timer
501 if (tempLabel != label_) {
502 label_ = tempLabel;
503 params_->set("Timer Label", label_);
504 std::string solveLabel = label_ + ": PCPGSolMgr total solve time";
505#ifdef BELOS_TEUCHOS_TIME_MONITOR
506 timerSolve_ = Teuchos::TimeMonitor::getNewCounter(solveLabel);
507#endif
508 if (ortho_ != Teuchos::null) {
509 ortho_->setLabel( label_ );
510 }
511 }
512 }
513
514 // Check for a change in verbosity level
515 if (params->isParameter("Verbosity")) {
516 if (Teuchos::isParameterType<int>(*params,"Verbosity")) {
517 verbosity_ = params->get("Verbosity", verbosity_default_);
518 } else {
519 verbosity_ = (int)Teuchos::getParameter<Belos::MsgType>(*params,"Verbosity");
520 }
521
522 // Update parameter in our list.
523 params_->set("Verbosity", verbosity_);
524 if (printer_ != Teuchos::null)
525 printer_->setVerbosity(verbosity_);
526 }
527
528 // Check for a change in output style
529 if (params->isParameter("Output Style")) {
530 if (Teuchos::isParameterType<int>(*params,"Output Style")) {
531 outputStyle_ = params->get("Output Style", outputStyle_default_);
532 } else {
533 outputStyle_ = (int)Teuchos::getParameter<Belos::OutputType>(*params,"Output Style");
534 }
535
536 // Reconstruct the convergence test if the explicit residual test is not being used.
537 params_->set("Output Style", outputStyle_);
538 outputTest_ = Teuchos::null;
539 }
540
541 // output stream
542 if (params->isParameter("Output Stream")) {
543 outputStream_ = Teuchos::getParameter<Teuchos::RCP<std::ostream> >(*params,"Output Stream");
544
545 // Update parameter in our list.
546 params_->set("Output Stream", outputStream_);
547 if (printer_ != Teuchos::null)
548 printer_->setOStream( outputStream_ );
549 }
550
551 // frequency level
552 if (verbosity_ & Belos::StatusTestDetails) {
553 if (params->isParameter("Output Frequency")) {
554 outputFreq_ = params->get("Output Frequency", outputFreq_default_);
555 }
556
557 // Update parameter in out list and output status test.
558 params_->set("Output Frequency", outputFreq_);
559 if (outputTest_ != Teuchos::null)
560 outputTest_->setOutputFrequency( outputFreq_ );
561 }
562
563 // Create output manager if we need to.
564 if (printer_ == Teuchos::null) {
565 printer_ = Teuchos::rcp( new OutputManager<ScalarType>(verbosity_, outputStream_) );
566 }
567
568 // Check if the orthogonalization changed.
569 bool changedOrthoType = false;
570 if (params->isParameter("Orthogonalization")) {
571 std::string tempOrthoType = params->get("Orthogonalization",orthoType_default_);
572 if (tempOrthoType != orthoType_) {
573 orthoType_ = tempOrthoType;
574 changedOrthoType = true;
575 }
576 }
577 params_->set("Orthogonalization", orthoType_);
578
579 // Check which orthogonalization constant to use.
580 if (params->isParameter("Orthogonalization Constant")) {
581 if (params->isType<MagnitudeType> ("Orthogonalization Constant")) {
582 orthoKappa_ = params->get ("Orthogonalization Constant",
583 static_cast<MagnitudeType> (DefaultSolverParameters::orthoKappa));
584 }
585 else {
586 orthoKappa_ = params->get ("Orthogonalization Constant",
588 }
589
590 // Update parameter in our list.
591 params_->set("Orthogonalization Constant",orthoKappa_);
592 if (orthoType_=="DGKS") {
593 if (orthoKappa_ > 0 && ortho_ != Teuchos::null && !changedOrthoType) {
594 Teuchos::rcp_dynamic_cast<DGKSOrthoManager<ScalarType,MV,OP,DM> >(ortho_)->setDepTol( orthoKappa_ );
595 }
596 }
597 }
598
599 // Create orthogonalization manager if we need to.
600 if (ortho_ == Teuchos::null || changedOrthoType) {
602 Teuchos::RCP<Teuchos::ParameterList> paramsOrtho; // can be null
603 if (orthoType_=="DGKS" && orthoKappa_ > 0) {
604 paramsOrtho = Teuchos::rcp(new Teuchos::ParameterList());
605 paramsOrtho->set ("depTol", orthoKappa_ );
606 }
607
608 ortho_ = factory.makeMatOrthoManager (orthoType_, Teuchos::null, printer_, label_, paramsOrtho);
609 }
610
611 // Convergence
612 typedef Belos::StatusTestCombo<ScalarType,MV,OP,DM> StatusTestCombo_t;
613 typedef Belos::StatusTestGenResNorm<ScalarType,MV,OP,DM> StatusTestResNorm_t;
614
615 // Check for convergence tolerance
616 if (params->isParameter("Convergence Tolerance")) {
617 if (params->isType<MagnitudeType> ("Convergence Tolerance")) {
618 convtol_ = params->get ("Convergence Tolerance",
619 static_cast<MagnitudeType> (DefaultSolverParameters::convTol));
620 }
621 else {
622 convtol_ = params->get ("Convergence Tolerance", DefaultSolverParameters::convTol);
623 }
624
625 // Update parameter in our list and residual tests.
626 params_->set("Convergence Tolerance", convtol_);
627 if (convTest_ != Teuchos::null)
628 convTest_->setTolerance( convtol_ );
629 }
630
631 // Create status tests if we need to.
632
633 // Basic test checks maximum iterations and native residual.
634 if (maxIterTest_ == Teuchos::null)
635 maxIterTest_ = Teuchos::rcp( new StatusTestMaxIters<ScalarType,MV,OP,DM>( maxIters_ ) );
636
637 if (convTest_ == Teuchos::null)
638 convTest_ = Teuchos::rcp( new StatusTestResNorm_t( convtol_, 1 ) );
639
640 sTest_ = Teuchos::rcp( new StatusTestCombo_t( StatusTestCombo_t::OR, maxIterTest_, convTest_ ) );
641
642 // Add a debug status test if one was provided (e.g. a wall-clock time limit).
643 // OR-combining it into the top-level test lets it stop the solve; the
644 // dispatch in solve() treats such a stop as an unconverged (recoverable)
645 // termination.
646 if (Teuchos::nonnull(debugStatusTest_)) {
647 sTest_ = Teuchos::rcp( new StatusTestCombo_t( StatusTestCombo_t::OR, sTest_, debugStatusTest_ ) );
648 }
649
650 // Create the status test output class.
651 // This class manages and formats the output from the status test.
653 outputTest_ = stoFactory.create( printer_, sTest_, outputFreq_, Passed+Failed+Undefined );
654
655 // Set the solver string for the output test
656 std::string solverDesc = " PCPG ";
657 outputTest_->setSolverDesc( solverDesc );
658
659 // Create the timer if we need to.
660 if (timerSolve_ == Teuchos::null) {
661 std::string solveLabel = label_ + ": PCPGSolMgr total solve time";
662#ifdef BELOS_TEUCHOS_TIME_MONITOR
663 timerSolve_ = Teuchos::TimeMonitor::getNewCounter(solveLabel);
664#endif
665 }
666
667 // Inform the solver manager that the current parameters were set.
668 isSet_ = true;
669}
670
671
672template<class ScalarType, class MV, class OP, class DM>
673Teuchos::RCP<const Teuchos::ParameterList>
675{
676 static Teuchos::RCP<const Teuchos::ParameterList> validPL;
677 if (is_null(validPL)) {
678 Teuchos::RCP<Teuchos::ParameterList> pl = Teuchos::parameterList();
679 // Set all the valid parameters and their default values.
680 pl->set("Convergence Tolerance", static_cast<MagnitudeType>(DefaultSolverParameters::convTol),
681 "The relative residual tolerance that needs to be achieved by the\n"
682 "iterative solver in order for the linear system to be declared converged.");
683 pl->set("Maximum Iterations", static_cast<int>(maxIters_default_),
684 "The maximum number of iterations allowed for each\n"
685 "set of RHS solved.");
686 pl->set("Num Deflated Blocks", static_cast<int>(deflatedBlocks_default_),
687 "The maximum number of vectors in the seed subspace." );
688 pl->set("Num Saved Blocks", static_cast<int>(savedBlocks_default_),
689 "The maximum number of vectors saved from old Krylov subspaces." );
690 pl->set("Verbosity", static_cast<int>(verbosity_default_),
691 "What type(s) of solver information should be outputted\n"
692 "to the output stream.");
693 pl->set("Output Style", static_cast<int>(outputStyle_default_),
694 "What style is used for the solver information outputted\n"
695 "to the output stream.");
696 pl->set("Output Frequency", static_cast<int>(outputFreq_default_),
697 "How often convergence information should be outputted\n"
698 "to the output stream.");
699 pl->set("Output Stream", Teuchos::rcpFromRef(std::cout),
700 "A reference-counted pointer to the output stream where all\n"
701 "solver output is sent.");
702 pl->set("Timer Label", static_cast<const char *>(label_default_),
703 "The string to use as a prefix for the timer labels.");
704 pl->set("Orthogonalization", static_cast<const char *>(orthoType_default_),
705 "The type of orthogonalization to use: DGKS, ICGS, IMGS");
706 pl->set("Orthogonalization Constant",static_cast<MagnitudeType>(DefaultSolverParameters::orthoKappa),
707 "The constant used by DGKS orthogonalization to determine\n"
708 "whether another step of classical Gram-Schmidt is necessary.");
709 validPL = pl;
710 }
711 return validPL;
712}
713
714
715// solve()
716template<class ScalarType, class MV, class OP, class DM>
719
720 // Set the current parameters if are not set already.
721 if (!isSet_) { setParameters( params_ ); }
722
723 Teuchos::LAPACK<int,ScalarType> lapack;
724 ScalarType one = Teuchos::ScalarTraits<ScalarType>::one();
725 ScalarType zero = Teuchos::ScalarTraits<ScalarType>::zero();
726
728 "Belos::PCPGSolMgr::solve(): Linear problem is not a valid object.");
729
731 "Belos::PCPGSolMgr::solve(): Linear problem is not ready, setProblem() has not been called.");
732
733 // Create indices for the linear systems to be solved.
734 int numRHS2Solve = MVT::GetNumberVecs( *(problem_->getRHS()) );
735 std::vector<int> currIdx(1);
736 currIdx[0] = 0;
737
738 // Inform the linear problem of the current linear system to solve.
739 problem_->setLSIndex( currIdx ); // block size == 1
740
741 // Assume convergence is achieved, then let any failed convergence set this to false.
742 bool isConverged = true;
743
745 // PCPG iteration parameter list
746 Teuchos::ParameterList plist;
747 plist.set("Saved Blocks", savedBlocks_);
748 plist.set("Block Size", 1);
749 plist.set("Keep Diagonal", true);
750 plist.set("Initialize Diagonal", true);
751
753 // PCPG solver
754
755 Teuchos::RCP<PCPGIter<ScalarType,MV,OP,DM> > pcpg_iter;
756 pcpg_iter = Teuchos::rcp( new PCPGIter<ScalarType,MV,OP,DM>(problem_,printer_,outputTest_,plist) );
757 // Number of iterations required to generate initial recycle space (if needed)
758
759 // Enter solve() iterations
760 {
761#ifdef BELOS_TEUCHOS_TIME_MONITOR
762 Teuchos::TimeMonitor slvtimer(*timerSolve_);
763#endif
764 while ( numRHS2Solve > 0 ) { // test for quick return
765
766 // Reset the status test.
767 outputTest_->reset();
768
769 // Create the first block in the current Krylov basis (residual).
770 if (R_ == Teuchos::null)
771 R_ = MVT::Clone( *(problem_->getRHS()), 1 );
772
773 problem_->computeCurrResVec( &*R_ );
774
775
776 // Hypothesis: if U_ is not null, then neither is C_ and furthermore U'C= I.
777 // TODO: ensure hypothesis right here ... I have to think about use cases.
778
779 if( U_ != Teuchos::null ){
780 // Hypothesis: if U_ is not null, then neither is C_ and furthermore U'C= I.
781
782 // possibly over solved equation ... I want residual norms
783 // relative to the initial residual, not what I am about to compute.
784 Teuchos::RCP<MV> cur_soln_vec = problem_->getCurrLHSVec();
785 std::vector<MagnitudeType> rnorm0(1);
786 MVT::MvNorm( *R_, rnorm0 ); // rnorm0 = norm(R_);
787
788 // Z := U_'*R_; xo += U_*Z ;R_ -= C_*Z
789 printer_->stream(Debug) << "Solver Manager: dimU_ = " << dimU_ << std::endl;
790 Teuchos::RCP<DM> Z = DMT::Create( dimU_, 1 );
791
792 Teuchos::RCP<const MV> Uactive, Cactive;
793 std::vector<int> active_columns( dimU_ );
794 for (int i=0; i < dimU_; ++i) active_columns[i] = i;
795 Uactive = MVT::CloneView(*U_, active_columns);
796 Cactive = MVT::CloneView(*C_, active_columns);
797
798 MVT::MvTransMv( one, *Uactive, *R_, *Z );
799 Teuchos::RCP<MV> tempU = MVT::Clone( *R_, 1 );
800 MVT::MvTimesMatAddMv( one, *Uactive, *Z, zero, *tempU ); // UZ
801 MVT::MvAddMv( one, *tempU, one, *cur_soln_vec, *cur_soln_vec ); // xo += tmp;
802 MVT::MvTimesMatAddMv( one, *Cactive, *Z, zero, *tempU ); // CZ
803 MVT::MvAddMv( -one, *tempU, one, *R_, *R_ ); // R_ -= tmp;
804 std::vector<MagnitudeType> rnorm(1);
805 MVT::MvNorm( *R_, rnorm );
806 if( rnorm[0] < rnorm0[0] * .001 ){ //reorthogonalize
807 MVT::MvTransMv( one, *Uactive, *R_, *Z );
808 MVT::MvTimesMatAddMv( one, *Uactive, *Z, zero, *tempU );
809 MVT::MvAddMv( one, *tempU, one, *cur_soln_vec, *cur_soln_vec ); // xo += UZ;
810 MVT::MvTimesMatAddMv( one, *Cactive, *Z, zero, *tempU );
811 MVT::MvAddMv( -one, *tempU, one, *R_, *R_ ); // R_ -= CZ;
812 }
813 Uactive = Teuchos::null;
814 Cactive = Teuchos::null;
815 tempU = Teuchos::null;
816 }
817 else {
818 dimU_ = 0;
819 }
820
821
822 // Set the new state and initialize the solver.
823 PCPGIterState<ScalarType,MV,DM> pcpgState; // fails if R == null.
824
825 pcpgState.R = R_;
826 if( U_ != Teuchos::null ) pcpgState.U = U_;
827 if( C_ != Teuchos::null ) pcpgState.C = C_;
828 if( dimU_ > 0 ) pcpgState.curDim = dimU_;
829 pcpg_iter->initialize(pcpgState);
830
831 // treat initialize() exceptions here? how to use try-catch-throw? DMD
832
833 // Get the current number of deflated blocks with the PCPG iteration
834 dimU_ = pcpgState.curDim;
835 if( !dimU_ ) printer_->stream(Debug) << " No recycled subspace available for RHS index " << currIdx[0] << std::endl << std::endl;
836 pcpg_iter->resetNumIters();
837
838 if( dimU_ > savedBlocks_ )
839 printer_->stream(Debug) << "Error: dimU_ = " << dimU_ << " > savedBlocks_ = " << savedBlocks_ << std::endl;
840
841 while(1) { // dummy loop for break
842
843 // tell pcpg_iter to iterate
844 try {
845 printer_->stream(Debug) << "********** Calling iterate...\n" << std::endl;
846 pcpg_iter->iterate();
847
849 //
850 // check convergence first
851 //
853 if ( convTest_->getStatus() == Passed ) {
854 // we have convergence
855 break; // break from while(1){pcpg_iter->iterate()}
856 }
858 //
859 // check for maximum iterations
860 //
862 else if ( maxIterTest_->getStatus() == Passed ) {
863 // we don't have convergence
865 isConverged = false;
866 break; // break from while(1){pcpg_iter->iterate()}
867 }
869 //
870 // check for a debug status test requesting termination
871 //
873 else if (Teuchos::nonnull(debugStatusTest_) &&
874 debugStatusTest_->getStatus() == Passed) {
875 // A debug status test (e.g. a wall-clock time limit) stopped the
876 // iteration. Treat as an unconverged termination rather than an
877 // inconsistent state.
879 isConverged = false;
880 break; // break from while(1){pcpg_iter->iterate()}
881 }
882 else {
883
885 //
886 // we returned from iterate(), but none of our status tests Passed.
887 // Something is wrong, and it is probably the developers fault.
888 //
891 TEUCHOS_TEST_FOR_EXCEPTION(true,std::logic_error,
892 "Belos::PCPGSolMgr::solve(): Invalid return from PCPGIter::iterate().");
893 } // end if
894 } // end try
895 catch (const StatusTestNaNError& e) {
896 // A NaN was detected in the solver. Set the solution to zero and return unconverged.
898 achievedTol_ = MT::one();
899 Teuchos::RCP<MV> X = problem_->getLHS();
900 MVT::MvInit( *X, SCT::zero() );
901 printer_->stream(Warnings) << "Belos::PCPG::solve(): Warning! NaN has been detected!"
902 << std::endl;
903 return retType;
904 }
905 catch (const std::exception &e) {
907 printer_->stream(Errors) << "Error! Caught exception in PCPGIter::iterate() at iteration "
908 << pcpg_iter->getNumIters() << std::endl
909 << e.what() << std::endl;
910 throw;
911 }
912 } // end of while(1)
913
914 // Update the linear problem.
915 Teuchos::RCP<MV> update = pcpg_iter->getCurrentUpdate();
916 problem_->updateSolution( update, true );
917
918 // Inform the linear problem that we are finished with this block linear system.
919 problem_->setCurrLS();
920
921 // Get the state. How did pcpgState die?
923
924 dimU_ = oldState.curDim;
925 int q = oldState.prevUdim;
926
927 printer_->stream(Debug) << "SolverManager: dimU_ " << dimU_ << " prevUdim= " << q << std::endl;
928
929 if( q > deflatedBlocks_ )
930 printer_->stream(Debug) << "SolverManager: Error deflatedBlocks = " << deflatedBlocks_ << std::endl;
931
932 int rank;
933 if( dimU_ > q ){ // Orthogonalize [U;C](:,prevUdim:dimU_)
934 //Given the seed space U and C = A U for some symmetric positive definite A,
935 //find U1 and C1 with span(U1)=span(U) such that C1'U1 = I maintaining C=AU
936
937 U_ = oldState.U; //MVT::MvPrint( *U_, std::cout );
938 C_ = oldState.C; //MVT::MvPrint( *C_, std::cout );
939 rank = ARRQR(dimU_,q, oldState.D );
940 if( rank < dimU_ ) {
941 printer_->stream(Debug) << " rank decreased in ARRQR, something to do? " << std::endl;
942 }
943 dimU_ = rank;
944
945 } // Now U_ and C_ = AU are dual bases.
946
947 if( dimU_ > deflatedBlocks_ ){
948
949 if( !deflatedBlocks_ ){
950 U_ = Teuchos::null;
951 C_ = Teuchos::null;
952 dimU_ = deflatedBlocks_;
953 break;
954 }
955
956 bool Harmonic = false; // (Harmonic) Ritz vectors
957
958 Teuchos::RCP<MV> Uorth;
959
960 std::vector<int> active_cols( dimU_ );
961 for (int i=0; i < dimU_; ++i) active_cols[i] = i;
962
963 if( Harmonic ){
964 Uorth = MVT::CloneCopy(*C_, active_cols);
965 }
966 else{
967 Uorth = MVT::CloneCopy(*U_, active_cols);
968 }
969
970 // Explicitly construct Q and R factors
971 Teuchos::RCP<DM> R = DMT::Create(dimU_,dimU_);
972 rank = ortho_->normalize(*Uorth, R);
973 DMT::SyncDeviceToHost( *R );
974 // TODO: During the previous solve, the matrix that normalizes U(1:q) was computed and discarded.
975 // One might save it, reuse it here, and just normalize columns U(q+1:dimU_) here.
976
977 // throw an error if U is both A-orthonormal and rank deficient
979 "Belos::PCPGSolMgr::solve(): Failed to compute orthonormal basis for initial recycled subspace.");
980
981
982 // R VT' = Ur S,
983 ScalarType *VT=0, *Ur=0; // Not referenced
984 int lwork = 5*dimU_; // minimal, extra computation < 67*dimU_
985 int info = 0; // Hermite
986 int lrwork = 1;
987 if( problem_->isHermitian() ) lrwork = dimU_;
988 std::vector<ScalarType> work(lwork); //
989 std::vector<ScalarType> Svec(dimU_); //
990 std::vector<ScalarType> rwork(lrwork);
991 lapack.GESVD('N', 'O',
992 DMT::GetNumRows(*R), DMT::GetNumCols(*R), DMT::GetRawHostPtr(*R), DMT::GetStride(*R),
993 &Svec[0],
994 Ur,1,
995 VT,1, // Output: VT stored in R
996 &work[0], lwork,
997 &rwork[0], &info);
998
1000 "Belos::PCPGSolMgr::solve(): LAPACK _GESVD failed to compute singular values.");
1001
1002 DMT::SyncHostToDevice( *R );
1003
1004 if( work[0] != 67. * dimU_ )
1005 printer_->stream(Debug) << " SVD " << dimU_ << " lwork " << work[0] << std::endl;
1006 for( int i=0; i< dimU_; i++)
1007 printer_->stream(Debug) << i << " " << Svec[i] << std::endl;
1008
1009 Teuchos::RCP<DM> wholeV = DMT::CreateCopy( *R, true );
1010
1011 int startRow = 0, startCol = 0;
1012 if( Harmonic )
1013 startCol = dimU_ - deflatedBlocks_;
1014
1015 Teuchos::RCP<const DM> V = DMT::SubviewConst( *wholeV, DMT::GetNumRows(*wholeV), deflatedBlocks_, startRow, startCol );
1016
1017 std::vector<int> active_columns( dimU_ );
1018 std::vector<int> def_cols( deflatedBlocks_ );
1019 for (int i=0; i < dimU_; ++i) active_columns[i] = i;
1020 for (int i=0; i < deflatedBlocks_; ++i) def_cols[i] = i;
1021
1022 Teuchos::RCP<MV> Uactive = MVT::CloneViewNonConst(*U_, def_cols);
1023 Teuchos::RCP<MV> Ucopy = MVT::CloneCopy( *U_, active_columns );
1024 MVT::MvTimesMatAddMv( one, *Ucopy, *V, zero, *Uactive ); // U:= U*V
1025 Teuchos::RCP<MV> Cactive = MVT::CloneViewNonConst(*C_, def_cols);
1026 Teuchos::RCP<MV> Ccopy = MVT::CloneCopy( *C_, active_columns );
1027 MVT::MvTimesMatAddMv( one, *Ccopy, *V, zero, *Cactive ); // C:= C*V
1028 dimU_ = deflatedBlocks_;
1029 }
1030 printer_->stream(Debug) << " Generated recycled subspace using RHS index " << currIdx[0] << " of dimension " << dimU_ << std::endl << std::endl;
1031
1032 // Inform the linear problem that we are finished with this block linear system.
1033 problem_->setCurrLS();
1034
1035 // Update indices for the linear systems to be solved.
1036 numRHS2Solve -= 1;
1037 if ( numRHS2Solve > 0 ) {
1038 currIdx[0]++;
1039
1040 // Set the next indices.
1041 problem_->setLSIndex( currIdx );
1042 }
1043 else {
1044 currIdx.resize( numRHS2Solve );
1045 }
1046 }// while ( numRHS2Solve > 0 )
1047 }
1048
1049 // print final summary
1050 sTest_->print( printer_->stream(FinalSummary) );
1051
1052 // print timing information
1053#ifdef BELOS_TEUCHOS_TIME_MONITOR
1054 // Calling summarize() can be expensive, so don't call unless the
1055 // user wants to print out timing details. summarize() will do all
1056 // the work even if it's passed a "black hole" output stream.
1057 if (verbosity_ & TimingDetails)
1058 Teuchos::TimeMonitor::summarize( printer_->stream(TimingDetails) );
1059#endif
1060
1061 // Save the convergence test value ("achieved tolerance") for this solve.
1062 {
1063 using Teuchos::rcp_dynamic_cast;
1065 // testValues is nonnull and not persistent.
1066 const std::vector<MagnitudeType>* pTestValues =
1067 rcp_dynamic_cast<conv_test_type>(convTest_)->getTestValue();
1068
1069 TEUCHOS_TEST_FOR_EXCEPTION(pTestValues == NULL, std::logic_error,
1070 "Belos::PCPGSolMgr::solve(): The convergence test's getTestValue() "
1071 "method returned NULL. Please report this bug to the Belos developers.");
1072
1073 TEUCHOS_TEST_FOR_EXCEPTION(pTestValues->size() < 1, std::logic_error,
1074 "Belos::PCPGSolMgr::solve(): The convergence test's getTestValue() "
1075 "method returned a vector of length zero. Please report this bug to the "
1076 "Belos developers.");
1077
1078 // FIXME (mfh 12 Dec 2011) Does pTestValues really contain the
1079 // achieved tolerances for all vectors in the current solve(), or
1080 // just for the vectors from the last deflation?
1081 achievedTol_ = *std::max_element (pTestValues->begin(), pTestValues->end());
1082 }
1083
1084 // get iteration information for this solve
1085 numIters_ = maxIterTest_->getNumIters();
1086
1087 if (!isConverged) {
1088 return retType; // return from PCPGSolMgr::solve()
1089 }
1090 return Converged; // return from PCPGSolMgr::solve()
1091}
1092
1093// A-orthogonalize the Seed Space
1094// Note that Anasazi::GenOrthoManager provides simplified versions of the algorithm,
1095// that are not rank revealing, and are not designed for PCPG in other ways too.
1096template<class ScalarType, class MV, class OP, class DM>
1097int PCPGSolMgr<ScalarType,MV,OP,DM,true>::ARRQR(int p, int q, const std::vector<ScalarType>& D)
1098{
1099 using Teuchos::RCP;
1100 ScalarType one = Teuchos::ScalarTraits<ScalarType>::one();
1101 ScalarType zero = Teuchos::ScalarTraits<ScalarType>::zero();
1102
1103 // Allocate memory for scalars.
1105 Teuchos::RCP<DM> alpha = DMT::Create( 1, 1 );
1106 std::vector<int> curind(1);
1107 std::vector<int> ipiv(p - q); // RRQR Pivot indices
1108 std::vector<ScalarType> Pivots(p); // RRQR Pivots
1109 int i, imax, j, l;
1110 ScalarType rteps = 1.5e-8;
1111
1112 // Scale such that diag( U'C) = I
1113 for( i = q ; i < p ; i++ ){
1114 ipiv[i-q] = i;
1115 curind[0] = i;
1116 RCP<MV> P = MVT::CloneViewNonConst(*U_,curind);
1117 RCP<MV> AP = MVT::CloneViewNonConst(*C_,curind);
1118 anorm = one / Teuchos::ScalarTraits<ScalarType>::squareroot( D[i-q] ) ;
1119 MVT::MvScale( *P, anorm );
1120 MVT::MvScale( *AP, anorm );
1121 Pivots[i] = one;
1122 }
1123
1124 for( i = q ; i < p ; i++ ){
1125 if( q < i && i < p-1 ){ // Find the largest pivot
1126 imax = i;
1127 l = ipiv[imax-q];
1128 for( j = i+1 ; j < p ; j++ ){
1129 const int k = ipiv[j-q];
1130 if( Pivots[k] > Pivots[l] ){
1131 imax = j;
1132 l = k;
1133 }
1134 } // end for
1135 if( imax > i ){
1136 l = ipiv[imax-q]; // swap ipiv( imax ) and ipiv(i+1)
1137 ipiv[imax-q] = ipiv[i-q];
1138 ipiv[i-q] = l;
1139 }
1140 } // largest pivot found
1141 int k = ipiv[i-q];
1142
1143 if( Pivots[k] > 1.5625e-2 ){
1144 anorm = Pivots[k]; // A-norm of u
1145 }
1146 else{ // anorm = sqrt( U(:,k)'*C(:,k) );
1147 curind[0] = k;
1148 RCP<const MV> P = MVT::CloneView(*U_,curind);
1149 RCP<const MV> AP = MVT::CloneView(*C_,curind);
1150 MVT::MvTransMv( one, *P, *AP, *alpha);
1151 DMT::SyncDeviceToHost( *alpha );
1152 anorm = Teuchos::ScalarTraits<ScalarType>::squareroot( DMT::ValueConst(*alpha,0,0) ) ;
1153 }
1154 if( rteps <= anorm && anorm < 9.765625e-4){
1155 /*
1156 C(:,k) = A*U(:,k); % Change C
1157 fixC = U(:, ipiv(1:i-1) )'*C(:,k);
1158 U(:,k) = U(:,k) - U(:, ipiv(1:i-1) )*fixC;
1159 C(:,k) = C(:,k) - C(:, ipiv(1:i-1) )*fixC;
1160 anorm = sqrt( U(:,k)'*C(:,k) );
1161 */
1162 printer_->stream(Errors) << "ARRQR: Bad case not implemented" << std::endl;
1163 }
1164 if( anorm < rteps ){ // rank [U;C] = i-1
1165 printer_->stream(Errors) << "ARRQR : deficient case not implemented " << std::endl;
1166 //U = U(:, ipiv(1:i-1) );
1167 //C = C(:, ipiv(1:i-1) );
1168 p = q + i;
1169 // update curDim_ in State
1170 break;
1171 }
1172 curind[0] = k;
1173 RCP<MV> P = MVT::CloneViewNonConst(*U_,curind);
1174 RCP<MV> AP = MVT::CloneViewNonConst(*C_,curind);
1175 MVT::MvScale( *P, anorm ); // U(:,k) = U(:,k)/anorm;
1176 MVT::MvScale( *AP, anorm ); // C(:,k) = C(:,k)/anorm;
1177 Pivots[k] = one;
1178 for( j = i+1 ; j < p ; j++ ){
1179 l = ipiv[j-q]; // ahhh
1180 curind[0] = l;
1181 RCP<MV> Q = MVT::CloneViewNonConst(*U_,curind); // segmentation fault, j=i+1=5
1182 MVT::MvTransMv( one, *Q, *AP, *alpha); // alpha(0,0) = U(:,l)'*C(:,k);
1183 DMT::SyncDeviceToHost(*alpha);
1184 MVT::MvAddMv( -DMT::ValueConst(*alpha,0,0), *P, one, *Q, *Q ); // U(:,l) -= U(:,k) * alpha(0,0);
1185 RCP<MV> AQ = MVT::CloneViewNonConst(*C_,curind);
1186 MVT::MvAddMv( -DMT::ValueConst(*alpha,0,0), *AP, one, *AQ, *AQ ); // C(:,l) -= C(:,l) - C(:,k) * alpha(0,0);
1187 gamma = ( Pivots[l] - DMT::ValueConst(*alpha,0,0))*( Pivots[l] + DMT::ValueConst(*alpha,0,0));
1188 if( gamma > zero){
1189 Pivots[l] = Teuchos::ScalarTraits<ScalarType>::squareroot( gamma );
1190 }
1191 else {
1192 Pivots[l] = zero; //rank deficiency revealed
1193 }
1194 }
1195 }
1196 return p;
1197}
1198
1199// The method returns a string describing the solver manager.
1200template<class ScalarType, class MV, class OP, class DM>
1202{
1203 std::ostringstream oss;
1204 oss << "Belos::PCPGSolMgr<...,"<<Teuchos::ScalarTraits<ScalarType>::name()<<">";
1205 oss << "{";
1206 oss << "Ortho Type='"<<orthoType_;
1207 oss << "}";
1208 return oss.str();
1209}
1210
1211} // end Belos namespace
1212
1213#ifdef HAVE_BELOS_TPETRA
1215
1216#define BELOS_TPETRA_PCPGSOLMGR_NOEXTERN_CALL(SC, LO, GO, NT) \
1217 BELOS_TPETRA_CALL(Belos::PCPGSolMgr, SC, LO, GO, NT)
1218
1219#define BELOS_TPETRA_PCPGSOLMGR_EXTERN_CALL(SC, LO, GO, NT) \
1220 BELOS_TPETRA_EXTERN_CALL(Belos::PCPGSolMgr, SC, LO, GO, NT)
1221
1222TPETRA_INSTANTIATE_SLGN_NO_ORDINAL_SCALAR(BELOS_TPETRA_PCPGSOLMGR_EXTERN_CALL)
1223#endif
1224
1225
1226#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.
void setDebugStatusTest(const Teuchos::RCP< StatusTest< ScalarType, MV, OP, DM > > &debugStatusTest) override
Set a debug status test, OR-combined into the top-level status test.
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
@ Unconverged
@ 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