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