LIBINT 2.9.0
oper.h
1/*
2 * Copyright (C) 2004-2024 Edward F. Valeev
3 *
4 * This file is part of Libint compiler.
5 *
6 * Libint compiler 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 compiler 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 compiler. 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 <contractable.h>
25#include <global_macros.h>
26#include <hashable.h>
27#include <iter.h>
28#include <multipole.h>
29#include <util.h>
30#include <vectorn.h>
31
32#include <boost/preprocessor/list/for_each.hpp>
33#include <string>
34
35namespace libint2 {
36
40 typedef enum { anti = -1, symm = 1, nonsymm = 0, nonstd = -2 } type;
41};
42
50template <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;
76 virtual int psymm(int i, int j) const = 0;
79 virtual int hermitian(int p) const = 0;
80
82 virtual bool origin_dependent() const = 0;
83
85 virtual unsigned int num_oper() const = 0;
86};
87
90template <class Props>
91class Oper : public OperSet {
92 public:
93 typedef Props Properties;
94 virtual ~Oper() {}
95
97 int psymm(int i, int j) const override;
99 int hermitian(int p) const override;
101 bool origin_dependent() const override { return Props::odep; }
102
103 bool operator==(const Oper&) const;
104
105 protected:
107 Oper() {}
108
109 private:
112 virtual int nonstd_psymm(int i, int j) const {
113 throw ProgrammingError("nonstd_psymm is not overloaded");
114 }
116 virtual int nonstd_hermitian(int p) const {
117 throw ProgrammingError("nonstd_hermitian is not overloaded");
118 }
119};
120
121template <class Props>
122int Oper<Props>::psymm(int i, int j) const {
123 if (i < 0 || i >= static_cast<int>(Props::np))
124 throw std::runtime_error(
125 "Oper<Props>::psymm(i,j) -- index i out of bounds");
126 if (j < 0 || j >= static_cast<int>(Props::np))
127 throw std::runtime_error(
128 "Oper<Props>::psymm(i,j) -- index j out of bounds");
129 if (i == j) return 1;
130
131 switch (Props::psymm) {
132 case PermutationalSymmetry::anti:
133 return -1;
134 case PermutationalSymmetry::symm:
135 return 1;
136 case PermutationalSymmetry::nonsymm:
137 return 0;
138 case PermutationalSymmetry::nonstd:
139 return nonstd_psymm(i, j);
140 default:
141 abort();
142 }
143}
144
145template <class Props>
146int Oper<Props>::hermitian(int p) const {
147 if (Props::multiplicative)
148 return +1;
149 else
150 return nonstd_hermitian(p);
151}
152
153template <class Props>
154bool Oper<Props>::operator==(const Oper& a) const {
155 return true;
156}
157
159
162template <class Descr>
163class GenOper : public Oper<typename Descr::Properties>,
164 public Hashable<unsigned, ComputeKey> {
165 public:
166 typedef Descr Descriptor;
167 typedef typename Descr::Properties Properties;
171
172 unsigned int num_oper() const override { return 1; }
174 unsigned int key() const override { return descr_.key(); }
176 static const unsigned int max_key = Descr::max_key;
178 std::string description() const override { return descr_.description(); }
180 std::string label() const override { return descr_.label(); }
182 Descr& descr() { return descr_; }
184 const Descr& descr() const { return descr_; }
185
186 GenOper(Descr descr = Descr()) : descr_(descr) {}
187 GenOper(const std::shared_ptr<GenOper>& o) : descr_(o->descr_) {}
188 GenOper(const std::shared_ptr<OperSet>& o)
189 : descr_(require_dynamic_cast<GenOper, OperSet>(o)->descr_) {}
190 GenOper(const std::shared_ptr<ConstructablePolymorphically>& o)
191 : descr_(require_dynamic_cast<GenOper, ConstructablePolymorphically>(o)
192 ->descr_) {}
193 explicit GenOper(const ConstructablePolymorphically& o)
194 : descr_(require_dynamic_cast<GenOper, ConstructablePolymorphically>(&o)
195 ->descr_) {}
196 virtual ~GenOper() {}
197
198 private:
199 Descr descr_;
200
202 int nonstd_psymm(int i, int j) const override {
203 // TODO: figure out how to call this only if Desc::Properties::psymm ==
204 // PermutationalSymmetry::nonstd
205 if (Descr::Properties::psymm == PermutationalSymmetry::nonstd)
206 return descr_.psymm(i, j);
207 else
208 throw ProgrammingError(
209 "GenOper::nonstd_psymm -- descriptor is not nonstd");
210 }
211
213 int nonstd_hermitian(int i) const override {
214 // TODO: figure out how to call this only if Desc::Properties::psymm ==
215 // PermutationalSymmetry::nonstd
216 if (!Descr::Properties::multiplicative)
217 return descr_.hermitian(i);
218 else
219 throw ProgrammingError(
220 "GenOper::nonstd_hermitian -- this operator is multiplicative");
221 }
222};
223
225
226typedef OperatorProperties<1, false, PermutationalSymmetry::nonsymm>
227 Nonmultiplicative1Body_Props;
228typedef OperatorProperties<1, true, PermutationalSymmetry::nonsymm>
229 Multiplicative1Body_Props;
230typedef OperatorProperties<1, true, PermutationalSymmetry::nonsymm, true>
231 MultiplicativeODep1Body_Props;
232typedef OperatorProperties<2, true, PermutationalSymmetry::symm>
233 MultiplicativeSymm2Body_Props;
234typedef OperatorProperties<2, true, PermutationalSymmetry::nonsymm>
235 MultiplicativeNonsymm2Body_Props;
236typedef OperatorProperties<2, false, PermutationalSymmetry::symm>
237 NonmultiplicativeSymm2Body_Props;
238typedef OperatorProperties<2, false, PermutationalSymmetry::nonsymm>
239 NonmultiplicativeNonsymm2Body_Props;
240
243template <unsigned int N>
244struct GenMultSymmOper_Descr : public Contractable<GenMultSymmOper_Descr<N>> {
246 static const unsigned int max_key = 1;
247 unsigned int key() const { return 0; }
248 std::string description() const {
249 return "generic multiplicative symmetric operator";
250 }
251 std::string label() const { return "GenMultSymmOper"; }
252 int psymm(int i, int j) const { abort(); }
253 int hermitian(int i) const { abort(); }
254};
256
257#define BOOST_PP_DECLARE_HERMITIAN_ONEBODY_DESCRIPTOR(r, propprefix, opname) \
258 struct opname##_Descr : public Contractable<opname##_Descr> { \
259 typedef propprefix##1Body_Props Properties; \
260 static const unsigned int max_key = 1; \
261 unsigned int key() const { return 0; } \
262 std::string description() const { return #opname; } \
263 std::string label() const { return #opname; } \
264 int psymm(int i, int j) const { abort(); } \
265 int hermitian(int i) const { return +1; } \
266 }; \
267 typedef GenOper<opname##_Descr> opname##Oper;
268
269#define BOOST_PP_HERMITIAN_ONEBODY_OPER_LIST (Kinetic, BOOST_PP_NIL)
270BOOST_PP_LIST_FOR_EACH(BOOST_PP_DECLARE_HERMITIAN_ONEBODY_DESCRIPTOR,
271 Nonmultiplicative, BOOST_PP_HERMITIAN_ONEBODY_OPER_LIST)
272#undef BOOST_PP_HERMITIAN_ONEBODY_OPER_LIST
273#define BOOST_PP_HERMITIAN_ONEBODY_OPER_LIST (Overlap, BOOST_PP_NIL)
274BOOST_PP_LIST_FOR_EACH(BOOST_PP_DECLARE_HERMITIAN_ONEBODY_DESCRIPTOR,
275 Multiplicative, BOOST_PP_HERMITIAN_ONEBODY_OPER_LIST)
276#undef BOOST_PP_HERMITIAN_ONEBODY_OPER_LIST
277#define BOOST_PP_HERMITIAN_ONEBODY_OPER_LIST (ElecPot, BOOST_PP_NIL)
278BOOST_PP_LIST_FOR_EACH(BOOST_PP_DECLARE_HERMITIAN_ONEBODY_DESCRIPTOR,
279 MultiplicativeODep, BOOST_PP_HERMITIAN_ONEBODY_OPER_LIST)
280#undef BOOST_PP_HERMITIAN_ONEBODY_OPER_LIST
281
282// N.B. σpVσp has 4 (Pauli) components, so need to customize its descriptor ...
283// may need to generalize this if need similar operators elsewhere
284// #define BOOST_PP_HERMITIAN_ONEBODY_OPER_LIST (σpVσp, BOOST_PP_NIL)
285// BOOST_PP_LIST_FOR_EACH ( BOOST_PP_DECLARE_HERMITIAN_ONEBODY_DESCRIPTOR,
286// MultiplicativeODep, BOOST_PP_HERMITIAN_ONEBODY_OPER_LIST) #undef
287// BOOST_PP_HERMITIAN_ONEBODY_OPER_LIST
288
289struct σpVσp_Descr : public Contractable<σpVσp_Descr> {
290 typedef MultiplicativeODep1Body_Props Properties;
291
292 σpVσp_Descr() : pauli_index_(0) {}
293 σpVσp_Descr(int pauli_index) : pauli_index_(pauli_index) {
294 assert(pauli_index <= 3);
295 }
296
297 static const unsigned int max_key = 4;
298 unsigned int key() const { return pauli_index(); }
299 std::string description() const {
300 std::string descr("opVop[");
301 if (pauli_index() == 0)
302 descr += "0";
303 else if (pauli_index() == 1)
304 descr += "Z";
305 else if (pauli_index() == 2)
306 descr += "X";
307 else if (pauli_index() == 3)
308 descr += "Y";
309 else
310 abort();
311 return descr + "]";
312 }
313 std::string label() const { return description(); }
314 int psymm(int i, int j) const { abort(); }
315 int hermitian(int i) const { return +1; }
316
317 int pauli_index() const { return pauli_index_; }
318
319 private:
320 const int pauli_index_ = -1;
321};
322typedef GenOper<σpVσp_Descr> σpVσpOper;
323
328template <unsigned int NDIM>
330 : public Contractable<CartesianMultipole_Descr<NDIM>>,
331 public CartesianMultipoleQuanta<NDIM> {
334
336 CartesianMultipole_Descr(unsigned int k) {
337 assert(NDIM == 1u);
338 this->inc(0, k);
339 }
340 std::string description() const {
341 std::string descr("CartesianMultipole[");
342 std::ostringstream oss;
343 for (unsigned i = 0; i != NDIM; ++i) {
344 oss << (*this)[i];
345 if (i + 1 != NDIM) oss << ",";
346 }
347 return descr + oss.str() + "]";
348 }
349 std::string label() const { return description(); }
350 int psymm(int i, int j) const { abort(); }
351 int hermitian(int i) const { return +1; }
352};
353template <unsigned int NDIM>
355
361struct SphericalMultipole_Descr : public Contractable<SphericalMultipole_Descr>,
364 using SphericalMultipoleQuanta::max_key;
365 using SphericalMultipoleQuanta::Sign;
366
372 SphericalMultipole_Descr(int l, int m, Sign sign)
373 : SphericalMultipoleQuanta(l, m, sign) {}
375 : SphericalMultipoleQuanta(quanta) {}
376
377 std::string description() const {
378 std::string descr =
379 std::string("SphericalMultipole[") + std::to_string(this->l()) + "," +
380 std::to_string((this->sign() == Sign::plus ? 1 : -1) * this->m()) + "]";
381 return descr;
382 }
383 std::string label() const { return description(); }
384 int psymm(int i, int j) const { abort(); }
385 int hermitian(int i) const { return +1; }
386};
387using SphericalMultipoleOper = GenOper<SphericalMultipole_Descr>;
388
391struct TwoPRep_Descr : public Contractable<TwoPRep_Descr> {
393 static const unsigned int max_key = 1;
394 unsigned int key() const { return 0; }
395 std::string description() const { return "1/r_{12}"; }
396 std::string label() const { return "TwoPRep"; }
397 int psymm(int i, int j) const { abort(); }
398 int hermitian(int i) const { return +1; }
399};
401
404struct GTG_1d_Descr : public Contractable<GTG_1d_Descr> {
406 static const unsigned int max_key = 1;
407 unsigned int key() const { return 0; }
408 std::string description() const { return "GTG_1d"; }
409 std::string label() const { return "GTG_1d"; }
410 int psymm(int i, int j) const { abort(); }
411 int hermitian(int i) const { return +1; }
412};
414
418class R12_k_G12_Descr : public Contractable<R12_k_G12_Descr> {
419 public:
422 R12_k_G12_Descr(int K) : K_(K) { assert(K >= -1 && K <= 4); }
424 : Contractable<R12_k_G12_Descr>(a), K_(a.K_) {}
425 static const unsigned int max_key = 5;
426 unsigned int key() const { return K_ + 1; }
427 std::string description() const { return label_(K_, this->contracted()); }
428 std::string label() const { return symbol_(K_, this->contracted()); }
429 int K() const { return K_; }
430 int psymm(int i, int j) const { abort(); }
431 int hermitian(int i) const { abort(); }
432
433 private:
435 static std::string label_(int K, bool contracted);
436 static std::string symbol_(int K, bool contracted);
437 int K_;
438};
439typedef GenOper<R12_k_G12_Descr> R12kG12;
440
445class R12k_R12l_G12_Descr : public Contractable<R12k_R12l_G12_Descr> {
446 public:
448 static const int kmax = 4;
449 R12k_R12l_G12_Descr(const IntVec3& K, const IntVec3& L) : K_(K), L_(L) {}
451 : Contractable<R12k_R12l_G12_Descr>(a), K_(a.K_), L_(a.L_) {}
452 const IntVec3& K() const { return K_; }
453 const IntVec3& L() const { return L_; }
454 static const unsigned int max_key = kmax * kmax * kmax * kmax * kmax * kmax;
455 unsigned int key() const;
456 std::string description() const { return label_(K_, L_, this->contracted()); }
457 std::string label() const { return symbol_(K_, L_, this->contracted()); }
458 int psymm(int i, int j) const { abort(); }
459 int hermitian(int i) const { abort(); }
460
461 private:
463 static std::string label_(const IntVec3& K, const IntVec3& L,
464 bool contracted);
465 static std::string symbol_(const IntVec3& K, const IntVec3& L,
466 bool contracted);
467 IntVec3 K_;
468 IntVec3 L_;
469};
471
475class Ti_G12_Descr : public Contractable<Ti_G12_Descr> {
476 public:
479 static const unsigned int max_key = 2;
480 Ti_G12_Descr(int K) : K_(K) { assert(K >= 0 && K <= 1); }
481 Ti_G12_Descr(const Ti_G12_Descr& a)
482 : Contractable<Ti_G12_Descr>(a), K_(a.K_) {}
483 unsigned int key() const { return K_; }
484 std::string description() const { return label_(K_, this->contracted()); }
485 std::string label() const { return symbol_(K_, this->contracted()); }
486 int K() const { return K_; }
487 int psymm(int i, int j) const { abort(); }
488 int hermitian(int i) const {
489 if (i != K_)
490 return +1;
491 else
492 return -1;
493 }
494
495 private:
496 Ti_G12_Descr();
497 static std::string label_(int K, bool contracted);
498 static std::string symbol_(int K, bool contracted);
499 int K_;
500};
501typedef GenOper<Ti_G12_Descr> TiG12;
502
507class G12_Ti_G12_Descr : public Contractable<G12_Ti_G12_Descr> {
508 public:
509 typedef MultiplicativeSymm2Body_Props Properties;
511 static const unsigned int max_key = 2;
512 G12_Ti_G12_Descr(int K) : K_(K) { assert(K >= 0 && K <= 1); }
513 G12_Ti_G12_Descr(const G12_Ti_G12_Descr& a)
514 : Contractable<G12_Ti_G12_Descr>(a), K_(a.K_) {}
515 unsigned int key() const { return K_; }
516 std::string description() const { return label_(K_, this->contracted()); }
517 std::string label() const { return symbol_(K_, this->contracted()); }
518 int K() const { return K_; }
519 int psymm(int i, int j) const { abort(); }
520 int hermitian(int i) const { return +1; }
521
522 private:
523 G12_Ti_G12_Descr();
524 static std::string label_(int K, bool contracted);
525 static std::string symbol_(int K, bool contracted);
526 int K_;
527};
528typedef GenOper<G12_Ti_G12_Descr> G12TiG12;
529
533struct R1dotR1_G12_Descr : public Contractable<R1dotR1_G12_Descr> {
534 typedef MultiplicativeNonsymm2Body_Props Properties;
535 static const unsigned int max_key = 1;
536 unsigned int key() const { return 0; }
537 std::string description() const { return "r_1.r_1 x G12"; }
538 std::string label() const { return "R1dotR1_G12"; }
539 int psymm(int i, int j) const { abort(); }
540 int hermitian(int i) const { abort(); }
541};
542typedef GenOper<R1dotR1_G12_Descr> R1dotR1_G12;
543
547struct R2dotR2_G12_Descr : public Contractable<R2dotR2_G12_Descr> {
548 typedef MultiplicativeNonsymm2Body_Props Properties;
549 static const unsigned int max_key = 1;
550 unsigned int key() const { return 0; }
551 std::string description() const { return "r_2.r_2 x G12"; }
552 std::string label() const { return "R2dotR2_G12"; }
553 int psymm(int i, int j) const { abort(); }
554 int hermitian(int i) const { abort(); }
555};
556typedef GenOper<R2dotR2_G12_Descr> R2dotR2_G12;
557
561struct R1dotR2_G12_Descr : public Contractable<R1dotR2_G12_Descr> {
562 typedef MultiplicativeSymm2Body_Props Properties;
563 static const unsigned int max_key = 1;
564 unsigned int key() const { return 0; }
565 std::string description() const { return "r_1.r_2 x G12"; }
566 std::string label() const { return "R1dotR2_G12"; }
567 int psymm(int i, int j) const { abort(); }
568 int hermitian(int i) const { abort(); }
569};
570typedef GenOper<R1dotR2_G12_Descr> R1dotR2_G12;
571
575struct DivG12prime_xTx_Descr : public Contractable<DivG12prime_xTx_Descr> {
576 typedef NonmultiplicativeNonsymm2Body_Props Properties;
577 static const unsigned int max_key = 2;
578 DivG12prime_xTx_Descr(int I) : I_(I) { assert(I >= 0 && I <= 1); }
579 DivG12prime_xTx_Descr(const DivG12prime_xTx_Descr& a)
580 : Contractable<DivG12prime_xTx_Descr>(a), I_(a.I_) {}
581 unsigned int key() const { return I_; }
582 std::string description() const { return label_(I_); }
583 std::string label() const { return symbol_(I_); }
584 int I() const { return I_; }
585 int psymm(int i, int j) const { abort(); }
586 int hermitian(int i) const {
587 if (i != I_)
588 return +1;
589 else
590 return -1;
591 }
592
593 private:
594 DivG12prime_xTx_Descr();
595 static std::string label_(int I);
596 static std::string symbol_(int I);
597 int I_;
598};
599typedef GenOper<DivG12prime_xTx_Descr> DivG12prime_xTx;
600
601}; // namespace libint2
602
603#endif
Represents quantum numbers of cartesian multipole operator.
Definition multipole.h:43
static const unsigned max_key
The range of keys is [0,max_key).
Definition multipole.h:136
void inc(unsigned int xyz, unsigned int c=1u)
Add c quanta along xyz.
Definition multipole.h:79
ConstructablePolymorphically is a base for all objects which can be constructed using a std::shared_p...
Definition polyconstr.h:30
use this as a base to add to Derived a "contracted()" attribute
Definition contractable.h:28
GenOper is a single operator described by descriptor Descr.
Definition oper.h:164
GenOper iter_type
GenOper is not a set.
Definition oper.h:170
Descr & descr()
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:176
std::string description() const override
Implementation of OperSet::description()
Definition oper.h:178
std::string label() const override
Implementation of OperSet::label()
Definition oper.h:180
const Descr & descr() const
Return the descriptor object.
Definition oper.h:184
unsigned int num_oper() const override
Number of operators in the set.
Definition oper.h:172
unsigned int key() const override
Implementation of Hashable::key()
Definition oper.h:174
Objects of Hashable<T> class provide hashing function key() which computes keys of type KeyType.
Definition hashable.h:79
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:91
int psymm(int i, int j) const override
Implementation of OperSet::psymm()
Definition oper.h:122
bool origin_dependent() const override
Implementation of OperSet::origin_dependent()
Definition oper.h:101
Oper()
The only declared constructor is only useable by derived classes.
Definition oper.h:107
int hermitian(int p) const override
Implementation of OperSet::hermitian()
Definition oper.h:146
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:85
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:418
R12_k_G12_Descr(int K)
K can range from -1 to 4.
Definition oper.h:422
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:445
Represents quantum numbers of real spherical multipole operator defined in Eqs.
Definition multipole.h:197
SphericalMultipoleQuanta()
constructs an object in default (unusable) state
Definition multipole.h:203
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:475
static const unsigned int max_key
K can range from 0 to 1.
Definition oper.h:479
Defaults definitions for various parameters assumed by Libint.
Definition algebra.cc:24
cartesian multipole operator in NDIM dimensions
Definition oper.h:331
GTG_1d is the two-body 1-dimensional Gaussian geminal.
Definition oper.h:404
GenMultSymmOper is a generic multiplicative symmetric N-body operator.
Definition oper.h:244
Permutational symmetries: antisymmetric(anti), symmetric(symm), nonsymmetric (nonsymm),...
Definition oper.h:39
Represents quantum numbers of real spherical multipole operator defined in Eqs.
Definition oper.h:362
SphericalMultipole_Descr(int l, int m)
constructs if , otherwise constructs
Definition oper.h:371
SphericalMultipole_Descr()
Default ctor makes a 0th-order multipole.
Definition oper.h:368
TwoPRep is the two-body repulsion operator.
Definition oper.h:391