Skip to content

API documentation

Models

dot_abs_chain(length, params=None)

Construct a spinful dot/ABS chain Hamiltonian.

The model includes on-site chemical potentials and Zeeman energies, Coulomb repulsion, s-wave pairing, nearest-neighbour hopping, and spin-orbit coupling.

Parameters:

Name Type Description Default
length int

Number of lattice sites.

required
params dict | None

Parameter policy for each physical quantity. When None the function creates symbolic defaults following the specification in :func:pmm_tools.model_helper.prepare_parameters.

None

Returns:

Type Description
tuple[dict[str, Any], Expr, list[FermionOp]]

The prepared parameter dictionary, symbolic Hamiltonian expression, and the list of spinful fermionic operators ordered as [c_{0↑}, c_{0↓}, c_{1↑}, …].

Source code in pmm_tools/models.py
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
def dot_abs_chain(
    length: int, params: dict[str, Any] | None = None
) -> tuple[dict[str, Any], Expr, list[FermionOp]]:
    """Construct a spinful dot/ABS chain Hamiltonian.

    The model includes on-site chemical potentials and Zeeman energies, Coulomb repulsion,
    s-wave pairing, nearest-neighbour hopping, and spin-orbit coupling.

    Args:
        length (int): Number of lattice sites.
        params (dict | None): Parameter policy for each physical quantity. When ``None`` the
            function creates symbolic defaults following the specification in
            :func:`pmm_tools.model_helper.prepare_parameters`.

    Returns:
        The prepared parameter dictionary, symbolic Hamiltonian expression, and the list of spinful fermionic operators ordered as ``[c_{0↑}, c_{0↓}, c_{1↑}, …]``.
    """

    lengths = {
        "mu": {"len": length, "real": True},
        "E_z": {"len": length, "real": True},
        "Delta": {"len": length, "real": False},
        "t_n": {"len": length - 1, "real": True},
        "t_so": {"len": length - 1, "real": True},
        "U": {"len": length, "real": True},
    }

    params = prepare_parameters(params, lengths)

    fermions = define_operators(length, True)

    # on-site
    H = sum(
        (_get_param_value(params["mu"], i) + _get_param_value(params["E_z"], i))
        * Dagger(fermions[2 * i])
        * fermions[2 * i]
        + (_get_param_value(params["mu"], i) - _get_param_value(params["E_z"], i))
        * Dagger(fermions[2 * i + 1])
        * fermions[2 * i + 1]
        for i in range(length)
    )

    # coulomb repulsion
    H += sum(
        _get_param_value(params["U"], i)
        * Dagger(fermions[2 * i])
        * fermions[2 * i]
        * Dagger(fermions[2 * i + 1])
        * fermions[2 * i + 1]
        for i in range(length)
    )

    # s-wave pairing
    H += sum(
        _get_param_value(params["Delta"], i)
        * Dagger(fermions[2 * i])
        * Dagger(fermions[2 * i + 1])
        + Dagger(_get_param_value(params["Delta"], i))
        * fermions[2 * i + 1]
        * fermions[2 * i]
        for i in range(length)
    )

    # normal hopping
    H += sum(
        _get_param_value(params["t_n"], i // 2) * (Dagger(a) * b + Dagger(b) * a)
        for i, (a, b) in enumerate(zip(fermions, fermions[2:]))
    )

    # SOI
    H += sum(
        -_get_param_value(params["t_so"], i) * (Dagger(a) * b + Dagger(b) * a)
        for i, (a, b) in enumerate(list(zip(fermions, fermions[3:]))[::2])
    )
    H += sum(
        _get_param_value(params["t_so"], i) * (Dagger(a) * b + Dagger(b) * a)
        for i, (a, b) in enumerate(list(zip(fermions, fermions[1:]))[1::2])
    )

    return params, H, fermions

interacting_kiteav_chain(length, params=None)

Build a spinless Kitaev-style chain with interactions.

Parameters:

Name Type Description Default
length int

Number of lattice sites.

required
params dict | None

Parameter policy describing the chemical potential, hopping, pairing, and interaction strengths. The accepted value formats match :func:pmm_tools.model_helper.prepare_parameters.

None

Returns:

Type Description
tuple[dict[str, Any], Expr, list[str]]

The prepared parameter mapping, the symbolic Hamiltonian in second quantization, and the list of fermionic operator labels.

Source code in pmm_tools/models.py
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
def interacting_kiteav_chain(
    length: int, params: dict[str, Any] | None = None
) -> tuple[dict[str, Any], Expr, list[str]]:
    """Build a spinless Kitaev-style chain with interactions.

    Args:
        length (int): Number of lattice sites.
        params (dict | None): Parameter policy describing the chemical potential, hopping,
            pairing, and interaction strengths. The accepted value formats match
            :func:`pmm_tools.model_helper.prepare_parameters`.

    Returns:
        The prepared parameter mapping, the symbolic Hamiltonian in second quantization, and the list of fermionic operator labels.
    """

    # expected parameter lengths
    lengths = {
        "mu": {"len": length, "real": True},
        "t": {"len": length - 1, "real": True},
        "Delta": {"len": length - 1, "real": True},
        "U": {"len": length - 1, "real": True},
    }
    params = prepare_parameters(params, lengths)

    # Generate fermionic operator names
    names = ["c_{i}".format(i=i) for i in range(length)]
    fermions = [FermionOp(name) for name in names]

    # Create the Hamiltonian
    H = sum(
        _get_param_value(params["t"], i) * Dagger(a) * b
        for i, (a, b) in enumerate(zip(fermions, fermions[1:]))
    )

    H += sum(
        _get_param_value(params["Delta"], i) * Dagger(a) * Dagger(b)
        for i, (a, b) in enumerate(zip(fermions, fermions[1:]))
    )

    H += Dagger(H)

    H += sum(
        _get_param_value(params["mu"], i) * Dagger(fermions[i]) * fermions[i]
        for i in range(len(fermions))
    )

    H += sum(
        _get_param_value(params["U"], i) * Dagger(a) * a * Dagger(b) * b
        for i, (a, b) in enumerate(zip(fermions, fermions[1:]))
    )

    return params, H, names

Model helpers

define_operators(length, spinful=False)

Create fermionic ladder operators for a 1D lattice.

Parameters:

Name Type Description Default
length int

Number of spatial sites.

required
spinful bool

If True generate both and operators for each site. If False produce a single spinless operator per site. Defaults to False.

False

Returns:

Type Description
list[FermionOp]

Fermionic annihilation operators named c_{i} (spinless) or c_{i↑}/c_{i↓} (spinful). Operators are created with real=True and commutative=True to match SymPy’s second-quantization conventions.

Source code in pmm_tools/model_helper.py
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
def define_operators(length: int, spinful: bool = False) -> list[FermionOp]:
    """Create fermionic ladder operators for a 1D lattice.

    Args:
        length (int): Number of spatial sites.
        spinful (bool, optional): If ``True`` generate both ``↑`` and ``↓`` operators for each site. If ``False`` produce a single spinless operator per site. Defaults to ``False``.

    Returns:
        Fermionic annihilation operators named ``c_{i}`` (spinless) or ``c_{i↑}``/``c_{i↓}`` (spinful). Operators are created with ``real=True`` and ``commutative=True`` to match SymPy’s second-quantization conventions.
    """

    if spinful:
        co_index = [r"\uparrow", r"\downarrow"]
    else:
        co_index = [""]
    return [
        FermionOp(r"c_{{{0}{1}}}".format(*elm), real=True, commutative=True)
        for elm in list(product([i for i in range(length)], co_index))
    ]

prepare_parameters(parameters, specs)

Prepare and validate a parameter specification.

Parameters:

Name Type Description Default
parameters dict | None

Mapping describing the value policy for each parameter. Each value can be: * a SymPy expression or numeric scalar to keep constant, * a sequence whose length matches specs[param]["len"], or * the strings "constant" / "space-dependent" to request automatic symbol creation. When None, every parameter defaults to "constant".

required
specs dict

Metadata describing the required length and realness of each parameter.

required

Returns:

Type Description
dict[str, Any]

Prepared parameter mapping containing scalars, lists of symbols, or the original

dict[str, Any]

sequence objects.

Raises:

Type Description
ValueError

If a provided value does not match the required length or uses an unsupported declarative string.

Source code in pmm_tools/model_helper.py
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
def prepare_parameters(
    parameters: dict[str, Any] | None, specs: dict[str, dict[str, Any]]
) -> dict[str, Any]:
    """Prepare and validate a parameter specification.

    Args:
        parameters (dict | None): Mapping describing the value policy for each parameter.
            Each value can be:
                * a SymPy expression or numeric scalar to keep constant,
                * a sequence whose length matches ``specs[param]["len"]``, or
                * the strings ``"constant"`` / ``"space-dependent"`` to request automatic
                  symbol creation.
            When ``None``, every parameter defaults to ``"constant"``.
        specs (dict): Metadata describing the required length and realness of each parameter.

    Returns:
        Prepared parameter mapping containing scalars, lists of symbols, or the original
        sequence objects.

    Raises:
        ValueError: If a provided value does not match the required length or uses an
            unsupported declarative string.
    """
    # If parameters is None, create a default dictionary with "constant" as the default value
    if parameters is None:
        parameters = {param: "constant" for param in specs.keys()}

    prepared_params = {}

    for param, value in parameters.items():
        # Get the required length for this parameter
        required_length = specs[param]["len"]
        real = specs[param]["real"]

        if isinstance(value, Expr):  # Single constant symbol or expression
            prepared_params[param] = value

        elif isinstance(value, (int, float)):  # Numeric constants
            prepared_params[param] = value

        elif isinstance(value, str):  # "constant" or "space-dependent"
            if value == "constant":
                prepared_params[param] = symbols(param, real=real)
            elif value == "space-dependent":
                if required_length is None:
                    raise ValueError(
                        f"Parameter '{param}' is space-dependent, but no length is specified."
                    )
                prepared_params[param] = [
                    symbols(f"{param}_{i}", real=real) for i in range(required_length)
                ]
            else:
                raise ValueError(
                    f"Invalid string value '{value}' for parameter '{param}'. "
                    "Expected 'constant' or 'space-dependent'."
                )

        elif hasattr(
            value, "__getitem__"
        ):  # Integer-indexable object (e.g., list, tuple, numpy array)
            # Validate the length of the provided array-like object
            if required_length is not None and len(value) != required_length:
                raise ValueError(
                    f"Parameter '{param}' has an array of length {len(value)}, "
                    f"but the required length is {required_length}."
                )
            prepared_params[param] = value

        else:
            raise ValueError(f"Invalid value for parameter '{param}': {value}")

    return prepared_params