Loading...
Searching...
No Matches
init.hpp
Go to the documentation of this file.
1#pragma once
2
3/**
4 * PawPseudopotential — projector-augmented-wave pseudopotential subclass.
5 *
6 * Extends UltrasoftPseudopotential rather than Pseudopotential directly: a PAW
7 * dataset carries the same augmentation apparatus an ultrasoft one does (UPF
8 * PAW files declare is_ultrasoft="T" and tabulate PP_Q / PP_QIJL identically),
9 * so the augmentation storage and the machinery built on it are shared rather
10 * than duplicated. What PAW adds on top is the one-center data that makes the
11 * transformation exact: the all-electron and pseudo partial waves, the
12 * all-electron core density and local potential, and the multipole moments of
13 * the compensation charge.
14 *
15 * Reading a PAW dataset is supported; running an SCF with one is not yet.
16 * load_pseudopotentials() rejects PAW at the point pseudopotentials enter a
17 * calculation, so a PAW file can never be silently treated as NC or US by the
18 * downstream factories (which dispatch on pseudopotential_type_enum()).
19 */
20
21#include <string>
22#include <vector>
23
29
30namespace q3 {
31
32/// PAW pseudopotential — extends ultrasoft with one-center (on-site) data.
34 public:
35 /**
36 * Name of the one-center convention this dataset's D_ion and one-center
37 * data are expressed in, resolved through the convention registry
38 * (layer_4_computation/paw/one_center/convention/registry.hpp).
39 *
40 * Not a detail of the file format but a statement about what the numbers
41 * in it *mean*, and conventions are not interchangeable. The default,
42 * "absolute", is QE's convention, which UPF-PAW datasets follow: `PP_DIJ`
43 * already contains the kinetic and core-reference pieces, and the SCF adds
44 * an absolute one-center Hxc energy on top. A format whose D_ion is
45 * instead referenced to the dataset's own atomic configuration (the
46 * linearized frozen-core formulation of Kresse & Joubert, PRB 59, 1758
47 * (1999)) has its reader record the name of the convention that
48 * re-references it, registered alongside that reader.
49 *
50 * Pairing one dataset's numbers with another convention's formulation is
51 * silently wrong by a per-element constant, which is why the reader
52 * records it on the dataset rather than it being inferred at the point of
53 * use.
54 */
55 std::string one_center_convention{"absolute"};
56
57 ~PawPseudopotential() override = default;
58
59 [[nodiscard]] std::unique_ptr<Pseudopotential> clone() const override {
60 return std::make_unique<PawPseudopotential>(*this);
61 }
62
66
67 [[nodiscard]] bool has_augmentation_charges() const override {
68 return true;
69 }
70
71 // ---- One-center basis ----
72
73 /// All-electron partial waves φ_i(r), one per projector channel.
74 std::vector<PartialWave> partial_waves_all_electron;
75 /// Pseudo partial waves φ̃_i(r), one per projector channel.
76 std::vector<PartialWave> partial_waves_pseudo;
77 /// Reference occupation of each projector channel in the generating atom.
78 std::vector<Real> channel_occupations;
79
80 // ---- One-center densities and potential ----
81
82 /// All-electron core density (distinct from the pseudized NLCC core density).
84 /// All-electron local potential (Ry); diverges as -2Z/r toward the origin.
86
87 // ---- Compensation-charge moments ----
88
89 /**
90 * Multipole moments of the augmentation channels, indexed
91 * [angular_momentum][projector_i][projector_j]:
92 *
93 * multipole_moments[L][i][j] = ∫ (φ_i φ_j − φ̃_i φ̃_j) r^L dr
94 *
95 * with r-weighted partial waves. Entries forbidden by the angular-momentum
96 * triangle condition (|l_i − l_j| ≤ L ≤ l_i + l_j with l_i + l_j + L even)
97 * are stored as zero. The L = 0 block equals augmentation_overlap_integrals.
98 */
99 std::vector<std::vector<std::vector<Real>>> multipole_moments;
100
101 // ---- Augmentation metadata ----
102
103 /// Shape function used to pseudize the augmentation charges (e.g. "BESSEL").
105 /// Radius beyond which the augmentation charges vanish (bohr).
107 /// Grid index corresponding to augmentation_cutoff_radius.
109 /// Highest angular momentum carried by the augmentation channels.
111 /// Number of angular-momentum channels, 2·l_max + 1.
113
114 /// One-center core energy, when the dataset provides it.
116 bool has_core_energy{false};
117
118 // ---- Projectors supplied in reciprocal space ----
119
120 /**
121 * Some dataset formats tabulate the projectors in reciprocal space rather
122 * than radially. Q3 also applies projectors in reciprocal space
123 * (BetaFunctionTable tabulates β(q) and the engine uses that), so such a
124 * dataset is best consumed directly instead of being transformed to r and
125 * straight back again.
126 *
127 * The values are β(q) in the convention of Q3's own forward transform,
128 * β(q) = 4π ∫ β(r) j_l(qr) r² dr, so they need no rescaling. The reader
129 * that fills this field records how that agreement was established.
130 *
131 * Empty when the dataset gives projectors radially (UPF), in which case
132 * `projectors` carries r·β(r) and the transform is used as before.
133 *
134 * Tabulated on a uniform grid q_i = i · reciprocal_grid_spacing, one entry
135 * per projector channel.
136 */
137 std::vector<std::vector<Real>> projectors_reciprocal;
139
140 [[nodiscard]] bool has_reciprocal_projectors() const {
141 return !projectors_reciprocal.empty() && reciprocal_grid_spacing > 0.0;
142 }
143
144 /**
145 * The atomic valence density ρ_at(q), when the dataset gives it
146 * reciprocally rather than radially.
147 *
148 * Same situation as the projectors, and the same resolution. Q3 wants this
149 * quantity in q-space too — the starting density is built by superposing
150 * ρ_at(G) — so the table is consumed as given instead of being inverted to
151 * r and transformed straight back.
152 *
153 * The convention matches Q3's radial path, ρ_at(q) = ∫ ρ_at(r) j_0(qr) dr,
154 * whose q = 0 value is the valence charge, so no rescaling.
155 *
156 * Reconstructing it from the partial waves is not an alternative: a
157 * dataset's reference occupancies need not be the neutral atom's, and then
158 * Σ_i f_i |φ̃_i|² does not integrate to the valence charge.
159 *
160 * Empty when the dataset gives the density radially (UPF), in which case
161 * `charge_atomic` carries it and the transform is used as before.
162 *
163 * Tabulated on a uniform grid q_i = i · reciprocal_charge_grid_spacing,
164 * which need not be the projector grid.
165 */
166 std::vector<Real> charge_atomic_reciprocal;
168
169 [[nodiscard]] bool has_reciprocal_atomic_charge() const {
171 }
172
173 /**
174 * The local pseudopotential V_loc(q), when the dataset gives it
175 * reciprocally.
176 *
177 * This is *not* the same object as the radial `potential_local`. A format
178 * may describe the potential inside the augmentation sphere radially and,
179 * separately, tabulate the pseudized local potential the plane waves see;
180 * using the radial one in its place is simply the wrong potential, not a
181 * coarser version of the right one.
182 *
183 * Stored in the dataset's own convention, which the table itself makes
184 * checkable: the Coulomb divergence is already subtracted, so the entry
185 * at q = 0 is finite and equals the α_Z constant. Q3's own V_loc(q) keeps
186 * that divergence, so the consumer subtracts 4πZe²/(Ωq²) back on — see
187 * calculate_local_potential_at_q.
188 *
189 * Units are energy × volume, so V(G) is the tabulated value at |G| divided
190 * by Ω; stored in Ry·bohr³.
191 *
192 * Empty for UPF datasets, which give the potential radially.
193 */
194 std::vector<Real> potential_local_reciprocal;
196
197 [[nodiscard]] bool has_reciprocal_local_potential() const {
199 }
200
201 /**
202 * The pseudized partial core density ñ_c(q), when the dataset gives it
203 * reciprocally.
204 *
205 * The third quantity a format may tabulate in q-space for the plane-wave
206 * grid, and the third that must not be taken from radial data instead: a
207 * radial pseudized core density kept for the one-center terms can be a
208 * different object on a truncated grid, carrying a different charge.
209 *
210 * Getting it wrong is not a constant shift. The grid-side XC is evaluated
211 * at n + ñ_c and is nonlinear in it, so an error here changes the energy's
212 * dependence on volume — which is exactly how it shows up: as a
213 * plausible-looking but wrong equation of state.
214 *
215 * Same convention as the radial path produces, 4π∫ñ_c(r)r²j₀(qr)dr, whose
216 * q = 0 value is the partial core charge.
217 *
218 * Empty for UPF datasets.
219 */
220 std::vector<Real> charge_core_reciprocal;
222
223 [[nodiscard]] bool has_reciprocal_core_charge() const {
225 }
226};
227
228} // namespace q3
PAW pseudopotential — extends ultrasoft with one-center (on-site) data.
Definition init.hpp:33
int maximum_angular_momentum_augmentation
Highest angular momentum carried by the augmentation channels.
Definition init.hpp:110
std::unique_ptr< Pseudopotential > clone() const override
Clone this pseudopotential (deep copy preserving derived type).
Definition init.hpp:59
bool has_augmentation_charges() const override
Definition init.hpp:67
int augmentation_cutoff_radius_index
Grid index corresponding to augmentation_cutoff_radius.
Definition init.hpp:108
std::vector< PartialWave > partial_waves_pseudo
Pseudo partial waves φ̃_i(r), one per projector channel.
Definition init.hpp:76
bool has_reciprocal_projectors() const
Definition init.hpp:140
Real core_energy
One-center core energy, when the dataset provides it.
Definition init.hpp:115
bool has_reciprocal_local_potential() const
Definition init.hpp:197
std::vector< PartialWave > partial_waves_all_electron
All-electron partial waves φ_i(r), one per projector channel.
Definition init.hpp:74
Real augmentation_cutoff_radius
Radius beyond which the augmentation charges vanish (bohr).
Definition init.hpp:106
std::vector< std::vector< Real > > projectors_reciprocal
Definition init.hpp:137
std::vector< Real > potential_local_reciprocal
Definition init.hpp:194
PotentialLocal potential_local_all_electron
All-electron local potential (Ry); diverges as -2Z/r toward the origin.
Definition init.hpp:85
Real reciprocal_charge_grid_spacing
Definition init.hpp:167
int number_of_augmentation_angular_momenta
Number of angular-momentum channels, 2·l_max + 1.
Definition init.hpp:112
std::vector< Real > channel_occupations
Reference occupation of each projector channel in the generating atom.
Definition init.hpp:78
Real reciprocal_core_grid_spacing
Definition init.hpp:221
std::vector< std::vector< std::vector< Real > > > multipole_moments
Definition init.hpp:99
std::vector< Real > charge_atomic_reciprocal
Definition init.hpp:166
std::string augmentation_shape
Shape function used to pseudize the augmentation charges (e.g. "BESSEL").
Definition init.hpp:104
Real reciprocal_potential_grid_spacing
Definition init.hpp:195
std::vector< Real > charge_core_reciprocal
Definition init.hpp:220
bool has_reciprocal_core_charge() const
Definition init.hpp:223
~PawPseudopotential() override=default
bool has_reciprocal_atomic_charge() const
Definition init.hpp:169
PseudopotentialType pseudopotential_type_enum() const override
Definition init.hpp:63
ChargeCore charge_core_all_electron
All-electron core density (distinct from the pseudized NLCC core density).
Definition init.hpp:83
std::string one_center_convention
Definition init.hpp:55
Ultrasoft pseudopotential — extends base with augmentation data.
Definition init.hpp:27
double Real
PseudopotentialType
Pseudopotential type classification.
Definition init.hpp:27
Core charge density ρ_core(r) from a pseudopotential (NLCC).
Local potential V_loc(r) from a pseudopotential (Ry).