1 """@package dmrg_postprocessing 2 @brief Python module for post-processing data files produced by a DMRG.x application. 3 See @ref Postprocessing module for more info. 5 @defgroup Postprocessing 6 @brief Python module for post-processing data files produced by a DMRG.x application. 10 >>> sys.path.append("/path/to/DMRG.x/postproc") 11 >>> import dmrg_postprocessing as dmrg 20 import matplotlib.pyplot
as plt
22 import dmrg_json_utils
as ju
26 Post-processing of a single DMRG run. 29 def __init__(self, base_dir, jobs_dir='', label=None):
30 """Initializes the Data object. 32 This initializer simply fills in the base directory and prepares the private 33 variables which will store the corresponding data. The variables are first 34 set to None. Whenever some data is requested, these variables will then be filled. 37 base_dir: directory containing the data files 40 jobs_dir: path to be prepended to base_dir 41 label: label for plots with this data object 44 >>> data = dmrg.Data("data_dir",jobs_dir="/tmp/data/",label="Data1") 46 self.
_base_dir = os.path.join(jobs_dir,base_dir)
59 """Returns the path to a filename prepended with the base directory 62 filename: filename to append to the base directory 64 A string combining the path and filename 66 return os.path.join(self.
_base_dir,filename)
70 Returns the label of the Data object 83 Loads the DMRGRun.json data file, if not loaded, and returns its contents 91 Returns the contents of the DMRGRun.json data file 106 """Loads data from DMRGSteps.json, if not loaded, and extracts the indices 107 for required data columns. 110 steps = ju.LoadJSONTable(self.
PathToFile(
'DMRGSteps.json'))
112 self.
_idxEnergy = self._stepsHeaders.index(
'GSEnergy')
113 self.
_idxNSysEnl = self._stepsHeaders.index(
'NSites_SysEnl')
114 self.
_idxNEnvEnl = self._stepsHeaders.index(
'NSites_EnvEnl')
115 self.
_idxLoopidx = self._stepsHeaders.index(
'LoopIdx')
117 self.
_steps = steps[
'table']
119 def Steps(self,header=None):
120 """Returns a specific column of data of DMRGSteps.json according to the 121 header string or returns a deepcopy of the entire data table 124 header: string corresponding to the 'header' of DMRGSteps.json 128 return copy.deepcopy(self.
_steps)
130 idx = self._stepsHeaders.index(header)
131 return np.array([row[idx]
for row
in self.
_steps])
134 """Returns the headers of the table in DMRGSteps.json 140 """Returns the step indices corresponding to the end of a sweep. 142 By default this function looks for the maximum LoopIdx in a range. 145 show_all: If set to `True`, all step indices will be given. 146 If `False`, return only those that correspond to where the 147 number of sites in the system is equal to the number of sites in 151 List of indices corresponding to `GlobIdx` 153 NSites_Sys = self.
Steps(
"NSites_Sys")
154 NSites_Env = self.
Steps(
"NSites_Env")
157 StepIdx = self.
Steps(
"StepIdx")
158 LoopIdx = self.
Steps(
"LoopIdx")
160 self.
_sweepIdx = [max(np.where(LoopIdx==i)[0])
for i
in list(set(LoopIdx))]
166 return [ j
for j
in self.
_sweepIdx if NSites_Sys[j]==NSites_Env[j]]
169 """Calculates the energy per site of the superblock Hamiltonian for all steps 172 Numpy array containing the energy per site at each step 178 """Determines the number of states in the superblock Hamiltonian. 180 If `n` is `None`, the number of sates for all steps will be returned. 183 n: Index of the step. 186 Single integer or array representing the number/s of states 196 """Plots the energy per site of the superblock Hamiltonian as a function of DMRG steps. 197 The given label and all kwargs will be passed to the plt.plot function. 200 >>> data = dmrg.Data("data_dir",jobs_dir="/tmp/data/",label="Data1") 201 >>> data.PlotEnergyPerSite(marker='.',color='r') 205 energy_iter = np.array(self.EnergyPerSite()) 206 self._p = plt.plot(energy_iter,label=self._label,**kwargs) 207 self._color = self._p[-1].get_color() 208 plt.xlabel('DMRG Steps') 209 plt.ylabel(r'$E_0/N$') 211 def PlotErrorEnergyPerSite(self,which='abs',compare_with='min',**kwargs): 212 """Plots the error
in the energy per site of the superblock Hamiltonian
as a function of DMRG steps.
213 Kwargs will be passed to the plt.plot function.
216 >>> data = dmrg.Data(
"data_dir",jobs_dir=
"/tmp/data/",label=
"Data1")
217 >>> data.PlotErrorEnergyPerSite(marker=
'.',which=
'rel',color=
'r') 221 which: Show either the absolute `'abs'`
or relative `
'rel'` error
222 compare_with: Compare against the minimum `
'min'`
or `
'last'` obtained value
223 **kwargs: keyword arguments to be passed to plt.semilogy
226 ValueError: When options are
not matched
229 if compare_with=='min': 230 best = lambda energy_iter: np.min(energy_iter) 231 elif compare_with=='last': 232 best = lambda energy_iter: energy_iter[-1] 234 raise ValueError("The value of compare_with can only be 'min' or 'last'. Got {}".format(compare_with)) 236 energy_iter = np.array(self.EnergyPerSite()) 237 energy_iter = np.abs((energy_iter - best(energy_iter))) 238 plt.ylabel(r'$E_0/N - \mathrm{min}(E_0/N)$') 240 energy_iter = np.array(self.EnergyPerSite()) 241 energy_iter = np.abs((energy_iter - best(energy_iter))/best(energy_iter)) 242 plt.ylabel(r'$[E_0/N - \mathrm{min}(E_0/N)] / \mathrm{min}(E_0/N)$') 244 raise ValueError("The value of which can only be 'abs' or 'rel'. Got {}".format(which)) 246 self._p = plt.semilogy(energy_iter,label=self._label,**kwargs) 247 self._color = self._p[-1].get_color() 248 plt.xlabel('DMRG Steps') 250 def PlotLoopBars(self,my_color=None,**kwargs): 251 """Plot vertical lines corresponding to the end of each sweep
254 my_color: Override default colors
255 **kwargs: keyword arguments to be passed to plt.axvline
258 LoopIdx = [row[self._idxLoopidx] for row in self._steps] 259 dm = np.where([LoopIdx[i] - LoopIdx[i-1] for i in range(1,len(LoopIdx))])[0] 261 if my_color is not None: 262 plt.axvline(x=d,color=my_color,linewidth=1,**kwargs) 263 elif self._color is None: 264 plt.axvline(x=d,linewidth=1,**kwargs) 266 plt.axvline(x=d,color=self._color,linewidth=1,**kwargs) 274 def _LoadTimings(self): 275 if self._timings is None: 276 timings = ju.LoadJSONTable(self.PathToFile('Timings.json')) 277 self._timingsHeaders = timings['headers'] 278 self._idxTimeTot = self._timingsHeaders.index('Total') 279 self._timings = timings['table'] 283 return copy.deepcopy(self._timings) 285 def TimingsHeaders(self): 287 return copy.deepcopy(self._timingsHeaders) 291 return np.array([row[self._idxTimeTot] for row in self._timings]) 293 def PlotTotalTime(self,which='plot',cumulative=False,units='sec',**kwargs): 294 totTime = self.TotalTime() 295 ylabel = "Time Elapsed per Step" 298 totTime = np.cumsum(totTime) 299 ylabel = "Cumulative Time Elapsed" 308 raise ValueError("units='{}' unsupported. Choose among ['sec','min','hrs']".format(units)) 311 self._p = plt.plot(totTime,label=self._label,**kwargs) 312 elif which=='semilogy': 313 self._p = plt.semilogy(totTime,label=self._label,**kwargs) 315 raise ValueError("which='{}' unsupported. Choose among ['plot','semilogy']".format(which)) 317 self._color = self._p[-1].get_color() 318 plt.xlabel('DMRG Steps') 319 plt.ylabel('{} ({})'.format(ylabel,units)) 324 def PreallocData(self,n=None,key=None): 325 if self._hamPrealloc is None: 326 self._hamPrealloc = ju.LoadJSONArray(self.PathToFile('HamiltonianPrealloc.json')) 328 return self._hamPrealloc 331 return self._hamPrealloc[n] 334 return np.array(self._hamPrealloc[n]["Dnnz"]) + np.array(self._hamPrealloc[n]["Onnz"]) 336 return self._hamPrealloc[n][key] 338 def PlotPreallocData(self,n,totals_only=True,**kwargs): 339 Dnnz = np.array(self.PreallocData(n)["Dnnz"]) 340 Onnz = np.array(self.PreallocData(n)["Onnz"]) 341 self._p = plt.plot(Dnnz+Onnz,label='Tnnz: {}'.format(n),marker='o',**kwargs) 343 color = self._p[-1].get_color() 344 self._p = plt.plot(Dnnz,label='Dnnz: {}'.format(n),color=color,marker='s',**kwargs) 345 self._p = plt.plot(Onnz,label='Onnz: {}'.format(n),color=color,marker='^',**kwargs) 348 # Entanglement Spectra 350 def _LoadSpectra(self): 351 if self._entSpectra is None: 354 # Change the output of DMRG.x from EntanglementSpectra.json 355 # to RDMEigenvalues.json 357 spectra = ju.LoadJSONArray(self.PathToFile('EntanglementSpectra.json')) 358 # determine which global indices are the ends of a sweep 360 self._entSpectra = spectra 362 def RDMEigenvalues(self,idx=None): 363 ''' Loads the reduced density matrix eigenvalues at the end of each sweep or for 367 idx: The index of the sweep requested. 368 If None, the data for all indices are returned. 370 An array of values when idx is None, or a single value otherwise. 374 vals = [self._entSpectra[row]['Sys'] for row in self.SweepIdx()] 376 row = self.SweepIdx()[idx] 377 vals = self._entSpectra[row]['Sys'] 380 def EntanglementEntropy(self): 381 ''' Calculates the entanglement entropy using eigenvalues from all sectors ''' 382 a = self.RDMEigenvalues() 383 l = [np.concatenate([a[i][j]['vals'] for j in range(len(a[i]))]) for i in range(len(a))] 384 return [-np.sum( [np.log(lii)*lii for lii in li if lii > 0] ) for li in l] 386 def PlotEntanglementEntropy(self): 387 ''' Plots the entanglement entropy using eigenvalues from all sectors ''' 388 ent = np.array(self.EntanglementEntropy()) 390 plt.xticks(np.arange(ent.shape[0])) 392 plt.ylabel(r"Von Neumann Entropy (S)") 397 def _LoadCorrelations(self): 398 if self._corr is None: 399 self._corr = ju.LoadJSONTable(self.PathToFile('Correlations.json')) 401 def _LoadCorrelationsLookup(self): 402 self._LoadCorrelations() 403 if self._corrLookup is None: 404 self._corrLookup = {} 405 for key in self._corr['info'][0].keys(): self._corrLookup[key] = [] 406 for corr in self._corr['info']: 408 self._corrLookup[key].append(corr[key]) 410 def Correlations(self): 411 self._LoadCorrelations() 414 def CorrelationsInfo(self): 415 return self.Correlations()['info'] 417 def CorrelationsValues(self, key=None, labels=None): 419 return np.array(self.Correlations()['values']) 420 elif labels is not None and key is None: 421 raise ValueError('key must be given when labels is not None') 423 idx = self.CorrelationsInfoGetIndex(key, labels) 424 return np.array(self.Correlations()['values'])[:,idx] 426 def CorrelationsInfoGetIndex(self, key=None, value=None): 427 self._LoadCorrelationsLookup() 429 if key is None and value is None: 430 return self._corrLookup 432 elif key is not None and value is None: 434 return self._corrLookup[key] 436 raise ValueError("Incorrect key='{}'. Choose among {}".format(key, self._corrLookup.keys())) 438 elif key is None and value is not None: 439 raise ValueError('key must be given when value is not None') 441 else: # both key and value are not none 442 if isinstance(value,(list,tuple,np.ndarray)): 443 return [self._corrLookup[key].index(v) for v in value] 445 return self._corrLookup[key].index(value) 449 Post-processing
for multiple DMRG runs
452 def __init__(self, base_dir_list, label_list=None, *args, **kwargs): 454 # if non-empty check whether the first entry is a tuple 455 if len(base_dir_list[0]) == 2: 456 dirs = [dl[0] for dl in base_dir_list] 457 labels = [dl[1] for dl in base_dir_list] 460 # note: overrides the input label_list 461 if label_list is None: 462 self.DataList = [ Data(base_dir, *args, label=base_dir, **kwargs) for base_dir in base_dir_list ] 464 self.DataList = [ Data(base_dir, *args, label=label, **kwargs) for (base_dir, label) in zip(base_dir_list,label_list) ] 467 return self.DataList[n] 469 def PlotEnergyPerSite(self,**kwargs): 470 for obj in self.DataList: obj.PlotEnergyPerSite(**kwargs) 472 def PlotErrorEnergyPerSite(self,which='abs',**kwargs): 473 for obj in self.DataList: obj.PlotErrorEnergyPerSite(which='abs',**kwargs) 475 def PlotTotalTime(self,**kwargs): 476 for obj in self.DataList: obj.PlotTotalTime(**kwargs) 478 def PlotLoopBars(self,n=None,**kwargs): 480 for obj in self.DataList: obj.PlotLoopBars(**kwargs) 482 self.DataList[n].PlotLoopBars(**kwargs) def Steps(self, header=None)
Returns a specific column of data of DMRGSteps.json according to the header string or returns a deepc...
def PlotEnergyPerSite(self, kwargs)
Plots the energy per site of the superblock Hamiltonian as a function of DMRG steps.
def RunData(self)
Returns the contents of the DMRGRun.json data file.
def NumStatesSuperblock(self, n=None)
Determines the number of states in the superblock Hamiltonian.
Post-processing of a single DMRG run.
def __init__(self, base_dir, jobs_dir='', label=None)
Initializes the Data object.
def SweepIdx(self, show_all=False)
Returns the step indices corresponding to the end of a sweep.
def _LoadRun(self)
Loads the DMRGRun.json data file, if not loaded, and returns its contents.
def PathToFile(self, filename="")
Returns the path to a filename prepended with the base directory.
def _LoadSteps(self)
Loads data from DMRGSteps.json, if not loaded, and extracts the indices for required data columns...
def EnergyPerSite(self)
Calculates the energy per site of the superblock Hamiltonian for all steps.
def StepsHeaders(self)
Returns the headers of the table in DMRGSteps.json.
def Label(self)
Returns the label of the Data object.