>= \
(major)*10000 + (minor)*100 + (subminor))
+/*
+ * SLEPC
+ * see slepcversion.h
+ */
+#define DEAL_II_SLEPC_VERSION_GTE(major,minor,subminor) \
+ ((SLEPC_VERSION_MAJOR * 10000 + \
+ SLEPC_VERSION_MINOR * 100 + \
+ SLEPC_VERSION_SUBMINOR) \
+ >= \
+ (major)*10000 + (minor)*100 + (subminor))
+
/*
* Trilinos:
*/
* Store a copy of the flags for this particular solver.
*/
const AdditionalData additional_data;
+
+ /**
+ * Make the solver class a friend, since it may need to set target
+ * equal the provided shift value.
+ */
+ friend class SolverBase;
};
/**
{
// set transformation type if any
// STSetShift is called inside
- const PetscErrorCode ierr = EPSSetST(eps,transformation.st);
+ PetscErrorCode ierr = EPSSetST(eps,transformation.st);
AssertThrow (ierr == 0, SolverBase::ExcSLEPcError(ierr));
+
+#if DEAL_II_SLEPC_VERSION_GTE(3, 8, 0)
+ // see https://lists.mcs.anl.gov/mailman/htdig/petsc-users/2017-October/033649.html
+ // From 3.8.0 SLEPc insists that when looking for smallest eigenvalues with shift-and-invert
+ // users should (a) set target (b) use EPS_TARGET_MAGNITUDE
+ // The former, however, needs to be applied to eps object and not spectral transformation.
+ if (SLEPcWrappers::TransformationShiftInvert *sinv = dynamic_cast<SLEPcWrappers::TransformationShiftInvert *>(&transformation))
+ {
+ ierr = EPSSetTarget (eps, sinv->additional_data.shift_parameter);
+ AssertThrow (ierr == 0, SolverBase::ExcSLEPcError(ierr));
+ }
+#endif
+
}
void
// Set the initial vector. This is optional, if not done the initial vector is set to random values
eigensolver->set_initial_space(eigenfunctions);
- eigensolver->set_which_eigenpairs (EPS_SMALLEST_REAL);
+ eigensolver->set_which_eigenpairs (EPS_TARGET_MAGNITUDE);
eigensolver->set_problem_type (EPS_GHEP);
eigensolver->solve (stiffness_matrix,