38 #ifndef GMM_SOLVERS_SCHWARZ_ADDITIVE_H__
39 #define GMM_SOLVERS_SCHWARZ_ADDITIVE_H__
55 struct using_gmres {};
56 struct using_bicgstab {};
59 template <
typename P,
typename local_solver,
typename Matrix>
60 struct actual_precond {
62 static const APrecond &transform(
const P &PP) {
return PP; }
65 template <
typename Matrix1,
typename Precond,
typename Vector>
66 void AS_local_solve(using_cg,
const Matrix1 &A, Vector &x,
const Vector &b,
67 const Precond &P, iteration &iter)
68 { cg(A, x, b, P, iter); }
70 template <
typename Matrix1,
typename Precond,
typename Vector>
71 void AS_local_solve(using_gmres,
const Matrix1 &A, Vector &x,
72 const Vector &b,
const Precond &P, iteration &iter)
73 {
gmres(A, x, b, P, 100, iter); }
75 template <
typename Matrix1,
typename Precond,
typename Vector>
76 void AS_local_solve(using_bicgstab,
const Matrix1 &A, Vector &x,
77 const Vector &b,
const Precond &P, iteration &iter)
78 { bicgstab(A, x, b, P, iter); }
80 template <
typename Matrix1,
typename Precond,
typename Vector>
81 void AS_local_solve(using_qmr,
const Matrix1 &A, Vector &x,
82 const Vector &b,
const Precond &P, iteration &iter)
83 {
qmr(A, x, b, P, iter); }
85 #if defined(GMM_USES_SUPERLU)
86 struct using_superlu {};
88 template <
typename P,
typename Matrix>
89 struct actual_precond<P, using_superlu, Matrix> {
90 typedef typename linalg_traits<Matrix>::value_type value_type;
91 typedef SuperLU_factor<value_type> APrecond;
92 template <
typename PR>
93 static APrecond transform(
const PR &) {
return APrecond(); }
94 static const APrecond &transform(
const APrecond &PP) {
return PP; }
97 template <
typename Matrix1,
typename Precond,
typename Vector>
98 void AS_local_solve(using_superlu,
const Matrix1 &, Vector &x,
99 const Vector &b,
const Precond &P, iteration &iter)
100 { P.solve(x, b); iter.set_iteration(1); }
107 template <
typename Matrix1,
typename Matrix2,
typename Precond,
108 typename local_solver>
109 struct add_schwarz_mat{
110 typedef typename linalg_traits<Matrix1>::value_type value_type;
113 const std::vector<Matrix2> *vB;
114 std::vector<Matrix2> vAloc;
115 mutable iteration iter;
118 mutable std::vector<std::vector<value_type> > gi, fi;
119 std::vector<
typename actual_precond<Precond, local_solver,
120 Matrix1>::APrecond> precond1;
122 void init(
const Matrix1 &A_,
const std::vector<Matrix2> &vB_,
123 iteration iter_,
const Precond &P,
double residual_);
125 add_schwarz_mat(
void) {}
126 add_schwarz_mat(
const Matrix1 &A_,
const std::vector<Matrix2> &vB_,
127 iteration iter_,
const Precond &P,
double residual_)
128 { init(A_, vB_, iter_, P, residual_); }
131 template <
typename Matrix1,
typename Matrix2,
typename Precond,
132 typename local_solver>
133 void add_schwarz_mat<Matrix1, Matrix2, Precond, local_solver>::init(
134 const Matrix1 &A_,
const std::vector<Matrix2> &vB_,
135 iteration iter_,
const Precond &P,
double residual_) {
137 vB = &vB_; A = &A_; iter = iter_;
138 residual = residual_;
141 vAloc.resize(nb_sub);
142 gi.resize(nb_sub); fi.resize(nb_sub);
143 precond1.resize(nb_sub);
144 std::fill(precond1.begin(), precond1.end(),
145 actual_precond<Precond, local_solver, Matrix1>::transform(P));
148 if (iter.get_noisy()) cout <<
"Init pour sub dom ";
150 int size,tranche,borne_sup,borne_inf,rank,tag1=11,tag2=12,tag3=13,sizepr = 0;
152 double t_ref,t_final;
155 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
156 MPI_Comm_size(MPI_COMM_WORLD, &size);
158 borne_inf=rank*tranche;
159 borne_sup=(rank+1)*tranche;
162 cout <<
"Nombre de sous domaines " << borne_sup - borne_inf << endl;
164 int sizeA = mat_nrows(*A);
165 gmm::csr_matrix<value_type> Acsr(sizeA, sizeA), Acsrtemp(sizeA, sizeA);
166 gmm::copy(gmm::eff_matrix(*A), Acsr);
167 int next = (rank + 1) % size;
168 int previous = (rank + size - 1) % size;
172 for (
int nproc = 0; nproc < size; ++nproc) {
178 cout <<
"Sous domaines " << i <<
" : " << mat_ncols((*vB)[i]) << endl;
183 if (iter.get_noisy()) cout << i <<
" " << std::flush;
184 Matrix2 Maux(mat_ncols((*vB)[i]), mat_nrows((*vB)[i]));
187 Matrix2 Maux2(mat_ncols((*vB)[i]), mat_ncols((*vB)[i]));
189 gmm::resize(vAloc[i], mat_ncols((*vB)[i]), mat_ncols((*vB)[i]));
192 gmm::mult(gmm::transposed((*vB)[i]), Acsr, Maux);
193 gmm::mult(Maux, (*vB)[i], Maux2);
194 gmm::add(Maux2, vAloc[i]);
196 gmm::resize(vAloc[i], mat_ncols((*vB)[i]), mat_ncols((*vB)[i]));
197 gmm::mult(gmm::transposed((*vB)[i]), *A, Maux);
198 gmm::mult(Maux, (*vB)[i], vAloc[i]);
202 if (nproc == size - 1 ) {
204 precond1[i].build_with(vAloc[i]);
214 if (nproc != size - 1) {
215 MPI_Sendrecv(&(Acsr.jc[0]), sizeA+1, MPI_INT, next, tag2,
216 &(Acsrtemp.jc[0]), sizeA+1, MPI_INT, previous, tag2,
217 MPI_COMM_WORLD, &status);
218 if (Acsrtemp.jc[sizeA] >
size_type(sizepr)) {
219 sizepr = Acsrtemp.jc[sizeA];
223 MPI_Sendrecv(&(Acsr.ir[0]), Acsr.jc[sizeA], MPI_INT, next, tag1,
224 &(Acsrtemp.ir[0]), Acsrtemp.jc[sizeA], MPI_INT, previous, tag1,
225 MPI_COMM_WORLD, &status);
227 MPI_Sendrecv(&(Acsr.pr[0]), Acsr.jc[sizeA], mpi_type(value_type()), next, tag3,
228 &(Acsrtemp.pr[0]), Acsrtemp.jc[sizeA], mpi_type(value_type()), previous, tag3,
229 MPI_COMM_WORLD, &status);
230 gmm::copy(Acsrtemp, Acsr);
234 cout<<
"temps boucle precond "<< t_final-t_ref<<endl;
236 if (iter.get_noisy()) cout <<
"\n";
239 template <
typename Matrix1,
typename Matrix2,
typename Precond,
240 typename Vector2,
typename Vector3,
typename local_solver>
241 void mult(
const add_schwarz_mat<Matrix1, Matrix2, Precond, local_solver> &M,
242 const Vector2 &p, Vector3 &q) {
245 static double tmult_tot = 0.0;
246 double t_ref = MPI_Wtime();
251 tmult_tot += MPI_Wtime()-t_ref;
252 cout <<
"tmult_tot = " << tmult_tot << endl;
254 std::vector<double> qbis(gmm::vect_size(q));
255 std::vector<double> qter(gmm::vect_size(q));
260 int size,tranche,borne_sup,borne_inf,rank;
262 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
263 MPI_Comm_size(MPI_COMM_WORLD, &size);
265 borne_inf=rank*tranche;
266 borne_sup=(rank+1)*tranche;
275 for (
size_type i = 0; i < M.fi.size(); ++i)
281 gmm::mult(gmm::transposed((*(M.vB))[i]), q, M.fi[i]);
283 AS_local_solve(local_solver(), (M.vAloc)[i], (M.gi)[i],
284 (M.fi)[i],(M.precond1)[i],M.iter);
285 itebilan = std::max(itebilan, M.iter.get_iteration());
289 cout <<
"First AS loop time " << MPI_Wtime() - t_ref << endl;
299 for (
size_type i = 0; i < M.gi.size(); ++i)
306 gmm::mult((*(M.vB))[i], M.gi[i], qter);
309 gmm::mult((*(M.vB))[i], M.gi[i], q, q);
317 cout <<
"Second AS loop time " << MPI_Wtime() - t_ref << endl;
323 static double t_tot = 0.0;
342 MPI_Allreduce(&(qbis[0]), &(q[0]),gmm::vect_size(q), MPI_DOUBLE,
343 MPI_SUM,MPI_COMM_WORLD);
345 t_tot += t_final-t_ref;
346 cout<<
"["<< rank<<
"] temps reduce Resol "<< t_final-t_ref <<
" t_tot = " << t_tot << endl;
349 if (M.iter.get_noisy() > 0) cout <<
"itebloc = " << itebilan << endl;
350 M.itebilan += itebilan;
351 M.iter.set_resmax((M.iter.get_resmax() + M.residual) * 0.5);
354 template <
typename Matrix1,
typename Matrix2,
typename Precond,
355 typename Vector2,
typename Vector3,
typename local_solver>
356 void mult(
const add_schwarz_mat<Matrix1, Matrix2, Precond, local_solver> &M,
357 const Vector2 &p,
const Vector3 &q) {
358 mult(M, p,
const_cast<Vector3 &
>(q));
361 template <
typename Matrix1,
typename Matrix2,
typename Precond,
362 typename Vector2,
typename Vector3,
typename Vector4,
363 typename local_solver>
364 void mult(
const add_schwarz_mat<Matrix1, Matrix2, Precond, local_solver> &M,
365 const Vector2 &p,
const Vector3 &p2, Vector4 &q)
366 { mult(M, p, q);
add(p2, q); }
368 template <
typename Matrix1,
typename Matrix2,
typename Precond,
369 typename Vector2,
typename Vector3,
typename Vector4,
370 typename local_solver>
371 void mult(
const add_schwarz_mat<Matrix1, Matrix2, Precond, local_solver> &M,
372 const Vector2 &p,
const Vector3 &p2,
const Vector4 &q)
373 { mult(M, p,
const_cast<Vector4 &
>(q));
add(p2, q); }
379 template <
typename ASM_type,
typename Vect>
380 void AS_global_solve(using_cg,
const ASM_type &ASM, Vect &x,
381 const Vect &b, iteration &iter)
382 { cg(ASM, x, b, *(ASM.A), identity_matrix(), iter); }
384 template <
typename ASM_type,
typename Vect>
385 void AS_global_solve(using_gmres,
const ASM_type &ASM, Vect &x,
386 const Vect &b, iteration &iter)
387 {
gmres(ASM, x, b, identity_matrix(), 100, iter); }
389 template <
typename ASM_type,
typename Vect>
390 void AS_global_solve(using_bicgstab,
const ASM_type &ASM, Vect &x,
391 const Vect &b, iteration &iter)
392 { bicgstab(ASM, x, b, identity_matrix(), iter); }
394 template <
typename ASM_type,
typename Vect>
395 void AS_global_solve(using_qmr,
const ASM_type &ASM, Vect &x,
396 const Vect &b, iteration &iter)
397 {
qmr(ASM, x, b, identity_matrix(), iter); }
399 #if defined(GMM_USES_SUPERLU)
400 template <
typename ASM_type,
typename Vect>
401 void AS_global_solve(using_superlu,
const ASM_type &, Vect &,
402 const Vect &, iteration &) {
403 GMM_ASSERT1(
false,
"You cannot use SuperLU as "
404 "global solver in additive Schwarz meethod");
419 template <
typename Matrix1,
typename Matrix2,
420 typename Vector2,
typename Vector3,
typename Precond,
421 typename local_solver,
typename global_solver>
423 add_schwarz_mat<Matrix1, Matrix2, Precond, local_solver> &ASM, Vector3 &u,
424 const Vector2 &f,
iteration &iter,
const global_solver&) {
426 typedef typename linalg_traits<Matrix1>::value_type value_type;
428 size_type nb_sub = ASM.vB->size(), nb_dof = gmm::vect_size(f);
430 std::vector<value_type> g(nb_dof);
431 std::vector<value_type> gbis(nb_dof);
433 double t_init=MPI_Wtime();
434 int size,tranche,borne_sup,borne_inf,rank;
435 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
436 MPI_Comm_size(MPI_COMM_WORLD, &size);
438 borne_inf=rank*tranche;
439 borne_sup=(rank+1)*tranche;
446 for (size_type i = 0; i < nb_sub; ++i)
453 gmm::mult(gmm::transposed((*(ASM.vB))[i]), f, ASM.fi[i]);
455 AS_local_solve(local_solver(), ASM.vAloc[i], ASM.gi[i], ASM.fi[i],
456 ASM.precond1[i], ASM.iter);
457 ASM.itebilan = std::max(ASM.itebilan, ASM.iter.get_iteration());
459 gmm::mult((*(ASM.vB))[i], ASM.gi[i], gbis,gbis);
461 gmm::mult((*(ASM.vB))[i], ASM.gi[i], g, g);
465 cout<<
"temps boucle init "<< MPI_Wtime()-t_init<<endl;
466 double t_ref,t_final;
468 MPI_Allreduce(&(gbis[0]), &(g[0]),gmm::vect_size(g), MPI_DOUBLE,
469 MPI_SUM,MPI_COMM_WORLD);
471 cout<<
"temps reduce init "<< t_final-t_ref<<endl;
475 cout<<
"begin global AS"<<endl;
477 AS_global_solve(global_solver(), ASM, u, g, iter);
480 cout<<
"temps AS Global Solve "<< t_final-t_ref<<endl;
482 if (iter.get_noisy())
483 cout <<
"Total number of internal iterations : " << ASM.itebilan << endl;
489 template <
typename Matrix1,
typename Matrix2,
490 typename Vector2,
typename Vector3,
typename Precond,
491 typename local_solver,
typename global_solver>
493 const Vector2 &f,
const Precond &P,
494 const std::vector<Matrix2> &vB,
498 if (iter.get_rhsnorm() == 0.0) {
gmm::clear(u);
return; }
499 iteration iter2 = iter; iter2.reduce_noisy();
501 add_schwarz_mat<Matrix1, Matrix2, Precond, local_solver>
502 ASM(A, vB, iter2, P, iter.get_resmax());
514 template <
typename Matrixt,
typename MatrixBi>
515 class NewtonAS_struct {
518 typedef Matrixt tangent_matrix_type;
519 typedef MatrixBi B_matrix_type;
520 typedef typename linalg_traits<Matrixt>::value_type value_type;
521 typedef std::vector<value_type> Vector;
524 virtual const std::vector<MatrixBi> &get_vB() = 0;
526 virtual void compute_F(Vector &f, Vector &x) = 0;
527 virtual void compute_tangent_matrix(Matrixt &M, Vector &x) = 0;
529 virtual void compute_sub_tangent_matrix(Matrixt &Mloc, Vector &x,
532 virtual void compute_sub_F(Vector &fi, Vector &x,
size_type i) = 0;
534 virtual ~NewtonAS_struct() {}
537 template <
typename Matrixt,
typename MatrixBi>
538 struct AS_exact_gradient {
539 const std::vector<MatrixBi> &vB;
540 std::vector<Matrixt> vM;
541 std::vector<Matrixt> vMloc;
544 for (
size_type i = 0; i < vB.size(); ++i) {
545 Matrixt aux(gmm::mat_ncols(vB[i]), gmm::mat_ncols(vM[i]));
546 gmm::resize(vMloc[i], gmm::mat_ncols(vB[i]), gmm::mat_ncols(vB[i]));
547 gmm::mult(gmm::transposed(vB[i]), vM[i], aux);
548 gmm::mult(aux, vB[i], vMloc[i]);
551 AS_exact_gradient(
const std::vector<MatrixBi> &vB_) : vB(vB_) {
552 vM.resize(vB.size()); vMloc.resize(vB.size());
553 for (
size_type i = 0; i < vB.size(); ++i) {
554 gmm::resize(vM[i], gmm::mat_nrows(vB[i]), gmm::mat_nrows(vB[i]));
559 template <
typename Matrixt,
typename MatrixBi,
560 typename Vector2,
typename Vector3>
561 void mult(
const AS_exact_gradient<Matrixt, MatrixBi> &M,
562 const Vector2 &p, Vector3 &q) {
564 typedef typename gmm::linalg_traits<Vector3>::value_type T;
565 std::vector<T> v(gmm::vect_size(p)), w, x;
566 for (
size_type i = 0; i < M.vB.size(); ++i) {
567 w.resize(gmm::mat_ncols(M.vB[i]));
568 x.resize(gmm::mat_ncols(M.vB[i]));
569 gmm::mult(M.vM[i], p, v);
570 gmm::mult(gmm::transposed(M.vB[i]), v, w);
572 SuperLU_solve(M.vMloc[i], x, w, rcond);
579 template <
typename Matrixt,
typename MatrixBi,
580 typename Vector2,
typename Vector3>
581 void mult(
const AS_exact_gradient<Matrixt, MatrixBi> &M,
582 const Vector2 &p,
const Vector3 &q) {
583 mult(M, p,
const_cast<Vector3 &
>(q));
586 template <
typename Matrixt,
typename MatrixBi,
587 typename Vector2,
typename Vector3,
typename Vector4>
588 void mult(
const AS_exact_gradient<Matrixt, MatrixBi> &M,
589 const Vector2 &p,
const Vector3 &p2, Vector4 &q)
590 { mult(M, p, q);
add(p2, q); }
592 template <
typename Matrixt,
typename MatrixBi,
593 typename Vector2,
typename Vector3,
typename Vector4>
594 void mult(
const AS_exact_gradient<Matrixt, MatrixBi> &M,
595 const Vector2 &p,
const Vector3 &p2,
const Vector4 &q)
596 { mult(M, p,
const_cast<Vector4 &
>(q));
add(p2, q); }
598 struct S_default_newton_line_search {
600 double conv_alpha, conv_r;
601 size_t it, itmax, glob_it;
603 double alpha, alpha_old, alpha_mult, first_res, alpha_max_ratio;
604 double alpha_min_ratio, alpha_min;
606 bool max_ratio_reached;
607 double alpha_max_ratio_reached, r_max_ratio_reached;
611 double converged_value(
void) {
return conv_alpha; };
612 double converged_residual(
void) {
return conv_r; };
614 virtual void init_search(
double r,
size_t git,
double = 0.0) {
615 alpha_min_ratio = 0.9;
617 alpha_max_ratio = 10.0;
620 glob_it = git;
if (git <= 1) count_pat = 0;
621 conv_alpha =
alpha = alpha_old = 1.;
622 conv_r = first_res = r; it = 0;
624 max_ratio_reached =
false;
626 virtual double next_try(
void) {
628 if (alpha >= 0.4)
alpha *= 0.5;
else alpha *= alpha_mult; ++it;
631 virtual bool is_converged(
double r,
double = 0.0) {
633 if (!max_ratio_reached && r < first_res * alpha_max_ratio) {
634 alpha_max_ratio_reached = alpha_old; r_max_ratio_reached = r;
635 it_max_ratio_reached = it; max_ratio_reached =
true;
637 if (max_ratio_reached && r < r_max_ratio_reached * 0.5
638 && r > first_res * 1.1 && it <= it_max_ratio_reached+1) {
639 alpha_max_ratio_reached = alpha_old; r_max_ratio_reached = r;
640 it_max_ratio_reached = it;
642 if (count == 0 || r < conv_r)
643 { conv_r = r; conv_alpha = alpha_old; count = 1; }
644 if (conv_r < first_res) ++count;
646 if (r < first_res * alpha_min_ratio)
647 { count_pat = 0;
return true; }
648 if (count >= 5 || (alpha < alpha_min && max_ratio_reached)) {
649 if (conv_r < first_res * 0.99) count_pat = 0;
651 { conv_r=r_max_ratio_reached; conv_alpha=alpha_max_ratio_reached; }
652 if (conv_r >= first_res * 0.9999) count_pat++;
657 S_default_newton_line_search(
void) { count_pat = 0; }
662 template <
typename Matrixt,
typename MatrixBi,
typename Vector,
663 typename Precond,
typename local_solver,
typename global_solver>
664 void Newton_additive_Schwarz(NewtonAS_struct<Matrixt, MatrixBi> &NS,
666 iteration &iter,
const Precond &P,
667 local_solver, global_solver) {
668 Vector &u =
const_cast<Vector &
>(u_);
669 typedef typename linalg_traits<Vector>::value_type value_type;
670 typedef typename number_traits<value_type>::magnitude_type mtype;
671 typedef actual_precond<Precond, local_solver, Matrixt> chgt_precond;
673 double residual = iter.get_resmax();
675 S_default_newton_line_search internal_ls;
676 S_default_newton_line_search external_ls;
678 typename chgt_precond::APrecond PP = chgt_precond::transform(P);
679 iter.set_rhsnorm(mtype(1));
680 iteration iternc(iter);
681 iternc.reduce_noisy(); iternc.set_maxiter(
size_type(-1));
682 iteration iter2(iternc);
683 iteration iter3(iter2); iter3.reduce_noisy();
684 iteration iter4(iter3);
685 iternc.set_name(
"Local Newton");
686 iter2.set_name(
"Linear System for Global Newton");
687 iternc.set_resmax(residual/100.0);
688 iter3.set_resmax(residual/10000.0);
689 iter2.set_resmax(residual/1000.0);
690 iter4.set_resmax(residual/1000.0);
691 std::vector<value_type> rhs(NS.size()), x(NS.size()), d(NS.size());
692 std::vector<value_type> xi, xii, fi, di;
694 std::vector< std::vector<value_type> > vx(NS.get_vB().size());
695 for (
size_type i = 0; i < NS.get_vB().size(); ++i)
698 Matrixt Mloc, M(NS.size(), NS.size());
699 NS.compute_F(rhs, u);
700 mtype act_res=
gmm::vect_norm2(rhs), act_res_new(0), precond_res = act_res;
703 while(!iter.finished(std::min(act_res, precond_res))) {
704 for (
int SOR_step = 0; SOR_step >= 0; --SOR_step) {
706 for (
size_type isd = 0; isd < NS.get_vB().size(); ++isd) {
707 const MatrixBi &Bi = (NS.get_vB())[isd];
710 xi.resize(si); xii.resize(si); fi.resize(si); di.resize(si);
713 iternc.set_maxiter(30);
714 if (iternc.get_noisy())
715 cout <<
"Non-linear local problem " << isd << endl;
718 NS.compute_sub_F(fi, x, isd); gmm::scale(fi, value_type(-1));
720 if (r > value_type(0)) {
721 iternc.set_rhsnorm(std::max(r, mtype(1)));
722 while(!iternc.finished(r)) {
723 NS.compute_sub_tangent_matrix(Mloc, x, isd);
727 AS_local_solve(local_solver(), Mloc, di, fi, PP, iter3);
729 internal_ls.init_search(r, iternc.get_iteration());
731 alpha = internal_ls.next_try();
732 gmm::add(xi, gmm::scaled(di, -alpha), xii);
733 gmm::mult(Bi, gmm::scaled(xii, -1.0), u, x);
734 NS.compute_sub_F(fi, x, isd); gmm::scale(fi, value_type(-1));
736 }
while (!internal_ls.is_converged(r_t));
738 if (alpha != internal_ls.converged_value()) {
739 alpha = internal_ls.converged_value();
740 gmm::add(xi, gmm::scaled(di, -alpha), xii);
741 gmm::mult(Bi, gmm::scaled(xii, -1.0), u, x);
742 NS.compute_sub_F(fi, x, isd); gmm::scale(fi, value_type(-1));
745 gmm::copy(x, vx[isd]);
747 if (iternc.get_noisy()) cout <<
"(step=" <<
alpha <<
")\t";
748 ++iternc; r = r_t; gmm::copy(xii, xi);
750 if (SOR_step) gmm::mult(Bi, gmm::scaled(xii, -1.0), u, u);
751 gmm::mult(Bi, gmm::scaled(xii, -1.0), rhs, rhs);
755 if (SOR_step) cout <<
"SOR step residual = " << precond_res << endl;
756 if (precond_res < residual)
break;
757 cout <<
"Precond residual = " << precond_res << endl;
763 NS.compute_tangent_matrix(M, u);
764 add_schwarz_mat<Matrixt, MatrixBi, Precond, local_solver>
765 ASM(M, NS.get_vB(), iter4, P, iter.get_resmax());
766 AS_global_solve(global_solver(), ASM, d, rhs, iter2);
769 AS_exact_gradient<Matrixt, MatrixBi> eg(NS.get_vB());
770 for (
size_type i = 0; i < NS.get_vB().size(); ++i) {
771 NS.compute_tangent_matrix(eg.vM[i], vx[i]);
774 gmres(eg, d, rhs, gmm::identity_matrix(), 50, iter2);
778 external_ls.init_search(act_res, iter.get_iteration());
780 alpha = external_ls.next_try();
781 gmm::add(gmm::scaled(d, alpha), u, x);
782 NS.compute_F(rhs, x);
784 }
while (!external_ls.is_converged(act_res_new));
786 if (alpha != external_ls.converged_value()) {
787 alpha = external_ls.converged_value();
788 gmm::add(gmm::scaled(d, alpha), u, x);
789 NS.compute_F(rhs, x);
793 if (iter.get_noisy() > 1) cout << endl;
794 act_res = act_res_new;
795 if (iter.get_noisy()) cout <<
"(step=" <<
alpha <<
")\t unprecond res = " << act_res <<
" ";
798 ++iter; gmm::copy(x, u);
805 #endif // GMM_SOLVERS_SCHWARZ_ADDITIVE_H__