21#ifndef _libint2_src_lib_libint_engine_h_
22#define _libint2_src_lib_libint_engine_h_
24#ifndef LIBINT2_DOES_NOT_INLINE_ENGINE
25#define __libint2_engine_inline inline
27#define __libint2_engine_inline
30#include <libint2/util/cxxstd.h>
31#if LIBINT2_CPLUSPLUS_STD < 2011
32#error "libint2/engine.h requires C++11 support"
35#include <libint2/boys_fwd.h>
36#include <libint2/braket.h>
37#include <libint2/cartesian.h>
38#include <libint2/cgshellinfo.h>
39#include <libint2/cxxapi.h>
40#include <libint2/shell.h>
41#include <libint2/solidharmonics.h>
42#include <libint2/util/any.h>
43#include <libint2/util/array_adaptor.h>
44#include <libint2/util/compressed_pair.h>
45#include <libint2/util/intpart_iter.h>
46#include <libint2/util/timer.h>
64#define LIBINT2_ENGINE_TIMERS
66#define LIBINT2_ENGINE_PROFILE_CLASS
77typedef std::vector<std::pair<double, double>> ContractedGaussianGeminal;
79constexpr size_t num_geometrical_derivatives(
size_t ncenter,
81 return (deriv_order > 0)
82 ? (num_geometrical_derivatives(ncenter, deriv_order - 1) *
83 (3 * ncenter + deriv_order - 1)) /
88template <
typename T,
unsigned N>
89__libint2_engine_inline
90 typename std::remove_all_extents<T>::type* to_ptr1(T (&a)[N]);
173 yukawa = stg_x_coulomb,
178 first_1body_oper = overlap,
179 last_1body_oper = opVop,
180 first_2body_oper = delta,
181 last_2body_oper = stg_x_coulomb,
182 first_oper = first_1body_oper,
183 last_oper = last_2body_oper
189inline constexpr int rank(Operator oper) {
190 return (oper >= Operator::first_1body_oper &&
191 oper <= Operator::last_1body_oper)
193 : ((oper >= Operator::first_2body_oper &&
194 oper <= Operator::last_2body_oper)
196 : throw std::logic_error(
197 "rank(Operator): invalid operator given"));
201struct default_operator_traits {
204 static oper_params_type
default_params() {
return oper_params_type{}; }
205 static constexpr auto nopers = 1u;
208 static constexpr auto intrinsic_deriv_order = 0u;
209 struct _core_eval_type {
210 template <
typename... params>
211 static std::shared_ptr<const _core_eval_type> instance(params...) {
215 using core_eval_type =
const _core_eval_type;
224template <Operator Op>
225struct operator_traits :
public detail::default_operator_traits {};
228struct operator_traits<Operator::nuclear>
229 :
public detail::default_operator_traits {
231 typedef std::vector<std::pair<scalar_type, std::array<scalar_type, 3>>>
233 static oper_params_type
default_params() {
return oper_params_type{}; }
234#ifndef LIBINT_USER_DEFINED_REAL
241struct operator_traits<Operator::opVop>
242 :
public operator_traits<Operator::nuclear> {
243 static constexpr auto nopers = 4;
244 static constexpr auto intrinsic_deriv_order = 2;
248struct operator_traits<Operator::erf_nuclear>
249 :
public detail::default_operator_traits {
252 typedef std::tuple<scalar_type,
typename operator_traits<
253 Operator::nuclear>::oper_params_type>
256 return std::make_tuple(
257 0, operator_traits<Operator::nuclear>::default_params());
265struct operator_traits<Operator::erfc_nuclear>
266 :
public detail::default_operator_traits {
269 typedef typename operator_traits<Operator::erf_nuclear>::oper_params_type
272 return std::make_tuple(
273 0, operator_traits<Operator::nuclear>::default_params());
281struct operator_traits<Operator::emultipole1>
282 :
public detail::default_operator_traits {
285 typedef std::array<double, 3> oper_params_type;
287 return oper_params_type{{0, 0, 0}};
289 static constexpr auto nopers = 4u;
292struct operator_traits<Operator::emultipole2>
293 :
public operator_traits<Operator::emultipole1> {
294 static constexpr auto nopers =
295 operator_traits<Operator::emultipole1>::nopers +
299struct operator_traits<Operator::emultipole3>
300 :
public operator_traits<Operator::emultipole1> {
301 static constexpr auto nopers =
302 operator_traits<Operator::emultipole2>::nopers + 10;
305struct operator_traits<Operator::sphemultipole>
306 :
public operator_traits<Operator::emultipole1> {
307 static constexpr auto nopers =
308 (MULTIPOLE_MAX_ORDER + 1) * (MULTIPOLE_MAX_ORDER + 1);
312struct operator_traits<Operator::coulomb>
313 :
public detail::default_operator_traits {
314#ifndef LIBINT_USER_DEFINED_REAL
322struct cgtg_operator_traits :
public detail::default_operator_traits {
324 typedef ContractedGaussianGeminal oper_params_type;
328struct operator_traits<Operator::cgtg>
329 :
public detail::cgtg_operator_traits<0> {};
331struct operator_traits<Operator::cgtg_x_coulomb>
332 :
public detail::cgtg_operator_traits<-1> {};
334struct operator_traits<Operator::delcgtg2>
335 :
public detail::cgtg_operator_traits<2> {};
338struct operator_traits<Operator::delta>
339 :
public detail::default_operator_traits {
346struct operator_traits<Operator::r12> :
public detail::default_operator_traits {
353struct operator_traits<Operator::erf_coulomb>
354 :
public detail::default_operator_traits {
356 typedef scalar_type oper_params_type;
357 static oper_params_type
default_params() {
return oper_params_type{0}; }
363struct operator_traits<Operator::erfc_coulomb>
364 :
public detail::default_operator_traits {
366 typedef scalar_type oper_params_type;
367 static oper_params_type
default_params() {
return oper_params_type{0}; }
374struct operator_traits<Operator::stg> :
public detail::default_operator_traits {
376 typedef scalar_type oper_params_type;
377 static oper_params_type
default_params() {
return oper_params_type{0}; }
382struct operator_traits<Operator::stg_x_coulomb>
383 :
public detail::default_operator_traits {
385 typedef scalar_type oper_params_type;
386 static oper_params_type
default_params() {
return oper_params_type{0}; }
394template <
typename core_eval_type>
395using __core_eval_pack_type =
396 compressed_pair<std::shared_ptr<core_eval_type>,
398template <Operator Op>
399using core_eval_pack_type =
400 __core_eval_pack_type<typename operator_traits<Op>::core_eval_type>;
403#define BOOST_PP_NBODY_BRAKET_MAX_INDEX 4
408inline constexpr int rank(BraKet braket) {
409 return (braket == BraKet::x_x || braket == BraKet::xs_xs)
411 : ((braket == BraKet::xs_xx || braket == BraKet::xx_xs)
413 : ((braket == BraKet::xx_xx)
415 : throw std::logic_error(
416 "rank(BraKet): invalid braket given")));
422inline constexpr BraKet default_braket(Operator oper) {
423 return (rank(oper) == 1)
427 : throw std::logic_error(
428 "default_braket(Operator): invalid operator given"));
431constexpr size_t nopers_2body =
static_cast<int>(Operator::last_2body_oper) -
432 static_cast<int>(Operator::first_2body_oper) +
434constexpr size_t nbrakets_2body =
static_cast<int>(BraKet::last_2body_braket) -
435 static_cast<int>(BraKet::first_2body_braket) +
437constexpr size_t nderivorders_2body = LIBINT2_MAX_DERIV_ORDER + 1;
450 static constexpr auto max_ntargets =
451 std::extent<decltype(std::declval<Libint_t>().targets), 0>::value;
452 using target_ptr_vec =
453 std::vector<
const value_type*,
454 detail::ext_stack_allocator<const value_type*, max_ntargets>>;
461 : oper_(Operator::invalid),
462 braket_(BraKet::invalid),
469 set_precision(std::numeric_limits<scalar_type>::epsilon());
502 template <
typename Params = empty_pod>
503 Engine(Operator oper,
size_t max_nprim,
int max_l,
int deriv_order = 0,
504 scalar_type precision = std::numeric_limits<scalar_type>::epsilon(),
505 Params params = empty_pod(), BraKet braket = BraKet::invalid,
506 ScreeningMethod screening_method = default_screening_method())
514 deriv_order_(deriv_order),
515 screening_method_(screening_method),
518 params_(enforce_params_type(oper, params)) {
519 set_precision(precision);
520 assert(max_nprim > 0);
522 core_eval_pack_ = make_core_eval_pack(oper);
525 init_core_ints_params(params_);
530 Engine(Engine&& other)
531 : oper_(other.oper_),
532 braket_(other.braket_),
533 primdata_(std::move(other.primdata_)),
534 spbra_(std::move(other.spbra_)),
535 spket_(std::move(other.spket_)),
536 stack_size_(other.stack_size_),
538 hard_lmax_(other.hard_lmax_),
539 hard_default_lmax_(other.hard_default_lmax_),
540 deriv_order_(other.deriv_order_),
541 precision_(other.precision_),
542 ln_precision_(other.ln_precision_),
543 screening_method_(other.screening_method_),
544 cartesian_shell_normalization_(other.cartesian_shell_normalization_),
545 scale_(other.scale_),
546 core_eval_pack_(std::move(other.core_eval_pack_)),
547 params_(std::move(other.params_)),
548 core_ints_params_(std::move(other.core_ints_params_)),
549 targets_(std::move(other.targets_)),
550 set_targets_(other.set_targets_),
551 scratch_(std::move(other.scratch_)),
552 scratch2_(other.scratch2_),
553 buildfnptrs_(other.buildfnptrs_) {
555 other.oper_ = Operator::invalid;
556 other.braket_ = BraKet::invalid;
557 other.scratch2_ =
nullptr;
561 Engine(
const Engine& other)
562 : oper_(other.oper_),
563 braket_(other.braket_),
564 primdata_(other.primdata_.size()),
565 spbra_(other.spbra_),
566 spket_(other.spket_),
567 stack_size_(other.stack_size_),
569 deriv_order_(other.deriv_order_),
570 precision_(other.precision_),
571 ln_precision_(other.ln_precision_),
572 screening_method_(other.screening_method_),
573 cartesian_shell_normalization_(other.cartesian_shell_normalization_),
574 scale_(other.scale_),
575 core_eval_pack_(other.core_eval_pack_),
576 params_(other.params_),
577 core_ints_params_(other.core_ints_params_) {
584 Engine& operator=(Engine&& other) {
586 braket_ = other.braket_;
587 primdata_ = std::move(other.primdata_);
588 spbra_ = std::move(other.spbra_);
589 spket_ = std::move(other.spket_);
590 stack_size_ = other.stack_size_;
592 hard_lmax_ = other.hard_lmax_;
593 hard_default_lmax_ = other.hard_default_lmax_;
594 deriv_order_ = other.deriv_order_;
595 precision_ = other.precision_;
596 ln_precision_ = other.ln_precision_;
597 screening_method_ = other.screening_method_;
598 cartesian_shell_normalization_ = other.cartesian_shell_normalization_;
599 scale_ = other.scale_;
600 core_eval_pack_ = std::move(other.core_eval_pack_);
601 params_ = std::move(other.params_);
602 core_ints_params_ = std::move(other.core_ints_params_);
603 targets_ = std::move(other.targets_);
604 set_targets_ = other.set_targets_;
605 scratch_ = std::move(other.scratch_);
606 scratch2_ = other.scratch2_;
607 buildfnptrs_ = other.buildfnptrs_;
609 other.oper_ = Operator::invalid;
610 other.braket_ = BraKet::invalid;
611 other.scratch2_ =
nullptr;
616 Engine& operator=(
const Engine& other) {
618 braket_ = other.braket_;
619 primdata_.resize(other.primdata_.size());
620 spbra_ = other.spbra_;
621 spket_ = other.spket_;
622 stack_size_ = other.stack_size_;
624 deriv_order_ = other.deriv_order_;
625 precision_ = other.precision_;
626 ln_precision_ = other.ln_precision_;
627 screening_method_ = other.screening_method_;
628 cartesian_shell_normalization_ = other.cartesian_shell_normalization_;
629 scale_ = other.scale_;
630 core_eval_pack_ = other.core_eval_pack_;
631 params_ = other.params_;
632 core_ints_params_ = other.core_ints_params_;
638 int operator_rank()
const {
return rank(oper_); }
641 int braket_rank()
const {
return rank(braket_); }
644 Operator oper()
const {
return oper_; }
647 BraKet braket()
const {
return braket_; }
650 int deriv_order()
const {
return deriv_order_; }
657 Engine& set(Operator new_oper) {
658 if (oper_ != new_oper) {
660 braket_ = default_braket(oper_);
663 core_eval_pack_ = make_core_eval_pack(oper_);
673 Engine& set(BraKet new_braket) {
674 if (braket_ != new_braket) {
675 braket_ = new_braket;
684 template <
typename Params>
685 Engine& set_params(
const Params& params) {
687 init_core_ints_params(params_);
693 std::size_t max_nprim()
const {
694 assert(spbra_.primpairs.size() == spket_.primpairs.size());
695 return static_cast<std::size_t
>(std::sqrt(spbra_.primpairs.size()));
702 Engine& set_max_nprim(std::size_t n) {
703 if (n * n > spbra_.primpairs.size()) {
712 std::size_t max_l()
const {
return lmax_; }
718 Engine& set_max_l(std::size_t L) {
719 if (L >=
static_cast<std::size_t
>(lmax_)) {
731 const target_ptr_vec& results()
const {
return targets_; }
736 unsigned int nshellsets()
const {
return targets_.size(); }
747 template <
typename... ShellPack>
748 __libint2_engine_inline
const target_ptr_vec& compute(
749 const libint2::Shell& first_shell,
const ShellPack&... rest_of_shells);
757 __libint2_engine_inline
const target_ptr_vec& compute1(
787 template <Operator oper, BraKet braket,
size_t deriv_order>
788 __libint2_engine_inline
const target_ptr_vec& compute2(
789 const Shell& bra1,
const Shell& bra2,
const Shell& ket1,
790 const Shell& ket2,
const ShellPair* spbra =
nullptr,
791 const ShellPair* spket =
nullptr);
793 typedef const target_ptr_vec& (Engine::*compute2_ptr_type)(
794 const Shell& bra1,
const Shell& bra2,
const Shell& ket1,
795 const Shell& ket2,
const ShellPair* spbra,
const ShellPair* spket);
809 Engine& set_precision(scalar_type prec) {
812 ln_precision_ = std::numeric_limits<scalar_type>::lowest();
819 ln_precision_ = log(precision_);
826 scalar_type precision()
const {
return precision_; }
829 Engine& set(ScreeningMethod screening_method) {
830 screening_method_ = screening_method;
839 return cartesian_shell_normalization_;
845 Engine& set(CartesianShellNormalization norm) {
846 cartesian_shell_normalization_ = norm;
851 scalar_type prescaled_by()
const {
return scale_; }
857 Engine& prescale_by(scalar_type sc) {
863 void print_timers(std::ostream& os = std::cout) {
864#ifdef LIBINT2_ENGINE_TIMERS
865 os <<
"timers: prereq = " << timers.read(0);
866#ifndef LIBINT2_PROFILE
869 os <<
" build = " << timers.read(1);
871 os <<
" tform = " << timers.read(2) << std::endl;
873#ifdef LIBINT2_PROFILE
874 os <<
"build timers: hrr = " << primdata_[0].timers->read(0)
875 <<
" vrr = " << primdata_[0].timers->read(1) << std::endl;
877#ifdef LIBINT2_ENGINE_TIMERS
878#ifdef LIBINT2_ENGINE_PROFILE_CLASS
879 for (
const auto& p : class_profiles) {
881 std::snprintf(buf,
sizeof(buf),
882 "{\"%s\", %10.5lf, %10.5lf, %10.5lf, %10.5lf, %ld, %ld},",
883 p.first.to_string().c_str(), p.second.prereqs,
884 p.second.build_vrr, p.second.build_hrr, p.second.tform,
885 p.second.nshellset, p.second.nprimset);
886 os << buf << std::endl;
893 class lmax_exceeded :
virtual public std::logic_error {
895 lmax_exceeded(
const char* task_name,
size_t lmax_limit,
896 size_t lmax_requested)
898 "Engine::lmax_exceeded -- angular momentum limit exceeded"),
899 lmax_limit_(lmax_limit),
900 lmax_requested_(lmax_requested) {
901 strncpy(task_name_, task_name, 64);
902 task_name_[64] =
'\0';
904 ~lmax_exceeded() noexcept {}
906 const char* task_name()
const {
907 return static_cast<const char*
>(task_name_);
909 size_t lmax_limit()
const {
return lmax_limit_; }
910 size_t lmax_requested()
const {
return lmax_requested_; }
915 size_t lmax_requested_;
919 class using_default_initialized :
virtual public std::logic_error {
921 using_default_initialized()
923 "Engine::using_default_initialized -- attempt to use a "
924 "default-initialized Engine") {}
925 ~using_default_initialized() noexcept {}
931 std::vector<Libint_t> primdata_;
932 ShellPair spbra_, spket_;
938 int hard_default_lmax_;
944 scalar_type precision_;
945 scalar_type ln_precision_;
963 any core_ints_params_;
965 void init_core_ints_params(
const any& params);
969 target_ptr_vec targets_;
974 std::vector<value_type>
976 value_type* scratch2_;
980 typedef void (*buildfnptr_t)(
const Libint_t*);
981 buildfnptr_t* buildfnptrs_;
984 unsigned int compute_nshellsets()
const {
985 const unsigned int num_operator_geometrical_derivatives =
986 (oper_ == Operator::nuclear || oper_ == Operator::erf_nuclear ||
987 oper_ == Operator::erfc_nuclear)
990 const auto ncenters = braket_rank() + num_operator_geometrical_derivatives;
991 return nopers() * num_geometrical_derivatives(ncenters, deriv_order_);
994 void reset_scratch() {
995 const auto nshsets = compute_nshellsets();
996 targets_.resize(nshsets);
998 (&targets_[0] !=
const_cast<const value_type**
>(primdata_[0].targets));
999 const auto ncart_max = (lmax_ + 1) * (lmax_ + 2) / 2;
1000 const auto target_shellset_size =
1001 nshsets * std::pow(ncart_max, braket_rank());
1009 const auto need_extra_large_scratch = stack_size_ < target_shellset_size;
1010 scratch_.resize(need_extra_large_scratch ? 2 * target_shellset_size
1011 : target_shellset_size);
1012 scratch2_ = need_extra_large_scratch ? &scratch_[target_shellset_size]
1013 : primdata_[0].stack;
1016 __libint2_engine_inline
void compute_primdata(Libint_t& primdata,
1018 const Shell& s2,
size_t p1,
1019 size_t p2,
size_t oset);
1025 __libint2_engine_inline
const std::vector<Engine::compute2_ptr_type>&
1026 compute2_ptrs()
const;
1030 __libint2_engine_inline
void initialize(
size_t max_nprim = 0);
1032 __libint2_engine_inline
void _initialize();
1035 if (primdata_.size() != 0) {
1036 libint2_cleanup_default(&primdata_[0]);
1043 unsigned int nparams()
const;
1044 unsigned int nopers()
const;
1045 unsigned int intrinsic_deriv_order()
const;
1052 template <
typename Params>
1053 static any enforce_params_type(
1054 Operator oper,
const Params& params,
1055 bool throw_if_wrong_type = !std::is_same<Params, empty_pod>::value);
1058 any make_core_eval_pack(Operator oper)
const;
1063 static const bool skip_core_ints =
false;
1068#ifndef LIBINT2_DOES_NOT_INLINE_ENGINE
1069#include "./engine.impl.h"
Computes the Boys function, $ F_m (T) = \int_0^1 u^{2m} \exp(-T u^2) \, {\rm d}u $,...
Definition boys.h:253
a partial C++17 std::any implementation (and less efficient than can be)
Definition any.h:67
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:1041
void initialize(bool verbose=false)
initializes the libint library if not currently initialized, no-op otherwise
Definition initialize.h:76
CartesianShellNormalization
Normalization convention for Cartesian Gaussian shells.
Definition cgshellinfo.h:31
void finalize()
finalizes the libint library.
Definition initialize.h:105
__libint2_engine_inline libint2::any default_params(const Operator &oper)
the runtime version of operator_traits<oper>::default_params()
Definition engine.impl.h:116
Computes the Boys function, , using single algorithm (asymptotic expansion).
Definition boys.h:144
generally-contracted Solid-Harmonic/Cartesion Gaussian Shell
Definition shell.h:720
core integral for Yukawa and exponential interactions
Definition boys.h:901
some evaluators need thread-local scratch, but most don't
Definition boys.h:1564