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"
43std::vector<double>
tk_radial(
int k,
double rN,
const std::vector<double> &r,
117 double R,
bool u_option,
bool print =
true);
155 double l1,
int gl1,
double I2,
double l2,
229 using RadialFunction = std::function<double(
double,
double)>;
247 hfs(
int in_k,
double GQ,
double rN_au,
const Grid &rgrid,
250 Hyperfine::tk_radial(in_k, rN_au, rgrid.r(), hfs_F)),
252 magnetic(k % 2 != 0),
253 cfg(magnetic ? 1.0 : 0.0),
254 cff(magnetic ? 0.0 : 1.0),
257 const auto power = magnetic ? (k - 1) / 2 : k / 2;
263 std::pow(PhysConst::barn_au, power);
264 m_unit = mMHzQ ? unit_au * PhysConst::Hartree_MHz : unit_au;
267 std::string
name() const override final {
268 return "hfs" + std::to_string(k) +
"";
270 std::string
units() const override final {
return mMHzQ ?
"MHz" :
"au"; }
272 double angularF(
const int ka,
const int kb)
const override final {
273 return magnetic ? -double(ka + kb) / double(k) *
278 double angularCff(
int,
int)
const override final {
return cff; }
279 double angularCgg(
int,
int)
const override final {
return cff; }
280 double angularCfg(
int,
int)
const override final {
return cfg; }
281 double angularCgf(
int,
int)
const override final {
return cfg; }
294inline std::unique_ptr<DiracOperator::TensorOperator>
299 {{
"",
"Most following will be taken from the default nucleus if "
300 "not explicitely given"},
301 {
"mu",
"Magnetic moment in mu_N"},
302 {
"Q",
"Nuclear quadrupole moment, in barns. Also used as overall "
303 "constant for any higher-order moments [1.0]"},
304 {
"k",
"Multipolarity. 1=mag. dipole, 2=elec. quad, etc. [1]"},
306 "nuclear (magnetic) rms radius, in Fermi (fm) (defult is charge rms)"},
307 {
"units",
"Units for output (only for k=1,k=2). MHz or au [MHz]"},
308 {
"F",
"F(r): Nuclear moment distribution: ball, point, shell, "
309 "SingleParticle, or doublyOddSP [ball]"},
310 {
"F(r)",
"Obselete; use 'F' from now - will be removed"},
311 {
"nuc_mag",
"Obselete; use 'F' from now - will be removed"},
312 {
"printF",
"Writes F(r) to a text file [false]"},
313 {
"print",
"Write F(r) info to screen [true]"},
314 {
"",
"The following are only for F=SingleParticle or doublyOddSP"},
315 {
"I",
"Nuclear spin. Taken from nucleus"},
316 {
"parity",
"Nulcear parity: +/-1"},
317 {
"l",
"l for unpaired nucleon (automatically derived from I and "
318 "parity; best to leave as default)"},
319 {
"gl",
"=1 for proton, =0 for neutron"},
320 {
"",
"The following are only used if F=doublyOddSP"},
321 {
"mu1",
"mag moment of 'first' unpaired nucleon"},
322 {
"gl1",
"gl of 'first' unpaired nucleon"},
323 {
"l1",
"l of 'first' unpaired nucleon"},
324 {
"l2",
"l of 'second' unpaired nucleon"},
325 {
"I1",
"total spin (J) of 'first' unpaired nucleon"},
326 {
"I2",
"total spin (J) of 'second' unpaired nucleon"},
327 {
"",
"The following are only for u(r) function"},
328 {
"u",
"u1 or u2 : u1(r) = (R-r)^n, u2(r) = r^n [u1]"},
329 {
"n",
"n that appears above. Should be between 0 and 2 [0]"}});
336 auto mu = input.
get(
"mu", isotope.mu ? *isotope.mu : 1.0);
337 auto I_nuc = input.
get(
"I", isotope.I_N ? *isotope.I_N : 1.0);
338 const auto print = input.
get(
"print",
true);
339 const auto k = input.
get(
"k", 1);
345 fmt2::styled_print(fg(fmt::color::red),
"\nError 246:\n");
346 std::cout <<
"In hyperfine: invalid K=" << k <<
"! meaningless results\n";
348 if (I_nuc <= 0 && k == 1) {
349 fmt2::styled_print(fg(fmt::color::orange),
"\nWarning 253:\n");
350 std::cout <<
"In hyperfine: invalid I_nuc=" << I_nuc
351 <<
"! meaningless results\nSetting I=1\n";
354 if (mu == 0.0 && k == 1) {
355 fmt2::styled_print(fg(fmt::color::orange),
"\nWarning 352:\n");
356 std::cout <<
"Setting mu=1\n";
360 const auto g_or_Q = (k == 1) ? (mu / I_nuc) :
361 (k == 2) ? input.
get(
"Q", isotope.q ? *isotope.q : 1.0) :
364 enum class DistroType {
374 std::string default_distribution =
"ball";
379 input.
get<std::string>(
"F", default_distribution) :
380 input.has_option(
"nuc_mag") ?
381 input.get<std::string>(
"nuc_mag", default_distribution) :
382 input.get<std::string>(
"F(r)", default_distribution);
384 const auto distro_type =
393 if (distro_type == DistroType::Error) {
394 fmt2::styled_print(fg(fmt::color::red),
"\nError 271:\n");
395 std::cout <<
"\nIn hyperfine. Unkown F(r) - " << Fr_str <<
"\n";
396 std::cout <<
"Defaulting to pointlike!\n";
400 distro_type == DistroType::point ? 0.0 : input.
get(
"rrms", nuc.r_rms());
401 const auto r_nucfm = std::sqrt(5.0 / 3) * r_rmsfm;
402 const auto r_nucau = r_nucfm / PhysConst::aB_fm;
405 std::cout <<
"\nHyperfine structure: " << wf.
atom() <<
"\n";
406 std::cout <<
"K=" << k <<
" ("
407 << (k == 1 ?
"magnetic dipole" :
408 k == 2 ?
"electric quadrupole" :
409 k % 2 == 0 ?
"electric multipole" :
410 "magnetic multipole")
412 std::cout <<
"Using " << Fr_str <<
" nuclear distro for F(r)\n"
413 <<
"w/ r_N = " << r_nucfm <<
"fm = " << r_nucau
414 <<
"au (r_rms=" << r_rmsfm <<
"fm)\n";
415 std::cout <<
"Points inside nucleus: " << wf.
grid().
getIndex(r_nucau)
418 std::cout <<
"mu = " << mu <<
", I = " << I_nuc <<
", g = " << g_or_Q
421 std::cout <<
"Q = " << g_or_Q <<
"\n";
427 if (distro_type == DistroType::ball) {
429 }
else if (distro_type == DistroType::shell) {
431 }
else if (distro_type == DistroType::SingleParticle) {
432 const auto pi = input.
get(
"parity", isotope.parity ? *isotope.parity : 0);
433 const auto l_tmp = int(I_nuc + 0.5 + 0.0001);
434 auto l = ((l_tmp % 2 == 0) == (pi == 1)) ? l_tmp : l_tmp - 1;
435 l = input.
get(
"l",
l);
436 const auto gl_default = wf.
Znuc() % 2 == 0 ? 0 : 1;
437 const auto gl = input.
get<
int>(
"gl", gl_default);
439 std::cout <<
"Single-Particle (Volotka formula) for unpaired";
441 std::cout <<
" proton ";
443 std::cout <<
" neturon ";
445 std::cout <<
" gl=" << gl <<
"??? program will run, but prob wrong!\n";
446 std::cout <<
"with l=" <<
l <<
" (pi=" << pi <<
")\n";
449 }
else if (distro_type == DistroType::spu) {
450 const auto pi = input.
get(
"parity", isotope.parity ? *isotope.parity : 0);
451 const auto u_func = input.
get(
"u", std::string{
"u1"});
452 const bool u_option = u_func == std::string{
"u1"};
453 const auto n = input.
get(
"n", 0.0);
454 const auto l_tmp = int(I_nuc + 0.5 + 0.0001);
455 auto l = ((l_tmp % 2 == 0) == (pi == 1)) ? l_tmp : l_tmp - 1;
456 l = input.
get(
"l",
l);
457 const auto gl_default = wf.
Znuc() % 2 == 0 ? 0 : 1;
458 const auto gl = input.
get<
int>(
"gl", gl_default);
460 std::cout <<
"Single-Particle (Volotka formula) with u(r) for unpaired";
462 std::cout <<
" proton ";
464 std::cout <<
" neturon ";
466 std::cout <<
" gl=" << gl <<
"??? program will run, but prob wrong!\n";
467 std::cout <<
"with l=" <<
l <<
" (pi=" << pi <<
")\n";
470 }
else if (distro_type == DistroType::doublyOddSP) {
471 const auto mu1 = input.
get<
double>(
"mu1", 1.0);
472 const auto gl1 = input.
get<
int>(
"gl1", -1);
473 if (gl1 != 0 && gl1 != 1) {
474 fmt2::styled_print(fg(fmt::color::red),
"\nError 324:\n");
475 std::cout <<
"In " << input.name() <<
" " << Fr_str
476 <<
"; have gl1=" << gl1 <<
" but need 1 or 0\n";
479 const auto l1 = input.
get<
double>(
"l1", -1.0);
480 const auto l2 = input.
get<
double>(
"l2", -1.0);
481 const auto I1 = input.
get<
double>(
"I1", -1.0);
482 const auto I2 = input.
get<
double>(
"I2", -1.0);
488 if (input.
get<
bool>(
"printF",
false)) {
489 std::ofstream of(wf.
identity() +
"_" + Fr_str +
".txt");
491 for (
auto r : wf.grid()) {
492 of << r * PhysConst::aB_fm <<
" "
493 << Fr(r * PhysConst::aB_fm, r_nucau * PhysConst::aB_fm) <<
"\n";
497 return std::make_unique<hfs>(k, g_or_Q, r_nucau, wf.
grid(), Fr, use_MHz);
Speacial operator: 0.
Definition TensorOperator.hpp:324
General operator (virtual base class); operators derive from this.
Definition TensorOperator.hpp:65
Generalised hyperfine-structure operator, including relevant nuclear moment.
Definition hfs.hpp:228
double angularCgg(int, int) const override final
Angular factor for g_a*g_b part of radial integral.
Definition hfs.hpp:279
double angularCgf(int, int) const override final
Angular factor for g_a*f_b part of radial integral.
Definition hfs.hpp:281
double angularCfg(int, int) const override final
Angular factor for f_a*g_b part of radial integral.
Definition hfs.hpp:280
std::string units() const override final
Returns units of operator (usually au, may be MHz, etc.)
Definition hfs.hpp:270
std::string name() const override final
Returns "name" of operator (e.g., 'E1')
Definition hfs.hpp:267
hfs(int in_k, double GQ, double rN_au, const Grid &rgrid, const RadialFunction &hfs_F=Hyperfine::pointlike_F(), bool MHzQ=true)
Constructs hyperfine operator of multipolarity k.
Definition hfs.hpp:247
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:272
double angularCff(int, int) const override final
Angular factor for f_a*f_b part of radial integral.
Definition hfs.hpp:278
l (orbital angular momentum) operator
Definition jls.hpp:27
Holds grid, including type + Jacobian (dr/du)
Definition Grid.hpp:31
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
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:682
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 Ck_kk(int k, int ka, int kb)
Reduced (relativistic) angular ME: <ka||C^k||kb> [takes k and kappa].
Definition Wigner369j.hpp:306
double convert_RME_to_HFSconstant_2J(int k, int tja, int tjb)
Converts reduced matrix element to A/B coeficients (takes k, 2J, 2J)
Definition hfs.cpp:169
RadialFunction doublyOddSP_F(double mut, double It, double mu1, double I1, double l1, int gl1, double I2, double l2, bool print)
Volotka single-particle model for doubly-odd nuclei.
Definition hfs.cpp:150
std::vector< double > tk_radial(int k, double rN, const std::vector< double > &r, const RadialFunction &hfs_F)
Definition hfs.cpp:14
double convert_RME_to_HFSconstant(int k, int ka, int kb)
Converts reduced matrix element to A/B coeficients (takes k, kappa, kappa)
Definition hfs.cpp:204
RadialFunction pointlike_F()
Pointlike F(r): 1.
Definition hfs.cpp:38
RadialFunction sphericalBall_F(int k)
Spherical ball model for F(r,rN) [default]. Uniformly distributed point k-poles.
Definition hfs.cpp:26
RadialFunction sphericalShell_F()
Spherical shell F(r): 0 for r<rN, 1 for r>rN.
Definition hfs.cpp:33
RadialFunction uSP(double mu, double I_nuc, double l_pn, int gl, double n, double R, bool u_option, bool print)
Elizarov single-particle magnetisation model [extended Volotka].
Definition hfs.cpp:81
std::function< double(double r, double r_Nuc)> RadialFunction
Type for radial function F(r,rN) (type alias to save typing)
Definition hfs.hpp:22
RadialFunction VolotkaSP_F(double mu, double I_nuc, double l_pn, int gl, bool print)
Volotka single-particle nuclear model: F(r,rN)
Definition hfs.cpp:44
Dirac Operators: General + derived.
Definition GenerateOperator.cpp:3
Parity
Parity of operator.
Definition TensorOperator.hpp:18
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
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:140
bool ci_compare(std::string_view s1, std::string_view s2)
Case insensitive string compare. Essentially: LowerCase(s1)==LowerCase(s2)
Definition String.hpp:132