/// <summary> /// Check residuals of generalized eigenvalue problem. /// </summary> /// <param name="A">Symmetric matrix.</param> /// <param name="B">Symmetric matrix.</param> /// <param name="k">The number of converged eigenvalues.</param> /// <param name="v">The eigenvalues array.</param> /// <param name="X">The eigenvectors matrix.</param> /// <param name="print">If true, print residuals.</param> /// <returns>True, if all residuals are below threshold.</returns> public static bool CheckResiduals(SparseMatrix A, SparseMatrix B, int k, Complex[] v, Matrix <Complex> X, bool print) { int N = A.RowCount; // If more eigenvalues converged than were requested (real, non-symmetric case only). k = Math.Min(k, X.ColumnCount); if (print) { Console.WriteLine(); Console.WriteLine(" Lambda Residual"); } var x = new Complex[N]; var y = new Complex[N]; bool ok = true; for (int i = 0; i < k; i++) { var lambda = v[i]; X.Column(i, x); CVector.Copy(x, y); if (B != null) { // y = B*x B.Multiply(x, y); } // y = A*x - lambda*B*x A.Multiply(1.0, x, -lambda, y); double r = CVector.Norm(y) / Complex.Abs(lambda); if (r > ERROR_THRESHOLD) { ok = false; } if (print) { Console.WriteLine("{0,3}: {1,10:0.00000000} {2,10:0.00e+00}", i, lambda, r); } } return(ok); }
/// <summary> /// Prints eigenvalues and eigenvectors of nonsymmetric generalized eigen-problems. /// </summary> public static void General(SparseMatrix A, SparseMatrix B, SpectraResult result, bool shift, bool cshift = false) { if (!EnsureSuccess(result)) { return; } int n = A.RowCount; int nconv = result.ConvergedEigenValues; Console.WriteLine(); Console.WriteLine("Testing ARPACK++ class ARluNonSymGenEig"); Console.WriteLine("Real nonsymmetric generalized eigenvalue problem: A*x - lambda*B*x"); Console.WriteLine(!shift ? "Regular mode" : (cshift ? "Shift and invert mode (using the imaginary part of OP)" : "Shift and invert mode (using the real part of OP)")); Console.WriteLine(); Console.WriteLine("Dimension of the system : " + n); Console.WriteLine("Number of 'requested' eigenvalues : " + result.Count); Console.WriteLine("Number of 'converged' eigenvalues : " + nconv); Console.WriteLine("Number of Arnoldi vectors generated: " + result.ArnoldiCount); Console.WriteLine("Number of iterations taken : " + result.IterationsTaken); Console.WriteLine(); var evals = result.EigenValues; var evecs = result.EigenVectors; // Printing eigenvalues. Console.WriteLine("Eigenvalues:"); for (int i = 0; i < nconv; i++) { Console.WriteLine(" lambda[" + (i + 1) + "]: " + evals[i]); } Console.WriteLine(); if (evecs != null) { // Printing the residual norm || A*x - lambda*B*x || // for the nconv accurately computed eigenvectors. var x = new Complex[n]; var y = new Complex[n]; var r = new double[nconv]; // residuals for (int i = 0; i < nconv; i++) { var lambda = evals[i]; evecs.Column(i, x); CVector.Copy(x, y); // y = B*x B.Multiply(x, y); // y = A*x - lambda*B*x A.Multiply(1.0, x, -lambda, y); r[i] = CVector.Norm(y) / Complex.Abs(lambda); } for (int i = 0; i < nconv; i++) { Console.WriteLine("||A*x(" + i + ") - lambda(" + i + ")*B*x(" + i + ")||: " + r[i]); } Console.WriteLine(); } }