Browse Source

Include first version of test Rho = Psidag Psi for LiebLin

master
J.-S. Caux 6 years ago
parent
commit
fbf1a64519
2 changed files with 217 additions and 19 deletions
  1. 31
    19
      src/SCAN/General_Scan.cc
  2. 186
    0
      src/TESTS/LiebLin_Rho_vs_Psidag_Psi.cc

+ 31
- 19
src/SCAN/General_Scan.cc View File

@@ -34,11 +34,11 @@ namespace ABACUS {
34 34
 
35 35
   // Types of descendents:
36 36
   // 14 == iK stepped up, leading exc one step further (can lead to ph recombination)
37
-  // 13 == iK stepped up, next exc (nr of ph preserved, not taking possible ph recombination into account)
38
-  // 12 == iK stepped up, next ext (nr ph increased, not taking possible ph recombination into account)
39
-  // 11 == iK stepped down, leading exc one step further (can lead to ph recombination)
40
-  // 10 == iK stepped down, next exc (nr of ph preserved, not taking possible ph recombination into account)
41
-  //  9 == iK stepped down, next exc (nr ph increased, not taking possible ph recombination into account)
37
+  // 13 == iK up, next exc (nr of ph preserved, not taking possible ph recombination into account)
38
+  // 12 == iK up, next ext (nr ph increased, not taking possible ph recombination into account)
39
+  // 11 == iK down, leading exc one step further (can lead to ph recombination)
40
+  // 10 == iK down, next exc (nr of ph preserved, not taking possible ph recombination into account)
41
+  //  9 == iK down, next exc (nr ph increased, not taking possible ph recombination into account)
42 42
   //  8 == iK preserved, 14 and 11 (up to 2 ph recombinations)
43 43
   //  7 == iK preserved, 14 and 10
44 44
   //  6 == iK preserved, 14 and 9
@@ -50,8 +50,10 @@ namespace ABACUS {
50 50
   //  0 == iK preserved, 12 and 9
51 51
 
52 52
   // For scanning over symmetric states, the interpretation is slightly different.
53
-  // Types 14, 13 and 12 step iK up using the Ix2 on the right only, and mirrors the change on the left Ix2.
54
-  // Types 11, 10 and 9 step iK down using the Ix2 on the right only, and mirrors the change on the left Ix2.
53
+  // Types 14, 13 and 12 step iK up using the Ix2 on the right only,
54
+  //  and mirrors the change on the left Ix2.
55
+  // Types 11, 10 and 9 step iK down using the Ix2 on the right only,
56
+  //  and mirrors the change on the left Ix2.
55 57
   // There is then no need of scanning over types 0 - 8.
56 58
   // By convention, types 9, 10 and 11 can call types 9 - 14; types 12-14 can only call types 12-14.
57 59
 
@@ -61,7 +63,8 @@ namespace ABACUS {
61 63
     // This function returns true if descending further can lead to a particle-hole recombination.
62 64
     // The criteria which are used are:
63 65
     // - the active excitation has moved at least one step (so it has already created its p-h pair)
64
-    // - there exists an OriginIx2 between the active Ix2 and the next Ix2 (to right or left depending on type of descendent)
66
+    // - there exists an OriginIx2 between the active Ix2 and the next Ix2
67
+    // (to right or left depending on type of descendent)
65 68
 
66 69
     Vect<Vect<int> > ScanIx2 = Return_Ix2_from_Label (ScanIx2_label, OriginIx2);
67 70
 
@@ -71,7 +74,7 @@ namespace ABACUS {
71 74
     bool excfound = false;
72 75
     do {
73 76
       exclevel++;
74
-      if (exclevel == ScanIx2.size()) { // there isn't a single right-moving quantum number in ScanIx2
77
+      if (exclevel == ScanIx2.size()) { // there is no right-moving quantum number in ScanIx2
75 78
 	break;
76 79
       }
77 80
       for (int alpha = 0; alpha < ScanIx2[exclevel].size(); ++alpha)
@@ -125,7 +128,8 @@ namespace ABACUS {
125 128
     // This function returns true if descending further can lead to a particle-hole recombination.
126 129
     // The criteria which are used are:
127 130
     // - the active excitation has moved at least one step (so it has already created its p-h pair)
128
-    // - there exists an OriginIx2 between the active Ix2 and the next Ix2 (to right or left depending on type of descendent)
131
+    // - there exists an OriginIx2 between the active Ix2 and the next Ix2
132
+    //   (to right or left depending on type of descendent)
129 133
 
130 134
     Vect<Vect<int> > ScanIx2 = Return_Ix2_from_Label (ScanIx2_label, OriginIx2);
131 135
 
@@ -153,7 +157,8 @@ namespace ABACUS {
153 157
     if (excfound && !BaseScanIx2[exclevel].includes(ScanIx2[exclevel][excindex])) {
154 158
       // there exists an already dispersing excitation which isn't in Origin
155 159
       // Is there a possible recombination?
156
-      if (excindex > 0) { // a particle to the left of excitation has already moved left, so there is a hole
160
+      if (excindex > 0) {
161
+	// a particle to the left of excitation has already moved left, so there is a hole
157 162
 	// check that there exists an occupied Ix2 in Origin sitting between the excitation
158 163
 	// and the next Ix2 to its left in ScanIx2
159 164
 	for (int alpha = 0; alpha < BaseScanIx2[exclevel].size(); ++alpha)
@@ -227,13 +232,18 @@ namespace ABACUS {
227 232
     int Max_Secs_alert = int(0.95 * Max_Secs); // we break any ongoing ithread loop beyond this point
228 233
 
229 234
     stringstream filenameprefix;
230
-    Data_File_Name (filenameprefix, whichDSF, iKmin, iKmax, kBT, AveragingState, SeedScanState, defaultScanStatename);
235
+    Data_File_Name (filenameprefix, whichDSF, iKmin, iKmax, kBT,
236
+		    AveragingState, SeedScanState, defaultScanStatename);
231 237
 
232
-    if (in_parallel) for (int r = 0; r < paralevel; ++r) filenameprefix << "_" << rank[r] << "_" << nr_processors[r];
238
+    if (in_parallel)
239
+      for (int r = 0; r < paralevel; ++r)
240
+	filenameprefix << "_" << rank[r] << "_" << nr_processors[r];
233 241
 
234 242
     string prefix = filenameprefix.str();
235 243
 
236
-    stringstream filenameprefix_prevparalevel;  // without the rank and nr_processors of the highest paralevel
244
+    stringstream filenameprefix_prevparalevel;
245
+    // without the rank and nr_processors of the highest paralevel
246
+
237 247
     Data_File_Name (filenameprefix_prevparalevel, whichDSF, iKmin, iKmax, kBT,
238 248
 		    AveragingState, SeedScanState, defaultScanStatename);
239 249
     if (in_parallel) for (int r = 0; r < paralevel - 1; ++r)
@@ -330,7 +340,7 @@ namespace ABACUS {
330 340
     ScanStateList.Populate_List(whichDSF, SeedScanState);
331 341
 
332 342
     if (refine && !in_parallel) ScanStateList.Load_Info (SUM_Cstr);
333
-    else if (in_parallel && rank.sum() == 0) {}; // do nothing, keep the info in the higher .sum file!
343
+    else if (in_parallel && rank.sum() == 0) {}; // do nothing, keep info in the higher .sum file!
334 344
 
335 345
     DP Chem_Pot = Chemical_Potential (AveragingState);
336 346
     DP sumrule_factor = Sumrule_Factor (whichDSF, AveragingState, Chem_Pot, iKmin, iKmax);
@@ -342,8 +352,8 @@ namespace ABACUS {
342 352
 
343 353
     int Ndata_previous_cycle = 0;
344 354
 
345
-    int ninadm = 0; // number of inadmissible states for which we save some info in .inadm file. Save first 1000.
346
-    int nconv0 = 0; // number of  unconverged states for which we save some info in .conv0 file. Save first 1000.
355
+    int ninadm = 0; // nr of inadm states for which we save info in .inadm file. Save first 1000.
356
+    int nconv0 = 0; // nr of unconv states for which we save info in .conv0 file. Save first 1000.
347 357
 
348 358
     double start_time_omp = omp_get_wtime();
349 359
     double current_time_omp = omp_get_wtime();
@@ -373,12 +383,14 @@ namespace ABACUS {
373 383
 	double start_time_flags = omp_get_wtime();
374 384
 
375 385
 	// First flag the new base/type 's that we need to include:
376
-	ScanStateList.Raise_Scanning_Flags (exp(-paused_thread_data.logscale * paused_thread_data.lowest_il_with_nthreads_neq_0));
386
+	ScanStateList.Raise_Scanning_Flags
387
+	  (exp(-paused_thread_data.logscale * paused_thread_data.lowest_il_with_nthreads_neq_0));
377 388
 
378 389
 
379 390
 	// Get these base/type started:
380 391
 	for (int i = 0; i < ScanStateList.ndef; ++i) {
381
-	  if (ScanStateList.flag_for_scan[i] && ScanStateList.info[i].Ndata == 0 && !ScanStateList.scan_attempted[i]) {
392
+	  if (ScanStateList.flag_for_scan[i] && ScanStateList.info[i].Ndata == 0
393
+	      && !ScanStateList.scan_attempted[i]) {
382 394
 
383 395
 	    Scan_Info scan_info_flags;
384 396
 

+ 186
- 0
src/TESTS/LiebLin_Rho_vs_Psidag_Psi.cc View File

@@ -0,0 +1,186 @@
1
+/**********************************************************
2
+
3
+This software is part of J.-S. Caux's ABACUS library.
4
+
5
+Copyright (c) J.-S. Caux.
6
+
7
+-----------------------------------------------------------
8
+
9
+File:  ln_Density_ME.cc
10
+
11
+Purpose:  Computes the density operator \rho(x = 0) matrix element
12
+
13
+***********************************************************/
14
+
15
+#include "ABACUS.h"
16
+
17
+using namespace std;
18
+using namespace ABACUS;
19
+
20
+
21
+/**
22
+   The matrix elements of \f$\hat{\rho}(x=0)\f$ and \f$\Psi^\dagger (x=0) \Psi(x=0)\f$
23
+   are compared between two random bra and ket states. The density matrix element is
24
+   directly computed from the determinant representation. The field operator product is
25
+   computed by introducing a resolution of the identity. The function outputs the degree
26
+   of accuracy achieved.
27
+ */
28
+int main()
29
+{
30
+
31
+  DP c_int = 4.344;
32
+  DP L = 8.0;
33
+  int N = 8;
34
+  DP kBT = 8.0;
35
+
36
+  int DiKmax = 10*N;
37
+
38
+  // Use a thermal state to get some nontrivial distribution
39
+  //LiebLin_Bethe_State spstate = Canonical_Saddle_Point_State (c_int, L, N, kBT);
40
+  LiebLin_Bethe_State spstate (c_int, L, N);
41
+  // spstate.Ix2[0] -= 8;
42
+  // spstate.Ix2[1] -= 4;
43
+  // spstate.Ix2[2] -= 2;
44
+  // spstate.Ix2[N-3] += 2;
45
+  // spstate.Ix2[N-2] += 4;
46
+  // spstate.Ix2[N-1] += 6; // keep asymmetry
47
+  spstate.Compute_All(true);
48
+  //cout << setprecision(16) << spstate << endl;
49
+
50
+
51
+  // Now define the anchor for scanning
52
+  LiebLin_Bethe_State SeedScanState = Remove_Particle_at_Center (spstate);
53
+  SeedScanState.Compute_All(true);
54
+  //cout << setprecision(16) << SeedScanState << endl;
55
+
56
+
57
+  // Map out the available unoccupied quantum nrs
58
+  // We scan from Ix2min - DiKmax to Ix2max + DiKmax, and there are N-1 occupied, so there are
59
+  int nr_par_positions = DiKmax + (SeedScanState.Ix2[N-2] - SeedScanState.Ix2[0])/2 + 1 - N + 1;
60
+  Vect<int> Ix2_available (nr_par_positions);
61
+  int nfound = 0;
62
+  for (int i = SeedScanState.Ix2[0] - DiKmax; i <= SeedScanState.Ix2[N-2] + DiKmax; i += 2) {
63
+    bool available = true;
64
+
65
+    for (int j = 0; j < N-1; ++j)
66
+      if (i == SeedScanState.Ix2[j]) {
67
+	available = false;
68
+	break;
69
+      }
70
+    if (available)
71
+      Ix2_available[nfound++] = i;
72
+  }
73
+  if (nfound != nr_par_positions) {
74
+    cout << "nround = " << nfound << "\tnr_par_positions = " << nr_par_positions << endl;
75
+    ABACUSerror("Wrong number of particle positions found.");
76
+  }
77
+
78
+
79
+  // Define bra and ket states
80
+  LiebLin_Bethe_State lstate = spstate;
81
+  lstate.Ix2[0] -= 4;
82
+  lstate.Ix2[1] -= 2;
83
+  lstate.Compute_All(false);
84
+  cout << setprecision(16) << lstate << endl;
85
+
86
+
87
+  LiebLin_Bethe_State rstate = spstate;
88
+  rstate.Ix2[N-1] += 8;
89
+  rstate.Ix2[N-2] += 2;
90
+  rstate.Compute_All(false);
91
+  cout << setprecision(16) << rstate << endl;
92
+
93
+
94
+
95
+  //lstate = rstate;
96
+
97
+  // Matrix element to reproduce
98
+  complex<DP> ln_rho_ME = ln_Density_ME(lstate, rstate);
99
+  cout << "ln_Density_ME = " << ln_rho_ME << endl;
100
+
101
+  // We now do hard-coded scanning of up to fixed nr of particle-hole pairs
102
+  complex<DP> Psidag_Psi = 0.0;
103
+
104
+  LiebLin_Bethe_State scanstate = SeedScanState;
105
+
106
+
107
+  // Zero particle-hole:
108
+  scanstate = SeedScanState;
109
+  Psidag_Psi += exp(conj(ln_Psi_ME(scanstate, lstate)) + ln_Psi_ME(scanstate, rstate));
110
+
111
+  cout << "Ratio Rho/PsidagPsi After scanning 0 p-h: "
112
+       << setprecision(16) << real(Psidag_Psi/exp(ln_rho_ME))
113
+       << "\t" << imag(Psidag_Psi/exp(ln_rho_ME)) << endl;
114
+
115
+
116
+  // One particle-hole:
117
+  char a;
118
+  for (int ih1 = 0; ih1 < N-1; ++ih1)
119
+    for (int ipar1 = 0; ipar1 < nr_par_positions - 1; ++ipar1) {
120
+
121
+      scanstate = SeedScanState;
122
+      scanstate.Ix2[ih1] = Ix2_available[ipar1];
123
+      scanstate.Ix2.QuickSort();
124
+      scanstate.Compute_All(true);
125
+      Psidag_Psi += exp(conj(ln_Psi_ME(scanstate, lstate)) + ln_Psi_ME(scanstate, rstate));
126
+
127
+      // cout << "ih1 = " << ih1 << "\tipar1 = " << ipar1
128
+      // 	   << "\tPsidag_Psi = " << setprecision(16) << Psidag_Psi << endl;
129
+      //cout << scanstate << endl;
130
+      //cin >> a;
131
+    }
132
+
133
+  cout << "Ratio Rho/PsidagPsi After scanning 1 p-h: "
134
+       << setprecision(16) << real(Psidag_Psi/exp(ln_rho_ME))
135
+       << "\t" << imag(Psidag_Psi/exp(ln_rho_ME)) << endl;
136
+
137
+  // Two particle-hole:
138
+  for (int ih1 = 0; ih1 < N-2; ++ih1)
139
+    for (int ih2 = ih1+1; ih2 < N-1; ++ih2)
140
+      for (int ipar1 = 0; ipar1 < nr_par_positions - 2; ++ipar1) {
141
+  	for (int ipar2 = ipar1+1; ipar2 < nr_par_positions - 1; ++ipar2) {
142
+
143
+  	  scanstate = SeedScanState;
144
+  	  scanstate.Ix2[ih1] = Ix2_available[ipar1];
145
+  	  scanstate.Ix2[ih2] = Ix2_available[ipar2];
146
+  	  scanstate.Ix2.QuickSort();
147
+  	  scanstate.Compute_All(true);
148
+  	  Psidag_Psi += exp(conj(ln_Psi_ME(scanstate, lstate)) + ln_Psi_ME(scanstate, rstate));
149
+
150
+  	}
151
+      }
152
+
153
+  cout << "Ratio Rho/PsidagPsi After scanning 2 p-h: "
154
+       << setprecision(16) << real(Psidag_Psi/exp(ln_rho_ME))
155
+       << "\t" << imag(Psidag_Psi/exp(ln_rho_ME)) << endl;
156
+
157
+
158
+  // Three particle-hole:
159
+  for (int ih1 = 0; ih1 < N-3; ++ih1)
160
+    for (int ih2 = ih1+1; ih2 < N-2; ++ih2)
161
+      for (int ih3 = ih2+1; ih3 < N-1; ++ih3)
162
+  	for (int ipar1 = 0; ipar1 < nr_par_positions - 3; ++ipar1) {
163
+  	  for (int ipar2 = ipar1+1; ipar2 < nr_par_positions - 2; ++ipar2) {
164
+  	    for (int ipar3 = ipar2+1; ipar3 < nr_par_positions - 1; ++ipar3) {
165
+
166
+  	      scanstate = SeedScanState;
167
+  	      scanstate.Ix2[ih1] = Ix2_available[ipar1];
168
+  	      scanstate.Ix2[ih2] = Ix2_available[ipar2];
169
+  	      scanstate.Ix2[ih3] = Ix2_available[ipar3];
170
+  	      scanstate.Ix2.QuickSort();
171
+  	      scanstate.Compute_All(true);
172
+  	      Psidag_Psi += exp(conj(ln_Psi_ME(scanstate, lstate)) + ln_Psi_ME(scanstate, rstate));
173
+  	    }
174
+  	  }
175
+  	  // cout << "Ratio Rho/PsidagPsi while scanning 3 p-h: "
176
+  	  //      << setprecision(16) << real(Psidag_Psi/exp(ln_rho_ME))
177
+  	  //      << "\t" << imag(Psidag_Psi/exp(ln_rho_ME)) << endl;
178
+  	}
179
+
180
+  cout << "Ratio Rho/PsidagPsi After scanning 3 p-h: "
181
+       << setprecision(16) << real(Psidag_Psi/exp(ln_rho_ME))
182
+       << "\t" << imag(Psidag_Psi/exp(ln_rho_ME)) << endl;
183
+
184
+
185
+  return(0);
186
+}

Loading…
Cancel
Save