9 #if defined(HAVE_SLEPC)
12 #if SLEPC_VERSION_RELEASE != 0 && \
13 (SLEPC_VERSION_MAJOR < 3 || \
14 (SLEPC_VERSION_MAJOR == 3 && SLEPC_VERSION_MINOR < 2))
15 #define EPSDestroy(e) EPSDestroy(*(e))
18 void eigenSolver::_check(
int ierr)
const { CHKERRABORT(PETSC_COMM_WORLD, ierr); }
21 std::string B,
bool hermitian)
22 : _sysA(0), _sysB(0), _hermitian(hermitian)
26 if(!_sysA)
Msg::Error(
"Could not find PETSc system '%s'", A.c_str());
30 if(!_sysB)
Msg::Error(
"Could not find PETSc system '%s'", B.c_str());
36 : _sysA(A), _sysB(B), _hermitian(hermitian)
41 std::string method,
double tolVal,
int iterMax)
43 if(!_sysA)
return false;
44 Mat A = _sysA->getMatrix();
45 Mat B = _sysB ? _sysB->getMatrix() : PETSC_NULL;
48 _check(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
49 _check(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
50 _check(MatGetSize(A, &N, &M));
54 _check(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
55 _check(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
56 _check(MatGetSize(B, &N2, &M2));
61 _check(EPSCreate(PETSC_COMM_WORLD, &eps));
62 _check(EPSSetOperators(eps, A, B));
64 _check(EPSSetProblemType(eps, _sysB ? EPS_GHEP : EPS_HEP));
66 _check(EPSSetProblemType(eps, _sysB ? EPS_GNHEP : EPS_NHEP));
69 _check(EPSSetDimensions(eps, numEigenValues, PETSC_DECIDE, PETSC_DECIDE));
70 _check(EPSSetTolerances(eps, tolVal, iterMax));
71 if(method ==
"krylovschur")
72 _check(EPSSetType(eps, EPSKRYLOVSCHUR));
73 else if(method ==
"arnoldi")
74 _check(EPSSetType(eps, EPSARNOLDI));
75 else if(method ==
"arpack")
76 _check(EPSSetType(eps, EPSARPACK));
77 else if(method ==
"power")
78 _check(EPSSetType(eps, EPSPOWER));
80 Msg::Error(
"eigenSolver: method '%s' not available", method.c_str());
81 _check(EPSSetType(eps, EPSKRYLOVSCHUR));
85 _check(EPSSetFromOptions(eps));
89 _check(EPSSetDimensions(eps, numEigenValues, PETSC_DECIDE, PETSC_DECIDE));
90 if(which ==
"smallest")
91 _check(EPSSetWhichEigenpairs(eps, EPS_SMALLEST_MAGNITUDE));
92 else if(which ==
"smallestReal")
93 _check(EPSSetWhichEigenpairs(eps, EPS_SMALLEST_REAL));
94 else if(which ==
"largest")
95 _check(EPSSetWhichEigenpairs(eps, EPS_LARGEST_MAGNITUDE));
98 #if(SLEPC_VERSION_RELEASE == 0 || \
99 (SLEPC_VERSION_MAJOR > 3 || \
100 (SLEPC_VERSION_MAJOR == 3 && SLEPC_VERSION_MINOR >= 4)))
105 _check(EPSGetType(eps, &type));
106 Msg::Debug(
"SLEPc solution method: %s", type);
109 _check(EPSGetDimensions(eps, &nev, PETSC_NULL, PETSC_NULL));
110 Msg::Debug(
"SLEPc number of requested eigenvalues: %d", nev);
113 _check(EPSGetTolerances(eps, &tol, &maxit));
114 Msg::Debug(
"SLEPc stopping condition: tol=%g, maxit=%d", tol, maxit);
119 _check(EPSSolve(eps));
123 _check(EPSGetIterationNumber(eps, &its));
124 EPSConvergedReason reason;
125 _check(EPSGetConvergedReason(eps, &reason));
126 if(reason == EPS_CONVERGED_TOL) {
128 Msg::Debug(
"SLEPc converged in %d iterations (Wall %gs, CPU %gs)", its,
131 else if(reason == EPS_DIVERGED_ITS)
132 Msg::Error(
"SLEPc diverged after %d iterations", its);
133 else if(reason == EPS_DIVERGED_BREAKDOWN)
134 Msg::Error(
"SLEPc generic breakdown in method");
135 #if(SLEPC_VERSION_MAJOR < 3 || \
136 (SLEPC_VERSION_MAJOR == 3 && SLEPC_VERSION_MINOR < 2))
137 else if(reason == EPS_DIVERGED_NONSYMMETRIC)
143 _check(EPSGetConverged(eps, &nconv));
144 Msg::Debug(
"SLEPc number of converged eigenpairs: %d", nconv);
147 if(nconv > nev) nconv = nev;
151 #if(PETSC_VERSION_MAJOR == 3) && (PETSC_VERSION_MINOR < 6)
152 _check(MatGetVecs(A, PETSC_NULL, &xr));
153 _check(MatGetVecs(A, PETSC_NULL, &xi));
155 _check(MatCreateVecs(A, PETSC_NULL, &xr));
156 _check(MatCreateVecs(A, PETSC_NULL, &xi));
160 for(
int i = 0; i < nconv; i++) {
162 _check(EPSGetEigenpair(eps, i, &kr, &ki, xr, xi));
164 #if(PETSC_VERSION_MAJOR == 3) && (PETSC_VERSION_MINOR < 6)
165 _check(EPSComputeRelativeError(eps, i, &error));
167 _check(EPSComputeError(eps, i, EPS_ERROR_RELATIVE, &error));
169 #if defined(PETSC_USE_COMPLEX)
170 PetscReal re = PetscRealPart(kr);
171 PetscReal im = PetscImaginaryPart(kr);
176 Msg::Debug(
"EIG %03d %s%.16e %s%.16e %3.6e", i, (re < 0) ?
"" :
" ", re,
177 (im < 0) ?
"" :
" ", im, error);
180 _eigenValues.push_back(std::complex<double>(re, im));
181 PetscScalar *tmpr, *tmpi;
182 _check(VecGetArray(xr, &tmpr));
183 _check(VecGetArray(xi, &tmpi));
184 std::vector<std::complex<double> > ev(N);
185 for(
int i = 0; i < N; i++) {
186 #if defined(PETSC_USE_COMPLEX)
189 ev[i] = std::complex<double>(tmpr[i], tmpi[i]);
192 _eigenVectors.push_back(ev);
194 _check(VecDestroy(&xr));
195 _check(VecDestroy(&xi));
198 _check(EPSDestroy(&eps));
200 if(reason == EPS_CONVERGED_TOL) {
213 for(std::size_t imode = 0; imode < modeView.size(); imode++) {
214 int i = modeView[imode];
216 for(std::size_t j = 0; j < _eigenVectors[i].size(); j++) {
217 std::complex<double> val = _eigenVectors[i][j];
218 double normval = std::abs(val);
225 for(std::size_t j = 0; j < _eigenVectors[i].size(); j++) {