Beispiel #1
0
    def _eval_evalf(self, prec):
        # The default code is insufficient for polar arguments.
        # mpmath provides an optional argument "r", which evaluates
        # G(z**(1/r)). I am not sure what its intended use is, but we hijack it
        # here in the following way: to evaluate at a number z of |argument|
        # less than (say) n*pi, we put r=1/n, compute z' = root(z, n)
        # (carefully so as not to loose the branch information), and evaluate
        # G(z'**(1/r)) = G(z'**n) = G(z).
        from sympy.functions import exp_polar, ceiling
        from sympy import Expr
        import mpmath
        znum = self.argument._eval_evalf(prec)
        if znum.has(exp_polar):
            znum, branch = znum.as_coeff_mul(exp_polar)
            if len(branch) != 1:
                return
            branch = branch[0].args[0] / I
        else:
            branch = S.Zero
        n = ceiling(abs(branch / S.Pi)) + 1
        znum = znum**(S.One / n) * exp(I * branch / n)

        # Convert all args to mpf or mpc
        try:
            [z, r, ap, bq] = [
                arg._to_mpmath(prec)
                for arg in [znum, 1 / n, self.args[0], self.args[1]]
            ]
        except ValueError:
            return

        with mpmath.workprec(prec):
            v = mpmath.meijerg(ap, bq, z, r)

        return Expr._from_mpmath(v, prec)
Beispiel #2
0
    def _eval_evalf(self, prec):
        # The default code is insufficient for polar arguments.
        # mpmath provides an optional argument "r", which evaluates
        # G(z**(1/r)). I am not sure what its intended use is, but we hijack it
        # here in the following way: to evaluate at a number z of |argument|
        # less than (say) n*pi, we put r=1/n, compute z' = root(z, n)
        # (carefully so as not to loose the branch information), and evaluate
        # G(z'**(1/r)) = G(z'**n) = G(z).
        from sympy.functions import exp_polar, ceiling
        from sympy import Expr
        import mpmath
        z = self.argument
        znum = self.argument._eval_evalf(prec)
        if znum.has(exp_polar):
            znum, branch = znum.as_coeff_mul(exp_polar)
            if len(branch) != 1:
                return
            branch = branch[0].args[0]/I
        else:
            branch = S(0)
        n = ceiling(abs(branch/S.Pi)) + 1
        znum = znum**(S(1)/n)*exp(I*branch / n)

        # Convert all args to mpf or mpc
        try:
            [z, r, ap, bq] = [arg._to_mpmath(prec)
                    for arg in [znum, 1/n, self.args[0], self.args[1]]]
        except ValueError:
            return

        with mpmath.workprec(prec):
            v = mpmath.meijerg(ap, bq, z, r)

        return Expr._from_mpmath(v, prec)
Beispiel #3
0
def analytical_base_partition_function(numer, denom):
    r"""Accurately approximate the partition function Z(numer / denom).

  This uses the analytical formulation of the true partition function Z(alpha),
  as described in the paper (the math after Equation 18), where alpha is a
  positive rational value numer/denom. This is expensive to compute and not
  differentiable, so it is only used for unit tests.

  Args:
    numer: the numerator of alpha, an integer >= 0.
    denom: the denominator of alpha, an integer > 0.

  Returns:
    Z(numer / denom), a double-precision float, accurate to around 9 digits
    of precision.

  Raises:
      ValueError: If `numer` is not a non-negative integer or if `denom` is not
        a positive integer.
  """
    if not isinstance(numer, numbers.Integral):
        raise ValueError(
            "Expected `numer` of type int, but is of type {}".format(
                type(numer)))
    if not isinstance(denom, numbers.Integral):
        raise ValueError(
            "Expected `denom` of type int, but is of type {}".format(
                type(denom)))
    if not numer >= 0:
        raise ValueError("Expected `numer` >= 0, but is = {}".format(numer))
    if not denom > 0:
        raise ValueError("Expected `denom` > 0, but is = {}".format(denom))

    alpha = numer / denom

    # The Meijer-G formulation of the partition function has singularities at
    # alpha = 0 and alpha = 2, but at those special cases the partition function
    # has simple closed forms which we special-case here.
    if alpha == 0:
        return np.pi * np.sqrt(2)
    if alpha == 2:
        return np.sqrt(2 * np.pi)

    # Z(n/d) as described in the paper.
    a_p = (np.arange(1, numer, dtype=np.float64) / numer).tolist()
    b_q = ((np.arange(-0.5, numer - 0.5, dtype=np.float64)) /
           numer).tolist() + (np.arange(1, 2 * denom, dtype=np.float64) /
                              (2 * denom)).tolist()
    z = (1.0 / numer - 1.0 / (2 * denom))**(2 * denom)
    mult = (np.exp(np.abs(2 * denom / numer - 1.0)) *
            np.sqrt(np.abs(2 * denom / numer - 1.0)) *
            (2 * np.pi)**(1 - denom))
    return mult * np.float64(mpmath.meijerg([[], a_p], [b_q, []], z))
Beispiel #4
0
def bg_3d_lum_int(rr,pp,qq,i0,bb):
    # Tested 2011-08-31
    """Fully analytic calculation of lum internal to rr"""
    if not (pp==int(pp) and qq==int(qq)): raise RuntimeError
    pp, qq = int(pp), int(qq)

    reff = 1.0
    ss = rr/reff
    avect = [[1-1.0/qq], [xx/(1.0*qq) for xx in range(1,qq)]]
    bvect = [[xx/(2.0*pp) for xx in range(1,2*pp)] +
             [xx/(2.0*qq) for xx in range(1,2*qq,2)], [-1.0/qq]]    
    factor = 2*i0*reff**2*np.sqrt(pp)/((2*np.pi)**(pp-1)*np.sqrt(qq))    
    zz = (bb/(2*pp))**(2*pp) * ss**(2*qq)
    return factor*ss**2*mpmath.meijerg(avect, bvect, zz)
Beispiel #5
0
def bg_3d_lum_int(rr, pp, qq, i0, bb):
    # Tested 2011-08-31
    """Fully analytic calculation of lum internal to rr"""
    if not (pp == int(pp) and qq == int(qq)): raise RuntimeError
    pp, qq = int(pp), int(qq)

    reff = 1.0
    ss = rr / reff
    avect = [[1 - 1.0 / qq], [xx / (1.0 * qq) for xx in range(1, qq)]]
    bvect = [[xx / (2.0 * pp) for xx in range(1, 2 * pp)] +
             [xx / (2.0 * qq) for xx in range(1, 2 * qq, 2)], [-1.0 / qq]]
    factor = 2 * i0 * reff**2 * np.sqrt(pp) / (
        (2 * np.pi)**(pp - 1) * np.sqrt(qq))
    zz = (bb / (2 * pp))**(2 * pp) * ss**(2 * qq)
    return factor * ss**2 * mpmath.meijerg(avect, bvect, zz)
def rouse_large_cvv_g(t, delta, deltaN, b, kbT=1, xi=1):
    """Cvv^delta(t) for infinite polymer.

    Lampo, BPJ, 2016 Eq. 16."""
    k = 3*kbT/b**2
    ndmap = lambda G, arr: np.array(list(map(G, arr)))
    G = lambda x: float(mpmath.meijerg([[],[3/2]], [[0,1/2],[]], x))
    gtmd = ndmap(G, np.power(deltaN, 2)*xi/(4*k*np.abs(t-delta)))
    gtpd = ndmap(G, np.power(deltaN, 2)*xi/(4*k*np.abs(t+delta)))
    gt = ndmap(G, np.power(deltaN, 2)*xi/(4*k*np.abs(t)))
    return 3*kbT/(np.power(delta, 2)*np.sqrt(xi*k))* (
        np.power(np.abs(t - delta), 1/2)*gtmd
      + np.power(np.abs(t + delta), 1/2)*gtpd
      - 2*np.power(np.abs(t), 1/2)*gt
    )
Beispiel #7
0
    def _p(self, K):
        G = lambda k : mpmath.meijerg([[1. / 6., 5. / 12., 11. / 12.], []],
                       [[1. / 6., 1. / 6., 5. / 12., 0.5, 2. / 3., 5. / 6., 11. / 12.], [0, 1. / 3.]],
                       k ** 6 / 46656.0) / (4 * np.sqrt(3) * np.pi ** (5 / 2) * k)

        if len(K.shape) == 2:
            K1 = np.reshape(K, -1)
            K1.sort()
        else:
            K1 = K
        res = np.zeros(len(K[K < 10 ** 3.2]))
        for i, k in enumerate(K1[K1 < 10 ** 3.2]):
            res[i] = G(k)

        fit = spline(np.log(K1[K1 < 10 ** 3.2]), np.log(res), k=1)
        res = np.reshape(np.exp(fit(np.log(np.reshape(K, -1)))), (len(K[:, 0]), len(K[0, :])))

        return res
Beispiel #8
0
    def _p(self, K):
        G = lambda k : mpmath.meijerg([[(self.alpha - 2) / 2.0, (self.alpha - 1) / 2.0], []],
                       [[0, 0, 0.5], [-0.5]],
                       k ** 2 / 4) / (np.sqrt(np.pi) * sp.gamma(3 - self.alpha))

        if len(K.shape) == 2:
            K1 = np.reshape(K, -1)
            K1.sort()
        else:
            K1 = K
        res = np.zeros(len(K[K < 10 ** 3.2]))
        for i, k in enumerate(K1[K1 < 10 ** 3.2]):
            res[i] = G(k)

        fit = spline(np.log(K1[K1 < 10 ** 3.2]), np.log(res), k=1)
        res = np.reshape(np.exp(fit(np.log(np.reshape(K, -1)))), (len(K[:, 0]), len(K[0, :])))

        return res
Beispiel #9
0
    def _p(self, K):
        G = lambda k: mpmath.meijerg([[(self.alpha - 2) / 2.0, (
            self.alpha - 1) / 2.0], []], [[0, 0, 0.5], [-0.5]], k**2 / 4) / (
                np.sqrt(np.pi) * sp.gamma(3 - self.alpha))

        if len(K.shape) == 2:
            K1 = np.reshape(K, -1)
            K1.sort()
        else:
            K1 = K
        res = np.zeros(len(K[K < 10**3.2]))
        for i, k in enumerate(K1[K1 < 10**3.2]):
            res[i] = G(k)

        fit = spline(np.log(K1[K1 < 10**3.2]), np.log(res), k=1)
        res = np.reshape(np.exp(fit(np.log(np.reshape(K, -1)))),
                         (len(K[:, 0]), len(K[0, :])))

        return res
Beispiel #10
0
    def _p(self, K):
        G = lambda k: mpmath.meijerg([[1. / 6., 5. / 12., 11. / 12.], []], [[
            1. / 6., 1. / 6., 5. / 12., 0.5, 2. / 3., 5. / 6., 11. / 12.
        ], [0, 1. / 3.]], k**6 / 46656.0) / (4 * np.sqrt(3) * np.pi**
                                             (5 / 2) * k)

        if len(K.shape) == 2:
            K1 = np.reshape(K, -1)
            K1.sort()
        else:
            K1 = K
        res = np.zeros(len(K[K < 10**3.2]))
        for i, k in enumerate(K1[K1 < 10**3.2]):
            res[i] = G(k)

        fit = spline(np.log(K1[K1 < 10**3.2]), np.log(res), k=1)
        res = np.reshape(np.exp(fit(np.log(np.reshape(K, -1)))),
                         (len(K[:, 0]), len(K[0, :])))

        return res
Beispiel #11
0
def totalDerivativeOfIncGamma(x, a, b, da, db):
    """
    Computes the total derivative for the (non-normalized) incomplete gamma function, i.e.

    d/dx gamma(a(x))*gammainc(a(x),b(x))

    :param x: Positions where the function is to be computed.
    :type x: numpy.ndarray
    :param a: function handle for a
    :type a: python function
    :param b: function handle for b
    :type b: python function
    :param da: function handle for da/dx
    :type da: python function
    :param db: function handle for db/dx
    :type db: python function
    :returns: derivative values
    :rtype:   numpy.ndarray

    """
    return digamma(a(x))*gammafunc(a(x))*da(x) + exp(-b(x))*b(x)**(a(x)-1)*db(x) \
     - (meijerg([[],[1,1],],[[0,0,a(x)],[]],b(x)) + log(b(x))*gammaincc(a(x),b(x))*gammafunc(a(x)))  * da(x)
Beispiel #12
0
def meijerg_func(m, x):
    return meijerg([[], []], [[0.5, m / 2 - 1, m / 2 - 0.5], [0]], x)
Beispiel #13
0
 def G(x):
     return float(mpmath.meijerg([[], [3/2]], [[0, 1/2], []], x))
Beispiel #14
0
def produce_subdiff_analytic_soln(params, T, xs):
    # Use meijer-G function to calculate subdiffusion for alpha = 1/2
    D_alpha = params[0]
    
    #def integrand(u): 
    #    return 1. / math.sqrt(8 * pow(math.pi,3) * math.sqrt(T)) * float(mpmath.meijerg([[],[]], [[0, 0.25, 0.5],[]], pow(u[0],4) / (256. * T)))
    integrand = lambda u: 1. / math.sqrt(8 * pow(math.pi,3) * D_alpha * math.sqrt(T)) * float(mpmath.meijerg([[],[]], [[0, 0.25, 0.5],[]], pow(u,4) / (256. * D_alpha * D_alpha * T)))
     
    return 1.0 - 2.0 * np.vectorize(lambda x: scipy.integrate.quad(integrand, 0., x)[0])(xs)
Beispiel #15
0
 def lum(rr):
     if np.iterable(rr): return np.array([lum(r) for r in rr])
     ss = rr/reff
     zz = (bb/(2*mm))**(2*mm) * ss**2
     return (factor/ss)*mpmath.meijerg(avect, bvect, zz)
Beispiel #16
0
def plane_wave_potential(grid, spinless=False, e_cutoff=None,
                         non_periodic=False, period_cutoff=None,
                         fieldlines=3, R0=1e8, verbose=False):
    """Return the e-e potential operator in the plane wave basis.

    Args:
        grid (Grid): The discretization to use.
        spinless (bool): Whether to use the spinless model or not.
        e_cutoff (float): Energy cutoff.
        non_periodic (bool): If the system is non-periodic, default to False.
        period_cutoff (float): Period cutoff, default to
            grid.volume_scale() ** (1. / grid.dimensions).
        fieldlines (int): Spatial dimension for electric field lines. 
        R0 (float): Reference length scale where the 2D Coulomb potential 
            is zero.
        verbose (bool): Whether to turn on print statements.  

    Returns:
        operator (FermionOperator)
    """
    print('MATHEMATICA 11')
    
    if grid.dimensions == 1:
        raise ValueError('System dimension cannot be 1.')
        
    # Initialize.
    prefactor = 0.
    
    # 3D case.
    if grid.dimensions == 3:
        prefactor = 2. * numpy.pi / grid.volume_scale()
    
    # 2D case.
    elif grid.dimensions == 2:
        prefactor = 1. / (2. * grid.volume_scale())
        
    operator = FermionOperator((), 0.0)
    spins = [None] if spinless else [0, 1]
    
    if non_periodic and period_cutoff is None:
        period_cutoff = grid.volume_scale() ** (1. / grid.dimensions)

    # Pre-Computations.
    shifted_omega_indices_dict = {}
    shifted_indices_minus_dict = {}
    shifted_indices_plus_dict = {}
    orbital_ids = {}
    for indices_a in grid.all_points_indices():
        shifted_omega_indices = [j - grid.length[i] // 2
                                 for i, j in enumerate(indices_a)]
        shifted_omega_indices_dict[indices_a] = shifted_omega_indices
        shifted_indices_minus_dict[indices_a] = {}
        shifted_indices_plus_dict[indices_a] = {}
        for indices_b in grid.all_points_indices():
            shifted_indices_minus_dict[indices_a][indices_b] = tuple([
                (indices_b[i] - shifted_omega_indices[i]) % grid.length[i]
                for i in range(grid.dimensions)])
            shifted_indices_plus_dict[indices_a][indices_b] = tuple([
                (indices_b[i] + shifted_omega_indices[i]) % grid.length[i]
                for i in range(grid.dimensions)])
        orbital_ids[indices_a] = {}
        for spin in spins:
            orbital_ids[indices_a][spin] = grid.orbital_id(indices_a, spin)

    # Loop once through all plane waves.
    for omega_indices in grid.all_points_indices():
        shifted_omega_indices = shifted_omega_indices_dict[omega_indices]

        # Get the momenta vectors.
        momenta = grid.momentum_vector(omega_indices)
        momenta_squared = momenta.dot(momenta)

        # Skip if momentum is zero.
        if momenta_squared == 0:
            continue

        # Energy cutoff.
        if e_cutoff is not None and momenta_squared / 2. > e_cutoff:
            continue

        # Compute coefficient.
        coefficient = 0.
        
        # 3D case.
        if grid.dimensions == 3:    
            coefficient = prefactor / momenta_squared
            
            # If non-periodic.
            if non_periodic:
                coefficient *= 1.0 - numpy.cos(
                               period_cutoff * numpy.sqrt(momenta_squared))
        
        # 2D case.
        elif grid.dimensions == 2:
            V_nu = 0.
            
            # 2D Coulomb potential.
            if fieldlines == 2:
                
                # If non-periodic.
                if non_periodic:
                    Dkv = period_cutoff * numpy.sqrt(momenta_squared)
                    V_nu = (
                        2. * numpy.pi / momenta_squared * (
                        Dkv * numpy.log(R0 / period_cutoff) * 
                        scipy.special.jv(1, Dkv) - scipy.special.jv(0, Dkv)))
                    
                    if verbose:
                        print('non-periodic')
                        print('cutoff: {}\n'.format(period_cutoff))
                        print('RO = {}'.format(R0))
                
                # If periodic.
                else:
                    var1 = 4. / momenta_squared
                    var2 = 0.25 * momenta_squared

                    V_nu = 0.5 * numpy.complex128(
                        mpmath.meijerg([[1., 1.5, 2.], []], 
                                       [[1.5], []], var1) -
                        mpmath.meijerg([[-0.5, 0., 0.], []], 
                                       [[-0.5, 0.], [-1.]], var2))
            
            # 3D Coulomb potential.
            elif fieldlines == 3:
                
                # If non-periodic.
                if non_periodic:
                    var = -0.25 * period_cutoff**2 * momenta_squared
                    V_nu = numpy.complex128(
                        2 * numpy.pi * period_cutoff * 
                        mpmath.hyp1f2(0.5, 1., 1.5, var))
                    
                    if verbose:
                        print('non-periodic')
                        print('cutoff: {}\n'.format(period_cutoff))
                
                # If periodic.
                else:
                    V_nu = 2 * numpy.pi / numpy.sqrt(momenta_squared)
                
            coefficient = prefactor * V_nu
            
            if verbose:
                print('fieldlines = {}'.format(fieldlines))
                print('prefactor: {}'.format(prefactor))
                print('V_nu: {}'.format(V_nu))
                print('coefficient: {}\n'.format(coefficient))
                
                
        for grid_indices_a in grid.all_points_indices():
            shifted_indices_d = (
                shifted_indices_minus_dict[omega_indices][grid_indices_a])
            for grid_indices_b in grid.all_points_indices():
                shifted_indices_c = (
                    shifted_indices_plus_dict[omega_indices][grid_indices_b])

                # Loop over spins.
                for spin_a in spins:
                    orbital_a = orbital_ids[grid_indices_a][spin_a]
                    orbital_d = orbital_ids[shifted_indices_d][spin_a]
                    for spin_b in spins:
                        orbital_b = orbital_ids[grid_indices_b][spin_b]
                        orbital_c = orbital_ids[shifted_indices_c][spin_b]

                        # Add interaction term.
                        if ((orbital_a != orbital_b) and
                                (orbital_c != orbital_d)):
                            operators = ((orbital_a, 1), (orbital_b, 1),
                                         (orbital_c, 0), (orbital_d, 0))
                            operator += FermionOperator(operators, coefficient)

    # Return.
    return operator
Beispiel #17
0
def jordan_wigner_dual_basis_jellium(grid, spinless=False,
                                     include_constant=False, 
                                     non_periodic=False, period_cutoff=None,
                                     fieldlines=3, R0=1e8, verbose=False):
    """Return the jellium Hamiltonian as QubitOperator in the dual basis.

    Args:
        grid (Grid): The discretization to use.
        spinless (bool): Whether to use the spinless model or not.
        include_constant (bool): Whether to include the Madelung constant.
            Note constant is unsupported for non-uniform, non-cubic cells with
            ions.
        non_periodic (bool): If the system is non-periodic, default to False.
        period_cutoff (float): Period cutoff, default to
            grid.volume_scale() ** (1. / grid.dimensions).
        fieldlines (int): Spatial dimension for electric field lines. 
        R0 (float): Reference length scale where the 2D Coulomb potential 
            is zero.
        verbose (bool): Whether to turn on print statements.

    Returns:
        hamiltonian (QubitOperator)
    """
    if grid.dimensions == 1:
        raise ValueError('System dimension cannot be 1.')
        
    # Initialize.
    n_orbitals = grid.num_points
    volume = grid.volume_scale()
    
    if non_periodic and period_cutoff is None:
        period_cutoff = volume ** (1.0 / grid.dimensions)
        
    if spinless:
        n_qubits = n_orbitals
    else:
        n_qubits = 2 * n_orbitals
    hamiltonian = QubitOperator()

    # Compute vectors.
    momentum_vectors = {}
    momenta_squared_dict = {}
    for indices in grid.all_points_indices():
        momenta = grid.momentum_vector(indices)
        momentum_vectors[indices] = momenta
        momenta_squared_dict[indices] = momenta.dot(momenta)
    
    #-------------------------------------------------------------------------
    # Compute the identity coefficient and the coefficient of local Z terms.
    #-------------------------------------------------------------------------
    identity_coefficient = 0.
    z_coefficient = 0.
    
    for k_indices in grid.all_points_indices():
        momenta = momentum_vectors[k_indices]
        momenta_squared = momenta.dot(momenta)
        if momenta_squared == 0:
            continue
    
        identity_coefficient += momenta_squared / 2.
        z_coefficient -= momenta_squared / (4. * float(n_orbitals))
        
        # Coefficients for this value of nu.
        identity_coefficient_nu = 0.
        z_coefficient_nu = 0.

        # 3D case.
        if grid.dimensions == 3:
            identity_coefficient_nu = (numpy.pi * float(n_orbitals) /
                                      (momenta_squared * volume))
            z_coefficient_nu = numpy.pi / (momenta_squared * volume)
            
            # If non-periodic.
            if non_periodic:
                correction = 1.0 - numpy.cos(
                             period_cutoff * numpy.sqrt(momenta_squared))
                identity_coefficient_nu *= correction
                z_coefficient_nu *= correction

                if verbose:
                    print('non_periodic')
                    print('cutoff: {}'.format(period_cutoff))
                    print('correction: {}'.format(correction))

        # 2D case.
        elif grid.dimensions == 2:
            V_nu = 0.
            
            # 2D Coulomb potential.
            if fieldlines == 2:
                
                # If non-periodic.
                if non_periodic:
                    Dkv = period_cutoff * numpy.sqrt(momenta_squared)
                    V_nu = (
                        2. * numpy.pi / momenta_squared * (
                        Dkv * numpy.log(R0 / period_cutoff) * 
                        scipy.special.jv(1, Dkv) - scipy.special.jv(0, Dkv)))
                    
                    if verbose:
                        print('non-periodic')
                        print('cutoff: {}'.format(period_cutoff))
                        print('RO = {}'.format(R0))
                
                # If periodic.
                else:
                    var1 = 4. / momenta_squared
                    var2 = 0.25 * momenta_squared

                    V_nu = 0.5 * numpy.complex128(
                        mpmath.meijerg([[1., 1.5, 2.], []], 
                                       [[1.5], []], var1) -
                        mpmath.meijerg([[-0.5, 0., 0.], []], 
                                       [[-0.5, 0.], [-1.]], var2))
            
            # 3D Coulomb potential.
            elif fieldlines == 3:
                
                # If non-periodic.
                if non_periodic:
                    var = -0.25 * period_cutoff**2 * momenta_squared
                    V_nu = numpy.complex128(
                        2 * numpy.pi * period_cutoff * 
                        mpmath.hyp1f2(0.5, 1., 1.5, var))
                    
                    if verbose:
                        print('non-periodic')
                        print('cutoff: {}'.format(period_cutoff))
                
                # If periodic.
                else:
                    V_nu = 2 * numpy.pi / numpy.sqrt(momenta_squared)

            identity_coefficient_nu = float(n_orbitals) / (4. * volume) * V_nu
            z_coefficient_nu = 1. / (4. * volume) * V_nu

            if verbose:
                print('V_nu: {}\n'.format(V_nu))
            
        identity_coefficient -= identity_coefficient_nu
        z_coefficient += z_coefficient_nu

        if verbose:
            print('fieldlines = {}'.format(fieldlines))
            print('identity coefficient: {}'.format(identity_coefficient))
            print('Z coefficient: {}\n'.format(z_coefficient))
            
            
    if spinless:
        identity_coefficient /= 2.
    

    # Add identity term.
    identity_term = QubitOperator((), identity_coefficient)
    hamiltonian += identity_term

    # Add local Z terms.
    for qubit in range(n_qubits):
        qubit_term = QubitOperator(((qubit, 'Z'),), z_coefficient)
        hamiltonian += qubit_term

    #-------------------------------------------------------------------------
    # Add ZZ terms and XZX + YZY terms.
    #-------------------------------------------------------------------------
    zz_prefactor = 0.
    
    # 3D case.
    if grid.dimensions == 3:
        zz_prefactor = numpy.pi / volume        
    
    # 2D case.
    elif grid.dimensions == 2:
        zz_prefactor = 1. / (4. * volume)
        
    xzx_yzy_prefactor = .25 / float(n_orbitals)
    for p in range(n_qubits):
        index_p = grid.grid_indices(p, spinless)
        position_p = grid.position_vector(index_p)
        for q in range(p + 1, n_qubits):
            index_q = grid.grid_indices(q, spinless)
            position_q = grid.position_vector(index_q)

            difference = position_p - position_q

            skip_xzx_yzy = not spinless and (p + q) % 2

            # Loop through momenta.
            zpzq_coefficient = 0.
            term_coefficient = 0.
            for k_indices in grid.all_points_indices():
                momenta = momentum_vectors[k_indices]
                momenta_squared = momenta_squared_dict[k_indices]
                if momenta_squared == 0:
                    continue

                cos_difference = numpy.cos(momenta.dot(difference))
                zpzq_coefficient_nu = 0.

                # 3D case.
                if grid.dimensions == 3:
                    zpzq_coefficient_nu = (zz_prefactor * cos_difference /
                                           momenta_squared)
                    
                    # If non-periodic.
                    if non_periodic:
                        correction = 1.0 - numpy.cos(
                                     period_cutoff * numpy.sqrt(momenta_squared))
                        zpzq_coefficient_nu *= correction

                        if verbose:
                            print('non_periodic')
                            print('cutoff: {}'.format(period_cutoff))
                            print('correction: {}'.format(correction))
                            
                # 2D case.
                elif grid.dimensions == 2:
                    V_nu = 0.
                    
                    # 2D Coulomb potential.
                    if fieldlines == 2:
                        
                        # If non-periodic.
                        if non_periodic:
                            Dkv = period_cutoff * numpy.sqrt(momenta_squared)
                            V_nu = (
                                2. * numpy.pi / momenta_squared * (
                                Dkv * numpy.log(R0 / period_cutoff) * 
                                scipy.special.jv(1, Dkv) - scipy.special.jv(0, Dkv)))
                            
                            if verbose:
                                print('non-periodic')
                                print('cutoff: {}'.format(period_cutoff))
                                print('RO = {}'.format(R0))
                        
                        # If periodic.
                        else:
                            var1 = 4. / momenta_squared
                            var2 = 0.25 * momenta_squared

                            V_nu = 0.5 * numpy.complex128(
                                mpmath.meijerg([[1., 1.5, 2.], []], 
                                               [[1.5], []], var1) -
                                mpmath.meijerg([[-0.5, 0., 0.], []], 
                                               [[-0.5, 0.], [-1.]], var2))
                    
                    # 3D Coulomb potential.
                    elif fieldlines == 3:
                        
                        # If non-periodic.
                        if non_periodic:
                            var = -0.25 * period_cutoff**2 * momenta_squared
                            V_nu = numpy.complex128(
                                2 * numpy.pi * period_cutoff * 
                                mpmath.hyp1f2(0.5, 1., 1.5, var))
                            
                            if verbose:
                                print('non-periodic')
                                print('cutoff: {}'.format(period_cutoff))
                        
                        # If periodic.
                        else:
                            V_nu = 2 * numpy.pi / numpy.sqrt(momenta_squared)
                    
                    zpzq_coefficient_nu = zz_prefactor * cos_difference * V_nu
                            
                zpzq_coefficient += zpzq_coefficient_nu

                if skip_xzx_yzy:
                    continue
                    
                term_coefficient += (xzx_yzy_prefactor * cos_difference *
                                     momenta_squared)

            # Add ZZ term.
            qubit_term = QubitOperator(((p, 'Z'), (q, 'Z')), zpzq_coefficient)
            hamiltonian += qubit_term

            # Add XZX + YZY term.
            if skip_xzx_yzy:
                continue
            z_string = tuple((i, 'Z') for i in range(p + 1, q))
            xzx_operators = ((p, 'X'),) + z_string + ((q, 'X'),)
            yzy_operators = ((p, 'Y'),) + z_string + ((q, 'Y'),)
            hamiltonian += QubitOperator(xzx_operators, term_coefficient)
            hamiltonian += QubitOperator(yzy_operators, term_coefficient)

    # Include the Madelung constant if requested.
    if include_constant:
        # TODO Generalize to other cells
        hamiltonian += (QubitOperator((),) *
                        (2.8372 / grid.volume_scale() ** (1./grid.dimensions)))

    # Return Hamiltonian.
    return hamiltonian
Beispiel #18
0
def dual_basis_jellium_model(grid, spinless=False,
                             kinetic=True, potential=True,
                             include_constant=False,
                             non_periodic=False, period_cutoff=None, 
                             fieldlines=3, R0=1e8, verbose=False):
    """Return jellium Hamiltonian in the dual basis of arXiv:1706.00023

    Args:
        grid (Grid): The discretization to use.
        spinless (bool): Whether to use the spinless model or not.
        kinetic (bool): Whether to include kinetic terms.
        potential (bool): Whether to include potential terms.
        include_constant (bool): Whether to include the Madelung constant.
            Note constant is unsupported for non-uniform, non-cubic cells with
            ions.
        non_periodic (bool): If the system is non-periodic, default to False.
        period_cutoff (float): Period cutoff, default to
            grid.volume_scale() ** (1. / grid.dimensions).
        fieldlines (int): Spatial dimension for electric field lines.
        R0 (float): Reference length scale where the 2D Coulomb potential 
            is zero.
        verbose (bool): Whether to turn on print statements.  

    Returns:
        operator (FermionOperator)
    """
    if potential == True and grid.dimensions == 1:
        raise ValueError('System dimension cannot be 1.')
        
    # Initialize.
    n_points = grid.num_points
    position_prefactor = 0.
    
    # 3D case.
    if grid.dimensions == 3:
        position_prefactor = 2.0 * numpy.pi / grid.volume_scale()
    
    # 2D case.
    elif grid.dimensions == 2:
        position_prefactor = 1. / (2. * grid.volume_scale())
        
    
    operator = FermionOperator()
    spins = [None] if spinless else [0, 1]
    
    
    if potential and non_periodic and period_cutoff is None:
        period_cutoff = grid.volume_scale() ** (1.0 / grid.dimensions)

    # Pre-Computations.
    position_vectors = {}
    momentum_vectors = {}
    momenta_squared_dict = {}
    orbital_ids = {}
    
    for indices in grid.all_points_indices():
        # Store position vectors in dictionary, with corresponding 
        # grid index as key.
        position_vectors[indices] = grid.position_vector(indices)
        
        # Get and store momentum vectors in dictionary, with corresponding 
        # grid index as key.
        momenta = grid.momentum_vector(indices)
        momentum_vectors[indices] = momenta
        
        # Store momentum squared in dictionary, with corresponding 
        # grid index as key.
        momenta_squared_dict[indices] = momenta.dot(momenta)
        
        # Store spin orbitals at each grid index in dictionary.
        orbital_ids[indices] = {}
        
        for spin in spins:
            orbital_ids[indices][spin] = grid.orbital_id(indices, spin)

    # This gives the position vector of the grid point at bottom-left-most 
    # corner. 
    #
    #                x---x---x
    #                |   |   |
    #                x---x---x
    #                |   |   |
    # this point <-- x---x---x
    #
    grid_origin = (0, ) * grid.dimensions
    coordinates_origin = position_vectors[grid_origin]
        
    # Loop once through all grid points.
    for grid_indices_b in grid.all_points_indices():
        if verbose:
            print('Grid point: {}\n'.format(grid_indices_b))
        
        # For all grid points, 'differences' gets the position displacement 
        # from the 'origin' point. This corresponds to evaluating 
        # (r_p - r_q) == r_(p-q).
        coordinates_b = position_vectors[grid_indices_b]
        differences = coordinates_b - coordinates_origin
        
        # Compute coefficients.
        kinetic_coefficient = 0.
        potential_coefficient = 0.
        
        # Loop once through all momentum indices, k_nu.
        for momenta_indices in grid.all_points_indices():
            momenta = momentum_vectors[momenta_indices]
            momenta_squared = momenta_squared_dict[momenta_indices]
            
            if momenta_squared == 0:
                continue

            cos_difference = numpy.cos(momenta.dot(differences))
            
            # This computes 1/(2N) * sum_nu{ k_nu^2 * cos[k_nu * r_(q-p)] }
            if kinetic:
                if verbose:
                    print('Added kinetic term.')
                
                kinetic_coefficient += (
                    cos_difference * momenta_squared /
                    (2. * float(n_points)))
            
            if verbose:
                print('Potential = {}'.format(potential))
                
            # This computes 2pi/Omega * sum_nu{ cos[k_nu * r_(p-q)] / k_nu^2 }
            if potential: 
                
                # Potential coefficient for this value of nu.
                potential_coefficient_nu = 0.
                
                # 3D case.
                if grid.dimensions == 3:
                    potential_coefficient_nu = (
                        position_prefactor * cos_difference / momenta_squared)
                    
                    # If non-periodic.
                    if non_periodic:
                        correction = 1.0 - numpy.cos(
                                     period_cutoff * numpy.sqrt(momenta_squared))
                        potential_coefficient_nu *= correction

                        if verbose:
                            print('non_periodic')
                            print('cutoff: {}'.format(period_cutoff))
                            print('correction: {}\n'.format(correction))
                            
                
                # 2D case.
                elif grid.dimensions == 2:
                    V_nu = 0.
                    
                    # 2D Coulomb potential.
                    if fieldlines == 2:
                        
                        # If non-periodic.
                        if non_periodic:
                            Dkv = period_cutoff * numpy.sqrt(momenta_squared)
                            V_nu = (
                                2. * numpy.pi / momenta_squared * (
                                Dkv * numpy.log(R0 / period_cutoff) * 
                                scipy.special.jv(1, Dkv) - scipy.special.jv(0, Dkv)))
                            
                            if verbose:
                                print('non-periodic')
                                print('cutoff: {}\n'.format(period_cutoff))
                                print('RO = {}'.format(R0))
                        
                        # If periodic.
                        else:
                            var1 = 4. / momenta_squared
                            var2 = 0.25 * momenta_squared

                            V_nu = 0.5 * numpy.complex128(
                                mpmath.meijerg([[1., 1.5, 2.], []], 
                                               [[1.5], []], var1) -
                                mpmath.meijerg([[-0.5, 0., 0.], []], 
                                               [[-0.5, 0.], [-1.]], var2))
                            
                    # 3D Coulomb potential.
                    elif fieldlines == 3:
                        
                        # If non-periodic.
                        if non_periodic:
                            var = -0.25 * period_cutoff**2 * momenta_squared
                            V_nu = numpy.complex128(
                                2 * numpy.pi * period_cutoff * 
                                mpmath.hyp1f2(0.5, 1., 1.5, var))
                            
                            if verbose:
                                print('non-periodic')
                                print('cutoff: {}\n'.format(period_cutoff))
                        
                        # If periodic.
                        else:    
                            V_nu = 2. * numpy.pi / numpy.sqrt(momenta_squared)
                            
                    # Potential coefficient for this value of nu.
                    potential_coefficient_nu = (
                        position_prefactor * V_nu * cos_difference)
                
                potential_coefficient += potential_coefficient_nu
                    
                if verbose:
                    print('fieldlines = {}'.format(fieldlines))
                    print('potential coefficient nu: {}\n'.format(potential_coefficient_nu))
                        
        
        if verbose:
            print('kinetic coefficient: {}'.format(kinetic_coefficient))
            print('potential coefficient: {}\n'.format(potential_coefficient))
        
        # Loop once through all grid points. 
        # We have r_p - r_q fixed by 'differences' computed above. 
        for grid_indices_shift in grid.all_points_indices():
            # Loop over spins and identify interacting orbitals.
            orbital_a = {}
            orbital_b = {}
            
            # grid_origin = (0, ) * grid.dimensions
            # 'shifted_index_1' is equivalent to just 'grid_indices_shift'.
            shifted_index_1 = tuple(
                [(grid_origin[i] + grid_indices_shift[i]) % grid.length[i]
                 for i in range(grid.dimensions)])
            
            # 'shifted_index_2' 
            shifted_index_2 = tuple(
                [(grid_indices_b[i] + grid_indices_shift[i]) % grid.length[i]
                 for i in range(grid.dimensions)])
            
            if verbose:
                print('shifted index 1: {}'.format(shifted_index_1))
                print('shifted index 2: {}'.format(shifted_index_2))
            
            for spin in spins:
                orbital_a[spin] = orbital_ids[shifted_index_1][spin]
                orbital_b[spin] = orbital_ids[shifted_index_2][spin]
                
            if kinetic:
                for spin in spins:
                    operators = ((orbital_a[spin], 1), (orbital_b[spin], 0))
                    operator += FermionOperator(operators, kinetic_coefficient)
                     
            if potential:
                for sa in spins:
                    for sb in spins:
                        if orbital_a[sa] == orbital_b[sb]:
                            continue
                            
                        operators = ((orbital_a[sa], 1), (orbital_a[sa], 0),
                                     (orbital_b[sb], 1), (orbital_b[sb], 0))
                        operator += FermionOperator(operators,
                                                    potential_coefficient)
        
        
    # Include the Madelung constant if requested.
    if include_constant:
        
        # TODO: Check for other unit cell shapes
        # Currently only for cubic cells.
        operator += (FermionOperator.identity() *
                     (2.8372 / grid.volume_scale()**(1./grid.dimensions)))
    
    # Return.
    return operator
Beispiel #19
0
def FourierF(k):
    return sqrt(2 / pi) * special.kv(0, abs(k))


def FourierIntegral(k):
    return sqrt(pi / 2) * (1 / k - special.kv(0, k) * special.modstruve(-1, k)
                           - special.kv(0, k) * special.modstruve(0, k))


interpolation_NUM = 1000

interpolation_points_x = np.logspace(-10, 1, interpolation_NUM)
interpolation_points_y = map(
    lambda k: 1 / sqrt(4 * pi) * (5.568327996831708 - float(
        meijerg([[1], [1]], [[1 / 2, 1 / 2, 1 / 2], [0]], k, 1 / 2))) / k,
    interpolation_points_x)
interpolated_function = interpolate.interp1d(interpolation_points_x,
                                             interpolation_points_y,
                                             fill_value='extrapolate')


def SqFourierIntegral(k):
    if (k < 10):
        return interpolated_function(k)
    else:
        return 0


#from matplotlib import pyplot as plt
#plt.loglog(interpolation_points_x, interpolation_points_y)
Beispiel #20
0
 def lum(rr):
     if np.iterable(rr): return np.array([lum(r) for r in rr])
     ss = rr / reff
     zz = (bb / (2 * mm))**(2 * mm) * ss**2
     return (factor / ss) * mpmath.meijerg(avect, bvect, zz)
Beispiel #21
0
 def luminosity(rr):
     if np.iterable(rr): return np.array([luminosity(r) for r in rr])
     ss = rr / reff
     zz = (bb / (2 * pp))**(2 * pp) * ss**(2 * qq)
     return lum * ((factor / ss) * mpmath.meijerg(avect, bvect, zz))
Beispiel #22
0
 def luminosity(rr):
     if np.iterable(rr): return np.array([luminosity(r) for r in rr])
     ss = rr/reff
     zz = (bb/(2*pp))**(2*pp) * ss**(2*qq)
     return lum*((factor/ss)*mpmath.meijerg(avect, bvect, zz))
Beispiel #23
0
def analytic_solve(params, T, xs):
    # Use meijer-G function to calculate subdiffusion for alpha = 1/2
    import mpmath

    D_alpha = params[0]
    
    integrand = lambda u: 1. / math.sqrt(8 * pow(math.pi,3) * D_alpha * math.sqrt(T)) * float(mpmath.meijerg([[],[]], [[0, 0.25, 0.5],[]], pow(u,4) / (256. * D_alpha * D_alpha * T)))

    return np.vectorize(lambda x: integrand(x))(xs) #1.0 - 2.0 * np.vectorize(lambda x: scipy.integrate.quad(integrand, 0., x)[0])(xs)