40 #ifndef GETFEM_MODEL_SOLVERS_H__ 41 #define GETFEM_MODEL_SOLVERS_H__ 53 template <
typename T>
struct sort_abs_val_
54 {
bool operator()(T x, T y) {
return (gmm::abs(x) < gmm::abs(y)); } };
56 template <
typename MAT>
void print_eigval(
const MAT &M) {
58 typedef typename gmm::linalg_traits<MAT>::value_type T;
60 gmm::dense_matrix<T> MM(n, n), Q(n, n);
61 std::vector<T> eigval(n);
64 gmm::implicit_qr_algorithm(MM, eigval, Q);
65 std::sort(eigval.begin(), eigval.end(), sort_abs_val_<T>());
66 cout <<
"eival = " << eigval << endl;
80 template <
typename MAT,
typename VECT>
81 struct abstract_linear_solver {
82 virtual void operator ()(
const MAT &, VECT &,
const VECT &,
84 virtual ~abstract_linear_solver() {}
87 template <
typename MAT,
typename VECT>
88 struct linear_solver_cg_preconditioned_ildlt
89 :
public abstract_linear_solver<MAT, VECT> {
90 void operator ()(
const MAT &M, VECT &x,
const VECT &b,
93 gmm::cg(M, x, b, P, iter);
94 if (!iter.converged()) GMM_WARNING2(
"cg did not converge!");
98 template <
typename MAT,
typename VECT>
99 struct linear_solver_gmres_preconditioned_ilu
100 :
public abstract_linear_solver<MAT, VECT> {
101 void operator ()(
const MAT &M, VECT &x,
const VECT &b,
104 gmm::gmres(M, x, b, P, 500, iter);
105 if (!iter.converged()) GMM_WARNING2(
"gmres did not converge!");
109 template <
typename MAT,
typename VECT>
110 struct linear_solver_gmres_unpreconditioned
111 :
public abstract_linear_solver<MAT, VECT> {
112 void operator ()(
const MAT &M, VECT &x,
const VECT &b,
114 gmm::identity_matrix P;
115 gmm::gmres(M, x, b, P, 500, iter);
116 if (!iter.converged()) GMM_WARNING2(
"gmres did not converge!");
120 template <
typename MAT,
typename VECT>
121 struct linear_solver_gmres_preconditioned_ilut
122 :
public abstract_linear_solver<MAT, VECT> {
123 void operator ()(
const MAT &M, VECT &x,
const VECT &b,
126 gmm::gmres(M, x, b, P, 500, iter);
127 if (!iter.converged()) GMM_WARNING2(
"gmres did not converge!");
131 template <
typename MAT,
typename VECT>
132 struct linear_solver_gmres_preconditioned_ilutp
133 :
public abstract_linear_solver<MAT, VECT> {
134 void operator ()(
const MAT &M, VECT &x,
const VECT &b,
137 gmm::gmres(M, x, b, P, 500, iter);
138 if (!iter.converged()) GMM_WARNING2(
"gmres did not converge!");
142 template <
typename MAT,
typename VECT>
143 struct linear_solver_superlu
144 :
public abstract_linear_solver<MAT, VECT> {
145 void operator ()(
const MAT &M, VECT &x,
const VECT &b,
151 int info = SuperLU_solve(M, x, b, rcond);
152 iter.enforce_converged(info == 0);
153 if (iter.get_noisy()) cout <<
"condition number: " << 1.0/rcond<< endl;
157 template <
typename MAT,
typename VECT>
158 struct linear_solver_dense_lu :
public abstract_linear_solver<MAT, VECT> {
159 void operator ()(
const MAT &M, VECT &x,
const VECT &b,
161 typedef typename gmm::linalg_traits<MAT>::value_type T;
162 gmm::dense_matrix<T> MM(gmm::mat_nrows(M),gmm::mat_ncols(M));
164 gmm::lu_solve(MM, x, b);
165 iter.enforce_converged(
true);
169 #ifdef GMM_USES_MUMPS 170 template <
typename MAT,
typename VECT>
171 struct linear_solver_mumps :
public abstract_linear_solver<MAT, VECT> {
172 void operator ()(
const MAT &M, VECT &x,
const VECT &b,
174 bool ok = gmm::MUMPS_solve(M, x, b,
false);
175 iter.enforce_converged(ok);
178 template <
typename MAT,
typename VECT>
179 struct linear_solver_mumps_sym :
public abstract_linear_solver<MAT, VECT> {
180 void operator ()(
const MAT &M, VECT &x,
const VECT &b,
182 bool ok = gmm::MUMPS_solve(M, x, b,
true);
183 iter.enforce_converged(ok);
188 #if GETFEM_PARA_LEVEL > 1 && GETFEM_PARA_SOLVER == MUMPS_PARA_SOLVER 189 template <
typename MAT,
typename VECT>
190 struct linear_solver_distributed_mumps
191 :
public abstract_linear_solver<MAT, VECT> {
192 void operator ()(
const MAT &M, VECT &x,
const VECT &b,
194 double tt_ref=MPI_Wtime();
195 bool ok = MUMPS_distributed_matrix_solve(M, x, b,
false);
196 iter.enforce_converged(ok);
197 if (MPI_IS_MASTER()) cout<<
"UNSYMMETRIC MUMPS time "<< MPI_Wtime() - tt_ref<<endl;
201 template <
typename MAT,
typename VECT>
202 struct linear_solver_distributed_mumps_sym
203 :
public abstract_linear_solver<MAT, VECT> {
204 void operator ()(
const MAT &M, VECT &x,
const VECT &b,
206 double tt_ref=MPI_Wtime();
207 bool ok = MUMPS_distributed_matrix_solve(M, x, b,
true);
208 iter.enforce_converged(ok);
209 if (MPI_IS_MASTER()) cout<<
"SYMMETRIC MUMPS time "<< MPI_Wtime() - tt_ref<<endl;
219 struct abstract_newton_line_search {
220 double conv_alpha, conv_r;
221 size_t it, itmax, glob_it;
223 virtual void init_search(
double r,
size_t git,
double R0 = 0.0) = 0;
224 virtual double next_try(
void) = 0;
225 virtual bool is_converged(
double,
double R1 = 0.0) = 0;
226 virtual double converged_value(
void) {
230 virtual double converged_residual(
void) {
return conv_r; };
231 virtual ~abstract_newton_line_search() { }
235 struct newton_search_with_step_control :
public abstract_newton_line_search {
237 virtual void init_search(
double ,
size_t ,
double = 0.0)
238 { GMM_ASSERT1(
false,
"Not to be used"); }
240 virtual double next_try(
void)
241 { GMM_ASSERT1(
false,
"Not to be used"); }
243 virtual bool is_converged(
double ,
double = 0.0)
244 { GMM_ASSERT1(
false,
"Not to be used"); }
246 newton_search_with_step_control() {}
250 struct quadratic_newton_line_search :
public abstract_newton_line_search {
253 double alpha, alpha_mult, first_res, alpha_max_ratio, alpha_min;
254 virtual void init_search(
double r,
size_t git,
double R0 = 0.0) {
255 GMM_ASSERT1(R0 != 0.0,
"You have to specify R0");
257 conv_alpha = alpha = double(1); conv_r = first_res = r; it = 0;
260 virtual double next_try(
void) {
262 if (it == 1)
return double(1);
263 GMM_ASSERT1(R1_ != 0.0,
"You have to specify R1");
264 double a = R0_ / R1_;
265 return (a < 0) ? (a*0.5 + sqrt(a*a*0.25-a)) : a*0.5;
267 virtual bool is_converged(
double r,
double R1 = 0.0) {
269 R1_ = R1;
return ((gmm::abs(R1_) < gmm::abs(R0_*0.5)) || it >= itmax);
271 quadratic_newton_line_search(
size_t imax =
size_t(-1)) { itmax = imax; }
275 struct simplest_newton_line_search :
public abstract_newton_line_search {
276 double alpha, alpha_mult, first_res, alpha_max_ratio, alpha_min,
278 virtual void init_search(
double r,
size_t git,
double = 0.0) {
280 conv_alpha = alpha = double(1); conv_r = first_res = r; it = 0;
282 virtual double next_try(
void)
283 { conv_alpha = alpha; alpha *= alpha_mult; ++it;
return conv_alpha; }
284 virtual bool is_converged(
double r,
double = 0.0) {
286 return ((it <= 1 && r < first_res)
287 || (r <= first_res * alpha_max_ratio && r <= alpha_threshold_res)
288 || (conv_alpha <= alpha_min && r < first_res * 1e5)
291 simplest_newton_line_search
292 (
size_t imax =
size_t(-1),
double a_max_ratio = 6.0/5.0,
293 double a_min = 1.0/1000.0,
double a_mult = 3.0/5.0,
294 double a_threshold_res = 1e50)
295 : alpha_mult(a_mult), alpha_max_ratio(a_max_ratio), alpha_min(a_min),
296 alpha_threshold_res(a_threshold_res)
300 struct default_newton_line_search :
public abstract_newton_line_search {
318 double alpha, alpha_old, alpha_mult, first_res, alpha_max_ratio;
319 double alpha_min_ratio, alpha_min;
321 bool max_ratio_reached;
322 double alpha_max_ratio_reached, r_max_ratio_reached;
325 virtual void init_search(
double r,
size_t git,
double = 0.0);
326 virtual double next_try(
void);
327 virtual bool is_converged(
double r,
double = 0.0);
328 default_newton_line_search(
void) { count_pat = 0; }
332 struct basic_newton_line_search :
public abstract_newton_line_search {
333 double alpha, alpha_mult, first_res, alpha_max_ratio;
334 double alpha_min, prev_res, alpha_max_augment;
335 virtual void init_search(
double r,
size_t git,
double = 0.0) {
337 conv_alpha = alpha = double(1);
338 prev_res = conv_r = first_res = r; it = 0;
340 virtual double next_try(
void)
341 { conv_alpha = alpha; alpha *= alpha_mult; ++it;
return conv_alpha; }
342 virtual bool is_converged(
double r,
double = 0.0) {
343 if (glob_it == 0 || (r < first_res /
double(2))
344 || (conv_alpha <= alpha_min && r < first_res * alpha_max_augment)
346 { conv_r = r;
return true; }
347 if (it > 1 && r > prev_res && prev_res < alpha_max_ratio * first_res)
349 prev_res = conv_r = r;
352 basic_newton_line_search
353 (
size_t imax =
size_t(-1),
354 double a_max_ratio = 5.0/3.0,
355 double a_min = 1.0/1000.0,
double a_mult = 3.0/5.0,
double a_augm = 2.0)
356 : alpha_mult(a_mult), alpha_max_ratio(a_max_ratio),
357 alpha_min(a_min), alpha_max_augment(a_augm) { itmax = imax; }
361 struct systematic_newton_line_search :
public abstract_newton_line_search {
362 double alpha, alpha_mult, first_res;
363 double alpha_min, prev_res;
365 virtual void init_search(
double r,
size_t git,
double = 0.0) {
367 conv_alpha = alpha = double(1);
368 prev_res = conv_r = first_res = r; it = 0; first =
true;
370 virtual double next_try(
void)
371 {
double a = alpha; alpha *= alpha_mult; ++it;
return a; }
372 virtual bool is_converged(
double r,
double = 0.0) {
374 if (r < conv_r || first)
375 { conv_r = r; conv_alpha = alpha / alpha_mult; first =
false; }
376 if ((alpha <= alpha_min*alpha_mult) || it >= itmax)
return true;
379 systematic_newton_line_search
380 (
size_t imax =
size_t(-1),
381 double a_min = 1.0/10000.0,
double a_mult = 3.0/5.0)
382 : alpha_mult(a_mult), alpha_min(a_min) { itmax = imax; }
410 template <
typename PB>
412 const abstract_linear_solver<
typename PB::MATRIX,
413 typename PB::VECTOR> &linear_solver) {
414 typedef typename gmm::linalg_traits<typename PB::VECTOR>::value_type T;
415 typedef typename gmm::number_traits<T>::magnitude_type R;
417 iter_linsolv0.reduce_noisy();
418 iter_linsolv0.set_resmax(iter.get_resmax()/20.0);
419 iter_linsolv0.set_maxiter(10000);
421 pb.compute_residual();
422 R approx_eln = pb.approx_external_load_norm();
423 if (approx_eln == R(0)) approx_eln = R(1);
425 typename PB::VECTOR b0(gmm::vect_size(pb.residual()));
426 gmm::copy(pb.residual(), b0);
427 typename PB::VECTOR Xi(gmm::vect_size(pb.residual()));
428 gmm::copy(pb.state_vector(), Xi);
430 typename PB::VECTOR dr(gmm::vect_size(pb.residual()));
431 typename PB::VECTOR b(gmm::vect_size(pb.residual()));
433 R alpha0(0), alpha(1), res0(gmm::vect_norm1(b0)), minres(res0);
440 scalar_type crit = pb.residual_norm() / approx_eln;
441 if (iter.finished(crit))
return;
446 if (!iter.converged(crit)) {
448 if (iter.get_noisy() > 1)
449 cout <<
"starting tangent matrix computation" << endl;
452 while (is_singular) {
453 pb.compute_tangent_matrix();
455 gmm::copy(gmm::scaled(pb.residual(), pb.scale_residual()), b);
456 gmm::add(gmm::scaled(b0,alpha-R(1)), b);
457 if (iter.get_noisy() > 1) cout <<
"starting linear solver" << endl;
459 linear_solver(pb.tangent_matrix(), dr, b, iter_linsolv);
460 if (!iter_linsolv.converged()) {
462 if (is_singular <= 4) {
463 if (iter.get_noisy())
464 cout <<
"Singular tangent matrix:" 465 " perturbation of the state vector." << endl;
467 pb.compute_residual();
469 if (iter.get_noisy())
470 cout <<
"Singular tangent matrix: perturbation failed, " 471 <<
"aborting." << endl;
475 else is_singular = 0;
477 if (iter.get_noisy() > 1) cout <<
"linear solver done" << endl;
480 gmm::add(dr, pb.state_vector());
481 pb.compute_residual();
483 R dec = R(1)/R(2), coeff2 = coeff * R(1.5);
485 while (dec > R(1E-5) && res >= res0 * coeff) {
486 gmm::add(gmm::scaled(dr, -dec), pb.state_vector());
487 pb.compute_residual();
489 if (res2 < res*R(0.95) || res2 >= res0 * coeff2) {
490 dec /= R(2); res = res2; coeff2 *= R(1.5);
492 gmm::add(gmm::scaled(dr, dec), pb.state_vector());
499 coeff = std::max(R(1.05), coeff*R(0.93));
500 bool near_end = (iter.get_iteration() > iter.get_maxiter()/2);
501 bool cut = (alpha < R(1)) && near_end;
502 if ((res > minres && nit > 4) || cut) {
505 if ((stagn > 10 && alpha > alpha0 + R(5E-2)) || cut) {
506 alpha = (alpha + alpha0) / R(2);
507 if (near_end) alpha = R(1);
508 gmm::copy(Xi, pb.state_vector());
509 pb.compute_residual();
512 stagn = 0; coeff = R(2);
515 if (res < minres || (alpha == R(1) && nit < 10)) stagn = 0;
517 if (nit < 5) minres = res0;
else minres = std::min(minres, res0);
519 if (iter.get_noisy())
520 cout <<
"step control [" << std::setw(8) << alpha0 <<
"," 521 << std::setw(8) << alpha <<
"," << std::setw(10) << dec <<
"]";
525 crit = res / approx_eln;
528 if (iter.finished(crit)) {
529 if (iter.converged() && alpha < R(1)) {
531 alpha = std::min(R(1), alpha*R(3) - alpha0*R(2));
533 gmm::copy(pb.state_vector(), Xi);
534 nit = 0; stagn = 0; coeff = R(2);
546 template <
typename PB>
548 const abstract_linear_solver<
typename PB::MATRIX,
549 typename PB::VECTOR> &linear_solver) {
550 typedef typename gmm::linalg_traits<typename PB::VECTOR>::value_type T;
551 typedef typename gmm::number_traits<T>::magnitude_type R;
553 iter_linsolv0.reduce_noisy();
554 iter_linsolv0.set_resmax(iter.get_resmax()/20.0);
555 iter_linsolv0.set_maxiter(10000);
557 pb.compute_residual();
558 R approx_eln = pb.approx_external_load_norm();
559 if (approx_eln == R(0)) approx_eln = R(1);
561 typename PB::VECTOR dr(gmm::vect_size(pb.residual()));
562 typename PB::VECTOR b(gmm::vect_size(pb.residual()));
564 scalar_type crit = pb.residual_norm() / approx_eln;
565 while (!iter.finished(crit)) {
567 if (iter.get_noisy() > 1)
568 cout <<
"starting computing tangent matrix" << endl;
571 while (is_singular) {
572 pb.compute_tangent_matrix();
574 gmm::copy(gmm::scaled(pb.residual(), pb.scale_residual()), b);
575 if (iter.get_noisy() > 1) cout <<
"starting linear solver" << endl;
577 linear_solver(pb.tangent_matrix(), dr, b, iter_linsolv);
578 if (!iter_linsolv.converged()) {
580 if (is_singular <= 4) {
581 if (iter.get_noisy())
582 cout <<
"Singular tangent matrix:" 583 " perturbation of the state vector." << endl;
585 pb.compute_residual();
587 if (iter.get_noisy())
588 cout <<
"Singular tangent matrix: perturbation failed, aborting." 593 else is_singular = 0;
596 if (iter.get_noisy() > 1) cout <<
"linear solver done" << endl;
597 R alpha = pb.line_search(dr, iter);
599 if (iter.get_noisy()) cout <<
"alpha = " << std::setw(6) << alpha <<
" ";
601 crit = std::min(pb.residual_norm() / approx_eln,
613 template <
typename MAT,
typename VEC>
618 typedef typename gmm::linalg_traits<VECTOR>::value_type T;
619 typedef typename gmm::number_traits<T>::magnitude_type R;
622 abstract_newton_line_search &ls;
623 VECTOR stateinit, &state;
627 void compute_tangent_matrix(
void) {
628 md.to_variables(state);
629 md.assembly(model::BUILD_MATRIX);
632 const MATRIX &tangent_matrix(
void) {
return K; }
634 inline T scale_residual(
void)
const {
return T(1); }
636 void compute_residual(
void) {
637 md.to_variables(state);
638 md.assembly(model::BUILD_RHS);
641 void perturbation(
void) {
642 R res =
gmm::vect_norm2(state), ampl = std::max(res*R(1E-20), R(1E-50));
643 std::vector<R> V(gmm::vect_size(state));
645 gmm::add(gmm::scaled(V, ampl), state);
648 const VECTOR &residual(
void)
const {
return rhs; }
649 const VECTOR &state_vector(
void)
const {
return state; }
650 VECTOR &state_vector(
void) {
return state; }
652 R state_norm(
void)
const 655 R approx_external_load_norm(
void)
656 {
return md.approx_external_load(); }
658 R residual_norm(
void) {
663 R compute_res(
bool comp =
true) {
664 if (comp) compute_residual();
665 return residual_norm();
672 gmm::copy(state, stateinit);
675 res = compute_res(
false);
677 R0 = gmm::real(gmm::vect_sp(dr, rhs));
680 static int trace_number = 0;
683 std::stringstream trace_name;
684 trace_name <<
"line_search_state" << std::setfill(
'0')
685 << std::setw(3) << trace_number <<
"_000_init";
686 gmm::vecsave(trace_name.str(),stateinit);
691 ls.init_search(res, iter.get_iteration(), R0);
693 alpha = ls.next_try();
694 gmm::add(stateinit, gmm::scaled(dr, alpha), state);
698 std::stringstream trace_name;
699 trace_name <<
"line_search_state" << std::setfill(
'0')
700 << std::setw(3) << trace_number <<
"_" 701 << std::setfill(
'0') << std::setw(3) << trace_iter;
702 gmm::vecsave(trace_name.str(), state);
707 R0 = gmm::real(gmm::vect_sp(dr, rhs));
710 }
while (!ls.is_converged(res, R0));
712 if (alpha != ls.converged_value()) {
713 alpha = ls.converged_value();
714 gmm::add(stateinit, gmm::scaled(dr, alpha), state);
715 res = ls.converged_residual();
722 model_pb(model &m, abstract_newton_line_search &ls_, VECTOR &st,
723 const VECTOR &rhs_,
const MATRIX &K_)
724 : md(m), ls(ls_), state(st), rhs(rhs_), K(K_) {}
732 typedef abstract_linear_solver<model_real_sparse_matrix,
733 model_real_plain_vector> rmodel_linear_solver;
734 typedef std::shared_ptr<rmodel_linear_solver> rmodel_plsolver_type;
735 typedef abstract_linear_solver<model_complex_sparse_matrix,
736 model_complex_plain_vector>
737 cmodel_linear_solver;
738 typedef std::shared_ptr<cmodel_linear_solver> cmodel_plsolver_type;
741 template<
typename MATRIX,
typename VECTOR>
742 std::shared_ptr<abstract_linear_solver<MATRIX, VECTOR>>
743 default_linear_solver(
const model &md) {
745 #if GETFEM_PARA_LEVEL == 1 && GETFEM_PARA_SOLVER == MUMPS_PARA_SOLVER 746 if (md.is_symmetric())
747 return std::make_shared<linear_solver_mumps_sym<MATRIX, VECTOR>>();
749 return std::make_shared<linear_solver_mumps<MATRIX, VECTOR>>();
750 #elif GETFEM_PARA_LEVEL > 1 && GETFEM_PARA_SOLVER == MUMPS_PARA_SOLVER 751 if (md.is_symmetric())
752 return std::make_shared
753 <linear_solver_distributed_mumps_sym<MATRIX, VECTOR>>();
755 return std::make_shared
756 <linear_solver_distributed_mumps<MATRIX, VECTOR>>();
758 size_type ndof = md.nb_dof(), max3d = 15000, dim = md.leading_dimension();
759 # ifdef GMM_USES_MUMPS 762 if ((ndof<300000 && dim<=2) || (ndof<max3d && dim<=3) || (ndof<1000)) {
763 # ifdef GMM_USES_MUMPS 764 if (md.is_symmetric())
765 return std::make_shared<linear_solver_mumps_sym<MATRIX, VECTOR>>();
767 return std::make_shared<linear_solver_mumps<MATRIX, VECTOR>>();
769 return std::make_shared<linear_solver_superlu<MATRIX, VECTOR>>();
773 if (md.is_coercive())
774 return std::make_shared
775 <linear_solver_cg_preconditioned_ildlt<MATRIX, VECTOR>>();
778 return std::make_shared
779 <linear_solver_gmres_preconditioned_ilut<MATRIX,VECTOR>>();
781 return std::make_shared
782 <linear_solver_gmres_preconditioned_ilu<MATRIX,VECTOR>>();
786 return std::shared_ptr<abstract_linear_solver<MATRIX, VECTOR>>();
789 template <
typename MATRIX,
typename VECTOR>
790 std::shared_ptr<abstract_linear_solver<MATRIX, VECTOR>>
791 select_linear_solver(
const model &md,
const std::string &name) {
792 std::shared_ptr<abstract_linear_solver<MATRIX, VECTOR>> p;
793 if (bgeot::casecmp(name,
"superlu") == 0)
794 return std::make_shared<linear_solver_superlu<MATRIX, VECTOR>>();
795 else if (bgeot::casecmp(name,
"dense_lu") == 0)
796 return std::make_shared<linear_solver_dense_lu<MATRIX, VECTOR>>();
797 else if (bgeot::casecmp(name,
"mumps") == 0) {
798 #ifdef GMM_USES_MUMPS 799 # if GETFEM_PARA_LEVEL <= 1 800 return std::make_shared<linear_solver_mumps<MATRIX, VECTOR>>();
802 return std::make_shared
803 <linear_solver_distributed_mumps<MATRIX, VECTOR>>();
806 GMM_ASSERT1(
false,
"Mumps is not interfaced");
809 else if (bgeot::casecmp(name,
"cg/ildlt") == 0)
810 return std::make_shared
811 <linear_solver_cg_preconditioned_ildlt<MATRIX, VECTOR>>();
812 else if (bgeot::casecmp(name,
"gmres/ilu") == 0)
813 return std::make_shared
814 <linear_solver_gmres_preconditioned_ilu<MATRIX, VECTOR>>();
815 else if (bgeot::casecmp(name,
"gmres/ilut") == 0)
816 return std::make_shared
817 <linear_solver_gmres_preconditioned_ilut<MATRIX, VECTOR>>();
818 else if (bgeot::casecmp(name,
"gmres/ilutp") == 0)
819 return std::make_shared
820 <linear_solver_gmres_preconditioned_ilutp<MATRIX, VECTOR>>();
821 else if (bgeot::casecmp(name,
"auto") == 0)
822 return default_linear_solver<MATRIX, VECTOR>(md);
824 GMM_ASSERT1(
false,
"Unknown linear solver");
825 return std::shared_ptr<abstract_linear_solver<MATRIX, VECTOR>>();
828 inline rmodel_plsolver_type rselect_linear_solver(
const model &md,
829 const std::string &name) {
830 return select_linear_solver<model_real_sparse_matrix,
831 model_real_plain_vector>(md, name);
834 inline cmodel_plsolver_type cselect_linear_solver(
const model &md,
835 const std::string &name) {
836 return select_linear_solver<model_complex_sparse_matrix,
837 model_complex_plain_vector>(md, name);
868 rmodel_plsolver_type lsolver,
869 abstract_newton_line_search &ls);
872 cmodel_plsolver_type lsolver,
873 abstract_newton_line_search &ls);
876 rmodel_plsolver_type lsolver);
879 cmodel_plsolver_type lsolver);
Incomplete LU without fill-in Preconditioner.
The Iteration object calculates whether the solution has reached the desired accuracy, or whether the maximum number of iterations has been reached.
void standard_solve(model &md, gmm::iteration &iter, rmodel_plsolver_type lsolver, abstract_newton_line_search &ls)
A default solver for the model brick system.
void fill_random(L &l, double cfill)
*/
number_traits< typename linalg_traits< V >::value_type >::magnitude_type vect_norm2(const V &v)
Euclidean norm of a vector.
number_traits< typename linalg_traits< V >::value_type >::magnitude_type vect_norm1(const V &v)
1-norm of a vector
size_t size_type
used as the common size type in the library
Model representation in Getfem.
Interface with MUMPS (LU direct solver for sparse matrices).
GEneric Tool for Finite Element Methods.
number_traits< typename linalg_traits< V1 >::value_type >::magnitude_type vect_dist1(const V1 &v1, const V2 &v2)
1-distance between two vectors
void clear(L &l)
clear (fill with zeros) a vector or matrix.
Include standard gmm iterative solvers (cg, gmres, ...)
ILUTP: Incomplete LU with threshold and K fill-in Preconditioner and column pivoting.
size_type alpha(short_type n, short_type d)
Return the value of which is the number of monomials of a polynomial of variables and degree ...
void resize(M &v, size_type m, size_type n)
*/
Incomplete LU with threshold and K fill-in Preconditioner.
Incomplete Level 0 LDLT Preconditioner.