Rework Makefile; adopt semver, starting with 1.0.0
This commit is contained in:
@@ -0,0 +1,275 @@
|
||||
/**********************************************************
|
||||
|
||||
This software is part of J.-S. Caux's ABACUS library.
|
||||
|
||||
Copyright (c) J.-S. Caux.
|
||||
|
||||
-----------------------------------------------------------
|
||||
|
||||
File: src/BETHE/Base.cc
|
||||
|
||||
Purpose: defines functions in Base class,
|
||||
providing a unified base object for all
|
||||
Bethe Ansatz integrable models.
|
||||
|
||||
***********************************************************/
|
||||
|
||||
#include "ABACUS.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace ABACUS {
|
||||
|
||||
// Function definitions: class Base
|
||||
|
||||
Base::Base () : Charge(0), Nrap(Vect<int>()), Nraptot(0), Ix2_infty(Vect<DP>()),
|
||||
Ix2_max(Vect<int>()), id(0LL) {}
|
||||
|
||||
Base::Base (int N) : Charge(N), Nrap(Vect<int>(N,1)), Nraptot(N), Ix2_infty(Vect<DP>(1.0e+100,1)),
|
||||
Ix2_max(Vect<int>(LONG_LONG_MAX, 1)), id(N) {}
|
||||
|
||||
Base::Base (const Base& RefBase) // copy constructor
|
||||
: Charge(RefBase.Charge), Nrap(Vect<int>(RefBase.Nrap.size())), Nraptot(RefBase.Nraptot),
|
||||
Ix2_infty(Vect<DP>(RefBase.Ix2_infty.size())),
|
||||
Ix2_max(Vect<int>(RefBase.Ix2_max.size())), id(RefBase.id)
|
||||
{
|
||||
for (int i = 0; i < Nrap.size(); ++i) {
|
||||
Nrap[i] = RefBase.Nrap[i];
|
||||
Ix2_infty[i] = RefBase.Ix2_infty[i];
|
||||
Ix2_max[i] = RefBase.Ix2_max[i];
|
||||
}
|
||||
}
|
||||
|
||||
Base::Base (const Heis_Chain& RefChain, const Vect<int>& Nrapidities)
|
||||
: Charge(0), Nrap(Nrapidities), Nraptot(0), Ix2_infty(Vect<DP>(RefChain.Nstrings)),
|
||||
Ix2_max(Vect<int>(RefChain.Nstrings)),
|
||||
id (0LL)
|
||||
{
|
||||
// Check consistency of Nrapidities vector with RefChain
|
||||
if (RefChain.Nstrings != Nrapidities.size())
|
||||
ABACUSerror("Incompatible Nrapidities vector used in Base constructor.");
|
||||
|
||||
int Mcheck = 0;
|
||||
for (int i = 0; i < RefChain.Nstrings; ++i) Mcheck += RefChain.Str_L[i] * Nrap[i];
|
||||
Charge = Mcheck;
|
||||
|
||||
Nraptot = 0;
|
||||
for (int i = 0; i < RefChain.Nstrings; ++i) Nraptot += Nrap[i];
|
||||
|
||||
// Compute id
|
||||
id += Nrapidities[0];
|
||||
long long int factor = 100000LL;
|
||||
for (int i = 1; i < RefChain.Nstrings; ++i) {
|
||||
id += factor * Nrapidities[i];
|
||||
factor *= 100LL;
|
||||
}
|
||||
|
||||
// Now compute the Ix2_infty numbers
|
||||
(*this).Compute_Ix2_limits(RefChain);
|
||||
}
|
||||
|
||||
Base::Base (const Heis_Chain& RefChain, long long int id_ref)
|
||||
: Charge(0), Nrap(Vect<int>(RefChain.Nstrings)), Nraptot(0),
|
||||
Ix2_infty(Vect<DP>(RefChain.Nstrings)), Ix2_max(Vect<int>(RefChain.Nstrings)),
|
||||
id (id_ref)
|
||||
{
|
||||
// Build Nrapidities vector from id_ref
|
||||
|
||||
long long int factor = pow_ulli (10LL, 2* RefChain.Nstrings + 1);
|
||||
long long int id_eff = id_ref;
|
||||
for (int i = 0; i < RefChain.Nstrings - 1; ++i) {
|
||||
Nrap[RefChain.Nstrings - 1 - i] = id_eff/factor;
|
||||
id_eff -= factor * Nrap[RefChain.Nstrings - 1 - i];
|
||||
factor /= 100LL;
|
||||
}
|
||||
Nrap[0] = id_eff;
|
||||
|
||||
int Mcheck = 0;
|
||||
for (int i = 0; i < RefChain.Nstrings; ++i) Mcheck += RefChain.Str_L[i] * Nrap[i];
|
||||
Charge = Mcheck;
|
||||
|
||||
Nraptot = 0;
|
||||
for (int i = 0; i < RefChain.Nstrings; ++i) Nraptot += Nrap[i];
|
||||
|
||||
// Now compute the Ix2_infty numbers
|
||||
(*this).Compute_Ix2_limits(RefChain);
|
||||
}
|
||||
|
||||
|
||||
Base& Base::operator= (const Base& RefBase)
|
||||
{
|
||||
if (this != & RefBase) {
|
||||
Charge = RefBase.Charge;
|
||||
Nrap = RefBase.Nrap;
|
||||
Nraptot = RefBase.Nraptot;
|
||||
Ix2_infty = RefBase.Ix2_infty;
|
||||
Ix2_max = RefBase.Ix2_max;
|
||||
id = RefBase.id;
|
||||
}
|
||||
return(*this);
|
||||
}
|
||||
|
||||
bool Base::operator== (const Base& RefBase)
|
||||
{
|
||||
bool answer = (Nrap == RefBase.Nrap);
|
||||
|
||||
return (answer);
|
||||
}
|
||||
|
||||
bool Base::operator!= (const Base& RefBase)
|
||||
{
|
||||
bool answer = (Nrap != RefBase.Nrap);
|
||||
|
||||
return (answer);
|
||||
}
|
||||
|
||||
void Base::Compute_Ix2_limits (const Heis_Chain& RefChain)
|
||||
{
|
||||
|
||||
if ((RefChain.Delta > 0.0) && (RefChain.Delta < 1.0)) {
|
||||
|
||||
// Compute the Ix2_infty numbers
|
||||
|
||||
DP sum1 = 0.0;
|
||||
DP sum2 = 0.0;
|
||||
|
||||
for (int j = 0; j < RefChain.Nstrings; ++j) {
|
||||
|
||||
sum1 = 0.0;
|
||||
|
||||
for (int k = 0; k < RefChain.Nstrings; ++k) {
|
||||
|
||||
sum2 = 0.0;
|
||||
|
||||
sum2 += (RefChain.Str_L[j] == RefChain.Str_L[k]) ? 0.0 :
|
||||
2.0 * atan(tan(0.25 * PI * (1.0 + RefChain.par[j] * RefChain.par[k])
|
||||
- 0.5 * fabs(RefChain.Str_L[j] - RefChain.Str_L[k]) * RefChain.anis));
|
||||
sum2 += 2.0 * atan(tan(0.25 * PI * (1.0 + RefChain.par[j] * RefChain.par[k])
|
||||
- 0.5 * (RefChain.Str_L[j] + RefChain.Str_L[k]) * RefChain.anis));
|
||||
|
||||
for (int a = 1; a < ABACUS::min(RefChain.Str_L[j], RefChain.Str_L[k]); ++a)
|
||||
sum2 += 2.0 * 2.0 * atan(tan(0.25 * PI * (1.0 + RefChain.par[j] * RefChain.par[k])
|
||||
- 0.5 * (fabs(RefChain.Str_L[j] - RefChain.Str_L[k])
|
||||
+ 2.0*a) * RefChain.anis));
|
||||
|
||||
sum1 += (Nrap[k] - ((j == k) ? 1 : 0)) * sum2;
|
||||
}
|
||||
|
||||
Ix2_infty[j] = (1.0/PI) * fabs(RefChain.Nsites *
|
||||
2.0 * atan(tan(0.25 * PI * (1.0 + RefChain.par[j])
|
||||
- 0.5 * RefChain.Str_L[j] * RefChain.anis)) - sum1);
|
||||
|
||||
} // The Ix2_infty are now set.
|
||||
|
||||
// Now compute the Ix2_max limits
|
||||
|
||||
for (int j = 0; j < RefChain.Nstrings; ++j) {
|
||||
|
||||
Ix2_max[j] = int(floor(Ix2_infty[j])); // sets basic integer
|
||||
|
||||
// Reject formally infinite rapidities (i.e. if Delta is root of unity)
|
||||
|
||||
//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;
|
||||
|
||||
while (Ix2_max[j] > RefChain.Nsites) {
|
||||
Ix2_max[j] -= 2;
|
||||
}
|
||||
}
|
||||
} // if XXZ gapless
|
||||
|
||||
else if (RefChain.Delta == 1.0) {
|
||||
|
||||
// Compute the Ix2_infty numbers
|
||||
|
||||
int sum1 = 0;
|
||||
|
||||
for (int j = 0; j < RefChain.Nstrings; ++j) {
|
||||
|
||||
sum1 = 0;
|
||||
|
||||
for (int k = 0; k < RefChain.Nstrings; ++k) {
|
||||
|
||||
sum1 += Nrap[k] * (2 * ABACUS::min(RefChain.Str_L[j], RefChain.Str_L[k]) - ((j == k) ? 1 : 0));
|
||||
}
|
||||
|
||||
//Ix2_infty[j] = (RefChain.Nsites - 1.0 + 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.
|
||||
|
||||
// Now compute the Ix2_max limits
|
||||
|
||||
for (int j = 0; j < RefChain.Nstrings; ++j) {
|
||||
|
||||
Ix2_max[j] = int(floor(Ix2_infty[j])); // sets basic integer
|
||||
|
||||
// Give the correct parity to Ix2_max
|
||||
|
||||
// If Nrap is even, Ix2_max must be odd. If odd, then even.
|
||||
|
||||
if (!((Nrap[j] + Ix2_max[j]) % 2)) Ix2_max[j] -= 1;
|
||||
|
||||
// If Ix2_max equals Ix2_infty, we reduce it by 2:
|
||||
|
||||
if (Ix2_max[j] == int(Ix2_infty[j])) Ix2_max[j] -= 2;
|
||||
|
||||
while (Ix2_max[j] > RefChain.Nsites) {
|
||||
Ix2_max[j] -= 2;
|
||||
}
|
||||
}
|
||||
|
||||
} // if XXX AFM
|
||||
|
||||
else if (RefChain.Delta > 1.0) {
|
||||
|
||||
// Compute the Ix2_infty numbers
|
||||
|
||||
int sum1 = 0;
|
||||
|
||||
for (int j = 0; j < RefChain.Nstrings; ++j) {
|
||||
|
||||
sum1 = 0;
|
||||
|
||||
for (int k = 0; k < RefChain.Nstrings; ++k) {
|
||||
|
||||
sum1 += Nrap[k] * (2 * ABACUS::min(RefChain.Str_L[j], RefChain.Str_L[k]) - ((j == k) ? 1 : 0));
|
||||
}
|
||||
|
||||
Ix2_infty[j] = (RefChain.Nsites - 1 + 2 * RefChain.Str_L[j] - sum1);
|
||||
|
||||
} // The Ix2_infty are now set.
|
||||
|
||||
// Now compute the Ix2_max limits
|
||||
|
||||
for (int j = 0; j < RefChain.Nstrings; ++j) {
|
||||
|
||||
Ix2_max[j] = int(floor(Ix2_infty[j])); // sets basic integer
|
||||
|
||||
// Give the correct parity to Ix2_max
|
||||
|
||||
// If Nrap is even, Ix2_max must be odd. If odd, then even.
|
||||
|
||||
if (!((Nrap[j] + Ix2_max[j]) % 2)) Ix2_max[j] -= 1;
|
||||
|
||||
// If Ix2_max equals Ix2_infty, we reduce it by 2:
|
||||
|
||||
//if (Ix2_max[j] == Ix2_infty[j]) Ix2_max[j] -= 2;
|
||||
|
||||
while (Ix2_max[j] > RefChain.Nsites) {
|
||||
Ix2_max[j] -= 2;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} // if XXZ_gpd
|
||||
|
||||
}
|
||||
|
||||
|
||||
} // namespace ABACUS
|
||||
@@ -0,0 +1,29 @@
|
||||
/**********************************************************
|
||||
|
||||
This software is part of J.-S. Caux's ABACUS library.
|
||||
|
||||
Copyright (c) J.-S. Caux.
|
||||
|
||||
-----------------------------------------------------------
|
||||
|
||||
File: src/BETHE/Bethe_State.cc
|
||||
|
||||
Purpose: defines functions in Bethe_State class,
|
||||
providing a unified object for eigenstates of all
|
||||
Bethe Ansatz integrable models.
|
||||
|
||||
IN DEVELOPMENT
|
||||
|
||||
***********************************************************/
|
||||
|
||||
#include "ABACUS.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace ABACUS {
|
||||
|
||||
Bethe_State::Bethe_State (long long int base_id_ref, long long int type_id_ref,
|
||||
long long int id_ref, long long int maxid_ref) :
|
||||
base_id(base_id_ref), type_id(type_id_ref), id(id_ref), maxid(maxid_ref) {}
|
||||
|
||||
} // namespace ABACUS
|
||||
@@ -0,0 +1,276 @@
|
||||
/**********************************************************
|
||||
|
||||
This software is part of J.-S. Caux's ABACUS library.
|
||||
|
||||
Copyright (c) J.-S. Caux.
|
||||
|
||||
-----------------------------------------------------------
|
||||
|
||||
File: src/BETHE/Offsets.cc
|
||||
|
||||
Purpose: defines functions in Offsets class.
|
||||
|
||||
IN DEVELOPMENT
|
||||
|
||||
***********************************************************/
|
||||
|
||||
#include "ABACUS.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace ABACUS {
|
||||
|
||||
// Function definitions: class Offsets
|
||||
|
||||
Offsets::Offsets () : base(), Tableau(Vect<Young_Tableau>()), type_id(0LL), id(0LL), maxid(0LL) {};
|
||||
|
||||
Offsets::Offsets (const Offsets& RefOffset) // copy constructor
|
||||
: base(RefOffset.base), Tableau(Vect<Young_Tableau> (2 * base.Nrap.size() + 2)), type_id(RefOffset.type_id), id(RefOffset.id), maxid(RefOffset.maxid)
|
||||
{
|
||||
for (int i = 0; i < 2 * base.Nrap.size() + 2; ++i) Tableau[i] = RefOffset.Tableau[i];
|
||||
}
|
||||
|
||||
Offsets::Offsets (const Heis_Base& RefBase, long long int req_type_id)
|
||||
// sets all tableaux to empty ones, with nparticles(req_type_id) at each level
|
||||
{
|
||||
// Build nparticles vector from req_type_id
|
||||
|
||||
Vect<int> nparticles(0, 2* RefBase.Nrap.size() + 2);
|
||||
long long int factor = pow_ulli (10LL, nparticles.size() - 1);
|
||||
long long int id_eff = req_type_id;
|
||||
for (int i = 0; i < nparticles.size(); ++i) {
|
||||
nparticles[nparticles.size() - 1 - i] = id_eff/factor;
|
||||
id_eff -= factor * nparticles[nparticles.size() - 1 - i];
|
||||
factor /= 10LL;
|
||||
}
|
||||
|
||||
// Check if we've got the right vector...
|
||||
long long int idcheck = Offsets_type_id (nparticles);
|
||||
if (idcheck != req_type_id) ABACUSerror("idcheck != req_type_id in Offsets constructor.");
|
||||
|
||||
(*this) = Offsets(RefBase, nparticles);
|
||||
}
|
||||
|
||||
Offsets::Offsets (const Heis_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(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 Offsets constructor.");
|
||||
|
||||
//if (base.Nrap[0] != (nparticles[3] + nparticles[2] + base.Mdown - nparticles[0] - nparticles[1])) ABACUSerror("Wrong Nrap[0] in 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 Offsets constructor.");
|
||||
}
|
||||
|
||||
for (int base_level = 1; base_level < base.Nrap.size(); ++ base_level)
|
||||
if (base.Nrap[base_level] != nparticles[2*base_level + 2] + nparticles[2*base_level + 3]) {
|
||||
cout << base_level << "\t" << base.Nrap[base_level] << "\t" << nparticles[2*base_level + 2] << "\t" << nparticles[2*base_level + 3] << endl;
|
||||
ABACUSerror("Wrong Nrap[] in 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 Offsets constructor.");
|
||||
if (nparticles[1] > base.Nrap[0]/2) ABACUSerror("nparticles[1] too large in 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 Offsets constructor.");
|
||||
if (nparticles[3] > (base.Ix2_max[0] - base.Nrap[0] + 1)/2) ABACUSerror("nparticles[3] too large in 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)
|
||||
//|| (nparticles[2*base_level + 3] > 0 && nparticles[2*base_level + 3] > (base.Ix2_max[base_level] - (base.Nrap[base_level] % 2) - 1)/2)) {
|
||||
|| (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)) {
|
||||
cout << 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 Offsets constructor.");
|
||||
}
|
||||
|
||||
// Check sum of rapidities
|
||||
|
||||
// Holes in GS interval
|
||||
Tableau[0] = Young_Tableau(nparticles[0], (base.Nrap[0] + 1)/2 - nparticles[0]);
|
||||
Tableau[1] = Young_Tableau(nparticles[1], base.Nrap[0]/2 - nparticles[1], Tableau[0]);
|
||||
|
||||
// Particles of type 0 out of GS interval
|
||||
Tableau[2] = Young_Tableau(nparticles[2], (base.Ix2_max[0] - base.Nrap[0] + 1)/2 - nparticles[2], Tableau[0]);
|
||||
Tableau[3] = Young_Tableau(nparticles[3], (base.Ix2_max[0] - base.Nrap[0] + 1)/2 - nparticles[3], Tableau[2]);
|
||||
|
||||
// Tableaux of index i = 2,...: data about string type i/2-1.
|
||||
for (int base_level = 1; base_level < base.Nrap.size(); ++base_level) {
|
||||
Tableau[2*base_level + 2] = Young_Tableau(nparticles[2*base_level + 2],
|
||||
//(base.Ix2_max[base_level] - ((base.Nrap[base_level]) % 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]);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
}
|
||||
|
||||
Offsets& Offsets::operator= (const Offsets& RefOffset)
|
||||
{
|
||||
if (this != &RefOffset) {
|
||||
base = RefOffset.base;
|
||||
Tableau = RefOffset.Tableau;
|
||||
type_id = RefOffset.type_id;
|
||||
id = RefOffset.id;
|
||||
maxid = RefOffset.maxid;
|
||||
}
|
||||
return(*this);
|
||||
}
|
||||
|
||||
bool Offsets::operator<= (const Offsets& RefOffsets)
|
||||
{
|
||||
// Check whether all nonzero tableau row lengths in RefOffsets
|
||||
// are <= than those in *this
|
||||
|
||||
bool answer = true;
|
||||
for (int level = 0; level < 4; ++level) { // check fundamental level only
|
||||
//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)
|
||||
if (Tableau[level].Row_L[tableau_level] > RefOffsets.Tableau[level].Row_L[tableau_level])
|
||||
answer = false;
|
||||
// Now check whether there exist extra rows violating rule:
|
||||
for (int tableau_level = ABACUS::min(Tableau[level].Nrows, RefOffsets.Tableau[level].Nrows); tableau_level < Tableau[level].Nrows; ++tableau_level)
|
||||
if (Tableau[level].Row_L[tableau_level] > 0) answer = false;
|
||||
}
|
||||
|
||||
return(answer);
|
||||
}
|
||||
|
||||
bool Offsets::operator>= (const Offsets& RefOffsets)
|
||||
{
|
||||
// Check whether all nonzero tableau row lengths in RefOffsets
|
||||
// are >= than those in *this
|
||||
|
||||
bool answer = true;
|
||||
for (int level = 0; level < 4; ++level) { // check fundamental level only
|
||||
//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)
|
||||
if (Tableau[level].Row_L[tableau_level] < RefOffsets.Tableau[level].Row_L[tableau_level])
|
||||
answer = false;
|
||||
// Now check whether there exist extra rows violating rule:
|
||||
for (int tableau_level = ABACUS::min(Tableau[level].Nrows, RefOffsets.Tableau[level].Nrows); tableau_level < RefOffsets.Tableau[level].Nrows; ++tableau_level)
|
||||
if (RefOffsets.Tableau[level].Row_L[tableau_level] > 0) answer = false;
|
||||
}
|
||||
|
||||
return(answer);
|
||||
}
|
||||
|
||||
void Offsets::Compute_type_id ()
|
||||
{
|
||||
type_id = 0LL;
|
||||
|
||||
for (int i = 0; i < 2*base.Nrap.size() + 2; ++i) {
|
||||
Tableau[i].Compute_id();
|
||||
type_id += Tableau[i].Nrows * pow_ulli(10LL, i);
|
||||
}
|
||||
}
|
||||
|
||||
void Offsets::Set_to_id (long long int idnr)
|
||||
{
|
||||
// The idnr of the Offset is given by
|
||||
// sub_id[0] + (total number of tableaux of type 0) * (sub_id[1] + (total number of tableaux of type 1) * (sub_id[2] + ...
|
||||
// + total number of tableaux of type (2*base.Nrap.size()) * sub_id[2*base.Nrap.size() + 1]
|
||||
|
||||
if (idnr > maxid) {
|
||||
cout << idnr << "\t" << maxid << endl;
|
||||
ABACUSerror("idnr too large in offsets.Set_to_id.");
|
||||
}
|
||||
|
||||
id = idnr;
|
||||
|
||||
Vect<long long int> sub_id(0LL, 2*base.Nrap.size() + 2);
|
||||
|
||||
long long int idnr_eff = idnr;
|
||||
long long int temp_prod = 1LL;
|
||||
|
||||
Vect<long long int> result_choose(2*base.Nrap.size() + 2);
|
||||
|
||||
for (int i = 0; i <= 2*base.Nrap.size(); ++i) {
|
||||
//result_choose[i] = choose_lli(Tableau[i].Nrows + Tableau[i].Ncols, Tableau[i].Nrows);
|
||||
result_choose[i] = Tableau[i].maxid + 1LL;
|
||||
temp_prod *= result_choose[i];
|
||||
}
|
||||
|
||||
for (int i = 2*base.Nrap.size() + 1; i > 0; --i) {
|
||||
sub_id[i] = idnr_eff/temp_prod;
|
||||
idnr_eff -= sub_id[i] * temp_prod;
|
||||
temp_prod /= result_choose[i-1];
|
||||
}
|
||||
sub_id[0] = idnr_eff; // what's left goes to the bottom...
|
||||
|
||||
for (int i = 0; i <= 2*base.Nrap.size() + 1; ++i) {
|
||||
//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].id != sub_id[i]) Tableau[i].Set_to_id(sub_id[i]);
|
||||
}
|
||||
|
||||
Compute_type_id ();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void Offsets::Compute_id ()
|
||||
{
|
||||
long long int prod_maxid = 1LL;
|
||||
|
||||
id = 0LL;
|
||||
|
||||
for (int i = 0; i < 2*base.Nrap.size() + 2; ++i) {
|
||||
Tableau[i].Compute_id();
|
||||
id += Tableau[i].id * prod_maxid;
|
||||
prod_maxid *= Tableau[i].maxid + 1LL;
|
||||
}
|
||||
}
|
||||
|
||||
Vect<long long int> Offsets::Descendents (bool fixed_iK)
|
||||
{
|
||||
// From a given vector of Young tableaux specifying a particular eigenstate,
|
||||
// this function provides the full set of descendents (either at the same momentum if
|
||||
// fixed_iK == true, or not) by returning a vector of all descendent id's (leaving the
|
||||
// base and type invariant), which can then be used for further calculations.
|
||||
|
||||
// This set of descendents is meant to be used when calculating either partition functions
|
||||
// or zero-temperature correlation functions.
|
||||
|
||||
// IMPORTANT ASSUMPTIONS:
|
||||
// - all even sectors consistently increase/decrease momentum for increasing tableau row length
|
||||
// - all odd sectors consistently decrease/increase momentum for increasing tableau row length
|
||||
|
||||
// FOR FIXED MOMENTUM:
|
||||
// all tableau levels `above' the lowest occupied one are descended as for fixed_iK == false,
|
||||
// and the lowest sector's highest tableau level's row length is modified (increased or decreased by one
|
||||
// unit if possible) such that the iK of Tableau_desc == iK of Tableau_ref.
|
||||
// The logic behind this is that for a state with nexc excitations, we let run nexc - 1 of the
|
||||
// excitations, and the lowest one is fixed in place by the momentum constraint, if possible.
|
||||
|
||||
Vect<Young_Tableau> Tableau_ref = (*this).Tableau;
|
||||
Vect<Young_Tableau> Tableau_desc = Tableau_ref;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // namespace ABACUS
|
||||
+1428
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,24 @@
|
||||
/**********************************************************
|
||||
|
||||
This software is part of J.-S. Caux's ABACUS library.
|
||||
|
||||
Copyright (c) J.-S. Caux.
|
||||
|
||||
-----------------------------------------------------------
|
||||
|
||||
File: src/ODSLF/ODSLF_Chem_Pot.cc
|
||||
|
||||
Purpose: calculates the chemical potential.
|
||||
|
||||
***********************************************************/
|
||||
|
||||
#include "ABACUS.h"
|
||||
|
||||
namespace ABACUS {
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
/**********************************************************
|
||||
|
||||
This software is part of J.-S. Caux's ABACUS library.
|
||||
|
||||
Copyright (c) J.-S. Caux.
|
||||
|
||||
-----------------------------------------------------------
|
||||
|
||||
File: ODSLF_DSF.cc
|
||||
|
||||
Purpose: main function for ABACUS for spinless fermions related to Heisenberg spin-1/2 chain
|
||||
|
||||
***********************************************************/
|
||||
|
||||
#include "ABACUS.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace ABACUS;
|
||||
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
|
||||
if (argc != 10) { // provide some info
|
||||
|
||||
cout << endl << "Welcome to ABACUS\t(copyright J.-S. Caux)." << endl;
|
||||
cout << "Usage of ODSLF_DSF executable: " << endl;
|
||||
cout << endl << "Provide the following arguments:" << endl << endl;
|
||||
cout << "char whichDSF \t\t Which structure factor should be calculated ? Options are: "
|
||||
"m for S- S+, z for Sz Sz, p for S+ S-." << endl;
|
||||
cout << "DP Delta \t\t Value of the anisotropy: use positive real values only" << endl;
|
||||
cout << "int N \t\t\t Length (number of sites) of the system: use positive even integer values only" << endl;
|
||||
cout << "int M \t\t\t Number of down spins: use positive integer values between 1 and N/2" << endl;
|
||||
cout << "int iKmin" << endl << "int iKmax \t\t Min and max momentum integers to scan over: "
|
||||
"recommended values: 0 and N" << endl;
|
||||
cout << "int Max_Secs \t\t Allowed computational time: (in seconds)" << endl;
|
||||
cout << "DP target_sumrule \t sumrule saturation you're satisfied with" << endl;
|
||||
cout << "bool refine \t\t Is this a refinement of a earlier calculations ? (0 == false, 1 == true)" << endl;
|
||||
cout << endl << "EXAMPLE: " << endl << endl;
|
||||
cout << "ODSLF_DSF z 1.0 100 40 0 100 600 1.0 0" << endl << endl;
|
||||
}
|
||||
|
||||
else if (argc == 10) { // !fixed_iK
|
||||
char whichDSF = *argv[1];
|
||||
DP Delta = atof(argv[2]);
|
||||
int N = atoi(argv[3]);
|
||||
int M = atoi(argv[4]);
|
||||
int iKmin = atoi(argv[5]);
|
||||
int iKmax = atoi(argv[6]);
|
||||
int Max_Secs = atoi(argv[7]);
|
||||
DP target_sumrule = atof(argv[8]);
|
||||
bool refine = (atoi(argv[9]) == 1);
|
||||
|
||||
Scan_ODSLF (whichDSF, Delta, N, M, iKmin, iKmax, Max_Secs, target_sumrule, refine, 0, 1);
|
||||
}
|
||||
|
||||
else ABACUSerror("Wrong number of arguments to ODSLF_DSF executable.");
|
||||
|
||||
return(0);
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
/**********************************************************
|
||||
|
||||
This software is part of J.-S. Caux's ABACUS library.
|
||||
|
||||
Copyright (c) J.-S. Caux.
|
||||
|
||||
-----------------------------------------------------------
|
||||
|
||||
File: src/ODSLF/ODSLF_Matrix_Element_Contrib.cc
|
||||
|
||||
Purpose: handles the generic call for a matrix element.
|
||||
|
||||
***********************************************************/
|
||||
|
||||
#include "ABACUS.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace ABACUS;
|
||||
|
||||
namespace ABACUS {
|
||||
|
||||
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)
|
||||
{
|
||||
// This function prints the matrix element information to the fstream,
|
||||
// and returns a weighed `data_value' to be multiplied by sumrule_factor,
|
||||
// to determine if scanning along this thread should be continued.
|
||||
|
||||
// Identify which matrix is needed from the number of particles in Left and Right states:
|
||||
|
||||
bool fixed_iK = (iKmin == iKmax);
|
||||
|
||||
DP ME = 0.0;
|
||||
if (whichDSF == 'Z')
|
||||
ME = LeftState.E - RefState.E;
|
||||
else if (whichDSF == 'm')
|
||||
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)
|
||||
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)));
|
||||
}
|
||||
else if (whichDSF == 'p')
|
||||
ME = exp(real(ln_Smin_ME (LeftState, RefState)));
|
||||
else ABACUSerror("Wrong whichDSF in Compute_Matrix_Element_Contrib.");
|
||||
|
||||
if (is_nan(ME)) ME = 0.0;
|
||||
|
||||
// Do the momentum business:
|
||||
int iKout = LeftState.iK - RefState.iK;
|
||||
while(iKout < 0) iKout += RefState.chain.Nsites;
|
||||
while(iKout >= RefState.chain.Nsites) iKout -= RefState.chain.Nsites;
|
||||
|
||||
DAT_outfile << setprecision(16);
|
||||
// Print information to fstream:
|
||||
if (iKout >= iKmin && iKout <= iKmax) {
|
||||
if (whichDSF == 'Z') {
|
||||
DAT_outfile << endl << LeftState.E - RefState.E - (LeftState.base.Mdown - RefState.base.Mdown) * Chem_Pot << "\t"
|
||||
<< iKout << "\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.base_id << "\t" << LeftState.type_id << "\t" << LeftState.id;
|
||||
}
|
||||
} // if iKmin <= iKout <= iKmax
|
||||
|
||||
// Calculate and return the data_value:
|
||||
DP data_value = ME * ME;
|
||||
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:
|
||||
data_value = ME * ME * (LeftState.E - RefState.E - (LeftState.base.Mdown - RefState.base.Mdown) * Chem_Pot);
|
||||
|
||||
return(data_value);
|
||||
}
|
||||
|
||||
} // namespace ABACUS
|
||||
@@ -0,0 +1,192 @@
|
||||
/**********************************************************
|
||||
|
||||
This software is part of J.-S. Caux's ABACUS library.
|
||||
|
||||
Copyright (c) J.-S. Caux.
|
||||
|
||||
-----------------------------------------------------------
|
||||
|
||||
File: src/ODSLF/ODSLF_Sumrules.cc
|
||||
|
||||
Purpose: defines sumrule factors for spinless fermions related to Heisenberg
|
||||
|
||||
***********************************************************/
|
||||
|
||||
#include "ABACUS.h"
|
||||
|
||||
using namespace ABACUS;
|
||||
using namespace std;
|
||||
|
||||
namespace ABACUS {
|
||||
|
||||
|
||||
DP ODSLF_X_avg (char xyorz, DP Delta, int N, int M)
|
||||
{
|
||||
// Calculates \sum_j < S_j^a S_{j+1}^a >, a = x, y or z.
|
||||
|
||||
DP eps_Delta = 0.00000001;
|
||||
|
||||
// Define the chain: J, Delta, h, Nsites
|
||||
Heis_Chain chain(1.0, Delta, 0.0, N);
|
||||
|
||||
// Define the base: chain, Mdown
|
||||
ODSLF_Base gbase(chain, M);
|
||||
|
||||
// Define the chain: J, Delta, h, Nsites
|
||||
Heis_Chain chain2(1.0, Delta + eps_Delta, 0.0, N);
|
||||
|
||||
// Define the base: chain, Mdown
|
||||
ODSLF_Base gbase2(chain2, M);
|
||||
|
||||
DP E0_Delta = 0.0;
|
||||
DP E0_Delta_eps = 0.0;
|
||||
|
||||
if (Delta > 0.0 && Delta < 1.0) {
|
||||
|
||||
// Define the ground state
|
||||
ODSLF_XXZ_Bethe_State gstate(chain, gbase);
|
||||
|
||||
// Compute everything about the ground state
|
||||
gstate.Compute_All(true);
|
||||
|
||||
E0_Delta = gstate.E;
|
||||
|
||||
// Define the ground state
|
||||
ODSLF_XXZ_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;
|
||||
if (xyorz == 'x' || xyorz == 'y') answer = 0.5 * (E0_Delta - Delta * (E0_Delta_eps - E0_Delta)/eps_Delta);
|
||||
|
||||
// Careful for z ! Hamiltonian defined as S^z S^z - 1/4, so add back N/4:
|
||||
else if (xyorz == 'z') answer = (E0_Delta_eps - E0_Delta)/eps_Delta + 0.25 * N;
|
||||
|
||||
else ABACUSerror("option not implemented in ODSLF_X_avg.");
|
||||
|
||||
return(answer);
|
||||
}
|
||||
|
||||
DP ODSLF_S1_sumrule_factor (char mporz, DP Delta, int N, int M, int iK)
|
||||
{
|
||||
|
||||
DP X_x = ODSLF_X_avg ('x', Delta, N, M);
|
||||
DP X_z = ODSLF_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;
|
||||
|
||||
else if (mporz == 'z') sumrule = iK == 0 ? 1.0 : -2.0 * X_x * (1.0 - cos((twoPI * iK)/N))/N;
|
||||
|
||||
else if (mporz == 'a') sumrule = 1.0;
|
||||
else if (mporz == 'b') sumrule = 1.0;
|
||||
|
||||
else ABACUSerror("option not implemented in ODSLF_S1_sumrule_factor.");
|
||||
|
||||
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 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;
|
||||
|
||||
else if (mporz == 'z') sumrule = -2.0 * X_x * (1.0 - cos((twoPI * iK)/N))/N;
|
||||
|
||||
else if (mporz == 'a') sumrule = 1.0;
|
||||
else if (mporz == 'b') sumrule = 1.0;
|
||||
|
||||
else ABACUSerror("option not implemented in ODSLF_S1_sumrule_factor.");
|
||||
|
||||
return(1.0/(sumrule + 1.0e-32)); // sumrule is 0 for iK == 0 or N
|
||||
}
|
||||
|
||||
DP Sumrule_Factor (char whichDSF, ODSLF_Bethe_State& RefState, DP Chem_Pot, int iKmin, int iKmax)
|
||||
{
|
||||
DP sumrule_factor = 1.0;
|
||||
if (iKmin != iKmax) {
|
||||
if (whichDSF == 'Z') sumrule_factor = 1.0;
|
||||
else if (whichDSF == 'm')
|
||||
sumrule_factor = 1.0/RefState.base.Mdown;
|
||||
else if (whichDSF == 'z') sumrule_factor = 1.0/(0.25 * RefState.chain.Nsites);
|
||||
else if (whichDSF == 'p') sumrule_factor = 1.0/(RefState.chain.Nsites - RefState.base.Mdown);
|
||||
else if (whichDSF == 'a') sumrule_factor = 1.0;
|
||||
else if (whichDSF == 'b') sumrule_factor = 1.0;
|
||||
else if (whichDSF == 'q') sumrule_factor = 1.0;
|
||||
|
||||
else ABACUSerror("whichDSF option not consistent in Sumrule_Factor");
|
||||
}
|
||||
else if (iKmin == iKmax) {
|
||||
if (whichDSF == 'Z') sumrule_factor = 1.0;
|
||||
else if (whichDSF == 'm' || whichDSF == 'z' || whichDSF == 'p')
|
||||
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;
|
||||
|
||||
else ABACUSerror("whichDSF option not consistent in Sumrule_Factor");
|
||||
}
|
||||
|
||||
|
||||
|
||||
return(sumrule_factor);
|
||||
}
|
||||
|
||||
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;
|
||||
RAW_stringstream << prefix << ".raw";
|
||||
RAW_string = RAW_stringstream.str(); const char* RAW_Cstr = RAW_string.c_str();
|
||||
|
||||
stringstream FSR_stringstream; string FSR_string;
|
||||
FSR_stringstream << prefix << ".fsr";
|
||||
FSR_string = FSR_stringstream.str(); const char* FSR_Cstr = FSR_string.c_str();
|
||||
|
||||
ifstream infile;
|
||||
infile.open(RAW_Cstr);
|
||||
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, iKmax - iKmin + 1); //
|
||||
|
||||
DP omega, FF;
|
||||
int iK, conv;
|
||||
long long int base_id, type_id, id;
|
||||
|
||||
while (infile.peek() != EOF) {
|
||||
infile >> omega >> iK >> FF >> conv >> base_id >> type_id >> id;
|
||||
if (iK >= iKmin && iK <= iKmax) Sum_omega_FFsq[iK - iKmin] += omega * FF * FF;
|
||||
}
|
||||
|
||||
infile.close();
|
||||
|
||||
ofstream outfile;
|
||||
outfile.open(FSR_Cstr);
|
||||
outfile.precision(16);
|
||||
|
||||
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);
|
||||
|
||||
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.close();
|
||||
}
|
||||
|
||||
} // namespace ABACUS
|
||||
@@ -0,0 +1,509 @@
|
||||
/**********************************************************
|
||||
|
||||
This software is part of J.-S. Caux's ABACUS library.
|
||||
|
||||
Copyright (c) J.-S. Caux.
|
||||
|
||||
-----------------------------------------------------------
|
||||
|
||||
File: src/ODSLF/ODSLF_XXZ_Bethe_State.cc
|
||||
|
||||
Purpose: defines Bethe states for 1d spinless fermions.
|
||||
|
||||
***********************************************************/
|
||||
|
||||
#include "ABACUS.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace ABACUS {
|
||||
|
||||
// Function prototypes
|
||||
|
||||
inline DP ODSLF_fbar_XXZ (DP lambda, int par, DP tannzetaover2);
|
||||
DP ODSLF_Theta_XXZ (DP lambda, int nj, int nk, int parj, int park, DP* tannzetaover2);
|
||||
DP ODSLF_hbar_XXZ (DP lambda, int n, int par, DP* si_n_anis_over_2);
|
||||
DP ODSLF_ddlambda_Theta_XXZ (DP lambda, int nj, int nk, int parj, int park, DP* si_n_anis_over_2);
|
||||
|
||||
|
||||
//***************************************************************************************************
|
||||
|
||||
// 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_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)),
|
||||
tanhlambda(ODSLF_Lambda(RefState.chain, RefState.base))
|
||||
{
|
||||
// copy arrays into new ones
|
||||
|
||||
//cout << "Calling XXZ state copy constructor." << endl;
|
||||
for (int j = 0; j < RefState.chain.Nstrings; ++j) {
|
||||
for (int alpha = 0; alpha < RefState.base[j]; ++j) {
|
||||
sinhlambda[j][alpha] = RefState.sinhlambda[j][alpha];
|
||||
coshlambda[j][alpha] = RefState.coshlambda[j][alpha];
|
||||
tanhlambda[j][alpha] = RefState.tanhlambda[j][alpha];
|
||||
}
|
||||
}
|
||||
//cout << "Done calling XXZ state copy constructor." << endl;
|
||||
}
|
||||
|
||||
ODSLF_XXZ_Bethe_State::ODSLF_XXZ_Bethe_State (const Heis_Chain& RefChain, int M)
|
||||
: ODSLF_Bethe_State(RefChain, M),
|
||||
sinhlambda(ODSLF_Lambda(RefChain, M)), coshlambda(ODSLF_Lambda(RefChain, M)), tanhlambda(ODSLF_Lambda(RefChain, M))
|
||||
{
|
||||
//cout << "Here in XXZ BS constructor." << endl;
|
||||
//cout << (*this).lambda[0][0] << endl;
|
||||
//cout << "OK" << endl;
|
||||
if ((RefChain.Delta <= -1.0) || (RefChain.Delta >= 1.0))
|
||||
ABACUSerror("Delta out of range in 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))
|
||||
{
|
||||
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_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");
|
||||
}
|
||||
|
||||
|
||||
ODSLF_XXZ_Bethe_State& ODSLF_XXZ_Bethe_State::operator= (const ODSLF_XXZ_Bethe_State& RefState)
|
||||
{
|
||||
if (this != &RefState) {
|
||||
chain = RefState.chain;
|
||||
base = RefState.base;
|
||||
offsets = RefState.offsets;
|
||||
Ix2 = RefState.Ix2;
|
||||
lambda = RefState.lambda;
|
||||
BE = RefState.BE;
|
||||
diffsq = RefState.diffsq;
|
||||
conv = RefState.conv;
|
||||
iter = RefState.iter;
|
||||
iter_Newton = RefState.iter_Newton;
|
||||
E = RefState.E;
|
||||
iK = RefState.iK;
|
||||
K = RefState.K;
|
||||
lnnorm = RefState.lnnorm;
|
||||
base_id = RefState.base_id;
|
||||
type_id = RefState.type_id;
|
||||
id = RefState.id;
|
||||
maxid = RefState.maxid;
|
||||
nparticles = RefState.nparticles;
|
||||
|
||||
sinhlambda = RefState.sinhlambda;
|
||||
coshlambda = RefState.coshlambda;
|
||||
tanhlambda = RefState.tanhlambda;
|
||||
}
|
||||
return(*this);
|
||||
}
|
||||
|
||||
// Member functions
|
||||
|
||||
void ODSLF_XXZ_Bethe_State::Set_Free_lambdas()
|
||||
{
|
||||
// Sets all the rapidities to the solutions of the BAEs without scattering terms
|
||||
|
||||
for (int i = 0; i < chain.Nstrings; ++i) {
|
||||
|
||||
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));
|
||||
|
||||
else ABACUSerror("Invalid parities in Set_Free_lambdas.");
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void ODSLF_XXZ_Bethe_State::Compute_sinhlambda()
|
||||
{
|
||||
for (int j = 0; j < chain.Nstrings; ++j) {
|
||||
|
||||
for (int alpha = 0; alpha < base[j]; ++alpha) sinhlambda[j][alpha] = sinh(lambda[j][alpha]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void ODSLF_XXZ_Bethe_State::Compute_coshlambda()
|
||||
{
|
||||
for (int j = 0; j < chain.Nstrings; ++j) {
|
||||
|
||||
for (int alpha = 0; alpha < base[j]; ++alpha) coshlambda[j][alpha] = cosh(lambda[j][alpha]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void ODSLF_XXZ_Bethe_State::Compute_tanhlambda()
|
||||
{
|
||||
for (int j = 0; j < chain.Nstrings; ++j) {
|
||||
|
||||
for (int alpha = 0; alpha < base[j]; ++alpha) tanhlambda[j][alpha] = tanh(lambda[j][alpha]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
bool ODSLF_XXZ_Bethe_State::Check_Admissibility(char option)
|
||||
{
|
||||
// This function checks the admissibility of the Ix2's of a state:
|
||||
// returns false if there are higher strings with Ix2 = 0, a totally symmetric distribution of I's at each level,
|
||||
// and strings of equal length modulo 2 and parity with Ix2 = 0, meaning at least two equal roots in BAE.
|
||||
|
||||
bool answer = true;
|
||||
Vect<bool> Zero_at_level(false, chain.Nstrings); // whether there exists an Ix2 == 0 at a given level
|
||||
|
||||
bool higher_string_on_zero = false;
|
||||
for (int j = 0; j < chain.Nstrings; ++j) {
|
||||
// The following line puts answer to true if there is at least one higher string with zero Ix2
|
||||
for (int alpha = 0; alpha < base[j]; ++alpha) if ((Ix2[j][alpha] == 0) && (chain.Str_L[j] >= 2))
|
||||
higher_string_on_zero = true;
|
||||
for (int alpha = 0; alpha < base[j]; ++alpha) if (Ix2[j][alpha] == 0) Zero_at_level[j] = true;
|
||||
// NOTE: if base[j] == 0, Zero_at_level[j] remains false.
|
||||
}
|
||||
|
||||
// check symmetry of Ix2 at each level, if there exists a potentially risky Ix2...
|
||||
|
||||
bool symmetric_state = (*this).Check_Symmetry();
|
||||
|
||||
bool string_coincidence = false;
|
||||
for (int j1 = 0; j1 < chain.Nstrings; ++j1) {
|
||||
for (int j2 = j1 + 1; j2 < chain.Nstrings; ++j2)
|
||||
if (Zero_at_level[j1] && Zero_at_level[j2] && (chain.par[j1] == chain.par[j2])
|
||||
&& (!((chain.Str_L[j1] + chain.Str_L[j2])%2)))
|
||||
string_coincidence = true;
|
||||
}
|
||||
|
||||
bool M_odd_and_onep_on_zero = false;
|
||||
if (option == 'z') { // for Sz, if M is odd, exclude symmetric states with a 1+ on zero
|
||||
// (zero rapidities in left and right states, so FF det not defined).
|
||||
bool is_ground_state = base.Nrap[0] == base.Mdown && Ix2[0][0] == -(base.Mdown - 1)
|
||||
&& Ix2[0][base.Mdown-1] == base.Mdown - 1;
|
||||
if (Zero_at_level[0] && (base.Mdown % 2) && !is_ground_state) M_odd_and_onep_on_zero = true;
|
||||
}
|
||||
|
||||
bool onep_onem_on_zero = false;
|
||||
if (option == 'm' || option == 'p') { // for Smin, we also exclude symmetric states with 1+ and 1- strings on zero
|
||||
if (Zero_at_level[0] && Zero_at_level[1]) onep_onem_on_zero = true;
|
||||
}
|
||||
|
||||
answer = !(symmetric_state && (higher_string_on_zero || string_coincidence
|
||||
|| onep_onem_on_zero || M_odd_and_onep_on_zero));
|
||||
|
||||
// Now check that no Ix2 is equal to +N (since we take -N into account, and I + N == I by periodicity of exp)
|
||||
|
||||
for (int j = 0; j < chain.Nstrings; ++j)
|
||||
for (int alpha = 0; alpha < base[j]; ++alpha)
|
||||
if ((Ix2[j][alpha] < -chain.Nsites) || (Ix2[j][alpha] >= chain.Nsites)) answer = false;
|
||||
|
||||
if (!answer) {
|
||||
E = 0.0;
|
||||
K = 0.0;
|
||||
conv = 0;
|
||||
iter = 0;
|
||||
iter_Newton = 0;
|
||||
lnnorm = -100.0;
|
||||
}
|
||||
|
||||
return(answer); // answer == true: nothing wrong with this Ix2_config
|
||||
}
|
||||
|
||||
void ODSLF_XXZ_Bethe_State::Compute_BE (int j, int alpha)
|
||||
{
|
||||
tanhlambda[j][alpha] = tanh(lambda[j][alpha]);
|
||||
|
||||
DP sumtheta = 0.0;
|
||||
|
||||
for (int k = 0; k < chain.Nstrings; ++k)
|
||||
for (int beta = 0; beta < base[k]; ++beta) {
|
||||
if ((chain.Str_L[j] == 1) && (chain.Str_L[k] == 1))
|
||||
sumtheta += (chain.par[j] == chain.par[k])
|
||||
? atan((tanhlambda[j][alpha] - tanhlambda[k][beta])
|
||||
/((1.0 - tanhlambda[j][alpha] * tanhlambda[k][beta]) * chain.ta_n_anis_over_2[2]))
|
||||
: - atan(((tanhlambda[j][alpha] - tanhlambda[k][beta])
|
||||
/(1.0 - tanhlambda[j][alpha] * tanhlambda[k][beta])) * chain.ta_n_anis_over_2[2]) ;
|
||||
else sumtheta += 0.5 * 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;
|
||||
|
||||
}
|
||||
|
||||
void ODSLF_XXZ_Bethe_State::Compute_BE ()
|
||||
{
|
||||
// Fills in the BE members with the value of the Bethe equations.
|
||||
|
||||
(*this).Compute_tanhlambda();
|
||||
|
||||
DP sumtheta = 0.0;
|
||||
|
||||
for (int j = 0; j < chain.Nstrings; ++j)
|
||||
for (int alpha = 0; alpha < base[j]; ++alpha) {
|
||||
|
||||
sumtheta = 0.0;
|
||||
for (int k = 0; k < chain.Nstrings; ++k)
|
||||
for (int beta = 0; beta < base[k]; ++beta) {
|
||||
if ((chain.Str_L[j] == 1) && (chain.Str_L[k] == 1))
|
||||
sumtheta += (chain.par[j] == chain.par[k])
|
||||
? atan((tanhlambda[j][alpha] - tanhlambda[k][beta])
|
||||
/((1.0 - tanhlambda[j][alpha] * tanhlambda[k][beta]) * chain.ta_n_anis_over_2[2]))
|
||||
: - atan(((tanhlambda[j][alpha] - tanhlambda[k][beta])
|
||||
/(1.0 - tanhlambda[j][alpha] * tanhlambda[k][beta])) * chain.ta_n_anis_over_2[2]) ;
|
||||
else sumtheta += 0.5 * 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;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
DP ODSLF_XXZ_Bethe_State::Iterate_BAE (int j, int alpha)
|
||||
{
|
||||
// Returns a new iteration value for lambda[j][alpha] given tanhlambda and BE Lambdas
|
||||
// Assumes that tanhlambda[][] and BE[][] have been computed.
|
||||
|
||||
DP new_lambda = 0.0;
|
||||
DP arg = 0.0;
|
||||
|
||||
if (chain.par[j] == 1) arg = chain.ta_n_anis_over_2[chain.Str_L[j]]
|
||||
* tan(0.5 *
|
||||
//(PI * Ix2[j][alpha] + sumtheta)/chain.Nsites
|
||||
(2.0 * atan(tanhlambda[j][alpha]/chain.ta_n_anis_over_2[chain.Str_L[j]]) - BE[j][alpha])
|
||||
);
|
||||
|
||||
else if (chain.par[j] == -1)
|
||||
arg = -tan(0.5 *
|
||||
(-2.0 * atan(tanhlambda[j][alpha] * chain.ta_n_anis_over_2[chain.Str_L[j]]) - BE[j][alpha]))
|
||||
/chain.ta_n_anis_over_2[chain.Str_L[j]];
|
||||
|
||||
if (fabs(arg) < 1.0) {
|
||||
new_lambda = atanh(arg);
|
||||
}
|
||||
|
||||
else {
|
||||
new_lambda = lambda[j][alpha]; // back to drawing board...
|
||||
int block = 0; // counter to prevent runaway while loop
|
||||
DP new_tanhlambda = 0.0;
|
||||
DP sumtheta = 0.0;
|
||||
arg = 10.0; // reset value to start while loop
|
||||
while ((fabs(arg) > 1.0) && (block++ < 100)) { // recompute the diverging root on its own...
|
||||
new_lambda *= 1.01; // try to go slowly towards infinity...
|
||||
new_tanhlambda = tanh(new_lambda);
|
||||
sumtheta = 0.0;
|
||||
for (int k = 0; k < chain.Nstrings; ++k) {
|
||||
for (int beta = 0; beta < base[k]; ++beta)
|
||||
if ((chain.Str_L[j] == 1) && (chain.Str_L[k] == 1))
|
||||
sumtheta += (chain.par[j] == chain.par[k])
|
||||
? atan((new_tanhlambda - tanhlambda[k][beta])
|
||||
/((1.0 - new_tanhlambda * tanhlambda[k][beta]) * chain.ta_n_anis_over_2[2]))
|
||||
: - atan(((new_tanhlambda - tanhlambda[k][beta])
|
||||
/(1.0 - new_tanhlambda * tanhlambda[k][beta])) * chain.ta_n_anis_over_2[2]) ;
|
||||
else sumtheta += 0.5 * 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);
|
||||
|
||||
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.");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return(new_lambda);
|
||||
}
|
||||
|
||||
bool ODSLF_XXZ_Bethe_State::Check_Rapidities()
|
||||
{
|
||||
bool nonan = true;
|
||||
|
||||
for (int j = 0; j < chain.Nstrings; ++j)
|
||||
for (int alpha = 0; alpha < base[j]; ++alpha) nonan *= !is_nan(lambda[j][alpha]);
|
||||
|
||||
return nonan;
|
||||
}
|
||||
|
||||
void ODSLF_XXZ_Bethe_State::Compute_Energy ()
|
||||
{
|
||||
DP sum = 0.0;
|
||||
|
||||
for (int j = 0; j < chain.Nstrings; ++j) {
|
||||
for (int alpha = 0; alpha < base[j]; ++alpha) {
|
||||
sum += sin(chain.Str_L[j] * chain.anis)
|
||||
/ (chain.par[j] * cosh(2.0 * lambda[j][alpha]) - cos(chain.Str_L[j] * chain.anis));
|
||||
}
|
||||
}
|
||||
|
||||
sum *= - chain.J * sin(chain.anis);
|
||||
|
||||
E = sum;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void ODSLF_XXZ_Bethe_State::Build_Reduced_Gaudin_Matrix (SQMat<complex<DP> >& Gaudin_Red)
|
||||
{
|
||||
|
||||
if (Gaudin_Red.size() != base.Nraptot) ABACUSerror("Passing matrix of wrong size in Build_Reduced_Gaudin_Matrix.");
|
||||
|
||||
int index_jalpha;
|
||||
int index_kbeta;
|
||||
|
||||
DP sum_hbar_XXZ = 0.0;
|
||||
|
||||
DP sinzetasq = pow(sin(chain.anis), 2.0);
|
||||
|
||||
(*this).Compute_sinhlambda();
|
||||
(*this).Compute_coshlambda();
|
||||
|
||||
index_jalpha = 0;
|
||||
for (int j = 0; j < chain.Nstrings; ++j) {
|
||||
for (int alpha = 0; alpha < base[j]; ++alpha) {
|
||||
index_kbeta = 0;
|
||||
for (int k = 0; k < chain.Nstrings; ++k) {
|
||||
for (int beta = 0; beta < base[k]; ++beta) {
|
||||
|
||||
if ((j == k) && (alpha == beta)) {
|
||||
|
||||
sum_hbar_XXZ = 0.0;
|
||||
|
||||
for (int kp = 0; kp < chain.Nstrings; ++kp) {
|
||||
for (int betap = 0; betap < base[kp]; ++betap) {
|
||||
if (!((j == kp) && (alpha == betap)))
|
||||
sum_hbar_XXZ
|
||||
+= 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);
|
||||
}
|
||||
|
||||
else {
|
||||
if ((chain.Str_L[j] == 1) && (chain.Str_L[k] == 1))
|
||||
Gaudin_Red[index_jalpha][index_kbeta] =
|
||||
complex<DP> ((chain.par[j] * chain.par[k] == 1)
|
||||
? chain.si_n_anis_over_2[4]
|
||||
/(pow(sinhlambda[j][alpha] * coshlambda[k][beta]
|
||||
- coshlambda[j][alpha] * sinhlambda[k][beta], 2.0) + sinzetasq)
|
||||
: chain.si_n_anis_over_2[4]
|
||||
/(-pow(coshlambda[j][alpha] * coshlambda[k][beta]
|
||||
- sinhlambda[j][alpha] * sinhlambda[k][beta], 2.0) + sinzetasq) );
|
||||
else
|
||||
Gaudin_Red[index_jalpha][index_kbeta] =
|
||||
complex<DP> (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++;
|
||||
}
|
||||
}
|
||||
index_jalpha++;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// ****************************************************************************************************
|
||||
|
||||
// non-member functions
|
||||
|
||||
inline DP ODSLF_fbar_XXZ (DP tanhlambda, int par, DP tannzetaover2)
|
||||
{
|
||||
DP result = 0.0;
|
||||
|
||||
if (par == 1) result = 2.0 * atan(tanhlambda/tannzetaover2);
|
||||
|
||||
else if (par == -1) result = -2.0 * atan(tanhlambda * tannzetaover2);
|
||||
|
||||
else ABACUSerror("Faulty parity in ODSLF_fbar_XXZ.");
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
DP ODSLF_Theta_XXZ (DP tanhlambda, int nj, int nk, int parj, int park, DP* tannzetaover2)
|
||||
{
|
||||
DP result = 0.0;
|
||||
|
||||
if ((nj == 1) && (nk == 1)) result = ODSLF_fbar_XXZ(tanhlambda, parj*park, tannzetaover2[2]);
|
||||
|
||||
else {
|
||||
|
||||
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]);
|
||||
|
||||
result += ODSLF_fbar_XXZ(tanhlambda, parj*park, tannzetaover2[nj + nk]);
|
||||
}
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
DP ODSLF_hbar_XXZ (DP lambda, int n, int par, DP* si_n_anis_over_2)
|
||||
{
|
||||
DP result = 0.0;
|
||||
|
||||
if (par == 1) result = si_n_anis_over_2[2*n]/(pow(sinh(lambda), 2.0) + pow(si_n_anis_over_2[n], 2.0));
|
||||
|
||||
else if (par == -1) result = si_n_anis_over_2[2*n]/(-pow(cosh(lambda), 2.0) + pow(si_n_anis_over_2[n], 2.0));
|
||||
|
||||
else ABACUSerror("Faulty parity in ODSLF_hbar_XXZ.");
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
DP ODSLF_ddlambda_Theta_XXZ (DP lambda, int nj, int nk, int parj, int park, DP* si_n_anis_over_2)
|
||||
{
|
||||
DP result = (nj == nk) ? 0.0 : 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);
|
||||
|
||||
result += ODSLF_hbar_XXZ(lambda, nj + nk, parj*park, si_n_anis_over_2);
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
|
||||
} // namespace ABACUS
|
||||
@@ -0,0 +1,82 @@
|
||||
/**********************************************************
|
||||
|
||||
This software is part of J.-S. Caux's ABACUS library.
|
||||
|
||||
Copyright (c) J.-S. Caux.
|
||||
|
||||
-----------------------------------------------------------
|
||||
|
||||
File: Smoothen_ODSLF_DSF.cc
|
||||
|
||||
Purpose: produces .dsf and .ssf files from a .raw file
|
||||
|
||||
***********************************************************/
|
||||
|
||||
#include "ABACUS.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace ABACUS;
|
||||
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
if (argc != 10 && argc != 11) { // Print out instructions
|
||||
cout << "Usage of Smoothen_ODSLF_DSF executable: " << endl << endl;
|
||||
cout << "Provide arguments using one of the following options:" << endl << endl;
|
||||
cout << "1) (for general momenta) whichDSF Delta N M iKmin iKmax ommin ommax Nom gwidth" << endl << endl;
|
||||
cout << "2) (for fixed momentum) whichDSF Delta N M iKneeded ommin ommax Nom gwidth" << endl << endl;
|
||||
}
|
||||
|
||||
else if (argc == 11) { // !fixed_iK
|
||||
char whichDSF = *argv[1];
|
||||
DP Delta = atof(argv[2]);
|
||||
int N = atoi(argv[3]);
|
||||
int M = atoi(argv[4]);
|
||||
int iKmin = atoi(argv[5]);
|
||||
int iKmax = atoi(argv[6]);
|
||||
DP ommin = atof(argv[7]);
|
||||
DP ommax = atof(argv[8]);
|
||||
int Nom = atoi(argv[9]);
|
||||
DP gwidth = atof(argv[10]);
|
||||
|
||||
stringstream filenameprefix;
|
||||
ODSLF_Data_File_Name (filenameprefix, whichDSF, Delta, N, M, iKmin, iKmax, 0.0, 0);
|
||||
string prefix = filenameprefix.str();
|
||||
|
||||
DP normalization = twoPI;
|
||||
|
||||
cout << "Smoothing: sumcheck = " << Smoothen_RAW_into_SF (prefix, iKmin, iKmax, 0.0, ommin, ommax,
|
||||
Nom, gwidth, normalization) << endl;
|
||||
|
||||
Write_K_File (N, iKmin, iKmax);
|
||||
Write_Omega_File (Nom, ommin, ommax);
|
||||
|
||||
}
|
||||
|
||||
else if (argc == 10) { // fixed_iK
|
||||
char whichDSF = *argv[1];
|
||||
DP Delta = atof(argv[2]);
|
||||
int N = atoi(argv[3]);
|
||||
int M = atoi(argv[4]);
|
||||
int iKneeded = atoi(argv[5]);
|
||||
DP ommin = atof(argv[6]);
|
||||
DP ommax = atof(argv[7]);
|
||||
int Nom = atoi(argv[8]);
|
||||
DP gwidth = atof(argv[9]);
|
||||
|
||||
bool fixed_iK = true;
|
||||
|
||||
stringstream filenameprefix;
|
||||
Data_File_Name (filenameprefix, whichDSF, Delta, N, M, fixed_iK, iKneeded, 0.0, 0);
|
||||
string prefix = filenameprefix.str();
|
||||
|
||||
DP normalization = twoPI;
|
||||
int iKmin = iKneeded;
|
||||
int iKmax = iKneeded;
|
||||
|
||||
cout << "Smoothing: sumcheck = " << Smoothen_RAW_into_SF (prefix, iKmin, iKmax, 0.0, ommin, ommax,
|
||||
Nom, gwidth, normalization) << endl;
|
||||
}
|
||||
|
||||
else ABACUSerror("Wrong number of arguments to Smoothen_Heis_DSF executable.");
|
||||
}
|
||||
@@ -0,0 +1,334 @@
|
||||
/**********************************************************
|
||||
|
||||
This software is part of J.-S. Caux's ABACUS library.
|
||||
|
||||
Copyright (c) J.-S. Caux.
|
||||
|
||||
-----------------------------------------------------------
|
||||
|
||||
File: ln_Smin_ME_ODSLF_XXZ.cc
|
||||
|
||||
Purpose: S^- matrix element
|
||||
|
||||
***********************************************************/
|
||||
|
||||
#include "ABACUS.h"
|
||||
|
||||
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;
|
||||
|
||||
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];
|
||||
|
||||
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))) {
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
}}}
|
||||
|
||||
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 *= ((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));
|
||||
}
|
||||
}
|
||||
|
||||
DP logabssinzeta = log(abs(sin(A.chain.anis)));
|
||||
|
||||
// Define regularized products in prefactors
|
||||
|
||||
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
|
||||
|
||||
ln_prod3 -= A.base.Mdown * 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);
|
||||
}
|
||||
|
||||
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) {
|
||||
|
||||
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));
|
||||
|
||||
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) {
|
||||
|
||||
// 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);
|
||||
|
||||
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;
|
||||
|
||||
} // if (B.chain.Str_L == 1)
|
||||
|
||||
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]) {
|
||||
|
||||
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);
|
||||
|
||||
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 += (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)
|
||||
|
||||
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]);
|
||||
|
||||
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_Fn_F(B, k, beta, jsum - 1)) + logabssinzeta);
|
||||
// include all string contributions F_B_0 in this term
|
||||
|
||||
Hm[index_a][index_b] = prod_num * sum1;
|
||||
|
||||
} // else if (b == B.chain.Str_L[k])
|
||||
} // else
|
||||
|
||||
index_b++;
|
||||
}}} // sums over k, beta, b
|
||||
|
||||
// now define the elements Hm[a][M]
|
||||
|
||||
Hm[index_a][B.base.Mdown] = one_over_A_sinhlambda_sq_plus_sinzetaover2sq;
|
||||
|
||||
index_a++;
|
||||
}}} // sums over j, alpha, a
|
||||
|
||||
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(0.5 * ln_ME_sq); // Return ME, not MEsq
|
||||
|
||||
}
|
||||
|
||||
} // namespace ABACUS
|
||||
@@ -0,0 +1,341 @@
|
||||
/**********************************************************
|
||||
|
||||
This software is part of J.-S. Caux's ABACUS library.
|
||||
|
||||
Copyright (c) J.-S. Caux.
|
||||
|
||||
-----------------------------------------------------------
|
||||
|
||||
File: ln_Sz_ME_ODSLF_XXZ.cc
|
||||
|
||||
Purpose: S^z matrix element
|
||||
|
||||
***********************************************************/
|
||||
|
||||
#include "ABACUS.h"
|
||||
|
||||
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;
|
||||
|
||||
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];
|
||||
|
||||
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))) {
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
}}}
|
||||
|
||||
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 *= ((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));
|
||||
}
|
||||
}
|
||||
|
||||
DP logabssinzeta = log(abs(sin(A.chain.anis)));
|
||||
|
||||
// Define regularized products in prefactors
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
ln_prod3 -= A.base.Mdown * 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);
|
||||
}
|
||||
|
||||
ln_prod4 -= B.base.Mdown * log(abs(sin(B.chain.anis)));
|
||||
|
||||
// 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) {
|
||||
|
||||
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));
|
||||
|
||||
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) {
|
||||
|
||||
// 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);
|
||||
|
||||
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
|
||||
* exp(II*im_ln_Fn_F_B_0[k][beta] + logabssinzeta);
|
||||
|
||||
}
|
||||
|
||||
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]) {
|
||||
|
||||
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);
|
||||
|
||||
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 += (-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)
|
||||
|
||||
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;
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
} // else if (b == B.chain.Str_L[k])
|
||||
} // else
|
||||
|
||||
index_b++;
|
||||
}}} // sums over k, beta, b
|
||||
index_a++;
|
||||
}}} // sums over j, alpha, a
|
||||
|
||||
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 * re_ln_det - A.lnnorm - B.lnnorm;
|
||||
|
||||
return(0.5 * ln_ME_sq); // Return ME, not MEsq
|
||||
|
||||
}
|
||||
|
||||
} // namespace ABACUS
|
||||
Reference in New Issue
Block a user