1 //
2 // BAGEL - Brilliantly Advanced General Electronic Structure Library
3 // Filename: matrix1earray.h
4 // Copyright (C) 2013 Toru Shiozaki
5 //
6 // Author: Shane Parker <shane.parker@u.northwestern.edu>
7 // Maintainer: Shiozaki group
8 //
9 // This file is part of the BAGEL package.
10 //
11 // This program is free software: you can redistribute it and/or modify
12 // it under the terms of the GNU General Public License as published by
13 // the Free Software Foundation, either version 3 of the License, or
14 // (at your option) any later version.
15 //
16 // This program 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 General Public License for more details.
20 //
21 // You should have received a copy of the GNU General Public License
22 // along with this program.  If not, see <http://www.gnu.org/licenses/>.
23 //
24 
25 
26 #ifndef __SRC_MOLECULE_MATRIX1EARRAY_H
27 #define __SRC_MOLECULE_MATRIX1EARRAY_H
28 
29 #include <src/mat1e/matrix1e.h>
30 #include <src/util/taskqueue.h>
31 
32 namespace bagel {
33 
34 template <int N, typename MatType>
35 class Matrix1eArrayTask;
36 
37 // specialized matrix for N component 1e integrals
38 template <int N, typename MatType = Matrix>
39 class Matrix1eArray {
40   friend class Matrix1eArrayTask<N, MatType>;
41   protected:
42     std::array<std::shared_ptr<MatType>, N> matrices_;
43 
44     virtual void init(std::shared_ptr<const Molecule>);
45     virtual void computebatch(const std::array<std::shared_ptr<const Shell>,2>&, const int, const int, std::shared_ptr<const Molecule>) = 0;
46 
47     bool localized_;
48 
49   public:
Matrix1eArray()50     Matrix1eArray() {}
51     Matrix1eArray(const std::shared_ptr<const Molecule>, const bool loc = false);
52     Matrix1eArray(const int n, const int m, const bool loc = false);
53     Matrix1eArray(const Matrix1eArray&);
~Matrix1eArray()54     virtual ~Matrix1eArray() { }
55 
ax_plus_y(const double a,const Matrix1eArray<N,MatType> & o)56     void ax_plus_y(const double a, const Matrix1eArray<N, MatType>& o) {
57       std::transform(o.matrices_.begin(), o.matrices_.end(), matrices_.begin(), matrices_.begin(),
58                      [&a](std::shared_ptr<MatType> p, std::shared_ptr<MatType> q) { q->ax_plus_y(a, p); return q; });
59     }
60 
data(const int i)61     std::shared_ptr<MatType>& data(const int i) { return matrices_[i]; }
data(const int i)62     std::shared_ptr<const MatType> data(const int i) const { return matrices_[i]; }
63 
64     MatType& operator[](const int i) { return *matrices_[i]; }
65     const MatType& operator[](const int i) const { return *matrices_[i]; }
66 
Nblocks()67     constexpr static int Nblocks() { return N; }
68 
fill_upper()69     void fill_upper()       { for (auto& i : matrices_) i->fill_upper(); }
fill_upper_conjg()70     void fill_upper_conjg() { for (auto& i : matrices_) i->fill_upper_conjg(); }
71     template<typename DataType>
scale(const DataType a)72     void scale(const DataType a) { for (auto& i : matrices_) i->scale(a); }
73 
74     virtual void print(const std::string name = "", const int len = 10) const;
75 
localize()76     void localize() {
77       localized_ = true;
78       for (auto& i : matrices_) i->localize();
79     }
80 
81 };
82 
83 template <int N, typename MatType>
Matrix1eArray(const std::shared_ptr<const Molecule> mol,const bool loc)84 Matrix1eArray<N, MatType>::Matrix1eArray(const std::shared_ptr<const Molecule> mol, const bool loc) : localized_(loc) {
85   static_assert(N > 0, "Matrix1eArray should be constructed with N > 0");
86   for(int i = 0; i < N; ++i) {
87     matrices_[i] = std::make_shared<MatType>(mol->nbasis(), mol->nbasis(), loc);
88   }
89 }
90 
91 
92 template <int N, typename MatType>
Matrix1eArray(const int n,const int m,const bool loc)93 Matrix1eArray<N, MatType>::Matrix1eArray(const int n, const int m, const bool loc) : localized_(loc) {
94   static_assert(N > 0, "Matrix1eArray should be constructed with N > 0");
95   for(int i = 0; i < N; ++i) {
96     matrices_[i] = std::make_shared<MatType>(n, m, loc);
97   }
98 }
99 
100 
101 template <int N, typename MatType>
Matrix1eArray(const Matrix1eArray & o)102 Matrix1eArray<N, MatType>::Matrix1eArray(const Matrix1eArray& o) : localized_(o.localized_) {
103   for (int i = 0; i < N; ++i) {
104     *data(i) = *o.data(i);
105   }
106 }
107 
108 
109 template <int N, typename MatType>
print(const std::string name,const int len)110 void Matrix1eArray<N, MatType>::print(const std::string name, const int len) const {
111   int j = 0;
112   for (auto& i : matrices_) {
113     std::stringstream ss; ss << name << " " << j++;
114     i->print(ss.str(), len);
115   }
116 }
117 
118 template <int N, typename MatType>
init(std::shared_ptr<const Molecule> mol)119 void Matrix1eArray<N, MatType>::init(std::shared_ptr<const Molecule> mol) {
120 
121   // identical to Matrix1e::init()
122   // only lower half will be stored
123   const size_t nshell = accumulate(mol->atoms().begin(), mol->atoms().end(), 0, [](int r, std::shared_ptr<const Atom> p) { return r+p->nshell(); });
124   TaskQueue<Matrix1eArrayTask<N, MatType>> task(nshell*(nshell+1)/2);
125 
126   size_t oa0 = 0;
127   int u = 0;
128   for (auto a0 = mol->atoms().begin(); a0 != mol->atoms().end(); ++a0) {
129     // iatom1 = iatom1;
130     size_t ob0 = oa0;
131     for (auto& b0 : (*a0)->shells()) {
132       size_t ob1 = oa0;
133       for (auto& b1 : (*a0)->shells()) {
134         if (u++ % mpi__->size() == mpi__->rank()) {
135           task.emplace_back(std::array<std::shared_ptr<const Shell>,2>{{b1, b0}}, ob0, ob1, mol, this);
136         }
137         ob1 += b1->nbasis();
138       }
139       ob0 += b0->nbasis();
140     }
141 
142     auto oa1 = oa0 + (*a0)->nbasis();
143     for (auto a1 = a0+1; a1 != mol->atoms().end(); ++a1) {
144       size_t ob0 = oa0;
145       for (auto& b0 : (*a0)->shells()) {
146         size_t ob1 = oa1;
147         for (auto& b1 : (*a1)->shells()) {
148           if (u++ % mpi__->size() == mpi__->rank()) {
149             task.emplace_back(std::array<std::shared_ptr<const Shell>,2>{{b1, b0}}, ob0, ob1, mol, this);
150           }
151           ob1 += b1->nbasis();
152         }
153         ob0 += b0->nbasis();
154       }
155       oa1 += (*a1)->nbasis();
156     }
157     oa0 += (*a0)->nbasis();
158   }
159   task.compute();
160   for (auto& i : matrices_) i->allreduce();
161 
162 }
163 
164 template <int N, typename MatType = Matrix>
165 class Matrix1eArrayTask {
166   protected:
167     Matrix1eArray<N, MatType>* parent_;
168     size_t ob0, ob1;
169     std::array<std::shared_ptr<const Shell>,2> bas;
170     std::shared_ptr<const Molecule> mol;
171   public:
172     Matrix1eArrayTask<N, MatType>(std::array<std::shared_ptr<const Shell>,2> a, size_t b, size_t c, std::shared_ptr<const Molecule> m, Matrix1eArray<N, MatType>* d)
parent_(d)173       : parent_(d), ob0(b), ob1(c), bas(a), mol(m) { }
compute()174     void compute() const { parent_->computebatch(bas, ob0, ob1, mol); }
175 };
176 
177 }
178 
179 #endif
180