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"
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>
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
typename std::remove_all_extents<T>::type* to_ptr1(T (&a)[N]);
158 yukawa = stg_x_coulomb,
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
173inline constexpr int rank(Operator oper) {
174 return (oper >= Operator::first_1body_oper &&
175 oper <= Operator::last_1body_oper)
177 ((oper >= Operator::first_2body_oper &&
178 oper <= Operator::last_2body_oper)
179 ? 2 :
throw std::logic_error(
"rank(Operator): invalid operator given"));
183struct default_operator_traits {
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...) {
194 using core_eval_type =
const _core_eval_type;
203template <Operator Op>
204struct operator_traits :
public detail::default_operator_traits {};
207struct operator_traits<Operator::nuclear>
208 :
public detail::default_operator_traits {
210 typedef std::vector<std::pair<scalar_type, std::array<scalar_type, 3>>>
212 static oper_params_type
default_params() {
return oper_params_type{}; }
213#ifndef LIBINT_USER_DEFINED_REAL
221struct operator_traits<Operator::erf_nuclear>
222 :
public detail::default_operator_traits {
226 scalar_type,
typename operator_traits<Operator::nuclear>::oper_params_type>
229 return std::make_tuple(0,operator_traits<Operator::nuclear>::default_params());
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;
242 return std::make_tuple(0,operator_traits<Operator::nuclear>::default_params());
249struct operator_traits<Operator::emultipole1>
250 :
public detail::default_operator_traits {
255 return oper_params_type{{0,0,0}};
257 static constexpr auto nopers = 4u;
260struct operator_traits<Operator::emultipole2>
261 :
public operator_traits<Operator::emultipole1> {
262 static constexpr auto nopers =
263 operator_traits<Operator::emultipole1>::nopers +
267struct operator_traits<Operator::emultipole3>
268 :
public operator_traits<Operator::emultipole1> {
269 static constexpr auto nopers =
270 operator_traits<Operator::emultipole2>::nopers + 10;
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);
280struct operator_traits<Operator::coulomb>
281 :
public detail::default_operator_traits {
282#ifndef LIBINT_USER_DEFINED_REAL
290struct cgtg_operator_traits :
public detail::default_operator_traits {
292 typedef ContractedGaussianGeminal oper_params_type;
296struct operator_traits<Operator::cgtg>
297 :
public detail::cgtg_operator_traits<0> {};
299struct operator_traits<Operator::cgtg_x_coulomb>
300 :
public detail::cgtg_operator_traits<-1> {};
302struct operator_traits<Operator::delcgtg2>
303 :
public detail::cgtg_operator_traits<2> {};
306struct operator_traits<Operator::delta>
307 :
public detail::default_operator_traits {
313struct operator_traits<Operator::r12>
314 :
public detail::default_operator_traits {
320struct operator_traits<Operator::erf_coulomb>
321 :
public detail::default_operator_traits {
323 typedef scalar_type oper_params_type;
325 return oper_params_type{0};
331struct operator_traits<Operator::erfc_coulomb>
332 :
public detail::default_operator_traits {
334 typedef scalar_type oper_params_type;
336 return oper_params_type{0};
343struct operator_traits<Operator::stg>
344 :
public detail::default_operator_traits {
346 typedef scalar_type oper_params_type;
348 return oper_params_type{0};
355struct operator_traits<Operator::stg_x_coulomb>
356 :
public detail::default_operator_traits {
358 typedef scalar_type oper_params_type;
360 return oper_params_type{0};
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>;
380#define BOOST_PP_NBODY_BRAKET_MAX_INDEX 4
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")));
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"));
399constexpr size_t nopers_2body =
static_cast<int>(Operator::last_2body_oper) -
400 static_cast<int>(Operator::first_2body_oper) +
402constexpr size_t nbrakets_2body =
static_cast<int>(BraKet::last_2body_braket) -
403 static_cast<int>(BraKet::first_2body_braket) +
405constexpr size_t nderivorders_2body = LIBINT2_MAX_DERIV_ORDER + 1;
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>>;
429 : oper_(Operator::invalid),
437 set_precision(std::numeric_limits<scalar_type>::epsilon());
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,
482 deriv_order_(deriv_order),
483 screening_method_(screening_method),
486 params_(enforce_params_type(oper, params)) {
487 set_precision(precision);
488 assert(max_nprim > 0);
490 core_eval_pack_ = make_core_eval_pack(oper);
493 init_core_ints_params(params_);
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_),
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_) {
523 other.oper_ = Operator::invalid;
524 other.braket_ = BraKet::invalid;
525 other.scratch2_ =
nullptr;
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_),
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_) {
552 Engine& operator=(Engine&& other) {
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_;
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_;
577 other.oper_ = Operator::invalid;
578 other.braket_ = BraKet::invalid;
579 other.scratch2_ =
nullptr;
584 Engine& operator=(
const Engine& other) {
586 braket_ = other.braket_;
587 primdata_.resize(other.primdata_.size());
588 spbra_ = other.spbra_;
589 spket_ = other.spket_;
590 stack_size_ = other.stack_size_;
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_;
606 int operator_rank()
const {
return rank(oper_); }
609 int braket_rank()
const {
return rank(braket_); }
612 Operator oper()
const {
return oper_; }
615 BraKet braket()
const {
return braket_; }
618 int deriv_order()
const {
return deriv_order_; }
623 Engine& set(Operator new_oper) {
624 if (oper_ != new_oper) {
626 braket_ = default_braket(oper_);
629 core_eval_pack_ = make_core_eval_pack(oper_);
638 Engine& set(
BraKet new_braket) {
639 if (braket_ != new_braket) {
640 braket_ = new_braket;
649 template <
typename Params>
650 Engine& set_params(
const Params& params) {
652 init_core_ints_params(params_);
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()));
666 Engine& set_max_nprim(std::size_t n) {
667 if (n*n > spbra_.primpairs.size()) {
676 std::size_t max_l()
const {
683 Engine& set_max_l(std::size_t L) {
684 if (L >=
static_cast<std::size_t
>(lmax_)) {
696 const target_ptr_vec& results()
const {
return targets_; }
701 unsigned int nshellsets()
const {
return targets_.size(); }
709 template <
typename... ShellPack>
710 __libint2_engine_inline
const target_ptr_vec& compute(
711 const libint2::Shell& first_shell,
const ShellPack&... rest_of_shells);
718 __libint2_engine_inline
const target_ptr_vec& compute1(
742 template <Operator oper, BraKet braket,
size_t deriv_order>
743 __libint2_engine_inline
const target_ptr_vec& compute2(
const Shell& bra1,
747 const ShellPair* spbra =
nullptr,
748 const ShellPair* spket =
nullptr);
750 typedef const target_ptr_vec& (Engine::*compute2_ptr_type)(
const Shell& bra1,
754 const ShellPair* spbra,
755 const ShellPair* spket);
769 Engine& set_precision(scalar_type prec) {
772 ln_precision_ = std::numeric_limits<scalar_type>::lowest();
778 ln_precision_ = log(precision_);
785 scalar_type precision()
const {
return precision_; }
788 Engine& set(
ScreeningMethod screening_method) { screening_method_ = screening_method;
return *
this; }
795 return cartesian_shell_normalization_;
802 cartesian_shell_normalization_ = norm;
807 scalar_type prescaled_by()
const {
814 Engine& prescale_by(scalar_type sc) {
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
826 os <<
" build = " << timers.read(1);
828 os <<
" tform = " << timers.read(2) << std::endl;
830#ifdef LIBINT2_PROFILE
831 os <<
"build timers: hrr = " << primdata_[0].timers->read(0)
832 <<
" vrr = " << primdata_[0].timers->read(1) << std::endl;
834#ifdef LIBINT2_ENGINE_TIMERS
835#ifdef LIBINT2_ENGINE_PROFILE_CLASS
836 for (
const auto& p : class_profiles) {
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,
842 os << buf << std::endl;
849 class lmax_exceeded :
virtual public std::logic_error {
851 lmax_exceeded(
const char* task_name,
size_t lmax_limit,
852 size_t lmax_requested)
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';
860 ~lmax_exceeded() noexcept {}
862 const char* task_name()
const {
863 return static_cast<const char*
>(task_name_);
865 size_t lmax_limit()
const {
return lmax_limit_; }
866 size_t lmax_requested()
const {
return lmax_requested_; }
871 size_t lmax_requested_;
875 class using_default_initialized :
virtual public std::logic_error {
877 using_default_initialized()
879 "Engine::using_default_initialized -- attempt to use a default-initialized Engine") {
881 ~using_default_initialized() noexcept {}
887 std::vector<Libint_t> primdata_;
888 ShellPair spbra_, spket_;
893 int hard_default_lmax_;
897 scalar_type precision_;
898 scalar_type ln_precision_;
915 any core_ints_params_;
917 void init_core_ints_params(
const any& params);
921 target_ptr_vec targets_;
926 std::vector<value_type>
928 value_type* scratch2_;
932 typedef void (*buildfnptr_t)(
const Libint_t*);
933 buildfnptr_t* buildfnptrs_;
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)
942 const auto ncenters = braket_rank() + num_operator_geometrical_derivatives;
943 return nopers() * num_geometrical_derivatives(ncenters, deriv_order_);
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());
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;
967 __libint2_engine_inline
void compute_primdata(Libint_t& primdata,
969 const Shell& s2,
size_t p1,
970 size_t p2,
size_t oset);
976 __libint2_engine_inline
const std::vector<Engine::compute2_ptr_type>&
977 compute2_ptrs()
const;
981 __libint2_engine_inline
void initialize(
size_t max_nprim = 0);
983 __libint2_engine_inline
void _initialize();
986 if (primdata_.size() != 0) {
987 libint2_cleanup_default(&primdata_[0]);
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;
1013 static const bool skip_core_ints =
false;
1019#ifndef LIBINT2_DOES_NOT_INLINE_ENGINE
1020#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: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_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