11{
22 "cells" : [
33 {
4- "outputs" : [],
54 "cell_type" : " code" ,
5+ "execution_count" : null ,
6+ "metadata" : {},
7+ "outputs" : [],
68 "source" : [
79 " using Markdown #hide"
8- ],
9- "metadata" : {},
10- "execution_count" : null
10+ ]
1111 },
1212 {
1313 "cell_type" : " markdown" ,
14+ "metadata" : {},
1415 "source" : [
1516 " # The 3D classical Ising model\n " ,
1617 " \n " ,
3637 " spirit as the boundary MPS methods demonstrated in another example.\n " ,
3738 " \n " ,
3839 " Let's start by making the example deterministic and importing the required packages:"
39- ],
40- "metadata" : {}
40+ ]
4141 },
4242 {
43- "outputs" : [],
4443 "cell_type" : " code" ,
44+ "execution_count" : null ,
45+ "metadata" : {},
46+ "outputs" : [],
4547 "source" : [
4648 " using Random\n " ,
4749 " using LinearAlgebra\n " ,
4850 " using PEPSKit, TensorKit\n " ,
4951 " using KrylovKit, OptimKit, Zygote\n " ,
5052 " \n " ,
5153 " Random.seed!(81812781144);"
52- ],
53- "metadata" : {},
54- "execution_count" : null
54+ ]
5555 },
5656 {
5757 "cell_type" : " markdown" ,
58+ "metadata" : {},
5859 "source" : [
5960 " ## Defining the partition function\n " ,
6061 " \n " ,
6566 " constituent rank-6 `PEPSKit.PEPOTensor` `O` located at each site of the cubic\n " ,
6667 " lattice. To verify our example we will check the magnetization and energy, so we also define\n " ,
6768 " the corresponding rank-6 tensors `M` and `E` while we're at it."
68- ],
69- "metadata" : {}
69+ ]
7070 },
7171 {
72- "outputs" : [],
7372 "cell_type" : " code" ,
73+ "execution_count" : null ,
74+ "metadata" : {},
75+ "outputs" : [],
7476 "source" : [
7577 " function three_dimensional_classical_ising(; beta, J = 1.0)\n " ,
7678 " K = beta * J\n " ,
108110 " \n " ,
109111 " return TensorMap(o, TMS), TensorMap(m, TMS), TensorMap(e, TMS)\n " ,
110112 " end;"
111- ],
112- "metadata" : {},
113- "execution_count" : null
113+ ]
114114 },
115115 {
116116 "cell_type" : " markdown" ,
117+ "metadata" : {},
117118 "source" : [
118119 " Let's initialize these tensors at inverse temperature $\\ beta=0.2391$, which corresponds to\n " ,
119120 " a slightly lower temperature than the critical value $\\ beta_c=0.2216544…$"
120- ],
121- "metadata" : {}
121+ ]
122122 },
123123 {
124- "outputs" : [],
125124 "cell_type" : " code" ,
125+ "execution_count" : null ,
126+ "metadata" : {},
127+ "outputs" : [],
126128 "source" : [
127129 " beta = 0.2391\n " ,
128130 " O, M, E = three_dimensional_classical_ising(; beta)\n " ,
129131 " O isa PEPSKit.PEPOTensor"
130- ],
131- "metadata" : {},
132- "execution_count" : null
132+ ]
133133 },
134134 {
135135 "cell_type" : " markdown" ,
136+ "metadata" : {},
136137 "source" : [
137138 " ## Contracting the partition function\n " ,
138139 " \n " ,
190191 " contraction algorithm we can use to compute the values of these two networks. In addition,\n " ,
191192 " we'll specify the specific reverse rule algorithm that will be used to compute the gradient\n " ,
192193 " of this cost function."
193- ],
194- "metadata" : {}
194+ ]
195195 },
196196 {
197- "outputs" : [],
198197 "cell_type" : " code" ,
198+ "execution_count" : null ,
199+ "metadata" : {},
200+ "outputs" : [],
199201 "source" : [
200202 " boundary_alg = SimultaneousCTMRG(; maxiter = 150, tol = 1.0e-8, verbosity = 1)\n " ,
201203 " rrule_alg = EigSolver(;\n " ,
202- " solver_alg = KrylovKit.Arnoldi(; maxiter = 30, tol = 1.0e-6, eager = true), iterscheme = :diffgauge\n " ,
204+ " solver_alg = KrylovKit.Arnoldi(; maxiter = 30, tol = 1.0e-6, eager = true),\n " ,
205+ " iterscheme = :fixed,\n " ,
203206 " )\n " ,
204207 " T = InfinitePEPO(O)\n " ,
205208 " \n " ,
240243 " g = only(gs)\n " ,
241244 " return E, g\n " ,
242245 " end;"
243- ],
244- "metadata" : {},
245- "execution_count" : null
246+ ]
246247 },
247248 {
248249 "cell_type" : " markdown" ,
250+ "metadata" : {},
249251 "source" : [
250252 " There are a few things to note about this cost function definition. Since we will pass it to\n " ,
251253 " the `OptimKit.optimize`, we require it to return both our cost function and the\n " ,
286288 " them where the only difference is that we have to pass along an extra environment since our\n " ,
287289 " cost function requires two distinct contractions as opposed to the setting of Hamiltonian\n " ,
288290 " PEPS optimization which only requires a double-layer contraction."
289- ],
290- "metadata" : {}
291+ ]
291292 },
292293 {
293- "outputs" : [],
294294 "cell_type" : " code" ,
295+ "execution_count" : null ,
296+ "metadata" : {},
297+ "outputs" : [],
295298 "source" : [
296299 " function pepo_retract((peps, env_double_layer, env_triple_layer), η, α)\n " ,
297300 " (peps´, env_double_layer´), ξ = PEPSKit.peps_retract((peps, env_double_layer), η, α)\n " ,
309312 " ξ, (peps, env_double_layer), η, α, (peps´, env_double_layer´)\n " ,
310313 " )\n " ,
311314 " end;"
312- ],
313- "metadata" : {},
314- "execution_count" : null
315+ ]
315316 },
316317 {
317318 "cell_type" : " markdown" ,
319+ "metadata" : {},
318320 "source" : [
319321 " ### Finding the fixed point\n " ,
320322 " \n " ,
321323 " All that is left then is to specify the virtual spaces of the PEPS and the two environments,\n " ,
322324 " initialize them in the appropriate way, choose an optimization algortithm and call the\n " ,
323325 " `optimize` function from OptimKit.jl to get our desired PEPS fixed point."
324- ],
325- "metadata" : {}
326+ ]
326327 },
327328 {
328- "outputs" : [],
329329 "cell_type" : " code" ,
330+ "execution_count" : null ,
331+ "metadata" : {},
332+ "outputs" : [],
330333 "source" : [
331334 " Vpeps = ℂ^2\n " ,
332335 " Venv = ℂ^12\n " ,
345348 " retract = pepo_retract,\n " ,
346349 " (transport!) = (pepo_transport!),\n " ,
347350 " );"
348- ],
349- "metadata" : {},
350- "execution_count" : null
351+ ]
351352 },
352353 {
353354 "cell_type" : " markdown" ,
355+ "metadata" : {},
354356 "source" : [
355357 " ### Verifying the result\n " ,
356358 " \n " ,
357359 " Having found the fixed point, we have essentially contracted the entire partition function\n " ,
358360 " and we can start computing observables. The free energy per site for example is just given by\n " ,
359361 " the final value of the cost function we have just optimized."
360- ],
361- "metadata" : {}
362+ ]
362363 },
363364 {
364- "outputs" : [],
365365 "cell_type" : " code" ,
366+ "execution_count" : null ,
367+ "metadata" : {},
368+ "outputs" : [],
366369 "source" : [
367370 " @show f"
368- ],
369- "metadata" : {},
370- "execution_count" : null
371+ ]
371372 },
372373 {
373374 "cell_type" : " markdown" ,
375+ "metadata" : {},
374376 "source" : [
375377 " As another check, we can compute the magnetization per site and compare it to a [reference\n " ,
376378 " value obtaind through Monte-Carlo simulations](@cite hasenbusch_monte_2001)."
377- ],
378- "metadata" : {}
379+ ]
379380 },
380381 {
381- "outputs" : [],
382382 "cell_type" : " code" ,
383+ "execution_count" : null ,
384+ "metadata" : {},
385+ "outputs" : [],
383386 "source" : [
384387 " n3_final = InfiniteSquareNetwork(psi_final, T)\n " ,
385388 " num = PEPSKit.contract_local_tensor((1, 1, 1), M, n3_final, env3_final)\n " ,
389392 " m_ref = 0.667162\n " ,
390393 " \n " ,
391394 " @show abs(m - m_ref)"
392- ],
393- "metadata" : {},
394- "execution_count" : null
395+ ]
395396 },
396397 {
397398 "cell_type" : " markdown" ,
399+ "metadata" : {},
398400 "source" : [
399401 " ---\n " ,
400402 " \n " ,
401403 " *This notebook was generated using [Literate.jl](https://github.com/fredrikekre/Literate.jl).*"
402- ],
403- "metadata" : {}
404+ ]
404405 }
405406 ],
406- "nbformat_minor" : 3 ,
407407 "metadata" : {
408+ "kernelspec" : {
409+ "display_name" : " Julia 1.12.5" ,
410+ "language" : " julia" ,
411+ "name" : " julia-1.12"
412+ },
408413 "language_info" : {
409414 "file_extension" : " .jl" ,
410415 "mimetype" : " application/julia" ,
411416 "name" : " julia" ,
412417 "version" : " 1.12.5"
413- },
414- "kernelspec" : {
415- "name" : " julia-1.12" ,
416- "display_name" : " Julia 1.12.5" ,
417- "language" : " julia"
418418 }
419419 },
420- "nbformat" : 4
420+ "nbformat" : 4 ,
421+ "nbformat_minor" : 3
421422}
0 commit comments