QMCPACK
ParseGridInput.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: Peter W. Doak, doakpw@ornl.gov, Oak Ridge National Lab
8 //
9 // File created by: Peter W. Doak, doakpw@ornl.gov, Oak Ridge National Lab
10 //////////////////////////////////////////////////////////////////////////////////////
11 
12 #include "ParseGridInput.hpp"
13 
14 #include <cmath>
15 
16 #include <ModernStringUtils.hpp>
18 
19 namespace qmcplusplus
20 {
21 
22 template<typename REAL>
23 AxisGrid<REAL> parseGridInput(std::istringstream& grid_input_stream)
24 {
25  using namespace modernstrutil;
26  const REAL utol = 1e-5;
27 
28  std::string grid_line;
29  std::getline(grid_input_stream, grid_line);
30  // This refactored from QMCHamiltonian/SpaceGrid::initializeRectilinear
31  std::vector<std::string_view> tokens = split(grid_line, " ");
32 
33  // count the number of intervals
34  int nintervals = 0;
35  for (int i = 0; i < tokens.size(); i++)
36  if (tokens[i][0] != '(')
37  nintervals++;
38  nintervals--;
39  // allocate temporary interval variables
40  AxisGrid<REAL> agr;
41  agr.ndom_int.resize(nintervals);
42  agr.du_int.resize(nintervals);
43  agr.ndu_int.resize(nintervals);
44  // determine number of domains in each interval and the width of each domain
45  REAL u1 = string2Real<REAL>(tokens[0]);
46 
47  agr.umin = u1;
48  if (std::abs(u1) > 1.0000001)
49  {
50  std::ostringstream msg;
51  msg << " interval endparticles cannot be greater than " << 1 << '\n' << " endpoint provided: " << u1;
52  throw UniformCommunicateError(msg.str());
53  }
54  bool is_int = false;
55  bool has_paren_val = false;
56  REAL du_i;
57  int ndom_i = 1;
58  int interval = -1;
59  for (int i = 1; i < tokens.size(); i++)
60  {
61  if (tokens[i][0] != '(')
62  {
63  REAL u2 = string2Real<REAL>(tokens[i]);
64  agr.umax = u2;
65  if (!has_paren_val)
66  du_i = u2 - u1;
67  has_paren_val = false;
68  interval++;
69  if (u2 < u1)
70  {
71  std::ostringstream msg;
72 
73  msg << " interval (" << u1 << "," << u2 << ") is negative" << std::endl;
74  throw UniformCommunicateError(msg.str());
75  }
76  if (std::abs(u2) > 1.0000001)
77  {
78  std::ostringstream msg;
79 
80  msg << " interval endparticles cannot be greater than " << 1 << std::endl;
81  msg << " endpoint provided: " << u2 << std::endl;
82  throw UniformCommunicateError(msg.str());
83  }
84  if (is_int)
85  {
86  agr.du_int[interval] = (u2 - u1) / ndom_i;
87  agr.ndom_int[interval] = ndom_i;
88  }
89  else
90  {
91  agr.du_int[interval] = du_i;
92  agr.ndom_int[interval] = std::floor((u2 - u1) / du_i + .5);
93  if (std::abs(u2 - u1 - du_i * agr.ndom_int[interval]) > utol)
94  {
95  std::ostringstream msg;
96 
97  msg << " interval (" << u1 << "," << u2 << ") not divisible by du=" << du_i << std::endl;
98  throw UniformCommunicateError(msg.str());
99  }
100  }
101  u1 = u2;
102  }
103  else
104  {
105  has_paren_val = true;
106  std::string paren_val{tokens[i].substr(1, tokens[i].length() - 2)};
107  is_int = tokens[i].find(".") == std::string::npos;
108  if (is_int)
109  {
110  ndom_i = string2Int<int>(paren_val);
111  du_i = -1.0;
112  }
113  else
114  {
115  ndom_i = 0;
116  du_i = string2Real<REAL>(paren_val);
117  }
118  }
119  }
120  // find the smallest domain width
121  REAL du_min = 1.0;
122  for (int i = 0; i < agr.du_int.size(); i++)
123  du_min = std::min(du_min, agr.du_int[i]);
124  agr.odu = 1.0 / du_min;
125  // make sure it divides into all other domain widths
126  for (int i = 0; i < agr.du_int.size(); i++)
127  {
128  agr.ndu_int[i] = floor(agr.du_int[i] / du_min + .5);
129  if (std::abs(agr.du_int[i] - agr.ndu_int[i] * du_min) > utol)
130  {
131  std::ostringstream msg;
132  msg << "interval " << i + 1 << " of axis is not divisible by smallest subinterval " << du_min;
133  throw UniformCommunicateError(msg.str());
134  }
135  }
136  // set up the interval map such that gmap[u/du]==domain index
137  agr.gmap.resize(floor((agr.umax - agr.umin) * agr.odu + .5));
138  int n = 0;
139  int nd = -1;
140  for (int i = 0; i < agr.ndom_int.size(); i++)
141  for (int j = 0; j < agr.ndom_int[i]; j++)
142  {
143  nd++;
144  for (int k = 0; k < agr.ndu_int[i]; k++)
145  {
146  //app_log()<<" accessing gmap "<<iaxis<<" "<<n<< std::endl;
147  agr.gmap[n] = nd;
148  n++;
149  }
150  }
151  agr.dimensions = nd + 1;
152  //end read in the grid contents
153  //save interval width information
154  int ndom_tot = 0;
155  for (int i = 0; i < agr.ndom_int.size(); i++)
156  ndom_tot += agr.ndom_int[i];
157  agr.ndu_per_interval.resize(ndom_tot);
158  int idom = 0;
159  for (int i = 0; i < agr.ndom_int.size(); i++)
160  for (int ii = 0; ii < agr.ndom_int[i]; ii++)
161  {
162  agr.ndu_per_interval[idom] = agr.ndu_int[i];
163  idom++;
164  }
165  return agr;
166 }
167 
168 template<typename REAL>
169 AxisGrid<REAL>::AxisGrid(std::vector<int>&& rhs_ndom_int,
170  std::vector<int>&& rhs_ndu_int,
171  std::vector<REAL>&& rhs_du_int,
172  REAL rhs_umin,
173  REAL rhs_umax,
174  REAL rhs_odu,
175  std::vector<int>&& rhs_gmap,
176  std::vector<int>&& rhs_ndu_per_interval,
177  int rhs_dimensions)
178 {
179  ndom_int = rhs_ndom_int;
180  ndu_int = rhs_ndu_int;
181  du_int = rhs_du_int;
182  umin = rhs_umin;
183  umax = rhs_umax;
184  odu = rhs_odu;
185  gmap = rhs_gmap;
186  ndu_per_interval = rhs_ndu_per_interval;
187  dimensions = rhs_dimensions;
188 }
189 
190 template<typename REAL>
192 {
193  ndom_int = rhs.ndom_int;
194  ndu_int = rhs.ndu_int;
195  du_int = rhs.du_int;
196  umin = rhs.umin;
197  umax = rhs.umax;
198  odu = rhs.odu;
199  gmap = rhs.gmap;
200  ndu_per_interval = rhs.ndu_per_interval;
201  dimensions = rhs.dimensions;
202 }
203 
204 template<typename REAL>
206 {
207  std::swap(ndom_int, rhs.ndom_int);
208  std::swap(ndu_int, rhs.ndu_int);
209  std::swap(du_int, rhs.du_int);
210  std::swap(umin, rhs.umin);
211  std::swap(umax, rhs.umax);
212  std::swap(odu, rhs.odu);
213  std::swap(gmap, rhs.gmap);
214  std::swap(ndu_per_interval, rhs.ndu_per_interval);
215  std::swap(dimensions, rhs.dimensions);
216  return *this;
217 }
218 
219 
220 // explicit instantiation
221 template struct AxisGrid<float>;
222 template struct AxisGrid<double>;
223 template AxisGrid<double> parseGridInput<double>(std::istringstream& grid_input_stream);
224 template AxisGrid<float> parseGridInput<float>(std::istringstream& grid_input_stream);
225 } // namespace qmcplusplus
template AxisGrid< double > parseGridInput< double >(std::istringstream &grid_input_stream)
std::vector< int > gmap
helper functions for EinsplineSetBuilder
Definition: Configuration.h:43
AxisGrid< REAL > parseGridInput(std::istringstream &grid_input_stream)
Parses the one dimensional grid specification format originated for EnergyDensity This has be refacto...
MakeReturn< UnaryNode< FnFabs, typename CreateLeaf< Vector< T1, C1 > >::Leaf_t > >::Expression_t abs(const Vector< T1, C1 > &l)
T min(T a, T b)
std::vector< int > ndu_per_interval
template AxisGrid< float > parseGridInput< float >(std::istringstream &grid_input_stream)
This a subclass for runtime errors that will occur on all ranks.
std::vector< int > ndom_int
AxisGrid & operator=(AxisGrid rhs)
std::vector< int > ndu_int
The AxisGrid data structure and the ParseGridInput factor parsing in a manner usable in acustom handl...
std::vector< std::string_view > split(const string_view s, const string_view delimiters)
std::vector< REAL > du_int
MakeReturn< UnaryNode< FnFloor, typename CreateLeaf< Vector< T1, C1 > >::Leaf_t > >::Expression_t floor(const Vector< T1, C1 > &l)