• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

materialsproject / pymatgen / 4075885785

pending completion
4075885785

push

github

Shyue Ping Ong
Merge branch 'master' of github.com:materialsproject/pymatgen

96 of 96 new or added lines in 27 files covered. (100.0%)

81013 of 102710 relevant lines covered (78.88%)

0.79 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

99.77
/pymatgen/io/vasp/tests/test_outputs.py
1
# Copyright (c) Pymatgen Development Team.
2
# Distributed under the terms of the MIT License.
3

4

5
from __future__ import annotations
1✔
6

7
import gzip
1✔
8
import json
1✔
9
import os
1✔
10
import unittest
1✔
11
import warnings
1✔
12
import xml.etree.ElementTree as ET
1✔
13
from pathlib import Path
1✔
14
from shutil import copyfile, copyfileobj
1✔
15

16
import numpy as np
1✔
17
import pytest
1✔
18
from monty.tempfile import ScratchDir
1✔
19
from pytest import approx
1✔
20

21
from pymatgen.core import Element
1✔
22
from pymatgen.core.lattice import Lattice
1✔
23
from pymatgen.core.structure import Structure
1✔
24
from pymatgen.electronic_structure.core import Magmom, Orbital, OrbitalType, Spin
1✔
25
from pymatgen.entries.compatibility import MaterialsProjectCompatibility
1✔
26
from pymatgen.io.vasp.inputs import Kpoints, Poscar
1✔
27
from pymatgen.io.vasp.outputs import (
1✔
28
    WSWQ,
29
    BSVasprun,
30
    Chgcar,
31
    Dynmat,
32
    Eigenval,
33
    Elfcar,
34
    Locpot,
35
    Oszicar,
36
    Outcar,
37
    Procar,
38
    UnconvergedVASPWarning,
39
    VaspParserError,
40
    Vasprun,
41
    Wavecar,
42
    Waveder,
43
    Xdatcar,
44
)
45
from pymatgen.io.wannier90 import Unk
1✔
46
from pymatgen.util.testing import PymatgenTest
1✔
47

48
try:
1✔
49
    import h5py
1✔
50
except ImportError:
×
51
    h5py = None
×
52

53

54
class VasprunTest(PymatgenTest):
1✔
55
    _multiprocess_shared_ = True
1✔
56

57
    def setUp(self):
1✔
58
        warnings.simplefilter("ignore")
1✔
59

60
    def tearDown(self):
1✔
61
        warnings.simplefilter("default")
1✔
62

63
    def test_vasprun_ml(self):
1✔
64
        v = Vasprun(self.TEST_FILES_DIR / "vasprun.xml.ml_md")
1✔
65
        assert len(v.md_data) == 100
1✔
66
        for d in v.md_data:
1✔
67
            assert "structure" in d
1✔
68
            assert "forces" in d
1✔
69
            assert "energy" in d
1✔
70
        assert v.md_data[-1]["energy"]["total"] == approx(-491.51831988)
1✔
71

72
    def test_bad_random_seed(self):
1✔
73
        _ = Vasprun(self.TEST_FILES_DIR / "vasprun.bad_random_seed.xml")
1✔
74

75
    def test_multiple_dielectric(self):
1✔
76
        v = Vasprun(self.TEST_FILES_DIR / "vasprun.GW0.xml")
1✔
77
        assert len(v.other_dielectric) == 3
1✔
78

79
    def test_charge_charge_dielectric(self):
1✔
80
        """
81
        VASP 5.4.4 writes out two dielectric functions to vasprun.xml
82
        These are the "density-density" and "velocity-velocity" linear response functions.
83
        See the comments in `linear_optics.F` for details.
84
        """
85
        v = Vasprun(
1✔
86
            self.TEST_FILES_DIR / "vasprun.xml.dielectric_5.4.4",
87
            parse_potcar_file=False,
88
        )
89
        assert (v.dielectric is not None) is True
1✔
90
        assert ("density" in v.dielectric_data) is True
1✔
91
        assert ("velocity" in v.dielectric_data) is True
1✔
92

93
    def test_optical_absorption_coeff(self):
1✔
94
        v = Vasprun(self.TEST_FILES_DIR / "vasprun.BSE.xml.gz")
1✔
95
        absorption_coeff = v.optical_absorption_coeff
1✔
96
        assert absorption_coeff[1] == 0.8327903762077188
1✔
97

98
    def test_vasprun_with_more_than_two_unlabelled_dielectric_functions(self):
1✔
99
        with pytest.raises(NotImplementedError):
1✔
100
            Vasprun(
1✔
101
                self.TEST_FILES_DIR / "vasprun.xml.dielectric_bad",
102
                parse_potcar_file=False,
103
            )
104

105
    def test_bad_vasprun(self):
1✔
106
        with pytest.raises(ET.ParseError):
1✔
107
            Vasprun(self.TEST_FILES_DIR / "bad_vasprun.xml")
1✔
108

109
        with warnings.catch_warnings(record=True) as w:
1✔
110
            # Cause all warnings to always be triggered.
111
            warnings.simplefilter("always")
1✔
112
            # Trigger a warning.
113
            v = Vasprun(self.TEST_FILES_DIR / "bad_vasprun.xml", exception_on_bad_xml=False)
1✔
114
            # Verify some things
115
            assert len(v.ionic_steps) == 1
1✔
116
            assert v.final_energy == approx(-269.00551374)
1✔
117
            assert issubclass(w[-1].category, UserWarning)
1✔
118

119
    def test_runtype(self):
1✔
120
        v = Vasprun(self.TEST_FILES_DIR / "vasprun.GW0.xml")
1✔
121
        assert v.run_type in "HF"
1✔
122

123
        v = Vasprun(self.TEST_FILES_DIR / "vasprun.xml.pbesol_vdw")
1✔
124
        assert v.run_type in "PBEsol+vdW-DFT-D3-BJ"
1✔
125

126
        v = Vasprun(self.TEST_FILES_DIR / "vasprun.xml.hse06")
1✔
127
        assert v.run_type in "HSE06"
1✔
128

129
        v = Vasprun(self.TEST_FILES_DIR / "vasprun.xml.scan_rvv10")
1✔
130
        assert v.run_type in "SCAN+rVV10"
1✔
131

132
        v = Vasprun(self.TEST_FILES_DIR / "vasprun.xml.dfpt.ionic")
1✔
133
        assert v.run_type in "GGA"
1✔
134

135
        v = Vasprun(self.TEST_FILES_DIR / "vasprun.xml.dfpt")
1✔
136
        assert v.run_type in "GGA+U"
1✔
137

138
        v = Vasprun(self.TEST_FILES_DIR / "vasprun.xml.r2scan")
1✔
139
        assert v.run_type in "R2SCAN"
1✔
140

141
        v = Vasprun(self.TEST_FILES_DIR / "vasprun.xml.scan")
1✔
142
        assert v.run_type in "SCAN"
1✔
143

144
        v = Vasprun(self.TEST_FILES_DIR / "vasprun.xml.pbesol")
1✔
145
        assert v.run_type in "PBEsol"
1✔
146

147
        v = Vasprun(self.TEST_FILES_DIR / "vasprun.xml.rscan")
1✔
148
        assert v.run_type in "RSCAN"
1✔
149

150
        v = Vasprun(self.TEST_FILES_DIR / "vasprun.xml.random")
1✔
151
        assert v.run_type in "RANDOMFUNCTIONAL"
1✔
152

153
        v = Vasprun(self.TEST_FILES_DIR / "vasprun.xml.unknown")
1✔
154
        with pytest.warns(UserWarning, match="Unknown run type!"):
1✔
155
            assert v.run_type in "unknown"
1✔
156

157
    def test_vdw(self):
1✔
158
        v = Vasprun(self.TEST_FILES_DIR / "vasprun.xml.vdw")
1✔
159
        assert v.final_energy == approx(-9.78310677)
1✔
160

161
    def test_energies(self):
1✔
162
        # VASP 5.4.1
163
        v = Vasprun(self.TEST_FILES_DIR / "vasprun.xml.etest1.gz")
1✔
164
        assert v.final_energy == approx(-11.18981538)
1✔
165

166
        # VASP 6.2.1
167
        v = Vasprun(self.TEST_FILES_DIR / "vasprun.xml.etest2.gz")
1✔
168
        assert v.final_energy == approx(-11.18986774)
1✔
169

170
        # VASP 5.4.1
171
        o = Vasprun(self.TEST_FILES_DIR / "vasprun.xml.etest3.gz")
1✔
172
        assert o.final_energy == approx(-15.89355325)
1✔
173

174
        # VASP 6.2.1
175
        o = Vasprun(self.TEST_FILES_DIR / "vasprun.xml.etest4.gz")
1✔
176
        assert o.final_energy == approx(-15.89364691)
1✔
177

178
    def test_nonlmn(self):
1✔
179
        filepath = self.TEST_FILES_DIR / "vasprun.xml.nonlm"
1✔
180
        vasprun = Vasprun(filepath, parse_potcar_file=False)
1✔
181
        orbs = list(vasprun.complete_dos.pdos[vasprun.final_structure[0]])
1✔
182
        assert OrbitalType.s in orbs
1✔
183

184
    def test_standard(self):
1✔
185
        filepath = self.TEST_FILES_DIR / "vasprun.xml"
1✔
186
        vasprun = Vasprun(filepath, parse_potcar_file=False)
1✔
187

188
        # Test NELM parsing.
189
        assert vasprun.parameters["NELM"] == 60
1✔
190
        # test pdos parsing
191

192
        assert vasprun.complete_dos.spin_polarization == 1.0
1✔
193
        assert Vasprun(self.TEST_FILES_DIR / "vasprun.xml.etest1.gz").complete_dos.spin_polarization is None
1✔
194

195
        pdos0 = vasprun.complete_dos.pdos[vasprun.final_structure[0]]
1✔
196
        assert pdos0[Orbital.s][Spin.up][16] == approx(0.0026)
1✔
197
        assert pdos0[Orbital.pz][Spin.down][16] == approx(0.0012)
1✔
198
        assert pdos0[Orbital.s][Spin.up].shape == (301,)
1✔
199

200
        pdos0_norm = vasprun.complete_dos_normalized.pdos[vasprun.final_structure[0]]
1✔
201
        assert pdos0_norm[Orbital.s][Spin.up][16] == approx(0.0026)  # the site data should not change
1✔
202
        assert pdos0_norm[Orbital.s][Spin.up].shape == (301,)
1✔
203

204
        cdos_norm, cdos = vasprun.complete_dos_normalized, vasprun.complete_dos
1✔
205
        ratio = np.nanmax(cdos.densities[Spin.up] / cdos_norm.densities[Spin.up])
1✔
206
        assert ratio == approx(vasprun.final_structure.volume)  # the site data should not change
1✔
207

208
        # check you can normalize an existing DOS
209
        cdos_norm2 = cdos.get_normalized()
1✔
210
        ratio = np.nanmax(cdos.densities[Spin.up] / cdos_norm2.densities[Spin.up])
1✔
211
        assert ratio == approx(vasprun.final_structure.volume)  # the site data should not change
1✔
212

213
        # but doing so twice should not change the data
214
        cdos_norm3 = cdos_norm2.get_normalized()
1✔
215
        ratio = np.nanmax(cdos.densities[Spin.up] / cdos_norm3.densities[Spin.up])
1✔
216
        assert ratio == approx(vasprun.final_structure.volume)  # the site data should not change
1✔
217

218
        pdos0_norm = vasprun.complete_dos_normalized.pdos[vasprun.final_structure[0]]
1✔
219
        self.assertAlmostEqual(pdos0_norm[Orbital.s][Spin.up][16], 0.0026)  # the site data should not change
1✔
220
        self.assertEqual(pdos0_norm[Orbital.s][Spin.up].shape, (301,))
1✔
221

222
        cdos_norm, cdos = vasprun.complete_dos_normalized, vasprun.complete_dos
1✔
223
        ratio = np.nanmax(cdos.densities[Spin.up] / cdos_norm.densities[Spin.up])
1✔
224
        self.assertAlmostEqual(ratio, vasprun.final_structure.volume)  # the site data should not change
1✔
225

226
        filepath2 = self.TEST_FILES_DIR / "lifepo4.xml"
1✔
227
        vasprun_ggau = Vasprun(filepath2, parse_projected_eigen=True, parse_potcar_file=False)
1✔
228
        totalscsteps = sum(len(i["electronic_steps"]) for i in vasprun.ionic_steps)
1✔
229
        assert 29 == len(vasprun.ionic_steps)
1✔
230
        assert len(vasprun.structures) == len(vasprun.ionic_steps)
1✔
231

232
        trajectory = vasprun.get_trajectory()
1✔
233
        assert len(trajectory) == len(vasprun.ionic_steps)
1✔
234
        assert "forces" in trajectory[0].site_properties
1✔
235

236
        for i, step in enumerate(vasprun.ionic_steps):
1✔
237
            assert vasprun.structures[i] == step["structure"]
1✔
238

239
        assert all(
1✔
240
            vasprun.structures[i] == vasprun.ionic_steps[i]["structure"] for i in range(len(vasprun.ionic_steps))
241
        )
242

243
        assert 308 == totalscsteps, "Incorrect number of energies read from vasprun.xml"
1✔
244

245
        assert ["Li"] + 4 * ["Fe"] + 4 * ["P"] + 16 * ["O"] == vasprun.atomic_symbols
1✔
246
        assert vasprun.final_structure.composition.reduced_formula == "LiFe4(PO4)4"
1✔
247
        assert vasprun.incar is not None, "Incar cannot be read"
1✔
248
        assert vasprun.kpoints is not None, "Kpoints cannot be read"
1✔
249
        assert vasprun.eigenvalues is not None, "Eigenvalues cannot be read"
1✔
250
        assert vasprun.final_energy == approx(-269.38319884, abs=1e-7)
1✔
251
        assert vasprun.tdos.get_gap() == approx(2.0589, abs=1e-4)
1✔
252
        expectedans = (2.539, 4.0906, 1.5516, False)
1✔
253
        (gap, cbm, vbm, direct) = vasprun.eigenvalue_band_properties
1✔
254
        assert gap == approx(expectedans[0])
1✔
255
        assert cbm == approx(expectedans[1])
1✔
256
        assert vbm == approx(expectedans[2])
1✔
257
        assert direct == expectedans[3]
1✔
258
        assert not vasprun.is_hubbard
1✔
259
        assert vasprun.potcar_symbols == [
1✔
260
            "PAW_PBE Li 17Jan2003",
261
            "PAW_PBE Fe 06Sep2000",
262
            "PAW_PBE Fe 06Sep2000",
263
            "PAW_PBE P 17Jan2003",
264
            "PAW_PBE O 08Apr2002",
265
        ]
266
        assert vasprun.kpoints is not None, "Kpoints cannot be read"
1✔
267
        assert vasprun.actual_kpoints is not None, "Actual kpoints cannot be read"
1✔
268
        assert vasprun.actual_kpoints_weights is not None, "Actual kpoints weights cannot be read"
1✔
269
        for atomdoses in vasprun.pdos:
1✔
270
            for orbitaldos in atomdoses:
1✔
271
                assert orbitaldos is not None, "Partial Dos cannot be read"
1✔
272

273
        # test skipping ionic steps.
274
        vasprun_skip = Vasprun(filepath, 3, parse_potcar_file=False)
1✔
275
        assert vasprun_skip.nionic_steps == 29
1✔
276
        assert len(vasprun_skip.ionic_steps) == int(vasprun.nionic_steps / 3) + 1
1✔
277
        assert len(vasprun_skip.ionic_steps) == len(vasprun_skip.structures)
1✔
278
        assert len(vasprun_skip.ionic_steps) == int(vasprun.nionic_steps / 3) + 1
1✔
279
        # Check that nionic_steps is preserved no matter what.
280
        assert vasprun_skip.nionic_steps == vasprun.nionic_steps
1✔
281

282
        assert vasprun_skip.final_energy != approx(vasprun.final_energy)
1✔
283

284
        # Test with ionic_step_offset
285
        vasprun_offset = Vasprun(filepath, 3, 6, parse_potcar_file=False)
1✔
286
        assert len(vasprun_offset.ionic_steps) == int(len(vasprun.ionic_steps) / 3) - 1
1✔
287
        assert vasprun_offset.structures[0] == vasprun_skip.structures[2]
1✔
288

289
        assert vasprun_ggau.is_hubbard
1✔
290
        assert vasprun_ggau.hubbards["Fe"] == 4.3
1✔
291
        assert vasprun_ggau.projected_eigenvalues[Spin.up][0][0][96][0] == approx(0.0032)
1✔
292
        d = vasprun_ggau.as_dict()
1✔
293
        assert d["elements"] == ["Fe", "Li", "O", "P"]
1✔
294
        assert d["nelements"] == 4
1✔
295

296
        entry = vasprun.get_computed_entry(inc_structure=True)
1✔
297
        assert entry.entry_id.startswith("vasprun")
1✔
298
        assert entry.parameters["run_type"] == "PBEO or other Hybrid Functional"
1✔
299

300
    def test_unconverged(self):
1✔
301
        filepath = self.TEST_FILES_DIR / "vasprun.xml.unconverged"
1✔
302
        with warnings.catch_warnings(record=True) as w:
1✔
303
            # Cause all warnings to always be triggered.
304
            warnings.simplefilter("always")
1✔
305
            # Trigger a warning.
306
            vasprun_unconverged = Vasprun(filepath, parse_potcar_file=False)
1✔
307
            # Verify some things
308
            assert len(w) == 1
1✔
309
            assert issubclass(w[-1].category, UnconvergedVASPWarning)
1✔
310

311
            assert vasprun_unconverged.converged_ionic
1✔
312
            assert not vasprun_unconverged.converged_electronic
1✔
313
            assert not vasprun_unconverged.converged
1✔
314

315
    def test_dfpt(self):
1✔
316
        filepath = self.TEST_FILES_DIR / "vasprun.xml.dfpt"
1✔
317
        vasprun_dfpt = Vasprun(filepath, parse_potcar_file=False)
1✔
318
        assert vasprun_dfpt.epsilon_static[0][0] == approx(3.26105533)
1✔
319
        assert vasprun_dfpt.epsilon_static[0][1] == approx(-0.00459066)
1✔
320
        assert vasprun_dfpt.epsilon_static[2][2] == approx(3.24330517)
1✔
321
        assert vasprun_dfpt.epsilon_static_wolfe[0][0] == approx(3.33402531)
1✔
322
        assert vasprun_dfpt.epsilon_static_wolfe[0][1] == approx(-0.00559998)
1✔
323
        assert vasprun_dfpt.epsilon_static_wolfe[2][2] == approx(3.31237357)
1✔
324
        assert vasprun_dfpt.converged
1✔
325

326
        entry = vasprun_dfpt.get_computed_entry()
1✔
327
        entry = MaterialsProjectCompatibility(check_potcar_hash=False).process_entry(entry)
1✔
328
        assert entry.uncorrected_energy + entry.correction == approx(entry.energy)
1✔
329

330
    def test_dfpt_ionic(self):
1✔
331
        filepath = self.TEST_FILES_DIR / "vasprun.xml.dfpt.ionic"
1✔
332
        vasprun_dfpt_ionic = Vasprun(filepath, parse_potcar_file=False)
1✔
333
        assert vasprun_dfpt_ionic.epsilon_ionic[0][0] == approx(515.73485838)
1✔
334
        assert vasprun_dfpt_ionic.epsilon_ionic[0][1] == approx(-0.00263523)
1✔
335
        assert vasprun_dfpt_ionic.epsilon_ionic[2][2] == approx(19.02110169)
1✔
336

337
    def test_dfpt_unconverged(self):
1✔
338
        filepath = self.TEST_FILES_DIR / "vasprun.xml.dfpt.unconverged"
1✔
339
        vasprun_dfpt_unconv = Vasprun(filepath, parse_potcar_file=False)
1✔
340
        assert not vasprun_dfpt_unconv.converged_electronic
1✔
341
        assert vasprun_dfpt_unconv.converged_ionic
1✔
342
        assert not vasprun_dfpt_unconv.converged
1✔
343

344
    def test_chi(self):
1✔
345
        filepath = self.TEST_FILES_DIR / "vasprun.xml.chi.gz"
1✔
346
        vasprun_chi = Vasprun(filepath, parse_potcar_file=False)
1✔
347
        assert vasprun_chi.incar.get("ALGO", ""), "CHI"
1✔
348

349
    def test_uniform(self):
1✔
350
        vasprun_uniform = Vasprun(self.TEST_FILES_DIR / "vasprun.xml.uniform", parse_potcar_file=False)
1✔
351
        assert vasprun_uniform.kpoints.style == Kpoints.supported_modes.Reciprocal
1✔
352

353
    def test_no_projected(self):
1✔
354
        vasprun_no_pdos = Vasprun(self.TEST_FILES_DIR / "Li_no_projected.xml", parse_potcar_file=False)
1✔
355
        assert vasprun_no_pdos.complete_dos is not None
1✔
356
        assert not vasprun_no_pdos.dos_has_errors
1✔
357

358
    def test_dielectric(self):
1✔
359
        vasprun_diel = Vasprun(self.TEST_FILES_DIR / "vasprun.xml.dielectric", parse_potcar_file=False)
1✔
360
        assert 0.4294 == approx(vasprun_diel.dielectric[0][10])
1✔
361
        assert 19.941 == approx(vasprun_diel.dielectric[1][51][0])
1✔
362
        assert 19.941 == approx(vasprun_diel.dielectric[1][51][1])
1✔
363
        assert 19.941 == approx(vasprun_diel.dielectric[1][51][2])
1✔
364
        assert 0.0 == approx(vasprun_diel.dielectric[1][51][3])
1✔
365
        assert 34.186 == approx(vasprun_diel.dielectric[2][85][0])
1✔
366
        assert 34.186 == approx(vasprun_diel.dielectric[2][85][1])
1✔
367
        assert 34.186 == approx(vasprun_diel.dielectric[2][85][2])
1✔
368
        assert 0.0 == approx(vasprun_diel.dielectric[2][85][3])
1✔
369

370
    def test_dielectric_vasp608(self):
1✔
371
        # test reading dielectric constant in vasp 6.0.8
372
        vasprun_diel = Vasprun(
1✔
373
            self.TEST_FILES_DIR / "vasprun.xml.dielectric_6.0.8",
374
            parse_potcar_file=False,
375
        )
376
        assert 0.4338 == approx(vasprun_diel.dielectric[0][10])
1✔
377
        assert 5.267 == approx(vasprun_diel.dielectric[1][51][0])
1✔
378
        assert 0.4338 == approx(vasprun_diel.dielectric_data["density"][0][10])
1✔
379
        assert 5.267 == approx(vasprun_diel.dielectric_data["density"][1][51][0])
1✔
380
        assert 0.4338 == approx(vasprun_diel.dielectric_data["velocity"][0][10])
1✔
381
        assert 1.0741 == approx(vasprun_diel.dielectric_data["velocity"][1][51][0])
1✔
382
        assert len(vasprun_diel.other_dielectric) == 0
1✔
383

384
    def test_indirect_vasprun(self):
1✔
385
        v = Vasprun(self.TEST_FILES_DIR / "vasprun.xml.indirect.gz")
1✔
386
        (gap, cbm, vbm, direct) = v.eigenvalue_band_properties
1✔
387
        assert not direct
1✔
388

389
    def test_optical_vasprun(self):
1✔
390
        vasprun_optical = Vasprun(
1✔
391
            self.TEST_FILES_DIR / "vasprun.xml.opticaltransitions",
392
            parse_potcar_file=False,
393
        )
394
        assert 3.084 == approx(vasprun_optical.optical_transition[0][0])
1✔
395
        assert 3.087 == approx(vasprun_optical.optical_transition[3][0])
1✔
396
        assert 0.001 == approx(vasprun_optical.optical_transition[0][1])
1✔
397
        assert 0.001 == approx(vasprun_optical.optical_transition[1][1])
1✔
398
        assert 0.001 == approx(vasprun_optical.optical_transition[7][1])
1✔
399
        assert 0.001 == approx(vasprun_optical.optical_transition[19][1])
1✔
400
        assert 3.3799999999 == approx(vasprun_optical.optical_transition[54][0])
1✔
401
        assert 3.381 == approx(vasprun_optical.optical_transition[55][0])
1✔
402
        assert 3.381 == approx(vasprun_optical.optical_transition[56][0])
1✔
403
        assert 10554.9860 == approx(vasprun_optical.optical_transition[54][1])
1✔
404
        assert 0.0 == approx(vasprun_optical.optical_transition[55][1])
1✔
405
        assert 0.001 == approx(vasprun_optical.optical_transition[56][1])
1✔
406

407
    def test_force_constants(self):
1✔
408
        vasprun_fc = Vasprun(self.TEST_FILES_DIR / "vasprun.xml.dfpt.phonon", parse_potcar_file=False)
1✔
409
        fc_ans = [
1✔
410
            [-0.00184451, -0.0, -0.0],
411
            [-0.0, -0.00933824, -0.03021279],
412
            [-0.0, -0.03021279, 0.01202547],
413
        ]
414
        nm_ans = [
1✔
415
            [0.0884346, -0.08837289, -0.24995639],
416
            [-0.0884346, 0.08837289, 0.24995639],
417
            [0.15306645, -0.05105771, -0.14441306],
418
            [-0.15306645, 0.05105771, 0.14441306],
419
            [-0.0884346, 0.08837289, 0.24995639],
420
            [0.0884346, -0.08837289, -0.24995639],
421
            [-0.15306645, 0.05105771, 0.14441306],
422
            [0.15306645, -0.05105771, -0.14441306],
423
            [-0.0884346, 0.08837289, 0.24995639],
424
            [0.0884346, -0.08837289, -0.24995639],
425
            [-0.15306645, 0.05105771, 0.14441306],
426
            [0.15306645, -0.05105771, -0.14441306],
427
            [0.0884346, -0.08837289, -0.24995639],
428
            [-0.0884346, 0.08837289, 0.24995639],
429
            [0.15306645, -0.05105771, -0.14441306],
430
            [-0.15306645, 0.05105771, 0.14441306],
431
        ]
432
        nm_eigenval_ans = [
1✔
433
            -0.59067079,
434
            -0.59067079,
435
            -0.59067003,
436
            -0.59067003,
437
            -0.59067003,
438
            -0.59067003,
439
            -0.585009,
440
            -0.585009,
441
            -0.58500895,
442
            -0.58500883,
443
            -0.5062956,
444
            -0.5062956,
445
        ]
446
        assert vasprun_fc.force_constants.shape == (16, 16, 3, 3)
1✔
447
        assert np.allclose(vasprun_fc.force_constants[8, 9], fc_ans)
1✔
448
        assert vasprun_fc.normalmode_eigenvals.size == 48
1✔
449
        assert np.allclose(vasprun_fc.normalmode_eigenvals[17:29], nm_eigenval_ans)
1✔
450
        assert vasprun_fc.normalmode_eigenvecs.shape == (48, 16, 3)
1✔
451
        assert np.allclose(vasprun_fc.normalmode_eigenvecs[33], nm_ans)
1✔
452

453
    def test_Xe(self):
1✔
454
        vr = Vasprun(self.TEST_FILES_DIR / "vasprun.xml.xe", parse_potcar_file=False)
1✔
455
        assert vr.atomic_symbols == ["Xe"]
1✔
456

457
    def test_invalid_element(self):
1✔
458
        with pytest.raises(ValueError):
1✔
459
            Vasprun(self.TEST_FILES_DIR / "vasprun.xml.wrong_sp")
1✔
460

461
    def test_selective_dynamics(self):
1✔
462
        vsd = Vasprun(self.TEST_FILES_DIR / "vasprun.xml.indirect.gz")
1✔
463
        np.testing.assert_array_equal(
1✔
464
            vsd.final_structure.site_properties.get("selective_dynamics"),
465
            [[True] * 3, [False] * 3],
466
            "Selective dynamics parsing error",
467
        )
468

469
    def test_as_dict(self):
1✔
470
        filepath = self.TEST_FILES_DIR / "vasprun.xml"
1✔
471
        vasprun = Vasprun(filepath, parse_potcar_file=False)
1✔
472
        # Test that as_dict() is json-serializable
473
        assert json.dumps(vasprun.as_dict()) is not None
1✔
474
        assert vasprun.as_dict()["input"]["potcar_type"] == ["PAW_PBE", "PAW_PBE", "PAW_PBE", "PAW_PBE", "PAW_PBE"]
1✔
475
        assert vasprun.as_dict()["input"]["nkpoints"] == 24
1✔
476

477
    def test_get_band_structure(self):
1✔
478
        with warnings.catch_warnings():
1✔
479
            warnings.simplefilter("ignore")
1✔
480
            filepath = self.TEST_FILES_DIR / "vasprun_Si_bands.xml"
1✔
481
            vasprun = Vasprun(filepath, parse_projected_eigen=True, parse_potcar_file=False)
1✔
482
            bs = vasprun.get_band_structure(kpoints_filename=self.TEST_FILES_DIR / "KPOINTS_Si_bands")
1✔
483
            cbm = bs.get_cbm()
1✔
484
            vbm = bs.get_vbm()
1✔
485
            assert cbm["kpoint_index"] == [13], "wrong cbm kpoint index"
1✔
486
            assert cbm["energy"] == approx(6.2301), "wrong cbm energy"
1✔
487
            assert cbm["band_index"] == {Spin.up: [4], Spin.down: [4]}, "wrong cbm bands"
1✔
488
            assert vbm["kpoint_index"] == [0, 63, 64]
1✔
489
            assert vbm["energy"] == approx(5.6158), "wrong vbm energy"
1✔
490
            assert vbm["band_index"] == {Spin.up: [1, 2, 3], Spin.down: [1, 2, 3]}, "wrong vbm bands"
1✔
491
            assert vbm["kpoint"].label == "\\Gamma", "wrong vbm label"
1✔
492
            assert cbm["kpoint"].label is None, "wrong cbm label"
1✔
493

494
            projected = bs.get_projection_on_elements()
1✔
495
            assert projected[Spin.up][0][0]["Si"] == approx(0.4238)
1✔
496
            projected = bs.get_projections_on_elements_and_orbitals({"Si": ["s"]})
1✔
497
            assert projected[Spin.up][0][0]["Si"]["s"] == approx(0.4238)
1✔
498

499
            # Test compressed files case 1: compressed KPOINTS in current dir
500
            with ScratchDir("./"):
1✔
501
                copyfile(self.TEST_FILES_DIR / "vasprun_Si_bands.xml", "vasprun.xml")
1✔
502

503
                # Check for error if no KPOINTS file
504
                vasprun = Vasprun("vasprun.xml", parse_projected_eigen=True, parse_potcar_file=False)
1✔
505
                with pytest.raises(VaspParserError):
1✔
506
                    _ = vasprun.get_band_structure(line_mode=True)
1✔
507

508
                # Check KPOINTS.gz successfully inferred and used if present
509
                with open(self.TEST_FILES_DIR / "KPOINTS_Si_bands", "rb") as f_in:
1✔
510
                    with gzip.open("KPOINTS.gz", "wb") as f_out:
1✔
511
                        copyfileobj(f_in, f_out)
1✔
512
                bs_kpts_gzip = vasprun.get_band_structure()
1✔
513
                assert bs.efermi == bs_kpts_gzip.efermi
1✔
514
                assert bs.as_dict() == bs_kpts_gzip.as_dict()
1✔
515

516
            # Test compressed files case 2: compressed vasprun in another dir
517
            with ScratchDir("./"):
1✔
518
                os.mkdir("deeper")
1✔
519
                copyfile(self.TEST_FILES_DIR / "KPOINTS_Si_bands", Path("deeper") / "KPOINTS")
1✔
520
                with open(self.TEST_FILES_DIR / "vasprun_Si_bands.xml", "rb") as f_in:
1✔
521
                    with gzip.open(os.path.join("deeper", "vasprun.xml.gz"), "wb") as f_out:
1✔
522
                        copyfileobj(f_in, f_out)
1✔
523
                vasprun = Vasprun(
1✔
524
                    os.path.join("deeper", "vasprun.xml.gz"),
525
                    parse_projected_eigen=True,
526
                    parse_potcar_file=False,
527
                )
528
                bs_vasprun_gzip = vasprun.get_band_structure(line_mode=True)
1✔
529
                assert bs.efermi == bs_vasprun_gzip.efermi
1✔
530
                assert bs.as_dict() == bs_vasprun_gzip.as_dict()
1✔
531

532
            # test hybrid band structures
533
            vasprun.actual_kpoints_weights[-1] = 0.0
1✔
534
            bs = vasprun.get_band_structure(kpoints_filename=self.TEST_FILES_DIR / "KPOINTS_Si_bands")
1✔
535
            cbm = bs.get_cbm()
1✔
536
            vbm = bs.get_vbm()
1✔
537
            assert cbm["kpoint_index"] == [0]
1✔
538
            assert cbm["energy"] == approx(6.3676)
1✔
539
            assert cbm["kpoint"].label is None
1✔
540
            assert vbm["kpoint_index"] == [0]
1✔
541
            assert vbm["energy"] == approx(2.8218)
1✔
542
            assert vbm["kpoint"].label is None
1✔
543

544
            # test self-consistent band structure calculation for non-hybrid functionals
545
            vasprun = Vasprun(
1✔
546
                self.TEST_FILES_DIR / "vasprun.xml.forcehybridlikecalc",
547
                parse_projected_eigen=True,
548
                parse_potcar_file=False,
549
            )
550
            bs = vasprun.get_band_structure(
1✔
551
                kpoints_filename=self.TEST_FILES_DIR / "KPOINTS.forcehybridlikecalc",
552
                force_hybrid_mode=True,
553
                line_mode=True,
554
            )
555

556
            dict_to_test = bs.get_band_gap()
1✔
557

558
            assert dict_to_test["direct"]
1✔
559
            assert dict_to_test["energy"] == approx(6.007899999999999)
1✔
560
            assert dict_to_test["transition"] == "\\Gamma-\\Gamma"
1✔
561
            assert bs.get_branch(0)[0]["start_index"] == 0
1✔
562
            assert bs.get_branch(0)[0]["end_index"] == 0
1✔
563

564
    def test_projected_magnetisation(self):
1✔
565
        filepath = self.TEST_FILES_DIR / "vasprun.lvel.Si2H.xml"
1✔
566
        vasprun = Vasprun(filepath, parse_projected_eigen=True)
1✔
567
        assert vasprun.projected_magnetisation is not None
1✔
568
        assert vasprun.projected_magnetisation.shape == (76, 240, 4, 9, 3)
1✔
569
        assert vasprun.projected_magnetisation[0, 0, 0, 0, 0] == approx(-0.0712)
1✔
570

571
    def test_smart_efermi(self):
1✔
572
        # branch 1 - E_fermi does not cross a band
573
        vrun = Vasprun(self.TEST_FILES_DIR / "vasprun.xml.LiF")
1✔
574
        smart_fermi = vrun.calculate_efermi()
1✔
575
        assert smart_fermi == approx(vrun.efermi, abs=1e-4)
1✔
576
        eigen_gap = vrun.eigenvalue_band_properties[0]
1✔
577
        bs_gap = vrun.get_band_structure(efermi=smart_fermi).get_band_gap()["energy"]
1✔
578
        assert bs_gap == approx(eigen_gap, abs=1e-3)
1✔
579

580
        # branch 2 - E_fermi crosses a band but bandgap=0
581
        vrun = Vasprun(self.TEST_FILES_DIR / "vasprun.xml.Al")
1✔
582
        smart_fermi = vrun.calculate_efermi()
1✔
583
        assert smart_fermi == approx(vrun.efermi, abs=1e-4)
1✔
584
        eigen_gap = vrun.eigenvalue_band_properties[0]
1✔
585
        bs_gap = vrun.get_band_structure(efermi=smart_fermi).get_band_gap()["energy"]
1✔
586
        assert bs_gap == approx(eigen_gap, abs=1e-3)
1✔
587

588
        # branch 3 - E_fermi crosses a band in an insulator
589
        vrun = Vasprun(self.TEST_FILES_DIR / "vasprun.xml.LiH_bad_efermi")
1✔
590
        smart_fermi = vrun.calculate_efermi()
1✔
591
        assert smart_fermi != approx(vrun.efermi, abs=1e-4)
1✔
592
        eigen_gap = vrun.eigenvalue_band_properties[0]
1✔
593
        bs_gap = vrun.get_band_structure(efermi="smart").get_band_gap()["energy"]
1✔
594
        assert bs_gap == approx(eigen_gap, abs=1e-3)
1✔
595
        assert vrun.get_band_structure(efermi=None).get_band_gap()["energy"] != approx(eigen_gap, abs=1e-3)
1✔
596
        assert bs_gap != 0
1✔
597

598
        # branch 4 - E_fermi incorrectly placed inside a band
599
        vrun = Vasprun(self.TEST_FILES_DIR / "vasprun.xml.bad_fermi.gz")
1✔
600
        smart_fermi = vrun.calculate_efermi()
1✔
601
        assert smart_fermi == approx(6.0165)
1✔
602

603
    def test_sc_step_overflow(self):
1✔
604
        filepath = self.TEST_FILES_DIR / "vasprun.xml.sc_overflow"
1✔
605
        # with warnings.catch_warnings(record=True) as w:
606
        #     warnings.simplefilter("always")
607
        #     vasprun = Vasprun(filepath)
608
        #     self.assertEqual(len(w), 3)
609
        vasprun = Vasprun(filepath)
1✔
610
        estep = vasprun.ionic_steps[0]["electronic_steps"][29]
1✔
611
        assert np.isnan(estep["e_wo_entrp"])
1✔
612

613
    def test_update_potcar(self):
1✔
614
        filepath = self.TEST_FILES_DIR / "vasprun.xml"
1✔
615
        potcar_path = self.TEST_FILES_DIR / "POTCAR.LiFePO4.gz"
1✔
616
        potcar_path2 = self.TEST_FILES_DIR / "POTCAR2.LiFePO4.gz"
1✔
617
        vasprun = Vasprun(filepath, parse_potcar_file=False)
1✔
618
        assert vasprun.potcar_spec == [
1✔
619
            {"titel": "PAW_PBE Li 17Jan2003", "hash": None},
620
            {"titel": "PAW_PBE Fe 06Sep2000", "hash": None},
621
            {"titel": "PAW_PBE Fe 06Sep2000", "hash": None},
622
            {"titel": "PAW_PBE P 17Jan2003", "hash": None},
623
            {"titel": "PAW_PBE O 08Apr2002", "hash": None},
624
        ]
625

626
        vasprun.update_potcar_spec(potcar_path)
1✔
627
        assert vasprun.potcar_spec == [
1✔
628
            {
629
                "titel": "PAW_PBE Li 17Jan2003",
630
                "hash": "65e83282d1707ec078c1012afbd05be8",
631
            },
632
            {
633
                "titel": "PAW_PBE Fe 06Sep2000",
634
                "hash": "9530da8244e4dac17580869b4adab115",
635
            },
636
            {
637
                "titel": "PAW_PBE Fe 06Sep2000",
638
                "hash": "9530da8244e4dac17580869b4adab115",
639
            },
640
            {
641
                "titel": "PAW_PBE P 17Jan2003",
642
                "hash": "7dc3393307131ae67785a0cdacb61d5f",
643
            },
644
            {
645
                "titel": "PAW_PBE O 08Apr2002",
646
                "hash": "7a25bc5b9a5393f46600a4939d357982",
647
            },
648
        ]
649

650
        vasprun2 = Vasprun(filepath, parse_potcar_file=False)
1✔
651
        with pytest.raises(ValueError):
1✔
652
            vasprun2.update_potcar_spec(potcar_path2)
1✔
653
        vasprun = Vasprun(filepath, parse_potcar_file=potcar_path)
1✔
654

655
        assert vasprun.potcar_spec == [
1✔
656
            {
657
                "titel": "PAW_PBE Li 17Jan2003",
658
                "hash": "65e83282d1707ec078c1012afbd05be8",
659
            },
660
            {
661
                "titel": "PAW_PBE Fe 06Sep2000",
662
                "hash": "9530da8244e4dac17580869b4adab115",
663
            },
664
            {
665
                "titel": "PAW_PBE Fe 06Sep2000",
666
                "hash": "9530da8244e4dac17580869b4adab115",
667
            },
668
            {
669
                "titel": "PAW_PBE P 17Jan2003",
670
                "hash": "7dc3393307131ae67785a0cdacb61d5f",
671
            },
672
            {
673
                "titel": "PAW_PBE O 08Apr2002",
674
                "hash": "7a25bc5b9a5393f46600a4939d357982",
675
            },
676
        ]
677

678
        with pytest.raises(ValueError):
1✔
679
            Vasprun(filepath, parse_potcar_file=potcar_path2)
1✔
680

681
    def test_search_for_potcar(self):
1✔
682
        filepath = self.TEST_FILES_DIR / "vasprun.xml"
1✔
683
        vasprun = Vasprun(filepath, parse_potcar_file=True)
1✔
684
        assert vasprun.potcar_spec == [
1✔
685
            {
686
                "titel": "PAW_PBE Li 17Jan2003",
687
                "hash": "65e83282d1707ec078c1012afbd05be8",
688
            },
689
            {
690
                "titel": "PAW_PBE Fe 06Sep2000",
691
                "hash": "9530da8244e4dac17580869b4adab115",
692
            },
693
            {
694
                "titel": "PAW_PBE Fe 06Sep2000",
695
                "hash": "9530da8244e4dac17580869b4adab115",
696
            },
697
            {
698
                "titel": "PAW_PBE P 17Jan2003",
699
                "hash": "7dc3393307131ae67785a0cdacb61d5f",
700
            },
701
            {
702
                "titel": "PAW_PBE O 08Apr2002",
703
                "hash": "7a25bc5b9a5393f46600a4939d357982",
704
            },
705
        ]
706

707
    def test_potcar_not_found(self):
1✔
708
        filepath = self.TEST_FILES_DIR / "vasprun.xml"
1✔
709
        # Ensure no potcar is found and nothing is updated
710
        with warnings.catch_warnings(record=True) as w:
1✔
711
            warnings.simplefilter("always")
1✔
712
            vasprun = Vasprun(filepath, parse_potcar_file=".")
1✔
713
            assert len(w) == 2
1✔
714
            assert vasprun.potcar_spec == [
1✔
715
                {"titel": "PAW_PBE Li 17Jan2003", "hash": None},
716
                {"titel": "PAW_PBE Fe 06Sep2000", "hash": None},
717
                {"titel": "PAW_PBE Fe 06Sep2000", "hash": None},
718
                {"titel": "PAW_PBE P 17Jan2003", "hash": None},
719
                {"titel": "PAW_PBE O 08Apr2002", "hash": None},
720
            ]
721

722
    def test_parsing_chemical_shift_calculations(self):
1✔
723
        with warnings.catch_warnings():
1✔
724
            warnings.simplefilter("ignore")
1✔
725
            filepath = self.TEST_FILES_DIR / "nmr" / "cs" / "basic" / "vasprun.xml.chemical_shift.scstep"
1✔
726
            vasprun = Vasprun(filepath)
1✔
727
            nestep = len(vasprun.ionic_steps[-1]["electronic_steps"])
1✔
728
            assert nestep == 10
1✔
729
            assert vasprun.converged
1✔
730

731
    def test_parsing_efg_calcs(self):
1✔
732
        with warnings.catch_warnings():
1✔
733
            warnings.simplefilter("ignore")
1✔
734
            filepath = self.TEST_FILES_DIR / "nmr" / "efg" / "AlPO4" / "vasprun.xml"
1✔
735
            vasprun = Vasprun(filepath)
1✔
736
            nestep = len(vasprun.ionic_steps[-1]["electronic_steps"])
1✔
737
            assert nestep == 18
1✔
738
            assert vasprun.converged
1✔
739

740
    def test_charged_structure(self):
1✔
741
        vpath = self.TEST_FILES_DIR / "vasprun.charged.xml"
1✔
742
        potcar_path = self.TEST_FILES_DIR / "POT_GGA_PAW_PBE" / "POTCAR.Si.gz"
1✔
743
        vasprun = Vasprun(vpath, parse_potcar_file=False)
1✔
744
        vasprun.update_charge_from_potcar(potcar_path)
1✔
745
        assert vasprun.parameters.get("NELECT", 8) == 9
1✔
746
        assert vasprun.structures[0].charge == -1
1✔
747
        assert vasprun.initial_structure.charge == -1
1✔
748
        assert vasprun.final_structure.charge == -1
1✔
749

750
        vpath = self.TEST_FILES_DIR / "vasprun.split.charged.xml"
1✔
751
        potcar_path = self.TEST_FILES_DIR / "POTCAR.split.charged.gz"
1✔
752
        vasprun = Vasprun(vpath, parse_potcar_file=False)
1✔
753
        vasprun.update_charge_from_potcar(potcar_path)
1✔
754
        assert vasprun.parameters.get("NELECT", 0) == 7
1✔
755
        assert vasprun.structures[-1].charge == -1
1✔
756
        assert vasprun.initial_structure.charge == -1
1✔
757
        assert vasprun.final_structure.charge == -1
1✔
758

759
    def test_kpointset_electronvelocities(self):
1✔
760
        vpath = self.TEST_FILES_DIR / "vasprun.lvel.Si2H.xml"
1✔
761
        vasprun = Vasprun(vpath, parse_potcar_file=False)
1✔
762
        assert vasprun.eigenvalues[Spin.up].shape[0] == len(vasprun.actual_kpoints)
1✔
763

764
    def test_eigenvalue_band_properties_separate_spins(self):
1✔
765
        eig = Vasprun(self.TEST_FILES_DIR / "vasprun_eig_separate_spins.xml.gz", separate_spins=True)
1✔
766
        props = eig.eigenvalue_band_properties
1✔
767
        eig2 = Vasprun(self.TEST_FILES_DIR / "vasprun_eig_separate_spins.xml.gz", separate_spins=False)
1✔
768
        props2 = eig2.eigenvalue_band_properties
1✔
769
        assert props[0][0] == approx(2.8772, abs=1e-4)
1✔
770
        assert props[0][1] == approx(1.2810, abs=1e-4)
1✔
771
        assert props[1][0] == approx(3.6741, abs=1e-4)
1✔
772
        assert props[1][1] == approx(1.6225, abs=1e-4)
1✔
773
        assert props[2][0] == approx(0.7969, abs=1e-4)
1✔
774
        assert props[2][1] == approx(0.3415, abs=1e-4)
1✔
775
        assert props2[0] == approx(np.min(props[1]) - np.max(props[2]), abs=1e-4)
1✔
776
        assert props[3][0] is True
1✔
777
        assert props[3][1] is True
1✔
778

779

780
class OutcarTest(PymatgenTest):
1✔
781
    _multiprocess_shared_ = True
1✔
782

783
    def test_init(self):
1✔
784
        for f in ["OUTCAR", "OUTCAR.gz"]:
1✔
785
            filepath = self.TEST_FILES_DIR / f
1✔
786
            outcar = Outcar(filepath)
1✔
787
            expected_mag = (
1✔
788
                {"d": 0.0, "p": 0.003, "s": 0.002, "tot": 0.005},
789
                {"d": 0.798, "p": 0.008, "s": 0.007, "tot": 0.813},
790
                {"d": 0.798, "p": 0.008, "s": 0.007, "tot": 0.813},
791
                {"d": 0.0, "p": -0.117, "s": 0.005, "tot": -0.112},
792
                {"d": 0.0, "p": -0.165, "s": 0.004, "tot": -0.162},
793
                {"d": 0.0, "p": -0.117, "s": 0.005, "tot": -0.112},
794
                {"d": 0.0, "p": -0.165, "s": 0.004, "tot": -0.162},
795
            )
796
            expected_chg = (
1✔
797
                {"p": 0.154, "s": 0.078, "d": 0.0, "tot": 0.232},
798
                {"p": 0.707, "s": 0.463, "d": 8.316, "tot": 9.486},
799
                {"p": 0.707, "s": 0.463, "d": 8.316, "tot": 9.486},
800
                {"p": 3.388, "s": 1.576, "d": 0.0, "tot": 4.964},
801
                {"p": 3.365, "s": 1.582, "d": 0.0, "tot": 4.947},
802
                {"p": 3.388, "s": 1.576, "d": 0.0, "tot": 4.964},
803
                {"p": 3.365, "s": 1.582, "d": 0.0, "tot": 4.947},
804
            )
805

806
            assert outcar.magnetization == approx(expected_mag, abs=1e-5), "Wrong magnetization read from Outcar"
1✔
807
            assert outcar.charge == approx(expected_chg, abs=1e-5), "Wrong charge read from Outcar"
1✔
808
            assert not outcar.is_stopped
1✔
809
            assert outcar.run_stats == {
1✔
810
                "System time (sec)": 0.938,
811
                "Total CPU time used (sec)": 545.142,
812
                "Elapsed time (sec)": 546.709,
813
                "Maximum memory used (kb)": 0.0,
814
                "Average memory used (kb)": 0.0,
815
                "User time (sec)": 544.204,
816
                "cores": 8,
817
            }
818
            assert outcar.efermi == approx(2.0112)
1✔
819
            assert outcar.nelect == approx(44.9999991)
1✔
820
            assert outcar.total_mag == approx(0.9999998)
1✔
821

822
            assert outcar.as_dict() is not None
1✔
823

824
            assert not outcar.lepsilon
1✔
825

826
            toten = 0
1✔
827
            for k in outcar.final_energy_contribs:
1✔
828
                toten += outcar.final_energy_contribs[k]
1✔
829
            assert toten == approx(outcar.final_energy, abs=1e-6)
1✔
830

831
    def test_stopped_old(self):
1✔
832
        filepath = self.TEST_FILES_DIR / "OUTCAR.stopped"
1✔
833
        outcar = Outcar(filepath)
1✔
834
        assert outcar.is_stopped
1✔
835
        for f in ["OUTCAR.lepsilon_old_born", "OUTCAR.lepsilon_old_born.gz"]:
1✔
836
            filepath = self.TEST_FILES_DIR / f
1✔
837
            outcar = Outcar(filepath)
1✔
838

839
            assert outcar.lepsilon
1✔
840
            assert outcar.dielectric_tensor[0][0] == approx(3.716432)
1✔
841
            assert outcar.dielectric_tensor[0][1] == approx(-0.20464)
1✔
842
            assert outcar.dielectric_tensor[1][2] == approx(-0.20464)
1✔
843
            assert outcar.dielectric_ionic_tensor[0][0] == approx(0.001419)
1✔
844
            assert outcar.dielectric_ionic_tensor[0][2] == approx(0.001419)
1✔
845
            assert outcar.dielectric_ionic_tensor[2][2] == approx(0.001419)
1✔
846
            assert outcar.piezo_tensor[0][0] == approx(0.52799)
1✔
847
            assert outcar.piezo_tensor[1][3] == approx(0.35998)
1✔
848
            assert outcar.piezo_tensor[2][5] == approx(0.35997)
1✔
849
            assert outcar.piezo_ionic_tensor[0][0] == approx(0.05868)
1✔
850
            assert outcar.piezo_ionic_tensor[1][3] == approx(0.06241)
1✔
851
            assert outcar.piezo_ionic_tensor[2][5] == approx(0.06242)
1✔
852
            assert outcar.born[0][1][2] == approx(-0.385)
1✔
853
            assert outcar.born[1][2][0] == approx(0.36465)
1✔
854
            assert outcar.internal_strain_tensor[0][0][0] == approx(-572.5437, abs=1e-4)
1✔
855
            assert outcar.internal_strain_tensor[0][1][0] == approx(683.2985, abs=1e-4)
1✔
856
            assert outcar.internal_strain_tensor[0][1][3] == approx(73.07059, abs=1e-4)
1✔
857
            assert outcar.internal_strain_tensor[1][0][0] == approx(570.98927, abs=1e-4)
1✔
858
            assert outcar.internal_strain_tensor[1][1][0] == approx(-683.68519, abs=1e-4)
1✔
859
            assert outcar.internal_strain_tensor[1][2][2] == approx(570.98927, abs=1e-4)
1✔
860

861
    def test_stopped(self):
1✔
862
        filepath = self.TEST_FILES_DIR / "OUTCAR.stopped"
1✔
863
        outcar = Outcar(filepath)
1✔
864
        assert outcar.is_stopped
1✔
865
        for f in ["OUTCAR.lepsilon", "OUTCAR.lepsilon.gz"]:
1✔
866
            filepath = self.TEST_FILES_DIR / f
1✔
867
            outcar = Outcar(filepath)
1✔
868

869
            assert outcar.lepsilon
1✔
870
            assert outcar.dielectric_tensor[0][0] == approx(3.716432)
1✔
871
            assert outcar.dielectric_tensor[0][1] == approx(-0.20464)
1✔
872
            assert outcar.dielectric_tensor[1][2] == approx(-0.20464)
1✔
873
            assert outcar.dielectric_ionic_tensor[0][0] == approx(0.001419)
1✔
874
            assert outcar.dielectric_ionic_tensor[0][2] == approx(0.001419)
1✔
875
            assert outcar.dielectric_ionic_tensor[2][2] == approx(0.001419)
1✔
876
            assert outcar.piezo_tensor[0][0] == approx(0.52799)
1✔
877
            assert outcar.piezo_tensor[1][3] == approx(0.35998)
1✔
878
            assert outcar.piezo_tensor[2][5] == approx(0.35997)
1✔
879
            assert outcar.piezo_ionic_tensor[0][0] == approx(0.05868)
1✔
880
            assert outcar.piezo_ionic_tensor[1][3] == approx(0.06241)
1✔
881
            assert outcar.piezo_ionic_tensor[2][5] == approx(0.06242)
1✔
882
            assert outcar.born[0][1][2] == approx(-0.385)
1✔
883
            assert outcar.born[1][2][0] == approx(0.36465)
1✔
884
            assert outcar.internal_strain_tensor[0][0][0] == approx(-572.5437, abs=1e-4)
1✔
885
            assert outcar.internal_strain_tensor[0][1][0] == approx(683.2985, abs=1e-4)
1✔
886
            assert outcar.internal_strain_tensor[0][1][3] == approx(73.07059, abs=1e-4)
1✔
887
            assert outcar.internal_strain_tensor[1][0][0] == approx(570.98927, abs=1e-4)
1✔
888
            assert outcar.internal_strain_tensor[1][1][0] == approx(-683.68519, abs=1e-4)
1✔
889
            assert outcar.internal_strain_tensor[1][2][2] == approx(570.98927, abs=1e-4)
1✔
890

891
    def test_soc(self):
1✔
892
        filepath = self.TEST_FILES_DIR / "OUTCAR.NiO_SOC.gz"
1✔
893
        outcar = Outcar(filepath)
1✔
894
        expected_mag = (
1✔
895
            {
896
                "s": Magmom([0.0, 0.0, -0.001]),
897
                "p": Magmom([0.0, 0.0, -0.003]),
898
                "d": Magmom([0.0, 0.0, 1.674]),
899
                "tot": Magmom([0.0, 0.0, 1.671]),
900
            },
901
            {
902
                "s": Magmom([0.0, 0.0, 0.001]),
903
                "p": Magmom([0.0, 0.0, 0.003]),
904
                "d": Magmom([0.0, 0.0, -1.674]),
905
                "tot": Magmom([0.0, 0.0, -1.671]),
906
            },
907
            {
908
                "s": Magmom([0.0, 0.0, 0.0]),
909
                "p": Magmom([0.0, 0.0, 0.0]),
910
                "d": Magmom([0.0, 0.0, 0.0]),
911
                "tot": Magmom([0.0, 0.0, 0.0]),
912
            },
913
            {
914
                "s": Magmom([0.0, 0.0, 0.0]),
915
                "p": Magmom([0.0, 0.0, 0.0]),
916
                "d": Magmom([0.0, 0.0, 0.0]),
917
                "tot": Magmom([0.0, 0.0, 0.0]),
918
            },
919
        )
920
        # test note: Magmom class uses np.allclose() when testing for equality
921
        # so fine to use assertEqual here
922
        assert outcar.magnetization == expected_mag, "Wrong vector magnetization read from Outcar for SOC calculation"
1✔
923

924
    def test_polarization(self):
1✔
925
        filepath = self.TEST_FILES_DIR / "OUTCAR.BaTiO3.polar"
1✔
926
        outcar = Outcar(filepath)
1✔
927
        assert outcar.spin is True
1✔
928
        assert outcar.noncollinear is False
1✔
929
        assert outcar.p_ion[0] == approx(0.0)
1✔
930
        assert outcar.p_ion[1] == approx(0.0)
1✔
931
        assert outcar.p_ion[2] == approx(-5.56684)
1✔
932
        assert outcar.p_sp1[0] == approx(2.00068)
1✔
933
        assert outcar.p_sp2[0] == approx(-2.00044)
1✔
934
        assert outcar.p_elec[0] == approx(0.00024)
1✔
935
        assert outcar.p_elec[1] == approx(0.00019)
1✔
936
        assert outcar.p_elec[2] == approx(3.61674)
1✔
937

938
    def test_pseudo_zval(self):
1✔
939
        filepath = self.TEST_FILES_DIR / "OUTCAR.BaTiO3.polar"
1✔
940
        outcar = Outcar(filepath)
1✔
941
        assert {"Ba": 10.00, "Ti": 10.00, "O": 6.00} == outcar.zval_dict
1✔
942

943
        filepath = self.TEST_FILES_DIR / "OUTCAR.LaSnNO2.polar"
1✔
944
        outcar = Outcar(filepath)
1✔
945
        assert {"La": 11.0, "N": 5.0, "O": 6.0, "Sn": 14.0} == outcar.zval_dict
1✔
946

947
    def test_dielectric(self):
1✔
948
        filepath = self.TEST_FILES_DIR / "OUTCAR.dielectric"
1✔
949
        outcar = Outcar(filepath)
1✔
950
        outcar.read_corrections()
1✔
951
        assert outcar.data["dipol_quadrupol_correction"] == approx(0.03565)
1✔
952
        assert outcar.final_energy == approx(-797.46294064)
1✔
953

954
    def test_freq_dielectric(self):
1✔
955
        filepath = self.TEST_FILES_DIR / "OUTCAR.LOPTICS"
1✔
956
        outcar = Outcar(filepath)
1✔
957
        outcar.read_freq_dielectric()
1✔
958
        assert outcar.dielectric_energies[0] == approx(0)
1✔
959
        assert outcar.dielectric_energies[-1] == approx(39.826101)
1✔
960
        assert outcar.dielectric_tensor_function[0][0, 0] == approx(8.96938800)
1✔
961
        assert outcar.dielectric_tensor_function[-1][0, 0] == approx(7.36167000e-01 + 1.53800000e-03j)
1✔
962
        assert len(outcar.dielectric_energies) == len(outcar.dielectric_tensor_function)
1✔
963
        np.testing.assert_array_equal(
1✔
964
            outcar.dielectric_tensor_function[0],
965
            outcar.dielectric_tensor_function[0].transpose(),
966
        )
967

968
        plasma_freq = outcar.plasma_frequencies
1✔
969
        self.assertArrayAlmostEqual(plasma_freq["intraband"], np.zeros((3, 3)))
1✔
970
        self.assertArrayAlmostEqual(
1✔
971
            plasma_freq["interband"],
972
            [
973
                [367.49, 63.939, 11.976],
974
                [63.939, 381.155, -24.461],
975
                [11.976, -24.461, 297.844],
976
            ],
977
        )
978

979
    def test_freq_dielectric_vasp544(self):
1✔
980
        filepath = self.TEST_FILES_DIR / "OUTCAR.LOPTICS.vasp544"
1✔
981
        outcar = Outcar(filepath)
1✔
982
        outcar.read_freq_dielectric()
1✔
983
        assert outcar.dielectric_energies[0] == approx(0)
1✔
984
        assert outcar.dielectric_energies[-1] == approx(39.63964)
1✔
985
        assert outcar.dielectric_tensor_function[0][0, 0] == approx(12.769435 + 0j)
1✔
986
        assert outcar.dielectric_tensor_function[-1][0, 0] == approx(0.828615 + 0.016594j)
1✔
987
        assert len(outcar.dielectric_energies) == len(outcar.dielectric_tensor_function)
1✔
988
        np.testing.assert_array_equal(
1✔
989
            outcar.dielectric_tensor_function[0],
990
            outcar.dielectric_tensor_function[0].transpose(),
991
        )
992

993
    def test_parse_sci_notation(self):
1✔
994
        invalid_pattern = "23535.35 35235.34 325325.3"
1✔
995
        valid_pattern1 = " 0.00000E+00 0.00000E+00 0.00000E+00 0.00000E+00 0.00000E+00 0.00000E+00 0.00000E+00"
1✔
996
        valid_pattern2 = " 0.62963E+00 0.15467E+02 0.15467E+02 0.15467E+02-0.30654E-16-0.91612E-16 0.52388E-16"
1✔
997

998
        assert Outcar._parse_sci_notation(invalid_pattern) == []
1✔
999
        assert Outcar._parse_sci_notation(valid_pattern1) == [0, 0, 0, 0, 0, 0, 0]
1✔
1000
        assert Outcar._parse_sci_notation(valid_pattern2) == [
1✔
1001
            0.62963,
1002
            0.15467e02,
1003
            0.15467e02,
1004
            0.15467e02,
1005
            -0.30654e-16,
1006
            -0.91612e-16,
1007
            0.52388e-16,
1008
        ]
1009

1010
    def test_read_elastic_tensor(self):
1✔
1011
        filepath = self.TEST_FILES_DIR / "OUTCAR.total_tensor.Li2O.gz"
1✔
1012
        outcar = Outcar(filepath)
1✔
1013

1014
        outcar.read_elastic_tensor()
1✔
1015

1016
        assert outcar.data["elastic_tensor"][0][0] == approx(1986.3391)
1✔
1017
        assert outcar.data["elastic_tensor"][0][1] == approx(187.8324)
1✔
1018
        assert outcar.data["elastic_tensor"][3][3] == approx(586.3034)
1✔
1019

1020
    def test_read_lcalcpol(self):
1✔
1021
        # outcar with electrons Angst units
1022
        folder = "BTO_221_99_polarization/interpolation_6_polarization/"
1✔
1023
        filepath = self.TEST_FILES_DIR / folder / "OUTCAR"
1✔
1024
        outcar = Outcar(filepath)
1✔
1025

1026
        outcar.read_lcalcpol()
1✔
1027

1028
        p_ion = [0.0, 0.0, 19.70306]
1✔
1029
        p_elec = [4.02264, 4.02263, -4.08851]
1✔
1030
        p_sp1 = [2.01124, 2.01124, -2.04426]
1✔
1031
        p_sp2 = [2.01139, 2.01139, -2.04426]
1✔
1032

1033
        for i in range(3):
1✔
1034
            assert outcar.p_ion[i] == approx(p_ion[i])
1✔
1035
            assert outcar.p_elec[i] == approx(p_elec[i])
1✔
1036
            assert outcar.p_sp1[i] == approx(p_sp1[i])
1✔
1037
            assert outcar.p_sp2[i] == approx(p_sp2[i])
1✔
1038

1039
        # outcar with |e| Angst units
1040
        filepath = self.TEST_FILES_DIR / "outcar_vasp_6.3.gz"
1✔
1041
        outcar = Outcar(filepath)
1✔
1042

1043
        outcar.read_lcalcpol()
1✔
1044

1045
        p_ion = [-79.03374, -0.0, -28.44354]
1✔
1046
        p_elec = [9.01127e00, -1.00000e-05, 3.24308e00]
1✔
1047
        p_sp1 = [4.50564, 0.0, 1.62154]
1✔
1048
        p_sp2 = [4.50563e00, -1.00000e-05, 1.62154e00]
1✔
1049

1050
        for i in range(3):
1✔
1051
            assert outcar.p_ion[i] == approx(p_ion[i])
1✔
1052
            assert outcar.p_elec[i] == approx(p_elec[i])
1✔
1053
            assert outcar.p_sp1[i] == approx(p_sp1[i])
1✔
1054
            assert outcar.p_sp2[i] == approx(p_sp2[i])
1✔
1055

1056
    def test_read_piezo_tensor(self):
1✔
1057
        filepath = self.TEST_FILES_DIR / "OUTCAR.lepsilon.gz"
1✔
1058
        outcar = Outcar(filepath)
1✔
1059

1060
        outcar.read_piezo_tensor()
1✔
1061
        assert outcar.data["piezo_tensor"][0][0] == approx(0.52799)
1✔
1062
        assert outcar.data["piezo_tensor"][1][3] == approx(0.35998)
1✔
1063
        assert outcar.data["piezo_tensor"][2][5] == approx(0.35997)
1✔
1064

1065
    def test_core_state_eigen(self):
1✔
1066
        filepath = self.TEST_FILES_DIR / "OUTCAR.CL"
1✔
1067
        cl = Outcar(filepath).read_core_state_eigen()
1✔
1068
        assert cl[6]["2s"][-1] == approx(-174.4779)
1✔
1069
        filepath = self.TEST_FILES_DIR / "OUTCAR.icorelevel"
1✔
1070
        outcar = Outcar(filepath)
1✔
1071
        cl = outcar.read_core_state_eigen()
1✔
1072
        assert cl[4]["3d"][-1] == approx(-31.4522)
1✔
1073

1074
        # test serialization
1075
        outcar.as_dict()
1✔
1076

1077
    def test_avg_core_poten(self):
1✔
1078
        filepath = self.TEST_FILES_DIR / "OUTCAR.lepsilon"
1✔
1079
        cp = Outcar(filepath).read_avg_core_poten()
1✔
1080
        assert cp[-1][1] == approx(-90.0487)
1✔
1081

1082
        filepath = self.TEST_FILES_DIR / "OUTCAR"
1✔
1083
        cp = Outcar(filepath).read_avg_core_poten()
1✔
1084
        assert cp[0][6] == approx(-73.1068)
1✔
1085

1086
        filepath = self.TEST_FILES_DIR / "OUTCAR.bad_core_poten.gz"
1✔
1087
        cp = Outcar(filepath).read_avg_core_poten()
1✔
1088
        assert cp[0][1] == approx(-101.5055)
1✔
1089

1090
    def test_single_atom(self):
1✔
1091
        filepath = self.TEST_FILES_DIR / "OUTCAR.Al"
1✔
1092
        outcar = Outcar(filepath)
1✔
1093
        expected_mag = ({"p": 0.0, "s": 0.0, "d": 0.0, "tot": 0.0},)
1✔
1094
        expected_chg = ({"p": 0.343, "s": 0.425, "d": 0.0, "tot": 0.768},)
1✔
1095

1096
        assert outcar.magnetization == approx(expected_mag)
1✔
1097
        assert outcar.charge == approx(expected_chg)
1✔
1098
        assert not outcar.is_stopped
1✔
1099
        assert outcar.run_stats == {
1✔
1100
            "System time (sec)": 0.592,
1101
            "Total CPU time used (sec)": 50.194,
1102
            "Elapsed time (sec)": 52.337,
1103
            "Maximum memory used (kb)": 62900.0,
1104
            "Average memory used (kb)": 0.0,
1105
            "User time (sec)": 49.602,
1106
            "cores": 32,
1107
        }
1108
        assert outcar.efermi == approx(8.0942)
1✔
1109
        assert outcar.nelect == approx(3)
1✔
1110
        assert outcar.total_mag == approx(8.2e-06)
1✔
1111

1112
        assert outcar.as_dict() is not None
1✔
1113

1114
    def test_chemical_shielding(self):
1✔
1115
        filename = self.TEST_FILES_DIR / "nmr" / "cs" / "core.diff" / "hydromagnesite" / "OUTCAR"
1✔
1116
        outcar = Outcar(filename)
1✔
1117
        expected_chemical_shielding = [
1✔
1118
            [191.9974, 69.5232, 0.6342],
1119
            [195.0808, 68.183, 0.833],
1120
            [192.0389, 69.5762, 0.6329],
1121
            [195.0844, 68.1756, 0.8336],
1122
            [192.005, 69.5289, 0.6339],
1123
            [195.0913, 68.1859, 0.833],
1124
            [192.0237, 69.565, 0.6333],
1125
            [195.0788, 68.1733, 0.8337],
1126
        ]
1127

1128
        assert len(outcar.data["chemical_shielding"]["valence_only"][20:28]) == approx(len(expected_chemical_shielding))
1✔
1129

1130
        self.assertArrayAlmostEqual(
1✔
1131
            outcar.data["chemical_shielding"]["valence_and_core"][20:28],
1132
            expected_chemical_shielding,
1133
            decimal=5,
1134
        )
1135

1136
    def test_chemical_shielding_with_different_core_contribution(self):
1✔
1137
        filename = self.TEST_FILES_DIR / "nmr" / "cs" / "core.diff" / "core.diff.chemical.shifts.OUTCAR"
1✔
1138
        outcar = Outcar(filename)
1✔
1139
        c_vo = outcar.data["chemical_shielding"]["valence_only"][7]
1✔
1140
        for x1, x2 in zip(list(c_vo), [198.7009, 73.7484, 1.0000]):
1✔
1141
            assert x1 == approx(x2)
1✔
1142
        c_vc = outcar.data["chemical_shielding"]["valence_and_core"][7]
1✔
1143
        for x1, x2 in zip(list(c_vc), [-1.9406, 73.7484, 1.0000]):
1✔
1144
            assert x1 == approx(x2)
1✔
1145

1146
    def test_cs_raw_tensors(self):
1✔
1147
        filename = self.TEST_FILES_DIR / "nmr" / "cs" / "core.diff" / "core.diff.chemical.shifts.OUTCAR"
1✔
1148
        outcar = Outcar(filename)
1✔
1149
        unsym_tensors = outcar.data["unsym_cs_tensor"]
1✔
1150
        assert unsym_tensors[0] == [
1✔
1151
            [-145.814605, -4.263425, 0.000301],
1152
            [4.263434, -145.812238, -8.7e-05],
1153
            [0.000136, -0.000189, -142.794068],
1154
        ]
1155
        assert unsym_tensors[29] == [
1✔
1156
            [287.789318, -53.799325, 30.900024],
1157
            [-53.799571, 225.668117, -17.839598],
1158
            [3.801103, -2.195218, 88.896756],
1159
        ]
1160

1161
    def test_cs_g0_contribution(self):
1✔
1162
        filename = self.TEST_FILES_DIR / "nmr" / "cs" / "core.diff" / "core.diff.chemical.shifts.OUTCAR"
1✔
1163
        outcar = Outcar(filename)
1✔
1164
        g0_contrib = outcar.data["cs_g0_contribution"]
1✔
1165
        assert g0_contrib == [
1✔
1166
            [-8.773535, 9e-06, 1e-06],
1167
            [1.7e-05, -8.773536, -0.0792],
1168
            [-6e-06, -0.008328, -9.320237],
1169
        ]
1170

1171
    def test_cs_core_contribution(self):
1✔
1172
        filename = self.TEST_FILES_DIR / "nmr" / "cs" / "core.diff" / "core.diff.chemical.shifts.OUTCAR"
1✔
1173
        outcar = Outcar(filename)
1✔
1174
        core_contrib = outcar.data["cs_core_contribution"]
1✔
1175
        assert core_contrib == {"Mg": -412.8248405, "C": -200.5098812, "O": -271.0766979}
1✔
1176

1177
    def test_nmr_efg(self):
1✔
1178
        filename = self.TEST_FILES_DIR / "nmr" / "efg" / "AlPO4" / "OUTCAR"
1✔
1179
        outcar = Outcar(filename)
1✔
1180
        expected_efg = [
1✔
1181
            {"eta": 0.465, "nuclear_quadrupole_moment": 146.6, "cq": -5.573},
1182
            {"eta": 0.465, "nuclear_quadrupole_moment": 146.6, "cq": -5.573},
1183
            {"eta": 0.137, "nuclear_quadrupole_moment": 146.6, "cq": 6.327},
1184
            {"eta": 0.137, "nuclear_quadrupole_moment": 146.6, "cq": 6.327},
1185
            {"eta": 0.112, "nuclear_quadrupole_moment": 146.6, "cq": -7.453},
1186
            {"eta": 0.112, "nuclear_quadrupole_moment": 146.6, "cq": -7.453},
1187
            {"eta": 0.42, "nuclear_quadrupole_moment": 146.6, "cq": -5.58},
1188
            {"eta": 0.42, "nuclear_quadrupole_moment": 146.6, "cq": -5.58},
1189
        ]
1190
        assert len(outcar.data["efg"][2:10]) == len(expected_efg)
1✔
1191
        for e1, e2 in zip(outcar.data["efg"][2:10], expected_efg):
1✔
1192
            for k in e1:
1✔
1193
                assert e1[k] == approx(e2[k], abs=1e-5)
1✔
1194

1195
        exepected_tensors = [
1✔
1196
            [[11.11, 1.371, 2.652], [1.371, 3.635, -3.572], [2.652, -3.572, -14.746]],
1197
            [[11.11, -1.371, 2.652], [-1.371, 3.635, 3.572], [2.652, 3.572, -14.746]],
1198
            [[-3.098, 6.511, 7.732], [6.511, 1.419, 11.445], [7.732, 11.445, 1.678]],
1199
            [
1200
                [-3.098, -6.511, 7.732],
1201
                [-6.511, 1.419, -11.445],
1202
                [7.732, -11.445, 1.678],
1203
            ],
1204
            [
1205
                [2.344, -10.775, -7.006],
1206
                [-10.775, -7.152, -11.309],
1207
                [-7.006, -11.309, 4.808],
1208
            ],
1209
            [
1210
                [2.344, 10.775, -7.006],
1211
                [10.775, -7.152, 11.309],
1212
                [-7.006, 11.309, 4.808],
1213
            ],
1214
            [[2.404, -0.588, -6.83], [-0.588, 10.435, 3.159], [-6.83, 3.159, -12.839]],
1215
            [[2.404, 0.588, -6.83], [0.588, 10.435, -3.159], [-6.83, -3.159, -12.839]],
1216
        ]
1217

1218
        assert len(outcar.data["unsym_efg_tensor"][2:10]) == len(exepected_tensors)
1✔
1219
        for e1, e2 in zip(outcar.data["unsym_efg_tensor"][2:10], exepected_tensors):
1✔
1220
            self.assertArrayAlmostEqual(e1, e2)
1✔
1221

1222
    def test_read_fermi_contact_shift(self):
1✔
1223
        filepath = self.TEST_FILES_DIR / "OUTCAR_fc"
1✔
1224
        outcar = Outcar(filepath)
1✔
1225
        outcar.read_fermi_contact_shift()
1✔
1226
        assert outcar.data["fermi_contact_shift"]["fch"][0][0] == approx(-0.002)
1✔
1227
        assert outcar.data["fermi_contact_shift"]["th"][0][0] == approx(-0.052)
1✔
1228
        assert outcar.data["fermi_contact_shift"]["dh"][0][0] == approx(0.0)
1✔
1229

1230
    def test_drift(self):
1✔
1231
        outcar = Outcar(self.TEST_FILES_DIR / "OUTCAR")
1✔
1232
        assert len(outcar.drift) == 5
1✔
1233
        assert np.sum(outcar.drift) == approx(0)
1✔
1234

1235
        outcar = Outcar(self.TEST_FILES_DIR / "OUTCAR.CL")
1✔
1236
        assert len(outcar.drift) == 79
1✔
1237
        assert np.sum(outcar.drift) == approx(0.448010)
1✔
1238

1239
    def test_electrostatic_potential(self):
1✔
1240
        outcar = Outcar(self.TEST_FILES_DIR / "OUTCAR")
1✔
1241
        assert outcar.ngf == [54, 30, 54]
1✔
1242
        assert np.allclose(outcar.sampling_radii, [0.9748, 0.9791, 0.7215])
1✔
1243
        assert np.allclose(
1✔
1244
            outcar.electrostatic_potential,
1245
            [-26.0704, -45.5046, -45.5046, -72.9539, -73.0621, -72.9539, -73.0621],
1246
        )
1247

1248
    def test_mag_electrostatic_error(self):
1✔
1249
        outcar = Outcar(self.TEST_FILES_DIR / "OUTCAR.electrostaticerror.gz")
1✔
1250
        assert outcar.electrostatic_potential == [
1✔
1251
            -21.1667,
1252
            -19.6865,
1253
            -22.3983,
1254
            -22.3307,
1255
            -20.5213,
1256
            -20.9292,
1257
            -21.5063,
1258
            -21.3554,
1259
            -21.74,
1260
            -21.7018,
1261
            -20.3422,
1262
            -20.6128,
1263
            -21.4405,
1264
            -21.0022,
1265
            -21.975,
1266
            -21.915,
1267
            -21.0156,
1268
            -21.9027,
1269
            -22.3712,
1270
            -21.5816,
1271
            -21.8535,
1272
            -20.5061,
1273
            -22.2474,
1274
            -22.1904,
1275
            -22.2203,
1276
            -20.1727,
1277
            -21.1068,
1278
            -20.1669,
1279
            -22.1272,
1280
            -21.3446,
1281
            -82.4717,
1282
            -83.035,
1283
            -81.8289,
1284
            -82.5957,
1285
            -81.7813,
1286
            -82.5011,
1287
            -82.6098,
1288
            -82.2885,
1289
            -81.606,
1290
            -99.1621,
1291
            -99.3146,
1292
            -99.1742,
1293
            -99.4728,
1294
            -100.2139,
1295
            -99.852,
1296
            -99.3575,
1297
            -99.4135,
1298
            -98.9092,
1299
            -99.8867,
1300
            -99.3707,
1301
            -99.0794,
1302
            -98.8376,
1303
            -99.3656,
1304
            -98.6474,
1305
            -99.3264,
1306
            -98.844,
1307
            -99.074,
1308
            -98.9354,
1309
            -99.1643,
1310
            -99.2412,
1311
            -68.7667,
1312
            -68.2528,
1313
            -66.7326,
1314
            -67.7113,
1315
            -69.2228,
1316
            -67.014,
1317
            -69.1456,
1318
            -67.3151,
1319
            -68.2625,
1320
            -67.6156,
1321
            -69.8112,
1322
            -68.9266,
1323
            -67.8286,
1324
            -69.3289,
1325
            -68.7017,
1326
            -67.2834,
1327
            -68.4665,
1328
            -68.0188,
1329
            -67.7083,
1330
            -69.7195,
1331
            -67.4078,
1332
            -67.9646,
1333
            -68.584,
1334
            -69.2387,
1335
            -69.7822,
1336
            -67.0701,
1337
            -67.8236,
1338
            -68.2468,
1339
            -68.6533,
1340
            -68.3218,
1341
            -67.5923,
1342
            -69.1266,
1343
            -68.4615,
1344
            -68.302,
1345
            -67.999,
1346
            -68.6709,
1347
            -68.9973,
1348
            -67.4147,
1349
            -68.4463,
1350
            -68.0899,
1351
            -67.665,
1352
            -69.6705,
1353
            -68.6433,
1354
            -68.4288,
1355
            -66.9027,
1356
            -67.3211,
1357
            -68.604,
1358
            -69.1299,
1359
            -67.5565,
1360
            -69.0845,
1361
            -67.4289,
1362
            -66.6864,
1363
            -67.6484,
1364
            -67.9783,
1365
            -67.7661,
1366
            -66.9797,
1367
            -67.8007,
1368
            -68.3194,
1369
            -69.3671,
1370
            -67.2708,
1371
        ]
1372

1373
    def test_onsite_density_matrix(self):
1✔
1374
        outcar = Outcar(self.TEST_FILES_DIR / "OUTCAR.LinearResponseU.gz")
1✔
1375
        matrices = outcar.data["onsite_density_matrices"]
1✔
1376
        assert matrices[0][Spin.up][0][0] == 1.0227
1✔
1377
        assert len(matrices[0][Spin.up]) == 5
1✔
1378
        assert len(matrices[0][Spin.up][0]) == 5
1✔
1379
        assert "onsite_density_matrices" in outcar.as_dict()
1✔
1380
        outcar = Outcar(self.TEST_FILES_DIR / "OUTCAR_merged_numbers")
1✔
1381
        matrices = outcar.data["onsite_density_matrices"]
1✔
1382
        assert matrices[0][Spin.up][0][-1] == 0.0
1✔
1383
        assert len(matrices[0][Spin.up]) == 7
1✔
1384
        assert len(matrices[0][Spin.up][0]) == 7
1✔
1385
        assert "onsite_density_matrices" in outcar.as_dict()
1✔
1386
        outcar = Outcar(self.TEST_FILES_DIR / "OUTCAR_merged_numbers2")
1✔
1387
        assert "onsite_density_matrices" in outcar.as_dict()
1✔
1388

1389
    def test_nplwvs(self):
1✔
1390
        outcar = Outcar(self.TEST_FILES_DIR / "OUTCAR")
1✔
1391
        assert outcar.data["nplwv"] == [[34560]]
1✔
1392
        assert outcar.data["nplwvs_at_kpoints"] == [
1✔
1393
            # fmt: off
1394
            1719, 1714, 1722, 1728, 1722, 1726, 1722, 1720, 1717, 1724, 1715, 1724, 1726,
1395
            1724, 1728, 1715, 1722, 1715, 1726, 1730, 1730, 1715, 1716, 1729, 1727, 1723,
1396
            1721, 1712, 1723, 1719, 1717, 1717, 1724, 1719, 1719, 1727, 1726, 1730, 1719,
1397
            1720, 1718, 1717, 1722, 1719, 1709, 1714, 1724, 1726, 1718, 1713, 1720, 1713,
1398
            1711, 1713, 1715, 1717, 1728, 1726, 1712, 1722, 1714, 1713, 1717, 1714, 1714,
1399
            1717, 1712, 1710, 1721, 1722, 1724, 1720, 1726, 1719, 1722, 1714,
1400
            # fmt: on
1401
        ]
1402
        outcar = Outcar(self.TEST_FILES_DIR / "OUTCAR.CL")
1✔
1403
        assert outcar.data["nplwv"] == [[None]]
1✔
1404
        assert outcar.data["nplwvs_at_kpoints"] == [85687]
1✔
1405

1406
    def test_vasp620_format(self):
1✔
1407
        filepath = self.TEST_FILES_DIR / "OUTCAR.vasp.6.2.0"
1✔
1408
        outcar = Outcar(filepath)
1✔
1409
        assert outcar.run_stats["Average memory used (kb)"] is None
1✔
1410

1411
        filepath = self.TEST_FILES_DIR / "OUTCAR.vasp.6.2.1.mpi"
1✔
1412
        outcar = Outcar(filepath)
1✔
1413
        assert outcar.run_stats["cores"] == 64
1✔
1414

1415
    def test_energies(self):
1✔
1416
        # VASP 5.2.1
1417
        o = Outcar(self.TEST_FILES_DIR / "OUTCAR.etest1.gz")
1✔
1418
        assert o.final_energy == approx(-11.18981538)
1✔
1419
        assert o.final_energy_wo_entrp == approx(-11.13480014)
1✔
1420
        assert o.final_fr_energy == approx(-11.21732300)
1✔
1421

1422
        # VASP 6.2.1
1423
        o = Outcar(self.TEST_FILES_DIR / "OUTCAR.etest2.gz")
1✔
1424
        assert o.final_energy == approx(-11.18986774)
1✔
1425
        assert o.final_energy_wo_entrp == approx(-11.13485250)
1✔
1426
        assert o.final_fr_energy == approx(-11.21737536)
1✔
1427

1428
        # VASP 5.2.1
1429
        o = Outcar(self.TEST_FILES_DIR / "OUTCAR.etest3.gz")
1✔
1430
        assert o.final_energy == approx(-15.89355325)
1✔
1431
        assert o.final_energy_wo_entrp == approx(-15.83853800)
1✔
1432
        assert o.final_fr_energy == approx(-15.92106087)
1✔
1433

1434
        # VASP 6.2.1
1435
        o = Outcar(self.TEST_FILES_DIR / "OUTCAR.etest4.gz")
1✔
1436
        assert o.final_energy == approx(-15.89364691)
1✔
1437
        assert o.final_energy_wo_entrp == approx(-15.83863167)
1✔
1438
        assert o.final_fr_energy == approx(-15.92115453)
1✔
1439

1440
    def test_read_table_pattern(self):
1✔
1441
        outcar = Outcar(self.TEST_FILES_DIR / "OUTCAR")
1✔
1442

1443
        header_pattern = r"\(the norm of the test charge is\s+[\.\-\d]+\)"
1✔
1444
        table_pattern = r"((?:\s+\d+\s*[\.\-\d]+)+)"
1✔
1445
        footer_pattern = r"\s+E-fermi :"
1✔
1446

1447
        pots = outcar.read_table_pattern(header_pattern, table_pattern, footer_pattern, last_one_only=True)
1✔
1448
        ref_last = [
1✔
1449
            ["       1 -26.0704       2 -45.5046       3 -45.5046       4 -72.9539       5 -73.0621"],
1450
            ["       6 -72.9539       7 -73.0621"],
1451
        ]
1452
        assert pots == ref_last
1✔
1453

1454
        pots = outcar.read_table_pattern(
1✔
1455
            header_pattern, table_pattern, footer_pattern, last_one_only=False, first_one_only=True
1456
        )
1457
        ref_first = [
1✔
1458
            ["       1 -26.1149       2 -45.5359       3 -45.5359       4 -72.9831       5 -73.1068"],
1459
            ["       6 -72.9831       7 -73.1068"],
1460
        ]
1461
        assert pots == ref_first
1✔
1462

1463
        with pytest.raises(ValueError):
1✔
1464
            outcar.read_table_pattern(
1✔
1465
                header_pattern, table_pattern, footer_pattern, last_one_only=True, first_one_only=True
1466
            )
1467

1468

1469
class BSVasprunTest(PymatgenTest):
1✔
1470
    _multiprocess_shared_ = True
1✔
1471

1472
    def test_get_band_structure(self):
1✔
1473
        filepath = self.TEST_FILES_DIR / "vasprun_Si_bands.xml"
1✔
1474
        vasprun = BSVasprun(filepath, parse_potcar_file=False)
1✔
1475
        bs = vasprun.get_band_structure(kpoints_filename=self.TEST_FILES_DIR / "KPOINTS_Si_bands")
1✔
1476
        cbm = bs.get_cbm()
1✔
1477
        vbm = bs.get_vbm()
1✔
1478
        assert cbm["kpoint_index"] == [13], "wrong cbm kpoint index"
1✔
1479
        assert cbm["energy"] == approx(6.2301), "wrong cbm energy"
1✔
1480
        assert cbm["band_index"] == {Spin.up: [4], Spin.down: [4]}, "wrong cbm bands"
1✔
1481
        assert vbm["kpoint_index"] == [0, 63, 64]
1✔
1482
        assert vbm["energy"] == approx(5.6158), "wrong vbm energy"
1✔
1483
        assert vbm["band_index"] == {Spin.up: [1, 2, 3], Spin.down: [1, 2, 3]}, "wrong vbm bands"
1✔
1484
        assert vbm["kpoint"].label == "\\Gamma", "wrong vbm label"
1✔
1485
        assert cbm["kpoint"].label is None, "wrong cbm label"
1✔
1486
        d = vasprun.as_dict()
1✔
1487
        assert "eigenvalues" in d["output"]
1✔
1488

1489

1490
class OszicarTest(PymatgenTest):
1✔
1491
    def test_init(self):
1✔
1492
        filepath = self.TEST_FILES_DIR / "OSZICAR"
1✔
1493
        oszicar = Oszicar(filepath)
1✔
1494
        assert len(oszicar.electronic_steps) == len(oszicar.ionic_steps)
1✔
1495
        assert len(oszicar.all_energies) == 60
1✔
1496
        assert oszicar.final_energy == approx(-526.63928)
1✔
1497

1498

1499
class LocpotTest(PymatgenTest):
1✔
1500
    def test_init(self):
1✔
1501
        filepath = self.TEST_FILES_DIR / "LOCPOT"
1✔
1502
        locpot = Locpot.from_file(filepath)
1✔
1503
        assert -217.05226954 == approx(sum(locpot.get_average_along_axis(0)))
1✔
1504
        assert locpot.get_axis_grid(0)[-1] == approx(2.87629, abs=1e-2)
1✔
1505
        assert locpot.get_axis_grid(1)[-1] == approx(2.87629, abs=1e-2)
1✔
1506
        assert locpot.get_axis_grid(2)[-1] == approx(2.87629, abs=1e-2)
1✔
1507

1508

1509
class ChgcarTest(PymatgenTest):
1✔
1510
    @classmethod
1✔
1511
    def setUpClass(cls):
1✔
1512
        filepath = cls.TEST_FILES_DIR / "CHGCAR.nospin"
1✔
1513
        cls.chgcar_no_spin = Chgcar.from_file(filepath)
1✔
1514

1515
        filepath = cls.TEST_FILES_DIR / "CHGCAR.spin"
1✔
1516
        cls.chgcar_spin = Chgcar.from_file(filepath)
1✔
1517

1518
        filepath = cls.TEST_FILES_DIR / "CHGCAR.Fe3O4"
1✔
1519
        cls.chgcar_fe3o4 = Chgcar.from_file(filepath)
1✔
1520

1521
        filepath = cls.TEST_FILES_DIR / "CHGCAR.NiO_SOC.gz"
1✔
1522
        cls.chgcar_NiO_SOC = Chgcar.from_file(filepath)
1✔
1523

1524
    def test_init(self):
1✔
1525
        assert self.chgcar_no_spin.get_integrated_diff(0, 2)[0, 1] == approx(0)
1✔
1526
        assert self.chgcar_spin.get_integrated_diff(0, 1)[0, 1] == approx(-0.0043896932237534022)
1✔
1527
        # test sum
1528
        chgcar = self.chgcar_spin + self.chgcar_spin
1✔
1529
        assert chgcar.get_integrated_diff(0, 1)[0, 1] == approx(-0.0043896932237534022 * 2)
1✔
1530

1531
        chgcar = self.chgcar_spin - self.chgcar_spin
1✔
1532
        assert chgcar.get_integrated_diff(0, 1)[0, 1] == approx(0)
1✔
1533

1534
        ans = [1.56472768, 3.25985108, 3.49205728, 3.66275028, 3.8045896, 5.10813352]
1✔
1535
        myans = self.chgcar_fe3o4.get_integrated_diff(0, 3, 6)
1✔
1536
        assert np.allclose(myans[:, 1], ans)
1✔
1537

1538
    def test_write(self):
1✔
1539
        self.chgcar_spin.write_file("CHGCAR_pmg")
1✔
1540
        with open("CHGCAR_pmg") as f:
1✔
1541
            for i, line in enumerate(f):
1✔
1542
                if i == 22130:
1✔
1543
                    assert "augmentation occupancies   1  15\n" == line
1✔
1544
                if i == 44255:
1✔
1545
                    assert "augmentation occupancies   1  15\n" == line
1✔
1546
        os.remove("CHGCAR_pmg")
1✔
1547

1548
    def test_soc_chgcar(self):
1✔
1549
        assert set(self.chgcar_NiO_SOC.data) == {"total", "diff_x", "diff_y", "diff_z", "diff"}
1✔
1550
        assert self.chgcar_NiO_SOC.is_soc
1✔
1551
        assert self.chgcar_NiO_SOC.data["diff"].shape == self.chgcar_NiO_SOC.data["diff_y"].shape
1✔
1552

1553
        # check our construction of chg.data['diff'] makes sense
1554
        # this has been checked visually too and seems reasonable
1555
        assert abs(self.chgcar_NiO_SOC.data["diff"][0][0][0]) == np.linalg.norm(
1✔
1556
            [
1557
                self.chgcar_NiO_SOC.data["diff_x"][0][0][0],
1558
                self.chgcar_NiO_SOC.data["diff_y"][0][0][0],
1559
                self.chgcar_NiO_SOC.data["diff_z"][0][0][0],
1560
            ]
1561
        )
1562

1563
        # and that the net magnetization is about zero
1564
        # note: we get ~ 0.08 here, seems a little high compared to
1565
        # vasp output, but might be due to chgcar limitations?
1566
        assert self.chgcar_NiO_SOC.net_magnetization == approx(0.0, abs=1e-0)
1✔
1567

1568
        self.chgcar_NiO_SOC.write_file("CHGCAR_pmg_soc")
1✔
1569
        chg_from_file = Chgcar.from_file("CHGCAR_pmg_soc")
1✔
1570
        assert chg_from_file.is_soc
1✔
1571
        os.remove("CHGCAR_pmg_soc")
1✔
1572

1573
    @unittest.skipIf(h5py is None, "h5py required for HDF5 support.")
1✔
1574
    def test_hdf5(self):
1✔
1575
        chgcar = Chgcar.from_file(self.TEST_FILES_DIR / "CHGCAR.NiO_SOC.gz")
1✔
1576
        chgcar.to_hdf5("chgcar_test.hdf5")
1✔
1577
        import h5py
1✔
1578

1579
        with h5py.File("chgcar_test.hdf5", "r") as f:
1✔
1580
            self.assertArrayAlmostEqual(np.array(f["vdata"]["total"]), chgcar.data["total"])
1✔
1581
            self.assertArrayAlmostEqual(np.array(f["vdata"]["diff"]), chgcar.data["diff"])
1✔
1582
            self.assertArrayAlmostEqual(np.array(f["lattice"]), chgcar.structure.lattice.matrix)
1✔
1583
            self.assertArrayAlmostEqual(np.array(f["fcoords"]), chgcar.structure.frac_coords)
1✔
1584
            for z in f["Z"]:
1✔
1585
                assert z in [Element.Ni.Z, Element.O.Z]
1✔
1586

1587
            for sp in f["species"]:
1✔
1588
                assert sp in [b"Ni", b"O"]
1✔
1589

1590
        chgcar2 = Chgcar.from_hdf5("chgcar_test.hdf5")
1✔
1591
        self.assertArrayAlmostEqual(chgcar2.data["total"], chgcar.data["total"])
1✔
1592
        os.remove("chgcar_test.hdf5")
1✔
1593

1594
    def test_spin_data(self):
1✔
1595
        for v in self.chgcar_spin.spin_data.values():
1✔
1596
            assert v.shape == (48, 48, 48)
1✔
1597

1598
    def test_add(self):
1✔
1599
        chgcar_sum = self.chgcar_spin + self.chgcar_spin
1✔
1600
        self.assertArrayAlmostEqual(chgcar_sum.data["total"], self.chgcar_spin.data["total"] * 2)
1✔
1601
        chgcar_copy = self.chgcar_spin.copy()
1✔
1602
        chgcar_copy.structure = self.get_structure("Li2O")
1✔
1603
        with warnings.catch_warnings(record=True) as w:
1✔
1604
            # Cause all warnings to always be triggered.
1605
            warnings.simplefilter("always")
1✔
1606
            # Trigger a warning.
1607
            chgcar_sum = chgcar_copy + self.chgcar_spin
1✔
1608
            # Verify some things
1609
            assert len(w) == 1
1✔
1610
            assert "Structures are different. Make sure you know what you are doing..." in str(w[-1].message)
1✔
1611
        with pytest.raises(ValueError):
1✔
1612
            self.chgcar_spin + self.chgcar_fe3o4
1✔
1613
        with pytest.raises(ValueError):
1✔
1614
            self.chgcar_spin + self.chgcar_no_spin
1✔
1615

1616
    def test_as_dict_and_from_dict(self):
1✔
1617
        d = self.chgcar_NiO_SOC.as_dict()
1✔
1618
        chgcar_from_dict = Chgcar.from_dict(d)
1✔
1619
        self.assertArrayAlmostEqual(self.chgcar_NiO_SOC.data["total"], chgcar_from_dict.data["total"])
1✔
1620
        self.assertArrayAlmostEqual(
1✔
1621
            self.chgcar_NiO_SOC.structure.lattice.matrix,
1622
            chgcar_from_dict.structure.lattice.matrix,
1623
        )
1624

1625

1626
class ElfcarTest(PymatgenTest):
1✔
1627
    def test_init(self):
1✔
1628
        elfcar = Elfcar.from_file(self.TEST_FILES_DIR / "ELFCAR.gz")
1✔
1629
        assert 0.19076207645194002 == approx(np.mean(elfcar.data["total"]))
1✔
1630
        assert 0.19076046677910055 == approx(np.mean(elfcar.data["diff"]))
1✔
1631
        reconstituted = Elfcar.from_dict(elfcar.as_dict())
1✔
1632
        assert elfcar.data == reconstituted.data
1✔
1633
        assert elfcar.poscar.structure == reconstituted.poscar.structure
1✔
1634

1635
    def test_alpha(self):
1✔
1636
        elfcar = Elfcar.from_file(self.TEST_FILES_DIR / "ELFCAR.gz")
1✔
1637
        alpha = elfcar.get_alpha()
1✔
1638
        assert 2.936678808979031 == approx(np.median(alpha.data["total"]))
1✔
1639

1640
    def test_interpolation(self):
1✔
1641
        elfcar = Elfcar.from_file(self.TEST_FILES_DIR / "ELFCAR.gz")
1✔
1642
        assert 0.0918471 == approx(elfcar.value_at(0.4, 0.5, 0.6))
1✔
1643
        assert 100 == len(elfcar.linear_slice([0.0, 0.0, 0.0], [1.0, 1.0, 1.0]))
1✔
1644

1645

1646
class ProcarTest(PymatgenTest):
1✔
1647
    _multiprocess_shared_ = True
1✔
1648

1649
    def test_init(self):
1✔
1650
        filepath = self.TEST_FILES_DIR / "PROCAR.simple"
1✔
1651
        p = Procar(filepath)
1✔
1652
        assert p.get_occupation(0, "d")[Spin.up] == approx(0)
1✔
1653
        assert p.get_occupation(0, "s")[Spin.up] == approx(0.35381249999999997)
1✔
1654
        assert p.get_occupation(0, "p")[Spin.up] == approx(1.19540625)
1✔
1655
        with pytest.raises(ValueError):
1✔
1656
            p.get_occupation(1, "m")
1✔
1657
        assert p.nbands == 10
1✔
1658
        assert p.nkpoints == 10
1✔
1659
        assert p.nions == 3
1✔
1660
        lat = Lattice.cubic(3.0)
1✔
1661
        s = Structure(
1✔
1662
            lat,
1663
            ["Li", "Na", "K"],
1664
            [[0.0, 0.0, 0.0], [0.25, 0.25, 0.25], [0.75, 0.75, 0.75]],
1665
        )
1666
        d = p.get_projection_on_elements(s)
1✔
1667
        assert d[Spin.up][2][2] == approx({"Na": 0.042, "K": 0.646, "Li": 0.042})
1✔
1668
        filepath = self.TEST_FILES_DIR / "PROCAR"
1✔
1669
        p = Procar(filepath)
1✔
1670
        assert p.get_occupation(0, "dxy")[Spin.up] == approx(0.96214813853000025)
1✔
1671
        assert p.get_occupation(0, "dxy")[Spin.down] == approx(0.85796295426000124)
1✔
1672

1673
    def test_phase_factors(self):
1✔
1674
        filepath = self.TEST_FILES_DIR / "PROCAR.phase"
1✔
1675
        p = Procar(filepath)
1✔
1676
        assert p.phase_factors[Spin.up][0, 0, 0, 0] == approx(-0.746 + 0.099j)
1✔
1677
        assert p.phase_factors[Spin.down][0, 0, 0, 0] == approx(0.372 - 0.654j)
1✔
1678

1679
        # Two Li should have same phase factor.
1680
        assert p.phase_factors[Spin.up][0, 0, 0, 0] == approx(p.phase_factors[Spin.up][0, 0, 1, 0])
1✔
1681
        assert p.phase_factors[Spin.up][0, 0, 2, 0] == approx(-0.053 + 0.007j)
1✔
1682
        assert p.phase_factors[Spin.down][0, 0, 2, 0] == approx(0.027 - 0.047j)
1✔
1683

1684
        # new style phase factors (VASP 5.4.4+)
1685
        filepath = self.TEST_FILES_DIR / "PROCAR.new_format_5.4.4"
1✔
1686
        p = Procar(filepath)
1✔
1687
        assert p.phase_factors[Spin.up][0, 0, 0, 0] == approx(-0.13 + 0.199j)
1✔
1688

1689

1690
class XdatcarTest(PymatgenTest):
1✔
1691
    def test_init(self):
1✔
1692
        filepath = self.TEST_FILES_DIR / "XDATCAR_4"
1✔
1693
        x = Xdatcar(filepath)
1✔
1694
        structures = x.structures
1✔
1695
        assert len(structures) == 4
1✔
1696
        for s in structures:
1✔
1697
            assert s.formula == "Li2 O1"
1✔
1698

1699
        filepath = self.TEST_FILES_DIR / "XDATCAR_5"
1✔
1700
        x = Xdatcar(filepath)
1✔
1701
        structures = x.structures
1✔
1702
        assert len(structures) == 4
1✔
1703
        for s in structures:
1✔
1704
            assert s.formula == "Li2 O1"
1✔
1705

1706
        x.concatenate(self.TEST_FILES_DIR / "XDATCAR_4")
1✔
1707
        assert len(x.structures) == 8
1✔
1708
        assert x.get_string() is not None
1✔
1709

1710
        filepath = self.TEST_FILES_DIR / "XDATCAR_6"
1✔
1711
        x = Xdatcar(filepath)
1✔
1712
        structures = x.structures
1✔
1713

1714
        assert structures[0].lattice != structures[-1].lattice
1✔
1715

1716

1717
class DynmatTest(PymatgenTest):
1✔
1718
    def test_init(self):
1✔
1719
        # nosetests pymatgen/io/vasp/tests/test_outputs.py:DynmatTest.test_init
1720
        filepath = self.TEST_FILES_DIR / "DYNMAT"
1✔
1721
        d = Dynmat(filepath)
1✔
1722
        assert d.nspecs == 2
1✔
1723
        assert d.natoms == 6
1✔
1724
        assert d.ndisps == 3
1✔
1725
        assert np.allclose(d.masses, [63.546, 196.966])
1✔
1726
        assert 4 in d.data
1✔
1727
        assert 2 in d.data[4]
1✔
1728
        assert np.allclose(d.data[4][2]["dispvec"], [0.0, 0.05, 0.0])
1✔
1729
        assert np.allclose(d.data[4][2]["dynmat"][3], [0.055046, -0.298080, 0.0])
1✔
1730
        # TODO: test get_phonon_frequencies once cross-checked
1731

1732

1733
class WavecarTest(PymatgenTest):
1✔
1734
    _multiprocess_shared_ = True
1✔
1735

1736
    def setUp(self):
1✔
1737
        a = np.array([[10.0, 0.0, 0.0], [0.0, 10.0, 0.0], [0.0, 0.0, 10.0]])
1✔
1738
        self.vol = np.dot(a[0, :], np.cross(a[1, :], a[2, :]))
1✔
1739
        b = np.array(
1✔
1740
            [
1741
                np.cross(a[1, :], a[2, :]),
1742
                np.cross(a[2, :], a[0, :]),
1743
                np.cross(a[0, :], a[1, :]),
1744
            ]
1745
        )
1746
        self.b = 2 * np.pi * b / self.vol
1✔
1747
        self.a = a
1✔
1748
        self.w = Wavecar(self.TEST_FILES_DIR / "WAVECAR.N2")
1✔
1749
        self.wH2 = Wavecar(self.TEST_FILES_DIR / "WAVECAR.H2_low_symm")
1✔
1750
        self.wH2_gamma = Wavecar(self.TEST_FILES_DIR / "WAVECAR.H2_low_symm.gamma")
1✔
1751
        self.w_ncl = Wavecar(self.TEST_FILES_DIR / "WAVECAR.H2.ncl")
1✔
1752
        self.w_frac_encut = Wavecar(self.TEST_FILES_DIR / "WAVECAR.frac_encut")
1✔
1753

1754
    def test_standard(self):
1✔
1755
        w = self.w
1✔
1756
        a = np.array([[10.0, 0.0, 0.0], [0.0, 10.0, 0.0], [0.0, 0.0, 10.0]])
1✔
1757
        vol = np.dot(a[0, :], np.cross(a[1, :], a[2, :]))
1✔
1758
        b = np.array(
1✔
1759
            [
1760
                np.cross(a[1, :], a[2, :]),
1761
                np.cross(a[2, :], a[0, :]),
1762
                np.cross(a[0, :], a[1, :]),
1763
            ]
1764
        )
1765
        b = 2 * np.pi * b / vol
1✔
1766

1767
        assert w.filename == self.TEST_FILES_DIR / "WAVECAR.N2"
1✔
1768
        assert w.efermi == approx(-5.7232, abs=1e-4)
1✔
1769
        assert w.encut == 25.0
1✔
1770
        assert w.nb == 9
1✔
1771
        assert w.nk == 1
1✔
1772
        assert np.allclose(w.a, a)
1✔
1773
        assert np.allclose(w.b, b)
1✔
1774
        assert w.vol == approx(vol)
1✔
1775
        assert len(w.kpoints) == w.nk
1✔
1776
        assert len(w.coeffs) == w.nk
1✔
1777
        assert len(w.coeffs[0]) == w.nb
1✔
1778
        assert len(w.band_energy) == w.nk
1✔
1779
        assert w.band_energy[0].shape == (w.nb, 3)
1✔
1780
        assert len(w.Gpoints[0]) <= 257
1✔
1781
        for k in range(w.nk):
1✔
1782
            for b in range(w.nb):
1✔
1783
                assert len(w.coeffs[k][b]) == len(w.Gpoints[k])
1✔
1784

1785
        # Test WAVECAR with fractional encut
1786
        assert self.w_frac_encut.encut == 100.5
1✔
1787

1788
        # Test malformed WAVECARs
1789
        with pytest.raises(ValueError):
1✔
1790
            Wavecar(self.TEST_FILES_DIR / "WAVECAR.N2.malformed")
1✔
1791

1792
        with pytest.raises(ValueError):
1✔
1793
            Wavecar(self.TEST_FILES_DIR / "WAVECAR.N2", vasp_type="poop")
1✔
1794

1795
        with pytest.raises(ValueError):
1✔
1796
            Wavecar(self.TEST_FILES_DIR / "WAVECAR.N2", vasp_type="g")
1✔
1797

1798
        with pytest.raises(ValueError):
1✔
1799
            Wavecar(self.TEST_FILES_DIR / "WAVECAR.N2", vasp_type="n")
1✔
1800

1801
        import sys
1✔
1802
        from io import StringIO
1✔
1803

1804
        saved_stdout = sys.stdout
1✔
1805
        try:
1✔
1806
            out = StringIO()
1✔
1807
            sys.stdout = out
1✔
1808
            Wavecar(self.TEST_FILES_DIR / "WAVECAR.N2", verbose=True)
1✔
1809
            assert out.getvalue().strip() != ""
1✔
1810
        finally:
1811
            sys.stdout = saved_stdout
1✔
1812

1813
    def test_n2_45210(self):
1✔
1814
        w = Wavecar(self.TEST_FILES_DIR / "WAVECAR.N2.45210")
1✔
1815
        assert w.filename == self.TEST_FILES_DIR / "WAVECAR.N2.45210"
1✔
1816
        assert w.efermi == approx(-5.7232, abs=1e-4)
1✔
1817
        assert w.encut == 25.0
1✔
1818
        assert w.nb == 9
1✔
1819
        assert w.nk == 1
1✔
1820
        assert np.allclose(w.a, self.a)
1✔
1821
        assert np.allclose(w.b, self.b)
1✔
1822
        assert w.vol == approx(self.vol)
1✔
1823
        assert len(w.kpoints) == w.nk
1✔
1824
        assert len(w.coeffs) == w.nk
1✔
1825
        assert len(w.coeffs[0]) == w.nb
1✔
1826
        assert len(w.band_energy) == w.nk
1✔
1827
        assert w.band_energy[0].shape == (w.nb, 3)
1✔
1828
        assert len(w.Gpoints[0]) <= 257
1✔
1829

1830
    def test_n2_spin(self):
1✔
1831
        w = Wavecar(self.TEST_FILES_DIR / "WAVECAR.N2.spin")
1✔
1832
        assert len(w.coeffs) == 2
1✔
1833
        assert len(w.band_energy) == 2
1✔
1834
        assert len(w.kpoints) == w.nk
1✔
1835
        assert len(w.Gpoints) == w.nk
1✔
1836
        assert len(w.coeffs[0][0]) == w.nb
1✔
1837
        assert len(w.band_energy[0]) == w.nk
1✔
1838

1839
        temp_ggp = Wavecar._generate_G_points
1✔
1840
        try:
1✔
1841
            Wavecar._generate_G_points = lambda x, y, gamma: []
1✔
1842
            with pytest.raises(ValueError):
1✔
1843
                Wavecar(self.TEST_FILES_DIR / "WAVECAR.N2")
1✔
1844
        finally:
1845
            Wavecar._generate_G_points = temp_ggp
1✔
1846

1847
    def test__generate_nbmax(self):
1✔
1848
        self.w._generate_nbmax()
1✔
1849
        assert self.w._nbmax.tolist() == [5, 5, 5]
1✔
1850

1851
    def test__generate_G_points(self):
1✔
1852
        for k in range(self.w.nk):
1✔
1853
            kp = self.w.kpoints[k]
1✔
1854
            assert len(self.w._generate_G_points(kp)) <= 257
1✔
1855

1856
    def test_evaluate_wavefunc(self):
1✔
1857
        self.w.Gpoints.append(np.array([0, 0, 0]))
1✔
1858
        self.w.kpoints.append(np.array([0, 0, 0]))
1✔
1859
        self.w.coeffs.append([[1 + 1j]])
1✔
1860
        assert self.w.evaluate_wavefunc(-1, -1, [0, 0, 0]) == approx((1 + 1j) / np.sqrt(self.vol), abs=1e-4)
1✔
1861
        assert self.w.evaluate_wavefunc(0, 0, [0, 0, 0]) == approx(
1✔
1862
            np.sum(self.w.coeffs[0][0]) / np.sqrt(self.vol), abs=1e-4
1863
        )
1864
        w = Wavecar(self.TEST_FILES_DIR / "WAVECAR.N2.spin")
1✔
1865
        w.Gpoints.append(np.array([0, 0, 0]))
1✔
1866
        w.kpoints.append(np.array([0, 0, 0]))
1✔
1867
        w.coeffs[0].append([[1 + 1j]])
1✔
1868
        assert w.evaluate_wavefunc(-1, -1, [0, 0, 0]) == approx((1 + 1j) / np.sqrt(self.vol), abs=1e-4)
1✔
1869

1870
    def test_fft_mesh_basic(self):
1✔
1871
        mesh = self.w.fft_mesh(0, 5)
1✔
1872
        ind = np.argmax(np.abs(mesh))
1✔
1873
        assert np.unravel_index(ind, mesh.shape) == (14, 1, 1)
1✔
1874
        assert mesh[tuple((self.w.ng / 2).astype(int))] == 0j
1✔
1875
        mesh = self.w.fft_mesh(0, 5, shift=False)
1✔
1876
        ind = np.argmax(np.abs(mesh))
1✔
1877
        assert np.unravel_index(ind, mesh.shape) == (6, 8, 8)
1✔
1878
        assert mesh[0, 0, 0] == 0j
1✔
1879

1880
    def test_fft_mesh_advanced(self):
1✔
1881
        ik = 0
1✔
1882
        ib = 0
1✔
1883
        mesh = self.wH2.fft_mesh(ik, ib)
1✔
1884
        mesh_gamma = self.wH2_gamma.fft_mesh(ik, ib)
1✔
1885
        mesh_ncl = self.w_ncl.fft_mesh(ik, ib)
1✔
1886

1887
        # check equality of plane-wave coefficients
1888
        ind_max = np.unravel_index(np.argmax(np.abs(mesh)), mesh.shape)
1✔
1889
        phase = mesh[ind_max] / mesh_gamma[ind_max]
1✔
1890
        assert np.max(np.abs(mesh - phase * mesh_gamma)) <= 1.0e-6
1✔
1891

1892
        # transform to real space for further checking
1893
        mesh = np.fft.ifftn(mesh)
1✔
1894
        mesh_gamma = np.fft.ifftn(mesh_gamma)
1✔
1895
        mesh_ncl = np.fft.ifftn(mesh_ncl)
1✔
1896

1897
        # check equality in real space for regular vs. gamma only
1898
        ind_max = np.unravel_index(np.argmax(np.abs(mesh)), mesh.shape)
1✔
1899
        phase = mesh[ind_max] / mesh_gamma[ind_max]
1✔
1900
        assert np.max(np.abs(mesh - phase * mesh_gamma)) <= 1.0e-6
1✔
1901

1902
        # spot check some points in real space
1903
        p1 = (
1✔
1904
            int(mesh.shape[0] / 2),
1905
            int(mesh.shape[1] / 2) - 1,
1906
            int(mesh.shape[2] / 2) - 2,
1907
        )
1908
        p2 = (p1[0] + 1, p1[1], p1[2])
1✔
1909
        c = np.array([[5, 0, 0], [0, 4, 0], [0, 0, 6]])  # this needs to match POSCAR,  which we don't have
1✔
1910
        r1 = np.dot(np.array(p1) / mesh.shape, c)
1✔
1911
        r2 = np.dot(np.array(p2) / mesh.shape, c)
1✔
1912

1913
        # check equality of FFT and slow FT for regular mesh (ratio, to account for normalization)
1914
        v1 = self.wH2.evaluate_wavefunc(ik, ib, r1)
1✔
1915
        v2 = self.wH2.evaluate_wavefunc(ik, ib, r2)
1✔
1916
        assert np.abs(mesh[p1]) / np.abs(mesh[p2]) == approx(np.abs(v1) / np.abs(v2), abs=1e-6)
1✔
1917

1918
        # spot check one value that we happen to know from reference run
1919
        assert v1 == approx(-0.01947068011502887 + 0.23340228099620275j, abs=1e-8)
1✔
1920

1921
        # check equality of FFT and slow FT for gamma-only mesh (ratio again)
1922
        v1_gamma = self.wH2_gamma.evaluate_wavefunc(ik, ib, r1)
1✔
1923
        v2_gamma = self.wH2_gamma.evaluate_wavefunc(ik, ib, r2)
1✔
1924
        assert np.abs(mesh_gamma[p1]) / np.abs(mesh_gamma[p2]) == approx(np.abs(v1_gamma) / np.abs(v2_gamma), abs=1e-6)
1✔
1925

1926
        # check equality of FFT and slow FT for ncl mesh (ratio again)
1927
        v1_ncl = self.w_ncl.evaluate_wavefunc(ik, ib, r1)
1✔
1928
        v2_ncl = self.w_ncl.evaluate_wavefunc(ik, ib, r2)
1✔
1929
        assert np.abs(mesh_ncl[p1]) / np.abs(mesh_ncl[p2]) == approx(np.abs(v1_ncl) / np.abs(v2_ncl), abs=1e-6)
1✔
1930

1931
    def test_get_parchg(self):
1✔
1932
        poscar = Poscar.from_file(self.TEST_FILES_DIR / "POSCAR")
1✔
1933

1934
        w = self.w
1✔
1935
        c = w.get_parchg(poscar, 0, 0, spin=0, phase=False)
1✔
1936
        assert "total" in c.data
1✔
1937
        assert "diff" not in c.data
1✔
1938
        assert np.prod(c.data["total"].shape) == np.prod(w.ng * 2)
1✔
1939
        assert np.all(c.data["total"] > 0.0)
1✔
1940

1941
        c = w.get_parchg(poscar, 0, 0, spin=0, phase=True)
1✔
1942
        assert "total" in c.data
1✔
1943
        assert "diff" not in c.data
1✔
1944
        assert np.prod(c.data["total"].shape) == np.prod(w.ng * 2)
1✔
1945
        assert not np.all(c.data["total"] > 0.0)
1✔
1946

1947
        w = Wavecar(self.TEST_FILES_DIR / "WAVECAR.N2.spin")
1✔
1948
        c = w.get_parchg(poscar, 0, 0, phase=False, scale=1)
1✔
1949
        assert "total" in c.data
1✔
1950
        assert "diff" in c.data
1✔
1951
        assert np.prod(c.data["total"].shape) == np.prod(w.ng)
1✔
1952
        assert np.all(c.data["total"] > 0.0)
1✔
1953
        assert not np.all(c.data["diff"] > 0.0)
1✔
1954

1955
        c = w.get_parchg(poscar, 0, 0, spin=0, phase=False)
1✔
1956
        assert "total" in c.data
1✔
1957
        assert "diff" not in c.data
1✔
1958
        assert np.prod(c.data["total"].shape) == np.prod(w.ng * 2)
1✔
1959
        assert np.all(c.data["total"] > 0.0)
1✔
1960

1961
        c = w.get_parchg(poscar, 0, 0, spin=0, phase=True)
1✔
1962
        assert "total" in c.data
1✔
1963
        assert "diff" not in c.data
1✔
1964
        assert np.prod(c.data["total"].shape) == np.prod(w.ng * 2)
1✔
1965
        assert not np.all(c.data["total"] > 0.0)
1✔
1966

1967
        w = self.w_ncl
1✔
1968
        w.coeffs.append([np.ones((2, 100))])
1✔
1969
        c = w.get_parchg(poscar, -1, 0, phase=False, spinor=None)
1✔
1970
        assert "total" in c.data
1✔
1971
        assert "diff" not in c.data
1✔
1972
        assert np.prod(c.data["total"].shape) == np.prod(w.ng * 2)
1✔
1973
        assert not np.all(c.data["total"] > 0.0)
1✔
1974

1975
        c = w.get_parchg(poscar, -1, 0, phase=True, spinor=0)
1✔
1976
        assert "total" in c.data
1✔
1977
        assert "diff" not in c.data
1✔
1978
        assert np.prod(c.data["total"].shape) == np.prod(w.ng * 2)
1✔
1979
        assert not np.all(c.data["total"] > 0.0)
1✔
1980

1981
        w.coeffs[-1] = [np.zeros((2, 100))]
1✔
1982
        c = w.get_parchg(poscar, -1, 0, phase=False, spinor=1)
1✔
1983
        assert "total" in c.data
1✔
1984
        assert "diff" not in c.data
1✔
1985
        assert np.prod(c.data["total"].shape) == np.prod(w.ng * 2)
1✔
1986
        assert np.allclose(c.data["total"], 0.0)
1✔
1987

1988
    def test_write_unks(self):
1✔
1989
        unk_std = Unk.from_file(self.TEST_FILES_DIR / "UNK.N2.std")
1✔
1990
        unk_ncl = Unk.from_file(self.TEST_FILES_DIR / "UNK.H2.ncl")
1✔
1991

1992
        with pytest.raises(ValueError):
1✔
1993
            self.w.write_unks(self.TEST_FILES_DIR / "UNK.N2.std")
1✔
1994

1995
        # different grids
1996
        with ScratchDir("."):
1✔
1997
            self.w.write_unks("./unk_dir")
1✔
1998
            assert len(list(Path("./unk_dir").glob("UNK*"))) == 1
1✔
1999
            unk = Unk.from_file("./unk_dir/UNK00001.1")
1✔
2000
            assert unk != unk_std
1✔
2001

2002
        # correct grid
2003
        self.w.ng = np.array([12, 12, 12])
1✔
2004
        with ScratchDir("."):
1✔
2005
            self.w.write_unks(".")
1✔
2006
            unk = Unk.from_file("UNK00001.1")
1✔
2007
            assert unk == unk_std
1✔
2008

2009
        # ncl test
2010
        with ScratchDir("."):
1✔
2011
            self.w_ncl.write_unks(".")
1✔
2012
            unk = Unk.from_file("UNK00001.NC")
1✔
2013
            assert unk == unk_ncl
1✔
2014

2015

2016
class EigenvalTest(PymatgenTest):
1✔
2017
    _multiprocess_shared_ = True
1✔
2018

2019
    def test_init(self):
1✔
2020
        eig = Eigenval(self.TEST_FILES_DIR / "EIGENVAL.gz")
1✔
2021
        assert eig.ispin == 1
1✔
2022
        assert eig.nkpt == len(eig.kpoints)
1✔
2023
        assert eig.nkpt == len(eig.kpoints_weights)
1✔
2024
        assert eig.nkpt == eig.eigenvalues[Spin.up].shape[0]
1✔
2025
        assert eig.nelect == 16
1✔
2026
        assert eig.nbands == eig.eigenvalues[Spin.up].shape[1]
1✔
2027
        assert np.max(eig.eigenvalues[Spin.up]) > 0
1✔
2028
        assert np.min(eig.eigenvalues[Spin.up]) < 0
1✔
2029

2030
    def test_ispin2(self):
1✔
2031
        eig = Eigenval(self.TEST_FILES_DIR / "EIGENVAL.ispin2.gz")
1✔
2032
        assert eig.ispin == 2
1✔
2033
        assert eig.nkpt == eig.eigenvalues[Spin.up].shape[0]
1✔
2034
        assert eig.nbands == eig.eigenvalues[Spin.up].shape[1]
1✔
2035
        assert eig.nkpt == eig.eigenvalues[Spin.down].shape[0]
1✔
2036
        assert eig.nbands == eig.eigenvalues[Spin.down].shape[1]
1✔
2037

2038
    def test_eigenvalue_band_properties(self):
1✔
2039
        eig = Eigenval(self.TEST_FILES_DIR / "EIGENVAL.gz")
1✔
2040
        props = eig.eigenvalue_band_properties
1✔
2041
        assert props[0] == approx(6.4153, abs=1e-4)
1✔
2042
        assert props[1] == approx(7.5587, abs=1e-4)
1✔
2043
        assert props[2] == approx(1.1434, abs=1e-4)
1✔
2044
        assert props[3] is False
1✔
2045

2046
    def test_eigenvalue_band_properties_separate_spins(self):
1✔
2047
        eig = Eigenval(self.TEST_FILES_DIR / "EIGENVAL_separate_spins.gz", separate_spins=True)
1✔
2048
        props = eig.eigenvalue_band_properties
1✔
2049
        eig2 = Eigenval(self.TEST_FILES_DIR / "EIGENVAL_separate_spins.gz", separate_spins=False)
1✔
2050
        props2 = eig2.eigenvalue_band_properties
1✔
2051
        assert props[0][0] == approx(2.8772, abs=1e-4)
1✔
2052
        assert props[0][1] == approx(1.2810, abs=1e-4)
1✔
2053
        assert props[1][0] == approx(3.6741, abs=1e-4)
1✔
2054
        assert props[1][1] == approx(1.6225, abs=1e-4)
1✔
2055
        assert props[2][0] == approx(0.7969, abs=1e-4)
1✔
2056
        assert props[2][1] == approx(0.3415, abs=1e-4)
1✔
2057
        assert props2[0] == approx(np.min(props[1]) - np.max(props[2]), abs=1e-4)
1✔
2058
        assert props[3][0] is True
1✔
2059
        assert props[3][1] is True
1✔
2060

2061

2062
class WavederTest(PymatgenTest):
1✔
2063
    _multiprocess_shared_ = True
1✔
2064

2065
    def setUp(self):
1✔
2066
        wder = Waveder.from_binary(self.TEST_FILES_DIR / "WAVEDER", "float64")
1✔
2067
        assert wder.nbands == 36
1✔
2068
        assert wder.nkpoints == 56
1✔
2069
        band_i = 0
1✔
2070
        band_j = 0
1✔
2071
        kp_index = 0
1✔
2072
        spin_index = 0
1✔
2073
        cart_dir_index = 0
1✔
2074
        cder = wder.get_orbital_derivative_between_states(band_i, band_j, kp_index, spin_index, cart_dir_index)
1✔
2075
        assert cder == approx(-1.33639226092e-103, abs=1e-114)
1✔
2076

2077
    def test_consistency(self):
1✔
2078
        wder_ref = np.loadtxt(self.TEST_FILES_DIR / "WAVEDERF.Si", skiprows=1)
1✔
2079

2080
        def _check(wder):
1✔
2081
            with open(self.TEST_FILES_DIR / "WAVEDERF.Si") as f:
1✔
2082
                first_line = [int(a) for a in f.readline().split()]
1✔
2083
            assert wder.nkpoints == first_line[1]
1✔
2084
            assert wder.nbands == first_line[2]
1✔
2085
            for i in range(10):
1✔
2086
                assert wder.get_orbital_derivative_between_states(0, i, 0, 0, 0).real == approx(
1✔
2087
                    wder_ref[i, 6], abs=1e-10
2088
                )
2089
                assert wder.cder[0, i, 0, 0, 0].real == approx(wder_ref[i, 6], abs=1e-10)
1✔
2090
                assert wder.cder[0, i, 0, 0, 0].imag == approx(wder_ref[i, 7], abs=1e-10)
1✔
2091
                assert wder.cder[0, i, 0, 0, 1].real == approx(wder_ref[i, 8], abs=1e-10)
1✔
2092
                assert wder.cder[0, i, 0, 0, 1].imag == approx(wder_ref[i, 9], abs=1e-10)
1✔
2093
                assert wder.cder[0, i, 0, 0, 2].real == approx(wder_ref[i, 10], abs=1e-10)
1✔
2094
                assert wder.cder[0, i, 0, 0, 2].imag == approx(wder_ref[i, 11], abs=1e-10)
1✔
2095

2096
        wder = Waveder.from_binary(self.TEST_FILES_DIR / "WAVEDER.Si")
1✔
2097
        _check(wder)
1✔
2098
        wderf = Waveder.from_formatted(self.TEST_FILES_DIR / "WAVEDERF.Si")
1✔
2099
        _check(wderf)
1✔
2100

2101

2102
class WSWQTest(PymatgenTest):
1✔
2103
    _multiprocess_shared_ = True
1✔
2104

2105
    def setUp(self):
1✔
2106
        self.wswq = WSWQ.from_file(self.TEST_FILES_DIR / "WSWQ.gz")
1✔
2107

2108
    def test_consistency(self):
1✔
2109
        assert True is True
1✔
2110
        assert self.wswq.nbands == 18
1✔
2111
        assert self.wswq.nkpoints == 20
1✔
2112
        assert self.wswq.nspin == 2
1✔
2113
        assert self.wswq.me_real.shape == (2, 20, 18, 18)
1✔
2114
        assert self.wswq.me_imag.shape == (2, 20, 18, 18)
1✔
2115
        for itr, (r, i) in enumerate(zip(self.wswq.me_real[0][0][4], self.wswq.me_imag[0][0][4])):
1✔
2116
            if itr == 4:
1✔
2117
                assert np.linalg.norm([r, i]) > 0.999
1✔
2118
            else:
2119
                assert np.linalg.norm([r, i]) < 0.001
1✔
2120

2121

2122
if __name__ == "__main__":
1✔
2123
    unittest.main()
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc