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 #ifndef PLAYA_BICGSTABSOLVER_IMPL_HPP
00043 #define PLAYA_BICGSTABSOLVER_IMPL_HPP
00044
00045 #include "PlayaBICGSTABSolverDecl.hpp"
00046 #include "PlayaLinearCombinationImpl.hpp"
00047 #include "PlayaSimpleScaledOpDecl.hpp"
00048 #include "PlayaSimpleComposedOpDecl.hpp"
00049
00050 #ifndef HAVE_TEUCHOS_EXPLICIT_INSTANTIATION
00051 #include "PlayaLinearOperatorImpl.hpp"
00052 #include "PlayaLinearSolverBaseImpl.hpp"
00053 #include "PlayaSimpleScaledOpImpl.hpp"
00054 #include "PlayaSimpleComposedOpImpl.hpp"
00055 #include "PlayaSimpleTransposedOpImpl.hpp"
00056 #endif
00057
00058
00059
00060 namespace Playa
00061 {
00062 using namespace Teuchos;
00063
00064
00065
00066 template <class Scalar> inline
00067 BICGSTABSolver<Scalar>
00068 ::BICGSTABSolver(const ParameterList& params)
00069 : KrylovSolver<Scalar>(params) {;}
00070
00071
00072 template <class Scalar> inline
00073 BICGSTABSolver<Scalar>::BICGSTABSolver(const ParameterList& params,
00074 const PreconditionerFactory<Scalar>& precond)
00075 : KrylovSolver<Scalar>(params, precond) {;}
00076
00077
00078 template <class Scalar> inline
00079 void BICGSTABSolver<Scalar>::print(std::ostream& os) const
00080 {
00081 os << description() << "[" << std::endl;
00082 os << this->parameters() << std::endl;
00083 os << "]" << std::endl;
00084 }
00085
00086
00087 template <class Scalar> inline
00088 SolverState<Scalar> BICGSTABSolver<Scalar>
00089 ::solveUnprec(const LinearOperator<Scalar>& op,
00090 const Vector<Scalar>& b,
00091 Vector<Scalar>& soln) const
00092 {
00093 int maxiters = this->getMaxiters();
00094 Scalar tol = this->getTol();
00095 int verbosity = this->verb();
00096
00097 Scalar normOfB = sqrt(b.dot(b));
00098
00099
00100 if (normOfB < tol)
00101 {
00102 soln = b.space().createMember();
00103 soln.zero();
00104 return SolverState<Scalar>(SolveConverged, "RHS was zero", 0, 0.0);
00105 }
00106
00107
00108 Vector<Scalar> x0 = b.copy();
00109 Vector<Scalar> r0 = b.space().createMember();
00110 Vector<Scalar> tmp = b.space().createMember();
00111
00112
00113 op.apply(x0, tmp);
00114 r0 = b - tmp;
00115
00116 if (sqrt(r0.dot(r0)) < tol*normOfB)
00117 {
00118 soln = x0;
00119 return SolverState<Scalar>(SolveConverged, "initial resid was zero",
00120 0, 0.0);
00121 }
00122
00123 Vector<Scalar> p0 = r0.copy();
00124
00125 Vector<Scalar> r0Hat = r0.copy();
00126 Vector<Scalar> xMid = b.space().createMember();
00127 Vector<Scalar> rMid = b.space().createMember();
00128 Vector<Scalar> ArMid = b.space().createMember();
00129 Vector<Scalar> x = b.space().createMember();
00130 Vector<Scalar> r = b.space().createMember();
00131 Vector<Scalar> s = b.space().createMember();
00132 Vector<Scalar> ap = b.space().createMember();
00133
00134 int myRank = MPIComm::world().getRank();
00135
00136 Scalar resid = -1.0;
00137
00138 for (int k=1; k<=maxiters; k++)
00139 {
00140
00141 op.apply(p0, ap);
00142
00143 Scalar den = ap.dot(r0Hat);
00144 if (Utils::chop(sqrt(fabs(den))/normOfB)==0)
00145 {
00146 SolverState<Scalar> rtn(SolveCrashed,
00147 "BICGSTAB failure mode 1", k, resid);
00148 return rtn;
00149 }
00150
00151 Scalar a0 = r0.dot(r0Hat)/den;
00152
00153 xMid = x0 + a0*p0;
00154
00155
00156 rMid = r0 - a0*ap;
00157
00158
00159
00160 Scalar resid = rMid.norm2()/normOfB;
00161 if (resid < tol)
00162 {
00163 soln = xMid;
00164 SolverState<Scalar> rtn(SolveConverged, "yippee!!", k, resid);
00165 return rtn;
00166 }
00167
00168
00169 op.apply(rMid, ArMid);
00170
00171 den = ArMid.dot(ArMid);
00172 if (Utils::chop(sqrt(fabs(den))/normOfB)==0)
00173 {
00174 SolverState<Scalar> rtn(SolveCrashed,
00175 "BICGSTAB failure mode 2", k, resid);
00176 return rtn;
00177 }
00178
00179 Scalar w = rMid.dot(ArMid)/den;
00180
00181 x = xMid + w*rMid;
00182
00183
00184 r = rMid - w*ArMid;
00185
00186
00187
00188 resid = sqrt(r.dot(r))/normOfB;
00189 if (resid < tol)
00190 {
00191 soln = x;
00192 SolverState<Scalar> rtn(SolveConverged, "yippee!!", k, resid);
00193 return rtn;
00194 }
00195
00196 den = w*(r0.dot(r0Hat));
00197 if (Utils::chop(sqrt(fabs(den))/normOfB)==0)
00198 {
00199 SolverState<Scalar> rtn(SolveCrashed,
00200 "BICGSTAB failure mode 3", k, resid);
00201 return rtn;
00202 }
00203 Scalar beta = a0*(r.dot(r0Hat))/den;
00204
00205 s = p0 - w*ap;
00206 p0 = r + beta*s;
00207
00208
00209
00210
00211 r0 = r.copy();
00212 x0 = x.copy();
00213
00214 if (myRank==0 && verbosity > 1 )
00215 {
00216 Out::os() << "BICGSTAB: iteration=";
00217 Out::os().width(8);
00218 Out::os() << k;
00219 Out::os().width(20);
00220 Out::os() << " resid=" << resid << std::endl;
00221 }
00222 }
00223
00224 SolverState<Scalar> rtn(SolveFailedToConverge,
00225 "BICGSTAB failed to converge",
00226 maxiters, resid);
00227 return rtn;
00228 }
00229
00230
00231 }
00232
00233 #endif