ISSN: 2229-371X

All submissions of the EM system will be redirected to Online Manuscript Submission System. Authors are requested to submit articles directly to Online Manuscript Submission System of respective journal.

Mathematica: A System of Computer Programs

Santanu K. Maiti*
Physics and Applied Mathematics Unit, Indian Statistical Institute, 203 Barrackpore Trunk Road, Kolkata-700108
Corresponding Author: Santanu K. Maiti, Physics and Applied Mathematics Unit, Indian Statistical Institute, 203 Barrackpore Trunk Road, Kolkata-700108
santanu.maiti@isical.ac.in
Related article at Pubmed, Scholar Google

Visit for more related articles at Journal of Global Research in Computer Sciences

INTRODUCTION

Mathematica, a system of computer programs, is a high-level computing environment including computer algebra, graphics and programming. Mathematica is specially suitable for mathematics, since it incorporates symbolic manipulation and automates many mathematical operations. The key intellectual aspect of Mathematica is the invention of a new kind of symbolic computation language that can manipulate the very wide range of objects needed to achieve the generality required for technical computing by using a very small number of basic primitives. Just a single line sometimes makes a meaningful program in mathematica–the syntax, documents and methodology used for input and output remaining as they are for immediate calculations. It supports every type of operation–be they data, functions, graphics, programs, or even complete documents– to be represented in a single, uniform way as a symbolic expression. This unification has many practical benefits to broadening the scope of applicability of each function. The raw algorithmic power of mathematica is magnified and its utility extended. Mathematica is now emerging as an important tool in many branches of computing, and today it stands as the world’s best system for general computation. Mathematica has widespread applications in different fields and is often used for research, loading and analyzing data, giving technical presentations and seminars etc. Mathematica is extraordinary well-rounded. It is suitable for both numeric and symbolic work, and it has remarkable word-processing capabilities as well. Mathematicians can search for a working model, do intensive calculation, and write a dissertation on the project (including complex graphics) – all from within mathematica. It is mathematica’s complete consistency in design at every stage that gives it this multilevel capability and helps advanced usage evolve naturally.

START WITH MATHEMATICA

We generally use mathematica through documents called notebooks. To start a mathematica notebook in Unix we write ‘mathematica &’ from a command line and then press the ‘Enter’ key from the key-board. A typical notebook consists of cells that may contain graphics, texts, programs or calculations. Now to exit from a mathematica notebook we first go to the command ‘File’ and then press ‘Quit’ from the menu bar of the notebook. Without using a notebook one can also use mathematica by typing the command ‘math’ from a command line and all the jobs
can also be done as well. To exit from mathematica for this particular case, we should write either ‘Exit’ or ‘Quit’ and then press the ‘Enter’ key. Thus one can run mathematica by using any one of the above two ways, but the most general way to do the interactive calculations in mathematica is the use of mathematica through notebook documents.

Use of a Mathematica Notebook

In a notebook, a job is performed in a particular cell and for different jobs we use different cells. One can also use a single cell for all the operations, but it is quite easy if different operations are performed in separate cells. A cell is automatically created when we begin to write anything in the notebook. After writing proper operation/operations, it is needed to run the jobs. For this purpose, we press the key ‘Shift’ and holding this key, we then press ‘Enter’ from the key-board. The results for the inputs are evaluated and they are available immediately underneath in a separate cell, so-called the output cell.
In mathematica we can do all kind of mathematical operations like numerical computation, algebric computation, matrix manipulation, different types of graphics etc., and all these things are clearly described by several examples in key mathematica book of Wolfram Research [1]. So in this article we shall not give any such example further. Now to do large numerical computations, it is needed to write a complete program. For this purpose, here we describe something about the way of writing a complete program in a mathematica notebook.

Way of Writing a Program in Mathematica

In mathematica, we can write a program efficiently compared to any other existing languages. As illustrative example, here we mention a very simple program which is: the generation of a list of two random numbers and the creation of a 2D plot from these numbers. The program is:
image
This is the complete program for the generation of a list of two random numbers and the creation of a 2D plot from these numbers. This program is written in a single cell. After the end of this program we run it by using the command ‘SHIFT’ + ‘ENTER’, and then the mathematica does the proper operations and executes the result in an output cell (Figure 1).
Now to understand this program, it is necessary to describe the meaning of the different commands used in this program. To start a program it is necessary to specify a name for the particular program. In this case, we specify ‘sample’ as a program name, for the sake of simplicity. One can also use any other name in place of ‘sample’, since this is a dummy name. If there is any running variable, like ‘times’ (a dummy variable) in this particular case, then it has to be given within the bracket ‘[ ]’. After that the symbol ‘_’ is used, which indicates the variable as a functional variable. This is similar to define a functional variable, like f[x] as f[x_] in mathematica. Now all the mathematical commands those are used for calculating the job are inserted within ‘Block [. . .]’. This is the central part of the program. This portion i.e., ‘Block[. . .]’ is connected with ‘sample[times_]’ by the symbols ‘:=’. The symbol ‘:’ has an important role, and therefore it has to be taken into account properly. Inside the ‘Block’ the ‘local variables’ for the program are declared within the bracket ‘{ }’. There may also exist another type of variables called ‘global variables’. Later in this article, we will focus about these two different types of variables in detail. Now the rest part of the program differs from program to program depending on the nature of the particular operations. In this program, first we construct a list of two random numbers. In mathematica, a random number is generated simply by using the command ‘Random[]’. Therefore, a list of two such random numbers can be done very easily if we construct a table, which is performed by the command ‘Table’ as given in the program. The integer i runs from 1 to ‘times’, where the value of ‘times’ can be put anything. So if we write ‘sample[10]’, here ‘times = 10’, then i runs from 1 to 10 and if we take ‘sample[30]’, where ‘times = 30’, then i goes from 1 to 30. Now it becomes quite user friendly if we mention different variable names for the different mathematical operations which are not exactly identical with any built in function available in mathematica like ‘Random’, ‘Table’, ‘Plot’, etc. In this program we use the variable names ‘numbers’ and ‘figure’ for the two different operations. At the end of each mathematical operation, except the last operation which gives the final output of a program, we put the symbol ‘;’. This is also very crucial. Here we use the symbol ‘;’ at the end of the second line only, but not in the last operation since this is the final output of this program. The command ‘ListPlot’ plots the list of data points where the command ‘PlotJoined ->True’ connects the lines between the data points. Finally, the command ‘AxesLabel’ in this line is an option for the graphics functions to specify the labels in the axes.
The output for this program is shown in Fig. 1, which appears in a separate cell just below the input cell of the program. So now we can easily write and compile a program in mathematica.

Characterization of Local and Global Variables

The local and global variables in mathematica play an important role, and therefore care should be taken about these two types of variables when we write a program in mathematica. We have already mentioned about the local variables in the previous section that these variables are introduced only inside the bracket ‘{ }’ at the beginning of the ‘Block[ ]’. In such a case, the values of these parameters are only defined within the cell where we write a particular program. Outside this cell, they are undefined and therefore, we may also use these same parameters for writing other programs without any trouble.
On the other hand, the global variables are those which are not used within the bracket ‘{ }’ of a program. For such a case, these variables are assigned throughout the notebook for all cells. Thus if we declare any value for a such parameter, then it will read this particular value whenever we use it in any program. Accordingly, it may cause a difficulty if we use the same variable in another program by mistake. So we should take care about these two types of variables. To make it clear, here we illustrate the behavior of these two different kinds of variables by giving proper examples.
image
Let us consider the above program which is written in a particular cell in the mathematica notebook. In this program, we introduce two local variables t = 2.3 and p = −1.5. Both these two variables are given inside the bracket ‘{ }’. Now if we check the values outside the cell then the output will be simply t and p for these two variables. So these are the local variables and one can safely use these parameters again in other programs.
image
Now we refer to this program where we introduce an extra line for another variable q = 3.5 compared to the previous program of this section. Once we run this program, the value of q will be assigned for any cell of the notebook. Therefore, in this case q becomes the global variable, and if one uses it further in other program then the value of this parameter q will be assigned as 3.5. Hence a mismatch will occur, and thus we should be very careful about these two different types of parameters.

WAY TO LINK EXTERNAL PROGRAMS IN MATHEMATICA BY PROPER MATH-LINK COMMANDS

This section illustrates an important part of this article which deals with the way of linking of an external program with mathematica through proper mathlink commands. The mechanism for the linking of external program written in C with mathematica has already been established [2]. But this will not work if one tries to link an external program written in other languages like F77, F90, F95, etc., with mathematica. This motivates us to find a way of linking an external program written either in any one of these later languages (F77, F90, F95) with mathematica. Here we illustrate it for the FORTRAN-90 source files [3,4] only, but this mechanism will also work significantly for the other Fortran source files as well.

Mathlink for XL Fortran-90 Source Files

In order to understand the basic mechanism for linking an external program with mathematica, let us begin by giving a simple example. Here we set the program as follows:
1. Construct two square matrices in mathematica.
2. Take the product of these two matrices by using an external program written in F90.
3. Calculate the eigenvalues of the product matrix in mathematica.
The whole operations can be pictorially represented as,
The operations 1 and 3 are performed in mathematica, while the operation 2 is evaluated by the external program. The transformations of the datas from the mathematica notebook to the external program are done by using some proper commands, so-called mathlink operation. To complete this particular job (operations 1-3), we need two programs. One is written in mathematica for the operations 1 and 3, while the other program is written in F90 for the operation 2. Now we describe all these steps one by one. Let us first concentrate on the external program, given below, where the multiplication of the two square matrices (operation 2) is performed. The first line of the program corresponds to the command line where the symbol ‘!’ is used to make a statement as a command statement. The next line provides a specific name of the program which is described by the command ‘program multiplication’. This actually starts the program, and accordingly, the program is ended by the command ‘end program multiplication’. In F90, we can allocate and deallocate array variables in the programs which help us a lot to save memory and are very essential to run many jobs simultaneously. Here we use three array variables ‘a, b and c’ for the three different matrices whose dimensions are allocated by the order of the matrix ‘n’. Finally, the product of the two matrices ‘a’ and ‘b’ is determined by the command ‘matmul (a,b)’ and the datas are stored in the matrix ‘c’. This is the full program for the matrix multiplication of any two square matrices of order ‘n’.
image

Compilation and Optimization of XL Fortran-90 Source Files

After writing a program, first we need to compile it to check whether there is any syntax error or not to proceed for further operations. Several commands are accessible for the compilation and optimization of a program. The commands generally used to compile a F90 source file are: xlf90, xlf90_r, xlf90_r7, etc. Thus we can use anyone of these to compile this program, but different commands optimize a program in different ways which solely depends on the nature of the particular program. The simplest way for the compilation of a program is,
image
With this operation, an ‘executable file’ named ‘a.out’ is created, by default, in the present working directory (pwd). But if one uses several programs simultaneously then it would be much better to specify different names of different ‘executable files’ for separate programs. To do this we use the prescription,
image
Under this process, the ‘executive file’ named as ‘filename’ is created. Thus we can create proper ‘executive files’ for different jobs and all the jobs can be performed simultaneously without any difficulty.
For our illustrative purposes, below we mention some other optimization techniques for the Fortran source files.
• -o : Optimizes code generated by the compiler.
• -o0 : Performs no optimizations. (It is the same as -qnoopt.)
• -o2 : Optimizes code (this is the same as -O).
• -o3 : Performs the -O level optimizations and performs additional optimizations that are
memory or compile time intensive.
• -o4 : Aggressively optimizes the source program, trading off additional compile time for
potential improvements in the generated code. This option implies the following options:
-qarch=auto -qtune=auto -qcache=auto -qhot -qipa.
• -o5 : Same as -O4, but also implies the -qipa=level=2 option
From these operations, we can make some flavors about the compilation and optimization technique for a Fortran source file. For a detailed description of each operation, we refer to the XL Fortran User’s Guide [5].

Link of XL Fortran-90 Program with Mathematica

This is the heart of this article. Below we set the mathematica program for the operations 1 and 3, incorporating the operation 2 by using the proper mathlink commands, and illustrate all the steps properly (Figure 2).
Let us suppose the external program, for the operation 2, is written in the directory ‘/allibmusers/santanu/files/test’. Generally we are habituated to see the working directory as ‘/user/santanu/...’ or ‘/ home/santanu/...’ or ‘/allusers/santanu/...’, etc. So it can be anything like these. Thus knowing the directory where the external program is written, we enter into that particular directory and compile the external program properly to create an ‘executive file’ for further operations. For this particular case, we create the ‘executive file’ named as ‘mat’ which is used in the 13-th line of the following mathematica program. Now the external program is ready for the operation, and we enter into the directory where we will run the job in the mathematica notebook for the operations 1 and 3.
Sitting in the directory where the mathematica notebook is open, we need to connect the proper directory where the ‘executive file’ for the external program exists. The name of the pwd can be checked directly from the mathematica notebook by using the command ‘Directory[]’. Suppose the pwd is ‘/allibmusers/santanu/ math’. Now If this pwd is different from the directory where the file ‘mat’ exists, then we make a link to that particular directory through the command ‘SetDirectory’. Below we give an example to connect the directory ‘/allibmusers/santanu/files/test’, where the file ‘mat’ exists.
image
For this operation, the total path must be used within the double quotes “”. Using the command ‘ResetDirectory[]’, we can come back to the initial directory. Thus we can connect and disconnect any directory with the pwd from the mathematica notebook, and able to link external programs with mathematica very easily.
image
In the above program, the variables ‘t’ and ‘s’ are the local variables, and we have already discussed about these variables in the previous section. ‘vacuum1={}’ and ‘vacuum2={}’ are the two empty lists where the datas are stored for each operation of the two ‘DO’ loops given in the program to make the lists ‘a2’ and ‘a4’ respectively. The ‘Partition’ command makes the partition of a list. The parameter ‘ns’ gives the order of the two square matrices. By using the command ‘Export’ we send the file ‘mat3.dat’ which is treated as the input file for the external program kept in the directory ‘/allibmusers/santanu/files/test’. To perform the matrix multiplication by using the external program and get back the product matrix in the mathematica notebook we use the operation: ReadList[“!mat<mat3.dat”, Number, RecordLists->True]. Here the command ‘ReadLeast’ is used to read the objects from a file and the commands ‘Number’ and ‘RecordLists!True’ are the options of the command ‘ReadList’. Finally, the eigenvalues of the matrix in the mathematica notebook are determined by using the command ‘Eigenvalues’.

Link of other XL Fortran Programs with Mathematica

Now we can also use the mathlink operations for other programs written either in F77 or F95 by the above mechanisms. For these programs, we should use proper commands for the compilations and optimizations. As representative example, here we mention some of the commands for the compilation of these XL Fortran source files those are: xlf, f77, fort77, xlf_r, xlf_r7, xlf95, xlf95_r and xlf95_r7.
So now we can able to use mathlink commands for any type of Fortran program

WAY TO CREATE A MATHEMATICA BATCH-FILE AND RUN IT IN BACKGROUND

In the above section, we have studied in detail how to start mathematica, write programs in mathematica and the way of linking of external programs with a mathematica notebook by using proper mathlink commands. Now it may be quite desirable to run jobs in background which take much time to finish, and to do other works in separate windows, keeping the jobs running. This motivates us to explore the basic mechanisms for running mathematica programs in background. It can be done by creating proper mathematica batch-file which we will describe here elaborately.
In order to understand the complete process, let us start by giving a very simple example of a mathematica program. We set the program as follows:
The generation of a list of two random numbers, a 2D plot from these set of random numbers and then the creation of an ‘EPS’ file for this 2D plot.
For this program, first we need to make a list of two random numbers and then construct a 2D plot using this set of random numbers. Finally, we make an ‘EPS’ file for this plot. Here, we are mainly interested to run this complete job in background. Before doing this job in background, let us now describe the different mathematical operations with proper commands which are to be done in a mathematica notebook for this particular operation.
The program for the generation of a set of two random numbers and a 2D plot from these numbers is as follows:
image
To get the output of this program, we run it by entering some value for the variable ‘times’, like ‘sample[100]’ or ‘sample[200]’ etc. Then the mathematica does the proper operations and executes the result in an output cell (Figure 3). The output of the 2D plot is shown in Figure 1.
Now to create an ‘EPS’ file for this 2D plot we use the following operation:
image
In this above expression, the name ‘fig’ is used to call the graphics file, and the ‘eps’ file is saved by the name ‘filename. eps’ in the present working directory.
Thus we are now clear about all the mathematical operations those are to be done in a mathematica notebook for the above mentioned program. So now we make our attention for running this program in background.
In order to run this program in background, first we need to create a batch-file which is a text file from these mathematica input commands those are written in different cells of a mathematica notebook. For this purpose, we go through these steps:
(a) Select the cells from the mathematica notebook, and then follow the direction by clicking on Cell→ Cell Properties→ Initialization Cell from the menu bar to initialize the cells.
(b) To generate the batch-file, follow the direction by clicking on File→ Save As Special→ Package Format from the menu bar.
Then a dialog box appears for specifying the file name and the location of the mathematica input file. Here we use the input file for the operation of the mathematica job.
After these steps, let us suppose, we generate a batch-file named as ‘santanu.m’ for the above mathematica program. Generally the batch-files for this purpose are specified by using the extension ‘.m’ i.e., like the name as ‘filename.m’. To run this batch-file ‘santanu.m’ in background, we use the following prescription:
image
The file name ‘santanu.out’ is the output file, where all the outputs for the different operations are available. To get both the input and output lines of the mathematica notebook, it is necessary to use the following command in the first line of the notebook.
image
At the end of all these steps, we get the output file ‘santanu. out’ and the graphics file ‘filename.eps’ in ‘EPS’ format in the present working directory where the batch-file ‘santanu.m’ is run in the background.

PARALLEL EVALUATION OF MATHEMATICA PROGRAMS

Parallelization is a form of computation in which one can perform many operations simultaneously. Parallel computation uses multiple processing elements simultaneously to finish a particular job. This is accomplished by breaking the job into independent parts so that each processing element can execute its part of the algorithm simultaneously with the others. The processing elements can be diverse and include resources such as a single computer with multiple processors, several networked computers, specialized hardware, or any combination of the above.
In this section, we narrate the basic mechanisms for parallelizing a mathematica program by running its independent parts in several computers available in the network. Since all the basic mathematical operations are performed quite nicely in any version of mathematica, it does not matter even if different versions of mathematica are installed in different computers those are required for the parallel computing.

How to Open Mathematica Slaves in Local Computer?

In parallel computation, different segments of a job are computed simultaneously. These operations can be performed either in a local computer or in remote computers available in the network. Separate operations are exhibited in separate mathematica slaves. In order to emphasize the basic mechanisms, let us now describe the way of starting a mathematica slave in a local computer. To do this, first we load the following package in a mathematica notebook.
image
To enable optional features, then we load the package,
image
Now we can open a mathematica slave in the local computer by using the command,
image
Using this command, several mathematica slaves can be started from the master slave. Now it becomes much more significant if we specify the names of different slaves so that independent parts of a job can be shared into different slaves appropriately. For our illustrations, below we give some examples how different slaves can be started with specific names.
image
Here link1, link2 and link3 correspond to the three different slaves. The details of these slaves can be available by using the following command,
image
The output of the above command becomes (as an example),
image
The results shown in this table are for the above three slaves named as link1, link2 and link3 respectively, where all these slaves are opened from the local computer named as ‘tcmpibm’ (say). To get the information about the total number of slaves those are opened, we use the command,
image
For this case, the total number of slaves becomes 3.

How to Open Mathematica Slaves in Remote Computers Available in Network?

To start a slave in remote computer, the command ‘ssh’ is used which offers secure cryptographic authentication and encryption of the communication between the local and remote computer. Before starting a slave in a remote computer, it is necessary to check whether ‘ssh’ is properly configured or not, and this can be done by using the prescription,
image
For example, if we want to connect a remote computer named as ‘tcmpxeon’, we should follow the command as,
image
Since ‘ssh’ connection for a remote computer is password protected, it is needed to insert proper password, and if ‘ssh’ is configured correctly, the above operation shows the command ‘In[1]:=’. Once ‘ssh’ works correctly, a mathematica slave can be opened in a remote computer through this command,
image
For our illustrative purposes, below we describe how different slaves with proper names can be started in different remote computers.
image
Here link1, link2, link3 and link4 are the four different slaves, where the link1 and link3 are opened in a remote computer named as ‘tcmpxeon’ (say), while the other two slaves are started in another one remote computer named as ‘tcmp441d’ (say). Using this prescription, several mathematica slaves can be started in different remote computers available in the network. The details of the above four slaves can be expressed in the tabular form as,
image
Thus we are now able to start mathematica slaves in local computer as well as in remote computers available in the network, and with this above background, we can describe the mechanisms for parallelizing a mathematica program.

Parallelizing of Mathematica Programs by using Remote Computers Available in Network

In order to understand the basic mechanisms of parallelizing a mathematica program, let us begin with a very simple problem. We set the problem as follows:
Problem: Construct a square matrix of any order in a local computer and two other square matrices of the same order with the previous one in two different remote computers. From the local computer, read these two matrices those are constructed in the two remote computers. Finally, take the product of these three matrices and calculate the eigenvalues of the product matrix in the local computer
To solve this problem we proceed through these steps in a mathematica notebook.
Step-1: For the sake of simplicity, let us first define the names of the three different computers those are needed to solve this problem. The local computer is named as ‘tcmpibm’, while the names of the other two remote computers are as ‘tcmpxeon’ and ‘tcmp441d’ respectively. Opening a mathematica notebook in the local computer, let us first load the package for parallelization, and to get the optional features, we load another one package as mentioned earlier. Then we start two mathematica slaves named as ‘link1’ and ‘link2’ in the two remote computers ‘tcmpxeon’ and ‘tcmp441d’ respectively by using the proper commands as discussed above.
Step-2: Next we make ready three programs for the three separate square matrices of same order in the local computer. Out of which one program will run in the local computer, while the rest two will run in the two remote computers. These three programs are as follows.
image
image
Since we are quite familiar about the way of writing mathematica programs [1], we do not describe here the meaning of the different symbols used in the above three programs further. Thus by using these programs, we can construct three separate square matrices of order ‘ns’.
Step-3: We are quite at the end of our complete operation. For the sake of simplicity, we assume that, the program-I is evaluated in the local computer, while the program-II and program-III are evaluated in the two remote computers respectively. All these three programs run simultaneously in three different computers. To understand the basic mechanisms, let us follow the program.
image
This is the final program. When it runs in the local computer, one matrix called as ‘mat1’ is evaluated in the local computer (3rd line of the program), and the other two matrices are determined in the remote computers by using the operations given in the 4th and 5th lines of the program respectively. The 2nd line of the program gives the command for the transformations of all the symbols and definitions to the remote computers. After the completion of the operations in remote computers, we call back these two matrices in the local computer by using the command ‘ReadList’, and store them in ‘mat2’ and ‘mat3’ respectively. Finally, we take the product of these three matrices and calculate the eigenvalues of the product matrix in the local computer by using the rest operations of the above program.
The whole operations can be pictorially represented in Figure 4.
At the end of all the operations, we close all the mathematica slaves by using the following command.
image

CONCLUDING REMARKS

In summary, the basic operations presented in this communication may be quite helpful for the beginners. Starting from the basic level, we have explored how to start mathematica, open a mathematica notebook, write a program in mathematica, etc. Following with this, we have also described the utilities of the local and global variables those are used for writing programs in mathematica.
Later, we have illustrated the basic mechanisms for the linking of external programs with mathematica notebook. This mathlink operation is an important part of this article, and it is extremely crucial for doing large numerical computations. Here we have concentrated the mathlink operation mainly for the XL Fortran 90 source files. But this operation can also be used for any other Fortran source file. In this section, we have also illustrated very briefly about the optimization techniques for the Fortran source files which may help us to run very complicated jobs quite efficiently.
Next we have addressed in detail how to set up a mathematica batch-file from a mathematica notebook and run it in the background of a computer. Several programs are there which can take a considerable amount of time to run. Some may take few days or even few weeks to complete their analysis. For this reason, it may be desirable to place such jobs in the background. This is a way of running a program that allows one to continue working on other tasks (or even log out) while still keeping the program running. Furthermore, backgrounded jobs are not dependent on our session remaining open, so even if our computer crashes, the job will continue uninterrupted.
At the end, we have explored the basic mechanisms for parallelizing a mathematica program by running its independent parts in remote computers available in the network. By using this parallelization technique, one can enhance the efficiency of the numerical works, and it helps us to perform all the mathematical operations within a very short period of time.
Throughout this article, we have focused all the basic operations for the Unix based operating system only. But all these operations also work very well in any other supported operating system like Windows, Macintosh, etc.

ACKNOWLEDGMENT

I acknowledge with deep sense of gratitude the illuminating comments and suggestions I have received from Prof. Sachindra Nath Karmakar during the preparation of this article.

Figures at a glance

Figure 1 Figure 2 Figure 3 Figure 4
Figure 1 Figure 2 Figure 3 Figure 4

References