Skip to content

Commit

Permalink
more 2d and 3d PBC functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
jcmgray committed Mar 28, 2024
1 parent cb8979c commit a5d2dc2
Show file tree
Hide file tree
Showing 7 changed files with 137 additions and 36 deletions.
20 changes: 20 additions & 0 deletions docs/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,14 @@ Release notes for `quimb`.
[`tn3d.contract_hotrg`](quimb.tensor.tensor_3d.TensorNetwork3D.contract_hotrg) and
the new function
[`tn3d.contract_ctmrg`](quimb.tensor.tensor_3d.TensorNetwork3D.contract_ctmrg).
- support PBC in
[`gen_2d_bonds`](quimb.tensor.tensor_2d.gen_2d_bonds) and
[`gen_3d_bonds`](quimb.tensor.tensor_3d.gen_3d_bonds), with ``cyclic`` kwarg.
- support PBC in
[`TN2D_rand_hidden_loop`](quimb.tensor.tensor_builder.TN2D_rand_hidden_loop)
and
[`TN3D_rand_hidden_loop`](quimb.tensor.tensor_builder.TN3D_rand_hidden_loop),
with ``cyclic`` kwarg.
- add [`tensor_network_apply_op_op`](quimb.tensor.tensor_arbgeom.tensor_network_apply_op_op)
for applying 'operator' TNs to 'operator' TNs.
- tweak [`tensor_network_apply_op_vec`](quimb.tensor.tensor_arbgeom.tensor_network_apply_op_vec)
Expand All @@ -26,6 +34,18 @@ Release notes for `quimb`.
method for applying 'operator' TNs to the lower indices of 'operator' TNs like $B \rightarrow B A$.
- add [`tnop.gate_sandwich_with_op_lazy`](quimb.tensor.tensor_arbgeom.TensorNetworkGenOperator.gate_sandwich_with_op_lazy)
method for applying 'operator' TNs to the upper and lower indices of 'operator' TNs like $B \rightarrow A B A^\dagger$.
- add `quimb.tensor.tensor_1d_compress` with functions for compressing generic
1D tensor networks (with arbitrary local structure) using various methods.
The methods are:

- The **'direct'** method: [`tensor_network_1d_compress_direct`](quimb.tensor.tensor_1d_compress.tensor_network_1d_compress_direct)
- The **'dm'** (density matrix) method: [`tensor_network_1d_compress_dm`](quimb.tensor.tensor_1d_compress.tensor_network_1d_compress_dm)
- The **'zipup'** method: [`tensor_network_1d_compress_zipup`](quimb.tensor.tensor_1d_compress.tensor_network_1d_compress_zipup)
- The **'zipup-first'** method: [`tensor_network_1d_compress_zipup_first`](quimb.tensor.tensor_1d_compress.tensor_network_1d_compress_zipup_first)
- The 1 and 2 site **'fit'** or sweeping method: [`tensor_network_1d_compress_fit`](quimb.tensor.tensor_1d_compress.tensor_network_1d_compress_fit)
- ... and some more niche methods for debugging and testing.

And can be accessed via the unified function [`tensor_network_1d_compress`](quimb.tensor.tensor_1d_compress.tensor_network_1d_compress).


(whats-new-1-7-3)=
Expand Down
34 changes: 32 additions & 2 deletions quimb/tensor/tensor_2d.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ def nearest_neighbors(coo):
return ((i - 1, j), (i, j - 1), (i, j + 1), (i + 1, j))


def gen_2d_bonds(Lx, Ly, steppers=None, coo_filter=None):
def gen_2d_bonds(Lx, Ly, steppers=None, coo_filter=None, cyclic=False):
"""Convenience function for tiling pairs of bond coordinates on a 2D
lattice given a function like ``lambda i, j: (i + 1, j + 1)``.
Expand Down Expand Up @@ -105,11 +105,27 @@ def gen_2d_bonds(Lx, Ly, steppers=None, coo_filter=None):
if callable(steppers):
steppers = (steppers,)

try:
cyclic_x, cyclic_y = cyclic
except (TypeError, ValueError):
cyclic_x = cyclic_y = cyclic

def _maybe_wrap_coo(w, Lw, cyclic):
if 0 <= w < Lw:
return w
if cyclic:
return w % Lw
return None

for i, j in product(range(Lx), range(Ly)):
if (coo_filter is None) or coo_filter(i, j):
for stepper in steppers:
i2, j2 = stepper(i, j)
if (0 <= i2 < Lx) and (0 <= j2 < Ly):

i2 = _maybe_wrap_coo(i2, Lx, cyclic_x)
j2 = _maybe_wrap_coo(j2, Ly, cyclic_y)

if (i2 is not None) and (j2 is not None):
yield (i, j), (i2, j2)


Expand Down Expand Up @@ -512,6 +528,7 @@ def gen_bond_coos(self):
self.Lx,
self.Ly,
steppers=[lambda i, j: (i, j + 1), lambda i, j: (i + 1, j)],
cyclic=(self.is_cyclic_x(), self.is_cyclic_y()),
)

def gen_horizontal_bond_coos(self):
Expand All @@ -522,6 +539,7 @@ def gen_horizontal_bond_coos(self):
steppers=[
lambda i, j: (i, j + 1),
],
cyclic=(self.is_cyclic_x(), self.is_cyclic_y()),
)

def gen_horizontal_even_bond_coos(self):
Expand All @@ -535,6 +553,7 @@ def gen_horizontal_even_bond_coos(self):
lambda i, j: (i, j + 1),
],
coo_filter=lambda i, j: j % 2 == 0,
cyclic=(self.is_cyclic_x(), self.is_cyclic_y()),
)

def gen_horizontal_odd_bond_coos(self):
Expand All @@ -548,6 +567,7 @@ def gen_horizontal_odd_bond_coos(self):
lambda i, j: (i, j + 1),
],
coo_filter=lambda i, j: j % 2 == 1,
cyclic=(self.is_cyclic_x(), self.is_cyclic_y()),
)

def gen_vertical_bond_coos(self):
Expand All @@ -558,6 +578,7 @@ def gen_vertical_bond_coos(self):
steppers=[
lambda i, j: (i + 1, j),
],
cyclic=(self.is_cyclic_x(), self.is_cyclic_y()),
)

def gen_vertical_even_bond_coos(self):
Expand All @@ -571,6 +592,7 @@ def gen_vertical_even_bond_coos(self):
lambda i, j: (i + 1, j),
],
coo_filter=lambda i, j: i % 2 == 0,
cyclic=(self.is_cyclic_x(), self.is_cyclic_y()),
)

def gen_vertical_odd_bond_coos(self):
Expand All @@ -584,6 +606,7 @@ def gen_vertical_odd_bond_coos(self):
lambda i, j: (i + 1, j),
],
coo_filter=lambda i, j: i % 2 == 1,
cyclic=(self.is_cyclic_x(), self.is_cyclic_y()),
)

def gen_diagonal_left_bond_coos(self):
Expand All @@ -594,6 +617,7 @@ def gen_diagonal_left_bond_coos(self):
steppers=[
lambda i, j: (i + 1, j - 1),
],
cyclic=(self.is_cyclic_x(), self.is_cyclic_y()),
)

def gen_diagonal_left_even_bond_coos(self):
Expand All @@ -607,6 +631,7 @@ def gen_diagonal_left_even_bond_coos(self):
lambda i, j: (i + 1, j - 1),
],
coo_filter=lambda i, j: j % 2 == 0,
cyclic=(self.is_cyclic_x(), self.is_cyclic_y()),
)

def gen_diagonal_left_odd_bond_coos(self):
Expand All @@ -620,6 +645,7 @@ def gen_diagonal_left_odd_bond_coos(self):
lambda i, j: (i + 1, j - 1),
],
coo_filter=lambda i, j: j % 2 == 1,
cyclic=(self.is_cyclic_x(), self.is_cyclic_y()),
)

def gen_diagonal_right_bond_coos(self):
Expand All @@ -630,6 +656,7 @@ def gen_diagonal_right_bond_coos(self):
steppers=[
lambda i, j: (i + 1, j + 1),
],
cyclic=(self.is_cyclic_x(), self.is_cyclic_y()),
)

def gen_diagonal_right_even_bond_coos(self):
Expand All @@ -643,6 +670,7 @@ def gen_diagonal_right_even_bond_coos(self):
lambda i, j: (i + 1, j + 1),
],
coo_filter=lambda i, j: i % 2 == 0,
cyclic=(self.is_cyclic_x(), self.is_cyclic_y()),
)

def gen_diagonal_right_odd_bond_coos(self):
Expand All @@ -656,6 +684,7 @@ def gen_diagonal_right_odd_bond_coos(self):
lambda i, j: (i + 1, j + 1),
],
coo_filter=lambda i, j: i % 2 == 1,
cyclic=(self.is_cyclic_x(), self.is_cyclic_y()),
)

def gen_diagonal_bond_coos(self):
Expand All @@ -667,6 +696,7 @@ def gen_diagonal_bond_coos(self):
lambda i, j: (i + 1, j - 1),
lambda i, j: (i + 1, j + 1),
],
cyclic=(self.is_cyclic_x(), self.is_cyclic_y()),
)

def valid_coo(self, coo, xrange=None, yrange=None):
Expand Down
6 changes: 3 additions & 3 deletions quimb/tensor/tensor_2d_tebd.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,12 +59,12 @@ class LocalHam2D(LocalHamGen):
"""

def __init__(self, Lx, Ly, H2, H1=None):
def __init__(self, Lx, Ly, H2, H1=None, cyclic=False):
self.Lx = int(Lx)
self.Ly = int(Ly)

# parse two site terms
if hasattr(H2, 'shape'):
if hasattr(H2, "shape"):
# use as default nearest neighbour term
H2 = {None: H2}
else:
Expand All @@ -76,7 +76,7 @@ def __init__(self, Lx, Ly, H2, H1=None):
for coo_a, coo_b in gen_2d_bonds(Lx, Ly, steppers=[
lambda i, j: (i, j + 1),
lambda i, j: (i + 1, j),
]):
], cyclic=cyclic):
if (coo_a, coo_b) not in H2 and (coo_b, coo_a) not in H2:
H2[coo_a, coo_b] = default_H2

Expand Down
26 changes: 24 additions & 2 deletions quimb/tensor/tensor_3d.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
)


def gen_3d_bonds(Lx, Ly, Lz, steppers=None, coo_filter=None):
def gen_3d_bonds(Lx, Ly, Lz, steppers=None, coo_filter=None, cyclic=False):
"""Convenience function for tiling pairs of bond coordinates on a 3D
lattice given a function like ``lambda i, j, k: (i + 1, j + 1, k + 1)``.
Expand Down Expand Up @@ -85,11 +85,28 @@ def gen_3d_bonds(Lx, Ly, Lz, steppers=None, coo_filter=None):
if callable(steppers):
steppers = (steppers,)

try:
cyclic_x, cyclic_y, cyclic_z = cyclic
except (TypeError, ValueError):
cyclic_x = cyclic_y = cyclic_z = cyclic

def _maybe_wrap_coo(w, Lw, cyclic):
if 0 <= w < Lw:
return w
if cyclic:
return w % Lw
return None

for i, j, k in product(range(Lx), range(Ly), range(Lz)):
if (coo_filter is None) or coo_filter(i, j, k):
for stepper in steppers:
i2, j2, k2 = stepper(i, j, k)
if (0 <= i2 < Lx) and (0 <= j2 < Ly) and (0 <= k2 < Lz):

i2 = _maybe_wrap_coo(i2, Lx, cyclic_x)
j2 = _maybe_wrap_coo(j2, Ly, cyclic_y)
k2 = _maybe_wrap_coo(k2, Lz, cyclic_z)

if all(x is not None for x in (i2, j2, k2)):
yield (i, j, k), (i2, j2, k2)


Expand Down Expand Up @@ -604,6 +621,11 @@ def gen_bond_coos(self):
lambda i, j, k: (i, j + 1, k),
lambda i, j, k: (i, j, k + 1),
],
cyclic=(
self.is_cyclic_x(),
self.is_cyclic_y(),
self.is_cyclic_z(),
),
)

def valid_coo(self, coo, xrange=None, yrange=None, zrange=None):
Expand Down
27 changes: 15 additions & 12 deletions quimb/tensor/tensor_3d_tebd.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,17 @@
"""Tools for performing TEBD like algorithms on a 3D lattice.
"""
"""Tools for performing TEBD like algorithms on a 3D lattice."""

from .tensor_3d import gen_3d_bonds
from .tensor_arbgeom_tebd import LocalHamGen


class LocalHam3D(LocalHamGen):

def __init__(self, Lx, Ly, Lz, H2, H1=None):
def __init__(self, Lx, Ly, Lz, H2, H1=None, cyclic=False):
self.Lx = int(Lx)
self.Ly = int(Ly)
self.Lz = int(Lz)

# parse two site terms
if hasattr(H2, 'shape'):
if hasattr(H2, "shape"):
# use as default nearest neighbour term
H2 = {None: H2}
else:
Expand All @@ -22,20 +20,25 @@ def __init__(self, Lx, Ly, Lz, H2, H1=None):
# possibly fill in default gates
default_H2 = H2.pop(None, None)
if default_H2 is not None:
for coo_a, coo_b in gen_3d_bonds(Lx, Ly, Lz, steppers=[
lambda i, j, k: (i, j, k + 1),
lambda i, j, k: (i, j + 1, k),
lambda i, j, k: (i + 1, j, k),
]):
for coo_a, coo_b in gen_3d_bonds(
Lx,
Ly,
Lz,
steppers=[
lambda i, j, k: (i, j, k + 1),
lambda i, j, k: (i, j + 1, k),
lambda i, j, k: (i + 1, j, k),
],
cyclic=cyclic,
):
if (coo_a, coo_b) not in H2 and (coo_b, coo_a) not in H2:
H2[coo_a, coo_b] = default_H2

super().__init__(H2=H2, H1=H1)

@property
def nsites(self):
"""The number of sites in the system.
"""
"""The number of sites in the system."""
return self.Lx * self.Ly * self.Lz

def __repr__(self):
Expand Down
Loading

0 comments on commit a5d2dc2

Please sign in to comment.