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
00017
00018
00019
00020
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
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
00081
00082
00083
00084
00085
00086
00087
00088 } else if (params_.get<string>("solver11") == "pcg_ml") {
00089
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
00096
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
00120
00121
00122
00123
00124 Ifpack Factory;
00125
00126
00127 Teuchos::ParameterList List;
00128
00129
00130
00131 #if 0
00132
00133 string PrecType = "ICT";
00134 List.set("fact: ict level-of-fill", 2.0);
00135 #endif
00136
00137 #if 0
00138
00139 string PrecType = "ICT stand-alone";
00140 List.set("fact: ict level-of-fill", 2.0);
00141 #endif
00142
00143 #if 1
00144
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;
00155
00156 operator11_ = Factory.Create(PrecType, K11, OverlapLevel);
00157 assert(operator11_ != 0);
00158
00159 dynamic_cast<Ifpack_Preconditioner*>(operator11_)->SetParameters(List);
00160
00161
00162
00163 dynamic_cast<Ifpack_Preconditioner*>(operator11_)->Initialize();
00164
00165
00166
00167 dynamic_cast<Ifpack_Preconditioner*>(operator11_)->Compute();
00168
00169
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
00182
00183 if (params_.get<string>("solver22") == "gmres_incomplete_block_jacobi") {
00184
00185
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
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
00204 operator22_ = new DiagonalPreconditioner(*K22);
00205 } else if (params_.get<string>("solver22") == "blockdiag") {
00206
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
00275
00276
00277
00278
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
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
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
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
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 }