src/eigsolv/HierarchicalBasisPrec.cpp

Go to the documentation of this file.
00001 #include "rlog/rlog.h"
00002 
00003 #include "Amesos_config.h"
00004 #include "Amesos.h"
00005 #include "Teuchos_ParameterList.hpp"
00006 
00007 #include "Epetra_LinearProblem.h"
00008 #include "Epetra_CrsMatrix.h"
00009 #include "Epetra_MultiVector.h"
00010 #include "Epetra_Map.h"
00011 #include "Epetra_Comm.h"
00012 #include "AztecOO.h"
00013 #include "AztecOO_Operator.h"
00014 
00015 #ifdef HAVE_AMESOS_SUPERLUDIST
00016 //commented out by Tizo
00017 //because of double definitions
00018 //in Tuechos_LAPACK_wrappers.h
00019 //#include <superlu_ddefs.h>
00020 //#include <supermatrix.h>
00021 #endif
00022 
00023 #include "OutputCapturer.h"
00024 #include "pbedefs.h"
00025 #include "myrlog.h"
00026 
00027 #include "BlockPCGSolver.h"
00028 #include "identityoperator.h"
00029 #include "diagonalpreconditioner.h"
00030 #include "BlockDiagOperator.h"
00031 
00032 #include "Ifpack.h"
00033 #include "Ifpack_IC.h"
00034 
00035 #include "HierarchicalBasisPrec.h"
00036 
00037 HierarchicalBasisPrec::HierarchicalBasisPrec(Epetra_CrsMatrix* Block11,
00038                                              Epetra_CrsMatrix* TMatrix,
00039                                              Epetra_CrsMatrix* NodeMatrix,
00040                                              Epetra_CrsMatrix* Block12,
00041                                              Epetra_CrsMatrix* Block22,
00042                                              const Epetra_Map& DMap,
00043                                              const Epetra_Map& RMap,
00044                                              Teuchos::ParameterList& params)
00045     : K11(Block11),
00046       TMatrix11(TMatrix),
00047       NodeMatrix11(NodeMatrix),
00048       K12(Block12),
00049       K22(Block22),
00050       DomainMap(DMap),
00051       RangeMap(RMap),
00052       Abase(0),
00053       ProblemL(0),
00054       solver22_(0),
00055       operator22_(0),
00056       operator11_(0),
00057       _Comm(Block11->Comm()),
00058       _useTranspose(false),
00059       isFactorized(false),
00060       params_(params)
00061 {
00062     pbe_start(110, "2-level preconditioner: construction");
00063 
00064     //**************************************************************************
00065     // Setup solver for (1,1)-block
00066 
00067     if (params_.get<string>("solver11") == "lu") {
00068         ProblemL = new Epetra_LinearProblem();
00069         ProblemL->SetOperator( K11 );
00070         Amesos Afactory;
00071         Abase = Afactory.Create( "Amesos_Superludist", *ProblemL );
00072         assert(Abase != 0);
00073         int ierr = Abase->SymbolicFactorization();
00074         assert(ierr == 0);
00075         ierr = Abase->NumericFactorization();
00076         assert(ierr == 0);
00077         isFactorized = true;
00078 
00079         /*
00080           ParamList = new Teuchos::ParameterList();
00081           ParamList->set( "Redistribute", false );
00082           ParamList->set( "AddZeroToDiag", false );
00083           Teuchos::ParameterList& SuperludistParams = ParamList->sublist("Superludist") ;
00084           SuperludistParams.set( "ReuseSymbolic", true );
00085           SuperludistParams.set( "MaxProcesses", 2 );
00086           Abase->SetParameters(*ParamList);
00087         */
00088     } else if (params_.get<string>("solver11") == "pcg_ml") {
00089         // pcg_ml is only suitable for H
00090         rAssert(TMatrix11 == 0 && NodeMatrix11 == 0);
00091         
00092         const int maxIterCG = 500;
00093         const int amg_H_smoother_degree = 2;
00094         operator11_ = new BlockPCGSolver(_Comm, K11, 1e-10, maxIterCG, 0);
00095         // Set an AMG preconditioner for PCG
00096         // param is the degree of polynomial for the smoother
00097         dynamic_cast<BlockPCGSolver*>(operator11_)->setAMGPreconditioner(1, amg_H_smoother_degree);
00098     } else if (params_.get<string>("solver11") == "ml") {
00099         OutputCapturer cap;
00100         cap.begin_capture();
00101         if ( TMatrix11 == 0 || NodeMatrix11 == 0 ) {
00102             operator11_ = new ML_Epetra::MultiLevelPreconditioner(*K11, params_.sublist("ml_params"), true);
00103         }
00104         else {
00105             operator11_ = new ML_Epetra::MultiLevelPreconditioner(*K11,
00106                                                                   *TMatrix11,
00107                                                                   *NodeMatrix11,
00108                                                                   params_.sublist("ml_params"),
00109                                                                   true);
00110         }
00111         cap.end_capture();
00112         cap.log("ML output:", RLOG_CHANNEL("debug"));
00113 
00114         ostringstream buf;
00115         buf << "Unused ML parameters:" << endl;
00116         dynamic_cast<ML_Epetra::MultiLevelPreconditioner*>(operator11_)->PrintUnused(buf);
00117         rDebug(buf.str().c_str());
00118     } else if (params_.get<string>("solver11") == "if") {
00119         // Approximately solve (1,1)-block by a singe application of a incomplete 
00120         // LDLT-factorisation.
00121     
00122         // allocates an IFPACK factory. No data is associated
00123         // to this object (only method Create()).
00124         Ifpack Factory;
00125     
00126         // Parameters for IFPACK
00127         Teuchos::ParameterList List;
00128 
00129         // Create the preconditioner. For valid PrecType values,
00130         // please check the documentation
00131 #if 0
00132         // FIXME: ICT is not a LDL^T method and cannot be used for indefinite matrices
00133         string PrecType = "ICT";
00134         List.set("fact: ict level-of-fill", 2.0);
00135 #endif        
00136 
00137 #if 0
00138         // FIXME: ICT is not a LDL^T method and cannot be used for indefinite matrices
00139         string PrecType = "ICT stand-alone";
00140         List.set("fact: ict level-of-fill", 2.0);
00141 #endif        
00142 
00143 #if 1
00144         // LDL^T
00145         string PrecType = "IC stand-alone";
00146         List.set("fact: level-of-fill", 1);
00147 #endif        
00148         
00149 #if 0
00150         string PrecType = "ILU stand-alone";
00151         List.set("fact: level-of-fill", 2);
00152 #endif        
00153         
00154         int OverlapLevel = 1; // must be >= 0. If Comm.NumProc() == 1,
00155                               // it is ignored.
00156         operator11_ = Factory.Create(PrecType, K11, OverlapLevel);
00157         assert(operator11_ != 0);
00158     
00159         dynamic_cast<Ifpack_Preconditioner*>(operator11_)->SetParameters(List);
00160     
00161         // Initialize the preconditioner. At this point the matrix must
00162         // have been FillComplete()'d, but actual values are ignored.
00163         dynamic_cast<Ifpack_Preconditioner*>(operator11_)->Initialize();
00164     
00165         // Builds the preconditioners, by looking for the values of
00166         // the matrix.
00167         dynamic_cast<Ifpack_Preconditioner*>(operator11_)->Compute();
00168         
00169         // Information about the preconditioner
00170         cout << *dynamic_cast<Ifpack_Preconditioner*>(operator11_);
00171         Ifpack_IC* ic_prec = dynamic_cast<Ifpack_IC*>(operator11_);
00172         if (ic_prec != 0)
00173             rInfo("#nonzeros of IF-preconditioner for K11: %d", ic_prec->NumGlobalNonzeros());
00174             
00175     } else {
00176         rExit("Unkown solver for (1,1)-block of hierarchical preconditioner: %s", 
00177               params_.get<string>("solver11").c_str());
00178     }
00179 
00180     //**************************************************************************
00181     // Setup solver for (2,2)-block
00182 
00183     if (params_.get<string>("solver22") == "gmres_incomplete_block_jacobi") {
00184         // CGS with block-Jacobi (with incomplete factorisation of the diagonal blocks)
00185         // preconditioner.
00186         solver22_ = new AztecOO();
00187         solver22_->SetUserMatrix(K22);
00188         solver22_->SetAztecOption(AZ_solver, AZ_cgs);
00189         solver22_->SetAztecOption(AZ_precond, AZ_dom_decomp);
00190         solver22_->SetAztecOption(AZ_subdomain_solve, AZ_ilu);
00191         solver22_->SetAztecOption(AZ_output, AZ_none);
00192         operator22_ = new AztecOO_Operator(solver22_, 2);
00193     } else if (params_.get<string>("solver22") == "pcg_jacobi") {
00194         // PCG with Point-Jacobi precondioner
00195         solver22_ = new AztecOO();
00196         solver22_->SetUserMatrix(K22);
00197         solver22_->SetAztecOption(AZ_solver, AZ_cg);
00198         solver22_->SetAztecOption(AZ_precond, AZ_Jacobi);
00199         solver22_->SetAztecOption(AZ_poly_ord, 1);
00200         solver22_->SetAztecOption(AZ_output, AZ_none);
00201         operator22_ = new AztecOO_Operator(solver22_, 2);
00202     } else if (params_.get<string>("solver22") == "diag") {
00203         // Diagonal preconditioner
00204         operator22_ = new DiagonalPreconditioner(*K22);
00205     } else if (params_.get<string>("solver22") == "blockdiag") {
00206         // Block Diagonal preconditioner
00207         operator22_ = new BlockDiagOperator(K22);
00208     } else if (params_.get<string>("solver22") == "none") {
00209         operator22_ = new IdentityOperator(K22->OperatorDomainMap(),
00210                                            K22->OperatorRangeMap(),
00211                                            K22->Comm());
00212     } else {
00213         rExit("Unkown solver for (2,2)-block of hierarchical preconditioner: %s",
00214               params_.get<string>("solver22").c_str());
00215     }
00216     pbe_stop(110);
00217 }
00218 
00219 HierarchicalBasisPrec::~HierarchicalBasisPrec() {
00220     if (Abase) 
00221         delete Abase;
00222     if (operator11_) 
00223         delete operator11_;
00224     if (solver22_)
00225         delete solver22_;
00226     if (operator22_)
00227         delete operator22_;
00228 }
00229 
00230 int HierarchicalBasisPrec::SetUseTranspose(bool UseTranspose) {
00231     int ierr = 0;
00232     _useTranspose = UseTranspose;
00233     return(ierr);
00234 }
00235 
00236 int HierarchicalBasisPrec::Apply(const Epetra_MultiVector& X, Epetra_MultiVector& Y) const {
00237     int ierr = 0;
00238 
00239     pbe_start(111, "2-level preconditioner: operator");
00240 
00241     if (!X.Map().SameAs(OperatorDomainMap()))
00242         EPETRA_CHK_ERR(-1);
00243     if (!Y.Map().SameAs(OperatorRangeMap()))
00244         EPETRA_CHK_ERR(-2);
00245     if (Y.NumVectors() != X.NumVectors())
00246         EPETRA_CHK_ERR(-3);
00247 
00248     Epetra_MultiVector X1(View, K11->DomainMap(), X.Values(), X.MyLength(), X.NumVectors());
00249     Epetra_MultiVector X2(View, K22->DomainMap(), X.Values() + X1.MyLength(), X.MyLength(), X.NumVectors());
00250     Epetra_MultiVector Y1(View, K11->RangeMap(), Y.Values(), Y.MyLength(), Y.NumVectors());
00251     Epetra_MultiVector Y2(View, K22->RangeMap(), Y.Values() + Y1.MyLength(), Y.MyLength(), Y.NumVectors());
00252 
00253     double *tt = new double[Y1.NumVectors()*Y1.MyLength()];
00254     Epetra_MultiVector Ytmp1(View, K11->RangeMap(), tt, Y1.MyLength(), Y1.NumVectors());
00255     K11->Multiply(false, X1, Y1);
00256     K12->Multiply(false, X2, Ytmp1);
00257     Y1.Update(1.0, Ytmp1, 1.0);
00258     delete[] tt;
00259 
00260     tt = new double[Y2.NumVectors()*Y2.MyLength()];
00261     Epetra_MultiVector Ytmp2(View, K22->RangeMap(), tt, Y2.MyLength(), Y2.NumVectors());
00262     K12->Multiply(true, X1, Ytmp2);
00263     K22->Multiply(false, X2, Y2);
00264     Y2.Update(1.0, Ytmp2, 1.0);
00265     delete[] tt;
00266     pbe_stop(111);
00267 
00268     return(ierr);
00269 }
00270 
00271 int HierarchicalBasisPrec::ApplyInverse(const Epetra_MultiVector& X, Epetra_MultiVector& Y) const {
00272     int ierr = 0;
00273 
00274     //We suppose :
00275     //K11->FillComplete(map1, map1);
00276     //K12->FillComplete(map2, map1);
00277     //K22->FillComplete(map2, map2);
00278     //map of X and Y is the ordered composition of (map1,map2)
00279 
00280     if (!X.Map().SameAs(OperatorDomainMap()))
00281         EPETRA_CHK_ERR(-1);
00282     if (!Y.Map().SameAs(OperatorRangeMap()))
00283         EPETRA_CHK_ERR(-2);
00284     if (Y.NumVectors() != X.NumVectors())
00285         EPETRA_CHK_ERR(-3);
00286 
00287     pbe_start(112, "2-level preconditioner: application");
00288 
00289     Epetra_MultiVector X1(View, K11->RangeMap(), X.Values(), X.MyLength(), X.NumVectors());
00290     Epetra_MultiVector X2(View, K22->RangeMap(), X.Values() + X1.MyLength(), X.MyLength(), X.NumVectors());
00291     Epetra_MultiVector Y1(View, K11->DomainMap(), Y.Values(), Y.MyLength(), Y.NumVectors());
00292     Epetra_MultiVector Y2(View, K22->DomainMap(), Y.Values() + Y1.MyLength(), Y.MyLength(), Y.NumVectors());
00293     Epetra_MultiVector Xtmp1(K11->RangeMap(), X.NumVectors(), false);
00294     Epetra_MultiVector Xtmp2(K22->RangeMap(), X.NumVectors(), false);
00295 
00296     //  This is necessary only in the case X and Y points to the same address in memory.
00297     Epetra_MultiVector* X11;
00298     if (X.Values() == Y.Values()) {
00299         X11 = new Epetra_MultiVector(X1);
00300     }
00301     else {
00302         X11 = &X1;
00303     }
00304 
00305     //
00306     //  Solve K11*Y1 = X1
00307     //
00308     pbe_start(113, "2-level preconditioner: (1,1)-solve");
00309     if (params_.get<string>("solver11") == "lu") {
00310         assert(Abase != 0);
00311         assert(isFactorized);
00312         ProblemL->SetLHS( &Y1 );
00313         ProblemL->SetRHS( &X1 );
00314         EPETRA_CHK_ERR( Abase->Solve(  ) );
00315     } else if (params_.get<string>("solver11") == "pcg_ml")  {
00316         operator11_->ApplyInverse(X1, Y1);
00317     } else if (params_.get<string>("solver11") == "ml")  {
00318         operator11_->ApplyInverse(X1, Y1);
00319     } else if (params_.get<string>("solver11") == "if")  {
00320         operator11_->ApplyInverse(X1, Y1);
00321     } else {
00322         assert(false);
00323     }
00324     pbe_stop(113);
00325 
00326     //
00327     // Solve K22*Y2 = X2 - K12^T * Y1
00328     //
00329     pbe_start(115, "2-level preconditioner: off-diagonal multiply");
00330     K12->Multiply(true, Y1, Xtmp2);
00331     pbe_stop(115);
00332     Xtmp2.Update(1.0, X2, -1.0);
00333     pbe_start(114, "2-level preconditioner: (2,2)-solve");
00334     operator22_->ApplyInverse(Xtmp2, Y2);
00335     pbe_stop(114);
00336 
00337     //
00338     // Solve K11*Y1 = X1 - K12*Y2
00339     //
00340     pbe_start(115, "2-level preconditioner: (1,2)/(2,1)-mult");
00341     K12->Multiply(false, Y2, Xtmp1);
00342     pbe_stop(115);
00343     Xtmp1.Update(1.0, X1, -1.0);
00344     pbe_start(113, "2-level preconditioner: (1,1)-solve");
00345     if (params_.get<string>("solver11") == "lu") {
00346         ProblemL->SetLHS( &Y1 );
00347         ProblemL->SetRHS( &Xtmp1 );
00348         EPETRA_CHK_ERR( Abase->Solve(  ) );
00349     } else if (params_.get<string>("solver11") == "pcg_ml")  {
00350         operator11_->ApplyInverse(Xtmp1, Y1);
00351     } else if (params_.get<string>("solver11") == "ml")  {
00352         operator11_->ApplyInverse(Xtmp1, Y1);
00353     } else if (params_.get<string>("solver11") == "if")  {
00354         operator11_->ApplyInverse(X1, Y1);
00355     } else {
00356         assert(false);
00357     }
00358 
00359     if (X11 != &X1)
00360         delete X11;
00361 
00362     pbe_stop(113);
00363     pbe_stop(112);
00364 
00365     return(ierr);
00366 }
00367 
00368 double HierarchicalBasisPrec::NormInf() const {
00369     cout << "Not implemented yet !!!!!!!!!!" << endl;
00370     return(1);
00371 }
00372 
00373 const char* HierarchicalBasisPrec::Label() const {
00374     return "Hierarchical preconditioner";
00375 }
00376 
00377 bool HierarchicalBasisPrec::UseTranspose() const {
00378     return(false);
00379 }
00380 
00381 bool HierarchicalBasisPrec::HasNormInf() const {
00382     return(false);
00383 }
00384 
00385 const Epetra_Comm& HierarchicalBasisPrec::Comm() const {
00386     return(_Comm);
00387 }
00388 
00389 const Epetra_Map& HierarchicalBasisPrec::OperatorDomainMap() const {
00390     return(DomainMap);
00391 }
00392 
00393 const Epetra_Map& HierarchicalBasisPrec::OperatorRangeMap() const {
00394     return(RangeMap);
00395 }

Generated on Fri Oct 26 13:35:11 2007 for FEMAXX (Finite Element Maxwell Eigensolver) by  doxygen 1.4.7