119 const Teuchos::RCP<
const LinearOpSourceBase<scalar_type> > &fwdOpSrc,
120 PreconditionerBase<scalar_type> *prec,
121 const ESupportSolveUse
129 TEUCHOS_ASSERT(Teuchos::nonnull(fwdOpSrc));
130 TEUCHOS_ASSERT(this->isCompatible(*fwdOpSrc));
131 TEUCHOS_ASSERT(prec);
133 Teuchos::Time totalTimer(
""), timer(
"");
134 totalTimer.start(
true);
136 const RCP<Teuchos::FancyOStream> out = this->getOStream();
137 const Teuchos::EVerbosityLevel verbLevel = this->getVerbLevel();
138 Teuchos::OSTab tab(out);
139 if (Teuchos::nonnull(out) && Teuchos::includesVerbLevel(verbLevel, Teuchos::VERB_MEDIUM)) {
140 *out <<
"\nEntering Thyra::BelosTpetraPreconditionerFactory::initializePrec(...) ...\n";
145 const RCP<const LinearOpBase<scalar_type> > fwdOp = fwdOpSrc->getOp();
146 TEUCHOS_TEST_FOR_EXCEPT(Teuchos::is_null(fwdOp));
148 typedef typename MatrixType::local_ordinal_type local_ordinal_type;
149 typedef typename MatrixType::global_ordinal_type global_ordinal_type;
150 typedef typename MatrixType::node_type node_type;
152 typedef Tpetra::Operator<scalar_type, local_ordinal_type, global_ordinal_type, node_type> TpetraLinOp;
153 using TpetraExtractHelper = TpetraOperatorVectorExtraction<scalar_type, local_ordinal_type, global_ordinal_type, node_type>;
154 const auto tpetraFwdOp = TpetraExtractHelper::getConstTpetraOperator(fwdOp);
155 TEUCHOS_TEST_FOR_EXCEPT(Teuchos::is_null(tpetraFwdOp));
158 typedef Tpetra::MultiVector<scalar_type, local_ordinal_type, global_ordinal_type, node_type> TpetraMV;
159 typedef Belos::TpetraOperator<scalar_type, local_ordinal_type, global_ordinal_type, node_type> BelosTpOp;
162#ifdef THYRA_BELOS_PREC_ENABLE_HALF_PRECISION
166 typedef typename Teuchos::ScalarTraits<scalar_type>::halfPrecision half_scalar_type;
167 typedef Tpetra::Operator<half_scalar_type, local_ordinal_type, global_ordinal_type, node_type> TpetraLinOpHalf;
168 typedef Tpetra::MultiVector<half_scalar_type, local_ordinal_type, global_ordinal_type, node_type> TpetraMVHalf;
169 typedef Belos::TpetraOperator<half_scalar_type, local_ordinal_type, global_ordinal_type, node_type> BelosTpOpHalf;
175 const Teuchos::Ptr<DefaultPreconditioner<scalar_type> > defaultPrec =
176 Teuchos::ptr(
dynamic_cast<DefaultPreconditioner<scalar_type> *
>(prec));
177 TEUCHOS_TEST_FOR_EXCEPT(Teuchos::is_null(defaultPrec));
180 RCP<Teuchos::ParameterList> innerParamList;
181 if (paramList_.is_null ()) {
182 innerParamList = rcp(
new Teuchos::ParameterList(*getValidParameters()));
185 innerParamList = paramList_;
188 bool useHalfPrecision =
false;
189 if (innerParamList->isParameter(
"half precision"))
190 useHalfPrecision = Teuchos::getParameter<bool>(*innerParamList,
"half precision");
192 const std::string solverType = Teuchos::getParameter<std::string>(*innerParamList,
"BelosPrec Solver Type");
193 const RCP<Teuchos::ParameterList> packageParamList = Teuchos::rcpFromRef(innerParamList->sublist(
"BelosPrec Solver Params"));
196 std::string solverTypeUpper (solverType);
197 std::transform(solverTypeUpper.begin(), solverTypeUpper.end(),solverTypeUpper.begin(), ::toupper);
200 if (Teuchos::nonnull(out) && Teuchos::includesVerbLevel(verbLevel, Teuchos::VERB_MEDIUM)) {
201 *out <<
"\nCreating a new BelosTpetra::Preconditioner object...\n";
203 RCP<LinearOpBase<scalar_type> > thyraPrecOp;
205 if (useHalfPrecision) {
206#ifdef THYRA_BELOS_PREC_ENABLE_HALF_PRECISION
207 if (Teuchos::nonnull(out) && Teuchos::includesVerbLevel(verbLevel, Teuchos::VERB_LOW)) {
208 Teuchos::OSTab(out).o() <<
"> Creating half precision preconditioner\n";
210 const RCP<const MatrixType> tpetraFwdMatrix = Teuchos::rcp_dynamic_cast<const MatrixType>(tpetraFwdOp);
211 TEUCHOS_TEST_FOR_EXCEPT(Teuchos::is_null(tpetraFwdMatrix));
212 auto tpetraFwdMatrixHalf = tpetraFwdMatrix->template convert<half_scalar_type>();
214 RCP<BelosTpLinProbHalf> belosLinProbHalf = rcp(
new BelosTpLinProbHalf());
215 belosLinProbHalf->setOperator(tpetraFwdMatrixHalf);
216 RCP<TpetraLinOpHalf> belosOpRCPHalf = rcp(
new BelosTpOpHalf(belosLinProbHalf, packageParamList, solverType,
true));
217 RCP<TpetraLinOp> wrappedOp = rcp(
new Tpetra::MixedScalarMultiplyOp<scalar_type,half_scalar_type,local_ordinal_type,global_ordinal_type,node_type>(belosOpRCPHalf));
219 thyraPrecOp = Thyra::createLinearOp(wrappedOp);
221 TEUCHOS_TEST_FOR_EXCEPTION(
true, std::logic_error,
"Solver does not have correct precisions enabled to use half precision.")
225 RCP<BelosTpLinProb> belosLinProb = rcp(
new BelosTpLinProb());
226 belosLinProb->setOperator(tpetraFwdOp);
227 RCP<TpetraLinOp> belosOpRCP = rcp(
new BelosTpOp(belosLinProb, packageParamList, solverType,
true));
228 thyraPrecOp = Thyra::createLinearOp(belosOpRCP);
230 defaultPrec->initializeUnspecified(thyraPrecOp);
233 if (Teuchos::nonnull(out) && Teuchos::includesVerbLevel(verbLevel, Teuchos::VERB_LOW)) {
234 *out <<
"\nTotal time in Thyra::BelosTpetraPreconditionerFactory::initializePrec(...) = " << totalTimer.totalElapsedTime() <<
" sec\n";
237 if (Teuchos::nonnull(out) && Teuchos::includesVerbLevel(verbLevel, Teuchos::VERB_MEDIUM)) {
238 *out <<
"\nLeaving Thyra::BelosTpetraPreconditionerFactory::initializePrec(...) ...\n";