Exemple #1
0
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("")
Exemple #2
0
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
Exemple #3
0
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
Exemple #4
0
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