296 lines
12 KiB
C++
296 lines
12 KiB
C++
/**********************************************************
|
|
|
|
This software is part of J.-S. Caux's ABACUS library.
|
|
|
|
Copyright (c) J.-S. Caux.
|
|
|
|
-----------------------------------------------------------
|
|
|
|
File: src/HEIS/Heis_Matrix_Element_Contrib.cc
|
|
|
|
Purpose: handles the generic call for a matrix element.
|
|
|
|
***********************************************************/
|
|
|
|
#include "ABACUS.h"
|
|
|
|
using namespace std;
|
|
using namespace ABACUS;
|
|
|
|
namespace ABACUS {
|
|
|
|
DP Compute_Matrix_Element_Contrib (char whichDSF, int iKmin, int iKmax, 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)
|
|
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 ABACUSerror("Wrong whichDSF in Compute_Matrix_Element_Contrib.");
|
|
|
|
if (is_nan(ME)) 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;
|
|
|
|
DAT_outfile << setprecision(16);
|
|
// 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"
|
|
<< 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"
|
|
<< setprecision(3) << LeftState.dev << "\t"
|
|
<< LeftState.label;
|
|
}
|
|
} // if iKmin <= iKout <= iKmax
|
|
|
|
// Calculate and return the data_value:
|
|
DP data_value = ME * ME;
|
|
|
|
if (whichDSF == 'Z') // use 1/(1 + omega)
|
|
data_value = 1.0/(1.0 + LeftState.E - 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, 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)
|
|
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 (RightState, LeftState);
|
|
else ABACUSerror("Wrong whichDSF in Compute_Matrix_Element_Contrib.");
|
|
|
|
if (is_nan(ME)) ME = 0.0;
|
|
if (is_nan(norm(ME_CX))) ME_CX = -100.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;
|
|
|
|
DAT_outfile << setprecision(16);
|
|
// 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"
|
|
<< 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"
|
|
<< 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"
|
|
<< setprecision(3) << LeftState.dev << "\t"
|
|
<< LeftState.label;
|
|
}
|
|
} // if iKmin <= iKout <= iKmax
|
|
|
|
// Calculate and return the data_value:
|
|
DP data_value = ME * ME;
|
|
if (whichDSF == 'Z') // use 1/(1 + omega)
|
|
data_value = 1.0/(1.0 + LeftState.E - 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, 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.
|
|
|
|
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) {
|
|
|
|
// 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 && 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)
|
|
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 ABACUSerror("Wrong whichDSF in Compute_Matrix_Element_Contrib.");
|
|
|
|
if (is_nan(ME)) ME = 0.0;
|
|
|
|
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;
|
|
|
|
DAT_outfile << setprecision(16);
|
|
// 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"
|
|
<< 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"
|
|
<< setprecision(3) << LeftState.dev << "\t"
|
|
<< LeftState.label;
|
|
}
|
|
} // if iKmin <= iKout <= iKmax
|
|
|
|
// Calculate and return the data_value:
|
|
DP data_value = ME * ME;
|
|
if (whichDSF == 'Z') // use 1/(1 + omega)
|
|
data_value = 1.0/(1.0 + LeftState.E - 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 ABACUS
|