Stratimikos Package Browser (Single Doxygen Collection)  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Thyra_BelosLinearOpWithSolveFactory_def.hpp
Go to the documentation of this file.
1 /*
2 // @HEADER
3 // ***********************************************************************
4 //
5 // Stratimikos: Thyra-based strategies for linear solvers
6 // Copyright (2006) Sandia Corporation
7 //
8 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
9 // license for use of this work by or on behalf of the U.S. Government.
10 //
11 // Redistribution and use in source and binary forms, with or without
12 // modification, are permitted provided that the following conditions are
13 // met:
14 //
15 // 1. Redistributions of source code must retain the above copyright
16 // notice, this list of conditions and the following disclaimer.
17 //
18 // 2. Redistributions in binary form must reproduce the above copyright
19 // notice, this list of conditions and the following disclaimer in the
20 // documentation and/or other materials provided with the distribution.
21 //
22 // 3. Neither the name of the Corporation nor the names of the
23 // contributors may be used to endorse or promote products derived from
24 // this software without specific prior written permission.
25 //
26 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
27 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
30 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
31 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
32 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
36 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 //
38 // Questions? Contact Roscoe A. Bartlett (rabartl@sandia.gov)
39 //
40 // ***********************************************************************
41 // @HEADER
42 */
43 
44 
45 #ifndef THYRA_BELOS_LINEAR_OP_WITH_SOLVE_FACTORY_HPP
46 #define THYRA_BELOS_LINEAR_OP_WITH_SOLVE_FACTORY_HPP
47 
48 
50 #include "Thyra_BelosLinearOpWithSolve.hpp"
51 #include "Thyra_ScaledAdjointLinearOpBase.hpp"
52 
53 #include "BelosBlockGmresSolMgr.hpp"
54 #include "BelosPseudoBlockGmresSolMgr.hpp"
55 #include "BelosBlockCGSolMgr.hpp"
56 #include "BelosPseudoBlockCGSolMgr.hpp"
57 #include "BelosPseudoBlockStochasticCGSolMgr.hpp"
58 #include "BelosGCRODRSolMgr.hpp"
59 #include "BelosRCGSolMgr.hpp"
60 #include "BelosMinresSolMgr.hpp"
61 #include "BelosTFQMRSolMgr.hpp"
62 #include "BelosBiCGStabSolMgr.hpp"
63 #include "BelosFixedPointSolMgr.hpp"
64 #include "BelosThyraAdapter.hpp"
65 
66 #if defined(HAVE_BELOS_TPETRA) && defined(HAVE_STRATIMIKOS_THYRATPETRAADAPTERS)
68 #endif
69 
73 #include "Teuchos_dyn_cast.hpp"
76 
77 
78 namespace Thyra {
79 
80 
81 // Parameter names for Parameter List
82 
83 template<class Scalar>
84 const std::string BelosLinearOpWithSolveFactory<Scalar>::SolverType_name = "Solver Type";
85 template<class Scalar>
86 const std::string BelosLinearOpWithSolveFactory<Scalar>::SolverType_default = "Pseudo Block GMRES";
87 template<class Scalar>
88 const std::string BelosLinearOpWithSolveFactory<Scalar>::SolverTypes_name = "Solver Types";
89 template<class Scalar>
90 const std::string BelosLinearOpWithSolveFactory<Scalar>::BlockGMRES_name = "Block GMRES";
91 template<class Scalar>
92 const std::string BelosLinearOpWithSolveFactory<Scalar>::PseudoBlockGMRES_name = "Pseudo Block GMRES";
93 template<class Scalar>
94 const std::string BelosLinearOpWithSolveFactory<Scalar>::BlockCG_name = "Block CG";
95 template<class Scalar>
96 const std::string BelosLinearOpWithSolveFactory<Scalar>::PseudoBlockCG_name = "Pseudo Block CG";
97 template<class Scalar>
98 const std::string BelosLinearOpWithSolveFactory<Scalar>::PseudoBlockStochasticCG_name = "Pseudo Block Stochastic CG";
99 template<class Scalar>
100 const std::string BelosLinearOpWithSolveFactory<Scalar>::GCRODR_name = "GCRODR";
101 template<class Scalar>
102 const std::string BelosLinearOpWithSolveFactory<Scalar>::RCG_name = "RCG";
103 template<class Scalar>
104 const std::string BelosLinearOpWithSolveFactory<Scalar>::MINRES_name = "MINRES";
105 template<class Scalar>
106 const std::string BelosLinearOpWithSolveFactory<Scalar>::TFQMR_name = "TFQMR";
107 template<class Scalar>
108 const std::string BelosLinearOpWithSolveFactory<Scalar>::BiCGStab_name = "BiCGStab";
109 template<class Scalar>
110 const std::string BelosLinearOpWithSolveFactory<Scalar>::FixedPoint_name = "Fixed Point";
111 
112 #if defined(HAVE_BELOS_TPETRA) && defined(HAVE_STRATIMIKOS_THYRATPETRAADAPTERS)
113 template<class Scalar>
114 const std::string BelosLinearOpWithSolveFactory<Scalar>::TpetraGmres_name = "TPETRA GMRES";
115 template<class Scalar>
116 const std::string BelosLinearOpWithSolveFactory<Scalar>::TpetraGmresPipeline_name = "TPETRA GMRES PIPELINE";
117 template<class Scalar>
118 const std::string BelosLinearOpWithSolveFactory<Scalar>::TpetraGmresSingleReduce_name = "TPETRA GMRES SINGLE REDUCE";
119 template<class Scalar>
120 const std::string BelosLinearOpWithSolveFactory<Scalar>::TpetraGmresSstep_name = "TPETRA GMRES S-STEP";
121 #endif
122 
123 template<class Scalar>
124 const std::string BelosLinearOpWithSolveFactory<Scalar>::ConvergenceTestFrequency_name = "Convergence Test Frequency";
125 
126 namespace {
127 const std::string LeftPreconditionerIfUnspecified_name = "Left Preconditioner If Unspecified";
128 }
129 
130 // Constructors/initializers/accessors
131 
132 
133 template<class Scalar>
135  :solverType_(SOLVER_TYPE_PSEUDO_BLOCK_GMRES),
136  convergenceTestFrequency_(1)
137 {
139 }
140 
141 
142 template<class Scalar>
144  const RCP<PreconditionerFactoryBase<Scalar> > &precFactory
145  )
146  :solverType_(SOLVER_TYPE_PSEUDO_BLOCK_GMRES)
147 {
148  this->setPreconditionerFactory(precFactory, "");
149 }
150 
151 
152 // Overridden from LinearOpWithSolveFactoryBase
153 
154 
155 template<class Scalar>
157 {
158  return true;
159 }
160 
161 
162 template<class Scalar>
164  const RCP<PreconditionerFactoryBase<Scalar> > &precFactory,
165  const std::string &precFactoryName
166  )
167 {
168  TEUCHOS_TEST_FOR_EXCEPT(!precFactory.get());
170  precFactoryValidPL = precFactory->getValidParameters();
171  const std::string _precFactoryName =
172  ( precFactoryName != ""
173  ? precFactoryName
174  : ( precFactoryValidPL.get() ? precFactoryValidPL->name() : "GENERIC PRECONDITIONER FACTORY" )
175  );
176  precFactory_ = precFactory;
177  precFactoryName_ = _precFactoryName;
178  updateThisValidParamList();
179 }
180 
181 
182 template<class Scalar>
185 {
186  return precFactory_;
187 }
188 
189 
190 template<class Scalar>
192  RCP<PreconditionerFactoryBase<Scalar> > *precFactory,
193  std::string *precFactoryName
194  )
195 {
196  if(precFactory) *precFactory = precFactory_;
197  if(precFactoryName) *precFactoryName = precFactoryName_;
198  precFactory_ = Teuchos::null;
199  precFactoryName_ = "";
200  updateThisValidParamList();
201 }
202 
203 
204 template<class Scalar>
206  const LinearOpSourceBase<Scalar> &fwdOpSrc
207  ) const
208 {
209  if(precFactory_.get())
210  return precFactory_->isCompatible(fwdOpSrc);
211  return true; // Without a preconditioner, we are compatible with all linear operators!
212 }
213 
214 
215 template<class Scalar>
218 {
220 }
221 
222 
223 template<class Scalar>
225  const RCP<const LinearOpSourceBase<Scalar> > &fwdOpSrc,
226  LinearOpWithSolveBase<Scalar> *Op,
227  const ESupportSolveUse supportSolveUse
228  ) const
229 {
230  using Teuchos::null;
231  initializeOpImpl(fwdOpSrc,null,null,false,Op,supportSolveUse);
232 }
233 
234 
235 template<class Scalar>
237  const RCP<const LinearOpSourceBase<Scalar> > &fwdOpSrc,
238  LinearOpWithSolveBase<Scalar> *Op
239  ) const
240 {
241  using Teuchos::null;
242  initializeOpImpl(fwdOpSrc,null,null,true,Op,SUPPORT_SOLVE_UNSPECIFIED);
243 }
244 
245 
246 template<class Scalar>
248  const EPreconditionerInputType precOpType
249  ) const
250 {
251  if(precFactory_.get())
252  return true;
253  return (precOpType==PRECONDITIONER_INPUT_TYPE_AS_OPERATOR);
254 }
255 
256 
257 template<class Scalar>
259  const RCP<const LinearOpSourceBase<Scalar> > &fwdOpSrc,
260  const RCP<const PreconditionerBase<Scalar> > &prec,
261  LinearOpWithSolveBase<Scalar> *Op,
262  const ESupportSolveUse supportSolveUse
263  ) const
264 {
265  using Teuchos::null;
266  initializeOpImpl(fwdOpSrc,null,prec,false,Op,supportSolveUse);
267 }
268 
269 
270 template<class Scalar>
272  const RCP<const LinearOpSourceBase<Scalar> > &fwdOpSrc,
273  const RCP<const LinearOpSourceBase<Scalar> > &approxFwdOpSrc,
274  LinearOpWithSolveBase<Scalar> *Op,
275  const ESupportSolveUse supportSolveUse
276  ) const
277 {
278  using Teuchos::null;
279  initializeOpImpl(fwdOpSrc,approxFwdOpSrc,null,false,Op,supportSolveUse);
280 }
281 
282 
283 template<class Scalar>
285  LinearOpWithSolveBase<Scalar> *Op,
286  RCP<const LinearOpSourceBase<Scalar> > *fwdOpSrc,
287  RCP<const PreconditionerBase<Scalar> > *prec,
288  RCP<const LinearOpSourceBase<Scalar> > *approxFwdOpSrc,
289  ESupportSolveUse *supportSolveUse
290  ) const
291 {
292 #ifdef TEUCHOS_DEBUG
293  TEUCHOS_TEST_FOR_EXCEPT(Op==NULL);
294 #endif
298  _fwdOpSrc = belosOp.extract_fwdOpSrc();
300  _prec = ( belosOp.isExternalPrec() ? belosOp.extract_prec() : Teuchos::null );
301  // Note: above we only extract the preconditioner if it was passed in
302  // externally. Otherwise, we need to hold on to it so that we can reuse it
303  // in the next initialization.
305  _approxFwdOpSrc = belosOp.extract_approxFwdOpSrc();
306  ESupportSolveUse
307  _supportSolveUse = belosOp.supportSolveUse();
308  if(fwdOpSrc) *fwdOpSrc = _fwdOpSrc;
309  if(prec) *prec = _prec;
310  if(approxFwdOpSrc) *approxFwdOpSrc = _approxFwdOpSrc;
311  if(supportSolveUse) *supportSolveUse = _supportSolveUse;
312 }
313 
314 
315 // Overridden from ParameterListAcceptor
316 
317 
318 template<class Scalar>
320  RCP<Teuchos::ParameterList> const& paramList
321  )
322 {
323  TEUCHOS_TEST_FOR_EXCEPT(paramList.get()==NULL);
324  paramList->validateParametersAndSetDefaults(*this->getValidParameters(), 1);
325  paramList_ = paramList;
326  solverType_ =
327  Teuchos::getIntegralValue<EBelosSolverType>(*paramList_, SolverType_name);
328  convergenceTestFrequency_ =
329  Teuchos::getParameter<int>(*paramList_, ConvergenceTestFrequency_name);
330  Teuchos::readVerboseObjectSublist(&*paramList_,this);
331 }
332 
333 
334 template<class Scalar>
337 {
338  return paramList_;
339 }
340 
341 
342 template<class Scalar>
345 {
346  RCP<Teuchos::ParameterList> _paramList = paramList_;
347  paramList_ = Teuchos::null;
348  return _paramList;
349 }
350 
351 
352 template<class Scalar>
355 {
356  return paramList_;
357 }
358 
359 
360 template<class Scalar>
363 {
364  return thisValidParamList_;
365 }
366 
367 
368 // Public functions overridden from Teuchos::Describable
369 
370 
371 template<class Scalar>
373 {
374  std::ostringstream oss;
376  oss << "{";
377  if (nonnull(precFactory_)) {
378  oss << precFactory_->description();
379  }
380  oss << "}";
381  return oss.str();
382 }
383 
384 
385 // private
386 
387 
388 template<class Scalar>
391 {
392  using Teuchos::as;
393  using Teuchos::tuple;
394  using Teuchos::setStringToIntegralParameter;
398  >::getDummyObject(),
400  EBelosSolverType> >::getDummyObject());
401 
402  typedef MultiVectorBase<Scalar> MV_t;
403  typedef LinearOpBase<Scalar> LO_t;
404  static RCP<Teuchos::ParameterList> validParamList;
405  if(validParamList.get()==NULL) {
406  validParamList = Teuchos::rcp(new Teuchos::ParameterList("BelosLinearOpWithSolveFactory"));
407  setStringToIntegralParameter<EBelosSolverType>(
408  SolverType_name, SolverType_default,
409  "Type of linear solver algorithm to use.",
410  tuple<std::string>(
411  "Block GMRES",
412  "Pseudo Block GMRES",
413  "Block CG",
414  "Pseudo Block CG",
415  "Pseudo Block Stochastic CG",
416  "GCRODR",
417  "RCG",
418  "MINRES",
419  "TFQMR",
420  "BiCGStab",
421  "Fixed Point"
422 #if defined(HAVE_BELOS_TPETRA) && defined(HAVE_STRATIMIKOS_THYRATPETRAADAPTERS)
423  ,"TPETRA GMRES",
424  "TPETRA GMRES PIPELINE",
425  "TPETRA GMRES SINGLE REDUCE",
426  "TPETRA GMRES S-STEP"
427 #endif
428  ),
429  tuple<std::string>(
430  "Block GMRES solver for nonsymmetric linear systems. It can also solve "
431  "single right-hand side systems, and can also perform Flexible GMRES "
432  "(where the preconditioner may change at every iteration, for example "
433  "for inner-outer iterations), by setting options in the \"Block GMRES\" "
434  "sublist.",
435 
436  "GMRES solver for nonsymmetric linear systems, that performs single "
437  "right-hand side solves on multiple right-hand sides at once. It "
438  "exploits operator multivector multiplication in order to amortize "
439  "global communication costs. Individual linear systems are deflated "
440  "out as they are solved.",
441 
442  "Block CG solver for symmetric (Hermitian in complex arithmetic) "
443  "positive definite linear systems. It can also solve single "
444  "right-hand-side systems.",
445 
446  "CG solver that performs single right-hand side CG on multiple right-hand "
447  "sides at once. It exploits operator multivector multiplication in order "
448  "to amortize global communication costs. Individual linear systems are "
449  "deflated out as they are solved.",
450 
451  "stochastic CG solver that performs single right-hand side CG on multiple right-hand "
452  "sides at once. It exploits operator multivector multiplication in order "
453  "to amortize global communication costs. Individual linear systems are "
454  "deflated out as they are solved. [EXPERIMENTAL]",
455 
456  "Variant of GMRES that performs subspace recycling to accelerate "
457  "convergence for sequences of solves with related linear systems. "
458  "Individual linear systems are deflated out as they are solved. "
459  "The current implementation only supports real-valued Scalar types.",
460 
461  "CG solver for symmetric (Hermitian in complex arithmetic) positive "
462  "definite linear systems, that performs subspace recycling to "
463  "accelerate convergence for sequences of related linear systems.",
464 
465  "MINRES solver for symmetric indefinite linear systems. It performs "
466  "single-right-hand-side solves on multiple right-hand sides sequentially.",
467 
468  "TFQMR (Transpose-Free QMR) solver for nonsymmetric linear systems.",
469 
470  "BiCGStab solver for nonsymmetric linear systems.",
471 
472  "Fixed point iteration"
473 
474 #if defined(HAVE_BELOS_TPETRA) && defined(HAVE_STRATIMIKOS_THYRATPETRAADAPTERS)
475  ,"Native Tpetra implementation of GMRES",
476 
477  "Native Tpetra implementation of pipeline GMRES",
478 
479  "Native Tpetra implementation of single-reduce GMRES",
480 
481  "Native Tpetra implementation of s-step GMRES"
482 #endif
483  ),
484  tuple<EBelosSolverType>(
485  SOLVER_TYPE_BLOCK_GMRES,
486  SOLVER_TYPE_PSEUDO_BLOCK_GMRES,
487  SOLVER_TYPE_BLOCK_CG,
488  SOLVER_TYPE_PSEUDO_BLOCK_CG,
489  SOLVER_TYPE_PSEUDO_BLOCK_STOCHASTIC_CG,
490  SOLVER_TYPE_GCRODR,
491  SOLVER_TYPE_RCG,
492  SOLVER_TYPE_MINRES,
493  SOLVER_TYPE_TFQMR,
494  SOLVER_TYPE_BICGSTAB,
495  SOLVER_TYPE_FIXEDPOINT
496 #if defined(HAVE_BELOS_TPETRA) && defined(HAVE_STRATIMIKOS_THYRATPETRAADAPTERS)
497  ,SOLVER_TYPE_TPETRA_GMRES,
498  SOLVER_TYPE_TPETRA_GMRES_PIPELINE,
499  SOLVER_TYPE_TPETRA_GMRES_SINGLE_REDUCE,
500  SOLVER_TYPE_TPETRA_GMRES_SSTEP
501 #endif
502  ),
503  &*validParamList
504  );
505  validParamList->set(ConvergenceTestFrequency_name, as<int>(1),
506  "Number of linear solver iterations to skip between applying"
507  " user-defined convergence test.");
508  validParamList->set(
509  LeftPreconditionerIfUnspecified_name, false,
510  "If the preconditioner does not specify if it is left or right, and this\n"
511  "option is set to true, put the preconditioner on the left side.\n"
512  "Historically, preconditioning is on the right. Some solvers may not\n"
513  "support left preconditioning.");
515  &solverTypesSL = validParamList->sublist(SolverTypes_name);
516 
517  const bool lapackSupportsScalar = Belos::Details::LapackSupportsScalar<Scalar>::value;
518  const bool scalarIsReal = !Teuchos::ScalarTraits<Scalar>::isComplex;
519 
520  {
521  Belos::BlockGmresSolMgr<Scalar,MV_t,LO_t> mgr;
522  solverTypesSL.sublist(BlockGMRES_name).setParameters(
523  *mgr.getValidParameters()
524  );
525  }
526  {
527  Belos::PseudoBlockGmresSolMgr<Scalar,MV_t,LO_t> mgr;
528  solverTypesSL.sublist(PseudoBlockGMRES_name).setParameters(
529  *mgr.getValidParameters()
530  );
531  }
532  if (lapackSupportsScalar) {
533  Belos::BlockCGSolMgr<Scalar,MV_t,LO_t> mgr;
534  solverTypesSL.sublist(BlockCG_name).setParameters(
535  *mgr.getValidParameters()
536  );
537  }
538  if (lapackSupportsScalar) {
539  Belos::PseudoBlockCGSolMgr<Scalar,MV_t,LO_t> mgr;
540  solverTypesSL.sublist(PseudoBlockCG_name).setParameters(
541  *mgr.getValidParameters()
542  );
543  }
544  {
545  Belos::PseudoBlockStochasticCGSolMgr<Scalar,MV_t,LO_t> mgr;
546  solverTypesSL.sublist(PseudoBlockStochasticCG_name).setParameters(
547  *mgr.getValidParameters()
548  );
549  }
550  if (lapackSupportsScalar) {
551  Belos::GCRODRSolMgr<Scalar,MV_t,LO_t> mgr;
552  solverTypesSL.sublist(GCRODR_name).setParameters(
553  *mgr.getValidParameters()
554  );
555  }
556  if (lapackSupportsScalar && scalarIsReal) {
557  Belos::RCGSolMgr<Scalar,MV_t,LO_t> mgr;
558  solverTypesSL.sublist(RCG_name).setParameters(
559  *mgr.getValidParameters()
560  );
561  }
562  {
563  Belos::MinresSolMgr<Scalar,MV_t,LO_t> mgr;
564  solverTypesSL.sublist(MINRES_name).setParameters(
565  *mgr.getValidParameters()
566  );
567  }
568  {
569  Belos::TFQMRSolMgr<Scalar,MV_t,LO_t> mgr;
570  solverTypesSL.sublist(TFQMR_name).setParameters(
571  *mgr.getValidParameters()
572  );
573  }
574  {
575  Belos::BiCGStabSolMgr<Scalar,MV_t,LO_t> mgr;
576  solverTypesSL.sublist(BiCGStab_name).setParameters(
577  *mgr.getValidParameters()
578  );
579  }
580  {
581  Belos::FixedPointSolMgr<Scalar,MV_t,LO_t> mgr;
582  solverTypesSL.sublist(FixedPoint_name).setParameters(
583  *mgr.getValidParameters()
584  );
585  }
586 #if defined(HAVE_BELOS_TPETRA) && defined(HAVE_STRATIMIKOS_THYRATPETRAADAPTERS)
587  {
589  solverTypesSL.sublist(TpetraGmres_name).setParameters(
590  *mgr.getValidParameters()
591  );
592  }
593  {
595  solverTypesSL.sublist(TpetraGmresPipeline_name).setParameters(
596  *mgr.getValidParameters()
597  );
598  }
599  {
601  solverTypesSL.sublist(TpetraGmresSingleReduce_name).setParameters(
602  *mgr.getValidParameters()
603  );
604  }
605  {
607  solverTypesSL.sublist(TpetraGmresSstep_name).setParameters(
608  *mgr.getValidParameters()
609  );
610  }
611 #endif
612  }
613  return validParamList;
614 }
615 
616 
617 template<class Scalar>
619 {
620  thisValidParamList_ = Teuchos::rcp(
621  new Teuchos::ParameterList(*generateAndGetValidParameters())
622  );
623  Teuchos::setupVerboseObjectSublist(&*thisValidParamList_);
624 }
625 
626 
627 template<class Scalar>
629  const RCP<const LinearOpSourceBase<Scalar> > &fwdOpSrc,
630  const RCP<const LinearOpSourceBase<Scalar> > &approxFwdOpSrc,
631  const RCP<const PreconditionerBase<Scalar> > &prec_in,
632  const bool reusePrec,
633  LinearOpWithSolveBase<Scalar> *Op,
634  const ESupportSolveUse supportSolveUse
635  ) const
636 {
637 
638  using Teuchos::rcp;
639  using Teuchos::set_extra_data;
641  typedef MultiVectorBase<Scalar> MV_t;
642  typedef LinearOpBase<Scalar> LO_t;
643 
644  const RCP<Teuchos::FancyOStream> out = this->getOStream();
645  const Teuchos::EVerbosityLevel verbLevel = this->getVerbLevel();
646  Teuchos::OSTab tab(out);
647  if(out.get() && static_cast<int>(verbLevel) > static_cast<int>(Teuchos::VERB_LOW))
648  *out << "\nEntering Thyra::BelosLinearOpWithSolveFactory<"<<ST::name()<<">::initializeOpImpl(...) ...\n";
649 
650  // These lines are changing the verbosity of the preconditioner, which has its own verbose object list,
651  // so I am commenting these out, as it is not the job of the linear solver to dictate preconditioner verbosity.
652  //typedef Teuchos::VerboseObjectTempState<PreconditionerFactoryBase<Scalar> > VOTSPF;
653  //VOTSPF precFactoryOutputTempState(precFactory_,out,verbLevel);
654 
655  TEUCHOS_TEST_FOR_EXCEPT(Op==NULL);
656  TEUCHOS_TEST_FOR_EXCEPT(fwdOpSrc.get()==NULL);
657  TEUCHOS_TEST_FOR_EXCEPT(fwdOpSrc->getOp().get()==NULL);
659  fwdOp = fwdOpSrc->getOp(),
660  approxFwdOp = ( approxFwdOpSrc.get() ? approxFwdOpSrc->getOp() : Teuchos::null );
661 
662  //
663  // Get the BelosLinearOpWithSolve interface
664  //
665 
668 
669  //
670  // Get/Create the preconditioner
671  //
672 
675  if(prec_in.get()) {
676  // Use an externally defined preconditioner
677  prec = prec_in;
678  }
679  else {
680  // Try and generate a preconditioner on our own
681  if(precFactory_.get()) {
682  myPrec =
683  ( !belosOp->isExternalPrec()
684  ? Teuchos::rcp_const_cast<PreconditionerBase<Scalar> >(belosOp->extract_prec())
685  : Teuchos::null
686  );
687  bool hasExistingPrec = false;
688  if(myPrec.get()) {
689  hasExistingPrec = true;
690  // ToDo: Get the forward operator and validate that it is the same
691  // operator that is used here!
692  }
693  else {
694  hasExistingPrec = false;
695  myPrec = precFactory_->createPrec();
696  }
697  if( hasExistingPrec && reusePrec ) {
698  // Just reuse the existing preconditioner again!
699  }
700  else {
701  // Update the preconditioner
702  if(approxFwdOp.get())
703  precFactory_->initializePrec(approxFwdOpSrc,&*myPrec);
704  else
705  precFactory_->initializePrec(fwdOpSrc,&*myPrec);
706  }
707  prec = myPrec;
708  }
709  }
710 
711  //
712  // Uninitialize the current solver object
713  //
714 
715  bool oldIsExternalPrec = false;
720  ESupportSolveUse oldSupportSolveUse = SUPPORT_SOLVE_UNSPECIFIED;
721 
722  belosOp->uninitialize( &oldLP, NULL, &oldIterSolver, &oldFwdOpSrc,
723  NULL, &oldIsExternalPrec, &oldApproxFwdOpSrc, &oldSupportSolveUse );
724 
725  //
726  // Create the Belos linear problem
727  // NOTE: If one exists already, reuse it.
728  //
729 
730  typedef Belos::LinearProblem<Scalar,MV_t,LO_t> LP_t;
731  RCP<LP_t> lp;
732  if (oldLP != Teuchos::null) {
733  lp = oldLP;
734  }
735  else {
736  lp = rcp(new LP_t());
737  }
738 
739  //
740  // Set the operator
741  //
742 
743  lp->setOperator(fwdOp);
744 
745  //
746  // Set the preconditioner
747  //
748 
749  if(prec.get()) {
750  RCP<const LinearOpBase<Scalar> > unspecified = prec->getUnspecifiedPrecOp();
751  RCP<const LinearOpBase<Scalar> > left = prec->getLeftPrecOp();
752  RCP<const LinearOpBase<Scalar> > right = prec->getRightPrecOp();
754  !( left.get() || right.get() || unspecified.get() ), std::logic_error
755  ,"Error, at least one preconditoner linear operator objects must be set!"
756  );
757  if (nonnull(unspecified)) {
758  if (paramList_->get<bool>(LeftPreconditionerIfUnspecified_name, false))
759  lp->setLeftPrec(unspecified);
760  else
761  lp->setRightPrec(unspecified);
762  }
763  else if (nonnull(left)) {
764  lp->setLeftPrec(left);
765  }
766  else if (nonnull(right)) {
767  lp->setRightPrec(right);
768  }
769  else {
770  // Set a left, right or split preconditioner
772  nonnull(left) && nonnull(right),std::logic_error
773  ,"Error, we can not currently handle split preconditioners!"
774  );
775  }
776  }
777  if(myPrec.get()) {
778  set_extra_data<RCP<PreconditionerBase<Scalar> > >(myPrec,"Belos::InternalPrec",
779  Teuchos::inOutArg(lp), Teuchos::POST_DESTROY, false);
780  }
781  else if(prec.get()) {
782  set_extra_data<RCP<const PreconditionerBase<Scalar> > >(prec,"Belos::ExternalPrec",
783  Teuchos::inOutArg(lp), Teuchos::POST_DESTROY, false);
784  }
785 
786  //
787  // Generate the parameter list.
788  //
789 
790  typedef Belos::SolverManager<Scalar,MV_t,LO_t> IterativeSolver_t;
791  RCP<IterativeSolver_t> iterativeSolver = Teuchos::null;
793 
794  switch(solverType_) {
795  case SOLVER_TYPE_BLOCK_GMRES:
796  {
797  // Set the PL
798  if(paramList_.get()) {
799  Teuchos::ParameterList &solverTypesPL = paramList_->sublist(SolverTypes_name);
800  Teuchos::ParameterList &gmresPL = solverTypesPL.sublist(BlockGMRES_name);
801  solverPL = Teuchos::rcp( &gmresPL, false );
802  }
803  // Create the solver
804  if (oldIterSolver != Teuchos::null) {
805  iterativeSolver = oldIterSolver;
806  iterativeSolver->setProblem( lp );
807  iterativeSolver->setParameters( solverPL );
808  }
809  else {
810  iterativeSolver = rcp(new Belos::BlockGmresSolMgr<Scalar,MV_t,LO_t>(lp,solverPL));
811  }
812  break;
813  }
814  case SOLVER_TYPE_PSEUDO_BLOCK_GMRES:
815  {
816  // Set the PL
817  if(paramList_.get()) {
818  Teuchos::ParameterList &solverTypesPL = paramList_->sublist(SolverTypes_name);
819  Teuchos::ParameterList &pbgmresPL = solverTypesPL.sublist(PseudoBlockGMRES_name);
820  solverPL = Teuchos::rcp( &pbgmresPL, false );
821  }
822  //
823  // Create the solver
824  //
825  if (oldIterSolver != Teuchos::null) {
826  iterativeSolver = oldIterSolver;
827  iterativeSolver->setProblem( lp );
828  iterativeSolver->setParameters( solverPL );
829  }
830  else {
831  iterativeSolver = rcp(new Belos::PseudoBlockGmresSolMgr<Scalar,MV_t,LO_t>(lp,solverPL));
832  }
833  break;
834  }
835  case SOLVER_TYPE_BLOCK_CG:
836  {
837  // Set the PL
838  if(paramList_.get()) {
839  Teuchos::ParameterList &solverTypesPL = paramList_->sublist(SolverTypes_name);
840  Teuchos::ParameterList &cgPL = solverTypesPL.sublist(BlockCG_name);
841  solverPL = Teuchos::rcp( &cgPL, false );
842  }
843  // Create the solver
844  if (oldIterSolver != Teuchos::null) {
845  iterativeSolver = oldIterSolver;
846  iterativeSolver->setProblem( lp );
847  iterativeSolver->setParameters( solverPL );
848  }
849  else {
850  iterativeSolver = rcp(new Belos::BlockCGSolMgr<Scalar,MV_t,LO_t>(lp,solverPL));
851  }
852  break;
853  }
854  case SOLVER_TYPE_PSEUDO_BLOCK_CG:
855  {
856  // Set the PL
857  if(paramList_.get()) {
858  Teuchos::ParameterList &solverTypesPL = paramList_->sublist(SolverTypes_name);
859  Teuchos::ParameterList &pbcgPL = solverTypesPL.sublist(PseudoBlockCG_name);
860  solverPL = Teuchos::rcp( &pbcgPL, false );
861  }
862  //
863  // Create the solver
864  //
865  if (oldIterSolver != Teuchos::null) {
866  iterativeSolver = oldIterSolver;
867  iterativeSolver->setProblem( lp );
868  iterativeSolver->setParameters( solverPL );
869  }
870  else {
871  iterativeSolver = rcp(new Belos::PseudoBlockCGSolMgr<Scalar,MV_t,LO_t>(lp,solverPL));
872  }
873  break;
874  }
875  case SOLVER_TYPE_PSEUDO_BLOCK_STOCHASTIC_CG:
876  {
877  // Set the PL
878  if(paramList_.get()) {
879  Teuchos::ParameterList &solverTypesPL = paramList_->sublist(SolverTypes_name);
880  Teuchos::ParameterList &pbcgPL = solverTypesPL.sublist(PseudoBlockStochasticCG_name);
881  solverPL = Teuchos::rcp( &pbcgPL, false );
882  }
883  //
884  // Create the solver
885  //
886  if (oldIterSolver != Teuchos::null) {
887  iterativeSolver = oldIterSolver;
888  iterativeSolver->setProblem( lp );
889  iterativeSolver->setParameters( solverPL );
890  }
891  else {
892  iterativeSolver = rcp(new Belos::PseudoBlockStochasticCGSolMgr<Scalar,MV_t,LO_t>(lp,solverPL));
893  }
894  break;
895  }
896  case SOLVER_TYPE_GCRODR:
897  {
898  // Set the PL
899  if(paramList_.get()) {
900  Teuchos::ParameterList &solverTypesPL = paramList_->sublist(SolverTypes_name);
901  Teuchos::ParameterList &gcrodrPL = solverTypesPL.sublist(GCRODR_name);
902  solverPL = Teuchos::rcp( &gcrodrPL, false );
903  }
904  // Create the solver
905  if (oldIterSolver != Teuchos::null) {
906  iterativeSolver = oldIterSolver;
907  iterativeSolver->setProblem( lp );
908  iterativeSolver->setParameters( solverPL );
909  }
910  else {
911  iterativeSolver = rcp(new Belos::GCRODRSolMgr<Scalar,MV_t,LO_t>(lp,solverPL));
912  }
913  break;
914  }
915  case SOLVER_TYPE_RCG:
916  {
917  // Set the PL
918  if(paramList_.get()) {
919  Teuchos::ParameterList &solverTypesPL = paramList_->sublist(SolverTypes_name);
920  Teuchos::ParameterList &rcgPL = solverTypesPL.sublist(RCG_name);
921  solverPL = Teuchos::rcp( &rcgPL, false );
922  }
923  // Create the solver
924  if (oldIterSolver != Teuchos::null) {
925  iterativeSolver = oldIterSolver;
926  iterativeSolver->setProblem( lp );
927  iterativeSolver->setParameters( solverPL );
928  }
929  else {
930  iterativeSolver = rcp(new Belos::RCGSolMgr<Scalar,MV_t,LO_t>(lp,solverPL));
931  }
932  break;
933  }
934  case SOLVER_TYPE_MINRES:
935  {
936  // Set the PL
937  if(paramList_.get()) {
938  Teuchos::ParameterList &solverTypesPL = paramList_->sublist(SolverTypes_name);
939  Teuchos::ParameterList &minresPL = solverTypesPL.sublist(MINRES_name);
940  solverPL = Teuchos::rcp( &minresPL, false );
941  }
942  // Create the solver
943  if (oldIterSolver != Teuchos::null) {
944  iterativeSolver = oldIterSolver;
945  iterativeSolver->setProblem( lp );
946  iterativeSolver->setParameters( solverPL );
947  }
948  else {
949  iterativeSolver = rcp(new Belos::MinresSolMgr<Scalar,MV_t,LO_t>(lp,solverPL));
950  }
951  break;
952  }
953  case SOLVER_TYPE_TFQMR:
954  {
955  // Set the PL
956  if(paramList_.get()) {
957  Teuchos::ParameterList &solverTypesPL = paramList_->sublist(SolverTypes_name);
958  Teuchos::ParameterList &minresPL = solverTypesPL.sublist(TFQMR_name);
959  solverPL = Teuchos::rcp( &minresPL, false );
960  }
961  // Create the solver
962  if (oldIterSolver != Teuchos::null) {
963  iterativeSolver = oldIterSolver;
964  iterativeSolver->setProblem( lp );
965  iterativeSolver->setParameters( solverPL );
966  }
967  else {
968  iterativeSolver = rcp(new Belos::TFQMRSolMgr<Scalar,MV_t,LO_t>(lp,solverPL));
969  }
970  break;
971  }
972  case SOLVER_TYPE_BICGSTAB:
973  {
974  // Set the PL
975  if(paramList_.get()) {
976  Teuchos::ParameterList &solverTypesPL = paramList_->sublist(SolverTypes_name);
977  Teuchos::ParameterList &bicgstabPL = solverTypesPL.sublist(BiCGStab_name);
978  solverPL = Teuchos::rcp( &bicgstabPL, false );
979  }
980  // Create the solver
981  if (oldIterSolver != Teuchos::null) {
982  iterativeSolver = oldIterSolver;
983  iterativeSolver->setProblem( lp );
984  iterativeSolver->setParameters( solverPL );
985  }
986  else {
987  iterativeSolver = rcp(new Belos::BiCGStabSolMgr<Scalar,MV_t,LO_t>(lp,solverPL));
988  }
989  break;
990  }
991  case SOLVER_TYPE_FIXEDPOINT:
992  {
993  // Set the PL
994  if(paramList_.get()) {
995  Teuchos::ParameterList &solverTypesPL = paramList_->sublist(SolverTypes_name);
996  Teuchos::ParameterList &fixedPointPL = solverTypesPL.sublist(FixedPoint_name);
997  solverPL = Teuchos::rcp( &fixedPointPL, false );
998  }
999  // Create the solver
1000  if (oldIterSolver != Teuchos::null) {
1001  iterativeSolver = oldIterSolver;
1002  iterativeSolver->setProblem( lp );
1003  iterativeSolver->setParameters( solverPL );
1004  }
1005  else {
1006  iterativeSolver = rcp(new Belos::FixedPointSolMgr<Scalar,MV_t,LO_t>(lp,solverPL));
1007  }
1008  break;
1009  }
1010 #if defined(HAVE_BELOS_TPETRA) && defined(HAVE_STRATIMIKOS_THYRATPETRAADAPTERS)
1011  case SOLVER_TYPE_TPETRA_GMRES:
1012  {
1013  // Get the PL
1014  if(paramList_.get()) {
1015  Teuchos::ParameterList &solverTypesPL = paramList_->sublist(SolverTypes_name);
1016  Teuchos::ParameterList &tpetraGmresPL = solverTypesPL.sublist(TpetraGmres_name);
1017  solverPL = Teuchos::rcp( &tpetraGmresPL, false );
1018  }
1019  // Create the solver, always
1020  iterativeSolver = rcp(new Thyra::BelosTpetraGmres<Scalar,MV_t,LO_t>());
1021  // Set the Problem & PL
1022  iterativeSolver->setProblem( lp );
1023  iterativeSolver->setParameters( solverPL );
1024  break;
1025  }
1026  case SOLVER_TYPE_TPETRA_GMRES_PIPELINE:
1027  {
1028  // Get the PL
1029  if(paramList_.get()) {
1030  Teuchos::ParameterList &solverTypesPL = paramList_->sublist(SolverTypes_name);
1031  Teuchos::ParameterList &tpetraGmresPipelinePL = solverTypesPL.sublist(TpetraGmresPipeline_name);
1032  solverPL = Teuchos::rcp( &tpetraGmresPipelinePL, false );
1033  }
1034  // Create the solver, always
1035  iterativeSolver = rcp(new Thyra::BelosTpetraGmresPipeline<Scalar,MV_t,LO_t>());
1036  // Set the Problem & PL
1037  iterativeSolver->setProblem( lp );
1038  iterativeSolver->setParameters( solverPL );
1039  break;
1040  }
1041  case SOLVER_TYPE_TPETRA_GMRES_SINGLE_REDUCE:
1042  {
1043  // Get the PL
1044  if(paramList_.get()) {
1045  Teuchos::ParameterList &solverTypesPL = paramList_->sublist(SolverTypes_name);
1046  Teuchos::ParameterList &tpetraGmresSingleReducePL = solverTypesPL.sublist(TpetraGmresSingleReduce_name);
1047  solverPL = Teuchos::rcp( &tpetraGmresSingleReducePL, false );
1048  }
1049  // Create the solver, always
1051  // Set the Problem & PL
1052  iterativeSolver->setProblem( lp );
1053  iterativeSolver->setParameters( solverPL );
1054  break;
1055  }
1056  case SOLVER_TYPE_TPETRA_GMRES_SSTEP:
1057  {
1058  // Get the PL
1059  if(paramList_.get()) {
1060  Teuchos::ParameterList &solverTypesPL = paramList_->sublist(SolverTypes_name);
1061  Teuchos::ParameterList &tpetraGmresSstepPL = solverTypesPL.sublist(TpetraGmresSstep_name);
1062  solverPL = Teuchos::rcp( &tpetraGmresSstepPL, false );
1063  }
1064  // Create the solver, always
1065  iterativeSolver = rcp(new Thyra::BelosTpetraGmresSstep<Scalar,MV_t,LO_t>());
1066  // Set the Problem & PL
1067  iterativeSolver->setProblem( lp );
1068  iterativeSolver->setParameters( solverPL );
1069  break;
1070  }
1071 #endif
1072  default:
1073  {
1075  }
1076  }
1077 
1078  //
1079  // Initialize the LOWS object
1080  //
1081 
1082  belosOp->initialize(
1083  lp, solverPL, iterativeSolver,
1084  fwdOpSrc, prec, myPrec.get()==NULL, approxFwdOpSrc,
1085  supportSolveUse, convergenceTestFrequency_
1086  );
1087  belosOp->setOStream(out);
1088  belosOp->setVerbLevel(verbLevel);
1089 #ifdef TEUCHOS_DEBUG
1090  if(paramList_.get()) {
1091  // Make sure we read the list correctly
1092  paramList_->validateParameters(*this->getValidParameters(),1); // Validate 0th and 1st level deep
1093  }
1094 #endif
1095  if(out.get() && static_cast<int>(verbLevel) > static_cast<int>(Teuchos::VERB_LOW))
1096  *out << "\nLeaving Thyra::BelosLinearOpWithSolveFactory<"<<ST::name()<<">::initializeOpImpl(...) ...\n";
1097 
1098 }
1099 
1100 
1101 } // namespace Thyra
1102 
1103 
1104 #endif // THYRA_BELOS_LINEAR_OP_WITH_SOLVE_FACTORY_HPP
Teuchos::RCP< const Teuchos::ParameterList > getValidParameters() const
void uninitializeOp(LinearOpWithSolveBase< Scalar > *Op, Teuchos::RCP< const LinearOpSourceBase< Scalar > > *fwdOpSrc, Teuchos::RCP< const PreconditionerBase< Scalar > > *prec, Teuchos::RCP< const LinearOpSourceBase< Scalar > > *approxFwdOpSrc, ESupportSolveUse *supportSolveUse) const
RCP< const LinearOpSourceBase< Scalar > > extract_approxFwdOpSrc()
static void addConverter(RCP< const ParameterEntryValidator > validator, RCP< ValidatorXMLConverter > converterToAdd)
void initialize(const RCP< Belos::LinearProblem< Scalar, MV_t, LO_t > > &lp, const RCP< Teuchos::ParameterList > &solverPL, const RCP< Belos::SolverManager< Scalar, MV_t, LO_t > > &iterativeSolver, const RCP< const LinearOpSourceBase< Scalar > > &fwdOpSrc, const RCP< const PreconditionerBase< Scalar > > &prec, const bool isExternalPrec, const RCP< const LinearOpSourceBase< Scalar > > &approxFwdOpSrc, const ESupportSolveUse &supportSolveUse, const int convergenceTestFrequency)
Initializes given precreated solver objects.
Concrete LinearOpWithSolveBase subclass in terms of Belos.
ParameterList & set(std::string const &name, T const &value, std::string const &docString="", RCP< const ParameterEntryValidator > const &validator=null)
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
RCP< const PreconditionerBase< Scalar > > extract_prec()
void initializeAndReuseOp(const Teuchos::RCP< const LinearOpSourceBase< Scalar > > &fwdOpSrc, LinearOpWithSolveBase< Scalar > *Op) const
RCP< ParameterList > sublist(const RCP< ParameterList > &paramList, const std::string &name, bool mustAlreadyExist=false, const std::string &docString="")
T * get() const
static Teuchos::RCP< const Teuchos::ParameterList > generateAndGetValidParameters()
void unsetPreconditionerFactory(Teuchos::RCP< PreconditionerFactoryBase< Scalar > > *precFactory, std::string *precFactoryName)
Thyra specializations of MultiVecTraits and OperatorTraits.
void setParameterList(Teuchos::RCP< Teuchos::ParameterList > const &paramList)
bool isCompatible(const LinearOpSourceBase< Scalar > &fwdOpSrc) const
Teuchos::RCP< const Teuchos::ParameterList > getValidParameters() const override
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
T_To & dyn_cast(T_From &from)
Teuchos::RCP< Teuchos::ParameterList > getNonconstParameterList()
virtual std::string description() const
void initializeOp(const Teuchos::RCP< const LinearOpSourceBase< Scalar > > &fwdOpSrc, LinearOpWithSolveBase< Scalar > *Op, const ESupportSolveUse supportSolveUse) const
void validateParametersAndSetDefaults(ParameterList const &validParamList, int const depth=1000)
void setPreconditionerFactory(const Teuchos::RCP< PreconditionerFactoryBase< Scalar > > &precFactory, const std::string &precFactoryName)
TypeTo as(const TypeFrom &t)
bool supportsPreconditionerInputType(const EPreconditionerInputType precOpType) const
Teuchos::RCP< const Teuchos::ParameterList > getParameterList() const
RCP< const LinearOpSourceBase< Scalar > > extract_fwdOpSrc()
bool nonnull(const boost::shared_ptr< T > &p)
Teuchos::RCP< PreconditionerFactoryBase< Scalar > > getPreconditionerFactory() const
void initializeApproxPreconditionedOp(const Teuchos::RCP< const LinearOpSourceBase< Scalar > > &fwdOpSrc, const Teuchos::RCP< const LinearOpSourceBase< Scalar > > &approxFwdOpSrc, LinearOpWithSolveBase< Scalar > *Op, const ESupportSolveUse supportSolveUse) const
void initializePreconditionedOp(const Teuchos::RCP< const LinearOpSourceBase< Scalar > > &fwdOpSrc, const Teuchos::RCP< const PreconditionerBase< Scalar > > &prec, LinearOpWithSolveBase< Scalar > *Op, const ESupportSolveUse supportSolveUse) const
Teuchos::RCP< LinearOpWithSolveBase< Scalar > > createOp() const
void uninitialize(RCP< Belos::LinearProblem< Scalar, MV_t, LO_t > > *lp=NULL, RCP< Teuchos::ParameterList > *solverPL=NULL, RCP< Belos::SolverManager< Scalar, MV_t, LO_t > > *iterativeSolver=NULL, RCP< const LinearOpSourceBase< Scalar > > *fwdOpSrc=NULL, RCP< const PreconditionerBase< Scalar > > *prec=NULL, bool *isExternalPrec=NULL, RCP< const LinearOpSourceBase< Scalar > > *approxFwdOpSrc=NULL, ESupportSolveUse *supportSolveUse=NULL)
Uninitializes and returns stored quantities.
BelosLinearOpWithSolveFactory()
Construct without preconditioner factory.
void initializeOpImpl(const Teuchos::RCP< const LinearOpSourceBase< Scalar > > &fwdOpSrc, const Teuchos::RCP< const LinearOpSourceBase< Scalar > > &approxFwdOpSrc, const Teuchos::RCP< const PreconditionerBase< Scalar > > &prec, const bool reusePrec, LinearOpWithSolveBase< Scalar > *Op, const ESupportSolveUse supportSolveUse) const
Teuchos::RCP< Teuchos::ParameterList > unsetParameterList()
#define TEUCHOS_TEST_FOR_EXCEPT(throw_exception_test)