Teko Version of the Day
Teko_LSCPreconditionerFactory.cpp
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
 All Classes Files Functions Variables