Skip to content

nchisholm/DFTMiniProject1

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Mini-Project 1 Readme

1 Project Goal

The objective of this project is to use data generated by ASE/JASP/VASP to produce 3D electron density plots. I have made a small module which contains a couple of functions that do this. As inputs, it takes calculation data generated by VASP (using JASP). The Mayavi “pipeline” is used to generate “advanced” 3D plots which display the charge density and optionally the atom locations and a bounding box representing the unit cell. You can also control some of the basics of the plot appearence in order to get a good-looking result.

2 Functions

2.1 ChargeDensityFog3D

ChgPlot.ChargeDensityFog3D(directory,
                           save_loc=None,
                           DrawAtoms=True,
                           DrawCell=True,
                           opacity_range=[0,1])
ArgumentDescription
directoryDirectory in which the VASP calculation files are located
save_locLocation where image of the figure should be saved. Saving can also be done through the Mayavi window.
DrawAtomsRepresent atoms as small spheres in the plot if True (default = True)
DrawCellDraw the unit cell surrounding the molecules if True (default = True)
opacity_rangeControls the transparency of the “fog” (default = [0,1])

The default values for the opacity_range makes the maximum electron density opaque and the minimum completely transparent. This seems to give good looking results, but it may be necessary to adjust the values to get the desired appearence. The first element of the list gives the transparency at the minimum electron density and the second element gives the transparency at the maximum.

2.2 ChargeDensitySlice3D

ChgPlot.ChargeDensitySlice3D(directory,
                             save_file=None,
                             x_loc=None,
                             y_loc=None,
                             z_loc=None,
                             DrawAtoms=True,
                             DrawCell=True)
ArgumentDescription
directoryDirectory in which the VASP calculation files are located
save_locLocation where image of the figure should be saved. Saving can also be done through the Mayavi window.
x_locLocation where the x-oriented slice should be placed (given in Angstroms)
y_locLocation where the y-oriented slice should be placed (given in Angstroms)
z_locLocation where the z-oriented slice should be placed (given in Angstroms)
DrawAtomsRepresent atoms as small spheres in the plot if True (default = True)
DrawCellDraw the unit cell surrounding the molecules if True (default = True)

If x_loc, y_loc, or z_loc are not specified, they will not be drawn. For example, only specifying y_loc will cause only the y-oriented plane to appear in the figure.

3 The Python Module

The python module is located in the file ChgPlot.py. The source code is also given below.

from jasp import *
from enthought.mayavi import mlab
from ase.data.molecules import molecule
from ase.data import vdw_radii
from ase.data.colors import cpk_colors
import numpy as np

def ChargeDensityFog3D(directory, save_file=None , DrawAtoms=True, DrawCell=True, opacity_range=[0,1]):
    # Get data from calculation files
    with jasp(directory) as calc:
        atoms = calc.get_atoms()
        x, y, z, cd = calc.get_charge_density()

    mlab.figure(bgcolor=(0,0,0), size=(640,480))

    # Draw atoms
    if DrawAtoms == True:
        for atom in atoms:
            mlab.points3d(atom.x,
                          atom.y,
                          atom.z,
                          scale_factor=vdw_radii[atom.number]/10.,
                          resolution=16,
                          color=tuple(cpk_colors[atom.number]),
                          scale_mode='none')
    # Draw unit cell
    if DrawCell == True:
        a1, a2, a3 = atoms.get_cell()
        origin = [0,0,0]
        cell_matrix = [[origin, a1],
                       [origin, a2],
                       [origin, a3],
                       [a1, a1+a2],
                       [a1, a1+a3],
                       [a2, a2+a1],
                       [a2, a2+a3],
                       [a3, a1+a3],
                       [a3, a2+a3],
                       [a1+a2, a1+a2+a3],
                       [a2+a3, a1+a2+a3],
                       [a1+a3, a1+a3+a2]] # contains all points on the box
        for p1, p2 in cell_matrix:
            mlab.plot3d([p1[0], p2[0]], # x-coords of box
                        [p1[1], p2[1]], # y-coords
                        [p1[2], p2[2]]) # z-coords

    # Plot the charge density
    src = mlab.pipeline.scalar_field(x, y, z, cd) #Source data
    vmin = cd.min() #find minimum and maximum value of CD data
    vmax = cd.max()
    vol = mlab.pipeline.volume(src) # Make a volumetric representation of the data

    # Set opacity transfer function
    from tvtk.util.ctf import PiecewiseFunction
    otf = PiecewiseFunction()
    otf.add_point(vmin, opacity_range[0]) #Transparency at zero electron density
    otf.add_point(vmax*1, opacity_range[1]) #Transparency at max electron density
    vol._otf=otf
    vol._volume_property.set_scalar_opacity(otf)

    #Show a legend
    mlab.colorbar(title="e- density\n(e/Ang^3)", orientation="vertical", nb_labels=5, label_fmt='%.2f')
    mlab.view(azimuth=-90, elevation=90, distance='auto') # Set viewing angle
    mlab.show()
    if save_file != None:
        mlab.savefig(save_file)

def ChargeDensitySlice3D(directory, save_file=None, x_loc=None, y_loc=None, z_loc=None, DrawAtoms=True, DrawCell=True):
    # Get data from calculation files
    with jasp(directory) as calc:
        atoms = calc.get_atoms()
        x, y, z, cd = calc.get_charge_density()

    mlab.figure(bgcolor=(0,0,0), size=(640,480))

    # Draw atoms
    if DrawAtoms == True:
        for atom in atoms:
            mlab.points3d(atom.x,
                          atom.y,
                          atom.z,
                          scale_factor=vdw_radii[atom.number]/10.,
                          resolution=16,
                          color=tuple(cpk_colors[atom.number]),
                          scale_mode='none')
    # Draw unit cell
    if DrawCell == True:
        a1, a2, a3 = atoms.get_cell()
        origin = [0,0,0]
        cell_matrix = [[origin, a1],
                       [origin, a2],
                       [origin, a3],
                       [a1, a1+a2],
                       [a1, a1+a3],
                       [a2, a2+a1],
                       [a2, a2+a3],
                       [a3, a1+a3],
                       [a3, a2+a3],
                       [a1+a2, a1+a2+a3],
                       [a2+a3, a1+a2+a3],
                       [a1+a3, a1+a3+a2]] # contains all points on the box
        for p1, p2 in cell_matrix:
            mlab.plot3d([p1[0], p2[0]], # x-coords of box
                        [p1[1], p2[1]], # y-coords
                        [p1[2], p2[2]]) # z-coords

    # Plot the charge density on three perpendicular planes at the center of the cell
    src = mlab.pipeline.scalar_field(x, y, z, cd) #Source data
    vmin = cd.min() #find minimum and maximum value of CD data
    vmax = cd.max()
    if x_loc != None:
        sliceX = mlab.pipeline.image_plane_widget(src,
                                                  plane_orientation = 'x_axes',
                                                  slice_index = x_loc * 10,
                                                  transparent = True)
    if y_loc != None:
        sliceY = mlab.pipeline.image_plane_widget(src,
                                                  plane_orientation = 'y_axes',
                                                  slice_index = y_loc * 10,
                                                  transparent = True)
    if z_loc != None:
        sliceZ = mlab.pipeline.image_plane_widget(src,
                                                  plane_orientation = 'z_axes',
                                                  slice_index = z_loc * 10,
                                                  transparent = True)
    #Show a legend
    mlab.colorbar(title="e- density\n(e/Ang^3)", orientation="vertical", nb_labels=5, label_fmt='%.2f')
    mlab.show()
    if save_file != None:
        mlab.savefig(save_file)

4 Examples

4.1 CH4 and NH3 “fog” plot

In this example, a simple relaxation calculation is performed on a methane molecule and then the electron density is plotted as a fog.

from jasp import *

from ase.data.molecules import molecule

NH3 = molecule("NH3")
NH3.set_cell([8,8,8], scale_atoms=False)
NH3.center()

CH4 = molecule("CH4")
CH4.set_cell([8,8,8], scale_atoms=False)
CH4.center()

ready = True
with jasp('example-calcs/CH4',
          xc = 'PBE',
          encut = 350,
          ismear = 0,
          sigma = 0.01,
          ibrion = 1,
          nsw = 50,
          ediffg = -0.05,
          atoms = CH4) as calc:
    try:
       calc.calculate()
       CH4 = calc.get_atoms()
    except (VaspSubmitted, VaspQueued):
       ready = False
       print "Jobs submitted/queued"

with jasp('example-calcs/NH3',
          xc = 'PBE',
          encut = 350,
          ismear = 0,
          sigma = 0.01,
          ibrion = 1,
          nsw = 50,
          ediffg = -0.05,
          atoms = NH3) as calc:
    try:
       calc.calculate()
       NH3 = calc.get_atoms()
    except (VaspSubmitted, VaspQueued):
       ready = False
       print "Jobs submitted/queued"

if not ready:
    import sys; sys.exit()

from ChgPlot import ChargeDensityFog3D

ChargeDensityFog3D("example-calcs/NH3")
ChargeDensityFog3D("example-calcs/CH4", opacity_range=[0, 0.75])

images/methane.png

4.2 Tantalum BCC unit cell electron density

Here, electron density is plotted as “slices” and as a fog. In this particular case, the volume rendering that Mayavi uses shows some weird artifacts at angles away from the x, y, and z axes. However, the plane slices give a pretty nice result and are a bit more informative.

from jasp import *
JASPRC['queue.walltime'] = '24:00:00' #Zhongnan's hax
from ase.lattice.cubic import BodyCenteredCubic

atoms = BodyCenteredCubic("Ta")

ready=True
with jasp("example-calcs/TaBCC",
          xc="PBE",
          encut=350,
          kpts=(8,8,8),
          atoms=atoms) as calc:
    try:
            calc.calculate()
            atoms = calc.get_atoms()
    except (VaspSubmitted, VaspQueued):
            ready=False

if not ready:
    import sys; sys.exit()

from ChgPlot import ChargeDensitySlice3D, ChargeDensityFog3D
ChargeDensitySlice3D("example-calcs/TaBCC", x_loc=3.3/2, y_loc=3.3/2, z_loc=0)

images/TaBCC-planes.png

5 Known Limitations

For simple molecules, rendering the electron density as a fog certainly produces a cool visual effect. However, it can sometimes be difficult to get useful information out of this kind of plot. This is mainly because the outer layers of “fog” can sometimes obscure the inner layers behind them. In the above examples, the transparency of the fog is scaled with the value of the electron density (i.e., the minimum electron desity is completely transparent while the maximum density is mostly opaque). It is possible to modify the color and opacity scaling by changing the “color transfer function” and “opacity transfer function”. A linear opacity transfer function was used in this example, but any “shape” can be given to this function. The same goes for the color transfer function. In this example, the hue is changed continuously with electron density. However, it is possible to use any combination of different colors.

Rendering a fog also seems to produce some strange artifacts in some cases. For example, viewing the Tantalum BCC unit cell in-line with the x-axis gives a result that looks reasonable (fig. 4), but viewing from an angle gives a strange result (fig. 5). In these kinds of cases, it is much more useful to plot electron density through plane slices instead as shown in the second example above. It may not be as fancy, but it avoids this problem as well as problems with the data obscuring itself. With highly symetric systems, one plane may be all that is necessary to visualize all of the data fully.

images/TaBCC-fog1.png

images/TaBCC-fog2.png

6 References

  1. J. Kitchin, “DFT-book”, p. 41-44.
  2. Ramachandran, P. and Varoquaux, G., “Mayavi: 3D Visualization of Scientific Data” IEEE Computing in Science & Engineering, 13 (2), pp. 40-51 (2011)
  3. Enthought Mayavi Documentation: http://docs.enthought.com/mayavi/mayavi/mlab.html#visualizing-volumetric-scalar-data

About

Foggy electron density

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages