MPQC  3.0.0-alpha
taskintegrals.hpp
1 //
2 // taskintegrals.hpp
3 //
4 // Copyright (C) 2013 Drew Lewis
5 //
6 // Authors: Drew Lewis
7 // Maintainer: Drew Lewis and Edward Valeev
8 //
9 // This file is part of the MPQC Toolkit.
10 //
11 // The MPQC Toolkit is free software; you can redistribute it and/or modify
12 // it under the terms of the GNU Library General Public License as published by
13 // the Free Software Foundation; either version 2, or (at your option)
14 // any later version.
15 //
16 // The MPQC Toolkit is distributed in the hope that it will be useful,
17 // but WITHOUT ANY WARRANTY; without even the implied warranty of
18 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 // GNU Library General Public License for more details.
20 //
21 // You should have received a copy of the GNU Library General Public License
22 // along with the MPQC Toolkit; see the file COPYING.LIB. If not, write to
23 // the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
24 //
25 // The U.S. Government is granted a limited license as per AL 91-7.
26 //
27 
28 #ifndef MPQC_CHEMISTRY_QC_BASIS_TASKINTEGRALS_HPP_
29 #define MPQC_CHEMISTRY_QC_BASIS_TASKINTEGRALS_HPP_
30 
31 #include <tiledarray.h>
32 #include <memory>
33 #include <chemistry/qc/basis/tiledbasisset.hpp>
34 #include <mpqc/integrals/integrals.hpp>
35 #include <chemistry/qc/basis/integral.h>
36 
37 namespace mpqc {
38  namespace TA {
39 
42  template<typename T>
43  using PoolPtrType = typename std::pointer_traits<T>::element_type;
44 
45 #ifndef DOXYGEN
46 // Helper class to get Integral Engine typetraits.
47  template<typename IntegralEngine>
48  struct EngineTypeTraits;
49  template<> struct EngineTypeTraits<sc::Ref<sc::TwoBodyInt> > {
50  static const size_t ncenters = 4u;
51  };
52  template<> struct EngineTypeTraits<sc::Ref<sc::TwoBodyThreeCenterInt> > {
53  static const size_t ncenters = 3u;
54  };
55  template<> struct EngineTypeTraits<sc::Ref<sc::TwoBodyTwoCenterInt> > {
56  static const size_t ncenters = 2u;
57  };
58  template<> struct EngineTypeTraits<sc::Ref<sc::OneBodyInt> > {
59  static const size_t ncenters = 2u;
60  };
61  template<> struct EngineTypeTraits<sc::Ref<sc::OneBodyOneCenterInt> > {
62  static const size_t ncenters = 1u;
63  };
64 
65  /*
66  * Does the dirty work of getting integrals into TA::Tiles
67  */
68  namespace int_details {
69  typedef std::vector<int> shell_range;
70 
71 // Takes a shell_range, sc::Engine_Type, and a TensorRef map to a TA::Tile
72  template<typename RefEngine>
73  void get_integrals(const std::vector<shell_range> &s, RefEngine &engine,
74  TensorRef<double, 2, TensorRowMajor> &tile_map) {
75  mpqc::lcao::evaluate(engine, s[0], s[1], tile_map);
76  }
77 
78  template<typename RefEngine>
79  void get_integrals(const std::vector<shell_range> &s, RefEngine &engine,
80  TensorRef<double, 3, TensorRowMajor> &tile_map) {
81  mpqc::lcao::evaluate(engine, s[0], s[1], s[2], tile_map);
82  }
83 
84  template<typename RefEngine>
85  void get_integrals(const std::vector<shell_range> &s, RefEngine &engine,
86  TensorRef<double, 4, TensorRowMajor> &tile_map) {
87  mpqc::lcao::evaluate(engine, s[0], s[1], s[2], s[3], tile_map);
88  }
89 
90  } // namespace int_details
91 
92  /*
93  * Computes shell ranges to pass to a TensorRef for getting integrals
94  */
95  template<typename Tile, typename RefEngine>
96  void get_integrals(Tile &tile, RefEngine &engine) {
97 
98  // Calculate the rank of our tiles
99  constexpr std::size_t rank = EngineTypeTraits<RefEngine>::ncenters;
100  typedef int_details::shell_range shell_range;
101 
102  std::vector<shell_range> ranges(rank);
103 
104  // Loop over each dimension of the tile.
105  for (std::size_t i = 0; i < rank; ++i) {
106 
107  // Get the global indices of the first and last function in a tile
108  // This corresponds to basis functions.
109  const std::size_t first_func = tile.range().lobound()[i];
110  const std::size_t last_func = tile.range().upbound()[i] - 1;
111 
112  // Compute the first and last shell for a given dimension of a tile
113  const std::size_t first_shell = engine->basis(i)->function_to_shell(
114  first_func);
115  const std::size_t last_shell = engine->basis(i)->function_to_shell(
116  last_func);
117 
118  // fill a vector with the shell indices that belong to dimension i
119  for (auto j = first_shell; j < last_shell + 1; ++j) {
120  ranges[i].push_back(j);
121  }
122  }
123 
124  // passes the TiledArray size into a fixed c-style array for Tensor class
125  const std::size_t (&dim)[rank] =
126  *reinterpret_cast<const std::size_t (*)[rank]>(tile.range().extent_data());
127 
128  TensorRef<double, rank, TensorRowMajor> tile_map(tile.data(), dim);
129 
130  int_details::get_integrals(ranges, engine, tile_map);
131 
132  }
133 
134  template<typename ShrPtrPool, typename It, class A>
135  void make_integral_task(It first, It last, const A &array, ShrPtrPool pool);
136 
137  /*
138  * Splits work in into manageable chunks by creating tasks. And then fills
139  * each tile with integrals.
140  */
141  template<typename ShrPtrPool, typename It, class A>
142  void integral_task(It first, It last, A &array, ShrPtrPool &pool) {
143 
144  // Divide work. If the distance between the first and last pointer
145  // is greater than some number then split the range in half and send
146  // half of the work to another task. Continue to do this until
147  // the distance between the pointers is small enough.
148  while (last - first > 10) {
149  It middle = first;
150  std::advance(middle, std::distance(first, last) / 2);
151  make_integral_task(middle, last, array, pool);
152  last = middle;
153  }
154 
155  // Once the pointer range is small enough unwrap the engine type
156  // and get a local instance
157  typename PoolPtrType<ShrPtrPool>::engine_type engine = pool->instance();
158 
159  // Loop over the iterator range and create tiles to populate the
160  // TiledArray. Fill the tiles with data in get_integrals
161  for (; first != last; ++first) {
162  typename A::value_type tile(array.trange().make_tile_range(*first));
163  get_integrals(tile, engine);
164 
165  array.set(*first, tile);
166  }
167  }
168 
169  /*
170  * Spawns tasks to fill tiles with integrals.
171  */
172  template<typename ShrPtrPool, typename It, class A>
173  void make_integral_task(It first, It last, const A &array, ShrPtrPool pool){
174  array.world().taskq.add(&integral_task<ShrPtrPool, It, A>, first, last,
175  array, pool);
176  }
177 
178 #endif //DOXYGEN
179 
184  template<typename ShrPtrPool, class A>
185  void fill_tiles(A &array, const ShrPtrPool &pool) {
186 
187  // get pointers
188  auto begin = array.pmap()->begin();
189  auto end = array.pmap()->end();
190 
191  // Create tasks to fill tiles with data. Boost const reference is used
192  // because Integral Engine pool is not copyable, but when sent to the
193  // Madness task queue all objects are copied.
194  make_integral_task(begin, end, array, pool);
195  }
196 
199 
200  template<typename ShrPtrPool>
201  ::TiledArray::Array<double,
202  EngineTypeTraits<typename PoolPtrType<ShrPtrPool>::engine_type>::ncenters >
203  Integrals(
204  madness::World &world, const ShrPtrPool &pool,
205  const sc::Ref<mpqc::TA::TiledBasisSet> &tbasis) {
206 
207  namespace TA = ::TiledArray;
208 
209  // Get the the type of integral that we are computing.
210  typedef typename PoolPtrType<ShrPtrPool>::engine_type engine_type;
211  // Determine the dimensions of our integrals as well as our TiledArray
212  constexpr size_t rank = EngineTypeTraits<engine_type>::ncenters;
213 
214  // Get the array to initialize the TiledArray::TiledRange using the
215  // TiledBasis
216  std::array<TiledArray::TiledRange1, rank> blocking;
217  for (auto i = 0; i < rank; ++i) {
218  blocking[i] = tbasis->trange1();
219  }
220 
221  // Construct the TiledArray::TiledRange object
222  TA::TiledRange trange(blocking.begin(), blocking.end());
223 
224  // Initialize the TiledArray
225  TA::Array<double, rank> array(world, trange);
226 
227  // Fill the TiledArray with data by looping over tiles and sending
228  // each tile to a madness task to be filled in parallel.
229  fill_tiles(array, pool);
230 
231  return array;
232  }
233 
234  template<typename ShrPtrPool>
235  ::TiledArray::Array<double,
236  EngineTypeTraits<typename PoolPtrType<ShrPtrPool>::engine_type>::ncenters >
237  Integrals( madness::World &world, const ShrPtrPool &pool,
238  const sc::Ref<mpqc::TA::TiledBasisSet> &tbasis,
239  const sc::Ref<mpqc::TA::TiledBasisSet> &dftbasis) {
240 
241  namespace TA = ::TiledArray;
242 
243  // Get the the type of integral that we are computing.
244  typedef typename PoolPtrType<ShrPtrPool>::engine_type engine_type;
245  // Determine the dimensions of our integrals as well as our TiledArray
246  constexpr size_t rank = EngineTypeTraits<engine_type>::ncenters;
247 
248  // Get the array to initialize the TiledArray::TiledRange using the
249  // TiledBasis
250  std::array<TiledArray::TiledRange1, rank> blocking;
251  for (auto i = 0; i < (rank - 1); ++i) {
252  blocking[i] = tbasis->trange1(); // Asign first 2 dims to regular basis
253  }
254  blocking.back() = dftbasis->trange1(); // Asign last dim to df basis
255 
256  // Construct the TiledArray::TiledRange object
257  TA::TiledRange trange(blocking.begin(), blocking.end());
258 
259  // Initialize the TiledArray
260  TA::Array<double, rank> array(world, trange);
261 
262  // Fill the TiledArray with data by looping over tiles and sending
263  // each tile to a madness task to be filled in parallel.
264  fill_tiles(array, pool);
265 
266  return array;
267  }
268 
270 
271  }// namespace TA
272 } // namespace mpqc
273 
274 #endif /* MPQC_CHEMISTRY_QC_BASIS_TASKINTEGRALS_HPP_ */
mpqc
Contains new MPQC code since version 3.
Definition: integralenginepool.hpp:37
sc::Ref< mpqc::TA::TiledBasisSet >
mpqc::TA::TiledBasisSet::trange1
TiledArray::TiledRange1 trange1() const
Returns the tiled range object describing the tiling of basis functions in this basis.
mpqc::TA::fill_tiles
void fill_tiles(A &array, const ShrPtrPool &pool)
Initial function called to fill a TiledArray with integrals.
Definition: taskintegrals.hpp:185
mpqc::lcao::evaluate
void evaluate(sc::Ref< sc::OneBodyInt > &engine, const std::vector< int > &P, const std::vector< int > &Q, TensorRef< double, 2, TensorRowMajor > &ints)
Evaluate set of shell blocks of integrals (p|O|q)
Definition: integrals.hpp:206
shell_iterable
Definition: cadf_attic.h:330
sc
Contains all MPQC code up to version 3.
Definition: mpqcin.h:14

Generated at Sun Jan 26 2020 23:23:57 for MPQC 3.0.0-alpha using the documentation package Doxygen 1.8.16.