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 36 namespace libint2 { 37 38 /** Permutational symmetries: antisymmetric(anti), symmetric(symm), nonsymmetric (nonsymm), 39 some more complicated symmetry (nonstd) */ 40 struct PermutationalSymmetry { 41 typedef enum {anti=-1, symm=1, nonsymm=0, nonstd=-2} type; 42 }; 43 44 /** OperatorProperties describes various properties of an operator or operator set 45 @tparam NP number of particles 46 @tparam multi true if multiplicative 47 @tparam psymmetry symmetry with respect to permutation of bra and ket 48 @tparam origin_dependent true if operator is origin-dependent 49 */ 50 template <unsigned int NP, bool multi, PermutationalSymmetry::type psymmetry, 51 bool origin_dependent = false> 52 class OperatorProperties { 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 60 /** OperSet is the base class for all (sets of) operators. 61 OperSet's must be constructable using 62 SafePtr<OperSet> or SafePtr<ConstructablePolymorphically>. 63 */ 64 class OperSet : public ConstructablePolymorphically { 65 public: 66 typedef DummyIterator iter_type; ~OperSet()67 virtual ~OperSet() {}; 68 69 /// Returns full human-readable description of the operator 70 virtual std::string description() const =0; 71 /// Returns short label for the operator 72 virtual std::string label() const =0; 73 /** Returns 1, 0, or -1, if each operator in the set is symmetric, nonsymmetric, 74 or antisymmetric with respect to permutation of particles i and j */ 75 virtual int psymm(int i, int j) const =0; 76 /** Returns 1, 0, or -1, if each operator in the set is Hermitian, non-Hermitian, 77 or anti-Hermitian w.r.t. particle p */ 78 virtual int hermitian(int p) const =0; 79 80 /// is operator origin-dependent? 81 virtual bool origin_dependent() const =0; 82 83 /// Number of operators in the set 84 virtual unsigned int num_oper() const =0; 85 }; 86 87 /** Oper is OperSet characterized by properties Props 88 */ 89 template <class Props> 90 class Oper : public OperSet { 91 public: 92 typedef Props Properties; ~Oper()93 virtual ~Oper() {} 94 95 /// Implementation of OperSet::psymm() 96 int psymm(int i, int j) const override; 97 /// Implementation of OperSet::hermitian() 98 int hermitian(int p) const override; 99 /// Implementation of OperSet::origin_dependent() origin_dependent()100 bool origin_dependent() const override { return Props::odep; } 101 102 bool operator==(const Oper&) const; 103 104 protected: 105 /// The only declared constructor is only useable by derived classes Oper()106 Oper() {} 107 108 private: 109 /// Must be overloaded by derived classes if Props::psymm == PermutationalSymmetry::nonstd nonstd_psymm(int i,int j)110 virtual int nonstd_psymm(int i, int j) const { throw ProgrammingError("nonstd_psymm is not overloaded"); } 111 /// Must be overloaded by derived classes if Props::multi != true nonstd_hermitian(int p)112 virtual int nonstd_hermitian(int p) const { throw ProgrammingError("nonstd_hermitian is not overloaded"); } 113 }; 114 115 template <class Props> 116 int psymm(int i,int j)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 hermitian(int p)142 Oper<Props>::hermitian(int p) const 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 157 ////////////////////////////// 158 159 /** GenOper is a single operator described by descriptor Descr 160 */ 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; 166 typedef Oper<Properties> parent_type; 167 /// GenOper is not a set 168 typedef GenOper iter_type; 169 num_oper()170 unsigned int num_oper() const override { return 1; } 171 /// Implementation of Hashable::key() key()172 unsigned int key() const override { return descr_.key(); } 173 /// Range of key is [0,Descr::max_key) 174 static const unsigned int max_key = Descr::max_key; 175 /// Implementation of OperSet::description() description()176 std::string description() const override { return descr_.description(); } 177 /// Implementation of OperSet::label() label()178 std::string label() const override { return descr_.label(); } 179 /// Return the descriptor object descr()180 Descr& descr() { return descr_; } 181 /// Return the descriptor object descr()182 const Descr& descr() const { return descr_; } 183 descr_(descr)184 GenOper(Descr descr = Descr()) : descr_(descr) {} GenOper(const SafePtr<GenOper> & o)185 GenOper(const SafePtr<GenOper>& o) : descr_(o->descr_) {} GenOper(const SafePtr<OperSet> & o)186 GenOper(const SafePtr<OperSet>& o) : descr_(require_dynamic_cast<GenOper,OperSet>(o)->descr_) {} GenOper(const SafePtr<ConstructablePolymorphically> & o)187 GenOper(const SafePtr<ConstructablePolymorphically>& o) : descr_(require_dynamic_cast<GenOper,ConstructablePolymorphically>(o)->descr_) {} GenOper(const ConstructablePolymorphically & o)188 explicit GenOper(const ConstructablePolymorphically& o) : descr_(require_dynamic_cast<GenOper,ConstructablePolymorphically>(&o)->descr_) {} ~GenOper()189 virtual ~GenOper() {} 190 191 private: 192 Descr descr_; 193 194 /// Implementation of Oper::nonstd_psymm() nonstd_psymm(int i,int j)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 202 /// Implementation of Oper::nonstd_hermitian() nonstd_hermitian(int i)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 212 ////////////////////////////// 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 222 /** GenMultSymmOper is a generic multiplicative symmetric N-body operator 223 */ 224 template <unsigned int N> 225 struct GenMultSymmOper_Descr : public Contractable<GenMultSymmOper_Descr<N> > { 226 typedef OperatorProperties<N,true,PermutationalSymmetry::symm> Properties; 227 static const unsigned int max_key = 1; keyGenMultSymmOper_Descr228 unsigned int key() const { return 0; } descriptionGenMultSymmOper_Descr229 std::string description() const { return "generic multiplicative symmetric operator"; } labelGenMultSymmOper_Descr230 std::string label() const { return "GenMultSymmOper"; } psymmGenMultSymmOper_Descr231 int psymm(int i, int j) const { abort(); } hermitianGenMultSymmOper_Descr232 int hermitian(int i) const { abort(); } 233 }; 234 typedef GenOper< GenMultSymmOper_Descr<2> > GenMultSymm2BodyOper; 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) 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 258 /// cartesian multipole operator in \c NDIM dimensions 259 /// \f$ \hat{O}(\vec{k}) \equiv \vec{r}^{\cdot \vec{k}} = r_1^{k_1} r_2^{k_2} \cdots \f$ 260 /// \internal OriginDerivative<NDIM> is used to store cartesian multipole quanta, not the derivative quanta 261 template <unsigned int NDIM> 262 struct CartesianMultipole_Descr : public Contractable<CartesianMultipole_Descr<NDIM>>, 263 public CartesianMultipoleQuanta<NDIM> { 264 typedef MultiplicativeODep1Body_Props Properties; 265 using CartesianMultipoleQuanta<NDIM>::max_key; 266 CartesianMultipole_DescrCartesianMultipole_Descr267 CartesianMultipole_Descr() { } CartesianMultipole_DescrCartesianMultipole_Descr268 CartesianMultipole_Descr(unsigned int k) { assert(NDIM==1u); this->inc(0,k); } descriptionCartesianMultipole_Descr269 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 } labelCartesianMultipole_Descr278 std::string label() const { return description(); } psymmCartesianMultipole_Descr279 int psymm(int i, int j) const { abort(); } hermitianCartesianMultipole_Descr280 int hermitian(int i) const { return +1; } 281 }; 282 template <unsigned int NDIM> using CartesianMultipoleOper = GenOper<CartesianMultipole_Descr<NDIM>>; 283 284 /** Represents quantum numbers of \em real spherical multipole operator 285 * defined in Eqs. 5 and 6 of J.M. Pérez-Jordá and W. Yang, J Chem Phys 104, 8003 (1996). 286 * ( \f$ m \geq 0 \f$ corresponds to moments \f$ \mathcal{N}^+ \f$ , \f$ m < 0 \f$ corresponds to \f$ \mathcal{N}^- \f$ ) 287 */ 288 struct SphericalMultipole_Descr : public Contractable<SphericalMultipole_Descr>, public SphericalMultipoleQuanta { 289 typedef MultiplicativeODep1Body_Props Properties; 290 using SphericalMultipoleQuanta::max_key; 291 using SphericalMultipoleQuanta::Sign; 292 293 /// Default ctor makes a 0th-order multipole SphericalMultipole_DescrSphericalMultipole_Descr294 SphericalMultipole_Descr() : SphericalMultipole_Descr(0,0) { } 295 /// constructs \f$ \mathcal{N}^{+}_{l,m} \f$ if \f$ m \geq 0 \f$, otherwise constructs \f$ \mathcal{N}^{-}_{l,m} \f$ SphericalMultipole_DescrSphericalMultipole_Descr296 SphericalMultipole_Descr(int l, int m) : SphericalMultipoleQuanta(l,m) {} SphericalMultipole_DescrSphericalMultipole_Descr297 SphericalMultipole_Descr(int l, int m, Sign sign) : SphericalMultipoleQuanta(l,m,sign) {} SphericalMultipole_DescrSphericalMultipole_Descr298 SphericalMultipole_Descr(const SphericalMultipoleQuanta& quanta) : SphericalMultipoleQuanta(quanta) {} 299 descriptionSphericalMultipole_Descr300 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 } labelSphericalMultipole_Descr304 std::string label() const { return description(); } psymmSphericalMultipole_Descr305 int psymm(int i, int j) const { abort(); } hermitianSphericalMultipole_Descr306 int hermitian(int i) const { return +1; } 307 }; 308 using SphericalMultipoleOper = GenOper<SphericalMultipole_Descr>; 309 310 /** TwoPRep is the two-body repulsion operator. 311 */ 312 struct TwoPRep_Descr : public Contractable<TwoPRep_Descr> { 313 typedef MultiplicativeSymm2Body_Props Properties; 314 static const unsigned int max_key = 1; keyTwoPRep_Descr315 unsigned int key() const { return 0; } descriptionTwoPRep_Descr316 std::string description() const { return "1/r_{12}"; } labelTwoPRep_Descr317 std::string label() const { return "TwoPRep"; } psymmTwoPRep_Descr318 int psymm(int i, int j) const { abort(); } hermitianTwoPRep_Descr319 int hermitian(int i) const { return +1; } 320 }; 321 typedef GenOper<TwoPRep_Descr> TwoPRep; 322 323 /** GTG_1d is the two-body 1-dimensional Gaussian geminal 324 */ 325 struct GTG_1d_Descr : public Contractable<GTG_1d_Descr> { 326 typedef MultiplicativeSymm2Body_Props Properties; 327 static const unsigned int max_key = 1; keyGTG_1d_Descr328 unsigned int key() const { return 0; } descriptionGTG_1d_Descr329 std::string description() const { return "GTG_1d"; } labelGTG_1d_Descr330 std::string label() const { return "GTG_1d"; } psymmGTG_1d_Descr331 int psymm(int i, int j) const { abort(); } hermitianGTG_1d_Descr332 int hermitian(int i) const { return +1; } 333 }; 334 typedef GenOper<GTG_1d_Descr> GTG_1d; 335 336 /** R12_k_G12 is a two-body operator of form r_{12}^k * exp(-\gamma * r_{12}), 337 where k is an integer and \gamma is a positive real number. 338 */ 339 class R12_k_G12_Descr : public Contractable<R12_k_G12_Descr> { 340 public: 341 typedef MultiplicativeSymm2Body_Props Properties; 342 /// K can range from -1 to 4 R12_k_G12_Descr(int K)343 R12_k_G12_Descr(int K) : K_(K) { assert(K >= -1 && K <= 4); } R12_k_G12_Descr(const R12_k_G12_Descr & a)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; key()346 unsigned int key() const { return K_ + 1; } description()347 std::string description() const { return label_(K_, this->contracted()); } label()348 std::string label() const { return symbol_(K_, this->contracted()); } K()349 int K() const { return K_; } psymm(int i,int j)350 int psymm(int i, int j) const { abort(); } hermitian(int i)351 int hermitian(int i) const { abort(); } 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 360 /** R12k_R12l_G12 is a two-body operator of form ( r_{12x}^kx * r_{12y}^ky * r_{12z}^kz ) * (r_{12x}^lx * r_{12y}^ly * r_{12z}^lz ) * G12 361 The following restrictions are imposed: 0 <= kx+ky+kz <= 4, 0 <= lx+ly+lz <= 4 362 */ 363 class R12k_R12l_G12_Descr : public Contractable<R12k_R12l_G12_Descr> { 364 public: 365 typedef MultiplicativeSymm2Body_Props Properties; 366 static const int kmax = 4; R12k_R12l_G12_Descr(const IntVec3 & K,const IntVec3 & L)367 R12k_R12l_G12_Descr(const IntVec3& K, const IntVec3& L) : K_(K), L_(L) { } R12k_R12l_G12_Descr(const R12k_R12l_G12_Descr & a)368 R12k_R12l_G12_Descr(const R12k_R12l_G12_Descr& a) : Contractable<R12k_R12l_G12_Descr>(a), K_(a.K_), L_(a.L_) {} K()369 const IntVec3& K() const { return K_; } L()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; description()373 std::string description() const { return label_(K_,L_, this->contracted()); } label()374 std::string label() const { return symbol_(K_,L_, this->contracted()); } psymm(int i,int j)375 int psymm(int i, int j) const { abort(); } hermitian(int i)376 int hermitian(int i) const { abort(); } 377 private: 378 R12k_R12l_G12_Descr(); 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 }; 384 typedef GenOper<R12k_R12l_G12_Descr> R12kR12lG12; 385 386 /** Ti_G12 is a two-body operator of form [T_i, G12], 387 where i is particle index (0 or 1) and G12 is a Gaussian Geminal. 388 */ 389 class Ti_G12_Descr : public Contractable<Ti_G12_Descr> { 390 public: 391 typedef NonmultiplicativeNonsymm2Body_Props Properties; 392 /// K can range from 0 to 1 393 static const unsigned int max_key = 2; Ti_G12_Descr(int K)394 Ti_G12_Descr(int K) : K_(K) { assert(K >= 0 && K <= 1); } Ti_G12_Descr(const Ti_G12_Descr & a)395 Ti_G12_Descr(const Ti_G12_Descr& a) : Contractable<Ti_G12_Descr>(a), K_(a.K_) {} key()396 unsigned int key() const { return K_; } description()397 std::string description() const { return label_(K_, this->contracted()); } label()398 std::string label() const { return symbol_(K_, this->contracted()); } K()399 int K() const { return K_; } psymm(int i,int j)400 int psymm(int i, int j) const { abort(); } hermitian(int i)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 410 /** G12_Ti_G12 is a two-body operator of form [G12, [T_i, G12]] = (Nabla_i G12) \dot (Nabla_i G12) 411 where i is particle index (0 or 1) and G12 is a Gaussian Geminal. 412 It is a *multiplicative* operator! 413 */ 414 class G12_Ti_G12_Descr : public Contractable<G12_Ti_G12_Descr> { 415 public: 416 typedef MultiplicativeSymm2Body_Props Properties; 417 /// K can range from 0 to 1 418 static const unsigned int max_key = 2; G12_Ti_G12_Descr(int K)419 G12_Ti_G12_Descr(int K) : K_(K) { assert(K >= 0 && K <= 1); } G12_Ti_G12_Descr(const G12_Ti_G12_Descr & a)420 G12_Ti_G12_Descr(const G12_Ti_G12_Descr& a) : Contractable<G12_Ti_G12_Descr>(a), K_(a.K_) {} key()421 unsigned int key() const { return K_; } description()422 std::string description() const { return label_(K_, this->contracted()); } label()423 std::string label() const { return symbol_(K_, this->contracted()); } K()424 int K() const { return K_; } psymm(int i,int j)425 int psymm(int i, int j) const { abort(); } hermitian(int i)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 435 /** r_1.r_1 x g12 is a result of differentiation of exp( - a r_1^2 - a r_2^2 - c r_{12}^2) geminal . 436 */ 437 struct R1dotR1_G12_Descr : public Contractable<R1dotR1_G12_Descr> { 438 typedef MultiplicativeNonsymm2Body_Props Properties; 439 static const unsigned int max_key = 1; keyR1dotR1_G12_Descr440 unsigned int key() const { return 0; } descriptionR1dotR1_G12_Descr441 std::string description() const { return "r_1.r_1 x G12"; } labelR1dotR1_G12_Descr442 std::string label() const { return "R1dotR1_G12"; } psymmR1dotR1_G12_Descr443 int psymm(int i, int j) const { abort(); } hermitianR1dotR1_G12_Descr444 int hermitian(int i) const { abort(); } 445 }; 446 typedef GenOper< R1dotR1_G12_Descr > R1dotR1_G12; 447 448 /** r_2.r_2 x g12 is a result of differentiation of exp( - a r_1^2 - a r_2^2 - c r_{12}^2) geminal . 449 */ 450 struct R2dotR2_G12_Descr : public Contractable<R2dotR2_G12_Descr> { 451 typedef MultiplicativeNonsymm2Body_Props Properties; 452 static const unsigned int max_key = 1; keyR2dotR2_G12_Descr453 unsigned int key() const { return 0; } descriptionR2dotR2_G12_Descr454 std::string description() const { return "r_2.r_2 x G12"; } labelR2dotR2_G12_Descr455 std::string label() const { return "R2dotR2_G12"; } psymmR2dotR2_G12_Descr456 int psymm(int i, int j) const { abort(); } hermitianR2dotR2_G12_Descr457 int hermitian(int i) const { abort(); } 458 }; 459 typedef GenOper< R2dotR2_G12_Descr > R2dotR2_G12; 460 461 /** r_1.r_2 x g12 is a result of differentiation of exp( - a r_1^2 - a r_2^2 - c r_{12}^2) geminal . 462 */ 463 struct R1dotR2_G12_Descr : public Contractable<R1dotR2_G12_Descr> { 464 typedef MultiplicativeSymm2Body_Props Properties; 465 static const unsigned int max_key = 1; keyR1dotR2_G12_Descr466 unsigned int key() const { return 0; } descriptionR1dotR2_G12_Descr467 std::string description() const { return "r_1.r_2 x G12"; } labelR1dotR2_G12_Descr468 std::string label() const { return "R1dotR2_G12"; } psymmR1dotR2_G12_Descr469 int psymm(int i, int j) const { abort(); } hermitianR1dotR2_G12_Descr470 int hermitian(int i) const { abort(); } 471 }; 472 typedef GenOper< R1dotR2_G12_Descr > R1dotR2_G12; 473 474 /** \f$ (\nabla_I \cdot g_{12}') (g_{12}' \cdot \nabla_K) \f$ is a component of \f$ [g_{12}, [\nabla_I^4, g_{12}]] \f$ integral 475 where I = 1 or 2. 476 */ 477 struct DivG12prime_xTx_Descr : public Contractable<DivG12prime_xTx_Descr> { 478 typedef NonmultiplicativeNonsymm2Body_Props Properties; 479 static const unsigned int max_key = 2; DivG12prime_xTx_DescrDivG12prime_xTx_Descr480 DivG12prime_xTx_Descr(int I) : I_(I) { assert(I >= 0 && I <= 1); } DivG12prime_xTx_DescrDivG12prime_xTx_Descr481 DivG12prime_xTx_Descr(const DivG12prime_xTx_Descr& a) : Contractable<DivG12prime_xTx_Descr>(a), I_(a.I_) {} keyDivG12prime_xTx_Descr482 unsigned int key() const { return I_; } descriptionDivG12prime_xTx_Descr483 std::string description() const { return label_(I_); } labelDivG12prime_xTx_Descr484 std::string label() const { return symbol_(I_); } IDivG12prime_xTx_Descr485 int I() const { return I_; } psymmDivG12prime_xTx_Descr486 int psymm(int i, int j) const { abort(); } hermitianDivG12prime_xTx_Descr487 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 500