LIBINT 2.7.2
engine.h
1/*
2 * Copyright (C) 2004-2021 Edward F. Valeev
3 *
4 * This file is part of Libint.
5 *
6 * Libint is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU Lesser General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * Libint is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with Libint. If not, see <http://www.gnu.org/licenses/>.
18 *
19 */
20
21#ifndef _libint2_src_lib_libint_engine_h_
22#define _libint2_src_lib_libint_engine_h_
23
24#ifndef LIBINT2_DOES_NOT_INLINE_ENGINE
25# define __libint2_engine_inline inline
26#else
27# define __libint2_engine_inline
28#endif
29
30#include <libint2/util/cxxstd.h>
31#if LIBINT2_CPLUSPLUS_STD < 2011
32# error "libint2/engine.h requires C++11 support"
33#endif
34
35#include <algorithm>
36#include <array>
37#include <cstring>
38#include <cstdio>
39#include <functional>
40#include <iostream>
41#include <limits>
42#include <map>
43#include <memory>
44#include <tuple>
45#include <utility>
46#include <vector>
47
48#include <libint2/cxxapi.h>
49#include <libint2/boys_fwd.h>
50#include <libint2/shell.h>
51#include <libint2/solidharmonics.h>
52#include <libint2/cartesian.h>
53#include <libint2/util/any.h>
54#include <libint2/util/array_adaptor.h>
55#include <libint2/util/intpart_iter.h>
56#include <libint2/util/compressed_pair.h>
57#include <libint2/util/timer.h>
58#include <libint2/cgshellinfo.h>
59#include <libint2/braket.h>
60
61// the engine will be profiled by default if library was configured with
62// --enable-profile
63#ifdef LIBINT2_PROFILE
64#define LIBINT2_ENGINE_TIMERS
65// uncomment if want to profile each integral class
66#define LIBINT2_ENGINE_PROFILE_CLASS
67#endif
68// uncomment if want to profile the engine even if library was configured
69// without --enable-profile
70//# define LIBINT2_ENGINE_TIMERS
71
72namespace libint2 {
73
77typedef std::vector<std::pair<double, double>> ContractedGaussianGeminal;
78
79constexpr size_t num_geometrical_derivatives(size_t ncenter,
80 size_t deriv_order) {
81 return (deriv_order > 0)
82 ? (num_geometrical_derivatives(ncenter, deriv_order - 1) *
83 (3 * ncenter + deriv_order - 1)) /
84 deriv_order
85 : 1;
86}
87
88template <typename T, unsigned N>
89__libint2_engine_inline typename std::remove_all_extents<T>::type* to_ptr1(T (&a)[N]);
90
92
96enum class Operator {
98 overlap = 0,
100 kinetic,
102 nuclear,
105 erf_nuclear,
108 erfc_nuclear,
113 emultipole1,
116 emultipole2,
119 emultipole3,
130 sphemultipole,
132 delta,
134 coulomb,
136 r12_m1 = coulomb,
138 cgtg,
140 cgtg_x_coulomb,
142 delcgtg2,
144 r12,
146 r12_1 = r12,
149 erf_coulomb,
152 erfc_coulomb,
154 stg,
156 stg_x_coulomb,
158 yukawa = stg_x_coulomb,
159 // do not modify this
160 invalid = -1,
161 // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!keep this updated!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
162 first_1body_oper = overlap,
163 last_1body_oper = sphemultipole,
164 first_2body_oper = delta,
165 last_2body_oper = stg_x_coulomb,
166 first_oper = first_1body_oper,
167 last_oper = last_2body_oper
168};
169
173inline constexpr int rank(Operator oper) {
174 return (oper >= Operator::first_1body_oper &&
175 oper <= Operator::last_1body_oper)
176 ? 1 :
177 ((oper >= Operator::first_2body_oper &&
178 oper <= Operator::last_2body_oper)
179 ? 2 : throw std::logic_error("rank(Operator): invalid operator given"));
180}
181
182namespace detail {
183struct default_operator_traits {
184 typedef struct {
185 } oper_params_type;
186 static oper_params_type default_params() { return oper_params_type{}; }
187 static constexpr auto nopers = 1u;
188 struct _core_eval_type {
189 template <typename... params>
190 static std::shared_ptr<const _core_eval_type> instance(params...) {
191 return nullptr;
192 }
193 };
194 using core_eval_type = const _core_eval_type;
195};
196} // namespace detail
197
203template <Operator Op>
204struct operator_traits : public detail::default_operator_traits {};
205
206template <>
207struct operator_traits<Operator::nuclear>
208 : public detail::default_operator_traits {
210 typedef std::vector<std::pair<scalar_type, std::array<scalar_type, 3>>>
211 oper_params_type;
212 static oper_params_type default_params() { return oper_params_type{}; }
213#ifndef LIBINT_USER_DEFINED_REAL
214 typedef const libint2::FmEval_Chebyshev7<scalar_type> core_eval_type;
215#else
216 typedef const libint2::FmEval_Reference<scalar_type> core_eval_type;
217#endif
218};
219
220template <>
221struct operator_traits<Operator::erf_nuclear>
222 : public detail::default_operator_traits {
225 typedef std::tuple<
226 scalar_type, typename operator_traits<Operator::nuclear>::oper_params_type>
227 oper_params_type;
228 static oper_params_type default_params() {
229 return std::make_tuple(0,operator_traits<Operator::nuclear>::default_params());
230 }
232 core_eval_type;
233};
234
235template <>
236struct operator_traits<Operator::erfc_nuclear>
237 : public detail::default_operator_traits {
240 typedef typename operator_traits<Operator::erf_nuclear>::oper_params_type oper_params_type;
241 static oper_params_type default_params() {
242 return std::make_tuple(0,operator_traits<Operator::nuclear>::default_params());
243 }
245 core_eval_type;
246};
247
248template <>
249struct operator_traits<Operator::emultipole1>
250 : public detail::default_operator_traits {
253 typedef std::array<double, 3> oper_params_type;
254 static oper_params_type default_params() {
255 return oper_params_type{{0,0,0}};
256 }
257 static constexpr auto nopers = 4u;
258};
259template <>
260struct operator_traits<Operator::emultipole2>
261 : public operator_traits<Operator::emultipole1> {
262 static constexpr auto nopers =
263 operator_traits<Operator::emultipole1>::nopers +
264 6;
265};
266template <>
267struct operator_traits<Operator::emultipole3>
268 : public operator_traits<Operator::emultipole1> {
269 static constexpr auto nopers =
270 operator_traits<Operator::emultipole2>::nopers + 10;
271};
272template <>
273struct operator_traits<Operator::sphemultipole>
274 : public operator_traits<Operator::emultipole1> {
275 static constexpr auto nopers =
276 (MULTIPOLE_MAX_ORDER + 1) * (MULTIPOLE_MAX_ORDER + 1);
277};
278
279template <>
280struct operator_traits<Operator::coulomb>
281 : public detail::default_operator_traits {
282#ifndef LIBINT_USER_DEFINED_REAL
283 typedef const libint2::FmEval_Chebyshev7<scalar_type> core_eval_type;
284#else
285 typedef const libint2::FmEval_Reference<scalar_type> core_eval_type;
286#endif
287};
288namespace detail {
289template <int K>
290struct cgtg_operator_traits : public detail::default_operator_traits {
291 typedef libint2::GaussianGmEval<scalar_type, K> core_eval_type;
292 typedef ContractedGaussianGeminal oper_params_type;
293};
294} // namespace detail
295template <>
296struct operator_traits<Operator::cgtg>
297 : public detail::cgtg_operator_traits<0> {};
298template <>
299struct operator_traits<Operator::cgtg_x_coulomb>
300 : public detail::cgtg_operator_traits<-1> {};
301template <>
302struct operator_traits<Operator::delcgtg2>
303 : public detail::cgtg_operator_traits<2> {};
304
305template <>
306struct operator_traits<Operator::delta>
307 : public detail::default_operator_traits {
309 core_eval_type;
310};
311
312template <>
313struct operator_traits<Operator::r12>
314 : public detail::default_operator_traits {
316 core_eval_type;
317};
318
319template <>
320struct operator_traits<Operator::erf_coulomb>
321 : public detail::default_operator_traits {
323 typedef scalar_type oper_params_type;
324 static oper_params_type default_params() {
325 return oper_params_type{0};
326 }
328 core_eval_type;
329};
330template <>
331struct operator_traits<Operator::erfc_coulomb>
332 : public detail::default_operator_traits {
334 typedef scalar_type oper_params_type;
335 static oper_params_type default_params() {
336 return oper_params_type{0};
337 }
339 core_eval_type;
340};
341
342template <>
343struct operator_traits<Operator::stg>
344 : public detail::default_operator_traits {
346 typedef scalar_type oper_params_type;
347 static oper_params_type default_params() {
348 return oper_params_type{0};
349 }
351 core_eval_type;
352};
353
354template <>
355struct operator_traits<Operator::stg_x_coulomb>
356 : public detail::default_operator_traits {
358 typedef scalar_type oper_params_type;
359 static oper_params_type default_params() {
360 return oper_params_type{0};
361 }
363 core_eval_type;
364};
365
368default_params(const Operator& oper);
369
370namespace detail {
371template <typename core_eval_type>
372using __core_eval_pack_type =
373 compressed_pair<std::shared_ptr<core_eval_type>,
375template <Operator Op>
376using core_eval_pack_type =
377 __core_eval_pack_type<typename operator_traits<Op>::core_eval_type>;
378}
379
380#define BOOST_PP_NBODY_BRAKET_MAX_INDEX 4
381
385inline constexpr int rank(BraKet braket) {
386 return (braket==BraKet::x_x || braket==BraKet::xs_xs) ? 2 :
387 ((braket==BraKet::xs_xx || braket==BraKet::xx_xs) ? 3 :
388 ((braket==BraKet::xx_xx) ? 4 : throw std::logic_error("rank(BraKet): invalid braket given")));
389}
390
394inline constexpr BraKet default_braket(Operator oper) {
395 return (rank(oper)==1) ? BraKet::x_x :
396 ((rank(oper)==2) ? BraKet::xx_xx : throw std::logic_error("default_braket(Operator): invalid operator given"));
397}
398
399constexpr size_t nopers_2body = static_cast<int>(Operator::last_2body_oper) -
400 static_cast<int>(Operator::first_2body_oper) +
401 1;
402constexpr size_t nbrakets_2body = static_cast<int>(BraKet::last_2body_braket) -
403 static_cast<int>(BraKet::first_2body_braket) +
404 1;
405constexpr size_t nderivorders_2body = LIBINT2_MAX_DERIV_ORDER + 1;
406
412class Engine {
413 private:
414 typedef struct {
415 } empty_pod;
416
417 public:
418
419 static constexpr auto max_ntargets =
420 std::extent<decltype(std::declval<Libint_t>().targets), 0>::value;
421 using target_ptr_vec =
422 std::vector<const value_type*, detail::ext_stack_allocator<const value_type*, max_ntargets>>;
423
428 Engine()
429 : oper_(Operator::invalid),
430 braket_(BraKet::invalid),
431 primdata_(),
432 stack_size_(0),
433 lmax_(-1),
434 deriv_order_(0),
435 cartesian_shell_normalization_(CartesianShellNormalization::standard),
436 scale_(1) {
437 set_precision(std::numeric_limits<scalar_type>::epsilon());
438 }
439
440 // clang-format off
442
469 // clang-format on
470 template <typename Params = empty_pod>
471 Engine(Operator oper, size_t max_nprim, int max_l, int deriv_order = 0,
472 scalar_type precision = std::numeric_limits<scalar_type>::epsilon(),
473 Params params = empty_pod(), BraKet braket = BraKet::invalid,
474 ScreeningMethod screening_method = default_screening_method())
475 : oper_(oper),
476 braket_(braket),
477 primdata_(),
478 spbra_(max_nprim),
479 spket_(max_nprim),
480 stack_size_(0),
481 lmax_(max_l),
482 deriv_order_(deriv_order),
483 screening_method_(screening_method),
484 cartesian_shell_normalization_(CartesianShellNormalization::standard),
485 scale_(1),
486 params_(enforce_params_type(oper, params)) {
487 set_precision(precision);
488 assert(max_nprim > 0);
489 initialize(max_nprim);
490 core_eval_pack_ = make_core_eval_pack(oper); // must follow initialize() to
491 // ensure default braket_ has
492 // been set
493 init_core_ints_params(params_);
494 }
495
497 // intel does not accept "move ctor = default"
498 Engine(Engine&& other)
499 : oper_(other.oper_),
500 braket_(other.braket_),
501 primdata_(std::move(other.primdata_)),
502 spbra_(std::move(other.spbra_)),
503 spket_(std::move(other.spket_)),
504 stack_size_(other.stack_size_),
505 lmax_(other.lmax_),
506 hard_lmax_(other.hard_lmax_),
507 hard_default_lmax_(other.hard_default_lmax_),
508 deriv_order_(other.deriv_order_),
509 precision_(other.precision_),
510 ln_precision_(other.ln_precision_),
511 screening_method_(other.screening_method_),
512 cartesian_shell_normalization_(other.cartesian_shell_normalization_),
513 scale_(other.scale_),
514 core_eval_pack_(std::move(other.core_eval_pack_)),
515 params_(std::move(other.params_)),
516 core_ints_params_(std::move(other.core_ints_params_)),
517 targets_(std::move(other.targets_)),
518 set_targets_(other.set_targets_),
519 scratch_(std::move(other.scratch_)),
520 scratch2_(other.scratch2_),
521 buildfnptrs_(other.buildfnptrs_) {
522 // leave other in an unusable (but valid) state
523 other.oper_ = Operator::invalid;
524 other.braket_ = BraKet::invalid;
525 other.scratch2_ = nullptr;
526 }
527
529 Engine(const Engine& other)
530 : oper_(other.oper_),
531 braket_(other.braket_),
532 primdata_(other.primdata_.size()),
533 spbra_(other.spbra_),
534 spket_(other.spket_),
535 stack_size_(other.stack_size_),
536 lmax_(other.lmax_),
537 deriv_order_(other.deriv_order_),
538 precision_(other.precision_),
539 ln_precision_(other.ln_precision_),
540 screening_method_(other.screening_method_),
541 cartesian_shell_normalization_(other.cartesian_shell_normalization_),
542 scale_(other.scale_),
543 core_eval_pack_(other.core_eval_pack_),
544 params_(other.params_),
545 core_ints_params_(other.core_ints_params_) {
546 initialize();
547 }
548
549 ~Engine() { finalize(); }
550
552 Engine& operator=(Engine&& other) {
553 oper_ = other.oper_;
554 braket_ = other.braket_;
555 primdata_ = std::move(other.primdata_);
556 spbra_ = std::move(other.spbra_);
557 spket_ = std::move(other.spket_);
558 stack_size_ = other.stack_size_;
559 lmax_ = other.lmax_;
560 hard_lmax_ = other.hard_lmax_;
561 hard_default_lmax_ = other.hard_default_lmax_;
562 deriv_order_ = other.deriv_order_;
563 precision_ = other.precision_;
564 ln_precision_ = other.ln_precision_;
565 screening_method_ = other.screening_method_;
566 cartesian_shell_normalization_ = other.cartesian_shell_normalization_;
567 scale_ = other.scale_;
568 core_eval_pack_ = std::move(other.core_eval_pack_);
569 params_ = std::move(other.params_);
570 core_ints_params_ = std::move(other.core_ints_params_);
571 targets_ = std::move(other.targets_);
572 set_targets_ = other.set_targets_;
573 scratch_ = std::move(other.scratch_);
574 scratch2_ = other.scratch2_;
575 buildfnptrs_ = other.buildfnptrs_;
576 // leave other in an unusable state
577 other.oper_ = Operator::invalid;
578 other.braket_ = BraKet::invalid;
579 other.scratch2_ = nullptr;
580 return *this;
581 }
582
584 Engine& operator=(const Engine& other) {
585 oper_ = other.oper_;
586 braket_ = other.braket_;
587 primdata_.resize(other.primdata_.size());
588 spbra_ = other.spbra_;
589 spket_ = other.spket_;
590 stack_size_ = other.stack_size_;
591 lmax_ = other.lmax_;
592 deriv_order_ = other.deriv_order_;
593 precision_ = other.precision_;
594 ln_precision_ = other.ln_precision_;
595 screening_method_ = other.screening_method_;
596 cartesian_shell_normalization_ = other.cartesian_shell_normalization_;
597 scale_ = other.scale_;
598 core_eval_pack_ = other.core_eval_pack_;
599 params_ = other.params_;
600 core_ints_params_ = other.core_ints_params_;
601 initialize();
602 return *this;
603 }
604
606 int operator_rank() const { return rank(oper_); }
607
609 int braket_rank() const { return rank(braket_); }
610
612 Operator oper() const { return oper_; }
613
615 BraKet braket() const { return braket_; }
616
618 int deriv_order() const { return deriv_order_; }
619
623 Engine& set(Operator new_oper) {
624 if (oper_ != new_oper) {
625 oper_ = new_oper;
626 braket_ = default_braket(oper_);
627 params_ = default_params(oper_);
628 initialize();
629 core_eval_pack_ = make_core_eval_pack(oper_); // must follow initialize() to
630 // ensure default braket_ has
631 // been set
632 }
633 return *this;
634 }
635
638 Engine& set(BraKet new_braket) {
639 if (braket_ != new_braket) {
640 braket_ = new_braket;
641 initialize();
642 }
643 return *this;
644 }
645
649 template <typename Params>
650 Engine& set_params(const Params& params) {
651 params_ = params;
652 init_core_ints_params(params_);
653 reset_scratch();
654 return *this;
655 }
656
658 std::size_t max_nprim() const {
659 assert(spbra_.primpairs.size() == spket_.primpairs.size());
660 return static_cast<std::size_t>(std::sqrt(spbra_.primpairs.size()));
661 }
662
666 Engine& set_max_nprim(std::size_t n) {
667 if (n*n > spbra_.primpairs.size()) {
668 spbra_.resize(n);
669 spket_.resize(n);
670 initialize(n);
671 }
672 return *this;
673 }
674
676 std::size_t max_l() const {
677 return lmax_;
678 }
679
683 Engine& set_max_l(std::size_t L) {
684 if (L >= static_cast<std::size_t>(lmax_)) {
685 lmax_ = L;
686 initialize();
687 }
688 return *this;
689 }
690
696 const target_ptr_vec& results() const { return targets_; }
697
701 unsigned int nshellsets() const { return targets_.size(); }
702
704
709 template <typename... ShellPack>
710 __libint2_engine_inline const target_ptr_vec& compute(
711 const libint2::Shell& first_shell, const ShellPack&... rest_of_shells);
712
718 __libint2_engine_inline const target_ptr_vec& compute1(
719 const libint2::Shell& s1, const libint2::Shell& s2);
720
742 template <Operator oper, BraKet braket, size_t deriv_order>
743 __libint2_engine_inline const target_ptr_vec& compute2(const Shell& bra1,
744 const Shell& bra2,
745 const Shell& ket1,
746 const Shell& ket2,
747 const ShellPair* spbra = nullptr,
748 const ShellPair* spket = nullptr);
749
750 typedef const target_ptr_vec& (Engine::*compute2_ptr_type)(const Shell& bra1,
751 const Shell& bra2,
752 const Shell& ket1,
753 const Shell& ket2,
754 const ShellPair* spbra,
755 const ShellPair* spket);
756
757 // clang-format off
768 // clang-format on
769 Engine& set_precision(scalar_type prec) {
770 if (prec <= 0.) {
771 precision_ = 0.;
772 ln_precision_ = std::numeric_limits<scalar_type>::lowest();
773 return *this;
774 }
775 if (prec > 0.) { // split single if/else to avoid speculative execution of else branch on Apple M1 with apple clang 13.0.0
776 precision_ = prec;
777 using std::log;
778 ln_precision_ = log(precision_);
779 return *this;
780 }
781 abort();
782 }
785 scalar_type precision() const { return precision_; }
786
788 Engine& set(ScreeningMethod screening_method) { screening_method_ = screening_method; return *this; }
789
791 ScreeningMethod screening_method() const { return screening_method_; }
792
794 CartesianShellNormalization cartesian_shell_normalization() const {
795 return cartesian_shell_normalization_;
796 }
797
801 Engine& set(CartesianShellNormalization norm) {
802 cartesian_shell_normalization_ = norm;
803 return *this;
804 }
805
807 scalar_type prescaled_by() const {
808 return scale_;
809 }
810
814 Engine& prescale_by(scalar_type sc) {
815 scale_ = sc;
816 return *this;
817 }
818
820 void print_timers(std::ostream& os = std::cout) {
821#ifdef LIBINT2_ENGINE_TIMERS
822 os << "timers: prereq = " << timers.read(0);
823#ifndef LIBINT2_PROFILE // if libint's profiling was on, engine's build timer
824 // will include its overhead
825 // do not report it, detailed profiling from libint will be printed below
826 os << " build = " << timers.read(1);
827#endif
828 os << " tform = " << timers.read(2) << std::endl;
829#endif
830#ifdef LIBINT2_PROFILE
831 os << "build timers: hrr = " << primdata_[0].timers->read(0)
832 << " vrr = " << primdata_[0].timers->read(1) << std::endl;
833#endif
834#ifdef LIBINT2_ENGINE_TIMERS
835#ifdef LIBINT2_ENGINE_PROFILE_CLASS
836 for (const auto& p : class_profiles) {
837 char buf[1024];
838 std::snprintf(buf, sizeof(buf), "{\"%s\", %10.5lf, %10.5lf, %10.5lf, %10.5lf, %ld, %ld},",
839 p.first.to_string().c_str(), p.second.prereqs, p.second.build_vrr,
840 p.second.build_hrr, p.second.tform, p.second.nshellset,
841 p.second.nprimset);
842 os << buf << std::endl;
843 }
844#endif
845#endif
846 }
847
849 class lmax_exceeded : virtual public std::logic_error {
850 public:
851 lmax_exceeded(const char* task_name, size_t lmax_limit,
852 size_t lmax_requested)
853 : std::logic_error(
854 "Engine::lmax_exceeded -- angular momentum limit exceeded"),
855 lmax_limit_(lmax_limit),
856 lmax_requested_(lmax_requested) {
857 strncpy(task_name_, task_name, 64);
858 task_name_[64] = '\0';
859 }
860 ~lmax_exceeded() noexcept {}
861
862 const char* task_name() const {
863 return static_cast<const char*>(task_name_);
864 }
865 size_t lmax_limit() const { return lmax_limit_; }
866 size_t lmax_requested() const { return lmax_requested_; }
867
868 private:
869 char task_name_[65];
870 size_t lmax_limit_;
871 size_t lmax_requested_;
872 };
873
875 class using_default_initialized : virtual public std::logic_error {
876 public:
877 using_default_initialized()
878 : std::logic_error(
879 "Engine::using_default_initialized -- attempt to use a default-initialized Engine") {
880 }
881 ~using_default_initialized() noexcept {}
882 };
883
884 private:
885 Operator oper_;
886 BraKet braket_;
887 std::vector<Libint_t> primdata_;
888 ShellPair spbra_, spket_;
889 size_t stack_size_; // amount allocated by libint2_init_xxx in
890 // primdata_[0].stack
891 int lmax_;
892 int hard_lmax_; // max L supported by library for this operator type (i.e. LIBINT2_MAX_AM_<task><deriv_order>) + 1
893 int hard_default_lmax_; // max L supported by library for default operator type
894 // (i.e. LIBINT2_MAX_AM_default<deriv_order>) + 1
895 // this is only set and used if LIBINT2_CENTER_DEPENDENT_MAX_AM_<task><deriv_order> == 1
896 int deriv_order_;
897 scalar_type precision_;
898 scalar_type ln_precision_;
899 ScreeningMethod screening_method_ = ScreeningMethod::Invalid;
900
901 // specifies the normalization convention for Cartesian Gaussians
902 CartesianShellNormalization cartesian_shell_normalization_;
903
904 // the target integrals are scaled by this factor (of course it is actually the core integrals that are scaled)
905 scalar_type scale_;
906
907 any core_eval_pack_;
908
910 any params_; // operator params
915 any core_ints_params_;
917 void init_core_ints_params(const any& params);
918
921 target_ptr_vec targets_;
924 bool set_targets_;
925
926 std::vector<value_type>
927 scratch_; // for transposes and/or transforming to solid harmonics
928 value_type* scratch2_; // &scratch_[0] points to the first block large enough to
929 // hold all target ints
930 // scratch2_ points to second such block. It could point into scratch_ or at
931 // primdata_[0].stack
932 typedef void (*buildfnptr_t)(const Libint_t*);
933 buildfnptr_t* buildfnptrs_;
934
936 unsigned int compute_nshellsets() const {
937 const unsigned int num_operator_geometrical_derivatives =
938 (oper_ == Operator::nuclear || oper_ == Operator::erf_nuclear ||
939 oper_ == Operator::erfc_nuclear)
940 ? this->nparams()
941 : 0;
942 const auto ncenters = braket_rank() + num_operator_geometrical_derivatives;
943 return nopers() * num_geometrical_derivatives(ncenters, deriv_order_);
944 }
945
946 void reset_scratch() {
947 const auto nshsets = compute_nshellsets();
948 targets_.resize(nshsets);
949 set_targets_ = (&targets_[0] != const_cast<const value_type**>(primdata_[0].targets));
950 const auto ncart_max = (lmax_ + 1) * (lmax_ + 2) / 2;
951 const auto target_shellset_size =
952 nshsets * std::pow(ncart_max, braket_rank());
953 // need to be able to hold 2 sets of target shellsets: the worst case occurs
954 // when dealing with
955 // 1-body Coulomb ints derivatives ... have 2+natom 1st-order derivative sets
956 // (and many more of 2nd and higher) that are stored in scratch
957 // then need to transform to solids. To avoid copying back and forth make
958 // sure that there is enough
959 // room to transform all ints and save them in correct order in single pass
960 const auto need_extra_large_scratch = stack_size_ < target_shellset_size;
961 scratch_.resize(need_extra_large_scratch ? 2 * target_shellset_size
962 : target_shellset_size);
963 scratch2_ = need_extra_large_scratch ? &scratch_[target_shellset_size]
964 : primdata_[0].stack;
965 }
966
967 __libint2_engine_inline void compute_primdata(Libint_t& primdata,
968 const Shell& s1,
969 const Shell& s2, size_t p1,
970 size_t p2, size_t oset);
971
972public:
976 __libint2_engine_inline const std::vector<Engine::compute2_ptr_type>&
977 compute2_ptrs() const;
978
979private:
980 // max_nprim=0 avoids resizing primdata_
981 __libint2_engine_inline void initialize(size_t max_nprim = 0);
982 // generic _initializer
983 __libint2_engine_inline void _initialize();
984
985 void finalize() {
986 if (primdata_.size() != 0) {
987 libint2_cleanup_default(&primdata_[0]);
988 }
989 } // finalize()
990
991 //-------
992 // utils
993 //-------
994 unsigned int nparams() const;
995 unsigned int nopers() const;
1002 template <typename Params>
1003 static any enforce_params_type(
1004 Operator oper, const Params& params,
1005 bool throw_if_wrong_type = !std::is_same<Params, empty_pod>::value);
1008 any make_core_eval_pack(Operator oper) const;
1009
1010 //-------
1011 // profiling
1012 //-------
1013 static const bool skip_core_ints = false;
1014}; // struct Engine
1015
1016
1017} // namespace libint2
1018
1019#ifndef LIBINT2_DOES_NOT_INLINE_ENGINE
1020#include "./engine.impl.h"
1021#endif
1022
1023#endif /* _libint2_src_lib_libint_engine_h_ */
1024
Computes the Boys function, $ F_m (T) = \int_0^1 u^{2m} \exp(-T u^2) \, {\rm d}u $,...
Definition: boys.h:245
a partial C++17 std::any implementation (and less efficient than can be)
Definition: any.h:67
Array idential to C++0X arrays.
Definition: stdarray_bits.h:14
Defaults definitions for various parameters assumed by Libint.
Definition: algebra.cc:24
ScreeningMethod
describes method for primitive screening used by ShellPair and Engine
Definition: shell.h:357
void initialize(bool verbose=false)
initializes the libint library if not currently initialized, no-op otherwise
Definition: initialize.h:70
CartesianShellNormalization
Normalization convention for Cartesian Gaussian shells.
Definition: cgshellinfo.h:31
BraKet
types of shell sets supported by Engine, in chemist notation (i.e.
Definition: include/libint2/braket.h:36
void finalize()
finalizes the libint library.
Definition: initialize.h:90
__libint2_engine_inline libint2::any default_params(const Operator &oper)
the runtime version of operator_traits<oper>::default_params()
Definition: engine.impl.h:111
Computes the Boys function, , using single algorithm (asymptotic expansion).
Definition: boys.h:142
Definition: boys.h:1351
Definition: boys_fwd.h:50
generally-contracted Solid-Harmonic/Cartesion Gaussian Shell
Definition: shell.h:81
core integral for Yukawa and exponential interactions
Definition: boys.h:832
some evaluators need thread-local scratch, but most don't
Definition: boys.h:1356