예제 #1
0
 def test_properties(self):
     g = Grid(dimensions=2, length=3, scale=5.0)
     self.assertEqual(g.num_points, 9)
     self.assertEqual(g.volume_scale(), 25)
     self.assertEqual(list(g.all_points_indices()), [
         (0, 0),
         (0, 1),
         (0, 2),
         (1, 0),
         (1, 1),
         (1, 2),
         (2, 0),
         (2, 1),
         (2, 2),
     ])
예제 #2
0
    def test_coefficients(self):
        # Test that the coefficients post-JW transform are as claimed in paper.
        grid = Grid(dimensions=2, length=3, scale=2.)
        spinless = 1
        n_orbitals = grid.num_points
        n_qubits = (2**(1 - spinless)) * n_orbitals
        volume = grid.volume_scale()

        # Kinetic operator.
        kinetic = dual_basis_kinetic(grid, spinless)
        qubit_kinetic = jordan_wigner(kinetic)

        # Potential operator.
        potential = dual_basis_potential(grid, spinless)
        qubit_potential = jordan_wigner(potential)

        # Check identity.
        identity = tuple()
        kinetic_coefficient = qubit_kinetic.terms[identity]
        potential_coefficient = qubit_potential.terms[identity]

        paper_kinetic_coefficient = 0.
        paper_potential_coefficient = 0.
        for indices in grid.all_points_indices():
            momenta = grid.momentum_vector(indices)
            paper_kinetic_coefficient += float(n_qubits) * momenta.dot(
                momenta) / float(4. * n_orbitals)

            if momenta.any():
                potential_contribution = -numpy.pi * float(n_qubits) / float(
                    2. * momenta.dot(momenta) * volume)
                paper_potential_coefficient += potential_contribution

        self.assertAlmostEqual(kinetic_coefficient, paper_kinetic_coefficient)
        self.assertAlmostEqual(potential_coefficient,
                               paper_potential_coefficient)

        # Check Zp.
        for p in range(n_qubits):
            zp = ((p, 'Z'), )
            kinetic_coefficient = qubit_kinetic.terms[zp]
            potential_coefficient = qubit_potential.terms[zp]

            paper_kinetic_coefficient = 0.
            paper_potential_coefficient = 0.
            for indices in grid.all_points_indices():
                momenta = grid.momentum_vector(indices)
                paper_kinetic_coefficient -= momenta.dot(momenta) / float(
                    4. * n_orbitals)

                if momenta.any():
                    potential_contribution = numpy.pi / float(
                        momenta.dot(momenta) * volume)
                    paper_potential_coefficient += potential_contribution

            self.assertAlmostEqual(kinetic_coefficient,
                                   paper_kinetic_coefficient)
            self.assertAlmostEqual(potential_coefficient,
                                   paper_potential_coefficient)

        # Check Zp Zq.
        if spinless:
            spins = [None]

        for indices_a in grid.all_points_indices():
            for indices_b in grid.all_points_indices():

                potential_coefficient = 0.
                paper_kinetic_coefficient = 0.
                paper_potential_coefficient = 0.

                position_a = grid.position_vector(indices_a)
                position_b = grid.position_vector(indices_b)
                differences = position_b - position_a

                for spin_a in spins:
                    for spin_b in spins:

                        p = grid.orbital_id(indices_a, spin_a)
                        q = grid.orbital_id(indices_b, spin_b)

                        if p == q:
                            continue

                        zpzq = ((min(p, q), 'Z'), (max(p, q), 'Z'))
                        if zpzq in qubit_potential.terms:
                            potential_coefficient = qubit_potential.terms[zpzq]

                        for indices_c in grid.all_points_indices():
                            momenta = grid.momentum_vector(indices_c)

                            if momenta.any():
                                potential_contribution = numpy.pi * numpy.cos(
                                    differences.dot(momenta)) / float(
                                        momenta.dot(momenta) * volume)
                                paper_potential_coefficient += (
                                    potential_contribution)

                        self.assertAlmostEqual(potential_coefficient,
                                               paper_potential_coefficient)
예제 #3
0
    def test_coefficients(self):
        # Test that the coefficients post-JW transform are as claimed in paper.
        spinless = True
        non_periodics = [False, True]

        # [[spatial dimension, fieldline dimension]].
        dims = [[2, 2], [2, 3], [3, 3]]

        # Reference length scale where the 2D Coulomb potential is zero.
        R0 = 1e8

        for dim in dims:

            # If dim[0] == 2, get range(2, 4).
            # If dim[0] == 3, get range(2, 3).
            for length in range(2, 6 - dim[0]):
                for non_periodic in non_periodics:
                    grid = Grid(dimensions=dim[0], length=length, scale=2.)
                    n_orbitals = grid.num_points
                    n_qubits = (2**(1 - spinless)) * n_orbitals
                    volume = grid.volume_scale()
                    period_cutoff = None

                    if non_periodic:
                        period_cutoff = volume**(1. / grid.dimensions)

                    fieldlines = dim[1]

                    # Kinetic operator.
                    kinetic = dual_basis_kinetic(grid, spinless)
                    qubit_kinetic = jordan_wigner(kinetic)

                    # Potential operator.
                    potential = dual_basis_potential(
                        grid,
                        spinless,
                        non_periodic=non_periodic,
                        period_cutoff=period_cutoff,
                        fieldlines=fieldlines)
                    qubit_potential = jordan_wigner(potential)

                    # Check identity.
                    identity = tuple()
                    kinetic_coefficient = qubit_kinetic.terms[identity]
                    potential_coefficient = qubit_potential.terms[identity]

                    paper_kinetic_coefficient = 0.
                    paper_potential_coefficient = 0.
                    for indices in grid.all_points_indices():
                        momenta = grid.momentum_vector(indices)
                        momenta_squared = momenta.dot(momenta)
                        paper_kinetic_coefficient += (float(n_qubits) *
                                                      momenta_squared /
                                                      float(4. * n_orbitals))

                        if momenta.any():
                            potential_contribution = 0.

                            # 3D case.
                            if grid.dimensions == 3:
                                potential_contribution = -(
                                    numpy.pi * float(n_qubits) /
                                    float(2. * momenta_squared * volume))

                                # If non-periodic.
                                if non_periodic:
                                    correction = 1.0 - numpy.cos(
                                        period_cutoff *
                                        numpy.sqrt(momenta_squared))
                                    potential_contribution *= 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 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 periodic.
                                    else:
                                        V_nu = (2 * numpy.pi /
                                                numpy.sqrt(momenta_squared))

                                potential_contribution = (-float(n_qubits) /
                                                          (8. * volume) * V_nu)

                            paper_potential_coefficient += potential_contribution

                    # Check if coefficients are equal.
                    self.assertAlmostEqual(kinetic_coefficient,
                                           paper_kinetic_coefficient)
                    self.assertAlmostEqual(potential_coefficient,
                                           paper_potential_coefficient)

                    # Check Zp.
                    for p in range(n_qubits):
                        zp = ((p, 'Z'), )
                        kinetic_coefficient = qubit_kinetic.terms[zp]
                        potential_coefficient = qubit_potential.terms[zp]

                        paper_kinetic_coefficient = 0.
                        paper_potential_coefficient = 0.
                        for indices in grid.all_points_indices():
                            momenta = grid.momentum_vector(indices)
                            momenta_squared = momenta.dot(momenta)
                            paper_kinetic_coefficient -= (
                                momenta_squared / float(4. * n_orbitals))

                            if momenta.any():
                                potential_contribution = 0.

                                # 3D case.
                                if grid.dimensions == 3:
                                    potential_contribution = (
                                        numpy.pi /
                                        float(momenta_squared * volume))

                                    # If non-periodic.
                                    if non_periodic:
                                        correction = 1.0 - numpy.cos(
                                            period_cutoff *
                                            numpy.sqrt(momenta_squared))
                                        potential_contribution *= 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 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 periodic.
                                        else:
                                            V_nu = (
                                                2 * numpy.pi /
                                                numpy.sqrt(momenta_squared))

                                    potential_contribution = (1. /
                                                              (4. * volume) *
                                                              V_nu)

                                paper_potential_coefficient += potential_contribution

                        # Check if coefficients are equal.
                        self.assertAlmostEqual(kinetic_coefficient,
                                               paper_kinetic_coefficient)
                        self.assertAlmostEqual(potential_coefficient,
                                               paper_potential_coefficient)

                    # Check Zp Zq.
                    if spinless:
                        spins = [None]

                    for indices_a in grid.all_points_indices():
                        for indices_b in grid.all_points_indices():

                            potential_coefficient = 0.
                            paper_kinetic_coefficient = 0.
                            paper_potential_coefficient = 0.

                            position_a = grid.position_vector(indices_a)
                            position_b = grid.position_vector(indices_b)
                            differences = position_b - position_a

                            for spin_a in spins:
                                for spin_b in spins:

                                    p = grid.orbital_id(indices_a, spin_a)
                                    q = grid.orbital_id(indices_b, spin_b)

                                    if p == q:
                                        continue

                                    zpzq = ((min(p, q), 'Z'), (max(p, q), 'Z'))
                                    if zpzq in qubit_potential.terms:
                                        potential_coefficient = qubit_potential.terms[
                                            zpzq]

                                    for indices_c in grid.all_points_indices():
                                        momenta = grid.momentum_vector(
                                            indices_c)
                                        momenta_squared = momenta.dot(momenta)

                                        if momenta.any():
                                            potential_contribution = 0.

                                            # 3D case.
                                            if grid.dimensions == 3:
                                                potential_contribution = (
                                                    numpy.pi * numpy.cos(
                                                        differences.dot(
                                                            momenta)) /
                                                    float(momenta_squared *
                                                          volume))

                                                # If non-periodic.
                                                if non_periodic:
                                                    correction = 1.0 - numpy.cos(
                                                        period_cutoff * numpy.
                                                        sqrt(momenta_squared))
                                                    potential_contribution *= 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 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 periodic.
                                                    else:
                                                        V_nu = 2 * numpy.pi / numpy.sqrt(
                                                            momenta_squared)

                                                potential_contribution = (
                                                    numpy.cos(
                                                        differences.dot(
                                                            momenta)) /
                                                    (4. * volume) * V_nu)

                                            paper_potential_coefficient += potential_contribution

                                    # Check if coefficients are equal.
                                    self.assertAlmostEqual(
                                        potential_coefficient,
                                        paper_potential_coefficient)