High-precision calculations for one- and two-valence atomic systems
DiracSpinor.hpp
1#pragma once
2#include "Physics/PhysConst_constants.hpp" // for default alpha
3#include <cstdint>
4#include <memory>
5#include <string>
6#include <utility>
7#include <vector>
8class Grid;
9
10/*!
11 @brief Stores radial Dirac spinor: F_nk = (f, g)
12
13 @details
14 \f[
15 \psi_{n\kappa m} = \frac{1}{r}
16 \begin{pmatrix}
17 f_{n\kappa}(r)\,\Omega_{\kappa m}\\
18 g_{n\kappa}(r)\,\Omega_{-\kappa m}
19 \end{pmatrix},
20 \quad
21 F_{n\kappa} =
22 \begin{pmatrix}
23 f_{n\kappa}(r)\\
24 g_{n\kappa}(r)
25 \end{pmatrix}
26 \f]
27
28 \par Construction.
29 Takes in n and k=kappa values + grid
30 - A shared pointer to the Grid is stored (to avoid many copies of Grid)
31
32 \par Operator Overloads
33 - Intuitive operator overloads are provided (Fa, Fb are DiracSpinors):
34 - v * Fa, where v is a double or vector works the obvious way
35 - Fa * Fb = <Fa|Fb>
36 - Fa == Fb returns true if {na,ka}=={nb,kb}
37 - Fa > Fb : first compares n, and then kappa (via kappa_index)
38 - Fa +/- Fb : Adds/subtracts the two spinors (and updates p0/pinf)
39 - You can make copies: auto Fnew = Fa
40 - And you can re-assign: Fb = Fa (copies all, including n and kappa)
41 - n has no setter; kappa only via set_new_kappa(). Avoids angular errors.
42 - non-const accessors (e.g., en(), f(), max_pt()) return mutable
43 references to variables
44
45 \par Continuum orbitals
46
47 @note
48 Continuum (and other unlabelled) orbitals have n = 0. Since they are
49 identified only by kappa, all n = 0 orbitals with the same kappa compare
50 equal (operator==), and their nk_index() coincides with that of a bound
51 state (see nk_index). They must not be mixed with each other, or with
52 bound states, in anything that identifies orbitals by {n, kappa}.
53 This might need to be updated later.
54*/
56
57public:
58 /*!
59 @brief Constructor: Requires n (PQN), kappa (Dirac QN), and grid.
60
61 @details
62 Grid is a shared pointer, as it's a shared resource. f and g are
63 initialised to zero over the full grid (max_pt() = grid size).
64
65 @param in_n Principal quantum number
66 @param in_kappa Dirac quantum number, kappa
67 @param in_rgrid Radial grid (shared resource)
68 @param negative_energy Marks a negative-energy (Dirac sea) solution
69 */
70 DiracSpinor(int in_n, int in_kappa, std::shared_ptr<const Grid> in_rgrid,
71 bool negative_energy = false);
72 //! Integer type for the compressed (n,kappa) index
73 using Index = uint16_t;
74
75private:
76 // Radial Grid; links F[i] to F(r)
77 std::shared_ptr<const Grid> m_rgrid;
78 // Principal quantum number
79 int m_n;
80 // Dirac quantum number, kappa
81 int m_kappa;
82 // Single-particle energy, not including rest energy
83 double m_en = 0.0;
84 // Upper (large) radial component
85 std::vector<double> m_f;
86 // Lower (small) radial component
87 std::vector<double> m_g;
88 // `practical zero': p0 is first non-zero point for f(r) [usually p0=0]
89 std::size_t m_p0 = 0;
90 // `practical infinity': pinf is last non-zero point for f(r)
91 std::size_t m_pinf;
92 // Number of iterations until energy convergence (for latest routine only)
93 int m_its = -1;
94 // Fractional energy convergence: eps = |(en'-en)/en|
95 double m_eps = -1.0;
96 // Occupation fraction. =1 for closed shells. =1/(2j+1) for valence
97 double m_occ_frac = 0.0;
98
99 // 2j, l, pi, kappa_index (for convenience): these are defined by n and kappa
100 int m_twoj;
101 int m_l;
102 int m_parity;
103 std::size_t m_kappa_index;
104 Index m_nkappa_index;
105
106 // flag for regular electron, or "exotic"
107 bool m_exotic{false};
108 // flag for negative-energy (Dirac sea) solution
109 bool m_negative_energy{false};
110
111public:
112 //! Principal quantum number, n
113 int n() const { return m_n; }
114 //! Dirac quantum number, kappa
115 int kappa() const { return m_kappa; }
116 //! Orbital angular momentum Q number
117 int l() const { return m_l; }
118 //! j(j+1)
119 double jjp1() const { return 0.25 * double(m_twoj * (m_twoj + 2)); }
120 //! 2j (twice the total angular momentum)
121 int twoj() const { return m_twoj; }
122 //! 2j+1
123 int twojp1() const { return m_twoj + 1; }
124 //! (-1)^l, returns +/- 1
125 int parity() const { return m_parity; }
126 //! kappa index (see Angular::kappa_to_kindex)
127 std::size_t k_index() const { return m_kappa_index; }
128 /*!
129 @brief (n,kappa) index
130
131 @details
132 See @ref Angular::nk_to_index.
133
134 @warning Unique only for 1 <= n <= 256: larger n overflows Index (not
135 checked here; see @ref SplineBasis::form_basis and @ref Angular::nk_to_index).
136
137 @note
138 For n = 0 (continuum orbitals),
139 it coincides with a bound-state index (that of n = 2: e.g.,
140 continuum s and 2s, p_1/2 and 2p_1/2, d_3/2 and 3s), so continuum and
141 bound states must not share a table keyed by this index.
142 */
143 Index nk_index() const { return m_nkappa_index; }
144 //! Single-electron term symbol (e.g., 6s_1/2). Gnuplot=true => 6s_{1/2}
145 std::string symbol(bool gnuplot = false) const;
146 //! e.g., 6p_1/2 => 6p-, 6p_3/2 => 6p+
147 std::string shortSymbol() const;
148
149 //! Checks if spinor is for "exotic" lepton, or regular electron
150 bool &exotic() { return m_exotic; }
151 //! Checks if spinor is for "exotic" lepton, or regular electron
152 bool exotic() const { return m_exotic; }
153
154 /*!
155 @brief Returns true if this is a negative-energy (Dirac sea) state.
156
157 @details
158 Set at construction (by the basis builder); independent of alpha and mass.
159 */
160 bool negativeEnergyStateQ() const { return m_negative_energy; }
161
162 //! Changes 'kappa' angular quantum number. Use with caution!
163 void set_new_kappa(int new_kappa);
164
165 //! Returns a const reference to the radial grid
166 const Grid &grid() const { return *m_rgrid; };
167 /*!
168 @brief Returns copy of shared_ptr to grid [shared resource].
169
170 @details
171 Used when we want to construct a new DiracSpinor that shares this grid.
172 */
173 std::shared_ptr<const Grid> grid_sptr() const { return m_rgrid; };
174
175 //! Single-particle energy, not including rest energy
176 double en() const { return m_en; }
177 double &en() { return m_en; }
178
179 //! Upper (large) radial component function, f
180 const std::vector<double> &f() const { return m_f; }
181 std::vector<double> &f() { return m_f; }
182 //! Upper (large) radial component, f(r_i)
183 double f(std::size_t i) const { return m_f.at(i); }
184 double &f(std::size_t i) { return m_f.at(i); }
185
186 //! Lower (small) radial component function, g
187 const std::vector<double> &g() const { return m_g; }
188 std::vector<double> &g() { return m_g; }
189 //! Lower (small) radial component, g(r_i)
190 double g(std::size_t i) const { return m_g.at(i); }
191 double &g(std::size_t i) { return m_g.at(i); }
192
193 /*!
194 @brief First non-zero point (index for f[i])
195
196 @deprecated Candidate for removal
197 */
198 auto min_pt() const { return m_p0; }
199 auto &min_pt() { return m_p0; }
200
201 //! Effective size(); index _after_ last non-zero point (index for f[i])
202 auto max_pt() const { return m_pinf; }
203 auto &max_pt() { return m_pinf; }
204
205 /*!
206 @brief r0 = r[min_pt] (in atomic units)
207
208 @deprecated Candidate for removal
209 */
210 double r0() const;
211 //! rinf = r[max_pt - 1], the last point of the spinor (au); 0 if max_pt = 0
212 double rinf() const;
213
214 //! Number of iterations until energy convergence (for latest routine only)
215 auto its() const { return m_its; }
216 auto &its() { return m_its; }
217
218 //! Occupation fraction. =1 for closed shells. =1/(2j+1) for valence
219 auto occ_frac() const { return m_occ_frac; }
220 auto &occ_frac() { return m_occ_frac; }
221
222 //! Fractional energy convergence: eps = |(en'-en)/en|
223 auto eps() const { return m_eps; }
224 auto &eps() { return m_eps; }
225
226 //! Scales DiracSpinor (f and g) by constant
227 const DiracSpinor &scale(const double factor);
228 /*!
229 @brief Scales DiracSpinor (f and g) by function of r
230
231 @details
232 Pointwise, over [min_pt, max_pt). Points beyond the end of @p v (up to
233 max_pt) are set to zero.
234 */
235 const DiracSpinor &scale(const std::vector<double> &v);
236 //! By default normalises to 1, but can normalise to other number.
237 void normalise(double norm_to = 1.0);
238 //! Forces f(r) and g(r) to be zero outside of [p0,pinf)
239 void zero_boundaries();
240
241 //! Returns the norm, defined: Norm = Sqrt[<a|a>]
242 double norm() const;
243 //! Returns the norm^2, defined: Norm2 = <a|a>
244 double norm2() const;
245
246 /*!
247 @brief Number of nodes (sign changes) in f(r).
248
249 @details
250 Should be n-l-1 for bound states.
251
252 Only counts out to the last point where |f| >= rel_cut*max|f|,
253 so that small-amplitude sign changes in the tail (e.g., the
254 exchange-dominated tail of Hartree-Fock orbitals), which are not physical
255 nodes, are not counted. Likewise, sign changes before |f| first reaches
256 1e-10*max|f| (near the nucleus, where high-l orbitals are negligible) are
257 not counted.
258
259 @param rel_cut Relative amplitude cut-off for the tail (see above)
260 @return Number of nodes; -1 if f is zero or not finite (failed solution).
261 */
262 int num_nodes(double rel_cut = 1.0e-3) const;
263
264 //! Returns [f[p0]/f_max , f[pinf-1]/f_max] - for tests; {0,0} if f = 0
265 std::pair<double, double> r0pinfratio() const;
266
267 /*!
268 @brief Radial density: rho(r) = (2j+1) * x_occ * |F^2|(r)
269
270 @details
271 \f$ \rho(r) = 4\pi r^2 \, x_{\rm occ} \sum_m |\psi_{n\kappa m}|^2
272 = (2j+1) \, x_{\rm occ} \, (f^2 + g^2) \f$, with x_occ = occ_frac().
273 Integrates (over r) to the number of electrons, for a normalised orbital.
274 */
275 std::vector<double> rho() const;
276
277 //! Number of occupied electrons: (2j+1)*occ_frac, rounded to an integer
278 int num_electrons() const;
279
280public:
281 // Operator overloads
282
283 //! Returns radial integral (Fa,Fb) = Int(fa*fb + ga*gb)
284 friend double operator*(const DiracSpinor &Fa, const DiracSpinor &Fb);
285
286 /*!
287 @brief Adds rhs to this, in place (should generally have same kappa, but forced)
288
289 @details
290 Kappa is not checked: the result keeps n and kappa of `this`. Range
291 [min_pt, max_pt) is extended to include that of @p rhs.
292 */
294 //! Subtracts rhs from this, in place; should generally have same kappa (see +=)
296 //! Adds x*rhs to this, in place (no temporary); should generally have same kappa
297 DiracSpinor &add_scaled(double x, const DiracSpinor &rhs);
298 //! Returns lhs + rhs; should generally have same kappa (see +=)
299 friend DiracSpinor operator+(DiracSpinor lhs, const DiracSpinor &rhs);
300 //! Returns lhs - rhs; should generally have same kappa (see +=)
301 friend DiracSpinor operator-(DiracSpinor lhs, const DiracSpinor &rhs);
302
303 //! Scales this by scalar x, in place
304 DiracSpinor &operator*=(const double x);
305 //! Returns Fa scaled by scalar x
306 friend DiracSpinor operator*(DiracSpinor Fa, const double x);
307 //! Returns Fa scaled by scalar x
308 friend DiracSpinor operator*(const double x, DiracSpinor Fa);
309
310 //! Multiplies this by function v(r), pointwise, in place
311 DiracSpinor &operator*=(const std::vector<double> &v);
312 //! Returns Fa multiplied by function v(r), pointwise
313 friend DiracSpinor operator*(const std::vector<double> &v, DiracSpinor Fa);
314
315 /*!
316 @brief Equality: true if {n,kappa} match
317
318 @note Compares labels only: any two continuum orbitals (n = 0) with the
319 same kappa compare equal, whatever their energy.
320 */
321 friend bool operator==(const DiracSpinor &lhs, const DiracSpinor &rhs);
322 //! Inequality: true if {n,kappa} differ
323 friend bool operator!=(const DiracSpinor &lhs, const DiracSpinor &rhs);
324 //! Ordering: compares n, then kappa (via kappa_index)
325 friend bool operator<(const DiracSpinor &lhs, const DiracSpinor &rhs);
326 //! Ordering: compares n, then kappa (via kappa_index)
327 friend bool operator>(const DiracSpinor &lhs, const DiracSpinor &rhs);
328 //! Ordering: compares n, then kappa (via kappa_index)
329 friend bool operator<=(const DiracSpinor &lhs, const DiracSpinor &rhs);
330 //! Ordering: compares n, then kappa (via kappa_index)
331 friend bool operator>=(const DiracSpinor &lhs, const DiracSpinor &rhs);
332
333 //! Comparator (for sorting): by l
334 static bool comp_l(const DiracSpinor &lhs, const DiracSpinor &rhs) {
335 return lhs.m_l < rhs.m_l;
336 }
337 //! Comparator (for sorting): by 2j
338 static bool comp_j(const DiracSpinor &lhs, const DiracSpinor &rhs) {
339 return lhs.m_twoj < rhs.m_twoj;
340 }
341 //! Comparator (for sorting): by kappa_index
342 static bool comp_ki(const DiracSpinor &lhs, const DiracSpinor &rhs) {
343 return lhs.m_kappa_index < rhs.m_kappa_index;
344 }
345 //! Comparator (for sorting): by n
346 static bool comp_n(const DiracSpinor &lhs, const DiracSpinor &rhs) {
347 return lhs.m_n < rhs.m_n;
348 }
349 //! Comparator (for sorting): by energy
350 static bool comp_en(const DiracSpinor &lhs, const DiracSpinor &rhs) {
351 return lhs.en() < rhs.en();
352 }
353
354 //! Writes short symbol to ostream
355 friend std::ostream &operator<<(std::ostream &ostr, const DiracSpinor &Fa) {
356 return ostr << Fa.shortSymbol();
357 }
358
359 // Static (helper) functions:
360
361 //! Returns worst |<a|b>| (or ||<a|b>|-1| for a=b) {val, state_names}
362 static std::pair<double, std::string>
363 check_ortho(const std::vector<DiracSpinor> &a,
364 const std::vector<DiracSpinor> &b);
365
366 /*!
367 @brief (approximately) OrthoNormalises a set of any orbitals
368
369 @details
370 Symmetric: each orbital is orthogonalised against all others of the same
371 kappa,
372 \f$ \ket{a} \to \ket{a} - \frac{1}{2}\sum_{b \neq a}
373 \ket{b}\langle b|a\rangle \f$ (overlaps from the start of the iteration),
374 then normalised. Half of each overlap is removed from each of the pair,
375 so the overlaps are removed to first order only. Repeated @p num_its
376 times.
377
378 @note Only updates orbs, not energies
379 */
380 static void orthonormaliseOrbitals(std::vector<DiracSpinor> &orbs,
381 int num_its = 1);
382
383 /*!
384 @brief Forces Fin to be orthogonal to orbs.
385
386 @details
387 If Fn (i.e., {n,k}) is in orbs, replaces Fin with that from orbs.
388 Otherwise, subtracts the projection of @p Fin onto each orbital in
389 @p orbs with the same kappa (exact only if @p orbs are orthonormal).
390
391 @note Energy is not updated (unless Fin is replaced from @p orbs).
392 */
393 [[nodiscard]] static DiracSpinor
394 orthogonaliseWrt(const DiracSpinor &Fin,
395 const std::vector<DiracSpinor> &orbs);
396
397 //! As orthogonaliseWrt(), but normalises Fin afterwards
398 [[nodiscard]] static DiracSpinor
400 const std::vector<DiracSpinor> &orbs);
401
402 /*!
403 @brief A more correct way to force orthogonality than normal
404
405 @details
406 |this> -> |this> - <this|rhs>|rhs>, only over the range where both
407 spinors are defined: min_pt() and max_pt() of this are unchanged. Does
408 nothing if kappa differs.
409
410 @note Assumes @p rhs is normalised.
411 */
412 void orthog(const DiracSpinor &rhs);
413
414 //! e.g., 6p_1/2 => 6p-, 6p_3/2 => 6p+
415 static std::string shortSymbol(int n, int kappa);
416
417 //! Which energy branch of a set of orbitals state_config() describes
418 enum class Branch { electron, positron, both };
419
420 /*!
421 @brief Returns formatted states string (e.g., '7sp5d') given list of orbs
422
423 @details
424 For the electron states, the number is the maximum n for each l. For the
425 negative-energy (positron) states, it is the number kept for each kappa
426 (the larger of the two kappa, for each l).
427 By default (both), the two are joined with '+' when negative-energy states
428 are present (e.g., '30spd20f+9spdf'), so they are always visible.
429 */
430 static std::string state_config(const std::vector<DiracSpinor> &orbs,
431 Branch branch = Branch::both);
432
433 /*!
434 @brief Formats a list of numbers into the compressed states-string notation
435
436 @details
437 One number per l, starting at l=0, e.g., {30,30,20,20} => '30sp20df'.
438 Zero entries are skipped.
439 */
440 static std::string config_string(const std::vector<int> &n_per_l);
441
442 /*!
443 @brief Constructs an exact H-like (pointlike Coulomb) DiracSpinor
444
445 @details
446 Relativistic Dirac-Coulomb bound orbital for nuclear charge @p zeff (see
447 DiracHydrogen).
448
449 @note alpha <= 0 gives the non-relativistic (Schrodinger) solution instead:
450 f = P_nl, g = 0.
451 */
452 static DiracSpinor exactHlike(int n, int k, std::shared_ptr<const Grid> rgrid,
453 double zeff, double alpha = PhysConst::alpha,
454 double mass = 1.0);
455
456 /*!
457 @brief Constructs an exact (Dirac-Coulomb) continuum DiracSpinor
458
459 @details
460 Energy-normalised relativistic continuum orbital (en > 0; n set to 0).
461 Requires FLINT for the relativistic case (see DiracContinuum::available).
462
463 @note alpha <= 0 gives the non-relativistic solution instead (f = P_el,
464 g = 0), which does not require FLINT.
465 @warning Relativistic case without FLINT: prints a warning and returns
466 NaN (assert fails if NDEBUG is not defined).
467 */
468 static DiracSpinor exactHlike_cntm(double en, int k,
469 std::shared_ptr<const Grid> rgrid,
470 double zeff,
471 double alpha = PhysConst::alpha,
472 double mass = 1.0);
473
474 /*!
475 @brief Constructs a basis of H-like (pointlike) DiracSpinors
476
477 @param max_l maximum l (both kappas calculated)
478 @param num_ns number of principal quantum numbers per l (not max n)
479 @param mass lepton mass in units of m_e (default 1 = electron)
480 @note alpha <= 0 gives the non-relativistic solutions (f = P_nl, g = 0)
481 */
482 static std::vector<DiracSpinor>
483 HlikeBasis(int max_l, int num_ns, std::shared_ptr<const Grid> rgrid,
484 double zeff, double alpha = PhysConst::alpha, double mass = 1.0);
485
486 /*!
487 @brief Constructs a basis of H-like (pointlike) DiracSpinors
488
489 @param basis_string e.g., "6sp5d": max n for each kappa; all n down to
490 n_min = l+1 are included
491 @param mass lepton mass in units of m_e (default 1 = electron)
492 @note alpha <= 0 gives the non-relativistic solutions (f = P_nl, g = 0)
493 */
494 static std::vector<DiracSpinor>
495 HlikeBasis(const std::string &basis_string, std::shared_ptr<const Grid> rgrid,
496 double zeff, double alpha = PhysConst::alpha, double mass = 1.0);
497
498 //! Searches for {n,k} in list of orbitals, returns pointer (may be null)
499 static const DiracSpinor *find(int n, int k,
500 const std::vector<DiracSpinor> &orbs);
501
502 //! Returns maximum (2j) found in {orbs}
503 static int max_tj(const std::vector<DiracSpinor> &orbs);
504 //! Returns maximum l found in {orbs}
505 static int max_l(const std::vector<DiracSpinor> &orbs);
506 //! Returns maximum n found in {orbs}
507 static int max_n(const std::vector<DiracSpinor> &orbs);
508 //! Returns maximum n found in {orbs}, for given kappa
509 static int max_n(const std::vector<DiracSpinor> &orbs, int kappa);
510 //! Returns maximum kappa_index found in {orbs}
511 static std::size_t max_kindex(const std::vector<DiracSpinor> &orbs);
512
513 //! Returns maximum Energy found in {orbs}
514 static double max_En(const std::vector<DiracSpinor> &orbs);
515 //! Returns minimum Energy found in {orbs}
516 static double min_En(const std::vector<DiracSpinor> &orbs);
517
518 /*!
519 @brief Splits orbitals into two groups (i.e., core, excited) by energy
520
521 @details
522 - The first group contains orbitals with energy <= @p Fermi_energy
523 - The second group contains orbitals with energy > @p Fermi_energy
524 - The first group is also limited to have n >= @p n_min_core (i.e.,
525 exclude deep core states)
526 - The second group is limited to have n <= @p n_max_excited
527 - Negative-energy states (if present) all go to the second group
528 (@p n_max_excited is not applied to them). Set
529 @p include_negative_energy = false to drop them entirely instead
530 */
531 static std::pair<std::vector<DiracSpinor>, std::vector<DiracSpinor>>
532 split_by_energy(const std::vector<DiracSpinor> &orbitals, double Fermi_energy,
533 int n_min_core = 1, int n_max_excited = 9999,
534 bool include_negative_energy = true);
535
536 /*!
537 @brief Splits orbitals into two groups (i.e., core, excited)
538
539 @details
540 - The first group contains orbitals with {n,kappa} in the given @p core
541 - The second group contains all of the rest
542 - The first group is also limited to have n >= @p n_min_core (i.e.,
543 exclude deep core states)
544 */
545 static std::pair<std::vector<DiracSpinor>, std::vector<DiracSpinor>>
546 split_by_core(const std::vector<DiracSpinor> &orbitals,
547 const std::vector<DiracSpinor> &core, int n_min_core = 1);
548
549 /*!
550 @brief Takes a subset of a basis (by copy), according to subset_string
551
552 @details
553 - Includes only states matching the @p subset_string (e.g., "6sp5d": max
554 n for each kappa)
555 - Negative-energy states are excluded, unless @p exclude_negative_energy
556 is false: then all those with kappa in @p subset_string are included
557 (the n limit is not applied to them)
558 */
559 static std::vector<DiracSpinor> subset(const std::vector<DiracSpinor> &basis,
560 const std::string &subset_string,
561 bool exclude_negative_energy = true);
562};
Stores radial Dirac spinor: F_nk = (f, g)
Definition DiracSpinor.hpp:55
static std::pair< std::vector< DiracSpinor >, std::vector< DiracSpinor > > split_by_energy(const std::vector< DiracSpinor > &orbitals, double Fermi_energy, int n_min_core=1, int n_max_excited=9999, bool include_negative_energy=true)
Splits orbitals into two groups (i.e., core, excited) by energy.
Definition DiracSpinor.cpp:606
std::pair< double, double > r0pinfratio() const
Returns [f[p0]/f_max , f[pinf-1]/f_max] - for tests; {0,0} if f = 0.
Definition DiracSpinor.cpp:113
void normalise(double norm_to=1.0)
By default normalises to 1, but can normalise to other number.
Definition DiracSpinor.cpp:98
static DiracSpinor orthonormaliseWrt(const DiracSpinor &Fin, const std::vector< DiracSpinor > &orbs)
As orthogonaliseWrt(), but normalises Fin afterwards.
Definition DiracSpinor.cpp:522
static int max_tj(const std::vector< DiracSpinor > &orbs)
Returns maximum (2j) found in {orbs}.
Definition DiracSpinor.cpp:354
int parity() const
(-1)^l, returns +/- 1
Definition DiracSpinor.hpp:125
double norm() const
Returns the norm, defined: Norm = Sqrt[<a|a>].
Definition DiracSpinor.cpp:72
friend bool operator<(const DiracSpinor &lhs, const DiracSpinor &rhs)
Ordering: compares n, then kappa (via kappa_index)
Definition DiracSpinor.cpp:279
friend DiracSpinor operator-(DiracSpinor lhs, const DiracSpinor &rhs)
Returns lhs - rhs; should generally have same kappa (see +=)
Definition DiracSpinor.cpp:233
uint16_t Index
Integer type for the compressed (n,kappa) index.
Definition DiracSpinor.hpp:73
static std::vector< DiracSpinor > subset(const std::vector< DiracSpinor > &basis, const std::string &subset_string, bool exclude_negative_energy=true)
Takes a subset of a basis (by copy), according to subset_string.
Definition DiracSpinor.cpp:652
static std::pair< double, std::string > check_ortho(const std::vector< DiracSpinor > &a, const std::vector< DiracSpinor > &b)
Returns worst |<a|b>| (or ||<a|b>|-1| for a=b) {val, state_names}.
Definition DiracSpinor.cpp:416
DiracSpinor & add_scaled(double x, const DiracSpinor &rhs)
Adds x*rhs to this, in place (no temporary); should generally have same kappa.
Definition DiracSpinor.cpp:237
auto max_pt() const
Effective size(); index after last non-zero point (index for f[i])
Definition DiracSpinor.hpp:202
static bool comp_j(const DiracSpinor &lhs, const DiracSpinor &rhs)
Comparator (for sorting): by 2j.
Definition DiracSpinor.hpp:338
static bool comp_n(const DiracSpinor &lhs, const DiracSpinor &rhs)
Comparator (for sorting): by n.
Definition DiracSpinor.hpp:346
Branch
Which energy branch of a set of orbitals state_config() describes.
Definition DiracSpinor.hpp:418
auto eps() const
Fractional energy convergence: eps = |(en'-en)/en|.
Definition DiracSpinor.hpp:223
static std::string config_string(const std::vector< int > &n_per_l)
Formats a list of numbers into the compressed states-string notation.
Definition DiracSpinor.cpp:336
const std::vector< double > & f() const
Upper (large) radial component function, f.
Definition DiracSpinor.hpp:180
bool negativeEnergyStateQ() const
Returns true if this is a negative-energy (Dirac sea) state.
Definition DiracSpinor.hpp:160
int num_nodes(double rel_cut=1.0e-3) const
Number of nodes (sign changes) in f(r).
Definition DiracSpinor.cpp:128
int twojp1() const
2j+1
Definition DiracSpinor.hpp:123
int kappa() const
Dirac quantum number, kappa.
Definition DiracSpinor.hpp:115
static std::pair< std::vector< DiracSpinor >, std::vector< DiracSpinor > > split_by_core(const std::vector< DiracSpinor > &orbitals, const std::vector< DiracSpinor > &core, int n_min_core=1)
Splits orbitals into two groups (i.e., core, excited)
Definition DiracSpinor.cpp:632
double norm2() const
Returns the norm^2, defined: Norm2 = <a|a>
Definition DiracSpinor.cpp:73
auto occ_frac() const
Occupation fraction. =1 for closed shells. =1/(2j+1) for valence.
Definition DiracSpinor.hpp:219
const Grid & grid() const
Returns a const reference to the radial grid.
Definition DiracSpinor.hpp:166
friend bool operator==(const DiracSpinor &lhs, const DiracSpinor &rhs)
Equality: true if {n,kappa} match.
Definition DiracSpinor.cpp:271
int n() const
Principal quantum number, n.
Definition DiracSpinor.hpp:113
friend bool operator<=(const DiracSpinor &lhs, const DiracSpinor &rhs)
Ordering: compares n, then kappa (via kappa_index)
Definition DiracSpinor.cpp:289
friend bool operator!=(const DiracSpinor &lhs, const DiracSpinor &rhs)
Inequality: true if {n,kappa} differ.
Definition DiracSpinor.cpp:275
static DiracSpinor orthogonaliseWrt(const DiracSpinor &Fin, const std::vector< DiracSpinor > &orbs)
Forces Fin to be orthogonal to orbs.
Definition DiracSpinor.cpp:505
std::shared_ptr< const Grid > grid_sptr() const
Returns copy of shared_ptr to grid [shared resource].
Definition DiracSpinor.hpp:173
static int max_l(const std::vector< DiracSpinor > &orbs)
Returns maximum l found in {orbs}.
Definition DiracSpinor.cpp:360
std::string symbol(bool gnuplot=false) const
Single-electron term symbol (e.g., 6s_1/2). Gnuplot=true => 6s_{1/2}.
Definition DiracSpinor.cpp:36
static DiracSpinor exactHlike_cntm(double en, int k, std::shared_ptr< const Grid > rgrid, double zeff, double alpha=PhysConst::alpha, double mass=1.0)
Constructs an exact (Dirac-Coulomb) continuum DiracSpinor.
Definition DiracSpinor.cpp:543
static double min_En(const std::vector< DiracSpinor > &orbs)
Returns minimum Energy found in {orbs}.
Definition DiracSpinor.cpp:408
DiracSpinor & operator*=(const double x)
Scales this by scalar x, in place.
Definition DiracSpinor.cpp:252
static int max_n(const std::vector< DiracSpinor > &orbs)
Returns maximum n found in {orbs}.
Definition DiracSpinor.cpp:365
static bool comp_ki(const DiracSpinor &lhs, const DiracSpinor &rhs)
Comparator (for sorting): by kappa_index.
Definition DiracSpinor.hpp:342
friend bool operator>=(const DiracSpinor &lhs, const DiracSpinor &rhs)
Ordering: compares n, then kappa (via kappa_index)
Definition DiracSpinor.cpp:293
friend DiracSpinor operator+(DiracSpinor lhs, const DiracSpinor &rhs)
Returns lhs + rhs; should generally have same kappa (see +=)
Definition DiracSpinor.cpp:230
double en() const
Single-particle energy, not including rest energy.
Definition DiracSpinor.hpp:176
static DiracSpinor exactHlike(int n, int k, std::shared_ptr< const Grid > rgrid, double zeff, double alpha=PhysConst::alpha, double mass=1.0)
Constructs an exact H-like (pointlike Coulomb) DiracSpinor.
Definition DiracSpinor.cpp:530
Index nk_index() const
(n,kappa) index
Definition DiracSpinor.hpp:143
void zero_boundaries()
Forces f(r) and g(r) to be zero outside of [p0,pinf)
Definition DiracSpinor.cpp:101
static const DiracSpinor * find(int n, int k, const std::vector< DiracSpinor > &orbs)
Searches for {n,k} in list of orbitals, returns pointer (may be null)
Definition DiracSpinor.cpp:389
static std::string state_config(const std::vector< DiracSpinor > &orbs, Branch branch=Branch::both)
Returns formatted states string (e.g., '7sp5d') given list of orbs.
Definition DiracSpinor.cpp:298
double f(std::size_t i) const
Upper (large) radial component, f(r_i)
Definition DiracSpinor.hpp:183
static std::size_t max_kindex(const std::vector< DiracSpinor > &orbs)
Returns maximum kappa_index found in {orbs}.
Definition DiracSpinor.cpp:382
double r0() const
r0 = r[min_pt] (in atomic units)
Definition DiracSpinor.cpp:183
double g(std::size_t i) const
Lower (small) radial component, g(r_i)
Definition DiracSpinor.hpp:190
friend bool operator>(const DiracSpinor &lhs, const DiracSpinor &rhs)
Ordering: compares n, then kappa (via kappa_index)
Definition DiracSpinor.cpp:285
void orthog(const DiracSpinor &rhs)
A more correct way to force orthogonality than normal.
Definition DiracSpinor.cpp:437
double jjp1() const
j(j+1)
Definition DiracSpinor.hpp:119
std::string shortSymbol() const
e.g., 6p_1/2 => 6p-, 6p_3/2 => 6p+
Definition DiracSpinor.cpp:49
static bool comp_l(const DiracSpinor &lhs, const DiracSpinor &rhs)
Comparator (for sorting): by l.
Definition DiracSpinor.hpp:334
static std::vector< DiracSpinor > HlikeBasis(int max_l, int num_ns, std::shared_ptr< const Grid > rgrid, double zeff, double alpha=PhysConst::alpha, double mass=1.0)
Constructs a basis of H-like (pointlike) DiracSpinors.
Definition DiracSpinor.cpp:570
bool & exotic()
Checks if spinor is for "exotic" lepton, or regular electron.
Definition DiracSpinor.hpp:150
auto min_pt() const
First non-zero point (index for f[i])
Definition DiracSpinor.hpp:198
static void orthonormaliseOrbitals(std::vector< DiracSpinor > &orbs, int num_its=1)
(approximately) OrthoNormalises a set of any orbitals
Definition DiracSpinor.cpp:450
static double max_En(const std::vector< DiracSpinor > &orbs)
Returns maximum Energy found in {orbs}.
Definition DiracSpinor.cpp:402
int num_electrons() const
Number of occupied electrons: (2j+1)*occ_frac, rounded to an integer.
Definition DiracSpinor.cpp:178
friend std::ostream & operator<<(std::ostream &ostr, const DiracSpinor &Fa)
Writes short symbol to ostream.
Definition DiracSpinor.hpp:355
const DiracSpinor & scale(const double factor)
Scales DiracSpinor (f and g) by constant.
Definition DiracSpinor.cpp:76
int twoj() const
2j (twice the total angular momentum)
Definition DiracSpinor.hpp:121
DiracSpinor & operator-=(const DiracSpinor &rhs)
Subtracts rhs from this, in place; should generally have same kappa (see +=)
Definition DiracSpinor.cpp:214
int l() const
Orbital angular momentum Q number.
Definition DiracSpinor.hpp:117
DiracSpinor & operator+=(const DiracSpinor &rhs)
Adds rhs to this, in place (should generally have same kappa, but forced)
Definition DiracSpinor.cpp:200
friend double operator*(const DiracSpinor &Fa, const DiracSpinor &Fb)
Returns radial integral (Fa,Fb) = Int(fa*fb + ga*gb)
Definition DiracSpinor.cpp:190
bool exotic() const
Checks if spinor is for "exotic" lepton, or regular electron.
Definition DiracSpinor.hpp:152
void set_new_kappa(int new_kappa)
Changes 'kappa' angular quantum number. Use with caution!
Definition DiracSpinor.cpp:62
std::size_t k_index() const
kappa index (see Angular::kappa_to_kindex)
Definition DiracSpinor.hpp:127
double rinf() const
rinf = r[max_pt - 1], the last point of the spinor (au); 0 if max_pt = 0
Definition DiracSpinor.cpp:184
std::vector< double > rho() const
Radial density: rho(r) = (2j+1) * x_occ * |F^2|(r)
Definition DiracSpinor.cpp:167
auto its() const
Number of iterations until energy convergence (for latest routine only)
Definition DiracSpinor.hpp:215
static bool comp_en(const DiracSpinor &lhs, const DiracSpinor &rhs)
Comparator (for sorting): by energy.
Definition DiracSpinor.hpp:350
const std::vector< double > & g() const
Lower (small) radial component function, g.
Definition DiracSpinor.hpp:187
Non-uniform radial grid with Jacobian, suitable for atomic structure calculations.
Definition Grid.hpp:85
constexpr double alpha
Fine-structure constant: alpha = 1/137.035 999 177(21) [CODATA 2022].
Definition PhysConst_constants.hpp:24