16 #ifndef dealii_solver_gmres_h 17 #define dealii_solver_gmres_h 21 #include <deal.II/base/config.h> 22 #include <deal.II/base/subscriptor.h> 23 #include <deal.II/base/logstream.h> 24 #include <deal.II/lac/householder.h> 25 #include <deal.II/lac/solver.h> 26 #include <deal.II/lac/solver_control.h> 27 #include <deal.II/lac/full_matrix.h> 28 #include <deal.II/lac/lapack_full_matrix.h> 29 #include <deal.II/lac/vector.h> 31 #include <deal.II/base/std_cxx14/memory.h> 37 DEAL_II_NAMESPACE_OPEN
47 namespace SolverGMRESImplementation
57 template <
typename VectorType>
77 VectorType &
operator[] (
const unsigned int i)
const;
86 const VectorType &temp);
92 unsigned int size()
const;
104 std::vector<typename VectorMemory<VectorType>::Pointer>
data;
176 template <
class VectorType = Vector<
double> >
245 template <
typename MatrixType,
typename PreconditionerType>
247 solve (
const MatrixType &A,
250 const PreconditionerType &preconditioner);
258 boost::signals2::connection
260 const bool every_iteration=
false);
268 boost::signals2::connection
270 const std::function<
void (
const std::vector<std::complex<double> > &)> &slot,
271 const bool every_iteration=
false);
280 boost::signals2::connection
283 const bool every_iteration=
true);
291 boost::signals2::connection
300 boost::signals2::connection
306 <<
"The number of temporary vectors you gave (" 307 << arg1 <<
") is too small. It should be at least 10 for " 308 <<
"any results, and much more for reasonable ones.");
357 boost::signals2::signal<void (const internal::SolverGMRESImplementation::TmpVectors<VectorType> &)>
krylov_space_signal;
391 const unsigned int dim,
392 const unsigned int accumulated_iterations,
395 bool &re_orthogonalize,
407 const unsigned int dim,
408 const boost::signals2::signal<
void (
const std::vector<std::complex<double> > &)> &
eigenvalues_signal,
410 const boost::signals2::signal<
void(
double)> &cond_signal);
451 template <
class VectorType = Vector<
double> >
493 template <
typename MatrixType,
typename PreconditionerType>
495 solve (
const MatrixType &A,
498 const PreconditionerType &preconditioner);
525 namespace SolverGMRESImplementation
527 template <
class VectorType>
539 template <
class VectorType>
552 template <
class VectorType>
555 const VectorType &temp)
559 if (data[i] ==
nullptr)
562 data[i]->reinit(temp);
569 template <
class VectorType>
573 return (data.size() > 0 ? data.size()-1 : 0);
580 bool complex_less_pred(
const std::complex<double> &x,
581 const std::complex<double> &y)
583 return x.real() < y.real() || (x.real() == y.real() && x.imag() < y.imag());
590 template <
class VectorType>
594 const bool right_preconditioning,
595 const bool use_default_residual,
596 const bool force_re_orthogonalization)
598 max_n_tmp_vectors(max_n_tmp_vectors),
599 right_preconditioning(right_preconditioning),
600 use_default_residual(use_default_residual),
601 force_re_orthogonalization(force_re_orthogonalization)
603 Assert(3 <= max_n_tmp_vectors,
ExcMessage(
"SolverGMRES needs at least three " 604 "temporary vectors."));
609 template <
class VectorType>
612 const AdditionalData &data)
614 Solver<VectorType> (cn,mem),
615 additional_data(data)
620 template <
class VectorType>
622 const AdditionalData &data) :
624 additional_data(data)
629 template <
class VectorType>
638 for (
int i=0 ; i<col ; i++)
640 const double s = si(i);
641 const double c = ci(i);
642 const double dummy = h(i);
643 h(i) = c*dummy + s*h(i+1);
644 h(i+1) = -s*dummy + c*h(i+1);
647 const double r = 1./std::sqrt(h(col)*h(col) + h(col+1)*h(col+1));
648 si(col) = h(col+1) *r;
650 h(col) = ci(col)*h(col) + si(col)*h(col+1);
651 b(col+1)= -si(col)*
b(col);
657 template <
class VectorType>
662 const unsigned int dim,
663 const unsigned int accumulated_iterations,
666 bool &reorthogonalize,
667 const boost::signals2::signal<
void(
int)> &reorthogonalize_signal)
670 const unsigned int inner_iteration = dim - 1;
673 double norm_vv_start = 0;
674 const bool consider_reorthogonalize = (reorthogonalize ==
false) &&
675 (inner_iteration % 5 == 4);
676 if (consider_reorthogonalize)
677 norm_vv_start = vv.l2_norm();
680 h(0) = vv * orthogonal_vectors[0];
681 for (
unsigned int i=1 ; i<dim ; ++i)
682 h(i) = vv.
add_and_dot(-h(i-1), orthogonal_vectors[i-1], orthogonal_vectors[i]);
683 double norm_vv = std::sqrt(vv.add_and_dot(-h(dim-1), orthogonal_vectors[dim-1], vv));
692 if (consider_reorthogonalize)
694 if (norm_vv > 10. * norm_vv_start *
695 std::sqrt(std::numeric_limits<typename VectorType::value_type>::epsilon()))
700 reorthogonalize =
true;
701 if (!reorthogonalize_signal.empty())
702 reorthogonalize_signal(accumulated_iterations);
706 if (reorthogonalize ==
true)
708 double htmp = vv * orthogonal_vectors[0];
710 for (
unsigned int i=1 ; i<dim ; ++i)
712 htmp = vv.
add_and_dot(-htmp, orthogonal_vectors[i-1], orthogonal_vectors[i]);
715 norm_vv = std::sqrt(vv.add_and_dot(-htmp, orthogonal_vectors[dim-1], vv));
723 template <
class VectorType>
727 const unsigned int dim,
728 const boost::signals2::signal<
void (
const std::vector<std::complex<double> > &)> &eigenvalues_signal,
730 const boost::signals2::signal<
void (
double)> &cond_signal)
733 if (!eigenvalues_signal.empty() || !hessenberg_signal.empty()
734 || !cond_signal.empty())
737 for (
unsigned int i=0; i<dim; ++i)
738 for (
unsigned int j=0; j<dim; ++j)
739 mat(i,j) = H_orig(i,j);
740 hessenberg_signal(H_orig);
742 if (!eigenvalues_signal.empty())
747 mat_eig.compute_eigenvalues();
748 std::vector<std::complex<double> >
eigenvalues(dim);
749 for (
unsigned int i=0; i<mat_eig.n(); ++i)
753 internal::SolverGMRESImplementation::complex_less_pred);
758 if (!cond_signal.empty() && (mat.n()>1))
761 double condition_number=mat.singular_value(0)/mat.singular_value(mat.n()-1);
762 cond_signal(condition_number);
769 template <
class VectorType>
770 template <
typename MatrixType,
typename PreconditionerType>
775 const PreconditionerType &preconditioner)
784 const unsigned int n_tmp_vectors = std::max(additional_data.
max_n_tmp_vectors, 3u);
792 unsigned int accumulated_iterations = 0;
794 const bool do_eigenvalues=
795 !condition_number_signal.empty()
796 ||!all_condition_numbers_signal.empty()
797 ||!eigenvalues_signal.empty()
798 ||!all_eigenvalues_signal.empty()
799 ||!hessenberg_signal.empty()
800 ||!all_hessenberg_signal.empty();
805 H_orig.
reinit(n_tmp_vectors, n_tmp_vectors-1);
808 H.reinit(n_tmp_vectors, n_tmp_vectors-1);
812 gamma(n_tmp_vectors),
813 ci (n_tmp_vectors-1),
814 si (n_tmp_vectors-1),
818 unsigned int dim = 0;
821 double last_res = -std::numeric_limits<double>::max();
833 VectorType &v = tmp_vectors(0, x);
834 VectorType &p = tmp_vectors(n_tmp_vectors-1, x);
840 std::unique_ptr<::Vector<double> > gamma_;
841 if (!use_default_residual)
848 gamma_ = std_cxx14::make_unique<::Vector<double> >(gamma.size());
860 h.
reinit (n_tmp_vectors-1);
862 if (left_precondition)
866 preconditioner.vmult(v,p);
874 double rho = v.l2_norm();
879 if (use_default_residual)
882 iteration_state = this->iteration_status (accumulated_iterations, rho, x);
889 deallog <<
"default_res=" << rho << std::endl;
891 if (left_precondition)
897 preconditioner.vmult(*r,v);
899 double res = r->l2_norm();
901 iteration_state = this->iteration_status (accumulated_iterations, res, x);
914 for (
unsigned int inner_iteration=0;
915 ((inner_iteration < n_tmp_vectors-2)
920 ++accumulated_iterations;
922 VectorType &vv = tmp_vectors(inner_iteration+1, x);
924 if (left_precondition)
926 A.vmult(p, tmp_vectors[inner_iteration]);
927 preconditioner.vmult(vv,p);
931 preconditioner.vmult(p, tmp_vectors[inner_iteration]);
935 dim = inner_iteration+1;
937 const double s = modified_gram_schmidt(tmp_vectors, dim,
938 accumulated_iterations,
939 vv, h, re_orthogonalize,
940 re_orthogonalize_signal);
941 h(inner_iteration+1) = s;
951 for (
unsigned int i=0; i<dim+1; ++i)
952 H_orig(i,inner_iteration) = h(i);
958 for (
unsigned int i=0; i<dim; ++i)
959 H(i,inner_iteration) = h(i);
962 rho = std::fabs(gamma(dim));
964 if (use_default_residual)
967 iteration_state = this->iteration_status (accumulated_iterations, rho, x);
971 deallog <<
"default_res=" << rho << std::endl;
976 H1.reinit(dim+1,dim);
978 for (
unsigned int i=0; i<dim+1; ++i)
979 for (
unsigned int j=0; j<dim; ++j)
982 H1.backward(h_,*gamma_);
984 if (left_precondition)
985 for (
unsigned int i=0 ; i<dim; ++i)
986 x_->add(h_(i), tmp_vectors[i]);
990 for (
unsigned int i=0; i<dim; ++i)
991 p.add(h_(i), tmp_vectors[i]);
992 preconditioner.vmult(*r,p);
998 if (left_precondition)
1000 const double res=r->l2_norm();
1003 iteration_state = this->iteration_status (accumulated_iterations, res, x);
1007 preconditioner.vmult(*x_, *r);
1008 const double preconditioned_res=x_->l2_norm();
1009 last_res = preconditioned_res;
1011 iteration_state = this->iteration_status (accumulated_iterations,
1012 preconditioned_res, x);
1019 H1.reinit(dim+1,dim);
1021 for (
unsigned int i=0; i<dim+1; ++i)
1022 for (
unsigned int j=0; j<dim; ++j)
1025 compute_eigs_and_cond(H_orig,dim,all_eigenvalues_signal,
1026 all_hessenberg_signal, condition_number_signal);
1028 H1.backward(h,gamma);
1030 if (left_precondition)
1031 for (
unsigned int i=0 ; i<dim; ++i)
1032 x.add(h(i), tmp_vectors[i]);
1036 for (
unsigned int i=0; i<dim; ++i)
1037 p.add(h(i), tmp_vectors[i]);
1038 preconditioner.vmult(v,p);
1046 compute_eigs_and_cond(H_orig,dim,eigenvalues_signal,hessenberg_signal,
1047 condition_number_signal);
1049 if (!krylov_space_signal.empty())
1050 krylov_space_signal(tmp_vectors);
1060 template <
class VectorType>
1061 boost::signals2::connection
1063 (
const std::function<
void(
double)> &slot,
1064 const bool every_iteration)
1066 if (every_iteration)
1068 return all_condition_numbers_signal.connect(slot);
1072 return condition_number_signal.connect(slot);
1078 template <
class VectorType>
1079 boost::signals2::connection
1081 (
const std::function<
void (
const std::vector<std::complex<double> > &)> &slot,
1082 const bool every_iteration)
1084 if (every_iteration)
1086 return all_eigenvalues_signal.connect(slot);
1090 return eigenvalues_signal.connect(slot);
1096 template <
class VectorType>
1097 boost::signals2::connection
1100 const bool every_iteration)
1102 if (every_iteration)
1104 return all_hessenberg_signal.connect(slot);
1108 return hessenberg_signal.connect(slot);
1114 template <
class VectorType>
1115 boost::signals2::connection
1119 return krylov_space_signal.connect(slot);
1124 template <
class VectorType>
1125 boost::signals2::connection
1127 (
const std::function<
void (
int)> &slot)
1129 return re_orthogonalize_signal.connect(slot);
1134 template <
class VectorType>
1147 template <
class VectorType>
1150 const AdditionalData &data)
1152 Solver<VectorType> (cn, mem),
1153 additional_data(data)
1158 template <
class VectorType>
1160 const AdditionalData &data)
1163 additional_data(data)
1168 template <
class VectorType>
1169 template <
typename MatrixType,
typename PreconditionerType>
1173 const VectorType &b,
1174 const PreconditionerType &preconditioner)
1180 const unsigned int basis_size = additional_data.max_basis_size;
1188 unsigned int accumulated_iterations = 0;
1191 H.reinit(basis_size+1, basis_size);
1198 double res = -std::numeric_limits<double>::max();
1205 aux->sadd(-1., 1., b);
1207 double beta = aux->l2_norm();
1209 iteration_state = this->iteration_status(accumulated_iterations, res, x);
1213 H.reinit(basis_size+1, basis_size);
1216 for (
unsigned int j=0; j<basis_size; ++j)
1219 v(j,x).equ(1./a, *aux);
1224 preconditioner.vmult(z(j,x), v[j]);
1225 A.vmult(*aux, z[j]);
1228 H(0,j) = *aux * v[0];
1229 for (
unsigned int i=1; i<=j; ++i)
1230 H(i,j) = aux->add_and_dot(-H(i-1,j), v[i-1], v[i]);
1231 H(j+1,j) = a = std::sqrt(aux->add_and_dot(-H(j,j), v[j], *aux));
1238 projected_rhs.
reinit(j+1);
1240 projected_rhs(0) = beta;
1248 res = house.least_squares(y, projected_rhs);
1249 iteration_state = this->iteration_status(++accumulated_iterations, res, x);
1256 for (
unsigned int j=0; j<y.
size(); ++j)
1269 DEAL_II_NAMESPACE_CLOSE
SolverFGMRES(SolverControl &cn, VectorMemory< VectorType > &mem, const AdditionalData &data=AdditionalData())
Number add_and_dot(const Number a, const Vector< Number > &V, const Vector< Number > &W)
TmpVectors(const unsigned int max_size, VectorMemory< VectorType > &vmem)
boost::signals2::connection connect_condition_number_slot(const std::function< void(double)> &slot, const bool every_iteration=false)
std::array< NumberType, 3 > givens_rotation(const NumberType &x, const NumberType &y)
boost::signals2::signal< void(const std::vector< std::complex< double > > &)> all_eigenvalues_signal
void solve(const MatrixType &A, VectorType &x, const VectorType &b, const PreconditionerType &preconditioner)
boost::signals2::connection connect_re_orthogonalization_slot(const std::function< void(int)> &slot)
AdditionalData additional_data
boost::signals2::signal< void(const internal::SolverGMRESImplementation::TmpVectors< VectorType > &)> krylov_space_signal
static ::ExceptionBase & ExcNotInitialized()
std::vector< typename VectorMemory< VectorType >::Pointer > data
#define AssertThrow(cond, exc)
static ::ExceptionBase & ExcIndexRange(int arg1, int arg2, int arg3)
AdditionalData additional_data
VectorType & operator()(const unsigned int i, const VectorType &temp)
static ::ExceptionBase & ExcTooFewTmpVectors(int arg1)
bool right_preconditioning
void solve(const MatrixType &A, VectorType &x, const VectorType &b, const PreconditionerType &preconditioner)
static ::ExceptionBase & ExcMessage(std::string arg1)
static void compute_eigs_and_cond(const FullMatrix< double > &H_orig, const unsigned int dim, const boost::signals2::signal< void(const std::vector< std::complex< double > > &)> &eigenvalues_signal, const boost::signals2::signal< void(const FullMatrix< double > &)> &hessenberg_signal, const boost::signals2::signal< void(double)> &cond_signal)
AdditionalData(const unsigned int max_n_tmp_vectors=30, const bool right_preconditioning=false, const bool use_default_residual=true, const bool force_re_orthogonalization=false)
#define DeclException1(Exception1, type1, outsequence)
Stop iteration, goal reached.
void reinit(const TableIndices< N > &new_size, const bool omit_default_initialization=false)
#define Assert(cond, exc)
boost::signals2::connection connect_krylov_space_slot(const std::function< void(const internal::SolverGMRESImplementation::TmpVectors< VectorType > &)> &slot)
unsigned int max_basis_size
boost::signals2::signal< void(const FullMatrix< double > &)> hessenberg_signal
static double modified_gram_schmidt(const internal::SolverGMRESImplementation::TmpVectors< VectorType > &orthogonal_vectors, const unsigned int dim, const unsigned int accumulated_iterations, VectorType &vv, Vector< double > &h, bool &re_orthogonalize, const boost::signals2::signal< void(int)> &re_orthogonalize_signal=boost::signals2::signal< void(int)>())
bool force_re_orthogonalization
boost::signals2::signal< void(int)> re_orthogonalize_signal
SymmetricTensor< 2, dim, Number > b(const Tensor< 2, dim, Number > &F)
VectorMemory< VectorType > & mem
virtual double criterion()
unsigned int size() const
boost::signals2::signal< void(double)> condition_number_signal
virtual void reinit(const size_type N, const bool omit_zeroing_entries=false)
std::array< Number, 1 > eigenvalues(const SymmetricTensor< 2, 1, Number > &T)
boost::signals2::signal< void(const FullMatrix< double > &)> all_hessenberg_signal
bool use_default_residual
VectorType & operator[](const unsigned int i) const
boost::signals2::connection connect_hessenberg_slot(const std::function< void(const FullMatrix< double > &)> &slot, const bool every_iteration=true)
AdditionalData(const unsigned int max_basis_size=30, const bool=true)
SolverGMRES(SolverControl &cn, VectorMemory< VectorType > &mem, const AdditionalData &data=AdditionalData())
void givens_rotation(Vector< double > &h, Vector< double > &b, Vector< double > &ci, Vector< double > &si, int col) const
boost::signals2::signal< void(const std::vector< std::complex< double > > &)> eigenvalues_signal
unsigned int max_n_tmp_vectors
boost::signals2::signal< void(double)> all_condition_numbers_signal
static ::ExceptionBase & ExcInternalError()
boost::signals2::connection connect_eigenvalues_slot(const std::function< void(const std::vector< std::complex< double > > &)> &slot, const bool every_iteration=false)