MPQC  3.0.0-alpha
purification.hpp
1 //
2 // purification.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_INTERFACES_PURIFICATION_HPP
29 #define MPQC_INTERFACES_PURIFICATION_HPP
30 
31 #include <mpqc/math/matrix.hpp>
32 #include <tiledarray.h>
33 #include <array>
34 
35 namespace mpqc {
36 namespace purification {
37 
38  using TArray2 = TA::Array<double, 2>;
39  // Holds data we want for each type of algorithm
40  struct performance {
41  std::size_t multiplies;
42  std::size_t adds;
43  std::size_t traces;
44  };
45 
46  // Compute Eigenvalue Estimates first element is largest eigenvalue.
47  std::array<double ,2> BoundsTA(const TArray2 &F){
48  // make madness::Group all process that contain important row.
49  // define local reduction reduces tiles into the vector
50  // global reduction to finish the vector off.
51  // or maybe an all reduce
52  // Final
53 
54  double min = 10, max = -10;
55  return {{max, min}};
56  }
57 
58  std::array<double, 2> Bounds(const Matrix &F){
59  auto n = F.rows();
60  double min = 10;
61  for(auto i = 0; i < n; ++i){
62  double row_sum = 0;
63  for(auto j = 0; j < n; ++j){
64  row_sum += (j != i) ? -std::abs(F(i,j)) : F(i,i);
65  }
66  min = (row_sum < min) ? row_sum : min;
67  }
68 
69  double max = -10;
70  for(auto i = 0; i < n; ++i){
71  double row_sum = 0;
72  for(auto j = 0; j < n; ++j){
73  row_sum += (j != i) ? std::abs(F(i,j)) : F(i,i);
74  }
75  max = (row_sum > max) ? row_sum : max;
76  }
77  return {{max, min}};
78  }
79 
80  // Performs Trace Resetting Purification and returns number of multiplies and additions
81  performance tr_pure(const TArray2 &F, TArray2 &D, std::size_t occ){
82  performance data;
83  data.multiplies = 0;
84  data.adds = 1;
85  data.traces = 1; // Start at 1 since last while loop won't be counted
86  // and has one of each.
87  auto E = Bounds(F);
88 
89  Matrix I = Eigen::MatrixXd::Identity(F.rows(), F.cols());
90 
91  D = (E[0] * I - F)/(E[0] - E[1]);
92  data.adds++;
93 
94  Matrix IDD = (I - D) * D;
95  data.adds++; data.multiplies++;
96 
97  while((IDD).lpNorm<Eigen::Infinity>() > 1e-6){ // While D^2 != D
98  data.adds++; // Update counters
99 
100  int gamma = (occ - D.trace() > 0) ? 1 : -1;
101  data.traces++;
102 
103  D = D + gamma * IDD;
104  data.adds++;
105  D = 0.5 * Matrix(D + D.transpose());
106  IDD = (I - D) * D;
107  data.adds++; data.multiplies++;
108 
109  }
110  return data;
111  }
112 
113  Matrix Fpure(Matrix &D){
114  Matrix I = Eigen::MatrixXd::Identity(D.rows(), D.cols());
115  return Matrix(D * D * D * (4 * I - 3 * D));
116  }
117 
118  Matrix Gpure(Matrix &D){
119  Matrix I = Eigen::MatrixXd::Identity(D.rows(), D.cols());
120  return Matrix( D * D * (I - D) * (I - D));
121  }
122 
123  performance fourth_order_pure(const Matrix &F, Matrix &D, std::size_t occ){
124  performance data;
125  data.multiplies = 0;
126  data.adds = 1;
127  data.traces = 1; // Start at 1 since last while loop won't be counted
128  // and has one of each.
129  auto E = Bounds(F);
130 
131  Matrix I = Eigen::MatrixXd::Identity(F.rows(), F.cols());
132 
133  D = (E[0] * I - F)/(E[0] - E[1]);
134  data.adds++;
135 
136  Matrix D2 = D*D;
137  data.multiplies++;
138 
139  while((D - D2).lpNorm<Eigen::Infinity>() > 1e-9){ // While D^2 != D
140  data.adds++; // Update counters
141 
142  Matrix D3 = D2 * D;
143  Matrix ID = I - D;
144  data.adds++; data.multiplies++;
145 
146  double gamma = (double(occ) - Matrix(D3 * (4 * I - 3 * D)).trace())/
147  (Matrix(D2 * ID * ID).trace());
148  data.adds += 1; data.multiplies += 3; data.traces += 2;
149  if(gamma >= 6) {
150  D = 2 * D - D2;
151  data.adds++;
152  }
153  else if (gamma < 0){
154  D = D2;
155  }
156  else {
157  D = D3 * (4 * I - 3 * D) + gamma * (D2 * ID * ID);
158  data.adds += 4; data.multiplies += 3;
159  }
160  D2 = D * D;
161  data.multiplies++;
162  }
163 
164  return data;
165  }
166 
167  performance canonical_pure(const Matrix &F, Matrix &D, std::size_t occ){
168  performance data;
169  data.multiplies = 1;
170  data.adds = 1;
171  data.traces = 1; // Start at 1 since last while loop won't be counted
172  // and has one of each.
173  auto n = F.rows();
174  auto E = Bounds(F);
175 
176  Matrix I = Eigen::MatrixXd::Identity(n, n);
177  double mu = F.trace()/n;
178  data.traces++;
179  double lambda = std::min(double(occ)/(E[0]-mu),
180  double(n-occ)/(mu - E[1]));
181  D = (lambda/double(n)) * (mu * I - F) + double(occ)/double(n) * I;
182  data.adds += 2;
183 
184  Matrix D2 = D * D;
185  data.multiplies++;
186 
187  while((D - D2).lpNorm<Eigen::Infinity>() > 1e-6
188  ){ // While D^2 != D
189  data.adds++; // Update counters
190 
191  Matrix D3 = D2 * D;
192  data.multiplies++;
193 
194  double c = (Matrix(D2 - D3).trace())/
195  (Matrix(D - D2).trace());
196  data.adds += 2; data.traces +=2;
197  if(c >= 0.5){
198  D = (1.0/c) * ((1 + c) * D2 - D3);
199  data.adds += 1;
200  } else {
201  D = 1.0/(1.0 - c) * ((1 - 2*c) * D + (1 + c)*D2 - D3);
202  data.adds += 2;
203  }
204 
205  D2 = D * D;
206  data.multiplies++;
207  }
208 
209  return data;
210  }
211 } // namespace purification
212 } // namespace mpqc
213 
214 
215 
216 
217 
218 
219 #endif /* MPQC_INTERFACES_PURIFICATION_HPP */
mpqc
Contains new MPQC code since version 3.
Definition: integralenginepool.hpp:37
mpqc::Matrix
matrix< double > Matrix
Convience double matrix type.
Definition: matrix.hpp:170
mpqc::purification::performance
Definition: purification.hpp:40

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