Пример #1
0
def _fourier_transform_helper(hamiltonian, grid, spinless, phase_factor,
                              vec_func_1, vec_func_2):
    hamiltonian_t = FermionOperator.zero()
    normalize_factor = numpy.sqrt(1.0 / float(grid.num_points()))

    for term in hamiltonian.terms:
        transformed_term = FermionOperator.identity()
        for ladder_op_mode, ladder_op_type in term:
            indices_1 = grid_indices(ladder_op_mode, grid, spinless)
            vec1 = vec_func_1(indices_1, grid)
            new_basis = FermionOperator.zero()
            for indices_2 in grid.all_points_indices():
                vec2 = vec_func_2(indices_2, grid)
                spin = None if spinless else ladder_op_mode % 2
                orbital = orbital_id(grid, indices_2, spin)
                exp_index = phase_factor * 1.0j * numpy.dot(vec1, vec2)
                if ladder_op_type == 1:
                    exp_index *= -1.0

                element = FermionOperator(((orbital, ladder_op_type), ),
                                          numpy.exp(exp_index))
                new_basis += element

            new_basis *= normalize_factor
            transformed_term *= new_basis

        # Coefficient.
        transformed_term *= hamiltonian.terms[term]

        hamiltonian_t += transformed_term

    return hamiltonian_t
Пример #2
0
def jellium_model(grid,
                  spinless=False,
                  plane_wave=True,
                  include_constant=False,
                  e_cutoff=None):
    """Return jellium Hamiltonian as FermionOperator class.

    Args:
        grid (openfermion.utils.Grid): The discretization to use.
        spinless (bool): Whether to use the spinless model or not.
        plane_wave (bool): Whether to return in momentum space (True)
            or position space (False).
        include_constant (bool): Whether to include the Madelung constant.
            Note constant is unsupported for non-uniform, non-cubic cells with
            ions.
        e_cutoff (float): Energy cutoff.

    Returns:
        FermionOperator: The Hamiltonian of the model.
    """
    if plane_wave:
        hamiltonian = plane_wave_kinetic(grid, spinless, e_cutoff)
        hamiltonian += plane_wave_potential(grid, spinless, e_cutoff)
    else:
        hamiltonian = dual_basis_jellium_model(grid, spinless)
    # Include the Madelung constant if requested.
    if include_constant:
        # TODO: Check for other unit cell shapes
        hamiltonian += (FermionOperator.identity() *
                        (2.8372 / grid.volume_scale()**(1. / grid.dimensions)))
    return hamiltonian
Пример #3
0
    def test_commutes_identity(self):
        com = commutator(FermionOperator.identity(),
                         FermionOperator('2^ 3', 2.3))
        self.assertEqual(com, FermionOperator.zero())

        com = commutator(BosonOperator.identity(), BosonOperator('2^ 3', 2.3))
        self.assertTrue(com == BosonOperator.zero())

        com = commutator(QuadOperator.identity(), QuadOperator('q2 p3', 2.3))
        self.assertTrue(com == QuadOperator.zero())
Пример #4
0
    def test_jordan_wigner_dual_basis_jellium_constant_shift(self):
        length_scale = 0.6
        grid = Grid(dimensions=2, length=3, scale=length_scale)
        spinless = True

        hamiltonian_without_constant = jordan_wigner_dual_basis_jellium(
            grid, spinless, include_constant=False)
        hamiltonian_with_constant = jordan_wigner_dual_basis_jellium(
            grid, spinless, include_constant=True)

        difference = hamiltonian_with_constant - hamiltonian_without_constant
        expected = FermionOperator.identity() * (2.8372 / length_scale)

        self.assertTrue(expected.isclose(difference))
Пример #5
0
    def test_canonical_anticommutation_relations(self):
        op_1 = FermionOperator('3')
        op_1_dag = FermionOperator('3^')
        op_2 = FermionOperator('4')
        op_2_dag = FermionOperator('4^')
        zero = FermionOperator.zero()
        one = FermionOperator.identity()

        self.assertEqual(one, normal_ordered(anticommutator(op_1, op_1_dag)))
        self.assertEqual(zero, normal_ordered(anticommutator(op_1, op_2)))
        self.assertEqual(zero, normal_ordered(anticommutator(op_1, op_2_dag)))
        self.assertEqual(zero, normal_ordered(anticommutator(op_1_dag, op_2)))
        self.assertEqual(zero,
                         normal_ordered(anticommutator(op_1_dag, op_2_dag)))
        self.assertEqual(one, normal_ordered(anticommutator(op_2, op_2_dag)))
Пример #6
0
def jellium_model(grid, spinless=False, plane_wave=True,
                  include_constant=False, e_cutoff=None,
                  non_periodic=False, period_cutoff=None, 
                  fieldlines=3, R0=1e8, verbose=False):
    """Return jellium Hamiltonian as FermionOperator class.

    Args:
        grid (openfermion.utils.Grid): The discretization to use.
        spinless (bool): Whether to use the spinless model or not.
        plane_wave (bool): Whether to return in momentum space (True)
            or position space (False).
        include_constant (bool): Whether to include the Madelung constant.
            Note constant is unsupported for non-uniform, non-cubic cells with
            ions.
        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:
        FermionOperator: The Hamiltonian of the model.
    """
    if grid.dimensions == 1:
        raise ValueError('System dimension cannot be 1.')
        
    if plane_wave:
        hamiltonian = plane_wave_kinetic(grid, spinless, e_cutoff)
        hamiltonian += plane_wave_potential(
            grid, spinless, e_cutoff, non_periodic, period_cutoff, fieldlines, R0, verbose)
    
    else:
        hamiltonian = dual_basis_jellium_model(
            grid, spinless, True, True, include_constant, non_periodic,
            period_cutoff, fieldlines, R0, verbose)
        
    # Include the Madelung constant if requested.
    if include_constant:
        # TODO: Check for other unit cell shapes
        hamiltonian += (FermionOperator.identity() *
                        (2.8372 / grid.volume_scale()**(1. / grid.dimensions)))
    return hamiltonian
Пример #7
0
def jellium_model(grid, spinless=False, plane_wave=True,
                  include_constant=False):
    """Return jellium Hamiltonian as FermionOperator class.

    Args:
        grid (openfermion.utils.Grid): The discretization to use.
        spinless (bool): Whether to use the spinless model or not.
        plane_wave (bool): Whether to return in momentum space (True)
            or position space (False).
        include_constant (bool): Whether to include the Madelung constant.

    Returns:
        FermionOperator: The Hamiltonian of the model.
    """
    if plane_wave:
        hamiltonian = plane_wave_kinetic(grid, spinless)
        hamiltonian += plane_wave_potential(grid, spinless)
    else:
        hamiltonian = dual_basis_jellium_model(grid, spinless)
    # Include the Madelung constant if requested.
    if include_constant:
        hamiltonian += FermionOperator.identity() * (2.8372 / grid.scale)
    return hamiltonian
Пример #8
0
def dual_basis_jellium_model(grid,
                             spinless=False,
                             kinetic=True,
                             potential=True,
                             include_constant=False,
                             non_periodic=False,
                             period_cutoff=None):
    """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).

    Returns:
        operator (FermionOperator)
    """
    # Initialize.
    n_points = grid.num_points
    position_prefactor = 2.0 * numpy.pi / 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():
        position_vectors[indices] = grid.position_vector(indices)
        momenta = grid.momentum_vector(indices)
        momentum_vectors[indices] = momenta
        momenta_squared_dict[indices] = momenta.dot(momenta)
        orbital_ids[indices] = {}
        for spin in spins:
            orbital_ids[indices][spin] = grid.orbital_id(indices, spin)

    # Loop once through all lattice sites.
    grid_origin = (0, ) * grid.dimensions
    coordinates_origin = position_vectors[grid_origin]
    for grid_indices_b in grid.all_points_indices():
        coordinates_b = position_vectors[grid_indices_b]
        differences = coordinates_b - coordinates_origin

        # Compute coefficients.
        kinetic_coefficient = 0.
        potential_coefficient = 0.
        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))
            if kinetic:
                kinetic_coefficient += (cos_difference * momenta_squared /
                                        (2. * float(n_points)))
            if potential:
                potential_coefficient += (position_prefactor * cos_difference /
                                          momenta_squared)
        for grid_indices_shift in grid.all_points_indices():
            # Loop over spins and identify interacting orbitals.
            orbital_a = {}
            orbital_b = {}
            shifted_index_1 = tuple([
                (grid_origin[i] + grid_indices_shift[i]) % grid.length[i]
                for i in range(grid.dimensions)
            ])
            shifted_index_2 = tuple([
                (grid_indices_b[i] + grid_indices_shift[i]) % grid.length[i]
                for i in range(grid.dimensions)
            ])

            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
        operator += (FermionOperator.identity() *
                     (2.8372 / grid.volume_scale()**(1. / grid.dimensions)))

    # Return.
    return operator
Пример #9
0
    def test_expectation_state_is_list_identity_fermion_operator(self):
        operator = FermionOperator.identity() * 1.1
        state = [0, 1, 1]

        self.assertAlmostEqual(
            expectation_computational_basis_state(operator, state), 1.1)
Пример #10
0
    def test_expectation_identity_fermion_operator(self):
        operator = FermionOperator.identity() * 1.1
        state = csc_matrix(([1], ([6], [0])), shape=(16, 1))

        self.assertAlmostEqual(
            expectation_computational_basis_state(operator, state), 1.1)
Пример #11
0
 def test_commutes_identity(self):
     com = commutator(FermionOperator.identity(),
                      FermionOperator('2^ 3', 2.3))
     self.assertTrue(com.isclose(FermionOperator.zero()))
Пример #12
0
def hartree_fock_state_jellium(grid,
                               n_electrons,
                               spinless=True,
                               plane_wave=False):
    """Give the Hartree-Fock state of jellium.

    Args:
        grid (Grid): The discretization to use.
        n_electrons (int): Number of electrons in the system.
        spinless (bool): Whether to use the spinless model or not.
        plane_wave (bool): Whether to return the Hartree-Fock state in
                           the plane wave (True) or dual basis (False).

    Notes:
        The jellium model is built up by filling the lowest-energy
        single-particle states in the plane-wave Hamiltonian until
        n_electrons states are filled.
    """
    from openfermion.hamiltonians import plane_wave_kinetic
    # Get the jellium Hamiltonian in the plane wave basis.
    # For determining the Hartree-Fock state in the PW basis, only the
    # kinetic energy terms matter.
    hamiltonian = plane_wave_kinetic(grid, spinless=spinless)
    hamiltonian = normal_ordered(hamiltonian)
    hamiltonian.compress()

    # The number of occupied single-particle states is the number of electrons.
    # Those states with the lowest single-particle energies are occupied first.
    occupied_states = lowest_single_particle_energy_states(
        hamiltonian, n_electrons)
    occupied_states = numpy.array(occupied_states)

    if plane_wave:
        # In the plane wave basis the HF state is a single determinant.
        hartree_fock_state_index = numpy.sum(2**occupied_states)
        hartree_fock_state = numpy.zeros(2**count_qubits(hamiltonian),
                                         dtype=complex)
        hartree_fock_state[hartree_fock_state_index] = 1.0

    else:
        # Inverse Fourier transform the creation operators for the state to get
        # to the dual basis state, then use that to get the dual basis state.
        hartree_fock_state_creation_operator = FermionOperator.identity()
        for state in occupied_states[::-1]:
            hartree_fock_state_creation_operator *= (FermionOperator(
                ((int(state), 1), )))
        dual_basis_hf_creation_operator = inverse_fourier_transform(
            hartree_fock_state_creation_operator, grid, spinless)

        dual_basis_hf_creation = normal_ordered(
            dual_basis_hf_creation_operator)

        # Initialize the HF state.
        hartree_fock_state = numpy.zeros(2**count_qubits(hamiltonian),
                                         dtype=complex)

        # Populate the elements of the HF state in the dual basis.
        for term in dual_basis_hf_creation.terms:
            index = 0
            for operator in term:
                index += 2**operator[0]
            hartree_fock_state[index] = dual_basis_hf_creation.terms[term]

    return hartree_fock_state
Пример #13
0
def dual_basis_jellium_model(grid, spinless=False,
                             kinetic=True, potential=True,
                             include_constant=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.

    Returns:
        operator (FermionOperator)
    """
    # Initialize.
    n_points = grid.num_points()
    position_prefactor = 2. * numpy.pi / grid.volume_scale()
    operator = FermionOperator()
    spins = [None] if spinless else [0, 1]

    # Pre-Computations.
    position_vectors = {}
    momentum_vectors = {}
    momenta_squared_dict = {}
    orbital_ids = {}
    for indices in grid.all_points_indices():
        position_vectors[indices] = position_vector(indices, grid)
        momenta = momentum_vector(indices, grid)
        momentum_vectors[indices] = momenta
        momenta_squared_dict[indices] = momenta.dot(momenta)
        orbital_ids[indices] = {}
        for spin in spins:
            orbital_ids[indices][spin] = orbital_id(grid, indices, spin)

    # Loop once through all lattice sites.
    for grid_indices_a in grid.all_points_indices():
        coordinates_a = position_vectors[grid_indices_a]
        for grid_indices_b in grid.all_points_indices():
            coordinates_b = position_vectors[grid_indices_b]
            differences = coordinates_b - coordinates_a

            # Compute coefficients.
            kinetic_coefficient = 0.
            potential_coefficient = 0.
            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))
                if kinetic:
                    kinetic_coefficient += (
                        cos_difference * momenta_squared /
                        (2. * float(n_points)))
                if potential:
                    potential_coefficient += (
                        position_prefactor * cos_difference / momenta_squared)

            # Loop over spins and identify interacting orbitals.
            orbital_a = {}
            orbital_b = {}
            for spin in spins:
                orbital_a[spin] = orbital_ids[grid_indices_a][spin]
                orbital_b[spin] = orbital_ids[grid_indices_b][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:
        operator += FermionOperator.identity() * (2.8372 / grid.scale)

    # Return.
    return operator
Пример #14
0
 def test_commutes_identity(self):
     com = commutator(FermionOperator.identity(),
                      FermionOperator('2^ 3', 2.3))
     self.assertEqual(com, FermionOperator.zero())
Пример #15
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