ampsci
c++ program for high-precision atomic structure calculations of single-valence systems
DiracSpinor.hpp
1 #pragma once
2 #include <memory>
3 #include <string>
4 #include <utility>
5 #include <vector>
6 class Grid;
7 
41 class DiracSpinor {
42 
43 public:
46  DiracSpinor(int in_n, int in_kappa, std::shared_ptr<const Grid> in_rgrid);
47  using Index = uint16_t;
48 
49 private:
50  // Radial Grid; links F[i] to F(r)
51  std::shared_ptr<const Grid> m_rgrid;
52  // Principal quantum number
53  int m_n;
54  // Dirac quantum number, kappa
55  int m_kappa;
56  // Single-particle energy, not including rest energy
57  double m_en = 0.0;
58  // Upper (large) radial component
59  std::vector<double> m_f;
60  // Lower (small) radial component
61  std::vector<double> m_g;
62  // `practical zero': p0 is first non-zero point for f(r) [usually p0=0]
63  std::size_t m_p0 = 0;
64  // `practical infinity': pinf is last non-zero point for f(r)
65  std::size_t m_pinf;
66  // Number of iterations until energy convergence (for latest routine only)
67  int m_its = -1;
68  // Fractional energy convergence: eps = |(en'-en)/en|
69  double m_eps = -1.0;
70  // Occupation fraction. =1 for closed shells. =1/(2j+1) for valence
71  double m_occ_frac = 0.0;
72 
73  // 2j, l, pi, kappa_index (for convenience): these are defined by n and kappa
74  int m_twoj;
75  int m_l;
76  int m_parity;
77  int m_kappa_index;
78  Index m_nkappa_index;
79 
80 public:
82  int n() const { return m_n; }
84  int kappa() const { return m_kappa; }
86  int l() const { return m_l; }
88  double jjp1() const { return 0.25 * double(m_twoj * (m_twoj + 2)); }
89  int twoj() const { return m_twoj; }
91  int twojp1() const { return m_twoj + 1; }
93  int parity() const { return m_parity; }
95  int k_index() const { return m_kappa_index; }
97  Index nk_index() const { return m_nkappa_index; }
99  std::string symbol(bool gnuplot = false) const;
101  std::string shortSymbol() const;
102 
104  void set_new_kappa(int new_kappa);
105 
107  const Grid &grid() const { return *m_rgrid; };
110  std::shared_ptr<const Grid> grid_sptr() const { return m_rgrid; };
111 
113  double en() const { return m_en; }
114  double &en() { return m_en; }
115 
117  const std::vector<double> &f() const { return m_f; }
118  std::vector<double> &f() { return m_f; }
120  double f(std::size_t i) const { return m_f.at(i); }
121  double &f(std::size_t i) { return m_f.at(i); }
122 
124  const std::vector<double> &g() const { return m_g; }
125  std::vector<double> &g() { return m_g; }
127  double g(std::size_t i) const { return m_g.at(i); }
128  double &g(std::size_t i) { return m_g.at(i); }
129 
131  // XXX Kill this?
132  auto min_pt() const { return m_p0; }
133  auto &min_pt() { return m_p0; }
134 
136  auto max_pt() const { return m_pinf; }
137  auto &max_pt() { return m_pinf; }
138 
140  double r0() const;
142  double rinf() const;
143 
145  auto its() const { return m_its; }
146  auto &its() { return m_its; }
147 
149  auto occ_frac() const { return m_occ_frac; }
150  auto &occ_frac() { return m_occ_frac; }
151 
153  auto eps() const { return m_eps; }
154  auto &eps() { return m_eps; }
155 
157  const DiracSpinor &scale(const double factor);
159  const DiracSpinor &scale(const std::vector<double> &v);
161  void normalise(double norm_to = 1.0);
163  void zero_boundaries();
164 
166  double norm() const;
168  double norm2() const;
169 
171  std::pair<double, double> r0pinfratio() const;
172 
174  std::vector<double> rho() const;
175 
177  int num_electrons() const;
178 
179 public:
180  // Operator overloads
181 
183  friend double operator*(const DiracSpinor &Fa, const DiracSpinor &Fb);
184 
186  DiracSpinor &operator+=(const DiracSpinor &rhs);
187  DiracSpinor &operator-=(const DiracSpinor &rhs);
188  friend DiracSpinor operator+(DiracSpinor lhs, const DiracSpinor &rhs);
189  friend DiracSpinor operator-(DiracSpinor lhs, const DiracSpinor &rhs);
190 
192  DiracSpinor &operator*=(const double x);
193  friend DiracSpinor operator*(DiracSpinor Fa, const double x);
194  friend DiracSpinor operator*(const double x, DiracSpinor Fa);
195 
197  DiracSpinor &operator*=(const std::vector<double> &v);
198  friend DiracSpinor operator*(const std::vector<double> &v, DiracSpinor Fa);
199 
201  friend bool operator==(const DiracSpinor &lhs, const DiracSpinor &rhs);
202  friend bool operator!=(const DiracSpinor &lhs, const DiracSpinor &rhs);
203  friend bool operator<(const DiracSpinor &lhs, const DiracSpinor &rhs);
204  friend bool operator>(const DiracSpinor &lhs, const DiracSpinor &rhs);
205  friend bool operator<=(const DiracSpinor &lhs, const DiracSpinor &rhs);
206  friend bool operator>=(const DiracSpinor &lhs, const DiracSpinor &rhs);
207 
209  static bool comp_l(const DiracSpinor &lhs, const DiracSpinor &rhs) {
210  return lhs.m_l < rhs.m_l;
211  }
212  static bool comp_j(const DiracSpinor &lhs, const DiracSpinor &rhs) {
213  return lhs.m_twoj < rhs.m_twoj;
214  }
215  static bool comp_ki(const DiracSpinor &lhs, const DiracSpinor &rhs) {
216  return lhs.m_kappa_index < rhs.m_kappa_index;
217  }
218  static bool comp_n(const DiracSpinor &lhs, const DiracSpinor &rhs) {
219  return lhs.m_n < rhs.m_n;
220  }
221  static bool comp_en(const DiracSpinor &lhs, const DiracSpinor &rhs) {
222  return lhs.en() < rhs.en();
223  }
224 
226  friend std::ostream &operator<<(std::ostream &ostr, const DiracSpinor &Fa) {
227  return ostr << Fa.shortSymbol();
228  }
229 
230  // Static (helper) functions:
231 
233  static std::pair<double, std::string>
234  check_ortho(const std::vector<DiracSpinor> &a,
235  const std::vector<DiracSpinor> &b);
236 
239  static void orthonormaliseOrbitals(std::vector<DiracSpinor> &orbs,
240  int num_its = 1);
241 
243  [[nodiscard]] static DiracSpinor
244  orthogonaliseWrt(const DiracSpinor &Fin,
245  const std::vector<DiracSpinor> &orbs);
246 
248  [[nodiscard]] static DiracSpinor
249  orthonormaliseWrt(const DiracSpinor &Fin,
250  const std::vector<DiracSpinor> &orbs);
251 
253  void orthog(const DiracSpinor &rhs);
254 
256  static std::string shortSymbol(int n, int kappa);
257 
259  static std::string state_config(const std::vector<DiracSpinor> &orbs);
260 
262  static DiracSpinor exactHlike(int n, int k, std::shared_ptr<const Grid> rgrid,
263  double zeff, double alpha = 0.0);
264 
266  static const DiracSpinor *find(int n, int k,
267  const std::vector<DiracSpinor> &orbs);
268 
270  static int max_tj(const std::vector<DiracSpinor> &orbs);
272  static int max_l(const std::vector<DiracSpinor> &orbs);
274  static int max_n(const std::vector<DiracSpinor> &orbs);
276  static int max_kindex(const std::vector<DiracSpinor> &orbs);
277 
278  static std::pair<std::vector<DiracSpinor>, std::vector<DiracSpinor>>
279  split_by_energy(const std::vector<DiracSpinor> &orbitals, double energy,
280  int n_min_core = 1);
281 
282  static std::pair<std::vector<DiracSpinor>, std::vector<DiracSpinor>>
283  split_by_core(const std::vector<DiracSpinor> &orbitals,
284  const std::vector<DiracSpinor> &core, int n_min_core = 1);
285 };
Stores radial Dirac spinor: F_nk = (f, g)
Definition: DiracSpinor.hpp:41
std::pair< double, double > r0pinfratio() const
Returns [f[p0]/f_max , f[pinf]/f_max] - for tests.
Definition: DiracSpinor.cpp:106
void normalise(double norm_to=1.0)
By default normalises to 1, but can normalise to other number.
Definition: DiracSpinor.cpp:91
DiracSpinor(int in_n, int in_kappa, std::shared_ptr< const Grid > in_rgrid)
Constructor: Requires n (PQN), kappa (Dirac QN), and grid (shared pointer, as it's a shared resource)
Definition: DiracSpinor.cpp:17
const Grid & grid() const
Resturns a const reference to the radial grid.
Definition: DiracSpinor.hpp:107
static DiracSpinor orthonormaliseWrt(const DiracSpinor &Fin, const std::vector< DiracSpinor > &orbs)
As orthogonaliseWrt(), but normalises Fin afterwards.
Definition: DiracSpinor.cpp:410
static int max_tj(const std::vector< DiracSpinor > &orbs)
Returns maximum (2j) found in {orbs}.
Definition: DiracSpinor.cpp:266
int parity() const
(-1)^l, returns +/- 1
Definition: DiracSpinor.hpp:93
double norm() const
Returns the norm, defined: Norm = Sqrt[<a|a>].
Definition: DiracSpinor.cpp:65
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:304
auto max_pt() const
Effective size(); index after last non-zero point (index for f[i])
Definition: DiracSpinor.hpp:136
friend std::ostream & operator<<(std::ostream &ostr, const DiracSpinor &Fa)
Writes short symbol to ostream.
Definition: DiracSpinor.hpp:226
auto eps() const
Fractional energy convergence: eps = |(en'-en)/en|.
Definition: DiracSpinor.hpp:153
int twojp1() const
2j+1
Definition: DiracSpinor.hpp:91
int kappa() const
Dirac quantum number, kappa.
Definition: DiracSpinor.hpp:84
double norm2() const
Returns the norm^2, defined: Norm2 = <a|a>
Definition: DiracSpinor.cpp:66
const std::vector< double > & f() const
Upper (large) radial component function, f.
Definition: DiracSpinor.hpp:117
auto occ_frac() const
Occupation fraction. =1 for closed shells. =1/(2j+1) for valence.
Definition: DiracSpinor.hpp:149
std::shared_ptr< const Grid > grid_sptr() const
Resturns copy of shared_ptr to grid [shared resource] - used when we want to construct a new DiracSpi...
Definition: DiracSpinor.hpp:110
friend bool operator==(const DiracSpinor &lhs, const DiracSpinor &rhs)
Comparitor overloads (compares n, then kappa):
Definition: DiracSpinor.cpp:206
int n() const
Principal quantum number, n.
Definition: DiracSpinor.hpp:82
static DiracSpinor orthogonaliseWrt(const DiracSpinor &Fin, const std::vector< DiracSpinor > &orbs)
Forces Fin to be orthogonal to orbs. If Fn (i.e., {n,k}) in in orbs, replaces Fin with that from orbs...
Definition: DiracSpinor.cpp:393
static int max_l(const std::vector< DiracSpinor > &orbs)
Returns maximum l found in {orbs}.
Definition: DiracSpinor.cpp:272
std::string symbol(bool gnuplot=false) const
Single-electron term symbol (e.g., 6s_1/2). Gnuplot=true => 6s_{1/2}.
Definition: DiracSpinor.cpp:32
DiracSpinor & operator*=(const double x)
Scalar multiplication.
Definition: DiracSpinor.cpp:187
static int max_n(const std::vector< DiracSpinor > &orbs)
Returns maximum n found in {orbs}.
Definition: DiracSpinor.cpp:277
double en() const
Single-particle energy, not including rest energy.
Definition: DiracSpinor.hpp:113
Index nk_index() const
(n,kappa) index (see AtomData)
Definition: DiracSpinor.hpp:97
void zero_boundaries()
Forces f(r) and g(r) to be zero outside of [p0,pinf)
Definition: DiracSpinor.cpp:94
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:289
double f(std::size_t i) const
Upper (large) radial component, f(r_i)
Definition: DiracSpinor.hpp:120
double r0() const
r0 = r[min_pt] (in atomic units) XXX Kill this?
Definition: DiracSpinor.cpp:135
double g(std::size_t i) const
Lower (small) radial component, g(r_i)
Definition: DiracSpinor.hpp:127
void orthog(const DiracSpinor &rhs)
A more correct way to force orthogonality than normal.
Definition: DiracSpinor.cpp:325
double jjp1() const
j(j+1)
Definition: DiracSpinor.hpp:88
std::string shortSymbol() const
e.g., 6p_1/2 => 6p-, 6p_3/2 => 6p+
Definition: DiracSpinor.cpp:43
static DiracSpinor exactHlike(int n, int k, std::shared_ptr< const Grid > rgrid, double zeff, double alpha=0.0)
Constructs H-like (pointlike) DiracSpinor - mainly for testing.
Definition: DiracSpinor.cpp:418
static bool comp_l(const DiracSpinor &lhs, const DiracSpinor &rhs)
Custom comparitors (for sorting): l, j, kappa_index, energy.
Definition: DiracSpinor.hpp:209
const std::vector< double > & g() const
Lower (small) radial component function, g.
Definition: DiracSpinor.hpp:124
auto min_pt() const
First non-zero point (index for f[i])
Definition: DiracSpinor.hpp:132
static void orthonormaliseOrbitals(std::vector< DiracSpinor > &orbs, int num_its=1)
(approximately) OrthoNormalises a set of any orbitals.
Definition: DiracSpinor.cpp:338
int k_index() const
kappa index (see AtomData)
Definition: DiracSpinor.hpp:95
int num_electrons() const
Number of occupied electrons: (2j+1)*occ_frac.
Definition: DiracSpinor.cpp:130
const DiracSpinor & scale(const double factor)
Scales DiracSpinor (f and g) by constant.
Definition: DiracSpinor.cpp:69
int l() const
Orbital angular momentum Q number.
Definition: DiracSpinor.hpp:86
static int max_kindex(const std::vector< DiracSpinor > &orbs)
Returns maximum kappa_index found in {orbs}.
Definition: DiracSpinor.cpp:282
DiracSpinor & operator+=(const DiracSpinor &rhs)
Addition of two DiracSpinors - must have same kappa.
Definition: DiracSpinor.cpp:150
friend double operator*(const DiracSpinor &Fa, const DiracSpinor &Fb)
Returns radial integral (Fa,Fb) = Int(fa*fb + ga*gb)
Definition: DiracSpinor.cpp:140
void set_new_kappa(int new_kappa)
Changes 'kappa' angular quantum number. Use with caution!
Definition: DiracSpinor.cpp:55
double rinf() const
rinf = r[max_pt]
Definition: DiracSpinor.cpp:136
std::vector< double > rho() const
rho(r) = sum_m |Psi^2|(r) = (2j+1) * x_occ * |F^2|(r)
Definition: DiracSpinor.cpp:119
auto its() const
Number of iterations until energy convergence (for latest routine only)
Definition: DiracSpinor.hpp:145
static std::string state_config(const std::vector< DiracSpinor > &orbs)
Returns formatted states string (e.g., '7sp5d') given list of orbs.
Definition: DiracSpinor.cpp:233
Holds grid, including type + Jacobian (dr/du)
Definition: Grid.hpp:31