TiledArray  0.7.0
btas.h
Go to the documentation of this file.
1 /*
2  * This file is a part of TiledArray.
3  * Copyright (C) 2018 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  * btas.h
19  * January 19, 2018
20  *
21  */
22 
23 #ifndef TILEDARRAY_CONVERSIONS_BTAS_H__INCLUDED
24 #define TILEDARRAY_CONVERSIONS_BTAS_H__INCLUDED
25 
26 #include <limits>
27 
28 #include <TiledArray/block_range.h>
30 #include <TiledArray/tensor.h>
32 #include <TiledArray/dense_shape.h>
37 
38 namespace TiledArray {
39 
41 
51  template <typename T, typename Range_, typename Storage_, typename Allocator_>
52  inline void btas_subtensor_to_tensor(const btas::Tensor<T,Range_,Storage_>& src, Tensor<T, Allocator_>& dst) {
53  TA_ASSERT(dst.range().rank() == src.range().rank());
54 
55  const auto& src_range = src.range();
56  const auto& dst_range = dst.range();
57  auto src_blk_range = TiledArray::BlockRange(detail::make_ta_range(src_range), dst_range.lobound(), dst_range.upbound());
58  using std::data;
59  auto src_view = TiledArray::make_const_map(data(src), src_blk_range);
60 
61  dst = src_view;
62  }
63 
65 
75  template <typename T, typename Allocator_, typename Range_, typename Storage_>
76  inline void tensor_to_btas_subtensor(const Tensor<T, Allocator_>& src, btas::Tensor<T,Range_,Storage_>& dst) {
77  TA_ASSERT(dst.range().rank() == src.range().rank());
78 
79  const auto& src_range = src.range();
80  const auto& dst_range = dst.range();
81  auto dst_blk_range = TiledArray::BlockRange(detail::make_ta_range(dst_range), src_range.lobound(), src_range.upbound());
82  using std::data;
83  auto dst_view = TiledArray::make_map(data(dst), dst_blk_range);
84 
85  dst_view = src;
86  }
87 
88 namespace detail {
89 
91 
98 template <typename DistArray_, typename BTAS_Tensor_>
99 void counted_btas_subtensor_to_tensor(const BTAS_Tensor_* src,
100  DistArray_* dst, const typename DistArray_::size_type i, madness::AtomicInt* counter)
101 {
102  typename DistArray_::value_type tensor(dst->trange().make_tile_range(i));
103  btas_subtensor_to_tensor(*src, tensor);
104  dst->set(i, tensor);
105  (*counter)++;
106 }
107 
109 
115 template <typename TA_Tensor_, typename BTAS_Tensor_>
116 void counted_tensor_to_btas_subtensor(const TA_Tensor_& src,
117  BTAS_Tensor_* dst, madness::AtomicInt* counter)
118 {
119  tensor_to_btas_subtensor(src, *dst);
120  (*counter)++;
121 }
122 
123 template <bool sparse>
124 auto make_shape(World& world, const TiledArray::TiledRange& trange);
125 
126 template <>
127 inline auto make_shape<true>(World& world, const TiledArray::TiledRange& trange) {
128  TiledArray::Tensor<float> tile_norms(trange.tiles_range(), std::numeric_limits<float>::max());
129  return TiledArray::SparseShape<float>(world, tile_norms, trange);
130 }
131 
132 template <>
133 inline auto make_shape<false>(World&, const TiledArray::TiledRange&) {
134  return TiledArray::DenseShape{};
135 }
136 
137 } // namespace detail
138 
140 
181 template <typename DistArray_,
182  typename T,
183  typename Range,
184  typename Storage>
185 DistArray_
186 btas_tensor_to_array(World& world, const TiledArray::TiledRange& trange,
187  const btas::Tensor<T, Range, Storage>& src, bool replicated = false)
188 {
189  // Test preconditions
190  const auto rank = trange.tiles_range().rank();
191  TA_USER_ASSERT(rank == src.range().rank(),
192  "TiledArray::btas_tensor_to_array(): rank of destination trange does not match the rank of source BTAS tensor.");
193  auto dst_range_extents = trange.elements_range().extent();
194  for(std::remove_const_t<decltype(rank)> d=0; d!=rank; ++d) {
195  TA_USER_ASSERT(dst_range_extents[d] == src.range().extent(d),
196  "TiledArray::btas_tensor_to_array(): source dimension does not match destination dimension.");
197  }
198 
199  using Tensor_ = btas::Tensor<T,Range,Storage>;
200  using Policy_ = typename DistArray_::policy_type;
201  const auto is_sparse = std::is_same<Policy_,TiledArray::SparsePolicy>::value;
202 
203  // Check that this is not a distributed computing environment
204  if(! replicated)
205  TA_USER_ASSERT(world.size() == 1,
206  "An array can be created from a btas::Tensor if the number of World ranks is greater than 1 only when replicated=true.");
207 
208  // Make a shape, only used if making a sparse array
209  using Shape_ = typename DistArray_::shape_type;
210  Shape_ shape = detail::make_shape<is_sparse>(world, trange);
211 
212  // Create a new tensor
213  DistArray_ array = (replicated && (world.size() > 1)
214  ? DistArray_(world, trange, shape,
215  std::static_pointer_cast<typename DistArray_::pmap_interface>(
216  std::make_shared<detail::ReplicatedPmap>(
217  world, trange.tiles_range().volume())))
218  : DistArray_(world, trange, shape));
219 
220  // Spawn copy tasks
221  madness::AtomicInt counter;
222  counter = 0;
223  std::int64_t n = 0;
224  for(std::size_t i = 0; i < array.size(); ++i) {
225  world.taskq.add(& detail::counted_btas_subtensor_to_tensor<DistArray_, Tensor_>,
226  &src, &array, i, &counter);
227  ++n;
228  }
229 
230  // Wait until the write tasks are complete
231  array.world().await([&counter,n] () { return counter == n; });
232 
233  // Analyze tiles norms and truncate based on sparse policy
234  if (is_sparse) truncate(array);
235 
236  return array;
237 }
238 
240 
257 template <typename Tile, typename Policy>
258 btas::Tensor<typename Tile::value_type>
260 {
261  // Test preconditions
262  if(! src.pmap()->is_replicated())
263  TA_USER_ASSERT(src.world().size() == 1,
264  "TiledArray::array_to_btas_tensor(): a non-replicated array can only be converted to a btas::Tensor if the number of World ranks is 1.");
265 
266  // Construct the result
267  using result_type = btas::Tensor<typename TiledArray::DistArray<Tile,Policy>::element_type>;
268  using result_range_type = typename result_type::range_type;
269  // if array is sparse must initialize to zero
270  result_type result(result_range_type(src.trange().elements_range().extent()), 0.0);
271 
272  // Spawn tasks to copy array tiles to btas::Tensor
273  madness::AtomicInt counter;
274  counter = 0;
275  int n = 0;
276  for(std::size_t i = 0; i < src.size(); ++i) {
277  if(! src.is_zero(i)) {
278  src.world().taskq.add(
279  & detail::counted_tensor_to_btas_subtensor<Tile, result_type>,
280  src.find(i), &result, &counter);
281  ++n;
282  }
283  }
284 
285  // Wait until the write tasks are complete
286  src.world().await([&counter,n] () { return counter == n; });
287 
288  return result;
289 }
290 
291 } // namespace TiledArray
292 
293 #endif // TILEDARRAY_CONVERSIONS_BTAS_H__INCLUDED
size_array lobound() const
Range lower bound accessor.
Definition: range.h:555
auto data(T &t)
Container data pointer accessor.
Definition: utility.h:89
Future< value_type > find(const Index &i) const
Find local or remote tile.
Definition: dist_array.h:324
An N-dimensional tensor object.
Definition: foreach.h:40
void truncate(DistArray< Tile, DensePolicy > &array)
Truncate a dense Array.
Definition: truncate.h:44
const range_type & range() const
Tensor range object accessor.
Definition: tensor.h:310
const trange_type & trange() const
Tiled range accessor.
Definition: dist_array.h:547
auto make_shape< false >(World &, const TiledArray::TiledRange &)
Definition: btas.h:133
KroneckerDeltaTile< _N >::numeric_type max(const KroneckerDeltaTile< _N > &arg)
TensorMap< T > make_map(T *const data, const Index &lower_bound, const Index &upper_bound)
Definition: tensor_map.h:51
unsigned int rank() const
Rank accessor.
Definition: range.h:542
void btas_subtensor_to_tensor(const btas::Tensor< T, Range_, Storage_ > &src, Tensor< T, Allocator_ > &dst)
Copy a block of a btas::Tensor into a TiledArray::Tensor.
Definition: btas.h:52
auto make_shape< true >(World &world, const TiledArray::TiledRange &trange)
Definition: btas.h:127
Arbitrary sparse shape.
Definition: sparse_shape.h:55
Dense shape of an array.
Definition: dense_shape.h:54
void counted_tensor_to_btas_subtensor(const TA_Tensor_ &src, BTAS_Tensor_ *dst, madness::AtomicInt *counter)
Task function for assigning a tensor to an Eigen submatrix.
Definition: btas.h:116
auto make_shape(World &world, const TiledArray::TiledRange &trange)
bool is_zero(const Index &i) const
Check for zero tiles.
Definition: dist_array.h:723
ordinal_type volume() const
Range volume accessor.
Definition: range.h:642
void counted_btas_subtensor_to_tensor(const BTAS_Tensor_ *src, DistArray_ *dst, const typename DistArray_::size_type i, madness::AtomicInt *counter)
Task function for converting btas::Tensor subblock to a TiledArray::DistArray.
Definition: btas.h:99
const range_type & tiles_range() const
Access the tile range.
Definition: tiled_range.h:122
TensorConstMap< T > make_const_map(const T *const data, const Index &lower_bound, const Index &upper_bound)
Definition: tensor_map.h:83
Forward declarations.
Definition: clone.h:32
#define TA_ASSERT(a)
Definition: error.h:107
World & world() const
World accessor.
Definition: dist_array.h:633
Range data of a tiled array.
Definition: tiled_range.h:31
void tensor_to_btas_subtensor(const Tensor< T, Allocator_ > &src, btas::Tensor< T, Range_, Storage_ > &dst)
Copy a block of a btas::Tensor into a TiledArray::Tensor.
Definition: btas.h:76
DistArray_ btas_tensor_to_array(World &world, const TiledArray::TiledRange &trange, const btas::Tensor< T, Range, Storage > &src, bool replicated=false)
Convert a btas::Tensor object into a TiledArray::DistArray object.
Definition: btas.h:186
Range that references a subblock of another range.
Definition: block_range.h:34
btas::Tensor< typename Tile::value_type > array_to_btas_tensor(const TiledArray::DistArray< Tile, Policy > &src)
Convert a TiledArray::DistArray object into a btas::Tensor object.
Definition: btas.h:259
const TiledArray::Range & make_ta_range(const TiledArray::Range &range)
Definition: btas.h:43
#define TA_USER_ASSERT(a, m)
Definition: error.h:123
extent_type extent() const
Range extent accessor.
Definition: range.h:601
size_type size() const
Definition: dist_array.h:573
const range_type & elements_range() const
Access the element range.
Definition: tiled_range.h:137
const std::shared_ptr< pmap_interface > & pmap() const
Process map accessor.
Definition: dist_array.h:647