Go to the documentation of this file.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 "PlayaPCGSolver.hpp"
00044 #include "PlayaOut.hpp"
00045 #include "PlayaTabs.hpp"
00046 #include "PlayaLinearCombinationImpl.hpp"
00047 #include "PlayaSimpleComposedOpImpl.hpp"
00048 #include <iomanip>
00049
00050 using std::setw;
00051
00052 namespace Playa
00053 {
00054
00055 SolverState<double> PCGSolver::solve(const LinearOperator<double>& A,
00056 const Vector<double>& b,
00057 Vector<double>& x) const
00058 {
00059 if (precFactory_.ptr().get() == 0)
00060 {
00061 return solveUnprec(A, b, x);
00062 }
00063 else
00064 {
00065 SolverState<double> rtn;
00066 Preconditioner<double> prec = precFactory_.createPreconditioner(A);
00067 if (prec.isIdentity())
00068 {
00069 rtn = solveUnprec(A, b, x);
00070 }
00071 else if (prec.isTwoSided())
00072 {
00073 LinearOperator<double> P = prec.left();
00074 LinearOperator<double> Q = prec.right();
00075 LinearOperator<double> PAQ = P*A*Q;
00076 Vector<double> Pb = P*b;
00077 Vector<double> y;
00078 rtn = solveUnprec(PAQ, Pb, y);
00079 x = Q*y;
00080 }
00081 else if (prec.hasRight())
00082 {
00083 LinearOperator<double> Q = prec.right();
00084 LinearOperator<double> AQ = A*Q;
00085 Vector<double> y;
00086 rtn = solveUnprec(AQ, b, y);
00087 x = Q*y;
00088 }
00089 else if (prec.hasLeft())
00090 {
00091 LinearOperator<double> P = prec.left();
00092 LinearOperator<double> PA = P*A;
00093 Vector<double> Pb = P*b;
00094 rtn = solveUnprec(PA, Pb, x);
00095 }
00096 else
00097 {
00098 TEUCHOS_TEST_FOR_EXCEPTION(true, std::runtime_error,
00099 "Inconsistent preconditioner state "
00100 "in PGCSolver::solve()");
00101 }
00102 return rtn;
00103 }
00104 }
00105
00106 SolverState<double> PCGSolver::solveUnprec(const LinearOperator<double>& A,
00107 const Vector<double>& b,
00108 Vector<double>& x) const
00109 {
00110 Tabs tab0;
00111 const ParameterList& params = parameters();
00112 int verb = 0;
00113 if (params.isParameter("Verbosity"))
00114 {
00115 verb = getParameter<int>(params, "Verbosity");
00116 }
00117
00118 int maxIters = getParameter<int>(params, "Max Iterations");
00119 double tol = getParameter<double>(params, "Tolerance");
00120
00121
00122 PLAYA_ROOT_MSG1(verb, tab0 << "Playa CG Solver");
00123 Tabs tab1;
00124 PLAYA_ROOT_MSG2(verb, tab0);
00125 PLAYA_ROOT_MSG2(verb, tab1 << "Verbosity " << verb);
00126 PLAYA_ROOT_MSG2(verb, tab1 << "Max Iters " << maxIters);
00127 PLAYA_ROOT_MSG2(verb, tab1 << "Tolerance " << tol);
00128
00129
00130 if (x.ptr().get()==0) x = b.copy();
00131
00132 Vector<double> r = b - A*x;
00133 Vector<double> p = r.copy();
00134 double bNorm = b.norm2();
00135 PLAYA_ROOT_MSG2(verb, tab1 << "Problem size: " << b.space().dim());
00136 PLAYA_ROOT_MSG2(verb, tab1 << "||rhs|| " << bNorm);
00137
00138
00139 SolverState<double> rtn;
00140 bool converged = false;
00141 bool shortcut = false;
00142
00143
00144 if (bNorm==0.0)
00145 {
00146 PLAYA_ROOT_MSG2(verb, tab1 << "RHS is zero!");
00147 rtn = SolverState<double>(SolveConverged, "Woo-hoo! Zero RHS shortcut",
00148 0, 0.0);
00149 shortcut = true;
00150 }
00151
00152 double rNorm = 0.0;
00153 double rtr = r*r;
00154
00155 if (!shortcut)
00156 {
00157 PLAYA_ROOT_MSG2(verb, tab1 << endl << tab1 << "CG Loop");
00158
00159 for (int k=0; k<maxIters; k++)
00160 {
00161 Tabs tab2;
00162 Vector<double> Ap = A*p;
00163 double alpha = rtr/(p*Ap);
00164 x += alpha*p;
00165 r -= alpha*Ap;
00166 double rtrNew = r*r;
00167 rNorm = sqrt(rtrNew);
00168 PLAYA_ROOT_MSG2(verb, tab2 << "iter=" << setw(10)
00169 << k << setw(20) << "||r||=" << rNorm);
00170
00171 if (rNorm < bNorm*tol)
00172 {
00173 rtn = SolverState<double>(SolveConverged, "Woo-hoo!",
00174 k, rNorm);
00175 converged = true;
00176 break;
00177 }
00178 double beta = rtrNew/rtr;
00179 rtr = rtrNew;
00180 p = r + beta*p;
00181 }
00182 }
00183
00184 if (!converged && !shortcut)
00185 {
00186 rtn = SolverState<double>(SolveFailedToConverge,
00187 "CG failed to converge",
00188 maxIters, rNorm);
00189 }
00190
00191 PLAYA_ROOT_MSG2(verb, tab0 << endl
00192 << tab0 << "CG finished with status "
00193 << rtn.stateDescription());
00194 return rtn;
00195 }
00196
00197
00198 }