qlat_utils.types — Element Type Descriptors and Buffer Protocol Support¶
Source: qlat-utils/qlat_utils/types.pyx
Note: Update this document when updating the source file.
Outline¶
Overview¶
types defines the Python-level type descriptors for the fundamental data types used in lattice QCD calculations. It provides:
Buffer— a Cython-level implementation of the Python buffer protocol (__getbuffer__/__releasebuffer__) that allows C++ memory to be exposed as NumPy-compatible buffers without copying.ElemTypeclass hierarchy — a family of descriptor classes, each encoding the shape, itemsize, format string, and byte-size of a specific C++ lattice type (e.g.,ColorMatrix,WilsonMatrix,ComplexD,RealD, etc.).
These types serve as metadata bridges between C++ field storage and Python’s buffer/NumPy ecosystem.
Python access:
import qlat_utils as q
Buffer Class¶
cdef class Buffer:
def __cinit__(self, object obj=None, int ndim=1, int itemsize=1,
char* fmt=NULL, char* buf=NULL)
A Cython extension type that implements the Python buffer protocol. Instances are not typically created directly by users; they are used internally by field types to expose their data as buffer-compatible objects.
Constructor Parameters¶
Parameter |
Type |
Default |
Description |
|---|---|---|---|
|
|
|
Parent object that owns the memory. Its |
|
|
|
Number of dimensions |
|
|
|
Size in bytes of a single element |
|
|
|
Format string for the buffer protocol (e.g. |
|
|
|
Pointer to the raw memory |
Internal Methods¶
Method |
Description |
|---|---|
|
Populate a |
|
Set the size of dimension |
|
Compute C-contiguous strides from the current shape |
|
Return total byte length ( |
Buffer Protocol¶
Buffer implements __getbuffer__ and __releasebuffer__, making it compatible with memoryview, np.asarray(), and any Python API that accepts the buffer protocol. When the buffer is released, the parent object’s release_buffer() method is called.
ElemType Hierarchy¶
ElemType is the base class for all element type descriptors. Each subclass encodes the metadata for a specific C++ lattice data type.
class ElemType:
name = ""
All subclasses provide the following class-level attributes:
Attribute |
Type |
Description |
|---|---|---|
|
|
Human-readable type name |
|
|
Total byte size of the C++ type |
All subclasses also provide the following Python-accessible static methods (wrappers around the internal cdef methods):
Method |
Return Type |
Description |
|---|---|---|
|
|
Buffer protocol format string (e.g., |
|
|
Byte size of one scalar element |
|
|
Number of dimensions |
|
|
Dimension sizes |
|
|
Total byte size of the type |
Matrix Types¶
These types represent 2D matrix structures used in lattice QCD calculations. All use ComplexD (complex double, 'Zd') as their scalar element type.
ElemTypeColorMatrix¶
3×3 complex color matrix. Used for SU(3) gauge links.
Property |
Value |
|---|---|
|
|
|
|
|
|
|
|
|
144 bytes |
ElemTypeWilsonMatrix¶
12×12 complex Wilson (Dirac-spinor × color) matrix.
Property |
Value |
|---|---|
|
|
|
|
|
|
|
|
|
2304 bytes |
ElemTypeNonRelWilsonMatrix¶
6×6 complex non-relativistic Wilson matrix.
Property |
Value |
|---|---|
|
|
|
|
|
|
|
|
|
576 bytes |
ElemTypeIsospinMatrix¶
2×2 complex isospin matrix.
Property |
Value |
|---|---|
|
|
|
|
|
|
|
|
|
64 bytes |
ElemTypeSpinMatrix¶
4×4 complex Dirac spin matrix.
Property |
Value |
|---|---|
|
|
|
|
|
|
|
|
|
256 bytes |
ElemTypeWilsonVector¶
12-component complex Wilson vector (Dirac spin × color).
Property |
Value |
|---|---|
|
|
|
|
|
|
|
|
|
192 bytes |
Scalar Types¶
These types represent scalar (0-dimensional) primitive types.
ElemTypeComplexD¶
Complex double precision (std::complex<double>).
Property |
Value |
|---|---|
|
|
|
|
|
|
|
|
|
16 bytes |
ElemTypeComplexF¶
Complex single precision (std::complex<float>).
Property |
Value |
|---|---|
|
|
|
|
|
|
|
|
|
8 bytes |
ElemTypeRealD¶
Double precision real (double).
Property |
Value |
|---|---|
|
|
|
|
|
|
|
|
|
8 bytes |
ElemTypeRealF¶
Single precision real (float).
Property |
Value |
|---|---|
|
|
|
|
|
|
|
|
|
4 bytes |
ElemTypeLong¶
64-bit signed integer (Long).
Property |
Value |
|---|---|
|
|
|
|
|
|
|
|
|
8 bytes |
ElemTypeInt¶
32-bit signed integer (int).
Property |
Value |
|---|---|
|
|
|
|
|
|
|
|
|
4 bytes |
ElemTypeChar¶
Signed character (char).
Property |
Value |
|---|---|
|
|
|
|
|
|
|
|
|
1 byte |
ElemTypeInt64t¶
64-bit signed integer (int64_t).
Property |
Value |
|---|---|
|
|
|
|
|
|
|
|
|
8 bytes |
ElemTypeInt32t¶
32-bit signed integer (int32_t).
Property |
Value |
|---|---|
|
|
|
|
|
|
|
|
|
4 bytes |
ElemTypeInt8t¶
8-bit signed integer (int8_t).
Property |
Value |
|---|---|
|
|
|
|
|
|
|
|
|
1 byte |
Type Properties Reference¶
Note: The tables below document the full type metadata.
nameandsizeof_mare class attributes.py_format(),py_itemsize(),py_ndim(),py_shape(), andpy_size()are Python-accessible static methods (wrappers around internalcdefmethods).
Matrix Types Summary¶
Type |
Name |
Shape |
Item Format |
Element Size |
Total Size |
|---|---|---|---|---|---|
|
|
|
|
16 B |
144 B |
|
|
|
|
16 B |
2304 B |
|
|
|
|
16 B |
576 B |
|
|
|
|
16 B |
64 B |
|
|
|
|
16 B |
256 B |
|
|
|
|
16 B |
192 B |
Scalar Types Summary¶
Type |
Name |
Format |
Size |
|---|---|---|---|
|
|
|
16 B |
|
|
|
8 B |
|
|
|
8 B |
|
|
|
4 B |
|
|
|
8 B |
|
|
|
4 B |
|
|
|
1 B |
|
|
|
8 B |
|
|
|
4 B |
|
|
|
1 B |
Examples¶
Querying Type Metadata¶
import qlat_utils as q
from qlat_utils.types import ElemTypeColorMatrix, ElemTypeWilsonMatrix, ElemTypeRealD
# ColorMatrix: 3x3 complex double, total size 144 bytes
print(ElemTypeColorMatrix.name) # "ColorMatrix"
print(ElemTypeColorMatrix.sizeof_m) # 144
# WilsonMatrix: 12x12 complex double
print(ElemTypeWilsonMatrix.name) # "WilsonMatrix"
print(ElemTypeWilsonMatrix.sizeof_m) # 2304
# Scalar type
print(ElemTypeRealD.name) # "RealD"
print(ElemTypeRealD.sizeof_m) # 8
Buffer Protocol Usage¶
The Buffer class is used internally by field types. A typical pattern:
import numpy as np
import qlat_utils as q
from qlat_utils.types import Buffer, ElemTypeComplexD
# Buffer is typically created internally by field objects.
# When a field exposes its data via the buffer protocol,
# NumPy can access it without copying:
# arr = np.asarray(field_buffer)
# The parent object controls memory lifetime via release_buffer().
Using ElemType for Array Construction¶
import numpy as np
from qlat_utils.types import ElemTypeColorMatrix
# Construct a zero-filled array matching the ColorMatrix layout
# ColorMatrix is 3x3 complex double (sizeof_m = 144 bytes)
shape = (3, 3)
dtype = np.complex128 # matches 'Zd' format
mat = np.zeros(shape, dtype=dtype)
print(mat.nbytes) # 144, matches ElemTypeColorMatrix.sizeof_m
Querying Type Properties via Python-Accessible Methods¶
All ElemType subclasses expose py_format(), py_itemsize(), py_ndim(),
py_shape(), and py_size() as static methods callable from Python:
from qlat_utils.types import ElemTypeColorMatrix, ElemTypeWilsonMatrix
from qlat_utils.types import ElemTypeComplexD, ElemTypeRealD, ElemTypeLong
# ColorMatrix: 3x3 complex double
assert ElemTypeColorMatrix.py_ndim() == 2
assert ElemTypeColorMatrix.py_shape() == (3, 3)
assert ElemTypeColorMatrix.py_itemsize() == 16
assert ElemTypeColorMatrix.py_size() == 144
assert ElemTypeColorMatrix.py_format() == 'Zd'
# WilsonMatrix: 12x12 complex double
assert ElemTypeWilsonMatrix.py_ndim() == 2
assert ElemTypeWilsonMatrix.py_shape() == (12, 12)
assert ElemTypeWilsonMatrix.py_itemsize() == 16
assert ElemTypeWilsonMatrix.py_size() == 2304
# Scalar types have ndim == 0 and empty shape
assert ElemTypeComplexD.py_ndim() == 0
assert ElemTypeComplexD.py_shape() == ()
assert ElemTypeComplexD.py_itemsize() == 16
assert ElemTypeComplexD.py_size() == 16
assert ElemTypeRealD.py_ndim() == 0
assert ElemTypeRealD.py_format() == 'd'
assert ElemTypeRealD.py_itemsize() == 8
assert ElemTypeLong.py_ndim() == 0
assert ElemTypeLong.py_format() == 'q'
assert ElemTypeLong.py_itemsize() == 8
Building a NumPy Array from Type Metadata¶
Use the Python-accessible methods to programmatically construct arrays whose layout matches a given ElemType, without hardcoding shape or dtype:
import numpy as np
from qlat_utils.types import ElemTypeSpinMatrix, ElemTypeWilsonVector
fmt_to_dtype = {
'Zd': np.complex128,
'Zf': np.complex64,
'd': np.float64,
'f': np.float32,
'q': np.int64,
'i': np.int32,
'b': np.int8,
}
def make_array(elem_type, count):
dtype = fmt_to_dtype[elem_type.py_format()]
shape = (count,) + elem_type.py_shape()
return np.zeros(shape, dtype=dtype)
# 10 SpinMatrix elements: shape (10, 4, 4), dtype complex128
arr = make_array(ElemTypeSpinMatrix, 10)
assert arr.shape == (10, 4, 4)
assert arr.dtype == np.complex128
assert arr.nbytes == 10 * ElemTypeSpinMatrix.py_size()
# 5 WilsonVector elements: shape (5, 12), dtype complex128
vec = make_array(ElemTypeWilsonVector, 5)
assert vec.shape == (5, 12)
assert vec.nbytes == 5 * ElemTypeWilsonVector.py_size()
Iterating Over All ElemType Subclasses¶
import numpy as np
from qlat_utils.types import (
ElemTypeColorMatrix, ElemTypeWilsonMatrix, ElemTypeNonRelWilsonMatrix,
ElemTypeIsospinMatrix, ElemTypeSpinMatrix, ElemTypeWilsonVector,
ElemTypeComplexD, ElemTypeComplexF, ElemTypeRealD, ElemTypeRealF,
ElemTypeLong, ElemTypeInt, ElemTypeChar, ElemTypeInt64t,
ElemTypeInt32t, ElemTypeInt8t,
)
all_types = [
ElemTypeColorMatrix, ElemTypeWilsonMatrix, ElemTypeNonRelWilsonMatrix,
ElemTypeIsospinMatrix, ElemTypeSpinMatrix, ElemTypeWilsonVector,
ElemTypeComplexD, ElemTypeComplexF, ElemTypeRealD, ElemTypeRealF,
ElemTypeLong, ElemTypeInt, ElemTypeChar, ElemTypeInt64t,
ElemTypeInt32t, ElemTypeInt8t,
]
for t in all_types:
assert t.py_size() == t.sizeof_m, f"{t.name}: py_size()={t.py_size()} != sizeof_m={t.sizeof_m}"
if t.py_ndim() > 0:
expected = t.py_itemsize() * int(np.prod(t.py_shape()))
else:
expected = t.py_itemsize()
assert t.py_size() == expected, f"{t.name}: py_size()={t.py_size()} != expected={expected}"
Verifying Consistency Between Properties¶
import numpy as np
from qlat_utils.types import (
ElemTypeColorMatrix, ElemTypeWilsonMatrix, ElemTypeNonRelWilsonMatrix,
ElemTypeIsospinMatrix, ElemTypeSpinMatrix, ElemTypeWilsonVector,
ElemTypeComplexD, ElemTypeComplexF, ElemTypeRealD, ElemTypeRealF,
ElemTypeLong, ElemTypeInt, ElemTypeChar, ElemTypeInt64t,
ElemTypeInt32t, ElemTypeInt8t,
)
all_types = [
ElemTypeColorMatrix, ElemTypeWilsonMatrix, ElemTypeNonRelWilsonMatrix,
ElemTypeIsospinMatrix, ElemTypeSpinMatrix, ElemTypeWilsonVector,
ElemTypeComplexD, ElemTypeComplexF, ElemTypeRealD, ElemTypeRealF,
ElemTypeLong, ElemTypeInt, ElemTypeChar, ElemTypeInt64t,
ElemTypeInt32t, ElemTypeInt8t,
]
for t in all_types:
assert t.py_size() == t.sizeof_m, f"{t.name}: py_size()={t.py_size()} != sizeof_m={t.sizeof_m}"
if t.py_ndim() > 0:
expected = t.py_itemsize() * int(np.prod(t.py_shape()))
else:
expected = t.py_itemsize()
assert t.py_size() == expected, f"{t.name}: py_size()={t.py_size()} != expected={expected}"
assert isinstance(t.name, str) and len(t.name) > 0
assert isinstance(t.py_ndim(), int) and t.py_ndim() >= 0
assert isinstance(t.py_shape(), tuple)
assert isinstance(t.py_itemsize(), int) and t.py_itemsize() > 0
assert isinstance(t.py_size(), int) and t.py_size() > 0
assert isinstance(t.py_format(), str) and len(t.py_format()) > 0