00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #ifndef ITL_PC_ILU_0_INCLUDE
00013 #define ITL_PC_ILU_0_INCLUDE
00014
00015 #include <boost/mpl/bool.hpp>
00016
00017 #include <boost/numeric/linear_algebra/identity.hpp>
00018 #include <boost/numeric/linear_algebra/inverse.hpp>
00019
00020 #include <boost/numeric/mtl/concept/collection.hpp>
00021 #include <boost/numeric/mtl/utility/tag.hpp>
00022 #include <boost/numeric/mtl/utility/category.hpp>
00023 #include <boost/numeric/mtl/utility/exception.hpp>
00024 #include <boost/numeric/mtl/operation/lower_trisolve.hpp>
00025 #include <boost/numeric/mtl/operation/upper_trisolve.hpp>
00026 #include <boost/numeric/mtl/operation/lu.hpp>
00027 #include <boost/numeric/mtl/matrix/compressed2D.hpp>
00028 #include <boost/numeric/mtl/matrix/dense2D.hpp>
00029 #include <boost/numeric/mtl/vector/dense_vector.hpp>
00030
00031
00032 namespace itl { namespace pc {
00033
00034 template <typename Matrix>
00035 class ilu_0
00036 {
00037 public:
00038 typedef typename mtl::Collection<Matrix>::value_type value_type;
00039 typedef typename mtl::Collection<Matrix>::size_type size_type;
00040 typedef ilu_0 self;
00041
00042 typedef mtl::compressed2D<value_type, mtl::matrix::parameters<mtl::tag::col_major> > L_type;
00043 typedef mtl::compressed2D<value_type> U_type;
00044 typedef mtl::compressed2D<value_type> LU_type;
00045
00046
00047
00048 ilu_0(const Matrix& A)
00049 {
00050 factorize(A, typename mtl::traits::category<Matrix>::type());
00051 }
00052
00053
00054 template <typename Vector>
00055 Vector solve(const Vector& b) const
00056 {
00057 return inverse_upper_trisolve(LU, unit_lower_trisolve(LU, b));
00058 }
00059
00060
00061 template <typename Vector>
00062 Vector adjoint_solve(const Vector& b) const
00063 {
00064 return unit_upper_trisolve(adjoint(LU), inverse_lower_trisolve(adjoint(LU), b));
00065 }
00066
00067
00068 L_type get_L() { return L_type(strict_lower(LU)); }
00069 U_type get_U() { return U_type(upper(LU)); }
00070
00071 protected:
00072
00073 void factorize(const Matrix& A, mtl::tag::dense)
00074 {
00075 MTL_THROW_IF(true, mtl::logic_error("ILU is not intended for dense matrices"));
00076 }
00077
00078 void factorize(const Matrix& A, mtl::tag::sparse)
00079 {
00080 using namespace mtl; using namespace mtl::tag; using mtl::traits::range_generator;
00081 using math::reciprocal;
00082 MTL_THROW_IF(num_rows(A) != num_cols(A), mtl::matrix_not_square());
00083
00084 LU= A;
00085
00086 typedef typename range_generator<row, LU_type>::type cur_type;
00087 typedef typename range_generator<nz, cur_type>::type icur_type;
00088 typename mtl::traits::col<LU_type>::type col(LU);
00089 typename mtl::traits::value<LU_type>::type value(LU);
00090 mtl::dense_vector<value_type> inv_dia(num_rows(A));
00091 cur_type ic= begin<row>(LU), iend= end<row>(LU);
00092 for (size_type i= 0; ic != iend; ++ic, ++i) {
00093
00094 for (icur_type kc= begin<nz>(ic), kend= end<nz>(ic); kc != kend; ++kc) {
00095 size_type k= col(*kc);
00096 if (k == i) break;
00097
00098 value_type aik= value(*kc) * inv_dia[k];
00099 value(*kc, aik);
00100
00101 for (icur_type jc= kc + 1; jc != kend; ++jc)
00102 value(*jc, value(*jc) - aik * LU[k][col(*jc)]);
00103
00104 }
00105 inv_dia[i]= reciprocal(LU[i][i]);
00106 }
00107 invert_diagonal(LU);
00108 }
00109 private:
00110 LU_type LU;
00111 };
00112
00113 template <typename Value>
00114 class ilu_0<mtl::dense2D<Value> >
00115 {
00116 public:
00117 typedef mtl::dense2D<Value> Matrix;
00118 typedef typename mtl::Collection<Matrix>::value_type value_type;
00119 typedef typename mtl::Collection<Matrix>::size_type size_type;
00120 typedef ilu_0 self;
00121 typedef Matrix LU_type;
00122
00123 ilu_0(const Matrix& A) : LU(A) { lu(LU, P); std::cout << "LU is\n" << LU << "P is " << P << "\n"; }
00124
00125
00126 template <typename Vector>
00127 Vector solve(const Vector& b) const { return lu_apply(LU, P, b); }
00128
00129
00130 template <typename Vector>
00131 Vector adjoint_solve(const Vector& b) const { return lu_adjoint_apply(LU, P, b); }
00132
00133 private:
00134 LU_type LU;
00135 mtl::dense_vector<size_type> P;
00136 };
00137
00139 template <typename Matrix, typename Vector>
00140 Vector solve(const ilu_0<Matrix>& P, const Vector& b)
00141 {
00142 return P.solve(b);
00143 }
00144
00146 template <typename Matrix, typename Vector>
00147 Vector adjoint_solve(const ilu_0<Matrix>& P, const Vector& b)
00148 {
00149 return P.adjoint_solve(b);
00150 }
00151
00152
00153 }}
00154
00155 #endif // ITL_PC_ILU_0_INCLUDE