10 #ifndef THYRA_MUELU_REFMAXWELL_PRECONDITIONER_FACTORY_DEF_HPP
11 #define THYRA_MUELU_REFMAXWELL_PRECONDITIONER_FACTORY_DEF_HPP
16 #if defined(HAVE_MUELU_STRATIMIKOS) && defined(HAVE_MUELU_THYRA)
19 #if ((defined(HAVE_TPETRA_INST_DOUBLE) && defined(HAVE_TPETRA_INST_FLOAT) && !defined(HAVE_TPETRA_INST_COMPLEX_DOUBLE) && !defined(HAVE_TPETRA_INST_COMPLEX_FLOAT)) || \
20 (!defined(HAVE_TPETRA_INST_DOUBLE) && !defined(HAVE_TPETRA_INST_FLOAT) && defined(HAVE_TPETRA_INST_COMPLEX_DOUBLE) && defined(HAVE_TPETRA_INST_COMPLEX_FLOAT)) || \
21 (defined(HAVE_TPETRA_INST_DOUBLE) && defined(HAVE_TPETRA_INST_FLOAT) && defined(HAVE_TPETRA_INST_COMPLEX_DOUBLE) && defined(HAVE_TPETRA_INST_COMPLEX_FLOAT)))
22 #define MUELU_CAN_USE_MIXED_PRECISION
30 using Teuchos::rcp_const_cast;
31 using Teuchos::rcp_dynamic_cast;
35 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
36 MueLuRefMaxwellPreconditionerFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node>::MueLuRefMaxwellPreconditionerFactory()
37 : paramList_(
rcp(new ParameterList())) {}
41 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
42 bool MueLuRefMaxwellPreconditionerFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node>::isCompatible(
const LinearOpSourceBase<Scalar>& fwdOpSrc)
const {
43 const RCP<const LinearOpBase<Scalar>> fwdOp = fwdOpSrc.getOp();
45 if (Xpetra::ThyraUtils<Scalar, LocalOrdinal, GlobalOrdinal, Node>::isTpetra(fwdOp))
return true;
47 #ifdef HAVE_MUELU_EPETRA
48 if (Xpetra::ThyraUtils<Scalar, LocalOrdinal, GlobalOrdinal, Node>::isEpetra(fwdOp))
return true;
54 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
55 RCP<PreconditionerBase<Scalar>> MueLuRefMaxwellPreconditionerFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node>::createPrec()
const {
59 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
60 void MueLuRefMaxwellPreconditionerFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node>::
61 initializePrec(
const RCP<
const LinearOpSourceBase<Scalar>>& fwdOpSrc, PreconditionerBase<Scalar>* prec,
const ESupportSolveUse supportSolveUse)
const {
64 typedef Xpetra::ThyraUtils<Scalar, LocalOrdinal, GlobalOrdinal, Node> XpThyUtils;
66 typedef Thyra::LinearOpBase<Scalar> ThyLinOpBase;
68 #if defined(MUELU_CAN_USE_MIXED_PRECISION)
69 typedef Xpetra::TpetraHalfPrecisionOperator<Scalar, LocalOrdinal, GlobalOrdinal, Node> XpHalfPrecOp;
71 typedef typename XpHalfPrecOp::HalfScalar HalfScalar;
87 ParameterList paramList = *paramList_;
90 const RCP<const ThyLinOpBase> fwdOp = fwdOpSrc->getOp();
94 bool bIsEpetra = XpThyUtils::isEpetra(fwdOp);
95 bool bIsTpetra = XpThyUtils::isTpetra(fwdOp);
100 RCP<XpMat> A = XpThyUtils::toXpetra(Teuchos::rcp_const_cast<ThyLinOpBase>(fwdOp));
108 RCP<ThyLinOpBase> thyra_precOp = Teuchos::null;
109 thyra_precOp = rcp_dynamic_cast<Thyra::LinearOpBase<Scalar>>(defaultPrec->getNonconstUnspecifiedPrecOp(),
true);
114 const bool startingOver = (thyra_precOp.is_null() || !paramList.isParameter(
"refmaxwell: enable reuse") || !paramList.get<
bool>(
"refmaxwell: enable reuse"));
115 const bool useHalfPrecision = paramList.get<
bool>(
"half precision",
false) && bIsTpetra;
118 if (startingOver ==
true) {
120 std::list<std::string> convertMat = {
121 "Dk_1",
"Dk_2",
"D0",
122 "Mk_one",
"Mk_1_one",
"M1_beta",
"M1_alpha",
123 "invMk_1_invBeta",
"invMk_2_invAlpha",
125 "M1",
"Ms",
"M0inv"};
126 std::list<std::string> convertMV = {
"Coordinates",
"Nullspace"};
127 std::list<std::string> convertXpetra;
128 convertXpetra.insert(convertXpetra.end(), convertMV.begin(), convertMV.end());
129 convertXpetra.insert(convertXpetra.end(), convertMat.begin(), convertMat.end());
130 for (
auto it = convertXpetra.begin(); it != convertXpetra.end(); ++it)
131 Converters<Scalar, LocalOrdinal, GlobalOrdinal, Node>::replaceWithXpetra(paramList, *it);
133 paramList.set<
bool>(
"refmaxwell: use as preconditioner",
true);
134 if (useHalfPrecision) {
135 #if defined(MUELU_CAN_USE_MIXED_PRECISION)
138 RCP<XphMat> halfA = Xpetra::convertToHalfPrecision(A);
139 if (paramList.isType<RCP<XpmMV>>(
"Coordinates")) {
140 RCP<XpmMV> coords = paramList.get<RCP<XpmMV>>(
"Coordinates");
141 paramList.remove(
"Coordinates");
142 RCP<XphmMV> halfCoords = Xpetra::convertToHalfPrecision(coords);
143 paramList.set(
"Coordinates", halfCoords);
145 if (paramList.isType<RCP<XpMV>>(
"Nullspace")) {
146 RCP<XpMV> nullspace = paramList.get<RCP<XpMV>>(
"Nullspace");
147 paramList.remove(
"Nullspace");
148 RCP<XphMV> halfNullspace = Xpetra::convertToHalfPrecision(nullspace);
149 paramList.set(
"Nullspace", halfNullspace);
151 for (
auto it = convertMat.begin(); it != convertMat.end(); ++it) {
152 if (paramList.isType<RCP<XpMat>>(*it)) {
153 RCP<XpMat> M = paramList.get<RCP<XpMat>>(*it);
154 paramList.remove(*it);
155 RCP<XphMat> halfM = Xpetra::convertToHalfPrecision(M);
156 paramList.set(*it, halfM);
162 xpPrecOp =
rcp(
new XpHalfPrecOp(halfPrec));
169 xpPrecOp = rcp_dynamic_cast<XpOp>(preconditioner);
174 RCP<ThyXpOp> thyXpOp = rcp_dynamic_cast<ThyXpOp>(thyra_precOp,
true);
175 RCP<XpOp> xpOp = thyXpOp->getXpetraOperator();
176 #if defined(MUELU_CAN_USE_MIXED_PRECISION)
177 RCP<XpHalfPrecOp> xpHalfPrecOp = rcp_dynamic_cast<XpHalfPrecOp>(xpOp);
178 if (!xpHalfPrecOp.is_null()) {
180 RCP<XphMat> halfA = Xpetra::convertToHalfPrecision(A);
181 preconditioner->resetMatrix(halfA);
182 xpPrecOp = rcp_dynamic_cast<XpOp>(preconditioner);
188 xpPrecOp = rcp_dynamic_cast<XpOp>(preconditioner);
193 RCP<const VectorSpaceBase<Scalar>> thyraRangeSpace = Xpetra::ThyraUtils<Scalar, LocalOrdinal, GlobalOrdinal, Node>::toThyra(xpPrecOp->getRangeMap());
194 RCP<const VectorSpaceBase<Scalar>> thyraDomainSpace = Xpetra::ThyraUtils<Scalar, LocalOrdinal, GlobalOrdinal, Node>::toThyra(xpPrecOp->getDomainMap());
196 RCP<ThyLinOpBase> thyraPrecOp = Thyra::xpetraLinearOp<Scalar, LocalOrdinal, GlobalOrdinal, Node>(thyraRangeSpace, thyraDomainSpace, xpPrecOp);
199 defaultPrec->initializeUnspecified(thyraPrecOp);
202 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
203 void MueLuRefMaxwellPreconditionerFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node>::
204 uninitializePrec(PreconditionerBase<Scalar>* prec, RCP<
const LinearOpSourceBase<Scalar>>* fwdOp, ESupportSolveUse* supportSolveUse)
const {
213 *fwdOp = Teuchos::null;
216 if (supportSolveUse) {
218 *supportSolveUse = Thyra::SUPPORT_SOLVE_UNSPECIFIED;
221 defaultPrec->uninitialize();
225 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
226 void MueLuRefMaxwellPreconditionerFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node>::setParameterList(RCP<ParameterList>
const& paramList) {
228 paramList_ = paramList;
231 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
232 RCP<ParameterList> MueLuRefMaxwellPreconditionerFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node>::getNonconstParameterList() {
236 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
237 RCP<ParameterList> MueLuRefMaxwellPreconditionerFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node>::unsetParameterList() {
238 RCP<ParameterList> savedParamList = paramList_;
239 paramList_ = Teuchos::null;
240 return savedParamList;
243 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
244 RCP<const ParameterList> MueLuRefMaxwellPreconditionerFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node>::getParameterList()
const {
248 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
249 RCP<const ParameterList> MueLuRefMaxwellPreconditionerFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node>::getValidParameters()
const {
250 static RCP<const ParameterList> validPL;
253 validPL =
rcp(
new ParameterList());
259 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
260 std::string MueLuRefMaxwellPreconditionerFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node>::description()
const {
261 return "Thyra::MueLuRefMaxwellPreconditionerFactory";
265 #endif // HAVE_MUELU_STRATIMIKOS
267 #endif // ifdef THYRA_MUELU_REFMAXWELL_PRECONDITIONER_FACTORY_DEF_HPP
bool nonnull(const std::shared_ptr< T > &p)
bool is_null(const std::shared_ptr< T > &p)
Preconditioner (wrapped as a Xpetra::Operator) for Maxwell's equations in curl-curl form...
static RCP< Time > getNewTimer(const std::string &name)
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
void resetMatrix(Teuchos::RCP< Matrix > SM_Matrix_new, bool ComputePrec=true)
Reset system matrix.
Concrete Thyra::LinearOpBase subclass for Xpetra::Operator.
#define TEUCHOS_ASSERT(assertion_test)
#define TEUCHOS_TEST_FOR_EXCEPT(throw_exception_test)