ampsci
High-precision calculations for one- and two-valence atomic systems
FieldShift.hpp
1#pragma once
2#include "DiracOperator/TensorOperator.hpp"
3#include "IO/InputBlock.hpp"
4#include "Maths/NumCalc_quadIntegrate.hpp"
5#include "Physics/PhysConst_constants.hpp"
6#include "Potentials/NuclearPotentials.hpp"
7#include "Wavefunction/Wavefunction.hpp"
8#include "qip/Vector.hpp" // qip::overloads
9
10namespace DiracOperator {
11
12/*! @brief Field shift operator: dV = V(r, nuc2) - V(r, nuc1)
13
14 @details
15 Computes the change in nuclear potential between two nuclei differing in
16 size or shape. Also stores \f$\delta\langle r^2\rangle\f$ and
17 \f$\delta\langle r^4\rangle\f$ (in fm^2 and fm^4).
18*/
19class fieldshift final : public ScalarOperator {
20
21private:
22 double m_dr2{-1};
23 double m_dr4{-1};
24
25public:
26 fieldshift(const Grid &rgrid, const Nuclear::Nucleus &nuc1,
27 const Nuclear::Nucleus &nuc2, double scale = 1.0)
29 Parity::even, scale,
30 qip::overloads::operator-(Nuclear::formPotential(nuc2, rgrid.r()),
31 Nuclear::formPotential(nuc1, rgrid.r()))),
32 m_dr2(nuc2.r_rms() * nuc2.r_rms() - nuc1.r_rms() * nuc1.r_rms()),
33 m_dr4(r4(rgrid, nuc2) - r4(rgrid, nuc1)) {}
34
35 std::string name() const override { return std::string("Field shift"); }
36 std::string units() const override { return "au"; }
37
38 //! delta <r^2> (in fm^2)
39 double dr2() const { return m_dr2; }
40 //! delta <r^4> (in fm^4)
41 double dr4() const { return m_dr4; }
42
43 //! Helper function: calculates <r^4> (nuclear) in fm^4
44 static double r4(const Grid &grid, const Nuclear::Nucleus &nuc) {
45
46 // <r^4> = \int_0^\infty [\rho(r) r^4] 4 \pi r^2 dr / Z
47 // Z is from normalisation of rho:
48 // \int_0^\infty [\rho(r) r^2] 4 \pi r^2 dr = Z
49 // by normalisation of nuclear charge density.
50 // Require four factors of aB to convert output to femtometres.
51
52 constexpr auto abfm4factor = 4.0 * M_PI * qip::pow<4>(PhysConst::aB_fm);
53 const auto rho = Nuclear::fermiNuclearDensity_tcN(
54 Nuclear::deformation_effective_t(nuc.c(), nuc.t(), nuc.beta()), nuc.c(),
55 nuc.z(), grid);
56 const auto rpow6 = grid.rpow(6);
57
58 return NumCalc::integrate(grid.du(), 0.0, 0.0, rpow6, rho, grid.drdu()) *
59 abfm4factor / nuc.z();
60 }
61
62 //! Helper function: calculates <r^2> (nuclear) in fm^2
63 static double r2(const Grid &grid, const Nuclear::Nucleus &nuc) {
64
65 constexpr auto abfm2factor = 4.0 * M_PI * qip::pow<2>(PhysConst::aB_fm);
66 const auto rho = Nuclear::fermiNuclearDensity_tcN(
67 Nuclear::deformation_effective_t(nuc.c(), nuc.t(), nuc.beta()), nuc.c(),
68 nuc.z(), grid);
69 const auto rpow4 = grid.rpow(4);
70
71 return NumCalc::integrate(grid.du(), 0.0, 0.0, rpow4, rho, grid.drdu()) *
72 abfm2factor / nuc.z();
73 }
74
75 static std::unique_ptr<TensorOperator> generate(const IO::InputBlock &input,
76 const Wavefunction &wf) {
77 input.check(
78 {{"", "Field shift operator."},
79 {"drrms",
80 "Change in nuclear rms charge radius (fm); must not be zero [0.01]"},
81 {"scale_factor", "Scale factor [1.0]"},
82 {"", "The following are normally not set:"},
83 {"dt", "Change in skin-thickness t (fm) [0.0]"},
84 {"dbeta", "Change in quadrupole deformation parameter, beta [0.0]"},
85 {"print", "Print details? [true]"}});
86 if (input.has_option("help"))
87 return nullptr;
88 const auto drrms = input.get("drrms", 0.01);
89 const auto scale = input.get("scale_factor", 1.0);
90 const auto dt = input.get("dt", 0.0);
91 const auto dbeta = input.get("dbeta", 0.0);
92 const auto print = input.get("print", true);
93 const auto &nuc0 = wf.nucleus();
94 auto nuc1 = nuc0;
95 nuc1.set_rrms(nuc1.r_rms() + drrms);
96 nuc1.t() = nuc0.t() + dt;
97 nuc1.beta() = nuc0.beta() + dbeta;
98 const auto vnuc1 = Nuclear::formPotential(nuc1, wf.grid().r());
99 auto h = std::make_unique<fieldshift>(wf.grid(), nuc0, nuc1, scale);
100 if (print) {
101 std::cout << "Field shift:\n"
102 << "Nuc1: " << nuc0 << "\n"
103 << "Nuc2: " << nuc1 << "\n"
104 << "delta<r^2> = " << h->dr2() << " fm^2\n"
105 << "delta<r^4> = " << h->dr4() << " fm^4\n";
106 }
107 return h;
108 }
109};
110
111} // namespace DiracOperator
Rank-0 (scalar) tensor operator; derives from TensorOperator with k=0.
Definition TensorOperator.hpp:561
Field shift operator: dV = V(r, nuc2) - V(r, nuc1)
Definition FieldShift.hpp:19
std::string name() const override
Returns "name" of operator (e.g., 'E1')
Definition FieldShift.hpp:35
double dr2() const
delta <r^2> (in fm^2)
Definition FieldShift.hpp:39
double dr4() const
delta <r^4> (in fm^4)
Definition FieldShift.hpp:41
std::string units() const override
Returns units of operator as a string (usually au, may be MHz, etc.)
Definition FieldShift.hpp:36
static double r4(const Grid &grid, const Nuclear::Nucleus &nuc)
Helper function: calculates <r^4> (nuclear) in fm^4.
Definition FieldShift.hpp:44
static double r2(const Grid &grid, const Nuclear::Nucleus &nuc)
Helper function: calculates <r^2> (nuclear) in fm^2.
Definition FieldShift.hpp:63
Non-uniform radial grid with Jacobian, suitable for atomic structure calculations.
Definition Grid.hpp:85
const std::vector< double > & r() const
Full grid vector r.
Definition Grid.hpp:131
std::vector< double > rpow(double k) const
Returns a vector of r^k for each grid point.
Definition Grid.cpp:120
auto du() const
Uniform step size du.
Definition Grid.hpp:124
const std::vector< double > & drdu() const
Full Jacobian vector dr/du.
Definition Grid.hpp:140
Holds a named list of key=value options and nested InputBlocks.
Definition InputBlock.hpp:154
bool check(std::initializer_list< std::string > blocks, const std::vector< std::pair< std::string, std::string > > &list, bool print=false) const
Validates options and sub-blocks against an allowed list.
Definition InputBlock.hpp:649
bool has_option(std::string_view key) const
Returns true if key is present in this block's option list, even if unset.
Definition InputBlock.hpp:247
T get(std::string_view key, T default_value) const
Returns the value of key, or default_value if not found.
Definition InputBlock.hpp:471
Stores set of nuclear parameters (all radii in fm)
Definition NuclearPotentials.hpp:20
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
const Nuclear::Nucleus & nucleus() const
Returns Nuclear::nucleus object (contains nuc. parameters)
Definition Wavefunction.hpp:97
Dirac operators: TensorOperator base class and derived implementations for single-particle (one-body)...
Definition GenerateOperator.cpp:6
std::vector< double > formPotential(const Nucleus &nuc, const std::vector< double > &r)
Calls one of the above, depending on params. Fills V(r), given r.
Definition NuclearPotentials.cpp:354
std::vector< double > fermiNuclearDensity_tcN(double t, double c, double Z_norm, const Grid &grid)
Fermi charge distribution, rho(r) - normalised to Z_norm.
Definition NuclearPotentials.cpp:319
double deformation_effective_t(double c, double t, double beta)
Calculates effective skin thickness due to quadrupole deformation [See Eq. 8 of https://doi....
Definition NuclearData.cpp:96
double integrate(const double dt, std::size_t beg, std::size_t end, const C &f1, const Args &...rest)
Quadrature integration of one or more vectors over a regular grid in t.
Definition NumCalc_quadIntegrate.hpp:53
void scale(std::vector< T > *vec, T x)
In-place scalar multiplication of a vector; types must match.
Definition Vector.hpp:227