MADNESS 0.10.1
correlationfactor.h
Go to the documentation of this file.
1/*
2 This file is part of MADNESS.
3
4 Copyright (C) 2007,2010 Oak Ridge National Laboratory
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
20 For more information please contact:
21
22 Robert J. Harrison
23 Oak Ridge National Laboratory
24 One Bethel Valley Road
25 P.O. Box 2008, MS-6367
26
27 email: harrisonrj@ornl.gov
28 tel: 865-241-3937
29 fax: 865-572-0680
30*/
31
32/*!
33 \file apps/chem/correlationfactor.h
34 \brief class for regularizing singular potentials in the molecular
35 Hamilton operator
36
37 \par Introduction
38
39 The correlation factors are intended to represent the cusps (nuclear or
40 electronic) in the molecular wave function. Their commutator over the
41 kinetic energy operator give a potential operator that cancels the
42 singular potential
43
44 [T, f12] = U + 1/r12
45 R^-1[T, R] = U_nuc - sum_A Z_A/r1A
46
47 The regularized potentials U and U_nuc contain two terms each, a local
48 potential, (denoted U2), and a potential that is multiplied with the
49 derivative operator \nabla (denoted U1)
50
51 U = U1 . (\nabla_1 - \nabla_2) + U2
52 U_nuc = U1 . \nabla + U2
53
54 with
55
56 U2 = (\nabla^2 f12)
57 U2 = R^{-1}(\nabla^2 R)
58
59 \vec U1 = (\vec \nabla f12)
60 \vec U1 = R^{-1}(\vec \nabla R)
61
62 To construct a nuclear correlation factor write:
63
64 std::shared_ptr<NuclearCorrelationFactor> nuclear_correlation
65 = create_nuclear_correlation_factor(world,*calc);
66
67 where calc is an SCF calculation which holds the molecule and the
68 nuclear_corrfac parameter name.
69*/
70
71
72#ifndef MADNESS_CHEM_NUCLEARCORRELATIONFACTOR_H_
73#define MADNESS_CHEM_NUCLEARCORRELATIONFACTOR_H_
74
75#include <madness/mra/mra.h>
79#include <algorithm>
80#include <limits>
81#include <numeric>
82
83namespace madness {
84
85/// ABC for the nuclear correlation factors
87public:
90 typedef std::shared_ptr< FunctionFunctorInterface<double,3> > functorT;
91
92 /// ctor
93
94 /// @param[in] world the world
95 /// @param[in] mol molecule with the sites of the nuclei
97 : world(world), vtol(FunctionDefaults<3>::get_thresh()*0.1)
98 , eprec(mol.get_eprec()), molecule(mol), all_atoms_(mol.natom()) {
99 std::iota(all_atoms_.begin(),all_atoms_.end(),0);
100 }
101
102 /// virtual destructor
104
105 /// projection depth of the factor's functions at the nuclei
106
107 /// The functors' default (6) can miss the exp(-a Z r) features, of width 1/(aZ), at a loose threshold for
108 /// Z above ~30: on NBr3 and PBr3 the k6 rung then starts hundreds of hartree off and never converges. 15 is
109 /// what the nuclear-potential functors use (potentialmanager.h); it costs seconds per rung.
110 static constexpr int ncf_special_level=15;
111
112 /// initialize the regularized potentials U1 and U2
113 void initialize(const double vtol1) {
114
115 // set threshold for projections
116 vtol=vtol1;
117
118 // Discard any previous set. initialize() is called again on every
119 // protocol step, and U1(axis) reads U1_function[axis] -- i.e. the FIRST
120 // three entries. Appending therefore left the accessor pinned to the
121 // functions built on the first call: at the initial (loosest) threshold,
122 // and at the initial k. With a pinned k that is a silent loss of
123 // precision for the rest of the ladder; with k varying across the
124 // protocol it is a tensor conformance failure.
125 U1_function.clear();
126
127 // construct the potential functions
128 // keep tighter threshold for orthogonalization
129 for (int axis=0; axis<3; ++axis) {
130 functorT U1f=functorT(new U1_functor(this,axis));
132 .functor(U1f).truncate_on_project());
133 U1_function.back().set_thresh(FunctionDefaults<3>::get_thresh());
134 }
135
136 // U2 is the term -S"/S - Z/r
137 functorT U2f=functorT(new U2_functor(this));
139 .functor(U2f).truncate_on_project();
141
142 // U3 is the term SA'/SA . SB'/SB
143 functorT U3f=functorT(new U3_functor(this));
145 .functor(U3f).truncate_on_project();
147 U2_function+=tmp;
149 }
150
151 virtual corrfactype type() const = 0;
152
153 /// apply the regularized potential U_nuc on a given function rhs
154 virtual real_function_3d apply_U(const real_function_3d& rhs) const {
155
156 // the purely local part
157 real_function_3d result=(U2()*rhs).truncate();
158
159 // the part with the derivative operators
160 result.compress();
161 for (int axis=0; axis<3; ++axis) {
162 real_derivative_3d D = free_space_derivative<double,3>(world, axis);
163 const real_function_3d Drhs=D(rhs).truncate();
164 result+=U1(axis)*Drhs;
165 }
166
167 result.truncate();
168 return result;
169 }
170
171 /// return the nuclear correlation factor
172 virtual real_function_3d function() const {
173 functorT Rf=functorT(new R_functor(this,1));
175 .functor(Rf).truncate_on_project();
176 return r;
177 }
178
179 /// return the square of the nuclear correlation factor
180 virtual real_function_3d square() const {
181 R_functor r(this,2);
183 .functor(r).truncate_on_project();
184 return R2;
185 }
186
187 /// return the square of the nuclear correlation factor multiplied with
188 /// the derivative of the nuclear potential for the specified atom
189
190 /// @return R^2 * \frac{\partial Z_A/r_{1A}}{\partial X_A}
191 virtual real_function_3d square_times_V_derivative(const int iatom, const int axis) const {
194 .functor(func).truncate_on_project();
195 return R2;
196 }
197
198 /// return the inverse nuclear correlation factor
199 virtual real_function_3d inverse() const {
200 R_functor r(this,-1);
202 .functor(r).truncate_on_project();
203 return R_inverse;
204 }
205
206 /// return the U1 term of the correlation function
207 virtual const real_function_3d U1(const int axis) const {
208 return U1_function[axis];
209 }
210
211 /// return the U1 functions in a vector
212 std::vector<real_function_3d> U1vec() const {
213 std::vector<real_function_3d> uvec(3);
214 uvec[0]=U1_function[0];
215 uvec[1]=U1_function[1];
216 uvec[2]=U1_function[2];
217 return uvec;
218 }
219
220 /// return the U2 term of the correlation function
221 virtual const real_function_3d U2() const {return U2_function;}
222
223private:
224
225 /// the world
227
228 /// the threshold for initial projection
229 double vtol;
230
231 /// smoothing of the potential/step function
232 double eprec;
233
234 /// the molecule
236 std::vector<size_t> all_atoms_;
237
238protected:
239 /// the three components of the U1 potential
240 std::vector<real_function_3d> U1_function;
241
242 /// the purely local U2 potential, having absorbed the nuclear pot V_nuc
244
245private:
246 /// the correlation factor S wrt a given atom
247
248 /// @param[in] r the distance of the req'd coord to the nucleus
249 /// @param[in] Z the nuclear charge
250 /// @return the nuclear correlation factor S_A(r_1A)
251 virtual double S(const double& r, const double& Z) const = 0;
252
253 /// the partial derivative of correlation factor S' wrt the cartesian coordinates
254
255 /// @param[in] vr1A the vector of the req'd coord to the nucleus
256 /// @param[in] Z the nuclear charge
257 /// @return the gradient of the nuclear correlation factor S'_A(r_1A)
258 virtual coord_3d Sp(const coord_3d& vr1A, const double& Z) const = 0;
259
260 /// the regularized potential wrt a given atom wrt the cartesian coordinate
261
262 /// S" is the Cartesian Laplacian applied on the NCF. Note the difference
263 /// to Srr_div_S, which is the second derivative wrt the distance rho.
264 /// this is: -S"/S - Z/r
265 /// @param[in] r the distance of the req'd coord to the nucleus
266 /// @param[in] Z the nuclear charge
267 /// @return the Laplacian of the nuclear correlation factor divided
268 /// by the correlation factor minus the nuclear potential
269 virtual double Spp_div_S(const double& r, const double& Z) const = 0;
270
271public:
272
273 /// first derivative of the NCF with respect to the relative distance rho
274 /// \f[
275 /// \frac{\partial S(\rho)}{\partial \rho} \frac{1}{S(\rho)}
276 /// \f]
277 /// where the distance of the electron to the nucleus A is given by
278 /// \f[
279 /// \rho = |\vec r - \vec R_A |
280 /// \f]
281 virtual double Sr_div_S(const double& r, const double& Z) const = 0;
282
283 /// distance from nucleus A beyond which its contributions to the functors are negligible
284
285 /// A factor that returns a finite radius guarantees that beyond it S_A - 1 and S'_A/S_A are
286 /// below ~1e-14 relative to their magnitude at the nucleus, and that S''_A/S_A equals the
287 /// Coulomb tail -Z_A/r to the same accuracy. Infinite (the default) keeps every atom in
288 /// every term.
289 virtual double screening_radius(const double /*Z*/) const {
290 return std::numeric_limits<double>::infinity();
291 }
292
293 /// indices of all atoms
294 const std::vector<size_t>& all_atoms() const {return all_atoms_;}
295
296 /// atoms whose screening sphere meets the bounding sphere of a set of points
297
298 /// The projection hands a functor all quadrature points of one box at once; an atom
299 /// screened out here is beyond its screening radius at every one of them.
300 std::vector<size_t> atoms_near(const double* x, const double* y, const double* z, const int npts) const {
301 coord_3d lo{x[0],y[0],z[0]}, hi{x[0],y[0],z[0]};
302 for (int p=1; p<npts; ++p) {
303 lo[0]=std::min(lo[0],x[p]); hi[0]=std::max(hi[0],x[p]);
304 lo[1]=std::min(lo[1],y[p]); hi[1]=std::max(hi[1],y[p]);
305 lo[2]=std::min(lo[2],z[p]); hi[2]=std::max(hi[2],z[p]);
306 }
307 coord_3d center, half;
308 for (int d=0; d<3; ++d) {
309 center[d]=0.5*(lo[d]+hi[d]);
310 half[d]=0.5*(hi[d]-lo[d]);
311 }
312 const double radius=half.normf();
313 std::vector<size_t> near;
314 for (size_t i=0; i<molecule.natom(); ++i) {
315 const Atom& atom=molecule.get_atom(i);
316 if ((center-atom.get_coords()).normf()-radius < screening_radius(atom.q)) near.push_back(i);
317 }
318 return near;
319 }
320
321 /// second derivative of the NCF with respect to the relative distance rho
322 /// \f[
323 /// \frac{\partial^2 S(\rho)}{\partial \rho^2} \frac{1}{S(\rho)}
324 /// \f]
325 /// where the distance of the electron to the nucleus A is given by
326 /// \f[
327 /// \rho = |\vec r - \vec R_A |
328 /// \f]
329 virtual double Srr_div_S(const double& r, const double& Z) const = 0;
330
331 /// third derivative of the NCF with respect to the relative distance rho
332 /// \f[
333 /// \frac{\partial^3 S(\rho)}{\partial \rho^3} \frac{1}{S(\rho)}
334 /// \f]
335 /// where the distance of the electron to the nucleus A is given by
336 /// \f[
337 /// \rho = |\vec r - \vec R_A |
338 /// \f]
339 virtual double Srrr_div_S(const double& r, const double& Z) const = 0;
340
341 /// derivative of the U2 potential wrt nuclear coordinate X (spherical part)
342
343 /// need to reimplement this for all derived classes due to the
344 /// range for r -> 0, where the singular terms cancel. With
345 /// \f[
346 /// \rho = \left| \vec r- \vec R_A \right|
347 /// \f]
348 /// returns the term in the parenthesis without the the derivative of rho
349 /// \f[
350 /// \frac{\partial U_2}{\partial X_A} = \frac{\partial \rho}{\partial X}
351 /// \left(-\frac{1}{2}\frac{S''' S - S'' S'}{S^2} + \frac{1}{\rho^2}\frac{S'}{S}
352 /// - \frac{1}{\rho} \frac{S''S - S'^2}{S^2} + \frac{Z_A}{\rho^2}\right)
353 /// \f]
354 virtual double U2X_spherical(const double& r, const double& Z, const double& rcut) const {
355 if (world.rank()==0) {
356 print("you can't compute the Hessian matrix");
357 print("U2X_spherical is not implemented for the nuclear correlation factor");
358 }
359 MADNESS_EXCEPTION("do more implementation work",1);
360 }
361
362public:
363
364 /// smoothed unit vector for the computation of the U1 potential
365
366 /// note the identity for exchanging nuclear and electronic coordinates
367 /// (there is a sign change, unlike for the smoothed potential)
368 /// \f[
369 /// \vec n = \frac{\partial \rho}{\partial x} = -\frac{\partial \rho}{\partial X}
370 /// \f]
371 /// \f[
372 /// \vec n = \left\{\frac{x \mathrm{erf}\left(\frac{r}{s}\right)}{r},
373 /// \frac{y \mathrm{erf}\left(\frac{r}{s}\right)}{r},
374 /// \frac{z \mathrm{erf}\left(\frac{r}{s}\right)}{r}\right\}
375 /// \f]
376 coord_3d smoothed_unitvec(const coord_3d& xyz, double smoothing=0.0) const {
377#if 0
378
379 if (smoothing==0.0) smoothing=molecule.get_eprec();
380 // TODO:need to test this
381 // reduce the smoothing for the unitvector
382 //if (not (this->type()==None or this->type()==Two)) smoothing=sqrt(smoothing);
383 smoothing=sqrt(smoothing);
384 const double r=xyz.normf();
385 const double rs=r/smoothing;
386 if (r<1.e-4) {
387 const double sqrtpi=sqrt(constants::pi);
388 double erfrs_div_r=2.0/(smoothing*sqrtpi)-2.0/3.0*rs*rs/(sqrtpi*smoothing);
389 return erfrs_div_r*xyz;
390 } else if (r<6.0) {
391 return erf(rs)/r*xyz;
392 } else {
393 return 1.0/r*xyz;
394 }
395
396
397
398#else
399 if (smoothing==0.0) smoothing=eprec;
400 // TODO:need to test this
401 // reduce the smoothing for the unitvector
402 //if (not (this->type()==None or this->type()==Two)) smoothing=sqrt(smoothing);
403 const double r=xyz.normf();
404 const double cutoff=smoothing;
405 if (r>cutoff) {
406 return 1.0/r*xyz;
407 } else if (r==0.0) {
408 // kk/r is 0/0 here and returns NaN. The limit is the zero vector:
409 // kk = (105/32)(r/cutoff) + O(r^3), so kk/r tends to 105/(32 cutoff)
410 // and kk/r*xyz tends to 0. Unreachable from Gauss quadrature, whose
411 // points are strictly interior, but reachable from any code that
412 // evaluates this functor on a grid containing a nuclear position.
413 return coord_3d{0.0,0.0,0.0};
414 } else {
415 const double xi=r/cutoff;
416 const double xi2=xi*xi;
417 const double xi3=xi*xi*xi;
418// const double nu21=0.5+1./32.*(45.*xi - 50.*xi3 + 21.*xi*xi*xi*xi*xi);
419 const double nu22=0.5 + 1./64.*(105* xi - 175 *xi3 + 147* xi2*xi3 - 45* xi3*xi3*xi);
420// const double nu40=0.5 + 1./128.*(225 *xi - 350 *xi3 + 189*xi2*xi3);
421 const double kk=2.*nu22-1.0;
422 return kk/r*xyz;
423 }
424
425#endif
426 }
427
428 /// derivative of smoothed unit vector wrt the *electronic* coordinate
429
430 /// note the sign change for exchanging nuclear and electronic coordinates
431 /// \f[
432 /// \frac{\partial \vec n}{\partial x} = -\frac{\partial \vec n}{\partial X}
433 /// \f]
434 /// the derivative wrt x is given by
435 /// \f[
436 /// \frac{\partial\vec n}{\partial x} =
437 /// \left\{\frac{\left(r^2-x^2\right) \mathrm{erf}\left(\frac{r}{s}\right)}{r^3}
438 /// +\frac{2 x^2 e^{-\frac{r^2}{s^2}}}{\sqrt{\pi } r^2 s},
439 /// x y \left(\frac{2 e^{-\frac{r^2}{s^2}}}{\sqrt{\pi } r^2 s}
440 /// -\frac{\mathrm{erf}\left(\frac{r}{s}\right)}{r^3}\right),
441 /// x z \left(\frac{2 e^{-\frac{r^2}{s^2}}}{\sqrt{\pi } r^2 s}
442 /// -\frac{\mathrm{erf}\left(\frac{r}{s}\right)}{r^3}\right)\right\}
443 /// \f]
445 double smoothing=0.0) const {
446
447 const double r=xyz.normf();
448 coord_3d result;
449 if (smoothing==0.0) smoothing=eprec;
450
451#if 1
452 // TODO:need to test this
453 // reduce the smoothing for the unitvector
454 //if (not (this->type()==None or this->type()==Two)) smoothing=sqrt(smoothing);
455 smoothing=sqrt(smoothing);
456
457 const double rs=r/smoothing;
458 const static double sqrtpi=sqrt(constants::pi);
459 const double sqrtpis3=sqrtpi*smoothing*smoothing*smoothing;
460
461 if (r<1.e-4) {
462 // series expansion
463 double p=-4.0/(3.0*sqrtpis3) + 4.0*rs*rs/(5.0*sqrtpis3);
464
465 double erfrs_div_r=2.0/(smoothing*sqrtpi)-2.0/3.0*rs*rs/(sqrtpi*smoothing);
466 result=xyz*xyz[axis]*p;
467 result[axis]+=erfrs_div_r;
468
469 } else if (r<6.0) {
470 const double erfrs_div_r=erf(rs)/r;
471 const double term1=2.0*exp(-rs*rs)/(sqrtpi*r*r*smoothing);
472 result=xyz*xyz[axis]*(term1-erfrs_div_r/(r*r));
473 result[axis]+=erfrs_div_r;
474#else
475 if (r<smoothing) {
476 double r2=r*r;
477 double s2=smoothing*smoothing;
478 double s7=s2*s2*s2*smoothing;
479 double x2=xyz[axis]*xyz[axis];
480
481 double fac_offdiag=-(((135. *r2*r2 - 294.* r2 *s2
482 + 175.*s2*s2))/(16.* s7));
483 double fac_diag=-((45.* r2*r2*r2 - 147.* r2*r2* s2
484 + 175.* r2*s2*s2 - 105.* s2*s2*s2 + 270.* r2*r2* x2
485 - 588.* r2* s2* x2 + 350.*s2* s2 *x2)/(32.* s7));
486
487 result[0]=fac_offdiag*xyz[0]*xyz[axis];
488 result[1]=fac_offdiag*xyz[1]*xyz[axis];
489 result[2]=fac_offdiag*xyz[2]*xyz[axis];
490 result[axis]=fac_diag;
491
492#endif
493 } else {
494 result=xyz*(-xyz[axis]/(r*r*r));
495 result[axis]+=1/r;
496 }
497 return result;
498 }
499
500
501 class R_functor : public FunctionFunctorInterface<double,3> {
504 public:
506 : ncf(ncf), exponent(e) {}
507
508 using FunctionFunctorInterface<double,3>::operator();
509
510 double operator()(const coord_3d& xyz) const override {
511 return eval(xyz,ncf->all_atoms());
512 }
513 bool supports_vectorized() const override {return true;}
514 void operator()(const Vector<double*,3>& xv, double* fv, int npts) const override {
515 const std::vector<size_t> near=ncf->atoms_near(xv[0],xv[1],xv[2],npts);
516 for (int p=0; p<npts; ++p) {
517 const coord_3d xyz{xv[0][p],xv[1][p],xv[2][p]};
518 fv[p]=eval(xyz,near);
519 }
520 }
521 /// an atom beyond its screening radius contributes the factor 1
522 double eval(const coord_3d& xyz, const std::vector<size_t>& atoms) const {
523 double result=1.0;
524 for (const size_t i : atoms) {
525 const Atom& atom=ncf->molecule.get_atom(i);
526 const coord_3d vr1A=xyz-atom.get_coords();
527 const double r=vr1A.normf();
528 result*=ncf->S(r,atom.q);
529 }
530 if (exponent==-1) return 1.0/result;
531 else if (exponent==2) return result*result;
532 else if (exponent==1) return result;
533 else {
534 return std::pow(result,double(exponent));
535 }
536
537 }
538 std::vector<coord_3d> special_points() const override {
539 return ncf->molecule.get_all_coords_vec();
540 }
541 };
542
543 /// functor for the local part of the U1 potential -- NOTE THE SIGN
544
545 /// U1 = -S'/S
546 class U1_functor : public FunctionFunctorInterface<double,3> {
547
549 const int axis;
550
551 public:
553 : ncf(ncf), axis(axis) {}
554
555
556 using FunctionFunctorInterface<double,3>::operator();
557
558 double operator()(const coord_3d& xyz) const override {
559 return eval(xyz,ncf->all_atoms());
560 }
561 bool supports_vectorized() const override {return true;}
562 void operator()(const Vector<double*,3>& xv, double* fv, int npts) const override {
563 const std::vector<size_t> near=ncf->atoms_near(xv[0],xv[1],xv[2],npts);
564 for (int p=0; p<npts; ++p) {
565 const coord_3d xyz{xv[0][p],xv[1][p],xv[2][p]};
566 fv[p]=eval(xyz,near);
567 }
568 }
569 double eval(const coord_3d& xyz, const std::vector<size_t>& atoms) const {
570 double result=0.0;
571 for (const size_t i : atoms) {
572 const Atom& atom=ncf->molecule.get_atom(i);
573 const coord_3d vr1A=xyz-atom.get_coords();
574 const double r=vr1A.normf();
575 const double& Z=atom.q;
576// result-=(ncf->Sp(vr1A,Z)[axis]/ncf->S(r,Z));
577 result-=ncf->Sr_div_S(r,Z)*ncf->smoothed_unitvec(vr1A)[axis];
578 }
579 return result;
580 }
581 std::vector<coord_3d> special_points() const override {
582 return ncf->molecule.get_all_coords_vec();
583 }
584 };
585
586 /// U1 functor for a specific atom
587
588 /// NOTE THE SIGN !!
589 /// this is
590 /// \f[
591 /// -\frac{\partial \rho}{\partial X_A}\frac{\partial S}{\partial \rho}\frac{1}{S}
592 /// \f]
594
596 const size_t iatom;
597 const int axis;
598
599 public:
601 const int axis) : ncf(ncf), iatom(atom), axis(axis) {}
602 using FunctionFunctorInterface<double,3>::operator();
603 double operator()(const coord_3d& xyz) const override {
604 const Atom& atom=ncf->molecule.get_atom(iatom);
605 const coord_3d vr1A=xyz-atom.get_coords();
606 const double r=vr1A.normf();
607 const double& Z=atom.q;
608 return ncf->Sr_div_S(r,Z)*ncf->smoothed_unitvec(vr1A)[axis];
609 }
610
611 std::vector<coord_3d> special_points() const override {
612 std::vector< madness::Vector<double,3> > c(1);
613 const Atom& atom=ncf->molecule.get_atom(iatom);
614 c[0][0]=atom.x;
615 c[0][1]=atom.y;
616 c[0][2]=atom.z;
617 return c;
618 }
619 };
620
621
622 /// functor for a local U1 dot U1 potential
623
624 /// \f[
625 /// U1\dot U1 = \frac{\left(S^r_A S^r_B\right)}{S_A S_B} n_A \cdot n_B
626 /// \f]
627 /// with positive sign!
629
631
632 public:
634
635 using FunctionFunctorInterface<double,3>::operator();
636 double operator()(const coord_3d& xyz) const override {
637 return eval(xyz,ncf->all_atoms());
638 }
639 bool supports_vectorized() const override {return true;}
640 void operator()(const Vector<double*,3>& xv, double* fv, int npts) const override {
641 const std::vector<size_t> near=ncf->atoms_near(xv[0],xv[1],xv[2],npts);
642 for (int p=0; p<npts; ++p) {
643 const coord_3d xyz{xv[0][p],xv[1][p],xv[2][p]};
644 fv[p]=eval(xyz,near);
645 }
646 }
647 double eval(const coord_3d& xyz, const std::vector<size_t>& atoms) const {
648 // sum_{AB} d_A d_B n_A.n_B with the diagonal taken as d_A^2, i.e. with the
649 // exact unit vector rather than the smoothed one that vanishes at nucleus A:
650 // = |sum_A d_A n_A|^2 + sum_A d_A^2 (1 - n_A.n_A)
651 // one pass over the atoms instead of one over the atom pairs
652 coord_3d u{0.0,0.0,0.0};
653 double diag=0.0;
654 for (const size_t i : atoms) {
655 const Atom& atom=ncf->molecule.get_atom(i);
656 const coord_3d vr1A=xyz-atom.get_coords();
657 const double d=ncf->Sr_div_S(vr1A.normf(),atom.q);
658 const coord_3d n=ncf->smoothed_unitvec(vr1A);
659 double nn=0.0;
660 for (int axis=0; axis<3; ++axis) {
661 u[axis]+=d*n[axis];
662 nn+=n[axis]*n[axis];
663 }
664 diag+=d*d*(1.0-nn);
665 }
666 double uu=0.0;
667 for (int axis=0; axis<3; ++axis) uu+=u[axis]*u[axis];
668 return uu+diag;
669 }
670 std::vector<coord_3d> special_points() const override {
671 return ncf->molecule.get_all_coords_vec();
672 }
673 };
674
675
676 class U2_functor : public FunctionFunctorInterface<double,3> {
678 public:
680
681 using FunctionFunctorInterface<double,3>::operator();
682 double operator()(const coord_3d& xyz) const override {
683 return eval(xyz,ncf->all_atoms());
684 }
685 bool supports_vectorized() const override {return true;}
686 void operator()(const Vector<double*,3>& xv, double* fv, int npts) const override {
687 const std::vector<size_t> near=ncf->atoms_near(xv[0],xv[1],xv[2],npts);
688 for (int p=0; p<npts; ++p) {
689 const coord_3d xyz{xv[0][p],xv[1][p],xv[2][p]};
690 fv[p]=eval(xyz,near);
691 }
692 }
693 /// the atoms in `near` (ascending) exactly, the others through the Coulomb tail of S''/S
694 double eval(const coord_3d& xyz, const std::vector<size_t>& near) const {
695 double result=0.0;
696 size_t k=0;
697 for (size_t i=0; i<ncf->molecule.natom(); ++i) {
698 const Atom& atom=ncf->molecule.get_atom(i);
699 const coord_3d vr1A=xyz-atom.get_coords();
700 const double r=vr1A.normf();
701 if (k<near.size() and near[k]==i) {
702 ++k;
703 result+=ncf->Spp_div_S(r,atom.q);
704 } else {
705 result-=atom.q/r;
706 }
707 }
708 return result;
709 }
710 std::vector<coord_3d> special_points() const override {
711 return ncf->molecule.get_all_coords_vec();
712 }
713 };
714
715 class U3_functor : public FunctionFunctorInterface<double,3> {
717 public:
719
720 using FunctionFunctorInterface<double,3>::operator();
721 double operator()(const coord_3d& xyz) const override {
722 return eval(xyz,ncf->all_atoms());
723 }
724 bool supports_vectorized() const override {return true;}
725 void operator()(const Vector<double*,3>& xv, double* fv, int npts) const override {
726 const std::vector<size_t> near=ncf->atoms_near(xv[0],xv[1],xv[2],npts);
727 for (int p=0; p<npts; ++p) {
728 const coord_3d xyz{xv[0][p],xv[1][p],xv[2][p]};
729 fv[p]=eval(xyz,near);
730 }
731 }
732 double eval(const coord_3d& xyz, const std::vector<size_t>& atoms) const {
733 // -sum_{A>B} t_A.t_B with t_A = (S'_A/S_A) n_A, as -1/2 (|sum_A t_A|^2 - sum_A t_A.t_A):
734 // one pass over the atoms instead of one over the atom pairs
735 coord_3d sum{0.0,0.0,0.0};
736 double diag=0.0;
737 for (const size_t i : atoms) {
738 const Atom& atom=ncf->molecule.get_atom(i);
739 const coord_3d vr1A=xyz-atom.get_coords();
740 const coord_3d t=ncf->Sr_div_S(vr1A.normf(),atom.q)*ncf->smoothed_unitvec(vr1A);
741 for (int axis=0; axis<3; ++axis) {
742 sum[axis]+=t[axis];
743 diag+=t[axis]*t[axis];
744 }
745 }
746 double sum2=0.0;
747 for (int axis=0; axis<3; ++axis) sum2+=sum[axis]*sum[axis];
748 return -0.5*(sum2-diag);
749 }
750 std::vector<coord_3d> special_points() const override {
751 return ncf->molecule.get_all_coords_vec();
752 }
753 };
754
755 /// U2 functor for a specific atom
757
759 const size_t iatom;
760
761 public:
763 : ncf(ncf), iatom(atom) {}
764
765 using FunctionFunctorInterface<double,3>::operator();
766 double operator()(const coord_3d& xyz) const override {
767 const Atom& atom=ncf->molecule.get_atom(iatom);
768 const coord_3d vr1A=xyz-atom.get_coords();
769 const double r=vr1A.normf();
770 return ncf->Spp_div_S(r,atom.q);
771 }
772
773 std::vector<coord_3d> special_points() const override {
774 std::vector< madness::Vector<double,3> > c(1);
775 const Atom& atom=ncf->molecule.get_atom(iatom);
776 c[0][0]=atom.x;
777 c[0][1]=atom.y;
778 c[0][2]=atom.z;
779 return c;
780 }
781 };
782
783 /// U3 functor for a specific atom
785
787 const size_t iatom;
788
789 public:
791 : ncf(ncf), iatom(atom) {}
792
793 using FunctionFunctorInterface<double,3>::operator();
794 double operator()(const coord_3d& xyz) const override {
795 const Atom& atomA=ncf->molecule.get_atom(iatom);
796 const coord_3d vr1A=xyz-atomA.get_coords();
797 const double rA=vr1A.normf();
798 const coord_3d nA=ncf->smoothed_unitvec(vr1A);
799 double Sr_div_SA=ncf->Sr_div_S(rA,atomA.q);
800
801 double result=0.0;
802 // sum over B
803 for (size_t i=0; i<ncf->molecule.natom(); ++i) {
804 if (i==iatom) continue; // restricted sum
805
806 const Atom& atomB=ncf->molecule.get_atom(i);
807 const coord_3d vr1B=xyz-atomB.get_coords();
808 const double rB=vr1B.normf();
809 const coord_3d nB=ncf->smoothed_unitvec(vr1B);
810 double Sr_div_SB=ncf->Sr_div_S(rB,atomB.q);
811
812 double dot=nA[0]*nB[0] + nA[1]*nB[1] + nA[2]*nB[2];
813 result+=Sr_div_SB*Sr_div_SA*dot;
814 }
815 return -0.5*result;
816 }
817
818 std::vector<coord_3d> special_points() const override {
819 std::vector< madness::Vector<double,3> > c(1);
820 const Atom& atom=ncf->molecule.get_atom(iatom);
821 c[0][0]=atom.x;
822 c[0][1]=atom.y;
823 c[0][2]=atom.z;
824 return c;
825 }
826 };
827
831 const size_t iatom;
832 public:
834 const Molecule& mol, const size_t iatom1)
835 : ncf(ncf), molecule(mol), iatom(iatom1) {}
836
837 using FunctionFunctorInterface<double,3>::operator();
838 double operator()(const coord_3d& xyz) const override {
839 double result=1.0;
840 for (size_t i=0; i<ncf->molecule.natom(); ++i) {
841 const Atom& atom=ncf->molecule.get_atom(i);
842 const coord_3d vr1A=xyz-atom.get_coords();
843 const double r=vr1A.normf();
844 result*=ncf->S(r,atom.q);
845 }
847 iatom, xyz[0], xyz[1], xyz[2]);
848 return result*result*V;
849
850 }
851 std::vector<coord_3d> special_points() const override {
852 return ncf->molecule.get_all_coords_vec();
853 }
854 };
855
856
860 const size_t iatom;
861 const int axis;
862 public:
864 const Molecule& molecule1, const size_t atom1, const int axis1)
865 : ncf(ncf), molecule(molecule1), iatom(atom1), axis(axis1) {}
866
867 using FunctionFunctorInterface<double,3>::operator();
868 double operator()(const coord_3d& xyz) const override {
869 double result=1.0;
870 for (size_t i=0; i<ncf->molecule.natom(); ++i) {
871 const Atom& atom=ncf->molecule.get_atom(i);
872 const coord_3d vr1A=xyz-atom.get_coords();
873 const double r=vr1A.normf();
874 result*=ncf->S(r,atom.q);
875 }
877 iatom, axis, xyz[0], xyz[1], xyz[2]);
878 return result*result*Vprime;
879
880 }
881 std::vector<coord_3d> special_points() const override {
882 return ncf->molecule.get_all_coords_vec();
883 }
884 };
885
886 /// compute the derivative of R wrt the displacement of atom A, coord axis
887 class RX_functor : public FunctionFunctorInterface<double,3> {
890 const int derivativeaxis; /// direction of the derivative operator
891 const int exponent; /// 1 or 2 -> R^X or R^X R
892
893 public:
895 const int daxis, const int exponent) : ncf(ncf), thisatom(atom1),
897 MADNESS_ASSERT((exponent==1) or (exponent==2) or (exponent==-1));
898 }
899
900 RX_functor(const NuclearCorrelationFactor* ncf, const int iatom,
901 const int daxis, const int exponent) : ncf(ncf),
902 thisatom(ncf->molecule.get_atom(iatom)),
904 MADNESS_ASSERT((exponent==1) or (exponent==2) or (exponent==-1));
905 }
906
907 using FunctionFunctorInterface<double,3>::operator();
908 double operator()(const coord_3d& xyz) const override {
909
910 // compute the R term
911 double result=1.0;
912 if ((exponent==1) or (exponent==2)) {
913 for (size_t i=0; i<ncf->molecule.natom(); ++i) {
914 const Atom& atom=ncf->molecule.get_atom(i);
915 const coord_3d vr1A=xyz-atom.get_coords();
916 const double r=vr1A.normf();
917 result*=ncf->S(r,atom.q);
918 }
919 if (exponent==2) result=result*result;
920 }
921
922 // compute the derivative term
923 {
924 const coord_3d vr1A=xyz-thisatom.get_coords();
925 const double r=vr1A.normf();
926 const double& Z=thisatom.q;
927 const double S1=-ncf->Sr_div_S(r,Z) // note the sign
928 *ncf->smoothed_unitvec(vr1A)[derivativeaxis];
929 result*=S1;
930 }
931 return result;
932 }
933
934 std::vector<coord_3d> special_points() const override {
935 return ncf->molecule.get_all_coords_vec();
936 }
937
938 };
939
940
941 /// compute the derivative of U1 wrt the displacement of atom A, coord axis
942 class U1X_functor : public FunctionFunctorInterface<double,3> {
945 const int U1axis; /// U1x/U1y/U1z potential?
946 const int derivativeaxis; /// direction of the derivative operator
947 public:
949 const int U1axis, const int daxis) : ncf(ncf), thisatom(atom1),
950 U1axis(U1axis), derivativeaxis(daxis) {
951 double lo=1.0/thisatom.q;
953 }
954
955 U1X_functor(const NuclearCorrelationFactor* ncf, const int iatom,
956 const int U1axis, const int daxis) : ncf(ncf),
957 thisatom(ncf->molecule.get_atom(iatom)),
958 U1axis(U1axis), derivativeaxis(daxis) {
959 double lo=1.0/thisatom.q;
961 }
962
963 using FunctionFunctorInterface<double,3>::operator();
964
965 double operator()(const coord_3d& xyz) const override {
966 const coord_3d vr1A=xyz-thisatom.get_coords();
967 const double r=vr1A.normf();
968 const double& Z=thisatom.q;
969 const double S1=ncf->Sr_div_S(r,Z);
970 const double S2=ncf->Srr_div_S(r,Z);
971
972 // note the sign change smoothed_unitvec due to the
973 // change in the derivative variable x: electronic -> nuclear
974 const double drhodx=-ncf->smoothed_unitvec(vr1A)[derivativeaxis];
975 return drhodx*(S2-S1*S1)*ncf->smoothed_unitvec(vr1A)[U1axis]
976 -S1*(ncf->dsmoothed_unitvec(vr1A,derivativeaxis)[U1axis]);
977 }
978
979 std::vector<coord_3d> special_points() const override {
980 std::vector< madness::Vector<double,3> > c(1);
981 c[0][0]=thisatom.x;
982 c[0][1]=thisatom.y;
983 c[0][2]=thisatom.z;
984 return c;
985 }
986
987 };
988
989
990 /// compute the derivative of U2 wrt the displacement of atom A
991 class U2X_functor : public FunctionFunctorInterface<double,3> {
993 const int iatom;
994 const int axis;
995 public:
996 U2X_functor(const NuclearCorrelationFactor* ncf, const int& atom1,
997 const int axis) : ncf(ncf), iatom(atom1), axis(axis) {
998 const Atom& atom=ncf->molecule.get_atom(iatom);
999 double lo=1.0/atom.q;
1001 }
1002
1003 using FunctionFunctorInterface<double,3>::operator();
1004 double operator()(const coord_3d& xyz) const override {
1005 const Atom& atom=ncf->molecule.get_atom(iatom);
1006 const coord_3d vr1A=xyz-atom.get_coords();
1007 const double r=vr1A.normf();
1008 const double& Z=atom.q;
1009 const double rcut=ncf->molecule.get_rcut()[iatom];
1010
1011 // note the sign change due to the change in the derivative
1012 // variable x: electronic -> nuclear in drho/dx
1013 const double drhodx=-ncf->smoothed_unitvec(vr1A)[axis];
1014 return drhodx*ncf->U2X_spherical(r,Z,rcut);
1015 }
1016
1017 std::vector<coord_3d> special_points() const override {
1018 std::vector< madness::Vector<double,3> > c(1);
1019 const Atom& atom=ncf->molecule.get_atom(iatom);
1020 c[0][0]=atom.x;
1021 c[0][1]=atom.y;
1022 c[0][2]=atom.z;
1023 return c;
1024 }
1025 };
1026
1027
1028 /// compute the derivative of U3 wrt the displacement of atom A, coord axis
1029
1030 /// \f[
1031 /// U_3^{X_A} = -\sum_{B\neq A}\left(\frac{\vec S_A'}{S_A}\right)^X\cdot\left(\frac{\vec S_B'}{S_B}\right)
1032 /// \f]
1033 /// with
1034 /// \f[
1035 /// \left(\frac{\vec S_A'}{S_A}\right)^X =
1036 /// \frac{\partial \rho}{\partial X}\left(\frac{S''_A}{S_A}
1037 /// -\left(\frac{S'_A}{S_A}\right)^2\right)\vec n_{1A}
1038 /// + \left(\frac{S'_A}{S_A}\right)\frac{\partial \vec n_{1A}}{\partial X}
1039 /// \f]
1040 class U3X_functor : public FunctionFunctorInterface<double,3> {
1042 const size_t iatom;
1043 const int axis;
1044 public:
1046 const int axis) : ncf(ncf), iatom(iatom), axis(axis) {}
1047
1048 using FunctionFunctorInterface<double,3>::operator();
1049 double operator()(const coord_3d& xyz) const override {
1050 const Atom& atomA=ncf->molecule.get_atom(iatom);
1051 const coord_3d vr1A=xyz-atomA.get_coords();
1052 const double r1A=vr1A.normf();
1053 const double& ZA=atomA.q;
1054
1055 double S1A=ncf->Sr_div_S(r1A,ZA);
1056 double S2A=ncf->Srr_div_S(r1A,ZA);
1057 double termA=S2A-S1A*S1A;
1058
1059 // unit vector \vec n_A = \vec r_{1A}/r_{1A}
1060 const coord_3d nA=ncf->smoothed_unitvec(vr1A);
1061 // derivative of the unit vector \frac{\partial \vec n_A}{\partial X}
1062 const coord_3d dnA=ncf->dsmoothed_unitvec(vr1A,axis)*(-1.0);
1063 // \frac{\partial \rho}{\partial X}
1064 const double drhodx=-nA[axis];
1065
1066 double term=0.0;
1067 for (size_t jatom=0; jatom<ncf->molecule.natom(); ++jatom) {
1068 if (iatom==jatom) continue; // restricted sum B \neq A
1069
1070 const Atom& atomB=ncf->molecule.get_atom(jatom);
1071 const coord_3d vr1B=xyz-atomB.get_coords();
1072 const double r1B=vr1B.normf();
1073 const double& ZB=atomB.q;
1074
1075 double S1B=ncf->Sr_div_S(r1B,ZB);
1076 const coord_3d nB=ncf->smoothed_unitvec(vr1B);
1077
1078 double dot=0.0; // n_A.n_B
1079 double ddot=0.0; // n'_A.n_B
1080 for (int i=0; i<3; ++i) {
1081 ddot+=dnA[i]*nB[i];
1082 dot+=nA[i]*nB[i];
1083 }
1084 term+=(+drhodx*termA*S1B*dot + S1A*S1B*ddot);
1085
1086 }
1087
1088 return term;
1089 }
1090
1091 std::vector<coord_3d> special_points() const override {
1092 return ncf->molecule.get_all_coords_vec();
1093 }
1094 };
1095
1096};
1097
1098
1099/// A nuclear correlation factor class
1100
1101/// The nuclear correlation factor is given by
1102/// \[f
1103/// R = \prod S_A ; S_A=exp(-Z_A r_{1A}) + ( 1 - exp(-r_{1A}^2) )
1104/// \]f
1106public:
1107 /// ctor
1108
1109 /// @param[in] world the world
1110 /// @param[in] mol molecule with the sites of the nuclei
1113
1114 if (world.rank()==0) {
1115 print("constructed nuclear correlation factor of the form");
1116 print(" R = Prod_A S_A");
1117 print(" S_A = exp(-Z_A r_{1A}) + (1 - exp(-Z_A^2*r_{1A}^2))");
1118 print("with eprec ",mol.get_eprec());
1119 print("which is of Gaussian-Slater type\n");
1120 }
1121
1122 }
1123
1125
1126private:
1127
1128 /// the nuclear correlation factor
1129 double S(const double& r, const double& Z) const {
1130 const double rho=r*Z;
1131 return exp(-rho)+(1.0-exp(-(rho*rho)));
1132 }
1133
1134 /// radial part first derivative of the nuclear correlation factor
1135 coord_3d Sp(const coord_3d& vr1A, const double& Z) const {
1136
1137 const double r=sqrt(vr1A[0]*vr1A[0] +
1138 vr1A[1]*vr1A[1] + vr1A[2]*vr1A[2]);
1139
1140 const double eA=exp(-Z*r);
1141 const double gA=exp(-Z*Z*r*r);
1142 coord_3d term=(2.0*gA*Z*Z*vr1A-Z*eA*smoothed_unitvec(vr1A));
1143 return term;
1144 }
1145
1146 /// second derivative of the nuclear correlation factor
1147
1148 /// -1/2 S"/S - Z/r
1149 double Spp_div_S(const double& r, const double& Z) const {
1150 const double rho=Z*r;
1151 if (rho<1.e-4) {
1152 return Z*Z*(-3.5 - 4.0*rho + 6.0*rho*rho + 12.0*rho*rho*rho);
1153 } else {
1154 const double e=exp(-rho);
1155 const double g=exp(-rho*rho);
1156 const double term1=-Z/r*(1.0-g);
1157 const double term2=-g*Z*Z*(3.0-2.0*Z*Z*r*r) - Z*Z/2.0*e;
1158 const double S_inv=exp(-rho)+(1.0-exp(-(rho*rho)));
1159 return (term1+term2)/S_inv;
1160 }
1161 }
1162
1163 double Sr_div_S(const double& r, const double& Z) const {
1164 const double Zr=r*Z;
1165 const double eA=exp(-Zr);
1166 const double gA=exp(-Zr*Zr);
1167 const double num=Z*(2.0*Zr*gA-eA);
1168 const double denom=1.0+eA-gA;
1169 return num/denom;
1170 }
1171
1172 double Srr_div_S(const double& r, const double& Z) const {
1173 const double Zr=r*Z;
1174 const double eA=exp(-Zr);
1175 const double gA=exp(-Zr*Zr);
1176 const double num=Z*Z*(eA+gA*(2.0-4.0*Zr*Zr));
1177 const double denom=1.0+eA-gA;
1178 return num/denom;
1179 }
1180
1181 double Srrr_div_S(const double& r, const double& Z) const {
1182 const double Zr=r*Z;
1183 const double eA=exp(-Zr);
1184 const double gA=exp(-Zr*Zr);
1185 const double num=Z*Z*Z*(-eA - 12.0*gA*Zr + 8.0*gA*Zr*Zr*Zr);
1186 const double denom=1.0+eA-gA;
1187 return num/denom;
1188
1189 }
1190
1191 /// derivative of the U2 potential wrt X (scalar part)
1192
1193 /// with
1194 /// \f[
1195 /// \rho = \left| \vec r- \vec R_A \right|
1196 /// \f]
1197 /// returns the term in the parenthesis without the the derivative of rho
1198 /// \f[
1199 /// \frac{\partial U_2}{\partial X_A} = \frac{\partial \rho}{\partial X}
1200 /// \left(-\frac{1}{2}\frac{S''' S - S'' S'}{S^2} + \frac{1}{\rho^2}\frac{S'}{S}
1201 /// - \frac{1}{\rho} \frac{S''S - S'^2}{S^2} + \frac{Z_A}{\rho^2}\right)
1202 /// \f]
1203 double U2X_spherical(const double& r, const double& Z, const double& rcut) const {
1204
1205 double result=0.0;
1206 if (r*Z<1.e-4) {
1207 const double ZZ=Z*Z;
1208 const double ZZZ=ZZ*Z;
1209 const double Z4=ZZ*ZZ;
1210 const double r0=-4.0*ZZZ;
1211 const double r1=12.0*Z4;
1212 const double r2=36*Z4*Z;
1213 const double r3=-67.0/6.0*Z4*ZZ;
1214 result=(r0 + r*r1 + r*r*r2 + r*r*r*r3);
1215
1216 } else {
1217 const double S1=Sr_div_S(r,Z);
1218 const double S2=Srr_div_S(r,Z);
1219 const double S3=Srrr_div_S(r,Z);
1220 const double term1=-0.5*(S3-S1*S2);
1221 const double term2=(S1+Z)/(r*r);
1222 const double term3=(S2-S1*S1)/r;
1223 result=term1+term2-term3;
1224 }
1225 return result;
1226 }
1227
1228
1229};
1230
1231/// A nuclear correlation factor class
1232
1233/// The nuclear correlation factor is given by
1234/// \[f
1235/// R = \prod S_A ; S_A=exp(-Z_A r_{1A}) + ( 1 - exp(-r_{1A}^2) )
1236/// \]f
1238public:
1239 /// ctor
1240
1241 /// @param[in] world the world
1242 /// @param[in] mol molecule with the sites of the nuclei
1243 GradientalGaussSlater(World& world, const Molecule& mol, const double a)
1245
1246 if (world.rank()==0) {
1247 print("constructed nuclear correlation factor of the form");
1248 print(" R = Prod_A S_A");
1249 print(" S_A = 1/sqrt{Z} exp(-Z_A r_{1A}) + (1 - exp(-a^2*Z_A^2*r_{1A}^2))");
1250 print(" a = ",a);
1251 print("with eprec ",mol.get_eprec());
1252 print("which is of Gradiental Gaussian-Slater type\n");
1253 }
1254
1255 }
1256
1258
1259private:
1260
1261 const double a;
1262
1263 /// the nuclear correlation factor
1264 double S(const double& r, const double& Z) const {
1265 const double rho=r*Z;
1266 return 1/sqrt(Z) * exp(-rho)+(1.0-exp(-(a*a*rho*rho)));
1267 }
1268
1269 /// radial part first derivative of the nuclear correlation factor
1270 coord_3d Sp(const coord_3d& vr1A, const double& Z) const {
1271
1272 const double r=sqrt(vr1A[0]*vr1A[0] +
1273 vr1A[1]*vr1A[1] + vr1A[2]*vr1A[2]);
1274
1275 const double rho=Z*r;
1276 const double sqrtz=sqrt(Z);
1277 const double term=-exp(-rho)*sqrtz + 2.0*a*a*exp(-a*a*rho*rho)*Z*rho;
1278 return term*smoothed_unitvec(vr1A);
1279 }
1280
1281 /// second derivative of the nuclear correlation factor
1282
1283 /// -1/2 S"/S - Z/r
1284 double Spp_div_S(const double& r, const double& Z) const {
1285 const double rho=Z*r;
1286 const double sqrtz=sqrt(Z);
1287 if (rho<1.e-4) {
1288 const double zfivehalf=Z*Z*sqrtz;
1289 const double a2=a*a;
1290 const double a4=a2*a2;
1291 return -0.5*Z*Z
1292 - 3. *a2 * zfivehalf
1293 - 4.* a2 *rho* zfivehalf
1294 - 2. *a2 * rho*rho*zfivehalf
1295 + 5. *a4 *rho*rho*zfivehalf
1296 + 3. *a4 *rho*rho*Z*Z*Z
1297 -0.5 *a2 *rho*rho*rho*zfivehalf
1298 +5.5 *a4 *rho*rho*rho*zfivehalf
1299 +7. *a4 *rho*rho*rho*Z*Z*Z;
1300 } else {
1301 const double e=exp(-rho);
1302 const double g=exp(-a*a*rho*rho);
1303 const double poly=(2.0-6.0*a*a*rho + 4.0*a*a*a*a*rho*rho*rho);
1304 const double num=Z*(-2.0 - e*r*sqrtz + g*poly);
1305 const double denom=2.0*r*(1.0-g+e/sqrtz);
1306 return num/denom;
1307 }
1308 }
1309
1310 double Sr_div_S(const double& r, const double& Z) const {
1311 const double rZ=r*Z;
1312 const double e=exp(-rZ);
1313 const double g=exp(-a*a*rZ*rZ);
1314 const double sqrtz=sqrt(Z);
1315 const double num=-sqrtz*e + 2.0*a*a*g*Z*rZ;
1316 const double denom=1.0-g+e/sqrtz;
1317 return num/denom;
1318 }
1319
1320 double Srr_div_S(const double& r, const double& Z) const {
1321 const double rZ=r*Z;
1322 const double e=exp(-rZ);
1323 const double g=exp(-a*a*rZ*rZ);
1324 const double sqrtz=sqrt(Z);
1325 const double num=e*Z*sqrtz + g*(2.0*a*a - 4.0*power<4>(a)*rZ*rZ)*Z*Z;
1326 const double denom=1.0-g+e/sqrtz;
1327 return num/denom;
1328 }
1329
1330 double Srrr_div_S(const double& r, const double& Z) const {
1331 const double rZ=r*Z;
1332 const double e=exp(-rZ);
1333 const double g=exp(-a*a*rZ*rZ);
1334 const double sqrtz=sqrt(Z);
1335 const double num=e*power<3>(Z) + (12.0*power<4>(a)*g*rZ
1336 -8.0*power<6>(a)*g*power<3>(rZ))*sqrtz*power<3>(Z);
1337 const double denom=e+sqrtz-g*sqrtz;
1338 return -num/denom;
1339 }
1340
1341 double U2X_spherical(const double& r, const double& Z, const double& rcut) const {
1342
1343 double result=0.0;
1344 if (r*Z<1.e-4) {
1345 const double sqrtz=sqrt(Z);
1346 const double Z2=Z*Z;
1347 const double Z4=Z2*Z2;
1348 const double Z5=Z4*Z;
1349 const double Z6=Z5*Z;
1350 const double Z7=Z6*Z;
1351 const double a2=a*a;
1352 const double a4=a2*a2;
1353
1354 const double r0=-4.* a2* sqrt(Z7);
1355 const double r1=2.* (-2.* a2* Z*sqrt(Z7)+ 5.* a4* Z*sqrt(Z7) + 3.* a4 *Z5) *r;
1356 const double r2=1.5 * (-a2* sqrtz*Z5 + 11.* a4* sqrtz*Z5 + 14.*a4* Z6)* r*r;
1357 const double r3=1./6.* (-a2* sqrtz*Z6 + 66.* a4*sqrtz*Z6 - 84.* a2*a4* sqrtz*Z6 +
1358 180. *a4* Z7 - 156.*a2*a4* Z7 - 72.* a2*a4*sqrtz*Z7) *r*r*r;
1359 result=(r0 + r1 + r2 + r3);
1360
1361 } else {
1362 const double S1=Sr_div_S(r,Z);
1363 const double S2=Srr_div_S(r,Z);
1364 const double S3=Srrr_div_S(r,Z);
1365 const double term1=-0.5*(S3-S1*S2);
1366 const double term2=(S1+Z)/(r*r);
1367 const double term3=(S2-S1*S1)/r;
1368 result=term1+term2-term3;
1369 }
1370 return result;
1371 }
1372};
1373
1374
1375/// A nuclear correlation factor class
1376
1377/// The nuclear correlation factor is given by
1378/// \[f
1379/// R = \prod S_A ; S_A= -Z_A r_{1A} exp(-Z_A r_{1A}) + 1
1380/// \]f
1382public:
1383 /// ctor
1384
1385 /// @param[in] world the world
1386 /// @param[in] mol molecule with the sites of the nuclei
1387 LinearSlater(World& world, const Molecule& mol, const double a)
1388 : NuclearCorrelationFactor(world,mol), a_(1.0) {
1389
1390 if (a!=0.0) a_=a;
1391
1392 if (world.rank()==0) {
1393 print("constructed nuclear correlation factor of the form");
1394 print(" S_A = -Z_A r_{1A} exp(-Z_A r_{1A}) + 1");
1395 print(" a = ",a_);
1396 print("with eprec ",mol.get_eprec());
1397 print("which is of linear Slater type\n");
1398 }
1399 }
1400
1402
1403private:
1404
1405 /// the length scale parameter a
1406 double a_;
1407
1408 double a_param() const {return 1.0;}
1409
1410 /// the nuclear correlation factor
1411 double S(const double& r, const double& Z) const {
1412 const double rho=r*Z;
1413 const double b=a_param();
1414 return (-rho)*exp(-b*rho)+1.0;
1415 }
1416
1417 /// radial part first derivative of the nuclear correlation factor
1418 coord_3d Sp(const coord_3d& vr1A, const double& Z) const {
1419
1420 const double b=a_param();
1421 const double r=sqrt(vr1A[0]*vr1A[0] +
1422 vr1A[1]*vr1A[1] + vr1A[2]*vr1A[2]);
1423
1424 const double ebrz=exp(-b*r*Z);
1425 const coord_3d term=Z*ebrz*(b*Z*(vr1A) - smoothed_unitvec(vr1A));
1426 return term;
1427 }
1428
1429 /// second derivative of the nuclear correlation factor
1430
1431 /// -1/2 S"/S - Z/r
1432 double Spp_div_S(const double& r, const double& Z) const {
1433
1434 const double b=a_param();
1435 const double rho=Z*r;
1436 if (rho<1.e-4) {
1437 const double O0=1.0- 3.0* b;
1438 const double O1=Z - 4.0*b*Z + 3.0*b*b*Z;
1439 const double O2=Z*Z - 5.0*b*Z*Z + 6.5*b*b*Z*Z - 5.0/3.0*b*b*b*Z*Z;
1440 return Z*Z*(O0 + O1*r + O2*r*r);
1441
1442 } else {
1443 const double ebrz=exp(-b*rho);
1444 const double num=Z* (ebrz - 1.0 + 0.5*ebrz*rho* (2.0 + b*(b*rho-4.0)));
1445 const double denom=r*(rho*ebrz-1.0);
1446 return -num/denom;
1447 }
1448 }
1449
1450 double Sr_div_S(const double& r, const double& Z) const {
1451 const double& a=a_param();
1452 const double earz=exp(-a*r*Z);
1453 return Z*earz*(a*r*Z-1.0)/(1.0-r*Z*earz);
1454 }
1455
1456 double Srr_div_S(const double& r, const double& Z) const {
1457 const double& a=a_param();
1458 const double earz=exp(-a*r*Z);
1459 return a*Z*Z*earz*(a*r*Z-2.0)/(-1.0+r*Z*earz);
1460 }
1461
1462 double Srrr_div_S(const double& r, const double& Z) const {
1463 const double& a=a_param();
1464 const double earz=exp(-a*r*Z);
1465 return a*a*Z*Z*Z*earz*(a*r*Z-3.0)/(1.0-r*Z*earz);
1466 }
1467
1468};
1469
1470
1471/// A nuclear correlation factor class
1473public:
1474 /// ctor
1475
1476 /// @param[in] world the world
1477 /// @param[in] mol molecule with the sites of the nuclei
1478 Slater(World& world, const Molecule& mol, const double a)
1479 : NuclearCorrelationFactor(world,mol), a_(1.5) {
1480
1481 if (a!=0.0) a_=a;
1482 eprec_=mol.get_eprec();
1483
1484 if (world.rank()==0) {
1485 print("\nconstructed nuclear correlation factor of the form");
1486 print(" S_A = 1/(a-1) exp(-a Z_A r_{1A}) + 1");
1487 print(" a = ",a_);
1488 print("with eprec ",eprec_);
1489 print("which is of Slater type\n");
1490 }
1491 }
1492
1494
1495private:
1496
1497 /// the length scale parameter
1498 double a_;
1499 double eprec_;
1500
1501 double a_param() const {return a_;}
1502 double eprec_param() const {return eprec_;}
1503
1504 /// every per-atom term of this factor decays as exp(-a Z r); 1e-14 relative to (a Z)^2
1505 double screening_radius(const double Z) const override {
1506 const double a=a_param();
1507 return std::log(a*Z*a*Z/((a-1.0)*1.e-14))/(a*Z);
1508 }
1509
1510 /// first derivative of the correlation factor wrt (r-R_A)
1511
1512 /// \f[
1513 /// Sr_div_S = \frac{1}{S(r)}\frac{\partial S(r)}{\partial r}
1514 /// \f]
1515 double Sr_div_S(const double& r, const double& Z) const override {
1516 const double& a=a_param();
1517 return -a*Z/(1.0+(a-1.0)*exp(a*r*Z));
1518 }
1519
1520 /// second derivative of the correlation factor wrt (r-R_A)
1521
1522 /// \f[
1523 /// result = \frac{1}{S(r)}\frac{\partial^2 S(r)}{\partial r^2}
1524 /// \f]
1525 double Srr_div_S(const double& r, const double& Z) const override {
1526 const double& a=a_param();
1527 const double aZ=a*Z;
1528 return aZ*aZ/(1.0+(a-1.0)*exp(r*aZ));
1529 }
1530
1531 /// third derivative of the correlation factor wrt (r-R_A)
1532
1533 /// \f[
1534 /// result = \frac{1}{S(r)}\frac{\partial^3 S(r)}{\partial r^3}
1535 /// \f]
1536 double Srrr_div_S(const double& r, const double& Z) const override {
1537 const double& a=a_param();
1538 const double aZ=a*Z;
1539 return -aZ*aZ*aZ/(1.0+(a-1.0)*exp(r*aZ));
1540 }
1541
1542 /// the nuclear correlation factor
1543 double S(const double& r, const double& Z) const override {
1544 const double a=a_param();
1545 //const double eprec=eprec_param();
1546 return 1.0+1.0/(a-1.0) * exp(-a*Z*r);
1547
1548// return 1.0 + 0.5/(a-1.0) *
1549// (exp(-a*r*Z + 0.5*a*a*Z*Z*eprec) * erfc((-r+a*eprec*Z)/sqrt(2*eprec))
1550// + exp(-a*r*Z + 0.5*a*Z*(4.0*r+a*eprec*Z)) * erfc((r+a*eprec*Z)/sqrt(2*eprec)));
1551 }
1552
1553 /// radial part first derivative of the nuclear correlation factor
1554 coord_3d Sp(const coord_3d& vr1A, const double& Z) const override {
1555 const double a=a_param();
1556 const double r=vr1A.normf();
1557 return -(a*exp(-a*Z*r)*Z)/(a-1.0)*smoothed_unitvec(vr1A);
1558 }
1559
1560 /// second derivative of the nuclear correlation factor
1561 double Spp_div_S(const double& r, const double& Z) const override {
1562 const double a=a_param();
1563
1564 if (r*Z<1.e-4) {
1565 const double O0=1.0-(1.5*a);
1566 const double O1=(a-1.0)*(a-1.0)*Z;
1567 const double O2=(1.0/12.0 * (a-1.0)*(12.0+a*(5*a-18.0)))*Z*Z;
1568 return Z*Z*(O0 + O1*r + O2*r*r);
1569
1570 } else {
1571 const double earz=exp(-a*r*Z);
1572 const double num=Z*(-earz + a*earz - (a-1.0) - 0.5*a*a*r*Z*earz);
1573 const double denom=(r*earz + (a-1.0) * r);
1574 return num/denom;
1575 }
1576 }
1577
1578
1579 /// derivative of the U2 potential wrt X (scalar part)
1580
1581 /// with
1582 /// \f[
1583 /// \rho = \left| \vec r- \vec R_A \right|
1584 /// \f]
1585 /// returns the term in the parenthesis without the the derivative of rho
1586 /// \f[
1587 /// \frac{\partial U_2}{\partial X_A} = \frac{\partial \rho}{\partial X}
1588 /// \left(-\frac{1}{2}\frac{S''' S - S'' S'}{S^2} + \frac{1}{\rho^2}\frac{S'}{S}
1589 /// - \frac{1}{\rho} \frac{S''S - S'^2}{S^2} + \frac{Z_A}{\rho^2}\right)
1590 /// \f]
1591 double U2X_spherical(const double& r, const double& Z, const double& rcut) const override {
1592 const double a=a_param();
1593
1594 double result=0.0;
1595 if (r*Z<1.e-4) {
1596 const double ZZ=Z*Z;
1597 const double ZZZ=ZZ*Z;
1598 const double a2=a*a;
1599 const double a4=a2*a2;
1600 const double r0=ZZZ*(1. - 2.* a + a2);
1601 const double r1=ZZ*ZZ/6.* (12.0 - 30.* a + 23. *a2 - 5.*a*a2);
1602 const double r2=1./8.*ZZ*ZZZ* (24. - 72.*a + 74.*a2 - 29.*a2*a + 3.*a4);
1603 const double r3=1./60.*ZZZ*ZZZ* (240. - 840.*a + 1080.*a2 - 610.*a2*a
1604 + 137.*a2*a2 - 7.*a4*a);
1605 result=(r0 + r*r1 + r*r*r2 + r*r*r*r3);
1606
1607 } else {
1608 const double S1=Sr_div_S(r,Z);
1609 const double S2=Srr_div_S(r,Z);
1610 const double S3=Srrr_div_S(r,Z);
1611 const double term1=-0.5*(S3-S1*S2);
1612 const double term2=(S1+Z)/(r*r);
1613 const double term3=(S2-S1*S1)/r;
1614 result=term1+term2-term3;
1615 }
1616 return result;
1617 }
1618
1619};
1620
1621
1623public:
1624 /// ctor
1625
1626 /// @param[in] world the world
1627 /// @param[in] mol molecule with the sites of the nuclei
1628 poly4erfc(World& world, const Molecule& mol, const double aa)
1629 : NuclearCorrelationFactor(world,mol), a(1.0) {
1630
1631 if (aa!=0.0) a=aa;
1632 eprec_=mol.get_eprec();
1633
1634 if (world.rank()==0) {
1635 print("\nconstructed nuclear correlation factor of the form");
1636 print(" S_A = 1 + (a0 + a1 arZ + a2 (arZ)^2 + a3 (arZ)^3 + a4 (arZ)^4) erfc(arZ)");
1637 print(" a = ",a);
1638 print("with eprec ",eprec_);
1639 print("which is of poly4erfc type\n");
1640 }
1641 //const double pi32=std::pow(constants::pi,1.5);
1642 //const double sqrtpi=sqrt(constants::pi);
1643 //const double Pi=constants::pi;
1644
1645 if (a==0.5) {
1646 a0=0.5083397721116242769;
1647 a1=-2.4430795355664112811;
1648 a2=3.569312300653802680;
1649 a3=-1.9812471972342746507;
1650 a4=0.3641705622093696564;
1651 } else if (a==1.0) {
1652 a0=0.20265985404508529127;
1653 a1=-0.9739826967339938056;
1654 a2=1.4229779953809877198;
1655 a3=-0.7898639647077711196;
1656 a4=0.14518390461225107425;
1657
1658 } else {
1659 print("invalid parameter a for poly4erfc: only 0.5 and 1.0 implemented");
1660 MADNESS_EXCEPTION("stupid you",1);
1661 }
1662 }
1663
1665
1666private:
1667
1668 /// the length scale parameter
1669 double a;
1670 double a0, a1, a2, a3, a4;
1671 double eprec_;
1672
1673 double a_param() const {return a;}
1674 double eprec_param() const {return eprec_;}
1675
1676 /// first derivative of the correlation factor wrt (r-R_A)
1677
1678 /// \f[
1679 /// Sr_div_S = \frac{1}{S(r)}\frac{\partial S(r)}{\partial r}
1680 /// \f]
1681 double Sr_div_S(const double& r, const double& Z) const {
1682 const double x=r*Z;
1683
1684 double result=0.0;
1685 if (a==0.5) {
1686 if (x<1.0) {
1687 result=(-17.97663543396820624361586474 + x*(32.78290319470982346841067868 +
1688 x*(-18.158574783628271659713638233 +
1689 x*(2.472138984374094343735335913 +
1690 x*(0.5516975358315341628276502285 +
1691 x*(-0.008573693952875097234391220137 +
1692 x*(-0.05596791202351071993748992739 +
1693 (0.002673799219133696315436690424 +
1694 0.0013386538660557369902632289083*x)*x)))))))/
1695 (17.976635433967702922140233083 + x*
1696 (-13.062204300852085089323266568 +
1697 x*(16.397871971437618641239835027 + x*(-5.383337491559214163188757918 + 1.*x))));
1698 } else if (x<2.0) {
1699 result=(-16.53370050883888159389958126 + x*(30.04151304875517461538549269 +
1700 x*(-16.692529697855029750948871179 +
1701 x*(2.50341008323651011875249567 +
1702 x*(0.3106921665634860719234742532 +
1703 x*(0.08721948207311506458903445571 +
1704 x*(-0.10041387133168708232852057948 +
1705 (0.02000987266876476192949541524 - 0.0012508983745483161308604975792*x)*
1706 x)))))))/
1707 (16.532205048243702951212522516 + x*
1708 (-11.89273747187279634240347945 +
1709 x*(15.157537549656745468895369276 + x*(-4.9102960292797655978798640519 + 1.*x))));
1710 } else if (x<5.0) {
1711 result=(-2352.191894900273554810118278 + x*(5782.846962269399174183661793 +
1712 x*(-5653.246084369776756298278851 +
1713 x*(2948.18046377483570925427449 +
1714 x*(-913.4583247839311453090142452 +
1715 x*(174.39391722588915386106331206 +
1716 x*(-20.22035127074332315930567933 +
1717 (1.3107321165711966663791114988 - 0.03655666729452579098523876463*x)*x))
1718 )))))/
1719 (886.4859678528423041797649741 + x*(269.17746130370931387996124706 +
1720 x*(-130.21383548057958115685397713 + x*(37.644499985765056273193347388 + 1.*x))));
1721 } else if (x<10) {
1722 result=(2.2759176275121988686860433041 + x*(-1.8014283464827425541637211503 +
1723 x*(0.60570955276433317373251991152 +
1724 x*(-0.11235368819003308411943926239 +
1725 x*(0.01243211635244600976892077538 +
1726 x*(-0.0008211800260491381826149891865 +
1727 x*(0.000029973534470203049782417744015 +
1728 (-4.6423722605763162431293872646e-7 -
1729 1.3224615425412157194986675329e-10*x)*x)))))))/
1730 (1039.800013929971888016478838 + x*(-702.5378531848183775210948787 +
1731 x*(183.17476380259879599459789974 + x*(-21.74106003575315304073197254 + 1.*x))));
1732 } else {
1733 result=0.0;
1734 }
1735 } else if (a==1.0) {
1736 if (x<1.0) {
1737 result=(-1.6046958001953006847027538457 + x*(5.948945186367159977879486279 +
1738 x*(-6.884321742840291285733040882 +
1739 x*(2.296896506418919905405783368 +
1740 x*(0.616939354810622973212914089 +
1741 x*(-0.13679830198890803519235207564 +
1742 x*(-0.3356576872066501398893403439 +
1743 (0.14876798925798674488426727928 - 0.016049886728185297028755535226*x)*x
1744 )))))))/
1745 (1.6046957999975126909719683196 + x*
1746 (-0.8234878506688316215458988304 +
1747 x*(3.4607641859010551501639903314 + x*(-1.8955210085531557309609670978 + 1.*x))));
1748 } else if (x<2.0) {
1749 result=(-7.143856421301985019580778813 + x*(33.35568129248075086686087865 +
1750 x*(-60.0412343766569246898209957 +
1751 x*(55.46407913315151830247939138 +
1752 x*(-28.7874770749840240158264326 +
1753 x*(8.379317837934083469035061852 +
1754 x*(-1.2103278392957399092107317741 +
1755 (0.04275186003977071121074860478 + 0.005247730112126140726731063205*x)*x
1756 )))))))/
1757 (5.4509691924562038998044993827 + x*
1758 (-2.2732931206867811068721699796 +
1759 x*(4.1530634219989859344450742259 + x*(-2.0183662125874366044951391259 + 1.*x))));
1760 } else if (x<5.0) {
1761 result=(-0.4869290414611847276899694883 + x*(1.0513417728218375522016338562 +
1762 x*(-0.9694851629317255156038942437 +
1763 x*(0.5007460889402078102011673774 +
1764 x*(-0.15897436623286639052954575417 +
1765 x*(0.03185042477631079356985872518 +
1766 x*(-0.003940899912654543218183049969 +
1767 (0.0002757919409481032696079686825 -
1768 8.369138363906178282041501561e-6*x)*x)))))))/
1769 (30.81121613134246115634780413 + x*(-49.989974505724725146933397436 +
1770 x*(31.455643953462635691568128729 + x*(-8.992097794824270871044305786 + 1.*x))));
1771 } else {
1772 result=0.0;
1773 }
1774 }
1775 return result*Z;
1776 }
1777
1778 /// second derivative of the correlation factor wrt (r-R_A)
1779
1780 /// \f[
1781 /// result = \frac{1}{S(r)}\frac{\partial^2 S(r)}{\partial r^2}
1782 /// \f]
1783 double Srr_div_S(const double& r, const double& Z) const {
1784 MADNESS_EXCEPTION("no Srr_div_S in Slater2 yet",0);
1785 return 0.0;
1786 }
1787
1788 /// third derivative of the correlation factor wrt (r-R_A)
1789
1790 /// \f[
1791 /// result = \frac{1}{S(r)}\frac{\partial^3 S(r)}{\partial r^3}
1792 /// \f]
1793 double Srrr_div_S(const double& r, const double& Z) const {
1794 MADNESS_EXCEPTION("no Srrr_div_S in Slater2 yet",0);
1795 return 0.0;
1796 }
1797
1798 /// the nuclear correlation factor
1799 double S(const double& r, const double& Z) const {
1800 const double arZ=a*r*Z;
1801 const double arZ2=a*a*r*r*Z*Z;
1802
1803 return 1.0 + (a0 +a1* arZ+ a2 * arZ2 + a3*arZ*arZ2 + + a4*arZ2*arZ2) *erfc( a*r*Z);
1804 }
1805
1806 /// radial part first derivative of the nuclear correlation factor
1807 coord_3d Sp(const coord_3d& vr1A, const double& Z) const {
1808 MADNESS_EXCEPTION("no Sp in Slater2 yet",0);
1809 return smoothed_unitvec(vr1A);;
1810 }
1811
1812 /// second derivative of the nuclear correlation factor
1813 double Spp_div_S(const double& r, const double& Z) const {
1814 const double x=r*Z;
1815 double result=0.0;
1816 if (a==0.5) {
1817 if (x<1.0) {
1818 result=(-37.75186842343823465059 + x*(21.3476988467348903615 +
1819 x*(0.014608707333424946750026 +
1820 x*(-3.704945314726273312722 +
1821 x*(0.08808104845382944292252 +
1822 x*(0.3362428305409206967066 +
1823 x*(-0.02288039625102549092766 +
1824 (-0.017240056622850307571001 + 0.002412740490618117536527*x)*x)))))))/
1825 (17.595611361287293183447 + x*(-12.421065066789808273295 +
1826 x*(15.957564552156320207938 + x*(-5.0239100389132464317907 + 1.*x))));
1827 } else if (x<2.0) {
1828 result=(-35.46082798344982189328 + x*(20.3565414350879797493 +
1829 x*(-0.3046488975234456455871 +
1830 x*(-3.298067641731523613442 +
1831 x*(-0.10712268902574947466554 +
1832 x*(0.4829111116912435121877 +
1833 x*(-0.10089023589818206760275 +
1834 (0.0013899828749998182176948 + 0.0008305150868988335610678*x)*x)))))))/
1835 (16.526499668833810286111 + x*(-11.79820182874024593006 +
1836 x*(15.115407083582433322342 + x*(-4.8449266197426825174319 + 1.*x))));
1837 } else if (x<5.0) {
1838 result=(-414.5311559516023264104 + x*(615.8720414166440747539 +
1839 x*(-422.5938440932793094888 + x*
1840 (159.72497494584873155352 +
1841 x*(-35.6790348104188081907 +
1842 x*(4.658777521872728594702 +
1843 x*(-0.328305094433759490678 +
1844 (0.009162754689309596905172 + 0.00005047926659010755662873*x)*x)))))))/
1845 (112.7044543272820830484 + x*(-56.072518762714727894479 +
1846 x*(28.188843903409059322224 + x*(-6.519554545057610040741 + 1.*x))));
1847 } else if (x<10.0) {
1848 result=(-146.68256559112012287314 + x*(188.52807059353309478385 +
1849 x*(-82.07176992590032524431 + x*
1850 (18.107697718347802322776 +
1851 x*(-2.3221393933622638466979 +
1852 x*(0.18681223946803275939642 +
1853 x*(-0.009601011427143648072501 +
1854 (0.00028623295732553770894583 - 3.77364531155112782235e-6*x)*x)))))))/
1855 (633.1319105785227043552 + x*(-574.29230199331494406798 +
1856 x*(171.872612865808639376 + x*(-21.906495121260483674385 + 1.*x))));
1857 } else {
1858 result=-1.0/x;
1859 }
1860 } else if (a==1.0) {
1861 if (x<1.0) {
1862 result=(-8.85288955131414420808 + x*(11.359434597010419928515 +
1863 x*(-2.982094072176256165405 + x*
1864 (-4.924201512880445076103 +
1865 x*(0.6773928043289287907009 +
1866 x*(2.061680233090141287213 +
1867 x*(-0.5528612000728412913713 +
1868 (-0.3024276764350212595121 + 0.10765958646570631264003*x)*x)))))))/
1869 (1.6731803922436094206275 + x*(-0.8242052614481793487834 +
1870 x*(3.5912910648514747558597 + x*(-1.9146644266104277222142 + 1.*x))));
1871 } else if (x<2.0) {
1872 result=(-8.538839434207355205544 + x*(-37.85611260277589742674 +
1873 x*(155.08466711228234382211 + x*
1874 (-241.1247881821171613212 +
1875 x*(199.33293375918859716585 +
1876 x*(-96.80750216221383928113 +
1877 x*(27.71704080319043943288 +
1878 (-4.354251431065185902435 + 0.2906781051124817624589*x)*x)))))))/
1879 (2.2233877901091612794108 + x*(3.2084406367698851844258 +
1880 x*(1.021615116328133792993 + x*(-0.9819667717342250528772 + 1.*x))));
1881 } else if (x<5.0) {
1882 result=(-7.338671998425412491091 + x*(18.593867285988629508481 +
1883 x*(-19.15344657249203844577 + x*
1884 (10.072359942912659732126 +
1885 x*(-2.99771628023376895151 +
1886 x*(0.5324416109232007541639 +
1887 x*(-0.05993976172902101376555 +
1888 (0.003887110757665478374745 - 0.00011079212872583089652945*x)*x)))))))/
1889 (13.273604111590967002999 + x*(-28.012330064250556933961 +
1890 x*(22.161347591665727407914 + x*(-7.617582259533338164664 + 1.*x))));
1891 } else if (x<10) {
1892 result=(132.78397650676876308801 + x*(-78.01898251977413923271 +
1893 x*(15.292039515801252996504 + x*
1894 (-1.000000154745351328125 +
1895 x*(1.950300262619412492847e-8 +
1896 x*(-1.6337541591423364318692e-9 +
1897 x*(8.771557330523968791519e-11 +
1898 (-2.7388800346031121159372e-12 + 3.7894572289998844980568e-14*x)*x))))))
1899 )/(-4.724326520908917985827e-6 + x*
1900 (-132.78397108375581258096 + x*(78.01897976124964688489 +
1901 x*(-15.292038699709498552356 + 1.*x))));
1902 } else {
1903 result=-1.0/x;
1904 }
1905 }
1906 return result*Z*Z;
1907 }
1908
1909
1910 /// derivative of the U2 potential wrt X (scalar part)
1911
1912 /// with
1913 /// \f[
1914 /// \rho = \left| \vec r- \vec R_A \right|
1915 /// \f]
1916 /// returns the term in the parenthesis without the the derivative of rho
1917 /// \f[
1918 /// \frac{\partial U_2}{\partial X_A} = \frac{\partial \rho}{\partial X}
1919 /// \left(-\frac{1}{2}\frac{S''' S - S'' S'}{S^2} + \frac{1}{\rho^2}\frac{S'}{S}
1920 /// - \frac{1}{\rho} \frac{S''S - S'^2}{S^2} + \frac{Z_A}{\rho^2}\right)
1921 /// \f]
1922 double U2X_spherical(const double& r, const double& Z, const double& rcut) const {
1923 MADNESS_EXCEPTION("no U2X_spherical in Slater2 yet",0);
1924 return 0.0;
1925 }
1926
1927};
1928
1929
1930
1931/// A nuclear correlation factor class
1932
1933/// should reduce to quartic for N=4
1934/// @tparam N the exponent of the polynomial
1935template<std::size_t N>
1937public:
1938 /// ctor
1939
1940 /// @param[in] world the world
1941 /// @param[in] mol molecule with the sites of the nuclei
1942 Polynomial(World& world, const Molecule& mol, const double a)
1944
1945 /// length scale parameter a, default chosen that linear terms in U2 vanish
1946 a_=(2. + (-2. + sqrt(-1. + N))*N)/(-2. + N);
1947
1948 if (a!=0.0) a_=a;
1949
1950 if (world.rank()==0) {
1951 print("constructed nuclear correlation factor of the form");
1952 print(" R = Prod_A S_A");
1953 print(" S_A = 1 + a (r/b -1)^N if r<b, with b= (N*a)/((1+a) Z)");
1954 print(" = 1 else ");
1955 print("with eprec ",mol.get_eprec());
1956 print("which is of polynomial type with exponent N = ",N);
1957 }
1958 }
1959
1961
1962private:
1963
1964 /// length scale parameter a, default chosen that linear terms in U2 vanish
1965 double a_;
1966
1967 double a_param() const {return a_;}
1968
1969 /// the cutoff
1970 static double b_param(const double& a) {return N*a/(1.0+a);}
1971
1972 /// the nuclear correlation factor
1973 double S(const double& r, const double& Z) const {
1974
1975 const double rho=r*Z;
1976 const double a=Polynomial<N>::a_param();
1977 const double b=Polynomial<N>::b_param(a);
1978
1979 if (rho<b) {
1980 const double arg=-1.0 + rho/b;
1981 return 1.0 + power<N>(-1.0) * a*power<N>(arg);
1982 } else {
1983 return 1.0;
1984 }
1985
1986 }
1987
1988 /// radial part first derivative of the nuclear correlation factor
1989 coord_3d Sp(const coord_3d& vr1A, const double& Z) const {
1990
1991 const double r=vr1A.normf();
1992 const double rho=r*Z;
1993 const double a=Polynomial<N>::a_param();
1994 const double b=Polynomial<N>::b_param(a);
1995
1996 if (rho<b) {
1997 return power<N>(-1.)*(1.+a)* Z* power<N-1>(-1.+rho/b)*smoothed_unitvec(vr1A);
1998 }
1999 return coord_3d(0.0);
2000 }
2001
2002 /// second derivative of the nuclear correlation factor
2003
2004 /// -1/2 S"/S - Z/r
2005 double Spp_div_S(const double& r, const double& Z) const {
2006
2007 const double rho=r*Z;
2008 const double a=Polynomial<N>::a_param();
2009 const double b=Polynomial<N>::b_param(a);
2010
2011 if (rho<1.e-6) {
2012 const double ap1=1.0+a;
2013 const double c0=((3. *(1. + a) - (3. + a) * N))/(2.* a*N);
2014 const double c1=((2.* ap1*ap1 - ap1* (3. + a)*N + N*N)*Z)/(a*a*N*N);
2015 const double c2=((30.*ap1*ap1*ap1- ap1*ap1* (55 + 18* a)*N +
2016 30 *ap1 *N*N + (-5 + a* (8 + a)) *N*N*N)* Z*Z)/(12 *a*a*a*N*N*N);
2017 return Z*Z*(c0 + c1*r + c2*r*r);
2018
2019 } else if (rho<b) {
2020
2021 const double num=Z* (2 + (power<N>(-1)* a* power<N>(-1 + rho/b)
2022 * (-2 *a*N*N + (1 + a) *N* (1 + a *(-3 + static_cast<int>(N)) + N)* rho +
2023 2 *(1 + a)*(1+a)* rho*rho))/power<2>(a* N - (1 + a)*rho));
2024
2025 const double denom=2.* (r + power<N>(-1) *a* r* power<N>(-1 + rho/b));
2026 return -num/denom;
2027
2028 } else {
2029 return -Z*Z/rho;
2030 }
2031 }
2032
2033 double Sr_div_S(const double& r, const double& Z) const {
2034 const double rho=r*Z;
2035 const double a=Polynomial<N>::a_param();
2036 const double b=Polynomial<N>::b_param(a);
2037
2038 if (rho<b) {
2039 const double negn= power<N>(-1.0);
2040 const double num=(negn*(1 + a)*Z*power<N-1>(-1 + ((1 + a)*r*Z)/(a*N)));
2041 const double denom=(1 + negn*a*power<N>(-1 + ((1 + a)*r*Z)/(a*N)));
2042 return num/denom;
2043 } else {
2044 return 0.0;
2045 }
2046
2047 }
2048
2049 double Srr_div_S(const double& r, const double& Z) const {
2050 const double rho=r*Z;
2051 const double a=Polynomial<N>::a_param();
2052 const double b=Polynomial<N>::b_param(a);
2053
2054 if (rho<b) {
2055 const double negn= power<N>(-1.0);
2056 return (negn*power<2>(1 + a)*(-1 + static_cast<int>(N))*power<2>(Z)*power<N-2>(-1 + ((1 + a)*r*Z)/(a*N)))/
2057 (a*N*(1 + negn*a*power<N>(-1 + ((1 + a)*r*Z)/(a*N))));
2058 } else {
2059 return 0.0;
2060 }
2061 }
2062
2063 double Srrr_div_S(const double& r, const double& Z) const {
2064 const double rho=r*Z;
2065 const double a=Polynomial<N>::a_param();
2066 const double b=Polynomial<N>::b_param(a);
2067
2068 if (rho<b) {
2069 const double negn= power<N>(-1.0);
2070 return (negn*power<3>(1 + a)*(-2 + static_cast<int>(N))*(-1 + static_cast<int>(N))*power<3>(Z)*power<N-3>(-1 + ((1 + a)*r*Z)/(a*N)))/
2071 (power<2>(a*N)*(1 + negn*a*power<N>(-1 + ((1 + a)*r*Z)/(a*N))));
2072 } else {
2073 return 0.0;
2074 }
2075 }
2076
2077 double U2X_spherical(const double& r, const double& Z, const double& rcut) const {
2078 const double a=a_param();
2079 const double aopt=(2. + (-2. + sqrt(-1. + N))*N)/(-2. + N);
2080 if (fabs(a-aopt)>1.e-10) {
2081 MADNESS_EXCEPTION("U2X_spherical for polynomial ncf only with aopt",1);
2082 }
2083
2084 double result=0.0;
2085 if (r*Z<1.e-4) {
2086 const double rn=sqrt(N-1);
2087 const double r0=0.0;
2088 const double r1=((2.*(-8. + 9.*rn) + N*(25. + 10.*rn + N))*r*power<4>(Z))/
2089 (6.*power<2>(-2 + static_cast<int>(N))*rn);
2090 const double r2=((-4*(17 + 9*rn) + N*(92 + 80*rn +
2091 N*(-29 - 33*rn + N*(4 + 7*rn + N))))*power<5>(Z))/
2092 (8.*power<3>(-2 + static_cast<int>(N))*(-1 + static_cast<int>(N))*rn);
2093 result=(r0 + r*r1 + r*r*r2);
2094
2095 } else {
2096 const double S1=Sr_div_S(r,Z);
2097 const double S2=Srr_div_S(r,Z);
2098 const double S3=Srrr_div_S(r,Z);
2099 const double term1=-0.5*(S3-S1*S2);
2100 const double term2=(S1+Z)/(r*r);
2101 const double term3=(S2-S1*S1)/r;
2102 result=term1+term2-term3;
2103 }
2104 return result;
2105 }
2106
2107};
2108
2110
2111public:
2112 /// ctor
2113
2114 /// @param[in] world the world
2115 /// @param[in] mol molecule with the sites of the nuclei
2117 const std::shared_ptr<PotentialManager> pot, const double fac)
2118 : NuclearCorrelationFactor(world,mol), potentialmanager(pot),
2119 eprec(mol.get_eprec()), fac(fac) {
2120
2121 if (world.rank()==0) {
2122 print("constructed nuclear correlation factor of the form");
2123 print(" R = ",fac);
2124 print("with eprec ",mol.get_eprec());
2125 print("which means it's (nearly) a conventional calculation\n");
2126 }
2127
2128 // add the missing -Z/r part to U2!
2129 }
2130
2131 corrfactype type() const {return None;}
2132
2133 /// return the U2 term of the correlation function
2134
2135 /// overloading to avoid inconsistent state of U2, which needs the
2136 /// nuclear potential
2137 const real_function_3d U2() const {
2138
2139// if (not U2_function.is_initialized()) {
2140 MADNESS_ASSERT(potentialmanager->vnuclear().is_initialized());
2141// }
2142 return potentialmanager->vnuclear();
2143 }
2144
2145 /// apply the regularized potential U_nuc on a given function rhs
2146
2147 /// overload the base class method for efficiency
2149 return (U2()*rhs).truncate();
2150 }
2151
2152
2153private:
2154
2155 /// underlying potential (=molecule)
2156 std::shared_ptr<PotentialManager> potentialmanager;
2157 double eprec;
2158
2159 /// the factor of the correlation factor: R=fac;
2160 const double fac;
2161
2162 double Sr_div_S(const double& r, const double& Z) const {return 0.0;}
2163
2164 double Srr_div_S(const double& r, const double& Z) const {return 0.0;}
2165
2166 double Srrr_div_S(const double& r, const double& Z) const {return 0.0;}
2167
2168 /// the nuclear correlation factor
2169 double S(const double& r, const double& Z) const {
2170 return fac;
2171 }
2172
2173 /// radial part first derivative of the nuclear correlation factor
2174 coord_3d Sp(const coord_3d& vr1A, const double& Z) const {
2175 return coord_3d(0.0);
2176 }
2177
2178 /// second derivative of the nuclear correlation factor
2179 double Spp_div_S(const double& r, const double& Z) const {
2180 double rcut= 1.0 / smoothing_parameter(Z, eprec);
2181 return - Z * smoothed_potential(r*rcut)*rcut;
2182 }
2183
2184 double U2X_spherical(const double& r, const double& Z, const double& rcut) const {
2185 // factor -1 from the definition of the dsmoothed_potential as -1/r^2
2186 return -Z*dsmoothed_potential(r * rcut) * (rcut * rcut);
2187 }
2188
2189};
2190
2191
2192/// this ncf has no information about itself, only U2 and U1 assigned
2194
2195public:
2196 /// ctor
2197
2198 /// @param[in] world the world
2199 /// @param[in] mol molecule with the sites of the nuclei
2201 const std::vector<real_function_3d>& U1)
2203
2204 U2_function=U2;
2205 U1_function=U1;
2206
2207 if (world.rank()==0) {
2208 print("constructed ad hoc nuclear correlation factor");
2209 }
2210 }
2211
2212 corrfactype type() const {return Adhoc;}
2213
2214private:
2215
2216 double Sr_div_S(const double& r, const double& Z) const {
2217 MADNESS_EXCEPTION("no Sr_div_S() in AdhocNuclearCorrelationFactor",0);
2218 return 0.0;
2219 }
2220
2221 double Srr_div_S(const double& r, const double& Z) const {
2222 MADNESS_EXCEPTION("no Srr_div_S() in AdhocNuclearCorrelationFactor",0);
2223 return 0.0;
2224 }
2225
2226 double Srrr_div_S(const double& r, const double& Z) const {
2227 MADNESS_EXCEPTION("no Srrr_div_S() in AdhocNuclearCorrelationFactor",0);
2228 return 0.0;
2229 }
2230
2231 /// the nuclear correlation factor
2232 double S(const double& r, const double& Z) const {
2233 MADNESS_EXCEPTION("no S() in AdhocNuclearCorrelationFactor",0);
2234 return 0.0;
2235 }
2236
2237 /// radial part first derivative of the nuclear correlation factor
2238 coord_3d Sp(const coord_3d& vr1A, const double& Z) const {
2239 MADNESS_EXCEPTION("no Sp() in AdhocNuclearCorrelationFactor",0);
2240 return coord_3d(0.0);
2241 }
2242
2243 /// second derivative of the nuclear correlation factor
2244 double Spp_div_S(const double& r, const double& Z) const {
2245 MADNESS_EXCEPTION("no Spp_div_S() in AdhocNuclearCorrelationFactor",0);
2246 return 0.0;
2247 }
2248};
2249
2250
2251std::shared_ptr<NuclearCorrelationFactor>
2253 const Molecule& molecule,
2254 const std::shared_ptr<PotentialManager> pm,
2255 const std::string inputline);
2256
2257std::shared_ptr<NuclearCorrelationFactor>
2259 const Molecule& molecule,
2260 const std::shared_ptr<PotentialManager> pm,
2261 const std::pair<std::string,double>& ncf);
2262
2263}
2264
2265
2266#endif /* NUCLEARCORRELATIONFACTOR_H_ */
Declaration of utility class and functions for atom.
this ncf has no information about itself, only U2 and U1 assigned
Definition correlationfactor.h:2193
double Spp_div_S(const double &r, const double &Z) const
second derivative of the nuclear correlation factor
Definition correlationfactor.h:2244
double Sr_div_S(const double &r, const double &Z) const
Definition correlationfactor.h:2216
coord_3d Sp(const coord_3d &vr1A, const double &Z) const
radial part first derivative of the nuclear correlation factor
Definition correlationfactor.h:2238
corrfactype type() const
Definition correlationfactor.h:2212
double Srr_div_S(const double &r, const double &Z) const
Definition correlationfactor.h:2221
AdhocNuclearCorrelationFactor(World &world, const real_function_3d U2, const std::vector< real_function_3d > &U1)
ctor
Definition correlationfactor.h:2200
double S(const double &r, const double &Z) const
the nuclear correlation factor
Definition correlationfactor.h:2232
double Srrr_div_S(const double &r, const double &Z) const
Definition correlationfactor.h:2226
Definition molecule.h:60
double y
Definition molecule.h:62
double x
Definition molecule.h:62
double z
Definition molecule.h:62
madness::Vector< double, 3 > get_coords() const
Definition molecule.h:106
double q
Coordinates and charge in atomic units.
Definition molecule.h:62
FunctionDefaults holds default paramaters as static class members.
Definition funcdefaults.h:101
Abstract base class interface required for functors used as input to Functions.
Definition function_interface.h:68
void set_length_scale(double lo)
adapt the special level to resolve the smallest length scale
Definition function_interface.h:80
double thresh() const
Returns value of truncation threshold. No communication.
Definition mra.h:673
void set_thresh(double value, bool fence=true)
Sets the value of the truncation threshold. Optional global fence.
Definition mra.h:683
Function< T, NDIM > & truncate(double tol=0.0, bool fence=true)
Truncate the function with optional fence. Compresses with fence if not compressed.
Definition mra.h:708
const Function< T, NDIM > & compress(bool fence=true) const
Compresses the function, transforming into wavelet basis. Possible non-blocking comm.
Definition mra.h:882
A nuclear correlation factor class.
Definition correlationfactor.h:1105
GaussSlater(World &world, const Molecule &mol)
ctor
Definition correlationfactor.h:1111
double Srr_div_S(const double &r, const double &Z) const
Definition correlationfactor.h:1172
double S(const double &r, const double &Z) const
the nuclear correlation factor
Definition correlationfactor.h:1129
double U2X_spherical(const double &r, const double &Z, const double &rcut) const
derivative of the U2 potential wrt X (scalar part)
Definition correlationfactor.h:1203
double Srrr_div_S(const double &r, const double &Z) const
Definition correlationfactor.h:1181
double Spp_div_S(const double &r, const double &Z) const
second derivative of the nuclear correlation factor
Definition correlationfactor.h:1149
corrfactype type() const
Definition correlationfactor.h:1124
coord_3d Sp(const coord_3d &vr1A, const double &Z) const
radial part first derivative of the nuclear correlation factor
Definition correlationfactor.h:1135
double Sr_div_S(const double &r, const double &Z) const
Definition correlationfactor.h:1163
A nuclear correlation factor class.
Definition correlationfactor.h:1237
double Srr_div_S(const double &r, const double &Z) const
Definition correlationfactor.h:1320
double S(const double &r, const double &Z) const
the nuclear correlation factor
Definition correlationfactor.h:1264
coord_3d Sp(const coord_3d &vr1A, const double &Z) const
radial part first derivative of the nuclear correlation factor
Definition correlationfactor.h:1270
double U2X_spherical(const double &r, const double &Z, const double &rcut) const
derivative of the U2 potential wrt nuclear coordinate X (spherical part)
Definition correlationfactor.h:1341
const double a
Definition correlationfactor.h:1261
double Srrr_div_S(const double &r, const double &Z) const
Definition correlationfactor.h:1330
double Spp_div_S(const double &r, const double &Z) const
second derivative of the nuclear correlation factor
Definition correlationfactor.h:1284
double Sr_div_S(const double &r, const double &Z) const
Definition correlationfactor.h:1310
GradientalGaussSlater(World &world, const Molecule &mol, const double a)
ctor
Definition correlationfactor.h:1243
corrfactype type() const
Definition correlationfactor.h:1257
A nuclear correlation factor class.
Definition correlationfactor.h:1381
LinearSlater(World &world, const Molecule &mol, const double a)
ctor
Definition correlationfactor.h:1387
double Srr_div_S(const double &r, const double &Z) const
Definition correlationfactor.h:1456
coord_3d Sp(const coord_3d &vr1A, const double &Z) const
radial part first derivative of the nuclear correlation factor
Definition correlationfactor.h:1418
double S(const double &r, const double &Z) const
the nuclear correlation factor
Definition correlationfactor.h:1411
double Sr_div_S(const double &r, const double &Z) const
Definition correlationfactor.h:1450
double a_param() const
Definition correlationfactor.h:1408
double a_
the length scale parameter a
Definition correlationfactor.h:1406
double Srrr_div_S(const double &r, const double &Z) const
Definition correlationfactor.h:1462
corrfactype type() const
Definition correlationfactor.h:1401
double Spp_div_S(const double &r, const double &Z) const
second derivative of the nuclear correlation factor
Definition correlationfactor.h:1432
Definition molecule.h:129
double atomic_attraction_potential(int iatom, double x, double y, double z) const
nuclear attraction potential for a specific atom in the molecule
Definition molecule.cc:1112
const Atom & get_atom(unsigned int i) const
Definition molecule.cc:502
size_t natom() const
Definition molecule.h:463
double get_eprec() const
Definition molecule.h:495
double nuclear_attraction_potential_derivative(int atom, int axis, double x, double y, double z) const
Definition molecule.cc:1125
compute the derivative of R wrt the displacement of atom A, coord axis
Definition correlationfactor.h:887
double operator()(const coord_3d &xyz) const override
Definition correlationfactor.h:908
std::vector< coord_3d > special_points() const override
Override this to return list of special points to be refined more deeply.
Definition correlationfactor.h:934
const NuclearCorrelationFactor * ncf
Definition correlationfactor.h:888
const Atom & thisatom
Definition correlationfactor.h:889
const int derivativeaxis
Definition correlationfactor.h:890
RX_functor(const NuclearCorrelationFactor *ncf, const Atom &atom1, const int daxis, const int exponent)
1 or 2 -> R^X or R^X R
Definition correlationfactor.h:894
const int exponent
direction of the derivative operator
Definition correlationfactor.h:891
RX_functor(const NuclearCorrelationFactor *ncf, const int iatom, const int daxis, const int exponent)
Definition correlationfactor.h:900
Definition correlationfactor.h:501
R_functor(const NuclearCorrelationFactor *ncf, const int e=1)
Definition correlationfactor.h:505
double operator()(const coord_3d &xyz) const override
Definition correlationfactor.h:510
int exponent
Definition correlationfactor.h:503
bool supports_vectorized() const override
Does the interface support a vectorized operator()?
Definition correlationfactor.h:513
const NuclearCorrelationFactor * ncf
Definition correlationfactor.h:502
double eval(const coord_3d &xyz, const std::vector< size_t > &atoms) const
an atom beyond its screening radius contributes the factor 1
Definition correlationfactor.h:522
void operator()(const Vector< double *, 3 > &xv, double *fv, int npts) const override
Definition correlationfactor.h:514
std::vector< coord_3d > special_points() const override
Override this to return list of special points to be refined more deeply.
Definition correlationfactor.h:538
compute the derivative of U1 wrt the displacement of atom A, coord axis
Definition correlationfactor.h:942
const NuclearCorrelationFactor * ncf
Definition correlationfactor.h:943
const int U1axis
Definition correlationfactor.h:945
U1X_functor(const NuclearCorrelationFactor *ncf, const int iatom, const int U1axis, const int daxis)
Definition correlationfactor.h:955
U1X_functor(const NuclearCorrelationFactor *ncf, const Atom &atom1, const int U1axis, const int daxis)
direction of the derivative operator
Definition correlationfactor.h:948
double operator()(const coord_3d &xyz) const override
Definition correlationfactor.h:965
const Atom & thisatom
Definition correlationfactor.h:944
const int derivativeaxis
U1x/U1y/U1z potential?
Definition correlationfactor.h:946
std::vector< coord_3d > special_points() const override
Override this to return list of special points to be refined more deeply.
Definition correlationfactor.h:979
U1 functor for a specific atom.
Definition correlationfactor.h:593
double operator()(const coord_3d &xyz) const override
Definition correlationfactor.h:603
const size_t iatom
Definition correlationfactor.h:596
std::vector< coord_3d > special_points() const override
Override this to return list of special points to be refined more deeply.
Definition correlationfactor.h:611
U1_atomic_functor(const NuclearCorrelationFactor *ncf, const size_t atom, const int axis)
Definition correlationfactor.h:600
const int axis
Definition correlationfactor.h:597
const NuclearCorrelationFactor * ncf
Definition correlationfactor.h:595
functor for a local U1 dot U1 potential
Definition correlationfactor.h:628
void operator()(const Vector< double *, 3 > &xv, double *fv, int npts) const override
Definition correlationfactor.h:640
double operator()(const coord_3d &xyz) const override
Definition correlationfactor.h:636
double eval(const coord_3d &xyz, const std::vector< size_t > &atoms) const
Definition correlationfactor.h:647
std::vector< coord_3d > special_points() const override
Override this to return list of special points to be refined more deeply.
Definition correlationfactor.h:670
const NuclearCorrelationFactor * ncf
Definition correlationfactor.h:630
U1_dot_U1_functor(const NuclearCorrelationFactor *ncf)
Definition correlationfactor.h:633
bool supports_vectorized() const override
Does the interface support a vectorized operator()?
Definition correlationfactor.h:639
functor for the local part of the U1 potential – NOTE THE SIGN
Definition correlationfactor.h:546
void operator()(const Vector< double *, 3 > &xv, double *fv, int npts) const override
Definition correlationfactor.h:562
std::vector< coord_3d > special_points() const override
Override this to return list of special points to be refined more deeply.
Definition correlationfactor.h:581
double eval(const coord_3d &xyz, const std::vector< size_t > &atoms) const
Definition correlationfactor.h:569
bool supports_vectorized() const override
Does the interface support a vectorized operator()?
Definition correlationfactor.h:561
const int axis
Definition correlationfactor.h:549
U1_functor(const NuclearCorrelationFactor *ncf, const int axis)
Definition correlationfactor.h:552
double operator()(const coord_3d &xyz) const override
Definition correlationfactor.h:558
const NuclearCorrelationFactor * ncf
Definition correlationfactor.h:548
compute the derivative of U2 wrt the displacement of atom A
Definition correlationfactor.h:991
const int iatom
Definition correlationfactor.h:993
const int axis
Definition correlationfactor.h:994
std::vector< coord_3d > special_points() const override
Override this to return list of special points to be refined more deeply.
Definition correlationfactor.h:1017
const NuclearCorrelationFactor * ncf
Definition correlationfactor.h:992
U2X_functor(const NuclearCorrelationFactor *ncf, const int &atom1, const int axis)
Definition correlationfactor.h:996
double operator()(const coord_3d &xyz) const override
Definition correlationfactor.h:1004
U2 functor for a specific atom.
Definition correlationfactor.h:756
const size_t iatom
Definition correlationfactor.h:759
double operator()(const coord_3d &xyz) const override
Definition correlationfactor.h:766
std::vector< coord_3d > special_points() const override
Override this to return list of special points to be refined more deeply.
Definition correlationfactor.h:773
const NuclearCorrelationFactor * ncf
Definition correlationfactor.h:758
U2_atomic_functor(const NuclearCorrelationFactor *ncf, const size_t atom)
Definition correlationfactor.h:762
Definition correlationfactor.h:676
double operator()(const coord_3d &xyz) const override
Definition correlationfactor.h:682
const NuclearCorrelationFactor * ncf
Definition correlationfactor.h:677
double eval(const coord_3d &xyz, const std::vector< size_t > &near) const
the atoms in near (ascending) exactly, the others through the Coulomb tail of S''/S
Definition correlationfactor.h:694
std::vector< coord_3d > special_points() const override
Override this to return list of special points to be refined more deeply.
Definition correlationfactor.h:710
bool supports_vectorized() const override
Does the interface support a vectorized operator()?
Definition correlationfactor.h:685
U2_functor(const NuclearCorrelationFactor *ncf)
Definition correlationfactor.h:679
void operator()(const Vector< double *, 3 > &xv, double *fv, int npts) const override
Definition correlationfactor.h:686
compute the derivative of U3 wrt the displacement of atom A, coord axis
Definition correlationfactor.h:1040
std::vector< coord_3d > special_points() const override
Override this to return list of special points to be refined more deeply.
Definition correlationfactor.h:1091
U3X_functor(const NuclearCorrelationFactor *ncf, const size_t iatom, const int axis)
Definition correlationfactor.h:1045
const NuclearCorrelationFactor * ncf
Definition correlationfactor.h:1041
const int axis
Definition correlationfactor.h:1043
const size_t iatom
Definition correlationfactor.h:1042
double operator()(const coord_3d &xyz) const override
Definition correlationfactor.h:1049
U3 functor for a specific atom.
Definition correlationfactor.h:784
const size_t iatom
Definition correlationfactor.h:787
const NuclearCorrelationFactor * ncf
Definition correlationfactor.h:786
double operator()(const coord_3d &xyz) const override
Definition correlationfactor.h:794
std::vector< coord_3d > special_points() const override
Override this to return list of special points to be refined more deeply.
Definition correlationfactor.h:818
U3_atomic_functor(const NuclearCorrelationFactor *ncf, const int atom)
Definition correlationfactor.h:790
Definition correlationfactor.h:715
void operator()(const Vector< double *, 3 > &xv, double *fv, int npts) const override
Definition correlationfactor.h:725
double eval(const coord_3d &xyz, const std::vector< size_t > &atoms) const
Definition correlationfactor.h:732
const NuclearCorrelationFactor * ncf
Definition correlationfactor.h:716
U3_functor(const NuclearCorrelationFactor *ncf)
Definition correlationfactor.h:718
double operator()(const coord_3d &xyz) const override
Definition correlationfactor.h:721
std::vector< coord_3d > special_points() const override
Override this to return list of special points to be refined more deeply.
Definition correlationfactor.h:750
bool supports_vectorized() const override
Does the interface support a vectorized operator()?
Definition correlationfactor.h:724
std::vector< coord_3d > special_points() const override
Override this to return list of special points to be refined more deeply.
Definition correlationfactor.h:881
const Molecule & molecule
Definition correlationfactor.h:859
const size_t iatom
Definition correlationfactor.h:860
const NuclearCorrelationFactor * ncf
Definition correlationfactor.h:858
square_times_V_derivative_functor(const NuclearCorrelationFactor *ncf, const Molecule &molecule1, const size_t atom1, const int axis1)
Definition correlationfactor.h:863
double operator()(const coord_3d &xyz) const override
Definition correlationfactor.h:868
const size_t iatom
Definition correlationfactor.h:831
const NuclearCorrelationFactor * ncf
Definition correlationfactor.h:829
square_times_V_functor(const NuclearCorrelationFactor *ncf, const Molecule &mol, const size_t iatom1)
Definition correlationfactor.h:833
double operator()(const coord_3d &xyz) const override
Definition correlationfactor.h:838
std::vector< coord_3d > special_points() const override
Override this to return list of special points to be refined more deeply.
Definition correlationfactor.h:851
const Molecule & molecule
Definition correlationfactor.h:830
ABC for the nuclear correlation factors.
Definition correlationfactor.h:86
double eprec
smoothing of the potential/step function
Definition correlationfactor.h:232
std::shared_ptr< FunctionFunctorInterface< double, 3 > > functorT
Definition correlationfactor.h:90
virtual const real_function_3d U2() const
return the U2 term of the correlation function
Definition correlationfactor.h:221
virtual real_function_3d square() const
return the square of the nuclear correlation factor
Definition correlationfactor.h:180
virtual double screening_radius(const double) const
distance from nucleus A beyond which its contributions to the functors are negligible
Definition correlationfactor.h:289
double vtol
the threshold for initial projection
Definition correlationfactor.h:229
virtual double Srrr_div_S(const double &r, const double &Z) const =0
virtual real_function_3d function() const
return the nuclear correlation factor
Definition correlationfactor.h:172
coord_3d smoothed_unitvec(const coord_3d &xyz, double smoothing=0.0) const
smoothed unit vector for the computation of the U1 potential
Definition correlationfactor.h:376
const Molecule & molecule
the molecule
Definition correlationfactor.h:235
virtual real_function_3d apply_U(const real_function_3d &rhs) const
apply the regularized potential U_nuc on a given function rhs
Definition correlationfactor.h:154
virtual real_function_3d inverse() const
return the inverse nuclear correlation factor
Definition correlationfactor.h:199
virtual double Spp_div_S(const double &r, const double &Z) const =0
the regularized potential wrt a given atom wrt the cartesian coordinate
World & world
the world
Definition correlationfactor.h:226
real_function_3d U2_function
the purely local U2 potential, having absorbed the nuclear pot V_nuc
Definition correlationfactor.h:243
std::vector< size_t > all_atoms_
Definition correlationfactor.h:236
virtual ~NuclearCorrelationFactor()
virtual destructor
Definition correlationfactor.h:103
virtual double U2X_spherical(const double &r, const double &Z, const double &rcut) const
derivative of the U2 potential wrt nuclear coordinate X (spherical part)
Definition correlationfactor.h:354
std::vector< size_t > atoms_near(const double *x, const double *y, const double *z, const int npts) const
atoms whose screening sphere meets the bounding sphere of a set of points
Definition correlationfactor.h:300
virtual double S(const double &r, const double &Z) const =0
the correlation factor S wrt a given atom
virtual real_function_3d square_times_V_derivative(const int iatom, const int axis) const
Definition correlationfactor.h:191
void initialize(const double vtol1)
initialize the regularized potentials U1 and U2
Definition correlationfactor.h:113
virtual coord_3d Sp(const coord_3d &vr1A, const double &Z) const =0
the partial derivative of correlation factor S' wrt the cartesian coordinates
virtual const real_function_3d U1(const int axis) const
return the U1 term of the correlation function
Definition correlationfactor.h:207
NuclearCorrelationFactor(World &world, const Molecule &mol)
ctor
Definition correlationfactor.h:96
std::vector< real_function_3d > U1_function
the three components of the U1 potential
Definition correlationfactor.h:240
virtual corrfactype type() const =0
std::vector< real_function_3d > U1vec() const
return the U1 functions in a vector
Definition correlationfactor.h:212
coord_3d dsmoothed_unitvec(const coord_3d &xyz, const int axis, double smoothing=0.0) const
derivative of smoothed unit vector wrt the electronic coordinate
Definition correlationfactor.h:444
static constexpr int ncf_special_level
projection depth of the factor's functions at the nuclei
Definition correlationfactor.h:110
virtual double Srr_div_S(const double &r, const double &Z) const =0
corrfactype
Definition correlationfactor.h:88
@ Two
Definition correlationfactor.h:89
@ LinearSlater
Definition correlationfactor.h:88
@ GradientalGaussSlater
Definition correlationfactor.h:88
@ poly4erfc
Definition correlationfactor.h:89
@ Slater
Definition correlationfactor.h:89
@ Adhoc
Definition correlationfactor.h:89
@ GaussSlater
Definition correlationfactor.h:88
@ None
Definition correlationfactor.h:88
@ Polynomial
Definition correlationfactor.h:89
virtual double Sr_div_S(const double &r, const double &Z) const =0
const std::vector< size_t > & all_atoms() const
indices of all atoms
Definition correlationfactor.h:294
A nuclear correlation factor class.
Definition correlationfactor.h:1936
double a_
length scale parameter a, default chosen that linear terms in U2 vanish
Definition correlationfactor.h:1965
Polynomial(World &world, const Molecule &mol, const double a)
ctor
Definition correlationfactor.h:1942
coord_3d Sp(const coord_3d &vr1A, const double &Z) const
radial part first derivative of the nuclear correlation factor
Definition correlationfactor.h:1989
double Spp_div_S(const double &r, const double &Z) const
second derivative of the nuclear correlation factor
Definition correlationfactor.h:2005
double S(const double &r, const double &Z) const
the nuclear correlation factor
Definition correlationfactor.h:1973
double Srrr_div_S(const double &r, const double &Z) const
Definition correlationfactor.h:2063
double U2X_spherical(const double &r, const double &Z, const double &rcut) const
derivative of the U2 potential wrt nuclear coordinate X (spherical part)
Definition correlationfactor.h:2077
corrfactype type() const
Definition correlationfactor.h:1960
double a_param() const
Definition correlationfactor.h:1967
double Srr_div_S(const double &r, const double &Z) const
Definition correlationfactor.h:2049
static double b_param(const double &a)
the cutoff
Definition correlationfactor.h:1970
double Sr_div_S(const double &r, const double &Z) const
Definition correlationfactor.h:2033
Definition correlationfactor.h:2109
double Srrr_div_S(const double &r, const double &Z) const
Definition correlationfactor.h:2166
double eprec
Definition correlationfactor.h:2157
corrfactype type() const
Definition correlationfactor.h:2131
std::shared_ptr< PotentialManager > potentialmanager
underlying potential (=molecule)
Definition correlationfactor.h:2156
real_function_3d apply_U(const real_function_3d &rhs) const
apply the regularized potential U_nuc on a given function rhs
Definition correlationfactor.h:2148
double Srr_div_S(const double &r, const double &Z) const
Definition correlationfactor.h:2164
const double fac
the factor of the correlation factor: R=fac;
Definition correlationfactor.h:2160
double U2X_spherical(const double &r, const double &Z, const double &rcut) const
derivative of the U2 potential wrt nuclear coordinate X (spherical part)
Definition correlationfactor.h:2184
double S(const double &r, const double &Z) const
the nuclear correlation factor
Definition correlationfactor.h:2169
double Sr_div_S(const double &r, const double &Z) const
Definition correlationfactor.h:2162
coord_3d Sp(const coord_3d &vr1A, const double &Z) const
radial part first derivative of the nuclear correlation factor
Definition correlationfactor.h:2174
PseudoNuclearCorrelationFactor(World &world, const Molecule &mol, const std::shared_ptr< PotentialManager > pot, const double fac)
ctor
Definition correlationfactor.h:2116
double Spp_div_S(const double &r, const double &Z) const
second derivative of the nuclear correlation factor
Definition correlationfactor.h:2179
const real_function_3d U2() const
return the U2 term of the correlation function
Definition correlationfactor.h:2137
A nuclear correlation factor class.
Definition correlationfactor.h:1472
double eprec_param() const
Definition correlationfactor.h:1502
double Sr_div_S(const double &r, const double &Z) const override
first derivative of the correlation factor wrt (r-R_A)
Definition correlationfactor.h:1515
double U2X_spherical(const double &r, const double &Z, const double &rcut) const override
derivative of the U2 potential wrt X (scalar part)
Definition correlationfactor.h:1591
double screening_radius(const double Z) const override
every per-atom term of this factor decays as exp(-a Z r); 1e-14 relative to (a Z)^2
Definition correlationfactor.h:1505
double a_param() const
Definition correlationfactor.h:1501
double S(const double &r, const double &Z) const override
the nuclear correlation factor
Definition correlationfactor.h:1543
double Srr_div_S(const double &r, const double &Z) const override
second derivative of the correlation factor wrt (r-R_A)
Definition correlationfactor.h:1525
Slater(World &world, const Molecule &mol, const double a)
ctor
Definition correlationfactor.h:1478
corrfactype type() const override
Definition correlationfactor.h:1493
double Srrr_div_S(const double &r, const double &Z) const override
third derivative of the correlation factor wrt (r-R_A)
Definition correlationfactor.h:1536
double eprec_
Definition correlationfactor.h:1499
coord_3d Sp(const coord_3d &vr1A, const double &Z) const override
radial part first derivative of the nuclear correlation factor
Definition correlationfactor.h:1554
double Spp_div_S(const double &r, const double &Z) const override
second derivative of the nuclear correlation factor
Definition correlationfactor.h:1561
double a_
the length scale parameter
Definition correlationfactor.h:1498
constexpr T normf() const
Calculate the 2-norm of the vector elements.
Definition vector.h:421
A parallel world class.
Definition world.h:134
ProcessID rank() const
Returns the process rank in this World (same as MPI_Comm_rank()).
Definition world.h:344
Definition correlationfactor.h:1622
double Srrr_div_S(const double &r, const double &Z) const
third derivative of the correlation factor wrt (r-R_A)
Definition correlationfactor.h:1793
double a
the length scale parameter
Definition correlationfactor.h:1669
double Spp_div_S(const double &r, const double &Z) const
second derivative of the nuclear correlation factor
Definition correlationfactor.h:1813
poly4erfc(World &world, const Molecule &mol, const double aa)
ctor
Definition correlationfactor.h:1628
double a0
Definition correlationfactor.h:1670
double eprec_
Definition correlationfactor.h:1671
coord_3d Sp(const coord_3d &vr1A, const double &Z) const
radial part first derivative of the nuclear correlation factor
Definition correlationfactor.h:1807
corrfactype type() const
Definition correlationfactor.h:1664
double U2X_spherical(const double &r, const double &Z, const double &rcut) const
derivative of the U2 potential wrt X (scalar part)
Definition correlationfactor.h:1922
double a_param() const
Definition correlationfactor.h:1673
double eprec_param() const
Definition correlationfactor.h:1674
double Srr_div_S(const double &r, const double &Z) const
second derivative of the correlation factor wrt (r-R_A)
Definition correlationfactor.h:1783
double Sr_div_S(const double &r, const double &Z) const
first derivative of the correlation factor wrt (r-R_A)
Definition correlationfactor.h:1681
double S(const double &r, const double &Z) const
the nuclear correlation factor
Definition correlationfactor.h:1799
char * p(char *buf, const char *name, int k, int initial_level, double thresh, int order)
Definition derivatives.cc:72
static double lo
Definition dirac-hatom.cc:23
Tensor< typename Tensor< T >::scalar_type > arg(const Tensor< T > &t)
Return a new tensor holding the argument of each element of t (complex types only)
Definition tensor.h:2757
static const double rcut
Definition hatom_sf_dirac.cc:19
static const double eprec
Definition hatom_sf_dirac.cc:18
static double u(double r, double c)
Definition he.cc:20
static double Z2(const coord_3d &r)
Definition helium_mp2.cc:124
#define MADNESS_EXCEPTION(msg, value)
Macro for throwing a MADNESS exception.
Definition madness_exception.h:119
#define MADNESS_ASSERT(condition)
Assert a condition that should be free of side-effects since in release builds this might be a no-op.
Definition madness_exception.h:134
void print(const tensorT &t)
Definition mcpfit.cc:140
static double dsmoothed_potential(double r)
Derivative of the regularized 1/r potential.
Definition mentity.cc:223
static double smoothed_potential(double r)
Regularized 1/r potential.
Definition mentity.cc:206
static double smoothing_parameter(double Z, double eprec)
Returns radius for smoothing nuclear potential with energy precision eprec.
Definition mentity.cc:192
Main include file for MADNESS and defines Function interface.
constexpr double pi
Mathematical constant .
Definition constants.h:48
Namespace for all elements and tools of MADNESS.
Definition DFConvergence.h:9
std::shared_ptr< NuclearCorrelationFactor > create_nuclear_correlation_factor(World &world, const Molecule &molecule, const std::shared_ptr< PotentialManager > potentialmanager, const std::string inputline)
create and return a new nuclear correlation factor
Definition correlationfactor.cc:45
int power< 4 >(int base)
Definition power.h:68
Function< TENSOR_RESULT_TYPE(T, R), NDIM > dot(World &world, const std::vector< Function< T, NDIM > > &a, const std::vector< Function< R, NDIM > > &b, bool fence=true, bool do_make_redundant=true)
Multiplies and sums two vectors of functions r = \sum_i a[i] * b[i]; see dot_sparse for screening.
Definition vmra.h:1848
static double r2(const coord_3d &x)
Definition smooth.h:45
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:336
int power< 5 >(int base)
Definition power.h:73
std::shared_ptr< FunctionFunctorInterface< double, 3 > > func(new opT(g))
FunctionFactory< double, 3 > real_factory_3d
Definition functypedefs.h:108
NDIM const Function< R, NDIM > & g
Definition mra.h:2664
int power< 2 >(int base)
Definition power.h:58
void print(const T &t, Ts &&... ts)
Print items to std::cout (items separated by spaces) and terminate with a new line.
Definition print.h:232
int power< 3 >(int base)
Definition power.h:63
Vector< double, 3 > coord_3d
Definition funcplot.h:1042
Derivative< double, 3 > real_derivative_3d
Definition functypedefs.h:185
int power< 6 >(int base)
Definition power.h:78
static const double b
Definition nonlinschro.cc:119
static const double d
Definition nonlinschro.cc:121
static const double a
Definition nonlinschro.cc:118
Declaration of molecule-related classes and functions.
static const double c
Definition relops.cc:10
static double Z
Definition rk.cc:35
static const double thresh
Definition rk.cc:45
static const long k
Definition rk.cc:44
const double xi
Exponent for delta function approx.
Definition siam_example.cc:60
Definition test_ar.cc:204
Definition dirac-hatom.cc:112
static double V(const coordT &r)
Definition tdse.cc:288
AtomicInt sum
Definition test_atomicint.cc:46
void e()
Definition test_sig.cc:75
double aa
Definition testbsh.cc:68
#define N
Definition testconv.cc:37
const auto npts
Definition testgconv.cc:52
std::size_t axis
Definition testpdiff.cc:59
const double a2
Definition vnucso.cc:86
const double R2
Definition vnucso.cc:84
const double a1
Definition vnucso.cc:85