You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

ODSLF_XXZ_Bethe_State.cc 17KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509
  1. /**********************************************************
  2. This software is part of J.-S. Caux's ABACUS library.
  3. Copyright (c) J.-S. Caux.
  4. -----------------------------------------------------------
  5. File: src/ODSLF/ODSLF_XXZ_Bethe_State.cc
  6. Purpose: defines Bethe states for 1d spinless fermions.
  7. ***********************************************************/
  8. #include "ABACUS.h"
  9. using namespace std;
  10. namespace ABACUS {
  11. // Function prototypes
  12. inline DP ODSLF_fbar_XXZ (DP lambda, int par, DP tannzetaover2);
  13. DP ODSLF_Theta_XXZ (DP lambda, int nj, int nk, int parj, int park, DP* tannzetaover2);
  14. DP ODSLF_hbar_XXZ (DP lambda, int n, int par, DP* si_n_anis_over_2);
  15. DP ODSLF_ddlambda_Theta_XXZ (DP lambda, int nj, int nk, int parj, int park, DP* si_n_anis_over_2);
  16. //***************************************************************************************************
  17. // Function definitions: class ODSLF_XXZ_Bethe_State
  18. ODSLF_XXZ_Bethe_State::ODSLF_XXZ_Bethe_State ()
  19. : ODSLF_Bethe_State(), sinhlambda(ODSLF_Lambda(chain, 1)), coshlambda(ODSLF_Lambda(chain, 1)),
  20. tanhlambda(ODSLF_Lambda(chain, 1))
  21. {};
  22. ODSLF_XXZ_Bethe_State::ODSLF_XXZ_Bethe_State (const ODSLF_XXZ_Bethe_State& RefState) // copy constructor
  23. : ODSLF_Bethe_State(RefState), sinhlambda(ODSLF_Lambda(RefState.chain, RefState.base)),
  24. coshlambda(ODSLF_Lambda(RefState.chain, RefState.base)),
  25. tanhlambda(ODSLF_Lambda(RefState.chain, RefState.base))
  26. {
  27. // copy arrays into new ones
  28. //cout << "Calling XXZ state copy constructor." << endl;
  29. for (int j = 0; j < RefState.chain.Nstrings; ++j) {
  30. for (int alpha = 0; alpha < RefState.base[j]; ++j) {
  31. sinhlambda[j][alpha] = RefState.sinhlambda[j][alpha];
  32. coshlambda[j][alpha] = RefState.coshlambda[j][alpha];
  33. tanhlambda[j][alpha] = RefState.tanhlambda[j][alpha];
  34. }
  35. }
  36. //cout << "Done calling XXZ state copy constructor." << endl;
  37. }
  38. ODSLF_XXZ_Bethe_State::ODSLF_XXZ_Bethe_State (const Heis_Chain& RefChain, int M)
  39. : ODSLF_Bethe_State(RefChain, M),
  40. sinhlambda(ODSLF_Lambda(RefChain, M)), coshlambda(ODSLF_Lambda(RefChain, M)), tanhlambda(ODSLF_Lambda(RefChain, M))
  41. {
  42. //cout << "Here in XXZ BS constructor." << endl;
  43. //cout << (*this).lambda[0][0] << endl;
  44. //cout << "OK" << endl;
  45. if ((RefChain.Delta <= -1.0) || (RefChain.Delta >= 1.0))
  46. ABACUSerror("Delta out of range in ODSLF_XXZ_Bethe_State constructor");
  47. }
  48. ODSLF_XXZ_Bethe_State::ODSLF_XXZ_Bethe_State (const Heis_Chain& RefChain, const ODSLF_Base& RefBase)
  49. : ODSLF_Bethe_State(RefChain, RefBase),
  50. sinhlambda(ODSLF_Lambda(RefChain, RefBase)), coshlambda(ODSLF_Lambda(RefChain, RefBase)),
  51. tanhlambda(ODSLF_Lambda(RefChain, RefBase))
  52. {
  53. if ((RefChain.Delta <= -1.0) || (RefChain.Delta >= 1.0))
  54. ABACUSerror("Delta out of range in ODSLF_XXZ_Bethe_State constructor");
  55. }
  56. ODSLF_XXZ_Bethe_State::ODSLF_XXZ_Bethe_State (const Heis_Chain& RefChain,
  57. long long int base_id_ref, long long int type_id_ref)
  58. : ODSLF_Bethe_State(RefChain, base_id_ref, type_id_ref),
  59. sinhlambda(ODSLF_Lambda(chain, base)), coshlambda(ODSLF_Lambda(chain, base)), tanhlambda(ODSLF_Lambda(chain, base))
  60. {
  61. if ((RefChain.Delta <= -1.0) || (RefChain.Delta >= 1.0))
  62. ABACUSerror("Delta out of range in ODSLF_XXZ_Bethe_State constructor");
  63. }
  64. ODSLF_XXZ_Bethe_State& ODSLF_XXZ_Bethe_State::operator= (const ODSLF_XXZ_Bethe_State& RefState)
  65. {
  66. if (this != &RefState) {
  67. chain = RefState.chain;
  68. base = RefState.base;
  69. offsets = RefState.offsets;
  70. Ix2 = RefState.Ix2;
  71. lambda = RefState.lambda;
  72. BE = RefState.BE;
  73. diffsq = RefState.diffsq;
  74. conv = RefState.conv;
  75. iter = RefState.iter;
  76. iter_Newton = RefState.iter_Newton;
  77. E = RefState.E;
  78. iK = RefState.iK;
  79. K = RefState.K;
  80. lnnorm = RefState.lnnorm;
  81. base_id = RefState.base_id;
  82. type_id = RefState.type_id;
  83. id = RefState.id;
  84. maxid = RefState.maxid;
  85. nparticles = RefState.nparticles;
  86. sinhlambda = RefState.sinhlambda;
  87. coshlambda = RefState.coshlambda;
  88. tanhlambda = RefState.tanhlambda;
  89. }
  90. return(*this);
  91. }
  92. // Member functions
  93. void ODSLF_XXZ_Bethe_State::Set_Free_lambdas()
  94. {
  95. // Sets all the rapidities to the solutions of the BAEs without scattering terms
  96. for (int i = 0; i < chain.Nstrings; ++i) {
  97. for (int alpha = 0; alpha < base[i]; ++alpha) {
  98. if(chain.par[i] == 1)
  99. lambda[i][alpha] = (tan(chain.Str_L[i] * 0.5 * chain.anis) * tan(PI * 0.5 * Ix2[i][alpha]/chain.Nsites));
  100. else if (chain.par[i] == -1)
  101. lambda[i][alpha] = (-tan((PI * 0.5 * Ix2[i][alpha])/chain.Nsites)/tan(chain.Str_L[i] * 0.5 * chain.anis));
  102. else ABACUSerror("Invalid parities in Set_Free_lambdas.");
  103. }
  104. }
  105. return;
  106. }
  107. void ODSLF_XXZ_Bethe_State::Compute_sinhlambda()
  108. {
  109. for (int j = 0; j < chain.Nstrings; ++j) {
  110. for (int alpha = 0; alpha < base[j]; ++alpha) sinhlambda[j][alpha] = sinh(lambda[j][alpha]);
  111. }
  112. return;
  113. }
  114. void ODSLF_XXZ_Bethe_State::Compute_coshlambda()
  115. {
  116. for (int j = 0; j < chain.Nstrings; ++j) {
  117. for (int alpha = 0; alpha < base[j]; ++alpha) coshlambda[j][alpha] = cosh(lambda[j][alpha]);
  118. }
  119. return;
  120. }
  121. void ODSLF_XXZ_Bethe_State::Compute_tanhlambda()
  122. {
  123. for (int j = 0; j < chain.Nstrings; ++j) {
  124. for (int alpha = 0; alpha < base[j]; ++alpha) tanhlambda[j][alpha] = tanh(lambda[j][alpha]);
  125. }
  126. return;
  127. }
  128. bool ODSLF_XXZ_Bethe_State::Check_Admissibility(char option)
  129. {
  130. // This function checks the admissibility of the Ix2's of a state:
  131. // returns false if there are higher strings with Ix2 = 0, a totally symmetric distribution of I's at each level,
  132. // and strings of equal length modulo 2 and parity with Ix2 = 0, meaning at least two equal roots in BAE.
  133. bool answer = true;
  134. Vect<bool> Zero_at_level(false, chain.Nstrings); // whether there exists an Ix2 == 0 at a given level
  135. bool higher_string_on_zero = false;
  136. for (int j = 0; j < chain.Nstrings; ++j) {
  137. // The following line puts answer to true if there is at least one higher string with zero Ix2
  138. for (int alpha = 0; alpha < base[j]; ++alpha) if ((Ix2[j][alpha] == 0) && (chain.Str_L[j] >= 2))
  139. higher_string_on_zero = true;
  140. for (int alpha = 0; alpha < base[j]; ++alpha) if (Ix2[j][alpha] == 0) Zero_at_level[j] = true;
  141. // NOTE: if base[j] == 0, Zero_at_level[j] remains false.
  142. }
  143. // check symmetry of Ix2 at each level, if there exists a potentially risky Ix2...
  144. bool symmetric_state = (*this).Check_Symmetry();
  145. bool string_coincidence = false;
  146. for (int j1 = 0; j1 < chain.Nstrings; ++j1) {
  147. for (int j2 = j1 + 1; j2 < chain.Nstrings; ++j2)
  148. if (Zero_at_level[j1] && Zero_at_level[j2] && (chain.par[j1] == chain.par[j2])
  149. && (!((chain.Str_L[j1] + chain.Str_L[j2])%2)))
  150. string_coincidence = true;
  151. }
  152. bool M_odd_and_onep_on_zero = false;
  153. if (option == 'z') { // for Sz, if M is odd, exclude symmetric states with a 1+ on zero
  154. // (zero rapidities in left and right states, so FF det not defined).
  155. bool is_ground_state = base.Nrap[0] == base.Mdown && Ix2[0][0] == -(base.Mdown - 1)
  156. && Ix2[0][base.Mdown-1] == base.Mdown - 1;
  157. if (Zero_at_level[0] && (base.Mdown % 2) && !is_ground_state) M_odd_and_onep_on_zero = true;
  158. }
  159. bool onep_onem_on_zero = false;
  160. if (option == 'm' || option == 'p') { // for Smin, we also exclude symmetric states with 1+ and 1- strings on zero
  161. if (Zero_at_level[0] && Zero_at_level[1]) onep_onem_on_zero = true;
  162. }
  163. answer = !(symmetric_state && (higher_string_on_zero || string_coincidence
  164. || onep_onem_on_zero || M_odd_and_onep_on_zero));
  165. // Now check that no Ix2 is equal to +N (since we take -N into account, and I + N == I by periodicity of exp)
  166. for (int j = 0; j < chain.Nstrings; ++j)
  167. for (int alpha = 0; alpha < base[j]; ++alpha)
  168. if ((Ix2[j][alpha] < -chain.Nsites) || (Ix2[j][alpha] >= chain.Nsites)) answer = false;
  169. if (!answer) {
  170. E = 0.0;
  171. K = 0.0;
  172. conv = 0;
  173. iter = 0;
  174. iter_Newton = 0;
  175. lnnorm = -100.0;
  176. }
  177. return(answer); // answer == true: nothing wrong with this Ix2_config
  178. }
  179. void ODSLF_XXZ_Bethe_State::Compute_BE (int j, int alpha)
  180. {
  181. tanhlambda[j][alpha] = tanh(lambda[j][alpha]);
  182. DP sumtheta = 0.0;
  183. for (int k = 0; k < chain.Nstrings; ++k)
  184. for (int beta = 0; beta < base[k]; ++beta) {
  185. if ((chain.Str_L[j] == 1) && (chain.Str_L[k] == 1))
  186. sumtheta += (chain.par[j] == chain.par[k])
  187. ? atan((tanhlambda[j][alpha] - tanhlambda[k][beta])
  188. /((1.0 - tanhlambda[j][alpha] * tanhlambda[k][beta]) * chain.ta_n_anis_over_2[2]))
  189. : - atan(((tanhlambda[j][alpha] - tanhlambda[k][beta])
  190. /(1.0 - tanhlambda[j][alpha] * tanhlambda[k][beta])) * chain.ta_n_anis_over_2[2]) ;
  191. else sumtheta += 0.5 * ODSLF_Theta_XXZ((tanhlambda[j][alpha] - tanhlambda[k][beta])
  192. /(1.0 - tanhlambda[j][alpha] * tanhlambda[k][beta]),
  193. chain.Str_L[j], chain.Str_L[k], chain.par[j], chain.par[k],
  194. chain.ta_n_anis_over_2);
  195. }
  196. sumtheta *= 2.0;
  197. BE[j][alpha] =
  198. ((chain.par[j] == 1) ? 2.0 * atan(tanhlambda[j][alpha]/chain.ta_n_anis_over_2[chain.Str_L[j]])
  199. : -2.0 * atan(tanhlambda[j][alpha] * chain.ta_n_anis_over_2[chain.Str_L[j]]))
  200. - (sumtheta + PI*Ix2[j][alpha])/chain.Nsites;
  201. }
  202. void ODSLF_XXZ_Bethe_State::Compute_BE ()
  203. {
  204. // Fills in the BE members with the value of the Bethe equations.
  205. (*this).Compute_tanhlambda();
  206. DP sumtheta = 0.0;
  207. for (int j = 0; j < chain.Nstrings; ++j)
  208. for (int alpha = 0; alpha < base[j]; ++alpha) {
  209. sumtheta = 0.0;
  210. for (int k = 0; k < chain.Nstrings; ++k)
  211. for (int beta = 0; beta < base[k]; ++beta) {
  212. if ((chain.Str_L[j] == 1) && (chain.Str_L[k] == 1))
  213. sumtheta += (chain.par[j] == chain.par[k])
  214. ? atan((tanhlambda[j][alpha] - tanhlambda[k][beta])
  215. /((1.0 - tanhlambda[j][alpha] * tanhlambda[k][beta]) * chain.ta_n_anis_over_2[2]))
  216. : - atan(((tanhlambda[j][alpha] - tanhlambda[k][beta])
  217. /(1.0 - tanhlambda[j][alpha] * tanhlambda[k][beta])) * chain.ta_n_anis_over_2[2]) ;
  218. else sumtheta += 0.5 * ODSLF_Theta_XXZ((tanhlambda[j][alpha] - tanhlambda[k][beta])
  219. /(1.0 - tanhlambda[j][alpha] * tanhlambda[k][beta]),
  220. chain.Str_L[j], chain.Str_L[k], chain.par[j], chain.par[k],
  221. chain.ta_n_anis_over_2);
  222. }
  223. sumtheta *= 2.0;
  224. BE[j][alpha] =
  225. ((chain.par[j] == 1) ? 2.0 * atan(tanhlambda[j][alpha]/chain.ta_n_anis_over_2[chain.Str_L[j]])
  226. : -2.0 * atan(tanhlambda[j][alpha] * chain.ta_n_anis_over_2[chain.Str_L[j]]))
  227. - (sumtheta + PI*Ix2[j][alpha])/chain.Nsites;
  228. }
  229. }
  230. DP ODSLF_XXZ_Bethe_State::Iterate_BAE (int j, int alpha)
  231. {
  232. // Returns a new iteration value for lambda[j][alpha] given tanhlambda and BE Lambdas
  233. // Assumes that tanhlambda[][] and BE[][] have been computed.
  234. DP new_lambda = 0.0;
  235. DP arg = 0.0;
  236. if (chain.par[j] == 1) arg = chain.ta_n_anis_over_2[chain.Str_L[j]]
  237. * tan(0.5 *
  238. //(PI * Ix2[j][alpha] + sumtheta)/chain.Nsites
  239. (2.0 * atan(tanhlambda[j][alpha]/chain.ta_n_anis_over_2[chain.Str_L[j]]) - BE[j][alpha])
  240. );
  241. else if (chain.par[j] == -1)
  242. arg = -tan(0.5 *
  243. (-2.0 * atan(tanhlambda[j][alpha] * chain.ta_n_anis_over_2[chain.Str_L[j]]) - BE[j][alpha]))
  244. /chain.ta_n_anis_over_2[chain.Str_L[j]];
  245. if (fabs(arg) < 1.0) {
  246. new_lambda = atanh(arg);
  247. }
  248. else {
  249. new_lambda = lambda[j][alpha]; // back to drawing board...
  250. int block = 0; // counter to prevent runaway while loop
  251. DP new_tanhlambda = 0.0;
  252. DP sumtheta = 0.0;
  253. arg = 10.0; // reset value to start while loop
  254. while ((fabs(arg) > 1.0) && (block++ < 100)) { // recompute the diverging root on its own...
  255. new_lambda *= 1.01; // try to go slowly towards infinity...
  256. new_tanhlambda = tanh(new_lambda);
  257. sumtheta = 0.0;
  258. for (int k = 0; k < chain.Nstrings; ++k) {
  259. for (int beta = 0; beta < base[k]; ++beta)
  260. if ((chain.Str_L[j] == 1) && (chain.Str_L[k] == 1))
  261. sumtheta += (chain.par[j] == chain.par[k])
  262. ? atan((new_tanhlambda - tanhlambda[k][beta])
  263. /((1.0 - new_tanhlambda * tanhlambda[k][beta]) * chain.ta_n_anis_over_2[2]))
  264. : - atan(((new_tanhlambda - tanhlambda[k][beta])
  265. /(1.0 - new_tanhlambda * tanhlambda[k][beta])) * chain.ta_n_anis_over_2[2]) ;
  266. else sumtheta += 0.5 * ODSLF_Theta_XXZ((new_tanhlambda - tanhlambda[k][beta])
  267. /(1.0 - new_tanhlambda * tanhlambda[k][beta]),
  268. chain.Str_L[j], chain.Str_L[k], chain.par[j], chain.par[k],
  269. chain.ta_n_anis_over_2);
  270. }
  271. sumtheta *= 2.0;
  272. if (chain.par[j] == 1)
  273. arg = chain.ta_n_anis_over_2[chain.Str_L[j]] * tan(0.5 * (PI * Ix2[j][alpha] + sumtheta)/chain.Nsites);
  274. else if (chain.par[j] == -1)
  275. arg = -tan(0.5 * (PI * Ix2[j][alpha] + sumtheta)/chain.Nsites)/chain.ta_n_anis_over_2[chain.Str_L[j]];
  276. else ABACUSerror("Invalid parities in Iterate_BAE.");
  277. }
  278. }
  279. return(new_lambda);
  280. }
  281. bool ODSLF_XXZ_Bethe_State::Check_Rapidities()
  282. {
  283. bool nonan = true;
  284. for (int j = 0; j < chain.Nstrings; ++j)
  285. for (int alpha = 0; alpha < base[j]; ++alpha) nonan *= !is_nan(lambda[j][alpha]);
  286. return nonan;
  287. }
  288. void ODSLF_XXZ_Bethe_State::Compute_Energy ()
  289. {
  290. DP sum = 0.0;
  291. for (int j = 0; j < chain.Nstrings; ++j) {
  292. for (int alpha = 0; alpha < base[j]; ++alpha) {
  293. sum += sin(chain.Str_L[j] * chain.anis)
  294. / (chain.par[j] * cosh(2.0 * lambda[j][alpha]) - cos(chain.Str_L[j] * chain.anis));
  295. }
  296. }
  297. sum *= - chain.J * sin(chain.anis);
  298. E = sum;
  299. return;
  300. }
  301. void ODSLF_XXZ_Bethe_State::Build_Reduced_Gaudin_Matrix (SQMat<complex<DP> >& Gaudin_Red)
  302. {
  303. if (Gaudin_Red.size() != base.Nraptot) ABACUSerror("Passing matrix of wrong size in Build_Reduced_Gaudin_Matrix.");
  304. int index_jalpha;
  305. int index_kbeta;
  306. DP sum_hbar_XXZ = 0.0;
  307. DP sinzetasq = pow(sin(chain.anis), 2.0);
  308. (*this).Compute_sinhlambda();
  309. (*this).Compute_coshlambda();
  310. index_jalpha = 0;
  311. for (int j = 0; j < chain.Nstrings; ++j) {
  312. for (int alpha = 0; alpha < base[j]; ++alpha) {
  313. index_kbeta = 0;
  314. for (int k = 0; k < chain.Nstrings; ++k) {
  315. for (int beta = 0; beta < base[k]; ++beta) {
  316. if ((j == k) && (alpha == beta)) {
  317. sum_hbar_XXZ = 0.0;
  318. for (int kp = 0; kp < chain.Nstrings; ++kp) {
  319. for (int betap = 0; betap < base[kp]; ++betap) {
  320. if (!((j == kp) && (alpha == betap)))
  321. sum_hbar_XXZ
  322. += ODSLF_ddlambda_Theta_XXZ (lambda[j][alpha] - lambda[kp][betap], chain.Str_L[j], chain.Str_L[kp],
  323. chain.par[j], chain.par[kp], chain.si_n_anis_over_2);
  324. }
  325. }
  326. Gaudin_Red[index_jalpha][index_kbeta]
  327. = complex<DP> ( chain.Nsites * ODSLF_hbar_XXZ (lambda[j][alpha], chain.Str_L[j], chain.par[j],
  328. chain.si_n_anis_over_2) - sum_hbar_XXZ);
  329. }
  330. else {
  331. if ((chain.Str_L[j] == 1) && (chain.Str_L[k] == 1))
  332. Gaudin_Red[index_jalpha][index_kbeta] =
  333. complex<DP> ((chain.par[j] * chain.par[k] == 1)
  334. ? chain.si_n_anis_over_2[4]
  335. /(pow(sinhlambda[j][alpha] * coshlambda[k][beta]
  336. - coshlambda[j][alpha] * sinhlambda[k][beta], 2.0) + sinzetasq)
  337. : chain.si_n_anis_over_2[4]
  338. /(-pow(coshlambda[j][alpha] * coshlambda[k][beta]
  339. - sinhlambda[j][alpha] * sinhlambda[k][beta], 2.0) + sinzetasq) );
  340. else
  341. Gaudin_Red[index_jalpha][index_kbeta] =
  342. complex<DP> (ODSLF_ddlambda_Theta_XXZ (lambda[j][alpha] - lambda[k][beta], chain.Str_L[j], chain.Str_L[k],
  343. chain.par[j], chain.par[k], chain.si_n_anis_over_2));
  344. }
  345. index_kbeta++;
  346. }
  347. }
  348. index_jalpha++;
  349. }
  350. }
  351. return;
  352. }
  353. // ****************************************************************************************************
  354. // non-member functions
  355. inline DP ODSLF_fbar_XXZ (DP tanhlambda, int par, DP tannzetaover2)
  356. {
  357. DP result = 0.0;
  358. if (par == 1) result = 2.0 * atan(tanhlambda/tannzetaover2);
  359. else if (par == -1) result = -2.0 * atan(tanhlambda * tannzetaover2);
  360. else ABACUSerror("Faulty parity in ODSLF_fbar_XXZ.");
  361. return (result);
  362. }
  363. DP ODSLF_Theta_XXZ (DP tanhlambda, int nj, int nk, int parj, int park, DP* tannzetaover2)
  364. {
  365. DP result = 0.0;
  366. if ((nj == 1) && (nk == 1)) result = ODSLF_fbar_XXZ(tanhlambda, parj*park, tannzetaover2[2]);
  367. else {
  368. result = (nj == nk) ? 0.0 : ODSLF_fbar_XXZ(tanhlambda, parj*park, tannzetaover2[fabs(nj - nk)]);
  369. for (int a = 1; a < ABACUS::min(nj, nk); ++a)
  370. result += 2.0 * ODSLF_fbar_XXZ(tanhlambda, parj*park, tannzetaover2[fabs(nj - nk) + 2*a]);
  371. result += ODSLF_fbar_XXZ(tanhlambda, parj*park, tannzetaover2[nj + nk]);
  372. }
  373. return (result);
  374. }
  375. DP ODSLF_hbar_XXZ (DP lambda, int n, int par, DP* si_n_anis_over_2)
  376. {
  377. DP result = 0.0;
  378. 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));
  379. 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));
  380. else ABACUSerror("Faulty parity in ODSLF_hbar_XXZ.");
  381. return (result);
  382. }
  383. DP ODSLF_ddlambda_Theta_XXZ (DP lambda, int nj, int nk, int parj, int park, DP* si_n_anis_over_2)
  384. {
  385. DP result = (nj == nk) ? 0.0 : ODSLF_hbar_XXZ(lambda, fabs(nj - nk), parj*park, si_n_anis_over_2);
  386. for (int a = 1; a < ABACUS::min(nj, nk); ++a)
  387. result += 2.0 * ODSLF_hbar_XXZ(lambda, fabs(nj - nk) + 2*a, parj*park, si_n_anis_over_2);
  388. result += ODSLF_hbar_XXZ(lambda, nj + nk, parj*park, si_n_anis_over_2);
  389. return (result);
  390. }
  391. } // namespace ABACUS