00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047 #include "NS/Teko_InvLSCStrategy.hpp"
00048
00049 #include "Thyra_DefaultDiagonalLinearOp.hpp"
00050 #include "Thyra_EpetraThyraWrappers.hpp"
00051 #include "Thyra_get_Epetra_Operator.hpp"
00052 #include "Thyra_EpetraLinearOp.hpp"
00053 #include "Thyra_VectorStdOps.hpp"
00054
00055 #include "Epetra_Vector.h"
00056 #include "Epetra_Map.h"
00057
00058 #include "EpetraExt_RowMatrixOut.h"
00059 #include "EpetraExt_MultiVectorOut.h"
00060 #include "EpetraExt_VectorOut.h"
00061
00062 #include "Teuchos_Time.hpp"
00063 #include "Teuchos_TimeMonitor.hpp"
00064
00065
00066 #include "Teko_Utilities.hpp"
00067 #include "NS/Teko_LSCPreconditionerFactory.hpp"
00068 #include "Epetra/Teko_EpetraHelpers.hpp"
00069 #include "Epetra/Teko_EpetraOperatorWrapper.hpp"
00070
00071 using Teuchos::RCP;
00072 using Teuchos::rcp_dynamic_cast;
00073 using Teuchos::rcp_const_cast;
00074
00075 namespace Teko {
00076 namespace NS {
00077
00079
00081
00082
00084 InvLSCStrategy::InvLSCStrategy()
00085 : massMatrix_(Teuchos::null), invFactoryF_(Teuchos::null), invFactoryS_(Teuchos::null), eigSolveParam_(5)
00086 , rowZeroingNeeded_(false), useFullLDU_(false), useMass_(false), useLumping_(false), useWScaling_(false), scaleType_(Diagonal)
00087 , isSymmetric_(true), assumeStable_(false)
00088 { }
00089
00090 InvLSCStrategy::InvLSCStrategy(const Teuchos::RCP<InverseFactory> & factory,bool rzn)
00091 : massMatrix_(Teuchos::null), invFactoryF_(factory), invFactoryS_(factory), eigSolveParam_(5), rowZeroingNeeded_(rzn)
00092 , useFullLDU_(false), useMass_(false), useLumping_(false), useWScaling_(false), scaleType_(Diagonal)
00093 , isSymmetric_(true), assumeStable_(false)
00094 { }
00095
00096 InvLSCStrategy::InvLSCStrategy(const Teuchos::RCP<InverseFactory> & invFactF,
00097 const Teuchos::RCP<InverseFactory> & invFactS,
00098 bool rzn)
00099 : massMatrix_(Teuchos::null), invFactoryF_(invFactF), invFactoryS_(invFactS), eigSolveParam_(5), rowZeroingNeeded_(rzn)
00100 , useFullLDU_(false), useMass_(false), useLumping_(false), useWScaling_(false), scaleType_(Diagonal)
00101 , isSymmetric_(true), assumeStable_(false)
00102 { }
00103
00104 InvLSCStrategy::InvLSCStrategy(const Teuchos::RCP<InverseFactory> & factory,LinearOp & mass,bool rzn)
00105 : massMatrix_(mass), invFactoryF_(factory), invFactoryS_(factory), eigSolveParam_(5), rowZeroingNeeded_(rzn)
00106 , useFullLDU_(false), useMass_(false), useLumping_(false), useWScaling_(false), scaleType_(Diagonal)
00107 , isSymmetric_(true), assumeStable_(false)
00108 { }
00109
00110 InvLSCStrategy::InvLSCStrategy(const Teuchos::RCP<InverseFactory> & invFactF,
00111 const Teuchos::RCP<InverseFactory> & invFactS,
00112 LinearOp & mass,bool rzn)
00113 : massMatrix_(mass), invFactoryF_(invFactF), invFactoryS_(invFactS), eigSolveParam_(5), rowZeroingNeeded_(rzn)
00114 , useFullLDU_(false), useMass_(false), useLumping_(false), useWScaling_(false), scaleType_(Diagonal)
00115 , isSymmetric_(true), assumeStable_(false)
00116 { }
00117
00119
00120 void InvLSCStrategy::buildState(BlockedLinearOp & A,BlockPreconditionerState & state) const
00121 {
00122 Teko_DEBUG_SCOPE("InvLSCStrategy::buildState",10);
00123
00124 LSCPrecondState * lscState = dynamic_cast<LSCPrecondState*>(&state);
00125 TEUCHOS_ASSERT(lscState!=0);
00126
00127
00128 if(not lscState->isInitialized()) {
00129 Teko_DEBUG_EXPR(Teuchos::Time timer(""));
00130
00131
00132 {
00133 Teko_DEBUG_SCOPE("LSC::buildState constructing operators",1);
00134 Teko_DEBUG_EXPR(timer.start(true));
00135
00136 initializeState(A,lscState);
00137
00138 Teko_DEBUG_EXPR(timer.stop());
00139 Teko_DEBUG_MSG("LSC::buildState BuildOpsTime = " << timer.totalElapsedTime(),1);
00140 }
00141
00142
00143 {
00144 Teko_DEBUG_SCOPE("LSC::buildState calculating inverses",1);
00145 Teko_DEBUG_EXPR(timer.start(true));
00146
00147 computeInverses(A,lscState);
00148
00149 Teko_DEBUG_EXPR(timer.stop());
00150 Teko_DEBUG_MSG("LSC::buildState BuildInvTime = " << timer.totalElapsedTime(),1);
00151 }
00152 }
00153 }
00154
00155
00156 LinearOp InvLSCStrategy::getInvBQBt(const BlockedLinearOp & A,BlockPreconditionerState & state) const
00157 {
00158 return state.getInverse("invBQBtmC");
00159 }
00160
00161 LinearOp InvLSCStrategy::getInvBHBt(const BlockedLinearOp & A,BlockPreconditionerState & state) const
00162 {
00163 return state.getInverse("invBHBtmC");
00164 }
00165
00166 LinearOp InvLSCStrategy::getInvF(const BlockedLinearOp & A,BlockPreconditionerState & state) const
00167 {
00168 return state.getInverse("invF");
00169 }
00170
00171 LinearOp InvLSCStrategy::getOuterStabilization(const BlockedLinearOp & A,BlockPreconditionerState & state) const
00172 {
00173 LSCPrecondState * lscState = dynamic_cast<LSCPrecondState*>(&state);
00174 TEUCHOS_ASSERT(lscState!=0);
00175 TEUCHOS_ASSERT(lscState->isInitialized())
00176
00177 return lscState->aiD_;
00178 }
00179
00180 LinearOp InvLSCStrategy::getInvMass(const BlockedLinearOp & A,BlockPreconditionerState & state) const
00181 {
00182 LSCPrecondState * lscState = dynamic_cast<LSCPrecondState*>(&state);
00183 TEUCHOS_ASSERT(lscState!=0);
00184 TEUCHOS_ASSERT(lscState->isInitialized())
00185
00186 return lscState->invMass_;
00187 }
00188
00189 LinearOp InvLSCStrategy::getHScaling(const BlockedLinearOp & A,BlockPreconditionerState & state) const
00190 {
00191 if(hScaling_!=Teuchos::null) return hScaling_;
00192 return getInvMass(A,state);
00193 }
00194
00196 void InvLSCStrategy::initializeState(const BlockedLinearOp & A,LSCPrecondState * state) const
00197 {
00198 Teko_DEBUG_SCOPE("InvLSCStrategy::initializeState",10);
00199
00200 const LinearOp F = getBlock(0,0,A);
00201 const LinearOp Bt = getBlock(0,1,A);
00202 const LinearOp B = getBlock(1,0,A);
00203 const LinearOp C = getBlock(1,1,A);
00204
00205 LinearOp D = B;
00206 LinearOp G = isSymmetric_ ? Bt : adjoint(D);
00207
00208 bool isStabilized = assumeStable_ ? false : (not isZeroOp(C));
00209
00210
00211
00212
00213
00214
00215
00216 if(massMatrix_==Teuchos::null) {
00217 Teko_DEBUG_MSG("LSC::initializeState Build Scaling <F> type \""
00218 << getDiagonalName(scaleType_) << "\"" ,1);
00219 state->invMass_ = getInvDiagonalOp(F,scaleType_);
00220 }
00221 else if(state->invMass_==Teuchos::null) {
00222 Teko_DEBUG_MSG("LSC::initializeState Build Scaling <mass> type \""
00223 << getDiagonalName(scaleType_) << "\"" ,1);
00224 state->invMass_ = getInvDiagonalOp(massMatrix_,scaleType_);
00225 }
00226
00227
00228
00229 state->BQBt_ = explicitMultiply(B,state->invMass_,Bt,state->BQBt_);
00230 Teko_DEBUG_MSG("Computed BQBt",10);
00231
00232
00233 if(wScaling_!=Teuchos::null && hScaling_==Teuchos::null) {
00234
00235 RCP<const Thyra::VectorBase<double> > w = wScaling_->col(0);
00236 RCP<const Thyra::VectorBase<double> > iQu
00237 = rcp_dynamic_cast<const Thyra::DiagonalLinearOpBase<double> >(state->invMass_)->getDiag();
00238 RCP<Thyra::VectorBase<double> > h = Thyra::createMember(iQu->space());
00239
00240 Thyra::put_scalar(0.0,h.ptr());
00241 Thyra::ele_wise_prod(1.0,*w,*iQu,h.ptr());
00242 hScaling_ = Teuchos::rcp(new Thyra::DefaultDiagonalLinearOp<double>(h));
00243 }
00244
00245 LinearOp H = hScaling_;
00246 if(H==Teuchos::null && not isSymmetric_)
00247 H = state->invMass_;
00248
00249
00250 if(H==Teuchos::null)
00251 state->BHBt_ = state->BQBt_;
00252 else {
00253 RCP<Teuchos::Time> time = Teuchos::TimeMonitor::getNewTimer("InvLSCStrategy::initializeState Build BHBt");
00254 Teuchos::TimeMonitor timer(*time);
00255
00256
00257 state->BHBt_ = explicitMultiply(D,H,G,state->BHBt_);
00258 }
00259
00260
00261 if(not isStabilized) {
00262 state->addInverse("BQBtmC",state->BQBt_);
00263 state->addInverse("BHBtmC",state->BHBt_);
00264 state->gamma_ = 0.0;
00265 state->alpha_ = 0.0;
00266 state->aiD_ = Teuchos::null;
00267
00268 state->setInitialized(true);
00269
00270 return;
00271 }
00272
00273
00274 LinearOp modF = F;
00275 const RCP<const Epetra_Operator> epF = Thyra::get_Epetra_Operator(*F);
00276 if(epF!=Teuchos::null && rowZeroingNeeded_) {
00277
00278 const RCP<const Epetra_CrsMatrix> crsF = rcp_dynamic_cast<const Epetra_CrsMatrix>(epF);
00279
00280
00281 if(crsF!=Teuchos::null) {
00282 std::vector<int> zeroIndices;
00283
00284
00285 Teko::Epetra::identityRowIndices(crsF->RowMap(), *crsF,zeroIndices);
00286
00287
00288 modF = Thyra::epetraLinearOp(rcp(new Teko::Epetra::ZeroedOperator(zeroIndices,crsF)));
00289 }
00290 }
00291
00292
00293 Teko_DEBUG_MSG("Calculating gamma",10);
00294 LinearOp iQuF = multiply(state->invMass_,modF);
00295
00296
00297 Teko::LinearOp stabMatrix;
00298 state->gamma_ = std::fabs(Teko::computeSpectralRad(iQuF,5e-2,false,eigSolveParam_))/3.0;
00299 Teko_DEBUG_MSG("Calculated gamma",10);
00300 if(userPresStabMat_!=Teuchos::null) {
00301 Teko::LinearOp invDGl = Teko::getInvDiagonalOp(userPresStabMat_);
00302 Teko::LinearOp gammaOp = multiply(invDGl,C);
00303 state->gamma_ *= std::fabs(Teko::computeSpectralRad(gammaOp,5e-2,false,eigSolveParam_));
00304 stabMatrix = userPresStabMat_;
00305 } else
00306 stabMatrix = C;
00307
00308
00309
00310 LinearOp invDiagF = getInvDiagonalOp(F);
00311 Teko::ModifiableLinearOp modB_idF_Bt = state->getInverse("BidFBt");
00312 modB_idF_Bt = explicitMultiply(B,invDiagF,Bt,modB_idF_Bt);
00313 state->addInverse("BidFBt",modB_idF_Bt);
00314 const LinearOp B_idF_Bt = modB_idF_Bt;
00315
00316 MultiVector vec_D = getDiagonal(B_idF_Bt);
00317 update(-1.0,getDiagonal(C),1.0,vec_D);
00318 const LinearOp invD = buildInvDiagonal(vec_D,"inv(D)");
00319
00320 Teko_DEBUG_MSG("Calculating alpha",10);
00321 const LinearOp BidFBtidD = multiply<double>(B_idF_Bt,invD);
00322 double num = std::fabs(Teko::computeSpectralRad(BidFBtidD,5e-2,false,eigSolveParam_));
00323 Teko_DEBUG_MSG("Calculated alpha",10);
00324 state->alpha_ = 1.0/num;
00325 state->aiD_ = Thyra::scale(state->alpha_,invD);
00326
00327
00328 Teko::ModifiableLinearOp BQBtmC = state->getInverse("BQBtmC");
00329 BQBtmC = explicitAdd(state->BQBt_,scale(-state->gamma_,stabMatrix),BQBtmC);
00330 state->addInverse("BQBtmC",BQBtmC);
00331
00332
00333 Teko::ModifiableLinearOp BHBtmC = state->getInverse("BHBtmC");
00334 if(H==Teuchos::null)
00335 BHBtmC = BQBtmC;
00336 else {
00337 BHBtmC = explicitAdd(state->BHBt_,scale(-state->gamma_,stabMatrix),BHBtmC);
00338 }
00339 state->addInverse("BHBtmC",BHBtmC);
00340
00341 Teko_DEBUG_MSG_BEGIN(5)
00342 DEBUG_STREAM << "LSC Gamma Parameter = " << state->gamma_ << std::endl;
00343 DEBUG_STREAM << "LSC Alpha Parameter = " << state->alpha_ << std::endl;
00344 Teko_DEBUG_MSG_END()
00345
00346 state->setInitialized(true);
00347 }
00348
00354 void InvLSCStrategy::computeInverses(const BlockedLinearOp & A,LSCPrecondState * state) const
00355 {
00356 Teko_DEBUG_SCOPE("InvLSCStrategy::computeInverses",10);
00357 Teko_DEBUG_EXPR(Teuchos::Time invTimer(""));
00358
00359 const LinearOp F = getBlock(0,0,A);
00360
00362
00363
00364 Teko_DEBUG_MSG("LSC::computeInverses Building inv(F)",1);
00365 Teko_DEBUG_EXPR(invTimer.start(true));
00366 InverseLinearOp invF = state->getInverse("invF");
00367 if(invF==Teuchos::null) {
00368 invF = buildInverse(*invFactoryF_,F);
00369 state->addInverse("invF",invF);
00370 } else {
00371 rebuildInverse(*invFactoryF_,F,invF);
00372 }
00373 Teko_DEBUG_EXPR(invTimer.stop());
00374 Teko_DEBUG_MSG("LSC::computeInverses GetInvF = " << invTimer.totalElapsedTime(),1);
00375
00377
00378
00379 Teko_DEBUG_MSG("LSC::computeInverses Building inv(BQBtmC)",1);
00380 Teko_DEBUG_EXPR(invTimer.start(true));
00381 const LinearOp BQBt = state->getInverse("BQBtmC");
00382 InverseLinearOp invBQBt = state->getInverse("invBQBtmC");
00383 if(invBQBt==Teuchos::null) {
00384 invBQBt = buildInverse(*invFactoryS_,BQBt);
00385 state->addInverse("invBQBtmC",invBQBt);
00386 } else {
00387 rebuildInverse(*invFactoryS_,BQBt,invBQBt);
00388 }
00389 Teko_DEBUG_EXPR(invTimer.stop());
00390 Teko_DEBUG_MSG("LSC::computeInverses GetInvBQBt = " << invTimer.totalElapsedTime(),1);
00391
00393
00394
00395 ModifiableLinearOp invBHBt = state->getInverse("invBHBtmC");
00396 if(hScaling_!=Teuchos::null || not isSymmetric_) {
00397
00398 Teko_DEBUG_MSG("LSC::computeInverses Building inv(BHBtmC)",1);
00399 Teko_DEBUG_EXPR(invTimer.start(true));
00400 const LinearOp BHBt = state->getInverse("BHBtmC");
00401 if(invBHBt==Teuchos::null) {
00402 invBHBt = buildInverse(*invFactoryS_,BHBt);
00403 state->addInverse("invBHBtmC",invBHBt);
00404 } else {
00405 rebuildInverse(*invFactoryS_,BHBt,invBHBt);
00406 }
00407 Teko_DEBUG_EXPR(invTimer.stop());
00408 Teko_DEBUG_MSG("LSC::computeInverses GetInvBHBt = " << invTimer.totalElapsedTime(),1);
00409 }
00410 else if(invBHBt==Teuchos::null) {
00411
00412 state->addInverse("invBHBtmC",invBQBt);
00413 }
00414 }
00415
00417 void InvLSCStrategy::initializeFromParameterList(const Teuchos::ParameterList & pl,const InverseLibrary & invLib)
00418 {
00419
00420 std::string invStr="", invVStr="", invPStr="";
00421 bool rowZeroing = true;
00422 bool useLDU = false;
00423 scaleType_ = Diagonal;
00424
00425
00426 if(pl.isParameter("Inverse Type"))
00427 invStr = pl.get<std::string>("Inverse Type");
00428 if(pl.isParameter("Inverse Velocity Type"))
00429 invVStr = pl.get<std::string>("Inverse Velocity Type");
00430 if(pl.isParameter("Inverse Pressure Type"))
00431 invPStr = pl.get<std::string>("Inverse Pressure Type");
00432 if(pl.isParameter("Ignore Boundary Rows"))
00433 rowZeroing = pl.get<bool>("Ignore Boundary Rows");
00434 if(pl.isParameter("Use LDU"))
00435 useLDU = pl.get<bool>("Use LDU");
00436 if(pl.isParameter("Use Mass Scaling"))
00437 useMass_ = pl.get<bool>("Use Mass Scaling");
00438
00439
00440 if(pl.isParameter("Use W-Scaling"))
00441 useWScaling_ = pl.get<bool>("Use W-Scaling");
00442 if(pl.isParameter("Eigen Solver Iterations"))
00443 eigSolveParam_ = pl.get<int>("Eigen Solver Iterations");
00444 if(pl.isParameter("Scaling Type")) {
00445 scaleType_ = getDiagonalType(pl.get<std::string>("Scaling Type"));
00446 TEUCHOS_TEST_FOR_EXCEPT(scaleType_==NotDiag);
00447 }
00448 if(pl.isParameter("Assume Stable Discretization"))
00449 assumeStable_ = pl.get<bool>("Assume Stable Discretization");
00450
00451 Teko_DEBUG_MSG_BEGIN(5)
00452 DEBUG_STREAM << "LSC Inverse Strategy Parameters: " << std::endl;
00453 DEBUG_STREAM << " inv type = \"" << invStr << "\"" << std::endl;
00454 DEBUG_STREAM << " inv v type = \"" << invVStr << "\"" << std::endl;
00455 DEBUG_STREAM << " inv p type = \"" << invPStr << "\"" << std::endl;
00456 DEBUG_STREAM << " bndry rows = " << rowZeroing << std::endl;
00457 DEBUG_STREAM << " use ldu = " << useLDU << std::endl;
00458 DEBUG_STREAM << " use mass = " << useMass_ << std::endl;
00459 DEBUG_STREAM << " use w-scaling = " << useWScaling_ << std::endl;
00460 DEBUG_STREAM << " assume stable = " << assumeStable_ << std::endl;
00461 DEBUG_STREAM << " scale type = " << getDiagonalName(scaleType_) << std::endl;
00462 DEBUG_STREAM << "LSC Inverse Strategy Parameter list: " << std::endl;
00463 pl.print(DEBUG_STREAM);
00464 Teko_DEBUG_MSG_END()
00465
00466
00467 if(invStr=="") invStr = "Amesos";
00468 if(invVStr=="") invVStr = invStr;
00469 if(invPStr=="") invPStr = invStr;
00470
00471
00472 invFactoryF_ = invLib.getInverseFactory(invVStr);
00473 invFactoryS_ = invFactoryF_;
00474 if(invVStr!=invPStr)
00475 invFactoryS_ = invLib.getInverseFactory(invPStr);
00476
00477
00478 setUseFullLDU(useLDU);
00479 setRowZeroing(rowZeroing);
00480
00481 if(useMass_) {
00482 Teuchos::RCP<Teko::RequestHandler> rh = getRequestHandler();
00483 rh->preRequest<Teko::LinearOp>(Teko::RequestMesg("Velocity Mass Matrix"));
00484 Teko::LinearOp mass
00485 = rh->request<Teko::LinearOp>(Teko::RequestMesg("Velocity Mass Matrix"));
00486 setMassMatrix(mass);
00487 }
00488
00489 }
00490
00492 Teuchos::RCP<Teuchos::ParameterList> InvLSCStrategy::getRequestedParameters() const
00493 {
00494 Teuchos::RCP<Teuchos::ParameterList> result;
00495 Teuchos::RCP<Teuchos::ParameterList> pl = rcp(new Teuchos::ParameterList());
00496
00497
00498 RCP<Teuchos::ParameterList> fList = invFactoryF_->getRequestedParameters();
00499 if(fList!=Teuchos::null) {
00500 Teuchos::ParameterList::ConstIterator itr;
00501 for(itr=fList->begin();itr!=fList->end();++itr)
00502 pl->setEntry(itr->first,itr->second);
00503 result = pl;
00504 }
00505
00506
00507 RCP<Teuchos::ParameterList> sList = invFactoryS_->getRequestedParameters();
00508 if(sList!=Teuchos::null) {
00509 Teuchos::ParameterList::ConstIterator itr;
00510 for(itr=sList->begin();itr!=sList->end();++itr)
00511 pl->setEntry(itr->first,itr->second);
00512 result = pl;
00513 }
00514
00515
00516 if(useWScaling_) {
00517 pl->set<Teko::LinearOp>("W-Scaling Vector", Teuchos::null,"W-Scaling Vector");
00518 result = pl;
00519 }
00520
00521 return result;
00522 }
00523
00525 bool InvLSCStrategy::updateRequestedParameters(const Teuchos::ParameterList & pl)
00526 {
00527 Teko_DEBUG_SCOPE("InvLSCStrategy::updateRequestedParameters",10);
00528 bool result = true;
00529
00530
00531 result &= invFactoryF_->updateRequestedParameters(pl);
00532 result &= invFactoryS_->updateRequestedParameters(pl);
00533
00534
00535 if(useWScaling_) {
00536 Teko::MultiVector wScale = pl.get<Teko::MultiVector>("W-Scaling Vector");
00537
00538 if(wScale==Teuchos::null)
00539 result &= false;
00540 else
00541 setWScaling(wScale);
00542 }
00543
00544 return result;
00545 }
00546
00547 }
00548 }