47 template <
typename T> compare_vp {
48 bool operator()(
const std::pair<T, size_type> &a,
49 const std::pair<T, size_type> &b)
const
50 {
return (gmm::abs(a.first) > gmm::abs(b.first)); }
53 struct idgmres_state {
54 size_type m, tb_deb, tb_def, p, k, nb_want, nb_unwant;
55 size_type nb_nolong, tb_deftot, tb_defwant, conv, nb_un, fin;
59 : m(mm), tb_deb(1), tb_def(0), p(pp), k(kk), nb_want(0),
60 nb_unwant(0), nb_nolong(0), tb_deftot(0), tb_defwant(0),
61 conv(0), nb_un(0), fin(0), ok(false); {}
65 : m(mm), tb_deb(1), tb_def(0), p(pp), k(kk), nb_want(0),
66 nb_unwant(0), nb_nolong(0), tb_deftot(0), tb_defwant(0),
67 conv(0), nb_un(0), fin(0), ok(false); {}
70 template <
typename CONT,
typename IND>
71 apply_permutation(CONT &cont,
const IND &ind) {
73 std::vector<bool> sorted(m,
false);
76 if (!sorted[l] && ind[l] != l) {
78 typeid(cont[0]) aux = cont[l];
83 for(k2 = ind[k]; k2 != l; k2 = ind[k]) {
111 template <
typename Mat,
typename Vec,
typename VecB,
typename Precond,
113 void idgmres(
const Mat &A, Vec &x,
const VecB &b,
const Precond &M,
115 iteration &outer, Basis& KS) {
117 typedef typename linalg_traits<Mat>::value_type T;
118 typedef typename number_traits<T>::magnitude_type R;
121 idgmres_state st(m, p, k);
123 std::vector<T> w(vect_size(x)), r(vect_size(x)), u(vect_size(x));
124 std::vector<T> c_rot(m+1), s_rot(m+1), s(m+1);
125 std::vector<T> y(m+1), ztest(m+1), gam(m+1);
126 std::vector<T> gamma(m+1);
127 gmm::dense_matrix<T> H(m+1, m), Hess(m+1, m),
128 Hobl(m+1, m), W(vect_size(x), m+1);
132 outer.set_rhsnorm(gmm::vect_norm2(b));
133 if (outer.get_rhsnorm() == 0.0) {
clear(x);
return; }
135 mult(A, scaled(x, -1.0), b, w);
139 iteration inner = outer;
140 inner.reduce_noisy();
141 inner.set_maxiter(m);
142 inner.set_name(
"GMRes inner iter");
144 while (! outer.finished(beta)) {
146 gmm::copy(gmm::scaled(r, 1.0/beta), KS[0]);
151 inner.set_maxiter(m - st.tb_deb + 1);
152 size_type i = st.tb_deb - 1; inner.init();
157 orthogonalize_with_refinment(KS, mat_col(H, i), i);
159 gmm::scale(KS[i+1], R(1) / a);
161 gmm::copy(mat_col(H, i), mat_col(Hess, i));
162 gmm::copy(mat_col(H, i), mat_col(Hobl, i));
166 Apply_Givens_rotation_left(H(l,i), H(l+1,i), c_rot[l], s_rot[l]);
168 Givens_rotation(H(i,i), H(i+1,i), c_rot[i], s_rot[i]);
169 Apply_Givens_rotation_left(H(i,i), H(i+1,i), c_rot[i], s_rot[i]);
171 Apply_Givens_rotation_left(s[i], s[i+1], c_rot[i], s_rot[i]);
173 ++inner, ++outer, ++i;
174 }
while (! inner.finished(gmm::abs(s[i])));
176 if (inner.converged()) {
178 upper_tri_solve(H, y, i,
false);
179 combine(KS, y, x, i);
180 mult(A, gmm::scaled(x, T(-1)), b, w);
188 Apply_Givens_rotation_left(gam[l-1], gam[l], gmm::conj(c_rot[l-1]),
191 mult(KS.mat(), gam, r);
194 mult(Hess, scaled(y, T(-1)), gamma, ztest);
200 T nss = H(m,m-1) / ztest[m];
201 nss /= gmm::abs(nss);
202 gmm::copy(KS.mat(), W); gmm::copy(scaled(r, nss /beta), mat_col(W, m));
205 sub_interval SUBI(0, m);
206 add(scaled(sub_vector(ztest, SUBI), -Hobl(m, m-1) / ztest[m]),
207 sub_vector(mat_col(Hobl, m-1), SUBI));
208 Hobl(m, m-1) *= nss * beta / ztest[m];
215 std::vector<std::complex<R> > eval(m);
216 dense_matrix<T> YB(m-st.tb_def, m-st.tb_def);
217 std::vector<char> pure(m-st.tb_def, 0);
220 select_eval(Hobl, eval, YB, pure, st);
225 T
alpha = Lock(W, Hobl,
226 sub_matrix(YB, sub_interval(0, m-st.tb_def)),
227 sub_interval(st.tb_def, m-st.tb_def),
228 (st.tb_defwant < p));
236 for (
size_type j = st.tb_def; j < st.tb_deftot; ++j) {
237 if ( pure[j-st.tb_def] == 0)
238 gmm::clear(sub_vector(mat_col(Hobl,j), sub_interval(j+1,m-j)));
239 else if (pure[j-st.tb_def] == 1) {
240 gmm::clear(sub_matrix(Hobl, sub_interval(j+2,m-j-1),
241 sub_interval(j, 2)));
244 else GMM_ASSERT3(
false,
"internal error");
250 size_type mm = std::min(k+st.nb_unwant+st.nb_nolong, m-1);
252 if (eval_sort[m-mm-1].second != R(0)
253 && eval_sort[m-mm-1].second == -eval_sort[m-mm].second) ++mm;
255 std::vector<complex<R> > shifts(m-mm);
257 shifts[i] = eval_sort[i].second;
259 apply_shift_to_Arnoldi_factorization(W, Hobl, shifts, mm,
265 st.fin = st.tb_deftot;
272 if (st.nb_nolong + st.nb_unwant > 0) {
274 std::vector<std::complex<R> > eval(m);
275 dense_matrix<T> YB(st.fin, st.tb_deftot);
276 std::vector<char> pure(st.tb_deftot, 0);
278 st.nb_un = st.nb_nolong + st.nb_unwant;
280 select_eval_for_purging(Hobl, eval, YB, pure, st);
282 T
alpha = Lock(W, Hobl, YB, sub_interval(0, st.fin), ok);
287 for (
size_type j = 0; j < st.tb_deftot; ++j) {
289 gmm::clear(sub_vector(mat_col(Hobl,j), sub_interval(j+1,m-j)));
290 else if (pure[j] == 1) {
291 gmm::clear(sub_matrix(Hobl, sub_interval(j+2,m-j-1),
292 sub_interval(j, 2)));
295 else GMM_ASSERT3(
false,
"internal error");
298 gmm::dense_matrix<T> z(st.nb_un, st.fin - st.nb_un);
299 sub_interval SUBI(0, st.nb_un), SUBJ(st.nb_un, st.fin - st.nb_un);
300 sylvester(sub_matrix(Hobl, SUBI),
301 sub_matrix(Hobl, SUBJ),
302 sub_matrix(gmm::scaled(Hobl, -T(1)), SUBI, SUBJ), z);
313 template <
typename Mat,
typename Vec,
typename VecB,
typename Precond >
314 void idgmres(
const Mat &A, Vec &x,
const VecB &b,
315 const Precond &M,
size_type m, iteration& outer) {
316 typedef typename linalg_traits<Mat>::value_type T;
317 modified_gram_schmidt<T> orth(m, vect_size(x));
318 gmres(A, x, b, M, m, outer, orth);
330 template <
typename T,
typename MATYB>
331 void Lock(gmm::dense_matrix<T> &W, gmm::dense_matrix<T> &H,
332 const MATYB &YB,
const sub_interval SUB,
333 bool restore, T &ns) {
335 size_type n = mat_nrows(W), m = mat_ncols(W) - 1;
336 size_type ncols = mat_ncols(YB), nrows = mat_nrows(YB);
337 size_type begin = min(SUB); end = max(SUB) - 1;
338 sub_interval SUBR(0, nrows), SUBC(0, ncols);
341 GMM_ASSERT2(((end-begin) == ncols) && (m == mat_nrows(H))
342 && (m+1 == mat_ncols(H)),
"dimensions mismatch");
346 dense_matrix<T> QR(n_rows, n_rows);
347 gmmm::copy(YB, sub_matrix(QR, SUBR, SUBC));
348 gmm::clear(submatrix(QR, SUBR, sub_interval(ncols, nrows-ncols)));
352 apply_house_left(QR, sub_matrix(H, SUB));
353 apply_house_right(QR, sub_matrix(H, SUBR, SUB));
354 apply_house_right(QR, sub_matrix(W, sub_interval(0, n), SUB));
361 gmm::dense_matrix tab_p(end - st.tb_deftot, end - st.tb_deftot);
362 gmm::copy(identity_matrix(), tab_p);
364 for (
size_type j = end-1; j >= st.tb_deftot+2; --j) {
367 std::vector<T> v(jm - st.tb_deftot);
368 sub_interval SUBtot(st.tb_deftot, jm - st.tb_deftot);
369 sub_interval SUBtot2(st.tb_deftot, end - st.tb_deftot);
370 gmm::copy(sub_vector(mat_row(H, j), SUBtot), v);
371 house_vector_last(v);
373 col_house_update(sub_matrix(H, SUBI, SUBtot), v, w);
374 w.resize(end - st.tb_deftot);
375 row_house_update(sub_matrix(H, SUBtot, SUBtot2), v, w);
377 sub_interval(st.tb_deftot, j-1-st.tb_deftot)));
378 w.resize(end - st.tb_deftot);
379 col_house_update(sub_matrix(tab_p, sub_interval(0, end-st.tb_deftot),
380 sub_interval(0, jm-st.tb_deftot)), v, w);
382 col_house_update(sub_matrix(W, sub_interval(0, n), SUBtot), v, w);
387 std::vector<T> d(fin-st.tb_deftot); d[0] = T(1);
392 for (
size_type j = 0; j+1 < end-st.tb_deftot; ++j) {
393 T e = H(st.tb_deftot+j, st.tb_deftot+j-1);
394 d[j+1] = (e == T(0)) ? T(1) : d[j] * gmm::abs(e) / e;
395 scale(sub_vector(mat_row(H, st.tb_deftot+j+1),
396 sub_interval(st.tb_deftot, m-st.tb_deftot)), d[j+1]);
397 scale(mat_col(H, st.tb_deftot+j+1), T(1) / d[j+1]);
398 scale(mat_col(W, st.tb_deftot+j+1), T(1) / d[j+1]);
401 alpha = tab_p(end-st.tb_deftot-1, end-st.tb_deftot-1) / d[end-st.tb_deftot-1];
402 alpha /= gmm::abs(alpha);
403 scale(mat_col(W, m), alpha);
424 template<
typename T,
typename C>
425 apply_shift_to_Arnoldi_factorization(dense_matrix<T> V, dense_matrix<T> H,
430 size_type k1 = 0, num = 0, kend = k+p, kp1 = k + 1;
434 dense_matrix<T> q(1, kend);
436 std::vector<T> hv(3), w(std::max(kend, mat_nrows(V)));
442 if (abs(Lambda[jj].real()) == 0.0) {
445 for (
size_type k1 = 0, k2 = 0; k2 != kend-1; k1 = k2+1) {
447 while (h(k2+1, k2) != T(0) && k2 < kend-1) ++k2;
449 Givens_rotation(H(k1, k1) - Lambda[jj], H(k1+1, k1), c, s);
451 for (i = k1; i <= k2; ++i) {
452 if (i > k1) Givens_rotation(H(i, i-1), H(i+1, i-1), c, s);
458 row_rot(sub_matrix(H, sub_interval(i,2), sub_interval(i, kend-i)),
463 col_rot(sub_matrix(H, sub_interval(0, ip2), sub_interval(i, 2))
467 col_rot(V, c, s, i, i+1);
470 Apply_Givens_rotation_left(q(0,i), q(0,i+1), c, s);
490 for (
size_type k1 = 0, k3 = 0; k3 != kend-2; k1 = k3+1) {
492 while (h(k3+1, k3) != T(0) && k3 < kend-2) ++k3;
496 x = H(k1,k1) * H(k1,k1) + H(k1,k2) * H(k2,k1)
497 - 2.0*Lambda[jj].real() * H(k1,k1) + gmm::abs_sqr(Lambda[jj]);
498 y = H(k2,k1) * (H(k1,k1) + H(k2,k2) - 2.0*Lambda[jj].real());
499 z = H(k2+1,k2) * H(k2,k1);
510 hv[0] = x; hv[1] = y; hv[2] = z;
517 row_house_update(sub_matrix(H, sub_interval(i, 2),
518 sub_interval(i, kend-i)), v, w);
524 col_house_update(sub_matrix(H, sub_interval(0, ip3),
525 sub_interval(i, 2)), v, w);
529 w.resize(mat_nrows(V));
530 col_house_update(sub_matrix(V, sub_interval(0, mat_nrows(V)),
531 sub_interval(i, 2)), v, w);
536 col_house_update(sub_matrix(q, sub_interval(0,1),
537 sub_interval(i,2)), v, w);
546 if (i > k1) Givens_rotation(H(i, i-1), H(i+1, i-1), c, s);
552 row_rot(sub_matrix(H, sub_interval(i,2), sub_interval(i, kend-i)),
557 col_rot(sub_matrix(H, sub_interval(0, ip2), sub_interval(i, 2))
561 col_rot(V, c, s, i, i+1);
564 Apply_Givens_rotation_left(q(0,i), q(0,i+1), c, s);
573 scale(mat_col(V, kend), q(0, k));
575 if (k < mat_nrows(H)) {
577 gmm::copy(mat_col(V, kend), mat_col(V, k));
581 gmm::add(scaled(mat_col(V, kend), H(kend, kend-1)),
582 scaled(mat_col(V, k), H(k, k-1)), mat_col(V, k));
586 scale(mat_col(V, kend), T(1) / H(k, k-1));
591 template<
typename MAT,
typename EVAL,
typename PURE>
592 void select_eval(
const MAT &Hobl, EVAL &eval, MAT &YB, PURE &pure,
595 typedef typename linalg_traits<MAT>::value_type T;
596 typedef typename number_traits<T>::magnitude_type R;
601 col_matrix< std::vector<T> > evect(m-st.tb_def, m-st.tb_def);
603 std::vector<R> ritznew(m, T(-1));
607 sub_interval SUB1(st.tb_def, m-st.tb_def);
608 implicit_qr_algorithm(sub_matrix(Hobl, SUB1),
609 sub_vector(eval, SUB1), evect);
610 sub_interval SUB2(0, st.tb_def);
611 implicit_qr_algorithm(sub_matrix(Hobl, SUB2),
612 sub_vector(eval, SUB2), );
614 for (
size_type l = st.tb_def; l < m; ++l)
615 ritznew[l] = gmm::abs(evect(m-st.tb_def-1, l-st.tb_def) * Hobl(m, m-1));
617 std::vector< std::pair<T, size_type> > eval_sort(m);
619 eval_sort[l] = std::pair<T, size_type>(eval[l], l);
620 std::sort(eval_sort.begin(), eval_sort.end(), compare_vp());
622 std::vector<size_type> index(m);
623 for (
size_type l = 0; l < m; ++l) index[l] = eval_sort[l].second;
625 std::vector<bool> kept(m,
false);
626 std::fill(kept.begin(), kept.begin()+st.tb_def,
true);
628 apply_permutation(eval, index);
629 apply_permutation(evect, index);
630 apply_permutation(ritznew, index);
631 apply_permutation(kept, index);
650 st.nb_want = 0, st.nb_unwant = 0, st.nb_nolong = 0;
653 for (j = 0, ind = 0; j < m-p; ++j) {
654 if (ritznew[j] == R(-1)) {
655 if (std::imag(eval[j]) != R(0)) {
656 st.nb_nolong += 2; ++j;
662 < tol_vp * gmm::abs(eval[j])) {
664 for (
size_type l = 0, l < m-st.tb_def; ++l)
665 YB(l, ind) = std::real(evect(l, j));
667 ++j; ++st.nb_unwant; ind++;
669 if (std::imag(eval[j]) != R(0)) {
670 for (
size_type l = 0, l < m-st.tb_def; ++l)
671 YB(l, ind) = std::imag(evect(l, j));
686 if (ritznew[j] != R(-1)) {
688 for (
size_type l = 0, l < m-st.tb_def; ++l)
689 YB(l, ind) = std::real(evect(l, j));
696 < tol_vp * gmm::abs(eval[j])) {
697 for (
size_type l = 0, l < m-st.tb_def; ++l)
698 YB(l, ind) = std::imag(evect(l, j));
710 std::vector<T> shift(m - st.tb_def - st.nb_want - st.nb_unwant);
712 if (!kept[j]) shift[i++] = eval[j];
719 size_type st.tb_deftot = st.tb_def + st.conv;
720 size_type st.tb_defwant = st.tb_def + st.nb_want - st.nb_nolong;
722 sub_interval SUBYB(0, st.conv);
724 if ( st.tb_defwant >= p ) {
727 st.nb_want = p + st.nb_nolong - st.tb_def;
730 if ( pure[st.conv - st.nb_want + 1] == 2 ) {
731 ++st.nb_want; st.tb_defwant = ++p;
734 SUBYB = sub_interval(st.conv - st.nb_want, st.nb_want);
737 st.conv = st.nb_want;
738 st.tb_deftot = st.tb_def + st.conv;
746 template<
typename MAT,
typename EVAL,
typename PURE>
747 void select_eval_for_purging(
const MAT &Hobl, EVAL &eval, MAT &YB,
748 PURE &pure, idgmres_state &st) {
750 typedef typename linalg_traits<MAT>::value_type T;
751 typedef typename number_traits<T>::magnitude_type R;
756 col_matrix< std::vector<T> > evect(st.tb_deftot, st.tb_deftot);
758 sub_interval SUB1(0, st.tb_deftot);
759 implicit_qr_algorithm(sub_matrix(Hobl, SUB1),
760 sub_vector(eval, SUB1), evect);
761 std::fill(eval.begin() + st.tb_deftot, eval.end(), std::complex<R>(0));
763 std::vector< std::pair<T, size_type> > eval_sort(m);
765 eval_sort[l] = std::pair<T, size_type>(eval[l], l);
766 std::sort(eval_sort.begin(), eval_sort.end(), compare_vp());
768 std::vector<bool> sorted(m);
769 std::fill(sorted.begin(), sorted.end(),
false);
771 std::vector<size_type> ind(m);
772 for (
size_type l = 0; l < m; ++l) ind[l] = eval_sort[l].second;
774 std::vector<bool> kept(m,
false);
775 std::fill(kept.begin(), kept.begin()+st.tb_def,
true);
777 apply_permutation(eval, ind);
778 apply_permutation(evect, ind);
781 for (j = 0; j < st.tb_deftot; ++j) {
783 for (
size_type l = 0, l < st.tb_deftot; ++l)
784 YB(l, j) = std::real(evect(l, j));
786 if (std::imag(eval[j]) != R(0)) {
787 for (
size_type l = 0, l < m-st.tb_def; ++l)
788 YB(l, j+1) = std::imag(evect(l, j));