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.
- dmrgpy/__init__.py +23 -0
- dmrgpy/algebra/__init__.py +0 -0
- dmrgpy/algebra/algebra.py +303 -0
- dmrgpy/algebra/arnolditk.py +414 -0
- dmrgpy/algebra/arpacktk.py +727 -0
- dmrgpy/algebra/fortran/algebra/algebraf90.f90 +15 -0
- dmrgpy/algebra/inverse.py +105 -0
- dmrgpy/algebra/kpm.py +636 -0
- dmrgpy/algebra/kpmextrapolate.py +138 -0
- dmrgpy/algebra/krylov.py +197 -0
- dmrgpy/algebra/parallel.py +75 -0
- dmrgpy/algebra/powermethod.py +87 -0
- dmrgpy/algebra/rootn.py +86 -0
- dmrgpy/analyticcontinuation.py +36 -0
- dmrgpy/atom.py +10 -0
- dmrgpy/atomtk/__init__.py +0 -0
- dmrgpy/atomtk/atomicbasis.py +203 -0
- dmrgpy/atomtk/iets.py +80 -0
- dmrgpy/bosonchain.py +115 -0
- dmrgpy/correlator.py +58 -0
- dmrgpy/cppext.py +64 -0
- dmrgpy/cvm.py +244 -0
- dmrgpy/dcex.py +137 -0
- dmrgpy/degeneracy.py +101 -0
- dmrgpy/densitymatrix.py +82 -0
- dmrgpy/distribution.py +56 -0
- dmrgpy/dmtk/__init__.py +0 -0
- dmrgpy/dmtk/densitymatrix.py +23 -0
- dmrgpy/dynamics.py +70 -0
- dmrgpy/dynamicstk/__init__.py +0 -0
- dmrgpy/dynamicstk/spincorrelators.py +33 -0
- dmrgpy/edtk/__init__.py +0 -0
- dmrgpy/edtk/distribution.py +61 -0
- dmrgpy/edtk/dynamics.py +312 -0
- dmrgpy/edtk/edchain.py +303 -0
- dmrgpy/edtk/finitetemperature.py +55 -0
- dmrgpy/edtk/one2many.py +23 -0
- dmrgpy/edtk/tdtk.py +104 -0
- dmrgpy/edtk/timedependent.py +70 -0
- dmrgpy/effectivehamiltonian.py +177 -0
- dmrgpy/entanglement.py +90 -0
- dmrgpy/entropy.py +101 -0
- dmrgpy/entropytk/__init__.py +0 -0
- dmrgpy/entropytk/correlationentropy.py +378 -0
- dmrgpy/excited.py +159 -0
- dmrgpy/extrapolate.py +21 -0
- dmrgpy/fermionchain.py +633 -0
- dmrgpy/fermionchaintk/__init__.py +0 -0
- dmrgpy/fermionchaintk/dynamicalcorrelator.py +98 -0
- dmrgpy/fermionchaintk/hamiltonian.py +35 -0
- dmrgpy/fermionchaintk/mop.py +99 -0
- dmrgpy/fermionchaintk/staticcorrelator.py +167 -0
- dmrgpy/fermionicparity.py +77 -0
- dmrgpy/fidelity.py +73 -0
- dmrgpy/filesystem.py +24 -0
- dmrgpy/functionfit.py +17 -0
- dmrgpy/funtk.py +36 -0
- dmrgpy/gap.py +32 -0
- dmrgpy/groundstate.py +291 -0
- dmrgpy/inference.py +36 -0
- dmrgpy/infinitechain.py +784 -0
- dmrgpy/juliapkg.json +18 -0
- dmrgpy/juliarun.py +58 -0
- dmrgpy/kondospectrumtk/conductance.py +182 -0
- dmrgpy/kondospectrumtk/dmrgtwotime.py +224 -0
- dmrgpy/kondospectrumtk/edkondo.py +55 -0
- dmrgpy/kondospectrumtk/edtwotimeref.py +76 -0
- dmrgpy/kondospectrumtk/potentialdc.py +69 -0
- dmrgpy/kondospectrumtk/secondorder_dc.py +95 -0
- dmrgpy/kondospectrumtk/stepfunctions.py +187 -0
- dmrgpy/kondospectrumtk/twotime.py +128 -0
- dmrgpy/kpmdmrg.py +245 -0
- dmrgpy/manybodychain.py +668 -0
- dmrgpy/maxenttk/pymaxent.py +222 -0
- dmrgpy/meanfield.py +57 -0
- dmrgpy/mixedchain.py +181 -0
- dmrgpy/mode.py +56 -0
- dmrgpy/mps.py +207 -0
- dmrgpy/mpsalgebra.py +230 -0
- dmrgpy/mpsalgebratk/__init__.py +0 -0
- dmrgpy/mpsalgebratk/disentangle.py +45 -0
- dmrgpy/mpsalgebratk/trace.py +38 -0
- dmrgpy/mpsjulia/commonmpsjulia.jl +16 -0
- dmrgpy/mpsjulia/compiler/packagecompile.jl +13 -0
- dmrgpy/mpsjulia/compiler/precompile_itensors.jl +15 -0
- dmrgpy/mpsjulia/customfermion.jl +77 -0
- dmrgpy/mpsjulia/get_gs.jl +26 -0
- dmrgpy/mpsjulia/get_input.jl +31 -0
- dmrgpy/mpsjulia/get_sites.jl +39 -0
- dmrgpy/mpsjulia/get_vev.jl +45 -0
- dmrgpy/mpsjulia/gs_energy.jl +16 -0
- dmrgpy/mpsjulia/kpm.jl +104 -0
- dmrgpy/mpsjulia/mpsalgebra.jl +59 -0
- dmrgpy/mpsjulia/mpsjulia.jl +36 -0
- dmrgpy/mpsjulia/read_operator.jl +43 -0
- dmrgpy/mpsjulia/read_wf.jl +11 -0
- dmrgpy/mpsjulia/write_in_file.jl +37 -0
- dmrgpy/mpsjulialive/__init__.py +0 -0
- dmrgpy/mpsjulialive/densitymatrix.jl +23 -0
- dmrgpy/mpsjulialive/densitymatrix.py +12 -0
- dmrgpy/mpsjulialive/dynamics.py +181 -0
- dmrgpy/mpsjulialive/entropy.jl +26 -0
- dmrgpy/mpsjulialive/entropy.py +6 -0
- dmrgpy/mpsjulialive/excited.jl +34 -0
- dmrgpy/mpsjulialive/excited.py +40 -0
- dmrgpy/mpsjulialive/generalized.jl +203 -0
- dmrgpy/mpsjulialive/generalized.py +79 -0
- dmrgpy/mpsjulialive/get_gs.jl +104 -0
- dmrgpy/mpsjulialive/groundstate.py +42 -0
- dmrgpy/mpsjulialive/juliasession.py +61 -0
- dmrgpy/mpsjulialive/kpm.jl +79 -0
- dmrgpy/mpsjulialive/metts.jl +335 -0
- dmrgpy/mpsjulialive/metts.py +87 -0
- dmrgpy/mpsjulialive/mpo.py +69 -0
- dmrgpy/mpsjulialive/mps.py +147 -0
- dmrgpy/mpsjulialive/mpsalgebra.jl +84 -0
- dmrgpy/mpsjulialive/nhdmrg.jl +259 -0
- dmrgpy/mpsjulialive/nhdmrg.py +95 -0
- dmrgpy/mpsjulialive/randommps.py +109 -0
- dmrgpy/mpsjulialive/read_operator.jl +36 -0
- dmrgpy/mpsjulialive/sites.jl +21 -0
- dmrgpy/mpsjulialive/sites.py +16 -0
- dmrgpy/mpsjulialive/tdvp.jl +204 -0
- dmrgpy/mpsjulialive/timedependent.py +120 -0
- dmrgpy/mpsjulialive/vev.py +8 -0
- dmrgpy/multioperator.py +399 -0
- dmrgpy/multioperatortk/__init__.py +0 -0
- dmrgpy/multioperatortk/jordanwigner.py +83 -0
- dmrgpy/multioperatortk/jordanwigner_spinful.py +69 -0
- dmrgpy/multioperatortk/longoperator.py +42 -0
- dmrgpy/multioperatortk/staticoperator.py +80 -0
- dmrgpy/multioperatortk/sympymultioperator.py +86 -0
- dmrgpy/nhdmrg.py +334 -0
- dmrgpy/nonhermitian/__init__.py +0 -0
- dmrgpy/nonhermitian/dynamics.py +41 -0
- dmrgpy/nonhermitian/kpm.py +86 -0
- dmrgpy/operatornames.py +100 -0
- dmrgpy/padetk/__init__.py +0 -0
- dmrgpy/padetk/bruteforcepade.py +43 -0
- dmrgpy/padetk/taylorpade.py +15 -0
- dmrgpy/parafermionchain.py +83 -0
- dmrgpy/parallel.py +84 -0
- dmrgpy/parallelslurm.py +176 -0
- dmrgpy/pyboson/__init__.py +0 -0
- dmrgpy/pyboson/boson.py +74 -0
- dmrgpy/pychain/__init__.py +0 -0
- dmrgpy/pychain/build.py +57 -0
- dmrgpy/pychain/chain.py +133 -0
- dmrgpy/pychainwrapper.py +144 -0
- dmrgpy/pyfermion/__init__.py +0 -0
- dmrgpy/pyfermion/mbfermion.py +236 -0
- dmrgpy/pyfermion/states.py +216 -0
- dmrgpy/pyitensor/__init__.py +39 -0
- dmrgpy/pyitensor/autompo.py +164 -0
- dmrgpy/pyitensor/chain.py +1173 -0
- dmrgpy/pyitensor/dmrg.py +658 -0
- dmrgpy/pyitensor/gse.py +171 -0
- dmrgpy/pyitensor/idmrg.py +2092 -0
- dmrgpy/pyitensor/idmrg_excitations.py +693 -0
- dmrgpy/pyitensor/idmrg_window.py +1067 -0
- dmrgpy/pyitensor/index.py +122 -0
- dmrgpy/pyitensor/kernels.py +423 -0
- dmrgpy/pyitensor/kpm_energy_truncation.py +179 -0
- dmrgpy/pyitensor/metts.py +611 -0
- dmrgpy/pyitensor/mpobuilder.py +100 -0
- dmrgpy/pyitensor/mpsalgebra.py +317 -0
- dmrgpy/pyitensor/mpscontainer.py +160 -0
- dmrgpy/pyitensor/nhdmrg.py +384 -0
- dmrgpy/pyitensor/sites/__init__.py +15 -0
- dmrgpy/pyitensor/sites/base.py +74 -0
- dmrgpy/pyitensor/sites/boson.py +61 -0
- dmrgpy/pyitensor/sites/fermion.py +78 -0
- dmrgpy/pyitensor/sites/parafermion.py +57 -0
- dmrgpy/pyitensor/sites/siteset.py +73 -0
- dmrgpy/pyitensor/sites/spin.py +129 -0
- dmrgpy/pyitensor/svd.py +118 -0
- dmrgpy/pyitensor/sweeps.py +48 -0
- dmrgpy/pyitensor/tdvp.py +329 -0
- dmrgpy/pyitensor/tebd.py +183 -0
- dmrgpy/pyitensor/tensor.py +299 -0
- dmrgpy/pyparafermion/__init__.py +0 -0
- dmrgpy/pyparafermion/parafermion.py +77 -0
- dmrgpy/pyspin/__init__.py +0 -0
- dmrgpy/pyspin/spin.py +12 -0
- dmrgpy/pyzn/__init__.py +0 -0
- dmrgpy/pyzn/zn.py +30 -0
- dmrgpy/randommps.py +103 -0
- dmrgpy/reconstruct.py +58 -0
- dmrgpy/rootndmrg.py +130 -0
- dmrgpy/sites.py +28 -0
- dmrgpy/spinchain.py +295 -0
- dmrgpy/spinfermionchain.py +8 -0
- dmrgpy/tdz.py +257 -0
- dmrgpy/thermal.py +87 -0
- dmrgpy/timedependent.py +306 -0
- dmrgpy/timeevolution.py +55 -0
- dmrgpy/topology.py +72 -0
- dmrgpy/vev.py +55 -0
- dmrgpy/vevtk/__init__.py +0 -0
- dmrgpy/vevtk/mettsdynamicalcorrelator.py +174 -0
- dmrgpy/vevtk/mettsvev.py +158 -0
- dmrgpy/vevtk/thermalvev.py +46 -0
- dmrgpy/wavefunction.py +29 -0
- dmrgpy-0.1.0.dist-info/METADATA +618 -0
- dmrgpy-0.1.0.dist-info/RECORD +208 -0
- dmrgpy-0.1.0.dist-info/WHEEL +5 -0
- dmrgpy-0.1.0.dist-info/licenses/LICENSE.md +674 -0
- 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
|
+
|