11import numpy as np
22from timeit import default_timer as timer
33from pyblock2 .driver .core import DMRGDriver , SymmetryTypes , MPOAlgorithmTypes
4+ import random
45
5- L = 100
6- N = L
7- TWOSZ = 0
6+ def fermi_hubbard (N , alg , t = 1 , U = 4 , J = 0 ):
7+ start = timer ()
8+
9+ driver = DMRGDriver (scratch = "./tmp" , symm_type = SymmetryTypes .SZ , n_threads = 4 )
10+ driver .initialize_system (n_sites = N , n_elec = N , spin = 0 )
811
9- driver = DMRGDriver (scratch = "./tmp" , symm_type = SymmetryTypes .SZ , n_threads = 4 )
10- driver .initialize_system (n_sites = L , n_elec = N , spin = TWOSZ )
12+ b = driver .expr_builder ()
1113
12- t = 1
13- U = 4
14+ epsilon = lambda k : 2 * np .cos (2 * np .pi * k / N )
1415
15- b = driver .expr_builder ()
16+ # Kinetic term
17+ for k in range (N ):
18+ b .add_term ("cd" , np .array ([k , k ]), - t * epsilon (k ))
19+ b .add_term ("CD" , np .array ([k , k ]), - t * epsilon (k ))
1620
17- epsilon = lambda k : 2 * np .cos (2 * np .pi * k / L )
21+ # Interaction term
22+ for p in range (N ):
23+ for q in range (N ):
24+ for k in range (N ):
25+ if J == 0 :
26+ b .add_term ("cCDd" , np .array ([(p - k ) % N , (q + k ) % N , q , p ]), U / N )
27+ else :
28+ factor = U - t * ((np .exp (J ) - 1 ) * epsilon (p - k ) + (np .exp (- J ) - 1 ) * epsilon (p ))
29+ b .add_term ("cCDd" , np .array ([(p - k ) % N , (q + k ) % N , q , p ]), factor / N )
30+ b .add_term ("CcdD" , np .array ([(p - k ) % N , (q + k ) % N , q , p ]), factor / N )
1831
19- # Kinetic term
20- for k in range (L ):
21- b .add_term ("cd" , np .array ([k , k ]), - t * epsilon (k ))
22- b .add_term ("CD" , np .array ([k , k ]), - t * epsilon (k ))
32+ if J != 0 :
33+ prefactor = 2 * t * (np .cosh (J ) - 1 ) / N ** 2
34+ for p in range (N ):
35+ for q in range (N ):
36+ for s in range (N ):
37+ for k in range (N ):
38+ for kp in range (N ):
39+ factor = prefactor * epsilon (p - (k - kp ))
40+ b .add_term ("cCCDDd" , np .array ([(p - k ) % N , (q + kp ) % N , (s + k - kp ) % N , s , q , p ]), factor )
41+ b .add_term ("CccddD" , np .array ([(p - k ) % N , (q + kp ) % N , (s + k - kp ) % N , s , q , p ]), factor )
2342
24- # Interaction term
25- sites = np .zeros (4 * L * L * L , dtype = np .int16 )
26- for p in range (L ):
27- for q in range (L ):
28- for k in range (L ):
29- b .add_term ("cCDd" , np .array ([(p - k ) % L , (q + k ) % L , q , p ]), U )
43+ print ("Done constructing representation." )
3044
31- print ("Done constructing representation." )
45+ b = b .finalize ()
46+ print ("Done finalizing representation." )
3247
33- alg = MPOAlgorithmTypes .SVD | MPOAlgorithmTypes .Blocked
34- # alg = MPOAlgorithmTypes.SVD | MPOAlgorithmTypes.Fast | MPOAlgorithmTypes.Blocked | MPOAlgorithmTypes.Disjoint
35- start = timer ()
36- mpo = driver .get_mpo (b .finalize (), iprint = 1 , algo_type = alg )
37- stop = timer ()
38- print (f"N = { L } , time = { stop - start } " )
48+ mpo = driver .get_mpo (b , iprint = 1 , algo_type = alg )
49+ stop = timer ()
50+ print (f"N = { N } , time = { stop - start } " )
51+
52+
53+ def get_coefficients (N ):
54+ rng = np .random .default_rng (0 )
55+ one_electron = rng .normal (size = (N , N ))
56+ two_electron = rng .normal (size = (N , 2 , N , 2 , N , 2 , N , 2 ))
57+
58+ return one_electron , two_electron
59+
60+ def electronic_structure (N , alg ):
61+ one_electron_coeffs , two_electron_coeffs = get_coefficients (N )
62+
63+ start = timer ()
64+ driver = DMRGDriver (scratch = "./tmp" , symm_type = SymmetryTypes .SZ , n_threads = 8 )
65+ driver .initialize_system (n_sites = N , n_elec = N , spin = 0 , orb_sym = None )
66+
67+ builder = driver .expr_builder ()
68+
69+ c = lambda spin : "c" if (spin == 0 ) else "C"
70+ d = lambda spin : "d" if (spin == 0 ) else "D"
71+
72+ for a in range (N ):
73+ for b in range (a , N ):
74+ factor = one_electron_coeffs [a , b ]
75+ for spin in (0 , 1 ):
76+ sites = np .array ([a , b ])
77+ builder .add_term (c (spin ) + d (spin ), sites , factor )
78+
79+ if a != b :
80+ sites = [b , a ]
81+ builder .add_term (c (spin ) + d (spin ), sites , factor )
82+
83+ for j in range (N ):
84+ for s_j in (0 , 1 ):
85+
86+ for k in range (N ):
87+ s_k = s_j
88+ if (s_k , k ) <= (s_j , j ):
89+ continue
90+
91+ for l in range (N ):
92+ for s_l in (0 , 1 ):
93+ if (s_l , l ) <= (s_j , j ):
94+ continue
95+
96+ for m in range (N ):
97+ s_m = s_l
98+ if (s_m , m ) <= (s_k , k ):
99+ continue
100+
101+ factor = two_electron_coeffs [j , s_j , l , s_l , m , s_m , k , s_k ]
102+ sites = np .array ([j , l , m , k ])
103+ builder .add_term (c (s_j ) + c (s_l ) + d (s_m ) + d (s_k ), sites , factor )
104+
105+ sites = np .flip (sites )
106+ builder .add_term (c (s_k ) + c (s_m ) + d (s_l ) + d (s_j ), sites , factor )
107+
108+ print ("Done constructing representation." )
109+
110+ builder = builder .finalize ()
111+ print ("Done finalizing representation." )
112+
113+ mpo = driver .get_mpo (builder , iprint = 1 , algo_type = alg )
114+ stop = timer ()
115+ print (f"N = { N } , time = { stop - start } " )
116+
117+
118+ for N in [10 ]:
119+ fermi_hubbard (N , MPOAlgorithmTypes .FastBlockedDisjointSVD )
120+ print ()
121+
122+ for N in [10 , 10 , 20 , 30 , 40 , 50 , 60 , 70 ]:
123+ electronic_structure (N , MPOAlgorithmTypes .FastBipartite )
124+ print ()
0 commit comments