MADNESS  0.10.1
gaussian.h
Go to the documentation of this file.
1 /* This file is a part of Slymer, which is distributed under the Creative
2  Commons Attribution-NonCommercial 4.0 International Public License.
3 
4  (c) 2017 Stony Brook University. */
5 
6 /**
7  * \file Basis/gaussian.h
8  * \brief Gaussian basis function API and routines.
9  *
10  * Handles Gaussian basis functions as special cases (class inheritance). Both
11  * primitive and contracted Gaussians from electronic structure codes are
12  * implemented, but not using those labels.
13  */
14 
15 #ifndef __Basis_gaussian_h__
16 #define __Basis_gaussian_h__
17 
18 #include <forward_list>
19 #include <utility>
20 #include<madness/chem/basis.h>
23 #include <madness/mra/mra.h>
24 #include <madness/constants.h>
25 
26 namespace slymer {
27 
28 /// Implemented types of Gaussian orbitals (from quantum chemistry codes).
29 enum class GaussianType {
30  // both Cartesian and spherical
31  s, px, py, pz,
32 
33  // Cartesian (and possibly spherical)
34  dxx, dxy, dxz, dyy, dyz, dzz,
36 
37  // spherical only ('m' denotes "minus")
38  dzzmrr, dxxmyy,
40 
41  // g
42  // cartesian
45  // spherical
46  // ('d' denotes "dot" for multiplication)
47  // (numbers in names indicate powers of preceding variable)
50 
51  // h
52  // cartesian
56  // spherical
57  // at this point, just giving names corresponding to value
58  // quantum number m
59  hm5, hm4, hm3, hm2, hm1, hzero, hp1, hp2, hp3, hp4, hp5
60 
61 };
62 
63 // forward declaration
64 class GaussianFunction;
65 
66 /**
67  * \brief A primitive Gaussian function.
68  *
69  * This basis function has the form \f[
70  * f(x,y,z) = p(x,y,z) \exp[(x-x_0)^T \Sigma (x-x_0)],
71  * \f]
72  * where \f$p\f$ is a polynomial and \f$x_0\f$ is the ``center'' of the
73  * Gaussian and \f$\Sigma\f$ is the variance/covariance matrix.
74  *
75  * This class is designed to work with Gaussian basis functions in quantum
76  * chemistry codes, but is made to be a bit more general for other
77  * applications.
78  *
79  * The wikipedia page on multivariable normal distributions may be helpful
80  * (https://en.wikipedia.org/wiki/Multivariate_normal_distribution).
81  */
83 
84 protected:
85  /// Polynomial prefactor (\f$p\f$ in the class description).
87 
88  /// Coefficients in the exponent's quadratic function.
90 
91  /**
92  * \brief Return type for the function's canonical form.
93  *
94  * The first element is the polynomial prefactor, converted to use the principal coordinates.
95  * The second element is the array of decay values (eigenvalues of the covariance matrix).
96  * The third element is the \f$\nu\f$ vector (essentially the center of the Gaussian).
97  * The fourth element are the canonical axes in the original coordinates (for debugging purposes).
98  */
99  using CF = std::tuple<PolynomialCoeffs, std::array<double, 3>, std::array<double, 3>, std::array<std::array<double, 3>, 3>>;
100 
101 public:
102  /// Default constructor: Make the function 1 (\f$p=1\f$, \f$f(\vec{x})=0\f$).
104  : prefactor(0), exppoly(2)
105  {
106  prefactor[{{0,0,0}}] = 1.;
107  }
108 
109  /**
110  * \brief Create a primitive Gaussian function centered on the specific point,
111  * with the specified decay constant and type.
112  *
113  * \throw std::invalid_argument if the decay constant is non-positive.
114  *
115  * \param[in] type The orbital type of the Gaussian.
116  * \param[in] center The center of the Gaussian.
117  * \param[in] ec The decay constant in the exponential.
118  */
120  const std::array<double, 3> &center, const double ec);
121 
122  /**
123  * \brief Create a primitive Gaussian function with the specified exponential
124  * polynomial (quadratic) and polynomial prefactor.
125  *
126  * \throw std::invalid_argument if the exponential polynomial is not
127  * quadratic (or constant or linear as subsets).
128  *
129  * \param[in] exppoly_ The exponential polynomial.
130  * \param[in] prefactor_ The degree of the prefactor.
131  */
132  PrimitiveGaussian(const PolynomialCoeffs &exppoly_,
133  const PolynomialCoeffs &prefactor_);
134 
135  /**
136  * \brief Evaluate the Gaussian primitive at the specified point.
137  *
138  * \param[in] x The point.
139  * \return The Gaussian primitive evaluated at the point x.
140  */
141  double operator() (const std::array<double, 3> &x) const;
142 
143  /**
144  * \brief Multiply two primitive Gaussians. The result is another.
145  *
146  * \param[in] rhs The right-hand object.
147  * \result The product.
148  */
150 };
151 
152 
153 /**
154  * \brief A Gaussian basis function used by chemistry electronic structure
155  * codes.
156  *
157  * This basis function has the form \f[
158  * \sum_j c_j x^{l_j} y^{m_j} z^{n_j} \exp[f_j(\vec{x})],
159  * \f]
160  * where \f$f_j(\vec{x})\f$ is a quadratic function. Note that this functional
161  * form is a bit more general than that used by standard electronic structure
162  * codes; we do not require the prinicpal axes of the Gaussian function to be
163  * coincident with the x-, y-, and z-axes. This class can also hold/handle any
164  * linear combination of primitive Gaussian functions (the exponents and
165  * centers do not have to be the same).
166  */
168 
169 protected:
170  /// Helper class for storing terms in the sum of Gaussian primitives.
171  using TermT = std::pair<double, PrimitiveGaussian>;
172 
173  /// The list of terms in the sum of Gaussian primitives.
174  std::forward_list<TermT> terms;
175 
176  /**
177  * \brief Removes terms with very small linear expansion coefficients.
178  *
179  * \param[in] eps The threshold for "small". Defaults to 1.e-6.
180  */
181  void removeSmallTerms(const double eps = 1.e-6) {
182  terms.remove_if(
183  [eps](const TermT &t) {
184  return std::abs(t.first) < eps;
185  }
186  );
187  }
188 
189 public:
190 
191  /// The center of the gaussian
192  std::array<double, 3> center;
193 
194  /// The exponent coefficients
195  std::vector<double> expcoeff;
196 
197  /// Default constructor: Make the function 0.
198  GaussianFunction() : terms(0), center({{0,0,0}}), expcoeff(std::vector<double>{0.0}) {}
199 
200  /**
201  * \brief Create a Gaussian orbital (uncontracted or contracted) from
202  * quantum chemistry codes.
203  *
204  * Both Cartesian and spherical orbitals are supported. The expcoeff and
205  * coeff parameters must be arrays. If the orbital is uncontracted, the
206  * arrays will be length 1.
207  *
208  * All uncontracted primitive Gaussian orbitals used underneath the
209  * GaussianFunction are normalized.
210  *
211  * \throw invalid_argument If a non-positive exponential coefficient is
212  * passed or if the lengths of expcoeff and coeff are not equal.
213  *
214  * \param[in] type The orbital type (from enum OrbitalType).
215  * \param[in] center The center of the Gaussian orbital.
216  * \param[in] expcoeff Array of coefficients in the exponents of the
217  * primitive Gaussians.
218  * \param[in] coeff Array of linear expansion coefficients of the primitive
219  * Gaussians.
220  */
221  GaussianFunction(const GaussianType type, const std::array<double, 3> &center,
222  const std::vector<double> &expcoeff, const std::vector<double> &coeff);
223 
224  /**
225  * \brief Create an uncontracted Gaussian orbital (shortcut to the more
226  * general constructor for Gaussian orbitals).
227  *
228  * \param[in] type The orbital type (from enum OrbitalType).
229  * \param[in] center The center of the Gaussian orbital.
230  * \param[in] expcoeff The coefficient in the exponent of the primitive
231  * Gaussian.
232  */
233  GaussianFunction(const GaussianType type, const std::array<double, 3> &center,
234  const double expcoeff)
235  : GaussianFunction(type, center, {expcoeff}, {1.}) {}
236 
237  /**
238  * \brief Evaluate the Gaussian function at the specified point.
239  *
240  * \param[in] x The point.
241  * \return The Gaussian function evaluated at the point x.
242  */
243  virtual double operator() (const std::array<double, 3> &x) const override;
244 
245  /**
246  * \brief Evaluate the Gaussian function at the specified point.
247  *
248  * \param[in] x The point.
249  * \return The Gaussian function evaluated at the point x.
250  */
251  double operator() (const madness::coord_3d& r) const {
252  return operator()(std::array<double, 3>{{r[0], r[1], r[2]}});
253  };
254 
255  /**
256  * \brief Additive inverse of the GaussianFunction (deep copy).
257  *
258  * \return The negated function.
259  */
261 
262  /**
263  * \brief Add two GaussianFunction objects, resulting in a new one.
264  *
265  * \param[in] rhs The right-hand GaussianFunction.
266  * \return The sum of this GaussianFunction and rhs.
267  */
268  GaussianFunction operator+(const GaussianFunction &rhs) const;
269 
270  /**
271  * \brief Add a GaussianFunction to this GaussianFunction.
272  *
273  * \param[in] rhs The right-hand GaussianFunction.
274  * \return The sum of this GaussianFunction and rhs, stored in *this.
275  */
277 
278  /**
279  * \brief Subtract a GaussianFunction from this one, returning the difference.
280  *
281  * \param[in] rhs The GaussianFunction to be subtracted.
282  * \return The difference of the two GaussianFunction objects.
283  */
285  return *this + (-rhs);
286  }
287 
288  /**
289  * \brief Subtract a GaussianFunction from this one.
290  *
291  * \param[in] rhs The GaussianFunction to be subtracted.
292  * \return This GaussianFunction (the difference).
293  */
295  return operator+=(-rhs);
296  }
297 
298  /**
299  * \brief Multiply the GaussianFunction by a scalar.
300  *
301  * \param[in] rhs The scalar multiplicative factor.
302  * \return This GaussianFunction, which has been scaled.
303  */
304  GaussianFunction &operator*=(const double rhs);
305 
306  /**
307  * \brief Multiply the GaussianFunction by another.
308  *
309  * \param[in] rhs The right-hand GaussianFunction object.
310  * \return This GaussianFunction, which is now the product.
311  */
313  GaussianFunction ret = (*this) * rhs;
314  terms.swap(ret.terms);
315  return *this;
316  }
317 
318  /**
319  * \brief Multiply the GaussianFunction by a scalar.
320  *
321  * \param[in] rhs The scalar multiplicative factor.
322  * \return The scaled GaussianFunction.
323  */
324  GaussianFunction operator*(const double rhs) const {
325  GaussianFunction ret(*this);
326  ret *= rhs;
327  return ret;
328  }
329 
330  /**
331  * \brief Multiply two GaussianFunctions.
332  *
333  * \param[in] rhs The right-hand GaussianFunction object.
334  * \return The product.
335  */
336  GaussianFunction operator*(const GaussianFunction &rhs) const;
337 
338  /**
339  * \brief Divide the GaussianFunction by a scalar.
340  *
341  * Does not check that the scalar is nonzero.
342  *
343  * \param[in] rhs The scalar factor.
344  * \return This GaussianFunction, which has been scaled.
345  */
346  GaussianFunction &operator/=(const double rhs) {
347  operator*=(1./rhs);
348  return *this;
349  }
350 
351  /**
352  * \brief Divide the GaussianFunction by a scalar.
353  *
354  * \param[in] rhs The scalar factor.
355  * \return The scaled GaussianFunction.
356  */
357  GaussianFunction operator/(const double rhs) const {
358  return (*this) * (1./rhs);
359  }
360 };
361 
362 
363 // helper functions
364 
365 /**
366  * \brief Multiply a GaussianFunction by a scalar.
367  *
368  * \param[in] lhs The scalar multiplicative factor.
369  * \param[in] rhs The GaussianFunction.
370  * \return The scaled GaussianFunction.
371  */
372 inline GaussianFunction operator*(const double lhs, const GaussianFunction &rhs) {
373  return rhs * lhs;
374 }
375 
377 private:
379  std::vector<madness::coord_3d> centers;
380 public:
381  Gaussian_Functor(GaussianFunction func, std::vector<madness::coord_3d> centers) : func(func), centers(centers) {}
382 
383  double operator()(const madness::coord_3d& r) const {
384  return func(r);
385  }
386 
387  std::vector<madness::coord_3d> special_points() const {
388  return centers;
389  }
390 
392  // From Robert:
393  // Pick initial level such that average gap between quadrature points
394  // will find a significant value
395  const int N = 6; // looking for where exp(-a*x^2) < 10**-N
396  const int K = 6; // typically the lowest order of the polyn
397  const double log10 = std::log(10.0);
398  const double log2 = std::log(2.0);
400  const double expnt = *(std::max_element(func.expcoeff.begin(), func.expcoeff.end()));
401  const double a = expnt*L*L;
402  //const double fac = pow(2.0/(expnt*madness::constants::pi), 3.0/2.0);
403  const double fac = 100.0;
404  double n = std::log(a/(4*K*K*(N*log10+std::log(fac))))/(2*log2);
405  return (n < 2 ? 2.0 : std::ceil(n)+1); // Added in the +1 for paranoia's sake
406  }
407 };
408 
409 } // namespace slymer
410 #endif
static double get_cell_min_width()
Returns the minimum width of any user cell dimension.
Definition: funcdefaults.h:478
Abstract base class interface required for functors used as input to Functions.
Definition: function_interface.h:68
Abstract base class for generic basis functions.
Definition: basis.h:25
A Gaussian basis function used by chemistry electronic structure codes.
Definition: gaussian.h:167
GaussianFunction operator-(const GaussianFunction &rhs) const
Subtract a GaussianFunction from this one, returning the difference.
Definition: gaussian.h:284
GaussianFunction operator*(const double rhs) const
Multiply the GaussianFunction by a scalar.
Definition: gaussian.h:324
virtual double operator()(const std::array< double, 3 > &x) const override
Evaluate the Gaussian function at the specified point.
Definition: madness/chem/gaussian.cc:1406
std::forward_list< TermT > terms
The list of terms in the sum of Gaussian primitives.
Definition: gaussian.h:174
GaussianFunction operator+(const GaussianFunction &rhs) const
Add two GaussianFunction objects, resulting in a new one.
Definition: madness/chem/gaussian.cc:1422
GaussianFunction & operator+=(const GaussianFunction &rhs)
Add a GaussianFunction to this GaussianFunction.
Definition: madness/chem/gaussian.cc:1430
GaussianFunction & operator*=(const double rhs)
Multiply the GaussianFunction by a scalar.
Definition: madness/chem/gaussian.cc:1440
GaussianFunction(const GaussianType type, const std::array< double, 3 > &center, const double expcoeff)
Create an uncontracted Gaussian orbital (shortcut to the more general constructor for Gaussian orbita...
Definition: gaussian.h:233
GaussianFunction & operator-=(const GaussianFunction &rhs)
Subtract a GaussianFunction from this one.
Definition: gaussian.h:294
GaussianFunction & operator*=(const GaussianFunction &rhs)
Multiply the GaussianFunction by another.
Definition: gaussian.h:312
void removeSmallTerms(const double eps=1.e-6)
Removes terms with very small linear expansion coefficients.
Definition: gaussian.h:181
std::array< double, 3 > center
The center of the gaussian.
Definition: gaussian.h:192
std::pair< double, PrimitiveGaussian > TermT
Helper class for storing terms in the sum of Gaussian primitives.
Definition: gaussian.h:171
GaussianFunction operator-() const
Additive inverse of the GaussianFunction (deep copy).
Definition: madness/chem/gaussian.cc:1413
GaussianFunction()
Default constructor: Make the function 0.
Definition: gaussian.h:198
std::vector< double > expcoeff
The exponent coefficients.
Definition: gaussian.h:195
GaussianFunction operator/(const double rhs) const
Divide the GaussianFunction by a scalar.
Definition: gaussian.h:357
GaussianFunction & operator/=(const double rhs)
Divide the GaussianFunction by a scalar.
Definition: gaussian.h:346
Definition: gaussian.h:376
double operator()(const madness::coord_3d &r) const
Definition: gaussian.h:383
GaussianFunction func
Definition: gaussian.h:378
std::vector< madness::coord_3d > special_points() const
Override this to return list of special points to be refined more deeply.
Definition: gaussian.h:387
Gaussian_Functor(GaussianFunction func, std::vector< madness::coord_3d > centers)
Definition: gaussian.h:381
madness::Level special_level()
Override this change level refinement for special points (default is 6)
Definition: gaussian.h:391
std::vector< madness::coord_3d > centers
Definition: gaussian.h:379
Array for storing coefficients of a polynomial of three variables with specified degree.
Definition: polynomial.h:35
A primitive Gaussian function.
Definition: gaussian.h:82
PrimitiveGaussian()
Default constructor: Make the function 1 ( , ).
Definition: gaussian.h:103
PolynomialCoeffs exppoly
Coefficients in the exponent's quadratic function.
Definition: gaussian.h:89
std::tuple< PolynomialCoeffs, std::array< double, 3 >, std::array< double, 3 >, std::array< std::array< double, 3 >, 3 > > CF
Return type for the function's canonical form.
Definition: gaussian.h:99
PrimitiveGaussian operator*(const PrimitiveGaussian &rhs) const
Multiply two primitive Gaussians. The result is another.
Definition: madness/chem/gaussian.cc:1368
double operator()(const std::array< double, 3 > &x) const
Evaluate the Gaussian primitive at the specified point.
Definition: madness/chem/gaussian.cc:1364
PolynomialCoeffs prefactor
Polynomial prefactor ( in the class description).
Definition: gaussian.h:86
Defines common mathematical and physical constants.
vecfuncT K(vecfuncT &ket, vecfuncT &bra, vecfuncT &vf)
Main include file for MADNESS and defines Function interface.
int Level
Definition: key.h:55
std::string type(const PairType &n)
Definition: PNOParameters.h:18
Definition: basis.h:22
GaussianType
Implemented types of Gaussian orbitals (from quantum chemistry codes).
Definition: gaussian.h:29
GaussianFunction operator*(const double lhs, const GaussianFunction &rhs)
Multiply a GaussianFunction by a scalar.
Definition: gaussian.h:372
static long abs(long a)
Definition: tensor.h:218
static const double a
Definition: nonlinschro.cc:118
static const double L
Definition: rk.cc:46
#define N
Definition: testconv.cc:37