/********************************************************** This software is part of J.-S. Caux's ABACUS library. Copyright (c) J.-S. Caux. ----------------------------------------------------------- File: ABACUS_Scan.h Purpose: Declares all classes and functions used in the ABACUS logic of scanning with threads. ***********************************************************/ #ifndef ABACUS_SCAN_H #define ABACUS_SCAN_H #include "ABACUS.h" namespace ABACUS { const int MAX_STATE_LIST_SIZE = 10000; // Functions in src/UTILS/Data_File_Name.cc: void Data_File_Name (std::stringstream& name, char whichDSF, DP c_int, DP L, int N, int iKmin, int iKmax, DP kBT, DP L2, std::string defaultname); void Data_File_Name (std::stringstream& name, char whichDSF, int iKmin, int iKmax, DP kBT, LiebLin_Bethe_State& State, LiebLin_Bethe_State& RefScanState, std::string defaultname); void Data_File_Name (std::stringstream& name, char whichDSF, DP Delta, int N, int M, int iKmin, int iKmax, DP kBT, int N2, std::string defaultname); void Data_File_Name (std::stringstream& name, char whichDSF, int iKmin, int iKmax, DP kBT, Heis_Bethe_State& State, Heis_Bethe_State& RefScanState, std::string defaultname); void ODSLF_Data_File_Name (std::stringstream& name, char whichDSF, DP Delta, int N, int M, int iKmin, int iKmax, DP kBT, int N2, std::string defaultname); void Data_File_Name (std::stringstream& name, char whichDSF, int iKmin, int iKmax, DP kBT, ODSLF_Bethe_State& State, ODSLF_Bethe_State& RefScanState, std::string defaultname); // Coding to convert ints to strings: for application in reduced labels //const int ABACUScodingsize = 64; // use a multiple of 2 to accelerate divisions in labeling. //const char ABACUScoding[] = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '!', '?'}; // From ABACUS++T_8 onwards: forbid special characters as |, :, !, ? and all capital letters in labels. // This is due to the dumb capitalization-preserving but capitalization-insensitive HFS+ filesystem on Mac OS X. const int ABACUScodingsize = 32; const char ABACUScoding[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v'}; const char LABELSEP = '_'; // was _ const char TYPESEP = 'x'; // was | const char EXCSEP = 'y'; // was : const char INEXCSEP = 'z'; // was @ struct State_Label_Data { Vect type; // integer type labels of the types present Vect M; // how many particles of each type Vect nexc; // how many excitations as compared to the reference state used Vect > Ix2old; // which Ix2 will be excited Vect > Ix2exc; // which Ix2 the excitation has shifted to State_Label_Data (const Vect& type_ref, const Vect& M_ref, const Vect& nexc_ref, const Vect >& Ix2old_ref, const Vect >& Ix2exc_ref) { type = type_ref; M = M_ref; nexc = nexc_ref; Ix2old = Ix2old_ref; Ix2exc = Ix2exc_ref; } }; std::string Extract_Base_Label (std::string label); // works for labels and complabels std::string Extract_nexc_Label (std::string label); // For compressed labels: conversions between integers and char/strings. std::string Convert_POSINT_to_STR (int int_to_convert); int Convert_CHAR_to_POSINT (char char_to_convert); int Convert_STR_to_POSINT (std::string str_to_convert); State_Label_Data Read_Base_Label (std::string label); State_Label_Data Read_State_Label (std::string label, const Vect >& OriginIx2); State_Label_Data Read_State_Label (std::string label, const Vect& OriginIx2); // if there is only one type std::string Return_State_Label (State_Label_Data data, const Vect >& OriginIx2); std::string Return_State_Label (State_Label_Data data, const Vect& OriginIx2); // if there is only one type std::string Return_State_Label (const Vect >& ScanIx2, const Vect >& OriginIx2); std::string Return_State_Label (const Vect& ScanIx2, const Vect& OriginIx2); // if there is only one type Vect > Return_Ix2_from_Label (std::string label_ref, const Vect >& OriginIx2); Vect Return_Ix2_from_Label (std::string label_ref, const Vect& OriginIx2); // specialization to Lieb-Liniger // Functions for descending states: in SCAN/Descendents.cc Vect Descendent_States_with_iK_Stepped_Up (std::string ScanIx2_label, const LiebLin_Bethe_State& OriginState, bool disperse_only_current_exc, bool preserve_nexc); Vect Descendent_States_with_iK_Stepped_Down (std::string ScanIx2_label, const LiebLin_Bethe_State& OriginState, bool disperse_only_current_exc, bool preserve_nexc); Vect Descendent_States_with_iK_Preserved (std::string ScanIx2_label, const LiebLin_Bethe_State& OriginState, bool disperse_only_current_exc_up, bool preserve_nexc_up, bool disperse_only_current_exc_down, bool preserve_nexc_down); Vect Descendent_States_with_iK_Stepped_Up (std::string ScanIx2_label, const Heis_Bethe_State& OriginState, bool disperse_only_current_exc, bool preserve_nexc); Vect Descendent_States_with_iK_Stepped_Down (std::string ScanIx2_label, const Heis_Bethe_State& OriginState, bool disperse_only_current_exc, bool preserve_nexc); Vect Descendent_States_with_iK_Preserved (std::string ScanIx2_label, const Heis_Bethe_State& OriginState, bool disperse_only_current_exc_up, bool preserve_nexc_up, bool disperse_only_current_exc_down, bool preserve_nexc_down); // For symmetric state scanning: Vect Descendent_States_with_iK_Stepped_Up_rightIx2only (std::string ScanIx2_label, const LiebLin_Bethe_State& OriginState, bool disperse_only_current_exc, bool preserve_nexc); Vect Descendent_States_with_iK_Stepped_Down_rightIx2only (std::string ScanIx2_label, const LiebLin_Bethe_State& OriginState, bool disperse_only_current_exc, bool preserve_nexc); Vect Descendent_States_with_iK_Stepped_Up_rightIx2only (std::string ScanIx2_label, const Heis_Bethe_State& OriginState, bool disperse_only_current_exc, bool preserve_nexc); Vect Descendent_States_with_iK_Stepped_Down_rightIx2only (std::string ScanIx2_label, const Heis_Bethe_State& OriginState, bool disperse_only_current_exc, bool preserve_nexc); // Functions to prepare and wrapup parallel scans: void Prepare_Parallel_Scan_LiebLin (char whichDSF, DP c_int, DP L, int N, int iKmin, int iKmax, DP kBT, std::string defaultname, int paralevel, Vect rank_lower_paralevels, Vect nr_processors_lower_paralevels, int nr_processors_at_newlevel); void Wrapup_Parallel_Scan_LiebLin (char whichDSF, DP c_int, DP L, int N, int iKmin, int iKmax, DP kBT, std::string defaultname, int paralevel, Vect rank_lower_paralevels, Vect nr_processors_lower_paralevels, int nr_processors_at_newlevel); void Prepare_Parallel_Scan_Heis (char whichDSF, DP Delta, int N, int M, int iKmin, int iKmax, int paralevel, Vect rank_lower_paralevels, Vect nr_processors_lower_paralevels, int nr_processors_at_newlevel); void Wrapup_Parallel_Scan_Heis (char whichDSF, DP Delta, int N, int M, int iKmin, int iKmax, int paralevel, Vect rank_lower_paralevels, Vect nr_processors_lower_paralevels, int nr_processors_at_newlevel); void Filter_RAW_File_for_iK (const char ff_file[], int iKneeded); void Sort_RAW_File (const char ffsq_file[], char optionchar); void Sort_RAW_File (const char ffsq_file[], char optionchar, char whichDSF); // Functions for data interpretation: DP Smoothen_RAW_into_SF (std::string prefix, int iKmin, int iKmax, int DiK, DP devmax, DP ommin, DP ommax, int Nom, DP gwidth, DP normalization, DP denom_sum_K); DP Smoothen_RAW_into_SF (std::string prefix, Vect rawfilename, Vect weight, int iKmin, int iKmax, int DiK, DP devmax, DP ommin, DP ommax, int Nom, DP gwidth, DP normalization, DP denom_sum_K); void Write_K_File (DP Length, int iKmin, int iKmax); void Write_Omega_File (int Nout_omega, DP omegamin, DP omegamax); void Write_Time_File (int Nt, DP tmin, DP tmax); // Smoothen with gaussian width scaled with two-particle bandwidth DP Smoothen_RAW_into_SF_LiebLin_Scaled (std::string prefix, DP L, int N, int iKmin, int iKmax, int DiK, DP ommin, DP ommax, int Nom, DP width, DP normalization); //**************************************************************************** struct Scan_Info { DP sumrule_obtained; DP Nfull; // dimensionality of (sub)Hilbert space considered long long int Ninadm; long long int Ndata; long long int Ndata_conv; long long int Ndata_conv0; double TT; // total computation time in seconds public: Scan_Info(); // constructor, puts everything to zero Scan_Info (DP sr, DP Nf, long long int Ni, long long int Nd, long long int Ndc, long long int Ndc0, double t); void Save (const char* outfile_Cstr); void Load (const char* infile_Cstr); inline Scan_Info& operator = (const Scan_Info& ref_info) { sumrule_obtained = ref_info.sumrule_obtained; Nfull = ref_info.Nfull; Ninadm = ref_info.Ninadm; Ndata = ref_info.Ndata; Ndata_conv = ref_info.Ndata_conv; Ndata_conv0 = ref_info.Ndata_conv0; TT = ref_info.TT; return(*this); } inline Scan_Info& operator+= (const Scan_Info& ref_info) { if (this != &ref_info) { sumrule_obtained += ref_info.sumrule_obtained; Nfull += ref_info.Nfull; Ninadm += ref_info.Ninadm; Ndata += ref_info.Ndata; Ndata_conv += ref_info.Ndata_conv; Ndata_conv0 += ref_info.Ndata_conv0; TT += ref_info.TT; } return(*this); } inline Scan_Info& operator-= (const Scan_Info& ref_info) { if (this != &ref_info) { sumrule_obtained -= ref_info.sumrule_obtained; Nfull -= ref_info.Nfull; Ninadm -= ref_info.Ninadm; Ndata -= ref_info.Ndata; Ndata_conv -= ref_info.Ndata_conv; Ndata_conv0 -= ref_info.Ndata_conv0; TT -= ref_info.TT; } return(*this); } }; std::ostream& operator<< (std::ostream& s, const Scan_Info& info); // Functions in src/SCAN/General_Scan.cc: template Scan_Info General_Scan (char whichDSF, int iKmin, int iKmax, int iKmod, DP kBT, Tstate& AveragingState, Tstate& SeedScanState, std::string defaultScanStatename, int Max_Secs, DP target_sumrule, bool refine, int paralevel, Vect rank, Vect nr_processors); Scan_Info 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 rank, Vect nr_processors); Scan_Info 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); Scan_Info Scan_LiebLin (char whichDSF, LiebLin_Bethe_State AveragingState, std::string defaultScanStatename, int iKmin, int iKmax, int Max_Secs, DP target_sumrule, bool refine, int paralevel, Vect rank, Vect nr_processors); Scan_Info Scan_LiebLin (char whichDSF, LiebLin_Bethe_State AveragingState, std::string defaultname, int iKmin, int iKmax, int Max_Secs, DP target_sumrule, bool refine); Scan_Info 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); Scan_Info 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 rank, Vect nr_processors); Scan_Info Scan_Heis (char whichDSF, DP Delta, int N, int M, int iKmin, int iKmax, int Max_Secs, DP target_sumrule, bool refine); Scan_Info Scan_Heis (char whichDSF, XXZ_Bethe_State& AveragingState, std::string defaultScanStatename, int iKmin, int iKmax, int Max_Secs, DP target_sumrule, bool refine, int paralevel, Vect rank, Vect nr_processors); Scan_Info Scan_Heis (char whichDSF, XXX_Bethe_State& AveragingState, std::string defaultScanStatename, int iKmin, int iKmax, int Max_Secs, DP target_sumrule, bool refine, int paralevel, Vect rank, Vect nr_processors); Scan_Info Scan_Heis (char whichDSF, XXZ_gpd_Bethe_State& AveragingState, std::string defaultScanStatename, int iKmin, int iKmax, int Max_Secs, DP target_sumrule, bool refine, int paralevel, Vect rank, Vect nr_processors); Scan_Info 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); Scan_Info Scan_ODSLF (char whichDSF, DP Delta, int N, int M, int iKmin, int iKmax, int Max_Secs, bool refine); Scan_Info Scan_ODSLF (char whichDSF, DP Delta, int N, int M, int iKneeded, int Max_Secs, bool refine); Scan_Info Scan_ODSLF (char whichDSF, DP Delta, int N, int M, int Max_Secs, bool refine); //**************************************************************************** // Functions in src/SCAN/Descendents.cc: Vect Descendents (const LiebLin_Bethe_State& ScanState, const LiebLin_Bethe_State& OriginState, int type_required); Vect Descendents (const Heis_Bethe_State& ScanState, const Heis_Bethe_State& OriginState, int type_required); struct Scan_Thread { std::string label; int type; Scan_Thread (); Scan_Thread (std::string label_ref, int type_ref) { label = label_ref; type = type_ref; } Scan_Thread& operator= (const Scan_Thread& RefThread); }; struct Scan_Thread_Data { // By convention, a Scan_Thread_Data object handles a list of threads which are yet to be descended. // Improvement on Scan_Thread_Set used up to ABACUS++G_7, saving data to disk instead of holding it in memory. int nlists = 6400; // number of threads lists, fixed to this number by convention. DP logscale = (1.0/64) * log(2.0); // each separate list contains threads differing by a scale factor of 2^{1/64} \approx 1.01. std::string thrdir_name; // directory in which threads files are saved. Vect nthreads_total; Vect nthreads_on_disk; int lowest_il_with_nthreads_neq_0; // In-memory storage, for adding threads efficiently without constantly writing to disk // These objects are saved to disk when Next_Scan_Threads are called. Vect dim; Vect nthreads_in_memory; Vect > label; Vect > type; // which type of descendent is needed Vect filename; Scan_Thread_Data (); Scan_Thread_Data (std::string thrdir_name_ref, bool refine); ~Scan_Thread_Data (); bool Increase_Memory_Size (int il, int nr_to_add); void Include_Thread (DP abs_data_value_ref, std::string label_ref, int type_ref); void Include_Thread (int il, std::string label_ref, int type_ref); Vect Extract_Next_Scan_Threads (); // returns a vector of the threads that are next in line. By defn, all threads with index il == lowest_il_with_nthreads_neq_0. These are removed from the object. Vect Extract_Next_Scan_Threads (int min_nr); // as above, but returns a minimum of min_nr threads. void Flush_to_Disk (int il); void Save (); void Load (); }; //**************************************************************************** // To populate a list of states for scanning: inline void Scan_for_Possible_Bases (const Vect SeedNrap, const Vect Str_L, int Mdown_remaining, Vect& possible_base_label, int& nfound, int nexc_max_used, int base_level_to_scan, Vect& Nrapidities) { if (Mdown_remaining < 0) { ABACUSerror("Scan_for_Possible_Bases: shouldn't be here..."); } // reached inconsistent point if (base_level_to_scan == 0) { if (Str_L[0] != 1) ABACUSerror("Str_L[0] != 1 in ABACUS_Scan.h Scan_for_Possible_Bases."); Nrapidities[0] = Mdown_remaining; // Set label: std::stringstream M0out; M0out << Nrapidities[0]; possible_base_label[nfound] = M0out.str(); for (int itype = 1; itype < Nrapidities.size(); ++itype) if (Nrapidities[itype] > 0) { possible_base_label[nfound] += TYPESEP; std::stringstream typeout; typeout << itype; possible_base_label[nfound] += typeout.str(); possible_base_label[nfound] += EXCSEP; std::stringstream Mout; Mout << Nrapidities[itype]; possible_base_label[nfound] += Mout.str(); } nfound++; } else { // Preserve the number of strings at this level as compared to SeedState: Nrapidities[base_level_to_scan] = SeedNrap[base_level_to_scan]; if (Mdown_remaining - Str_L[base_level_to_scan] * Nrapidities[base_level_to_scan] >= 0) Scan_for_Possible_Bases (SeedNrap, Str_L, Mdown_remaining - Str_L[base_level_to_scan] * Nrapidities[base_level_to_scan], possible_base_label, nfound, nexc_max_used, base_level_to_scan - 1, Nrapidities); // Reduce number of strings at this level as compared to SeedState: for (int i = 1; i <= ABACUS::min(SeedNrap[base_level_to_scan], nexc_max_used/Str_L[base_level_to_scan]); ++i) { Nrapidities[base_level_to_scan] = SeedNrap[base_level_to_scan] - i; if (Mdown_remaining - Str_L[base_level_to_scan] * Nrapidities[base_level_to_scan] >= 0) Scan_for_Possible_Bases (SeedNrap, Str_L, Mdown_remaining - Str_L[base_level_to_scan] * Nrapidities[base_level_to_scan], possible_base_label, nfound, nexc_max_used - i*Str_L[base_level_to_scan], base_level_to_scan - 1, Nrapidities); } // Increase the number of strings at this level as compared to SeedState: for (int i = 1; i <= ABACUS::min(Mdown_remaining/Str_L[base_level_to_scan], nexc_max_used/Str_L[base_level_to_scan]); ++i) { Nrapidities[base_level_to_scan] = SeedNrap[base_level_to_scan] + i; if (Mdown_remaining - Str_L[base_level_to_scan] * Nrapidities[base_level_to_scan] >= 0) Scan_for_Possible_Bases (SeedNrap, Str_L, Mdown_remaining - Str_L[base_level_to_scan] * Nrapidities[base_level_to_scan], possible_base_label, nfound, nexc_max_used - i*Str_L[base_level_to_scan], base_level_to_scan - 1, Nrapidities); } } } inline Vect Possible_Bases (const Vect SeedNrap, const Vect Str_L, int Mdown)//const Heis_Bethe_State& SeedState) { int nexc_max_used = NEXC_MAX_HEIS; Vect possible_base_label (1000); int nfound = 0; Vect Nrapidities = SeedNrap; int Mdown_remaining = Mdown; Scan_for_Possible_Bases (SeedNrap, Str_L, Mdown_remaining, possible_base_label, nfound, nexc_max_used, SeedNrap.size() - 1, Nrapidities); // Copy results into a clean vector: Vect possible_base_label_found (nfound); for (int i = 0; i < nfound; ++i) possible_base_label_found[i] = possible_base_label[i]; return(possible_base_label_found); } //**************************************************************************** template class Scan_State_List { public: int ndef; Vect State; Vect base_label; Vect info; // info for base and type of State[n] Vect flag_for_scan; // set to true, next round of scanning will use this base/type Vect scan_attempted; // whether this has already been attempted public: inline Scan_State_List (char whichDSF, const Tstate& SeedScanState); public: inline Tstate& Return_State (std::string base_label_ref); // returns a state corresponding to same base and type inline void Populate_List (char whichDSF, const Tstate& SeedScanState); // creates all types of states containing up to nexc_max excitations inline void Include_Info (Scan_Info& info_to_add, std::string base_label_ref); inline void Raise_Scanning_Flags (DP threshold); // checks whether base/type should be scanned based on simpler base/type combinations inline void Order_in_SRC (); inline void Save_Info (const char* sumfile_Cstr); inline void Load_Info (const char* sumfile_Cstr); }; // Do the explicit class specializations: template<> inline Scan_State_List::Scan_State_List (char whichDSF, const LiebLin_Bethe_State& SeedScanState) : ndef(0), State(Vect(MAX_STATE_LIST_SIZE)), base_label(Vect(MAX_STATE_LIST_SIZE)), info(Vect(MAX_STATE_LIST_SIZE)), flag_for_scan(Vect(false, MAX_STATE_LIST_SIZE)), scan_attempted(Vect(false, MAX_STATE_LIST_SIZE)) { State[0] = SeedScanState; } template<> inline Scan_State_List::Scan_State_List (char whichDSF, const XXZ_Bethe_State& SeedScanState) : ndef(0), State(Vect(MAX_STATE_LIST_SIZE)), base_label(Vect(MAX_STATE_LIST_SIZE)), info(Vect(MAX_STATE_LIST_SIZE)), flag_for_scan(Vect(false, MAX_STATE_LIST_SIZE)), scan_attempted(Vect(false, MAX_STATE_LIST_SIZE)) { State[0] = SeedScanState; } template<> inline Scan_State_List::Scan_State_List (char whichDSF, const XXX_Bethe_State& SeedScanState) : ndef(0), State(Vect(MAX_STATE_LIST_SIZE)), base_label(Vect(MAX_STATE_LIST_SIZE)), info(Vect(MAX_STATE_LIST_SIZE)), flag_for_scan(Vect(false, MAX_STATE_LIST_SIZE)), scan_attempted(Vect(false, MAX_STATE_LIST_SIZE)) { State[0] = SeedScanState; } template<> inline Scan_State_List::Scan_State_List (char whichDSF, const XXZ_gpd_Bethe_State& SeedScanState) : ndef(0), State(Vect(MAX_STATE_LIST_SIZE)), base_label(Vect(MAX_STATE_LIST_SIZE)), info(Vect(MAX_STATE_LIST_SIZE)), flag_for_scan(Vect(false, MAX_STATE_LIST_SIZE)), scan_attempted(Vect(false, MAX_STATE_LIST_SIZE)) { State[0] = SeedScanState; } /* IN_DEVELOPMENT template<> inline Scan_State_List::Scan_State_List (char whichDSF, const ODSLF_XXZ_Bethe_State& RefState) : ndef(0), State(Vect(MAX_STATE_LIST_SIZE)), base_label(Vect(MAX_STATE_LIST_SIZE)), info(Vect(MAX_STATE_LIST_SIZE)), flag_for_scan(Vect(false, MAX_STATE_LIST_SIZE)), scan_attempted(Vect(false, MAX_STATE_LIST_SIZE)) { if (whichDSF == 'Z' || whichDSF == 'z') State[0] = ODSLF_XXZ_Bethe_State(RefState.chain, RefState.base.Mdown); else if (whichDSF == 'm') State[0] = ODSLF_XXZ_Bethe_State(RefState.chain, RefState.base.Mdown - 1); else if (whichDSF == 'p') State[0] = ODSLF_XXZ_Bethe_State(RefState.chain, RefState.base.Mdown + 1); else ABACUSerror("Unknown whichDSF in Scan_State_List inline LiebLin_Bethe_State& Scan_State_List::Return_State (std::string base_label_ref) { int n = 0; while (n < ndef && base_label_ref.compare(base_label[n]) != 0) n++; if (n == ndef) { State[n] = State[0]; base_label[n] = base_label_ref; info[n].Nfull = 1LL; // Nfull not definable for LiebLin ndef++; } return(State[n]); } template<> inline XXZ_Bethe_State& Scan_State_List::Return_State (std::string base_label_ref) { int n = 0; while (n < ndef && base_label_ref.compare(base_label[n]) != 0) n++; if (n == ndef) { Heis_Base checkbase (State[0].chain, base_label_ref); State[n] = XXZ_Bethe_State (State[0].chain, checkbase); info[n].Nfull = checkbase.dimH; ndef++; } return(State[n]); } template<> inline XXX_Bethe_State& Scan_State_List::Return_State (std::string base_label_ref) { int n = 0; while (n < ndef && base_label_ref.compare(base_label[n]) != 0) n++; if (n == ndef) { Heis_Base checkbase (State[0].chain, base_label_ref); State[n] = XXX_Bethe_State (State[0].chain, checkbase); info[n].Nfull = checkbase.dimH; ndef++; } return(State[n]); } template<> inline XXZ_gpd_Bethe_State& Scan_State_List::Return_State (std::string base_label_ref) { int n = 0; while (n < ndef && base_label_ref.compare(base_label[n]) != 0) n++; if (n == ndef) { Heis_Base checkbase (State[0].chain, base_label_ref); State[n] = XXZ_gpd_Bethe_State (State[0].chain, checkbase); info[n].Nfull = checkbase.dimH; ndef++; } return(State[n]); } /* IN DEVELOPMENT template<> inline ODSLF_XXZ_Bethe_State& Scan_State_List::Return_State (long long int base_id_ref, long long int type_id_ref) { int n = 0; while (n < ndef && !(base_id_ref == State[n].base_id && type_id_ref == State[n].type_id)) n++; if (n == ndef) { State[n] = ODSLF_XXZ_Bethe_State (State[0].chain, base_id_ref, type_id_ref); info[n].Nfull = State[n].maxid + 1LL; ndef++; } return(State[n]); } */ template<> inline void Scan_State_List::Populate_List (char whichDSF, const LiebLin_Bethe_State& SeedScanState) { // For LiebLin_Bethe_State: only one base is used, so there is only one state here. if (ndef != 0) ABACUSerror("Please only populate a virgin Scan_State_List."); std::stringstream baselabel; baselabel << State[0].N; base_label[0] = baselabel.str(); std::stringstream label0; label0 << State[0].N << LABELSEP << ABACUScoding[0] << LABELSEP;//"_0_"; State[0].Set_to_Label (label0.str(), SeedScanState.Ix2); info[0].Nfull = 1LL; // Nfull not definable for LiebLin ndef = 1; } template<> inline void Scan_State_List::Populate_List (char whichDSF, const XXZ_Bethe_State& SeedScanState) { // creates all types of states containing up to nexc_max excitations if (ndef != 0) ABACUSerror("Please only populate a virgin Scan_State_List."); // We assume that SeedScanState has quantum numbers which are set according to the relevant AveragingState. // This function creates a list of states with other bases in the vicinity of that of SeedScanState, // matching the quantum numbers as closely as possible. Vect Str_L(SeedScanState.chain.Nstrings); for (int i = 0; i < SeedScanState.chain.Nstrings; ++i) Str_L[i] = SeedScanState.chain.Str_L[i]; // First of all, we create a list of the possible bases themselves. Vect bases_label = Possible_Bases (SeedScanState.base.Nrap, Str_L, SeedScanState.base.Mdown); // returns a vector of possible bases for (int ib = 0; ib < bases_label.size(); ++ib) { Heis_Base checkbase (State[0].chain, bases_label[ib]); State[ndef] = XXZ_Bethe_State (State[0].chain, checkbase); State[ndef].Set_to_Closest_Matching_Ix2_fixed_Base (SeedScanState); State[ndef].Set_Label_from_Ix2 (State[ndef].Ix2); // sets to trivial label for this base base_label[ndef] = bases_label[ib]; info[ndef].Nfull = State[ndef].base.dimH; ndef++; if (ndef >= MAX_STATE_LIST_SIZE) ABACUSerror("Increase number of elements in ScanStateList."); } } template<> inline void Scan_State_List::Populate_List (char whichDSF, const XXX_Bethe_State& SeedScanState) { // creates all types of states containing up to nexc_max excitations if (ndef != 0) ABACUSerror("Please only populate a virgin Scan_State_List."); // We assume that SeedScanState has quantum numbers which are set according to the relevant AveragingState. // This function creates a list of states with other bases in the vicinity of that of SeedScanState, // matching the quantum numbers as closely as possible. Vect Str_L(SeedScanState.chain.Nstrings); for (int i = 0; i < SeedScanState.chain.Nstrings; ++i) Str_L[i] = SeedScanState.chain.Str_L[i]; // To take infinite rapidities into account, we use intermediate states with up to 2 less finite rapidities (1 for Szz, 2 for Spm) int nrinfrapmax = 0; if (whichDSF == 'z') nrinfrapmax = 1; else if (whichDSF == 'p') nrinfrapmax = ABACUS::min(2, SeedScanState.base.Mdown); Vect Nrapmod = SeedScanState.base.Nrap; for (int nrinfrap = 0; nrinfrap <= nrinfrapmax; ++nrinfrap) { Nrapmod[0] = SeedScanState.base.Nrap[0] - nrinfrap; if (Nrapmod[0] < 0) ABACUSerror("Putting too many rapidities at infinity in ABACUS_Scan.h: Possible_Bases."); Vect bases_label = Possible_Bases (Nrapmod, Str_L, SeedScanState.base.Mdown-nrinfrap); // returns a vector of possible bases for (int ib = 0; ib < bases_label.size(); ++ib) { Heis_Base checkbase (State[0].chain, bases_label[ib]); State[ndef] = XXX_Bethe_State (State[0].chain, checkbase); State[ndef].Set_to_Closest_Matching_Ix2_fixed_Base (SeedScanState); base_label[ndef] = bases_label[ib]; info[ndef].Nfull = State[ndef].base.dimH; ndef++; if (ndef >= MAX_STATE_LIST_SIZE) ABACUSerror("Increase number of elements in ScanStateList."); } } // for nrinfrap } template<> inline void Scan_State_List::Populate_List (char whichDSF, const XXZ_gpd_Bethe_State& SeedScanState) { // creates all types of states containing up to nexc_max excitations if (ndef != 0) ABACUSerror("Please only populate a virgin Scan_State_List."); // We assume that SeedScanState has quantum numbers which are set according to the relevant AveragingState. // This function creates a list of states with other bases in the vicinity of that of SeedScanState, // matching the quantum numbers as closely as possible. Vect Str_L(SeedScanState.chain.Nstrings); for (int i = 0; i < SeedScanState.chain.Nstrings; ++i) Str_L[i] = SeedScanState.chain.Str_L[i]; // First of all, we create a list of the possible bases themselves. Vect bases_label = Possible_Bases (SeedScanState.base.Nrap, Str_L, SeedScanState.base.Mdown); // returns a vector of possible bases for (int ib = 0; ib < bases_label.size(); ++ib) { Heis_Base checkbase (State[0].chain, bases_label[ib]); State[ndef] = XXZ_gpd_Bethe_State (State[0].chain, checkbase); State[ndef].Set_to_Closest_Matching_Ix2_fixed_Base (SeedScanState); base_label[ndef] = bases_label[ib]; info[ndef].Nfull = State[ndef].base.dimH; ndef++; if (ndef >= MAX_STATE_LIST_SIZE) ABACUSerror("Increase number of elements in ScanStateList."); } } /* IN DEVELOPMENT template<> inline void Scan_State_List::Populate_List () { // creates all types of states containing up to nexc_max excitations if (ndef != 0) ABACUSerror("Please only populate a virgin Scan_State_List."); //std::cout << "In Populate_List: " << State[0] << std::endl; Vect bases_id = State[0].chain.Possible_Bases (State[0].base.Mdown); // returns a vector of possible bases //std::cout << "Mdown = " << State[0].base.Mdown << "\tPossible bases size: " << bases_id.size() << "\tPossible bases: " << bases_id << std::endl; for (int ib = 0; ib < bases_id.size(); ++ib) { ODSLF_Base checkbase (State[0].chain, bases_id[ib]); Vect types_id = checkbase.Possible_Types (); // returns a vector of possible types //std::cout << "For base_id " << bases_id[ib] << "\t found types " << types_id << std::endl; for (int it = 0; it < types_id.size(); ++it) { if (bases_id[ib] < 1000000) { // FUDGE: consider only one-strings //std::cout << "Populate list: constructing state: " << bases_id[ib] << "\t" << types_id[it] << std::endl; State[ndef] = ODSLF_XXZ_Bethe_State (State[0].chain, bases_id[ib], types_id[it]); //std::cout << "Populate list: before setting id: " << std::endl << State[ndef] << std::endl; State[ndef].Set_to_id(0LL); //std::cout << "Populate list: after setting id: " << std::endl << State[ndef] << std::endl; info[ndef].Nfull = State[ndef].maxid + 1LL; ndef++; if (ndef >= MAX_STATE_LIST_SIZE) ABACUSerror("Increase number of elements in ScanStateList."); } } } } */ template inline void Scan_State_List::Include_Info (Scan_Info& info_to_add, std::string base_label_ref) { int n = 0; while (n < ndef && base_label_ref.compare(base_label[n]) != 0) n++; if (n == ndef) { std::cout << "ndef = " << ndef << std::endl; for (int i = 0; i < ndef; ++i) std::cout << base_label[i] << "\t"; std::cout << std::endl; std::cout << "base_label_ref " << base_label_ref << std::endl; ABACUSerror("Did not find base_label_ref in Scan_State_List::Include_Info."); } info[n] += info_to_add; return; } template inline void Scan_State_List::Raise_Scanning_Flags (DP threshold) { flag_for_scan = true; } template inline void Scan_State_List::Order_in_SRC () { if (ndef > 0) { Vect_INT index(ndef); for (int i = 0; i < ndef; ++i) index[i] = i; Vect sr (ndef); for (int i = 0; i < ndef; ++i) sr[i] = info[i].sumrule_obtained; sr.QuickSort(index, 0, ndef - 1); Vect State_ordered(ndef); Vect base_label_ordered(ndef); Vect info_ordered(ndef); Vect flag_for_scan_ordered(ndef); // Put data in proper order for (int i = 0; i < ndef; ++i) { State_ordered[i] = State[index[ndef - 1 - i] ]; base_label_ordered[i] = base_label[index[ndef - 1 - i] ]; info_ordered[i] = info[index[ndef - 1 - i] ]; flag_for_scan_ordered[i] = flag_for_scan[index[ndef - 1 - i] ]; } // Put back in *this object: for (int i = 0; i < ndef; ++i) { State[i] = State_ordered[i]; base_label[i] = base_label_ordered[i]; info[i] = info_ordered[i]; flag_for_scan[i] = flag_for_scan_ordered[i]; } // The rest are all simply 0. } } template inline void Scan_State_List::Save_Info (const char* sumfile_Cstr) { std::ofstream outfile; outfile.open(sumfile_Cstr); if (outfile.fail()) ABACUSerror("Could not open outfile... "); outfile.setf(std::ios::fixed); outfile.precision(16); outfile << std::setw(20) << "base" << std::setw(25) << "sumrule_obtained" << std::setw(25) << "Nfull" << std::setw(10) << "Ninadm" << std::setw(10) << "Ndata" << std::setw(10) << "conv" << std::setw(10) << "conv0" << std::setw(10) << "TT."; for (int i = 0; i < ndef; ++i) if (info[i].Nfull > 0.0) { int TT_hr = int(info[i].TT/3600); int TT_min = int((info[i].TT - 3600.0*TT_hr)/60); outfile << std::endl << std::setw(20) << base_label[i] << std::setw(25); if (info[i].sumrule_obtained < 1.0) outfile << std::fixed; else outfile << std::scientific; outfile << std::setprecision(16) << info[i].sumrule_obtained; if (info[i].Nfull < 1.0e+10) outfile << std::setw(25) << std::fixed << std::setprecision(0) << info[i].Nfull; else outfile << std::setw(25) << std::scientific << std::setprecision(16) << info[i].Nfull; outfile << std::setw(10) << info[i].Ninadm << std::setw(10) << info[i].Ndata << std::setw(10) << info[i].Ndata_conv << std::setw(10) << info[i].Ndata_conv0 << std::setw(10) << TT_hr << " h " << TT_min << " m " << std::fixed << std::showpoint << std::setprecision(3) << info[i].TT - 3600.0*TT_hr - 60.0*TT_min << " s"; } outfile.close(); } template inline void Scan_State_List::Load_Info (const char* sumfile_Cstr) { std::ifstream infile; infile.open(sumfile_Cstr); if(infile.fail()) { std::cout << std::endl << sumfile_Cstr << std::endl; ABACUSerror("Could not open input file in Scan_State_List::Load_Info."); } // Load first line, containing informative text: char junk[256]; infile.getline(junk, 256); // Now load the previous info's: std::string base_label_ref; DP sr_ref; DP Nfull_ref; long long int Ninadm_ref, Ndata_ref, conv_ref, conv0_ref; DP TT_ref; int TT_hr, TT_min; DP TT_sec; char a; while (infile.peek() != EOF) { infile >> base_label_ref >> sr_ref >> Nfull_ref >> Ninadm_ref >> Ndata_ref >> conv_ref >> conv0_ref >> TT_hr >> a >> TT_min >> a >> TT_sec >> a; TT_ref = 3600.0 * TT_hr + 60.0* TT_min + TT_sec; Scan_Info info_ref (sr_ref, Nfull_ref, Ninadm_ref, Ndata_ref, conv_ref, conv0_ref, TT_ref); (*this).Include_Info (info_ref, base_label_ref); } infile.close(); return; } } // namespace ABACUS #endif