MPQC  3.0.0-alpha
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 
49 namespace 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 
247 template <TwoBodyOper::type OperType>
248 class 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 
326 template <TwoBodyOper::type OperType>
327 TwoBodyOSARLibint2<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 
418 template <TwoBodyOper::type OperType>
419 TwoBodyOSARLibint2<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 
436 template <TwoBodyOper::type OperType>
437 TwoBodyOSARLibint2<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 
499 template <TwoBodyOper::type OperType>
500 Ref<Int2eLibint2>
501 TwoBodyOSARLibint2<OperType>::clone() {
502  return new TwoBodyOSARLibint2<OperType>(*this);
503 }
504 
505 template <TwoBodyOper::type OperType>
506 size_t
507 TwoBodyOSARLibint2<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 
569 template <TwoBodyOper::type OperType>
570 size_t
571 TwoBodyOSARLibint2<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::bind2nd(std::multiplies<double>(), 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 
766 template <TwoBodyOper::type OperType>
767 void
768 TwoBodyOSARLibint2<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:
sc::Ref::pointer
T * pointer() const
Returns a pointer the reference counted object.
Definition: ref.h:413
sc::ExEnv::errn
static std::ostream & errn()
Return an ostream for error messages that writes from all nodes.
Definition: exenv.h:83
sc::other
SpinCase1 other(SpinCase1 S)
given 1-spin return the other 1-spin
sc::ProgrammingError
This is thrown when a situations arises that should be impossible.
Definition: scexception.h:92
sc::IntParamsG12::null_geminal
static ContractedGeminal null_geminal
null (i.e., invalid) geminal
Definition: intparams.h:152
sc::transform
RefSCMatrix transform(const OrbitalSpace &space2, const OrbitalSpace &space1, const Ref< SCMatrixKit > &kit=SCMatrixKit::default_matrixkit())
transform(s2,s1) returns matrix that transforms s1 to s2.
sc::deallocate
void deallocate(T *&array)
this version will set array to 0 upon return
Definition: consumableresources.h:452
sc::TwoBodyOper::r12_m1_g12
(contracted) Gaussian geminal over Coulomb,
Definition: operator.h:324
sc
Contains all MPQC code up to version 3.
Definition: mpqcin.h:14
sc::ConsumableResources::get_default_instance
static const Ref< ConsumableResources > & get_default_instance()
Returns the default ConsumableResources object.
sc::manage_array
void manage_array(T *const &array, std::size_t size)
manage or unmanaged array of data using default ConsumableResources object
Definition: consumableresources.h:464

Generated at Sun Jan 26 2020 23:23:58 for MPQC 3.0.0-alpha using the documentation package Doxygen 1.8.16.