File: test_abinit.py

package info (click to toggle)
python-ase 3.21.1-2
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 13,936 kB
  • sloc: python: 122,428; xml: 946; makefile: 111; javascript: 47
file content (137 lines) | stat: -rw-r--r-- 3,892 bytes parent folder | download
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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
from io import StringIO

import numpy as np
import pytest

from ase.io import read, write
from ase.build import bulk
from ase.calculators.calculator import compare_atoms
from ase.io.abinit import read_abinit_out, read_eig, match_kpt_header
from ase.units import Hartree, Bohr


def test_abinit_inputfile_roundtrip():
    m1 = bulk('Ti')
    m1.set_initial_magnetic_moments(range(len(m1)))
    write('abinit_save.in', images=m1, format='abinit-in')
    m2 = read('abinit_save.in', format='abinit-in')

    # (How many decimals?)
    assert not compare_atoms(m1, m2, tol=1e-7)


# "Hand-written" (reduced) abinit txt file based on v8.0.8 format:
sample_outfile = """\

.Version 8.0.8 of ABINIT

 -outvars: echo values of preprocessed input variables --------
            natom           2
           ntypat           1
            rprim      5.0  0.0  0.1
                       0.0  6.0  0.0
                       0.0  0.0  7.0
            typat      1  1
            znucl        8.0

================================

 ----iterations are completed or convergence reached----

 cartesian coordinates (angstrom) at end:
    1      2.5     2.5     3.7
    2      2.5     2.5     2.5

 cartesian forces (eV/Angstrom) at end:
    1     -0.1    -0.3    0.4
    2     -0.2    -0.4   -0.5

 Components of total free energy (in Hartree) :

    >>>>>>>>> Etotal= -42.5

 Cartesian components of stress tensor (hartree/bohr^3)
  sigma(1 1)=  2.3  sigma(3 2)=  3.1
  sigma(2 2)=  2.4  sigma(3 1)=  3.2
  sigma(3 3)=  2.5  sigma(2 1)=  3.3

END DATASET(S)
"""


def test_read_abinit_output():
    fd = StringIO(sample_outfile)
    results = read_abinit_out(fd)

    assert results.pop('version') == '8.0.8'

    atoms = results.pop('atoms')
    assert all(atoms.symbols == 'OO')
    assert atoms.positions == pytest.approx(
        np.array([[2.5, 2.5, 3.7], [2.5, 2.5, 2.5]]))
    assert all(atoms.pbc)
    assert atoms.cell[:] == pytest.approx(
        np.array([[5.0, 0.0, 0.1], [0.0, 6.0, 0.0], [0.0, 0.0, 7.0]]))

    ref_stress = pytest.approx([2.3, 2.4, 2.5, 3.1, 3.2, 3.3])
    assert results.pop('stress') / (Hartree / Bohr**3) == ref_stress
    assert results.pop('forces') == pytest.approx(
        np.array([[-0.1, -0.3, 0.4], [-0.2, -0.4, -0.5]]))

    for name in 'energy', 'free_energy':
        assert results.pop(name) / Hartree == -42.5

    assert not results


eig_text = """\
 Fermi (or HOMO) energy (hartree) =   0.123   Average Vxc (hartree)=  -0.456
 Eigenvalues (hartree) for nkpt=  2  k points:
 kpt#   1, nband=  3, wtk=  0.1, kpt=  0.2  0.3  0.4 (reduced coord)
  -0.2 0.2 0.3
 kpt#   2, nband=  3, wtk=  0.2, kpt=  0.3  0.4  0.5 (reduced coord)
  -0.3 0.4 0.5
"""


def test_parse_eig_with_fermiheader():
    eigval_ref = np.array([
        [-0.2, 0.2, 0.3],
        [-0.3, 0.4, 0.5]
    ]).reshape(1, 2, 3)  # spin x kpts x bands

    kpts_ref = np.array([
        [0.2, 0.3, 0.4],
        [0.3, 0.4, 0.5]
    ])

    weights_ref = [0.1, 0.2]

    eig_buf = StringIO(eig_text)
    data = read_eig(eig_buf)

    assert data['eigenvalues'] / Hartree == pytest.approx(eigval_ref)
    assert data['ibz_kpoints'] == pytest.approx(kpts_ref)
    assert data['kpoint_weights'] == pytest.approx(weights_ref)
    assert data['fermilevel'] / Hartree == pytest.approx(0.123)


def test_parse_eig_without_fermiheader():
    fd = StringIO(eig_text)
    next(fd)  # Header is omitted e.g. in non-selfconsistent calculations.

    data = read_eig(fd)
    assert 'fermilevel' not in data
    assert {'eigenvalues', 'ibz_kpoints', 'kpoint_weights'} == set(data)


def test_match_kpt_header():
    header_line = """\
kpt#  12, nband=  5, wtk=  0.02778, \
kpt=  0.4167  0.4167  0.0833 (reduced coord)
"""

    nbands, weight, vector = match_kpt_header(header_line)
    assert nbands == 5
    assert weight == pytest.approx(0.02778)
    assert vector == pytest.approx([0.4167, 0.4167, 0.0833])