def solve_exp(t, A, b, x): # Setup the solver M = SLEPc.MFN().create() M.setOperator(A) f = M.getFN() f.setType(SLEPc.FN.Type.EXP) f.setScale(t) M.setTolerances(1e-7) M.setFromOptions() # Solve the problem M.solve(b, x) its = M.getIterationNumber() Print("Number of iterations of the method: %i" % its) sol_type = M.getType() Print("Solution method: %s" % sol_type) ncv = M.getDimensions() Print("") Print("Subspace dimension: %i" % ncv) tol, maxit = M.getTolerances() Print("Stopping condition: tol=%.4g, maxit=%d" % (tol, maxit)) Print("Computed vector at time t=%.4g has norm %g" % (t.real, x.norm())) Print("")
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 evolve(state,H=None,t=None,result=None,tol=None,mfn=None): """ Evolve a quantum state according to the Schrodinger equation under the Hamiltonian H. The units are natural, that is, the evolution is simply .. math:: \Psi_t = e^{-iHt} \Psi_0 Parameters ---------- state : petsc4py.PETSc.Vec A PETSc vector containing the state to be evolved. Can be created easily with :func:`dynamite.tools.build_state`. H : Operator The Hamiltonian t : float The time for which to evolve. Can be negative to evolve backwards in time. result : petsc4py.PETSc.Vec, optional Where to store the result state. If not given, a new vector is created in which to store the result. If evolving repeatedly many times, it is a good idea to pass a result vector to avoid repeatedly allocating a lot of memory. Will be overwritten. tol : float, optional The tolerance for the evolution. Error estimation is difficult for Krylov exponentiation; this merely requests that the error be somewhat close to ``tol``. There is no guarantee that it will actually be smaller. mfn : slepc4py.SLEPc.MFN, optional Advanced users can pass their own matrix function object from SLEPc. In that case the arguments ``H`` and ``t`` can be omitted if they have been set for the MFN object manually. Returns ------- petsc4py.PETSc.Vec The result vector """ if result is None: result = H.get_mat().createVecs(side='l') if H is not None: # check if the evolution is trivial. if H*state = 0, # then the evolution does nothing and state is unchanged. # In this case MFNSolve fails. to avoid that, we check if # we have that condition. # TODO: this is really fast because it's just a matrix-vector # multiply, but it takes a non-negligible amount of time for # really big matrices. Should think of a better way or add a # switch to remove this check H.get_mat().mult(state,result) if result.norm() == 0: result = state.copy() return result if mfn is None: mfn = SLEPc.MFN().create() mfn.setType('expokit') f = mfn.getFN() f.setType(SLEPc.FN.Type.EXP) mfn.setFromOptions() if t is None or H is None: raise ValueError('Must supply t and H if not supplying mfn to evolve') if tol is not None: mfn.setTolerances(tol) if H is not None: mfn.setOperator(H.get_mat()) if t is not None: f = mfn.getFN() f.setScale(-1j*t) mfn.solve(state,result) conv = mfn.getConvergedReason() if conv <= 0: if conv == -1: raise RuntimeError('solver reached maximum number of iterations without ' 'converging. perhaps try increasing the max iterations with ' 'the options to config.initialize ["-mfn_max_it","<maxits>"].') elif conv == -2: raise RuntimeError('solver failed to converge with MFN_DIVERGED_BREAKDOWN.') else: raise RuntimeError('solver failed to converge.') return result
def mfn_multiply_slepc(mat, vec, fntype='exp', MFNType='AUTO', comm=None, isherm=False): """Compute the action of ``func(mat) @ vec``. Parameters ---------- mat : matrix-like Matrix to compute function action of. vec : vector-like Vector to compute matrix function action on. func : {'exp', 'sqrt', 'log'}, optional Function to use. MFNType : {'krylov', 'expokit'}, optional Method of computing the matrix function action, 'expokit' is only available for func='exp'. comm : mpi4py.MPI.Comm instance, optional The mpi communicator. isherm : bool, optional If `mat` is known to be hermitian, this might speed things up in some circumstances. Returns ------- fvec : np.matrix The vector output of ``func(mat) @ vec``. """ SLEPc, comm = get_slepc(comm=comm) mat = convert_mat_to_petsc(mat, comm=comm) if isherm: mat.setOption(mat.Option.HERMITIAN, True) vec = convert_vec_to_petsc(vec, comm=comm) out = new_petsc_vec(vec.size, comm=comm) if MFNType.upper() == 'AUTO': if (fntype == 'exp') and (vec.size <= 2**16): MFNType = 'EXPOKIT' else: MFNType = 'KRYLOV' # set up the matrix function options and objects mfn = SLEPc.MFN().create(comm=comm) mfn.setType(getattr(SLEPc.MFN.Type, MFNType.upper())) mfn_fn = mfn.getFN() mfn_fn.setType(getattr(SLEPc.FN.Type, fntype.upper())) mfn_fn.setScale(1.0, 1.0) mfn.setFromOptions() mfn.setOperator(mat) # 'solve' / perform the matrix function mfn.solve(vec, out) # --> gather the (distributed) petsc vector to a numpy matrix on master all_out = gather_petsc_array(out, comm=comm, out_shape=(-1, 1), matrix=True) comm.Barrier() mfn.destroy() return all_out