ampsci
c++ program for high-precision atomic structure calculations of single-valence 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/NuclearPotentials.hpp"
6 #include "Physics/PhysConst_constants.hpp"
7 #include "Wavefunction/Wavefunction.hpp"
8 #include "qip/Vector.hpp" // qip::overloads
9 
10 namespace DiracOperator {
11 
13 
15 class fieldshift final : public ScalarOperator {
16 
17 private:
18  double m_dr2{-1};
19  double m_dr4{-1};
20 
21 public:
22  fieldshift(const Grid &rgrid, const Nuclear::Nucleus &nuc1,
23  const Nuclear::Nucleus &nuc2, double scale = 1.0)
25  Parity::even, scale,
26  qip::overloads::operator-(Nuclear::formPotential(nuc2, rgrid.r()),
27  Nuclear::formPotential(nuc1, rgrid.r()))),
28  m_dr2(nuc2.r_rms() * nuc2.r_rms() - nuc1.r_rms() * nuc1.r_rms()),
29  m_dr4(r4(rgrid, nuc2) - r4(rgrid, nuc1)) {}
30 
31  std::string name() const override { return std::string("Field shift"); }
32  std::string units() const override { return "au"; }
33 
35  double dr2() const { return m_dr2; }
37  double dr4() const { return m_dr4; }
38 
40  static double r4(const Grid &grid, const Nuclear::Nucleus &nuc) {
41 
42  // <r^4> = \int_0^\infty [\rho(r) r^4] 4 \pi r^2 dr / Z
43  // Z is from normalisation of rho:
44  // \int_0^\infty [\rho(r) r^2] 4 \pi r^2 dr = Z
45  // by normalisation of nuclear charge density.
46  // Require four factors of aB to convert output to femtometres.
47 
48  constexpr auto abfm4factor = 4.0 * M_PI * qip::pow<4>(PhysConst::aB_fm);
49  const auto rho = Nuclear::fermiNuclearDensity_tcN(
50  Nuclear::deformation_effective_t(nuc.c(), nuc.t(), nuc.beta()), nuc.c(),
51  nuc.z(), grid);
52  const auto rpow6 = grid.rpow(6);
53 
54  return NumCalc::integrate(grid.du(), 0.0, 0.0, rpow6, rho, grid.drdu()) *
55  abfm4factor / nuc.z();
56  }
57 
59  static double r2(const Grid &grid, const Nuclear::Nucleus &nuc) {
60 
61  constexpr auto abfm2factor = 4.0 * M_PI * qip::pow<2>(PhysConst::aB_fm);
62  const auto rho = Nuclear::fermiNuclearDensity_tcN(
63  Nuclear::deformation_effective_t(nuc.c(), nuc.t(), nuc.beta()), nuc.c(),
64  nuc.z(), grid);
65  const auto rpow4 = grid.rpow(4);
66 
67  return NumCalc::integrate(grid.du(), 0.0, 0.0, rpow4, rho, grid.drdu()) *
68  abfm2factor / nuc.z();
69  }
70 };
71 
72 inline std::unique_ptr<DiracOperator::TensorOperator>
73 generate_fieldshift(const IO::InputBlock &input, const Wavefunction &wf) {
74  using namespace DiracOperator;
75  input.check(
76  {{"", "Field shift operator."},
77  {"drrms",
78  "Change in nuclear rms charge radius (fm); must not be zero [0.01]"},
79  {"scale_factor", "Scale factor [1.0]"},
80  {"", "The following are normally not set:"},
81  {"dt", "Change in skin-thickness t (fm) [0.0]"},
82  {"dbeta", "Change in quadrupole deformation parameter, beta [0.0]"},
83  {"print", "Print details? [true]"}});
84  if (input.has_option("help")) {
85  return nullptr;
86  }
87 
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 
94  const auto &nuc0 = wf.nucleus();
95 
96  // Update parameters for "2nd" nucleus:
97  auto nuc1 = nuc0;
98  nuc1.set_rrms(nuc1.r_rms() + drrms);
99  nuc1.t() = nuc0.t() + dt;
100  nuc1.beta() = nuc0.beta() + dbeta;
101  const auto vnuc1 = Nuclear::formPotential(nuc1, wf.grid().r());
102 
103  auto h = std::make_unique<fieldshift>(wf.grid(), nuc0, nuc1, scale);
104 
105  if (print) {
106  std::cout << "Field shift:\n"
107  << "Nuc1: " << nuc0 << "\n"
108  << "Nuc2: " << nuc1 << "\n"
109  << "delta<r^2> = " << h->dr2() << " fm^2\n"
110  << "delta<r^4> = " << h->dr4() << " fm^4\n";
111  }
112 
113  return h;
114 }
115 
116 } // namespace DiracOperator
Speacial case for scalar operator.
Definition: TensorOperator.hpp:233
void scale(double lambda)
Permanently re-scales the operator by constant, lambda.
Definition: TensorOperator.cpp:84
Field shift operator, (e.g.) dV = V(r+dr) - V(r)
Definition: FieldShift.hpp:15
std::string name() const override
Returns "name" of operator (e.g., 'E1')
Definition: FieldShift.hpp:31
double dr2() const
\delta <r^2> (in fm^2)
Definition: FieldShift.hpp:35
double dr4() const
\delta <r^4> (in fm^2)
Definition: FieldShift.hpp:37
std::string units() const override
Returns units of operator (usually au, may be MHz, etc.)
Definition: FieldShift.hpp:32
static double r4(const Grid &grid, const Nuclear::Nucleus &nuc)
Helper function: calculates <r^4> (nuclear) in fm^4.
Definition: FieldShift.hpp:40
static double r2(const Grid &grid, const Nuclear::Nucleus &nuc)
Helper function: calculates <r^2> (nuclear) in fm^2.
Definition: FieldShift.hpp:59
Holds grid, including type + Jacobian (dr/du)
Definition: Grid.hpp:31
std::vector< double > rpow(double k) const
Calculates+returns vector of 1/r.
Definition: Grid.cpp:120
auto du() const
Linear step size dr = (dr/dr)*du.
Definition: Grid.hpp:68
const std::vector< double > & drdu() const
Jacobian (dr/du)[i].
Definition: Grid.hpp:80
const std::vector< double > & r() const
Grid points, r.
Definition: Grid.hpp:75
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 set of nuclear parameters (all radii in fm)
Definition: NuclearPotentials.hpp:20
Stores Wavefunction (set of valence orbitals, grid, HF etc.)
Definition: Wavefunction.hpp:36
const Grid & grid() const
Returns a const reference to the radial grid.
Definition: Wavefunction.hpp:81
const Nuclear::Nucleus & nucleus() const
Returns Nuclear::nucleus object (contains nuc. parameters)
Definition: Wavefunction.hpp:96
Dirac Operators: General + derived.
Definition: GenerateOperator.cpp:12
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:358
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:322
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
void scale(std::vector< T > *vec, T x)
In-place scalar multiplication of std::vector - types must match.
Definition: Vector.hpp:210