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