oomph::LAPACK_QZ Class Reference

Class for the LAPACK eigensolver. More...

#include <eigen_solver.h>

+ Inheritance diagram for oomph::LAPACK_QZ:

Public Member Functions

 LAPACK_QZ ()
 Empty constructor. More...
 
 LAPACK_QZ (const LAPACK_QZ &)
 Empty copy constructor. More...
 
virtual ~LAPACK_QZ ()
 Empty desctructor. More...
 
void solve_eigenproblem (Problem *const &problem_pt, const int &n_eval, Vector< std::complex< double >> &eigenvalue, Vector< DoubleVector > &eigenvector)
 Solve the eigen problem. More...
 
void find_eigenvalues (const ComplexMatrixBase &A, const ComplexMatrixBase &M, Vector< std::complex< double >> &eigenvalue, Vector< Vector< std::complex< double >>> &eigenvector)
 
void get_eigenvalues_right_of_shift ()
 
- Public Member Functions inherited from oomph::EigenSolver
 EigenSolver ()
 Empty constructor. More...
 
 EigenSolver (const EigenSolver &)
 Empty copy constructor. More...
 
virtual ~EigenSolver ()
 Empty destructor. More...
 
void set_shift (const double &shift_value)
 Set the value of the shift. More...
 
const doubleget_shift () const
 Return the value of the shift (const version) More...
 
- Public Member Functions inherited from oomph::DistributableLinearAlgebraObject
 DistributableLinearAlgebraObject ()
 Default constructor - create a distribution. More...
 
 DistributableLinearAlgebraObject (const DistributableLinearAlgebraObject &matrix)=delete
 Broken copy constructor. More...
 
void operator= (const DistributableLinearAlgebraObject &)=delete
 Broken assignment operator. More...
 
virtual ~DistributableLinearAlgebraObject ()
 Destructor. More...
 
LinearAlgebraDistributiondistribution_pt () const
 access to the LinearAlgebraDistribution More...
 
unsigned nrow () const
 access function to the number of global rows. More...
 
unsigned nrow_local () const
 access function for the num of local rows on this processor. More...
 
unsigned nrow_local (const unsigned &p) const
 access function for the num of local rows on this processor. More...
 
unsigned first_row () const
 access function for the first row on this processor More...
 
unsigned first_row (const unsigned &p) const
 access function for the first row on this processor More...
 
bool distributed () const
 distribution is serial or distributed More...
 
bool distribution_built () const
 
void build_distribution (const LinearAlgebraDistribution *const dist_pt)
 
void build_distribution (const LinearAlgebraDistribution &dist)
 

Additional Inherited Members

- Protected Member Functions inherited from oomph::DistributableLinearAlgebraObject
void clear_distribution ()
 
- Protected Attributes inherited from oomph::EigenSolver
double Sigma_real
 

Detailed Description

Class for the LAPACK eigensolver.

Constructor & Destructor Documentation

◆ LAPACK_QZ() [1/2]

oomph::LAPACK_QZ::LAPACK_QZ ( )
inline

Empty constructor.

227 : EigenSolver() {}
EigenSolver()
Empty constructor.
Definition: eigen_solver.h:69

◆ LAPACK_QZ() [2/2]

oomph::LAPACK_QZ::LAPACK_QZ ( const LAPACK_QZ )
inline

Empty copy constructor.

230 {}

◆ ~LAPACK_QZ()

virtual oomph::LAPACK_QZ::~LAPACK_QZ ( )
inlinevirtual

Empty desctructor.

233 {}

Member Function Documentation

◆ find_eigenvalues()

void oomph::LAPACK_QZ::find_eigenvalues ( const ComplexMatrixBase A,
const ComplexMatrixBase M,
Vector< std::complex< double >> &  eigenvalue,
Vector< Vector< std::complex< double >>> &  eigenvector 
)

Find the eigenvalues of a generalised eigenvalue problem specified by \( Ax = \lambda Mx \)

Use LAPACK to solve a complex eigen problem specified by the given matrices.

712  {
713  // Some character identifiers for use in the LAPACK routine
714  // Do not calculate the left eigenvectors
715  char no_eigvecs[2] = "N";
716  // Do caculate the eigenvectors
717  char eigvecs[2] = "V";
718 
719  // Get the dimension of the matrix
720  int n = A.nrow(); // Total size of matrix
721 
722  // Storage for the matrices in the packed form required by the LAPACK
723  // routine
724  double* M_linear = new double[2 * n * n];
725  double* A_linear = new double[2 * n * n];
726 
727  // Now convert the matrices into the appropriate packed form
728  unsigned index = 0;
729  for (int i = 0; i < n; ++i)
730  {
731  for (int j = 0; j < n; ++j)
732  {
733  M_linear[index] = M(j, i).real();
734  A_linear[index] = A(j, i).real();
735  ++index;
736  M_linear[index] = M(j, i).imag();
737  A_linear[index] = A(j, i).imag();
738  ++index;
739  }
740  }
741 
742  // Temporary eigenvalue storage
743  double* alpha = new double[2 * n];
744  double* beta = new double[2 * n];
745  // Temporary eigenvector storage
746  double* vec_left = new double[2];
747  double* vec_right = new double[2 * n * n];
748 
749  // Workspace for the LAPACK routine
750  std::vector<double> work(2, 0.0);
751  std::vector<double> rwork(8 * n, 0.0);
752 
753  // Info flag for the LAPACK routine
754  int info = 0;
755 
756  // Call FORTRAN LAPACK to get the required workspace
757  // Note the use of the padding flag
758  LAPACK_ZGGEV(no_eigvecs,
759  eigvecs,
760  n,
761  &A_linear[0],
762  n,
763  &M_linear[0],
764  n,
765  alpha,
766  beta,
767  vec_left,
768  1,
769  vec_right,
770  n,
771  &work[0],
772  -1,
773  &rwork[0],
774  info);
775 
776  // Get the amount of requires workspace
777  int required_workspace = (int)work[0];
778  // If we need it
779  work.resize(2 * required_workspace);
780 
781  // call FORTRAN LAPACK again with the optimum workspace
782  LAPACK_ZGGEV(no_eigvecs,
783  eigvecs,
784  n,
785  &A_linear[0],
786  n,
787  &M_linear[0],
788  n,
789  alpha,
790  beta,
791  vec_left,
792  1,
793  vec_right,
794  n,
795  &work[0],
796  required_workspace,
797  &rwork[0],
798  info);
799 
800  // Now resize storage for the eigenvalues and eigenvectors
801  // We get them all!
802  eigenvalue.resize(n);
803  eigenvector.resize(n);
804 
805  // Now convert the output into our format
806  for (int i = 0; i < n; ++i)
807  {
808  // We have temporary complex numbers
809  std::complex<double> num(alpha[2 * i], alpha[2 * i + 1]);
810  std::complex<double> den(beta[2 * i], beta[2 * i + 1]);
811 
812  // N.B. This is naive and dangerous according to the documentation
813  // beta could be very small giving over or under flow
814  eigenvalue[i] = num / den;
815 
816  // Resize the eigenvector storage
817  eigenvector[i].resize(n);
818  // Load up the eigenvector (assume that it's real)
819  for (int k = 0; k < n; ++k)
820  {
821  eigenvector[i][k] = std::complex<double>(
822  vec_right[2 * i * n + 2 * k], vec_right[2 * i * n + 2 * k + 1]);
823  }
824  }
825 
826  // Delete all allocated storage
827  delete[] vec_right;
828  delete[] vec_left;
829  delete[] beta;
830  delete[] alpha;
831  delete[] A_linear;
832  delete[] M_linear;
833  }
int i
Definition: BiCGSTAB_step_by_step.cpp:9
const unsigned n
Definition: CG3DPackingUnitTest.cpp:11
Matrix< SCALARA, Dynamic, Dynamic, opt_A > A
Definition: bench_gemm.cpp:47
Matrix< RealScalar, Dynamic, Dynamic > M
Definition: bench_gemm.cpp:50
#define LAPACK_ZGGEV(JOBVL, JOBVR, N, A, LDA, B, LDB, ALPHA, BETA, VL, LDVL, VR, LDVR, WORK, LWORK, RWORK, INFO)
Definition: lapack_qz.h:56
return int(ret)+1
RealScalar alpha
Definition: level1_cplx_impl.h:151
int info
Definition: level2_cplx_impl.h:39
Scalar beta
Definition: level2_cplx_impl.h:36
char char char int int * k
Definition: level2_impl.h:374
std::ptrdiff_t j
Definition: tut_arithmetic_redux_minmax.cpp:2

References alpha, beta, i, info, int(), j, k, LAPACK_ZGGEV, and n.

◆ get_eigenvalues_right_of_shift()

void oomph::LAPACK_QZ::get_eigenvalues_right_of_shift ( )
inline

Set the desired eigenvalues to be right of the shift Dummy at the moment

250 {}

◆ solve_eigenproblem()

void oomph::LAPACK_QZ::solve_eigenproblem ( Problem *const &  problem_pt,
const int n_eval,
Vector< std::complex< double >> &  eigenvalue,
Vector< DoubleVector > &  eigenvector 
)
virtual

Solve the eigen problem.

Use LAPACK to solve an eigen problem that is assembled by elements in a mesh in a Problem object.

Implements oomph::EigenSolver.

544  {
545  // Some character identifiers for use in the LAPACK routine
546  // Do not calculate the left eigenvectors
547  char no_eigvecs[2] = "N";
548  // Do caculate the eigenvectors
549  char eigvecs[2] = "V";
550 
551  // Get the dimension of the matrix
552  int n = problem_pt->ndof(); // Total size of matrix
553 
554  // Initialise a padding integer
555  int padding = 0;
556  // If the dimension of the matrix is even, then pad the arrays to
557  // make the size odd. This somehow sorts out a strange run-time behaviour
558  // identified by Rich Hewitt.
559  if (n % 2 == 0)
560  {
561  padding = 1;
562  }
563 
564  // Get the real and imaginary parts of the shift
565  double sigmar = Sigma_real; // sigmai = 0.0;
566 
567  // Actual size of matrix that will be allocated
568  int padded_n = n + padding;
569 
570  // Storage for the matrices in the packed form required by the LAPACK
571  // routine
572  double* M = new double[padded_n * padded_n];
573  double* A = new double[padded_n * padded_n];
574 
575  // TEMPORARY
576  // only use non-distributed matrices and vectors
577  LinearAlgebraDistribution dist(problem_pt->communicator_pt(), n, false);
578  this->build_distribution(dist);
579 
580  // Enclose in a separate scope so that memory is cleaned after assembly
581  {
582  // Allocated Row compressed matrices for the mass matrix and shifted main
583  // matrix
584  CRDoubleMatrix temp_M(this->distribution_pt()),
585  temp_AsigmaM(this->distribution_pt());
586 
587  // Assemble the matrices
588  problem_pt->get_eigenproblem_matrices(temp_M, temp_AsigmaM, sigmar);
589 
590  // Now convert these matrices into the appropriate packed form
591  unsigned index = 0;
592  for (int i = 0; i < n; ++i)
593  {
594  for (int j = 0; j < n; ++j)
595  {
596  M[index] = temp_M(j, i);
597  A[index] = temp_AsigmaM(j, i);
598  ++index;
599  }
600  // If necessary pad the columns with zeros
601  if (padding)
602  {
603  M[index] = 0.0;
604  A[index] = 0.0;
605  ++index;
606  }
607  }
608  // No need to pad the final row because it is never accessed by the
609  // routine.
610  }
611 
612  // Temporary eigenvalue storage
613  double* alpha_r = new double[n];
614  double* alpha_i = new double[n];
615  double* beta = new double[n];
616  // Temporary eigenvector storage
617  double* vec_left = new double[1];
618  double* vec_right = new double[n * n];
619 
620  // Workspace for the LAPACK routine
621  std::vector<double> work(1, 0.0);
622  // Info flag for the LAPACK routine
623  int info = 0;
624 
625  // Call FORTRAN LAPACK to get the required workspace
626  // Note the use of the padding flag
627  LAPACK_DGGEV(no_eigvecs,
628  eigvecs,
629  n,
630  &A[0],
631  padded_n,
632  &M[0],
633  padded_n,
634  alpha_r,
635  alpha_i,
636  beta,
637  vec_left,
638  1,
639  vec_right,
640  n,
641  &work[0],
642  -1,
643  info);
644 
645  // Get the amount of requires workspace
646  int required_workspace = (int)work[0];
647  // If we need it
648  work.resize(required_workspace);
649 
650  // call FORTRAN LAPACK again with the optimum workspace
651  LAPACK_DGGEV(no_eigvecs,
652  eigvecs,
653  n,
654  &A[0],
655  padded_n,
656  &M[0],
657  padded_n,
658  alpha_r,
659  alpha_i,
660  beta,
661  vec_left,
662  1,
663  vec_right,
664  n,
665  &work[0],
666  required_workspace,
667  info);
668 
669  // Now resize storage for the eigenvalues and eigenvectors
670  // We get them all!
671  eigenvalue.resize(n);
672  eigenvector.resize(n);
673 
674  // Now convert the output into our format
675  for (int i = 0; i < n; ++i)
676  {
677  // N.B. This is naive and dangerous according to the documentation
678  // beta could be very small giving over or under flow
679  // Remember to fix the shift back again
680  eigenvalue[i] = std::complex<double>(sigmar + alpha_r[i] / beta[i],
681  alpha_i[i] / beta[i]);
682 
683  // Resize the eigenvector storage
684  eigenvector[i].build(this->distribution_pt(), 0.0);
685  // Load up the eigenvector (assume that it's real)
686  for (int k = 0; k < n; ++k)
687  {
688  eigenvector[i][k] = vec_right[i * n + k];
689  }
690  }
691 
692  // Delete all allocated storage
693  delete[] vec_right;
694  delete[] vec_left;
695  delete[] beta;
696  delete[] alpha_r;
697  delete[] alpha_i;
698  delete[] A;
699  delete[] M;
700  }
The matrix class, also used for vectors and row-vectors.
Definition: Eigen/Eigen/src/Core/Matrix.h:186
LinearAlgebraDistribution * distribution_pt() const
access to the LinearAlgebraDistribution
Definition: linear_algebra_distribution.h:457
void build_distribution(const LinearAlgebraDistribution *const dist_pt)
Definition: linear_algebra_distribution.h:507
double Sigma_real
Definition: eigen_solver.h:65
#define LAPACK_DGGEV(JOBVL, JOBVR, N, A, LDA, B, LDB, ALPHAR, ALPHAI, BETA, VL, LDVL, VR, LDVR, WORK, LWORK, INFO)
Definition: lapack_qz.h:50

References beta, oomph::DistributableLinearAlgebraObject::build_distribution(), oomph::Problem::communicator_pt(), oomph::DistributableLinearAlgebraObject::distribution_pt(), oomph::Problem::get_eigenproblem_matrices(), i, info, int(), j, k, LAPACK_DGGEV, n, oomph::Problem::ndof(), and oomph::EigenSolver::Sigma_real.


The documentation for this class was generated from the following files: