quspin.tools.block_tools.block_ops

class quspin.tools.block_tools.block_ops(blocks, static, dynamic, basis_con, basis_args, dtype, basis_kwargs={}, get_proj_kwargs={}, save_previous_data=True, compute_all_blocks=False, check_symm=True, check_herm=True, check_pcon=True)[source]

Bases: object

Splits up the dynamics of a state over various symmetry sectors.

Particularly useful if the initial state does NOT obey a symmetry but the hamiltonian does. Moreover, we provide a multiprocessing option which allows the user to split up the dynamics over multiple processing cores.

Can be used to calculate nonequal time correlators in symmetry-reduced sectors.

Notes

The block_ops object is initialised only after calling the function methods of the class to save memory.

Examples

The following sequence of examples uses the Bose-Hubbard model

\[H=-J\sum_j b^\dagger_{j+1}b_j + \mathrm{h.c.} + \frac{U}{2}\sum_j n_j(n_j-1)\]

to show how to use the block_ops class to evolve a Fock state, which explicitly breaks translational invariance, by decomposing it in all momentum blocks, time-evolving the projections, and putting the state back together in the Fock basis in the end. We use the time-evolved state to measure the local density operator \(n_j\).

The code snippets for the time evolution can be found in the examples for the function methods of the class. The code snippet below initiates the class, and is required to run the example codes for the function methods.

 1from quspin.basis import boson_basis_1d  # bosonic Hilbert space
 2from quspin.tools.block_tools import block_ops  # dynamics in symmetry blocks
 3import numpy as np  # general math functions
 4
 5#
 6##### define model parameters
 7# initial seed for random number generator
 8np.random.seed(0)  # seed is 0 to produce plots from QuSpin2 paper
 9# setting up parameters of simulation
10L = 6  # length of chain
11J = 1.0  # top side of ladder hopping
12U = 20.0  # Hubbard interaction
13#
14##### set up Hamiltonian and observables
15# define site-coupling lists
16int_list_1 = [[-0.5 * U, i] for i in range(L)]  # interaction $-U/2 \sum_i n_i$
17int_list_2 = [[0.5 * U, i, i] for i in range(L)]  # interaction: $U/2 \num_i n_i^2$
18# setting up hopping lists
19hop_list = [[-J, i, (i + 1) % L] for i in range(L)]  # PBC
20# set up static and dynamic lists
21static = [
22    ["+-", hop_list],  # hopping
23    ["-+", hop_list],  # hopping h.c.
24    ["nn", int_list_2],  # U n_i^2
25    ["n", int_list_1],  # -U n_i
26]
27dynamic = []  # no dynamic operators
28# create block_ops object
29blocks = [dict(kblock=kblock) for kblock in range(L)]  # blocks to project on to
30baisis_args = (L,)  # boson_basis_1d manditory arguments
31basis_kwargs = dict(Nb=L // 2, sps=3)  # boson_basis_1d optional args
32get_proj_kwargs = dict(pcon=True)  # set projection to full particle basis
33H_block = block_ops(
34    blocks,
35    static,
36    dynamic,
37    boson_basis_1d,
38    baisis_args,
39    np.complex128,
40    basis_kwargs=basis_kwargs,
41    get_proj_kwargs=get_proj_kwargs,
42)
43#
44# setting up local Fock basis
45basis = boson_basis_1d(L, Nb=L // 2, sps=3)
46# setting up observables
47no_checks = dict(check_herm=False, check_symm=False, check_pcon=False)
48n_list = [
49    hamiltonian([["n", [[1.0, i]]]], [], basis=basis, dtype=np.float64, **no_checks)
__init__(blocks, static, dynamic, basis_con, basis_args, dtype, basis_kwargs={}, get_proj_kwargs={}, save_previous_data=True, compute_all_blocks=False, check_symm=True, check_herm=True, check_pcon=True)[source]

Instantiates the block_ops class.

Parameters:
blockslist/tuple/iterator

Contains the symmetry blocks to construct the Hamiltonian with, as dictionaries or hamiltonian objects.

staticlist

Static operator list used to construct the block Hamiltonians. Follows hamiltonian format.

dynamiclist

Dynamic operator list used to construct the block Hamiltonians. Follows hamiltonian format.

basis_conbasis

Basis constructor used to build the basis objects to create the block diagonal Hamiltonians.

basis_argstuple

This argument is passed as the first argument for basis_con. Contains all required arguments for the basis.

dtype‘type’

The data type (e.g. numpy.float64) to construct the Hamiltonian with.

basis_kwargsdict, optional

Dictionary of keyword arguments to add when calling basis constructor.

get_proj_kwargsdict, optional

Dictionary of keyword arguments for basis.get_proj() and basis.project_from().

save_previous_databool, optional

To do time evolution the block_ops class constructs Hamiltonians, which can take time. Set this flag to True, and the class will save previously calculated Hamiltonians, so next time one needs to do evolution in that block, the code does NOT have to calculate it again. Default is True.

compute_all_blocksbool, optional

Flag which tells the block_ops class to compute all symmetry blocks at initialization. Default is False.

This option sets save_previous_data = True automatically.

check_symmbool, optional

Enable/Disable symmetry check of the operators for the first Hamiltonian constructed.

check_hermbool, optional

Enable/Disable hermiticity check of the operators for the first Hamiltonian constructed.

check_pconbool, optional

Enable/Disable particle conservation check of the operators for the first Hamiltonian constructed.

Methods

__init__(blocks, static, dynamic, basis_con, ...)

Instantiates the block_ops class.

compute_all_blocks()

Sets compute_all_blocks = True.

evolve(psi_0, t0, times[, iterate, n_jobs, ...])

Creates symmetry blocks of the Hamiltonian and then uses them to run hamiltonian.evolve() in parallel.

expm(psi_0[, H_time_eval, iterate, n_jobs, ...])

Creates symmetry blocks of the Hamiltonian and then uses them to run _expm_multiply() in parallel.

update_blocks(blocks, basis_con, basis_args)

Allows to update the blocks variable of the class.

Attributes

H_dict

dictionary which contains the block Hamiltonians under keys labelled by the symmetry blocks, e.g. str(block) where block is a block dictionary variable.

P_dict

dictionary which contains the block projectors under keys labelled by the symmetry blocks, e.g. str(block) where block is a block dictionary variable.

basis_dict

dictionary which contains the basis objects under keys labelled by the symmetry blocks, e.g. str(block) where block is a block dictionary variable.

dtype

numpy data type to store the block hamiltonians in.

dynamic

contains the dynamic operators used to construct the symmetry-block Hamiltonians.

save_previous_data

reflects state of optimal argument save_previous_data.

static

contains the static operators used to construct the symmetry-block Hamiltonians.

property H_dict

dictionary which contains the block Hamiltonians under keys labelled by the symmetry blocks, e.g. str(block) where block is a block dictionary variable.

Type:

dict

property P_dict

dictionary which contains the block projectors under keys labelled by the symmetry blocks, e.g. str(block) where block is a block dictionary variable.

Type:

dict

property basis_dict

dictionary which contains the basis objects under keys labelled by the symmetry blocks, e.g. str(block) where block is a block dictionary variable.

Type:

dict

compute_all_blocks()[source]

Sets compute_all_blocks = True.

Examples

The example below builds on the code snippet shown in the description of the block_ops class.

1]
2#
property dtype

numpy data type to store the block hamiltonians in.

Type:

type

property dynamic

contains the dynamic operators used to construct the symmetry-block Hamiltonians.

Type:

list

evolve(psi_0, t0, times, iterate=False, n_jobs=1, block_diag=False, stack_state=False, imag_time=False, solver_name='dop853', **solver_args)[source]

Creates symmetry blocks of the Hamiltonian and then uses them to run hamiltonian.evolve() in parallel.

Arguments NOT described below can be found in the documentation for the `hamiltonian.evolve()` method.

Parameters:
psi_0numpy.ndarray, list, tuple

Quantum state which defined on the full Hilbert space of the problem. Does not need to obey and sort of symmetry.

t0float

Inistial time to start the evolution at.

timesnumpy.ndarray, list

Contains the times to compute the solution at. Must be some an iterable object.

iteratebool, optional

Flag to return generator when set to True. Otherwise the output is an array of states. Default is ‘False’.

n_jobsint, optional

Number of processes requested for the computation time evolution dynamics.

NOTE: one of those processes is used to gather results. For best performance, all blocks should be approximately the same size and n_jobs-1 must be a common devisor of the number of blocks, such that there is roughly an equal workload for each process. Otherwise the computation will be as slow as the slowest process.

block_diagbool, optional

When set to True, this flag puts the Hamiltonian matrices for the separate symemtry blocks into a list and then loops over it to do time evolution. When set to False, it puts all blocks in a single giant sparse block diagonal matrix. Default is False.

This flag is useful if there are a lot of smaller-sized blocks.

Returns:
obj

if iterate = True, returns generator which generates the time dependent state in the full H-space basis.

if iterate = False, returns numpy.ndarray which has the time-dependent states in the full H-space basis in the rows.

Raises:
ValueError

Variable imag_time=True option on hamiltonian.evolve() method not supported.

ValueError

iterate=True requires times to be an array or a list.

RuntimeError

Terminates when initial state has no projection onto the specified symmetry blocks.

Examples

The example below builds on the code snippet shown in the description of the block_ops class.

 1#
 2##### compute all momentum blocks
 3H_block.compute_all_blocks()
 4#
 5##### calculating the evolved states using matrix exponentiation
 6# setting up parameters for evolution
 7start, stop, num = 0, 30, 301  # 0.1 equally spaced points
 8times = np.linspace(start, stop, num)
 9n_jobs = 1  # paralelisation: increase to see if calculation runs faster!
10psi_t = H_block.expm(
11    psi, a=-1j, start=start, stop=stop, num=num, block_diag=False, n_jobs=n_jobs
12)
13# calculating the local densities as a function of time
14n_t = np.vstack([n.expt_value(psi_t).real for n in n_list]).T
15#
16##### calculating the evolved state using the evolve method
17# setting up parameters for evolution
18start, stop, num = 0, 30, 301  # 0.1 equally spaced points
19times = np.linspace(start, stop, num)
20psi_t = H_block.evolve(psi, times[0], times)
21n_t = np.vstack([n.expt_value(psi_t).real for n in n_list]).T
expm(psi_0, H_time_eval=0.0, iterate=False, n_jobs=1, block_diag=False, a=-0 - 1j, start=None, stop=None, endpoint=None, num=None, shift=None)[source]

Creates symmetry blocks of the Hamiltonian and then uses them to run _expm_multiply() in parallel.

Arguments NOT described below can be found in the documentation for the `exp_op` class.

Parameters:
psi_0numpy.ndarray, list, tuple

Quantum state which defined on the full Hilbert space of the problem. Does not need to obey and sort of symmetry.

t0float

Inistial time to start the evolution at.

H_time_evalnumpy.ndarray, list

Times to evaluate the Hamiltonians at when doing the matrix exponentiation.

iteratebool, optional

Flag to return generator when set to True. Otherwise the output is an array of states. Default is ‘False’.

n_jobsint, optional

Number of processes requested for the computation time evolution dynamics.

NOTE: one of those processes is used to gather results. For best performance, all blocks should be approximately the same size and n_jobs-1 must be a common devisor of the number of blocks, such that there is roughly an equal workload for each process. Otherwise the computation will be as slow as the slowest process.

block_diagbool, optional

When set to True, this flag puts the Hamiltonian matrices for the separate symemtri blocks into a list and then loops over it to do time evolution. When set to False, it puts all blocks in a single giant sparse block diagonal matrix. Default is False.

This flag is useful if there are a lot of smaller-sized blocks.

Returns:
obj

if iterate = True, returns generator which generates the time dependent state in the full H-space basis.

if iterate = False, returns numpy.ndarray which has the time-dependent states in the full H-space basis in the rows.

Raises:
ValueError

Various ValueError`s of `exp_op class.

RuntimeError

Terminates when initial state has no projection onto the specified symmetry blocks.

Examples

The example below builds on the code snippet shown in the description of the block_ops class.

1# set up initial state
2i0 = basis.index("111000")  # pick state from basis set
3psi = np.zeros(basis.Ns, dtype=np.float64)
4psi[i0] = 1.0
5# print info about setup
6state_str = "".join(
7    str(int((basis[i0] // basis.sps ** (L - i - 1)) % basis.sps)) for i in range(L)
8)
property save_previous_data

reflects state of optimal argument save_previous_data.

Type:

bool

property static

contains the static operators used to construct the symmetry-block Hamiltonians.

Type:

list

update_blocks(blocks, basis_con, basis_args, compute_all_blocks=False)[source]

Allows to update the blocks variable of the class.

Parameters:
blockslist/tuple/iterator

Contains the new symmetry blocks to be added to the basis_dict attribute of the class, as dictionaries or hamiltonian objects.

basis_conbasis

Basis constructor used to build the basis objects to create the new block diagonal Hamiltonians.

basis_argstuple

This argument is passed as the first argument for basis_con. Contains all required arguments for the basis.

compute_all_blocksbool, optional

Flag which tells the block_ops class to compute all symmetry blocks at initialization. Default is False.