LIBINT 2.9.0
engine.h
1/*
2 * Copyright (C) 2004-2024 Edward F. Valeev
3 *
4 * This file is part of Libint library.
5 *
6 * Libint library 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 library 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 library. 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 <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>
47
48#include <algorithm>
49#include <array>
50#include <cstdio>
51#include <cstring>
52#include <functional>
53#include <iostream>
54#include <limits>
55#include <map>
56#include <memory>
57#include <tuple>
58#include <utility>
59#include <vector>
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
90 typename std::remove_all_extents<T>::type* to_ptr1(T (&a)[N]);
91
93
98enum class Operator {
100 overlap = 0,
102 kinetic,
104 nuclear,
107 erf_nuclear,
110 erfc_nuclear,
115 emultipole1,
118 emultipole2,
121 emultipole3,
142 sphemultipole,
144 opVop,
146 delta,
148 coulomb,
150 r12_m1 = coulomb,
152 cgtg,
154 cgtg_x_coulomb,
156 delcgtg2,
158 r12,
160 r12_1 = r12,
163 erf_coulomb,
166 erfc_coulomb,
168 stg,
171 stg_x_coulomb,
173 yukawa = stg_x_coulomb,
174 // do not modify this
175 invalid = -1,
176 // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!keep this
177 // updated!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
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
184};
185
189inline constexpr int rank(Operator oper) {
190 return (oper >= Operator::first_1body_oper &&
191 oper <= Operator::last_1body_oper)
192 ? 1
193 : ((oper >= Operator::first_2body_oper &&
194 oper <= Operator::last_2body_oper)
195 ? 2
196 : throw std::logic_error(
197 "rank(Operator): invalid operator given"));
198}
199
200namespace detail {
201struct default_operator_traits {
202 typedef struct {
203 } oper_params_type;
204 static oper_params_type default_params() { return oper_params_type{}; }
205 static constexpr auto nopers = 1u;
206 // N.B.: Below field means we *should* template specialize operator_traits for
207 // Operator::kinetic, but L2 doesn't use that anywhere.
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...) {
212 return nullptr;
213 }
214 };
215 using core_eval_type = const _core_eval_type;
216};
217} // namespace detail
218
224template <Operator Op>
225struct operator_traits : public detail::default_operator_traits {};
226
227template <>
228struct operator_traits<Operator::nuclear>
229 : public detail::default_operator_traits {
231 typedef std::vector<std::pair<scalar_type, std::array<scalar_type, 3>>>
232 oper_params_type;
233 static oper_params_type default_params() { return oper_params_type{}; }
234#ifndef LIBINT_USER_DEFINED_REAL
235 typedef const libint2::FmEval_Chebyshev7<scalar_type> core_eval_type;
236#else
237 typedef const libint2::FmEval_Reference<scalar_type> core_eval_type;
238#endif
239};
240template <>
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;
245};
246
247template <>
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>
254 oper_params_type;
255 static oper_params_type default_params() {
256 return std::make_tuple(
257 0, operator_traits<Operator::nuclear>::default_params());
258 }
259 typedef const libint2::GenericGmEval<
261 core_eval_type;
262};
263
264template <>
265struct operator_traits<Operator::erfc_nuclear>
266 : public detail::default_operator_traits {
269 typedef typename operator_traits<Operator::erf_nuclear>::oper_params_type
270 oper_params_type;
271 static oper_params_type default_params() {
272 return std::make_tuple(
273 0, operator_traits<Operator::nuclear>::default_params());
274 }
275 typedef const libint2::GenericGmEval<
277 core_eval_type;
278};
279
280template <>
281struct operator_traits<Operator::emultipole1>
282 : public detail::default_operator_traits {
285 typedef std::array<double, 3> oper_params_type;
286 static oper_params_type default_params() {
287 return oper_params_type{{0, 0, 0}};
288 }
289 static constexpr auto nopers = 4u;
290};
291template <>
292struct operator_traits<Operator::emultipole2>
293 : public operator_traits<Operator::emultipole1> {
294 static constexpr auto nopers =
295 operator_traits<Operator::emultipole1>::nopers +
296 6;
297};
298template <>
299struct operator_traits<Operator::emultipole3>
300 : public operator_traits<Operator::emultipole1> {
301 static constexpr auto nopers =
302 operator_traits<Operator::emultipole2>::nopers + 10;
303};
304template <>
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);
309};
310
311template <>
312struct operator_traits<Operator::coulomb>
313 : public detail::default_operator_traits {
314#ifndef LIBINT_USER_DEFINED_REAL
315 typedef const libint2::FmEval_Chebyshev7<scalar_type> core_eval_type;
316#else
317 typedef const libint2::FmEval_Reference<scalar_type> core_eval_type;
318#endif
319};
320namespace detail {
321template <int K>
322struct cgtg_operator_traits : public detail::default_operator_traits {
323 typedef libint2::GaussianGmEval<scalar_type, K> core_eval_type;
324 typedef ContractedGaussianGeminal oper_params_type;
325};
326} // namespace detail
327template <>
328struct operator_traits<Operator::cgtg>
329 : public detail::cgtg_operator_traits<0> {};
330template <>
331struct operator_traits<Operator::cgtg_x_coulomb>
332 : public detail::cgtg_operator_traits<-1> {};
333template <>
334struct operator_traits<Operator::delcgtg2>
335 : public detail::cgtg_operator_traits<2> {};
336
337template <>
338struct operator_traits<Operator::delta>
339 : public detail::default_operator_traits {
340 typedef const libint2::GenericGmEval<
342 core_eval_type;
343};
344
345template <>
346struct operator_traits<Operator::r12> : public detail::default_operator_traits {
347 typedef const libint2::GenericGmEval<
349 core_eval_type;
350};
351
352template <>
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}; }
358 typedef const libint2::GenericGmEval<
360 core_eval_type;
361};
362template <>
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}; }
368 typedef const libint2::GenericGmEval<
370 core_eval_type;
371};
372
373template <>
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}; }
378 typedef const libint2::TennoGmEval<scalar_type> core_eval_type;
379};
380
381template <>
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}; }
387 typedef const libint2::TennoGmEval<scalar_type> core_eval_type;
388};
389
391libint2::any default_params(const Operator& oper);
392
393namespace detail {
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>;
401} // namespace detail
402
403#define BOOST_PP_NBODY_BRAKET_MAX_INDEX 4
404
408inline constexpr int rank(BraKet braket) {
409 return (braket == BraKet::x_x || braket == BraKet::xs_xs)
410 ? 2
411 : ((braket == BraKet::xs_xx || braket == BraKet::xx_xs)
412 ? 3
413 : ((braket == BraKet::xx_xx)
414 ? 4
415 : throw std::logic_error(
416 "rank(BraKet): invalid braket given")));
417}
418
422inline constexpr BraKet default_braket(Operator oper) {
423 return (rank(oper) == 1)
424 ? BraKet::x_x
425 : ((rank(oper) == 2)
426 ? BraKet::xx_xx
427 : throw std::logic_error(
428 "default_braket(Operator): invalid operator given"));
429}
430
431constexpr size_t nopers_2body = static_cast<int>(Operator::last_2body_oper) -
432 static_cast<int>(Operator::first_2body_oper) +
433 1;
434constexpr size_t nbrakets_2body = static_cast<int>(BraKet::last_2body_braket) -
435 static_cast<int>(BraKet::first_2body_braket) +
436 1;
437constexpr size_t nderivorders_2body = LIBINT2_MAX_DERIV_ORDER + 1;
438
444class Engine {
445 private:
446 typedef struct {
447 } empty_pod;
448
449 public:
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>>;
455
460 Engine()
461 : oper_(Operator::invalid),
462 braket_(BraKet::invalid),
463 primdata_(),
464 stack_size_(0),
465 lmax_(-1),
466 deriv_order_(0),
467 cartesian_shell_normalization_(CartesianShellNormalization::standard),
468 scale_(1) {
469 set_precision(std::numeric_limits<scalar_type>::epsilon());
470 }
471
472 // clang-format off
474
501 // clang-format on
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())
507 : oper_(oper),
508 braket_(braket),
509 primdata_(),
510 spbra_(max_nprim),
511 spket_(max_nprim),
512 stack_size_(0),
513 lmax_(max_l),
514 deriv_order_(deriv_order),
515 screening_method_(screening_method),
516 cartesian_shell_normalization_(CartesianShellNormalization::standard),
517 scale_(1),
518 params_(enforce_params_type(oper, params)) {
519 set_precision(precision);
520 assert(max_nprim > 0);
521 initialize(max_nprim);
522 core_eval_pack_ = make_core_eval_pack(oper); // must follow initialize() to
523 // ensure default braket_ has
524 // been set
525 init_core_ints_params(params_);
526 }
527
529 // intel does not accept "move ctor = default"
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_),
537 lmax_(other.lmax_),
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_) {
554 // leave other in an unusable (but valid) state
555 other.oper_ = Operator::invalid;
556 other.braket_ = BraKet::invalid;
557 other.scratch2_ = nullptr;
558 }
559
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_),
568 lmax_(other.lmax_),
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_) {
578 initialize();
579 }
580
581 ~Engine() { finalize(); }
582
584 Engine& operator=(Engine&& other) {
585 oper_ = other.oper_;
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_;
591 lmax_ = other.lmax_;
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_;
608 // leave other in an unusable state
609 other.oper_ = Operator::invalid;
610 other.braket_ = BraKet::invalid;
611 other.scratch2_ = nullptr;
612 return *this;
613 }
614
616 Engine& operator=(const Engine& other) {
617 oper_ = other.oper_;
618 braket_ = other.braket_;
619 primdata_.resize(other.primdata_.size());
620 spbra_ = other.spbra_;
621 spket_ = other.spket_;
622 stack_size_ = other.stack_size_;
623 lmax_ = other.lmax_;
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_;
633 initialize();
634 return *this;
635 }
636
638 int operator_rank() const { return rank(oper_); }
639
641 int braket_rank() const { return rank(braket_); }
642
644 Operator oper() const { return oper_; }
645
647 BraKet braket() const { return braket_; }
648
650 int deriv_order() const { return deriv_order_; }
651
657 Engine& set(Operator new_oper) {
658 if (oper_ != new_oper) {
659 oper_ = new_oper;
660 braket_ = default_braket(oper_);
661 params_ = default_params(oper_);
662 initialize();
663 core_eval_pack_ = make_core_eval_pack(oper_); // must follow initialize()
664 // to ensure default
665 // braket_ has been set
666 }
667 return *this;
668 }
669
673 Engine& set(BraKet new_braket) {
674 if (braket_ != new_braket) {
675 braket_ = new_braket;
676 initialize();
677 }
678 return *this;
679 }
680
684 template <typename Params>
685 Engine& set_params(const Params& params) {
686 params_ = params;
687 init_core_ints_params(params_);
688 reset_scratch();
689 return *this;
690 }
691
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()));
696 }
697
702 Engine& set_max_nprim(std::size_t n) {
703 if (n * n > spbra_.primpairs.size()) {
704 spbra_.resize(n);
705 spket_.resize(n);
706 initialize(n);
707 }
708 return *this;
709 }
710
712 std::size_t max_l() const { return lmax_; }
713
718 Engine& set_max_l(std::size_t L) {
719 if (L >= static_cast<std::size_t>(lmax_)) {
720 lmax_ = L;
721 initialize();
722 }
723 return *this;
724 }
725
731 const target_ptr_vec& results() const { return targets_; }
732
736 unsigned int nshellsets() const { return targets_.size(); }
737
739
747 template <typename... ShellPack>
748 __libint2_engine_inline const target_ptr_vec& compute(
749 const libint2::Shell& first_shell, const ShellPack&... rest_of_shells);
750
757 __libint2_engine_inline const target_ptr_vec& compute1(
758 const libint2::Shell& s1, const libint2::Shell& s2);
759
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);
792
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);
796
797 // clang-format off
808 // clang-format on
809 Engine& set_precision(scalar_type prec) {
810 if (prec <= 0.) {
811 precision_ = 0.;
812 ln_precision_ = std::numeric_limits<scalar_type>::lowest();
813 return *this;
814 }
815 if (prec > 0.) { // split single if/else to avoid speculative execution of
816 // else branch on Apple M1 with apple clang 13.0.0
817 precision_ = prec;
818 using std::log;
819 ln_precision_ = log(precision_);
820 return *this;
821 }
822 abort();
823 }
826 scalar_type precision() const { return precision_; }
827
829 Engine& set(ScreeningMethod screening_method) {
830 screening_method_ = screening_method;
831 return *this;
832 }
833
835 ScreeningMethod screening_method() const { return screening_method_; }
836
838 CartesianShellNormalization cartesian_shell_normalization() const {
839 return cartesian_shell_normalization_;
840 }
841
845 Engine& set(CartesianShellNormalization norm) {
846 cartesian_shell_normalization_ = norm;
847 return *this;
848 }
849
851 scalar_type prescaled_by() const { return scale_; }
852
857 Engine& prescale_by(scalar_type sc) {
858 scale_ = sc;
859 return *this;
860 }
861
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 // if libint's profiling was on, engine's build timer
867 // will include its overhead
868 // do not report it, detailed profiling from libint will be printed below
869 os << " build = " << timers.read(1);
870#endif
871 os << " tform = " << timers.read(2) << std::endl;
872#endif
873#ifdef LIBINT2_PROFILE
874 os << "build timers: hrr = " << primdata_[0].timers->read(0)
875 << " vrr = " << primdata_[0].timers->read(1) << std::endl;
876#endif
877#ifdef LIBINT2_ENGINE_TIMERS
878#ifdef LIBINT2_ENGINE_PROFILE_CLASS
879 for (const auto& p : class_profiles) {
880 char buf[1024];
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;
887 }
888#endif
889#endif
890 }
891
893 class lmax_exceeded : virtual public std::logic_error {
894 public:
895 lmax_exceeded(const char* task_name, size_t lmax_limit,
896 size_t lmax_requested)
897 : std::logic_error(
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';
903 }
904 ~lmax_exceeded() noexcept {}
905
906 const char* task_name() const {
907 return static_cast<const char*>(task_name_);
908 }
909 size_t lmax_limit() const { return lmax_limit_; }
910 size_t lmax_requested() const { return lmax_requested_; }
911
912 private:
913 char task_name_[65];
914 size_t lmax_limit_;
915 size_t lmax_requested_;
916 };
917
919 class using_default_initialized : virtual public std::logic_error {
920 public:
921 using_default_initialized()
922 : std::logic_error(
923 "Engine::using_default_initialized -- attempt to use a "
924 "default-initialized Engine") {}
925 ~using_default_initialized() noexcept {}
926 };
927
928 private:
929 Operator oper_;
930 BraKet braket_;
931 std::vector<Libint_t> primdata_;
932 ShellPair spbra_, spket_;
933 size_t stack_size_; // amount allocated by libint2_init_xxx in
934 // primdata_[0].stack
935 int lmax_;
936 int hard_lmax_; // max L supported by library for this operator type (i.e.
937 // LIBINT2_MAX_AM_<task><deriv_order>) + 1
938 int hard_default_lmax_; // max L supported by library for default operator
939 // type (i.e. LIBINT2_MAX_AM_default<deriv_order>) +
940 // 1 this is only set and used if
941 // LIBINT2_CENTER_DEPENDENT_MAX_AM_<task><deriv_order>
942 // == 1
943 int deriv_order_;
944 scalar_type precision_;
945 scalar_type ln_precision_;
946 ScreeningMethod screening_method_ = ScreeningMethod::Invalid;
947
948 // specifies the normalization convention for Cartesian Gaussians
949 CartesianShellNormalization cartesian_shell_normalization_;
950
951 // the target integrals are scaled by this factor (of course it is actually
952 // the core integrals that are scaled)
953 scalar_type scale_;
954
955 any core_eval_pack_;
956
958 any params_; // operator params
963 any core_ints_params_;
965 void init_core_ints_params(const any& params);
966
969 target_ptr_vec targets_;
972 bool set_targets_;
973
974 std::vector<value_type>
975 scratch_; // for transposes and/or transforming to solid harmonics
976 value_type* scratch2_; // &scratch_[0] points to the first block large enough
977 // to hold all target ints
978 // scratch2_ points to second such block. It could point into scratch_ or at
979 // primdata_[0].stack
980 typedef void (*buildfnptr_t)(const Libint_t*);
981 buildfnptr_t* buildfnptrs_;
982
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)
988 ? this->nparams()
989 : 0;
990 const auto ncenters = braket_rank() + num_operator_geometrical_derivatives;
991 return nopers() * num_geometrical_derivatives(ncenters, deriv_order_);
992 }
993
994 void reset_scratch() {
995 const auto nshsets = compute_nshellsets();
996 targets_.resize(nshsets);
997 set_targets_ =
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());
1002 // need to be able to hold 2 sets of target shellsets: the worst case occurs
1003 // when dealing with
1004 // 1-body Coulomb ints derivatives ... have 2+natom 1st-order derivative
1005 // sets (and many more of 2nd and higher) that are stored in scratch then
1006 // need to transform to solids. To avoid copying back and forth make sure
1007 // that there is enough room to transform all ints and save them in correct
1008 // order in single pass
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;
1014 }
1015
1016 __libint2_engine_inline void compute_primdata(Libint_t& primdata,
1017 const Shell& s1,
1018 const Shell& s2, size_t p1,
1019 size_t p2, size_t oset);
1020
1021 public:
1025 __libint2_engine_inline const std::vector<Engine::compute2_ptr_type>&
1026 compute2_ptrs() const;
1027
1028 private:
1029 // max_nprim=0 avoids resizing primdata_
1030 __libint2_engine_inline void initialize(size_t max_nprim = 0);
1031 // generic _initializer
1032 __libint2_engine_inline void _initialize();
1033
1034 void finalize() {
1035 if (primdata_.size() != 0) {
1036 libint2_cleanup_default(&primdata_[0]);
1037 }
1038 } // finalize()
1039
1040 //-------
1041 // utils
1042 //-------
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;
1059
1060 //-------
1061 // profiling
1062 //-------
1063 static const bool skip_core_ints = false;
1064}; // struct Engine
1065
1066} // namespace libint2
1067
1068#ifndef LIBINT2_DOES_NOT_INLINE_ENGINE
1069#include "./engine.impl.h"
1070#endif
1071
1072#endif /* _libint2_src_lib_libint_engine_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
Definition boys.h:1558
Definition boys_fwd.h:51
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
Definition boys_fwd.h:56