46#ifndef THYRA_MUELU_REFMAXWELL_PRECONDITIONER_FACTORY_DEF_HPP
47#define THYRA_MUELU_REFMAXWELL_PRECONDITIONER_FACTORY_DEF_HPP
52#if defined(HAVE_MUELU_STRATIMIKOS) && defined(HAVE_MUELU_THYRA)
55#if((defined(HAVE_TPETRA_INST_DOUBLE) && defined(HAVE_TPETRA_INST_FLOAT) && !defined(HAVE_TPETRA_INST_COMPLEX_DOUBLE) && !defined(HAVE_TPETRA_INST_COMPLEX_FLOAT)) || \
56 (!defined(HAVE_TPETRA_INST_DOUBLE) && !defined(HAVE_TPETRA_INST_FLOAT) && defined(HAVE_TPETRA_INST_COMPLEX_DOUBLE) && defined(HAVE_TPETRA_INST_COMPLEX_FLOAT)) || \
57 (defined(HAVE_TPETRA_INST_DOUBLE) && defined(HAVE_TPETRA_INST_FLOAT) && defined(HAVE_TPETRA_INST_COMPLEX_DOUBLE) && defined(HAVE_TPETRA_INST_COMPLEX_FLOAT)))
58# define MUELU_CAN_USE_MIXED_PRECISION
66 using Teuchos::ParameterList;
67 using Teuchos::rcp_dynamic_cast;
68 using Teuchos::rcp_const_cast;
72 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
73 MueLuRefMaxwellPreconditionerFactory<Scalar,LocalOrdinal,GlobalOrdinal,Node>::MueLuRefMaxwellPreconditionerFactory() :
74 paramList_(rcp(new ParameterList()))
79 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
80 bool MueLuRefMaxwellPreconditionerFactory<Scalar,LocalOrdinal,GlobalOrdinal,Node>::isCompatible(
const LinearOpSourceBase<Scalar>& fwdOpSrc)
const {
81 const RCP<const LinearOpBase<Scalar> > fwdOp = fwdOpSrc.getOp();
83 if (Xpetra::ThyraUtils<Scalar,LocalOrdinal,GlobalOrdinal,Node>::isTpetra(fwdOp))
return true;
85#ifdef HAVE_MUELU_EPETRA
86 if (Xpetra::ThyraUtils<Scalar,LocalOrdinal,GlobalOrdinal,Node>::isEpetra(fwdOp))
return true;
93 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
94 RCP<PreconditionerBase<Scalar> > MueLuRefMaxwellPreconditionerFactory<Scalar,LocalOrdinal,GlobalOrdinal,Node>::createPrec()
const {
95 return Teuchos::rcp(
new DefaultPreconditioner<Scalar>);
98 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
99 void MueLuRefMaxwellPreconditionerFactory<Scalar,LocalOrdinal,GlobalOrdinal,Node>::
100 initializePrec(
const RCP<
const LinearOpSourceBase<Scalar> >& fwdOpSrc, PreconditionerBase<Scalar>* prec,
const ESupportSolveUse supportSolveUse)
const {
103 typedef Xpetra::Operator<Scalar, LocalOrdinal, GlobalOrdinal, Node> XpOp;
104 typedef Xpetra::ThyraUtils<Scalar,LocalOrdinal,GlobalOrdinal,Node> XpThyUtils;
105 typedef Xpetra::Matrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> XpMat;
106 typedef Thyra::LinearOpBase<Scalar> ThyLinOpBase;
108#if defined(MUELU_CAN_USE_MIXED_PRECISION)
109 typedef Xpetra::TpetraHalfPrecisionOperator<Scalar,LocalOrdinal,GlobalOrdinal,Node> XpHalfPrecOp;
110 typedef Xpetra::MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node> XpMV;
111 typedef typename XpHalfPrecOp::HalfScalar HalfScalar;
112 typedef typename Teuchos::ScalarTraits<Scalar>::magnitudeType Magnitude;
113 typedef typename Teuchos::ScalarTraits<Magnitude>::halfPrecision HalfMagnitude;
114 typedef Xpetra::MultiVector<HalfScalar,LocalOrdinal,GlobalOrdinal,Node> XphMV;
115 typedef Xpetra::MultiVector<Magnitude,LocalOrdinal,GlobalOrdinal,Node > XpmMV;
116 typedef Xpetra::MultiVector<HalfMagnitude,LocalOrdinal,GlobalOrdinal,Node > XphmMV;
117 typedef Xpetra::Matrix<HalfScalar,LocalOrdinal,GlobalOrdinal,Node> XphMat;
119 Teuchos::TimeMonitor tM(*Teuchos::TimeMonitor::getNewTimer(std::string(
"ThyraMueLuRefMaxwell::initializePrec")));
122 TEUCHOS_ASSERT(Teuchos::nonnull(fwdOpSrc));
123 TEUCHOS_ASSERT(this->isCompatible(*fwdOpSrc));
124 TEUCHOS_ASSERT(prec);
127 ParameterList paramList = *paramList_;
130 const RCP<const ThyLinOpBase> fwdOp = fwdOpSrc->getOp();
131 TEUCHOS_TEST_FOR_EXCEPT(Teuchos::is_null(fwdOp));
134 bool bIsEpetra = XpThyUtils::isEpetra(fwdOp);
135 bool bIsTpetra = XpThyUtils::isTpetra(fwdOp);
136 TEUCHOS_TEST_FOR_EXCEPT((bIsEpetra ==
true && bIsTpetra ==
true));
140 RCP<XpMat> A = XpThyUtils::toXpetra(Teuchos::rcp_const_cast<ThyLinOpBase>(fwdOp));
141 TEUCHOS_TEST_FOR_EXCEPT(Teuchos::is_null(A));
144 const Teuchos::Ptr<DefaultPreconditioner<Scalar> > defaultPrec = Teuchos::ptr(
dynamic_cast<DefaultPreconditioner<Scalar> *
>(prec));
145 TEUCHOS_TEST_FOR_EXCEPT(Teuchos::is_null(defaultPrec));
148 RCP<ThyLinOpBase> thyra_precOp = Teuchos::null;
149 thyra_precOp = rcp_dynamic_cast<Thyra::LinearOpBase<Scalar> >(defaultPrec->getNonconstUnspecifiedPrecOp(),
true);
154 const bool startingOver = (thyra_precOp.is_null() || !paramList.isParameter(
"refmaxwell: enable reuse") || !paramList.get<
bool>(
"refmaxwell: enable reuse"));
155 const bool useHalfPrecision = paramList.get<
bool>(
"half precision",
false) && bIsTpetra;
158 if (startingOver ==
true) {
161 std::list<std::string> convertXpetra = {
"Coordinates",
"Nullspace",
"M1",
"Ms",
"D0",
"M0inv"};
162 for (
auto it = convertXpetra.begin(); it != convertXpetra.end(); ++it)
163 Converters<Scalar,LocalOrdinal,GlobalOrdinal,Node>::replaceWithXpetra(paramList,*it);
165 paramList.set<
bool>(
"refmaxwell: use as preconditioner",
true);
166 if (useHalfPrecision) {
167#if defined(MUELU_CAN_USE_MIXED_PRECISION)
170 RCP<XphMat> halfA = Xpetra::convertToHalfPrecision(A);
171 if (paramList.isType<RCP<XpmMV> >(
"Coordinates")) {
172 RCP<XpmMV> coords = paramList.get<RCP<XpmMV> >(
"Coordinates");
173 paramList.remove(
"Coordinates");
174 RCP<XphmMV> halfCoords = Xpetra::convertToHalfPrecision(coords);
175 paramList.set(
"Coordinates",halfCoords);
177 if (paramList.isType<RCP<XpMV> >(
"Nullspace")) {
178 RCP<XpMV> nullspace = paramList.get<RCP<XpMV> >(
"Nullspace");
179 paramList.remove(
"Nullspace");
180 RCP<XphMV> halfNullspace = Xpetra::convertToHalfPrecision(nullspace);
181 paramList.set(
"Nullspace",halfNullspace);
183 std::list<std::string> convertMat = {
"M1",
"Ms",
"D0",
"M0inv"};
184 for (
auto it = convertMat.begin(); it != convertMat.end(); ++it) {
185 if (paramList.isType<RCP<XpMat> >(*it)) {
186 RCP<XpMat> M = paramList.get<RCP<XpMat> >(*it);
187 paramList.remove(*it);
188 RCP<XphMat> halfM = Xpetra::convertToHalfPrecision(M);
189 paramList.set(*it,halfM);
195 xpPrecOp = rcp(
new XpHalfPrecOp(halfPrec));
197 TEUCHOS_TEST_FOR_EXCEPT(
true);
203 xpPrecOp = rcp_dynamic_cast<XpOp>(preconditioner);
208 RCP<ThyXpOp> thyXpOp = rcp_dynamic_cast<ThyXpOp>(thyra_precOp,
true);
209 RCP<XpOp> xpOp = thyXpOp->getXpetraOperator();
210#if defined(MUELU_CAN_USE_MIXED_PRECISION)
211 RCP<XpHalfPrecOp> xpHalfPrecOp = rcp_dynamic_cast<XpHalfPrecOp>(xpOp);
212 if (!xpHalfPrecOp.is_null()) {
213 RCP<MueLu::RefMaxwell<HalfScalar,LocalOrdinal,GlobalOrdinal,Node> > preconditioner = rcp_dynamic_cast<MueLu::RefMaxwell<HalfScalar,LocalOrdinal,GlobalOrdinal,Node>>(xpHalfPrecOp->GetHalfPrecisionOperator(),
true);
214 RCP<XphMat> halfA = Xpetra::convertToHalfPrecision(A);
215 preconditioner->resetMatrix(halfA);
216 xpPrecOp = rcp_dynamic_cast<XpOp>(preconditioner);
220 RCP<MueLu::RefMaxwell<Scalar,LocalOrdinal,GlobalOrdinal,Node> > preconditioner = rcp_dynamic_cast<MueLu::RefMaxwell<Scalar,LocalOrdinal,GlobalOrdinal,Node>>(xpOp,
true);
221 preconditioner->resetMatrix(A);
222 xpPrecOp = rcp_dynamic_cast<XpOp>(preconditioner);
227 RCP<const VectorSpaceBase<Scalar> > thyraRangeSpace = Xpetra::ThyraUtils<Scalar,LocalOrdinal,GlobalOrdinal,Node>::toThyra(xpPrecOp->getRangeMap());
228 RCP<const VectorSpaceBase<Scalar> > thyraDomainSpace = Xpetra::ThyraUtils<Scalar,LocalOrdinal,GlobalOrdinal,Node>::toThyra(xpPrecOp->getDomainMap());
231 TEUCHOS_TEST_FOR_EXCEPT(Teuchos::is_null(thyraPrecOp));
233 defaultPrec->initializeUnspecified(thyraPrecOp);
237 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
238 void MueLuRefMaxwellPreconditionerFactory<Scalar,LocalOrdinal,GlobalOrdinal,Node>::
239 uninitializePrec(PreconditionerBase<Scalar>* prec, RCP<
const LinearOpSourceBase<Scalar> >* fwdOp, ESupportSolveUse* supportSolveUse)
const {
240 TEUCHOS_ASSERT(prec);
243 const Teuchos::Ptr<DefaultPreconditioner<Scalar> > defaultPrec = Teuchos::ptr(
dynamic_cast<DefaultPreconditioner<Scalar> *
>(prec));
244 TEUCHOS_TEST_FOR_EXCEPT(Teuchos::is_null(defaultPrec));
248 *fwdOp = Teuchos::null;
251 if (supportSolveUse) {
253 *supportSolveUse = Thyra::SUPPORT_SOLVE_UNSPECIFIED;
256 defaultPrec->uninitialize();
261 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
262 void MueLuRefMaxwellPreconditionerFactory<Scalar,LocalOrdinal,GlobalOrdinal,Node>::setParameterList(RCP<ParameterList>
const& paramList) {
263 TEUCHOS_TEST_FOR_EXCEPT(Teuchos::is_null(paramList));
264 paramList_ = paramList;
267 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
268 RCP<ParameterList> MueLuRefMaxwellPreconditionerFactory<Scalar,LocalOrdinal,GlobalOrdinal,Node>::getNonconstParameterList() {
272 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
273 RCP<ParameterList> MueLuRefMaxwellPreconditionerFactory<Scalar,LocalOrdinal,GlobalOrdinal,Node>::unsetParameterList() {
274 RCP<ParameterList> savedParamList = paramList_;
275 paramList_ = Teuchos::null;
276 return savedParamList;
279 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
280 RCP<const ParameterList> MueLuRefMaxwellPreconditionerFactory<Scalar,LocalOrdinal,GlobalOrdinal,Node>::getParameterList()
const {
284 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
285 RCP<const ParameterList> MueLuRefMaxwellPreconditionerFactory<Scalar,LocalOrdinal,GlobalOrdinal,Node>::getValidParameters()
const {
286 static RCP<const ParameterList> validPL;
288 if (Teuchos::is_null(validPL))
289 validPL = rcp(
new ParameterList());
295 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
296 std::string MueLuRefMaxwellPreconditionerFactory<Scalar,LocalOrdinal,GlobalOrdinal,Node>::description()
const {
297 return "Thyra::MueLuRefMaxwellPreconditionerFactory";
Preconditioner (wrapped as a Xpetra::Operator) for Maxwell's equations in curl-curl form.
Concrete Thyra::LinearOpBase subclass for Xpetra::Operator.
RCP< XpetraLinearOp< Scalar, LocalOrdinal, GlobalOrdinal, Node > > xpetraLinearOp(const RCP< const VectorSpaceBase< Scalar > > &rangeSpace, const RCP< const VectorSpaceBase< Scalar > > &domainSpace, const RCP< Xpetra::Operator< Scalar, LocalOrdinal, GlobalOrdinal, Node > > &xpetraOperator)
Nonmmeber constructor for XpetraLinearOp.