00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <BaseVector.hpp>
00022 #include <BaseMatrix.hpp>
00023
00024 #include <Vector.hpp>
00025 #include <SparseMatrix.hpp>
00026
00027 #include <KrylovSolver.hpp>
00028
00029 #include <Preconditioner.hpp>
00030
00031 #include <DiagPrecond.hpp>
00032 #include <IncompleteCholeskiFactorization.hpp>
00033 #include <IdentityPrecond.hpp>
00034
00035 #include <SpectralFEMPreconditioner.hpp>
00036
00037 #include <PDESystem.hpp>
00038
00039 #include <ConjugateGradient.hpp>
00040 #include <BiConjugateGradient.hpp>
00041 #include <BiConjugateGradientStabilized.hpp>
00042
00043 #include <FGMRES.hpp>
00044 #include <GMRES.hpp>
00045
00046 #include <PETScKrylovSolver.hpp>
00047
00048 #include <MultiGrid.hpp>
00049
00050 #include <Timer.hpp>
00051
00052 void KrylovSolverDim(ReferenceCounting<Vector<real_t> > u,
00053 const BaseMatrix& A, const BaseVector& b,
00054 const Problem& problem,
00055 const KrylovSolverOptions::Type& type,
00056 const KrylovSolverOptions::PreconditionerType& pType,
00057 const DegreeOfFreedomSet& degreeOfFreedomSet)
00058 {
00059 #warning temporay implementation
00060 #ifdef HAVE_PETSC
00061 ASSERT(A.type() == BaseMatrix::petscMatrix);
00062 PETScKrylovSolver pks(static_cast<const Vector<real_t>&>(b),
00063 static_cast<const PETScMatrix&>(A),
00064 static_cast<Vector<real_t>&>(u));
00065 return;
00066 #endif // HAVE_PETSC
00067 ReferenceCounting<Preconditioner> P = 0;
00068
00069 switch (pType) {
00070 case KrylovSolverOptions::none: {
00071 P = new IdentityPrecond(problem);
00072 break;
00073 }
00074 case KrylovSolverOptions::diagonal: {
00075 P = new DiagPrecond(problem, A);
00076 break;
00077 }
00078 case KrylovSolverOptions::incompleteCholeski: {
00079 P = new IncompleteCholeskiFactorization(problem, A);
00080 break;
00081 }
00082 case KrylovSolverOptions::multiGrid: {
00083 P = new MultiGrid(problem,
00084 static_cast<const SparseMatrix&>(A),
00085 degreeOfFreedomSet);
00086 break;
00087 }
00088 case KrylovSolverOptions::spectralFEM: {
00089 P = new SpectralFEMPreconditioner(problem);
00090 break;
00091 }
00092 default: {
00093 throw ErrorHandler(__FILE__,__LINE__,
00094 "unexpected preconditioner type",
00095 ErrorHandler::unexpected);
00096 }
00097 }
00098 ffout(2) << "- preconditioner: " << (*P).name() << '\n';
00099 ffout(2) << "- preconditioner initialization\n";
00100 (*P).initializes();
00101 ffout(2) << " preconditioner initialization: done\n";
00102
00103 switch (type) {
00104 case (KrylovSolverOptions::conjugateGradient): {
00105 ConjugateGradient cg(static_cast<const Vector<real_t>&>(b),
00106 A, *P, *u);
00107 break;
00108 }
00109 case (KrylovSolverOptions::biConjugateGradient): {
00110 BiConjugateGradient bicg(static_cast<const Vector<real_t>&>(b),
00111 A, *P, *u);
00112 break;
00113 }
00114 case (KrylovSolverOptions::biConjugateGradientStabilized): {
00115 BiConjugateGradientStabilized bicgstab(static_cast<const Vector<real_t>&>(b),
00116 A, *P, *u);
00117 break;
00118 }
00119 case (KrylovSolverOptions::fgmres): {
00120 FGMRES fgmres(static_cast<const Vector<real_t>&>(b),
00121 A, *P, *u);
00122 break;
00123 }
00124 case (KrylovSolverOptions::gmres): {
00125 GMRES gmres(static_cast<const Vector<real_t>&>(b),
00126 A, *P, *u);
00127 break;
00128 }
00129
00130
00131
00132
00133
00134
00135
00136 case (KrylovSolverOptions::iterativeLUFactorization): {
00137
00138
00139
00140 throw ErrorHandler(__FILE__,__LINE__,
00141 "not implemented",
00142 ErrorHandler::unexpected);
00143 break;
00144 }
00145 default: {
00146 throw ErrorHandler(__FILE__,__LINE__,
00147 "unexpected linear solver type",
00148 ErrorHandler::unexpected);
00149 }
00150 }
00151 }
00152
00153 void KrylovSolver::solve(const Problem& problem,
00154 ReferenceCounting<Vector<real_t> > u)
00155 {
00156
00157 Timer t;
00158 t.start();
00159
00160 ffout(2) << "Krylov solver\n";
00161 ffout(2) << "- number of unknowns: " << u->size() << '\n';
00162
00163 KrylovSolverDim(u, __A, __b, problem, __type, __pType,
00164 __degreeOfFreedomSet);
00165
00166 t.stop();
00167 ffout(2) << "Krylov solver: done";
00168 ffout(3) << " [cost: " << t << ']';
00169 ffout(2) << '\n';
00170 }