QMCPACK
MagnetizationDensity.cpp
Go to the documentation of this file.
1 //////////////////////////////////////////////////////////////////////////////////////
2 // This file is distributed under the University of Illinois/NCSA Open Source License.
3 // See LICENSE file in top directory for details.
4 //
5 // Copyright (c) 2023 QMCPACK developers.
6 //
7 // File developed by: Raymond Clay, rclay@sandia.gov, Sandia National Laboratories
8 //
9 // File created by: Raymond Clay, rclay@sandia.gov, Sandia National Laboratories
10 //////////////////////////////////////////////////////////////////////////////////////
13 
14 namespace qmcplusplus
15 {
17  : OperatorEstBase(DataLocality::crowd), input_(minput), lattice_(lat)
18 {
19  my_name_ = "MagnetizationDensity";
20  //Pull consistent corner, grids, etc., from already inititalized input.
21  //DerivedParameters does the sanity checks and consistent initialization of these variables.
22  MagnetizationDensityInput::DerivedParameters derived = minput.calculateDerivedParameters(lat);
23 
24  //If DerivedParameters does its job, these are all correct, so we pull them and keep them in the class.
25  npoints_ = derived.npoints;
26  grid_ = derived.grid;
27  gdims_ = derived.gdims;
28 
29  rcorner_ = derived.corner;
31 
34 
35  //Resize the data arrays.
36  data_.resize(getFullDataSize(), 0);
37 }
38 
40  : MagnetizationDensity(magdens)
41 {
42  my_name_ = "MagnetizationDensity";
43  data_locality_ = dl;
44 }
46 
48 
50  const RefVector<ParticleSet>& psets,
51  const RefVector<TrialWaveFunction>& wfns,
52  const RefVector<QMCHamiltonian>& hams,
54 {
55  for (int iw = 0; iw < walkers.size(); ++iw)
56  {
57  MCPWalker& walker = walkers[iw];
58  ParticleSet& pset = psets[iw];
59  TrialWaveFunction& wfn = wfns[iw];
60 
61  QMCT::RealType weight = walker.Weight;
62  std::vector<Value> sxgrid(nsamples_, 0.0);
63  std::vector<Value> sygrid(nsamples_, 0.0);
64  std::vector<Value> szgrid(nsamples_, 0.0);
65 
66  //Temporary variables to hold the integrated sx, sy, sz estimates.
67  //These are overwritten as needed in the loop over particles.
68  Value sx(0.0);
69  Value sy(0.0);
70  Value sz(0.0);
71 
72  const int np = pset.getTotalNum();
73  assert(weight >= 0);
74 
75  walkers_weight_ += weight;
76  for (int p = 0; p < np; ++p)
77  {
78  size_t sxindex = computeBin(pset.R[p], 0);
79  generateSpinIntegrand(pset, wfn, p, sxgrid, sygrid, szgrid);
80  sx = integrateMagnetizationDensity(sxgrid);
81  sy = integrateMagnetizationDensity(sygrid);
82  sz = integrateMagnetizationDensity(szgrid);
83 
84  data_[sxindex] += std::real(sx * weight);
85  data_[sxindex + 1] += std::real(sy * weight);
86  data_[sxindex + 2] += std::real(sz * weight);
87  }
88  }
89 };
90 
91 void MagnetizationDensity::collect(const RefVector<OperatorEstBase>& type_erased_operator_estimators)
92 {
94  {
95  OperatorEstBase::collect(type_erased_operator_estimators);
96  }
97  else
98  {
99  throw std::runtime_error("You cannot call collect on MagnetizationDensity with this DataLocality");
100  }
101 }
102 
103 size_t MagnetizationDensity::computeBin(const QMCT::PosType& r, const unsigned int component) const
104 {
105  assert(component < QMCT::DIM);
107  size_t point = 0; //This establishes the real space grid point.
108  for (int d = 0; d < QMCT::DIM; ++d)
109  point += gdims_[d] * ((int)(grid_[d] * (u[d] - std::floor(u[d])))); //periodic only
110 
111  //We now have the real space grid point. For each grid point, we store sx[point],sy[point],sz[point].
112  //Thus, the actual position in array is DIM*point+component.
113  return DIM * point + component;
114 }
115 
116 std::unique_ptr<OperatorEstBase> MagnetizationDensity::spawnCrowdClone() const
117 {
118  std::size_t data_size = data_.size();
119  auto spawn_data_locality = data_locality_;
120 
121  //Everyone else has this attempt to set up a non-implemented memory saving optimization.
122  //We won't rock the boat.
124  {
125  // This is just a stub until a memory saving optimization is deemed necessary
126  spawn_data_locality = DataLocality::queue;
127  data_size = 0;
128  throw std::runtime_error("There is no memory savings implementation for MagnetizationDensity");
129  }
130 
131  UPtr<MagnetizationDensity> spawn(std::make_unique<MagnetizationDensity>(*this, spawn_data_locality));
132  spawn->get_data().resize(data_size);
133  return spawn;
134 };
135 
137  TrialWaveFunction& psi_target,
138  const int iat,
139  std::vector<Value>& sxgrid,
140  std::vector<Value>& sygrid,
141  std::vector<Value>& szgrid)
142 
143 {
144  std::vector<Real> sgrid(nsamples_);
145  std::vector<Real> ds(nsamples_, 0.0);
146  std::vector<Value> ratios(nsamples_, 0);
147  generateGrid(sgrid);
148  for (int samp = 0; samp < nsamples_; samp++)
149  ds[samp] = sgrid[samp] - pset_target.spins[iat];
150 
152  std::vector<Position> dV(nsamples_, 0);
153  vp.makeMovesWithSpin(pset_target, iat, dV, ds);
154  psi_target.evaluateRatios(vp, ratios);
155 
156  const std::complex<Real> eye(0, 1.0);
157 
158  for (int samp = 0; samp < nsamples_; samp++)
159  {
160  sxgrid[samp] = std::real(Real(2.0) * Real(std::cos(sgrid[samp] + pset_target.spins[iat])) * ratios[samp]);
161  sygrid[samp] = std::real(Real(2.0) * Real(std::sin(sgrid[samp] + pset_target.spins[iat])) * ratios[samp]);
162  szgrid[samp] = std::real(Real(-2.0) * eye * std::sin(ds[samp]) * ratios[samp]);
163  }
164 }
165 
166 void MagnetizationDensity::generateUniformGrid(std::vector<Real>& sgrid, const Real start, const Real stop) const
167 {
168  size_t num_gridpoints = sgrid.size();
169  Real delta = (stop - start) / (num_gridpoints - 1.0);
170  for (int i = 0; i < num_gridpoints; i++)
171  sgrid[i] = start + i * delta;
172 }
173 
174 void MagnetizationDensity::generateGrid(std::vector<Real>& sgrid) const
175 {
176  sgrid.resize(nsamples_);
177  Real start = 0.0;
178  Real stop = 2 * M_PI;
179 
180  switch (integrator_)
181  {
183  generateUniformGrid(sgrid, start, stop);
184  break;
186  throw std::runtime_error("Monte Carlo sampling not implemented yet");
187  break;
188  }
189 }
190 
192 {
193  std::vector<size_t> my_indexes;
194 
195  std::vector<int> ng(1, getFullDataSize());
196 
197  hdf_path hdf_name{my_name_};
198  h5desc_.emplace_back(hdf_name);
199  auto& oh = h5desc_.back();
200  oh.set_dimensions(ng, 0);
201 }
202 
204  Real gridDx) const
205 {
206  Value sint(0.0);
207  int gridsize = fgrid.size();
208  for (int is = 1; is < gridsize - 1; is += 2)
209  sint += Real(4. / 3.) * gridDx * fgrid[is];
210 
211  for (int is = 2; is < gridsize - 1; is += 2)
212  sint += Real(2. / 3.) * gridDx * fgrid[is];
213 
214  sint += Real(1. / 3.) * gridDx * fgrid[0];
215  sint += Real(1. / 3.) * gridDx * fgrid[gridsize - 1];
216 
217  return sint;
218 }
219 
221 {
222  Real start = 0.0;
223  Real stop = 2 * M_PI;
224  Real deltax = (stop - start) / (nsamples_ - 1.0);
225  Value val = 0.0;
226  switch (integrator_)
227  {
229  //There's a normalizing 2pi factor in this integral. Take care of it here.
230  val = integrateBySimpsonsRule(fgrid, deltax) / Real(2.0 * M_PI);
231 
232  break;
234  //Integrand has form that can be monte carlo sampled. This means the 2*PI
235  //is taken care of if the integrand is uniformly sampled between [0,2PI),
236  //which it is. The following is just an average.
237  val = std::accumulate(fgrid.begin(), fgrid.end(), Value(0));
238  val /= Real(nsamples_);
239  break;
240  }
241  return val;
242 }
243 
244 void MagnetizationDensity::generateRandomGrid(std::vector<Real>& sgrid,
246  Real start,
247  Real stop) const
248 {
249  size_t npoints = sgrid.size();
250  for (int i = 0; i < npoints; i++)
251  sgrid[i] = (stop - start) * rng();
252 }
253 
254 } //namespace qmcplusplus
a class that defines a supercell in D-dimensional Euclean space.
SingleParticlePos Center
Center of the cell sum(Rv[i])/2.
QMCTraits::RealType real
size_t computeBin(const Position &r, const unsigned int component) const
For a given spatial position r and spin component s, this returns the bin for accumulating the observ...
helper functions for EinsplineSetBuilder
Definition: Configuration.h:43
QTBase::RealType RealType
Definition: Configuration.h:58
std::vector< ObservableHelper > h5desc_
MakeReturn< UnaryNode< FnSin, typename CreateLeaf< Vector< T1, C1 > >::Leaf_t > >::Expression_t sin(const Vector< T1, C1 > &l)
A ParticleSet that handles virtual moves of a selected particle of a given physical ParticleSet Virtu...
void generateSpinIntegrand(ParticleSet &pset, TrialWaveFunction &wfn, const int iat, std::vector< Value > &sx, std::vector< Value > &sy, std::vector< Value > &sz)
Generates the spin integrand (s&#39;)/Psi(s)* s | {} | s&#39; for a specific electron iat.
class to handle hdf file
Definition: hdf_archive.h:51
MagnetizationDensity(MagnetizationDensityInput &&min, const Lattice &lattice)
const char walkers[]
Definition: HDFVersion.h:36
DataLocality data_locality_
locality for accumulation of estimator data.
Value integrateMagnetizationDensity(const std::vector< Value > &fgrid) const
This is a convenience function that handles ^{2} dx f(x).
void collect(const RefVector< OperatorEstBase > &operator_estimators) override
Reduce estimator result data from crowds to rank.
void registerOperatorEstimator(hdf_archive &file) override
Specialized paritlce class for atomistic simulations.
Definition: ParticleSet.h:55
QMCT::FullPrecRealType walkers_weight_
Value integrateBySimpsonsRule(const std::vector< Value > &fgrid, Real gridDx) const
Implementation of Simpson&#39;s 1/3 rule to integrate a function on a uniform grid.
MakeReturn< UnaryNode< FnCos, typename CreateLeaf< Vector< T1, C1 > >::Leaf_t > >::Expression_t cos(const Vector< T1, C1 > &l)
void generateGrid(std::vector< Real > &sgrid) const
Convenience function to generate a grid between 0 and 2pi, consistent with nsamples_ and integration ...
An abstract class for gridded estimators.
void generateUniformGrid(std::vector< Real > &sgrid, const Real start, const Real stop) const
Generate a uniform grid between [start,stop] for numerical quadrature.
SingleParticlePos toUnit(const TinyVector< T1, D > &r) const
Convert a cartesian vector to a unit vector.
std::unique_ptr< OperatorEstBase > spawnCrowdClone() const override
std::unique_ptr< T > UPtr
size_t getFullDataSize()
This returns the total size of data object required for this estimator.
std::vector< std::reference_wrapper< T > > RefVector
void accumulate(const RefVector< MCPWalker > &walkers, const RefVector< ParticleSet > &psets, const RefVector< TrialWaveFunction > &wfns, const RefVector< QMCHamiltonian > &hams, RandomBase< FullPrecReal > &rng) override
Class to represent a many-body trial wave function.
void set_dimensions(const std::vector< int > &dims, int first)
set the shape of this observable
DataLocality
data locality with respect to walker buffer
Definition: DataLocality.h:19
void generateRandomGrid(std::vector< Real > &sgrid, RandomBase< FullPrecReal > &rng, Real start, Real stop) const
Generate random grid between [start,stop] for MC integration.
Magnetization density estimator for non-collinear spin calculations.
A container class to represent a walker.
Definition: Walker.h:49
void evaluateRatios(const VirtualParticleSet &VP, std::vector< ValueType > &ratios, ComputeType ct=ComputeType::ALL)
compulte multiple ratios to handle non-local moves and other virtual moves
ObservableHelper oh
virtual void collect(const RefVector< OperatorEstBase > &oebs)
Reduce estimator result data from crowds to rank.
MakeReturn< UnaryNode< FnFloor, typename CreateLeaf< Vector< T1, C1 > >::Leaf_t > >::Expression_t floor(const Vector< T1, C1 > &l)
std::string my_name_
name of this object – only used for debugging and h5 output