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