|
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 "Teko_LSCPreconditionerFactory.hpp" 00048 00049 #include "Thyra_DefaultMultipliedLinearOp.hpp" 00050 #include "Thyra_DefaultAddedLinearOp.hpp" 00051 #include "Thyra_DefaultIdentityLinearOp.hpp" 00052 #include "Thyra_DefaultZeroLinearOp.hpp" 00053 #include "Thyra_get_Epetra_Operator.hpp" 00054 00055 #include "Teko_LU2x2InverseOp.hpp" 00056 #include "Teko_Utilities.hpp" 00057 #include "Teko_BlockUpperTriInverseOp.hpp" 00058 #include "Teko_StaticLSCStrategy.hpp" 00059 #include "Teko_InvLSCStrategy.hpp" 00060 #include "Teko_PresLaplaceLSCStrategy.hpp" 00061 00062 #include "EpetraExt_RowMatrixOut.h" 00063 00064 #include "Teuchos_Time.hpp" 00065 00066 namespace Teko { 00067 namespace NS { 00068 00069 using Teuchos::rcp; 00070 using Teuchos::rcp_dynamic_cast; 00071 using Teuchos::RCP; 00072 00073 using Thyra::multiply; 00074 using Thyra::add; 00075 using Thyra::identity; 00076 00077 // Stabilized constructor 00078 LSCPreconditionerFactory::LSCPreconditionerFactory(const LinearOp & invF,const LinearOp & invBQBtmC, 00079 const LinearOp & invD,const LinearOp & invMass) 00080 : invOpsStrategy_(rcp(new StaticLSCStrategy(invF,invBQBtmC,invD,invMass))), isSymmetric_(true) 00081 { } 00082 00083 // Stable constructor 00084 LSCPreconditionerFactory::LSCPreconditionerFactory(const LinearOp & invF, const LinearOp & invBQBtmC, 00085 const LinearOp & invMass) 00086 : invOpsStrategy_(rcp(new StaticLSCStrategy(invF,invBQBtmC,invMass))), isSymmetric_(true) 00087 { } 00088 00089 // fully generic constructor 00090 LSCPreconditionerFactory::LSCPreconditionerFactory(const RCP<LSCStrategy> & strategy) 00091 : invOpsStrategy_(strategy), isSymmetric_(true) 00092 { } 00093 00094 LSCPreconditionerFactory::LSCPreconditionerFactory() : isSymmetric_(true) 00095 { } 00096 00097 // for PreconditionerFactoryBase 00099 00100 // initialize a newly created preconditioner object 00101 LinearOp LSCPreconditionerFactory::buildPreconditionerOperator(BlockedLinearOp & blockOp,BlockPreconditionerState & state) const 00102 { 00103 Teko_DEBUG_SCOPE("LSCPreconditionerFactory::buildPreconditionerOperator",10); 00104 Teko_DEBUG_EXPR(Teuchos::Time timer("")); 00105 Teko_DEBUG_EXPR(Teuchos::Time totalTimer("")); 00106 Teko_DEBUG_EXPR(totalTimer.start()); 00107 00108 // extract sub-matrices from source operator 00109 LinearOp F = blockOp->getBlock(0,0); 00110 LinearOp B = blockOp->getBlock(1,0); 00111 LinearOp Bt = blockOp->getBlock(0,1); 00112 00113 if(not isSymmetric_) 00114 Bt = scale(-1.0,adjoint(B)); 00115 00116 // build what is neccessary for the state object 00117 Teko_DEBUG_EXPR(timer.start(true)); 00118 invOpsStrategy_->buildState(blockOp,state); 00119 Teko_DEBUG_EXPR(timer.stop()); 00120 Teko_DEBUG_MSG("LSCPrecFact::buildPO BuildStateTime = " << timer.totalElapsedTime(),2); 00121 00122 // extract operators from strategy 00123 Teko_DEBUG_EXPR(timer.start(true)); 00124 LinearOp invF = invOpsStrategy_->getInvF(blockOp,state); 00125 LinearOp invBQBtmC = invOpsStrategy_->getInvBQBt(blockOp,state); 00126 LinearOp invBHBtmC = invOpsStrategy_->getInvBHBt(blockOp,state); 00127 LinearOp invAlphaD = invOpsStrategy_->getInvAlphaD(blockOp,state); 00128 00129 // if necessary build an identity mass matrix 00130 LinearOp invMass = invOpsStrategy_->getInvMass(blockOp,state); 00131 LinearOp HScaling = invOpsStrategy_->getHScaling(blockOp,state); 00132 if(invMass==Teuchos::null) invMass = identity<double>(F->range()); 00133 if(HScaling==Teuchos::null) HScaling = identity<double>(F->range()); 00134 Teko_DEBUG_EXPR(timer.stop()); 00135 Teko_DEBUG_MSG("LSCPrecFact::buildPO GetInvTime = " << timer.totalElapsedTime(),2); 00136 00137 // need to build Schur complement, inv(P) = inv(B*Bt)*(B*F*Bt)*inv(B*Bt) 00138 00139 // first construct middle operator: M = B * inv(Mass) * F * inv(Mass) * Bt 00140 LinearOp M = 00141 // (B * inv(Mass) ) * F * (inv(Mass) * Bt) 00142 multiply( multiply(B,invMass), F , multiply(HScaling,Bt)); 00143 00144 // now construct a linear operator schur complement 00145 LinearOp invPschur; 00146 if(invAlphaD!=Teuchos::null) 00147 invPschur = add(multiply(invBQBtmC, M , invBHBtmC), invAlphaD); 00148 else 00149 invPschur = multiply(invBQBtmC, M , invBHBtmC); 00150 00151 // build the preconditioner operator: Use LDU or upper triangular approximation 00152 if(invOpsStrategy_->useFullLDU()) { 00153 Teko_DEBUG_EXPR(totalTimer.stop()); 00154 Teko_DEBUG_MSG("LSCPrecFact::buildPO TotalTime = " << totalTimer.totalElapsedTime(),2); 00155 00156 // solve using a full LDU decomposition 00157 return createLU2x2InverseOp(blockOp,invF,invPschur,"LSC-LDU"); 00158 } else { 00159 // build diagonal operations 00160 std::vector<LinearOp> invDiag(2); 00161 invDiag[0] = invF; 00162 invDiag[1] = Thyra::scale(-1.0,invPschur); 00163 00164 // get upper triangular matrix 00165 BlockedLinearOp U = getUpperTriBlocks(blockOp); 00166 00167 Teko_DEBUG_EXPR(totalTimer.stop()); 00168 Teko_DEBUG_MSG("LSCPrecFact::buildPO TotalTime = " << totalTimer.totalElapsedTime(),2); 00169 00170 // solve using only one inversion of F 00171 return createBlockUpperTriInverseOp(U,invDiag,"LSC-Upper"); 00172 } 00173 } 00174 00176 void LSCPreconditionerFactory::initializeFromParameterList(const Teuchos::ParameterList & pl) 00177 { 00178 Teko_DEBUG_SCOPE("LSCPreconditionerFactory::initializeFromParameterList",10); 00179 00180 RCP<const InverseLibrary> invLib = getInverseLibrary(); 00181 00182 if(pl.isParameter("Is Symmetric")) 00183 isSymmetric_ = pl.get<bool>("Is Symmetric"); 00184 00185 std::string name = "Basic Inverse"; 00186 if(pl.isParameter("Strategy Name")) 00187 name = pl.get<std::string>("Strategy Name"); 00188 const Teuchos::ParameterEntry * pe = pl.getEntryPtr("Strategy Settings"); 00189 00190 // check for a mistake in input file 00191 if(name!="Basic Inverse" && pe==0) { 00192 RCP<Teuchos::FancyOStream> out = getOutputStream(); 00193 *out << "LSC Construction failed: "; 00194 *out << "Strategy \"" << name << "\" requires a \"Strategy Settings\" sublist" << std::endl; 00195 throw std::runtime_error("LSC Construction failed: Strategy Settings not set"); 00196 } 00197 00198 // get the parameter list to construct the strategy 00199 Teuchos::RCP<const Teuchos::ParameterList> stratPL = Teuchos::rcpFromRef(pl); 00200 if(pe!=0) 00201 stratPL = Teuchos::rcpFromRef(pl.sublist("Strategy Settings")); 00202 00203 // build the strategy object 00204 RCP<LSCStrategy> strategy = buildStrategy(name,*stratPL,invLib,getRequestHandler()); 00205 00206 // strategy could not be built 00207 if(strategy==Teuchos::null) { 00208 RCP<Teuchos::FancyOStream> out = getOutputStream(); 00209 *out << "LSC Construction failed: "; 00210 *out << "Strategy \"" << name << "\" could not be constructed" << std::endl; 00211 throw std::runtime_error("LSC Construction failed: Strategy could not be constructed"); 00212 } 00213 00214 strategy->setSymmetric(isSymmetric_); 00215 invOpsStrategy_ = strategy; 00216 } 00217 00219 Teuchos::RCP<Teuchos::ParameterList> LSCPreconditionerFactory::getRequestedParameters() const 00220 { 00221 return invOpsStrategy_->getRequestedParameters(); 00222 } 00223 00225 bool LSCPreconditionerFactory::updateRequestedParameters(const Teuchos::ParameterList & pl) 00226 { 00227 return invOpsStrategy_->updateRequestedParameters(pl); 00228 } 00229 00231 // Static members and methods 00233 00235 CloneFactory<LSCStrategy> LSCPreconditionerFactory::strategyBuilder_; 00236 00249 RCP<LSCStrategy> LSCPreconditionerFactory::buildStrategy(const std::string & name, 00250 const Teuchos::ParameterList & settings, 00251 const RCP<const InverseLibrary> & invLib, 00252 const RCP<RequestHandler> & rh) 00253 { 00254 Teko_DEBUG_SCOPE("LSCPreconditionerFactory::buildStrategy",10); 00255 00256 // initialize the defaults if necessary 00257 if(strategyBuilder_.cloneCount()==0) initializeStrategyBuilder(); 00258 00259 // request the preconditioner factory from the CloneFactory 00260 Teko_DEBUG_MSG("Building LSC strategy \"" << name << "\"",1); 00261 RCP<LSCStrategy> strategy = strategyBuilder_.build(name); 00262 00263 if(strategy==Teuchos::null) return Teuchos::null; 00264 00265 // now that inverse library has been set, 00266 // pass in the parameter list 00267 strategy->setRequestHandler(rh); 00268 strategy->initializeFromParameterList(settings,*invLib); 00269 00270 return strategy; 00271 } 00272 00286 void LSCPreconditionerFactory::addStrategy(const std::string & name,const RCP<Cloneable> & clone) 00287 { 00288 // initialize the defaults if necessary 00289 if(strategyBuilder_.cloneCount()==0) initializeStrategyBuilder(); 00290 00291 // add clone to builder 00292 strategyBuilder_.addClone(name,clone); 00293 } 00294 00296 void LSCPreconditionerFactory::initializeStrategyBuilder() 00297 { 00298 RCP<Cloneable> clone; 00299 00300 // add various strategies to the factory 00301 clone = rcp(new AutoClone<InvLSCStrategy>()); 00302 strategyBuilder_.addClone("Basic Inverse",clone); 00303 00304 // add various strategies to the factory 00305 clone = rcp(new AutoClone<PresLaplaceLSCStrategy>()); 00306 strategyBuilder_.addClone("Pressure Laplace",clone); 00307 } 00308 00309 } // end namespace NS 00310 } // end namespace Teko
1.7.4