MPQC 3.0.0-alpha
Loading...
Searching...
No Matches
sigma3.hpp
1#ifndef MPQC_CI_SIGMA3_HPP
2#define MPQC_CI_SIGMA3_HPP
3
4#include "mpqc/ci/ci.hpp"
5#include "mpqc/ci/string.hpp"
6#include "mpqc/ci/subspace.hpp"
7
8#include "mpqc/utility/timer.hpp"
9#include "mpqc/range.hpp"
10#include "mpqc/math/matrix.hpp"
11#include "mpqc/omp.hpp"
12
13#include "mpqc/array.hpp"
14#include "mpqc/array/functions.hpp"
15
16#include <boost/type_traits/is_same.hpp>
17
18namespace mpqc {
19namespace ci {
20
22 struct Excitation {
23 float sgn;
25 int I;
26 int J;
27 };
28
29 // inline bool operator<(const Excitation &a, const Excitation &b) {
30 // // sort by I or by J if I's are the same
31 // return ((a.I != b.I) ? (a.I < b.I) : (a.J < b.J));
32 // }
33
34 inline std::ostream& operator<<(std::ostream &os, const Excitation &r) {
35 os << r.I << " -> " << r.J
36 << ", phase = " << r.sgn
37 << ", ij = " << r.integral;
38 return os;
39 }
40
43 template<class CI, class Spin>
44 void append(const CI &ci,
45 const String &I, const Subspace<Spin> &S,
46 std::vector<Excitation> &V) {
47 // this particular traversal is used to generate semi-ordered list
48 int idx = (int)ci.template strings<Spin>()[I];
49 size_t i = I.size();
50 while (i--) {
51 if (!I[i]) continue; // empty orbital
52 for (size_t j = 0; j < I.size(); ++j) {
53 if (I[j] && (i != j)) continue; // not an empty orbital
54 String J = I.swap(i, j);
55 if (!ci.test(J)) continue;
56 int jdx = (int)ci.template strings<Spin>()[J];
57 if (!S.test(jdx)) continue; // string not in S
58 Excitation t;
59 t.sgn = (float)sgn(I, i, j);
60 t.integral = (int)index(i,j);
61 t.I = idx;
62 t.J = jdx;
63 V.push_back(t);
64 }
65 }
66 }
67
69 template<class Spin>
70 struct Excitations {
71 template<class CI>
72 Excitations(const CI &ci, const Subspace<Spin> &I, const Subspace<Spin> &J)
73 : I_(I), J_(J)
74 {
75 BOOST_FOREACH (int i, I) {
76 append(ci, ci.template strings<Spin>()[i], J, data_);
77 }
78 }
79 typedef std::vector<Excitation>::const_iterator const_iterator;
80 const_iterator begin() const { return data_.begin(); }
81 const_iterator end() const { return data_.end(); }
82 size_t size() const { return data_.size(); }
83 const Excitation& operator[](int i) const { return data_.at(i); }
84 const Subspace<Spin>& I() const { return this->I_; }
85 const Subspace<Spin>& J() const { return this->J_; }
86 private:
87 std::vector<Excitation> data_;
88 Subspace<Spin> I_, J_;
89 };
90
91#define MPQC_CI_SIGMA3_NAIVE
92#ifdef MPQC_CI_SIGMA3_NAIVE
93
95 void sigma3(const Excitations<Alpha> &alpha, const Excitations<Beta> &beta,
96 const Matrix &V, const Matrix &C, Matrix &S) {
97 // beta->beta excitations
98 BOOST_FOREACH (auto b, beta) {
99 // alpha->alpha excitations
100 BOOST_FOREACH (auto a, alpha) {
101 int Ia = a.I;
102 int Ja = a.J;
103 int Ib = b.I;
104 int Jb = b.J;
105 double c = C(Ja - *alpha.J().begin(), Jb - *beta.J().begin());
106 double s = a.sgn*b.sgn*V(a.integral,b.integral)*c;
107 S(Ia - *alpha.I().begin(), Ib - *beta.I().begin()) += s;
108 }
109 }
110 }
111
112#else // MPQC_CI_SIGMA3_NAIVE
113
115 void sigma3(int n, double phase,
116 const double * RESTRICT v,
117 const double * RESTRICT c,
118 double * RESTRICT s) {
119 for (int i = 0; i < n; ++i) {
120 s[i] += phase*c[i]*v[i];
121 }
122 }
123
125 template<class V, class C, class S>
126 void sigma3(int n, double phase, const V &v, const C &c, S &s) {
127 sigma3(n, phase, v.data(), c.data(), s.data());
128 // for (int i = 0; i < n; ++i) {
129 // s[i] += phase*c[i]*v[i];
130 // }
131 }
132
140 template<class SpinA, class SpinB>
141 void sigma3(const Excitations<SpinA> &A, const Excitations<SpinB> &B,
142 const Matrix &V, const Matrix &C, Matrix &S) {
143 static_assert(!boost::is_same<SpinA,SpinB>::value, "spins must not be the same");
144 const int BLOCK = 128;
145 mpqc::Matrix c, v;
146 mpqc::Vector s;
147 std::vector<int> Ia;
148 // iterate over A excitations in blocks
149 for (int ba = 0; ba < A.size(); ba += BLOCK) {
150 int na = std::min<int>(A.size() - ba, BLOCK);
151 c.resize(na, C.cols());
152 v.resize(na, V.cols());
153 Ia.clear();
155 for (int a = 0; a < na; ++a) {
156 auto aa = A[a+ba];
157 c.row(a) = C.row(aa.J - *A.J().begin());
158 v.row(a) = V.col(aa.integral);
159 v.row(a) *= aa.sgn;
160 Ia.push_back(aa.I - *A.I().begin()); // record Ia index
161 }
162 s = mpqc::Vector::Zero(na);
163 for (auto b = B.begin(); b != B.end(); ++b) {
164 int Ib = b->I - *B.I().begin();
165 int Jb = b->J - *B.J().begin();
166 // vectorized s += sgn(Ib,Jb)*v*c
167 sigma3(na, b->sgn, v.col(b->integral), c.col(Jb), s);
168 // next iteration updates same Ib
169 if ((b+1) != B.end() && (b+1)->I == (b)->I) continue;
170 // scatter
171 //mutex.lock();
172 for (int a = 0; a < Ia.size(); ++a) {
173 S(Ia[a], Ib) += s(a);
174 s(a) = 0;
175 }
176 //mutex.unlock();
177 }
178 }
179 }
180
181#endif // MPQC_CI_SIGMA3_NAIVE
182
183}
184}
185
186#endif /* MPQC_CI_SIGMA3_HPP */
187
matrix< double > Matrix
Convience double matrix type.
Definition matrix.hpp:170
Contains new MPQC code since version 3.
Definition integralenginepool.hpp:37
CI class template.
Definition ci.hpp:75
One-particle excitation from string I to string J, {sign, ij, I, J}.
Definition sigma3.hpp:22
int integral
replacement parity, -1 or 1
Definition sigma3.hpp:24
int I
integral index, (i**2+i)/2 + j
Definition sigma3.hpp:25
int J
ref.
Definition sigma3.hpp:26
Vector of single particle excitations from I to J subspace.
Definition sigma3.hpp:70
A range of a space where all objects in the subspace range are assumed to have the same space rank.
Definition subspace.hpp:51
Matrix class derived from Eigen::Matrix with additional MPQC integration.
Definition matrix.hpp:23
Vector class derived from Eigen::Matrix with additional MPQC integration.
Definition matrix.hpp:133

Generated at Wed Sep 25 2024 02:45:30 for MPQC 3.0.0-alpha using the documentation package Doxygen 1.12.0.