void CompCol_ICPreconditioner :: ICSolve(FloatArray &dest) const { int i, t, M = dest.giveSize(); FloatArray work(M); double val; // lower diag work.zero(); // solve Uw=x for ( i = 0; i < M; i++ ) { work(i) = val = ( dest(i) + work(i) ) / val_( pntr_(i) ); for ( t = pntr_(i) + 1; t < pntr_(i + 1); t++ ) { work( indx_(t) ) -= val_(t) * val; } } dest.zero(); // solve U^Ty=w for ( i = M - 1; i >= 0; i-- ) { for ( t = pntr_(i) + 1; t < pntr_(i + 1); t++ ) { dest(i) -= val_(t) * dest( indx_(t) ); } dest(i) = ( work(i) + dest(i) ) / val_( pntr_(i) ); } }
void CompCol_ICPreconditioner :: ICFactor() { int d, g, h, i, j, k, n = pntr_.giveSize() - 1; double z; for ( k = 0; k < n - 1; k++ ) { d = pntr_(k); z = val_(d) = sqrt( val_(d) ); for ( i = d + 1; i < pntr_(k + 1); i++ ) { val_(i) /= z; } for ( i = d + 1; i < pntr_(k + 1); i++ ) { z = val_(i); h = indx_(i); g = i; for ( j = pntr_(h); j < pntr_(h + 1); j++ ) { for ( ; g < pntr_(k + 1) && indx_(g + 1) <= indx_(j); g++ ) { if ( indx_(g) == indx_(j) ) { val_(j) -= z * val_(g); } } } } } d = pntr_(n - 1); val_(d) = sqrt( val_(d) ); }
void CompCol_ICPreconditioner :: initialize(const CompCol &A) { dim_ [ 0 ] = A.dim(0); dim_ [ 1 ] = A.dim(1); pntr_.resize(A.dim(1) + 1); int i, j, k; nz_ = 0; for ( k = 0; k < dim_ [ 1 ]; k++ ) { for ( j = A.col_ptr(k); j < A.col_ptr(k + 1); j++ ) { if ( A.row_ind(j) >= k ) { nz_++; } } } val_.resize(nz_); indx_.resize(nz_); // Copy just triangular part pntr_(0) = 0; for ( k = 0; k < dim_ [ 1 ]; k++ ) { pntr_(k + 1) = pntr_(k); for ( j = A.col_ptr(k); j < A.col_ptr(k + 1); j++ ) { if ( A.row_ind(j) >= k ) { i = pntr_(k + 1)++; val_(i) = A.val(j); indx_(i) = A.row_ind(j); } } } // for (i = 0; i < dim_[1]; i++) // qsortRow(indx_, val_, pntr_(i), pntr_(i+1) -1); for ( i = 0; i < dim_ [ 1 ]; i++ ) { if ( indx_( pntr_(i) ) != i ) { OOFEM_ERROR("diagonal not found!"); } } this->ICFactor(); }
ICPreconditioner_double::ICPreconditioner_double(const CompRow_Mat_double &A) : val_(0), pntr_(A.dim(0)+1), indx_(0), nz_(0) { dim_[0] = A.dim(0); dim_[1] = A.dim(1); int i, j, k; for (k = 0; k < dim_[0]; k++) for (j = A.row_ptr(k); j < A.row_ptr(k+1); j++) if (A.col_ind(j) >= k) nz_++; val_.newsize(nz_); indx_.newsize(nz_); // Copy just triangular part (including diagonal) pntr_(0) = 0; for (k = 0; k < dim_[0]; k++) { pntr_(k+1) = pntr_(k); for (j = A.row_ptr(k); j < A.row_ptr(k+1); j++) { if (A.col_ind(j) >= k) { i = pntr_(k+1)++; val_(i) = A.val(j); indx_(i) = A.col_ind(j); } } } for (i = 0; i < dim_[0]; i++) QSort(indx_, val_, pntr_[i], pntr_[i+1] - pntr_[i]); for (i = 0; i < dim_[0]; i++) if (indx_[pntr_(i)] != i) { std::cerr << "IC Preconditioner: diagonal not found!" << i << "\n"; exit(1); } ICFactor(pntr_, indx_, val_); }