QMCPACK
ECPComponentBuilder_L2.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) 2016 Jeongnim Kim and QMCPACK developers.
6 //
7 // File developed by: Jaron T. Krogel, krogeljt@ornl.gov, Oak Ridge National Laboratory
8 //
9 // File created by: Jaron T. Krogel, krogeljt@ornl.gov, Oak Ridge National Laboratory
10 //////////////////////////////////////////////////////////////////////////////////////
11 
12 
14 namespace qmcplusplus
15 {
16 void ECPComponentBuilder::buildL2(xmlNodePtr cur)
17 {
18  // report to log and check for global grid (pseudo/grid)
19  app_log() << " ECPComponentBuilder::buildL2 " << std::endl;
20  if (grid_global == 0)
21  {
22  app_error() << " Global grid needs to be defined." << std::endl;
23  myComm->barrier_and_abort("ECPComponentBuilder::buildL2");
24  }
25 
26  // read <L2> attributes
27  std::string eunits = "hartree";
28  std::string format = "r*V";
29  RealType rcut = -1.0;
30  OhmmsAttributeSet attrib;
31  attrib.add(eunits, "units");
32  attrib.add(format, "format");
33  attrib.add(rcut, "cutoff");
34  attrib.put(cur);
35 
36  // check validity of <L2> attributes
37  RealType Vprefactor = 1.0;
38  if (eunits.find("ydberg") < eunits.size())
39  {
40  app_log() << " Input energy unit = Rydberg " << std::endl;
41  Vprefactor = 0.5;
42  }
43  else
44  {
45  app_log() << " Assuming Hartree unit" << std::endl;
46  }
47  bool is_r_times_V(true);
48  if (format == "r*V")
49  is_r_times_V = true;
50  else if (format == "V")
51  is_r_times_V = false;
52  else
53  {
54  app_error() << " Unrecognized format \"" << format << "\" in PP file." << std::endl;
55  myComm->barrier_and_abort("ECPComponentBuilder::buildL2");
56  }
57  if (rcut < 0.0)
58  {
59  app_error() << " L2 attribute cutoff is missing or negative. Cutoff must be a positive real number." << std::endl;
60  myComm->barrier_and_abort("ECPComponentBuilder::buildL2");
61  }
62  int npts = grid_global->size();
63 
64  // read in the data
65  std::vector<RealType> vL2in(npts);
66  xmlNodePtr c = cur->children;
67  while (c != NULL)
68  {
69  if (xmlStrEqual(c->name, (const xmlChar*)"radfunc"))
70  {
71  xmlNodePtr c1 = c->children;
72  while (c1 != NULL)
73  {
74  if (xmlStrEqual(c1->name, (const xmlChar*)"data"))
75  putContent(vL2in, c1);
76  c1 = c1->next;
77  }
78  }
79  c = c->next;
80  }
81 
82  // convert to r*V if needed
83  if (!is_r_times_V)
84  {
85  app_log() << " Input pseudopotential is converted into r*V" << std::endl;
86  for (int i = 0; i < npts; i++)
87  vL2in[i] *= grid_global->r(i);
88  }
89 
90  // create a new grid with maximum extent set to the cutoff radius
91  RealType rmax = rcut;
92  const int max_points = 100000;
93  app_log() << " Creating a Linear Grid Rmax=" << rmax << std::endl;
94  auto grid = std::make_unique<LinearGrid<RealType>>();
95  RealType d = 1e-4;
96  int ng;
97  if (grid_global->getGridTag() == LINEAR_1DGRID)
98  {
99  ng = (int)std::ceil(rmax * grid_global->DeltaInv) + 1;
100  if (ng <= max_points)
101  {
102  app_log() << " Using global grid with delta = " << grid_global->Delta << std::endl;
103  rmax = grid_global->Delta * (ng - 1);
104  grid->set(0.0, rmax, ng);
105  }
106  else
107  grid->set(0.0, rmax, max_points);
108  }
109  else
110  {
111  ng = std::min(max_points, static_cast<int>(rmax / d) + 1);
112  grid->set(0, rmax, ng);
113  }
114  d = grid->Delta;
115 
116  // follow doBreakUp and reinterpolate the data
117  // likely necessary for data inputted on other than a linear grid
118  // but seems extraneous for data on linear grid (most common case)
119  int ngIn = npts - 2;
120  std::vector<RealType> new_vL2(ng);
121  std::vector<RealType> new_vL2in(ngIn);
122  for (int i = 0; i < ngIn; i++)
123  new_vL2in[i] = Vprefactor * vL2in[i];
124  OneDimCubicSpline<mRealType> infunc(grid_global->makeClone(), new_vL2in);
125  infunc.spline(0, 0.0, ngIn - 1, 0.0);
126  for (int i = 1; i < ng - 1; i++)
127  {
128  RealType r = d * i;
129  new_vL2[i] = infunc.splint(r) / r;
130  }
131  new_vL2[0] = new_vL2[1];
132  new_vL2[ng - 1] = 0.0;
133  auto vL2 = std::make_unique<RadialPotentialType>(std::move(grid), new_vL2);
134  vL2->spline();
135 
136  // save the splined L2 potential
137  pp_L2 = std::make_unique<L2RadialPotential>();
138  pp_L2->vL2 = std::move(vL2);
139  pp_L2->rcut = rcut;
140 
141  //app_log()<<std::endl;
142  //for(int i=0;i<ng;i++)
143  // app_log()<<d*i<<" "<<pp_L2->vL2->splint(d*i)*d*i<<std::endl;
144  //app_log()<<std::endl;
145  //app_log()<<pp_L2->rcut;
146  //APP_ABORT("here");
147 }
148 
149 } // namespace qmcplusplus
helper functions for EinsplineSetBuilder
Definition: Configuration.h:43
QTBase::RealType RealType
Definition: Configuration.h:58
std::ostream & app_log()
Definition: OutputManager.h:65
bool put(xmlNodePtr cur)
assign attributes to the set
Definition: AttributeSet.h:55
std::ostream & app_error()
Definition: OutputManager.h:67
void spline(int imin, value_type yp1, int imax, value_type ypn) override
Evaluate the 2nd derivative on the grid points.
T min(T a, T b)
std::unique_ptr< mGridType > grid_global
MakeReturn< UnaryNode< FnCeil, typename CreateLeaf< Vector< T1, C1 > >::Leaf_t > >::Expression_t ceil(const Vector< T1, C1 > &l)
Communicate * myComm
pointer to Communicate
Definition: MPIObjectBase.h:62
Declaration of a builder class for an ECP component for an ionic type.
class to handle a set of attributes of an xmlNode
Definition: AttributeSet.h:24
bool putContent(T &a, xmlNodePtr cur)
replaces a&#39;s value with the first "element" in the "string" returned by XMLNodeString{cur}.
Definition: libxmldefs.h:88
std::unique_ptr< L2RadialPotential > pp_L2
void barrier_and_abort(const std::string &msg) const
void add(PDT &aparam, const std::string &aname, std::vector< PDT > candidate_values={}, TagStatus status=TagStatus::OPTIONAL)
add a new attribute
Definition: AttributeSet.h:42