10 #include "NS/Teko_InvLSCStrategy.hpp"
12 #include "Thyra_DefaultDiagonalLinearOp.hpp"
13 #include "Thyra_VectorStdOps.hpp"
15 #include "Teko_ConfigDefs.hpp"
17 #ifdef TEKO_HAVE_EPETRA
18 #include "Thyra_EpetraThyraWrappers.hpp"
19 #include "Thyra_get_Epetra_Operator.hpp"
20 #include "Thyra_EpetraLinearOp.hpp"
21 #include "Epetra_Vector.h"
22 #include "Epetra_Map.h"
23 #include "EpetraExt_RowMatrixOut.h"
24 #include "EpetraExt_MultiVectorOut.h"
25 #include "EpetraExt_VectorOut.h"
26 #include "Teko_EpetraHelpers.hpp"
27 #include "Teko_EpetraOperatorWrapper.hpp"
30 #include "Teuchos_Time.hpp"
31 #include "Teuchos_TimeMonitor.hpp"
35 #include "NS/Teko_LSCPreconditionerFactory.hpp"
37 #include "Teko_TpetraHelpers.hpp"
39 #include "Thyra_TpetraLinearOp.hpp"
42 using Teuchos::rcp_const_cast;
43 using Teuchos::rcp_dynamic_cast;
54 InvLSCStrategy::InvLSCStrategy()
55 : massMatrix_(Teuchos::null),
56 invFactoryF_(Teuchos::null),
57 invFactoryS_(Teuchos::null),
59 rowZeroingNeeded_(false),
66 assumeStable_(false) {}
68 InvLSCStrategy::InvLSCStrategy(
const Teuchos::RCP<InverseFactory>& factory,
bool rzn)
69 : massMatrix_(Teuchos::null),
70 invFactoryF_(factory),
71 invFactoryS_(factory),
73 rowZeroingNeeded_(rzn),
80 assumeStable_(false) {}
82 InvLSCStrategy::InvLSCStrategy(
const Teuchos::RCP<InverseFactory>& invFactF,
83 const Teuchos::RCP<InverseFactory>& invFactS,
bool rzn)
84 : massMatrix_(Teuchos::null),
85 invFactoryF_(invFactF),
86 invFactoryS_(invFactS),
88 rowZeroingNeeded_(rzn),
95 assumeStable_(false) {}
97 InvLSCStrategy::InvLSCStrategy(
const Teuchos::RCP<InverseFactory>& factory, LinearOp& mass,
100 invFactoryF_(factory),
101 invFactoryS_(factory),
103 rowZeroingNeeded_(rzn),
108 scaleType_(Diagonal),
110 assumeStable_(false) {}
112 InvLSCStrategy::InvLSCStrategy(
const Teuchos::RCP<InverseFactory>& invFactF,
113 const Teuchos::RCP<InverseFactory>& invFactS, LinearOp& mass,
116 invFactoryF_(invFactF),
117 invFactoryS_(invFactS),
119 rowZeroingNeeded_(rzn),
124 scaleType_(Diagonal),
126 assumeStable_(false) {}
131 Teko_DEBUG_SCOPE(
"InvLSCStrategy::buildState", 10);
134 TEUCHOS_ASSERT(lscState != 0);
138 Teko_DEBUG_EXPR(Teuchos::Time timer(
""));
142 Teko_DEBUG_SCOPE(
"LSC::buildState constructing operators", 1);
143 Teko_DEBUG_EXPR(timer.start(
true));
145 initializeState(A, lscState);
147 Teko_DEBUG_EXPR(timer.stop());
148 Teko_DEBUG_MSG(
"LSC::buildState BuildOpsTime = " << timer.totalElapsedTime(), 1);
153 Teko_DEBUG_SCOPE(
"LSC::buildState calculating inverses", 1);
154 Teko_DEBUG_EXPR(timer.start(
true));
156 computeInverses(A, lscState);
158 Teko_DEBUG_EXPR(timer.stop());
159 Teko_DEBUG_MSG(
"LSC::buildState BuildInvTime = " << timer.totalElapsedTime(), 1);
165 LinearOp InvLSCStrategy::getInvBQBt(
const BlockedLinearOp& ,
170 LinearOp InvLSCStrategy::getInvBHBt(
const BlockedLinearOp& ,
175 LinearOp InvLSCStrategy::getInvF(
const BlockedLinearOp& ,
180 LinearOp InvLSCStrategy::getOuterStabilization(
const BlockedLinearOp& ,
183 TEUCHOS_ASSERT(lscState != 0);
186 return lscState->
aiD_;
189 LinearOp InvLSCStrategy::getInvMass(
const BlockedLinearOp& ,
192 TEUCHOS_ASSERT(lscState != 0);
198 LinearOp InvLSCStrategy::getHScaling(
const BlockedLinearOp& A,
200 if (hScaling_ != Teuchos::null)
return hScaling_;
201 return getInvMass(A, state);
205 void InvLSCStrategy::initializeState(
const BlockedLinearOp& A,
LSCPrecondState* state)
const {
206 Teko_DEBUG_SCOPE(
"InvLSCStrategy::initializeState", 10);
208 const LinearOp F = getBlock(0, 0, A);
209 const LinearOp Bt = getBlock(0, 1, A);
210 const LinearOp B = getBlock(1, 0, A);
211 const LinearOp C = getBlock(1, 1, A);
214 LinearOp G = isSymmetric_ ? Bt : adjoint(D);
216 bool isStabilized = assumeStable_ ?
false : (not isZeroOp(C));
224 if (massMatrix_ == Teuchos::null) {
226 "LSC::initializeState Build Scaling <F> type \"" << getDiagonalName(scaleType_) <<
"\"", 1);
227 state->
invMass_ = getInvDiagonalOp(F, scaleType_);
228 }
else if (state->
invMass_ == Teuchos::null) {
230 "LSC::initializeState Build Scaling <mass> type \"" << getDiagonalName(scaleType_) <<
"\"",
232 state->
invMass_ = getInvDiagonalOp(massMatrix_, scaleType_);
238 Teko_DEBUG_MSG(
"Computed BQBt", 10);
241 if (wScaling_ != Teuchos::null && hScaling_ == Teuchos::null) {
243 RCP<const Thyra::VectorBase<double> > w = wScaling_->col(0);
244 RCP<const Thyra::VectorBase<double> > iQu =
245 rcp_dynamic_cast<
const Thyra::DiagonalLinearOpBase<double> >(state->
invMass_)->getDiag();
246 RCP<Thyra::VectorBase<double> > h = Thyra::createMember(iQu->space());
248 Thyra::put_scalar(0.0, h.ptr());
249 Thyra::ele_wise_prod(1.0, *w, *iQu, h.ptr());
250 hScaling_ = Teuchos::rcp(
new Thyra::DefaultDiagonalLinearOp<double>(h));
253 LinearOp H = hScaling_;
254 if (H == Teuchos::null && not isSymmetric_) H = state->
invMass_;
257 if (H == Teuchos::null)
260 RCP<Teuchos::Time> time =
261 Teuchos::TimeMonitor::getNewTimer(
"InvLSCStrategy::initializeState Build BHBt");
262 Teuchos::TimeMonitor timer(*time);
265 state->
BHBt_ = explicitMultiply(D, H, G, state->
BHBt_);
269 if (not isStabilized) {
274 state->
aiD_ = Teuchos::null;
283 if (!Teko::TpetraHelpers::isTpetraLinearOp(F)) {
284 #ifdef TEKO_HAVE_EPETRA
285 const RCP<const Epetra_Operator> epF = Thyra::get_Epetra_Operator(*F);
286 if (epF != Teuchos::null && rowZeroingNeeded_) {
288 const RCP<const Epetra_CrsMatrix> crsF = rcp_dynamic_cast<
const Epetra_CrsMatrix>(epF);
291 if (crsF != Teuchos::null) {
292 std::vector<int> zeroIndices;
295 Teko::Epetra::identityRowIndices(crsF->RowMap(), *crsF, zeroIndices);
302 throw std::logic_error(
303 "InvLSCStrategy::initializeState is trying to use "
304 "Epetra code, but TEKO is not built with Epetra!");
309 RCP<const Tpetra::CrsMatrix<ST, LO, GO, NT> > crsF =
310 Teko::TpetraHelpers::getTpetraCrsMatrix(F, &scalar, &transp);
312 std::vector<GO> zeroIndices;
315 Teko::TpetraHelpers::identityRowIndices(*crsF->getRowMap(), *crsF, zeroIndices);
318 modF = Thyra::tpetraLinearOp<ST, LO, GO, NT>(
319 Thyra::tpetraVectorSpace<ST, LO, GO, NT>(crsF->getDomainMap()),
320 Thyra::tpetraVectorSpace<ST, LO, GO, NT>(crsF->getRangeMap()),
325 Teko_DEBUG_MSG(
"Calculating gamma", 10);
326 LinearOp iQuF = multiply(state->
invMass_, modF);
329 Teko::LinearOp stabMatrix;
330 state->
gamma_ = std::fabs(Teko::computeSpectralRad(iQuF, 5e-2,
false, eigSolveParam_)) / 3.0;
331 Teko_DEBUG_MSG(
"Calculated gamma", 10);
332 if (userPresStabMat_ != Teuchos::null) {
333 Teko::LinearOp invDGl = Teko::getInvDiagonalOp(userPresStabMat_);
334 Teko::LinearOp gammaOp = multiply(invDGl, C);
335 state->
gamma_ *= std::fabs(Teko::computeSpectralRad(gammaOp, 5e-2,
false, eigSolveParam_));
336 stabMatrix = userPresStabMat_;
342 LinearOp invDiagF = getInvDiagonalOp(F);
343 Teko::ModifiableLinearOp modB_idF_Bt = state->
getInverse(
"BidFBt");
344 modB_idF_Bt = explicitMultiply(B, invDiagF, Bt, modB_idF_Bt);
346 const LinearOp B_idF_Bt = modB_idF_Bt;
348 MultiVector vec_D = getDiagonal(B_idF_Bt);
349 update(-1.0, getDiagonal(C), 1.0, vec_D);
350 const LinearOp invD = buildInvDiagonal(vec_D,
"inv(D)");
352 Teko_DEBUG_MSG(
"Calculating alpha", 10);
353 const LinearOp BidFBtidD = multiply<double>(B_idF_Bt, invD);
354 double num = std::fabs(Teko::computeSpectralRad(BidFBtidD, 5e-2,
false, eigSolveParam_));
355 Teko_DEBUG_MSG(
"Calculated alpha", 10);
356 state->
alpha_ = 1.0 / num;
357 state->
aiD_ = Thyra::scale(state->
alpha_, invD);
360 Teko::ModifiableLinearOp BQBtmC = state->
getInverse(
"BQBtmC");
361 BQBtmC = explicitAdd(state->
BQBt_, scale(-state->
gamma_, stabMatrix), BQBtmC);
365 Teko::ModifiableLinearOp BHBtmC = state->
getInverse(
"BHBtmC");
366 if (H == Teuchos::null)
369 BHBtmC = explicitAdd(state->
BHBt_, scale(-state->
gamma_, stabMatrix), BHBtmC);
373 Teko_DEBUG_MSG_BEGIN(5) DEBUG_STREAM <<
"LSC Gamma Parameter = " << state->
gamma_ << std::endl;
374 DEBUG_STREAM <<
"LSC Alpha Parameter = " << state->
alpha_ << std::endl;
385 void InvLSCStrategy::computeInverses(
const BlockedLinearOp& A,
LSCPrecondState* state)
const {
386 Teko_DEBUG_SCOPE(
"InvLSCStrategy::computeInverses", 10);
387 Teko_DEBUG_EXPR(Teuchos::Time invTimer(
""));
389 const LinearOp F = getBlock(0, 0, A);
394 Teko_DEBUG_MSG(
"LSC::computeInverses Building inv(F)", 1);
395 Teko_DEBUG_EXPR(invTimer.start(
true));
396 InverseLinearOp invF = state->
getInverse(
"invF");
397 if (invF == Teuchos::null) {
403 Teko_DEBUG_EXPR(invTimer.stop());
404 Teko_DEBUG_MSG(
"LSC::computeInverses GetInvF = " << invTimer.totalElapsedTime(), 1);
409 Teko_DEBUG_MSG(
"LSC::computeInverses Building inv(BQBtmC)", 1);
410 Teko_DEBUG_EXPR(invTimer.start(
true));
411 const LinearOp BQBt = state->
getInverse(
"BQBtmC");
412 InverseLinearOp invBQBt = state->
getInverse(
"invBQBtmC");
413 if (invBQBt == Teuchos::null) {
419 Teko_DEBUG_EXPR(invTimer.stop());
420 Teko_DEBUG_MSG(
"LSC::computeInverses GetInvBQBt = " << invTimer.totalElapsedTime(), 1);
425 ModifiableLinearOp invBHBt = state->
getInverse(
"invBHBtmC");
426 if (hScaling_ != Teuchos::null || not isSymmetric_) {
428 Teko_DEBUG_MSG(
"LSC::computeInverses Building inv(BHBtmC)", 1);
429 Teko_DEBUG_EXPR(invTimer.start(
true));
430 const LinearOp BHBt = state->
getInverse(
"BHBtmC");
431 if (invBHBt == Teuchos::null) {
437 Teko_DEBUG_EXPR(invTimer.stop());
438 Teko_DEBUG_MSG(
"LSC::computeInverses GetInvBHBt = " << invTimer.totalElapsedTime(), 1);
439 }
else if (invBHBt == Teuchos::null) {
446 void InvLSCStrategy::initializeFromParameterList(
const Teuchos::ParameterList& pl,
447 const InverseLibrary& invLib) {
449 std::string invStr =
"", invVStr =
"", invPStr =
"";
450 bool rowZeroing =
true;
452 scaleType_ = Diagonal;
455 if (pl.isParameter(
"Inverse Type")) invStr = pl.get<std::string>(
"Inverse Type");
456 if (pl.isParameter(
"Inverse Velocity Type"))
457 invVStr = pl.get<std::string>(
"Inverse Velocity Type");
458 if (pl.isParameter(
"Inverse Pressure Type"))
459 invPStr = pl.get<std::string>(
"Inverse Pressure Type");
460 if (pl.isParameter(
"Ignore Boundary Rows")) rowZeroing = pl.get<
bool>(
"Ignore Boundary Rows");
461 if (pl.isParameter(
"Use LDU")) useLDU = pl.get<
bool>(
"Use LDU");
462 if (pl.isParameter(
"Use Mass Scaling")) useMass_ = pl.get<
bool>(
"Use Mass Scaling");
465 if (pl.isParameter(
"Use W-Scaling")) useWScaling_ = pl.get<
bool>(
"Use W-Scaling");
466 if (pl.isParameter(
"Eigen Solver Iterations"))
467 eigSolveParam_ = pl.get<
int>(
"Eigen Solver Iterations");
468 if (pl.isParameter(
"Scaling Type")) {
469 scaleType_ = getDiagonalType(pl.get<std::string>(
"Scaling Type"));
470 TEUCHOS_TEST_FOR_EXCEPT(scaleType_ == NotDiag);
472 if (pl.isParameter(
"Assume Stable Discretization"))
473 assumeStable_ = pl.get<
bool>(
"Assume Stable Discretization");
475 Teko_DEBUG_MSG_BEGIN(5) DEBUG_STREAM <<
"LSC Inverse Strategy Parameters: " << std::endl;
476 DEBUG_STREAM <<
" inv type = \"" << invStr <<
"\"" << std::endl;
477 DEBUG_STREAM <<
" inv v type = \"" << invVStr <<
"\"" << std::endl;
478 DEBUG_STREAM <<
" inv p type = \"" << invPStr <<
"\"" << std::endl;
479 DEBUG_STREAM <<
" bndry rows = " << rowZeroing << std::endl;
480 DEBUG_STREAM <<
" use ldu = " << useLDU << std::endl;
481 DEBUG_STREAM <<
" use mass = " << useMass_ << std::endl;
482 DEBUG_STREAM <<
" use w-scaling = " << useWScaling_ << std::endl;
483 DEBUG_STREAM <<
" assume stable = " << assumeStable_ << std::endl;
484 DEBUG_STREAM <<
" scale type = " << getDiagonalName(scaleType_) << std::endl;
485 DEBUG_STREAM <<
"LSC Inverse Strategy Parameter list: " << std::endl;
486 pl.print(DEBUG_STREAM);
490 #if defined(Teko_ENABLE_Amesos)
491 if (invStr ==
"") invStr =
"Amesos";
492 #elif defined(Teko_ENABLE_Amesos2)
493 if (invStr ==
"") invStr =
"Amesos2";
495 if (invVStr ==
"") invVStr = invStr;
496 if (invPStr ==
"") invPStr = invStr;
499 invFactoryF_ = invLib.getInverseFactory(invVStr);
500 invFactoryS_ = invFactoryF_;
501 if (invVStr != invPStr)
502 invFactoryS_ = invLib.getInverseFactory(invPStr);
505 setUseFullLDU(useLDU);
506 setRowZeroing(rowZeroing);
509 Teuchos::RCP<Teko::RequestHandler> rh = getRequestHandler();
510 rh->preRequest<Teko::LinearOp>(Teko::RequestMesg(
"Velocity Mass Matrix"));
511 Teko::LinearOp mass = rh->request<Teko::LinearOp>(Teko::RequestMesg(
"Velocity Mass Matrix"));
517 Teuchos::RCP<Teuchos::ParameterList> InvLSCStrategy::getRequestedParameters()
const {
518 Teuchos::RCP<Teuchos::ParameterList> result;
519 Teuchos::RCP<Teuchos::ParameterList> pl = rcp(
new Teuchos::ParameterList());
522 RCP<Teuchos::ParameterList> fList = invFactoryF_->getRequestedParameters();
523 if (fList != Teuchos::null) {
524 Teuchos::ParameterList::ConstIterator itr;
525 for (itr = fList->begin(); itr != fList->end(); ++itr) pl->setEntry(itr->first, itr->second);
530 RCP<Teuchos::ParameterList> sList = invFactoryS_->getRequestedParameters();
531 if (sList != Teuchos::null) {
532 Teuchos::ParameterList::ConstIterator itr;
533 for (itr = sList->begin(); itr != sList->end(); ++itr) pl->setEntry(itr->first, itr->second);
539 pl->set<Teko::LinearOp>(
"W-Scaling Vector", Teuchos::null,
"W-Scaling Vector");
547 bool InvLSCStrategy::updateRequestedParameters(
const Teuchos::ParameterList& pl) {
548 Teko_DEBUG_SCOPE(
"InvLSCStrategy::updateRequestedParameters", 10);
552 result &= invFactoryF_->updateRequestedParameters(pl);
553 result &= invFactoryS_->updateRequestedParameters(pl);
557 Teko::MultiVector wScale = pl.get<Teko::MultiVector>(
"W-Scaling Vector");
559 if (wScale == Teuchos::null)
void rebuildInverse(const InverseFactory &factory, const LinearOp &A, InverseLinearOp &invA)
virtual Teko::InverseLinearOp getInverse(const std::string &name) const
Get a named inverse from the state object.
An implementation of a state object for block preconditioners.
virtual bool isInitialized() const
virtual void addInverse(const std::string &name, const Teko::InverseLinearOp &ilo)
Add a named inverse to the state object.
LinearOp invMass_
Inverse mass operator ( )
Preconditioner state for the LSC factory.
InverseLinearOp buildInverse(const InverseFactory &factory, const LinearOp &A)
Build an inverse operator using a factory and a linear operator.
virtual void setInitialized(bool init=true)