|
Teko Version of the Day
|
00001 /* 00002 // @HEADER 00003 // 00004 // *********************************************************************** 00005 // 00006 // Teko: A package for block and physics based preconditioning 00007 // Copyright 2010 Sandia Corporation 00008 // 00009 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, 00010 // the U.S. Government retains certain rights in this software. 00011 // 00012 // Redistribution and use in source and binary forms, with or without 00013 // modification, are permitted provided that the following conditions are 00014 // met: 00015 // 00016 // 1. Redistributions of source code must retain the above copyright 00017 // notice, this list of conditions and the following disclaimer. 00018 // 00019 // 2. Redistributions in binary form must reproduce the above copyright 00020 // notice, this list of conditions and the following disclaimer in the 00021 // documentation and/or other materials provided with the distribution. 00022 // 00023 // 3. Neither the name of the Corporation nor the names of the 00024 // contributors may be used to endorse or promote products derived from 00025 // this software without specific prior written permission. 00026 // 00027 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY 00028 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00029 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 00030 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE 00031 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 00032 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 00033 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00034 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 00035 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00036 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00037 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00038 // 00039 // Questions? Contact Eric C. Cyr (eccyr@sandia.gov) 00040 // 00041 // *********************************************************************** 00042 // 00043 // @HEADER 00044 00045 */ 00046 00047 #include "NS/Teko_PresLaplaceLSCStrategy.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 00054 #include "Teuchos_Time.hpp" 00055 #include "Teuchos_TimeMonitor.hpp" 00056 00057 // Teko includes 00058 #include "Teko_Utilities.hpp" 00059 #include "NS/Teko_LSCPreconditionerFactory.hpp" 00060 00061 using Teuchos::RCP; 00062 using Teuchos::rcp_dynamic_cast; 00063 using Teuchos::rcp_const_cast; 00064 00065 namespace Teko { 00066 namespace NS { 00067 00069 // PresLaplaceLSCStrategy Implementation 00071 00072 // constructors 00074 PresLaplaceLSCStrategy::PresLaplaceLSCStrategy() 00075 : invFactoryV_(Teuchos::null), invFactoryP_(Teuchos::null) 00076 , eigSolveParam_(5), useFullLDU_(false), useMass_(false), scaleType_(AbsRowSum) 00077 { } 00078 00079 PresLaplaceLSCStrategy::PresLaplaceLSCStrategy(const Teuchos::RCP<InverseFactory> & factory) 00080 : invFactoryV_(factory), invFactoryP_(factory) 00081 , eigSolveParam_(5), useFullLDU_(false), useMass_(false), scaleType_(AbsRowSum) 00082 { } 00083 00084 PresLaplaceLSCStrategy::PresLaplaceLSCStrategy(const Teuchos::RCP<InverseFactory> & invFactF, 00085 const Teuchos::RCP<InverseFactory> & invFactS) 00086 : invFactoryV_(invFactF), invFactoryP_(invFactS) 00087 , eigSolveParam_(5), useFullLDU_(false), useMass_(false), scaleType_(AbsRowSum) 00088 { } 00089 00091 00092 void PresLaplaceLSCStrategy::buildState(BlockedLinearOp & A,BlockPreconditionerState & state) const 00093 { 00094 Teko_DEBUG_SCOPE("PresLaplaceLSCStrategy::buildState",10); 00095 00096 LSCPrecondState * lscState = dynamic_cast<LSCPrecondState*>(&state); 00097 TEUCHOS_ASSERT(lscState!=0); 00098 00099 // if neccessary save state information 00100 if(not lscState->isInitialized()) { 00101 Teko_DEBUG_EXPR(Teuchos::Time timer("")); 00102 00103 // construct operators 00104 { 00105 Teko_DEBUG_SCOPE("PL-LSC::buildState constructing operators",1); 00106 Teko_DEBUG_EXPR(timer.start(true)); 00107 00108 initializeState(A,lscState); 00109 00110 Teko_DEBUG_EXPR(timer.stop()); 00111 Teko_DEBUG_MSG("PL-LSC::buildState BuildOpsTime = " << timer.totalElapsedTime(),1); 00112 } 00113 00114 // Build the inverses 00115 { 00116 Teko_DEBUG_SCOPE("PL-LSC::buildState calculating inverses",1); 00117 Teko_DEBUG_EXPR(timer.start(true)); 00118 00119 computeInverses(A,lscState); 00120 00121 Teko_DEBUG_EXPR(timer.stop()); 00122 Teko_DEBUG_MSG("PL-LSC::buildState BuildInvTime = " << timer.totalElapsedTime(),1); 00123 } 00124 } 00125 } 00126 00127 // functions inherited from LSCStrategy 00128 LinearOp PresLaplaceLSCStrategy::getInvBQBt(const BlockedLinearOp & A,BlockPreconditionerState & state) const 00129 { 00130 return state.getModifiableOp("invPresLap"); 00131 } 00132 00133 LinearOp PresLaplaceLSCStrategy::getInvBHBt(const BlockedLinearOp & A,BlockPreconditionerState & state) const 00134 { 00135 return state.getModifiableOp("invPresLap"); 00136 } 00137 00138 LinearOp PresLaplaceLSCStrategy::getInvF(const BlockedLinearOp & A,BlockPreconditionerState & state) const 00139 { 00140 return state.getModifiableOp("invF"); 00141 } 00142 00143 LinearOp PresLaplaceLSCStrategy::getInvAlphaD(const BlockedLinearOp & A,BlockPreconditionerState & state) const 00144 { 00145 LSCPrecondState * lscState = dynamic_cast<LSCPrecondState*>(&state); 00146 TEUCHOS_ASSERT(lscState!=0); 00147 TEUCHOS_ASSERT(lscState->isInitialized()) 00148 00149 return lscState->aiD_; 00150 } 00151 00152 LinearOp PresLaplaceLSCStrategy::getInvMass(const BlockedLinearOp & A,BlockPreconditionerState & state) const 00153 { 00154 LSCPrecondState * lscState = dynamic_cast<LSCPrecondState*>(&state); 00155 TEUCHOS_ASSERT(lscState!=0); 00156 TEUCHOS_ASSERT(lscState->isInitialized()) 00157 00158 return lscState->invMass_; 00159 } 00160 00161 LinearOp PresLaplaceLSCStrategy::getHScaling(const BlockedLinearOp & A,BlockPreconditionerState & state) const 00162 { 00163 return getInvMass(A,state); 00164 } 00165 00167 void PresLaplaceLSCStrategy::initializeState(const BlockedLinearOp & A,LSCPrecondState * state) const 00168 { 00169 Teko_DEBUG_SCOPE("PresLaplaceLSCStrategy::initializeState",10); 00170 00171 std::string velMassStr = getVelocityMassString(); 00172 00173 const LinearOp F = getBlock(0,0,A); 00174 const LinearOp Bt = getBlock(0,1,A); 00175 const LinearOp B = getBlock(1,0,A); 00176 const LinearOp C = getBlock(1,1,A); 00177 00178 LinearOp D = B; 00179 LinearOp G = Bt; 00180 00181 bool isStabilized = (not isZeroOp(C)); 00182 00183 // grab operators from state object 00184 LinearOp massMatrix = state->getLinearOp(velMassStr); 00185 00186 // The logic follows like this 00187 // if there is no mass matrix available --> build from F 00188 // if there is a mass matrix and the inverse hasn't yet been built 00189 // --> build from the mass matrix 00190 // otherwise, there is already an invMass_ matrix that is appropriate 00191 // --> use that one 00192 if(massMatrix==Teuchos::null) { 00193 Teko_DEBUG_MSG("PL-LSC::initializeState Build Scaling <F> type \"" 00194 << getDiagonalName(scaleType_) << "\"" ,1); 00195 state->invMass_ = getInvDiagonalOp(F,scaleType_); 00196 } 00197 else if(state->invMass_==Teuchos::null) { 00198 Teko_DEBUG_MSG("PL-LSC::initializeState Build Scaling <mass> type \"" 00199 << getDiagonalName(scaleType_) << "\"" ,1); 00200 state->invMass_ = getInvDiagonalOp(massMatrix,scaleType_); 00201 } 00202 // else "invMass_" should be set and there is no reason to rebuild it 00203 00204 // if this is a stable discretization...we are done! 00205 if(not isStabilized) { 00206 state->aiD_ = Teuchos::null; 00207 00208 state->setInitialized(true); 00209 00210 return; 00211 } 00212 00213 // compute alpha scaled inv(D): EHSST2007 Eq. 4.29 00214 // construct B_idF_Bt and save it for refilling later: This could reuse BQBt graph 00215 LinearOp invDiagF = getInvDiagonalOp(F); 00216 Teko::ModifiableLinearOp & modB_idF_Bt = state->getModifiableOp("BidFBt"); 00217 modB_idF_Bt = explicitMultiply(B,invDiagF,Bt,modB_idF_Bt); 00218 const LinearOp B_idF_Bt = modB_idF_Bt; 00219 00220 MultiVector vec_D = getDiagonal(B_idF_Bt); // this memory could be reused 00221 update(-1.0,getDiagonal(C),1.0,vec_D); // vec_D = diag(B*inv(diag(F))*Bt)-diag(C) 00222 const LinearOp invD = buildInvDiagonal(vec_D,"inv(D)"); 00223 00224 Teko_DEBUG_MSG("Calculating alpha",10); 00225 const LinearOp BidFBtidD = multiply<double>(B_idF_Bt,invD); 00226 double num = std::fabs(Teko::computeSpectralRad(BidFBtidD,5e-2,false,eigSolveParam_)); 00227 Teko_DEBUG_MSG("Calculated alpha",10); 00228 state->alpha_ = 1.0/num; 00229 state->aiD_ = Thyra::scale(state->alpha_,invD); 00230 00231 Teko_DEBUG_MSG_BEGIN(5) 00232 DEBUG_STREAM << "PL-LSC Alpha Parameter = " << state->alpha_ << std::endl; 00233 Teko_DEBUG_MSG_END() 00234 00235 state->setInitialized(true); 00236 } 00237 00243 void PresLaplaceLSCStrategy::computeInverses(const BlockedLinearOp & A,LSCPrecondState * state) const 00244 { 00245 Teko_DEBUG_SCOPE("PresLaplaceLSCStrategy::computeInverses",10); 00246 Teko_DEBUG_EXPR(Teuchos::Time invTimer("")); 00247 00248 std::string presLapStr = getPressureLaplaceString(); 00249 00250 const LinearOp F = getBlock(0,0,A); 00251 const LinearOp presLap = state->getLinearOp(presLapStr); 00252 00254 00255 // (re)build the inverse of F 00256 Teko_DEBUG_MSG("PL-LSC::computeInverses Building inv(F)",1); 00257 Teko_DEBUG_EXPR(invTimer.start(true)); 00258 ModifiableLinearOp & invF = state->getModifiableOp("invF"); 00259 if(invF==Teuchos::null) { 00260 invF = buildInverse(*invFactoryV_,F); 00261 } else { 00262 rebuildInverse(*invFactoryV_,F,invF); 00263 } 00264 Teko_DEBUG_EXPR(invTimer.stop()); 00265 Teko_DEBUG_MSG("PL-LSC::computeInverses GetInvF = " << invTimer.totalElapsedTime(),1); 00266 00268 00269 // (re)build the inverse of P 00270 Teko_DEBUG_MSG("PL-LSC::computeInverses Building inv(PresLap)",1); 00271 Teko_DEBUG_EXPR(invTimer.start(true)); 00272 ModifiableLinearOp & invPresLap = state->getModifiableOp("invPresLap"); 00273 if(invPresLap==Teuchos::null) { 00274 invPresLap = buildInverse(*invFactoryP_,presLap); 00275 } else { 00276 // not need because the pressure laplacian never changes 00277 // rebuildInverse(*invFactoryP_,presLap,invPresLap); 00278 } 00279 Teko_DEBUG_EXPR(invTimer.stop()); 00280 Teko_DEBUG_MSG("PL-LSC::computeInverses GetInvBQBt = " << invTimer.totalElapsedTime(),1); 00281 } 00282 00284 void PresLaplaceLSCStrategy::initializeFromParameterList(const Teuchos::ParameterList & pl,const InverseLibrary & invLib) 00285 { 00286 // get string specifying inverse 00287 std::string invStr="Amesos", invVStr="", invPStr=""; 00288 bool useLDU = false; 00289 scaleType_ = AbsRowSum; 00290 00291 // "parse" the parameter list 00292 if(pl.isParameter("Inverse Type")) 00293 invStr = pl.get<std::string>("Inverse Type"); 00294 if(pl.isParameter("Inverse Velocity Type")) 00295 invVStr = pl.get<std::string>("Inverse Velocity Type"); 00296 if(pl.isParameter("Inverse Pressure Type")) 00297 invPStr = pl.get<std::string>("Inverse Pressure Type"); 00298 if(pl.isParameter("Use LDU")) 00299 useLDU = pl.get<bool>("Use LDU"); 00300 if(pl.isParameter("Use Mass Scaling")) 00301 useMass_ = pl.get<bool>("Use Mass Scaling"); 00302 if(pl.isParameter("Eigen Solver Iterations")) 00303 eigSolveParam_ = pl.get<int>("Eigen Solver Iterations"); 00304 if(pl.isParameter("Scaling Type")) { 00305 scaleType_ = getDiagonalType(pl.get<std::string>("Scaling Type")); 00306 TEST_FOR_EXCEPT(scaleType_==NotDiag); 00307 } 00308 00309 // set defaults as needed 00310 if(invVStr=="") invVStr = invStr; 00311 if(invPStr=="") invPStr = invStr; 00312 00313 Teko_DEBUG_MSG_BEGIN(5) 00314 DEBUG_STREAM << "LSC Inverse Strategy Parameters: " << std::endl; 00315 DEBUG_STREAM << " inv v type = \"" << invVStr << "\"" << std::endl; 00316 DEBUG_STREAM << " inv p type = \"" << invPStr << "\"" << std::endl; 00317 DEBUG_STREAM << " use ldu = " << useLDU << std::endl; 00318 DEBUG_STREAM << " use mass = " << useMass_ << std::endl; 00319 DEBUG_STREAM << " scale type = " << getDiagonalName(scaleType_) << std::endl; 00320 DEBUG_STREAM << "LSC Pressure Laplace Strategy Parameter list: " << std::endl; 00321 pl.print(DEBUG_STREAM); 00322 Teko_DEBUG_MSG_END() 00323 00324 // build velocity inverse factory 00325 invFactoryV_ = invLib.getInverseFactory(invVStr); 00326 invFactoryP_ = invFactoryV_; // by default these are the same 00327 if(invVStr!=invPStr) // if different, build pressure inverse factory 00328 invFactoryP_ = invLib.getInverseFactory(invPStr); 00329 00330 // set other parameters 00331 setUseFullLDU(useLDU); 00332 } 00333 00335 Teuchos::RCP<Teuchos::ParameterList> PresLaplaceLSCStrategy::getRequestedParameters() const 00336 { 00337 Teko_DEBUG_SCOPE("PresLaplaceLSCStrategy::getRequestedParameters",10); 00338 Teuchos::RCP<Teuchos::ParameterList> pl = rcp(new Teuchos::ParameterList()); 00339 00340 // grab parameters from F solver 00341 RCP<Teuchos::ParameterList> fList = invFactoryV_->getRequestedParameters(); 00342 if(fList!=Teuchos::null) { 00343 Teuchos::ParameterList::ConstIterator itr; 00344 for(itr=fList->begin();itr!=fList->end();++itr) 00345 pl->setEntry(itr->first,itr->second); 00346 } 00347 00348 // grab parameters from S solver 00349 RCP<Teuchos::ParameterList> sList = invFactoryP_->getRequestedParameters(); 00350 if(sList!=Teuchos::null) { 00351 Teuchos::ParameterList::ConstIterator itr; 00352 for(itr=sList->begin();itr!=sList->end();++itr) 00353 pl->setEntry(itr->first,itr->second); 00354 } 00355 00356 // use the mass matrix 00357 if(useMass_) 00358 pl->set(getVelocityMassString(), false,"Velocity mass matrix"); 00359 pl->set(getPressureLaplaceString(), false,"Pressure Laplacian matrix"); 00360 00361 return pl; 00362 } 00363 00365 bool PresLaplaceLSCStrategy::updateRequestedParameters(const Teuchos::ParameterList & pl) 00366 { 00367 Teko_DEBUG_SCOPE("PresLaplaceLSCStrategy::updateRequestedParameters",10); 00368 bool result = true; 00369 00370 // update requested parameters in solvers 00371 result &= invFactoryV_->updateRequestedParameters(pl); 00372 result &= invFactoryP_->updateRequestedParameters(pl); 00373 00374 Teuchos::ParameterList hackList(pl); 00375 00376 // get required operator acknowledgment...user must set these to true 00377 bool plo = hackList.get<bool>(getPressureLaplaceString(),false); 00378 00379 bool vmo = true; 00380 if(useMass_) 00381 vmo = hackList.get<bool>(getVelocityMassString(),false); 00382 00383 if(not plo) { Teko_DEBUG_MSG("User must acknowledge the use of the \"" << getPressureLaplaceString() << "\"!",0); } 00384 if(not vmo) { Teko_DEBUG_MSG("User must acknowledge the use of the \"" << getVelocityMassString() << "\"!",0); } 00385 00386 result &= (plo & vmo); 00387 00388 return result; 00389 } 00390 00391 } // end namespace NS 00392 } // end namespace Teko
1.7.4