1814 lines
78 KiB
C++
1814 lines
78 KiB
C++
/**********************************************************
|
|
|
|
This software is part of J.-S. Caux's ABACUS library.
|
|
|
|
Copyright (c).
|
|
|
|
-----------------------------------------------------------
|
|
|
|
File: src/SCAN/General_Scan.cc
|
|
|
|
Purpose: universal implementation of state scanning:
|
|
functions to descend down hierarchy of intermediate states.
|
|
|
|
NOTE: since templated functions have to be in the same file,
|
|
we put all scanning functions here. The externally-accessible
|
|
functions are defined at the end of this file.
|
|
|
|
***********************************************************/
|
|
|
|
#include "JSC.h"
|
|
|
|
using namespace std;
|
|
using namespace JSC;
|
|
|
|
|
|
string LABEL_TO_CHECK = "bla";
|
|
//string LABEL_TO_CHECK = "6_0_";
|
|
//string LABEL_TO_CHECK = "6_2_22y32";
|
|
|
|
|
|
namespace JSC {
|
|
|
|
// Types of descendents:
|
|
// 14 == iK stepped up, leading exc one step further (can lead to ph recombination)
|
|
// 13 == iK stepped up, next exc (nr of ph preserved, not taking possible ph recombination into account)
|
|
// 12 == iK stepped up, next ext (nr ph increased, not taking possible ph recombination into account)
|
|
// 11 == iK stepped down, leading exc one step further (can lead to ph recombination)
|
|
// 10 == iK stepped down, next exc (nr of ph preserved, not taking possible ph recombination into account)
|
|
// 9 == iK stepped down, next exc (nr ph increased, not taking possible ph recombination into account)
|
|
// 8 == iK preserved, 14 and 11 (up to 2 ph recombinations)
|
|
// 7 == iK preserved, 14 and 10
|
|
// 6 == iK preserved, 14 and 9
|
|
// 5 == iK preserved, 13 and 11
|
|
// 4 == iK preserved, 13 and 10
|
|
// 3 == iK preserved, 13 and 9
|
|
// 2 == iK preserved, 12 and 11
|
|
// 1 == iK preserved, 12 and 10
|
|
// 0 == iK preserved, 12 and 9
|
|
|
|
// For scanning over symmetric states, the interpretation is slightly different.
|
|
// Types 14, 13 and 12 step iK up using the Ix2 on the right only, and mirrors the change on the left Ix2.
|
|
// Types 11, 10 and 9 step iK down using the Ix2 on the right only, and mirrors the change on the left Ix2.
|
|
// There is then no need of scanning over types 0 - 8.
|
|
// By convention, types 9, 10 and 11 can call types 9 - 14; types 12-14 can only call types 12-14.
|
|
|
|
bool Expect_ph_Recombination_iK_Up (string ScanIx2_label, const Vect<Vect<int> >& OriginIx2, const Vect<Vect<int> >& BaseScanIx2)
|
|
{
|
|
// This function returns true if descending further can lead to a particle-hole recombination.
|
|
// The criteria which are used are:
|
|
// - the active excitation has moved at least one step (so it has already created its p-h pair)
|
|
// - there exists an OriginIx2 between the active Ix2 and the next Ix2 (to right or left depending on type of descendent)
|
|
|
|
Vect<Vect<int> > ScanIx2 = Return_Ix2_from_Label (ScanIx2_label, OriginIx2);
|
|
|
|
// Determine the level and index of the bottom-most left-most right-moving quantum number sits:
|
|
int exclevel = -1;
|
|
int excindex = 0;
|
|
bool excfound = false;
|
|
do {
|
|
exclevel++;
|
|
if (exclevel == ScanIx2.size()) { // there isn't a single right-moving quantum number in ScanIx2
|
|
break;
|
|
}
|
|
for (int alpha = 0; alpha < ScanIx2[exclevel].size(); ++alpha)
|
|
if (ScanIx2[exclevel][alpha] > BaseScanIx2[exclevel][alpha]) {
|
|
excindex = alpha;
|
|
excfound = true;
|
|
break;
|
|
}
|
|
} while (!excfound);
|
|
// If we haven't found an excitation, then exclevel == ScanIx2.size() and excindex = 0;
|
|
|
|
if (excfound && !BaseScanIx2[exclevel].includes(ScanIx2[exclevel][excindex])) { // there exists an already dispersing excitation which isn't in Origin
|
|
// Is there a possible recombination?
|
|
if (excindex < ScanIx2[exclevel].size() - 1) { // a particle to the right of excitation has already move right, so there is a hole
|
|
// check that there exists an occupied Ix2 in Origin sitting between the excitation and the next Ix2 to its right in ScanIx2
|
|
for (int alpha = BaseScanIx2[exclevel].size() - 1; alpha >= 0; --alpha)
|
|
if (BaseScanIx2[exclevel][alpha] > ScanIx2[exclevel][excindex] && BaseScanIx2[exclevel][alpha] < ScanIx2[exclevel][excindex + 1]) {
|
|
return(true);
|
|
}
|
|
}
|
|
} // if (excfound)
|
|
|
|
return(false);
|
|
}
|
|
|
|
// Specialization for Lieb-Liniger:
|
|
bool Expect_ph_Recombination_iK_Up (string ScanIx2_label, const LiebLin_Bethe_State& OriginState)
|
|
{
|
|
Vect<Vect<int> > OriginIx2here(1);
|
|
OriginIx2here[0] = OriginState.Ix2;
|
|
Vect<Vect<int> > BaseScanIx2here(1);
|
|
BaseScanIx2here[0] = OriginState.Ix2;
|
|
return(Expect_ph_Recombination_iK_Up (ScanIx2_label, OriginIx2here, BaseScanIx2here));
|
|
}
|
|
|
|
// Specialization for Heis
|
|
bool Expect_ph_Recombination_iK_Up (string ScanIx2_label, const Heis_Bethe_State& OriginState)
|
|
{
|
|
return(Expect_ph_Recombination_iK_Up (ScanIx2_label, OriginState.Ix2, OriginState.Ix2));
|
|
}
|
|
|
|
|
|
|
|
bool Expect_ph_Recombination_iK_Down (string ScanIx2_label, const Vect<Vect<int> >& OriginIx2, const Vect<Vect<int> >& BaseScanIx2)
|
|
{
|
|
// This function returns true if descending further can lead to a particle-hole recombination.
|
|
// The criteria which are used are:
|
|
// - the active excitation has moved at least one step (so it has already created its p-h pair)
|
|
// - there exists an OriginIx2 between the active Ix2 and the next Ix2 (to right or left depending on type of descendent)
|
|
|
|
Vect<Vect<int> > ScanIx2 = Return_Ix2_from_Label (ScanIx2_label, OriginIx2);
|
|
|
|
// Determine the level and index of the bottom-most right-most left-moving quantum number sits:
|
|
int exclevel = -1;
|
|
int excindex = 0;
|
|
bool excfound = false;
|
|
|
|
//cout << "Looking for exclevel and excindex for " << endl << "\tBaseIx2 = " << BaseScanIx2 << endl << "\tScanIx2 = " << ScanIx2 << endl;
|
|
do {
|
|
exclevel++;
|
|
if (exclevel == ScanIx2.size()) { // there isn't a single left-moving quantum number in ScanIx2
|
|
break;
|
|
}
|
|
for (int alpha = ScanIx2[exclevel].size() - 1; alpha >= 0; --alpha) {
|
|
//cout << exclevel << "\t" << alpha << "\t" << ScanIx2[exclevel][alpha] << "\t" << BaseScanIx2[exclevel][alpha] << "\t" << (ScanIx2[exclevel][alpha] < BaseScanIx2[exclevel][alpha]) << endl;
|
|
if (ScanIx2[exclevel][alpha] < BaseScanIx2[exclevel][alpha]) {
|
|
excindex = alpha;
|
|
excfound = true;
|
|
break;
|
|
}
|
|
}
|
|
} while (!excfound);
|
|
// If we haven't found an excitation, then exclevel == ScanIx2.size() and excindex = 0;
|
|
if (!excfound) excindex = ScanIx2[exclevel].size() - 1;
|
|
|
|
if (excfound && !BaseScanIx2[exclevel].includes(ScanIx2[exclevel][excindex])) { // there exists an already dispersing excitation which isn't in Origin
|
|
// Is there a possible recombination?
|
|
if (excindex > 0) { // a particle to the left of excitation has already moved left, so there is a hole
|
|
// check that there exists an occupied Ix2 in Origin sitting between the excitation and the next Ix2 to its left in ScanIx2
|
|
for (int alpha = 0; alpha < BaseScanIx2[exclevel].size(); ++alpha)
|
|
if (BaseScanIx2[exclevel][alpha] > ScanIx2[exclevel][excindex - 1] && BaseScanIx2[exclevel][alpha] < ScanIx2[exclevel][excindex]) {
|
|
return(true);
|
|
}
|
|
}
|
|
} // if (excfound)
|
|
|
|
return(false);
|
|
}
|
|
|
|
// Specialization for Lieb-Liniger:
|
|
bool Expect_ph_Recombination_iK_Down (string ScanIx2_label, const LiebLin_Bethe_State& OriginState)
|
|
{
|
|
Vect<Vect<int> > OriginIx2here(1);
|
|
OriginIx2here[0] = OriginState.Ix2;
|
|
Vect<Vect<int> > BaseScanIx2here(1);
|
|
BaseScanIx2here[0] = OriginState.Ix2;
|
|
return(Expect_ph_Recombination_iK_Down (ScanIx2_label, OriginIx2here, BaseScanIx2here));
|
|
}
|
|
|
|
// Specialization for Heis
|
|
bool Expect_ph_Recombination_iK_Down (string ScanIx2_label, const Heis_Bethe_State& OriginState)
|
|
{
|
|
return(Expect_ph_Recombination_iK_Down (ScanIx2_label, OriginState.Ix2, OriginState.Ix2));
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
template<class Tstate>
|
|
void Descend_and_Compute_for_Fixed_Base (char whichDSF, Tstate& AveragingState, Tstate& BaseScanState, Tstate& ScanState,
|
|
int type_required, int iKmin, int iKmax, int iKmod,
|
|
//Scan_Thread_List& paused_thread_list,
|
|
//Scan_Thread_Set& paused_thread_set,
|
|
Scan_Thread_Data& paused_thread_data,
|
|
//thresholdremoved DP& running_scan_threshold, //DP ref_abs_data_value,
|
|
DP& ph_cost, int Max_Secs, DP sumrule_factor, DP Chem_Pot, Scan_Info& scan_info,
|
|
fstream& RAW_outfile, fstream& INADM_outfile, int& ninadm,
|
|
fstream& CONV0_outfile, int& nconv0, fstream& STAT_outfile)
|
|
{
|
|
|
|
//cout << "Calling descent with type_required " << type_required << " on state " << ScanState.label << "\t" << Return_Ix2_from_Label(ScanState.label, AveragingState.Ix2) << endl;
|
|
//cout << "Calling descent with type_required " << type_required << " on state " << ScanState.label << endl;
|
|
ScanState.Compute_Momentum();
|
|
Vect<string> desc_label;
|
|
|
|
// ++G_7 logic
|
|
bool disperse_only_current_exc_up = false;
|
|
if (type_required == 14 || type_required == 8 || type_required == 7 || type_required == 6) disperse_only_current_exc_up = true;
|
|
bool preserve_nexc_up = false;
|
|
if (type_required == 13 || type_required == 5 || type_required == 4 || type_required == 3) preserve_nexc_up = true;
|
|
bool disperse_only_current_exc_down = false;
|
|
if (type_required == 11 || type_required == 8 || type_required == 5 || type_required == 2) disperse_only_current_exc_down = true;
|
|
bool preserve_nexc_down = false;
|
|
if (type_required == 10 || type_required == 7 || type_required == 4 || type_required == 1) preserve_nexc_down = true;
|
|
|
|
if (whichDSF == 'B') { // symmetric state scanning
|
|
if (type_required >= 9 && type_required <= 11)
|
|
desc_label = Descendent_States_with_iK_Stepped_Down_rightIx2only (ScanState.label, BaseScanState, disperse_only_current_exc_down, preserve_nexc_down);
|
|
else if (type_required >= 12 && type_required <= 14)
|
|
desc_label = Descendent_States_with_iK_Stepped_Up_rightIx2only (ScanState.label, BaseScanState, disperse_only_current_exc_up, preserve_nexc_up);
|
|
}
|
|
else {
|
|
if (type_required >= 0 && type_required <= 8) {
|
|
desc_label = Descendent_States_with_iK_Preserved(ScanState.label, BaseScanState, disperse_only_current_exc_up, preserve_nexc_up, disperse_only_current_exc_down, preserve_nexc_down);
|
|
}
|
|
else if (type_required >= 9 && type_required <= 11)
|
|
desc_label = Descendent_States_with_iK_Stepped_Down (ScanState.label, BaseScanState, disperse_only_current_exc_down, preserve_nexc_down);
|
|
else if (type_required >= 12 && type_required <= 14)
|
|
desc_label = Descendent_States_with_iK_Stepped_Up (ScanState.label, BaseScanState, disperse_only_current_exc_up, preserve_nexc_up);
|
|
}
|
|
//cout << "Found " << desc_label.size() << " descendents." << endl;
|
|
//for (int is = 0; is < desc_label.size(); ++is) cout << "is " << is << "\tdesc: " << desc_label[is] << "\t" << Return_Ix2_from_Label(desc_label[is], AveragingState.Ix2) << endl;
|
|
//char a;
|
|
//cin >> a;
|
|
|
|
//cout << "OK for descend on " << ScanState.label << " with type_required = " << type_required << endl;
|
|
//cout << desc_label << endl;
|
|
|
|
//Vect<string> desc_label = desc_data.label;
|
|
//Vect<int> desc_type = desc_data.type;
|
|
|
|
//bool disp_OK = false;
|
|
|
|
//if (ScanState.label == "7|2:1_0|1_|0@2") {
|
|
//if (ScanState.label == "64_1_63@319") {
|
|
//if (ScanState.label == "32_1_-29@-33") {
|
|
|
|
if (ScanState.label == LABEL_TO_CHECK) {
|
|
cout << "Called Descend on state " << ScanState << endl;
|
|
cout << "For type_required == " << type_required << ", found " << desc_label.size() << " descendents, ";
|
|
for (int i = 0; i < desc_label.size(); ++i) {
|
|
//cout << desc_label[i] << "\t"; cout << endl;
|
|
ScanState.Set_to_Label (desc_label[i], BaseScanState.Ix2);
|
|
ScanState.Compute_All(true);
|
|
cout << ScanState << endl;
|
|
}
|
|
cout << "Do you want to follow one of these descendents? (y/n)" << endl;
|
|
char a; cin >> a;
|
|
if (a == 'y') {
|
|
cout << "Which label do you want to follow?" << endl;
|
|
cin >> LABEL_TO_CHECK;
|
|
}
|
|
}
|
|
|
|
|
|
string label_here = ScanState.label;
|
|
//int ScanState_iK = ScanState.iK;
|
|
|
|
for (int idesc = 0; idesc < desc_label.size(); ++idesc) {
|
|
|
|
//cout << "\tDealing with descendent " << idesc << " out of " << desc_label.size() << " with label " << desc_label[idesc] << endl;
|
|
//cout << "\tfrom state with label " << label_here << " and of type_required " << type_required << endl;
|
|
|
|
clock_t start_time_here = clock();
|
|
|
|
//if (desc_label[idesc] == "64_2_0yvv7") {
|
|
if (false) {
|
|
cout << "Found " << desc_label[idesc] << " as descendent of type " << type_required << " of " << label_here << endl;
|
|
ScanState.Set_to_Label (label_here, BaseScanState.Ix2);
|
|
cout << ScanState.Ix2 << endl;
|
|
//cout << "Found " << desc_label.size() << " descendents, " << endl;
|
|
//for (int i = 0; i < desc_label.size(); ++i) cout << desc_label[i] << "\t"; cout << endl;
|
|
ScanState.Set_to_Label (desc_label[idesc], BaseScanState.Ix2);
|
|
cout << ScanState.Ix2 << endl;
|
|
//ScanState.Compute_All(true);
|
|
//cout << "Resulting Ix2: " << ScanState.Ix2 << endl;
|
|
//cout << ScanState << endl;
|
|
//cout << "Admissible: " << ScanState.Check_Admissibility(whichDSF) << endl;
|
|
//char a; cin >> a;
|
|
}
|
|
|
|
|
|
ScanState.Set_to_Label (desc_label[idesc], BaseScanState.Ix2);
|
|
|
|
bool admissible = ScanState.Check_Admissibility(whichDSF);
|
|
|
|
DP data_value = 0.0;
|
|
|
|
scan_info.Ndata++;
|
|
|
|
ScanState.conv = false;
|
|
ScanState.Compute_Momentum(); // since momentum is used as forced descent criterion
|
|
|
|
|
|
if (admissible) {
|
|
|
|
ScanState.Compute_All (idesc == 0);
|
|
//ScanState.Compute_All (true);
|
|
|
|
//scan_info.Ndata++;
|
|
|
|
if (ScanState.conv) {
|
|
scan_info.Ndata_conv++;
|
|
|
|
// Put momentum in fundamental window, if possible:
|
|
int iKexc = ScanState.iK - AveragingState.iK;
|
|
while (iKexc > iKmax && iKexc - iKmod >= iKmin) iKexc -= iKmod;
|
|
while (iKexc < iKmin && iKexc + iKmod <= iKmax) iKexc += iKmod;
|
|
|
|
data_value = Compute_Matrix_Element_Contrib (whichDSF, iKmin, iKmax, ScanState, AveragingState, Chem_Pot, RAW_outfile);
|
|
if (iKexc >= iKmin && iKexc <= iKmax) scan_info.sumrule_obtained += data_value*sumrule_factor;
|
|
//cout << "data_value found = " << data_value * sumrule_factor << endl;
|
|
|
|
// Uncomment line below if .stat file is desired:
|
|
//STAT_outfile << setw(20) << label_here << "\t" << setw(5) << type_required << "\t" << setw(16) << std::scientific << running_scan_threshold << "\t" << setw(20) << ScanState.label << "\t" << setw(16) << data_value << "\t" << setw(16) << std::fixed << setprecision(8) << data_value/running_scan_threshold << endl;
|
|
|
|
} // if (ScanState.conv)
|
|
else {
|
|
if (nconv0++ < 1000)
|
|
CONV0_outfile << setw(25) << ScanState.label << setw(25) << ScanState.diffsq << setw(5) << ScanState.Check_Rapidities()
|
|
<< setw(25) << ScanState.String_delta() << endl;
|
|
scan_info.Ndata_conv0++;
|
|
//cout << "State did not converge." << endl;
|
|
}
|
|
} // if (admissible)
|
|
|
|
else {
|
|
if (ninadm++ < 1000000) INADM_outfile << ScanState.label << endl;
|
|
scan_info.Ninadm++;
|
|
//cout << "State was inadmissible." << endl;
|
|
// Set data_value to enable continued scanning later on:
|
|
//thresholdremoved data_value = 0.1* running_scan_threshold;
|
|
}
|
|
|
|
clock_t stop_time_here = clock();
|
|
|
|
scan_info.CPU_ticks += stop_time_here - start_time_here;
|
|
|
|
Tstate state_to_descend; state_to_descend = ScanState; // for checking
|
|
|
|
ScanState.Compute_Momentum();
|
|
// Put momentum in fundamental window, if possible:
|
|
int iKexc = ScanState.iK - AveragingState.iK;
|
|
while (iKexc > iKmax && iKexc - iKmod >= iKmin) iKexc -= iKmod;
|
|
while (iKexc < iKmin && iKexc + iKmod <= iKmax) iKexc += iKmod;
|
|
|
|
// ++G_7 logic
|
|
// Momentum-preserving are only descended to momentum-preserving.
|
|
// Momentum-increasing are only descended to momentum-preserving and momentum-increasing.
|
|
// Momentum-decreasing are only descended to momentum-preserving and momentum-decreasing.
|
|
Vect<bool> allowed(false, 15);
|
|
if (whichDSF == 'B') {
|
|
// We scan over symmetric states. Only types 14 down to 9 are allowed.
|
|
if (type_required >= 9 && type_required <= 11) { // iK stepped down on rightIx2; step further up or down
|
|
allowed[9] = true; allowed[10] = true; allowed[11] = true;
|
|
allowed[12] = true; allowed[13] = true; allowed[14] = true;
|
|
}
|
|
else if (type_required >= 12 && type_required <= 14) { // iK stepped up on rightIx2; only step further up
|
|
allowed[12] = true; allowed[13] = true; allowed[14] = true;
|
|
}
|
|
}
|
|
else {
|
|
if (type_required >= 0 && type_required <= 8) { // momentum-preserving
|
|
allowed[0] = (iKexc >= iKmin && iKexc <= iKmax);
|
|
allowed[9] = false;
|
|
allowed[12] = false;
|
|
}
|
|
if (type_required >= 9 && type_required <= 11) { // momentum-decreasing
|
|
allowed[0] = (iKexc >= iKmin && iKexc <= iKmax);
|
|
allowed[9] = (iKexc > iKmin);
|
|
allowed[12] = false;
|
|
}
|
|
if (type_required >= 12 && type_required <= 14) { // momentum-increasing
|
|
allowed[0] = (iKexc >= iKmin && iKexc <= iKmax);
|
|
allowed[9] = false;
|
|
allowed[12] = (iKexc < iKmax);
|
|
}
|
|
// The others are just copies of the ones above:
|
|
allowed[1] = allowed[0]; allowed[2] = allowed[0]; allowed[3] = allowed[0]; allowed[4] = allowed[0]; allowed[5] = allowed[0]; allowed[6] = allowed[0]; allowed[7] = allowed[0]; allowed[8] = allowed[0];
|
|
allowed[10] = allowed[9]; allowed[11] = allowed[9];
|
|
allowed[13] = allowed[12]; allowed[14] = allowed[12];
|
|
}
|
|
|
|
|
|
for (int type_required_here = 0; type_required_here < 15; ++type_required_here) {
|
|
|
|
if (!allowed[type_required_here]) continue;
|
|
|
|
// Reset ScanState to what it was, if change on first pass
|
|
if (type_required_here > 0) ScanState = state_to_descend;
|
|
|
|
// We determine if we carry on scanning based on the data_value obtained, or forcing conditions:
|
|
// Forcing conditions:
|
|
//if (!admissible || Force_Descent(whichDSF, ScanState, AveragingState, type_required_here, iKmod, Chem_Pot))
|
|
////data_value = 1.01 * running_scan_threshold/ph_cost; // force for all types of desc
|
|
//data_value = 1.01 * running_scan_threshold; // only force for no new ph pairs
|
|
////data_value = 1.0; // force for all types of desc
|
|
// If we're sitting out of the iKmin & iKmax window, stop:
|
|
//if (iKmin != iKmax && (ScanState.iK - AveragingState.iK > iKmax || ScanState.iK - AveragingState.iK < iKmin)) data_value = 0.0;
|
|
|
|
//if (abs(data_value) * (type_required_here != 2 ? 1.0 : ph_cost) > running_scan_threshold
|
|
//if ((abs(data_value) > running_scan_threshold
|
|
//|| Nr_ph_Recombinations_Possible (ScanState.label, BaseScanState, type_required_here) > 0)
|
|
|
|
//DP expected_abs_data_value = abs(data_value)/pow(ph_cost, DP(Nr_ph_Recombinations_Possible (ScanState.label, BaseScanState, type_required_here)));
|
|
DP expected_abs_data_value = abs(data_value);
|
|
|
|
//++G_7 logic
|
|
if ((type_required_here == 14 || type_required_here == 8 || type_required_here == 7 || type_required_here == 6)
|
|
&& Expect_ph_Recombination_iK_Up (ScanState.label, BaseScanState)) expected_abs_data_value /= ph_cost;
|
|
if (type_required_here == 12 || type_required_here == 2 || type_required_here == 1 || type_required_here == 0)
|
|
expected_abs_data_value *= ph_cost;
|
|
if ((type_required_here == 11 || type_required_here == 8 || type_required_here == 5 || type_required_here == 2)
|
|
&& Expect_ph_Recombination_iK_Down (ScanState.label, BaseScanState)) expected_abs_data_value /= ph_cost;
|
|
if (type_required_here == 9 || type_required_here == 6 || type_required_here == 3 || type_required_here == 0)
|
|
expected_abs_data_value *= ph_cost;
|
|
|
|
//cout << "\tIncluding thread " << expected_abs_data_value << "\t" << ScanState.label << "\t" << type_required_here << endl;
|
|
//paused_thread_set.Include_Thread (expected_abs_data_value, ScanState.label, type_required_here);
|
|
paused_thread_data.Include_Thread (expected_abs_data_value, ScanState.label, type_required_here);
|
|
//cout << "\tDone including thread." << endl;
|
|
} // for type_required_here
|
|
|
|
//cout << "\tFinished with descendent " << idesc << " out of " << desc_label.size() << " with label " << desc_label[idesc] << endl;
|
|
//cout << "\tfrom state with label " << label_here << endl;
|
|
} // for idesc
|
|
|
|
//cout << "Finished Descend on state " << endl << ScanState.label << endl;
|
|
|
|
return;
|
|
}
|
|
*/
|
|
|
|
template<class Tstate>
|
|
Scan_Info General_Scan (char whichDSF, int iKmin, int iKmax, int iKmod, DP kBT, Tstate& AveragingState, Tstate& SeedScanState,
|
|
string defaultScanStatename, int Max_Secs, DP target_sumrule, bool refine, int paralevel, Vect<int> rank, Vect<int> nr_processors)
|
|
{
|
|
// Performs the scan over excited states, writing data to file.
|
|
|
|
// AveragingState is the state on which the correlations are calculated.
|
|
// SeedScanState is the originator of all scan states.
|
|
// This distinction is kept to allow for quenches and finite temperatures.
|
|
|
|
// This function is also called by the parallel implementation of ABACUS.
|
|
// In this case, file names carry a rank and nr_processors suffix.
|
|
// In fact, the parallelization can be done in incremental levels.
|
|
// If paralevel == 0, the run is serial.
|
|
// If paralevel == n, the run is parallelized in a tree with n levels of branching.
|
|
// A paralevel == 1 branching's files have a suffix of the form "_3_8", meaning that this is the rank 3 out of 8 processors.
|
|
// A paralevel == 2 branching's files have a suffix of the form "_3_8_2_8", meaning that this is the rank 2 out of 8 subscan of the _3_8 scan.
|
|
|
|
//clock_t start_time = clock();
|
|
//clock_t current_time = clock();
|
|
|
|
//bool in_parallel = (nr_processors > 1);
|
|
bool in_parallel = (paralevel > 0);
|
|
if (in_parallel && (rank.size() != paralevel || nr_processors.size() != paralevel)) {
|
|
cout << "paralevel = " << paralevel << "\trank.size() = " << rank.size() << "\tnr_processors.size() = " << nr_processors.size() << endl;
|
|
cout << "rank = " << rank << endl;
|
|
cout << "nr_processors = " << nr_processors << endl;
|
|
JSCerror("Inconsistent paralevel, rank or nr_processors in General_Scan.");
|
|
}
|
|
|
|
if (in_parallel && !refine) JSCerror("Must refine when using parallel ABACUS++");
|
|
|
|
DP ph_cost = Particle_Hole_Excitation_Cost (whichDSF, AveragingState); // expected cost on data_value of adding a particle-hole excitation.
|
|
|
|
int Max_Secs_used = int(0.9 * Max_Secs); // we don't start any new ithread loop beyond this point
|
|
int Max_Secs_alert = int(0.95 * Max_Secs); // we break any ongoing ithread loop beyond this point
|
|
|
|
//clock_t start_time_local = clock();
|
|
|
|
stringstream filenameprefix;
|
|
Data_File_Name (filenameprefix, whichDSF, iKmin, iKmax, kBT, AveragingState, SeedScanState, defaultScanStatename);
|
|
|
|
if (in_parallel) for (int r = 0; r < paralevel; ++r) filenameprefix << "_" << rank[r] << "_" << nr_processors[r];
|
|
|
|
string prefix = filenameprefix.str();
|
|
|
|
stringstream filenameprefix_prevparalevel; // without the rank and nr_processors of the highest paralevel
|
|
Data_File_Name (filenameprefix_prevparalevel, whichDSF, iKmin, iKmax, kBT, AveragingState, SeedScanState, defaultScanStatename);
|
|
if (in_parallel) for (int r = 0; r < paralevel - 1; ++r) filenameprefix << "_" << rank[r] << "_" << nr_processors[r];
|
|
|
|
string prefix_prevparalevel = filenameprefix_prevparalevel.str();
|
|
|
|
stringstream RAW_stringstream; string RAW_string;
|
|
stringstream INADM_stringstream; string INADM_string;
|
|
stringstream CONV0_stringstream; string CONV0_string;
|
|
stringstream STAT_stringstream; string STAT_string;
|
|
stringstream LOG_stringstream; string LOG_string;
|
|
stringstream THR_stringstream; string THR_string;
|
|
stringstream THRDIR_stringstream; string THRDIR_string;
|
|
stringstream SRC_stringstream; string SRC_string;
|
|
//stringstream FSR_stringstream; string FSR_string;
|
|
stringstream SUM_stringstream; string SUM_string;
|
|
//stringstream SUM_prevparalevel_stringstream; string SUM_prevparalevel_string;
|
|
|
|
RAW_stringstream << prefix << ".raw";
|
|
INADM_stringstream << prefix << ".inadm";
|
|
CONV0_stringstream << prefix << ".conv0";
|
|
STAT_stringstream << prefix << ".stat";
|
|
LOG_stringstream << prefix << ".log";
|
|
THR_stringstream << prefix << ".thr";
|
|
THRDIR_stringstream << prefix << "_thrdir";
|
|
SRC_stringstream << prefix << ".src";
|
|
//FSR_stringstream << prefix << ".fsr";
|
|
SUM_stringstream << prefix << ".sum";
|
|
//SUM_prevparalevel_stringstream << prefix_prevparalevel << ".sum";
|
|
|
|
RAW_string = RAW_stringstream.str(); const char* RAW_Cstr = RAW_string.c_str();
|
|
INADM_string = INADM_stringstream.str(); const char* INADM_Cstr = INADM_string.c_str();
|
|
CONV0_string = CONV0_stringstream.str(); const char* CONV0_Cstr = CONV0_string.c_str();
|
|
STAT_string = STAT_stringstream.str(); const char* STAT_Cstr = STAT_string.c_str();
|
|
LOG_string = LOG_stringstream.str(); const char* LOG_Cstr = LOG_string.c_str();
|
|
THR_string = THR_stringstream.str(); const char* THR_Cstr = THR_string.c_str();
|
|
SRC_string = SRC_stringstream.str(); const char* SRC_Cstr = SRC_string.c_str();
|
|
//FSR_string = FSR_stringstream.str(); const char* FSR_Cstr = FSR_string.c_str();
|
|
SUM_string = SUM_stringstream.str(); const char* SUM_Cstr = SUM_string.c_str();
|
|
//SUM_prevparalevel_string = SUM_prevparalevel_stringstream.str(); const char* SUM_prevparalevel_Cstr = SUM_prevparalevel_string.c_str();
|
|
|
|
THRDIR_string = THRDIR_stringstream.str();
|
|
|
|
fstream RAW_outfile;
|
|
if (!refine || in_parallel) RAW_outfile.open(RAW_Cstr, fstream::out | fstream::trunc);
|
|
else RAW_outfile.open(RAW_Cstr, fstream::out | fstream::app);
|
|
if (RAW_outfile.fail()) {
|
|
cout << RAW_Cstr << endl;
|
|
JSCerror("Could not open RAW_outfile... ");
|
|
}
|
|
RAW_outfile.precision(16);
|
|
|
|
fstream INADM_outfile;
|
|
if (!refine || in_parallel) INADM_outfile.open(INADM_Cstr, fstream::out | fstream::trunc);
|
|
else INADM_outfile.open(INADM_Cstr, fstream::out | fstream::app);
|
|
if (INADM_outfile.fail()) JSCerror("Could not open INADM_outfile... ");
|
|
INADM_outfile.precision(16);
|
|
|
|
fstream CONV0_outfile;
|
|
if (!refine || in_parallel) CONV0_outfile.open(CONV0_Cstr, fstream::out | fstream::trunc);
|
|
else CONV0_outfile.open(CONV0_Cstr, fstream::out | fstream::app);
|
|
if (CONV0_outfile.fail()) JSCerror("Could not open CONV0_outfile... ");
|
|
CONV0_outfile.precision(16);
|
|
|
|
fstream STAT_outfile;
|
|
if (!refine || in_parallel) STAT_outfile.open(STAT_Cstr, fstream::out | fstream::trunc);
|
|
else STAT_outfile.open(STAT_Cstr, fstream::out | fstream::app);
|
|
if (STAT_outfile.fail()) JSCerror("Could not open STAT_outfile... ");
|
|
STAT_outfile.precision(8);
|
|
|
|
ofstream LOG_outfile;
|
|
if (!in_parallel) {
|
|
if (!refine) LOG_outfile.open(LOG_Cstr, fstream::out | fstream::trunc);
|
|
else LOG_outfile.open(LOG_Cstr, fstream::out | fstream::app);
|
|
if (LOG_outfile.fail()) JSCerror("Could not open LOG_outfile... ");
|
|
LOG_outfile.precision(16);
|
|
}
|
|
else { // in_parallel
|
|
LOG_outfile.open(LOG_Cstr, fstream::out | fstream::trunc);
|
|
if (LOG_outfile.fail()) JSCerror("Could not open LOG_outfile... ");
|
|
LOG_outfile.precision(16);
|
|
//LOG_outfile << endl;
|
|
}
|
|
|
|
Scan_Info scan_info;
|
|
|
|
//Scan_Thread_Set paused_thread_set;
|
|
//Scan_Thread_Set paused_thread_set_this_run;
|
|
if (!refine) mkdir(THRDIR_string.c_str(), S_IRWXU | S_IRWXG | S_IRWXO);
|
|
Scan_Thread_Data paused_thread_data (THRDIR_string, refine);
|
|
|
|
if (refine) {
|
|
//paused_thread_set.Load(THR_Cstr);
|
|
paused_thread_data.Load();
|
|
if (!in_parallel) scan_info.Load(SRC_Cstr);
|
|
}
|
|
|
|
Scan_Info scan_info_before = scan_info; // for LOG file
|
|
Scan_Info scan_info_before_descent;
|
|
Scan_Info scan_info_obtained_in_descent;
|
|
|
|
Scan_State_List<Tstate> ScanStateList (whichDSF, SeedScanState);
|
|
ScanStateList.Populate_List(whichDSF, SeedScanState);
|
|
|
|
if (refine && !in_parallel) ScanStateList.Load_Info (SUM_Cstr);
|
|
else if (in_parallel && rank.sum() == 0) {}; // do nothing, keep the info in the higher .sum file!
|
|
|
|
DP Chem_Pot = Chemical_Potential (AveragingState);
|
|
DP sumrule_factor = Sumrule_Factor (whichDSF, AveragingState, Chem_Pot, iKmin, iKmax);
|
|
|
|
//clock_t stop_time_local = clock();
|
|
|
|
|
|
// Now go for it !
|
|
|
|
bool at_least_one_new_flag_raised = false;
|
|
|
|
int Ndata_previous_cycle = 0;
|
|
|
|
int ninadm = 0; // number of inadmissible states for which we save some info in .inadm file. Save first 1000.
|
|
int nconv0 = 0; // number of unconverged states for which we save some info in .conv0 file. Save first 1000.
|
|
|
|
double start_time_omp = omp_get_wtime();
|
|
double current_time_omp = omp_get_wtime();
|
|
|
|
#pragma omp parallel
|
|
do {
|
|
|
|
int omp_thread_nr = omp_get_thread_num();
|
|
|
|
if ((paused_thread_data.lowest_il_with_nthreads_neq_0 == paused_thread_data.nlists - 1)
|
|
&& omp_thread_nr > 0) {
|
|
double start_time_wait = omp_get_wtime();
|
|
//cout << "omp_thread " << omp_thread_nr << " sleeping for 5 seconds... " << endl;
|
|
//sleep(5); // give time to master omp_thread to populate threads
|
|
double stop_time_wait;
|
|
do {
|
|
for (int i = 0; i < 100000; ++i) { }
|
|
stop_time_wait = omp_get_wtime();
|
|
} while (stop_time_wait - start_time_wait < 5.0);
|
|
//cout << "omp_thread " << omp_thread_nr << " restarting" << endl;
|
|
}
|
|
|
|
double start_time_cycle_omp = omp_get_wtime();
|
|
|
|
at_least_one_new_flag_raised = false;
|
|
|
|
//if (!in_parallel) { // flag raising not allowed in parallel mode
|
|
//if (!in_parallel || rank == 0) { // flag raising only allowed if not in parallel mode, or if rank == 0
|
|
//if (!in_parallel || rank.sum() == 0) { // flag raising only allowed if not in parallel mode, or if rank == 0 at all paralevels
|
|
|
|
//if (!in_parallel) { // flag raising not allowed in parallel mode
|
|
#pragma omp master
|
|
{
|
|
//clock_t start_time_flags = clock();
|
|
double start_time_flags = omp_get_wtime();
|
|
|
|
// First flag the new base/type 's that we need to include:
|
|
//thresholdremoved ScanStateList.Raise_Scanning_Flags (running_scan_threshold);
|
|
ScanStateList.Raise_Scanning_Flags (exp(-paused_thread_data.logscale * paused_thread_data.lowest_il_with_nthreads_neq_0));
|
|
|
|
//cout << "flags: " << endl << ScanStateList.flag_for_scan << endl;
|
|
|
|
|
|
// Get these base/type started:
|
|
for (int i = 0; i < ScanStateList.ndef; ++i) {
|
|
if (ScanStateList.flag_for_scan[i] && ScanStateList.info[i].Ndata == 0 && !ScanStateList.scan_attempted[i]) {
|
|
|
|
Scan_Info scan_info_flags;
|
|
|
|
at_least_one_new_flag_raised = true;
|
|
|
|
ScanStateList.scan_attempted[i] = true;
|
|
|
|
Tstate ScanState;
|
|
|
|
//scan_info_before_descent = scan_info;
|
|
|
|
ScanState = ScanStateList.State[i];
|
|
|
|
//cout << "ScanStateList.State[i] = " << ScanState << endl;
|
|
|
|
DP data_value = -1.0;
|
|
|
|
bool admissible = ScanState.Check_Admissibility(whichDSF);
|
|
|
|
if (admissible) {
|
|
|
|
ScanState.Compute_All(true);
|
|
|
|
if (ScanState.conv) {
|
|
|
|
// Put momentum in fundamental window, if possible:
|
|
int iKexc = ScanState.iK - AveragingState.iK;
|
|
while (iKexc > iKmax && iKexc - iKmod >= iKmin) iKexc -= iKmod;
|
|
while (iKexc < iKmin && iKexc + iKmod <= iKmax) iKexc += iKmod;
|
|
|
|
//if (iKexc >= iKmin && iKexc <= iKmax) RAW_outfile << endl;
|
|
|
|
//data_value = Compute_Matrix_Element_Contrib (whichDSF, iKmin, iKmax, ScanState, AveragingState, Chem_Pot, RAW_outfile);
|
|
stringstream rawfile_entry;
|
|
data_value = Compute_Matrix_Element_Contrib (whichDSF, iKmin, iKmax, ScanState, AveragingState, Chem_Pot, rawfile_entry);
|
|
{
|
|
#pragma omp critical
|
|
RAW_outfile << rawfile_entry.str();
|
|
}
|
|
//cout << "data_value for ScanState.label " << ScanState.label << " = " << data_value << endl;
|
|
{
|
|
#pragma omp critical
|
|
if (iKexc >= iKmin && iKexc <= iKmax) {
|
|
scan_info_flags.Ndata++;
|
|
scan_info_flags.Ndata_conv++;
|
|
scan_info_flags.sumrule_obtained += data_value*sumrule_factor;
|
|
}
|
|
}
|
|
//cout << data_value * sumrule_factor << endl;
|
|
|
|
// If we force descent: modify data_value by hand so that descent is forced on next scanning pass
|
|
//if (Force_Descent(whichDSF, ScanState, AveragingState, iKmod, Chem_Pot) && ScanState.iK - AveragingState.iK < iKmax && Sca nState.iK - AveragingState.iK > iKmin)
|
|
//if (Force_Descent(whichDSF, ScanState, AveragingState, iKmod, Chem_Pot))
|
|
for (int itype = 0; itype < 15; ++itype) {
|
|
DP data_value_used = 0.1* exp(-paused_thread_data.logscale * JSC::min(0, paused_thread_data.lowest_il_with_nthreads_neq_0));
|
|
if (Force_Descent(whichDSF, ScanState, AveragingState, itype, iKmod, Chem_Pot))
|
|
//data_value = 0.1* exp(-paused_thread_data.logscale * paused_thread_data.lowest_il_with_nthreads_neq_0);
|
|
data_value = data_value_used;
|
|
}
|
|
// ++G_7 logic
|
|
Vect<bool> allowed(false, 15);
|
|
if (whichDSF == 'B') { // symmetric state scanning
|
|
allowed[9] = true; allowed[10] = true; allowed[11] = true;
|
|
allowed[12] = true; allowed[13] = true; allowed[14] = true;
|
|
}
|
|
else {
|
|
allowed[0] = (iKexc >= iKmin && iKexc <= iKmax);
|
|
allowed[1] = allowed[0]; allowed[2] = allowed[0]; allowed[3] = allowed[0]; allowed[4] = allowed[0]; allowed[5] = allowed[0]; allowed[6] = allowed[0]; allowed[7] = allowed[0]; allowed[8] = allowed[0];
|
|
//allowed[9] = (iKexc <= 0 && iKexc > iKmin);
|
|
allowed[9] = (iKexc > iKmin);
|
|
allowed[10] = allowed[9]; allowed[11] = allowed[9];
|
|
//allowed[12] = (iKexc >= 0 && iKexc < iKmax);
|
|
allowed[12] = (iKexc < iKmax);
|
|
allowed[13] = allowed[12]; allowed[14] = allowed[12];
|
|
}
|
|
for (int type_required_here = 0; type_required_here < 15; ++type_required_here) {
|
|
if (!allowed[type_required_here]) continue;
|
|
// All cases here are such that the ScanState hasn't been descended yet, so we simply use data_value as expected data value:
|
|
//paused_thread_set_this_run.Include_Thread (abs(data_value), ScanState.label, type_required_here);
|
|
{
|
|
#pragma omp critical
|
|
paused_thread_data.Include_Thread (abs(data_value), ScanState.label, type_required_here);
|
|
}
|
|
}
|
|
} // if (ScanState.conv)
|
|
|
|
else {
|
|
if (nconv0++ < 1000)
|
|
CONV0_outfile << setw(25) << ScanState.label << setw(25) << ScanState.diffsq << setw(5) << ScanState.Check_Rapidities()
|
|
<< setw(25) << ScanState.String_delta() << endl;
|
|
scan_info_flags.Ndata++;
|
|
scan_info_flags.Ndata_conv0++;
|
|
}
|
|
} // if admissible
|
|
|
|
else { // if inadmissible, modify data_value by hand so that descent is forced on next scanning pass
|
|
|
|
if (ninadm++ < 10000000) INADM_outfile << ScanState.label << endl;
|
|
scan_info_flags.Ndata++;
|
|
scan_info_flags.Ninadm++;
|
|
|
|
// Put momentum in fundamental window, if possible:
|
|
int iKexc = ScanState.iK - AveragingState.iK;
|
|
while (iKexc > iKmax && iKexc - iKmod >= iKmin) iKexc -= iKmod;
|
|
while (iKexc < iKmin && iKexc + iKmod <= iKmax) iKexc += iKmod;
|
|
|
|
//thresholdremoved DP data_value = 2.0* running_scan_threshold;
|
|
//DP data_value = 2.0 * exp(-paused_thread_data.logscale * paused_thread_data.lowest_il_with_nthreads_neq_0);
|
|
//DP data_value = 0.1* running_scan_threshold;
|
|
DP data_value = 1.0e-32;
|
|
for (int itype = 0; itype < 15; ++itype)
|
|
if (Force_Descent(whichDSF, ScanState, AveragingState, itype, iKmod, Chem_Pot))
|
|
data_value = 0.1* exp(-paused_thread_data.logscale * paused_thread_data.lowest_il_with_nthreads_neq_0);
|
|
|
|
// ++G_7 logic
|
|
Vect<bool> allowed(false, 15);
|
|
if (whichDSF == 'B') {
|
|
// We scan over symmetric states. Only types 14 down to 9 are allowed.
|
|
allowed[9] = true; allowed[10] = true; allowed[11] = true;
|
|
allowed[12] = true; allowed[13] = true; allowed[14] = true;
|
|
}
|
|
else {
|
|
allowed[0] = (iKexc >= iKmin && iKexc <= iKmax);
|
|
allowed[1] = allowed[0]; allowed[2] = allowed[0]; allowed[3] = allowed[0]; allowed[4] = allowed[0]; allowed[5] = allowed[0]; allowed[6] = allowed[0]; allowed[7] = allowed[0]; allowed[8] = allowed[0];
|
|
//allowed[9] = (iKexc <= 0 && iKexc > iKmin);
|
|
allowed[9] = (iKexc > iKmin);
|
|
allowed[10] = allowed[9]; allowed[11] = allowed[9];
|
|
//allowed[12] = (iKexc >= 0 && iKexc < iKmax);
|
|
allowed[12] = (iKexc < iKmax);
|
|
allowed[13] = allowed[12]; allowed[14] = allowed[12];
|
|
}
|
|
for (int type_required_here = 0; type_required_here < 15; ++type_required_here) {
|
|
if (!allowed[type_required_here]) continue;
|
|
//paused_thread_set_this_run.Include_Thread (abs(data_value), ScanState.label, type_required_here);
|
|
{
|
|
#pragma omp critical
|
|
paused_thread_data.Include_Thread (abs(data_value), ScanState.label, type_required_here);
|
|
}
|
|
}
|
|
} // inadmissible
|
|
|
|
//scan_info_obtained_in_descent = scan_info;
|
|
//scan_info_obtained_in_descent -= scan_info_before_descent;
|
|
|
|
scan_info_flags.TT += omp_get_wtime() - start_time_flags;
|
|
|
|
// Put this info into the appropriate ScanStateList.info
|
|
{
|
|
#pragma omp critical
|
|
//ScanStateList.Include_Info(scan_info_obtained_in_descent, ScanStateList.base_label[i]);
|
|
//cout << "Including info_flags: " << scan_info_flags << endl;
|
|
ScanStateList.Include_Info(scan_info_flags, ScanStateList.base_label[i]);
|
|
scan_info += scan_info_flags;
|
|
}
|
|
|
|
//cout << "Done with state " << ScanState.label << endl;
|
|
|
|
} // if flag_for_scan
|
|
} // for i
|
|
|
|
//clock_t stop_time_flags = clock();
|
|
|
|
//scan_info.CPU_ticks += stop_time_flags - start_time_flags;
|
|
//scan_info.TT += (stop_time_flags - start_time_flags)/CLOCKS_PER_SEC;
|
|
//scan_info.TT += omp_get_wtime() - start_time_flags;
|
|
|
|
//} // if (!in_parallel || rank == 0)
|
|
|
|
} // #pragma omp master
|
|
|
|
//cout << "Done raising flags." << endl;
|
|
|
|
// Now we deal with the previously existing paused threads:
|
|
|
|
//if (scan_info.CPU_ticks < ((long long int) Max_Secs) * ((long long int) CLOCKS_PER_SEC)) {
|
|
|
|
//Vect<Scan_Thread> threads_to_do = paused_thread_data.Extract_Next_Scan_Threads();
|
|
Vect<Scan_Thread> threads_to_do;
|
|
int il_to_do = paused_thread_data.lowest_il_with_nthreads_neq_0; // for resaving threads in case we're out of time
|
|
{
|
|
#pragma omp critical
|
|
threads_to_do = paused_thread_data.Extract_Next_Scan_Threads();
|
|
//threads_to_do = paused_thread_data.Extract_Next_Scan_Threads(100);
|
|
}
|
|
//cout << "Size of threads_to_do: " << threads_to_do.size() << endl;
|
|
//for (int i = 0; i < threads_to_do.size(); ++i) cout << threads_to_do[i].label << "\t" << threads_to_do[i].type << "\t";
|
|
//cout << endl;
|
|
|
|
int ithread;
|
|
|
|
//omp1#pragma omp parallel
|
|
{
|
|
//omp1#pragma omp for
|
|
for (ithread = 0; ithread < threads_to_do.size(); ++ithread) {
|
|
|
|
//cout << "\tithread = " << ithread << endl;
|
|
//scan_info_before_descent = scan_info;
|
|
|
|
//int tid = omp_get_thread_num();
|
|
//{
|
|
//#pragma omp critical
|
|
//cout << "Thread " << tid << " handling ithread " << ithread << " out of " << threads_to_do.size() << "\t" << threads_to_do[ithread].label << "\t" << threads_to_do[ithread].type << endl;
|
|
//}
|
|
|
|
Scan_Info scan_info_this_ithread;
|
|
double start_time_this_ithread = omp_get_wtime();
|
|
|
|
// If we don't have time anymore, resave the threads instead of computing them:
|
|
if (start_time_this_ithread - start_time_omp > Max_Secs_alert) {
|
|
for (int ith = ithread; ith < threads_to_do.size(); ++ith) {
|
|
#pragma omp critical
|
|
paused_thread_data.Include_Thread (il_to_do, threads_to_do[ith].label, threads_to_do[ith].type);
|
|
}
|
|
break; // jump out of ithread loop
|
|
}
|
|
|
|
Tstate ScanState;
|
|
{
|
|
#pragma omp critical
|
|
ScanState = ScanStateList.Return_State(Extract_Base_Label(threads_to_do[ithread].label));
|
|
}
|
|
Tstate BaseScanState; BaseScanState = ScanState;
|
|
|
|
//cout << "Setting to label = " << threads_to_do[ithread].label << ", descending type " << threads_to_do[ithread].type << endl;
|
|
ScanState.Set_to_Label(threads_to_do[ithread].label, BaseScanState.Ix2);
|
|
//cout << "ScanState after setting label: " << threads_to_do[ithread].label << endl << ScanState << endl;
|
|
|
|
|
|
//cout << "Calling Descend_and_Compute with type " << paused_thread_list.type[ithread] << " on state" << endl << ScanState << endl;
|
|
/*
|
|
Descend_and_Compute_for_Fixed_Base (whichDSF, AveragingState, BaseScanState, ScanState,
|
|
//paused_thread_set.type[ilist][ithread], iKmin, iKmax, iKmod,
|
|
threads_to_do[ithread].type, iKmin, iKmax, iKmod,
|
|
//paused_thread_set_this_run, running_scan_threshold,
|
|
paused_thread_data, //thresholdremoved running_scan_threshold,
|
|
//paused_thread_set[ilist].abs_data_value[ithread],
|
|
ph_cost,
|
|
Max_Secs_used, sumrule_factor, Chem_Pot, scan_info, RAW_outfile,
|
|
INADM_outfile, ninadm, CONV0_outfile, nconv0, STAT_outfile);
|
|
*/
|
|
|
|
// STARTING Descend_and_Compute block:
|
|
int type_required = threads_to_do[ithread].type;
|
|
|
|
ScanState.Compute_Momentum();
|
|
Vect<string> desc_label;
|
|
|
|
// ++G_7 logic
|
|
bool disperse_only_current_exc_up = false;
|
|
if (type_required == 14 || type_required == 8 || type_required == 7 || type_required == 6) disperse_only_current_exc_up = true;
|
|
bool preserve_nexc_up = false;
|
|
if (type_required == 13 || type_required == 5 || type_required == 4 || type_required == 3) preserve_nexc_up = true;
|
|
bool disperse_only_current_exc_down = false;
|
|
if (type_required == 11 || type_required == 8 || type_required == 5 || type_required == 2) disperse_only_current_exc_down = true;
|
|
bool preserve_nexc_down = false;
|
|
if (type_required == 10 || type_required == 7 || type_required == 4 || type_required == 1) preserve_nexc_down = true;
|
|
|
|
if (whichDSF == 'B') { // symmetric state scanning
|
|
if (type_required >= 9 && type_required <= 11)
|
|
desc_label = Descendent_States_with_iK_Stepped_Down_rightIx2only (ScanState.label, BaseScanState, disperse_only_current_exc_down, preserve_nexc_down);
|
|
else if (type_required >= 12 && type_required <= 14)
|
|
desc_label = Descendent_States_with_iK_Stepped_Up_rightIx2only (ScanState.label, BaseScanState, disperse_only_current_exc_up, preserve_nexc_up);
|
|
}
|
|
else {
|
|
if (type_required >= 0 && type_required <= 8) {
|
|
desc_label = Descendent_States_with_iK_Preserved(ScanState.label, BaseScanState, disperse_only_current_exc_up, preserve_nexc_up, disperse_only_current_exc_down, preserve_nexc_down);
|
|
}
|
|
else if (type_required >= 9 && type_required <= 11)
|
|
desc_label = Descendent_States_with_iK_Stepped_Down (ScanState.label, BaseScanState, disperse_only_current_exc_down, preserve_nexc_down);
|
|
else if (type_required >= 12 && type_required <= 14)
|
|
desc_label = Descendent_States_with_iK_Stepped_Up (ScanState.label, BaseScanState, disperse_only_current_exc_up, preserve_nexc_up);
|
|
}
|
|
|
|
string label_here = ScanState.label;
|
|
//int ScanState_iK = ScanState.iK;
|
|
|
|
for (int idesc = 0; idesc < desc_label.size(); ++idesc) {
|
|
|
|
//clock_t start_time_here = clock();
|
|
|
|
ScanState.Set_to_Label (desc_label[idesc], BaseScanState.Ix2);
|
|
|
|
bool admissible = ScanState.Check_Admissibility(whichDSF);
|
|
|
|
DP data_value = 0.0;
|
|
|
|
//scan_info.Ndata++;
|
|
//scan_info_this_ithread.Ndata++;
|
|
|
|
ScanState.conv = false;
|
|
ScanState.Compute_Momentum(); // since momentum is used as forced descent criterion
|
|
|
|
|
|
if (admissible) {
|
|
|
|
ScanState.Compute_All (idesc == 0);
|
|
//ScanState.Compute_All (true);
|
|
|
|
//scan_info.Ndata++;
|
|
|
|
if (ScanState.conv) {
|
|
//scan_info_this_ithread.Ndata_conv++;
|
|
|
|
// Put momentum in fundamental window, if possible:
|
|
int iKexc = ScanState.iK - AveragingState.iK;
|
|
while (iKexc > iKmax && iKexc - iKmod >= iKmin) iKexc -= iKmod;
|
|
while (iKexc < iKmin && iKexc + iKmod <= iKmax) iKexc += iKmod;
|
|
|
|
//data_value = Compute_Matrix_Element_Contrib (whichDSF, iKmin, iKmax, ScanState, AveragingState, Chem_Pot, RAW_outfile);
|
|
stringstream rawfile_entry;
|
|
data_value = Compute_Matrix_Element_Contrib (whichDSF, iKmin, iKmax, ScanState, AveragingState, Chem_Pot, rawfile_entry);
|
|
|
|
{
|
|
#pragma omp critical
|
|
RAW_outfile << rawfile_entry.str();
|
|
if (iKexc >= iKmin && iKexc <= iKmax) {
|
|
scan_info_this_ithread.Ndata++;
|
|
scan_info_this_ithread.Ndata_conv++;
|
|
scan_info_this_ithread.sumrule_obtained += data_value*sumrule_factor;
|
|
}
|
|
}
|
|
|
|
//if (iKexc >= iKmin && iKexc <= iKmax) scan_info_this_ithread.sumrule_obtained += data_value*sumrule_factor;
|
|
//cout << "data_value found = " << data_value * sumrule_factor << endl;
|
|
|
|
// Uncomment line below if .stat file is desired:
|
|
//STAT_outfile << setw(20) << label_here << "\t" << setw(5) << type_required << "\t" << setw(16) << std::scientific << running_scan_threshold << "\t" << setw(20) << ScanState.label << "\t" << setw(16) << data_value << "\t" << setw(16) << std::fixed << setprecision(8) << data_value/running_scan_threshold << endl;
|
|
|
|
} // if (ScanState.conv)
|
|
else {
|
|
if (nconv0++ < 1000)
|
|
CONV0_outfile << setw(25) << ScanState.label << setw(25) << ScanState.diffsq << setw(5) << ScanState.Check_Rapidities()
|
|
<< setw(25) << ScanState.String_delta() << endl;
|
|
//scan_info.Ndata_conv0++;
|
|
scan_info_this_ithread.Ndata++;
|
|
scan_info_this_ithread.Ndata_conv0++;
|
|
//cout << "State did not converge." << endl;
|
|
}
|
|
} // if (admissible)
|
|
|
|
else {
|
|
if (ninadm++ < 1000000) INADM_outfile << ScanState.label << endl;
|
|
//scan_info.Ninadm++;
|
|
scan_info_this_ithread.Ndata++;
|
|
scan_info_this_ithread.Ninadm++;
|
|
//cout << "State was inadmissible." << endl;
|
|
// Set data_value to enable continued scanning later on:
|
|
//thresholdremoved data_value = 0.1* running_scan_threshold;
|
|
}
|
|
|
|
|
|
//clock_t stop_time_here = clock();
|
|
|
|
//scan_info.CPU_ticks += stop_time_here - start_time_here;
|
|
//scan_info_this_ithread.CPU_ticks += stop_time_here - start_time_here;
|
|
//scan_info_this_ithread.TT += (stop_time_here - start_time_here)/CLOCKS_PER_SEC;
|
|
|
|
Tstate state_to_descend; state_to_descend = ScanState; // for checking
|
|
|
|
ScanState.Compute_Momentum();
|
|
// Put momentum in fundamental window, if possible:
|
|
int iKexc = ScanState.iK - AveragingState.iK;
|
|
while (iKexc > iKmax && iKexc - iKmod >= iKmin) iKexc -= iKmod;
|
|
while (iKexc < iKmin && iKexc + iKmod <= iKmax) iKexc += iKmod;
|
|
|
|
// ++G_7 logic
|
|
// Momentum-preserving are only descended to momentum-preserving.
|
|
// Momentum-increasing are only descended to momentum-preserving and momentum-increasing.
|
|
// Momentum-decreasing are only descended to momentum-preserving and momentum-decreasing.
|
|
Vect<bool> allowed(false, 15);
|
|
if (whichDSF == 'B') {
|
|
// We scan over symmetric states. Only types 14 down to 9 are allowed.
|
|
if (type_required >= 9 && type_required <= 11) { // iK stepped down on rightIx2; step further up or down
|
|
allowed[9] = true; allowed[10] = true; allowed[11] = true;
|
|
allowed[12] = true; allowed[13] = true; allowed[14] = true;
|
|
}
|
|
else if (type_required >= 12 && type_required <= 14) { // iK stepped up on rightIx2; only step further up
|
|
allowed[12] = true; allowed[13] = true; allowed[14] = true;
|
|
}
|
|
}
|
|
else {
|
|
if (type_required >= 0 && type_required <= 8) { // momentum-preserving
|
|
allowed[0] = (iKexc >= iKmin && iKexc <= iKmax);
|
|
allowed[9] = false;
|
|
allowed[12] = false;
|
|
}
|
|
if (type_required >= 9 && type_required <= 11) { // momentum-decreasing
|
|
allowed[0] = (iKexc >= iKmin && iKexc <= iKmax);
|
|
allowed[9] = (iKexc > iKmin);
|
|
allowed[12] = false;
|
|
}
|
|
if (type_required >= 12 && type_required <= 14) { // momentum-increasing
|
|
allowed[0] = (iKexc >= iKmin && iKexc <= iKmax);
|
|
allowed[9] = false;
|
|
allowed[12] = (iKexc < iKmax);
|
|
}
|
|
// The others are just copies of the ones above:
|
|
allowed[1] = allowed[0]; allowed[2] = allowed[0]; allowed[3] = allowed[0]; allowed[4] = allowed[0]; allowed[5] = allowed[0]; allowed[6] = allowed[0]; allowed[7] = allowed[0]; allowed[8] = allowed[0];
|
|
allowed[10] = allowed[9]; allowed[11] = allowed[9];
|
|
allowed[13] = allowed[12]; allowed[14] = allowed[12];
|
|
}
|
|
|
|
|
|
for (int type_required_here = 0; type_required_here < 15; ++type_required_here) {
|
|
|
|
if (!allowed[type_required_here]) continue;
|
|
|
|
// Reset ScanState to what it was, if change on first pass
|
|
if (type_required_here > 0) ScanState = state_to_descend;
|
|
|
|
// We determine if we carry on scanning based on the data_value obtained, or forcing conditions:
|
|
// Forcing conditions:
|
|
//if (!admissible || Force_Descent(whichDSF, ScanState, AveragingState, type_required_here, iKmod, Chem_Pot))
|
|
////data_value = 1.01 * running_scan_threshold/ph_cost; // force for all types of desc
|
|
//data_value = 1.01 * running_scan_threshold; // only force for no new ph pairs
|
|
////data_value = 1.0; // force for all types of desc
|
|
// If we're sitting out of the iKmin & iKmax window, stop:
|
|
//if (iKmin != iKmax && (ScanState.iK - AveragingState.iK > iKmax || ScanState.iK - AveragingState.iK < iKmin)) data_value = 0.0;
|
|
|
|
//if (abs(data_value) * (type_required_here != 2 ? 1.0 : ph_cost) > running_scan_threshold
|
|
//if ((abs(data_value) > running_scan_threshold
|
|
//|| Nr_ph_Recombinations_Possible (ScanState.label, BaseScanState, type_required_here) > 0)
|
|
|
|
//DP expected_abs_data_value = abs(data_value)/pow(ph_cost, DP(Nr_ph_Recombinations_Possible (ScanState.label, BaseScanState, type_required_here)));
|
|
DP expected_abs_data_value = abs(data_value);
|
|
|
|
//++G_7 logic
|
|
if ((type_required_here == 14 || type_required_here == 8 || type_required_here == 7 || type_required_here == 6)
|
|
&& Expect_ph_Recombination_iK_Up (ScanState.label, BaseScanState)) expected_abs_data_value /= ph_cost;
|
|
if (type_required_here == 12 || type_required_here == 2 || type_required_here == 1 || type_required_here == 0)
|
|
expected_abs_data_value *= ph_cost;
|
|
if ((type_required_here == 11 || type_required_here == 8 || type_required_here == 5 || type_required_here == 2)
|
|
&& Expect_ph_Recombination_iK_Down (ScanState.label, BaseScanState)) expected_abs_data_value /= ph_cost;
|
|
if (type_required_here == 9 || type_required_here == 6 || type_required_here == 3 || type_required_here == 0)
|
|
expected_abs_data_value *= ph_cost;
|
|
|
|
//paused_thread_set.Include_Thread (expected_abs_data_value, ScanState.label, type_required_here);
|
|
{
|
|
#pragma omp critical
|
|
//cout << "\tIncluding thread " << ScanState.label << "\t" << type_required_here << "\tdata_value " << data_value << "\texpected abs data value " << expected_abs_data_value << endl;
|
|
paused_thread_data.Include_Thread (expected_abs_data_value, ScanState.label, type_required_here);
|
|
}
|
|
//cout << "\tDone including thread." << endl;
|
|
} // for type_required_here
|
|
|
|
//cout << "\tFinished with descendent " << idesc << " out of " << desc_label.size() << " with label " << desc_label[idesc] << endl;
|
|
//cout << "\tfrom state with label " << label_here << endl;
|
|
} // for idesc
|
|
|
|
//cout << "Finished Descend on state " << endl << ScanState.label << endl;
|
|
|
|
// FINISHED Descend_and_Compute block
|
|
|
|
|
|
|
|
//cout << "Finished descending." << endl;
|
|
//cout << "\tFinished descending ithread = " << ithread << endl;
|
|
|
|
//scan_info_obtained_in_descent = scan_info;
|
|
//scan_info_obtained_in_descent -= scan_info_before_descent;
|
|
//// Put this info into the appropriate ScanStateList.info
|
|
//ScanStateList.Include_Info(scan_info_obtained_in_descent, Extract_Base_Label(threads_to_do[ithread].label));
|
|
|
|
scan_info_this_ithread.TT += omp_get_wtime() - start_time_this_ithread;
|
|
|
|
#pragma omp critical
|
|
{
|
|
scan_info += scan_info_this_ithread;
|
|
//cout << "Including info_ihtread: " << scan_info_this_ithread << endl;
|
|
ScanStateList.Include_Info(scan_info_this_ithread, Extract_Base_Label(threads_to_do[ithread].label));
|
|
}
|
|
} // for ithread
|
|
|
|
} // omp parallel region
|
|
|
|
// Resynchronize all compute threads:
|
|
//omp1#pragma omp barrier
|
|
|
|
//cout << "Done with threads_to_do." << endl;
|
|
|
|
// } // if time
|
|
|
|
//start_time_local = clock();
|
|
|
|
/*
|
|
if (!in_parallel)
|
|
LOG_outfile << "Ndata handled up to now: " << scan_info.Ndata_conv
|
|
<< ". Threshold level " << paused_thread_data.lowest_il_with_nthreads_neq_0 << " " << setprecision(6) << exp(-paused_thread_data.logscale * paused_thread_data.lowest_il_with_nthreads_neq_0)
|
|
<< ". " << scan_info.Ndata - Ndata_previous_cycle << " new data points. Number of threads: "
|
|
<< paused_thread_data.nthreads_total.sum()
|
|
<< ". Saturation: " << setprecision(12) << scan_info.sumrule_obtained << endl;
|
|
*/
|
|
|
|
//int tid = omp_get_thread_num();
|
|
#pragma omp master
|
|
{
|
|
if (!in_parallel)
|
|
LOG_outfile << "Master cycling. Ndata_conv " << scan_info.Ndata_conv
|
|
<< ". Threshold " << paused_thread_data.lowest_il_with_nthreads_neq_0 << " " << setw(9) << setprecision(3) << exp(-paused_thread_data.logscale * paused_thread_data.lowest_il_with_nthreads_neq_0)
|
|
<< ". " << setw(12) << scan_info.Ndata - Ndata_previous_cycle << " new data. Nr of threads: "
|
|
<< setw(14) << paused_thread_data.nthreads_total.sum()
|
|
<< ". Saturation: " << setprecision(12) << scan_info.sumrule_obtained << endl;
|
|
|
|
Ndata_previous_cycle = scan_info.Ndata;
|
|
}
|
|
|
|
|
|
//stop_time_local = clock();
|
|
|
|
//current_time = clock();
|
|
|
|
//scan_info.CPU_ticks += stop_time_local - start_time_local;
|
|
|
|
//#pragma omp critical
|
|
//scan_info.TT += omp_get_wtime() - start_time_cycle_omp;
|
|
|
|
current_time_omp = omp_get_wtime();
|
|
|
|
//int tid = omp_get_thread_num();
|
|
//if (tid == 0) cout << "current_time_omp - start_time_omp = " << current_time_omp - start_time_omp << "\t" << Max_Secs_used << endl;
|
|
//if (current_time_omp - start_time_omp > Max_Secs_used)
|
|
//cout << "tid " << tid << " exiting." << endl;
|
|
|
|
|
|
//} while (scan_info.CPU_ticks < ((long long int) Max_Secs_used) * ((long long int) CLOCKS_PER_SEC)
|
|
//} while (current_time - start_time < ((long long int) Max_Secs_used) * ((long long int) CLOCKS_PER_SEC)
|
|
} while (current_time_omp - start_time_omp < Max_Secs_used
|
|
&& scan_info.sumrule_obtained < target_sumrule
|
|
//&& paused_thread_list.Highest_abs_data_value(0.0, 1.0e+10) > 1.0e-30
|
|
//&& !(all_threads_zero_previous_cycle && all_threads_zero_current_cycle && !at_least_one_new_flag_raised)
|
|
//thresholdremoved && running_scan_threshold > 1.0e-10*MACHINE_EPS
|
|
);
|
|
// This closes the #pragram omp parallel block
|
|
|
|
RAW_outfile.close();
|
|
INADM_outfile.close();
|
|
CONV0_outfile.close();
|
|
STAT_outfile.close();
|
|
|
|
|
|
//scan_info.CPU_ticks_TOT += scan_info.CPU_ticks;
|
|
scan_info.Save(SRC_Cstr);
|
|
|
|
Scan_Info scan_info_refine = scan_info;
|
|
scan_info_refine -= scan_info_before;
|
|
|
|
if (!in_parallel) {
|
|
|
|
if (scan_info.sumrule_obtained >= target_sumrule)
|
|
LOG_outfile << endl << "Achieved sumrule saturation of " << scan_info.sumrule_obtained
|
|
<< "\t(target was " << target_sumrule << ")." << endl << endl;
|
|
|
|
//thresholdremoved
|
|
//if (running_scan_threshold < MACHINE_EPS)
|
|
//LOG_outfile << endl << "Stopping because threshold lower than machine precision. " << endl << endl;
|
|
|
|
//thresholdremoved if (!refine) LOG_outfile << "Main run info: " << scan_info << endl << "Latest running_scan_threshold = " << running_scan_threshold << endl;
|
|
if (!refine) {
|
|
LOG_outfile << "Main run info: " << scan_info << endl;
|
|
LOG_outfile << "Latest threshold level " << paused_thread_data.lowest_il_with_nthreads_neq_0 << " " << std::scientific << setprecision(3) << exp(-paused_thread_data.logscale * paused_thread_data.lowest_il_with_nthreads_neq_0) << endl;
|
|
}
|
|
else if (refine) {
|
|
//thresholdremoved LOG_outfile << "Refining info: " << scan_info_refine << endl << "Latest running_scan_threshold = " << running_scan_threshold << endl
|
|
LOG_outfile << "Refining info: " << scan_info_refine << endl;
|
|
LOG_outfile << "Latest threshold level " << paused_thread_data.lowest_il_with_nthreads_neq_0 << " " << std::scientific << setprecision(3) << exp(-paused_thread_data.logscale * paused_thread_data.lowest_il_with_nthreads_neq_0) << endl;
|
|
LOG_outfile << "Resulting info: " << scan_info << endl;
|
|
}
|
|
LOG_outfile << "Code version " << JSC_VERSION << ", copyright J.-S. Caux." << endl << endl;
|
|
LOG_outfile.close();
|
|
}
|
|
|
|
else { // in_parallel
|
|
|
|
//thresholdremoved
|
|
//if (running_scan_threshold < MACHINE_EPS)
|
|
//LOG_outfile << "rank " << rank << " out of " << nr_processors << " processors: "
|
|
// << "Stopping because threshold lower than machine precision. " << endl << endl;
|
|
|
|
LOG_outfile << "rank " << rank << " out of " << nr_processors << " processors: "
|
|
//thresholdremoved << "run info: " << scan_info << endl << "Latest running_scan_threshold = " << running_scan_threshold << endl;
|
|
<< "run info: " << scan_info << endl << "Latest threshold = " << exp(-paused_thread_data.logscale * paused_thread_data.lowest_il_with_nthreads_neq_0) << endl;
|
|
}
|
|
|
|
//if (paused_thread_list.dim < 1000000) paused_thread_list.Order_in_abs_data_value();
|
|
//paused_thread_list.Save(THR_Cstr);
|
|
//paused_thread_set.Save(THR_Cstr);
|
|
paused_thread_data.Save();
|
|
|
|
ScanStateList.Order_in_SRC ();
|
|
|
|
//cout << "Saving info: " << endl; for (int idef = 0; idef < ScanStateList.ndef; ++idef) cout << ScanStateList.info[idef] << endl;
|
|
ScanStateList.Save_Info (SUM_Cstr);
|
|
|
|
|
|
// Evaluate f-sumrule:
|
|
//if (!fixed_iK && !in_parallel) if (whichDSF != 'q') Evaluate_F_Sumrule (whichDSF, AveragingState, Chem_Pot, RAW_Cstr, FSR_Cstr);
|
|
//if (iKmin != iKmax && !in_parallel) if (whichDSF != 'q') Evaluate_F_Sumrule (whichDSF, AveragingState, Chem_Pot, iKmin, iKmax, RAW_Cstr, FSR_Cstr);
|
|
//if (iKmin != iKmax && !in_parallel ) if (whichDSF != 'q') Evaluate_F_Sumrule (prefix_prevparalevel, whichDSF, AveragingState, Chem_Pot, iKmin, iKmax);
|
|
if (!in_parallel ) if (whichDSF != 'q') Evaluate_F_Sumrule (prefix_prevparalevel, whichDSF, AveragingState, Chem_Pot, iKmin, iKmax);
|
|
|
|
// Produce sorted file
|
|
//if (!in_parallel && whichDSF != 'Z') Sort_RAW_File (RAW_Cstr, 'f', whichDSF);
|
|
//if (!in_parallel && whichDSF == 'Z') Sort_RAW_File (RAW_Cstr, 'e', whichDSF);
|
|
|
|
return(scan_info);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//******************************************************
|
|
|
|
// Functions to initiate scans:
|
|
|
|
|
|
// General version for equilibrium correlators at generic (possibly finite) temperature:
|
|
|
|
void Scan_LiebLin (char whichDSF, DP c_int, DP L, int N, int iKmin, int iKmax, DP kBT,
|
|
int Max_Secs, DP target_sumrule, bool refine, int paralevel, Vect<int> rank, Vect<int> nr_processors)
|
|
{
|
|
|
|
// This function scans the Hilbert space of the LiebLin gas,
|
|
// for the function identified by whichDSF.
|
|
|
|
// whichDSF == 'Z': canonical partition function
|
|
// whichDSF == 'd': density-density correlation function
|
|
// whichDSF == 'g': Green's function < \Psi \Psi^{\dagger}>
|
|
// whichDSF == 'o': one-body function < \Psi^{\dagger} \Psi >
|
|
|
|
// Delta is the number of sites involved in the smoothing of the entropy
|
|
//int Delta = int(sqrt(N))/2;//6;//N/20;
|
|
//DP epsilon = log(L)/L; // using Gaussian for density in entropy.
|
|
//DP epsilon = 1.0/L; // using Lorentzian for density in entropy.
|
|
|
|
// Construct the finite-size saddle-point state:
|
|
// if we refine, read the quantum numbers of the saddle point state (and seed sps) from the sps file:
|
|
|
|
stringstream SPS_stringstream; string SPS_string;
|
|
//SPS_stringstream << "Tgt0_";
|
|
//Data_File_Name (SPS_stringstream, whichDSF, iKmin, iKmax, kBT, spstate, SeedScanState, "");
|
|
Data_File_Name (SPS_stringstream, whichDSF, c_int, L, N, iKmin, iKmax, kBT, 0.0, "");
|
|
SPS_stringstream << ".sps";
|
|
SPS_string = SPS_stringstream.str(); const char* SPS_Cstr = SPS_string.c_str();
|
|
|
|
fstream spsfile;
|
|
if (refine) spsfile.open(SPS_Cstr, fstream::in);
|
|
else spsfile.open(SPS_Cstr, fstream::out | fstream::trunc);
|
|
if (spsfile.fail()) {
|
|
cout << SPS_Cstr << endl; JSCerror("Could not open spsfile.");
|
|
}
|
|
|
|
LiebLin_Bethe_State spstate;
|
|
|
|
if (!refine) { // obtain the sps from discretized TBA
|
|
spstate = Canonical_Saddle_Point_State (c_int, L, N, whichDSF == 'Z' ? 0.0 : kBT);
|
|
}
|
|
else { // read it from the sps file
|
|
// Check that the sps has the right number of Ix2:
|
|
int Nspsread;
|
|
spsfile >> Nspsread;
|
|
if (Nspsread != N) {
|
|
cout << Nspsread << "\t" << N << endl;
|
|
JSCerror("Wrong number of Ix2 in saddle-point state.");
|
|
}
|
|
spstate = LiebLin_Bethe_State (c_int, L, N);
|
|
for (int i = 0; i < N; ++i) spsfile >> spstate.Ix2[i];
|
|
}
|
|
spstate.Compute_All(true);
|
|
|
|
int Nscan = N;
|
|
if (whichDSF == 'o') Nscan = N - 1;
|
|
if (whichDSF == 'g') Nscan = N + 1;
|
|
|
|
// Now construct or read off the seed scan state:
|
|
|
|
// TO MODIFY: this is not a good idea, since this might construct a state with many p-h w/r to the AveragingState.
|
|
LiebLin_Bethe_State SeedScanState;
|
|
|
|
if (whichDSF != 'o' && whichDSF != 'g') SeedScanState = spstate;
|
|
|
|
else if (whichDSF == 'o' || whichDSF == 'g') {
|
|
if (!refine) {
|
|
//SeedScanState = Canonical_Saddle_Point_State (c_int, L, Nscan, kBT);
|
|
//LiebLin_Bethe_State scanspstate = Canonical_Saddle_Point_State (c_int, L, Nscan, kBT);
|
|
//SeedScanState = scanspstate;
|
|
if (whichDSF == 'o') SeedScanState = Remove_Particle_at_Center (spstate);
|
|
else SeedScanState = Add_Particle_at_Center (spstate);
|
|
}
|
|
else { // read it from the sps file
|
|
// Check that the sps has the right number of Ix2:
|
|
int Nsspsread;
|
|
spsfile >> Nsspsread;
|
|
if (Nsspsread != Nscan) {
|
|
cout << Nsspsread << "\t" << Nscan << endl;
|
|
JSCerror("Wrong number of Ix2 in scan saddle-point state.");
|
|
}
|
|
SeedScanState = LiebLin_Bethe_State (c_int, L, Nscan);
|
|
for (int i = 0; i < Nscan; ++i) spsfile >> SeedScanState.Ix2[i];
|
|
}
|
|
} // if one-body or Green's function
|
|
|
|
SeedScanState.Compute_All(true);
|
|
|
|
LiebLin_Bethe_State ScanState = SeedScanState;
|
|
|
|
DP delta = sqrt(DP(N)) * (spstate.lambdaoc[N-1] - spstate.lambdaoc[0])/N;
|
|
|
|
if (!refine) { // we write data to the sps file
|
|
|
|
spsfile << N << endl;
|
|
spsfile << spstate.Ix2 << endl;
|
|
spsfile << Nscan << endl;
|
|
spsfile << SeedScanState.Ix2 << endl;
|
|
|
|
spsfile << endl << spstate << endl << endl;
|
|
for (int i = 1; i < spstate.N - 2; ++i)
|
|
spsfile << 0.5 * (spstate.lambdaoc[i] + spstate.lambdaoc[i+1])
|
|
//<< "\t" << twoPI/(spstate.L * (spstate.lambdaoc[i+1] - spstate.lambdaoc[i])) << endl;
|
|
<< "\t" << 1.0/spstate.L * (0.25/(spstate.lambdaoc[i] - spstate.lambdaoc[i-1])
|
|
+ 0.5/(spstate.lambdaoc[i+1] - spstate.lambdaoc[i])
|
|
+ 0.25/(spstate.lambdaoc[i+2] - spstate.lambdaoc[i+1]))
|
|
<< "\t" << rho_of_lambdaoc_1 (spstate, 0.5 * (spstate.lambdaoc[i] + spstate.lambdaoc[i+1]), delta)
|
|
<< "\t" << rho_of_lambdaoc_2 (spstate, 0.5 * (spstate.lambdaoc[i] + spstate.lambdaoc[i+1]), delta)
|
|
<< endl;
|
|
}
|
|
spsfile.close();
|
|
|
|
// Perform the scan:
|
|
General_Scan (whichDSF, iKmin, iKmax, 100000000, kBT, spstate, SeedScanState, "", Max_Secs, target_sumrule, refine, paralevel, rank, nr_processors);
|
|
|
|
return;
|
|
}
|
|
|
|
void Scan_LiebLin (char whichDSF, DP c_int, DP L, int N, int iKmin, int iKmax, DP kBT,
|
|
int Max_Secs, DP target_sumrule, bool refine)
|
|
{
|
|
int paralevel = 0;
|
|
Vect<int> rank(0,1);
|
|
Vect<int> nr_processors(0,1);
|
|
|
|
Scan_LiebLin (whichDSF, c_int, L, N, iKmin, iKmax, kBT, Max_Secs, target_sumrule, refine, paralevel, rank, nr_processors);
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
// Scanning on an excited state defined by a set of Ix2:
|
|
void Scan_LiebLin (char whichDSF, LiebLin_Bethe_State AveragingState, string defaultScanStatename, int iKmin, int iKmax,
|
|
int Max_Secs, DP target_sumrule, bool refine, int paralevel, Vect<int> rank, Vect<int> nr_processors)
|
|
{
|
|
// This function is as Scan_LiebLin for generic T defined above, except that the
|
|
// averaging is now done on a state defined by AveragingStateIx2
|
|
|
|
// PRECONDITIONS:
|
|
// - the Ix2 of AveragingState are properly set.
|
|
|
|
DP c_int = AveragingState.c_int;
|
|
DP L = AveragingState.L;
|
|
int N = AveragingState.N;
|
|
|
|
//LiebLin_Bethe_State GroundState (c_int, L, N);
|
|
// Make sure the label of AveragingState is properly set to that relative to GS:
|
|
//AveragingState.Set_Label_from_Ix2 (GroundState.Ix2);
|
|
|
|
// The label of the Averaging State is by definition the `empty' label
|
|
AveragingState.Set_Label_from_Ix2 (AveragingState.Ix2);
|
|
AveragingState.Compute_All(true);
|
|
|
|
int Nscan = N;
|
|
if (whichDSF == 'o') Nscan = N - 1;
|
|
if (whichDSF == 'g') Nscan = N + 1;
|
|
|
|
LiebLin_Bethe_State SeedScanState (c_int, L, Nscan);
|
|
if (whichDSF == 'd' || whichDSF == 'B') SeedScanState.Ix2 = AveragingState.Ix2;
|
|
// If 'o', remove rightmost and shift quantum numbers by half-integer towards center.
|
|
// if (whichDSF == 'o') for (int i = 0; i < N-1; ++i) SeedScanState.Ix2[i] = AveragingState.Ix2[i] + 1;
|
|
// If 'g', add a new particle at the right, after shifting all towards center.
|
|
//if (whichDSF == 'g') {
|
|
//for (int i = 0; i < N; ++i) SeedScanState.Ix2[i] = AveragingState.Ix2[i] - 1;
|
|
//SeedScanState.Ix2[N] = SeedScanState.Ix2[N-1] + 2;
|
|
//}
|
|
// If 'o', remove midmost and shift quantum numbers by half-integer towards removed one:
|
|
|
|
if (whichDSF == 'o') {
|
|
for (int i = 0; i < N-1; ++i)
|
|
SeedScanState.Ix2[i] = AveragingState.Ix2[i + (i >= N/2)] + 1 - 2*(i >= N/2);
|
|
}
|
|
// If 'g', add a quantum number in middle (explicitly: to right of index N/2)
|
|
// and shift quantum numbers by half-integer away from added one:
|
|
if (whichDSF == 'g') {
|
|
SeedScanState.Ix2[N/2] = AveragingState.Ix2[N/2] - 1;
|
|
for (int i = 0; i < N+1; ++i)
|
|
SeedScanState.Ix2[i + (i >= N/2)] = AveragingState.Ix2[i] - 1 + 2*(i >= N/2);
|
|
}
|
|
SeedScanState.Compute_All(true);
|
|
|
|
SeedScanState.Set_Label_from_Ix2 (SeedScanState.Ix2);
|
|
|
|
//cout << "which DSF = " << whichDSF << endl;
|
|
//cout << "AveragingState Ix2: " << endl << AveragingState.Ix2 << endl;
|
|
//cout << "SeedScanState Ix2: " << endl << SeedScanState.Ix2 << endl;
|
|
|
|
DP kBT = 0.0;
|
|
|
|
// Perform the scan:
|
|
General_Scan (whichDSF, iKmin, iKmax, 100000000, kBT, AveragingState, SeedScanState, defaultScanStatename, Max_Secs, target_sumrule, refine, paralevel, rank, nr_processors);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
// Simplified function call of the above:
|
|
void Scan_LiebLin (char whichDSF, LiebLin_Bethe_State AveragingState, string defaultScanStatename, int iKmin, int iKmax,
|
|
int Max_Secs, DP target_sumrule, bool refine)
|
|
{
|
|
int paralevel = 0;
|
|
Vect<int> rank(0,1);
|
|
Vect<int> nr_processors(0,1);
|
|
|
|
Scan_LiebLin (whichDSF, AveragingState, defaultScanStatename, iKmin, iKmax, Max_Secs, target_sumrule, refine, paralevel, rank, nr_processors);
|
|
|
|
return;
|
|
}
|
|
|
|
// Scanning on a previously-defined AveragingState
|
|
void Scan_Heis (char whichDSF, XXZ_Bethe_State& AveragingState, string defaultScanStatename, int iKmin, int iKmax,
|
|
int Max_Secs, DP target_sumrule, bool refine, int paralevel, Vect<int> rank, Vect<int> nr_processors)
|
|
{
|
|
// General state scanning for Heisenberg chains
|
|
|
|
// PRECONDITIONS:
|
|
// - the Ix2 of AveragingState are properly set.
|
|
|
|
// Prepare the AveragingState:
|
|
AveragingState.Compute_All(true);
|
|
|
|
XXZ_Bethe_State SeedScanState;
|
|
if (whichDSF == 'Z' || whichDSF == 'z') SeedScanState = AveragingState;
|
|
else if (whichDSF == 'm') SeedScanState = Remove_Particle_at_Center (AveragingState);
|
|
else if (whichDSF == 'p') SeedScanState = Add_Particle_at_Center (AveragingState);
|
|
else JSCerror("Unknown whichDSF in Scan_Heis.");
|
|
|
|
//cout << "In General_Scan: SeedScanState = " << SeedScanState << endl;
|
|
|
|
// Now the scan itself
|
|
General_Scan (whichDSF, iKmin, iKmax, AveragingState.chain.Nsites, 0.0, AveragingState, SeedScanState, defaultScanStatename, Max_Secs, target_sumrule, refine, paralevel, rank, nr_processors);
|
|
|
|
}
|
|
|
|
// Scanning on a previously-defined AveragingState
|
|
void Scan_Heis (char whichDSF, XXX_Bethe_State& AveragingState, string defaultScanStatename, int iKmin, int iKmax,
|
|
int Max_Secs, DP target_sumrule, bool refine, int paralevel, Vect<int> rank, Vect<int> nr_processors)
|
|
{
|
|
// General state scanning for Heisenberg chains
|
|
|
|
// PRECONDITIONS:
|
|
// - the Ix2 of AveragingState are properly set.
|
|
|
|
// Prepare the AveragingState:
|
|
AveragingState.Compute_All(true);
|
|
|
|
XXX_Bethe_State SeedScanState;
|
|
if (whichDSF == 'Z' || whichDSF == 'z') SeedScanState = AveragingState;
|
|
else if (whichDSF == 'm') SeedScanState = Remove_Particle_at_Center (AveragingState);
|
|
else if (whichDSF == 'p') SeedScanState = Add_Particle_at_Center (AveragingState);
|
|
else JSCerror("Unknown whichDSF in Scan_Heis.");
|
|
|
|
// Now the scan itself
|
|
General_Scan (whichDSF, iKmin, iKmax, AveragingState.chain.Nsites, 0.0, AveragingState, SeedScanState, defaultScanStatename, Max_Secs, target_sumrule, refine, paralevel, rank, nr_processors);
|
|
|
|
}
|
|
|
|
// Scanning on a previously-defined AveragingState
|
|
void Scan_Heis (char whichDSF, XXZ_gpd_Bethe_State& AveragingState, string defaultScanStatename, int iKmin, int iKmax,
|
|
int Max_Secs, DP target_sumrule, bool refine, int paralevel, Vect<int> rank, Vect<int> nr_processors)
|
|
{
|
|
// General state scanning for Heisenberg chains
|
|
|
|
// PRECONDITIONS:
|
|
// - the Ix2 of AveragingState are properly set.
|
|
|
|
// Prepare the AveragingState:
|
|
AveragingState.Compute_All(true);
|
|
|
|
XXZ_gpd_Bethe_State SeedScanState;
|
|
if (whichDSF == 'Z' || whichDSF == 'z') SeedScanState = AveragingState;
|
|
else if (whichDSF == 'm') SeedScanState = Remove_Particle_at_Center (AveragingState);
|
|
else if (whichDSF == 'p') SeedScanState = Add_Particle_at_Center (AveragingState);
|
|
else JSCerror("Unknown whichDSF in Scan_Heis.");
|
|
|
|
// Now the scan itself
|
|
General_Scan (whichDSF, iKmin, iKmax, AveragingState.chain.Nsites, 0.0, AveragingState, SeedScanState, defaultScanStatename, Max_Secs, target_sumrule, refine, paralevel, rank, nr_processors);
|
|
|
|
}
|
|
|
|
|
|
//void Scan_Heis (char whichDSF, DP Delta, DP N, int M, bool fixed_iK, int iKneeded,
|
|
void Scan_Heis (char whichDSF, DP Delta, int N, int M, int iKmin, int iKmax,
|
|
int Max_Secs, DP target_sumrule, bool refine, int paralevel, Vect<int> rank, Vect<int> nr_processors)
|
|
{
|
|
// This function scans the Hilbert space of the Heisenberg spin-1/2 chain
|
|
// for the function identified by whichDSF.
|
|
|
|
// whichDSF == 'Z': canonical partition function
|
|
// whichDSF == 'm': S^{-+}
|
|
// whichDSF == 'z': S^{zz}
|
|
// whichDSF == 'p': S^{+-}
|
|
// whichDSF == 'a': < S^z_j S^z_{j+1} S^z_l S^z_{l+1} > for RIXS
|
|
// whichDSF == 'b': < S^z_j S^-_{j+1} S^-_l S^z_{l+1} > + (m <-> z) for RIXS
|
|
// whichDSF == 'c': < S^-_j S^-_{j+1} S^-_l S^-_{l+1} > for RIXS
|
|
|
|
Heis_Chain BD1(1.0, Delta, 0.0, N);
|
|
|
|
Vect_INT Nrapidities_groundstate(0, BD1.Nstrings);
|
|
|
|
Nrapidities_groundstate[0] = M;
|
|
|
|
Heis_Base baseconfig_groundstate(BD1, Nrapidities_groundstate);
|
|
|
|
|
|
if ((Delta > 0.0) && (Delta < 1.0)) {
|
|
|
|
XXZ_Bethe_State GroundState(BD1, baseconfig_groundstate);
|
|
GroundState.Compute_All(true);
|
|
// The ground state is now fully defined.
|
|
|
|
XXZ_Bethe_State SeedScanState;
|
|
if (whichDSF == 'Z' || whichDSF == 'z') SeedScanState = GroundState;
|
|
else if (whichDSF == 'm') SeedScanState = XXZ_Bethe_State(GroundState.chain, M - 1);
|
|
else if (whichDSF == 'p') SeedScanState = XXZ_Bethe_State(GroundState.chain, M + 1);
|
|
else JSCerror("Unknown whichDSF in Scan_Heis.");
|
|
|
|
// Now the scan itself
|
|
General_Scan (whichDSF, iKmin, iKmax, N, 0.0, GroundState, SeedScanState, "", Max_Secs, target_sumrule, refine, paralevel, rank, nr_processors);
|
|
|
|
}
|
|
|
|
else if (Delta == 1.0) {
|
|
|
|
XXX_Bethe_State GroundState(BD1, baseconfig_groundstate);
|
|
GroundState.Compute_All(true);
|
|
// The ground state is now fully defined.
|
|
|
|
XXX_Bethe_State SeedScanState;
|
|
if (whichDSF == 'Z' || whichDSF == 'z' || whichDSF == 'a' || whichDSF == 'q') SeedScanState = GroundState;
|
|
else if (whichDSF == 'm') SeedScanState = XXX_Bethe_State(GroundState.chain, M - 1);
|
|
else if (whichDSF == 'p') SeedScanState = XXX_Bethe_State(GroundState.chain, M + 1);
|
|
else if (whichDSF == 'c') SeedScanState = XXX_Bethe_State(GroundState.chain, M - 2);
|
|
else JSCerror("Unknown whichDSF in Scan_Heis.");
|
|
|
|
// Now the scan itself
|
|
General_Scan (whichDSF, iKmin, iKmax, N, 0.0, GroundState, SeedScanState, "", Max_Secs, target_sumrule, refine, paralevel, rank, nr_processors);
|
|
}
|
|
|
|
else if (Delta > 1.0) {
|
|
|
|
XXZ_gpd_Bethe_State GroundState(BD1, baseconfig_groundstate);
|
|
GroundState.Compute_All(true);
|
|
// The ground state is now fully defined.
|
|
|
|
XXZ_gpd_Bethe_State SeedScanState;
|
|
if (whichDSF == 'Z' || whichDSF == 'z') SeedScanState = GroundState;
|
|
else if (whichDSF == 'm') SeedScanState = XXZ_gpd_Bethe_State(GroundState.chain, M - 1);
|
|
else if (whichDSF == 'p') SeedScanState = XXZ_gpd_Bethe_State(GroundState.chain, M + 1);
|
|
else JSCerror("Unknown whichDSF in Scan_Heis.");
|
|
|
|
// Now the scan itself
|
|
General_Scan (whichDSF, iKmin, iKmax, N, 0.0, GroundState, SeedScanState, "", Max_Secs, target_sumrule, refine, paralevel, rank, nr_processors);
|
|
}
|
|
|
|
else JSCerror("Delta out of range in Heis_Structure_Factor");
|
|
|
|
return;
|
|
}
|
|
|
|
void Scan_Heis (char whichDSF, DP Delta, int N, int M, int iKmin, int iKmax,
|
|
int Max_Secs, DP target_sumrule, bool refine)
|
|
{
|
|
int paralevel = 0;
|
|
Vect<int> rank(0,1);
|
|
Vect<int> nr_processors(0,1);
|
|
|
|
Scan_Heis (whichDSF, Delta, N, M, iKmin, iKmax, Max_Secs, target_sumrule, refine, paralevel, rank, nr_processors);
|
|
|
|
return;
|
|
}
|
|
|
|
/*
|
|
// Simplified calls:
|
|
|
|
void Scan_Heis (char whichDSF, DP Delta, int N, int M, int iKmin, int iKmax, int Max_Secs, bool refine)
|
|
{
|
|
//Scan_Heis (whichDSF, Delta, N, M, false, 0, Max_Secs, refine, 0, 1);
|
|
Scan_Heis (whichDSF, Delta, N, M, iKmin, iKmax, Max_Secs, 1.0e+6, refine, 0, 1);
|
|
}
|
|
|
|
void Scan_Heis (char whichDSF, DP Delta, int N, int M, int iKneeded, int Max_Secs, bool refine)
|
|
{
|
|
//Scan_Heis (whichDSF, Delta, N, M, true, iKneeded, Max_Secs, refine, 0, 1);
|
|
Scan_Heis (whichDSF, Delta, N, M, iKneeded, iKneeded, Max_Secs, 1.0e+6, refine, 0, 1);
|
|
}
|
|
|
|
void Scan_Heis (char whichDSF, DP Delta, int N, int M, int Max_Secs, bool refine)
|
|
{
|
|
//Scan_Heis (whichDSF, Delta, N, M, false, 0, Max_Secs, refine, 0, 1);
|
|
Scan_Heis (whichDSF, Delta, N, M, 0, N, Max_Secs, 1.0e+6, refine, 0, 1);
|
|
}
|
|
*/
|
|
/*
|
|
void Scan_ODSLF (char whichDSF, DP Delta, int N, int M, int iKmin, int iKmax,
|
|
int Max_Secs, DP target_sumrule, bool refine, int rank, int nr_processors)
|
|
{
|
|
// This function scans the Hilbert space of the spinless fermions related to Heisenberg spin-1/2 chain
|
|
// for the function identified by whichDSF.
|
|
|
|
// whichDSF == 'Z': canonical partition function
|
|
// whichDSF == 'm': S^{-+}
|
|
// whichDSF == 'z': S^{zz}
|
|
// whichDSF == 'p': S^{+-}
|
|
// whichDSF == 'a': < S^z_j S^_{j+1} S^z_l S^z_{l+1} > for RIXS
|
|
|
|
Heis_Chain BD1(1.0, Delta, 0.0, N);
|
|
|
|
Vect_INT Nrapidities_groundstate(0, BD1.Nstrings);
|
|
|
|
Nrapidities_groundstate[0] = M;
|
|
|
|
ODSLF_Base baseconfig_groundstate(BD1, Nrapidities_groundstate);
|
|
|
|
ODSLF_Ix2_Offsets baseoffsets(baseconfig_groundstate, 0ULL);
|
|
|
|
if ((Delta > 0.0) && (Delta < 1.0)) {
|
|
|
|
ODSLF_XXZ_Bethe_State GroundState(BD1, baseconfig_groundstate);
|
|
GroundState.Compute_All(true);
|
|
|
|
// The ground state is now fully defined. Now the scan itself
|
|
//General_Scan (whichDSF, fixed_iK, iKneeded, N, GroundState, GroundState, Max_Secs, refine, rank, nr_processors);
|
|
General_Scan (whichDSF, iKmin, iKmax, N, 0.0, GroundState, GroundState, Max_Secs, target_sumrule, refine, rank, nr_processors);
|
|
|
|
}
|
|
*/
|
|
/*
|
|
else if (Delta == 1.0) {
|
|
|
|
XXX_Bethe_State GroundState(BD1, baseconfig_groundstate);
|
|
GroundState.Compute_All(true);
|
|
|
|
// The ground state is now fully defined. Now the scan itself
|
|
//General_Scan (whichDSF, fixed_iK, iKneeded, N, GroundState, GroundState, Max_Secs, refine, rank, nr_processors);
|
|
General_Scan (whichDSF, iKmin, iKmax, N, GroundState, GroundState, Max_Secs, refine, rank, nr_processors);
|
|
}
|
|
|
|
else if (Delta > 1.0) {
|
|
|
|
XXZ_gpd_Bethe_State GroundState(BD1, baseconfig_groundstate);
|
|
GroundState.Compute_All(true);
|
|
|
|
// The ground state is now fully defined. Now the scan itself
|
|
//General_Scan (whichDSF, fixed_iK, iKneeded, N, GroundState, GroundState, Max_Secs, refine, rank, nr_processors);
|
|
General_Scan (whichDSF, iKmin, iKmax, N, GroundState, GroundState, Max_Secs, refine, rank, nr_processors);
|
|
}
|
|
*/
|
|
/*
|
|
else JSCerror("Delta out of range in ODSLF Structure Factor");
|
|
|
|
return;
|
|
}
|
|
|
|
// Simplified calls:
|
|
|
|
void Scan_ODSLF (char whichDSF, DP Delta, int N, int M, int iKmin, int iKmax, int Max_Secs, bool refine)
|
|
{
|
|
//Scan_Heis (whichDSF, Delta, N, M, false, 0, Max_Secs, refine, 0, 1);
|
|
Scan_ODSLF (whichDSF, Delta, N, M, iKmin, iKmax, Max_Secs, 1.0e+6, refine, 0, 1);
|
|
}
|
|
|
|
void Scan_ODSLF (char whichDSF, DP Delta, int N, int M, int iKneeded, int Max_Secs, bool refine)
|
|
{
|
|
//Scan_Heis (whichDSF, Delta, N, M, true, iKneeded, Max_Secs, refine, 0, 1);
|
|
Scan_ODSLF (whichDSF, Delta, N, M, iKneeded, iKneeded, Max_Secs, 1.0e+6, refine, 0, 1);
|
|
}
|
|
|
|
void Scan_ODSLF (char whichDSF, DP Delta, int N, int M, int Max_Secs, bool refine)
|
|
{
|
|
//Scan_Heis (whichDSF, Delta, N, M, false, 0, Max_Secs, refine, 0, 1);
|
|
Scan_ODSLF (whichDSF, Delta, N, M, 0, N, Max_Secs, 1.0e+6, refine, 0, 1);
|
|
}
|
|
|
|
|
|
|
|
// Geometric quenches
|
|
|
|
void Scan_LiebLin_Geometric_Quench (DP c_int, DP L_1, int type_id_1, long long int id_1, DP L_2, int N, int iK_UL,
|
|
int Max_Secs, DP target_sumrule, bool refine)
|
|
{
|
|
// We decompose the wavefunction of state 1 (living on length L_1) into
|
|
// the wavefunctions living on length L_2.
|
|
|
|
// IMPORTANT ASSUMPTIONS:
|
|
|
|
LiebLin_Bethe_State lstate(c_int, L_1, N, iK_UL, type_id_1);
|
|
lstate.Set_to_id(id_1);
|
|
lstate.Compute_All(true);
|
|
|
|
// We now put the rapidities and norm into a state in length L_2,
|
|
// which will serve as basis for the scan.
|
|
|
|
LiebLin_Bethe_State lstate2(c_int, L_2, N, iK_UL, type_id_1);
|
|
lstate2.Set_to_id (0LL);
|
|
lstate2.Compute_All(true);
|
|
|
|
char whichDSF = 'q';
|
|
|
|
//General_Scan (whichDSF, false, 0, 100000000, lstate, lstate2, Max_Secs, refine, 0, 1);
|
|
General_Scan (whichDSF, -iK_UL, iK_UL, 100000000, 0.0, lstate, lstate2, Max_Secs, target_sumrule, refine, 0, 1);
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
void Scan_Heis_Geometric_Quench (DP Delta, int N_1, int M, long long int base_id_1, long long int type_id_1, long long int id_1,
|
|
int N_2, int iKmin, int iKmax, int Max_Secs, DP target_sumrule, bool refine)
|
|
{
|
|
// We decompose the wavefunction of state 1 (living on length L_1) into
|
|
// the wavefunctions living on length L_2.
|
|
|
|
Heis_Chain BD_1(1.0, Delta, 0.0, N_1);
|
|
Heis_Chain BD_2(1.0, Delta, 0.0, N_2);
|
|
|
|
|
|
if ((Delta > 0.0) && (Delta < 1.0)) {
|
|
JSCerror("Geometric quench not yet implemented for XXZ.");
|
|
}
|
|
|
|
else if (Delta == 1.0) {
|
|
|
|
XXX_Bethe_State BasicState_1(BD_1, base_id_1, type_id_1);
|
|
BasicState_1.Set_to_id (id_1);
|
|
BasicState_1.Compute_All(true);
|
|
|
|
// Ref state for scanning:
|
|
XXX_Bethe_State BasicState_2(BD_2, M);
|
|
BasicState_2.Set_to_id (0LL);
|
|
BasicState_2.Compute_All(true);
|
|
|
|
char whichDSF = 'q';
|
|
|
|
// The ground state is now fully defined. Now the scan itself
|
|
//General_Scan (whichDSF, fixed_iK, iKneeded, N, GroundState, GroundState, Max_Secs, refine, rank, nr_processors);
|
|
General_Scan (whichDSF, iKmin, iKmax, N_2, 0.0, BasicState_1, BasicState_2, Max_Secs, target_sumrule, refine, 0, 1);
|
|
}
|
|
|
|
else if (Delta > 1.0) {
|
|
JSCerror("Geometric quench not yet implemented for XXZ_gpd.");
|
|
}
|
|
|
|
else JSCerror("Delta out of range in Heis_Structure_Factor");
|
|
|
|
return;
|
|
}
|
|
*/
|
|
|
|
} // namespace JSC
|