Amplitude-Based Circuits#

This page documents the components that are used in algorithms that use the A mplitude B ased (AB) Encoding. At the moment, this includes two algorihtms:

  1. The “regular” Amplitude-Based Collisionless QLBM: ABQLBM,

  2. The Multi-Speed (MS) Collisionless QLBM: MSQLBM.

ABQLBM uses ABLattices and OHLattices, while MSQLBM is built from MSLattices. The general interface of CQLBM is built from all 3 lattice instances and delegeates to the appropriate implementation automatically.

Both algorithms are instances of the Collisionless QLBM (CQLBM), also known as the Quantum Transport Method (QTM). Both algorithms compress the grid and the vnumber of discrete velocities into \(N_g\cdot N_v \mapsto \lceil \log_2 N_g \rceil + \lceil \log_2 N_v \rceil\) qubits. The amplitude of each basis state is directly related to the populations in the classical LBM discretization. The MSQLBM is a generalization of the ABQLBM. The implementation of the algorithms was first described in [10] and later expanded in [11].

At its core, the CQLBM algorithm manipulates the particle probability distribution in an amplitude-based encoding of the quantum state. The End-to-end algorithms can be broken down into several distinct steps:

  1. Initial Conditions conditions prepare the starting state of the probability distribution function.

  2. Streaming circuits increment or decrement the position of particles in physical space through QFT-based streaming.

  3. Reflection circuits apply boundary conditions that affect particles that come in contact with solid obstacles. Reflection places those particles back in the appropriate position of the fluid domain.

  4. Measurement operations extract information out of the quantum state, which can later be post-processed classically.

This page documents the individual components that make up the CQLBM algorithm. Subsections follow a top-down approach, where end-to-end operators are introduced first, before being broken down into their constituent parts.

End-to-end algorithms#

class qlbm.components.CQLBM(lattice, use_agnostic_bcs=False, logger=<Logger qlbm (WARNING)>)[source]#

The end-to-end algorithm of the Collisionless Quantum Lattice Boltzmann Algorithm first introduced in Schalkers and Möller [10] and later extended in Schalkers and Möller [11].

Implementations based on lattices with the DdQq discretization use the ABQLBM:

from qlbm.components import CQLBM
from qlbm.lattice import ABLattice

lattice = ABLattice(
    {
        "lattice": {"dim": {"x": 4, "y": 4}, "velocities": "d2q9"},
        "geometry": [],
    }
)

CQLBM(lattice).draw("mpl")

(Source code, png, hires.png, pdf)

../_images/comps_cqlbm-1.png

Implementations where the number of velocities is defined per dimension delegate to the MSQLBM.

from qlbm.components import CQLBM
from qlbm.lattice import MSLattice

lattice = MSLattice(
    {
        "lattice": {"dim": {"x": 4, "y": 4}, "velocities": {"x": 4, "y": 4}},
        "geometry": [],
    }
)

CQLBM(lattice).draw("mpl")

(Source code, png, hires.png, pdf)

../_images/comps_cqlbm-2.png
Parameters:
  • lattice (Lattice)

  • use_agnostic_bcs (bool)

  • logger (Logger)

class qlbm.components.ms.MSQLBM(lattice, group_velocities=False, logger=<Logger qlbm (WARNING)>)[source]#

The end-to-end algorithm of the Multi-Speed Collisionless Quantum Lattice Boltzmann Algorithm first introduced in Schalkers and Möller [10] and later extended in Schalkers and Möller [11].

This implementation supports 2D and 3D simulations with with cuboid objects with either bounce-back or specular reflection boundary conditions.

The algorithm is composed of three steps that are repeated according to a CFL counter:

  1. Streaming performed by the MSStreamingOperator increments or decrements the positions of particles on the grid.

  2. BounceBackReflectionOperator and SpecularReflectionOperator reflect the particles that come in contact with Block obstacles encoded in the MSLattice.

  3. The StreamingAncillaPreparation resets the state of the ancilla qubits for the next CFL counter substep.

Attribute

Summary

lattice

The MSLattice based on which the properties of the operator are inferred.

logger

The performance logger, by default getLogger("qlbm").

group_velocities

Whether to group velocities into 1 streaming step in the CFL series.

Parameters:
  • lattice (Lattice)

  • group_velocities (bool)

  • logger (Logger)

class qlbm.components.ab.ABQLBM(lattice, use_agnostic_bcs=False, logger=<Logger qlbm (WARNING)>)[source]#

Implementation of the A mplitude B ased QLBM (ABQLBM).

The algorithm consists of interleaving steps of streaming and boundary conditions. Note that there is no collision in this algorithm as of yet. Details of the general framework can be found in [10]. The ABQLBM works with \(D_dQ_q\) discretizations only. For multi-speed alternatives, see MSQLBM.

Eample usage:

from qlbm.components.ab import ABQLBM
from qlbm.lattice import ABLattice

# Example with streaming only for simplicity.
lattice = ABLattice(
    {
        "lattice": {"dim": {"x": 16, "y": 8}, "velocities": "d2q9"},
        "geometry": [],
    }
)

ABQLBM(lattice).draw("mpl")
Parameters:
  • lattice (Lattice)

  • use_agnostic_bcs (bool)

  • logger (Logger)

Initial Conditions#

class qlbm.components.ms.primitives.MSInitialConditions(lattice, logger=<Logger qlbm (WARNING)>)[source]#

A primitive that creates the quantum circuit to prepare the flow field in its initial conditions for the MSLattice.

The initial conditions create a quantum state spanning half the grid in the x-axis, and the entirety of the y (and z)-axes (if 3D). All velocities are pointing in the positive direction.

Attribute

Summary

lattice

The MSLattice based on which the properties of the operator are inferred.

logger

The performance logger, by default getLogger("qlbm").

Example usage:

from qlbm.components.ms import MSInitialConditions
from qlbm.lattice import MSLattice

# Build an example lattice
lattice = MSLattice({
    "lattice": {
        "dim": {
                "x": 8,
                "y": 8
            },
            "velocities": {
                "x": 4,
                "y": 4
        }
    },
    "geometry": [
        {
            "shape": "cuboid",
            "x": [5, 6],
            "y": [1, 2],
            "boundary": "specular"
        }
    ]
})

# Draw the initial conditions circuit
MSInitialConditions(lattice).draw("mpl")

(Source code, png, hires.png, pdf)

../_images/comps_cqlbm-3.png
Parameters:
class qlbm.components.ms.primitives.MSInitialConditions3DSlim(lattice, logger=<Logger qlbm (WARNING)>)[source]#

A primitive that creates the quantum circuit to prepare the flow field in its initial conditions for 3 dimensions.

The initial conditions create the quantum state \(\Sigma_{j}\ket{0}^{\otimes n_{g_x}}\ket{0}^{\otimes n_{g_y}}\ket{j}\) over the grid qubits, that is, spanning the z-axis at the bottom of the x- and y-axes. This is helpful for debugging edge cases around the corners of 3D obstacles. All velocities are pointing in the positive direction.

Attribute

Summary

lattice

The MSLattice based on which the properties of the operator are inferred.

logger

The performance logger, by default getLogger("qlbm").

Example usage:

from qlbm.components.ms import MSInitialConditions3DSlim
from qlbm.lattice import MSLattice

# Build an example lattice
lattice = MSLattice({
    "lattice": {
        "dim": {
        "x": 8,
        "y": 8,
        "z": 8
        },
        "velocities": {
        "x": 4,
        "y": 4,
        "z": 4
        }
    },
    "geometry": []
})

# Draw the initial conditions circuit
MSInitialConditions3DSlim(lattice).draw("mpl")

(Source code, png, hires.png, pdf)

../_images/comps_cqlbm-4.png
Parameters:
class qlbm.components.ab.initial.ABDiscreteUniformInitialConditions(lattice, velocity_indices, grid_qubits_to_superpose, logger=<Logger qlbm (WARNING)>)[source]#

Initial conditions for the ABQLBM algorithm.

This component creates an equal magnitude superposition of a configurable set of velocity and grid indices.

Example usage:

from qlbm.components.ab import ABDiscreteUniformInitialConditions
from qlbm.lattice import ABLattice

lattice = ABLattice(
    {
        "lattice": {"dim": {"x": 16, "y": 8}, "velocities": "d2q9"},
    }
)

ABDiscreteUniformInitialConditions(lattice, [1, 3, 4], ([], [])).draw("mpl")

(Source code, png, hires.png, pdf)

../_images/comps_cqlbm-5.png

The primitive can also applied to the OHLattice:

from qlbm.components.ab import ABDiscreteUniformInitialConditions
from qlbm.lattice import OHLattice

lattice = OHLattice(
    {
        "lattice": {"dim": {"x": 16, "y": 8}, "velocities": "d2q9"},
    }
)

ABDiscreteUniformInitialConditions(lattice, [0, 1], ([0, 1], [0])).draw("mpl")

(Source code, png, hires.png, pdf)

../_images/comps_cqlbm-6.png
Parameters:
  • lattice (ABLattice)

  • velocity_indices (List[int])

  • grid_qubits_to_superpose (Tuple[List[int], ...])

  • logger (Logger)

class qlbm.components.ab.initial.ABParallelDiscreteUniformInitialConditions(lattice, velocity_indices_list, grid_qubits_to_superpose_list, logger=<Logger qlbm (WARNING)>)[source]#

Marker-sensitive initial conditions for the ABQLBM algorithm.

This component creates an equal magnitude superposition of a configurable set of velocity and grid indices, entangled with the state of the marker register. Used in parallel realizations of configurations.

Example usage:

from qlbm.components.ab import ABParallelDiscreteUniformInitialConditions
from qlbm.lattice import ABLattice

lattice = ABLattice(
    {
        "lattice": {"dim": {"x": 16, "y": 8}, "velocities": "d2q9"},
    }
)

lattice.set_num_marker_qubits(2)

ABParallelDiscreteUniformInitialConditions(
    lattice,
    [[0, 1], [0, 3], [0], [0, 5]],
    [([0], [0])] * 4,
).draw("mpl")

(Source code, png, hires.png, pdf)

../_images/comps_cqlbm-7.png
Parameters:
  • lattice (ABLattice)

  • velocity_indices_list (List[List[int]])

  • grid_qubits_to_superpose_list (List[Tuple[List[int], ...]])

  • logger (Logger)

class qlbm.components.ab.initial.ABInitialConditions(lattice, logger=<Logger qlbm (WARNING)>)[source]#

Initial conditions for the ABQLBM algorithm.

This component creates an equal magnitude superposition of all velocity basis states at position (0, 0) using the UniformStatePrep.

Example usage:

from qlbm.components.ab import ABInitialConditions
from qlbm.lattice import ABLattice

lattice = ABLattice(
    {
        "lattice": {"dim": {"x": 16, "y": 8}, "velocities": "d2q9"},
        "geometry": [],
    }
)

ABInitialConditions(lattice).draw("mpl")

(Source code, png, hires.png, pdf)

../_images/comps_cqlbm-8.png

You can also get the low-level decomposition of the circuit as:

from qlbm.components.ab import ABInitialConditions
from qlbm.lattice import ABLattice

lattice = ABLattice(
    {
        "lattice": {"dim": {"x": 4, "y": 4}, "velocities": "d2q9"},
        "geometry": [],
    }
)

ABInitialConditions(lattice).circuit.decompose(reps=2).draw("mpl")

(Source code, png, hires.png, pdf)

../_images/comps_cqlbm-9.png
Parameters:

Streaming#

class qlbm.components.ms.streaming.MSStreamingOperator(lattice, velocities, logger=<Logger qlbm (WARNING)>)[source]#

An operator that performs streaming in Fourier space as part of the MSQLBM algorithm.

Streaming is broken down into the following steps:

  1. A StreamingAncillaPreparation object prepares the ancilla velocity qubits for CFL time step. This happens independently for all dimensions, and it is assumed the velocity discretization is uniform across dimensions.

  2. A ControlledIncrementer performs incrementation or decrementation in the Fourier space, controlled on the ancilla qubits set in the previous steps.

  3. For efficiency reasons, the velocity qubits set in step 1 are not reset, as they will be re-used in the subsequent reflection step. Another instance of the StreamingAncillaPreparation would be required to consistently end the step.

For an in-depth mathematical explanation of the procedure, consult Section 4 of Schalkers and Möller [10].

Attribute

Summary

lattice

The MSLattice based on which the properties of the operator are inferred.

velocities

A list of velocities to increment. This is computed according to CFL counter.

logger

The performance logger, by default getLogger("qlbm").

Example usage:

from qlbm.components.ms import MSStreamingOperator
from qlbm.lattice import MSLattice

# Build an example lattice
lattice = MSLattice(
    {
        "lattice": {"dim": {"x": 8, "y": 8}, "velocities": {"x": 4, "y": 4}},
        "geometry": [],
    }
)

# Streaming the velocity with index 2
MSStreamingOperator(lattice=lattice, velocities=[2]).draw("mpl")

(Source code, png, hires.png, pdf)

../_images/comps_cqlbm-10.png
Parameters:
  • lattice (MSLattice)

  • velocities (List[int])

  • logger (Logger)

class qlbm.components.ms.streaming.StreamingAncillaPreparation(lattice, velocities, dim, logger=<Logger qlbm (WARNING)>)[source]#

A primitive used in MSStreamingOperator that implements the preparatory step of streaming necessary for the MSQLBM method.

This operator sets the ancilla qubits to \(\ket{1}\) for the velocities that will be streamed in the next CFL time step.

Attribute

Summary

lattice

The MSLattice based on which the properties of the operator are inferred.

velocities

The velocities that need to be streamed within the next time step.

dim

The dimension to which the velocities correspond.

logger

The performance logger, by default getLogger("qlbm").

Example usage:

from qlbm.components.ms import StreamingAncillaPreparation
from qlbm.lattice import MSLattice

# Build an example lattice
lattice = MSLattice(
    {
        "lattice": {"dim": {"x": 8, "y": 8}, "velocities": {"x": 4, "y": 4}},
        "geometry": [],
    }
)

# Streaming velocities indexed 2 in the y (1) dimension
StreamingAncillaPreparation(lattice=lattice, velocities=[2], dim=1).draw("mpl")

(Source code, png, hires.png, pdf)

../_images/comps_cqlbm-11.png
Parameters:
  • lattice (MSLattice)

  • velocities (List[int])

  • dim (int)

  • logger (Logger)

class qlbm.components.ms.streaming.ControlledIncrementer(lattice, reflection=None, logger=<Logger qlbm (WARNING)>)[source]#

A primitive used in MSStreamingOperator that implements the streaming operation on the states for which the ancilla qubits are in the state \(\ket{1}\).

This primitive is applied after the primitive StreamingAncillaPreparation to compose the streaming operator.

Attribute

Summary

lattice

The MSLattice based on which the properties of the operator are inferred.

reflection

The reflection attribute decides the type of reflection that will take place. This should be either “specular”, “bounceback”, or None, and defaults to None. This parameter governs which qubits are used as controls for the Fourier space phase shifts.

logger

The performance logger, by default getLogger("qlbm").

Example usage:

from qlbm.components.ms import ControlledIncrementer
from qlbm.lattice import MSLattice

# Build an example lattice
lattice = MSLattice(
    {
        "lattice": {"dim": {"x": 8, "y": 8}, "velocities": {"x": 4, "y": 4}},
        "geometry": [],
    }
)

# Streaming velocities indexed 2 in the y (1) dimension
ControlledIncrementer(lattice=lattice).draw("mpl")

(Source code, png, hires.png, pdf)

../_images/comps_cqlbm-12.png
Parameters:
  • lattice (MSLattice)

  • reflection (str | None)

  • logger (Logger)

class qlbm.components.ms.streaming.PhaseShift(num_qubits, positive=False, logger=<Logger qlbm (WARNING)>)[source]#

A primitive that applies the phase-shift as part of the ControlledIncrementer used in the MSStreamingOperator.

The rotation applied is \(\pm\frac{\pi}{2^{n_q - 1 - j}}\), with \(j\) the position of the qubit (indexed starting with 0). For an in-depth mathematical explanation of the procedure and its use within QLBM, consult Section 4 of Schalkers and Möller [10]. The Draper adder was originally formulated in [2], while the version implemented here uses the one-register approach, which was first described in [1].

Attribute

Summary

num_qubits

The number of qubits to perform the phase shift for.

positive

Whether the phase shift is applied to increment (T) or decrement (F) the position of the particles. Defaults to False.

logger

The performance logger, by default getLogger("qlbm").

Example usage:

from qlbm.components.common.adders import PhaseShift

# A phase shift of 5 qubits
PhaseShift(num_qubits=5, positive=False).draw("mpl")

(Source code, png, hires.png, pdf)

../_images/comps_cqlbm-13.png
Parameters:
  • num_qubits (int)

  • positive (bool)

  • logger (Logger)

class qlbm.components.ab.streaming.ABStreamingOperator(lattice, additional_control_qubit_indices=[], logger=<Logger qlbm (WARNING)>)[source]#

Streaming operator for the ABQLBM algorithm.

Uses a variant of the Draper adder described in [10]. The operator works by applying QFTs in parallel to each dimension of the grid, followed by phase gates that perform incrementation in the Fourier basis, and, finally, by applying an inverse QFT mapping the qubits back to the computational basis.

Populations are streamed one after the other in Fourier space by controlling phase gates on the state of the velocity qubits. Additional controls qubits can be specified to restrict this operation.

Example usage:

from qlbm.components.ab import ABStreamingOperator
from qlbm.lattice import ABLattice

lattice = ABLattice(
    {
        "lattice": {"dim": {"x": 4, "y": 8}, "velocities": "d2q9"},
        "geometry": [],
    }
)

ABStreamingOperator(lattice).draw("mpl")

(Source code, png, hires.png, pdf)

../_images/comps_cqlbm-14.png
Parameters:
  • lattice (AmplitudeLattice)

  • additional_control_qubit_indices (List[int])

  • logger (Logger)

Reflection#

class qlbm.components.ms.bounceback_reflection.BounceBackReflectionOperator(lattice, blocks, logger=<Logger qlbm (WARNING)>)[source]#

Operator implementing the 2D and 3D Bounce-Back (BB) boundary conditions as described in Schalkers and Möller [11].

The operator parses information encoded in Block objects to detect particles that have virtually streamed into the solid domain before placing them back to their previous positions in the fluid domain. The pseudocode for this procedure is as follows:

  1. Components of the quantum state that encode particles that have streamed inside the obstacle are identified with BounceBackWallComparator objects;

  2. These components have their velocity direction qubits flipped in all three dimensions;

  3. Particles are streamed outside the solid domain with inverted velocity directions;

  4. Once streamed outside the solid domain, components encoding affected particles have their obstacle ancilla qubit reset based on grid position, velocity direction, and whether they have streamed in the CFL timestep.

Attribute

Summary

lattice

The MSLattice based on which the properties of the operator are inferred.

blocks

A list of Block objects for which to generate the BB boundary condition circuits.

logger

The performance logger, by default getLogger("qlbm").

Example usage:

from qlbm.components.ms import BounceBackReflectionOperator
from qlbm.lattice import MSLattice

# Build an example lattice
lattice = MSLattice(
    {
        "lattice": {"dim": {"x": 8, "y": 8}, "velocities": {"x": 4, "y": 4}},
        "geometry": [{"shape":"cuboid", "x": [5, 6], "y": [1, 2], "boundary": "bounceback"}],
    }
)

BounceBackReflectionOperator(lattice=lattice, blocks=lattice.shape_list)

(Source code)

Parameters:
create_circuit()[source]#

Creates the qiskit.QuantumCircuit of this object.

This method is called automatically at construction time for all quantum components.

Returns:

The generated QuantumCircuit.

Return type:

QuantumCircuit

reflect_wall(circuit, wall)[source]#

Performs reflection based on information encoded in a ReflectionWall as follows.

  1. A series of \(X\) gates set the grid qubits to the \(\ket{1}\) state for the dimension that the wall spans.

  2. Comparator circuits set the comparator ancilla qubits to \(\ket{1}\) based on the size of the wall in the other dimension(s).

  3. Depending on the use, the directional velocity qubits are also set to \(\ket{1}\) based on the dimension that the wall spans.

  4. A multi-controlled \(X\) gate flips the obstacle ancilla qubit, controlled on the qubits set in the previous steps.

  5. The control qubits are set back to their previous state.

The wall reflection operation is versatile and can be used to both set and re-set the state of the obstacle ancilla qubit at different stages of reflection. When performing BB reflection, this function is first used to flip the ancilla obstacle qubit from \(\ket{0}\) to \(\ket{1}\), irrespective of how particles arrived there. Subsequently, an additional controls are placed on the velocity direction qubits to reset the ancilla obstacle qubit to \(\ket{0}\), after particles have been streamed out of the solid domain.

Parameters:
  • circuit (QuantumCircuit) – The circuit on which to perform BB reflection of the wall.

  • wall (ReflectionWall) – The wall encoding the reflection logic.

  • inside_obstacle (bool) – Whether the wall is inside the obstacle.

Returns:

The circuit performing BB reflection of the wall.

Return type:

QuantumCircuit

reset_edge_state(circuit, edge)[source]#

Resets the state of an edge along the side of an obstacle in 3D as follows.

  1. A series of \(X\) gates set the grid qubits to the \(\ket{1}\) state for the 2 dimensions that the edge spans.

  2. A comparator circuits sets the comparator ancilla qubits to \(\ket{1}\) based on the size of the edge in the remaining dimension.

  3. The directional velocity qubits are also set to \(\ket{1}\) on the specific velocity profile of the targeted particles.

  4. A multi-controlled \(X\) gate flips the obstacle ancilla qubit, controlled on the qubits set in the previous steps.

  5. The control qubits are set back to their previous state.

This function resets the ancilla obstacle qubit to \(\ket{0}\) for particles along 36 specific edges of a cube after those particles have been streamed out of the obstacle in the CFL time step.

Parameters:
  • circuit (QuantumCircuit) – The circuit on which to perform resetting of the edge state.

  • edge (ReflectionResetEdge) – The edge on which to apply the reflection reset logic.

Returns:

The circuit performing the resetting of the edge state.

Return type:

QuantumCircuit

reset_point_state(circuit, corner)[source]#

Resets the state of the ancilla obstacle qubit of a single point on the grid as follows.

  1. A series of \(X\) gates set the grid qubits to the \(\ket{1}\) state for the dimension that the wall spans.

  2. The directional velocity qubits are also set to \(\ket{1}\) based on the specific velocity profile of the targeted particles.

  3. A multi-controlled \(X\) gate flips the obstacle ancilla qubit, controlled on the qubits set in the previous steps.

  4. The control qubits are set back to their previous state.

Parameters:
  • circuit (QuantumCircuit) – The circuit on which to perform the resetting of the point state.

  • corner (ReflectionPoint) – The corner for which to reset the desired point states.

Returns:

The circuit resetting the point state as desired.

Return type:

QuantumCircuit

flip_and_stream(circuit)[source]#

Flips the velocity direction qubit controlled on the ancilla obstacle qubit, before performing streaming.

Unlike in the regular MSStreamingOperator, the ControlledIncrementer phase shift circuit is additionally controlled on the ancilla obstacle qubit, which ensures that only particles whose grid position gets incremented (decremented) are those that have streamed inside the solid domain in this CFL time step.

Parameters:

circuit (QuantumCircuit) – The circuit on which to perform the flip and stream operation.

class qlbm.components.ms.specular_reflection.SpecularReflectionOperator(lattice, blocks, logger=<Logger qlbm (WARNING)>)[source]#

Operator implementing the 2D and 3D Specular Reflection (SR) boundary conditions as described Schalkers and Möller [10].

The operator parses information encoded in Block objects to detect particles that have virtually streamed into the solid domain before placing them back to their previous positions in the fluid domain. The pseudocode for this procedure is as follows:

  1. Components of the quantum state that encode particles that have streamed inside the obstacle are identified with SpecularWallComparator objects;

  2. These components have their velocity direction qubits flipped according to the wall they came in contact with. Where two or three walls come together, the two or three corresponding directions are inverted;

  3. Particles are streamed outside the solid domain with inverted velocity directions;

  4. Once streamed outside the solid domain, components encoding affected particles have their obstacle ancilla qubits reset based on grid position, velocity direction, and whether they have streamed in the CFL timestep.

Attribute

Summary

lattice

The MSLattice based on which the properties of the operator are inferred.

blocks

A list of Block objects for which to generate the BB boundary condition circuits.

logger

The performance logger, by default getLogger("qlbm").

Example usage:

from qlbm.components.ms import SpecularReflectionOperator
from qlbm.lattice import MSLattice

# Build an example lattice
lattice = MSLattice(
    {
        "lattice": {"dim": {"x": 8, "y": 8}, "velocities": {"x": 4, "y": 4}},
        "geometry": [{"shape":"cuboid", "x": [5, 6], "y": [1, 2], "boundary": "specular"}],
    }
)

SpecularReflectionOperator(lattice=lattice, blocks=lattice.shape_list)

(Source code)

Parameters:
create_circuit()[source]#

Creates the qiskit.QuantumCircuit of this object.

This method is called automatically at construction time for all quantum components.

Returns:

The generated QuantumCircuit.

Return type:

QuantumCircuit

reflect_wall(circuit, wall)[source]#

Performs reflection based on information encoded in a ReflectionWall as follows.

  1. A series of \(X\) gates set the grid qubits to the \(\ket{1}\) state for the dimension that the wall spans.

  2. Comparator circuits set the comparator ancilla qubits to \(\ket{1}\) based on the size of the wall in the other dimension(s).

  3. Depending on the use, the directional velocity qubits are also set to \(\ket{1}\) based on the dimension that the wall spans.

  4. A multi-controlled \(X\) gate flips the obstacle ancilla qubits of the particular dimension that the wall reflects, controlled on the qubits set in the previous steps.

  5. The control qubits are set back to their previous state.

The wall reflection operation is versatile and can be used to both set and re-set the state of the obstacle ancilla qubit at different stages of reflection. When performing SR reflection, this function is first used to flip the ancilla obstacle qubit from \(\ket{0}\) to \(\ket{1}\), irrespective of how particles arrived there. Subsequently, an additional controls are placed on the velocity direction qubits to reset the ancilla obstacle qubit to \(\ket{0}\), after particles have been streamed out of the solid domain.

Parameters:
  • circuit (QuantumCircuit) – The circuit on which to perform resetting of the edge state.

  • wall (ReflectionWall) – The wall encoding the reflection logic.

Returns:

The circuit performing specular reflection of the wall.

Return type:

QuantumCircuit

reset_edge_state(circuit, edge)[source]#

Resets the state of an edge along the side of an obstacle in 3D as follows.

  1. A series of \(X\) gates set the grid qubits to the \(\ket{1}\) state for the 2 dimensions that the edge spans.

  2. A comparator circuits sets the comparator ancilla qubits to \(\ket{1}\) based on the size of the edge in the remaining dimension.

  3. The directional velocity qubits are also set to \(\ket{1}\) on the specific velocity profile of the targeted particles.

  4. A multi-controlled \(X\) gate flips the obstacle ancilla qubits of the direction reflect by the wall(s) that the edge is next to, controlled on the qubits set in the previous steps.

  5. The control qubits are set back to their previous state.

This function resets the ancilla obstacle qubit to \(\ket{0}\) for particles along 36 specific edges of a cube after those particles have been streamed out of the obstacle in the CFL time step.

Parameters:
  • circuit (QuantumCircuit) – The circuit on which to perform resetting of the edge state.

  • edge (ReflectionResetEdge) – The edge on which to apply the reflection reset logic.

Returns:

The circuit performing the resetting of the edge state.

Return type:

QuantumCircuit

reset_point_state(circuit, corner)[source]#

Resets the state of the ancilla obstacle qubit of a single point on the grid as follows.

  1. A series of \(X\) gates set the grid qubits to the \(\ket{1}\) state for the dimension that the wall spans.

  2. The directional velocity qubits are also set to \(\ket{1}\) based on the specific velocity profile of the targeted particles.

  3. A multi-controlled \(X\) gate flips the obstacle ancilla qubits corresponding to the dimensions that particles would have traveled to arrive there via reflection, controlled on the qubits set in the previous steps.

  4. The control qubits are set back to their previous state.

Parameters:
  • circuit (QuantumCircuit) – The circuit on which to perform the resetting of the point state.

  • corner (ReflectionPoint) – The corner for which to reset the desired point states.

Returns:

The circuit resetting the point state as desired.

Return type:

QuantumCircuit

flip_and_stream(circuit)[source]#

Flips the velocity direction qubit controlled on the ancilla obstacle qubit, before performing streaming.

Unlike in the regular MSStreamingOperator, the ControlledIncrementer phase shift circuit is additionally controlled on the ancilla obstacle qubit of the streaming dimension, which ensures that only particles whose grid position gets incremented (decremented) are those that have streamed inside the solid domain in this CFL time step.

Parameters:

circuit (QuantumCircuit) – The circuit on which to perform the flip and stream operation.

class qlbm.components.ms.bounceback_reflection.BounceBackWallComparator(lattice, wall, logger=<Logger qlbm (WARNING)>)[source]#

A primitive used in the collision BounceBackReflectionOperator that implements the comparator for the BB boundary conditions as described in Schalkers and Möller [11].

The comparator sets an ancilla qubit to \(\ket{1}\) for the components of the quantum state whose grid qubits fall within the range spanned by the wall.

Attribute

Summary

lattice

The MSLattice based on which the properties of the operator are inferred.

wall

The ReflectionWall encoding the range spanned by the wall.

logger

The performance logger, by default getLogger("qlbm").

Example usage:

from qlbm.components.ms import BounceBackWallComparator
from qlbm.lattice import MSLattice

# Build an example lattice
lattice = MSLattice(
    {
        "lattice": {"dim": {"x": 8, "y": 8}, "velocities": {"x": 4, "y": 4}},
        "geometry": [{"shape":"cuboid", "x": [5, 6], "y": [1, 2], "boundary": "bounceback"}],
    }
)

# Comparing on the indices of the inside x-wall on the lower-bound of the obstacle
BounceBackWallComparator(
    lattice=lattice, wall=lattice.shape_list[0].walls_inside[0][0]
).draw("mpl")

(Source code, png, hires.png, pdf)

../_images/comps_cqlbm-17.png
Parameters:
class qlbm.components.ms.specular_reflection.SpecularWallComparator(lattice, wall, logger=<Logger qlbm (WARNING)>)[source]#

A primitive used in the collisionless SpecularReflectionOperator that implements the comparator for the specular reflection boundary conditions around the wall as described Schalkers and Möller [10].

The comparator sets the d ancilla qubits to \(\ket{1}\) for the components of the quantum state whose grid qubits fall within the range spanned by the wall.

Attribute

Summary

lattice

The AmplitudeLattice based on which the properties of the operator are inferred.

wall

The ReflectionWall encoding the range spanned by the wall.

logger

The performance logger, by default getLogger("qlbm").

Example usage:

from qlbm.components.ms import SpecularWallComparator
from qlbm.lattice import MSLattice

# Build an example lattice
lattice = MSLattice(
    {
        "lattice": {"dim": {"x": 8, "y": 8}, "velocities": {"x": 4, "y": 4}},
        "geometry": [{"shape":"cuboid", "x": [5, 6], "y": [1, 2], "boundary": "specular"}],
    }
)

# Comparing on the indices of the inside x-wall on the lower-bound of the obstacle
SpecularWallComparator(
    lattice=lattice, wall=lattice.shape_list[0].walls_inside[0][0]
).draw("mpl")

(Source code, png, hires.png, pdf)

../_images/comps_cqlbm-18.png
Parameters:
class qlbm.components.ms.primitives.EdgeComparator(lattice, edge, logger=<Logger qlbm (WARNING)>)[source]#

A primitive used in the 3D collisionless SpecularReflectionOperator and BounceBackReflectionOperator described in Schalkers and Möller [10].

Attribute

Summary

lattice

The MSLattice based on which the properties of the operator are inferred.

logger

The performance logger, by default getLogger("qlbm").

edge

The coordinates of the edge within the grid.

Example usage:

from qlbm.components.ms import EdgeComparator
from qlbm.lattice import MSLattice

# Build an example lattice
lattice = MSLattice(
    {
        "lattice": {
            "dim": {"x": 8, "y": 8, "z": 8},
            "velocities": {"x": 4, "y": 4, "z": 4},
        },
        "geometry": [{"shape":"cuboid", "x": [2, 5], "y": [2, 5], "z": [2, 5], "boundary": "specular"}],
    }
)

# Draw the edge comparator circuit for one specific corner edge
EdgeComparator(lattice, lattice.shape_list[0].corner_edges_3d[0]).draw("mpl")

(Source code, png, hires.png, pdf)

../_images/comps_cqlbm-19.png
Parameters:

Note

The amplitude-based QLBM supports two kinds of reflection operators: segment-wise (or standard) and zone-agnostic. The two methods are physically equivalent, but their implementation differs algorithmically. For multi-geometry cases, only the segment-wise implementation is currently supported.

class qlbm.components.ab.reflection.ABReflectionOperator(lattice, shapes=None, logger=<Logger qlbm (WARNING)>)[source]#

Implements reflection boundary conditions in the amplitude-based encoding of ABQLBM for \(D_dQ_q\) discretizations.

This is the top-level entrypoint that delegates to ABBounceBackReflectionOperator and ABSpecularReflectionOperator based on the boundary condition types present in the geometry.

Example usage:

from qlbm.components.ab import ABReflectionOperator
from qlbm.lattice import ABLattice

lattice = ABLattice(
    {
        "lattice": {"dim": {"x": 4, "y": 4}, "velocities": "d2q9"},
        "geometry": [
            {
                "shape": "cuboid",
                "x": [1, 3],
                "y": [1, 3],
                "boundary": "bounceback",
            }
        ],
    }
)

ABReflectionOperator(lattice).draw("mpl")

(Source code, png, hires.png, pdf)

../_images/comps_cqlbm-20.png
Parameters:
class qlbm.components.ab.reflection.ABBounceBackReflectionOperator(lattice, blocks, control_on_marker_state=False, logger=<Logger qlbm (WARNING)>)[source]#

Implements bounce-back reflection in the amplitude-based encoding of ABQLBM for \(D_2Q_9\).

Bounce-back reflection reverses all velocity components of particles that have entered the obstacle walls. The algorithm proceeds as:

  1. Mark inner walls – Set the obstacle ancilla for gridpoints inside each wall segment.

  2. Mark inner corners – Set the obstacle ancilla for the inner corner gridpoints.

  3. Permute and stream – Apply the bounce-back velocity permutation (full reversal) and stream, both controlled on the obstacle ancilla.

  4. Reset outer walls – Reset the obstacle ancilla using the outside wall comparators.

  5. Corner corrections – Fix near-corner and outside-corner ancilla residuals.

Parameters:
class qlbm.components.ab.reflection.ABSpecularReflectionOperator(lattice, blocks, control_on_marker_state=False, logger=<Logger qlbm (WARNING)>)[source]#

Implements specular reflection in the amplitude-based encoding of ABQLBM for \(D_2Q_9\).

This operator uses per-dimension obstacle ancillae (a_x, a_y) to track which wall a particle has entered through. The algorithm proceeds in five phases:

  1. Mark inner walls – For each dimension, set the per-dimension obstacle ancilla for all gridpoints lying inside the walls of each block.

  2. Specular permutations – Apply per-dimension velocity permutations controlled on the corresponding obstacle ancilla.

  3. Dimension-selective stream – For each dimension d, stream the grid qubits of d controlled on ancilla[d]. This ensures a particle reflected off an x-wall only moves in x, while a corner particle (both ancillae set) moves in both.

  4. Reset outer walls – For each dimension, reset the per-dimension obstacle ancilla using the outside wall comparators.

  5. Corner corrections – Fix near-corner and outside-corner ancilla residuals caused by the wall-based reset overshoot and by cardinal velocities at inner corners.

Parameters:
  • lattice (ABLattice) – The lattice on which to build the reflection circuit.

  • blocks (List[Shape]) – The list of specular Block objects.

  • control_on_marker_state (bool) – Whether to control all MCX gates on the marker register.

  • logger (Logger) – The performance logger.

class qlbm.components.ab.reflection.ABZoneAgnosticReflectionOperator(lattice, shapes=None, logger=<Logger qlbm (WARNING)>)[source]#

Implements bounceback reflection in the amplitude-based encoding of ABQLBM for \(D_dQ_q\) discretizations.

Uses a zone-agnostic approach that relies on the existence of an oracle that marks the basis states belonging to the inside of the solid geometry. For more details on the oracle, see ABZoneAgnosticReflectionOracle.

Example usage:

from qlbm.components.ab import ABZoneAgnosticReflectionOperator
from qlbm.lattice import ABLattice

lattice = ABLattice(
    {
        "lattice": {"dim": {"x": 4, "y": 4}, "velocities": "d2q9"},
        "geometry": [
            {
                "shape": "cuboid",
                "x": [1, 3],
                "y": [1, 3],
                "boundary": "bounceback",
            }
        ],
    }
)

ABZoneAgnosticReflectionOperator(lattice).draw("mpl")

(Source code, png, hires.png, pdf)

../_images/comps_cqlbm-21.png
Parameters:
class qlbm.components.ab.reflection.ABZoneAgnosticReflectionOracle(lattice, shape, control_on_marker_state=False, additional_control_qubits=[], target_obstacle_index=0, logger=<Logger qlbm (WARNING)>)[source]#

Implementation of the oracle required for ABZoneAgnosticReflectionOperator.

An oracle is an operator \(U_{\Omega}\) for an obstacle’s region \(\Omega\) such that, in the amplitude-based encoding, \(U_\Omega\ket{x}\ket{v}\ket{0}_\mathbb{o} = \ket{x}\ket{v}\ket{x \in \Omega}_\mathbb{o}\). Intuitively, the operator flips the object ancilla qubit if and only if the position \(x\) falls within the bounds of the object.

Currently, the only available implementation is for 2D axis-aligned Block and YMonomial objects.

Important

The YMonomial implementation is a work in progress. At present, only the \(x^2\) monomial case is supported, and only when the monomial result register width matches the \(y\) grid register width.

This is an improvement in asymptotic and practical complexity compared to the methods described in [10]. This operation relies on basic arithmetic through the ParameterizedDraperAdder class and comparison operation through the Comparator circuits.

When control_on_marker_state is True, the oracle additionally conditions the obstacle ancilla flip on the marker register being in the all-ones state. This is used for parallel boundary conditions where multiple geometries are simulated on the same lattice, each identified by a marker state. Only the central MCX gate (for cuboids) is controlled on the marker, since the surrounding adder and comparator operations are self-inverse and their net effect on the grid register is zero.

Important

Marker-controlled oracles for YMonomial shapes are not yet supported. Passing control_on_marker_state=True with a YMonomial shape will raise a CircuitException.

Example usage for a cuboid Block:

from qlbm.components.ab.reflection import ABZoneAgnosticReflectionOracle
from qlbm.lattice import ABLattice

lattice = ABLattice(
    {
        "lattice": {"dim": {"x": 4, "y": 16}, "velocities": "d2q9"},
        "geometry": [
            {
                "shape": "cuboid",
                "x": [1, 3],
                "y": [1, 3],
                "boundary": "bounceback",
            }
        ],
    }
)

ABZoneAgnosticReflectionOracle(lattice, shape=lattice.shapes["bounceback"][0]).draw("mpl")

(Source code, png, hires.png, pdf)

../_images/comps_cqlbm-22.png

And for a YMonomial:

from qlbm.components.ab.reflection import ABZoneAgnosticReflectionOracle
from qlbm.lattice import ABLattice

lattice = ABLattice(
    {
        "lattice": {"dim": {"x": 4, "y": 16}, "velocities": "d2q9"},
        "geometry": [
            {
                "shape": "ymonomial",
                "exponent": 2,
                "comparator": "<",
                "boundary": "bounceback",
            }
        ],
    }
)

ABZoneAgnosticReflectionOracle(lattice, shape=lattice.shapes["bounceback"][0]).draw("mpl")

(Source code, png, hires.png, pdf)

../_images/comps_cqlbm-23.png
Parameters:
  • lattice (ABLattice)

  • shape (Shape)

  • control_on_marker_state (bool)

  • additional_control_qubits (List[int])

  • target_obstacle_index (int)

  • logger (Logger)

Measurement#

class qlbm.components.ms.primitives.GridMeasurement(lattice, logger=<Logger qlbm (WARNING)>)[source]#

A primitive that implements a measurement operation on the grid qubits.

Used at the end of the time step circuit to extract information from the quantum state.

Attribute

Summary

lattice

The MSLattice based on which the properties of the operator are inferred.

logger

The performance logger, by default getLogger("qlbm").

Example usage:

from qlbm.components.ms import GridMeasurement
from qlbm.lattice import MSLattice

# Build an example lattice
lattice = MSLattice({
    "lattice": {
        "dim": {
                "x": 8,
                "y": 8
            },
            "velocities": {
                "x": 4,
                "y": 4
        }
    },
    "geometry": [
        {
            "shape": "cuboid",
            "x": [5, 6],
            "y": [1, 2],
            "boundary": "specular"
        }
    ]
})

# Draw the measurement circuit
GridMeasurement(lattice).draw("mpl")

(Source code, png, hires.png, pdf)

../_images/comps_cqlbm-24.png
Parameters:
class qlbm.components.ab.measurement.ABGridMeasurement(lattice, measure_velocity_qubits=False, logger=<Logger qlbm (WARNING)>)[source]#

Grid measurement for the ABQLBM algorithm.

Example usage:

from qlbm.components.ab import ABGridMeasurement
from qlbm.lattice import ABLattice

lattice = ABLattice(
    {
        "lattice": {"dim": {"x": 32, "y": 8}, "velocities": "d2q9"},
        "geometry": [],
    }
)

ABGridMeasurement(lattice).draw("mpl")

(Source code, png, hires.png, pdf)

../_images/comps_cqlbm-25.png
Parameters:
  • lattice (ABLattice)

  • measure_velocity_qubits (bool)

  • logger (Logger)