Example: Static Ising ModelΒΆ

In the following paragraphs we will see how OSMPS integrates with the python environment in a manner that allows for easy visualization of important quantities. We will begin by analyzing the file IsingStatics.py given in the Examples subdirectory of OSMPS. This file performs simulations for many values of the transverse field coupling g, and produces a plot illustrating how the spin correlation between far apart sites changes as a function of the disorder inducing transverse magnetic field. The transverse Ising Hamltonian can be written as shown in Eq. (1), in the file IsingStatics.py we will understand how to implement in this Hamiltonian in OSMPS, and how we can study some of its ground state properties.

(1)\hat{H} = -J \sum_{i=1}^{L-1} \hat{\sigma}_{i}^{z} \hat{\sigma}_{i+1}^{z}
 - J g \sum_{i=1}^{L} \hat{\sigma}_{i}^{x}

The file begins by importing MPSPyLib and NumPy, and it also imports matplotlib.pyplot. This of course requires the installation of matplotlib, see Sec. Dependencies.

1
2
3
4
import MPSPyLib as mps
import numpy as np
import matplotlib.pyplot as plt
import sys

If we call the file from the command line, the main function will be executed, which takes a logic variable as argument. The default value PostProcess=False means we have not yet run our simulation. If PostProcess=True is passed as argument, we have run our simulation and are now using the file to organize and plot our outputs. When calling the script from the command line this can be specified via --PostProcess=F or --PostProcess=T:

6
def main(PostProcess=False):

Here we populate Operators with the spin operators defined in the description of Ops.BuildSpinOperators(). We use these operators to define the Pauli matrices Operator['sigmaz'] and Operator['sigmax'] using well known operator identities.

19
20
21
22
    # Build spin operators for spin-1/2 system
    Operators = mps.BuildSpinOperators(0.5)
    Operators['sigmaz'] = 2 * Operators['sz']
    Operators['sigmax'] = (Operators['splus'] + Operators['sminus'])

Here we construct the Hamiltonian for the transverse Ising model, the first term couples the z component of spin of nearest neighbor qubits, the second term couples the qubits to a transverse magnetic field, this field tends to disorder the qubits with respect to measurement in the z direction. It is important to note that line 17 implicitly sets J=1.0, this will be done explicitly on line 26.

24
25
26
27
28
29
    # Define Hamiltonian of transverse Ising model
    H = mps.MPO(Operators)
    # Note the J parameter in the transverse Ising Hamiltonian
    # has been set to 1, we are modelling a ferromagnetic chain.
    H.AddMPOTerm('bond', ['sigmaz', 'sigmaz'], hparam='J', weight=-1.0)
    H.AddMPOTerm('site', 'sigmax', hparam='g', weight=-1.0)

Here we specify that we interested in the correlation of the z-component of spin among all qubits in the lattice. We associate this observable with the key 'zz', we will use this key in post processing to obtain the correlation data OSMPS has computed and stored in output dictionaries.

31
32
33
    # Observables and convergence parameters
    myObservables = mps.Observables(Operators)
    myObservables.AddObservable('corr', ['sigmaz', 'sigmaz'], 'zz')

Here we explicitly set J=1.0, so that as we increase the strength of the transverse magnetic field coupling g, the ground state of the model will transition from ferromagnetic to paramagnetic. Note that line 40 creates a list of values for the parameter g, for each value of g in the list glist another dictionary of parameters is created, and appended to the list parameters.

38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
    # Specify constants and parameter lists
    J = 1.0
    glist = np.linspace(0, 2, 21)
    parameters = []
    L = 30

    for g in glist:
        parameters.append({
            'simtype'                   : 'Finite',
            # Directories
            'job_ID'                    : 'Ising_Statics',
            'unique_ID'                 : 'g_' + str(g),
            'Write_Directory'           : 'TMP/',
            'Output_Directory'          : 'OUTPUTS/',
            # System size and Hamiltonian parameters
            'L'                         : L,
	    'J'		 	        : J,
            'g'                         : g,
            # ObservablesConvergence parameters
            'verbose'                   : 1,
            'MPSObservables'            : myObservables,
            'MPSConvergenceParameters'  : myConv,
            'logfile' : True

As mentioned, the simulations will be carried out if PostProcess=False.

62
63
64
65
66
67
68
69
    # Write Fortran-readable main files
    MainFiles = mps.WriteFiles(parameters, Operators, H,
                               PostProcess=PostProcess)

    # Run the simulations and quit if we are not just Post
    if(not PostProcess):
        mps.runMPS(MainFiles)

Alternatively, if PostProcess=True then we have already run our simulations and are only interested in plotting. This brings us to line 71, where, assuming we have already run our simulations and set PostProcess=True, we enter the PostProcess if statement. We first initialize the list magnetizationlist as an empty list. We then use ReadStaticObservables to store the output dictionaries of our simulations in Outputs. Since each entry in Outputs is a dictionary, we need to supply the proper key to each dictionary in order to receive the observable data our simulations have generated. We accomplish this with lines 80, for each Output dictionary in our list Outputs, we supply the key 'zz', returned to us is the corresponding observable, in this case a two dimensional array summarizing the correlations between all sites in the system. On line 80 we pick out the spin-spin correlation between sites 4 and 27, these are arbitrary numbers, chosen only to be separated by many sites, and not directly located at a boundary, and use the square root of this quantity as an estimate of the magnetization of the system. The correlation between these two sites is temporarily stored in spincorrelation, each time we pass through the for loop we append the new value of spincorrelation to spincorr. Finally lines 61-68 use the plotting function scatter from matplotlib.pyplot to create a plot of the magnetization as a function of the disorder inducing transverse magnetic field, the usetex=True on line 82 allows us to use the built in LaTeX capabilities in matplotlib.pyplot. Note that any text within quotes preceded by r, will be parsed as LaTeX. So that if lines 82-91 are to run without error, you must install matplotlib, LaTeX, and additional fonts as described in the dependencies section, see Sec. Dependencies.

71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
    # PostProcess
    # -----------

    magnetizationlist = []
    Outputs = mps.ReadStaticObservables(parameters)
    for Output in Outputs:
        print(Output['converged'])

        # Get magnetization from spincorrelation zz
        magnetizationlist.append(np.sqrt(Output['zz'][3][26]))

    plt.rc('text', usetex=True)
    plt.rc('font', family='serif')
    plt.scatter(glist, magnetizationlist)
    plt.xlabel(r"\textbf{transverse field coupling}  " r"$g$", fontsize=16)
    plt.ylabel(r"\textbf{Magnetization}"
               r"$\sqrt{\langle\sigma^\mathbf{z}_4\sigma^\mathbf{z}_{27}\rangle}$",
               fontsize=16)
    plt.xlim((0, 2))
    plt.ylim((0, 1))
    plt.show()

Running this example we receive the following plot as output.

../_images/Tut1_Ising_Magnetization.jpg

Alternatively, if you would rather use the plotting capabilities provided by other programs, the data can easily be written out by substituting the following code in place of lines 82-91, note the indentation of the code below assures that it is contained within the if statement if PostProcess:. The key line in the code below is line 64, this line writes each element of the lists glist and magnetizationlist to the file 'IsingMagnetizationData.dat'. The string '\%30.15E' is a format specifier, the number 30 claims 30 units of space for the argument enclosed in parentheses, for instance glist[i], the number 15 specifies 15 decimals of precision past the decimal point, and the letter E specifies that the output is to be in scientific notation. So, each pass through the for loop we write out another line to the file 'IsingMagnetizationData.dat' containing element number i of glist and magnetizationlist, each given thirty units of space, specified to 15 places past the decimal point and always in scientific notation. The last entry in each line is the string '\textbackslash n' the newline character, this assures that the next set of entries written to the file are written on a new line.

outfilename='IsingMagnetizationData.dat'
outfile=open(outfilename,'w')
for i in range(len(magnetizationlist)):
    outfile.write('%30.15E'%(glist[i])+'%30.15E'%(magnetizationlist[i])+'\n')
outfile.close()

We note that it is a simple matter to add the 'unique_ID' string to the end of a file name using +, which adds numbers and joins strings.