GQCP
Loading...
Searching...
No Matches
ImplicitRankFourTensorSlice.hpp
Go to the documentation of this file.
1// This file is part of GQCG-GQCP.
2//
3// Copyright (C) 2017-2020 the GQCG developers
4//
5// GQCG-GQCP is free software: you can redistribute it and/or modify
6// it under the terms of the GNU Lesser General Public License as published by
7// the Free Software Foundation, either version 3 of the License, or
8// (at your option) any later version.
9//
10// GQCG-GQCP is distributed in the hope that it will be useful,
11// but WITHOUT ANY WARRANTY; without even the implied warranty of
12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13// GNU Lesser General Public License for more details.
14//
15// You should have received a copy of the GNU Lesser General Public License
16// along with GQCG-GQCP. If not, see <http://www.gnu.org/licenses/>.
17
18#pragma once
19
20
23
24#include <map>
25#include <numeric>
26#include <vector>
27
28
29namespace GQCP {
30
31
37template <typename _Scalar>
39public:
40 using Scalar = _Scalar;
41
42
43private:
44 std::vector<std::map<size_t, size_t>> indices_implicit_to_dense; // an array of maps, mapping the implicit tensor indices to these of the dense representation
45
46 Tensor<Scalar, 4> T; // the dense representation of the slice
47
48
49public:
50 /*
51 * CONSTRUCTORS
52 */
53
60 ImplicitRankFourTensorSlice(const std::vector<std::map<size_t, size_t>>& indices_implicit_to_dense, const Tensor<Scalar, 4>& T) :
61 indices_implicit_to_dense {indices_implicit_to_dense},
62 T {T} {
63
64 // Check if the given maps are consistent with the given tensor's dimensions.
65 const auto dimensions = T.dimensions();
66 for (size_t axis_index = 0; axis_index < 4; axis_index++) {
67 if (this->indices_implicit_to_dense[axis_index].size() != dimensions[axis_index]) {
68 throw std::invalid_argument("ImplicitRankFourTensorSlice(const std::vector<std::map<size_t, size_t>>&, const Tensor<Scalar, 4>&): The given dense representation of the slice has an incompatible dimension for axis number " + std::to_string(axis_index) + ".");
69 }
70 }
71 }
72
73
78 // Use a named constructor for the default initialization.
80
81
82 /*
83 * NAMED CONSTRUCTORS
84 */
85
101 static ImplicitRankFourTensorSlice<Scalar> FromBlockRanges(const size_t axis1_start, const size_t axis1_end, const size_t axis2_start, const size_t axis2_end, const size_t axis3_start, const size_t axis3_end, const size_t axis4_start, const size_t axis4_end, const Tensor<Scalar, 4>& T) {
102
103 // Convert the ranges into allowed indices of the implicit tensor, and then use another named constructor.
104 std::vector<size_t> axis1_indices(axis1_end - axis1_start);
105 std::iota(axis1_indices.begin(), axis1_indices.end(), axis1_start);
106
107 std::vector<size_t> axis2_indices(axis2_end - axis2_start);
108 std::iota(axis2_indices.begin(), axis2_indices.end(), axis2_start);
109
110 std::vector<size_t> axis3_indices(axis3_end - axis3_start);
111 std::iota(axis3_indices.begin(), axis3_indices.end(), axis3_start);
112
113 std::vector<size_t> axis4_indices(axis4_end - axis4_start);
114 std::iota(axis4_indices.begin(), axis4_indices.end(), axis4_start);
115
116 return ImplicitRankFourTensorSlice<Scalar>::FromIndices(axis1_indices, axis2_indices, axis3_indices, axis4_indices, T);
117 }
118
119
128 static ImplicitRankFourTensorSlice<Scalar> FromIndices(const std::vector<std::vector<size_t>>& axes_indices, const Tensor<Scalar, 4>& T) {
129
130 // Loop over all indices of all axes, mapping them to the indices of the dense representation of the slice.
131 std::vector<std::map<size_t, size_t>> indices_maps;
132 for (size_t axis_index = 0; axis_index < 4; axis_index++) {
133 size_t dense_index = 0; // index in the dense representation of the slice
134
135 std::map<size_t, size_t> axis_map {}; // the index mapping for the current axis index
136 for (const auto& implicit_index : axes_indices[axis_index]) {
137 axis_map[implicit_index] = dense_index;
138 dense_index++; // the dense indices are contiguous
139 }
140 indices_maps.push_back(axis_map);
141 }
142
143 return ImplicitRankFourTensorSlice<Scalar>(indices_maps, T);
144 }
145
146
158 static ImplicitRankFourTensorSlice<Scalar> FromIndices(const std::vector<size_t>& axis1_indices, const std::vector<size_t>& axis2_indices, const std::vector<size_t>& axis3_indices, const std::vector<size_t>& axis4_indices, const Tensor<Scalar, 4>& T) {
159
160 // Wrap the separate indices for the axes into one array and use another named constructor.
161 std::vector<std::vector<size_t>> axes_indices {axis1_indices, axis2_indices, axis3_indices, axis4_indices};
162
164 }
165
166
181 static ImplicitRankFourTensorSlice<Scalar> ZeroFromBlockRanges(const size_t axis1_start, const size_t axis1_end, const size_t axis2_start, const size_t axis2_end, const size_t axis3_start, const size_t axis3_end, const size_t axis4_start, const size_t axis4_end) {
182
183 // Create the zero dense representation of the slice and then use another named constructor.
184 const auto axis1_dimension = static_cast<long>(axis1_end - axis1_start); // need static_cast for Tensor
185 const auto axis2_dimension = static_cast<long>(axis2_end - axis2_start);
186 const auto axis3_dimension = static_cast<long>(axis3_end - axis3_start);
187 const auto axis4_dimension = static_cast<long>(axis4_end - axis4_start);
188
189 Tensor<Scalar, 4> T {axis1_dimension, axis2_dimension, axis3_dimension, axis4_dimension};
190 T.setZero();
191
192 return ImplicitRankFourTensorSlice<Scalar>::FromBlockRanges(axis1_start, axis1_end, axis2_start, axis2_end, axis3_start, axis3_end, axis4_start, axis4_end, T);
193 }
194
195
206 static ImplicitRankFourTensorSlice<Scalar> ZeroFromIndices(const std::vector<size_t>& axis1_indices, const std::vector<size_t>& axis2_indices, const std::vector<size_t>& axis3_indices, const std::vector<size_t>& axis4_indices) {
207
208 // Zero-initialize a tensor with the required dimensions and then use another named constructor.
209 const auto axis1_dimension = static_cast<long>(axis1_indices.size());
210 const auto axis2_dimension = static_cast<long>(axis2_indices.size());
211 const auto axis3_dimension = static_cast<long>(axis3_indices.size());
212 const auto axis4_dimension = static_cast<long>(axis4_indices.size());
213
214 Tensor<Scalar, 4> T {axis1_dimension, axis2_dimension, axis3_dimension, axis4_dimension};
215 T.setZero();
216
217 return ImplicitRankFourTensorSlice<Scalar>::FromIndices(axis1_indices, axis2_indices, axis3_indices, axis4_indices, T);
218 }
219
220
221 /*
222 * OPERATORS
223 */
224
235 Scalar operator()(const size_t index1, const size_t index2, const size_t index3, const size_t index4) const {
236
237 // Map the implicit indices to the indices of the dense representation of this slice.
238 const auto dense_index1 = this->denseIndexOf<0>(index1);
239 const auto dense_index2 = this->denseIndexOf<1>(index2);
240 const auto dense_index3 = this->denseIndexOf<2>(index3);
241 const auto dense_index4 = this->denseIndexOf<3>(index4);
242
243 return this->T(dense_index1, dense_index2, dense_index3, dense_index4);
244 }
245
256 Scalar& operator()(const size_t index1, const size_t index2, const size_t index3, const size_t index4) {
257
258 // Map the implicit indices to the indices of the dense representation of this slice.
259 const auto dense_index1 = this->denseIndexOf<0>(index1);
260 const auto dense_index2 = this->denseIndexOf<1>(index2);
261 const auto dense_index3 = this->denseIndexOf<2>(index3);
262 const auto dense_index4 = this->denseIndexOf<3>(index4);
263
264 return this->T(dense_index1, dense_index2, dense_index3, dense_index4);
265 }
266
267
268 /*
269 * PUBLIC METHODS
270 */
271
275 MatrixX<Scalar> asMatrix() const { return this->T.pairWiseReduced(); }
276
280 const Tensor<Scalar, 4>& asTensor() const { return this->T; }
281
291 template <size_t Axis>
292 size_t denseIndexOf(const size_t index) const { return this->indices_implicit_to_dense[Axis].at(index); }
293
297 const std::vector<std::map<size_t, size_t>>& indexMaps() const { return this->indices_implicit_to_dense; }
298};
299
300
301} // namespace GQCP
Definition: ImplicitRankFourTensorSlice.hpp:38
_Scalar Scalar
Definition: ImplicitRankFourTensorSlice.hpp:40
size_t denseIndexOf(const size_t index) const
Definition: ImplicitRankFourTensorSlice.hpp:292
static ImplicitRankFourTensorSlice< Scalar > FromIndices(const std::vector< std::vector< size_t > > &axes_indices, const Tensor< Scalar, 4 > &T)
Definition: ImplicitRankFourTensorSlice.hpp:128
const Tensor< Scalar, 4 > & asTensor() const
Definition: ImplicitRankFourTensorSlice.hpp:280
MatrixX< Scalar > asMatrix() const
Definition: ImplicitRankFourTensorSlice.hpp:275
ImplicitRankFourTensorSlice(const std::vector< std::map< size_t, size_t > > &indices_implicit_to_dense, const Tensor< Scalar, 4 > &T)
Definition: ImplicitRankFourTensorSlice.hpp:60
ImplicitRankFourTensorSlice()
Definition: ImplicitRankFourTensorSlice.hpp:77
static ImplicitRankFourTensorSlice< Scalar > ZeroFromIndices(const std::vector< size_t > &axis1_indices, const std::vector< size_t > &axis2_indices, const std::vector< size_t > &axis3_indices, const std::vector< size_t > &axis4_indices)
Definition: ImplicitRankFourTensorSlice.hpp:206
Scalar operator()(const size_t index1, const size_t index2, const size_t index3, const size_t index4) const
Definition: ImplicitRankFourTensorSlice.hpp:235
Scalar & operator()(const size_t index1, const size_t index2, const size_t index3, const size_t index4)
Definition: ImplicitRankFourTensorSlice.hpp:256
static ImplicitRankFourTensorSlice< Scalar > FromBlockRanges(const size_t axis1_start, const size_t axis1_end, const size_t axis2_start, const size_t axis2_end, const size_t axis3_start, const size_t axis3_end, const size_t axis4_start, const size_t axis4_end, const Tensor< Scalar, 4 > &T)
Definition: ImplicitRankFourTensorSlice.hpp:101
const std::vector< std::map< size_t, size_t > > & indexMaps() const
Definition: ImplicitRankFourTensorSlice.hpp:297
static ImplicitRankFourTensorSlice< Scalar > ZeroFromBlockRanges(const size_t axis1_start, const size_t axis1_end, const size_t axis2_start, const size_t axis2_end, const size_t axis3_start, const size_t axis3_end, const size_t axis4_start, const size_t axis4_end)
Definition: ImplicitRankFourTensorSlice.hpp:181
static ImplicitRankFourTensorSlice< Scalar > FromIndices(const std::vector< size_t > &axis1_indices, const std::vector< size_t > &axis2_indices, const std::vector< size_t > &axis3_indices, const std::vector< size_t > &axis4_indices, const Tensor< Scalar, 4 > &T)
Definition: ImplicitRankFourTensorSlice.hpp:158
Definition: Matrix.hpp:47
Definition: Tensor.hpp:46
enable_if_t< Z==4, Matrix< Scalar > > pairWiseReduced(const size_t start_i=0, const size_t start_j=0, const size_t start_k=0, const size_t start_l=0) const
Definition: Tensor.hpp:219
Definition: BaseOneElectronIntegralBuffer.hpp:25