c2x and Python

C2x has two output formats which are designed to facilitate interoperability with python. Both are inspired by the Atomic Simulation Environment for python (available for both python 2.x and 3.x), although one can also be used with other packages.

Atoms

Dictionary format

The more flexible --py format produces output of the form:

structure = {'cell':[(2.730000,2.730000,0.000000),
                     (2.730000,0.000000,2.730000),
                     (0.000000,2.730000,2.730000)],
  'symbols':['Si','Si'],
  'scaled_positions':[
    (0.000000,0.000000,0.000000),
    (0.250000,0.250000,0.250000)],
  'pbc':True}

There are many ways that this could be used from python, but, assuming the above is stored in a file called Si2.py, then

>>> from ase import Atoms
>>> import Si2
>>> st=Atoms(**Si2.structure)
>>> print(st)

should work, as should the use of any module containing a datastructure similar to ASE's Atoms structure.

ASE format

The second format provided, --pya, is firmly tied to ASE, and produces output of the form:

from ase import Atoms
structure = Atoms(cell=[(2.730000,2.730000,0.000000),
                     (2.730000,0.000000,2.730000),
                     (0.000000,2.730000,2.730000)],
  symbols=['Si','Si'],
  scaled_positions=[
    (0.000000,0.000000,0.000000),
    (0.250000,0.250000,0.250000)],
  pbc=True)

Again assuming the above is stored in a file called Si2.py, this can be used as:

>>> import Si2
>>> print(Si2.structure)

Densities

Densities can be written as numpy arrays. They default to single precision real, but double precision can be written by using the -15 flag.

$ c2x -c -15 --npy si2.check si2.npy

The densities can either be loaded into python on their own, or combined with atomic data. As a simple example showing how to sum a density to obtain the number of electrons, assuming the ASE format

  import numpy as np
  import Si2
  rho=np.load('si2.npy', allow_pickle=False)
  q=np.sum(rho)*Si2.structure.get_volume()/np.prod(rho.shape)
  print(q)

This prints "7.999999995185326", so the unit cell contained eight electrons. The use of allow_pickle=False is, of course, optional.

If trying to calculate moments etc., can be useful to rescale rho so that it represents the charge associated with each point.

  rho*=Si2.structure.get_volume()/np.prod(rho.shape)

After which the total charge is simply np.sum(rho).

A further example of using numpy arrays as input to c2x is given on the page on masking data.