Import ABACUS++G_8 code; cleanup files; new README

This commit is contained in:
J.-S. Caux
2018-02-09 17:34:05 +01:00
parent 61084ef3b3
commit 103cbe84d6
172 changed files with 46745 additions and 0 deletions
+307
View File
@@ -0,0 +1,307 @@
/**********************************************************
This software is part of J.-S. Caux's ABACUS++ library.
-----------------------------------------------------------
File: src/BETHE/Base.cc
Purpose: defines functions in Base class,
providing a unified base object for all
Bethe Ansatz integrable models.
***********************************************************/
#include "JSC.h"
using namespace std;
namespace JSC {
// 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];
}
}
/*
// DEPRECATED
Base::Base (const Heis_Chain& RefChain, int M)
: Charge(M), Nrap(Vect<int>(RefChain.Nstrings)), Nraptot(0), Ix2_infty(Vect<DP>(RefChain.Nstrings)), Ix2_max(Vect<int>(RefChain.Nstrings))
{
for (int i = 0; i < RefChain.Nstrings; ++i) Nrap[i] = 0;
Nrap[0] = M;
Nraptot = 0;
for (int i = 0; i < RefChain.Nstrings; ++i) Nraptot += Nrap[i];
// The id of this is zero by definition
id = 0LL;
// Now compute the Ix2_infty numbers
(*this).Compute_Ix2_limits(RefChain);
}
*/
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()) cout << "error: Nstrings = " << RefChain.Nstrings << "\tNrap.size = " << Nrapidities.size() << endl;
if (RefChain.Nstrings != Nrapidities.size()) JSCerror("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;
//id = id_ref;
//cout << "In Base constructor: id_ref = " << id_ref << " and Nrapidities = " << Nrap << endl;
// Check consistency of Nrapidities vector with RefChain
//if (RefChain.Nstrings != Nrap.size()) JSCerror("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];
// 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 < JSC::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 * JSC::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 * JSC::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;
}
// Fudge, for strings:
//if (RefChain.Str_L[j] >= 1) Ix2_max[j] += 2;
//Ix2_max[j] += 2;
}
} // if XXZ_gpd
}
} // namespace JSC
+29
View File
@@ -0,0 +1,29 @@
/**********************************************************
This software is part of J.-S. Caux's ABACUS++ library.
Copyright (c).
-----------------------------------------------------------
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.
***********************************************************/
#include "JSC.h"
using namespace std;
namespace JSC {
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 JSC
+277
View File
@@ -0,0 +1,277 @@
/**********************************************************
This software is part of J.-S. Caux's ABACUS++ library.
Copyright (c) 2006-9.
-----------------------------------------------------------
File: src/BETHE/Offsets.cc
Purpose: defines functions in Offsets class.
Last modified: 19/10/2009
***********************************************************/
#include "JSC.h"
using namespace std;
namespace JSC {
// 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) JSCerror("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) JSCerror("Wrong nparticles.size in Offsets constructor.");
//if (base.Nrap[0] != (nparticles[3] + nparticles[2] + base.Mdown - nparticles[0] - nparticles[1])) JSCerror("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;
JSCerror("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;
JSCerror("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) JSCerror("nparticles[0] too large in Offsets constructor.");
if (nparticles[1] > base.Nrap[0]/2) JSCerror("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) JSCerror("nparticles[2] too large in Offsets constructor.");
if (nparticles[3] > (base.Ix2_max[0] - base.Nrap[0] + 1)/2) JSCerror("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;
JSCerror("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 < JSC::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 = JSC::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 < JSC::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 = JSC::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;
JSCerror("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)) JSCerror("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 JSC
+89
View File
@@ -0,0 +1,89 @@
/****************************************************************
This software is part of J.-S. Caux's C++ library.
Copyright (c) 2006.
-----------------------------------------------------------
Combinatorics.cc
Defines all class related to combinatorics.
LAST MODIFIED: 04/09/06
******************************************************************/
#include "JSC.h"
using namespace std;
namespace JSC {
Choose_Table::Choose_Table ()
: Npower(0ULL), Npowerp1(1ULL), table(new unsigned long long int[1])
{
table[0] = 1ULL;
}
Choose_Table::Choose_Table (int Npower_ref)
: Npower(Npower_ref), Npowerp1(Npower_ref + 1ULL)
{
dim = Npowerp1 * Npowerp1;
// We can only go up to ULL_MAX:
if (log(DP(ULONG_LONG_MAX)) < DP(Npowerp1) * log(2.0))
JSCerror("Choose_Table: too large to contruct.");
table = new unsigned long long int[dim];
(*this).Fill_table();
}
void Choose_Table::Fill_table()
{
table[0] = 1ULL;
int n,m;
for (n = 0; n <= Npower; ++n) {
table[Npowerp1 * n] = 1ULL;
for (m = 1; m < n; ++m) {
table[Npowerp1 * n + m] = table[Npowerp1 * (n-1) + m - 1] + table[Npowerp1 * (n-1) + m];
}
table[Npowerp1 * n + n] = 1ULL;
for (m = n+1; m <= Npower; ++m)
table[Npowerp1 * n + m] = 0ULL;
}
}
int Choose_Table::power()
{
return(Npower);
}
unsigned long long int Choose_Table::choose(int N, int M)
{
if (N < 0 || N > Npower) JSCerror("N out of bounds in choose(N,M).");
if (M < 0 || M > Npower) JSCerror("M out of bounds in choose(N,M).");
return(table[Npowerp1 * N + M]);
}
std::ostream& operator<< (std::ostream& s, Choose_Table& Ref_table)
{
s << endl;
for (int n = 0; n <= Ref_table.power(); ++n) {
for (int m = 0; m <= Ref_table.power(); ++m)
s << Ref_table.choose(n, m) << " ";
s << endl;
}
s << endl;
return(s);
}
Choose_Table::~Choose_Table()
{
delete[] table;
}
} // namespace JSC
+43
View File
@@ -0,0 +1,43 @@
/**********************************************************
This software is part of J.-S. Caux's ABACUS library.
Copyright (c).
-----------------------------------------------------------
File: 2CBG_ThLim.cc
Purpose: solves the TBA equations for the 2-component Bose gas
***********************************************************/
#include "JSC.h"
using namespace std;
using namespace JSC;
int main(int argc, const char* argv[])
{
if (argc != 7) JSCerror("Wrong number of arguments to 2CBG_ThLim executable. Use c(best to set to 1), mu, Omega, kBT, TT(minutes), bool Save_data (0 == false).");
DP c_int = atof(argv[1]);
DP mu = atof(argv[2]);
DP Omega = atof(argv[3]);
DP kBT = atof(argv[4]);
int Max_Secs = 60 * atoi(argv[5]);
bool Save_data = bool(atoi(argv[6]));
if (c_int <= 0.0) JSCerror("Give a strictly positive c.");
if (Omega <= 0.0) JSCerror("Give a strictly positive Omega, otherwise the algorithm cannot converge.");
if (kBT <= 0.0) JSCerror("Negative T ? You must be a string theorist.");
if (Max_Secs < 10) JSCerror("Give more time.");
//cout << "Read c_int = " << c_int << "\tmu = " << mu << "\tOmega = " << Omega << "\tkBT = " << kBT << "\tMax_Secs = " << Max_Secs << endl;
Solve_2CBG_TBAE_via_refinements (c_int, mu, Omega, kBT, Max_Secs, Save_data);
return(0);
}
+84
View File
@@ -0,0 +1,84 @@
/**********************************************************
This software is part of J.-S. Caux's ABACUS++ library.
Copyright (c)
-----------------------------------------------------------
File: Analyze_RAW_File.cc
Purpose: give some statistics for the matrix element distribution in a raw file.
***********************************************************/
#include "JSC.h"
using namespace std;
using namespace JSC;
int main(int argc, char* argv[])
{
if (argc != 4) {
cout << "Argument needed: rawfile, iKmin, iKmax." << endl;
JSCerror("");
}
const char* rawfilename = argv[1];
int iKmin = atoi(argv[2]);
int iKmax = atoi(argv[3]);
ifstream RAW_infile;
RAW_infile.open(rawfilename);
if (RAW_infile.fail()) {
cout << rawfilename << endl;
JSCerror("Could not open RAW_infile... ");
}
DP omega;
int iK;
DP FF;
//int conv;
DP dev;
string label;
DP sumFFsq = 0.0;
DP sumFF4 = 0.0;
DP sumFFsqlnFFsq = 0.0;
Vect<int> nFFatK (0, iKmax - iKmin + 1);
Vect<DP> sumFFsqatK (0.0, iKmax - iKmin + 1);
Vect<DP> sumFF4atK (0.0, iKmax - iKmin + 1);
Vect<DP> sumFFsqlnFFsqatK (0.0, iKmax - iKmin + 1);
int nread = 0;
while (RAW_infile.peek() != EOF) {
RAW_infile >> omega >> iK >> FF >> dev >> label;
nread++;
sumFFsq += FF*FF;
sumFF4 += FF*FF*FF*FF;
sumFFsqlnFFsq += FF*FF * log(FF*FF);
if (iK >= iKmin && iK <= iKmax) {
nFFatK[iK-iKmin] += 1;
sumFFsqatK[iK - iKmin] += FF*FF;
sumFF4atK[iK - iKmin] += FF*FF*FF*FF;
sumFFsqlnFFsqatK[iK - iKmin] += FF*FF * log(FF*FF);
}
}
RAW_infile.close();
cout << "Inverse participation ratio: \t" << sumFF4/(sumFFsq*sumFFsq) << endl;
// Entropy is -sum (FFsq/sumFFsq) * ln(FFsq/sumFFsq) = sum (FFsq lnFFsq - FFsq ln sumFFsq)/sumFFsq
cout << "Entropy: \t" << -(sumFFsqlnFFsq - sumFFsq * log(sumFFsq))/sumFFsq << endl;
cout << "iK\tnFFatK\tIPRatiK\tentropyatiK:" << endl;
for (int iK = iKmin; iK <= iKmax; ++iK) cout << iK << "\t" << nFFatK[iK-iKmin] << "\t" << sumFF4atK[iK-iKmin]/(sumFFsqatK[iK - iKmin] * sumFFsqatK[iK - iKmin]) << "\t" << -(sumFFsqlnFFsqatK[iK-iKmin] - sumFFsqatK[iK-iKmin] * log(sumFFsqatK[iK-iKmin]))/sumFFsqatK[iK-iKmin]<< endl;
return(0);
}
+147
View File
@@ -0,0 +1,147 @@
/**********************************************************
This software is part of J.-S. Caux's ABACUS library.
Copyright (c).
-----------------------------------------------------------
File: Check_RAW_File.cc
Purpose: from a .raw_srt file, check that nonzero momentum states
appear (only) twice, and zero momentum ones (only) once.
***********************************************************/
#include "JSC.h"
using namespace std;
using namespace JSC;
int main(int argc, char* argv[])
{
if (argc != 7) { // print out some instructions
cout << "Usage of Check_RAW_File executable: provide the following arguments:" << endl;
cout << "(sorted!) raw file name, iKmin, iKmax, sympoint, FFmin, check_option." << endl;
cout << "Check option: 0 == check for missing states, 1 == check for multiply-appearing states." << endl;
}
char* rawfilename = argv[1];
int iKmin = atoi(argv[2]);
int iKmax = atoi(argv[3]);
int sympoint = atoi(argv[4]);
DP FFmin = atof(argv[5]);
int check_option = atoi(argv[6]);
ifstream RAW_infile;
RAW_infile.open(rawfilename);
if (RAW_infile.fail()) {
cout << rawfilename << endl;
JSCerror("Could not open sorted RAW_infile... ");
}
DP omega_next, omega, omega_prev;
int iK_next, iK, iK_prev;
DP FF_next, FF, FF_prev;
//int conv_next, conv, conv_prev;
DP dev_next, dev, dev_prev;
string label_next, label, label_prev;
if (check_option > 1) {
FF = 0.0;
FF_prev = 0.0;
FF_next = 0.0;
FFmin = -1.0;
}
//RAW_infile >> omega >> iK >> FF >> conv >> label;
RAW_infile >> omega >> iK;
if (check_option <= 1) RAW_infile >> FF;
RAW_infile >> dev;
RAW_infile >> label;
//RAW_infile >> omega_next >> iK_next >> FF_next >> conv_next >> label_next;
RAW_infile >> omega_next >> iK_next;
if (check_option <= 1) RAW_infile >> FF_next;
RAW_infile >> dev_next;
RAW_infile >> label_next;
int line = 1;
char a;
while (fabs(FF) > FFmin && RAW_infile.peek() != EOF) {
//omega_prev = omega; iK_prev = iK; FF_prev = FF; conv_prev = conv; label_prev = label;
omega_prev = omega; iK_prev = iK; FF_prev = FF; dev_prev = dev; label_prev = label;
//omega = omega_next; iK = iK_next; FF = FF_next; conv = conv_next; label = label_next;
omega = omega_next; iK = iK_next; FF = FF_next; dev = dev_next; label = label_next;
//RAW_infile >> omega_next >> iK_next >> FF_next >> conv_next >> label_next;
RAW_infile >> omega_next >> iK_next;
if (check_option <= 1) RAW_infile >> FF_next; // for non-Z checks
RAW_infile >> dev_next;
RAW_infile >> label_next;
//cout << "checking line " << line << endl;
//cout << omega_prev << "\t" << iK_prev << "\t" << FF_prev << "\t" << label_prev << endl
// << omega << "\t" << iK << "\t" << FF << "\t" << label << endl
// << omega_next << "\t" << iK_next << "\t" << FF_next << "\t" << label_next << endl;
line++;
if (label.compare(label_next) == 0)
cout << "Identical labels around line " << line << ": " << endl
<< omega << "\t" << iK << "\t" << FF << "\t" << dev << "\t" << label << endl;
if (check_option == 0 && iK != 0 && iK != sympoint && iK >= iKmin && iK <= iKmax
&& fabs((FF - FF_prev)/(FF + FF_prev)) > 1.0e-6 && fabs((FF - FF_next)/(FF + FF_next)) > 1.0e-6) {
cout << "State missing around line " << line << ": " << endl
//<< omega_prev << "\t" << iK_prev << "\t" << FF_prev << "\t" << conv_prev << "\t" << label_prev << endl
<< omega_prev << "\t" << iK_prev << "\t" << FF_prev << "\t" << dev_prev << "\t" << label_prev << endl
//<< omega << "\t" << iK << "\t" << FF << "\t" << conv << "\t" << label << endl
<< omega << "\t" << iK << "\t" << FF << "\t" << dev << "\t" << label << endl
//<< omega_next << "\t" << iK_next << "\t" << FF_next << "\t" << conv_next << "\t" << label_next << endl;
<< omega_next << "\t" << iK_next << "\t" << FF_next << "\t" << dev_next << "\t" << label_next << endl;
cin >> a;
//break;
}
if (check_option == 1 && iK_prev == iK && iK == iK_next && fabs((omega - omega_prev)/(omega + omega_prev)) < 1.0e-8 && fabs((omega - omega_next)/(omega + omega_next)) < 1.0e-8 && fabs((FF - FF_prev)/(FF + FF_prev)) < 1.0e-8 && fabs((FF - FF_next)/(FF + FF_next)) < 1.0e-8) {
cout << "Triple state around line " << line << ": " << endl
//<< omega_prev << "\t" << iK_prev << "\t" << FF_prev << "\t" << conv_prev << "\t" << label_prev << endl
<< omega_prev << "\t" << iK_prev << "\t" << FF_prev << "\t" << dev_prev << "\t" << label_prev << endl
//<< omega << "\t" << iK << "\t" << FF << "\t" << conv << "\t" << label << endl
<< omega << "\t" << iK << "\t" << FF << "\t" << dev << "\t" << label << endl
//<< omega_next << "\t" << iK_next << "\t" << FF_next << "\t" << conv_next << "\t" << label_next << endl;
<< omega_next << "\t" << iK_next << "\t" << FF_next << "\t" << dev_next << "\t" << label_next << endl;
cin >> a;
}
if (check_option == 2 && iK != 0 && iK != sympoint && iK >= iKmin && iK <= iKmax
&& fabs((omega - omega_prev)/(omega + omega_prev)) > 1.0e-6 && fabs((omega - omega_next)/(omega + omega_next)) > 1.0e-6) {
cout << "State missing around line " << line << ": " << endl
<< omega_prev << "\t" << iK_prev << "\t" << dev_prev << "\t" << label_prev << endl
<< omega << "\t" << iK << "\t" << dev << "\t" << label << endl
<< omega_next << "\t" << iK_next << "\t" << dev_next << "\t" << label_next << endl;
cin >> a;
//break;
}
if (check_option == 3 && iK_prev == iK && iK == iK_next && fabs((omega - omega_prev)/(omega + omega_prev)) < 1.0e-8 && fabs((omega - omega_next)/(omega + omega_next)) < 1.0e-8) {
cout << "Triple state around line " << line << ": " << endl
<< omega_prev << "\t" << iK_prev << "\t" << dev_prev << "\t" << label_prev << endl
<< omega << "\t" << iK << "\t" << dev << "\t" << label << endl
<< omega_next << "\t" << iK_next << "\t" << dev_next << "\t" << label_next << endl;
cin >> a;
}
}
return(0);
}
+142
View File
@@ -0,0 +1,142 @@
/**********************************************************
This software is part of J.-S. Caux's ABACUS++ library.
Copyright (c)
-----------------------------------------------------------
File: Heis_DSF.cc
Purpose: main function for ABACUS++ for Heisenberg spin-1/2 chain
***********************************************************/
#include "JSC.h"
using namespace std;
using namespace JSC;
int main(int argc, char* argv[])
{
if (argc != 8) { // provide some info
cout << endl << "Welcome to ABACUS++\t(copyright J.-S. Caux)." << endl;
cout << endl << "Usage of Heis_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 << "Heis_DSF z 1.0 100 40 0 100 600 1.0 0" << endl << endl;
}
else if (argc == 8) { // !fixed_iK
int ctr = 1;
char whichDSF = *argv[ctr++];
DP Delta = atof(argv[ctr++]);
int N = atoi(argv[ctr++]);
int M = atoi(argv[ctr++]);
//int iKmin = atoi(argv[5]);
//int iKmax = atoi(argv[6]);
int Max_Secs = atoi(argv[ctr++]);
DP target_sumrule = atof(argv[ctr++]);
bool refine = (atoi(argv[ctr++]) == 1);
// We systematically scan over all momentum integers (to avoid problems with Brillouin folding
int iKmin = -1000*N;
int iKmax = 1000*N;
//Scan_Heis (whichDSF, Delta, N, M, iKmin, iKmax, Max_Secs, target_sumrule, refine, 0, 1);
Scan_Heis (whichDSF, Delta, N, M, iKmin, iKmax, Max_Secs, target_sumrule, refine);
}
// The argument given is the name of the standard args_Heis_DSF arguments file
/*
if (argc == 2) { // Used an input file to provide the arguments
if (strcmp(argv[1],"help") == 0) { // Output some instructions
cout << "Usage of Heis_DSF executable: " << endl;
cout << endl << "Provide arguments by either using one of the three following options:" << endl << endl;
cout << "1) via an argument file (see the template `args_Heis_DSF' in directory src/EXECS/), for example" << endl << endl;
cout << "Heis_DSF args_Heis_DSF" << endl << endl;
cout << "2) with arguments (for general momenta scan) whichDSF Delta N M iKmin iKmax Max_Secs refine, for example" << endl << endl;
cout << "Heis_DSF z 0.9 100 40 0 50 600 0" << endl << endl;
cout << "3) with arguments (for general momenta scan) whichDSF Delta N M iKneeded Max_Secs refine, for example" << endl << endl;
cout << "Heis_DSF z 0.9 100 40 20 600 0" << endl << endl;
}
else { // read argument file
ifstream argsfile;
argsfile.open(argv[1]);
if (argsfile.fail()) {
cout << argv[1] << endl;
JSCerror("Could not open arguments file.");
}
char junk[256];
while (argsfile.peek() == '#' || argsfile.peek() == '\t' || argsfile.peek() == ' ' || argsfile.peek() == '\n') argsfile.getline(junk, 256);
char whichDSF; argsfile >> whichDSF;
while (argsfile.peek() == '#' || argsfile.peek() == '\t' || argsfile.peek() == ' ' || argsfile.peek() == '\n') argsfile.getline(junk, 256);
DP Delta; argsfile >> Delta;
while (argsfile.peek() == '#' || argsfile.peek() == '\t' || argsfile.peek() == ' ' || argsfile.peek() == '\n') argsfile.getline(junk, 256);
int N; argsfile >> N;
while (argsfile.peek() == '#' || argsfile.peek() == '\t' || argsfile.peek() == ' ' || argsfile.peek() == '\n') argsfile.getline(junk, 256);
int M; argsfile >> M;
while (argsfile.peek() == '#' || argsfile.peek() == '\t' || argsfile.peek() == ' ' || argsfile.peek() == '\n') argsfile.getline(junk, 256);
//bool fixed_iK; argsfile >> fixed_iK;
//while (argsfile.peek() == '#' || argsfile.peek() == '\t' || argsfile.peek() == ' ' || argsfile.peek() == '\n') argsfile.getline(junk, 256);
//int iKneeded; argsfile >> iKneeded;
int iKmin, iKmax; argsfile >> iKmin >> iKmax;
while (argsfile.peek() == '#' || argsfile.peek() == '\t' || argsfile.peek() == ' ' || argsfile.peek() == '\n') argsfile.getline(junk, 256);
int Max_Secs; argsfile >> Max_Secs;
while (argsfile.peek() == '#' || argsfile.peek() == '\t' || argsfile.peek() == ' ' || argsfile.peek() == '\n') argsfile.getline(junk, 256);
bool refine; argsfile >> refine;
Scan_Heis (whichDSF, Delta, N, M, iKmin, iKmax, Max_Secs, refine);
}
} // if (argc == 2)
else if (argc == 8) { // 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]);
int Max_Secs = atoi(argv[6]);
bool refine = (atoi(argv[7]) == 1);
//Scan_Heis (whichDSF, Delta, N, M, iKneeded, Max_Secs, refine);
Scan_Heis (whichDSF, Delta, N, M, iKneeded, iKneeded, Max_Secs, refine);
}
else if (argc == 9) { // !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]);
bool refine = (atoi(argv[8]) == 1);
//Scan_Heis (whichDSF, Delta, N, M, iKneeded, Max_Secs, refine);
Scan_Heis (whichDSF, Delta, N, M, iKmin, iKmax, Max_Secs, refine);
}
else JSCerror("Wrong number of arguments to Heis_DSF executable.");
*/
return(0);
}
+133
View File
@@ -0,0 +1,133 @@
/**********************************************************
This software is part of J.-S. Caux's ABACUS++ library.
Copyright (c)
-----------------------------------------------------------
File: Heis_DSF_GeneralState.cc
Purpose: main function for ABACUS++ for Heisenberg spin-1/2 chain
***********************************************************/
#include "JSC.h"
using namespace std;
using namespace JSC;
int main(int argc, char* argv[])
{
if (argc != 9) { // provide some info
cout << endl << "Welcome to ABACUS++\t(copyright J.-S. Caux)." << endl;
cout << endl << "Usage of Heis_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 << "char* defaultScanStatename:\t\t file [].Ix2 contains the quantum numbers defining the AveragingState; used as defaultScanStatename" << 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;
}
else if (argc == 9) { // !fixed_iK
int ctr = 1;
char whichDSF = *argv[ctr++];
DP Delta = atof(argv[ctr++]);
int N = atoi(argv[ctr++]);
int M = atoi(argv[ctr++]);
char* Ix2filenameprefix = argv[ctr++];
//int iKmin = atoi(argv[5]);
//int iKmax = atoi(argv[6]);
int Max_Secs = atoi(argv[ctr++]);
DP target_sumrule = atof(argv[ctr++]);
bool refine = (atoi(argv[ctr++]) == 1);
// We systematically scan over all momentum integers (to avoid problems with Brillouin folding
int iKmin = -1000*N;
int iKmax = 1000*N;
// Read the Ix2 from the file:
// Format is:
// base_level, Nrap[base_level], \endl Ix2[base_level], repeat for all occupied base_levels...
ifstream Ix2_input_file;
stringstream filenamestrstream;
filenamestrstream << Ix2filenameprefix;
string defaultScanStatename = filenamestrstream.str();
filenamestrstream << ".Ix2";
string filenamestr = filenamestrstream.str();
const char* filename_Cstr = filenamestr.c_str();
Ix2_input_file.open(filename_Cstr);
if (Ix2_input_file.fail()) {
cout << filename_Cstr << endl;
JSCerror("Could not open Ix2 input file in Heis_DSF_GeneralState");
}
Heis_Chain chain(1.0, Delta, 0.0, N);
Vect<int> Nrap_read (0, chain.Nstrings);
int level = 0;
Vect<Vect<int> > Ix2_read (chain.Nstrings);
do {
Ix2_input_file >> level;
Ix2_input_file >> Nrap_read[level];
Ix2_read[level] = Vect<int> (Nrap_read[level]);
for (int alpha = 0; alpha < Nrap_read[level]; ++alpha) Ix2_input_file >> Ix2_read[level][alpha];
//cout << "Read level = " << level << "\tNrap_read[level] = " << Nrap_read[level] << endl;
//cout << "\tIx2_read[level] = " << Ix2_read[level] << endl;
} while (Ix2_input_file.peek() != EOF);
// Construct the Averaging State:
Heis_Base base (chain, Nrap_read);
int paralevel = 0;
Vect<int> rank; // dummy
Vect<int> nr_processors; // dummy
if (Delta > 0.0 && Delta < 1.0) {
XXZ_Bethe_State AveragingState (chain, base);
for (int il = 0; il < chain.Nstrings; ++il) {
if (Nrap_read[il] > 0) for (int alpha = 0; alpha < Nrap_read[il]; ++alpha) AveragingState.Ix2[il][alpha] = Ix2_read[il][alpha];
}
AveragingState.Set_Label_from_Ix2(AveragingState.Ix2);
AveragingState.Compute_All(true);
//cout << "AveragingState read from file: " << AveragingState << endl;
// Perform the scan:
Scan_Heis (whichDSF, AveragingState, defaultScanStatename, iKmin, iKmax, Max_Secs, target_sumrule, refine, paralevel, rank, nr_processors);
}
else if (Delta == 1.0) {
XXX_Bethe_State AveragingState (chain, base);
for (int il = 0; il < chain.Nstrings; ++il) {
for (int alpha = 0; alpha < Nrap_read[il]; ++alpha) AveragingState.Ix2[il][alpha] = Ix2_read[il][alpha];
}
AveragingState.Set_Label_from_Ix2(AveragingState.Ix2);
AveragingState.Compute_All(true);
// Perform the scan:
Scan_Heis (whichDSF, AveragingState, defaultScanStatename, iKmin, iKmax, Max_Secs, target_sumrule, refine, paralevel, rank, nr_processors);
}
else if (Delta > 1.0) {
XXZ_gpd_Bethe_State AveragingState (chain, base);
for (int il = 0; il < chain.Nstrings; ++il) {
for (int alpha = 0; alpha < Nrap_read[il]; ++alpha) AveragingState.Ix2[il][alpha] = Ix2_read[il][alpha];
}
AveragingState.Set_Label_from_Ix2(AveragingState.Ix2);
AveragingState.Compute_All(true);
// Perform the scan:
Scan_Heis (whichDSF, AveragingState, defaultScanStatename, iKmin, iKmax, Max_Secs, target_sumrule, refine, paralevel, rank, nr_processors);
}
}
return(0);
}
+120
View File
@@ -0,0 +1,120 @@
/**********************************************************
This software is part of J.-S. Caux's ABACUS library.
Copyright (c).
-----------------------------------------------------------
File: Heis_DSF_par.cc
Purpose: Parallel version of ABACUS++ using MPICH.
***********************************************************/
#include "JSC.h"
#include "mpi.h"
using namespace JSC;
int main(int argc, char *argv[])
{
char whichDSF;
DP Delta;
int N, M, iKneeded, iKmin, iKmax, Max_Secs;
DP target_sumrule = 1.0e+6; // effectively deactivated here
bool refine;
if (argc != 8) { // provide some info
cout << endl << "Welcome to ABACUS++\t(copyright J.-S. Caux)." << endl;
cout << endl << "Usage of Heis_DSF_par executable: " << endl;
cout << endl << "This function runs ABACUS++ in parallel mode, starting from a preexisting serial run (obtained using the Heis_DSF executable) using the same model parameters." << 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 << endl << "EXAMPLE: " << endl << endl;
cout << "mpiexec -np 8 Heis_DSF_par z 1.0 100 40 0 100 600" << endl << endl;
return(0);
}
else { // (argc == 8) correct nr of arguments
whichDSF = *argv[1];
Delta = atof(argv[2]);
N = atoi(argv[3]);
M = atoi(argv[4]);
iKmin = atoi(argv[5]);
iKmax = atoi(argv[6]);
Max_Secs = atoi(argv[7]);
}
DP supercycle_time = 600.0; // allotted time per supercycle
if (Max_Secs <= supercycle_time + 300) JSCerror("Please allow more time in Heis_DSF_par.");
MPI::Init(argc, argv);
DP tstart = MPI::Wtime();
int rank = MPI::COMM_WORLD.Get_rank();
int nr_processors = MPI::COMM_WORLD.Get_size();
if (nr_processors < 2) JSCerror("Give at least 2 processors to ABACUS++ parallel !");
refine = true;
// ASSUMPTION: preexisting files (raw, thr, ...) exist for the run.
// IMPORTANT PRECONDITION: no flags are being raised in General_Scan in parallel mode, so
// the preinitializing serial run must be extensive enough to have flagged all base/type s necessary.
DP tnow = MPI::Wtime();
while (tnow - tstart < Max_Secs - supercycle_time - 300) { // space for one more supercycle, + 5 minutes safety
//cout << "rank " << rank << " ready to prepare." << endl;
if (rank == 0)
// Split up thread list into chunks, one per processor
Prepare_Parallel_Scan_Heis (whichDSF, Delta, N, M, iKmin, iKmax, nr_processors);
//cout << "rank " << rank << " done preparing, ready to scan." << endl;
// Barrier synchronization, to make sure other processes wait for process of rank 0
// to have finished splitting up the thr file into pieces before starting:
MPI_Barrier (MPI::COMM_WORLD);
// then everybody gets going on their own chunk !
Scan_Heis (whichDSF, Delta, N, M, iKmin, iKmax,
supercycle_time, target_sumrule, refine, rank, nr_processors);
//cout << "rank " << rank << " finished scanning, reached wrapup stage." << endl;
// Another barrier synchronization
MPI_Barrier (MPI::COMM_WORLD);
// Now that everybody is done, digest data into unique files
if (rank == 0)
Wrapup_Parallel_Scan_Heis (whichDSF, Delta, N, M, iKmin, iKmax, nr_processors);
//cout << "rank " << rank << " passed wrapup stage." << endl;
// Another barrier synchronization
MPI_Barrier (MPI::COMM_WORLD);
tnow = MPI::Wtime();
} // while (tnow - tstart...
MPI::Finalize();
return(0);
}
+75
View File
@@ -0,0 +1,75 @@
/**********************************************************
This software is part of J.-S. Caux's C++ library.
Copyright (c)
-----------------------------------------------------------
File: Heis_DSF_par_Prepare.cc
Purpose: Parallel version of ABACUS++ using MPICH.
***********************************************************/
#include "JSC.h"
//#include "mpi.h" // not needed for Prepare
using namespace JSC;
int main(int argc, char *argv[])
{
char whichDSF;
DP Delta;
int N, M, iKmin, iKmax, paralevel, nr_processors_at_newlevel;
DP target_sumrule = 1.0e+6; // effectively deactivated here
bool refine = true; // always true for parallel mode
if (argc < 9) { // provide some info
cout << endl << "Welcome to ABACUS++\t(copyright J.-S. Caux)." << endl;
cout << endl << "Usage of Heis_DSF_par_Prepare executable: " << endl;
cout << endl << "This function prepares for ABACUS++G in parallel mode, starting from a preexisting serial run (obtained using the Heis_DSF executable) using the same model parameters." << 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 paralevel" << endl;
cout << "rank[i], nr_processors[i] \t rank and nr_processors of each earlier paralevels." << endl;
cout << "int nr_processors_at_new_level \t for this new parallelization level." << endl;
return(0);
}
else { // correct nr of arguments
int n = 1;
whichDSF = *argv[n++];
Delta = atof(argv[n++]);
N = atoi(argv[n++]);
M = atoi(argv[n++]);
iKmin = atoi(argv[n++]);
iKmax = atoi(argv[n++]);
paralevel = atoi(argv[n++]); // paralevel == 1 means that we have one layer of parallelization, so no previous rank and nr_processors to specify
if (argc != 9 + 2*(paralevel - 1)) JSCerror("Wrong nr of arguments in Heis_DSF_par_Prepare.");
Vect<int> rank_lower_paralevels(paralevel - 1);
Vect<int> nr_processors_lower_paralevels(paralevel - 1);
for (int i = 0; i < paralevel - 1; ++i) {
rank_lower_paralevels[i] = atoi(argv[n++]);
nr_processors_lower_paralevels[i] = atoi(argv[n++]);
}
nr_processors_at_newlevel = atoi(argv[n++]);
string defaultScanStatename = "";
// Split up thread list into chunks, one per processor
Prepare_Parallel_Scan_Heis (whichDSF, Delta, N, M, iKmin, iKmax, paralevel, rank_lower_paralevels, nr_processors_lower_paralevels, nr_processors_at_newlevel);
}
return(0);
}
+127
View File
@@ -0,0 +1,127 @@
/**********************************************************
This software is part of J.-S. Caux's ABACUS library.
Copyright (c).
-----------------------------------------------------------
File: Heis_DSF_par_Run.cc
Purpose: Parallel version of ABACUS++ using MPICH.
***********************************************************/
#include "JSC.h"
#include "mpi.h"
using namespace JSC;
int main(int argc, char *argv[])
{
char whichDSF;
DP Delta;
int N, M, iKmin, iKmax, Max_Secs, supercycle_time, paralevel;
DP target_sumrule = 1.0e+6; // effectively deactivated here
bool refine = true; // always true for parallel mode
if (argc < 10) { // provide some info
cout << endl << "Welcome to ABACUS++\t(copyright J.-S. Caux)." << endl;
cout << endl << "Usage of Heis_DSF_par_Run executable: " << endl;
cout << endl << "This function runs ABACUS++ in parallel mode, starting from a preexisting serial run (obtained using the Heis_DSF executable) using the same model parameters." << 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 paralevel" << endl;
cout << "rank[i], nr_processors[i] \t rank and nr_processors of each earlier paralevels." << endl;
cout << "int Max_Secs \t\t Allowed computational time: (in seconds)" << endl;
cout << "int supercycle_time \t\t time for one supercycle (in seconds)" << endl;
cout << endl << "EXAMPLE: " << endl << endl;
cout << "mpiexec -np 8 Heis_DSF_par_Run z 1 128 64 0 128 [**UPDATE]" << endl << endl;
return(0);
}
//else { // (argc == 9) correct nr of arguments
int n = 1;
whichDSF = *argv[n++];
Delta = atof(argv[n++]);
N = atoi(argv[n++]);
M = atoi(argv[n++]);
iKmin = atoi(argv[n++]);
iKmax = atoi(argv[n++]);
paralevel = atoi(argv[n++]); // paralevel == 1 means that we have one layer of parallelization, so no previous rank and nr_processors to specify
if (argc != 10 + 2*(paralevel - 1)) JSCerror("Wrong nr of arguments in Heis_DSF_par_Run.");
Vect<int> rank_lower_paralevels(paralevel - 1);
Vect<int> nr_processors_lower_paralevels(paralevel - 1);
for (int i = 0; i < paralevel - 1; ++i) {
rank_lower_paralevels[i] = atoi(argv[n++]);
nr_processors_lower_paralevels[i] = atoi(argv[n++]);
}
Max_Secs = atoi(argv[n++]);
supercycle_time = atoi(argv[n++]);
//}
//DP supercycle_time = 600.0; // allotted time per supercycle
if (Max_Secs <= supercycle_time) JSCerror("Please allow more time in Heis_DSF_par_Run.");
MPI::Init(argc, argv);
DP tstart = MPI::Wtime();
int rank_here = MPI::COMM_WORLD.Get_rank();
int nr_processors_here = MPI::COMM_WORLD.Get_size();
Vect<int> rank (paralevel);
Vect<int> nr_processors (paralevel);
for (int i = 0; i < paralevel - 1; ++i) {
rank[i] = rank_lower_paralevels[i];
nr_processors[i] = nr_processors_lower_paralevels[i];
}
rank[paralevel-1] = rank_here;
nr_processors[paralevel-1] = nr_processors_here;
if (nr_processors_here < 2) JSCerror("Give at least 2 processors to ABACUS++ parallel !");
refine = true;
// ASSUMPTION: preexisting files (raw, thr, ...) exist for the run.
DP tnow = MPI::Wtime();
string defaultScanStatename = "";
while (tnow - tstart < Max_Secs - supercycle_time - 120) { // space for one more supercycle, + 2 minutes safety
// Barrier synchronization, to make sure other processes wait for process of rank 0
// to have finished splitting up the thr file into pieces before starting:
MPI_Barrier (MPI::COMM_WORLD);
// then everybody gets going on their own chunk !
Scan_Heis (whichDSF, Delta, N, M, iKmin, iKmax,
supercycle_time, target_sumrule, refine, paralevel, rank, nr_processors);
// Another barrier synchronization
MPI_Barrier (MPI::COMM_WORLD);
// Now that everybody is done, digest data into unique files
// Another barrier synchronization
MPI_Barrier (MPI::COMM_WORLD);
tnow = MPI::Wtime();
} // while (tnow - tstart...
MPI::Finalize();
return(0);
}
+75
View File
@@ -0,0 +1,75 @@
/**********************************************************
This software is part of J.-S. Caux's C++ library.
Copyright (c)
-----------------------------------------------------------
File: Heis_DSF_par_Prepare.cc
Purpose: Parallel version of ABACUS++ using MPICH.
***********************************************************/
#include "JSC.h"
//#include "mpi.h" // not needed for Prepare or Wrapup
using namespace JSC;
int main(int argc, char *argv[])
{
char whichDSF;
DP Delta;
int N, M, iKmin, iKmax, paralevel, nr_processors_at_newlevel;
DP target_sumrule = 1.0e+6; // effectively deactivated here
bool refine = true; // always true for parallel mode
if (argc < 9) { // provide some info
cout << endl << "Welcome to ABACUS++\t(copyright J.-S. Caux)." << endl;
cout << endl << "Usage of Heis_DSF_par_Wrapup executable: " << endl;
cout << endl << "This function wraps up an ABACUS++G parallel mode run." << 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 paralevel" << endl;
cout << "rank[i], nr_processors[i] \t rank and nr_processors of each earlier paralevels." << endl;
cout << "int nr_processors_at_new_level \t for this latest parallelization level." << endl;
return(0);
}
else { // correct nr of arguments
int n = 1;
whichDSF = *argv[n++];
Delta = atof(argv[n++]);
N = atoi(argv[n++]);
M = atoi(argv[n++]);
iKmin = atoi(argv[n++]);
iKmax = atoi(argv[n++]);
paralevel = atoi(argv[n++]); // paralevel == 1 means that we have one layer of parallelization, so no previous rank and nr_processors to specify
if (argc != 9 + 2*(paralevel - 1)) JSCerror("Wrong nr of arguments in Heis_DSF_par_Wrapup.");
Vect<int> rank_lower_paralevels(paralevel - 1);
Vect<int> nr_processors_lower_paralevels(paralevel - 1);
for (int i = 0; i < paralevel - 1; ++i) {
rank_lower_paralevels[i] = atoi(argv[n++]);
nr_processors_lower_paralevels[i] = atoi(argv[n++]);
}
nr_processors_at_newlevel = atoi(argv[n++]);
string defaultScanStatename = "";
// Split up thread list into chunks, one per processor
Wrapup_Parallel_Scan_Heis (whichDSF, Delta, N, M, iKmin, iKmax, paralevel, rank_lower_paralevels, nr_processors_lower_paralevels, nr_processors_at_newlevel);
}
return(0);
}
@@ -0,0 +1,116 @@
/**********************************************************
This software is part of J.-S. Caux's ABACUS library.
Copyright (c).
-----------------------------------------------------------
File: LiebLin_Catalogue_Fixed_c_k_Nscaling.cc
Purpose: Produces sets of data files for correlations, increasing system size at fixed c and momentum.
***********************************************************/
#include "JSC.h"
using namespace std;
using namespace JSC;
int main(int argc, char* argv[])
{
if (argc != 7) { // provide some info
cout << endl << "Welcome to ABACUS\t(copyright J.-S. Caux)." << endl;
cout << endl << "Usage of LiebLin_Catalogue_Fixed_c_k_Nscaling executable: " << endl;
cout << endl << "Provide the following arguments:" << endl << endl;
cout << "char whichDSF \t\t Which structure factor should be calculated ? Options are: d for rho rho, g for psi psi{dagger}, o for psi{dagger} psi" << endl;
cout << "DP c_int \t\t Value of the interaction parameter: use positive real values only" << endl;
//cout << "int Nc \t\t number of steps in interaction value" << endl;
//cout << "int Nstep \t\t\t Steps to be taken in number of particles: use positive integer values only. Filling will be set to 1 (L == N)" << endl;
//cout << "int iKmin" << endl << "int iKmax \t\t Min and max momentum integers to scan over (in units of N == Nstep): recommended values: 0 and 2*N" << endl;
cout << "int kfact \t\t momentum factor: momemntum will be set to kfact * kF/4" << endl;
cout << "DP kBT \t\t Temperature (positive only of course)" << endl;
cout << "DP target_sumrule \t sumrule saturation you're satisfied with" << endl;
cout << "int Max_Secs \t\t Allowed computational time" << endl;
}
else { // correct nr of arguments
int ia = 1;
char whichDSF = *argv[ia++];
DP c_int = atof(argv[ia++]);
int kfact = atoi(argv[ia++]);
DP kBT = atof(argv[ia++]);
DP target_sumrule = atof(argv[ia++]);
int Max_Secs = atoi(argv[ia++]);
//clock_t StartTime = clock();
double StartTime = omp_get_wtime();
//clock_t ActualTime = StartTime;
double ActualTime = omp_get_wtime();
int Secs_left = Max_Secs;
int iN = 0;
int nN = 12;
Vect<int> Nv(nN);
Nv[0] = 160; Nv[1] = 192; Nv[2] = 224; Nv[3] = 256;
Nv[4] = 320; Nv[5] = 384; Nv[6] = 448; Nv[7] = 512;
Nv[8] = 640; Nv[9] = 768; Nv[10] = 896; Nv[11] = 1024;
for (int iN = 0; iN < nN; ++iN) {
int N = Nv[iN];
DP L = N;
int iKmin = (kfact * N)/8;
int iKmax = iKmin;
DP srsat = 0.0;
bool refine = false;
stringstream SRC_stringstream; string SRC_string;
Data_File_Name (SRC_stringstream, whichDSF, c_int, L, N, iKmin, iKmax, kBT, 0.0, "");
SRC_stringstream << ".src";
SRC_string = SRC_stringstream.str(); const char* SRC_Cstr = SRC_string.c_str();
fstream srcfile;
srcfile.open(SRC_Cstr, fstream::in);
if (srcfile.fail()) {
srsat = 0.0;
refine = false;
}
else {
srcfile >> srsat;
refine = true;
}
srcfile.close();
ActualTime = omp_get_wtime();
Secs_left = int(Max_Secs - (ActualTime - StartTime));
if (srsat < target_sumrule && Secs_left > Max_Secs/2)
// Improve the icmin calculation by one chunk:
Scan_LiebLin (whichDSF, c_int, L, N, iKmin, iKmax, kBT, Secs_left, target_sumrule, refine);
ActualTime = omp_get_wtime();
//Secs_left = int(60*Max_minutes - double(ActualTime - StartTime)/CLOCKS_PER_SEC);
Secs_left = int(Max_Secs - (ActualTime - StartTime));
cout << "Done with N = " << N << ". Time left = " << Secs_left << " seconds." << endl;
if (Secs_left < 60) {
cout << "Breaking out after N = " << N << " since time left = " << Secs_left << endl;
break;
}
} // while there is time
} // else if arguments given OK
return(0);
}
+62
View File
@@ -0,0 +1,62 @@
/**********************************************************
This software is part of J.-S. Caux's ABACUS library.
Copyright (c).
-----------------------------------------------------------
File: LiebLin_DSF.cc
Purpose: main function for ABACUS++ for LiebLin gas
***********************************************************/
#include "JSC.h"
using namespace std;
using namespace JSC;
int main(int argc, char* argv[])
{
if (argc != 11) { // provide some info
cout << endl << "Welcome to ABACUS++\t(copyright J.-S. Caux)." << endl;
cout << endl << "Usage of LiebLin_DSF_Tgt0 executable: " << endl;
cout << endl << "Provide the following arguments:" << endl << endl;
cout << "char whichDSF \t\t Which structure factor should be calculated ? Options are: d for rho rho, g for psi psi{dagger}, o for psi{dagger} psi" << endl;
cout << "DP c_int \t\t Value of the interaction parameter: use positive real values only" << endl;
cout << "DP L \t\t\t Length of the system: use positive real values only" << endl;
cout << "int N \t\t\t Number of particles: use positive integer values only" << endl;
cout << "int iKmin" << endl << "int iKmax \t\t Min and max momentum integers to scan over: recommended values: -2*N and 2*N" << endl;
cout << "DP kBT \t\t Temperature (positive only of course)" << 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 earlier calculations ? (0 == false, 1 == true)" << endl;
cout << endl << "EXAMPLE: " << endl << endl;
cout << "LiebLin_DSF d 1.0 100.0 100 0 200 0.56 600 1.0 0" << endl << endl;
}
else { // (argc == 10), correct nr of arguments
char whichDSF = *argv[1];
DP c_int = atof(argv[2]);
DP L = atof(argv[3]);
int N = atoi(argv[4]);
int iKmin = atoi(argv[5]);
int iKmax = atoi(argv[6]);
DP kBT = atof(argv[7]);
int Max_Secs = atoi(argv[8]);
DP target_sumrule = atof(argv[9]);
bool refine = (atoi(argv[10]) == 1);
//cout << "target_sumrule = " << target_sumrule << endl;
//Scan_LiebLin (whichDSF, c_int, L, N, iKmin, iKmax, kBT, Max_Secs, target_sumrule, refine, 0, 1);
Scan_LiebLin (whichDSF, c_int, L, N, iKmin, iKmax, kBT, Max_Secs, target_sumrule, refine);
}
return(0);
}
+97
View File
@@ -0,0 +1,97 @@
/**********************************************************
This software is part of J.-S. Caux's ABACUS library.
Copyright (c).
-----------------------------------------------------------
File: LiebLin_DSF_GeneralState.cc
Purpose: function for ABACUS++ for LiebLin gas, on general states
***********************************************************/
#include "JSC.h"
using namespace std;
using namespace JSC;
int main(int argc, char* argv[])
{
if (argc != 11) { // provide some info
cout << endl << "Welcome to ABACUS++\t(copyright J.-S. Caux)." << endl;
cout << endl << "Usage of LiebLin_DSF_Tgt0 executable: " << endl;
cout << endl << "Provide the following arguments:" << endl << endl;
cout << "char whichDSF \t\t Which structure factor should be calculated ? Options are: d for rho rho, g for psi psi{dagger}, o for psi{dagger} psi" << endl;
cout << "DP c_int \t\t Value of the interaction parameter: use positive real values only" << endl;
cout << "DP L \t\t\t Length of the system: use positive real values only" << endl;
cout << "int N \t\t\t Number of particles: use positive integer values only" << endl;
cout << "char* defaultScanStatename:\t\t file [].Ix2 contains the quantum numbers defining the AveragingState; used as defaultScanStatename" << endl;
cout << "int iKmin" << endl << "int iKmax \t\t Min and max momentum integers to scan over: recommended values: -2*N and 2*N" << endl;
//cout << "DP kBT \t\t Temperature (positive only of course)" << 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 earlier calculations ? (0 == false, 1 == true)" << endl;
cout << endl << "EXAMPLE: " << endl << endl;
cout << "LiebLin_DSF d 1.0 100.0 100 0 200 0.56 600 1.0 0" << endl << endl;
}
else { // (argc == 10), correct nr of arguments
int n = 1;
char whichDSF = *argv[n++];
DP c_int = atof(argv[n++]);
DP L = atof(argv[n++]);
int N = atoi(argv[n++]);
char* Ix2filenameprefix = argv[n++];
int iKmin = atoi(argv[n++]);
int iKmax = atoi(argv[n++]);
//DP kBT = atof(argv[n++]);
int Max_Secs = atoi(argv[n++]);
DP target_sumrule = atof(argv[n++]);
bool refine = (atoi(argv[n++]) == 1);
// Read the Ix2 from the file:
Vect<int> Ix2_input(N);
ifstream Ix2_input_file;
stringstream filenamestrstream;
filenamestrstream << Ix2filenameprefix;
string defaultScanStatename = filenamestrstream.str();
filenamestrstream << ".Ix2";
string filenamestr = filenamestrstream.str();
const char* filename_Cstr = filenamestr.c_str();
Ix2_input_file.open(filename_Cstr);
if (Ix2_input_file.fail()) {
cout << filename_Cstr << endl;
JSCerror("Could not open Ix2 input file in LiebLin_DSF_GeneralState");
}
for (int i = 0; i < N; ++i) {
Ix2_input_file >> Ix2_input[i];
//cout << i << "\t" << Ix2_input[i] << endl;
}
// Now define the AveragingState
LiebLin_Bethe_State AveragingState(c_int, L, N);
AveragingState.Ix2 = Ix2_input;
AveragingState.Compute_All(true);
//cout << "Averaging state: " << AveragingState << endl;
//Scan_LiebLin (whichDSF, c_int, L, N, iKmin, iKmax, kBT, Max_Secs, target_sumrule, refine, 0, 1);
//Scan_LiebLin (whichDSF, c_int, L, N, iKmin, iKmax, kBT, Max_Secs, target_sumrule, refine);
//void Scan_LiebLin (char whichDSF, LiebLin_Bethe_State AveragingState, string defaultScanStatename, int iKmin, int iKmax,
// int Max_Secs, DP target_sumrule, bool refine, int paralevel, Vect<int> rank, Vect<int> nr_processors)
// Simplified function call of the above:
//void Scan_LiebLin (char whichDSF, LiebLin_Bethe_State AveragingState, string defaultScanStatename, int iKmin, int iKmax,
// int Max_Secs, DP target_sumrule, bool refine)
Scan_LiebLin (whichDSF, AveragingState, defaultScanStatename, iKmin, iKmax, Max_Secs, target_sumrule, refine);
}
return(0);
}
@@ -0,0 +1,106 @@
/**********************************************************
This software is part of J.-S. Caux's ABACUS library.
Copyright (c).
-----------------------------------------------------------
File: LiebLin_DSF_GeneralState_par_Prepare.cc
Purpose: Parallel version of ABACUS++ using MPICH.
***********************************************************/
#include "JSC.h"
//#include "mpi.h" // not needed for Prepare
using namespace JSC;
int main(int argc, char *argv[])
{
char whichDSF;
DP c_int, L, kBT;
int N, iKmin, iKmax, paralevel, nr_processors_at_newlevel;
DP target_sumrule = 1.0e+6; // effectively deactivated here
bool refine = true; // always true for parallel mode
char* Ix2filenameprefix;
if (argc < 10) { // provide some info
cout << endl << "Welcome to ABACUS++\t(copyright J.-S. Caux)." << endl;
cout << endl << "Usage of LiebLin_DSF_par_Prepare executable: " << endl;
cout << endl << "This function prepares an ABACUS++ parallel mode run, starting from a preexisting serial run (obtained using the LiebLin_DSF executable) using the same model parameters." << endl;
cout << endl << "Provide the following arguments:" << endl << endl;
cout << "char whichDSF \t\t Which structure factor should be calculated ? Options are: d for rho rho, g for psi psi{dagger}, o for psi{dagger} psi" << endl;
cout << "DP c_int \t\t Value of the interaction parameter: use positive real values only" << endl;
cout << "DP L \t\t\t Length of the system: use positive real values only" << endl;
cout << "int N \t\t\t Number of particles: use positive integer values only" << endl;
cout << "char* defaultScanStatename:\t\t file [].Ix2 contains the quantum numbers defining the AveragingState; used as defaultScanStatename" << endl;
cout << "int iKmin" << endl << "int iKmax \t\t Min and max momentum integers to scan over: recommended values: -2*N and 2*N" << endl;
//cout << "DP kBT \t\t Temperature (positive only of course)" << endl;
cout << "int paralevel" << endl;
cout << "rank[i], nr_processors[i] \t rank and nr_processors of each earlier paralevels." << endl;
cout << "int nr_processors_at_new_level \t for this new parallelization level." << endl;
return(0);
}
else { // correct nr of arguments
int n = 1;
whichDSF = *argv[n++];
c_int = atof(argv[n++]);
L = atof(argv[n++]);
N = atoi(argv[n++]);
Ix2filenameprefix = argv[n++];
iKmin = atoi(argv[n++]);
iKmax = atoi(argv[n++]);
//kBT = atof(argv[n++]);
paralevel = atoi(argv[n++]); // paralevel == 1 means that we have one layer of parallelization, so no previous rank and nr_processors to specify
if (argc != 10 + 2*(paralevel - 1)) JSCerror("Wrong nr of arguments in LiebLin_DSF_GeneralState_par_Prepare.");
Vect<int> rank_lower_paralevels(paralevel - 1);
Vect<int> nr_processors_lower_paralevels(paralevel - 1);
for (int i = 0; i < paralevel - 1; ++i) {
rank_lower_paralevels[i] = atoi(argv[n++]);
nr_processors_lower_paralevels[i] = atoi(argv[n++]);
}
nr_processors_at_newlevel = atoi(argv[n++]);
// Read the Ix2 from the file:
Vect<int> Ix2_input(N);
ifstream Ix2_input_file;
stringstream filenamestrstream;
filenamestrstream << Ix2filenameprefix;
string defaultScanStatename = filenamestrstream.str();
/*
filenamestrstream << ".Ix2";
string filenamestr = filenamestrstream.str();
const char* filename_Cstr = filenamestr.c_str();
Ix2_input_file.open(filename_Cstr);
if (Ix2_input_file.fail()) {
cout << filename_Cstr << endl;
JSCerror("Could not open Ix2 input file in LiebLin_DSF_GeneralState");
}
for (int i = 0; i < N; ++i) {
Ix2_input_file >> Ix2_input[i];
//cout << i << "\t" << Ix2_input[i] << endl;
}
// Define the AveragingState
LiebLin_Bethe_State AveragingState(c_int, L, N);
AveragingState.Ix2 = Ix2_input;
//AveragingState.Compute_All(true);
*/
// Split up thread list into chunks, one per processor
Prepare_Parallel_Scan_LiebLin (whichDSF, c_int, L, N, iKmin, iKmax, kBT, defaultScanStatename, paralevel, rank_lower_paralevels, nr_processors_lower_paralevels, nr_processors_at_newlevel);
}
return(0);
}
@@ -0,0 +1,153 @@
/**********************************************************
This software is part of J.-S. Caux's ABACUS library.
Copyright (c).
-----------------------------------------------------------
File: LiebLin_DSF_GeneralState_par_Run.cc
Purpose: Parallel version of ABACUS++ using MPICH.
***********************************************************/
#include "JSC.h"
#include "mpi.h"
using namespace JSC;
int main(int argc, char *argv[])
{
char whichDSF;
DP c_int, L, kBT;
int N, iKmin, iKmax, Max_Secs, paralevel;
DP target_sumrule = 1.0e+6; // effectively deactivated here
bool refine = true; // always true for parallel mode
char* Ix2filenameprefix;
if (argc < 10) { // provide some info
cout << endl << "Welcome to ABACUS++\t(copyright J.-S. Caux)." << endl;
cout << endl << "Usage of LiebLin_DSF_par executable: " << endl;
cout << endl << "This function runs ABACUS++ in parallel mode, starting from a preexisting serial run (obtained using the LiebLin_DSF executable) using the same model parameters." << endl;
cout << endl << "Provide the following arguments:" << endl << endl;
cout << "char whichDSF \t\t Which structure factor should be calculated ? Options are: d for rho rho, g for psi psi{dagger}, o for psi{dagger} psi" << endl;
cout << "DP c_int \t\t Value of the interaction parameter: use positive real values only" << endl;
cout << "DP L \t\t\t Length of the system: use positive real values only" << endl;
cout << "int N \t\t\t Number of particles: use positive integer values only" << endl;
cout << "char* defaultScanStatename:\t\t file [].Ix2 contains the quantum numbers defining the AveragingState; used as defaultScanStatename" << endl;
cout << "int iKmin" << endl << "int iKmax \t\t Min and max momentum integers to scan over: recommended values: -2*N and 2*N" << endl;
//cout << "DP kBT \t\t Temperature (positive only of course)" << endl;
cout << "int paralevel" << endl;
cout << "rank[i], nr_processors[i] \t rank and nr_processors of each earlier paralevels." << endl;
cout << "int Max_Secs \t\t Allowed computational time: (in seconds)" << endl;
//cout << "int supercycle_time \t\t time for one supercycle (in seconds)" << endl;
return(0);
}
//else { // correct nr of arguments
int n = 1;
whichDSF = *argv[n++];
c_int = atof(argv[n++]);
L = atof(argv[n++]);
N = atoi(argv[n++]);
Ix2filenameprefix = argv[n++];
iKmin = atoi(argv[n++]);
iKmax = atoi(argv[n++]);
//kBT = atof(argv[n++]);
paralevel = atoi(argv[n++]); // paralevel == 1 means that we have one layer of parallelization, so no previous rank and nr_processors to specify
if (argc != 10 + 2*(paralevel - 1)) JSCerror("Wrong nr of arguments in LiebLin_DSF_par_Prepare.");
Vect<int> rank_lower_paralevels(paralevel - 1);
Vect<int> nr_processors_lower_paralevels(paralevel - 1);
for (int i = 0; i < paralevel - 1; ++i) {
rank_lower_paralevels[i] = atoi(argv[n++]);
nr_processors_lower_paralevels[i] = atoi(argv[n++]);
}
Max_Secs = atoi(argv[n++]);
// supercycle_time = atoi(argv[n++]);
//}
//DP supercycle_time = 600.0; // allotted time per supercycle
if (Max_Secs <= 120) JSCerror("Please allow more time in LiebLin_DSF_par_Run.");
int Max_Secs_used = Max_Secs - 120;
MPI::Init(argc, argv);
DP tstart = MPI::Wtime();
int rank_here = MPI::COMM_WORLD.Get_rank();
int nr_processors_here = MPI::COMM_WORLD.Get_size();
// Read the Ix2 from the file:
Vect<int> Ix2_input(N);
ifstream Ix2_input_file;
stringstream filenamestrstream;
filenamestrstream << Ix2filenameprefix;
string defaultScanStatename = filenamestrstream.str();
filenamestrstream << ".Ix2";
string filenamestr = filenamestrstream.str();
const char* filename_Cstr = filenamestr.c_str();
Ix2_input_file.open(filename_Cstr);
if (Ix2_input_file.fail()) {
cout << filename_Cstr << endl;
JSCerror("Could not open Ix2 input file in LiebLin_DSF_GeneralState");
}
for (int i = 0; i < N; ++i) {
Ix2_input_file >> Ix2_input[i];
//cout << i << "\t" << Ix2_input[i] << endl;
}
// Now define the AveragingState
LiebLin_Bethe_State AveragingState(c_int, L, N);
AveragingState.Ix2 = Ix2_input;
AveragingState.Compute_All(true);
Vect<int> rank (paralevel);
Vect<int> nr_processors (paralevel);
for (int i = 0; i < paralevel - 1; ++i) {
rank[i] = rank_lower_paralevels[i];
nr_processors[i] = nr_processors_lower_paralevels[i];
}
rank[paralevel-1] = rank_here;
nr_processors[paralevel-1] = nr_processors_here;
if (nr_processors_here < 2) JSCerror("Give at least 2 processors to ABACUS++ parallel !");
refine = true;
// ASSUMPTION: preexisting files (raw, thr, ...) exist for the run.
DP tnow = MPI::Wtime();
//while (tnow - tstart < Max_Secs - supercycle_time - 120) { // space for one more supercycle, + 2 minutes safety
if (Max_Secs_used > 0) {
// Barrier synchronization
MPI_Barrier (MPI::COMM_WORLD);
// then everybody gets going on their own chunk !
//Scan_LiebLin (whichDSF, c_int, L, N, iK_UL, fixed_iK, iKneeded,
//Scan_LiebLin (whichDSF, c_int, L, N, iKmin, iKmax, kBT,
// supercycle_time, target_sumrule, refine, paralevel, rank, nr_processors);
Scan_LiebLin (whichDSF, AveragingState, defaultScanStatename, iKmin, iKmax, Max_Secs, target_sumrule, refine, paralevel, rank, nr_processors);
// Another barrier synchronization
MPI_Barrier (MPI::COMM_WORLD);
tnow = MPI::Wtime();
} // while (tnow - tstart...
MPI::Finalize();
return(0);
}
@@ -0,0 +1,104 @@
/**********************************************************
This software is part of J.-S. Caux's ABACUS library.
Copyright (c).
-----------------------------------------------------------
File: LiebLin_DSF_par_Prepare.cc
Purpose: Parallel version of ABACUS++ using MPICH.
***********************************************************/
#include "JSC.h"
//#include "mpi.h" // not needed for Prepare
using namespace JSC;
int main(int argc, char *argv[])
{
char whichDSF;
DP c_int, L, kBT;
int N, iKmin, iKmax, paralevel, nr_processors_at_newlevel;
DP target_sumrule = 1.0e+6; // effectively deactivated here
bool refine = true; // always true for parallel mode
char* Ix2filenameprefix;
if (argc < 10) { // provide some info
cout << endl << "Welcome to ABACUS++\t(copyright J.-S. Caux)." << endl;
cout << endl << "Usage of LiebLin_DSF_par_Wrapup executable: " << endl;
cout << endl << "This function wraps up an ABACUS++ parallel mode run." << endl;
cout << endl << "Provide the following arguments:" << endl << endl;
cout << "char whichDSF \t\t Which structure factor should be calculated ? Options are: d for rho rho, g for psi psi{dagger}, o for psi{dagger} psi" << endl;
cout << "DP c_int \t\t Value of the interaction parameter: use positive real values only" << endl;
cout << "DP L \t\t\t Length of the system: use positive real values only" << endl;
cout << "int N \t\t\t Number of particles: use positive integer values only" << endl;
cout << "char* defaultScanStatename:\t\t file [].Ix2 contains the quantum numbers defining the AveragingState; used as defaultScanStatename" << endl;
cout << "int iKmin" << endl << "int iKmax \t\t Min and max momentum integers to scan over: recommended values: -2*N and 2*N" << endl;
//cout << "DP kBT \t\t Temperature (positive only of course)" << endl;
cout << "int paralevel" << endl;
cout << "rank[i], nr_processors[i] \t rank and nr_processors of each earlier paralevels." << endl;
cout << "int nr_processors_at_new_level \t for this latest parallelization level." << endl;
return(0);
}
else { // correct nr of arguments
int n = 1;
whichDSF = *argv[n++];
c_int = atof(argv[n++]);
L = atof(argv[n++]);
N = atoi(argv[n++]);
Ix2filenameprefix = argv[n++];
iKmin = atoi(argv[n++]);
iKmax = atoi(argv[n++]);
//kBT = atof(argv[n++]);
paralevel = atoi(argv[n++]); // paralevel == 1 means that we have one layer of parallelization, so no previous rank and nr_processors to specify
if (argc != 10 + 2*(paralevel - 1)) JSCerror("Wrong nr of arguments in LiebLin_DSF_par_Prepare.");
Vect<int> rank_lower_paralevels(paralevel - 1);
Vect<int> nr_processors_lower_paralevels(paralevel - 1);
for (int i = 0; i < paralevel - 1; ++i) {
rank_lower_paralevels[i] = atoi(argv[n++]);
nr_processors_lower_paralevels[i] = atoi(argv[n++]);
}
nr_processors_at_newlevel = atoi(argv[n++]);
// Read the Ix2 from the file:
Vect<int> Ix2_input(N);
ifstream Ix2_input_file;
stringstream filenamestrstream;
filenamestrstream << Ix2filenameprefix;
string defaultScanStatename = filenamestrstream.str();
/*
filenamestrstream << ".Ix2";
string filenamestr = filenamestrstream.str();
const char* filename_Cstr = filenamestr.c_str();
Ix2_input_file.open(filename_Cstr);
if (Ix2_input_file.fail()) {
cout << filename_Cstr << endl;
JSCerror("Could not open Ix2 input file in LiebLin_DSF_GeneralState");
}
for (int i = 0; i < N; ++i) {
Ix2_input_file >> Ix2_input[i];
//cout << i << "\t" << Ix2_input[i] << endl;
}
// Define the AveragingState
LiebLin_Bethe_State AveragingState(c_int, L, N);
AveragingState.Ix2 = Ix2_input;
//AveragingState.Compute_All(true);
*/
// Digest files into a unique one for the latest paralevel:
Wrapup_Parallel_Scan_LiebLin (whichDSF, c_int, L, N, iKmin, iKmax, kBT, defaultScanStatename, paralevel, rank_lower_paralevels, nr_processors_lower_paralevels, nr_processors_at_newlevel);
}
return(0);
}
+84
View File
@@ -0,0 +1,84 @@
/**********************************************************
This software is part of J.-S. Caux's ABACUS library.
Copyright (c).
-----------------------------------------------------------
File: LiebLin_DSF.cc
Purpose: main function for ABACUS++ for LiebLin gas
***********************************************************/
#include "JSC.h"
using namespace std;
using namespace JSC;
int main(int argc, char* argv[])
{
if (argc != 13) { // provide some info
cout << endl << "Welcome to ABACUS++\t(copyright J.-S. Caux)." << endl;
cout << endl << "Usage of LiebLin_DSF_MosesState executable: " << endl;
cout << endl << "Provide the following arguments:" << endl << endl;
cout << "char whichDSF \t\t Which structure factor should be calculated ? Options are: d for rho rho, g for psi psi{dagger}, o for psi{dagger} psi" << endl;
cout << "DP c_int \t\t Value of the interaction parameter: use positive real values only" << endl;
cout << "DP L \t\t\t Length of the system: use positive real values only" << endl;
cout << "int N \t\t\t Number of particles: use positive integer values only" << endl;
cout << "int Nl \t\t\t Number of particles in left Fermi sea (Nr is then N - Nl)" << endl;
cout << "int DIl \t\t shift of left sea as compared to its ground state position" << endl;
cout << "int DIr \t\t shift of right sea as compared to its ground state position" << endl;
cout << "int iKmin" << endl << "int iKmax \t\t Min and max momentum integers to scan over: recommended values: -2*N and 2*N" << endl;
//cout << "DP kBT \t\t Temperature (positive only of course)" << 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 earlier calculations ? (0 == false, 1 == true)" << endl;
cout << endl << "EXAMPLE: " << endl << endl;
cout << "LiebLin_DSF_MosesState d 1.0 100.0 100 50 -30 20 0 200 600 1.0 0" << endl << endl;
}
else { // (argc == 13), correct nr of arguments
char whichDSF = *argv[1];
DP c_int = atof(argv[2]);
DP L = atof(argv[3]);
int N = atoi(argv[4]);
int Nl = atoi(argv[5]);
//int Nr = N - Nl;
int DIl = atoi(argv[6]);
int DIr = atoi(argv[7]);
int iKmin = atoi(argv[8]);
int iKmax = atoi(argv[9]);
//DP kBT = atof(argv[7]);
int Max_Secs = atoi(argv[10]);
DP target_sumrule = atof(argv[11]);
bool refine = (atoi(argv[12]) == 1);
// Define the Moses state:
LiebLin_Bethe_State MosesState (c_int, L, N);
// Split the sea:
for (int i = 0; i < Nl; ++i) MosesState.Ix2[i] += 2 * DIl;
for (int i = Nl; i < N; ++i) MosesState.Ix2[i] += 2 * DIr;
MosesState.Compute_All (true);
//cout << MosesState << endl;
// Handy default name:
stringstream defaultScanStatename_strstream;
defaultScanStatename_strstream << "Moses_Nl_" << Nl << "_DIl_" << DIl << "_DIr_" << DIr;
string defaultScanStatename = defaultScanStatename_strstream.str();
// Compute the correlation:
Scan_LiebLin (whichDSF, MosesState, defaultScanStatename, iKmin, iKmax, Max_Secs, target_sumrule, refine);
}
return(0);
}
+139
View File
@@ -0,0 +1,139 @@
/**********************************************************
This software is part of J.-S. Caux's ABACUS library.
Copyright (c).
-----------------------------------------------------------
File: LiebLin_DSF_par.cc
Purpose: Parallel version of ABACUS++ using MPICH.
***********************************************************/
#include "JSC.h"
#include "mpi.h"
using namespace JSC;
int main(int argc, char *argv[])
{
char whichDSF;
DP c_int, L;
int N, Nl, DIl, DIr, iKmin, iKmax, Max_Secs, supercycle_time;
DP target_sumrule = 1.0e+6; // effectively deactivated here
bool refine = true; // always true for parallel mode
DP kBT = 0.0; // dummy
if (argc != 12) { // provide some info
cout << endl << "Welcome to ABACUS++\t(copyright J.-S. Caux)." << endl;
cout << endl << "Usage of LiebLin_DSF_MosesState_par executable: " << endl;
cout << endl << "This function runs ABACUS++ in parallel mode, starting from a preexisting serial run (obtained using the LiebLin_DSF executable) using the same model parameters." << endl;
cout << endl << "Provide the following arguments:" << endl << endl;
cout << "char whichDSF \t\t Which structure factor should be calculated ? Options are: d for rho rho, g for psi psi{dagger}, o for psi{dagger} psi" << endl;
cout << "DP c_int \t\t Value of the interaction parameter: use positive real values only" << endl;
cout << "DP L \t\t\t Length of the system: use positive real values only" << endl;
cout << "int N \t\t\t Number of particles: use positive integer values only" << endl;
cout << "int Nl \t\t\t Number of particles in left Fermi sea (Nr is then N - Nl)" << endl;
cout << "int DIl \t\t shift of left sea as compared to its ground state position" << endl;
cout << "int DIr \t\t shift of right sea as compared to its ground state position" << endl;
cout << "int iKmin" << endl << "int iKmax \t\t Min and max momentum integers to scan over: recommended values: -2*N and 2*N" << endl;
cout << "int Max_Secs \t\t Allowed computational time: (in seconds)" << endl;
cout << "int supercycle_time \t\t time for one supercycle (in seconds)" << endl;
cout << endl << "EXAMPLE: " << endl << endl;
cout << "mpiexec -np 8 LiebLin_DSF_MosesState_par d 1.0 100.0 100 50 -30 20 -400 400 3600 600" << endl << endl;
return(0);
}
else { // (argc == 11) correct nr of arguments
whichDSF = *argv[1];
c_int = atof(argv[2]);
L = atof(argv[3]);
N = atoi(argv[4]);
Nl = atoi(argv[5]);
DIl = atoi(argv[6]);
DIr = atoi(argv[7]);
iKmin = atoi(argv[8]);
iKmax = atoi(argv[9]);
Max_Secs = atoi(argv[10]);
supercycle_time = atoi(argv[11]);
}
//DP supercycle_time = 600.0; // allotted time per supercycle
if (Max_Secs <= supercycle_time) JSCerror("Please allow more time in LiebLin_DSF_par.");
MPI::Init(argc, argv);
DP tstart = MPI::Wtime();
int rank = MPI::COMM_WORLD.Get_rank();
int nr_processors = MPI::COMM_WORLD.Get_size();
if (nr_processors < 2) JSCerror("Give at least 2 processors to ABACUS++ parallel !");
refine = true;
// ASSUMPTION: preexisting files (raw, thr, ...) exist for the run.
DP tnow = MPI::Wtime();
// Define the Moses state:
LiebLin_Bethe_State MosesState (c_int, L, N);
// Split the sea:
for (int i = 0; i < Nl; ++i) MosesState.Ix2[i] += 2 * DIl;
for (int i = Nl; i < N; ++i) MosesState.Ix2[i] += 2 * DIr;
MosesState.Compute_All (true);
// Handy default name:
stringstream defaultScanStatename_strstream;
defaultScanStatename_strstream << "Moses_Nl_" << Nl << "_DIl_" << DIl << "_DIr_" << DIr;
string defaultScanStatename = defaultScanStatename_strstream.str();
MPI_Barrier (MPI::COMM_WORLD);
while (tnow - tstart < Max_Secs - supercycle_time - 120) { // space for one more supercycle, + 2 minutes safety
if (rank == 0)
// Split up thread list into chunks, one per processor
//Prepare_Parallel_Scan_LiebLin (whichDSF, c_int, L, N, iK_UL, fixed_iK, iKneeded, nr_processors);
Prepare_Parallel_Scan_LiebLin (whichDSF, c_int, L, N, iKmin, iKmax, kBT, defaultScanStatename, nr_processors);
// Barrier synchronization, to make sure other processes wait for process of rank 0
// to have finished splitting up the thr file into pieces before starting:
MPI_Barrier (MPI::COMM_WORLD);
// then everybody gets going on their own chunk !
//Scan_LiebLin (whichDSF, c_int, L, N, iK_UL, fixed_iK, iKneeded,
//Scan_LiebLin (whichDSF, c_int, L, N, iKmin, iKmax, kBT, supercycle_time, target_sumrule, refine, rank, nr_processors);
Scan_LiebLin (whichDSF, MosesState, defaultScanStatename, iKmin, iKmax, supercycle_time, target_sumrule, refine, rank, nr_processors);
// Another barrier synchronization
MPI_Barrier (MPI::COMM_WORLD);
// Now that everybody is done, digest data into unique files
if (rank == 0)
//Wrapup_Parallel_Scan_LiebLin (whichDSF, c_int, L, N, iK_UL, fixed_iK, iKneeded, nr_processors);
Wrapup_Parallel_Scan_LiebLin (whichDSF, c_int, L, N, iKmin, iKmax, kBT, defaultScanStatename, nr_processors);
// Another barrier synchronization
MPI_Barrier (MPI::COMM_WORLD);
tnow = MPI::Wtime();
} // while (tnow - tstart...
MPI::Finalize();
return(0);
}
@@ -0,0 +1,96 @@
/**********************************************************
This software is part of J.-S. Caux's ABACUS library.
Copyright (c).
-----------------------------------------------------------
File: LiebLin_DSF_par_Prepare.cc
Purpose: Parallel version of ABACUS++ using MPICH.
***********************************************************/
#include "JSC.h"
//#include "mpi.h" // not needed for Prepare
using namespace JSC;
int main(int argc, char *argv[])
{
char whichDSF;
DP c_int, L;
int N, Nl, DIl, DIr, iKmin, iKmax, paralevel, nr_processors_at_newlevel;
DP target_sumrule = 1.0e+6; // effectively deactivated here
bool refine = true; // always true for parallel mode
DP kBT = 0.0; // dummy
if (argc < 12) { // provide some info
cout << endl << "Welcome to ABACUS++\t(copyright J.-S. Caux)." << endl;
cout << endl << "Usage of LiebLin_DSF_MosesState_par_Prepare executable: " << endl;
cout << endl << "This function prepares an ABACUS++ parallel mode run, starting from a preexisting serial run (obtained using the LiebLin_DSF executable) using the same model parameters." << endl;
cout << endl << "Provide the following arguments:" << endl << endl;
cout << "char whichDSF \t\t Which structure factor should be calculated ? Options are: d for rho rho, g for psi psi{dagger}, o for psi{dagger} psi" << endl;
cout << "DP c_int \t\t Value of the interaction parameter: use positive real values only" << endl;
cout << "DP L \t\t\t Length of the system: use positive real values only" << endl;
cout << "int N \t\t\t Number of particles: use positive integer values only" << endl;
cout << "int Nl \t\t\t Number of particles in left Fermi sea (Nr is then N - Nl)" << endl;
cout << "int DIl \t\t shift of left sea as compared to its ground state position" << endl;
cout << "int DIr \t\t shift of right sea as compared to its ground state position" << endl;
cout << "int iKmin" << endl << "int iKmax \t\t Min and max momentum integers to scan over: recommended values: -2*N and 2*N" << endl;
cout << "int paralevel" << endl;
cout << "rank[i], nr_processors[i] \t rank and nr_processors of each earlier paralevels." << endl;
cout << "int nr_processors_at_new_level \t for this new parallelization level." << endl;
return(0);
}
else { // correct nr of arguments
int n = 1;
whichDSF = *argv[n++];
c_int = atof(argv[n++]);
L = atof(argv[n++]);
N = atoi(argv[n++]);
Nl = atoi(argv[n++]);
DIl = atoi(argv[n++]);
DIr = atoi(argv[n++]);
iKmin = atoi(argv[n++]);
iKmax = atoi(argv[n++]);
paralevel = atoi(argv[n++]); // paralevel == 1 means that we have one layer of parallelization, so no previous rank and nr_processors to specify
if (argc != 12 + 2*(paralevel - 1)) JSCerror("Wrong nr of arguments in LiebLin_DSF_MosesState_par_Prepare.");
Vect<int> rank_lower_paralevels(paralevel - 1);
Vect<int> nr_processors_lower_paralevels(paralevel - 1);
for (int i = 0; i < paralevel - 1; ++i) {
rank_lower_paralevels[i] = atoi(argv[n++]);
nr_processors_lower_paralevels[i] = atoi(argv[n++]);
}
nr_processors_at_newlevel = atoi(argv[n++]);
// Define the Moses state:
LiebLin_Bethe_State MosesState (c_int, L, N);
// Split the sea:
for (int i = 0; i < Nl; ++i) MosesState.Ix2[i] += 2 * DIl;
for (int i = Nl; i < N; ++i) MosesState.Ix2[i] += 2 * DIr;
MosesState.Compute_All (true);
// Handy default name:
stringstream defaultScanStatename_strstream;
defaultScanStatename_strstream << "Moses_Nl_" << Nl << "_DIl_" << DIl << "_DIr_" << DIr;
string defaultScanStatename = defaultScanStatename_strstream.str();
// Split up thread list into chunks, one per processor
Prepare_Parallel_Scan_LiebLin (whichDSF, c_int, L, N, iKmin, iKmax, kBT, defaultScanStatename, paralevel, rank_lower_paralevels, nr_processors_lower_paralevels, nr_processors_at_newlevel);
}
return(0);
}
+162
View File
@@ -0,0 +1,162 @@
/**********************************************************
This software is part of J.-S. Caux's ABACUS library.
Copyright (c).
-----------------------------------------------------------
File: LiebLin_DSF_par.cc
Purpose: Parallel version of ABACUS++ using MPICH.
***********************************************************/
#include "JSC.h"
#include "mpi.h"
using namespace JSC;
int main(int argc, char *argv[])
{
char whichDSF;
DP c_int, L;
int N, Nl, DIl, DIr, iKmin, iKmax, Max_Secs, supercycle_time, paralevel;
DP target_sumrule = 1.0e+6; // effectively deactivated here
bool refine = true; // always true for parallel mode
DP kBT = 0.0; // dummy
if (argc < 13) { // provide some info
cout << endl << "Welcome to ABACUS++\t(copyright J.-S. Caux)." << endl;
cout << endl << "Usage of LiebLin_DSF_MosesState_par_Run executable: " << endl;
cout << endl << "This function runs ABACUS++ in parallel mode, starting from a preexisting serial run (obtained using the LiebLin_DSF executable) using the same model parameters." << endl;
cout << endl << "Provide the following arguments:" << endl << endl;
cout << "char whichDSF \t\t Which structure factor should be calculated ? Options are: d for rho rho, g for psi psi{dagger}, o for psi{dagger} psi" << endl;
cout << "DP c_int \t\t Value of the interaction parameter: use positive real values only" << endl;
cout << "DP L \t\t\t Length of the system: use positive real values only" << endl;
cout << "int N \t\t\t Number of particles: use positive integer values only" << endl;
cout << "int Nl \t\t\t Number of particles in left Fermi sea (Nr is then N - Nl)" << endl;
cout << "int DIl \t\t shift of left sea as compared to its ground state position" << endl;
cout << "int DIr \t\t shift of right sea as compared to its ground state position" << endl;
cout << "int iKmin" << endl << "int iKmax \t\t Min and max momentum integers to scan over: recommended values: -2*N and 2*N" << endl;
cout << "int paralevel" << endl;
cout << "rank[i], nr_processors[i] \t rank and nr_processors of each earlier paralevels." << endl;
cout << "int Max_Secs \t\t Allowed computational time: (in seconds)" << endl;
cout << "int supercycle_time \t\t time for one supercycle (in seconds)" << endl;
return(0);
}
//else { // correct nr of arguments
int n = 1;
whichDSF = *argv[n++];
c_int = atof(argv[n++]);
L = atof(argv[n++]);
N = atoi(argv[n++]);
Nl = atoi(argv[n++]);
DIl = atoi(argv[n++]);
DIr = atoi(argv[n++]);
iKmin = atoi(argv[n++]);
iKmax = atoi(argv[n++]);
paralevel = atoi(argv[n++]); // paralevel == 1 means that we have one layer of parallelization, so no previous rank and nr_processors to specify
if (argc != 13 + 2*(paralevel - 1)) JSCerror("Wrong nr of arguments in LiebLin_DSF_par_Prepare.");
Vect<int> rank_lower_paralevels(paralevel - 1);
Vect<int> nr_processors_lower_paralevels(paralevel - 1);
for (int i = 0; i < paralevel - 1; ++i) {
rank_lower_paralevels[i] = atoi(argv[n++]);
nr_processors_lower_paralevels[i] = atoi(argv[n++]);
}
Max_Secs = atoi(argv[n++]);
supercycle_time = atoi(argv[n++]);
//}
//DP supercycle_time = 600.0; // allotted time per supercycle
if (Max_Secs <= supercycle_time) JSCerror("Please allow more time in LiebLin_DSF_par_Run.");
MPI::Init(argc, argv);
DP tstart = MPI::Wtime();
int rank_here = MPI::COMM_WORLD.Get_rank();
int nr_processors_here = MPI::COMM_WORLD.Get_size();
//cout << "rank " << rank_here << " out of " << nr_processors_here << " ready to go." << endl;
Vect<int> rank (paralevel);
Vect<int> nr_processors (paralevel);
for (int i = 0; i < paralevel - 1; ++i) {
rank[i] = rank_lower_paralevels[i];
nr_processors[i] = nr_processors_lower_paralevels[i];
}
rank[paralevel-1] = rank_here;
nr_processors[paralevel-1] = nr_processors_here;
if (nr_processors_here < 2) JSCerror("Give at least 2 processors to ABACUS++ parallel !");
refine = true;
// ASSUMPTION: preexisting files (raw, thr, ...) exist for the run.
DP tnow = MPI::Wtime();
// Define the Moses state:
LiebLin_Bethe_State MosesState (c_int, L, N);
// Split the sea:
for (int i = 0; i < Nl; ++i) MosesState.Ix2[i] += 2 * DIl;
for (int i = Nl; i < N; ++i) MosesState.Ix2[i] += 2 * DIr;
MosesState.Compute_All (true);
// Handy default name:
stringstream defaultScanStatename_strstream;
defaultScanStatename_strstream << "Moses_Nl_" << Nl << "_DIl_" << DIl << "_DIr_" << DIr;
string defaultScanStatename = defaultScanStatename_strstream.str();
//cout << "rank " << rank_here << " out of " << nr_processors_here << " waiting at barrier." << endl;
MPI_Barrier (MPI::COMM_WORLD);
while (tnow - tstart < Max_Secs - supercycle_time - 120) { // space for one more supercycle, + 2 minutes safety
//if (rank == 0)
// Split up thread list into chunks, one per processor
//Prepare_Parallel_Scan_LiebLin (whichDSF, c_int, L, N, iK_UL, fixed_iK, iKneeded, nr_processors);
//Prepare_Parallel_Scan_LiebLin (whichDSF, c_int, L, N, iKmin, iKmax, kBT, defaultScanStatename, nr_processors);
// Barrier synchronization, to make sure other processes wait for process of rank 0
// to have finished splitting up the thr file into pieces before starting:
MPI_Barrier (MPI::COMM_WORLD);
// then everybody gets going on their own chunk !
//Scan_LiebLin (whichDSF, c_int, L, N, iK_UL, fixed_iK, iKneeded,
//Scan_LiebLin (whichDSF, c_int, L, N, iKmin, iKmax, kBT, supercycle_time, target_sumrule, refine, paralevel, rank, nr_processors);
Scan_LiebLin (whichDSF, MosesState, defaultScanStatename, iKmin, iKmax, supercycle_time, target_sumrule, refine, paralevel, rank, nr_processors);
// Another barrier synchronization
MPI_Barrier (MPI::COMM_WORLD);
// Now that everybody is done, digest data into unique files
//if (rank == 0)
//Wrapup_Parallel_Scan_LiebLin (whichDSF, c_int, L, N, iK_UL, fixed_iK, iKneeded, nr_processors);
//Wrapup_Parallel_Scan_LiebLin (whichDSF, c_int, L, N, iKmin, iKmax, kBT, defaultScanStatename, nr_processors);
// Another barrier synchronization
MPI_Barrier (MPI::COMM_WORLD);
tnow = MPI::Wtime();
} // while (tnow - tstart...
MPI::Finalize();
return(0);
}
@@ -0,0 +1,96 @@
/**********************************************************
This software is part of J.-S. Caux's ABACUS library.
Copyright (c).
-----------------------------------------------------------
File: LiebLin_DSF_MosesState_par_Wrapup.cc
Purpose: Parallel version of ABACUS++ using MPICH.
***********************************************************/
#include "JSC.h"
//#include "mpi.h" // not needed for Prepare
using namespace JSC;
int main(int argc, char *argv[])
{
char whichDSF;
DP c_int, L;
int N, Nl, DIl, DIr, iKmin, iKmax, paralevel, nr_processors_at_newlevel;
DP target_sumrule = 1.0e+6; // effectively deactivated here
bool refine = true; // always true for parallel mode
DP kBT = 0.0; // dummy
if (argc < 12) { // provide some info
cout << endl << "Welcome to ABACUS++\t(copyright J.-S. Caux)." << endl;
cout << endl << "Usage of LiebLin_DSF_MosesState_par_Wrapup executable: " << endl;
cout << endl << "This function wraps up an ABACUS++ parallel mode run." << endl;
cout << endl << "Provide the following arguments:" << endl << endl;
cout << "char whichDSF \t\t Which structure factor should be calculated ? Options are: d for rho rho, g for psi psi{dagger}, o for psi{dagger} psi" << endl;
cout << "DP c_int \t\t Value of the interaction parameter: use positive real values only" << endl;
cout << "DP L \t\t\t Length of the system: use positive real values only" << endl;
cout << "int N \t\t\t Number of particles: use positive integer values only" << endl;
cout << "int Nl \t\t\t Number of particles in left Fermi sea (Nr is then N - Nl)" << endl;
cout << "int DIl \t\t shift of left sea as compared to its ground state position" << endl;
cout << "int DIr \t\t shift of right sea as compared to its ground state position" << endl;
cout << "int iKmin" << endl << "int iKmax \t\t Min and max momentum integers to scan over: recommended values: -2*N and 2*N" << endl;
cout << "int paralevel" << endl;
cout << "rank[i], nr_processors[i] \t rank and nr_processors of each earlier paralevels." << endl;
cout << "int nr_processors_at_new_level \t for this new parallelization level." << endl;
return(0);
}
else { // correct nr of arguments
int n = 1;
whichDSF = *argv[n++];
c_int = atof(argv[n++]);
L = atof(argv[n++]);
N = atoi(argv[n++]);
Nl = atoi(argv[n++]);
DIl = atoi(argv[n++]);
DIr = atoi(argv[n++]);
iKmin = atoi(argv[n++]);
iKmax = atoi(argv[n++]);
paralevel = atoi(argv[n++]); // paralevel == 1 means that we have one layer of parallelization, so no previous rank and nr_processors to specify
if (argc != 12 + 2*(paralevel - 1)) JSCerror("Wrong nr of arguments in LiebLin_DSF_MosesState_par_Prepare.");
Vect<int> rank_lower_paralevels(paralevel - 1);
Vect<int> nr_processors_lower_paralevels(paralevel - 1);
for (int i = 0; i < paralevel - 1; ++i) {
rank_lower_paralevels[i] = atoi(argv[n++]);
nr_processors_lower_paralevels[i] = atoi(argv[n++]);
}
nr_processors_at_newlevel = atoi(argv[n++]);
// Define the Moses state:
LiebLin_Bethe_State MosesState (c_int, L, N);
// Split the sea:
for (int i = 0; i < Nl; ++i) MosesState.Ix2[i] += 2 * DIl;
for (int i = Nl; i < N; ++i) MosesState.Ix2[i] += 2 * DIr;
MosesState.Compute_All (true);
// Handy default name:
stringstream defaultScanStatename_strstream;
defaultScanStatename_strstream << "Moses_Nl_" << Nl << "_DIl_" << DIl << "_DIr_" << DIr;
string defaultScanStatename = defaultScanStatename_strstream.str();
// Digest files into a unique one for the latest paralevel:
Wrapup_Parallel_Scan_LiebLin (whichDSF, c_int, L, N, iKmin, iKmax, kBT, defaultScanStatename, paralevel, rank_lower_paralevels, nr_processors_lower_paralevels, nr_processors_at_newlevel);
}
return(0);
}
+99
View File
@@ -0,0 +1,99 @@
/**********************************************************
This software is part of J.-S. Caux's ABACUS library.
Copyright (c).
-----------------------------------------------------------
File: LiebLin_DSF_over_Ensemble.cc
Purpose: main function for ABACUS++T for LiebLin gas, averaging over an Ensemble.
***********************************************************/
#include "JSC.h"
using namespace std;
using namespace JSC;
int main(int argc, char* argv[])
{
if (argc != 10) { // provide some info
cout << endl << "Welcome to ABACUS++\t(copyright J.-S. Caux)." << endl;
cout << endl << "Usage of LiebLin_DSF_Tgt0 executable: " << endl;
cout << endl << "Provide the following arguments:" << endl << endl;
cout << "char whichDSF \t\t Which structure factor should be calculated ? Options are: d for rho rho, g for psi psi{dagger}, o for psi{dagger} psi" << endl;
cout << "DP c_int \t\t Value of the interaction parameter: use positive real values only" << endl;
cout << "DP L \t\t\t Length of the system: use positive real values only" << endl;
cout << "int N \t\t\t Number of particles: use positive integer values only" << endl;
cout << "int iKmin" << endl << "int iKmax \t\t Min and max momentum integers to scan over: recommended values: -2*N and 2*N" << endl;
cout << "DP kBT \t\t Temperature (positive only of course)" << endl;
//cout << "int nstates \t\t\t Number of states to be considered in the ensemble" << 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 earlier calculations ? (0 == false, 1 == true)" << endl;
cout << endl << "EXAMPLE: " << endl << endl;
cout << "LiebLin_DSF_over_Ensemble d 1.0 100.0 100 0 200 0.56 10 600 0" << endl << endl;
}
else { // (argc == 10), correct nr of arguments
char whichDSF = *argv[1];
DP c_int = atof(argv[2]);
DP L = atof(argv[3]);
int N = atoi(argv[4]);
int iKmin = atoi(argv[5]);
int iKmax = atoi(argv[6]);
DP kBT = atof(argv[7]);
//int nstates_req = atoi(argv[8]);
int Max_Secs = atoi(argv[8]);
bool refine = (atoi(argv[9]) == 1);
// Start by constructing (or loading) the state ensemble.
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();
if (!refine) { // Construct the state ensemble
//ensemble = LiebLin_Thermal_Saddle_Point_Ensemble (c_int, L, N, kBT, nstates_req);
ensemble = LiebLin_Thermal_Saddle_Point_Ensemble (c_int, L, N, kBT);
ensemble.Save(ensfile_Cstr); // Save the ensemble
}
else { // load the ensemble data
ensemble.Load(c_int, L, N, ensfile_Cstr);
}
// Now perform the DSF calculation over each state in the ensemble, distributing the time according to the weight
for (int ns = 0; ns < ensemble.nstates; ++ns) {
//void Scan_LiebLin (char whichDSF, LiebLin_Bethe_State AveragingState, string defaultScanStatename, int iKmin, int iKmax,
//int Max_Secs, DP target_sumrule, bool refine, int rank, int nr_processors)
//Scan_LiebLin (whichDSF, ensemble.state[ns], ensemble.state[ns].label, iKmin, iKmax, int(Max_Secs * ensemble.weight[ns]), 1.0e+6, refine, 0, 1);
Scan_LiebLin (whichDSF, ensemble.state[ns], ensemble.state[ns].label, iKmin, iKmax, int(Max_Secs * ensemble.weight[ns]), 1.0e+6, refine);
}
// Evaluate the f-sumrule
stringstream FSR_stringstream; string FSR_string;
Data_File_Name (FSR_stringstream, whichDSF, c_int, L, N, iKmin, iKmax, kBT, 0.0, "");
FSR_stringstream << "_ns_" << ensemble.nstates << ".fsr";
FSR_string = FSR_stringstream.str(); const char* FSR_Cstr = FSR_string.c_str();
DP Chem_Pot = 0.0;
Evaluate_F_Sumrule (whichDSF, c_int, L, N, kBT, ensemble.nstates, Chem_Pot, iKmin, iKmax, FSR_Cstr);
} // correct nr of arguments
return(0);
}
+191
View File
@@ -0,0 +1,191 @@
/**********************************************************
This software is part of J.-S. Caux's ABACUS library.
Copyright (c).
-----------------------------------------------------------
File: LiebLin_DSF_over_Ensemble_par.cc
Purpose: main function for ABACUS for LiebLin gas, averaging over an Ensemble, parallel implementation.
***********************************************************/
#include "JSC.h"
#include "mpi.h"
using namespace std;
using namespace JSC;
int main(int argc, char* argv[])
{
if (argc != 10) { // provide some info
cout << endl << "Welcome to ABACUS++\t(copyright J.-S. Caux)." << endl;
cout << endl << "Usage of LiebLin_DSF_Tgt0 executable: " << endl;
cout << endl << "Provide the following arguments:" << endl << endl;
cout << "char whichDSF \t\t Which structure factor should be calculated ? Options are: d for rho rho, g for psi psi{dagger}, o for psi{dagger} psi" << endl;
cout << "DP c_int \t\t Value of the interaction parameter: use positive real values only" << endl;
cout << "DP L \t\t\t Length of the system: use positive real values only" << endl;
cout << "int N \t\t\t Number of particles: use positive integer values only" << endl;
cout << "int iKmin" << endl << "int iKmax \t\t Min and max momentum integers to scan over: recommended values: -2*N and 2*N" << endl;
cout << "DP kBT \t\t Temperature (positive only of course)" << endl;
//cout << "int nstates \t\t\t Number of states to be considered in the ensemble" << 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 earlier calculations ? (0 == false, 1 == true)" << endl;
cout << endl << "EXAMPLE: " << endl << endl;
cout << "LiebLin_DSF_over_Ensemble d 1.0 100.0 100 0 200 0.56 10 600 0" << endl << endl;
}
else { // (argc == 10), correct nr of arguments
char whichDSF = *argv[1];
DP c_int = atof(argv[2]);
DP L = atof(argv[3]);
int N = atoi(argv[4]);
int iKmin = atoi(argv[5]);
int iKmax = atoi(argv[6]);
DP kBT = atof(argv[7]);
//int nstates_req = atoi(argv[8]);
int Max_Secs = atoi(argv[8]);
bool refine = (atoi(argv[9]) == 1);
if (refine == false) JSCerror("Please run the serial version of LiebLin_DSF_over_Ensemble first.");
MPI::Init(argc, argv);
DP tstart = MPI::Wtime();
int rank = MPI::COMM_WORLD.Get_rank();
int nr_processors = MPI::COMM_WORLD.Get_size();
if (nr_processors < 2) JSCerror("Give at least 2 processors to ABACUS++ parallel !");
// Start by constructing (or loading) the state ensemble.
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();
if (!refine) { // Construct the state ensemble
//ensemble = LiebLin_Thermal_Saddle_Point_Ensemble (c_int, L, N, kBT, nstates_req);
ensemble = LiebLin_Thermal_Saddle_Point_Ensemble (c_int, L, N, kBT);
ensemble.Save(ensfile_Cstr); // Save the ensemble
}
else { // load the ensemble data
ensemble.Load(c_int, L, N, ensfile_Cstr);
}
MPI_Barrier (MPI::COMM_WORLD);
// Now perform the DSF calculation over each state in the ensemble
/* Original implementation: Scan always called serially. Superseded by version below, using successive parallel scans on each state in the ensemble.
int nDSFperproc = ensemble.nstates/nr_processors + 1;
//if (ensemble.nstates % nr_processors) JSCerror("Use nr_processors * integer multiple == ensemble.nstates in LiebLin_DSF_over_Ensemble_par.");
// Processor with rank r does all
int ns;
int Max_Secs_used = Max_Secs/nDSFperproc;
for (int ir = 0; ir < nDSFperproc; ++ir) {
ns = rank + ir * nr_processors;
//void Scan_LiebLin (char whichDSF, LiebLin_Bethe_State AveragingState, string defaultScanStatename, int iKmin, int iKmax,
//int Max_Secs, DP target_sumrule, bool refine, int rank, int nr_processors)
if (ns < ensemble.nstates) {
//cout << "Processor rank " << rank << " going for ns = " << ns << " out of " << ensemble.nstates << endl;
Scan_LiebLin (whichDSF, ensemble.state[ns], ensemble.state[ns].label, iKmin, iKmax, Max_Secs_used, 1.0e+6, refine, 0, 1);
}
}
*/
// Version 2013 04 24:
// Makes use of a parallel scan for each state in the ensemble, in succession.
// Code is simple adaptation of LiebLin_DSF_par executable code.
int Max_Secs_used = Max_Secs/ensemble.nstates;
DP supercycle_time = 600.0; // allotted time per supercycle
if (Max_Secs_used <= supercycle_time) JSCerror("Please allow more time in LiebLin_DSF_par.");
// Main loop over ensemble:
for (int ns = 0; ns < ensemble.nstates; ++ns) {
tstart = MPI::Wtime();
DP tnow = MPI::Wtime();
string defaultScanStatename = ensemble.state[ns].label;
while (tnow - tstart < Max_Secs_used - supercycle_time) { // space for one more supercycle
if (rank == 0)
// Split up thread list into chunks, one per processor
//Prepare_Parallel_Scan_LiebLin (whichDSF, c_int, L, N, iK_UL, fixed_iK, iKneeded, nr_processors);
Prepare_Parallel_Scan_LiebLin (whichDSF, c_int, L, N, iKmin, iKmax, kBT, defaultScanStatename, nr_processors);
// Barrier synchronization, to make sure other processes wait for process of rank 0
// to have finished splitting up the thr file into pieces before starting:
MPI_Barrier (MPI::COMM_WORLD);
// then everybody gets going on their own chunk !
//Scan_LiebLin (whichDSF, c_int, L, N, iK_UL, fixed_iK, iKneeded,
//Scan_LiebLin (whichDSF, c_int, L, N, iKmin, iKmax, kBT,
//supercycle_time, target_sumrule, refine, rank, nr_processors);
Scan_LiebLin (whichDSF, ensemble.state[ns], ensemble.state[ns].label, iKmin, iKmax, supercycle_time, 1.0e+6, refine, rank, nr_processors);
// Another barrier synchronization
MPI_Barrier (MPI::COMM_WORLD);
// Now that everybody is done, digest data into unique files
if (rank == 0)
//Wrapup_Parallel_Scan_LiebLin (whichDSF, c_int, L, N, iK_UL, fixed_iK, iKneeded, nr_processors);
Wrapup_Parallel_Scan_LiebLin (whichDSF, c_int, L, N, iKmin, iKmax, kBT, defaultScanStatename, nr_processors);
// Another barrier synchronization
MPI_Barrier (MPI::COMM_WORLD);
tnow = MPI::Wtime();
} // while (tnow - tstart...
} // for ns
MPI_Barrier (MPI::COMM_WORLD);
// Final wrapup of the data
if (rank == 0) {
// Evaluate the f-sumrule
stringstream FSR_stringstream; string FSR_string;
Data_File_Name (FSR_stringstream, whichDSF, c_int, L, N, iKmin, iKmax, kBT, 0.0, "");
FSR_stringstream << "_ns_" << ensemble.nstates << ".fsr";
FSR_string = FSR_stringstream.str(); const char* FSR_Cstr = FSR_string.c_str();
DP Chem_Pot = 0.0;
Evaluate_F_Sumrule (whichDSF, c_int, L, N, kBT, ensemble.nstates, Chem_Pot, iKmin, iKmax, FSR_Cstr);
}
MPI_Barrier (MPI::COMM_WORLD);
} // correct nr of arguments
MPI::Finalize();
return(0);
}
+119
View File
@@ -0,0 +1,119 @@
/**********************************************************
This software is part of J.-S. Caux's ABACUS library.
Copyright (c).
-----------------------------------------------------------
File: LiebLin_DSF_par.cc
Purpose: Parallel version of ABACUS++ using MPICH.
***********************************************************/
#include "JSC.h"
#include "mpi.h"
using namespace JSC;
int main(int argc, char *argv[])
{
char whichDSF;
DP c_int, L, kBT;
int N, iKmin, iKmax, Max_Secs, supercycle_time;
DP target_sumrule = 1.0e+6; // effectively deactivated here
bool refine = true; // always true for parallel mode
if (argc != 10) { // provide some info
cout << endl << "Welcome to ABACUS++\t(copyright J.-S. Caux)." << endl;
cout << endl << "Usage of LiebLin_DSF_par executable: " << endl;
cout << endl << "This function runs ABACUS++ in parallel mode, starting from a preexisting serial run (obtained using the LiebLin_DSF executable) using the same model parameters." << endl;
cout << endl << "Provide the following arguments:" << endl << endl;
cout << "char whichDSF \t\t Which structure factor should be calculated ? Options are: d for rho rho, g for psi psi{dagger}, o for psi{dagger} psi" << endl;
cout << "DP c_int \t\t Value of the interaction parameter: use positive real values only" << endl;
cout << "DP L \t\t\t Length of the system: use positive real values only" << endl;
cout << "int N \t\t\t Number of particles: use positive integer values only" << endl;
cout << "int iKmin" << endl << "int iKmax \t\t Min and max momentum integers to scan over: recommended values: -2*N and 2*N" << endl;
cout << "DP kBT \t\t Temperature (positive only of course)" << endl;
cout << "int Max_Secs \t\t Allowed computational time: (in seconds)" << endl;
cout << "int supercycle_time \t\t time for one supercycle (in seconds)" << endl;
cout << endl << "EXAMPLE: " << endl << endl;
cout << "mpiexec -np 8 LiebLin_DSF_MosesState_par d 1.0 100.0 100 -400 400 0.0 3600 600" << endl << endl;
return(0);
}
else { // (argc == 9) correct nr of arguments
whichDSF = *argv[1];
c_int = atof(argv[2]);
L = atof(argv[3]);
N = atoi(argv[4]);
iKmin = atoi(argv[5]);
iKmax = atoi(argv[6]);
kBT = atof(argv[7]);
Max_Secs = atoi(argv[8]);
supercycle_time = atoi(argv[9]);
}
//DP supercycle_time = 600.0; // allotted time per supercycle
if (Max_Secs <= supercycle_time) JSCerror("Please allow more time in LiebLin_DSF_par.");
MPI::Init(argc, argv);
DP tstart = MPI::Wtime();
int rank = MPI::COMM_WORLD.Get_rank();
int nr_processors = MPI::COMM_WORLD.Get_size();
if (nr_processors < 2) JSCerror("Give at least 2 processors to ABACUS++ parallel !");
refine = true;
// ASSUMPTION: preexisting files (raw, thr, ...) exist for the run.
DP tnow = MPI::Wtime();
string defaultScanStatename = "";
while (tnow - tstart < Max_Secs - supercycle_time - 120) { // space for one more supercycle, + 2 minutes safety
if (rank == 0)
// Split up thread list into chunks, one per processor
//Prepare_Parallel_Scan_LiebLin (whichDSF, c_int, L, N, iK_UL, fixed_iK, iKneeded, nr_processors);
Prepare_Parallel_Scan_LiebLin (whichDSF, c_int, L, N, iKmin, iKmax, kBT, defaultScanStatename, nr_processors);
// Barrier synchronization, to make sure other processes wait for process of rank 0
// to have finished splitting up the thr file into pieces before starting:
MPI_Barrier (MPI::COMM_WORLD);
// then everybody gets going on their own chunk !
//Scan_LiebLin (whichDSF, c_int, L, N, iK_UL, fixed_iK, iKneeded,
Scan_LiebLin (whichDSF, c_int, L, N, iKmin, iKmax, kBT,
supercycle_time, target_sumrule, refine, rank, nr_processors);
// Another barrier synchronization
MPI_Barrier (MPI::COMM_WORLD);
// Now that everybody is done, digest data into unique files
if (rank == 0)
//Wrapup_Parallel_Scan_LiebLin (whichDSF, c_int, L, N, iK_UL, fixed_iK, iKneeded, nr_processors);
Wrapup_Parallel_Scan_LiebLin (whichDSF, c_int, L, N, iKmin, iKmax, kBT, defaultScanStatename, nr_processors);
// Another barrier synchronization
MPI_Barrier (MPI::COMM_WORLD);
tnow = MPI::Wtime();
} // while (tnow - tstart...
MPI::Finalize();
return(0);
}
+77
View File
@@ -0,0 +1,77 @@
/**********************************************************
This software is part of J.-S. Caux's ABACUS library.
Copyright (c).
-----------------------------------------------------------
File: LiebLin_DSF_par_Prepare.cc
Purpose: Parallel version of ABACUS++ using MPICH.
***********************************************************/
#include "JSC.h"
//#include "mpi.h" // not needed for Prepare
using namespace JSC;
int main(int argc, char *argv[])
{
char whichDSF;
DP c_int, L, kBT;
int N, iKmin, iKmax, paralevel, nr_processors_at_newlevel;
DP target_sumrule = 1.0e+6; // effectively deactivated here
bool refine = true; // always true for parallel mode
if (argc < 10) { // provide some info
cout << endl << "Welcome to ABACUS++\t(copyright J.-S. Caux)." << endl;
cout << endl << "Usage of LiebLin_DSF_par_Prepare executable: " << endl;
cout << endl << "This function prepares an ABACUS++ parallel mode run, starting from a preexisting serial run (obtained using the LiebLin_DSF executable) using the same model parameters." << endl;
cout << endl << "Provide the following arguments:" << endl << endl;
cout << "char whichDSF \t\t Which structure factor should be calculated ? Options are: d for rho rho, g for psi psi{dagger}, o for psi{dagger} psi" << endl;
cout << "DP c_int \t\t Value of the interaction parameter: use positive real values only" << endl;
cout << "DP L \t\t\t Length of the system: use positive real values only" << endl;
cout << "int N \t\t\t Number of particles: use positive integer values only" << endl;
cout << "int iKmin" << endl << "int iKmax \t\t Min and max momentum integers to scan over: recommended values: -2*N and 2*N" << endl;
cout << "DP kBT \t\t Temperature (positive only of course)" << endl;
cout << "int paralevel" << endl;
cout << "rank[i], nr_processors[i] \t rank and nr_processors of each earlier paralevels." << endl;
cout << "int nr_processors_at_new_level \t for this new parallelization level." << endl;
return(0);
}
else { // correct nr of arguments
int n = 1;
whichDSF = *argv[n++];
c_int = atof(argv[n++]);
L = atof(argv[n++]);
N = atoi(argv[n++]);
iKmin = atoi(argv[n++]);
iKmax = atoi(argv[n++]);
kBT = atof(argv[n++]);
paralevel = atoi(argv[n++]); // paralevel == 1 means that we have one layer of parallelization, so no previous rank and nr_processors to specify
if (argc != 10 + 2*(paralevel - 1)) JSCerror("Wrong nr of arguments in LiebLin_DSF_par_Prepare.");
Vect<int> rank_lower_paralevels(paralevel - 1);
Vect<int> nr_processors_lower_paralevels(paralevel - 1);
for (int i = 0; i < paralevel - 1; ++i) {
rank_lower_paralevels[i] = atoi(argv[n++]);
nr_processors_lower_paralevels[i] = atoi(argv[n++]);
}
nr_processors_at_newlevel = atoi(argv[n++]);
string defaultScanStatename = "";
// Split up thread list into chunks, one per processor
Prepare_Parallel_Scan_LiebLin (whichDSF, c_int, L, N, iKmin, iKmax, kBT, defaultScanStatename, paralevel, rank_lower_paralevels, nr_processors_lower_paralevels, nr_processors_at_newlevel);
}
return(0);
}
+120
View File
@@ -0,0 +1,120 @@
/**********************************************************
This software is part of J.-S. Caux's ABACUS library.
Copyright (c).
-----------------------------------------------------------
File: LiebLin_DSF_par_Run.cc
Purpose: Parallel version of ABACUS++ using MPICH.
***********************************************************/
#include "JSC.h"
#include "mpi.h"
using namespace JSC;
int main(int argc, char *argv[])
{
char whichDSF;
DP c_int, L, kBT;
int N, iKmin, iKmax, Max_Secs, paralevel;
DP target_sumrule = 1.0e+6; // effectively deactivated here
bool refine = true; // always true for parallel mode
if (argc < 10) { // provide some info
cout << endl << "Welcome to ABACUS++\t(copyright J.-S. Caux)." << endl;
cout << endl << "Usage of LiebLin_DSF_par_Run executable: " << endl;
cout << endl << "This function runs ABACUS++ in parallel mode, starting from a preexisting serial run (obtained using the LiebLin_DSF executable) using the same model parameters." << endl;
cout << endl << "Provide the following arguments:" << endl << endl;
cout << "char whichDSF \t\t Which structure factor should be calculated ? Options are: d for rho rho, g for psi psi{dagger}, o for psi{dagger} psi" << endl;
cout << "DP c_int \t\t Value of the interaction parameter: use positive real values only" << endl;
cout << "DP L \t\t\t Length of the system: use positive real values only" << endl;
cout << "int N \t\t\t Number of particles: use positive integer values only" << endl;
cout << "int iKmin" << endl << "int iKmax \t\t Min and max momentum integers to scan over: recommended values: -2*N and 2*N" << endl;
cout << "DP kBT \t\t Temperature (positive only of course)" << endl;
cout << "int paralevel" << endl;
cout << "rank[i], nr_processors[i] \t rank and nr_processors of each earlier paralevels." << endl;
cout << "int Max_Secs \t\t Allowed computational time: (in seconds)" << endl;
cout << endl << "EXAMPLE: " << endl << endl;
cout << "mpiexec -np 8 LiebLin_DSF_par_Run d 1.0 100.0 100 0 400 0.0 1 3600" << endl << endl;
return(0);
}
int n = 1;
whichDSF = *argv[n++];
c_int = atof(argv[n++]);
L = atof(argv[n++]);
N = atoi(argv[n++]);
iKmin = atoi(argv[n++]);
iKmax = atoi(argv[n++]);
kBT = atof(argv[n++]);
paralevel = atoi(argv[n++]); // paralevel == 1 means that we have one layer of parallelization, so no previous rank and nr_processors to specify
if (argc != 10 + 2*(paralevel - 1)) JSCerror("Wrong nr of arguments in LiebLin_DSF_par_Run.");
Vect<int> rank_lower_paralevels(paralevel - 1);
Vect<int> nr_processors_lower_paralevels(paralevel - 1);
for (int i = 0; i < paralevel - 1; ++i) {
rank_lower_paralevels[i] = atoi(argv[n++]);
nr_processors_lower_paralevels[i] = atoi(argv[n++]);
}
Max_Secs = atoi(argv[n++]);
if (Max_Secs < 120) JSCerror("Please allow more time in LiebLin_DSF_par_Run.");
int Max_Secs_used = Max_Secs - 120;
MPI::Init(argc, argv);
DP tstart = MPI::Wtime();
int rank_here = MPI::COMM_WORLD.Get_rank();
int nr_processors_here = MPI::COMM_WORLD.Get_size();
Vect<int> rank (paralevel);
Vect<int> nr_processors (paralevel);
for (int i = 0; i < paralevel - 1; ++i) {
rank[i] = rank_lower_paralevels[i];
nr_processors[i] = nr_processors_lower_paralevels[i];
}
rank[paralevel-1] = rank_here;
nr_processors[paralevel-1] = nr_processors_here;
if (nr_processors_here < 2) JSCerror("Give at least 2 processors to ABACUS parallel !");
refine = true;
// ASSUMPTION: preexisting files (raw, thr, ...) exist for the run.
DP tnow = MPI::Wtime();
string defaultScanStatename = "";
if (Max_Secs_used > 0) { // space for 2 minutes safety
// Barrier synchronization
MPI_Barrier (MPI::COMM_WORLD);
// then everybody gets going on their own chunk !
//Scan_LiebLin (whichDSF, c_int, L, N, iK_UL, fixed_iK, iKneeded,
Scan_LiebLin (whichDSF, c_int, L, N, iKmin, iKmax, kBT,
Max_Secs_used, target_sumrule, refine, paralevel, rank, nr_processors);
// Another barrier synchronization
MPI_Barrier (MPI::COMM_WORLD);
tnow = MPI::Wtime();
}
MPI::Finalize();
return(0);
}
+77
View File
@@ -0,0 +1,77 @@
/**********************************************************
This software is part of J.-S. Caux's ABACUS library.
Copyright (c).
-----------------------------------------------------------
File: LiebLin_DSF_par_Wrapup.cc
Purpose: Parallel version of ABACUS++ using MPICH.
***********************************************************/
#include "JSC.h"
//#include "mpi.h" // not needed for Prepare or Wrapup
using namespace JSC;
int main(int argc, char *argv[])
{
char whichDSF;
DP c_int, L, kBT;
int N, iKmin, iKmax, paralevel, nr_processors_at_newlevel;
DP target_sumrule = 1.0e+6; // effectively deactivated here
bool refine = true; // always true for parallel mode
if (argc < 10) { // provide some info
cout << endl << "Welcome to ABACUS++\t(copyright J.-S. Caux)." << endl;
cout << endl << "Usage of LiebLin_DSF_par_Wrapup executable: " << endl;
cout << endl << "This function wraps up an ABACUS++ parallel mode run." << endl;
cout << endl << "Provide the following arguments:" << endl << endl;
cout << "char whichDSF \t\t Which structure factor should be calculated ? Options are: d for rho rho, g for psi psi{dagger}, o for psi{dagger} psi" << endl;
cout << "DP c_int \t\t Value of the interaction parameter: use positive real values only" << endl;
cout << "DP L \t\t\t Length of the system: use positive real values only" << endl;
cout << "int N \t\t\t Number of particles: use positive integer values only" << endl;
cout << "int iKmin" << endl << "int iKmax \t\t Min and max momentum integers to scan over: recommended values: -2*N and 2*N" << endl;
cout << "DP kBT \t\t Temperature (positive only of course)" << endl;
cout << "int paralevel" << endl;
cout << "rank[i], nr_processors[i] \t rank and nr_processors of each earlier paralevels." << endl;
cout << "int nr_processors_at_new_level \t for this latest parallelization level." << endl;
return(0);
}
else { // correct nr of arguments
int n = 1;
whichDSF = *argv[n++];
c_int = atof(argv[n++]);
L = atof(argv[n++]);
N = atoi(argv[n++]);
iKmin = atoi(argv[n++]);
iKmax = atoi(argv[n++]);
kBT = atof(argv[n++]);
paralevel = atoi(argv[n++]); // paralevel == 1 means that we have one layer of parallelization, so no previous rank and nr_processors to specify
if (argc != 10 + 2*(paralevel - 1)) JSCerror("Wrong nr of arguments in LiebLin_DSF_par_Wrapup.");
Vect<int> rank_lower_paralevels(paralevel - 1);
Vect<int> nr_processors_lower_paralevels(paralevel - 1);
for (int i = 0; i < paralevel - 1; ++i) {
rank_lower_paralevels[i] = atoi(argv[n++]);
nr_processors_lower_paralevels[i] = atoi(argv[n++]);
}
nr_processors_at_newlevel = atoi(argv[n++]);
string defaultScanStatename = "";
// Digest files into a unique one for the latest paralevel:
Wrapup_Parallel_Scan_LiebLin (whichDSF, c_int, L, N, iKmin, iKmax, kBT, defaultScanStatename, paralevel, rank_lower_paralevels, nr_processors_lower_paralevels, nr_processors_at_newlevel);
}
return(0);
}
+92
View File
@@ -0,0 +1,92 @@
/**********************************************************
This software is part of J.-S. Caux's ABACUS library.
Copyright (c).
-----------------------------------------------------------
File: LiebLin_DSF_tester.cc
Purpose: allows for Ix2 manipulations (user-prompted) for LiebLin gas
***********************************************************/
#include "JSC.h"
using namespace std;
using namespace JSC;
int main(int argc, char* argv[])
{
if (argc != 6) { // provide some info
cout << endl << "Welcome to ABACUS++\t(copyright J.-S. Caux)." << endl;
cout << endl << "Usage of LiebLin_DSF_tester executable: " << endl;
cout << endl << "Provide the following arguments:" << endl << endl;
cout << "char whichDSF \t\t Which structure factor should be calculated ? Options are: d for rho rho, g for psi psi{dagger}, o for psi{dagger} psi" << endl;
cout << "DP c_int \t\t Value of the interaction parameter: use positive real values only" << endl;
cout << "DP L \t\t\t Length of the system: use positive real values only" << endl;
cout << "int N \t\t\t Number of particles: use positive integer values only" << endl;
cout << "DP kBT \t\t Temperature (positive only of course)" << endl;
cout << endl << "EXAMPLE: " << endl << endl;
cout << "LiebLin_DSF_tester d 1.0 100.0 100 0.56 " << endl << endl;
}
else { // (argc == 6), correct nr of arguments
char whichDSF = *argv[1];
DP c_int = atof(argv[2]);
DP L = atof(argv[3]);
int N = atoi(argv[4]);
DP kBT = atof(argv[5]);
//if (whichDSF != 'd') JSCerror("Other options not implemented yet in finite T Scan_LiebLin");
// Delta is the number of sites involved in the smoothing of the entropy
//int Delta = int(sqrt(N))/2;//6;//N/20;
// Construct the finite-size saddle-point state:
//LiebLin_Bethe_State spstate = Canonical_Saddle_Point_State (c_int, L, N, kBT, Delta);
LiebLin_Bethe_State spstate = Canonical_Saddle_Point_State (c_int, L, N, kBT);
spstate.Compute_All(true);
LiebLin_Bethe_State estate = spstate;
if (whichDSF == 'o') estate = Remove_Particle_at_Center (spstate);
else if (whichDSF == 'g') estate = Add_Particle_at_Center (spstate);
if (whichDSF != 'd') estate.Compute_All(true);
cout << estate << endl;
Vect<int> OriginIx2 = estate.Ix2;
int Ix2old, Ix2new;
int again = 0;
string label_req;
do {
//cout << "Substitute Ix2: which for which ?" << endl;
//cin >> Ix2old >> Ix2new;
//for (int i = 0; i < estate.N; ++i) if (estate.Ix2[i] == Ix2old) estate.Ix2[i] = Ix2new;
//estate.Ix2.QuickSort();
cout << "Which label should the exc state be set to?" << endl;
cin >> label_req;
estate.Set_to_Label(label_req, OriginIx2);
estate.Compute_All(false);
cout << spstate << endl;
cout << estate;
if (whichDSF == 'd')
cout << setprecision(16) << "estate.E - spstate.E = " << estate.E - spstate.E << "\tME = " << real(exp(ln_Density_ME(spstate, estate))) << endl;
else if (whichDSF == 'o')
cout << setprecision(16) << "estate.E - spstate.E = " << estate.E - spstate.E << "\tME = " << real(exp(ln_Psi_ME(estate, spstate))) << endl;
else if (whichDSF == 'g')
cout << setprecision(16) << "estate.E - spstate.E = " << estate.E - spstate.E << "\tME = " << real(exp(ln_Psi_ME(spstate, estate))) << endl;
//cout << "Another try ? (1 == yes, 0 == no)" << endl;
again = 1;
cin >> again;
} while (again != 0);
}
return(0);
}
+92
View File
@@ -0,0 +1,92 @@
/**********************************************************
This software is part of J.-S. Caux's ABACUS library.
Copyright (c).
-----------------------------------------------------------
File: LiebLin_DSF_tester.cc
Purpose: allows for Ix2 manipulations (user-prompted) for LiebLin gas
***********************************************************/
#include "JSC.h"
using namespace std;
using namespace JSC;
int main(int argc, char* argv[])
{
if (argc != 6) { // provide some info
cout << endl << "Welcome to ABACUS++\t(copyright J.-S. Caux)." << endl;
cout << endl << "Usage of LiebLin_DSF_tester executable: " << endl;
cout << endl << "Provide the following arguments:" << endl << endl;
cout << "char whichDSF \t\t Which structure factor should be calculated ? Options are: d for rho rho, g for psi psi{dagger}, o for psi{dagger} psi" << endl;
cout << "DP c_int \t\t Value of the interaction parameter: use positive real values only" << endl;
cout << "DP L \t\t\t Length of the system: use positive real values only" << endl;
cout << "int N \t\t\t Number of particles: use positive integer values only" << endl;
cout << "DP kBT \t\t Temperature (positive only of course)" << endl;
cout << endl << "EXAMPLE: " << endl << endl;
cout << "LiebLin_DSF_tester d 1.0 100.0 100 0.56 " << endl << endl;
}
else { // (argc == 6), correct nr of arguments
char whichDSF = *argv[1];
DP c_int = atof(argv[2]);
DP L = atof(argv[3]);
int N = atoi(argv[4]);
DP kBT = atof(argv[5]);
//if (whichDSF != 'd') JSCerror("Other options not implemented yet in finite T Scan_LiebLin");
// Delta is the number of sites involved in the smoothing of the entropy
//int Delta = int(sqrt(N))/2;//6;//N/20;
// Construct the finite-size saddle-point state:
//LiebLin_Bethe_State spstate = Canonical_Saddle_Point_State (c_int, L, N, kBT, Delta);
LiebLin_Bethe_State spstate = Canonical_Saddle_Point_State (c_int, L, N, kBT);
spstate.Compute_All(true);
LiebLin_Bethe_State estate = spstate;
if (whichDSF == 'o') estate = Remove_Particle_at_Center (spstate);
else if (whichDSF == 'g') estate = Add_Particle_at_Center (spstate);
if (whichDSF != 'd') estate.Compute_All(true);
cout << estate << endl;
Vect<int> OriginIx2 = estate.Ix2;
int Ix2old, Ix2new;
int again = 0;
string label_req;
do {
cout << "Substitute Ix2: which for which ?" << endl;
cin >> Ix2old >> Ix2new;
for (int i = 0; i < estate.N; ++i) if (estate.Ix2[i] == Ix2old) estate.Ix2[i] = Ix2new;
estate.Ix2.QuickSort();
//cout << "Which label should the exc state be set to?" << endl;
//cin >> label_req;
//estate.Set_to_Label(label_req, OriginIx2);
estate.Compute_All(false);
cout << spstate << endl;
cout << estate;
if (whichDSF == 'd')
cout << setprecision(16) << "estate.E - spstate.E = " << estate.E - spstate.E << "\tME = " << real(exp(ln_Density_ME(spstate, estate))) << endl;
else if (whichDSF == 'o')
cout << setprecision(16) << "estate.E - spstate.E = " << estate.E - spstate.E << "\tME = " << real(exp(ln_Psi_ME(estate, spstate))) << endl;
else if (whichDSF == 'g')
cout << setprecision(16) << "estate.E - spstate.E = " << estate.E - spstate.E << "\tME = " << real(exp(ln_Psi_ME(spstate, estate))) << endl;
cout << "Another try ? (1 == yes, 0 == no)" << endl;
again = 1;
cin >> again;
} while (again != 0);
}
return(0);
}
+120
View File
@@ -0,0 +1,120 @@
/**********************************************************
This software is part of J.-S. Caux's ABACUS library.
Copyright (c).
-----------------------------------------------------------
File: LiebLin_Data_Daemon.cc
Purpose: Produces sets of data files for correlations.
***********************************************************/
#include "JSC.h"
using namespace std;
using namespace JSC;
int main(int argc, char* argv[])
{
if (argc != 11) { // provide some info
cout << endl << "Welcome to ABACUS\t(copyright J.-S. Caux)." << endl;
cout << endl << "Usage of LiebLin_Data_Daemon executable: " << endl;
cout << endl << "Provide the following arguments:" << endl << endl;
cout << "char whichDSF \t\t Which structure factor should be calculated ? Options are: d for rho rho, g for psi psi{dagger}, o for psi{dagger} psi" << endl;
cout << "DP c_int_max \t\t Largest value of the interaction parameter: use positive real values only" << endl;
cout << "int Nc \t\t number of steps in interaction value" << endl;
cout << "int cfact \t\t dividing factor (each new interaction value if 1/cfact times the previous)" << endl;
cout << "DP L \t\t\t Length of the system: use positive real values only" << endl;
cout << "int N \t\t\t Number of particles: use positive integer values only" << endl;
cout << "int iKmin" << endl << "int iKmax \t\t Min and max momentum integers to scan over: recommended values: -2*N and 2*N" << endl;
cout << "DP kBT \t\t Temperature (positive only of course)" << endl;
cout << "int Max_Hrs \t\t Allowed computational time: (in hours)" << endl;
}
else { // (argc == 10), correct nr of arguments
int ia = 1;
char whichDSF = *argv[ia++];
DP c_int_max = atof(argv[ia++]);
int Nc = atoi(argv[ia++]);
int cfact = atoi(argv[ia++]);
DP L = atof(argv[ia++]);
int N = atoi(argv[ia++]);
int iKmin = atoi(argv[ia++]);
int iKmax = atoi(argv[ia++]);
DP kBT = atof(argv[ia++]);
int Max_Hrs = atoi(argv[ia++]);
// Individual computations are split into chuncks of Max_Hrs/(Nc * 4)
//int Max_Secs = (Max_Hrs * 900)/Nc;
int Max_Secs = (Max_Hrs * 2700)/Nc; // to minimize wrapping up & restarting time
cout << "Data daemon will use chunks of " << Max_Secs << " seconds." << endl;
//clock_t StartTime = clock();
double StartTime = omp_get_wtime();
//clock_t ActualTime = StartTime;
double ActualTime = omp_get_wtime();
DP c_int;
DP target_sumrule = 1.0;
//while (double(ActualTime - StartTime)/CLOCKS_PER_SEC < double(3600 * Max_Hrs - Max_Secs)) {
while (ActualTime - StartTime < double(3600 * Max_Hrs - Max_Secs)) {
Vect<DP> srsat(0.0, Nc);
Vect<bool> refine(false, Nc);
DP srmin = 1.0;
int icmin = 0;
// Determine which correlation has the worst sum rule:
for (int ic = 0; ic < Nc; ++ic) {
c_int = c_int_max/pow(cfact, ic);
stringstream SRC_stringstream; string SRC_string;
Data_File_Name (SRC_stringstream, whichDSF, c_int, L, N, iKmin, iKmax, kBT, 0.0, "");
SRC_stringstream << ".src";
SRC_string = SRC_stringstream.str(); const char* SRC_Cstr = SRC_string.c_str();
fstream srcfile;
srcfile.open(SRC_Cstr, fstream::in);
if (srcfile.fail()) {
srsat[ic] = 0.0;
refine[ic] = false;
}
else {
srcfile >> srsat[ic];
refine[ic] = true;
}
if (srsat[ic] < srmin) {
srmin = srsat[ic];
icmin = ic;
}
srcfile.close();
} // for ic
cout << "srsat min found: " << srmin << "\t for c = " << c_int_max/pow(cfact, icmin) << ". Now refining this."
//<< " Time left: " << 3600* Max_Hrs - (ActualTime - StartTime)/CLOCKS_PER_SEC << " seconds." << endl;
<< " Time left: " << 3600* Max_Hrs - (ActualTime - StartTime) << " seconds." << endl;
// Improve the icmin calculation by one chunk:
Scan_LiebLin (whichDSF, c_int_max/pow(cfact, icmin), L, N, iKmin, iKmax, kBT, Max_Secs, target_sumrule, refine[icmin]);
//ActualTime = clock();
ActualTime = omp_get_wtime();
} // while there is time
cout << "Wrapping up, time's up." << endl;
} // else if arguments given OK
return(0);
}
+104
View File
@@ -0,0 +1,104 @@
/**********************************************************
This software is part of J.-S. Caux's ABACUS library.
Copyright (c).
-----------------------------------------------------------
File: LiebLin_Data_Daemon_Nscaling.cc
Purpose: Produces sets of data files for correlations, increasing system size at fixed c and momentum window.
***********************************************************/
#include "JSC.h"
using namespace std;
using namespace JSC;
int main(int argc, char* argv[])
{
if (argc != 9) { // provide some info
cout << endl << "Welcome to ABACUS\t(copyright J.-S. Caux)." << endl;
cout << endl << "Usage of LiebLin_Data_Daemon_Nscaling executable: " << endl;
cout << endl << "Provide the following arguments:" << endl << endl;
cout << "char whichDSF \t\t Which structure factor should be calculated ? Options are: d for rho rho, g for psi psi{dagger}, o for psi{dagger} psi" << endl;
cout << "DP c_int \t\t Value of the interaction parameter: use positive real values only" << endl;
//cout << "int Nc \t\t number of steps in interaction value" << endl;
cout << "int Nstep \t\t\t Steps to be taken in number of particles: use positive integer values only. Filling will be set to 1 (L == N)" << endl;
cout << "int iKmin" << endl << "int iKmax \t\t Min and max momentum integers to scan over (in units of N == Nstep): recommended values: 0 and 2*N" << endl;
cout << "DP kBT \t\t Temperature (positive only of course)" << endl;
cout << "DP target_sumrule \t sumrule saturation you're satisfied with" << endl;
cout << "int Max_minutes \t\t Allowed computational time: (in minutes)" << endl;
}
else { // (argc == 10), correct nr of arguments
int ia = 1;
char whichDSF = *argv[ia++];
DP c_int = atof(argv[ia++]);
int Nstep = atoi(argv[ia++]);
int iKmin_Nstep = atoi(argv[ia++]);
int iKmax_Nstep = atoi(argv[ia++]);
DP kBT = atof(argv[ia++]);
DP target_sumrule = atof(argv[ia++]);
int Max_minutes = atoi(argv[ia++]);
//clock_t StartTime = clock();
double StartTime = omp_get_wtime();
//clock_t ActualTime = StartTime;
double ActualTime = omp_get_wtime();
int Secs_left = 60* Max_minutes;
int iN = 0;
while (Secs_left > 0) {
iN += 1;
int N = Nstep * iN;
DP L = N;
int iKmin = iKmin_Nstep * iN;
int iKmax = iKmax_Nstep * iN;
DP srsat = 0.0;
bool refine = false;
stringstream SRC_stringstream; string SRC_string;
Data_File_Name (SRC_stringstream, whichDSF, c_int, L, N, iKmin, iKmax, kBT, 0.0, "");
SRC_stringstream << ".src";
SRC_string = SRC_stringstream.str(); const char* SRC_Cstr = SRC_string.c_str();
fstream srcfile;
srcfile.open(SRC_Cstr, fstream::in);
if (srcfile.fail()) {
srsat = 0.0;
refine = false;
}
else {
srcfile >> srsat;
refine = true;
}
srcfile.close();
// Improve the icmin calculation by one chunk:
Scan_LiebLin (whichDSF, c_int, L, N, iKmin, iKmax, kBT, Secs_left, target_sumrule, refine);
ActualTime = clock();
//Secs_left = int(60*Max_minutes - double(ActualTime - StartTime)/CLOCKS_PER_SEC);
Secs_left = int(60*Max_minutes - (ActualTime - StartTime));
cout << "Done with N = " << N << ". Time left = " << Secs_left << " seconds." << endl;
} // while there is time
} // else if arguments given OK
return(0);
}
+149
View File
@@ -0,0 +1,149 @@
/**********************************************************
This software is part of J.-S. Caux's ABACUS library.
Copyright (c).
-----------------------------------------------------------
File: LiebLin_Fourier_to_Qsqx.cc
Purpose: Compute the Q(x)^2 expectation value for LiebLin, where Q(x) = \int_0^x dx \rho(x).
***********************************************************/
#include "JSC.h"
using namespace std;
using namespace JSC;
int main(int argc, char* argv[])
{
if (argc != 9) { // provide some info
cout << endl << "Welcome to ABACUS++\t(copyright J.-S. Caux)." << endl;
cout << endl << "Usage of LiebLin_Fourier_to_Qsqx executable: " << endl;
cout << endl << "Provide the following arguments:" << endl << endl;
cout << "char whichDSF \t\t Which structure factor ? Options are: d for rho rho, g for psi psi{dagger}, o for psi{dagger} psi" << endl;
cout << "DP c_int \t\t Value of the interaction parameter" << endl;
cout << "DP L \t\t\t Length of the system" << endl;
cout << "int N \t\t\t Number of particles" << endl;
cout << "int iKmin" << endl << "int iKmax \t\t Min and max momentum integers scanned over" << endl;
cout << "DP kBT \t\t Temperature" << endl;
cout << "int Npts_x Number of points in space for the Fourier transform" << endl;
}
else { // (argc == 9), correct nr of arguments
char whichDSF = *argv[1];
DP c_int = atof(argv[2]);
DP L = atof(argv[3]);
int N = atoi(argv[4]);
int iKmin = atoi(argv[5]);
int iKmax = atoi(argv[6]);
DP kBT = atof(argv[7]);
int Npts_x = atoi(argv[8]);
// Force Npts_x
//Npts_x = L;
if (whichDSF != 'd') JSCerror("Must use whichDSF == d in LiebLin_Fourier_ssf_to_Qsqx");
stringstream filenameprefix;
Data_File_Name (filenameprefix, whichDSF, c_int, L, N, iKmin, iKmax, kBT, 0.0, "");
string prefix = filenameprefix.str();
stringstream RAW_stringstream; string RAW_string;
RAW_stringstream << prefix << ".raw";
RAW_string = RAW_stringstream.str(); const char* RAW_Cstr = RAW_string.c_str();
ifstream RAW_infile;
RAW_infile.open(RAW_Cstr);
if (RAW_infile.fail()) {
cout << RAW_Cstr << endl;
JSCerror("Could not open RAW_infile... ");
}
// We also read the f-sumrule file, to correct for missing intensity.
stringstream FSR_stringstream; string FSR_string;
FSR_stringstream << prefix << ".fsr";
FSR_string = FSR_stringstream.str(); const char* FSR_Cstr = FSR_string.c_str();
ifstream FSR_infile;
FSR_infile.open(FSR_Cstr);
if (FSR_infile.fail()) {
cout << FSR_Cstr << endl;
JSCerror("Could not open FSR_infile... ");
}
stringstream SFT_stringstream; string SFT_string;
SFT_stringstream << prefix << ".Qsqx";
SFT_string = SFT_stringstream.str(); const char* SFT_Cstr = SFT_string.c_str();
ofstream SFT_outfile;
SFT_outfile.open(SFT_Cstr);
if (SFT_outfile.fail()) JSCerror("Could not open SFT_outfile... ");
// First compute the static structure factor from the RAW data:
Vect_DP SSF(0.0, iKmax - iKmin + 1);
DP omega;
int iK;
DP FF;
//int conv;
DP dev;
string label;
while (RAW_infile.peek() != EOF) {
RAW_infile >> omega >> iK >> FF >> dev >> label;
if (iK >= iKmin && iK <= iKmax) {
SSF[iK - iKmin] += FF * FF;
}
}
RAW_infile.close();
// Reset proper normalization:
DP normalization = twoPI * L;
for (int iK = 0; iK < iKmax - iKmin + 1; ++iK) SSF[iK] *= normalization/twoPI; // twoPI from integral over omega
// Now define real-space coordinates: between 0 and L/2
Vect_DP xlattice(Npts_x);
for (int i = 0; i < Npts_x; ++i) xlattice[i] = (i + 0.5) * 0.5* L/Npts_x;
// Now the correlation at x:
Vect_DP FT(0.0, Npts_x);
DP pioverL = PI/L;
// Fourier transform:
for (int ix = 0; ix < Npts_x; ++ix) {
for (int iK = 1; iK <= iKmax; ++iK) {
FT[ix] += SSF[iK - iKmin] * pow(sin(pioverL * iK * xlattice[ix])/iK, 2.0);
}
// Reset proper normalization: 1/L from space FT,
FT[ix] *= 2.0*L/(PI * PI);
// Outside of window iKmin, iKmax, we take the DSF to be a constant with delta function
// at free energy k^2, so DSF = 2\pi N/L \delta(\omega - k^2) (to fit f-sumrule)
// so SSF becomes N/L.
// We thus need to correct above by adding
// \frac{1}{L} \sum_{-\infty}^{iKmin - 1} SSF e^{ikx} + \frac{1}{L} \sum_{iKmax + 1}^\infty SSF e^{ikx}
// Resumming carefully:
//FTre[ix] += (sin(twopioverL * (iKmin - 0.5) * xlattice[ix]) - sin(twopioverL * (iKmax + 0.5) * xlattice[ix]))
//* N/(2.0 * L*L * sin(PI * xlattice[ix]/L));
//FTim[ix] += (-cos(twopioverL * (iKmin - 0.5) * xlattice[ix]) + cos(twopioverL * (iKmax + 0.5) * xlattice[ix]))
//* N/(2.0 * L*L * sin(PI * xlattice[ix]/L));
}
// Output to file:
for (int ix = 0; ix < Npts_x; ++ix) {
if (ix > 0) SFT_outfile << endl;
//SFT_outfile << xlattice[ix] << "\t" << FTre[ix] << "\t" << FTim[ix] << "\t" << FTreavg[ix] << "\t" << FTimavg[ix];
SFT_outfile << xlattice[ix]/L << "\t" << FT[ix];
}
SFT_outfile.close();
}
return(0);
}
+132
View File
@@ -0,0 +1,132 @@
/**********************************************************
This software is part of J.-S. Caux's ABACUS library.
Copyright (c).
-----------------------------------------------------------
File: LiebLin_Fourier_to_t_equal_x.cc
Purpose: Fourier transform to static space correlator for LiebLin.
***********************************************************/
#include "JSC.h"
using namespace std;
using namespace JSC;
int main(int argc, char* argv[])
{
if (argc != 10) { // provide some info
cout << endl << "Welcome to ABACUS++\t(copyright J.-S. Caux)." << endl;
cout << endl << "Usage of LiebLin_Fourier_to_x_equal_t executable: " << endl;
cout << endl << "Provide the following arguments:" << endl << endl;
cout << "char whichDSF \t\t Which structure factor ? Options are: d for rho rho, g for psi psi{dagger}, o for psi{dagger} psi" << endl;
cout << "DP c_int \t\t Value of the interaction parameter" << endl;
cout << "DP L \t\t\t Length of the system" << endl;
cout << "int N \t\t\t Number of particles" << endl;
cout << "int iKmin" << endl << "int iKmax \t\t Min and max momentum integers scanned over" << endl;
cout << "DP kBT \t\t Temperature" << endl;
cout << "int Npts_t \t Number of points in time for the Fourier transform" << endl;
cout << "DP t_max \t Max time to be used" << endl;
}
else { // (argc == 10), correct nr of arguments
char whichDSF = *argv[1];
DP c_int = atof(argv[2]);
DP L = atof(argv[3]);
int N = atoi(argv[4]);
int iKmin = atoi(argv[5]);
int iKmax = atoi(argv[6]);
DP kBT = atof(argv[7]);
int Npts_t = atoi(argv[8]);
DP t_max = atof(argv[9]);
// Momentum business: use symmetry
if (iKmin != 0) JSCerror("LiebLin_Fourier_to_t_equal_x only implemented for raw files with iKmin == 0.");
stringstream filenameprefix;
Data_File_Name (filenameprefix, whichDSF, c_int, L, N, iKmin, iKmax, kBT, 0.0, "");
string prefix = filenameprefix.str();
stringstream RAW_stringstream; string RAW_string;
RAW_stringstream << prefix << ".raw";
RAW_string = RAW_stringstream.str(); const char* RAW_Cstr = RAW_string.c_str();
ifstream RAW_infile;
RAW_infile.open(RAW_Cstr);
if (RAW_infile.fail()) {
cout << RAW_Cstr << endl;
JSCerror("Could not open RAW_infile... ");
}
// We also read the f-sumrule file, to correct for missing intensity.
stringstream FSR_stringstream; string FSR_string;
FSR_stringstream << prefix << ".fsr";
FSR_string = FSR_stringstream.str(); const char* FSR_Cstr = FSR_string.c_str();
ifstream FSR_infile;
FSR_infile.open(FSR_Cstr);
if (FSR_infile.fail()) {
cout << FSR_Cstr << endl;
JSCerror("Could not open FSR_infile... ");
}
stringstream SFT_stringstream; string SFT_string;
SFT_stringstream << prefix << ".tft";
SFT_string = SFT_stringstream.str(); const char* SFT_Cstr = SFT_string.c_str();
ofstream SFT_outfile;
SFT_outfile.open(SFT_Cstr);
if (SFT_outfile.fail()) JSCerror("Could not open TFT_outfile... ");
// First compute the static structure factor from the RAW data:
Vect_DP TSF(0.0, Npts_t);
DP omega;
int iK;
DP FF;
//int conv;
DP dev;
string label;
// Now define time coordinates: between 0 and t_max
Vect_DP tlattice(Npts_t);
for (int i = 0; i < Npts_t; ++i) tlattice[i] = (i + 0.5) * t_max/Npts_t;
// Now the correlation at t:
Vect<complex<DP> > FT(0.0, Npts_t);
Vect_DP FTre(0.0, Npts_t);
Vect_DP FTim(0.0, Npts_t);
while (RAW_infile.peek() != EOF) {
RAW_infile >> omega >> iK >> FF >> dev >> label;
if (iK == 0)
for (int it = 0; it < Npts_t; ++it)
FT[it] += FF * FF * exp(II * omega * tlattice[it]);
else
for (int it = 0; it < Npts_t; ++it)
FT[it] += 2.0 * FF * FF * exp(II * omega * tlattice[it]);
}
RAW_infile.close();
// Reset proper normalization:
for (int it = 0; it < Npts_t; ++it) {
FTre[it] = real(FT[it]);
FTim[it] = imag(FT[it]);
}
// Output to file:
for (int it = 0; it < Npts_t; ++it) {
if (it > 0) SFT_outfile << endl;
SFT_outfile << tlattice[it] << "\t" << FTre[it] << "\t" << FTim[it];
}
SFT_outfile.close();
}
return(0);
}
@@ -0,0 +1,118 @@
/**********************************************************
This software is part of J.-S. Caux's ABACUS library.
Copyright (c).
-----------------------------------------------------------
File: LiebLin_Fourier_to_t_equal_x.cc
Purpose: Fourier transform to static space correlator for LiebLin.
***********************************************************/
#include "JSC.h"
using namespace std;
using namespace JSC;
int main(int argc, char* argv[])
{
if (argc != 10) { // provide some info
cout << endl << "Welcome to ABACUS++\t(copyright J.-S. Caux)." << endl;
cout << endl << "Usage of LiebLin_Fourier_to_x_equal_t executable: " << endl;
cout << endl << "Provide the following arguments:" << endl << endl;
cout << "char whichDSF \t\t Which structure factor ? Options are: d for rho rho, g for psi psi{dagger}, o for psi{dagger} psi" << endl;
cout << "DP c_int \t\t Value of the interaction parameter" << endl;
cout << "DP L \t\t\t Length of the system" << endl;
cout << "int N \t\t\t Number of particles" << endl;
cout << "int iKmin" << endl << "int iKmax \t\t Min and max momentum integers scanned over" << endl;
//cout << "DP kBT \t\t Temperature" << endl;
cout << "RAW file name" << endl;
cout << "int Npts_t \t Number of points in time for the Fourier transform" << endl;
cout << "DP t_max \t Max time to be used" << endl;
}
else { // (argc == 10), correct nr of arguments
char whichDSF = *argv[1];
DP c_int = atof(argv[2]);
DP L = atof(argv[3]);
int N = atoi(argv[4]);
int iKmin = atoi(argv[5]);
int iKmax = atoi(argv[6]);
//DP kBT = atof(argv[7]);
char* rawfilename = argv[7];
int Npts_t = atoi(argv[8]);
DP t_max = atof(argv[9]);
// Momentum business: use symmetry
if (iKmin != 0) JSCerror("LiebLin_Fourier_to_t_equal_x only implemented for raw files with iKmin == 0.");
ifstream RAW_infile;
//RAW_infile.open(RAW_Cstr);
RAW_infile.open(rawfilename);
if (RAW_infile.fail()) {
//cout << RAW_Cstr << endl;
cout << rawfilename << endl;
JSCerror("Could not open RAW_infile... ");
}
stringstream SFT_stringstream; string SFT_string;
SFT_stringstream << rawfilename << "_tft";
SFT_string = SFT_stringstream.str(); const char* SFT_Cstr = SFT_string.c_str();
ofstream SFT_outfile;
SFT_outfile.open(SFT_Cstr);
if (SFT_outfile.fail()) JSCerror("Could not open TFT_outfile... ");
// First compute the static structure factor from the RAW data:
Vect_DP TSF(0.0, Npts_t);
DP omega;
int iK;
DP FF;
//int conv;
DP dev;
string label;
// Now define time coordinates: between 0 and t_max
Vect_DP tlattice(Npts_t);
for (int i = 0; i < Npts_t; ++i) tlattice[i] = (i + 0.5) * t_max/Npts_t;
// Now the correlation at t:
Vect<complex<DP> > FT(0.0, Npts_t);
Vect_DP FTre(0.0, Npts_t);
Vect_DP FTim(0.0, Npts_t);
while (RAW_infile.peek() != EOF) {
RAW_infile >> omega >> iK >> FF >> dev >> label;
if (iK == 0)
for (int it = 0; it < Npts_t; ++it)
FT[it] += FF * FF * exp(II * omega * tlattice[it]);
else
for (int it = 0; it < Npts_t; ++it)
FT[it] += 2.0 * FF * FF * exp(II * omega * tlattice[it]);
}
RAW_infile.close();
// Reset proper normalization:
for (int it = 0; it < Npts_t; ++it) {
FTre[it] = real(FT[it]);
FTim[it] = imag(FT[it]);
}
// Output to file:
for (int it = 0; it < Npts_t; ++it) {
if (it > 0) SFT_outfile << endl;
SFT_outfile << tlattice[it] << "\t" << FTre[it] << "\t" << FTim[it];
}
SFT_outfile.close();
}
return(0);
}
+191
View File
@@ -0,0 +1,191 @@
/**********************************************************
This software is part of J.-S. Caux's ABACUS library.
Copyright (c).
-----------------------------------------------------------
File: LiebLin_Fourier_to_x_equal_t.cc
Purpose: Fourier transform to static space correlator for LiebLin.
***********************************************************/
#include "JSC.h"
using namespace std;
using namespace JSC;
int main(int argc, char* argv[])
{
if (argc != 9) { // provide some info
cout << endl << "Welcome to ABACUS++\t(copyright J.-S. Caux)." << endl;
cout << endl << "Usage of LiebLin_Fourier_to_x_equal_t executable: " << endl;
cout << endl << "Provide the following arguments:" << endl << endl;
cout << "char whichDSF \t\t Which structure factor ? Options are: d for rho rho, g for psi psi{dagger}, o for psi{dagger} psi" << endl;
cout << "DP c_int \t\t Value of the interaction parameter" << endl;
cout << "DP L \t\t\t Length of the system" << endl;
cout << "int N \t\t\t Number of particles" << endl;
cout << "int iKmin" << endl << "int iKmax \t\t Min and max momentum integers scanned over" << endl;
cout << "DP kBT \t\t Temperature" << endl;
cout << "int Npts_x Number of points in space for the Fourier transform" << endl;
}
else { // (argc == 9), correct nr of arguments
char whichDSF = *argv[1];
DP c_int = atof(argv[2]);
DP L = atof(argv[3]);
int N = atoi(argv[4]);
int iKmin = atoi(argv[5]);
int iKmax = atoi(argv[6]);
DP kBT = atof(argv[7]);
int Npts_x = atoi(argv[8]);
// Force Npts_x
//Npts_x = L;
stringstream filenameprefix;
Data_File_Name (filenameprefix, whichDSF, c_int, L, N, iKmin, iKmax, kBT, 0.0, "");
string prefix = filenameprefix.str();
stringstream RAW_stringstream; string RAW_string;
RAW_stringstream << prefix << ".raw";
RAW_string = RAW_stringstream.str(); const char* RAW_Cstr = RAW_string.c_str();
ifstream RAW_infile;
RAW_infile.open(RAW_Cstr);
if (RAW_infile.fail()) {
cout << RAW_Cstr << endl;
JSCerror("Could not open RAW_infile... ");
}
// We also read the f-sumrule file, to correct for missing intensity.
stringstream FSR_stringstream; string FSR_string;
FSR_stringstream << prefix << ".fsr";
FSR_string = FSR_stringstream.str(); const char* FSR_Cstr = FSR_string.c_str();
ifstream FSR_infile;
FSR_infile.open(FSR_Cstr);
if (FSR_infile.fail()) {
cout << FSR_Cstr << endl;
JSCerror("Could not open FSR_infile... ");
}
stringstream SFT_stringstream; string SFT_string;
SFT_stringstream << prefix << ".sft";
SFT_string = SFT_stringstream.str(); const char* SFT_Cstr = SFT_string.c_str();
ofstream SFT_outfile;
SFT_outfile.open(SFT_Cstr);
if (SFT_outfile.fail()) JSCerror("Could not open SFT_outfile... ");
// First compute the static structure factor from the RAW data:
Vect_DP SSF(0.0, iKmax - iKmin + 1);
DP omega;
int iK;
DP FF;
//int conv;
DP dev;
string label;
while (RAW_infile.peek() != EOF) {
RAW_infile >> omega >> iK >> FF >> dev >> label;
if (iK >= iKmin && iK <= iKmax) {
SSF[iK - iKmin] += FF * FF;
}
}
RAW_infile.close();
// Reset proper normalization:
DP normalization = twoPI * L;
for (int iK = 0; iK < iKmax - iKmin + 1; ++iK) SSF[iK] *= normalization/twoPI; // twoPI from integral over omega
// We now refine the SSF in the following way.
// First, we read off the f-sumrule saturation from the FSR file.
// Then, we put back the missing weight, assuming that it lives
// on the free k^2 dispersion relation (so the DSF is then simply 2\pi N/L \delta(\omega - k^2)).
Vect_DP FSRsaturated(0.0, iKmax - iKmin + 1);
int dummyint;
DP dummy;
for (int i = iKmin; i <= iKmax; ++i)
FSR_infile >> dummyint >> FSRsaturated[i - iKmin] >> dummy;
FSR_infile.close();
// Now correct the SSF by the missing piece:
//for (int iK = iKmin; iK <= iKmax; ++iK)
//SSF[iK - iKmin] += (1.0 - FSRsaturated[iK - iKmin]) * N/L;
//cout << FSRsaturated << endl;
//cout << SSF << endl;
// Now define real-space coordinates: between 0 and L
Vect_DP xlattice(Npts_x);
for (int i = 0; i < Npts_x; ++i) xlattice[i] = (i + 0.5) * L/Npts_x;
// Now the correlation at x:
Vect_DP FTre(0.0, Npts_x);
Vect_DP FTim(0.0, Npts_x);
DP twopioverL = twoPI/L;
// Fourier transform:
for (int ix = 0; ix < Npts_x; ++ix) {
for (int iK = iKmin; iK <= iKmax; ++iK) {
FTre[ix] += SSF[iK - iKmin] * cos(twopioverL * iK * xlattice[ix]);
FTim[ix] += SSF[iK - iKmin] * sin(twopioverL * iK * xlattice[ix]);
}
// Reset proper normalization: 1/L from space FT,
FTre[ix] /= L;
FTim[ix] /= L;
// Outside of window iKmin, iKmax, we take the DSF to be a constant with delta function
// at free energy k^2, so DSF = 2\pi N/L \delta(\omega - k^2) (to fit f-sumrule)
// so SSF becomes N/L.
// We thus need to correct above by adding
// \frac{1}{L} \sum_{-\infty}^{iKmin - 1} SSF e^{ikx} + \frac{1}{L} \sum_{iKmax + 1}^\infty SSF e^{ikx}
// Resumming carefully:
if (whichDSF == 'd') {
FTre[ix] += (sin(twopioverL * (iKmin - 0.5) * xlattice[ix]) - sin(twopioverL * (iKmax + 0.5) * xlattice[ix]))
* N/(2.0 * L*L * sin(PI * xlattice[ix]/L));
FTim[ix] += (-cos(twopioverL * (iKmin - 0.5) * xlattice[ix]) + cos(twopioverL * (iKmax + 0.5) * xlattice[ix]))
* N/(2.0 * L*L * sin(PI * xlattice[ix]/L));
}
}
// Since iKmax and iKmin are finite, we need to average over an interval of
// deltax such that (2\pi/L) iKmax deltax = 2\pi, with deltax == deltaix * L/Npts_x
// so deltaix = (Npts_x/L) * (L/iKmax)
/*
int deltaix = 0*int(Npts_x/(2.0*iKmax));
cout << "deltaix = " << deltaix << endl;
Vect_DP FTreavg(0.0, Npts_x);
Vect_DP FTimavg(0.0, Npts_x);
for (int ix = 0; ix < Npts_x; ++ix) {
for (int ix2 = -deltaix; ix2 < deltaix; ++ix2) {
FTreavg[ix] += FTre[JSC::min(JSC::max(0, ix + ix2), Npts_x - 1)];
FTimavg[ix] += FTim[JSC::min(JSC::max(0, ix + ix2), Npts_x - 1)];
}
FTreavg[ix] /= (2*deltaix + 1);
FTimavg[ix] /= (2*deltaix + 1);
}
*/
if (whichDSF == 'd') cout << "g2(0) = dE0_dc/L = " << LiebLin_dE0_dc (c_int, L, N)/L << "\t" << LiebLin_dE0_dc (c_int, 2.0*L, 2*N)/(2.0*L) << endl;
// Output to file:
for (int ix = 0; ix < Npts_x; ++ix) {
if (ix > 0) SFT_outfile << endl;
//SFT_outfile << xlattice[ix] << "\t" << FTre[ix] << "\t" << FTim[ix] << "\t" << FTreavg[ix] << "\t" << FTimavg[ix];
SFT_outfile << xlattice[ix] << "\t" << FTre[ix] << "\t" << FTim[ix];
}
SFT_outfile.close();
}
return(0);
}
@@ -0,0 +1,147 @@
/**********************************************************
This software is part of J.-S. Caux's ABACUS library.
Copyright (c).
-----------------------------------------------------------
File: LiebLin_Fourier_to_x_equal_t.cc
Purpose: Fourier transform to static space correlator for LiebLin.
***********************************************************/
#include "JSC.h"
using namespace std;
using namespace JSC;
int main(int argc, char* argv[])
{
if (argc != 9) { // provide some info
cout << endl << "Welcome to ABACUS++\t(copyright J.-S. Caux)." << endl;
cout << endl << "Usage of LiebLin_Fourier_to_x_equal_t executable: " << endl;
cout << endl << "Provide the following arguments:" << endl << endl;
cout << "char whichDSF \t\t Which structure factor ? Options are: d for rho rho, g for psi psi{dagger}, o for psi{dagger} psi" << endl;
cout << "DP c_int \t\t Value of the interaction parameter" << endl;
cout << "DP L \t\t\t Length of the system" << endl;
cout << "int N \t\t\t Number of particles" << endl;
cout << "int iKmin" << endl << "int iKmax \t\t Min and max momentum integers scanned over" << endl;
//cout << "DP kBT \t\t Temperature" << endl;
cout << "RAW file name" << endl;
cout << "int Npts_x Number of points in space for the Fourier transform" << endl;
}
else { // (argc == 9), correct nr of arguments
char whichDSF = *argv[1];
DP c_int = atof(argv[2]);
DP L = atof(argv[3]);
int N = atoi(argv[4]);
int iKmin = atoi(argv[5]);
int iKmax = atoi(argv[6]);
//DP kBT = atof(argv[7]);
char* rawfilename = argv[7];
int Npts_x = atoi(argv[8]);
// Force Npts_x
//Npts_x = L;
//stringstream filenameprefix;
//Data_File_Name (filenameprefix, whichDSF, c_int, L, N, iKmin, iKmax, kBT, 0.0, "");
//string prefix = filenameprefix.str();
//stringstream RAW_stringstream; string RAW_string;
//RAW_stringstream << prefix << ".raw";
//RAW_string = RAW_stringstream.str(); const char* RAW_Cstr = RAW_string.c_str();
ifstream RAW_infile;
//RAW_infile.open(RAW_Cstr);
RAW_infile.open(rawfilename);
if (RAW_infile.fail()) {
//cout << RAW_Cstr << endl;
cout << rawfilename << endl;
JSCerror("Could not open RAW_infile... ");
}
// Define the output file name: use the RAW file name but with different suffix
stringstream SFT_stringstream; string SFT_string;
SFT_stringstream << rawfilename << "_sft";
SFT_string = SFT_stringstream.str(); const char* SFT_Cstr = SFT_string.c_str();
ofstream SFT_outfile;
SFT_outfile.open(SFT_Cstr);
if (SFT_outfile.fail()) JSCerror("Could not open SFT_outfile... ");
// First compute the static structure factor from the RAW data:
Vect_DP SSF(0.0, iKmax - iKmin + 1);
DP omega;
int iK;
DP FF;
//int conv;
DP dev;
string label;
while (RAW_infile.peek() != EOF) {
RAW_infile >> omega >> iK >> FF >> dev >> label;
if (iK >= iKmin && iK <= iKmax) {
SSF[iK - iKmin] += FF * FF;
}
}
RAW_infile.close();
// Reset proper normalization:
DP normalization = twoPI * L;
for (int iK = 0; iK < iKmax - iKmin + 1; ++iK) SSF[iK] *= normalization/twoPI; // twoPI from integral over omega
// Now define real-space coordinates: between 0 and L
Vect_DP xlattice(Npts_x);
for (int i = 0; i < Npts_x; ++i) xlattice[i] = (i + 0.5) * L/Npts_x;
// Now the correlation at x:
Vect_DP FTre(0.0, Npts_x);
Vect_DP FTim(0.0, Npts_x);
DP twopioverL = twoPI/L;
// Fourier transform:
for (int ix = 0; ix < Npts_x; ++ix) {
for (int iK = iKmin; iK <= iKmax; ++iK) {
FTre[ix] += SSF[iK - iKmin] * cos(twopioverL * iK * xlattice[ix]);
FTim[ix] += SSF[iK - iKmin] * sin(twopioverL * iK * xlattice[ix]);
}
// Reset proper normalization: 1/L from space FT,
FTre[ix] /= L;
FTim[ix] /= L;
// Outside of window iKmin, iKmax, we take the DSF to be a constant with delta function
// at free energy k^2, so DSF = 2\pi N/L \delta(\omega - k^2) (to fit f-sumrule)
// so SSF becomes N/L.
// We thus need to correct above by adding
// \frac{1}{L} \sum_{-\infty}^{iKmin - 1} SSF e^{ikx} + \frac{1}{L} \sum_{iKmax + 1}^\infty SSF e^{ikx}
// Resumming carefully:
//if (whichDSF == 'd') {
//FTre[ix] += (sin(twopioverL * (iKmin - 0.5) * xlattice[ix]) - sin(twopioverL * (iKmax + 0.5) * xlattice[ix]))
// * N/(2.0 * L*L * sin(PI * xlattice[ix]/L));
//FTim[ix] += (-cos(twopioverL * (iKmin - 0.5) * xlattice[ix]) + cos(twopioverL * (iKmax + 0.5) * xlattice[ix]))
// * N/(2.0 * L*L * sin(PI * xlattice[ix]/L));
//}
}
// Output to file:
for (int ix = 0; ix < Npts_x; ++ix) {
if (ix > 0) SFT_outfile << endl;
//SFT_outfile << xlattice[ix] << "\t" << FTre[ix] << "\t" << FTim[ix] << "\t" << FTreavg[ix] << "\t" << FTimavg[ix];
SFT_outfile << xlattice[ix] << "\t" << FTre[ix] << "\t" << FTim[ix];
}
SFT_outfile.close();
}
return(0);
}
+79
View File
@@ -0,0 +1,79 @@
/**********************************************************
This software is part of J.-S. Caux's ABACUS library.
Copyright (c).
-----------------------------------------------------------
File: LiebLin_DSF_tester.cc
Purpose: allows for Ix2 manipulations (user-prompted) for LiebLin gas
***********************************************************/
#include "JSC.h"
using namespace std;
using namespace JSC;
int main(int argc, char* argv[])
{
if (argc != 8) { // provide some info
cout << endl << "Welcome to ABACUS++\t(copyright J.-S. Caux)." << endl;
cout << endl << "Usage of LiebLin_DSF_tester executable: " << endl;
cout << endl << "Provide the following arguments:" << endl << endl;
cout << "char whichDSF \t\t Which structure factor should be calculated ? Options are: d for rho rho, g for psi psi{dagger}, o for psi{dagger} psi" << endl;
cout << "DP c_int \t\t Value of the interaction parameter: use positive real values only" << endl;
cout << "DP L \t\t\t Length of the system: use positive real values only" << endl;
cout << "int N \t\t\t Number of particles: use positive integer values only" << endl;
cout << "int Nl \t\t\t Number of particles in left Fermi sea (Nr is then N - Nl)" << endl;
cout << "int DIl \t\t shift of left sea as compared to its ground state position" << endl;
cout << "int DIr \t\t shift of right sea as compared to its ground state position" << endl;
}
else { // (argc == 6), correct nr of arguments
char whichDSF = *argv[1];
DP c_int = atof(argv[2]);
DP L = atof(argv[3]);
int N = atoi(argv[4]);
int Nl = atoi(argv[5]);
//int Nr = N - Nl;
int DIl = atoi(argv[6]);
int DIr = atoi(argv[7]);
if (whichDSF != 'd') JSCerror("Other options not implemented yet in LiebLin_Moses_tester");
// Define the Moses state:
LiebLin_Bethe_State MosesState (c_int, L, N);
// Split the sea:
for (int i = 0; i < Nl; ++i) MosesState.Ix2[i] -= 2 * DIl;
for (int i = Nl; i < N; ++i) MosesState.Ix2[i] += 2 * DIr;
MosesState.Compute_All (true);
LiebLin_Bethe_State estate = MosesState;
cout << MosesState;
int Ix2old, Ix2new;
int again = 0;
do {
cout << "Substitute Ix2: which for which ?" << endl;
cin >> Ix2old >> Ix2new;
for (int i = 0; i < estate.N; ++i) if (estate.Ix2[i] == Ix2old) estate.Ix2[i] = Ix2new;
estate.Compute_All(false);
cout << estate;
cout << setprecision(16) << "omega = " << estate.E - MosesState.E << "\t" << exp(real(ln_Density_ME(MosesState, estate))) << endl;
cout << "Another try ? (0 == no)" << endl;
cin >> again;
} while (again != 0);
}
return(0);
}
+134
View File
@@ -0,0 +1,134 @@
/**********************************************************
This software is part of J.-S. Caux's ABACUS library.
Copyright (c).
-----------------------------------------------------------
File: LiebLin_RAW_File_stats.cc
Purpose: Analyzes the distribution of matrix element values in a RAW file,
to help with optimization of the scanning procedure.
***********************************************************/
#include "JSC.h"
using namespace std;
using namespace JSC;
int main(int argc, char* argv[])
{
if (argc != 9) { // provide some info
cout << endl << "Welcome to ABACUS++\t(copyright J.-S. Caux)." << endl;
cout << endl << "Usage of LiebLin_RAW_File_Stats executable: " << endl;
cout << endl << "Provide the following arguments:" << endl << endl;
cout << "char whichDSF \t\t Which structure factor? Options are: d for rho rho, g for psi psi{dagger}, o for psi{dagger} psi" << endl;
cout << "DP c_int \t\t Value of the interaction parameter: use positive real values only" << endl;
cout << "DP L \t\t\t Length of the system: use positive real values only" << endl;
cout << "int N \t\t\t Number of particles: use positive integer values only" << endl;
cout << "int iKmin" << endl << "int iKmax \t\t Min and max momentum integers to scan over: recommended values: -2*N and 2*N" << endl;
cout << "DP kBT \t\t Temperature (positive only of course)" << endl;
cout << "int Aggregate size" << endl;
}
else { // (argc == 9), correct nr of arguments
char whichDSF = *argv[1];
DP c_int = atof(argv[2]);
DP L = atof(argv[3]);
int N = atoi(argv[4]);
int iKmin = atoi(argv[5]);
int iKmax = atoi(argv[6]);
DP kBT = atof(argv[7]);
int AgSize = atoi(argv[8]);
if (AgSize < 2) JSCerror("Give an aggregate size > 1 in LiebLin_RAW_File_Stats.");
stringstream RAW_stringstream; string RAW_string;
Data_File_Name (RAW_stringstream, whichDSF, c_int, L, N, iKmin, iKmax, kBT, 0.0, "");
RAW_stringstream << ".raw";
RAW_string = RAW_stringstream.str(); const char* RAW_Cstr = RAW_string.c_str();
ifstream RAW_infile;
RAW_infile.open(RAW_Cstr);
if (RAW_infile.fail()) {
cout << RAW_Cstr << endl;
JSCerror("Could not open RAW_infile... ");
}
stringstream STAT_stringstream; string STAT_string;
Data_File_Name (STAT_stringstream, whichDSF, c_int, L, N, iKmin, iKmax, kBT, 0.0, "");
STAT_stringstream << ".stat";
STAT_string = STAT_stringstream.str(); const char* STAT_Cstr = STAT_string.c_str();
ofstream STATfile;
STATfile.open(STAT_Cstr);
if (STATfile.fail()) {
cout << STAT_Cstr << endl; JSCerror("Could not open STATfile.");
}
LiebLin_Bethe_State AveragingState = Canonical_Saddle_Point_State (c_int, L, N, whichDSF == 'Z' ? 0.0 : kBT);
DP Chem_Pot = Chemical_Potential (AveragingState);
//DP sumrule_factor = Sumrule_Factor (whichDSF, AveragingState, Chem_Pot, fixed_iK, iKneeded);
Vect<DP> sumrule_factor(iKmax - iKmin + 1);
for (int ik = 0; ik < iKmax - iKmin + 1; ++ik)
sumrule_factor[ik] = Sumrule_Factor (whichDSF, AveragingState, Chem_Pot, ik, ik);
// Normalize by total number of considered momenta
DP correction_factor = 1.0/(iKmax - iKmin + 1);
if (iKmin <= 0 && iKmax >= 0 && whichDSF == 'd') { // correct for fact that RhoRho is 0 at k = 0
sumrule_factor[0] = 0.0;
correction_factor = 1.0/(iKmax - iKmin);
}
for (int ik = 0; ik < iKmax - iKmin + 1; ++ik) sumrule_factor[ik] *= correction_factor;
DP omega;
int iK;
DP ME;
DP dev;
string label;
int nread = 0;
DP srcont = 0.0;
DP abssrcont = 0.0;
DP maxsrcont = 0.0;
DP totsrcont = 0.0;
DP accumulatedsrcont = 0.0;
int naccounted = 0;
while (RAW_infile.peek() != EOF) {
RAW_infile >> omega >> iK >> ME >> dev >> label;
nread++;
if (iK >= iKmin && iK <= iKmax) {
srcont = omega * ME * ME * sumrule_factor[iK - iKmin];
abssrcont = fabs(srcont);
maxsrcont = JSC::max(maxsrcont, abssrcont);
totsrcont += srcont;
accumulatedsrcont += srcont;
naccounted++;
}
if (naccounted >= AgSize) {
STATfile << nread << "\t" << maxsrcont << "\t" << totsrcont/AgSize << "\t" << totsrcont/(AgSize * (maxsrcont > 0.0 ? maxsrcont : 1.0)) << "\t" << accumulatedsrcont << endl;
naccounted = 0;
maxsrcont = 0.0;
totsrcont = 0.0;
}
}
RAW_infile.close();
STATfile.close();
}
return(0);
}
+45
View File
@@ -0,0 +1,45 @@
/**********************************************************
This software is part of J.-S. Caux's ABACUS library.
Copyright (c).
-----------------------------------------------------------
File: LiebLin_TBA.cc
Purpose: solves the TBA equations for Lieb-Liniger
***********************************************************/
#include "JSC.h"
using namespace std;
using namespace JSC;
int main(int argc, const char* argv[])
{
//if (argc != 7) JSCerror("Wrong number of arguments to 2CBG_ThLim executable. Use c(best to set to 1), nbar, ebar, req_diff, Max_Secs, bool Save_data (0 == false).");
if (argc != 6) JSCerror("Wrong number of arguments. Use c(best to set to 1), mu, kBT, req_diff, Max_Secs");
DP c_int = atof(argv[1]);
DP mu = atof(argv[2]);
DP kBT = atof(argv[3]);
DP req_diff = atof(argv[4]);
int Max_Secs = atoi(argv[5]);
if (c_int <= 0.0) JSCerror("Give a strictly positive c.");
if (kBT <= 0.0) JSCerror("Negative T ? Not for the LiebLin gas.");
if (Max_Secs < 10) JSCerror("Give more time.");
//cout << "Read c_int = " << c_int << "\tmu = " << mu << "\tOmega = " << Omega << "\tkBT = " << kBT << "\tMax_Secs = " << Max_Secs << endl;
LiebLin_TBA_Solution solution(c_int, mu, kBT, req_diff, Max_Secs);
cout << solution.nbar << "\t" << solution.ebar << "\t" << solution.sbar << "\t";
return(0);
}
+44
View File
@@ -0,0 +1,44 @@
/**********************************************************
This software is part of J.-S. Caux's ABACUS library.
Copyright (c).
-----------------------------------------------------------
File: LiebLin_TBA_fixed_nbar.cc
Purpose: solves the TBA equations for Lieb-Liniger
***********************************************************/
#include "JSC.h"
using namespace std;
using namespace JSC;
int main(int argc, const char* argv[])
{
//if (argc != 7) JSCerror("Wrong number of arguments to 2CBG_ThLim executable. Use c(best to set to 1), nbar, ebar, req_diff, Max_Secs, bool Save_data (0 == false).");
if (argc != 6) JSCerror("Wrong number of arguments. Use c(best to set to 1), nbar, kBT, req_diff, Max_Secs");
DP c_int = atof(argv[1]);
DP nbar = atof(argv[2]);
DP kBT = atof(argv[3]);
DP req_diff = atof(argv[4]);
int Max_Secs = atoi(argv[5]);
if (c_int <= 0.0) JSCerror("Give a strictly positive c.");
if (kBT <= 0.0) JSCerror("Negative T ? Not for the LiebLin gas.");
if (Max_Secs < 10) JSCerror("Give more time.");
//cout << "Read c_int = " << c_int << "\tmu = " << mu << "\tOmega = " << Omega << "\tkBT = " << kBT << "\tMax_Secs = " << Max_Secs << endl;
LiebLin_TBA_Solution solution = LiebLin_TBA_Solution_fixed_nbar (c_int, nbar, kBT, req_diff, Max_Secs);
cout << solution.nbar << "\t" << solution.ebar << "\t" << solution.sbar << "\t";
return(0);
}
+43
View File
@@ -0,0 +1,43 @@
/**********************************************************
This software is part of J.-S. Caux's ABACUS library.
Copyright (c).
-----------------------------------------------------------
File: LiebLin_TBA_fixed_nbar_ebar.cc
Purpose: solves the TBA equations for Lieb-Liniger
***********************************************************/
#include "JSC.h"
using namespace std;
using namespace JSC;
int main(int argc, const char* argv[])
{
if (argc != 7) JSCerror("Wrong number of arguments. Use c(best to set to 1), nbar, ebar, req_diff, Max_Secs, bool Save_data (0 == false).");
DP c_int = atof(argv[1]);
DP nbar = atof(argv[2]);
DP ebar = atof(argv[3]);
DP req_diff = atof(argv[4]);
int Max_Secs = atoi(argv[5]);
bool Save_data = bool(atoi(argv[6]));
if (c_int <= 0.0) JSCerror("Give a strictly positive c.");
if (Max_Secs < 10) JSCerror("Give more time.");
//cout << "Read c_int = " << c_int << "\tmu = " << mu << "\tOmega = " << Omega << "\tkBT = " << kBT << "\tMax_Secs = " << Max_Secs << endl;
LiebLin_TBA_Solution solution = LiebLin_TBA_Solution_fixed_nbar_ebar(c_int, nbar, ebar, req_diff, Max_Secs);
cout << solution.nbar << "\t" << solution.ebar << "\t" << solution.sbar << "\t";
return(0);
}
+60
View File
@@ -0,0 +1,60 @@
/**********************************************************
This software is part of J.-S. Caux's ABACUS++ library.
Copyright (c)
-----------------------------------------------------------
File: ODSLF_DSF.cc
Purpose: main function for ABACUS++ for spinless fermions related to Heisenberg spin-1/2 chain
***********************************************************/
#include "JSC.h"
using namespace std;
using namespace JSC;
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 JSCerror("Wrong number of arguments to ODSLF_DSF executable.");
return(0);
}
+37
View File
@@ -0,0 +1,37 @@
/**********************************************************
This software is part of J.-S. Caux's ABACUS++ library.
Copyright (c)
-----------------------------------------------------------
File: Sort_RAW_File.cc
Purpose: produce a sorted .raw file.
***********************************************************/
#include "JSC.h"
using namespace std;
using namespace JSC;
int main(int argc, char* argv[])
{
if (argc != 4) {
cout << "Arguments needed: rawfile, whichDSF, whichsorting." << endl;
JSCerror("");
}
const char* rawfilename = argv[1];
char whichDSF = *argv[2];
char whichsorting = *argv[3];
//cout << rawfilename << "\t" << whichDSF << "\t" << whichsorting << endl;
Sort_RAW_File (rawfilename, whichsorting, whichDSF);
return(0);
}
+99
View File
@@ -0,0 +1,99 @@
/**********************************************************
This software is part of J.-S. Caux's ABACUS library.
Copyright (c).
-----------------------------------------------------------
File: RAW_File_stats.cc
Purpose: Analyzes the distribution of matrix element values in a RAW file,
to help with optimization of the scanning procedure.
***********************************************************/
#include "JSC.h"
using namespace std;
using namespace JSC;
int main(int argc, char* argv[])
{
if (argc != 3) { // provide some info
cout << endl << "Welcome to ABACUS++\t(copyright J.-S. Caux)." << endl;
cout << endl << "Usage of RAW_File_Stats executable: " << endl;
cout << endl << "Provide the following arguments:" << endl << endl;
cout << endl << "string RAW file name" << endl;
cout << "int Aggregate size" << endl;
}
else { // correct nr of arguments
const char* rawfilename = argv[1];
int AgSize = atoi(argv[2]);
if (AgSize < 2) JSCerror("Give an aggregate size > 1 in LiebLin_RAW_File_Stats.");
ifstream RAW_infile;
RAW_infile.open(rawfilename);
if (RAW_infile.fail()) {
cout << rawfilename << endl;
JSCerror("Could not open RAW_infile... ");
}
stringstream STAT_stringstream; string STAT_string;
STAT_stringstream << rawfilename << "_AgS_" << AgSize << "_stat";
STAT_string = STAT_stringstream.str(); const char* STAT_Cstr = STAT_string.c_str();
ofstream STATfile;
STATfile.open(STAT_Cstr);
if (STATfile.fail()) {
cout << STAT_Cstr << endl; JSCerror("Could not open STATfile.");
}
DP omega;
int iK;
DP ME;
DP dev;
string label;
int nread = 0;
DP srcont = 0.0;
DP abssrcont = 0.0;
DP maxsrcont = 0.0;
DP totsrcont = 0.0;
DP accumulatedsrcont = 0.0;
int naccounted = 0;
while (RAW_infile.peek() != EOF) {
RAW_infile >> omega >> iK >> ME >> dev >> label;
nread++;
srcont = ME * ME;
abssrcont = fabs(srcont);
maxsrcont = JSC::max(maxsrcont, abssrcont);
totsrcont += srcont;
accumulatedsrcont += srcont;
naccounted++;
if (naccounted >= AgSize) {
STATfile << nread << "\t" << maxsrcont << "\t" << totsrcont/AgSize << "\t" << totsrcont/(AgSize * (maxsrcont > 0.0 ? maxsrcont : 1.0)) << "\t" << accumulatedsrcont << endl;
naccounted = 0;
maxsrcont = 0.0;
totsrcont = 0.0;
}
}
RAW_infile.close();
STATfile.close();
}
return(0);
}
+90
View File
@@ -0,0 +1,90 @@
/**********************************************************
This software is part of J.-S. Caux's ABACUS++ library.
Copyright (c)
-----------------------------------------------------------
File: Smoothen_Heis_DSF.cc
Purpose: produces .dsf and .ssf files from a .raw file
***********************************************************/
#include "JSC.h"
using namespace std;
using namespace JSC;
int main(int argc, char* argv[])
{
if (argc != 13 && argc != 14) { // Print out instructions
//if (strcmp(argv[1],"help") == 0) { // Output some instructions
cout << "Usage of Smoothen_Heis_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 DiK kBT ommin ommax Nom gwidth" << endl << endl;
cout << "2) (for fixed momentum) whichDSF Delta N M iKneeded ommin ommax Nom gwidth" << endl << endl;
//else JSCerror("Incomprehensible arguments in Smoothen_Heis_DSF executable.");
}
else if (argc == 13) { // !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 DiK = atoi(argv[7]);
DP kBT = atof(argv[8]);
DP ommin = atof(argv[9]);
DP ommax = atof(argv[10]);
int Nom = atoi(argv[11]);
DP gwidth = atof(argv[12]);
stringstream filenameprefix;
Data_File_Name (filenameprefix, whichDSF, Delta, N, M, iKmin, iKmax, kBT, 0, "");
string prefix = filenameprefix.str();
DP normalization = twoPI;
DP denom_sum_K = 1.0/N;
Write_K_File (N, iKmin, iKmax);
Write_Omega_File (Nom, ommin, ommax);
DP sumcheck;
sumcheck = Smoothen_RAW_into_SF (prefix, iKmin, iKmax, DiK, ommin, ommax, Nom, gwidth, normalization, denom_sum_K);
}
/*
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, ommin, ommax, Nom, gwidth, normalization) << endl;
}
*/
//else JSCerror("Wrong number of arguments to Smoothen_Heis_DSF executable.");
return(0);
}
+111
View File
@@ -0,0 +1,111 @@
/**********************************************************
This software is part of J.-S. Caux's ABACUS library.
Copyright (c).
-----------------------------------------------------------
File: Smoothen_LiebLin_DSF.cc
Purpose: produces .dsf and .ssf files from a .raw file
***********************************************************/
#include "JSC.h"
using namespace std;
using namespace JSC;
int main(int argc, char* argv[])
{
if (argc != 13) { // Print out instructions
cout << endl << "Welcome to ABACUS++\t(copyright J.-S. Caux)." << endl;
cout << endl << "Usage of Smoothen_LiebLin_DSF executable: " << endl;
cout << endl << "Provide the following arguments:" << endl << endl;
cout << "char whichDSF \t\t Which structure factor should be calculated ? Options are: d for rho rho, g for psi psi{dagger}, o for psi{dagger} psi" << endl;
cout << "DP c_int \t\t Value of the interaction parameter" << endl;
cout << "DP L \t\t\t Length of the system" << endl;
cout << "int N \t\t\t Number of particles" << endl;
cout << "int iKmin" << endl << "int iKmax \t\t Min and max momentum integers" << endl;
cout << "DP kBT \t\t Temperature" << endl;
cout << "int DiK \t\t\t Window of iK over which DSF is averaged (DiK == 0 means a single iK is used; DiK == 1 means 3 are used (iK-1, iK, iK+1), etc.)" << endl;
cout << "DP ommin" << endl << "DP ommax \t\t Min and max frequencies to cover in smoothened DSF" << endl;
cout << "Nom \t\t\t Number of frequency points used for discretization" << endl;
cout << "DP width \t\t Gaussian width used in smoothing, in units of two-particle level spacing" << endl;
cout << endl << "EXAMPLE: " << endl << endl;
cout << "Smoothen_LiebLin_DSF d 1.0 100.0 100 0 200 5.0 1 0.0 10.0 500 2.0" << endl << endl;
}
else if (argc == 13) { // !fixed_iK
char whichDSF = *argv[1];
DP c_int = atof(argv[2]);
DP L = atof(argv[3]);
int N = atoi(argv[4]);
int iKmin = atoi(argv[5]);
int iKmax = atoi(argv[6]);
DP kBT = atof(argv[7]);
int DiK = atoi(argv[8]);
DP ommin = atof(argv[9]);
DP ommax = atof(argv[10]);
int Nom = atoi(argv[11]);
DP width = atof(argv[12]);
stringstream filenameprefix;
//void Data_File_Name (stringstream& name, char whichDSF, DP c_int, DP L, int N, int iKmin, int iKmax, DP kBT, DP L2)
Data_File_Name (filenameprefix, whichDSF, c_int, L, N, iKmin, iKmax, kBT, 0.0, "");
string prefix = filenameprefix.str();
DP normalization = twoPI * L;
DP denom_sum_K = L;
Write_K_File (L, iKmin, iKmax);
Write_Omega_File (Nom, ommin, ommax);
//cout << "Smoothing: sumcheck = " << Smoothen_RAW_into_SF (prefix, iKmin, iKmax, ommin, ommax, Nom, width, normalization) << endl;
// We use the scaled width function as default:
DP sumcheck;
//if (kBT < 0.1)
//sumcheck = Smoothen_RAW_into_SF_LiebLin_Scaled (prefix, L, N, iKmin, iKmax, DiK, ommin, ommax, Nom, width, normalization);
sumcheck = Smoothen_RAW_into_SF (prefix, iKmin, iKmax, DiK, ommin, ommax, Nom, width, normalization, denom_sum_K);
//else sumcheck = Smoothen_RAW_into_SF (prefix, iKmin, iKmax, ommin, ommax, Nom, width, normalization);
//cout << "Smoothing: sumcheck = " << sumcheck << endl;
}
/*
else if (argc == 11) { // fixed_iK
char whichDSF = *argv[1];
DP c_int = atof(argv[2]);
DP L = atof(argv[3]);
int N = atoi(argv[4]);
int iK_UL = atoi(argv[5]);
int iKneeded = atoi(argv[6]);
DP ommin = atof(argv[7]);
DP ommax = atof(argv[8]);
int Nom = atoi(argv[9]);
DP gwidth = atof(argv[10]);
//bool fixed_iK = true;
//LiebLin_Bethe_State GroundState (c_int, L, N, iK_UL, 0LL);
stringstream filenameprefix;
//Data_File_Name (filenameprefix, whichDSF, fixed_iK, iKneeded, GroundState, GroundState);
//Data_File_Name (filenameprefix, whichDSF, c_int, L, N, iK_UL, fixed_iK, iKneeded, 0.0);
Data_File_Name (filenameprefix, whichDSF, c_int, L, N, iK_UL, iKneeded, iKneeded, 0.0);
string prefix = filenameprefix.str();
DP normalization = twoPI * L;
int iKmin = iKneeded;
int iKmax = iKneeded;
cout << "Smoothing: sumcheck = " << Smoothen_RAW_into_SF (prefix, iKmin, iKmax, ommin, ommax, Nom, gwidth, normalization) << endl;
}
*/
//else JSCerror("Wrong number of arguments to Smoothen_LiebLin_DSF executable.");
return(0);
}
@@ -0,0 +1,120 @@
/**********************************************************
This software is part of J.-S. Caux's ABACUS library.
Copyright (c).
-----------------------------------------------------------
File: Smoothen_LiebLin_DSF_GeneralState.cc
Purpose: produces .dsf and .ssf files from a .raw file
***********************************************************/
#include "JSC.h"
using namespace std;
using namespace JSC;
int main(int argc, char* argv[])
{
if (argc != 13) { // Print out instructions
cout << endl << "Welcome to ABACUS++\t(copyright J.-S. Caux)." << endl;
cout << endl << "Usage of Smoothen_LiebLin_DSF executable: " << endl;
cout << endl << "Provide the following arguments:" << endl << endl;
cout << "char whichDSF \t\t Which structure factor should be calculated ? Options are: d for rho rho, g for psi psi{dagger}, o for psi{dagger} psi" << endl;
cout << "DP c_int \t\t Value of the interaction parameter" << endl;
cout << "DP L \t\t\t Length of the system" << endl;
cout << "int N \t\t\t Number of particles" << endl;
cout << "char* defaultScanStatename:\t\t file [].Ix2 contains the quantum numbers defining the AveragingState; used as defaultScanStatename" << endl;
cout << "int iKmin" << endl << "int iKmax \t\t Min and max momentum integers" << endl;
//cout << "DP kBT \t\t Temperature" << endl;
cout << "int DiK \t\t\t Window of iK over which DSF is averaged (DiK == 0 means a single iK is used; DiK == 1 means 3 are used (iK-1, iK, iK+1), etc.)" << endl;
cout << "DP ommin" << endl << "DP ommax \t\t Min and max frequencies to cover in smoothened DSF" << endl;
cout << "Nom \t\t\t Number of frequency points used for discretization" << endl;
cout << "DP width \t\t Gaussian width used in smoothing, in units of two-particle level spacing" << endl;
cout << endl << "EXAMPLE: " << endl << endl;
cout << "Smoothen_LiebLin_DSF d 1.0 100.0 100 0 200 5.0 1 0.0 10.0 500 2.0" << endl << endl;
}
else if (argc == 13) { // !fixed_iK
int n = 1;
char whichDSF = *argv[n++];
DP c_int = atof(argv[n++]);
DP L = atof(argv[n++]);
int N = atoi(argv[n++]);
char* Ix2filenameprefix = argv[n++];
int iKmin = atoi(argv[n++]);
int iKmax = atoi(argv[n++]);
//DP kBT = atof(argv[7]);
DP kBT = 0.0;
int DiK = atoi(argv[n++]);
DP ommin = atof(argv[n++]);
DP ommax = atof(argv[n++]);
int Nom = atoi(argv[n++]);
DP width = atof(argv[n++]);
stringstream filenamestrstream;
filenamestrstream << Ix2filenameprefix;
string defaultScanStatename = filenamestrstream.str();
stringstream filenameprefix;
//void Data_File_Name (stringstream& name, char whichDSF, DP c_int, DP L, int N, int iKmin, int iKmax, DP kBT, DP L2)
//Data_File_Name (filenameprefix, whichDSF, c_int, L, N, iKmin, iKmax, kBT, 0.0, "");
Data_File_Name (filenameprefix, whichDSF, c_int, L, N, iKmin, iKmax, kBT, 0.0, defaultScanStatename);
string prefix = filenameprefix.str();
DP normalization = twoPI * L;
DP denom_sum_K = L;
Write_K_File (L, iKmin, iKmax);
Write_Omega_File (Nom, ommin, ommax);
//cout << "Smoothing: sumcheck = " << Smoothen_RAW_into_SF (prefix, iKmin, iKmax, ommin, ommax, Nom, width, normalization) << endl;
// We use the scaled width function as default:
DP sumcheck;
//if (kBT < 0.1)
//sumcheck = Smoothen_RAW_into_SF_LiebLin_Scaled (prefix, L, N, iKmin, iKmax, DiK, ommin, ommax, Nom, width, normalization);
sumcheck = Smoothen_RAW_into_SF (prefix, iKmin, iKmax, DiK, ommin, ommax, Nom, width, normalization, denom_sum_K);
//else sumcheck = Smoothen_RAW_into_SF (prefix, iKmin, iKmax, ommin, ommax, Nom, width, normalization);
//cout << "Smoothing: sumcheck = " << sumcheck << endl;
}
/*
else if (argc == 11) { // fixed_iK
char whichDSF = *argv[1];
DP c_int = atof(argv[2]);
DP L = atof(argv[3]);
int N = atoi(argv[4]);
int iK_UL = atoi(argv[5]);
int iKneeded = atoi(argv[6]);
DP ommin = atof(argv[7]);
DP ommax = atof(argv[8]);
int Nom = atoi(argv[9]);
DP gwidth = atof(argv[10]);
//bool fixed_iK = true;
//LiebLin_Bethe_State GroundState (c_int, L, N, iK_UL, 0LL);
stringstream filenameprefix;
//Data_File_Name (filenameprefix, whichDSF, fixed_iK, iKneeded, GroundState, GroundState);
//Data_File_Name (filenameprefix, whichDSF, c_int, L, N, iK_UL, fixed_iK, iKneeded, 0.0);
Data_File_Name (filenameprefix, whichDSF, c_int, L, N, iK_UL, iKneeded, iKneeded, 0.0);
string prefix = filenameprefix.str();
DP normalization = twoPI * L;
int iKmin = iKneeded;
int iKmax = iKneeded;
cout << "Smoothing: sumcheck = " << Smoothen_RAW_into_SF (prefix, iKmin, iKmax, ommin, ommax, Nom, gwidth, normalization) << endl;
}
*/
//else JSCerror("Wrong number of arguments to Smoothen_LiebLin_DSF executable.");
return(0);
}
@@ -0,0 +1,97 @@
/**********************************************************
This software is part of J.-S. Caux's ABACUS library.
Copyright (c).
-----------------------------------------------------------
File: Smoothen_LiebLin_DSF_MosesState.cc
Purpose: produces .dsf and .ssf files from a .raw file
***********************************************************/
#include "JSC.h"
using namespace std;
using namespace JSC;
int main(int argc, char* argv[])
{
if (argc != 15) { // Print out instructions
cout << endl << "Welcome to ABACUS++\t(copyright J.-S. Caux)." << endl;
cout << endl << "Usage of Smoothen_LiebLin_DSF_MosesState executable: " << endl;
cout << endl << "Provide the following arguments:" << endl << endl;
cout << "char whichDSF \t\t Which structure factor should be calculated ? Options are: d for rho rho, g for psi psi{dagger}, o for psi{dagger} psi" << endl;
cout << "DP c_int \t\t Value of the interaction parameter" << endl;
cout << "DP L \t\t\t Length of the system" << endl;
cout << "int N \t\t\t Number of particles" << endl;
cout << "int Nl \t\t\t Number of particles in left Fermi sea (Nr is then N - Nl)" << endl;
cout << "int DIl \t\t shift of left sea as compared to its ground state position" << endl;
cout << "int DIr \t\t shift of right sea as compared to its ground state position" << endl;
cout << "int iKmin" << endl << "int iKmax \t\t Min and max momentum integers" << endl;
//cout << "DP kBT \t\t Temperature" << endl;
cout << "int DiK \t\t\t Window of iK over which DSF is averaged (DiK == 0 means a single iK is used; DiK == 1 means 3 are used (iK-1, iK, iK+1), etc.)" << endl;
cout << "DP ommin" << endl << "DP ommax \t\t Min and max frequencies to cover in smoothened DSF" << endl;
cout << "Nom \t\t\t Number of frequency points used for discretization" << endl;
cout << "DP width \t\t Gaussian width used in smoothing, in units of two-particle level spacing" << endl;
cout << endl << "EXAMPLE: " << endl << endl;
cout << "Smoothen_LiebLin_DSF_MosesState d 1.0 100.0 100 50 -30 40 0 200 1 0.0 10.0 500 2.0" << endl << endl;
}
else if (argc == 15) { // !fixed_iK
char whichDSF = *argv[1];
DP c_int = atof(argv[2]);
DP L = atof(argv[3]);
int N = atoi(argv[4]);
int Nl = atoi(argv[5]);
//int Nr = N - Nl;
int DIl = atoi(argv[6]);
int DIr = atoi(argv[7]);
int iKmin = atoi(argv[8]);
int iKmax = atoi(argv[9]);
//DP kBT = atof(argv[10]);
DP kBT = 0.0;
int DiK = atoi(argv[10]);
DP ommin = atof(argv[11]);
DP ommax = atof(argv[12]);
int Nom = atoi(argv[13]);
DP width = atof(argv[14]);
// Handy default name:
stringstream defaultScanStatename_strstream;
defaultScanStatename_strstream << "Moses_Nl_" << Nl << "_DIl_" << DIl << "_DIr_" << DIr;
string defaultScanStatename = defaultScanStatename_strstream.str();
stringstream filenameprefix;
//void Data_File_Name (stringstream& name, char whichDSF, DP c_int, DP L, int N, int iKmin, int iKmax, DP kBT, DP L2)
Data_File_Name (filenameprefix, whichDSF, c_int, L, N, iKmin, iKmax, kBT, 0.0, defaultScanStatename);
string prefix = filenameprefix.str();
DP normalization = twoPI * L;
DP denom_sum_K = L;
Write_K_File (L, iKmin, iKmax);
Write_Omega_File (Nom, ommin, ommax);
//cout << "Smoothing: sumcheck = " << Smoothen_RAW_into_SF (prefix, iKmin, iKmax, ommin, ommax, Nom, width, normalization) << endl;
// We use the scaled width function as default:
DP sumcheck;
//if (kBT < 0.1)
//sumcheck = Smoothen_RAW_into_SF_LiebLin_Scaled (prefix, L, N, iKmin, iKmax, DiK, ommin, ommax, Nom, width, normalization);
sumcheck = Smoothen_RAW_into_SF (prefix, iKmin, iKmax, DiK, ommin, ommax, Nom, width, normalization, denom_sum_K);
//else sumcheck = Smoothen_RAW_into_SF (prefix, iKmin, iKmax, ommin, ommax, Nom, width, normalization);
//cout << "Smoothing: sumcheck = " << sumcheck << endl;
}
//else JSCerror("Wrong number of arguments to Smoothen_LiebLin_DSF executable.");
return(0);
}
+82
View File
@@ -0,0 +1,82 @@
/**********************************************************
This software is part of J.-S. Caux's ABACUS library.
Copyright (c).
-----------------------------------------------------------
File: Smoothen_LiebLin_DSF_Scaled.cc
Purpose: produces .dsfs and .ssf files from a .raw file
***********************************************************/
#include "JSC.h"
using namespace std;
using namespace JSC;
int main(int argc, char* argv[])
{
if (argc != 13) { // Print out instructions
cout << endl << "Welcome to ABACUS++\t(copyright J.-S. Caux)." << endl;
cout << endl << "Usage of Smoothen_LiebLin_DSF_Scaled executable: " << endl;
cout << endl << "Provide the following arguments:" << endl << endl;
cout << "char whichDSF \t\t Which structure factor should be calculated ? Options are: d for rho rho, g for psi psi{dagger}, o for psi{dagger} psi" << endl;
cout << "DP c_int \t\t Value of the interaction parameter" << endl;
cout << "DP L \t\t\t Length of the system" << endl;
cout << "int N \t\t\t Number of particles" << endl;
cout << "int iKmin" << endl << "int iKmax \t\t Min and max momentum integers" << endl;
cout << "DP kBT \t\t Temperature" << endl;
cout << "int DiK \t\t\t Window of iK over which DSF is averaged (DiK == 0 means a single iK is used; DiK == 1 means 3 are used (iK-1, iK, iK+1), etc.)" << endl;
cout << "DP ommin" << endl << "DP ommax \t\t Min and max frequencies to cover in smoothened DSF" << endl;
cout << "Nom \t\t\t Number of frequency points used for discretization" << endl;
cout << "DP width \t\t Gaussian width used in smoothing, in units of two-particle level spacing" << endl;
cout << endl << "EXAMPLE: " << endl << endl;
cout << "Smoothen_LiebLin_DSF d 1.0 100.0 100 0 200 5.0 1 0.0 10.0 500 2.0" << endl << endl;
}
else if (argc == 13) { // !fixed_iK
char whichDSF = *argv[1];
DP c_int = atof(argv[2]);
DP L = atof(argv[3]);
int N = atoi(argv[4]);
int iKmin = atoi(argv[5]);
int iKmax = atoi(argv[6]);
DP kBT = atof(argv[7]);
int DiK = atoi(argv[8]);
DP ommin = atof(argv[9]);
DP ommax = atof(argv[10]);
int Nom = atoi(argv[11]);
DP width = atof(argv[12]);
stringstream filenameprefix;
//void Data_File_Name (stringstream& name, char whichDSF, DP c_int, DP L, int N, int iKmin, int iKmax, DP kBT, DP L2)
Data_File_Name (filenameprefix, whichDSF, c_int, L, N, iKmin, iKmax, kBT, 0.0, "");
string prefix = filenameprefix.str();
DP normalization = twoPI * L;
//DP denom_sum_K = L;
Write_K_File (L, iKmin, iKmax);
Write_Omega_File (Nom, ommin, ommax);
//cout << "Smoothing: sumcheck = " << Smoothen_RAW_into_SF (prefix, iKmin, iKmax, ommin, ommax, Nom, width, normalization) << endl;
// We use the scaled width function as default:
DP sumcheck;
//if (kBT < 0.1)
sumcheck = Smoothen_RAW_into_SF_LiebLin_Scaled (prefix, L, N, iKmin, iKmax, DiK, ommin, ommax, Nom, width, normalization);
//sumcheck = Smoothen_RAW_into_SF (prefix, iKmin, iKmax, DiK, ommin, ommax, Nom, width, normalization, denom_sum_K);
//else sumcheck = Smoothen_RAW_into_SF (prefix, iKmin, iKmax, ommin, ommax, Nom, width, normalization);
//cout << "Smoothing: sumcheck = " << sumcheck << endl;
}
//else JSCerror("Wrong number of arguments to Smoothen_LiebLin_DSF executable.");
return(0);
}
@@ -0,0 +1,103 @@
/**********************************************************
This software is part of J.-S. Caux's ABACUS library.
Copyright (c).
-----------------------------------------------------------
File: Smoothen_LiebLin_DSF_over_Ensemble.cc
Purpose: produces .dsf and .ssf files from an ensemble of .raw files
***********************************************************/
#include "JSC.h"
using namespace std;
using namespace JSC;
int main(int argc, char* argv[])
{
if (argc != 13) { // Print out instructions
cout << endl << "Welcome to ABACUS++\t(copyright J.-S. Caux)." << endl;
cout << endl << "Usage of Smoothen_LiebLin_DSF_over_Ensemble executable: " << endl;
cout << endl << "Provide the following arguments:" << endl << endl;
cout << "char whichDSF \t\t Which structure factor should be calculated ? Options are: d for rho rho, g for psi psi{dagger}, o for psi{dagger} psi" << endl;
cout << "DP c_int \t\t Value of the interaction parameter" << endl;
cout << "DP L \t\t\t Length of the system" << endl;
cout << "int N \t\t\t Number of particles" << endl;
cout << "int iKmin" << endl << "int iKmax \t\t Min and max momentum integers" << endl;
cout << "DP kBT \t\t Temperature" << endl;
//cout << "int nstates \t\t\t Number of states considered in the ensemble" << endl;
cout << "int DiK \t\t\t Window of iK over which DSF is averaged (DiK == 0 means a single iK is used; DiK == 1 means 3 are used (iK-1, iK, iK+1), etc.)" << endl;
cout << "DP ommin" << endl << "DP ommax \t\t Min and max frequencies to cover in smoothened DSF" << endl;
cout << "Nom \t\t\t Number of frequency points used for discretization" << endl;
cout << "DP width \t\t Gaussian width used in smoothing, in units of two-particle level spacing" << endl;
cout << endl << "EXAMPLE: " << endl << endl;
cout << "Smoothen_LiebLin_DSF_over_Ensemble d 1.0 100.0 100 0 200 5.0 1 0.0 10.0 500 2.0" << endl << endl;
}
else if (argc == 13) {
char whichDSF = *argv[1];
DP c_int = atof(argv[2]);
DP L = atof(argv[3]);
int N = atoi(argv[4]);
int iKmin = atoi(argv[5]);
int iKmax = atoi(argv[6]);
DP kBT = atof(argv[7]);
//int nstates_req = atoi(argv[8]);
int DiK = atoi(argv[8]);
DP ommin = atof(argv[9]);
DP ommax = atof(argv[10]);
int Nom = atoi(argv[11]);
DP width = atof(argv[12]);
stringstream filenameprefix;
//void Data_File_Name (stringstream& name, char whichDSF, DP c_int, DP L, int N, int iKmin, int iKmax, DP kBT, DP L2)
Data_File_Name (filenameprefix, whichDSF, c_int, L, N, iKmin, iKmax, kBT, 0.0, "");
string prefix = filenameprefix.str();
DP normalization = twoPI * L;
DP denom_sum_K = L;
Write_K_File (L, iKmin, iKmax);
Write_Omega_File (Nom, ommin, ommax);
// Read the weights from the ensembles file:
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();
ensemble.Load(c_int, L, N, ensfile_Cstr);
// Define the raw file names
Vect<string> rawfilename(ensemble.nstates);
for (int ns = 0; ns < ensemble.nstates; ++ns) {
// 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);
string prefix = filenameprefix.str();
stringstream RAW_stringstream; string RAW_string;
RAW_stringstream << prefix << ".raw";
//RAW_string = RAW_stringstream.str(); const char* RAW_Cstr = RAW_string.c_str();
rawfilename[ns] = RAW_stringstream.str();
}
Smoothen_RAW_into_SF (prefix, rawfilename, ensemble.weight, iKmin, iKmax, DiK,
ommin, ommax, Nom, width, normalization, denom_sum_K);
}
return(0);
}
+82
View File
@@ -0,0 +1,82 @@
/**********************************************************
This software is part of J.-S. Caux's ABACUS++ library.
Copyright (c)
-----------------------------------------------------------
File: Smoothen_ODSLF_DSF.cc
Purpose: produces .dsf and .ssf files from a .raw file
***********************************************************/
#include "JSC.h"
using namespace std;
using namespace JSC;
int main(int argc, char* argv[])
{
if (argc != 10 && argc != 11) { // Print out instructions
//if (strcmp(argv[1],"help") == 0) { // Output some 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 JSCerror("Incomprehensible arguments in Smoothen_ODSLF_DSF executable.");
}
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, 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, ommin, ommax, Nom, gwidth, normalization) << endl;
}
else JSCerror("Wrong number of arguments to Smoothen_Heis_DSF executable.");
}
+112
View File
@@ -0,0 +1,112 @@
/**********************************************************
This software is part of J.-S. Caux's ABACUS++ library.
Copyright (c)
-----------------------------------------------------------
File: ABACUS++G_2_testing.cc
Purpose: testing of ABACUS++2
***********************************************************/
#include "JSC.h"
using namespace std;
using namespace JSC;
int main( int argc, char* argv[])
{
if (!(argc == 3 || argc == 5)) { // provide some info
cout << endl << "This code computes the (1/N) (-1)^j S^z_j on-site staggered magnetization for XXZ_gpd in zero field." << endl;
cout << "First option: provide two arguments: anisotropy Delta (> 1) and system size N (even)." << endl;
cout << "Second option: provide five arguments: system size N (even), Delta min, Delta max, NDelta." << endl;
cout << "The output is Delta, N, stag mag, energy gap." << endl;
JSCerror("");
}
else if (argc == 3) {
DP Delta = atof(argv[1]);
if (Delta <= 1.0) JSCerror("Provide Delta > 1.");
int N = atoi(argv[2]);
if (N % 2) JSCerror("Provide an even Delta.");
int M = N/2;
// Define the chain: J, Delta, h, Nsites
Heis_Chain chain(1.0, Delta, 0.0, N);
Heis_Base gbase(chain, M);
XXZ_gpd_Bethe_State gstate(chain, gbase);
gstate.Compute_All(true);
XXZ_gpd_Bethe_State estate(chain, gbase);
estate.Ix2[0][0] = M+1; // umklapp excitation
estate.Compute_All(true);
stringstream basestrstream;
basestrstream << M-2 << "x1";
string basestr = basestrstream.str();
Heis_Base basegap(chain, basestr);
XXZ_gpd_Bethe_State estategap(chain, basegap);
estategap.Compute_All(true);
if (!gstate.conv) JSCerror("Ground state did not converge.");
if (!estate.conv) JSCerror("Umklapp state did not converge.");
if (!estategap.conv) JSCerror("Gap state did not converge.");
cout << Delta << "\t" << N << "\t" << setprecision(12) << exp(real(ln_Sz_ME (gstate, estate)))/sqrt(N) << "\t" << estategap.E - gstate.E << endl;
}
else if (argc == 5) { // Do a scan in Delta
int N = atoi(argv[1]);
if (N % 2) JSCerror("Provide an even Delta.");
int M = N/2;
DP Deltamin = atof(argv[2]);
if (Deltamin <= 1.0) JSCerror("Provide Deltamin > 1.");
DP Deltamax = atof(argv[3]);
if (Deltamin <= 1.0) JSCerror("Provide Deltamax > Deltamin.");
int NDelta = atoi(argv[4]);
for (int iDelta = 0; iDelta <= NDelta; ++iDelta) {
DP Delta = (Deltamin * (NDelta -iDelta) + Deltamax * iDelta)/NDelta;
// Define the chain: J, Delta, h, Nsites
Heis_Chain chain(1.0, Delta, 0.0, N);
Heis_Base gbase(chain, M);
XXZ_gpd_Bethe_State gstate(chain, gbase);
gstate.Compute_All(true);
XXZ_gpd_Bethe_State estate(chain, gbase);
estate.Ix2[0][0] = M+1; // umklapp excitation
estate.Compute_All(true);
stringstream basestrstream;
basestrstream << M-2 << "x1";
string basestr = basestrstream.str();
Heis_Base basegap(chain, basestr);
XXZ_gpd_Bethe_State estategap(chain, basegap);
estategap.Compute_All(true);
if (!gstate.conv) JSCerror("Ground state did not converge.");
if (!estate.conv) JSCerror("Umklapp state did not converge.");
if (!estategap.conv) JSCerror("Gap state did not converge.");
cout << Delta << "\t" << N << "\t" << setprecision(12) << exp(real(ln_Sz_ME (gstate, estate)))/sqrt(N) << "\t" << estategap.E - gstate.E << endl;
}
}
return(0);
}
+41
View File
@@ -0,0 +1,41 @@
/**********************************************************
This software is part of J.-S. Caux's C++ library.
Copyright (c) 2007.
-----------------------------------------------------------
File: mrqmin.cc
Purpose: Nonlinear fitting
Last modified: 14/08/07
***********************************************************/
#include "JSC.h"
using namespace std;
namespace JSC {
void covsrt (SQMat_DP& covar, Vect<bool>& ia, const int mfit)
{
int i, j, k;
int ma = ia.size();
for (i = mfit; i < ma; i++)
for (j = 0; j < i+1; j++) covar[i][j] = covar[j][i] = 0.0;
k = mfit - 1;
for (j = ma - 1; j >= 0; j--) {
if (ia[j]) {
for (i = 0; i < ma; i++) SWAP(covar[i][k], covar[i][j]);
for (i = 0; i < ma; i++) SWAP(covar[k][i], covar[j][i]);
k--;
}
}
}
}
+73
View File
@@ -0,0 +1,73 @@
/**********************************************************
This software is part of J.-S. Caux's C++ library.
Copyright (c) 2006.
-----------------------------------------------------------
File: lin_reg.cc
Purpose: Linear regression
Last modified: 11/05/07
***********************************************************/
#include "JSC.h"
using namespace std;
namespace JSC {
void lin_reg (Vect_DP x, Vect_DP y, Vect_DP sigma, DP& a, DP& b, DP& chisq)
{
// Performs simple linear regression on data
int Npts = x.size();
DP S = 0.0;
DP Sx = 0.0;
DP Sy = 0.0;
DP Stt = 0.0;
Vect_DP t(0.0, Npts);
for (int i = 0; i < Npts; ++i) {
S += 1.0/(sigma[i] * sigma[i]);
Sx += x[i]/(sigma[i] * sigma[i]);
Sy += y[i]/(sigma[i] * sigma[i]);
}
for (int i = 0; i < Npts; ++i) {
t[i] = (x[i] - Sx/S)/sigma[i];
Stt += t[i] * t[i];
}
a = 0.0;
b = 0.0;
for (int i = 0; i < Npts; ++i) {
b += t[i] * y[i]/sigma[i];
}
b /= Stt;
a = (Sy - Sx * b)/S;
chisq = 0.0;
for (int i = 0; i < Npts; ++i) {
chisq += (y[i] - a - b * x[i]) * (y[i] - a - b * x[i]) / (sigma[i] * sigma[i]);
}
return;
}
void lin_reg (Vect_DP x, Vect_DP y, DP& a, DP& b, DP& chisq)
{
// Assumes all sigma == 1
Vect_DP sigma(1.0, x.size());
lin_reg (x, y, sigma, a, b, chisq);
return;
}
}
+127
View File
@@ -0,0 +1,127 @@
/**********************************************************
This software is part of J.-S. Caux's C++ library.
Copyright (c) 2007.
-----------------------------------------------------------
File: mrqmin.cc
Purpose: Nonlinear fitting
Last modified: 14/08/07
***********************************************************/
#include "JSC.h"
using namespace std;
namespace JSC {
void mrqmin (Vect_DP& x, Vect_DP& y, Vect_DP& sig, Vect_DP& a,
Vect<bool>& ia, SQMat_DP& covar, SQMat_DP& alpha, DP& chisq,
void funcs(const DP, Vect_DP&, DP&, Vect_DP&), DP& alambda)
{
// Levenberg-Marquardt method. See NRC++ p.691.
static int mfit;
static DP ochisq;
int j, k, l;
int ma = a.size();
static SQMat_DP oneda (ma);
static Vect_DP atry(ma);
static Vect_DP beta(ma);
static Vect_DP da(ma);
if (alambda < 0.0) {
mfit = 0;
for (j = 0; j < ma; j++)
if (ia[j]) mfit++;
alambda = 0.001;
mrqcof (x, y, sig, a, ia, alpha, beta, chisq, funcs);
ochisq = chisq;
for (j = 0; j < ma; j++) atry[j] = a[j];
}
SQMat_DP temp (mfit);
for (j = 0; j < mfit; j++) {
for (k = 0; k < mfit; k++) covar[j][k] = alpha[j][k];
covar[j][j] = alpha[j][j] * (1.0 + alambda);
for (k = 0; k < mfit; k++) temp[j][k] = covar[j][k];
oneda[j][0] = beta[j];
}
gaussj (temp, oneda);
for (j = 0; j < mfit; j++) {
for (k = 0; k < mfit; k++) covar[j][k] = temp[j][k];
da[j] = oneda[j][0];
}
if (alambda == 0.0) {
covsrt (covar, ia, mfit);
covsrt (alpha, ia, mfit);
return;
}
for (j = 0, l = 0; l < ma; l++)
if (ia[l]) atry[l] = a[l] + da[j++];
mrqcof (x, y, sig, atry, ia, covar, da, chisq, funcs);
if (chisq < ochisq) {
alambda *= 0.1;
ochisq = chisq;
for (j = 0; j < mfit; j++) {
for (k = 0; k < mfit; k++) alpha[j][k] = covar[j][k];
beta[j] = da[j];
}
for (l = 0; l < ma; l++) a[l] = atry[l];
} else {
alambda *= 10.0;
chisq = ochisq;
}
}
void mrqcof (Vect_DP& x, Vect_DP& y, Vect_DP& sig, Vect_DP& a,
Vect<bool>& ia, SQMat_DP& alpha, Vect_DP& beta, DP& chisq,
void funcs (const DP, Vect_DP&, DP&, Vect_DP&))
{
int i, j, k, l, m, mfit = 0;
DP ymod, wt, sig2i, dy;
int ndata = x.size();
int ma = a.size();
Vect_DP dyda (ma);
for (j = 0; j < ma; j++)
if (ia[j]) mfit++;
for (j = 0; j < mfit; j++) {
for (k = 0; k <= j; k++) alpha[j][k] = 0.0;
beta[j] = 0.0;
}
chisq = 0.0;
for (i = 0; i < ndata; i++) {
funcs (x[i], a, ymod, dyda);
sig2i = 1.0/(sig[i] * sig[i]);
dy = y[i] - ymod;
for (j = 0, l = 0; l < ma; l++) {
if (ia[l]) {
wt = dyda[l] * sig2i;
for (k = 0, m = 0; m < l+1; m++)
if (ia[m]) alpha[j][k++] += wt * dyda[m];
beta[j++] += dy * wt;
}
}
chisq += dy * dy * sig2i;
}
for (j = 1; j < mfit; j++)
for (k = 0; k < j; k++) alpha[k][j] = alpha[j][k];
}
}
+35
View File
@@ -0,0 +1,35 @@
#include "JSC.h"
using namespace std;
void JSC::polint(Vect_DP& xa, Vect_DP& ya, const DP x, DP& y, DP& dy)
{
// Polynomial interpolation/extrapolation, NR page 113.
int i, m, ns=0;
DP den, dif, dift, ho, hp, w;
int n = xa.size();
Vect_DP c(n), d(n);
dif = fabs(x-xa[0]);
for (i = 0; i < n; i++) {
if ((dift = fabs(x-xa[i])) < dif) {
ns = i;
dif = dift;
}
c[i] = ya[i];
d[i] = ya[i];
}
y = ya[ns--];
for (m = 1; m < n; m++) {
for (i = 0; i < n-m; i++) {
ho = xa[i] - x;
hp = xa[i+m] - x;
w = c[i+1] - d[i];
if ((den = ho-hp) == 0.0) JSCerror("Error in routine polint.");
den = w/den;
d[i] = hp * den;
c[i] = ho * den;
}
y += (dy = (2 * (ns + 1) < (n-m) ? c[ns + 1] : d[ns--]));
}
}
+36
View File
@@ -0,0 +1,36 @@
#include "JSC.h"
using namespace std;
void JSC::polint(Vect_CX& xa, Vect_CX& ya, const complex<DP> x, complex<DP>& y, complex<DP>& dy)
{
// Polynomial interpolation/extrapolation, NR page 113.
int i, m, ns=0;
DP dif, dift;
complex<DP> den, ho, hp, w;
int n = xa.size();
Vect_CX c(n), d(n);
dif = abs(x-xa[0]);
for (i = 0; i < n; i++) {
if ((dift = abs(x-xa[i])) < dif) {
ns = i;
dif = dift;
}
c[i] = ya[i];
d[i] = ya[i];
}
y = ya[ns--];
for (m = 1; m < n; m++) {
for (i = 0; i < n-m; i++) {
ho = xa[i] - x;
hp = xa[i+m] - x;
w = c[i+1] - d[i];
if ((den = ho-hp) == 0.0) JSCerror("Error in routine polint_cx.");
den = w/den;
d[i] = hp * den;
c[i] = ho * den;
}
y += (dy = (2 * (ns + 1) < (n-m) ? c[ns + 1] : d[ns--]));
}
}
+1717
View File
File diff suppressed because it is too large Load Diff
+142
View File
@@ -0,0 +1,142 @@
/**********************************************************
This software is part of J.-S. Caux's ABACUS++ library.
Copyright (c)
-----------------------------------------------------------
File: src/HEIS/Heis_Chem_Pot.cc
Purpose: calculates the chemical potential.
***********************************************************/
#include "JSC.h"
namespace JSC {
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) JSCerror("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;
Heis_Base baseconfig_groundstate(BD1, Nrapidities_groundstate);
if ((Delta > 0.0) && (Delta < 1.0)) {
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 JSCerror("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;
JSCerror("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) JSCerror("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 Heis_Bethe_State& AveragingState)
{
return(-H_vs_M (AveragingState.chain.Delta, AveragingState.chain.Nsites, AveragingState.base.Mdown)); // - sign since E_{M+1} - E_M = -H
}
}
+376
View File
@@ -0,0 +1,376 @@
/**********************************************************
This software is part of J.-S. Caux's ABACUS++ library.
Copyright (c)
-----------------------------------------------------------
File: src/HEIS/Heis_Matrix_Element_Contrib.cc
Purpose: handles the generic call for a matrix element.
***********************************************************/
#include "JSC.h"
using namespace std;
using namespace JSC;
namespace JSC {
//DP Compute_Matrix_Element_Contrib (char whichDSF, bool fixed_iK, XXZ_Bethe_State& LeftState,
//XXZ_Bethe_State& RightState, DP Chem_Pot, fstream& DAT_outfile)
//DP Compute_Matrix_Element_Contrib (char whichDSF, int iKmin, int iKmax, XXZ_Bethe_State& LeftState,
// XXZ_Bethe_State& RightState, DP Chem_Pot, fstream& DAT_outfile)
DP Compute_Matrix_Element_Contrib (char whichDSF, int iKmin, int iKmax, XXZ_Bethe_State& LeftState,
XXZ_Bethe_State& RightState, DP Chem_Pot, stringstream& DAT_outfile)
{
// This function prints the matrix 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 element is needed from the number of particles in Left and Right states:
bool fixed_iK = (iKmin == iKmax);
DP ME = 0.0;
if (!(LeftState.conv && RightState.conv)) ME = 0.0;
else if (whichDSF == 'Z')
ME = LeftState.E - RightState.E;
else if (whichDSF == 'm')
ME = exp(real(ln_Smin_ME (RightState, LeftState)));
else if (whichDSF == 'z') {
if (LeftState.label == RightState.label)
//MEsq = RightState.chain.Nsites * 0.25 * pow((1.0 - 2.0*RightState.base.Mdown/RightState.chain.Nsites), 2.0);
ME = sqrt(RightState.chain.Nsites * 0.25) * (1.0 - 2.0*RightState.base.Mdown/RightState.chain.Nsites);
else ME = exp(real(ln_Sz_ME (RightState, LeftState)));
}
else if (whichDSF == 'p')
ME = exp(real(ln_Smin_ME (LeftState, RightState)));
else JSCerror("Wrong whichDSF in Compute_Matrix_Element_Contrib.");
if (is_nan(ME)) ME = 0.0;
//if (LeftState.dev > 1.0e-16 || RightState.dev > 1.0e-16) ME = 0.0; // kill deviated contributions
// Do the momentum business:
int iKout = LeftState.iK - RightState.iK;
while(iKout < 0) iKout += RightState.chain.Nsites;
while(iKout >= RightState.chain.Nsites) iKout -= RightState.chain.Nsites;
// Print information to fstream:
if (iKout >= iKmin && iKout <= iKmax) {
if (whichDSF == 'Z') {
DAT_outfile << endl << setprecision(16) << LeftState.E - RightState.E - (LeftState.base.Mdown - RightState.base.Mdown) * Chem_Pot << "\t"
<< iKout << "\t"
//<< LeftState.conv << "\t"
<< setprecision(3) << LeftState.dev << "\t"
<< LeftState.label;
}
else {
DAT_outfile << endl << setprecision(16) << LeftState.E - RightState.E - (LeftState.base.Mdown - RightState.base.Mdown) * Chem_Pot << "\t"
<< iKout << "\t"
<< ME << "\t"
//<< LeftState.conv << "\t"
<< setprecision(3) << LeftState.dev << "\t"
<< LeftState.label;
}
} // 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 - RightState.E - (LeftState.base.Mdown - RightState.base.Mdown) * Chem_Pot);
else if (fixed_iK) // data value is MEsq * omega:
data_value = ME * ME * (LeftState.E - RightState.E - (LeftState.base.Mdown - RightState.base.Mdown) * Chem_Pot);
return(data_value);
}
//DP Compute_Matrix_Element_Contrib (char whichDSF, bool fixed_iK, XXX_Bethe_State& LeftState,
//XXX_Bethe_State& RightState, DP Chem_Pot, fstream& DAT_outfile)
//DP Compute_Matrix_Element_Contrib (char whichDSF, int iKmin, int iKmax, XXX_Bethe_State& LeftState,
//XXX_Bethe_State& RightState, DP Chem_Pot, fstream& DAT_outfile)
DP Compute_Matrix_Element_Contrib (char whichDSF, int iKmin, int iKmax, XXX_Bethe_State& LeftState,
XXX_Bethe_State& RightState, DP Chem_Pot, stringstream& 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 element is needed from the number of particles in Left and Right states:
bool fixed_iK = (iKmin == iKmax);
DP ME = 0.0;
complex<DP> ME_CX = 0.0;
int nrinfrap = 0; // for energy shift from chemical potential
if (!(LeftState.conv && RightState.conv)) { ME = 0.0; ME_CX = 0.0;}
else if (whichDSF == 'Z')
ME = LeftState.E - RightState.E;
else if (whichDSF == 'm')
ME = exp(real(ln_Smin_ME (RightState, LeftState)));
else if (whichDSF == 'z') {
// Recognize the presence of an infinite rapidity:
if (LeftState.base.Mdown == RightState.base.Mdown - 1) { // infinite rapidity present, use rescaled S^- matrix element instead of S^z one:
nrinfrap = 1;
// Correction factor for MEsq: Smffsq to Szffsq = 1/(N - 2M + 2)
ME = sqrt(1.0/(RightState.chain.Nsites - 2*RightState.base.Mdown + 2)) * exp(real(ln_Smin_ME (RightState, LeftState)));
}
else { // no infinite rapidity, use S^z matrix element:
if (LeftState.label == RightState.label)
//MEsq = RightState.chain.Nsites * 0.25 * pow((1.0 - 2.0*RightState.base.Mdown/RightState.chain.Nsites), 2.0);
ME = sqrt(RightState.chain.Nsites * 0.25) * (1.0 - 2.0*RightState.base.Mdown/RightState.chain.Nsites);
else ME = exp(real(ln_Sz_ME (RightState, LeftState)));
}
}
else if (whichDSF == 'p') {
// Recognize the presence of two infinite rapidities:
if (LeftState.base.Mdown == RightState.base.Mdown - 1) { // two infinite rapidities, use rescaled S^- matrix element instead of S^+
nrinfrap = 2;
// Correction factor for MEsq: Smffsq to Spffsq = 2/((N - 2M + 2) (N - 2M + 1))
ME = sqrt(2.0/((RightState.chain.Nsites - 2*RightState.base.Mdown + 2.0) * (RightState.chain.Nsites - 2*RightState.base.Mdown + 1.0)))
* exp(real(ln_Smin_ME (RightState, LeftState)));
}
else if (LeftState.base.Mdown == RightState.base.Mdown) { // one infinite rapidity, use rescaled S^z matrix element instead of S^+
nrinfrap = 1;
// Correction factor for MEsq: Szffsq to Spffsq = 4/(N - 2M)
ME = sqrt(4.0/(RightState.chain.Nsites - 2* RightState.base.Mdown)) * exp(real(ln_Sz_ME (RightState, LeftState)));
}
else ME = exp(real(ln_Smin_ME (LeftState, RightState)));
}
else if (whichDSF == 'a') // S^z_j S^z_{j+1} operator
ME = exp(real(ln_Szz_ME (LeftState, RightState)));
else if (whichDSF == 'b') // S^z_j S^-_{j+1} + h.c. operator
ME = exp(real(ln_Szm_p_Smz_ME (RightState, LeftState)));
else if (whichDSF == 'c') // S^-_j S^-{j+1} operator
ME = exp(real(ln_Smm_ME (RightState, LeftState)));
else if (whichDSF == 'q') // Geometric quench
//ME_CX = ln_Overlap (LeftState, RightState);
ME_CX = ln_Overlap (RightState, LeftState);
else JSCerror("Wrong whichDSF in Compute_Matrix_Element_Contrib.");
if (is_nan(ME)) ME = 0.0;
if (is_nan(norm(ME_CX))) ME_CX = -100.0;
//if (LeftState.dev > 1.0e-16 || RightState.dev > 1.0e-16) {
//ME = 0.0; ME_CX = (0.0,0.0); // kill deviated contributions
//}
// Do the momentum business:
int iKout = LeftState.iK - RightState.iK;
while(iKout < 0) iKout += RightState.chain.Nsites;
while(iKout >= RightState.chain.Nsites) iKout -= RightState.chain.Nsites;
// Print information to fstream:
if (iKout >= iKmin && iKout <= iKmax) {
if (whichDSF == 'Z') {
DAT_outfile << endl << setprecision(16) << LeftState.E - RightState.E - (LeftState.base.Mdown + nrinfrap - RightState.base.Mdown) * Chem_Pot << "\t"
<< iKout << "\t"
//<< LeftState.conv << "\t"
<< setprecision(3) << LeftState.dev << "\t"
<< LeftState.label;
}
else if (whichDSF == 'q') {
DAT_outfile << endl << setprecision(16) << LeftState.E - RightState.E - (LeftState.base.Mdown + nrinfrap - RightState.base.Mdown) * Chem_Pot << "\t"
<< iKout << "\t"
<< real(ME_CX) << "\t" << imag(ME_CX) - twoPI * int(imag(ME_CX)/twoPI + 1.0e-10) << "\t"
//<< LeftState.conv << "\t"
<< setprecision(3) << LeftState.dev << "\t"
<< LeftState.label;
}
else {
DAT_outfile << endl << setprecision(16) << LeftState.E - RightState.E - (LeftState.base.Mdown + nrinfrap - RightState.base.Mdown) * Chem_Pot << "\t"
<< iKout << "\t"
<< ME << "\t"
//<< LeftState.conv << "\t"
<< setprecision(3) << LeftState.dev << "\t"
<< LeftState.label;
}
} // 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 - RightState.E - (LeftState.base.Mdown - RightState.base.Mdown) * Chem_Pot);
else if (whichDSF == 'q')
data_value = exp(2.0 * real(ME_CX));
else if (fixed_iK) // data value is MEsq * omega:
data_value = ME * ME * (LeftState.E - RightState.E - (LeftState.base.Mdown - RightState.base.Mdown) * Chem_Pot);
return(data_value);
}
//DP Compute_Matrix_Element_Contrib (char whichDSF, bool fixed_iK, XXZ_gpd_Bethe_State& LeftState,
//XXZ_gpd_Bethe_State& RightState, DP Chem_Pot, fstream& DAT_outfile)
//DP Compute_Matrix_Element_Contrib (char whichDSF, int iKmin, int iKmax, XXZ_gpd_Bethe_State& LeftState,
// XXZ_gpd_Bethe_State& RightState, DP Chem_Pot, fstream& DAT_outfile)
DP Compute_Matrix_Element_Contrib (char whichDSF, int iKmin, int iKmax, XXZ_gpd_Bethe_State& LeftState,
XXZ_gpd_Bethe_State& RightState, DP Chem_Pot, stringstream& 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.
/*
cout << "\t" << LeftState.label << endl << "\t" << LeftState.Ix2 << endl;
cout << "\t0: ";
for (int i = 0; i < LeftState.base.Nrap[0]; ++i) cout << LeftState.lambda[0][i]*2.0/PI << "\t";
cout << endl;
cout << "\t1: ";
for (int i = 0; i < LeftState.base.Nrap[1]; ++i) cout << LeftState.lambda[1][i]*2.0/PI << "\t";
cout << endl;
*/
bool fixed_iK = (iKmin == iKmax);
// If any of the rapidities outside of fundamental interval -pi/2 < lambda <= pi/2, set matrix element to zero.
bool rap_in_fundamental = true;
int sum1 = 0;
for (int j = 0; j < LeftState.chain.Nstrings; ++j) {
//for (int alpha = 0; alpha < LeftState.base.Nrap[j]; ++alpha) {
//if (LeftState.lambda[j][alpha] <= -0.5*PI || LeftState.lambda[j][alpha] > 0.5*PI)
//if (LeftState.lambda[j][alpha] <= -0.5*PI || LeftState.lambda[j][alpha] > 0.5*PI)
//rap_in_fundamental = false;
//}
/*
// TEST 2014 06 26: comment this out, replace by -\pi/2 \leq \lambda \leq \pi/2, see below
if (LeftState.base.Nrap[j] > 0 && LeftState.lambda[j][LeftState.base.Nrap[j] - 1] - LeftState.lambda[j][0] >= PI)
rap_in_fundamental = false;
sum1 = 0;
for (int k = 0; k < LeftState.chain.Nstrings; ++k)
sum1 += LeftState.base.Nrap[k] * (2 * JSC::min(LeftState.chain.Str_L[j], LeftState.chain.Str_L[k]) - ((j == k) ? 1 : 0));
// This almost does it: only missing are the states with one on -PI/2 and one on PI/2
if (LeftState.base.Nrap[j] >= 1
&& (LeftState.Ix2[j][0] <= -(LeftState.chain.Nsites - sum1)
|| (LeftState.Ix2[j][LeftState.base.Nrap[j] - 1] - LeftState.Ix2[j][0])
> 2*(LeftState.chain.Nsites - sum1)))
rap_in_fundamental = false;
*/
// attempt 2014 06 26
//for (int alpha = 0; alpha < LeftState.base.Nrap[j]; ++alpha) {
//if (LeftState.lambda[j][alpha] < -0.5*PI || LeftState.lambda[j][alpha] > 0.5*PI)
// rap_in_fundamental = false;
//}
/*
if (LeftState.base.Nrap[j] > 0 &&
((LeftState.lambda[j][LeftState.base.Nrap[j] - 1] - LeftState.lambda[j][0] >= PI)
|| LeftState.lambda[j][0] < -0.5*PI + 1.0e-10
|| LeftState.lambda[j][LeftState.base.Nrap[j] - 1] > 0.5*PI
//|| LeftState.lambda[j][0] > 0.5*PI
//((LeftState.lambda[j][LeftState.base.Nrap[j] - 1] - LeftState.lambda[j][0] >= PI - 1.0e-10)
//|| LeftState.lambda[j][0] < -0.5*PI + 1.0e-10
//|| LeftState.lambda[j][LeftState.base.Nrap[j] - 1] > 0.5*PI + 1.0e-10
)) // include safety in limits
rap_in_fundamental = false;
*/
/*
if (LeftState.base.Nrap[j] > 0 &&
((LeftState.lambda[j][LeftState.base.Nrap[j] - 1] - LeftState.lambda[j][0] >= PI)
//|| (LeftState.base.Nrap[j] == 1 && fabs(LeftState.lambda[j][0]) > 0.5*PI)
))
rap_in_fundamental = false;
*/
// Logic: allow rapidities -PI/2 <= lambda <= PI/2 (including boundaries)
if (LeftState.base.Nrap[j] > 0 &&
(LeftState.lambda[j][0] < -PI/2 || LeftState.lambda[j][LeftState.base.Nrap[j] - 1] > PI/2))
rap_in_fundamental = false;
if (RightState.base.Nrap[j] > 0 &&
(RightState.lambda[j][0] < -PI/2 || RightState.lambda[j][RightState.base.Nrap[j] - 1] > PI/2))
rap_in_fundamental = false;
// rapidities should also be ordered as the quantum numbers:
for (int alpha = 1; alpha < LeftState.base.Nrap[j]; ++alpha)
if (LeftState.lambda[j][alpha - 1] >= LeftState.lambda[j][alpha])
rap_in_fundamental = false;
for (int alpha = 1; alpha < RightState.base.Nrap[j]; ++alpha)
if (RightState.lambda[j][alpha - 1] >= RightState.lambda[j][alpha])
rap_in_fundamental = false;
} // for int j
// Identify which matrix element is needed from the number of particles in Left and Right states:
DP ME = 0.0;
//if (!(LeftState.conv && RightState.conv)) ME = 0.0;
if (!(LeftState.conv && RightState.conv && rap_in_fundamental)) ME = 0.0;
else if (whichDSF == 'Z')
ME = LeftState.E - RightState.E;
else if (whichDSF == 'm')
ME = exp(real(ln_Smin_ME (RightState, LeftState)));
else if (whichDSF == 'z') {
if (LeftState.label == RightState.label)
//MEsq = RightState.chain.Nsites * 0.25 * pow((1.0 - 2.0*RightState.base.Mdown/RightState.chain.Nsites), 2.0);
ME = sqrt(RightState.chain.Nsites * 0.25) * (1.0 - 2.0*RightState.base.Mdown/RightState.chain.Nsites);
else ME = exp(real(ln_Sz_ME (RightState, LeftState)));
}
else if (whichDSF == 'p')
ME = exp(real(ln_Smin_ME (LeftState, RightState)));
else JSCerror("Wrong whichDSF in Compute_Matrix_Element_Contrib.");
if (is_nan(ME)) ME = 0.0;
//if (LeftState.dev > 1.0e+2 || RightState.dev > 1.0e+2) ME = 0.0; // kill deviated contributions
if (fabs(ME) > 1.0) ME = 0.0;
// Do the momentum business:
int iKout = LeftState.iK - RightState.iK;
while(iKout < 0) iKout += RightState.chain.Nsites;
while(iKout >= RightState.chain.Nsites) iKout -= RightState.chain.Nsites;
// Print information to fstream:
if (iKout >= iKmin && iKout <= iKmax) {
if (whichDSF == 'Z') {
DAT_outfile << endl << setprecision(16) << LeftState.E - RightState.E - (LeftState.base.Mdown - RightState.base.Mdown) * Chem_Pot << "\t"
<< iKout << "\t"
//<< LeftState.conv << "\t"
<< setprecision(3) << LeftState.dev << "\t"
<< LeftState.label;
}
else {
DAT_outfile << endl << setprecision(16) << LeftState.E - RightState.E - (LeftState.base.Mdown - RightState.base.Mdown) * Chem_Pot << "\t"
<< iKout << "\t"
<< ME << "\t"
//<< LeftState.conv << "\t"
<< setprecision(3) << LeftState.dev << "\t"
<< LeftState.label;
/*
cout << setprecision(16) << LeftState.E - RightState.E - (LeftState.base.Mdown - RightState.base.Mdown) * Chem_Pot << "\t" << iKout << "\t" << ME << "\t" << setprecision(3) << LeftState.dev << "\t" << LeftState.label << "\t" << setprecision(16) << LeftState.lambda[0][0]/PI << "\t" << LeftState.Ix2[0][0] << "\t" << LeftState.lambda[0][LeftState.base.Nrap[0] - 1]/PI << "\t" << LeftState.Ix2[0][LeftState.base.Nrap[0] - 1];
if (LeftState.base.Nrap[1] > 0) cout << "\t" << LeftState.lambda[1][0]/PI << "\t" << LeftState.Ix2[1][0];
if (LeftState.lambda[0][0] < -0.5*PI + 1.0e-10 || LeftState.lambda[0][LeftState.base.Nrap[0] - 1] > 0.5*PI - 1.0e-10 || (LeftState.base.Nrap[1] > 0 && (LeftState.lambda[1][0] < -0.5*PI || LeftState.lambda[1][0] > 0.5*PI))) cout << "\t" << "*****";
cout << endl;
*/
}
} // 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 - RightState.E - (LeftState.base.Mdown - RightState.base.Mdown) * Chem_Pot);
else if (fixed_iK) // data value is MEsq * omega:
data_value = ME * ME * (LeftState.E - RightState.E - (LeftState.base.Mdown - RightState.base.Mdown) * Chem_Pot);
return(data_value);
}
} // namespace JSC
+255
View File
@@ -0,0 +1,255 @@
/**********************************************************
This software is part of J.-S. Caux's ABACUS++ library.
Copyright (c)
-----------------------------------------------------------
File: src/HEIS/Heis_Sumrules.cc
Purpose: defines sumrule factors for Heisenberg
***********************************************************/
#include "JSC.h"
using namespace std;
namespace JSC {
DP 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;
if (Delta < 1.0 && 1.0 - Delta < 1.0e-6) eps_Delta *= -1.0;
// Define the chain: J, Delta, h, Nsites
Heis_Chain chain(1.0, Delta, 0.0, N);
// Define the base: chain, Mdown
Heis_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
Heis_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
XXZ_Bethe_State gstate(chain, gbase);
// Compute everything about the ground state
gstate.Compute_All(true);
E0_Delta = gstate.E;
// Define the ground state
XXZ_Bethe_State gstate2(chain2, gbase2);
// Compute everything about the ground state
gstate2.Compute_All(true);
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 JSCerror("Wrong anisotropy in 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);
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 JSCerror("option not implemented in X_avg.");
return(answer);
}
DP S1_sumrule_factor (char mporz, DP Delta, int N, int M, DP Chem_Pot, 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 = - 4.0 * ((1.0 - Delta * cos((twoPI * iK)/N)) * X_x + (Delta - cos((twoPI * iK)/N)) * X_z + 0.5 * Chem_Pot * 0.5 *(N - 2*M))/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;
else if (mporz == 'z') sumrule = iK == 0 ? 1.0 : -2.0 * X_x * (1.0 - cos((twoPI * iK)/N))/N;
else if (mporz == 'Z') sumrule = 1.0; // partition function
else if (mporz == 'a') sumrule = 1.0;
else if (mporz == 'b') sumrule = 1.0;
else if (mporz == 'c') sumrule = 1.0;
else JSCerror("option not implemented in S1_sumrule_factor.");
//return(1.0/sumrule);
return(1.0/(sumrule + 1.0e-16)); // sumrule is 0 for iK == 0 or N
}
DP S1_sumrule_factor (char mporz, DP Delta, int N, int M, DP Chem_Pot, 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 = - 4.0 * ((1.0 - Delta * cos((twoPI * iK)/N)) * X_x + (Delta - cos((twoPI * iK)/N)) * X_z + 0.5 * Chem_Pot * 0.5 *(N - 2*M))/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;
else if (mporz == 'z') sumrule = -2.0 * X_x * (1.0 - cos((twoPI * iK)/N))/N;
else if (mporz == 'Z') sumrule = 1.0; // partition function
else if (mporz == 'a') sumrule = 1.0;
else if (mporz == 'b') sumrule = 1.0;
else if (mporz == 'c') sumrule = 1.0;
else JSCerror("option not implemented in S1_sumrule_factor.");
return(1.0/(sumrule + 1.0e-16)); // sumrule is 0 for iK == 0 or N
}
//DP Sumrule_Factor (char whichDSF, Heis_Bethe_State& AveragingState, DP Chem_Pot, bool fixed_iK, int iKneeded)
DP Sumrule_Factor (char whichDSF, Heis_Bethe_State& AveragingState, 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')
sumrule_factor = 1.0/AveragingState.base.Mdown;
else if (whichDSF == 'z') sumrule_factor = 1.0/(0.25 * AveragingState.chain.Nsites);
else if (whichDSF == 'p') sumrule_factor = 1.0/(AveragingState.chain.Nsites - AveragingState.base.Mdown);
else if (whichDSF == 'a') sumrule_factor = 1.0;
else if (whichDSF == 'b') sumrule_factor = 1.0;
else if (whichDSF == 'c') sumrule_factor = 1.0;
else if (whichDSF == 'q') sumrule_factor = 1.0;
else JSCerror("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, AveragingState.chain.Delta, AveragingState.chain.Nsites, AveragingState.base.Mdown, iKneeded);
sumrule_factor = S1_sumrule_factor (whichDSF, AveragingState.chain.Delta, AveragingState.chain.Nsites, AveragingState.base.Mdown, Chem_Pot, iKmax);
else if (whichDSF == 'a') sumrule_factor = 1.0;
else if (whichDSF == 'b') sumrule_factor = 1.0;
else if (whichDSF == 'c') sumrule_factor = 1.0;
else if (whichDSF == 'q') sumrule_factor = 1.0;
else JSCerror("whichDSF option not consistent in Sumrule_Factor");
}
return(sumrule_factor);
}
void Evaluate_F_Sumrule (string prefix, char whichDSF, const Heis_Bethe_State& AveragingState, DP Chem_Pot, int iKmin_ref, int iKmax_ref)
{
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()) JSCerror("Could not open raw input file in Evaluate_F_Sumrule(Heis...).");
int iKmin = 0;
int iKmax = AveragingState.chain.Nsites;
int iKmod = AveragingState.chain.Nsites;
// We run through the data file to chech the f sumrule at each positive momenta:
//Vect<DP> Sum_omega_MEsq(0.0, iKmax - iKmin + 1);
Vect<DP> Sum_omega_MEsq(0.0, iKmax - iKmin + 1);
DP omega, ME;
int iK, iKexc;
//int conv;
DP dev;
string label;
while (infile.peek() != EOF) {
infile >> omega >> iK >> ME >> dev >> label;
//if (iK >= iKmin && iK <= iKmax) Sum_omega_MEsq[iK - iKmin] += omega * ME * ME;
iKexc = iK;
while (iKexc > iKmax && iKexc - iKmod >= iKmin) iKexc -= iKmod;
while (iKexc < iKmin && iKexc + iKmod <= iKmax) iKexc += iKmod;
if (iKexc >= iKmin && iKexc <= iKmax) Sum_omega_MEsq[iKexc - iKmin] += omega * ME * ME;
}
infile.close();
ofstream outfile;
outfile.open(FSR_Cstr);
outfile.precision(16);
DP X_x = X_avg ('x', AveragingState.chain.Delta, AveragingState.chain.Nsites, AveragingState.base.Mdown);
DP X_z = X_avg ('z', AveragingState.chain.Delta, AveragingState.chain.Nsites, AveragingState.base.Mdown);
for (int i = iKmin; i <= iKmax; ++i) {
if (i > iKmin) outfile << endl;
outfile << i << "\t" << Sum_omega_MEsq[i] * S1_sumrule_factor (whichDSF, AveragingState.chain.Delta, AveragingState.chain.Nsites, AveragingState.base.Mdown, Chem_Pot, X_x, X_z, i);
}
outfile.close();
}
} // namespace JSC
+139
View File
@@ -0,0 +1,139 @@
/**********************************************************
This software is part of J.-S. Caux's ABACUS++ library.
Copyright (c) 2006-9.
-----------------------------------------------------------
File: M_vs_H.cc
Purpose: field to and from magnetization for Heisenberg
Last modified: 21/10/09
***********************************************************/
#include "JSC.h"
namespace JSC {
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) JSCerror("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;
Heis_Base baseconfig_groundstate(BD1, Nrapidities_groundstate);
if ((Delta > 0.0) && (Delta < 1.0)) {
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 JSCerror("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;
JSCerror("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) JSCerror("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);
}
}
+626
View File
@@ -0,0 +1,626 @@
/**********************************************************
This software is part of J.-S. Caux's ABACUS++ library.
Copyright (c)
-----------------------------------------------------------
File: src/HEIS/XXX_Bethe_State.cc
Purpose: Defines all functions for XXX_Bethe_State
******************************************************************/
#include "JSC.h"
using namespace std;
namespace JSC {
// Function prototypes
DP Theta_XXX (DP lambda, int nj, int nk);
DP ddlambda_Theta_XXX (DP lambda, int nj, int nk);
//***************************************************************************************************
// Function definitions: class XXX_Bethe_State
XXX_Bethe_State::XXX_Bethe_State ()
: Heis_Bethe_State()
{};
XXX_Bethe_State::XXX_Bethe_State (const XXX_Bethe_State& RefState) // copy constructor
: Heis_Bethe_State(RefState)
{
}
XXX_Bethe_State::XXX_Bethe_State (const Heis_Chain& RefChain, int M)
: Heis_Bethe_State(RefChain, M)
{
if (RefChain.Delta != 1.0) {
cout << setprecision(16) << RefChain.Delta << endl;
JSCerror("Delta != 1.0 in XXX_Bethe_State constructor");
}
}
XXX_Bethe_State::XXX_Bethe_State (const Heis_Chain& RefChain, const Heis_Base& RefBase)
: Heis_Bethe_State(RefChain, RefBase)
{
if (RefChain.Delta != 1.0) {
cout << setprecision(16) << RefChain.Delta << endl;
JSCerror("Delta != 1.0 in XXX_Bethe_State constructor");
}
}
/*
XXX_Bethe_State::XXX_Bethe_State (const Heis_Chain& RefChain, long long int base_id_ref, long long int type_id_ref)
: Heis_Bethe_State(RefChain, base_id_ref, type_id_ref)
{
if (RefChain.Delta != 1.0) {
cout << setprecision(16) << RefChain.Delta << endl;
JSCerror("Delta != 1.0 in XXX_Bethe_State constructor");
}
}
*/
XXX_Bethe_State& XXX_Bethe_State::operator= (const XXX_Bethe_State& RefState)
{
if (this != &RefState) {
chain = RefState.chain;
base = RefState.base;
//offsets = RefState.offsets;
Ix2 = RefState.Ix2;
lambda = RefState.lambda;
BE = RefState.BE;
diffsq = RefState.diffsq;
conv = RefState.conv;
iter = RefState.iter;
iter_Newton = RefState.iter_Newton;
E = RefState.E;
iK = RefState.iK;
K = RefState.K;
lnnorm = RefState.lnnorm;
//base_id = RefState.base_id;
//type_id = RefState.type_id;
//id = RefState.id;
//maxid = RefState.maxid;
//nparticles = RefState.nparticles;
label = RefState.label;
}
return(*this);
}
// Member functions
void XXX_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) {
lambda[i][alpha] = chain.Str_L[i] * 0.5 * tan(PI * 0.5 * Ix2[i][alpha]/chain.Nsites);
}
}
return;
}
bool XXX_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;
//int test1, test3;
Vect<bool> Zero_at_level(false, chain.Nstrings); // whether there exists an Ix2 == 0 at a given level
bool higher_string_on_zero = false;
for (int j = 0; j < chain.Nstrings; ++j) {
// The following line puts answer to true if there is at least one higher string with zero Ix2
for (int alpha = 0; alpha < base[j]; ++alpha) if ((Ix2[j][alpha] == 0) && (chain.Str_L[j] > 2) && !(chain.Str_L[j] % 2))
higher_string_on_zero = true;
for (int alpha = 0; alpha < base[j]; ++alpha) if (Ix2[j][alpha] == 0) Zero_at_level[j] = true;
// NOTE: if base[j] == 0, Zero_at_level[j] remains false.
}
bool symmetric_state = (*this).Check_Symmetry();
bool string_coincidence = false;
// Checks that we have strings of equal length modulo 2 with Ix2 == 0, so equal rapidities, and inadmissibility
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.Str_L[j1] + chain.Str_L[j2])%2)))
string_coincidence = true;
}
/*
bool onep_onem_on_zero = false;
if (option == 'm') { // 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*/));
// 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 XXX_Bethe_State::Compute_BE (int j, int alpha)
{
// Fills in the BE members with the value of the Bethe equations.
DP sumtheta = 0.0;
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 += atan(lambda[j][alpha] - lambda[k][beta]);
else sumtheta += 0.5 * Theta_XXX((lambda[j][alpha] - lambda[k][beta]), chain.Str_L[j], chain.Str_L[k]);
}
sumtheta *= 2.0;
BE[j][alpha] = 2.0 * atan(2.0 * lambda[j][alpha]/chain.Str_L[j]) - (sumtheta + PI*Ix2[j][alpha])/chain.Nsites;
}
void XXX_Bethe_State::Compute_BE ()
{
// Fills in the BE members with the value of the Bethe equations.
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 += atan(lambda[j][alpha] - lambda[k][beta]);
else sumtheta += 0.5 * Theta_XXX((lambda[j][alpha] - lambda[k][beta]), chain.Str_L[j], chain.Str_L[k]);
}
sumtheta *= 2.0;
BE[j][alpha] = 2.0 * atan(2.0 * lambda[j][alpha]/chain.Str_L[j]) - (sumtheta + PI*Ix2[j][alpha])/chain.Nsites;
}
}
}
DP XXX_Bethe_State::Iterate_BAE (int j, int alpha)
{
// Returns a new iteration value for lambda[j][alpha] given BE[j][alpha]
return(0.5 * chain.Str_L[j] * tan(0.5 *
//(PI * Ix2[j][alpha] + sumtheta)/chain.Nsites
(2.0 * atan(2.0 * lambda[j][alpha]/chain.Str_L[j]) - BE[j][alpha])
));
}
/*
void XXX_Bethe_State::Iterate_BAE ()
{
// Recalculates the rapidities by iterating Bethe equations
Lambda New_lambda(chain, base);
DP sumtheta = 0.0;
DP arg = 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 += atan(lambda[j][alpha] - lambda[k][beta]);
else sumtheta += 0.5 * Theta_XXX(lambda[j][alpha] - lambda[k][beta], chain.Str_L[j], chain.Str_L[k]);
}
sumtheta *= 2.0;
New_lambda[j][alpha] = 0.5 * chain.Str_L[j] * tan((PI * 0.5 * Ix2[j][alpha] + 0.5 * sumtheta)/chain.Nsites);
}
}
DP New_diffsq = 0.0;
for (int j = 0; j < chain.Nstrings; ++j) {
for (int alpha = 0; alpha < base[j]; ++alpha) {
New_diffsq += pow(New_lambda[j][alpha] - lambda[j][alpha], 2.0);
lambda[j][alpha] = 1.0 * New_lambda[j][alpha] + 0.0 * lambda[j][alpha];
}
}
diffsq = New_diffsq;
iter++;
return;
}
*/
/*
void XXX_Bethe_State::Iterate_BAE_Newton ()
{
// does one step of a Newton method on the rapidities...
Vect_DP RHSBAE (0.0, base.Nraptot); // contains RHS of BAEs
Vect_CX dlambda (0.0, base.Nraptot); // contains delta lambda computed from Newton's method
SQMat_CX Gaudin (0.0, base.Nraptot);
Vect_INT indx (base.Nraptot);
DP sumtheta = 0.0;
DP arg = 0.0;
DP fn_arg = 0.0;
DP olddiffsq = diffsq;
// Compute the RHS of the BAEs:
int index = 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 += atan(lambda[j][alpha] - lambda[k][beta]);
else sumtheta += 0.5 * Theta_XXX((lambda[j][alpha] - lambda[k][beta]), chain.Str_L[j], chain.Str_L[k]);
}
sumtheta *= 2.0;
RHSBAE[index] = chain.Nsites * 2.0 * atan(2.0 * lambda[j][alpha]/chain.Str_L[j]) - sumtheta - PI*Ix2[j][alpha];
index++;
}
}
(*this).Build_Reduced_Gaudin_Matrix (Gaudin);
for (int i = 0; i < base.Nraptot; ++i) dlambda[i] = - RHSBAE[i];
DP d;
ludcmp_CX (Gaudin, indx, d);
lubksb_CX (Gaudin, indx, dlambda);
diffsq = 0.0;
for (int i = 0; i < base.Nraptot; ++i) diffsq += norm(dlambda[i]);
// 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]));
}
index = 0;
for (int j = 0; j < chain.Nstrings; ++j) {
for (int alpha = 0; alpha < base[j]; ++alpha) {
lambda[j][alpha] += real(dlambda[index]);
index++;
}
}
iter_Newton++;
return;
}
*/
bool XXX_Bethe_State::Check_Rapidities()
{
bool nonan = true;
for (int j = 0; j < chain.Nstrings; ++j)
for (int alpha = 0; alpha < base[j]; ++alpha) nonan *= !is_nan(lambda[j][alpha]);
return nonan;
}
DP XXX_Bethe_State::String_delta ()
{
// Computes the sum of absolute value of \delta^{a, a+1} in string hypothesis, for a given Bethe eigenstate
DP delta = 0.0;
int occupied_strings = 0;
for (int i = 0; i < (*this).chain.Nstrings; ++i) if ((*this).chain.Str_L[i] > 1) occupied_strings += (*this).base.Nrap[i];
//if ((*this).conv == 0) delta = 1.0;
if (occupied_strings == 0) delta = 0.0;
else {
Vect_DP ln_deltadiff(0.0, 1000); // contains ln |delta^{a, a+1}|
Vect_DP deltadiff(0.0, 1000); // contains |delta^{a, a+1}|
complex<DP> log_BAE_reg = 0.0;
for (int j = 0; j < (*this).chain.Nstrings; ++j) {
for (int alpha = 0; alpha < (*this).base[j]; ++alpha) {
ln_deltadiff = 0.0;
for (int a = 1; a <= (*this).chain.Str_L[j]; ++a) {
if ((*this).chain.Str_L[j] > 1) { // else the BAE are already 1
log_BAE_reg = DP((*this).chain.Nsites) * log(((*this).lambda[j][alpha] + 0.5 * II * ((*this).chain.Str_L[j] + 1.0 - 2.0 * a + 1.0))
/((*this).lambda[j][alpha] + 0.5 * II * ((*this).chain.Str_L[j] + 1.0 - 2.0 * a - 1.0)));
for (int k = 0; k < (*this).chain.Nstrings; ++k)
for (int beta = 0; beta < (*this).base[k]; ++beta)
for (int b = 1; b <= (*this).chain.Str_L[k]; ++b) {
if ((j != k) || (alpha != beta) || (a != b - 1))
log_BAE_reg += log((*this).lambda[j][alpha] + 0.5 * II * ((*this).chain.Str_L[j] + 1.0 - 2.0 * a )
- ((*this).lambda[k][beta] + 0.5 * II * ((*this).chain.Str_L[k] + 1.0 - 2.0 * b )
) - II );
if ((j != k) || (alpha != beta) || (a != b + 1))
log_BAE_reg -= log(((*this).lambda[j][alpha] + 0.5 * II * ((*this).chain.Str_L[j] + 1.0 - 2.0 * a )
)
- ((*this).lambda[k][beta] + 0.5 * II * ((*this).chain.Str_L[k] + 1.0 - 2.0 * b )
) + II );
}
// The regular LHS of BAE is now defined. Now sum up the deltas...
if (a == 1) ln_deltadiff[0] = - real(log_BAE_reg);
else if (a < (*this).chain.Str_L[j]) ln_deltadiff[a - 1] = ln_deltadiff[a-2] - real(log_BAE_reg);
else if (a == (*this).chain.Str_L[j]) ln_deltadiff[a-1] = real(log_BAE_reg);
} // if ((*this).chain.Str_L[j] > 1)
} // for (int a = 1; ...
for (int a = 0; a < (*this).chain.Str_L[j]; ++a) {
deltadiff[a] = ln_deltadiff[a] != 0.0 ? exp(ln_deltadiff[a]) : 0.0;
delta += fabs(deltadiff[a]);
}
} // alpha sum
} // j sum
if (is_nan(delta)) delta = 1.0; // sentinel
} // else
return delta;
}
void XXX_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 += chain.Str_L[j] / ( 4.0 * lambda[j][alpha] * lambda[j][alpha] + chain.Str_L[j] * chain.Str_L[j]);
}
}
sum *= - chain.J * 2.0;
E = sum;
return;
}
/*
void XXX_Bethe_State::Compute_Momentum ()
{
int sum_Ix2 = 0;
DP sum_M = 0.0;
for (int j = 0; j < chain.Nstrings; ++j) {
sum_M += base[j];
for (int alpha = 0; alpha < base[j]; ++alpha) {
sum_Ix2 += Ix2[j][alpha];
}
}
iK = (chain.Nsites/2) * int(sum_M) - (sum_Ix2/2);
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 XXX_Bethe_State::Build_Reduced_Gaudin_Matrix (SQMat<complex<DP> >& Gaudin_Red)
{
if (Gaudin_Red.size() != base.Nraptot) JSCerror("Passing matrix of wrong size in Build_Reduced_Gaudin_Matrix.");
int index_jalpha;
int index_kbeta;
DP sum_hbar_XXX = 0.0;
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_XXX = 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_XXX
+= ddlambda_Theta_XXX (lambda[j][alpha] - lambda[kp][betap], chain.Str_L[j], chain.Str_L[kp]);
}
}
Gaudin_Red[index_jalpha][index_kbeta]
= complex<DP> ( chain.Nsites * chain.Str_L[j]/(lambda[j][alpha] * lambda[j][alpha] + 0.25 * chain.Str_L[j] * chain.Str_L[j])
- sum_hbar_XXX);
}
else {
if ((chain.Str_L[j] == 1) && (chain.Str_L[k] == 1))
Gaudin_Red[index_jalpha][index_kbeta] =
complex<DP> ( 2.0/(pow(lambda[j][alpha] - lambda[k][beta], 2.0) + 1.0));
else
Gaudin_Red[index_jalpha][index_kbeta] =
complex<DP> (ddlambda_Theta_XXX (lambda[j][alpha] - lambda[k][beta], chain.Str_L[j], chain.Str_L[k]));
}
index_kbeta++;
}
}
index_jalpha++;
}
}
return;
}
bool XXX_Bethe_State::Check_Finite_rap ()
{
bool answer = true;
for (int j = 0; j < chain.Nstrings; ++j) {
for (int alpha = 0; alpha < base[j]; ++alpha) {
if (fabs(lambda[j][alpha]) > 1.0e6) answer = false;
}
}
return(answer);
}
// ****************************************************************************************************
// non-member functions
DP Theta_XXX (DP lambda, int nj, int nk)
{
DP result;
if ((nj == 1) && (nk == 1)) result = 2.0 * atan(lambda);
else {
result = (nj == nk) ? 0.0 : 2.0 * atan(2.0 * lambda/fabs(nj - nk));
for (int a = 1; a < JSC::min(nj, nk); ++a) result += 4.0 * atan(2.0 * lambda/(fabs(nj - nk) + 2*a));
result += 2.0 * atan(2.0 * lambda/(nj + nk));
}
return (result);
}
DP ddlambda_Theta_XXX (DP lambda, int nj, int nk)
{
int n = abs(nj - nk);
DP result = (nj == nk) ? 0.0 : DP(n)/(lambda * lambda + 0.25 * n * n);
for (int a = 1; a < JSC::min(nj, nk); ++a) result += 2.0 * (n + 2.0*a)
/ (lambda * lambda + 0.25 * (n + 2.0*a) * (n + 2.0*a));
result += DP(nj + nk)/(lambda * lambda + 0.25 * (nj + nk) * (nj + nk));
return (result);
}
/*
DP ddlambda_Theta_XXX (DP lambda, int nj, int nk)
{
DP result = (nj == nk) ? 0.0 : DP(nj - nk)/(lambda * lambda + 0.25 * (nj - nk) * (nj - nk));
for (int a = 1; a < JSC::min(nj, nk); ++a) result += 2.0 * (nj - nk + 2.0*a) * (nj - nk + 2.0*a)
/ (lambda * lambda + 0.25 * (nj - nk + 2.0*a) * (nj - nk + 2.0*a));
result += DP(nj + nk)/(lambda * lambda + 0.25 * (nj + nk) * (nj + nk));
return (result);
}
*/
XXX_Bethe_State Add_Particle_at_Center (const XXX_Bethe_State& RefState)
{
if (2*RefState.base.Mdown == RefState.chain.Nsites)
JSCerror("Trying to add a down spin to a zero-magnetized chain in Add_Particle_at_Center.");
Vect<int> newM = RefState.base.Nrap;
newM[0] = newM[0] + 1;
Heis_Base newBase (RefState.chain, newM);
XXX_Bethe_State ReturnState (RefState.chain, newBase);
for (int il = 1; il < RefState.chain.Nstrings; ++il)
for (int alpha = 0; alpha < RefState.base.Nrap[il]; ++alpha)
ReturnState.Ix2[il][alpha] = RefState.Ix2[il][alpha];
// Add a quantum number in middle (explicitly: to right of index M[0]/2)
// and shift quantum numbers by half-integer away from added one:
ReturnState.Ix2[0][RefState.base.Nrap[0]/2] = RefState.Ix2[0][RefState.base.Nrap[0]/2] - 1;
for (int i = 0; i < RefState.base.Nrap[0] + 1; ++i)
ReturnState.Ix2[0][i + (i >= RefState.base.Nrap[0]/2)] = RefState.Ix2[0][i] - 1 + 2*(i >= RefState.base.Nrap[0]/2);
return(ReturnState);
}
XXX_Bethe_State Remove_Particle_at_Center (const XXX_Bethe_State& RefState)
{
if (RefState.base.Nrap[0] == 0)
JSCerror("Trying to remove a down spin in an empty Nrap[0] state.");
Vect<int> newM = RefState.base.Nrap;
newM[0] = newM[0] - 1;
Heis_Base newBase (RefState.chain, newM);
XXX_Bethe_State ReturnState (RefState.chain, newBase);
for (int il = 1; il < RefState.chain.Nstrings; ++il)
for (int alpha = 0; alpha < RefState.base.Nrap[il]; ++alpha)
ReturnState.Ix2[il][alpha] = RefState.Ix2[il][alpha];
// Remove midmost and shift quantum numbers by half-integer towards removed one:
for (int i = 0; i < RefState.base.Nrap[0]-1; ++i)
ReturnState.Ix2[0][i] = RefState.Ix2[0][i + (i >= RefState.base.Nrap[0]/2)] + 1 - 2*(i >= RefState.base.Nrap[0]/2);
return(ReturnState);
}
} // namespace JSC
+646
View File
@@ -0,0 +1,646 @@
/**********************************************************
This software is part of J.-S. Caux's ABACUS++ library.
Copyright (c)
-----------------------------------------------------------
File: src/HEIS/XXZ_Bethe_State.cc
Purpose: Defines all functions for XXZ_Bethe_State
******************************************************************/
#include "JSC.h"
using namespace std;
namespace JSC {
// Function prototypes
inline DP fbar_XXZ (DP lambda, int par, DP tannzetaover2);
DP Theta_XXZ (DP lambda, int nj, int nk, int parj, int park, DP* tannzetaover2);
DP hbar_XXZ (DP lambda, int n, int par, DP* si_n_anis_over_2);
DP ddlambda_Theta_XXZ (DP lambda, int nj, int nk, int parj, int park, DP* si_n_anis_over_2);
//***************************************************************************************************
// Function definitions: class XXZ_Bethe_State
XXZ_Bethe_State::XXZ_Bethe_State ()
: Heis_Bethe_State(), sinhlambda(Lambda(chain, 1)), coshlambda(Lambda(chain, 1)), tanhlambda(Lambda(chain, 1))
{};
XXZ_Bethe_State::XXZ_Bethe_State (const XXZ_Bethe_State& RefState) // copy constructor
: Heis_Bethe_State(RefState), sinhlambda(Lambda(RefState.chain, RefState.base)), coshlambda(Lambda(RefState.chain, RefState.base)),
tanhlambda(Lambda(RefState.chain, RefState.base))
{
// copy arrays into new ones
//cout << "Calling XXZ state copy constructor." << endl;
for (int j = 0; j < RefState.chain.Nstrings; ++j) {
for (int alpha = 0; alpha < RefState.base[j]; ++j) {
sinhlambda[j][alpha] = RefState.sinhlambda[j][alpha];
coshlambda[j][alpha] = RefState.coshlambda[j][alpha];
tanhlambda[j][alpha] = RefState.tanhlambda[j][alpha];
}
}
//cout << "Done calling XXZ state copy constructor." << endl;
}
XXZ_Bethe_State::XXZ_Bethe_State (const Heis_Chain& RefChain, int M)
: Heis_Bethe_State(RefChain, M),
sinhlambda(Lambda(RefChain, M)), coshlambda(Lambda(RefChain, M)), tanhlambda(Lambda(RefChain, M))
{
//cout << "Here in XXZ BS constructor." << endl;
//cout << (*this).lambda[0][0] << endl;
//cout << "OK" << endl;
if ((RefChain.Delta <= -1.0) || (RefChain.Delta >= 1.0)) JSCerror("Delta out of range in XXZ_Bethe_State constructor");
}
XXZ_Bethe_State::XXZ_Bethe_State (const Heis_Chain& RefChain, const Heis_Base& RefBase)
: Heis_Bethe_State(RefChain, RefBase),
sinhlambda(Lambda(RefChain, RefBase)), coshlambda(Lambda(RefChain, RefBase)), tanhlambda(Lambda(RefChain, RefBase))
{
if ((RefChain.Delta <= -1.0) || (RefChain.Delta >= 1.0)) JSCerror("Delta out of range in XXZ_Bethe_State constructor");
}
/*
XXZ_Bethe_State::XXZ_Bethe_State (const Heis_Chain& RefChain, long long int base_id_ref, long long int type_id_ref)
: Heis_Bethe_State(RefChain, base_id_ref, type_id_ref),
sinhlambda(Lambda(chain, base)), coshlambda(Lambda(chain, base)), tanhlambda(Lambda(chain, base))
{
if ((RefChain.Delta <= -1.0) || (RefChain.Delta >= 1.0)) JSCerror("Delta out of range in XXZ_Bethe_State constructor");
}
*/
XXZ_Bethe_State& XXZ_Bethe_State::operator= (const XXZ_Bethe_State& RefState)
{
if (this != &RefState) {
chain = RefState.chain;
base = RefState.base;
//offsets = RefState.offsets;
Ix2 = RefState.Ix2;
lambda = RefState.lambda;
BE = RefState.BE;
diffsq = RefState.diffsq;
conv = RefState.conv;
iter = RefState.iter;
iter_Newton = RefState.iter_Newton;
E = RefState.E;
iK = RefState.iK;
K = RefState.K;
lnnorm = RefState.lnnorm;
//base_id = RefState.base_id;
//type_id = RefState.type_id;
//id = RefState.id;
//maxid = RefState.maxid;
//nparticles = RefState.nparticles;
label = RefState.label;
sinhlambda = RefState.sinhlambda;
coshlambda = RefState.coshlambda;
tanhlambda = RefState.tanhlambda;
}
return(*this);
}
// Member functions
void XXZ_Bethe_State::Set_Free_lambdas()
{
// Sets all the rapidities to the solutions of the BAEs without scattering terms
DP x = 0.0;
for (int i = 0; i < chain.Nstrings; ++i) {
for (int alpha = 0; alpha < base[i]; ++alpha) {
if (chain.par[i] == 1) {
//lambda[i][alpha] = atanh(tan(chain.Str_L[i] * 0.5 * chain.anis) * tan(PI * 0.5 * Ix2[i][alpha]/chain.Nsites));
x = tan(chain.Str_L[i] * 0.5 * chain.anis) * tan(PI * 0.5 * Ix2[i][alpha]/chain.Nsites);
lambda[i][alpha] = atanh(x/sqrt(1.0 + x*x)); // lambda then always initiated real
}
else if (chain.par[i] == -1) {
//lambda[i][alpha] = atanh(-tan(PI * 0.5 * Ix2[i][alpha]/chain.Nsites)/tan(chain.Str_L[i] * 0.5 * chain.anis));
x = -tan(PI * 0.5 * Ix2[i][alpha]/chain.Nsites)/tan(chain.Str_L[i] * 0.5 * chain.anis);
lambda[i][alpha] = atanh(x/sqrt(1.0 + x*x)); // lambda then always initiated real
}
else JSCerror("Invalid parities in Set_Free_lambdas.");
//cout << tan(chain.Str_L[i] * 0.5 * chain.anis) << endl;
//cout << "Set_Free_lambdas: " << i << "\t" << alpha << "\t" << lambda[i][alpha] << "\t" << tan(chain.Str_L[i] * 0.5 * chain.anis) * tan(PI * 0.5 * Ix2[i][alpha]/chain.Nsites) << endl;
}
}
return;
}
void XXZ_Bethe_State::Compute_sinhlambda()
{
for (int j = 0; j < chain.Nstrings; ++j) {
for (int alpha = 0; alpha < base[j]; ++alpha) sinhlambda[j][alpha] = sinh(lambda[j][alpha]);
}
return;
}
void XXZ_Bethe_State::Compute_coshlambda()
{
for (int j = 0; j < chain.Nstrings; ++j) {
for (int alpha = 0; alpha < base[j]; ++alpha) coshlambda[j][alpha] = cosh(lambda[j][alpha]);
}
return;
}
void XXZ_Bethe_State::Compute_tanhlambda()
{
for (int j = 0; j < chain.Nstrings; ++j) {
for (int alpha = 0; alpha < base[j]; ++alpha) tanhlambda[j][alpha] = tanh(lambda[j][alpha]);
}
return;
}
bool XXZ_Bethe_State::Check_Admissibility(char option)
{
// This function checks the admissibility of the Ix2's of a state:
// returns false if there are higher strings with Ix2 = 0, a totally symmetric distribution of I's at each level,
// and strings of equal length modulo 2 and parity with Ix2 = 0, meaning at least two equal roots in BAE.
bool answer = true;
Vect<bool> Zero_at_level(false, chain.Nstrings); // whether there exists an Ix2 == 0 at a given level
bool higher_string_on_zero = false;
for (int j = 0; j < chain.Nstrings; ++j) {
// The following line puts answer to true if there is at least one higher string with zero Ix2
for (int alpha = 0; alpha < base[j]; ++alpha) if ((Ix2[j][alpha] == 0) && (chain.Str_L[j] >= 2) /*&& !(chain.Str_L[j] % 2)*/)
higher_string_on_zero = true;
for (int alpha = 0; alpha < base[j]; ++alpha) if (Ix2[j][alpha] == 0) Zero_at_level[j] = true;
// NOTE: if base[j] == 0, Zero_at_level[j] remains false.
}
// check symmetry of Ix2 at each level, if there exists a potentially risky Ix2...
bool symmetric_state = (*this).Check_Symmetry();
bool string_coincidence = false;
for (int j1 = 0; j1 < chain.Nstrings; ++j1) {
for (int j2 = j1 + 1; j2 < chain.Nstrings; ++j2)
if (Zero_at_level[j1] && Zero_at_level[j2] && (chain.par[j1] == chain.par[j2]) && (!((chain.Str_L[j1] + chain.Str_L[j2])%2)))
string_coincidence = true;
}
bool M_odd_and_onep_on_zero = false;
if (option == 'z') { // for Sz, if M is odd, exclude symmetric states with a 1+ on zero
// (zero rapidities in left and right states, so FF det not defined).
bool is_ground_state = base.Nrap[0] == base.Mdown && Ix2[0][0] == -(base.Mdown - 1) && Ix2[0][base.Mdown-1] == base.Mdown - 1;
if (Zero_at_level[0] && (base.Mdown % 2) && !is_ground_state) M_odd_and_onep_on_zero = true;
}
bool onep_onem_on_zero = false;
if (option == 'm' || option == 'p') { // for Smin, we also exclude symmetric states with 1+ and 1- strings on zero
if (Zero_at_level[0] && Zero_at_level[1]) onep_onem_on_zero = true;
}
answer = !(symmetric_state && (higher_string_on_zero || string_coincidence || onep_onem_on_zero || M_odd_and_onep_on_zero));
// Now check that no Ix2 is equal to +N (since we take -N into account, and I + N == I by periodicity of exp)
for (int j = 0; j < chain.Nstrings; ++j)
for (int alpha = 0; alpha < base[j]; ++alpha) if ((Ix2[j][alpha] < -chain.Nsites) || (Ix2[j][alpha] >= chain.Nsites)) answer = false;
if (!answer) {
E = 0.0;
K = 0.0;
conv = 0;
iter = 0;
iter_Newton = 0;
lnnorm = -100.0;
}
return(answer); // answer == true: nothing wrong with this Ix2_config
}
void XXZ_Bethe_State::Compute_BE (int j, int alpha)
{
tanhlambda[j][alpha] = tanh(lambda[j][alpha]);
DP sumtheta = 0.0;
for (int k = 0; k < chain.Nstrings; ++k)
for (int beta = 0; beta < base[k]; ++beta) {
if ((chain.Str_L[j] == 1) && (chain.Str_L[k] == 1))
sumtheta += (chain.par[j] == chain.par[k])
? atan((tanhlambda[j][alpha] - tanhlambda[k][beta])/((1.0 - tanhlambda[j][alpha] * tanhlambda[k][beta]) * chain.ta_n_anis_over_2[2]))
: - atan(((tanhlambda[j][alpha] - tanhlambda[k][beta])/(1.0 - tanhlambda[j][alpha] * tanhlambda[k][beta])) * chain.ta_n_anis_over_2[2]) ;
else sumtheta += 0.5 * Theta_XXZ((tanhlambda[j][alpha] - tanhlambda[k][beta])/(1.0 - tanhlambda[j][alpha] * tanhlambda[k][beta]),
chain.Str_L[j], chain.Str_L[k], chain.par[j], chain.par[k], chain.ta_n_anis_over_2);
}
sumtheta *= 2.0;
BE[j][alpha] = ((chain.par[j] == 1) ? 2.0 * atan(tanhlambda[j][alpha]/chain.ta_n_anis_over_2[chain.Str_L[j]])
: -2.0 * atan(tanhlambda[j][alpha] * chain.ta_n_anis_over_2[chain.Str_L[j]])) - (sumtheta + PI*Ix2[j][alpha])/chain.Nsites;
}
void XXZ_Bethe_State::Compute_BE ()
{
// Fills in the BE members with the value of the Bethe equations.
(*this).Compute_tanhlambda();
DP sumtheta = 0.0;
for (int j = 0; j < chain.Nstrings; ++j)
for (int alpha = 0; alpha < base[j]; ++alpha) {
sumtheta = 0.0;
for (int k = 0; k < chain.Nstrings; ++k)
for (int beta = 0; beta < base[k]; ++beta) {
if ((chain.Str_L[j] == 1) && (chain.Str_L[k] == 1))
sumtheta += (chain.par[j] == chain.par[k])
? atan((tanhlambda[j][alpha] - tanhlambda[k][beta])/((1.0 - tanhlambda[j][alpha] * tanhlambda[k][beta]) * chain.ta_n_anis_over_2[2]))
: - atan(((tanhlambda[j][alpha] - tanhlambda[k][beta])/(1.0 - tanhlambda[j][alpha] * tanhlambda[k][beta])) * chain.ta_n_anis_over_2[2]) ;
else sumtheta += 0.5 * Theta_XXZ((tanhlambda[j][alpha] - tanhlambda[k][beta])/(1.0 - tanhlambda[j][alpha] * tanhlambda[k][beta]),
chain.Str_L[j], chain.Str_L[k], chain.par[j], chain.par[k], chain.ta_n_anis_over_2);
}
sumtheta *= 2.0;
BE[j][alpha] = ((chain.par[j] == 1) ? 2.0 * atan(tanhlambda[j][alpha]/chain.ta_n_anis_over_2[chain.Str_L[j]])
: -2.0 * atan(tanhlambda[j][alpha] * chain.ta_n_anis_over_2[chain.Str_L[j]])) - (sumtheta + PI*Ix2[j][alpha])/chain.Nsites;
//if (is_nan(BE[j][alpha])) cout << "BE nan: " << j << "\t" << alpha << "\t" << lambda[j][alpha] << "\t" << tanhlambda[j][alpha] << endl;
}
}
DP XXZ_Bethe_State::Iterate_BAE (int j, int alpha)
{
// Returns a new iteration value for lambda[j][alpha] given tanhlambda and BE Lambdas
// Assumes that tanhlambda[][] and BE[][] have been computed.
DP new_lambda = 0.0;
DP arg = 0.0;
if (chain.par[j] == 1) arg = chain.ta_n_anis_over_2[chain.Str_L[j]]
* tan(0.5 *
//(PI * Ix2[j][alpha] + sumtheta)/chain.Nsites
(2.0 * atan(tanhlambda[j][alpha]/chain.ta_n_anis_over_2[chain.Str_L[j]]) - BE[j][alpha])
);
else if (chain.par[j] == -1) arg = -tan(0.5 *
//(PI * Ix2[j][alpha] + sumtheta)/chain.Nsites)
(-2.0 * atan(tanhlambda[j][alpha] * chain.ta_n_anis_over_2[chain.Str_L[j]]) - BE[j][alpha]))
/chain.ta_n_anis_over_2[chain.Str_L[j]];
if (fabs(arg) < 1.0) {
new_lambda = atanh(arg);
}
else {
new_lambda = lambda[j][alpha]; // back to drawing board...
int block = 0; // counter to prevent runaway while loop
DP new_tanhlambda = 0.0;
DP sumtheta = 0.0;
arg = 10.0; // reset value to start while loop
while ((fabs(arg) > 1.0) && (block++ < 100)) { // recompute the diverging root on its own...
new_lambda *= 1.01; // try to go slowly towards infinity...
new_tanhlambda = tanh(new_lambda);
sumtheta = 0.0;
for (int k = 0; k < chain.Nstrings; ++k) {
for (int beta = 0; beta < base[k]; ++beta)
if ((chain.Str_L[j] == 1) && (chain.Str_L[k] == 1))
sumtheta += (chain.par[j] == chain.par[k])
? atan((new_tanhlambda - tanhlambda[k][beta])/((1.0 - new_tanhlambda * tanhlambda[k][beta]) * chain.ta_n_anis_over_2[2]))
: - atan(((new_tanhlambda - tanhlambda[k][beta])/(1.0 - new_tanhlambda * tanhlambda[k][beta])) * chain.ta_n_anis_over_2[2]) ;
else sumtheta += 0.5 * Theta_XXZ((new_tanhlambda - tanhlambda[k][beta])/(1.0 - new_tanhlambda * tanhlambda[k][beta]),
chain.Str_L[j], chain.Str_L[k], chain.par[j], chain.par[k], chain.ta_n_anis_over_2);
}
sumtheta *= 2.0;
if (chain.par[j] == 1) arg = chain.ta_n_anis_over_2[chain.Str_L[j]] * tan(0.5 * (PI * Ix2[j][alpha] + sumtheta)/chain.Nsites);
else if (chain.par[j] == -1) arg = -tan(0.5 * (PI * Ix2[j][alpha] + sumtheta)/chain.Nsites)/chain.ta_n_anis_over_2[chain.Str_L[j]];
else JSCerror("Invalid parities in Iterate_BAE.");
}
if (fabs(arg) < 1.0) {
new_lambda = atanh(arg);
}
//else cout << "Rapidity blows up !\t" << lambda[j][alpha] << "\t" << new_lambda << endl;
} // else
return(new_lambda);
}
bool XXZ_Bethe_State::Check_Rapidities()
{
bool nonan = true;
for (int j = 0; j < chain.Nstrings; ++j)
for (int alpha = 0; alpha < base[j]; ++alpha) nonan *= !is_nan(lambda[j][alpha]);
return nonan;
}
DP XXZ_Bethe_State::String_delta ()
{
// Computes the sum of absolute value of \delta^{a, a+1} in string hypothesis, for a given bethe eigenstate
DP delta = 0.0;
int occupied_strings = 0;
for (int i = 0; i < (*this).chain.Nstrings; ++i) if ((*this).chain.Str_L[i] > 1) occupied_strings += (*this).base.Nrap[i];
//if ((*this).conv == 0) delta = 1.0;
if (occupied_strings == 0) delta = 0.0;
else {
Vect_DP ln_deltadiff(0.0, 1000); // contains ln |delta^{a, a+1}|
Vect_DP deltadiff(0.0, 1000); // contains |delta^{a, a+1}|
complex<DP> log_BAE_reg = 0.0;
for (int j = 0; j < (*this).chain.Nstrings; ++j) {
for (int alpha = 0; alpha < (*this).base[j]; ++alpha) {
ln_deltadiff = 0.0;
for (int a = 1; a <= (*this).chain.Str_L[j]; ++a) {
if ((*this).chain.Str_L[j] > 1) { // else the BAE are already 1
log_BAE_reg = DP((*this).chain.Nsites) * log(sinh((*this).lambda[j][alpha]
+ 0.5 * II * (*this).chain.anis * ((*this).chain.Str_L[j] + 1.0 - 2.0 * a + 1.0)
+ 0.25 * II * PI * (1.0 - (*this).chain.par[j]))
/sinh((*this).lambda[j][alpha] + 0.5 * II * (*this).chain.anis * ((*this).chain.Str_L[j] + 1.0 - 2.0 * a - 1.0)
+ 0.25 * II * PI * (1.0 - (*this).chain.par[j])));
for (int k = 0; k < (*this).chain.Nstrings; ++k)
for (int beta = 0; beta < (*this).base[k]; ++beta)
for (int b = 1; b <= (*this).chain.Str_L[k]; ++b) {
if ((j != k) || (alpha != beta) || (a != b - 1))
log_BAE_reg += log(sinh(((*this).lambda[j][alpha] + 0.5 * II * (*this).chain.anis * ((*this).chain.Str_L[j] + 1.0 - 2.0 * a )
+ 0.25 * II * PI * (1.0 - (*this).chain.par[j]))
- ((*this).lambda[k][beta] + 0.5 * II * (*this).chain.anis * ((*this).chain.Str_L[k] + 1.0 - 2.0 * b )
+ 0.25 * II * PI * (1.0 - (*this).chain.par[k])) - II * (*this).chain.anis));
if ((j != k) || (alpha != beta) || (a != b + 1))
log_BAE_reg -= log(sinh(((*this).lambda[j][alpha] + 0.5 * II * (*this).chain.anis * ((*this).chain.Str_L[j] + 1.0 - 2.0 * a )
+ 0.25 * II * PI * (1.0 - (*this).chain.par[j]))
- ((*this).lambda[k][beta] + 0.5 * II * (*this).chain.anis * ((*this).chain.Str_L[k] + 1.0 - 2.0 * b )
+ 0.25 * II * PI * (1.0 - (*this).chain.par[k])) + II * (*this).chain.anis));
}
// The regular LHS of BAE is now defined. Now sum up the deltas...
if (a == 1) ln_deltadiff[0] = - real(log_BAE_reg);
else if (a < (*this).chain.Str_L[j]) ln_deltadiff[a - 1] = ln_deltadiff[a-2] - real(log_BAE_reg);
else if (a == (*this).chain.Str_L[j]) ln_deltadiff[a-1] = real(log_BAE_reg);
} // if ((*this).chain.Str_L[j] > 1)
} // for (int a = 1; ...
for (int a = 0; a < (*this).chain.Str_L[j]; ++a) {
deltadiff[a] = ln_deltadiff[a] != 0.0 ? exp(ln_deltadiff[a]) : 0.0;
delta += fabs(deltadiff[a]);
}
} // alpha sum
} // j sum
if (is_nan(delta)) delta = 1.0; // sentinel
} // else
return delta;
}
void XXZ_Bethe_State::Compute_Energy ()
{
DP sum = 0.0;
for (int j = 0; j < chain.Nstrings; ++j) {
for (int alpha = 0; alpha < base[j]; ++alpha) {
sum += sin(chain.Str_L[j] * chain.anis) / (chain.par[j] * cosh(2.0 * lambda[j][alpha]) - cos(chain.Str_L[j] * chain.anis));
}
}
sum *= - chain.J * sin(chain.anis);
E = sum;
return;
}
/*
void XXZ_Bethe_State::Compute_Momentum ()
{
int sum_Ix2 = 0;
DP sum_M = 0.0;
for (int j = 0; j < chain.Nstrings; ++j) {
sum_M += 0.5 * (1.0 + chain.par[j]) * base[j];
for (int alpha = 0; alpha < base[j]; ++alpha) {
sum_Ix2 += Ix2[j][alpha];
}
}
iK = (chain.Nsites/2) * int(sum_M + 0.1) - (sum_Ix2/2); // + 0.1: for safety...
while (iK >= chain.Nsites) iK -= chain.Nsites;
while (iK < 0) iK += chain.Nsites;
K = PI * sum_M - PI * sum_Ix2/chain.Nsites;
while (K >= 2.0*PI) K -= 2.0*PI;
while (K < 0.0) K += 2.0*PI;
return;
}
*/
void XXZ_Bethe_State::Build_Reduced_Gaudin_Matrix (SQMat<complex<DP> >& Gaudin_Red)
{
if (Gaudin_Red.size() != base.Nraptot) JSCerror("Passing matrix of wrong size in Build_Reduced_Gaudin_Matrix.");
int index_jalpha;
int index_kbeta;
DP sum_hbar_XXZ = 0.0;
DP sinzetasq = pow(sin(chain.anis), 2.0);
(*this).Compute_sinhlambda();
(*this).Compute_coshlambda();
index_jalpha = 0;
for (int j = 0; j < chain.Nstrings; ++j) {
for (int alpha = 0; alpha < base[j]; ++alpha) {
index_kbeta = 0;
for (int k = 0; k < chain.Nstrings; ++k) {
for (int beta = 0; beta < base[k]; ++beta) {
if ((j == k) && (alpha == beta)) {
sum_hbar_XXZ = 0.0;
for (int kp = 0; kp < chain.Nstrings; ++kp) {
for (int betap = 0; betap < base[kp]; ++betap) {
if (!((j == kp) && (alpha == betap)))
sum_hbar_XXZ
+= ddlambda_Theta_XXZ (lambda[j][alpha] - lambda[kp][betap], chain.Str_L[j], chain.Str_L[kp], chain.par[j], chain.par[kp],
chain.si_n_anis_over_2);
}
}
Gaudin_Red[index_jalpha][index_kbeta]
= complex<DP> ( chain.Nsites * hbar_XXZ (lambda[j][alpha], chain.Str_L[j], chain.par[j], chain.si_n_anis_over_2) - sum_hbar_XXZ);
}
else {
if ((chain.Str_L[j] == 1) && (chain.Str_L[k] == 1))
Gaudin_Red[index_jalpha][index_kbeta] =
complex<DP> ((chain.par[j] * chain.par[k] == 1)
? chain.si_n_anis_over_2[4]/(pow(sinhlambda[j][alpha] * coshlambda[k][beta]
- coshlambda[j][alpha] * sinhlambda[k][beta], 2.0) + sinzetasq)
: chain.si_n_anis_over_2[4]/(-pow(coshlambda[j][alpha] * coshlambda[k][beta]
- sinhlambda[j][alpha] * sinhlambda[k][beta], 2.0) + sinzetasq) );
else
Gaudin_Red[index_jalpha][index_kbeta] = complex<DP> (ddlambda_Theta_XXZ (lambda[j][alpha] - lambda[k][beta], chain.Str_L[j], chain.Str_L[k],
chain.par[j], chain.par[k], chain.si_n_anis_over_2));
}
index_kbeta++;
}
}
index_jalpha++;
}
}
return;
}
// ****************************************************************************************************
// non-member functions
inline DP fbar_XXZ (DP tanhlambda, int par, DP tannzetaover2)
{
DP result = 0.0;
if (par == 1) result = 2.0 * atan(tanhlambda/tannzetaover2);
else if (par == -1) result = -2.0 * atan(tanhlambda * tannzetaover2);
else JSCerror("Faulty parity in fbar_XXZ.");
return (result);
}
DP Theta_XXZ (DP tanhlambda, int nj, int nk, int parj, int park, DP* tannzetaover2)
{
DP result = 0.0;
if ((nj == 1) && (nk == 1)) result = fbar_XXZ(tanhlambda, parj*park, tannzetaover2[2]);
else {
result = (nj == nk) ? 0.0 : fbar_XXZ(tanhlambda, parj*park, tannzetaover2[fabs(nj - nk)]);
for (int a = 1; a < JSC::min(nj, nk); ++a) result += 2.0 * fbar_XXZ(tanhlambda, parj*park, tannzetaover2[fabs(nj - nk) + 2*a]);
result += fbar_XXZ(tanhlambda, parj*park, tannzetaover2[nj + nk]);
}
return (result);
}
DP hbar_XXZ (DP lambda, int n, int par, DP* si_n_anis_over_2)
{
DP result = 0.0;
if (par == 1) result = si_n_anis_over_2[2*n]/(pow(sinh(lambda), 2.0) + pow(si_n_anis_over_2[n], 2.0));
else if (par == -1) result = si_n_anis_over_2[2*n]/(-pow(cosh(lambda), 2.0) + pow(si_n_anis_over_2[n], 2.0));
else JSCerror("Faulty parity in hbar_XXZ.");
return (result);
}
DP ddlambda_Theta_XXZ (DP lambda, int nj, int nk, int parj, int park, DP* si_n_anis_over_2)
{
DP result = (nj == nk) ? 0.0 : hbar_XXZ(lambda, fabs(nj - nk), parj*park, si_n_anis_over_2);
for (int a = 1; a < JSC::min(nj, nk); ++a) result += 2.0 * hbar_XXZ(lambda, fabs(nj - nk) + 2*a, parj*park, si_n_anis_over_2);
result += hbar_XXZ(lambda, nj + nk, parj*park, si_n_anis_over_2);
return (result);
}
XXZ_Bethe_State Add_Particle_at_Center (const XXZ_Bethe_State& RefState)
{
if (2*RefState.base.Mdown == RefState.chain.Nsites)
JSCerror("Trying to add a down spin to a zero-magnetized chain in Add_Particle_at_Center.");
Vect<int> newM = RefState.base.Nrap;
newM[0] = newM[0] + 1;
Heis_Base newBase (RefState.chain, newM);
XXZ_Bethe_State ReturnState (RefState.chain, newBase);
for (int il = 1; il < RefState.chain.Nstrings; ++il)
for (int alpha = 0; alpha < RefState.base.Nrap[il]; ++alpha)
ReturnState.Ix2[il][alpha] = RefState.Ix2[il][alpha];
// Add a quantum number in middle (explicitly: to right of index M[0]/2)
// and shift quantum numbers by half-integer away from added one:
ReturnState.Ix2[0][RefState.base.Nrap[0]/2] = RefState.Ix2[0][RefState.base.Nrap[0]/2] - 1;
for (int i = 0; i < RefState.base.Nrap[0] + 1; ++i)
ReturnState.Ix2[0][i + (i >= RefState.base.Nrap[0]/2)] = RefState.Ix2[0][i] - 1 + 2*(i >= RefState.base.Nrap[0]/2);
return(ReturnState);
}
XXZ_Bethe_State Remove_Particle_at_Center (const XXZ_Bethe_State& RefState)
{
if (RefState.base.Nrap[0] == 0)
JSCerror("Trying to remove a down spin in an empty Nrap[0] state.");
Vect<int> newM = RefState.base.Nrap;
newM[0] = newM[0] - 1;
Heis_Base newBase (RefState.chain, newM);
XXZ_Bethe_State ReturnState (RefState.chain, newBase);
for (int il = 1; il < RefState.chain.Nstrings; ++il)
for (int alpha = 0; alpha < RefState.base.Nrap[il]; ++alpha)
ReturnState.Ix2[il][alpha] = RefState.Ix2[il][alpha];
// Remove midmost and shift quantum numbers by half-integer towards removed one:
for (int i = 0; i < RefState.base.Nrap[0]-1; ++i)
ReturnState.Ix2[0][i] = RefState.Ix2[0][i + (i >= RefState.base.Nrap[0]/2)] + 1 - 2*(i >= RefState.base.Nrap[0]/2);
return(ReturnState);
}
} // namespace JSC
+814
View File
@@ -0,0 +1,814 @@
/**********************************************************
This software is part of J.-S. Caux's ABACUS++ library.
Copyright (c)
-----------------------------------------------------------
File: src/HEIS/XXZ_gpd_Bethe_State.cc
Purpose: Defines all functions for XXZ_gpd_Bethe_State
******************************************************************/
#include "JSC.h"
using namespace std;
namespace JSC {
// Function prototypes
inline DP fbar_XXZ_gpd (DP lambda, int par, DP tanhnetaover2);
DP Theta_XXZ_gpd (DP lambda, int nj, int nk, DP* tanhnetaover2);
DP hbar_XXZ_gpd (DP lambda, int n, DP* si_n_anis_over_2);
DP ddlambda_Theta_XXZ_gpd (DP lambda, int nj, int nk, DP* si_n_anis_over_2);
//***************************************************************************************************
// Function definitions: class XXZ_gpd_Bethe_State
XXZ_gpd_Bethe_State::XXZ_gpd_Bethe_State ()
: Heis_Bethe_State(), sinlambda(Lambda(chain, 1)), coslambda(Lambda(chain, 1)), tanlambda(Lambda(chain, 1))
{};
XXZ_gpd_Bethe_State::XXZ_gpd_Bethe_State (const XXZ_gpd_Bethe_State& RefState) // copy constructor
: Heis_Bethe_State(RefState),
sinlambda(Lambda(RefState.chain, RefState.base)), coslambda(Lambda(RefState.chain, RefState.base)),
tanlambda(Lambda(RefState.chain, RefState.base))
{
// copy arrays into new ones
for (int j = 0; j < RefState.chain.Nstrings; ++j) {
for (int alpha = 0; alpha < RefState.base[j]; ++j) {
sinlambda[j][alpha] = RefState.sinlambda[j][alpha];
coslambda[j][alpha] = RefState.coslambda[j][alpha];
tanlambda[j][alpha] = RefState.tanlambda[j][alpha];
}
}
}
XXZ_gpd_Bethe_State::XXZ_gpd_Bethe_State (const Heis_Chain& RefChain, int M)
: Heis_Bethe_State(RefChain, M),
sinlambda(Lambda(RefChain, M)), coslambda(Lambda(RefChain, M)), tanlambda(Lambda(RefChain, M))
{
if (RefChain.Delta <= 1.0) JSCerror("Delta too low in XXZ_gpd_Bethe_State constructor");
}
XXZ_gpd_Bethe_State::XXZ_gpd_Bethe_State (const Heis_Chain& RefChain, const Heis_Base& RefBase)
: Heis_Bethe_State(RefChain, RefBase),
sinlambda(Lambda(RefChain, RefBase)), coslambda(Lambda(RefChain, RefBase)),
tanlambda(Lambda(RefChain, RefBase))
{
if (RefChain.Delta <= 1.0) JSCerror("Delta too low in XXZ_gpd_Bethe_State constructor");
}
/*
XXZ_gpd_Bethe_State::XXZ_gpd_Bethe_State (const Heis_Chain& RefChain, long long int base_id_ref, long long int type_id_ref)
: Heis_Bethe_State(RefChain, base_id_ref, type_id_ref),
sinlambda(Lambda(chain, base)), coslambda(Lambda(chain, base)), tanlambda(Lambda(chain, base))
{
if (RefChain.Delta <= 1.0) JSCerror("Delta too low in XXZ_gpd_Bethe_State constructor");
}
*/
XXZ_gpd_Bethe_State& XXZ_gpd_Bethe_State::operator= (const XXZ_gpd_Bethe_State& RefState)
{
if (this != &RefState) {
chain = RefState.chain;
base = RefState.base;
//offsets = RefState.offsets;
Ix2 = RefState.Ix2;
lambda = RefState.lambda;
BE = RefState.BE;
diffsq = RefState.diffsq;
conv = RefState.conv;
iter = RefState.iter;
iter_Newton = RefState.iter_Newton;
E = RefState.E;
iK = RefState.iK;
K = RefState.K;
lnnorm = RefState.lnnorm;
//base_id = RefState.base_id;
//type_id = RefState.type_id;
//id = RefState.id;
//maxid = RefState.maxid;
//nparticles = RefState.nparticles;
label = RefState.label;
sinlambda = RefState.sinlambda;
coslambda = RefState.coslambda;
tanlambda = RefState.tanlambda;
}
return(*this);
}
// Member functions
void XXZ_gpd_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) {
lambda[i][alpha] = atan((tanh(chain.Str_L[i] * 0.5 * chain.anis) * tan(PI * 0.5 * Ix2[i][alpha]/chain.Nsites)));
}
}
return;
}
void XXZ_gpd_Bethe_State::Compute_sinlambda()
{
for (int j = 0; j < chain.Nstrings; ++j) {
for (int alpha = 0; alpha < base[j]; ++alpha) sinlambda[j][alpha] = sin(lambda[j][alpha]);
}
return;
}
void XXZ_gpd_Bethe_State::Compute_coslambda()
{
for (int j = 0; j < chain.Nstrings; ++j) {
for (int alpha = 0; alpha < base[j]; ++alpha) coslambda[j][alpha] = cos(lambda[j][alpha]);
}
return;
}
void XXZ_gpd_Bethe_State::Compute_tanlambda()
{
for (int j = 0; j < chain.Nstrings; ++j) {
for (int alpha = 0; alpha < base[j]; ++alpha) {
tanlambda[j][alpha] = tan(lambda[j][alpha]);
//if (lambda[j][alpha] > 0.5*PI) cout << "Rapidity higher than 0.5*PI: j = " << j << "\talpha = " << alpha << "\trap = " << lambda[j][alpha] << "\ttan = " << tanlambda[j][alpha] << endl;
}
}
return;
}
bool XXZ_gpd_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
/*
Vect<bool> min_Ix2_max_busy(false, chain.Nstrings);
Vect<bool> plus_Ix2_max_busy(false, chain.Nstrings);
for (int j = 0; j < chain.Nstrings; ++j)
for (int alpha = 0; alpha < base[j]; ++alpha) {
if (Ix2[j][alpha] == -base.Ix2_max[j]) min_Ix2_max_busy[j] = true;
if (Ix2[j][alpha] == base.Ix2_max[j]) plus_Ix2_max_busy[j] = true;
}
*/
/*
// State is not admissible if this is false: -N/2 + 1 \leq \sum I^j_{\alpha} \leq N
int sum_all_Ix2 = 0;
for (int j = 0; j < chain.Nstrings; ++j)
for (int alpha = 0; alpha < base[j]; ++alpha) {
sum_all_Ix2 += Ix2[j][alpha];
}
if (sum_all_Ix2 > chain.Nsites || sum_all_Ix2 <= -chain.Nsites) {
cout << "\tSum Ix2 out of fundamental interval: sum_all_Ix2 = " << sum_all_Ix2 << "\tfor N = " << chain.Nsites << endl;
return(false);
}
*/
//Deactivated 2014 06 11, put in Heis_Form_Factor_Entry.cc
/*
// State is not admissible if I_max > 1/2 (N - \sum_k t_{jk} M_k) or I_min < -1/2 (N - sum_k...) + 1 at any level:
int sum1 = 0;
for (int j = 0; j < chain.Nstrings; ++j) {
sum1 = 0;
for (int k = 0; k < chain.Nstrings; ++k) {
sum1 += base[k] * (2 * JSC::min(chain.Str_L[j], chain.Str_L[k]) - ((j == k) ? 1 : 0));
}
// Define limits...
//if (!((Nrap[j] + Ix2_max[j]) % 2)) Ix2_max[j] -= 1;
// This almost does it: only missing are the states with one on -PI/2 and one on PI/2
if (base[j] >= 1 && (Ix2[j][0] <= -(chain.Nsites - sum1) ||
(Ix2[j][base[j] - 1] - Ix2[j][0]) > 2*(chain.Nsites - sum1))) {
//cout << "\tAn Ix2 is out of interval at level " << j << endl;
//cout << Ix2[j][base[j] - 1] << "\t" << Ix2[j][0] << "\t" << chain.Nsites << "\t" << sum1 << endl;
return(false);
}
}
*/
/*
// State is not admissible if both a min_ and plus_Ix2_max are busy simultaneously:
bool is_a_min_Ix2_max_busy = false;
for (int j = 0; j < chain.Nstrings; ++j) if (min_Ix2_max_busy[j]) is_a_min_Ix2_max_busy = true;
bool is_a_plus_Ix2_max_busy = false;
for (int j = 0; j < chain.Nstrings; ++j) if (plus_Ix2_max_busy[j]) is_a_plus_Ix2_max_busy = true;
*/
/*
// State is not admissible if all min_Ix2_max are busy simultaneously:
bool any_min_Ix2_max_free = false;
for (int j = 0; j < chain.Nstrings; ++j)
if (base[j] > 0 && !min_Ix2_max_busy[j]) any_min_Ix2_max_free = true;
if (!any_min_Ix2_max_free) return(false);
*/
/*
// State is not admissible if -Ix2_max, -Ix2_max + 2, ..., -Ix2_max + 2*(Str_L - 1) are busy:
for (int j = 0; j < chain.Nstrings; ++j)
if (base[j] > 0 && Ix2[j][0] <= -base.Ix2_max[j] + 2*(chain.Str_L[j] - 1))
return(false);
// Almost correct with above !
// State is not admissible if Ix2_max - 2, ..., Ix2_max - 2*(Str_L - 2) are busy (NB: one slot more than on left):
for (int j = 0; j < chain.Nstrings; ++j)
if (base[j] > 0 && Ix2[j][base[j] - 1] >= base.Ix2_max[j] - 2*(chain.Str_L[j] - 2))
return(false);
*/
// Check that at all at least doubly occupied levels, the difference between max and min quantum numbers
// is strictly smaller than 2*Ix2_max - 2, so that lambda_max - lambda_min < PI at each level:
//for (int j = 0; j < chain.Nstrings; ++j)
//if (base[j] >= 2 && Ix2[j][base[j] - 1] - Ix2[j][0] >= 2* base.Ix2_max[j] - 2) answer = false;
//if (is_a_min_Ix2_max_busy && is_a_plus_Ix2_max_busy) return(false);
bool higher_string_on_zero = false;
for (int j = 0; j < chain.Nstrings; ++j) {
// The following line puts answer to true if there is at least one higher string with zero Ix2
for (int alpha = 0; alpha < base[j]; ++alpha) if ((Ix2[j][alpha] == 0) && (chain.Str_L[j] > 2) /*&& !(chain.Str_L[j] % 2)*/)
higher_string_on_zero = true;
for (int alpha = 0; alpha < base[j]; ++alpha) if (Ix2[j][alpha] == 0) Zero_at_level[j] = true;
// NOTE: if base[j] == 0, Zero_at_level[j] remains false.
}
bool symmetric_state = (*this).Check_Symmetry();
bool string_coincidence = false;
// Checks that we have strings of equal length modulo 2 and same parity with Ix2 == 0, so equal rapidities, and inadmissibility
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.Str_L[j1] + chain.Str_L[j2])%2)))
string_coincidence = 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;
//}
//cout << min_Ix2_max_busy << "\t" << symmetric_state << "\t" << higher_string_on_zero << "\t" << string_coincidence << "\t" << onep_onem_on_zero << endl;
//answer = !((symmetric_state && (higher_string_on_zero || string_coincidence || onep_onem_on_zero)));
answer = !(symmetric_state && (higher_string_on_zero || string_coincidence));
// Explicitly exclude state with min_Ix2_max_busy && iK == 0
//Compute_Momentum();
//answer = !((min_Ix2_max_busy && iK == 0) || (symmetric_state && (higher_string_on_zero || string_coincidence || onep_onem_on_zero)));
// Now check that no Ix2 is equal to +N (since we take -N into account, and I + N == I by periodicity of exp)
for (int j = 0; j < chain.Nstrings; ++j)
for (int alpha = 0; alpha < base[j]; ++alpha) if ((Ix2[j][alpha] < -chain.Nsites) || (Ix2[j][alpha] >= chain.Nsites)) answer = false;
if (!answer) {
E = 0.0;
K = 0.0;
conv = 0;
iter = 0;
iter_Newton = 0;
lnnorm = -100.0;
}
return(answer); // answer == true: nothing wrong with this Ix2_config
}
void XXZ_gpd_Bethe_State::Compute_BE (int j, int alpha)
{
// Fills in the BE members with the value of the Bethe equations.
tanlambda[j][alpha] = tan(lambda[j][alpha]);
DP sumtheta = 0.0;
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 += atan ((tanlambda[j][alpha] - tanlambda[k][beta])/((1.0 + tanlambda[j][alpha] * tanlambda[k][beta])
* chain.ta_n_anis_over_2[2]))
+ PI * floor(0.5 + (lambda[j][alpha] - lambda[k][beta])/PI);
}
else sumtheta += 0.5 * Theta_XXZ_gpd((tanlambda[j][alpha] - tanlambda[k][beta])/(1.0 + tanlambda[j][alpha] * tanlambda[k][beta]),
chain.Str_L[j], chain.Str_L[k], chain.ta_n_anis_over_2)
+ PI * (2.0 * JSC::min(chain.Str_L[j], chain.Str_L[k]) - ((j == k) ? 1.0 : 0))
* floor(0.5 + (lambda[j][alpha] - lambda[k][beta])/PI);
}
sumtheta *= 2.0;
BE[j][alpha] = 2.0 * (atan(tanlambda[j][alpha]/chain.ta_n_anis_over_2[chain.Str_L[j]])
+ PI * floor(0.5 + lambda[j][alpha]/PI))
- (sumtheta + PI*Ix2[j][alpha])/chain.Nsites;
}
void XXZ_gpd_Bethe_State::Compute_BE ()
{
// Fills in the BE members with the value of the Bethe equations.
(*this).Compute_tanlambda();
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 += atan ((tanlambda[j][alpha] - tanlambda[k][beta])/((1.0 + tanlambda[j][alpha] * tanlambda[k][beta])
* chain.ta_n_anis_over_2[2]))
+ PI * floor(0.5 + (lambda[j][alpha] - lambda[k][beta])/PI);
}
else sumtheta += 0.5 * Theta_XXZ_gpd((tanlambda[j][alpha] - tanlambda[k][beta])/(1.0 + tanlambda[j][alpha] * tanlambda[k][beta]),
chain.Str_L[j], chain.Str_L[k], chain.ta_n_anis_over_2)
+ PI * (2.0 * JSC::min(chain.Str_L[j], chain.Str_L[k]) - ((j == k) ? 1.0 : 0))
* floor(0.5 + (lambda[j][alpha] - lambda[k][beta])/PI);
}
sumtheta *= 2.0;
BE[j][alpha] = 2.0 * (atan(tanlambda[j][alpha]/chain.ta_n_anis_over_2[chain.Str_L[j]])
+ PI * floor(0.5 + lambda[j][alpha]/PI))
- (sumtheta + PI*Ix2[j][alpha])/chain.Nsites;
}
}
DP XXZ_gpd_Bethe_State::Iterate_BAE (int j, int alpha)
{
// Returns a new iteration value for lambda[j][alpha] given tanlambda[][] and BE[][]
// Assumes that tanlambda[][] and BE[][] have been computed.
DP arg0 = 0.5 * (2.0 * (atan(tanlambda[j][alpha]/chain.ta_n_anis_over_2[chain.Str_L[j]])
+ PI * floor(0.5 + lambda[j][alpha]/PI)) - BE[j][alpha]);
DP arg = chain.ta_n_anis_over_2[chain.Str_L[j]] * tan(
arg0
//0.5 *
//(PI * Ix2[j][alpha] + sumtheta)/chain.Nsites
//(2.0 * (atan(tanlambda[j][alpha]/chain.ta_n_anis_over_2[chain.Str_L[j]])
// + PI * floor(0.5 + lambda[j][alpha]/PI)) - BE[j][alpha])
);
return(atan(arg)
//+ PI * floor(0.5 + arg0)
//0.5 * (Ix2[j][alpha] + sumtheta/PI)/(chain.Nsites)
+ PI * floor(0.5 + arg0/PI)
);
}
/*
void XXZ_gpd_Bethe_State::Iterate_BAE ()
{
// Recalculates the rapidities by iterating Bethe equations
Lambda New_lambda(chain, base);
DP sumtheta = 0.0;
DP arg = 0.0;
// First, compute the tan of rapidities:
(*this).Compute_tanlambda();
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 += atan((tanlambda[j][alpha] - tanlambda[k][beta])/((1.0 + tanlambda[j][alpha] * tanlambda[k][beta])
* chain.ta_n_anis_over_2[2]))
+ PI * floor(0.5 + (lambda[j][alpha] - lambda[k][beta])/PI);
else sumtheta += 0.5 * Theta_XXZ_gpd((tanlambda[j][alpha] - tanlambda[k][beta])/(1.0 + tanlambda[j][alpha] * tanlambda[k][beta]),
chain.Str_L[j], chain.Str_L[k], chain.ta_n_anis_over_2)
+ PI * (2.0 * JSC::min(chain.Str_L[j], chain.Str_L[k]) - ((j == k) ? 1.0 : 0))
* floor(0.5 + (lambda[j][alpha] - lambda[k][beta])/PI);
}
sumtheta *= 2.0;
arg = chain.ta_n_anis_over_2[chain.Str_L[j]] * tan((PI * 0.5 * Ix2[j][alpha] + 0.5 * sumtheta)/chain.Nsites);
New_lambda[j][alpha] = atan(arg) + PI * floor(0.5 + (0.5 * Ix2[j][alpha] + 0.5 * sumtheta/PI)/(chain.Nsites));
}
}
DP New_diffsq = 0.0;
for (int j = 0; j < chain.Nstrings; ++j) {
for (int alpha = 0; alpha < base[j]; ++alpha) {
//New_diffsq += pow(tan(New_lambda[j][alpha]) - tanlambda[j][alpha], 2.0);
New_diffsq += pow(New_lambda[j][alpha] - lambda[j][alpha], 2.0);
lambda[j][alpha] = 1.0 * New_lambda[j][alpha] + 0.0 * lambda[j][alpha];
}
}
diffsq = New_diffsq;
iter++;
return;
}
*/
/*
void XXZ_gpd_Bethe_State::Iterate_BAE_Newton ()
{
// does one step of a Newton method on the rapidities...
Vect_DP RHSBAE (0.0, base.Nraptot); // contains RHS of BAEs
Vect_CX dlambda (0.0, base.Nraptot); // contains delta lambda computed from Newton's method
SQMat_CX Gaudin (0.0, base.Nraptot);
Vect_INT indx (base.Nraptot);
DP sumtheta = 0.0;
DP arg = 0.0;
DP fn_arg = 0.0;
DP olddiffsq = diffsq;
// Compute the RHS of the BAEs:
int index = 0;
(*this).Compute_tanlambda();
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 += atan ((tanlambda[j][alpha] - tanlambda[k][beta])/((1.0 + tanlambda[j][alpha] * tanlambda[k][beta])
* chain.ta_n_anis_over_2[2]))
+ PI * floor(0.5 + (lambda[j][alpha] - lambda[k][beta])/PI);
}
else sumtheta += 0.5 * Theta_XXZ_gpd((tanlambda[j][alpha] - tanlambda[k][beta])/(1.0 + tanlambda[j][alpha] * tanlambda[k][beta]),
chain.Str_L[j], chain.Str_L[k], chain.ta_n_anis_over_2)
+ PI * (2.0 * JSC::min(chain.Str_L[j], chain.Str_L[k]) - ((j == k) ? 1.0 : 0))
* floor(0.5 + (lambda[j][alpha] - lambda[k][beta])/PI);
}
sumtheta *= 2.0;
RHSBAE[index] = chain.Nsites * 2.0 * (atan(tanlambda[j][alpha]/chain.ta_n_anis_over_2[chain.Str_L[j]])
+ PI * floor(0.5 + lambda[j][alpha]/PI))
// )
- sumtheta - PI*Ix2[j][alpha];
index++;
}
}
(*this).Build_Reduced_Gaudin_Matrix (Gaudin);
for (int i = 0; i < base.Nraptot; ++i) dlambda[i] = - RHSBAE[i];
DP d;
ludcmp_CX (Gaudin, indx, d);
lubksb_CX (Gaudin, indx, dlambda);
diffsq = 0.0;
// for (int i = 0; i < base.Nraptot; ++i) diffsq += norm(dlambda[i]);
int ctr = 0;
for (int j = 0; j < chain.Nstrings; ++j) {
for (int alpha = 0; alpha < base[j]; ++alpha) {
diffsq += norm(tan(lambda[j][alpha] + dlambda[ctr]) - tanlambda[j][alpha]);
// cout << "lambda = " << lambda[j][alpha] << "\tdlambda = " << dlambda[ctr] << endl;
ctr++;
}
}
// 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]));
}
index = 0;
for (int j = 0; j < chain.Nstrings; ++j) {
for (int alpha = 0; alpha < base[j]; ++alpha) {
lambda[j][alpha] += real(dlambda[index]);
index++;
}
}
iter_Newton++;
// cout << "iter_N = " << iter_Newton << "\t" << diffsq << endl;
return;
}
*/
bool XXZ_gpd_Bethe_State::Check_Rapidities()
{
bool nonan = true;
for (int j = 0; j < chain.Nstrings; ++j)
for (int alpha = 0; alpha < base[j]; ++alpha) if (nonan) nonan = ((!is_nan(lambda[j][alpha]))
//&& (lambda[j][alpha] > -0.5*PI*chain.Str_L[j])
//&& (lambda[j][alpha] <= 0.5*PI*chain.Str_L[j])
);
bool all_within_pi_interval = true;
DP min_lambda = 10.0;
DP max_lambda = -10.0;
for (int j = 0; j < chain.Nstrings; ++j)
for (int alpha = 0; alpha < base[j]; ++alpha) {
if (lambda[j][alpha] < min_lambda) min_lambda = lambda[j][alpha];
if (lambda[j][alpha] > max_lambda) max_lambda = lambda[j][alpha];
}
//all_within_pi_interval = (fabs(max_lambda - min_lambda) < PI - 0.0 * 1.0e-12);
// Use pi interval, but centered on 0:
all_within_pi_interval = max_lambda < 0.5* PI + 1.0e-8 && min_lambda > -0.5* PI - 1.0e-8;
//nonan *= all_within_pi_interval;
return nonan;
}
DP XXZ_gpd_Bethe_State::String_delta ()
{
// Computes the sum of absolute value of \delta^{a, a+1} in string hypothesis, for a given bethe eigenstate
DP delta = 0.0;
int occupied_strings = 0;
for (int i = 0; i < (*this).chain.Nstrings; ++i) if ((*this).chain.Str_L[i] > 1) occupied_strings += (*this).base.Nrap[i];
//if ((*this).conv == 0) delta = 1.0;
if (occupied_strings == 0) delta = 0.0;
else {
Vect_DP ln_deltadiff(0.0, 1000); // contains ln |delta^{a, a+1}|
Vect_DP deltadiff(0.0, 1000); // contains |delta^{a, a+1}|
complex<DP> log_BAE_reg = 0.0;
for (int j = 0; j < (*this).chain.Nstrings; ++j) {
for (int alpha = 0; alpha < (*this).base[j]; ++alpha) {
ln_deltadiff = 0.0;
for (int a = 1; a <= (*this).chain.Str_L[j]; ++a) {
if ((*this).chain.Str_L[j] > 1) { // else the BAE are already 1
log_BAE_reg = DP((*this).chain.Nsites) * log(sin((*this).lambda[j][alpha] + 0.5 * II * (*this).chain.anis
* ((*this).chain.Str_L[j] + 1.0 - 2.0 * a + 1.0))
/sin((*this).lambda[j][alpha] + 0.5 * II * (*this).chain.anis * ((*this).chain.Str_L[j] + 1.0 - 2.0 * a - 1.0)));
for (int k = 0; k < (*this).chain.Nstrings; ++k)
for (int beta = 0; beta < (*this).base[k]; ++beta)
for (int b = 1; b <= (*this).chain.Str_L[k]; ++b) {
if ((j != k) || (alpha != beta) || (a != b - 1))
log_BAE_reg += log(sin(((*this).lambda[j][alpha] + 0.5 * II * (*this).chain.anis * ((*this).chain.Str_L[j] + 1.0 - 2.0 * a ))
- ((*this).lambda[k][beta] + 0.5 * II * (*this).chain.anis * ((*this).chain.Str_L[k] + 1.0 - 2.0 * b ))
- II * (*this).chain.anis));
if ((j != k) || (alpha != beta) || (a != b + 1))
log_BAE_reg -= log(sin(((*this).lambda[j][alpha] + 0.5 * II * (*this).chain.anis * ((*this).chain.Str_L[j] + 1.0 - 2.0 * a ))
- ((*this).lambda[k][beta] + 0.5 * II * (*this).chain.anis * ((*this).chain.Str_L[k] + 1.0 - 2.0 * b ))
+ II * (*this).chain.anis));
}
// The regular LHS of BAE is now defined. Now sum up the deltas...
if (a == 1) ln_deltadiff[0] = -real(log_BAE_reg);
else if (a < (*this).chain.Str_L[j]) ln_deltadiff[a - 1] = ln_deltadiff[a-2] - real(log_BAE_reg);
else if (a == (*this).chain.Str_L[j]) ln_deltadiff[a-1] = real(log_BAE_reg);
} // if ((*this).chain.Str_L[j] > 1)
} // for (int a = 1; ...
for (int a = 0; a < (*this).chain.Str_L[j]; ++a) {
deltadiff[a] = ln_deltadiff[a] != 0.0 ? exp(ln_deltadiff[a]) : 0.0;
delta += fabs(deltadiff[a]);
}
} // alpha sum
} // j sum
if (is_nan(delta)) delta = 1.0; // sentinel
} // else
return delta;
}
void XXZ_gpd_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 += sinh(chain.Str_L[j] * chain.anis) / (cos(2.0 * lambda[j][alpha]) - cosh(chain.Str_L[j] * chain.anis));
}
}
sum *= chain.J * sinh(chain.anis);
E = sum;
return;
}
/*
void XXZ_gpd_Bethe_State::Compute_Momentum ()
{
int sum_Ix2 = 0;
DP sum_M = 0.0;
for (int j = 0; j < chain.Nstrings; ++j) {
sum_M += base[j];
for (int alpha = 0; alpha < base[j]; ++alpha) {
sum_Ix2 += Ix2[j][alpha];
}
}
iK = (chain.Nsites/2) * int(sum_M) - (sum_Ix2/2);
while (iK >= chain.Nsites) iK -= chain.Nsites;
while (iK < 0) iK += chain.Nsites;
K = PI * sum_M - PI * sum_Ix2/chain.Nsites;
while (K >= 2.0*PI) K -= 2.0*PI;
while (K < 0.0) K += 2.0*PI;
return;
}
*/
void XXZ_gpd_Bethe_State::Build_Reduced_Gaudin_Matrix (SQMat<complex<DP> >& Gaudin_Red)
{
if (Gaudin_Red.size() != base.Nraptot) JSCerror("Passing matrix of wrong size in Build_Reduced_Gaudin_Matrix.");
int index_jalpha;
int index_kbeta;
DP sum_hbar_XXZ = 0.0;
DP sinhetasq = pow(sinh(chain.anis), 2.0);
(*this).Compute_sinlambda();
(*this).Compute_coslambda();
index_jalpha = 0;
for (int j = 0; j < chain.Nstrings; ++j) {
for (int alpha = 0; alpha < base[j]; ++alpha) {
index_kbeta = 0;
for (int k = 0; k < chain.Nstrings; ++k) {
for (int beta = 0; beta < base[k]; ++beta) {
if ((j == k) && (alpha == beta)) {
sum_hbar_XXZ = 0.0;
for (int kp = 0; kp < chain.Nstrings; ++kp) {
for (int betap = 0; betap < base[kp]; ++betap) {
if (!((j == kp) && (alpha == betap)))
sum_hbar_XXZ
+= ddlambda_Theta_XXZ_gpd (lambda[j][alpha] - lambda[kp][betap], chain.Str_L[j], chain.Str_L[kp],
chain.si_n_anis_over_2);
}
}
Gaudin_Red[index_jalpha][index_kbeta]
= complex<DP> ( chain.Nsites * hbar_XXZ_gpd (lambda[j][alpha], chain.Str_L[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.si_n_anis_over_2[4]/(pow(sinlambda[j][alpha] * coslambda[k][beta]
- coslambda[j][alpha] * sinlambda[k][beta], 2.0) + sinhetasq));
else
Gaudin_Red[index_jalpha][index_kbeta] = complex<DP> (ddlambda_Theta_XXZ_gpd (lambda[j][alpha] - lambda[k][beta], chain.Str_L[j],
chain.Str_L[k], chain.si_n_anis_over_2));
}
index_kbeta++;
}
}
index_jalpha++;
}
}
return;
}
// ****************************************************************************************************
// non-member functions
inline DP fbar_XXZ_gpd (DP tanlambda, DP tanhnetaover2)
{
return (2.0 * atan(tanlambda/tanhnetaover2));
}
DP Theta_XXZ_gpd (DP tanlambda, int nj, int nk, DP* tanhnetaover2)
{
DP result;
if ((nj == 1) && (nk == 1)) result = fbar_XXZ_gpd(tanlambda, tanhnetaover2[2]);
else {
result = (nj == nk) ? 0.0 : fbar_XXZ_gpd(tanlambda, tanhnetaover2[fabs(nj - nk)]);
for (int a = 1; a < JSC::min(nj, nk); ++a) result += 2.0 * fbar_XXZ_gpd(tanlambda, tanhnetaover2[fabs(nj - nk) + 2*a]);
result += fbar_XXZ_gpd(tanlambda, tanhnetaover2[nj + nk]);
}
return (result);
}
DP hbar_XXZ_gpd (DP lambda, int n, DP* si_n_anis_over_2)
{
return (si_n_anis_over_2[2*n]/(pow(sin(lambda), 2.0) + pow(si_n_anis_over_2[n], 2.0)));
}
DP ddlambda_Theta_XXZ_gpd (DP lambda, int nj, int nk, DP* si_n_anis_over_2)
{
DP result = (nj == nk) ? 0.0 : hbar_XXZ_gpd(lambda, fabs(nj - nk), si_n_anis_over_2);
for (int a = 1; a < JSC::min(nj, nk); ++a) result += 2.0 * hbar_XXZ_gpd(lambda, fabs(nj - nk) + 2*a, si_n_anis_over_2);
result += hbar_XXZ_gpd(lambda, nj + nk, si_n_anis_over_2);
return (result);
}
XXZ_gpd_Bethe_State Add_Particle_at_Center (const XXZ_gpd_Bethe_State& RefState)
{
if (2*RefState.base.Mdown == RefState.chain.Nsites)
JSCerror("Trying to add a down spin to a zero-magnetized chain in Add_Particle_at_Center.");
Vect<int> newM = RefState.base.Nrap;
newM[0] = newM[0] + 1;
Heis_Base newBase (RefState.chain, newM);
XXZ_gpd_Bethe_State ReturnState (RefState.chain, newBase);
for (int il = 1; il < RefState.chain.Nstrings; ++il)
for (int alpha = 0; alpha < RefState.base.Nrap[il]; ++alpha)
ReturnState.Ix2[il][alpha] = RefState.Ix2[il][alpha];
// Add a quantum number in middle (explicitly: to right of index M[0]/2)
// and shift quantum numbers by half-integer away from added one:
ReturnState.Ix2[0][RefState.base.Nrap[0]/2] = RefState.Ix2[0][RefState.base.Nrap[0]/2] - 1;
for (int i = 0; i < RefState.base.Nrap[0] + 1; ++i)
ReturnState.Ix2[0][i + (i >= RefState.base.Nrap[0]/2)] = RefState.Ix2[0][i] - 1 + 2*(i >= RefState.base.Nrap[0]/2);
return(ReturnState);
}
XXZ_gpd_Bethe_State Remove_Particle_at_Center (const XXZ_gpd_Bethe_State& RefState)
{
if (RefState.base.Nrap[0] == 0)
JSCerror("Trying to remove a down spin in an empty Nrap[0] state.");
Vect<int> newM = RefState.base.Nrap;
newM[0] = newM[0] - 1;
Heis_Base newBase (RefState.chain, newM);
XXZ_gpd_Bethe_State ReturnState (RefState.chain, newBase);
for (int il = 1; il < RefState.chain.Nstrings; ++il)
for (int alpha = 0; alpha < RefState.base.Nrap[il]; ++alpha)
ReturnState.Ix2[il][alpha] = RefState.Ix2[il][alpha];
// Remove midmost and shift quantum numbers by half-integer towards removed one:
for (int i = 0; i < RefState.base.Nrap[0]-1; ++i)
ReturnState.Ix2[0][i] = RefState.Ix2[0][i + (i >= RefState.base.Nrap[0]/2)] + 1 - 2*(i >= RefState.base.Nrap[0]/2);
return(ReturnState);
}
} // namespace JSC
+253
View File
@@ -0,0 +1,253 @@
/**********************************************************
This software is part of J.-S. Caux's ABACUS++ library.
Copyright (c)
-----------------------------------------------------------
***********************************************************/
#include "JSC.h"
using namespace JSC;
namespace JSC {
inline complex<DP> ln_Fn_F (XXX_Bethe_State& B, int k, int beta, int b)
{
complex<DP> ans = 0.0;
for (int j = 0; j < B.chain.Nstrings; ++j) {
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)))
ans += log(B.lambda[j][alpha] - B.lambda[k][beta]
+ 0.5 * II * (B.chain.Str_L[j] - B.chain.Str_L[k] - 2.0 * (a - b)));
}
}
}
return(ans);
}
inline complex<DP> ln_Fn_G (XXX_Bethe_State& A, XXX_Bethe_State& B, int k, int beta, int b)
{
complex<DP> ans = 0.0;
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) {
ans += log(A.lambda[j][alpha] - B.lambda[k][beta]
+ 0.5 * II * (A.chain.Str_L[j] - B.chain.Str_L[k] - 2.0 * (a - b)));
}
}
}
return(ans);
}
inline complex<DP> Fn_K (XXX_Bethe_State& A, int j, int alpha, int a, XXX_Bethe_State& B, int k, int beta, int b)
{
return(1.0/((A.lambda[j][alpha] - B.lambda[k][beta]
+ 0.5 * II * (A.chain.Str_L[j] - B.chain.Str_L[k] - 2.0 * (a - b)))
* (A.lambda[j][alpha] - B.lambda[k][beta]
+ 0.5 * II * (A.chain.Str_L[j] - B.chain.Str_L[k] - 2.0 * (a - b - 1.0)) )));
}
inline complex<DP> Fn_L (XXX_Bethe_State& A, int j, int alpha, int a, XXX_Bethe_State& B, int k, int beta, int b)
{
return ((2.0 * (A.lambda[j][alpha] - B.lambda[k][beta]
+ 0.5 * II * (A.chain.Str_L[j] - B.chain.Str_L[k] - 2.0 * (a - b - 0.5))
))
* pow(Fn_K (A, j, alpha, a, B, k, beta, b), 2.0));
}
complex<DP> ln_Overlap (XXX_Bethe_State& A, XXX_Bethe_State& B)
{
// This function returns the overlap of states A and B.
// The A and B states can contain strings.
// IMPORTANT ASSUMPTIONS:
// - State B is an eigenstate of the model on which the overlap measure is defined
// Check that A and B are compatible: same Mdown
if (A.base.Mdown != B.base.Mdown) return(complex<DP>(-300.0)); // overlap vanishes
// Some convenient arrays
Lambda re_ln_Fn_F_B_0(B.chain, B.base);
Lambda im_ln_Fn_F_B_0(B.chain, B.base);
Lambda re_ln_Fn_G_0(B.chain, B.base);
Lambda im_ln_Fn_G_0(B.chain, B.base);
Lambda re_ln_Fn_G_2(B.chain, B.base);
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((A.lambda[i][alpha] + 0.5 * II * (A.chain.Str_L[i] + 1.0 - 2.0 * a - 1.0))));
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((B.lambda[i][alpha] + 0.5 * II * (B.chain.Str_L[i] + 1.0 - 2.0 * a - 1.0))) > 100.0 * MACHINE_EPS_SQ)
ln_prod2 += log(norm((B.lambda[i][alpha] + 0.5 * II * (B.chain.Str_L[i] + 1.0 - 2.0 * a - 1.0))));
*/
// 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));
}
}
// 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.zeta)));
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.zeta)));
// 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_lambda_sq_plus_1over2sq;
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_lambda_sq_plus_1over2sq = 2.0/((A.lambda[j][alpha] + 0.5 * II * (A.chain.Str_L[j] + 1.0 - 2.0 * a)) *
// (A.lambda[j][alpha] + 0.5 * II * (A.chain.Str_L[j] + 1.0 - 2.0 * a)) + 0.25);
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]);
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]);
//Prod_powerN = pow((B.lambda[k][beta] + 0.5 * II)/(B.lambda[k][beta] - 0.5 * II), complex<DP> (B.chain.Nsites));
Prod_powerN = pow((B.lambda[k][beta] + 0.5 * II)/(B.lambda[k][beta] - 0.5 * II), complex<DP> (A.chain.Nsites)); // careful !
Hm2P[index_a][index_b] = Fn_K_0_G_0 - Prod_powerN * Fn_K_1_G_2
//- two_over_A_lambda_sq_plus_1over2sq * exp(II*im_ln_Fn_F_B_0[k][beta]);
;
}
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 += 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]]);
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))); // include all string contributions F_B_0 in this term
//Hm2P[index_a][index_b] = prod_num * (sum1 - sum2 * two_over_A_lambda_sq_plus_1over2sq);
Hm2P[index_a][index_b] = prod_num * sum1;
} // else if (b == B.chain.Str_L[k])
} // else
index_b++;
}}} // sums over k, beta, b
index_a++;
}}} // sums over j, alpha, a
//cout << "Matrix: " << endl;
//Hm2P.Print();
complex<DP> det = lndet_LU_CX_dstry(Hm2P);
/*
complex<DP> ln_form_factor_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))
+ 2.0 * det
- A.lnnorm - B.lnnorm;
//cout << "ln_SZ: " << endl << ln_prod1 << "\t" << -ln_prod2 << "\t" << -ln_prod3 << "\t" << ln_prod4 << "\t" << 2.0 * det
// << "\t" << -A.lnnorm << "\t" << -B.lnnorm << endl;
return(ln_form_factor_sq);
*/
complex<DP> ln_overlap = 0.5 * (-ln_prod3 + ln_prod4) + det - 0.5 * (A.lnnorm + B.lnnorm);
cout << "ln_overlap: " << endl << -ln_prod3 << "\t" << ln_prod4 << "\t" << 2.0 * det
<< "\t" << -A.lnnorm << "\t" << -B.lnnorm << endl;
return(ln_overlap);
}
} // namespace JSC
+239
View File
@@ -0,0 +1,239 @@
#include "JSC.h"
using namespace JSC;
namespace JSC {
inline complex<DP> ln_Fn_F (XXX_Bethe_State& B, int k, int beta, int b)
{
complex<DP> ans = 0.0;
for (int j = 0; j < B.chain.Nstrings; ++j) {
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)))
ans += log(B.lambda[j][alpha] - B.lambda[k][beta]
+ 0.5 * II * (B.chain.Str_L[j] - B.chain.Str_L[k] - 2.0 * (a - b)));
}
}
}
return(ans);
}
inline complex<DP> ln_Fn_G (XXX_Bethe_State& A, XXX_Bethe_State& B, int k, int beta, int b)
{
complex<DP> ans = 0.0;
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) {
ans += log(A.lambda[j][alpha] - B.lambda[k][beta]
+ 0.5 * II * (A.chain.Str_L[j] - B.chain.Str_L[k] - 2.0 * (a - b)));
}
}
}
return(ans);
}
inline complex<DP> Fn_K (XXX_Bethe_State& A, int j, int alpha, int a, XXX_Bethe_State& B, int k, int beta, int b)
{
return(1.0/((A.lambda[j][alpha] - B.lambda[k][beta]
+ 0.5 * II * (A.chain.Str_L[j] - B.chain.Str_L[k] - 2.0 * (a - b)))
* (A.lambda[j][alpha] - B.lambda[k][beta]
+ 0.5 * II * (A.chain.Str_L[j] - B.chain.Str_L[k] - 2.0 * (a - b - 1.0)) )));
}
inline complex<DP> Fn_L (XXX_Bethe_State& A, int j, int alpha, int a, XXX_Bethe_State& B, int k, int beta, int b)
{
return ((2.0 * (A.lambda[j][alpha] - B.lambda[k][beta]
+ 0.5 * II * (A.chain.Str_L[j] - B.chain.Str_L[k] - 2.0 * (a - b - 0.5))
))
* pow(Fn_K (A, j, alpha, a, B, k, beta, b), 2.0));
}
complex<DP> ln_Smin_ME (XXX_Bethe_State& A, XXX_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) JSCerror("Incompatible XXX_Chains in Smin matrix element.");
// Check that A and B are Mdown-compatible:
if (A.base.Mdown != B.base.Mdown + 1) JSCerror("Incompatible Mdown between the two states in Smin matrix element!");
// Some convenient arrays
Lambda re_ln_Fn_F_B_0(B.chain, B.base);
Lambda im_ln_Fn_F_B_0(B.chain, B.base);
Lambda re_ln_Fn_G_0(B.chain, B.base);
Lambda im_ln_Fn_G_0(B.chain, B.base);
Lambda re_ln_Fn_G_2(B.chain, B.base);
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(A.lambda[i][alpha] + 0.5 * II * (A.chain.Str_L[i] + 1.0 - 2.0 * a - 1.0)));
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(B.lambda[i][alpha] + 0.5 * II * (B.chain.Str_L[i] + 1.0 - 2.0 * a - 1.0)) > 100.0 * MACHINE_EPS_SQ)
ln_prod2 += log(norm(B.lambda[i][alpha] + 0.5 * II * (B.chain.Str_L[i] + 1.0 - 2.0 * a - 1.0)));
// Define the F ones earlier...
complex<DP> ln_FB0, ln_FG0, ln_FG2;
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));
ln_FB0 = ln_Fn_F(B, j, alpha, 0);
re_ln_Fn_F_B_0[j][alpha] = real(ln_FB0);
im_ln_Fn_F_B_0[j][alpha] = imag(ln_FB0);
//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));
ln_FG0 = ln_Fn_G(A, B, j, alpha, 0);
re_ln_Fn_G_0[j][alpha] = real(ln_FG0);
im_ln_Fn_G_0[j][alpha] = imag(ln_FG0);
//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_FG2 = ln_Fn_G(A, B, j, alpha, 2);
re_ln_Fn_G_2[j][alpha] = real(ln_FG2);
im_ln_Fn_G_2[j][alpha] = imag(ln_FG2);
}
}
// 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.zeta)));
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.zeta)));
// 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_lambda_sq_plus_1over2sq;
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_lambda_sq_plus_1over2sq = 1.0/((A.lambda[j][alpha] + 0.5 * II * (A.chain.Str_L[j] + 1.0 - 2.0 * a)) *
(A.lambda[j][alpha] + 0.5 * II * (A.chain.Str_L[j] + 1.0 - 2.0 * a)) + 0.25);
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]);
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]);
Prod_powerN = pow((B.lambda[k][beta] + II * 0.5) /(B.lambda[k][beta] - II * 0.5), complex<DP> (B.chain.Nsites));
Hm[index_a][index_b] = Fn_K_0_G_0 - 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 += 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]]);
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)));
// 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_lambda_sq_plus_1over2sq;
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)) - A.lnnorm - B.lnnorm;
//return(ln_ME_sq);
return(0.5 * ln_ME_sq); // Return ME, not MEsq
}
} // namespace JSC
+328
View File
@@ -0,0 +1,328 @@
#include "JSC.h"
using namespace JSC;
namespace JSC {
inline complex<DP> ln_Fn_F (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 *= 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])) );
*/
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 (XXZ_Bethe_State& A, 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 (XXZ_Bethe_State& A, int j, int alpha, int a, 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 (XXZ_Bethe_State& A, int j, int alpha, int a, 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 (XXZ_Bethe_State& A, 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) JSCerror("Incompatible XXZ_Chains in Smin matrix element.");
// Check that A and B are Mdown-compatible:
if (A.base.Mdown != B.base.Mdown + 1) {
cout << "A.base.Mdown = " << A.base.Mdown << "\tB.base.Mdown = " << B.base.Mdown << endl;
cout << "A: " << A << endl << "B: " << B << endl;
JSCerror("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
Lambda re_ln_Fn_F_B_0(B.chain, B.base);
Lambda im_ln_Fn_F_B_0(B.chain, B.base);
Lambda re_ln_Fn_G_0(B.chain, B.base);
Lambda im_ln_Fn_G_0(B.chain, B.base);
Lambda re_ln_Fn_G_2(B.chain, B.base);
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 - 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 += 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_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(ln_ME_sq);
return(0.5 * ln_ME_sq); // Return ME, not MEsq
}
} // namespace JSC
+303
View File
@@ -0,0 +1,303 @@
#include "JSC.h"
using namespace JSC;
namespace JSC {
inline complex<DP> ln_Fn_F (XXZ_gpd_Bethe_State& B, int k, int beta, int b)
{
complex<DP> ans = 0.0;
complex<DP> prod_temp = 1.0;
int counter = 0;
for (int j = 0; j < B.chain.Nstrings; ++j) {
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)))
ans += log(-II * sin(B.lambda[j][alpha] - B.lambda[k][beta]
+ 0.5 * II * B.chain.eta * (B.chain.Str_L[j] - B.chain.Str_L[k] - 2.0 * (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 *= -II * (B.sinlambda[j][alpha] * B.coslambda[k][beta] - B.coslambda[j][alpha] * B.sinlambda[k][beta])
* cosh(0.5 * B.chain.anis * (B.chain.Str_L[j] - B.chain.Str_L[k] - 2.0 * (a - b))) +
(B.coslambda[j][alpha] * B.coslambda[k][beta] + B.sinlambda[j][alpha] * B.sinlambda[k][beta])
* sinh(0.5 * B.chain.anis * (B.chain.Str_L[j] - B.chain.Str_L[k] - 2.0 * (a - b)));
}
if (counter++ > 10) { // we do at most 10 products before taking a log
ans += log(prod_temp);
prod_temp = 1.0;
counter = 0;
}
}}}
// return(ans);
return(ans + log(prod_temp));
}
inline complex<DP> ln_Fn_G (XXZ_gpd_Bethe_State& A, XXZ_gpd_Bethe_State& B, int k, int beta, int b)
{
complex<DP> ans = 0.0;
complex<DP> prod_temp = 1.0;
int counter = 0;
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) {
/*
prod_temp *= -II * sin(A.lambda[j][alpha] - B.lambda[k][beta]
+ 0.5 * II * B.chain.eta * (A.chain.Str_L[j] - B.chain.Str_L[k] - 2.0 * (a - b)));
*/
// arg = A.chain.Str_L[j] - B.chain.Str_L[k] - 2 * (a - b);
// absarg = abs(arg);
prod_temp *= -II * (A.sinlambda[j][alpha] * B.coslambda[k][beta] - A.coslambda[j][alpha] * B.sinlambda[k][beta])
* cosh(0.5 * B.chain.anis * (A.chain.Str_L[j] - B.chain.Str_L[k] - 2.0 * (a - b))) +
(A.coslambda[j][alpha] * B.coslambda[k][beta] + A.sinlambda[j][alpha] * B.sinlambda[k][beta])
* sinh(0.5 * B.chain.anis * (A.chain.Str_L[j] - B.chain.Str_L[k] - 2.0 * (a - b)));
if (counter++ > 25) { // we do at most 25 products before taking a log
ans += log(prod_temp);
prod_temp = 1.0;
counter = 0;
}
}}}
// return(ans);
return(ans + log(prod_temp));
}
inline complex<DP> Fn_K (XXZ_gpd_Bethe_State& A, int j, int alpha, int a, XXZ_gpd_Bethe_State& B, int k, int beta, int b)
{
/*
return(-1.0/(sin(A.lambda[j][alpha] - B.lambda[k][beta]
+ 0.5 * II * B.chain.zeta * (A.chain.Str_L[j] - B.chain.Str_L[k] - 2.0 * (a - b)))
* sin(A.lambda[j][alpha] - B.lambda[k][beta]
+ 0.5 * II * B.chain.zeta * (A.chain.Str_L[j] - B.chain.Str_L[k] - 2.0 * (a - b - 1.0)))));
*/
// int arg1 = A.chain.Str_L[j] - B.chain.Str_L[k] - 2 * (a - b);
// int absarg1 = abs(arg1);
// int arg2 = A.chain.Str_L[j] - B.chain.Str_L[k] - 2 * (a - b - 1);
// int arg2 = arg1 + 2;
// int absarg2 = abs(arg2);
return(1.0/(( -II * (A.sinlambda[j][alpha] * B.coslambda[k][beta] - A.coslambda[j][alpha] * B.sinlambda[k][beta])
* cosh(0.5 * B.chain.anis * (A.chain.Str_L[j] - B.chain.Str_L[k] - 2.0 * (a - b))) +
(A.coslambda[j][alpha] * B.coslambda[k][beta] + A.sinlambda[j][alpha] * B.sinlambda[k][beta])
* sinh(0.5 * B.chain.anis * (A.chain.Str_L[j] - B.chain.Str_L[k] - 2.0 * (a - b)))) *
(-II * (A.sinlambda[j][alpha] * B.coslambda[k][beta] - A.coslambda[j][alpha] * B.sinlambda[k][beta])
* cosh(0.5 * B.chain.anis * (A.chain.Str_L[j] - B.chain.Str_L[k] - 2.0 * (a - b - 1.0))) +
(A.coslambda[j][alpha] * B.coslambda[k][beta] + A.sinlambda[j][alpha] * B.sinlambda[k][beta])
* sinh(0.5 * B.chain.anis * (A.chain.Str_L[j] - B.chain.Str_L[k] - 2.0 * (a - b - 1.0))))));
}
inline complex<DP> Fn_L (XXZ_gpd_Bethe_State& A, int j, int alpha, int a, XXZ_gpd_Bethe_State& B, int k, int beta, int b)
{
/*
complex<DP> ans = -II * sin(2.0 * (A.lambda[j][alpha] - B.lambda[k][beta]
+ 0.5 * II * B.chain.zeta * (A.chain.Str_L[j] - B.chain.Str_L[k] - 2.0 * (a - b - 0.5))));
return (ans * pow(Fn_K (A, j, alpha, a, B, k, beta, b), 2.0));
*/
return (-II * sin(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))))
* pow(Fn_K (A, j, alpha, a, B, k, beta, b), 2.0));
}
complex<DP> ln_Smin_ME (XXZ_gpd_Bethe_State& A, XXZ_gpd_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 refer to the same XXZ_gpd_Chain
if (A.chain != B.chain) JSCerror("Incompatible XXZ_gpd_Chains in Smin matrix element.");
// Check that A and B are compatible: same Mdown
if (A.base.Mdown != B.base.Mdown + 1) JSCerror("Incompatible Mdown between the two states in Smin matrix element!");
// Compute the sin and cos of rapidities
A.Compute_sinlambda();
A.Compute_coslambda();
B.Compute_sinlambda();
B.Compute_coslambda();
// Some convenient arrays
Lambda re_ln_Fn_F_B_0(B.chain, B.base);
Lambda im_ln_Fn_F_B_0(B.chain, B.base);
Lambda re_ln_Fn_G_0(B.chain, B.base);
Lambda im_ln_Fn_G_0(B.chain, B.base);
Lambda re_ln_Fn_G_2(B.chain, B.base);
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(sin(A.lambda[i][alpha] + 0.5 * II * A.chain.anis * (A.chain.Str_L[i] + 1.0 - 2.0 * a - 1.0))));
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(sin(B.lambda[i][alpha] + 0.5 * II * B.chain.anis * (B.chain.Str_L[i] + 1.0 - 2.0 * a - 1.0))) > 100.0 * MACHINE_EPS_SQ)
ln_prod2 += log(norm(sin(B.lambda[i][alpha] + 0.5 * II * B.chain.anis * (B.chain.Str_L[i] + 1.0 - 2.0 * a - 1.0))));
// one_over_A_sinlambda_sq_plus_sinhetaover2sq[j][alpha] = 1.0/(pow(A.sinlambda[j][alpha], 2.0) + pow(sinh(0.5*A.chain.anis), 2.0));
// 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 logabssinheta = log(abs(sinh(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(sinh(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(sinh(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_sinlambda_sq_plus_sinhetaover2sq = 0.0;
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_sinlambda_sq_plus_sinhetaover2sq = -1.0/((sin(A.lambda[j][alpha] // minus sign: from 1/(sinh^2... to -1/(sin^2...
+ 0.5 * II * A.chain.anis * (A.chain.Str_L[j] + 1.0 - 2.0 * a))) *
(sin(A.lambda[j][alpha] // minus sign: from 1/(sinh^2... to -1/(sin^2...
+ 0.5 * II * A.chain.anis * (A.chain.Str_L[j] + 1.0 - 2.0 * a)))
+ pow(sinh(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] + logabssinheta);
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] + logabssinheta);
Prod_powerN = pow((B.sinlambda[k][beta] * B.chain.co_n_anis_over_2[1] + II * B.coslambda[k][beta] * B.chain.si_n_anis_over_2[1])
/(B.sinlambda[k][beta] * B.chain.co_n_anis_over_2[1] - II * B.coslambda[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 - Prod_powerN * Fn_K_1_G_2;
}
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 += 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]] + logabssinheta);
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)) + logabssinheta);
// 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_sinlambda_sq_plus_sinhetaover2sq;
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)) + logabssinheta - A.lnnorm - B.lnnorm;
//return(ln_ME_sq);
return(0.5 * ln_ME_sq); // Return ME, not MEsq
}
} // namespace JSC
+307
View File
@@ -0,0 +1,307 @@
#include "JSC.h"
using namespace JSC;
namespace JSC {
inline complex<DP> phi(complex<DP> x){return x;}
inline complex<DP> a(complex<DP> x){return 1;}
inline complex<DP> b(complex<DP> x,complex<DP> y, complex<DP> eta){ return phi(x-y)/phi(x-y+complex<DP>(0.0,1.0)*eta);}
inline complex<DP> d(complex<DP> x, complex<DP> xi, complex<DP> eta, int N){return pow(b(x,xi,eta),N);}
inline complex<DP> ln_Fn_F (XXX_Bethe_State& B, int k, int beta, int b)
{
complex<DP> ans = 0.0;
for (int j = 0; j < B.chain.Nstrings; ++j) {
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)))
ans += log(B.lambda[j][alpha] - B.lambda[k][beta]
+ 0.5 * II * (B.chain.Str_L[j] - B.chain.Str_L[k] - 2.0 * (a - b)));
}
}
}
return(ans);
}
inline complex<DP> ln_Fn_G (XXX_Bethe_State& A, XXX_Bethe_State& B, int k, int beta, int b)
{
complex<DP> ans = 0.0;
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) {
ans += log(A.lambda[j][alpha] - B.lambda[k][beta]
+ 0.5 * II * (A.chain.Str_L[j] - B.chain.Str_L[k] - 2.0 * (a - b)));
}
}
}
return(ans);
}
inline complex<DP> Fn_K (XXX_Bethe_State& A, int j, int alpha, int a, XXX_Bethe_State& B, int k, int beta, int b)
{
return(1.0/((A.lambda[j][alpha] - B.lambda[k][beta]
+ 0.5 * II * (A.chain.Str_L[j] - B.chain.Str_L[k] - 2.0 * (a - b)))
* (A.lambda[j][alpha] - B.lambda[k][beta]
+ 0.5 * II * (A.chain.Str_L[j] - B.chain.Str_L[k] - 2.0 * (a - b - 1.0)) )));
}
inline complex<DP> Fn_L (XXX_Bethe_State& A, int j, int alpha, int a, XXX_Bethe_State& B, int k, int beta, int b)
{
return ((2.0 * (A.lambda[j][alpha] - B.lambda[k][beta]
+ 0.5 * II * (A.chain.Str_L[j] - B.chain.Str_L[k] - 2.0 * (a - b - 0.5))
))
* pow(Fn_K (A, j, alpha, a, B, k, beta, b), 2.0));
}
complex<DP> ln_Smm_ME (XXX_Bethe_State& A, XXX_Bethe_State& B)
{
const DP Zero_Center_Thres=1.0e-5;
const DP real_dev=1.0e-14;
const DP Diff_ME_Thres=1.e-6;
//clock_t start_time_local = clock();
// This function returns the natural log of the S^z operator matrix element.
// The A and B states can contain strings.
// A is the reference state.
// Check that the two states refer to the same XXX_Chain
if (A.chain != B.chain) JSCerror("Incompatible XXX_Chains in Smm matrix element.");
// Check that A and B are compatible: same Mdown
if (A.base.Mdown != B.base.Mdown + 2) JSCerror("Incompatible Mdown between the two states in Smm matrix element!");
//if(B.String_delta()> HEIS_deltaprec) return(complex<DP>(-300.0)); // DEPRECATED in ++T_9
//if (B.type_id > 999999LL) return(complex<DP>(-300.0));
// Some convenient arrays
complex<DP> eta=-II;
complex<DP> ln_prod = complex<DP>(0.0,0.0);
complex<DP> result=-300;
complex<DP> prev_result=-300;
XXX_Bethe_State B_origin; B_origin=B;
bool zero_string=false;
for (int j = 0; j < B_origin.chain.Nstrings; ++j)
for (int alpha = 0; alpha < B_origin.base.Nrap[j]; ++alpha)
if(abs(B_origin.lambda[j][alpha])<Zero_Center_Thres) zero_string=true;
// Some convenient arrays
bool real_dev_conv=false;
int dev=-1;
while(!real_dev_conv){
real_dev_conv=true;
dev++;
//add a delta to the origin of the centered strings
if(zero_string){
real_dev_conv=false;
for (int j = 0; j < B.chain.Nstrings; ++j)
for (int alpha = 0; alpha < B.base.Nrap[j]; ++alpha)
if(abs(B_origin.lambda[j][alpha])<Zero_Center_Thres)
B.lambda[j][alpha]=real_dev*pow(10.0,dev);
}
prev_result=result;
result=log(B.chain.Nsites*1.0);
int sizeA=0;
int sizeB=0;
for (int i = 0; i < A.chain.Nstrings; ++i)
sizeA+=A.base.Nrap[i]*A.chain.Str_L[i];
for (int i = 0; i < B.chain.Nstrings; ++i)
sizeB+=B.base.Nrap[i]*B.chain.Str_L[i];
complex<DP>* mu = new complex<DP>[sizeA];
complex<DP>* lam = new complex<DP>[sizeB];
int index=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)
{
mu[index]=(A.lambda[i][alpha] + 0.5 * -eta * (A.chain.Str_L[i] + 1.0 - 2.0 * a));
index++;
}
index=0;
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)
{
lam[index]=(B.lambda[i][alpha] + 0.5 * -eta * (B.chain.Str_L[i] + 1.0 - 2.0 * a));
index++;
}
Lambda re_ln_Fn_F_B_0(B.chain, B.base);
Lambda im_ln_Fn_F_B_0(B.chain, B.base);
Lambda re_ln_Fn_G_0(B.chain, B.base);
Lambda im_ln_Fn_G_0(B.chain, B.base);
Lambda re_ln_Fn_G_2(B.chain, B.base);
Lambda im_ln_Fn_G_2(B.chain, B.base);
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));
}
}
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(A.lambda[i][alpha] + 0.5 * II * (A.chain.Str_L[i] + 1.0 - 2.0 * a - 1.0)));
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(B.lambda[i][alpha] + 0.5 * II * (B.chain.Str_L[i] + 1.0 - 2.0 * a - 1.0)) > 100.0 * MACHINE_EPS_SQ)
ln_prod2 += log(norm(B.lambda[i][alpha] + 0.5 * II * (B.chain.Str_L[i] + 1.0 - 2.0 * a - 1.0)));
// 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);
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);
}
result += 2.0*real(ln_prod1 - ln_prod2) - real(ln_prod3) + real(ln_prod4) - A.lnnorm - B.lnnorm;
// Define the F ones earlier...
int index_a = 0;
int index_b = 0;
complex<DP> Prod_powerN;
//mu is the ground state!
//A -> mu, B -> lam
SQMat_CX H(0.0, A.base.Mdown);
index_a = 0;
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;
complex<DP> Da;
complex<DP> Ca;
Da=eta/((mu[index_a]-eta*0.5)*(mu[index_a]+eta*0.5));
Ca=eta*((mu[index_a]-eta*0.5)+(mu[index_a]+eta*0.5))/pow(((mu[index_a]-eta*0.5)*(mu[index_a]+eta*0.5)),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) {
complex<DP> prodplus= complex<DP>(1.0,0.0);
complex<DP> prodminus= complex<DP>(1.0,0.0);
// use simplified code for one-string here: original form of Hm2P matrix
prodplus = Fn_K (A, j, alpha, a, B, k, beta, 0);// 1.0/ (phi(mu[l]-lam[k]) phi(mu[l]-lam[k]+eta) )
prodplus*= exp(re_ln_Fn_G_0[k][beta] + II * im_ln_Fn_G_0[k][beta] - re_ln_Fn_F_B_0[k][beta]);//Prod phi(mu[l]-lam[k]+eta) / prod_l!=k |phi(lam[l]-lam[k]) |;
prodminus = Fn_K (A, j, alpha, a, B, k, beta, 1);// 1.0/ (phi(mu[l]-lam[k]) phi(mu[l]-lam[k]-eta) )
prodminus*= exp(re_ln_Fn_G_2[k][beta] + II * im_ln_Fn_G_2[k][beta] - re_ln_Fn_F_B_0[k][beta]);//Prod phi(mu[l]-lam[k]-eta)/ prod_l!=k | phi(lam[l]-lam[k]) |;
Prod_powerN = pow((B.lambda[k][beta] - eta*0.5) /(B.lambda[k][beta] + eta*0.5), complex<DP> (B.chain.Nsites));
H[index_a][index_b] =eta*(prodplus-prodminus*Prod_powerN);
} // if (B.chain.Str_L == 1)
else {
// */{
if (b > 1){
H[index_a][index_b] = eta* Fn_K(A, j, alpha, a, B, k, beta, b-1)*exp(ln_Fn_G(A,B,k,beta,b-1))*exp(-real(ln_Fn_F(B, k, beta, b - 1)));//.../ prod_l!=k | phi(lam[l]-lam[k]) |
}
else if (b == 1) {
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);
complex<DP> sum1 = complex<DP>(0.0,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]);//sum term when i=0
sum1 += 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]); //sum term when i=n
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]);
}
H[index_a][index_b] = eta * exp(ln_FunctionF[0]+ ln_FunctionF[1] - ln_FunctionG[1]) * sum1 * exp( - real(ln_Fn_F(B, k, beta, b - 1))); //the absolute value prod_l!=k phi(lam[l]-lam[k]) : real(ln_...)
} // else if (b == B.chain.Str_L[k])
} // else
index_b++;
}}} // sums over k, beta, b
// now define the elements H[a][M] & H[a][M-1]
H[index_a][B.base.Mdown]=Da;
H[index_a][B.base.Mdown+1]=Ca;
index_a++;
}}} // sums over j, alpha, a
complex<DP> logF=lndet_LU_CX_dstry(H);
result+=2.0*real(logF);
result+=log(2.0)-log((A.chain.Nsites-A.base.Mdown*2+3.0)*((A.chain.Nsites-A.base.Mdown*2+4.0)));
if (!(real_dev_conv) && abs(exp(result)-exp(prev_result))<abs( Diff_ME_Thres*exp(result)))
real_dev_conv=true;
if (!(real_dev_conv) && dev >20){
result=-300;
real_dev_conv=true;
}
delete[] mu;
delete[] lam;
}
//return(result);
return(0.5 * result); // Return ME, not MEsq
}
} // namespace JSC
+247
View File
@@ -0,0 +1,247 @@
/**********************************************************
This software is part of J.-S. Caux's ABACUS++ library.
Copyright (c)
-----------------------------------------------------------
***********************************************************/
#include "JSC.h"
using namespace JSC;
namespace JSC {
inline complex<DP> ln_Fn_F (XXX_Bethe_State& B, int k, int beta, int b)
{
complex<DP> ans = 0.0;
for (int j = 0; j < B.chain.Nstrings; ++j) {
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)))
ans += log(B.lambda[j][alpha] - B.lambda[k][beta]
+ 0.5 * II * (B.chain.Str_L[j] - B.chain.Str_L[k] - 2.0 * (a - b)));
}
}
}
return(ans);
}
inline complex<DP> ln_Fn_G (XXX_Bethe_State& A, XXX_Bethe_State& B, int k, int beta, int b)
{
complex<DP> ans = 0.0;
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) {
ans += log(A.lambda[j][alpha] - B.lambda[k][beta]
+ 0.5 * II * (A.chain.Str_L[j] - B.chain.Str_L[k] - 2.0 * (a - b)));
}
}
}
return(ans);
}
inline complex<DP> Fn_K (XXX_Bethe_State& A, int j, int alpha, int a, XXX_Bethe_State& B, int k, int beta, int b)
{
return(1.0/((A.lambda[j][alpha] - B.lambda[k][beta]
+ 0.5 * II * (A.chain.Str_L[j] - B.chain.Str_L[k] - 2.0 * (a - b)))
* (A.lambda[j][alpha] - B.lambda[k][beta]
+ 0.5 * II * (A.chain.Str_L[j] - B.chain.Str_L[k] - 2.0 * (a - b - 1.0)) )));
}
inline complex<DP> Fn_L (XXX_Bethe_State& A, int j, int alpha, int a, XXX_Bethe_State& B, int k, int beta, int b)
{
return ((2.0 * (A.lambda[j][alpha] - B.lambda[k][beta]
+ 0.5 * II * (A.chain.Str_L[j] - B.chain.Str_L[k] - 2.0 * (a - b - 0.5))
))
* pow(Fn_K (A, j, alpha, a, B, k, beta, b), 2.0));
}
complex<DP> ln_Sz_ME (XXX_Bethe_State& A, XXX_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 XXX_Chain
if (A.chain != B.chain) JSCerror("Incompatible XXX_Chains in Sz matrix element.");
// Check that A and B are compatible: same Mdown
if (A.base.Mdown != B.base.Mdown) JSCerror("Incompatible Mdown between the two states in Sz matrix element!");
//if (A.iK == B.iK && (A.label != B.label))
if (A.iK == B.iK && (A.label.compare(B.label) != 0))
return(-300.0); // matrix element identically vanishes
// Some convenient arrays
Lambda re_ln_Fn_F_B_0(B.chain, B.base);
Lambda im_ln_Fn_F_B_0(B.chain, B.base);
Lambda re_ln_Fn_G_0(B.chain, B.base);
Lambda im_ln_Fn_G_0(B.chain, B.base);
Lambda re_ln_Fn_G_2(B.chain, B.base);
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((A.lambda[i][alpha] + 0.5 * II * (A.chain.Str_L[i] + 1.0 - 2.0 * a - 1.0))));
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((B.lambda[i][alpha] + 0.5 * II * (B.chain.Str_L[i] + 1.0 - 2.0 * a - 1.0))) > 100.0 * MACHINE_EPS_SQ)
ln_prod2 += log(norm((B.lambda[i][alpha] + 0.5 * II * (B.chain.Str_L[i] + 1.0 - 2.0 * a - 1.0))));
// 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));
}
}
// 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.zeta)));
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.zeta)));
// 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_lambda_sq_plus_1over2sq;
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_lambda_sq_plus_1over2sq = 2.0/((A.lambda[j][alpha] + 0.5 * II * (A.chain.Str_L[j] + 1.0 - 2.0 * a)) *
(A.lambda[j][alpha] + 0.5 * II * (A.chain.Str_L[j] + 1.0 - 2.0 * a)) + 0.25);
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]);
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]);
Prod_powerN = pow((B.lambda[k][beta] + 0.5 * II)/(B.lambda[k][beta] - 0.5 * II), complex<DP> (B.chain.Nsites));
Hm2P[index_a][index_b] = Fn_K_0_G_0 - Prod_powerN * Fn_K_1_G_2
- two_over_A_lambda_sq_plus_1over2sq * exp(II*im_ln_Fn_F_B_0[k][beta]);
}
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 += 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]]);
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))); // include all string contributions F_B_0 in this term
Hm2P[index_a][index_b] = prod_num * (sum1 - sum2 * two_over_A_lambda_sq_plus_1over2sq);
} // else if (b == B.chain.Str_L[k])
} // else
index_b++;
}}} // sums over k, beta, b
index_a++;
}}} // sums over j, alpha, a
//cout << "Matrix: " << endl;
//Hm2P.Print();
DP 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))
+ 2.0 * det
- A.lnnorm - B.lnnorm;
//cout << "ln_Sz: " << endl << ln_prod1 << "\t" << -ln_prod2 << "\t" << -ln_prod3 << "\t" << ln_prod4 << "\t" << 2.0 * det
// << "\t" << -A.lnnorm << "\t" << -B.lnnorm << endl;
//return(ln_ME_sq);
return(0.5 * ln_ME_sq); // Return ME, not MEsq
}
} // namespace JSC
+563
View File
@@ -0,0 +1,563 @@
#include "JSC.h"
using namespace JSC;
namespace JSC {
inline complex<DP> ln_Fn_F (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 *= 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));
}
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 (XXZ_Bethe_State& A, 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 (XXZ_Bethe_State& A, int j, int alpha, int a, 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 (XXZ_Bethe_State& A, int j, int alpha, int a, 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));
}
// Version without phases:
complex<DP> ln_Sz_ME (XXZ_Bethe_State& A, 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) {
JSCerror("Incompatible XXZ_Chains in Sz matrix element.");
}
// Check that A and B are compatible: same Mdown
if (A.base.Mdown != B.base.Mdown) {
cout << "Bra state: " << endl << A << endl;
cout << "Ket state: " << endl << B << endl;
cout << A.base.Mdown << "\t" << B.base.Mdown << endl;
JSCerror("Incompatible Mdown between the two states in Sz matrix element!");
}
if (A.iK == B.iK && (A.label != B.label))
return(-300.0); // matrix element identically vanishes
// Compute the sinh and cosh of rapidities
A.Compute_sinhlambda();
A.Compute_coshlambda();
B.Compute_sinhlambda();
B.Compute_coshlambda();
// Some convenient arrays
Lambda re_ln_Fn_F_B_0(B.chain, B.base);
Lambda im_ln_Fn_F_B_0(B.chain, B.base);
Lambda re_ln_Fn_G_0(B.chain, B.base);
Lambda im_ln_Fn_G_0(B.chain, B.base);
Lambda re_ln_Fn_G_2(B.chain, B.base);
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...
complex<DP> ln_Fn_F_B_0;
for (int j = 0; j < B.chain.Nstrings; ++j) {
for (int alpha = 0; alpha < B.base.Nrap[j]; ++alpha) {
ln_Fn_F_B_0 = ln_Fn_F(B, j, alpha, 0);
//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_F_B_0[j][alpha] = real(ln_Fn_F_B_0);
im_ln_Fn_F_B_0[j][alpha] = imag(ln_Fn_F_B_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));
//cout << "Prod_powerN = " << Prod_powerN << "\t" << abs(Prod_powerN) << endl;
Hm2P[index_a][index_b] = Fn_K_0_G_0 - 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 += 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 * /*real(lndet_LU_CX_dstry(Hm2P))*/ 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(ln_ME_sq);
return(0.5 * ln_ME_sq); // Return ME, not MEsq
}
// Version with phases:
complex<DP> ln_Sz_ME_with_phase (XXZ_Bethe_State& A, 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) JSCerror("Incompatible XXZ_Chains in Sz matrix element.");
// Check that A and B are compatible: same Mdown
if (A.base.Mdown != B.base.Mdown) {
cout << "Bra state: " << endl << A << endl;
cout << "Ket state: " << endl << B << endl;
cout << A.base.Mdown << "\t" << B.base.Mdown << endl;
JSCerror("Incompatible Mdown between the two states in Sz matrix element!");
}
if (A.iK == B.iK && (A.label != B.label))
return(-300.0); // matrix element identically vanishes
// Compute the sinh and cosh of rapidities
A.Compute_sinhlambda();
A.Compute_coshlambda();
B.Compute_sinhlambda();
B.Compute_coshlambda();
// Some convenient arrays
Lambda re_ln_Fn_F_B_0(B.chain, B.base);
Lambda im_ln_Fn_F_B_0(B.chain, B.base);
Lambda re_ln_Fn_G_0(B.chain, B.base);
Lambda im_ln_Fn_G_0(B.chain, B.base);
Lambda re_ln_Fn_G_2(B.chain, B.base);
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(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])));
complex<DP> shB;
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(shB = 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]))));
ln_prod2 += log(shB);
// Define the F ones earlier...
complex<DP> ln_Fn_F_B_0, ln_Fn_G_0, ln_Fn_G_2;
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));
ln_Fn_F_B_0 = ln_Fn_F(B, j, alpha, 0);
re_ln_Fn_F_B_0[j][alpha] = real(ln_Fn_F_B_0);
im_ln_Fn_F_B_0[j][alpha] = imag(ln_Fn_F_B_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));
ln_Fn_G_0 = ln_Fn_G(A, B, j, alpha, 0);
re_ln_Fn_G_0[j][alpha] = real(ln_Fn_G_0);
im_ln_Fn_G_0[j][alpha] = imag(ln_Fn_G_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_Fn_G_0 = ln_Fn_G(A, B, j, alpha, 2);
re_ln_Fn_G_2[j][alpha] = real(ln_Fn_G_2);
im_ln_Fn_G_2[j][alpha] = imag(ln_Fn_G_2);
}
}
DP logsinzeta = log(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)));
ln_prod3 -= A.base.Mdown * logsinzeta;
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)));
ln_prod4 -= B.base.Mdown * logsinzeta;
// 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] + logsinzeta);
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] + logsinzeta);
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));
//cout << "Prod_powerN = " << Prod_powerN << "\t" << abs(Prod_powerN) << endl;
Hm2P[index_a][index_b] = Fn_K_0_G_0 - Prod_powerN * Fn_K_1_G_2 - two_over_A_sinhlambda_sq_plus_sinzetaover2sq
* exp(II*im_ln_Fn_F_B_0[k][beta] + logsinzeta);
}
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 += 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]] + logsinzeta);
for (int jsum = 2; jsum <= B.chain.Str_L[k]; ++jsum)
prod_num *= exp(ln_FunctionG[jsum] - real(ln_FunctionF[jsum - 1]) + logsinzeta);
// 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
complex<DP> ln_det = lndet_LU_CX_dstry(Hm2P);
complex<DP> ln_ME = log(0.5 * sqrt(A.chain.Nsites)) + ln_prod1 - ln_prod2 - ln_prod3 + ln_prod4 + 2.0 * 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_form_factor_sq << endl;
//return(ln_ME_sq);
return(ln_ME); // Return ME, not MEsq
}
} // namespace JSC
+304
View File
@@ -0,0 +1,304 @@
#include "JSC.h"
using namespace JSC;
namespace JSC {
inline complex<DP> ln_Fn_F (XXZ_gpd_Bethe_State& B, int k, int beta, int b)
{
complex<DP> ans = 0.0;
complex<DP> prod_temp = 1.0;
int counter = 0;
for (int j = 0; j < B.chain.Nstrings; ++j) {
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)))
ans += log(-II * sin(B.lambda[j][alpha] - B.lambda[k][beta]
+ 0.5 * II * B.chain.eta * (B.chain.Str_L[j] - B.chain.Str_L[k] - 2.0 * (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 *= -II * (B.sinlambda[j][alpha] * B.coslambda[k][beta] - B.coslambda[j][alpha] * B.sinlambda[k][beta])
* cosh(0.5 * B.chain.anis * (B.chain.Str_L[j] - B.chain.Str_L[k] - 2.0 * (a - b))) +
(B.coslambda[j][alpha] * B.coslambda[k][beta] + B.sinlambda[j][alpha] * B.sinlambda[k][beta])
* sinh(0.5 * B.chain.anis * (B.chain.Str_L[j] - B.chain.Str_L[k] - 2.0 * (a - b)));
}
if (counter++ > 10) { // we do at most 10 products before taking a log
ans += log(prod_temp);
prod_temp = 1.0;
counter = 0;
}
}}}
// return(ans);
return(ans + log(prod_temp));
}
inline complex<DP> ln_Fn_G (XXZ_gpd_Bethe_State& A, XXZ_gpd_Bethe_State& B, int k, int beta, int b)
{
complex<DP> ans = 0.0;
complex<DP> prod_temp = 1.0;
int counter = 0;
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) {
/*
prod_temp *= -II * sin(A.lambda[j][alpha] - B.lambda[k][beta]
+ 0.5 * II * B.chain.eta * (A.chain.Str_L[j] - B.chain.Str_L[k] - 2.0 * (a - b)));
*/
// arg = A.chain.Str_L[j] - B.chain.Str_L[k] - 2 * (a - b);
// absarg = abs(arg);
prod_temp *= -II * (A.sinlambda[j][alpha] * B.coslambda[k][beta] - A.coslambda[j][alpha] * B.sinlambda[k][beta])
* cosh(0.5 * B.chain.anis * (A.chain.Str_L[j] - B.chain.Str_L[k] - 2.0 * (a - b))) +
(A.coslambda[j][alpha] * B.coslambda[k][beta] + A.sinlambda[j][alpha] * B.sinlambda[k][beta])
* sinh(0.5 * B.chain.anis * (A.chain.Str_L[j] - B.chain.Str_L[k] - 2.0 * (a - b)));
if (counter++ > 25) { // we do at most 25 products before taking a log
ans += log(prod_temp);
prod_temp = 1.0;
counter = 0;
}
}}}
// return(ans);
return(ans + log(prod_temp));
}
inline complex<DP> Fn_K (XXZ_gpd_Bethe_State& A, int j, int alpha, int a, XXZ_gpd_Bethe_State& B, int k, int beta, int b)
{
/*
return(-1.0/(sin(A.lambda[j][alpha] - B.lambda[k][beta]
+ 0.5 * II * B.chain.zeta * (A.chain.Str_L[j] - B.chain.Str_L[k] - 2.0 * (a - b)))
* sin(A.lambda[j][alpha] - B.lambda[k][beta]
+ 0.5 * II * B.chain.zeta * (A.chain.Str_L[j] - B.chain.Str_L[k] - 2.0 * (a - b - 1.0)))));
*/
// int arg1 = A.chain.Str_L[j] - B.chain.Str_L[k] - 2 * (a - b);
// int absarg1 = abs(arg1);
// int arg2 = A.chain.Str_L[j] - B.chain.Str_L[k] - 2 * (a - b - 1);
// int arg2 = arg1 + 2;
// int absarg2 = abs(arg2);
return(1.0/(( -II * (A.sinlambda[j][alpha] * B.coslambda[k][beta] - A.coslambda[j][alpha] * B.sinlambda[k][beta])
* cosh(0.5 * B.chain.anis * (A.chain.Str_L[j] - B.chain.Str_L[k] - 2.0 * (a - b))) +
(A.coslambda[j][alpha] * B.coslambda[k][beta] + A.sinlambda[j][alpha] * B.sinlambda[k][beta])
* sinh(0.5 * B.chain.anis * (A.chain.Str_L[j] - B.chain.Str_L[k] - 2.0 * (a - b)))) *
(-II * (A.sinlambda[j][alpha] * B.coslambda[k][beta] - A.coslambda[j][alpha] * B.sinlambda[k][beta])
* cosh(0.5 * B.chain.anis * (A.chain.Str_L[j] - B.chain.Str_L[k] - 2.0 * (a - b - 1.0))) +
(A.coslambda[j][alpha] * B.coslambda[k][beta] + A.sinlambda[j][alpha] * B.sinlambda[k][beta])
* sinh(0.5 * B.chain.anis * (A.chain.Str_L[j] - B.chain.Str_L[k] - 2.0 * (a - b - 1.0))))));
}
inline complex<DP> Fn_L (XXZ_gpd_Bethe_State& A, int j, int alpha, int a, XXZ_gpd_Bethe_State& B, int k, int beta, int b)
{
/*
complex<DP> ans = -II * sin(2.0 * (A.lambda[j][alpha] - B.lambda[k][beta]
+ 0.5 * II * B.chain.zeta * (A.chain.Str_L[j] - B.chain.Str_L[k] - 2.0 * (a - b - 0.5))));
return (ans * pow(Fn_K (A, j, alpha, a, B, k, beta, b), 2.0));
*/
return (-II * sin(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))))
* pow(Fn_K (A, j, alpha, a, B, k, beta, b), 2.0));
}
complex<DP> ln_Sz_ME (XXZ_gpd_Bethe_State& A, XXZ_gpd_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_gpd_Chain
if (A.chain != B.chain) JSCerror("Incompatible XXZ_gpd_Chains in Sz matrix element.");
// Check that A and B are compatible: same Mdown
if (A.base.Mdown != B.base.Mdown) JSCerror("Incompatible Mdown between the two states in Sz matrix element!");
if (A.iK == B.iK && (A.label != B.label))
return(-300.0); // matrix element identically vanishes
// Compute the sin and cos of rapidities
A.Compute_sinlambda();
A.Compute_coslambda();
B.Compute_sinlambda();
B.Compute_coslambda();
// Some convenient arrays
Lambda re_ln_Fn_F_B_0(B.chain, B.base);
Lambda im_ln_Fn_F_B_0(B.chain, B.base);
Lambda re_ln_Fn_G_0(B.chain, B.base);
Lambda im_ln_Fn_G_0(B.chain, B.base);
Lambda re_ln_Fn_G_2(B.chain, B.base);
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(sin(A.lambda[i][alpha] + 0.5 * II * A.chain.anis * (A.chain.Str_L[i] + 1.0 - 2.0 * a - 1.0))));
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(sin(B.lambda[i][alpha] + 0.5 * II * B.chain.anis * (B.chain.Str_L[i] + 1.0 - 2.0 * a - 1.0))) > 100.0 * MACHINE_EPS_SQ)
ln_prod2 += log(norm(sin(B.lambda[i][alpha] + 0.5 * II * B.chain.anis * (B.chain.Str_L[i] + 1.0 - 2.0 * a - 1.0))));
// 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 logabssinheta = log(abs(sinh(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(sinh(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(sinh(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_sinlambda_sq_plus_sinhetaover2sq = 0.0;
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_sinlambda_sq_plus_sinhetaover2sq = -2.0/((sin(A.lambda[j][alpha] // minus sign: from 1/(sinh^2... to -1/(sin^2...
+ 0.5 * II * A.chain.anis * (A.chain.Str_L[j] + 1.0 - 2.0 * a))) *
(sin(A.lambda[j][alpha] // minus sign: from 1/(sinh^2... to -1/(sin^2...
+ 0.5 * II * A.chain.anis * (A.chain.Str_L[j] + 1.0 - 2.0 * a)))
+ pow(sinh(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] + logabssinheta);
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] + logabssinheta);
Prod_powerN = pow((B.sinlambda[k][beta] * B.chain.co_n_anis_over_2[1] + II * B.coslambda[k][beta] * B.chain.si_n_anis_over_2[1])
/(B.sinlambda[k][beta] * B.chain.co_n_anis_over_2[1] - II * B.coslambda[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 - Prod_powerN * Fn_K_1_G_2
- two_over_A_sinlambda_sq_plus_sinhetaover2sq * exp(II*im_ln_Fn_F_B_0[k][beta] + logabssinheta);
}
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 += 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]] + logabssinheta);
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)) + logabssinheta);
// include all string contributions F_B_0 in this term
Hm2P[index_a][index_b] = prod_num * (sum1 - sum2 * two_over_A_sinlambda_sq_plus_sinhetaover2sq);
} // else if (b == B.chain.Str_L[k])
} // else
index_b++;
}}} // sums over k, beta, b
index_a++;
}}} // sums over j, alpha, a
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)) - A.lnnorm - B.lnnorm;
//cout << endl << ln_prod1 << "\t" << ln_prod2 << "\t" << ln_prod3 << "\t" << ln_prod4 << "\t" << A.lnnorm << "\t" << B.lnnorm << "\t"
// << lndet_LU_CX(Hm2P) << endl;
//return(ln_ME_sq);
return(0.5 * ln_ME_sq); // Return ME, not MEsq
}
} // namespace JSC
+502
View File
@@ -0,0 +1,502 @@
#include "JSC.h"
using namespace JSC;
namespace JSC {
inline complex<DP> phi(complex<DP> x){return x;}
inline complex<DP> a(complex<DP> x){return 1;}
inline complex<DP> b(complex<DP> x,complex<DP> y, complex<DP> eta){ return phi(x-y)/phi(x-y+complex<DP>(0.0,1.0)*eta);}
inline complex<DP> d(complex<DP> x, complex<DP> xi, complex<DP> eta, int N){return pow(b(x,xi,eta),N);}
inline complex<DP> ln_Fn_F (XXX_Bethe_State& B, int k, int beta, int b)
{
complex<DP> ans = 0.0;
for (int j = 0; j < B.chain.Nstrings; ++j) {
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)))
ans += log(B.lambda[j][alpha] - B.lambda[k][beta]
+ 0.5 * II * (B.chain.Str_L[j] - B.chain.Str_L[k] - 2.0 * (a - b)));
}
}
}
return(ans);
}
inline complex<DP> ln_Fn_G (XXX_Bethe_State& A, XXX_Bethe_State& B, int k, int beta, int b)
{
complex<DP> ans = 0.0;
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) {
ans += log(A.lambda[j][alpha] - B.lambda[k][beta]
+ 0.5 * II * (A.chain.Str_L[j] - B.chain.Str_L[k] - 2.0 * (a - b)));
}
}
}
return(ans);
}
inline complex<DP> Fn_K (XXX_Bethe_State& A, int j, int alpha, int a, XXX_Bethe_State& B, int k, int beta, int b)
{
return(1.0/((A.lambda[j][alpha] - B.lambda[k][beta]
+ 0.5 * II * (A.chain.Str_L[j] - B.chain.Str_L[k] - 2.0 * (a - b)))
* (A.lambda[j][alpha] - B.lambda[k][beta]
+ 0.5 * II * (A.chain.Str_L[j] - B.chain.Str_L[k] - 2.0 * (a - b - 1.0)) )));
}
inline complex<DP> Fn_L (XXX_Bethe_State& A, int j, int alpha, int a, XXX_Bethe_State& B, int k, int beta, int b)
{
return ((2.0 * (A.lambda[j][alpha] - B.lambda[k][beta]
+ 0.5 * II * (A.chain.Str_L[j] - B.chain.Str_L[k] - 2.0 * (a - b - 0.5))
))
* pow(Fn_K (A, j, alpha, a, B, k, beta, b), 2.0));
}
complex<DP> ln_Szm_p_Smz_ME (XXX_Bethe_State& A, XXX_Bethe_State& B)
{
//clock_t start_time_local = clock();
//A has to be the ground state!
// 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 XXX_Chain
if (A.chain != B.chain) JSCerror("Incompatible XXX_Chains in Szm_p_Smz matrix element.");
// Check that A and B are compatible: same Mdown
if (A.base.Mdown != B.base.Mdown + 1) JSCerror("Incompatible Mdown between the two states in SzSm_p_SmSz matrix element!");
//if (B.type_id > 999999LL) return(complex<DP>(-300.0));
//add a delta to the origin of the centered strings
for (int i = 0; i < A.chain.Nstrings; ++i)
for (int alpha = 0; alpha < A.base.Nrap[i]; ++alpha)
if(abs(A.lambda[i][alpha])<5.55112e-12)A.lambda[i][alpha]=5.55112e-12;
for (int i = 0; i < B.chain.Nstrings; ++i)
for (int alpha = 0; alpha < B.base.Nrap[i]; ++alpha)
if(abs(B.lambda[i][alpha])<5.55112e-5)B.lambda[i][alpha]=5.55112e-5;
// Some convenient arrays
complex<DP> i=complex<DP>(0.0,1.0);
complex<DP> eta=-i;
complex<DP> ln_prod = complex<DP>(0.0,0.0);
complex<DP> result;
result=log(B.chain.Nsites*1.0/4.0);
int sizeA=0;
int sizeB=0;
for (int i = 0; i < A.chain.Nstrings; ++i)
sizeA+=A.base.Nrap[i]*A.chain.Str_L[i];
for (int i = 0; i < B.chain.Nstrings; ++i)
sizeB+=B.base.Nrap[i]*B.chain.Str_L[i];
complex<DP>* mu = new complex<DP>[sizeA];
complex<DP>* lam = new complex<DP>[sizeB];
int index=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)
{
// mu[index]=(A.lambda[i][alpha] + 0.5 * II * (A.chain.Str_L[i] + 1.0 - 2.0 * a));
mu[index]=(A.lambda[i][alpha] + 0.5 * -eta * (A.chain.Str_L[i] + 1.0 - 2.0 * a));
index++;
}
index=0;
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)
{
// lam[index]=(B.lambda[i][alpha] + 0.5 * II * (B.chain.Str_L[i] + 1.0 - 2.0 * a));
lam[index]=(B.lambda[i][alpha] + 0.5 * -eta * (B.chain.Str_L[i] + 1.0 - 2.0 * a));
index++;
}
Lambda re_ln_Fn_F_B_0(B.chain, B.base);
Lambda im_ln_Fn_F_B_0(B.chain, B.base);
Lambda re_ln_Fn_G_0(B.chain, B.base);
Lambda im_ln_Fn_G_0(B.chain, B.base);
Lambda re_ln_Fn_G_2(B.chain, B.base);
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(A.lambda[i][alpha] + 0.5 * II * (A.chain.Str_L[i] + 1.0 - 2.0 * a - 1.0)));
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(B.lambda[i][alpha] + 0.5 * II * (B.chain.Str_L[i] + 1.0 - 2.0 * a - 1.0)) > 100.0 * MACHINE_EPS_SQ)
ln_prod2 += log(norm(B.lambda[i][alpha] + 0.5 * II * (B.chain.Str_L[i] + 1.0 - 2.0 * a - 1.0)));
// 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));
}
}
// 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_prod+=log(abs(phi((A.lambda[i][alpha] + 0.5 * II * (A.chain.Str_L[i] + 1.0 - 2.0 * a))+eta*0.5)))
// 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)
// ln_prod+=-log(abs(phi(-(B.lambda[i][alpha] + 0.5 * II * (B.chain.Str_L[i] + 1.0 - 2.0 * a))+eta*0.5)));
// 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)
// for (int j = 0; j < B.chain.Nstrings; ++j)
// for (int beta = 0; beta < B.base.Nrap[j]; ++beta)
// for (int b = 1; b <= B.chain.Str_L[j]; ++b)
// if(i!=j || alpha!=beta ||a!=b)ln_prod3+=-0.5*log(abs(phi((B.lambda[i][alpha] + 0.5 * II * (B.chain.Str_L[i] + 1.0 - 2.0 * a))-(B.lambda[j][beta] + 0.5 * II * (B.chain.Str_L[j] + 1.0 - 2.0 * b))-eta)));
// 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)
// for (int j = 0; j < A.chain.Nstrings; ++j)
// for (int beta = 0; beta < A.base.Nrap[j]; ++beta)
// for (int b = 1; b <= A.chain.Str_L[j]; ++b)
// if(abs((A.lambda[i][alpha] + 0.5 * II * (A.chain.Str_L[i] + 1.0 - 2.0 * a))-(A.lambda[j][beta] + 0.5 * II * (A.chain.Str_L[j] + 1.0 - 2.0 * b))-eta)!=0 && (i!=j && alpha!=beta && a!=b))
// ln_prod3+=-0.5*log(abs((A.lambda[i][alpha] + 0.5 * II * (A.chain.Str_L[i] + 1.0 - 2.0 * a))-(A.lambda[j][beta] + 0.5 * II * (A.chain.Str_L[j] + 1.0 - 2.0 * b))-eta));
//mu is the ground state!
//A -> mu, B -> lam
complex<DP> prod=complex<DP>(1.0,0.0);
complex<DP> prod2=complex<DP>(1.0,0.0);
complex<DP> prod3=complex<DP>(1.0,0.0);
for(int l=0; l<sizeA;l++) prod*=phi(mu[l]+eta*0.5);
for(int l=0; l<sizeB;l++) prod/=phi(lam[l]+eta*0.5);
for(int l=0; l<sizeA;l++)
for(int m=0; m<sizeA;m++)
if(l!=m)prod2*=1.0/sqrt(abs(phi(mu[m]-mu[l]-eta)));
for(int l=0; l<sizeB;l++)
for(int m=0; m<sizeB;m++)
if(abs(lam[m]-lam[l]-eta)!=0 && l!=m)prod3*=1.0/sqrt(abs(phi(lam[m]-lam[l]-eta)));
result+=2.0*log(abs(prod))-2.0*log(prod3)+2.0*log(prod2) - A.lnnorm - B.lnnorm;// a factor prod3^2 is inserted in the determinant!
// cout<<"prod:"<<prod<<endl;
SQMat_CX Hm(0.0, A.base.Mdown);
//complex<DP> H[sizeA][sizeA];
// cout<<"mu[l]:";
// for(int l=0; l<sizeA;l++)
// cout<<mu[l]<<", ";
// cout<<endl;
// cout<<"lam[l]:";
// for(int l=0; l<sizeB;l++)
// cout<<lam[l]<<", ";
// cout<<endl;
int index_a = 0;
int index_b = 0;
complex<DP> Prod_powerN;
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;
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) {
complex<DP> prodplus= complex<DP>(1.0,0.0);
complex<DP> prodminus= complex<DP>(1.0,0.0);
// use simplified code for one-string here: original form of Hm2P matrix
prodplus = Fn_K (A, j, alpha, a, B, k, beta, 0);// 1.0/ (phi(mu[l]-lam[k]) phi(mu[l]-lam[k]+eta) )
prodplus*= exp(re_ln_Fn_G_0[k][beta] + II * im_ln_Fn_G_0[k][beta] - re_ln_Fn_F_B_0[k][beta]);//Prod phi(mu[l]-lam[k]+eta) / prod_l!=k |phi(lam[l]-lam[k]) |;
prodminus = Fn_K (A, j, alpha, a, B, k, beta, 1);// 1.0/ (phi(mu[l]-lam[k]) phi(mu[l]-lam[k]-eta) )
prodminus*= exp(re_ln_Fn_G_2[k][beta] + II * im_ln_Fn_G_2[k][beta] - re_ln_Fn_F_B_0[k][beta]);//Prod phi(mu[l]-lam[k]-eta)/ prod_l!=k | phi(lam[l]-lam[k]) |;
Prod_powerN = pow((B.lambda[k][beta] -eta*0.5) /(B.lambda[k][beta] +eta*0.5), complex<DP> (B.chain.Nsites));
Hm[index_a][index_b] =eta*(prodplus-prodminus*Prod_powerN);
} // if (B.chain.Str_L == 1)
else {
if (b > 1) Hm[index_a][index_b] = eta* Fn_K(A, j, alpha, a, B, k, beta, b-1)*exp(ln_Fn_G(A,B,k,beta,b-1))*exp(-real(ln_Fn_F(B, k, beta, b - 1)));//.../ prod_l!=k | phi(lam[l]-lam[k]) |
else if (b == 1) {
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);
complex<DP> sum1 = complex<DP>(0.0,0.0);
sum1 += Fn_K (A, j, alpha, a, B, k, beta, 0) *exp(ln_FunctionG[0]+ ln_FunctionG[1] //sum term when i=0
- ln_FunctionF[0] - ln_FunctionF[1]);
sum1 += Fn_K (A, j, alpha, a, B, k, beta, B.chain.Str_L[k]) //sum term when i=n
* 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]);
Hm[index_a][index_b] = eta * exp(ln_FunctionF[0]+ ln_FunctionF[1] - ln_FunctionG[1]) * sum1 * exp( - real(ln_Fn_F(B, k, beta, b - 1))); //the absolute value prod_l!=k phi(lam[l]-lam[k]) : real(ln_...)
} // 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_lambda_sq_plus_1over2sq;
//Hm[index_a][B.base.Mdown] = eta/((A.lambda[j][alpha] + 0.5 * II * (A.chain.Str_L[j] + 1.0 - 2.0 * a)) *
// (A.lambda[j][alpha] + 0.5 * II * (A.chain.Str_L[j] + 1.0 - 2.0 * a)) + 0.25);
Hm[index_a][B.base.Mdown] = eta/((mu[index_a]-eta*0.5)*(mu[index_a]+eta*0.5));
index_a++;
}}} // sums over j, alpha, a
// cout<<"Hm:";
// for(int j=0; j<sizeA;j++){
// for(int k=0; k<sizeA;k++) cout<<"Hm["<<j<<"]["<<k<<"]:"<<Hm[j][k]<<", ";
// cout<<endl;
// }
complex<DP> F= complex<DP>(0.0,0.0);
complex<DP> detmatrix;
detmatrix=exp(lndet_LU_CX_dstry(Hm));
//cout<<"exp(lndet_LU_CX(Hm)):"<<abs(detmatrix)<<endl;
// cout<<"exp(i*(A.K-B.K))+1.0):"<<exp(i*(A.K-B.K))+1.0<<"det(matrix):"<<detmatrix<<endl;
//F=-(exp(-i*(A.K-B.K))+1.0)*detmatrix;
//mu is the ground state!
//A -> mu, B -> lam
SQMat_CX G(0.0, A.base.Mdown);
SQMat_CX BbDa(0.0, A.base.Mdown);
index_a = 0;
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;
complex<DP> Da;
complex<DP> Ca;
Da=eta/((mu[index_a]-eta*0.5)*(mu[index_a]+eta*0.5));
Ca=eta*((mu[index_a]-eta*0.5)+(mu[index_a]+eta*0.5))/pow(((mu[index_a]-eta*0.5)*(mu[index_a]+eta*0.5)),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) {
complex<DP> Bb;
Bb=-(phi(lam[index_b]+eta*0.5)+phi(lam[index_b]-eta*0.5));
complex<DP> product=complex<DP>(1.0,0.0);
for(int o=0; o<sizeB;o++)product*=phi(lam[o]-lam[index_b]+eta);
Bb*=product;
complex<DP> prodplus= complex<DP>(1.0,0.0);
complex<DP> prodminus= complex<DP>(1.0,0.0);
// use simplified code for one-string here: original form of Hm2P matrix
prodplus = Fn_K (A, j, alpha, a, B, k, beta, 0);// 1.0/ (phi(mu[l]-lam[k]) phi(mu[l]-lam[k]+eta) )
prodplus*= exp(re_ln_Fn_G_0[k][beta] + II * im_ln_Fn_G_0[k][beta] - re_ln_Fn_F_B_0[k][beta]);//Prod phi(mu[l]-lam[k]+eta) / prod_l!=k |phi(lam[l]-lam[k]) |;
//prodplus*= exp(re_ln_Fn_G_0[k][beta] + II * im_ln_Fn_G_0[k][beta]);// - re_ln_Fn_F_B_0[k][beta]);//Prod phi(mu[l]-lam[k]+eta) / prod_l!=k |phi(lam[l]-lam[k]) |;
prodminus = Fn_K (A, j, alpha, a, B, k, beta, 1);// 1.0/ (phi(mu[l]-lam[k]) phi(mu[l]-lam[k]-eta) )
prodminus*= exp(re_ln_Fn_G_2[k][beta] + II * im_ln_Fn_G_2[k][beta] - re_ln_Fn_F_B_0[k][beta]);//Prod phi(mu[l]-lam[k]-eta)/ prod_l!=k | phi(lam[l]-lam[k]) |;
// prodminus*= exp(re_ln_Fn_G_2[k][beta] + II * im_ln_Fn_G_2[k][beta]);// - re_ln_Fn_F_B_0[k][beta]);//Prod phi(mu[l]-lam[k]-eta)/ prod_l!=k | phi(lam[l]-lam[k]) |;
Prod_powerN = pow((B.lambda[k][beta] - eta*0.5) /(B.lambda[k][beta] + eta*0.5), complex<DP> (B.chain.Nsites));
G[index_a][index_b] =eta*(prodplus-prodminus*Prod_powerN);
BbDa[index_a][index_b]=Bb*Da*exp(- re_ln_Fn_F_B_0[k][beta]);
} // if (B.chain.Str_L == 1)
else {
*/{
if (b > 1){
G[index_a][index_b] = eta* Fn_K(A, j, alpha, a, B, k, beta, b-1)*exp(ln_Fn_G(A,B,k,beta,b-1))*exp(-real(ln_Fn_F(B, k, beta, b - 1)));//.../ prod_l!=k | phi(lam[l]-lam[k]) |
BbDa[index_a][index_b] =0 ;
}
else if (b == 1) {
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);
complex<DP> sum1 = complex<DP>(0.0,0.0);
complex<DP> sum2 = complex<DP>(0.0,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]);//sum term when i=0
//sum2 doesn't have a i=0 term
sum1 += 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]); //sum term when i=n
sum2 += exp(ln_FunctionG[B.chain.Str_L[k]]- ln_FunctionF[B.chain.Str_L[k]] )
* (phi((B.lambda[k][beta] + 0.5 * II * (B.chain.Str_L[k] + 1.0 - 2.0 * B.chain.Str_L[k]))-eta*0.5)
+ phi((B.lambda[k][beta] + 0.5 * II * (B.chain.Str_L[k] + 1.0 - 2.0 * B.chain.Str_L[k]))+eta*0.5) ); //sum term when i=n
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 += exp(ln_FunctionG[jsum]- ln_FunctionF[jsum] )
* (phi((B.lambda[k][beta] + 0.5 * II * (B.chain.Str_L[k] + 1.0 - 2.0 * jsum))-eta*0.5)
+ phi((B.lambda[k][beta] + 0.5 * II * (B.chain.Str_L[k] + 1.0 - 2.0 * jsum))+eta*0.5) );
}
G[index_a][index_b] = eta * exp(ln_FunctionF[0]+ ln_FunctionF[1] - ln_FunctionG[1]) * sum1 * exp( - real(ln_Fn_F(B, k, beta, b - 1))); //the absolute value prod_l!=k phi(lam[l]-lam[k]) : real(ln_...)
BbDa[index_a][index_b] = - Da* exp(ln_FunctionF[0]+ ln_FunctionF[1] - ln_FunctionG[1]) * sum2 * exp( - real(ln_Fn_F(B, k, beta, b - 1)));//the absolute value prod_l!=k phi(lam[l]-lam[k]) : real(ln_...)
} // 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] = eta/((A.lambda[j][alpha] + 0.5 * II * (A.chain.Str_L[j] + 1.0 - 2.0 * a)) * (A.lambda[j][alpha] + 0.5 * II * (A.chain.Str_L[j] + 1.0 - 2.0 * a)) + 0.25);
G[index_a][B.base.Mdown]=Ca;
BbDa[index_a][B.base.Mdown]=0;
index_a++;
}}} // sums over j, alpha, a
SQMat_CX matrix(0.0, A.base.Mdown);
for(int a=0; a<sizeA;a++)
for(int b=0; b<sizeA;b++)
matrix[a][b]=G[a][b]+BbDa[a][b];
// cout<<"matrix:";
// for(int j=0; j<sizeA;j++){
// for(int k=0; k<sizeA;k++) cout<<"matrix["<<j<<"]["<<k<<"]:"<<matrix[j][k]<<", ";
// cout<<endl;
// }
// cout<<"matrixtest:";
// for(int j=0; j<sizeA;j++){
// for(int k=0; k<sizeA;k++) cout<<"matrixtest["<<j<<"]["<<k<<"]:"<<matrixtest[j][k]<<", ";
// cout<<endl;
// }
// cout<<"BbDa[a][b]:";
// for(int j=0; j<sizeA;j++){
// for(int k=0; k<sizeA;k++) cout<<"BbDa["<<j<<"]["<<k<<"]:"<<BbDa[j][k]<<", ";
// cout<<endl;
// }
// cout<<"Bn[b]*Da[a]:";
// for(int j=0; j<sizeA;j++){
// for(int k=0; k<sizeA;k++) cout<<"test["<<j<<"]["<<k<<"]:"<<Bn[k]*Da[j]<<", ";
// cout<<endl;
// }
// cout<<"prod:"<<prod<<endl;
// cout<<"(exp(lndet_LU_CX_dstry(matrix))-exp(lndet_LU_CX_dstry(G))):"<<(exp(lndet_LU_CX(matrix))-exp(lndet_LU_CX(G)))<<endl;
// cout<<"(exp(lndet_LU_CX_dstry(matrix)):"<<(exp(lndet_LU_CX(matrix)))<<endl;
//cout<<" an(n):"<<an(n)<<" det(matrix):"<<det(matrix)<< " det(Gn):"<<det(Gn)<<" an(n)*(det(matrix)-det(Gn)):"<<an(n)*(det(matrix)-det(Gn))<<endl;
complex<DP> sum=prod*(exp(lndet_LU_CX_dstry(matrix))-exp(lndet_LU_CX_dstry(G)));
//sum=conj(prod)*(exp(lndet_LU_CX_dstry(matrix))-exp(lndet_LU_CX_dstry(G)));
//cout<<"an(n):"<< an(n)<< "det(matrix):"<<det(matrix)<<" det(Gn):"<<det(Gn)<<endl;
//sum_nm_test=(0.5*(lam[0]-lam[1])*(eta*eta+4.0*lam[0]*lam[1]))/pow((lam[0]-eta/2.0)*(lam[0]+eta/2.0)*(lam[1]-eta/2.0)*(lam[1]+eta/2.0),2.0)*(0.5*(mu[0]-mu[1])*(eta*eta+4.0*mu[0]*mu[1]))/pow((mu[0]-eta/2.0)*(mu[0]+eta/2.0)*(mu[1]-eta/2.0)*(mu[1]+eta/2.0),2.0);
//sum_nm_test=(0.5*(lam[0]-lam[1])*(eta*eta+4.0*lam[0]*lam[1]))*(0.5*(mu[0]-mu[1])*(eta*eta+4.0*mu[0]*mu[1]))/pow((mu[0]-eta/2.0)*(mu[0]+eta/2.0)*(mu[1]-eta/2.0)*(mu[1]+eta/2.0),2.0);
//cout<<"F1:"<<F<<endl;
// F+=4.0*pow(prod,2)*exp(i*(qlam+qmu))*sum_n;
// F+=+2.0*exp(i*(A.K-B.K))*sum;
complex<DP> F2=exp(eta*(B.K-A.K))*(-2.0*sum);
complex<DP> F3=(exp(eta*(B.K-A.K)))*(detmatrix);
F=detmatrix;
// cout<<"F1:"<<F*sqrt(exp(result))<<" F2:"<<F2*sqrt(exp(result))<<" F3:"<<F3*sqrt(exp(result))<<endl;
// cout<<"abs(F1)^2:"<<abs(F*F*(exp(result)))<<" abs(F2)^2:"<<abs(F2*F2*(exp(result)))<<" abs(F3)^2:"<<abs(F3*F3*(exp(result)))<<endl;
// cout<<"arg(F1):"<<-i*log(F*sqrt(exp(result))/abs(F*sqrt(exp(result))))/M_PI<<" arg(F2):"<<-i*log(F2*sqrt(exp(result))/abs(F2*sqrt(exp(result))))/M_PI<<" arg(F3):"<<-i*log(F3*sqrt(exp(result))/abs(F3*sqrt(exp(result))))/M_PI<<endl;
// cout<<"F:"<<(F)<<endl;
// cout<<"Smff:"<<exp(result)*4.0*abs(detmatrix*detmatrix)<<endl;
F+=exp(i*(A.K-B.K))*(2.0*sum*(-1.0)+detmatrix);
// cout<<"sum:"<<sum<<endl;
// cout<<"exp(result):"<<exp(result)<<endl;
//TEST!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
result+=2.0*log(abs(F));
result-=log(A.chain.Nsites-A.base.Mdown*2+2.0);
//result*=pow(abs((exp(i*(A.K-B.K))+1.0)*detmatrix),2);//*(exp(i*(A.K-B.K))+1.0)
//result*=pow(abs(2.0*exp(i*(A.K-B.K))*sum),2);
//result/=(B.chain.Nsites)*1/16.0;
//cout<<"TEST::::::::::::::::::::::"<<"A.Check_Admissibility('a'):"<<A.Check_Admissibility('a')<<endl;
//cout<<"mu:"<<mu<<" lam:"<<lam<<endl;
// cout<<"an(n):"<<an<<endl;
// cout<<"prod^2:"<<pow(abs(prod),2)<<endl;
// cout<<"prod3:"<<prod3<<endl;
// cout<<"prod2:"<<prod2<<endl;
// cout<<"normlam"<<"normmu:"<<(exp(A.lnnorm))<<":"<<(exp(B.lnnorm))<<endl;
// cout<<"abs(prod*prod*prod2*sum_n):"<<abs(prod*prod*prod2*sum_n)<<endl;
//cout<<"computation time for Szm:"<<clock()-start_time_local<<endl;
complex<DP> ln_ME_sq = result;
// if (real(ln_ME_sq) > 10.0) ln_ME_sq = complex<DP> (-300.0); // fix for artificial divergences
delete[] mu;
delete[] lam;
//return(ln_ME_sq);
return(0.5 * ln_ME_sq); // Return ME, not MEsq
}
} // namespace JSC
+417
View File
@@ -0,0 +1,417 @@
#include "JSC.h"
using namespace JSC;
namespace JSC {
complex<DP> phi(complex<DP> x){return x;}
complex<DP> a(complex<DP> x){return 1;}
complex<DP> b(complex<DP> x,complex<DP> y, complex<DP> eta){ return phi(x-y)/phi(x-y+complex<DP>(0.0,1.0)*eta);}
complex<DP> d(complex<DP> x, complex<DP> xi, complex<DP> eta, int N){return pow(b(x,xi,eta),N);}
inline complex<DP> ln_Fn_F (XXX_Bethe_State& B, int k, int beta, int b)
{
complex<DP> ans = 0.0;
for (int j = 0; j < B.chain.Nstrings; ++j) {
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)))
ans += log(B.lambda[j][alpha] - B.lambda[k][beta]
+ 0.5 * II * (B.chain.Str_L[j] - B.chain.Str_L[k] - 2.0 * (a - b)));
}
}
}
return(ans);
}
inline complex<DP> ln_Fn_G (XXX_Bethe_State& A, XXX_Bethe_State& B, int k, int beta, int b)
{
complex<DP> ans = 0.0;
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) {
ans += log(A.lambda[j][alpha] - B.lambda[k][beta]
+ 0.5 * II * (A.chain.Str_L[j] - B.chain.Str_L[k] - 2.0 * (a - b)));
}
}
}
return(ans);
}
inline complex<DP> Fn_K (XXX_Bethe_State& A, int j, int alpha, int a, XXX_Bethe_State& B, int k, int beta, int b)
{
return(1.0/((A.lambda[j][alpha] - B.lambda[k][beta]
+ 0.5 * II * (A.chain.Str_L[j] - B.chain.Str_L[k] - 2.0 * (a - b)))
* (A.lambda[j][alpha] - B.lambda[k][beta]
+ 0.5 * II * (A.chain.Str_L[j] - B.chain.Str_L[k] - 2.0 * (a - b - 1.0)) )));
}
inline complex<DP> Fn_L (XXX_Bethe_State& A, int j, int alpha, int a, XXX_Bethe_State& B, int k, int beta, int b)
{
return ((2.0 * (A.lambda[j][alpha] - B.lambda[k][beta]
+ 0.5 * II * (A.chain.Str_L[j] - B.chain.Str_L[k] - 2.0 * (a - b - 0.5))
))
* pow(Fn_K (A, j, alpha, a, B, k, beta, b), 2.0));
}
complex<DP> ln_Szz_ME (XXX_Bethe_State& A, XXX_Bethe_State& B){
//clock_t start_time_local = clock();
//B has to be the ground state!
const DP Zero_Center_Thres=1.0e-5;
const DP real_dev=1.0e-14;
const DP Diff_ME_Thres=1.e-6;
// 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 XXX_Chain
if (A.chain != B.chain) JSCerror("Incompatible XXX_Chains in Szz matrix element.");
// Check that A and B are compatible: same Mdown
if (A.base.Mdown != B.base.Mdown) JSCerror("Incompatible Mdown between the two states in Szz matrix element!");
complex<DP> eta=-II;
complex<DP> ln_prod = complex<DP>(0.0,0.0);
complex<DP> result=-300;
complex<DP> prev_result=-300;
//if(A.String_delta()> HEIS_deltaprec) return(complex<DP>(-300.0)); // DEPRECATED in ++T_9
if((A.E)==(B.E) && B.chain.Nsites ==B.base.Mdown*2){
return(2*log(abs((B.E+(B.chain.Nsites)/4.0)/(3.0*sqrt(B.chain.Nsites)))));
}
XXX_Bethe_State A_origin; A_origin=A;
bool zero_string=false;
for (int j = 0; j < A_origin.chain.Nstrings; ++j)
for (int alpha = 0; alpha < A_origin.base.Nrap[j]; ++alpha)
if(abs(A_origin.lambda[j][alpha])<Zero_Center_Thres) zero_string=true;
// Some convenient arrays
bool real_dev_conv=false;
int dev=-1;
while(!real_dev_conv){
real_dev_conv=true;
dev++;
//add a delta to the origin of the centered strings
if(zero_string){
real_dev_conv=false;
for (int j = 0; j < A.chain.Nstrings; ++j)
for (int alpha = 0; alpha < A.base.Nrap[j]; ++alpha)
if(abs(A_origin.lambda[j][alpha])<Zero_Center_Thres)
A.lambda[j][alpha]=real_dev*pow(10.0,dev);
}
prev_result=result;
//add manualy the ground state value
int sizeA=0;
int sizeB=0;
for (int i = 0; i < A.chain.Nstrings; ++i)
sizeA+=A.base.Nrap[i]*A.chain.Str_L[i];
for (int i = 0; i < B.chain.Nstrings; ++i)
sizeB+=B.base.Nrap[i]*B.chain.Str_L[i];
complex<DP>* mu = new complex<DP>[sizeA];
complex<DP>* lam = new complex<DP>[sizeB];
int index=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)
{
mu[index]=(A.lambda[i][alpha] + 0.5 * II * (A.chain.Str_L[i] + 1.0 - 2.0 * a));
index++;
}
index=0;
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)
{
lam[index]=(B.lambda[i][alpha] + 0.5 * II * (B.chain.Str_L[i] + 1.0 - 2.0 * a));
index++;
}
Lambda re_ln_Fn_F_A_0(A.chain, A.base);
Lambda im_ln_Fn_F_A_0(A.chain, A.base);
Lambda re_ln_Fn_F_B_0(B.chain, B.base);
Lambda im_ln_Fn_F_B_0(B.chain, B.base);
Lambda re_ln_Fn_G_0(B.chain, B.base);
Lambda im_ln_Fn_G_0(B.chain, B.base);
Lambda re_ln_Fn_G_2(B.chain, B.base);
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(A.lambda[i][alpha] + 0.5 * II * (A.chain.Str_L[i] + 1.0 - 2.0 * a - 1.0)));
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(B.lambda[i][alpha] + 0.5 * II * (B.chain.Str_L[i] + 1.0 - 2.0 * a - 1.0)) > 100.0 * MACHINE_EPS_SQ)
ln_prod2 += log(norm(B.lambda[i][alpha] + 0.5 * II * (B.chain.Str_L[i] + 1.0 - 2.0 * a - 1.0)));
// Define the F ones earlier...
for (int j = 0; j < A.chain.Nstrings; ++j) {
for (int alpha = 0; alpha < A.base.Nrap[j]; ++alpha) {
re_ln_Fn_F_A_0[j][alpha] = real(ln_Fn_F(A, j, alpha, 0));
im_ln_Fn_F_A_0[j][alpha] = imag(ln_Fn_F(A, j, alpha, 0));
}
}
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));
}
}
// Define regularized products in prefactors
for (int k = 0; k < A.chain.Nstrings; ++k)
for (int beta = 0; beta < A.base.Nrap[k]; ++beta)
for (int b = 1; b <= A.chain.Str_L[k]; ++b) {
if (b == 1)ln_prod3 += re_ln_Fn_F_A_0[k][beta];
else if (b > 1) ln_prod3 += ln_Fn_F(A, k, beta, b - 1);/*TEST*/
}
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);
}
complex<DP> prod=complex<DP>(1.0,0.0);
for(int l=0; l<sizeA;l++) prod*=phi(mu[l]+eta*0.5);
for(int l=0; l<sizeB;l++) prod/=phi(lam[l]+eta*0.5);
double factor = log((B.chain.Nsites)*1/16.0);
factor +=(2.0*log(abs(prod)) - real(ln_prod3) + real(ln_prod4) - A.lnnorm - B.lnnorm);// a factor prod4^-2 is inserted in the determinant!
int index_a = 0;
int index_b = 0;
complex<DP> Prod_powerN;
SQMat_CX H(0.0, A.base.Mdown);
SQMat_CX P(0.0, A.base.Mdown);
index_a = 0;
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;
complex<DP> Da;
complex<DP> Ca;
Da=eta/((mu[index_a]-eta*0.5)*(mu[index_a]+eta*0.5));
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) {
complex<DP> Bb=complex<DP>(1.0,0.0);
for(int o=0; o<sizeB;o++)Bb*=phi(lam[o]-lam[index_b]+eta);
complex<DP> prodplus= complex<DP>(1.0,0.0);
complex<DP> prodminus= complex<DP>(1.0,0.0);
// use simplified code for one-string here: original form of Hm2P matrix
prodplus = Fn_K (A, j, alpha, a, B, k, beta, 0);
prodplus*= exp(re_ln_Fn_G_0[k][beta] + II * im_ln_Fn_G_0[k][beta] - re_ln_Fn_F_B_0[k][beta]);
prodminus = Fn_K (A, j, alpha, a, B, k, beta, 1);
prodminus*= exp(re_ln_Fn_G_2[k][beta] + II * im_ln_Fn_G_2[k][beta] - re_ln_Fn_F_B_0[k][beta]);
Prod_powerN = pow((B.lambda[k][beta] - eta*0.5) /(B.lambda[k][beta] + eta*0.5), complex<DP> (B.chain.Nsites));
H[index_a][index_b] = eta*(prodplus-prodminus*Prod_powerN);
P[index_a][index_b] = Bb*Da*exp(- re_ln_Fn_F_B_0[k][beta]);
} // if (B.chain.Str_L == 1)
else {
if (b > 1){
H[index_a][index_b] = eta* Fn_K(A, j, alpha, a, B, k, beta, b-1)*exp(ln_Fn_G(A,B,k,beta,b-1))*exp(-real(ln_Fn_F(B, k, beta, b - 1)));//.../ prod_l!=k | phi(lam[l]-lam[k]) |
P[index_a][index_b] =0 ;
}
else if (b == 1) {
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);
complex<DP> sum1 = complex<DP>(0.0,0.0);
complex<DP> sum2 = complex<DP>(0.0,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]);//sum term when i=0
//sum2 doesn't have a i=0 term
sum1 += 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]); //sum term when i=n
sum2 += exp(ln_FunctionG[B.chain.Str_L[k]]- ln_FunctionF[B.chain.Str_L[k]] ); //sum term when i=n
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 += exp(ln_FunctionG[jsum]- ln_FunctionF[jsum] );
}
H[index_a][index_b] = eta * exp(ln_FunctionF[0]+ ln_FunctionF[1] - ln_FunctionG[1]) * sum1 * exp( - real(ln_Fn_F(B, k, beta, b - 1))); //the absolute value prod_l!=k phi(lam[l]-lam[k]) : real(ln_...)
P[index_a][index_b] = - Da* exp(ln_FunctionF[0]+ ln_FunctionF[1] - ln_FunctionG[1]) * sum2 * exp( - real(ln_Fn_F(B, k, beta, b - 1)));//the absolute value prod_l!=k phi(lam[l]-lam[k]) : real(ln_...)
} // else if (b == B.chain.Str_L[k])
} // else
index_b++;
}}} // sums over k, beta, b
index_a++;
}}} // sums over j, alpha, a
complex<DP> F= complex<DP>(0.0,0.0);
SQMat_CX matrix(0.0, A.base.Mdown);
for(int j=0; j<sizeA;j++)
for(int k=0; k<sizeA;k++){
matrix[j][k]=(H[j][k]-2.0*P[j][k]);
}
complex<DP> detmatrix;
detmatrix=exp(lndet_LU_CX_dstry(matrix)+0.5*factor);
SQMat_CX Gn(0.0, A.base.Mdown);
complex<DP> sum_n=complex<DP>(0.0,0.0);
for(int n=0; n<sizeA;n++){
complex<DP> An;
An=-phi(lam[n]-eta*0.5);
for(int m=0; m<sizeA;m++)
An*=phi(lam[m]-lam[n]+eta);
SQMat_CX Gn(0.0, A.base.Mdown);
SQMat_CX BnbDa(0.0, A.base.Mdown);
index_a = 0;
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;
complex<DP> Da;
complex<DP> Ca;
Da=eta/((mu[index_a]-eta*0.5)*(mu[index_a]+eta*0.5));
Ca=(eta)*((mu[index_a]-eta*0.5)+(mu[index_a]+eta*0.5))/pow(((mu[index_a]-eta*0.5)*(mu[index_a]+eta*0.5)),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(index_b==n){
Gn[index_a][index_b] = Ca*exp(-real(ln_Fn_F(B, k, beta, b - 1)));
BnbDa[index_a][index_b] = 0;
} // else (index_b!=n)
else if (B.chain.Str_L[k] == 1) {
complex<DP> Bnb;
Bnb=-phi(lam[index_b]+eta*0.5)/phi(lam[n]-lam[index_b]-eta);
complex<DP> product=complex<DP>(1.0,0.0);
for(int o=0; o<sizeB;o++)product*=phi(lam[o]-lam[index_b]+eta);
Bnb*=product;
complex<DP> prodplus= complex<DP>(1.0,0.0);
complex<DP> prodminus= complex<DP>(1.0,0.0);
// use simplified code for one-string here: original form of Hm2P matrix
prodplus = Fn_K (A, j, alpha, a, B, k, beta, 0);// 1.0/ (phi(mu[l]-lam[k]) phi(mu[l]-lam[k]+eta) )
prodplus*= exp(re_ln_Fn_G_0[k][beta] + II * im_ln_Fn_G_0[k][beta] - re_ln_Fn_F_B_0[k][beta]);//Prod phi(mu[l]-lam[k]+eta) / prod_l!=k |phi(lam[l]-lam[k]) |;
prodminus = Fn_K (A, j, alpha, a, B, k, beta, 1);// 1.0/ (phi(mu[l]-lam[k]) phi(mu[l]-lam[k]-eta) )
prodminus*= exp(re_ln_Fn_G_2[k][beta] + II * im_ln_Fn_G_2[k][beta] - re_ln_Fn_F_B_0[k][beta]);//Prod phi(mu[l]-lam[k]-eta)/ prod_l!=k | phi(lam[l]-lam[k]) |;
Prod_powerN = pow((B.lambda[k][beta] - eta*0.5) /(B.lambda[k][beta] + eta*0.5), complex<DP> (B.chain.Nsites));
Gn[index_a][index_b] =eta*(prodplus-prodminus*Prod_powerN);
BnbDa[index_a][index_b]=Bnb*Da*exp(- re_ln_Fn_F_B_0[k][beta]);
} // if (B.chain.Str_L == 1)
else{
JSCerror("The Szz matrix element computation is not able to handle string states in the B.state (second argument). This is in development...");
} // else
index_b++;
}}} // sums over k, beta, b
index_a++;
}}} // sums over j, alpha, a
SQMat_CX matrix(0.0, A.base.Mdown);
for(int a=0; a<sizeA;a++)
for(int b=0; b<sizeA;b++)
matrix[a][b]=Gn[a][b]+BnbDa[a][b];
sum_n+=(exp(lndet_LU_CX_dstry(matrix)+0.5*factor+log(An))-exp(lndet_LU_CX_dstry(Gn)+0.5*factor+log(An)));
}// sum over n
sum_n*=prod;
F=(exp(II*(A.K-B.K))+1.0)*detmatrix;
F+=-4.0*exp(II*(A.K-B.K))*sum_n;
result=2*log(abs(F));
if (!(real_dev_conv) && abs(exp(result)-exp(prev_result))<abs( Diff_ME_Thres*exp(result))){
real_dev_conv=true;
}
if (!(real_dev_conv) && dev >20){
result=-300;
real_dev_conv=true;
}
delete[] mu;
delete[] lam;
}
//return(result);
return(0.5 * result); // Return ME, not MEsq
}
} // namespace JSC
+25
View File
@@ -0,0 +1,25 @@
/**********************************************************
This software is part of J.-S. Caux's ABACUS++ library.
Copyright (c)
-----------------------------------------------------------
File: Infprec.cc
Purpose: Definitions for infinite precision arithmetic classes.
***********************************************************/
#include "JSC.h"
using namespace std;
namespace JSC {
//***************************************************************************************************
} // namespace JSC
File diff suppressed because it is too large Load Diff
+152
View File
@@ -0,0 +1,152 @@
/****************************************************************
This software is part of J.-S. Caux's C++ library.
Copyright (c) 2006.
-----------------------------------------------------------
Integration_par.cc
Defines all functions to perform integration of functions, parallel (MPI).
LAST MODIFIED: 30/10/06
******************************************************************/
#include "JSC.h"
#include "mpi.h"
using namespace std;
namespace JSC {
void Improve_estimate_par (MPI_Comm comm, Integral_data& integdat, DP (*function) (Vect_DP, I_table), Vect_DP& args, int arg_to_integ, I_table Itable, int max_nr_pts)
{
// This function is only ever called by process rank 0.
// We generate a max of 3* n_vals points
data_pt* new_data = new data_pt[3* integdat.integ_res.n_vals];
DP* new_abs_d2f_dx = new DP[integdat.integ_res.n_vals];
// Check points in batches of 3; if needed, improve
int threei = 0;
int index_new = 0;
int i, j;
integdat.integ_res.abs_prec = 0.0;
integdat.integ_res.integ_est = 0.0;
DP new_max_abs_d2f_dx = 0.0;
for (i = 0; i < integdat.integ_res.n_vals/3; ++i) {
threei = 3 * i;
if (integdat.abs_d2f_dx[i] <= 0.1 * integdat.max_abs_d2f_dx || index_new + integdat.integ_res.n_vals - threei > max_nr_pts) {
// simply transfer the data points into new_data
new_abs_d2f_dx[index_new/3] = integdat.abs_d2f_dx[i];
new_max_abs_d2f_dx = JSC::max(new_max_abs_d2f_dx, new_abs_d2f_dx[index_new/3]);
for (j = 0; j < 3; ++j) {
new_data[index_new].x = integdat.data[threei + j].x;
new_data[index_new].f = integdat.data[threei + j].f;
new_data[index_new].dx = integdat.data[threei + j].dx;
integdat.integ_res.integ_est += new_data[index_new].dx * new_data[index_new].f;
index_new++;
}
integdat.integ_res.abs_prec += abs_d2f_dx[i];
}
else { // create six new entries and transfer the three existing ones
new_data[index_new].dx = integdat.data[threei].dx/3.0;
for (j = 1; j < 9; ++j) new_data[index_new + j].dx = new_data[index_new].dx;
new_data[index_new].x = integdat.data[threei].x - new_data[index_new].dx;
new_data[index_new + 1].x = integdat.data[threei].x;
new_data[index_new + 2].x = integdat.data[threei].x + new_data[index_new].dx;
new_data[index_new + 3].x = integdat.data[threei + 1].x - new_data[index_new].dx;
new_data[index_new + 4].x = integdat.data[threei + 1].x;
new_data[index_new + 5].x = integdat.data[threei + 1].x + new_data[index_new].dx;
new_data[index_new + 6].x = integdat.data[threei + 2].x - new_data[index_new].dx;
new_data[index_new + 7].x = integdat.data[threei + 2].x;
new_data[index_new + 8].x = integdat.data[threei + 2].x + new_data[index_new].dx;
args[arg_to_integ] = new_data[index_new].x;
new_data[index_new].f = function(args, Itable);
new_data[index_new + 1].f = integdat.data[threei].f;
args[arg_to_integ] = new_data[index_new + 2].x;
new_data[index_new + 2].f = function(args, Itable);
args[arg_to_integ] = new_data[index_new + 3].x;
new_data[index_new + 3].f = function(args, Itable);
new_data[index_new + 4].f = integdat.data[threei + 1].f;
args[arg_to_integ] = new_data[index_new + 5].x;
new_data[index_new + 5].f = function(args, Itable);
args[arg_to_integ] = new_data[index_new + 6].x;
new_data[index_new + 6].f = function(args, Itable);
new_data[index_new + 7].f = integdat.data[threei + 2].f;
args[arg_to_integ] = new_data[index_new + 8].x;
new_data[index_new + 8].f = function(args, Itable);
new_abs_d2f_dx[index_new/3] = fabs(new_data[index_new].dx * (new_data[index_new].f - 2.0 * new_data[index_new + 1].f + new_data[index_new + 2].f));
new_abs_d2f_dx[index_new/3 + 1] = fabs(new_data[index_new].dx * (new_data[index_new + 3].f - 2.0 * new_data[index_new + 4].f + new_data[index_new + 5].f));
new_abs_d2f_dx[index_new/3 + 2] = fabs(new_data[index_new].dx * (new_data[index_new + 6].f - 2.0 * new_data[index_new + 7].f + new_data[index_new + 8].f));
new_max_abs_d2f_dx = JSC::max(new_max_abs_d2f_dx, new_abs_d2f_dx[index_new/3]);
new_max_abs_d2f_dx = JSC::max(new_max_abs_d2f_dx, new_abs_d2f_dx[index_new/3 + 1]);
new_max_abs_d2f_dx = JSC::max(new_max_abs_d2f_dx, new_abs_d2f_dx[index_new/3 + 2]);
integdat.integ_res.integ_est += new_data[index_new].dx * (new_data[index_new].f + new_data[index_new + 1].f + new_data[index_new + 2].f
+ new_data[index_new + 3].f + new_data[index_new + 4].f + new_data[index_new + 5].f
+ new_data[index_new + 6].f + new_data[index_new + 7].f + new_data[index_new + 8].f);
integdat.integ_res.abs_prec += new_abs_d2f_dx[index_new/3] + new_abs_d2f_dx[index_new/3 + 1] + new_abs_d2f_dx[index_new/3 + 2];
index_new += 9;
} // else
} // for (i < nvals/3)
integdat.integ_res.rel_prec = integdat.integ_res.abs_prec/integdat.integ_res.integ_est;
integdat.integ_res.n_vals = index_new;
delete[] integdat.data;
integdat.data = new_data;
integdat.max_abs_d2f_dx = new_max_abs_d2f_dx;
delete[] integdat.abs_d2f_dx;
integdat.abs_d2f_dx = new_abs_d2f_dx;
return;
}
Integral_result Integrate_optimal_par_using_table (MPI_Comm comm, DP (*function) (Vect_DP, I_table), Vect_DP& args, int arg_to_integ,
I_table Itable, DP xmin, DP xmax, DP req_rel_prec, DP req_abs_prec, int max_nr_pts, ofstream& outfile)
{
if (xmax < xmin) JSCerror("Use xmax > xmin in Integrate.");
Integral_data integ_dat (function, args, arg_to_integ, Itable, xmin, xmax);
while ((integ_dat.integ_res.rel_prec > req_rel_prec || integ_dat.integ_res.abs_prec > req_abs_prec) && integ_dat.integ_res.n_vals < max_nr_pts) {
Improve_estimate_par (comm, integ_dat, function, args, arg_to_integ, Itable, max_nr_pts);
integ_dat.Save (outfile);
}
return(integ_dat.integ_res);
}
} // namespace JSC
+809
View File
@@ -0,0 +1,809 @@
/**********************************************************
This software is part of J.-S. Caux's ABACUS library.
Copyright (c).
-----------------------------------------------------------
File: LiebLin_Bethe_State.cc
Purpose: Definitions for LiebLin_Bethe_State class.
***********************************************************/
#include "JSC.h"
using namespace std;
namespace JSC {
//***************************************************************************************************
// Function definitions: class LiebLin_Bethe_State
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)),
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 + JSCcoding[0] + LABELSEP;//"_0_";
}
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)),
S(Vect<DP>(0.0, N)), dSdlambdaoc(Vect<DP>(0.0, N)),
diffsq(0.0), prec(JSC::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) JSCerror("You must use a positive interaction parameter !");
if (N < 0) JSCerror("Particle number must be strictly positive.");
stringstream Nout; Nout << N; label = Nout.str() + LABELSEP + JSCcoding[0] + LABELSEP;//+ "_0_";
// Set quantum numbers to ground-state configuration:
for (int i = 0; i < N; ++i) Ix2[i] = -(N-1) + 2*i;
Vect<int> OriginIx2 = Ix2;
(*this).Set_Label_from_Ix2 (OriginIx2);
//(*this).Set_Label_Internals_from_Ix2 (OriginIx2);
}
LiebLin_Bethe_State& LiebLin_Bethe_State::operator= (const LiebLin_Bethe_State& RefState)
{
if (this != &RefState) {
c_int = RefState.c_int;
L = RefState.L;
cxL = RefState.cxL;
N = RefState.N;
label = RefState.label;
Ix2_available = RefState.Ix2_available;
index_first_hole_to_right = RefState.index_first_hole_to_right;
displacement = RefState.displacement;
Ix2 = RefState.Ix2;
lambdaoc = RefState.lambdaoc;
//BE = RefState.BE;
S = RefState.S;
dSdlambdaoc = RefState.dSdlambdaoc;
diffsq = RefState.diffsq;
prec = RefState.prec;
conv = RefState.conv;
iter_Newton = RefState.iter_Newton;
E = RefState.E;
iK = RefState.iK;
K = RefState.K;
lnnorm = RefState.lnnorm;
}
return(*this);
}
void LiebLin_Bethe_State::Set_to_Label (string label_ref, const Vect<int>& OriginStateIx2)
{
State_Label_Data labeldata = Read_State_Label (label_ref, OriginStateIx2);
if (N != labeldata.M[0]) {
cout << label_ref << endl;
cout << labeldata.M << endl;
JSCerror("Trying to set an incorrect label on LiebLin_Bethe_State: N != M[0].");
}
if (N != OriginStateIx2.size()) {
cout << label_ref << endl;
cout << labeldata.M << endl;
JSCerror("Trying to set an incorrect label on LiebLin_Bethe_State: N != OriginStateIx2.size().");
}
label = label_ref;
Vect<int> OriginStateIx2ordered = OriginStateIx2;
OriginStateIx2ordered.QuickSort();
// Set all Ix2 to OriginState's Ix2:
for (int i = 0; i < N; ++i) Ix2[i] = OriginStateIx2ordered[i];
// Now set the excitations:
for (int iexc = 0; iexc < labeldata.nexc[0]; ++iexc)
for (int i = 0; i < N; ++i) if (Ix2[i] == labeldata.Ix2old[0][iexc]) Ix2[i] = labeldata.Ix2exc[0][iexc];
// 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)
{
// This function assumes that OriginState is the ground state.
Vect<int> OriginStateIx2(N);
for (int i = 0; i < N; ++i) OriginStateIx2[i] = -N + 1 + 2*i;
(*this).Set_to_Label(label_ref, OriginStateIx2);
}
void LiebLin_Bethe_State::Set_Label_from_Ix2 (const Vect<int>& OriginStateIx2)
{
// This function does not assume any ordering of the Ix2.
if (N != OriginStateIx2.size()) JSCerror("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);
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 (!OriginStateIx2.includes(Ix2[i])) nexc_ref[0] += 1;
Vect<Vect<int> > Ix2old_ref(1);
Vect<Vect<int> > Ix2exc_ref(1);
Ix2old_ref[0] = Vect<int>(JSC::max(nexc_ref[0],1));
Ix2exc_ref[0] = Vect<int>(JSC::max(nexc_ref[0],1));
int nexccheck = 0;
for (int i = 0; i < N; ++i) if (!OriginStateIx2.includes(Ix2[i])) Ix2exc_ref[0][nexccheck++] = Ix2[i];
if (nexccheck != nexc_ref[0]) JSCerror("Counting excitations wrong (1) in LiebLin_Bethe_State::Set_Label_from_Ix2");
nexccheck = 0;
for (int i = 0; i < N; ++i) if (!Ix2.includes (OriginStateIx2[i])) Ix2old_ref[0][nexccheck++] = OriginStateIx2[i];
if (nexccheck != nexc_ref[0]) {
cout << "nexc_ref[0] = " << nexc_ref[0] << "\tnexccheck = " << nexccheck << endl;
cout << OriginStateIx2 << endl;
cout << Ix2 << endl;
cout << nexc_ref[0] << endl;
cout << Ix2old_ref[0] << endl;
cout << Ix2exc_ref[0] << endl;
JSCerror("Counting excitations wrong (2) in LiebLin_Bethe_State::Set_Label_from_Ix2");
}
// Now order the Ix2old_ref and Ix2exc_ref:
Ix2old_ref[0].QuickSort();
Ix2exc_ref[0].QuickSort();
State_Label_Data labeldata(type_ref, M_ref, nexc_ref, Ix2old_ref, Ix2exc_ref);
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()) JSCerror("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>(JSC::max(nexc_ref[0],1));
Ix2exc_ref[0] = Vect<int>(JSC::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)
{
//JSCerror("LiebLin_Bethe_State::Set_Label_Internals_from_Ix2 deprecated 20110604");
if (N != OriginStateIx2.size()) JSCerror("N != OriginStateIx2.size() in Set_Label_Internals_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 (!OriginStateIx2.includes(Ix2[i])) nexc_ref[0] += 1;
Vect<Vect<int> > Ix2old_ref(1);
Vect<Vect<int> > Ix2exc_ref(1);
Ix2old_ref[0] = Vect<int>(JSC::max(nexc_ref[0],1));
Ix2exc_ref[0] = Vect<int>(JSC::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, OriginStateIx2);
// Construct the Ix2_available vector: we give one more quantum number on left and right:
int navailable = 2 + (JSC::max(Ix2.max(), OriginStateIx2.max()) - JSC::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] = JSC::min(Ix2.min(), OriginStateIx2.min()) - 2 + 2*i;
// Now shift according to Ix2 of OriginState:
for (int j = 0; j < N; ++j) {
int i = 0;
while (Ix2_available[i] < OriginStateIx2ordered[j]) i++;
// We now have Ix2_available[i] == OriginStateIx2[j]. Shift all Ix2_available to the right of this by 2;
for (int i1 = i; i1 < navailable; ++i1) Ix2_available[i1] += 2;
index_first_hole_to_right[j] = i;
}
// Ix2_available and index_first_hole_to_right are now fully defined.
// Now set displacement vector:
displacement = Vect<int>(0, N);
// Set displacement vector from the Ix2:
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;
JSCerror("Going down too far in Set_Label_Internals...");
}
displacement[j]--;
}
}
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;
JSCerror("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)
{
//if (Ix2.min() < -13 || Ix2.max() > 13) return(false); // For testing with restricted Hilbert space
return(true);
}
void LiebLin_Bethe_State::Find_Rapidities (bool reset_rapidities)
{
// This function finds the rapidities of the eigenstate
lnnorm = -100.0; // sentinel value, recalculated if Newton method used in the last step of iteration.
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 << (*this) << endl;
return;
}
bool LiebLin_Bethe_State::Check_Rapidities()
{
bool nonan = true;
for (int j = 0; j < N; ++j) nonan *= !is_nan(lambdaoc[j]);
return nonan;
}
DP LiebLin_Bethe_State::String_delta()
{
return(0.0); // no strings (thus no deviations) in replusive LiebLin
}
bool LiebLin_Bethe_State::Check_Symmetry ()
{
// Checks whether the I's are symmetrically distributed.
bool symmetric_state = true;
Vect<int> Ix2check = Ix2;
Ix2check.QuickSort();
for (int alpha = 0; alpha <= N/2; ++alpha)
symmetric_state = symmetric_state && (Ix2check[alpha] == -Ix2check[N - 1 - alpha]);
return(symmetric_state);
}
void LiebLin_Bethe_State::Compute_lnnorm ()
{
if (lnnorm == -100.0) { // else Gaudin part already calculated by Newton method
SQMat_DP Gaudin_Red(N);
(*this).Build_Reduced_Gaudin_Matrix(Gaudin_Red);
lnnorm = real(lndet_LU_dstry(Gaudin_Red));
// 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));
}
return;
}
void LiebLin_Bethe_State::Compute_All (bool reset_rapidities) // solves BAE, computes E, K and lnnorm
{
(*this).Find_Rapidities (reset_rapidities);
if (conv == 1) {
(*this).Compute_Energy ();
(*this).Compute_Momentum ();
(*this).Compute_lnnorm ();
}
return;
}
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 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;
}
void LiebLin_Bethe_State::Iterate_BAE (DP damping)
{
// does one step of simple iterations
DP sumtheta = 0.0;
Vect_DP dlambdaoc (0.0, N);
for (int j = 0; j < N; ++j) {
sumtheta = 0.0;
for (int k = 0; k < N; ++k) sumtheta += atan((lambdaoc[j] - lambdaoc[k]));
sumtheta *= 2.0;
dlambdaoc[j] = damping * ((PI*Ix2[j] - sumtheta)/cxL - lambdaoc[j]);
}
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;
}
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.
Vect_DP dlambdaoc (0.0, N);
// Start by calculating S and dSdlambdaoc:
for (int j = 0; j < N; ++j) {
S[j] = 0.0;
for (int k = 0; k < N; ++k) S[j] += atan((lambdaoc[j] - lambdaoc[k]));
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);
dSdlambdaoc[j] *= 2.0/(PI * cxL);
dlambdaoc[j] = (PI*Ix2[j]/cxL - S[j] + lambdaoc[j] * dSdlambdaoc[j])/(1.0 + dSdlambdaoc[j]) - lambdaoc[j];
}
diffsq = 0.0;
for (int i = 0; i < N; ++i) {
lambdaoc[i] += damping * 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);
iter_Newton++;
return;
}
void LiebLin_Bethe_State::Iterate_BAE_Newton (DP damping)
{
// does one step of a Newton method on the rapidities...
Vect_DP RHSBAE (0.0, N); // contains RHS of BAEs
Vect_DP dlambdaoc (0.0, N); // contains delta lambdaoc computed from Newton's method
SQMat_DP Gaudin (0.0, N);
Vect_INT indx (N);
DP sumtheta = 0.0;
int atanintshift = 0; // for large |lambda|, use atan (lambda) = sgn(lambda) pi/2 - atan(1/lambda)
DP lambdahere = 0.0;
// Compute the RHS of the BAEs:
for (int j = 0; j < N; ++j) {
sumtheta = 0.0;
atanintshift = 0;
for (int k = 0; k < N; ++k)
if (j != k) { // otherwise 0
if (fabs(lambdahere = lambdaoc[j] - lambdaoc[k]) < 1.0) { // use straight atan
sumtheta += atan(lambdahere);
}
else { // for large rapidities, use dual form of atan, extracting pi/2 factors
atanintshift += sgn_DP(lambdahere);
sumtheta -= atan(1.0/lambdahere);
}
}
sumtheta *= 2.0;
//cout << j << "\t" << Ix2[j] << "\t" << atanintshift << endl;
RHSBAE[j] = cxL * lambdaoc[j] + sumtheta - PI*(Ix2[j] - atanintshift);
}
(*this).Build_Reduced_Gaudin_Matrix (Gaudin);
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;
// To prevent Newton from diverging, we limit the size of the rapidity changes.
// The leftmost and rightmost rapidities can grow by one order of magnitude per iteration step.
if (ordering_changed) { // We explicitly ensure that the ordering remains correct after the iteration step.
bool ordering_still_changed = false;
DP maxdlambdaoc = 0.0;
do {
ordering_still_changed = false;
if (dlambdaoc[0] < 0.0 && fabs(dlambdaoc[0]) > (maxdlambdaoc = 10.0*JSC::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*JSC::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 = JSC::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);
}
diffsq /= DP(N);
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));
}
return;
}
void LiebLin_Bethe_State::Compute_Energy()
{
E = 0.0;
for (int j = 0; j < N; ++j) E += lambdaoc[j] * lambdaoc[j];
E *= c_int * c_int;
}
void LiebLin_Bethe_State::Compute_Momentum()
{
iK = 0;
for (int j = 0; j < N; ++j) {
//cout << j << "\t" << iK << "\t" << Ix2[j] << endl;
iK += Ix2[j];
}
if (iK % 2) {
cout << Ix2 << endl;
cout << iK << "\t" << iK % 2 << endl;
JSCerror("Sum of Ix2 is not even: inconsistency.");
}
iK /= 2; // sum of Ix2 is guaranteed even.
K = 2.0 * iK * PI/L;
}
DP LiebLin_Bethe_State::Kernel (int a, int b)
{
return(2.0/(pow(lambdaoc[a] - lambdaoc[b], 2.0) + 1.0));
}
DP LiebLin_Bethe_State::Kernel (DP lambdaoc_ref)
{
return(2.0/(lambdaoc_ref * lambdaoc_ref + 1.0));
}
void LiebLin_Bethe_State::Build_Reduced_Gaudin_Matrix (SQMat<DP>& Gaudin_Red)
{
if (Gaudin_Red.size() != N) JSCerror("Passing matrix of wrong size in Build_Reduced_Gaudin_Matrix.");
DP sum_Kernel = 0.0;
for (int j = 0; j < N; ++j)
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 += Kernel (lambdaoc[j] - lambdaoc[kp]);
Gaudin_Red[j][k] = cxL + sum_Kernel;
}
else Gaudin_Red[j][k] = - Kernel (lambdaoc[j] - lambdaoc[k]);
}
return;
}
void LiebLin_Bethe_State::Build_Reduced_BEC_Quench_Gaudin_Matrix (SQMat<DP>& Gaudin_Red)
{
// Passing a matrix of dimension N/2
if (N % 2 != 0) JSCerror("Choose a state with even numer of particles please");
// Check Parity invariant
bool ck = true;
for (int j = 0; j < N/2; ++j){ if(Ix2[j] != - Ix2[N-j-1]) ck = false;}
if (!ck) JSCerror("Choose a parity invariant state please");
if (Gaudin_Red.size() != N/2) JSCerror("Passing matrix of wrong size in Build_Reduced_Gaudin_Matrix.");
DP sum_Kernel = 0.0;
for (int j = 0; j < N/2; ++j)
for (int k = 0; k < N/2; ++k) {
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]);
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]) );
}
return;
}
void LiebLin_Bethe_State::Annihilate_ph_pair (int ipart, int ihole, const Vect<int>& OriginStateIx2)
{
// 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]) JSCerror("Particle label too large in LiebLin_Bethe_State::Annihilate_ph_pair.");
if (ihole >= currentdata.nexc[0]) JSCerror("Hole label too large in LiebLin_Bethe_State::Annihilate_ph_pair.");
// Simply remove the given pair:
Vect<int> type_new = currentdata.type;
Vect<int> M_new = currentdata.M;
Vect<int> nexc_new = currentdata.nexc;
nexc_new[0] -= 1; // we drill one more particle-hole pair at level 0
int ntypespresent = 1; // only one type for LiebLin
Vect<Vect<int> > Ix2old_new(ntypespresent);
Vect<Vect<int> > Ix2exc_new(ntypespresent);
for (int it = 0; it < ntypespresent; ++it) Ix2old_new[it] = Vect<int>(JSC::max(nexc_new[it],1));
for (int it = 0; it < ntypespresent; ++it) Ix2exc_new[it] = Vect<int>(JSC::max(nexc_new[it],1));
// Copy earlier data in, leaving out ipart and ihole:
for (int it = 0; it < ntypespresent; ++it) {
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 ()
{
// For simplicity, we don't redo base_id, type_id, id.
Vect_INT Ix2buff = Ix2;
Vect_DP lambdaocbuff = lambdaoc;
for (int i = 0; i < N; ++i) Ix2[i] = -Ix2buff[N - 1 - i];
for (int i = 0; i < N; ++i) lambdaoc[i] = -lambdaocbuff[N - 1 - i];
iK = -iK;
K = -K;
}
std::ostream& operator<< (std::ostream& s, const LiebLin_Bethe_State& state)
{
s << endl << "******** State for c = " << state.c_int << " L = " << state.L << " N = " << state.N
<< " with label " << state.label << " ********" << endl;
s << "Ix2:" << endl;
for (int j = 0; j < state.N; ++j) s << state.Ix2[j] << " ";
s << endl << "lambdaocs:" << endl;
for (int j = 0; j < state.N; ++j) s << state.lambdaoc[j] << " ";
s << endl << "conv = " << state.conv << " iter_Newton = " << state.iter_Newton << endl;
s << "E = " << state.E << " iK = " << state.iK << " K = " << state.K << " lnnorm = " << state.lnnorm << endl;
return(s);
}
} // namespace JSC
+38
View File
@@ -0,0 +1,38 @@
/**********************************************************
This software is part of J.-S. Caux's ABACUS library.
Copyright (c).
-----------------------------------------------------------
File: src/LIEBLIN/LiebLin_Chem_Pot.cc
Purpose: calculates the chemical potential.
***********************************************************/
#include "JSC.h"
using namespace std;
using namespace JSC;
namespace JSC {
DP Chemical_Potential (LiebLin_Bethe_State& RefState)
{
// 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));
}
} // namespace JSC
@@ -0,0 +1,184 @@
/**********************************************************
This software is part of J.-S. Caux's ABACUS library.
Copyright (c).
-----------------------------------------------------------
File: src/LIEBLIN/LiebLin_Matrix_Element_Contrib.cc
Purpose: handles the generic call for a Lieb-Liniger matrix element contribution.
***********************************************************/
#include "JSC.h"
using namespace std;
using namespace JSC;
namespace JSC {
//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)
{
// 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.
bool fixed_iK = (iKmin == iKmax);
// Identify which matrix element is needed from the number of particles in Left and Right states:
DP ME = 0.0;
complex<DP> ME_CX = 0.0;
if (whichDSF == 'Z')
ME = LeftState.E - RefState.E;
else if (whichDSF == 'd' || whichDSF == '1')
ME = real(exp(ln_Density_ME (LeftState, RefState)));
else if (whichDSF == 'o')
ME = real(exp(ln_Psi_ME (LeftState, RefState)));
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
// 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
}
else if (whichDSF == 'C') { // BEC to finite c quench: overlap
ME_CX = exp(2.0* ln_Overlap_with_BEC (LeftState)); // overlap sq part
ME = 0.0;
}
else JSCerror("Wrong whichDSF in Compute_Matrix_Element_Contrib.");
if (is_nan(ME)) ME = (whichDSF == 'Z') ? 1.0e+200 : 0.0;
if (is_nan(norm(ME_CX))) ME_CX = -100.0;
// Print information to fstream:
if (LeftState.iK - RefState.iK >= iKmin && LeftState.iK - RefState.iK <= iKmax) {
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;
}
else if (whichDSF == 'q') {
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;
}
else if (whichDSF == '1') {
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)
DAT_outfile << endl << LeftState.E - RefState.E << "\t"
<< 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
if (fabs(real(ME_CX)) > 1.0e-100)
DAT_outfile << endl << LeftState.E - RefState.E << "\t"
<< 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;
}
} // if iKmin <= iK <= 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.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/JSC::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/JSC::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;
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')
data_value = abs(ME_CX * ME)/(1.0 + sqrt(fabs(LeftState.E - RefState.E)));
else if (whichDSF == 'C')
data_value = abs(ME_CX);
if (whichDSF == '1') // hard cutoff for nr, nl when calculating exponents
if (Momentum_Right_Excitations(LeftState) >= 30 || Momentum_Left_Excitations(LeftState) >= 30)
data_value = 0.0;
return(data_value);
}
} // namespace JSC
+929
View File
@@ -0,0 +1,929 @@
/**********************************************************
This software is part of J.-S. Caux's ABACUS library.
Copyright (c).
-----------------------------------------------------------
File: LiebLin_State_Ensemble.cc
Purpose: State ensembles for Lieb-Liniger
***********************************************************/
#include "JSC.h"
using namespace std;
using namespace JSC;
namespace JSC {
// Constructors:
LiebLin_Diagonal_State_Ensemble::LiebLin_Diagonal_State_Ensemble ()
: nstates(0), state(Vect<LiebLin_Bethe_State>(1)), weight(0.0, 1)
{
}
LiebLin_Diagonal_State_Ensemble::LiebLin_Diagonal_State_Ensemble (const LiebLin_Bethe_State& RefState, int nstates_req)
: 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) JSCerror("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)
{
int type_required = 3;
Vect<string> desc_label = Descendents (ActualState, OriginState, type_required);
if (desc_label.size() > 0) { // follow down recursively
LiebLin_Bethe_State ActualState_here = ActualState;
for (int idesc = 0; idesc < desc_label.size(); ++idesc) {
ActualState_here.Set_to_Label (desc_label[idesc], OriginState.Ix2);
// output data:
cout << *ndesc_ptr << "\t" << desc_label[idesc] << endl;
cout << "origin: " << OriginState.Ix2 << endl;
cout << "shiftd: " << ActualState_here.Ix2 << endl;
ActualState_here.Compute_All(false);
cout << "\t\t\t\t\t\t" << ActualState.E - OriginState.E << endl;
*ndesc_ptr += 1;
Generate_type_2_descendents (ActualState_here, ndesc_ptr, OriginState);
// do them mod st:
idesc += 6;
}
}
return;
}
//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)
{
//version with 4 states in ensemble
Root_Density x(rho.Npts, rho.lambdamax);
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
//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:
// 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);
LiebLin_Bethe_State rhostate(c_int, N, L);
nstates = 4;
state = Vect<LiebLin_Bethe_State>(rhostate, nstates);
weight = Vect<DP>(nstates);
weight[0] = 1.0/nstates;
weight[1] = 1.0/nstates;
weight[2] = 1.0/nstates;
weight[3] = 1.0/nstates;
int n_moves = 0;
bool change = true;
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
JSCerror("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]);
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
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++;
}
}
//cout << "\ti = " << i << "\tintegral = " << integral << "\tNfound = " << Nfound << endl;
}
//cout << endl;
//fix state[3] and state[4]
for(int i=0; i<N-1; ++i) {
if(state[2].Ix2[i] == state[2].Ix2[i+1]) {
if(state[2].Ix2[i] != state[2].Ix2[i-1] + 2) state[2].Ix2[i] -= 2;
else state[2].Ix2[i+1] += 2;
}
if(state[3].Ix2[i] == state[3].Ix2[i+1]) {
if(state[3].Ix2[i] != state[3].Ix2[i-1] + 2) state[3].Ix2[i] -= 2;
else state[3].Ix2[i+1] += 2;
}
}
bool all_Diff = true;
//check that all 'ns' states are different, we assume that Ix2 are ordered
for(int i=0; i<nstates; ++i)
for(int j=i+1; j<nstates; ++j) {
if(state[i].Ix2 == state[j].Ix2)
all_Diff = false;
}
if(!all_Diff) {
//check if the first two states are different
if(state[0].Ix2 == state[1].Ix2)
JSCerror("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;
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
JSCerror("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 JSCerror("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
// JSCerror("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 < JSC::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;
JSCerror("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 = JSC::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;
}
*/
//JSCerror("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;
//JSCerror("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) JSCerror("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 < JSC::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) JSCerror("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) {
nstates = rhs.nstates;
state = rhs.state;
weight = rhs.weight;
}
return(*this);
}
void LiebLin_Diagonal_State_Ensemble::Load (DP c_int, DP L, int N, const char* ensfile_Cstr)
{
ifstream infile(ensfile_Cstr);
// Count nr of lines in file:
string dummy;
int nrlines = 0;
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);
weight = Vect<DP> (0.0, nstates);
infile.open(ensfile_Cstr);
string dummylabel;
for (int ns = 0; ns < nstates; ++ns) {
infile >> weight[ns] >> dummylabel;
for (int i = 0; i < state[ns].N; ++i) infile >> state[ns].Ix2[i];
}
infile.close();
for (int ns = 0; ns < nstates; ++ns) {
state[ns].Set_Label_from_Ix2 (state[0].Ix2); // labels are ref to the saddle-point state
state[ns].Compute_All(true);
}
}
void LiebLin_Diagonal_State_Ensemble::Save (const char* ensfile_Cstr)
{
ofstream outfile;
outfile.open(ensfile_Cstr);
for (int ns = 0; ns < nstates; ++ns) {
if (ns > 0) outfile << endl;
outfile << setprecision(16) << weight[ns] << "\t" << state[ns].label << "\t";
for (int i = 0; i < state[ns].N; ++i) outfile << " " << state[ns].Ix2[i];
}
}
//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.
// Start as per Canonical_Saddle_Point_State:
// This function returns the discretized state minimizing the canonical free energy
// F = E - T S.
// This is obtained by rediscretizing the solution coming from TBA.
// Otherwise, return the discretized TBA saddle-point state:
LiebLin_TBA_Solution TBAsol = LiebLin_TBA_Solution_fixed_nbar (c_int, N/L, kBT, 1.0e-4, 100);
LiebLin_Diagonal_State_Ensemble ensemble(c_int, L, N, TBAsol.rho);
cout << "nbar: " << TBAsol.nbar << endl;
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);
}
} // namespace JSC
+302
View File
@@ -0,0 +1,302 @@
/**********************************************************
This software is part of J.-S. Caux's ABACUS library.
Copyright (c).
-----------------------------------------------------------
File: src/LIEBLIN/LiebLin_Sumrules.cc
Purpose: provides functions evaluating various sumrule factors
for Lieb-Liniger.
***********************************************************/
#include "JSC.h"
using namespace std;
using namespace JSC;
namespace JSC {
//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') {
// 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])
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;
else if (whichDSF == 'B') sumrule_factor = 1.0;
else if (whichDSF == 'C') sumrule_factor = 1.0;
else JSCerror("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);
}
//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;
else JSCerror("whichDSF option not consistent in Sumrule_Factor");
}
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)
{
ifstream infile;
infile.open(RAW_Cstr);
if(infile.fail()) {
cout << "Filename RAW_Cstr = " << RAW_Cstr << endl;
JSCerror("Could not open input file in Evaluate_F_Sumrule(LiebLin...).");
}
// 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);
DP Sum_MEsq = 0.0;
DP omega, ME;
int iK;
//int conv;
DP dev;
string label;
int nr, nl;
int nraw = 0;
while (infile.peek() != EOF) {
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;
}
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 * JSC::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 * JSC::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:
<< "\t" << ((i + iKmin <= 0 && -i < iKmax + 1) ?
0.5 * (Sum_omega_MEsq[i - iKmin] + Sum_omega_MEsq[-i - iKmin])
: Sum_omega_MEsq[i - iKmin])
* pow(RefState.L, 4.0)/(pow(2.0 * PI * JSC::max(abs(i), 1), 2.0) * RefState.N);
}
}
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);
}
}
outfile.close();
}
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;
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();
Evaluate_F_Sumrule (whichDSF, RefState, Chem_Pot, iKmin, iKmax, RAW_Cstr, FSR_Cstr);
}
// 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)
{
// We run through the data file to check the f sumrule at each positive momenta:
Vect_DP Sum_omega_MEsq (0.0, iKmax - iKmin + 1);
DP Sum_MEsq = 0.0;
DP omega, ME;
int iK;
//int conv;
DP dev;
string label;
int nr, nl;
// Read the weights from the ensembles file:
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();
ensemble.Load(c_int, L, N, ensfile_Cstr);
for (int ns = 0; ns < ensemble.nstates; ++ns) {
// 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);
string prefix = filenameprefix.str();
stringstream RAW_stringstream; string RAW_string;
RAW_stringstream << prefix << ".raw";
RAW_string = RAW_stringstream.str(); const char* RAW_Cstr = RAW_string.c_str();
ifstream infile;
infile.open(RAW_Cstr);
if(infile.fail()) {
cout << "Filename RAW_Cstr = " << RAW_Cstr << endl;
JSCerror("Could not open input file in Evaluate_F_Sumrule(LiebLin...).");
}
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;
}
infile.close();
}
LiebLin_Bethe_State RefState = ensemble.state[0]; // to use the code below, which comes from earlier Evaluate_F_Sumrule
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 * JSC::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 * JSC::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:
<< "\t" << ((i + iKmin <= 0 && -i < iKmax + 1) ?
0.5 * (Sum_omega_MEsq[i - iKmin] + Sum_omega_MEsq[-i - iKmin])
: Sum_omega_MEsq[i - iKmin])
* pow(RefState.L, 4.0)/(pow(2.0 * PI * JSC::max(abs(i), 1), 2.0) * RefState.N);
}
}
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);
}
}
outfile.close();
}
} // namespace JSC
+536
View File
@@ -0,0 +1,536 @@
/**********************************************************
This software is part of J.-S. Caux's ABACUS library.
Copyright (c).
-----------------------------------------------------------
File: LiebLin_Tgt0.cc
Purpose: Finite temperature correlations for Lieb-Liniger
***********************************************************/
#include "JSC.h"
using namespace std;
using namespace JSC;
namespace JSC {
/*
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 = JSC::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)
{
// 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.
// 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
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;
JSCerror("Counting q numbers incorrectly in Entropy.");
}
// 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;
int np;
for (int i = 0; i < nrIs - Delta; ++i) {
np = 0;
for (int iD = 0; iD < Delta; ++iD) if (occupancy[i + iD] == 1) np++;
entropy += oneoverDeltalnchoose[np];
}
return(entropy);
}
DP Entropy (LiebLin_Bethe_State& RefState, int Delta)
{
// Perform an average of entropies for regulators from Delta to 2Delta:
DP entropysum = 0.0;
for (int ie = 0; ie < Delta; ++ie) entropysum += Entropy_Fixed_Delta (RefState, Delta + ie);
return(entropysum/Delta);
}
DP Entropy (LiebLin_Bethe_State& RefState)
{
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 *= 1.0/(PI * delta * RefState.L);
return(answer);
}
DP rho_of_lambdaoc_2 (LiebLin_Bethe_State& RefState, DP lambdaoc, DP delta)
{
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);
return(answer);
}
// Better implementation: making use of rediscretized TBA state.
LiebLin_Bethe_State Canonical_Saddle_Point_State (DP c_int, DP L, int N, DP kBT)
{
// This function returns the discretized state minimizing the canonical free energy
// F = E - T S.
// This is obtained by rediscretizing the solution coming from TBA.
// ASSUMPTIONS:
// Periodic boundary conditions (the state which is output is forced to be symmetric Ix2 == -Ix2).
// For zero temperature, return the ground state:
if (fabs(kBT) < 1.0e-4) return(LiebLin_Bethe_State(c_int, L, N));
// Otherwise, return the discretized TBA saddle-point state:
LiebLin_TBA_Solution TBAsol = LiebLin_TBA_Solution_fixed_nbar (c_int, N/L, kBT, 1.0e-4, JSC::max(N/10, 10));
LiebLin_Bethe_State spstate = Discretized_LiebLin_Bethe_State (c_int, L, N, TBAsol.rho);
// Explicitly symmetrize:
for (int i = 0; i < N/2; ++i) spstate.Ix2[i] = -spstate.Ix2[N-1-i];
spstate.Compute_All(false);
return(spstate);
}
LiebLin_Bethe_State Add_Particle_at_Center (const LiebLin_Bethe_State& RefState)
{
LiebLin_Bethe_State ReturnState (RefState.c_int, RefState.L, RefState.N + 1);
// Add a quantum number in middle (explicitly: to right of index N/2)
// and shift quantum numbers by half-integer away from added one:
ReturnState.Ix2[RefState.N/2] = RefState.Ix2[RefState.N/2] - 1;
for (int i = 0; i < RefState.N+1; ++i)
ReturnState.Ix2[i + (i >= RefState.N/2)] = RefState.Ix2[i] - 1 + 2*(i >= RefState.N/2);
return(ReturnState);
}
LiebLin_Bethe_State Remove_Particle_at_Center (const LiebLin_Bethe_State& RefState)
{
LiebLin_Bethe_State ReturnState (RefState.c_int, RefState.L, RefState.N - 1);
// Remove midmost and shift quantum numbers by half-integer towards removed one:
for (int i = 0; i < RefState.N-1; ++i)
ReturnState.Ix2[i] = RefState.Ix2[i + (i >= RefState.N/2)] + 1 - 2*(i >= RefState.N/2);
return(ReturnState);
}
} // namespace JSC
+117
View File
@@ -0,0 +1,117 @@
/**********************************************************
This software is part of J.-S. Caux's ABACUS library.
Copyright (c).
-----------------------------------------------------------
File: LiebLin_Twisted_ln_Overlap.cc
Purpose: Calculates Nikita Slavnov's determinant, case RHS is Bethe
and LHS is twisted Bethe
***********************************************************/
#include "JSC.h"
using namespace std;
using namespace JSC;
namespace JSC {
complex<DP> Kernel_Twisted (complex<DP> expbeta, complex<DP> lambdaoc)
{
return(1.0/(lambdaoc + II) - expbeta/(lambdaoc - II));
}
complex<DP> Kernel_Twisted (complex<DP> expbeta, DP lambdaoc)
{
return(1.0/(lambdaoc + II) - expbeta/(lambdaoc - II));
}
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> Fn_V_Nikita (int j, int sign, Vect<complex<DP> >& lstate_lambdaoc, LiebLin_Bethe_State& rstate)
{
// To match with Nikita's new conventions
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)
{
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)
{
// 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_Nikita (0.0, rstate.N); // contains V^+_j
Vect_CX Vminus_Nikita (0.0, rstate.N); // contains V^-_j
Vect_CX Fn_Prod (0.0, rstate.N); // product_{m\neq j} (\mu_m - \lambda_j)/(\lambda_m - \lambda_j)
Vect_CX rKern (0.0, rstate.N); // K(lambda_j - lambda_p)
int p = 0;
complex<DP> Kout = lstate_lambdaoc.sum() - rstate.K;
for (int a = 0; a < rstate.N; ++a) {
Vplus_Nikita[a] = Fn_V_Nikita (a, 1, lstate_lambdaoc, rstate);
Vminus_Nikita[a] = Fn_V_Nikita (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);
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]))
* 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);
complex<DP> ln_prod_V = 0.0;
for (int a = 0; a < rstate.N; ++a) ln_prod_V += log(expbeta * Vplus_Nikita[a]/Vminus_Nikita[a] - 1.0);
ln_prod_V -= 0.5 * rstate.N * log(expbeta);
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((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));
}
}
+52
View File
@@ -0,0 +1,52 @@
/**********************************************************
This software is part of J.-S. Caux's ABACUS library.
Copyright (c).
-----------------------------------------------------------
File: LiebLin_Gaudin_lnnorm.cc
Purpose: calculates the Gaudin norm of a vector of arbitrary
complex rapidities
***********************************************************/
#include "JSC.h"
using namespace std;
using namespace JSC;
namespace JSC {
DP LiebLin_Twisted_lnnorm (Vect<complex<DP> >& lambdaoc, double cxL)
{
// Calculates the lnnorm of an eigenstate of the twisted transfer matrix
// so Gaudin can be used.
int N = lambdaoc.size();
SQMat<complex<DP> > Gaudin(N);
complex<DP> sum_Kernel = 0.0;
for (int j = 0; j < N; ++j)
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);
Gaudin[j][k] = cxL + sum_Kernel;
}
else Gaudin[j][k] = - 2.0/((lambdaoc[j] - lambdaoc[k]) * (lambdaoc[j] - lambdaoc[k]) + 1.0);
}
DP lnnorm = real(lndet_LU_CX_dstry(Gaudin));
// 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/norm(lambdaoc[j] - lambdaoc[k]));
return(lnnorm);
}
} // namespace JSC
+108
View File
@@ -0,0 +1,108 @@
/**********************************************************
This software is part of J.-S. Caux's ABACUS library.
Copyright (c).
-----------------------------------------------------------
File: LiebLin_Utils.cc
Purpose: Utilities for Lieb-Liniger gas
***********************************************************/
#include "JSC.h"
namespace JSC {
DP LiebLin_dE0_dc (DP c_int, DP L, int N)
{
LiebLin_Bethe_State groundstate (c_int, L, N);
groundstate.Compute_All(true);
DP dc_int = 1.0e-5 * c_int;
LiebLin_Bethe_State groundstate_2 (c_int + dc_int, L, N);
groundstate_2.Compute_All(true);
return((groundstate_2.E - groundstate.E)/dc_int);
}
DP LiebLin_vs (DP c_int, DP L, int N)
{
LiebLin_Bethe_State gstate (c_int, L, N);
gstate.Compute_All(true);
DP Egs = gstate.E;
gstate.Ix2[N-1] += 2;
gstate.Compute_All(false);
return((gstate.E - Egs) * L/twoPI);
}
DP LiebLin_Dressed_Charge_N (DP c_int, DP L, int N)
{
LiebLin_Bethe_State gstate(c_int, L, N);
gstate.Compute_All(true);
return(twoPI/(c_int * L * (gstate.lambdaoc[N-1] - gstate.lambdaoc[N-2]))); // lambda in units of c within code
}
// For computation of threshold exponents:
int Momentum_Right_Excitations (LiebLin_Bethe_State& ScanState)
{
// Calculates the momentum of the excitations on the right of Fermi
// surface, discarding the rightmost excitation.
int nr = 0;
for (int i = ScanState.N - 2; i >= ScanState.N/2; --i)
if (ScanState.Ix2[i] >= 0) nr += (ScanState.Ix2[i] + ScanState.N - 1 - 2*i)/2;
return(nr);
}
int Momentum_Left_Excitations (LiebLin_Bethe_State& ScanState)
{
// Calculates the momentum of the excitations on the left of Fermi
// surface, discarding the rightmost excitation.
int nl = 0;
for (int i = 0; i < ScanState.N/2; ++i)
if (ScanState.Ix2[i] < 0) nl -= (ScanState.Ix2[i] + ScanState.N - 1 - 2*i)/2;
return(nl);
}
DP ln_Overlap_with_BEC (LiebLin_Bethe_State& lambda) // Note: factorial approximated with Lanczos
{
int N = lambda.N;
int L = lambda.L;
DP c_int = lambda.c_int;
// The overlap identically vanishes if the state is not parity invariant:
if (!lambda.Check_Symmetry()) return(-300.0);
SQMat_DP Gaudin( N);
SQMat_DP Gaudin_Quench( N/2);
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 ]) ;
//cout << ln_prefactor << endl;
return (ln_prefactor + real(lndet_LU_dstry(Gaudin_Quench)) - 0.5 * real(lndet_LU_dstry(Gaudin)));
}
}
+186
View File
@@ -0,0 +1,186 @@
/**********************************************************
This software is part of J.-S. Caux's ABACUS library.
Copyright (c).
-----------------------------------------------------------
File: LiebLin_ln_Overlap.cc
Purpose: Calculates Nikita Slavnov's determinant, case RHS is Bethe
and LHS is arbitrary
***********************************************************/
#include "JSC.h"
using namespace std;
using namespace JSC;
namespace JSC {
/*
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)
{
Vect<complex<DP> > lstate_lambdaoc_CX(rstate.N);
for (int i = 0; i < rstate.N; ++i) lstate_lambdaoc_CX[i] = complex<DP>(lstate_lambdaoc[i]);
return(LiebLin_ln_Overlap(lstate_lambdaoc_CX, lstate_lnnorm, rstate));
}
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
// IMPORTANT ASSUMPTIONS:
// The length over which the overlap is calculated is that in rstate
if (lstate_lambdaoc.size() != rstate.N) {
cout << "Caution: calling overlap of states with difference charges. Are you sure that's what you want ?" << endl;
return(0.0);
}
// \mu are rstate rapidities, \lambda are from lstate (not BE)
Vect_CX ln_prod_plus(0.0, rstate.N); // contains \prod_a (\mu_a - lambdaoc_k + II)
Vect_CX ln_prod_minus(0.0, rstate.N); // contains \prod_a (\mu_a - \lambdaoc_k - II)
Vect_CX ln_prod_ll_plus (0.0, rstate.N); // contains \prod_{a \neq k} (\lambdaoc_a - \lambdaoc_k + II)
Vect_CX ln_prod_ll_minus (0.0, rstate.N); // contains \prod_{a \neq k} (\lambdaoc_a - \lambdaoc_k - II)
for (int j = 0; j < rstate.N; ++j)
for (int k = 0; k < rstate.N; ++k) {
ln_prod_plus[k] += log(rstate.lambdaoc[j] - lstate_lambdaoc[k] + II);
ln_prod_minus[k] += log(rstate.lambdaoc[j] - lstate_lambdaoc[k] - II);
if (j != k) {
ln_prod_ll_plus[k] += log(lstate_lambdaoc[j] - lstate_lambdaoc[k] + II);
ln_prod_ll_minus[k] += log(lstate_lambdaoc[j] - lstate_lambdaoc[k] - II);
}
}
// Build the matrix:
SQMat_CX Omega (0.0, rstate.N);
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();
complex<DP> ln_prod_mu = 0.0;
complex<DP> ln_prod_lambdaoc = 0.0;
complex<DP> ln_prod_plusminus = 0.0;
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]);
}
for (int j = 0; j < rstate.N; ++j)
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;
//JSCerror("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));
}
/*
// 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 JSC
+97
View File
@@ -0,0 +1,97 @@
/**********************************************************
This software is part of J.-S. Caux's ABACUS library.
Copyright (c).
-----------------------------------------------------------
File: ln_Density_ME.cc
Purpose: Computes the density operator \rho(x = 0) matrix element
***********************************************************/
#include "JSC.h"
using namespace std;
using namespace JSC;
namespace JSC {
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);
}
complex<DP> ln_Density_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 = 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))
//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 Kout = lstate.K - rstate.K;
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]));
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]);
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 * Kout) + ln_ddalpha_sigma - 0.5 * (lstate.lnnorm + rstate.lnnorm));
}
}
+81
View File
@@ -0,0 +1,81 @@
/**********************************************************
This software is part of J.-S. Caux's ABACUS library.
Copyright (c).
-----------------------------------------------------------
File: ln_Psi_ME.cc
Purpose: Computes the matrix element of \Psi (x = 0)
***********************************************************/
#include "JSC.h"
using namespace std;
using namespace JSC;
namespace JSC {
complex<DP> Fn_V_Psi (int j, LiebLin_Bethe_State& lstate, LiebLin_Bethe_State& rstate)
{
// lstate has one particle less than rstate
complex<DP> result_num = 1.0;
complex<DP> result_den = 1.0;
for (int m = 0; m < lstate.N; ++m)
result_num *= (lstate.lambdaoc[m] - rstate.lambdaoc[j] + II);
for (int m = 0; m < rstate.N; ++m)
result_den *= (rstate.lambdaoc[m] - rstate.lambdaoc[j] + II);
return(result_num/result_den);
}
complex<DP> ln_Psi_ME (LiebLin_Bethe_State& lstate, LiebLin_Bethe_State& rstate)
{
// Computes the log of the annihilation operator matrix element between lstate and rstate.
if (lstate.N + 1 != rstate.N) JSCerror("Wrong particle numbers in left and right states for Psi FF.");
SQMat_DP U_Psi (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} (\mu_m - \lambdaoc_j)/product_{m neq j} (\lambdaoc_m - \lambdaoc_j)
Vect_DP rKern (0.0, lstate.N); // K(lambdaoc_j - lambdaoc_(p == N))
int p = rstate.N - 1;
for (int a = 0; a < lstate.N; ++a) {
Vplus[a] = Fn_V_Psi (a, lstate, rstate);
Fn_Prod[a] = (lstate.lambdaoc[a] - rstate.lambdaoc[a])/(rstate.lambdaoc[rstate.N - 1] - rstate.lambdaoc[a]);
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]);
rKern[a] = rstate.Kernel (a, p);
}
for (int a = 0; a < lstate.N; ++a)
for (int b = 0; b < lstate.N; ++b)
U_Psi[a][b] = (a == b ? 2.0 * imag(Vplus[a]) : 0.0) + Fn_Prod[a] * (rstate.Kernel(a,b) - rKern[b]);
complex<DP> ln_det_U_Psi = lndet_LU_dstry(U_Psi);
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);
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));
}
}
+193
View File
@@ -0,0 +1,193 @@
/**********************************************************
This software is part of J.-S. Caux's ABACUS library.
Copyright (c).
-----------------------------------------------------------
File: src/LIEBLIN/ln_g2_ME.cc
Purpose: provides the matrix element of the second density moment g2(x = 0)
NOTE: based on Lorenzo Piroli's expression of the matrix element
***********************************************************/
#include "JSC.h"
using namespace std;
using namespace JSC;
namespace JSC {
/*
complex<DP> ln_g2_ME_old_jacopo (LiebLin_Bethe_State& mu, LiebLin_Bethe_State& lambda)
{
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 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));
}
*/
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_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));
}
} // namespace JSC
+47
View File
@@ -0,0 +1,47 @@
#include "JSC.h"
using namespace std;
void JSC::balanc(SQMat_DP& a)
{
// Balancing of nonsymmetric matrix. See NR p.489.
const DP RADIX = numeric_limits<DP>::radix;
int i, j, last = 0;
DP s, r, g, f, c, sqrdx;
int n = a.size();
sqrdx = RADIX * RADIX;
while (last == 0) {
last = 1;
for (i = 0; i < n; i++) {
r = c = 0.0;
for (j = 0; j < n; j++)
if (j != i) {
c += fabs(a[j][i]);
r += fabs(a[i][j]);
}
if (c != 0.0 && r != 0.0) {
g = r/RADIX;
f = 1.0;
s = c + r;
while (c < g) {
f *= RADIX;
c *= sqrdx;
}
g = r * RADIX;
while (c > g) {
f /= RADIX;
c /= sqrdx;
}
if ((c + r)/f < 0.95 * s) {
last = 0;
g = 1.0/f;
for (j = 0; j < n; j++) a[i][j] *= g;
for (j = 0; j < n; j++) a[j][i] *= f;
}
}
}
}
}
+20
View File
@@ -0,0 +1,20 @@
#include "JSC.h"
using namespace std;
DP JSC::det_LU (SQMat_DP a)
{
// Returns the determinant of matrix a, through LU decomposition
// In order to preserve the original matrix, it is copied first.
Vect_INT indx(a.size());
SQMat_DP mat = a;
DP d;
JSC::ludcmp (mat, indx, d);
for (int j = 0; j < mat.size(); j++) d *= mat[j][j];
return(d);
}
+21
View File
@@ -0,0 +1,21 @@
#include "JSC.h"
using namespace std;
complex<DP> JSC::det_LU_CX (SQMat_CX a)
{
// Returns the determinant of matrix a, through LU decomposition
Vect_INT indx(a.size());
SQMat_CX mat = a;
DP d;
JSC::ludcmp_CX (mat, indx, d);
complex<DP> dd = d;
for (int j = 0; j < mat.size(); j++) dd *= mat[j][j];
return(dd);
}
+28
View File
@@ -0,0 +1,28 @@
#include "JSC.h"
void JSC::eigsrt (Vect_DP& d, SQMat_DP& v)
{
// This puts the eigenvalues in INCREASING order, not decreasing as in NR !
int i, j, k;
DP p;
int n = d.size();
for (i = 0; i < n-1; i++) {
p = d[k=i];
for (j = i; j < n; j++) {
if (d[j] <= p) {
p = d[k = j];
}
}
if (k != i) {
d[k] = d[i];
d[i] = p;
for (j = 0; j < n; j++) {
p = v[j][i];
v[j][i] = v[j][k];
v[j][k] = p;
}
}
}
}
+36
View File
@@ -0,0 +1,36 @@
#include "JSC.h"
using namespace std;
void JSC::elmhes(SQMat_DP& a)
{
// Reduction to Hessenberg form by elimination method. NR p.490
int i, j, m;
DP y, x;
int n = a.size();
for (m = 1; m < n-1; m++) {
x = 0.0;
i = m;
for (j = m; j < n; j++) {
if (fabs(a[j][m-1]) > fabs(x)) {
x = a[j][m-1];
i = j;
}
}
if (i != m) {
for (j = m - 1; j < n; j++) SWAP(a[i][j], a[m][j]);
for (j = 0; j < n; j++) SWAP(a[j][i], a[j][m]);
}
if (x != 0.0) {
for (i = m + 1; i < n; i++) {
if ((y = a[i][m-1]) != 0.0) {
y /= x;
a[i][m-1] = y;
for (j = m; j < n; j++) a[i][j] -= y*a[m][j];
for (j = 0; j < n; j++) a[j][m] += y*a[j][i];
}
}
}
}
}
+56
View File
@@ -0,0 +1,56 @@
#include "JSC.h"
using namespace std;
void JSC::gaussj (SQMat_DP& a, SQMat_DP& b)
{
int i, j, k, l, ll;
int icol = 0;
int irow = 0;
DP big, dum, pivinv;
int n = a.size();
int m = b.size();
Vect_INT indxc(n), indxr(n), ipiv(n);
for (j = 0; j < n; j++) ipiv[j] = 0;
for (i = 0; i < n; i++) {
big = 0.0;
for (j = 0; j < n; j++)
if (ipiv[j] != 1)
for (k = 0; k < n; k++) {
if (ipiv[k] == 0) {
if (fabs(a[j][k]) >= big) {
big = fabs(a[j][k]);
irow = j;
icol = k;
}
}
}
++(ipiv[icol]);
if (irow != icol) {
for (l = 0; l < n; l++) SWAP (a[irow][l], a[icol][l]);
for (l = 0; l < m; l++) SWAP (b[irow][l], b[icol][l]);
}
indxr[i] = irow;
indxc[i] = icol;
if (a[icol][icol] == 0.0) JSCerror("gaussj: singular matrix");
pivinv = 1.0/a[icol][icol];
a[icol][icol] = 1.0;
for (l = 0; l < n; l++) a[icol][l] *= pivinv;
for (l = 0; l < m; l++) b[icol][l] *= pivinv;
for (ll = 0; ll < n; ll++)
if (ll != icol) {
dum = a[ll][icol];
a[ll][icol] = 0.0;
for (l = 0; l < n; l++) a[ll][l] -= a[icol][l] * dum;
for (l = 0; l < m; l++) b[ll][l] -= b[icol][l] * dum;
}
}
for (l = n - 1; l >= 0; l--) {
if (indxr[l] != indxc[l])
for (k = 0; k < n; k++)
SWAP (a[k][indxr[l]], a[k][indxc[l]]);
}
}

Some files were not shown because too many files have changed in this diff Show More