Clean up sources up to (before) src/SCAN.

This commit is contained in:
J.-S. Caux 2018-02-11 10:01:56 +01:00
parent d337885305
commit e7dd24d337
28 changed files with 1046 additions and 2987 deletions

View File

@ -1,5 +1,5 @@
#+TODO: TODO(t@) | DONE(d@)
#+TODO: BUGREPORT(b@) CRITICAL(#@) | SOLVED(s@)
#+TODO: BUGREPORT(b@) BUGRISK(?@) CRITICAL(#@) | SOLVED(s@)
#+TODO: CONCEPT(c@) UPDATED(u@) | REJECTED(r@)
#+TODO: PICKEDUP(p@) | ABANDONED(k@) IMPLEMENTED(i@)
@ -24,6 +24,23 @@ Type your description here
:END:
* Bugrisks :ABACUS:Dev:Bugrisks:
:PROPERTIES:
:ARCHIVE: %s_archive::* Bugrisks
:CUSTOM_ID: Bugrisks
:END:
TIP: Search for the string BUGRISK in the codebase
** BUGRISK Value of LiebLin ln_Density_ME
- State "BUGRISK" from "" [2018-02-11 Sun 09:11]
File: ln_Density_ME.cc
line 66
Why real?
* Priority :ABACUS:Dev:Priority:
:PROPERTIES:
:ARCHIVE: %s_archive::* Priority

View File

@ -25,11 +25,16 @@ $ make
```
This will produce all executables, together with a library `ABACUS_[vn]` where vn is of the form [digit][character].
## Warnings
* The ODSLF part (for one-dimensional spinless fermions) is not functional: it is based on the old Young Tableaux ids, and must be upgraded to `State_Label`s.
* The Richardson part is not implemented; what exists is old and long deprecated.
## Acknowledgements
__Antoine Klauser__ provided functions for computing neighbour-operator-product matrix elements in XXX: `ln_Szz_ME`, `ln_Szm_p_Smz_ME` and `ln_Smm_ME`.
__Jacopo De Nardis__ provided the code for the `ln_g2_ME` function for Lieb-Liniger.
__Miłosz Panfil__ contributed to code to help in the calculation of finite-temperature correlations of Lieb-Liniger.
__Jacopo De Nardis__ contributed code for the `ln_g2_ME` function for Lieb-Liniger.
__Teun Zwart__ has given much useful advice concerning C++ code organization.

View File

@ -24,27 +24,26 @@ namespace ABACUS {
LiebLin_Bethe_State::LiebLin_Bethe_State ()
: c_int (0.0), L(0.0), cxL(0.0), N(0),
//OriginStateIxe(Vect<int>(0,1)),
Ix2_available(Vect<int>(0, 1)), index_first_hole_to_right (Vect<int>(0,1)), displacement (Vect<int>(0,1)),
Ix2(Vect<int>(0, 1)), lambdaoc(Vect<DP>(0.0, 1)), //BE(Vect<DP>(0.0, 1)),
Ix2(Vect<int>(0, 1)), lambdaoc(Vect<DP>(0.0, 1)),
S(Vect<DP>(0.0, 1)), dSdlambdaoc(Vect<DP>(0.0, 1)),
diffsq(0.0), prec(ITER_REQ_PREC_LIEBLIN), conv(0), iter_Newton(0), E(0.0), iK(0), K(0.0), lnnorm(-100.0)
{
stringstream Nout; Nout << N; label = Nout.str() + LABELSEP + ABACUScoding[0] + LABELSEP;//"_0_";
stringstream Nout; Nout << N; label = Nout.str() + LABELSEP + ABACUScoding[0] + LABELSEP;
}
LiebLin_Bethe_State::LiebLin_Bethe_State (DP c_int_ref, DP L_ref, int N_ref)
: c_int(c_int_ref), L(L_ref), cxL(c_int_ref * L_ref), N(N_ref),
//OriginStateIx2(Vect<int>(0,N),
Ix2_available(Vect<int>(0, 2)), index_first_hole_to_right (Vect<int>(0,N)), displacement (Vect<int>(0,N)),
Ix2(Vect<int>(0, N)), lambdaoc(Vect<DP>(0.0, N)), //BE(Vect<DP>(0.0, N)),
Ix2(Vect<int>(0, N)), lambdaoc(Vect<DP>(0.0, N)),
S(Vect<DP>(0.0, N)), dSdlambdaoc(Vect<DP>(0.0, N)),
diffsq(0.0), prec(ABACUS::max(1.0, 1.0/(c_int * c_int)) * ITER_REQ_PREC_LIEBLIN), conv(0), iter_Newton(0), E(0.0), iK(0), K(0.0), lnnorm(-100.0)
diffsq(0.0), prec(ABACUS::max(1.0, 1.0/(c_int * c_int)) * ITER_REQ_PREC_LIEBLIN),
conv(0), iter_Newton(0), E(0.0), iK(0), K(0.0), lnnorm(-100.0)
{
if (c_int < 0.0) ABACUSerror("You must use a positive interaction parameter !");
if (N < 0) ABACUSerror("Particle number must be strictly positive.");
stringstream Nout; Nout << N; label = Nout.str() + LABELSEP + ABACUScoding[0] + LABELSEP;//+ "_0_";
stringstream Nout; Nout << N; label = Nout.str() + LABELSEP + ABACUScoding[0] + LABELSEP;
// Set quantum numbers to ground-state configuration:
for (int i = 0; i < N; ++i) Ix2[i] = -(N-1) + 2*i;
@ -52,7 +51,6 @@ namespace ABACUS {
Vect<int> OriginIx2 = Ix2;
(*this).Set_Label_from_Ix2 (OriginIx2);
//(*this).Set_Label_Internals_from_Ix2 (OriginIx2);
}
@ -69,7 +67,6 @@ namespace ABACUS {
displacement = RefState.displacement;
Ix2 = RefState.Ix2;
lambdaoc = RefState.lambdaoc;
//BE = RefState.BE;
S = RefState.S;
dSdlambdaoc = RefState.dSdlambdaoc;
diffsq = RefState.diffsq;
@ -114,11 +111,7 @@ namespace ABACUS {
// Now reorder the Ix2 to follow convention:
Ix2.QuickSort();
//cout << "Setting label:" << label_ref << endl << "Ix2old = " << labeldata.Ix2old[0] << endl << "Ix2exc = " << labeldata.Ix2exc[0] << endl;
//cout << "on " << OriginStateIx2ordered << endl << "giving " << Ix2 << endl;
(*this).Set_Label_from_Ix2 (OriginStateIx2ordered);
//(*this).Set_Label_Internals_from_Ix2 (OriginStateIx2ordered);
}
void LiebLin_Bethe_State::Set_to_Label (string label_ref)
@ -138,7 +131,6 @@ namespace ABACUS {
if (N != OriginStateIx2.size()) ABACUSerror("N != OriginStateIx2.size() in Set_Label_from_Ix2.");
//cout << "Setting label on Ix2 " << endl << Ix2 << endl;
// Set the state label:
Vect<int> type_ref(0,1);
@ -173,44 +165,8 @@ namespace ABACUS {
label = Return_State_Label (labeldata, OriginStateIx2);
}
/*
void LiebLin_Bethe_State::Set_Label_from_Ix2 (const Vect<int>& OriginStateIx2)
{
// This function was deprecated since it assumed that the Ix2 of the state were
// in a particular order mirroring the indices of OriginStateIx2.
if (N != OriginStateIx2.size()) ABACUSerror("N != OriginStateIx2.size() in Set_Label_from_Ix2.");
Vect<int> OriginStateIx2ordered = OriginStateIx2;
OriginStateIx2ordered.QuickSort();
// Set the state label:
Vect<int> type_ref(0,1);
Vect<int> M_ref(N, 1);
Vect<int> nexc_ref(0, 1);
// Count nr of particle-holes:
for (int i = 0; i < N; ++i) if (Ix2[i] != OriginStateIx2ordered[i]) nexc_ref[0] += 1;
Vect<Vect<int> > Ix2old_ref(1);
Vect<Vect<int> > Ix2exc_ref(1);
Ix2old_ref[0] = Vect<int>(ABACUS::max(nexc_ref[0],1));
Ix2exc_ref[0] = Vect<int>(ABACUS::max(nexc_ref[0],1));
int nexccheck = 0;
for (int i = 0; i < N; ++i)
if (Ix2[i] != OriginStateIx2ordered[i]) {
Ix2old_ref[0][nexccheck] = OriginStateIx2ordered[i];
Ix2exc_ref[0][nexccheck++] = Ix2[i];
}
State_Label_Data labeldata(type_ref, M_ref, nexc_ref, Ix2old_ref, Ix2exc_ref);
label = Return_State_Label (labeldata);
}
*/
void LiebLin_Bethe_State::Set_Label_Internals_from_Ix2 (const Vect<int>& OriginStateIx2)
{
//ABACUSerror("LiebLin_Bethe_State::Set_Label_Internals_from_Ix2 deprecated 20110604");
if (N != OriginStateIx2.size()) ABACUSerror("N != OriginStateIx2.size() in Set_Label_Internals_from_Ix2.");
Vect<int> OriginStateIx2ordered = OriginStateIx2;
@ -238,12 +194,14 @@ namespace ABACUS {
label = Return_State_Label (labeldata, OriginStateIx2);
// Construct the Ix2_available vector: we give one more quantum number on left and right:
int navailable = 2 + (ABACUS::max(Ix2.max(), OriginStateIx2.max()) - ABACUS::min(Ix2.min(), OriginStateIx2.min()))/2 - N + 1;
int navailable = 2 + (ABACUS::max(Ix2.max(), OriginStateIx2.max())
- ABACUS::min(Ix2.min(), OriginStateIx2.min()))/2 - N + 1;
Ix2_available = Vect<int>(navailable);
index_first_hole_to_right = Vect<int>(N);
// First set Ix2_available to all holes from left
for (int i = 0; i < Ix2_available.size(); ++i) Ix2_available[i] = ABACUS::min(Ix2.min(), OriginStateIx2.min()) - 2 + 2*i;
for (int i = 0; i < Ix2_available.size(); ++i)
Ix2_available[i] = ABACUS::min(Ix2.min(), OriginStateIx2.min()) - 2 + 2*i;
// Now shift according to Ix2 of OriginState:
for (int j = 0; j < N; ++j) {
@ -261,11 +219,10 @@ namespace ABACUS {
for (int j = 0; j < N; ++j) {
if (Ix2[j] < OriginStateIx2ordered[j]) {
// Ix2[j] must be equal to some OriginState_Ix2_available[i] for i < OriginState_index_first_hole_to_right[j]
//cout << "Going down\t" << Ix2[j] << "\t" << index_first_hole_to_right[j] << "\t" << displacement[j] << endl;
while (Ix2[j] != Ix2_available[index_first_hole_to_right[j] + displacement[j] ]) {
//cout << j << "\t" << index_first_hole_to_right[j] << "\t" << displacement[j] << "\t" << Ix2_available[index_first_hole_to_right[j] + displacement[j] ] << endl;
if (index_first_hole_to_right[j] + displacement[j] == 0) {
cout << label << endl << j << endl << OriginStateIx2 << endl << Ix2 << endl << Ix2_available << endl << index_first_hole_to_right << endl << displacement << endl;
cout << label << endl << j << endl << OriginStateIx2 << endl << Ix2 << endl << Ix2_available
<< endl << index_first_hole_to_right << endl << displacement << endl;
ABACUSerror("Going down too far in Set_Label_Internals...");
}
displacement[j]--;
@ -273,23 +230,17 @@ namespace ABACUS {
}
if (Ix2[j] > OriginStateIx2ordered[j]) {
// Ix2[j] must be equal to some Ix2_available[i] for i >= index_first_hole_to_right[j]
//cout << "Going up\t" << Ix2[j] << "\t" << index_first_hole_to_right[j] << "\t" << displacement[j] << endl;
displacement[j] = 1; // start with this value to prevent segfault
while (Ix2[j] != Ix2_available[index_first_hole_to_right[j] - 1 + displacement[j] ]) {
//cout << j << "\t" << index_first_hole_to_right[j] << "\t" << displacement[j] << "\t" << Ix2_available[index_first_hole_to_right[j] + displacement[j] ] << endl;
if (index_first_hole_to_right[j] + displacement[j] == Ix2_available.size() - 1) {
cout << label << endl << j << endl << OriginStateIx2 << endl << Ix2 << endl << Ix2_available << endl << index_first_hole_to_right << endl << displacement << endl;
cout << label << endl << j << endl << OriginStateIx2 << endl << Ix2 << endl << Ix2_available
<< endl << index_first_hole_to_right << endl << displacement << endl;
ABACUSerror("Going up too far in Set_Label_Internals...");
}
displacement[j]++;
}
}
}
//cout << "label " << label << endl;
//cout << "Ix2: " << Ix2 << endl << "Ix2_available: " << Ix2_available << endl << "index...: " << index_first_hole_to_right << endl << "displacement: " << displacement << endl;
//char a; cin >> a;
}
bool LiebLin_Bethe_State::Check_Admissibility (char whichDSF)
@ -307,43 +258,25 @@ namespace ABACUS {
diffsq = 1.0;
if (reset_rapidities) (*this).Set_Free_lambdaocs();
/*
// Start with normal iterations:
//for (int niternormal = 0; niternormal < 10; ++niternormal) {
for (int niternormal = 0; niternormal < N; ++niternormal) {
//(*this).Iterate_BAE(0.99);
(*this).Iterate_BAE(0.9);
cout << "Normal: " << niternormal << "\t" << diffsq << endl;
cout << (*this).lambdaoc << endl;
if (diffsq < sqrt(prec)) break;
}
*/
iter_Newton = 0;
DP damping = 1.0;
DP diffsq_prev = 1.0e+6;
//while (diffsq > prec && !is_nan(diffsq) && iter_Newton < 40) {
while (diffsq > prec && !is_nan(diffsq) && iter_Newton < 100) {
//while (diffsq > prec && !is_nan(diffsq) && iter_Newton < 400) {
(*this).Iterate_BAE_Newton(damping);
//(*this).Iterate_BAE_S(damping); // Not as fast as Newton for N up to ~ 256
//if (diffsq > diffsq_prev) damping /= 2.0;
if (diffsq > diffsq_prev && damping > 0.5) damping /= 2.0;
else if (diffsq < diffsq_prev) damping = 1.0;
diffsq_prev = diffsq;
//cout << iter_Newton << "\t" << diffsq << "\t" << damping << endl;
//cout << (*this).lambdaoc << endl;
}
conv = ((diffsq < prec) && (*this).Check_Rapidities()) ? 1 : 0;
if (!conv) {
cout << "Alert! State " << label << " did not converge... diffsq " << diffsq << "\titer_Newton " << iter_Newton << (*this) << endl;
//char a; cin >> a;
cout << "Alert! State " << label << " did not converge... diffsq " << diffsq
<< "\titer_Newton " << iter_Newton << (*this) << endl;
}
//cout << (*this) << endl;
return;
}
@ -388,7 +321,8 @@ namespace ABACUS {
// Add the pieces outside of Gaudin determinant
for (int j = 0; j < N - 1; ++j) for (int k = j+1; k < N; ++k) lnnorm += log(1.0 + 1.0/pow(lambdaoc[j] - lambdaoc[k], 2.0));
for (int j = 0; j < N - 1; ++j) for (int k = j+1; k < N; ++k)
lnnorm += log(1.0 + 1.0/pow(lambdaoc[j] - lambdaoc[k], 2.0));
}
@ -409,19 +343,14 @@ namespace ABACUS {
void LiebLin_Bethe_State::Set_Free_lambdaocs()
{
if (cxL >= 1.0)
for (int a = 0; a < N; ++a) lambdaoc[a] = PI * Ix2[a]/cxL;
for (int a = 0; a < N; ++a) lambdaoc[a] = PI * Ix2[a]/cxL;
// For small values of c, use better approximation using approximate zeroes of Hermite polynomials: see Gaudin eqn 4.71.
if (cxL < 1.0) {
//DP sqrtcL = pow(cxL, 0.5);
DP oneoversqrtcLN = 1.0/pow(cxL * N, 0.5);
for (int a = 0; a < N; ++a) lambdaoc[a] = oneoversqrtcLN * PI * Ix2[a];
//for (int a = 0; a < N; ++a) lambdaoc[a] = sqrtcL * PI * Ix2[a]; // wrong values, correct scaling with c
//for (int a = 0; a < N; ++a) lambdaoc[a] = PI * Ix2[a]/(cxL + 2.0 * N); // set to minimal distance lattice
}
//cout << "Set free lambdaocs to: " << endl << lambdaoc << endl;
return;
}
@ -443,19 +372,13 @@ namespace ABACUS {
}
diffsq = 0.0;
//DP sumsq = 0.0;
for (int i = 0; i < N; ++i) {
lambdaoc[i] += dlambdaoc[i];
//sumsq += lambdaoc[i] * lambdaoc[i];
//diffsq += dlambdaoc[i] * dlambdaoc[i];
//if (cxL > 1.0) diffsq += dlambdaoc[i] * dlambdaoc[i];
//else diffsq += cxL * cxL * dlambdaoc[i] * dlambdaoc[i];
// Normalize the diffsq by the typical value of the rapidities:
if (cxL > 1.0) diffsq += dlambdaoc[i] * dlambdaoc[i]/(lambdaoc[i] * lambdaoc[i] + 1.0e-6);
else diffsq += cxL * cxL * dlambdaoc[i] * dlambdaoc[i]/(lambdaoc[i] * lambdaoc[i] + 1.0e-6);
}
diffsq /= DP(N);
//diffsq /= sqrt(sumsq) * DP(N);
return;
}
@ -463,7 +386,8 @@ namespace ABACUS {
void LiebLin_Bethe_State::Iterate_BAE_S (DP damping)
{
// This is essentially Newton's method but only in one variable.
// The logic is that the derivative of the LHS of the BE_j w/r to lambdaoc_j is much larger than with respect to lambdaoc_l with l != j.
// The logic is that the derivative of the LHS of the BE_j w/r to lambdaoc_j is much larger
// than with respect to lambdaoc_l with l != j.
Vect_DP dlambdaoc (0.0, N);
@ -475,7 +399,8 @@ namespace ABACUS {
S[j] *= 2.0/cxL;
dSdlambdaoc[j] = 0.0;
for (int k = 0; k < N; ++k) dSdlambdaoc[j] += 1.0/((lambdaoc[j] - lambdaoc[k]) * (lambdaoc[j] - lambdaoc[k]) + 1.0);
for (int k = 0; k < N; ++k)
dSdlambdaoc[j] += 1.0/((lambdaoc[j] - lambdaoc[k]) * (lambdaoc[j] - lambdaoc[k]) + 1.0);
dSdlambdaoc[j] *= 2.0/(PI * cxL);
dlambdaoc[j] = (PI*Ix2[j]/cxL - S[j] + lambdaoc[j] * dSdlambdaoc[j])/(1.0 + dSdlambdaoc[j]) - lambdaoc[j];
@ -526,8 +451,6 @@ namespace ABACUS {
}
sumtheta *= 2.0;
//cout << j << "\t" << Ix2[j] << "\t" << atanintshift << endl;
RHSBAE[j] = cxL * lambdaoc[j] + sumtheta - PI*(Ix2[j] - atanintshift);
}
@ -535,14 +458,10 @@ namespace ABACUS {
for (int j = 0; j < N; ++j) dlambdaoc[j] = - RHSBAE[j];
//cout << "dlambdaoc pre lubksb = " << dlambdaoc << endl;
DP d;
ludcmp (Gaudin, indx, d);
lubksb (Gaudin, indx, dlambdaoc);
//cout << "dlambdaoc post lubksb = " << dlambdaoc << endl;
bool ordering_changed = false;
for (int j = 0; j < N-1; ++j) if (lambdaoc[j] + dlambdaoc[j] > lambdaoc[j+1] + dlambdaoc[j+1]) ordering_changed = true;
@ -553,71 +472,35 @@ namespace ABACUS {
DP maxdlambdaoc = 0.0;
do {
ordering_still_changed = false;
if (dlambdaoc[0] < 0.0 && fabs(dlambdaoc[0]) > (maxdlambdaoc = 10.0*ABACUS::max(fabs(lambdaoc[0]), fabs(lambdaoc[N-1]))))
if (dlambdaoc[0] < 0.0 && fabs(dlambdaoc[0])
> (maxdlambdaoc = 10.0*ABACUS::max(fabs(lambdaoc[0]), fabs(lambdaoc[N-1]))))
dlambdaoc[0] = -maxdlambdaoc;
if (lambdaoc[0] + dlambdaoc[0] > lambdaoc[1] + dlambdaoc[1]) {
dlambdaoc[0] = 0.25 * (lambdaoc[1] + dlambdaoc[1] - lambdaoc[0] ); // max quarter distance
ordering_still_changed = true;
//cout << "reason 1" << endl;
}
if (dlambdaoc[N-1] > 0.0 && fabs(dlambdaoc[N-1]) > (maxdlambdaoc = 10.0*ABACUS::max(fabs(lambdaoc[0]), fabs(lambdaoc[N-1]))))
if (dlambdaoc[N-1] > 0.0 && fabs(dlambdaoc[N-1])
> (maxdlambdaoc = 10.0*ABACUS::max(fabs(lambdaoc[0]), fabs(lambdaoc[N-1]))))
dlambdaoc[N-1] = maxdlambdaoc;
if (lambdaoc[N-1] + dlambdaoc[N-1] < lambdaoc[N-2] + dlambdaoc[N-2]) {
dlambdaoc[N-1] = 0.25 * (lambdaoc[N-2] + dlambdaoc[N-2] - lambdaoc[N-1]);
ordering_still_changed = true;
//cout << "reason 2" << endl;
}
for (int j = 1; j < N-1; ++j) {
if (lambdaoc[j] + dlambdaoc[j] > lambdaoc[j+1] + dlambdaoc[j+1]) {
dlambdaoc[j] = 0.25 * (lambdaoc[j+1] + dlambdaoc[j+1] - lambdaoc[j]);
ordering_still_changed = true;
//cout << "reason 3" << endl;
}
if (lambdaoc[j] + dlambdaoc[j] < lambdaoc[j-1] + dlambdaoc[j-1]) {
dlambdaoc[j] = 0.25 * (lambdaoc[j-1] + dlambdaoc[j-1] - lambdaoc[j]);
ordering_still_changed = true;
//cout << "reason 4" << endl;
}
}
} while (ordering_still_changed);
}
//if (ordering_changed) cout << "dlambdaoc post checking = " << dlambdaoc << endl;
/*
bool orderingchanged = false;
//bool dlambdaexceedsmaxrapdiff = false;
DP damping_to_use = damping;
for (int j = 0; j < N-1; ++j) {
if (lambdaoc[j] + dlambdaoc[j] > lambdaoc[j+1] + dlambdaoc[j+1]) // unacceptable, order changed!
orderingchanged = true;
// We must damp the dlambda such that the ordering is unchanged:
// the condition is lambdaoc[j] + damping*dlambdaoc[j] < lambdaoc[j+1] + damping*dlambdaoc[j+1]
damping_to_use = ABACUS::min(damping_to_use, 0.5 * (lambdaoc[j+1] - lambdaoc[j])/(dlambdaoc[j] - dlambdaoc[j+1]));
}
*/
//for (int j = 0; j < N; ++j)
//if (fabs(dlambdaoc[j]) > maxrapdiff) dlambdaexceedsmaxrapdiff = true;
/*
// The dlambdaoc must be smaller than the distance to neighbouring rapidities:
// If any dlambdaoc is greater than half the distance, set all to half the previous distance:
if (orderingchanged || dlambdaexceedsmaxrapdiff) {
if (dlambdaoc[0] > 0.0) dlambdaoc[0] = 0.25 * (lambdaoc[1] - lambdaoc[0]);
//else dlambdaoc[0] = 0.25 * (lambdaoc[0] - lambdaoc[1]);
else dlambdaoc[0] = -fabs(lambdaoc[0]); // strictly limit the growth of lambdaoc[0]
//if (dlambdaoc[N-1] > 0.0) dlambdaoc[N-1] = 0.25 * (lambdaoc[N-1] - lambdaoc[N-2]);
if (dlambdaoc[N-1] > 0.0) dlambdaoc[N-1] = fabs(lambdaoc[N-1]); // strictly limit the growth of lambdaoc[N-1]
else dlambdaoc[N-1] = 0.25 * (lambdaoc[N-2] - lambdaoc[N-1]);
for (int j = 1; j < N-1; ++j) {
if (dlambdaoc[j] > 0.0) dlambdaoc[j] = 0.25 * (lambdaoc[j+1] - lambdaoc[j]);
if (dlambdaoc[j] < 0.0) dlambdaoc[j] = 0.25 * (lambdaoc[j-1] - lambdaoc[j]);
}
//cout << "Corrected dlambdaoc = " << dlambdaoc << endl;
}
*/
diffsq = 0.0;
for (int i = 0; i < N; ++i) {
//diffsq += dlambdaoc[i] * dlambdaoc[i];
// Normalize the diffsq by the typical value of the rapidities:
if (cxL > 1.0) diffsq += dlambdaoc[i] * dlambdaoc[i]/(lambdaoc[i] * lambdaoc[i] + 1.0e-6);
else diffsq += cxL * cxL * dlambdaoc[i] * dlambdaoc[i]/(lambdaoc[i] * lambdaoc[i] + 1.0e-6);
@ -627,20 +510,20 @@ namespace ABACUS {
if (ordering_changed) diffsq = 1.0; // reset if Newton wanted to change ordering
for (int j = 0; j < N; ++j) lambdaoc[j] += damping * dlambdaoc[j];
//for (int j = 0; j < N; ++j) lambdaoc[j] += damping_to_use * dlambdaoc[j];
iter_Newton++;
// if we've converged, calculate the norm here, since the work has been done...
//if (diffsq < prec && !orderingchanged && !dlambdaexceedsmaxrapdiff) {
if (diffsq < prec && !ordering_changed) {
lnnorm = 0.0;
for (int j = 0; j < N; j++) lnnorm += log(fabs(Gaudin[j][j]));
// Add the pieces outside of Gaudin determinant
for (int j = 0; j < N - 1; ++j) for (int k = j+1; k < N; ++k) lnnorm += log(1.0 + 1.0/pow(lambdaoc[j] - lambdaoc[k], 2.0));
for (int j = 0; j < N - 1; ++j)
for (int k = j+1; k < N; ++k)
lnnorm += log(1.0 + 1.0/pow(lambdaoc[j] - lambdaoc[k], 2.0));
}
return;
@ -657,7 +540,6 @@ namespace ABACUS {
{
iK = 0;
for (int j = 0; j < N; ++j) {
//cout << j << "\t" << iK << "\t" << Ix2[j] << endl;
iK += Ix2[j];
}
if (iK % 2) {
@ -683,7 +565,8 @@ namespace ABACUS {
void LiebLin_Bethe_State::Build_Reduced_Gaudin_Matrix (SQMat<DP>& Gaudin_Red)
{
if (Gaudin_Red.size() != N) ABACUSerror("Passing matrix of wrong size in Build_Reduced_Gaudin_Matrix.");
if (Gaudin_Red.size() != N)
ABACUSerror("Passing matrix of wrong size in Build_Reduced_Gaudin_Matrix.");
DP sum_Kernel = 0.0;
@ -717,7 +600,8 @@ namespace ABACUS {
if (!ck) ABACUSerror("Choose a parity invariant state please");
if (Gaudin_Red.size() != N/2) ABACUSerror("Passing matrix of wrong size in Build_Reduced_Gaudin_Matrix.");
if (Gaudin_Red.size() != N/2)
ABACUSerror("Passing matrix of wrong size in Build_Reduced_Gaudin_Matrix.");
DP sum_Kernel = 0.0;
@ -726,11 +610,14 @@ namespace ABACUS {
if (j == k) {
sum_Kernel = 0.0;
for (int kp = N/2; kp < N; ++kp) if (j + N/2 != kp) sum_Kernel += Kernel (lambdaoc[j+N/2] - lambdaoc[kp]) + Kernel (lambdaoc[j+N/2] + lambdaoc[kp]);
for (int kp = N/2; kp < N; ++kp)
if (j + N/2 != kp)
sum_Kernel += Kernel (lambdaoc[j+N/2] - lambdaoc[kp]) + Kernel (lambdaoc[j+N/2] + lambdaoc[kp]);
Gaudin_Red[j][k] = cxL + sum_Kernel;
}
else Gaudin_Red[j][k] = - (Kernel (lambdaoc[j+ N/2] - lambdaoc[k+ N/2]) + Kernel (lambdaoc[j+ N/2] + lambdaoc[k+ N/2]) );
else Gaudin_Red[j][k] = - (Kernel (lambdaoc[j+ N/2] - lambdaoc[k+ N/2])
+ Kernel (lambdaoc[j+ N/2] + lambdaoc[k+ N/2]) );
}
@ -743,14 +630,12 @@ namespace ABACUS {
// This function changes the Ix2 of a given state by annihilating a particle and hole
// pair specified by ipart and ihole (counting from the left, starting with index 0).
//cout << "Annihilating ipart " << ipart << " and ihole " << ihole << " of state with label " << (*this).label << endl;
State_Label_Data currentdata = Read_State_Label ((*this).label, OriginStateIx2);
//cout << "current Ix2old " << currentdata.Ix2old[0] << endl;
//cout << "current Ix2exc " << currentdata.Ix2exc[0] << endl;
if (ipart >= currentdata.nexc[0]) ABACUSerror("Particle label too large in LiebLin_Bethe_State::Annihilate_ph_pair.");
if (ihole >= currentdata.nexc[0]) ABACUSerror("Hole label too large in LiebLin_Bethe_State::Annihilate_ph_pair.");
if (ipart >= currentdata.nexc[0])
ABACUSerror("Particle label too large in LiebLin_Bethe_State::Annihilate_ph_pair.");
if (ihole >= currentdata.nexc[0])
ABACUSerror("Hole label too large in LiebLin_Bethe_State::Annihilate_ph_pair.");
// Simply remove the given pair:
Vect<int> type_new = currentdata.type;
@ -768,16 +653,12 @@ namespace ABACUS {
for (int i = 0; i < nexc_new[it]; ++i) {
Ix2old_new[it][i] = currentdata.Ix2old[it][i + (i >= ihole)];
Ix2exc_new[it][i] = currentdata.Ix2exc[it][i + (i >= ipart)];
}
}
//cout << "Ix2old_new " << Ix2old_new[0] << endl;
//cout << "Ix2exc_new " << Ix2exc_new[0] << endl;
}
State_Label_Data newdata (type_new, M_new, nexc_new, Ix2old_new, Ix2exc_new);
(*this).Set_to_Label (Return_State_Label(newdata, OriginStateIx2));
//cout << "Obtained label " << (*this).label << endl;
}
void LiebLin_Bethe_State::Parity_Flip ()

View File

@ -24,14 +24,11 @@ namespace ABACUS {
// RefState is used here to provide the c_int, L and N parameters.
LiebLin_Bethe_State Nplus1State(RefState.c_int, RefState.L, RefState.N + 1);
//LiebLin_Bethe_State NState(RefState.c_int, RefState.L, RefState.N);
LiebLin_Bethe_State Nmin1State(RefState.c_int, RefState.L, RefState.N - 1);
Nplus1State.Compute_All(true);
//NState.Compute_All(true);
Nmin1State.Compute_All(true);
//return(NState.E - Nmin1State.E);
return(0.5 * (Nplus1State.E - Nmin1State.E));
}

View File

@ -19,10 +19,6 @@ using namespace ABACUS;
namespace ABACUS {
//DP Compute_Matrix_Element_Contrib (char whichDSF, bool fixed_iK, LiebLin_Bethe_State& LeftState,
// LiebLin_Bethe_State& RefState, DP Chem_Pot, fstream& DAT_outfile)
//DP Compute_Matrix_Element_Contrib (char whichDSF, int iKmin, int iKmax, LiebLin_Bethe_State& LeftState,
// LiebLin_Bethe_State& RefState, DP Chem_Pot, fstream& DAT_outfile)
DP Compute_Matrix_Element_Contrib (char whichDSF, int iKmin, int iKmax, LiebLin_Bethe_State& LeftState,
LiebLin_Bethe_State& RefState, DP Chem_Pot, stringstream& DAT_outfile)
{
@ -45,13 +41,12 @@ namespace ABACUS {
else if (whichDSF == 'g')
ME = real(exp(ln_Psi_ME (RefState, LeftState)));
else if (whichDSF == 'q') // geometrical quench
//ME_CX = (LiebLin_Twisted_ln_Overlap(1.0, RefState.lambdaoc, RefState.lnnorm, LeftState));
//ME_CX = (LiebLin_ln_Overlap(RefState.lambdaoc, RefState.lnnorm, LeftState));
ME_CX = LiebLin_ln_Overlap(LeftState.lambdaoc, LeftState.lnnorm, RefState);
else if (whichDSF == 'B') { // BEC to finite c quench: g2(x=0)
//ME_CX = exp(ln_Overlap_with_BEC (LeftState)); // overlap part
ME_CX = exp(ln_Overlap_with_BEC (LeftState) - ln_Overlap_with_BEC (RefState)); // overlap part, relative to saddle-point state
ME = real(exp(ln_g2_ME (RefState, LeftState))); // matrix element part
// overlap part, relative to saddle-point state
ME_CX = exp(ln_Overlap_with_BEC (LeftState) - ln_Overlap_with_BEC (RefState));
// matrix element part
ME = real(exp(ln_g2_ME (RefState, LeftState)));
// The product is ME_CX * ME = e^{-\delta S_e} \langle \rho_{sp} | g2 (x=0) | \rho_{sp} + e \rangle
// and is the first half of the t-dep expectation value formula coming from the Quench Action formalism
}
@ -71,7 +66,6 @@ namespace ABACUS {
if (whichDSF == 'Z') {
DAT_outfile << endl << LeftState.E - RefState.E - (LeftState.N - RefState.N) * Chem_Pot << "\t"
<< LeftState.iK - RefState.iK
//<< "\t" << LeftState.conv
<< 0 << "\t" // This is the deviation, here always 0
<< "\t" << LeftState.label;
}
@ -79,7 +73,6 @@ namespace ABACUS {
DAT_outfile << endl << LeftState.E - RefState.E - (LeftState.N - RefState.N) * Chem_Pot << "\t"
<< LeftState.iK - RefState.iK << "\t"
<< real(ME_CX) << "\t" << imag(ME_CX) - twoPI * int(imag(ME_CX)/twoPI + 1.0e-10) << "\t"
//<< LeftState.conv << "\t"
<< 0 << "\t" // This is the deviation, here always 0
<< LeftState.label;
}
@ -87,11 +80,9 @@ namespace ABACUS {
DAT_outfile << endl << LeftState.E - RefState.E - (LeftState.N - RefState.N) * Chem_Pot << "\t"
<< LeftState.iK - RefState.iK << "\t"
<< ME << "\t"
//<< LeftState.conv << "\t"
<< 0 << "\t" // This is the deviation, here always 0
<< LeftState.label;
DAT_outfile << "\t" << Momentum_Right_Excitations(LeftState) << "\t" << Momentum_Left_Excitations(LeftState);
//cout << Momentum_Right_Excitations(LeftState) << "\t" << Momentum_Left_Excitations(LeftState);
}
else if (whichDSF == 'B') { // BEC to finite c > 0 quench; g2 (x=0)
if (fabs(real(ME_CX) * ME) > 1.0e-100)
@ -99,7 +90,6 @@ namespace ABACUS {
<< LeftState.iK - RefState.iK << "\t"
<< real(ME_CX) << "\t" // the overlap is always real
<< ME << "\t"
//<< 0 << "\t" // This is the deviation, here always 0 // omit this here
<< LeftState.label;
}
else if (whichDSF == 'C') { // BEC to finite c, overlap sq
@ -108,14 +98,12 @@ namespace ABACUS {
<< LeftState.iK - RefState.iK << "\t"
<< real(ME_CX) << "\t" // the overlap is always real
<< ME << "\t"
//<< 0 << "\t" // This is the deviation, here always 0 // omit this here
<< LeftState.label;
}
else {
DAT_outfile << endl << LeftState.E - RefState.E - (LeftState.N - RefState.N) * Chem_Pot << "\t"
<< LeftState.iK - RefState.iK << "\t"
<< ME << "\t"
//<< LeftState.conv << "\t"
<< 0 << "\t" // This is the deviation, here always 0
<< LeftState.label;
}
@ -127,46 +115,18 @@ namespace ABACUS {
data_value = 1.0/(1.0 + LeftState.E - RefState.E - (LeftState.N - RefState.N) * Chem_Pot);
else if (whichDSF == 'd' || whichDSF == '1') {
if (fixed_iK)
/*
// use omega * MEsq/iK^2
//data_value = (LeftState.E - RefState.E - (LeftState.N - RefState.N) * Chem_Pot)
// MEsq/ABACUS::max(1, (LeftState.iK - RefState.iK) * (LeftState.iK - RefState.iK))
//: 0.0;
*/
// Careful: use fabs(E) since this must also work with Tgt0 or arbitrary RefState DEPRECATED ++G_1, USE abs_data_value
data_value = (LeftState.E - RefState.E - (LeftState.N - RefState.N) * Chem_Pot) * ME * ME;
else if (!fixed_iK) // use ME if momentum in fundamental window -iK_UL <= iK <= iK_UL
//data_value = abs(LeftState.iK - RefState.iK) <= RefState.Tableau[0].Ncols ? // this last nr is iK_UL
//MEsq : 0.0;
//data_value = (LeftState.iK - RefState.iK == 0 ? 1.0 : 2.0) * MEsq;
//data_value = ME * ME;
// use omega * MEsq/iK^2
// Careful: use fabs(E) since this must also work with Tgt0 or arbitrary RefState DEPRECATED ++G_1, USE abs_data_value
data_value = (LeftState.E - RefState.E - (LeftState.N - RefState.N) * Chem_Pot) * ME * ME/ABACUS::max(1, (LeftState.iK - RefState.iK) * (LeftState.iK - RefState.iK));
else if (!fixed_iK)
data_value = (LeftState.E - RefState.E - (LeftState.N - RefState.N) * Chem_Pot) * ME * ME
/ABACUS::max(1, (LeftState.iK - RefState.iK) * (LeftState.iK - RefState.iK));
}
else if (whichDSF == 'g' || whichDSF == 'o') {
if (fixed_iK)
/*
// use omega * MEsq/((k^2 - mu + 4 c N/L)/L)
data_value = (LeftState.E - RefState.E - (LeftState.N - RefState.N) * Chem_Pot)
* MEsq/((((LeftState.K - RefState.K) * (LeftState.K - RefState.K) - Chem_Pot) + 4.0 * RefState.c_int * RefState.N/RefState.L)/RefState.L)
: 0.0;
*/
// Careful: use fabs(E) since this must also work with Tgt0 or arbitrary RefState
data_value = (LeftState.E - RefState.E - (LeftState.N - RefState.N) * Chem_Pot) * ME * ME;
else if (!fixed_iK) { // simply use MEsq if momentum in fundamental window -iK_UL <= iK <= iK_UL
//data_value = abs(LeftState.iK - RefState.iK) <= RefState.Tableau[0].Ncols ? // this last nr is iK_UL
//MEsq : 0.0;
//data_value = (LeftState.iK - RefState.iK == 0 ? 1.0 : 2.0) * MEsq;
else if (!fixed_iK) {
data_value = ME * ME;
//data_value = fabs(LeftState.E - RefState.E - (LeftState.N - RefState.N) * Chem_Pot) * ME * ME;
// In the case of whichDSF == 'o', the state with label (N-1)_0_ gives zero data_value. Force to 1.
//if (whichDSF == 'o' && fabs(LeftState.E - RefState.E - (LeftState.N - RefState.N) * Chem_Pot) < 1.0e-10) data_value = 1.0;
}
}
//else if (whichDSF == 'o')
//data_value = abs(LeftState.iK - RefState.iK) <= RefState.Tableau[0].Ncols ? // this last nr is iK_UL
//MEsq : 0.0;
else if (whichDSF == 'q')
data_value = exp(2.0 * real(ME_CX));
else if (whichDSF == 'B')

View File

@ -30,13 +30,6 @@ namespace ABACUS {
: nstates(nstates_req), state(Vect<LiebLin_Bethe_State>(RefState, nstates_req)), weight(1.0/nstates_req, nstates_req)
{
}
/*
LiebLin_Diagonal_State_Ensemble::LiebLin_Diagonal_State_Ensemble (const LiebLin_Bethe_State& RefState, int nstates_req, const Vect<DP>& weight_ref)
: nstates(nstates_req), state(Vect<LiebLin_Bethe_State>(RefState, nstates_req)), weight(weight_ref)
{
if (weight_ref.size() != nstates_req) ABACUSerror("Incompatible vector size in LiebLin_Diagonal_State_Ensemble constructor.");
}
*/
// Recursively go through all arbitrary-order type 2 descendents
void Generate_type_2_descendents (LiebLin_Bethe_State& ActualState, int* ndesc_ptr, const LiebLin_Bethe_State& OriginState)
@ -65,12 +58,11 @@ namespace ABACUS {
}
//LiebLin_Diagonal_State_Ensemble::LiebLin_Diagonal_State_Ensemble (DP c_int, DP L, int N, const Root_Density& rho, int nstates_req)
//: nstates(nstates_req)
LiebLin_Diagonal_State_Ensemble::LiebLin_Diagonal_State_Ensemble (DP c_int, DP L, int N, const Root_Density& rho)
{
// This function returns a state ensemble matching the continuous density rho.
// The logic closely resembles the one used in Discretized_LiebLin_Bethe_State.
//version with 4 states in ensemble
Root_Density x(rho.Npts, rho.lambdamax);
@ -81,8 +73,6 @@ namespace ABACUS {
x.value[ix] += 2.0 * rho.value[ip] * rho.dlambda[ip] * atan ((x.lambda[ix] - rho.lambda[ip])/c_int);
}
x.value[ix] /= 2.0*PI; //normalization
//cout << x.lambda[ix] << "\t" << x.value[ix] << "\t" << rho.lambda[ix] "\t" << rho.value[ix] <<endl;
}
// Now carry on as per Discretized_LiebLin_Bethe_State:
@ -111,55 +101,53 @@ namespace ABACUS {
for (int i = 0; i < rho.Npts; ++i) {
integral_prev = integral;
integral += L * rho.value[i] * rho.dlambda[i];
//cout << x.value[i] << "\t" << integral << endl;
if (integral > Nfound + 0.5) {
// Subtle error: if the rho is too discontinuous, i.e. if more than one rapidity is found, must correct for this.
if (integral > Nfound + 1.5 && integral < Nfound + 2.5) { // found two rapidities
ABACUSerror("The distribution of particles is too discontinous for discretisation");
}
if (integral > Nfound + 1.5 && integral < Nfound + 2.5) { // found two rapidities
ABACUSerror("The distribution of particles is too discontinous for discretisation");
}
else {
// few variables to clarify the computations, they do not need to be vectors, not used outside this loop
//Ix2_found[Nfound] = 2.0 * L * (x.value[i] * (integral - Nfound - 0.5) + x.value[i-1] * (Nfound + 0.5 - integral_prev))/(integral - integral_prev);
Ix2_found[Nfound] = 2.0 * L * x.Return_Value(rho.lambda[i]);
else {
// few variables to clarify the computations, they do not need to be vectors, not used outside this loop
Ix2_found[Nfound] = 2.0 * L * x.Return_Value(rho.lambda[i]);
Ix2_left = floor(Ix2_found[Nfound]);
Ix2_left -= (Ix2_left + N + 1)%2 ? 1 : 0; //adjust parity
Ix2_left = floor(Ix2_found[Nfound]);
Ix2_left -= (Ix2_left + N + 1)%2 ? 1 : 0; //adjust parity
Ix2_right = ceil(Ix2_found[Nfound]);
Ix2_right += (Ix2_right + N + 1)%2 ? 1 : 0; //adjust parity
Ix2_right = ceil(Ix2_found[Nfound]);
Ix2_right += (Ix2_right + N + 1)%2 ? 1 : 0; //adjust parity
int Ix2_in = (Ix2_found[Nfound] > 0 ? Ix2_left : Ix2_right);
int Ix2_out = (Ix2_found[Nfound] > 0 ? Ix2_right : Ix2_left);
cout << rho.lambda[i] << "\t" << x.Return_Value(rho.lambda[i]) << "\t" << Ix2_found[Nfound] << endl;
int Ix2_in = (Ix2_found[Nfound] > 0 ? Ix2_left : Ix2_right);
int Ix2_out = (Ix2_found[Nfound] > 0 ? Ix2_right : Ix2_left);
cout << rho.lambda[i] << "\t" << x.Return_Value(rho.lambda[i]) << "\t" << Ix2_found[Nfound] << endl;
//choose the saddle point state and remember the uncertain choices
if(Ix2_found[Nfound] - Ix2_left < 0.5) {
state[0].Ix2[Nfound] = Ix2_left;
state[1].Ix2[Nfound] = Ix2_left;
state[2].Ix2[Nfound] = Ix2_left;
state[3].Ix2[Nfound] = Ix2_left;
}
else if (Ix2_right - Ix2_found[Nfound] < 0.5) {
state[0].Ix2[Nfound] = Ix2_right;
state[1].Ix2[Nfound] = Ix2_right;
state[2].Ix2[Nfound] = Ix2_right;
state[3].Ix2[Nfound] = Ix2_right;
}
else { //it's a kind of magic: the zeroth goes in whle the first goes out, the second goes left if the third goes right
state[0].Ix2[Nfound] = Ix2_in;
state[1].Ix2[Nfound] = Ix2_out;
state[2+change].Ix2[Nfound] = Ix2_left;
state[2+!change].Ix2[Nfound] = Ix2_right;
change = !change;
++n_moves;
}
Nfound++;
}
//choose the saddle point state and remember the uncertain choices
if(Ix2_found[Nfound] - Ix2_left < 0.5) {
state[0].Ix2[Nfound] = Ix2_left;
state[1].Ix2[Nfound] = Ix2_left;
state[2].Ix2[Nfound] = Ix2_left;
state[3].Ix2[Nfound] = Ix2_left;
}
else if (Ix2_right - Ix2_found[Nfound] < 0.5) {
state[0].Ix2[Nfound] = Ix2_right;
state[1].Ix2[Nfound] = Ix2_right;
state[2].Ix2[Nfound] = Ix2_right;
state[3].Ix2[Nfound] = Ix2_right;
}
else {
//it's a kind of magic: the zeroth goes in whle the first goes out,
//the second goes left if the third goes right
state[0].Ix2[Nfound] = Ix2_in;
state[1].Ix2[Nfound] = Ix2_out;
state[2+change].Ix2[Nfound] = Ix2_left;
state[2+!change].Ix2[Nfound] = Ix2_right;
change = !change;
++n_moves;
}
Nfound++;
}
}
//cout << "\ti = " << i << "\tintegral = " << integral << "\tNfound = " << Nfound << endl;
}
//cout << endl;
//fix state[3] and state[4]
for(int i=0; i<N-1; ++i) {
@ -184,659 +172,26 @@ namespace ABACUS {
if(!all_Diff) {
//check if the first two states are different
if(state[0].Ix2 == state[1].Ix2)
ABACUSerror("Cannot create 4 (nor 2) different states in LiebLin_Diagonal_State_Ensemble. Consider increasing system size");
ABACUSerror("Cannot create 4 (nor 2) different states in LiebLin_Diagonal_State_Ensemble. "
"Consider increasing system size");
else {
nstates = 2;
weight[0] = 0.5;
weight[1] = 0.5;
}
}
//set the weights accordingly to the distance between the states.
// int n_moves_2 = 0, n_moves_3 = 0;
// for(int i=0; i < N; ++i) {
// if (!state[0].Ix2.is_in(state[2].Ix2[i])) ++n_moves_2;
// if (!state[0].Ix2.is_in(state[3].Ix2[i])) ++n_moves_3;
// }
//
// n_moves_2 = min(n_moves_2, n_moves - n_moves_2);
// n_moves_3 = min(n_moves_3, n_moves - n_moves_3);
//
// weight[2] *= 2.0*n_moves_2/n_moves;
// weight[3] *= 2.0*n_moves_3/n_moves;
//
// DP sum_weight = weight[0] + weight[1] + weight[2] + weight[3];
for(int i=0; i<nstates; ++i) {
//weight[i] /= sum_weight;
state[i].Set_Label_from_Ix2(state[0].Ix2);
state[i].Compute_All(true);
}
cout << weight[0] << "\t" << state[0].Ix2 << endl << weight[0] << "\t" << state[1].Ix2 << endl;// << state[2].Ix2 << endl << state[3].Ix2 << endl;
cout << weight[0] << "\t" << state[0].Ix2 << endl << weight[0] << "\t" << state[1].Ix2 << endl;
return;
//old working version but not enough to saturate +fsumrule
/*
Root_Density x = rho;
for(int ix=0; ix<x.Npts; ++ix) {
x.value[ix] = x.lambda[ix];
for( int ip=0; ip<rho.Npts; ++ip) {
x.value[ix] += 2.0 * rho.value[ip] * rho.dlambda[ip] * atan ((x.lambda[ix] - rho.lambda[ip])/c_int);
}
x.value[ix] /= 2.0*PI; //normalization
}
// Now carry on as per Discretized_LiebLin_Bethe_State:
// Each time N \int_{-\infty}^\lambda d\lambda' \rho(\lambda') crosses a half integer, add a particle:
DP integral = 0.0;
DP integral_prev = 0.0;
int Nfound = 0;
Vect<DP> Ix2_found(0.0, N);
int Ix2_left, Ix2_right;
Vect<int> Ix2(N);
Vect<int> Ix2_uncertain(0, N);
Vect<int> index_uncertain(0, N);
int n_uncertain = 0, n_states_raw = 1;
for (int i = 0; i < rho.Npts; ++i) {
integral_prev = integral;
integral += L * rho.value[i] * rho.dlambda[i];
//cout << x.value[i] << "\t" << integral << endl;
if (integral > Nfound + 0.5) {
// Subtle error: if the rho is too discontinuous, i.e. if more than one rapidity is found, must correct for this.
if (integral > Nfound + 1.5 && integral < Nfound + 2.5) { // found two rapidities
ABACUSerror("The distribution of particles is too discontinous for discretisation");
}
else {
// few variables to clarify the computations, they do not need to be vectors, not used outside this loop
Ix2_found[Nfound] = 2.0 * L * (x.value[i] * (integral - Nfound - 0.5) + x.value[i-1] * (Nfound + 0.5 - integral_prev))/(integral - integral_prev);
Ix2_left = floor(Ix2_found[Nfound]);
Ix2_left -= (Ix2_left + N + 1)%2 ? 1 : 0; //adjust parity
Ix2_right = ceil(Ix2_found[Nfound]);
Ix2_right += (Ix2_right + N + 1)%2 ? 1 : 0; //adjust parity
//cout << Ix2_found[Nfound] << "\t";
//choose the saddle point state and remember the uncertain choices
if(Ix2_found[Nfound] - Ix2_left < 1) {
Ix2[Nfound] = Ix2_left;
if(Ix2_found[Nfound] - Ix2_left > 0.75) {
Ix2_uncertain[n_uncertain] = -1;
index_uncertain[n_uncertain] = Nfound;
++n_uncertain;
n_states_raw *= 2;
}
}
else if (Ix2_right - Ix2_found[Nfound] < 1) {
Ix2[Nfound] = Ix2_right;
if(Ix2_right - Ix2_found[Nfound] > 0.75) {
Ix2_uncertain[n_uncertain] = 1;
index_uncertain[n_uncertain] = Nfound;
++n_uncertain;
n_states_raw *= 2;
}
}
else ABACUSerror("Cannot deduce a quantum number from x(lambda)");
Nfound++;
}
}
//cout << "\ti = " << i << "\tintegral = " << integral << "\tNfound = " << Nfound << endl;
}
//cout << endl;
//cout << Ix2 << endl;
// create ensamble of states and compute its weights with respect to exact Ix2 saddle point
Vect<Vect<int> > Ix2states(Ix2, n_states_raw);
Vect<DP> Ix2weight(0.0, n_states_raw);
// Ix2states[0] = Ix2;
// Ix2weight[0] = ;
int n_states_proper = 0;
for(int i=0; i < n_states_raw; ++i) {
//only symmetric modifications
for(int mod_index = 0; mod_index<n_uncertain; ++mod_index) {
if((i & (1 << mod_index)) >> mod_index != 0) {
Ix2states[n_states_proper][index_uncertain[mod_index]] += (-2)*Ix2_uncertain[mod_index];
////Ix2states[state_index][N - 1 - hole_position[mod_index]] += (2)*holes[hole_position[mod_index]];
}
}
//check if it's a proper set of quantum numbers
bool OK = true;
for(int j=0; j<N-1; ++j) if(Ix2states[n_states_proper][j] == Ix2states[n_states_proper][j+1]) OK = false;
if(OK) {
DP sum = 0;
for(int j=0; j<N; ++j) sum += abs(Ix2_found[j] - Ix2states[n_states_proper][j]);
Ix2weight[n_states_proper] = exp(-sum);
n_states_proper++;
}
else Ix2states[n_states_proper] = Ix2;
}
//sort the states in increasing weight order;
Vect<int> index(0, n_states_raw);
for (int nrs = 0; nrs < n_states_raw; ++nrs) index[nrs] = nrs;
Ix2weight.QuickSort(index);
//cut the number of states if above 21 <- arbitrary number for now
nstates = min(n_states_proper, 21);
cout << n_states_raw << "\t" << n_states_proper << "\t" << nstates << endl;
//create ensamble of states with normalised weights and ordered accordingly
LiebLin_Bethe_State rhostate(c_int, N, L);
rhostate.Ix2 = Ix2;
rhostate.Compute_All(true);
state = Vect<LiebLin_Bethe_State>(rhostate, nstates);
weight = Vect<DP>(nstates);
DP sum_weight = 0.0;
for(int i=0; i<nstates; ++i) {
state[i].Ix2 = Ix2states[index[n_states_raw - i - 1]];
state[i].Set_Label_from_Ix2 (state[0].Ix2);
weight[i] = Ix2weight[n_states_raw - i - 1];
sum_weight += weight[i];
}
//renormalise
for(int i=0; i<nstates; ++i) weight[i] /= sum_weight;
// for(int i=0; i<nstates; ++i) {
// cout << weight[i] << "\t" << state[i].Ix2 << endl;
// }
return;
*/
//cout << rho_t.value << endl;
// different attempts - to delete soon
// ABACUSerror("Stop here.");
/*
// This function returns a state ensemble matching the continuous density rho.
// The logic closely resembles the one used in Discretized_LiebLin_Bethe_State.
// Now carry on as per Discretized_LiebLin_Bethe_State:
// Each time N \int_{-\infty}^\lambda d\lambda' \rho(\lambda') crosses a half integer, add a particle:
DP integral = 0.0;
DP integral_prev = 0.0;
int Nfound = 0;
Vect<DP> lambda_found(0.0, 2*N);
for (int i = 0; i < rho.Npts; ++i) {
integral_prev = integral;
integral += L * rho.value[i] * rho.dlambda[i];
//cout << x.value[i] << "\t" << integral << endl;
if (integral > Nfound + 0.5) {
cout << L*x.value[i] << "\t" << integral << endl;
// Subtle error: if the rho is too discontinuous, i.e. if more than one rapidity is found, must correct for this.
if (integral > Nfound + 1.5 && integral < Nfound + 2.5) { // found two rapidities
lambda_found[Nfound++] = 0.25 * (3.0 * rho.lambda[i-1] + rho.lambda[i]);
lambda_found[Nfound++] = 0.25 * (rho.lambda[i-1] + 3.0 * rho.lambda[i]);
}
else {
//lambda_found[Nfound] = rho.lambda[i];
// Better: center the lambda_found between these points:
//lambda_found[Nfound] = rho.lambda[i-1] + (rho.lambda[i] - rho.lambda[i-1]) * ((Nfound + 1.0) - integral_prev)/(integral - integral_prev);
lambda_found[Nfound] = 0.5 * (rho.lambda[i-1] + rho.lambda[i]);
Nfound++;
}
}
//cout << "\ti = " << i << "\tintegral = " << integral << "\tNfound = " << Nfound << endl;
}
//cout << "rho: " << rho.Npts << " points" << endl << rho.value << endl;
//cout << "sym: " << rho.value[0] << " " << rho.value[rho.value.size() - 1]
// << "\t" << rho.value[rho.value.size()/2] << " " << rho.value[rho.value.size()/2 + 1] << endl;
//cout << "Found " << Nfound << " particles." << endl;
//cout << "lambda_found = " << lambda_found << endl;
Vect<DP> lambda(N);
// Fill up the found rapidities:
for (int il = 0; il < ABACUS::min(N, Nfound); ++il) lambda[il] = lambda_found[il];
// If there are missing ones, put them at the end; ideally, this should never be called
for (int il = Nfound; il < N; ++il) lambda[il] = lambda_found[Nfound-1] + (il - Nfound + 1) * (lambda_found[Nfound-1] - lambda_found[Nfound-2]);
//cout << lambda << endl;
*/
//try a different method
//first determine bins, that is intervals in lambda which contain a single rapidity
/*
Vect<int> lambda_bin(0.0, N+1);
integral = 0.0;
Nfound = 0;
lambda_bin[0] = 0;
lambda_bin[N] = rho.Npts-1;
for(int i=0; i<rho.Npts; ++i) {
integral += L * rho.value[i] * rho.dlambda[i];
if (integral > Nfound + 1.0) lambda_bin[++Nfound] = i - (rho.lambda[i]>0);
}
//put rapidity at the mean value of the distribution inside the bin
for(int ib=0; ib < N; ++ib) {
lambda_found[ib] = 0.0;
for(int i=lambda_bin[ib]; i<lambda_bin[ib+1]; ++i) lambda_found[ib] += L * rho.value[i] * rho.lambda[i] * rho.dlambda[i];
}
//cout << lambda_found << endl;
for(int i=0; i<N; ++i) cout << L*lambda[i]/PI << "\t" << L*lambda_found[i]/PI << endl;
ABACUSerror("Stop here.");
*/
/*
// Calculate quantum numbers: 2\pi * (L lambda + \sum_j 2 atan((lambda - lambda_j)/c)) = I_j
// Use rounding.
Vect<DP> Ix2_exact(N);
for (int i = 0; i < N; ++i) {
DP sum = 0.0;
for (int j = 0; j < N; ++j) sum += 2.0 * atan((lambda[i] - lambda[j])/c_int);
Ix2_exact[i] = (L * lambda[i] + sum)/PI;
Ix2_left[i] = floor(Ix2_exact[i]);
Ix2_left[i] -= (Ix2_left[i] + N + 1)%2 ? 1 : 0;
Ix2_right[i] = ceil(Ix2_exact[i]);
Ix2_right[i] += (Ix2_right[i] + N + 1)%2 ? 1 : 0;
//cout << Ix2_left[i] << "\t" << Ix2_exact[i] << "\t" << Ix2_right[i] << endl;
//Ix2[i] = 2.0* int((L * lambda[i] + sum)/twoPI) + (N % 2) - 1;
// For N is even/odd, we want to round off to the nearest odd/even integer.
//Ix2[i] = 2.0 * floor((L* lambda[i] + sum)/twoPI + 0.5 * (N%2 ? 1 : 2)) + (N%2) - 1;
}
//cout << "Found quantum numbers " << endl << Ix2 << endl;
*/
/*
//create the reference state and mark possible hole positions
Vect<int> Ix2(N);
Vect<float> holes(0.0, N);
for(int i=0; i < N; ++i) {
if(Ix2_found[i] - Ix2_left[i] < 1) {
Ix2[i] = Ix2_left[i];
if(Ix2_found[i] - Ix2_left[i] > 0.75) holes[i] = -1;
}
else {
Ix2[i] = Ix2_right[i];
if(Ix2_right[i] - Ix2_found[i] > 0.75) holes[i] = 1;
}
}
*/
// cout << endl << Ix2 << endl;
// cout << endl << holes << endl;
/*
//count number of possible states
int n = 0;
for(int i=0; i < N; ++i) {
if(holes[i] != 0) ++n;
}
int n_states_raw = 1;
*/
/* only symmetric modifications
for(int i=0; i<0.5*n; ++i) n_states_raw *= 2.0; //we count only symmetric modiications
Vect<Vect<int> > Ix2states(Ix2, n_states_raw);
Vect<int> hole_position(0, 0.5*n);
int hole_index = 0;
for(int i=N/2 + N%2; i<N; ++i) {
if(holes[i] != 0) hole_position[hole_index++] = i;
}
//create modifications, we use bit representation of integers between 0 and n_states-1 treating zero as no change and 1 as mutltiplication by -1
int state_index = 1;
for(int i=1; i < n_states_raw; ++i) {
//only symmetric modifications
for(int mod_index = 0; mod_index<0.5*n; ++mod_index) {
if((i & (1 << mod_index)) >> mod_index != 0) {
Ix2states[state_index][hole_position[mod_index]] += (-2)*holes[hole_position[mod_index]];
Ix2states[state_index][N - 1 - hole_position[mod_index]] += (2)*holes[hole_position[mod_index]];
}
}
//check if it's a proper set of quantum numbers
bool OK = true;
for(int j=0; j<N-1; ++j) if(Ix2states[state_index][j] == Ix2states[state_index][j+1]) OK = false;
if(OK) state_index++;
else Ix2states[state_index] = Ix2;
}
*/
/*
for(int i=0; i<n; ++i) n_states_raw *= 2.0; //we count all posibilities
Vect<Vect<int> > Ix2states(Ix2, n_states_raw);
Vect<int> hole_position(0, n);
int hole_index = 0;
for(int i=0; i<N; ++i) {
if(holes[i] != 0) hole_position[hole_index++] = i;
}
//create modifications, we use bit representation of integers between 0 and n_states-1 treating zero as no change and 1 as mutltiplication by -1
int state_index = 1;
for(int i=1; i < n_states_raw; ++i) {
//only symmetric modifications
for(int mod_index = 0; mod_index<n; ++mod_index) {
if((i & (1 << mod_index)) >> mod_index != 0) {
Ix2states[state_index][hole_position[mod_index]] += (-2)*holes[hole_position[mod_index]];
//Ix2states[state_index][N - 1 - hole_position[mod_index]] += (2)*holes[hole_position[mod_index]];
}
}
//check if it's a proper set of quantum numbers
bool OK = true;
for(int j=0; j<N-1; ++j) if(Ix2states[state_index][j] == Ix2states[state_index][j+1]) OK = false;
if(OK) state_index++;
else Ix2states[state_index] = Ix2;
}
*/
/*
n_states_raw = state_index;
// for(int i=0; i<n_states; ++i) cout << Ix2states[i] << endl;
LiebLin_Bethe_State rhostate(c_int, N, L);
rhostate.Ix2 = Ix2;
rhostate.Compute_All(true);
Vect<LiebLin_Bethe_State> state_raw = Vect<LiebLin_Bethe_State>(rhostate, n_states_raw);
Vect<DP> weight_raw(0.0, n_states_raw);
*/
/*
DP energy_rho = 0;
for (int i = 0; i < rho.Npts; ++i) {
energy_rho += L * rho.value[i] * rho.dlambda[i] * rho.lambda[i] * rho.lambda[i];
}
cout << energy_rho << endl;
DP energy_discrete = 0;
for (int i=0; i < N; ++i) {
energy_discrete += lambda[i] * lambda[i];
}
energy_discrete /= N;
cout << energy_discrete;
*/
/*
DP sum_weight_raw = 0.0;
for(int i=0; i<n_states_raw; ++i) {
//state_raw[i].Ix2 = Ix2states[i];
//state_raw[i].Set_Label_from_Ix2 (state_raw[0].Ix2);
//state_raw[i].Compute_All(true);
DP sum = 0;
for(int j=0; j<N; ++j) sum += fabs(Ix2states[i][j] - Ix2_found[j]);
weight_raw[i] = exp(sum)/L;
sum_weight_raw += weight_raw[i];
}
for(int i=0; i<n_states_raw; ++i) weight_raw[i] /= sum_weight_raw;
// Order the weights in decreasing value:
Vect<int> index(n_states_raw);
for (int nrs = 0; nrs < n_states_raw; ++nrs) index[nrs] = nrs;
weight_raw.QuickSort(index);
//nstates = 0;
//for(int i=0; i<n_states_raw; ++i) if (weight_raw[i] > 0.01) ++nstates;
nstates = ABACUS::min(n_states_raw, 21);
cout << nstates << endl;
state = Vect<LiebLin_Bethe_State>(rhostate, nstates);
weight = Vect<DP>(nstates);
DP sum_weight = 0.0;
for(int i=0; i<nstates; ++i) {
state[i].Ix2 = Ix2states[index[i]];
state[i].Set_Label_from_Ix2 (state[0].Ix2);
weight[i] = weight_raw[index[i]];
sum_weight += weight[i];
}
//renormalise
for(int i=0; i<nstates; ++i) weight[i] /= sum_weight;
for(int i=0; i<nstates; ++i) {
cout << weight[i] << "\t" << state[i].Ix2 << endl;
}
*/
//ABACUSerror("Stop here.");
// end of different attempts
/*
// Check that the quantum numbers are all distinct:
bool allOK = false;
while (!allOK) {
for (int i = 0; i < N-1; ++i) if (Ix2[i] == Ix2[i+1] && Ix2[i] < 0) Ix2[i] -= 2;
for (int i = 1; i < N; ++i) if (Ix2[i] == Ix2[i-1] && Ix2[i] > 0) Ix2[i] += 2;
allOK = true;
for (int i = 0; i < N-1; ++i) if (Ix2[i] == Ix2[i+1]) allOK = false;
}
//cout << "Found modified quantum numbers " << endl << Ix2 << endl;
LiebLin_Bethe_State rhostate(c_int, N, L);
rhostate.Ix2 = Ix2;
rhostate.Compute_All(true);
//cout << "rapidities of state found: " << rhostate.lambda << endl;
// Until here, the code is identical to that in Discretized_LiebLin_Bethe_State.
// Construct states in the vicinity by going through type 2 descendents recursively:
int ndesc_type2 = 0;
int* ndesc_type2_ptr = &ndesc_type2;
Generate_type_2_descendents (rhostate, ndesc_type2_ptr, rhostate);
cout << "Found " << ndesc_type2 << " descendents for state " << rhostate << endl;
//ABACUSerror("Stop here...");
// Now try to construct states in the vicinity.
int nrstates1mod = 1;
for (int i = 0; i < N; ++i) {
if (i == 0 || Ix2[i-1] < Ix2[i] - 2) nrstates1mod++;
if (i == N-1 || Ix2[i+1] > Ix2[i] + 2) nrstates1mod++;
}
//if (nrstates1mod < nstates_req) ABACUSerror("nrstates1mod < nstates_req in LiebLin_Diagonal_State_Ensemble.");
nstates = nrstates1mod;
Vect<Vect<int> > Ix2states1mod(nrstates1mod);
for (int nrs = 0; nrs < nrstates1mod; ++nrs) Ix2states1mod[nrs] = Vect<int> (N);
int nfound = 0;
Ix2states1mod[nfound++] = Ix2; // this is the sp state
for (int i = 0; i < N; ++i) {
if (i == 0 || Ix2[i-1] < Ix2[i] - 2) {
Ix2states1mod[nfound] = Ix2;
Ix2states1mod[nfound++][i] -= 2;
}
if (i == N-1 || Ix2[i+1] > Ix2[i] + 2) {
Ix2states1mod[nfound] = Ix2;
Ix2states1mod[nfound++][i] += 2;
}
}
// Evaluate the weight of all found states:
Vect<DP> rawweight(nrstates1mod);
for (int nrs = 0; nrs < nrstates1mod; ++nrs) {
DP sumweight = 0.0;
for (int i = 0; i < N; ++i) sumweight += fabs(Ix2states1mod[nrs][i] - Ix2_exact[i]);
rawweight[nrs] = exp(-sumweight/log(L));
}
// Order the weights in decreasing value:
Vect<int> index(nrstates1mod);
for (int nrs = 0; nrs < nrstates1mod; ++nrs) index[nrs] = nrs;
rawweight.QuickSort(index);
// Calculate weight normalization:
DP weightnorm = 0.0;
//for (int ns = 0; ns < nstates_req; ++ns) weightnorm += rawweight[nrstates1mod - 1 - ns];
for (int ns = 0; ns < nstates; ++ns) weightnorm += rawweight[nrstates1mod - 1 - ns];
state = Vect<LiebLin_Bethe_State>(rhostate, nstates);
weight = Vect<DP> (nstates);
for (int ns = 0; ns < nstates; ++ns) {
weight[ns] = rawweight[nrstates1mod - 1 - ns]/weightnorm;
state[ns].Ix2 = Ix2states1mod[index[nrstates1mod - 1 - ns] ];
state[ns].Set_Label_from_Ix2 (rhostate.Ix2);
state[ns].Compute_All(true);
}
*/
}
/*
LiebLin_Diagonal_State_Ensemble::LiebLin_Diagonal_State_Ensemble (DP c_int, DP L, int N, const Root_Density& rho, int nstates_req)
: nstates(nstates_req)
{
// This function returns a state ensemble matching the continuous density rho.
// The logic closely resembles the one used in Discretized_LiebLin_Bethe_State.
// Each `exact' (from rho) quantum number is matched to its two possible values,
// assigning a probability to each according to the proximity of the quantum number values.
// The set is then ordered in energy, and split into nstates_req boxes from which one
// representative is selected, and given the probability = sum of probabilities in the box.
// Begin as per Discretized_LiebLin_Bethe_State, to find the saddle-point state.
// Each time N \int_{-\infty}^\lambda d\lambda' \rho(\lambda') crosses a half integer, add a particle:
DP integral = 0.0;
DP integral_prev = 0.0;
int Nfound = 0;
Vect<DP> lambda_found(0.0, 2*N);
for (int i = 0; i < rho.Npts; ++i) {
integral_prev = integral;
integral += L * rho.value[i] * rho.dlambda[i];
if (integral > Nfound + 0.5) {
// Subtle error: if the rho is too discontinuous, i.e. if more than one rapidity is found, must correct for this.
if (integral > Nfound + 1.5 && integral < Nfound + 2.5) { // found two rapidities
lambda_found[Nfound++] = 0.25 * (3.0 * rho.lambda[i-1] + rho.lambda[i]);
lambda_found[Nfound++] = 0.25 * (rho.lambda[i-1] + 3.0 * rho.lambda[i]);
}
else {
//lambda_found[Nfound] = rho.lambda[i];
// Better: center the lambda_found between these points:
//lambda_found[Nfound] = rho.lambda[i-1] + (rho.lambda[i] - rho.lambda[i-1]) * ((Nfound + 1.0) - integral_prev)/(integral - integral_prev);
lambda_found[Nfound] = 0.5 * (rho.lambda[i-1] + rho.lambda[i]);
Nfound++;
}
}
//cout << "\ti = " << i << "\tintegral = " << integral << "\tNfound = " << Nfound << endl;
}
//cout << "rho: " << rho.Npts << " points" << endl << rho.value << endl;
//cout << "sym: " << rho.value[0] << " " << rho.value[rho.value.size() - 1]
// << "\t" << rho.value[rho.value.size()/2] << " " << rho.value[rho.value.size()/2 + 1] << endl;
//cout << "Found " << Nfound << " particles." << endl;
//cout << "lambda_found = " << lambda_found << endl;
Vect<DP> lambda(N);
// Fill up the found rapidities:
for (int il = 0; il < ABACUS::min(N, Nfound); ++il) lambda[il] = lambda_found[il];
// If there are missing ones, put them at the end; ideally, this should never be called
for (int il = Nfound; il < N; ++il) lambda[il] = lambda_found[Nfound-1] + (il - Nfound + 1) * (lambda_found[Nfound-1] - lambda_found[Nfound-2]);
// Calculate quantum numbers: 2\pi * (L lambda + \sum_j 2 atan((lambda - lambda_j)/c)) = I_j
// Use rounding.
Vect<DP> Ix2_exact(N);
Vect<int> Ix2(N);
for (int i = 0; i < N; ++i) {
DP sum = 0.0;
for (int j = 0; j < N; ++j) sum += 2.0 * atan((lambda[i] - lambda[j])/c_int);
Ix2_exact[i] = (L * lambda[i] + sum)/PI;
//Ix2[i] = 2.0* int((L * lambda[i] + sum)/twoPI) + (N % 2) - 1;
// For N is even/odd, we want to round off to the nearest odd/even integer.
Ix2[i] = 2.0 * floor((L* lambda[i] + sum)/twoPI + 0.5 * (N%2 ? 1 : 2)) + (N%2) - 1;
}
//cout << "Found quantum numbers " << endl << Ix2 << endl;
// Check that the quantum numbers are all distinct:
bool allOK = false;
while (!allOK) {
for (int i = 0; i < N-1; ++i) if (Ix2[i] == Ix2[i+1] && Ix2[i] < 0) Ix2[i] -= 2;
for (int i = 1; i < N; ++i) if (Ix2[i] == Ix2[i-1] && Ix2[i] > 0) Ix2[i] += 2;
allOK = true;
for (int i = 0; i < N-1; ++i) if (Ix2[i] == Ix2[i+1]) allOK = false;
}
//cout << "Found modified quantum numbers " << endl << Ix2 << endl;
LiebLin_Bethe_State rhostate(c_int, N, L);
rhostate.Ix2 = Ix2;
rhostate.Compute_All(true);
//cout << "rapidities of state found: " << rhostate.lambda << endl;
// Until here, the code is identical to that in Discretized_LiebLin_Bethe_State.
// Now try to construct states in the vicinity.
int nrstates1mod = 1;
for (int i = 0; i < N; ++i) {
if (i == 0 || Ix2[i-1] < Ix2[i] - 2) nrstates1mod++;
if (i == N-1 || Ix2[i+1] > Ix2[i] + 2) nrstates1mod++;
}
if (nrstates1mod < nstates_req) ABACUSerror("nrstates1mod < nstates_req in LiebLin_Diagonal_State_Ensemble.");
Vect<Vect<int> > Ix2states1mod(nrstates1mod);
for (int nrs = 0; nrs < nrstates1mod; ++nrs) Ix2states1mod[nrs] = Vect<int> (N);
int nfound = 0;
Ix2states1mod[nfound++] = Ix2; // this is the sp state
for (int i = 0; i < N; ++i) {
if (i == 0 || Ix2[i-1] < Ix2[i] - 2) {
Ix2states1mod[nfound] = Ix2;
Ix2states1mod[nfound++][i] -= 2;
}
if (i == N-1 || Ix2[i+1] > Ix2[i] + 2) {
Ix2states1mod[nfound] = Ix2;
Ix2states1mod[nfound++][i] += 2;
}
}
// Evaluate the weight of all found states:
Vect<DP> rawweight(nrstates1mod);
for (int nrs = 0; nrs < nrstates1mod; ++nrs) {
DP sumweight = 0.0;
for (int i = 0; i < N; ++i) sumweight += fabs(Ix2states1mod[nrs][i] - Ix2_exact[i]);
rawweight[nrs] = exp(-sumweight/log(L));
}
// Order the weights in decreasing value:
Vect<int> index(nrstates1mod);
for (int nrs = 0; nrs < nrstates1mod; ++nrs) index[nrs] = nrs;
rawweight.QuickSort(index);
// Calculate weight normalization:
DP weightnorm = 0.0;
for (int ns = 0; ns < nstates_req; ++ns) weightnorm += rawweight[nrstates1mod - 1 - ns];
state = Vect<LiebLin_Bethe_State>(rhostate, nstates_req);
weight = Vect<DP> (nstates_req);
for (int ns = 0; ns < nstates_req; ++ns) {
weight[ns] = rawweight[nrstates1mod - 1 - ns]/weightnorm;
state[ns].Ix2 = Ix2states1mod[index[nrstates1mod - 1 - ns] ];
state[ns].Set_Label_from_Ix2 (rhostate.Ix2);
state[ns].Compute_All(true);
}
}
*/
LiebLin_Diagonal_State_Ensemble& LiebLin_Diagonal_State_Ensemble::operator= (const LiebLin_Diagonal_State_Ensemble& rhs)
{
if (this != &rhs) {
@ -858,7 +213,6 @@ namespace ABACUS {
while (getline(infile, dummy)) ++nrlines;
infile.close();
//cout << "Found " << nrlines << " lines in ens file." << endl;
nstates = nrlines;
LiebLin_Bethe_State examplestate (c_int, L, N);
state = Vect<LiebLin_Bethe_State> (examplestate, nstates);
@ -893,7 +247,6 @@ namespace ABACUS {
}
//LiebLin_Diagonal_State_Ensemble LiebLin_Thermal_Saddle_Point_Ensemble (DP c_int, DP L, int N, DP kBT, int nstates_req)
LiebLin_Diagonal_State_Ensemble LiebLin_Thermal_Saddle_Point_Ensemble (DP c_int, DP L, int N, DP kBT)
{
// This function constructs a manifold of states around the thermal saddle-point.
@ -915,7 +268,6 @@ namespace ABACUS {
cout << "ebar: " << TBAsol.ebar << endl;
cout << ensemble.state[0].E << endl;
//return(LiebLin_Diagonal_State_Ensemble (c_int, L, N, TBAsol.rho, nstates_req));
return(ensemble);
}

View File

@ -20,12 +20,10 @@ using namespace ABACUS;
namespace ABACUS {
//DP Sumrule_Factor (char whichDSF, LiebLin_Bethe_State& RefState, DP Chem_Pot, bool fixed_iK, int iKneeded)
DP Sumrule_Factor (char whichDSF, LiebLin_Bethe_State& RefState, DP Chem_Pot, int iKmin, int iKmax)
{
DP sumrule_factor = 1.0;
//if (!fixed_iK) {
if (iKmin != iKmax) {
if (whichDSF == 'Z') sumrule_factor = 1.0;
else if (whichDSF == 'd' || whichDSF == '1') {
@ -33,28 +31,15 @@ namespace ABACUS {
// Here, we use a measure decreasing in K with K^2.
// We sum up omega * MEsq/(iK^2) for all values of iKmin <= iK <= iKmax, discounting iK == 0 (where DSF vanishes)
// We therefore have (N/L) x L^{-1} x (2\pi/L)^2 x (iKmax - iKmin + 1) = 4 \pi^2 x N x (iKmax - iKmin + 1)/L^4
// Discounting iK == 0 (where DSF vanishes), if iKmin <= 0 && iKmax >= 0 (in which case 0 is containted in [iKmin, iKmax])
// Discounting iK == 0 (where DSF vanishes),
// if iKmin <= 0 && iKmax >= 0 (in which case 0 is containted in [iKmin, iKmax])
sumrule_factor = (iKmin <= 0 && iKmax >= 0) ?
(RefState.L * RefState.L * RefState.L * RefState.L)/(4.0 * PI * PI * RefState.N * (iKmax - iKmin))
: (RefState.L * RefState.L * RefState.L * RefState.L)/(4.0 * PI * PI * RefState.N * (iKmax - iKmin + 1));
/*
// Measure using the g2(0) + delta function: // DOES NOT WORK VERY WELL
DP dE0_dc = LiebLin_dE0_dc (RefState.c_int, RefState.L, RefState.N);
//sumrule_factor = 1.0/((dE0_dc + (2.0 * RefState.Tableau[0].Ncols + 1.0)*RefState.N/RefState.L)/RefState.L);
// Assume that iKmin == 0 here:
//sumrule_factor = 1.0/((dE0_dc + (2*iKmax + 1)*RefState.N/RefState.L)/RefState.L);
// For iKmin != 0:
sumrule_factor = 1.0/((dE0_dc + (iKmax - iKmin + 1)*RefState.N/RefState.L)/RefState.L);
*/
}
// For the Green's function, it's the delta function \delta(x = 0) plus the density:
//else if (whichDSF == 'g') sumrule_factor = 1.0/((2.0 * RefState.Tableau[0].Ncols + 1.0)/RefState.L + RefState.N/RefState.L);
// Assume that iKmin == 0 here:
//else if (whichDSF == 'g') sumrule_factor = 1.0/(2.0* iKmax + 1.0)/RefState.L + RefState.N/RefState.L);
else if (whichDSF == 'g')
sumrule_factor = 1.0/((abs(iKmax - iKmin) + 1.0)/RefState.L + RefState.N/RefState.L);
//sumrule_factor = 1.0/((pow(twoPI * iKmax/RefState.L, 2.0) - Chem_Pot + 4.0 * RefState.c_int * RefState.N/RefState.L)/RefState.L);
// For the one-body function, it's just the density:
else if (whichDSF == 'o') sumrule_factor = RefState.L/RefState.N;
else if (whichDSF == 'q') sumrule_factor = 1.0;
@ -63,21 +48,16 @@ namespace ABACUS {
else ABACUSerror("whichDSF option not consistent in Sumrule_Factor");
}
//else if (fixed_iK) {
else if (iKmin == iKmax) {
if (whichDSF == 'Z') sumrule_factor = 1.0;
else if (whichDSF == 'd' || whichDSF == '1')
//// We sum up omega * MEsq/(iK^2): this should give (1/L) x (N/L) x k^2 = N x (2\pi)^2/L^4
//sumrule_factor = pow(RefState.L, 4.0)/(4.0 * PI * PI * RefState.N);
// We sum up omega * MEsq
//sumrule_factor = pow(RefState.L, 4.0)/(4.0 * PI * PI * iKneeded * iKneeded * RefState.N);
sumrule_factor = pow(RefState.L, 4.0)/(4.0 * PI * PI * iKmax * iKmax * RefState.N);
else if (whichDSF == 'g' || whichDSF == 'o') {
// We sum up omega * MEsq
//sumrule_factor = 1.0/((pow(twoPI * iKneeded/RefState.L, 2.0) - Chem_Pot + 4.0 * RefState.c_int * RefState.N/RefState.L)/RefState.L);
sumrule_factor = 1.0/((pow(twoPI * iKmax/RefState.L, 2.0) - Chem_Pot + 4.0 * RefState.c_int * RefState.N/RefState.L)/RefState.L);
sumrule_factor = 1.0/((pow(twoPI * iKmax/RefState.L, 2.0) - Chem_Pot
+ 4.0 * RefState.c_int * RefState.N/RefState.L)/RefState.L);
}
//else if (whichDSF == 'o') sumrule_factor = RefState.L/RefState.N;
else if (whichDSF == 'q') sumrule_factor = 1.0;
else if (whichDSF == 'B') sumrule_factor = 1.0;
else if (whichDSF == 'C') sumrule_factor = 1.0;
@ -87,7 +67,8 @@ namespace ABACUS {
return(sumrule_factor);
}
void Evaluate_F_Sumrule (char whichDSF, const LiebLin_Bethe_State& RefState, DP Chem_Pot, int iKmin, int iKmax, const char* RAW_Cstr, const char* FSR_Cstr)
void Evaluate_F_Sumrule (char whichDSF, const LiebLin_Bethe_State& RefState, DP Chem_Pot,
int iKmin, int iKmax, const char* RAW_Cstr, const char* FSR_Cstr)
{
ifstream infile;
@ -98,8 +79,6 @@ namespace ABACUS {
}
// We run through the data file to check the f sumrule at each positive momenta:
//int iK_UL = RefState.Tableau[0].Ncols; // this is iK_UL
//Vect<DP> Sum_omega_MEsq(0.0, iK_UL + 1);
Vect_DP Sum_omega_MEsq (0.0, iKmax - iKmin + 1);
Vect_DP Sum_abs_omega_MEsq (0.0, iKmax - iKmin + 1);
@ -107,7 +86,6 @@ namespace ABACUS {
DP omega, ME;
int iK;
//int conv;
DP dev;
string label;
int nr, nl;
@ -118,7 +96,6 @@ namespace ABACUS {
nraw++;
infile >> omega >> iK >> ME >> dev >> label;
if (whichDSF == '1') infile >> nr >> nl;
//if (iK > 0 && iK <= iK_UL) Sum_omega_MEsq[iK] += omega * MEsq;
if (iK >= iKmin && iK <= iKmax) Sum_omega_MEsq[iK - iKmin] += omega * ME * ME;
if (iK >= iKmin && iK <= iKmax) Sum_abs_omega_MEsq[iK - iKmin] += fabs(omega * ME * ME);
Sum_MEsq += ME * ME;
@ -126,25 +103,18 @@ namespace ABACUS {
infile.close();
//cout << "Read " << nraw << " entries in raw file." << endl;
ofstream outfile;
outfile.open(FSR_Cstr);
outfile.precision(16);
if (whichDSF == 'd' || whichDSF == '1') {
/*
outfile << 0 << "\t" << 1; // full saturation at k = 0 !
for (int i = 1; i <= iK_UL; ++i)
outfile << endl << i << "\t" << Sum_omega_MEsq[i] * RefState.L * RefState.L
* RefState.L * RefState.L/(4.0 * PI * PI * i * i * RefState.N);
*/
for (int i = iKmin; i <= iKmax; ++i) {
if (i > iKmin) outfile << endl;
//outfile << i << "\t" << Sum_omega_MEsq[i - iKmin] * pow(RefState.L, 4.0)/(pow(2.0 * PI * ABACUS::max(abs(i), 1), 2.0) * RefState.N);
outfile << i << "\t" << Sum_omega_MEsq[i - iKmin] * pow(RefState.L, 4.0)/(pow(2.0 * PI * ABACUS::max(abs(i), 1), 2.0) * RefState.N)
outfile << i << "\t" << Sum_omega_MEsq[i - iKmin] * pow(RefState.L, 4.0)
/(pow(2.0 * PI * ABACUS::max(abs(i), 1), 2.0) * RefState.N)
// Include average of result at +iK and -iK in a third column: iK is at index index(iK) = iK - iKmin
// so -iK is at index index(-iK) = -iK - iKmin
// We can only use this index if it is >= 0 and < iKmax - iKmin + 1, otherwise third column is copy of second:
@ -155,21 +125,13 @@ namespace ABACUS {
}
}
else if (whichDSF == 'g' || whichDSF == 'o') {
/*
for (int i = 0; i <= iK_UL; ++i)
outfile << endl << i << "\t" << Sum_omega_MEsq[i] * RefState.L
/((4.0 * PI * PI * i * i)/(RefState.L * RefState.L) - Chem_Pot + 4.0 * RefState.c_int * RefState.N/RefState.L);
//cout << "Sum_MEsq = " << Sum_MEsq << "\tN/L = " << RefState.N/RefState.L << endl;
*/
for (int i = iKmin; i <= iKmax; ++i) {
if (i > iKmin) outfile << endl;
//outfile << i << "\t" << Sum_omega_MEsq[i - iKmin] * RefState.L
///((4.0 * PI * PI * i * i)/(RefState.L * RefState.L) - Chem_Pot + 4.0 * RefState.c_int * RefState.N/RefState.L);
outfile << i << "\t" << Sum_omega_MEsq[i - iKmin] * RefState.L
/((4.0 * PI * PI * i * i)/(RefState.L * RefState.L) - Chem_Pot + 4.0 * RefState.c_int * RefState.N/RefState.L)
<< "\t" << ((i + iKmin <= 0 && -i < iKmax + 1) ?
0.5 * (Sum_omega_MEsq[i - iKmin] + Sum_omega_MEsq[-i - iKmin]) : Sum_omega_MEsq[i - iKmin])
* RefState.L/((4.0 * PI * PI * i * i)/(RefState.L * RefState.L) - Chem_Pot + 4.0 * RefState.c_int * RefState.N/RefState.L);
* RefState.L/((4.0 * PI * PI * i * i)/(RefState.L * RefState.L) - Chem_Pot + 4.0 * RefState.c_int * RefState.N/RefState.L);
}
}
@ -177,7 +139,8 @@ namespace ABACUS {
}
void Evaluate_F_Sumrule (string prefix, char whichDSF, const LiebLin_Bethe_State& RefState, DP Chem_Pot, int iKmin, int iKmax)
void Evaluate_F_Sumrule (string prefix, char whichDSF, const LiebLin_Bethe_State& RefState,
DP Chem_Pot, int iKmin, int iKmax)
{
stringstream RAW_stringstream; string RAW_string;
@ -193,7 +156,8 @@ namespace ABACUS {
}
// Using diagonal state ensemble:
void Evaluate_F_Sumrule (char whichDSF, DP c_int, DP L, int N, DP kBT, int nstates_req, DP Chem_Pot, int iKmin, int iKmax, const char* FSR_Cstr)
void Evaluate_F_Sumrule (char whichDSF, DP c_int, DP L, int N, DP kBT, int nstates_req,
DP Chem_Pot, int iKmin, int iKmax, const char* FSR_Cstr)
{
// We run through the data file to check the f sumrule at each positive momenta:
@ -203,7 +167,6 @@ namespace ABACUS {
DP omega, ME;
int iK;
//int conv;
DP dev;
string label;
int nr, nl;
@ -212,7 +175,6 @@ namespace ABACUS {
LiebLin_Diagonal_State_Ensemble ensemble;
stringstream ensfilestrstream;
//ensfilestrstream << "LiebLin_c_int_" << c_int << "_L_" << L << "_N_" << N << "_kBT_" << kBT << "_ns_" << nstates_req << ".ens";
ensfilestrstream << "LiebLin_c_int_" << c_int << "_L_" << L << "_N_" << N << "_kBT_" << kBT << ".ens";
string ensfilestr = ensfilestrstream.str();
const char* ensfile_Cstr = ensfilestr.c_str();
@ -223,8 +185,8 @@ namespace ABACUS {
// Define the raw input file name:
stringstream filenameprefix;
//Data_File_Name (filenameprefix, whichDSF, iKmin, iKmax, kBT, ensemble.state[ns], ensemble.state[ns], ensemble.state[ns].label);
Data_File_Name (filenameprefix, whichDSF, iKmin, iKmax, 0.0, ensemble.state[ns], ensemble.state[ns], ensemble.state[ns].label);
Data_File_Name (filenameprefix, whichDSF, iKmin, iKmax, 0.0, ensemble.state[ns],
ensemble.state[ns], ensemble.state[ns].label);
string prefix = filenameprefix.str();
stringstream RAW_stringstream; string RAW_string;
RAW_stringstream << prefix << ".raw";
@ -240,7 +202,6 @@ namespace ABACUS {
while (infile.peek() != EOF) {
infile >> omega >> iK >> ME >> dev >> label;
if (whichDSF == '1') infile >> nr >> nl;
//if (iK > 0 && iK <= iK_UL) Sum_omega_MEsq[iK] += omega * MEsq;
if (iK >= iKmin && iK <= iKmax) Sum_omega_MEsq[iK - iKmin] += ensemble.weight[ns] * omega * ME * ME;
Sum_MEsq += ensemble.weight[ns] * ME * ME;
}
@ -255,16 +216,10 @@ namespace ABACUS {
outfile.precision(16);
if (whichDSF == 'd' || whichDSF == '1') {
/*
outfile << 0 << "\t" << 1; // full saturation at k = 0 !
for (int i = 1; i <= iK_UL; ++i)
outfile << endl << i << "\t" << Sum_omega_MEsq[i] * RefState.L * RefState.L
* RefState.L * RefState.L/(4.0 * PI * PI * i * i * RefState.N);
*/
for (int i = iKmin; i <= iKmax; ++i) {
if (i > iKmin) outfile << endl;
//outfile << i << "\t" << Sum_omega_MEsq[i - iKmin] * pow(RefState.L, 4.0)/(pow(2.0 * PI * ABACUS::max(abs(i), 1), 2.0) * RefState.N);
outfile << i << "\t" << Sum_omega_MEsq[i - iKmin] * pow(RefState.L, 4.0)/(pow(2.0 * PI * ABACUS::max(abs(i), 1), 2.0) * RefState.N)
outfile << i << "\t" << Sum_omega_MEsq[i - iKmin] * pow(RefState.L, 4.0)
/(pow(2.0 * PI * ABACUS::max(abs(i), 1), 2.0) * RefState.N)
// Include average of result at +iK and -iK in a third column: iK is at index index(iK) = iK - iKmin
// so -iK is at index index(-iK) = -iK - iKmin
// We can only use this index if it is >= 0 and < iKmax - iKmin + 1, otherwise third column is copy of second:
@ -275,21 +230,14 @@ namespace ABACUS {
}
}
else if (whichDSF == 'g' || whichDSF == 'o') {
/*
for (int i = 0; i <= iK_UL; ++i)
outfile << endl << i << "\t" << Sum_omega_MEsq[i] * RefState.L
/((4.0 * PI * PI * i * i)/(RefState.L * RefState.L) - Chem_Pot + 4.0 * RefState.c_int * RefState.N/RefState.L);
//cout << "Sum_MEsq = " << Sum_MEsq << "\tN/L = " << RefState.N/RefState.L << endl;
*/
for (int i = iKmin; i <= iKmax; ++i) {
if (i > iKmin) outfile << endl;
//outfile << i << "\t" << Sum_omega_MEsq[i - iKmin] * RefState.L
///((4.0 * PI * PI * i * i)/(RefState.L * RefState.L) - Chem_Pot + 4.0 * RefState.c_int * RefState.N/RefState.L);
outfile << i << "\t" << Sum_omega_MEsq[i - iKmin] * RefState.L
/((4.0 * PI * PI * i * i)/(RefState.L * RefState.L) - Chem_Pot + 4.0 * RefState.c_int * RefState.N/RefState.L)
<< "\t" << ((i + iKmin <= 0 && -i < iKmax + 1) ?
0.5 * (Sum_omega_MEsq[i - iKmin] + Sum_omega_MEsq[-i - iKmin]) : Sum_omega_MEsq[i - iKmin])
* RefState.L/((4.0 * PI * PI * i * i)/(RefState.L * RefState.L) - Chem_Pot + 4.0 * RefState.c_int * RefState.N/RefState.L);
0.5 * (Sum_omega_MEsq[i - iKmin] + Sum_omega_MEsq[-i - iKmin])
: Sum_omega_MEsq[i - iKmin]) * RefState.L
/((4.0 * PI * PI * i * i)/(RefState.L * RefState.L) - Chem_Pot + 4.0 * RefState.c_int * RefState.N/RefState.L);
}
}

View File

@ -20,116 +20,6 @@ using namespace ABACUS;
namespace ABACUS {
/*
DP Entropy (LiebLin_Bethe_State& RefState, DP epsilon)
{
// This function calculates the entropy of a finite Lieb-Liniger state,
// using the quantum number space particle and hole densities.
// The densities are a sum of Gaussians with width epsilon.
// We calculate \rho (x) and \rho_h (x) for x_j on a fine lattice.
int Ix2max = RefState.Ix2.max();
int Ix2min = RefState.Ix2.min();
//cout << Ix2max << "\t" << Ix2min << endl;
// Give a bit of room for leftmost and rightmost particles Gaussians to attain asymptotic values:
Ix2max += int(10.0 * RefState.L * epsilon);
Ix2min -= int(10.0 * RefState.L * epsilon);
//cout << Ix2max << "\t" << Ix2min << endl;
DP xmax = Ix2max/(2.0* RefState.L);
DP xmin = Ix2min/(2.0* RefState.L);
//xmax += 10.0* epsilon;
//xmin -= 10.0* epsilon;
DP dx = 0.1/RefState.L;
int Nptsx = int((xmax - xmin)/dx);
Vect<bool> occupied (false, (Ix2max - Ix2min)/2 + 1); // whether there is a particle or not
for (int i = 0; i < RefState.N; ++i) occupied[(RefState.Ix2[i] - Ix2min)/2] = true;
Vect<double> rho(0.0, Nptsx);
Vect<double> rhoh(0.0, Nptsx);
//cout << xmin << "\t" << xmax << "\t" << dx << "\t" << Nptsx << endl;
DP x;
DP epsilonsq = epsilon * epsilon;
DP twoepsilonsq = 2.0 * epsilon * epsilon;
//Vect<DP> xparticle(RefState.N);
//for (int i = 0; i < RefState.N; ++i) xparticle[i] = RefState.Ix2[i]/(2.0* RefState.L);
Vect<DP> xarray((Ix2max - Ix2min)/2 + 1);
for (int i = 0; i < (Ix2max - Ix2min)/2 + 1; ++i) xarray[i] = (0.5*Ix2min + i)/RefState.L;
for (int ix = 0; ix < Nptsx; ++ix) {
x = xmin + dx * (ix + 0.5);
//for (int i = 0; i < RefState.N; ++i) rho[ix] += 1.0/((x - xparticle[i]) * (x - xparticle[i]) + epsilonsq);
//rho[ix] *= epsilon/(PI * RefState.L);
for (int i = 0; i < (Ix2max - Ix2min)/2 + 1; ++i) {
// Using Gaussians:
//if (occupied[i]) rho[ix] += exp(-(x - xarray[i]) * (x - xarray[i])/twoepsilonsq);
//else rhoh[ix] += exp(-(x - xarray[i]) * (x - xarray[i])/twoepsilonsq);
// Using Lorentzians:
if (occupied[i]) rho[ix] += 1.0/((x - xarray[i]) * (x - xarray[i]) + epsilonsq);
else rhoh[ix] += 1.0/((x - xarray[i]) * (x - xarray[i]) + epsilonsq);
}
//rho[ix] /= sqrt(twoPI) * epsilon * RefState.L;
//rhoh[ix] /= sqrt(twoPI) * epsilon * RefState.L;
rho[ix] *= epsilon/(PI * RefState.L);
rhoh[ix] *= epsilon/(PI * RefState.L);
//cout << ix << " x = " << x << "\trho = " << rho[ix] << "\trhoh = " << rhoh[ix] << "\trho + rhoh = " << rho[ix] + rhoh[ix] << endl;
}
// Now calculate the entropy:
complex<DP> entropy = 0.0;
DP Deltax = log(RefState.L)/RefState.L;
for (int ix = 0; ix < Nptsx; ++ix)
//entropy -= ln_Gamma (1.0 + rho[ix]) + ln_Gamma (2.0 - rho[ix]); // This is ln (\rho_tot choose \rho) with \rho_tot = 1.
entropy += ln_Gamma (RefState.L * (rho[ix] + rhoh[ix]) * Deltax + 1.0) - ln_Gamma(RefState.L * rho[ix] * Deltax + 1.0) - ln_Gamma (RefState.L * rhoh[ix] * Deltax + 1.0); // This is ln (\rho_tot choose \rho) with \rho_tot = 1.
entropy *= dx/Deltax;
//cout << "Entropy found " << entropy << "\t" << real(entropy) << endl;
return(real(entropy));
}
*/
/*
DP Entropy_rho (LiebLin_Bethe_State& RefState, int Delta)
{
// This function calculates the discrete entropy of a finite Lieb-Liniger state,
// counting the possible permutations within windows of fixed width.
// We assume that the quantum numbers are ordered.
// Calculate a density \rho_\Delta (x) for x_j on the lattice:
int iK_UL = ABACUS::max(RefState.Ix2[0], RefState.Ix2[RefState.N - 1]);
Vect<double> rhoD(0.0, 2* iK_UL);
int fourDeltasq = 4 * Delta * Delta;
for (int ix = 0; ix < 2* iK_UL; ++ix) {
// x = (-iK_UL + 1/2 + ix)/L
for (int i = 0; i < RefState.N; ++i) rhoD[ix] += 1.0/((-2*iK_UL + 1 + 2*ix -RefState.Ix2[i]) * (-2*iK_UL + 1 + 2*ix -RefState.Ix2[i]) + fourDeltasq);
rhoD[ix] *= 4.0 * Delta/PI;
//cout << "x = " << (-iK_UL + 1/2 + ix)/RefState.L << "\trhoD = " << rhoD[ix] << endl;
}
// Now calculate the entropy:
DP entropy = 0.0;
for (int ix = 0; ix < 2* iK_UL; ++ix)
entropy -= rhoD[ix] * log(rhoD[ix]) + (1.0 - rhoD[ix]) * log(1.0 - rhoD[ix]);
return(entropy);
}
*/
DP Entropy_Fixed_Delta (LiebLin_Bethe_State& RefState, int Delta)
{
@ -139,13 +29,13 @@ namespace ABACUS {
// We assume that the quantum numbers are ordered.
// Fill in vector of occupancies:
int nrIs = (RefState.Ix2[RefState.N-1] - RefState.Ix2[0])/2 + 1 + 2*Delta; // assume Ix2 are ordered, leave space of Delta on both sides
// assume Ix2 are ordered, leave space of Delta on both sides
int nrIs = (RefState.Ix2[RefState.N-1] - RefState.Ix2[0])/2 + 1 + 2*Delta;
Vect<int> occupancy(0, nrIs); // leave space of Delta on both sides
for (int i = 0; i < RefState.N; ++i) occupancy[Delta + (RefState.Ix2[i] -RefState.Ix2[0])/2] = 1;
// Check:
int ncheck = 0;
for (int i = 0; i < nrIs; ++i) if(occupancy[i] == 1) ncheck++;
//cout << "Check occupancy: " << endl << occupancy << endl;
if (ncheck != RefState.N) {
cout << ncheck << "\t" << RefState.N << endl;
ABACUSerror("Counting q numbers incorrectly in Entropy.");
@ -154,10 +44,6 @@ namespace ABACUS {
// Define some useful numbers:
Vect_DP oneoverDeltalnchoose(Delta + 1);
for (int i = 0; i <= Delta; ++i) oneoverDeltalnchoose[i] = ln_choose(Delta, i)/Delta;
//Vect_DP oneoverDeltalnchoosecheck(Delta + 1);
//for (int i = 0; i <= Delta; ++i) oneoverDeltalnchoosecheck[i] = log(DP(choose(Delta, i)))/Delta;
//cout << oneoverDeltalnchoose << endl;
//cout << oneoverDeltalnchoosecheck << endl;
// Compute entropy:
DP entropy = 0.0;
@ -185,288 +71,18 @@ namespace ABACUS {
int Delta = int(log(RefState.L));
return(Entropy (RefState, Delta));
}
/*
DP Canonical_Free_Energy (LiebLin_Bethe_State& RefState, DP kBT, int Delta)
{
return(RefState.E - kBT * Entropy (RefState, Delta));
}
DP Canonical_Free_Energy (LiebLin_Bethe_State& RefState, DP kBT, int Delta)
{
return(RefState.E - kBT * Entropy (RefState, Delta));
}
*/
DP Canonical_Free_Energy (LiebLin_Bethe_State& RefState, DP kBT)
{
return(RefState.E - kBT * Entropy (RefState));
}
/*
//LiebLin_Bethe_State Canonical_Saddle_Point_State (DP c_int, DP L, int N, DP kBT, int Delta)
LiebLin_Bethe_State Canonical_Saddle_Point_State_pre20110618 (DP c_int, DP L, int N, DP kBT, DP epsilon)
{
// This function returns the discretized state minimizing the canonical free energy
// F = E - T S.
LiebLin_Bethe_State spstate(c_int, L, N);
spstate.Compute_All (true);
if (kBT < 1.0e-3) return(spstate); // interpret as zero T case
LiebLin_Bethe_State spstateup = spstate;
LiebLin_Bethe_State spstatedown = spstate;
bool converged = false;
bool convergedati = false;
DP canfreeenstay, canfreeenup, canfreeendown;
DP Estay, Eup, Edown;
DP Sstay, Sup, Sdown;
while (!converged) {
spstate.Compute_All (false);
converged = true; // set to false if we change anything
// If we can minimize the free energy by changing the quantum number, we do:
// NOTE: we keep the state symmetric w/r to parity.
for (int i = 0; i < N/2; ++i) {
// Try to increase or decrease this quantum number
convergedati = false;
while (!convergedati) {
convergedati = true; // set to false if we change anything
Estay = spstate.E;
//Sstay = Entropy (spstate, Delta);
Sstay = Entropy (spstate, epsilon);
//canfreeenstay = Canonical_Free_Energy (spstate, kBT, Delta);
canfreeenstay = Estay - kBT * Sstay;
spstateup = spstate;
if (i == 0 || spstateup.Ix2[i-1] < spstateup.Ix2[i] - 2) {
spstateup.Ix2[i] -= 2;
spstateup.Ix2[N-1-i] += 2;
spstateup.Compute_All(false);
Eup = spstateup.E;
//Sup = Entropy(spstateup, Delta);
Sup = Entropy(spstateup, epsilon);
//canfreeenup = Canonical_Free_Energy (spstateup, kBT, Delta);
canfreeenup = Eup - kBT * Sup;
}
else canfreeenup = canfreeenstay + 1.0e-6;
spstatedown = spstate;
if (spstatedown.Ix2[i+1] > spstatedown.Ix2[i] + 2) {
spstatedown.Ix2[i] += 2;
spstatedown.Ix2[N-1-i] -= 2;
spstatedown.Compute_All(false);
Edown = spstatedown.E;
//Sdown = Entropy(spstatedown, Delta);
Sdown = Entropy(spstatedown, epsilon);
//canfreeendown = Canonical_Free_Energy (spstatedown, kBT, Delta);
canfreeendown = Edown - kBT * Sdown;
}
else canfreeendown = canfreeenstay + 1.0e-6;
//cout << "i = " << i << "\t" << spstate.Ix2[i] << "\t\t" << canfreeenstay << "\t" << canfreeenup << "\t" << canfreeendown
// << "\t\t" << Estay << "\t" << Eup << "\t" << Edown << "\t\t" << Sstay << "\t" << Sup << "\t" << Sdown << endl;
// Choose what to do:
if (canfreeenup < canfreeenstay && canfreeendown < canfreeenstay)
cout << canfreeenstay << "\t" << canfreeenup << "\t" << canfreeendown << "\tWarning: unclear option for minimization." << endl;
else if (canfreeenup < canfreeenstay) {
spstate = spstateup;
convergedati = false;
converged = false;
}
else if (canfreeendown < canfreeenstay) {
spstate = spstatedown;
convergedati = false;
converged = false;
}
// else do nothing.
} // while !convergedati
} // for i
} // while (!converged)
return(spstate);
}
*/
/* REMOVED FROM ++G_3 ONWARDS
//LiebLin_Bethe_State Canonical_Saddle_Point_State (DP c_int, DP L, int N, DP kBT, int Delta)
//LiebLin_Bethe_State Canonical_Saddle_Point_State (DP c_int, DP L, int N, DP kBT, DP epsilon)
LiebLin_Bethe_State Canonical_Saddle_Point_State_pre8 (DP c_int, DP L, int N, DP kBT)
{
// This function returns the discretized state minimizing the canonical free energy
// F = E - T S.
// Improvement on version pre20110618: allow for pairwise `in' and `out' movements
// keeping the energy the same to order 1/L^2 but changing the entropy.
// The regulator Delta also has become an `internal' parameter.
LiebLin_Bethe_State spstate(c_int, L, N);
spstate.Compute_All (true);
if (kBT < 1.0e-3) return(spstate); // interpret as zero T case
LiebLin_Bethe_State spstateup = spstate;
LiebLin_Bethe_State spstatedown = spstate;
LiebLin_Bethe_State spstatein = spstate;
LiebLin_Bethe_State spstateout = spstate;
bool converged = false;
bool convergedati = false;
DP canfreeenstay, canfreeenup, canfreeendown, canfreeenin, canfreeenout;
DP Estay, Eup, Edown, Ein, Eout;
DP Sstay, Sup, Sdown, Sin, Sout;
Estay = 0.0; Eup = 0.0; Edown = 0.0; Ein = 0.0; Eout = 0.0;
Sstay = 0.0; Sup = 0.0; Sdown = 0.0; Sin = 0.0; Sout = 0.0;
while (!converged) {
spstate.Compute_All (false);
converged = true; // set to false if we change anything
// If we can minimize the free energy by changing the quantum number, we do:
// NOTE: we keep the state symmetric w/r to parity.
for (int i = 0; i < N/2 - 1; ++i) {
// Try to increase or decrease the quantum numbers at i ,
// or do an (approximately) energy-preserving move with i+1 (and parity pairs)
// giving 5 possible options: stay same, (\pm 1, 0), (+1, -1), (-1, +1)
convergedati = false;
while (!convergedati) {
convergedati = true; // set to false if we change anything
Estay = spstate.E;
Sstay = Entropy (spstate);
//Sstay = Entropy (spstate, Delta);
//Sstay = Entropy (spstate, epsilon);
//canfreeenstay = Canonical_Free_Energy (spstate, kBT, Delta);
canfreeenstay = Estay - kBT * Sstay;
spstateup = spstate;
if (i == 0 || spstateup.Ix2[i-1] < spstateup.Ix2[i] - 2) {
spstateup.Ix2[i] -= 2;
spstateup.Ix2[N-1-i] += 2;
spstateup.Compute_All(false);
Eup = spstateup.E;
Sup = Entropy(spstateup);
//Sup = Entropy(spstateup, Delta);
//Sup = Entropy(spstateup, epsilon);
//canfreeenup = Canonical_Free_Energy (spstateup, kBT, Delta);
canfreeenup = Eup - kBT * Sup;
}
else canfreeenup = canfreeenstay + 1.0e-6;
spstatedown = spstate;
if (spstatedown.Ix2[i+1] > spstatedown.Ix2[i] + 2) {
spstatedown.Ix2[i] += 2;
spstatedown.Ix2[N-1-i] -= 2;
spstatedown.Compute_All(false);
Edown = spstatedown.E;
Sdown = Entropy(spstatedown);
//Sdown = Entropy(spstatedown, Delta);
//Sdown = Entropy(spstatedown, epsilon);
//canfreeendown = Canonical_Free_Energy (spstatedown, kBT, Delta);
canfreeendown = Edown - kBT * Sdown;
}
else canfreeendown = canfreeenstay + 1.0e-6;
spstatein = spstate;
if (spstatein.Ix2[i+1] > spstatein.Ix2[i] + 4) { // can move them closer
spstatein.Ix2[i] += 2;
spstatein.Ix2[i+1] -= 2;
spstatein.Ix2[N-1-i] -= 2;
spstatein.Ix2[N-1-i-1] += 2;
spstatein.Compute_All(false);
Ein = spstatein.E;
Sin = Entropy(spstatein);
//Sin = Entropy(spstatein, Delta);
//Sin = Entropy(spstatein, epsilon);
//canfreeenin = Canonical_Free_Energy (spstatein, kBT, Delta);
canfreeenin = Ein - kBT * Sin;
}
else canfreeenin = canfreeenstay + 1.0e-6;
spstateout = spstate;
if (i == 0 && spstateout.Ix2[1] + 2 < spstateout.Ix2[2]
|| (i < N/2 - 1 && spstateout.Ix2[i] - 2 > spstateout.Ix2[i-1]
&& spstateout.Ix2[i+1] + 2 < spstateout.Ix2[i+2])) { // can move them further apart
spstateout.Ix2[i] -= 2;
spstateout.Ix2[i+1] += 2;
spstateout.Ix2[N-1-i] += 2;
spstateout.Ix2[N-1-i-1] -= 2;
spstateout.Compute_All(false);
Eout = spstateout.E;
Sout = Entropy(spstateout);
//Sout = Entropy(spstateout, Delta);
//Sout = Entropy(spstateout, epsilon);
//canfreeenout = Canonical_Free_Energy (spstateout, kBT, Delta);
canfreeenout = Eout - kBT * Sout;
}
else canfreeenout = canfreeenstay + 1.0e-6;
//cout << setprecision(8) << "i = " << i << "\t" << spstate.Ix2[i] << "\t" << spstate.Ix2[i+1] << "\t\t" << canfreeenstay << "\t" << canfreeenup << "\t" << canfreeendown << "\t" << canfreeenin << "\t" << canfreeenout << endl;
//cout << "\t\tE: " << Estay << "\t" << Eup << "\t" << Edown << "\t" << Ein << "\t" << Eout << endl;
//cout << "\t\tS: " << Sstay << "\t" << Sup << "\t" << Sdown << "\t" << Sin << "\t" << Sout << endl;
// Choose what to do: find minimum,
if (canfreeenstay < canfreeenup && canfreeenstay < canfreeendown && canfreeenstay < canfreeenin && canfreeenstay < canfreeenout) {
// do nothing, convergetati is already true
}
else if (canfreeenup < canfreeenstay && canfreeenup < canfreeendown && canfreeenup < canfreeenin && canfreeenup < canfreeenout) {
spstate = spstateup;
convergedati = false;
converged = false;
}
else if (canfreeendown < canfreeenstay && canfreeendown < canfreeenup && canfreeendown < canfreeenin && canfreeendown < canfreeenout) {
spstate = spstatedown;
convergedati = false;
converged = false;
}
else if (canfreeenin < canfreeenstay && canfreeenin < canfreeenup && canfreeenin < canfreeendown && canfreeenin < canfreeenout) {
spstate = spstatein;
convergedati = false;
converged = false;
}
else if (canfreeenout < canfreeenstay && canfreeenout < canfreeenup && canfreeenout < canfreeendown && canfreeenout < canfreeenin) {
spstate = spstateout;
convergedati = false;
converged = false;
}
else cout << canfreeenstay << "\t" << canfreeenup << "\t" << canfreeendown << "\t" << canfreeenin << "\t" << canfreeenout << "\tWarning: unclear option for minimization." << endl;
// else do nothing.
} // while !convergedati
} // for i
} // while (!converged)
//cout << "Number of holes between I's: " << endl;
//for (int i = 0; i < N/2; ++i) cout << (spstate.Ix2[i+1] - spstate.Ix2[i])/2 - 1 << "\t";
//cout << endl;
return(spstate);
}
*/
DP rho_of_lambdaoc_1 (LiebLin_Bethe_State& RefState, DP lambdaoc, DP delta)
{
DP answer = 0.0;
for (int i = 0; i < RefState.N; ++i)
answer += atan((lambdaoc - RefState.lambdaoc[i])/delta + 0.5) - atan((lambdaoc - RefState.lambdaoc[i])/delta - 0.5);
answer += atan((lambdaoc - RefState.lambdaoc[i])/delta + 0.5)
- atan((lambdaoc - RefState.lambdaoc[i])/delta - 0.5);
answer *= 1.0/(PI * delta * RefState.L);
return(answer);
@ -477,7 +93,7 @@ namespace ABACUS {
DP answer = 0.0;
for (int i = 0; i < RefState.N; ++i)
answer += 1.0/(pow(lambdaoc - RefState.lambdaoc[i], 2.0) + delta*delta);
answer *= delta/(PI * RefState.L);
answer *= delta/(PI * RefState.L);
return(answer);
}

View File

@ -51,14 +51,16 @@ namespace ABACUS {
return(1.0/Fn_V (j, -sign, lstate_lambdaoc, rstate));
}
complex<DP> LiebLin_Twisted_ln_Overlap (DP expbeta, Vect<DP> lstate_lambdaoc, DP lstate_lnnorm, LiebLin_Bethe_State& rstate)
complex<DP> LiebLin_Twisted_ln_Overlap (DP expbeta, Vect<DP> lstate_lambdaoc,
DP lstate_lnnorm, LiebLin_Bethe_State& rstate)
{
Vect<complex<DP> > lstate_lambdaoc_CX(lstate_lambdaoc.size());
for (int i = 0; i < lstate_lambdaoc.size(); ++i) lstate_lambdaoc_CX[i] = complex<DP>(lstate_lambdaoc[i]);
return(LiebLin_Twisted_ln_Overlap (complex<DP>(expbeta), lstate_lambdaoc_CX, lstate_lnnorm, rstate));
}
complex<DP> LiebLin_Twisted_ln_Overlap (complex<DP> expbeta, Vect<complex<DP> > lstate_lambdaoc, DP lstate_lnnorm, LiebLin_Bethe_State& rstate)
complex<DP> LiebLin_Twisted_ln_Overlap (complex<DP> expbeta, Vect<complex<DP> > lstate_lambdaoc,
DP lstate_lnnorm, LiebLin_Bethe_State& rstate)
{
// Computes the log of the overlap between the left state and the Bethe rstate
@ -81,13 +83,13 @@ namespace ABACUS {
Fn_Prod[a] = 1.0;
for (int m = 0; m < rstate.N; ++m)
if (m != a) Fn_Prod[a] *= (lstate_lambdaoc[m] - rstate.lambdaoc[a])/(rstate.lambdaoc[m] - rstate.lambdaoc[a]);
//rKern[a] = rstate.Kernel (a, p);
rKern[a] = Kernel_Twisted (expbeta, rstate.lambdaoc[p] - rstate.lambdaoc[a]);
}
for (int a = 0; a < rstate.N; ++a)
for (int b = 0; b < rstate.N; ++b)
one_plus_U[a][b] = (a == b ? 1.0 : 0.0) + ((lstate_lambdaoc[a] - rstate.lambdaoc[a])/(1.0/Vplus_Nikita[a] - 1.0/Vminus_Nikita[a]))
one_plus_U[a][b] = (a == b ? 1.0 : 0.0)
+ ((lstate_lambdaoc[a] - rstate.lambdaoc[a])/(1.0/Vplus_Nikita[a] - 1.0/Vminus_Nikita[a]))
* Fn_Prod[a] * (Kernel_Twisted(expbeta, rstate.lambdaoc[a] - rstate.lambdaoc[b]) - rKern[b]);
complex<DP> ln_ddalpha_sigma = lndet_LU_CX_dstry(one_plus_U);
@ -101,16 +103,8 @@ namespace ABACUS {
for (int b = 0; b < rstate.N; ++b)
ln_prod_2 += log((lstate_lambdaoc[a] - rstate.lambdaoc[b] - II)/(rstate.lambdaoc[a] - lstate_lambdaoc[b]));
//cout << endl << ln_ddalpha_sigma << "\t" << ln_prod_V << "\t" << ln_prod_2 << "\t" << - log(2.0 * II * imag(Vplus[p])) << endl;
//cout << endl << ln_ddalpha_sigma << "\t" << ln_prod_V << "\t" << ln_prod_2 << "\t" << - log(Vplus[p] - Vminus[p]) << endl;
ln_ddalpha_sigma += ln_prod_V + ln_prod_2 - log(Vplus_Nikita[p] - expbeta * Vminus_Nikita[p]);
//cout << "shift = " << (complex<DP>(rstate.N) * (lstate_lambdaoc[0] - rstate.lambdaoc[0])/twoPI) << "\tKout = " << Kout << "\texp(-II*Kout) = " << exp(-II * Kout)
// << "\tlog(exp(-II * Kout) - 1.0) = " << log(exp(-II * Kout) - 1.0) << endl;
//cout << ln_ddalpha_sigma << "\t" << ln_prod_V << "\t" << ln_prod_2 << "\t" << lstate_lnnorm << endl << endl;
//return (log(1.0 - expbeta) + ln_ddalpha_sigma - 0.5 * (lstate_lnnorm + rstate.lnnorm));
return (log(1.0 - exp(-II * Kout)) + ln_ddalpha_sigma - 0.5 * (lstate_lnnorm + rstate.lnnorm));
}

View File

@ -35,7 +35,8 @@ namespace ABACUS {
for (int k = 0; k < N; ++k) {
if (j == k) {
sum_Kernel = 0.0;
for (int kp = 0; kp < N; ++kp) if (j != kp) sum_Kernel += 2.0/((lambdaoc[j] - lambdaoc[kp]) * (lambdaoc[j] - lambdaoc[kp]) + 1.0);
for (int kp = 0; kp < N; ++kp)
if (j != kp) sum_Kernel += 2.0/((lambdaoc[j] - lambdaoc[kp]) * (lambdaoc[j] - lambdaoc[kp]) + 1.0);
Gaudin[j][k] = cxL + sum_Kernel;
}
else Gaudin[j][k] = - 2.0/((lambdaoc[j] - lambdaoc[k]) * (lambdaoc[j] - lambdaoc[k]) + 1.0);

View File

@ -97,13 +97,11 @@ namespace ABACUS {
lambda.Build_Reduced_Gaudin_Matrix ( Gaudin);
lambda.Build_Reduced_BEC_Quench_Gaudin_Matrix (Gaudin_Quench);
//DP ln_prefactor = N/2.0 * log(2./fabs(c_int*L) ) + 0.5 * (N*log(N) - N + 0.5*log(2. * PI * N));
DP ln_prefactor = N/2.0 * log(2./(c_int*L) ) + 0.5 * real(ln_Gamma(complex<double>(N+1.0)));
for(int i =N/2; i<N; i ++) ln_prefactor -= log(fabs(lambda.lambdaoc[i ])) + 0.5*log( 1. + 4. * lambda.lambdaoc[i ]*lambda.lambdaoc[i ]) ;
for(int i =N/2; i<N; i ++)
ln_prefactor -= log(fabs(lambda.lambdaoc[i ])) + 0.5*log( 1. + 4. * lambda.lambdaoc[i ]*lambda.lambdaoc[i ]) ;
//cout << ln_prefactor << endl;
return (ln_prefactor + real(lndet_LU_dstry(Gaudin_Quench)) - 0.5 * real(lndet_LU_dstry(Gaudin)));
}

View File

@ -19,22 +19,6 @@ using namespace std;
using namespace ABACUS;
namespace ABACUS {
/*
complex<DP> Fn_V (int j, int sign, Vect<complex<DP> >& lstate_lambdaoc, LiebLin_Bethe_State& rstate)
{
complex<DP> result_num = 1.0;
complex<DP> result_den = 1.0;
complex<DP> signcx = complex<DP>(sign);
for (int m = 0; m < rstate.N; ++m) {
result_num *= (lstate_lambdaoc[m] - rstate.lambdaoc[j] + signcx * II);
result_den *= (rstate.lambdaoc[m] - rstate.lambdaoc[j] + signcx * II);
}
return(result_num/result_den);
}
*/
complex<DP> LiebLin_ln_Overlap (Vect<DP> lstate_lambdaoc, DP lstate_lnnorm, LiebLin_Bethe_State& rstate)
{
@ -77,26 +61,12 @@ namespace ABACUS {
for (int j = 0; j < rstate.N; ++j)
for (int k = 0; k < rstate.N; ++k)
//Omega[j][k] = exp(-II * rstate.cxL * lstate_lambdaoc[k] + ln_prod_plus[k] - ln_prod_ll_plus[k])
//* (II/((rstate.lambdaoc[j] - lstate_lambdaoc[k])*(rstate.lambdaoc[j] - lstate_lambdaoc[k] + II)))
//- (II/((rstate.lambdaoc[j] - lstate_lambdaoc[k])*(rstate.lambdaoc[j] - lstate_lambdaoc[k] - II)))
//* exp(ln_prod_minus[k] - ln_prod_ll_plus[k]);
Omega[j][k] = exp(-II * rstate.cxL * lstate_lambdaoc[k] - ln_prod_plus[k] + ln_prod_minus[k])
* (II/((rstate.lambdaoc[j] - lstate_lambdaoc[k])*(rstate.lambdaoc[j] - lstate_lambdaoc[k] - II)))
- (II/((rstate.lambdaoc[j] - lstate_lambdaoc[k])*(rstate.lambdaoc[j] - lstate_lambdaoc[k] + II)));
//for (int j = 0; j < rstate.N; ++j) {
//for (int k = 0; k < rstate.N; ++k)
//cout << Omega[j][k] << "\t";
//cout << endl;
//}
complex<DP> lndetOmega = lndet_LU_CX_dstry(Omega);
//cout << "lndetOmega = " << lndetOmega << endl;
// Prefactors:
complex<DP> ln_prod_d_mu = II * 0.5 * rstate.cxL * rstate.lambdaoc.sum();
complex<DP> ln_prod_d_lambdaoc = II * 0.5 * rstate.cxL * lstate_lambdaoc.sum();
@ -107,7 +77,6 @@ namespace ABACUS {
for (int j = 0; j < rstate.N - 1; ++j)
for (int k = j+1; k < rstate.N; ++k) {
ln_prod_mu += log(rstate.lambdaoc[k] - rstate.lambdaoc[j]);
//ln_prod_lambdaoc += log((lstate_lambdaoc[j] - lstate_lambdaoc[k] + II) * (lstate_lambdaoc[j] - lstate_lambdaoc[k] - II)/(lstate_lambdaoc[k] - lstate_lambdaoc[j]));
ln_prod_lambdaoc += log(lstate_lambdaoc[k] - lstate_lambdaoc[j]);
}
@ -115,72 +84,8 @@ namespace ABACUS {
for (int k = 0; k < rstate.N; ++k)
ln_prod_plusminus += log((rstate.lambdaoc[j] - lstate_lambdaoc[k] + II));
//cout << "ln_prod_mu " << ln_prod_mu << "\tln_prod_lambdaoc " << ln_prod_lambdaoc << "\tln_prod_plusminus " << ln_prod_plusminus
// << "\texp1 " << exp(-ln_prod_mu - ln_prod_lambdaoc) << "\texp2 " << exp(ln_prod_plusminus) << endl;
//if (real(ln_prod_d_mu + ln_prod_d_lambdaoc - ln_prod_mu + ln_prod_lambdaoc + lndetOmega - 0.5 * (lstate_lnnorm + rstate.lnnorm)) > 10.0) {
//cout << ln_prod_d_mu << "\t" << ln_prod_d_lambdaoc << "\t" << -ln_prod_mu << "\t" << ln_prod_lambdaoc << "\t" << lndetOmega << "\t" << -0.5 * lstate_lnnorm << "\t" << -0.5 * rstate.lnnorm << endl; cout << ln_prod_d_mu + ln_prod_d_lambdaoc - ln_prod_mu + ln_prod_lambdaoc + lndetOmega - 0.5 * (lstate_lnnorm + rstate.lnnorm) << endl;
//ABACUSerror("Overlap exceeds 1.");
//}
//return(ln_prod_d_mu + ln_prod_d_lambdaoc - ln_prod_mu + ln_prod_lambdaoc + lndetOmega - 0.5 * (lstate_lnnorm + rstate.lnnorm));
return(ln_prod_d_mu + ln_prod_d_lambdaoc - ln_prod_mu - ln_prod_lambdaoc + ln_prod_plusminus + lndetOmega - 0.5 * (lstate_lnnorm + rstate.lnnorm));
return(ln_prod_d_mu + ln_prod_d_lambdaoc - ln_prod_mu - ln_prod_lambdaoc + ln_prod_plusminus
+ lndetOmega - 0.5 * (lstate_lnnorm + rstate.lnnorm));
}
/*
// Incorrect version
complex<DP> LiebLin_ln_Overlap (Vect<complex<DP> > lstate_lambdaoc, DP lstate_lnnorm, LiebLin_Bethe_State& rstate)
{
// Computes the log of the overlap between the left state and the Bethe rstate
// If momentum difference is zero but states are different, then form factor is zero:
SQMat_CX one_plus_U (0.0, rstate.N);
Vect_CX Vplus (0.0, rstate.N); // contains V^+_j
Vect_CX Vminus (0.0, rstate.N); // contains V^-_j
Vect_CX Fn_Prod (0.0, rstate.N); // product_{m\neq j} (\mu_m - \lambdaoc_j)/(\lambdaoc_m - \lambdaoc_j)
//Vect_DP rKern (0.0, rstate.N); // K(lambdaoc_j - lambdaoc_p)
//int p = 0;
complex<DP> Kout = lstate_lambdaoc.sum() - rstate.K;
for (int a = 0; a < rstate.N; ++a) {
Vplus[a] = Fn_V (a, 1, lstate_lambdaoc, rstate);
Vminus[a] = Fn_V (a, -1, lstate_lambdaoc, rstate);
Fn_Prod[a] = 1.0;
for (int m = 0; m < rstate.N; ++m)
if (m != a) Fn_Prod[a] *= (lstate_lambdaoc[m] - rstate.lambdaoc[a])/(rstate.lambdaoc[m] - rstate.lambdaoc[a]);
//rKern[a] = rstate.Kernel (a, p);
}
for (int a = 0; a < rstate.N; ++a)
for (int b = 0; b < rstate.N; ++b)
one_plus_U[a][b] = (a == b ? 1.0 : 0.0) + II * ((lstate_lambdaoc[a] - rstate.lambdaoc[a])/(Vplus[a] - Vminus[a]))
* Fn_Prod[a] * rstate.Kernel(a,b);
complex<DP> ln_ddalpha_sigma = lndet_LU_CX_dstry(one_plus_U);
complex<DP> ln_prod_V = 0.0;
for (int a = 0; a < rstate.N; ++a) ln_prod_V += log(Vplus[a] - Vminus[a]);
complex<DP> ln_prod_2 = 0.0;
for (int a = 0; a < rstate.N; ++a)
for (int b = 0; b < rstate.N; ++b)
ln_prod_2 += log((rstate.lambdaoc[a] - rstate.lambdaoc[b] + II)/(lstate_lambdaoc[a] - rstate.lambdaoc[b]));
//cout << endl << ln_ddalpha_sigma << "\t" << ln_prod_V << "\t" << ln_prod_2 << "\t" << - log(2.0 * II * imag(Vplus[p])) << endl;
cout << endl << ln_ddalpha_sigma << "\t" << ln_prod_V << "\t" << ln_prod_2 << "\t" << 0.5 * lstate_lnnorm << "\t" << 0.5 * rstate.lnnorm << endl;//- log(Vplus[p] - Vminus[p]) << endl;
ln_ddalpha_sigma += ln_prod_V + ln_prod_2;// - log(Vplus[p] - Vminus[p]);
//cout << "shift = " << (complex<DP>(rstate.N) * (lstate_lambdaoc[0] - rstate.lambdaoc[0])/twoPI) << "\tKout = " << Kout << "\texp(-II*Kout) = " << exp(-II * Kout)
// << "\tlog(exp(-II * Kout) - 1.0) = " << log(exp(-II * Kout) - 1.0) << endl;
//cout << ln_ddalpha_sigma << "\t" << ln_prod_V << "\t" << ln_prod_2 << "\t" << - log(Vplus[p] - Vminus[p]) << "\t" << lstate_lnnorm << endl << endl;
return (ln_ddalpha_sigma - 0.5 * (lstate_lnnorm + rstate.lnnorm));
}
*/
} // namespace ABACUS

View File

@ -21,17 +21,12 @@ namespace ABACUS {
complex<DP> Fn_V (int j, LiebLin_Bethe_State& lstate, LiebLin_Bethe_State& rstate)
{
//complex<DP> result_num = 1.0;
//complex<DP> result_den = 1.0;
complex<DP> result = 1.0;
for (int m = 0; m < lstate.N; ++m) {
//result_num *= (lstate.lambdaoc[m] - rstate.lambdaoc[j] + II);
//result_den *= (rstate.lambdaoc[m] - rstate.lambdaoc[j] + II);
result *= (lstate.lambdaoc[m] - rstate.lambdaoc[j] + II)/(rstate.lambdaoc[m] - rstate.lambdaoc[j] + II);
}
//return(result_num/result_den);
return(result);
}
@ -40,18 +35,14 @@ namespace ABACUS {
// Computes the log of the density operator \rho(x = 0) matrix element between lstate and rstate.
// If we have lstate == rstate, density matrix element = N/L:
if (lstate.Ix2 == rstate.Ix2) return(log(lstate.N/lstate.L));
// If momentum difference is zero but states are different, then matrix element is zero:
else if (lstate.iK == rstate.iK) return(-200.0); // so exp(.) is zero
SQMat_DP one_plus_U (0.0, lstate.N);
Vect_CX Vplus (0.0, lstate.N); // contains V^+_j; V^-_j is the conjugate
//Vect_DP Fn_Prod (0.0, lstate.N); // product_{m\neq j} (\mu_m - \lambdaoc_j)/(\lambdaoc_m - \lambdaoc_j)
// From ABACUS++G_3 onwards: use logs to stabilize numerical values at small c, at the cost of execution speed.
Vect_CX ln_Fn_Prod (0.0, lstate.N); // product_{m\neq j} (\mu_m - \lambdaoc_j)/(\lambdaoc_m - \lambdaoc_j)
Vect_DP rKern (0.0, lstate.N); // K(lambdaoc_j - lambdaoc_(p == arbitrary))
@ -62,19 +53,17 @@ namespace ABACUS {
for (int a = 0; a < lstate.N; ++a) {
Vplus[a] = Fn_V (a, lstate, rstate);
//Fn_Prod[a] = 1.0;
ln_Fn_Prod[a] = 0.0;;
for (int m = 0; m < lstate.N; ++m)
//if (m != a) Fn_Prod[a] *= (lstate.lambdaoc[m] - rstate.lambdaoc[a])/(rstate.lambdaoc[m] - rstate.lambdaoc[a]);
if (m != a) ln_Fn_Prod[a] += log(complex<DP>(lstate.lambdaoc[m] - rstate.lambdaoc[a])/(rstate.lambdaoc[m] - rstate.lambdaoc[a]));
if (m != a) ln_Fn_Prod[a] += log(complex<DP>(lstate.lambdaoc[m] - rstate.lambdaoc[a])
/(rstate.lambdaoc[m] - rstate.lambdaoc[a]));
rKern[a] = rstate.Kernel (a, p);
}
for (int a = 0; a < lstate.N; ++a)
for (int b = 0; b < lstate.N; ++b)
one_plus_U[a][b] = (a == b ? 1.0 : 0.0) + 0.5 * ((lstate.lambdaoc[a] - rstate.lambdaoc[a])/imag(Vplus[a]))
//* Fn_Prod[a] * (rstate.Kernel(a,b) - rKern[b]);
* real(exp(ln_Fn_Prod[a])) * (rstate.Kernel(a,b) - rKern[b]);
* real(exp(ln_Fn_Prod[a])) * (rstate.Kernel(a,b) - rKern[b]); // BUGRISK: why real here?
complex<DP> ln_ddalpha_sigma = lndet_LU_dstry(one_plus_U);
@ -86,9 +75,6 @@ namespace ABACUS {
for (int b = 0; b < lstate.N; ++b)
ln_prod_2 += log((rstate.lambdaoc[a] - rstate.lambdaoc[b] + II)/(lstate.lambdaoc[a] - rstate.lambdaoc[b]));
//cout << "ln_Fn_Prod = " << ln_Fn_Prod << endl;
//cout << endl << ln_ddalpha_sigma << "\t" << ln_prod_V << "\t" << ln_prod_2 << "\t" << - log(2.0 * II * imag(Vplus[p])) << "\t" << - 0.5 * (lstate.lnnorm + rstate.lnnorm) << "\t" << ln_ddalpha_sigma + ln_prod_V + ln_prod_2 - log(2.0 * II * imag(Vplus[p])) - 0.5 * (lstate.lnnorm + rstate.lnnorm) << endl;
ln_ddalpha_sigma += ln_prod_V + ln_prod_2 - log(2.0 * II * imag(Vplus[p]));
return (log(-II * Kout) + ln_ddalpha_sigma - 0.5 * (lstate.lnnorm + rstate.lnnorm));

View File

@ -66,16 +66,16 @@ namespace ABACUS {
complex<DP> ln_prod_lambdaocsq_plus_one = 0.0;
for (int a = 0; a < rstate.N - 1; ++a)
for (int b = a; b < rstate.N; ++b)
ln_prod_lambdaocsq_plus_one += log(complex<DP>((rstate.lambdaoc[a] - rstate.lambdaoc[b]) * (rstate.lambdaoc[a] - rstate.lambdaoc[b])) + 1.0);
ln_prod_lambdaocsq_plus_one += log(complex<DP>((rstate.lambdaoc[a] - rstate.lambdaoc[b])
* (rstate.lambdaoc[a] - rstate.lambdaoc[b])) + 1.0);
complex<DP> ln_prod_lambdaoca_min_mub = 0.0;
for (int a = 0; a < rstate.N; ++a)
for (int b = 0; b < lstate.N; ++b)
ln_prod_lambdaoca_min_mub += log(complex<DP>(rstate.lambdaoc[a] - lstate.lambdaoc[b]));
//cout << endl << "Factors are " << ln_det_U_Psi << "\t" << ln_prod_lambdaocsq_plus_one << "\t" << ln_prod_lambdaoca_min_mub << endl;
return (ln_det_U_Psi + 0.5 * log(lstate.c_int) + ln_prod_lambdaocsq_plus_one - ln_prod_lambdaoca_min_mub - 0.5 * (lstate.lnnorm + rstate.lnnorm));
return (ln_det_U_Psi + 0.5 * log(lstate.c_int) + ln_prod_lambdaocsq_plus_one - ln_prod_lambdaoca_min_mub
- 0.5 * (lstate.lnnorm + rstate.lnnorm));
}
}
} // namespace ABACUS

View File

@ -20,173 +20,66 @@ using namespace std;
using namespace ABACUS;
namespace ABACUS {
/*
complex<DP> ln_g2_ME_old_jacopo (LiebLin_Bethe_State& mu, LiebLin_Bethe_State& lambda)
complex<DP> Fn_V_g2 (int j, LiebLin_Bethe_State& lstate, LiebLin_Bethe_State& rstate)
{
complex<DP> result = 1.0;
if (mu.Ix2 == lambda.Ix2) return(-200.);
DP c_int = mu.c_int;
SQMat_CX G(lambda.N);
SQMat_CX GpB(lambda.N);
SQMat_CX B(lambda.N);
complex<DP> log_themp;
complex<DP> lnprefactor = 0. ;
lnprefactor += 2.*log(c_int) ;
for(int j=0; j < mu.N; ++j){
for(int k=0; k < j; ++k){
lnprefactor -= log((mu.lambdaoc[j] - mu.lambdaoc[k]));
lnprefactor -= log((lambda.lambdaoc[j] - lambda.lambdaoc[k]));
}
for (int m = 0; m < lstate.N; ++m) {
result *= (lstate.lambdaoc[m] - rstate.lambdaoc[j] + II)/(rstate.lambdaoc[m] - rstate.lambdaoc[j] + II);
}
for(int j=0; j < mu.N; ++j){
for(int k=0; k <mu.N; ++k){
lnprefactor += log(mu.lambdaoc[j] - mu.lambdaoc[k] + II);
}
}
Vect_CX VVP (0.0, mu.N);
Vect_CX VVM (0.0, mu.N);
//compute the vectors
for(int j=0; j < mu.N; ++j) {
log_themp = 0.;
for(int k=0; k < mu.N; ++k) log_themp += log(mu.lambdaoc[j] - lambda.lambdaoc[k] + II) - log(mu.lambdaoc[j] - mu.lambdaoc[k] + II);
VVP[j] = exp(log_themp);
}
for(int j=0; j < mu.N; ++j) {
log_themp = 0.;
for(int k=0; k < mu.N; ++k) log_themp += log(mu.lambdaoc[j] - lambda.lambdaoc[k] - II) - log(mu.lambdaoc[j] - mu.lambdaoc[k] - II);
VVM[j] = exp(log_themp);
}
//compute the sum of determinants
complex<DP> sum_n =0.;
for(int n=0; n < mu.N; ++n) {
// compute the matrices
for (int a = 0; a < mu.N; ++a){
for (int b = 0; b < mu.N; ++b){
if(b == n){
G[a][b] = 2.*II* lambda.lambdaoc[a];
}
else{
G[a][b] = II*1./(lambda.lambdaoc[a] - mu.lambdaoc[b])*( VVP[b]*1.0/(mu.lambdaoc[b] - lambda.lambdaoc[a] + II) +
VVM[b]*1.0/(mu.lambdaoc[b] - lambda.lambdaoc[a] - II) );
}
}
}
for (int a = 0; a < mu.N; ++a){
for (int b = 0; b < mu.N; ++b){
if(b == n){
B[a][b] = 0.;
}
else{
B[a][b] = II*1.0/(mu.lambdaoc[b] - mu.lambdaoc[n] - II) ;
}
}
}
for (int a = 0; a < mu.N; ++a){
for (int b = 0; b < mu.N; ++b){
GpB[a][b] = G[a][b] + B[a][b];
}
}
//finally add
sum_n += exp( lndet_LU_CX(GpB) ) - exp(lndet_LU_CX(G) ) ;
}
return(log(sum_n ) + lnprefactor - 0.5 * (mu.lnnorm + lambda.lnnorm));
return(result);
}
*/
complex<DP> Fn_V_g2 (int j, LiebLin_Bethe_State& lstate, LiebLin_Bethe_State& rstate)
{
//complex<DP> result_num = 1.0;
//complex<DP> result_den = 1.0;
complex<DP> result = 1.0;
for (int m = 0; m < lstate.N; ++m) {
//result_num *= (lstate.lambdaoc[m] - rstate.lambdaoc[j] + II);
//result_den *= (rstate.lambdaoc[m] - rstate.lambdaoc[j] + II);
result *= (lstate.lambdaoc[m] - rstate.lambdaoc[j] + II)/(rstate.lambdaoc[m] - rstate.lambdaoc[j] + II);
}
//return(result_num/result_den);
return(result);
complex<DP> ln_g2_ME (LiebLin_Bethe_State& lstate, LiebLin_Bethe_State& rstate)
{
// Computes the log of the density operator \rho(x = 0) matrix element between lstate and rstate.
// If we have lstate == rstate, density matrix element = 0:
if (lstate.Ix2 == rstate.Ix2) return(-200.);
SQMat_DP one_plus_U (0.0, lstate.N);
Vect_CX Vplus (0.0, lstate.N); // contains V^+_j; V^-_j is the conjugate
Vect_CX ln_Fn_Prod (0.0, lstate.N); // product_{m\neq j} (\mu_m - \lambdaoc_j)/(\lambdaoc_m - \lambdaoc_j)
Vect_DP rKern (0.0, lstate.N); // K(lambdaoc_j - lambdaoc_(p == arbitrary))
int p = rstate.N/2-1; // choice doesn't matter, see 1990_Slavnov_TMP_82 after (3.8). Choose rapidity around the middle.
DP c_int = rstate.c_int;
DP Eout = log(pow(lstate.E - rstate.E,2.)) - (2)*log(c_int) - log(2*lstate.N);
for (int a = 0; a < lstate.N; ++a) {
Vplus[a] = Fn_V_g2 (a, lstate, rstate);
ln_Fn_Prod[a] = 0.0;;
for (int m = 0; m < lstate.N; ++m)
if (m != a) ln_Fn_Prod[a] += log(complex<DP>(lstate.lambdaoc[m] - rstate.lambdaoc[a])
/(rstate.lambdaoc[m] - rstate.lambdaoc[a]));
rKern[a] = rstate.Kernel (a, p);
}
for (int a = 0; a < lstate.N; ++a)
for (int b = 0; b < lstate.N; ++b)
one_plus_U[a][b] = (a == b ? 1.0 : 0.0) + 0.5 * 1./imag(Vplus[a])
* ((lstate.lambdaoc[a] - rstate.lambdaoc[a])*real(exp(ln_Fn_Prod[a]))
* (rstate.Kernel(a,b) - rKern[b]) + rKern[b]);
complex<DP> ln_g2_ME (LiebLin_Bethe_State& lstate, LiebLin_Bethe_State& rstate)
{
// Computes the log of the density operator \rho(x = 0) matrix element between lstate and rstate.
// If we have lstate == rstate, density matrix element = 0:
if (lstate.Ix2 == rstate.Ix2) return(-200.);
SQMat_DP one_plus_U (0.0, lstate.N);
Vect_CX Vplus (0.0, lstate.N); // contains V^+_j; V^-_j is the conjugate
//Vect_DP Fn_Prod (0.0, lstate.N); // product_{m\neq j} (\mu_m - \lambdaoc_j)/(\lambdaoc_m - \lambdaoc_j)
// From ABACUS++G_3 onwards: use logs to stabilize numerical values at small c, at the cost of execution speed.
Vect_CX ln_Fn_Prod (0.0, lstate.N); // product_{m\neq j} (\mu_m - \lambdaoc_j)/(\lambdaoc_m - \lambdaoc_j)
Vect_DP rKern (0.0, lstate.N); // K(lambdaoc_j - lambdaoc_(p == arbitrary))
//int p = 0;
int p = rstate.N/2-1; // choice doesn't matter, see 1990_Slavnov_TMP_82 after (3.8). Choose rapidity around the middle.
DP c_int = rstate.c_int;
DP Eout = log(pow(lstate.E - rstate.E,2.)) - (2)*log(c_int) - log(2*lstate.N);
for (int a = 0; a < lstate.N; ++a) {
Vplus[a] = Fn_V_g2 (a, lstate, rstate);
//Fn_Prod[a] = 1.0;
ln_Fn_Prod[a] = 0.0;;
for (int m = 0; m < lstate.N; ++m)
//if (m != a) Fn_Prod[a] *= (lstate.lambdaoc[m] - rstate.lambdaoc[a])/(rstate.lambdaoc[m] - rstate.lambdaoc[a]);
if (m != a) ln_Fn_Prod[a] += log(complex<DP>(lstate.lambdaoc[m] - rstate.lambdaoc[a])/(rstate.lambdaoc[m] - rstate.lambdaoc[a]));
rKern[a] = rstate.Kernel (a, p);
}
for (int a = 0; a < lstate.N; ++a)
for (int b = 0; b < lstate.N; ++b)
one_plus_U[a][b] = (a == b ? 1.0 : 0.0) + 0.5 * 1./imag(Vplus[a])
//* Fn_Prod[a] * (rstate.Kernel(a,b) - rKern[b]);
* ((lstate.lambdaoc[a] - rstate.lambdaoc[a])*real(exp(ln_Fn_Prod[a])) * (rstate.Kernel(a,b) - rKern[b]) + rKern[b]);
complex<DP> ln_ddalpha_sigma = lndet_LU_dstry(one_plus_U);
complex<DP> ln_prod_V = 0.0;
for (int a = 0; a < lstate.N; ++a) ln_prod_V += log(2.0 * II * imag(Vplus[a]));
complex<DP> ln_prod_2 = 0.0;
for (int a = 0; a < lstate.N; ++a)
for (int b = 0; b < lstate.N; ++b)
ln_prod_2 += log((rstate.lambdaoc[a] - rstate.lambdaoc[b] + II)/(lstate.lambdaoc[a] - rstate.lambdaoc[b]));
//cout << "ln_Fn_Prod = " << ln_Fn_Prod << endl;
//cout << endl << ln_ddalpha_sigma << "\t" << ln_prod_V << "\t" << ln_prod_2 << "\t" << - log(2.0 * II * imag(Vplus[p])) << "\t" << - 0.5 * (lstate.lnnorm + rstate.lnnorm) << "\t" << ln_ddalpha_sigma + ln_prod_V + ln_prod_2 - log(2.0 * II * imag(Vplus[p])) - 0.5 * (lstate.lnnorm + rstate.lnnorm) << endl;
ln_ddalpha_sigma += ln_prod_V + ln_prod_2 - log(2.0 * II * imag(Vplus[p]));
return (log(II) + Eout + ln_ddalpha_sigma - 0.5 * (lstate.lnnorm + rstate.lnnorm));
}
complex<DP> ln_ddalpha_sigma = lndet_LU_dstry(one_plus_U);
complex<DP> ln_prod_V = 0.0;
for (int a = 0; a < lstate.N; ++a) ln_prod_V += log(2.0 * II * imag(Vplus[a]));
complex<DP> ln_prod_2 = 0.0;
for (int a = 0; a < lstate.N; ++a)
for (int b = 0; b < lstate.N; ++b)
ln_prod_2 += log((rstate.lambdaoc[a] - rstate.lambdaoc[b] + II)/(lstate.lambdaoc[a] - rstate.lambdaoc[b]));
ln_ddalpha_sigma += ln_prod_V + ln_prod_2 - log(2.0 * II * imag(Vplus[p]));
return (log(II) + Eout + ln_ddalpha_sigma - 0.5 * (lstate.lnnorm + rstate.lnnorm));
}
} // namespace ABACUS

View File

@ -6,7 +6,6 @@ void ABACUS::ludcmp_CX (SQMat_CX& a, Vect_INT& indx, DP& d)
const complex<DP> TINY = 1.0e-200;
int i, j, k;
int imax = 0;
// DP big, dum, sum, temp;
complex<DP> big, dum, sum, temp;
int n = a.size();
@ -16,10 +15,8 @@ void ABACUS::ludcmp_CX (SQMat_CX& a, Vect_INT& indx, DP& d)
for (i = 0; i < n; i++) {
big = 0.0;
for (j = 0; j < n; j++)
// if ((temp = fabs(a[i][j])) > big) big = temp;
if ((abs(temp = a[i][j])) > abs(big)) big = temp;
//if ((norm(temp = a[i][j])) > norm(big)) big = temp;
if (big == 0.0) throw Divide_by_zero(); //ABACUSerror("Singular matrix in routine ludcmp.");
if (big == 0.0) throw Divide_by_zero();
vv[i] = 1.0/big;
}
for (j = 0; j < n; j++) {
@ -33,9 +30,7 @@ void ABACUS::ludcmp_CX (SQMat_CX& a, Vect_INT& indx, DP& d)
sum = a[i][j];
for (k = 0; k < j; k++) sum -= a[i][k] * a[k][j];
a[i][j] = sum;
// if ((dum = vv[i]*fabs(sum)) >= big) {
if ((abs(dum = vv[i]*sum)) >= abs(big)) {
//if ((norm(dum = vv[i]*sum)) >= norm(big)) {
big = dum;
imax = i;
}

View File

@ -14,7 +14,6 @@ void ABACUS::tred2 (SQMat_DP& a, Vect_DP& d, Vect_DP& e)
for (k = 0; k < l + 1; k++) scale += fabs(a[i][k]);
if (scale == 0.0) e[i] = a[i][l];
else {
// scale = 1.0; // <- added this myself...
for (k = 0; k < l + 1; k++) {
a[i][k] /= scale;
h += a[i][k] * a[i][k];

View File

@ -21,8 +21,10 @@ using namespace ABACUS;
namespace ABACUS {
void Build_DME_Matrix_Block_for_NRG (DP c_int, DP L, int N, int iKmin, int iKmax, int Nstates_required, bool symmetric_states, int iKmod,
int weighing_option, int nrglabel_left_begin, int nrglabel_left_end, int nrglabel_right_begin, int nrglabel_right_end,
void Build_DME_Matrix_Block_for_NRG (DP c_int, DP L, int N, int iKmin, int iKmax,
int Nstates_required, bool symmetric_states, int iKmod,
int weighing_option, int nrglabel_left_begin, int nrglabel_left_end,
int nrglabel_right_begin, int nrglabel_right_end,
int block_option, DP* DME_block_1, DP* DME_block_2, Vect_DP Kweight)
{
// Given a list of states produced by Select_States_for_NRG, this function
@ -39,12 +41,18 @@ namespace ABACUS {
// We assume the DME_blocks are already reserved in memory.
// If !symmetric states, DME_block_2 doesn't need to be allocated.
if (nrglabel_left_begin < 0 || nrglabel_right_begin < 0) ABACUSerror("beginning nrglabels negative in Build_DME_Matrix_Block_for_NRG");
if (nrglabel_left_end >= Nstates_required) ABACUSerror("nrglabel_left_end too large in Build_DME_Matric_Block_for_NRG");
if (nrglabel_right_end >= Nstates_required) ABACUSerror("nrglabel_right_end too large in Build_DME_Matric_Block_for_NRG");
if (nrglabel_left_begin < 0 || nrglabel_right_begin < 0)
ABACUSerror("beginning nrglabels negative in Build_DME_Matrix_Block_for_NRG");
if (nrglabel_left_end >= Nstates_required)
ABACUSerror("nrglabel_left_end too large in Build_DME_Matric_Block_for_NRG");
if (nrglabel_right_end >= Nstates_required)
ABACUSerror("nrglabel_right_end too large in Build_DME_Matric_Block_for_NRG");
if (nrglabel_left_begin > nrglabel_left_end)
ABACUSerror("nrglabels of left states improperly chosen in DME block builder.");
if (nrglabel_right_begin > nrglabel_right_end)
ABACUSerror("nrglabels of right states improperly chosen in DME block builder.");
if (nrglabel_left_begin > nrglabel_left_end) ABACUSerror("nrglabels of left states improperly chosen in DME block builder.");
if (nrglabel_right_begin > nrglabel_right_end) ABACUSerror("nrglabels of right states improperly chosen in DME block builder.");
// DME_block is a pointer of size row_l * col_l, where
int block_row_length = nrglabel_right_end - nrglabel_right_begin + 1;
int block_col_length = nrglabel_left_end - nrglabel_left_begin + 1;
@ -77,7 +85,6 @@ namespace ABACUS {
}
// Read the whole data file:
//const int MAXDATA = 5000000;
const int MAXDATA = ABACUS::max(nrglabel_left_end, nrglabel_right_end) + 10; // 10 for safety...
int* nrglabel = new int[MAXDATA];
@ -123,8 +130,9 @@ namespace ABACUS {
Kept_States_left[nrglabel_left - nrglabel_left_begin] = Scanstate;
if (!Scanstate.conv) cout << "State of label " << label[nrglabel_left] << " did not converge after " << Scanstate.iter_Newton
<< " Newton step; diffsq = " << Scanstate.diffsq << endl;
if (!Scanstate.conv)
cout << "State of label " << label[nrglabel_left] << " did not converge after " << Scanstate.iter_Newton
<< " Newton step; diffsq = " << Scanstate.diffsq << endl;
} // for nrglabel_left
for (int nrglabel_right = nrglabel_right_begin; nrglabel_right <= nrglabel_right_end; ++nrglabel_right) {
@ -136,8 +144,9 @@ namespace ABACUS {
Kept_States_right[nrglabel_right - nrglabel_right_begin] = Scanstate;
if (!Scanstate.conv) cout << "State of label " << label[nrglabel_right] << " did not converge after " << Scanstate.iter_Newton
<< " Newton step; diffsq = " << Scanstate.diffsq << endl;
if (!Scanstate.conv)
cout << "State of label " << label[nrglabel_right] << " did not converge after " << Scanstate.iter_Newton
<< " Newton step; diffsq = " << Scanstate.diffsq << endl;
} // for nrglabel_left
@ -147,7 +156,6 @@ namespace ABACUS {
for (int lr = 0; lr < block_row_length; ++lr) {
if (Kept_States_left[ll].conv && Kept_States_right[lr].conv
//&& abs(Kept_States[il].iK - Kept_States[ir].iK) % iKmod == 0)
&& abs(Kept_States_left[ll].iK) % iKmod == 0
&& abs(Kept_States_right[lr].iK) % iKmod == 0) {
@ -176,15 +184,19 @@ namespace ABACUS {
if (block_option == 1) {
DME_block_1[ll* block_row_length + lr] =
(Kweight[abs(Kept_States_left[ll].iK - Kept_States_right[lr].iK)] * real(exp(ln_Density_ME (Kept_States_left[ll], Kept_States_right[lr])))
+ Kweight[abs(Kept_States_left[ll].iK - PRstate.iK)] * real(exp(ln_Density_ME (Kept_States_left[ll], PRstate))));
(Kweight[abs(Kept_States_left[ll].iK - Kept_States_right[lr].iK)]
* real(exp(ln_Density_ME (Kept_States_left[ll], Kept_States_right[lr])))
+ Kweight[abs(Kept_States_left[ll].iK - PRstate.iK)]
* real(exp(ln_Density_ME (Kept_States_left[ll], PRstate))));
// We don't do anything with block 2, we don't even assume it's been allocated.
}
else if (block_option == 2) {
DME_block_1[ll* block_row_length + lr] =
Kweight[abs(Kept_States_left[ll].iK - Kept_States_right[lr].iK)] * real(exp(ln_Density_ME (Kept_States_left[ll], Kept_States_right[lr])));
Kweight[abs(Kept_States_left[ll].iK - Kept_States_right[lr].iK)]
* real(exp(ln_Density_ME (Kept_States_left[ll], Kept_States_right[lr])));
DME_block_2[ll* block_row_length + lr] =
Kweight[abs(Kept_States_left[ll].iK - PRstate.iK)] * real(exp(ln_Density_ME (Kept_States_left[ll], PRstate)));
Kweight[abs(Kept_States_left[ll].iK - PRstate.iK)]
* real(exp(ln_Density_ME (Kept_States_left[ll], PRstate)));
}
}
@ -194,15 +206,19 @@ namespace ABACUS {
if (block_option == 1) {
DME_block_1[ll* block_row_length + lr] = sqrt(0.5) *
(Kweight[abs(Kept_States_left[ll].iK - Kept_States_right[lr].iK)] * real(exp(ln_Density_ME (Kept_States_left[ll], Kept_States_right[lr])))
+ Kweight[abs(Kept_States_left[ll].iK - PRstate.iK)] * real(exp(ln_Density_ME (Kept_States_left[ll], PRstate))));
(Kweight[abs(Kept_States_left[ll].iK - Kept_States_right[lr].iK)]
* real(exp(ln_Density_ME (Kept_States_left[ll], Kept_States_right[lr])))
+ Kweight[abs(Kept_States_left[ll].iK - PRstate.iK)]
* real(exp(ln_Density_ME (Kept_States_left[ll], PRstate))));
// We don't do anything with block 2, we don't even assume it's been allocated.
}
else if (block_option == 2) {
DME_block_1[ll* block_row_length + lr] = sqrt(0.5) *
Kweight[abs(Kept_States_left[ll].iK - Kept_States_right[lr].iK)] * real(exp(ln_Density_ME (Kept_States_left[ll], Kept_States_right[lr])));
Kweight[abs(Kept_States_left[ll].iK - Kept_States_right[lr].iK)]
* real(exp(ln_Density_ME (Kept_States_left[ll], Kept_States_right[lr])));
DME_block_2[ll* block_row_length + lr] = sqrt(0.5) *
Kweight[abs(Kept_States_left[ll].iK - PRstate.iK)] * real(exp(ln_Density_ME (Kept_States_left[ll], PRstate)));
Kweight[abs(Kept_States_left[ll].iK - PRstate.iK)]
* real(exp(ln_Density_ME (Kept_States_left[ll], PRstate)));
}
}
@ -212,15 +228,19 @@ namespace ABACUS {
if (block_option == 1) {
DME_block_1[ll* block_row_length + lr] = sqrt(0.5) *
(Kweight[abs(Kept_States_left[ll].iK - Kept_States_right[lr].iK)] * real(exp(ln_Density_ME (Kept_States_left[ll], Kept_States_right[lr])))
+ Kweight[abs(PLstate.iK - Kept_States_right[lr].iK)] * real(exp(ln_Density_ME (PLstate, Kept_States_right[lr]))));
(Kweight[abs(Kept_States_left[ll].iK - Kept_States_right[lr].iK)]
* real(exp(ln_Density_ME (Kept_States_left[ll], Kept_States_right[lr])))
+ Kweight[abs(PLstate.iK - Kept_States_right[lr].iK)]
* real(exp(ln_Density_ME (PLstate, Kept_States_right[lr]))));
// We don't do anything with block 2, we don't even assume it's been allocated.
}
else if (block_option == 2) {
DME_block_1[ll* block_row_length + lr] = sqrt(0.5) *
Kweight[abs(Kept_States_left[ll].iK - Kept_States_right[lr].iK)] * real(exp(ln_Density_ME (Kept_States_left[ll], Kept_States_right[lr])));
Kweight[abs(Kept_States_left[ll].iK - Kept_States_right[lr].iK)]
* real(exp(ln_Density_ME (Kept_States_left[ll], Kept_States_right[lr])));
DME_block_2[ll* block_row_length + lr] = sqrt(0.5) *
Kweight[abs(PLstate.iK - Kept_States_right[lr].iK)] * real(exp(ln_Density_ME (PLstate, Kept_States_right[lr])));
Kweight[abs(PLstate.iK - Kept_States_right[lr].iK)]
* real(exp(ln_Density_ME (PLstate, Kept_States_right[lr])));
}
}
@ -229,16 +249,13 @@ namespace ABACUS {
else {
DME_block_1[ll* block_row_length + lr] = 0.0;
if (symmetric_states && block_option == 2) DME_block_2[ll* block_row_length + lr] = 0.0; // condition, to prevent segfault if DME_block_2 not allocated.
// condition, to prevent segfault if DME_block_2 not allocated.
if (symmetric_states && block_option == 2) DME_block_2[ll* block_row_length + lr] = 0.0;
}
//cout << ll << "\t" << lr << "\t" << DME_block[ll* block_row_length + lr] << endl;
} // for lr
} // for ll
return;
}
} // namespace ABACUS

View File

@ -43,6 +43,4 @@ namespace ABACUS {
return(value);
}
} // namespace ABACUS

View File

@ -22,12 +22,8 @@ namespace ABACUS {
DP Estimate_Contribution_of_Single_ph_Annihilation_Path_to_2nd_Order_PT (LiebLin_Bethe_State& TopState,
LiebLin_Bethe_State& GroundState,
//Vect_DP Weight_integral)
Vect<complex <DP> >& FT_of_potential)
{
//cout << TopState.label << "\t" << GroundState.label << endl;
//cout << TopState.lambdaoc << endl;
DP contrib_estimate = 0.0;
// Define OriginIx2 for labelling:
@ -49,8 +45,6 @@ namespace ABACUS {
int nr_cont = 0;
// Add first-order PT contribution, and 2nd order from ground state (V_{00} == 1)
//contrib_estimate += Weight_integral[Weight_integral.size()/2 + (TopState.iK - GroundState.iK)]
//* (densityME/(GroundState.E - TopState.E)) * (1.0 - (GroundState.N/GroundState.L)/(GroundState.E - TopState.E));
contrib_estimate += abs(FT_of_potential[FT_of_potential.size()/2 + (TopState.iK - GroundState.iK)]
* (densityME/(GroundState.E - TopState.E))
* (1.0 - (GroundState.N/GroundState.L)/(GroundState.E - TopState.E)));
@ -58,10 +52,6 @@ namespace ABACUS {
nr_cont++;
// Add second order PT contribution coming from TopState:
//contrib_estimate += Weight_integral[Weight_integral.size()/2 + 0]
//* Weight_integral[Weight_integral.size()/2 + (TopState.iK - GroundState.iK)]
//* 1.0 * densityME * (GroundState.N/GroundState.L) // 1.0 is V_{TopState, TopState}
///((GroundState.E - TopState.E) * (GroundState.E - TopState.E));
contrib_estimate += abs(FT_of_potential[FT_of_potential.size()/2 + 0]
* FT_of_potential[FT_of_potential.size()/2 + (TopState.iK - GroundState.iK)]
* 1.0 * densityME * (GroundState.N/GroundState.L) // 1.0 is V_{TopState, TopState}
@ -69,32 +59,20 @@ namespace ABACUS {
nr_cont++;
//cout << "Here b" << endl;
// Now add 2nd order terms coming from single particle-hole annihilation paths:
// this is only to be included for states with at least 4 excitations (2 ph pairs)
if (nphpairs >= 2) {
for (int ipart = 0; ipart < nphpairs; ++ipart) {
for (int ihole = 0; ihole < nphpairs; ++ihole) {
LiebLin_Bethe_State DescendedState = TopState;
//cout << "Here 2a" << "\tipart " << ipart << "\tihole " << ihole << " out of " << nphpairs << " nphpairs, label " << TopState.label << endl;
//cout << "TopState.Ix2 " << TopState.Ix2 << endl;
//cout << "DescendedIx2 " << DescendedState.Ix2 << endl;
DescendedState.Annihilate_ph_pair(ipart, ihole, OriginIx2);
DescendedState.Compute_All(true);
//cout << "DescendedIx2 " << DescendedState.Ix2 << endl;
DP densityME_top_desc = real(exp(ln_Density_ME (TopState, DescendedState)));
DP densityME_desc_ground = real(exp(ln_Density_ME (DescendedState, GroundState)));
//contrib_estimate += Weight_integral[Weight_integral.size()/2 + (TopState.iK - DescendedState.iK)]
//* Weight_integral[Weight_integral.size()/2 + (DescendedState.iK - GroundState.iK)]
//* densityME_top_desc * densityME_desc_ground
///((GroundState.E - TopState.E) * (GroundState.E - DescendedState.E));
// if intermediate state has momentum within allowable window, OK, otherwise discard contribution:
if (abs(TopState.iK - DescendedState.iK) < FT_of_potential.size()/2 &&
abs(DescendedState.iK - GroundState.iK) < FT_of_potential.size()/2) {
@ -112,21 +90,12 @@ namespace ABACUS {
for (int ihole2 = ihole; ihole2 < nphpairs - 1; ++ihole2) {
LiebLin_Bethe_State DescendedState2 = DescendedState;
//cout << "Here 3a" << "\tipart2 " << ipart2 << "\tihole2 " << ihole2 << endl;
//cout << DescendedState2.Ix2 << endl;
DescendedState2.Annihilate_ph_pair(ipart2, ihole2, OriginIx2);
DescendedState2.Compute_All(true);
//cout << DescendedState2.Ix2 << endl;
//cout << DescendedState2.lambdaoc << endl;
DP densityME_top_desc2 = real(exp(ln_Density_ME (TopState, DescendedState2)));
DP densityME_desc2_ground = real(exp(ln_Density_ME (DescendedState2, GroundState)));
//contrib_estimate += Weight_integral[Weight_integral.size()/2 + (TopState.iK - DescendedState2.iK)]
//* Weight_integral[Weight_integral.size()/2 + (DescendedState2.iK - GroundState.iK)]
//* densityME_top_desc2 * densityME_desc2_ground
///((GroundState.E - TopState.E) * (GroundState.E - DescendedState2.E));
// if intermediate state has momentum within allowable window, OK, otherwise discard contribution:
if (abs(TopState.iK - DescendedState2.iK) < FT_of_potential.size()/2 &&
abs(DescendedState2.iK - GroundState.iK) < FT_of_potential.size()/2) {
@ -144,26 +113,19 @@ namespace ABACUS {
for (int ihole3 = ihole2; ihole3 < nphpairs - 2; ++ihole3) {
LiebLin_Bethe_State DescendedState3 = DescendedState2;
//cout << "Here 4a" << "\tipart3 " << ipart3 << "\tihole3 " << ihole3 << endl;
DescendedState3.Annihilate_ph_pair(ipart3, ihole3, OriginIx2);
//cout << DescendedState3.Ix2 << endl;
DescendedState3.Compute_All(true);
//cout << DescendedState3.Ix2 << endl;
DP densityME_top_desc3 = real(exp(ln_Density_ME (TopState, DescendedState3)));
DP densityME_desc3_ground = real(exp(ln_Density_ME (DescendedState3, GroundState)));
//contrib_estimate += Weight_integral[Weight_integral.size()/2 + (TopState.iK - DescendedState3.iK)]
//* Weight_integral[Weight_integral.size()/2 + (DescendedState3.iK - GroundState.iK)]
//* densityME_top_desc3 * densityME_desc3_ground
///((GroundState.E - TopState.E) * (GroundState.E - DescendedState3.E));
// if intermediate state has momentum within allowable window, OK, otherwise discard contribution:
if (abs(TopState.iK - DescendedState3.iK) < FT_of_potential.size()/2 &&
abs(DescendedState3.iK - GroundState.iK) < FT_of_potential.size()/2) {
contrib_estimate += abs(FT_of_potential[FT_of_potential.size()/2 + (TopState.iK - DescendedState3.iK)]
* FT_of_potential[FT_of_potential.size()/2 + (DescendedState3.iK - GroundState.iK)]
* FT_of_potential[FT_of_potential.size()/2
+ (DescendedState3.iK - GroundState.iK)]
* densityME_top_desc3 * densityME_desc3_ground
/((GroundState.E - TopState.E) * (GroundState.E - DescendedState3.E)));
@ -181,34 +143,12 @@ namespace ABACUS {
} // for ipart
} // if nphpairs >= 2
//cout << "Here b" << endl;
//cout << "type_id " << TopState.type_id << "\tid " << TopState.id << "\tcontrib_est = " << contrib_estimate << "\tnr_cont = " << nr_cont << endl;
return(contrib_estimate);
}
/*
DP Estimate_Contribution_of_Base_to_2nd_Order_PT (LiebLin_Bethe_State& ScanState, LiebLin_Bethe_State& GroundState,
Vect_DP Weight_integral, LiebLin_States_and_Density_ME_of_Base& StatesBase)
{
// This function calculates the second-order perturbation theory contribution to
// state ScanState coming from states of base defined in StatesBase.
DP sum_contrib = 0.0;
for (int i = 0; i <= StatesBase.maxid; ++i)
sum_contrib += Weight_integral[Weight_integral.size()/2 + (ScanState.iK - StatesBase.State[i].iK)]
* Weight_integral[Weight_integral.size()/2 + (StatesBase.State[i].iK - GroundState.iK)]
* real(exp(ln_Density_ME (ScanState, StatesBase.State[i]))) * StatesBase.densityME[i]
/((GroundState.E - StatesBase.State[i].E) * (GroundState.E - ScanState.E));
// The strange vector size is so that iK == 0 corresponds to index size/2, as per convention
return(sum_contrib);
}
*/
void Select_States_for_NRG (DP c_int, DP L, int N, int iKmin, int iKmax, int Nstates_required, bool symmetric_states, int iKmod,
//int weighing_option, DP (*weight_integrand_fn) (Vect_DP), Vect_DP& args_to_weight_integrand)
int weighing_option, Vect<complex <DP> >& FT_of_potential)
void Select_States_for_NRG (DP c_int, DP L, int N, int iKmin, int iKmax, int Nstates_required,
bool symmetric_states, int iKmod, int weighing_option, Vect<complex <DP> >& FT_of_potential)
{
// This function reads an existing partition function file and determines whether
// each state is to be included in NRG by applying an energy, momentum and form factor criterion.
@ -218,7 +158,6 @@ namespace ABACUS {
// weighing_option == 1: ordering according to perturbation theory in single p-h annihilation path
// weighing_option == 2: same as 1, but output of list is ordered in weight
stringstream filenameprefix;
Data_File_Name (filenameprefix, 'Z', c_int, L, N, iKmin, iKmax, 0.0, 0.0, "");
string prefix = filenameprefix.str();
@ -250,21 +189,10 @@ namespace ABACUS {
NRG_outfile.open(NRG_Cstr);
if (NRG_outfile.fail()) ABACUSerror("Could not open NRG_outfile... ");
//NRG_outfile.setf(ios::scientific);
NRG_outfile.precision(16);
// Read the whole data file:
/*
// estimate its size:
struct stat statbuf;
stat (RAW_Cstr, &statbuf);
int filesize = statbuf.st_size;
// Determine the number of entries approximately
int entry_size = 1* sizeof(double) + 2*sizeof(int) + 3* sizeof(long long int);
int estimate_nr_entries = filesize/entry_size;
*/
// Count the number of entries in raw file:
int estimate_nr_entries = 0;
@ -273,13 +201,10 @@ namespace ABACUS {
getline(infile, line);
estimate_nr_entries++;
}
const int MAXDATA = estimate_nr_entries;
//cout << "estimate_nr_entries: " << estimate_nr_entries << endl;
DP* E = new DP[MAXDATA];
int* iK = new int[MAXDATA];
//int* conv = new int[MAXDATA];
string* label = new string[MAXDATA];
bool* sym = new bool[MAXDATA];
@ -291,12 +216,10 @@ namespace ABACUS {
while (((infile.peek()) != EOF) && (Ndata < MAXDATA)) {
infile >> E[Ndata];
infile >> iK[Ndata];
//infile >> conv[Ndata];
infile >> label[Ndata];
Ndata++;
}
//cout << "input " << Ndata << " data lines." << endl;
infile.close();
// Define the ground state:
@ -313,30 +236,8 @@ namespace ABACUS {
// To cover negative and positive momenta (in case potential is not symmetric),
// we define the Weight_integral vector entry with index size/2 as corresponding to iK == 0.
/*
// DEPRECATED 25/1/2012: from now on (ABACUS++T_8 onwards), use FT of potential as argument to this function.
Vect_DP Weight_integral (0.0, 4* (iKmax - iKmin)); // we give a large window
//Vect_DP args(0.0, 2);
DP req_rel_prec = 1.0e-6;
DP req_abs_prec = 1.0e-6;
int max_nr_pts = 10000;
for (int iK = -Weight_integral.size()/2; iK < Weight_integral.size()/2; ++iK) {
args_to_weight_integrand[1] = DP(iK);
Integral_result answer = Integrate_optimal (weight_integrand_fn, args_to_weight_integrand,
0, 0.0, 0.5, req_rel_prec, req_abs_prec, max_nr_pts);
Weight_integral[Weight_integral.size()/2 + iK] = answer.integ_est;
}
*/
// Calculate weight of states using selection criterion function
//DP absdensityME = 0.0;
DP* weight = new DP[Ndata];
// For weighing using 2nd order PT, we only trace over 2 excitation states (1 p-h pair)
@ -344,8 +245,6 @@ namespace ABACUS {
for (int i = 0; i < Ndata; ++i) {
//cout << i << " out of " << Ndata << "\tlabel = " << label[i] << endl;
if (abs(iK[i]) % iKmod != 0) { // if iK not a multiple of iKmod: give stupidly high weight.
weight[i] = 1.0e+100;
sym[i] = false; // doesn't matter
@ -359,16 +258,11 @@ namespace ABACUS {
if (weighing_option == 1 || weighing_option == 2) ScanState.Compute_All(true);
sym[i] = ScanState.Check_Symmetry();
//cout << "Setting state " << i << "\t to label " << label[i] << "\tsym: " << sym[i] << endl;
// WEIGHING THE STATES: **********************************************
State_Label_Data currentdata = Read_State_Label (label[i], OriginIx2);
if (currentdata.nexc[0] == 0) weight[i] = 0.0;
else if (symmetric_states && iK[i] < 0 || iK[i] < iKmin || iK[i] > iKmax) weight[i] = 1.0e+100;
//else if (symmetric_states && iK[i] == 0 && !ScanState.Check_Symmetry()) {
else if (symmetric_states && iK[i] == 0 && !sym[i]) {
// This state is at zero momentum but not symmetric. we keep it only if
// the first non-symmetric pair of quantum numbers is right-weighted:
@ -378,7 +272,6 @@ namespace ABACUS {
if (weighing_option == 0) weight[i] = E[i];
else if (weighing_option == 1 || weighing_option == 2)
weight[i] = 1.0/(1.0e-100 + fabs(Estimate_Contribution_of_Single_ph_Annihilation_Path_to_2nd_Order_PT
//(ScanState, GroundState, Weight_integral)));
(ScanState, GroundState, FT_of_potential)));
}
else weight[i] = 1.0e+100;
@ -388,10 +281,8 @@ namespace ABACUS {
if (weighing_option == 0) weight[i] = E[i];
else if (weighing_option == 1 || weighing_option == 2)
weight[i] = 1.0/(1.0e-100 + fabs(Estimate_Contribution_of_Single_ph_Annihilation_Path_to_2nd_Order_PT
//(ScanState, GroundState, Weight_integral)));
(ScanState, GroundState, FT_of_potential)));
}
//cout << i << " out of " << Ndata << "\tlabel = " << label[i] << "\tweight = " << weight[i] << endl;
}
} // for i
@ -402,18 +293,15 @@ namespace ABACUS {
QuickSort(weight, index, 0, Ndata - 1);
// Select states by increasing weight, with a max of Nstates_required entries
DP* E_kept = new DP[Nstates_required];
int* iK_kept = new int[Nstates_required];
//int* conv_kept = new int[Nstates_required];
string* label_kept = new string[Nstates_required];
bool* sym_kept = new bool[Nstates_required];
DP* weight_kept = new DP[Nstates_required];
// Copy selected states into new vectors:
for (int i = 0; i < ABACUS::min(Ndata, Nstates_required); ++i) {
E_kept[i] = E[index[i] ];
iK_kept[i] = iK[index[i] ];
@ -425,7 +313,6 @@ namespace ABACUS {
// If needed, order selected states by increasing energy:
int* index_kept = new int[Nstates_required];
for (int i = 0; i < Nstates_required; ++i) index_kept[i] = i;
@ -436,19 +323,16 @@ namespace ABACUS {
for (int i = 0; i < Nstates_required; ++i) {
if (i > 0) NRG_outfile << endl;
NRG_outfile << i << "\t" << E_kept[i] << "\t" << iK_kept[index_kept[i] ]
//<< "\t" << conv_kept[index_kept[i] ]
<< "\t" << label_kept[index_kept[i] ]
<< "\t" << sym_kept[index_kept[i] ] << "\t" << weight_kept[index_kept[i] ];
}
delete[] E;
delete[] iK;
//delete[] conv;
delete[] label;
delete[] sym;
delete[] E_kept;
delete[] iK_kept;
//delete[] conv_kept;
delete[] label_kept;
delete[] sym_kept;
delete[] weight;
@ -458,5 +342,4 @@ namespace ABACUS {
return;
}
} // namespace ABACUS

View File

@ -37,7 +37,8 @@ namespace ABACUS {
}
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))
: 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;
@ -55,15 +56,14 @@ namespace ABACUS {
}
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)
: 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()) cout << "error: Nstrings = " << RefChain.Nstrings << "\tNrap.size = " << Nrapidities.size() << endl;
if (RefChain.Nstrings != Nrapidities.size()) ABACUSerror("Incompatible Nrapidities vector used in ODSLF_Base constructor.");
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];
@ -81,14 +81,13 @@ namespace ABACUS {
}
// 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)
: 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
@ -101,14 +100,6 @@ namespace ABACUS {
}
Nrap[0] = id_eff;
//id = id_ref;
//cout << "In ODSLF_Base constructor: id_ref = " << id_ref << " and Nrapidities = " << Nrap << endl;
// Check consistency of Nrapidities vector with RefChain
//if (RefChain.Nstrings != Nrap.size()) ABACUSerror("Incompatible Nrapidities vector used in ODSLFBase constructor.");
int Mcheck = 0;
for (int i = 0; i < RefChain.Nstrings; ++i) Mcheck += RefChain.Str_L[i] * Nrap[i];
Mdown = Mcheck;
@ -117,7 +108,6 @@ namespace ABACUS {
for (int i = 0; i < RefChain.Nstrings; ++i) Nraptot += Nrap[i];
// Now compute the Ix2_infty numbers
(*this).Compute_Ix2_limits(RefChain);
}
@ -167,8 +157,9 @@ namespace ABACUS {
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 += (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));
@ -179,8 +170,9 @@ namespace ABACUS {
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);
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.
@ -192,17 +184,12 @@ namespace ABACUS {
// Reject formally infinite rapidities (i.e. if Delta is root of unity)
//cout << "Ix2_infty - Ix2_max = " << Ix2_infty[j] - Ix2_max[j] << endl;
//if (Ix2_infty[j] == Ix2_max[j]) {
//Ix2_max[j] -= 2;
//}
// 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 !
// 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;
// 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;
@ -225,7 +212,6 @@ namespace ABACUS {
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 + 2.0 * RefChain.Str_L[j] - sum1);
Ix2_infty[j] = (RefChain.Nsites + 1.0 - sum1); // to get counting right...
} // The Ix2_infty are now set.
@ -292,16 +278,14 @@ namespace ABACUS {
Ix2_max[j] -= 2;
}
// Fudge, for strings:
//if (RefChain.Str_L[j] >= 1) Ix2_max[j] += 2;
//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)
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
@ -335,8 +319,7 @@ namespace ABACUS {
// 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 + 1;
int Nexc_R_max = (Ix2_max[base_level] + 2)/2; // bug in earlier line: if Ix2_max < 0, must have Nexc_R_max == 0, not 1.
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) {
@ -376,44 +359,22 @@ namespace ABACUS {
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 (Vect<Vect<int> > (1))
{
Ix2[0] = new int[M];
//Ix2[0] = Vect<int> (M);
for (int j = 0; j < M; ++j) {
Ix2[0][j] = -(M - 1) + 2*j;
/*
cout << j << "\t" << Ix2[0][j] << endl;
cout << "Here 1" << endl;
cout << RefChain.Str_L[0] << endl;
// ODSLF: put back correct parity of quantum nr:
cout << "M = " << M << endl;
cout << Ix2[0][j] << endl;
cout << Nrap[0] << endl;
cout << Nraptot << endl;
cout << RefChain.Str_L[0] << endl;
cout << RefChain.par[0] << endl;
cout << RefChain.Nsites << endl;
if ((Ix2[0][j] + RefChain.Nsites - 1 + Nrap[0] + (Nraptot + 1) * RefChain.Str_L[0] + (RefChain.par[0] == 1 ? 0 : RefChain.Nsites)) % 2) Ix2[0][j] -= 1;
cout << "Here 2" << endl;
*/
// Use simplification: Nrap[0] = M = Nraptot, Str_L[0] = 1, par = 1, so
if ((Ix2[0][j] + RefChain.Nsites) % 2) Ix2[0][j] -= 1;
//OBSOLETE: 1 - (M % 2); // last term: correction for ODSLF
}
}
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 (Vect<Vect<int> > (RefChain.Nstrings))
{
//Ix2[0] = new int[base.Mdown];
Ix2[0] = new int[base.Nraptot];
for (int i = 1; i < RefChain.Nstrings; ++i) Ix2[i] = Ix2[i-1] + base[i-1];
//for (int i = 0; i < RefChain.Nstrings; ++i) Ix2[i] = Vect<int> (base[i]);
// 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);
@ -424,30 +385,11 @@ namespace ABACUS {
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;
/*
// New meaning of negative parity:
for (int j = 1; j < base.Nrap.size(); ++j)
if (RefChain.par[j] == -1) // we `invert' the meaning of the quantum numbers
for (int alpha = 0; alpha < base[j]; ++alpha) {
if (Ix2[j][alpha] >= 0) Ix2[j][alpha] -= 2*(base.Ix2_max[j]/2 + 1);
else Ix2[j][alpha] += 2*(base.Ix2_max[j]/2 + 1);
}
*/
}
ODSLF_Ix2_Config& ODSLF_Ix2_Config::operator= (const ODSLF_Ix2_Config& RefConfig)
{
if (this != &RefConfig) {
/*
Ix2 = Vect<Vect<int> > (RefConfig.Ix2.size());
for (int i = 0; i < RefConfig.Ix2.size(); ++i) {
Ix2[i] = Vect<int> (RefConfig.Ix2[i].size());
for (int j = 0; j < RefConfig.Ix2[i].size(); ++j)
Ix2[i][j] = RefConfig.Ix2[i][j];
}
*/
Nstrings = RefConfig.Nstrings;
Nrap = RefConfig.Nrap;
Nraptot = RefConfig.Nraptot;
@ -461,7 +403,7 @@ namespace ABACUS {
for (int i = 0; i < Nstrings; ++i)
for (int j = 0; j < Nrap[i]; ++j) Ix2[i][j] = RefConfig.Ix2[i][j];
}
}
return(*this);
}
@ -494,22 +436,17 @@ namespace ABACUS {
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(Vect<Vect<DP> > (1))
{
lambda[0] = new DP[M];
//lambda[0] = Vect<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(Vect<Vect<DP> > (RefChain.Nstrings))
{
//lambda[0] = new DP[base.Mdown];
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) lambda[i] = Vect<DP> (base[i]);
for (int i = 0; i < RefChain.Nstrings; ++i) {
for (int j = 0; j < base[i]; ++j) lambda[i][j] = 0.0;
@ -519,15 +456,6 @@ namespace ABACUS {
ODSLF_Lambda& ODSLF_Lambda::operator= (const ODSLF_Lambda& RefLambda)
{
if (this != &RefLambda) {
//lambda = RefLambda.lambda;
/*
lambda = Vect<Vect<DP> > (RefLambda.lambda.size());
for (int i = 0; i < RefLambda.lambda.size(); ++i) {
lambda[i] = Vect<DP> (RefLambda.lambda[i].size());
for (int j = 0; j < RefLambda.lambda[i].size(); ++j) lambda[i][j] = RefLambda.lambda[i][j];
}
*/
Nstrings = RefLambda.Nstrings;
Nrap = RefLambda.Nrap;
Nraptot = RefLambda.Nraptot;
@ -541,7 +469,7 @@ namespace ABACUS {
for (int i = 0; i < Nstrings; ++i)
for (int j = 0; j < Nrap[i]; ++j) lambda[i][j] = RefLambda.lambda[i][j];
}
}
return(*this);
}
@ -586,15 +514,16 @@ namespace ABACUS {
(*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)
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.size() != 2 * base.Nrap.size() + 2)
ABACUSerror("Wrong nparticles.size in Ix2_Offsets constructor.");
//if (base.Nrap[0] != (nparticles[3] + nparticles[2] + base.Mdown - nparticles[0] - nparticles[1])) ABACUSerror("Wrong Nrap[0] 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.");
@ -602,35 +531,42 @@ namespace ABACUS {
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;
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.");
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.");
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] - ((base.Nrap[base_level] + 1) % 2) + 2)/2)
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] - (base.Nrap[base_level] % 2) - 1)/2)) {
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 - (base.Ix2_max[base_level] - ((base.Nrap[base_level] + 1) % 2) + 2)/2))
&& 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] - (base.Nrap[base_level] % 2) - 1)/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.");
}
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
@ -644,20 +580,19 @@ namespace ABACUS {
// 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]) % 2) + 2)/2 - nparticles[2*base_level + 2], Tableau[2]);
//(base.Ix2_max[base_level] - base.Nrap[base_level] % 2 + 2)/2 - nparticles[2*base_level + 2], Tableau[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)/2 - nparticles[2*base_level + 3], Tableau[3]);
(base.Ix2_max[base_level] - (base.Nrap[base_level] % 2) - 1)/2 + 1 - nparticles[2*base_level + 3], Tableau[3]);
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;
//id = Tableau[0].id;
for (int i = 0; i < nparticles.size(); ++i) {
maxid *= Tableau[i].maxid + 1LL;
//id += maxid + Tableau[i].id;
}
maxid -= 1LL;
@ -682,13 +617,14 @@ namespace ABACUS {
bool answer = true;
for (int level = 0; level < 4; ++level) { // check fundamental level only
//for (int level = 0; level < 2 * base.Nrap.size() + 2; ++level) {
// 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)
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)
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;
}
@ -702,13 +638,14 @@ namespace ABACUS {
bool answer = true;
for (int level = 0; level < 4; ++level) { // check fundamental level only
//for (int level = 0; level < 2 * base.Nrap.size() + 2; ++level) {
// 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)
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)
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;
}
@ -721,8 +658,6 @@ namespace ABACUS {
// 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]
//cout << "Called Ix2_Offsets::Set_to_id" << endl;
if (idnr > maxid) {
cout << idnr << "\t" << maxid << endl;
ABACUSerror("idnr too large in offsets.Set_to_id.");
@ -738,7 +673,6 @@ namespace ABACUS {
Vect<long long int> result_choose(2*base.Nrap.size() + 2);
for (int i = 0; i <= 2*base.Nrap.size(); ++i) {
//result_choose[i] = choose_lli(Tableau[i].Nrows + Tableau[i].Ncols, Tableau[i].Nrows);
result_choose[i] = Tableau[i].maxid + 1LL;
temp_prod *= result_choose[i];
}
@ -751,8 +685,8 @@ namespace ABACUS {
sub_id[0] = idnr_eff; // what's left goes to the bottom...
for (int i = 0; i <= 2*base.Nrap.size() + 1; ++i) {
//cout << "level = " << i << " Tableau.id = " << sub_id[i] << endl;
if ((Tableau[i].Nrows * Tableau[i].Ncols == 0) && (sub_id[i] != 0)) ABACUSerror("index too large in offset.Set_to_id.");
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]);
}
@ -795,16 +729,11 @@ namespace ABACUS {
if (Nboxes < 0) ABACUSerror("Can't use Nboxes < 0 in Add_Boxes_From_Lowest");
else if (Nboxes == 0) return(true); // nothing to do
//cout << "Requesting Nboxes " << Nboxes << " in " << odd_sectors << " sectors." << endl;
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) {
//cout << "working sector " << working_sector << "\tNboxes_put " << Nboxes_put << endl;
//cout << "Tableau before put: " << Tableau[working_sector] << endl;
Nboxes_put += Tableau[working_sector].Add_Boxes_From_Lowest(Nboxes - Nboxes_put);
//cout << "Tableau after put: " << Tableau[working_sector] << endl;
working_sector += 2;
}
Compute_id();
@ -872,33 +801,21 @@ namespace ABACUS {
};
ODSLF_Bethe_State::ODSLF_Bethe_State (const ODSLF_Bethe_State& RefState) // copy constructor
//: chain(RefState.chain), base(RefState.base), offsets(RefState.offsets), Ix2(Ix2_Config(RefState.chain, RefState.base.Mdown)),
// lambda(Lambda(RefState.chain, RefState.base.Mdown)), BE(Lambda(RefState.chain, RefState.base.Mdown)),
: chain(RefState.chain), base(RefState.base), offsets(RefState.offsets), Ix2(ODSLF_Ix2_Config(RefState.chain, RefState.base)),
: 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),
//id(RefState.id), maxid(RefState.maxid)
base_id(RefState.base_id), type_id(RefState.type_id), id(RefState.id), maxid(RefState.maxid),
nparticles(RefState.nparticles)
{
// copy arrays into new ones
/*
cout << "Here in Heis constructor state" << endl;
cout << "lambda " << lambda[0][0] << endl;
cout << "lambda OK" << endl;
cout << "RefConfig: " << endl << RefState.Ix2 << endl;
cout << "(*this).Ix2: " << endl << Ix2 << endl;
*/
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];
}
}
//cout << "Heis constructor state OK" << endl;
}
ODSLF_Bethe_State::ODSLF_Bethe_State (const ODSLF_Bethe_State& RefState, long long int type_id_ref)
@ -906,72 +823,49 @@ namespace ABACUS {
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),
//id(0LL), maxid(0LL)
base_id(RefState.base_id), type_id(0LL), id(0LL), maxid(offsets.maxid), nparticles(0)
{
//cout << "Here in Heis constructor state type_id" << endl;
//cout << "lambda " << lambda[0][0] << endl;
//cout << "lambda OK" << endl;
(*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)),
: 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),
//id(0LL), maxid(0LL)
base_id(0LL), type_id(0LL), id(0LL), maxid(offsets.maxid), nparticles(0)
{
//cout << "Here in Heis constructor chain M" << endl;
//cout << "requested M = " << M << endl;
//cout << "lambda " << lambda[0][0] << endl;
//cout << "lambda OK" << endl;
}
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),
//id(0LL), maxid(0LL)
: 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
//cout << "Here in Heis constructor chain base" << endl;
//cout << "lambda " << lambda[0][0] << endl;
//cout << "lambda OK" << endl;
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.");
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),
//id(0LL), maxid(0LL)
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)
{
//cout << "Here in Heis constructor chain base_id type_id" << endl;
//cout << "lambda " << lambda[0][0] << endl;
//cout << "lambda OK" << endl;
}
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.");
/*
// Check if total number of holes agrees with number of rapidities in higher particles
int total_nr_holes = RefOffset.Tableau[0].Nrows + RefOffset.Tableau[1].Nrows;
int total_nr_rap_in_particles = 0;
for (int offsets_level = 2; offsets_level < RefOffset.Tableau.size(); offsets_level += 2)
total_nr_rap_in_particles += chain.Str_L[offsets_level/2 - 1] * (RefOffset.Tableau[offsets_level].Nrows + RefOffset.Tableau[offsets_level + 1].Nrows);
cout << total_nr_holes << "\t" << total_nr_rap_in_particles << endl;
if (total_nr_holes != total_nr_rap_in_particles) ABACUSerror("Offset with incompatible Nparticles used in ODSLF_Bethe_State::Set_Ix2_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.
@ -979,103 +873,70 @@ namespace ABACUS {
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];
//cout << "R pcles, j = " << base.Nrap[0] - 1 - j << " Ix2[j] = " << Ix2[0][base.Nrap[0] - 1 - j] << endl;
//cout << "j = " << j << "\tbase.Nrap[0] " << base.Nrap[0] << "\t2*RefOffset.Tableau[2].Nrows " << 2*RefOffset.Tableau[2].Nrows << "\t2*RefOffset.Tableau[2].Row_L[j] " << 2*RefOffset.Tableau[2].Row_L[j] << endl;
//cout << base.Nrap[0] - 1 - j << "\t" << base.Nrap[0] - 1 + 2* RefOffset.Tableau[2].Nrows - 2*j + 2*RefOffset.Tableau[2].Row_L[j] << "\t" << Ix2[0][base.Nrap[0] - 1 - j] << "\t" << Ix2[0][9] << endl;
}
nparticles = RefOffset.Tableau[2].Nrows;
//cout << "Here a" << endl;
// 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*RefOffset.Tableau[0].Nrows - 2*j + 2*RefOffset.Tableau[0].Col_L[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];
//cout << "R holes, j = " << base.Nrap[0] - 1 - RefOffset.Tableau[2].Nrows - j << " Ix2[j] = " << Ix2[0][base.Nrap[0] - 1 - RefOffset.Tableau[2].Nrows - j] << endl;
//cout << base.Nrap[0] << "\t" << (base.Nrap[0] + 1) % 2 << "\t" << RefOffset.Tableau[0].Ncols << "\t" << RefOffset.Tableau[0].Col_L[j] << endl;
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;
//cout << "Here b" << endl;
// 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];
//cout << "L holes, j = " << base.Nrap[0] - 1 - RefOffset.Tableau[0].Ncols - RefOffset.Tableau[2].Nrows- j << " Ix2[j] = " << Ix2[0][base.Nrap[0] - 1 - RefOffset.Tableau[0].Ncols - RefOffset.Tableau[2].Nrows- j] << endl;
}
nparticles += RefOffset.Tableau[1].Ncols;
// cout << "Here c" << endl;
// 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]);
//cout << "R pcles, j = " << base.Nrap[0] - 1 - RefOffset.Tableau[0].Ncols - RefOffset.Tableau[1].Ncols - RefOffset.Tableau[2].Nrows << " Ix2[j] = " << Ix2[0][base.Nrap[0] - 1 - RefOffset.Tableau[0].Ncols - RefOffset.Tableau[1].Ncols - RefOffset.Tableau[2].Nrows] << endl;
}
nparticles += RefOffset.Tableau[3].Nrows;
//cout << "Here d" << endl;
// 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];
= ((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];
= -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;
}
//// Set the correct parity: quantum numbers always integer. Comparing ODSLF with Heis: if M is even, shift all Ix2 by +1:
//if (base.Nrap[0] % 2 == 0)
//for (int j = 0; j < base.Nrap[0]; ++j) Ix2[0][j] += 1; WRONG!!
// 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)
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;
//cout << "Here e" << endl;
//id = RefOffset.id;
//maxid = RefOffset.maxid;
type_id = RefOffset.type_id;
id = RefOffset.id;
maxid = RefOffset.maxid;
/*
// New meaning of negative parity:
for (int j = 1; j < base.Nrap.size(); ++j)
if (chain.par[j] == -1) // we `invert' the meaning of the quantum numbers
for (int alpha = 0; alpha < base[j]; ++alpha) {
if (Ix2[j][alpha] >= 0) Ix2[j][alpha] -= 2*(base.Ix2_max[j]/2 + 1);
else Ix2[j][alpha] += 2*(base.Ix2_max[j]/2 + 1);
}
*/
//cout << "After setting Ix2 with offsets of type_id " << type_id << " and id " << id << endl;
//cout << RefOffset.Tableau[0].Nrows << "\t" << RefOffset.Tableau[0].Ncols << "\t" << RefOffset.Tableau[1].Nrows << "\t" << RefOffset.Tableau[1].Ncols << "\t" << RefOffset.Tableau[2].Nrows << "\t" << RefOffset.Tableau[2].Ncols << "\t" << RefOffset.Tableau[3].Nrows << "\t" << RefOffset.Tableau[3].Ncols << "\t" << endl;
//cout << Ix2[0] << endl;
return;
}
void ODSLF_Bethe_State::Set_to_id (long long int id_ref)
{
//cout << "Heis: Set_to_id called." << endl;
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)
{
//cout << "Heis: Set_to_id called." << endl;
offsets.Set_to_id (id_ref);
(*this).Set_Ix2_Offsets (offsets);
}
@ -1083,40 +944,20 @@ namespace ABACUS {
bool ODSLF_Bethe_State::Check_Symmetry ()
{
// Checks whether the I's are symmetrically distributed.
bool symmetric_state = true;
int arg, test1, test3;
//if (chain.Delta <= 1.0) {
for (int j = 0; j < chain.Nstrings; ++j) {
test1 = 0;
test3 = 0;
for (int alpha = 0; alpha < base[j]; ++alpha) {
arg = (Ix2[j][alpha] != chain.Nsites) ? Ix2[j][alpha] : 0; // since Ix2 = N is same as Ix2 = -N by periodicity, this is symmetric.
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;
}
//}
/*
else if (chain.Delta > 1.0) {
// For the gapped antiferromagnet, we check symmetry *excluding* the Ix2_max values
// The state is then inadmissible is symmetric && -Ix2_max occupied
for (int j = 0; j < chain.Nstrings; ++j) {
test1 = 0;
test3 = 0;
for (int alpha = 0; alpha < base[j]; ++alpha) {
arg = (Ix2[j][alpha] != chain.Nsites
&& abs(Ix2[j][alpha]) != base.Ix2_max[j]) ? Ix2[j][alpha] : 0; // since Ix2 = N is same as Ix2 = -N by periodicity, this is symmetric.
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;
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;
}
@ -1134,22 +975,18 @@ namespace ABACUS {
jmax = j;
alphamax = alpha;
maxterm = pow(BE[j][alpha], 2.0)/chain.Nsites;
}
}
}
diffsq /= DP(chain.Nsites);
}
void ODSLF_Bethe_State::Iterate_BAE ()
{
//DP lambda_old;
for (int j = 0; j < chain.Nstrings; ++j) {
for (int alpha = 0; alpha < base[j]; ++alpha)
{
//lambda_old = lambda[j][alpha];
lambda[j][alpha] = Iterate_BAE (j, alpha);
//cout << j << "\t" << alpha << "\t" << Ix2[j][alpha] << "\t" << lambda_old << "\t" << lambda[j][alpha] << "\t";
}
//cout << endl;
}
iter++;
@ -1193,7 +1030,8 @@ namespace ABACUS {
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];
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);
@ -1216,16 +1054,13 @@ namespace ABACUS {
return;
}
//cout << iter_Newton << "\t" << dlambda << endl;
// 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;//(real(dlambda[i]) > 0) ? 1.0 : -1.0;
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]);
//cout << j << "\t" << alpha << "\t" << dlambda[index] << "\t" << lambda_ref[j][alpha] << "\t" << lambda[j][alpha] << endl;
index++;
}
@ -1234,7 +1069,6 @@ namespace ABACUS {
(*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]));
@ -1258,7 +1092,6 @@ namespace ABACUS {
prec_obtained = pow(BE[j][alpha], 2.0)/chain.Nsites;
niter_here++;
}
}
void ODSLF_Bethe_State::Find_Rapidities (bool reset_rapidities)
@ -1291,9 +1124,6 @@ namespace ABACUS {
while (diffsq > chain.prec && iter < 300 && iter_Newton < 20) {
// If we haven't reset, first try a few Newton steps...
//if (!reset_rapidities && iter_Newton == 0) (*this).Solve_BAE_Newton (chain.prec, 10);
do {
interp_start = clock();
iter_interp_start = iter;
@ -1307,18 +1137,13 @@ namespace ABACUS {
iter_prec = diffsq * 0.001;
//cout << "Interp: iter " << iter << "\tdiffsq " << diffsq << endl;
} 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);
}
//cout << "Smackdown: iter " << iter << "\tdiffsq " << diffsq << endl;
// Now try Newton
Newton_start = clock();
@ -1331,14 +1156,10 @@ namespace ABACUS {
iter_Newton_stop = iter_Newton;
diffsq_Newton_stop = diffsq;
//cout << "Newton: iter " << iter_Newton << "\tdiffsq " << diffsq << endl;
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);
//cout << "Straight iter: iter " << iter << "\tdiffsq " << diffsq << endl;
// If we haven't converged here, retry with more precision in interp method...
if (is_nan(diffsq)) {
@ -1352,9 +1173,6 @@ namespace ABACUS {
}
// Check convergence:
//cout << "Check_Rapidities: " << (*this).Check_Rapidities() << endl;
conv = (diffsq < chain.prec && (*this).Check_Rapidities()) ? 1 : 0;
return;
@ -1369,7 +1187,8 @@ namespace ABACUS {
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];
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...
@ -1384,7 +1203,8 @@ namespace ABACUS {
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];
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;
}
@ -1400,7 +1220,8 @@ namespace ABACUS {
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];
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...
@ -1415,7 +1236,8 @@ namespace ABACUS {
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];
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;
}
}
@ -1429,7 +1251,8 @@ namespace ABACUS {
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];
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...
@ -1446,15 +1269,17 @@ namespace ABACUS {
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];
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];
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];
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];
//(*this).Iterate_BAE();
//for (int j = 0; j < chain.Nstrings; ++j) for (int alpha = 0; alpha < base[j]; ++alpha) lambda5[j][alpha] = lambda[j][alpha];
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;
@ -1467,23 +1292,21 @@ namespace ABACUS {
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];
//rap[4] = lambda5[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);
//cout << j << "\t" << alpha << "\t" << rap << "\t" << lambda[j][alpha] << "\t" << deltalambda << endl;
}
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];
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;
}
@ -1498,19 +1321,7 @@ namespace ABACUS {
SQMat_CX Gaudin_Red(base.Nraptot);
(*this).Build_Reduced_Gaudin_Matrix(Gaudin_Red);
/*
cout << endl << "Gaudin matrix: " << endl;
for (int j = 0; j < Gaudin_Red.size(); ++j) {
for (int k = 0; k < Gaudin_Red.size(); ++k) cout << Gaudin_Red[j][k] << " ";
cout << endl;
}
cout << endl << endl;
*/
complex<DP> lnnorm_check = lndet_LU_CX_dstry(Gaudin_Red);
//cout << "Calculated lnnorm = " << lnnorm_check;
//lnnorm = real(lndet_LU_CX_dstry(Gaudin_Red));
lnnorm = real(lnnorm_check);
}
@ -1577,15 +1388,19 @@ namespace ABACUS {
{
// sends all the state data to output stream
s << endl << "******** Chain with Nsites = " << state.chain.Nsites << " Mdown (nr fermions) = " << state.base.Mdown
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;
<< "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]
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]);
@ -1610,6 +1425,4 @@ namespace ABACUS {
}
} // namespace ABACUS

View File

@ -16,125 +16,6 @@ Purpose: calculates the chemical potential.
namespace ABACUS {
/*
DP Ezero (DP Delta, int N, int M)
{
// Returns the energy of the ground state with M down spins
if (M < 0 || M > N/2) ABACUSerror("M out of bounds in Ezero.");
DP E = -1.0; // sentinel value
if (M == 0) E = N * Delta/4.0;
else {
Heis_Chain BD1(1.0, Delta, 0.0, N);
Vect_INT Nrapidities_groundstate(0, BD1.Nstrings);
Nrapidities_groundstate[0] = M;
ODSLF_Base baseconfig_groundstate(BD1, Nrapidities_groundstate);
if ((Delta > 0.0) && (Delta < 1.0)) {
ODSLF_XXZ_Bethe_State groundstate(BD1, baseconfig_groundstate);
groundstate.Compute_All(true);
E = groundstate.E;
}
else if (Delta == 1.0) {
XXX_Bethe_State groundstate(BD1, baseconfig_groundstate);
groundstate.Compute_All(true);
E = groundstate.E;
}
else if (Delta > 1.0) {
XXZ_gpd_Bethe_State groundstate(BD1, baseconfig_groundstate);
groundstate.Compute_All(true);
E = groundstate.E;
}
else ABACUSerror("Anisotropy out of bounds in Ezero.");
}
return(E);
}
DP H_vs_M (DP Delta, int N, int M)
{
// Assumes dE/dM = 0 = dE_0/dM + h, with dE_0/dM = E_0(M) - E_0 (M - 1)
DP H = 0.0;
if (2*M == N) H = 0.0;
else if (Delta <= 1.0) H = Ezero (Delta, N, M - 1) - Ezero (Delta, N, M);
return(H);
}
DP HZmin (DP Delta, int N, int M, Vect_DP& Ezero_ref)
{
if (M < 0 || M > N/2 - 1) {
cout << "M = " << M << endl;
ABACUSerror("M out of bounds in HZmin.");
}
if (Ezero_ref[M] == -1.0) Ezero_ref[M] = Ezero(Delta, N, M);
if (Ezero_ref[M + 1] == -1.0) Ezero_ref[M + 1] = Ezero(Delta, N, M + 1);
return(Ezero_ref[M] - Ezero_ref[M + 1]);
}
int M_vs_H (DP Delta, int N, DP HZ)
{
// Returns the value of M for given field HZ
if (HZ < 0.0) ABACUSerror("Please use a positive field in M_vs_H.");
else if (HZ == 0.0) return(N/2);
// Here, -1.0 is a sentinel value.
Vect_DP Ezero(-1.0, N/2 + 1); // contains the GSE[M].
// We look for M s.t. HZmin[M] < HZ <= HZmin[M + 1]
int M_actual = N/4; // start somewhere in middle
int M_step = N/8 - 1; // step
DP HZmin_actual = 0.0;
DP HZmax_actual = 0.0;
bool M_found = false;
if (HZ >= 1.0 + Delta) M_actual = 0; // saturation
else {
HZmin_actual = HZmin (Delta, N, M_actual, Ezero);
HZmax_actual = HZmin (Delta, N, M_actual - 1, Ezero);
while (!M_found) {
if (HZmin_actual > HZ) M_actual += M_step;
else if (HZmax_actual <= HZ) M_actual -= M_step;
M_step = (M_step + 1)/2;
HZmin_actual = HZmin (Delta, N, M_actual, Ezero);
HZmax_actual = HZmin (Delta, N, M_actual - 1, Ezero);
M_found = (HZmin_actual < HZ && HZ <= HZmax_actual);
//cout << "M_actual = " << M_actual << "\tM_step = " << M_step
// << "\tHZmin_actual = " << HZmin_actual << "\tHZmax_actual = " << HZmax_actual << "\tHZ = " << HZ << "\t" << M_found << endl;
}
}
//cout << "M found = " << M_actual << "\tHZmax = " << Ezero[M_actual] - Ezero[M_actual + 1] << "\tHZmin = " << Ezero[M_actual - 1] - Ezero[M_actual] << endl;
return(M_actual);
}
*/
DP Chemical_Potential (const ODSLF_Bethe_State& RefState)
{
return(-H_vs_M (RefState.chain.Delta, RefState.chain.Nsites, RefState.base.Mdown)); // - sign since E_{M+1} - E_M = -H

View File

@ -19,8 +19,6 @@ using namespace ABACUS;
namespace ABACUS {
//DP Compute_Matrix_Element_Contrib (char whichDSF, bool fixed_iK, ODSLF_XXZ_Bethe_State& LeftState,
//ODSLF_XXZ_Bethe_State& RefState, DP Chem_Pot, fstream& DAT_outfile)
DP Compute_Matrix_Element_Contrib (char whichDSF, int iKmin, int iKmax, ODSLF_XXZ_Bethe_State& LeftState,
ODSLF_XXZ_Bethe_State& RefState, DP Chem_Pot, fstream& DAT_outfile)
{
@ -39,7 +37,6 @@ namespace ABACUS {
ME = exp(real(ln_Smin_ME (RefState, LeftState)));
else if (whichDSF == 'z') {
if (LeftState.base_id == RefState.base_id && LeftState.type_id == RefState.type_id && LeftState.id == RefState.id)
//MEsq = RefState.chain.Nsites * 0.25 * pow((1.0 - 2.0*RefState.base.Mdown/RefState.chain.Nsites), 2.0);
ME = sqrt(RefState.chain.Nsites * 0.25) * (1.0 - 2.0*RefState.base.Mdown/RefState.chain.Nsites);
else ME = exp(real(ln_Sz_ME (RefState, LeftState)));
}
@ -60,21 +57,18 @@ namespace ABACUS {
if (whichDSF == 'Z') {
DAT_outfile << endl << LeftState.E - RefState.E - (LeftState.base.Mdown - RefState.base.Mdown) * Chem_Pot << "\t"
<< iKout << "\t"
//<< LeftState.conv << "\t"
<< LeftState.base_id << "\t" << LeftState.type_id << "\t" << LeftState.id;
}
else {
DAT_outfile << endl << LeftState.E - RefState.E - (LeftState.base.Mdown - RefState.base.Mdown) * Chem_Pot << "\t"
<< iKout << "\t"
<< ME << "\t"
//<< LeftState.conv << "\t"
<< LeftState.base_id << "\t" << LeftState.type_id << "\t" << LeftState.id;
}
} // if iKmin <= iKout <= iKmax
// Calculate and return the data_value:
DP data_value = ME * ME;
//DP data_value = (iKout == 0 ? 1.0 : 2.0) * MEsq;
if (whichDSF == 'Z') // use 1/(1 + omega)
data_value = 1.0/(1.0 + LeftState.E - RefState.E - (LeftState.base.Mdown - RefState.base.Mdown) * Chem_Pot);
else if (fixed_iK) // data value is MEsq * omega:
@ -83,5 +77,4 @@ namespace ABACUS {
return(data_value);
}
} // namespace ABACUS

View File

@ -59,43 +59,7 @@ namespace ABACUS {
E0_Delta_eps = gstate2.E;
}
/*
else if (Delta == 1.0) {
// Define the ground state
XXX_Bethe_State gstate(chain, gbase);
// Compute everything about the ground state
gstate.Compute_All(true);
E0_Delta = gstate.E;
// Define the ground state
XXZ_gpd_Bethe_State gstate2(chain2, gbase2); // need XXZ_gpd here
// Compute everything about the ground state
gstate2.Compute_All(true);
E0_Delta_eps = gstate2.E;
}
else if (Delta > 1.0) {
// Define the ground state
XXZ_gpd_Bethe_State gstate(chain, gbase);
// Compute everything about the ground state
gstate.Compute_All(true);
E0_Delta = gstate.E;
// Define the ground state
XXZ_gpd_Bethe_State gstate2(chain2, gbase2);
// Compute everything about the ground state
gstate2.Compute_All(true);
E0_Delta_eps = gstate2.E;
}
*/
else ABACUSerror("Wrong anisotropy in ODSLF_S1_sumrule_factor.");
DP answer = 0.0;
@ -117,8 +81,8 @@ namespace ABACUS {
DP sumrule = 0.0;
if (mporz == 'm' || mporz == 'p') sumrule = - 2.0 * ((1.0 - Delta * cos((twoPI * iK)/N)) * X_x + (Delta - cos((twoPI * iK)/N)) * X_z)/N;
//if (mporz == 'm' || mporz == 'p') sumrule = - 1.0 * ((1.0 - Delta * cos((twoPI * iK)/N)) * 2.0 * X_x + (Delta - cos((twoPI * iK)/N)) * (X_x + X_z))/N;
if (mporz == 'm' || mporz == 'p')
sumrule = - 2.0 * ((1.0 - Delta * cos((twoPI * iK)/N)) * X_x + (Delta - cos((twoPI * iK)/N)) * X_z)/N;
else if (mporz == 'z') sumrule = iK == 0 ? 1.0 : -2.0 * X_x * (1.0 - cos((twoPI * iK)/N))/N;
@ -127,20 +91,15 @@ namespace ABACUS {
else ABACUSerror("option not implemented in ODSLF_S1_sumrule_factor.");
//return(1.0/sumrule);
return(1.0/(sumrule + 1.0e-16)); // sumrule is 0 for iK == 0 or N
return(1.0/(sumrule + 1.0e-32)); // sumrule is 0 for iK == 0 or N
}
DP ODSLF_S1_sumrule_factor (char mporz, DP Delta, int N, DP X_x, DP X_z, int iK)
{
//DP X_x = X_avg ('x', Delta, N, M);
//DP X_z = X_avg ('z', Delta, N, M);
DP sumrule = 0.0;
if (mporz == 'm' || mporz == 'p') sumrule = - 2.0 * ((1.0 - Delta * cos((twoPI * iK)/N)) * X_x + (Delta - cos((twoPI * iK)/N)) * X_z)/N;
//if (mporz == 'm' || mporz == 'p') sumrule = - 1.0 * ((1.0 - Delta * cos((twoPI * iK)/N)) * 2.0 * X_x + (Delta - cos((twoPI * iK)/N)) * (X_x + X_z))/N;
if (mporz == 'm' || mporz == 'p')
sumrule = - 2.0 * ((1.0 - Delta * cos((twoPI * iK)/N)) * X_x + (Delta - cos((twoPI * iK)/N)) * X_z)/N;
else if (mporz == 'z') sumrule = -2.0 * X_x * (1.0 - cos((twoPI * iK)/N))/N;
@ -149,15 +108,12 @@ namespace ABACUS {
else ABACUSerror("option not implemented in ODSLF_S1_sumrule_factor.");
//return(1.0/sumrule);
return(1.0/(sumrule + 1.0e-16)); // sumrule is 0 for iK == 0 or N
return(1.0/(sumrule + 1.0e-32)); // sumrule is 0 for iK == 0 or N
}
//DP Sumrule_Factor (char whichDSF, Heis_Bethe_State& RefState, DP Chem_Pot, bool fixed_iK, int iKneeded)
DP Sumrule_Factor (char whichDSF, ODSLF_Bethe_State& RefState, DP Chem_Pot, int iKmin, int iKmax)
{
DP sumrule_factor = 1.0;
//if (!fixed_iK) {
if (iKmin != iKmax) {
if (whichDSF == 'Z') sumrule_factor = 1.0;
else if (whichDSF == 'm')
@ -170,12 +126,11 @@ namespace ABACUS {
else ABACUSerror("whichDSF option not consistent in Sumrule_Factor");
}
//else if (fixed_iK) {
else if (iKmin == iKmax) {
if (whichDSF == 'Z') sumrule_factor = 1.0;
else if (whichDSF == 'm' || whichDSF == 'z' || whichDSF == 'p')
//sumrule_factor = S1_sumrule_factor (whichDSF, RefState.chain.Delta, RefState.chain.Nsites, RefState.base.Mdown, iKneeded);
sumrule_factor = ODSLF_S1_sumrule_factor (whichDSF, RefState.chain.Delta, RefState.chain.Nsites, RefState.base.Mdown, iKmax);
sumrule_factor = ODSLF_S1_sumrule_factor (whichDSF, RefState.chain.Delta, RefState.chain.Nsites,
RefState.base.Mdown, iKmax);
else if (whichDSF == 'a') sumrule_factor = 1.0;
else if (whichDSF == 'b') sumrule_factor = 1.0;
else if (whichDSF == 'q') sumrule_factor = 1.0;
@ -188,8 +143,8 @@ namespace ABACUS {
return(sumrule_factor);
}
//void Evaluate_F_Sumrule (char whichDSF, const ODSLF_Bethe_State& RefState, DP Chem_Pot, int iKmin, int iKmax, const char* FFsq_Cstr, const char* FSR_Cstr)
void Evaluate_F_Sumrule (string prefix, char whichDSF, const ODSLF_Bethe_State& RefState, DP Chem_Pot, int iKmin, int iKmax)
void Evaluate_F_Sumrule (string prefix, char whichDSF, const ODSLF_Bethe_State& RefState,
DP Chem_Pot, int iKmin, int iKmax)
{
stringstream RAW_stringstream; string RAW_string;
@ -205,7 +160,6 @@ namespace ABACUS {
if(infile.fail()) ABACUSerror("Could not open input file in Evaluate_F_Sumrule(ODSLF...).");
// We run through the data file to chech the f sumrule at each positive momenta:
//Vect<DP> Sum_omega_FFsq(0.0, RefState.chain.Nsites/2 + 1); //
Vect<DP> Sum_omega_FFsq(0.0, iKmax - iKmin + 1); //
DP omega, FF;
@ -214,7 +168,6 @@ namespace ABACUS {
while (infile.peek() != EOF) {
infile >> omega >> iK >> FF >> conv >> base_id >> type_id >> id;
//if (iK > 0 && iK <= RefState.chain.Nsites/2) Sum_omega_FFsq[iK] += omega * FFsq;
if (iK >= iKmin && iK <= iKmax) Sum_omega_FFsq[iK - iKmin] += omega * FF * FF;
}
@ -227,15 +180,10 @@ namespace ABACUS {
DP X_x = X_avg ('x', RefState.chain.Delta, RefState.chain.Nsites, RefState.base.Mdown);
DP X_z = X_avg ('z', RefState.chain.Delta, RefState.chain.Nsites, RefState.base.Mdown);
/*
outfile << 0 << "\t" << Sum_omega_FFsq[0] * S1_sumrule_factor (whichDSF, RefState.chain.Delta, RefState.chain.Nsites, X_x, X_z, 0);
for (int i = 1; i <= RefState.chain.Nsites/2; ++i)
outfile << endl << i << "\t" << Sum_omega_FFsq[i] * S1_sumrule_factor (whichDSF, RefState.chain.Delta, RefState.chain.Nsites, X_x, X_z, i);
*/
for (int i = iKmin; i <= iKmax; ++i) {
if (i > iKmin) outfile << endl;
outfile << i << "\t" << Sum_omega_FFsq[i] * ODSLF_S1_sumrule_factor (whichDSF, RefState.chain.Delta, RefState.chain.Nsites, X_x, X_z, i);
outfile << i << "\t" << Sum_omega_FFsq[i] * ODSLF_S1_sumrule_factor (whichDSF, RefState.chain.Delta,
RefState.chain.Nsites, X_x, X_z, i);
}
outfile.close();

View File

@ -31,11 +31,13 @@ namespace ABACUS {
// Function definitions: class ODSLF_XXZ_Bethe_State
ODSLF_XXZ_Bethe_State::ODSLF_XXZ_Bethe_State ()
: ODSLF_Bethe_State(), sinhlambda(ODSLF_Lambda(chain, 1)), coshlambda(ODSLF_Lambda(chain, 1)), tanhlambda(ODSLF_Lambda(chain, 1))
: ODSLF_Bethe_State(), sinhlambda(ODSLF_Lambda(chain, 1)), coshlambda(ODSLF_Lambda(chain, 1)),
tanhlambda(ODSLF_Lambda(chain, 1))
{};
ODSLF_XXZ_Bethe_State::ODSLF_XXZ_Bethe_State (const ODSLF_XXZ_Bethe_State& RefState) // copy constructor
: ODSLF_Bethe_State(RefState), sinhlambda(ODSLF_Lambda(RefState.chain, RefState.base)), coshlambda(ODSLF_Lambda(RefState.chain, RefState.base)),
: ODSLF_Bethe_State(RefState), sinhlambda(ODSLF_Lambda(RefState.chain, RefState.base)),
coshlambda(ODSLF_Lambda(RefState.chain, RefState.base)),
tanhlambda(ODSLF_Lambda(RefState.chain, RefState.base))
{
// copy arrays into new ones
@ -58,21 +60,26 @@ namespace ABACUS {
//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 ODSLF_XXZ_Bethe_State constructor");
if ((RefChain.Delta <= -1.0) || (RefChain.Delta >= 1.0))
ABACUSerror("Delta out of range in ODSLF_XXZ_Bethe_State constructor");
}
ODSLF_XXZ_Bethe_State::ODSLF_XXZ_Bethe_State (const Heis_Chain& RefChain, const ODSLF_Base& RefBase)
: ODSLF_Bethe_State(RefChain, RefBase),
sinhlambda(ODSLF_Lambda(RefChain, RefBase)), coshlambda(ODSLF_Lambda(RefChain, RefBase)), tanhlambda(ODSLF_Lambda(RefChain, RefBase))
sinhlambda(ODSLF_Lambda(RefChain, RefBase)), coshlambda(ODSLF_Lambda(RefChain, RefBase)),
tanhlambda(ODSLF_Lambda(RefChain, RefBase))
{
if ((RefChain.Delta <= -1.0) || (RefChain.Delta >= 1.0)) ABACUSerror("Delta out of range in ODSLF_XXZ_Bethe_State constructor");
if ((RefChain.Delta <= -1.0) || (RefChain.Delta >= 1.0))
ABACUSerror("Delta out of range in ODSLF_XXZ_Bethe_State constructor");
}
ODSLF_XXZ_Bethe_State::ODSLF_XXZ_Bethe_State (const Heis_Chain& RefChain, long long int base_id_ref, long long int type_id_ref)
ODSLF_XXZ_Bethe_State::ODSLF_XXZ_Bethe_State (const Heis_Chain& RefChain,
long long int base_id_ref, long long int type_id_ref)
: ODSLF_Bethe_State(RefChain, base_id_ref, type_id_ref),
sinhlambda(ODSLF_Lambda(chain, base)), coshlambda(ODSLF_Lambda(chain, base)), tanhlambda(ODSLF_Lambda(chain, base))
{
if ((RefChain.Delta <= -1.0) || (RefChain.Delta >= 1.0)) ABACUSerror("Delta out of range in ODSLF_XXZ_Bethe_State constructor");
if ((RefChain.Delta <= -1.0) || (RefChain.Delta >= 1.0))
ABACUSerror("Delta out of range in ODSLF_XXZ_Bethe_State constructor");
}
@ -116,13 +123,13 @@ namespace ABACUS {
for (int alpha = 0; alpha < base[i]; ++alpha) {
if(chain.par[i] == 1) lambda[i][alpha] = (tan(chain.Str_L[i] * 0.5 * chain.anis) * tan(PI * 0.5 * Ix2[i][alpha]/chain.Nsites));
else if (chain.par[i] == -1) lambda[i][alpha] = (-tan((PI * 0.5 * Ix2[i][alpha])/chain.Nsites)/tan(chain.Str_L[i] * 0.5 * chain.anis));
if(chain.par[i] == 1)
lambda[i][alpha] = (tan(chain.Str_L[i] * 0.5 * chain.anis) * tan(PI * 0.5 * Ix2[i][alpha]/chain.Nsites));
else if (chain.par[i] == -1)
lambda[i][alpha] = (-tan((PI * 0.5 * Ix2[i][alpha])/chain.Nsites)/tan(chain.Str_L[i] * 0.5 * chain.anis));
else ABACUSerror("Invalid parities in Set_Free_lambdas.");
// if (lambda[i][alpha] == 0.0) lambda[i][alpha] = 0.001 * (1.0 + i) * (1.0 + alpha) / chain.Nsites; // some arbitrary starting point here...
}
}
@ -168,8 +175,8 @@ namespace ABACUS {
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) && (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.
}
@ -181,14 +188,16 @@ namespace ABACUS {
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)))
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;
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;
}
@ -197,12 +206,14 @@ namespace ABACUS {
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));
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;
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;
@ -226,17 +237,23 @@ namespace ABACUS {
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 * ODSLF_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);
? 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 * ODSLF_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;
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 ODSLF_XXZ_Bethe_State::Compute_BE ()
{
@ -254,17 +271,22 @@ namespace ABACUS {
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 * ODSLF_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);
? 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 * ODSLF_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;
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;
}
}
@ -277,15 +299,15 @@ namespace ABACUS {
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])
);
* 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]];
else if (chain.par[j] == -1)
arg = -tan(0.5 *
(-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);
@ -305,21 +327,26 @@ namespace ABACUS {
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 * ODSLF_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);
? 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 * ODSLF_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);
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 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.");
}
//cout << "Rapidity blows up !\t" << lambda[j][alpha] << "\t" << new_lambda << endl;
}
return(new_lambda);
@ -341,7 +368,8 @@ namespace ABACUS {
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 += sin(chain.Str_L[j] * chain.anis)
/ (chain.par[j] * cosh(2.0 * lambda[j][alpha]) - cos(chain.Str_L[j] * chain.anis));
}
}
@ -352,32 +380,6 @@ namespace ABACUS {
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 ODSLF_XXZ_Bethe_State::Build_Reduced_Gaudin_Matrix (SQMat<complex<DP> >& Gaudin_Red)
{
@ -408,26 +410,30 @@ namespace ABACUS {
for (int betap = 0; betap < base[kp]; ++betap) {
if (!((j == kp) && (alpha == betap)))
sum_hbar_XXZ
+= ODSLF_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);
+= ODSLF_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 * ODSLF_hbar_XXZ (lambda[j][alpha], chain.Str_L[j], chain.par[j], chain.si_n_anis_over_2) - sum_hbar_XXZ);
= complex<DP> ( chain.Nsites * ODSLF_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) );
? 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> (ODSLF_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));
Gaudin_Red[index_jalpha][index_kbeta] =
complex<DP> (ODSLF_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++;
}
@ -465,7 +471,8 @@ namespace ABACUS {
result = (nj == nk) ? 0.0 : ODSLF_fbar_XXZ(tanhlambda, parj*park, tannzetaover2[fabs(nj - nk)]);
for (int a = 1; a < ABACUS::min(nj, nk); ++a) result += 2.0 * ODSLF_fbar_XXZ(tanhlambda, parj*park, tannzetaover2[fabs(nj - nk) + 2*a]);
for (int a = 1; a < ABACUS::min(nj, nk); ++a)
result += 2.0 * ODSLF_fbar_XXZ(tanhlambda, parj*park, tannzetaover2[fabs(nj - nk) + 2*a]);
result += ODSLF_fbar_XXZ(tanhlambda, parj*park, tannzetaover2[nj + nk]);
}
@ -490,7 +497,8 @@ namespace ABACUS {
{
DP result = (nj == nk) ? 0.0 : ODSLF_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 * ODSLF_hbar_XXZ(lambda, fabs(nj - nk) + 2*a, parj*park, si_n_anis_over_2);
for (int a = 1; a < ABACUS::min(nj, nk); ++a)
result += 2.0 * ODSLF_hbar_XXZ(lambda, fabs(nj - nk) + 2*a, parj*park, si_n_anis_over_2);
result += ODSLF_hbar_XXZ(lambda, nj + nk, parj*park, si_n_anis_over_2);

View File

@ -18,323 +18,317 @@ using namespace ABACUS;
namespace ABACUS {
inline complex<DP> ln_Fn_F (ODSLF_XXZ_Bethe_State& B, int k, int beta, int b)
{
complex<DP> ans = 0.0;
complex<DP> prod_temp = 1.0;
int counter = 0;
int arg = 0;
int absarg = 0;
int par_comb_1, par_comb_2;
inline complex<DP> ln_Fn_F (ODSLF_XXZ_Bethe_State& B, int k, int beta, int b)
{
complex<DP> ans = 0.0;
complex<DP> prod_temp = 1.0;
int counter = 0;
int arg = 0;
int absarg = 0;
int par_comb_1, par_comb_2;
for (int j = 0; j < B.chain.Nstrings; ++j) {
for (int j = 0; j < B.chain.Nstrings; ++j) {
par_comb_1 = B.chain.par[j] == B.chain.par[k] ? 1 : 0;
par_comb_2 = B.chain.par[k] == B.chain.par[j] ? 0 : B.chain.par[k];
par_comb_1 = B.chain.par[j] == B.chain.par[k] ? 1 : 0;
par_comb_2 = B.chain.par[k] == B.chain.par[j] ? 0 : B.chain.par[k];
for (int alpha = 0; alpha < B.base.Nrap[j]; ++alpha) {
for (int a = 1; a <= B.chain.Str_L[j]; ++a) {
for (int alpha = 0; alpha < B.base.Nrap[j]; ++alpha) {
for (int a = 1; a <= B.chain.Str_L[j]; ++a) {
if (!((j == k) && (alpha == beta) && (a == b))) {
if (!((j == k) && (alpha == beta) && (a == b))) {
arg = B.chain.Str_L[j] - B.chain.Str_L[k] - 2 * (a - b);
absarg = abs(arg);
/*
prod_temp *= 0.5 * //done later...
((B.sinhlambda[j][alpha] * B.coshlambda[k][beta] - B.coshlambda[j][alpha] * B.sinhlambda[k][beta])
* (B.chain.co_n_anis_over_2[absarg] * (1.0 + B.chain.par[j] * B.chain.par[k])
- sgn_int(arg) * B.chain.si_n_anis_over_2[absarg] * (B.chain.par[k] - B.chain.par[j]))
+ II * (B.coshlambda[j][alpha] * B.coshlambda[k][beta] - B.sinhlambda[j][alpha] * B.sinhlambda[k][beta])
* (sgn_int(arg) * B.chain.si_n_anis_over_2[absarg] * (1.0 + B.chain.par[j] * B.chain.par[k])
+ B.chain.co_n_anis_over_2[absarg] * (B.chain.par[k] - B.chain.par[j])) );
*/
arg = B.chain.Str_L[j] - B.chain.Str_L[k] - 2 * (a - b);
absarg = abs(arg);
prod_temp *= ((B.sinhlambda[j][alpha] * B.coshlambda[k][beta] - B.coshlambda[j][alpha] * B.sinhlambda[k][beta])
* (B.chain.co_n_anis_over_2[absarg] * par_comb_1 - sgn_int(arg) * B.chain.si_n_anis_over_2[absarg] * par_comb_2)
+ II * (B.coshlambda[j][alpha] * B.coshlambda[k][beta] - B.sinhlambda[j][alpha] * B.sinhlambda[k][beta])
* (sgn_int(arg) * B.chain.si_n_anis_over_2[absarg] * par_comb_1 + B.chain.co_n_anis_over_2[absarg] * par_comb_2));
}
prod_temp *= ((B.sinhlambda[j][alpha] * B.coshlambda[k][beta]
- B.coshlambda[j][alpha] * B.sinhlambda[k][beta])
* (B.chain.co_n_anis_over_2[absarg] * par_comb_1
- sgn_int(arg) * B.chain.si_n_anis_over_2[absarg] * par_comb_2)
+ II * (B.coshlambda[j][alpha] * B.coshlambda[k][beta]
- B.sinhlambda[j][alpha] * B.sinhlambda[k][beta])
* (sgn_int(arg) * B.chain.si_n_anis_over_2[absarg] * par_comb_1
+ B.chain.co_n_anis_over_2[absarg] * par_comb_2));
}
if (counter++ > 100) { // we do at most 100 products before taking a log
ans += log(prod_temp);
prod_temp = 1.0;
counter = 0;
}
if (counter++ > 100) { // we do at most 100 products before taking a log
ans += log(prod_temp);
prod_temp = 1.0;
counter = 0;
}
}}}
}}}
return(ans + log(prod_temp));
}
inline complex<DP> ln_Fn_G (ODSLF_XXZ_Bethe_State& A, ODSLF_XXZ_Bethe_State& B, int k, int beta, int b)
{
complex<DP> ans = 0.0;
complex<DP> prod_temp = 1.0;
int counter = 0;
int arg = 0;
int absarg = 0;
int par_comb_1, par_comb_2;
for (int j = 0; j < A.chain.Nstrings; ++j) {
par_comb_1 = A.chain.par[j] == B.chain.par[k] ? 1 : 0;
par_comb_2 = B.chain.par[k] == A.chain.par[j] ? 0 : B.chain.par[k];
for (int alpha = 0; alpha < A.base.Nrap[j]; ++alpha) {
for (int a = 1; a <= A.chain.Str_L[j]; ++a) {
arg = A.chain.Str_L[j] - B.chain.Str_L[k] - 2 * (a - b);
absarg = abs(arg);
/*
prod_temp *= 0.5 * //done later...
((A.sinhlambda[j][alpha] * B.coshlambda[k][beta] - A.coshlambda[j][alpha] * B.sinhlambda[k][beta])
* (A.chain.co_n_anis_over_2[absarg] * (1.0 + A.chain.par[j] * B.chain.par[k])
- sgn_int(arg) * A.chain.si_n_anis_over_2[absarg] * (B.chain.par[k] - A.chain.par[j]))
+ II * (A.coshlambda[j][alpha] * B.coshlambda[k][beta] - A.sinhlambda[j][alpha] * B.sinhlambda[k][beta])
* (sgn_int(arg) * A.chain.si_n_anis_over_2[absarg] * (1.0 + A.chain.par[j] * B.chain.par[k])
+ A.chain.co_n_anis_over_2[absarg] * (B.chain.par[k] - A.chain.par[j])) );
*/
prod_temp *= ((A.sinhlambda[j][alpha] * B.coshlambda[k][beta] - A.coshlambda[j][alpha] * B.sinhlambda[k][beta])
* (A.chain.co_n_anis_over_2[absarg] * par_comb_1 - sgn_int(arg) * A.chain.si_n_anis_over_2[absarg] * par_comb_2)
+ II * (A.coshlambda[j][alpha] * B.coshlambda[k][beta] - A.sinhlambda[j][alpha] * B.sinhlambda[k][beta])
* (sgn_int(arg) * A.chain.si_n_anis_over_2[absarg] * par_comb_1 + A.chain.co_n_anis_over_2[absarg] * par_comb_2));
if (counter++ > 100) { // we do at most 100 products before taking a log
ans += log(prod_temp);
prod_temp = 1.0;
counter = 0;
}
}}}
return(ans + log(prod_temp));
}
inline complex<DP> Fn_K (ODSLF_XXZ_Bethe_State& A, int j, int alpha, int a, ODSLF_XXZ_Bethe_State& B, int k, int beta, int b)
{
int arg1 = A.chain.Str_L[j] - B.chain.Str_L[k] - 2 * (a - b);
int absarg1 = abs(arg1);
int arg2 = arg1 + 2;
int absarg2 = abs(arg2);
return(4.0/(
((A.sinhlambda[j][alpha] * B.coshlambda[k][beta] - A.coshlambda[j][alpha] * B.sinhlambda[k][beta])
* (A.chain.co_n_anis_over_2[absarg1] * (1.0 + A.chain.par[j] * B.chain.par[k])
- sgn_int(arg1) * A.chain.si_n_anis_over_2[absarg1] * (B.chain.par[k] - A.chain.par[j]))
+ II * (A.coshlambda[j][alpha] * B.coshlambda[k][beta] - A.sinhlambda[j][alpha] * B.sinhlambda[k][beta])
* (sgn_int(arg1) * A.chain.si_n_anis_over_2[absarg1] * (1.0 + A.chain.par[j] * B.chain.par[k])
+ A.chain.co_n_anis_over_2[absarg1] * (B.chain.par[k] - A.chain.par[j])) )
*
((A.sinhlambda[j][alpha] * B.coshlambda[k][beta] - A.coshlambda[j][alpha] * B.sinhlambda[k][beta])
* (A.chain.co_n_anis_over_2[absarg2] * (1.0 + A.chain.par[j] * B.chain.par[k])
- sgn_int(arg2) * A.chain.si_n_anis_over_2[absarg2] * (B.chain.par[k] - A.chain.par[j]))
+ II * (A.coshlambda[j][alpha] * B.coshlambda[k][beta] - A.sinhlambda[j][alpha] * B.sinhlambda[k][beta])
* (sgn_int(arg2) * A.chain.si_n_anis_over_2[absarg2] * (1.0 + A.chain.par[j] * B.chain.par[k])
+ A.chain.co_n_anis_over_2[absarg2] * (B.chain.par[k] - A.chain.par[j])) )
));
}
inline complex<DP> Fn_L (ODSLF_XXZ_Bethe_State& A, int j, int alpha, int a, ODSLF_XXZ_Bethe_State& B, int k, int beta, int b)
{
return (sinh(2.0 * (A.lambda[j][alpha] - B.lambda[k][beta]
+ 0.5 * II * B.chain.anis * (A.chain.Str_L[j] - B.chain.Str_L[k] - 2.0 * (a - b - 0.5))
+ 0.25 * II * PI * complex<DP>(-A.chain.par[j] + B.chain.par[k])))
* pow(Fn_K (A, j, alpha, a, B, k, beta, b), 2.0));
}
complex<DP> ln_Smin_ME (ODSLF_XXZ_Bethe_State& A, ODSLF_XXZ_Bethe_State& B)
{
// This function returns the natural log of the S^- operator matrix element.
// The A and B states can contain strings.
// Check that the two states are compatible
if (A.chain != B.chain) ABACUSerror("Incompatible ODSLF_XXZ_Chains in Smin matrix element.");
// Check that A and B are Mdown-compatible:
if (A.base.Mdown != B.base.Mdown + 1) ABACUSerror("Incompatible Mdown between the two states in Smin matrix element!");
// Compute the sinh and cosh of rapidities
A.Compute_sinhlambda();
A.Compute_coshlambda();
B.Compute_sinhlambda();
B.Compute_coshlambda();
// Some convenient arrays
ODSLF_Lambda re_ln_Fn_F_B_0(B.chain, B.base);
ODSLF_Lambda im_ln_Fn_F_B_0(B.chain, B.base);
ODSLF_Lambda re_ln_Fn_G_0(B.chain, B.base);
ODSLF_Lambda im_ln_Fn_G_0(B.chain, B.base);
ODSLF_Lambda re_ln_Fn_G_2(B.chain, B.base);
ODSLF_Lambda im_ln_Fn_G_2(B.chain, B.base);
complex<DP> ln_prod1 = 0.0;
complex<DP> ln_prod2 = 0.0;
complex<DP> ln_prod3 = 0.0;
complex<DP> ln_prod4 = 0.0;
for (int i = 0; i < A.chain.Nstrings; ++i)
for (int alpha = 0; alpha < A.base.Nrap[i]; ++alpha)
for (int a = 1; a <= A.chain.Str_L[i]; ++a)
ln_prod1 += log(norm(sinh(A.lambda[i][alpha] + 0.5 * II * A.chain.anis * (A.chain.Str_L[i] + 1.0 - 2.0 * a - 1.0)
+ 0.25 * II * PI * (1.0 - A.chain.par[i]))));
for (int i = 0; i < B.chain.Nstrings; ++i)
for (int alpha = 0; alpha < B.base.Nrap[i]; ++alpha)
for (int a = 1; a <= B.chain.Str_L[i]; ++a)
if (norm(sinh(B.lambda[i][alpha] + 0.5 * II * B.chain.anis * (B.chain.Str_L[i] + 1.0 - 2.0 * a - 1.0)
+ 0.25 * II * PI * (1.0 - B.chain.par[i]))) > 100.0 * MACHINE_EPS_SQ)
ln_prod2 += log(norm(sinh(B.lambda[i][alpha] + 0.5 * II * B.chain.anis * (B.chain.Str_L[i] + 1.0 - 2.0 * a - 1.0)
+ 0.25 * II * PI * (1.0 - B.chain.par[i]))));
// Define the F ones earlier...
for (int j = 0; j < B.chain.Nstrings; ++j) {
for (int alpha = 0; alpha < B.base.Nrap[j]; ++alpha) {
re_ln_Fn_F_B_0[j][alpha] = real(ln_Fn_F(B, j, alpha, 0));
im_ln_Fn_F_B_0[j][alpha] = imag(ln_Fn_F(B, j, alpha, 0));
re_ln_Fn_G_0[j][alpha] = real(ln_Fn_G(A, B, j, alpha, 0));
im_ln_Fn_G_0[j][alpha] = imag(ln_Fn_G(A, B, j, alpha, 0));
re_ln_Fn_G_2[j][alpha] = real(ln_Fn_G(A, B, j, alpha, 2));
im_ln_Fn_G_2[j][alpha] = imag(ln_Fn_G(A, B, j, alpha, 2));
}
return(ans + log(prod_temp));
}
DP logabssinzeta = log(abs(sin(A.chain.anis)));
inline complex<DP> ln_Fn_G (ODSLF_XXZ_Bethe_State& A, ODSLF_XXZ_Bethe_State& B, int k, int beta, int b)
{
complex<DP> ans = 0.0;
complex<DP> prod_temp = 1.0;
int counter = 0;
int arg = 0;
int absarg = 0;
int par_comb_1, par_comb_2;
// Define regularized products in prefactors
for (int j = 0; j < A.chain.Nstrings; ++j) {
for (int j = 0; j < A.chain.Nstrings; ++j)
for (int alpha = 0; alpha < A.base.Nrap[j]; ++alpha)
for (int a = 1; a <= A.chain.Str_L[j]; ++a)
ln_prod3 += ln_Fn_F(A, j, alpha, a - 1); // assume only one-strings here
par_comb_1 = A.chain.par[j] == B.chain.par[k] ? 1 : 0;
par_comb_2 = B.chain.par[k] == A.chain.par[j] ? 0 : B.chain.par[k];
ln_prod3 -= A.base.Mdown * log(abs(sin(A.chain.anis)));
for (int alpha = 0; alpha < A.base.Nrap[j]; ++alpha) {
for (int a = 1; a <= A.chain.Str_L[j]; ++a) {
for (int k = 0; k < B.chain.Nstrings; ++k)
for (int beta = 0; beta < B.base.Nrap[k]; ++beta)
for (int b = 1; b <= B.chain.Str_L[k]; ++b) {
if (b == 1) ln_prod4 += re_ln_Fn_F_B_0[k][beta];
else if (b > 1) ln_prod4 += ln_Fn_F(B, k, beta, b - 1);
arg = A.chain.Str_L[j] - B.chain.Str_L[k] - 2 * (a - b);
absarg = abs(arg);
prod_temp *= ((A.sinhlambda[j][alpha] * B.coshlambda[k][beta]
- A.coshlambda[j][alpha] * B.sinhlambda[k][beta])
* (A.chain.co_n_anis_over_2[absarg] * par_comb_1
- sgn_int(arg) * A.chain.si_n_anis_over_2[absarg] * par_comb_2)
+ II * (A.coshlambda[j][alpha] * B.coshlambda[k][beta]
- A.sinhlambda[j][alpha] * B.sinhlambda[k][beta])
* (sgn_int(arg) * A.chain.si_n_anis_over_2[absarg] * par_comb_1
+ A.chain.co_n_anis_over_2[absarg] * par_comb_2));
if (counter++ > 100) { // we do at most 100 products before taking a log
ans += log(prod_temp);
prod_temp = 1.0;
counter = 0;
}
}}}
return(ans + log(prod_temp));
}
inline complex<DP> Fn_K (ODSLF_XXZ_Bethe_State& A, int j, int alpha, int a,
ODSLF_XXZ_Bethe_State& B, int k, int beta, int b)
{
int arg1 = A.chain.Str_L[j] - B.chain.Str_L[k] - 2 * (a - b);
int absarg1 = abs(arg1);
int arg2 = arg1 + 2;
int absarg2 = abs(arg2);
return(4.0/(
((A.sinhlambda[j][alpha] * B.coshlambda[k][beta] - A.coshlambda[j][alpha] * B.sinhlambda[k][beta])
* (A.chain.co_n_anis_over_2[absarg1] * (1.0 + A.chain.par[j] * B.chain.par[k])
- sgn_int(arg1) * A.chain.si_n_anis_over_2[absarg1] * (B.chain.par[k] - A.chain.par[j]))
+ II * (A.coshlambda[j][alpha] * B.coshlambda[k][beta] - A.sinhlambda[j][alpha] * B.sinhlambda[k][beta])
* (sgn_int(arg1) * A.chain.si_n_anis_over_2[absarg1] * (1.0 + A.chain.par[j] * B.chain.par[k])
+ A.chain.co_n_anis_over_2[absarg1] * (B.chain.par[k] - A.chain.par[j])) )
*
((A.sinhlambda[j][alpha] * B.coshlambda[k][beta] - A.coshlambda[j][alpha] * B.sinhlambda[k][beta])
* (A.chain.co_n_anis_over_2[absarg2] * (1.0 + A.chain.par[j] * B.chain.par[k])
- sgn_int(arg2) * A.chain.si_n_anis_over_2[absarg2] * (B.chain.par[k] - A.chain.par[j]))
+ II * (A.coshlambda[j][alpha] * B.coshlambda[k][beta] - A.sinhlambda[j][alpha] * B.sinhlambda[k][beta])
* (sgn_int(arg2) * A.chain.si_n_anis_over_2[absarg2] * (1.0 + A.chain.par[j] * B.chain.par[k])
+ A.chain.co_n_anis_over_2[absarg2] * (B.chain.par[k] - A.chain.par[j])) )
));
}
inline complex<DP> Fn_L (ODSLF_XXZ_Bethe_State& A, int j, int alpha, int a,
ODSLF_XXZ_Bethe_State& B, int k, int beta, int b)
{
return (sinh(2.0 * (A.lambda[j][alpha] - B.lambda[k][beta]
+ 0.5 * II * B.chain.anis * (A.chain.Str_L[j] - B.chain.Str_L[k] - 2.0 * (a - b - 0.5))
+ 0.25 * II * PI * complex<DP>(-A.chain.par[j] + B.chain.par[k])))
* pow(Fn_K (A, j, alpha, a, B, k, beta, b), 2.0));
}
complex<DP> ln_Smin_ME (ODSLF_XXZ_Bethe_State& A, ODSLF_XXZ_Bethe_State& B)
{
// This function returns the natural log of the S^- operator matrix element.
// The A and B states can contain strings.
// Check that the two states are compatible
if (A.chain != B.chain)
ABACUSerror("Incompatible ODSLF_XXZ_Chains in Smin matrix element.");
// Check that A and B are Mdown-compatible:
if (A.base.Mdown != B.base.Mdown + 1)
ABACUSerror("Incompatible Mdown between the two states in Smin matrix element!");
// Compute the sinh and cosh of rapidities
A.Compute_sinhlambda();
A.Compute_coshlambda();
B.Compute_sinhlambda();
B.Compute_coshlambda();
// Some convenient arrays
ODSLF_Lambda re_ln_Fn_F_B_0(B.chain, B.base);
ODSLF_Lambda im_ln_Fn_F_B_0(B.chain, B.base);
ODSLF_Lambda re_ln_Fn_G_0(B.chain, B.base);
ODSLF_Lambda im_ln_Fn_G_0(B.chain, B.base);
ODSLF_Lambda re_ln_Fn_G_2(B.chain, B.base);
ODSLF_Lambda im_ln_Fn_G_2(B.chain, B.base);
complex<DP> ln_prod1 = 0.0;
complex<DP> ln_prod2 = 0.0;
complex<DP> ln_prod3 = 0.0;
complex<DP> ln_prod4 = 0.0;
for (int i = 0; i < A.chain.Nstrings; ++i)
for (int alpha = 0; alpha < A.base.Nrap[i]; ++alpha)
for (int a = 1; a <= A.chain.Str_L[i]; ++a)
ln_prod1 += log(norm(sinh(A.lambda[i][alpha] + 0.5 * II * A.chain.anis * (A.chain.Str_L[i] + 1.0 - 2.0 * a - 1.0)
+ 0.25 * II * PI * (1.0 - A.chain.par[i]))));
for (int i = 0; i < B.chain.Nstrings; ++i)
for (int alpha = 0; alpha < B.base.Nrap[i]; ++alpha)
for (int a = 1; a <= B.chain.Str_L[i]; ++a)
if (norm(sinh(B.lambda[i][alpha] + 0.5 * II * B.chain.anis * (B.chain.Str_L[i] + 1.0 - 2.0 * a - 1.0)
+ 0.25 * II * PI * (1.0 - B.chain.par[i]))) > 100.0 * MACHINE_EPS_SQ)
ln_prod2 += log(norm(sinh(B.lambda[i][alpha] + 0.5 * II * B.chain.anis * (B.chain.Str_L[i] + 1.0 - 2.0 * a - 1.0)
+ 0.25 * II * PI * (1.0 - B.chain.par[i]))));
// Define the F ones earlier...
for (int j = 0; j < B.chain.Nstrings; ++j) {
for (int alpha = 0; alpha < B.base.Nrap[j]; ++alpha) {
re_ln_Fn_F_B_0[j][alpha] = real(ln_Fn_F(B, j, alpha, 0));
im_ln_Fn_F_B_0[j][alpha] = imag(ln_Fn_F(B, j, alpha, 0));
re_ln_Fn_G_0[j][alpha] = real(ln_Fn_G(A, B, j, alpha, 0));
im_ln_Fn_G_0[j][alpha] = imag(ln_Fn_G(A, B, j, alpha, 0));
re_ln_Fn_G_2[j][alpha] = real(ln_Fn_G(A, B, j, alpha, 2));
im_ln_Fn_G_2[j][alpha] = imag(ln_Fn_G(A, B, j, alpha, 2));
}
}
ln_prod4 -= B.base.Mdown * log(abs(sin(B.chain.anis)));
DP logabssinzeta = log(abs(sin(A.chain.anis)));
// Now proceed to build the Hm matrix
// Define regularized products in prefactors
SQMat_CX Hm(0.0, A.base.Mdown);
for (int j = 0; j < A.chain.Nstrings; ++j)
for (int alpha = 0; alpha < A.base.Nrap[j]; ++alpha)
for (int a = 1; a <= A.chain.Str_L[j]; ++a)
ln_prod3 += ln_Fn_F(A, j, alpha, a - 1); // assume only one-strings here
int index_a = 0;
int index_b = 0;
ln_prod3 -= A.base.Mdown * log(abs(sin(A.chain.anis)));
complex<DP> sum1 = 0.0;
complex<DP> sum2 = 0.0;
complex<DP> prod_num = 0.0;
complex<DP> Fn_K_0_G_0 = 0.0;
complex<DP> Prod_powerN = 0.0;
complex<DP> Fn_K_1_G_2 = 0.0;
complex<DP> one_over_A_sinhlambda_sq_plus_sinzetaover2sq;
for (int k = 0; k < B.chain.Nstrings; ++k)
for (int beta = 0; beta < B.base.Nrap[k]; ++beta)
for (int b = 1; b <= B.chain.Str_L[k]; ++b) {
if (b == 1) ln_prod4 += re_ln_Fn_F_B_0[k][beta];
else if (b > 1) ln_prod4 += ln_Fn_F(B, k, beta, b - 1);
}
ln_prod4 -= B.base.Mdown * log(abs(sin(B.chain.anis)));
// Now proceed to build the Hm matrix
SQMat_CX Hm(0.0, A.base.Mdown);
int index_a = 0;
int index_b = 0;
complex<DP> sum1 = 0.0;
complex<DP> sum2 = 0.0;
complex<DP> prod_num = 0.0;
complex<DP> Fn_K_0_G_0 = 0.0;
complex<DP> Prod_powerN = 0.0;
complex<DP> Fn_K_1_G_2 = 0.0;
complex<DP> one_over_A_sinhlambda_sq_plus_sinzetaover2sq;
for (int j = 0; j < A.chain.Nstrings; ++j) {
for (int alpha = 0; alpha < A.base.Nrap[j]; ++alpha) {
for (int a = 1; a <= A.chain.Str_L[j]; ++a) {
for (int j = 0; j < A.chain.Nstrings; ++j) {
for (int alpha = 0; alpha < A.base.Nrap[j]; ++alpha) {
for (int a = 1; a <= A.chain.Str_L[j]; ++a) {
index_b = 0;
index_b = 0;
one_over_A_sinhlambda_sq_plus_sinzetaover2sq = 1.0/((sinh(A.lambda[j][alpha] + 0.5 * II * A.chain.anis * (A.chain.Str_L[j] + 1.0 - 2.0 * a)
+ 0.25 * II * PI * (1.0 - A.chain.par[j])))
* (sinh(A.lambda[j][alpha] + 0.5 * II * A.chain.anis * (A.chain.Str_L[j] + 1.0 - 2.0 * a)
+ 0.25 * II * PI * (1.0 - A.chain.par[j])))
+ pow(sin(0.5*A.chain.anis), 2.0));
one_over_A_sinhlambda_sq_plus_sinzetaover2sq =
1.0/((sinh(A.lambda[j][alpha] + 0.5 * II * A.chain.anis * (A.chain.Str_L[j] + 1.0 - 2.0 * a)
+ 0.25 * II * PI * (1.0 - A.chain.par[j])))
* (sinh(A.lambda[j][alpha] + 0.5 * II * A.chain.anis * (A.chain.Str_L[j] + 1.0 - 2.0 * a)
+ 0.25 * II * PI * (1.0 - A.chain.par[j])))
+ pow(sin(0.5*A.chain.anis), 2.0));
for (int k = 0; k < B.chain.Nstrings; ++k) {
for (int beta = 0; beta < B.base.Nrap[k]; ++beta) {
for (int b = 1; b <= B.chain.Str_L[k]; ++b) {
for (int k = 0; k < B.chain.Nstrings; ++k) {
for (int beta = 0; beta < B.base.Nrap[k]; ++beta) {
for (int b = 1; b <= B.chain.Str_L[k]; ++b) {
if (B.chain.Str_L[k] == 1) {
if (B.chain.Str_L[k] == 1) {
// use simplified code for one-string here: original form of Hm matrix
// use simplified code for one-string here: original form of Hm matrix
Fn_K_0_G_0 = Fn_K (A, j, alpha, a, B, k, beta, 0) *
exp(re_ln_Fn_G_0[k][beta] + II * im_ln_Fn_G_0[k][beta] - re_ln_Fn_F_B_0[k][beta] + logabssinzeta);
Fn_K_1_G_2 = Fn_K (A, j, alpha, a, B, k, beta, 1) *
exp(re_ln_Fn_G_2[k][beta] + II * im_ln_Fn_G_2[k][beta] - re_ln_Fn_F_B_0[k][beta] + logabssinzeta);
Fn_K_0_G_0 = Fn_K (A, j, alpha, a, B, k, beta, 0) *
exp(re_ln_Fn_G_0[k][beta] + II * im_ln_Fn_G_0[k][beta] - re_ln_Fn_F_B_0[k][beta] + logabssinzeta);
Fn_K_1_G_2 = Fn_K (A, j, alpha, a, B, k, beta, 1) *
exp(re_ln_Fn_G_2[k][beta] + II * im_ln_Fn_G_2[k][beta] - re_ln_Fn_F_B_0[k][beta] + logabssinzeta);
Prod_powerN = pow( B.chain.par[k] == 1 ?
(B.sinhlambda[k][beta] * B.chain.co_n_anis_over_2[1] + II * B.coshlambda[k][beta] * B.chain.si_n_anis_over_2[1])
/(B.sinhlambda[k][beta] * B.chain.co_n_anis_over_2[1] - II * B.coshlambda[k][beta] * B.chain.si_n_anis_over_2[1])
:
(B.coshlambda[k][beta] * B.chain.co_n_anis_over_2[1] + II * B.sinhlambda[k][beta] * B.chain.si_n_anis_over_2[1])
/(B.coshlambda[k][beta] * B.chain.co_n_anis_over_2[1] - II * B.sinhlambda[k][beta] * B.chain.si_n_anis_over_2[1])
, complex<DP> (B.chain.Nsites));
Prod_powerN = pow( B.chain.par[k] == 1 ?
(B.sinhlambda[k][beta] * B.chain.co_n_anis_over_2[1]
+ II * B.coshlambda[k][beta] * B.chain.si_n_anis_over_2[1])
/(B.sinhlambda[k][beta] * B.chain.co_n_anis_over_2[1]
- II * B.coshlambda[k][beta] * B.chain.si_n_anis_over_2[1])
:
(B.coshlambda[k][beta] * B.chain.co_n_anis_over_2[1]
+ II * B.sinhlambda[k][beta] * B.chain.si_n_anis_over_2[1])
/(B.coshlambda[k][beta] * B.chain.co_n_anis_over_2[1]
- II * B.sinhlambda[k][beta] * B.chain.si_n_anis_over_2[1])
, complex<DP> (B.chain.Nsites));
Hm[index_a][index_b] = Fn_K_0_G_0 - (1.0 - 2.0 * (B.base.Mdown % 2)) * // MODIF from XXZ
Prod_powerN * Fn_K_1_G_2;
Hm[index_a][index_b] = Fn_K_0_G_0 - (1.0 - 2.0 * (B.base.Mdown % 2)) * // MODIF from XXZ
Prod_powerN * Fn_K_1_G_2;
} // if (B.chain.Str_L == 1)
} // if (B.chain.Str_L == 1)
else {
else {
if (b <= B.chain.Str_L[k] - 1) Hm[index_a][index_b] = Fn_K(A, j, alpha, a, B, k, beta, b);
else if (b == B.chain.Str_L[k]) {
if (b <= B.chain.Str_L[k] - 1) Hm[index_a][index_b] = Fn_K(A, j, alpha, a, B, k, beta, b);
else if (b == B.chain.Str_L[k]) {
Vect_CX ln_FunctionF(B.chain.Str_L[k] + 2);
for (int i = 0; i < B.chain.Str_L[k] + 2; ++i) ln_FunctionF[i] = ln_Fn_F (B, k, beta, i);
Vect_CX ln_FunctionF(B.chain.Str_L[k] + 2);
for (int i = 0; i < B.chain.Str_L[k] + 2; ++i) ln_FunctionF[i] = ln_Fn_F (B, k, beta, i);
Vect_CX ln_FunctionG(B.chain.Str_L[k] + 2);
for (int i = 0; i < B.chain.Str_L[k] + 2; ++i) ln_FunctionG[i] = ln_Fn_G (A, B, k, beta, i);
Vect_CX ln_FunctionG(B.chain.Str_L[k] + 2);
for (int i = 0; i < B.chain.Str_L[k] + 2; ++i) ln_FunctionG[i] = ln_Fn_G (A, B, k, beta, i);
sum1 = 0.0;
sum1 = 0.0;
sum1 += Fn_K (A, j, alpha, a, B, k, beta, 0) * exp(ln_FunctionG[0] + ln_FunctionG[1] - ln_FunctionF[0] - ln_FunctionF[1]);
sum1 += Fn_K (A, j, alpha, a, B, k, beta, 0)
* exp(ln_FunctionG[0] + ln_FunctionG[1] - ln_FunctionF[0] - ln_FunctionF[1]);
sum1 += (1.0 - 2.0 * (B.base.Mdown % 2)) * // MODIF from XXZ
Fn_K (A, j, alpha, a, B, k, beta, B.chain.Str_L[k])
* exp(ln_FunctionG[B.chain.Str_L[k]] + ln_FunctionG[B.chain.Str_L[k] + 1]
- ln_FunctionF[B.chain.Str_L[k]] - ln_FunctionF[B.chain.Str_L[k] + 1]);
sum1 += (1.0 - 2.0 * (B.base.Mdown % 2)) * // MODIF from XXZ
Fn_K (A, j, alpha, a, B, k, beta, B.chain.Str_L[k])
* exp(ln_FunctionG[B.chain.Str_L[k]] + ln_FunctionG[B.chain.Str_L[k] + 1]
- ln_FunctionF[B.chain.Str_L[k]] - ln_FunctionF[B.chain.Str_L[k] + 1]);
for (int jsum = 1; jsum < B.chain.Str_L[k]; ++jsum)
for (int jsum = 1; jsum < B.chain.Str_L[k]; ++jsum)
sum1 -= Fn_L (A, j, alpha, a, B, k, beta, jsum) *
exp(ln_FunctionG[jsum] + ln_FunctionG[jsum + 1] - ln_FunctionF[jsum] - ln_FunctionF[jsum + 1]);
sum1 -= Fn_L (A, j, alpha, a, B, k, beta, jsum) *
exp(ln_FunctionG[jsum] + ln_FunctionG[jsum + 1] - ln_FunctionF[jsum] - ln_FunctionF[jsum + 1]);
/*
sum2 = 0.0;
prod_num = exp(II * im_ln_Fn_F_B_0[k][beta] + ln_FunctionF[1]
- ln_FunctionG[B.chain.Str_L[k]] + logabssinzeta);
for (int jsum = 1; jsum <= B.chain.Str_L[k]; ++jsum) sum2 += exp(ln_FunctionG[jsum] - ln_FunctionF[jsum]);
for (int jsum = 2; jsum <= B.chain.Str_L[k]; ++jsum)
prod_num *= exp(ln_FunctionG[jsum] - real(ln_Fn_F(B, k, beta, jsum - 1)) + logabssinzeta);
// include all string contributions F_B_0 in this term
*/
prod_num = exp(II * im_ln_Fn_F_B_0[k][beta] + ln_FunctionF[1] - ln_FunctionG[B.chain.Str_L[k]] + logabssinzeta);
Hm[index_a][index_b] = prod_num * sum1;
for (int jsum = 2; jsum <= B.chain.Str_L[k]; ++jsum)
prod_num *= exp(ln_FunctionG[jsum] - real(ln_Fn_F(B, k, beta, jsum - 1)) + logabssinzeta);
// include all string contributions F_B_0 in this term
} // else if (b == B.chain.Str_L[k])
} // else
Hm[index_a][index_b] = prod_num * sum1;
index_b++;
}}} // sums over k, beta, b
} // else if (b == B.chain.Str_L[k])
} // else
// now define the elements Hm[a][M]
index_b++;
}}} // sums over k, beta, b
Hm[index_a][B.base.Mdown] = one_over_A_sinhlambda_sq_plus_sinzetaover2sq;
// now define the elements Hm[a][M]
index_a++;
}}} // sums over j, alpha, a
Hm[index_a][B.base.Mdown] = one_over_A_sinhlambda_sq_plus_sinzetaover2sq;
complex<DP> ln_ME_sq = log(1.0 * A.chain.Nsites) + real(ln_prod1 - ln_prod2) - real(ln_prod3) + real(ln_prod4)
+ 2.0 * real(lndet_LU_CX_dstry(Hm)) + logabssinzeta - A.lnnorm - B.lnnorm;
index_a++;
}}} // sums over j, alpha, a
return(0.5 * ln_ME_sq); // Return ME, not MEsq
complex<DP> ln_ME_sq = log(1.0 * A.chain.Nsites) + real(ln_prod1 - ln_prod2) - real(ln_prod3) + real(ln_prod4)
+ 2.0 * real(lndet_LU_CX_dstry(Hm)) + logabssinzeta - A.lnnorm - B.lnnorm;
//return(ln_ME_sq);
return(0.5 * ln_ME_sq); // Return ME, not MEsq
}
}
} // namespace ABACUS

View File

@ -18,327 +18,324 @@ using namespace ABACUS;
namespace ABACUS {
inline complex<DP> ln_Fn_F (ODSLF_XXZ_Bethe_State& B, int k, int beta, int b)
{
complex<DP> ans = 0.0;
complex<DP> prod_temp = 1.0;
int counter = 0;
int arg = 0;
int absarg = 0;
int par_comb_1, par_comb_2;
inline complex<DP> ln_Fn_F (ODSLF_XXZ_Bethe_State& B, int k, int beta, int b)
{
complex<DP> ans = 0.0;
complex<DP> prod_temp = 1.0;
int counter = 0;
int arg = 0;
int absarg = 0;
int par_comb_1, par_comb_2;
for (int j = 0; j < B.chain.Nstrings; ++j) {
for (int j = 0; j < B.chain.Nstrings; ++j) {
par_comb_1 = B.chain.par[j] == B.chain.par[k] ? 1 : 0;
par_comb_2 = B.chain.par[k] == B.chain.par[j] ? 0 : B.chain.par[k];
par_comb_1 = B.chain.par[j] == B.chain.par[k] ? 1 : 0;
par_comb_2 = B.chain.par[k] == B.chain.par[j] ? 0 : B.chain.par[k];
for (int alpha = 0; alpha < B.base.Nrap[j]; ++alpha) {
for (int alpha = 0; alpha < B.base.Nrap[j]; ++alpha) {
for (int a = 1; a <= B.chain.Str_L[j]; ++a) {
for (int a = 1; a <= B.chain.Str_L[j]; ++a) {
if (!((j == k) && (alpha == beta) && (a == b))) {
if (!((j == k) && (alpha == beta) && (a == b))) {
arg = B.chain.Str_L[j] - B.chain.Str_L[k] - 2 * (a - b);
absarg = abs(arg);
/*
prod_temp *= 0.5 *
((B.sinhlambda[j][alpha] * B.coshlambda[k][beta] - B.coshlambda[j][alpha] * B.sinhlambda[k][beta])
* (B.chain.co_n_anis_over_2[absarg] * (1.0 + B.chain.par[j] * B.chain.par[k])
- sgn_int(arg) * B.chain.si_n_anis_over_2[absarg] * (B.chain.par[k] - B.chain.par[j]))
+ II * (B.coshlambda[j][alpha] * B.coshlambda[k][beta] - B.sinhlambda[j][alpha] * B.sinhlambda[k][beta])
* (sgn_int(arg)
* B.chain.si_n_anis_over_2[absarg] * (1.0 + B.chain.par[j] * B.chain.par[k])
+ B.chain.co_n_anis_over_2[absarg] * (B.chain.par[k] - B.chain.par[j])) );
*/
prod_temp *= ((B.sinhlambda[j][alpha] * B.coshlambda[k][beta] - B.coshlambda[j][alpha] * B.sinhlambda[k][beta])
* (B.chain.co_n_anis_over_2[absarg] * par_comb_1 - sgn_int(arg) * B.chain.si_n_anis_over_2[absarg] * par_comb_2)
+ II * (B.coshlambda[j][alpha] * B.coshlambda[k][beta] - B.sinhlambda[j][alpha] * B.sinhlambda[k][beta])
* (sgn_int(arg) * B.chain.si_n_anis_over_2[absarg] * par_comb_1 + B.chain.co_n_anis_over_2[absarg] * par_comb_2));
arg = B.chain.Str_L[j] - B.chain.Str_L[k] - 2 * (a - b);
absarg = abs(arg);
prod_temp *= ((B.sinhlambda[j][alpha] * B.coshlambda[k][beta]
- B.coshlambda[j][alpha] * B.sinhlambda[k][beta])
* (B.chain.co_n_anis_over_2[absarg] * par_comb_1
- sgn_int(arg) * B.chain.si_n_anis_over_2[absarg] * par_comb_2)
+ II * (B.coshlambda[j][alpha] * B.coshlambda[k][beta]
- B.sinhlambda[j][alpha] * B.sinhlambda[k][beta])
* (sgn_int(arg) * B.chain.si_n_anis_over_2[absarg] * par_comb_1
+ B.chain.co_n_anis_over_2[absarg] * par_comb_2));
}
}
if (counter++ > 100) { // we do at most 100 products before taking a log
ans += log(prod_temp);
prod_temp = 1.0;
counter = 0;
}
if (counter++ > 100) { // we do at most 100 products before taking a log
ans += log(prod_temp);
prod_temp = 1.0;
counter = 0;
}
}}}
}}}
return(ans + log(prod_temp));
}
inline complex<DP> ln_Fn_G (ODSLF_XXZ_Bethe_State& A, ODSLF_XXZ_Bethe_State& B, int k, int beta, int b)
{
complex<DP> ans = 0.0;
complex<DP> prod_temp = 1.0;
int counter = 0;
int arg = 0;
int absarg = 0;
int par_comb_1, par_comb_2;
for (int j = 0; j < A.chain.Nstrings; ++j) {
par_comb_1 = A.chain.par[j] == B.chain.par[k] ? 1 : 0;
par_comb_2 = B.chain.par[k] == A.chain.par[j] ? 0 : B.chain.par[k];
for (int alpha = 0; alpha < A.base.Nrap[j]; ++alpha) {
for (int a = 1; a <= A.chain.Str_L[j]; ++a) {
arg = A.chain.Str_L[j] - B.chain.Str_L[k] - 2 * (a - b);
absarg = abs(arg);
/*
prod_temp *= 0.5 *
((A.sinhlambda[j][alpha] * B.coshlambda[k][beta] - A.coshlambda[j][alpha] * B.sinhlambda[k][beta])
* (A.chain.co_n_anis_over_2[absarg] * (1.0 + A.chain.par[j] * B.chain.par[k])
- sgn_int(arg) * A.chain.si_n_anis_over_2[absarg] * (B.chain.par[k] - A.chain.par[j]))
+ II * (A.coshlambda[j][alpha] * B.coshlambda[k][beta] - A.sinhlambda[j][alpha] * B.sinhlambda[k][beta])
* (sgn_int(arg) * A.chain.si_n_anis_over_2[absarg] * (1.0 + A.chain.par[j] * B.chain.par[k])
+ A.chain.co_n_anis_over_2[absarg] * (B.chain.par[k] - A.chain.par[j])) );
*/
prod_temp *= ((A.sinhlambda[j][alpha] * B.coshlambda[k][beta] - A.coshlambda[j][alpha] * B.sinhlambda[k][beta])
* (A.chain.co_n_anis_over_2[absarg] * par_comb_1 - sgn_int(arg) * A.chain.si_n_anis_over_2[absarg] * par_comb_2)
+ II * (A.coshlambda[j][alpha] * B.coshlambda[k][beta] - A.sinhlambda[j][alpha] * B.sinhlambda[k][beta])
* (sgn_int(arg) * A.chain.si_n_anis_over_2[absarg] * par_comb_1 + A.chain.co_n_anis_over_2[absarg] * par_comb_2));
if (counter++ > 100) { // we do at most 100 products before taking a log
ans += log(prod_temp);
prod_temp = 1.0;
counter = 0;
}
}}}
return(ans + log(prod_temp));
}
inline complex<DP> Fn_K (ODSLF_XXZ_Bethe_State& A, int j, int alpha, int a, ODSLF_XXZ_Bethe_State& B, int k, int beta, int b)
{
int arg1 = A.chain.Str_L[j] - B.chain.Str_L[k] - 2 * (a - b);
int absarg1 = abs(arg1);
int arg2 = arg1 + 2;
int absarg2 = abs(arg2);
return(4.0/(
((A.sinhlambda[j][alpha] * B.coshlambda[k][beta] - A.coshlambda[j][alpha] * B.sinhlambda[k][beta])
* (A.chain.co_n_anis_over_2[absarg1] * (1.0 + A.chain.par[j] * B.chain.par[k])
- sgn_int(arg1) * A.chain.si_n_anis_over_2[absarg1] * (B.chain.par[k] - A.chain.par[j]))
+ II * (A.coshlambda[j][alpha] * B.coshlambda[k][beta] - A.sinhlambda[j][alpha] * B.sinhlambda[k][beta])
* (sgn_int(arg1) * A.chain.si_n_anis_over_2[absarg1] * (1.0 + A.chain.par[j] * B.chain.par[k])
+ A.chain.co_n_anis_over_2[absarg1] * (B.chain.par[k] - A.chain.par[j])) )
*
((A.sinhlambda[j][alpha] * B.coshlambda[k][beta] - A.coshlambda[j][alpha] * B.sinhlambda[k][beta])
* (A.chain.co_n_anis_over_2[absarg2] * (1.0 + A.chain.par[j] * B.chain.par[k])
- sgn_int(arg2) * A.chain.si_n_anis_over_2[absarg2] * (B.chain.par[k] - A.chain.par[j]))
+ II * (A.coshlambda[j][alpha] * B.coshlambda[k][beta] - A.sinhlambda[j][alpha] * B.sinhlambda[k][beta])
* (sgn_int(arg2) * A.chain.si_n_anis_over_2[absarg2] * (1.0 + A.chain.par[j] * B.chain.par[k])
+ A.chain.co_n_anis_over_2[absarg2] * (B.chain.par[k] - A.chain.par[j])) )
));
}
inline complex<DP> Fn_L (ODSLF_XXZ_Bethe_State& A, int j, int alpha, int a, ODSLF_XXZ_Bethe_State& B, int k, int beta, int b)
{
return (sinh(2.0 * (A.lambda[j][alpha] - B.lambda[k][beta]
+ 0.5 * II * B.chain.anis * (A.chain.Str_L[j] - B.chain.Str_L[k] - 2.0 * (a - b - 0.5))
+ 0.25 * II * PI * complex<DP>(-A.chain.par[j] + B.chain.par[k])))
* pow(Fn_K (A, j, alpha, a, B, k, beta, b), 2.0));
}
complex<DP> ln_Sz_ME (ODSLF_XXZ_Bethe_State& A, ODSLF_XXZ_Bethe_State& B)
{
// This function returns the natural log of the S^z operator matrix element.
// The A and B states can contain strings.
// Check that the two states refer to the same XXZ_Chain
if (A.chain != B.chain) ABACUSerror("Incompatible ODSLF_XXZ_Chains in Sz matrix element.");
// Check that A and B are compatible: same Mdown
if (A.base.Mdown != B.base.Mdown) ABACUSerror("Incompatible Mdown between the two states in Sz matrix element!");
// Compute the sinh and cosh of rapidities
A.Compute_sinhlambda();
A.Compute_coshlambda();
B.Compute_sinhlambda();
B.Compute_coshlambda();
// Some convenient arrays
ODSLF_Lambda re_ln_Fn_F_B_0(B.chain, B.base);
ODSLF_Lambda im_ln_Fn_F_B_0(B.chain, B.base);
ODSLF_Lambda re_ln_Fn_G_0(B.chain, B.base);
ODSLF_Lambda im_ln_Fn_G_0(B.chain, B.base);
ODSLF_Lambda re_ln_Fn_G_2(B.chain, B.base);
ODSLF_Lambda im_ln_Fn_G_2(B.chain, B.base);
complex<DP> ln_prod1 = 0.0;
complex<DP> ln_prod2 = 0.0;
complex<DP> ln_prod3 = 0.0;
complex<DP> ln_prod4 = 0.0;
for (int i = 0; i < A.chain.Nstrings; ++i)
for (int alpha = 0; alpha < A.base.Nrap[i]; ++alpha)
for (int a = 1; a <= A.chain.Str_L[i]; ++a)
ln_prod1 += log(norm(sinh(A.lambda[i][alpha] + 0.5 * II * A.chain.anis * (A.chain.Str_L[i] + 1.0 - 2.0 * a - 1.0)
+ 0.25 * II * PI * (1.0 - A.chain.par[i]))));
for (int i = 0; i < B.chain.Nstrings; ++i)
for (int alpha = 0; alpha < B.base.Nrap[i]; ++alpha)
for (int a = 1; a <= B.chain.Str_L[i]; ++a)
if (norm(sinh(B.lambda[i][alpha] + 0.5 * II * B.chain.anis * (B.chain.Str_L[i] + 1.0 - 2.0 * a - 1.0)
+ 0.25 * II * PI * (1.0 - B.chain.par[i]))) > 100.0 * MACHINE_EPS_SQ)
ln_prod2 += log(norm(sinh(B.lambda[i][alpha] + 0.5 * II * B.chain.anis * (B.chain.Str_L[i] + 1.0 - 2.0 * a - 1.0)
+ 0.25 * II * PI * (1.0 - B.chain.par[i]))));
// Define the F ones earlier...
for (int j = 0; j < B.chain.Nstrings; ++j) {
for (int alpha = 0; alpha < B.base.Nrap[j]; ++alpha) {
re_ln_Fn_F_B_0[j][alpha] = real(ln_Fn_F(B, j, alpha, 0));
im_ln_Fn_F_B_0[j][alpha] = imag(ln_Fn_F(B, j, alpha, 0));
re_ln_Fn_G_0[j][alpha] = real(ln_Fn_G(A, B, j, alpha, 0));
im_ln_Fn_G_0[j][alpha] = imag(ln_Fn_G(A, B, j, alpha, 0));
re_ln_Fn_G_2[j][alpha] = real(ln_Fn_G(A, B, j, alpha, 2));
im_ln_Fn_G_2[j][alpha] = imag(ln_Fn_G(A, B, j, alpha, 2));
}
return(ans + log(prod_temp));
}
DP logabssinzeta = log(abs(sin(A.chain.anis)));
inline complex<DP> ln_Fn_G (ODSLF_XXZ_Bethe_State& A, ODSLF_XXZ_Bethe_State& B, int k, int beta, int b)
{
complex<DP> ans = 0.0;
complex<DP> prod_temp = 1.0;
int counter = 0;
int arg = 0;
int absarg = 0;
int par_comb_1, par_comb_2;
// Define regularized products in prefactors
for (int j = 0; j < A.chain.Nstrings; ++j) {
for (int j = 0; j < A.chain.Nstrings; ++j)
for (int alpha = 0; alpha < A.base.Nrap[j]; ++alpha)
for (int a = 1; a <= A.chain.Str_L[j]; ++a) {
ln_prod3 += ln_Fn_F (A, j, alpha, a - 1);
par_comb_1 = A.chain.par[j] == B.chain.par[k] ? 1 : 0;
par_comb_2 = B.chain.par[k] == A.chain.par[j] ? 0 : B.chain.par[k];
for (int alpha = 0; alpha < A.base.Nrap[j]; ++alpha) {
for (int a = 1; a <= A.chain.Str_L[j]; ++a) {
arg = A.chain.Str_L[j] - B.chain.Str_L[k] - 2 * (a - b);
absarg = abs(arg);
prod_temp *= ((A.sinhlambda[j][alpha] * B.coshlambda[k][beta]
- A.coshlambda[j][alpha] * B.sinhlambda[k][beta])
* (A.chain.co_n_anis_over_2[absarg] * par_comb_1
- sgn_int(arg) * A.chain.si_n_anis_over_2[absarg] * par_comb_2)
+ II * (A.coshlambda[j][alpha] * B.coshlambda[k][beta]
- A.sinhlambda[j][alpha] * B.sinhlambda[k][beta])
* (sgn_int(arg) * A.chain.si_n_anis_over_2[absarg] * par_comb_1
+ A.chain.co_n_anis_over_2[absarg] * par_comb_2));
if (counter++ > 100) { // we do at most 100 products before taking a log
ans += log(prod_temp);
prod_temp = 1.0;
counter = 0;
}
}}}
return(ans + log(prod_temp));
}
inline complex<DP> Fn_K (ODSLF_XXZ_Bethe_State& A, int j, int alpha, int a,
ODSLF_XXZ_Bethe_State& B, int k, int beta, int b)
{
int arg1 = A.chain.Str_L[j] - B.chain.Str_L[k] - 2 * (a - b);
int absarg1 = abs(arg1);
int arg2 = arg1 + 2;
int absarg2 = abs(arg2);
return(4.0/(
((A.sinhlambda[j][alpha] * B.coshlambda[k][beta] - A.coshlambda[j][alpha] * B.sinhlambda[k][beta])
* (A.chain.co_n_anis_over_2[absarg1] * (1.0 + A.chain.par[j] * B.chain.par[k])
- sgn_int(arg1) * A.chain.si_n_anis_over_2[absarg1] * (B.chain.par[k] - A.chain.par[j]))
+ II * (A.coshlambda[j][alpha] * B.coshlambda[k][beta] - A.sinhlambda[j][alpha] * B.sinhlambda[k][beta])
* (sgn_int(arg1) * A.chain.si_n_anis_over_2[absarg1] * (1.0 + A.chain.par[j] * B.chain.par[k])
+ A.chain.co_n_anis_over_2[absarg1] * (B.chain.par[k] - A.chain.par[j])) )
*
((A.sinhlambda[j][alpha] * B.coshlambda[k][beta] - A.coshlambda[j][alpha] * B.sinhlambda[k][beta])
* (A.chain.co_n_anis_over_2[absarg2] * (1.0 + A.chain.par[j] * B.chain.par[k])
- sgn_int(arg2) * A.chain.si_n_anis_over_2[absarg2] * (B.chain.par[k] - A.chain.par[j]))
+ II * (A.coshlambda[j][alpha] * B.coshlambda[k][beta] - A.sinhlambda[j][alpha] * B.sinhlambda[k][beta])
* (sgn_int(arg2) * A.chain.si_n_anis_over_2[absarg2] * (1.0 + A.chain.par[j] * B.chain.par[k])
+ A.chain.co_n_anis_over_2[absarg2] * (B.chain.par[k] - A.chain.par[j])) )
));
}
inline complex<DP> Fn_L (ODSLF_XXZ_Bethe_State& A, int j, int alpha, int a,
ODSLF_XXZ_Bethe_State& B, int k, int beta, int b)
{
return (sinh(2.0 * (A.lambda[j][alpha] - B.lambda[k][beta]
+ 0.5 * II * B.chain.anis * (A.chain.Str_L[j] - B.chain.Str_L[k] - 2.0 * (a - b - 0.5))
+ 0.25 * II * PI * complex<DP>(-A.chain.par[j] + B.chain.par[k])))
* pow(Fn_K (A, j, alpha, a, B, k, beta, b), 2.0));
}
complex<DP> ln_Sz_ME (ODSLF_XXZ_Bethe_State& A, ODSLF_XXZ_Bethe_State& B)
{
// This function returns the natural log of the S^z operator matrix element.
// The A and B states can contain strings.
// Check that the two states refer to the same XXZ_Chain
if (A.chain != B.chain)
ABACUSerror("Incompatible ODSLF_XXZ_Chains in Sz matrix element.");
// Check that A and B are compatible: same Mdown
if (A.base.Mdown != B.base.Mdown)
ABACUSerror("Incompatible Mdown between the two states in Sz matrix element!");
// Compute the sinh and cosh of rapidities
A.Compute_sinhlambda();
A.Compute_coshlambda();
B.Compute_sinhlambda();
B.Compute_coshlambda();
// Some convenient arrays
ODSLF_Lambda re_ln_Fn_F_B_0(B.chain, B.base);
ODSLF_Lambda im_ln_Fn_F_B_0(B.chain, B.base);
ODSLF_Lambda re_ln_Fn_G_0(B.chain, B.base);
ODSLF_Lambda im_ln_Fn_G_0(B.chain, B.base);
ODSLF_Lambda re_ln_Fn_G_2(B.chain, B.base);
ODSLF_Lambda im_ln_Fn_G_2(B.chain, B.base);
complex<DP> ln_prod1 = 0.0;
complex<DP> ln_prod2 = 0.0;
complex<DP> ln_prod3 = 0.0;
complex<DP> ln_prod4 = 0.0;
for (int i = 0; i < A.chain.Nstrings; ++i)
for (int alpha = 0; alpha < A.base.Nrap[i]; ++alpha)
for (int a = 1; a <= A.chain.Str_L[i]; ++a)
ln_prod1 += log(norm(sinh(A.lambda[i][alpha] + 0.5 * II * A.chain.anis * (A.chain.Str_L[i] + 1.0 - 2.0 * a - 1.0)
+ 0.25 * II * PI * (1.0 - A.chain.par[i]))));
for (int i = 0; i < B.chain.Nstrings; ++i)
for (int alpha = 0; alpha < B.base.Nrap[i]; ++alpha)
for (int a = 1; a <= B.chain.Str_L[i]; ++a)
if (norm(sinh(B.lambda[i][alpha] + 0.5 * II * B.chain.anis * (B.chain.Str_L[i] + 1.0 - 2.0 * a - 1.0)
+ 0.25 * II * PI * (1.0 - B.chain.par[i]))) > 100.0 * MACHINE_EPS_SQ)
ln_prod2 += log(norm(sinh(B.lambda[i][alpha] + 0.5 * II * B.chain.anis * (B.chain.Str_L[i] + 1.0 - 2.0 * a - 1.0)
+ 0.25 * II * PI * (1.0 - B.chain.par[i]))));
// Define the F ones earlier...
for (int j = 0; j < B.chain.Nstrings; ++j) {
for (int alpha = 0; alpha < B.base.Nrap[j]; ++alpha) {
re_ln_Fn_F_B_0[j][alpha] = real(ln_Fn_F(B, j, alpha, 0));
im_ln_Fn_F_B_0[j][alpha] = imag(ln_Fn_F(B, j, alpha, 0));
re_ln_Fn_G_0[j][alpha] = real(ln_Fn_G(A, B, j, alpha, 0));
im_ln_Fn_G_0[j][alpha] = imag(ln_Fn_G(A, B, j, alpha, 0));
re_ln_Fn_G_2[j][alpha] = real(ln_Fn_G(A, B, j, alpha, 2));
im_ln_Fn_G_2[j][alpha] = imag(ln_Fn_G(A, B, j, alpha, 2));
}
}
ln_prod3 -= A.base.Mdown * log(abs(sin(A.chain.anis)));
DP logabssinzeta = log(abs(sin(A.chain.anis)));
for (int k = 0; k < B.chain.Nstrings; ++k)
for (int beta = 0; beta < B.base.Nrap[k]; ++beta)
for (int b = 1; b <= B.chain.Str_L[k]; ++b) {
if (b == 1) ln_prod4 += re_ln_Fn_F_B_0[k][beta];
else if (b > 1) ln_prod4 += ln_Fn_F(B, k, beta, b - 1);
}
// Define regularized products in prefactors
ln_prod4 -= B.base.Mdown * log(abs(sin(B.chain.anis)));
for (int j = 0; j < A.chain.Nstrings; ++j)
for (int alpha = 0; alpha < A.base.Nrap[j]; ++alpha)
for (int a = 1; a <= A.chain.Str_L[j]; ++a) {
ln_prod3 += ln_Fn_F (A, j, alpha, a - 1);
}
// Now proceed to build the Hm2P matrix
ln_prod3 -= A.base.Mdown * log(abs(sin(A.chain.anis)));
SQMat_CX Hm2P(0.0, A.base.Mdown);
for (int k = 0; k < B.chain.Nstrings; ++k)
for (int beta = 0; beta < B.base.Nrap[k]; ++beta)
for (int b = 1; b <= B.chain.Str_L[k]; ++b) {
if (b == 1) ln_prod4 += re_ln_Fn_F_B_0[k][beta];
else if (b > 1) ln_prod4 += ln_Fn_F(B, k, beta, b - 1);
}
int index_a = 0;
int index_b = 0;
ln_prod4 -= B.base.Mdown * log(abs(sin(B.chain.anis)));
complex<DP> sum1 = 0.0;
complex<DP> sum2 = 0.0;
complex<DP> prod_num = 0.0;
complex<DP> Fn_K_0_G_0 = 0.0;
complex<DP> Prod_powerN = 0.0;
complex<DP> Fn_K_1_G_2 = 0.0;
complex<DP> two_over_A_sinhlambda_sq_plus_sinzetaover2sq;
// Now proceed to build the Hm2P matrix
SQMat_CX Hm2P(0.0, A.base.Mdown);
int index_a = 0;
int index_b = 0;
complex<DP> sum1 = 0.0;
complex<DP> sum2 = 0.0;
complex<DP> prod_num = 0.0;
complex<DP> Fn_K_0_G_0 = 0.0;
complex<DP> Prod_powerN = 0.0;
complex<DP> Fn_K_1_G_2 = 0.0;
complex<DP> two_over_A_sinhlambda_sq_plus_sinzetaover2sq;
for (int j = 0; j < A.chain.Nstrings; ++j) {
for (int alpha = 0; alpha < A.base.Nrap[j]; ++alpha) {
for (int a = 1; a <= A.chain.Str_L[j]; ++a) {
for (int j = 0; j < A.chain.Nstrings; ++j) {
for (int alpha = 0; alpha < A.base.Nrap[j]; ++alpha) {
for (int a = 1; a <= A.chain.Str_L[j]; ++a) {
index_b = 0;
index_b = 0;
two_over_A_sinhlambda_sq_plus_sinzetaover2sq = 2.0/((sinh(A.lambda[j][alpha] + 0.5 * II * A.chain.anis * (A.chain.Str_L[j] + 1.0 - 2.0 * a)
+ 0.25 * II * PI * (1.0 - A.chain.par[j])))
* (sinh(A.lambda[j][alpha] + 0.5 * II * A.chain.anis * (A.chain.Str_L[j] + 1.0 - 2.0 * a)
+ 0.25 * II * PI * (1.0 - A.chain.par[j])))
+ pow(sin(0.5*A.chain.anis), 2.0));
two_over_A_sinhlambda_sq_plus_sinzetaover2sq =
2.0/((sinh(A.lambda[j][alpha] + 0.5 * II * A.chain.anis * (A.chain.Str_L[j] + 1.0 - 2.0 * a)
+ 0.25 * II * PI * (1.0 - A.chain.par[j])))
* (sinh(A.lambda[j][alpha] + 0.5 * II * A.chain.anis * (A.chain.Str_L[j] + 1.0 - 2.0 * a)
+ 0.25 * II * PI * (1.0 - A.chain.par[j])))
+ pow(sin(0.5*A.chain.anis), 2.0));
for (int k = 0; k < B.chain.Nstrings; ++k) {
for (int beta = 0; beta < B.base.Nrap[k]; ++beta) {
for (int b = 1; b <= B.chain.Str_L[k]; ++b) {
for (int k = 0; k < B.chain.Nstrings; ++k) {
for (int beta = 0; beta < B.base.Nrap[k]; ++beta) {
for (int b = 1; b <= B.chain.Str_L[k]; ++b) {
if (B.chain.Str_L[k] == 1) {
if (B.chain.Str_L[k] == 1) {
// use simplified code for one-string here: original form of Hm2P matrix
// use simplified code for one-string here: original form of Hm2P matrix
Fn_K_0_G_0 = Fn_K (A, j, alpha, a, B, k, beta, 0) *
exp(re_ln_Fn_G_0[k][beta] + II * im_ln_Fn_G_0[k][beta] - re_ln_Fn_F_B_0[k][beta] + logabssinzeta);
Fn_K_1_G_2 = Fn_K (A, j, alpha, a, B, k, beta, 1) *
exp(re_ln_Fn_G_2[k][beta] + II * im_ln_Fn_G_2[k][beta] - re_ln_Fn_F_B_0[k][beta] + logabssinzeta);
Fn_K_0_G_0 = Fn_K (A, j, alpha, a, B, k, beta, 0) *
exp(re_ln_Fn_G_0[k][beta] + II * im_ln_Fn_G_0[k][beta] - re_ln_Fn_F_B_0[k][beta] + logabssinzeta);
Fn_K_1_G_2 = Fn_K (A, j, alpha, a, B, k, beta, 1) *
exp(re_ln_Fn_G_2[k][beta] + II * im_ln_Fn_G_2[k][beta] - re_ln_Fn_F_B_0[k][beta] + logabssinzeta);
Prod_powerN = pow( B.chain.par[k] == 1 ?
(B.sinhlambda[k][beta] * B.chain.co_n_anis_over_2[1] + II * B.coshlambda[k][beta] * B.chain.si_n_anis_over_2[1])
/(B.sinhlambda[k][beta] * B.chain.co_n_anis_over_2[1] - II * B.coshlambda[k][beta] * B.chain.si_n_anis_over_2[1])
:
(B.coshlambda[k][beta] * B.chain.co_n_anis_over_2[1] + II * B.sinhlambda[k][beta] * B.chain.si_n_anis_over_2[1])
/(B.coshlambda[k][beta] * B.chain.co_n_anis_over_2[1] - II * B.sinhlambda[k][beta] * B.chain.si_n_anis_over_2[1])
, complex<DP> (B.chain.Nsites));
Prod_powerN = pow( B.chain.par[k] == 1 ?
(B.sinhlambda[k][beta] * B.chain.co_n_anis_over_2[1]
+ II * B.coshlambda[k][beta] * B.chain.si_n_anis_over_2[1])
/(B.sinhlambda[k][beta] * B.chain.co_n_anis_over_2[1]
- II * B.coshlambda[k][beta] * B.chain.si_n_anis_over_2[1])
:
(B.coshlambda[k][beta] * B.chain.co_n_anis_over_2[1]
+ II * B.sinhlambda[k][beta] * B.chain.si_n_anis_over_2[1])
/(B.coshlambda[k][beta] * B.chain.co_n_anis_over_2[1]
- II * B.sinhlambda[k][beta] * B.chain.si_n_anis_over_2[1])
, complex<DP> (B.chain.Nsites));
Hm2P[index_a][index_b] = Fn_K_0_G_0 - (-1.0 + 2.0 * (B.base.Mdown % 2)) * // MODIF from XXZ
Prod_powerN * Fn_K_1_G_2 - two_over_A_sinhlambda_sq_plus_sinzetaover2sq
Hm2P[index_a][index_b] = Fn_K_0_G_0 - (-1.0 + 2.0 * (B.base.Mdown % 2)) * // MODIF from XXZ
Prod_powerN * Fn_K_1_G_2 - two_over_A_sinhlambda_sq_plus_sinzetaover2sq
* exp(II*im_ln_Fn_F_B_0[k][beta] + logabssinzeta);
}
}
else {
else {
if (b <= B.chain.Str_L[k] - 1) Hm2P[index_a][index_b] = Fn_K(A, j, alpha, a, B, k, beta, b);
else if (b == B.chain.Str_L[k]) {
if (b <= B.chain.Str_L[k] - 1) Hm2P[index_a][index_b] = Fn_K(A, j, alpha, a, B, k, beta, b);
else if (b == B.chain.Str_L[k]) {
Vect_CX ln_FunctionF(B.chain.Str_L[k] + 2);
for (int i = 0; i < B.chain.Str_L[k] + 2; ++i) ln_FunctionF[i] = ln_Fn_F (B, k, beta, i);
Vect_CX ln_FunctionF(B.chain.Str_L[k] + 2);
for (int i = 0; i < B.chain.Str_L[k] + 2; ++i) ln_FunctionF[i] = ln_Fn_F (B, k, beta, i);
Vect_CX ln_FunctionG(B.chain.Str_L[k] + 2);
for (int i = 0; i < B.chain.Str_L[k] + 2; ++i) ln_FunctionG[i] = ln_Fn_G (A, B, k, beta, i);
Vect_CX ln_FunctionG(B.chain.Str_L[k] + 2);
for (int i = 0; i < B.chain.Str_L[k] + 2; ++i) ln_FunctionG[i] = ln_Fn_G (A, B, k, beta, i);
sum1 = 0.0;
sum1 = 0.0;
sum1 += Fn_K (A, j, alpha, a, B, k, beta, 0) * exp(ln_FunctionG[0] + ln_FunctionG[1] - ln_FunctionF[0] - ln_FunctionF[1]);
sum1 += Fn_K (A, j, alpha, a, B, k, beta, 0)
* exp(ln_FunctionG[0] + ln_FunctionG[1] - ln_FunctionF[0] - ln_FunctionF[1]);
sum1 += (-1.0 + 2.0 * (B.base.Mdown % 2)) * // MODIF from XXZ
Fn_K (A, j, alpha, a, B, k, beta, B.chain.Str_L[k])
* exp(ln_FunctionG[B.chain.Str_L[k]] + ln_FunctionG[B.chain.Str_L[k] + 1]
- ln_FunctionF[B.chain.Str_L[k]] - ln_FunctionF[B.chain.Str_L[k] + 1]);
sum1 += (-1.0 + 2.0 * (B.base.Mdown % 2)) * // MODIF from XXZ
Fn_K (A, j, alpha, a, B, k, beta, B.chain.Str_L[k])
* exp(ln_FunctionG[B.chain.Str_L[k]] + ln_FunctionG[B.chain.Str_L[k] + 1]
- ln_FunctionF[B.chain.Str_L[k]] - ln_FunctionF[B.chain.Str_L[k] + 1]);
for (int jsum = 1; jsum < B.chain.Str_L[k]; ++jsum)
for (int jsum = 1; jsum < B.chain.Str_L[k]; ++jsum)
sum1 -= Fn_L (A, j, alpha, a, B, k, beta, jsum) *
exp(ln_FunctionG[jsum] + ln_FunctionG[jsum + 1] - ln_FunctionF[jsum] - ln_FunctionF[jsum + 1]);
sum1 -= Fn_L (A, j, alpha, a, B, k, beta, jsum) *
exp(ln_FunctionG[jsum] + ln_FunctionG[jsum + 1] - ln_FunctionF[jsum] - ln_FunctionF[jsum + 1]);
sum2 = 0.0;
sum2 = 0.0;
for (int jsum = 1; jsum <= B.chain.Str_L[k]; ++jsum) sum2 += exp(ln_FunctionG[jsum] - ln_FunctionF[jsum]);
for (int jsum = 1; jsum <= B.chain.Str_L[k]; ++jsum)
sum2 += exp(ln_FunctionG[jsum] - ln_FunctionF[jsum]);
prod_num = exp(II * im_ln_Fn_F_B_0[k][beta] + ln_FunctionF[1] - ln_FunctionG[B.chain.Str_L[k]] + logabssinzeta);
prod_num = exp(II * im_ln_Fn_F_B_0[k][beta] + ln_FunctionF[1]
- ln_FunctionG[B.chain.Str_L[k]] + logabssinzeta);
for (int jsum = 2; jsum <= B.chain.Str_L[k]; ++jsum)
prod_num *= exp(ln_FunctionG[jsum] - real(ln_FunctionF[jsum - 1]) + logabssinzeta);
// include all string contributions F_B_0 in this term
for (int jsum = 2; jsum <= B.chain.Str_L[k]; ++jsum)
prod_num *= exp(ln_FunctionG[jsum] - real(ln_FunctionF[jsum - 1]) + logabssinzeta);
// include all string contributions F_B_0 in this term
Hm2P[index_a][index_b] = prod_num * (sum1 - sum2 * two_over_A_sinhlambda_sq_plus_sinzetaover2sq);
Hm2P[index_a][index_b] = prod_num * (sum1 - sum2 * two_over_A_sinhlambda_sq_plus_sinzetaover2sq);
} // else if (b == B.chain.Str_L[k])
} // else
} // else if (b == B.chain.Str_L[k])
} // else
index_b++;
}}} // sums over k, beta, b
index_a++;
}}} // sums over j, alpha, a
index_b++;
}}} // sums over k, beta, b
index_a++;
}}} // sums over j, alpha, a
DP re_ln_det = real(lndet_LU_CX_dstry(Hm2P));
DP re_ln_det = real(lndet_LU_CX_dstry(Hm2P));
complex<DP> ln_ME_sq = log(0.25 * A.chain.Nsites) + real(ln_prod1 - ln_prod2) - real(ln_prod3) + real(ln_prod4)
+ 2.0 * /*real(lndet_LU_CX_dstry(Hm2P))*/ re_ln_det - A.lnnorm - B.lnnorm;
complex<DP> ln_ME_sq = log(0.25 * A.chain.Nsites) + real(ln_prod1 - ln_prod2) - real(ln_prod3) + real(ln_prod4)
+ 2.0 * re_ln_det - A.lnnorm - B.lnnorm;
//cout << endl << ln_prod1 << "\t" << ln_prod2 << "\t" << ln_prod3 << "\t" << ln_prod4 << "\t" << A.lnnorm << "\t" << B.lnnorm
// << "\t" << re_ln_det << "\t" << ln_ME_sq << endl;
return(0.5 * ln_ME_sq); // Return ME, not MEsq
//return(ln_ME_sq);
return(0.5 * ln_ME_sq); // Return ME, not MEsq
}
}
} // namespace ABACUS

View File

@ -31,21 +31,20 @@ namespace ABACUS {
//DP bquad = -1.0/g_int - sumoneovereps[j];
//DP cquad = sumSovereps[j];
/*
DP discr = 0.0;
bool retval = false;
//if ((discr = bquad * bquad - 4.0 * cquad) >= 0.0) {
if ((discr = (1.0/g_int + sumoneovereps[j]) * (1.0/g_int + sumoneovereps[j]) - 4.0 * sumSovereps[j]) >= 0.0) {
DP discr = 0.0;
bool retval = false;
//if ((discr = bquad * bquad - 4.0 * cquad) >= 0.0) {
if ((discr = (1.0/g_int + sumoneovereps[j]) * (1.0/g_int + sumoneovereps[j]) - 4.0 * sumSovereps[j]) >= 0.0) {
discr = sqrt(discr);
Sjleft = 0.5 * (-(1.0/g_int + sumoneovereps[j]) - discr);
Sjright = 0.5 * (-(1.0/g_int + sumoneovereps[j]) + discr);
retval = true;
}
}
return(retval);
return(retval);
*/
complex<DP> discr = sqrt((1.0/g_int + sumoneovereps[j]) * (1.0/g_int + sumoneovereps[j]) - 4.0 * sumSovereps[j]);
//complex<DP> discr = sqrt(ABACUS::max(0.0, real((1.0/g_int + sumoneovereps[j]) * (1.0/g_int + sumoneovereps[j]) - 4.0 * sumSovereps[j])));
Sjleft = 0.5 * (1.0/g_int + sumoneovereps[j] - discr);
Sjright = 0.5 * (1.0/g_int + sumoneovereps[j] + discr);
return(true);
@ -93,8 +92,6 @@ namespace ABACUS {
// Re-solve for jmax:
if (Solve_Richardson_Quad_S (g_int, epsilon, sumoneovereps, S, sumSovereps, jmax, Sleft, Sright)) {
//if (leftroot[jmax] == true) S[jmax] = damping * Sleft + (1.0 - damping) * S[jmax];
//else S[jmax] = damping * Sright + (1.0 - damping) * S[jmax];
if (abs(S[jmax] - Sleft) < abs(S[jmax] - Sright)) S[jmax] = damping * Sleft + (1.0 - damping) * S[jmax];
else S[jmax] = damping * Sright + (1.0 - damping) * S[jmax];
}
@ -104,14 +101,11 @@ namespace ABACUS {
cout << " to " << S[jmax] << endl;
// Re-solve also for a random j, given by
//int jrand = int(maxabsLHSRE * 1.0e+6) % Nlevels;
int jrand = rand() % Nlevels;
cout << "identified jrand = " << jrand << endl;
cout << "S[jrand]: from " << S[jrand];
if (Solve_Richardson_Quad_S (g_int, epsilon, sumoneovereps, S, sumSovereps, jrand, Sleft, Sright)) {
//if (leftroot[jrand] == true) S[jrand] = damping * Sleft + (1.0 - damping) * S[jrand];
//else S[jrand] = damping * Sright + (1.0 - damping) * S[jrand];
if (abs(S[jrand] - Sleft) < abs(S[jrand] - Sright)) S[jrand] = damping * Sleft + (1.0 - damping) * S[jrand];
else S[jrand] = damping * Sright + (1.0 - damping) * S[jrand];
}
@ -120,18 +114,6 @@ namespace ABACUS {
}
cout << " to " << S[jrand] << endl;
/*
for (int j = 0; j < Nlevels; ++j) {
if (Solve_Richardson_Quad_S (g_int, epsilon, sumoneovereps, S, sumSovereps, j, Sleft, Sright)) {
if (leftroot[j] == true) S[j] = damping * Sleft + (1.0 - damping) * S[j];
else S[j] = damping * Sright + (1.0 - damping) * S[j];
}
else {
ABACUSerror("Complex root.");
}
}
*/
// Recalculate all sums:
for (int j = 0; j < Nlevels; ++j) {
sumSovereps[j] = 0.0;
@ -144,8 +126,6 @@ namespace ABACUS {
}
} // namespace ABACUS