26 #ifndef OOMPH_TRILINOS_EIGEN_SOLVER_HEADER
27 #define OOMPH_TRILINOS_EIGEN_SOLVER_HEADER
36 #include "AnasaziOutputManager.hpp"
37 #include "AnasaziBasicOutputManager.hpp"
38 #include "AnasaziConfigDefs.hpp"
39 #include "AnasaziOperator.hpp"
40 #include "AnasaziMultiVec.hpp"
41 #include "AnasaziBasicEigenproblem.hpp"
42 #include "AnasaziBlockKrylovSchurSolMgr.hpp"
54 class MultiVecTraits<double,
oomph::DoubleMultiVector>
59 static Teuchos::RCP<oomph::DoubleMultiVector>
Clone(
67 static Teuchos::RCP<oomph::DoubleMultiVector>
CloneCopy(
77 static Teuchos::RCP<oomph::DoubleMultiVector>
CloneCopy(
85 static Teuchos::RCP<oomph::DoubleMultiVector>
CloneCopy(
116 static Teuchos::RCP<const oomph::DoubleMultiVector>
CloneView(
127 static Teuchos::RCP<oomph::DoubleMultiVector>
CloneView(
138 static Teuchos::RCP<oomph::DoubleMultiVector>
CloneView(
147 return static_cast<int>(mv.
nrow());
153 return static_cast<int>(mv.
nvector());
160 const Teuchos::SerialDenseMatrix<int, double>&
B,
171 int mv_n_vector = mv.
nvector();
177 for (
int i = 0;
i < n_row_local; ++
i)
179 for (
int j = 0; j < mv_n_vector; j++)
182 for (
int k = 0; k < A_n_vector; k++)
184 res += C(k,
i) *
B(k, j);
198 const unsigned n_vector = A.
nvector();
200 for (
unsigned v = 0; v < n_vector; v++)
202 for (
unsigned i = 0;
i < n_row_local;
i++)
204 mv(v,
i) = alpha * A(v,
i) + beta *
B(v,
i);
220 const std::vector<double>& alpha)
222 const unsigned n_vector = mv.
nvector();
224 for (
unsigned v = 0; v < n_vector; v++)
226 for (
unsigned i = 0;
i < n_row_local;
i++)
228 mv(v,
i) *= alpha[v];
239 Teuchos::SerialDenseMatrix<int, double>&
B)
241 const unsigned A_nvec = A.
nvector();
243 const unsigned mv_nvec = mv.
nvector();
246 for (
unsigned v1 = 0; v1 < A_nvec; v1++)
248 for (
unsigned v2 = 0; v2 < mv_nvec; v2++)
251 for (
unsigned i = 0;
i < A_nrow_local;
i++)
253 B(v1, v2) += A(v1,
i) * mv(v2,
i);
264 const int n_total_val = A_nvec * mv_nvec;
266 double b[n_total_val];
267 double b2[n_total_val];
269 for (
unsigned v1 = 0; v1 < A_nvec; v1++)
271 for (
unsigned v2 = 0; v2 < mv_nvec; v2++)
273 b[count] =
B(v1, v2);
274 b2[count] = b[count];
288 for (
unsigned v1 = 0; v1 < A_nvec; v1++)
290 for (
unsigned v2 = 0; v2 < mv_nvec; v2++)
292 B(v1, v2) = b2[count];
307 std::vector<double>& b)
318 std::vector<double>& normvec)
335 const std::vector<int>& index,
339 const unsigned n_index = index.size();
345 for (
unsigned v = 0; v < n_index; v++)
347 for (
unsigned i = 0;
i < n_row_local;
i++)
349 mv(index[v],
i) = A(v,
i);
367 const Teuchos::Range1D& index,
371 const unsigned n_index = index.size();
377 unsigned range_index = index.lbound();
378 for (
unsigned v = 0; v < n_index; v++)
380 for (
unsigned i = 0;
i < n_row_local;
i++)
382 mv(range_index,
i) = A(v,
i);
401 const unsigned n_vector = mv.
nvector();
403 for (
unsigned v = 0; v < n_vector; v++)
405 for (
unsigned i = 0;
i < n_row_local;
i++)
407 mv(v,
i) = Teuchos::ScalarTraits<double>::random();
416 const double alpha = Teuchos::ScalarTraits<double>::zero())
468 class OperatorTraits<double,
469 oomph::DoubleMultiVector,
509 const double& sigma = 0.0)
539 const unsigned n_vec = x.
nvector();
561 for (
unsigned i = 0;
i < n_row_local;
i++)
567 for (
unsigned v = 1; v < n_vec; ++v)
576 for (
unsigned i = 0;
i < n_row_local;
i++)
608 const double& sigma = 0.0)
633 const unsigned n_vec = x.
nvector();
650 for (
unsigned i = 0;
i < n_row_local;
i++)
656 for (
unsigned v = 1; v < n_vec; ++v)
661 for (
unsigned i = 0;
i < n_row_local;
i++)
677 typedef Teuchos::ScalarTraits<ST>
SCT;
678 typedef SCT::magnitudeType
MT;
679 typedef Anasazi::MultiVec<ST>
MV;
680 typedef Anasazi::Operator<ST>
OP;
681 typedef Anasazi::MultiVecTraits<ST, MV>
MVT;
682 typedef Anasazi::OperatorTraits<ST, MV, OP>
OPT;
719 verbosity += Anasazi::Warnings;
720 verbosity += Anasazi::FinalSummary;
721 verbosity += Anasazi::TimingDetails;
726 << Anasazi::Anasazi_Version() << std::endl
777 Vector<std::complex<double>>& alpha,
781 const bool& do_adjoint_problem)
791 unsigned n = eigenvalue.size();
794 for (
unsigned i = 0;
i < n;
i++)
796 alpha[
i] = eigenvalue[
i];
804 Vector<std::complex<double>>& eigenvalue,
807 const bool& do_adjoint_problem)
817 Teuchos::RCP<DoubleMultiVector> initial =
819 Anasazi::MultiVecTraits<double, DoubleMultiVector>::MvRandom(*initial);
822 Teuchos::RCP<DoubleMultiVectorOperator> Op_pt;
823 if (do_adjoint_problem)
835 Teuchos::RCP<Anasazi::BasicEigenproblem<double,
838 anasazi_pt = Teuchos::rcp(
839 new Anasazi::BasicEigenproblem<
double,
845 anasazi_pt->setHermitian(
false);
848 anasazi_pt->setNEV(n_eval);
851 if (anasazi_pt->setProblem() !=
true)
853 oomph_info <<
"Anasazi::BasicEigenproblem::setProblem() had an error."
855 <<
"End Result: TEST FAILED" << std::endl;
863 verbosity += Anasazi::Warnings;
870 Teuchos::ParameterList MyPL;
871 MyPL.set(
"Which",
"LM");
872 MyPL.set(
"Block Size", 1);
874 MyPL.set(
"Maximum Restarts", 500);
875 MyPL.set(
"Orthogonalization",
"DGKS");
876 MyPL.set(
"Verbosity", verbosity);
877 MyPL.set(
"Convergence Tolerance", tol);
878 Anasazi::BlockKrylovSchurSolMgr<double,
881 BKS(anasazi_pt, MyPL);
884 Anasazi::ReturnType ret = BKS.solve();
885 if (ret != Anasazi::Converged)
887 std::string error_message =
"Eigensolver did not converge!\n";
890 error_message, OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
895 Anasazi::Eigensolution<double, DoubleMultiVector> sol =
896 anasazi_pt->getSolution();
897 std::vector<Anasazi::Value<double>> evals = sol.Evals;
898 Teuchos::RCP<DoubleMultiVector> evecs = sol.Evecs;
905 std::vector<int> index_vector = sol.index;
908 unsigned n_eval_avail = evals.size();
909 eigenvalue.resize(n_eval_avail);
910 eigenvector_real.resize(n_eval_avail);
911 eigenvector_imag.resize(n_eval_avail);
914 for (
unsigned i = 0;
i < n_eval_avail;
i++)
917 double a = evals[
i].realpart;
918 double b = evals[
i].imagpart;
919 double det = a * a + b * b;
920 eigenvalue[
i] = std::complex<double>(a / det +
Sigma_real, -b / det);
924 eigenvector_real[
i].build(evecs->distribution_pt(), 0.0);
925 eigenvector_imag[
i].build(evecs->distribution_pt(), 0.0);
949 if (index_vector[
i] == 0)
953 eigenvector_real[
i][j] = (*evecs)(
i, j);
954 eigenvector_imag[
i][j] = 0.0;
957 else if (index_vector[
i] == 1)
961 eigenvector_real[
i][j] = (*evecs)(
i, j);
962 eigenvector_imag[
i][j] = (*evecs)(
i + 1, j);
965 else if (index_vector[
i] == -1)
969 eigenvector_real[
i][j] = (*evecs)(
i - 1, j);
970 eigenvector_imag[
i][j] = -(*evecs)(
i, j);
975 oomph_info <<
"Never get here: index_vector[ " <<
i
976 <<
" ] = " << index_vector[
i] << std::endl;
989 Vector<std::complex<double>>& eigenvalue,
991 const bool& do_adjoint_problem)
997 unsigned multivector_dimension = 1;
998 Teuchos::RCP<DoubleMultiVector> initial =
1001 Anasazi::MultiVecTraits<double, DoubleMultiVector>::MvRandom(*initial);
1004 Teuchos::RCP<DoubleMultiVectorOperator> Op_pt;
1005 if (do_adjoint_problem)
1017 Teuchos::RCP<Anasazi::BasicEigenproblem<double,
1020 anasazi_pt = Teuchos::rcp(
1021 new Anasazi::BasicEigenproblem<
double,
1027 anasazi_pt->setHermitian(
false);
1030 anasazi_pt->setNEV(n_eval);
1033 if (anasazi_pt->setProblem() !=
true)
1035 oomph_info <<
"Anasazi::BasicEigenproblem::setProblem() had an error."
1037 <<
"End Result: TEST FAILED" << std::endl;
1045 Anasazi::Warnings + Anasazi::FinalSummary + Anasazi::TimingDetails;
1047 Teuchos::ParameterList MyPL;
1048 MyPL.set(
"Which",
"LM");
1049 MyPL.set(
"Block Size", 1);
1051 MyPL.set(
"Maximum Restarts", 500);
1052 MyPL.set(
"Orthogonalization",
"DGKS");
1053 MyPL.set(
"Verbosity", verbosity);
1054 MyPL.set(
"Convergence Tolerance", tol);
1055 Anasazi::BlockKrylovSchurSolMgr<double,
1058 BKS(anasazi_pt, MyPL);
1061 Anasazi::ReturnType ret = BKS.solve();
1063 if (ret != Anasazi::Converged)
1069 Anasazi::Eigensolution<double, DoubleMultiVector> sol =
1070 anasazi_pt->getSolution();
1071 std::vector<Anasazi::Value<double>> evals = sol.Evals;
1072 Teuchos::RCP<DoubleMultiVector> evecs = sol.Evecs;
1074 eigenvalue.resize(evals.size());
1075 eigenvector.resize(evals.size());
1077 for (
unsigned i = 0;
i < evals.size();
i++)
1080 double a = evals[
i].realpart;
1081 double b = evals[
i].imagpart;
1082 double det = a * a + b * b;
1083 eigenvalue[
i] = std::complex<double>(a / det +
Sigma_real, -b / det);
1086 eigenvector[
i].build(evecs->distribution_pt());
1095 eigenvector[
i][n] = (*evecs)(
i, n);
static Teuchos::RCP< oomph::DoubleMultiVector > CloneCopy(const oomph::DoubleMultiVector &mv)
Creates a deep copy of the DoubleMultiVector mv return Reference-counted pointer to the new DoubleMul...
static int GetVecLength(const oomph::DoubleMultiVector &mv)
Obtain the global length of the vector.
static Teuchos::RCP< oomph::DoubleMultiVector > CloneCopy(const oomph::DoubleMultiVector &mv, const std::vector< int > &index)
Creates a new oomph::DoubleMultiVector and (deep) copies the contents of the vectors in index into th...
static void MvTransMv(const double alpha, const oomph::DoubleMultiVector &A, const oomph::DoubleMultiVector &mv, Teuchos::SerialDenseMatrix< int, double > &B)
Compute a dense matrix B through the matrix-matrix multiply .
static void MvTimesMatAddMv(const double alpha, const oomph::DoubleMultiVector &A, const Teuchos::SerialDenseMatrix< int, double > &B, const double beta, oomph::DoubleMultiVector &mv)
Update mv with .
static void MvPrint(const oomph::DoubleMultiVector &mv, std::ostream &os)
Print the mv multi-vector to the os output stream.
static Teuchos::RCP< oomph::DoubleMultiVector > CloneView(oomph::DoubleMultiVector &mv, const Teuchos::Range1D &index)
Creates a new oomph::DoubleMultiVector that contains shallow copies of selected entries of the oomph:...
static void SetBlock(const oomph::DoubleMultiVector &A, const Teuchos::Range1D &index, oomph::DoubleMultiVector &mv)
Deep copy of A into specified columns of mv.
static Teuchos::RCP< oomph::DoubleMultiVector > CloneViewNonConst(oomph::DoubleMultiVector &mv, const std::vector< int > &index)
Creates a new oomph::DoubleMultiVector that contains shallow copies of selected entries of the oomph:...
static void MvScale(oomph::DoubleMultiVector &mv, const std::vector< double > &alpha)
Scale each element of the i-th vector in mv with alpha[i].
static void MvScale(oomph::DoubleMultiVector &mv, const double alpha)
Scale each element of the vectors in mv with alpha.
static Teuchos::RCP< const oomph::DoubleMultiVector > CloneView(const oomph::DoubleMultiVector &mv, const std::vector< int > &index)
Creates a new oomph::DoubleMultiVector that contains shallow copies of selected entries of the oomph:...
static void MvAddMv(const double alpha, const oomph::DoubleMultiVector &A, const double beta, const oomph::DoubleMultiVector &B, oomph::DoubleMultiVector &mv)
Replace mv with .
static Teuchos::RCP< oomph::DoubleMultiVector > Clone(const oomph::DoubleMultiVector &mv, const int numvecs)
Creates a new empty DoubleMultiVector containing numvecs columns. Return a reference-counted pointer ...
static int GetNumberVecs(const oomph::DoubleMultiVector &mv)
Obtain the number of vectors in the multivector.
static void SetBlock(const oomph::DoubleMultiVector &A, const std::vector< int > &index, oomph::DoubleMultiVector &mv)
Copy the vectors in A to a set of vectors in mv indicated by the indices given in index.
static Teuchos::RCP< oomph::DoubleMultiVector > CloneViewNonConst(oomph::DoubleMultiVector &mv, const Teuchos::Range1D &index)
Creates a new oomph::DoubleMultiVector that contains shallow copies of selected entries of the oomph:...
static void MvNorm(const oomph::DoubleMultiVector &mv, std::vector< double > &normvec)
Compute the 2-norm of each individual vector of mv. Upon return, normvec[i] holds the value of ,...
static Teuchos::RCP< oomph::DoubleMultiVector > CloneView(oomph::DoubleMultiVector &mv, const std::vector< int > &index)
Creates a new oomph::DoubleMultiVector that contains shallow copies of selected entries of the oomph:...
static void MvDot(const oomph::DoubleMultiVector &mv, const oomph::DoubleMultiVector &A, std::vector< double > &b)
Compute a vector b where the components are the individual dot-products of the i-th columns of A and ...
static void MvRandom(oomph::DoubleMultiVector &mv)
Replace the vectors in mv with random vectors.
static Teuchos::RCP< oomph::DoubleMultiVector > CloneCopy(const oomph::DoubleMultiVector &mv, const Teuchos::Range1D &index)
Deep copy of specified columns of oomph::DoubleMultiVector return Reference-counted pointer to the ne...
static void MvInit(oomph::DoubleMultiVector &mv, const double alpha=Teuchos::ScalarTraits< double >::zero())
Replace each element of the vectors in mv with alpha.
static void Assign(const oomph::DoubleMultiVector &A, oomph::DoubleMultiVector &mv)
mv := A
static void Apply(const oomph::DoubleMultiVectorOperator &Op, const oomph::DoubleMultiVector &x, oomph::DoubleMultiVector &y)
Matrix operator application method.
Class for the Anasazi eigensolver.
void solve_eigenproblem(Problem *const &problem_pt, const int &n_eval, Vector< std::complex< double >> &alpha, Vector< double > &beta, Vector< DoubleVector > &eigenvector_real, Vector< DoubleVector > &eigenvector_imag, const bool &do_adjoint_problem)
Solve the real eigenproblem that is assembled by elements in a mesh in a Problem object....
LinearSolver * Default_linear_solver_pt
Pointer to a default linear solver.
Anasazi::OutputManager< ST > * Output_manager_pt
Pointer to output manager.
Teuchos::ScalarTraits< ST > SCT
Anasazi::OperatorTraits< ST, MV, OP > OPT
virtual ~ANASAZI()
Destructor, delete the linear solver.
LinearSolver * Linear_solver_pt
Pointer to a linear solver.
void solve_eigenproblem(Problem *const &problem_pt, const int &n_eval, Vector< std::complex< double >> &eigenvalue, Vector< DoubleVector > &eigenvector_real, Vector< DoubleVector > &eigenvector_imag, const bool &do_adjoint_problem)
Solve the eigen problem.
LinearSolver *const & linear_solver_pt() const
Return a pointer to the linear solver object (const version)
void solve_eigenproblem_legacy(Problem *const &problem_pt, const int &n_eval, Vector< std::complex< double >> &eigenvalue, Vector< DoubleVector > &eigenvector, const bool &do_adjoint_problem)
Solve the eigen problem.
Anasazi::MultiVec< ST > MV
Anasazi::MultiVecTraits< ST, MV > MVT
ANASAZI(const ANASAZI &)
Empty copy constructor.
Anasazi::Operator< ST > OP
LinearSolver *& linear_solver_pt()
Return a pointer to the linear solver object.
Class for the adjoing problem shift invert operation.
CRDoubleMatrix * AsigmaM_pt
Problem * Problem_pt
Pointer to the problem.
AdjointProblemBasedShiftInvertOperator(Problem *const &problem_pt, LinearSolver *const &linear_solver_pt, const double &sigma=0.0)
void apply(const DoubleMultiVector &x, DoubleMultiVector &y) const
Now specify how to apply the operator.
double Sigma
Storage for the shift.
LinearSolver * Linear_solver_pt
Pointer to the linear solver used.
CRDoubleMatrix * M_pt
Storage for the matrices.
A class for compressed row matrices. This is a distributable object.
void multiply(const DoubleVector &x, DoubleVector &soln) const
Multiply the matrix by the vector x: soln=Ax.
void get_matrix_transpose(CRDoubleMatrix *result) const
Returns the transpose of this matrix.
bool distributed() const
distribution is serial or distributed
LinearAlgebraDistribution * distribution_pt() const
access to the LinearAlgebraDistribution
unsigned nrow() const
access function to the number of global rows.
unsigned nrow_local() const
access function for the num of local rows on this processor.
Base class for Oomph-lib's Vector Operator classes that will be used with the DoubleMultiVector.
DoubleMultiVectorOperator()
Empty constructor.
virtual ~DoubleMultiVectorOperator()
virtual destructor
virtual void apply(const DoubleMultiVector &x, DoubleMultiVector &y) const =0
The apply interface.
A multi vector in the mathematical sense, initially developed for linear algebra type applications....
void output(std::ostream &outfile) const
output the contents of the vector
void initialise(const double &initial_value)
initialise the whole vector with value v
void dot(const DoubleMultiVector &vec, std::vector< double > &result) const
compute the 2 norm of this vector
void norm(std::vector< double > &result) const
compute the 2 norm of this vector
DoubleVector & doublevector(const unsigned &i)
access to the DoubleVector representatoin
unsigned nvector() const
Return the number of vectors.
A vector in the mathematical sense, initially developed for linear algebra type applications....
Base class for all EigenProblem solves. This simply defines standard interfaces so that different sol...
double Sigma_real
Double value that represents the real part of the shift in shifted eigensolvers.
Describes the distribution of a distributable linear algebra type object. Typically this is a contain...
OomphCommunicator * communicator_pt() const
const access to the communicator pointer
Base class for all linear solvers. This merely defines standard interfaces for linear solvers,...
virtual void solve(Problem *const &problem_pt, DoubleVector &result)=0
Solver: Takes pointer to problem and returns the results vector which contains the solution of the li...
virtual void enable_resolve()
Enable resolve (i.e. store matrix and/or LU decomposition, say) Virtual so it can be overloaded to pe...
virtual void resolve(const DoubleVector &rhs, DoubleVector &result)
Resolve the system defined by the last assembled jacobian and the rhs vector. Solution is returned in...
void disable_doc_time()
Disable documentation of solve times.
An OomphLibError object which should be thrown when an run-time error is encountered....
Class for the shift invert operation.
void apply(const DoubleMultiVector &x, DoubleMultiVector &y) const
The apply interface.
ProblemBasedShiftInvertOperator(Problem *const &problem_pt, LinearSolver *const &linear_solver_pt, const double &sigma=0.0)
CRDoubleMatrix * AsigmaM_pt
LinearSolver * Linear_solver_pt
////////////////////////////////////////////////////////////////// //////////////////////////////////...
LinearAlgebraDistribution *const & dof_distribution_pt() const
Return the pointer to the dof distribution (read-only)
virtual void get_eigenproblem_matrices(CRDoubleMatrix &mass_matrix, CRDoubleMatrix &main_matrix, const double &shift=0.0)
Get the matrices required by a eigensolver. If the shift parameter is non-zero the second matrix will...
LinearSolver *& linear_solver_pt()
Return a pointer to the linear solver object.
void create_new_linear_algebra_distribution(LinearAlgebraDistribution *&dist_pt)
Get new linear algebra distribution (you're in charge of deleting it!)
A slight extension to the standard template vector class so that we can include "graceful" array rang...
bool Use_temporary_code_for_andrew_legacy_version
std::string string(const unsigned &i)
Return the i-th string or "" if the relevant string hasn't been defined.
//////////////////////////////////////////////////////////////////// ////////////////////////////////...
OomphInfo oomph_info
Single (global) instantiation of the OomphInfo object – this is used throughout the library as a "rep...