87 const Teuchos::RCP<
const LinearOpSourceBase<scalar_type> > &fwdOpSrc,
88 PreconditionerBase<scalar_type> *prec,
89 const ESupportSolveUse
97 TEUCHOS_ASSERT(Teuchos::nonnull(fwdOpSrc));
98 TEUCHOS_ASSERT(this->isCompatible(*fwdOpSrc));
101 Teuchos::Time totalTimer(
"Stratimikos::BelosTpetraPreconditionerFactory");
102 totalTimer.start(
true);
104 const RCP<Teuchos::FancyOStream> out = this->getOStream();
105 const Teuchos::EVerbosityLevel verbLevel = this->getVerbLevel();
106 Teuchos::OSTab tab(out);
107 if (Teuchos::nonnull(out) && Teuchos::includesVerbLevel(verbLevel, Teuchos::VERB_MEDIUM)) {
108 *out <<
"\nEntering Thyra::BelosTpetraPreconditionerFactory::initializePrec(...) ...\n";
113 const RCP<const LinearOpBase<scalar_type> > fwdOp = fwdOpSrc->getOp();
114 TEUCHOS_TEST_FOR_EXCEPT(Teuchos::is_null(fwdOp));
116 typedef typename MatrixType::local_ordinal_type local_ordinal_type;
117 typedef typename MatrixType::global_ordinal_type global_ordinal_type;
118 typedef typename MatrixType::node_type node_type;
120 typedef Tpetra::Operator<scalar_type, local_ordinal_type, global_ordinal_type, node_type> TpetraLinOp;
121 using TpetraExtractHelper = TpetraOperatorVectorExtraction<scalar_type, local_ordinal_type, global_ordinal_type, node_type>;
122 const auto tpetraFwdOp = TpetraExtractHelper::getConstTpetraOperator(fwdOp);
123 TEUCHOS_TEST_FOR_EXCEPT(Teuchos::is_null(tpetraFwdOp));
126 typedef Tpetra::MultiVector<scalar_type, local_ordinal_type, global_ordinal_type, node_type> TpetraMV;
127 typedef Belos::TpetraOperator<scalar_type, local_ordinal_type, global_ordinal_type, node_type> BelosTpOp;
130#ifdef THYRA_BELOS_PREC_ENABLE_HALF_PRECISION
134 typedef typename Teuchos::ScalarTraits<scalar_type>::halfPrecision half_scalar_type;
135 typedef Tpetra::Operator<half_scalar_type, local_ordinal_type, global_ordinal_type, node_type> TpetraLinOpHalf;
136 typedef Tpetra::MultiVector<half_scalar_type, local_ordinal_type, global_ordinal_type, node_type> TpetraMVHalf;
137 typedef Belos::TpetraOperator<half_scalar_type, local_ordinal_type, global_ordinal_type, node_type> BelosTpOpHalf;
143 const Teuchos::Ptr<DefaultPreconditioner<scalar_type> > defaultPrec =
144 Teuchos::ptr(
dynamic_cast<DefaultPreconditioner<scalar_type> *
>(prec));
145 TEUCHOS_TEST_FOR_EXCEPT(Teuchos::is_null(defaultPrec));
148 RCP<Teuchos::ParameterList> innerParamList;
149 if (paramList_.is_null ()) {
150 innerParamList = rcp(
new Teuchos::ParameterList(*getValidParameters()));
153 innerParamList = paramList_;
156 bool useHalfPrecision =
false;
157 if (innerParamList->isParameter(
"half precision"))
158 useHalfPrecision = Teuchos::getParameter<bool>(*innerParamList,
"half precision");
160 const std::string solverType = Teuchos::getParameter<std::string>(*innerParamList,
"BelosPrec Solver Type");
161 const RCP<Teuchos::ParameterList> packageParamList = Teuchos::rcpFromRef(innerParamList->sublist(
"BelosPrec Solver Params"));
164 std::string solverTypeUpper (solverType);
165 std::transform(solverTypeUpper.begin(), solverTypeUpper.end(),solverTypeUpper.begin(), ::toupper);
168 if (Teuchos::nonnull(out) && Teuchos::includesVerbLevel(verbLevel, Teuchos::VERB_MEDIUM)) {
169 *out <<
"\nCreating a new BelosTpetra::Preconditioner object...\n";
171 RCP<LinearOpBase<scalar_type> > thyraPrecOp;
173 if (useHalfPrecision) {
174#ifdef THYRA_BELOS_PREC_ENABLE_HALF_PRECISION
175 if (Teuchos::nonnull(out) && Teuchos::includesVerbLevel(verbLevel, Teuchos::VERB_LOW)) {
176 Teuchos::OSTab(out).o() <<
"> Creating half precision preconditioner\n";
178 const RCP<const MatrixType> tpetraFwdMatrix = Teuchos::rcp_dynamic_cast<const MatrixType>(tpetraFwdOp);
179 TEUCHOS_TEST_FOR_EXCEPT(Teuchos::is_null(tpetraFwdMatrix));
180 auto tpetraFwdMatrixHalf = tpetraFwdMatrix->template convert<half_scalar_type>();
182 RCP<BelosTpLinProbHalf> belosLinProbHalf = rcp(
new BelosTpLinProbHalf());
183 belosLinProbHalf->setOperator(tpetraFwdMatrixHalf);
184 RCP<TpetraLinOpHalf> belosOpRCPHalf = rcp(
new BelosTpOpHalf(belosLinProbHalf, packageParamList, solverType,
true));
185 RCP<TpetraLinOp> wrappedOp = rcp(
new Tpetra::MixedScalarMultiplyOp<scalar_type,half_scalar_type,local_ordinal_type,global_ordinal_type,node_type>(belosOpRCPHalf));
187 thyraPrecOp = Thyra::createLinearOp(wrappedOp);
189 TEUCHOS_TEST_FOR_EXCEPTION(
true, std::logic_error,
"Solver does not have correct precisions enabled to use half precision.")
193 RCP<BelosTpLinProb> belosLinProb = rcp(
new BelosTpLinProb());
194 belosLinProb->setOperator(tpetraFwdOp);
195 RCP<TpetraLinOp> belosOpRCP = rcp(
new BelosTpOp(belosLinProb, packageParamList, solverType,
true));
196 thyraPrecOp = Thyra::createLinearOp(belosOpRCP);
198 defaultPrec->initializeUnspecified(thyraPrecOp);
201 if (Teuchos::nonnull(out) && Teuchos::includesVerbLevel(verbLevel, Teuchos::VERB_LOW)) {
202 *out <<
"\nTotal time in Thyra::BelosTpetraPreconditionerFactory::initializePrec(...) = " << totalTimer.totalElapsedTime() <<
" sec\n";
205 if (Teuchos::nonnull(out) && Teuchos::includesVerbLevel(verbLevel, Teuchos::VERB_MEDIUM)) {
206 *out <<
"\nLeaving Thyra::BelosTpetraPreconditionerFactory::initializePrec(...) ...\n";