MADNESS  version 0.9
gth_pseudopotential.h
Go to the documentation of this file.
1 //#define WORLD_INSTANTIATE_STATIC_TEMPLATES
2 
3 #include <madness/mra/mra.h>
5 
6 //using namespace madness;
7 
8 #include <chem/molecule.h>
9 #include <chem/molecularbasis.h>
10 #include <chem/xcfunctional.h>
11 
12 namespace madness {
13 
14 typedef Tensor<double> tensorT;
15 
16 double get_charge_from_file(const std::string filename, unsigned int atype);
17 
18 /*template <typename Q, int NDIM>
19 struct function_real2complex_op
20 {
21  typedef std::complex<Q> resultT;
22  Tensor<resultT> operator()(const Key<NDIM>& key, const Tensor<Q>& t) const
23  {
24  Tensor<resultT> result(t.ndim(), t.dims());
25  BINARY_OPTIMIZED_ITERATOR(const Q, t, resultT, result, *_p1 = resultT(*_p0,0.0););
26  return result;
27  }
28  template <typename Archive>
29  void serialize(Archive& ar) {}
30 };
31 
32 Function<std::complex<double>,3> function_real2complex(const Function<double,3>& r)
33 {
34  return unary_op_coeffs(r, function_real2complex_op<double,3>());
35 }*/
36 
37 class VLocalFunctor : public FunctionFunctorInterface<double,3> {
38 private:
39  double Zeff, zi, C1, C2, C3, C4;
40  coord_3d center;
41  std::vector<coord_3d> specialpts;
42 
43 public:
44  VLocalFunctor(double Zeff, double zi,
45  double C1, double C2, double C3, double C4, const coord_3d& center)
46  : Zeff(Zeff), zi(zi), C1(C1), C2(C2),
47  C3(C3), C4(C4), center(center) {
48  specialpts.push_back(center);
49  }
50 
51  double operator()(const coord_3d& r) const {
52  const double x = r[0]-center[0]; const double y = r[1]-center[1]; const double z = r[2]-center[2];
53  double rr = std::sqrt(x*x + y*y + z*z);
54  double rs = rr/zi;
55  double rs2 = rs*rs; double rs4 = rs2*rs2; double rs6 = rs2*rs4;
56  return -(Zeff/rr)*erf(rs/std::sqrt(2.0))
57  + std::exp(-0.5*rs2)*
58  (C1 + C2*rs2 + C3*rs4 + C4*rs6);
59  }
60 
61  std::vector<coord_3d> special_points() const {return specialpts;}
62 
64  return 6;
65  }
66 };
67 
68 class ProjRLMFunctor : public FunctionFunctorInterface<double,3> {
69 private:
70  double alpha; // radius
71  int l, m, i; // i = 1,2,3 and m = 0,1,2,3 and l = 0,1,2,3 (angular momentum)
72  coord_3d center;
73  std::vector<coord_3d> specialpts;
74  // gamma of half-integers starting and 1 (which means 1/2)
75  /*const double gamma_data[17] = {1.0, 0.0, 1.0/2.0, 0.0, 3.0/4.0, 0.0, 15.0/8.0, 0.0, 105.0/16.0, 0.0,
76  945.0/32.0, 0.0, 10395.0/64.0, 0.0, 135135.0/128.0, 0.0, 2027025.0/256.0};*/
77  double sqrtPI;
78  int itmp, itmp2;
79  double t1;
80 
81 public:
82 
83  virtual bool supports_vectorized() const {return false;}
84 
85  static const double gamma_data[17];
86 
87  ProjRLMFunctor(double alpha, int l, int m, int i, const coord_3d& center)
88  : alpha(alpha), l(l), m(m), i(i), center(center) {
89  specialpts.push_back(coord_3d(0.0));
90  sqrtPI = std::sqrt(constants::pi);
91  itmp = 2*l + (4*i-1);
92  itmp2 = 2*(i-1);
93  t1 = 1./std::pow(alpha, 0.5*(double)itmp)/std::sqrt(gamma_data[itmp-1]*sqrtPI);
94  }
95 
96  double operator()(const coord_3d& r) const {
97  double x = r[0]-center[0]; double y = r[1]-center[1]; double z = r[2]-center[2];
98  double rsq = x*x + y*y + z*z;
99 
100  if (rsq > 40.0) return 0.0;
101 
102  double rr = std::sqrt(rsq);
103  double rval = t1;
104  const double PI = constants::pi;
105  // Radial part
106  if (itmp2 == 0) {
107  rval *= std::sqrt(2);
108  }
109  else if (itmp2 == 1) {
110  rval *= rr*std::sqrt(2);
111  }
112  else if (itmp2 == 2) {
113  rval *= rsq*std::sqrt(2);
114  }
115  else if (itmp2 == 3) {
116  rval *= rr*rsq*std::sqrt(2);
117  }
118  else if (itmp2 == 4) {
119  rval *= rsq*rsq*std::sqrt(2);
120  }
121  else if (itmp2 == 5) {
122  rval *= rr*rsq*rsq*std::sqrt(2);
123  }
124  else if (itmp2 == 6) {
125  rval *= rsq*rsq*rsq*std::sqrt(2);
126  }
127  else if (itmp2 == 7) {
128  rval *= rr*rsq*rsq*rsq*std::sqrt(2);
129  }
130  // Angular part
131  if (l == 0) {
132  rval *= (1./2.)*std::sqrt(1./PI);
133  } else if (l == 1) {
134  if (m == 0) {
135  rval *= std::sqrt(3./4./PI)*x;
136  }
137  else if (m == 1) {
138  rval *= std::sqrt(3./4./PI)*y;
139  }
140  else if (m == 2) {
141  rval *= std::sqrt(3./4./PI)*z;
142  }
143  else {
144  MADNESS_EXCEPTION("m out of range for l = 1", 0);
145  }
146  } else if (l == 2) {
147  if (m == 0) {
148  rval *= (1./4.)*std::sqrt(5./PI)*(-x*x - y*y + 2*z*z);
149  }
150  else if (m == 1) {
151  rval *= (1./2.)*std::sqrt(15./PI)*(y*z);
152  }
153  else if (m == 2) {
154  rval *= (1./2.)*std::sqrt(15./PI)*(x*z);
155  }
156  else if (m == 3) {
157  rval *= (1./2.)*std::sqrt(15./PI)*(x*y);
158  }
159  else if (m == 4) {
160  rval *= (1./4.)*std::sqrt(15./PI)*(x*x - y*y);
161  }
162  else {
163  MADNESS_EXCEPTION("m out of range for l = 2", 0);
164  }
165  }
166  rval *= std::exp(-0.5*(rsq/alpha/alpha));
167  return rval;
168  }
169 
170  virtual bool screened(const coord_3d& c1, const coord_3d& c2) const {
171  double ftol = 1e-12;
172 
173  double x1 = c1[0]; double y1 = c1[1]; double z1 = c1[2];
174  double x2 = c2[0]; double y2 = c1[1]; double z2 = c1[2];
175 
176  // if center is inside box, then return false
177  // otherwise, look for the closests point and check
178  bool inside = (center[0] >= x1) && (center[0] <= x2) &&
179  (center[1] >= y1) && (center[1] <= y2) &&
180  (center[2] >= z1) && (center[2] <= z2);
181  if (inside) {
182  return false;
183  }
184  else {
185  //printf("GTH_pseudopotential: (point not inside)\n");
186  //print(" c1: ", c1, " c2: ", c2);
187  double minr = 1e10;
188  int ii = -1; int jj = -1; int kk = -1;
189  for (int i = 0; i <= 1; i++) {
190  for (int j = 0; j <= 1; j++) {
191  for (int k = 0; k <= 1; k++) {
192  double x = (i == 0) ? c1[0] : c2[0];
193  double y = (j == 0) ? c1[1] : c2[1];
194  double z = (k == 0) ? c1[2] : c2[2];
195  coord_3d rr = vec(x, y, z) - center;
196  double rsq = rr[0]*rr[0]+rr[1]*rr[1]+rr[2]*rr[2];
197  // print("current minr: ", minr, " point: ", vec(x,y,z), " center: ", center, " p: ", vec(x,y,z), " rsq: ", rsq);
198  if (minr > rsq) {
199  minr = rsq;
200  ii = i; jj = j; kk = k;
201  }
202  }
203  }
204  }
205  //print("ii: ", ii, "jj: ", jj, "kk: ", kk);
206  //printf("\n");
207  if ((ii < 0) || (jj < 0) || (kk < 0)) MADNESS_EXCEPTION("GTH_Pseudopotential: failed to find suitable minimum point\n", 0);
208  double x = (ii == 0) ? c1[0] : c2[0];
209  double y = (jj == 0) ? c1[1] : c2[1];
210  double z = (kk == 0) ? c1[2] : c2[2];
211  double fval = this->operator()(vec(x, y, z));
212  if (fval < ftol) return true;
213  else return false;
214  }
215  }
216 
217  virtual void operator()(const Vector<double*,3>& xvals, double* restrict fvals, int npts) const {
218 
219  double* x = new double[npts];
220  double* y = new double[npts];
221  double* z = new double[npts];
222  double* rsq = new double[npts];
223  double* rr = new double[npts];
224 
225  double* x1 = xvals[0]; double* x2 = xvals[1]; double* x3 = xvals[2];
226  for (int i = 0; i < npts; i++) {
227  x[i] = x1[i]-center[0];
228  y[i] = x2[i]-center[1];
229  z[i] = x3[i]-center[2];
230  rsq[i] = x[i]*x[i] + y[i]*y[i] + z[i]*z[i];
231  rr[i] = std::sqrt(rsq[i]);
232  fvals[i] = t1;
233  }
234 
235  const double PI = constants::pi;
236 
237  // Radial part
238  if (itmp2 == 0) {
239  for (int i = 0; i < npts; i++) {
240  fvals[i] *= std::sqrt(2);
241  }
242  }
243  else if (itmp2 == 1) {
244  for (int i = 0; i < npts; i++) {
245  fvals[i] *= rr[i]*std::sqrt(2);
246  }
247  }
248  else if (itmp2 == 2) {
249  for (int i = 0; i < npts; i++) {
250  fvals[i] *= rsq[i]*std::sqrt(2);
251  }
252  }
253  else if (itmp2 == 3) {
254  for (int i = 0; i < npts; i++) {
255  fvals[i] *= rr[i]*rsq[i]*std::sqrt(2);
256  }
257  }
258  else if (itmp2 == 4) {
259  for (int i = 0; i < npts; i++) {
260  fvals[i] *= rsq[i]*rsq[i]*std::sqrt(2);
261  }
262  }
263  else if (itmp2 == 5) {
264  for (int i = 0; i < npts; i++) {
265  fvals[i] *= rr[i]*rsq[i]*rsq[i]*std::sqrt(2);
266  }
267  }
268  else if (itmp2 == 6) {
269  for (int i = 0; i < npts; i++) {
270  fvals[i] *= rsq[i]*rsq[i]*rsq[i]*std::sqrt(2);
271  }
272  }
273  else if (itmp2 == 7) {
274  for (int i = 0; i < npts; i++) {
275  fvals[i] *= rr[i]*rsq[i]*rsq[i]*rsq[i];
276  }
277  }
278  // Angular part
279  if (l == 0) {
280  for (int i = 0; i < npts; i++) {
281  fvals[i] *= (1./2.)*std::sqrt(1./PI)*std::exp(-0.5*(rsq[i]/alpha/alpha));
282  }
283  } else if (l == 1) {
284  if (m == 0) {
285  for (int i = 0; i < npts; i++) {
286  fvals[i] *= std::sqrt(3./4./PI)*x[i]*std::exp(-0.5*(rsq[i]/alpha/alpha));
287  }
288  }
289  else if (m == 1) {
290  for (int i = 0; i < npts; i++) {
291  fvals[i] *= std::sqrt(3./4./PI)*y[i]*std::exp(-0.5*(rsq[i]/alpha/alpha));
292  }
293  }
294  else if (m == 2) {
295  for (int i = 0; i < npts; i++) {
296  fvals[i] *= std::sqrt(3./4./PI)*z[i]*std::exp(-0.5*(rsq[i]/alpha/alpha));
297  }
298  }
299  else {
300  MADNESS_EXCEPTION("m out of range for l = 1", 0);
301  }
302  } else if (l == 2) {
303  if (m == 0) {
304  for (int i = 0; i < npts; i++) {
305  fvals[i] *= (1./4.)*std::sqrt(5./PI)*(-x[i]*x[i] - y[i]*y[i] + 2*z[i]*z[i])*std::exp(-0.5*(rsq[i]/alpha/alpha));
306  }
307  }
308  else if (m == 1) {
309  for (int i = 0; i < npts; i++) {
310  fvals[i] *= (1./2.)*std::sqrt(15./PI)*(y[i]*z[i])*std::exp(-0.5*(rsq[i]/alpha/alpha));
311  }
312  }
313  else if (m == 2) {
314  for (int i = 0; i < npts; i++) {
315  fvals[i] *= (1./2.)*std::sqrt(15./PI)*(x[i]*z[i])*std::exp(-0.5*(rsq[i]/alpha/alpha));
316  }
317  }
318  else if (m == 3) {
319  for (int i = 0; i < npts; i++) {
320  fvals[i] *= (1./2.)*std::sqrt(15./PI)*(x[i]*y[i])*std::exp(-0.5*(rsq[i]/alpha/alpha));
321  }
322  }
323  else if (m == 4) {
324  for (int i = 0; i < npts; i++) {
325  fvals[i] *= (1./4.)*std::sqrt(15./PI)*(x[i]*x[i] - y[i]*y[i])*std::exp(-0.5*(rsq[i]/alpha/alpha));
326  }
327  }
328  else {
329  MADNESS_EXCEPTION("m out of range for l = 2", 0);
330  }
331  }
332  //for (int i = 0; i < npts; i++) {
333  // fvals[i] *= std::exp(-0.5*(rsq[i]/alpha/alpha));
334  //}
335 
336  delete [] x;
337  delete [] y;
338  delete [] z;
339  delete [] rsq;
340  delete [] rr;
341  }
342 
343  std::vector<coord_3d> special_points() const {return specialpts;}
344 
346  return 6;
347  }
348 };
349 
351 private:
352  int maxL;
353  real_tensor radii;
354  coord_3d center;
355 
356 public:
357  ProjRLMStore(const real_tensor& radii, const coord_3d& center)
358  : maxL(radii.dim(0)), radii(radii), center(center) {}
359 
360  real_function_3d nlmproj(World& world, int l, int m, int i) {
361  real_function_3d f1 = (m < 2*l+1) ?
362  real_factory_3d(world).functor(real_functor_3d(new ProjRLMFunctor(radii(l), l, m, i, center))).
363  truncate_on_project().nofence().truncate_mode(0) : real_factory_3d(world);
364  return f1;
365  }
366 
367  ProjRLMFunctor nlmproj_functor(World& world, int l, int m, int i) {
368  return ProjRLMFunctor(radii(l), l, m, i, center);
369  }
370 };
371 
372 template <typename Q>
374 private:
375 public:
382  std::vector<unsigned int> atoms_with_projectors;
383 
384 
385 public:
386  GTHPseudopotential(World& world, Molecule molecule) : molecule(molecule) {}
387 
389  // Load info from file
390  load_pseudo_from_file(world, "gth.xml");
391  atoms_with_projectors.clear();
392 
393  // fill list with atoms-with-projectors (i.e. not H or He)
394  for (int iatom = 0; iatom < molecule.natom(); iatom++) {
395  Atom atom = molecule.get_atom(iatom);
396  unsigned int atype = atom.atomic_number;
397  if (radii[atype-1].dim(0) > 0)
398  atoms_with_projectors.push_back(iatom);
399  }
400 
401  vlocalp = real_factory_3d(world);
402  vlocalp.compress();
403  for (int iatom = 0; iatom < molecule.natom(); iatom++) {
404  // Get atom and it's associated GTH tensors
405  Atom atom = molecule.get_atom(iatom);
406  coord_3d center = atom.get_coords();
407  unsigned int atype = atom.atomic_number;
408  // do local part
409  real_tensor atom_localp = localp[atype-1];
410  real_function_3d temp = real_factory_3d(world).functor(
411  real_functor_3d(new
412  VLocalFunctor(atom_localp[0], atom_localp[1], atom_localp[2], atom_localp[3], atom_localp[4], atom_localp[5], center))).
413  truncate_mode(0).truncate_on_project();
414  temp.compress();
415  //vlocalp += temp;
416  vlocalp.gaxpy(1.0, temp, 1.0, true);
417  }
418  }
419 
421  return vlocalp;
422  }
423 
424  void reproject(int k, double thresh) {
425  vlocalp = madness::project(vlocalp, k, thresh, true);
426  }
427 
428  void load_pseudo_from_file(World& world, const std::string filename) {
429  bool debug = true;
430 
431  TiXmlDocument doc(filename);
432  if (!doc.LoadFile()) {
433  MADNESS_EXCEPTION("Failed to load GTH pseudopotential file", 0);
434  }
435 
436  for (int iatom = 0; iatom < molecule.natom(); iatom++) {
437  Atom atom = molecule.get_atom(iatom);
438  unsigned int atype = atom.atomic_number;
439  if (debug && world.rank() == 0) {printf("atom atomic_number = %d\n", atype);}
440 
441  bool success = false;
442  for (TiXmlElement* node=doc.FirstChildElement(); node && !success; node=node->NextSiblingElement()) {
443  if (strcmp(node->Value(),"name") == 0) {
444  std::string name = node->GetText();
445  if (debug && world.rank() == 0) std::cout << "Loading pseudopotential file " << name << std::endl;
446  }
447  else if (strcmp(node->Value(), "atom") == 0) {
448  const char* symbol = node->Attribute("symbol");
449  unsigned int atn = symbol_to_atomic_number(symbol);
450  if (atype == atn) {
451  success = true;
452  if (debug && world.rank() == 0) std::cout << " found atomic pseudopotential " << symbol << std::endl;
453  int lmax = -1;
454  node->Attribute("lmax", &lmax);
455  if (debug && world.rank() == 0) std::cout << " maximum L is " << lmax << std::endl;
456  real_tensor t_radii((long)lmax+1);
457  real_tensor t_hlij((long)lmax+1, (long)3, (long)3);
458  real_tensor t_klij((long)lmax+1, (long)3, (long)3);
459  // local part
460  TiXmlElement* xmlVLocal = node->FirstChildElement();
461  real_tensor t_localp((long)6);
462  double zeff = 0.0; xmlVLocal->Attribute("Zeff", &zeff); t_localp[0] = zeff;
463  double lradius = 0.0; xmlVLocal->Attribute("radius", &lradius); t_localp(1) = lradius;
464  double C1 = 0.0; xmlVLocal->Attribute("C1", &C1); t_localp[2] = C1;
465  double C2 = 0.0; xmlVLocal->Attribute("C2", &C2); t_localp[3] = C2;
466  double C3 = 0.0; xmlVLocal->Attribute("C3", &C3); t_localp[4] = C3;
467  double C4 = 0.0; xmlVLocal->Attribute("C4", &C4); t_localp[5] = C4;
468  // loop through nonlocal part
469  for (TiXmlElement* xmlLnlproj = xmlVLocal->NextSiblingElement();
470  xmlLnlproj; xmlLnlproj=xmlLnlproj->NextSiblingElement()) {
471  int lvalue = -1; xmlLnlproj->Attribute("l", &lvalue);
472  double radius = 0.0; xmlLnlproj->Attribute("radius", &radius); t_radii[lvalue] = radius;
473  double h00 = 0.0; xmlLnlproj->Attribute("h00", &h00); t_hlij(lvalue, 0, 0) = h00;
474  double h11 = 0.0; xmlLnlproj->Attribute("h11", &h11); t_hlij(lvalue, 1, 1) = h11;
475  double h22 = 0.0; xmlLnlproj->Attribute("h22", &h22); t_hlij(lvalue, 2, 2) = h22;
476  double k00 = 0.0; xmlLnlproj->Attribute("k00", &k00); t_klij(lvalue, 0, 0) = k00;
477  double k11 = 0.0; xmlLnlproj->Attribute("k11", &k11); t_klij(lvalue, 1, 1) = k11;
478  double k22 = 0.0; xmlLnlproj->Attribute("k22", &k22); t_klij(lvalue, 2, 2) = k22;
479  }
480  // off-diagonal elements
481  if (lmax >= 0) {
482  t_hlij(0, 0, 1) = -1./2.*std::sqrt(3./5.)*t_hlij(0, 1, 1);
483  t_hlij(0, 1, 0) = t_hlij(0, 0, 1);
484  t_hlij(0, 0, 2) = 1./2.*std::sqrt(5./21.)*t_hlij(0, 2, 2);
485  t_hlij(0, 2, 0) = t_hlij(0, 0, 2);
486  t_hlij(0, 1, 2) = -1./2.*std::sqrt(100./63.)*t_hlij(0, 2, 2);
487  t_hlij(0, 2, 1) = t_hlij(0, 1, 2);
488  } if (lmax >= 1) {
489  t_hlij(1, 0, 1) = -1./2.*std::sqrt(5./7.)*t_hlij(1, 1, 1);
490  t_hlij(1, 1, 0) = t_hlij(1, 0, 1);
491  t_hlij(1, 0, 2) = 1./6.*std::sqrt(35./11.)*t_hlij(1, 2, 2);
492  t_hlij(1, 2, 0) = t_hlij(1, 0, 2);
493  t_hlij(1, 1, 2) = -1./6.*14./std::sqrt(11.)*t_hlij(1, 2, 2);
494  t_hlij(1, 2, 1) = t_hlij(1, 1, 2);
495  } if (lmax >= 2) {
496  t_hlij(2, 0, 1) = -1./2.*std::sqrt(7./9.)*t_hlij(2, 1, 1);
497  t_hlij(2, 1, 0) = t_hlij(2, 0, 1);
498  t_hlij(2, 0, 2) = 1./2.*std::sqrt(63./143.)*t_hlij(2, 2, 2);
499  t_hlij(2, 2, 0) = t_hlij(2, 0, 2);
500  t_hlij(2, 1, 2) = -1./2.*18./std::sqrt(143.)*t_hlij(2, 2, 2);
501  t_hlij(2, 2, 1) = t_hlij(2, 1, 2);
502  }
503 
504  // Copy to main array
505  localp[atype-1] = t_localp;
506  radii[atype-1] = t_radii;
507  hlij[atype-1] = t_hlij;
508  klij[atype-1] = t_klij;
509  }
510  }
511  }
512  }
513  }
514 
515 
516  std::vector<Function<Q,3> > apply_potential(World& world, const real_function_3d& potential, const std::vector<Function<Q,3> >& psi, const tensorT & occ, Q & enl) {
517  bool debug = (world.rank() == 0) && false;
519  double vtol = 1e-2*thresh;
520  std::vector<Function<Q,3> > vpsi = mul_sparse(world,(potential), psi, vtol);
521 
522  unsigned int norbs = psi.size();
523  unsigned int natoms = atoms_with_projectors.size();
524 
525  // NEW (VECTORIZED) ... hopefully
526  vector_real_function_3d localproj;
527  int lidx = 0;
528  unsigned int maxLL = 0;
529  // loop through all of the atom types in the molecule and get the maximum L value
530  // we need this because we are going to create a fixed sized tensor to store
531  // mapping between a linear index and (ias=which atom, i=which projector, l=angular momentum,
532  // m=angular momentum projection)
533  for (unsigned int iatom = 0; iatom < natoms; iatom++) {
534  // Get atom and its associated GTH tensors
535  Atom atom = molecule.get_atom(atoms_with_projectors[iatom]);
536  unsigned int atype = atom.atomic_number;
537  real_tensor& atom_radii = radii[atype-1];
538  if (atom_radii.dim(0) > 0)
539  maxLL = std::max(maxLL,(unsigned int)atom_radii.dim(0)-1);
540  }
541 
542  // Pilm_lookup is a mapping between a linear index and (ias,i,l,m)
543  Tensor<int> Pilm_lookup((unsigned int) natoms, (unsigned long) 3, (unsigned long) maxLL+1, (unsigned long) 2*maxLL+1);
544  for (unsigned int iatom = 0; iatom < natoms; iatom++) {
545  // Get atom and its associated GTH tensors
546  Atom atom = molecule.get_atom(atoms_with_projectors[iatom]);
547  coord_3d center = atom.get_coords();
548  unsigned int atype = atom.atomic_number;
549  real_tensor& atom_radii = radii[atype-1];
550  real_tensor& atom_hlij = hlij[atype-1];
551 
552  // Create function stores for projectors
553  ProjRLMStore prlmstore(atom_radii, center);
554  for (unsigned int j = 1; j <= 3; j++) {
555  for (unsigned int l = 0; l <= maxLL; l++) {
556  for (unsigned int m = 0; m < 2*maxLL+1; m++) {
557  Pilm_lookup(iatom, j-1, l, m) = lidx++;
558  if (m < 2*l+1) localproj.push_back(prlmstore.nlmproj(world,l,m,j));
559  else localproj.push_back(real_factory_3d(world));
560  }
561  }
562  }
563  // Somehow this scares me ... thread-safety of the container localproj (???)
564  world.gop.fence();
565  }
566  truncate(world, localproj, FunctionDefaults<3>::get_thresh());
567  compress(world, localproj);
568  //truncate(world, psi, FunctionDefaults<3>::get_thresh());
569  compress(world, psi);
570  //truncate(world, vpsi, FunctionDefaults<3>::get_thresh());
571  compress(world, vpsi);
572 
573  Tensor<Q> Pilm = matrix_inner(world, localproj, psi);
574  Pilm = Pilm.reshape(natoms, 3, maxLL+1, 2*maxLL+1, norbs);
575 
576  Tensor<Q> Qilm((unsigned int) natoms, (unsigned long) 3, (unsigned long) maxLL+1, (unsigned long) 2*maxLL+1, (unsigned int) norbs);
577  for (unsigned int iorb=0; iorb<psi.size(); iorb++) {
578  for (unsigned int iatom = 0; iatom < natoms; iatom++) {
579  // Get atom and its associated GTH tensors
580  Atom atom = molecule.get_atom(atoms_with_projectors[iatom]);
581  unsigned int atype = atom.atomic_number;
582  real_tensor& atom_radii = radii[atype-1];
583  real_tensor& atom_hlij = hlij[atype-1];
584  int maxL = atom_radii.dim(0)-1;
585  for (unsigned int i = 1; i <= 3; i++) {
586  for (int l = 0; l <= maxL; l++) {
587  for (int m = 0; m < 2*l+1; m++) {
588  Q s = 0.0;
589  for (unsigned int j = 1; j <= 3; j++) {
590  s += atom_hlij(l,i-1,j-1)*Pilm(iatom, j-1,l,m,iorb);
591  }
592  Qilm(iatom, i-1,l,m,iorb) = s;
593  }
594  }
595  }
596  }
597  }
598  Qilm = Qilm.reshape(natoms*3*(maxLL+1)*(2*maxLL+1),norbs);
599 
600  double vtol2 = 1e-4*thresh;
601  double trantol = vtol2 / std::min(30.0, double(localproj.size()));
602  vector_real_function_3d dpsi = transform(world, localproj, Qilm, trantol, true);
603 
604  // calculate non-local energy
605  tensorT nlmat = matrix_inner(world, dpsi, psi, true);
606  int nocc = occ.size();
607  enl = 0.0;
608  for(int i = 0;i < nocc;++i){
609  enl += occ[i] * nlmat(i, i);
610  }
611 
612  //test
613  /*tensorT lmat = matrix_inner(world, vpsi, psi, true);
614  Q el = 0.0;
615  for(int i = 0;i < nocc;++i){
616  el += occ[i] * lmat(i, i);
617  }
618 
619  if(world.rank() == 0){
620  printf("\n enl, el, epot %16.8f %16.8f %16.8f\n", enl, el, enl+el);
621  }*/
622 
623  gaxpy(world, 1.0, vpsi, 1.0, dpsi);
624 
625  return vpsi;
626  }
627 
628  std::vector<Function<Q,3> > apply_potential_simple(World& world, const real_function_3d& potential, const std::vector<Function<Q,3> >& psi, const tensorT & occ, Q & enl) {
629  bool debug = (world.rank() == 0) && false;
631  double vtol = 1e-2*thresh;
632  std::vector<Function<Q,3> > vpsi = mul_sparse(world,(potential), psi, vtol);
633 
634  unsigned int norbs = psi.size();
635  unsigned int natoms = atoms_with_projectors.size();
636 
637  for (unsigned int iatom = 0; iatom < natoms; iatom++) {
638  Atom atom = molecule.get_atom(atoms_with_projectors[iatom]);
639  unsigned int atype = atom.atomic_number;
640  real_tensor& atom_radii = radii[atype-1];
641  real_tensor& atom_hlij = hlij[atype-1];
642  coord_3d center = atom.get_coords();
643  ProjRLMStore prlmstore(atom_radii, center);
644  unsigned int maxLL = atom_radii.dim(0)-1;
645  for (unsigned int l = 0; l <= maxLL; l++) {
646  for (unsigned int m = 0; m < 2*l+1; m++) {
647  for (unsigned int i = 1; i <= 3; i++) {
648  real_function_3d fproji = prlmstore.nlmproj(world,l,m,i);
649  for (unsigned int j = 1; j <= 3; j++) {
650  real_function_3d fprojj = prlmstore.nlmproj(world,l,m,j);
651  for (unsigned int iorb = 0; iorb < psi.size(); iorb++) {
652  double val = atom_hlij(l,i-1,j-1)*(fprojj.inner(psi[iorb]));
653  if (std::abs(val) > vtol*1e-2) {
654  vpsi[iorb] += val*fproji;
655  }
656  }
657  }
658  }
659  }
660  }
661  }
662  return vpsi;
663  }
664 };
665 
666 
667 
668 
669 }
void make_pseudo_potential(World &world)
Definition: gth_pseudopotential.h:388
void matrix_inner(DistributedMatrix< T > &A, const std::vector< Function< T, NDIM > > &f, const std::vector< Function< T, NDIM > > &g, bool sym=false)
Definition: chem/distpm.cc:38
const double thresh
Definition: dielectric.cc:185
std::vector< unsigned int > atoms_with_projectors
Definition: gth_pseudopotential.h:382
WorldGopInterface & gop
Global operations.
Definition: worldfwd.h:462
const mpreal exp(const mpreal &v, mp_rnd_t rnd_mode)
Definition: mpreal.h:2234
static const double gamma_data[17]
Definition: gth_pseudopotential.h:85
const double pi
Mathematical constant pi.
Definition: constants.h:44
ProjRLMStore(const real_tensor &radii, const coord_3d &center)
Definition: gth_pseudopotential.h:357
const mpreal erf(const mpreal &v, mp_rnd_t rnd_mode)
Definition: mpreal.h:2457
std::array< real_tensor, 118 > radii
Definition: gth_pseudopotential.h:378
Main include file for MADNESS and defines Function interface.
std::array< real_tensor, 118 > klij
Definition: gth_pseudopotential.h:380
FunctionDefaults holds default paramaters as static class members.
Definition: funcdefaults.h:175
void gaxpy(World &world, Q alpha, std::vector< Function< T, NDIM > > &a, Q beta, const std::vector< Function< R, NDIM > > &b, bool fence=true)
Generalized A*X+Y for vectors of functions -— a[i] = alpha*a[i] + beta*b[i].
Definition: vmra.h:680
Definition: gth_pseudopotential.h:373
const Function< T, NDIM > & compress(bool fence=true) const
Compresses the function, transforming into wavelet basis. Possible non-blocking comm.
Definition: mra.h:683
const bool debug
Definition: tdse1.cc:45
Definition: gth_pseudopotential.h:350
const mpreal dim(const mpreal &a, const mpreal &b, mp_rnd_t rnd_mode)
Definition: mpreal.h:2201
double operator()(const coord_3d &r) const
Definition: gth_pseudopotential.h:96
void truncate(World &world, std::vector< Function< T, NDIM > > &v, double tol=0.0, bool fence=true)
Truncates a vector of functions.
Definition: vmra.h:194
::std::string string
Definition: gtest-port.h:872
double get_charge_from_file(const std::string filename, unsigned int atype)
Definition: gth_pseudopotential.cc:8
Vector< double, 3 > coord_3d
Definition: funcplot.h:634
VLocalFunctor(double Zeff, double zi, double C1, double C2, double C3, double C4, const coord_3d &center)
Definition: gth_pseudopotential.h:44
madness::Vector< double, 3 > get_coords() const
Definition: chem/molecule.h:71
static const double & get_thresh()
Returns the default threshold.
Definition: funcdefaults.h:225
std::vector< coord_3d > special_points() const
Override this to return list of special points to be refined more deeply.
Definition: gth_pseudopotential.h:343
bool LoadFile(TiXmlEncoding encoding=TIXML_DEFAULT_ENCODING)
Definition: tinyxml.cc:924
std::vector< real_function_3d > vector_real_function_3d
Definition: functypedefs.h:79
virtual void operator()(const Vector< double *, 3 > &xvals, double *restrict fvals, int npts) const
Definition: gth_pseudopotential.h:217
Level special_level()
Override this change level refinement for special points (default is 6)
Definition: gth_pseudopotential.h:63
ProjRLMFunctor(double alpha, int l, int m, int i, const coord_3d &center)
Definition: gth_pseudopotential.h:87
double operator()(const coord_3d &r) const
Definition: gth_pseudopotential.h:51
int natom() const
Definition: chem/molecule.h:148
std::vector< coord_3d > special_points() const
Override this to return list of special points to be refined more deeply.
Definition: gth_pseudopotential.h:61
std::array< real_tensor, 118 > localp
Definition: gth_pseudopotential.h:377
#define max(a, b)
Definition: lda.h:53
Definition: gth_pseudopotential.h:37
Vector< T, 1 > vec(T x)
Your friendly neighborhood factory function.
Definition: array.h:456
const int k
Definition: dielectric.cc:184
ProjRLMFunctor nlmproj_functor(World &world, int l, int m, int i)
Definition: gth_pseudopotential.h:367
Level special_level()
Override this change level refinement for special points (default is 6)
Definition: gth_pseudopotential.h:345
real_function_3d vlocalp
Definition: gth_pseudopotential.h:381
const mpreal min(const mpreal &x, const mpreal &y)
Definition: mpreal.h:2675
Definition: tinyxml.h:1386
const TiXmlElement * FirstChildElement() const
Convenience function to get through elements.
Definition: tinyxml.cc:431
double psi(const Vector< double, 3 > &r)
Definition: apps/ii/hatom_energy.cc:42
unsigned int atomic_number
Atomic number.
Definition: chem/molecule.h:58
Tensor< double > tensorT
Definition: chem/distpm.cc:13
virtual bool screened(const coord_3d &c1, const coord_3d &c2) const
Definition: gth_pseudopotential.h:170
void load_pseudo_from_file(World &world, const std::string filename)
Definition: gth_pseudopotential.h:428
std::array< real_tensor, 118 > hlij
Definition: gth_pseudopotential.h:379
Tensor< double > real_tensor
Definition: functypedefs.h:40
tensorT sqrt(const tensorT &s, double tol=1e-8)
Computes matrix square root (not used any more?)
Definition: DFcode/moldft.cc:446
A parallel world with full functionality wrapping an MPI communicator.
Definition: worldfwd.h:416
void fence()
Synchronizes all processes in communicator AND globally ensures no pending AM or tasks.
Definition: worldgop.cc:52
std::shared_ptr< FunctionFunctorInterface< double, 3 > > real_functor_3d
Definition: functypedefs.h:107
double potential(const coord_3d &r)
Definition: 3dharmonic.cc:133
void reproject(int k, double thresh)
Definition: gth_pseudopotential.h:424
Definition: chem/molecule.h:55
int Level
Definition: key.h:58
const TiXmlElement * NextSiblingElement() const
Definition: tinyxml.cc:461
virtual bool supports_vectorized() const
Does the interface support a vectorized operator()?
Definition: gth_pseudopotential.h:83
Abstract base class interface required for functors used as input to Functions.
Definition: function_interface.h:58
const double m
Definition: gfit.cc:199
ProcessID rank() const
Returns the process rank in this world (same as MPI_Comm_rank()))
Definition: worldfwd.h:526
Function< TENSOR_RESULT_TYPE(L, R), NDIM > mul_sparse(const Function< L, NDIM > &left, const Function< R, NDIM > &right, double tol, bool fence=true)
Sparse multiplication — left and right must be reconstructed and if tol!=0 have tree of norms alread...
Definition: mra.h:1569
unsigned int symbol_to_atomic_number(const std::string &symbol)
Definition: chem/atomutil.cc:166
Definition: chem/molecule.h:83
Definition: gth_pseudopotential.h:68
std::vector< Function< Q, 3 > > apply_potential(World &world, const real_function_3d &potential, const std::vector< Function< Q, 3 > > &psi, const tensorT &occ, Q &enl)
Definition: gth_pseudopotential.h:516
Function< T, NDIM > & gaxpy(const T &alpha, const Function< Q, NDIM > &other, const R &beta, bool fence=true)
Inplace, general bi-linear operation in wavelet basis. No communication except for optional fence...
Definition: mra.h:924
real_function_3d nlmproj(World &world, int l, int m, int i)
Definition: gth_pseudopotential.h:360
GTHPseudopotential(World &world, Molecule molecule)
Definition: gth_pseudopotential.h:386
Molecule molecule
Definition: gth_pseudopotential.h:376
const T1 & f1
Definition: gtest-tuple.h:680
FunctionFactory< double, 3 > real_factory_3d
Definition: functypedefs.h:93
Function< T, NDIM > project(const Function< T, NDIM > &other, int k=FunctionDefaults< NDIM >::get_k(), double thresh=FunctionDefaults< NDIM >::get_thresh(), bool fence=true)
Definition: mra.h:2162
#define MADNESS_EXCEPTION(msg, value)
Definition: worldexc.h:88
#define restrict
Definition: config.h:403
Holds machinery to set up Functions/FuncImpls using various Factories and Interfaces.
Definition: chem/atomutil.cc:45
const char * Attribute(const char *name) const
Definition: tinyxml.cc:555
std::vector< Function< TENSOR_RESULT_TYPE(T, R), NDIM > > transform(World &world, const std::vector< Function< T, NDIM > > &v, const DistributedMatrix< R > &c, bool fence=true)
Definition: chem/SCF.cc:86
const Atom & get_atom(unsigned int i) const
Definition: chem/molecule.cc:223
real_function_3d vlocalpot()
Definition: gth_pseudopotential.h:420
std::vector< Function< Q, 3 > > apply_potential_simple(World &world, const real_function_3d &potential, const std::vector< Function< Q, 3 > > &psi, const tensorT &occ, Q &enl)
Definition: gth_pseudopotential.h:628
Definition: tinyxml.h:945
void compress(World &world, const std::vector< Function< T, NDIM > > &v, bool fence=true)
Compress a vector of functions.
Definition: vmra.h:130
const double PI
Definition: projPsi.cc:68