MPQC  3.0.0-alpha
preconditioner.hpp
1 #ifndef MPQC_CI_PRECONDITIONER_HPP
2 #define MPQC_CI_PRECONDITIONER_HPP
3 
4 #include "mpqc/ci/hamiltonian.hpp"
5 #include "mpqc/ci/vector.hpp"
6 #include "mpqc/math/matrix.hpp"
7 #include <boost/foreach.hpp>
8 #include "mpqc/mpi.hpp"
9 #include "mpqc/mpi/task.hpp"
10 
11 #include "mpqc/utility/profile.hpp"
12 
13 namespace mpqc {
14 namespace ci {
15 
16  void symmetrize(mpqc::Matrix &a, double phase, double scale) {
17  MPQC_CHECK(a.rows() == a.cols());
18  for (size_t j = 0; j < a.cols(); ++j) {
19  a(j,j) *= scale;
20  for (size_t i = 0; i < j; ++i) {
21  a(i,j) = scale*a(i,j); // + a(j,i));
22  a(j,i) = phase*a(i,j);
23  }
24  }
25  }
26 
27  template<class Type, class Index>
28  void preconditioner(CI<Type, Index> &ci,
29  const mpqc::Vector &h, const mpqc::Matrix &V,
30  double lambda, ci::Vector &D) {
31 
32  MPQC_PROFILE_LINE;
33 
34  const auto &comm = ci.comm;
35  const auto &alpha = ci.alpha;
36  const auto &beta = ci.beta;
37 
38  double dd = 0;
39 
40  const std::vector< Subspace<Alpha> > &A = ci.subspace.alpha();
41  const std::vector< Subspace<Beta> > &B = ci.subspace.beta();
42  const auto &blocks = ci::blocks(A, B);
43 
44  std::unique_ptr<MPI::Task> task;
45 
46  task.reset(new MPI::Task(comm));
47 #pragma omp parallel
48  while (true) {
49 
50  auto next = task->next(blocks.begin(), blocks.end());
51  if (next == blocks.end()) break;
52 
53  auto Ia = A.at(next->alpha);
54  auto Ib = B.at(next->beta);
55  if (!ci.test(Ia,Ib)) continue;
56 
57  mpqc::Matrix d = D(Ia,Ib);
58  mpqc::Vector aa(Ia.size());
59  for (int a = 0; a < Ia.size(); ++a) {
60  aa(a) = diagonal(alpha[*Ia.begin() + a], h, V);
61  }
62  for (int j = 0; j < Ib.size(); ++j) {
63  const String &bj = beta[*Ib.begin() + j];
64  double bb = diagonal(bj, h, V);
65  for (int a = 0; a < Ia.size(); ++a) {
66  double q = diagonal2(alpha[*Ia.begin() + a], bj, V);
67  q = (lambda - (q + aa(a) + bb));
68  d(a,j) = (fabs(q) > 1.0e-4) ? d(a,j)/q : 0;
69  }
70  }
71  D(Ia,Ib) = d;
72  dd += dot(d, d);
73  }
74  comm.sum(dd);
75  D.sync();
76 
77  if (ci.config.ms != 0) {
78  throw MPQC_EXCEPTION("Preconditioner not yet implemented for ci.ms != 0");
79  }
80 
81  double phase = 1.0;
82  double scale = 1.0/sqrt(dd);
83 
84  task.reset(new MPI::Task(comm));
85 #pragma omp parallel
86  while (true) {
87 
88  auto next = task->next(blocks.begin(), blocks.end());
89  if (next == blocks.end()) break;
90 
91  auto Ia = A.at(next->alpha);
92  auto Ib = B.at(next->beta);
93  if (!ci.test(Ia,Ib)) continue;
94 
95  if (next->alpha == next->beta) {
96  Matrix aa = D(Ia,Ib);
97  ci::symmetrize(aa, phase, scale);
98  D(Ia,Ib) = aa;
99  }
100 
101  if (next->alpha < next->beta) {
102  Matrix ab = D(Ia,Ib);
103  Matrix ba = D(Ib,Ia);
104  ab *= scale;
105  ba = phase*(ab.transpose());
106  D(Ia,Ib) = ab;
107  D(Ib,Ia) = ba;
108  }
109 
110  }
111  D.sync();
112 
113  }
114 
115 } // namespace ci
116 } // namespace mpqc
117 
118 
119 #endif /* MPQC_CI_PRECONDITIONER_HPP */
mpqc
Contains new MPQC code since version 3.
Definition: integralenginepool.hpp:37
mpqc::matrix
Matrix class derived from Eigen::Matrix with additional MPQC integration.
Definition: matrix.hpp:21
sc::symmetrize
void symmetrize(const Ref< GPetiteList2 > &plist2, const Ref< Integral > &integral, const RefSymmSCMatrix &skel, const RefSymmSCMatrix &sym)
Uses plist2 to convert the "skeleton" matrix into the full matrix. Only applicable when the two basis...
mpqc::Matrix
matrix< double > Matrix
Convience double matrix type.
Definition: matrix.hpp:170
MPQC_EXCEPTION
#define MPQC_EXCEPTION(...)
Definition: exception.hpp:51
mpqc::dot
T dot(const matrix< T > &a, const matrix< T > &b)
element-wise dot product of two matrices
Definition: matrix.hpp:186
mpqc::Vector
vector< double > Vector
Convience double vector type.
Definition: matrix.hpp:172
mpqc::vector
Vector class derived from Eigen::Matrix with additional MPQC integration.
Definition: matrix.hpp:133

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