One of the fundamentally important applications of ATK is to produce an I-V curve for a two-probe system. There is, however, no simple way to do it without quite a bit of scripting, as noted in another post on this Forum (http://quantumwise.com/forum/index.php?topic=11.0).
Here is a script/module ivcurve.py (attached) that takes care of that, at least in a quick-and-dirty way. The script is not a masterpiece of software design, and does no error checking etc, but ... it works :-)
The idea is to minimize the code the user has to write in his own script. The only required code to add is something along the lines of
import ivcurve
voltages=[0.0,0.1,0.2,0.3]*Volt
ivcurve.runIVcurve (
twoprobe_configuration,
two_probe_method,
runtime_parameters,
voltages,
vnl_filename='myfile.vnl', sample_name='mysample',
current_k_point_sampling = (1,1),
current_number_of_points = 100
)
iv = ivcurve.extractIVcurveFromVNLFile('myfile.vnl','mysample')
ivcurve.plotIVCurve(iv,'iv.png')
Hopefully the above is relatively self-explanatory, but we'll review some details below. Note how the variable names above are chosen to match those used by Virtual NanoLab when it produces NanoLanguage code for a two-probe system. Therefore it is very easy to just include the code above at the end of a script produced by Virtual NanoLab to obtain an I-V curve.
For a more complete example, see the attached script lih2li_iv.py. It is based on the Li-H2-Li system from the manual, just because it's relatively quick to compute, so it's easy to test the I-V curve script using this system. To run the example you should have the geometry file lih2li.vnl too; for simplicity it is also attached.
The code above should be inserted into a script, after the usual part which defines the TwoProbeConfiguration and the TwoProbeMethod, and also the run-time parameters. Then, insert the code snipped above at the bottom of the script, replacing the execution statement (executeSelfConsistentCalculation()) if present. If you used your own variable names for the configuration, method and run-time parameters, adjust accordingly.
The code snippet above
- defines the voltages for which to compute the current
- runs a sweep with one calculation for each voltage bias
- produces a plot, stored in "iv.png" of the I-V curve
Important notes:
- The bias values should come in sequence and start with 0 V, since for each bias, the previous converged calculation is used to initialize the calculation.
- An alternative way to set up the bias is to use numpy; to sweep from 0.0 to 1.0 V in steps of 0.1 V, use
import numpy
voltages = numpy.arange(0.,1.01,0.1)*Volt
- If the runtime parameters contain a checkpoint filename, the value of the bias will be added before the extension to create a unique NetCDF file for each bias. Thus, if you specified file.nc for a run with bias 0.0, 0.1 and 0.2 V, you will get three nc files file-0.0.nc, file-0.1.nc, and file-0.2.nc.
- The runtime parameters argument is required, but you can give None if you don't want any NetCDF files.
- All the computed values of the current will be stored in the VNL file specified, under the given sample name. You can inspect these values in Virtual NanoLab afterwards too.
- Remember to provide the correct integration parameters for the current (k-point sampling, in particular!).
- The plot can be customized to your liking. ATK actually has a built-in plotting engine (matplotlib (http://matplotlib.sourceforge.net/)), and you can produce very beautiful plots directly in NanoLanguage by using it. I'll make a separate post on that below!
- You can change the extension of the image file from "png" to any other supported file format (such as "eps").
- To print the I-V values, add this code to the end of the script:
print 'Bias (V)\tCurrent (A)\n' + '-'*40
for i in iv:
print i[0],'\t\t',i[1]
It's not unlikely that I overlooked some detail in this script, which causes it not to work in a particular situation... But please try it out, and together we can update it to make it a powerful NanoLanguage tool!
Edit: Updated version of script, which is safe for running in parallel.
I mentioned in the original post that you can do nice plotting with ATK + matplotlib. A specific example of this is how the I-V script plots the results, and we can present that in a bit more detail, for those interested.
Remember from the actual I-V calculation that we have stored the values of bias and current in an array called "iv".
The simplest version of a plotting code would look like this:
import matplotlib
matplotlib.use('Agg')
import pylab as P
from numpy import array
X = array(iv)[:,0]
Y = array(iv)[:,1]
P.plot(X,Y)
P.xlabel('Bias (Volt)')
P.ylabel('Current (Ampere)')
P.title('I-V curve for Li-H2-Li')
P.savefig('lih2li_iv.png')
This looks very much like Matlab, and should be trivial to understand. The plot is attached as "lih2li_iv.png", and we can see that there are some things we would like to improve one (no plot points, scaling of the y-axis values).
Now, in the actual I-V script we go a step beyond this, since we wish to give the user control over things like the output file name, plot title, axis labels, etc, but also
- scaling (currents are in microamperes)
- plot symbols and colors
- axis min/max
- ... and perhaps something more
There are many ways to solve that, but one simple way is to use a dictionary. The script contains an internal dict(ionary) the defines the default values, and we then allow the user to pass another dict to the plot function, and use it to overwrite the defaults with any user-defined parameters.
A simple example of this technique is
# Default values
parameters = { 'a' : 5, 'b' : 3 }
# User-defined parameters
my_parameters = { 'b' : 8 }
# Apply user parameters
parameters.update(my_parameters)
After that, the dict "parameters" will have a=5 (default) and b=8 (user-defined).
We use this in the plot function of the I-V script as follows. The default values are:
plot_params = {
# Blue circles with a line is default plot style
'plot_color' : 'b',
'plot_symbol' : 'o-',
'ylabel' : 'Current (micro-Ampere)',
'xlabel' : 'Bias (V)',
'grid' : False,
'title' : 'I-V curve',
'ymin' : None,
'ymax' : None,
# Scaling factor for the y-axis
'yscale' : 1.e6
}
To result of using these default can be seen in the original post (updated!).
The user can then make his own preferences, like
my_plot_params = {
# I want a green line with X plot symbols
'plot_color' : 'g',
'plot_symbol' : 'x-',
# No scaling, please
'yscale' : 1
'ylabel' : 'Current (Ampere)',
# I want a grid
'grid' : False,
'title' : 'I-V curve',
}
He then passes this to the plot script:
ivcurve.plotIVCurve(iv,'lih2li_iv_green.png',my_plot_params)
The result is also attached, as "lih2li_iv_green.png".
As mentioned above already, more details on matplotlib is available on their webpage.
Hopefully this demonstrates some of the powerful stuff you can do with plotting inside ATK!
It should be quite easy to do. Let's see, step by step.
1. Insert the line
right after the two import statements at the top of your script. The reason we do this early in the script is because if it fails (for some reason), we will know immediately. The file needs to be in the same directory as your script.
2. Remove all code in your script after and including the line
# Perform self-consistent field calculation
3. Insert this code at the end of the script instead:
voltages=[0.0,0.1,0.2,0.3]*Volt
ivcurve.runIVcurve (
twoprobe_configuration,
two_probe_method,
runtime_parameters,
voltages,
vnl_filename='FeMgOFe_iv.vnl', sample_name='FeMgOFe',
current_k_point_sampling = (10,10),
current_number_of_points = 100
)
4. Change the voltages to whatever range you prefer, as well as the file and sample name.
Notes:
In your original script, the k-point sampling for the current calculation was 1x1. A characteristic feature of the FeMgOFe system is that you need very, very many k-points to get an accurate current for the minority transmission in the parallel electrode confiuration. I have used 10x10 in the example code above, but you should really check this number, and find out how many you need. Just do it for the zero bias case, that should be fine.
However, and this is crucial: the way you have set up the system, it is not spin-polarized. For this you must add an initial spin to the electron density parameters. For more information, see the tutorial on FeMgO (http://quantumwise.com/publications/tutorials).
Another point is that this calculation will be extremely time-consuming. However, by running it on a cluster you can probably save a factor of 10 or more in time. In that case, you may have to take some special care about the path and import statements etc. However, I note that you are using Windows, and currently there is not parallel Windows version of ATK. So, I really hope you have opportunity to access a parallel Linux machine, or you may have to wait a week or so for the results of this calculation!
In the call to runIVCurve you must give the name of the VNL file with full path, like you did when it was defined
if processIsMaster(): file = VNLFile('C:/Users/617/Desktop/lih.vnl')
So change to
ivcurve.runIVcurve (
twoprobe_configuration,
two_probe_method,
runtime_parameters,
voltages,
vnl_filename='C:/Users/617/Desktop/lih.vnl', sample_name='lih',
current_k_point_sampling = (1,1),
current_number_of_points = 100
)
and it should work better! :)