VMPS++
Loading...
Searching...
No Matches
Heisenberg.h
Go to the documentation of this file.
1#ifndef VANILLA_HEISENBERG
2#define VANILLA_HEISENBERG
3
5#include "symmetry/U0.h"
6
7namespace VMPS
8{
9
33class Heisenberg : public Mpo<Sym::U0,double>, public HeisenbergObservables<Sym::U0>, public ParamReturner
34{
35public:
38
39 static qarray<0> singlet(int N=0) {return qarray<0>{};};
40 static constexpr MODEL_FAMILY FAMILY = HEISENBERG;
41
42private:
43 typedef typename Symmetry::qType qType;
44
45public:
46
49
50 Heisenberg (const size_t &L, const vector<Param> &params, const BC &boundary=BC::OPEN, const DMRG::VERBOSITY::OPTION& VERB=DMRG::VERBOSITY::OPTION::ON_EXIT);
51
52 Heisenberg (Mpo<Symmetry> &Mpo_input, const vector<Param> &params)
53 :Mpo<Symmetry>(Mpo_input),
56 {
57 ParamHandler P(params,Heisenberg::defaults);
58 size_t Lcell = P.size();
59 N_phys = 0;
60 for (size_t l=0; l<N_sites; ++l) N_phys += P.get<size_t>("Ly",l%Lcell);
61 this->precalc_TwoSiteData();
62 this->HERMITIAN = true;
63 this->HAMILTONIAN = true;
64 };
66
67 static void add_operators (const std::vector<SpinBase<Symmetry>> &B, const ParamHandler &P,
68 PushType<SiteOperator<Symmetry,double>,double>& pushlist,
69 std::vector<std::vector<std::string>>& labellist, const BC boundary=BC::OPEN);
70
71 static const std::map<string,std::any> defaults;
72 static const std::map<string,std::any> sweep_defaults;
73
74 static refEnergy ref (const vector<Param> &params, double L=numeric_limits<double>::infinity());
75};
76
77const std::map<string,std::any> Heisenberg::defaults =
78{
79 {"J",0.}, {"Jprime",0.}, {"Jrung",0.},
80 {"Jxy",0.}, {"Jxyprime",0.}, {"Jxyrung",0.},
81 {"Jz",0.}, {"Jzprime",0.}, {"Jzrung",0.},
82
83 {"Jx",0.}, {"Jxrung",0.},
84 {"Jy",0.}, {"Jyrung",0.},
85 {"Jz",0.}, {"Jzrung",0.},
86 {"Jw",0.}, {"Jwrung",0.}, // couples the twisted components Sw=Sy*exp(i*pi*Sz)=exp(i*pi*Sx)*Sy (for S=1)
87 {"betaKT",0.},
88
89 {"R",0.}, // quadrupole coupling
90 {"Bz",0.}, {"Bx",0.},
91 {"Kz",0.}, {"Kx",0.},
92 {"Dy",0.}, {"Dyprime",0.}, {"Dyrung",0.}, // Dzialoshinsky-Moriya terms
93 {"t",0.}, {"mu",0.}, {"Delta",0.}, // Kitaev chain terms
94 {"mu",0.}, {"nu",0.}, // couple to Sz_i-1/2 and Sz_i+1/2
95 {"D",2ul}, {"maxPower",2ul}, {"CYLINDER",false}, {"Ly",1ul}, {"mfactor",1}
96};
97
98const std::map<string,std::any> Heisenberg::sweep_defaults =
99{
100 {"max_alfa",100.}, {"min_alfa",1.e-11}, {"lim_alfa",10ul}, {"eps_svd",1.e-7},
101 {"Mincr_abs", 10ul}, {"Mincr_per", 2ul}, {"Mincr_rel", 1.1},
102 {"min_Nsv",0ul}, {"max_Nrich",-1},
103 {"max_halfsweeps",40ul}, {"min_halfsweeps",1ul},
104 {"Minit",10ul}, {"Qinit",1ul}, {"Mlimit",500ul},
105 {"tol_eigval",1.e-5}, {"tol_state",1.e-5},
106 {"savePeriod",0ul}, {"CALC_S_ON_EXIT", true}, {"CONVTEST", DMRG::CONVTEST::VAR_2SITE}
107};
108
110Heisenberg (const size_t &L, const vector<Param> &params, const BC &boundary, const DMRG::VERBOSITY::OPTION &VERB)
111:Mpo<Symmetry> (L, Symmetry::qvacuum(), "", PROP::HERMITIAN, PROP::NON_UNITARY, boundary, VERB),
112 HeisenbergObservables(L,params,Heisenberg::defaults),
113 ParamReturner(Heisenberg::sweep_defaults)
114{
115 ParamHandler P(params,Heisenberg::defaults);
116 size_t Lcell = P.size();
117
118 for (size_t l=0; l<N_sites; ++l)
119 {
120 N_phys += P.get<size_t>("Ly",l%Lcell);
121 setLocBasis(B[l].get_basis().qloc(),l);
122 }
123
124 if (P.HAS_ANY_OF({"Dy", "Dyperp", "Dyprime"}))
125 {
126 this->set_name("Dzyaloshinsky-Moriya");
127 }
128 else if (P.HAS_ANY_OF({"t", "mu", "Delta"}))
129 {
130 this->set_name("KitaevChain");
131 }
132 else
133 {
134 this->set_name("Heisenberg");
135 }
136
138 std::vector<std::vector<std::string>> labellist;
139 HeisenbergU1::set_operators(B, P, pushlist, labellist, boundary);
140 add_operators(B, P, pushlist, labellist, boundary);
141
142 this->construct_from_pushlist(pushlist, labellist, Lcell);
143 this->finalize(PROP::COMPRESS, P.get<size_t>("maxPower"));
144
145 this->precalc_TwoSiteData();
146}
147
149add_operators (const std::vector<SpinBase<Symmetry>> &B, const ParamHandler &P, PushType<SiteOperator<Symmetry,double>,double>& pushlist, std::vector<std::vector<std::string>>& labellist, const BC boundary)
150{
151 std::size_t Lcell = P.size();
152 std::size_t N_sites = B.size();
153 if(labellist.size() != N_sites) {labellist.resize(N_sites);}
154
155 for(std::size_t loc=0; loc<N_sites; ++loc)
156 {
157 size_t lp1 = (loc+1)%N_sites;
158 size_t lp2 = (loc+2)%N_sites;
159
160 std::size_t orbitals = B[loc].orbitals();
161 std::size_t next_orbitals = B[lp1].orbitals();
162 std::size_t nextn_orbitals = B[lp2].orbitals();
163
164 // Local terms: B, K, DM⟂
165
166 param1d Bx = P.fill_array1d<double>("Bx", "Bxorb", orbitals, loc%Lcell);
167 param1d Kx = P.fill_array1d<double>("Kx", "Kxorb", orbitals, loc%Lcell);
168 param2d Dyperp = P.fill_array2d<double>("Dyrung", "Dy", "Dyperp", orbitals, loc%Lcell, P.get<bool>("CYLINDER"));
169
170 labellist[loc].push_back(Bx.label);
171 labellist[loc].push_back(Kx.label);
172 labellist[loc].push_back(Dyperp.label);
173
174 param2d Jxpara = P.fill_array2d<double>("Jx", "Jxpara", {orbitals, next_orbitals}, loc%Lcell);
175 param2d Jypara = P.fill_array2d<double>("Jy", "Jypara", {orbitals, next_orbitals}, loc%Lcell);
176 param2d Jwpara = P.fill_array2d<double>("Jw", "Jwpara", {orbitals, next_orbitals}, loc%Lcell);
177 param2d betaKTpara = P.fill_array2d<double>("betaKT", "betaKTpara", {orbitals, next_orbitals}, loc%Lcell);
178
179 labellist[loc].push_back(Jxpara.label);
180 labellist[loc].push_back(Jypara.label);
181 labellist[loc].push_back(Jwpara.label);
182 labellist[loc].push_back(betaKTpara.label);
183
184 ArrayXd Bz_array = B[loc].ZeroField();
185 ArrayXd mu_array = B[loc].ZeroField();
186 ArrayXd nu_array = B[loc].ZeroField();
187 ArrayXd Kz_array = B[loc].ZeroField();
188 ArrayXXd Jperp_array = B[loc].ZeroHopping();
189
191 B[loc].HeisenbergHamiltonian(Jperp_array, Jperp_array, Bz_array, Bx.a, mu_array, nu_array, Kz_array, Kx.a, Dyperp.a));
192 pushlist.push_back(std::make_tuple(loc, Hloc, 1.));
193
194 // Nearest-neighbour terms: DM=Dzyaloshinsky-Moriya
195 param2d Dypara = P.fill_array2d<double>("Dy", "Dypara", {orbitals, next_orbitals}, loc%Lcell);
196 labellist[loc].push_back(Dypara.label);
197
198 if (loc < N_sites-1 or !static_cast<bool>(boundary))
199 {
200 for (std::size_t alfa=0; alfa<orbitals; alfa++)
201 for (std::size_t beta=0; beta<next_orbitals; ++beta)
202 {
203 pushlist.push_back(std::make_tuple(loc, Mpo<Symmetry,double>::get_N_site_interaction(B[loc].Scomp(SX,alfa), B[lp1].Scomp(SZ,beta)), +Dypara(alfa,beta)));
204 pushlist.push_back(std::make_tuple(loc, Mpo<Symmetry,double>::get_N_site_interaction(B[loc].Scomp(SZ,alfa), B[lp1].Scomp(SX,beta)), -Dypara(alfa,beta)));
205
206 // Hamiltonian after the Kennedy-Tasaki transformation of the Haldane chain:
207 // H = Σ_i h_i
208 // h_i = -S^z(i)*S^z(i+1) -S^x(i)*S^x(i+1) +S^w(i)*S^w(i+1)
209 // S^w = S^y*exp(iπSz) = exp(iπSx)*Sy
210 // To test, set Jz=-1, Jx=-1, Jw=+1
211 // Sz coupling is set somewhere else, set the x- and w-coupling here:
212
213 auto local_Sx = B[loc].Scomp(SX,alfa);
214 auto local_Sz = B[loc].Scomp(SZ,alfa);
215 auto local_iSy = B[loc].Scomp(iSY,alfa);
216
217 auto tight_Sx = B[(loc+1)%N_sites].Scomp(SX,beta);
218 auto tight_Sz = B[(loc+1)%N_sites].Scomp(SZ,beta);
219 auto tight_iSy = B[(loc+1)%N_sites].Scomp(iSY,beta);
220
221 // Set first to 1 in order to avoid warning for half-integer spin
222/* auto local_iSw = B[loc].Id();*/
223/* auto tight_iSw = B[(loc+1)%N_sites].Id();*/
224/* if (abs(Jwpara(alfa,beta)) != 0.)*/
225/* {*/
226/* local_iSw= local_iSy*B[loc].bead(STRINGZ,alfa);*/
227/* tight_iSw= B[(loc+1)%N_sites].bead(STRINGX,alfa)*tight_iSy;*/
228/* }*/
229/* */
230/* pushlist.push_back(std::make_tuple(loc, Mpo<Symmetry,double>::get_N_site_interaction(local_Sx, tight_Sx), Jxpara(alfa,beta)));*/
231/* pushlist.push_back(std::make_tuple(loc, Mpo<Symmetry,double>::get_N_site_interaction(local_iSy, tight_iSy), -Jypara(alfa,beta)));*/
232/* pushlist.push_back(std::make_tuple(loc, Mpo<Symmetry,double>::get_N_site_interaction(local_iSw, tight_iSw), -Jwpara(alfa,beta)));*/
233/* */
234/* // Hamiltonian after the Kennedy-Tasaki transformation of the bilinear-biquadratic chain:*/
235/* // H = Σ_i h_i - β (h_i)^2*/
236/* // AKLT point: H = Σ_i h_i + 1/3 (h_i)^2*/
237/* // To test the AKLT point (4-fold degenerate ground state with OBC), set betaKT = -1/3*/
238/* // All terms of (h_i)^2 are multiplied out in the following:*/
239/* */
240/* auto xx_local = local_Sx*local_Sx;*/
241/* auto zz_local = local_Sz*local_Sz;*/
242/* auto ww_mlocal = local_iSw*local_iSw;*/
243/* */
244/* auto xx_tight = tight_Sx*tight_Sx;*/
245/* auto zz_tight = tight_Sz*tight_Sz;*/
246/* auto ww_mtight = tight_iSw*tight_iSw;*/
247/* */
248/* auto xz_local = local_Sx*local_Sz;*/
249/* auto ixw_local = local_Sx*local_iSw;*/
250/* auto izw_local = local_Sz*local_iSw;*/
251/* */
252/* auto zx_local = local_Sz*local_Sx;*/
253/* auto iwx_local = local_iSw*local_Sx;*/
254/* auto iwz_local = local_iSw*local_Sz;*/
255/* */
256/* auto xz_tight = tight_Sx*tight_Sz;*/
257/* auto ixw_tight = tight_Sx*tight_iSw;*/
258/* auto izw_tight = tight_Sz*tight_iSw;*/
259/* */
260/* auto zx_tight = tight_Sz*tight_Sx;*/
261/* auto iwx_tight = tight_iSw*tight_Sx;*/
262/* auto iwz_tight = tight_iSw*tight_Sz;*/
263/* */
264/* pushlist.push_back(std::make_tuple(loc, Mpo<Symmetry,double>::get_N_site_interaction(xx_local, xx_tight), -betaKTpara(alfa,beta)));*/
265/* pushlist.push_back(std::make_tuple(loc, Mpo<Symmetry,double>::get_N_site_interaction(zz_local, zz_tight), -betaKTpara(alfa,beta)));*/
266/* pushlist.push_back(std::make_tuple(loc, Mpo<Symmetry,double>::get_N_site_interaction(ww_mlocal, ww_mtight), -betaKTpara(alfa,beta)));*/
267/* */
268/* pushlist.push_back(std::make_tuple(loc, Mpo<Symmetry,double>::get_N_site_interaction(xz_local, xz_tight), -betaKTpara(alfa,beta)));*/
269/* pushlist.push_back(std::make_tuple(loc, Mpo<Symmetry,double>::get_N_site_interaction(ixw_local, ixw_tight), -betaKTpara(alfa,beta))); // sign: i^2*(-1) from x-term*/
270/* pushlist.push_back(std::make_tuple(loc, Mpo<Symmetry,double>::get_N_site_interaction(izw_local, izw_tight), -betaKTpara(alfa,beta))); // sign: i^2*(-1) from z-term*/
271/* */
272/* pushlist.push_back(std::make_tuple(loc, Mpo<Symmetry,double>::get_N_site_interaction(zx_local, zx_tight), -betaKTpara(alfa,beta)));*/
273/* pushlist.push_back(std::make_tuple(loc, Mpo<Symmetry,double>::get_N_site_interaction(iwx_local, iwx_tight), -betaKTpara(alfa,beta))); // sign: i^2*(-1) from x-term*/
274/* pushlist.push_back(std::make_tuple(loc, Mpo<Symmetry,double>::get_N_site_interaction(iwz_local, iwz_tight), -betaKTpara(alfa,beta))); // sign: i^2*(-1) from z-term*/
275 }
276 }
277
278 // Next-nearest-neighbour terms: DM
279 param2d Dyprime = P.fill_array2d<double>("Dyprime", "Dyprime_array", {orbitals, nextn_orbitals}, loc%Lcell);
280 labellist[loc].push_back(Dyprime.label);
281
282 if (loc < N_sites-2 or !static_cast<bool>(boundary))
283 {
284 for (std::size_t alfa=0; alfa<orbitals; ++alfa)
285 for (std::size_t beta=0; beta<nextn_orbitals; ++beta)
286 {
287 pushlist.push_back(std::make_tuple(loc, Mpo<Symmetry,double>::get_N_site_interaction(B[loc].Scomp(SX,alfa),
288 B[lp1].Id(),
289 B[lp2].Scomp(SZ,beta)), +Dyprime(alfa,beta)));
290 pushlist.push_back(std::make_tuple(loc, Mpo<Symmetry,double>::get_N_site_interaction(B[loc].Scomp(SZ,alfa),
291 B[lp1].Id(),
292 B[lp2].Scomp(SX,beta)), -Dyprime(alfa,beta)));
293 }
294 }
295 }
296}
297
299ref (const vector<Param> &params, double L)
300{
301 ParamHandler P(params,{{"D",2ul},{"Ly",1ul},{"m",0.},{"J",1.},{"Jxy",0.},{"Jz",0.},
302 {"Jprime",0.},{"Bz",0.},{"Bx",0.},{"Kx",0.},{"Kz",0.},{"Dy",0.},{"Dyprime",0.},{"R",0.}});
303 refEnergy out;
304
305 size_t Ly = P.get<size_t>("Ly");
306 size_t D = P.get<size_t>("D");
307 double J = P.get<double>("J");
308 double Jxy = P.get<double>("Jxy");
309 double Jz = P.get<double>("Jz");
310 double Jprime = P.get<double>("Jprime");
311 double R = P.get<double>("R");
312
313 // Heisenberg chain and ladder
314 if (isinf(L) and J > 0. and P.ARE_ALL_ZERO<double>({"m","Jprime","Jxy","Jz","Bz","Bx","Kx","Kz","Dy","Dyprime","R"}))
315 {
316 // out.source = "T. Xiang, Thermodynamics of quantum Heisenberg spin chains, Phys. Rev. B 58, 9142 (1998)";
317 out.source = "F. B. Ramos and J. C. Xavier, N-leg spin-S Heisenberg ladders, Phys. Rev. B 89, 094424 (2014)";
318 out.method = "literature";
319
320 if (D == 2)
321 {
322 if (Ly == 1) {out.value = -log(2)+0.25; out.method = "analytical";}
323 if (Ly == 2) {out.value = -0.578043140180; out.method = "IDMRG high precision";}
324 if (Ly == 3) {out.value = -0.600537;}
325 if (Ly == 4) {out.value = -0.618566;}
326 if (Ly == 5) {out.value = -0.62776;}
327 if (Ly == 6) {out.value = -0.6346;}
328 }
329 else if (D == 3)
330 {
331 if (Ly == 1) {out.value = -1.40148403897;}
332 if (Ly == 2) {out.value = -1.878372746;}
333 if (Ly == 3) {out.value = -2.0204;}
334 if (Ly == 4) {out.value = -2.0957;}
335 if (Ly == 5) {out.value = -2.141;}
336 if (Ly == 6) {out.value = -2.169;}
337 }
338 else if (D == 4)
339 {
340 if (Ly == 1) {out.value = -2.828337;}
341 if (Ly == 2) {out.value = -3.930067;}
342 if (Ly == 3) {out.value = -4.2718;}
343 if (Ly == 4) {out.value = -4.446;}
344 if (Ly == 5) {out.value = -4.553;}
345 if (Ly == 6) {out.value = -4.60;}
346 }
347 else if (D == 5)
348 {
349 if (Ly == 1) {out.value = -4.761248;}
350 if (Ly == 2) {out.value = -6.73256;}
351 if (Ly == 3) {out.value = -7.3565;}
352 if (Ly == 4) {out.value = -7.669;}
353 if (Ly == 5) {out.value = -7.865;}
354 if (Ly == 6) {out.value = -7.94;}
355 }
356 else if (D == 6)
357 {
358 if (Ly == 1) {out.value = -7.1924;}
359 if (Ly == 2) {out.value = -10.2852;}
360 if (Ly == 3) {out.value = -11.274;}
361 if (Ly == 4) {out.value = -11.76;}
362 if (Ly == 5) {out.value = -12.08;}
363 if (Ly == 6) {out.value = -12.1;}
364 }
365
366 out.value *= J;
367 }
368 // XX chain
369 else if (isinf(L) and D == 2 and Jxy > 0. and P.ARE_ALL_ZERO<double>({"m","J","Jprime","Jz","Bz","Bx","Kx","Kz","Dy","Dyprime","R"}))
370 {
371 out.value = -M_1_PI*Jxy;
372 out.source = "S. Paul, A. K. Ghosh, Ground state properties of the bond alternating spin-1/2 anisotropic Heisenberg chain, Condensed Matter Physics, 2017, Vol. 20, No 2, 23701: 1–16";
373 out.method = "analytical";
374 }
375 // Majumdar-Ghosh chain
376 else if (D == 2 and J > 0. and Jprime == 0.5*J and P.ARE_ALL_ZERO<double>({"m","Jxy","Jz","Bz","Bx","Kx","Kz","Dy","Dyprime","R"}))
377 {
378 out.value = -0.375*J;
379 out.source = "https://en.wikipedia.org/wiki/Majumdar-Ghosh_model";
380 out.method = "analytical";
381 }
382 if (isinf(L) and D==3 and abs(J-0.5)<1e-14 and abs(R+0.5)<1e-14)
383 {
384 double x = 0.5*(7.+3.*sqrt(5.));
385 double sumres = 0.;
386 for (int n=1; n<10000; ++n)
387 {
388 sumres += 1./(1.+pow(x,n));
389 }
390 out.value = -1.-sqrt(5)/2.*(1.+4.*sumres) + 8./3.;
391 out.source = "Barber & Batchelor (1989), Parkinson (1988)";
392 out.method = "analytical";
393 }
394
395 return out;
396}
397
398} // end namespace VMPS
399
400#endif
MODEL_FAMILY
Definition: DmrgTypedefs.h:96
@ HEISENBERG
Definition: DmrgTypedefs.h:96
@ iSY
Definition: DmrgTypedefs.h:60
@ SZ
Definition: DmrgTypedefs.h:60
@ SX
Definition: DmrgTypedefs.h:60
BC
Definition: DmrgTypedefs.h:161
@ B
Definition: DmrgTypedefs.h:130
vector< SpinBase< Sym::U0 > > B
std::enable_if<!Dummy::IS_SPIN_SU2(), Mpo< Sym::U0, double > >::type Scomp(SPINOP_LABEL Sa, size_t locx, size_t locy=0, double factor=1.) const
std::size_t N_phys
Definition: MpoTerms.h:400
void finalize(const bool COMPRESS=true, const std::size_t power=1, const double tolerance=::mynumeric_limits< double >::epsilon())
Definition: MpoTerms.h:1281
std::size_t N_sites
Definition: MpoTerms.h:395
void setLocBasis(const std::vector< std::vector< qType > > &q)
Definition: MpoTerms.h:715
DMRG::VERBOSITY::OPTION VERB
Definition: MpoTerms.h:102
void set_name(const std::string &label_in)
Definition: MpoTerms.h:471
Definition: Mpo.h:40
static std::vector< T > get_N_site_interaction(T const &Op0, Operator const &... Ops)
Definition: Mpo.h:117
void precalc_TwoSiteData(bool FORCE=false)
void construct_from_pushlist(const PushType< OperatorType, CouplScalar > &pushlist, const std::vector< std::vector< std::string > > &labellist, size_t Lcell)
Definition: U0.h:28
static void set_operators(const std::vector< SpinBase< Symmetry_ > > &B, const ParamHandler &P, PushType< SiteOperator< Symmetry_, double >, double > &pushlist, std::vector< std::vector< std::string > > &labellist, const BC boundary=BC::OPEN)
Definition: HeisenbergU1.h:180
Heisenberg Model.
Definition: Heisenberg.h:34
static const std::map< string, std::any > sweep_defaults
Definition: Heisenberg.h:72
Sym::U0 Symmetry
Definition: Heisenberg.h:36
static void add_operators(const std::vector< SpinBase< Symmetry > > &B, const ParamHandler &P, PushType< SiteOperator< Symmetry, double >, double > &pushlist, std::vector< std::vector< std::string > > &labellist, const BC boundary=BC::OPEN)
Definition: Heisenberg.h:149
static qarray< 0 > singlet(int N=0)
Definition: Heisenberg.h:39
static const std::map< string, std::any > defaults
Definition: Heisenberg.h:71
static refEnergy ref(const vector< Param > &params, double L=numeric_limits< double >::infinity())
Definition: Heisenberg.h:299
Symmetry::qType qType
Definition: Heisenberg.h:43
Heisenberg(Mpo< Symmetry > &Mpo_input, const vector< Param > &params)
Definition: Heisenberg.h:52
static constexpr MODEL_FAMILY FAMILY
Definition: Heisenberg.h:40
#define MAKE_TYPEDEFS(MODEL)
Definition: macros.h:4
const bool COMPRESS
Definition: DmrgTypedefs.h:499
Definition: qarray.h:26
string source
Definition: DmrgTypedefs.h:463