/********************************************************** This software is part of J.-S. Caux's ABACUS library. Copyright (c) J.-S. Caux. ----------------------------------------------------------- File: src/HEIS/Heis_Chem_Pot.cc Purpose: calculates the chemical potential. ***********************************************************/ #include "ABACUS.h" using namespace std; namespace ABACUS { 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) ABACUSerror("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 ABACUSerror("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; ABACUSerror("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) ABACUSerror("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 } }