Quantum 3xplorer (Q3)
An AI-native quantum simulation engine
Loading...
Searching...
No Matches
specification.hpp
Go to the documentation of this file.
1#pragma once
2
3/**
4 * InterpolationSpecification — the `control.interpolation` block of an input.
5 *
6 * One block serves two steps of the same feature, and which step is meant is
7 * decided by `control.calculation`, not by the block:
8 *
9 * - On an NSCF run the block is a BUILD request: the engine constructs a
10 * small model of the band structure from its converged states -- for
11 * `method: wannier`, the interface matrices on the full k-grid -- and saves
12 * it as `<prefix>.save/interpolation.q3ip`, plus whatever interoperability
13 * formats `export_formats` lists. `grid` is required here: the k-points arrive as
14 * an explicit `control.kpoints_list`, which carries no grid shape of its
15 * own, and the neighbour arithmetic needs one.
16 * - On `calculation: interpolation` the block is an EVALUATION request,
17 * consumed by `q3_utility interpolate`, never by the engine: read the saved
18 * model and evaluate it along `control.band_path` / `control.kpoints_list`
19 * and, when `dos_mesh` is set, on that dense mesh for a density of states.
20 *
21 * Method-specific keys (`projection_centers`, `projection_decay_bohr`) sit in
22 * the same block rather than in a per-method sub-block so that an input reads
23 * as one decision -- "interpolate, this way". With one method there is nothing
24 * to refuse yet; when a second lands, the parser owns the rule that a key the
25 * chosen method does not use is an error rather than an ignored field.
26 */
27
28#include <array>
29#include <map>
30#include <string>
31#include <vector>
32
37
38namespace q3 {
39
41 /// "" when no interpolation was asked for; otherwise the method name ("wannier").
42 std::string method;
43
44 /// The full k-point grid `control.kpoints_list` enumerates; {0,0,0} = not stated.
45 std::array<int, 3> grid = {0, 0, 0};
46
47 /**
48 * The 1-based inclusive band range the model is built from; {0,0} = not
49 * stated, meaning the lowest bands.
50 *
51 * A range exists because the manifold worth modelling does not always
52 * start at band 1. A pseudopotential that carries semicore states puts
53 * them underneath it -- gallium with 3d in valence adds five bands below
54 * GaAs's four sp valence bands -- and those lower bands are a different,
55 * separately isolated manifold rather than something to interpolate
56 * alongside. Selecting a range is NOT disentanglement: it picks a
57 * contiguous set that must still be isolated from what surrounds it at
58 * every k-point. A manifold that is entangled with its neighbours, as a
59 * transition metal's d and s bands are, is not fixed by any choice of
60 * range.
61 */
62 std::array<int, 2> bands = {0, 0};
63
64 /**
65 * Wannier: centres of the s-type trial orbitals in crystal coordinates.
66 * Empty selects the pseudopotentials' own atom-centred orbitals -- the
67 * wrong shape whenever the Wannier functions are not on atoms (silicon's
68 * valence manifold lives on the bonds), so the example states them.
69 */
70 std::vector<Vector3D> projection_centers;
71 /// Wannier: decay length of those orbitals in bohr (Wannier90's `zona` is 1/a).
73
74 /**
75 * Build step: which of each species' pseudo-atomic shells become trial
76 * orbitals, as 0-based indices in the order the pseudopotential file lists
77 * its atomic wavefunctions. A species not named keeps every shell its
78 * pseudopotential does not mark unusable (a negative occupation, or a
79 * zero-norm radial function), which is the whole set and the default.
80 *
81 * An augmented dataset lists more than its atom's valence: a PAW file's
82 * unoccupied second s and p partial waves, an ultrasoft file's empty 4s and
83 * 4p projector channels. As trial orbitals they double the functions asked
84 * for and the band window sized from them. The automatic workflow decides
85 * which shells to leave out and writes them here; the engine honours the
86 * list and does not guess.
87 */
88 std::map<std::string, std::vector<int>> trial_shells;
89
90 /**
91 * How the N states the gauge is built from are chosen out of the band
92 * window: "" or "none" requires the window to be exactly those states,
93 * "projectability" classifies and then optimises the subspace.
94 */
95 std::string disentanglement;
96 /// The classifier's thresholds; the defaults are BandClassificationThresholds' own.
99 /**
100 * In electronvolts; see the schema for why this is not redundant with the
101 * above. Read only when `frozen_window_is_automatic` is false.
102 */
104 /**
105 * `frozen_window_above_fermi_ev: auto`, the default: the classifier
106 * applies the published window for atomic projectors, E_F + 2 eV, to metal
107 * and insulator alike (BandClassifier documents why the two are not
108 * treated differently). A number given explicitly overrides it.
109 */
111
112 /**
113 * Evaluation step: the spread minimiser's iteration budget. Three thousand
114 * is far more than a well-posed case needs (copper converges in about
115 * sixty); the retry ladder doubles it after a stall, which is the one
116 * reason it is a key rather than a constant. The default is
117 * SpreadMinimizationSettings' own.
118 */
120
121 /**
122 * Evaluation step: the subspace iteration's budget and its relative
123 * convergence tolerance; the defaults are DisentanglementSettings' own. A disentanglement
124 * that exhausts the budget throws with its last five spreads, and the retry
125 * ladder loosens the tolerance to a margin above the change among them: the
126 * iteration is deterministic, so the retry stops no later than the failure
127 * did, where a larger budget would cost as much again.
128 */
131
132 /**
133 * How the gauge inside the chosen subspace is fixed.
134 *
135 * auto minimise the spread when the record carries the neighbour
136 * overlaps, and keep the projection gauge when it does not.
137 * maximal minimise it, and fail if the record cannot support that.
138 * none keep the projection gauge.
139 *
140 * The default is "auto" rather than "maximal" because the spread is defined
141 * through M_mn(k,b), and a record imported from another code's projections
142 * and eigenvalues alone does not carry them. Defaulting to a demand would
143 * make every such record an error for asking for the default -- so the
144 * default is a preference and "maximal" is the demand. Localising is the
145 * preference because the projection gauge is exact at the mesh points
146 * whatever it does, which means a model built without it looks perfect
147 * where it was fitted and is only as good as its trial orbitals everywhere
148 * else, which is where an interpolator is actually used.
149 */
150 std::string localization = "auto";
151
152 /// Interoperability formats to write beside the native record ("wannier90").
153 std::vector<std::string> export_formats;
154
155 /// Evaluation step: the dense k-mesh for the interpolated DOS; {0,0,0} = none.
156 std::array<int, 3> dos_mesh = {0, 0, 0};
157
158 [[nodiscard]] bool requested() const {
159 return !method.empty();
160 }
161 [[nodiscard]] bool has_grid() const {
162 return grid[0] > 0 && grid[1] > 0 && grid[2] > 0;
163 }
164 [[nodiscard]] bool disentangles() const {
165 return disentanglement == "projectability";
166 }
167 [[nodiscard]] bool has_band_selection() const {
168 return bands[0] > 0 && bands[1] > 0;
169 }
170 /// 0-based index of the first selected band; 0 when no range was given.
171 [[nodiscard]] int first_band_index() const {
172 return has_band_selection() ? bands[0] - 1 : 0;
173 }
174 /// How many bands the range holds; 0 when no range was given.
175 [[nodiscard]] int number_of_selected_bands() const {
176 return has_band_selection() ? bands[1] - bands[0] + 1 : 0;
177 }
178 [[nodiscard]] bool wants_density_of_states() const {
179 return dos_mesh[0] > 0 && dos_mesh[1] > 0 && dos_mesh[2] > 0;
180 }
181};
182
183} // namespace q3
double Real
Real projectability_maximum
p >= this freezes a band regardless of its energy.
Real projectability_minimum
p < this discards a band, whatever its energy: the singular-gauge rule.
Real convergence_tolerance
Relative, because an absolute spread threshold does not transfer between systems.
std::map< std::string, std::vector< int > > trial_shells
int first_band_index() const
0-based index of the first selected band; 0 when no range was given.
int number_of_selected_bands() const
How many bands the range holds; 0 when no range was given.
std::string method
"" when no interpolation was asked for; otherwise the method name ("wannier").
std::array< int, 3 > grid
The full k-point grid control.kpoints_list enumerates; {0,0,0} = not stated.
Real projection_decay_bohr
Wannier: decay length of those orbitals in bohr (Wannier90's zona is 1/a).
Real projectability_minimum
The classifier's thresholds; the defaults are BandClassificationThresholds' own.
std::array< int, 3 > dos_mesh
Evaluation step: the dense k-mesh for the interpolated DOS; {0,0,0} = none.
std::vector< Vector3D > projection_centers
std::vector< std::string > export_formats
Interoperability formats to write beside the native record ("wannier90").