def solve_eigensystem(A, B, problem_type=SLEPc.EPS.ProblemType.GHEP): # Create the results vectors xr, tmp = A.getVecs() xi, tmp = A.getVecs() pc = PETSc.PC().create() # pc.setType(pc.Type.HYPRE) pc.setType(pc.Type.BJACOBI) ksp = PETSc.KSP().create() ksp.setType(ksp.Type.PREONLY) ksp.setPC(pc) F = SLEPc.ST().create() F.setType(F.Type.PRECOND) F.setKSP(ksp) F.setShift(0) # Setup the eigensolver E = SLEPc.EPS().create() E.setST(F) E.setOperators(A, B) E.setType(E.Type.LOBPCG) E.setDimensions(10, PETSc.DECIDE) E.setWhichEigenpairs(E.Which.SMALLEST_REAL) E.setProblemType(problem_type) E.setFromOptions() # Solve the eigensystem E.solve() Print("") its = E.getIterationNumber() Print("Number of iterations of the method: %i" % its) sol_type = E.getType() Print("Solution method: %s" % sol_type) nev, ncv, mpd = E.getDimensions() Print("Number of requested eigenvalues: %i" % nev) tol, maxit = E.getTolerances() Print("Stopping condition: tol=%.4g, maxit=%d" % (tol, maxit)) nconv = E.getConverged() Print("Number of converged eigenpairs: %d" % nconv) if nconv > 0: Print("") Print(" k ||Ax-kx||/||kx|| ") Print("----------------- ------------------") for i in range(nconv): k = E.getEigenpair(i, xr, xi) error = E.computeError(i) if k.imag != 0.0: Print(" %9f%+9f j %12g" % (k.real, k.imag, error)) else: Print(" %12f %12g" % (k.real, error)) Print("")
def _create(self,nev,target): """ Create and setup the SLEPC solver""" # mpi stuff comm=PETSc.COMM_WORLD.tompi4py() rank = comm.Get_rank() # create the solver with the selected factory E = self._SLEPc_PB() E.create() # Setup the spectral transformation SHIFT = SLEPc.ST().create() SHIFT.setType(SHIFT.Type.SINVERT) E.setST(SHIFT) E.setTarget(target) # operator setup K = self.K if self.pb_type == 'std': # unpack the operator matrix E.setOperators(*K) if self.pb_type == 'gen': # M=-K1 E.setOperators(K[0],-K[1]) else: E.setOperators(K) # number of eigenvlue we are looking for E.setDimensions(nev=nev) # By defaut use non hermitian solver E.setProblemType(self.PB_TYPE[self.pb_type]) # Direct solver seting (for shift and invert) ksp=SHIFT.getKSP() ksp.setType('preonly') # direct solver in petsc= preconditioner pc=ksp.getPC() pc.setType('lu') #pc.setFactorSolverType('superlu_dist') # set solver options pc.setFactorSolverType(gopts['direct_solver_name']) opts = PETSc.Options(gopts['direct_solver_petsc_options_name']) for op_name,op_value in gopts['direct_solver_petsc_options_dict'].items(): opts[op_name]=op_value # Mumps options to avoid mumps crash with high fill in # The problem arise if the prediction/mem allocation is too different (default 20%) #opts["icntl_14"] = 50 # ICNTL(14) controls the percentage increase in the estimated working space #opts["icntl_6"] = 5 # Use ICNTL(6)= 5 for augmented system (which is asystem with a large zero diagonal block). # After all options have been set, the user should call the setFromOptions() E.setFromOptions() # store the solver self.E=E
def DirectModeSLEPc(ffdisc, shift, nev): from petsc4py import PETSc from slepc4py import SLEPc # Operators print 'Set operators' Lmat = CSR2Mat(ffdisc.L) Bmat = CSR2Mat(ffdisc.B) # Setup EPS print 'Set solver' S = SLEPc.EPS() S.create() S.setTarget(shift) S.setWhichEigenpairs(SLEPc.EPS.Which.TARGET_MAGNITUDE) SI = SLEPc.ST().create() SI.setType(SLEPc.ST.Type.SINVERT) SI.setOperators(Lmat, Bmat) SI.setShift(shift) S.setST(SI) S.setDimensions(nev=nev, ncv=60) S.setTolerances(tol=tol_ev, max_it=100) S.setFromOptions() # Solve the EVP print 'Solving EVP' S.solve() its = S.getIterationNumber() nconv = S.getConverged() omega = zeros(nconv, 'complex') modes = zeros([ffdisc.ndof, nconv], 'complex') ev = Lmat.getVecRight() for i in range(nconv): eigval = S.getEigenpair(i, ev) v = Vec2DOF(ev) omega[i] = eigval / (-1j) modes[:, i] = v return omega, modes
def _init_spectral_inverter(STType="sinvert", KSPType="preonly", PCType="lu", PCFactorSolverType="mumps", comm=None): """Create a slepc spectral transformation object with specified solver. """ SLEPc, comm = get_slepc(comm=comm) S = SLEPc.ST().create(comm=comm) S.setType(STType) # set the krylov subspace and preconditioner. if KSPType: K = _init_krylov_subspace( KSPType=KSPType, PCType=PCType, comm=comm, PCFactorSolverType=PCFactorSolverType) S.setKSP(K) S.setFromOptions() return S
def help(args=None): import sys # program name try: prog = sys.argv[0] except Exception: prog = getattr(sys, 'executable', 'python') # arguments if args is None: args = sys.argv[1:] elif isinstance(args, str): args = args.split() else: args = [str(a) for a in args] # initialization import slepc4py slepc4py.init([prog, '-help'] + args) from slepc4py import SLEPc # and finally ... COMM = SLEPc.COMM_SELF if 'eps' in args: eps = SLEPc.EPS().create(comm=COMM) eps.setFromOptions() eps.destroy() del eps if 'svd' in args: svd = SLEPc.SVD().create(comm=COMM) svd.setFromOptions() svd.destroy() del svd if 'pep' in args: pep = SLEPc.PEP().create(comm=COMM) pep.setFromOptions() pep.destroy() del pep if 'nep' in args: nep = SLEPc.NEP().create(comm=COMM) nep.setFromOptions() nep.destroy() del nep if 'mfn' in args: mfn = SLEPc.MFN().create(comm=COMM) mfn.setFromOptions() mfn.destroy() del mfn if 'st' in args: st = SLEPc.ST().create(comm=COMM) st.setFromOptions() st.destroy() del st if 'bv' in args: bv = SLEPc.BV().create(comm=COMM) bv.setFromOptions() bv.destroy() del bv if 'rg' in args: rg = SLEPc.RG().create(comm=COMM) rg.setFromOptions() rg.destroy() del rg if 'fn' in args: fn = SLEPc.FN().create(comm=COMM) fn.setFromOptions() fn.destroy() del fn if 'ds' in args: ds = SLEPc.DS().create(comm=COMM) ds.setFromOptions() ds.destroy() del ds
def DirectModeSLEPc(L, B, shift, nev): """ Computes generalized eigenvectors and eigenvalues for the problem Lq = lambda Bq using SLEPc inputs : B,L, PETSc Mats shift, scalar (same on all procs). Shift parameter for the shift-invert method nev, integer. Number of requested eigenvalues outputs: omega, complex array(nconv). Conputed eigenvalues modes, complex array(nconv,ndofs). Computed eigenvectors residual, real array(nconv). Actual residuals for each mode ALL OUTPUT ARE ONLY ON PROC 0 (=None on other procs) TO DO: compute left eigenvectors (adjoint problem) """ comm = MPI.COMM_WORLD rank = comm.Get_rank() ev = L.getVecRight() Lq = ev.duplicate() Bq = ev.duplicate() ndof = ev.getSize() # Setup EPS Print(" - Setting up the EPS and the ST") SI = SLEPc.ST().create() SI.setType(SLEPc.ST.Type.SINVERT) SI.setOperators(L, B) SI.setShift(shift) SI.setFromOptions() S = SLEPc.EPS() S.create(comm) S.setTarget(shift) S.setWhichEigenpairs(SLEPc.EPS.Which.TARGET_MAGNITUDE) S.setST(SI) S.setDimensions(nev=nev, ncv=60) S.setTolerances(tol=tol_ev, max_it=100) S.setFromOptions() # Solve the EVP Print(" - Solving the EPS") S.solve() its = S.getIterationNumber() nconv = S.getConverged() if rank == 0: residual = zeros(nconv) omega = zeros(nconv, 'complex') modes = zeros([ndof, nconv], 'complex') else: residual = None omega = None modes = None for i in range(nconv): eigval = S.getEigenpair(i, ev) L.mult(ev, Lq) B.mult(ev, Bq) Bq.aypx(-eigval, Lq) res = Bq.norm() / ev.norm() v = Vec2DOF(ev) if rank == 0: omega[i] = eigval / (-1j) modes[:, i] = v residual[i] = res return omega, modes, residual