Loading...
Searching...
No Matches
init.hpp
Go to the documentation of this file.
1#pragma once
2
3/**
4 * MeanFieldRecord — everything a mean-field exporter needs, as plain data.
5 *
6 * This is the seam that turns Q3's in-process exporters into converters. The
7 * BerkeleyGW writers used to read a live
8 * `NormConservingPlanewaveKohnShamSCFState`, which tied them to a running SCF:
9 * getting a file wrong meant re-running the calculation, and a second output
10 * format meant another engine flavor and another `control.*` key. They now read
11 * this record instead, and the record can be built two ways:
12 *
13 * - `build_mean_field_record()` (from_scf_state.hpp) — from a live SCF state,
14 * for the in-process export; and
15 * - `read_mean_field_record()` (checkpoint.hpp) — from `<prefix>.save/`, for
16 * the standalone converter.
17 *
18 * Same writer code either way, so the two paths cannot drift. This mirrors how
19 * Quantum ESPRESSO splits `pw.x` from `pw2bgw.x`, and is what makes a second
20 * format (Yambo, HDF5 `WFN.h5`) a converter over this record rather than more
21 * engine surface area.
22 *
23 * Everything here is plain data with one deliberate exception: wavefunction
24 * coefficients come through MeanFieldBandSource. Materializing every band would
25 * change the in-process path's peak memory from one band to all of them, which
26 * is a real regression on large systems for no benefit -- the live source hands
27 * back a pointer into the quantum system exactly as before, and the file-backed
28 * source reads one k-point at a time.
29 *
30 * Units follow `Crystal`'s own conventions rather than a new normalized set:
31 * lattice vectors and Cartesian atom positions in units of `alat`, reciprocal
32 * lattice vectors in units of `tpiba` = 2*pi/alat, `alat`/`cell_volume` in
33 * bohr and bohr^3, energies in Rydberg, k-points and fractional translations in
34 * crystal coordinates, Miller indices as integers. Re-scaling to bohr here
35 * would only force every writer to undo it -- BerkeleyGW wants exactly these
36 * units. Format-specific conversions that are genuinely format-specific (BGW's
37 * Ry->eV for `vxc.dat`, its `sum(kw) = 1` renormalization) stay in the writers.
38 */
39
40#include <array>
41#include <memory>
42#include <vector>
43
47
48namespace q3 {
49
50/**
51 * Per-band plane-wave coefficients, fetched on demand.
52 *
53 * `coefficients()` returns a pointer to `plane_waves_per_kpoint[kpoint_index]`
54 * contiguous values, valid until the next call for a different k-point (the
55 * file-backed implementation caches one k-point). Callers write them out
56 * immediately, which is all any exporter does.
57 */
59 public:
60 virtual ~MeanFieldBandSource() = default;
61
62 /**
63 * `kpoint_state_index` is the (k-point, spin) state index, matching the
64 * eigenvalue/occupation row convention below -- not the physical k-point
65 * index. They coincide only for a spin-unpolarized run.
66 */
67 [[nodiscard]] virtual const Complex* coefficients(int kpoint_state_index,
68 int band_index) const = 0;
69};
70
71struct [[nodiscard]] MeanFieldRecord {
72 // ── Cell ─────────────────────────────────────────────────────────
73 /// QE `ibrav` convention; 0 means explicit/free lattice vectors.
74 int bravais_lattice_index = 0;
75 Real lattice_parameter = 0.0; // alat, bohr
76 Real two_pi_over_lattice_parameter = 0.0; // tpiba, 1/bohr
77 Real cell_volume = 0.0; // bohr^3
78 Matrix3x3 lattice_vectors; // rows are a1/a2/a3, in alat units
79 Matrix3x3 reciprocal_lattice_vectors; // rows are b1/b2/b3, in tpiba units
80
81 // ── Atoms ────────────────────────────────────────────────────────
82 /// Cartesian positions in alat units, parallel to `atomic_numbers`.
83 std::vector<Vector3D> atom_positions_cartesian;
84 std::vector<int> atomic_numbers;
85
86 // ── Symmetry ─────────────────────────────────────────────────────
87 /**
88 * Already resolved, so a converter never needs spglib. `reciprocal_rotation`
89 * is `(rotation^-1)^T`, which is what BerkeleyGW's `tnp` record is built
90 * from -- see berkeleygw/header.hpp.
91 */
92 std::vector<SymmetryOperation> symmetry_operations;
93
94 // ── Basis ────────────────────────────────────────────────────────
95 /// Charge-density ("dense") FFT grid dimensions.
96 std::array<int, 3> fft_grid_dimensions = {0, 0, 0};
97 /**
98 * Miller indices of the charge-density G set, in the engine's own order.
99 * Only the integer indices are kept: every mean-field format writes those,
100 * and none of them needs the Cartesian coordinates or |G|^2 that the
101 * engine's GVector also carries. Keeping this order stable matters --
102 * per-k-point G sets below index into it.
103 */
104 std::vector<IntegerVector3D> charge_density_miller_indices;
105 bool is_gamma_only = false;
106 /// Plane-wave kinetic-energy cutoffs, Rydberg (BGW's `ecutrho`/`ecutwfc`).
107 Real charge_density_energy_cutoff = 0.0;
108 Real wavefunction_energy_cutoff = 0.0;
109
110 // ── k-points ─────────────────────────────────────────────────────
111 /**
112 * Monkhorst-Pack grid dimensions and 0/1 shift flags as requested.
113 * Explicit k-point lists retain zero dimensions and shifts.
114 */
115 std::array<int, 3> kpoint_grid_dimensions = {0, 0, 0};
116 std::array<int, 3> kpoint_grid_shifts = {0, 0, 0};
117 /// Crystal (fractional) coordinates, one per physical k-point.
118 std::vector<Vector3D> kpoint_coordinates;
119 /// Engine-convention weights; formats renormalize as they require.
120 std::vector<Real> kpoint_weights;
121 std::vector<int> plane_waves_per_kpoint;
122 /// Per physical k-point, indices into `charge_density_miller_indices`.
123 std::vector<std::vector<int>> kpoint_g_vector_indices;
124
125 // ── Bands ────────────────────────────────────────────────────────
126 int number_of_bands = 0;
127 int number_of_spin_components = 1;
128 /// Indexed [kpoint_state_index][band_index]; Rydberg.
129 std::vector<std::vector<Real>> eigenvalues_rydberg;
130 /// Indexed [kpoint_state_index][band_index]; max 1 per (k, spin) state.
131 std::vector<std::vector<Real>> occupations;
132 std::shared_ptr<const MeanFieldBandSource> band_source;
133
134 // ── Fields ───────────────────────────────────────────────────────
135 /**
136 * Charge density on the charge-density G set, one entry per spin channel,
137 * each parallel to `charge_density_miller_indices`.
138 *
139 * G-space rather than real-space on purpose. The engine holds rho(r) and
140 * the writers used to call `PlanewaveBasis::rho_r_to_g()` themselves --
141 * a *computation*, which a converter reading files has no basis to
142 * perform. Doing the transform once while the record is built keeps the
143 * record purely descriptive, and matches
144 * `exchange_correlation_potential_g`, which is G-space already. Not scaled
145 * by the cell volume: that is BerkeleyGW's convention, applied by its
146 * writer.
147 */
148 std::vector<std::vector<Complex>> charge_density_g;
149 /**
150 * Exchange-correlation potential on the charge-density G set, Rydberg,
151 * parallel to `charge_density_miller_indices`. Empty when the producing run
152 * did not have one; `vxc.dat` export refuses rather than inventing values.
153 */
155 /**
156 * The local Kohn-Sham potential the Hamiltonian applied -- ionic local plus
157 * Hartree plus exchange-correlation -- one entry per spin channel, Rydberg,
158 * parallel to `charge_density_miller_indices`, G = 0 the cell average.
159 * Empty when the producing run did not have one, which includes every
160 * record read back from `mean-field.q3mf`; `VSC` export then refuses.
161 */
162 std::vector<std::vector<Complex>> self_consistent_potential_g;
163
164 // ── Nonlocal pseudopotential ─────────────────────────────────────
165 /**
166 * Filled only when the projectors were requested
167 * (`control.mean_field_export_kleinman_bylander_projectors`), and only for
168 * norm-conserving datasets: then V_NL = Σ_atom |β⟩ D ⟨β| is the whole
169 * nonlocal part of H. `projector_source` stays null otherwise, and the
170 * `VKB` file is not written.
171 */
172 /// 0-based species index of each atom, parallel to `atomic_numbers`.
173 std::vector<int> atom_species_indices;
174 /// Projector channels -- one per (β, m) -- of each species.
175 std::vector<int> projectors_per_species;
176 /**
177 * D_ij in Rydberg, indexed [spin][atom], each block
178 * `projectors_per_species[species]` squared values with the first index
179 * fastest -- the channel order of `projector_source`'s rows for that atom.
180 */
181 std::vector<std::vector<std::vector<Real>>> nonlocal_coefficients;
182 std::shared_ptr<const MeanFieldProjectorSource> projector_source;
183
184 [[nodiscard]] int number_of_kpoints() const {
185 return static_cast<int>(kpoint_coordinates.size());
186 }
187
188 [[nodiscard]] int number_of_atoms() const {
189 return static_cast<int>(atomic_numbers.size());
190 }
191
192 [[nodiscard]] int number_of_g_vectors() const {
193 return static_cast<int>(charge_density_miller_indices.size());
194 }
195
196 /// (k-point, spin) state count -- the row count of eigenvalues/occupations.
197 [[nodiscard]] int number_of_kpoint_states() const {
198 return number_of_kpoints() * number_of_spin_components;
199 }
200};
201
202} // namespace q3
virtual const Complex * coefficients(int kpoint_state_index, int band_index) const =0
virtual ~MeanFieldBandSource()=default
double Real
std::complex< double > Complex
3×3 matrix stored row-major: row i = mat[i]
std::vector< Vector3D > kpoint_coordinates
Crystal (fractional) coordinates, one per physical k-point.
Definition init.hpp:118
std::vector< std::vector< Real > > occupations
Indexed [kpoint_state_index][band_index]; max 1 per (k, spin) state.
Definition init.hpp:131
int number_of_atoms() const
Definition init.hpp:188
std::vector< std::vector< int > > kpoint_g_vector_indices
Per physical k-point, indices into charge_density_miller_indices.
Definition init.hpp:123
std::vector< SymmetryOperation > symmetry_operations
Definition init.hpp:92
Matrix3x3 reciprocal_lattice_vectors
Definition init.hpp:79
int number_of_kpoints() const
Definition init.hpp:184
std::vector< std::vector< Complex > > charge_density_g
Definition init.hpp:148
std::vector< std::vector< std::vector< Real > > > nonlocal_coefficients
Definition init.hpp:181
std::vector< std::vector< Real > > eigenvalues_rydberg
Indexed [kpoint_state_index][band_index]; Rydberg.
Definition init.hpp:129
std::vector< int > projectors_per_species
Projector channels – one per (β, m) – of each species.
Definition init.hpp:175
std::vector< Complex > exchange_correlation_potential_g
Definition init.hpp:154
Matrix3x3 lattice_vectors
Definition init.hpp:78
std::vector< std::vector< Complex > > self_consistent_potential_g
Definition init.hpp:162
std::vector< int > plane_waves_per_kpoint
Definition init.hpp:121
std::vector< int > atomic_numbers
Definition init.hpp:84
int number_of_kpoint_states() const
(k-point, spin) state count – the row count of eigenvalues/occupations.
Definition init.hpp:197
std::shared_ptr< const MeanFieldBandSource > band_source
Definition init.hpp:132
std::vector< IntegerVector3D > charge_density_miller_indices
Definition init.hpp:104
std::vector< int > atom_species_indices
0-based species index of each atom, parallel to atomic_numbers.
Definition init.hpp:173
int number_of_g_vectors() const
Definition init.hpp:192
std::shared_ptr< const MeanFieldProjectorSource > projector_source
Definition init.hpp:182
std::vector< Vector3D > atom_positions_cartesian
Cartesian positions in alat units, parallel to atomic_numbers.
Definition init.hpp:83
std::vector< Real > kpoint_weights
Engine-convention weights; formats renormalize as they require.
Definition init.hpp:120