Vector Fields in c2x

The following functionality exists concerning vector fields in c2x from version 2.41. Note that the order of command-line arguments is generally unimportant, so for certain sequences it will be necessary to write out an intermediate result, possibly as a NumPy file.


Vectors field may be read from:

Vectors field may be written to:


With -v the following information is printed about each component of vector fields: maximum value, minimum value, integral, and integral of modulus. Note that an antiferromagnetic spin state will have a near-zero integral, but a far from zero integral of modulus.


The --grad command line option will convert scalar fields to their vector gradient. It works via FFTs.

The --mod command line option will convert vector fields to their scalar modulus.

The --div command line option will convert vector fields to their scalar divergence.

The -c=n option will extract a single component from a vector field, replacing the vector dataset by a scalar one. The valid range for n is 1<=n<=3 (assuming three element vectors).

The -F command-line option first calculates the potental from a charge density, then it finds the gradient, with a suitable pre-factor, in order to calculate the vector field.

XSF Files

Vectors can be included in XSF files as "forces" on atoms. There are two approaches.

Regular grids

C2x can generate a regular grid of dummy atoms (atomic number 0, atomic symbol X), and place "forces" on these. The grid will be generated at the density of the FFT grid, which generally leads to XCrysDen crashing, and anyway the output could look messy. So one should first reduce the grid size to something more manageable. E.g.

c2x -s -i=10x10x10 --xsf in.castep_bin out.xsf

On atoms

C2x can also replace any force vectors on atoms with the value of the vector field at that point. But one might have to think hard about what is really wanted. For spin, the most common vector field, the total spin on an atom is not the spin density at its nucleus. Given that spin is an electronic property, one first needs to work out how to divide the electrons up amongst the nuclei. Different methods may well give different answers.

C2x offers two approaches. Firstly the point value at the nucleus, which is possibly more useful for electric fields than spin densities. For this, the option is simply --vec2force.

It can also average over a sphere centred on each atom, e.g. --vec2force=0.5 or --vec2force=1B for a radius of 0.5A and 1 Bohr respectively.

If one suffixes an i, the average becomes an integral, i.e. it multiplies by (4/3)πr3. This will turn a spin density into a total spin. However, using a fixed radius is far from ideal physically.

If one is concerned about the numerical accuracy of the averaging or integration, add a final suffix (after the "i" if present) of one or two f's (for fine).

The following examples repeat the Mn3Sn example on the spinors page.

$ c2x -s --vec2force Mn3Sn.castep_bin Mn3Sn.xsf


Using point sampling at the nuclei, a force scale factor of 20 was needed to produce the above. The spin density at these points was around 0.11eA-3.

$ c2x -s --vec2force=1.35 Mn3Sn.castep_bin Mn3Sn.xsf

Averaging over spheres of radius 1.35A produces much the same picture, except that the spin density is now around 0.3eA-3. In other words, the spin density is not maximal at the nuclei.

$ c2x -sv --vec2force=1.35i Mn3Sn.castep_bin Mn3Sn.xsf
Closest atoms separation 2.7445 A
Found 3D data for Vector spin
Data contain 3 components. Per component analysis:
  min=-2.51651 max=4.19771 sum=164.742 int=0.128258 int|s|=12.9432
  min=-3.79732 max=3.59936 sum=-130.111 int=-0.101296 int|s|=11.7991
  min=-1.06501 max=0.682232 sum=100.884 int=0.0785418 int|s|=1.95981
  (integral is e per cell for charge and spin densities)
Sampling of vector data integrating over 1.350000A using 30 points radially
Mn at (0.8227,0.6613,0.2500) vector ( 3.1515, 0.1252, 0.1677) modulus 3.1584
Mn at (0.3387,0.6613,0.2500) vector (-1.4382,-2.7875, 0.3852) modulus 3.1602
Mn at (0.3387,0.1773,0.2500) vector (-1.6464, 2.6055,-0.7090) modulus 3.1626
Mn at (0.6613,0.8227,0.7500) vector (-1.6692, 2.6538, 0.4121) modulus 3.1620
Mn at (0.6613,0.3387,0.7500) vector (-1.4241,-2.8160,-0.1776) modulus 3.1606
Mn at (0.1773,0.3387,0.7500) vector ( 3.1567, 0.1142, 0.0009) modulus 3.1588
Sn at (0.8333,0.1667,0.2500) vector (-0.0010, 0.0010,-0.0017) modulus 0.0022
Sn at (0.1667,0.8333,0.7500) vector (-0.0011, 0.0011, 0.0005) modulus 0.0016

The use of integration spheres of radius 1.35A on each atom produces non-overlapping spheres, as the closest atom separation is 2.74A. The magnitudes of the spins attributed to each Mn atom are approximately equal, and for the Sn atoms approximately zero. The sum of the x components of the spins is 0.130, very similar to the calculated integral over the whole cell of 0.125. The sum of the moduli of the x components is 12.49, a little less than the integral over the cell of 12.94. It must be less as there is likely to be spin outside of the spheres used for the integration, and there may be some cancellation within each integration sphere. The z components of the spins look somewhat random.

Using --vec2force=1.37if improves the sum of the moduli to 12.55, although the addition of the f slows c2x down noticeably, as it uses approximately eight times as many sampling points in each sphere.

Finally the assignment of the vector field to atoms can be restricted to atoms of certain species. Other atoms will have their forces set to zero.

$ c2x -sv --vec2force=Sn:1.35i Mn3Sn.castep_bin Mn3Sn.xsf

The list of species is comma separated, immediately follows the equals sign, and, if an averaging/integration radius follows, is terminated by a colon. So for this example

--vec2force=Sn,Mn and --vec2force are identical, and
--vec2force=Mn,Sn:1.35i and --vec2force=1.35i are identical.