Actual source code: cgeig.c

  1: /*
  2:    Code for calculating extreme eigenvalues via the Lanczo method
  3:    running with CG. Note this only works for symmetric real and Hermitian
  4:    matrices (not complex matrices that are symmetric).
  5: */
  6: #include <../src/ksp/ksp/impls/cg/cgimpl.h>
  7: #include <../include/petscblaslapack.h>

  9: PetscErrorCode KSPComputeEigenvalues_CG(KSP ksp, PetscInt nmax, PetscReal *r, PetscReal *c, PetscInt *neig)
 10: {
 11:   KSP_CG      *cgP = (KSP_CG *)ksp->data;
 12:   PetscScalar *d, *e;
 13:   PetscReal   *ee;
 14:   PetscInt     n = ksp->its;
 15:   PetscBLASInt bn, lierr = 0, ldz = 1;

 17:   PetscFunctionBegin;
 18:   PetscCheck(nmax >= n, PetscObjectComm((PetscObject)ksp), PETSC_ERR_ARG_SIZ, "Not enough room in work space r and c for eigenvalues");
 19:   *neig = n;

 21:   PetscCall(PetscArrayzero(c, nmax));
 22:   if (!n) PetscFunctionReturn(PETSC_SUCCESS);
 23:   d  = cgP->d;
 24:   e  = cgP->e;
 25:   ee = cgP->ee;

 27:   /* copy tridiagonal matrix to work space */
 28:   for (PetscInt j = 0; j < n; j++) {
 29:     r[j]  = PetscRealPart(d[j]);
 30:     ee[j] = PetscRealPart(e[j]);
 31:   }

 33:   PetscCall(PetscBLASIntCast(n, &bn));
 34:   PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
 35:   PetscCallBLAS("LAPACKREALstev", LAPACKREALstev_("N", &bn, r, ee, NULL, &ldz, NULL, &lierr));
 36:   PetscCheck(!lierr, PETSC_COMM_SELF, PETSC_ERR_PLIB, "xSTEV error");
 37:   PetscCall(PetscFPTrapPop());
 38:   PetscCall(PetscSortReal(n, r));
 39:   PetscFunctionReturn(PETSC_SUCCESS);
 40: }

 42: PetscErrorCode KSPComputeExtremeSingularValues_CG(KSP ksp, PetscReal *emax, PetscReal *emin)
 43: {
 44:   KSP_CG      *cgP = (KSP_CG *)ksp->data;
 45:   PetscScalar *d, *e;
 46:   PetscReal   *dd, *ee;
 47:   PetscInt     n = ksp->its;
 48:   PetscBLASInt bn, lierr = 0, ldz = 1;

 50:   PetscFunctionBegin;
 51:   if (!n) {
 52:     *emax = *emin = 1.0;
 53:     PetscFunctionReturn(PETSC_SUCCESS);
 54:   }
 55:   d  = cgP->d;
 56:   e  = cgP->e;
 57:   dd = cgP->dd;
 58:   ee = cgP->ee;

 60:   /* copy tridiagonal matrix to work space */
 61:   for (PetscInt j = 0; j < n; j++) {
 62:     dd[j] = PetscRealPart(d[j]);
 63:     ee[j] = PetscRealPart(e[j]);
 64:   }

 66:   PetscCall(PetscBLASIntCast(n, &bn));
 67:   PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF));
 68:   PetscCallBLAS("LAPACKREALstev", LAPACKREALstev_("N", &bn, dd, ee, NULL, &ldz, NULL, &lierr));
 69:   PetscCheck(!lierr, PETSC_COMM_SELF, PETSC_ERR_PLIB, "xSTEV error");
 70:   PetscCall(PetscFPTrapPop());
 71:   *emin = dd[0];
 72:   *emax = dd[n - 1];
 73:   PetscFunctionReturn(PETSC_SUCCESS);
 74: }