ASE - Modify the source code of Write function

  1. Reference:
  2. Why it didn’t work
  3. Find the source code and change it
  4. Write the end:

A good neighbour is better than a bother in the next village.

远亲不如近邻

Updated time: 01/18 2024.

Reference:

  1. The Atoms object — ASE documentation (dtu.dk)
  2. Format Specific Options — ASE documentation (dtu.dk)
  3. ase / ase · GitLab (the latest version)

在我使用 Write 函数生成 POSCAR 时,我发现该函数不支持设置 scaled factor 的设置。这是因为 Atoms 的属性中并无这一缩放因子,如果加入这一属性会使得计算变得复杂。但如果是只针对输出,我们可以通过修改源代码来实现这一目的。

值得注意的是,ASE 对 write_vasp 这一函数修改变化挺大的,我在 import 时发现我Anaconda中不包含指定函数,检查发现我看的最新代码和我使用的 ASE package 版本不一样。

Why it didn’t work

When I used the write function in ASE to parse the POSCAR file, I found that the lattice factor on the second line was always 1.

write(myfile_path, self, format=myformat, direct=mydirect, vasp5=myvasp5)

So I searched the “write” in manual

search results

please be focused on ase.Atoms.write and ase.io.write.

it’s same because the first is called the second function.

ase.Atoms.write source code

So let’s see the second one. Below is its usage, the format has many types, so turn to VASP. And click on the "vasp". and we found the function write_vasp is the core function worked.

ase.io.write usage

format about VASP

write_vasp function

Let’s see the source code.

some interesting comments

Find the source code and change it

For simplicity, we write the unit cell in real coordinates, so the scaling factor is always set to 1.0.

So the developer thinks the scaling factor should always be set to 1.

Emm, after thinking carefully, I support his opinions, it’s true.

But I want to add this function in this writing function.

So I copy the source code of write_vasp in "ase/io/vasp.py".

# add those command
# the  _symbol_count_from_symbols, _write_symbol_count may be changed, so depending your ase's version to adjust
from ase.io.vasp import _symbol_count_from_symbols, _write_symbol_count
from ase.utils import reader, writer

header

@writer
def my_write_vasp(filename,
               atoms,
               label=None,
               lattice_scale_factor = 1,
               direct=False,
               sort=None,
               symbol_count=None,
               long_format=True,
               vasp5=True,
               ignore_constraints=False,
               wrap=False):

and changed

    # Write unitcell in real coordinates and adapt to VASP convention
    # for unit cell
    # ase Atoms doesn't store the lattice constant separately, so always
    # write 1.0.
    fd.write('%19.16f\n' % lattice_scale_factor)
    scaled_cell = atoms.get_cell()/lattice_scale_factor
    if long_format:
        latt_form = ' %21.16f'
    else:
        latt_form = ' %11.6f'
    for vec in scaled_cell:
        fd.write(' ')
        for el in vec:
            fd.write(latt_form % el)
        fd.write('\n')

here film is my atom object, it’s done!

# film = Atoms(symbols = 'H', positions=[(0, 0, 0)],
#               cell=(d, 0, 0),
#               pbc=(1, 0, 0))

my_write_vasp(file= open('./POSCAR','w'), atoms = film, label = 'Au', lattice_scale_factor=2.0, direct = True, sort = True, vasp5 = True

Write the end:

  • when I copied the source code and set the import command, I found my ASE package in ASE (__version__ = '3.22.1') was incompatible with the latest source code (Ref 3) that I opened on VS code (__version__ = '3.23.0b1').

Please indicate the source when reprinting. Please verify the citation sources in the article and point out any errors or unclear expressions.