LIBINT  2.6.0
oper.h
1 /*
2  * Copyright (C) 2004-2019 Edward F. Valeev
3  *
4  * This file is part of Libint.
5  *
6  * Libint 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 3 of the License, or
9  * (at your option) any later version.
10  *
11  * Libint 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 Libint. If not, see <http://www.gnu.org/licenses/>.
18  *
19  */
20 
21 #ifndef _libint2_src_bin_libint_oper_h_
22 #define _libint2_src_bin_libint_oper_h_
23 
24 #include <string>
25 
26 #include <boost/preprocessor/list/for_each.hpp>
27 
28 #include <hashable.h>
29 #include <global_macros.h>
30 #include <util.h>
31 #include <iter.h>
32 #include <vectorn.h>
33 #include <contractable.h>
34 #include <multipole.h>
35 
36 namespace libint2 {
37 
40  typedef struct {
41  typedef enum {anti=-1, symm=1, nonsymm=0, nonstd=-2} type;
43 
50  template <unsigned int NP, bool multi, PermutationalSymmetry::type psymmetry,
51  bool origin_dependent = false>
53  public:
54  static constexpr auto np = NP;
55  static constexpr auto multiplicative = multi;
56  static constexpr auto psymm = psymmetry;
57  static constexpr auto odep = origin_dependent;
58  };
59 
65  public:
66  typedef DummyIterator iter_type;
67  virtual ~OperSet() {};
68 
70  virtual std::string description() const =0;
72  virtual std::string label() const =0;
75  virtual int psymm(int i, int j) const =0;
78  virtual int hermitian(int p) const =0;
79 
81  virtual bool origin_dependent() const =0;
82 
84  virtual unsigned int num_oper() const =0;
85  };
86 
89  template <class Props>
90  class Oper : public OperSet {
91  public:
92  typedef Props Properties;
93  virtual ~Oper() {}
94 
96  int psymm(int i, int j) const;
98  int hermitian(int p) const;
100  bool origin_dependent() const { return Props::odep; }
101 
102  bool operator==(const Oper&) const;
103 
104  protected:
106  Oper() {}
107 
108  private:
110  virtual int nonstd_psymm(int i, int j) const { throw ProgrammingError("nonstd_psymm is not overloaded"); }
112  virtual int nonstd_hermitian(int p) const { throw ProgrammingError("nonstd_hermitian is not overloaded"); }
113  };
114 
115  template <class Props>
116  int
117  Oper<Props>::psymm(int i, int j) const
118  {
119  if (i<0 || i>=static_cast<int>(Props::np))
120  throw std::runtime_error("Oper<Props>::psymm(i,j) -- index i out of bounds");
121  if (j<0 || j>=static_cast<int>(Props::np))
122  throw std::runtime_error("Oper<Props>::psymm(i,j) -- index j out of bounds");
123  if (i == j)
124  return 1;
125 
126  switch(Props::psymm) {
127  case PermutationalSymmetry::anti:
128  return -1;
129  case PermutationalSymmetry::symm:
130  return 1;
131  case PermutationalSymmetry::nonsymm:
132  return 0;
133  case PermutationalSymmetry::nonstd:
134  return nonstd_psymm(i,j);
135  default:
136  abort();
137  }
138  }
139 
140  template <class Props>
141  int
143  {
144  if (Props::multiplicative)
145  return +1;
146  else
147  return nonstd_hermitian(p);
148  }
149 
150  template <class Props>
151  bool
152  Oper<Props>::operator==(const Oper& a) const
153  {
154  return true;
155  }
156 
158 
161  template <class Descr>
162  class GenOper : public Oper<typename Descr::Properties>, public Hashable<unsigned,ComputeKey> {
163  public:
164  typedef Descr Descriptor;
165  typedef typename Descr::Properties Properties;
169 
170  unsigned int num_oper() const { return 1; };
172  unsigned int key() const { return descr_.key(); }
174  static const unsigned int max_key = Descr::max_key;
176  std::string description() const { return descr_.description(); }
178  std::string label() const { return descr_.label(); }
180  Descr& descr() { return descr_; }
182  const Descr& descr() const { return descr_; }
183 
184  GenOper(Descr descr = Descr()) : descr_(descr) {}
185  GenOper(const SafePtr<GenOper>& o) : descr_(o->descr_) {}
186  GenOper(const SafePtr<OperSet>& o) : descr_(require_dynamic_cast<GenOper,OperSet>(o)->descr_) {}
187  GenOper(const SafePtr<ConstructablePolymorphically>& o) : descr_(require_dynamic_cast<GenOper,ConstructablePolymorphically>(o)->descr_) {}
188  explicit GenOper(const ConstructablePolymorphically& o) : descr_(require_dynamic_cast<GenOper,ConstructablePolymorphically>(&o)->descr_) {}
189  virtual ~GenOper() {}
190 
191  private:
192  Descr descr_;
193 
195  int nonstd_psymm(int i, int j) const {
196  // TODO: figure out how to call this only if Desc::Properties::psymm == PermutationalSymmetry::nonstd
197  if (Descr::Properties::psymm == PermutationalSymmetry::nonstd)
198  return descr_.psymm(i,j);
199  else throw ProgrammingError("GenOper::nonstd_psymm -- descriptor is not nonstd");
200  }
201 
203  int nonstd_hermitian(int i) const {
204  // TODO: figure out how to call this only if Desc::Properties::psymm == PermutationalSymmetry::nonstd
205  if (!Descr::Properties::multiplicative)
206  return descr_.hermitian(i);
207  else throw ProgrammingError("GenOper::nonstd_hermitian -- this operator is multiplicative");
208  }
209 
210  };
211 
213 
214  typedef OperatorProperties<1,false,PermutationalSymmetry::nonsymm> Nonmultiplicative1Body_Props;
215  typedef OperatorProperties<1,true, PermutationalSymmetry::nonsymm> Multiplicative1Body_Props;
216  typedef OperatorProperties<1,true, PermutationalSymmetry::nonsymm, true> MultiplicativeODep1Body_Props;
217  typedef OperatorProperties<2,true, PermutationalSymmetry::symm> MultiplicativeSymm2Body_Props;
218  typedef OperatorProperties<2,true, PermutationalSymmetry::nonsymm> MultiplicativeNonsymm2Body_Props;
219  typedef OperatorProperties<2,false,PermutationalSymmetry::symm> NonmultiplicativeSymm2Body_Props;
220  typedef OperatorProperties<2,false,PermutationalSymmetry::nonsymm> NonmultiplicativeNonsymm2Body_Props;
221 
224  template <unsigned int N>
225  struct GenMultSymmOper_Descr : public Contractable<GenMultSymmOper_Descr<N> > {
227  static const unsigned int max_key = 1;
228  unsigned int key() const { return 0; }
229  std::string description() const { return "generic multiplicative symmetric operator"; }
230  std::string label() const { return "GenMultSymmOper"; }
231  int psymm(int i, int j) const { assert(false); }
232  int hermitian(int i) const { assert(false); }
233  };
235 
236 #define BOOST_PP_DECLARE_HERMITIAN_ONEBODY_DESCRIPTOR(r,propprefix,opname) \
237  struct opname ## _Descr : public Contractable<opname ## _Descr> { \
238  typedef propprefix ## 1Body_Props Properties; \
239  static const unsigned int max_key = 1; \
240  unsigned int key() const { return 0; } \
241  std::string description() const { return #opname; } \
242  std::string label() const { return #opname; } \
243  int psymm(int i, int j) const { assert(false); } \
244  int hermitian(int i) const { return +1; } \
245  }; \
246  typedef GenOper<opname ## _Descr> opname ## Oper; \
247 
248 #define BOOST_PP_HERMITIAN_ONEBODY_OPER_LIST (Kinetic, BOOST_PP_NIL)
249 BOOST_PP_LIST_FOR_EACH ( BOOST_PP_DECLARE_HERMITIAN_ONEBODY_DESCRIPTOR, Nonmultiplicative, BOOST_PP_HERMITIAN_ONEBODY_OPER_LIST)
250 #undef BOOST_PP_HERMITIAN_ONEBODY_OPER_LIST
251 #define BOOST_PP_HERMITIAN_ONEBODY_OPER_LIST (Overlap, BOOST_PP_NIL)
252 BOOST_PP_LIST_FOR_EACH ( BOOST_PP_DECLARE_HERMITIAN_ONEBODY_DESCRIPTOR, Multiplicative, BOOST_PP_HERMITIAN_ONEBODY_OPER_LIST)
253 #undef BOOST_PP_HERMITIAN_ONEBODY_OPER_LIST
254 #define BOOST_PP_HERMITIAN_ONEBODY_OPER_LIST (ElecPot, BOOST_PP_NIL)
255 BOOST_PP_LIST_FOR_EACH ( BOOST_PP_DECLARE_HERMITIAN_ONEBODY_DESCRIPTOR, MultiplicativeODep, BOOST_PP_HERMITIAN_ONEBODY_OPER_LIST)
256 #undef BOOST_PP_HERMITIAN_ONEBODY_OPER_LIST
257 
261 template <unsigned int NDIM>
262 struct CartesianMultipole_Descr : public Contractable<CartesianMultipole_Descr<NDIM>>,
263  public CartesianMultipoleQuanta<NDIM> {
264  typedef MultiplicativeODep1Body_Props Properties;
266 
267  CartesianMultipole_Descr() { }
268  CartesianMultipole_Descr(unsigned int k) { assert(NDIM==1u); this->inc(0,k); }
269  std::string description() const {
270  std::string descr("CartesianMultipole[");
271  std::ostringstream oss;
272  for(unsigned i=0; i!=NDIM; ++i) {
273  oss << (*this)[i];
274  if (i+1 != NDIM) oss << ",";
275  }
276  return descr + oss.str() + "]";
277  }
278  std::string label() const { return description(); }
279  int psymm(int i, int j) const { assert(false); }
280  int hermitian(int i) const { return +1; }
281 };
283 
288 struct SphericalMultipole_Descr : public Contractable<SphericalMultipole_Descr>, public SphericalMultipoleQuanta {
290  using SphericalMultipoleQuanta::max_key;
291  using SphericalMultipoleQuanta::Sign;
292 
297  SphericalMultipole_Descr(int l, int m, Sign sign) : SphericalMultipoleQuanta(l,m,sign) {}
299 
300  std::string description() const {
301  std::string descr = std::string("SphericalMultipole[") + std::to_string(this->l()) + "," + std::to_string((this->sign() == Sign::plus ? 1 : -1) * this->m()) + "]";
302  return descr;
303  }
304  std::string label() const { return description(); }
305  int psymm(int i, int j) const { assert(false); }
306  int hermitian(int i) const { return +1; }
307 };
308 using SphericalMultipoleOper = GenOper<SphericalMultipole_Descr>;
309 
312  struct TwoPRep_Descr : public Contractable<TwoPRep_Descr> {
314  static const unsigned int max_key = 1;
315  unsigned int key() const { return 0; }
316  std::string description() const { return "1/r_{12}"; }
317  std::string label() const { return "TwoPRep"; }
318  int psymm(int i, int j) const { assert(false); }
319  int hermitian(int i) const { return +1; }
320  };
322 
325  struct GTG_1d_Descr : public Contractable<GTG_1d_Descr> {
327  static const unsigned int max_key = 1;
328  unsigned int key() const { return 0; }
329  std::string description() const { return "GTG_1d"; }
330  std::string label() const { return "GTG_1d"; }
331  int psymm(int i, int j) const { assert(false); }
332  int hermitian(int i) const { return +1; }
333  };
335 
339  class R12_k_G12_Descr : public Contractable<R12_k_G12_Descr> {
340  public:
343  R12_k_G12_Descr(int K) : K_(K) { assert(K >= -1 && K <= 4); }
344  R12_k_G12_Descr(const R12_k_G12_Descr& a) : Contractable<R12_k_G12_Descr>(a), K_(a.K_) {}
345  static const unsigned int max_key = 5;
346  unsigned int key() const { return K_ + 1; }
347  std::string description() const { return label_(K_, this->contracted()); }
348  std::string label() const { return symbol_(K_, this->contracted()); }
349  int K() const { return K_; }
350  int psymm(int i, int j) const { assert(false); }
351  int hermitian(int i) const { assert(false); }
352  private:
353  R12_k_G12_Descr();
354  static std::string label_(int K, bool contracted);
355  static std::string symbol_(int K, bool contracted);
356  int K_;
357  };
358  typedef GenOper<R12_k_G12_Descr> R12kG12;
359 
363  class R12k_R12l_G12_Descr : public Contractable<R12k_R12l_G12_Descr> {
364  public:
366  static const int kmax = 4;
367  R12k_R12l_G12_Descr(const IntVec3& K, const IntVec3& L) : K_(K), L_(L) { }
369  const IntVec3& K() const { return K_; }
370  const IntVec3& L() const { return L_; }
371  static const unsigned int max_key = kmax * kmax * kmax * kmax * kmax * kmax;
372  unsigned int key() const;
373  std::string description() const { return label_(K_,L_, this->contracted()); }
374  std::string label() const { return symbol_(K_,L_, this->contracted()); }
375  int psymm(int i, int j) const { assert(false); }
376  int hermitian(int i) const { assert(false); }
377  private:
379  static std::string label_(const IntVec3& K, const IntVec3& L, bool contracted);
380  static std::string symbol_(const IntVec3& K, const IntVec3& L, bool contracted);
381  IntVec3 K_;
382  IntVec3 L_;
383  };
385 
389  class Ti_G12_Descr : public Contractable<Ti_G12_Descr> {
390  public:
393  static const unsigned int max_key = 2;
394  Ti_G12_Descr(int K) : K_(K) { assert(K >= 0 && K <= 1); }
395  Ti_G12_Descr(const Ti_G12_Descr& a) : Contractable<Ti_G12_Descr>(a), K_(a.K_) {}
396  unsigned int key() const { return K_; }
397  std::string description() const { return label_(K_, this->contracted()); }
398  std::string label() const { return symbol_(K_, this->contracted()); }
399  int K() const { return K_; }
400  int psymm(int i, int j) const { assert(false); }
401  int hermitian(int i) const { if (i != K_) return +1; else return -1; }
402  private:
403  Ti_G12_Descr();
404  static std::string label_(int K, bool contracted);
405  static std::string symbol_(int K, bool contracted);
406  int K_;
407  };
408  typedef GenOper<Ti_G12_Descr> TiG12;
409 
414  class G12_Ti_G12_Descr : public Contractable<G12_Ti_G12_Descr> {
415  public:
416  typedef MultiplicativeSymm2Body_Props Properties;
418  static const unsigned int max_key = 2;
419  G12_Ti_G12_Descr(int K) : K_(K) { assert(K >= 0 && K <= 1); }
420  G12_Ti_G12_Descr(const G12_Ti_G12_Descr& a) : Contractable<G12_Ti_G12_Descr>(a), K_(a.K_) {}
421  unsigned int key() const { return K_; }
422  std::string description() const { return label_(K_, this->contracted()); }
423  std::string label() const { return symbol_(K_, this->contracted()); }
424  int K() const { return K_; }
425  int psymm(int i, int j) const { assert(false); }
426  int hermitian(int i) const { return +1; }
427  private:
428  G12_Ti_G12_Descr();
429  static std::string label_(int K, bool contracted);
430  static std::string symbol_(int K, bool contracted);
431  int K_;
432  };
433  typedef GenOper<G12_Ti_G12_Descr> G12TiG12;
434 
437  struct R1dotR1_G12_Descr : public Contractable<R1dotR1_G12_Descr> {
438  typedef MultiplicativeNonsymm2Body_Props Properties;
439  static const unsigned int max_key = 1;
440  unsigned int key() const { return 0; }
441  std::string description() const { return "r_1.r_1 x G12"; }
442  std::string label() const { return "R1dotR1_G12"; }
443  int psymm(int i, int j) const { assert(false); }
444  int hermitian(int i) const { assert(false); }
445  };
446  typedef GenOper< R1dotR1_G12_Descr > R1dotR1_G12;
447 
450  struct R2dotR2_G12_Descr : public Contractable<R2dotR2_G12_Descr> {
451  typedef MultiplicativeNonsymm2Body_Props Properties;
452  static const unsigned int max_key = 1;
453  unsigned int key() const { return 0; }
454  std::string description() const { return "r_2.r_2 x G12"; }
455  std::string label() const { return "R2dotR2_G12"; }
456  int psymm(int i, int j) const { assert(false); }
457  int hermitian(int i) const { assert(false); }
458  };
459  typedef GenOper< R2dotR2_G12_Descr > R2dotR2_G12;
460 
463  struct R1dotR2_G12_Descr : public Contractable<R1dotR2_G12_Descr> {
464  typedef MultiplicativeSymm2Body_Props Properties;
465  static const unsigned int max_key = 1;
466  unsigned int key() const { return 0; }
467  std::string description() const { return "r_1.r_2 x G12"; }
468  std::string label() const { return "R1dotR2_G12"; }
469  int psymm(int i, int j) const { assert(false); }
470  int hermitian(int i) const { assert(false); }
471  };
472  typedef GenOper< R1dotR2_G12_Descr > R1dotR2_G12;
473 
477  struct DivG12prime_xTx_Descr : public Contractable<DivG12prime_xTx_Descr> {
478  typedef NonmultiplicativeNonsymm2Body_Props Properties;
479  static const unsigned int max_key = 2;
480  DivG12prime_xTx_Descr(int I) : I_(I) { assert(I >= 0 && I <= 1); }
481  DivG12prime_xTx_Descr(const DivG12prime_xTx_Descr& a) : Contractable<DivG12prime_xTx_Descr>(a), I_(a.I_) {}
482  unsigned int key() const { return I_; }
483  std::string description() const { return label_(I_); }
484  std::string label() const { return symbol_(I_); }
485  int I() const { return I_; }
486  int psymm(int i, int j) const { assert(false); }
487  int hermitian(int i) const { if (i != I_) return +1; else return -1; }
488  private:
489  DivG12prime_xTx_Descr();
490  static std::string label_(int I);
491  static std::string symbol_(int I);
492  int I_;
493  };
494  typedef GenOper< DivG12prime_xTx_Descr > DivG12prime_xTx;
495 
496 };
497 
498 #endif
499 
R12_k_G12 is a two-body operator of form r_{12}^k * exp(-\gamma * r_{12}), where k is an integer and ...
Definition: oper.h:339
virtual std::string description() const =0
Returns full human-readable description of the operator.
use this as a base to add to Derived a "contracted()" attribute
Definition: contractable.h:27
virtual int hermitian(int p) const =0
Returns 1, 0, or -1, if each operator in the set is Hermitian, non-Hermitian, or anti-Hermitian w....
ConstructablePolymorphically is a base for all objects which can be constructed using a SafePtr to a ...
Definition: polyconstr.h:31
std::string label() const
Implementation of OperSet::label()
Definition: oper.h:178
GenMultSymmOper is a generic multiplicative symmetric N-body operator.
Definition: oper.h:225
TwoPRep is the two-body repulsion operator.
Definition: oper.h:312
std::string description() const
Implementation of OperSet::description()
Definition: oper.h:176
Represents quantum numbers of cartesian multipole operator.
Definition: multipole.h:41
GenOper iter_type
GenOper is not a set.
Definition: oper.h:168
Defaults definitions for various parameters assumed by Libint.
Definition: algebra.cc:24
Objects of Hashable<T> class provide hashing function key() which computes keys of type KeyType.
Definition: hashable.h:73
Represents quantum numbers of real spherical multipole operator defined in Eqs.
Definition: multipole.h:185
unsigned int num_oper() const
Number of operators in the set.
Definition: oper.h:170
virtual int psymm(int i, int j) const =0
Returns 1, 0, or -1, if each operator in the set is symmetric, nonsymmetric, or antisymmetric with re...
virtual std::string label() const =0
Returns short label for the operator.
Oper()
The only declared constructor is only useable by derived classes.
Definition: oper.h:106
GenOper is a single operator described by descriptor Descr.
Definition: oper.h:162
OperatorProperties describes various properties of an operator or operator set.
Definition: oper.h:52
static const unsigned int max_key
K can range from 0 to 1.
Definition: oper.h:393
R12_k_G12_Descr(int K)
K can range from -1 to 4.
Definition: oper.h:343
Ti_G12 is a two-body operator of form [T_i, G12], where i is particle index (0 or 1) and G12 is a Gau...
Definition: oper.h:389
SphericalMultipole_Descr()
Default ctor makes a 0th-order multipole.
Definition: oper.h:294
Oper is OperSet characterized by properties Props.
Definition: oper.h:90
(BOOST_PP_DECLARE_HERMITIAN_ONEBODY_DESCRIPTOR, MultiplicativeODep, BOOST_PP_HERMITIAN_ONEBODY_OPER_LIST) template< unsigned int NDIM > struct CartesianMultipole_Descr GenOper< CartesianMultipole_Descr< NDIM > > CartesianMultipoleOper
cartesian multipole operator in NDIM dimensions
Definition: oper.h:282
R12k_R12l_G12 is a two-body operator of form ( r_{12x}^kx * r_{12y}^ky * r_{12z}^kz ) * (r_{12x}^lx *...
Definition: oper.h:363
SphericalMultipole_Descr(int l, int m)
constructs if , otherwise constructs
Definition: oper.h:296
GTG_1d is the two-body 1-dimensional Gaussian geminal.
Definition: oper.h:325
Descr & descr()
Return the descriptor object.
Definition: oper.h:180
OperSet is the base class for all (sets of) operators.
Definition: oper.h:64
int hermitian(int p) const
Implementation of OperSet::hermitian()
Definition: oper.h:142
int psymm(int i, int j) const
Implementation of OperSet::psymm()
Definition: oper.h:117
bool origin_dependent() const
Implementation of OperSet::origin_dependent()
Definition: oper.h:100
virtual unsigned int num_oper() const =0
Number of operators in the set.
virtual bool origin_dependent() const =0
is operator origin-dependent?
Represents quantum numbers of real spherical multipole operator defined in Eqs.
Definition: oper.h:288
const Descr & descr() const
Return the descriptor object.
Definition: oper.h:182
static const unsigned int max_key
Range of key is [0,Descr::max_key)
Definition: oper.h:174
unsigned int key() const
Implementation of Hashable::key()
Definition: oper.h:172
Permutational symmetries: antisymmetric(anti), symmetric(symm), nonsymmetric (nonsymm),...
Definition: oper.h:40
This exception used to indicate some programming error.
Definition: exception.h:95
SphericalMultipoleQuanta()
constructs an object in default (unusable) state
Definition: multipole.h:191