140 řádky
3.5 KiB
C++
140 řádky
3.5 KiB
C++
/**********************************************************
|
|
|
|
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);
|
|
}
|
|
|
|
}
|