MADNESS 0.10.1
electronic_correlation_factor.h
Go to the documentation of this file.
1/*
2 * electronic_correlation_factor.h
3 *
4 * Created on: Jul 9, 2015
5 * Author: fbischoff
6 */
7
8#ifndef SRC_APPS_CHEM_ELECTRONIC_CORRELATION_FACTOR_H_
9#define SRC_APPS_CHEM_ELECTRONIC_CORRELATION_FACTOR_H_
10
11
12
13#include <madness/mra/mra.h>
14#include <madness/mra/lbdeux.h>
16#include <iomanip>
17
18namespace madness {
19/// a class holding the electronic correlation factor for R12 theory
21
22 World& world;
23 double _gamma; ///< the correlation factor exp(-gamma r12)
24 double dcut; ///< the cutoff for the 1/r potential
25 double lo; ///< smallest length scale to be resolved
26
27public:
28
29 /// ctor, use negative gamma for linear correlation factor r12
30 CorrelationFactor(World& world) : world(world), _gamma(-1.0), dcut(1.e-10),
31 lo(1.e-10) {
32 }
33
34 /// ctor, use negative gamma for linear correlation factor r12
35 CorrelationFactor(World& world, const double& gamma, const double dcut,
36 const Molecule& molecule) : world(world), _gamma(gamma), dcut(dcut) {
37 lo=1.e-6;//lo = molecule.smallest_length_scale();
38// if (world.rank()==0) {
39// if (gamma>0.0) print("constructed correlation factor with gamma=",gamma);
40// else if (gamma==0.0) print("constructed linear correlation factor");
41// }
42 }
43 /// ctor, use negative gamma for linear correlation factor r12
44 CorrelationFactor(World& world, const double& gamma, const double dcut,
45 const double lo) : world(world), _gamma(gamma), dcut(dcut), lo(lo) {
46// if (world.rank()==0) {
47// if (gamma>0.0) print("constructed correlation factor with gamma=",gamma);
48// else if (gamma==0.0) print("constructed linear correlation factor");
49// }
50 }
51
52 /// copy ctor
53 CorrelationFactor(const CorrelationFactor& other) : world(other.world) {
54 _gamma=other._gamma;
55 dcut=other.dcut;
56 lo=other.lo;
57 }
58
59 /// assignment; assume other's world is this world
60 CorrelationFactor& operator=(const CorrelationFactor& other) {
61 _gamma=other._gamma;
62 dcut=other.dcut;
63 lo=other.lo;
64 return *this;
65 }
66
67 /// return the exponent of this correlation factor
68 double gamma() const {return _gamma;}
69
70 /// return the value of the correlation factor
71 double operator()(const coord_6d& r) const {
72 const double rr=r12(r);
73 if (_gamma>0.0) return (1.0-exp(-_gamma*rr))/(2.0*_gamma);
74 return 0.5*rr;
75 }
76
77 /// apply Kutzelnigg's regularized potential to an orbital product
79 const real_convolution_6d& op_mod, const bool symmetric=false) const {
80 if(not op_mod.modified()) MADNESS_EXCEPTION("ElectronicCorrelationFactor::apply_U, op_mod must be in modified_NS form",1);
82 const bool debug = false;
84
86
87 for (int axis=0; axis<3; ++axis) {
88 //if (world.rank()==0) print("working on axis",axis);
92 if(symmetric) Dj=madness::copy(Di);
93 else Dj=(D(phi_j)).truncate();
94
97 .g12(u).particle1(copy(Di)).particle2(copy(phi_j)).thresh(thresh);
98 tmp1.fill_cuspy_tree(op_mod).truncate();
99
101 if(symmetric) tmp2 = -1.0*swap_particles(tmp1);
102 else{
104 .g12(u).particle1(copy(phi_i)).particle2(copy(Dj)).thresh(thresh);
105 tmp2.fill_cuspy_tree(op_mod).truncate();
106 }
107
108 result=result+(tmp1-tmp2).truncate();
109
110
111 tmp1.clear();
112 tmp2.clear();
113 world.gop.fence();
114 result.truncate().reduce_rank();
115 }
116
117 // include the purely local potential that (partially) cancels 1/r12
118 if (_gamma>0.0) {
122 .g12(fg3).particle1(copy(phi_i)).particle2(copy(phi_j)).thresh(thresh);;
123 mul.fill_cuspy_tree(op_mod).truncate();
124 // mul.print_size("mul");
125
126 result=(result+mul).truncate().reduce_rank();
127 }
128 if(debug) result.print_size("Ue|ij>");
129 return result;
130 }
131
132 /// return the U1 term of the correlation function
133 real_function_6d U1(const int axis) const {
134 U func(_gamma,axis,dcut);
137 return u1;
138 }
139
140 /// return the U1 term of the correlation function
141 real_function_6d U2() const {
142 if (world.rank()==0) print("U2 for the electronic correlation factor");
143 if (world.rank()==0) print("is expensive -- do you really need it??");
144 MADNESS_EXCEPTION("U2() not implemented, since it might be expensive",1);
145 return real_factory_6d(world);
146 }
147
148 /// return the correlation factor as on-demand function
149 real_function_6d f() const {
150// real_function_6d tmp=real_factory_6d(world).functor2(*this).is_on_demand();
152 real_function_6d tmp=TwoElectronFactory(world)
153 .dcut(dcut).gamma(_gamma).f12().thresh(thresh);
154 return tmp;
155 }
156
157 /// return f^2 as on-demand function
158 real_function_6d f2() const {
159 f2_ func(_gamma);
161 return tmp;
162 }
163
164 /// return fg+sth as on-demand function
165 real_function_6d fg() const {
168 return tmp;
169 }
170
171 /// return f/r as on-demand function
172 real_function_6d f_over_r() const {
175 return tmp;
176 }
177
178 /// return (\nabla f)^2 as on-demand functions
179 real_function_6d nablaf2() const {
182 return tmp;
183 }
184
185private:
186 /// functor for the local potential (1-f12)/r12 + sth (doubly connected term of the commutator)
187
188 /// TODO: turn this into coeffs directly
189 struct fg_ : FunctionFunctorInterface<double,6> {
190 double gamma;
191 double dcut;
192 fg_(double gamma, double dcut) : gamma(gamma), dcut(dcut) {
193 MADNESS_ASSERT(gamma>0.0);
194 }
195
196 using FunctionFunctorInterface<double,6>::operator();
197
198 double operator()(const coord_6d& r) const override {
199 const double rr=r12(r);
200 const double e=exp(-gamma*rr);
201 if (rr<5.e-2) {
202 double value= 1.5*gamma - 1.*std::pow(gamma,2)*rr + 0.41666666666666663*std::pow(gamma,3)*std::pow(rr,2) -
203 0.125*std::pow(gamma,4)*std::pow(rr,3) + 0.029166666666666667*std::pow(gamma,5)*std::pow(rr,4)
204 + 0.005555555555555556*std::pow(gamma,6)*std::pow(rr,5) +
205 0.0008928571428571429*std::pow(gamma,7)*std::pow(rr,6);
206 return value;
207 } else {
208 // return (1.0-e)*u(rr,dcut) + 0.5*gamma*e;
209 return (1.0-e)/rr + 0.5*gamma*e;
210 }
211 }
212 };
213
214 /// functor for the local potential (1-f12)/r12
215 struct f_over_r_ : FunctionFunctorInterface<double,6> {
216 double gamma;
217 double dcut;
218 f_over_r_(double gamma, double dcut) : gamma(gamma), dcut(dcut) {
219 MADNESS_ASSERT(gamma>0.0);
220 }
221
222 using FunctionFunctorInterface<double,6>::operator();
223
224 double operator()(const coord_6d& r) const override {
225 const double rr=r12(r);
226 const double e=exp(-gamma*rr);
227 return (1.0-e)*u(rr,dcut)/(2.0*gamma);
228 }
229 };
230
231 /// functor for the local part of the regularized potential: f12/r12*(r1-r2)(D1-D2)
232 struct U : FunctionFunctorInterface<double,6> {
233 double gamma;
234 int axis;
235 double dcut;
236 U(double gamma, int axis, double dcut) : gamma(gamma), axis(axis),
237 dcut(dcut) {
238 MADNESS_ASSERT(axis>=0 and axis<3);
239 }
240 using FunctionFunctorInterface<double,6>::operator();
241 double operator()(const coord_6d& r) const override {
242 const double rr=r12(r);
243 const coord_3d vr12{r[0]-r[3],r[1]-r[4],r[2]-r[5]};
244 const coord_3d N=unitvec(vr12);
245 if (gamma>0.0) return -0.5*exp(-gamma*rr)*N[axis];
246 MADNESS_EXCEPTION("no gamma in electronic corrfac::U1",1);
247// const double rr=r12(r);
248// const double g12=u(rr,dcut);
249// double a=0.5;
250// if (gamma>0.0) a=0.5*exp(-gamma*rr);
251// return -a*x12(r,axis) * g12;
252 }
253 };
254
255 /// functor for the local potential (1-f12)^2
256 struct f2_ : FunctionFunctorInterface<double,6> {
257 double gamma;
258 f2_(double gamma) : gamma(gamma) {MADNESS_ASSERT(gamma>0.0);}
259 using FunctionFunctorInterface<double,6>::operator();
260 double operator()(const coord_6d& r) const override {
261 const double rr=r12(r);
262 const double e=exp(-gamma*rr);
263 const double f=(1.0-e)/(2.0*gamma);
264 return f*f;
265 }
266 };
267
268 /// functor for the local potential (\nabla f)^2
269 struct nablaf2_ : FunctionFunctorInterface<double,6> {
270 double gamma;
271 nablaf2_(double gamma) : gamma(gamma) {
272 MADNESS_ASSERT(gamma>0.0);
273 MADNESS_ASSERT(gamma==1.0);
274 }
275 using FunctionFunctorInterface<double,6>::operator();
276 double operator()(const coord_6d& r) const override {
277 const double rr=r12(r);
278 const double f=exp(-2.0*gamma*rr)/(4.0*gamma*gamma);
279 return f;
280 }
281 };
282
283 /// Smoothed 1/r potential (c is the smoothing distance)
284 static double u(double r, double c) {
285 r = r/c;
286 double r2 = r*r, pot;
287 if (r > 6.5){
288 pot = 1.0/r;
289 } else if (r > 1e-2) {
290 pot = erf(r)/r + exp(-r2)*0.56418958354775630;
291 } else{
292 pot = 1.6925687506432689-r2*(0.94031597257959381-r2*(0.39493270848342941-0.12089776790309064*r2));
293 }
294 return pot/c;
295 }
296
297 static double r12(const coord_6d& r) {
298 const double x12=r[0]-r[3];
299 const double y12=r[1]-r[4];
300 const double z12=r[2]-r[5];
301 const double r12=sqrt(x12*x12 + y12*y12 + z12*z12);
302 return r12;
303 }
304 static double x12(const coord_6d& r, const int axis) {
305 return r[axis]-r[axis+3];
306 }
307
308 static coord_3d smoothed_unitvec(const coord_3d& xyz, double smoothing) {
309// if (smoothing==0.0) smoothing=molecule.get_eprec();
310 // TODO:need to test this
311 // reduce the smoothing for the unitvector
312 //if (not (this->type()==None or this->type()==Two)) smoothing=sqrt(smoothing);
313 const double r=xyz.normf();
314 const double cutoff=smoothing;
315 if (r>cutoff) {
316 return 1.0/r*xyz;
317 } else {
318 const double xi=r/cutoff;
319 const double xi2=xi*xi;
320 const double xi3=xi*xi*xi;
321// const double nu21=0.5+1./32.*(45.*xi - 50.*xi3 + 21.*xi*xi*xi*xi*xi);
322 const double nu22=0.5 + 1./64.*(105* xi - 175 *xi3 + 147* xi2*xi3 - 45* xi3*xi3*xi);
323// const double nu40=0.5 + 1./128.*(225 *xi - 350 *xi3 + 189*xi2*xi3);
324 const double kk=2.*nu22-1.0;
325 return kk/(r+1.e-15)*xyz;
326 }
327 }
328};
329
330/// a class holding the electronic correlation factor for R12 theory
331/// CorrelationFactor2 = (1-0.5*exp(-gamma*r12), gamma=0.5
332/// (CorrelationFactor + 1)*2.0 = CorrelationFactor2 (currently CorrelationFactor2 is only implemented for gamma=0.5 so use this gamma also on CorrelationFactor
333class CorrelationFactor2 {
334
335 World& world;
336 double _gamma; ///< the correlation factor exp(-gamma r12)
337 typedef std::shared_ptr< FunctionFunctorInterface<double,6> > functorT;
338
339public:
340
341 double dcut; ///< the cutoff for the 1/r potential
342 double lo; ///< smallest length scale to be resolved
343 double vtol; ///< initial projection threshold
344
345
346 /// ctor, use negative gamma for linear correlation factor r12
347 CorrelationFactor2(World& world) : world(world), _gamma(0.5), dcut(1.e-10),
348 lo(1.e-10), vtol(FunctionDefaults<3>::get_thresh()*0.1) {
350 }
351
352 /// return the exponent of this correlation factor
353 double gamma() const {return _gamma;}
354
355 real_function_6d function() const {
356 functorT R=functorT(new R_functor(_gamma,1));
357 return real_factory_6d(world).functor(R).is_on_demand();
358 }
359
360 real_function_6d square() const {
361 functorT R2=functorT(new R_functor(_gamma,2));
362 return real_factory_6d(world).functor(R2).is_on_demand();
363 }
364
365 real_function_6d inverse() const {
366 functorT R=functorT(new R_functor(_gamma,-1));
367 return real_factory_6d(world).functor(R).is_on_demand();
368 }
369
370 /// return the U1 term of the correlation function
371 real_function_6d U1(const int axis) const {
372 functorT U1f=functorT(new U1_functor(_gamma,axis));
373 return real_factory_6d(world).functor(U1f).is_on_demand();
374 }
375
376 /// return the U2 term of the correlation function
377 real_function_6d U2() const {
378 functorT U2f=functorT(new U2_functor(_gamma));
379 return real_factory_6d(world).functor(U2f).is_on_demand();
380 }
381
382 /// apply Kutzelnigg's regularized potential to an orbital product
383 real_function_6d apply_U(const real_function_6d& psi, const double eps) const {
384 const double bsh_thresh=1.e-7;
385
386 real_function_6d result=real_factory_6d(world);
387
389 op_mod.modified()=true;
390
391 for (int axis=0; axis<3; ++axis) {
392 //if (world.rank()==0) print("working on axis",axis);
397
398 const real_function_6d u1=U1(axis);
399
401 .g12(u1).ket(copy(Drhs1));
403
405 .g12(u1).ket(copy(Drhs2));
407 // if (world.rank()==0) print("done with fill_tree");
408
409 result=result+(tmp1-tmp2).truncate();
410 tmp1.clear();
411 tmp2.clear();
412 world.gop.fence();
413 result.truncate().reduce_rank();
414
415 // if (world.rank()==0) printf("done with multiplication with U at ime %.1f\n",wall_time());
416 // result.print_size("result");
417 }
418
419 real_function_6d u2=U2();
421 .g12(u2);
423 result=(result+r2).truncate();
424 return result;
425 }
426
427
428private:
429
430 /// functor for the correlation factor R
431 class R_functor : public FunctionFunctorInterface<double,6> {
432 double gamma;
433 int exponent;
434
435
436 public:
437 R_functor(double gamma, int e=1) : gamma(gamma), exponent(e) {
438 MADNESS_ASSERT(gamma==0.5);
439 }
440
441 using FunctionFunctorInterface<double,6>::operator();
442
443 // only valid for gamma=1
444 double operator()(const coord_6d& r) const override {
445 const double rr=r12(r);
446 double val=(1.0-0.5*exp(-gamma*rr));
447 if (exponent==1) return val;
448 else if (exponent==2) return val*val;
449 else if (exponent==-1) return 1.0/val;
450 else {
451 MADNESS_EXCEPTION("fancy exponent in correlationfactor2",1);
452 }
453 }
454 };
455
456 /// functor for the U2 local potential
457 class U2_functor : public FunctionFunctorInterface<double,6> {
458 double gamma;
459
460 public:
461 U2_functor(double gamma) : gamma(gamma) {
462 MADNESS_ASSERT(gamma==0.5);
463 }
464
465 using FunctionFunctorInterface<double,6>::operator();
466
467 // only valid for gamma=1
468 double operator()(const coord_6d& r) const override {
469 const double rr=r12(r);
470 // Taylor expansion for small r
471 if (rr<1.e-4) { // valid for gamma==0.5, otherwise singular
472 return (5./4.0 - rr + (35.0* rr*rr)/48.0 - (101.0*rr*rr*rr)/192.0);
473 }
474 const double egr=exp(-gamma*rr);
475 return -(-8.*egr + 8.0 + rr*egr)/(4.0 *rr*egr - 8 *rr);
476 }
477 };
478
479 /// functor for the U1 = -\frac{\vec\nabla_1 f_{12}}{f_{12}} potential
480
481 /// the potential is given by
482 /// U1 = -\frac{\vec\nabla_1 f_{12}}{f_{12}}
483 /// = \frac{e^{-r12/2}{4-2e^{-r12/2}} \vec unitvec
484 /// the derivative operators are not included
485 class U1_functor : public FunctionFunctorInterface<double,6> {
486 double gamma;
487 int axis;
488
489 public:
490 U1_functor(double gamma, int axis) : gamma(gamma), axis(axis) {
491 MADNESS_ASSERT(gamma==0.5);
493 }
494
495 using FunctionFunctorInterface<double,6>::operator();
496
497 double operator()(const coord_6d& r) const override {
498 const double rr=r12(r);
499 const coord_3d vr12{r[0]-r[3],r[1]-r[4],r[2]-r[5]};
500 const coord_3d N=unitvec(vr12);
501 // Taylor expansion for small r
502 double val;
503 if (rr<1.e-4) { // valid for gamma==0.5, otherwise singular
504 val = 0.5 - 0.5*rr + 0.125*(3.*rr*rr) - (13.* rr*rr*rr)/48.0;
505 } else {
506 const double egr=exp(-gamma*rr);
507 val=egr/(4.0-2.0*egr);
508 }
509 // NOTE the sign
510 return -val*N[axis];
511 }
512 };
513
514 /// helper function
515 static double r12(const coord_6d& r) {
516 const double x12=r[0]-r[3];
517 const double y12=r[1]-r[4];
518 const double z12=r[2]-r[5];
519 const double r12=sqrt(x12*x12 + y12*y12 + z12*z12);
520 return r12;
521 }
522
523};
524
525}
526
527
528
529#endif /* SRC_APPS_CHEM_ELECTRONIC_CORRELATION_FACTOR_H_ */
static const double & get_thresh()
Returns the default threshold.
Definition funcdefaults.h:177
FunctionFactory & functor(const std::shared_ptr< FunctionFunctorInterface< T, NDIM > > &f)
Definition function_factory.h:141
virtual FunctionFactory & is_on_demand()
Definition function_factory.h:288
Function< T, NDIM > & fill_tree(const Function< R, NDIM > &g, bool fence=true)
With this being an on-demand function, fill the MRA tree according to different criteria.
Definition mra.h:1291
Function< T, NDIM > & fill_cuspy_tree(const opT &op, const bool fence=true)
Definition mra.h:1332
double thresh() const
Returns value of truncation threshold. No communication.
Definition mra.h:677
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:712
constexpr T normf() const
Calculate the 2-norm of the vector elements.
Definition vector.h:421
static const double R
Definition csqrt.cc:46
double(* f)(const coord_3d &)
Definition derivatives.cc:54
double(* f2)(const coord_3d &)
Definition derivatives.cc:56
static double lo
Definition dirac-hatom.cc:23
static bool debug
Definition dirac-hatom.cc:16
static double function(const coord_3d &r)
Normalized gaussian.
Definition functionio.cc:100
double psi(const Vector< double, 3 > &r)
Definition hatom_energy.cc:78
static double u(double r, double c)
Definition he.cc:20
static const double dcut
Definition he.cc:13
Implements (2nd generation) static load/data balancing for functions.
#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
std::shared_ptr< FunctionFunctorInterface< double, 3 > > functorT
Definition mcpfit.cc:49
Main include file for MADNESS and defines Function interface.
Namespace for all elements and tools of MADNESS.
Definition DFParameters.h:10
Function< T, NDIM > square(const Function< T, NDIM > &f, bool fence=true)
Create a new function that is the square of f - global comm only if not reconstructed.
Definition mra.h:2885
Function< TENSOR_RESULT_TYPE(Q, T), NDIM > mul(const Q alpha, const Function< T, NDIM > &f, bool fence=true)
Returns new function equal to alpha*f(x) with optional fence.
Definition mra.h:1884
std::enable_if_t< NDIM%2==0, Function< T, NDIM > > swap_particles(const Function< T, NDIM > &f)
swap particles 1 and 2
Definition mra.h:2503
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
Vector< double, 6 > coord_6d
Definition funcplot.h:1043
double norm2(World &world, const std::vector< Function< T, NDIM > > &v)
Computes the 2-norm of a vector of functions.
Definition vmra.h:922
std::shared_ptr< FunctionFunctorInterface< double, 3 > > func(new opT(g))
Tensor< T > inverse(const Tensor< T > &a_in)
invert general square matrix A
Definition lapack.cc:832
constexpr Vector< T, N > unitvec(const Vector< T, N > &r, const double eps=1.e-6)
Construct a unit-Vector that has the same direction as r.
Definition vector.h:768
Function< double, 6 > real_function_6d
Definition functypedefs.h:83
void print(const T &t, const Ts &... ts)
Print items to std::cout (items separated by spaces) and terminate with a new line.
Definition print.h:227
NDIM & f
Definition mra.h:2620
std::shared_ptr< FunctionFunctorInterface< double, 3 > > functorT
Definition corepotential.cc:55
Function< double, 3 > real_function_3d
Definition functypedefs.h:80
SeparatedConvolution< double, 6 > real_convolution_6d
Definition functypedefs.h:139
Vector< double, 3 > coord_3d
Definition funcplot.h:1042
Derivative< double, 6 > real_derivative_6d
Definition functypedefs.h:188
static XNonlinearSolver< std::vector< Function< T, NDIM > >, T, vector_function_allocator< T, NDIM > > nonlinear_vector_solver(World &world, const long nvec)
Definition nonlinsol.h:371
FunctionFactory< double, 6 > real_factory_6d
Definition functypedefs.h:111
Derivative< double, 3 > real_derivative_3d
Definition functypedefs.h:185
Function< T, NDIM > copy(const Function< T, NDIM > &f, const std::shared_ptr< WorldDCPmapInterface< Key< NDIM > > > &pmap, bool fence=true)
Create a new copy of the function with different distribution and optional fence.
Definition mra.h:2185
static const double c
Definition relops.cc:10
static const double thresh
Definition rk.cc:45
const double xi
Exponent for delta function approx.
Definition siam_example.cc:60
Definition test_ar.cc:204
void e()
Definition test_sig.cc:75
#define N
Definition testconv.cc:37
std::size_t axis
Definition testpdiff.cc:59
static Molecule molecule
Definition testperiodicdft.cc:39
const double R2
Definition vnucso.cc:84