00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043 #include "PlayaAztecSolver.hpp"
00044 #include "PlayaEpetraVector.hpp"
00045 #include "PlayaEpetraMatrix.hpp"
00046 #include "Ifpack_Preconditioner.h"
00047 #include "Ifpack.h"
00048 #include "EpetraPlayaOperator.hpp"
00049 #include "Teuchos_basic_oblackholestream.hpp"
00050
00051
00052
00053 #ifndef HAVE_TEUCHOS_EXPLICIT_INSTANTIATION
00054 #include "PlayaVectorImpl.hpp"
00055 #include "PlayaLinearOperatorImpl.hpp"
00056 #include "PlayaLinearSolverImpl.hpp"
00057 #endif
00058
00059 #ifdef HAVE_ML
00060 #include "ml_include.h"
00061 #include "ml_epetra_utils.h"
00062 #include "ml_epetra_operator.h"
00063 #include "ml_aztec_utils.h"
00064 #include "ml_MultiLevelPreconditioner.h"
00065 using namespace ML_Epetra;
00066 #else
00067 #error blarf
00068 #endif
00069
00070 using namespace Playa;
00071 using namespace Teuchos;
00072
00073
00074 AztecSolver::AztecSolver(const ParameterList& params)
00075 : LinearSolverBase<double>(params),
00076 options_(AZ_OPTIONS_SIZE),
00077 parameters_(AZ_PARAMS_SIZE),
00078 useML_(false),
00079 useIfpack_(false),
00080 useUserPrec_(false),
00081 aztec_recursive_iterate_(false),
00082 precParams_(),
00083 userPrec_(),
00084 aztec_status(AZ_STATUS_SIZE),
00085 aztec_proc_config(AZ_PROC_SIZE)
00086 {
00087 initParamMap();
00088
00089
00090 AZ_defaults((int*) &(options_[0]), (double*) &(parameters_[0]));
00091
00092
00093
00094 ParameterList::ConstIterator iter;
00095 for (iter=params.begin(); iter != params.end(); ++iter)
00096 {
00097 const std::string& name = params.name(iter);
00098 const ParameterEntry& entry = params.entry(iter);
00099
00100 if (entry.isList())
00101 {
00102 if (name=="Preconditioner")
00103 {
00104 precParams_ = params.sublist("Preconditioner");
00105 TEUCHOS_TEST_FOR_EXCEPTION(!precParams_.isParameter("Type"), std::runtime_error,
00106 "preconditioner type not specified in parameter list "
00107 << precParams_);
00108 if (precParams_.get<string>("Type") == "ML")
00109 {
00110 useML_ = true;
00111 }
00112 else if (precParams_.get<string>("Type") == "Ifpack")
00113 {
00114 useIfpack_ = true;
00115 }
00116 else if (precParams_.get<string>("Type") == "User")
00117 {
00118 useUserPrec_ = true;
00119 }
00120 continue;
00121 }
00122 }
00123
00124
00125 if (paramMap().find(name) == paramMap().end()) continue;
00126
00127
00128 int aztecCode = paramMap()[name];
00129
00130 if (name=="Recursive Iterate")
00131 {
00132 if (getValue<int>(entry))
00133 aztec_recursive_iterate_ = true;
00134 else
00135 aztec_recursive_iterate_ = false;
00136 continue;
00137 }
00138
00139
00140
00141
00142
00143
00144
00145
00146 if (entry.isType<string>())
00147 {
00148 std::string val = getValue<string>(entry);
00149 TEUCHOS_TEST_FOR_EXCEPTION(paramMap().find(val) == paramMap().end(),
00150 std::runtime_error,
00151 "Aztec solver ctor: [" << val << "] is not a "
00152 "valid Aztec option value");
00153 int optionVal = paramMap()[val];
00154 options_[aztecCode] = optionVal;
00155 }
00156 else if (entry.isType<int>())
00157 {
00158 int val = getValue<int>(entry);
00159 options_[aztecCode] = val;
00160 if (name=="Verbosity") setVerb(val);
00161 }
00162 else if (entry.isType<double>())
00163 {
00164 double val = getValue<double>(entry);
00165 parameters_[aztecCode] = val;
00166 }
00167 }
00168 }
00169
00170
00171 AztecSolver::AztecSolver(const Teuchos::map<int, int>& aztecOptions,
00172 const Teuchos::map<int, double>& aztecParameters)
00173 : LinearSolverBase<double>(ParameterList()),
00174 options_(AZ_OPTIONS_SIZE),
00175 parameters_(AZ_PARAMS_SIZE),
00176 useML_(false),
00177 useIfpack_(false),
00178 useUserPrec_(false),
00179 aztec_recursive_iterate_(false),
00180 precParams_(),
00181 userPrec_(),
00182 aztec_status(AZ_STATUS_SIZE),
00183 aztec_proc_config(AZ_PROC_SIZE)
00184 {
00185 if (aztecOptions.find(AZ_recursive_iterate) != aztecOptions.end())
00186 {
00187 aztec_recursive_iterate_ = true;
00188 }
00189
00190
00191 AZ_defaults((int*) &(options_[0]), (double*) &(parameters_[0]));
00192
00193
00194 map<int, int>::const_iterator opIter;
00195 for (opIter=aztecOptions.begin(); opIter!=aztecOptions.end(); opIter++)
00196 {
00197 int opKey = opIter->first;
00198 if (opKey==AZ_recursive_iterate) continue;
00199 int opValue = opIter->second;
00200 options_[opKey] = opValue;
00201 }
00202
00203
00204 map<int, double>::const_iterator parIter;
00205 for (parIter=aztecParameters.begin(); parIter!=aztecParameters.end();
00206 parIter++)
00207 {
00208 int parKey = parIter->first;
00209 double parValue = parIter->second;
00210 parameters_[parKey] = parValue;
00211 }
00212 }
00213
00214
00215 void AztecSolver::updateTolerance(const double& tol)
00216 {
00217 parameters_[AZ_tol] = tol;
00218 }
00219
00220 SolverState<double> AztecSolver::solve(const LinearOperator<double>& op,
00221 const Vector<double>& rhs,
00222 Vector<double>& soln) const
00223 {
00224 RCP<ostream> out;
00225 if (verb()==0)
00226 {
00227 out = rcp(new oblackholestream());
00228 }
00229 else
00230 {
00231 out = rcp(&Out::os(), false);
00232 }
00233 RCP<MultiLevelPreconditioner> mlPrec;
00234 RCP<Ifpack_Preconditioner> ifpackPrec;
00235 RCP<Epetra_Operator> prec;
00236
00237 Playa::Vector<double> bCopy = rhs.copy();
00238 Playa::Vector<double> xCopy = rhs.copy();
00239
00240 if (verb() > 4)
00241 {
00242 *out << "rhs=" << bCopy << std::endl;
00243 }
00244
00245 Epetra_Vector* b = EpetraVector::getConcretePtr(bCopy);
00246 Epetra_Vector* x = EpetraVector::getConcretePtr(xCopy);
00247
00248 Epetra_CrsMatrix& A = EpetraMatrix::getConcrete(op);
00249
00250 AztecOO aztec(&A, x, b);
00251
00252 aztec.SetAllAztecOptions((int*) &(options_[0]));
00253 aztec.SetAllAztecParams((double*) &(parameters_[0]));
00254 aztec.SetOutputStream(*out);
00255 aztec.SetErrorStream(*out);
00256
00257 int maxIters = options_[AZ_max_iter];
00258 double tol = parameters_[AZ_tol];
00259
00260 if (useML_)
00261 {
00262 std::string precType = precParams_.get<string>("Problem Type");
00263 ParameterList mlParams;
00264 ML_Epetra::SetDefaults(precType, mlParams);
00265
00266
00267
00268 ParameterList::ConstIterator iter;
00269 ParameterList mlSettings = precParams_.sublist("ML Settings");
00270 for (iter=mlSettings.begin(); iter!=mlSettings.end(); ++iter)
00271 {
00272 const std::string& name = mlSettings.name(iter);
00273 const ParameterEntry& entry = mlSettings.entry(iter);
00274 mlParams.setEntry(name, entry);
00275 }
00276
00277 mlPrec = rcp(new ML_Epetra::MultiLevelPreconditioner(A, mlParams));
00278 prec = rcp_dynamic_cast<Epetra_Operator>(mlPrec);
00279 }
00280 else if (useIfpack_)
00281 {
00282 Ifpack precFactory;
00283 int overlap = precParams_.get<int>("Overlap");
00284 std::string precType = precParams_.get<string>("Prec Type");
00285
00286 ParameterList ifpackParams = precParams_.sublist("Ifpack Settings");
00287
00288 ifpackPrec = rcp(precFactory.Create(precType, &A, overlap));
00289 prec = rcp_dynamic_cast<Epetra_Operator>(ifpackPrec);
00290 ifpackPrec->SetParameters(ifpackParams);
00291 ifpackPrec->Initialize();
00292 ifpackPrec->Compute();
00293 }
00294 else if (useUserPrec_)
00295 {
00296 TEUCHOS_TEST_FOR_EXCEPT(userPrec_.get() == 0);
00297 prec = userPrec_;
00298 }
00299
00300
00301 if (prec.get() != 0) aztec.SetPrecOperator(prec.get());
00302
00303 aztec.CheckInput();
00304
00305
00306
00307 if (aztec_recursive_iterate_)
00308 {
00309 aztec.recursiveIterate(maxIters, tol);
00310 }
00311 else
00312 {
00313 aztec.Iterate(maxIters, tol);
00314 }
00315
00316 soln = xCopy;
00317
00318 const double* status = aztec.GetAztecStatus();
00319 SolverStatusCode state = SolveCrashed;
00320
00321 std::string msg;
00322 switch((int) status[AZ_why])
00323 {
00324 case AZ_normal:
00325 state = SolveConverged;
00326 msg = "converged";
00327 break;
00328 case AZ_param:
00329 state = SolveCrashed;
00330 msg = "failed: parameter not available";
00331 break;
00332 case AZ_breakdown:
00333 state = SolveCrashed;
00334 msg = "failed: numerical breakdown";
00335 break;
00336 case AZ_loss:
00337 state = SolveCrashed;
00338 msg = "failed: numerical loss of precision";
00339 break;
00340 case AZ_ill_cond:
00341 state = SolveCrashed;
00342 msg = "failed: ill-conditioned Hessenberg matrix in GMRES";
00343 break;
00344 case AZ_maxits:
00345 state = SolveFailedToConverge;
00346 msg = "failed: maxiters reached without converged";
00347 break;
00348 }
00349 SolverState<double> rtn(state, "Aztec solver " + msg, (int) status[AZ_its],
00350 status[AZ_r]);
00351 return rtn;
00352 }
00353
00354
00355 void AztecSolver::setUserPrec(const LinearOperator<double>& P,
00356 const LinearSolver<double>& pSolver)
00357 {
00358 if (useUserPrec_)
00359 {
00360 userPrec_ = rcp(new Epetra::Epetra_PlayaOperator(P, pSolver));
00361 }
00362 else
00363 {
00364 TEUCHOS_TEST_FOR_EXCEPTION(!useUserPrec_, std::runtime_error,
00365 "Attempt to set user-defined preconditioner "
00366 "after another preconditioner has been specified");
00367 }
00368 }
00369
00370 void AztecSolver::initParamMap()
00371 {
00372 static bool first = true;
00373 if (first)
00374 {
00375 paramMap()["Method"]=AZ_solver;
00376 paramMap()["CG"]=AZ_cg;
00377 paramMap()["GMRES"]=AZ_gmres;
00378 paramMap()["CGS"]=AZ_cgs;
00379 paramMap()["TFQMR"]=AZ_tfqmr;
00380 paramMap()["BICGSTAB"]=AZ_bicgstab;
00381 paramMap()["Direct"]=AZ_lu;
00382 paramMap()["Precond"]=AZ_precond;
00383 paramMap()["None"]=AZ_none;
00384 paramMap()["Jacobi"]=AZ_Jacobi;
00385 paramMap()["Neumann Series"]=AZ_Neumann;
00386 paramMap()["Symmetric Gauss-Seidel"]=AZ_sym_GS;
00387 paramMap()["Least-Squares Polynomial"]=AZ_ls;
00388 paramMap()["Recursive Iterate"]=AZ_recursive_iterate;
00389 paramMap()["Domain Decomposition"]=AZ_dom_decomp;
00390 paramMap()["Subdomain Solver"]=AZ_subdomain_solve;
00391 paramMap()["Approximate Sparse LU"]=AZ_lu;
00392 paramMap()["Saad ILUT"]=AZ_ilut;
00393 paramMap()["ILU"]=AZ_ilu;
00394 paramMap()["RILU"]=AZ_rilu;
00395 paramMap()["Block ILU"]=AZ_bilu;
00396 paramMap()["Incomplete Cholesky"]=AZ_icc;
00397 paramMap()["Residual Scaling"]=AZ_conv;
00398 paramMap()["Initial"]=AZ_r0;
00399 paramMap()["RHS"]=AZ_rhs;
00400 paramMap()["Matrix"]=AZ_Anorm;
00401 paramMap()["Solution"]=AZ_sol;
00402 paramMap()["No Scaling"]=AZ_noscaled;
00403 paramMap()["Verbosity"]=AZ_output;
00404 paramMap()["All"]=AZ_all;
00405 paramMap()["Silent"]=AZ_none;
00406 paramMap()["Warnings"]=AZ_warnings;
00407 paramMap()["Final Residual"]=AZ_last;
00408 paramMap()["Graph Fill"]=AZ_graph_fill;
00409 paramMap()["Max Iterations"]=AZ_max_iter;
00410 paramMap()["Polynomial Order"]=AZ_poly_ord;
00411 paramMap()["Overlap"]=AZ_overlap;
00412 paramMap()["Overlap Type"]=AZ_type_overlap;
00413 paramMap()["Standard"]=AZ_standard;
00414 paramMap()["Symmetric"]=AZ_symmetric;
00415 paramMap()["Restart Size"]=AZ_kspace;
00416 paramMap()["Reorder ILU"]=AZ_reorder;
00417 paramMap()["Keep Factorization"]=AZ_keep_info;
00418 paramMap()["GMRES Orthogonalization"]=AZ_orthog;
00419 paramMap()["Classical Gram-Schmidt"]=AZ_classic;
00420 paramMap()["Modified Gram-Schmidt"]=AZ_modified;
00421 paramMap()["Auxiliary Vector"]=AZ_aux_vec;
00422 paramMap()["Residual"]=AZ_resid;
00423 paramMap()["Random"]=AZ_rand;
00424 paramMap()["Tolerance"]=AZ_tol;
00425 paramMap()["Drop Tolerance"]=AZ_drop;
00426 paramMap()["Fill Ratio"]=AZ_ilut_fill;
00427 paramMap()["Damping"]=AZ_omega;
00428
00429 first = false;
00430 }
00431 }
00432
00433