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,
230 using RadialFunction = std::function<double(
double,
double)>;
248 hfs(
int in_k,
double GQ,
double rN_au,
const Grid &rgrid,
251 Hyperfine::tk_radial(in_k, rN_au, rgrid.r(), hfs_F)),
253 magnetic(k % 2 != 0),
254 cfg(magnetic ? 1.0 : 0.0),
255 cff(magnetic ? 0.0 : 1.0),
258 const auto power = magnetic ? (k - 1) / 2 : k / 2;
264 std::pow(PhysConst::barn_au, power);
265 m_unit = mMHzQ ? unit_au * PhysConst::Hartree_MHz : 1.0;
268 std::string
name() const override final {
269 return "hfs" + std::to_string(k) +
"";
271 std::string
units() const override final {
return mMHzQ ?
"MHz" :
"au"; }
273 double angularF(
const int ka,
const int kb)
const override final {
274 return magnetic ? -double(ka + kb) / double(k) *
279 double angularCff(
int,
int)
const override final {
return cff; }
280 double angularCgg(
int,
int)
const override final {
return cff; }
281 double angularCfg(
int,
int)
const override final {
return cfg; }
282 double angularCgf(
int,
int)
const override final {
return cfg; }
295inline std::unique_ptr<DiracOperator::TensorOperator>
300 {{
"",
"Most following will be taken from the default nucleus if "
301 "not explicitely given"},
302 {
"mu",
"Magnetic moment in mu_N"},
303 {
"Q",
"Nuclear quadrupole moment, in barns. Also used as overall "
304 "constant for any higher-order moments [1.0]"},
305 {
"k",
"Multipolarity. 1=mag. dipole, 2=elec. quad, etc. [1]"},
307 "nuclear (magnetic) rms radius, in Fermi (fm) (defult is charge rms)"},
308 {
"units",
"Units for output (only for k=1,k=2). MHz or au. For MHz, "
309 "assumes nuclear moments g/Q are in mu_N*barns^p. For atomic "
310 "units, best to set g=Q=1 to get raw t^k matrix elements [MHz]"},
311 {
"F",
"F(r): Nuclear moment distribution: ball, point, shell, "
312 "SingleParticle, or doublyOddSP [ball]"},
313 {
"F(r)",
"Obselete; use 'F' from now - will be removed"},
314 {
"nuc_mag",
"Obselete; use 'F' from now - will be removed"},
315 {
"printF",
"Writes F(r) to a text file [false]"},
316 {
"print",
"Write F(r) info to screen [true]"},
317 {
"",
"The following are only for F=SingleParticle or doublyOddSP"},
318 {
"I",
"Nuclear spin. Taken from nucleus"},
319 {
"parity",
"Nulcear parity: +/-1"},
320 {
"l",
"l for unpaired nucleon (automatically derived from I and "
321 "parity; best to leave as default)"},
322 {
"gl",
"=1 for proton, =0 for neutron"},
323 {
"",
"The following are only used if F=doublyOddSP"},
324 {
"mu1",
"mag moment of 'first' unpaired nucleon"},
325 {
"gl1",
"gl of 'first' unpaired nucleon"},
326 {
"l1",
"l of 'first' unpaired nucleon"},
327 {
"l2",
"l of 'second' unpaired nucleon"},
328 {
"I1",
"total spin (J) of 'first' unpaired nucleon"},
329 {
"I2",
"total spin (J) of 'second' unpaired nucleon"},
330 {
"",
"The following are only for u(r) function"},
331 {
"u",
"u1 or u2 : u1(r) = (R-r)^n, u2(r) = r^n [u1]"},
332 {
"n",
"n that appears above. Should be between 0 and 2 [0]"}});
339 auto mu = input.
get(
"mu", isotope.mu ? *isotope.mu : 1.0);
340 auto I_nuc = input.
get(
"I", isotope.I_N ? *isotope.I_N : 1.0);
341 const auto print = input.
get(
"print",
true);
342 const auto k = input.
get(
"k", 1);
348 fmt2::styled_print(fg(fmt::color::red),
"\nError 246:\n");
349 std::cout <<
"In hyperfine: invalid K=" << k <<
"! meaningless results\n";
351 if (I_nuc <= 0 && k == 1) {
352 fmt2::styled_print(fg(fmt::color::orange),
"\nWarning 253:\n");
353 std::cout <<
"In hyperfine: invalid I_nuc=" << I_nuc
354 <<
"! meaningless results\nSetting I=1\n";
357 if (mu == 0.0 && k == 1) {
358 fmt2::styled_print(fg(fmt::color::orange),
"\nWarning 352:\n");
359 std::cout <<
"Setting mu=1\n";
363 const auto g_or_Q = (k == 1) ? (mu / I_nuc) :
364 (k == 2) ? input.
get(
"Q", isotope.q ? *isotope.q : 1.0) :
367 enum class DistroType {
377 std::string default_distribution =
"ball";
382 input.
get<std::string>(
"F", default_distribution) :
383 input.has_option(
"nuc_mag") ?
384 input.get<std::string>(
"nuc_mag", default_distribution) :
385 input.get<std::string>(
"F(r)", default_distribution);
387 const auto distro_type =
396 if (distro_type == DistroType::Error) {
397 fmt2::styled_print(fg(fmt::color::red),
"\nError 271:\n");
398 std::cout <<
"\nIn hyperfine. Unkown F(r) - " << Fr_str <<
"\n";
399 std::cout <<
"Defaulting to pointlike!\n";
403 distro_type == DistroType::point ? 0.0 : input.
get(
"rrms", nuc.r_rms());
404 const auto r_nucfm = std::sqrt(5.0 / 3) * r_rmsfm;
405 const auto r_nucau = r_nucfm / PhysConst::aB_fm;
408 std::cout <<
"\nHyperfine structure: " << wf.
atom() <<
"\n";
409 std::cout <<
"K=" << k <<
" ("
410 << (k == 1 ?
"magnetic dipole" :
411 k == 2 ?
"electric quadrupole" :
412 k % 2 == 0 ?
"electric multipole" :
413 "magnetic multipole")
415 std::cout <<
"Using " << Fr_str <<
" nuclear distro for F(r)\n"
416 <<
"w/ r_N = " << r_nucfm <<
"fm = " << r_nucau
417 <<
"au (r_rms=" << r_rmsfm <<
"fm)\n";
418 std::cout <<
"Points inside nucleus: " << wf.
grid().
getIndex(r_nucau)
421 std::cout <<
"mu = " << mu <<
", I = " << I_nuc <<
", g = " << g_or_Q
424 std::cout <<
"Q = " << g_or_Q <<
"\n";
430 if (distro_type == DistroType::ball) {
432 }
else if (distro_type == DistroType::shell) {
434 }
else if (distro_type == DistroType::SingleParticle) {
435 const auto pi = input.
get(
"parity", isotope.parity ? *isotope.parity : 0);
436 const auto l_tmp = int(I_nuc + 0.5 + 0.0001);
437 auto l = ((l_tmp % 2 == 0) == (pi == 1)) ? l_tmp : l_tmp - 1;
438 l = input.
get(
"l",
l);
439 const auto gl_default = wf.
Znuc() % 2 == 0 ? 0 : 1;
440 const auto gl = input.
get<
int>(
"gl", gl_default);
442 std::cout <<
"Single-Particle (Volotka formula) for unpaired";
444 std::cout <<
" proton ";
446 std::cout <<
" neturon ";
448 std::cout <<
" gl=" << gl <<
"??? program will run, but prob wrong!\n";
449 std::cout <<
"with l=" <<
l <<
" (pi=" << pi <<
")\n";
452 }
else if (distro_type == DistroType::spu) {
453 const auto pi = input.
get(
"parity", isotope.parity ? *isotope.parity : 0);
454 const auto u_func = input.
get(
"u", std::string{
"u1"});
455 const bool u_option = u_func == std::string{
"u1"};
456 const auto n = input.
get(
"n", 0.0);
457 const auto l_tmp = int(I_nuc + 0.5 + 0.0001);
458 auto l = ((l_tmp % 2 == 0) == (pi == 1)) ? l_tmp : l_tmp - 1;
459 l = input.
get(
"l",
l);
460 const auto gl_default = wf.
Znuc() % 2 == 0 ? 0 : 1;
461 const auto gl = input.
get<
int>(
"gl", gl_default);
463 std::cout <<
"Single-Particle (Volotka formula) with u(r) for unpaired";
465 std::cout <<
" proton ";
467 std::cout <<
" neturon ";
469 std::cout <<
" gl=" << gl <<
"??? program will run, but prob wrong!\n";
470 std::cout <<
"with l=" <<
l <<
" (pi=" << pi <<
")\n";
473 }
else if (distro_type == DistroType::doublyOddSP) {
474 const auto mu1 = input.
get<
double>(
"mu1", 1.0);
475 const auto gl1 = input.
get<
int>(
"gl1", -1);
476 if (gl1 != 0 && gl1 != 1) {
477 fmt2::styled_print(fg(fmt::color::red),
"\nError 324:\n");
478 std::cout <<
"In " << input.name() <<
" " << Fr_str
479 <<
"; have gl1=" << gl1 <<
" but need 1 or 0\n";
482 const auto l1 = input.
get<
double>(
"l1", -1.0);
483 const auto l2 = input.
get<
double>(
"l2", -1.0);
484 const auto I1 = input.
get<
double>(
"I1", -1.0);
485 const auto I2 = input.
get<
double>(
"I2", -1.0);
491 if (input.
get<
bool>(
"printF",
false)) {
492 std::ofstream of(wf.
identity() +
"_" + Fr_str +
".txt");
494 for (
auto r : wf.grid()) {
495 of << r * PhysConst::aB_fm <<
" "
496 << Fr(r * PhysConst::aB_fm, r_nucau * PhysConst::aB_fm) <<
"\n";
500 return std::make_unique<hfs>(k, g_or_Q, r_nucau, wf.
grid(), Fr, use_MHz);
Speacial operator: 0.
Definition TensorOperator.hpp:362
General operator (virtual base class); operators derive from this.
Definition TensorOperator.hpp:66
Generalised hyperfine-structure operator, including relevant nuclear moment.
Definition hfs.hpp:229
double angularCgg(int, int) const override final
Angular factor for g_a*g_b part of radial integral.
Definition hfs.hpp:280
double angularCgf(int, int) const override final
Angular factor for g_a*f_b part of radial integral.
Definition hfs.hpp:282
double angularCfg(int, int) const override final
Angular factor for f_a*g_b part of radial integral.
Definition hfs.hpp:281
std::string units() const override final
Returns units of operator (usually au, may be MHz, etc.)
Definition hfs.hpp:271
std::string name() const override final
Returns "name" of operator (e.g., 'E1')
Definition hfs.hpp:268
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:248
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:273
double angularCff(int, int) const override final
Angular factor for f_a*f_b part of radial integral.
Definition hfs.hpp:279
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:372
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:203
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:19
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