pythtb.TBModel.velocity#

TBModel.velocity(k_pts, cartesian=False, flatten_spin_axis=False, *, param_periods=None, diff_scheme='central', diff_order=2, **params)[source]#

Generate the velocity operator in the orbital basis.

The velocity operator is related to the derivative of the Hamiltonian with respect to each reciprocal lattice direction, i.e.,

\[v_{\mu}(k) = \hbar \frac{\partial H(k)}{\partial k_{\mu}}\]

When passing parameter sweeps via **params, the generalized velocity operator is computed by appending finite-difference derivatives of the Hamiltonian with respect to the swept parameters.

Added in version 2.0.0.

Parameters:
k_pts(Nk, dim_k) numpy.ndarray

Reduced k-points where the velocity operator is evaluated. Must be a 2D array of shape (Nk, dim_k), where dim_k is the number of periodic directions in the model.

cartesianbool, optional

If True, use Cartesian coordinates for the velocity operator, otherwise derivatives are taken with respect to reduced coordinates.

flatten_spin_axisbool, optional

If True, the spin indices are flattened into the orbital indices. This results in a velocity operator of shape (..., norb*nspin, norb*nspin). If False (default), the velocity operator has shape (..., norb, nspin, norb, nspin).

param_periodsdict[str, float], optional

Optional map {param_name: period} for swept parameters. When supplied, assumes the parameter is cyclic and trims any duplicated endpoints, or endpoints equal to the start plus the given period, before building finite-difference stencils. This can improve numerical accuracy by using centered differences throughout the parameter range. Otherwise, the function will use a backward difference at the endpoint and a forward difference at the start.

diff_schemestr, optional

Finite difference scheme to use for parameter derivatives. Options are “central” (default) or “forward”. This parameter is only relevant when passing varying parameters.

diff_orderint, optional

Order of accuracy for finite difference lambda derivatives. Must be an even integer for “central” scheme (default is 4), and a positive integer for “forward” scheme. This parameter is only relevant when passing varying parameters.

**params

Parameter assignments. Scalars are applied directly; any 1D array/list is treated as a sweep and automatically adds a finite-difference derivative \(\partial_{\lambda} H\) for that parameter. The velocity operator is evaluated at all combinations of parameter values.

Returns:
velnumpy.ndarray

Velocity operator in the orbital basis. First axis indexes the cartesian direction if cartesian=True. Otherwise, it indexes the reduced direction. If include_lambda=True, the lambda (parameter) derivatives are appended after the k-directions along the first axis.

Shape is:

  • (n_dir, Nk, *param_shape, norb, norb) for spinless models,

  • (n_dir, Nk, *param_shape, norb, 2, norb, 2) for spinful models.

  • (..., norb*nspin, norb*nspin) if flatten_spin_axis=True.

where n_dir = dim_k + n_params, where n_params is the number of parameters being swept over.

Notes

  • We use units where \(\hbar = 1\), and thus the velocity operator is simply defined as the gradient of the Hamiltonian with respect to \(\mathbf{k}\) or \(\boldsymbol{\lambda}\).

  • The velocity operator is computed in tight-binding convention I, which includes phase factors associated with orbital positions in the hopping terms.

  • For the k-derivatives, if cartesian=True, the velocity operator is given by the derivative with respect to Cartesian \(\mathbf{k}\)-coordinates:

    \[v_\alpha(\mathbf{k}) = \frac{\partial H(\mathbf{k})}{\partial k_\alpha} = \sum_{\mathbf{R}} H_{ij}(\mathbf{R}) \, i(\mathbf{R} + \boldsymbol{\tau}_j - \boldsymbol{\tau}_i)_{\alpha} \, \exp[i \mathbf{k} \cdot (\mathbf{R} + \boldsymbol{\tau}_j - \boldsymbol{\tau}_i)]\]

    where \(\boldsymbol{\tau}_i\) and \(\boldsymbol{\tau}_j\) are the orbital positions in Cartesian coordinates, and \(\mathbf{R}\) are the lattice vectors in Cartesian coordinates.

  • For the k-derivatives, if cartesian=False, the velocity operator is given by the derivative with respect to reduced \(\boldsymbol{\kappa}\)-coordinates:

    \[v_\alpha(\boldsymbol{\kappa}) = \frac{\partial H(\boldsymbol{\kappa})}{\partial \kappa_\alpha} = \sum_{\mathbf{R}} H_{ij}(\mathbf{R}) \, i 2 \pi (\mathbf{R} + \boldsymbol{\tau_j} - \boldsymbol{\tau_i})_{\alpha} \, \exp[i 2 \pi \boldsymbol{\kappa} \cdot (\mathbf{R} + \boldsymbol{\tau_i}- \boldsymbol{\tau_j})]\]

    where \(\boldsymbol{\tau_i}\) and \(\boldsymbol{\tau_j}\) are the orbital positions in reduced coordinates, \(\boldsymbol{\kappa}\) are the k-points in reduced coordinates, and \(\mathbf{R}\) are the lattice vectors in reduced coordinates.

  • Passing a list/array for a parameter means you want derivatives with respect to that parameter. If the intent is simply to evaluate at a specific value, resolve the symbol first via set_parameters(), or simply pass a scalar value with **params.

  • When passing a list/array for a parameter, the finite difference derivatives are computed explicitly as

    \[\frac{\partial H}{\partial \lambda} \approx \sum_{m} c_m H(\lambda + m \Delta \lambda)\]

    where the coefficients \(c_m\) depend on the finite difference scheme and order.

Examples

Compute the velocity operator at the Gamma point:

>>> vel = tb.velocity(np.array([[0.0, 0.0]]))

Compute the velocity operator at several k-points with a parameter sweep. This will compute the velocity operator at all values of mA = 0.0, 1.0, 2.0 and the first axis will have length equal to dim_k + 1, with the last slice corresponding to the finite-difference derivative with respect to mA.

>>> vel = tb.velocity(
... np.array([[0.0, 0.0], [0.5, 0.5]]),
... mA=np.linspace(0, np.pi, 10, endpoint=False)
... )

If mA is a periodic parameter with period 2*pi, and 2*pi is included in the parameter list, we can inform the velocity function to trim the duplicated endpoint before building the finite-difference stencil. This can improve numerical accuracy by using centered differences throughout the parameter range. Otherwise, the function will use a backward difference at the endpoint and a forward difference at the start.

Specify this by passing a dictionary to the param_periods argument:

>>> vel = tb.velocity(
... np.array([[0.0, 0.0]]),
... mA=np.linspace(0, 2*np.pi, 10, endpoint=True),
... param_periods={"mA": 2*np.pi}
... )