From 0685529d3325d1a79d77e492b4c03627156a33de Mon Sep 17 00:00:00 2001 From: ddhawan11 Date: Fri, 6 Sep 2024 13:05:18 -0400 Subject: [PATCH 01/11] Added 3d models --- pennylane/spin/lattice.py | 91 ++++++++++++++- tests/spin/test_lattice.py | 225 +++++++++++++++++++++++++++++++++++++ 2 files changed, 314 insertions(+), 2 deletions(-) diff --git a/pennylane/spin/lattice.py b/pennylane/spin/lattice.py index 84bae270698..e83983d0640 100644 --- a/pennylane/spin/lattice.py +++ b/pennylane/spin/lattice.py @@ -317,6 +317,73 @@ def _kagome(n_cells, boundary_condition=False, neighbour_order=1): return lattice_kagome +def _lieb(n_cells, boundary_condition=False, neighbour_order=1): + r"""Generates a lieb lattice""" + vectors = [[0, 1], [1, 0]] + positions = [[0, 0], [0.5, 0], [0, 0.5]] + + n_cells = n_cells[0:2] + lattice_lieb = Lattice( + n_cells=n_cells, + vectors=vectors, + positions=positions, + neighbour_order=neighbour_order, + boundary_condition=boundary_condition, + ) + + return lattice_lieb + + +def _cubic(n_cells, boundary_condition=False, neighbour_order=1): + r"""Generates a cubic lattice""" + vectors = math.eye(3) + + n_cells = n_cells[0:3] + lattice_cubic = Lattice( + n_cells=n_cells, + vectors=vectors, + neighbour_order=neighbour_order, + boundary_condition=boundary_condition, + ) + + return lattice_cubic + + +def _bcc(n_cells, boundary_condition=False, neighbour_order=1): + r"""Generates a body centered cubic lattice""" + vectors = math.eye(3) + positions = [[0, 0, 0], [0.5, 0.5, 0.5]] + + n_cells = n_cells[0:3] + lattice_bcc = Lattice( + n_cells=n_cells, + vectors=vectors, + positions=positions, + neighbour_order=neighbour_order, + boundary_condition=boundary_condition, + ) + print(lattice_bcc.edges) + + return lattice_bcc + + +def _fcc(n_cells, boundary_condition=False, neighbour_order=1): + r"""Generates a face centered cubic lattice""" + vectors = math.eye(3) + positions = [[0, 0, 0], [0.5, 0.5, 0.0], [0.5, 0, 0.5], [0.0, 0.5, 0.5]] + + n_cells = n_cells[0:3] + lattice_fcc = Lattice( + n_cells=n_cells, + vectors=vectors, + positions=positions, + neighbour_order=neighbour_order, + boundary_condition=boundary_condition, + ) + + return lattice_fcc + + # TODO Check the efficiency of this function with a dictionary instead. def _generate_lattice(lattice, n_cells, boundary_condition=False, neighbour_order=1): r"""Generates the lattice object for a given shape and n_cells. @@ -333,10 +400,22 @@ def _generate_lattice(lattice, n_cells, boundary_condition=False, neighbour_orde lattice_shape = lattice.strip().lower() - if lattice_shape not in ["chain", "square", "rectangle", "honeycomb", "triangle", "kagome"]: + if lattice_shape not in [ + "chain", + "square", + "rectangle", + "honeycomb", + "triangle", + "kagome", + "lieb", + "cubic", + "bcc", + "fcc", + ]: raise ValueError( f"Lattice shape, '{lattice}' is not supported." - f"Please set lattice to: chain, square, rectangle, honeycomb, triangle, or kagome" + f"Please set lattice to: chain, square, rectangle, honeycomb, triangle, kagome, lieb," + f"cubic, bcc or fcc." ) if lattice_shape == "chain": @@ -351,5 +430,13 @@ def _generate_lattice(lattice, n_cells, boundary_condition=False, neighbour_orde lattice = _triangle(n_cells, boundary_condition, neighbour_order) elif lattice_shape == "kagome": lattice = _kagome(n_cells, boundary_condition, neighbour_order) + elif lattice_shape == "lieb": + lattice = _lieb(n_cells, boundary_condition, neighbour_order) + elif lattice_shape == "cubic": + lattice = _cubic(n_cells, boundary_condition, neighbour_order) + elif lattice_shape == "bcc": + lattice = _bcc(n_cells, boundary_condition, neighbour_order) + elif lattice_shape == "fcc": + lattice = _fcc(n_cells, boundary_condition, neighbour_order) return lattice diff --git a/tests/spin/test_lattice.py b/tests/spin/test_lattice.py index 6576a396f3d..ad5eaeba349 100644 --- a/tests/spin/test_lattice.py +++ b/tests/spin/test_lattice.py @@ -525,6 +525,231 @@ def test_add_edge(): (8, 9, 0), ], ), + ( + "LIEB", + [2, 2], + [ + (0, 1, 0), + (0, 2, 0), + (1, 3, 0), + (2, 6, 0), + (3, 4, 0), + (3, 5, 0), + (5, 9, 0), + (6, 7, 0), + (6, 8, 0), + (7, 9, 0), + (9, 10, 0), + (9, 11, 0), + ], + ), + ( + " cubic", + [3, 3, 3], + [ + (0, 1, 0), + (0, 3, 0), + (0, 9, 0), + (1, 2, 0), + (1, 4, 0), + (1, 10, 0), + (2, 5, 0), + (2, 11, 0), + (3, 4, 0), + (3, 6, 0), + (3, 12, 0), + (4, 5, 0), + (4, 7, 0), + (4, 13, 0), + (5, 8, 0), + (5, 14, 0), + (6, 7, 0), + (6, 15, 0), + (7, 8, 0), + (7, 16, 0), + (8, 17, 0), + (9, 10, 0), + (9, 12, 0), + (9, 18, 0), + (10, 11, 0), + (10, 13, 0), + (10, 19, 0), + (11, 14, 0), + (11, 20, 0), + (12, 13, 0), + (12, 15, 0), + (12, 21, 0), + (13, 14, 0), + (13, 16, 0), + (13, 22, 0), + (14, 17, 0), + (14, 23, 0), + (15, 16, 0), + (15, 24, 0), + (16, 17, 0), + (16, 25, 0), + (17, 26, 0), + (18, 19, 0), + (18, 21, 0), + (19, 20, 0), + (19, 22, 0), + (20, 23, 0), + (21, 22, 0), + (21, 24, 0), + (22, 23, 0), + (22, 25, 0), + (23, 26, 0), + (24, 25, 0), + (25, 26, 0), + ], + ), + ( + "BCC", + [2, 2, 2], + [ + (0, 1, 0), + (1, 2, 0), + (1, 4, 0), + (1, 6, 0), + (1, 8, 0), + (1, 10, 0), + (1, 12, 0), + (1, 14, 0), + (2, 3, 0), + (3, 6, 0), + (3, 10, 0), + (3, 14, 0), + (4, 5, 0), + (5, 6, 0), + (5, 12, 0), + (5, 14, 0), + (6, 7, 0), + (7, 14, 0), + (8, 9, 0), + (9, 10, 0), + (9, 12, 0), + (9, 14, 0), + (10, 11, 0), + (11, 14, 0), + (12, 13, 0), + (13, 14, 0), + (14, 15, 0), + ], + ), + ( + "FCC", + [2, 2, 2], + [ + (0, 1, 0), + (0, 2, 0), + (0, 3, 0), + (1, 2, 0), + (1, 3, 0), + (1, 8, 0), + (1, 10, 0), + (1, 16, 0), + (1, 19, 0), + (1, 24, 0), + (2, 3, 0), + (2, 4, 0), + (2, 5, 0), + (2, 16, 0), + (2, 19, 0), + (2, 20, 0), + (3, 4, 0), + (3, 5, 0), + (3, 8, 0), + (3, 10, 0), + (3, 12, 0), + (4, 5, 0), + (4, 6, 0), + (4, 7, 0), + (5, 6, 0), + (5, 7, 0), + (5, 10, 0), + (5, 12, 0), + (5, 14, 0), + (5, 19, 0), + (5, 20, 0), + (5, 23, 0), + (5, 28, 0), + (6, 7, 0), + (6, 20, 0), + (6, 23, 0), + (7, 12, 0), + (7, 14, 0), + (8, 9, 0), + (8, 10, 0), + (8, 11, 0), + (9, 10, 0), + (9, 11, 0), + (9, 24, 0), + (9, 27, 0), + (10, 11, 0), + (10, 12, 0), + (10, 13, 0), + (10, 19, 0), + (10, 24, 0), + (10, 27, 0), + (10, 28, 0), + (11, 12, 0), + (11, 13, 0), + (12, 13, 0), + (12, 14, 0), + (12, 15, 0), + (13, 14, 0), + (13, 15, 0), + (13, 27, 0), + (13, 28, 0), + (13, 31, 0), + (14, 15, 0), + (14, 23, 0), + (14, 28, 0), + (14, 31, 0), + (16, 17, 0), + (16, 18, 0), + (16, 19, 0), + (17, 18, 0), + (17, 19, 0), + (17, 24, 0), + (17, 26, 0), + (18, 19, 0), + (18, 20, 0), + (18, 21, 0), + (19, 20, 0), + (19, 21, 0), + (19, 24, 0), + (19, 26, 0), + (19, 28, 0), + (20, 21, 0), + (20, 22, 0), + (20, 23, 0), + (21, 22, 0), + (21, 23, 0), + (21, 26, 0), + (21, 28, 0), + (21, 30, 0), + (22, 23, 0), + (23, 28, 0), + (23, 30, 0), + (24, 25, 0), + (24, 26, 0), + (24, 27, 0), + (25, 26, 0), + (25, 27, 0), + (26, 27, 0), + (26, 28, 0), + (26, 29, 0), + (27, 28, 0), + (27, 29, 0), + (28, 29, 0), + (28, 30, 0), + (28, 31, 0), + (29, 30, 0), + (29, 31, 0), + (30, 31, 0), + ], + ), ], ) def test_edges_for_shapes(shape, n_cells, expected_edges): From 799351c63c90e07e7c7425151c25ded56498d181 Mon Sep 17 00:00:00 2001 From: ddhawan11 Date: Tue, 10 Sep 2024 12:25:47 -0400 Subject: [PATCH 02/11] Changed to dictionary format for shapes --- pennylane/spin/lattice.py | 225 ++++++-------------------------------- 1 file changed, 31 insertions(+), 194 deletions(-) diff --git a/pennylane/spin/lattice.py b/pennylane/spin/lattice.py index e83983d0640..c80ccebcc2f 100644 --- a/pennylane/spin/lattice.py +++ b/pennylane/spin/lattice.py @@ -125,9 +125,6 @@ def _identify_neighbours(self, cutoff): tree = KDTree(self.lattice_points) indices = tree.query_ball_tree(tree, cutoff) - # Number to scale the distance, needed to sort edges into appropriate bins, it is currently - # set as a multiple of expected denominators. - bin_density = 2 ^ 5 * 3 ^ 3 * 5 ^ 2 * 7 * 11 * 13 unique_pairs = set() edges = {} for i, neighbours in enumerate(indices): @@ -139,11 +136,11 @@ def _identify_neighbours(self, cutoff): dist = math.linalg.norm( self.lattice_points[i] - self.lattice_points[neighbour] ) - scaled_dist = math.rint(dist * bin_density) + dist = math.round(dist, 4) - if scaled_dist not in edges: - edges[scaled_dist] = [] - edges[scaled_dist].append((i, neighbour)) + if dist not in edges: + edges[dist] = [] + edges[dist].append((i, neighbour)) edges = [value for _, value in sorted(edges.items())] return edges @@ -220,171 +217,6 @@ def add_edge(self, edge_indices): self.edges.append(new_edge) -def _chain(n_cells, boundary_condition=False, neighbour_order=1): - r"""Generates a chain lattice""" - vectors = [[1]] - n_cells = n_cells[0:1] - lattice_chain = Lattice( - n_cells=n_cells, - vectors=vectors, - neighbour_order=neighbour_order, - boundary_condition=boundary_condition, - ) - return lattice_chain - - -def _square(n_cells, boundary_condition=False, neighbour_order=1): - r"""Generates a square lattice""" - vectors = [[1, 0], [0, 1]] - positions = [[0, 0]] - n_cells = n_cells[0:2] - lattice_square = Lattice( - n_cells=n_cells, - vectors=vectors, - positions=positions, - neighbour_order=neighbour_order, - boundary_condition=boundary_condition, - ) - - return lattice_square - - -def _rectangle(n_cells, boundary_condition=False, neighbour_order=1): - r"""Generates a rectangle lattice""" - vectors = [[1, 0], [0, 1]] - positions = [[0, 0]] - - n_cells = n_cells[0:2] - lattice_rec = Lattice( - n_cells=n_cells, - vectors=vectors, - positions=positions, - neighbour_order=neighbour_order, - boundary_condition=boundary_condition, - ) - - return lattice_rec - - -def _honeycomb(n_cells, boundary_condition=False, neighbour_order=1): - r"""Generates a honeycomb lattice""" - vectors = [[1, 0], [0.5, math.sqrt(3) / 2]] - positions = [[0, 0], [0.5, 0.5 / 3**0.5]] - - n_cells = n_cells[0:2] - lattice_honeycomb = Lattice( - n_cells=n_cells, - vectors=vectors, - positions=positions, - neighbour_order=neighbour_order, - boundary_condition=boundary_condition, - ) - - return lattice_honeycomb - - -def _triangle(n_cells, boundary_condition=False, neighbour_order=1): - r"""Generates a triangular lattice""" - vectors = [[1, 0], [0.5, math.sqrt(3) / 2]] - positions = [[0, 0]] - - n_cells = n_cells[0:2] - lattice_triangle = Lattice( - n_cells=n_cells, - vectors=vectors, - positions=positions, - neighbour_order=neighbour_order, - boundary_condition=boundary_condition, - ) - - return lattice_triangle - - -def _kagome(n_cells, boundary_condition=False, neighbour_order=1): - r"""Generates a kagome lattice""" - vectors = [[1, 0], [0.5, math.sqrt(3) / 2]] - positions = [[0.0, 0], [-0.25, math.sqrt(3) / 4], [0.25, math.sqrt(3) / 4]] - - n_cells = n_cells[0:2] - lattice_kagome = Lattice( - n_cells=n_cells, - vectors=vectors, - positions=positions, - neighbour_order=neighbour_order, - boundary_condition=boundary_condition, - ) - - return lattice_kagome - - -def _lieb(n_cells, boundary_condition=False, neighbour_order=1): - r"""Generates a lieb lattice""" - vectors = [[0, 1], [1, 0]] - positions = [[0, 0], [0.5, 0], [0, 0.5]] - - n_cells = n_cells[0:2] - lattice_lieb = Lattice( - n_cells=n_cells, - vectors=vectors, - positions=positions, - neighbour_order=neighbour_order, - boundary_condition=boundary_condition, - ) - - return lattice_lieb - - -def _cubic(n_cells, boundary_condition=False, neighbour_order=1): - r"""Generates a cubic lattice""" - vectors = math.eye(3) - - n_cells = n_cells[0:3] - lattice_cubic = Lattice( - n_cells=n_cells, - vectors=vectors, - neighbour_order=neighbour_order, - boundary_condition=boundary_condition, - ) - - return lattice_cubic - - -def _bcc(n_cells, boundary_condition=False, neighbour_order=1): - r"""Generates a body centered cubic lattice""" - vectors = math.eye(3) - positions = [[0, 0, 0], [0.5, 0.5, 0.5]] - - n_cells = n_cells[0:3] - lattice_bcc = Lattice( - n_cells=n_cells, - vectors=vectors, - positions=positions, - neighbour_order=neighbour_order, - boundary_condition=boundary_condition, - ) - print(lattice_bcc.edges) - - return lattice_bcc - - -def _fcc(n_cells, boundary_condition=False, neighbour_order=1): - r"""Generates a face centered cubic lattice""" - vectors = math.eye(3) - positions = [[0, 0, 0], [0.5, 0.5, 0.0], [0.5, 0, 0.5], [0.0, 0.5, 0.5]] - - n_cells = n_cells[0:3] - lattice_fcc = Lattice( - n_cells=n_cells, - vectors=vectors, - positions=positions, - neighbour_order=neighbour_order, - boundary_condition=boundary_condition, - ) - - return lattice_fcc - - -# TODO Check the efficiency of this function with a dictionary instead. def _generate_lattice(lattice, n_cells, boundary_condition=False, neighbour_order=1): r"""Generates the lattice object for a given shape and n_cells. @@ -418,25 +250,30 @@ def _generate_lattice(lattice, n_cells, boundary_condition=False, neighbour_orde f"cubic, bcc or fcc." ) - if lattice_shape == "chain": - lattice = _chain(n_cells, boundary_condition, neighbour_order) - elif lattice_shape == "square": - lattice = _square(n_cells, boundary_condition, neighbour_order) - elif lattice_shape == "rectangle": - lattice = _rectangle(n_cells, boundary_condition, neighbour_order) - elif lattice_shape == "honeycomb": - lattice = _honeycomb(n_cells, boundary_condition, neighbour_order) - elif lattice_shape == "triangle": - lattice = _triangle(n_cells, boundary_condition, neighbour_order) - elif lattice_shape == "kagome": - lattice = _kagome(n_cells, boundary_condition, neighbour_order) - elif lattice_shape == "lieb": - lattice = _lieb(n_cells, boundary_condition, neighbour_order) - elif lattice_shape == "cubic": - lattice = _cubic(n_cells, boundary_condition, neighbour_order) - elif lattice_shape == "bcc": - lattice = _bcc(n_cells, boundary_condition, neighbour_order) - elif lattice_shape == "fcc": - lattice = _fcc(n_cells, boundary_condition, neighbour_order) - - return lattice + lattice_dict={ + "chain":{"dim":1, "vectors":[[1]], "positions":None}, + "square":{"dim":2, "vectors":[[0,1],[1,0]], "positions":None}, + "rectangle":{"dim":2, "vectors":[[0,1], [1,0]], "positions":None}, + "triangle":{"dim":2, "vectors":[[1, 0], [0.5, math.sqrt(3) / 2]], "positions":None}, + "honeycomb":{"dim":2, "vectors":[[1, 0], [0.5, math.sqrt(3) / 2]], + "positions":[[0, 0], [0.5, 0.5 / 3**0.5]]}, + "kagome":{"dim":2, "vectors":[[1, 0], [0.5, math.sqrt(3) / 2]], + "positions":[[0.0, 0], [-0.25, math.sqrt(3) / 4], [0.25, math.sqrt(3) / 4]]}, + "lieb":{"dim":2, "vectors":[[0, 1], [1, 0]], + "positions":[[0, 0], [0.5, 0], [0, 0.5]]}, + "cubic":{"dim":3, "vectors":math.eye(3), + "positions":None}, + "bcc":{"dim":3, "vectors":math.eye(3), + "positions":[[0, 0, 0], [0.5, 0.5, 0.5]]}, + "fcc":{"dim":3, "vectors":math.eye(3), + "positions":[[0, 0, 0], [0.5, 0.5, 0], [0.5, 0, 0.5], [0, 0.5, 0.5]]}, + } + + lattice_obj = Lattice( + n_cells=n_cells[0:lattice_dict[lattice_shape]["dim"]], + vectors=lattice_dict[lattice_shape]["vectors"], + positions=lattice_dict[lattice_shape]["positions"], + neighbour_order=neighbour_order, + boundary_condition=boundary_condition, + ) + return lattice_obj From 3b5f4ed4f6a7faa9ec5b97ac5252018e1a2fef7e Mon Sep 17 00:00:00 2001 From: ddhawan11 Date: Tue, 10 Sep 2024 12:26:00 -0400 Subject: [PATCH 03/11] Changed to dictionary format for shapes --- pennylane/spin/lattice.py | 44 ++++++++++++++++++++++----------------- 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/pennylane/spin/lattice.py b/pennylane/spin/lattice.py index c80ccebcc2f..9c6025fc938 100644 --- a/pennylane/spin/lattice.py +++ b/pennylane/spin/lattice.py @@ -250,27 +250,33 @@ def _generate_lattice(lattice, n_cells, boundary_condition=False, neighbour_orde f"cubic, bcc or fcc." ) - lattice_dict={ - "chain":{"dim":1, "vectors":[[1]], "positions":None}, - "square":{"dim":2, "vectors":[[0,1],[1,0]], "positions":None}, - "rectangle":{"dim":2, "vectors":[[0,1], [1,0]], "positions":None}, - "triangle":{"dim":2, "vectors":[[1, 0], [0.5, math.sqrt(3) / 2]], "positions":None}, - "honeycomb":{"dim":2, "vectors":[[1, 0], [0.5, math.sqrt(3) / 2]], - "positions":[[0, 0], [0.5, 0.5 / 3**0.5]]}, - "kagome":{"dim":2, "vectors":[[1, 0], [0.5, math.sqrt(3) / 2]], - "positions":[[0.0, 0], [-0.25, math.sqrt(3) / 4], [0.25, math.sqrt(3) / 4]]}, - "lieb":{"dim":2, "vectors":[[0, 1], [1, 0]], - "positions":[[0, 0], [0.5, 0], [0, 0.5]]}, - "cubic":{"dim":3, "vectors":math.eye(3), - "positions":None}, - "bcc":{"dim":3, "vectors":math.eye(3), - "positions":[[0, 0, 0], [0.5, 0.5, 0.5]]}, - "fcc":{"dim":3, "vectors":math.eye(3), - "positions":[[0, 0, 0], [0.5, 0.5, 0], [0.5, 0, 0.5], [0, 0.5, 0.5]]}, - } + lattice_dict = { + "chain": {"dim": 1, "vectors": [[1]], "positions": None}, + "square": {"dim": 2, "vectors": [[0, 1], [1, 0]], "positions": None}, + "rectangle": {"dim": 2, "vectors": [[0, 1], [1, 0]], "positions": None}, + "triangle": {"dim": 2, "vectors": [[1, 0], [0.5, math.sqrt(3) / 2]], "positions": None}, + "honeycomb": { + "dim": 2, + "vectors": [[1, 0], [0.5, math.sqrt(3) / 2]], + "positions": [[0, 0], [0.5, 0.5 / 3**0.5]], + }, + "kagome": { + "dim": 2, + "vectors": [[1, 0], [0.5, math.sqrt(3) / 2]], + "positions": [[0.0, 0], [-0.25, math.sqrt(3) / 4], [0.25, math.sqrt(3) / 4]], + }, + "lieb": {"dim": 2, "vectors": [[0, 1], [1, 0]], "positions": [[0, 0], [0.5, 0], [0, 0.5]]}, + "cubic": {"dim": 3, "vectors": math.eye(3), "positions": None}, + "bcc": {"dim": 3, "vectors": math.eye(3), "positions": [[0, 0, 0], [0.5, 0.5, 0.5]]}, + "fcc": { + "dim": 3, + "vectors": math.eye(3), + "positions": [[0, 0, 0], [0.5, 0.5, 0], [0.5, 0, 0.5], [0, 0.5, 0.5]], + }, + } lattice_obj = Lattice( - n_cells=n_cells[0:lattice_dict[lattice_shape]["dim"]], + n_cells=n_cells[0 : lattice_dict[lattice_shape]["dim"]], vectors=lattice_dict[lattice_shape]["vectors"], positions=lattice_dict[lattice_shape]["positions"], neighbour_order=neighbour_order, From 024f072d0550138a7c39263d2a0b06c9ef35f7b9 Mon Sep 17 00:00:00 2001 From: ddhawan11 Date: Tue, 10 Sep 2024 12:34:33 -0400 Subject: [PATCH 04/11] Updated changelog --- doc/releases/changelog-dev.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/doc/releases/changelog-dev.md b/doc/releases/changelog-dev.md index 813ee6374e4..fa9458acb34 100644 --- a/doc/releases/changelog-dev.md +++ b/doc/releases/changelog-dev.md @@ -4,6 +4,7 @@

New features since last release

+

Improvements 🛠

* Improve unit testing for capturing of nested control flows. @@ -17,6 +18,9 @@ unique representation of the object. [(#6167)](https://github.com/PennyLaneAI/pennylane/pull/6167) +* More predefined lattice shapes can now be generated. + [(6237)](https://github.com/PennyLaneAI/pennylane/pull/6237) +

Breaking changes 💔

* `qml.transforms.hamiltonian_expand` and `qml.transforms.sum_expand` are removed. From 0c9a86a824515f4a24b11c8731a280d20269d48f Mon Sep 17 00:00:00 2001 From: ddhawan11 Date: Tue, 10 Sep 2024 12:45:17 -0400 Subject: [PATCH 05/11] minor docstring fixes --- pennylane/spin/lattice.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/pennylane/spin/lattice.py b/pennylane/spin/lattice.py index 9c6025fc938..eb77dfcaedd 100644 --- a/pennylane/spin/lattice.py +++ b/pennylane/spin/lattice.py @@ -35,10 +35,10 @@ class Lattice: positions (list[list[float]]): Initial positions of spin cites. Default value is ``[[0.0]`` :math:`\times` ``number of dimensions]``. - boundary_condition (bool or list[bool]): Defines boundary conditions in different lattice axes, - default is ``False`` indicating open boundary condition. + boundary_condition (bool or list[bool]): Defines boundary conditions in different lattice axes. + Default is ``False`` indicating open boundary condition. neighbour_order (int): Specifies the interaction level for neighbors within the lattice. - Default is 1 (nearest neighbour). + Default is 1, indicating nearest neighbour. distance_tol (float): Distance below which spatial points are considered equal for the purpose of identifying nearest neighbours. Default value is 1e-5. @@ -221,10 +221,13 @@ def _generate_lattice(lattice, n_cells, boundary_condition=False, neighbour_orde r"""Generates the lattice object for a given shape and n_cells. Args: - lattice (str): Shape of the lattice. Input Values can be ``'chain'``, ``'square'``, ``'rectangle'``, ``'honeycomb'``, ``'triangle'``, or ``'kagome'``. + lattice (str): Shape of the lattice. Input Values can be ``'chain'``, ``'square'``, ``'rectangle'``, + ``'honeycomb'``, ``'triangle'``, ``'kagome'``, ``'lieb'``, ``'cubic'``, ``'bcc'``, or ``'fcc'``. n_cells (list[int]): Number of cells in each direction of the grid. - boundary_condition (bool or list[bool]): Defines boundary conditions, False for open boundary condition, each element represents the axis for lattice. It defaults to False. - neighbour_order (int): Specifies the interaction level for neighbors within the lattice. Default is 1 (nearest neighbour). + boundary_condition (bool or list[bool]): Defines boundary conditions in different lattice axes. + Default is ``False`` indicating open boundary condition. + neighbour_order (int): Specifies the interaction level for neighbors within the lattice. + Default is 1, indicating nearest neighbour. Returns: lattice object. From 2a19d6f609b0e4b160d9dd3276e7bc67a75f0832 Mon Sep 17 00:00:00 2001 From: ddhawan11 Date: Mon, 16 Sep 2024 08:49:02 -0400 Subject: [PATCH 06/11] Addressed comments --- doc/releases/changelog-dev.md | 2 +- pennylane/spin/lattice.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/releases/changelog-dev.md b/doc/releases/changelog-dev.md index f8b921ddec8..f4e1e63df95 100644 --- a/doc/releases/changelog-dev.md +++ b/doc/releases/changelog-dev.md @@ -50,7 +50,7 @@ unique representation of the object. [(#6167)](https://github.com/PennyLaneAI/pennylane/pull/6167) -* More predefined lattice shapes can now be generated. +* Predefined lattice shapes, lieb, cubic, bcc, and fcc, can now be generated. [(6237)](https://github.com/PennyLaneAI/pennylane/pull/6237) * The `to_mat` methods for `FermiWord` and `FermiSentence` now optionally return diff --git a/pennylane/spin/lattice.py b/pennylane/spin/lattice.py index eb77dfcaedd..6c5bc2c216a 100644 --- a/pennylane/spin/lattice.py +++ b/pennylane/spin/lattice.py @@ -249,8 +249,8 @@ def _generate_lattice(lattice, n_cells, boundary_condition=False, neighbour_orde ]: raise ValueError( f"Lattice shape, '{lattice}' is not supported." - f"Please set lattice to: chain, square, rectangle, honeycomb, triangle, kagome, lieb," - f"cubic, bcc or fcc." + f"Please set lattice to: 'chain', 'square', 'rectangle', 'honeycomb', 'triangle', 'kagome', 'lieb'," + f"'cubic', 'bcc' or 'fcc'." ) lattice_dict = { From 5d561135f15bd922751dffa4e2b71339a768d5d0 Mon Sep 17 00:00:00 2001 From: ddhawan11 Date: Mon, 16 Sep 2024 14:07:22 -0400 Subject: [PATCH 07/11] Added more tests --- tests/spin/test_lattice.py | 178 ++++++++++++++++++++++++++++++++++++- 1 file changed, 177 insertions(+), 1 deletion(-) diff --git a/tests/spin/test_lattice.py b/tests/spin/test_lattice.py index ad5eaeba349..900e4baa0aa 100644 --- a/tests/spin/test_lattice.py +++ b/tests/spin/test_lattice.py @@ -419,7 +419,6 @@ def test_add_edge(): lattice.add_edge(edge_indices) lattice.add_edge([[0, 2, 1]]) assert np.all(np.isin(edge_indices, lattice.edges)) - print(lattice.edges) assert np.all(np.isin([0, 2, 1], lattice.edges)) @@ -764,3 +763,180 @@ def test_shape_error(): lattice = "Octagon" with pytest.raises(ValueError, match="Lattice shape, 'Octagon' is not supported."): _generate_lattice(lattice=lattice, n_cells=n_cells) + + +@pytest.mark.parametrize( + ("shape", "n_cells", "expected_number"), + # expected_number here was obtained manually. + [ + ("fcc", [2, 2, 2], 32), + ("bcc", [2, 2, 2], 16), + ("kagome", [2, 2], 12), + ("lieb", [3, 3], 27), + ], +) +def test_num_sites_lattice_templates(shape, n_cells, expected_number): + r"""Test that the correct number of lattice points are generated for the given attributes""" + lattice = _generate_lattice(lattice=shape, n_cells=n_cells) + assert lattice.n_sites == expected_number + + +@pytest.mark.parametrize( + # expected_points here were calculated manually. + ("shape", "n_cells", "expected_points"), + [ + ( + "kagome", + [2, 2], + [ + [0, 0], + [-0.25, 0.4330127], + [0.25, 0.4330127], + [0.5, 0.8660254], + [0.25, 1.29903811], + [0.75, 1.29903811], + [1.0, 0.0], + [0.75, 0.4330127], + [1.25, 0.4330127], + [1.5, 0.8660254], + [1.25, 1.29903811], + [1.75, 1.29903811], + ], + ), + ( + "lieb", + [3, 3], + [ + [0, 0], + [0.5, 0], + [0, 0.5], + [1, 0], + [1.5, 0], + [1, 0.5], + [2, 0], + [2.5, 0], + [2, 0.5], + [0, 1], + [0.5, 1], + [0, 1.5], + [1, 1], + [1.5, 1], + [1, 1.5], + [2, 1], + [2.5, 1], + [2, 1.5], + [0, 2], + [0.5, 2], + [0, 2.5], + [1, 2], + [1.5, 2], + [1, 2.5], + [2, 2], + [2.5, 2], + [2, 2.5], + ], + ), + ( + "fcc", + [2, 2, 2], + [ + [0, 0, 0], + [0.5, 0.5, 0], + [0.5, 0, 0.5], + [0, 0.5, 0.5], + [0, 0, 1], + [0.5, 0.5, 1], + [0.5, 0, 1.5], + [0, 0.5, 1.5], + [0, 1, 0], + [0.5, 1.5, 0], + [0.5, 1, 0.5], + [0, 1.5, 0.5], + [0, 1, 1], + [0.5, 1.5, 1], + [0.5, 1, 1.5], + [0, 1.5, 1.5], + [1, 0, 0], + [1.5, 0.5, 0], + [1.5, 0, 0.5], + [1, 0.5, 0.5], + [1, 0, 1], + [1.5, 0.5, 1], + [1.5, 0, 1.5], + [1, 0.5, 1.5], + [1, 1, 0], + [1.5, 1.5, 0], + [1.5, 1, 0.5], + [1, 1.5, 0.5], + [1, 1, 1], + [1.5, 1.5, 1], + [1.5, 1, 1.5], + [1, 1.5, 1.5], + ], + ), + ( + "bcc", + [2, 2, 2], + [ + [ + 0, + 0, + 0, + ], + [0.5, 0.5, 0.5], + [0, 0, 1], + [0.5, 0.5, 1.5], + [0, 1, 0], + [0.5, 1.5, 0.5], + [0, 1, 1], + [0.5, 1.5, 1.5], + [1, 0, 0], + [1.5, 0.5, 0.5], + [1, 0, 1], + [1.5, 0.5, 1.5], + [1, 1, 0], + [1.5, 1.5, 0.5], + [1, 1, 1], + [1.5, 1.5, 1.5], + ], + ), + ( + "cubic", + [3, 3, 3], + [ + [0, 0, 0], + [0, 0, 1], + [0, 0, 2], + [0, 1, 0], + [0, 1, 1], + [0, 1, 2], + [0, 2, 0], + [0, 2, 1], + [0, 2, 2], + [1, 0, 0], + [1, 0, 1], + [1, 0, 2], + [1, 1, 0], + [1, 1, 1], + [1, 1, 2], + [1, 2, 0], + [1, 2, 1], + [1, 2, 2], + [2, 0, 0], + [2, 0, 1], + [2, 0, 2], + [2, 1, 0], + [2, 1, 1], + [2, 1, 2], + [2, 2, 0], + [2, 2, 1], + [2, 2, 2], + ], + ), + ], +) +def test_lattice_points_templates(shape, n_cells, expected_points): + r"""Test that the correct lattice points are generated for a given template.""" + + lattice = _generate_lattice(lattice=shape, n_cells=n_cells) + assert np.allclose(expected_points, lattice.lattice_points) From 394cbd820f4a8cc614b77f039b99be3bd610856b Mon Sep 17 00:00:00 2001 From: Diksha Dhawan <40900030+ddhawan11@users.noreply.github.com> Date: Fri, 20 Sep 2024 08:00:47 -0400 Subject: [PATCH 08/11] Update doc/releases/changelog-dev.md Co-authored-by: Utkarsh --- doc/releases/changelog-dev.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/releases/changelog-dev.md b/doc/releases/changelog-dev.md index a34d76be0a1..f8ab0c0fe71 100644 --- a/doc/releases/changelog-dev.md +++ b/doc/releases/changelog-dev.md @@ -51,7 +51,7 @@ unique representation of the object. [(#6167)](https://github.com/PennyLaneAI/pennylane/pull/6167) -* Predefined lattice shapes, lieb, cubic, bcc, and fcc, can now be generated. +* Predefined lattice shapes such as `lieb`, `cubic`, `bcc`, and `fcc` can now be generated. [(6237)](https://github.com/PennyLaneAI/pennylane/pull/6237) * The `to_mat` methods for `FermiWord` and `FermiSentence` now optionally return From b446667842ceb0aa7112a7880a8d830f633b5d14 Mon Sep 17 00:00:00 2001 From: ddhawan11 Date: Fri, 20 Sep 2024 08:19:56 -0400 Subject: [PATCH 09/11] Added diamond lattice --- doc/releases/changelog-dev.md | 3 +- pennylane/spin/lattice.py | 11 +++++-- tests/spin/test_lattice.py | 57 ++++++++++++++++++++++++++++++++--- 3 files changed, 64 insertions(+), 7 deletions(-) diff --git a/doc/releases/changelog-dev.md b/doc/releases/changelog-dev.md index f8ab0c0fe71..7184825e793 100644 --- a/doc/releases/changelog-dev.md +++ b/doc/releases/changelog-dev.md @@ -51,7 +51,8 @@ unique representation of the object. [(#6167)](https://github.com/PennyLaneAI/pennylane/pull/6167) -* Predefined lattice shapes such as `lieb`, `cubic`, `bcc`, and `fcc` can now be generated. +* Predefined lattice shapes such as `lieb`, `cubic`, `bcc`, `fcc`, and `diamond` + can now be generated. [(6237)](https://github.com/PennyLaneAI/pennylane/pull/6237) * The `to_mat` methods for `FermiWord` and `FermiSentence` now optionally return diff --git a/pennylane/spin/lattice.py b/pennylane/spin/lattice.py index 6c5bc2c216a..92c54aa27de 100644 --- a/pennylane/spin/lattice.py +++ b/pennylane/spin/lattice.py @@ -222,7 +222,8 @@ def _generate_lattice(lattice, n_cells, boundary_condition=False, neighbour_orde Args: lattice (str): Shape of the lattice. Input Values can be ``'chain'``, ``'square'``, ``'rectangle'``, - ``'honeycomb'``, ``'triangle'``, ``'kagome'``, ``'lieb'``, ``'cubic'``, ``'bcc'``, or ``'fcc'``. + ``'honeycomb'``, ``'triangle'``, ``'kagome'``, ``'lieb'``, ``'cubic'``, ``'bcc'``, ``'fcc'``, + or ``'diamond'``. n_cells (list[int]): Number of cells in each direction of the grid. boundary_condition (bool or list[bool]): Defines boundary conditions in different lattice axes. Default is ``False`` indicating open boundary condition. @@ -246,11 +247,12 @@ def _generate_lattice(lattice, n_cells, boundary_condition=False, neighbour_orde "cubic", "bcc", "fcc", + "diamond", ]: raise ValueError( f"Lattice shape, '{lattice}' is not supported." f"Please set lattice to: 'chain', 'square', 'rectangle', 'honeycomb', 'triangle', 'kagome', 'lieb'," - f"'cubic', 'bcc' or 'fcc'." + f"'cubic', 'bcc', 'fcc', or 'diamond'." ) lattice_dict = { @@ -276,6 +278,11 @@ def _generate_lattice(lattice, n_cells, boundary_condition=False, neighbour_orde "vectors": math.eye(3), "positions": [[0, 0, 0], [0.5, 0.5, 0], [0.5, 0, 0.5], [0, 0.5, 0.5]], }, + "diamond": { + "dim": 3, + "vectors": [[0, 0.5, 0.5], [0.5, 0, 0.5], [0.5, 0.5, 0]], + "positions": [[0, 0, 0], [0.25, 0.25, 0.25]], + }, } lattice_obj = Lattice( diff --git a/tests/spin/test_lattice.py b/tests/spin/test_lattice.py index 900e4baa0aa..2cdc5915682 100644 --- a/tests/spin/test_lattice.py +++ b/tests/spin/test_lattice.py @@ -749,6 +749,32 @@ def test_add_edge(): (30, 31, 0), ], ), + ( + "Diamond", + [2, 2, 2], + [ + (0, 1, 0), + (1, 2, 0), + (1, 4, 0), + (1, 8, 0), + (2, 3, 0), + (3, 6, 0), + (3, 10, 0), + (4, 5, 0), + (5, 6, 0), + (5, 12, 0), + (6, 7, 0), + (7, 14, 0), + (8, 9, 0), + (9, 10, 0), + (9, 12, 0), + (10, 11, 0), + (11, 14, 0), + (12, 13, 0), + (13, 14, 0), + (14, 15, 0), + ], + ), ], ) def test_edges_for_shapes(shape, n_cells, expected_edges): @@ -766,19 +792,20 @@ def test_shape_error(): @pytest.mark.parametrize( - ("shape", "n_cells", "expected_number"), - # expected_number here was obtained manually. + ("shape", "n_cells", "expected_n_sites"), + # expected_n_sites here was obtained manually. [ ("fcc", [2, 2, 2], 32), ("bcc", [2, 2, 2], 16), ("kagome", [2, 2], 12), ("lieb", [3, 3], 27), + ("diamond", [2, 2, 2], 16), ], ) -def test_num_sites_lattice_templates(shape, n_cells, expected_number): +def test_num_sites_lattice_templates(shape, n_cells, expected_n_sites): r"""Test that the correct number of lattice points are generated for the given attributes""" lattice = _generate_lattice(lattice=shape, n_cells=n_cells) - assert lattice.n_sites == expected_number + assert lattice.n_sites == expected_n_sites @pytest.mark.parametrize( @@ -933,6 +960,28 @@ def test_num_sites_lattice_templates(shape, n_cells, expected_number): [2, 2, 2], ], ), + ( + "diamond", + [2, 2, 2], + [ + [0, 0, 0], + [0.25, 0.25, 0.25], + [0.5, 0.5, 0], + [0.75, 0.75, 0.25], + [0.5, 0, 0.5], + [0.75, 0.25, 0.75], + [1, 0.5, 0.5], + [1.25, 0.75, 0.75], + [0, 0.5, 0.5], + [0.25, 0.75, 0.75], + [0.5, 1, 0.5], + [0.75, 1.25, 0.75], + [0.5, 0.5, 1], + [0.75, 0.75, 1.25], + [1, 1, 1], + [1.25, 1.25, 1.25], + ], + ), ], ) def test_lattice_points_templates(shape, n_cells, expected_points): From d00db8adb49f0962f3f4c970ed04a38144598df7 Mon Sep 17 00:00:00 2001 From: ddhawan11 Date: Fri, 20 Sep 2024 09:47:59 -0400 Subject: [PATCH 10/11] Added error statement for wrong cell dimensions --- pennylane/spin/lattice.py | 9 ++++++++- tests/spin/test_lattice.py | 13 ++++++++++++- tests/spin/test_spin_hamiltonian.py | 30 ++++++++++++++--------------- 3 files changed, 35 insertions(+), 17 deletions(-) diff --git a/pennylane/spin/lattice.py b/pennylane/spin/lattice.py index 92c54aa27de..d43433a961c 100644 --- a/pennylane/spin/lattice.py +++ b/pennylane/spin/lattice.py @@ -285,8 +285,15 @@ def _generate_lattice(lattice, n_cells, boundary_condition=False, neighbour_orde }, } + lattice_dim = lattice_dict[lattice_shape]["dim"] + if len(n_cells) != lattice_dim: + raise ValueError( + f"Argument `n_cells` must be of the correct dimension for the given lattice shape." + f" {lattice_shape} lattice is of dimension {lattice_dim}, got {len(n_cells)}." + ) + lattice_obj = Lattice( - n_cells=n_cells[0 : lattice_dict[lattice_shape]["dim"]], + n_cells=n_cells, vectors=lattice_dict[lattice_shape]["vectors"], positions=lattice_dict[lattice_shape]["positions"], neighbour_order=neighbour_order, diff --git a/tests/spin/test_lattice.py b/tests/spin/test_lattice.py index 2cdc5915682..392dfa5af28 100644 --- a/tests/spin/test_lattice.py +++ b/tests/spin/test_lattice.py @@ -428,7 +428,7 @@ def test_add_edge(): [ ( "chAin ", - [10, 0, 0], + [10], [ (0, 1, 0), (1, 2, 0), @@ -791,6 +791,17 @@ def test_shape_error(): _generate_lattice(lattice=lattice, n_cells=n_cells) +def test_dimension_error(): + r"""Test that an error is raised if wrong dimension is provided for a given lattice shape.""" + n_cells = [5, 5, 5] + lattice = "square" + with pytest.raises( + ValueError, + match="Argument `n_cells` must be of the correct dimension for" " the given lattice shape.", + ): + _generate_lattice(lattice=lattice, n_cells=n_cells) + + @pytest.mark.parametrize( ("shape", "n_cells", "expected_n_sites"), # expected_n_sites here was obtained manually. diff --git a/tests/spin/test_spin_hamiltonian.py b/tests/spin/test_spin_hamiltonian.py index 929a7b2a32f..7a21c29eb0c 100644 --- a/tests/spin/test_spin_hamiltonian.py +++ b/tests/spin/test_spin_hamiltonian.py @@ -46,21 +46,21 @@ def test_coupling_error(): [ ( "chain", - [4, 0, 0], + [4], 1.0, 0, -1.0 * (Z(0) @ Z(1)) + -1.0 * (Z(1) @ Z(2)) + -1.0 * (Z(2) @ Z(3)), ), ( "chain", - [4, 0, 0], + [4], 1.0, 0, -1.0 * (Z(0) @ Z(1)) + -1.0 * (Z(1) @ Z(2)) + -1.0 * (Z(2) @ Z(3)), ), ( "chain", - [8, 0, 0], + [8], [1.0], -0.17676768, -1.0 * (Z(0) @ Z(1)) @@ -81,7 +81,7 @@ def test_coupling_error(): ), ( "rectangle", - [4, 2, 0], + [4, 2], [1.0], -0.25252525, -1.0 * (Z(0) @ Z(1)) @@ -105,7 +105,7 @@ def test_coupling_error(): ), ( "rectangle", - [8, 2, 0], + [8, 2], [1.0], -0.44444444, -1.0 * (Z(0) @ Z(1)) @@ -163,14 +163,14 @@ def test_ising_hamiltonian(shape, n_cells, j, h, expected_ham): [ ( "chain", - [4, 0, 0], + [4], [[0, 1, 0, 0], [1, 0, 1, 0], [0, 1, 0, 1], [0, 0, 1, 0]], 0, -1.0 * (Z(0) @ Z(1)) + -1.0 * (Z(1) @ Z(2)) + -1.0 * (Z(2) @ Z(3)), ), ( "square", - [2, 2, 0], + [2, 2], [[0, 0.5, 0.5, 0], [0.5, 0, 0, 0.5], [0.5, 0, 0, 0.5], [0, 0.5, 0.5, 0]], -1.0, -0.5 * (Z(0) @ Z(1)) @@ -210,7 +210,7 @@ def test_coupling_error_heisenberg(): [ ( "chain", - [4, 1, 1], + [4], None, 1.0 * (Z(0) @ Z(1)) + 1.0 * (Z(1) @ Z(2)) @@ -224,7 +224,7 @@ def test_coupling_error_heisenberg(): ), ( "chain", - [4, 1, 1], + [4], [[-1.0, -1.0, -0.16161616]], -0.16161616161616163 * (Z(0) @ Z(1)) + -0.16161616161616163 * (Z(1) @ Z(2)) @@ -264,7 +264,7 @@ def test_coupling_error_heisenberg(): ), ( "rectangle", - [4, 2, 1], + [4, 2], [[-1.0, -1.0, -0.08080808]], -0.08080808080808081 * (Z(0) @ Z(1)) + -0.08080808080808081 * (Z(0) @ Z(2)) @@ -299,7 +299,7 @@ def test_coupling_error_heisenberg(): ), ( "rectangle", - [8, 2, 1], + [8, 2], [[-1.0, -1.0, -0.12121212]], -0.12121212121212122 * (Z(0) @ Z(1)) + -0.12121212121212122 * (Z(0) @ Z(2)) @@ -401,7 +401,7 @@ def test_heisenberg_hamiltonian(shape, n_cells, j, expected_ham): ), ( "square", - [2, 2, 1], + [2, 2], [ [[0, 0.5, 0.5, 0], [0.5, 0, 0, 0.5], [0.5, 0, 0, 0.5], [0, 0.5, 0.5, 0]], [[0, 1.0, 1.0, 0], [1.0, 0, 0, 1.0], [1.0, 0, 0, 1.0], [0, 1.0, 1.0, 0]], @@ -493,7 +493,7 @@ def test_mapping_error_fermi_hubbard(): ), ( "chain", - [8, 0, 0], + [8], [-1.0], 0.0, 0.5 * (Y(0) @ Z(1) @ Y(2)) @@ -717,7 +717,7 @@ def test_fermi_hubbard_mapping(shape, n_cells, hopping, mapping, expected_ham): [ ( "chain", - [4, 0, 0], + [4], [[0, 1, 0, 0], [1, 0, 1, 0], [0, 1, 0, 1], [0, 0, 1, 0]], 0.1, -0.5 * (Y(0) @ Z(1) @ Y(2)) @@ -748,7 +748,7 @@ def test_fermi_hubbard_mapping(shape, n_cells, hopping, mapping, expected_ham): ), ( "square", - [2, 2, 0], + [2, 2], [[0, 0.5, 0.5, 0], [0.5, 0, 0, 0.5], [0.5, 0, 0, 0.5], [0, 0.5, 0.5, 0]], [-1.0, 0.0, 1.0, 0], -0.25 * (Y(0) @ Z(1) @ Y(2)) From 268b8a6aad6e872088e9b74e44d3ad3e89717c03 Mon Sep 17 00:00:00 2001 From: Diksha Dhawan <40900030+ddhawan11@users.noreply.github.com> Date: Fri, 20 Sep 2024 12:33:32 -0400 Subject: [PATCH 11/11] Update pennylane/spin/lattice.py Co-authored-by: Austin Huang <65315367+austingmhuang@users.noreply.github.com> --- pennylane/spin/lattice.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pennylane/spin/lattice.py b/pennylane/spin/lattice.py index d43433a961c..add00151143 100644 --- a/pennylane/spin/lattice.py +++ b/pennylane/spin/lattice.py @@ -221,7 +221,7 @@ def _generate_lattice(lattice, n_cells, boundary_condition=False, neighbour_orde r"""Generates the lattice object for a given shape and n_cells. Args: - lattice (str): Shape of the lattice. Input Values can be ``'chain'``, ``'square'``, ``'rectangle'``, + lattice (str): Shape of the lattice. Input values can be ``'chain'``, ``'square'``, ``'rectangle'``, ``'honeycomb'``, ``'triangle'``, ``'kagome'``, ``'lieb'``, ``'cubic'``, ``'bcc'``, ``'fcc'``, or ``'diamond'``. n_cells (list[int]): Number of cells in each direction of the grid.