00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #ifndef ITL_PC_IC_0_INCLUDE
00013 #define ITL_PC_IC_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/matrix/upper.hpp>
00027 #include <boost/numeric/mtl/matrix/compressed2D.hpp>
00028
00029
00030 namespace itl { namespace pc {
00031
00032 template <typename Matrix>
00033 class ic_0
00034 {
00035 public:
00036 typedef typename mtl::Collection<Matrix>::value_type value_type;
00037 typedef typename mtl::Collection<Matrix>::size_type size_type;
00038 typedef ic_0 self;
00039
00040 typedef mtl::compressed2D<value_type> U_type;
00041 typedef U_type L_type;
00042
00043
00044
00045 ic_0(const Matrix& A)
00046 {
00047 factorize(A, typename mtl::traits::category<Matrix>::type());
00048 }
00049
00050
00051 template <typename Vector>
00052 Vector solve(const Vector& x) const
00053 {
00054 return inverse_upper_trisolve(U, inverse_lower_trisolve(adjoint(U), x));
00055 }
00056
00057
00058 template <typename Vector>
00059 Vector adjoint_solve(const Vector& x) const
00060 {
00061 return solve(x);
00062 }
00063
00064
00065 L_type get_L() { return L_type(trans(U)); }
00066 U_type get_U() { return U; }
00067
00068 protected:
00069
00070 void factorize(const Matrix& A, mtl::tag::dense)
00071 {
00072 MTL_THROW_IF(true, mtl::logic_error("IC is not intended for dense matrices"));
00073 }
00074
00075
00076 void factorize(const Matrix& A, mtl::tag::sparse)
00077 {
00078 using namespace mtl; using namespace mtl::tag; using mtl::traits::range_generator;
00079 using math::reciprocal; using mtl::matrix::upper;
00080
00081 typedef typename range_generator<row, U_type>::type cur_type;
00082 typedef typename range_generator<nz, cur_type>::type icur_type;
00083
00084 MTL_THROW_IF(num_rows(A) != num_cols(A), mtl::matrix_not_square());
00085 U= upper(A); crop(U);
00086 U_type L(lower(A));
00087
00088 typename mtl::traits::col<U_type>::type col(U), col_l(L);
00089 typename mtl::traits::value<U_type>::type value(U);
00090
00091
00092 cur_type kc= begin<row>(U), kend= end<row>(U);
00093 for (size_type k= 0; kc != kend; ++kc, ++k) {
00094
00095 icur_type ic= begin<nz>(kc), iend= end<nz>(kc);
00096 MTL_DEBUG_THROW_IF(col(*ic) != k, mtl::missing_diagonal());
00097
00098
00099 value_type inv_dia= reciprocal(sqrt(value(*ic)));
00100 value(*ic, inv_dia);
00101 icur_type jbegin= ++ic;
00102 for (; ic != iend; ++ic) {
00103
00104 value_type d= value(*ic) * inv_dia;
00105 value(*ic, d);
00106 size_type i= col(*ic);
00107
00108
00109
00110 cur_type irow= begin<row>(L); irow+= i;
00111
00112 icur_type jc= begin<nz>(irow), jend= end<nz>(irow);
00113 while (col_l(*jc) <= k) ++jc;
00114 while (col_l(*--jend) > i);
00115 ++jend;
00116
00117 for (; jc != jend; ++jc) {
00118 size_type j= col_l(*jc);
00119 U.lvalue(j, i)-= d * U[k][j];
00120 }
00121
00122 }
00123 }
00124 }
00125
00126 U_type U;
00127 };
00128
00129
00130 template <typename Matrix, typename Vector>
00131 Vector solve(const ic_0<Matrix>& P, const Vector& x)
00132 {
00133 return P.solve(x);
00134 }
00135
00136 template <typename Matrix, typename Vector>
00137 Vector adjoint_solve(const ic_0<Matrix>& P, const Vector& x)
00138 {
00139 return P.adjoint_solve(x);
00140 }
00141
00142
00143 }}
00144
00145 #endif // ITL_PC_IC_0_INCLUDE