ABACUS/src/HEIS/Heis_Matrix_Element_Contrib.cc

377 righe
17 KiB
C++

/**********************************************************
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