Supporting scripts

Generating input files for force matching

The prepare_configurations_for_force_matching.py script that can be found in the utility_scripts directory allows one to create structure files that contain not only positions but also forces suitable for force matching. The script reads an atomic simulation environment (ASE) compatible input file containing one or more configurations of positions and forces, e.g. a VASP OUTCAR file or a .traj file. It then writes one or more corresponding files in a modified POSCAR format that includes forces, which is suitable for force matching using atomicrex.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
#!/usr/bin/env python
# PE, 2015/06/04

description_string =
"""The script reads an ASE compatible input file containing one or
more configurations of positions and forces, e.g. a VASP OUTCAR file
or a .traj file. It then writes one or more corresponding files in a
POSCAR like format including forces, which is suitable for force
matching using the atomicrex code.

"""

from ase import *
from ase.io import *

#------------------------------------------------
# Handle the command line
import argparse
parser = argparse.ArgumentParser(description=description_string)
parser.add_argument('filename', help='input structure in ASE readable format; the file can contain multiple configurations')
parser.add_argument('-o', '--outfile', default='FPOSCAR.new', help='name of output file')
args = parser.parse_args()

#------------------------------------------------
def write_configuration(outfile, conf, direct=False, comment='', form='%21.16f'):

    with open(outfile, 'w') as f:

        # Element names
        elements = []
        for elem in conf.get_chemical_symbols():
            if not elem in elements: elements.append(elem)

        # Comment line (here we store the energy per atom)
        energy = conf.get_potential_energy()
        energy /= conf.get_number_of_atoms()
        f.write('%.6g\n' % energy)

        # Cell metric
        f.write('1.0\n')
        for vec in conf.cell:
            for v in vec: f.write((' '+form) % v)
            f.write('\n')

        # Element names
        for elem in elements: f.write(' %2s' % elem)
        f.write('\n')

        # Number of elements per type
        for elem in elements:
            f.write(' %d' % conf.get_chemical_symbols().count(elem))
        f.write('\n')

        # Scaled or cartesian coordinates
        if direct:
            coordinates = atoms.get_scaled_positions()
            f.write('Direct\n')
        else:
            coordinates = conf.get_positions()
            f.write('Cartesian\n')

        # Coordinates and forces
        for coord,force in zip(coordinates, conf.get_forces()):
            for r in coord: f.write((' '+form) % r)
            f.write('   ')
            for r in force: f.write((' '+form) % r)
            f.write('\n')

#------------------------------------------------
# Read and write configuration
fname = args.filename
try:
    confs = read(fname, ':')
except:
    print "ERROR: file %s could not be read"%fname
    raise
for k,conf in enumerate(confs):
    if len(confs) > 1:
        outfile = args.outfile+'_%d' % k
    else:
        outfile = args.outfile
    write_configuration(outfile, conf)

Generating XML code for the <structures> block

The prepare_structure_xml_file.py script that can be found in the utility_scripts directory allows one to generate XML code suitable for insertion into the <structures> block of an atomicrex input file. The script reads a series of atomic simulation environment (ASE) compatible input files containing one or more configurations of positions and forces.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#!/usr/bin/env python
# PE, 2015/06/04

description_string =
"""The script reads an ASE compatible input files containing one or
more configurations of positions and forces. It then prints XML code
to standard output that can be inserted into an atomicrex input file.

"""

import xml.etree.cElementTree as ET
import os

#------------------------------------------------
# Handle the command line
import argparse
parser = argparse.ArgumentParser(description=description_string)
parser.add_argument('files', nargs='+', action='append',
                    help='input files in modified POSCAR format for force matching.')
args = parser.parse_args()

root = ET.Element('group')
root.attrib['exclude-fit'] = 'false'
root.attrib['exclude-output'] = 'false'
for fname in args.files[0]:

    structure = ET.SubElement(root, 'user-structure')
    structure.attrib['id'] = os.path.basename(fname)

    conffile = ET.SubElement(structure, 'poscar-file').text = fname

    properties = ET.SubElement(structure, 'properties')

    with open(fname, 'r') as f:
        target_energy = float(f.readline().split()[0])
    
    energy = ET.SubElement(properties, 'atomic-energy')
    energy.attrib['relax'] = 'false'
    energy.attrib['fit'] = 'true'
    energy.attrib['target'] = '%.6f' % target_energy

    forces = ET.SubElement(properties, 'atomic-forces')
    forces.attrib['fit'] = 'true'
    forces.attrib['output-all'] = 'true'

print ET.tostring(root)