3#ifndef DUNE_ISTL_EIGENVALUE_ARPACKPP_HH_FORK
4#define DUNE_ISTL_EIGENVALUE_ARPACKPP_HH_FORK
13#include <dune/common/fvector.hh>
14#include <dune/common/exceptions.hh>
16#include <dune/istl/bvector.hh>
17#include <dune/istl/istlexception.hh>
18#include <dune/istl/io.hh>
50 template <
class BCRSMatrix>
51 class ArPackPlusPlus_BCRSMatrixWrapper
55 typedef typename BCRSMatrix::field_type Real;
59 ArPackPlusPlus_BCRSMatrixWrapper (
const BCRSMatrix& A)
61 a_(A_.M() * mBlock), n_(A_.N() * nBlock)
65 (BCRSMatrix::blocklevel == 2,
66 "Only BCRSMatrices with blocklevel 2 are supported.");
70 domainBlockVector.resize(A_.N(),
false);
71 rangeBlockVector.resize(A_.M(),
false);
75 inline void multMv (Real* v, Real* w)
78 arrayToDomainBlockVector(v,domainBlockVector);
81 A_.mv(domainBlockVector,rangeBlockVector);
84 rangeBlockVectorToArray(rangeBlockVector,w);
88 inline void multMtMv (Real* v, Real* w)
91 arrayToDomainBlockVector(v,domainBlockVector);
94 A_.mv(domainBlockVector,rangeBlockVector);
95 A_.mtv(rangeBlockVector,domainBlockVector);
98 domainBlockVectorToArray(domainBlockVector,w);
102 inline void multMMtv (Real* v, Real* w)
105 arrayToRangeBlockVector(v,rangeBlockVector);
108 A_.mtv(rangeBlockVector,domainBlockVector);
109 A_.mv(domainBlockVector,rangeBlockVector);
112 rangeBlockVectorToArray(rangeBlockVector,w);
116 inline int nrows ()
const {
return a_; }
119 inline int ncols ()
const {
return n_; }
123 constexpr static int mBlock = BCRSMatrix::block_type::rows;
124 constexpr static int nBlock = BCRSMatrix::block_type::cols;
128 constexpr static int dbvBlockSize = nBlock;
129 typedef Dune::FieldVector<Real,dbvBlockSize> DomainBlockVectorBlock;
130 typedef Dune::BlockVector<DomainBlockVectorBlock> DomainBlockVector;
134 constexpr static int rbvBlockSize = mBlock;
135 typedef Dune::FieldVector<Real,rbvBlockSize> RangeBlockVectorBlock;
136 typedef Dune::BlockVector<RangeBlockVectorBlock> RangeBlockVector;
139 typedef typename DomainBlockVector::size_type dbv_size_type;
140 typedef typename RangeBlockVector::size_type rbv_size_type;
141 typedef typename DomainBlockVectorBlock::size_type dbvb_size_type;
142 typedef typename RangeBlockVectorBlock::size_type rbvb_size_type;
147 domainBlockVectorToArray (
const DomainBlockVector& dbv, Real* v)
149 for (dbv_size_type block = 0; block < dbv.N(); ++block)
150 for (dbvb_size_type iBlock = 0; iBlock < dbvBlockSize; ++iBlock)
151 v[block*dbvBlockSize + iBlock] = dbv[block][iBlock];
157 rangeBlockVectorToArray (
const RangeBlockVector& rbv, Real* v)
159 for (rbv_size_type block = 0; block < rbv.N(); ++block)
160 for (rbvb_size_type iBlock = 0; iBlock < rbvBlockSize; ++iBlock)
161 v[block*rbvBlockSize + iBlock] = rbv[block][iBlock];
167 static inline void arrayToDomainBlockVector (
const Real* v,
168 DomainBlockVector& dbv)
170 for (dbv_size_type block = 0; block < dbv.N(); ++block)
171 for (dbvb_size_type iBlock = 0; iBlock < dbvBlockSize; ++iBlock)
172 dbv[block][iBlock] = v[block*dbvBlockSize + iBlock];
177 static inline void arrayToRangeBlockVector (
const Real* v,
178 RangeBlockVector& rbv)
180 for (rbv_size_type block = 0; block < rbv.N(); ++block)
181 for (rbvb_size_type iBlock = 0; iBlock < rbvBlockSize; ++iBlock)
182 rbv[block][iBlock] = v[block*rbvBlockSize + iBlock];
187 const BCRSMatrix& A_;
194 mutable DomainBlockVector domainBlockVector;
195 mutable RangeBlockVector rangeBlockVector;
200 template <
class BCRSMatrix>
201 class ArPackPlusPlus_BCRSMatrixWrapper2
205 typedef typename BCRSMatrix::field_type Real;
209 ArPackPlusPlus_BCRSMatrixWrapper2 (
const BCRSMatrix& A,
const BCRSMatrix& B)
212 a_(A_.M() * mBlock), n_(A_.N() * nBlock)
216 (BCRSMatrix::blocklevel == 2,
217 "Only BCRSMatrices with blocklevel 2 are supported.");
221 domainBlockVector.resize(A_.N(),
false);
222 rangeBlockVector.resize(A_.M(),
false);
226 inline void multMv (Real* v, Real* w)
229 arrayToDomainBlockVector(v,domainBlockVector);
232 B_.mv(domainBlockVector,rangeBlockVector);
234 Dune::InverseOperatorResult result;
235 auto rangeBlockVector2 = rangeBlockVector;
236 A_solver.apply(rangeBlockVector2, rangeBlockVector, result);
239 rangeBlockVectorToArray(rangeBlockVector2,w);
242 inline void multMvB (Real* v, Real* w)
245 arrayToDomainBlockVector(v,domainBlockVector);
248 B_.mv(domainBlockVector,rangeBlockVector);
251 rangeBlockVectorToArray(rangeBlockVector,w);
284 inline int nrows ()
const {
return a_; }
287 inline int ncols ()
const {
return n_; }
291 constexpr static int mBlock = BCRSMatrix::block_type::rows;
292 constexpr static int nBlock = BCRSMatrix::block_type::cols;
296 constexpr static int dbvBlockSize = nBlock;
297 typedef Dune::FieldVector<Real,dbvBlockSize> DomainBlockVectorBlock;
298 typedef Dune::BlockVector<DomainBlockVectorBlock> DomainBlockVector;
302 constexpr static int rbvBlockSize = mBlock;
303 typedef Dune::FieldVector<Real,rbvBlockSize> RangeBlockVectorBlock;
304 typedef Dune::BlockVector<RangeBlockVectorBlock> RangeBlockVector;
307 typedef typename DomainBlockVector::size_type dbv_size_type;
308 typedef typename RangeBlockVector::size_type rbv_size_type;
309 typedef typename DomainBlockVectorBlock::size_type dbvb_size_type;
310 typedef typename RangeBlockVectorBlock::size_type rbvb_size_type;
315 domainBlockVectorToArray (
const DomainBlockVector& dbv, Real* v)
317 for (dbv_size_type block = 0; block < dbv.N(); ++block)
318 for (dbvb_size_type iBlock = 0; iBlock < dbvBlockSize; ++iBlock)
319 v[block*dbvBlockSize + iBlock] = dbv[block][iBlock];
325 rangeBlockVectorToArray (
const RangeBlockVector& rbv, Real* v)
327 for (rbv_size_type block = 0; block < rbv.N(); ++block)
328 for (rbvb_size_type iBlock = 0; iBlock < rbvBlockSize; ++iBlock)
329 v[block*rbvBlockSize + iBlock] = rbv[block][iBlock];
335 static inline void arrayToDomainBlockVector (
const Real* v,
336 DomainBlockVector& dbv)
338 for (dbv_size_type block = 0; block < dbv.N(); ++block)
339 for (dbvb_size_type iBlock = 0; iBlock < dbvBlockSize; ++iBlock)
340 dbv[block][iBlock] = v[block*dbvBlockSize + iBlock];
345 static inline void arrayToRangeBlockVector (
const Real* v,
346 RangeBlockVector& rbv)
348 for (rbv_size_type block = 0; block < rbv.N(); ++block)
349 for (rbvb_size_type iBlock = 0; iBlock < rbvBlockSize; ++iBlock)
350 rbv[block][iBlock] = v[block*rbvBlockSize + iBlock];
355 const BCRSMatrix& A_;
356 const BCRSMatrix& B_;
358 Dune::UMFPack<BCRSMatrix> A_solver;
365 mutable DomainBlockVector domainBlockVector;
366 mutable RangeBlockVector rangeBlockVector;
407 template <
typename BCRSMatrix,
typename BlockVector>
408 class ArPackPlusPlus_Algorithms
411 typedef typename BlockVector::field_type Real;
432 ArPackPlusPlus_Algorithms (
const BCRSMatrix& m,
433 const unsigned int nIterationsMax = 100000,
434 const unsigned int verbosity_level = 0)
435 : a_(m), nIterationsMax_(nIterationsMax),
436 verbosity_level_(verbosity_level),
438 title_(
" ArPackPlusPlus_Algorithms: "),
439 blank_(title_.length(),
' ')
453 inline void computeSymMaxMagnitude (
const Real& epsilon,
454 BlockVector& x, Real& lambda)
const
457 if (verbosity_level_ > 0)
458 std::cout << title_ <<
"Computing an approximation of "
459 <<
"the dominant eigenvalue of a matrix which "
460 <<
"is assumed to be symmetric." << std::endl;
464 typedef ArPackPlusPlus_BCRSMatrixWrapper<BCRSMatrix> WrappedMatrix;
468 const int nrows = A.nrows();
469 const int ncols = A.ncols();
473 DUNE_THROW(Dune::ISTLError,
"Matrix is not square ("
474 << nrows <<
"x" << ncols <<
").");
479 const Real tol = epsilon;
480 const int maxit = nIterationsMax_*nev;
481 Real* ev =
new Real[nev];
482 const bool ivec =
true;
487 ARSymStdEig<Real,WrappedMatrix>
488 dprob(nrows, nev, &A, &WrappedMatrix::multMv, which, ncv, tol, maxit);
491 if (verbosity_level_ > 3) dprob.Trace();
494 nconv = dprob.Eigenvalues(ev,ivec);
500 Real* x_raw = dprob.RawEigenvector(nev-1);
501 WrappedMatrix::arrayToDomainBlockVector(x_raw,x);
504 nIterations_ = dprob.GetIter();
508 Real* Ax_raw =
new Real[nrows];
509 A.multMv(x_raw,Ax_raw);
510 WrappedMatrix::arrayToDomainBlockVector(Ax_raw,r);
512 const Real r_norm = r.two_norm();
515 if (verbosity_level_ > 0)
517 if (verbosity_level_ > 1)
520 std::cout << blank_ <<
"Obtained eigenvalues of A by solving "
521 <<
"A*x = λ*x using the ARPACK++ class ARSym"
522 <<
"StdEig:" << std::endl;
523 std::cout << blank_ <<
" converged eigenvalues of A: "
524 << nconv <<
" / " << nev << std::endl;
525 std::cout << blank_ <<
" dominant eigenvalue of A: "
526 << lambda << std::endl;
528 std::cout << blank_ <<
"Result ("
529 <<
"#iterations = " << nIterations_ <<
", "
530 <<
"║residual║_2 = " << r_norm <<
"): "
531 <<
"λ = " << lambda << std::endl;
532 if (verbosity_level_ > 2)
535 Dune::printvector(std::cout,x,blank_+
"x",blank_+
"row");
545 inline void computeGenSymMaxMagnitude (
const BCRSMatrix& b_,
const Real& epsilon,
546 BlockVector& x, Real& lambda)
const
549 if (verbosity_level_ > 0)
550 std::cout << title_ <<
"Computing an approximation of "
551 <<
"the dominant eigenvalue of a matrix which "
552 <<
"is assumed to be symmetric." << std::endl;
556 typedef ArPackPlusPlus_BCRSMatrixWrapper<BCRSMatrix> WrappedMatrix;
561 const int nrows = A.nrows();
562 const int ncols = A.ncols();
566 DUNE_THROW(Dune::ISTLError,
"Matrix is not square ("
567 << nrows <<
"x" << ncols <<
").");
572 const Real tol = epsilon;
573 const int maxit = nIterationsMax_*nev;
574 Real* ev =
new Real[nev];
575 const bool ivec =
true;
580 ARSymGenEig<Real,WrappedMatrix,WrappedMatrix>
581 dprob(nrows, nev, &A, &WrappedMatrix::multMv, &B, &WrappedMatrix::multMv, which, ncv, tol, maxit);
584 if (verbosity_level_ > 3) dprob.Trace();
587 nconv = dprob.Eigenvalues(ev,ivec);
593 Real* x_raw = dprob.RawEigenvector(nev-1);
594 WrappedMatrix::arrayToDomainBlockVector(x_raw,x);
597 nIterations_ = dprob.GetIter();
601 Real* Ax_raw =
new Real[nrows];
602 A.multMv(x_raw,Ax_raw);
603 WrappedMatrix::arrayToDomainBlockVector(Ax_raw,r);
605 const Real r_norm = r.two_norm();
608 if (verbosity_level_ > 0)
610 if (verbosity_level_ > 1)
613 std::cout << blank_ <<
"Obtained eigenvalues of A by solving "
614 <<
"A*x = λ*x using the ARPACK++ class ARSym"
615 <<
"StdEig:" << std::endl;
616 std::cout << blank_ <<
" converged eigenvalues of A: "
617 << nconv <<
" / " << nev << std::endl;
618 std::cout << blank_ <<
" dominant eigenvalue of A: "
619 << lambda << std::endl;
621 std::cout << blank_ <<
"Result ("
622 <<
"#iterations = " << nIterations_ <<
", "
623 <<
"║residual║_2 = " << r_norm <<
"): "
624 <<
"λ = " << lambda << std::endl;
625 if (verbosity_level_ > 2)
628 Dune::printvector(std::cout,x,blank_+
"x",blank_+
"row");
649 inline void computeSymMinMagnitude (
const Real& epsilon,
650 BlockVector& x, Real& lambda)
const
653 if (verbosity_level_ > 0)
654 std::cout << title_ <<
"Computing an approximation of the "
655 <<
"least dominant eigenvalue of a matrix which "
656 <<
"is assumed to be symmetric." << std::endl;
660 typedef ArPackPlusPlus_BCRSMatrixWrapper<BCRSMatrix> WrappedMatrix;
664 const int nrows = A.nrows();
665 const int ncols = A.ncols();
669 DUNE_THROW(Dune::ISTLError,
"Matrix is not square ("
670 << nrows <<
"x" << ncols <<
").");
675 const Real tol = epsilon;
676 const int maxit = nIterationsMax_*nev;
677 Real* ev =
new Real[nev];
678 const bool ivec =
true;
684 ARSymStdEig<Real,WrappedMatrix>
686 dprob(nrows, nev, &A, &WrappedMatrix::multMv, which, ncv, tol, maxit);
689 if (verbosity_level_ > 3) dprob.Trace();
692 nconv = dprob.Eigenvalues(ev,ivec);
698 Real* x_raw = dprob.RawEigenvector(nev-1);
699 WrappedMatrix::arrayToDomainBlockVector(x_raw,x);
702 nIterations_ = dprob.GetIter();
706 Real* Ax_raw =
new Real[nrows];
707 A.multMv(x_raw,Ax_raw);
708 WrappedMatrix::arrayToDomainBlockVector(Ax_raw,r);
710 const Real r_norm = r.two_norm();
713 if (verbosity_level_ > 0)
715 if (verbosity_level_ > 1)
718 std::cout << blank_ <<
"Obtained eigenvalues of A by solving "
719 <<
"A*x = λ*x using the ARPACK++ class ARSym"
720 <<
"StdEig:" << std::endl;
721 std::cout << blank_ <<
" converged eigenvalues of A: "
722 << nconv <<
" / " << nev << std::endl;
723 std::cout << blank_ <<
" least dominant eigenvalue of A: "
724 << lambda << std::endl;
726 std::cout << blank_ <<
"Result ("
727 <<
"#iterations = " << nIterations_ <<
", "
728 <<
"║residual║_2 = " << r_norm <<
"): "
729 <<
"λ = " << lambda << std::endl;
730 if (verbosity_level_ > 2)
733 Dune::printvector(std::cout,x,blank_+
"x",blank_+
"row");
742 inline void computeGenSymMinMagnitude (
const BCRSMatrix& b_,
const Real& epsilon,
int& nev,
743 std::vector<BlockVector>& x, std::vector<Real>& lambda, Real sigma)
const
746 if (verbosity_level_ > 0)
747 std::cout << title_ <<
"Computing an approximation of the "
748 <<
"least dominant eigenvalue of a matrix which "
749 <<
"is assumed to be symmetric." << std::endl;
756 const Real tol = epsilon;
757 const int maxit = nIterationsMax_*nev;
758 Real* ev =
new Real[nev];
759 Real* ev_imag =
new Real[nev];
760 const bool ivec =
true;
762 char invertmodep =
'S';
764 BCRSMatrix ashiftb(a_);
765 ashiftb.axpy(-sigma,b_);
769 typedef ArPackPlusPlus_BCRSMatrixWrapper2<BCRSMatrix> WrappedMatrix;
770 WrappedMatrix A(ashiftb,b_);
773 const int nrows = A.nrows();
774 const int ncols = A.ncols();
778 DUNE_THROW(Dune::ISTLError,
"Matrix is not square ("
779 << nrows <<
"x" << ncols <<
").");
787 ARSymStdEig<Real,WrappedMatrix>
788 dprob(nrows, nev, &A, &WrappedMatrix::multMv, which, ncv, tol, maxit);
792 if (verbosity_level_ > 3) dprob.Trace();
795 nconv = dprob.Eigenvalues(ev,ev_imag,ivec);
798 std::vector<int> index(nev, 0);
799 for (
int i = 0 ; i != index.size() ; i++) {
802 std::sort(index.begin(), index.end(),
803 [&](
const int& a,
const int& b) {
804 return (sigma+1./ev[a] < sigma+1./ev[b]);
812 for (
int i = 0; i < nev; i++) {
813 lambda[i] = sigma+1./ev[index[i]];
814 Real* x_raw = dprob.RawEigenvector(index[i]);
815 WrappedMatrix::arrayToDomainBlockVector(x_raw,x[i]);
819 nIterations_ = dprob.GetIter();
860 inline void computeGenNonSymMinMagnitude (
const BCRSMatrix& b_,
const Real& epsilon,
int& nev,
861 std::vector<BlockVector>& x, std::vector<Real>& lambda, Real sigma)
const
864 if (verbosity_level_ > 0)
865 std::cout << title_ <<
"Computing an approximation of the "
866 <<
"least dominant eigenvalue of a matrix which "
867 <<
"is assumed to be symmetric." << std::endl;
874 const Real tol = epsilon;
875 const int maxit = nIterationsMax_*nev;
876 Real* ev =
new Real[nev];
877 Real* ev_imag =
new Real[nev];
878 const bool ivec =
true;
882 BCRSMatrix ashiftb(a_);
883 ashiftb.axpy(-sigma,b_);
887 typedef ArPackPlusPlus_BCRSMatrixWrapper2<BCRSMatrix> WrappedMatrix;
888 WrappedMatrix A(ashiftb,b_);
891 const int nrows = A.nrows();
892 const int ncols = A.ncols();
896 DUNE_THROW(Dune::ISTLError,
"Matrix is not square ("
897 << nrows <<
"x" << ncols <<
").");
905 ARNonSymStdEig<Real,WrappedMatrix>
906 dprob(nrows, nev, &A, &WrappedMatrix::multMv, which, ncv, tol, maxit);
910 if (verbosity_level_ > 3) dprob.Trace();
913 nconv = dprob.Eigenvalues(ev,ev_imag,ivec);
914 if (verbosity_level_ > 3) std::cout << nconv << std::endl;
917 std::vector<int> index(nev, 0);
918 for (
unsigned int i = 0 ; i != index.size() ; i++) {
921 std::sort(index.begin(), index.end(),
922 [&](
const int& a,
const int& b) {
923 return (sigma+1./ev[a] < sigma+1./ev[b]);
931 for (
int i = 0; i < nev; i++) {
932 lambda[i] = sigma+1./ev[index[i]];
933 Real* x_raw = dprob.RawEigenvector(index[i]);
934 WrappedMatrix::arrayToDomainBlockVector(x_raw,x[i]);
938 nIterations_ = dprob.GetIter();
989 inline void computeSymCond2 (
const Real& epsilon, Real& cond_2)
const
992 if (verbosity_level_ > 0)
993 std::cout << title_ <<
"Computing an approximation of the "
994 <<
"spectral condition number of a matrix which "
995 <<
"is assumed to be symmetric." << std::endl;
999 typedef ArPackPlusPlus_BCRSMatrixWrapper<BCRSMatrix> WrappedMatrix;
1000 WrappedMatrix A(a_);
1003 const int nrows = A.nrows();
1004 const int ncols = A.ncols();
1008 DUNE_THROW(Dune::ISTLError,
"Matrix is not square ("
1009 << nrows <<
"x" << ncols <<
").");
1014 const Real tol = epsilon;
1015 const int maxit = nIterationsMax_*nev;
1016 Real* ev =
new Real[nev];
1017 const bool ivec =
true;
1021 char which[] =
"BE";
1022 ARSymStdEig<Real,WrappedMatrix>
1023 dprob(nrows, nev, &A, &WrappedMatrix::multMv, which, ncv, tol, maxit);
1026 if (verbosity_level_ > 3) dprob.Trace();
1029 nconv = dprob.Eigenvalues(ev,ivec);
1032 const Real& lambda_max = ev[nev-1];
1033 const Real& lambda_min = ev[0];
1036 Real* x_max_raw = dprob.RawEigenvector(nev-1);
1037 Real* x_min_raw = dprob.RawEigenvector(0);
1040 cond_2 = std::abs(lambda_max / lambda_min);
1043 nIterations_ = dprob.GetIter();
1046 Real* Ax_max_raw =
new Real[nrows];
1047 Real* Ax_min_raw =
new Real[nrows];
1048 A.multMv(x_max_raw,Ax_max_raw);
1049 A.multMv(x_min_raw,Ax_min_raw);
1050 Real r_max_norm = 0.0;
1051 Real r_min_norm = 0.0;
1052 for (
int i = 0; i < nrows; ++i)
1054 r_max_norm += std::pow(Ax_max_raw[i] - lambda_max * x_max_raw[i],2);
1055 r_min_norm += std::pow(Ax_min_raw[i] - lambda_min * x_min_raw[i],2);
1057 r_max_norm = std::sqrt(r_max_norm);
1058 r_min_norm = std::sqrt(r_min_norm);
1061 if (verbosity_level_ > 0)
1063 if (verbosity_level_ > 1)
1066 std::cout << blank_ <<
"Obtained eigenvalues of A by solving "
1067 <<
"A*x = λ*x using the ARPACK++ class ARSym"
1068 <<
"StdEig:" << std::endl;
1069 std::cout << blank_ <<
" converged eigenvalues of A: "
1070 << nconv <<
" / " << nev << std::endl;
1071 std::cout << blank_ <<
" dominant eigenvalue of A: "
1072 << lambda_max << std::endl;
1073 std::cout << blank_ <<
" least dominant eigenvalue of A: "
1074 << lambda_min << std::endl;
1075 std::cout << blank_ <<
" spectral condition number of A: "
1076 << cond_2 << std::endl;
1078 std::cout << blank_ <<
"Result ("
1079 <<
"#iterations = " << nIterations_ <<
", "
1080 <<
"║residual║_2 = {" << r_max_norm <<
","
1081 << r_min_norm <<
"}, " <<
"λ = {"
1082 << lambda_max <<
"," << lambda_min
1083 <<
"}): cond_2 = " << cond_2 << std::endl;
1087 delete[] Ax_min_raw;
1088 delete[] Ax_max_raw;
1105 inline void computeNonSymMax (
const Real& epsilon,
1106 BlockVector& x, Real& sigma)
const
1109 if (verbosity_level_ > 0)
1110 std::cout << title_ <<
"Computing an approximation of the "
1111 <<
"largest singular value of a matrix which "
1112 <<
"is assumed to be nonsymmetric." << std::endl;
1116 typedef ArPackPlusPlus_BCRSMatrixWrapper<BCRSMatrix> WrappedMatrix;
1117 WrappedMatrix A(a_);
1120 const int nrows = A.nrows();
1121 const int ncols = A.ncols();
1125 DUNE_THROW(Dune::ISTLError,
"Matrix has less rows than "
1126 <<
"columns (" << nrows <<
"x" << ncols <<
")."
1127 <<
" This case is not implemented, yet.");
1132 const Real tol = epsilon;
1133 const int maxit = nIterationsMax_*nev;
1134 Real* ev =
new Real[nev];
1135 const bool ivec =
true;
1139 char which[] =
"LA";
1140 ARSymStdEig<Real,WrappedMatrix>
1141 dprob(ncols, nev, &A, &WrappedMatrix::multMtMv, which, ncv, tol, maxit);
1144 if (verbosity_level_ > 3) dprob.Trace();
1147 nconv = dprob.Eigenvalues(ev,ivec);
1150 const Real& lambda = ev[nev-1];
1153 Real* x_raw = dprob.RawEigenvector(nev-1);
1154 WrappedMatrix::arrayToDomainBlockVector(x_raw,x);
1157 nIterations_ = dprob.GetIter();
1161 Real* AtAx_raw =
new Real[ncols];
1162 A.multMtMv(x_raw,AtAx_raw);
1163 WrappedMatrix::arrayToDomainBlockVector(AtAx_raw,r);
1165 const Real r_norm = r.two_norm();
1169 sigma = std::sqrt(lambda);
1172 if (verbosity_level_ > 0)
1174 if (verbosity_level_ > 1)
1177 std::cout << blank_ <<
"Obtained singular values of A by sol"
1178 <<
"ving (A^T*A)*x = σ²*x using the ARPACK++ "
1179 <<
"class ARSymStdEig:" << std::endl;
1180 std::cout << blank_ <<
" converged eigenvalues of A^T*A: "
1181 << nconv <<
" / " << nev << std::endl;
1182 std::cout << blank_ <<
" largest eigenvalue of A^T*A: "
1183 << lambda << std::endl;
1184 std::cout << blank_ <<
" => largest singular value of A: "
1185 << sigma << std::endl;
1187 std::cout << blank_ <<
"Result ("
1188 <<
"#iterations = " << nIterations_ <<
", "
1189 <<
"║residual║_2 = " << r_norm <<
"): "
1190 <<
"σ = " << sigma << std::endl;
1191 if (verbosity_level_ > 2)
1195 Dune::printvector(std::cout,x,blank_+
"x",blank_+
"row");
1217 inline void computeNonSymMin (
const BCRSMatrix& b_,
const Real& epsilon,
1218 BlockVector& x, Real& sigma)
const
1221 if (verbosity_level_ > 0)
1222 std::cout << title_ <<
"Computing an approximation of the "
1223 <<
"smallest singular value of a matrix which "
1224 <<
"is assumed to be nonsymmetric." << std::endl;
1228 typedef ArPackPlusPlus_BCRSMatrixWrapper<BCRSMatrix> WrappedMatrix;
1229 WrappedMatrix A(a_);
1230 WrappedMatrix B(b_);
1233 const int nrows = A.nrows();
1234 const int ncols = A.ncols();
1238 DUNE_THROW(Dune::ISTLError,
"Matrix has less rows than "
1239 <<
"columns (" << nrows <<
"x" << ncols <<
")."
1240 <<
" This case is not implemented, yet.");
1245 const Real tol = epsilon;
1246 const int maxit = nIterationsMax_*nev;
1247 Real* ev =
new Real[nev];
1248 Real* ev_imag =
new Real[nev];
1249 const bool ivec =
true;
1253 char which[] =
"SM";
1254 ARNonSymGenEig<Real,WrappedMatrix,WrappedMatrix>
1255 dprob(ncols, nev, &A, &WrappedMatrix::multMv, &B, &WrappedMatrix::multMv, which, ncv, tol, maxit);
1258 if (verbosity_level_ > 3) dprob.Trace();
1261 nconv = dprob.Eigenvalues(ev,ev_imag,ivec);
1264 const Real& lambda = ev[nev-1];
1267 Real* x_raw = dprob.RawEigenvector(nev-1);
1268 WrappedMatrix::arrayToDomainBlockVector(x_raw,x);
1271 nIterations_ = dprob.GetIter();
1275 Real* AtAx_raw =
new Real[ncols];
1276 A.multMtMv(x_raw,AtAx_raw);
1277 WrappedMatrix::arrayToDomainBlockVector(AtAx_raw,r);
1279 const Real r_norm = r.two_norm();
1283 sigma = std::sqrt(lambda);
1286 if (verbosity_level_ > 0)
1288 if (verbosity_level_ > 1)
1291 std::cout << blank_ <<
"Obtained singular values of A by sol"
1292 <<
"ving (A^T*A)*x = σ²*x using the ARPACK++ "
1293 <<
"class ARSymStdEig:" << std::endl;
1294 std::cout << blank_ <<
" converged eigenvalues of A^T*A: "
1295 << nconv <<
" / " << nev << std::endl;
1296 std::cout << blank_ <<
" smallest eigenvalue of A^T*A: "
1297 << lambda << std::endl;
1298 std::cout << blank_ <<
" => smallest singular value of A: "
1299 << sigma << std::endl;
1301 std::cout << blank_ <<
"Result ("
1302 <<
"#iterations = " << nIterations_ <<
", "
1303 <<
"║residual║_2 = " << r_norm <<
"): "
1304 <<
"σ = " << sigma << std::endl;
1305 if (verbosity_level_ > 2)
1309 Dune::printvector(std::cout,x,blank_+
"x",blank_+
"row");
1328 inline void computeNonSymCond2 (
const Real& epsilon, Real& cond_2)
const
1331 if (verbosity_level_ > 0)
1332 std::cout << title_ <<
"Computing an approximation of the "
1333 <<
"spectral condition number of a matrix which "
1334 <<
"is assumed to be nonsymmetric." << std::endl;
1338 typedef ArPackPlusPlus_BCRSMatrixWrapper<BCRSMatrix> WrappedMatrix;
1339 WrappedMatrix A(a_);
1342 const int nrows = A.nrows();
1343 const int ncols = A.ncols();
1347 DUNE_THROW(Dune::ISTLError,
"Matrix has less rows than "
1348 <<
"columns (" << nrows <<
"x" << ncols <<
")."
1349 <<
" This case is not implemented, yet.");
1354 const Real tol = epsilon;
1355 const int maxit = nIterationsMax_*nev;
1356 Real* ev =
new Real[nev];
1357 const bool ivec =
true;
1361 char which[] =
"BE";
1362 ARSymStdEig<Real,WrappedMatrix>
1363 dprob(ncols, nev, &A, &WrappedMatrix::multMtMv, which, ncv, tol, maxit);
1366 if (verbosity_level_ > 3) dprob.Trace();
1369 nconv = dprob.Eigenvalues(ev,ivec);
1372 const Real& lambda_max = ev[nev-1];
1373 const Real& lambda_min = ev[0];
1376 Real* x_max_raw = dprob.RawEigenvector(nev-1);
1377 Real* x_min_raw = dprob.RawEigenvector(0);
1380 nIterations_ = dprob.GetIter();
1383 Real* AtAx_max_raw =
new Real[ncols];
1384 Real* AtAx_min_raw =
new Real[ncols];
1385 A.multMtMv(x_max_raw,AtAx_max_raw);
1386 A.multMtMv(x_min_raw,AtAx_min_raw);
1387 Real r_max_norm = 0.0;
1388 Real r_min_norm = 0.0;
1389 for (
int i = 0; i < ncols; ++i)
1391 r_max_norm += std::pow(AtAx_max_raw[i] - lambda_max * x_max_raw[i],2);
1392 r_min_norm += std::pow(AtAx_min_raw[i] - lambda_min * x_min_raw[i],2);
1394 r_max_norm = std::sqrt(r_max_norm);
1395 r_min_norm = std::sqrt(r_min_norm);
1398 const Real sigma_max = std::sqrt(lambda_max);
1399 const Real sigma_min = std::sqrt(lambda_min);
1402 cond_2 = sigma_max / sigma_min;
1405 if (verbosity_level_ > 0)
1407 if (verbosity_level_ > 1)
1410 std::cout << blank_ <<
"Obtained singular values of A by sol"
1411 <<
"ving (A^T*A)*x = σ²*x using the ARPACK++ "
1412 <<
"class ARSymStdEig:" << std::endl;
1413 std::cout << blank_ <<
" converged eigenvalues of A^T*A: "
1414 << nconv <<
" / " << nev << std::endl;
1415 std::cout << blank_ <<
" largest eigenvalue of A^T*A: "
1416 << lambda_max << std::endl;
1417 std::cout << blank_ <<
" smallest eigenvalue of A^T*A: "
1418 << lambda_min << std::endl;
1419 std::cout << blank_ <<
" => largest singular value of A: "
1420 << sigma_max << std::endl;
1421 std::cout << blank_ <<
" => smallest singular value of A: "
1422 << sigma_min << std::endl;
1424 std::cout << blank_ <<
"Result ("
1425 <<
"#iterations = " << nIterations_ <<
", "
1426 <<
"║residual║_2 = {" << r_max_norm <<
","
1427 << r_min_norm <<
"}, " <<
"σ = {"
1428 << sigma_max <<
"," << sigma_min
1429 <<
"}): cond_2 = " << cond_2 << std::endl;
1433 delete[] AtAx_min_raw;
1434 delete[] AtAx_max_raw;
1442 inline unsigned int getIterationCount ()
const
1444 if (nIterations_ == 0)
1445 DUNE_THROW(Dune::ISTLError,
"No algorithm applied, yet.");
1447 return nIterations_;
1452 const BCRSMatrix& a_;
1453 const unsigned int nIterationsMax_;
1456 const unsigned int verbosity_level_;
1461 mutable unsigned int nIterations_;
1464 const std::string title_;
1465 const std::string blank_;