diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 671ce0a1..8141ca88 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -25,6 +25,7 @@ Added - Single-Site DMRG with the :class:`~tenpy.algorithms.dmrg.SingleSiteDMRG`. - Example function in ``examples/c_tebd.py`` how to run TEBD with a model originally having next-nearest neighbors. - :meth:`~tenpy.networks.mps.MPS.increase_L` to allow increasing the unit cell of an MPS. +- Additional option ``order='folded'`` for the :class:`~tenpy.models.lattice.Chain`. Fixed ^^^^^ diff --git a/tenpy/models/lattice.py b/tenpy/models/lattice.py index efe5872a..c81ea460 100644 --- a/tenpy/models/lattice.py +++ b/tenpy/models/lattice.py @@ -441,12 +441,12 @@ def mps_lat_idx_fix_u(self, u=None): return mps_idx, self.order[mps_idx, :-1] def mps2lat_values(self, A, axes=0, u=None): - """reshape/reorder A to replace an MPS index by lattice indices. + """Reshape/reorder `A` to replace an MPS index by lattice indices. Parameters ---------- A : ndarray - some values. Must have ``A.shape[axes] = self.N_sites`` if `u` is ``None``, or + Some values. Must have ``A.shape[axes] = self.N_sites`` if `u` is ``None``, or ``A.shape[axes] = self.N_cells`` if `u` is an int. axes : (iterable of) int chooses the axis which should be replaced. @@ -458,7 +458,7 @@ def mps2lat_values(self, A, axes=0, u=None): Returns ------- res_A : ndarray - reshaped and reordered verions of A. Such that an MPS index `j` is replaced by + Reshaped and reordered verions of A. Such that an MPS index `j` is replaced by ``res_A[..., self.order, ...] = A[..., np.arange(self.N_sites), ...]`` Examples @@ -485,7 +485,7 @@ def mps2lat_values(self, A, axes=0, u=None): If the unit cell consists of different physical sites, an onsite operator might be defined only on one of the sites in the unit cell. Then you can use :meth:`mps_idx_fix_u` to get the indices of sites it is defined on, measure the operator on these sites, and use - the argument `u` of this function. say y + the argument `u` of this function. >>> u = 0 >>> idx_subset = lat.mps_idx_fix_u(u) @@ -1056,6 +1056,43 @@ def __init__(self, L, site, **kwargs): # and otherwise default values. SimpleLattice.__init__(self, [L], site, **kwargs) + def ordering(self, order): + """Provide possible orderings of the `N` lattice sites. + + The following orders are defined in this method compared to :meth:`Lattice.ordering`: + + ================== ============================================================ + `order` Resulting order + ================== ============================================================ + ``'default'`` ``0, 1, 2, 3, 4, ... ,L-1`` + ------------------ ------------------------------------------------------------ + ``'folded'`` ``0, L-1, 1, L-2, ... , L//2``. + This order might be usefull if you want to consider a + ring with periodic boundary conditions with a finite MPS: + It avoids the ultra-long range of the coupling from site + 0 to L present in the default order. + ================== ============================================================ + """ + if isinstance(order, str) and order == 'default' or order == 'folded': + (L, u) = self.shape + assert u == 1 + ordering = np.zeros([L, 2], dtype=np.intp) + if order == 'default': + ordering[:, 0] = np.arange(L, dtype=np.intp) + elif order == 'folded': + order = [] + for i in range(L // 2): + order.append(i) + order.append(L - i - 1) + if L % 2 == 1: + order.append(L // 2) + assert len(order) == L + ordering[:, 0] = np.array(order, dtype=np.intp) + else: + assert (False) # should not be possible + return ordering + return super().ordering(order) + class Ladder(Lattice): """A ladder coupling two chains. diff --git a/tests/test_lattice.py b/tests/test_lattice.py index 10bbde5a..c8e6e547 100644 --- a/tests/test_lattice.py +++ b/tests/test_lattice.py @@ -105,6 +105,15 @@ def test_number_nn(): def test_lattice_order(): s = site.SpinHalfSite('Sz') # yapf: disable + chain = lattice.Chain(4, s) + order_default = np.array([[0, 0], [1, 0], [2, 0], [3, 0]]) + npt.assert_equal(chain.order, order_default) + chain = lattice.Chain(4, s, order='folded') + order_folded = np.array([[0, 0], [3, 0], [1, 0], [2, 0]]) + npt.assert_equal(chain.order, order_folded) + chain = lattice.Chain(5, s, order='folded') + order_folded = np.array([[0, 0], [4, 0], [1, 0], [3, 0], [2, 0]]) + npt.assert_equal(chain.order, order_folded) square = lattice.Square(2, 2, s, order='default') order_default = np.array([[0, 0, 0], [0, 1, 0], [1, 0, 0], [1, 1, 0]]) npt.assert_equal(square.order, order_default)