ampsci
c++ program for high-precision atomic structure calculations of single-valence systems
Loading...
Searching...
No Matches
hfs.hpp
1#pragma once
2#include "DiracOperator/TensorOperator.hpp"
3#include "IO/InputBlock.hpp"
4#include "Wavefunction/Wavefunction.hpp"
5#include "fmt/color.hpp"
6#include "qip/Maths.hpp"
7#include <functional>
8
9namespace DiracOperator {
10
11//==============================================================================
13namespace Hyperfine {
14
15using Func_R2_R = std::function<double(double, double)>; // save typing
16
17//==============================================================================
19inline std::vector<double> RadialFunc(int k, double rN, const Grid &rgrid,
20 const Func_R2_R &hfs_F) {
21 std::vector<double> rfunc;
22 rfunc.reserve(rgrid.num_points());
23 for (const auto r : rgrid) {
24 rfunc.push_back(hfs_F(r, rN) / std::pow(r, k + 1));
25 }
26 return rfunc;
27}
28
29//==============================================================================
31inline auto sphericalBall_F(int k = 1) -> Func_R2_R {
32 return [=](double r, double rN) {
33 return (r > rN) ? 1.0 : std::pow(r / rN, 2 * k + 1);
34 };
35}
36
38inline auto sphericalShell_F() -> Func_R2_R {
39 return [=](double r, double rN) { return (r > rN) ? 1.0 : 0.0; };
40}
41
43inline auto pointlike_F() -> Func_R2_R {
44 return [=](double, double) { return 1.0; };
45}
46
47//------------------------------------------------------------------------------
49inline auto VolotkaSP_F(double mu, double I_nuc, double l_pn, int gl,
50 bool print = true) -> Func_R2_R
51// Function that returns generates + returns F_BW Bohr-Weiskopf
52// gl = 1 for proton, =0 for neutron. Double allowed for testing..
53// mu is in units of Nuclear Magneton!
54{
55 const auto two_I = int(2 * I_nuc + 0.0001);
56 const auto two_l = int(2 * l_pn + 0.0001);
57 const auto g_l = double(gl); // just safety
58 const auto gI = mu / I_nuc;
59
60 const auto K = (l_pn * (l_pn + 1.0) - (3. / 4.)) / (I_nuc * (I_nuc + 1.0));
61 const double g_s = (2.0 * gI - g_l * (K + 1.0)) / (1.0 - K);
62 if (print)
63 std::cout << "SingleParticle using: gl=" << g_l << ", gs=" << g_s
64 << ", l=" << l_pn << ", gI=" << gI << " (I=" << I_nuc << ")\n";
65 const double factor =
66 (two_I == two_l + 1) ?
67 g_s * (1 - two_I) / (4.0 * (two_I + 2)) + g_l * 0.5 * (two_I - 1) :
68 g_s * (3 + two_I) / (4.0 * (two_I + 2)) +
69 g_l * 0.5 * two_I * (two_I + 3) / (two_I + 2);
70 if (two_I != two_l + 1 && two_I != two_l - 1) {
71 std::cerr << "\nFAIL:59 in Hyperfine (VolotkaSP_F):\n "
72 "we must have I = l +/- 1/2, but we have: I,l = "
73 << I_nuc << "," << l_pn << "\n";
74 return [](double, double) { return 0.0; };
75 }
76 return [=](double r, double rN) {
77 return (r > rN) ? 1.0 :
78 ((r * r * r) / (rN * rN * rN)) *
79 (1.0 - (3.0 / mu) * std::log(r / rN) * factor);
80 };
81}
82
83//------------------------------------------------------------------------------
85inline auto uSP(double mu, double I_nuc, double l_pn, int gl, double n,
86 double R, bool u_option, bool print = true) -> Func_R2_R {
87 const auto two_I = int(2 * I_nuc + 0.0001);
88 const auto two_l = int(2 * l_pn + 0.0001);
89 const auto g_l = double(gl); // just safety
90 const auto gI = mu / I_nuc;
91
92 const auto K = (l_pn * (l_pn + 1.0) - (3. / 4.)) / (I_nuc * (I_nuc + 1.0));
93 const double g_s = (2.0 * gI - g_l * (K + 1.0)) / (1.0 - K);
94 if (print) {
95 std::cout << "uSP using: gl=" << g_l << ", gs=" << g_s << ", l=" << l_pn
96 << ", gI=" << gI << " (I=" << I_nuc << ")\n";
97 if (u_option) {
98 std::cout << "u(r) = u1(r) = u0 (R-r)^n ";
99 } else {
100 std::cout << "u(r) = u2(r) = u0 r^n ";
101 }
102 std::cout << "with n = " << n << "\n";
103 }
104 if (two_I != two_l + 1 && two_I != two_l - 1) {
105 std::cerr << "\nFAIL:59 in Hyperfine (uSP):\n "
106 "we must have I = l +/- 1/2, but we have: I,l = "
107 << I_nuc << "," << l_pn << "\n";
108 return [](double, double) { return 0.0; };
109 }
110
111 // nb: in theory, can read u(r) in from file!
112 // r^2 * u(r)^2
113 const auto r2u2 = [=](double r) {
114 return u_option ? r * r * std::pow(R - r, 2.0 * n) :
115 r * r * std::pow(r, 2.0 * n);
116 };
117
118 // normalisation
119 const auto u02 =
120 1.0 / NumCalc::num_integrate(r2u2, 0.0, R, 100, NumCalc::linear);
121
122 const auto F0r = [=](double r) {
123 const auto f = [=](double x) { return u02 * r2u2(x); };
124 return NumCalc::num_integrate(f, 0.0, r, 100, NumCalc::linear);
125 };
126
127 const auto FrR = [=](double r) {
128 const auto f = [=](double x) {
129 return u02 * r2u2(x) * r * r * r / x / x / x;
130 };
131 return NumCalc::num_integrate(f, r, R, 100, NumCalc::linear);
132 };
133
134 const auto two_Ip1 = 2.0 * (I_nuc + 1.0);
135 const auto twoI_p3 = 2.0 * I_nuc + 3.0;
136 const auto twoI_m1 = 2.0 * I_nuc - 1.0;
137
138 double f1 = (two_I == two_l + 1) ?
139 0.5 * g_s + (I_nuc - 0.5) * g_l :
140 -I_nuc / two_Ip1 * g_s + I_nuc * twoI_p3 / two_Ip1 * g_l;
141
142 double f2 =
143 (two_I == two_l + 1) ?
144 -twoI_m1 / (4.0 * two_Ip1) * g_s + (I_nuc - 0.5) * g_l :
145 twoI_p3 / (4.0 * two_Ip1) * g_s + I_nuc * twoI_p3 / two_Ip1 * g_l;
146
147 return [=](double r, double rN) {
148 return (r > rN) ? 1.0 : (1.0 / mu) * (f1 * F0r(r) + f2 * FrR(r));
149 };
150}
151
152//------------------------------------------------------------------------------
154inline auto doublyOddSP_F(double mut, double It, double mu1, double I1,
155 double l1, int gl1, double I2, double l2,
156 bool print = true) -> Func_R2_R
157// F(r) * g = 0.5 [ g1F1 + g2F2 + (g1F1 - g2F2) * K]
158// K = [I1(I1+1) - I2(I2+1)] / [I(I+1)]
159// return F(r) [divide by g]
160// VolotkaSP_F(mu, I, l, g_l); //gl is 1 or 0
161// g2 : from: g = 0.5 [ g1 + g2 + (g1 - g2) * K]
162{
163 const auto K = (I1 * (I1 + 1.0) - I2 * (I2 + 1.0)) / (It * (It + 1.0));
164 const auto gt = mut / It;
165 const auto g1 = mu1 / I1;
166 const auto g2 = (g1 * (K + 1.0) - 2.0 * gt) / (K - 1.0);
167 const auto mu2 = g2 * I2;
168 const auto gl2 = (gl1 == 0) ? 1 : 0;
169 const auto F1 = VolotkaSP_F(mu1, I1, l1, gl1, print);
170 const auto F2 = VolotkaSP_F(mu2, I2, l2, gl2, print);
171 return [=](double r, double rN) {
172 return (0.5 / gt) * (g1 * F1(r, rN) + g2 * F2(r, rN) +
173 K * (g1 * F1(r, rN) - g2 * F2(r, rN)));
174 };
175}
176
177//------------------------------------------------------------------------------
179inline double convert_RME_to_AB_2J(int k, int tja, int tjb) {
180 // first, get stretched state:
181 const auto tjz = std::min(tja, tjb); // arbitrary choice
182 const auto s = Angular::neg1pow_2(tja - tjb);
183 const auto tjs = Angular::threej_2(tja, 2 * k, tjb, -tjz, 0, tjz);
184 // then: moment-specific factor
185 // const auto f = k % 2 == 0 ? 2.0 : 1 / (0.5 * tjz);
186 const auto f = [&]() {
187 switch (k) {
188 case 1: {
189 // A: RME includes (/I) A = (1/J) <T1^e>_J (/I)
190 const double J = 0.5 * tjz;
191 return 1.0 / J;
192 }
193 case 2:
194 // B: Q = 2 <T2^n> B = 2 Q <T2^e>_J
195 return 2.0;
196 case 3:
197 // C: = - <T3^n> C = - <T3^e>_J
198 return -1.0;
199 case 4:
200 // D: = <T4^n> (standard) D = <T4^e>_J
201 return 1.0; // ???
202
203 default:
204 std::cout << "Warning: k=" << k
205 << " has no standard A/B/C/D hyperfine-constant definition; "
206 "using f=1\n";
207 return 1.0; // ???
208 }
209 }();
210 return s * f * tjs;
211}
212
214inline double convert_RME_to_AB(int k, int ka, int kb) {
215 const auto tja = Angular::twoj_k(ka);
216 const auto tjb = Angular::twoj_k(kb);
217 return convert_RME_to_AB_2J(k, tja, tjb);
218}
219
220inline double hfsA(const TensorOperator *h, const DiracSpinor &Fa) {
221 auto Raa = h->radialIntegral(Fa, Fa); //?
222 return Raa * Fa.kappa() / (Fa.jjp1()) * PhysConst::muN_CGS_MHz;
223}
224
225inline double hfsB(const TensorOperator *h, const DiracSpinor &Fa) {
226 auto Raa = h->radialIntegral(Fa, Fa); //?
227 return Raa * double(Fa.twoj() - 1) / double(Fa.twoj() + 2) *
228 PhysConst::barn_MHz;
229}
230
231} // namespace Hyperfine
232
233//==============================================================================
234//==============================================================================
235//==============================================================================
238class hfs final : public TensorOperator {
239 // see Xiao, ..., Derevianko, Phys. Rev. A 102, 022810 (2020).
240 using Func_R2_R = std::function<double(double, double)>;
241
242public:
243 hfs(int in_k, double in_GQ, double rN_au, const Grid &rgrid,
244 const Func_R2_R &hfs_F = Hyperfine::pointlike_F(), bool MHzQ = true)
245 : TensorOperator(in_k, Parity::even, in_GQ,
246 Hyperfine::RadialFunc(in_k, rN_au, rgrid, hfs_F)),
247 k(in_k),
248 magnetic(k % 2 != 0),
249 cfg(magnetic ? 1.0 : 0.0),
250 cff(magnetic ? 0.0 : 1.0),
251 mMHzQ(MHzQ) {
252
253 const auto power = magnetic ? (k - 1) / 2 : k / 2;
254
255 // Assumes nuclear moment in muN*b^(k-1)/2 for magnetic,
256 // and b^k/2 for electric
257 const auto unit_au =
258 magnetic ? PhysConst::muN_CGS * std::pow(PhysConst::barn_au, power) :
259 std::pow(PhysConst::barn_au, power);
260 m_unit = mMHzQ ? unit_au * PhysConst::Hartree_MHz : unit_au;
261 }
262
263 std::string name() const override final {
264 return "hfs" + std::to_string(k) + "";
265 }
266 std::string units() const override final { return mMHzQ ? "MHz" : "au"; }
267
268 double angularF(const int ka, const int kb) const override final {
269 return magnetic ? -double(ka + kb) / double(k) *
270 Angular::Ck_kk(k, -ka, kb) * m_unit :
271 -Angular::Ck_kk(k, ka, kb) * m_unit;
272 }
273
274 double angularCff(int, int) const override final { return cff; }
275 double angularCgg(int, int) const override final { return cff; }
276 double angularCfg(int, int) const override final { return cfg; }
277 double angularCgf(int, int) const override final { return cfg; }
278
279private:
280 int k;
281 bool magnetic;
282 double cfg;
283 double cff;
284 bool mMHzQ;
285 double m_unit{1.0};
286};
287
288//==============================================================================
289//==============================================================================
290inline std::unique_ptr<DiracOperator::TensorOperator>
291generate_hfs(const IO::InputBlock &input, const Wavefunction &wf) {
292 using namespace DiracOperator;
293
294 input.check(
295 {{"", "Most following will be taken from the default nucleus if "
296 "not explicitely given"},
297 {"mu", "Magnetic moment in mu_N"},
298 {"Q", "Nuclear quadrupole moment, in barns. Also used as overall "
299 "constant for any higher-order moments [1.0]"},
300 {"k", "Multipolarity. 1=mag. dipole, 2=elec. quad, etc. [1]"},
301 {"rrms",
302 "nuclear (magnetic) rms radius, in Fermi (fm) (defult is charge rms)"},
303 {"units", "Units for output (only for k=1,k=2). MHz or au [MHz]"},
304 {"F", "F(r): Nuclear moment distribution: ball, point, shell, "
305 "SingleParticle, or doublyOddSP [ball]"},
306 {"F(r)", "Obselete; use 'F' from now - will be removed"},
307 {"nuc_mag", "Obselete; use 'F' from now - will be removed"},
308 {"printF", "Writes F(r) to a text file [false]"},
309 {"print", "Write F(r) info to screen [true]"},
310 {"", "The following are only for F=SingleParticle or doublyOddSP"},
311 {"I", "Nuclear spin. Taken from nucleus"},
312 {"parity", "Nulcear parity: +/-1"},
313 {"l", "l for unpaired nucleon (automatically derived from I and "
314 "parity; best to leave as default)"},
315 {"gl", "=1 for proton, =0 for neutron"},
316 {"", "The following are only used if F=doublyOddSP"},
317 {"mu1", "mag moment of 'first' unpaired nucleon"},
318 {"gl1", "gl of 'first' unpaired nucleon"},
319 {"l1", "l of 'first' unpaired nucleon"},
320 {"l2", "l of 'second' unpaired nucleon"},
321 {"I1", "total spin (J) of 'first' unpaired nucleon"},
322 {"I2", "total spin (J) of 'second' unpaired nucleon"},
323 {"", "The following are only for u(r) function"},
324 {"u", "u1 or u2 : u1(r) = (R-r)^n, u2(r) = r^n [u1]"},
325 {"n", "n that appears above. Should be between 0 and 2 [0]"}});
326 if (input.has_option("help")) {
327 return nullptr;
328 }
329
330 const auto nuc = wf.nucleus();
331 const auto isotope = Nuclear::findIsotopeData(nuc.z(), nuc.a());
332 auto mu = input.get("mu", isotope.mu ? *isotope.mu : 1.0);
333 auto I_nuc = input.get("I", isotope.I_N ? *isotope.I_N : 1.0);
334 const auto print = input.get("print", true);
335 const auto k = input.get("k", 1);
336
337 const auto use_MHz =
338 qip::ci_compare(input.get<std::string>("units", "MHz"), "MHz");
339
340 if (k <= 0) {
341 fmt2::styled_print(fg(fmt::color::red), "\nError 246:\n");
342 std::cout << "In hyperfine: invalid K=" << k << "! meaningless results\n";
343 }
344 if (I_nuc <= 0 && k == 1) {
345 fmt2::styled_print(fg(fmt::color::orange), "\nWarning 253:\n");
346 std::cout << "In hyperfine: invalid I_nuc=" << I_nuc
347 << "! meaningless results\nSetting I=1\n";
348 I_nuc = 1;
349 }
350 if (mu == 0.0 && k == 1) {
351 fmt2::styled_print(fg(fmt::color::orange), "\nWarning 352:\n");
352 std::cout << "Setting mu=1\n";
353 mu = 1;
354 }
355
356 const auto g_or_Q = (k == 1) ? (mu / I_nuc) :
357 (k == 2) ? input.get("Q", isotope.q ? *isotope.q : 1.0) :
358 input.get("Q", 1.0);
359
360 enum class DistroType {
361 point,
362 ball,
363 shell,
364 SingleParticle,
365 doublyOddSP,
366 spu,
367 Error
368 };
369
370 std::string default_distribution = "ball";
371
372 // For compatability with old notation of 'F(r)' input option
373 const auto Fr_str =
374 input.has_option("F") ?
375 input.get<std::string>("F", default_distribution) :
376 input.has_option("nuc_mag") ?
377 input.get<std::string>("nuc_mag", default_distribution) :
378 input.get<std::string>("F(r)", default_distribution);
379
380 const auto distro_type =
381 (qip::ci_wc_compare(Fr_str, "point*") || qip::ci_compare(Fr_str, "1")) ?
382 DistroType::point :
383 qip::ci_compare(Fr_str, "ball") ? DistroType::ball :
384 qip::ci_compare(Fr_str, "shell") ? DistroType::shell :
385 qip::ci_wc_compare(Fr_str, "Single*") ? DistroType::SingleParticle :
386 qip::ci_wc_compare(Fr_str, "doublyOdd*") ? DistroType::doublyOddSP :
387 qip::ci_compare(Fr_str, "spu") ? DistroType::spu :
388 DistroType::Error;
389 if (distro_type == DistroType::Error) {
390 fmt2::styled_print(fg(fmt::color::red), "\nError 271:\n");
391 std::cout << "\nIn hyperfine. Unkown F(r) - " << Fr_str << "\n";
392 std::cout << "Defaulting to pointlike!\n";
393 }
394
395 const auto r_rmsfm =
396 distro_type == DistroType::point ? 0.0 : input.get("rrms", nuc.r_rms());
397 const auto r_nucfm = std::sqrt(5.0 / 3) * r_rmsfm;
398 const auto r_nucau = r_nucfm / PhysConst::aB_fm;
399
400 if (print) {
401 std::cout << "\nHyperfine structure: " << wf.atom() << "\n";
402 std::cout << "K=" << k << " ("
403 << (k == 1 ? "magnetic dipole" :
404 k == 2 ? "electric quadrupole" :
405 k % 2 == 0 ? "electric multipole" :
406 "magnetic multipole")
407 << ")\n";
408 std::cout << "Using " << Fr_str << " nuclear distro for F(r)\n"
409 << "w/ r_N = " << r_nucfm << "fm = " << r_nucau
410 << "au (r_rms=" << r_rmsfm << "fm)\n";
411 std::cout << "Points inside nucleus: " << wf.grid().getIndex(r_nucau)
412 << "\n";
413 if (k == 1) {
414 std::cout << "mu = " << mu << ", I = " << I_nuc << ", g = " << g_or_Q
415 << "\n";
416 } else {
417 std::cout << "Q = " << g_or_Q << "\n";
418 }
419 }
420
421 // default is BALL:
422 auto Fr = Hyperfine::sphericalBall_F(k);
423 if (distro_type == DistroType::ball) {
425 } else if (distro_type == DistroType::shell) {
427 } else if (distro_type == DistroType::SingleParticle) {
428 const auto pi = input.get("parity", isotope.parity ? *isotope.parity : 0);
429 const auto l_tmp = int(I_nuc + 0.5 + 0.0001);
430 auto l = ((l_tmp % 2 == 0) == (pi == 1)) ? l_tmp : l_tmp - 1;
431 l = input.get("l", l); // can override derived 'l' (not recommended)
432 const auto gl_default = wf.Znuc() % 2 == 0 ? 0 : 1; // unparied proton?
433 const auto gl = input.get<int>("gl", gl_default);
434 if (print) {
435 std::cout << "Single-Particle (Volotka formula) for unpaired";
436 if (gl == 1)
437 std::cout << " proton ";
438 else if (gl == 0)
439 std::cout << " neturon ";
440 else
441 std::cout << " gl=" << gl << "??? program will run, but prob wrong!\n";
442 std::cout << "with l=" << l << " (pi=" << pi << ")\n";
443 }
444 Fr = Hyperfine::VolotkaSP_F(mu, I_nuc, l, gl, print);
445 } else if (distro_type == DistroType::spu) {
446 const auto pi = input.get("parity", isotope.parity ? *isotope.parity : 0);
447 const auto u_func = input.get("u", std::string{"u1"}); // u1=(R-r)^n, u2=r^n
448 const bool u_option = u_func == std::string{"u1"};
449 const auto n = input.get("n", 0.0); // u1=(R-r)^n, u2=r^n
450 const auto l_tmp = int(I_nuc + 0.5 + 0.0001);
451 auto l = ((l_tmp % 2 == 0) == (pi == 1)) ? l_tmp : l_tmp - 1;
452 l = input.get("l", l); // can override derived 'l' (not recommended)
453 const auto gl_default = wf.Znuc() % 2 == 0 ? 0 : 1; // unparied proton?
454 const auto gl = input.get<int>("gl", gl_default);
455 if (print) {
456 std::cout << "Single-Particle (Volotka formula) with u(r) for unpaired";
457 if (gl == 1)
458 std::cout << " proton ";
459 else if (gl == 0)
460 std::cout << " neturon ";
461 else
462 std::cout << " gl=" << gl << "??? program will run, but prob wrong!\n";
463 std::cout << "with l=" << l << " (pi=" << pi << ")\n";
464 }
465 Fr = Hyperfine::uSP(mu, I_nuc, l, gl, n, r_nucau, u_option, print);
466 } else if (distro_type == DistroType::doublyOddSP) {
467 const auto mu1 = input.get<double>("mu1", 1.0);
468 const auto gl1 = input.get<int>("gl1", -1); // 1 or 0 (p or n)
469 if (gl1 != 0 && gl1 != 1) {
470 fmt2::styled_print(fg(fmt::color::red), "\nError 324:\n");
471 std::cout << "In " << input.name() << " " << Fr_str
472 << "; have gl1=" << gl1 << " but need 1 or 0\n";
473 return std::make_unique<NullOperator>(NullOperator());
474 }
475 const auto l1 = input.get<double>("l1", -1.0);
476 const auto l2 = input.get<double>("l2", -1.0);
477 const auto I1 = input.get<double>("I1", -1.0);
478 const auto I2 = input.get<double>("I2", -1.0);
479
480 Fr = Hyperfine::doublyOddSP_F(mu, I_nuc, mu1, I1, l1, gl1, I2, l2, print);
481 }
482
483 // Optionally print F(r) function to file
484 if (input.get<bool>("printF", false)) {
485 std::ofstream of(wf.identity() + "_" + Fr_str + ".txt");
486 of << "r/fm F(r)\n";
487 for (auto r : wf.grid()) {
488 of << r * PhysConst::aB_fm << " "
489 << Fr(r * PhysConst::aB_fm, r_nucau * PhysConst::aB_fm) << "\n";
490 }
491 }
492
493 return std::make_unique<hfs>(k, g_or_Q, r_nucau, wf.grid(), Fr, use_MHz);
494}
495
496} // namespace DiracOperator
Speacial operator: 0.
Definition TensorOperator.hpp:279
General operator (virtual base class); operators derive from this.
Definition TensorOperator.hpp:110
virtual double radialIntegral(const DiracSpinor &Fa, const DiracSpinor &Fb) const
Defined via <a||h||b> = angularF(a,b) * radialIntegral(a,b) (Note: if radial_rhs is overridden,...
Definition TensorOperator.cpp:133
Units: Assumes nuclear moment in units of powers of nuclear magnetons and/or barns - muN*b^(k-1)/2 fo...
Definition hfs.hpp:238
std::string units() const override final
Returns units of operator (usually au, may be MHz, etc.)
Definition hfs.hpp:266
std::string name() const override final
Returns "name" of operator (e.g., 'E1')
Definition hfs.hpp:263
double angularF(const int ka, const int kb) const override final
angularF: links radiation integral to RME. RME = <a||h||b> = angularF(a,b) * radial_int(a,...
Definition hfs.hpp:268
l (orbital angular momentum) operator
Definition jls.hpp:27
s (spin) operator
Definition jls.hpp:50
Stores radial Dirac spinor: F_nk = (f, g)
Definition DiracSpinor.hpp:41
int kappa() const
Dirac quantum number, kappa.
Definition DiracSpinor.hpp:87
double jjp1() const
j(j+1)
Definition DiracSpinor.hpp:91
Holds grid, including type + Jacobian (dr/du)
Definition Grid.hpp:31
auto num_points() const
Number of grid points.
Definition Grid.hpp:64
std::size_t getIndex(double x, bool require_nearest=false) const
Given value, returns grid index. if not require_nearest, returns lower.
Definition Grid.cpp:76
Holds list of Options, and a list of other InputBlocks. Can be initialised with a list of options,...
Definition InputBlock.hpp:142
bool check(std::initializer_list< std::string > blocks, const std::vector< std::pair< std::string, std::string > > &list, bool print=false) const
Check all the options and blocks in this; if any of them are not present in 'list',...
Definition InputBlock.hpp:594
bool has_option(std::string_view key) const
Check is option is present (even if not set) in current block.
Definition InputBlock.hpp:201
T get(std::string_view key, T default_value) const
If 'key' exists in the options, returns value. Else, returns default_value. Note: If two keys with sa...
Definition InputBlock.hpp:417
Stores Wavefunction (set of valence orbitals, grid, HF etc.)
Definition Wavefunction.hpp:37
const Grid & grid() const
Returns a const reference to the radial grid.
Definition Wavefunction.hpp:82
int Znuc() const
Nuclear charge, Z.
Definition Wavefunction.hpp:99
std::string identity() const
Atomic symbol, including core ionisation degree and run_label.
Definition Wavefunction.cpp:685
std::string atom() const
String of atom info (e.g., "Cs, Z=55, A=133")
Definition Wavefunction.hpp:190
const Nuclear::Nucleus & nucleus() const
Returns Nuclear::nucleus object (contains nuc. parameters)
Definition Wavefunction.hpp:97
double threej_2(int two_j1, int two_j2, int two_j3, int two_m1, int two_m2, int two_m3)
Calculates wigner 3j symbol. Takes in 2*j (or 2*l) - intput is integer.
Definition Wigner369j.hpp:177
constexpr int neg1pow_2(int two_a)
Evaluates (-1)^{two_a/2} (for integer a; two_a is even)
Definition Wigner369j.hpp:152
constexpr int twoj_k(int ka)
returns 2j given kappa
Definition Wigner369j.hpp:45
double Ck_kk(int k, int ka, int kb)
Reduced (relativistic) angular ME: <ka||C^k||kb> [takes k and kappa].
Definition Wigner369j.hpp:298
auto doublyOddSP_F(double mut, double It, double mu1, double I1, double l1, int gl1, double I2, double l2, bool print=true) -> Func_R2_R
'Volotka' SP model, for doubly-odd nuclei: Phys. Rev. Lett. 125, 063002 (2020)
Definition hfs.hpp:154
auto sphericalBall_F(int k=1) -> Func_R2_R
Spherical ball F(r): (r/rN)^3 for r<rN, 1 for r>rN.
Definition hfs.hpp:31
auto uSP(double mu, double I_nuc, double l_pn, int gl, double n, double R, bool u_option, bool print=true) -> Func_R2_R
Elizarov et al., Optics and Spectroscopy (2006): u(r) = u0(R-r)^n.
Definition hfs.hpp:85
auto pointlike_F() -> Func_R2_R
Pointlike F(r): 1.
Definition hfs.hpp:43
double convert_RME_to_AB(int k, int ka, int kb)
Converts reduced matrix element to A/B coeficients (takes k, kappa, kappa)
Definition hfs.hpp:214
double convert_RME_to_AB_2J(int k, int tja, int tjb)
Converts reduced matrix element to A/B coeficients (takes k, 2J, 2J)
Definition hfs.hpp:179
auto VolotkaSP_F(double mu, double I_nuc, double l_pn, int gl, bool print=true) -> Func_R2_R
'Volotka' single-particle model: see Phys. Rev. Lett. 125, 063002 (2020)
Definition hfs.hpp:49
auto sphericalShell_F() -> Func_R2_R
Spherical shell F(r): 0 for r<rN, 1 for r>rN.
Definition hfs.hpp:38
std::vector< double > RadialFunc(int k, double rN, const Grid &rgrid, const Func_R2_R &hfs_F)
Takes in F(r) and k, and forms hyperfine radial function: F(r,rN)/r^{k+1}.
Definition hfs.hpp:19
Dirac Operators: General + derived.
Definition GenerateOperator.cpp:3
Isotope findIsotopeData(int z, int a)
Looks up + returns an isotope from the list. If not in list, partially blank.
Definition NuclearData.cpp:6
constexpr double muN_CGS_MHz
Nulcear magneton in MHz (via Gaussian CGS-derived atomic units):
Definition PhysConst_constants.hpp:103
constexpr double muN_CGS
Nulcear magneton (in Gaussian CGS-derived atomic units):
Definition PhysConst_constants.hpp:101
qip library: A collection of useful functions
Definition Array.hpp:9
bool ci_wc_compare(std::string_view s1, std::string_view s2)
Compares two strings, s1 and s2. s2 may contain ONE wildcard ('*') which will match anything....
Definition String.hpp:139
bool ci_compare(std::string_view s1, std::string_view s2)
Case insensitive string compare. Essentially: LowerCase(s1)==LowerCase(s2)
Definition String.hpp:131