34 template<
typename REAL>
38 const bool is_periodic)
39 : NESpaceGrid(sgi, points, 0, nvalues, is_periodic)
42 template<
typename REAL>
47 const bool is_periodic)
48 : input_(sgi), ndparticles_(ndp), is_periodic_(is_periodic), points_(points), nvalues_per_domain_(nvalues)
50 bool init_success = initializeCoordSystem();
52 throw std::runtime_error(
"NESpaceGrid initialization failed");
55 template<
typename REAL>
58 ParticlePos& static_particle_positions,
62 const bool is_periodic)
63 : input_(sgi), ndparticles_(ndp), is_periodic_(is_periodic), points_(points), nvalues_per_domain_(nvalues)
65 bool init_success = initializeCoordSystem();
67 throw std::runtime_error(
"NESpaceGrid initialization failed");
70 template<
typename REAL>
74 bool init_success =
false;
75 switch (input_.get_coord_form())
77 case (CoordForm::CARTESIAN):
78 init_success = initializeRectilinear(input_, points_);
80 case (CoordForm::CYLINDRICAL):
81 init_success = initializeCylindrical(input_, points_);
83 case (CoordForm::SPHERICAL):
84 init_success = initializeSpherical(input_, points_);
90 template<
typename REAL>
93 auto& axis_labels =
input.get_axis_labels();
94 auto& axis_p1s =
input.get_axis_p1s();
95 auto& axis_p2s =
input.get_axis_p2s();
96 auto& axis_scales =
input.get_axis_scales();
97 auto& axis_grids =
input.get_axis_grids();
100 for (
int iaxis = 0; iaxis <
OHMMS_DIM; ++iaxis)
102 Real frac = axis_scales[iaxis];
104 axes(d, iaxis) = frac * (points.at(axis_p1s[iaxis])[d] - points.at(axis_p2s[iaxis])[d]);
109 template<
typename REAL>
112 const std::string& origin_p1 =
input.get_origin_p1();
113 const std::string& origin_p2 =
input.get_origin_p2();
115 if (origin_p1.size() > 0 && origin_p2.size() > 0)
117 return points.at(origin_p1) +
input.get_origin_fraction() * (points.at(origin_p2) - points.at(origin_p1));
119 else if (origin_p1.size() > 0)
120 return points.at(origin_p1);
122 return points.at(
"zero");
125 template<
typename REAL>
131 origin_ = deriveOrigin(
input, points);
132 processAxis(
input, points, axes_, axinv_);
137 someMoreAxisGridStuff();
144 template<
typename REAL>
150 origin_ = deriveOrigin(
input, points);
151 processAxis(
input, points, axes_, axinv_);
154 someMoreAxisGridStuff();
161 template<
typename REAL>
167 origin_ = deriveOrigin(
input, points);
168 processAxis(
input, points, axes_, axinv_);
171 someMoreAxisGridStuff();
178 template<
typename REAL>
181 auto& axis_grids = input_.get_axis_grids();
185 dm_[0] = axis_grids[1].dimensions * axis_grids[2].dimensions;
186 dm_[1] = axis_grids[2].dimensions;
193 ndomains_ = axis_grids[0].dimensions * axis_grids[1].dimensions * axis_grids[2].dimensions;
195 data_.resize(ndomains_ * nvalues_per_domain_);
200 domain_volumes_.resize(ndomains_, 1);
201 domain_centers_.resize(ndomains_,
OHMMS_DIM);
202 domain_uwidths_.resize(ndomains_,
OHMMS_DIM);
203 std::vector<Real> interval_centers[
OHMMS_DIM];
204 std::vector<Real> interval_widths[
OHMMS_DIM];
206 auto& agr = axis_grids;
210 int nintervals = agr[d].ndu_per_interval.size();
211 app_log() <<
"nintervals " << d <<
" " << nintervals << std::endl;
212 interval_centers[d].resize(nintervals);
213 interval_widths[d].resize(nintervals);
214 interval_widths[d][0] = agr[d].ndu_per_interval[0] / agr[d].odu;
215 interval_centers[d][0] = interval_widths[d][0] / 2.0 + agr[d].umin;
216 for (
int i = 1; i < nintervals; i++)
218 interval_widths[d][i] = agr[d].ndu_per_interval[i] / agr[d].odu;
219 interval_centers[d][i] = interval_centers[d][i - 1] + .5 * (interval_widths[d][i] + interval_widths[d][i - 1]);
228 Point du, uc, ubc, rc;
232 for (
int i = 0; i < agr[0].dimensions; i++)
234 for (
int j = 0; j < agr[1].dimensions; j++)
236 for (
int k = 0; k < agr[2].dimensions; k++)
238 int idomain = dm_[0] * i + dm_[1] * j + dm_[2] * k;
239 du[0] = interval_widths[0][i];
240 du[1] = interval_widths[1][j];
241 du[2] = interval_widths[2][k];
242 uc[0] = interval_centers[0][i];
243 uc[1] = interval_centers[1][j];
244 uc[2] = interval_centers[2][k];
245 switch (input_.get_coord_form())
247 case (CoordForm::CARTESIAN):
248 vol = du[0] * du[1] * du[2];
251 case (CoordForm::CYLINDRICAL):
252 uc[1] = 2.0 * M_PI * uc[1] - M_PI;
253 du[1] = 2.0 * M_PI * du[1];
254 vol = uc[0] * du[0] * du[1] * du[2];
255 ubc[0] = uc[0] *
cos(uc[1]);
256 ubc[1] = uc[0] *
sin(uc[1]);
259 case (CoordForm::SPHERICAL):
260 uc[1] = 2.0 * M_PI * uc[1] - M_PI;
261 du[1] = 2.0 * M_PI * du[1];
262 uc[2] = M_PI * uc[2];
263 du[2] = M_PI * du[2];
264 vol = (uc[0] * uc[0] + du[0] * du[0] / 12.0) * du[0]
266 * 2.0 *
sin(uc[2]) *
sin(.5 * du[2]);
267 ubc[0] = uc[0] *
sin(uc[2]) *
cos(uc[1]);
268 ubc[1] = uc[0] *
sin(uc[2]) *
sin(uc[1]);
269 ubc[2] = uc[0] *
cos(uc[2]);
275 rc =
dot(axes_, ubc) + origin_;
281 domain_volumes_(idomain, 0) = vol;
284 domain_uwidths_(idomain, d) = du[d];
285 domain_centers_(idomain, d) = rc[d];
294 du[d] = agr[d].umax - agr[d].umin;
295 uc[d] = .5 * (agr[d].umax + agr[d].umin);
297 switch (input_.get_coord_form())
299 case CoordForm::CARTESIAN:
300 vol = du[0] * du[1] * du[2];
302 case CoordForm::CYLINDRICAL:
303 uc[1] = 2.0 * M_PI * uc[1] - M_PI;
304 du[1] = 2.0 * M_PI * du[1];
305 vol = uc[0] * du[0] * du[1] * du[2];
307 case CoordForm::SPHERICAL:
308 uc[1] = 2.0 * M_PI * uc[1] - M_PI;
309 du[1] = 2.0 * M_PI * du[1];
310 uc[2] = M_PI * uc[2];
311 du[2] = M_PI * du[2];
312 vol = (uc[0] * uc[0] + du[0] * du[0] / 12.0) * du[0]
314 * 2.0 *
sin(uc[2]) *
sin(.5 * du[2]);
319 volume_ = vol *
det(axes_);
352 template<
typename REAL>
355 os << indent +
"SpaceGrid" << std::endl;
358 switch (input_.get_coord_form())
360 case CoordForm::CARTESIAN:
363 case CoordForm::CYLINDRICAL:
366 case CoordForm::SPHERICAL:
372 auto& agr = input_.get_axis_grids();
373 auto& axis_labels = input_.get_axis_labels();
374 os << indent +
" SpaceGridInput::lookup_input_ename_value(input_.get_coord_form() = " +
s << std::endl;
375 os << indent +
" ndomains_ = " << ndomains_ << std::endl;
376 os << indent +
" axes = " << axes_ << std::endl;
377 os << indent +
" axinv = " << axinv_ << std::endl;
380 os << indent +
" axis " << axis_labels[d] <<
":" << std::endl;
381 os << indent +
" umin = " << agr[d].umin << std::endl;
382 os << indent +
" umax = " << agr[d].umax << std::endl;
383 os << indent +
" du = " << 1.0 /
static_cast<double>(agr[d].odu) << std::endl;
384 os << indent +
" dm = " << dm_[d] << std::endl;
385 os << indent +
" gmap = ";
386 for (
int g = 0; g < gmap_[d].size(); g++)
388 os << gmap_[d][g] <<
" ";
392 os << indent +
"end NESpaceGrid" << std::endl;
395 template<
typename REAL>
400 std::vector<int> ng(1);
402 std::stringstream ss;
403 ss << grid_index + cshift;
404 hdf_path hdf_name{
"spacegrid" + ss.str()};
405 observable_helper_ = std::make_shared<ObservableHelper>(hdf_name);
406 auto&
oh = *observable_helper_;
407 ng[0] = nvalues_per_domain_ * ndomains_;
411 auto& agr = input_.get_axis_grids();
415 dimensions[id] = agr[id].dimensions;
418 int coord =
static_cast<int>(input_.get_coord_form());
420 oh.
addProperty(const_cast<int&>(ndomains_),
"ndomains", file);
421 oh.
addProperty(const_cast<int&>(nvalues_per_domain_),
"nvalues_per_domain_", file);
430 std::map<std::string, int> axtmap;
438 auto& axis_labels = input_.get_axis_labels();
441 axtypes[d] = axtmap[axis_labels[d]];
448 std::string iname[ni];
450 ivar[
n] = (
int*)axtypes;
451 iname[
n] =
"axtypes";
453 ivar[
n] = dimensions.data();
454 iname[
n] =
"dimensions";
461 std::string rname[nr];
463 rvar[
n] = (
Real*)odu_;
466 rvar[
n] = (
Real*)umin_;
469 rvar[
n] = (
Real*)umax_;
473 for (
int i = 0; i < ni; i++)
476 imat(d, 0) = ivar[i][d];
481 for (
int i = 0; i < nr; i++)
484 rmat(d, 0) = rvar[i][d];
489 int gsize = gmap_[d].size();
490 imat.resize(gsize, 1);
491 for (
int i = 0; i < gsize; i++)
493 int gval = gmap_[d][i];
497 std::string gmname =
"gmap" +
int2string(ival);
503 template<
typename REAL>
506 if (observable_helper_)
508 if constexpr (std::is_same<Real, QMCTraits::FullPrecRealType>::value)
510 observable_helper_->write(data_.data(), file);
514 std::vector<QMCTraits::FullPrecRealType> expanded_data(data_.size(), 0.0);
515 std::copy_n(data_.begin(), data_.size(), expanded_data.begin());
516 assert(!data_.empty());
519 observable_helper_->write(expanded_data.data(), file);
526 #define NESpaceGrid_CHECK 528 template<
typename REAL>
531 auto& agr = input_.get_axis_grids();
534 odu_[id] = agr[id].odu;
535 umin_[id] = agr[id].umin;
536 umax_[id] = agr[id].umax;
537 gmap_[id].resize(
floor((umax_[
id] - umin_[
id]) * odu_[
id] + .5));
538 gmap_[id] = agr[id].gmap;
542 template<
typename REAL>
545 std::vector<bool>& particles_outside,
579 accumulate(R, values, particles_outside);
582 template<
typename REAL>
585 std::vector<bool>& particles_outside)
588 int nparticles = values.
size1();
589 int nvalues = values.
size2();
592 const Real o2pi = 1.0 / (2.0 * M_PI);
594 auto& agr = input_.get_axis_grids();
595 std::fill(particles_outside.begin(),particles_outside.end(),
true);
597 switch (input_.get_coord_form())
599 case CoordForm::CARTESIAN:
600 if (input_.isPeriodic())
602 for (p = 0; p < nparticles; p++)
604 particles_outside[p] =
false;
605 Point u =
dot(axinv_, (R[p] - origin_));
609 iu[d] = gmap_[d].at(
floor((u[d] - umin_[d]) * odu_[d]));
611 catch (
const std::exception& exc)
613 std::ostringstream
error;
614 error <<
"NESpaceGrid: particle: " << p <<
" position: " << R[p]
615 <<
" falls outside of the cell, for a period system all particle positions must be in the cell!\n";
616 std::throw_with_nested(std::runtime_error(
error.str()));
618 buf_index = buffer_offset_;
620 buf_index += nvalues * dm_[d] * iu[d];
621 for (v = 0; v < nvalues; v++, buf_index++)
622 data_[buf_index] += values(p, v);
627 for (p = 0; p < nparticles; p++)
629 Point u =
dot(axinv_, (R[p] - origin_));
630 if (u[0] > umin_[0] && u[0] < umax_[0] && u[1] > umin_[1] && u[1] < umax_[1] && u[2] > umin_[2] &&
633 particles_outside[p] =
false;
634 iu[0] = gmap_[0][
floor((u[0] - umin_[0]) * odu_[0])];
635 iu[1] = gmap_[1][
floor((u[1] - umin_[1]) * odu_[1])];
636 iu[2] = gmap_[2][
floor((u[2] - umin_[2]) * odu_[2])];
637 buf_index = buffer_offset_ + nvalues * (dm_[0] * iu[0] + dm_[1] * iu[1] + dm_[2] * iu[2]);
638 for (v = 0; v < nvalues; v++, buf_index++)
639 data_[buf_index] += values(p, v);
644 case CoordForm::CYLINDRICAL:
645 for (p = 0; p < nparticles; p++)
647 Point ub =
dot(axinv_, (R[p] - origin_));
648 Point u{
sqrt(ub[0] * ub[0] + ub[1] * ub[1]),
static_cast<Real>(
atan2(ub[1], ub[0]) * o2pi + .5), ub[2]};
649 if (u[0] > umin_[0] && u[0] < umax_[0] && u[1] > umin_[1] && u[1] < umax_[1] && u[2] > umin_[2] &&
652 particles_outside[p] =
false;
653 iu[0] = gmap_[0][
floor((u[0] - umin_[0]) * odu_[0])];
654 iu[1] = gmap_[1][
floor((u[1] - umin_[1]) * odu_[1])];
655 iu[2] = gmap_[2][
floor((u[2] - umin_[2]) * odu_[2])];
656 buf_index = buffer_offset_ + nvalues * (dm_[0] * iu[0] + dm_[1] * iu[1] + dm_[2] * iu[2]);
657 for (v = 0; v < nvalues; v++, buf_index++)
658 data_[buf_index] += values(p, v);
662 case CoordForm::SPHERICAL:
663 for (p = 0; p < nparticles; p++)
665 Point ub =
dot(axinv_, (R[p] - origin_));
667 u[0] =
sqrt(ub[0] * ub[0] + ub[1] * ub[1] + ub[2] * ub[2]);
668 u[1] =
atan2(ub[1], ub[0]) * o2pi + .5;
669 u[2] =
acos(ub[2] / u[0]) * o2pi * 2.0;
670 if (u[0] > umin_[0] && u[0] < umax_[0] && u[1] > umin_[1] && u[1] < umax_[1] && u[2] > umin_[2] &&
673 particles_outside[p] =
false;
674 iu[0] = gmap_[0][
floor((u[0] - umin_[0]) * odu_[0])];
675 iu[1] = gmap_[1][
floor((u[1] - umin_[1]) * odu_[1])];
676 iu[2] = gmap_[2][
floor((u[2] - umin_[2]) * odu_[2])];
677 buf_index = buffer_offset_ + nvalues * (dm_[0] * iu[0] + dm_[1] * iu[1] + dm_[2] * iu[2]);
678 for (v = 0; v < nvalues; v++, buf_index++)
679 data_[buf_index] += values(p, v);
684 app_log() <<
" coordinate type must be cartesian, cylindrical, spherical" << std::endl;
685 throw std::runtime_error(
"SpaceGrid<REAL>::evaluate received an invalid coordinate type");
689 template<
typename REAL>
692 for (
int v = 0; v < nvalues_per_domain_; v++)
696 for (
int i = 0,
n = buffer_offset_; i < ndomains_; i++,
n += nvalues_per_domain_)
698 for (
int v = 0; v < nvalues_per_domain_; v++)
700 vals[v] += data_[
n + v];
705 template<
typename REAL>
708 for (
NESpaceGrid& crowd_grid : grid_for_each_crowd)
710 std::transform(reduction_grid.
data_.begin(), reduction_grid.
data_.end(), crowd_grid.data_.begin(),
711 reduction_grid.
data_.begin(), std::plus<>{});
716 template<
typename REAL>
722 template<
typename REAL>
725 app_log() <<
"SpaceGrid<REAL>::check_grid" << std::endl;
726 const Real o2pi = 1.0 / (2.0 * M_PI);
731 auto& agr = input_.get_axis_grids();
732 for (
int i = 0; i < ndomains_; i++)
735 dc[d] = domain_centers_(i, d);
736 Point ub =
dot(axinv_, (dc - origin_));
739 switch (input_.get_coord_form())
741 case CoordForm::CARTESIAN:
744 case CoordForm::CYLINDRICAL:
745 u[0] =
sqrt(ub[0] * ub[0] + ub[1] * ub[1]);
746 u[1] =
atan2(ub[1], ub[0]) * o2pi + .5;
749 case CoordForm::SPHERICAL:
750 u[0] =
sqrt(ub[0] * ub[0] + ub[1] * ub[1] + ub[2] * ub[2]);
751 u[1] =
atan2(ub[1], ub[0]) * o2pi + .5;
752 u[2] =
acos(ub[2] / u[0]) * o2pi * 2.0;
757 iu[0] = gmap_[0][
floor((u[0] - agr[0].umin) * odu_[0])];
758 iu[1] = gmap_[1][
floor((u[1] - agr[1].umin) * odu_[1])];
759 iu[2] = gmap_[2][
floor((u[2] - agr[2].umin) * odu_[2])];
760 idomain = dm_[0] * iu[0] + dm_[1] * iu[1] + dm_[2] * iu[2];
763 app_log() <<
" cell mismatch " << i <<
" " << idomain << std::endl;
769 app_log() <<
" NESpaceGrid cells do not map onto themselves" << std::endl;
771 app_log() <<
"end NESpaceGrid<REAL>::check_grid" << std::endl;
bool initializeSpherical(const SpaceGridInput &input, const Points &points)
Initialize NESpaceGrid for cylindrical grid.
static Point deriveOrigin(const SpaceGridInput &input, const Points &points)
return actual origin point based on input
helper functions for EinsplineSetBuilder
Tensor< T, D >::Type_t det(const Tensor< T, D > &a)
MakeReturn< UnaryNode< FnFabs, typename CreateLeaf< Vector< T1, C1 > >::Leaf_t > >::Expression_t abs(const Vector< T1, C1 > &l)
typename NEReferencePoints::Point Point
std::map< std::string, Point > Points
MakeReturn< UnaryNode< FnSin, typename CreateLeaf< Vector< T1, C1 > >::Leaf_t > >::Expression_t sin(const Vector< T1, C1 > &l)
typename NEReferencePoints::Points Points
std::string int2string(const int &i)
void addProperty(T &p, const std::string &pname, hdf_archive &file)
add named property to describe the collectable this helper class handles
void resize(size_type n, size_type m)
Resize the container.
Attaches a unit to a Vector for IO.
This is the port of QMCHamiltonian/SpaceGrid to the new Estimator design.
void copyToSoA()
copy AxisGrid data to SoA layout for evaluation
void accumulate(const ParticlePos &R, const Matrix< Real > &values, std::vector< bool > &particles_outside)
void error(char const *m)
MakeReturn< UnaryNode< FnCos, typename CreateLeaf< Vector< T1, C1 > >::Leaf_t > >::Expression_t cos(const Vector< T1, C1 > &l)
MakeReturn< UnaryNode< FnArcCos, typename CreateLeaf< Vector< T1, C1 > >::Leaf_t > >::Expression_t acos(const Vector< T1, C1 > &l)
static void processAxis(const SpaceGridInput &input, const Points &points, AxTensor &axes, AxTensor &axinv)
create axes and axinv tensors
MakeReturn< BinaryNode< FnArcTan2, typename CreateLeaf< Vector< T1, C1 > >::Leaf_t, typename CreateLeaf< Vector< T2, C2 > >::Leaf_t > >::Expression_t atan2(const Vector< T1, C1 > &l, const Vector< T2, C2 > &r)
AB type of DistanceTable containing storage.
void write_description(std::ostream &os, const std::string &indent)
bool initializeCylindrical(const SpaceGridInput &input, const Points &points)
Initialize NESpaceGrid for cylindrical grid.
bool initializeRectilinear(const SpaceGridInput &input, const Points &points)
Initialize NESpaceGrid for rectilinear grid.
bool initializeCoordSystem()
dispatch to correct initialize for coord type
std::vector< std::reference_wrapper< T > > RefVector
MakeReturn< UnaryNode< FnSqrt, typename CreateLeaf< Vector< T1, C1 > >::Leaf_t > >::Expression_t sqrt(const Vector< T1, C1 > &l)
void registerGrid(hdf_archive &file, int grid_index)
set up Observable helper(s) for this grid almost unchanged from legacy
sycl::event copy_n(sycl::queue &aq, const T1 *restrict VA, size_t array_size, T2 *restrict VC, const std::vector< sycl::event > &events)
Tensor< T, D > inverse(const Tensor< T, D > &a)
void set_dimensions(const std::vector< int > &dims, int first)
set the shape of this observable
Tensor< typename BinaryReturn< T1, T2, OpMultiply >::Type_t, D > dot(const AntiSymTensor< T1, D > &lhs, const AntiSymTensor< T2, D > &rhs)
static void collect(NESpaceGrid &reduction_grid, RefVector< NESpaceGrid > grid_for_each_crowd)
void write(hdf_archive &file) const
void sum(const BufferType &buf, Real *vals)
void someMoreAxisGridStuff()
Initialize NESpaceGrid for voronoi grid.
NESpaceGrid(SpaceGridInput &sgi, const Points &points, const int nvalues, const bool is_periodic)
This constructor is used for electron only grids.
std::vector< Real > data_
MakeReturn< UnaryNode< FnFloor, typename CreateLeaf< Vector< T1, C1 > >::Leaf_t > >::Expression_t floor(const Vector< T1, C1 > &l)