123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646 |
- /**********************************************************
-
- This software is part of J.-S. Caux's ABACUS library.
-
- Copyright (c)
-
- -----------------------------------------------------------
-
- File: src/HEIS/XXZ_Bethe_State.cc
-
- Purpose: Defines all functions for XXZ_Bethe_State
-
- ******************************************************************/
-
- #include "ABACUS.h"
-
- using namespace std;
-
- namespace ABACUS {
-
- // Function prototypes
-
- inline DP fbar_XXZ (DP lambda, int par, DP tannzetaover2);
- DP Theta_XXZ (DP lambda, int nj, int nk, int parj, int park, DP* tannzetaover2);
- DP hbar_XXZ (DP lambda, int n, int par, DP* si_n_anis_over_2);
- DP ddlambda_Theta_XXZ (DP lambda, int nj, int nk, int parj, int park, DP* si_n_anis_over_2);
-
-
- //***************************************************************************************************
-
- // Function definitions: class XXZ_Bethe_State
-
- XXZ_Bethe_State::XXZ_Bethe_State ()
- : Heis_Bethe_State(), sinhlambda(Lambda(chain, 1)), coshlambda(Lambda(chain, 1)), tanhlambda(Lambda(chain, 1))
- {};
-
- XXZ_Bethe_State::XXZ_Bethe_State (const XXZ_Bethe_State& RefState) // copy constructor
- : Heis_Bethe_State(RefState), sinhlambda(Lambda(RefState.chain, RefState.base)), coshlambda(Lambda(RefState.chain, RefState.base)),
- tanhlambda(Lambda(RefState.chain, RefState.base))
- {
- // copy arrays into new ones
-
- //cout << "Calling XXZ state copy constructor." << endl;
- for (int j = 0; j < RefState.chain.Nstrings; ++j) {
- for (int alpha = 0; alpha < RefState.base[j]; ++j) {
- sinhlambda[j][alpha] = RefState.sinhlambda[j][alpha];
- coshlambda[j][alpha] = RefState.coshlambda[j][alpha];
- tanhlambda[j][alpha] = RefState.tanhlambda[j][alpha];
- }
- }
- //cout << "Done calling XXZ state copy constructor." << endl;
- }
-
- XXZ_Bethe_State::XXZ_Bethe_State (const Heis_Chain& RefChain, int M)
- : Heis_Bethe_State(RefChain, M),
- sinhlambda(Lambda(RefChain, M)), coshlambda(Lambda(RefChain, M)), tanhlambda(Lambda(RefChain, M))
- {
- //cout << "Here in XXZ BS constructor." << endl;
- //cout << (*this).lambda[0][0] << endl;
- //cout << "OK" << endl;
- if ((RefChain.Delta <= -1.0) || (RefChain.Delta >= 1.0)) ABACUSerror("Delta out of range in XXZ_Bethe_State constructor");
- }
-
- XXZ_Bethe_State::XXZ_Bethe_State (const Heis_Chain& RefChain, const Heis_Base& RefBase)
- : Heis_Bethe_State(RefChain, RefBase),
- sinhlambda(Lambda(RefChain, RefBase)), coshlambda(Lambda(RefChain, RefBase)), tanhlambda(Lambda(RefChain, RefBase))
- {
- if ((RefChain.Delta <= -1.0) || (RefChain.Delta >= 1.0)) ABACUSerror("Delta out of range in XXZ_Bethe_State constructor");
- }
- /*
- XXZ_Bethe_State::XXZ_Bethe_State (const Heis_Chain& RefChain, long long int base_id_ref, long long int type_id_ref)
- : Heis_Bethe_State(RefChain, base_id_ref, type_id_ref),
- sinhlambda(Lambda(chain, base)), coshlambda(Lambda(chain, base)), tanhlambda(Lambda(chain, base))
- {
- if ((RefChain.Delta <= -1.0) || (RefChain.Delta >= 1.0)) ABACUSerror("Delta out of range in XXZ_Bethe_State constructor");
- }
- */
-
- XXZ_Bethe_State& XXZ_Bethe_State::operator= (const XXZ_Bethe_State& RefState)
- {
- if (this != &RefState) {
- chain = RefState.chain;
- base = RefState.base;
- //offsets = RefState.offsets;
- Ix2 = RefState.Ix2;
- lambda = RefState.lambda;
- BE = RefState.BE;
- 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;
- label = RefState.label;
-
- sinhlambda = RefState.sinhlambda;
- coshlambda = RefState.coshlambda;
- tanhlambda = RefState.tanhlambda;
- }
- return(*this);
- }
-
- // Member functions
-
- void XXZ_Bethe_State::Set_Free_lambdas()
- {
- // Sets all the rapidities to the solutions of the BAEs without scattering terms
-
- DP x = 0.0;
- for (int i = 0; i < chain.Nstrings; ++i) {
-
- for (int alpha = 0; alpha < base[i]; ++alpha) {
-
- if (chain.par[i] == 1) {
- //lambda[i][alpha] = atanh(tan(chain.Str_L[i] * 0.5 * chain.anis) * tan(PI * 0.5 * Ix2[i][alpha]/chain.Nsites));
- x = tan(chain.Str_L[i] * 0.5 * chain.anis) * tan(PI * 0.5 * Ix2[i][alpha]/chain.Nsites);
- lambda[i][alpha] = atanh(x/sqrt(1.0 + x*x)); // lambda then always initiated real
- }
-
- else if (chain.par[i] == -1) {
- //lambda[i][alpha] = atanh(-tan(PI * 0.5 * Ix2[i][alpha]/chain.Nsites)/tan(chain.Str_L[i] * 0.5 * chain.anis));
- x = -tan(PI * 0.5 * Ix2[i][alpha]/chain.Nsites)/tan(chain.Str_L[i] * 0.5 * chain.anis);
- lambda[i][alpha] = atanh(x/sqrt(1.0 + x*x)); // lambda then always initiated real
- }
-
- else ABACUSerror("Invalid parities in Set_Free_lambdas.");
- //cout << tan(chain.Str_L[i] * 0.5 * chain.anis) << endl;
- //cout << "Set_Free_lambdas: " << i << "\t" << alpha << "\t" << lambda[i][alpha] << "\t" << tan(chain.Str_L[i] * 0.5 * chain.anis) * tan(PI * 0.5 * Ix2[i][alpha]/chain.Nsites) << endl;
-
- }
- }
-
- return;
- }
-
- void XXZ_Bethe_State::Compute_sinhlambda()
- {
- for (int j = 0; j < chain.Nstrings; ++j) {
-
- for (int alpha = 0; alpha < base[j]; ++alpha) sinhlambda[j][alpha] = sinh(lambda[j][alpha]);
- }
- return;
- }
-
- void XXZ_Bethe_State::Compute_coshlambda()
- {
- for (int j = 0; j < chain.Nstrings; ++j) {
-
- for (int alpha = 0; alpha < base[j]; ++alpha) coshlambda[j][alpha] = cosh(lambda[j][alpha]);
- }
- return;
- }
-
- void XXZ_Bethe_State::Compute_tanhlambda()
- {
- for (int j = 0; j < chain.Nstrings; ++j) {
-
- for (int alpha = 0; alpha < base[j]; ++alpha) tanhlambda[j][alpha] = tanh(lambda[j][alpha]);
- }
- return;
- }
-
- bool XXZ_Bethe_State::Check_Admissibility(char option)
- {
- // This function checks the admissibility of the Ix2's of a state:
- // returns false if there are higher strings with Ix2 = 0, a totally symmetric distribution of I's at each level,
- // and strings of equal length modulo 2 and parity with Ix2 = 0, meaning at least two equal roots in BAE.
-
- bool answer = true;
- Vect<bool> Zero_at_level(false, chain.Nstrings); // whether there exists an Ix2 == 0 at a given level
-
- bool higher_string_on_zero = false;
- for (int j = 0; j < chain.Nstrings; ++j) {
- // The following line puts answer to true if there is at least one higher string with zero Ix2
- for (int alpha = 0; alpha < base[j]; ++alpha) if ((Ix2[j][alpha] == 0) && (chain.Str_L[j] >= 2) /*&& !(chain.Str_L[j] % 2)*/)
- higher_string_on_zero = true;
- for (int alpha = 0; alpha < base[j]; ++alpha) if (Ix2[j][alpha] == 0) Zero_at_level[j] = true;
- // NOTE: if base[j] == 0, Zero_at_level[j] remains false.
- }
-
- // check symmetry of Ix2 at each level, if there exists a potentially risky Ix2...
-
- bool symmetric_state = (*this).Check_Symmetry();
-
- bool string_coincidence = false;
- for (int j1 = 0; j1 < chain.Nstrings; ++j1) {
- for (int j2 = j1 + 1; j2 < chain.Nstrings; ++j2)
- if (Zero_at_level[j1] && Zero_at_level[j2] && (chain.par[j1] == chain.par[j2]) && (!((chain.Str_L[j1] + chain.Str_L[j2])%2)))
- string_coincidence = true;
- }
-
- bool M_odd_and_onep_on_zero = false;
- if (option == 'z') { // for Sz, if M is odd, exclude symmetric states with a 1+ on zero
- // (zero rapidities in left and right states, so FF det not defined).
- bool is_ground_state = base.Nrap[0] == base.Mdown && Ix2[0][0] == -(base.Mdown - 1) && Ix2[0][base.Mdown-1] == base.Mdown - 1;
- if (Zero_at_level[0] && (base.Mdown % 2) && !is_ground_state) M_odd_and_onep_on_zero = true;
- }
-
- bool onep_onem_on_zero = false;
- if (option == 'm' || option == 'p') { // for Smin, we also exclude symmetric states with 1+ and 1- strings on zero
- if (Zero_at_level[0] && Zero_at_level[1]) onep_onem_on_zero = true;
- }
-
- answer = !(symmetric_state && (higher_string_on_zero || string_coincidence || onep_onem_on_zero || M_odd_and_onep_on_zero));
-
- // Now check that no Ix2 is equal to +N (since we take -N into account, and I + N == I by periodicity of exp)
-
- for (int j = 0; j < chain.Nstrings; ++j)
- for (int alpha = 0; alpha < base[j]; ++alpha) if ((Ix2[j][alpha] < -chain.Nsites) || (Ix2[j][alpha] >= chain.Nsites)) answer = false;
-
- if (!answer) {
- E = 0.0;
- K = 0.0;
- conv = 0;
- iter = 0;
- iter_Newton = 0;
- lnnorm = -100.0;
- }
-
- return(answer); // answer == true: nothing wrong with this Ix2_config
- }
-
- void XXZ_Bethe_State::Compute_BE (int j, int alpha)
- {
- tanhlambda[j][alpha] = tanh(lambda[j][alpha]);
-
- DP sumtheta = 0.0;
-
- for (int k = 0; k < chain.Nstrings; ++k)
- for (int beta = 0; beta < base[k]; ++beta) {
- if ((chain.Str_L[j] == 1) && (chain.Str_L[k] == 1))
- sumtheta += (chain.par[j] == chain.par[k])
- ? atan((tanhlambda[j][alpha] - tanhlambda[k][beta])/((1.0 - tanhlambda[j][alpha] * tanhlambda[k][beta]) * chain.ta_n_anis_over_2[2]))
- : - atan(((tanhlambda[j][alpha] - tanhlambda[k][beta])/(1.0 - tanhlambda[j][alpha] * tanhlambda[k][beta])) * chain.ta_n_anis_over_2[2]) ;
- else sumtheta += 0.5 * Theta_XXZ((tanhlambda[j][alpha] - tanhlambda[k][beta])/(1.0 - tanhlambda[j][alpha] * tanhlambda[k][beta]),
- chain.Str_L[j], chain.Str_L[k], chain.par[j], chain.par[k], chain.ta_n_anis_over_2);
- }
- sumtheta *= 2.0;
-
- BE[j][alpha] = ((chain.par[j] == 1) ? 2.0 * atan(tanhlambda[j][alpha]/chain.ta_n_anis_over_2[chain.Str_L[j]])
- : -2.0 * atan(tanhlambda[j][alpha] * chain.ta_n_anis_over_2[chain.Str_L[j]])) - (sumtheta + PI*Ix2[j][alpha])/chain.Nsites;
-
- }
-
- void XXZ_Bethe_State::Compute_BE ()
- {
- // Fills in the BE members with the value of the Bethe equations.
-
- (*this).Compute_tanhlambda();
-
- DP sumtheta = 0.0;
-
- for (int j = 0; j < chain.Nstrings; ++j)
- for (int alpha = 0; alpha < base[j]; ++alpha) {
-
- sumtheta = 0.0;
- for (int k = 0; k < chain.Nstrings; ++k)
- for (int beta = 0; beta < base[k]; ++beta) {
- if ((chain.Str_L[j] == 1) && (chain.Str_L[k] == 1))
- sumtheta += (chain.par[j] == chain.par[k])
- ? atan((tanhlambda[j][alpha] - tanhlambda[k][beta])/((1.0 - tanhlambda[j][alpha] * tanhlambda[k][beta]) * chain.ta_n_anis_over_2[2]))
- : - atan(((tanhlambda[j][alpha] - tanhlambda[k][beta])/(1.0 - tanhlambda[j][alpha] * tanhlambda[k][beta])) * chain.ta_n_anis_over_2[2]) ;
- else sumtheta += 0.5 * Theta_XXZ((tanhlambda[j][alpha] - tanhlambda[k][beta])/(1.0 - tanhlambda[j][alpha] * tanhlambda[k][beta]),
- chain.Str_L[j], chain.Str_L[k], chain.par[j], chain.par[k], chain.ta_n_anis_over_2);
- }
- sumtheta *= 2.0;
-
- BE[j][alpha] = ((chain.par[j] == 1) ? 2.0 * atan(tanhlambda[j][alpha]/chain.ta_n_anis_over_2[chain.Str_L[j]])
- : -2.0 * atan(tanhlambda[j][alpha] * chain.ta_n_anis_over_2[chain.Str_L[j]])) - (sumtheta + PI*Ix2[j][alpha])/chain.Nsites;
-
- //if (is_nan(BE[j][alpha])) cout << "BE nan: " << j << "\t" << alpha << "\t" << lambda[j][alpha] << "\t" << tanhlambda[j][alpha] << endl;
- }
- }
-
- DP XXZ_Bethe_State::Iterate_BAE (int j, int alpha)
- {
- // Returns a new iteration value for lambda[j][alpha] given tanhlambda and BE Lambdas
- // Assumes that tanhlambda[][] and BE[][] have been computed.
-
- DP new_lambda = 0.0;
- DP arg = 0.0;
-
- if (chain.par[j] == 1) arg = chain.ta_n_anis_over_2[chain.Str_L[j]]
- * tan(0.5 *
- //(PI * Ix2[j][alpha] + sumtheta)/chain.Nsites
- (2.0 * atan(tanhlambda[j][alpha]/chain.ta_n_anis_over_2[chain.Str_L[j]]) - BE[j][alpha])
- );
-
- else if (chain.par[j] == -1) arg = -tan(0.5 *
- //(PI * Ix2[j][alpha] + sumtheta)/chain.Nsites)
- (-2.0 * atan(tanhlambda[j][alpha] * chain.ta_n_anis_over_2[chain.Str_L[j]]) - BE[j][alpha]))
- /chain.ta_n_anis_over_2[chain.Str_L[j]];
-
- if (fabs(arg) < 1.0) {
- new_lambda = atanh(arg);
- }
-
- else {
- new_lambda = lambda[j][alpha]; // back to drawing board...
- int block = 0; // counter to prevent runaway while loop
- DP new_tanhlambda = 0.0;
- DP sumtheta = 0.0;
- arg = 10.0; // reset value to start while loop
- while ((fabs(arg) > 1.0) && (block++ < 100)) { // recompute the diverging root on its own...
- new_lambda *= 1.01; // try to go slowly towards infinity...
- new_tanhlambda = tanh(new_lambda);
- sumtheta = 0.0;
- for (int k = 0; k < chain.Nstrings; ++k) {
- for (int beta = 0; beta < base[k]; ++beta)
- if ((chain.Str_L[j] == 1) && (chain.Str_L[k] == 1))
- sumtheta += (chain.par[j] == chain.par[k])
- ? atan((new_tanhlambda - tanhlambda[k][beta])/((1.0 - new_tanhlambda * tanhlambda[k][beta]) * chain.ta_n_anis_over_2[2]))
- : - atan(((new_tanhlambda - tanhlambda[k][beta])/(1.0 - new_tanhlambda * tanhlambda[k][beta])) * chain.ta_n_anis_over_2[2]) ;
- else sumtheta += 0.5 * Theta_XXZ((new_tanhlambda - tanhlambda[k][beta])/(1.0 - new_tanhlambda * tanhlambda[k][beta]),
- chain.Str_L[j], chain.Str_L[k], chain.par[j], chain.par[k], chain.ta_n_anis_over_2);
- }
- sumtheta *= 2.0;
- if (chain.par[j] == 1) arg = chain.ta_n_anis_over_2[chain.Str_L[j]] * tan(0.5 * (PI * Ix2[j][alpha] + sumtheta)/chain.Nsites);
-
- else if (chain.par[j] == -1) arg = -tan(0.5 * (PI * Ix2[j][alpha] + sumtheta)/chain.Nsites)/chain.ta_n_anis_over_2[chain.Str_L[j]];
-
- else ABACUSerror("Invalid parities in Iterate_BAE.");
-
- }
-
- if (fabs(arg) < 1.0) {
- new_lambda = atanh(arg);
- }
-
- //else cout << "Rapidity blows up !\t" << lambda[j][alpha] << "\t" << new_lambda << endl;
- } // else
-
- return(new_lambda);
- }
-
- bool XXZ_Bethe_State::Check_Rapidities()
- {
- bool nonan = true;
-
- for (int j = 0; j < chain.Nstrings; ++j)
- for (int alpha = 0; alpha < base[j]; ++alpha) nonan *= !is_nan(lambda[j][alpha]);
-
- return nonan;
- }
-
- DP XXZ_Bethe_State::String_delta ()
- {
- // Computes the sum of absolute value of \delta^{a, a+1} in string hypothesis, for a given bethe eigenstate
-
- DP delta = 0.0;
-
- int occupied_strings = 0;
- for (int i = 0; i < (*this).chain.Nstrings; ++i) if ((*this).chain.Str_L[i] > 1) occupied_strings += (*this).base.Nrap[i];
-
- //if ((*this).conv == 0) delta = 1.0;
-
- if (occupied_strings == 0) delta = 0.0;
-
- else {
-
- Vect_DP ln_deltadiff(0.0, 1000); // contains ln |delta^{a, a+1}|
- Vect_DP deltadiff(0.0, 1000); // contains |delta^{a, a+1}|
-
- complex<DP> log_BAE_reg = 0.0;
-
- for (int j = 0; j < (*this).chain.Nstrings; ++j) {
- for (int alpha = 0; alpha < (*this).base[j]; ++alpha) {
-
- ln_deltadiff = 0.0;
-
- for (int a = 1; a <= (*this).chain.Str_L[j]; ++a) {
-
- if ((*this).chain.Str_L[j] > 1) { // else the BAE are already 1
-
- log_BAE_reg = DP((*this).chain.Nsites) * log(sinh((*this).lambda[j][alpha]
- + 0.5 * II * (*this).chain.anis * ((*this).chain.Str_L[j] + 1.0 - 2.0 * a + 1.0)
- + 0.25 * II * PI * (1.0 - (*this).chain.par[j]))
- /sinh((*this).lambda[j][alpha] + 0.5 * II * (*this).chain.anis * ((*this).chain.Str_L[j] + 1.0 - 2.0 * a - 1.0)
- + 0.25 * II * PI * (1.0 - (*this).chain.par[j])));
-
- for (int k = 0; k < (*this).chain.Nstrings; ++k)
- for (int beta = 0; beta < (*this).base[k]; ++beta)
- for (int b = 1; b <= (*this).chain.Str_L[k]; ++b) {
- if ((j != k) || (alpha != beta) || (a != b - 1))
-
- log_BAE_reg += log(sinh(((*this).lambda[j][alpha] + 0.5 * II * (*this).chain.anis * ((*this).chain.Str_L[j] + 1.0 - 2.0 * a )
- + 0.25 * II * PI * (1.0 - (*this).chain.par[j]))
- - ((*this).lambda[k][beta] + 0.5 * II * (*this).chain.anis * ((*this).chain.Str_L[k] + 1.0 - 2.0 * b )
- + 0.25 * II * PI * (1.0 - (*this).chain.par[k])) - II * (*this).chain.anis));
-
- if ((j != k) || (alpha != beta) || (a != b + 1))
-
- log_BAE_reg -= log(sinh(((*this).lambda[j][alpha] + 0.5 * II * (*this).chain.anis * ((*this).chain.Str_L[j] + 1.0 - 2.0 * a )
- + 0.25 * II * PI * (1.0 - (*this).chain.par[j]))
- - ((*this).lambda[k][beta] + 0.5 * II * (*this).chain.anis * ((*this).chain.Str_L[k] + 1.0 - 2.0 * b )
- + 0.25 * II * PI * (1.0 - (*this).chain.par[k])) + II * (*this).chain.anis));
- }
-
- // The regular LHS of BAE is now defined. Now sum up the deltas...
-
- if (a == 1) ln_deltadiff[0] = - real(log_BAE_reg);
-
- else if (a < (*this).chain.Str_L[j]) ln_deltadiff[a - 1] = ln_deltadiff[a-2] - real(log_BAE_reg);
-
- else if (a == (*this).chain.Str_L[j]) ln_deltadiff[a-1] = real(log_BAE_reg);
-
- } // if ((*this).chain.Str_L[j] > 1)
-
- } // for (int a = 1; ...
-
- for (int a = 0; a < (*this).chain.Str_L[j]; ++a) {
- deltadiff[a] = ln_deltadiff[a] != 0.0 ? exp(ln_deltadiff[a]) : 0.0;
- delta += fabs(deltadiff[a]);
- }
-
- } // alpha sum
- } // j sum
-
- if (is_nan(delta)) delta = 1.0; // sentinel
-
- } // else
-
- return delta;
- }
-
-
- void XXZ_Bethe_State::Compute_Energy ()
- {
- DP sum = 0.0;
-
- for (int j = 0; j < chain.Nstrings; ++j) {
- for (int alpha = 0; alpha < base[j]; ++alpha) {
- sum += sin(chain.Str_L[j] * chain.anis) / (chain.par[j] * cosh(2.0 * lambda[j][alpha]) - cos(chain.Str_L[j] * chain.anis));
- }
- }
-
- sum *= - chain.J * sin(chain.anis);
-
- E = sum;
-
- return;
- }
-
- /*
- void XXZ_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 XXZ_Bethe_State::Build_Reduced_Gaudin_Matrix (SQMat<complex<DP> >& Gaudin_Red)
- {
-
- if (Gaudin_Red.size() != base.Nraptot) ABACUSerror("Passing matrix of wrong size in Build_Reduced_Gaudin_Matrix.");
-
- int index_jalpha;
- int index_kbeta;
-
- DP sum_hbar_XXZ = 0.0;
-
- DP sinzetasq = pow(sin(chain.anis), 2.0);
-
- (*this).Compute_sinhlambda();
- (*this).Compute_coshlambda();
-
- index_jalpha = 0;
- for (int j = 0; j < chain.Nstrings; ++j) {
- for (int alpha = 0; alpha < base[j]; ++alpha) {
- index_kbeta = 0;
- for (int k = 0; k < chain.Nstrings; ++k) {
- for (int beta = 0; beta < base[k]; ++beta) {
-
- if ((j == k) && (alpha == beta)) {
-
- sum_hbar_XXZ = 0.0;
-
- for (int kp = 0; kp < chain.Nstrings; ++kp) {
- for (int betap = 0; betap < base[kp]; ++betap) {
- if (!((j == kp) && (alpha == betap)))
- sum_hbar_XXZ
- += ddlambda_Theta_XXZ (lambda[j][alpha] - lambda[kp][betap], chain.Str_L[j], chain.Str_L[kp], chain.par[j], chain.par[kp],
- chain.si_n_anis_over_2);
- }
- }
-
- Gaudin_Red[index_jalpha][index_kbeta]
- = complex<DP> ( chain.Nsites * hbar_XXZ (lambda[j][alpha], chain.Str_L[j], chain.par[j], chain.si_n_anis_over_2) - sum_hbar_XXZ);
- }
-
- else {
- if ((chain.Str_L[j] == 1) && (chain.Str_L[k] == 1))
- Gaudin_Red[index_jalpha][index_kbeta] =
- complex<DP> ((chain.par[j] * chain.par[k] == 1)
- ? chain.si_n_anis_over_2[4]/(pow(sinhlambda[j][alpha] * coshlambda[k][beta]
- - coshlambda[j][alpha] * sinhlambda[k][beta], 2.0) + sinzetasq)
- : chain.si_n_anis_over_2[4]/(-pow(coshlambda[j][alpha] * coshlambda[k][beta]
- - sinhlambda[j][alpha] * sinhlambda[k][beta], 2.0) + sinzetasq) );
- else
- Gaudin_Red[index_jalpha][index_kbeta] = complex<DP> (ddlambda_Theta_XXZ (lambda[j][alpha] - lambda[k][beta], chain.Str_L[j], chain.Str_L[k],
- chain.par[j], chain.par[k], chain.si_n_anis_over_2));
- }
- index_kbeta++;
- }
- }
- index_jalpha++;
- }
- }
- return;
- }
-
- // ****************************************************************************************************
-
- // non-member functions
-
- inline DP fbar_XXZ (DP tanhlambda, int par, DP tannzetaover2)
- {
- DP result = 0.0;
-
- if (par == 1) result = 2.0 * atan(tanhlambda/tannzetaover2);
-
- else if (par == -1) result = -2.0 * atan(tanhlambda * tannzetaover2);
-
- else ABACUSerror("Faulty parity in fbar_XXZ.");
-
- return (result);
- }
-
- DP Theta_XXZ (DP tanhlambda, int nj, int nk, int parj, int park, DP* tannzetaover2)
- {
- DP result = 0.0;
-
- if ((nj == 1) && (nk == 1)) result = fbar_XXZ(tanhlambda, parj*park, tannzetaover2[2]);
-
- else {
-
- result = (nj == nk) ? 0.0 : fbar_XXZ(tanhlambda, parj*park, tannzetaover2[fabs(nj - nk)]);
-
- for (int a = 1; a < ABACUS::min(nj, nk); ++a) result += 2.0 * fbar_XXZ(tanhlambda, parj*park, tannzetaover2[fabs(nj - nk) + 2*a]);
-
- result += fbar_XXZ(tanhlambda, parj*park, tannzetaover2[nj + nk]);
- }
-
- return (result);
- }
-
- DP hbar_XXZ (DP lambda, int n, int par, DP* si_n_anis_over_2)
- {
- DP result = 0.0;
-
- if (par == 1) result = si_n_anis_over_2[2*n]/(pow(sinh(lambda), 2.0) + pow(si_n_anis_over_2[n], 2.0));
-
- else if (par == -1) result = si_n_anis_over_2[2*n]/(-pow(cosh(lambda), 2.0) + pow(si_n_anis_over_2[n], 2.0));
-
- else ABACUSerror("Faulty parity in hbar_XXZ.");
-
- return (result);
- }
-
- DP ddlambda_Theta_XXZ (DP lambda, int nj, int nk, int parj, int park, DP* si_n_anis_over_2)
- {
- DP result = (nj == nk) ? 0.0 : hbar_XXZ(lambda, fabs(nj - nk), parj*park, si_n_anis_over_2);
-
- for (int a = 1; a < ABACUS::min(nj, nk); ++a) result += 2.0 * hbar_XXZ(lambda, fabs(nj - nk) + 2*a, parj*park, si_n_anis_over_2);
-
- result += hbar_XXZ(lambda, nj + nk, parj*park, si_n_anis_over_2);
-
- return (result);
- }
-
-
- XXZ_Bethe_State Add_Particle_at_Center (const XXZ_Bethe_State& RefState)
- {
- if (2*RefState.base.Mdown == RefState.chain.Nsites)
- ABACUSerror("Trying to add a down spin to a zero-magnetized chain in Add_Particle_at_Center.");
-
- Vect<int> newM = RefState.base.Nrap;
- newM[0] = newM[0] + 1;
-
- Heis_Base newBase (RefState.chain, newM);
-
- XXZ_Bethe_State ReturnState (RefState.chain, newBase);
-
- for (int il = 1; il < RefState.chain.Nstrings; ++il)
- for (int alpha = 0; alpha < RefState.base.Nrap[il]; ++alpha)
- ReturnState.Ix2[il][alpha] = RefState.Ix2[il][alpha];
-
- // Add a quantum number in middle (explicitly: to right of index M[0]/2)
- // and shift quantum numbers by half-integer away from added one:
- ReturnState.Ix2[0][RefState.base.Nrap[0]/2] = RefState.Ix2[0][RefState.base.Nrap[0]/2] - 1;
- for (int i = 0; i < RefState.base.Nrap[0] + 1; ++i)
- ReturnState.Ix2[0][i + (i >= RefState.base.Nrap[0]/2)] = RefState.Ix2[0][i] - 1 + 2*(i >= RefState.base.Nrap[0]/2);
-
- return(ReturnState);
- }
-
-
- XXZ_Bethe_State Remove_Particle_at_Center (const XXZ_Bethe_State& RefState)
- {
- if (RefState.base.Nrap[0] == 0)
- ABACUSerror("Trying to remove a down spin in an empty Nrap[0] state.");
-
- Vect<int> newM = RefState.base.Nrap;
- newM[0] = newM[0] - 1;
-
- Heis_Base newBase (RefState.chain, newM);
-
- XXZ_Bethe_State ReturnState (RefState.chain, newBase);
-
- for (int il = 1; il < RefState.chain.Nstrings; ++il)
- for (int alpha = 0; alpha < RefState.base.Nrap[il]; ++alpha)
- ReturnState.Ix2[il][alpha] = RefState.Ix2[il][alpha];
-
- // Remove midmost and shift quantum numbers by half-integer towards removed one:
- for (int i = 0; i < RefState.base.Nrap[0]-1; ++i)
- ReturnState.Ix2[0][i] = RefState.Ix2[0][i + (i >= RefState.base.Nrap[0]/2)] + 1 - 2*(i >= RefState.base.Nrap[0]/2);
-
- return(ReturnState);
- }
-
- } // namespace ABACUS
|