123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428 |
- /**********************************************************
-
- This software is part of J.-S. Caux's ABACUS library.
-
- Copyright (c) J.-S. Caux.
-
- -----------------------------------------------------------
-
- File: src/1DSLF/1DSLF.cc
-
- Purpose: defines functions for 1d spinless fermion classes.
-
- ***********************************************************/
-
- #include "ABACUS.h"
-
- using namespace std;
-
- namespace ABACUS {
-
- //***************************************************************************************************
-
- // Function definitions: class ODSLF_Base
-
- ODSLF_Base::ODSLF_Base () : Mdown(0), Nrap(Vect<int>()), Nraptot(0), Ix2_infty(Vect<DP>()), Ix2_max(Vect<int>()) {}
-
- ODSLF_Base::ODSLF_Base (const ODSLF_Base& RefBase) // copy constructor
- : Mdown(RefBase.Mdown), Nrap(Vect<int>(RefBase.Nrap.size())), Nraptot(RefBase.Nraptot),
- Ix2_infty(Vect<DP>(RefBase.Nrap.size())), Ix2_max(Vect<int>(RefBase.Nrap.size())),
- id(RefBase.id)
- {
- for (int i = 0; i < Nrap.size(); ++i) {
- Nrap[i] = RefBase.Nrap[i];
- Ix2_infty[i] = RefBase.Ix2_infty[i];
- Ix2_max[i] = RefBase.Ix2_max[i];
- }
- }
-
- ODSLF_Base::ODSLF_Base (const Heis_Chain& RefChain, int M)
- : Mdown(M), Nrap(Vect<int>(RefChain.Nstrings)), Nraptot(0), Ix2_infty(Vect<DP>(RefChain.Nstrings)),
- Ix2_max(Vect<int>(RefChain.Nstrings))
- {
- for (int i = 0; i < RefChain.Nstrings; ++i) Nrap[i] = 0;
- Nrap[0] = M;
-
- Nraptot = 0;
- for (int i = 0; i < RefChain.Nstrings; ++i) Nraptot += Nrap[i];
-
- // The id of this is zero by definition
- id = 0LL;
-
- // Now compute the Ix2_infty numbers
-
- (*this).Compute_Ix2_limits(RefChain);
-
- }
-
- ODSLF_Base::ODSLF_Base (const Heis_Chain& RefChain, const Vect<int>& Nrapidities)
- : Mdown(0), Nrap(Nrapidities), Nraptot(0), Ix2_infty(Vect<DP>(RefChain.Nstrings)),
- Ix2_max(Vect<int>(RefChain.Nstrings)), id (0LL)
- {
-
- // Check consistency of Nrapidities vector with RefChain
-
- if (RefChain.Nstrings != Nrapidities.size())
- ABACUSerror("Incompatible Nrapidities vector used in ODSLF_Base constructor.");
-
- int Mcheck = 0;
- for (int i = 0; i < RefChain.Nstrings; ++i) Mcheck += RefChain.Str_L[i] * Nrap[i];
- Mdown = Mcheck;
-
- Nraptot = 0;
- for (int i = 0; i < RefChain.Nstrings; ++i) Nraptot += Nrap[i];
-
- // Compute id
- id += Nrapidities[0];
- long long int factor = 100000LL;
- for (int i = 1; i < RefChain.Nstrings; ++i) {
- id += factor * Nrapidities[i];
- factor *= 100LL;
- }
-
- // Now compute the Ix2_infty numbers
- (*this).Compute_Ix2_limits(RefChain);
-
- }
-
- ODSLF_Base::ODSLF_Base (const Heis_Chain& RefChain, long long int id_ref)
- : Mdown(0), Nrap(Vect<int>(RefChain.Nstrings)), Nraptot(0), Ix2_infty(Vect<DP>(RefChain.Nstrings)),
- Ix2_max(Vect<int>(RefChain.Nstrings)), id (id_ref)
- {
- // Build Nrapidities vector from id_ref
-
- long long int factor = pow_ulli (10LL, 2* RefChain.Nstrings + 1);
- long long int id_eff = id_ref;
- for (int i = 0; i < RefChain.Nstrings - 1; ++i) {
- Nrap[RefChain.Nstrings - 1 - i] = id_eff/factor;
- id_eff -= factor * Nrap[RefChain.Nstrings - 1 - i];
- factor /= 100LL;
- }
- Nrap[0] = id_eff;
-
- int Mcheck = 0;
- for (int i = 0; i < RefChain.Nstrings; ++i) Mcheck += RefChain.Str_L[i] * Nrap[i];
- Mdown = Mcheck;
-
- Nraptot = 0;
- for (int i = 0; i < RefChain.Nstrings; ++i) Nraptot += Nrap[i];
-
- // Now compute the Ix2_infty numbers
- (*this).Compute_Ix2_limits(RefChain);
- }
-
-
- ODSLF_Base& ODSLF_Base::operator= (const ODSLF_Base& RefBase)
- {
- if (this != & RefBase) {
- Mdown = RefBase.Mdown;
- Nrap = RefBase.Nrap;
- Nraptot = RefBase.Nraptot;
- Ix2_infty = RefBase.Ix2_infty;
- Ix2_max = RefBase.Ix2_max;
- id = RefBase.id;
- }
- return(*this);
- }
-
- bool ODSLF_Base::operator== (const ODSLF_Base& RefBase)
- {
- bool answer = (Nrap == RefBase.Nrap);
-
- return (answer);
- }
-
- bool ODSLF_Base::operator!= (const ODSLF_Base& RefBase)
- {
- bool answer = (Nrap != RefBase.Nrap);
-
- return (answer);
- }
-
- void ODSLF_Base::Compute_Ix2_limits (const Heis_Chain& RefChain)
- {
-
- if ((RefChain.Delta > 0.0) && (RefChain.Delta < 1.0)) {
-
- // Compute the Ix2_infty numbers
-
- DP sum1 = 0.0;
- DP sum2 = 0.0;
-
- for (int j = 0; j < RefChain.Nstrings; ++j) {
-
- sum1 = 0.0;
-
- for (int k = 0; k < RefChain.Nstrings; ++k) {
-
- sum2 = 0.0;
-
- sum2 += (RefChain.Str_L[j] == RefChain.Str_L[k]) ? 0.0 :
- 2.0 * atan(tan(0.25 * PI * (1.0 + RefChain.par[j] * RefChain.par[k])
- - 0.5 * fabs(RefChain.Str_L[j] - RefChain.Str_L[k]) * RefChain.anis));
- sum2 += 2.0 * atan(tan(0.25 * PI * (1.0 + RefChain.par[j] * RefChain.par[k])
- - 0.5 * (RefChain.Str_L[j] + RefChain.Str_L[k]) * RefChain.anis));
-
- for (int a = 1; a < ABACUS::min(RefChain.Str_L[j], RefChain.Str_L[k]); ++a)
- sum2 += 2.0 * 2.0 * atan(tan(0.25 * PI * (1.0 + RefChain.par[j] * RefChain.par[k])
- - 0.5 * (fabs(RefChain.Str_L[j] - RefChain.Str_L[k]) + 2.0*a) * RefChain.anis));
-
- sum1 += (Nrap[k] - ((j == k) ? 1 : 0)) * sum2;
- }
-
- Ix2_infty[j] = (1.0/PI) * fabs(RefChain.Nsites * 2.0
- * atan(tan(0.25 * PI * (1.0 + RefChain.par[j])
- - 0.5 * RefChain.Str_L[j] * RefChain.anis)) - sum1);
-
- } // The Ix2_infty are now set.
-
- // Now compute the Ix2_max limits
-
- for (int j = 0; j < RefChain.Nstrings; ++j) {
-
- Ix2_max[j] = int(floor(Ix2_infty[j])); // sets basic integer
-
- // Reject formally infinite rapidities (i.e. if Delta is root of unity)
-
-
- // For ODSLF: parity of quantum numbers is complicated:
- // if (N-1 + M_j + (M + 1) n_j + (1 - nu_j) N/2) is even, q# are integers,
- // so Ix2_max must be even (conversely, if odd, then odd).
- if ((Ix2_max[j] + RefChain.Nsites - 1 + Nrap[j] + (Nraptot + 1) * RefChain.Str_L[j]
- + (RefChain.par[j] == 1 ? 0 : RefChain.Nsites)) % 2) Ix2_max[j] -= 1;
-
- while (Ix2_max[j] > RefChain.Nsites) {
- Ix2_max[j] -= 2;
- }
- }
- } // if XXZ gapless
-
- else if (RefChain.Delta == 1.0) {
-
- // Compute the Ix2_infty numbers
-
- int sum1 = 0;
-
- for (int j = 0; j < RefChain.Nstrings; ++j) {
-
- sum1 = 0;
-
- for (int k = 0; k < RefChain.Nstrings; ++k) {
-
- sum1 += Nrap[k] * (2 * ABACUS::min(RefChain.Str_L[j], RefChain.Str_L[k]) - ((j == k) ? 1 : 0));
- }
-
- Ix2_infty[j] = (RefChain.Nsites + 1.0 - sum1); // to get counting right...
-
- } // The Ix2_infty are now set.
-
- // Now compute the Ix2_max limits
-
- for (int j = 0; j < RefChain.Nstrings; ++j) {
-
- Ix2_max[j] = int(floor(Ix2_infty[j])); // sets basic integer
-
- // Give the correct parity to Ix2_max
-
- // If Nrap is even, Ix2_max must be odd. If odd, then even.
-
- //if (!((Nrap[j] + Ix2_max[j]) % 2)) Ix2_max[j] -= 1; DEACTIVATED FOR ODSLF !
-
- // If Ix2_max equals Ix2_infty, we reduce it by 2:
-
- if (Ix2_max[j] == int(Ix2_infty[j])) Ix2_max[j] -= 2;
-
- while (Ix2_max[j] > RefChain.Nsites) {
- Ix2_max[j] -= 2;
- }
- }
-
- } // if XXX AFM
-
- else if (RefChain.Delta > 1.0) {
-
- // Compute the Ix2_infty numbers
-
- int sum1 = 0;
-
- for (int j = 0; j < RefChain.Nstrings; ++j) {
-
- sum1 = 0;
-
- for (int k = 0; k < RefChain.Nstrings; ++k) {
-
- sum1 += Nrap[k] * (2 * ABACUS::min(RefChain.Str_L[j], RefChain.Str_L[k]) - ((j == k) ? 1 : 0));
- }
-
- Ix2_infty[j] = (RefChain.Nsites - 1 + 2 * RefChain.Str_L[j] - sum1);
-
- } // The Ix2_infty are now set.
-
- // Now compute the Ix2_max limits
-
- for (int j = 0; j < RefChain.Nstrings; ++j) {
-
- Ix2_max[j] = int(floor(Ix2_infty[j])); // sets basic integer
-
- // Give the correct parity to Ix2_max
-
- // If Nrap is even, Ix2_max must be odd. If odd, then even.
-
- //if (!((Nrap[j] + Ix2_max[j]) % 2)) Ix2_max[j] -= 1; DEACTIVATED FOR ODSLF !
-
- // If Ix2_max equals Ix2_infty, we reduce it by 2:
-
- //if (Ix2_max[j] == Ix2_infty[j]) Ix2_max[j] -= 2;
-
- while (Ix2_max[j] > RefChain.Nsites) {
- Ix2_max[j] -= 2;
- }
-
- }
-
- } // if XXZ_gpd
-
- }
-
- void ODSLF_Base::Scan_for_Possible_Types (Vect<long long int>& possible_type_id, int& nfound,
- int base_level, Vect<int>& Nexcitations)
- {
- if (base_level == 0) {
- // We set all sectors 0, 1, 2, 3
-
- int Nexc_max_0 = (Nrap[0] + 1)/2; // holes on R
- int Nexc_max_1 = Nrap[0]/2;
- int Nexc_max_2 = (Ix2_max[0] - Nrap[0] + 1)/2;
- int Nexc_max_3 = Nexc_max_2;
-
- // Count the number of excitations in higher levels:
- int Nexc_above = 0;
- for (int i = 4; i < Nexcitations.size(); ++i) Nexc_above += Nexcitations[i];
-
- for (int nphpairs = 0; nphpairs <= NEXC_MAX_HEIS/2 - Nexc_above; ++nphpairs)
- for (int nexc0 = 0; nexc0 <= ABACUS::min(Nexc_max_0, nphpairs); ++nexc0) {
- int nexc1 = nphpairs - nexc0;
- for (int nexc2 = 0; nexc2 <= ABACUS::min(Nexc_max_2, nphpairs); ++nexc2) {
- int nexc3 = nphpairs - nexc2;
-
- if (nexc1 >= 0 && nexc1 <= Nexc_max_1 && nexc3 >= 0 && nexc3 <= Nexc_max_3) {
- // acceptable type found
- Nexcitations[0] = nexc0; Nexcitations[1] = nexc1; Nexcitations[2] = nexc2; Nexcitations[3] = nexc3;
- possible_type_id[nfound] = Ix2_Offsets_type_id (Nexcitations);
- nfound++;
- }
- }
- }
- }
-
- else { // base_level > 0
- // We scan over the possible distributions of the excitations on the L and R sides:
-
- // Count the number of slots available on R:
- int Nexc_R_max = (Ix2_max[base_level] + 2)/2;
- int Nexc_L_max = (Ix2_max[base_level] + 1)/2;
- for (int Nexcleft = 0; Nexcleft <= Nrap[base_level]; ++Nexcleft)
- if (Nexcleft <= Nexc_L_max && Nrap[base_level] - Nexcleft <= Nexc_R_max) {
- Nexcitations[2*base_level + 2] = Nrap[base_level] - Nexcleft;
- Nexcitations[2*base_level + 3] = Nexcleft;
- Scan_for_Possible_Types (possible_type_id, nfound, base_level - 1, Nexcitations);
- }
- }
-
- }
-
- Vect<long long int> ODSLF_Base::Possible_Types ()
- {
- // Given a base, this returns a vector of possible types
-
- Vect<long long int> possible_type_id (0LL, 1000);
- int nfound = 0;
-
- Vect<int> Nexcitations (0, 2*Nrap.size() + 2);
-
- Scan_for_Possible_Types (possible_type_id, nfound, Nrap.size() - 1, Nexcitations);
-
- // Copy results into new vector:
- Vect<long long int> possible_type_id_found (nfound);
- for (int i = 0; i < nfound; ++i)
- possible_type_id_found[i] = possible_type_id[i];
-
- return(possible_type_id_found);
- }
-
-
- //***************************************************************************************************
-
- // Function definitions: class Ix2_Config
-
- ODSLF_Ix2_Config::ODSLF_Ix2_Config () {}
-
- ODSLF_Ix2_Config::ODSLF_Ix2_Config (const Heis_Chain& RefChain, int M)
- : Nstrings(1), Nrap(Vect<int>(M,1)), Nraptot(M), Ix2(new int*[1]) // single type of string here
- {
- Ix2[0] = new int[M];
-
- for (int j = 0; j < M; ++j) {
- Ix2[0][j] = -(M - 1) + 2*j;
- // Use simplification: Nrap[0] = M = Nraptot, Str_L[0] = 1, par = 1, so
- if ((Ix2[0][j] + RefChain.Nsites) % 2) Ix2[0][j] -= 1;
- }
- }
-
- ODSLF_Ix2_Config::ODSLF_Ix2_Config (const Heis_Chain& RefChain, const ODSLF_Base& base)
- : Nstrings(RefChain.Nstrings), Nrap(base.Nrap), Nraptot(base.Nraptot), Ix2(new int*[RefChain.Nstrings])
- {
- Ix2[0] = new int[base.Nraptot];
- for (int i = 1; i < RefChain.Nstrings; ++i) Ix2[i] = Ix2[i-1] + base[i-1];
-
- // And now for the other string types...
- for (int i = 0; i < RefChain.Nstrings; ++i) {
- for (int j = 0; j < base[i]; ++j) Ix2[i][j] = -(base[i] - 1) + 2*j + 1 - (base[i] % 2);
- }
-
- // ODSLF: put back correct parity of quantum nr:
- for (int i = 0; i < RefChain.Nstrings; ++i)
- for (int j = 0; j < base[i]; ++j)
- if ((Ix2[i][j] + RefChain.Nsites - 1 + base.Nrap[i] + (base.Nraptot + 1) * RefChain.Str_L[i] + (RefChain.par[i] == 1 ? 0 : RefChain.Nsites)) % 2)
- Ix2[i][j] -= 1;
- }
-
- ODSLF_Ix2_Config& ODSLF_Ix2_Config::operator= (const ODSLF_Ix2_Config& RefConfig)
- {
- if (this != &RefConfig) {
- Nstrings = RefConfig.Nstrings;
- Nrap = RefConfig.Nrap;
- Nraptot = RefConfig.Nraptot;
- if (Ix2 != 0) {
- delete[] (Ix2[0]);
- delete[] (Ix2);
- }
- Ix2 = new int*[Nstrings];
- Ix2[0] = new int[Nraptot];
- for (int i = 1; i < Nstrings; ++i) Ix2[i] = Ix2[i-1] + Nrap[i-1];
- for (int i = 0; i < Nstrings; ++i)
- for (int j = 0; j < Nrap[i]; ++j) Ix2[i][j] = RefConfig.Ix2[i][j];
-
- }
- return(*this);
- }
-
- ODSLF_Ix2_Config::~ODSLF_Ix2_Config()
- {
- if (Ix2 != 0) {
- delete[] (Ix2[0]);
- delete[] Ix2;
- }
- }
-
- std::ostream& operator<< (std::ostream& s, const ODSLF_Ix2_Config& RefConfig)
- {
- s << &RefConfig << "\t" << RefConfig.Nstrings << "\t" << RefConfig.Nraptot << endl;
- for (int i = 0; i < RefConfig.Nstrings; ++i) s << RefConfig.Nrap[i] << "\t";
- s << endl;
- for (int i = 0; i < RefConfig.Nstrings; ++i) {
- s << "i " << i << "\t";
- for (int j = 0; j < RefConfig.Nrap[i]; ++j) s << RefConfig.Ix2[i][j] << "\t";
- s << endl;
- }
- return(s);
- }
-
- //***************************************************************************************************
-
- // Function definitions: class Lambda
-
- ODSLF_Lambda::ODSLF_Lambda () {}
-
- ODSLF_Lambda::ODSLF_Lambda (const Heis_Chain& RefChain, int M)
- : Nstrings(1), Nrap(Vect<int>(M,1)), Nraptot(M), lambda(new DP*[1]) // single type of string here
- {
- lambda[0] = new DP[M];
-
- for (int j = 0; j < M; ++j) lambda[0][j] = 0.0;
- }
-
- ODSLF_Lambda::ODSLF_Lambda (const Heis_Chain& RefChain, const ODSLF_Base& base)
- : Nstrings(RefChain.Nstrings), Nrap(base.Nrap), Nraptot(base.Nraptot), lambda(new DP*[RefChain.Nstrings])
- {
- lambda[0] = new DP[base.Nraptot];
- for (int i = 1; i < RefChain.Nstrings; ++i) lambda[i] = lambda[i-1] + base[i-1];
-
- for (int i = 0; i < RefChain.Nstrings; ++i) {
- for (int j = 0; j < base[i]; ++j) lambda[i][j] = 0.0;
- }
- }
-
- ODSLF_Lambda& ODSLF_Lambda::operator= (const ODSLF_Lambda& RefLambda)
- {
- if (this != &RefLambda) {
- Nstrings = RefLambda.Nstrings;
- Nrap = RefLambda.Nrap;
- Nraptot = RefLambda.Nraptot;
- if (lambda != 0) {
- delete[] (lambda[0]);
- delete[] (lambda);
- }
- lambda = new DP*[Nstrings];
- lambda[0] = new DP[Nraptot];
- for (int i = 1; i < Nstrings; ++i) lambda[i] = lambda[i-1] + Nrap[i-1];
- for (int i = 0; i < Nstrings; ++i)
- for (int j = 0; j < Nrap[i]; ++j) lambda[i][j] = RefLambda.lambda[i][j];
-
- }
- return(*this);
- }
-
- ODSLF_Lambda::~ODSLF_Lambda()
- {
- if (lambda != 0) {
- delete[] (lambda[0]);
- delete[] lambda;
- }
- }
-
- //***************************************************************************************************
-
- // Function definitions: class ODSLF_Ix2_Offsets
-
- ODSLF_Ix2_Offsets::ODSLF_Ix2_Offsets () : base(), Tableau(Vect<Young_Tableau>()), type_id(0LL), id(0LL), maxid(0LL) {};
-
- ODSLF_Ix2_Offsets::ODSLF_Ix2_Offsets (const ODSLF_Ix2_Offsets& RefOffset) // copy constructor
- : base(RefOffset.base), Tableau(Vect<Young_Tableau> (2 * base.Nrap.size() + 2)), type_id(RefOffset.type_id), id(RefOffset.id), maxid(RefOffset.maxid)
- {
- for (int i = 0; i < 2 * base.Nrap.size() + 2; ++i) Tableau[i] = RefOffset.Tableau[i];
- }
-
- ODSLF_Ix2_Offsets::ODSLF_Ix2_Offsets (const ODSLF_Base& RefBase, long long int req_type_id)
- // sets all tableaux to empty ones, with nparticles(req_type_id) at each level
- {
- // Build nparticles vector from req_type_id
-
- Vect<int> nparticles(0, 2* RefBase.Nrap.size() + 2);
- long long int factor = pow_ulli (10LL, nparticles.size() - 1);
- long long int id_eff = req_type_id;
- for (int i = 0; i < nparticles.size(); ++i) {
- nparticles[nparticles.size() - 1 - i] = id_eff/factor;
- id_eff -= factor * nparticles[nparticles.size() - 1 - i];
- factor /= 10LL;
- }
-
- // Check if we've got the right vector...
- long long int idcheck = Ix2_Offsets_type_id (nparticles);
- if (idcheck != req_type_id) ABACUSerror("idcheck != req_type_id in Ix2_Offsets constructor.");
-
- (*this) = ODSLF_Ix2_Offsets(RefBase, nparticles);
- }
-
- ODSLF_Ix2_Offsets::ODSLF_Ix2_Offsets (const ODSLF_Base& RefBase, Vect<int> nparticles)
- // sets all tableaux to empty ones, with nparticles at each level
- : base(RefBase), Tableau(Vect<Young_Tableau> (2 * base.Nrap.size() + 2)),
- type_id(Ix2_Offsets_type_id (nparticles)), id(0LL), maxid(0LL)
- {
- // Checks on nparticles vector:
-
- if (nparticles.size() != 2 * base.Nrap.size() + 2)
- ABACUSerror("Wrong nparticles.size in Ix2_Offsets constructor.");
-
- if (nparticles[3] + nparticles[2] != nparticles[0] + nparticles[1]) {
- cout << nparticles[0] << "\t" << nparticles[1] << "\t" << nparticles[2] << "\t" << nparticles[3] << endl;
- ABACUSerror("Wrong Npar[0-3] in Ix2_Offsets constructor.");
- }
-
- for (int base_level = 1; base_level < base.Nrap.size(); ++ base_level)
- if (base.Nrap[base_level] != nparticles[2*base_level + 2] + nparticles[2*base_level + 3]) {
- cout << base_level << "\t" << base.Nrap[base_level] << "\t" << nparticles[2*base_level + 2]
- << "\t" << nparticles[2*base_level + 3] << endl;
- ABACUSerror("Wrong Nrap[] in Ix2_Offsets constructor.");
- }
-
- // nparticles[0,1]: number of holes on R and L side in GS interval
- if (nparticles[0] > (base.Nrap[0] + 1)/2)
- ABACUSerror("nparticles[0] too large in Ix2_Offsets constructor.");
- if (nparticles[1] > base.Nrap[0]/2)
- ABACUSerror("nparticles[1] too large in Ix2_Offsets constructor.");
-
- // nparticles[2,3]: number of particles of type 0 on R and L side out of GS interval
- if (nparticles[2] > (base.Ix2_max[0] - base.Nrap[0] + 1)/2)
- ABACUSerror("nparticles[2] too large in Ix2_Offsets constructor.");
- if (nparticles[3] > (base.Ix2_max[0] - base.Nrap[0] + 1)/2)
- ABACUSerror("nparticles[3] too large in Ix2_Offsets constructor.");
-
- for (int base_level = 1; base_level < base.Nrap.size(); ++ base_level)
- if ((nparticles[2*base_level + 2] > 0 && nparticles[2*base_level + 2]
- > (base.Ix2_max[base_level] + 2)/2) // ODSLF modif
- || (nparticles[2*base_level + 3] > 0
- && nparticles[2*base_level + 3] > (base.Ix2_max[base_level] + 1)/2)) // ODSLF modif
- {
- cout << base_level << "\t" << base.Ix2_max[base_level] << "\t" << base.Ix2_infty[base_level]
- << "\t" << nparticles[2*base_level + 2] << "\t"
- << (base.Ix2_max[base_level] - ((base.Nrap[base_level] + 1) % 2) + 2)/2
- << "\t" << nparticles[2*base_level + 3] << "\t"
- << (base.Ix2_max[base_level] - (base.Nrap[base_level] % 2) - 1)/2
- << "\t" << (nparticles[2*base_level + 2] > 0) << "\t"
- << (nparticles[2*base_level + 2] > (base.Ix2_max[base_level] - ((base.Nrap[base_level] + 1) % 2) + 2)/2)
- << "\t" << (nparticles[2*base_level + 3] > 0) << "\t"
- << (nparticles[2*base_level + 3] > base.Ix2_max[base_level] + 1
- - (base.Ix2_max[base_level] - ((base.Nrap[base_level] + 1) % 2) + 2)/2)
- << endl;
- ABACUSerror("nparticles too large in Ix2_Offsets constructor.");
- }
-
- // Check sum of rapidities
-
- // Holes in GS interval
- Tableau[0] = Young_Tableau(nparticles[0], (base.Nrap[0] + 1)/2 - nparticles[0]);
- Tableau[1] = Young_Tableau(nparticles[1], base.Nrap[0]/2 - nparticles[1], Tableau[0]);
-
- // Particles of type 0 out of GS interval
- Tableau[2] = Young_Tableau(nparticles[2], (base.Ix2_max[0] - base.Nrap[0] + 1)/2 - nparticles[2], Tableau[0]);
- Tableau[3] = Young_Tableau(nparticles[3], (base.Ix2_max[0] - base.Nrap[0] + 1)/2 - nparticles[3], Tableau[2]);
-
- // Tableaux of index i = 2,...: data about string type i/2-1.
- for (int base_level = 1; base_level < base.Nrap.size(); ++base_level) {
- Tableau[2*base_level + 2] =
- Young_Tableau(nparticles[2*base_level + 2],
- (base.Ix2_max[base_level] - ((base.Nrap[base_level] + 1) % 2))/2 + 1
- - nparticles[2*base_level + 2], Tableau[2]);
- Tableau[2*base_level + 3] =
- Young_Tableau(nparticles[2*base_level + 3],
- (base.Ix2_max[base_level] - (base.Nrap[base_level] % 2) - 1)/2 + 1
- - nparticles[2*base_level + 3], Tableau[3]);
- }
-
- maxid = 1LL;
- for (int i = 0; i < nparticles.size(); ++i) {
- maxid *= Tableau[i].maxid + 1LL;
- }
- maxid -= 1LL;
-
- }
-
- ODSLF_Ix2_Offsets& ODSLF_Ix2_Offsets::operator= (const ODSLF_Ix2_Offsets& RefOffset)
- {
- if (this != &RefOffset) {
- base = RefOffset.base;
- Tableau = RefOffset.Tableau;
- type_id = RefOffset.type_id;
- id = RefOffset.id;
- maxid = RefOffset.maxid;
- }
- return(*this);
- }
-
- bool ODSLF_Ix2_Offsets::operator<= (const ODSLF_Ix2_Offsets& RefOffsets)
- {
- // Check whether all nonzero tableau row lengths in RefOffsets
- // are <= than those in *this
-
- bool answer = true;
- for (int level = 0; level < 4; ++level) { // check fundamental level only
- // First check whether all rows which exist in both tableaux satisfy rule:
- for (int tableau_level = 0; tableau_level
- < ABACUS::min(Tableau[level].Nrows, RefOffsets.Tableau[level].Nrows); ++tableau_level)
- if (Tableau[level].Row_L[tableau_level] > RefOffsets.Tableau[level].Row_L[tableau_level])
- answer = false;
- // Now check whether there exist extra rows violating rule:
- for (int tableau_level = ABACUS::min(Tableau[level].Nrows, RefOffsets.Tableau[level].Nrows);
- tableau_level < Tableau[level].Nrows; ++tableau_level)
- if (Tableau[level].Row_L[tableau_level] > 0) answer = false;
- }
-
- return(answer);
- }
-
- bool ODSLF_Ix2_Offsets::operator>= (const ODSLF_Ix2_Offsets& RefOffsets)
- {
- // Check whether all nonzero tableau row lengths in RefOffsets
- // are >= than those in *this
-
- bool answer = true;
- for (int level = 0; level < 4; ++level) { // check fundamental level only
- // First check whether all rows which exist in both tableaux satisfy rule:
- for (int tableau_level = 0; tableau_level
- < ABACUS::min(Tableau[level].Nrows, RefOffsets.Tableau[level].Nrows); ++tableau_level)
- if (Tableau[level].Row_L[tableau_level] < RefOffsets.Tableau[level].Row_L[tableau_level])
- answer = false;
- // Now check whether there exist extra rows violating rule:
- for (int tableau_level = ABACUS::min(Tableau[level].Nrows, RefOffsets.Tableau[level].Nrows);
- tableau_level < RefOffsets.Tableau[level].Nrows; ++tableau_level)
- if (RefOffsets.Tableau[level].Row_L[tableau_level] > 0) answer = false;
- }
-
- return(answer);
- }
-
- void ODSLF_Ix2_Offsets::Set_to_id (long long int idnr)
- {
- // The idnr of the Offset is given by
- // sub_id[0] + (total number of tableaux of type 0) * (sub_id[1] + (total number of tableaux of type 1) * (sub_id[2] + ...
- // + total number of tableaux of type (2*base.Nrap.size()) * sub_id[2*base.Nrap.size() + 1]
-
- if (idnr > maxid) {
- cout << idnr << "\t" << maxid << endl;
- ABACUSerror("idnr too large in offsets.Set_to_id.");
- }
-
- id = idnr;
-
- Vect<long long int> sub_id(0LL, 2*base.Nrap.size() + 2);
-
- long long int idnr_eff = idnr;
- long long int temp_prod = 1LL;
-
- Vect<long long int> result_choose(2*base.Nrap.size() + 2);
-
- for (int i = 0; i <= 2*base.Nrap.size(); ++i) {
- result_choose[i] = Tableau[i].maxid + 1LL;
- temp_prod *= result_choose[i];
- }
-
- for (int i = 2*base.Nrap.size() + 1; i > 0; --i) {
- sub_id[i] = idnr_eff/temp_prod;
- idnr_eff -= sub_id[i] * temp_prod;
- temp_prod /= result_choose[i-1];
- }
- sub_id[0] = idnr_eff; // what's left goes to the bottom...
-
- for (int i = 0; i <= 2*base.Nrap.size() + 1; ++i) {
- if ((Tableau[i].Nrows * Tableau[i].Ncols == 0) && (sub_id[i] != 0))
- ABACUSerror("index too large in offset.Set_to_id.");
- if (Tableau[i].id != sub_id[i]) Tableau[i].Set_to_id(sub_id[i]);
- }
-
- Compute_type_id ();
-
- return;
- }
-
- void ODSLF_Ix2_Offsets::Compute_type_id ()
- {
- type_id = 0LL;
-
- for (int i = 0; i < 2*base.Nrap.size() + 2; ++i) {
- Tableau[i].Compute_id();
- type_id += Tableau[i].Nrows * pow_ulli(10LL, i);
- }
- }
-
- void ODSLF_Ix2_Offsets::Compute_id ()
- {
- long long int prod_maxid = 1LL;
-
- id = 0LL;
-
- for (int i = 0; i < 2*base.Nrap.size() + 2; ++i) {
- Tableau[i].Compute_id();
- id += Tableau[i].id * prod_maxid;
- prod_maxid *= Tableau[i].maxid + 1LL;
- }
-
- }
-
- bool ODSLF_Ix2_Offsets::Add_Boxes_From_Lowest (int Nboxes, bool odd_sectors)
- {
- // Tries to add Nboxes to Young tableau in given sector parity.
- // If Nboxes is too large to be accommodated, `false' is returned.
-
- ODSLF_Ix2_Offsets offsets_init(*this); // keep a copy in case it fails
-
- if (Nboxes < 0) ABACUSerror("Can't use Nboxes < 0 in Add_Boxes_From_Lowest");
- else if (Nboxes == 0) return(true); // nothing to do
-
- int Nboxes_put = 0;
- int working_sector = odd_sectors;
- // We start from the bottom up.
- while (Nboxes_put < Nboxes && working_sector < 2*base.Nrap.size() + 2) {
- Nboxes_put += Tableau[working_sector].Add_Boxes_From_Lowest(Nboxes - Nboxes_put);
- working_sector += 2;
- }
- Compute_id();
-
- if (Nboxes_put < Nboxes) (*this) = offsets_init; // reset !
- else if (Nboxes_put > Nboxes) {
- cout << Nboxes_put << "\t" << Nboxes << endl;
- ABACUSerror("Putting too many boxes in Ix2_Offsets::Add_Boxes_From_Lowest.");
- }
- return(Nboxes_put == Nboxes);
- }
-
- //***************************************************************************************************
-
- // Function definitions: class ODSLF_Ix2_Offsets_List
-
- ODSLF_Ix2_Offsets_List::ODSLF_Ix2_Offsets_List() : ndef(0), Offsets(Vect<ODSLF_Ix2_Offsets>(NBASESMAX)) {};
-
- ODSLF_Ix2_Offsets& ODSLF_Ix2_Offsets_List::Return_Offsets (ODSLF_Base& RefBase, Vect<int> nparticles)
- {
-
- long long int Ix2_Offsets_type_id_ref = Ix2_Offsets_type_id (nparticles);
- int n = 0;
-
- while (n < ndef && !(Ix2_Offsets_type_id_ref == Offsets[n].type_id && RefBase == Offsets[n].base)) n++;
-
- if (n == ndef) {
- Offsets[n] = ODSLF_Ix2_Offsets (RefBase, nparticles);
- ndef++;
- }
-
- if (ndef >= NBASESMAX) ABACUSerror("Ix2_Offsets_List: need bigger Offsets vector.");
-
- return(Offsets[n]);
- }
-
- ODSLF_Ix2_Offsets& ODSLF_Ix2_Offsets_List::Return_Offsets (ODSLF_Base& RefBase, long long int req_type_id)
- {
-
- int n = 0;
-
- while (n < ndef && !(req_type_id == Offsets[n].type_id && RefBase == Offsets[n].base)) n++;
-
- if (n == ndef) {
- Offsets[n] = ODSLF_Ix2_Offsets (RefBase, req_type_id);
- ndef++;
- }
-
- if (ndef >= NBASESMAX) ABACUSerror("Ix2_Offsets_List: need bigger Offsets vector.");
-
- return(Offsets[n]);
- }
-
-
-
- //***************************************************************************************************
-
- // Function definitions: class ODSLF_Bethe_State
-
- ODSLF_Bethe_State::ODSLF_Bethe_State ()
- : chain(Heis_Chain()), base(ODSLF_Base()), offsets(ODSLF_Ix2_Offsets()), Ix2(ODSLF_Ix2_Config(chain, 1)),
- lambda(ODSLF_Lambda(chain, 1)), BE(ODSLF_Lambda(chain, 1)), diffsq(0.0), conv(0), iter(0), iter_Newton(0),
- E(0.0), iK(0), K(0.0), lnnorm(-100.0), base_id(0LL), type_id(0LL), id(0LL), maxid(0LL), nparticles(0)
- {
- };
-
- ODSLF_Bethe_State::ODSLF_Bethe_State (const ODSLF_Bethe_State& RefState) // copy constructor
- : chain(RefState.chain), base(RefState.base), offsets(RefState.offsets),
- Ix2(ODSLF_Ix2_Config(RefState.chain, RefState.base)),
- lambda(ODSLF_Lambda(RefState.chain, RefState.base)), BE(ODSLF_Lambda(RefState.chain, RefState.base)),
- diffsq(RefState.diffsq), conv(RefState.conv), iter(RefState.iter), iter_Newton(RefState.iter_Newton),
- E(RefState.E), iK(RefState.iK), K(RefState.K), lnnorm(RefState.lnnorm),
- base_id(RefState.base_id), type_id(RefState.type_id), id(RefState.id), maxid(RefState.maxid),
- nparticles(RefState.nparticles)
- {
- // copy arrays into new ones
- for (int j = 0; j < RefState.chain.Nstrings; ++j) {
- for (int alpha = 0; alpha < RefState.base[j]; ++j) {
- Ix2[j][alpha] = RefState.Ix2[j][alpha];
- lambda[j][alpha] = RefState.lambda[j][alpha];
- }
- }
- }
-
- ODSLF_Bethe_State::ODSLF_Bethe_State (const ODSLF_Bethe_State& RefState, long long int type_id_ref)
- : chain(RefState.chain), base(RefState.base), offsets(ODSLF_Ix2_Offsets(RefState.base, type_id_ref)),
- Ix2(ODSLF_Ix2_Config(RefState.chain, RefState.base)), lambda(ODSLF_Lambda(RefState.chain, RefState.base)),
- BE(ODSLF_Lambda(RefState.chain, RefState.base)), diffsq(1.0), conv(0), iter(0), iter_Newton(0),
- E(0.0), iK(0), K(0.0), lnnorm(-100.0),
- base_id(RefState.base_id), type_id(0LL), id(0LL), maxid(offsets.maxid), nparticles(0)
- {
- (*this).Set_Ix2_Offsets (offsets);
- }
-
- ODSLF_Bethe_State::ODSLF_Bethe_State (const Heis_Chain& RefChain, int M)
- : chain(RefChain), base(RefChain, M), offsets(base, 0LL), Ix2(ODSLF_Ix2_Config(RefChain, M)),
- lambda(ODSLF_Lambda(RefChain, M)),
- BE(ODSLF_Lambda(RefChain, M)), diffsq(1.0), conv(0), iter(0), iter_Newton(0),
- E(0.0), iK(0), K(0.0), lnnorm(-100.0),
- base_id(0LL), type_id(0LL), id(0LL), maxid(offsets.maxid), nparticles(0)
- {
- }
-
- ODSLF_Bethe_State::ODSLF_Bethe_State (const Heis_Chain& RefChain, const ODSLF_Base& RefBase)
- : chain(RefChain), base(RefBase), offsets(RefBase, 0LL),
- Ix2(ODSLF_Ix2_Config(RefChain, RefBase)), lambda(ODSLF_Lambda(RefChain, RefBase)),
- BE(ODSLF_Lambda(RefChain, RefBase)), diffsq(1.0), conv(0), iter(0), iter_Newton(0),
- E(0.0), iK(0), K(0.0), lnnorm(-100.0),
- base_id(RefBase.id), type_id(0LL), id(0LL), maxid(offsets.maxid), nparticles(0)
- {
- // Check that the number of rapidities is consistent with Mdown
- int Mcheck = 0;
- for (int i = 0; i < RefChain.Nstrings; ++i) Mcheck += base[i] * RefChain.Str_L[i];
- if (RefBase.Mdown != Mcheck)
- ABACUSerror("Wrong M from Nrapidities input vector, in ODSLF_Bethe_State constructor.");
-
- }
-
- ODSLF_Bethe_State::ODSLF_Bethe_State (const Heis_Chain& RefChain,
- long long int base_id_ref, long long int type_id_ref)
- : chain(RefChain), base(ODSLF_Base(RefChain, base_id_ref)), offsets(base, type_id_ref),
- Ix2(ODSLF_Ix2_Config(RefChain, base)), lambda(ODSLF_Lambda(RefChain, base)),
- BE(ODSLF_Lambda(RefChain, base)), diffsq(1.0), conv(0), iter(0), iter_Newton(0),
- E(0.0), iK(0), K(0.0), lnnorm(-100.0),
- base_id(base_id_ref), type_id(type_id_ref), id(0LL), maxid(offsets.maxid), nparticles(0)
- {
- }
-
- void ODSLF_Bethe_State::Set_Ix2_Offsets (const ODSLF_Ix2_Offsets& RefOffset) // sets the Ix2 to given offsets
- {
- if (base != RefOffset.base)
- ABACUSerror("Offset with incompatible base used in ODSLF_Bethe_State::Set_Ix2_Offsets.");
-
- // For each base_level, we make sure that the Ix2 are ordered: Ix2[0][j] < Ix2[0][k] if j < k.
-
- // Level 2: particles in R part outside GS interval
- for (int j = 0; j < RefOffset.Tableau[2].Nrows; ++j) {
- Ix2[0][base.Nrap[0] - 1 - j]
- = base.Nrap[0] - 1 + 2* RefOffset.Tableau[2].Nrows - 2*j + 2*RefOffset.Tableau[2].Row_L[j];
- }
- nparticles = RefOffset.Tableau[2].Nrows;
-
- // Level 0: holes in R part of GS interval
- for (int j = 0; j < RefOffset.Tableau[0].Ncols; ++j) {
- Ix2[0][base.Nrap[0] - 1 - RefOffset.Tableau[2].Nrows - j] = (base.Nrap[0] + 1) % 2
- + 2*RefOffset.Tableau[0].Ncols - 2 - 2*j + 2*RefOffset.Tableau[0].Col_L[j];
- }
- nparticles += RefOffset.Tableau[0].Ncols;
-
- // Level 1: holes in L part of GS interval
- for (int j = 0; j < RefOffset.Tableau[1].Ncols; ++j) {
- Ix2[0][base.Nrap[0] - 1 - RefOffset.Tableau[0].Ncols - RefOffset.Tableau[2].Nrows - j]
- = -1 - (base.Nrap[0] % 2) - 2* j - 2*RefOffset.Tableau[1].Col_L[RefOffset.Tableau[1].Ncols - 1 - j];
- }
- nparticles += RefOffset.Tableau[1].Ncols;
-
- // Level 3: particles in L part outside GS interval
- for (int j = 0; j < RefOffset.Tableau[3].Nrows; ++j) {
- Ix2[0][base.Nrap[0] - 1 - RefOffset.Tableau[0].Ncols - RefOffset.Tableau[1].Ncols - RefOffset.Tableau[2].Nrows - j]
- = -(base.Nrap[0] + 1 + 2*j + 2*RefOffset.Tableau[3].Row_L[RefOffset.Tableau[3].Nrows - 1 - j]);
- }
- nparticles += RefOffset.Tableau[3].Nrows;
-
- // Subsequent levels: particles on R and L
- for (int base_level = 1; base_level < base.Nrap.size(); ++base_level) {
-
- for (int j = 0; j < RefOffset.Tableau[2*base_level + 2].Nrows; ++j)
- Ix2[base_level][base.Nrap[base_level] - 1 - j]
- = ((base.Nrap[base_level] + 1) % 2) + 2*(RefOffset.Tableau[2*base_level + 2].Nrows - 1) -2*j
- + 2*RefOffset.Tableau[2*base_level + 2].Row_L[j];
-
- nparticles += RefOffset.Tableau[2*base_level + 2].Nrows;
-
- for (int j = 0; j < RefOffset.Tableau[2*base_level + 3].Nrows; ++j)
- Ix2[base_level][base.Nrap[base_level] - 1 - RefOffset.Tableau[2*base_level + 2].Nrows - j]
- = -1 - ((base.Nrap[base_level]) % 2) -2*j
- - 2*RefOffset.Tableau[2*base_level + 3].Row_L[RefOffset.Tableau[2*base_level + 3].Nrows - 1 - j];
-
- nparticles += RefOffset.Tableau[2*base_level + 3].Nrows;
- }
-
- // ODSLF: put back correct parity of quantum nr:
- for (int j = 0; j < base.Nrap.size(); ++j)
- for (int alpha = 0; alpha < base[j]; ++alpha)
- if ((Ix2[j][alpha] + chain.Nsites - 1 + base.Nrap[j] + (base.Nraptot + 1) * chain.Str_L[j]
- + (chain.par[j] == 1 ? 0 : chain.Nsites)) % 2)
- Ix2[j][alpha] -= 1;
-
- type_id = RefOffset.type_id;
- id = RefOffset.id;
- maxid = RefOffset.maxid;
-
- return;
- }
-
- void ODSLF_Bethe_State::Set_to_id (long long int id_ref)
- {
- offsets.Set_to_id (id_ref);
- (*this).Set_Ix2_Offsets (offsets);
- }
-
- void ODSLF_Bethe_State::Set_to_id (long long int id_ref, ODSLF_Bethe_State& RefState)
- {
- offsets.Set_to_id (id_ref);
- (*this).Set_Ix2_Offsets (offsets);
- }
-
- bool ODSLF_Bethe_State::Check_Symmetry ()
- {
- // Checks whether the I's are symmetrically distributed.
- bool symmetric_state = true;
- int arg, test1, test3;
-
- for (int j = 0; j < chain.Nstrings; ++j) {
- test1 = 0;
- test3 = 0;
- for (int alpha = 0; alpha < base[j]; ++alpha) {
- // since Ix2 = N is same as Ix2 = -N by periodicity, this is symmetric.
- arg = (Ix2[j][alpha] != chain.Nsites) ? Ix2[j][alpha] : 0;
- test1 += arg;
- test3 += arg * arg * arg; // to make sure that all I's are symmetrical...
- }
- if (!(symmetric_state && (test1 == 0) && (test3 == 0))) symmetric_state = false;
- }
-
- return symmetric_state;
- }
-
- void ODSLF_Bethe_State::Compute_diffsq ()
- {
- DP maxterm = 0.0;
- int jmax, alphamax;
-
- diffsq = 0.0;
- for (int j = 0; j < chain.Nstrings; ++j)
- for (int alpha = 0; alpha < base[j]; ++alpha) {
- diffsq += pow(BE[j][alpha], 2.0);
- if (pow(BE[j][alpha], 2.0)/chain.Nsites > maxterm) {
- jmax = j;
- alphamax = alpha;
- maxterm = pow(BE[j][alpha], 2.0)/chain.Nsites;
- }
- }
- diffsq /= DP(chain.Nsites);
- }
-
- void ODSLF_Bethe_State::Iterate_BAE ()
- {
- for (int j = 0; j < chain.Nstrings; ++j) {
- for (int alpha = 0; alpha < base[j]; ++alpha)
- {
- lambda[j][alpha] = Iterate_BAE (j, alpha);
- }
- }
-
- iter++;
-
- (*this).Compute_BE();
- (*this).Compute_diffsq();
- }
-
- void ODSLF_Bethe_State::BAE_smackdown (DP max_allowed)
- {
- // Re-solves for all rapidities lambda[j][alpha] such that BE[j][alpha]^2/N > max_allowed.
- // Assumes that BE[][] is up-to-date.
-
- for (int j = 0; j < chain.Nstrings; ++j)
- for (int alpha = 0; alpha < base[j]; ++alpha)
- if (pow(BE[j][alpha], 2.0)/chain.Nsites > max_allowed) (*this).Solve_BAE (j, alpha, max_allowed, 100);
- }
-
- void ODSLF_Bethe_State::Solve_BAE_smackdown (DP max_allowed, int maxruns)
- {
- int runs_done = 0;
-
- (*this).Compute_BE();
- (*this).Compute_diffsq();
-
- while (diffsq > chain.prec && diffsq > max_allowed && runs_done < maxruns) {
- (*this).BAE_smackdown (max_allowed);
- (*this).Compute_BE();
- (*this).Compute_diffsq();
- runs_done++;
- }
- }
-
- void ODSLF_Bethe_State::Iterate_BAE_Newton ()
- {
- // does one step of a Newton method on the rapidities...
- // Assumes that BE[j][alpha] have been computed
-
- Vect_CX dlambda (0.0, base.Nraptot); // contains delta lambda computed from Newton's method
- SQMat_CX Gaudin (0.0, base.Nraptot);
- Vect_INT indx (base.Nraptot);
-
- ODSLF_Lambda lambda_ref(chain, base);
- for (int j = 0; j < chain.Nstrings; ++j)
- for (int alpha = 0; alpha < base[j]; ++alpha) lambda_ref[j][alpha] = lambda[j][alpha];
-
- (*this).Build_Reduced_Gaudin_Matrix (Gaudin);
-
- int index = 0;
- for (int j = 0; j < chain.Nstrings; ++j)
- for (int alpha = 0; alpha < base[j]; ++alpha) {
- dlambda[index] = - BE[j][alpha] * chain.Nsites;
- index++;
- }
-
- DP d;
-
- try {
- ludcmp_CX (Gaudin, indx, d);
- lubksb_CX (Gaudin, indx, dlambda);
- }
-
- catch (Divide_by_zero) {
- diffsq = log(-1.0); // reset to nan to stop Newton method
- return;
- }
-
- // Regularize dlambda: max step is +-1.0 to prevent rapidity flying off into outer space.
- for (int i = 0; i < base.Nraptot; ++i) if (fabs(real(dlambda[i])) > 1.0) dlambda[i] = 0.0;
-
- index = 0;
- for (int j = 0; j < chain.Nstrings; ++j)
- for (int alpha = 0; alpha < base[j]; ++alpha) {
- lambda[j][alpha] = lambda_ref[j][alpha] + real(dlambda[index]);
- index++;
- }
-
- (*this).Compute_BE();
- (*this).Iterate_BAE();
- (*this).Compute_diffsq();
-
- // if we've converged, calculate the norm here, since the work has been done...
- if (diffsq < chain.prec) {
- lnnorm = 0.0;
- for (int j = 0; j < base.Nraptot; j++) lnnorm += log(abs(Gaudin[j][j]));
- }
-
- iter_Newton++;
-
- return;
- }
-
- void ODSLF_Bethe_State::Solve_BAE (int j, int alpha, DP req_prec, int itermax)
- {
- // Finds the root lambda[j][alpha] to precision req_prec
-
- DP prec_obtained = 1.0;
- int niter_here = 0;
-
- while (prec_obtained > req_prec && niter_here < itermax) {
- lambda[j][alpha] = (*this).Iterate_BAE (j, alpha);
- (*this).Compute_BE (j, alpha);
- prec_obtained = pow(BE[j][alpha], 2.0)/chain.Nsites;
- niter_here++;
- }
- }
-
- void ODSLF_Bethe_State::Find_Rapidities (bool reset_rapidities)
- {
- // This function finds the rapidities of the eigenstate
-
- lnnorm = -100.0; // sentinel value, recalculated if Newton method used in the last step of iteration.
-
- ODSLF_Lambda lambda_ref(chain, base);
-
- diffsq = 1.0;
-
- if (reset_rapidities)
- (*this).Set_Free_lambdas();
- (*this).Compute_BE();
-
- iter = 0;
- iter_Newton = 0;
-
- // Start with conventional iterations
-
- DP iter_prec = 1.0e-2/DP(chain.Nsites);
-
- clock_t interp_start;
- clock_t interp_stop;
- clock_t Newton_start;
- clock_t Newton_stop;
- int iter_interp_start, iter_interp_stop, iter_Newton_start, iter_Newton_stop;
- DP diffsq_interp_start, diffsq_interp_stop, diffsq_Newton_start, diffsq_Newton_stop;
-
- while (diffsq > chain.prec && iter < 300 && iter_Newton < 20) {
-
- do {
- interp_start = clock();
- iter_interp_start = iter;
- diffsq_interp_start = diffsq;
-
- if (diffsq > iter_prec) (*this).Solve_BAE_interp (iter_prec, 10);
-
- interp_stop = clock();
- iter_interp_stop = iter;
- diffsq_interp_stop = diffsq;
-
- iter_prec = diffsq * 0.001;
-
- } while (diffsq > chain.prec && !is_nan(diffsq) && diffsq_interp_stop/diffsq_interp_start < 0.001);
-
- // If we haven't even reached iter_prec, try normal iterations without extrapolations
- if (diffsq > iter_prec) {
- (*this).Solve_BAE_smackdown (0.1 * diffsq, 1);
- }
-
- // Now try Newton
-
- Newton_start = clock();
- iter_Newton_start = iter_Newton;
- diffsq_Newton_start = diffsq;
-
- if (diffsq > iter_prec) (*this).Solve_BAE_Newton (chain.prec, 5);
-
- Newton_stop = clock();
- iter_Newton_stop = iter_Newton;
- diffsq_Newton_stop = diffsq;
-
- if (diffsq > iter_prec) (*this).Solve_BAE_smackdown (0.1 * diffsq, 1);
-
- if (diffsq > iter_prec) (*this).Solve_BAE_straight_iter (0.1 * diffsq, 50);
-
- // If we haven't converged here, retry with more precision in interp method...
-
- if (is_nan(diffsq)) {
- (*this).Set_Free_lambdas(); // good start if we've messed up with Newton
- diffsq = 1.0;
- }
-
- iter_prec *= 1.0e-4;
- iter_prec = ABACUS::max(iter_prec, chain.prec);
-
- }
-
- // Check convergence:
- conv = (diffsq < chain.prec && (*this).Check_Rapidities()) ? 1 : 0;
-
- return;
- }
-
- void ODSLF_Bethe_State::Solve_BAE_Newton (DP Newton_prec, int max_iter_Newton)
- {
- // This function attempts to get convergence diffsq <= Newton_prec in at most max_iter_Newton steps.
-
- // The results are accepted if diffsq has decreased, otherwise the lambda's are reset to original values, defined as...
-
- ODSLF_Lambda lambda_ref(chain, base);
- DP diffsq_ref = 1.0;
-
- for (int j = 0; j < chain.Nstrings; ++j)
- for (int alpha = 0; alpha < base[j]; ++alpha) lambda_ref[j][alpha] = lambda[j][alpha];
- diffsq_ref = diffsq;
-
- // Now begin solving...
-
- int iter_done_here = 0;
-
- while ((diffsq > Newton_prec) && (diffsq < 10.0) && (!is_nan(diffsq)) && (iter_done_here < max_iter_Newton)) {
- (*this).Iterate_BAE_Newton();
- iter_done_here++;
- (*this).Iterate_BAE();
- }
-
- if ((diffsq > diffsq_ref) || (is_nan(diffsq))) {
- // This procedure has failed. We reset everything to begin values.
- for (int j = 0; j < chain.Nstrings; ++j)
- for (int alpha = 0; alpha < base[j]; ++alpha) lambda[j][alpha] = lambda_ref[j][alpha];
- diffsq = diffsq_ref;
- }
-
- return;
- }
-
- void ODSLF_Bethe_State::Solve_BAE_straight_iter (DP interp_prec, int max_iter_interp)
- {
- // This function attempts to get convergence diffsq <= interp_prec in at most max_iter_interp steps.
-
- // If this fails, the lambda's are reset to original values, defined as...
-
- ODSLF_Lambda lambda_ref(chain, base);
- DP diffsq_ref = 1.0;
-
- for (int j = 0; j < chain.Nstrings; ++j)
- for (int alpha = 0; alpha < base[j]; ++alpha) lambda_ref[j][alpha] = lambda[j][alpha];
- diffsq_ref = diffsq;
-
- // Now begin solving...
-
- diffsq = 1.0;
- int iter_done_here = 0;
-
- while ((diffsq > interp_prec) && (max_iter_interp > iter_done_here)) {
- (*this).Iterate_BAE();
- iter_done_here++;
- }
-
- if ((diffsq > diffsq_ref)) {
- // This procedure has failed. We reset everything to begin values.
- for (int j = 0; j < chain.Nstrings; ++j)
- for (int alpha = 0; alpha < base[j]; ++alpha) lambda[j][alpha] = lambda_ref[j][alpha];
- diffsq = diffsq_ref;
- }
- }
-
- void ODSLF_Bethe_State::Solve_BAE_interp (DP interp_prec, int max_iter_interp)
- {
- // This function attempts to get convergence diffsq <= interp_prec in at most max_iter_interp steps.
-
- // If this fails, the lambda's are reset to original values, defined as...
-
- ODSLF_Lambda lambda_ref(chain, base);
- DP diffsq_ref = 1.0;
-
- for (int j = 0; j < chain.Nstrings; ++j)
- for (int alpha = 0; alpha < base[j]; ++alpha) lambda_ref[j][alpha] = lambda[j][alpha];
- diffsq_ref = diffsq;
-
- // Now begin solving...
-
- diffsq = 1.0;
- int iter_done_here = 0;
-
- ODSLF_Lambda lambda1(chain, base);
- ODSLF_Lambda lambda2(chain, base);
- ODSLF_Lambda lambda3(chain, base);
- ODSLF_Lambda lambda4(chain, base);
- ODSLF_Lambda lambda5(chain, base);
-
- while ((diffsq > interp_prec) && (max_iter_interp > iter_done_here)) {
-
- (*this).Iterate_BAE();
- for (int j = 0; j < chain.Nstrings; ++j)
- for (int alpha = 0; alpha < base[j]; ++alpha) lambda1[j][alpha] = lambda[j][alpha];
- (*this).Iterate_BAE();
- for (int j = 0; j < chain.Nstrings; ++j)
- for (int alpha = 0; alpha < base[j]; ++alpha) lambda2[j][alpha] = lambda[j][alpha];
- (*this).Iterate_BAE();
- for (int j = 0; j < chain.Nstrings; ++j)
- for (int alpha = 0; alpha < base[j]; ++alpha) lambda3[j][alpha] = lambda[j][alpha];
- (*this).Iterate_BAE();
- for (int j = 0; j < chain.Nstrings; ++j)
- for (int alpha = 0; alpha < base[j]; ++alpha) lambda4[j][alpha] = lambda[j][alpha];
-
- iter_done_here += 4;
-
- // now extrapolate the result to infinite number of iterations...
-
- Vect_DP rap(0.0, 4);
- Vect_DP oneoverP(0.0, 4);
- DP deltalambda = 0.0;
-
- for (int i = 0; i < 4; ++i) oneoverP[i] = 1.0/(1.0 + i*i);
-
- for (int j = 0; j < chain.Nstrings; ++j) for (int alpha = 0; alpha < base[j]; ++alpha) {
- rap[0] = lambda1[j][alpha];
- rap[1] = lambda2[j][alpha];
- rap[2] = lambda3[j][alpha];
- rap[3] = lambda4[j][alpha];
-
- polint (oneoverP, rap, 0.0, lambda[j][alpha], deltalambda);
- }
-
- (*this).Iterate_BAE();
- }
-
- if ((diffsq >= diffsq_ref)) {
- // This procedure has failed. We reset everything to begin values.
- for (int j = 0; j < chain.Nstrings; ++j)
- for (int alpha = 0; alpha < base[j]; ++alpha) lambda[j][alpha] = lambda_ref[j][alpha];
- diffsq = diffsq_ref;
- }
-
- return;
- }
-
- void ODSLF_Bethe_State::Compute_lnnorm ()
- {
- if (true || lnnorm == -100.0) { // else norm already calculated by Newton method
- // Actually, compute anyway to increase accuracy !
-
- SQMat_CX Gaudin_Red(base.Nraptot);
-
- (*this).Build_Reduced_Gaudin_Matrix(Gaudin_Red);
- complex<DP> lnnorm_check = lndet_LU_CX_dstry(Gaudin_Red);
- lnnorm = real(lnnorm_check);
- }
-
- return;
- }
-
- void ODSLF_Bethe_State::Compute_Momentum ()
- {
- int sum_Ix2 = 0;
- DP sum_M = 0.0;
-
- for (int j = 0; j < chain.Nstrings; ++j) {
- sum_M += 0.5 * (1.0 + chain.par[j]) * base[j];
- for (int alpha = 0; alpha < base[j]; ++alpha) {
- sum_Ix2 += Ix2[j][alpha];
- }
- }
-
- iK = (chain.Nsites/2) * int(sum_M + 0.1) - (sum_Ix2/2); // + 0.1: for safety...
-
- while (iK >= chain.Nsites) iK -= chain.Nsites;
- while (iK < 0) iK += chain.Nsites;
-
- K = PI * sum_M - PI * sum_Ix2/chain.Nsites;
-
- while (K >= 2.0*PI) K -= 2.0*PI;
- while (K < 0.0) K += 2.0*PI;
-
- return;
- }
-
- void ODSLF_Bethe_State::Compute_All (bool reset_rapidities) // solves BAE, computes E, K and lnnorm
- {
- (*this).Find_Rapidities (reset_rapidities);
- if (conv == 1) {
- (*this).Compute_Energy ();
- (*this).Compute_Momentum ();
- (*this).Compute_lnnorm ();
- }
- return;
- }
-
- bool ODSLF_Bethe_State::Boost_Momentum (int iKboost)
- {
- if (iKboost == 0) return(true); // done
-
- ODSLF_Ix2_Offsets offsets_here = offsets;
-
- bool success = false;
-
- if (iKboost < 0)
- success = offsets_here.Add_Boxes_From_Lowest(-iKboost, 0); // add boxes in even sectors to decrease iK
-
- else if (iKboost > 0)
- success = offsets_here.Add_Boxes_From_Lowest(iKboost, 1); // add boxes in odd sectors to increase iK
-
- if (success) (*this).Set_Ix2_Offsets(offsets_here);
-
- return(success);
- }
-
-
- std::ostream& operator<< (std::ostream& s, const ODSLF_Bethe_State& state)
- {
- // sends all the state data to output stream
-
- s << endl << "******** Chain with Nsites = " << state.chain.Nsites
- << " Mdown (nr fermions) = " << state.base.Mdown
- << ": eigenstate with base_id " << state.base_id << ", type_id " << state.type_id
- << " id " << state.id << " maxid " << state.offsets.maxid << endl
- << "E = " << state.E << " K = " << state.K << " iK = " << state.iK
- << " lnnorm = " << state.lnnorm << endl
- << "conv = " << state.conv << " iter = " << state.iter
- << " iter_Newton = " << state.iter_Newton << "\tdiffsq " << state.diffsq << endl;
-
- for (int j = 0; j < state.chain.Nstrings; ++j) {
- if (state.base.Nrap[j] > 0) {
- s << "Type " << j << " Str_L = " << state.chain.Str_L[j]
- << " par = " << state.chain.par[j] << " M_j = " << state.base.Nrap[j]
- << " Ix2_infty = " << state.base.Ix2_infty[j] << " Ix2_max = " << state.base.Ix2_max[j] << endl;
- Vect_INT qnumbers(state.base.Nrap[j]);
- Vect_DP rapidities(state.base.Nrap[j]);
- for (int alpha = 0; alpha < state.base.Nrap[j]; ++alpha) {
- qnumbers[alpha] = state.Ix2[j][alpha];
- rapidities[alpha] = state.lambda[j][alpha];
- }
- qnumbers.QuickSort();
- rapidities.QuickSort();
-
- s << "Ix2 quantum numbers: " << endl;
- for (int alpha = 0; alpha < state.base.Nrap[j]; ++alpha) s << qnumbers[alpha] << " ";
- s << endl;
- s << "Rapidities: " << endl;
- for (int alpha = 0; alpha < state.base.Nrap[j]; ++alpha) s << rapidities[alpha] << " ";
- s << endl;
- }
- }
- s << endl;
-
- return s;
-
- }
-
- } // namespace ABACUS
|