Creating and manipulating Qbits#

import qse
import numpy as np

1. Create Qbits.#

A Qbits object can represent :

  • An arbitrary qubit layout.

  • A repeated structure.

Qbits objects can be created in different ways. Let’s see how it is done by performing providing some examples.

1.1. Specify the qubits positions.#

The first way of creating a Qbits object is by specifying the positions of their qubits in the cartesian coordinate system. With the labels parameter we are assigning a label to each qubit.

coords_1 = np.array([[0.76, 0, 0.58]])
coords_2 = np.array([[-0.76, 0, 0.58]])
coords_3 = np.array([[0, 0, 0]])
positions = np.concatenate((coords_1, coords_2, coords_3), axis=0)
qbits_1 = qse.Qbits(positions=positions, labels=["qbit1", "qbit2", "qbit3"])

1.2. Specify the cell positions.#

We can also create a qbits object by inputting the unit cell coordinates into the cell argument. Let’s see an example for a cubic cell type. The scaled_positions argument is the position of the qubits, given in units of the unit cell.

cell = np.array(
    [[4.994, 0, 0], [0, 4.994, 0], [0, 0, 4.994]]
)  # cell is defined using coordinates.
scaled_positions = np.array([[0.0, 0.0, 0.0], [0.5, 0.5, 0.5]])
qbits_2 = qse.Qbits(cell=cell, scaled_positions=scaled_positions)

1.3. Specify the structure vectors and angles.#

We can use the lattice vectors $a_1$, $a_2$, $a_3$ and the angles $\alpha\angle a_2a_3$ , $\beta\angle a_1a_3$ , $\gamma\angle a_1a_2$, to define our cell instead of using its coordinates as we did before. Let’s see an example where:

$\alpha = \gamma = 90°, \beta = 112.48$, $a_1 = 5.87A$, $a_2 = 8.12A$, $a_3 = 7.45A$

a1 = 4.13
a2 = 4.13
a3 = 6.91
alpha = 90.00
beta = 90.00
gamma = 120.00
cell = [
    a1,
    a2,
    a3,
    alpha,
    beta,
    gamma,
]  # cell is defined using lattice vectors and angles
scaled_positions_1 = [0, 0, 0]
scaled_positions_2 = [0.33, 0.66, 0.25]
scaled_positions = np.array([scaled_positions_1, scaled_positions_2])
qbits_3 = qse.Qbits(cell=cell, scaled_positions=scaled_positions)

1.4. Add single Qbit objects.#

Single Qbit objects can be added to form a Qbits object. Let’s build again the Qbits object we saw in section 1.1 this way.

qbit_1 = qse.Qbit(position=coords_1.flatten().tolist())
qbit_2 = qse.Qbit(position=coords_2.flatten().tolist())
qbit_3 = qse.Qbit(position=coords_3.flatten().tolist())

qbits_4 = qse.Qbits()
qbits_4.extend(qbit_1)
qbits_4.extend(qbit_2)
qbits_4.extend(qbit_3)

2. Qbits methods.#

2.1. Draw qbits.#

After the cells are created, we can use the repeat method to generate repeated structure. The argument of repeat can be a sequence of three integers indicating the number of repetitions on each direction or a simple integer indicating equal repetition on each direction. Once the repeated structure is created, we can use the draw method to visualise it.

qbits_2 = qbits_2.repeat((3, 2, 2))
qbits_2.draw(radius="nearest")
../_images/11882681d1762efd80df1f460fda2bf1b016f47de16e61ed7e0245622297d7f9.png
qbits_3 = qbits_3.repeat(2)
qbits_3.draw(radius="nearest")
../_images/b3c1a79a65776fbf752675f351fc37478ba6b934e63ff8bc05fbe1784d639737.png

Our drawing function is also able to draw 2d structures. We can see an example of this in the cell below, that creates and draws a 2d Qbits object.

cell = np.array(
    [
        [1.0, 0.0, 0.0],
        [0.0, 1.0, 0.0],
        [0.0, 0.0, 0.0],
    ]
)

positions = np.array(
    [
        [0.0, 0.0, 0.0],
        [0.5, 0.0, 0.0],
        [0.0, 0.5, 0.0],
        [0.5, 0.5, 0.0],
    ]
)
qbits_5 = qse.Qbits(cell=cell, positions=positions)
qbits_5 = qbits_5.repeat((2, 2, 1))
qbits_5.draw(radius="nearest")
../_images/44b981a703bc26f959d81930125b4141c0ea75fff60383f9ce888015feda527b.png

2.2. Translate repeated structure.#

We can translate our repeated structures using the translate method, to which we can input an xyz vector that dictates how much the structure is translated in each direction.

qbits_2.translate((100, 1, 2))
qbits_2.draw(radius="nearest")
../_images/79eed8745f30fe1caf86d83e93cf0e9d7524a57c9c73d1e401c7202437320e9f.png

Translations of the structure can also be made using the set_centroid method, as we can see below.

qbits_2.set_centroid((1, 1, 100))
qbits_2.draw(radius="nearest")
../_images/e0498c24025a36ddc3128e43d934b9648d95877bdbbb9a55695ea9395278f76b.png

2.3. Rotate structures.#

One can use the method rotate to perform lattice rotations, specifying the angle and the axis along which the rotation will be performed.

qbits_3.rotate(45, v="x", rotate_cell=True)
qbits_3.draw(radius="nearest")
../_images/88d9ca10bc579b5810a3e8f460d3a774cbb6bee8fd6bdfbfea1ed2dbc3ded254.png

With the method euler_rotate we can rotate a lattice by inputting the angles $\phi$, $\theta$, $\psi$ in degrees, as shown below.

qbits_3.euler_rotate(30, 80, 70)
qbits_3.draw(radius="nearest")
../_images/16c197f70c137e092b583f43efe07f412af6ad10cc374882d343d752cdf6565b.png