68 Vector<std::complex<double>>& alpha_eval,
74 char no_eigvecs[2] =
"N";
77 char eigvecs[2] =
"V";
80 int n = problem_pt->
ndof();
83 bool use_padding =
false;
98 double* M =
new double[padded_n * padded_n];
99 double* A =
new double[padded_n * padded_n];
118 for (
int i = 0;
i < n; ++
i)
120 for (
int j = 0; j < n; ++j)
122 M[index] = temp_M(j,
i);
123 A[index] = temp_AsigmaM(j,
i);
139 double* alpha_r =
new double[n];
140 double* alpha_i =
new double[n];
141 double* beta =
new double[n];
143 double* vec_left =
new double[1];
144 const int leading_dimension_vec_left = 1;
145 double* vec_right =
new double[n * n];
146 const int leading_dimension_vec_right = n;
149 std::vector<double> work(1, 0.0);
153 const int query_workspace = -1;
159 LAPACK_DGGEV(no_eigvecs,
170 leading_dimension_vec_left,
172 leading_dimension_vec_right,
184 int required_workspace = (int)work[0];
186 work.resize(required_workspace);
189 LAPACK_DGGEV(no_eigvecs,
200 leading_dimension_vec_left,
202 leading_dimension_vec_right,
215 alpha_eval.resize(n);
217 eigenvector_aux.resize(n);
220 for (
int i = 0;
i < n; ++
i)
223 alpha_eval[
i] = std::complex<double>(
Sigma_real + alpha_r[
i], alpha_i[
i]);
224 beta_eval[
i] = beta[
i];
235 for (
int k = 0; k < n; ++k)
237 eigenvector_aux[
i][k] = vec_right[
i * n + k];
268 Vector<std::complex<double>>& alpha_eval,
272 const bool& do_adjoint_problem)
274 if (do_adjoint_problem)
276 throw OomphLibError(
"Solving an adjoint eigenproblem is not currently "
277 "implemented for LAPACK_QZ.",
278 OOMPH_CURRENT_FUNCTION,
279 OOMPH_EXCEPTION_LOCATION);
285 problem_pt, n_eval, alpha_eval, beta_eval, eigenvector_aux);
298 unsigned n = problem_pt->
ndof();
299 eigenvector_real.resize(n);
300 eigenvector_imag.resize(n);
301 unsigned eval_count = 0;
302 while (eval_count < n)
305 if (alpha_eval[eval_count].imag() == 0.0)
311 for (
unsigned j = 0; j < n; ++j)
313 eigenvector_real[eval_count][j] = eigenvector_aux[eval_count][j];
314 eigenvector_imag[eval_count][j] = 0.0;
326 if ((beta_eval[eval_count] != 0.0) &&
327 (beta_eval[eval_count + 1] != 0.0))
329 std::complex<double> lambda_this =
330 alpha_eval[eval_count] / beta_eval[eval_count];
332 std::complex<double> lambda_next =
333 alpha_eval[eval_count + 1] / beta_eval[eval_count + 1];
336 if (fabs(lambda_this.imag() + lambda_next.imag()) >
339 std::ostringstream error_stream;
340 error_stream <<
"Non-zero imaginary part of eigenvalue "
341 << eval_count <<
" : " << lambda_this.imag()
344 <<
"isn't the negative of its subsequent value : "
345 << lambda_next.imag() << std::endl
346 <<
"Their sum " << (lambda_this.imag() + lambda_next.imag())
347 <<
" is greater than Tolerance_for_ccness_check = "
350 OOMPH_CURRENT_FUNCTION,
351 OOMPH_EXCEPTION_LOCATION);
353 if (fabs(lambda_this.real() - lambda_next.real()) >
356 std::ostringstream error_stream;
357 error_stream <<
"Real parts of complex eigenvalue " << eval_count
358 <<
" : " << lambda_this.real() << std::endl;
360 <<
" doesn't agree with its supposed-to-be cc counterpart : "
361 << lambda_next.real() << std::endl
362 <<
"Their difference "
363 << (lambda_this.real() - lambda_next.real())
364 <<
" is greater than Tolerance_for_ccness_check = "
367 OOMPH_CURRENT_FUNCTION,
368 OOMPH_EXCEPTION_LOCATION);
381 for (
unsigned j = 0; j < n; ++j)
383 eigenvector_real[eval_count][j] = eigenvector_aux[eval_count][j];
384 eigenvector_imag[eval_count][j] = eigenvector_aux[eval_count + 1][j];
386 eigenvector_real[eval_count + 1][j] = eigenvector_aux[eval_count][j];
387 eigenvector_imag[eval_count + 1][j] =
388 -eigenvector_aux[eval_count + 1][j];
404 Vector<std::complex<double>>& eigenvalue,
410 std::stringstream error_stream;
411 error_stream <<
"Non-zero shift Sigma_real = " <<
Sigma_real
412 <<
" ignored in LAPACK_QZ::find_eigenvalues\n";
414 error_stream.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
420 char no_eigvecs[2] =
"N";
423 char eigvecs[2] =
"V";
430 double* M_linear =
new double[2 * n * n];
431 double* A_linear =
new double[2 * n * n];
435 for (
int i = 0;
i < n; ++
i)
437 for (
int j = 0; j < n; ++j)
439 M_linear[index] = M(j,
i).real();
440 A_linear[index] = A(j,
i).real();
442 M_linear[index] = M(j,
i).imag();
443 A_linear[index] = A(j,
i).imag();
449 double* alpha =
new double[2 * n];
450 double* beta =
new double[2 * n];
452 double* vec_left =
new double[2];
453 const int leading_dimension_vec_left = 1;
454 double* vec_right =
new double[2 * n * n];
455 const int leading_dimension_vec_right = n;
458 std::vector<double> work(2, 0.0);
462 const int query_workspace = -1;
463 std::vector<double> rwork(8 * n, 0.0);
469 LAPACK_ZGGEV(no_eigvecs,
479 leading_dimension_vec_left,
481 leading_dimension_vec_right,
495 int required_workspace = (int)work[0];
497 work.resize(2 * required_workspace);
500 LAPACK_ZGGEV(no_eigvecs,
526 eigenvalue.resize(n);
527 eigenvector.resize(n);
530 for (
int i = 0;
i < n; ++
i)
533 std::complex<double> num(alpha[2 *
i], alpha[2 *
i + 1]);
534 std::complex<double> den(beta[2 *
i], beta[2 *
i + 1]);
538 eigenvalue[
i] = num / den;
541 eigenvector[
i].resize(n);
544 for (
int k = 0; k < n; ++k)
546 eigenvector[
i][k] = std::complex<double>(
547 vec_right[2 *
i * n + 2 * k], vec_right[2 *
i * n + 2 * k + 1]);
A class for compressed row matrices. This is a distributable object.
Abstract base class for matrices of complex doubles – adds abstract interfaces for solving,...
virtual unsigned long nrow() const =0
Return the number of rows of the matrix.
LinearAlgebraDistribution * distribution_pt() const
access to the LinearAlgebraDistribution
void build_distribution(const LinearAlgebraDistribution *const dist_pt)
setup the distribution of this distributable linear algebra object
double Sigma_real
Double value that represents the real part of the shift in shifted eigensolvers.
void ZGGEV_error(const int &info, const int &n)
Provide diagonstic for ZGGEV error return.
void solve_eigenproblem_helper(Problem *const &problem_pt, const int &n_eval, Vector< std::complex< double >> &alpha, Vector< double > &beta, Vector< DoubleVector > &eigenvector)
Helper function called from "raw" lapack code.
void find_eigenvalues(const ComplexMatrixBase &A, const ComplexMatrixBase &M, Vector< std::complex< double >> &eigenvalue, Vector< Vector< std::complex< double >>> &eigenvector)
Find the eigenvalues of a complex generalised eigenvalue problem specified by . Note: the (real) shif...
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=false)
Solve the real eigenproblem that is assembled by elements in a mesh in a Problem object....
void DGGEV_error(const int &info, const int &n)
Provide diagonstic for DGGEV error return.
double Tolerance_for_ccness_check
Tolerance for checking complex conjugateness of eigenvalues.
Describes the distribution of a distributable linear algebra type object. Typically this is a contain...
An OomphLibError object which should be thrown when an run-time error is encountered....
An OomphLibWarning object which should be created as a temporary object to issue a warning....
////////////////////////////////////////////////////////////////// //////////////////////////////////...
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...
unsigned long ndof() const
Return the number of dofs.
OomphCommunicator * communicator_pt()
access function to the oomph-lib communicator
A slight extension to the standard template vector class so that we can include "graceful" array rang...
//////////////////////////////////////////////////////////////////// ////////////////////////////////...