1%%%%%%%%%%%%%%%%%%% 2% XLiFE++ is an extended library of finite elements written in C++ 3% Copyright (C) 2014 Lunéville, Eric; Kielbasiewicz, Nicolas; Lafranche, Yvon; Nguyen, Manh-Ha; Chambeyron, Colin 4% 5% This program is free software: you can redistribute it and/or modify 6% it under the terms of the GNU General Public License as published by 7% the Free Software Foundation, either version 3 of the License, or 8% (at your option) any later version. 9% This program is distributed in the hope that it will be useful, 10% but WITHOUT ANY WARRANTY; without even the implied warranty of 11% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12% GNU General Public License for more details. 13% You should have received a copy of the GNU General Public License 14% along with this program. If not, see <http://www.gnu.org/licenses/>. 15%%%%%%%%%%%%%%%%%%% 16 17\section {\arpackpp interface layer} 18 19\arpackpp interface is a group of class which is an interface between \xlifepp and \arpackpp. Each class of this group corresponds to a specific eigen problem with a computational mode.\\ 20\begin{figure} [H] 21\centering 22\includeTikZPict[width=13cm]{largeMatrixArpackpp.png} 23\caption{Hierarchy of LargeMatrixArpackpp} 24\end{figure} 25{\class LargeMatrixArpackpp} is an interface class between \xlifepp and \arpackpp. This class is an abstract base class so that all classes to be used in the program are derived from this one. This class defines some basic properties and methods which are used in all derived classes. 26\vspace{.1cm} 27\begin{lstlisting}[deletekeywords={[3] x, y, name}] 28template<typename K, class Mat> 29class LargeMatrixArpackpp 30{ 31 public: 32 LargeMatrixArpackpp(const Mat& matA, const Number sizeProblem); 33 LargeMatrixArpackpp(const Mat& matA, const Number sizeProblem, const String name); 34 virtual ~LargeMatrixArpackpp(); 35 virtual void multOPx (K* x, K* y) = 0; 36 String kindOfFactorization() const {return factName_;} 37 38 protected: 39 const Mat* matA_p; //< Left hand-side matrix A, generally stiffness matrix (given data) 40 Number size_; //< Size of problem 41 String name_; //< Name of problem 42 String factName_; //< Name of the algorithm used to compute the factorization pointed to by fact_p 43 Mat* fact_p; //<Factorization of matB, matAsI or matAsB in order to speed up linear systems solving. 44 45 protected: 46 void (Mat::*solver_)(std::vector<K>& b, std::vector<K>& x); 47 void checkDims(const Mat* mat); 48 void factorize(const Mat* mat); 49 void bzMultAx(K* x, K* y); //< Matrix-vector product y <- A * x 50 void array2Vector(const K*, std::vector<K>&); //< Convert array to Vector 51 void vector2Array(std::vector<K>&, K*); //< Convert Vector to Array 52}; // end of Class LargeMatrixArpackpp 53\end{lstlisting} 54\vspace{.1cm} 55 56\displayInfos{library=eigenSolvers, test={test\_EigenSolverArpackpp.hpp}, header dep={}} 57 58\subsection {The {\classtitle LargeMatrixArpackppStdReg} class} 59 60{\class LargeMatrixArpackppStdReg} class is an interface between \xlifepp and \arpackpp designed to enable the use of Arpack++'s own classes for standard problems in regular mode. This class allows \xlifepp users to solve real symmetric, non-symmetric and complex standard eigen problem in regular mode. This class holds informations of matrices and some methods related to product matrix-vector. In general, only matrix-vector product $y\leftarrow Ax$ is needed. 61\vspace{.1cm} 62\begin{lstlisting}[deletekeywords={[3] x, y}] 63template<typename K, class Mat> 64class LargeMatrixArpackppStdReg: public LargeMatrixArpackpp<K, Mat> 65{ 66 public: 67 LargeMatrixArpackppStdReg(const Mat& matA, const Number sizeProblem); 68 virtual ~LargeMatrixArpackppStdReg() {} 69 virtual void multOPx(K* x, K* y); //< Matrix-vector product y <- A * x 70 71 private: 72 //! Duplicating such object is disabled 73 LargeMatrixArpackppStdReg(const LargeMatrixArpackppStdReg&); 74 LargeMatrixArpackppStdReg& operator=(const LargeMatrixArpackppStdReg&); 75}; // end of Class LargeMatrixArpackppStdReg 76\end{lstlisting} 77\vspace{.1cm} 78\displayInfos{library=eigenSolvers, test={test\_EigenSolverArpackpp.hpp}, header dep={LargeMatrixArpackpp.hpp}} 79 80\subsection{The {\classtitle LargeMatrixArpackppStdShf} class} 81 82{\class LargeMatrixArpackppStdShf} class is an interface between \xlifepp and \arpackpp designed to enable the use of \arpackpp's own classes for standard problems in shift and inverse mode. This class allows \xlifepp users to solve real symmetric, non-symmetric and complex standard eigen problem in shift and inverse mode. This class holds informations of matrices and some methods related to product matrix-vector. In general, we need to provide matrix-vector product $y\leftarrow (A-\sigma I)^{-1}x$. However, thanks to some built-in special solvers of \xlifepp, only $(A-\sigma I)$ is enough. 83\vspace{.1cm} 84\begin{lstlisting}[deletekeywords={[3] x, y}] 85template<typename K, class Mat> 86class LargeMatrixArpackppStdShf: public LargeMatrixArpackpp<K, Mat> 87{ 88 public: 89 LargeMatrixArpackppStdShf(const Mat& matA, const Number sizeProblem, const K sigma); 90 virtual ~LargeMatrixArpackppStdShf(); 91 virtual void multOPx (K* x, K* y); //< Matrix-vector product y <- inv(A-sigma*Id) * x 92 private: 93 const Mat* matAsI_p; //< A - sigma Id matrix for shift and invert mode in standard problems 94 bool localAlloc_; //< flag to indicate if dynamic memory is allocated to store the matrix (A - sigma*Id) 95 96 //! Duplicating such object is disabled 97 LargeMatrixArpackppStdShf(const LargeMatrixArpackppStdShf&); 98 LargeMatrixArpackppStdShf& operator=(const LargeMatrixArpackppStdShf&); 99}; // end of Class LargeMatrixArpackppStdShf 100\end{lstlisting} 101\vspace{.1cm} 102\displayInfos{library=eigenSolvers, test={test\_EigenSolverArpackpp.hpp}, header dep={LargeMatrixArpackpp.hpp}} 103 104\subsection{The {\classtitle LargeMatrixArpackppGen} class} 105 106{\class LargeMatrixArpackppGen} is an abstract class which plays a role of an interface between \xlifepp and \arpackpp designed to enable the use of \arpackpp's own classes for generalized eigen problem $Ax=\lambda Bx$. All classes for generalized problem are derived from this one. 107\vspace{.1cm} 108\begin{lstlisting}[deletekeywords={[3] name, x, y}] 109template<typename K, class Mat> 110class LargeMatrixArpackppGen: public LargeMatrixArpackpp<K, Mat> 111{ 112 public: 113 LargeMatrixArpackppGen(const Mat& matA, const Mat& matB, const Number sizeProblem); 114 LargeMatrixArpackppGen(const Mat& matA, const Mat& matB, const Number sizeProblem, const String name); 115 virtual ~LargeMatrixArpackppGen() {} 116 virtual void multBx (K* x, K* y); //< Matrix-vector product y <- B * x required for all derived classes 117 118 protected: 119 const Mat* matB_p; //< Right hand-side matrix B, e.g. mass matrix (given data) 120 Mat* matAsB_p; //!< Matrix (A - sigma*B) 121 bool localAlloc_; //< flag to indicate if dynamic memory is allocated to store A - sigma B, 122 123 private: 124 //! Duplicating such object is disabled 125 LargeMatrixArpackppGen(const LargeMatrixArpackppGen&); 126 LargeMatrixArpackppGen& operator=(const LargeMatrixArpackppGen&); 127}; // end of Class LargeMatrixArpackppGen 128\end{lstlisting} 129\vspace{.1cm} 130 131\displayInfos{library=eigenSolvers, test={test\_EigenSolverArpackpp.hpp}, header dep={LargeMatrixArpackpp.hpp}} 132 133\subsection{The {\classtitle LargeMatrixArpackppGenReg} class} 134 135{\class LargeMatrixArpackppGenReg} class is interface classes between \xlifepp and \arpackpp designed 136 to enable the use of \arpackpp's own classes for generalized problems in regular mode except for real symmtric generalize problem. This class holds informations of matrices and some methods related to product matrix-vector. In general, we need to provide matrix-vector product $w\leftarrow (B)^{-1}Ax$ and $z\leftarrow Bx$ 137\vspace{.1cm} 138\begin{lstlisting}[deletekeywords={[3] x, y}] 139template<typename K, class Mat> 140class LargeMatrixArpackppGenReg: public LargeMatrixArpackppGen<K, Mat> 141{ 142 public: 143 LargeMatrixArpackppGenReg(const Mat& matA, const Mat& matB, const Number sizeProblem); 144 virtual ~LargeMatrixArpackppGenReg() {}; 145 virtual void multOPx (K* x, K* y); //< Matrix-vector product y <- inv(B)*A * x 146 147 private: 148 //! Duplicating such object is disabled 149 LargeMatrixArpackppGenReg(const LargeMatrixArpackppGenReg&); 150 LargeMatrixArpackppGenReg& operator=(const LargeMatrixArpackppGenReg&); 151}; // end of Class LargeMatrixArpackppGenReg 152\end{lstlisting} 153\vspace{.1cm} 154 155\displayInfos{library=eigenSolvers, test={test\_EigenSolverArpackpp.hpp}, header dep={LargeMatrixArpackppGen.hpp}} 156 157\subsection{The {\classtitle LargeMatrixArpackppSymGenReg} class} 158 159{\class LargeMatrixArpackppGenReg} is basically not different from class{\class LargeMatrixArpackppGenReg} except on how the calculation results are returned. Maybe in the future, we don't need this class anymore. 160\vspace{.1cm} 161\begin{lstlisting}[deletekeywords={[3] x, y}] 162template<typename K, class Mat> 163class LargeMatrixArpackppSymGenReg: public LargeMatrixArpackppGen<K, Mat> 164{ 165 public: 166 LargeMatrixArpackppSymGenReg(const Mat& matA, const Mat& matB, const Number sizeProblem); 167 virtual ~LargeMatrixArpackppSymGenReg() {} 168 virtual void multOPx (K* x, K* y); //< Matrix-vector product y <- inv(B)*A * x 169 170 private: 171 //! Duplicating such object is disabled 172 LargeMatrixArpackppSymGenReg(const LargeMatrixArpackppSymGenReg&); 173 LargeMatrixArpackppSymGenReg& operator=(const LargeMatrixArpackppSymGenReg&); 174}; // end of Class LargeMatrixArpackppSymGenReg 175\end{lstlisting} 176\vspace{.1cm} 177 178\displayInfos{library=eigenSolvers, test={test\_EigenSolverArpackpp.hpp}, header dep={LargeMatrixArpackppGen.hpp}} 179 180\subsection{The {\classtitle LargeMatrixArpackppGenShf} class} 181 182Class {\class LargeMatrixArpackppGenShf} is interface between \xlifepp and \arpackpp designed to enable the use of \arpackpp's own classes for generalized problems in shift and invert mode. All classes for generalized problem in relevant shift and invert mode (including Buckling and Cayley) are derived from this one. 183\vspace{.1cm} 184\begin{lstlisting}[deletekeywords={[3] x, y, name}] 185template<typename K, class Mat> 186class LargeMatrixArpackppGenShf: public LargeMatrixArpackppGen<K, Mat> 187{ 188 public: 189 LargeMatrixArpackppGenShf(const Mat& matA, Mat& matB, const Number sizeProblem, const K sigma, const String name = "Generalized Shift and Invert"); 190 virtual ~LargeMatrixArpackppGenShf() {} 191 virtual void multOPx (K* x, K* y); //< Matrix-vector product y <- inv(A-sigma B)*x 192 193 private: 194 //! Duplicating such object is disabled 195 LargeMatrixArpackppGenShf(const LargeMatrixArpackppGenShf&); 196 LargeMatrixArpackppGenShf& operator=(const LargeMatrixArpackppGenShf&); 197}; // end of Class LargeMatrixArpackppGenShf 198\end{lstlisting} 199\vspace{.1cm} 200 201\displayInfos{library=eigenSolvers, test={test\_EigenSolverArpackpp.hpp}, header dep={LargeMatrixArpackppGen.hpp}} 202 203\subsection{The {\classtitle LargeMatrixArpackppGenBuc} class} 204 205Class {\class LargeMatrixArpackppGenBuc} is derived from class {\class LargeMatrixArpackppGenShf} to solve generalized problems Buckling mode. Two products matrix-vector need provided: $w\leftarrow (A-\sigma B)^{-1}x$ and $z\leftarrow Ax$ 206\vspace{.1cm} 207\begin{lstlisting}[deletekeywords={[3] x, y}] 208template<typename K, class Mat> 209class LargeMatrixArpackppGenBuc: public LargeMatrixArpackppGenShf<K, Mat> 210{ 211 public: 212 LargeMatrixArpackppGenBuc(const Mat& matA, Mat& matB, const Number sizeProblem, const K sigma); 213 virtual ~LargeMatrixArpackppGenBuc() {} 214 virtual void multBx (K* x, K* y);//< Matrix-vector product y <- A * x 215 216 private: 217 //! Duplicating such object is disabled 218 LargeMatrixArpackppGenBuc(const LargeMatrixArpackppGenBuc&); 219 LargeMatrixArpackppGenBuc& operator=(const LargeMatrixArpackppGenBuc&); 220}; // end of Class LargeMatrixArpackppGenBuc 221\end{lstlisting} 222\vspace{.1cm} 223 224\displayInfos{library=eigenSolvers, test={test\_EigenSolverArpackpp.hpp}, header dep={LargeMatrixArpackppGen.hpp}} 225 226\subsection{The {\classtitle LargeMatrixArpackppGenCay} class} 227 228Class {\class LargeMatrixArpackppGenCay} is derived from class {\class LargeMatrixArpackppGenShf} to solve generalized problems in Cayley mode. Three products matrix-vector need provided: $y\leftarrow (A-\sigma B)^{-1}z$, $w\leftarrow Az$ and $u\leftarrow Bz$ 229\vspace{.1cm} 230\begin{lstlisting}[deletekeywords={[3] x, y}] 231template<typename K, class Mat> 232class LargeMatrixArpackppGenBuc: public LargeMatrixArpackppGenShf<K, Mat> 233{ 234 public: 235 LargeMatrixArpackppGenBuc(const Mat& matA, Mat& matB, const Number sizeProblem, const K sigma); 236 virtual ~LargeMatrixArpackppGenBuc() {} 237 virtual void multBx (K* x, K* y);//< Matrix-vector product y <- A * x 238 239 private: 240 //! Duplicating such object is disabled 241 LargeMatrixArpackppGenBuc(const LargeMatrixArpackppGenBuc&); 242 LargeMatrixArpackppGenBuc& operator=(const LargeMatrixArpackppGenBuc&); 243}; // end of Class LargeMatrixArpackppGenBuc 244\end{lstlisting} 245\vspace{.1cm} 246 247\displayInfos{library=eigenSolvers, test={test\_EigenSolverArpackpp.hpp}, header dep={LargeMatrixArpackppGen.hpp}} 248 249\subsection{The {\classtitle LargeMatrixArpackppGenCsh} class} 250 251Class {\class LargeMatrixArpackppGenCsh} is derived from class {\class LargeMatrixArpackppGen} to solve real non-symmetric generalized problem in complex shift and invert mode. Three products matrix-vector need provided: $y\leftarrow (A-\sigma B)^{-1}z$, $w\leftarrow Az$ and $u\leftarrow Bz$ 252\vspace{.1cm} 253\begin{lstlisting}[deletekeywords={[3] x, y}] 254template<typename K, class Mat> 255class LargeMatrixArpackppGenCsh : public LargeMatrixArpackppGen<K, Mat> 256{ 257 public: 258 LargeMatrixArpackppGenCsh(const Mat& matA, Mat& matB, const Number sizeProblem, Complex sigma, const char part); 259 virtual ~LargeMatrixArpackppGenCsh() {}; 260 /*! 261 Matrix-vector product y <- real(inv(A - sigma*B)) if part = 'R' 262 y <- imag(inv(A - sigma*B)) if part = 'I' 263 */ 264 void virtual multOPx (K* x, K* y); 265 void multAx (K* x, K* y); //< Matrix-vector product y <- A * x 266 private: 267 //! Duplicating such object is disabled 268 LargeMatrixArpackppGenCsh(const LargeMatrixArpackppGenCsh&); 269 LargeMatrixArpackppGenCsh& operator=(const LargeMatrixArpackppGenCsh&); 270}; // end of Class LargeMatrixArpackppGenCsh 271\end{lstlisting} 272\vspace{.1cm} 273\displayInfos{library=eigenSolvers, test={test\_EigenSolverArpackpp.hpp}, header dep={LargeMatrixArpackppGen.hpp}} 274 275\section{Users interface layer} 276 277User interface contains classes which wrap all \arpackpp interface layer and provide user a simple prototype. All eigen solvers are invoked by operator(), which is similar to other iterative solvers of {\lib solvers} library. There are two principal classes, each of which solves a specific eigen problem 278\begin{itemize} 279\item {\class EigenSolverStdArpackpp} for standard eigen problem $Ax=\lambda x$ 280\item {\class EigenSolverGenArpackpp} for generalized eigen problem $Ax=\lambda Bx$ 281\end{itemize} 282For each type of eigen problem, input matrix \verb?A? decides the value type (Real or Complex) of eigenvalue and/or eigenvector found. 283There are three cases corresponding to input matrix \verb?A?: real symmetric, complex and real non-symmetric. For the first two cases, the eigenvalue and/or eigenvector found have the same value type of matrix \verb?A? (i.e: Real if matrix \verb?A? is real symmetric and Complex if matrix \verb?A? is complex). For the real non-symmetric case, eigenvalue and/or eigenvector can be complex. Based on value type of input matrix and output eigenvalue (and/or eigenvector), an operator () can be invoked to solve an eigen problem correctly. There are three prototypes of operator() corresponding to three cases: 284\begin{itemize} 285\item {\class real symmetric case}: input matrix \verb?A? is real symmetric and output eigenvalues/eigenvectors are real 286\item {\class real non-symmetric case}: input matrix \verb?A? is real non-symmetric and output eigenvalues/eigenvectors are complex 287\item {\class complex case} : input matrix \verb?A? is complex and output eigenvalues/eigenvectors are complex 288\end{itemize} 289\begin{figure}[H] 290\centering 291\includeTikZPict[width=13cm]{eigenSolverBaseArpackpp.png} 292\caption{{\class EigenSolverBaseArpackpp} class} 293\end{figure} 294 295\subsection{The {\classtitle EigenSolverBaseArpackpp} class} 296 297The {\class EigenSolverBaseArpackpp} is the base class which provides some methods to construct object and retrieve eigenvalue/eigenvector returned by \arpackpp. All other wrapper classes are derived from this one. 298\vspace{.1cm} 299\begin{lstlisting}[deletekeywords={[3] epsilon, size}] 300class EigenSolverBaseArpackpp 301{ 302 public: 303 EigenSolverBaseArpackpp(const String& nam); 304 EigenSolverBaseArpackpp(const String& nam, const Number maxOfIt, const Real epsilon); 305 virtual ~EigenSolverBaseArpackpp(); 306 // Iterative solver name for documentation purposes 307 String name() { return name_; } 308 // Some functions to extract Eigenvalue and EigenVector returned from Arpack 309 // Extract EigenValue and EigenVector 310 template<class ArProblem, class EigValue, class EigVector> 311 Number extractEigenValueVector(ArProblem& arProb, 312 EigValue& eigValue, EigVector& eigVector, 313 Number nev, Number size, bool isReturnVector); 314 315 // Extract EigenValue and EigenVector for non-symmetric problem 316 template<class ArProblem, class EigValue, class EigVector> 317 Number extractEigenValueVectorNonSym(ArProblem& arProb, 318 EigValue& eigValue, EigVector& eigVector, 319 Number nev, Number size, bool isReturnVector); 320 321 // Set some parameters with user-defined value 322 template<class ArProblem> 323 void setParameters(ArProblem& arProb); 324 protected: 325 // Extract result EigenVector 326 template<typename K, class ArProblem> 327 void extractEigenVector(ArProblem& arProb, std::vector<K>& result, Number size, Number idx); 328 329 // Extract result EigenVector of non-symmetric problem 330 template<class ArProblem> 331 void extractEigenVectorNonSym(ArProblem& arProb, std::vector<Complex>& result, Number size, Number idx, bool isNegative, bool isNegativeLeft); 332 ... 333}; 334\end{lstlisting} 335\vspace{.1cm} 336 337\subsection{The {\classtitle EigenSolverStdArpackpp} class} 338 339The {\class EigenSolverStdArpackpp} class enables the use of \arpackpp to solve the standard eigen problem $Ax=\lambda x$ in all computational modes. Moreover, this class simplifies the post-processing stage, the found eigenvalues/eigenvectors are returned directly to user. However, advanced user can easily customize the some lines of code to get more features of \arpackpp (e.g Schur vector, etc, ...). There are three prototypes of operator () corresponding to three cases: real symmetric, complex and real non-symmetric. 340\begin{itemize} 341\item Real symmetric: 342\vspace{.1cm} 343\begin{lstlisting} 344template<class Mat> 345Number operator()(Mat& matA, Vector<Real>& eigValue, std::vector<Vector<Real> >& eigVector, Number nev, EigenComputationalMode compMode, Real sigma, const char* calMode = "LM") 346\end{lstlisting} 347\vspace{.1cm} 348\item Real non-symmetric: 349\vspace{.1cm} 350\begin{lstlisting} 351template<class Mat> 352Number operator()(Mat& matA, Vector<Complex>& eigValue, std::vector<Vector<Complex> >& eigVector, Number nev, EigenComputationalMode compMode, Complex sigma, const char* calMode = "LM") 353\end{lstlisting} 354\vspace{.1cm} 355\item Complex: 356\vspace{.1cm} 357\begin{lstlisting} 358template<class Mat> 359Number operator()(Mat& matA, Vector<Complex>& eigValue, std::vector<Vector<Complex> >& eigVector, Number nev, EigenComputationalMode compMode, Real sigma, const char* calMode = "LM") 360\end{lstlisting} 361\vspace{.1cm} 362\end{itemize} 363 364\begin{remark} 365If \verb?compMode? isn't \verb?_regular?, only largeMatrix with storage of \verb?skylineStorage? can be used as matrix input. 366\end{remark} 367 368The operator() returns a value specifying the number of eigenvalues/eigenvectors being have found by \arpackpp. This value is equal or less than the input \verb?nev?, which determines the number of eigenvalues/eigenvectors which user needs. \verb?sigma? determines shift value in Shift mode (also in Buckling and Cayley mode). By default, \verb?nev? eigenvalues with largest magnitude are turned; however, the function can return eigenvalues with smalles magnitude by changing \verb?calMode? to {"SM"}. 369 370The {\class EigenComputationalMode} is enumeration: 371\vspace{.1cm} 372\begin{lstlisting} 373enum EigenComputationalMode {_regular, _buckling, _cayley, _shiftInv, _cplxShiftInv}; 374\end{lstlisting} 375\vspace{.1cm} 376In order to solve eigen problem with \arpackpp, it is necessary to define a \arpackpp problem then link this problem to \xlifepp through \arpackpp interface layer (i.e {\class LargeMatrixArpackpp}, etc, ...). There are three \arpackpp classes which are used to define a standard eigen problem: {\class ARSymStdEig}, {\class ARNonSymStdEig}, {\class ARCompStdEig}. \\ 377The following functions define \arpackpp problem and make link to \xlifepp via \arpackpp interface layer. 378\vspace{.1cm} 379\begin{lstlisting}[deletekeywords={[3] size}] 380template<typename K, class MatArpackpp, class Arpackpp, class Mat, class EigValue, class EigVector> 381Number regMode(Mat& matA, Number size, Number nev, EigValue& eigValue, EigVector& eigVector, const char* calMode); 382Number shfInvMode(Mat& matA, Number size, Number nev, K sigma, EigValue& eigValue, EigVector& eigVector, const char* calMode); 383Number regModeNonSym(Mat& matA, Number size, Number nev, EigValue& eigValue, EigVector& eigVector, const char* calMode); 384Number shfInvModeNonSym(Mat& matA, Number size, Number nev, K sigma, EigValue& eigValue, EigVector& eigVector, const char* calMode); 385\end{lstlisting} 386\vspace{.1cm} 387 388\begin{remark} 389Users can easily customize the parameters of \arpackpp problem corresponding to their need. 390\end{remark} 391 392\displayInfos{library=eigenSolvers, test={test\_EigenSolverArpackpp.hpp}, header dep={EigenSolverBaseArpackpp.hpp, LargeMatrixArpackppStdReg.hpp, LargeMatrixArpackppStdShf.hpp}} 393 394\subsection{The {\classtitle EigenSolverGenArpackpp} class} 395 396The {\class EigenSolverStdArpackpp} class enables the use of \arpackpp to solve the generalized eigen problem $Ax=\lambda Bx$ in all computational modes. Moreover, this class simplifies the post-processing stage, the found eigenvalues/eigenvectors are returned directly to user. However, advanced user can easily customize several lines of code to get more features of \arpackpp (e.g Schur vector, etc, ...). There are three prototypes of operator () corresponding to three cases: real symmetric, complex and real non-symmetric. 397\begin{itemize} 398\item Real symmetric: 399\vspace{.1cm} 400\begin{lstlisting} 401template<class Mat> 402Number operator()(const Mat& matA, Mat& matB, Vector<Real>& eigValue, std::vector<Vector<Real> >& eigVector, Number nev, EigenComputationalMode compMode, Real sigmaR, const char* calMode = "LM"); 403\end{lstlisting} 404\vspace{.1cm} 405\item Real non-symmetric: 406\vspace{.1cm} 407\begin{lstlisting} 408template<class Mat> 409Number operator()(const Mat& matA, Mat& matB, Vector<Complex>& eigValue, std::vector<Vector<Complex> >& eigVector, Number nev, EigenComputationalMode compMode, Complex sigma, const char* calMode = "LM"); 410\end{lstlisting} 411\vspace{.1cm} 412\item Complex: 413\vspace{.1cm} 414\begin{lstlisting} 415template<class Mat> 416Number operator()(const Mat& matA, Mat& matB, Vector<Complex>& eigValue, std::vector<Vector<Complex> >& eigVector, Number nev, EigenComputationalMode compMode, Real sigmaR, const char* calMode = "LM"); 417\end{lstlisting} 418\vspace{.1cm} 419\item Real non-symmetric with complex shift: 420\vspace{.1cm} 421\begin{lstlisting} 422template<class Mat> 423Number operator()(const Mat& matA, Mat& matB, Vector<Complex>& eigValue, std::vector<Vector<Complex> >& eigVector, Number nev, EigenComputationalMode compMode, const char mode, Complex sigma, const char* calMode = "LM"); 424\end{lstlisting} 425\vspace{.1cm} 426\end{itemize} 427 428\begin{remark} 429If \verb?compMode? isn't \verb?_regular?, only largeMatrix with storage of \verb?skylineStorage? can be used as matrix input. 430\end{remark} 431 432Having matrix {B} as an additional input, the operator() of {\class EigenSolverGenArpackpp} class is called with the same parameters as the case of {\class EigenSolverStdArpackpp}. Moreover, it has one more prototype which is served for real non-symmetric case with complex shift value. Besides the same parameters like other prototypes, it is necessary for user to specify which part of complex shift value:real or imaginary, to use in the shift mode by parameter \verb?mode?. This input can be {'R'} for real part or {'I'} for imaginary part of complex shift value \verb?sigma?. 433Same as {\class EigenSolverStdArpackpp}, it needs to define \arpackpp problems and link them to \xlifepp. {\class ARSymGenEig}, {\class ARNonSymGenEig} and {\class ARCompGenEig} class are used to define \arpackpp generalized problem. \\ 434The following functions define {\lib Arpack++} problem and make link to \xlifepp via \arpackpp interface layer. 435\vspace{.1cm} 436\begin{lstlisting}[deletekeywords={[3] size}] 437template<typename K, class MatArpackpp, class Arpackpp, class Mat, class EigValue, class EigVector> 438Number regMode(const Mat& matA, const Mat& matB, Number size, Number nev, EigValue& eigValue, EigVector& eigVector, const char* calMode); 439Number regModeNonSym(const Mat& matA, const Mat& matB, Number size, Number nev, EigValue& eigValue, EigVector& eigVector, const char* calMode); 440Number symShfBucMode(const Mat& matA, Mat& matB, Number size, Number nev, K sigma, const char mode, EigValue& eigValue, EigVector& eigVector, const char* calMode); 441Number symCaleyMode(const Mat& matA, Mat& matB, Number size, Number nev, K sigma, EigValue& eigValue, EigVector& eigVector, const char* calMode); 442Number shfMode(const Mat& matA, Mat& matB, Number size, Number nev, K sigma, EigValue& eigValue, EigVector& eigVector, const char* calMode); 443Number shfModeNonSym(const Mat& matA, Mat& matB, Number size, Number nev, K sigma, EigValue& eigValue, EigVector& eigVector, const char* calMode); 444Number complexShfInvMode(const Mat& matA, Mat& matB, Number size, Number nev, Real sigmaR, Real sigmaI, const char mode, EigValue& eigValue, EigVector& eigVector, const char* calMode); 445\end{lstlisting} 446\vspace{.1cm} 447 448\begin{remark} 449Users can easily customize the parameters of \arpackpp problem corresponding to their need. 450\end{remark} 451 452\displayInfos{library=eigenSolvers, test={test\_EigenSolverArpackpp.hpp}, header dep={EigenSolverBaseArpackpp.hpp, LargeMatrixArpackppGenReg.hpp, LargeMatrixArpackppGenShf.hpp}} 453 454\subsection{Examples} 455 456The following matrices and vectors are used for all examples below. 457\vspace{.1cm} 458\begin{lstlisting}[] 459const Number rowNum = 20; 460const Number colNum = 20; 461const Number nev = 15; 462const String rMatrixDataSym("rSym20.data"); 463const String rMatrixDataSymPosDef("rSymPos20.data"); 464const String rMatrixDataNoSym("rnonSym20.data"); 465const String cMatrixDataSym("c20.data"); 466const String cMatrixData("c20b.data"); 467Vector<Real> rEigValue(colNum); 468Vector<Complex> cEigValue(colNum); 469std::vector<Vector<Real> > rEigVector(nev, rEigValue); 470std::vector<Vector<Complex> > cEigVector(nev, cEigValue); 471 472LargeMatrix<Real> rMatSkylineSym(dataPathTo(rMatrixDataNoSym), _dense, rowNum, colNum, _skyline, _sym); 473LargeMatrix<Real> rMatSkylineSymSym(dataPathTo(rMatrixDataSym), _dense, rowNum, _skyline, _symmetric); 474 475// A trick to make matrix A and matrix B have the same storage (just for testing purpose) 476LargeMatrix<Real> rMatPosDefTemp(dataPathTo(rMatrixDataSymPosDef), _dense, rowNum, _skyline, _symmetric); 477LargeMatrix<Real> rMatPosDefSym(rMatSkylineSymSym); 478 for (Number i = 1; i < rowNum + 1; i++) 479 for (Number j = 1; j < colNum + 1; j++) 480 { rMatPosDefSym(i, j) = rMatPosDefTemp(i, j); } 481 482// Positive definite in real non-symmetric case 483LargeMatrix<Real> rMatPosDefNoSymTemp(dataPathTo(rMatrixDataSymPosDef), _dense, rowNum, colNum, _skyline, _sym); 484LargeMatrix<Real> rMatPosDefNoSym(rMatSkylineSym); 485 for (Number i = 1; i < rowNum + 1; i++) 486 for (Number j = 1; j < colNum + 1; j++) 487 { rMatPosDefNoSym(i, j) = rMatPosDefNoSymTemp(i, j); } 488 489// Complex Large Matrix 490LargeMatrix<Complex> cMatSkylineSymSym(dataPathTo(cMatrixDataSym), _dense, rowNum, _skyline, _symmetric); 491 492Real sigma = 10.0; 493Complex csigma(-700, 20.0); 494EigenSolverStdArpackpp eigenSolverStd; 495EigenSolverGenArpackpp eigenSolverGen; 496\end{lstlisting} 497 498\subsubsection{Standard eigenvalue problem} 499 500Real symmetric case 501\vspace{.1cm} 502\begin{lstlisting}[] 503// Regular mode 504if ( 0 != eigenSolverStd(rMatSkylineSymSym, rEigValue, rEigVector, nev, _regular, sigma) ) { 505 out << "Eigenvalue regular mode (Skyline Sym) : " << rEigValue << std::endl; 506 out << "Eigenvector regular mode (Skyline Sym) : " << rEigVector << std::endl; 507} 508// Shift and invert mode 509if ( 0 != eigenSolverStd(rMatSkylineSymSym, rEigValue, rEigVector, nev, _shiftInv, sigma) ) { 510 out << "Eigenvalue shift and inverse mode :" << rEigValue << std::endl; 511 out << "Eigenvalue shift and inverse mode: " << rEigVector << std::endl; 512} 513\end{lstlisting} 514\vspace{.1cm} 515Real non -symmetric case 516\vspace{.1cm} 517\begin{lstlisting}[] 518// Regular mode 519if ( 0 != eigenSolverStd(rMatSkylineSym, cEigValue, cEigVector, nev, _regular, sigma)) { 520 out << "Eigenvalue regular mode (Skyline Sym) : " << cEigValue << std::endl; 521 out << "Eigenvector regular mode (Skyline Sym) : " << cEigVector << std::endl; 522 } 523//Shift and invert mode 524if ( 0 != eigenSolverStd(rMatSkylineSym, cEigValue, cEigVector, nev, _shiftInv, sigma)) { 525 out << "Eigenvalue shift and inverse mode (Skyline Sym) :" << cEigValue << std::endl; 526 out << "Eigenvalue shift and inverse mode (Skyline Sym): " << cEigVector << std::endl; 527} 528\end{lstlisting} 529\vspace{.1cm} 530Complex case 531\vspace{.1cm} 532\begin{lstlisting}[] 533// Regular mode 534if ( 0 != eigenSolverStd(cMatSkylineSymSym, cEigValue, cEigVector, nev, _regular, csigma)) { 535 out << "Eigenvalue regular mode (Skyline Sym) : " << cEigValue << std::endl; 536 out << "Eigenvector regular mode (Skyline Sym) : " << cEigVector << std::endl; 537} 538// Shift and invert mode 539if ( 0 != eigenSolverStd(cMatSkylineSymSym, cEigValue, cEigVector, nev, _shiftInv, csigma)) { 540 out << "Eigenvalue shift and inverse mode (Skyline Sym) : " << cEigValue << std::endl; 541 out << "Eigenvector shift and inverse mode (Skyline Sym) : " << cEigVector << std::endl; 542} 543\end{lstlisting} 544\vspace{.1cm} 545 546\subsubsection{Generalized eigenvalue problem} 547 548Real symmetric case 549\vspace{.1cm} 550\begin{lstlisting}[] 551// Regular mode 552if ( 0 != eigenSolverGen(rMatSkylineSymSym, rMatPosDefSym, rEigValue, rEigVector, nev, _regular, sigma) ) { 553 out << "Eigenvalue regular mode (Skyline Sym):" << rEigValue << std::endl; 554 out << "Eigenvalue regular mode (Skyline Sym): " << rEigVector << std::endl; 555} 556// Shift and invert mode 557if ( 0 != eigenSolverGen(rMatSkylineSymSym, rMatPosDefSym, rEigValue, rEigVector, nev, _shiftInv, sigma) ) { 558 out << "Eigenvalue shift and inverse mode (Skyline Sym) :" << rEigValue << std::endl; 559 out << "Eigenvalue shift and inverse mode (Skyline Sym) : " << rEigVector << std::endl; 560} 561// Buckling mode 562if ( 0 != eigenSolverGen(rMatPosDefSym, rMatSkylineSymSym, rEigValue, rEigVector, nev, _buckling, sigma) ) { 563 out << "Eigenvalue buckling mode (Skyline Sym) (positive definite):" << rEigValue << std::endl; 564 out << "Eigenvalue buckling mode (Skyline Sym) (positive definite): " << rEigVector << std::endl; 565} 566// Cayley mode 567if ( 0 != eigenSolverGen(rMatSkylineSymSym, rMatPosDefSym, rEigValue, rEigVector, nev, _cayley, sigma) ) { 568 out << "Eigenvalue cayley mode (Skyline Sym):" << rEigValue << std::endl; 569 out << "Eigenvalue cayley mode (Skyline Sym): " << rEigVector << std::endl; 570} 571\end{lstlisting} 572\vspace{.1cm} 573Real non -symmetric case 574\vspace{.1cm} 575\begin{lstlisting}[] 576// Regular mode 577if ( 0 != eigenSolverGen(rMatSkylineSym, rMatPosDefSym, cEigValue, cEigVector, nev, _regular, sigma) ) { 578 out << "Eigenvalue regular mode (Skyline Dual) : " << cEigValue << std::endl; 579 out << "Eigenvector regular mode (Skyline Dual) : " << cEigVector << std::endl; 580} 581// Shift and invert mode 582if ( 0 != eigenSolverGen(rMatSkylineSym, rMatPosDefNoSym, cEigValue, cEigVector, nev, _shiftInv, sigma) ) { 583 out << "Eigenvalue shift and inverse mode :" << cEigValue << std::endl; 584 out << "Eigenvalue shift and inverse mode: " << cEigVector << std::endl; 585} 586// Complex shift with real part 587if ( 0 != eigenSolverGen(rMatSkylineSym, rMatPosDefNoSym, cEigValue, cEigVector, nev, _cplxShiftInv, 'R', csigma) ) { 588 out << "Eigenvalue complex shift and inverse mode (Real part) :" << cEigValue << std::endl; 589 out << "Eigenvalue complex shift and inverse mode (Real part): " << cEigVector << std::endl; 590} 591// Complex shift with imaginary part 592if ( 0 != eigenSolverGen(rMatSkylineSym, rMatPosDefNoSym, cEigValue, cEigVector, nev, _cplxShiftInv, 'I', csigma) ) { 593 out << "Eigenvalue complex shift and inverse mode (Imaginary part):" << cEigValue << std::endl; 594 out << "Eigenvalue complex shift and inverse mode (Imaginary part): " << cEigVector << std::endl; 595} 596\end{lstlisting} 597\vspace{.1cm} 598Complex case 599\vspace{.1cm} 600\begin{lstlisting}[] 601// Regular mode 602if ( 0 != eigenSolverGen(cMatSkylineSymSym, cMatPosDef, cEigValue, cEigVector, nev, _regular, csigma)) { 603 out << "Eigenvalue regular mode (Skyline Sym) : " << cEigValue << std::endl; 604 out << "Eigenvector regular mode (Skyline Sym) : " << cEigVector << std::endl; 605} 606// Shift and invert mode 607if ( 0 != eigenSolverGen(cMatSkylineSymSym, cMatPosDef, cEigValue, cEigVector, nev, _shiftInv, csigma, "LM")) { 608 out << "Eigenvalue shift and inverse mode (Skyline Sym) : " << cEigValue << std::endl; 609 out << "Eigenvector shift and inverse mode (Skyline Sym) : " << cEigVector << std::endl; 610} 611\end{lstlisting} 612\vspace{.1cm} 613Besides making use of class {\class EigenSolverStdArpackpp} and class {\class EigenSolverGenArpackpp}, we can call \arpackpp problem object directly. However, it's only recommended for advanced users!! 614The following examples describe how to use \arpackpp object directly. 615\vspace{.1cm} 616\begin{lstlisting}[deletekeywords={[3]size}] 617 //1. Create interface object 618 LargeMatrixArpackppStdReg<Real, LargeMatrix<Real> > intMat(rMatSkylineSymSym, size); 619 620 //2. Create Arpack++ problem object 621 ARSymStdEig<Real, LargeMatrixArpackppStdReg<Real, LargeMatrix<Real> > > arProb(size, nev, &intMat, &LargeMatrixArpackppStdReg<Real, LargeMatrix<Real> >::multOPx, (char *)"LM"); 622 623 //3. Compute eigenvalues 624 Int nconv = arProb.FindEigenvalues(); 625 626 for (Int i = 0; i < nconv; ++i) { 627 out << arProb.Eigenvalue(i) << " "; 628 } 629 out << "\n"; 630 //4. Change some parameters 631 arProb.ChangeNev(nev-2); 632 arProb.ChangeTol(1.e-6); 633 634 nconv = arProb.FindEigenvectors(); 635 636 for (Int i = 0; i < nconv; ++i) { 637 out << arProb.Eigenvalue(i) << " "; 638 } 639 out << "\n"; 640 641 //4. Retrieve eigenVector 642 Real* eigenVec_p = 0; 643 for (Int i = 0; i < nconv; ++i) { 644 eigenVec_p = arProb.RawEigenvector(i); 645 out << "Eigenvector [" << i << "] :" ; 646 for (Int j = 0; j < size; j++) { 647 out << *eigenVec_p << " "; 648 eigenVec_p++; 649 } 650 out << "\n"; 651 } 652 653 out << "\n"; 654\end{lstlisting} 655\vspace{.1cm} 656