TiledArray  0.7.0
kronecker_delta.h
Go to the documentation of this file.
1 /*
2  * This file is a part of TiledArray.
3  * Copyright (C) 2015 Virginia Tech
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU 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  * This program 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 General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17  *
18  */
19 
20 #ifndef TILEDARRAY_SPECIAL_KRONECKER_DELTA_H__INCLUDED
21 #define TILEDARRAY_SPECIAL_KRONECKER_DELTA_H__INCLUDED
22 
23 #include <tuple>
24 #include <memory>
25 
26 #include <tiledarray_fwd.h>
27 
28 #include <TiledArray/madness.h>
29 
30 // Array class
31 #include <TiledArray/tensor.h>
32 #include <TiledArray/tile.h>
34 
35 // Array policy classes
38 
40 
49 template<unsigned _N = 1>
51  public:
52  // Constants
53  static constexpr unsigned N = _N;
54  // Concept typedefs
55  typedef TiledArray::Range range_type; // range type
56  typedef int value_type; // Element type
57  typedef value_type numeric_type; // The scalar type that is compatible with value_type
58  typedef size_t size_type; // Size type
59 
60  private:
61  range_type range_;
62  bool empty_;
63 
64  public:
65 
67  KroneckerDeltaTile() : empty_(true) {
68  }
69 
71  KroneckerDeltaTile(const range_type& range) : range_(range), empty_(is_empty(range_)) {
72  }
73 
75  KroneckerDeltaTile(const KroneckerDeltaTile&) = default;
76 
79  operator=(const KroneckerDeltaTile& other) = default;
80 
83  clone() const {
84  KroneckerDeltaTile result(*this);
85  return result;
86  }
87 
89  range() const {
90  return range_;
91  }
92 
93  bool empty() const { return empty_; }
94 
96  template<typename Archive>
97  void
98  serialize(Archive& ar) {
99  std::cout << "KroneckerDelta::serialize not implemented by design!" << std::endl;
100  abort(); // should never travel
101  }
102 
103  private:
105  static bool is_empty(const range_type& range) {
106  bool empty = false;
107  TA_ASSERT(range.rank() == 2*N);
108  auto lobound = range.lobound_data();
109  auto upbound = range.upbound_data();
110  for(auto i=0; i!=2*N && not empty; i+=2)
111  empty = (upbound[i] > lobound[i+1] && upbound[i+1] > lobound[i]) ? true : false; // assumes extents > 0
112  return empty;
113  }
114 
115  }; // class KroneckerDeltaTile
116 
117 // these are to satisfy interfaces, but not needed, actually
118 
119 // Sum of hyper diagonal elements
120 template <unsigned _N>
122 trace(const KroneckerDeltaTile<_N>& arg);
123 // foreach(i) result += arg[i]
124 template <unsigned _N>
126 sum(const KroneckerDeltaTile<_N>& arg);
127 // foreach(i) result *= arg[i]
128 template <unsigned _N>
130 product(const KroneckerDeltaTile<_N>& arg);
131 // foreach(i) result += arg[i] * arg[i]
132 template <unsigned _N>
135 // foreach(i) result = min(result, arg[i])
136 template <unsigned _N>
138 min(const KroneckerDeltaTile<_N>& arg);
139 // foreach(i) result = max(result, arg[i])
140 template <unsigned _N>
142 max(const KroneckerDeltaTile<_N>& arg);
143 // foreach(i) result = abs_min(result, arg[i])
144 template <unsigned _N>
146 abs_min(const KroneckerDeltaTile<_N>& arg);
147 // foreach(i) result = abs_max(result, arg[i])
148 template <unsigned _N>
150 abs_max(const KroneckerDeltaTile<_N>& arg);
151 
152 // Permutation operation
153 
154 // returns a tile for which result[perm ^ i] = tile[i]
155 template <unsigned N>
157  const TiledArray::Permutation& perm) {
158  abort();
159 }
160 
161 // dense_result[i] = dense_arg1[i] * sparse_arg2[i]
162 template<typename T, unsigned _N>
165  const TiledArray::Tensor<T>& arg2) {
166  abort();
167 }
168 // dense_result[perm ^ i] = dense_arg1[i] * sparse_arg2[i]
169 template<typename T, unsigned _N>
172  const TiledArray::Tensor<T>& arg2,
173  const Permutation& perm) {
174  abort();
175 }
176 
177 // dense_result[i] *= sparse_arg1[i]
178 template<typename T, unsigned N>
181  const KroneckerDeltaTile<N>& arg1) {
182  abort();
183  return result;
184  }
185 
186 // Contraction operation
187 
188 // GEMM operation with fused indices as defined by gemm_config:
189 // dense_result[i,j] = dense_arg1[i,k] * sparse_arg2[k,j]
190 template<typename T, unsigned N>
193  const KroneckerDeltaTile<N>& arg1,
194  const TiledArray::Tensor<T>& arg2,
195  const typename TiledArray::Tensor<T>::numeric_type factor,
196  const TiledArray::math::GemmHelper& gemm_config) {
197 
198  // preconditions:
199  // 1. implemented only outer product
200  assert(gemm_config.result_rank() == gemm_config.left_rank() + gemm_config.right_rank());
201 
202  auto arg1_range = arg1.range();
203  auto arg2_range = arg2.range();
204  auto result_range = gemm_config.make_result_range<TiledArray::Range> (
205  arg1_range, arg2_range);
206  TiledArray::Tensor<T> result (result_range, 0);
207 
208  auto result_data = result.data();
209  auto arg1_extents = arg1_range.extent_data();
210  auto arg2_data = arg2.data();
211  auto arg2_volume = arg2_range.volume();
212 
213  if (not arg1.empty ()) {
214  switch (N) {
215  case 1: {
216  auto i0_range = std::min (arg1_extents[0], arg1_extents[1]);
217  for (decltype(i0_range) i0 = 0; i0 != i0_range; ++i0) {
218  auto result_i0i0_ptr = result_data
219  + (i0 * arg1_extents[1] + i0) * arg2_volume;
220  std::copy (arg2_data, arg2_data + arg2_volume, result_i0i0_ptr);
221  }
222  }
223  break;
224  case 2: {
225  auto i0_range = std::min (arg1_extents[0], arg1_extents[1]);
226  auto i1_range = std::min (arg1_extents[2], arg1_extents[3]);
227  auto ndim23 = arg1_extents[2] * arg1_extents[3];
228  for (decltype(i0_range) i0 = 0; i0 != i0_range; ++i0) {
229  auto result_i0i0i1i1_ptr_offset = result_data
230  + (i0 * arg1_extents[1] + i0) * ndim23 * arg2_volume;
231  for (decltype(i1_range) i1 = 0; i1 != i1_range; ++i1) {
232  auto result_i0i0i1i1_ptr = result_i0i0i1i1_ptr_offset
233  + (i1 * arg1_extents[3] + i1) * arg2_volume;
234  std::copy (arg2_data, arg2_data + arg2_volume, result_i0i0i1i1_ptr);
235  }
236  }
237  }
238  break;
239 
240  default:
241  abort (); // not implemented
242  }
243  }
244 
245  return result;
246 }
247 // GEMM operation with fused indices as defined by gemm_config:
248 // dense_result[i,j] += dense_arg1[i,k] * sparse_arg2[k,j]
249 template<typename T, unsigned N>
250  void
252  TiledArray::Tensor<T>& result,
253  const KroneckerDeltaTile<N>& arg1,
254  const TiledArray::Tensor<T>& arg2,
255  const typename TiledArray::Tensor<T>::numeric_type factor,
256  const TiledArray::math::GemmHelper& gemm_config) {
257  abort();
258  }
259 
260 #endif // TILEDARRAY_TEST_SPARSE_TILE_H__INCLUDED
static constexpr unsigned N
A (hyperrectangular) interval on , space of integer n-indices.
Definition: range.h:39
KroneckerDeltaTile< _N >::numeric_type sum(const KroneckerDeltaTile< _N > &arg)
const size_type * extent_data() const
Range extent data accessor.
Definition: range.h:594
generalized (asymmetric) Kronecker delta
range_type range() const
An N-dimensional tensor object.
Definition: foreach.h:40
TiledArray::Range range_type
const range_type & range() const
Tensor range object accessor.
Definition: tensor.h:310
KroneckerDeltaTile< _N >::numeric_type product(const KroneckerDeltaTile< _N > &arg)
TiledArray::detail::numeric_type< T >::type numeric_type
the numeric type that supports T
Definition: tensor.h:50
KroneckerDeltaTile< _N >::numeric_type abs_max(const KroneckerDeltaTile< _N > &arg)
unsigned int result_rank() const
Result rank accessor.
Definition: gemm_helper.h:134
KroneckerDeltaTile< _N >::numeric_type max(const KroneckerDeltaTile< _N > &arg)
KroneckerDeltaTile(const range_type &range)
Productive ctor 1.
value_type numeric_type
unsigned int rank() const
Rank accessor.
Definition: range.h:542
R make_result_range(const Left &left, const Right &right) const
Construct a result range based on left and right ranges.
Definition: gemm_helper.h:166
const size_type * upbound_data() const
Range upper bound data accessor.
Definition: range.h:570
const_pointer data() const
Data direct access.
Definition: tensor.h:416
KroneckerDeltaTile< _N >::numeric_type trace(const KroneckerDeltaTile< _N > &arg)
#define TA_ASSERT(a)
Definition: error.h:107
KroneckerDeltaTile clone() const
clone = copy
KroneckerDeltaTile< _N >::numeric_type squared_norm(const KroneckerDeltaTile< _N > &arg)
KroneckerDeltaTile & operator=(const KroneckerDeltaTile &other)=default
assignment
bool empty() const
KroneckerDeltaTile< N > permute(const KroneckerDeltaTile< N > &tile, const TiledArray::Permutation &perm)
DistArray< Tile, Policy > copy(const DistArray< Tile, Policy > &a)
Definition: utils.h:58
TiledArray::Tensor< T > & mult_to(TiledArray::Tensor< T > &result, const KroneckerDeltaTile< N > &arg1)
unsigned int right_rank() const
Right-hand argument rank accessor.
Definition: gemm_helper.h:144
Contraction to *GEMM helper.
Definition: gemm_helper.h:39
Permutation of a sequence of objects indexed by base-0 indices.
Definition: permutation.h:119
const size_type * lobound_data() const
Range lower bound data accessor.
Definition: range.h:548
TiledArray::Tensor< T > gemm(const KroneckerDeltaTile< N > &arg1, const TiledArray::Tensor< T > &arg2, const typename TiledArray::Tensor< T >::numeric_type factor, const TiledArray::math::GemmHelper &gemm_config)
KroneckerDeltaTile< _N >::numeric_type abs_min(const KroneckerDeltaTile< _N > &arg)
TiledArray::Tensor< T > mult(const KroneckerDeltaTile< _N > &arg1, const TiledArray::Tensor< T > &arg2)
KroneckerDeltaTile< _N >::numeric_type min(const KroneckerDeltaTile< _N > &arg)
unsigned int left_rank() const
Left-hand argument rank accessor.
Definition: gemm_helper.h:139
void serialize(Archive &ar)
MADNESS compliant serialization.
KroneckerDeltaTile()
default constructor makes an empty tile