Berry Curvature

double *diverge_fukui(diverge_model_t *m, complex128_t *U, index_t nb, index_t *nk)
[source]

Calculate Berry’s curvature \(\Omega(\boldsymbol{k})\) using the Fukui-Hatsugai method, normed to the Chern number, i.e., the sum of all elements for a certain chern band yields the Chern number of that band, not \(2\pi\) times the Chern number.

Parameters:
  • m (diverge_model_t) – model instance. obtain all parameters from there by default. internals must be set (diverge_model_internals_common()) in order to have U initialized. if NULL is passed, the function can still operate in case all the other parameters are set accordingly.

  • U (complex128_t*) – orbital to band matrices as (k,b,o) array. Use if != NULL.

  • nb (index_t) – number of bands. Use this if > 0.

  • nk (index_t*) – number of k points (3,) array. Use if != NULL. If nk[0] < 0 || nk[1] < 0 || nk[2] < 0, include transformation to improper gauge in the calculation of \(\Omega(\boldsymbol{k})\) and use abs(nk[i]) as number of \(\boldsymbol{k}\) points. In case the improper gauge is used, one can swap the sign convention by changing the number of negative dimensions.

Returns:

double array of shape (nk, nb, 3) that contains the Berry curvature along the three crystal axes. Must be freed manually by a call to free or diverge_mem_free(). May be NULL on errors.

double *diverge_fukui_non_abelian(diverge_model_t *m, complex128_t *U, index_t nb, index_t *nk, index_t *which_bands, index_t n_which_bands)
[source]

Calculate the non-abelian Berry curvature over a set of bands using Fukui’s method. As for diverge_fukui(), we norm it to the Chern number. The input parameters also follow the function diverge_fukui():

Parameters:
  • m (diverge_model_t) – model instance. obtain all parameters from there by default. internals must be set (diverge_model_internals_common()) in order to have U initialized. if NULL is passed, the function can still operate in case all the other parameters are set accordingly.

  • U (complex128_t*) – orbital to band matrices as (k,b,o) array. Use if != NULL.

  • nb (index_t) – number of bands. Use this if > 0.

  • nk (index_t*) – number of k points (3,) array. Use if != NULL. If nk[0] < 0 || nk[1] < 0 || nk[2] < 0, include transformation to improper gauge in the calculation of \(\Omega(\boldsymbol{k})\) and use abs(nk[i]) as number of \(\boldsymbol{k}\) points. In case the improper gauge is used, one can swap the sign convention by changing the number of negative dimensions.

  • which_bands (index_t*) – selection of bands to take the non-abelian determinant over

  • n_which_bands (index_t) – number of bands in the selection (same usage as in diverge_qgt())

Returns:

double array of shape (nk, 3) that contains the non-abelian Berry curvature along the three crystal axes. Must be freed manually by a call to free or diverge_mem_free(). May be NULL on errors.

double *diverge_qgt(diverge_model_t *m, complex128_t *U, index_t nb, index_t *nk, index_t *which_bands, index_t n_which_bands, int non_ortho_grad)
[source]

Calculate the Fubini-Study metric \(g(\boldsymbol k)\). It is defined as \(g(\boldsymbol k) = \frac{1}{2} \mathrm{Tr} \partial_i P_{\mathcal S} \partial_i P_\mathcal{S}\), where \(P^{o,o'}_{\mathcal S}(\boldsymbol k) = \sum_{b\in\mathcal S} U_{o,b}(\boldsymbol k) U_{o',b}^*(\boldsymbol k)\), and \(\mathcal S\) denotes a set of bands to sum over. Our implementation only takes finite differences along each of the lattice directions, which are transformed to cartesian coordinates with non_ortho_grad.

Parameters:
  • m (diverge_model_t) – the model instance. May be NULL in case all other parameters are given (non-NULL / not -1).

  • U (complex128_t*) – orbital to band matrices as (k,b,o) array; \(U_{o,b}(\boldsymbol k)\). May be NULL in case m contains common internals.

  • nb (index_t) – total number of bands in the system. May be -1 in case m is given.

  • nk (index_t*) – number of k points as array of shape (3,). May be NULL in case m is given. As for diverge_fukui(), if any of the provided mesh lengths is negative, this function transforms to the improper gauge; the model m must not be NULL for this to work. In case the improper gauge is used, one can swap the sign convention by changing the number of negative dimensions.

  • which_bands (index_t*) – the bands to sum over. Describes the set \(\mathcal S\). Must not be NULL. Array of shape (n_which_bands,).

  • n_which_bands (index_t) – number of bands to sum over. Describes the set \(\mathcal S\), i.e., the array which_bands.

  • non_ortho_grad (int) – boolean flag that determines whether the lattice vectors are taken into account in the calculation of \(\nabla f \cdot \nabla g\).

Returns:

a double array of size (nk,) with the values of \(g(\boldsymbol k)\). Must be free’d by the user by a call to free or diverge_mem_free().

complex128_t *diverge_qgt_tensor(diverge_model_t *m, complex128_t *U, index_t nb, index_t *nk, index_t *which_bands, index_t n_which_bands, int non_ortho_grad)
[source]

Calculate the full quantum geometric tensor \(\eta_{\mu\nu}(\boldsymbol k)\), which split into real- and imaginary parts yields the Berry curvature \(-2\mathrm{Im}\, \eta_{\mu\nu}(\boldsymbol k) = \Omega_{\mu\nu}(\boldsymbol k)\) (see diverge_fukui_non_abelian()) and the quantum metric \(\mathrm{Re}\, \eta_{\mu\nu}(\boldsymbol k) = g_{\mu\nu}(\boldsymbol k)\) (see diverge_qgt()). Following [Resta, EPJB 79, 121-137 (2011)], we can obtain the metric tensor in a fully gauge-invariant way by calculating \(\eta_{\mu\nu}(\boldsymbol k) = \mathrm{Tr}\big[ \partial_\mu \hat P(\boldsymbol k) \hat Q(\boldsymbol k) \partial_\nu \hat P(\boldsymbol k) \big]\). The projectors are defined as \(P_{o,o'}(\boldsymbol k) = \sum_{b\in\mathcal S} U_{o,b}(\boldsymbol k) U_{o',b}^*(\boldsymbol k)\) and \(\hat Q(\boldsymbol k) = 1 - \hat P(\boldsymbol k)\), where \(\mathcal S\) denotes the set of isolated bands to calculate the quantum metric over.

Note

The Berry curvature obtained from this function is not normalized intuitively. To obtain the Chern number (in a certain direction), you have to calculate

\[\mathcal C_{\mu\nu} = \frac{-2\pi}{A N_{\boldsymbol k}} \sum_{\boldsymbol k} \mathrm{Im}\big( \Omega_{\mu\nu}(\boldsymbol k) - \Omega_{\nu\mu}(\boldsymbol k)\big) \,,\]

with \(A = (\boldsymbol a_1 \times \boldsymbol a_2) \cdot \boldsymbol a_3\) the unit cell area.

The quantum metric (diverge_qgt()) is given in the same units:

\[g(\boldsymbol k) = \sum_i \mathrm{Re}\big( \eta_{ii}(\boldsymbol k) \big) \,.\]
Parameters:
  • m (diverge_model_t) – the model instance. May be NULL in case all other parameters are given (non-NULL / not -1).

  • U (complex128_t*) – orbital to band matrices as (k,b,o) array; \(U_{o,b}(\boldsymbol k)\). May be NULL in case m contains common internals.

  • nb (index_t) – total number of bands in the system. May be -1 in case m is given.

  • nk (index_t*) – number of k points as array of shape (3,). May be NULL in case m is given. As for diverge_fukui(), if any of the provided mesh lengths is negative, this function transforms to the improper gauge; the model m must not be NULL for this to work. In case the improper gauge is used, one can swap the sign convention by changing the number of negative dimensions.

  • which_bands (index_t*) – the bands to sum over. Describes the set \(\mathcal S\). Must not be NULL. Array of shape (n_which_bands,).

  • n_which_bands (index_t) – number of bands to sum over. Describes the set \(\mathcal S\), i.e., the array which_bands.

  • non_ortho_grad (int) – boolean flag that determines whether the lattice vectors are taken into account in the calculation of \(\nabla f \cdot \nabla g\).

Returns:

a complex128_t array of size (nk,3,3) with the values of \(\eta_{\mu\nu}(\boldsymbol k)\). Must be free’d by the user by a call to free or diverge_mem_free().