QMCPACK
LinearMethod.cpp
Go to the documentation of this file.
1 //////////////////////////////////////////////////////////////////////////////////////
2 // This file is distributed under the University of Illinois/NCSA Open Source License.
3 // See LICENSE file in top directory for details.
4 //
5 // Copyright (c) 2020 QMCPACK developers.
6 //
7 // File developed by: Jeremy McMinnis, jmcminis@gmail.com, University of Illinois at Urbana-Champaign
8 // Jeongnim Kim, jeongnim.kim@gmail.com, University of Illinois at Urbana-Champaign
9 // Jaron T. Krogel, krogeljt@ornl.gov, Oak Ridge National Laboratory
10 // Miguel Morales, moralessilva2@llnl.gov, Lawrence Livermore National Laboratory
11 // Ye Luo, yeluo@anl.gov, Argonne National Laboratory
12 // Mark A. Berrill, berrillma@ornl.gov, Oak Ridge National Laboratory
13 // Mark Dewing, mdewing@anl.gov, Argonne National Laboratory
14 //
15 // File created by: Jeremy McMinnis, jmcminis@gmail.com, University of Illinois at Urbana-Champaign
16 //////////////////////////////////////////////////////////////////////////////////////
17 
18 
19 #include "LinearMethod.h"
20 #include "Eigensolver.h"
21 #include <vector>
22 #include "QMCCostFunctionBase.h"
23 #include <CPU/BLAS.hpp>
26 
27 
28 namespace qmcplusplus
29 {
30 
32 {
33  int Nl(ev.size());
34  std::vector<Real> alphar(Nl);
35  Matrix<Real> eigenT(Nl, Nl);
36  Real zerozero = A(0, 0);
38  return selectEigenvalue(alphar, eigenT, zerozero, ev);
39 }
40 
42 {
43  int Nl(ev.size());
44  std::vector<Real> alphar(Nl);
45  Matrix<Real> eigenT(Nl, Nl);
46  Real zerozero = A(0, 0);
48  return selectEigenvalue(alphar, eigenT, zerozero, ev);
49 }
50 
51 // Input
52 // -eigenvals
53 // -eigenvectors
54 // Returns selected eigenvalue
55 // - ev - scaled eigenvector corresponding to selected eigenvalue
56 
58  Matrix<Real>& eigenvectors,
59  Real zerozero,
60  std::vector<Real>& ev)
61 {
62  // Filter and sort to find desired eigenvalue.
63  // Filter accepts eigenvalues between E_0 and E_0 - 100.0,
64  // where E_0 is H(0,0), the current estimate for the VMC energy.
65  // Sort searches for eigenvalue closest to E_0 - 2.0
66  int Nl = eigenvals.size();
67 
68  bool found_any_eigenvalue = false;
69  std::vector<std::pair<Real, int>> mappedEigenvalues(Nl);
70  for (int i = 0; i < Nl; i++)
71  {
72  Real evi(eigenvals[i]);
73  if ((evi < zerozero) && (evi > (zerozero - 1e2)))
74  {
75  mappedEigenvalues[i].first = (evi - zerozero + 2.0) * (evi - zerozero + 2.0);
76  mappedEigenvalues[i].second = i;
77  found_any_eigenvalue = true;
78  }
79  else
80  {
81  mappedEigenvalues[i].first = std::numeric_limits<Real>::max();
82  mappedEigenvalues[i].second = i;
83  }
84  }
85 
86  // Sometimes there is no eigenvalue less than E_0, but there is one slightly higher.
87  // Run filter and sort again, except this time accept eigenvalues between E_0 + 100.0 and E_0 - 100.0.
88  // Since it's already been determined there are no eigenvalues below E_0, the sort
89  // finds the eigenvalue closest to E_0.
90  if (!found_any_eigenvalue)
91  {
92  app_log() << "No eigenvalues passed initial filter. Trying broader 100 a.u. filter" << std::endl;
93 
94  bool found_higher_eigenvalue;
95  for (int i = 0; i < Nl; i++)
96  {
97  Real evi(eigenvals[i]);
98  if ((evi < zerozero + 1e2) && (evi > (zerozero - 1e2)))
99  {
100  mappedEigenvalues[i].first = (evi - zerozero + 2.0) * (evi - zerozero + 2.0);
101  mappedEigenvalues[i].second = i;
102  found_higher_eigenvalue = true;
103  }
104  else
105  {
106  mappedEigenvalues[i].first = std::numeric_limits<Real>::max();
107  mappedEigenvalues[i].second = i;
108  }
109  }
110  if (!found_higher_eigenvalue)
111  {
112  app_log() << "No eigenvalues passed second filter. Optimization is likely to fail." << std::endl;
113  }
114  }
115  std::sort(mappedEigenvalues.begin(), mappedEigenvalues.end());
116  // for (int i=0; i<4; i++) app_log()<<i<<": "<<alphar[mappedEigenvalues[i].second]<< std::endl;
117  for (int i = 0; i < Nl; i++)
118  ev[i] = eigenvectors(mappedEigenvalues[0].second, i) / eigenvectors(mappedEigenvalues[0].second, 0);
119  return eigenvals[mappedEigenvalues[0].second];
120 }
121 
122 
124 {
125  int Nl(ev.size());
126  // Getting the optimal worksize
127  Real zerozero = A(0, 0);
128  char jl('N');
129  char jr('V');
130  std::vector<Real> alphar(Nl), alphai(Nl), beta(Nl);
131  Matrix<Real> eigenT(Nl, Nl);
132  Matrix<Real> eigenD(Nl, Nl);
133  int info;
134  int lwork(-1);
135  std::vector<Real> work(1);
136  LAPACK::geev(&jl, &jr, &Nl, A.data(), &Nl, &alphar[0], &alphai[0], eigenD.data(), &Nl, eigenT.data(), &Nl, &work[0],
137  &lwork, &info);
138  lwork = int(work[0]);
139  work.resize(lwork);
140 
141  LAPACK::geev(&jl, &jr, &Nl, A.data(), &Nl, &alphar[0], &alphai[0], eigenD.data(), &Nl, eigenT.data(), &Nl, &work[0],
142  &lwork, &info);
143  if (info != 0)
144  {
145  APP_ABORT("Invalid Matrix Diagonalization Function!");
146  }
147 
148  // Filter and sort to find desired eigenvalue.
149  // Filter accepts eigenvalues between E_0 and E_0 - 100.0,
150  // where E_0 is H(0,0), the current estimate for the VMC energy.
151  // Sort searches for eigenvalue closest to E_0 - 2.0
152 
153  bool found_any_eigenvalue = false;
154  std::vector<std::pair<Real, int>> mappedEigenvalues(Nl);
155  for (int i = 0; i < Nl; i++)
156  {
157  Real evi(alphar[i]);
158  if ((evi < zerozero) && (evi > (zerozero - 1e2)))
159  {
160  mappedEigenvalues[i].first = (evi - zerozero + 2.0) * (evi - zerozero + 2.0);
161  mappedEigenvalues[i].second = i;
162  found_any_eigenvalue = true;
163  }
164  else
165  {
166  mappedEigenvalues[i].first = std::numeric_limits<Real>::max();
167  mappedEigenvalues[i].second = i;
168  }
169  }
170 
171  // Sometimes there is no eigenvalue less than E_0, but there is one slightly higher.
172  // Run filter and sort again, except this time accept eigenvalues between E_0 + 100.0 and E_0 - 100.0.
173  // Since it's already been determined there are no eigenvalues below E_0, the sort
174  // finds the eigenvalue closest to E_0.
175  if (!found_any_eigenvalue)
176  {
177  app_log() << "No eigenvalues passed initial filter. Trying broader 100 a.u. filter" << std::endl;
178 
179  bool found_higher_eigenvalue;
180  for (int i = 0; i < Nl; i++)
181  {
182  Real evi(alphar[i]);
183  if ((evi < zerozero + 1e2) && (evi > (zerozero - 1e2)))
184  {
185  mappedEigenvalues[i].first = (evi - zerozero + 2.0) * (evi - zerozero + 2.0);
186  mappedEigenvalues[i].second = i;
187  found_higher_eigenvalue = true;
188  }
189  else
190  {
191  mappedEigenvalues[i].first = std::numeric_limits<Real>::max();
192  mappedEigenvalues[i].second = i;
193  }
194  }
195  if (!found_higher_eigenvalue)
196  {
197  app_log() << "No eigenvalues passed second filter. Optimization is likely to fail." << std::endl;
198  }
199  }
200  std::sort(mappedEigenvalues.begin(), mappedEigenvalues.end());
201  // for (int i=0; i<4; i++) app_log()<<i<<": "<<alphar[mappedEigenvalues[i].second]<< std::endl;
202  for (int i = 0; i < Nl; i++)
203  ev[i] = eigenT(mappedEigenvalues[0].second, i) / eigenT(mappedEigenvalues[0].second, 0);
204  return alphar[mappedEigenvalues[0].second];
205  // }
206 }
207 
208 void LinearMethod::getNonLinearRange(int& first, int& last, const QMCCostFunctionBase& optTarget) const
209 {
210  std::vector<int> types;
211  optTarget.getParameterTypes(types);
212  first = 0;
213  last = types.size();
214  //assume all non-linear coeffs are together.
215  if (types[0] == optimize::LINEAR_P)
216  {
217  int i(0);
218  while (i < types.size())
219  {
220  if (types[i] == optimize::LINEAR_P)
221  first = i;
222  i++;
223  }
224  first++;
225  }
226  else
227  {
228  int i(types.size() - 1);
229  while (i >= 0)
230  {
231  if (types[i] == optimize::LINEAR_P)
232  last = i;
233  i--;
234  }
235  }
236  // returns the number of non-linear parameters.
237  // app_log()<<"line params: "<<first<<" "<<last<< std::endl;
238 }
239 
241  Matrix<Real>& S,
242  const QMCCostFunctionBase& optTarget) const
243 {
244  int first(0), last(0);
245  getNonLinearRange(first, last, optTarget);
246  if (first == last)
247  return 1.0;
248  Real rescale(1.0);
249  Real xi(0.5);
250  Real D(0.0);
251  for (int i = first; i < last; i++)
252  for (int j = first; j < last; j++)
253  D += S(i + 1, j + 1) * dP[i + 1] * dP[j + 1];
254  rescale = (1 - xi) * D / ((1 - xi) + xi * std::sqrt(1 + D));
255  rescale = 1.0 / (1.0 - rescale);
256  // app_log()<<"rescale: "<<rescale<< std::endl;
257  return rescale;
258 }
259 
260 
261 } // namespace qmcplusplus
void getNonLinearRange(int &first, int &last, const QMCCostFunctionBase &optTarget) const
helper functions for EinsplineSetBuilder
Definition: Configuration.h:43
static void solveGeneralizedEigenvalues(Matrix< Real > &A, Matrix< Real > &B, std::vector< Real > &eigenvals, Matrix< Real > &eigenvectors)
Use generalized eigenvalue solver.
Definition: Eigensolver.cpp:32
std::ostream & app_log()
Definition: OutputManager.h:65
LinearMethod related functions.
QMCTraits::RealType Real
Definition: LinearMethod.h:33
static Real getLowestEigenvector_Inv(Matrix< Real > &A, Matrix< Real > &B, std::vector< Real > &ev)
Solve the generalized eigenvalue problem and return a scaled eigenvector corresponding to the selecte...
static void solveGeneralizedEigenvalues_Inv(Matrix< Real > &A, Matrix< Real > &B, std::vector< Real > &eigenvals, Matrix< Real > &eigenvectors)
Solve by explicitly inverting the overlap matrix.
Definition: Eigensolver.cpp:78
static Real getLowestEigenvector_Gen(Matrix< Real > &A, Matrix< Real > &B, std::vector< Real > &ev)
Solve the generalized eigenvalue problem and return a scaled eigenvector corresponding to the selecte...
void getParameterTypes(std::vector< int > &types) const
Real getLowestEigenvector(Matrix< Real > &A, std::vector< Real > &ev) const
#define APP_ABORT(msg)
Widely used but deprecated fatal error macros from legacy code.
Definition: AppAbort.h:27
Implements wave-function optimization.
Define determinant operators.
MakeReturn< UnaryNode< FnSqrt, typename CreateLeaf< Vector< T1, C1 > >::Leaf_t > >::Expression_t sqrt(const Vector< T1, C1 > &l)
double B(double x, int k, int i, const std::vector< double > &t)
static Real selectEigenvalue(std::vector< Real > &eigenvals, Matrix< Real > &eigenvectors, Real zerozero, std::vector< Real > &ev)
Select eigenvalue and return corresponding scaled eigenvector.
static void geev(char *jobvl, char *jobvr, int *n, double *a, int *lda, double *alphar, double *alphai, double *vl, int *ldvl, double *vr, int *ldvr, double *work, int *lwork, int *info)
Definition: BLAS.hpp:594
Real getNonLinearRescale(std::vector< Real > &dP, Matrix< Real > &S, const QMCCostFunctionBase &optTarget) const