QMCPACK
test_DiracMatrix.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) 2017 Jeongnim Kim and QMCPACK developers.
6 //
7 // File developed by: Mark Dewing, mdewing@anl.gov, Argonne National Laboratory
8 //
9 // File created by: Mark Dewing, mdewing@anl.gov, Argonne National Laboratory
10 //////////////////////////////////////////////////////////////////////////////////////
11 
12 
13 #include "catch.hpp"
14 
15 #include "OhmmsData/Libxml2Doc.h"
16 #include "OhmmsPETE/OhmmsMatrix.h"
21 #include "checkMatrix.hpp"
22 #include "createTestMatrix.h"
23 
24 #include <stdio.h>
25 #include <string>
26 
27 using std::string;
28 
29 namespace qmcplusplus
30 {
33 using LogValue = std::complex<QMCTraits::QTFull::RealType>;
35 
36 TEST_CASE("DiracMatrix_identity", "[wavefunction][fermion]")
37 {
39 
40  Matrix<ValueType> m, m_invT;
41  LogValue log_value;
42  m.resize(3, 3);
43  m_invT.resize(3, 3);
44 
46 
47  dm.invert_transpose(m, m_invT, log_value);
48  CHECK(log_value == LogComplexApprox(0.0));
49 
51  eye.resize(3, 3);
52  fillIdentityMatrix(eye);
53 
55  CHECKED_ELSE(check_matrix_result.result) { FAIL(check_matrix_result.result_message); }
56 }
57 
58 TEST_CASE("DiracMatrix_inverse", "[wavefunction][fermion]")
59 {
61 
62  Matrix<ValueType> a, a_T, a_inv;
63  LogValue log_value;
64  a.resize(3, 3);
65  a_T.resize(3, 3);
66  a_inv.resize(3, 3);
67 
69 
70  simd::transpose(a.data(), a.rows(), a.cols(), a_T.data(), a_T.rows(), a_T.cols());
71  dm.invert_transpose(a_T, a_inv, log_value);
73 
75  b.resize(3, 3);
76 
78 
79  auto check_matrix_result = checkMatrix(a_inv, b);
80  CHECKED_ELSE(check_matrix_result.result) { FAIL(check_matrix_result.result_message); }
81 }
82 
83 TEST_CASE("DiracMatrix_inverse_matching", "[wavefunction][fermion]")
84 {
86 
87  Matrix<double> a, a_T, a_inv;
88  LogValue log_value;
89  a.resize(4, 4);
90  a_T.resize(4, 4);
91  a_inv.resize(4, 4);
92 
93  a(0, 0) = 6;
94  a(0, 1) = 5;
95  a(0, 2) = 7;
96  a(0, 3) = 5;
97  a(1, 0) = 2;
98  a(1, 1) = 2;
99  a(1, 2) = 5;
100  a(1, 3) = 4;
101  a(2, 0) = 8;
102  a(2, 1) = 2;
103  a(2, 2) = 6;
104  a(2, 3) = 4;
105  a(3, 0) = 3;
106  a(3, 1) = 8;
107  a(3, 2) = 6;
108  a(3, 3) = 8;
109 
110  simd::transpose(a.data(), a.rows(), a.cols(), a_T.data(), a_T.rows(), a_T.cols());
111  dm.invert_transpose(a_T, a_inv, log_value);
112  CHECK(log_value == LogComplexApprox(std::complex<double>{5.50533, 6.28319}));
113 
115  inv_M.resize(4, 4);
116  inv_M(0, 0) = -0.0650406504065041;
117  inv_M(0, 1) = -0.2113821138211382;
118  inv_M(0, 2) = 0.2113821138211382;
119  inv_M(0, 3) = 0.04065040650406502;
120  inv_M(1, 0) = 0.3739837398373983;
121  inv_M(1, 1) = -0.28455284552845533;
122  inv_M(1, 2) = -0.21544715447154467;
123  inv_M(1, 3) = 0.016260162601626094;
124  inv_M(2, 0) = 0.3902439024390243;
125  inv_M(2, 1) = 0.2682926829268292;
126  inv_M(2, 2) = -0.2682926829268292;
127  inv_M(2, 3) = -0.24390243902439013;
128  inv_M(3, 0) = -0.6422764227642275;
129  inv_M(3, 1) = 0.1626016260162603;
130  inv_M(3, 2) = 0.33739837398373973;
131  inv_M(3, 3) = 0.2764227642276421;
132 
133  auto check_matrix_result = checkMatrix(inv_M, a_inv);
134  CHECKED_ELSE(check_matrix_result.result) { FAIL(check_matrix_result.result_message); }
135 }
136 
137 TEST_CASE("DiracMatrix_inverse_matching_2", "[wavefunction][fermion]")
138 {
140 
141  Matrix<double> a, a_T, a_inv;
142  LogValue log_value;
143  a.resize(4, 4);
144  a_T.resize(4, 4);
145  a_inv.resize(4, 4);
146 
147  a(0, 0) = 6;
148  a(0, 1) = 2;
149  a(0, 2) = 8;
150  a(0, 3) = 3;
151  a(1, 0) = 5;
152  a(1, 1) = 2;
153  a(1, 2) = 2;
154  a(1, 3) = 8;
155  a(2, 0) = 7;
156  a(2, 1) = 5;
157  a(2, 2) = 6;
158  a(2, 3) = 6;
159  a(3, 0) = 5;
160  a(3, 1) = 4;
161  a(3, 2) = 4;
162  a(3, 3) = 8;
163 
164  // lets check Xgetrf against the cuBLAS batched
165 
166  simd::transpose(a.data(), a.rows(), a.cols(), a_T.data(), a_T.rows(), a_T.cols());
167  int pivot[4]{-1, -1, -1, -1};
168  int status = Xgetrf(a_T.rows(), a_T.cols(), a_T.data(), a_T.cols(), pivot);
169  std::vector<double> lu{7.0,
170  0.8571428571428571,
171  0.7142857142857142,
172  0.7142857142857142,
173  5.0,
174  -2.2857142857142856,
175  0.6874999999999998,
176  -0.18750000000000022,
177  6.0,
178  2.8571428571428577,
179  -4.249999999999999,
180  -0.05882352941176502,
181  6.0,
182  -2.1428571428571423,
183  5.1875,
184  3.617647058823531};
185 
186  Matrix<double> lu_mat(lu.data(), 4, 4);
188  CHECKED_ELSE(check_matrix_result.result) { FAIL(check_matrix_result.result_message); }
189 
190  dm.invert_transpose(a, a_inv, log_value);
191  CHECK(log_value == LogComplexApprox(std::complex<double>{5.50533, 6.28319}));
192 
194  inv_M.resize(4, 4);
195  inv_M(0, 0) = -0.0650406504065041;
196  inv_M(0, 1) = -0.2113821138211382;
197  inv_M(0, 2) = 0.2113821138211382;
198  inv_M(0, 3) = 0.04065040650406502;
199  inv_M(1, 0) = 0.3739837398373983;
200 
201  inv_M(1, 1) = -0.28455284552845533;
202  inv_M(1, 2) = -0.21544715447154467;
203  inv_M(1, 3) = 0.016260162601626094;
204  inv_M(2, 0) = 0.3902439024390243;
205  inv_M(2, 1) = 0.2682926829268292;
206  inv_M(2, 2) = -0.2682926829268292;
207  inv_M(2, 3) = -0.24390243902439013;
208  inv_M(3, 0) = -0.6422764227642275;
209  inv_M(3, 1) = 0.1626016260162603;
210  inv_M(3, 2) = 0.33739837398373973;
211  inv_M(3, 3) = 0.2764227642276421;
212 
213  check_matrix_result = checkMatrix(inv_M, a_inv);
214  CHECKED_ELSE(check_matrix_result.result) { FAIL(check_matrix_result.result_message); }
215 }
216 
217 /** This test case is meant to match the cuBLAS_LU::getrf_batched_complex
218  *
219  */
220 TEST_CASE("DiracMatrix_inverse_complex", "[wavefunction][fermion]")
221 {
223 
224  Matrix<std::complex<double>> a, a_T, a_inv;
225  LogValue log_value;
226  a.resize(4, 4);
227  a_T.resize(4, 4);
228  a_inv.resize(4, 4);
229 
230  a(0, 0) = {2.0, 0.1};
231  a(0, 1) = {5.0, 0.1};
232  a(0, 2) = {7.0, 0.2};
233  a(0, 3) = {5.0, 0.0};
234  a(1, 0) = {5.0, 0.1};
235  a(1, 1) = {2.0, 0.2};
236  a(1, 2) = {5.0, 1.0};
237  a(1, 3) = {4.0, -0.1};
238  a(2, 0) = {8.0, 0.5};
239  a(2, 1) = {2.0, 0.1};
240  a(2, 2) = {6.0, -0.2};
241  a(2, 3) = {4.0, -0.6};
242  a(3, 0) = {7.0, 1.0};
243  a(3, 1) = {8.0, 0.5};
244  a(3, 2) = {6.0, -0.2};
245  a(3, 3) = {8.0, -2.0};
246 
247  simd::transpose(a.data(), a.rows(), a.cols(), a_T.data(), a_T.rows(), a_T.cols());
248  int pivot[4]{-1, -1, -1, -1};
249  int status = Xgetrf(a_T.rows(), a_T.cols(), a_T.data(), a_T.cols(), pivot);
250 
251  double lu[32]{8.0,
252  0.5,
253  0.8793774319066148,
254  0.07003891050583658,
255  0.24980544747081712,
256  -0.0031128404669260694,
257  0.6233463035019455,
258  -0.026459143968871595,
259  2.0,
260  0.1,
261  6.248249027237354,
262  0.2719844357976654,
263  0.7194170575332381,
264  -0.01831314754114669,
265  0.1212375092639108,
266  0.02522449751055713,
267  6.0,
268  -0.2,
269  0.7097276264591441,
270  -0.4443579766536965,
271  4.999337315778741,
272  0.6013141870887196,
273  0.26158183940834034,
274  0.23245112532996867,
275  4.0,
276  -0.6,
277  4.440466926070039,
278  -1.7525291828793774,
279  0.840192589866152,
280  1.5044529443071093,
281  1.0698651110730424,
282  -0.10853319738453365};
283 
284  Matrix<std::complex<double>> lu_mat(reinterpret_cast<std::complex<double>*>(lu), 4, 4);
286  CHECKED_ELSE(check_matrix_result.result) { FAIL(check_matrix_result.result_message); }
287 
288  dm.invert_transpose(a, a_inv, log_value);
289  CHECK(log_value == LogComplexApprox(std::complex<double>{5.603777579195571, 0.12452497406076501}));
290 
292  b.resize(4, 4);
293 
294  b(0, 0) = {-0.05356228836958328, 0.018778132944668208};
295  b(0, 1) = {0.20217332569060176, 0.10247607676441389};
296  b(0, 2) = {0.1752053760997507, 0.08545803475354152};
297  b(0, 3) = {-0.22019253129809616, -0.23960901438764967};
298  b(1, 0) = {-0.16917709116094917, 0.18307841761769691};
299  b(1, 1) = {-0.6356039515926515, 0.24028909525203923};
300  b(1, 2) = {-0.16030725389326506, -0.2749054789157097};
301  b(1, 3) = {0.9251760746083686, 0.09385511919367814};
302  b(2, 0) = {0.21572431303125872, -0.10633509516999905};
303  b(2, 1) = {0.24869726332502523, -0.11905352270298367};
304  b(2, 2) = {0.16292868571183988, 0.17275739697798137};
305  b(2, 3) = {-0.560684625012445, -0.09607837395378985};
306  b(3, 0) = {0.023435592783503056, -0.030184486280558254};
307  b(3, 1) = {0.09553876547173154, -0.09007339752988484};
308  b(3, 2) = {-0.11510984212629605, -0.020898880528951114};
309  b(3, 3) = {0.05299966349431483, 0.13363053130258684};
310  check_matrix_result = checkMatrix(b, a_inv);
311  CHECKED_ELSE(check_matrix_result.result) { FAIL(check_matrix_result.result_message); }
312 }
313 
314 
315 TEST_CASE("DiracMatrix_update_row", "[wavefunction][fermion]")
316 {
319  updateEng.resize(3, 1);
320 
321  Matrix<ValueType> a, a_T, a_inv;
322  LogValue log_value;
323  a.resize(3, 3);
324  a_T.resize(3, 3);
325  a_inv.resize(3, 3);
326 
327  a(0, 0) = 2.3;
328  a(0, 1) = 4.5;
329  a(0, 2) = 2.6;
330  a(1, 0) = 0.5;
331  a(1, 1) = 8.5;
332  a(1, 2) = 3.3;
333  a(2, 0) = 1.8;
334  a(2, 1) = 4.4;
335  a(2, 2) = 4.9;
336 
337  simd::transpose(a.data(), a.rows(), a.cols(), a_T.data(), a_T.rows(), a_T.cols());
338  dm.invert_transpose(a_T, a_inv, log_value);
339 
340  // new row
341  Vector<ValueType> v(3), invRow(3);
342  v[0] = 1.9;
343  v[1] = 2.0;
344  v[2] = 3.1;
345 
346  updateEng.getInvRow(a_inv, 0, invRow);
347  ValueType det_ratio1 = simd::dot(v.data(), invRow.data(), invRow.size());
348 
349  ValueType det_ratio = 0.178276269185;
350  CHECK(det_ratio1 == ValueApprox(det_ratio));
351  updateEng.acceptRow(a_inv, 0, v, det_ratio1);
352 
354  b.resize(3, 3);
355 
356  b(0, 0) = 3.455170657;
357  b(0, 1) = -1.35124809;
358  b(0, 2) = -0.9233316353;
359  b(1, 0) = 0.05476311768;
360  b(1, 1) = 0.1591951095;
361  b(1, 2) = -0.1362710138;
362  b(2, 0) = -2.235099338;
363  b(2, 1) = 0.7119205298;
364  b(2, 2) = 0.9105960265;
365 
366  auto check_matrix_result = checkMatrix(a_inv, b);
367  CHECKED_ELSE(check_matrix_result.result) { FAIL(check_matrix_result.result_message); }
368 }
369 
370 } // namespace qmcplusplus
helper functions for EinsplineSetBuilder
Definition: Configuration.h:43
T dot(const T *restrict a, const T *restrict b, int n, TRES res=TRES())
dot product
QTBase::RealType RealType
Definition: Configuration.h:58
void acceptRow(Matrix< T > &Ainv, int rowchanged, const VVT &psiV, const RATIOT ratio_new)
accept a move with the update delayed
TEST_CASE("complex_helper", "[type_traits]")
CHECKED_ELSE(check_matrix_result.result)
void transpose(const T *restrict A, size_t m, size_t lda, TO *restrict B, size_t n, size_t ldb)
transpose of A(m,n) to B(n,m)
Definition: algorithm.hpp:97
auto check_matrix_result
void resize(size_type n, size_type m)
Resize the container.
Definition: OhmmsMatrix.h:99
implements delayed update on CPU using BLAS
Definition: DelayedUpdate.h:29
int Xgetrf(int n, int m, float *restrict a, int lda, int *restrict piv)
wrappers around xgetrf lapack routines
Definition: DiracMatrix.h:31
Catch::Detail::LogComplexApprox LogComplexApprox
size_type cols() const
Definition: OhmmsMatrix.h:78
size_type size() const
return the current size
Definition: OhmmsVector.h:162
QTBase::ValueType ValueType
Definition: Configuration.h:60
helper class to compute matrix inversion and the log value of determinant
Definition: DiracMatrix.h:111
static void fillInverse(Matrix< T > &b)
size_type rows() const
Definition: OhmmsMatrix.h:77
testing::MatrixAccessor< double > lu_mat(lu.data(), 4, 4)
QMCTraits::RealType RealType
CheckMatrixResult checkMatrix(M1 &a_mat, M2 &b_mat, const bool check_all=false, std::optional< const double > eps=std::nullopt)
This function checks equality a_mat and b_mat elements M1, M2 need to have their element type declare...
Definition: checkMatrix.hpp:63
void resize(int norb, int delay)
resize the internal storage
Definition: DelayedUpdate.h:58
CHECK(log_values[0]==ComplexApprox(std::complex< double >{ 5.603777579195571, -6.1586603331188225 }))
void fillIdentityMatrix(Matrix< T > &m)
std::vector< StdComp, CUDAHostAllocator< StdComp > > lu
LatticeGaussianProduct::ValueType ValueType
Declaration of WaveFunctionComponent.
std::complex< double > LogValue
std::enable_if_t< std::is_same< T_FP, TMAT >::value > invert_transpose(const Matrix< TMAT, ALLOC1 > &amat, Matrix< TMAT, ALLOC2 > &invMat, std::complex< TREAL > &LogDet)
compute the inverse of the transpose of matrix A and its determinant value in log when T_FP and TMAT ...
Definition: DiracMatrix.h:188
static void fillInput(Matrix< T > &a)
void getInvRow(const Matrix< T > &Ainv, int rowchanged, VVT &invRow)
compute the row of up-to-date Ainv
Definition: DelayedUpdate.h:97