# MultiCouplingModel¶

• full name: tenpy.models.model.MultiCouplingModel

• parent module: tenpy.models.model

• type: class

Inheritance Diagram

Methods

class tenpy.models.model.MultiCouplingModel(lattice, bc_coupling=None)[source]

Generalizes CouplingModel to allow couplings involving more than two sites.

The corresponding couplings can be added with add_multi_coupling() and add_multi_coupling_term() and are saved in coupling_terms, which can now contain instances of MultiCouplingTerms.

add_multi_coupling(strength, u0, op0, other_ops, op_string=None, category=None)[source]

Add multi-site coupling terms to the Hamiltonian, summing over lattice sites.

Represents couplings of the form $$sum_{x_0, ..., x_{dim-1}} strength[loc(\vec{x})] * OP0 * OP1 * ... * OPM$$, where OP_0 := lat.unit_cell[u0].get_op(op0) acts on the site (x_0, ..., x_{dim-1}, u0), and OP_m := lat.unit_cell[other_u[m]].get_op(other_op[m]), m=1…M, acts on the site (x_0+other_dx[m][0], ..., x_{dim-1}+other_dx[m][dim-1], other_u[m]). For periodic boundary conditions along direction a (lat.bc[a] == False) the index x_a is taken modulo lat.Ls[a] and runs through range(lat.Ls[a]). For open boundary conditions, x_a is limited to 0 <= x_a < Ls[a] and 0 <= x_a+other_dx[m,a] < lat.Ls[a]. The coupling strength may vary spatially, $$loc(\vec{x})$$ indicates the lower left corner of the hypercube containing all the involved sites $$\vec{x}, \vec{x}+\vec{other_dx[m, :]}$$.

The necessary terms are just added to coupling_terms; doesn’t rebuild the MPO.

Parameters
• strength (scalar | array) – Prefactor of the coupling. May vary spatially and is tiled to the required shape.

• u0 (int) – Picks the site lat.unit_cell[u0] for OP0.

• op0 (str) – Valid operator name of an onsite operator in lat.unit_cell[u0] for OP0.

• other_ops (list of (u, op_m, dx)) – One tuple for each of the other operators OP1, OP2, ... OPM involved. u picks the site lat.unit_cell[u], op_name is a valid operator acting on that site, and dx gives the translation vector between OP0 and the specified operator.

• op_string (str | None) –

Name of an operator to be used inbetween the operators, excluding the sites on which the operators act. This operator should be defined on all sites in the unit cell.

Special case: If None, auto-determine whether a Jordan-Wigner string is needed (using op_needs_JW()), for each of the segments inbetween the operators and also on the sites of the left operators. Note that in this case the ordering of the operators is important and handled in the usual convention that OPM acts first and OP0 last on a physical state.

• category (str) – Descriptive name used as key for coupling_terms. Defaults to a string of the form "{op0}_i {other_ops[0]}_j {other_ops[1]}_k ...".

Add a general M-site coupling term on given MPS sites.

Parameters
• strength (float) – The strength of the coupling term.

• ijkl (list of int) – The MPS indices of the sites on which the operators acts. With i, j, k, … = ijkl, we require that they are ordered ascending, i < j < k < ... and that 0 <= i < N_sites. Inidces >= N_sites indicate couplings between different unit cells of an infinite MPS.

• ops_ijkl (list of str) – Names of the involved operators on sites i, j, k, ….

• op_string (list of str) – Names of the operator to be inserted between the operators, e.g., op_string[0] is inserted between i and j.

• category (str) – Descriptive name used as key for coupling_terms. Defaults to a string of the form "{op0}_i {other_ops[0]}_j {other_ops[1]}_k ...".

add_coupling(strength, u1, op1, u2, op2, dx, op_string=None, str_on_first=True, raise_op2_left=False, category=None)[source]

Add twosite coupling terms to the Hamiltonian, summing over lattice sites.

Represents couplings of the form $$\sum_{x_0, ..., x_{dim-1}} strength[loc(\vec{x})] * OP1 * OP2$$, where OP1 := lat.unit_cell[u1].get_op(op1) acts on the site (x_0, ..., x_{dim-1}, u1), and OP2 := lat.unit_cell[u2].get_op(op2) acts on the site (x_0+dx[0], ..., x_{dim-1}+dx[dim-1], u2). Possible combinations x_0, ..., x_{dim-1} are determined from the boundary conditions in possible_couplings().

The coupling strength may vary spatially, $$loc(\vec{x})$$ indicates the lower left corner of the hypercube containing the involved sites $$\vec{x}$$ and $$\vec{x}+\vec{dx}$$.

The necessary terms are just added to coupling_terms; doesn’t (re)build the MPO.

Deprecated since version 0.4.0: The arguments str_on_first and raise_op2_left will be removed in version 1.0.0.

Parameters
• strength (scalar | array) – Prefactor of the coupling. May vary spatially (see above). If an array of smaller size is provided, it gets tiled to the required shape.

• u1 (int) – Picks the site lat.unit_cell[u1] for OP1.

• op1 (str) – Valid operator name of an onsite operator in lat.unit_cell[u1] for OP1.

• u2 (int) – Picks the site lat.unit_cell[u2] for OP2.

• op2 (str) – Valid operator name of an onsite operator in lat.unit_cell[u2] for OP2.

• dx (iterable of int) – Translation vector (of the unit cell) between OP1 and OP2. For a 1D lattice, a single int is also fine.

• op_string (str | None) – Name of an operator to be used between the OP1 and OP2 sites. Typical use case is the phase for a Jordan-Wigner transformation. The operator should be defined on all sites in the unit cell. If None, auto-determine whether a Jordan-Wigner string is needed, using op_needs_JW().

• str_on_first (bool) – Whether the provided op_string should also act on the first site. This option should be chosen as True for Jordan-Wigner strings. When handling Jordan-Wigner strings we need to extend the op_string to also act on the ‘left’, first site (in the sense of the MPS ordering of the sites given by the lattice). In this case, there is a well-defined ordering of the operators in the physical sense (i.e. which of op1 or op2 acts first on a given state). We follow the convention that op2 acts first (in the physical sense), independent of the MPS ordering. Deprecated.

• raise_op2_left (bool) – Raise an error when op2 appears left of op1 (in the sense of the MPS ordering given by the lattice). Deprecated.

• category (str) – Descriptive name used as key for coupling_terms. Defaults to a string of the form "{op1}_i {op2}_j".

Examples

When initializing a model, you can add a term $$J \sum_{<i,j>} S^z_i S^z_j$$ on all nearest-neighbor bonds of the lattice like this:

>>> J = 1.  # the strength
>>> for u1, u2, dx in self.lat.pairs['nearest_neighbors']:
...     self.add_coupling(J, u1, 'Sz', u2, 'Sz', dx)

The strength can be an array, which get’s tiled to the correct shape. For example, in a 1D Chain with an even number of sites and periodic (or infinite) boundary conditions, you can add alternating strong and weak couplings with a line like:

>>> self.add_coupling([1.5, 1.], 0, 'Sz', 0, 'Sz', dx)

To add the hermitian conjugate, e.g. for a hopping term, you should add it in the opposite direction -dx, complex conjugate the strength, and take the hermitian conjugate of the operators in swapped order (including a swap of u1 <-> u2). For spin-less fermions (FermionSite), this would be

>>> t = 1.  # hopping strength
>>> for u1, u2, dx in self.lat.pairs['nearest_neighbors']:
...     self.add_coupling(t, u1, 'Cd', u2, 'C', dx)
...     self.add_coupling(np.conj(t), u2, 'Cd', u1, 'C', -dx)  # h.c.

With spin-full fermions (SpinHalfFermions), it could be:

>>> for u1, u2, dx in self.lat.pairs['nearest_neighbors']:
...     self.add_coupling(t, u1, 'Cdu', u2, 'Cd', dx)  # Cdagger_up C_down
...     self.add_coupling(np.conj(t), u2, 'Cdd', u1, 'Cu', -dx)  # h.c. Cdagger_down C_up

Note that the Jordan-Wigner strings are figured out automatically!

add_coupling_term(strength, i, j, op_i, op_j, op_string='Id', category=None)[source]

Add a two-site coupling term on given MPS sites.

Parameters
• strength (float) – The strength of the coupling term.

• j (i,) – The MPS indices of the two sites on which the operator acts. We require 0 <= i < N_sites and i < j, i.e., op_i acts “left” of op_j. If j >= N_sites, it indicates couplings between unit cells of an infinite MPS.

• op2 (op1,) – Names of the involved operators.

• op_string (str) – The operator to be inserted between i and j.

• category (str) – Descriptive name used as key for coupling_terms. Defaults to a string of the form "{op1}_i {op2}_j".

Adds a term $$\sum_{x_0, ..., x_{dim-1}} strength[x_0, ..., x_{dim-1}] * OP$$, where the operator OP=lat.unit_cell[u].get_op(opname) acts on the site given by a lattice index (x_0, ..., x_{dim-1}, u), to the represented Hamiltonian.

The necessary terms are just added to onsite_terms; doesn’t rebuild the MPO.

Parameters
• strength (scalar | array) – Prefactor of the onsite term. May vary spatially. If an array of smaller size is provided, it gets tiled to the required shape.

• u (int) – Picks a Site lat.unit_cell[u] out of the unit cell.

• opname (str) – valid operator name of an onsite operator in lat.unit_cell[u].

• category (str) – Descriptive name used as key for onsite_terms. Defaults to opname.

Add an onsite term on a given MPS site.

Parameters
• strength (float) – The strength of the term.

• i (int) – The MPS index of the site on which the operator acts. We require 0 <= i < L.

• op (str) – Name of the involved operator.

• category (str) – Descriptive name used as key for onsite_terms. Defaults to op.

all_coupling_terms()[source]

Sum of all coupling_terms.

all_onsite_terms()[source]

Sum of all onsite_terms.

calc_H_MPO(tol_zero=1e-15)[source]

Calculate MPO representation of the Hamiltonian.

Uses onsite_terms and coupling_terms to build an MPO graph (and then an MPO).

Parameters

tol_zero (float) – Prefactors with abs(strength) < tol_zero are considered to be zero.

Returns

H_MPO – MPO representation of the Hamiltonian.

Return type

MPO

calc_H_bond(tol_zero=1e-15)[source]

calculate H_bond from coupling_terms and onsite_terms.

Parameters

tol_zero (float) – prefactors with abs(strength) < tol_zero are considered to be zero.

Returns

H_bond – Bond terms as required by the constructor of NearestNeighborModel. Legs are ['p0', 'p0*', 'p1', 'p1*']

Return type

list of Array

:raises ValueError : if the Hamiltonian contains longer-range terms.:

calc_H_onsite(tol_zero=1e-15)[source]

Calculate H_onsite from self.onsite_terms.

Deprecated since version 0.4.0: This function will be removed in 1.0.0. Replace calls to this function by self.all_onsite_terms().remove_zeros(tol_zero).to_Arrays(self.lat.mps_sites()).

Parameters

tol_zero (float) – prefactors with abs(strength) < tol_zero are considered to be zero.

Returns

H_onsite – onsite terms of the Hamiltonian.

Return type

list of npc.Array

Add an external flux to the coupling strength.

When performing DMRG on a “cylinder” geometry, it might be useful to put an “external flux” through the cylinder. This means that a particle hopping around the cylinder should pick up a phase given by the external flux [Resta1997]. This is also called “twisted boundary conditions” in literature. This function adds a complex phase to the strength array on some bonds, such that particles hopping in positive direction around the cylinder pick up exp(+i phase).

Warning

For the sign of phase it is important that you consistently use the creation operator as op1 and the annihilation operator as op2 in add_coupling().

Parameters
• strength (scalar | array) – The strength to be used in add_coupling(), when no external flux would be present.

• dx (iterable of int) – Translation vector (of the unit cell) between op1 and op2 in add_coupling().

• phase (iterable of float) – The phase of the external flux for hopping in each direction of the lattice. E.g., if you want flux through the cylinder on which you have an infinite MPS, you should give phase=[0, phi] souch that particles pick up a phase phi when hopping around the cylinder.

Returns

strength – The strength array to be used as strength in add_coupling() with the given dx.

Return type

complex array

Examples

Let’s say you have an infinite MPS on a cylinder, and want to add nearest-neighbor hopping of fermions with the FermionSite. The cylinder axis is the x-direction of the lattice, so to put a flux through the cylinder, you want particles hopping around the cylinder to pick up a phase phi given by the external flux.

>>> strength = 1. # hopping strength without external flux
>>> phi = np.pi/4 # determines the external flux strength
>>> strength_with_flux = self.coupling_strength_add_ext_flux(strength, dx, [0, phi])
>>> for u1, u2, dx in self.lat.pairs['nearest_neighbors']:
...     self.add_coupling(strength_with_flux, u1, 'Cd', u2, 'C', dx)
...     self.add_coupling(np.conj(strength_with_flux), u2, 'Cd', u1, 'C', -dx)

Load instance from a HDF5 file.

This method reconstructs a class instance from the data saved with save_hdf5().

Parameters

• h5gr (Group) – HDF5 group which is represent the object to be constructed.

• subpath (str) – The name of h5gr with a '/' in the end.

Returns

obj – Newly generated class instance containing the required data.

Return type

cls

group_sites(n=2, grouped_sites=None)[source]

Modify self in place to group sites.

Group each n sites together using the GroupedSite. This might allow to do TEBD with a Trotter decomposition, or help the convergence of DMRG (in case of too long range interactions).

This has to be done after finishing initialization and can not be reverted.

Parameters
• n (int) – Number of sites to be grouped together.

• grouped_sites (None | list of GroupedSite) – The sites grouped together.

Returns

grouped_sites – The sites grouped together.

Return type

list of GroupedSite

save_hdf5(hdf5_saver, h5gr, subpath)[source]

Export self into a HDF5 file.

This method saves all the data it needs to reconstruct self with from_hdf5().

This implementation saves the content of __dict__ with save_dict_content(), storing the format under the attribute 'format'.

Parameters
• hdf5_saver (Hdf5Saver) – Instance of the saving engine.

• h5gr (:classGroup) – HDF5 group which is supposed to represent self.

• subpath (str) – The name of h5gr with a '/' in the end.

test_sanity()[source]

Sanity check, raises ValueErrors, if something is wrong.