LIBINT 2.9.0
vrr_1_onep_1.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_vrr1onep1_h_
22#define _libint2_src_bin_libint_vrr1onep1_h_
23
24#include <generic_rr.h>
25#include <onep_1_1.h>
26
27#include <cassert>
28
29namespace libint2 {
30
34template <class BFSet, FunctionPosition where>
36 VRR_1_Overlap_1<BFSet, where>, BFSet,
37 GenIntegralSet_1_1<BFSet, OverlapOper, EmptySet> > {
38 public:
44 static const unsigned int max_nchildren = 9;
45
47
49 static bool directional() { return ParentType::default_directional(); }
50
51 private:
53 using ParentType::target_;
54 using ParentType::RecurrenceRelation::expr_;
55 using ParentType::RecurrenceRelation::nflops_;
56
59 VRR_1_Overlap_1(const std::shared_ptr<TargetType>&, unsigned int dir);
60
61 static std::string descr() { return "OSVRROverlap"; }
62};
63
64template <class F, FunctionPosition where>
65VRR_1_Overlap_1<F, where>::VRR_1_Overlap_1(
66 const std::shared_ptr<TargetType>& Tint, unsigned int dir)
67 : ParentType(Tint, dir) {
68 using namespace libint2::algebra;
69 using namespace libint2::prefactor;
70 using namespace libint2::braket;
71 const F& _1 = unit<F>(dir);
72
73 { // can't apply to contracted basis functions
74 F a(Tint->bra(0, 0));
75 F b(Tint->ket(0, 0));
76 if (a.contracted() || b.contracted()) return;
77 }
78
79 // if derivative integrals, there will be extra terms (Eq. (143) in Obara &
80 // Saika JCP 89)
81 const OriginDerivative<3u> dA = Tint->bra(0, 0).deriv();
82 const OriginDerivative<3u> dB = Tint->ket(0, 0).deriv();
83 const bool deriv = !dA.zero() || !dB.zero();
84
85 typedef TargetType ChildType;
87
88 // Build on A or B
89 {
90 // bf quantum on the build center subtracted by 1
91 auto a = (where == InBra ? Tint->bra(0, 0) - _1 : Tint->bra(0, 0));
92 if (!exists(a)) return;
93 auto b = (where == InKet ? Tint->ket(0, 0) - _1 : Tint->ket(0, 0));
94 if (!exists(b)) return;
95
96 auto AB = factory.make_child(a, b);
97 if (is_simple()) {
98 expr_ = Vector(where == InBra ? "PA" : "PB")[dir] * AB;
99 nflops_ += 1;
100 }
101
102 auto am1 = a - _1;
103 auto am1_exists = exists(am1);
104 auto bm1 = b - _1;
105 auto bm1_exists = exists(bm1);
106
107 if (am1_exists) {
108 auto Am1B = factory.make_child(am1, b);
109 if (is_simple()) {
110 expr_ += (Scalar(a[dir]) * Scalar("oo2z")) * Am1B;
111 nflops_ += 3;
112 }
113 }
114 if (bm1_exists) {
115 auto ABm1 = factory.make_child(a, bm1);
116 if (is_simple()) {
117 expr_ += (Scalar(b[dir]) * Scalar("oo2z")) * ABm1;
118 nflops_ += 3;
119 }
120 }
121 }
122
123 // if got here, can decrement by at least 1 quantum
124 // add additional derivative terms
125 if (deriv) {
126 // bf quantum on the build center subtracted by 1
127 F a(where == InBra ? Tint->bra(0, 0) - _1 : Tint->bra(0, 0));
128 F b(where == InKet ? Tint->ket(0, 0) - _1 : Tint->ket(0, 0));
129
130 // treatment of derivative terms differs for shell sets and integrals
131 // since in computing shell sets transfer/build will occur in all 3
132 // directions change in up to all three derivative indices will occur
133 for (unsigned int dxyz = 0; dxyz < 3; ++dxyz) {
134 if (is_simple() && dxyz != dir) // for integrals only consider
135 // derivatives in THE build direction
136 continue;
137
139 _d1.inc(dxyz);
140
141 std::shared_ptr<DGVertex> _nullptr;
142
143 // dA - _1?
144 {
145 const OriginDerivative<3u> dAm1(dA - _d1);
146 if (exists(dAm1)) { // yes
147 a.deriv() = dAm1;
148 auto AB = factory.make_child(a, b);
149 if (is_simple()) {
150 if (where == InBra) { // building on A
151 expr_ -= Vector(dA)[dxyz] * Scalar("rho12_over_alpha1") * AB;
152 nflops_ += 3;
153 }
154 if (where == InKet) { // building on B
155 expr_ += Vector(dA)[dxyz] * Scalar("rho12_over_alpha2") * AB;
156 nflops_ += 3;
157 }
158 }
159 a.deriv() = dA;
160 }
161 }
162
163 // dB - _1?
164 {
165 const OriginDerivative<3u> dBm1(dB - _d1);
166 if (exists(dBm1)) { // yes
167 b.deriv() = dBm1;
168 auto AB = factory.make_child(a, b);
169 if (is_simple()) {
170 if (where == InBra) { // building on A
171 expr_ += Vector(dB)[dxyz] * Scalar("rho12_over_alpha1") * AB;
172 nflops_ += 3;
173 }
174 if (where == InKet) { // building on B
175 expr_ -= Vector(dB)[dxyz] * Scalar("rho12_over_alpha2") * AB;
176 nflops_ += 3;
177 }
178 }
179 b.deriv() = dB;
180 }
181 }
182 }
183 } // end of deriv
184
185 return;
186}
187
191template <CartesianAxis Axis, FunctionPosition where>
194 VRR_1_Overlap_1_1d<Axis, where>, CGF1d<Axis>,
195 GenIntegralSet_1_1<CGF1d<Axis>, OverlapOper, EmptySet> > {
196 public:
204 TargetType>;
205 static const unsigned int max_nchildren = 9;
206 static constexpr auto axis = Axis;
207
209
212
213 private:
215 using ParentType::target_;
216 using ParentType::RecurrenceRelation::expr_;
217 using ParentType::RecurrenceRelation::nflops_;
218
221 VRR_1_Overlap_1_1d(const std::shared_ptr<TargetType>&, unsigned int dir);
222
223 static std::string descr() {
224 return std::string("OSVRROverlap") + to_string(axis);
225 }
226};
227
228template <CartesianAxis Axis, FunctionPosition where>
230 const std::shared_ptr<TargetType>& Tint, unsigned int dir)
231 : ParentType(Tint, dir) {
232 assert(dir == 0); // this integral is along 1 axis only
233
234 using namespace libint2::algebra;
235 using namespace libint2::prefactor;
236 using namespace libint2::braket;
237 typedef CGF1d<Axis> F;
238 const F& _1 = unit<F>(dir);
239
240 { // can't apply to contracted basis functions
241 F a(Tint->bra(0, 0));
242 F b(Tint->ket(0, 0));
243 if (a.contracted() || b.contracted()) return;
244 }
245
246 // if derivative integrals, there will be extra terms (Eq. (143) in Obara &
247 // Saika JCP 89)
248 const OriginDerivative<1u> dA = Tint->bra(0, 0).deriv();
249 const OriginDerivative<1u> dB = Tint->ket(0, 0).deriv();
250 const bool deriv = !dA.zero() || !dB.zero();
251
252 typedef TargetType ChildType;
254
255 // handle the special case of (0|0) integral
256 // to avoid complications with non-precomputed shell blocks it's "computed
257 // by copying from inteval
258 auto zero = Tint->bra(0, 0).zero() and Tint->ket(0, 0).zero() and not deriv;
259 if (zero) {
260 std::shared_ptr<DGVertex> int00 = Vector("_0_Overlap_0")[Axis];
261 expr_ = Scalar(0u) + int00;
262 this->add_child(int00);
263 return;
264 }
265
266 // Build on A or B
267 {
268 // bf quantum on the build center subtracted by 1
269 auto a = (where == InBra ? Tint->bra(0, 0) - _1 : Tint->bra(0, 0));
270 if (!exists(a)) return;
271 auto b = (where == InKet ? Tint->ket(0, 0) - _1 : Tint->ket(0, 0));
272 if (!exists(b)) return;
273
274 auto AB = factory.make_child(a, b);
275 if (is_simple()) {
276 expr_ = Vector(where == InBra ? "PA" : "PB")[Axis] * AB;
277 nflops_ += 1;
278 }
279
280 auto am1 = a - _1;
281 auto am1_exists = exists(am1);
282 auto bm1 = b - _1;
283 auto bm1_exists = exists(bm1);
284
285 if (am1_exists) {
286 auto Am1B = factory.make_child(am1, b);
287 if (is_simple()) {
288 expr_ += (Scalar(a.qn()) * Scalar("oo2z")) * Am1B;
289 nflops_ += 3;
290 }
291 }
292 if (bm1_exists) {
293 auto ABm1 = factory.make_child(a, bm1);
294 if (is_simple()) {
295 expr_ += (Scalar(b.qn()) * Scalar("oo2z")) * ABm1;
296 nflops_ += 3;
297 }
298 }
299 }
300
301 // if got here, can decrement by at least 1 quantum
302 // add additional derivative terms
303 if (deriv) {
304 // bf quantum on the build center subtracted by 1
305 F a(where == InBra ? Tint->bra(0, 0) - _1 : Tint->bra(0, 0));
306 F b(where == InKet ? Tint->ket(0, 0) - _1 : Tint->ket(0, 0));
307
308 {
310 _d1.inc(0);
311
312 std::shared_ptr<DGVertex> _nullptr;
313
314 // dA - _1?
315 {
316 const OriginDerivative<1u> dAm1(dA - _d1);
317 if (exists(dAm1)) { // yes
318 a.deriv() = dAm1;
319 auto AB = factory.make_child(a, b);
320 if (is_simple()) {
321 if (where == InBra) { // building on A
322 expr_ -= Scalar(dA[0]) * Scalar("rho12_over_alpha1") * AB;
323 nflops_ += 3;
324 }
325 if (where == InKet) { // building on B
326 expr_ += Scalar(dA[0]) * Scalar("rho12_over_alpha2") * AB;
327 nflops_ += 3;
328 }
329 }
330 a.deriv() = dA;
331 }
332 }
333
334 // dB - _1?
335 {
336 const OriginDerivative<1u> dBm1(dB - _d1);
337 if (exists(dBm1)) { // yes
338 b.deriv() = dBm1;
339 auto AB = factory.make_child(a, b);
340 if (is_simple()) {
341 if (where == InBra) { // building on A
342 expr_ += Scalar(dB[0]) * Scalar("rho12_over_alpha1") * AB;
343 nflops_ += 3;
344 }
345 if (where == InKet) { // building on B
346 expr_ -= Scalar(dB[0]) * Scalar("rho12_over_alpha2") * AB;
347 nflops_ += 3;
348 }
349 }
350 b.deriv() = dB;
351 }
352 }
353 }
354 } // end of deriv
355
356 return;
357}
358
362template <class BFSet, FunctionPosition where>
364 VRR_1_Kinetic_1<BFSet, where>, BFSet,
365 GenIntegralSet_1_1<BFSet, KineticOper, EmptySet> > {
366 public:
368 typedef BFSet BasisFunctionType;
372 static const unsigned int max_nchildren = 9;
373
375
378
379 private:
381 using ParentType::target_;
382 using ParentType::RecurrenceRelation::expr_;
383 using ParentType::RecurrenceRelation::nflops_;
384
387 VRR_1_Kinetic_1(const std::shared_ptr<TargetType>&, unsigned int dir);
388
389 static std::string descr() { return "OSVRRKinetic"; }
390};
391
392template <class F, FunctionPosition where>
394 const std::shared_ptr<TargetType>& Tint, unsigned int dir)
395 : ParentType(Tint, dir) {
396 using namespace libint2::algebra;
397 using namespace libint2::prefactor;
398 using namespace libint2::braket;
399 const F& _1 = unit<F>(dir);
400
401 { // can't apply to contracted basis functions
402 F a(Tint->bra(0, 0));
403 F b(Tint->ket(0, 0));
404 if (a.contracted() || b.contracted()) return;
405 }
406
407 // if derivative integrals, there will be extra terms (Eq. (143) in Obara &
408 // Saika JCP 89)
409 const OriginDerivative<3u> dA = Tint->bra(0, 0).deriv();
410 const OriginDerivative<3u> dB = Tint->ket(0, 0).deriv();
411 const bool deriv = !dA.zero() || !dB.zero();
412
413 typedef TargetType Child1Type;
416 ChildFactory<ThisType, Child2Type> overlap_factory(this);
417
418 // Build on A or B
419 {
420 // bf quantum on the build center subtracted by 1
421 auto a = (where == InBra ? Tint->bra(0, 0) - _1 : Tint->bra(0, 0));
422 if (!exists(a)) return;
423 auto b = (where == InKet ? Tint->ket(0, 0) - _1 : Tint->ket(0, 0));
424 if (!exists(b)) return;
425
426 auto AB = factory.make_child(a, b);
427 if (is_simple()) {
428 expr_ = Vector(where == InBra ? "PA" : "PB")[dir] * AB;
429 nflops_ += 1;
430 }
431
432 auto am1 = a - _1;
433 if (exists(am1)) {
434 auto Am1B = factory.make_child(am1, b);
435 auto S_Am1B = (where == InBra) ? overlap_factory.make_child(am1, b)
436 : std::shared_ptr<DGVertex>();
437 if (is_simple()) {
438 if (where == InBra) {
439 expr_ += Scalar(a[dir]) * (Scalar("oo2z") * Am1B -
440 Scalar("rho12_over_alpha1") * S_Am1B);
441 nflops_ += 5;
442 } else {
443 expr_ += Scalar(a[dir]) * Scalar("oo2z") * Am1B;
444 nflops_ += 3;
445 }
446 }
447 }
448 auto bm1 = b - _1;
449 if (exists(bm1)) {
450 auto ABm1 = factory.make_child(a, bm1);
451 auto S_ABm1 = (where == InKet) ? overlap_factory.make_child(a, bm1)
452 : std::shared_ptr<DGVertex>();
453 if (is_simple()) {
454 if (where == InKet) {
455 expr_ += Scalar(b[dir]) * (Scalar("oo2z") * ABm1 -
456 Scalar("rho12_over_alpha2") * S_ABm1);
457 nflops_ += 5;
458 } else {
459 expr_ += Scalar(b[dir]) * Scalar("oo2z") * ABm1;
460 nflops_ += 3;
461 }
462 }
463 }
464
465 {
466 auto S_AB_target = where == InBra ? overlap_factory.make_child(a + _1, b)
467 : overlap_factory.make_child(a, b + _1);
468 if (is_simple()) {
469 expr_ += Scalar("two_rho12") * S_AB_target;
470 nflops_ += 2;
471 }
472 }
473 }
474
475 // if got here, can decrement by at least 1 quantum
476 // add additional derivative terms
477 if (deriv) {
478 assert(false); // not yet implemented
479
480 // bf quantum on the build center subtracted by 1
481 F a(where == InBra ? Tint->bra(0, 0) - _1 : Tint->bra(0, 0));
482 F b(where == InKet ? Tint->ket(0, 0) - _1 : Tint->ket(0, 0));
483
484 // treatment of derivative terms differs for shell sets and integrals
485 // since in computing shell sets transfer/build will occur in all 3
486 // directions change in up to all three derivative indices will occur
487 for (unsigned int dxyz = 0; dxyz < 3; ++dxyz) {
488 if (is_simple() && dxyz != dir) // for integrals only consider
489 // derivatives in THE build direction
490 continue;
491
493 _d1.inc(dxyz);
494
495 std::shared_ptr<DGVertex> _nullptr;
496
497 // dA - _1?
498 {
499 const OriginDerivative<3u> dAm1(dA - _d1);
500 if (exists(dAm1)) { // yes
501 a.deriv() = dAm1;
502 auto AB = factory.make_child(a, b);
503 if (is_simple()) {
504 if (where == InBra) { // building on A
505 expr_ -= Vector(dA)[dxyz] * Scalar("rho12_over_alpha1") * AB;
506 nflops_ += 3;
507 }
508 if (where == InKet) { // building on B
509 expr_ += Vector(dA)[dxyz] * Scalar("rho12_over_alpha2") * AB;
510 nflops_ += 3;
511 }
512 }
513 a.deriv() = dA;
514 }
515 }
516
517 // dB - _1?
518 {
519 const OriginDerivative<3u> dBm1(dB - _d1);
520 if (exists(dBm1)) { // yes
521 b.deriv() = dBm1;
522 auto AB = factory.make_child(a, b);
523 if (is_simple()) {
524 if (where == InBra) { // building on A
525 expr_ += Vector(dB)[dxyz] * Scalar("rho12_over_alpha1") * AB;
526 nflops_ += 3;
527 }
528 if (where == InKet) { // building on B
529 expr_ -= Vector(dB)[dxyz] * Scalar("rho12_over_alpha2") * AB;
530 nflops_ += 3;
531 }
532 }
533 b.deriv() = dB;
534 }
535 }
536 }
537 } // end of deriv
538
539 return;
540}
541
545template <class BFSet, FunctionPosition where>
547 VRR_1_ElecPot_1<BFSet, where>, BFSet,
548 GenIntegralSet_1_1<BFSet, ElecPotOper, mType> > {
549 public:
551 typedef BFSet BasisFunctionType;
555 static const unsigned int max_nchildren = 9;
556
558
561
562 private:
564 using ParentType::target_;
565 using ParentType::RecurrenceRelation::expr_;
566 using ParentType::RecurrenceRelation::nflops_;
567
570 VRR_1_ElecPot_1(const std::shared_ptr<TargetType>&, unsigned int dir);
571
572 static std::string descr() { return "OSVRRElecPot"; }
577 std::string generate_label() const override {
578 typedef typename TargetType::AuxIndexType mType;
579 static std::shared_ptr<mType> aux0(new mType(0u));
580 std::ostringstream os;
581 os << descr() << to_string(where)
582 << genintegralset_label(target_->bra(), target_->ket(), aux0,
583 target_->oper());
584 return os.str();
585 }
586};
587
588template <class F, FunctionPosition where>
590 const std::shared_ptr<TargetType>& Tint, unsigned int dir)
591 : ParentType(Tint, dir) {
592 using namespace libint2::algebra;
593 using namespace libint2::prefactor;
594 using namespace libint2::braket;
595 const unsigned int m = Tint->aux()->elem(0);
596 const F& _1 = unit<F>(dir);
597
598 { // can't apply to contracted basis functions
599 F a(Tint->bra(0, 0));
600 F b(Tint->ket(0, 0));
601 if (a.contracted() || b.contracted()) return;
602 }
603
604 // if derivative integrals, there will be extra terms (Eq. (143) in Obara &
605 // Saika JCP 89 1540 (1988))
606 const OriginDerivative<3u> dA = Tint->bra(0, 0).deriv();
607 const OriginDerivative<3u> dB = Tint->ket(0, 0).deriv();
608 const bool deriv = !dA.zero() || !dB.zero();
609
610 typedef TargetType ChildType;
612
613 // Build on A or B
614 {
615 // bf quantum on the build center subtracted by 1
616 auto a = (where == InBra ? Tint->bra(0, 0) - _1 : Tint->bra(0, 0));
617 if (!exists(a)) return;
618 auto b = (where == InKet ? Tint->ket(0, 0) - _1 : Tint->ket(0, 0));
619 if (!exists(b)) return;
620
621 auto AB_m = factory.make_child(a, b, m);
622 auto AB_mp1 = factory.make_child(a, b, m + 1);
623 if (is_simple()) {
624 expr_ = Vector(where == InBra ? "PA" : "PB")[dir] * AB_m -
625 Vector("PC")[dir] * AB_mp1;
626 nflops_ += 3;
627 }
628
629 auto am1 = a - _1;
630 if (exists(am1)) {
631 auto Am1B_m = factory.make_child(am1, b, m);
632 auto Am1B_mp1 = factory.make_child(am1, b, m + 1);
633 if (is_simple()) {
634 expr_ += Scalar(a[dir]) * Scalar("oo2z") * (Am1B_m - Am1B_mp1);
635 nflops_ += 4;
636 }
637 }
638 auto bm1 = b - _1;
639 if (exists(bm1)) {
640 auto ABm1_m = factory.make_child(a, bm1, m);
641 auto ABm1_mp1 = factory.make_child(a, bm1, m + 1);
642 if (is_simple()) {
643 expr_ += Scalar(b[dir]) * Scalar("oo2z") * (ABm1_m - ABm1_mp1);
644 nflops_ += 4;
645 }
646 }
647 }
648
649 // if got here, can decrement by at least 1 quantum
650 // add additional derivative terms
651 if (deriv) {
652 // bf quantum on the build center subtracted by 1
653 F a(where == InBra ? Tint->bra(0, 0) - _1 : Tint->bra(0, 0));
654 F b(where == InKet ? Tint->ket(0, 0) - _1 : Tint->ket(0, 0));
655
656 // treatment of derivative terms differs for shell sets and integrals
657 // since in computing shell sets transfer/build will occur in all 3
658 // directions change in up to all three derivative indices will occur
659 for (unsigned int dxyz = 0; dxyz < 3; ++dxyz) {
660 if (is_simple() && dxyz != dir) // for integrals only consider
661 // derivatives in THE build direction
662 continue;
663
665 _d1.inc(dxyz);
666
667 std::shared_ptr<DGVertex> _nullptr;
668
669 // dA - _1?
670 {
671 const OriginDerivative<3u> dAm1(dA - _d1);
672 if (exists(dAm1)) { // yes
673 a.deriv() = dAm1;
674 auto AB_m = factory.make_child(a, b, m);
675 auto AB_mp1 = factory.make_child(a, b, m + 1);
676 if (is_simple()) {
677 if (where == InBra) { // building on A -> derivative of (PA)_i and
678 // (PC)_i prefactors w.r.t A_i
679 expr_ -=
680 Vector(dA)[dxyz] * (Scalar("rho12_over_alpha1") * AB_m +
681 Scalar("rho12_over_alpha2") * AB_mp1);
682 nflops_ += 5;
683 }
684 if (where == InKet) { // building on B -> derivative of (PB)_i and
685 // (PC)_i prefactors w.r.t A_i
686 expr_ += Vector(dA)[dxyz] * Scalar("rho12_over_alpha2") *
687 (AB_m - AB_mp1);
688 nflops_ += 4;
689 }
690 }
691 a.deriv() = dA;
692 }
693 }
694
695 // dB - _1?
696 {
697 const OriginDerivative<3u> dBm1(dB - _d1);
698 if (exists(dBm1)) { // yes
699 b.deriv() = dBm1;
700 auto AB_m = factory.make_child(a, b, m);
701 auto AB_mp1 = factory.make_child(a, b, m + 1);
702 if (is_simple()) {
703 if (where == InBra) { // building on A -> derivative of (PA)_i and
704 // (PC)_i prefactors w.r.t B_i
705 expr_ += Vector(dB)[dxyz] * Scalar("rho12_over_alpha1") *
706 (AB_m - AB_mp1);
707 nflops_ += 4;
708 }
709 if (where == InKet) { // building on B -> derivative of (PB)_i and
710 // (PC)_i prefactors w.r.t B_i
711 expr_ -=
712 Vector(dB)[dxyz] * (Scalar("rho12_over_alpha2") * AB_m +
713 Scalar("rho12_over_alpha1") * AB_mp1);
714 nflops_ += 5;
715 }
716 }
717 b.deriv() = dB;
718 }
719 }
720 }
721 } // end of deriv
722
723 return;
724}
725
730template <class BFSet, FunctionPosition where>
733 VRR_1_SMultipole_1<BFSet, where>, BFSet,
734 GenIntegralSet_1_1<BFSet, SphericalMultipoleOper, EmptySet> > {
735 public:
737 typedef BFSet BasisFunctionType;
743 static const unsigned int max_nchildren = 8;
744
746
749
750 private:
752 using ParentType::target_;
753 using ParentType::RecurrenceRelation::expr_;
754 using ParentType::RecurrenceRelation::nflops_;
755 using typename ParentType::RecurrenceRelation::ExprType;
756
757 static std::string descr() { return "OSVRRSMultipole"; }
758
761 VRR_1_SMultipole_1(const std::shared_ptr<TargetType>& Tint, unsigned int dir)
762 : ParentType(Tint, dir) {
763 using namespace libint2::algebra;
764 using namespace libint2::prefactor;
765 using namespace libint2::braket;
766 using Sign = SphericalMultipoleQuanta::Sign;
767 using F = BFSet;
768 const F& _1 = unit<F>(dir);
769
770 { // can't apply to contracted basis functions
771 F a(Tint->bra(0, 0));
772 F b(Tint->ket(0, 0));
773 if (a.contracted() || b.contracted()) return;
774 }
775
776 // implementation follows J.M. Pérez-Jordá and W. Yang, J Chem Phys 107,
777 // 1218 (1997). Eqs. (58-61) for gaussian quanta, and J.M. Pérez-Jordá and
778 // W. Yang, J Chem Phys 104, 8003 (1996), Eqs. (23-27) for multipole quanta
779 const OriginDerivative<3u> dA = Tint->bra(0, 0).deriv();
780 const OriginDerivative<3u> dB = Tint->ket(0, 0).deriv();
781 const bool deriv = !dA.zero() || !dB.zero();
782 if (deriv) // derivative relations not yet implemented
783 return;
784
785 auto O_l_m = Tint->oper()->descr();
786 const auto l = O_l_m.l();
787 const auto m = O_l_m.m();
788 const auto sign = O_l_m.sign();
789
790 typedef TargetType ChildType;
792
793 auto make_child =
794 [&](const F& bra, const F& ket,
795 const OperType::Descriptor& descr) -> std::shared_ptr<DGVertex> {
796 return factory.make_child(bra, ket, EmptySet(), descr);
797 };
798
799 // Build on A or B if either bra or ket has quanta, otherwise build
800 // multipole quanta
801 if (Tint->bra(0, 0).norm() != 0 || Tint->ket(0, 0).norm() != 0) {
802 // build A or B
803
804 // bf quantum on the build center subtracted by 1
805 auto a = (where == InBra ? Tint->bra(0, 0) - _1 : Tint->bra(0, 0));
806 if (!exists(a)) return;
807 auto b = (where == InKet ? Tint->ket(0, 0) - _1 : Tint->ket(0, 0));
808 if (!exists(b)) return;
809
810 //
811 // first 2 terms are common to Eqs. (58-60)
812 //
813 auto AB = make_child(a, b, O_l_m);
814 if (is_simple()) {
815 expr_ = Vector(where == InBra ? "PA" : "PB")[dir] * AB;
816 nflops_ += 1;
817 }
818
819 auto am1 = a - _1;
820 auto am1_exists = exists(am1);
821 auto bm1 = b - _1;
822 auto bm1_exists = exists(bm1);
823
824 std::shared_ptr<ExprType> subexpr; // to be multiplied by 1/(2 zeta)
825
826 if (am1_exists) {
827 auto Am1B = make_child(am1, b, O_l_m);
828 if (is_simple()) {
829 subexpr += Scalar(a[dir]) * Am1B;
830 nflops_ += 1;
831 }
832 }
833 if (bm1_exists) {
834 auto ABm1 = make_child(a, bm1, O_l_m);
835 if (is_simple()) {
836 subexpr += Scalar(b[dir]) * ABm1;
837 nflops_ += 1;
838 }
839 }
840
841 // Eq. (58)
842 // (a|N_{l,m}|b) += 0.5 * ((a|N_{l-1,m+1}|b) - (a|N_{l-1,m-1}|b))
843 auto O_lm1_mp1 = SphericalMultipole_Descr(l - 1, m + 1, sign);
844 if (exists(O_lm1_mp1)) {
845 auto AB_O_lm1_mp1 = make_child(a, b, O_lm1_mp1);
846 if (is_simple() && dir == 0) {
847 subexpr += Scalar(O_lm1_mp1.phase() > 0 ? 0.5 : -0.5) * AB_O_lm1_mp1;
848 nflops_ += 1;
849 }
850 }
851
852 auto O_lm1_mm1 = SphericalMultipole_Descr(l - 1, m - 1, sign);
853 if (exists(O_lm1_mm1)) {
854 auto AB_O_lm1_mm1 = make_child(a, b, O_lm1_mm1);
855 if (is_simple() && dir == 0) {
856 subexpr -= Scalar(O_lm1_mm1.phase() > 0 ? 0.5 : -0.5) * AB_O_lm1_mm1;
857 nflops_ += 1;
858 }
859 }
860
861 // Eq. (59)
862 // (a|N^{+-}_{l,m}|b) {+-}= 0.5 * ((a|N^{-+}_{l-1,m+1}|b) +
863 // (a|N^{-+}_{l-1,m-1}|b))
864 const auto m_pfac = sign == Sign::plus ? 1 : -1;
865 auto Om_lm1_mp1 = SphericalMultipole_Descr(l - 1, m + 1, flip(sign));
866 if (exists(Om_lm1_mp1)) {
867 auto AB_Om_lm1_mp1 = make_child(a, b, Om_lm1_mp1);
868 if (is_simple() && dir == 1) {
869 subexpr += Scalar(m_pfac * (Om_lm1_mp1.phase() > 0 ? 0.5 : -0.5)) *
870 AB_Om_lm1_mp1;
871 nflops_ += 1;
872 }
873 }
874
875 auto Om_lm1_mm1 = SphericalMultipole_Descr(l - 1, m - 1, flip(sign));
876 if (exists(Om_lm1_mm1)) {
877 auto AB_Om_lm1_mm1 = make_child(a, b, Om_lm1_mm1);
878 if (is_simple() && dir == 1) {
879 subexpr += Scalar(m_pfac * (Om_lm1_mm1.phase() > 0 ? 0.5 : -0.5)) *
880 AB_Om_lm1_mm1;
881 nflops_ += 1;
882 }
883 }
884
885 // Eq. (60)
886 auto O_lm1_m = SphericalMultipole_Descr(l - 1, m, sign);
887 if (exists(O_lm1_m)) {
888 auto AB_O_lm1_m = make_child(a, b, O_lm1_m);
889 if (is_simple() && dir == 2) {
890 subexpr += AB_O_lm1_m;
891 nflops_ += 1;
892 }
893 }
894
895 if (is_simple()) {
896 if (subexpr) expr_ += Scalar("oo2z") * subexpr;
897 }
898 } else {
899 // build multipole quanta only if dir == 0
900 if (dir != 0) return;
901 auto a = Tint->bra(0, 0);
902 auto b = Tint->ket(0, 0);
903
904 if (l == m) {
905 if (l == 0) { // Eq.
906 assert(sign == Sign::plus); // Eq. (24) should not be needed
907 // since N^-_{0,0} should just be
908 // omitted above
910 EmptySet>
911 OverlapType;
912 ChildFactory<ThisType, OverlapType> overlap_factory(this);
913 auto S00 = overlap_factory.make_child(a, b);
914 if (is_simple()) {
915 expr_ = Scalar(1) * S00; // Eq. (25) and Eq. (61)
916 }
917 } else {
918 std::shared_ptr<ExprType> subexpr; // to be multiplied by - 1/(2 m)
919
920 // Eqs. (25-26)
921 // (0|N^+_{m,m}|0) = -(1/(2m)) ( x (0|N^+_{m-1,m-1}|0) - y
922 // (0|N^-_{m-1,m-1}|0) )
923 auto Op_lm1_mm1 = SphericalMultipole_Descr(l - 1, m - 1, Sign::plus);
924 auto AB_Op_lm1_mm1 = make_child(a, b, Op_lm1_mm1);
925 if (is_simple()) {
926 subexpr =
927 Scalar(sign == Sign::plus ? "PO_x" : "PO_y") * AB_Op_lm1_mm1;
928 }
929 auto Om_lm1_mm1 = SphericalMultipole_Descr(l - 1, m - 1, Sign::minus);
930 if (exists(Om_lm1_mm1)) {
931 auto AB_Om_lm1_mm1 = make_child(a, b, Om_lm1_mm1);
932 if (is_simple()) {
933 if (sign == Sign::plus)
934 subexpr -= Scalar("PO_y") * AB_Om_lm1_mm1;
935 else // sign == Sign::minus
936 subexpr += Scalar("PO_x") * AB_Om_lm1_mm1;
937 }
938 }
939 if (is_simple()) {
940 assert(subexpr);
941 expr_ = Scalar(-0.5 / m) * subexpr;
942 }
943 }
944 } else { // l != m, use Eq. 27
945 std::shared_ptr<ExprType>
946 subexpr; // to be multiplied by 1/((l+m)(l-m))
947
948 auto O_lm1_m = SphericalMultipole_Descr(l - 1, m, sign);
949 if (exists(O_lm1_m)) {
950 auto AB_O_lm1_m = make_child(a, b, O_lm1_m);
951 if (is_simple())
952 subexpr = Scalar((2 * l - 1)) * Scalar("PO_z") * AB_O_lm1_m;
953 }
954
955 auto O_lm2_m = SphericalMultipole_Descr(l - 2, m, sign);
956 if (exists(O_lm2_m)) {
957 auto AB_O_lm2_m = make_child(a, b, O_lm2_m);
958 if (is_simple()) subexpr -= Scalar("PO2") * AB_O_lm2_m;
959 }
960
961 if (is_simple()) {
962 assert(subexpr);
963 expr_ = Scalar(1.0 / ((l + m) * (l - m))) * subexpr;
964 }
965 }
966 }
967
968 return;
969 }
970
971}; // VRR_1_SMultipole_1
972
973}; // namespace libint2
974
975#endif
Set of basis functions.
Definition bfset.h:43
Cartesian components of 3D CGF = 1D CGF.
Definition bfset.h:457
Helps GenericRecurrenceRelation to work around the compiler problem with make_child.
Definition generic_rr.h:150
Generic integral over a one-body operator with one bfs for each particle in bra and ket.
Definition integral_1_1.h:36
GenOper is a single operator described by descriptor Descr.
Definition oper.h:164
RRImpl must inherit GenericRecurrenceRelation<RRImpl>
Definition generic_rr.h:47
const std::shared_ptr< DGVertex > & make_child(const typename RealChildType::BasisFunctionType &A, const typename RealChildType::BasisFunctionType &B, const typename RealChildType::BasisFunctionType &C, const typename RealChildType::BasisFunctionType &D, const typename RealChildType::AuxIndexType &aux=typename RealChildType::AuxIndexType(), const typename RealChildType::OperType &oper=typename RealChildType::OperType())
make_child should really looks something like this, but gcc 4.3.0 craps out TODO test is this works
Definition generic_rr.h:129
bool is_simple() const override
Implementation of RecurrenceRelation::is_simple()
Definition generic_rr.h:81
const std::shared_ptr< DGVertex > & add_child(const std::shared_ptr< DGVertex > &child)
add child
Definition generic_rr.h:109
static bool default_directional()
is this recurrence relation parameterized by a direction (x, y, or z).
Definition generic_rr.h:101
static std::shared_ptr< RRImpl > Instance(const std::shared_ptr< TargetType > &Tint, unsigned int dir)
Return an instance if applicable, or a null pointer otherwise.
Definition generic_rr.h:55
Represents cartesian derivatives of atom-centered basis functions.
Definition bfset.h:101
bool zero() const
norm() == 0
Definition bfset.h:158
void inc(unsigned int xyz, unsigned int c=1u)
Add c quanta along xyz.
Definition bfset.h:140
QuantumNumbersA<T,N> is a set of N quantum numbers of type T implemented in terms of a C-style array.
Definition quanta.h:193
VRR Recurrence Relation for 1-e electrostatic potential integrals.
Definition vrr_1_onep_1.h:548
static bool directional()
Default directionality.
Definition vrr_1_onep_1.h:560
VRR Recurrence Relation for 1-e kinetic energy integrals.
Definition vrr_1_onep_1.h:365
static bool directional()
Default directionality.
Definition vrr_1_onep_1.h:377
VRR Recurrence Relation for 1-d overlap integrals.
Definition vrr_1_onep_1.h:195
static bool directional()
Default directionality.
Definition vrr_1_onep_1.h:211
VRR Recurrence Relation for 1-e overlap integrals.
Definition vrr_1_onep_1.h:37
static bool directional()
Default directionality.
Definition vrr_1_onep_1.h:49
VRR Recurrence Relation for 1-e spherical multipole moment aka regular solid harmonics integrals.
Definition vrr_1_onep_1.h:734
static bool directional()
Default directionality.
Definition vrr_1_onep_1.h:748
these objects help to construct BraketPairs
Definition src/bin/libint/braket.h:275
Defaults definitions for various parameters assumed by Libint.
Definition algebra.cc:24
bool exists(const IncableBFSet &A)
Return true if A is valid.
Definition bfset.h:96
DefaultQuantumNumbers< unsignedint, 1 >::Result mType
mType is the type that describes the auxiliary index of standard 2-body repulsion integrals
Definition quanta.h:395
std::string to_string(const T &x)
Converts x to its string representation.
Definition entity.h:121
DefaultQuantumNumbers< int, 0 >::Result EmptySet
EmptySet is the type that describes null set of auxiliary indices.
Definition quanta.h:390
SphericalMultipoleQuanta::Sign flip(const SphericalMultipoleQuanta::Sign &s)
plus <-> minus
Definition multipole.h:271
Represents quantum numbers of real spherical multipole operator defined in Eqs.
Definition oper.h:362