dmrgpy 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (208) hide show
  1. dmrgpy/__init__.py +23 -0
  2. dmrgpy/algebra/__init__.py +0 -0
  3. dmrgpy/algebra/algebra.py +303 -0
  4. dmrgpy/algebra/arnolditk.py +414 -0
  5. dmrgpy/algebra/arpacktk.py +727 -0
  6. dmrgpy/algebra/fortran/algebra/algebraf90.f90 +15 -0
  7. dmrgpy/algebra/inverse.py +105 -0
  8. dmrgpy/algebra/kpm.py +636 -0
  9. dmrgpy/algebra/kpmextrapolate.py +138 -0
  10. dmrgpy/algebra/krylov.py +197 -0
  11. dmrgpy/algebra/parallel.py +75 -0
  12. dmrgpy/algebra/powermethod.py +87 -0
  13. dmrgpy/algebra/rootn.py +86 -0
  14. dmrgpy/analyticcontinuation.py +36 -0
  15. dmrgpy/atom.py +10 -0
  16. dmrgpy/atomtk/__init__.py +0 -0
  17. dmrgpy/atomtk/atomicbasis.py +203 -0
  18. dmrgpy/atomtk/iets.py +80 -0
  19. dmrgpy/bosonchain.py +115 -0
  20. dmrgpy/correlator.py +58 -0
  21. dmrgpy/cppext.py +64 -0
  22. dmrgpy/cvm.py +244 -0
  23. dmrgpy/dcex.py +137 -0
  24. dmrgpy/degeneracy.py +101 -0
  25. dmrgpy/densitymatrix.py +82 -0
  26. dmrgpy/distribution.py +56 -0
  27. dmrgpy/dmtk/__init__.py +0 -0
  28. dmrgpy/dmtk/densitymatrix.py +23 -0
  29. dmrgpy/dynamics.py +70 -0
  30. dmrgpy/dynamicstk/__init__.py +0 -0
  31. dmrgpy/dynamicstk/spincorrelators.py +33 -0
  32. dmrgpy/edtk/__init__.py +0 -0
  33. dmrgpy/edtk/distribution.py +61 -0
  34. dmrgpy/edtk/dynamics.py +312 -0
  35. dmrgpy/edtk/edchain.py +303 -0
  36. dmrgpy/edtk/finitetemperature.py +55 -0
  37. dmrgpy/edtk/one2many.py +23 -0
  38. dmrgpy/edtk/tdtk.py +104 -0
  39. dmrgpy/edtk/timedependent.py +70 -0
  40. dmrgpy/effectivehamiltonian.py +177 -0
  41. dmrgpy/entanglement.py +90 -0
  42. dmrgpy/entropy.py +101 -0
  43. dmrgpy/entropytk/__init__.py +0 -0
  44. dmrgpy/entropytk/correlationentropy.py +378 -0
  45. dmrgpy/excited.py +159 -0
  46. dmrgpy/extrapolate.py +21 -0
  47. dmrgpy/fermionchain.py +633 -0
  48. dmrgpy/fermionchaintk/__init__.py +0 -0
  49. dmrgpy/fermionchaintk/dynamicalcorrelator.py +98 -0
  50. dmrgpy/fermionchaintk/hamiltonian.py +35 -0
  51. dmrgpy/fermionchaintk/mop.py +99 -0
  52. dmrgpy/fermionchaintk/staticcorrelator.py +167 -0
  53. dmrgpy/fermionicparity.py +77 -0
  54. dmrgpy/fidelity.py +73 -0
  55. dmrgpy/filesystem.py +24 -0
  56. dmrgpy/functionfit.py +17 -0
  57. dmrgpy/funtk.py +36 -0
  58. dmrgpy/gap.py +32 -0
  59. dmrgpy/groundstate.py +291 -0
  60. dmrgpy/inference.py +36 -0
  61. dmrgpy/infinitechain.py +784 -0
  62. dmrgpy/juliapkg.json +18 -0
  63. dmrgpy/juliarun.py +58 -0
  64. dmrgpy/kondospectrumtk/conductance.py +182 -0
  65. dmrgpy/kondospectrumtk/dmrgtwotime.py +224 -0
  66. dmrgpy/kondospectrumtk/edkondo.py +55 -0
  67. dmrgpy/kondospectrumtk/edtwotimeref.py +76 -0
  68. dmrgpy/kondospectrumtk/potentialdc.py +69 -0
  69. dmrgpy/kondospectrumtk/secondorder_dc.py +95 -0
  70. dmrgpy/kondospectrumtk/stepfunctions.py +187 -0
  71. dmrgpy/kondospectrumtk/twotime.py +128 -0
  72. dmrgpy/kpmdmrg.py +245 -0
  73. dmrgpy/manybodychain.py +668 -0
  74. dmrgpy/maxenttk/pymaxent.py +222 -0
  75. dmrgpy/meanfield.py +57 -0
  76. dmrgpy/mixedchain.py +181 -0
  77. dmrgpy/mode.py +56 -0
  78. dmrgpy/mps.py +207 -0
  79. dmrgpy/mpsalgebra.py +230 -0
  80. dmrgpy/mpsalgebratk/__init__.py +0 -0
  81. dmrgpy/mpsalgebratk/disentangle.py +45 -0
  82. dmrgpy/mpsalgebratk/trace.py +38 -0
  83. dmrgpy/mpsjulia/commonmpsjulia.jl +16 -0
  84. dmrgpy/mpsjulia/compiler/packagecompile.jl +13 -0
  85. dmrgpy/mpsjulia/compiler/precompile_itensors.jl +15 -0
  86. dmrgpy/mpsjulia/customfermion.jl +77 -0
  87. dmrgpy/mpsjulia/get_gs.jl +26 -0
  88. dmrgpy/mpsjulia/get_input.jl +31 -0
  89. dmrgpy/mpsjulia/get_sites.jl +39 -0
  90. dmrgpy/mpsjulia/get_vev.jl +45 -0
  91. dmrgpy/mpsjulia/gs_energy.jl +16 -0
  92. dmrgpy/mpsjulia/kpm.jl +104 -0
  93. dmrgpy/mpsjulia/mpsalgebra.jl +59 -0
  94. dmrgpy/mpsjulia/mpsjulia.jl +36 -0
  95. dmrgpy/mpsjulia/read_operator.jl +43 -0
  96. dmrgpy/mpsjulia/read_wf.jl +11 -0
  97. dmrgpy/mpsjulia/write_in_file.jl +37 -0
  98. dmrgpy/mpsjulialive/__init__.py +0 -0
  99. dmrgpy/mpsjulialive/densitymatrix.jl +23 -0
  100. dmrgpy/mpsjulialive/densitymatrix.py +12 -0
  101. dmrgpy/mpsjulialive/dynamics.py +181 -0
  102. dmrgpy/mpsjulialive/entropy.jl +26 -0
  103. dmrgpy/mpsjulialive/entropy.py +6 -0
  104. dmrgpy/mpsjulialive/excited.jl +34 -0
  105. dmrgpy/mpsjulialive/excited.py +40 -0
  106. dmrgpy/mpsjulialive/generalized.jl +203 -0
  107. dmrgpy/mpsjulialive/generalized.py +79 -0
  108. dmrgpy/mpsjulialive/get_gs.jl +104 -0
  109. dmrgpy/mpsjulialive/groundstate.py +42 -0
  110. dmrgpy/mpsjulialive/juliasession.py +61 -0
  111. dmrgpy/mpsjulialive/kpm.jl +79 -0
  112. dmrgpy/mpsjulialive/metts.jl +335 -0
  113. dmrgpy/mpsjulialive/metts.py +87 -0
  114. dmrgpy/mpsjulialive/mpo.py +69 -0
  115. dmrgpy/mpsjulialive/mps.py +147 -0
  116. dmrgpy/mpsjulialive/mpsalgebra.jl +84 -0
  117. dmrgpy/mpsjulialive/nhdmrg.jl +259 -0
  118. dmrgpy/mpsjulialive/nhdmrg.py +95 -0
  119. dmrgpy/mpsjulialive/randommps.py +109 -0
  120. dmrgpy/mpsjulialive/read_operator.jl +36 -0
  121. dmrgpy/mpsjulialive/sites.jl +21 -0
  122. dmrgpy/mpsjulialive/sites.py +16 -0
  123. dmrgpy/mpsjulialive/tdvp.jl +204 -0
  124. dmrgpy/mpsjulialive/timedependent.py +120 -0
  125. dmrgpy/mpsjulialive/vev.py +8 -0
  126. dmrgpy/multioperator.py +399 -0
  127. dmrgpy/multioperatortk/__init__.py +0 -0
  128. dmrgpy/multioperatortk/jordanwigner.py +83 -0
  129. dmrgpy/multioperatortk/jordanwigner_spinful.py +69 -0
  130. dmrgpy/multioperatortk/longoperator.py +42 -0
  131. dmrgpy/multioperatortk/staticoperator.py +80 -0
  132. dmrgpy/multioperatortk/sympymultioperator.py +86 -0
  133. dmrgpy/nhdmrg.py +334 -0
  134. dmrgpy/nonhermitian/__init__.py +0 -0
  135. dmrgpy/nonhermitian/dynamics.py +41 -0
  136. dmrgpy/nonhermitian/kpm.py +86 -0
  137. dmrgpy/operatornames.py +100 -0
  138. dmrgpy/padetk/__init__.py +0 -0
  139. dmrgpy/padetk/bruteforcepade.py +43 -0
  140. dmrgpy/padetk/taylorpade.py +15 -0
  141. dmrgpy/parafermionchain.py +83 -0
  142. dmrgpy/parallel.py +84 -0
  143. dmrgpy/parallelslurm.py +176 -0
  144. dmrgpy/pyboson/__init__.py +0 -0
  145. dmrgpy/pyboson/boson.py +74 -0
  146. dmrgpy/pychain/__init__.py +0 -0
  147. dmrgpy/pychain/build.py +57 -0
  148. dmrgpy/pychain/chain.py +133 -0
  149. dmrgpy/pychainwrapper.py +144 -0
  150. dmrgpy/pyfermion/__init__.py +0 -0
  151. dmrgpy/pyfermion/mbfermion.py +236 -0
  152. dmrgpy/pyfermion/states.py +216 -0
  153. dmrgpy/pyitensor/__init__.py +39 -0
  154. dmrgpy/pyitensor/autompo.py +164 -0
  155. dmrgpy/pyitensor/chain.py +1173 -0
  156. dmrgpy/pyitensor/dmrg.py +658 -0
  157. dmrgpy/pyitensor/gse.py +171 -0
  158. dmrgpy/pyitensor/idmrg.py +2092 -0
  159. dmrgpy/pyitensor/idmrg_excitations.py +693 -0
  160. dmrgpy/pyitensor/idmrg_window.py +1067 -0
  161. dmrgpy/pyitensor/index.py +122 -0
  162. dmrgpy/pyitensor/kernels.py +423 -0
  163. dmrgpy/pyitensor/kpm_energy_truncation.py +179 -0
  164. dmrgpy/pyitensor/metts.py +611 -0
  165. dmrgpy/pyitensor/mpobuilder.py +100 -0
  166. dmrgpy/pyitensor/mpsalgebra.py +317 -0
  167. dmrgpy/pyitensor/mpscontainer.py +160 -0
  168. dmrgpy/pyitensor/nhdmrg.py +384 -0
  169. dmrgpy/pyitensor/sites/__init__.py +15 -0
  170. dmrgpy/pyitensor/sites/base.py +74 -0
  171. dmrgpy/pyitensor/sites/boson.py +61 -0
  172. dmrgpy/pyitensor/sites/fermion.py +78 -0
  173. dmrgpy/pyitensor/sites/parafermion.py +57 -0
  174. dmrgpy/pyitensor/sites/siteset.py +73 -0
  175. dmrgpy/pyitensor/sites/spin.py +129 -0
  176. dmrgpy/pyitensor/svd.py +118 -0
  177. dmrgpy/pyitensor/sweeps.py +48 -0
  178. dmrgpy/pyitensor/tdvp.py +329 -0
  179. dmrgpy/pyitensor/tebd.py +183 -0
  180. dmrgpy/pyitensor/tensor.py +299 -0
  181. dmrgpy/pyparafermion/__init__.py +0 -0
  182. dmrgpy/pyparafermion/parafermion.py +77 -0
  183. dmrgpy/pyspin/__init__.py +0 -0
  184. dmrgpy/pyspin/spin.py +12 -0
  185. dmrgpy/pyzn/__init__.py +0 -0
  186. dmrgpy/pyzn/zn.py +30 -0
  187. dmrgpy/randommps.py +103 -0
  188. dmrgpy/reconstruct.py +58 -0
  189. dmrgpy/rootndmrg.py +130 -0
  190. dmrgpy/sites.py +28 -0
  191. dmrgpy/spinchain.py +295 -0
  192. dmrgpy/spinfermionchain.py +8 -0
  193. dmrgpy/tdz.py +257 -0
  194. dmrgpy/thermal.py +87 -0
  195. dmrgpy/timedependent.py +306 -0
  196. dmrgpy/timeevolution.py +55 -0
  197. dmrgpy/topology.py +72 -0
  198. dmrgpy/vev.py +55 -0
  199. dmrgpy/vevtk/__init__.py +0 -0
  200. dmrgpy/vevtk/mettsdynamicalcorrelator.py +174 -0
  201. dmrgpy/vevtk/mettsvev.py +158 -0
  202. dmrgpy/vevtk/thermalvev.py +46 -0
  203. dmrgpy/wavefunction.py +29 -0
  204. dmrgpy-0.1.0.dist-info/METADATA +618 -0
  205. dmrgpy-0.1.0.dist-info/RECORD +208 -0
  206. dmrgpy-0.1.0.dist-info/WHEEL +5 -0
  207. dmrgpy-0.1.0.dist-info/licenses/LICENSE.md +674 -0
  208. dmrgpy-0.1.0.dist-info/top_level.txt +1 -0
dmrgpy/__init__.py ADDED
@@ -0,0 +1,23 @@
1
+ import warnings as _warnings
2
+
3
+ from . import cppext as _cppext
4
+
5
+ if not _cppext.available(_cppext.DEFAULT_ITENSOR_VERSION):
6
+ # Two very different audiences hit this warning, so it has to serve both.
7
+ # From a git checkout, the fix is to compile the extension with
8
+ # install.py. From a PyPI install there *is* no install.py -- the wheel
9
+ # deliberately ships no C++ at all (see pyproject.toml) -- and the real
10
+ # answer is itensor_version="python", the pure-Python DMRG backend, which
11
+ # always works and is far faster than the ED fallback on larger chains.
12
+ # Mentioning only install.py would send pip users chasing a file they
13
+ # don't have.
14
+ _warnings.warn(
15
+ "ITensor v%s (dmrgpy's default C++ DMRG backend) is not compiled, so "
16
+ "chains fall back to exact diagonalization, which does not scale past "
17
+ "small systems. For real DMRG without compiling anything, use the "
18
+ "pure-Python backend: Spin_Chain(..., itensor_version=\"python\") or "
19
+ "chain.setup_python(). To build the (faster) C++ backend instead, run "
20
+ "`python install.py --itensor-version=%s` from a clone of the dmrgpy "
21
+ "repository."
22
+ % (_cppext.DEFAULT_ITENSOR_VERSION, _cppext.DEFAULT_ITENSOR_VERSION),
23
+ stacklevel=2)
File without changes
@@ -0,0 +1,303 @@
1
+ from scipy.sparse import issparse
2
+ from scipy.sparse import csc_matrix as csc
3
+ import scipy.linalg as dlg
4
+ import scipy.sparse.linalg as slg
5
+ import numpy as np
6
+
7
+
8
+ det = dlg.det
9
+
10
+ maxsize = 2000
11
+ tol = 1e-7 # tolerancy
12
+ maxiter = 1e6 # maximum number of iterations
13
+
14
+
15
+
16
+ def braket_wAw(w,A,wi=None):
17
+ """
18
+ Compute the braket of a wavefunction
19
+ """
20
+ if wi is None: wi = w
21
+ if issparse(A): # sparse matrices
22
+ return (np.conjugate(wi)@A@w) # modern way
23
+ else: # matrices and arrays
24
+ if len(w.shape)==1: return (np.conjugate(wi)@A@w) # modern way
25
+ else: return (np.conjugate(wi)@A@w)[0,0] # modern way
26
+
27
+
28
+
29
+ def dagger(m):
30
+ return np.conjugate(m.T)
31
+
32
+
33
+ def braket_ww(w,wi):
34
+ """
35
+ Compute the braket of two wavefunctions
36
+ """
37
+ w = matrix2vector(w) # convert to vector
38
+ wi = matrix2vector(wi) # convert to vector
39
+ return (np.conjugate(w)@wi) # modern way
40
+
41
+
42
+
43
+
44
+ def disentangle_manifold(wfs,A):
45
+ """
46
+ Disentangles the wavefunctions of a degenerate manifold
47
+ by expressing them in terms of eigenvalues of an input operator
48
+ """
49
+ ma = get_representation(wfs,A) # get the matrix form of the operator
50
+ wfsout = [] # empty list
51
+ evals,evecs = dlg.eigh(ma) # diagonalize
52
+
53
+ evecs = evecs.transpose() # transpose eigenvectors
54
+ for v in evecs: # loop over eigenvectors
55
+ wf = wfs[0]*0.0j
56
+ for (i,iv) in zip(range(len(v)),v): # loop over components
57
+ wf += iv*wfs[i] # add contribution
58
+ wfsout.append(wf.copy()) # store wavefunction
59
+ return wfsout
60
+
61
+
62
+
63
+ def get_representation(wfs,A):
64
+ """
65
+ Gets the matrix representation of a certain operator
66
+ """
67
+ n = len(wfs) # number of eigenfunctions
68
+ ma = np.zeros((n,n),dtype=np.complex128) # representation of A
69
+ sa = csc(A) # sparse matrix
70
+ for i in range(n):
71
+ vi = csc(np.conjugate(wfs[i])) # first wavefunction
72
+ for j in range(n):
73
+ vj = csc(wfs[j]).transpose() # second wavefunction
74
+ data = (vi@sa@vj).todense()[0,0]
75
+ ma[i,j] = data
76
+ return ma
77
+
78
+
79
+
80
+
81
+
82
+ ## routines for diagonalization ##
83
+
84
+ error = 1e-7
85
+
86
+
87
+
88
+ accelerate = False
89
+
90
+ def eigh(m):
91
+ """Wrapper for linalg"""
92
+ m = todense(m)
93
+ o = dlg.eigh(m)
94
+ return o
95
+
96
+ def eigvalsh(m):
97
+ """Wrapper for linalg"""
98
+ m = todense(m)
99
+ return dlg.eigvalsh(m)
100
+
101
+
102
+ def matrix2vector(v):
103
+ """Transform a matrix into a vector"""
104
+ if issparse(v): # sparse matrix
105
+ v = v.todense() # convert to conventional matrix
106
+ v = np.array(v) # convert to array
107
+ if len(v.shape)==1: return v
108
+ else: return v.reshape(v.shape[0]*v.shape[1])
109
+
110
+
111
+ def ground_state(h,nmax=maxsize):
112
+ """Get a ground state"""
113
+ info = False
114
+ if h.shape[0]>nmax:
115
+ if info: print("Calling ARPACK")
116
+ try:
117
+ eig,eigvec = slg.eigsh(h,k=10,which="SA",maxiter=int(maxiter))
118
+ except:
119
+ eig,eigvec = slg.eigsh(h,k=10,which="SA",maxiter=int(maxiter),tol=tol)
120
+ eig = np.sort(eig)
121
+ else:
122
+ if info: print("Full diagonalization")
123
+ eig,eigvec = dlg.eigh(todense(h))
124
+ return eig[0],eigvec.transpose()[0]
125
+
126
+
127
+ def todense(m):
128
+ """Turn a matrix dense"""
129
+ if issparse(m):
130
+ if m.shape[0]>maxsize: raise
131
+ else: return m.todense()
132
+ else: return m
133
+
134
+
135
+ def lowest_eigenvalues(h,n=10):
136
+ """Get a ground state"""
137
+ info = False
138
+ if h.shape[0]>maxsize: # for sparse use arpack
139
+ eig,vs = lowest_states(h,n=n)
140
+ else:
141
+ if info: print("Full diagonalization")
142
+ if ishermitian(h):
143
+ eig = dlg.eigvalsh(h.todense())
144
+ else:
145
+ eig = dlg.eigvals(h.todense())
146
+ eig,eigvec = sorteigen(eig,eig)
147
+ return np.array(eig[0:n])
148
+
149
+
150
+ def lowest_states(h,n=10,**kwargs):
151
+ """Get a ground state"""
152
+ nmax = maxsize
153
+ info = False
154
+ if h.shape[0]>nmax:
155
+ if info: print("Calling ARPACK")
156
+ if ishermitian(h): # Hermitian matrix
157
+ eig,eigvec = slg.eigsh(h,k=n,which="SA",maxiter=int(maxiter),tol=tol)
158
+ eig,eigvec = sorteigen(eig,eigvec.T)
159
+ return (eig,eigvec)
160
+ else:
161
+ eig,eigvec = slg.eigs(h,k=n,which="SR",maxiter=int(maxiter),tol=tol)
162
+ eig,eigvec = sorteigen(eig,eigvec.T)
163
+ return (eig,eigvec)
164
+ else:
165
+ if info: print("Full diagonalization")
166
+ if ishermitian(h): # Hermitian matrix
167
+ eig,vs = dlg.eigh(h.todense())
168
+ return eig[0:n],vs.T[0:n]
169
+ else: # non Hermitian matrix
170
+ eig,vs = dlg.eig(h.todense())
171
+ eig,vs = sorteigen(eig,vs.T)
172
+ return eig[0:n],vs[0:n]
173
+
174
+ lowest_eigenvectors = lowest_states
175
+
176
+
177
+ def biorthogonal_ground_state(h,**kwargs):
178
+ """Return (e0,vr,vl), the ground state of a (possibly non-Hermitian)
179
+ matrix h as a biorthogonal right/left pair: h@vr = e0*vr and
180
+ dagger(h)@vl = conj(e0)*vl, normalized so that conj(vl)@vr = 1 (the
181
+ convention needed by braket_ww-style expectation values). vr/vl pick
182
+ the state with smallest real part of the eigenvalue, matching
183
+ lowest_states' own non-Hermitian ordering."""
184
+ er,vsr = lowest_states(h,n=1,**kwargs)
185
+ el,vsl = lowest_states(dagger(h),n=1,**kwargs)
186
+ vr = matrix2vector(vsr[0])
187
+ vl = matrix2vector(vsl[0])
188
+ norm = np.conjugate(vl)@vr
189
+ if np.abs(norm)<1e-8:
190
+ raise ValueError("Right and left ground states are (near) "
191
+ "orthogonal, <vl|vr> = "+str(norm)+" - biorthogonal "
192
+ "normalization failed")
193
+ vl = vl/np.conjugate(norm)
194
+ return er[0],vr,vl
195
+
196
+ def sorteigen(eig,vs):
197
+ """Return sorted eigenvalues and eigenvectors"""
198
+ w = eig - np.min(eig.real) # smallest real part
199
+ imweight = 1e-3 # how much to weight im when sorting
200
+ wz = w.real + imweight*w.imag
201
+ vs = [y for (x,y) in sorted(zip(wz,vs),key=lambda x: x[0])]
202
+ eig = [y.copy() for (x,y) in sorted(zip(wz,eig),key=lambda x: x[0])]
203
+ return np.array(eig),vs
204
+
205
+
206
+
207
+ def ishermitian(m):
208
+ """Check if a matrix is Hermitian"""
209
+ d = m - np.conjugate(m.T)
210
+ if np.max(np.abs(d))>1e-6: return False
211
+ return True
212
+
213
+ def expm(m):
214
+ """Compute exponential"""
215
+ m = todense(m)
216
+ return dlg.expm(m)
217
+
218
+
219
+ def inv(m):
220
+ """Inverse"""
221
+ m = todense(m)
222
+ return dlg.inv(m)
223
+
224
+
225
+
226
+ def expm(m):
227
+ m = todense(m)
228
+ return dlg.expm(m) # exponential matrix
229
+
230
+ #def expm(m):
231
+ # m = todense(m)
232
+ # es,vs = dlg.eig(m)
233
+ # d = np.zeros(m.shape,dtype=np.complex128)
234
+ # for i in range(len(es)): d[i,i] = np.exp(es[i])
235
+ # R = vs.T
236
+ # Rh = np.conjugate(R.T)
237
+ # U = Rh@d@R
238
+ # return U
239
+
240
+
241
+
242
+ def ismatrix(m):
243
+ return type(m)==np.ndarray or issparse(m) or type(m)==np.matrix
244
+
245
+
246
+
247
+
248
+
249
+ def smooth_gauge(w1,w2):
250
+ """Perform a gauge rotation so that the second set of waves are smooth
251
+ with respect to the first one"""
252
+ m = uij(w1,w2) # matrix of wavefunctions
253
+ U, s, V = np.linalg.svd(m, full_matrices=True) # sing val decomp
254
+ R = np.conjugate(U@V).T # rotation matrix
255
+ wnew = [w.copy()*0. for w in w2] # new WF
256
+ wold = [w.copy() for w in w2] # old WF
257
+ for ii in range(R.shape[0]):
258
+ for jj in range(R.shape[0]):
259
+ wnew[ii] = wnew[ii] + R[jj,ii]*wold[jj]
260
+ return wnew
261
+
262
+
263
+
264
+ def uij(wf1,wf2):
265
+ m = np.matrix(np.zeros((len(wf1),len(wf2)),dtype=np.complex128))
266
+ for i in range(len(wf1)):
267
+ for j in range(len(wf2)):
268
+ m[i,j] = wf1[i].dot(wf2[j])
269
+ return m
270
+
271
+
272
+ def trace(A):
273
+ """Compute trace"""
274
+ if issparse(A): return A.trace()
275
+ else: return np.trace(A)
276
+
277
+
278
+
279
+ def is_hermitian(h,**kwargs):
280
+ h = h - dagger(h) # difference
281
+ return is_zero_matrix(h,**kwargs)
282
+
283
+
284
+ def is_zero_matrix(h,tol=1e-8):
285
+ h = h@dagger(h)
286
+ t = np.abs(trace(h)) # this should be a trace
287
+ return t<tol
288
+
289
+
290
+
291
+ def applyinverse(A,b):
292
+ """Apply A^-1 to b"""
293
+ if A.shape[0]<30: return inv(A)@b
294
+ else: return slg.spsolve(A,b)
295
+
296
+
297
+
298
+
299
+
300
+
301
+
302
+
303
+