CouplingModel¶
full name: tenpy.models.model.CouplingModel
parent module:
tenpy.models.model
type: class
Inheritance Diagram
Methods



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

Add a twosite coupling term on given MPS sites. 
Add an exponentially decaying longrange coupling. 


Add a single term to self. 

Add multisite coupling terms to the Hamiltonian, summing over lattice sites. 
Add a general Msite coupling term on given MPS sites. 


Add onsite terms to 

Add an onsite term on a given MPS site. 
Sum of all 

Sum of all 


Calculate MPO representation of the Hamiltonian. 

calculate H_bond from 

Calculate H_onsite from self.onsite_terms. 
Shallow copy of self. 

Add an external flux to the coupling strength. 


Repeat the unit cell for infinite MPS boundary conditions; in place. 

Return a (shallow) copy with extracted segment of MPS. 

Load instance from a HDF5 file. 

Modify self in place to group sites. 

Export self into a HDF5 file. 
Sanity check, raises ValueErrors, if something is wrong. 
Class Attributes and Properties

class attribute. 
 class tenpy.models.model.CouplingModel(lattice, bc_coupling=None, explicit_plus_hc=False)[source]¶
Bases:
tenpy.models.model.Model
Base class for a general model of a Hamiltonian consisting of twosite couplings.
In this class, the terms of the Hamiltonian are specified explicitly as
OnsiteTerms
orCouplingTerms
.Deprecated since version 0.4.0: bc_coupling will be removed in 1.0.0. To specify the full geometry in the lattice, use the bc parameter of the
Lattice
. Parameters
lattice (
Lattice
) – The lattice defining the geometry and the local Hilbert space(s).bc_coupling ((iterable of) {
'open'
'periodic'
int
}) – Boundary conditions of the couplings in each direction of the lattice. Defines how the couplings are added inadd_coupling()
. A single string holds for all directions. An integer shift means that we have periodic boundary conditions along this direction, but shift/tilt byshift*lattice.basis[0]
(~cylinder axis forbc_MPS='infinite'
) when going around the boundary along this direction.explicit_plus_hc (bool) – If True, the Hermitian conjugate of the MPO is computed at runtime, rather than saved in the MPO.
 onsite_terms¶
The
OnsiteTerms
ordered by category. Type
{‘category’:
OnsiteTerms
}
 coupling_terms¶
The
CouplingTerms
ordered by category. In case we’ve added terms with more than 2 operators, e.g. withadd_multi_coupling()
, the values of the dictionary may also beMultiCouplingTerms
. Type
{‘category’:
CouplingTerms
}
 exp_decaying_terms¶
Collection of coupling terms with exponentially decaying longrange interactions. Filled by
add_exponentially_decaying_coupling()
.
 explicit_plus_hc¶
If True, self represents the terms in
onsite_terms
,coupling_terms
andexp_decaying_terms
plus their hermitian conjugate added. The flag will be carried on to the MPO, which will have a reduced bond dimension ifself.add_coupling(..., plus_hc=True)
was used. Note thatadd_onsite()
,add_coupling()
,add_multi_coupling()
andadd_exponentially_decaying_coupling()
respect this flag, ensuring that the represented Hamiltonian is indepentent of the explicit_plus_hc flag. Type
 add_local_term(strength, term, category=None, plus_hc=False)[source]¶
Add a single term to self.
The repesented term is strength times the product of the operators given in terms. Each operator is specified by the name and the site it acts on; the latter given by a lattice index, see
Lattice
.Depending on the length of term, it can add an onsite term or a coupling term to
onsite_terms
orcoupling_terms
, respectively. Parameters
strength (float/complex) – The prefactor of the term.
term (list of (str, array_like)) – List of tuples
(opname, lat_idx)
where opname is a string describing the operator acting on the site given by the lattice index lat_idx. Here, lat_idx is for example [x, y, u] for a 2D lattice, with u being the index within the unit cell.category – Descriptive name used as key for
onsite_terms
orcoupling_terms
.plus_hc (bool) – If True, the hermitian conjugate of the terms is added automatically.
 add_onsite(strength, u, opname, category=None, plus_hc=False)[source]¶
Add onsite terms to
onsite_terms
.Adds \(\sum_{\vec{x}} strength[\vec{x}] * OP\) to the represented Hamiltonian, where the operator
OP=lat.unit_cell[u].get_op(opname)
acts on the site given by a lattice index(x_0, ..., x_{dim1}, u)
,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.plus_hc (bool) – If True, the hermitian conjugate of the terms is added automatically.
See also
add_coupling
Add a terms acting on two sites.
add_onsite_term
Add a single term without summing over \(vec{x}\).
 add_onsite_term(strength, i, op, category=None, plus_hc=False)[source]¶
Add an onsite term on a given MPS site.
Wrapper for
self.onsite_terms[category].add_onsite_term(...)
. 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.plus_hc (bool) – If True, the hermitian conjugate of the term is added automatically.
 all_onsite_terms()[source]¶
Sum of all
onsite_terms
.
 add_coupling(strength, u1, op1, u2, op2, dx, op_string=None, str_on_first=True, raise_op2_left=False, category=None, plus_hc=False)[source]¶
Add twosite coupling terms to the Hamiltonian, summing over lattice sites.
Represents couplings of the form \(\sum_{x_0, ..., x_{dim1}} strength[shift(\vec{x})] * OP0 * OP1\), where
OP0 := lat.unit_cell[u0].get_op(op0)
acts on the site(x_0, ..., x_{dim1}, u1)
, andOP1 := lat.unit_cell[u1].get_op(op1)
acts on the site(x_0+dx[0], ..., x_{dim1}+dx[dim1], u1)
. Possible combinationsx_0, ..., x_{dim1}
are determined from the boundary conditions inpossible_couplings()
.The coupling strength may vary spatially if the given strength is a numpy array. The correct shape of this array is the coupling_shape returned by
tenpy.models.lattice.coupling_shape()
and depends on the boundary conditions. Theshift(...)
depends on dx, and is chosen such that the first entrystrength[0, 0, ...]
of strength is the prefactor for the first possible coupling fitting into the lattice if you imagine open boundary conditions.The necessary terms are just added to
coupling_terms
; this function does not rebuild 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 JordanWigner transformation. The operator should be defined on all sites in the unit cell. If
None
, autodetermine whether a JordanWigner string is needed, usingop_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 JordanWigner strings. When handling JordanWigner 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 welldefined 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"
.plus_hc (bool) – If True, the hermitian conjugate of the terms is added automatically.
Examples
When initializing a model, you can add a term \(J \sum_{<i,j>} S^z_i S^z_j\) on all nearestneighbor 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 gets 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.], u1, 'Sz', u2, 'Sz', dx)
Make sure to use the plus_hc argument if necessary, e.g. for hoppings:
>>> t = 1. # hopping strength >>> for u1, u2, dx in self.lat.pairs['nearest_neighbors']: ... self.add_coupling(t, u1, 'Cd', u2, 'C', dx, plus_hc=True)
Alternatively, you can add the hermitian conjugate terms explictly. The correct way is to complex conjugate the strength, take the hermitian conjugate of the operators and swap the order (including a swap u1 <> u2), and use the opposite direction
dx
, i.e. the h.c. ofadd_coupling(t, u1, 'A', u2, 'B', dx)
isadd_coupling(np.conj(t), u2, hc('B'), u1, hc('A'), dx)
, where hc takes the hermitian conjugate of the operator names, seeget_hc_op_name()
. For spinless fermions (FermionSite
), this would be>>> 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 spinfull 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 JordanWigner strings for the fermions are added automatically!
See also
add_onsite
Add terms acting on one site only.
add_multi_coupling_term
for terms on more than two sites.
add_coupling_term
Add a single term without summing over \(\vec{x}\).
 add_coupling_term(strength, i, j, op_i, op_j, op_string='Id', category=None, plus_hc=False)[source]¶
Add a twosite coupling term on given MPS sites.
Wrapper for
self.coupling_terms[category].add_coupling_term(...)
.Warning
This function does not handle JordanWigner strings! You might want to use
add_local_term()
instead. Parameters
strength (float) – The strength of the coupling term.
i (int) – The MPS indices of the two sites on which the operator acts. We require
0 <= i < N_sites
andi < j
, i.e., op_i acts “left” of op_j. If j >= N_sites, it indicates couplings between unit cells of an infinite MPS.j (int) – The MPS indices of the two sites on which the operator acts. We require
0 <= i < N_sites
andi < j
, i.e., op_i acts “left” of op_j. If j >= N_sites, it indicates couplings between unit cells of an infinite MPS.op1 (str) – Names of the involved operators.
op2 (str) – 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"
.plus_hc (bool) – If True, the hermitian conjugate of the term is added automatically.
 all_coupling_terms()[source]¶
Sum of all
coupling_terms
.
 add_multi_coupling(strength, ops, _deprecate_1='DEPRECATED', _deprecate_2='DEPRECATED', op_string=None, category=None, plus_hc=False)[source]¶
Add multisite coupling terms to the Hamiltonian, summing over lattice sites.
Represents couplings of the form \(sum_{\vec{x}} strength[shift(\vec{x})] * OP_0 * OP_1 * ... * OP_{M1}\), involving M operators. Here, \(OP_m\) stands for the operator defined by the mth tuple
(opname, dx, u)
given in the argument ops, which determines the position \(\vec{x} + \vec{dx}\) and unitcell index u of the site it acts on; the actual operator is given by self.lat.unit_cell[u].get_op(opname).The coupling strength may vary spatially if the given strength is a numpy array. The correct shape of this array is the coupling_shape returned by
tenpy.models.lattice.possible_multi_couplings()
and depends on the boundary conditions. Theshift(...)
depends on the dx entries of ops and is chosen such that the first entrystrength[0, 0, ...]
of strength is the prefactor for the first possible coupling fitting into the lattice if you imagine open boundary conditions.The necessary terms are just added to
coupling_terms
; this function does not rebuild the MPO.Deprecated since version 0.6.0: We switched from the three arguments u0, op0 and other_op with
other_ops=[(u1, op1, dx1), (op2, u2, dx2), ...]
to a single, equivalent argment ops which should now readops=[(op0, dx0, u0), (op1, dx1, u1), (op2, dx2, u2), ...]
, wheredx0 = [0]*self.lat.dim
. Note the changed order inside the tuples! Parameters
strength (scalar  array) – Prefactor of the coupling. May vary spatially, and is tiled to the required shape.
ops (list of
(opname, dx, u)
) – Each tuple determines one operator of the coupling, see the description above. opname (str) is the name of the operator, dx (list of length lat.dim) is a translation vector, and u (int) is the index of lat.unit_cell on which the operator acts. The first entry of ops corresponds to \(OP_0\) and acts last in the physical sense.If a string is given, we use this as the name of an operator to be used inbetween the operators, excluding the sites on which any operators act. This operator should be defined on all sites in the unit cell.
If
None
, autodetermine whether a JordanWigner string is needed (usingop_needs_JW()
) for each of the segments inbetween the operators and also on the sites of the left operators.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 ..."
.plus_hc (bool) – If True, the hermitian conjugate of the terms is added automatically.
Examples
A call to
add_coupling()
with argumentsadd_coupling(strength, u1, 'A', u2, 'B', dx)
is equivalent to the following:>>> dx_0 = [0] * self.lat.dim # = [0] for a 1D lattice, [0, 0] in 2D >>> self.add_multi_coupling(strength, [('A', dx_0, u1), ('B', dx, u2)])
To explicitly add the hermitian conjugate (instead of simply using plus_hc = True), you need to take the complex conjugate of the strength, reverse the order of the operators and take the hermitian conjugates of the individual operator names (indicated by the
hc(...)
, seeget_hc_op_name()
):>>> self.add_multi_coupling(np.conj(strength), [(hc('B'), dx, u2), (hc('A'), dx_0, u1)])
See also
add_onsite
Add terms acting on one site only.
add_coupling
Add terms acting on two sites.
add_multi_coupling_term
Add a single term, not summing over the possible \(\vec{x}\).
 add_multi_coupling_term(strength, ijkl, ops_ijkl, op_string, category=None, plus_hc=False)[source]¶
Add a general Msite coupling term on given MPS sites.
Wrapper for
self.coupling_terms[category].add_multi_coupling_term(...)
.Warning
This function does not handle JordanWigner strings! You might want to use
add_local_term()
instead. 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 that0 <= 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 {op1}_j {op2}_k ..."
.plus_hc (bool) – If True, the hermitian conjugate of the term is added automatically.
 add_exponentially_decaying_coupling(strength, lambda_, op_i, op_j, subsites=None, op_string=None, plus_hc=False)[source]¶
Add an exponentially decaying longrange coupling.
\[strength \sum_{i < j} \lambda^{ij} A_{subsites[i]} B_{subsites[j]}\]Where the operator A is given by op_i, and B is given by op_j. Note that the sum over i,j is longrange, for infinite systems going beyond the MPS unit cell. Moreover, note that the distance in the exponent is the distance within subsites.
 Parameters
strength (float) – Overall prefactor.
lambda (float) – Decayrate
op_i (string) – Names for the operators.
op_j (string) – Names for the operators.
subsites (None  1D array) – Selects a subset of sites within the MPS unit cell on which the operators act. Needs to be sorted.
None
selects all sites.op_string (None  str) – The operator to be inserted between A and B; If
None
, this function checks whether a fermionic"JW"
string is needed for the given operators; in this case the right op_j acts first.plus_hc (bool) – If True, the hermitian conjugate of the term is added automatically.
Examples
At least for simple enough 1D chains (or ladders), you can use
fit_with_sum_of_exp()
to approximate a longrange function with a few sum of exponentials and then add them with this function.>>> def decay(x): ... return np.exp(0.1*x) / x**2 >>> from tenpy.tools.fit import fit_with_sum_of_exp, sum_of_exp >>> n_exp = 5 >>> fit_range = 50 >>> lam, pref = fit_with_sum_of_exp(decay, n_exp, fit_range) >>> x = np.arange(1, fit_range + 1) >>> print('error in fit: {0:.3e}'.format(np.sum(np.abs(decay(x)  sum_of_exp(lam, pref, x))))) error in fit: 1.073e04 >>> for pr, la in zip(pref, lam): ... self.add_exponentially_decaying_coupling(pr, la, 'N', 'N')
 calc_H_onsite(tol_zero=1e15)[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())
. You might also want to takeexplicit_plus_hc
into account. Parameters
tol_zero (float) – prefactors with
abs(strength) < tol_zero
are considered to be zero. Returns
H_onsite (list of npc.Array)
onsite terms of the Hamiltonian. If
explicit_plus_hc
is True, – Hermitian conjugates of the onsite terms will be included.
 calc_H_bond(tol_zero=1e15)[source]¶
calculate H_bond from
coupling_terms
andonsite_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 longerrange terms.:
 calc_H_MPO(tol_zero=1e15)[source]¶
Calculate MPO representation of the Hamiltonian.
Uses
onsite_terms
andcoupling_terms
to build an MPOGraph (and then an MPO).
 coupling_strength_add_ext_flux(strength, dx, phase)[source]¶
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 [resta1998]. 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 nearestneighbor hopping of fermions with the
FermionSite
. The cylinder axis is the xdirection 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 >>> for u1, u2, dx in self.lat.pairs['nearest_neighbors']: ... strength_with_flux = self.coupling_strength_add_ext_flux(strength, dx, [0, phi]) ... self.add_coupling(strength_with_flux, u1, 'Cd', u2, 'C', dx) ... self.add_coupling(np.conj(strength_with_flux), u2, 'Cd', u1, 'C', dx)
 enlarge_mps_unit_cell(factor=2)[source]¶
Repeat the unit cell for infinite MPS boundary conditions; in place.
This has to be done after finishing initialization and can not be reverted.
 Parameters
factor (int) – The new number of sites in the MPS unit cell will be increased from N_sites to
factor*N_sites_per_ring
. Since MPS unit cells are repeated in the xdirection in our convetion, the lattice shape goes from(Lx, Ly, ..., Lu)
to(Lx*factor, Ly, ..., Lu)
.
 extract_segment(first=0, last=None, enlarge=None)[source]¶
Return a (shallow) copy with extracted segment of MPS.
 Parameters
first (int) – See
extract_segment()
.last (int) – See
extract_segment()
.enlarge (int) – See
extract_segment()
.
 Returns
cp – A shallow copy of self with MPO and lattice extracted for the segment.
 Return type
 classmethod from_hdf5(hdf5_loader, h5gr, subpath)[source]¶
Load instance from a HDF5 file.
This method reconstructs a class instance from the data saved with
save_hdf5()
. Parameters
hdf5_loader (
Hdf5Loader
) – Instance of the loading engine.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__
withsave_dict_content()
, storing the format under the attribute'format'
.