53 static void initialize() {
54 int max_deriv_order = 0;
55#if defined(LIBINT2_MAX_DERIV_ORDER)
56 max_deriv_order = LIBINT2_MAX_DERIV_ORDER;
59 if (INCLUDE_ERI > max_deriv_order) max_deriv_order = INCLUDE_ERI;
62 if (INCLUDE_ERI3 > max_deriv_order) max_deriv_order = INCLUDE_ERI3;
65 for (
int d = 1; d <= max_deriv_order; ++d) {
66 braket_xx_xx().push_back(
67 DerivMapGenerator::generate_deriv_index_map(d, BraKet::xx_xx));
68 braket_xs_xx().push_back(
69 DerivMapGenerator::generate_deriv_index_map(d, BraKet::xs_xx));
75 static std::vector<Tensor<size_t>>& braket_xx_xx() {
76 static std::vector<Tensor<size_t>> braket_xx_xx_maps;
77 return braket_xx_xx_maps;
80 static std::vector<Tensor<size_t>>& braket_xs_xx() {
81 static std::vector<Tensor<size_t>> braket_xs_xx_maps;
82 return braket_xs_xx_maps;
89 return braket_xx_xx()[deriv_order_ - 1];
92 return braket_xs_xx()[deriv_order_ - 1];
96 "Derivative index permutation maps for this braket type not yet "
108 static void cwr_recursion(std::vector<size_t> inp, std::vector<size_t>& out,
109 std::vector<std::vector<size_t>>& result,
size_t k,
110 size_t i,
size_t n) {
112 if (out.size() == k) {
113 result.push_back(out);
116 for (
size_t j = i; j < n; j++) {
117 out.push_back(inp[j]);
118 cwr_recursion(inp, out, result, k, j, n);
127 static size_t how_many_derivs(
size_t k,
size_t n) {
129 size_t factorial = 1;
130 for (
size_t i = 0; i < n; i++) {
153 static std::vector<std::vector<size_t>> generate_multi_index_lookup(
154 size_t nparams,
size_t deriv_order) {
158 for (
size_t i = 0; i < nparams; i++) {
165 vector<vector<size_t>> combos;
166 cwr_recursion(inp, out, combos, deriv_order, 0, nparams);
171 static Tensor<size_t> generate_deriv_index_map(
size_t deriv_order,
175 vector<size_t> swap_braket_perm;
176 vector<size_t> swap_bra_perm;
177 vector<size_t> swap_ket_perm;
178 vector<vector<size_t>> swap_combos;
181 case BraKet::xx_xx: {
182 swap_braket_perm = {6, 7, 8, 9, 10, 11, 0, 1, 2, 3, 4, 5};
183 swap_bra_perm = {3, 4, 5, 0, 1, 2, 6, 7, 8, 9, 10, 11};
184 swap_ket_perm = {0, 1, 2, 3, 4, 5, 9, 10, 11, 6, 7, 8};
187 swap_combos = {{0, 0, 0}, {0, 0, 1}, {0, 1, 0}, {0, 1, 1},
188 {1, 0, 0}, {1, 0, 1}, {1, 1, 0}, {1, 1, 1}};
191 case BraKet::xs_xx: {
192 swap_braket_perm = {0, 1, 2, 3, 4, 5, 6, 7, 8};
193 swap_bra_perm = {0, 1, 2, 3, 4, 5, 6, 7, 8};
194 swap_ket_perm = {0, 1, 2, 6, 7, 8, 3, 4, 5};
195 swap_combos = {{0, 0, 0}, {0, 0, 1}};
201 "Derivative index maps for this BraKet type not implemented.");
205 auto nderivs = how_many_derivs(
206 ncenters, deriv_order);
209 auto nparams = ncenters * 3;
217 Tensor<size_t> mapDerivIndex{swap_dim, swap_dim, swap_dim, nderivs};
223 vector<vector<size_t>> lookup =
224 generate_multi_index_lookup(nparams, deriv_order);
227 for (
size_t swap = 0; swap < swap_combos.size(); swap++) {
228 auto swap_braket = swap_combos[swap][0];
229 auto swap_bra = swap_combos[swap][1];
230 auto swap_ket = swap_combos[swap][2];
233 for (
size_t i = 0; i < nderivs; i++) {
234 vector<size_t> multi_idx = lookup[i];
235 vector<size_t> permuted_indices;
236 for (
size_t j = 0; j < multi_idx.size(); j++) {
237 size_t idx = multi_idx[j];
238 if (swap_braket == 1) idx = swap_braket_perm[idx];
239 if (swap_bra == 1) idx = swap_bra_perm[idx];
240 if (swap_ket == 1) idx = swap_ket_perm[idx];
241 permuted_indices.push_back(idx);
245 sort(permuted_indices.begin(), permuted_indices.end());
252 auto it = lower_bound(lookup.begin(), lookup.end(), permuted_indices);
253 if (it != lookup.end()) new_idx = it - lookup.begin();
254 (*mapDerivIndex.data(swap_braket, swap_bra, swap_ket, i)) = new_idx;
257 return mapDerivIndex;