Loading...
Searching...
No Matches
hamiltonian_decay.hpp
Go to the documentation of this file.
1#pragma once
2
3/**
4 * HamiltonianDecay — how far a real-space Hamiltonian H(R) has decayed by the
5 * outermost shell of its lattice vectors.
6 *
7 * A local-orbital model is a Fourier sum over the lattice vectors of its
8 * domain, exact at the k-points it was built from whatever the sum's last
9 * terms are. Between those points the error IS those terms. So the largest
10 * term on the outermost shell, against the largest hopping anywhere, is the
11 * one number that predicts off-mesh error without a reference calculation --
12 * and unlike a spread it is in energy units and can be read as one.
13 *
14 * The denominator is the largest term that varies with k (any R other than
15 * zero, or an off-diagonal on-site element) rather than the largest on-site
16 * element, because the on-site diagonal carries the absolute zero of energy,
17 * which a pseudopotential sets arbitrarily; a ratio built on it would change
18 * under a rigid shift of every eigenvalue.
19 *
20 * The lengths are in whatever unit the domain's Cartesian vectors are in and
21 * the magnitudes in the Hamiltonian's; nothing here converts. It holds for a
22 * model built by any method, which is why it sits beside the Hamiltonian it
23 * measures rather than with one of them.
24 */
25
26#include <algorithm>
27#include <cmath>
28#include <cstddef>
29#include <stdexcept>
30#include <vector>
31
35
36namespace q3 {
37
38struct [[nodiscard]] HamiltonianDecay {
39 /// |R| of the outermost shell, in the lattice's length unit.
40 Real outermost_shell_distance = 0.0;
41 /// How many lattice vectors share that distance (to the registry's shell width).
42 int outermost_shell_size = 0;
43 /// The largest Bloch-sum term w_R |H_mn(R)| on that shell, in the Hamiltonian's unit.
44 Real outermost_shell_maximum = 0.0;
45 /// The largest term that varies with k: R away from the origin, or m != n on site.
46 Real largest_hopping = 0.0;
47 /// outermost_shell_maximum / largest_hopping; zero when there is nothing to divide by.
48 Real ratio = 0.0;
49
50 [[nodiscard]] static HamiltonianDecay measured_on(const LocalOrbitalHamiltonian& hamiltonian) {
51 const std::vector<LocalOrbitalLatticeVector>& vectors = hamiltonian.lattice_vectors();
52 const std::vector<std::vector<Complex>>& blocks = hamiltonian.hamiltonian_blocks();
53 if (vectors.empty() || blocks.size() != vectors.size()) {
54 throw std::runtime_error("HamiltonianDecay::measured_on: the Hamiltonian has no "
55 "blocks on its lattice vectors");
56 }
57 const std::size_t dimension = static_cast<std::size_t>(hamiltonian.number_of_orbitals());
58
59 HamiltonianDecay decay;
60 for (const LocalOrbitalLatticeVector& vector : vectors) {
62 std::max(decay.outermost_shell_distance, vector.cartesian.norm());
63 }
64 const Real shell_floor =
65 decay.outermost_shell_distance * (1.0 - math::tolerances::lattice_shell_relative_width);
66
67 for (std::size_t vector_index = 0; vector_index < vectors.size(); vector_index++) {
68 const LocalOrbitalLatticeVector& vector = vectors[vector_index];
69 const bool on_site = vector.translation == IntegerVector3D{0, 0, 0};
70 const bool on_outermost_shell = vector.cartesian.norm() >= shell_floor;
71 if (on_outermost_shell) {
73 }
74 const std::vector<Complex>& block = blocks[vector_index];
75 for (std::size_t element = 0; element < block.size(); element++) {
76 /// Column-major, so an element is on the diagonal when its row is its column.
77 const bool diagonal = element % dimension == element / dimension;
78 const Real magnitude = vector.bloch_sum_weight * std::abs(block[element]);
79 if (!on_site || !diagonal) {
80 decay.largest_hopping = std::max(decay.largest_hopping, magnitude);
81 }
82 if (on_outermost_shell) {
84 std::max(decay.outermost_shell_maximum, magnitude);
85 }
86 }
87 }
88 decay.ratio = decay.largest_hopping > 0.0
90 : 0.0;
91 return decay;
92 }
93};
94
95} // namespace q3
int number_of_orbitals() const
Definition init.hpp:119
const std::vector< std::vector< Complex > > & hamiltonian_blocks() const
Definition init.hpp:127
const std::vector< LocalOrbitalLatticeVector > & lattice_vectors() const
Definition init.hpp:123
double Real
Real outermost_shell_distance
|R| of the outermost shell, in the lattice's length unit.
Real largest_hopping
The largest term that varies with k: R away from the origin, or m != n on site.
int outermost_shell_size
How many lattice vectors share that distance (to the registry's shell width).
Real outermost_shell_maximum
The largest Bloch-sum term w_R |H_mn(R)| on that shell, in the Hamiltonian's unit.
Real ratio
outermost_shell_maximum / largest_hopping; zero when there is nothing to divide by.
static HamiltonianDecay measured_on(const LocalOrbitalHamiltonian &hamiltonian)
Integer 3-vector for Miller indices / FFT grid indices.
One lattice vector of the Hamiltonian's real-space domain.
Definition init.hpp:48
Vector3D cartesian
Cartesian R in whatever length unit the caller used; decay diagnostics only.
Definition init.hpp:51
IntegerVector3D translation
Definition init.hpp:49
Real norm() const
Definition vector_3d.hpp:68