MPQC 3.0.0-alpha
Loading...
Searching...
No Matches
tbosar.h
1//
2// tbosar.h
3//
4// Copyright (C) 2001 Edward Valeev
5//
6// Author: Edward Valeev <evaleev@vt.edu>
7// Maintainer: EV
8//
9// This file is part of the SC Toolkit.
10//
11// The SC Toolkit is free software; you can redistribute it and/or modify
12// it under the terms of the GNU Library General Public License as published by
13// the Free Software Foundation; either version 2, or (at your option)
14// any later version.
15//
16// The SC Toolkit is distributed in the hope that it will be useful,
17// but WITHOUT ANY WARRANTY; without even the implied warranty of
18// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19// GNU Library General Public License for more details.
20//
21// You should have received a copy of the GNU Library General Public License
22// along with the SC Toolkit; see the file COPYING.LIB. If not, write to
23// the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
24//
25// The U.S. Government is granted a limited license as per AL 91-7.
26//
27
28#include <limits.h>
29#include <stdexcept>
30
31#include <util/ref/ref.h>
32#include <util/misc/scexception.h>
33#include <util/misc/consumableresources.h>
34#include <chemistry/qc/basis/basis.h>
35#include <chemistry/qc/libint2/shellpairs.h>
36#include <chemistry/qc/basis/fjt.h>
37#include <chemistry/qc/libint2/int2e.h>
38#include <chemistry/qc/libint2/macros.h>
39#include <chemistry/qc/libint2/libint2_utils.h>
40#include <libint2.h>
41#include <libint2/boys.h>
42#include <chemistry/qc/libint2/core_ints_engine.h>
43
44#if LIBINT2_SUPPORT_ERI
45
46#ifndef _chemistry_qc_libint2_tbosar_h
47#define _chemistry_qc_libint2_tbosar_h
48
49namespace sc {
50
51 namespace detail {
52 template <TwoBodyOper::type OperType>
53 struct OSAR_CoreInts;
54
55 template <>
56 struct OSAR_CoreInts<TwoBodyOper::eri> {
57
58 //typedef FJT _FmEvalType; // Curt's Taylor code
59 typedef ::libint2::FmEval_Chebyshev7<double> _FmEvalType; // vectorized high-order interpolation
60 typedef CoreIntsEngine<_FmEvalType>::Engine FmEvalType;
61 Ref<FmEvalType> Fm_Eval_;
62
63 OSAR_CoreInts(unsigned int mmax, const Ref<IntParams>& params) :
64 Fm_Eval_(CoreIntsEngine<_FmEvalType>::instance(mmax)) {
65 }
66
67 const double* eval(double* Fm_table, unsigned int mmax, double T, double rho = 0.0,
68 void* /* thread_local_scratch */ = 0) const {
69 static double oo2np1[] = {1.0, 1.0/3.0, 1.0/5.0, 1.0/7.0, 1.0/9.0,
70 1.0/11.0, 1.0/13.0, 1.0/15.0, 1.0/17.0, 1.0/19.0,
71 1.0/21.0, 1.0/23.0, 1.0/25.0, 1.0/27.0, 1.0/29.0,
72 1.0/31.0, 1.0/33.0, 1.0/35.0, 1.0/37.0, 1.0/39.0,
73 1.0/41.0, 1.0/43.0, 1.0/45.0, 1.0/47.0, 1.0/49.0,
74 1.0/51.0, 1.0/53.0, 1.0/55.0, 1.0/57.0, 1.0/59.0,
75 1.0/61.0, 1.0/63.0, 1.0/65.0, 1.0/67.0, 1.0/69.0,
76 1.0/71.0, 1.0/73.0, 1.0/75.0, 1.0/77.0, 1.0/79.0};
77
78 const static double small_T = 1E-15; /*--- Use only one term in Taylor expansion of Fj(T) if T < small_T ---*/
79 if(T < small_T){
80 return oo2np1;
81 }
82 else {
83 // Cheb3
84 Fm_Eval_->eval(Fm_table, T, mmax);
85 return Fm_table;
86 // old Taylor
87 //return Fm_Eval_->values(mmax, T);
88 }
89 }
90 };
91
92 namespace {
93 // this does common work for geminal-depenent kernels
94 struct OSAR_CoreInts_G12Base {
95 IntParamsG12::ContractedGeminal g12_;
96
97 OSAR_CoreInts_G12Base(const Ref<IntParams>& p) {
98
99 Ref<IntParamsG12> params = require_dynamic_cast<IntParamsG12*>(p, "");
100
101 const bool braonly = (params->ket() == IntParamsG12::null_geminal);
102 g12_ = braonly ? params->bra() : IntParamsG12::product(params->bra(), params->ket());
103 }
104
105 struct softcomparer {
106 softcomparer(double tol = DBL_EPSILON) : tol_(tol) {}
107 bool operator()(double a, double b) const { return a + tol_ < b; }
108 double tol_;
109 };
110
111 // reduce terms with common exponents
112 static IntParamsG12::ContractedGeminal
113 reduce(const IntParamsG12::ContractedGeminal& g12) {
114 softcomparer comp;
115 std::map<double, double, softcomparer> g12red(comp);
116 typedef std::map<double, double, softcomparer>::iterator iter;
117
118 const size_t np = g12.size();
119 for(size_t p=0; p<np; ++p) {
120 iter i = g12red.find(g12[p].first);
121 if (i != g12red.end()) {
122 i->second += g12[p].second;
123 }
124 else
125 g12red[g12[p].first] = g12[p].second;
126 }
127
128 IntParamsG12::ContractedGeminal result;
129 for(iter i=g12red.begin();
130 i != g12red.end();
131 ++i) {
132 result.push_back(*i);
133 }
134
135 return result;
136 }
137 };
138 } // namespace <anonymous>
139
140 template <>
141 struct OSAR_CoreInts<TwoBodyOper::r12_0_g12> : OSAR_CoreInts_G12Base {
142 typedef ::libint2::GaussianGmEval<double, 0> _GmEvalType;
143 typedef CoreIntsEngine<_GmEvalType>::Engine GmEvalType;
144 Ref<GmEvalType> Gm_Eval_;
145
146 OSAR_CoreInts(unsigned int mmax, const Ref<IntParams>& params) :
147 OSAR_CoreInts_G12Base(params), Gm_Eval_(CoreIntsEngine<_GmEvalType>::instance(mmax, 1e-14))
148 {
149 g12_ = reduce(g12_);
150 }
151 double* eval(double* Gm_table, unsigned int mmax, double T, double rho = 0.0,
152 void* /* thread_local_scratch */ = 0) {
153 Gm_Eval_->eval(Gm_table, rho, T, mmax, g12_);
154 return Gm_table;
155 }
156 };
157 template <>
158 struct OSAR_CoreInts<TwoBodyOper::r12_m1_g12> : OSAR_CoreInts_G12Base {
159 typedef ::libint2::GaussianGmEval<double, -1> _GmEvalType;
160 typedef CoreIntsEngine<_GmEvalType>::Engine GmEvalType;
161 Ref<GmEvalType> Gm_Eval_;
162
163 OSAR_CoreInts(unsigned int mmax, const Ref<IntParams>& params) :
164 OSAR_CoreInts_G12Base(params), Gm_Eval_(CoreIntsEngine<_GmEvalType>::instance(mmax, 1e-14))
165 {
166 g12_ = reduce(g12_);
167 }
168 double* eval(double* Gm_table, unsigned int mmax, double T, double rho = 0.0,
169 void* thread_local_scratch = 0) {
170 Gm_Eval_->eval(Gm_table, rho, T, mmax, g12_, thread_local_scratch);
171 return Gm_table;
172 }
173 };
174
175 template <>
176 struct OSAR_CoreInts<TwoBodyOper::g12t1g12> : OSAR_CoreInts_G12Base {
177 typedef ::libint2::GaussianGmEval<double, 2> _GmEvalType;
178 typedef CoreIntsEngine<_GmEvalType>::Engine GmEvalType;
179 Ref<GmEvalType> Gm_Eval_;
180
181 OSAR_CoreInts(unsigned int mmax, const Ref<IntParams>& params) :
182 OSAR_CoreInts_G12Base(params), Gm_Eval_(CoreIntsEngine<_GmEvalType>::instance(mmax, 1e-14))
183 {
184 // [exp(-a r_{12}^2),[T1,exp(-b r_{12}^2)]] = 4 a b (r_{12}^2 exp(- (a+b) r_{12}^2) )
185 // i.e. need to scale each coefficient by 4 a b
186 Ref<IntParamsG12> p = require_dynamic_cast<IntParamsG12*>(params, "");
187 const IntParamsG12::ContractedGeminal& gbra = p->bra();
188 const IntParamsG12::ContractedGeminal& gket = p->ket();
189 for(size_t b=0, bk=0; b<gbra.size(); ++b)
190 for(size_t k=0; k<gket.size(); ++k, ++bk)
191 g12_[bk].second *= 4.0 * gbra[b].first * gket[k].first;
192 g12_ = reduce(g12_);
193 }
194 double* eval(double* Gm_table, unsigned int mmax, double T, double rho = 0.0,
195 void* /* thread_local_scratch */ = 0) {
196 Gm_Eval_->eval(Gm_table, rho, T, mmax, g12_);
197 return Gm_table;
198 }
199 };
200
201 template <>
202 struct OSAR_CoreInts<TwoBodyOper::delta> {
203 OSAR_CoreInts(unsigned int mmax, const Ref<IntParams>& params) {}
204 const double* eval(double* Fm_table, unsigned int mmax, double T, double rho = 0.0,
205 void* /* thread_local_scratch */ = 0) const {
206 const static double one_over_two_pi = 1.0 / (2.0 * M_PI);
207 const double G0 = exp(-T) * rho * one_over_two_pi;
208 //const double G0 = 0.5 * sqrt(M_PI / rho); // <- 1 (=> product of 1-e overlaps), instead of delta function
209 std::fill(Fm_table, Fm_table+mmax+1, G0);
210 return Fm_table;
211 }
212 };
213 }
214
215 namespace {
216
217 inline void
218 swtch(GaussianBasisSet* &i,GaussianBasisSet* &j)
219 {
220 GaussianBasisSet *tmp;
221 tmp = i;
222 i = j;
223 j = tmp;
224 }
225
226 inline void
227 pswtch(void**i,void**j)
228 {
229 void*tmp;
230 tmp = *i;
231 *i = *j;
232 *j = tmp;
233 }
234
235 inline void
236 iswtch(int *i,int *j)
237 {
238 int tmp;
239 tmp = *i;
240 *i = *j;
241 *j = tmp;
242 }
243
244 }; // end of namespace <anonymous>
245
247template <TwoBodyOper::type OperType>
248class TwoBodyOSARLibint2: public Int2eLibint2 {
249 private:
250
251 static bool store_pair_data() { return true; } // hardwired for now
252
253 // Storage for target integrals
254 double *target_ints_buffer_;
255
256 /*--- Intermediate scratch arrays (may be used in new[] and delete[]) ---*/
257 double *cart_ints_; // cartesian integrals, in by-contraction-quartet order
258 double *sphharm_ints_; // transformed integrals, in by-contraction-quartet order
259 double *perm_ints_; // redundant target integrals in shell quartet order, shells permuted
260
261 /*--- Pointers to scratch arrays (never used in new[] and delete[]) ---*/
262 double *prim_ints_; // this points to the appropriate location for raw integrals
263 double *contr_quartets_;
264 double *shell_quartet_;
265
266 /*--- Precomputed data ---*/
267 Ref<ShellPairsLibint2> shell_pairs12_;
268 Ref<ShellPairsLibint2> shell_pairs34_;
269
270 /*--- Internally used "interfaces" ---*/
271 struct {
272 int p12, p34, p13p24; // flags indicating if functions were permuted
273 ShellPairLibint2 *shell_pair12, *shell_pair34; // Shell pairs corresponding to the original
274 // (before permutation) order of shell
275 int *op1, *op2, *op3, *op4; // pointers to the primitive indices in the original order
277 double A[3], B[3], C[3], D[3];
278 double AB2, CD2;
279 int gc1, gc2, gc3, gc4;
280 int p1, p2, p3, p4;
281 int am;
282 } quartet_info_;
283 typedef Libint_t prim_data;
284 // returns 0 if primitive quartet is negligible, 1 otherwise
285 size_t quartet_data_(prim_data *Data, double scale);
286 /*--- Compute engines ---*/
287 std::vector<Libint_t> Libint_;
288 detail::OSAR_CoreInts<OperType> coreints_;
289 // r12_m1_g12 requires per-thread local storage
290 // negligible overhead for other types
291 libint2::detail::CoreEvalScratch<libint2::GaussianGmEval<double, -1>> coreints_scratch_;
292
293 public:
294 TwoBodyOSARLibint2(Integral *,
295 const Ref<GaussianBasisSet>&,
296 const Ref<GaussianBasisSet>&,
297 const Ref<GaussianBasisSet>&,
298 const Ref<GaussianBasisSet>&,
299 size_t storage,
300 const Ref<IntParams>& oper_params);
301 ~TwoBodyOSARLibint2();
302
303 // reimplements Int2eLibint2::clone()
304 Ref<Int2eLibint2> clone();
305
306 double *buffer(unsigned int t = 0) const {
307 return target_ints_buffer_;
308 }
309
310 static size_t storage_required(const Ref<GaussianBasisSet>& b1,
311 const Ref<GaussianBasisSet>& b2 = 0,
312 const Ref<GaussianBasisSet>& b3 = 0,
313 const Ref<GaussianBasisSet>& b4 = 0);
314
315 // evaluate integrals
316 void compute_quartet(int*, int*, int*, int*);
317
318 private:
320
322 TwoBodyOSARLibint2(const TwoBodyOSARLibint2& other);
323
324};
325
326template <TwoBodyOper::type OperType>
327TwoBodyOSARLibint2<OperType>::TwoBodyOSARLibint2(Integral *integral,
328 const Ref<GaussianBasisSet>& b1,
329 const Ref<GaussianBasisSet>& b2,
330 const Ref<GaussianBasisSet>& b3,
331 const Ref<GaussianBasisSet>& b4,
332 size_t storage,
333 const Ref<IntParams>& oper_params) :
334 Int2eLibint2(integral,b1,b2,b3,b4,storage),
335 coreints_(b1->max_angular_momentum() +
336 b2->max_angular_momentum() +
337 b3->max_angular_momentum() +
338 b4->max_angular_momentum(),
339 oper_params)
340{
341 // The static part of Libint's interface is automatically initialized in libint.cc
342 const int l1 = bs1_->max_angular_momentum();
343 const int l2 = bs2_->max_angular_momentum();
344 const int l3 = bs3_->max_angular_momentum();
345 const int l4 = bs4_->max_angular_momentum();
346 const int lmax = std::max(std::max(l1,l2),std::max(l3,l4));
347 if (lmax > LIBINT2_MAX_AM_eri) {
348 throw LimitExceeded<int>("TwoBodyOSARLibint2::TwoBodyOSARLibint2() -- maxam of the basis is too high,\
349 not supported by this libint2 library. Recompile libint2.",__FILE__,__LINE__,LIBINT2_MAX_AM_eri,lmax);
350 }
351
352 /*--- Initialize storage ---*/
353 const int max_num_prim_comb = bs1_->max_nprimitive_in_shell()*
354 bs2_->max_nprimitive_in_shell()*
355 bs3_->max_nprimitive_in_shell()*
356 bs4_->max_nprimitive_in_shell();
357 // need one Libint_t object for each primitive combination
358 // if Libint2 does not support contractions, just allocate 1
359#if LIBINT2_CONTRACTED_INTS
360 Libint_.resize(max_num_prim_comb);
361#else
362 Libint_.resize(1);
363#endif
364 ConsumableResources::get_default_instance()->consume_memory(Libint_.size() * sizeof(Libint_[0]));
365
366 const int max_cart_target_size = bs1_->max_ncartesian_in_shell()*bs2_->max_ncartesian_in_shell()*
367 bs3_->max_ncartesian_in_shell()*bs4_->max_ncartesian_in_shell();
368 const int max_target_size = bs1_->max_nfunction_in_shell()*bs2_->max_nfunction_in_shell()*
369 bs3_->max_nfunction_in_shell()*bs4_->max_nfunction_in_shell();
370
371 size_t storage_needed = LIBINT2_PREFIXED_NAME(libint2_need_memory_eri)(lmax) * sizeof(LIBINT2_REALTYPE);
372 LIBINT2_PREFIXED_NAME(libint2_init_eri)(&Libint_[0],lmax,0); // only need to initialize stack of the first Libint_t object
373 manage_array(Libint_[0].stack, storage_needed/sizeof(LIBINT2_REALTYPE));
374
375 target_ints_buffer_ = allocate<double>(max_target_size);
376 cart_ints_ = allocate<double>(max_cart_target_size);
377 if (bs1_->has_pure() || bs2_->has_pure() || bs3_->has_pure() || bs4_->has_pure() ||
378 bs1_->max_ncontraction() != 1 || bs2_->max_ncontraction() != 1 ||
379 bs3_->max_ncontraction() != 1 || bs4_->max_ncontraction() != 1) {
380 sphharm_ints_ = allocate<double>(max_target_size);
381 storage_needed += max_target_size*sizeof(double);
382 }
383 else {
384 sphharm_ints_ = 0;
385 }
386 if (l1 || l2 || l3 || l4) {
387 perm_ints_ = allocate<double>(max_target_size);
388 storage_needed += max_target_size*sizeof(double);
389 }
390 else
391 perm_ints_ = 0;
392
393 // See if can store primitive-pair data
394 size_t primitive_pair_storage_estimate = (bs1_->nprimitive()*(size_t)bs2_->nprimitive() +
395 bs3_->nprimitive()*(size_t)bs4_->nprimitive())*sizeof(prim_pair_t);
396 // ExEnv::errn() << scprintf("need %d bytes to store primitive pair data\n",primitive_pair_storage_estimate);
397
398 MPQC_ASSERT(store_pair_data());
399 {
400 shell_pairs12_ = new ShellPairsLibint2(bs1_,bs2_);
401 if ( (bs1_ == bs3_ && bs2_ == bs4_) /*||
402 // if this is (ab|ba) case -- should i try to save storage?
403 (bs1_ == bs4_ && bs2_ == bs3_)*/ )
404 shell_pairs34_ = new ShellPairsLibint2(*shell_pairs12_);
405 else
406 shell_pairs34_ = new ShellPairsLibint2(bs3_,bs4_);
407 storage_needed += primitive_pair_storage_estimate;
408 }
409
410 if (OperType == TwoBodyOper::r12_m1_g12)
411 coreints_scratch_ = libint2::detail::CoreEvalScratch<libint2::GaussianGmEval<double, -1>>(l1+l2+l3+l4);
412
413 storage_used_ = storage_needed;
414 // Check if storage_ > storage_needed
415 check_storage_();
416}
417
418template <TwoBodyOper::type OperType>
419TwoBodyOSARLibint2<OperType>::~TwoBodyOSARLibint2()
420{
421 unmanage_array(Libint_[0].stack);
422 LIBINT2_PREFIXED_NAME(libint2_cleanup_eri)(&Libint_[0]);
423 Libint_[0].stack = 0;
424 ConsumableResources::get_default_instance()->release_memory(Libint_.size() * sizeof(Libint_[0]));
425 deallocate(target_ints_buffer_);
426 deallocate(cart_ints_);
427 if (sphharm_ints_)
428 deallocate(sphharm_ints_);
429 if (perm_ints_)
430 deallocate(perm_ints_);
431#ifdef DMALLOC
432 dmalloc_shutdown();
433#endif
434}
435
436template <TwoBodyOper::type OperType>
437TwoBodyOSARLibint2<OperType>::TwoBodyOSARLibint2(const TwoBodyOSARLibint2& other) :
438 Int2eLibint2(other),
439 shell_pairs12_(new ShellPairsLibint2(*other.shell_pairs12_)),
440 shell_pairs34_(new ShellPairsLibint2(*other.shell_pairs34_)),
441 coreints_(other.coreints_)
442{
443 // The static part of Libint's interface is automatically initialized in libint.cc
444 const int l1 = bs1_->max_angular_momentum();
445 const int l2 = bs2_->max_angular_momentum();
446 const int l3 = bs3_->max_angular_momentum();
447 const int l4 = bs4_->max_angular_momentum();
448 const int lmax = std::max(std::max(l1,l2),std::max(l3,l4));
449
450 /*--- Initialize storage ---*/
451 const int max_num_prim_comb = bs1_->max_nprimitive_in_shell()*
452 bs2_->max_nprimitive_in_shell()*
453 bs3_->max_nprimitive_in_shell()*
454 bs4_->max_nprimitive_in_shell();
455 // need one Libint_t object for each primitive combination
456 // if Libint2 does not support contractions, just allocate 1
457#if LIBINT2_CONTRACTED_INTS
458 Libint_.resize(max_num_prim_comb);
459#else
460 Libint_.resize(1);
461#endif
462 ConsumableResources::get_default_instance()->consume_memory(Libint_.size() * sizeof(Libint_[0]));
463
464 const int max_cart_target_size = bs1_->max_ncartesian_in_shell()*bs2_->max_ncartesian_in_shell()*
465 bs3_->max_ncartesian_in_shell()*bs4_->max_ncartesian_in_shell();
466 const int max_target_size = bs1_->max_nfunction_in_shell()*bs2_->max_nfunction_in_shell()*
467 bs3_->max_nfunction_in_shell()*bs4_->max_nfunction_in_shell();
468
469 size_t storage_needed = LIBINT2_PREFIXED_NAME(libint2_need_memory_eri)(lmax) * sizeof(LIBINT2_REALTYPE);
470 LIBINT2_PREFIXED_NAME(libint2_init_eri)(&Libint_[0],lmax,0); // only need to initialize stack of the first Libint_t object
471 manage_array(Libint_[0].stack, storage_needed/sizeof(LIBINT2_REALTYPE));
472
473 target_ints_buffer_ = allocate<double>(max_target_size);
474 cart_ints_ = allocate<double>(max_cart_target_size);
475 if (bs1_->has_pure() || bs2_->has_pure() || bs3_->has_pure() || bs4_->has_pure() ||
476 bs1_->max_ncontraction() != 1 || bs2_->max_ncontraction() != 1 ||
477 bs3_->max_ncontraction() != 1 || bs4_->max_ncontraction() != 1) {
478 sphharm_ints_ = allocate<double>(max_target_size);
479 storage_needed += max_target_size*sizeof(double);
480 }
481 else {
482 sphharm_ints_ = 0;
483 }
484 if (l1 || l2 || l3 || l4) {
485 perm_ints_ = allocate<double>(max_target_size);
486 storage_needed += max_target_size*sizeof(double);
487 }
488 else
489 perm_ints_ = 0;
490
491 if (OperType == TwoBodyOper::r12_m1_g12)
492 coreints_scratch_ = libint2::detail::CoreEvalScratch<libint2::GaussianGmEval<double, -1>>(l1+l2+l3+l4);
493
494 storage_used_ = storage_needed;
495 // Check if storage_ > storage_needed
496 check_storage_();
497}
498
499template <TwoBodyOper::type OperType>
500Ref<Int2eLibint2>
501TwoBodyOSARLibint2<OperType>::clone() {
502 return new TwoBodyOSARLibint2<OperType>(*this);
503}
504
505template <TwoBodyOper::type OperType>
506size_t
507TwoBodyOSARLibint2<OperType>::storage_required(const Ref<GaussianBasisSet>& b1,
508 const Ref<GaussianBasisSet>& b2,
509 const Ref<GaussianBasisSet>& b3,
510 const Ref<GaussianBasisSet>& b4)
511{
512 Ref<GaussianBasisSet> bs1 = b1;
513 Ref<GaussianBasisSet> bs2 = b2;
514 Ref<GaussianBasisSet> bs3 = b3;
515 Ref<GaussianBasisSet> bs4 = b4;
516
517 if (bs2.null())
518 bs2 = bs1;
519 if (bs3.null())
520 bs3 = bs1;
521 if (bs4.null())
522 bs4 = bs1;
523
524 int l1 = bs1->max_angular_momentum();
525 int l2 = bs2->max_angular_momentum();
526 int l3 = bs3->max_angular_momentum();
527 int l4 = bs4->max_angular_momentum();
528 int lmax = std::max(std::max(l1,l2),std::max(l3,l4));
529
530 size_t storage_required = storage_required_(bs1,bs2,bs3,bs4);
531
532 const int max_num_prim_comb = bs1->max_nprimitive_in_shell()*
533 bs2->max_nprimitive_in_shell()*
534 bs3->max_nprimitive_in_shell()*
535 bs4->max_nprimitive_in_shell();
536#if LIBINT2_CONTRACTED_INTS
537 storage_required += max_num_prim_comb * sizeof(Libint_t);
538#else
539 storage_required += sizeof(Libint_t);
540#endif
541
542 const int max_cart_target_size = bs1->max_ncartesian_in_shell()*bs2->max_ncartesian_in_shell()*
543 bs3->max_ncartesian_in_shell()*bs4->max_ncartesian_in_shell();
544 const int max_target_size = bs1->max_nfunction_in_shell()*bs2->max_nfunction_in_shell()*
545 bs3->max_nfunction_in_shell()*bs4->max_nfunction_in_shell();
546
547 storage_required += LIBINT2_PREFIXED_NAME(libint2_need_memory_eri)(lmax) * sizeof(LIBINT2_REALTYPE);
548
549 if (bs1->has_pure() || bs2->has_pure() || bs3->has_pure() || bs4->has_pure() ||
550 bs1->max_ncontraction() != 1 || bs2->max_ncontraction() != 1 ||
551 bs3->max_ncontraction() != 1 || bs4->max_ncontraction() != 1) {
552 storage_required += max_target_size*sizeof(double);
553 }
554
555 if (l1 || l2 || l3 || l4) {
556 storage_required += max_target_size*sizeof(double);
557 }
558
559 // See if can store primitive-pair data
560 size_t primitive_pair_storage_estimate = (bs1->nprimitive()*bs2->nprimitive() +
561 bs3->nprimitive()*bs4->nprimitive())*sizeof(prim_pair_t);
562#if STORE_PAIR_DATA
563 storage_required += primitive_pair_storage_estimate;
564#endif
565
566 return storage_required;
567}
568
569template <TwoBodyOper::type OperType>
570size_t
571TwoBodyOSARLibint2<OperType>::quartet_data_(prim_data *Data, double scale)
572{
573
574 prim_pair_t* pair12;
575 prim_pair_t* pair34;
576 if (!quartet_info_.p13p24) {
577 pair12 = quartet_info_.shell_pair12->prim_pair(*quartet_info_.op1,*quartet_info_.op2);
578 pair34 = quartet_info_.shell_pair34->prim_pair(*quartet_info_.op3,*quartet_info_.op4);
579 }
580 else {
581 pair12 = quartet_info_.shell_pair34->prim_pair(*quartet_info_.op3,*quartet_info_.op4);
582 pair34 = quartet_info_.shell_pair12->prim_pair(*quartet_info_.op1,*quartet_info_.op2);
583 }
584
585 const int p1 = quartet_info_.p1;
586 const int p2 = quartet_info_.p2;
587 const int p3 = quartet_info_.p3;
588 const int p4 = quartet_info_.p4;
589
590 const double pfac_norm = int_shell1_->coefficient_unnorm(quartet_info_.gc1,p1)*
591 int_shell2_->coefficient_unnorm(quartet_info_.gc2,p2)*
592 int_shell3_->coefficient_unnorm(quartet_info_.gc3,p3)*
593 int_shell4_->coefficient_unnorm(quartet_info_.gc4,p4);
594
595 const double pfac_simple = pair12->ovlp*pair34->ovlp*pfac_norm;
596// How to screen out primitive combinations?
597// if (pfac_simple < 1e-9)
598// return 0;
599
600 double P[3], Q[3], PQ[3], W[3];
601
602 const double zeta = pair12->gamma;
603 const double eta = pair34->gamma;
604 const double ooz = 1.0/zeta;
605 const double ooe = 1.0/eta;
606 const double ooze = 1.0/(zeta+eta);
607#if LIBINT2_DEFINED(eri,roz)
608 Data->roz[0] = eta*ooze;
609 const double rho = zeta*Data->roz[0];
610#else
611 const double rho = zeta * eta * ooze;
612#endif
613
614 const double pfac = 2.0*sqrt(rho*M_1_PI)*scale*pfac_simple;
615
616 P[0] = pair12->P[0];
617 P[1] = pair12->P[1];
618 P[2] = pair12->P[2];
619 Q[0] = pair34->P[0];
620 Q[1] = pair34->P[1];
621 Q[2] = pair34->P[2];
622 PQ[0] = P[0] - Q[0];
623 PQ[1] = P[1] - Q[1];
624 PQ[2] = P[2] - Q[2];
625 double PQ2 = PQ[0]*PQ[0];
626 PQ2 += PQ[1]*PQ[1];
627 PQ2 += PQ[2]*PQ[2];
628 double T = rho*PQ2;
629
630 if (!quartet_info_.am) {
631 const double* Fm = coreints_.eval(Data->LIBINT_T_SS_EREP_SS(0), 0, T, rho,
632 static_cast<void*>(&coreints_scratch_));
633 Data->LIBINT_T_SS_EREP_SS(0)[0] = Fm[0]*pfac;
634 }
635 else {
636#if LIBINT2_DEFINED(eri,oo2ze)
637 Data->oo2ze[0] = 0.5*ooze;
638#endif
639#if LIBINT2_DEFINED(eri,roe)
640 Data->roe[0] = zeta*ooze;
641#endif
642#if LIBINT2_DEFINED(eri,oo2z)
643 Data->oo2z[0] = 0.5/zeta;
644#endif
645#if LIBINT2_DEFINED(eri,oo2e)
646 Data->oo2e[0] = 0.5/eta;
647#endif
648 W[0] = (zeta*P[0] + eta*Q[0])*ooze;
649 W[1] = (zeta*P[1] + eta*Q[1])*ooze;
650 W[2] = (zeta*P[2] + eta*Q[2])*ooze;
651
652 const double* Gm = coreints_.eval(Data->LIBINT_T_SS_EREP_SS(0), quartet_info_.am, T, rho,
653 static_cast<void*>(&coreints_scratch_));
654 std::transform(Gm, Gm+quartet_info_.am+1,
655 Data->LIBINT_T_SS_EREP_SS(0),
656 std::bind(std::multiplies<double>(), std::placeholders::_1, pfac));
657
658 /* PA */
659#if LIBINT2_DEFINED(eri,PA_x)
660 Data->PA_x[0] = P[0] - quartet_info_.A[0];
661#endif
662#if LIBINT2_DEFINED(eri,PA_y)
663 Data->PA_y[0] = P[1] - quartet_info_.A[1];
664#endif
665#if LIBINT2_DEFINED(eri,PA_z)
666 Data->PA_z[0] = P[2] - quartet_info_.A[2];
667#endif
668 /* QC */
669#if LIBINT2_DEFINED(eri,QC_x)
670 Data->QC_x[0] = Q[0] - quartet_info_.C[0];
671#endif
672#if LIBINT2_DEFINED(eri,QC_y)
673 Data->QC_y[0] = Q[1] - quartet_info_.C[1];
674#endif
675#if LIBINT2_DEFINED(eri,QC_z)
676 Data->QC_z[0] = Q[2] - quartet_info_.C[2];
677#endif
678 /* WP */
679#if LIBINT2_DEFINED(eri,WP_x)
680 Data->WP_x[0] = W[0] - P[0];
681#endif
682#if LIBINT2_DEFINED(eri,WP_y)
683 Data->WP_y[0] = W[1] - P[1];
684#endif
685#if LIBINT2_DEFINED(eri,WP_z)
686 Data->WP_z[0] = W[2] - P[2];
687#endif
688 /* WQ */
689#if LIBINT2_DEFINED(eri,WQ_x)
690 Data->WQ_x[0] = W[0] - Q[0];
691#endif
692#if LIBINT2_DEFINED(eri,WQ_y)
693 Data->WQ_y[0] = W[1] - Q[1];
694#endif
695#if LIBINT2_DEFINED(eri,WQ_z)
696 Data->WQ_z[0] = W[2] - Q[2];
697#endif
698
699#if LIBINT2_DEFINED(eri,TwoPRepITR_pfac0_0_0_x) || \
700 LIBINT2_DEFINED(eri,TwoPRepITR_pfac0_0_0_y) || \
701 LIBINT2_DEFINED(eri,TwoPRepITR_pfac0_0_0_z) || \
702 LIBINT2_DEFINED(eri,TwoPRepITR_pfac0_1_0_x) || \
703 LIBINT2_DEFINED(eri,TwoPRepITR_pfac0_1_0_y) || \
704 LIBINT2_DEFINED(eri,TwoPRepITR_pfac0_1_0_z)
705 double a2 = int_shell2_->exponent(quartet_info_.p2);
706 double a4 = int_shell4_->exponent(quartet_info_.p4);
707#endif
708#if LIBINT2_DEFINED(eri,TwoPRepITR_pfac0_0_1_x) || \
709 LIBINT2_DEFINED(eri,TwoPRepITR_pfac0_0_1_y) || \
710 LIBINT2_DEFINED(eri,TwoPRepITR_pfac0_0_1_z) || \
711 LIBINT2_DEFINED(eri,TwoPRepITR_pfac0_1_1_x) || \
712 LIBINT2_DEFINED(eri,TwoPRepITR_pfac0_1_1_y) || \
713 LIBINT2_DEFINED(eri,TwoPRepITR_pfac0_1_1_z)
714 double a1 = int_shell1_->exponent(quartet_info_.p1);
715 double a3 = int_shell3_->exponent(quartet_info_.p3);
716#endif
717
718 // using ITR?
719#if LIBINT2_DEFINED(eri,TwoPRepITR_pfac0_0_0_x)
720 Data->TwoPRepITR_pfac0_0_0_x[0] = - (a2*(quartet_info_.A[0]-quartet_info_.B[0]) + a4*(quartet_info_.C[0]-quartet_info_.D[0]))/zeta;
721#endif
722#if LIBINT2_DEFINED(eri,TwoPRepITR_pfac0_0_0_y)
723 Data->TwoPRepITR_pfac0_0_0_y[0] = - (a2*(quartet_info_.A[1]-quartet_info_.B[1]) + a4*(quartet_info_.C[1]-quartet_info_.D[1]))/zeta;
724#endif
725#if LIBINT2_DEFINED(eri,TwoPRepITR_pfac0_0_0_z)
726 Data->TwoPRepITR_pfac0_0_0_z[0] = - (a2*(quartet_info_.A[2]-quartet_info_.B[2]) + a4*(quartet_info_.C[2]-quartet_info_.D[2]))/zeta;
727#endif
728#if LIBINT2_DEFINED(eri,TwoPRepITR_pfac0_1_0_x)
729 Data->TwoPRepITR_pfac0_1_0_x[0] = - (a2*(quartet_info_.A[0]-quartet_info_.B[0]) + a4*(quartet_info_.C[0]-quartet_info_.D[0]))/eta;
730#endif
731#if LIBINT2_DEFINED(eri,TwoPRepITR_pfac0_1_0_y)
732 Data->TwoPRepITR_pfac0_1_0_y[0] = - (a2*(quartet_info_.A[1]-quartet_info_.B[1]) + a4*(quartet_info_.C[1]-quartet_info_.D[1]))/eta;
733#endif
734#if LIBINT2_DEFINED(eri,TwoPRepITR_pfac0_1_0_z)
735 Data->TwoPRepITR_pfac0_1_0_z[0] = - (a2*(quartet_info_.A[2]-quartet_info_.B[2]) + a4*(quartet_info_.C[2]-quartet_info_.D[2]))/eta;
736#endif
737#if LIBINT2_DEFINED(eri,TwoPRepITR_pfac0_0_1_x)
738 Data->TwoPRepITR_pfac0_0_1_x[0] = (a1*(quartet_info_.A[0]-quartet_info_.B[0]) + a3*(quartet_info_.C[0]-quartet_info_.D[0]))/zeta;
739#endif
740#if LIBINT2_DEFINED(eri,TwoPRepITR_pfac0_0_1_y)
741 Data->TwoPRepITR_pfac0_0_1_y[0] = (a1*(quartet_info_.A[1]-quartet_info_.B[1]) + a3*(quartet_info_.C[1]-quartet_info_.D[1]))/zeta;
742#endif
743#if LIBINT2_DEFINED(eri,TwoPRepITR_pfac0_0_1_z)
744 Data->TwoPRepITR_pfac0_0_1_z[0] = (a1*(quartet_info_.A[2]-quartet_info_.B[2]) + a3*(quartet_info_.C[2]-quartet_info_.D[2]))/zeta;
745#endif
746#if LIBINT2_DEFINED(eri,TwoPRepITR_pfac0_1_1_x)
747 Data->TwoPRepITR_pfac0_1_1_x[0] = (a1*(quartet_info_.A[0]-quartet_info_.B[0]) + a3*(quartet_info_.C[0]-quartet_info_.D[0]))/eta;
748#endif
749#if LIBINT2_DEFINED(eri,TwoPRepITR_pfac0_1_1_y)
750 Data->TwoPRepITR_pfac0_1_1_y[0] = (a1*(quartet_info_.A[1]-quartet_info_.B[1]) + a3*(quartet_info_.C[1]-quartet_info_.D[1]))/eta;
751#endif
752#if LIBINT2_DEFINED(eri,TwoPRepITR_pfac0_1_1_z)
753 Data->TwoPRepITR_pfac0_1_1_z[0] = (a1*(quartet_info_.A[2]-quartet_info_.B[2]) + a3*(quartet_info_.C[2]-quartet_info_.D[2]))/eta;
754#endif
755#if LIBINT2_DEFINED(eri,eoz)
756 Data->eoz[0] = eta * ooz;
757#endif
758#if LIBINT2_DEFINED(eri,zoe)
759 Data->zoe[0] = zeta * ooe;
760#endif
761 }
762
763 return 1;
764}
765
766template <TwoBodyOper::type OperType>
767void
768TwoBodyOSARLibint2<OperType>::compute_quartet(int *psh1, int *psh2, int *psh3, int *psh4)
769{
770#ifdef EREP_TIMING
771 char section[30];
772#endif
773 GaussianBasisSet *pbs1=bs1_.pointer();
774 GaussianBasisSet *pbs2=bs2_.pointer();
775 GaussianBasisSet *pbs3=bs3_.pointer();
776 GaussianBasisSet *pbs4=bs4_.pointer();
777 int int_expweight1; // For exponent weighted contractions.
778 int int_expweight2; // For exponent weighted contractions.
779 int int_expweight3; // For exponent weighted contractions.
780 int int_expweight4; // For exponent weighted contractions.
781 int size;
782 int ii;
783 int size1, size2, size3, size4;
784 int tam1,tam2,tam3,tam4;
785 int i,j,k,l;
786 int pi, pj, pk, pl;
787 int gci, gcj, gck, gcl;
788 int sh1,sh2,sh3,sh4;
789 int osh1,osh2,osh3,osh4;
790 int am1,am2,am3,am4,am12,am34;
791 int minam1,minam2,minam3,minam4;
792 int redundant_index;
793 int e12,e13e24,e34;
794 int p12,p34,p13p24;
795 int eAB;
796
797 osh1 = sh1 = *psh1;
798 osh2 = sh2 = *psh2;
799 osh3 = sh3 = *psh3;
800 osh4 = sh4 = *psh4;
801
802 /* Test the arguments to make sure that they are sensible. */
803 if ( sh1 < 0 || sh1 >= bs1_->nbasis()
804 || sh2 < 0 || sh2 >= bs2_->nbasis()
805 || sh3 < 0 || sh3 >= bs3_->nbasis()
806 || sh4 < 0 || sh4 >= bs4_->nbasis() ) {
807 ExEnv::errn() << scprintf("compute_erep has been incorrectly used\n");
808 ExEnv::errn() << scprintf("shells (bounds): %d (%d), %d (%d), %d (%d), %d (%d)\n",
809 sh1,bs1_->nbasis()-1,
810 sh2,bs2_->nbasis()-1,
811 sh3,bs3_->nbasis()-1,
812 sh4,bs4_->nbasis()-1);
813 throw sc::ProgrammingError("", __FILE__, __LINE__);
814 }
815
816 /* Set up pointers to the current shells. */
817 int_shell1_ = &bs1_->shell(sh1);
818 int_shell2_ = &bs2_->shell(sh2);
819 int_shell3_ = &bs3_->shell(sh3);
820 int_shell4_ = &bs4_->shell(sh4);
821
822 /* Compute the maximum angular momentum on each centers to
823 * determine the most efficient way to invoke the building and shifting
824 * routines. The minimum angular momentum will be computed at the
825 * same time. */
826 minam1 = int_shell1_->min_am();
827 minam2 = int_shell2_->min_am();
828 minam3 = int_shell3_->min_am();
829 minam4 = int_shell4_->min_am();
830 am1 = int_shell1_->max_am();
831 am2 = int_shell2_->max_am();
832 am3 = int_shell3_->max_am();
833 am4 = int_shell4_->max_am();
834 am12 = am1 + am2;
835 am34 = am3 + am4;
836
837 // This condition being true is guaranteed by the constructor of IntegralLibint2
838 //if (minam1 != am1 ||
839 // minam2 != am2 ||
840 // minam3 != am3 ||
841 // minam4 != am4 ) {
842 // ExEnv::errn() << scprintf("Int2eLibint2::comp_eri() cannot yet handle fully general contractions") << endl;
843 // fail();
844 //}
845
846 /* See if need to transform to spherical harmonics */
847 bool need_cart2sph_transform = false;
848 if (int_shell1_->has_pure() ||
849 int_shell2_->has_pure() ||
850 int_shell3_->has_pure() ||
851 int_shell4_->has_pure())
852 need_cart2sph_transform = true;
853
854
855 /* See if contraction quartets need to be resorted into a shell quartet */
856 bool need_sort_to_shell_quartet = false;
857 int num_gen_shells = 0;
858 if (int_shell1_->ncontraction() > 1)
859 num_gen_shells++;
860 if (int_shell2_->ncontraction() > 1)
861 num_gen_shells++;
862 if (int_shell3_->ncontraction() > 1)
863 num_gen_shells++;
864 if (int_shell4_->ncontraction() > 1)
865 num_gen_shells++;
866 if (am12+am34 && num_gen_shells >= 1)
867 need_sort_to_shell_quartet = true;
868
869 /* Unique integrals are needed only ?*/
870 bool need_unique_ints_only = false;
871 if (!redundant_) {
872 e12 = 0;
873 if (int_shell1_ == int_shell2_ && int_shell1_->nfunction()>1)
874 e12 = 1;
875 e34 = 0;
876 if (int_shell3_ == int_shell4_ && int_shell3_->nfunction()>1)
877 e34 = 1;
878 e13e24 = 0;
879 if (int_shell1_ == int_shell3_ && int_shell2_ == int_shell4_ && int_shell1_->nfunction()*int_shell2_->nfunction()>1)
880 e13e24 = 1;
881
882 if ( e12 || e34 || e13e24 )
883 need_unique_ints_only = true;
884 }
885
886
887#ifdef EREP_TIMING
888 sprintf(section,"erep am=%02d",am12+am34);
889 tim_enter(section);
890 tim_enter("setup");
891#endif
892
893 /* Convert the integral to the most efficient form. */
894 p12 = 0;
895 p34 = 0;
896 p13p24 = 0;
897
898 if (am2 > am1) {
899 p12 = 1;
900 iswtch(&am1,&am2);iswtch(&sh1,&sh2);iswtch(psh1,psh2);
901 iswtch(&minam1,&minam2);
902 pswtch((void**)&int_shell1_,(void**)&int_shell2_);
903 swtch(pbs1,pbs2);
904 }
905 if (am4 > am3) {
906 p34 = 1;
907 iswtch(&am3,&am4);iswtch(&sh3,&sh4);iswtch(psh3,psh4);
908 iswtch(&minam3,&minam4);
909 pswtch((void**)&int_shell3_,(void**)&int_shell4_);
910 swtch(pbs3,pbs4);
911 }
912 if (am12 > am34) {
913 p13p24 = 1;
914 iswtch(&am1,&am3);iswtch(&sh1,&sh3);iswtch(psh1,psh3);
915 iswtch(&am2,&am4);iswtch(&sh2,&sh4);iswtch(psh2,psh4);
916 iswtch(&am12,&am34);
917 iswtch(&minam1,&minam3);
918 iswtch(&minam2,&minam4);
919 pswtch((void**)&int_shell1_,(void**)&int_shell3_);
920 swtch(pbs1,pbs3);
921 pswtch((void**)&int_shell2_,(void**)&int_shell4_);
922 swtch(pbs2,pbs4);
923 }
924 bool shells_were_permuted = (p12||p34||p13p24);
925
926 /* If the centers were permuted, then the int_expweighted variable may
927 * need to be changed. */
928 if (p12) {
929 iswtch(&int_expweight1,&int_expweight2);
930 }
931 if (p34) {
932 iswtch(&int_expweight3,&int_expweight4);
933 }
934 if (p13p24) {
935 iswtch(&int_expweight1,&int_expweight3);
936 iswtch(&int_expweight2,&int_expweight4);
937 }
938
939 /* Compute the shell sizes. */
940 size1 = int_shell1_->ncartesian();
941 size2 = int_shell2_->ncartesian();
942 size3 = int_shell3_->ncartesian();
943 size4 = int_shell4_->ncartesian();
944 size = size1*size2*size3*size4;
945
946 /* Compute center data for Libint */
947 int ctr1 = pbs1->shell_to_center(sh1);
948 int ctr2 = pbs2->shell_to_center(sh2);
949 int ctr3 = pbs3->shell_to_center(sh3);
950 int ctr4 = pbs4->shell_to_center(sh4);
951 Libint_t& libint0 = Libint_[0];
952 libint0.AB_x[0] = pbs1->r(ctr1,0) - pbs2->r(ctr2,0);
953 libint0.AB_y[0] = pbs1->r(ctr1,1) - pbs2->r(ctr2,1);
954 libint0.AB_z[0] = pbs1->r(ctr1,2) - pbs2->r(ctr2,2);
955 libint0.CD_x[0] = pbs3->r(ctr3,0) - pbs4->r(ctr4,0);
956 libint0.CD_y[0] = pbs3->r(ctr3,1) - pbs4->r(ctr4,1);
957 libint0.CD_z[0] = pbs3->r(ctr3,2) - pbs4->r(ctr4,2);
958 for(i=0;i<3;i++) {
959 quartet_info_.A[i] = pbs1->r(ctr1,i);
960 quartet_info_.B[i] = pbs2->r(ctr2,i);
961 quartet_info_.C[i] = pbs3->r(ctr3,i);
962 quartet_info_.D[i] = pbs4->r(ctr4,i);
963 }
964 quartet_info_.AB2 = libint0.AB_x[0]*libint0.AB_x[0];
965 quartet_info_.AB2 += libint0.AB_y[0]*libint0.AB_y[0];
966 quartet_info_.AB2 += libint0.AB_z[0]*libint0.AB_z[0];
967 quartet_info_.CD2 = libint0.CD_x[0]*libint0.CD_x[0];
968 quartet_info_.CD2 += libint0.CD_y[0]*libint0.CD_y[0];
969 quartet_info_.CD2 += libint0.CD_z[0]*libint0.CD_z[0];
970
971 /* Set up pointers to the current shell pairs. */
972 quartet_info_.shell_pair12 = shell_pairs12_->shell_pair(osh1,osh2);
973 quartet_info_.shell_pair34 = shell_pairs34_->shell_pair(osh3,osh4);
974
975 /* Remember how permuted - will need to access shell pairs in grt_quartet_data_() using the original
976 primitive indices */
977 quartet_info_.p12 = p12;
978 quartet_info_.p34 = p34;
979 quartet_info_.p13p24 = p13p24;
980
981 /* Remember the original primitive indices to access shell pair data
982 Note the reverse order of switching, p13p24 first,
983 then p12 and p34 - because we need the inverse mapping! */
984 quartet_info_.op1 = &quartet_info_.p1;
985 quartet_info_.op2 = &quartet_info_.p2;
986 quartet_info_.op3 = &quartet_info_.p3;
987 quartet_info_.op4 = &quartet_info_.p4;
988 if (p13p24) {
989 pswtch((void **)&quartet_info_.op1,(void **)&quartet_info_.op3);
990 pswtch((void **)&quartet_info_.op2,(void **)&quartet_info_.op4);
991 }
992 if (p12)
993 pswtch((void **)&quartet_info_.op1,(void **)&quartet_info_.op2);
994 if (p34)
995 pswtch((void **)&quartet_info_.op3,(void **)&quartet_info_.op4);
996
997 /* Determine where integrals need to go at each stage */
998 if (shells_were_permuted)
999 if (need_sort_to_shell_quartet) {
1000 prim_ints_ = cart_ints_;
1001 if (need_cart2sph_transform)
1002 contr_quartets_ = sphharm_ints_;
1003 else
1004 contr_quartets_ = cart_ints_;
1005 shell_quartet_ = perm_ints_;
1006 }
1007 else {
1008 prim_ints_ = cart_ints_;
1009 if (need_cart2sph_transform) {
1010 contr_quartets_ = sphharm_ints_;
1011 shell_quartet_ = contr_quartets_;
1012 }
1013 else
1014 shell_quartet_ = cart_ints_;
1015 }
1016 else
1017 if (need_sort_to_shell_quartet) {
1018 prim_ints_ = cart_ints_;
1019 if (need_cart2sph_transform)
1020 contr_quartets_ = sphharm_ints_;
1021 else
1022 contr_quartets_ = cart_ints_;
1023 shell_quartet_ = target_ints_buffer_;
1024 }
1025 else {
1026 if (need_cart2sph_transform) {
1027 prim_ints_ = cart_ints_;
1028 contr_quartets_ = target_ints_buffer_;
1029 shell_quartet_ = target_ints_buffer_;
1030 }
1031 else {
1032 prim_ints_ = target_ints_buffer_;
1033 shell_quartet_ = target_ints_buffer_;
1034 }
1035 }
1036
1037 /* Begin loops over generalized contractions. */
1038 int buffer_offset = 0;
1039 for (gci=0; gci<int_shell1_->ncontraction(); gci++) {
1040 tam1 = int_shell1_->am(gci);
1041 int tsize1 = INT_NCART_NN(tam1);
1042 quartet_info_.gc1 = gci;
1043 for (gcj=0; gcj<int_shell2_->ncontraction(); gcj++) {
1044 tam2 = int_shell2_->am(gcj);
1045 int tsize2 = INT_NCART_NN(tam2);
1046 quartet_info_.gc2 = gcj;
1047 for (gck=0; gck<int_shell3_->ncontraction(); gck++) {
1048 tam3 = int_shell3_->am(gck);
1049 int tsize3 = INT_NCART_NN(tam3);
1050 quartet_info_.gc3 = gck;
1051 for (gcl=0; gcl<int_shell4_->ncontraction(); gcl++) {
1052 tam4 = int_shell4_->am(gcl);
1053 int tsize4 = INT_NCART_NN(tam4);
1054 quartet_info_.gc4 = gcl;
1055 quartet_info_.am = tam1 + tam2 + tam3 + tam4;
1056 int size = tsize1*tsize2*tsize3*tsize4;
1057
1058 /* Begin loop over primitives. */
1059 int num_prim_combinations = 0;
1060 for (pi=0; pi<int_shell1_->nprimitive(); pi++) {
1061 quartet_info_.p1 = pi;
1062 for (pj=0; pj<int_shell2_->nprimitive(); pj++) {
1063 quartet_info_.p2 = pj;
1064 for (pk=0; pk<int_shell3_->nprimitive(); pk++) {
1065 quartet_info_.p3 = pk;
1066 for (pl=0; pl<int_shell4_->nprimitive(); pl++) {
1067 quartet_info_.p4 = pl;
1068
1069 // Compute primitive data for Libint
1070 size_t ncomb = quartet_data_(&Libint_[num_prim_combinations], 1.0);
1071 num_prim_combinations += ncomb;
1072 }}}}
1073
1074 if (quartet_info_.am) {
1075 // Compute the integrals
1076 Libint_[0].contrdepth = num_prim_combinations;
1077 LIBINT2_PREFIXED_NAME(libint2_build_eri)[tam1][tam2][tam3][tam4](&Libint_[0]);
1078 // Copy the contracted integrals over to prim_ints_
1079 const LIBINT2_REALTYPE* prim_ints = Libint_[0].targets[0];
1080 for(int ijkl=0; ijkl<size; ijkl++)
1081 prim_ints_[buffer_offset + ijkl] = (double) prim_ints[ijkl];
1082
1083#if 0
1084 std::cout << *psh1 << " " << *psh2 << " " << *psh3 << " " << *psh4 << " " << std::endl;
1085 for(int ijkl=0; ijkl<size; ijkl++) {
1086 std::cout << " " << prim_ints[ijkl] << std::endl;
1087 }
1088#endif
1089 }
1090 else {
1091 double ssss = 0.0;
1092 for(int p=0; p<num_prim_combinations; ++p)
1093 ssss += Libint_[p].LIBINT_T_SS_EREP_SS(0)[0];
1094 prim_ints_[buffer_offset] = ssss;
1095 }
1096 buffer_offset += size;
1097 }}}}
1098
1099 /*-------------------------------------------
1100 Transform to spherical harmonics if needed
1101 -------------------------------------------*/
1102 if (need_cart2sph_transform)
1103 transform_contrquartets_(prim_ints_,contr_quartets_);
1104
1105 //
1106 // If not CCA-compliant normalization -- re-normalize all integrals to 1
1107 //
1108#if INTEGRALLIBINT2_NORMCONV != INTEGRALLIBINT2_NORMCONV_CCA
1109 norm_contrcart1_(need_cart2sph_transform ? contr_quartets_ : prim_ints_);
1110#endif
1111
1112 /*----------------------------------------------
1113 Resort integrals from by-contraction-quartets
1114 into shell-quartet order if needed
1115 ----------------------------------------------*/
1116 if (need_sort_to_shell_quartet)
1117 sort_contrquartets_to_shellquartet_(contr_quartets_,shell_quartet_);
1118
1119 /*---------------------------------
1120 Permute integrals back if needed
1121 ---------------------------------*/
1122 if ((!permute_)&&shells_were_permuted) {
1123 // handle integrals first
1124 permute_target_(shell_quartet_,target_ints_buffer_,p13p24,p12,p34);
1125 // then indices
1126 if (p13p24) {
1127 iswtch(&sh1,&sh3);iswtch(psh1,psh3);
1128 iswtch(&sh2,&sh4);iswtch(psh2,psh4);
1129 iswtch(&am1,&am3);
1130 iswtch(&am2,&am4);
1131 iswtch(&am12,&am34);
1132 pswtch((void**)&int_shell1_,(void**)&int_shell3_);
1133 swtch(pbs1,pbs3);
1134 pswtch((void**)&int_shell2_,(void**)&int_shell4_);
1135 swtch(pbs2,pbs4);
1136 iswtch(&int_expweight1,&int_expweight3);
1137 iswtch(&int_expweight2,&int_expweight4);
1138 }
1139 if (p34) {
1140 iswtch(&sh3,&sh4);iswtch(psh3,psh4);
1141 iswtch(&am3,&am4);
1142 pswtch((void**)&int_shell3_,(void**)&int_shell4_);
1143 swtch(pbs3,pbs4);
1144 iswtch(&int_expweight3,&int_expweight4);
1145 }
1146 if (p12) {
1147 iswtch(&sh1,&sh2);iswtch(psh1,psh2);
1148 iswtch(&am1,&am2);
1149 pswtch((void**)&int_shell1_,(void**)&int_shell2_);
1150 swtch(pbs1,pbs2);
1151 iswtch(&int_expweight1,&int_expweight2);
1152 }
1153 }
1154
1155 /*--- Extract unique integrals if needed ---*/
1156 if (need_unique_ints_only)
1157 get_nonredundant_ints_(target_ints_buffer_,target_ints_buffer_,e13e24,e12,e34);
1158
1159}
1160
1161}
1162
1163#endif // header guard
1164#endif // if LIBINT2_SUPPORT_ERI
1165
1166// Local Variables:
1167// mode: c++
1168// c-file-style: "CLJ"
1169// End:
This is thrown when a situations arises that should be impossible.
Definition scexception.h:92
SpinCase1 other(SpinCase1 S)
given 1-spin return the other 1-spin
Contains all MPQC code up to version 3.
Definition mpqcin.h:14
void manage_array(T *const &array, std::size_t size)
manage or unmanaged array of data using default ConsumableResources object
Definition consumableresources.h:464
void deallocate(T *&array)
this version will set array to 0 upon return
Definition consumableresources.h:452

Generated at Wed Sep 25 2024 02:45:29 for MPQC 3.0.0-alpha using the documentation package Doxygen 1.12.0.