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) 2016 Jeongnim Kim and QMCPACK developers.
6 //
7 // File developed by: Paul R. C. Kent, kentpr@ornl.gov, Oak Ridge National Laboratory
8 // Mark A. Berrill, berrillma@ornl.gov, Oak Ridge National Laboratory
9 //
10 // File created by: Paul R. C. Kent, kentpr@ornl.gov, Oak Ridge National Laboratory
11 //////////////////////////////////////////////////////////////////////////////////////
12
13
14 // http://pathintegrals.info //
15 /////////////////////////////////////////////////////////////
16
17 #ifndef GRID_H
18 #define GRID_H
19
20 #include "IO.h"
21
22 #include "Blitz.h"
23
24 using IO::IOSectionClass;
25
26 //Ken's Grid Class
27
28 /// The different types of grids that we currently allow
29 typedef enum
30 {
31 NONE,
32 LINEAR,
33 OPTIMAL,
34 OPTIMAL2,
35 LOG,
36 CLUSTER,
37 GENERAL,
38 CENTER
39 } GridType;
40
41
42 /// Parent class for all grids
43 class Grid
44 {
45 protected:
46 /// Contains the grid points
47 Array<double, 1> grid;
48
49 public:
50 /// First and last grid points
51 double Start, End;
52
53 /// Number of points in the grid
54 int NumPoints;
55
56 /// The i'th point in the grid
operator()57 inline double operator()(int i) const { return (grid(i)); }
data()58 inline double* data() { return grid.data(); }
Points()59 inline Array<double, 1>& Points() { return grid; }
60
61 /// Returns the type of the grid (i.e. linear, optimal, etc)
62 virtual GridType Type() = 0;
63
64 ///Returns the index of the nearest point below r.
65 virtual int ReverseMap(double r) = 0;
66 virtual void Write(IOSectionClass& out) = 0;
67 virtual void Read(IOSectionClass& inSection) = 0;
~Grid()68 virtual ~Grid(){}
69 };
70
71
72 /// Linear Grid inherets from Grid.
73 class LinearGrid : public Grid
74 {
75 private:
76 /// The value between successive grid points.
77 double delta, deltainv;
78 inline void CheckRoundingMode();
79
80 public:
81 /// Returns the type of the grid (in this case LINEAR)
Type()82 GridType Type() { return (LINEAR); }
83
84 /// Returns the index of the nearest point below r.
ReverseMap(double r)85 int ReverseMap(double r) { return ((int)nearbyint((r - Start) * deltainv - 0.5)); }
86
87 /// Initializes the linear grid.
Init(double start,double end,int numpoints)88 inline void Init(double start, double end, int numpoints)
89 {
90 Start = start;
91 End = end;
92 NumPoints = numpoints;
93 grid.resize(NumPoints);
94 delta = (End - Start) / (double)(NumPoints - 1);
95 deltainv = 1.0 / delta;
96 for (int i = 0; i < NumPoints; i++)
97 grid(i) = Start + (double)i * delta;
98 CheckRoundingMode();
99 }
100
Write(IOSectionClass & outSection)101 void Write(IOSectionClass& outSection)
102 {
103 outSection.WriteVar("Points", grid);
104 outSection.WriteVar("Type", std::string("Linear"));
105 outSection.WriteVar("Start", Start);
106 outSection.WriteVar("End", End);
107 outSection.WriteVar("NumPoints", NumPoints);
108 }
109
Read(IOSectionClass & inSection)110 void Read(IOSectionClass& inSection)
111 {
112 assert(inSection.ReadVar("Start", Start));
113 assert(inSection.ReadVar("End", End));
114 assert(inSection.ReadVar("NumPoints", NumPoints));
115 Init(Start, End, NumPoints);
116 }
117
118 /// Useless constructor
LinearGrid()119 LinearGrid()
120 { /* Do nothing */
121 }
122
123 LinearGrid& operator=(const LinearGrid& lin)
124 {
125 grid.resize(lin.grid.shape());
126 Start = lin.Start;
127 End = lin.End;
128 grid = lin.grid;
129 delta = lin.delta;
130 deltainv = lin.deltainv;
131 return *this;
132 }
133
134 /// Constructor that sets the number of points, start and end point
135 /// of the original grid
LinearGrid(double start,double end,int numpoints)136 LinearGrid(double start, double end, int numpoints) { Init(start, end, numpoints); }
137 };
138
139
140 /// General Grid inherets from Grid.
141 class GeneralGrid : public Grid
142 {
143 public:
144 /// Returns the type of the grid (in this case GENERAL)
Type()145 GridType Type() { return (GENERAL); }
146
147 /// Returns the index of the nearest point below r.
ReverseMap(double r)148 int ReverseMap(double r)
149 {
150 if (r <= grid(0))
151 return (0);
152 else if (r >= grid(NumPoints - 1))
153 return (NumPoints - 1);
154 else
155 {
156 int hi = NumPoints - 1;
157 int lo = 0;
158 bool done = false;
159 while (!done)
160 {
161 int i = (hi + lo) >> 1;
162 if (grid(i) > r)
163 hi = i;
164 else
165 lo = i;
166 done = (hi - lo) < 2;
167 }
168 return std::min(lo, NumPoints - 2);
169 }
170 }
171
Write(IOSectionClass & outSection)172 void Write(IOSectionClass& outSection)
173 {
174 outSection.WriteVar("Points", grid);
175 outSection.WriteVar("Type", std::string("General"));
176 }
177
Read(IOSectionClass & inSection)178 void Read(IOSectionClass& inSection)
179 {
180 assert(inSection.ReadVar("Points", grid));
181 Start = grid(0);
182 End = grid(grid.size() - 1);
183 NumPoints = grid.size();
184 }
185
Init(Array<double,1> & points)186 void Init(Array<double, 1>& points)
187 {
188 NumPoints = points.size();
189 grid.resize(NumPoints);
190 grid = points;
191 Start = grid(0);
192 End = grid(NumPoints - 1);
193 }
194
195 /// Useless constructor
GeneralGrid()196 GeneralGrid()
197 { /* Do nothing */
198 }
199 };
200
201
202 /// The OptimalGrid class stores a grid which has linear spacing at
203 /// the origin and exponential spacing further out. It has the
204 /// analytic form \f[r_k = a\left(e^{kb}-1\right)\f].
205 class OptimalGrid : public Grid
206 {
207 private:
208 double a, b;
209
210 public:
Type()211 GridType Type() { return (OPTIMAL); }
212
ReverseMap(double r)213 int ReverseMap(double r)
214 {
215 if ((r / a) < 1e-6)
216 return ((int)floor(r / (a * b) + 0.5) - 1);
217 else
218 return ((int)floor(log(r / a + 1.0) / b + 0.5) - 1);
219 }
220
221 /// Returns a parameter
Geta()222 double Geta() const { return (a); }
223
224 /// Returns b parameter
Getb()225 double Getb() const { return (b); }
226
OptimalGrid()227 OptimalGrid()
228 {
229 // Do nothing
230 }
231
232 /// This form of the constructor takes the number of points, the
233 /// maximum radius and the value of b.
Init(int numpoints,double rmax,double bval)234 void Init(int numpoints, double rmax, double bval)
235 {
236 NumPoints = numpoints;
237 b = bval;
238 End = rmax;
239 a = End / (exp(b * (double)NumPoints) - 1.0);
240 Start = a * (exp(b) - 1.0);
241 grid.resize(NumPoints);
242
243 for (int i = 0; i < NumPoints; i++)
244 grid(i) = a * (exp(b * (i + 1)) - 1.0);
245 }
246
OptimalGrid(int numPoints,double rmax,double bval)247 OptimalGrid(int numPoints, double rmax, double bval) { Init(numPoints, rmax, bval); }
248
Init(double aval,double bval,int numPoints)249 void Init(double aval, double bval, int numPoints)
250 {
251 a = aval;
252 b = bval;
253 NumPoints = numPoints;
254 Start = a * (exp(b) - 1.0);
255 End = a * (exp(b * NumPoints) - 1.0);
256
257 grid.resize(NumPoints);
258
259 for (int i = 0; i < NumPoints; i++)
260 grid(i) = a * (exp(b * (i + 1)) - 1.0);
261 }
262
263
264 /// This form of the constructor takes a, b, and the number of points.
OptimalGrid(double aval,double bval,int numPoints)265 OptimalGrid(double aval, double bval, int numPoints) { Init(aval, bval, numPoints); }
266
Write(IOSectionClass & outSection)267 void Write(IOSectionClass& outSection)
268 {
269 outSection.WriteVar("Points", grid);
270 outSection.WriteVar("Type", std::string("Optimal"));
271 outSection.WriteVar("a", a);
272 outSection.WriteVar("b", b);
273 outSection.WriteVar("NumPoints", NumPoints);
274 }
275
Read(IOSectionClass & inSection)276 void Read(IOSectionClass& inSection)
277 {
278 double aval, bval;
279 int numPoints;
280 if (inSection.ReadVar("a", aval))
281 {
282 assert(inSection.ReadVar("b", bval));
283 assert(inSection.ReadVar("NumPoints", numPoints));
284 Init(aval, bval, numPoints);
285 }
286 else
287 {
288 double Z, rmax;
289 assert(inSection.ReadVar("Z", Z));
290 assert(inSection.ReadVar("rmax", rmax));
291 Init(Z, rmax);
292 }
293 }
294
InitRatio(double end,double ratio,int numpoints)295 void InitRatio(double end, double ratio, int numpoints)
296 {
297 End = end;
298 NumPoints = numpoints;
299
300 b = log(ratio) / (double)(numpoints - 2);
301 a = end / (exp(b * (double)(numpoints - 1)) - 1);
302
303 grid.resize(NumPoints);
304
305 for (int i = 0; i < NumPoints; i++)
306 grid(i) = a * (exp(b * i) - 1.0);
307 }
308
309
310 /// This form of the constructor takes a nuclear charge and a
311 /// maxmimum radius and chooses an appropriate number of points for
312 /// that atom.
Init(double Z,double rmax)313 void Init(double Z, double rmax)
314 {
315 a = 4.34e-6 / Z;
316 //a = 4.0e-2;
317 b = 0.002304;
318 //b = 0.004;
319
320 NumPoints = (int)ceil(log(rmax / a + 1.0) / b);
321 b = log(rmax / a + 1.0) / (double)NumPoints;
322 Start = a * (exp(b) - 1.0);
323 End = rmax;
324 //End = a * (exp(b*NumPoints) - 1.0);
325
326 grid.resize(NumPoints);
327
328 for (int i = 0; i < NumPoints; i++)
329 {
330 grid(i) = a * (exp(b * (i + 1)) - 1.0);
331 //fprintf (stdout, "%1.12e\n", grid(i));
332 }
333 }
334
335 inline OptimalGrid& operator=(const OptimalGrid& opt)
336 {
337 grid.resize(opt.grid.shape());
338 a = opt.a;
339 b = opt.b;
340 NumPoints = opt.NumPoints;
341 Start = opt.Start;
342 End = opt.End;
343 grid = opt.grid;
344 return *this;
345 }
346
OptimalGrid(double Z,double rmax)347 OptimalGrid(double Z, double rmax) { Init(Z, rmax); }
348 };
349
350
351 /// The OptimalGrid class stores a grid which has linear spacing at
352 /// the origin and exponential spacing further out. It has the
353 /// analytic form \f[r_k = a\left(e^{kb}-1\right)\f].
354 class OptimalGrid2 : public Grid
355 {
356 private:
357 double a, b, c;
358 double Ratio;
359
360 public:
Type()361 GridType Type() { return (OPTIMAL2); }
362
ReverseMap(double r)363 int ReverseMap(double r)
364 {
365 // if ((r/a) < 1e-6)
366 // return ((int)floor(r/(a*b)));
367 // else
368 return ((int)floor(log1p((r - c) / a) / b));
369 }
370
371 /// Returns a parameter
Geta()372 double Geta() const { return (a); }
373
374 /// Returns b parameter
Getb()375 double Getb() const { return (b); }
376
OptimalGrid2()377 OptimalGrid2()
378 {
379 // Do nothing
380 }
381
382 /// This form of the constructor takes the number of points, the
383 /// maximum radius and the value of b.
OptimalGrid2(int numpoints,double rmax,double bval)384 OptimalGrid2(int numpoints, double rmax, double bval)
385 {
386 NumPoints = numpoints;
387 b = bval;
388 End = rmax;
389 a = End / (exp(b * (double)NumPoints) - 1.0);
390 Start = a * (exp(b) - 1.0);
391 grid.resize(NumPoints);
392 c = 0.0;
393
394 for (int i = 0; i < NumPoints; i++)
395 grid(i) = c + a * expm1(b * i);
396 }
397
Init(double start,double end,double ratio,int numpoints)398 void Init(double start, double end, double ratio, int numpoints)
399 {
400 Start = start;
401 End = end;
402 Ratio = ratio;
403 NumPoints = numpoints;
404
405 b = log(ratio) / (double)(numpoints - 2);
406 c = Start;
407 a = (end - c) / expm1(b * (double)(numpoints - 1));
408
409 grid.resize(NumPoints);
410
411 for (int i = 0; i < NumPoints; i++)
412 grid(i) = c + a * expm1(b * i);
413 }
414
415
416 /// This form of the constructor takes a, b, and the number of points.
OptimalGrid2(double start,double end,double ratio,int numpoints)417 OptimalGrid2(double start, double end, double ratio, int numpoints) { Init(start, end, ratio, numpoints); }
418
Write(IOSectionClass & outSection)419 void Write(IOSectionClass& outSection)
420 {
421 outSection.WriteVar("Points", grid);
422 outSection.WriteVar("Type", std::string("Optimal2"));
423 outSection.WriteVar("Start", Start);
424 outSection.WriteVar("End", End);
425 outSection.WriteVar("Ratio", Ratio);
426 outSection.WriteVar("NumPoints", NumPoints);
427 }
428
Read(IOSectionClass & inSection)429 void Read(IOSectionClass& inSection)
430 {
431 double start, end, ratio;
432 int numPoints;
433 assert(inSection.ReadVar("Start", start));
434 assert(inSection.ReadVar("End", end));
435 assert(inSection.ReadVar("Ratio", ratio));
436 assert(inSection.ReadVar("NumPoints", numPoints));
437 Init(start, end, ratio, numPoints);
438 }
439 };
440
441
442 class CenterGrid : public Grid
443 {
444 private:
445 double a, aInv, b, bInv, center;
446 int HalfPoints;
447 bool Odd;
448 double EvenHalf;
449 int OddOne;
450
451 public:
452 // ratio gives approximately the largest grid spacing divided by the
453 // smallest.
Type()454 GridType Type() { return CENTER; }
455
ReverseMap(double x)456 int ReverseMap(double x)
457 {
458 x -= center;
459 double index = copysign(log1p(std::abs(x) * aInv) * bInv, x);
460 return (int)floor(HalfPoints + index - EvenHalf);
461 }
Write(IOSectionClass & out)462 void Write(IOSectionClass& out) {}
Read(IOSectionClass & in)463 void Read(IOSectionClass& in) {}
Init(double start,double end,double ratio,int numPoints)464 void Init(double start, double end, double ratio, int numPoints)
465 {
466 assert(ratio > 1.0);
467 Start = start;
468 End = end;
469 center = 0.5 * (start + end);
470 NumPoints = numPoints;
471 HalfPoints = numPoints / 2;
472 Odd = ((numPoints % 2) == 1);
473 b = log(ratio) / (double)(HalfPoints - 1);
474 bInv = 1.0 / b;
475 grid.resize(numPoints);
476 if (Odd)
477 {
478 EvenHalf = 0.0;
479 OddOne = 1;
480 a = 0.5 * (end - start) / expm1(b * HalfPoints);
481 aInv = 1.0 / a;
482 for (int i = -HalfPoints; i <= HalfPoints; i++)
483 {
484 double sign = (i < 0) ? -1.0 : 1.0;
485 grid(i + HalfPoints) = sign * a * expm1(b * std::abs(i)) + center;
486 }
487 }
488 else
489 {
490 EvenHalf = 0.5;
491 OddOne = 0;
492 a = 0.5 * (end - start) / expm1(b * (-0.5 + HalfPoints));
493 aInv = 1.0 / a;
494 for (int i = -HalfPoints; i < HalfPoints; i++)
495 {
496 double sign = (i < 0) ? -1.0 : 1.0;
497 grid(i + HalfPoints) = sign * a * expm1(b * std::abs(0.5 + i)) + center;
498 }
499 }
500 }
501 };
502
503
504 /// LogGrid is a function whose gridpoints increase exponentially with
505 /// the index. That is, it has the analytic form
506 /// \f[ r_k = \frac{r_0}{Z} \Delta^k.\f] It is appropriate for
507 /// functions which change rapidly near the origin but vary smoothly
508 /// further out.
509 class LogGrid : public Grid
510 {
511 public:
512 double Z, r0, Spacing;
513
Type()514 GridType Type() { return (LOG); }
515
ReverseMap(double r)516 int ReverseMap(double r) { return ((int)(floor(log(Z * r / r0) / log(Spacing)))); }
517
LogGrid()518 LogGrid()
519 {
520 // Do nothing
521 }
522
Init(double R0,double spacing,int numpoints)523 void Init(double R0, double spacing, int numpoints)
524 {
525 NumPoints = numpoints;
526 Z = 1.0;
527 r0 = R0;
528 Spacing = spacing;
529 Start = r0;
530 End = r0 * pow(Spacing, (double)NumPoints - 1);
531 grid.resize(NumPoints);
532
533 for (int i = 0; i < NumPoints; i++)
534 grid(i) = r0 * pow(Spacing, (double)i);
535 }
536
537
Write(IOSectionClass & outSection)538 void Write(IOSectionClass& outSection)
539 {
540 outSection.WriteVar("Points", grid);
541 outSection.WriteVar("Type", std::string("Log"));
542 outSection.WriteVar("r0", r0);
543 outSection.WriteVar("Spacing", Spacing);
544 }
545
Read(IOSectionClass & inSection)546 void Read(IOSectionClass& inSection)
547 {
548 double tempr0, tempSpacing;
549 int tempNumPoints;
550 assert(inSection.ReadVar("r0", tempr0));
551 assert(inSection.ReadVar("Spacing", tempSpacing));
552 assert(inSection.ReadVar("NumPoints", tempNumPoints));
553 Init(tempr0, tempSpacing, tempNumPoints);
554 }
555
LogGrid(double R0,double spacing,int numpoints)556 LogGrid(double R0, double spacing, int numpoints) { Init(R0, spacing, numpoints); }
557
LogGrid(int numpoints,double z,double R0,double spacing)558 LogGrid(int numpoints, double z, double R0, double spacing)
559 {
560 NumPoints = numpoints;
561 Z = z;
562 r0 = R0;
563 Spacing = spacing;
564
565 Start = r0 / Z;
566 End = r0 / Z * pow(Spacing, (double)(NumPoints - 1));
567
568 grid.resize(NumPoints);
569
570 for (int i = 0; i < NumPoints; i++)
571 grid(i) = r0 / Z * pow(Spacing, (double)i);
572 }
573 };
574
575
576 /// ClusterGrid is a function whose gridpoints are clustered tightly
577 /// around the origin.
578 class ClusterGrid : public Grid
579 {
580 private:
581 double x0, dri, rr;
582
583 public:
584 double Start, End, Cluster;
585
Type()586 GridType Type() { return (CLUSTER); }
587
ReverseMap(double r)588 int ReverseMap(double r) { return ((int)floor(dri / (r - rr) - 1.0 + x0)); }
589
Init(double start,double end,double cluster,int numpoints)590 void Init(double start, double end, double cluster, int numpoints)
591 {
592 Start = start;
593 End = end;
594 Cluster = cluster;
595 NumPoints = numpoints;
596
597 x0 = (NumPoints - Cluster) / (1.0 - Cluster);
598 dri = -(End - Start) * ((double)NumPoints - x0) * (1.0 - x0) / ((double)NumPoints - 1.0);
599 rr = Start - dri / (1.0 - x0);
600 grid.resize(NumPoints);
601 for (int i = 0; i < NumPoints; i++)
602 grid(i) = rr + dri / (i + 1.0 - x0);
603 }
604
Write(IOSectionClass & outSection)605 void Write(IOSectionClass& outSection)
606 {
607 outSection.WriteVar("Points", grid);
608 outSection.WriteVar("Type", std::string("Cluster"));
609 outSection.WriteVar("Start", Start);
610 outSection.WriteVar("End", End);
611 outSection.WriteVar("Cluster", Cluster);
612 outSection.WriteVar("NumPoints", NumPoints);
613 }
614
Read(IOSectionClass & inSection)615 void Read(IOSectionClass& inSection)
616 {
617 double start, end, cluster;
618 int numpoints;
619 assert(inSection.ReadVar("Start", start));
620 assert(inSection.ReadVar("End", end));
621 assert(inSection.ReadVar("Cluster", cluster));
622 assert(inSection.ReadVar("NumPoints", numpoints));
623 Init(start, end, cluster, numpoints);
624 }
625
ClusterGrid(double start,double end,double cluster,int numpoints)626 ClusterGrid(double start, double end, double cluster, int numpoints) { Init(start, end, cluster, numpoints); }
ClusterGrid()627 ClusterGrid()
628 { /* Do nothing */
629 }
630 };
631
632
ReadGrid(IOSectionClass & inSection)633 inline Grid* ReadGrid(IOSectionClass& inSection)
634 {
635 std::string Type;
636 assert(inSection.ReadVar("Type", Type));
637
638 Grid* newGrid;
639 if (Type == "Linear")
640 newGrid = new LinearGrid;
641 else if (Type == "General")
642 newGrid = new GeneralGrid;
643 else if (Type == "Optimal")
644 newGrid = new OptimalGrid;
645 else if (Type == "Optimal2")
646 newGrid = new OptimalGrid2;
647 else if (Type == "Log")
648 newGrid = new LogGrid;
649 else if (Type == "Cluster")
650 newGrid = new ClusterGrid;
651 else
652 {
653 std::cerr << "Unrecognized Grid type " << Type << "\n";
654 exit(1);
655 }
656 newGrid->Read(inSection);
657 return (newGrid);
658 }
659
660
CheckRoundingMode()661 inline void LinearGrid::CheckRoundingMode()
662 {
663 for (int i = 0; i < 100; i++)
664 {
665 double x = 100.0 * drand48() - 50.0;
666 if (nearbyint(x) != round(x))
667 {
668 std::cerr << "Error in rounding mode detected in LinearGrid. Abort.\n";
669 abort();
670 }
671 }
672 }
673
674
675 #endif
676