Skip to content

qten.topology.chern

Module reference for qten.topology.chern.

chern

Quantum geometry and first Chern number of momentum-resolved band Hamiltonians.

This module computes geometric properties of an isolated occupied-band subspace carried by a rank-3 Tensor with dims (MomentumSpace, HilbertSpace, HilbertSpace). The Hamiltonian is diagonalized independently at every momentum, and the n_occupied lowest-energy eigenvectors define the occupied projector \(P(k)\).

Core API
  • quantum_geometric_tensor Gauge-invariant quantum geometric tensor obtained from finite differences of the occupied projector.
  • fubini_study_metric Symmetric metric given by the real part of the quantum geometric tensor.
  • berry_curvature Local Berry curvature given by its imaginary antisymmetric part.
  • chern_number First Chern number computed either with discrete FHS link variables or by integrating the finite-difference Berry curvature.
  • FHSResult, QGTResult Result mappings returned by method="fhs" and method="qgt".
Mathematical convention

For occupied projector \(P(k)\), QTen uses

\[ Q_{ij}(k) = \operatorname{Tr}\!\left[ P(k)\,\partial_i P(k)\,\partial_j P(k) \right], \qquad g_{ij}(k) = \operatorname{Re} Q_{ij}(k), \qquad \Omega_{ij}(k) = 2\operatorname{Im} Q_{ij}(k). \]

The curvature sign agrees with the oriented plaquette used by chern_number(..., method="fhs"). Projector derivatives make these local quantities invariant under phase changes and general unitary rotations among occupied eigenvectors.

Momentum-grid convention

Finite differences follow every primitive quotient direction \(e_i\). Tensor components are therefore expressed per reciprocal-grid step. Local quantum-geometric results retain the input MomentumSpace as their first symbolic dimension. Their data therefore use the flat momentum-space order rather than an unlabeled rectangular reshape.

Numerical methods

The default Chern method is the gauge-invariant Fukui--Hatsugai--Suzuki (FHS) link-variable formula. It is the preferred finite-mesh topological invariant because a sufficiently resolved, isolated bundle gives an integer up to floating-point error. Integrating QGT-derived curvature exposes the connection between local quantum geometry and topology, but is a central-finite-difference estimate and generally approaches an integer only as the momentum mesh is refined.

FHSResult

Bases: TypedDict

Result of chern_number(..., method="fhs").

Discrete Fukui--Hatsugai--Suzuki Chern number on a complete 2-D reciprocal mesh. The runtime object is a plain dict.

Attributes:

Name Type Description
chern float

Sum of oriented plaquette phases divided by \(2\pi\).

nearest_integer int

numpy.rint(chern) as a convenience diagnostic, not a proof that the bundle is isolated.

direct_gap float

Minimum occupied-to-empty direct gap over the mesh.

berry_flux Tensor

Plaquette phase in radians as a labeled Tensor with dims (MomentumSpace,) and shape (N_k,). Momentum \(k\) labels the plaquette anchored at \(k\); the order matches the input Hamiltonian momentum space.

See Also

chern_number Public constructor of this mapping.

chern instance-attribute

chern: float

nearest_integer instance-attribute

nearest_integer: int

direct_gap instance-attribute

direct_gap: float

berry_flux instance-attribute

berry_flux: Tensor

QGTResult

Bases: TypedDict

Result of chern_number(..., method="qgt").

Chern number from integrated projector Berry curvature, plus the local quantum-geometric tensors. The runtime object is a plain dict.

Attributes:

Name Type Description
chern float

\((2\pi)^{-1}\sum_k\Omega_{xy}(k)\) from central finite differences. Approaches an integer only as the mesh is refined.

nearest_integer int

numpy.rint(chern) as a convenience diagnostic.

direct_gap float

Minimum occupied-to-empty direct gap over the mesh.

quantum_geometric_tensor Tensor

Complex QGT with dims (MomentumSpace, IndexSpace(2), IndexSpace(2)) and shape (N_k, 2, 2). Components are per reciprocal-grid step.

fubini_study_metric Tensor

Real part of quantum_geometric_tensor, same dims and shape.

berry_curvature Tensor

\(\Omega_{ij}=2\operatorname{Im}Q_{ij}\), same dims and shape. The \(xy\) orientation matches the FHS plaquette.

See Also

quantum_geometric_tensor Standalone QGT used to build this mapping. chern_number Public constructor of this mapping.

chern instance-attribute

chern: float

nearest_integer instance-attribute

nearest_integer: int

direct_gap instance-attribute

direct_gap: float

quantum_geometric_tensor instance-attribute

quantum_geometric_tensor: Tensor

fubini_study_metric instance-attribute

fubini_study_metric: Tensor

berry_curvature instance-attribute

berry_curvature: Tensor

quantum_geometric_tensor

quantum_geometric_tensor(
    bloch_hamiltonian: Tensor,
    n_occupied: int | None = None,
    gap_tolerance: float = 1e-08,
) -> Tensor

Compute the occupied-subspace quantum geometric tensor on a 1-D, 2-D, or 3-D grid.

The occupied projector is built from the n_occupied lowest-energy eigenvectors at every momentum. Central differences along every primitive reciprocal-grid direction approximate \(\partial_iP\), after which \(Q_{ij}=\operatorname{Tr}[P(\partial_iP)(\partial_jP)]\) is evaluated.

Parameters:

Name Type Description Default
bloch_hamiltonian Tensor

Rank-3 Hermitian Tensor with dims (MomentumSpace, HilbertSpace, HilbertSpace). The final two data axes must be square Hilbert-space matrices at each momentum and are aligned onto a common Hilbert space.

required
n_occupied int | None

Number of lowest-energy bands included in the occupied projector. Defaults to half the Hamiltonian bands using integer division.

None
gap_tolerance float

Minimum acceptable direct gap between bands n_occupied - 1 and n_occupied. A gap at or below this value emits a RuntimeWarning, because the selected bundle is not numerically isolated. Defaults to 1e-8.

1e-08

Returns:

Type Description
Tensor

Complex QGT with dims (MomentumSpace, IndexSpace(d), IndexSpace(d)) and shape (N_k, d, d), where d is the momentum-space dimension. The first dimension is the input Hamiltonian's momentum space, so momentum labels and their ordering are preserved. Components are measured per reciprocal-grid step, not per Cartesian inverse-length unit.

Raises:

Type Description
TypeError

If the first tensor dimension is not a MomentumSpace, or either matrix dimension is not a HilbertSpace.

ValueError

If the tensor is not rank 3, its Hamiltonian blocks are not square, n_occupied is invalid, the momentum space is not 1-D, 2-D, or 3-D, the boundary is not periodic, or momentum points do not form a unique complete reciprocal quotient.

Notes

The projector formulation is invariant under arbitrary momentum-dependent unitary rotations within the occupied subspace. It therefore remains well-defined when occupied bands cross each other, provided the occupied subspace stays separated from the empty bands.

See Also

fubini_study_metric Real part of this tensor. berry_curvature Imaginary antisymmetric part of this tensor. chern_number Brillouin-zone topological invariant.

Source code in src/qten/topology/chern.py
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
def quantum_geometric_tensor(
    bloch_hamiltonian: Tensor,
    n_occupied: int | None = None,
    gap_tolerance: float = 1e-8,
) -> Tensor:
    r"""Compute the occupied-subspace quantum geometric tensor on a 1-D, 2-D,
    or 3-D grid.

    The occupied projector is built from the ``n_occupied`` lowest-energy
    eigenvectors at every momentum. Central differences along every primitive
    reciprocal-grid direction approximate \(\partial_iP\), after which
    \(Q_{ij}=\operatorname{Tr}[P(\partial_iP)(\partial_jP)]\) is evaluated.

    Parameters
    ----------
    bloch_hamiltonian : Tensor
        Rank-3 Hermitian [`Tensor`][qten.linalg.tensors.Tensor] with dims
        ``(MomentumSpace, HilbertSpace, HilbertSpace)``. The final two data
        axes must be square Hilbert-space matrices at each momentum and are
        aligned onto a common Hilbert space.
    n_occupied : int | None, optional
        Number of lowest-energy bands included in the occupied projector.
        Defaults to half the Hamiltonian bands using integer division.
    gap_tolerance : float, optional
        Minimum acceptable direct gap between bands ``n_occupied - 1`` and
        ``n_occupied``. A gap at or below this value emits a
        `RuntimeWarning`, because the selected bundle is not
        numerically isolated. Defaults to ``1e-8``.

    Returns
    -------
    Tensor
        Complex QGT with dims ``(MomentumSpace, IndexSpace(d),
        IndexSpace(d))`` and shape ``(N_k, d, d)``, where ``d`` is the
        momentum-space dimension. The first dimension is the input
        Hamiltonian's momentum space, so momentum labels and their ordering
        are preserved. Components are measured per reciprocal-grid step, not
        per Cartesian inverse-length unit.

    Raises
    ------
    TypeError
        If the first tensor dimension is not a
        [`MomentumSpace`][qten.symbolics.state_space.MomentumSpace], or either
        matrix dimension is not a `HilbertSpace`.
    ValueError
        If the tensor is not rank 3, its Hamiltonian blocks are not square,
        ``n_occupied`` is invalid, the momentum space is not 1-D, 2-D, or 3-D,
        the boundary is not periodic, or momentum points do not form a unique
        complete reciprocal quotient.

    Notes
    -----
    The projector formulation is invariant under arbitrary momentum-dependent
    unitary rotations within the occupied subspace. It therefore remains
    well-defined when occupied bands cross each other, provided the occupied
    subspace stays separated from the empty bands.

    See Also
    --------
    [`fubini_study_metric`][qten.topology.fubini_study_metric]
        Real part of this tensor.
    [`berry_curvature`][qten.topology.berry_curvature]
        Imaginary antisymmetric part of this tensor.
    [`chern_number`][qten.topology.chern_number]
        Brillouin-zone topological invariant.
    """
    grid = _topology_grid(bloch_hamiltonian, n_occupied, gap_tolerance)
    return _quantum_geometric_tensor_from_grid(grid)

fubini_study_metric

fubini_study_metric(
    bloch_hamiltonian: Tensor,
    n_occupied: int | None = None,
    gap_tolerance: float = 1e-08,
) -> Tensor

Compute the occupied-subspace Fubini--Study metric on a 1-D, 2-D, or 3-D grid.

This function returns \(g_{ij}(k)=\operatorname{Re}Q_{ij}(k)\), where the QGT is computed by quantum_geometric_tensor.

Parameters:

Name Type Description Default
bloch_hamiltonian Tensor

Rank-3 Hermitian Tensor with dims (MomentumSpace, HilbertSpace, HilbertSpace).

required
n_occupied int | None

Number of lowest-energy occupied bands. Defaults to half the bands.

None
gap_tolerance float

Direct-gap warning threshold. Defaults to 1e-8.

1e-08

Returns:

Type Description
Tensor

Real metric with dims (MomentumSpace, IndexSpace(d), IndexSpace(d)) and shape (N_k, d, d). Components are expressed per reciprocal-grid step.

Raises:

Type Description
TypeError

If the first tensor dimension is not a momentum space.

ValueError

If the Hamiltonian, occupied-band selection, or reciprocal grid is invalid. See quantum_geometric_tensor for the complete validation contract.

See Also

quantum_geometric_tensor Complex parent tensor of the metric and curvature. berry_curvature Berry curvature from the imaginary part of the QGT.

Source code in src/qten/topology/chern.py
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
def fubini_study_metric(
    bloch_hamiltonian: Tensor,
    n_occupied: int | None = None,
    gap_tolerance: float = 1e-8,
) -> Tensor:
    r"""Compute the occupied-subspace Fubini--Study metric on a 1-D, 2-D,
    or 3-D grid.

    This function returns \(g_{ij}(k)=\operatorname{Re}Q_{ij}(k)\), where the
    QGT is computed by
    [`quantum_geometric_tensor`][qten.topology.quantum_geometric_tensor].

    Parameters
    ----------
    bloch_hamiltonian : Tensor
        Rank-3 Hermitian [`Tensor`][qten.linalg.tensors.Tensor] with dims
        ``(MomentumSpace, HilbertSpace, HilbertSpace)``.
    n_occupied : int | None, optional
        Number of lowest-energy occupied bands. Defaults to half the bands.
    gap_tolerance : float, optional
        Direct-gap warning threshold. Defaults to ``1e-8``.

    Returns
    -------
    Tensor
        Real metric with dims ``(MomentumSpace, IndexSpace(d),
        IndexSpace(d))`` and shape ``(N_k, d, d)``. Components are expressed
        per reciprocal-grid step.

    Raises
    ------
    TypeError
        If the first tensor dimension is not a momentum space.
    ValueError
        If the Hamiltonian, occupied-band selection, or reciprocal grid is
        invalid. See
        [`quantum_geometric_tensor`][qten.topology.quantum_geometric_tensor]
        for the complete validation contract.

    See Also
    --------
    [`quantum_geometric_tensor`][qten.topology.quantum_geometric_tensor]
        Complex parent tensor of the metric and curvature.
    [`berry_curvature`][qten.topology.berry_curvature]
        Berry curvature from the imaginary part of the QGT.
    """
    return quantum_geometric_tensor(bloch_hamiltonian, n_occupied, gap_tolerance).real()

berry_curvature

berry_curvature(
    bloch_hamiltonian: Tensor,
    n_occupied: int | None = None,
    gap_tolerance: float = 1e-08,
) -> Tensor

Compute occupied-subspace Berry curvature on a 1-D, 2-D, or 3-D grid.

QTen uses \(\Omega_{ij}(k)=2\operatorname{Im}Q_{ij}(k)\). In two dimensions, the \(xy\) orientation agrees with chern_number(..., method="fhs").

Parameters:

Name Type Description Default
bloch_hamiltonian Tensor

Rank-3 Hermitian Tensor with dims (MomentumSpace, HilbertSpace, HilbertSpace).

required
n_occupied int | None

Number of lowest-energy occupied bands. Defaults to half the bands.

None
gap_tolerance float

Direct-gap warning threshold. Defaults to 1e-8.

1e-08

Returns:

Type Description
Tensor

Pointwise real antisymmetric curvature tensor at every momentum, with dims (MomentumSpace, IndexSpace(d), IndexSpace(d)) and shape (N_k, d, d). In two dimensions, summing curvature.data[..., 0, 1] and dividing by 2*pi gives the central-finite-difference estimate of the first Chern number.

Raises:

Type Description
TypeError

If the first tensor dimension is not a momentum space.

ValueError

If the Hamiltonian, occupied-band selection, or reciprocal grid is invalid. See quantum_geometric_tensor for the complete validation contract.

Notes

This is QGT-derived curvature, not the compact plaquette flux returned by chern_number(..., method="fhs"). Its integral need not be exactly quantized on a finite grid.

See Also

quantum_geometric_tensor Complex tensor from which the curvature is derived. chern_number FHS or curvature-integral Chern number.

Source code in src/qten/topology/chern.py
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
def berry_curvature(
    bloch_hamiltonian: Tensor,
    n_occupied: int | None = None,
    gap_tolerance: float = 1e-8,
) -> Tensor:
    r"""Compute occupied-subspace Berry curvature on a 1-D, 2-D, or 3-D grid.

    QTen uses \(\Omega_{ij}(k)=2\operatorname{Im}Q_{ij}(k)\). In two dimensions,
    the \(xy\) orientation agrees with
    [`chern_number(..., method="fhs")`][qten.topology.chern_number].

    Parameters
    ----------
    bloch_hamiltonian : Tensor
        Rank-3 Hermitian [`Tensor`][qten.linalg.tensors.Tensor] with dims
        ``(MomentumSpace, HilbertSpace, HilbertSpace)``.
    n_occupied : int | None, optional
        Number of lowest-energy occupied bands. Defaults to half the bands.
    gap_tolerance : float, optional
        Direct-gap warning threshold. Defaults to ``1e-8``.

    Returns
    -------
    Tensor
        Pointwise real antisymmetric curvature tensor at every momentum, with dims
        ``(MomentumSpace, IndexSpace(d), IndexSpace(d))`` and shape
        ``(N_k, d, d)``. In two dimensions, summing
        ``curvature.data[..., 0, 1]`` and dividing by ``2*pi`` gives the
        central-finite-difference estimate of the first Chern number.

    Raises
    ------
    TypeError
        If the first tensor dimension is not a momentum space.
    ValueError
        If the Hamiltonian, occupied-band selection, or reciprocal grid is
        invalid. See
        [`quantum_geometric_tensor`][qten.topology.quantum_geometric_tensor]
        for the complete validation contract.

    Notes
    -----
    This is QGT-derived curvature, not the compact plaquette flux returned by
    ``chern_number(..., method="fhs")``. Its integral need not be exactly
    quantized on a finite grid.

    See Also
    --------
    [`quantum_geometric_tensor`][qten.topology.quantum_geometric_tensor]
        Complex tensor from which the curvature is derived.
    [`chern_number`][qten.topology.chern_number]
        FHS or curvature-integral Chern number.
    """
    qgt = quantum_geometric_tensor(bloch_hamiltonian, n_occupied, gap_tolerance)
    return 2.0 * qgt.imag()

chern_number

chern_number(
    bloch_hamiltonian: Tensor,
    n_occupied: int | None = None,
    gap_tolerance: float = 1e-08,
    *,
    method: Literal["fhs"] = "fhs",
) -> FHSResult
chern_number(
    bloch_hamiltonian: Tensor,
    n_occupied: int | None = None,
    gap_tolerance: float = 1e-08,
    *,
    method: Literal["qgt"],
) -> QGTResult

Compute the first Chern number of an occupied band subspace.

The n_occupied lowest-energy eigenstates define an occupied bundle over a complete two-dimensional periodic momentum grid. Two numerical methods are available:

  • method="fhs" computes normalized determinant link variables between neighboring occupied subspaces and sums their oriented plaquette phases. This gauge-invariant Fukui--Hatsugai--Suzuki construction is the default and the recommended finite-grid topological invariant.
  • method="qgt" computes the projector quantum geometric tensor, takes \(\Omega_{xy}=2\operatorname{Im}Q_{xy}\), and evaluates \(C=(2\pi)^{-1}\sum_k\Omega_{xy}(k)\). It additionally returns all local quantum-geometric data.

Parameters:

Name Type Description Default
bloch_hamiltonian Tensor

Rank-3 Hermitian Tensor with dims (MomentumSpace, HilbertSpace, HilbertSpace). The first data axis enumerates a complete two-dimensional reciprocal quotient; the last two axes are square Bloch-Hamiltonian matrices and are aligned onto a common Hilbert space.

required
n_occupied int | None

Number of lowest-energy bands defining the occupied subspace. It must lie strictly between zero and the total band count. Defaults to half the bands using integer division.

None
gap_tolerance float

Warning threshold for the minimum direct gap \(\min_k[E_{n_\mathrm{occupied}}(k)- E_{n_\mathrm{occupied}-1}(k)]\). A gap at or below this value emits a RuntimeWarning, because the occupied bundle is not isolated and its Chern number is not well-defined. Defaults to 1e-8.

1e-08
method (fhs, qgt)

Numerical construction. "fhs" uses discrete determinant link variables and is robustly quantized on a suitable finite mesh. "qgt" integrates central-finite-difference curvature and exposes local quantum geometry. Defaults to "fhs".

"fhs"

Returns:

Type Description
dict[str, Any]

Result mapping. Both methods return:

  • "chern": raw floating-point Chern value.
  • "nearest_integer": nearest integer obtained with numpy.rint.
  • "direct_gap": minimum occupied-to-empty direct gap.

For method="fhs" the mapping also contains "berry_flux", the oriented plaquette phase in radians as a labeled Tensor with dims (MomentumSpace,) and shape (N_k,). Momentum \(k\) labels the plaquette anchored at \(k\), and the order matches the input MomentumSpace.

For method="qgt" the mapping instead contains labeled Tensor values: "quantum_geometric_tensor" and "fubini_study_metric" and "berry_curvature" all have shape (N_k, 2, 2). Each retains the input momentum space as its first dimension.

Raises:

Type Description
TypeError

If the first tensor dimension is not a MomentumSpace, or either matrix dimension is not a HilbertSpace.

ValueError

If method is unsupported; the input is not a rank-3 square Bloch Hamiltonian; n_occupied is outside the valid range; the momentum space is not two-dimensional and periodic; or its points do not form a unique complete reciprocal quotient.

RuntimeError

For method="fhs", if a neighboring occupied-subspace overlap has determinant magnitude below 1e-14. This indicates a singular link; increasing the momentum-grid resolution may resolve it.

Warns:

Type Description
RuntimeWarning

If the minimum direct gap is no larger than gap_tolerance.

Notes

The FHS value satisfies

\[ C_\mathrm{FHS} = \frac{1}{2\pi} \sum_k \operatorname{Arg}\!\left[ U_x(k)U_y(k+e_x)U_x(k+e_y)^*U_y(k)^* \right], \]

where \(U_i(k)\) is the phase of the determinant of the occupied-subspace overlap between \(k\) and \(k+e_i\). Determinants make the formula invariant under arbitrary unitary changes of occupied-band basis.

nearest_integer is a convenience diagnostic, not proof that the bundle is isolated or the mesh is sufficiently resolved. Inspect direct_gap and, when necessary, repeat the calculation on finer momentum grids.

The flux tensor is intentionally flat for every cell: its symbolic MomentumSpace dimension preserves labels without implying rectangular heatmap adjacency. This is especially important for sheared cells, whose quotient-representative order is not a rectangular Brillouin-zone heatmap.

Examples:

Use the robust finite-grid method:

result = chern_number(hamiltonian, n_occupied=1)
invariant = result["nearest_integer"]
flux = result["berry_flux"]

Request the differential-geometric decomposition:

geometry = chern_number(hamiltonian, n_occupied=1, method="qgt")
metric = geometry["fubini_study_metric"]
curvature = geometry["berry_curvature"]
See Also

quantum_geometric_tensor Gauge-invariant local quantum geometric tensor. fubini_study_metric Metric part of the QGT. berry_curvature Curvature part of the QGT.

Source code in src/qten/topology/chern.py
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
def chern_number(
    bloch_hamiltonian: Tensor,
    n_occupied: int | None = None,
    gap_tolerance: float = 1e-8,
    *,
    method: Literal["fhs", "qgt"] = "fhs",
) -> FHSResult | QGTResult:
    r"""Compute the first Chern number of an occupied band subspace.

    The ``n_occupied`` lowest-energy eigenstates define an occupied bundle over
    a complete two-dimensional periodic momentum grid. Two numerical methods
    are available:

    - ``method="fhs"`` computes normalized determinant link variables between
      neighboring occupied subspaces and sums their oriented plaquette phases.
      This gauge-invariant Fukui--Hatsugai--Suzuki construction is the default
      and the recommended finite-grid topological invariant.
    - ``method="qgt"`` computes the projector quantum geometric tensor, takes
      \(\Omega_{xy}=2\operatorname{Im}Q_{xy}\), and evaluates
      \(C=(2\pi)^{-1}\sum_k\Omega_{xy}(k)\). It additionally returns all local
      quantum-geometric data.

    Parameters
    ----------
    bloch_hamiltonian : Tensor
        Rank-3 Hermitian [`Tensor`][qten.linalg.tensors.Tensor] with dims
        ``(MomentumSpace, HilbertSpace, HilbertSpace)``. The first data axis
        enumerates a complete two-dimensional reciprocal quotient; the last
        two axes are square Bloch-Hamiltonian matrices and are aligned onto
        a common Hilbert space.
    n_occupied : int | None, optional
        Number of lowest-energy bands defining the occupied subspace. It must
        lie strictly between zero and the total band count. Defaults to half
        the bands using integer division.
    gap_tolerance : float, optional
        Warning threshold for the minimum direct gap
        \(\min_k[E_{n_\mathrm{occupied}}(k)-
        E_{n_\mathrm{occupied}-1}(k)]\). A gap at or below this value emits a
        `RuntimeWarning`, because the occupied bundle is not
        isolated and its Chern number is not well-defined. Defaults to
        ``1e-8``.
    method : {"fhs", "qgt"}, optional
        Numerical construction. ``"fhs"`` uses discrete determinant link
        variables and is robustly quantized on a suitable finite mesh.
        ``"qgt"`` integrates central-finite-difference curvature and exposes
        local quantum geometry. Defaults to ``"fhs"``.

    Returns
    -------
    dict[str, Any]
        Result mapping. Both methods return:

        - ``"chern"``: raw floating-point Chern value.
        - ``"nearest_integer"``: nearest integer obtained with `numpy.rint`.
        - ``"direct_gap"``: minimum occupied-to-empty direct gap.

        For ``method="fhs"`` the mapping also contains ``"berry_flux"``, the
        oriented plaquette phase in radians as a labeled `Tensor` with dims
        ``(MomentumSpace,)`` and shape ``(N_k,)``. Momentum \(k\) labels the
        plaquette anchored at \(k\), and the order matches the input
        `MomentumSpace`.

        For ``method="qgt"`` the mapping instead contains labeled `Tensor`
        values: ``"quantum_geometric_tensor"`` and
        ``"fubini_study_metric"`` and ``"berry_curvature"`` all have shape
        ``(N_k, 2, 2)``. Each retains the input momentum space as its first
        dimension.

    Raises
    ------
    TypeError
        If the first tensor dimension is not a
        [`MomentumSpace`][qten.symbolics.state_space.MomentumSpace], or either
        matrix dimension is not a `HilbertSpace`.
    ValueError
        If ``method`` is unsupported; the input is not a rank-3 square Bloch
        Hamiltonian; ``n_occupied`` is outside the valid range; the momentum
        space is not two-dimensional and periodic; or its points do not form a
        unique complete reciprocal quotient.
    RuntimeError
        For ``method="fhs"``, if a neighboring occupied-subspace overlap has
        determinant magnitude below ``1e-14``. This indicates a singular link;
        increasing the momentum-grid resolution may resolve it.

    Warns
    -----
    RuntimeWarning
        If the minimum direct gap is no larger than ``gap_tolerance``.

    Notes
    -----
    The FHS value satisfies

    \[
    C_\mathrm{FHS} = \frac{1}{2\pi}
    \sum_k \operatorname{Arg}\!\left[
      U_x(k)U_y(k+e_x)U_x(k+e_y)^*U_y(k)^*
    \right],
    \]

    where \(U_i(k)\) is the phase of the determinant of the occupied-subspace
    overlap between \(k\) and \(k+e_i\). Determinants make the formula
    invariant under arbitrary unitary changes of occupied-band basis.

    ``nearest_integer`` is a convenience diagnostic, not proof that the bundle
    is isolated or the mesh is sufficiently resolved. Inspect ``direct_gap``
    and, when necessary, repeat the calculation on finer momentum grids.

    The flux tensor is intentionally flat for every cell: its symbolic
    `MomentumSpace` dimension preserves labels without implying rectangular
    heatmap adjacency. This is especially important for sheared cells, whose
    quotient-representative order is not a rectangular Brillouin-zone heatmap.

    Examples
    --------
    Use the robust finite-grid method:

    ```python
    result = chern_number(hamiltonian, n_occupied=1)
    invariant = result["nearest_integer"]
    flux = result["berry_flux"]
    ```

    Request the differential-geometric decomposition:

    ```python
    geometry = chern_number(hamiltonian, n_occupied=1, method="qgt")
    metric = geometry["fubini_study_metric"]
    curvature = geometry["berry_curvature"]
    ```

    See Also
    --------
    [`quantum_geometric_tensor`][qten.topology.quantum_geometric_tensor]
        Gauge-invariant local quantum geometric tensor.
    [`fubini_study_metric`][qten.topology.fubini_study_metric]
        Metric part of the QGT.
    [`berry_curvature`][qten.topology.berry_curvature]
        Curvature part of the QGT.
    """
    if method == "fhs":
        return _discrete_chern_number(bloch_hamiltonian, n_occupied, gap_tolerance)
    if method != "qgt":
        raise ValueError("method must be 'fhs' or 'qgt'.")

    grid = _topology_grid(bloch_hamiltonian, n_occupied, gap_tolerance)
    if grid.momentum_dim != 2:
        raise ValueError("The first Chern number requires a two-dimensional grid.")
    qgt = _quantum_geometric_tensor_from_grid(grid)
    curvature = 2.0 * qgt.imag()
    chern = float(curvature.data[..., 0, 1].sum() / (2.0 * np.pi))
    return {
        "chern": chern,
        "nearest_integer": int(np.rint(chern)),
        "direct_gap": grid.direct_gap,
        "quantum_geometric_tensor": qgt,
        "fubini_study_metric": qgt.real(),
        "berry_curvature": curvature,
    }