Spinization of the Hamiltonian
We need to implement the conversion of Hamiltonian from spatial orbital basis to spin-resolved basis.
Technical Details:
The conversion rules for one-body terms are:
- $h_{pq}^{αα} = h_{pq}^{ββ} = h_{pq}^{spatial}$
- $h_{pq}^{αβ} = h_{pq}^{βα} = 0$
For two-body terms:
- $V_{pqrs}^{αααα} = V_{pqrs}^{ββββ} = V_{pqrs}^{αβαβ} = V_{pqrs}^{βαβα} = V_{pqrs}^{spatial}$
Code Structure: Implementing MolHam Class
Overview
Create a new Python module molkit to handle molecular Hamiltonian operations with a focus on spin-orbital conversions.
Class Structure
class MolHam:
def __init__(self, one_body, two_body):
"""
Initialize MolHam with one and two electron integrals.
Parameters
----------
one_body : np.ndarray
One-electron integrals in spatial orbital basis
two_body : np.ndarray
Two-electron integrals in spatial orbital basis
"""
self.one_body = one_body
self.two_body = two_body
self.n_spatial = one_body.shape[0]
self.n_spin = 2 * self.n_spatial
self.reduced_ham = None
def spinize(self):
"""Convert spatial orbital Hamiltonian to spin-orbital basis"""
pass
def antisymmetrize(self):
"""Apply proper antisymmetrization to two-electron integrals"""
pass
def get_spin_blocks(self):
"""Extract different spin blocks from the Hamiltonian"""
pass
def build_reduced(self):
"""Build the reduced hamiltonian form"""
Implementation Tasks
- [ ] Create basic module structure and class scaffold
- [ ] Implement spinize() method with proper handling of one and two-electron terms
- [ ] Add antisymmetrization functionality
- [ ] Create comprehensive test suite
- [ ] Add validation methods for integral properties
- [ ] Build tensor that corresponds to reduced hamiltonian
Directory Structure
molkit/
├── __init__.py
├── hamiltonian.py # Contains MolHam class
├── utils/
│ ├── __init__.py
│ ├── spinops.py # Spin operation utilities such as antisymmetrization
└── tests/
├── __init__.py
├── test_hamiltonian.py
└── test_spinops.py
Expected Methods
- spinize(): Convert spatial to spin-orbital basis
- antisymmetrize(): Handle proper antisymmetrization
- validate_integrals(): Check integral properties and symmetries
- get_blocks(): Extract specific spin blocks
@PaulWAyers can you double check that the conversion makes sense (technical details part) assuming we work with physics notations?
One has to be a bit careful for the 2-body terms. Often V_{pqrs} in terms of spin are the antisymmetrized integrals, while the spatial ones are usually not antisymmetrized. That's the thing I see. In that case, $V_{pqrs}^{\alpha \alpha \alpha \alpha} \ne V_{pqrs}^{\alpha \beta \alpha \beta}$ because the "antisymmetrization" part of the integral vanishes for the second piece but not the first piece. In that case the "spatial integral" would be $V_{pqrs}^{\alpha \beta \alpha \beta}$, but not the same-spin component.
I agree, we will need to antisymmetrize the $V_{pqrs}^{\alpha\alpha\alpha\alpha}$ and $V_{pqrs}^{\beta\beta\beta\beta}$ as:
$$ V_{pqrs}^{\alpha\alpha\alpha\alpha} = V_{pqrs}^{\beta\beta\beta\beta} = 0.5 \cdot \left(V_{pqrs}^{spatial} - V_{pqsr}^{spatial} \right) $$
I think?
Another question is whether of not we will need to antisymmetrize the entire tensor after construction? If so, this will create unphysical (?) integrals such as $\alpha \beta \beta \alpha$ and $\beta \alpha \alpha \beta$ integrals
These integrals aren't unphysical in the antisymmetrized basis. I.e., there are integrals that only have the "first" part of the antisymmetric integrals and others than only have the second part. So it really depends on the definition. If one considers
$$ V_{pqrs}^{\sigma_p \sigma_q \sigma_r \sigma_s} = \braket{\emptyset | {a_p a_q V(\mathbf{r}_1 \mathbf{r_2}) a_s^\dagger a_r^\dagger} | \emptyset} $$
then these "unphysical" integrals do exist and the only zero-valued integrals are things like $V_{pqrs}^{\alpha \alpha \beta \beta}$. One basically needs to be very careful and explicit with one's definition.
@RichRick1 Not sure to understand the functions:
def get_spin_blocks(self):
"""Extract different spin blocks from the Hamiltonian"""
pass
def build_reduced(self):
"""Build the reduced hamiltonian form"""
can you please give a more descriptive idea of these?
So basically for the get_spin_blocks method we will need for a spinized hamiltonian return $\alpha \alpha$, $\alpha \beta$, and $\beta \beta$ block in the form of the dictionary.
For the build_reduced method we will need to combine the one and two electron integrals into a reduced hamiltonian according to the formula:
I think this is done!