Quantum Compass Model
The Quantum Compass model serves as an insightful example of a Hamiltonian used to explore quantum phase transitions and has subextensive degeneracy in zero field. Its Hamiltonian is defined as:
The two_site_hamiltonian method defines the bond interactions along the x- and z-directions, using Pauli matrices for spin interactions. The Model method bond_direction maps each bond to a direction in the set {“+x”, “-x”, “+y”, “-y”} to help with specifying bond-dependent Hamiltonians.
Defining a Custom Model
To define a custom model, import the Model class, create a subclass, and implement the two_site_hamiltonian and one_site_hamiltonian methods. These methods specify bond interactions and single-site terms, respectively. In the example below, we define the Quantum Compass model’s Hamiltonian in the two_site_hamiltonian method.
Here is an example of how to define the model:
from acetn.model import Model
from acetn.model.pauli_matrix import pauli_matrices
class CompassModel(Model):
def __init__(self, config):
super().__init__(config)
def two_site_hamiltonian(self, bond):
jx = self.params.get("jx")
jz = self.params.get("jz")
X,Y,Z,I = pauli_matrices(self.dtype, self.device)
if self.bond_direction(bond) in ["+x", "-x"]:
return -jx*X*X
elif self.bond_direction(bond) in ["+y", "-y"]:
return -jz*Z*Z
def one_site_hamiltonian(self, site):
hx = self.params.get("hx")
hz = self.params.get("hz")
X,Y,Z,I = pauli_matrices(self.dtype, self.device)
return -hx*X - hz*Z
Defining Observables
In addition to the Hamiltonian, we need to define the observables that will be measured during the simulation. For the Quantum Compass model, an important observable is the order parameter that characterizes the spin orientations along the bond directions. The order parameter phi is defined as:
This order parameter is negative when the spins are oriented along the ±z-directions and positive when they are oriented along the ±x-directions. We can define this observable in the two_site_observables method of the custom model class.
In addition to phi, we may also want to measure the correlation between the Pauli matrices X and Z along different bonds. This is a component of the vector chirality, denoted chi, and defined as:
This characterizes the ordered state when Jx = Jz = -hx = -hz < 0, which can be derived exactly.
We can define both phi and chi in the two_site_observables method as shown below:
def two_site_observables(self, bond):
observables = {}
X, Y, Z, I = pauli_matrices(self.dtype, self.device)
if self.bond_direction(bond) in ["+x", "-x"]:
observables["phi"] = X*X
elif self.bond_direction(bond) in ["+y", "-y"]:
observables["phi"] = -Z*Z
observables["chi"] = X*Z - Z*X
return observables
Setting up the iPEPS Simulation
Once the custom model is defined, the iPEPS instance can be configured to run the simulation. The iPEPS configuration specifies physical and bond dimensions. The model parameters are provided for the Hamiltonian.
Here is an example of how to configure the iPEPS simulation:
config = {
"dtype": "float64",
"device": "cpu",
"TN": {
"dims": {"phys": 2, "bond": 2, "chi": 10},
"nx": 2,
"ny": 2
},
}
ipeps = Ipeps(config)
ipeps.set_model(CompassModel, {"jx": -1.0/4., "jz": -1.0/4., "hz": 1.0/2., "hx": 1.0/2.})
Note: The QCM has subextensive ground-state degeneracy in zero field. You may want to increase the lattice size parameters nx and/or ny to explore the properties of the ground states.
Running the Imaginary-Time Evolution
The iPEPS simulation can be used to evolve the system to obtain its ground state. The evolution is performed by iterating through a series of time steps with gradually smaller time intervals.
Here is how to perform the imaginary-time evolution:
dtau = 0.1
steps = 50
ipeps.evolve(dtau, steps=steps)
dtau = 0.01
steps = 100
for _ in range(5):
ipeps.evolve(dtau, steps=steps)
In this step: - We start by evolving the system with a larger time step (dtau = 0.1) for 50 steps. - The time step is then reduced to dtau = 0.01, and 100 steps are performed to refine the accuracy.
Full Code Example
Below is the complete Python script demonstrating the Quantum Compass model with iPEPS:
from acetn.ipeps import Ipeps
from acetn.model import Model
from acetn.model.pauli_matrix import pauli_matrices
class CompassModel(Model):
def __init__(self, config):
super().__init__(config)
def two_site_hamiltonian(self, bond):
jx = self.params.get("jx")
jz = self.params.get("jz")
X,Y,Z,I = pauli_matrices(self.dtype, self.device)
if self.bond_direction(bond) in ["+x", "-x"]:
return -jx*X*X
elif self.bond_direction(bond) in ["+y", "-y"]:
return -jz*Z*Z
def one_site_hamiltonian(self, site):
hx = self.params.get('hx')
hz = self.params.get('hz')
X,Y,Z,I = pauli_matrices(self.dtype, self.device)
return -hx*X - hz*Z
def two_site_observables(self, bond):
observables = {}
X,Y,Z,I = pauli_matrices(self.dtype, self.device)
if self.bond_direction(bond) in ["+x", "-x"]:
observables["phi"] = X*X
elif self.bond_direction(bond) in ["+y", "-y"]:
observables["phi"] = -Z*Z
return observables
if __name__ == "__main__":
config = {
"dtype": "float64",
"device": "cpu",
"TN": {"dims": {"phys": 2, "bond": 2, "chi": 10}, "nx": 2, "ny": 2},
}
ipeps = Ipeps(config)
ipeps.set_model(CompassModel, {"jx": -1.0/4., "jz": -1.0/4., "hz": 1.0/2., "hx": 1.0/2.})
dtau = 0.1
steps = 50
ipeps.evolve(dtau, steps=steps)
ipeps.measure()
dtau = 0.01
steps = 100
for _ in range(5):
ipeps.evolve(dtau, steps=steps)
ipeps.measure()