LIBINT 2.7.2
oper.h
1/*
2 * Copyright (C) 2004-2021 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
36namespace libint2 {
37
41 typedef enum {anti=-1, symm=1, nonsymm=0, nonstd=-2} type;
42 };
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 override;
98 int hermitian(int p) const override;
100 bool origin_dependent() const override { 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 override { return 1; }
172 unsigned int key() const override { return descr_.key(); }
174 static const unsigned int max_key = Descr::max_key;
176 std::string description() const override { return descr_.description(); }
178 std::string label() const override { 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 override {
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 override {
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 { abort(); }
232 int hermitian(int i) const { abort(); }
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 { abort(); } \
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)
249BOOST_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)
252BOOST_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)
255BOOST_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
261template <unsigned int NDIM>
262struct 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 { abort(); }
280 int hermitian(int i) const { return +1; }
281};
283
288struct 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 { abort(); }
306 int hermitian(int i) const { return +1; }
307};
308using 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 { abort(); }
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 { abort(); }
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); }
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 { abort(); }
351 int hermitian(int i) const { abort(); }
352 private:
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 { abort(); }
376 int hermitian(int i) const { abort(); }
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 { abort(); }
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 { abort(); }
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 { abort(); }
444 int hermitian(int i) const { abort(); }
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 { abort(); }
457 int hermitian(int i) const { abort(); }
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 { abort(); }
470 int hermitian(int i) const { abort(); }
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 { abort(); }
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
Represents quantum numbers of cartesian multipole operator.
Definition: multipole.h:41
ConstructablePolymorphically is a base for all objects which can be constructed using a SafePtr to a ...
Definition: polyconstr.h:31
use this as a base to add to Derived a "contracted()" attribute
Definition: contractable.h:27
GenOper is a single operator described by descriptor Descr.
Definition: oper.h:162
GenOper iter_type
GenOper is not a set.
Definition: oper.h:168
Descr & descr()
Return the descriptor object.
Definition: oper.h:180
static const unsigned int max_key
Range of key is [0,Descr::max_key)
Definition: oper.h:174
std::string description() const override
Implementation of OperSet::description()
Definition: oper.h:176
std::string label() const override
Implementation of OperSet::label()
Definition: oper.h:178
const Descr & descr() const
Return the descriptor object.
Definition: oper.h:182
unsigned int num_oper() const override
Number of operators in the set.
Definition: oper.h:170
unsigned int key() const override
Implementation of Hashable::key()
Definition: oper.h:172
Objects of Hashable<T> class provide hashing function key() which computes keys of type KeyType.
Definition: hashable.h:74
OperSet is the base class for all (sets of) operators.
Definition: oper.h:64
virtual std::string label() const =0
Returns short label for the operator.
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....
virtual unsigned int num_oper() const =0
Number of operators in the set.
virtual bool origin_dependent() const =0
is operator origin-dependent?
virtual std::string description() const =0
Returns full human-readable description of the operator.
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...
Oper is OperSet characterized by properties Props.
Definition: oper.h:90
int psymm(int i, int j) const override
Implementation of OperSet::psymm()
Definition: oper.h:117
bool origin_dependent() const override
Implementation of OperSet::origin_dependent()
Definition: oper.h:100
Oper()
The only declared constructor is only useable by derived classes.
Definition: oper.h:106
int hermitian(int p) const override
Implementation of OperSet::hermitian()
Definition: oper.h:142
OperatorProperties describes various properties of an operator or operator set.
Definition: oper.h:52
This exception used to indicate some programming error.
Definition: exception.h:95
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
R12_k_G12_Descr(int K)
K can range from -1 to 4.
Definition: oper.h:343
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
Represents quantum numbers of real spherical multipole operator defined in Eqs.
Definition: multipole.h:185
SphericalMultipoleQuanta()
constructs an object in default (unusable) state
Definition: multipole.h:191
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
static const unsigned int max_key
K can range from 0 to 1.
Definition: oper.h:393
Defaults definitions for various parameters assumed by Libint.
Definition: algebra.cc:24
(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
GTG_1d is the two-body 1-dimensional Gaussian geminal.
Definition: oper.h:325
GenMultSymmOper is a generic multiplicative symmetric N-body operator.
Definition: oper.h:225
Permutational symmetries: antisymmetric(anti), symmetric(symm), nonsymmetric (nonsymm),...
Definition: oper.h:40
Represents quantum numbers of real spherical multipole operator defined in Eqs.
Definition: oper.h:288
SphericalMultipole_Descr(int l, int m)
constructs if , otherwise constructs
Definition: oper.h:296
SphericalMultipole_Descr()
Default ctor makes a 0th-order multipole.
Definition: oper.h:294
TwoPRep is the two-body repulsion operator.
Definition: oper.h:312