QMCPACK
DeterminantOperators.h
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) 2016 Jeongnim Kim and QMCPACK developers.
6 //
7 // File developed by: Ken Esler, kpesler@gmail.com, University of Illinois at Urbana-Champaign
8 // Miguel Morales, moralessilva2@llnl.gov, Lawrence Livermore National Laboratory
9 // Jeongnim Kim, jeongnim.kim@gmail.com, University of Illinois at Urbana-Champaign
10 // Jeremy McMinnis, jmcminis@gmail.com, University of Illinois at Urbana-Champaign
11 // Mark A. Berrill, berrillma@ornl.gov, Oak Ridge National Laboratory
12 //
13 // File created by: Jeongnim Kim, jeongnim.kim@gmail.com, University of Illinois at Urbana-Champaign
14 //////////////////////////////////////////////////////////////////////////////////////
15 
16 
17 /** @file
18  * @brief Define determinant operators
19  */
20 #ifndef OHMMS_NUMERIC_DETERMINANT_H
21 #define OHMMS_NUMERIC_DETERMINANT_H
22 
23 #include <algorithm>
24 #include "OhmmsPETE/TinyVector.h"
25 #include "OhmmsPETE/OhmmsVector.h"
26 #include "OhmmsPETE/OhmmsMatrix.h"
27 #include "CPU/BLAS.hpp"
28 #include "CPU/math.hpp"
33 
34 namespace qmcplusplus
35 {
36 /** LU factorization of double */
37 inline void LUFactorization(int n, int m, double* restrict a, int n0, int* restrict piv)
38 {
39  int status;
40  dgetrf(n, m, a, n0, piv, status);
41 }
42 
43 /** LU factorization of float */
44 inline void LUFactorization(int n, int m, float* restrict a, const int& n0, int* restrict piv)
45 {
46  int status;
47  sgetrf(n, m, a, n0, piv, status);
48 }
49 
50 /** LU factorization of std::complex<double> */
51 inline void LUFactorization(int n, int m, std::complex<double>* restrict a, int n0, int* restrict piv)
52 {
53  int status;
54  zgetrf(n, m, a, n0, piv, status);
55 }
56 
57 /** LU factorization of complex<float> */
58 inline void LUFactorization(int n, int m, std::complex<float>* restrict a, int n0, int* restrict piv)
59 {
60  int status;
61  cgetrf(n, m, a, n0, piv, status);
62 }
63 
64 /** Inversion of a double matrix after LU factorization*/
65 inline void InvertLU(int n, double* restrict a, int n0, int* restrict piv, double* restrict work, int n1)
66 {
67  int status;
68  dgetri(n, a, n0, piv, work, n1, status);
69 }
70 
71 /** Inversion of a float matrix after LU factorization*/
72 inline void InvertLU(const int& n,
73  float* restrict a,
74  const int& n0,
75  int* restrict piv,
76  float* restrict work,
77  const int& n1)
78 {
79  int status;
80  sgetri(n, a, n0, piv, work, n1, status);
81 }
82 
83 /** Inversion of a std::complex<double> matrix after LU factorization*/
84 inline void InvertLU(int n,
85  std::complex<double>* restrict a,
86  int n0,
87  int* restrict piv,
88  std::complex<double>* restrict work,
89  int n1)
90 {
91  int status;
92  zgetri(n, a, n0, piv, work, n1, status);
93 }
94 
95 /** Inversion of a complex<float> matrix after LU factorization*/
96 inline void InvertLU(int n,
97  std::complex<float>* restrict a,
98  int n0,
99  int* restrict piv,
100  std::complex<float>* restrict work,
101  int n1)
102 {
103  int status;
104  cgetri(n, a, n0, piv, work, n1, status);
105 }
106 
107 /** @}*/
108 
109 /** inverse a matrix
110  * @param x starting address of an n-by-m matrix
111  * @param n rows
112  * @param m cols
113  * @param work workspace array
114  * @param pivot integer pivot array
115  * @return determinant
116  */
117 template<class T>
118 inline T Invert(T* restrict x, int n, int m, T* restrict work, int* restrict pivot)
119 {
120  T detvalue(1.0);
121  LUFactorization(n, m, x, n, pivot);
122  for (int i = 0, ip = 1; i < m; i++, ip++)
123  {
124  if (pivot[i] == ip)
125  detvalue *= x[i * m + i];
126  else
127  detvalue *= -x[i * m + i];
128  }
129  InvertLU(n, x, n, pivot, work, n);
130  return detvalue;
131 }
132 
133 /** determinant of a matrix
134  * @param x starting address of an n-by-m matrix
135  * @param n rows
136  * @param m cols
137  * @param pivot integer pivot array
138  * @return determinant
139  */
140 template<class T>
141 inline T Determinant(T* restrict x, int n, int m, int* restrict pivot)
142 {
143  T detvalue(1.0);
144  LUFactorization(n, m, x, n, pivot);
145  for (int i = 0, ip = 1; i < m; i++, ip++)
146  {
147  if (pivot[i] == ip)
148  detvalue *= x[i * m + i];
149  else
150  detvalue *= -x[i * m + i];
151  }
152  return detvalue;
153 }
154 
155 /** inverse a matrix
156  * @param x starting address of an n-by-m matrix
157  * @param n rows
158  * @param m cols
159  * @return determinant
160  *
161  * Workspaces are handled internally.
162  */
163 template<class T>
164 inline T Invert(T* restrict x, int n, int m)
165 {
166  std::vector<int> pivot(n);
167  std::vector<T> work(n);
168  return Invert(x, n, m, work.data(), pivot.data());
169 }
170 
171 template<class T, class T1>
172 inline void InvertWithLog(T* restrict x, int n, int m, T* restrict work, int* restrict pivot, std::complex<T1>& logdet)
173 {
174  LUFactorization(n, m, x, n, pivot);
175  logdet = std::complex<T1>();
176  for (int i = 0; i < n; i++)
177  logdet += std::log(std::complex<T1>((pivot[i] == i + 1) ? x[i * m + i] : -x[i * m + i]));
178  InvertLU(n, x, n, pivot, work, n);
179 }
180 
181 /** invert a matrix
182  * \param M a matrix to be inverted
183  * \param getdet bool, if true, calculate the determinant
184  * \return the determinant
185  */
186 template<class MatrixA>
187 inline typename MatrixA::value_type invert_matrix(MatrixA& M, bool getdet = true)
188 {
189  OMPThreadCountProtectorLA protector;
190  using value_type = typename MatrixA::value_type;
191  const int n = M.rows();
192  std::vector<int> pivot(n);
193  std::vector<value_type> work(n);
194  LUFactorization(n, n, M.data(), n, pivot.data());
195  value_type det0 = 1.0;
196  if (getdet)
197  // calculate determinant
198  {
199  int sign = 1;
200  for (int i = 0; i < n; ++i)
201  {
202  if (pivot[i] != i + 1)
203  sign *= -1;
204  det0 *= M(i, i);
205  }
206  det0 *= static_cast<value_type>(sign);
207  }
208  InvertLU(n, M.data(), n, pivot.data(), work.data(), n);
209  return det0;
210 }
211 
212 /** determinant ratio with a row substitution
213  * @param Minv inverse matrix
214  * @param newv row vector
215  * @param rowchanged row index to be replaced
216  * @return \f$ M^{new}/M\f$
217  */
218 template<typename MatA, typename VecB>
219 inline typename MatA::value_type DetRatioByRow(const MatA& Minv, const VecB& newv, int rowchanged)
220 {
221  return simd::dot(Minv[rowchanged], newv.data(), Minv.cols());
222  //return BLAS::dot(Minv.cols(),Minv[rowchanged],newv.data());
223 }
224 
225 /** determinant ratio with a column substitution
226  * @param Minv inverse matrix
227  * @param newv column vector
228  * @param colchanged column index to be replaced
229  * @return \f$ M^{new}/M\f$
230  */
231 template<typename MatA, typename VecB>
232 inline typename MatA::value_type DetRatioByColumn(const MatA& Minv, const VecB& newv, int colchanged)
233 {
234  //use BLAS dot since the stride is not uniform
235  return simd::dot(Minv.cols(), Minv.data() + colchanged, Minv.cols(), newv.data(), 1);
236 }
237 
238 /** update a inverse matrix by a row substitution
239  * @param Minv in/out inverse matrix
240  * @param newrow row vector
241  * @param rvec workspace
242  * @param rvecinv workspace
243  * @param rowchanged row index to be replaced
244  * @param c_ratio determinant-ratio with the row replacement
245  */
246 template<typename T, typename ALLOC>
248  Vector<T, ALLOC>& newrow,
249  Vector<T, ALLOC>& rvec,
250  Vector<T, ALLOC>& rvecinv,
251  int rowchanged,
252  T c_ratio)
253 {
254  //using gemv+ger
255  det_row_update(Minv.data(), newrow.data(), Minv.cols(), rowchanged, c_ratio, rvec.data(), rvecinv.data());
256  //int ncols=Minv.cols();
257  //typename MatA::value_type ratio_inv=1.0/c_ratio;
258  //for(int j=0; j<ncols; j++) {
259  // if(j == rowchanged) continue;
260  // typename MatA::value_type temp = 0.0;
261  // for(int k=0; k<ncols; k++) temp += newrow[k]*Minv(j,k);
262  // temp *= -ratio_inv;
263  // for(int k=0; k<ncols; k++) Minv(j,k) += temp*Minv(rowchanged,k);
264  //}
265  //for(int k=0; k<ncols; k++) Minv(rowchanged,k) *= ratio_inv;
266 }
267 
268 template<typename T, typename ALLOC>
270  Vector<T, ALLOC>& newcol,
271  Vector<T, ALLOC>& rvec,
272  Vector<T, ALLOC>& rvecinv,
273  int colchanged,
274  T c_ratio)
275 {
276  det_col_update(Minv.data(), newcol.data(), Minv.rows(), colchanged, c_ratio, rvec.data(), rvecinv.data());
277  //int nrows=Minv.rows();
278  //typename MatA::value_type ratio_inv=1.0/c_ratio;
279  //for(int i=0; i<nrows; i++) {
280  // if(i == colchanged) continue;
281  // typename MatA::value_type temp = 0.0;
282  // for(int k=0; k<nrows; k++) temp += newcol[k]*Minv(k,i);
283  // temp *= -ratio_inv;
284  // for(int k=0; k<nrows; k++) Minv(k,i) += temp*Minv(k,colchanged);
285  //}
286  //for(int k=0; k<nrows; k++) Minv(k,colchanged) *= ratio_inv;
287 }
288 } // namespace qmcplusplus
289 #endif
MatrixA::value_type invert_matrix(MatrixA &M, bool getdet=true)
invert a matrix
helper functions for EinsplineSetBuilder
Definition: Configuration.h:43
T Determinant(T *restrict x, int n, int m, int *restrict pivot)
determinant of a matrix
T dot(const T *restrict a, const T *restrict b, int n, TRES res=TRES())
dot product
void InverseUpdateByRow(Matrix< T, ALLOC > &Minv, Vector< T, ALLOC > &newrow, Vector< T, ALLOC > &rvec, Vector< T, ALLOC > &rvecinv, int rowchanged, T c_ratio)
update a inverse matrix by a row substitution
void cgetri(const int &n, std::complex< float > *a, const int &n0, int const *piv, std::complex< float > *work, const int &, int &st)
void LUFactorization(int n, int m, double *restrict a, int n0, int *restrict piv)
LU factorization of double.
void InvertLU(int n, double *restrict a, int n0, int *restrict piv, double *restrict work, int n1)
Inversion of a double matrix after LU factorization.
MatA::value_type DetRatioByRow(const MatA &Minv, const VecB &newv, int rowchanged)
determinant ratio with a row substitution
size_type cols() const
Definition: OhmmsMatrix.h:78
void sgetri(const int &n, float *a, const int &n0, int const *piv, float *work, const int &, int &st)
void InvertWithLog(T *restrict x, int n, int m, T *restrict work, int *restrict pivot, std::complex< T1 > &logdet)
MatA::value_type DetRatioByColumn(const MatA &Minv, const VecB &newv, int colchanged)
determinant ratio with a column substitution
void dgetrf(const int &n, const int &m, double *a, const int &n0, int *piv, int &st)
void cgetrf(const int &n, const int &m, std::complex< float > *a, const int &n0, int *piv, int &st)
void zgetri(const int &n, std::complex< double > *a, const int &n0, int const *piv, std::complex< double > *work, const int &, int &st)
void sgetrf(const int &n, const int &m, float *a, const int &n0, int *piv, int &st)
size_type rows() const
Definition: OhmmsMatrix.h:77
double sign(double x)
Definition: Standard.h:73
MakeReturn< UnaryNode< FnLog, typename CreateLeaf< Vector< T1, C1 > >::Leaf_t > >::Expression_t log(const Vector< T1, C1 > &l)
Declaraton of Vector<T,Alloc> Manage memory through Alloc directly and allow referencing an existing ...
void det_row_update(T *restrict pinv, const T *restrict tv, int m, int rowchanged, T c_ratio, T *restrict temp, T *restrict rcopy)
T Invert(T *restrict x, int n, int m, T *restrict work, int *restrict pivot)
inverse a matrix
void det_col_update(T *restrict pinv, const T *restrict tv, int m, int colchanged, T c_ratio, T *restrict temp, T *restrict rcopy)
QMCTraits::FullPrecRealType value_type
void zgetrf(const int &n, const int &m, std::complex< double > *a, const int &n0, int *piv, int &st)
void dgetri(const int &n, double *a, const int &n0, int const *piv, double *work, const int &, int &st)
void InverseUpdateByColumn(Matrix< T, ALLOC > &Minv, Vector< T, ALLOC > &newcol, Vector< T, ALLOC > &rvec, Vector< T, ALLOC > &rvecinv, int colchanged, T c_ratio)