Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -413,3 +413,9 @@ docs/superpowers/
# committed once, so every full `pytest` run left a spurious deletion in
# `git status`.) Committed inputs here are .dat/.in files, never *_fixture.npz.
tests/rpa/input/*_fixture.npz

# Superpowers planning/handoff docs (internal, not shipped)
docs/superpowers

# Validation harness run artifacts (regenerated by run.sh)
tests/validation/**/work/
1 change: 1 addition & 0 deletions docs/en/source/algorithm/al-index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@ Algorithms
uhf
rpa
eliashberg
uhfk_to_mvmc

172 changes: 172 additions & 0 deletions docs/en/source/algorithm/uhfk_to_mvmc.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
.. highlight:: none

UHFk to mVMC PairProduct conversion
***************************************

``tools/uhfk_to_mvmc.py`` converts a self-consistent H-wave UHFk solution
into the initial PairProduct wave function of mVMC. This chapter states the
conventions and the construction. For usage, see
:doc:`../uhfk/tools/uhfk_to_mvmc`.

The conversion has four stages: extraction of the occupied Slater columns,
gauge composition under sublattice folding, construction of the pair
amplitude :math:`F`, and, when spin-orbit coupling is present, emission of
``trans.def``.

Bloch amplitude sign convention
===============================

The bridge adopts the **positive-Bloch amplitude convention**, that is, the
real-space amplitude is defined as

.. math::

c_R = \frac{1}{\sqrt{N_\mathrm{folded}}} \sum_k c_k e^{+i k R}

This sign is fixed by H-wave's internal conventions and is not a free
choice. H-wave treats antiperiodic boundary conditions with the
negative-sign gauge

.. math::

\tilde{c}_r = e^{-i \theta r / L_\mathrm{phys}} c_r

and uses ``ifftn(..., norm="forward")`` for the inverse Fourier transform.
Composing the two makes the Bloch transform on the tilde side positive.

For ``SubShape = [1, 1, 1]`` the :math:`(k, -k)` time-reversal sum
symmetrizes the plane-wave factor, so the density does not depend on the
choice of sign. For ``SubShape > [1, 1, 1]`` the sublattice envelope of the
folded eigenvectors is non-trivial, the two conventions are distinguishable,
and only the positive convention agrees element-wise with H-wave's
``greenone.dat``.

Sublattice folding and gauge composition
========================================

When ``SubShape`` divides ``CellShape`` in every direction, the lattice is
folded onto a supercell. The folded orbital index encodes the cell position
``sub_offset`` within the supercell together with the original orbital
index. Physical sites are reconstructed by decomposing that index.

Two phases multiply the Slater matrix under folding, and they are composed:

.. math::

\exp\left[-i k_\mathrm{folded} \cdot (\mathrm{folded\_cell} + \mathrm{sub\_offset})\right]
\times
\exp\left[-i \theta \cdot r_\mathrm{phys} / L_\mathrm{phys}\right]

The first factor is the gauge of the intra-supercell offset, the second is
the antiperiodic boundary twist. ``build_slater_orbitals`` applies the
composed phase to the emitted Slater matrix.

On the verification side, ``gauge_lift`` uses the same composed transform to
lift H-wave's ``green_sublattice``, which is stored in the folded Bloch
basis, into the physical basis. Because both share one transform, the
density check can take the emitted Slater matrix itself as its subject.

Construction of the pair amplitude F
====================================

The one-body density matrix convention is

.. math::

G_{ij} = \langle c^\dagger_i c_j \rangle = \left(\overline{A} A^{T}\right)_{ij}

where :math:`A` denotes the matrix of occupied Slater columns.

Canonical pairs
---------------

Pairs are emitted from one canonical row per unordered pair
:math:`\{k, \mathrm{partner}(k)\}`. The canonical row is defined as follows.

- For a self-pair (:math:`\mathrm{partner}(k) = k`), :math:`k` itself is
canonical.
- Otherwise, the row whose wavevector index tuple is lexicographically
smaller is canonical, with the smaller row index as tie-break.

:math:`F` is a :math:`(2N_\mathrm{site}, 2N_\mathrm{site})` complex
antisymmetric matrix; the lower triangle is filled by
:math:`F_{ji} = -F_{ij}`.

Partner balance
---------------

For the canonical pair emission to close consistently, the two rows of a
pair must carry the same occupation. The bridge rejects, before conversion,
any occupation for which either of the following holds.

- Some pair has :math:`n_\mathrm{occ}(k) \neq n_\mathrm{occ}(\mathrm{partner}(k))`.
- A canonical self-pair :math:`k` has odd :math:`n_\mathrm{occ}(k)`.

``validate_general_prerequisites`` performs this check and reports a failing
occupation as an error. It does not silently emit an approximate result.

When choosing a filling, the spectral gap alone is not sufficient. The gap
says nothing about how the occupation is distributed over the two rows of a
canonical pair, so the partner-balance invariant has to be checked
separately.

Projection to the density
-------------------------

Obtaining the one-body density from :math:`F` uses a skew-SVD projection.
The leading :math:`2 N_\mathrm{pairs}` left singular vectors span the
occupied subspace. This projection is used to verify that the emitted
:math:`F` represents the intended Slater state.

Transfer mapping convention
===========================

When spin-orbit coupling is present, the ``trans.def`` produced by mVMC's
``vmcdry.out`` keeps only the spin-diagonal entries and drops the
:math:`s \neq t` terms. The bridge therefore emits ``trans.def`` directly
from H-wave's ``Transfer.dat``.

The mapping is as follows. The mVMC convention is
:math:`H = -\sum \mathrm{trans}\, c^\dagger c`, and ComplexUHF builds its
bare Hamiltonian as :math:`K = -\mathrm{trans}`. In H-wave's negative-Bloch
physical basis, an entry :math:`(R, s, t, v)` of ``Transfer.dat`` maps at
displacement :math:`+R` as

.. math::

K[i, t;\, i+R, s] &= \overline{v} \\
\mathrm{trans}[i, t;\, i+R, s] &= -\overline{v}

The site endpoints stay :math:`i \to i+R`, the **spin endpoints are
swapped**, and the coefficient is conjugated and negated. On a real
spin-diagonal entry the swap is a no-op and the rule reduces to
:math:`\mathrm{trans} = -v`.

This general rule is derived. It follows the path from H-wave's
:math:`e^{+ikR}` transform under ``ifftn(norm="forward")``, through the
Hermitian transpose, to ComplexUHF's :math:`K = -\mathrm{trans}`. As
numerical support, reconstructing H-wave's bare :math:`K` from all stored
eigenpairs gives a maximum absolute deviation of
:math:`1.1 \times 10^{-12}` for this rule, with no entry above
:math:`10^{-10}`.

The older rule, which does not swap the spin endpoints (:math:`-v` for
:math:`s = t` and :math:`+v` for :math:`s \neq t`), was not derived; it was
pinned so that the numbers agreed, and it is a special case rather than an
equivalent. The two rules emit the same matrix only for matrices satisfying
:math:`v[t,s] = -\overline{v[s,t]}` at fixed :math:`R`. A system with
in-plane Rashba coupling alone satisfies that condition, so no difference
appears there, but a spin-symmetric hopping carrying both a real and an
imaginary part does not. In the same reconstruction the older rule gives a
maximum absolute deviation of :math:`6.0 \times 10^{-1}`.

The boundary wrap phase is applied **after** conjugation. A row crossing the
boundary along an antiperiodic direction is multiplied by
:math:`e^{+i\theta_d}` for a crossing at positive :math:`R` and
:math:`e^{-i\theta_d}` for a crossing at negative :math:`R`.

.. note::

The verified range covers only :math:`\theta` whose components are in
:math:`\{0, \pi\}`, where the wrap phase is real. A general complex
twist is out of scope and has not been verified.
21 changes: 21 additions & 0 deletions docs/en/source/uhfk/filespecification/config/index_config.rst
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,27 @@ Parameters
**Description :**
This parameter specifies the shape of the sublattice Bx, By, Bz.

- ``BoundaryCondition``

**Type :**
List of strings of length 3 (default value is ``["periodic", "periodic", "periodic"]``)

**Description :**
This parameter specifies the boundary condition along each spatial direction (x, y, z).
Accepted values per direction (case-insensitive):
``"periodic"`` / ``"P"`` and ``"antiperiodic"`` / ``"AP"``.
Antiperiodic corresponds to a twist angle of :math:`\pi`.

Compatible with any ``SubShape``, including the default
``SubShape = CellShape``. The gauge phase is applied to the input
``Transfer`` in its original signed-displacement representation before
any sublattice fold, so the choice of ``SubShape`` does not change the
physical result.

Non-density-type interactions (``PairHop``, ``PairLift``) combined with
any antiperiodic direction are rejected, because they are not gauge
invariant under the site-dependent gauge used to implement APBC.

- ``T``

**Type :**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ The following code is an example for reading the data from the output file.

wavevector_unit = data["wavevector_unit"]
wavevector_index = data["wavevector_index"]
twist_offset = data["twist_offset"]

``eigenvalue`` contains the eigenvalues :math:`\lambda_l(\vec{k})` for each wave number.
The wave number is taken in unit of sublattice when the sublattice is considered.
Expand All @@ -48,5 +49,19 @@ The wave number vector that corresponds to the index ``k`` is obtained by

k_vec = np.dot(wavevector_index[k], wavevector_unit)

``twist_offset`` contains the per-direction twist offset
:math:`\theta_d / (2\pi)` for the boundary condition under which the
calculation was run. Each component is ``0`` for ``periodic`` and ``1/2`` for
``antiperiodic``. The physical wave number that corresponds to the index ``k``
under arbitrary boundary conditions is obtained by

.. code-block:: python

k_vec_phys = np.dot(wavevector_index[k] + twist_offset, wavevector_unit)

Under full periodic boundaries ``twist_offset`` is all zeros, so consumers
that ignore the field continue to observe the original integer-grid
behavior (backward compatible).


.. raw:: latex
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,18 @@ In this case the file also carries the key ``green_convention`` with the value
``green_slot_first``, which records the fold-sign convention of the ``green`` key
so that it can be folded back unambiguously (e.g. when reused as RPA ``green_init``).

When ``BoundaryCondition`` includes ``antiperiodic`` directions, the
Green's function stored under ``green`` (and ``green_sublattice``) is in the
gauge-transformed basis used internally by the SCF, NOT the physical
:math:`\langle c_{i\sigma_1}^{\dagger}c_{j\sigma_2}^{\phantom{\dagger}}\rangle`
on the antiperiodic boundary. The applied twist is recorded as
``boundary_theta`` in the same npz file. The user-facing physical Green
under APBC is emitted by ``onebodyg`` (``greenone.dat``), where the
inverse gauge phase is undone per (i, j) pair before output.
Restarting from a Green saved under APBC must be done with the same
``BoundaryCondition``; a mismatch is reported as a warning at restart
read time.

The following code is an example for reading the data from the output file.

.. code-block:: python
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@ This section describes the file formats of the outputs of UHFk.
energy_uhfk
eigen_uhfk
green_uhfk
occupation_uhfk
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
.. highlight:: none

occupation.npz
~~~~~~~~~~~~~~

The converged SCF occupation, chemical potential, temperature, and
per-column metadata are saved to ``occupation.npz`` (key name
configurable via ``[file.output].occupation``; default
``occupation.npz``). Consumers (notably the ``tools/uhfk_to_mvmc.py``
bridge) need this information together with ``eigen.npz`` to project
finite-temperature occupations to T=0 Slater determinants without
re-solving the SCF.

Keys
^^^^

- ``occupation`` (shape ``(nvol, nd)``, ``float64``)
Fermi-Dirac weight :math:`f(\epsilon_{k,n})` per (k-point, band)
used at the final SCF iteration. At T=0 the values are 0 or 1; at
T>0 they are fractional.

- ``mu`` (shape ``(n_mu_groups,)``, ``float64``)
Chemical potential per mu-group. With ``2Sz = 0`` in Sz-fixed mode,
there are 2 groups (up, down); in Sz-free mode there is 1 group.

- ``T`` (scalar ``float64``)
Temperature used during SCF.

- ``column_spin`` (shape ``(nd,)``, ``int64``)
Spin character of each eigenvector column. ``0`` = up-only block,
``1`` = down-only block, ``-1`` = mixed (Sz-free).

- ``column_mu_group`` (shape ``(nd,)``, ``int64``)
Mu-group index for each column. ``mu[column_mu_group[n]]`` gives the
chemical potential associated with column ``n``.

Conventions
^^^^^^^^^^^

The column layout matches the ``eigenvector`` array in ``eigen.npz``:
columns are arranged by block order from ``UHFk._init_block_structure``,
and rows live in the original ``nd`` index space.
9 changes: 9 additions & 0 deletions docs/en/source/uhfk/tools/index_tools.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
.. _uhfk_tools_index:

Auxiliary tools
~~~~~~~~~~~~~~~

.. toctree::
:maxdepth: 1

uhfk_to_mvmc
Loading
Loading