• 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.82
/pymatgen/entries/tests/test_compatibility.py
1
# Copyright (c) Pymatgen Development Team.
2
# Distributed under the terms of the MIT License.
3

4
from __future__ import annotations
1✔
5

6
import os
1✔
7
import unittest
1✔
8
import warnings
1✔
9
from collections import defaultdict
1✔
10
from math import sqrt
1✔
11
from pathlib import Path
1✔
12

13
import pytest
1✔
14
from monty.json import MontyDecoder
1✔
15

16
from pymatgen.core.composition import Composition
1✔
17
from pymatgen.core.lattice import Lattice
1✔
18
from pymatgen.core.periodic_table import Element
1✔
19
from pymatgen.core.structure import Structure
1✔
20
from pymatgen.entries.compatibility import (
1✔
21
    MU_H2O,
22
    AqueousCorrection,
23
    Compatibility,
24
    CompatibilityError,
25
    MaterialsProject2020Compatibility,
26
    MaterialsProjectAqueousCompatibility,
27
    MaterialsProjectCompatibility,
28
    MITAqueousCompatibility,
29
    MITCompatibility,
30
)
31
from pymatgen.entries.computed_entries import (
1✔
32
    ComputedEntry,
33
    ComputedStructureEntry,
34
    ConstantEnergyAdjustment,
35
)
36
from pymatgen.util.testing import PymatgenTest
1✔
37

38

39
class CorrectionSpecificityTest(unittest.TestCase):
1✔
40
    """
41
    Make sure corrections are only applied to GGA or GGA+U entries
42
    """
43

44
    def setUp(self):
1✔
45
        warnings.simplefilter("ignore")
1✔
46
        self.entry1 = ComputedEntry(
1✔
47
            "Fe2O3",
48
            -1,
49
            0.0,
50
            parameters={
51
                "is_hubbard": True,
52
                "hubbards": {"Fe": 5.3, "O": 0},
53
                "run_type": "GGA+U",
54
                "potcar_spec": [
55
                    {
56
                        "titel": "PAW_PBE Fe_pv 06Sep2000",
57
                        "hash": "994537de5c4122b7f1b77fb604476db4",
58
                    },
59
                    {
60
                        "titel": "PAW_PBE O 08Apr2002",
61
                        "hash": "7a25bc5b9a5393f46600a4939d357982",
62
                    },
63
                ],
64
            },
65
        )
66
        self.entry2 = ComputedEntry(
1✔
67
            "FeS",
68
            -1,
69
            0.0,
70
            parameters={
71
                "is_hubbard": False,
72
                "run_type": "GGA",
73
                "potcar_spec": [
74
                    {
75
                        "titel": "PAW_PBE Fe_pv 06Sep2000",
76
                        "hash": "994537de5c4122b7f1b77fb604476db4",
77
                    },
78
                    {
79
                        "titel": "PAW_PBE S 08Apr2002",
80
                        "hash": "7a25bc5b9a5393f46600a4939d357982",
81
                    },
82
                ],
83
            },
84
        )
85

86
        self.entry3 = ComputedEntry(
1✔
87
            "Fe2O3",
88
            -1,
89
            0.0,
90
            parameters={
91
                "is_hubbard": False,
92
                "run_type": "R2SCAN",
93
                "potcar_spec": [
94
                    {
95
                        "titel": "PAW_PBE Fe_pv 06Sep2000",
96
                        "hash": "994537de5c4122b7f1b77fb604476db4",
97
                    },
98
                    {
99
                        "titel": "PAW_PBE O 08Apr2002",
100
                        "hash": "7a25bc5b9a5393f46600a4939d357982",
101
                    },
102
                ],
103
            },
104
        )
105
        self.compat = MaterialsProjectCompatibility(check_potcar_hash=False)
1✔
106

107
    def test_correction_specificity(self):
1✔
108
        processed = self.compat.process_entries([self.entry1, self.entry2, self.entry3])
1✔
109

110
        assert len(processed) == 2
1✔
111

112
        assert self.entry1.correction != 0
1✔
113
        assert self.entry2.correction != 0
1✔
114
        assert self.entry3.correction == 0.0
1✔
115

116

117
# abstract Compatibility tests
118
class DummyCompatibility(Compatibility):
1✔
119
    """
120
    Dummy class to test abstract Compatibility interface
121
    """
122

123
    def get_adjustments(self, entry):
1✔
124
        return [ConstantEnergyAdjustment(-10, name="Dummy adjustment")]
1✔
125

126

127
def test_process_entries_return_type():
1✔
128
    """
129
    process_entries should accept single entries or a list, and always return a list
130
    """
131
    entry = ComputedEntry("Fe2O3", -2)
1✔
132
    compat = DummyCompatibility()
1✔
133

134
    assert isinstance(compat.process_entries(entry), list)
1✔
135
    assert isinstance(compat.process_entries([entry]), list)
1✔
136

137

138
def test_no_duplicate_corrections():
1✔
139
    """
140
    Compatibility should never apply the same correction twice
141
    """
142
    entry = ComputedEntry("Fe2O3", -2)
1✔
143
    compat = DummyCompatibility()
1✔
144

145
    assert entry.correction == 0
1✔
146
    compat.process_entries(entry)
1✔
147
    assert entry.correction == -10
1✔
148
    compat.process_entries(entry)
1✔
149
    assert entry.correction == -10
1✔
150
    compat.process_entries(entry, clean=True)
1✔
151
    assert entry.correction == -10
1✔
152

153

154
def test_clean_arg():
1✔
155
    """
156
    clean=False should preserve existing corrections, clean=True should delete
157
    them before processing
158
    """
159
    entry = ComputedEntry("Fe2O3", -2, correction=-4)
1✔
160
    compat = DummyCompatibility()
1✔
161

162
    assert entry.correction == -4
1✔
163
    compat.process_entries(entry, clean=False)
1✔
164
    assert entry.correction == -14
1✔
165
    compat.process_entries(entry)
1✔
166
    assert entry.correction == -10
1✔
167

168

169
def test_energy_adjustment_normalize():
1✔
170
    """
171
    Both manual and automatically generated energy adjustments should be scaled
172
    by the normalize method
173
    """
174
    entry = ComputedEntry("Fe4O6", -2, correction=-4)
1✔
175
    entry = entry.normalize()
1✔
176
    for ea in entry.energy_adjustments:
1✔
177
        if "Manual" in ea.name:
1✔
178
            assert ea.value == -2
1✔
179

180
    compat = DummyCompatibility()
1✔
181
    entry = ComputedEntry("Fe4O6", -2, correction=-4)
1✔
182
    entry = compat.process_entries(entry)[0]
1✔
183
    entry = entry.normalize()
1✔
184
    for ea in entry.energy_adjustments:
1✔
185
        if "Dummy" in ea.name:
1✔
186
            assert ea.value == -5
1✔
187

188

189
def test_overlapping_adjustments():
1✔
190
    """
191
    Compatibility should raise a CompatibilityError if there is already a
192
    correction with the same name, but a different value, and process_entries
193
    should skip that entry.
194
    """
195
    ea = ConstantEnergyAdjustment(-5, name="Dummy adjustment")
1✔
196
    entry = ComputedEntry("Fe2O3", -2, energy_adjustments=[ea])
1✔
197
    compat = DummyCompatibility()
1✔
198

199
    assert entry.correction == -5
1✔
200

201
    # in case of a collision between EnergyAdjustment, check for a UserWarning
202
    with pytest.warns(UserWarning, match="already has an energy adjustment called Dummy"):
1✔
203
        processed = compat.process_entries(entry, clean=False)
1✔
204

205
    assert len(processed) == 0
1✔
206

207

208
class MaterialsProjectCompatibilityTest(unittest.TestCase):
1✔
209
    def setUp(self):
1✔
210
        warnings.simplefilter("ignore")
1✔
211
        self.entry1 = ComputedEntry(
1✔
212
            "Fe2O3",
213
            -1,
214
            correction=0.0,
215
            parameters={
216
                "is_hubbard": True,
217
                "hubbards": {"Fe": 5.3, "O": 0},
218
                "run_type": "GGA+U",
219
                "potcar_spec": [
220
                    {
221
                        "titel": "PAW_PBE Fe_pv 06Sep2000",
222
                        "hash": "994537de5c4122b7f1b77fb604476db4",
223
                    },
224
                    {
225
                        "titel": "PAW_PBE O 08Apr2002",
226
                        "hash": "7a25bc5b9a5393f46600a4939d357982",
227
                    },
228
                ],
229
            },
230
        )
231

232
        self.entry_sulfide = ComputedEntry(
1✔
233
            "FeS",
234
            -1,
235
            correction=0.0,
236
            parameters={
237
                "is_hubbard": False,
238
                "run_type": "GGA",
239
                "potcar_spec": [
240
                    {
241
                        "titel": "PAW_PBE Fe_pv 06Sep2000",
242
                        "hash": "994537de5c4122b7f1b77fb604476db4",
243
                    },
244
                    {
245
                        "titel": "PAW_PBE S 08Apr2002",
246
                        "hash": "7a25bc5b9a5393f46600a4939d357982",
247
                    },
248
                ],
249
            },
250
        )
251

252
        self.entry4 = ComputedEntry(
1✔
253
            "H8",
254
            -27.1,
255
            correction=0.0,
256
            parameters={
257
                "run_type": "LDA",
258
                "is_hubbard": False,
259
                "pseudo_potential": {
260
                    "functional": "PBE",
261
                    "labels": ["H"],
262
                    "pot_type": "paw",
263
                },
264
                "hubbards": {},
265
                "potcar_symbols": ["PBE H"],
266
                "oxide_type": "None",
267
            },
268
        )
269

270
        self.entry2 = ComputedEntry(
1✔
271
            "Fe3O4",
272
            -2,
273
            correction=0.0,
274
            parameters={
275
                "is_hubbard": True,
276
                "hubbards": {"Fe": 5.3, "O": 0},
277
                "run_type": "GGA+U",
278
                "potcar_spec": [
279
                    {
280
                        "titel": "PAW_PBE Fe_pv 06Sep2000",
281
                        "hash": "994537de5c4122b7f1b77fb604476db4",
282
                    },
283
                    {
284
                        "titel": "PAW_PBE O 08Apr2002",
285
                        "hash": "7a25bc5b9a5393f46600a4939d357982",
286
                    },
287
                ],
288
            },
289
        )
290
        self.entry3 = ComputedEntry(
1✔
291
            "FeO",
292
            -2,
293
            correction=0.0,
294
            parameters={
295
                "is_hubbard": True,
296
                "hubbards": {"Fe": 4.3, "O": 0},
297
                "run_type": "GGA+U",
298
                "potcar_spec": [
299
                    {
300
                        "titel": "PAW_PBE Fe_pv 06Sep2000",
301
                        "hash": "994537de5c4122b7f1b77fb604476db4",
302
                    },
303
                    {
304
                        "titel": "PAW_PBE O 08Apr2002",
305
                        "hash": "7a25bc5b9a5393f46600a4939d357982",
306
                    },
307
                ],
308
            },
309
        )
310

311
        self.compat = MaterialsProjectCompatibility(check_potcar_hash=False)
1✔
312
        self.ggacompat = MaterialsProjectCompatibility("GGA", check_potcar_hash=False)
1✔
313

314
    def tearDown(self):
1✔
315
        warnings.simplefilter("default")
1✔
316

317
    def test_process_entry(self):
1✔
318
        # Correct parameters
319
        assert self.compat.process_entry(self.entry1) is not None
1✔
320
        assert self.ggacompat.process_entry(self.entry1) is None
1✔
321

322
        # Correct parameters
323
        entry = ComputedEntry(
1✔
324
            "Fe2O3",
325
            -1,
326
            correction=0.0,
327
            parameters={
328
                "is_hubbard": False,
329
                "hubbards": {},
330
                "run_type": "GGA",
331
                "potcar_spec": [
332
                    {
333
                        "titel": "PAW_PBE Fe_pv 06Sep2000",
334
                        "hash": "994537de5c4122b7f1b77fb604476db4",
335
                    },
336
                    {
337
                        "titel": "PAW_PBE O 08Apr2002",
338
                        "hash": "7a25bc5b9a5393f46600a4939d357982",
339
                    },
340
                ],
341
            },
342
        )
343
        assert self.compat.process_entry(entry) is None
1✔
344
        assert self.ggacompat.process_entry(entry) is not None
1✔
345

346
        entry = ComputedEntry(
1✔
347
            "Fe2O3",
348
            -1,
349
            correction=0.0,
350
            parameters={
351
                "is_hubbard": True,
352
                "hubbards": {"Fe": 5.3, "O": 0},
353
                "run_type": "GGA+U",
354
                "potcar_spec": [
355
                    {
356
                        "titel": "PAW_PBE Fe_pv 06Sep2000",
357
                        "hash": "994537de5c4122b7f1b77fb604476db4",
358
                    },
359
                    {
360
                        "titel": "PAW_PBE O 08Apr2002",
361
                        "hash": "7a25bc5b9a5393f46600a4939d357982",
362
                    },
363
                ],
364
            },
365
        )
366
        assert self.compat.process_entry(entry) is not None
1✔
367

368
    def test_correction_values(self):
1✔
369
        # test_corrections
370
        assert self.compat.process_entry(self.entry1).correction == pytest.approx(-2.733 * 2 - 0.70229 * 3)
1✔
371

372
        entry = ComputedEntry(
1✔
373
            "FeF3",
374
            -2,
375
            correction=0.0,
376
            parameters={
377
                "is_hubbard": True,
378
                "hubbards": {"Fe": 5.3, "F": 0},
379
                "run_type": "GGA+U",
380
                "potcar_spec": [
381
                    {
382
                        "titel": "PAW_PBE Fe_pv 06Sep2000",
383
                        "hash": "994537de5c4122b7f1b77fb604476db4",
384
                    },
385
                    {
386
                        "titel": "PAW_PBE F 08Apr2002",
387
                        "hash": "180141c33d032bfbfff30b3bea9d23dd",
388
                    },
389
                ],
390
            },
391
        )
392
        assert self.compat.process_entry(entry) is not None
1✔
393

394
        # Check actual correction
395
        assert self.compat.process_entry(entry).correction == pytest.approx(-2.733)
1✔
396

397
        assert self.compat.process_entry(self.entry_sulfide).correction == pytest.approx(-0.66346)
1✔
398

399
    def test_U_values(self):
1✔
400
        # Wrong U value
401
        entry = ComputedEntry(
1✔
402
            "Fe2O3",
403
            -1,
404
            correction=0.0,
405
            parameters={
406
                "is_hubbard": True,
407
                "hubbards": {"Fe": 5.2, "O": 0},
408
                "run_type": "GGA+U",
409
                "potcar_spec": [
410
                    {
411
                        "titel": "PAW_PBE Fe_pv 06Sep2000",
412
                        "hash": "994537de5c4122b7f1b77fb604476db4",
413
                    },
414
                    {
415
                        "titel": "PAW_PBE O 08Apr2002",
416
                        "hash": "7a25bc5b9a5393f46600a4939d357982",
417
                    },
418
                ],
419
            },
420
        )
421
        assert self.compat.process_entry(entry) is None
1✔
422

423
        # GGA run of U
424
        entry = ComputedEntry(
1✔
425
            "Fe2O3",
426
            -1,
427
            correction=0.0,
428
            parameters={
429
                "is_hubbard": False,
430
                "hubbards": None,
431
                "run_type": "GGA",
432
                "potcar_spec": [
433
                    {
434
                        "titel": "PAW_PBE Fe_pv 06Sep2000",
435
                        "hash": "994537de5c4122b7f1b77fb604476db4",
436
                    },
437
                    {
438
                        "titel": "PAW_PBE O 08Apr2002",
439
                        "hash": "7a25bc5b9a5393f46600a4939d357982",
440
                    },
441
                ],
442
            },
443
        )
444
        assert self.compat.process_entry(entry) is None
1✔
445

446
        # GGA+U run of non-U
447
        entry = ComputedEntry(
1✔
448
            "Al2O3",
449
            -1,
450
            correction=0.0,
451
            parameters={
452
                "is_hubbard": True,
453
                "hubbards": {"Al": 5.3, "O": 0},
454
                "run_type": "GGA+U",
455
                "potcar_spec": [
456
                    {
457
                        "titel": "PAW_PBE Al 06Sep2000",
458
                        "hash": "805c888bbd2793e462311f6a20d873d9",
459
                    },
460
                    {
461
                        "titel": "PAW_PBE O 08Apr2002",
462
                        "hash": "7a25bc5b9a5393f46600a4939d357982",
463
                    },
464
                ],
465
            },
466
        )
467
        assert self.compat.process_entry(entry) is None
1✔
468

469
        # Materials project should not have a U for sulfides
470
        entry = ComputedEntry(
1✔
471
            "FeS2",
472
            -2,
473
            correction=0.0,
474
            parameters={
475
                "is_hubbard": True,
476
                "hubbards": {"Fe": 5.3, "S": 0},
477
                "run_type": "GGA+U",
478
                "potcar_spec": [
479
                    {
480
                        "titel": "PAW_PBE Fe_pv 06Sep2000",
481
                        "hash": "994537de5c4122b7f1b77fb604476db4",
482
                    },
483
                    {
484
                        "titel": "PAW_PBE S 08Apr2002",
485
                        "hash": "f7f8e4a74a6cbb8d63e41f4373b54df2",
486
                    },
487
                ],
488
            },
489
        )
490
        assert self.compat.process_entry(entry) is None
1✔
491

492
    def test_wrong_psp(self):
1✔
493
        # Wrong psp
494
        entry = ComputedEntry(
1✔
495
            "Fe2O3",
496
            -1,
497
            correction=0.0,
498
            parameters={
499
                "is_hubbard": True,
500
                "hubbards": {"Fe": 5.3, "O": 0},
501
                "run_type": "GGA+U",
502
                "potcar_spec": [
503
                    {
504
                        "titel": "PAW_PBE Fe 06Sep2000",
505
                        "hash": "9530da8244e4dac17580869b4adab115",
506
                    },
507
                    {
508
                        "titel": "PAW_PBE O 08Apr2002",
509
                        "hash": "7a25bc5b9a5393f46600a4939d357982",
510
                    },
511
                ],
512
            },
513
        )
514
        assert self.compat.process_entry(entry) is None
1✔
515

516
    def test_element_processing(self):
1✔
517
        entry = ComputedEntry(
1✔
518
            "O",
519
            -1,
520
            correction=0.0,
521
            parameters={
522
                "is_hubbard": False,
523
                "hubbards": {},
524
                "potcar_spec": [
525
                    {
526
                        "titel": "PAW_PBE O 08Apr2002",
527
                        "hash": "7a25bc5b9a5393f46600a4939d357982",
528
                    }
529
                ],
530
                "run_type": "GGA",
531
            },
532
        )
533
        entry = self.compat.process_entry(entry)
1✔
534
        #        self.assertEqual(entry.entry_id, -8)
535
        assert entry.energy == pytest.approx(-1)
1✔
536
        assert self.ggacompat.process_entry(entry).energy == pytest.approx(-1)
1✔
537

538
    def test_get_explanation_dict(self):
1✔
539
        compat = MaterialsProjectCompatibility(check_potcar_hash=False)
1✔
540
        entry = ComputedEntry(
1✔
541
            "Fe2O3",
542
            -1,
543
            correction=0.0,
544
            parameters={
545
                "is_hubbard": True,
546
                "hubbards": {"Fe": 5.3, "O": 0},
547
                "run_type": "GGA+U",
548
                "potcar_spec": [
549
                    {
550
                        "titel": "PAW_PBE Fe_pv 06Sep2000",
551
                        "hash": "994537de5c4122b7f1b77fb604476db4",
552
                    },
553
                    {
554
                        "titel": "PAW_PBE O 08Apr2002",
555
                        "hash": "7a25bc5b9a5393f46600a4939d357982",
556
                    },
557
                ],
558
            },
559
        )
560
        d = compat.get_explanation_dict(entry)
1✔
561
        assert "MPRelaxSet Potcar Correction" == d["corrections"][0]["name"]
1✔
562

563
    def test_get_corrections_dict(self):
1✔
564
        compat = MaterialsProjectCompatibility(check_potcar_hash=False)
1✔
565
        ggacompat = MaterialsProjectCompatibility("GGA", check_potcar_hash=False)
1✔
566

567
        # Correct parameters
568
        entry = ComputedEntry(
1✔
569
            "Fe2O3",
570
            -1,
571
            correction=0.0,
572
            parameters={
573
                "is_hubbard": True,
574
                "hubbards": {"Fe": 5.3, "O": 0},
575
                "run_type": "GGA+U",
576
                "potcar_spec": [
577
                    {
578
                        "titel": "PAW_PBE Fe_pv 06Sep2000",
579
                        "hash": "994537de5c4122b7f1b77fb604476db4",
580
                    },
581
                    {
582
                        "titel": "PAW_PBE O 08Apr2002",
583
                        "hash": "7a25bc5b9a5393f46600a4939d357982",
584
                    },
585
                ],
586
            },
587
        )
588
        c = compat.get_corrections_dict(entry)[0]
1✔
589
        assert c["MP Anion Correction"] == pytest.approx(-2.10687)
1✔
590
        assert c["MP Advanced Correction"] == pytest.approx(-5.466)
1✔
591

592
        entry.parameters["is_hubbard"] = False
1✔
593
        del entry.parameters["hubbards"]
1✔
594
        c = ggacompat.get_corrections_dict(entry)[0]
1✔
595
        assert "MP Advanced Correction" not in c
1✔
596

597
    def test_process_entries(self):
1✔
598
        entries = self.compat.process_entries([self.entry1, self.entry2, self.entry3, self.entry4])
1✔
599
        assert len(entries) == 2
1✔
600

601
    def test_msonable(self):
1✔
602
        compat_dict = self.compat.as_dict()
1✔
603
        decoder = MontyDecoder()
1✔
604
        temp_compat = decoder.process_decoded(compat_dict)
1✔
605
        assert isinstance(temp_compat, MaterialsProjectCompatibility)
1✔
606

607

608
class MaterialsProjectCompatibility2020Test(unittest.TestCase):
1✔
609
    def setUp(self):
1✔
610
        warnings.simplefilter("ignore")
1✔
611
        self.entry1 = ComputedEntry(
1✔
612
            "Fe2O3",
613
            -1,
614
            correction=0.0,
615
            parameters={
616
                "is_hubbard": True,
617
                "hubbards": {"Fe": 5.3, "O": 0},
618
                "run_type": "GGA+U",
619
                "potcar_spec": [
620
                    {
621
                        "titel": "PAW_PBE Fe_pv 06Sep2000",
622
                        "hash": "994537de5c4122b7f1b77fb604476db4",
623
                    },
624
                    {
625
                        "titel": "PAW_PBE O 08Apr2002",
626
                        "hash": "7a25bc5b9a5393f46600a4939d357982",
627
                    },
628
                ],
629
            },
630
        )
631

632
        self.entry_sulfide = ComputedEntry(
1✔
633
            "FeS",
634
            -1,
635
            correction=0.0,
636
            parameters={
637
                "is_hubbard": False,
638
                "run_type": "GGA",
639
                "potcar_spec": [
640
                    {
641
                        "titel": "PAW_PBE Fe_pv 06Sep2000",
642
                        "hash": "994537de5c4122b7f1b77fb604476db4",
643
                    },
644
                    {
645
                        "titel": "PAW_PBE S 08Apr2002",
646
                        "hash": "7a25bc5b9a5393f46600a4939d357982",
647
                    },
648
                ],
649
            },
650
        )
651

652
        self.entry2 = ComputedEntry(
1✔
653
            "Fe3O4",
654
            -2,
655
            correction=0.0,
656
            parameters={
657
                "is_hubbard": True,
658
                "hubbards": {"Fe": 5.3, "O": 0},
659
                "run_type": "GGA+U",
660
                "potcar_spec": [
661
                    {
662
                        "titel": "PAW_PBE Fe_pv 06Sep2000",
663
                        "hash": "994537de5c4122b7f1b77fb604476db4",
664
                    },
665
                    {
666
                        "titel": "PAW_PBE O 08Apr2002",
667
                        "hash": "7a25bc5b9a5393f46600a4939d357982",
668
                    },
669
                ],
670
            },
671
        )
672
        self.entry3 = ComputedEntry(
1✔
673
            "FeO",
674
            -2,
675
            correction=0.0,
676
            parameters={
677
                "is_hubbard": True,
678
                "hubbards": {"Fe": 4.3, "O": 0},
679
                "run_type": "GGA+U",
680
                "potcar_spec": [
681
                    {
682
                        "titel": "PAW_PBE Fe_pv 06Sep2000",
683
                        "hash": "994537de5c4122b7f1b77fb604476db4",
684
                    },
685
                    {
686
                        "titel": "PAW_PBE O 08Apr2002",
687
                        "hash": "7a25bc5b9a5393f46600a4939d357982",
688
                    },
689
                ],
690
            },
691
        )
692

693
        self.compat = MaterialsProject2020Compatibility(check_potcar_hash=False)
1✔
694
        self.ggacompat = MaterialsProject2020Compatibility("GGA", check_potcar_hash=False)
1✔
695

696
    def tearDown(self):
1✔
697
        warnings.simplefilter("default")
1✔
698

699
    def test_process_entry(self):
1✔
700
        # Correct parameters
701
        assert self.compat.process_entry(self.entry1) is not None
1✔
702
        assert self.ggacompat.process_entry(self.entry1) is None
1✔
703

704
        # Correct parameters
705
        entry = ComputedEntry(
1✔
706
            "Fe2O3",
707
            -1,
708
            correction=0.0,
709
            parameters={
710
                "is_hubbard": False,
711
                "hubbards": {},
712
                "run_type": "GGA",
713
                "potcar_spec": [
714
                    {
715
                        "titel": "PAW_PBE Fe_pv 06Sep2000",
716
                        "hash": "994537de5c4122b7f1b77fb604476db4",
717
                    },
718
                    {
719
                        "titel": "PAW_PBE O 08Apr2002",
720
                        "hash": "7a25bc5b9a5393f46600a4939d357982",
721
                    },
722
                ],
723
            },
724
        )
725
        assert self.compat.process_entry(entry) is None
1✔
726
        assert self.ggacompat.process_entry(entry) is not None
1✔
727

728
        entry = ComputedEntry(
1✔
729
            "Fe2O3",
730
            -1,
731
            correction=0.0,
732
            parameters={
733
                "is_hubbard": True,
734
                "hubbards": {"Fe": 5.3, "O": 0},
735
                "run_type": "GGA+U",
736
                "potcar_spec": [
737
                    {
738
                        "titel": "PAW_PBE Fe_pv 06Sep2000",
739
                        "hash": "994537de5c4122b7f1b77fb604476db4",
740
                    },
741
                    {
742
                        "titel": "PAW_PBE O 08Apr2002",
743
                        "hash": "7a25bc5b9a5393f46600a4939d357982",
744
                    },
745
                ],
746
            },
747
        )
748
        assert self.compat.process_entry(entry) is not None
1✔
749

750
    def test_oxi_state_guess(self):
1✔
751
        # An entry where Composition.oxi_state_guesses will return an empty list
752
        entry_blank = ComputedEntry(
1✔
753
            "Ga3Te",
754
            -12.1900,
755
            correction=0.0,
756
            parameters={
757
                "run_type": "GGA",
758
                "is_hubbard": False,
759
                "pseudo_potential": {"functional": "PBE", "labels": ["Ga_d", "Te"], "pot_type": "paw"},
760
                "hubbards": {},
761
                "potcar_symbols": ["PBE Ga_d", "PBE Te"],
762
                "oxide_type": "None",
763
            },
764
        )
765

766
        # An entry where one anion will only be corrected if oxidation_states is populated
767
        entry_oxi = ComputedEntry(
1✔
768
            "Mo2Cl8O",
769
            -173.0655,
770
            correction=0.0,
771
            parameters={
772
                "run_type": "GGA+U",
773
                "is_hubbard": True,
774
                "pseudo_potential": {"functional": "PBE", "labels": ["Mo_pv", "Cl", "O"], "pot_type": "paw"},
775
                "hubbards": {"Mo": 4.38, "Cl": 0.0, "O": 0.0},
776
                "potcar_symbols": ["PBE Mo_pv", "PBE Cl", "PBE O"],
777
                "oxide_type": "oxide",
778
            },
779
        )
780

781
        # An entry that should receive multiple anion corrections if oxidation
782
        # states are populated
783
        entry_multi_anion = ComputedEntry(
1✔
784
            "C8N4Cl4",
785
            -87.69656726,
786
            correction=0.0,
787
            parameters={
788
                "run_type": "GGA",
789
                "is_hubbard": False,
790
                "pseudo_potential": {"functional": "PBE", "labels": ["C", "N", "Cl"], "pot_type": "paw"},
791
                "hubbards": {},
792
                "potcar_symbols": ["PBE C", "PBE N", "PBE Cl"],
793
                "oxide_type": "None",
794
            },
795
        )
796

797
        with pytest.warns(UserWarning, match="Failed to guess oxidation state"):
1✔
798
            e1 = self.compat.process_entry(entry_blank)
1✔
799
            assert e1.correction == pytest.approx(-0.422)
1✔
800

801
        e2 = self.compat.process_entry(entry_oxi)
1✔
802
        assert e2.correction == pytest.approx(-0.687 + -3.202 * 2 + -0.614 * 8)
1✔
803

804
        e3 = self.compat.process_entry(entry_multi_anion)
1✔
805
        assert e3.correction == pytest.approx(-0.361 * 4 + -0.614 * 4)
1✔
806

807
    def test_correction_values(self):
1✔
808
        # test_corrections
809
        assert self.compat.process_entry(self.entry1).correction == pytest.approx(-2.256 * 2 - 0.687 * 3)
1✔
810

811
        entry = ComputedEntry(
1✔
812
            "FeF3",
813
            -2,
814
            correction=0.0,
815
            parameters={
816
                "is_hubbard": True,
817
                "hubbards": {"Fe": 5.3, "F": 0},
818
                "run_type": "GGA+U",
819
                "potcar_spec": [
820
                    {
821
                        "titel": "PAW_PBE Fe_pv 06Sep2000",
822
                        "hash": "994537de5c4122b7f1b77fb604476db4",
823
                    },
824
                    {
825
                        "titel": "PAW_PBE F 08Apr2002",
826
                        "hash": "180141c33d032bfbfff30b3bea9d23dd",
827
                    },
828
                ],
829
            },
830
        )
831
        assert self.compat.process_entry(entry) is not None
1✔
832

833
        # Check actual correction
834
        assert self.compat.process_entry(entry).correction == pytest.approx(-0.462 * 3 + -2.256)
1✔
835

836
        assert self.compat.process_entry(self.entry_sulfide).correction == pytest.approx(-0.503)
1✔
837

838
    def test_oxdiation_by_electronegativity(self):
1✔
839
        # make sure anion corrections are only applied when the element has
840
        # a negative oxidation state (e.g., correct CaSi but not SiO2 for Si)
841
        # as determined by electronegativity (i.e., the data.oxidation_states key is absent)
842

843
        entry1 = ComputedEntry.from_dict(
1✔
844
            {
845
                "@module": "pymatgen.entries.computed_entries",
846
                "@class": "ComputedEntry",
847
                "energy": -17.01015622,
848
                "composition": defaultdict(float, {"Si": 2.0, "Ca": 2.0}),
849
                "energy_adjustments": [],
850
                "parameters": {
851
                    "run_type": "GGA",
852
                    "is_hubbard": False,
853
                    "pseudo_potential": {
854
                        "functional": "PBE",
855
                        "labels": ["Ca_sv", "Si"],
856
                        "pot_type": "paw",
857
                    },
858
                    "hubbards": {},
859
                    "potcar_symbols": ["PBE Ca_sv", "PBE Si"],
860
                    "oxide_type": "None",
861
                },
862
                "data": {"oxide_type": "None"},
863
                "entry_id": "mp-1563",
864
                "correction": 0.0,
865
            }
866
        )
867

868
        entry2 = ComputedEntry.from_dict(
1✔
869
            {
870
                "@module": "pymatgen.entries.computed_entries",
871
                "@class": "ComputedEntry",
872
                "energy": -47.49120119,
873
                "composition": defaultdict(float, {"Si": 2.0, "O": 4.0}),
874
                "energy_adjustments": [],
875
                "parameters": {
876
                    "run_type": "GGA",
877
                    "is_hubbard": False,
878
                    "pseudo_potential": {
879
                        "functional": "PBE",
880
                        "labels": ["Si", "O"],
881
                        "pot_type": "paw",
882
                    },
883
                    "hubbards": {},
884
                    "potcar_symbols": ["PBE Si", "PBE O"],
885
                    "oxide_type": "oxide",
886
                },
887
                "data": {"oxide_type": "oxide"},
888
                "entry_id": "mp-546794",
889
                "correction": 0.0,
890
            }
891
        )
892

893
        # CaSi; only correction should be Si
894
        assert self.compat.process_entry(entry1).correction == pytest.approx(0.071 * 2)
1✔
895

896
        # SiO2; only corrections should be oxide
897
        assert self.compat.process_entry(entry2).correction == pytest.approx(-0.687 * 4)
1✔
898

899
    def test_oxdiation(self):
1✔
900
        # make sure anion corrections are only applied when the element has
901
        # a negative oxidation state (e.g., correct CaSi but not SiO2 for Si)
902
        # as determined by the data.oxidation_states key
903

904
        entry1 = ComputedEntry.from_dict(
1✔
905
            {
906
                "@module": "pymatgen.entries.computed_entries",
907
                "@class": "ComputedEntry",
908
                "energy": -17.01015622,
909
                "composition": defaultdict(float, {"Si": 2.0, "Ca": 2.0}),
910
                "energy_adjustments": [],
911
                "parameters": {
912
                    "run_type": "GGA",
913
                    "is_hubbard": False,
914
                    "pseudo_potential": {
915
                        "functional": "PBE",
916
                        "labels": ["Ca_sv", "Si"],
917
                        "pot_type": "paw",
918
                    },
919
                    "hubbards": {},
920
                    "potcar_symbols": ["PBE Ca_sv", "PBE Si"],
921
                    "oxide_type": "None",
922
                },
923
                "data": {
924
                    "oxide_type": "None",
925
                    "oxidation_states": {"Ca": 2.0, "Si": -2.0},
926
                },
927
                "entry_id": "mp-1563",
928
                "correction": 0.0,
929
            }
930
        )
931

932
        entry2 = ComputedEntry.from_dict(
1✔
933
            {
934
                "@module": "pymatgen.entries.computed_entries",
935
                "@class": "ComputedEntry",
936
                "energy": -47.49120119,
937
                "composition": defaultdict(float, {"Si": 2.0, "O": 4.0}),
938
                "energy_adjustments": [],
939
                "parameters": {
940
                    "run_type": "GGA",
941
                    "is_hubbard": False,
942
                    "pseudo_potential": {
943
                        "functional": "PBE",
944
                        "labels": ["Si", "O"],
945
                        "pot_type": "paw",
946
                    },
947
                    "hubbards": {},
948
                    "potcar_symbols": ["PBE Si", "PBE O"],
949
                    "oxide_type": "oxide",
950
                },
951
                "data": {
952
                    "oxide_type": "oxide",
953
                    "oxidation_states": {"Si": 4.0, "O": -2.0},
954
                },
955
                "entry_id": "mp-546794",
956
                "correction": 0.0,
957
            }
958
        )
959

960
        # CaSi; only correction should be Si
961
        assert self.compat.process_entry(entry1).correction == pytest.approx(0.071 * 2)
1✔
962

963
        # SiO2; only corrections should be oxide
964
        assert self.compat.process_entry(entry2).correction == pytest.approx(-0.687 * 4)
1✔
965

966
    def test_U_values(self):
1✔
967
        # Wrong U value
968
        entry = ComputedEntry(
1✔
969
            "Fe2O3",
970
            -1,
971
            correction=0.0,
972
            parameters={
973
                "is_hubbard": True,
974
                "hubbards": {"Fe": 5.2, "O": 0},
975
                "run_type": "GGA+U",
976
                "potcar_spec": [
977
                    {
978
                        "titel": "PAW_PBE Fe_pv 06Sep2000",
979
                        "hash": "994537de5c4122b7f1b77fb604476db4",
980
                    },
981
                    {
982
                        "titel": "PAW_PBE O 08Apr2002",
983
                        "hash": "7a25bc5b9a5393f46600a4939d357982",
984
                    },
985
                ],
986
            },
987
        )
988
        assert self.compat.process_entry(entry) is None
1✔
989

990
        # GGA run of U
991
        entry = ComputedEntry(
1✔
992
            "Fe2O3",
993
            -1,
994
            correction=0.0,
995
            parameters={
996
                "is_hubbard": False,
997
                "hubbards": None,
998
                "run_type": "GGA",
999
                "potcar_spec": [
1000
                    {
1001
                        "titel": "PAW_PBE Fe_pv 06Sep2000",
1002
                        "hash": "994537de5c4122b7f1b77fb604476db4",
1003
                    },
1004
                    {
1005
                        "titel": "PAW_PBE O 08Apr2002",
1006
                        "hash": "7a25bc5b9a5393f46600a4939d357982",
1007
                    },
1008
                ],
1009
            },
1010
        )
1011
        assert self.compat.process_entry(entry) is None
1✔
1012

1013
        # GGA+U run of non-U
1014
        entry = ComputedEntry(
1✔
1015
            "Al2O3",
1016
            -1,
1017
            correction=0.0,
1018
            parameters={
1019
                "is_hubbard": True,
1020
                "hubbards": {"Al": 5.3, "O": 0},
1021
                "run_type": "GGA+U",
1022
                "potcar_spec": [
1023
                    {
1024
                        "titel": "PAW_PBE Al 06Sep2000",
1025
                        "hash": "805c888bbd2793e462311f6a20d873d9",
1026
                    },
1027
                    {
1028
                        "titel": "PAW_PBE O 08Apr2002",
1029
                        "hash": "7a25bc5b9a5393f46600a4939d357982",
1030
                    },
1031
                ],
1032
            },
1033
        )
1034
        assert self.compat.process_entry(entry) is None
1✔
1035

1036
        # Materials project should not have a U for sulfides
1037
        entry = ComputedEntry(
1✔
1038
            "FeS2",
1039
            -2,
1040
            correction=0.0,
1041
            parameters={
1042
                "is_hubbard": True,
1043
                "hubbards": {"Fe": 5.3, "S": 0},
1044
                "run_type": "GGA+U",
1045
                "potcar_spec": [
1046
                    {
1047
                        "titel": "PAW_PBE Fe_pv 06Sep2000",
1048
                        "hash": "994537de5c4122b7f1b77fb604476db4",
1049
                    },
1050
                    {
1051
                        "titel": "PAW_PBE S 08Apr2002",
1052
                        "hash": "f7f8e4a74a6cbb8d63e41f4373b54df2",
1053
                    },
1054
                ],
1055
            },
1056
        )
1057
        assert self.compat.process_entry(entry) is None
1✔
1058

1059
    def test_wrong_psp(self):
1✔
1060
        # Wrong psp
1061
        entry = ComputedEntry(
1✔
1062
            "Fe2O3",
1063
            -1,
1064
            correction=0.0,
1065
            parameters={
1066
                "is_hubbard": True,
1067
                "hubbards": {"Fe": 5.3, "O": 0},
1068
                "run_type": "GGA+U",
1069
                "potcar_spec": [
1070
                    {
1071
                        "titel": "PAW_PBE Fe 06Sep2000",
1072
                        "hash": "9530da8244e4dac17580869b4adab115",
1073
                    },
1074
                    {
1075
                        "titel": "PAW_PBE O 08Apr2002",
1076
                        "hash": "7a25bc5b9a5393f46600a4939d357982",
1077
                    },
1078
                ],
1079
            },
1080
        )
1081
        assert self.compat.process_entry(entry) is None
1✔
1082

1083
    def test_element_processing(self):
1✔
1084
        entry = ComputedEntry(
1✔
1085
            "O",
1086
            -1,
1087
            correction=0.0,
1088
            parameters={
1089
                "is_hubbard": False,
1090
                "hubbards": {},
1091
                "potcar_spec": [
1092
                    {
1093
                        "titel": "PAW_PBE O 08Apr2002",
1094
                        "hash": "7a25bc5b9a5393f46600a4939d357982",
1095
                    }
1096
                ],
1097
                "run_type": "GGA",
1098
            },
1099
        )
1100
        entry = self.compat.process_entry(entry)
1✔
1101
        assert entry.energy == pytest.approx(-1)
1✔
1102
        assert self.ggacompat.process_entry(entry).energy == pytest.approx(-1)
1✔
1103

1104
    def test_get_explanation_dict(self):
1✔
1105
        compat = MaterialsProjectCompatibility(check_potcar_hash=False)
1✔
1106
        entry = ComputedEntry(
1✔
1107
            "Fe2O3",
1108
            -1,
1109
            correction=0.0,
1110
            parameters={
1111
                "is_hubbard": True,
1112
                "hubbards": {"Fe": 5.3, "O": 0},
1113
                "run_type": "GGA+U",
1114
                "potcar_spec": [
1115
                    {
1116
                        "titel": "PAW_PBE Fe_pv 06Sep2000",
1117
                        "hash": "994537de5c4122b7f1b77fb604476db4",
1118
                    },
1119
                    {
1120
                        "titel": "PAW_PBE O 08Apr2002",
1121
                        "hash": "7a25bc5b9a5393f46600a4939d357982",
1122
                    },
1123
                ],
1124
            },
1125
        )
1126
        d = compat.get_explanation_dict(entry)
1✔
1127
        assert "MPRelaxSet Potcar Correction" == d["corrections"][0]["name"]
1✔
1128

1129
    def test_energy_adjustments(self):
1✔
1130
        compat = MaterialsProject2020Compatibility(check_potcar_hash=False)
1✔
1131
        ggacompat = MaterialsProject2020Compatibility("GGA", check_potcar_hash=False)
1✔
1132

1133
        # Fe 4 Co 2 O 8 (Fe2CoO4)
1134
        entry = {
1✔
1135
            "@module": "pymatgen.entries.computed_entries",
1136
            "@class": "ComputedEntry",
1137
            "energy": -91.94962744,
1138
            "composition": defaultdict(float, {"Fe": 4.0, "Co": 2.0, "O": 8.0}),
1139
            "energy_adjustments": [],
1140
            "parameters": {
1141
                "run_type": "GGA+U",
1142
                "is_hubbard": True,
1143
                "pseudo_potential": {
1144
                    "functional": "PBE",
1145
                    "labels": ["Fe_pv", "Co", "O"],
1146
                    "pot_type": "paw",
1147
                },
1148
                "hubbards": {"Fe": 5.3, "Co": 3.32, "O": 0.0},
1149
                "potcar_symbols": ["PBE Fe_pv", "PBE Co", "PBE O"],
1150
                "oxide_type": "oxide",
1151
            },
1152
            "data": {"oxide_type": "oxide"},
1153
            "entry_id": "mp-753222",
1154
            "correction": 0,
1155
        }
1156
        entry = ComputedEntry.from_dict(entry)
1✔
1157

1158
        c = compat.process_entry(entry)
1✔
1159
        assert "MP2020 anion correction (oxide)" in [ea.name for ea in c.energy_adjustments]
1✔
1160
        assert "MP2020 GGA/GGA+U mixing correction (Fe)" in [ea.name for ea in c.energy_adjustments]
1✔
1161
        assert "MP2020 GGA/GGA+U mixing correction (Co)" in [ea.name for ea in c.energy_adjustments]
1✔
1162

1163
        for ea in c.energy_adjustments:
1✔
1164
            if ea.name == "MP2020 GGA/GGA+U mixing correction (Fe)":
1✔
1165
                assert ea.value == pytest.approx(-2.256 * 4)
1✔
1166
                assert ea.uncertainty == pytest.approx(0.0101 * 4)
1✔
1167
            elif ea.name == "MP2020 GGA/GGA+U mixing correction (Co)":
1✔
1168
                assert ea.value == pytest.approx(-1.638 * 2)
1✔
1169
                assert ea.uncertainty == pytest.approx(0.006 * 2)
1✔
1170
            elif ea.name == "MP2020 anion correction (oxide)":
1✔
1171
                assert ea.value == pytest.approx(-0.687 * 8)
1✔
1172
                assert ea.uncertainty == pytest.approx(0.002 * 8)
1✔
1173

1174
        entry.parameters["is_hubbard"] = False
1✔
1175
        del entry.parameters["hubbards"]
1✔
1176
        c = ggacompat.process_entry(entry)
1✔
1177
        assert "MP2020 GGA/GGA+U mixing correction" not in [ea.name for ea in c.energy_adjustments]
1✔
1178

1179
    def test_process_entries(self):
1✔
1180
        entries = self.compat.process_entries([self.entry1, self.entry2, self.entry3])
1✔
1181
        assert len(entries) == 2
1✔
1182

1183
    def test_config_file(self):
1✔
1184
        config_file = Path(PymatgenTest.TEST_FILES_DIR / "MP2020Compatibility_alternate.yaml")
1✔
1185
        compat = MaterialsProject2020Compatibility(config_file=config_file)
1✔
1186
        entry = compat.process_entry(self.entry1)
1✔
1187
        for ea in entry.energy_adjustments:
1✔
1188
            if ea.name == "MP2020 GGA/GGA+U mixing correction (Fe)":
1✔
1189
                assert ea.value == pytest.approx(-0.224 * 2)
1✔
1190

1191
    def test_msonable(self):
1✔
1192
        compat_dict = self.compat.as_dict()
1✔
1193
        decoder = MontyDecoder()
1✔
1194
        temp_compat = decoder.process_decoded(compat_dict)
1✔
1195
        assert isinstance(temp_compat, MaterialsProject2020Compatibility)
1✔
1196

1197

1198
class MITCompatibilityTest(unittest.TestCase):
1✔
1199
    def tearDown(self):
1✔
1200
        warnings.simplefilter("default")
1✔
1201

1202
    def setUp(self):
1✔
1203
        warnings.simplefilter("ignore")
1✔
1204
        self.compat = MITCompatibility(check_potcar_hash=True)
1✔
1205
        self.ggacompat = MITCompatibility("GGA", check_potcar_hash=True)
1✔
1206
        self.entry_O = ComputedEntry(
1✔
1207
            "Fe2O3",
1208
            -1,
1209
            correction=0.0,
1210
            parameters={
1211
                "is_hubbard": True,
1212
                "hubbards": {"Fe": 4.0, "O": 0},
1213
                "run_type": "GGA+U",
1214
                "potcar_spec": [
1215
                    {
1216
                        "titel": "PAW_PBE Fe 06Sep2000",
1217
                        "hash": "9530da8244e4dac17580869b4adab115",
1218
                    },
1219
                    {
1220
                        "titel": "PAW_PBE O 08Apr2002",
1221
                        "hash": "7a25bc5b9a5393f46600a4939d357982",
1222
                    },
1223
                ],
1224
            },
1225
        )
1226

1227
        self.entry_F = ComputedEntry(
1✔
1228
            "FeF3",
1229
            -2,
1230
            correction=0.0,
1231
            parameters={
1232
                "is_hubbard": True,
1233
                "hubbards": {"Fe": 4.0, "F": 0},
1234
                "run_type": "GGA+U",
1235
                "potcar_spec": [
1236
                    {
1237
                        "titel": "PAW_PBE Fe 06Sep2000",
1238
                        "hash": "9530da8244e4dac17580869b4adab115",
1239
                    },
1240
                    {
1241
                        "titel": "PAW_PBE F 08Apr2002",
1242
                        "hash": "180141c33d032bfbfff30b3bea9d23dd",
1243
                    },
1244
                ],
1245
            },
1246
        )
1247
        self.entry_S = ComputedEntry(
1✔
1248
            "FeS2",
1249
            -2,
1250
            correction=0.0,
1251
            parameters={
1252
                "is_hubbard": True,
1253
                "hubbards": {"Fe": 1.9, "S": 0},
1254
                "run_type": "GGA+U",
1255
                "potcar_spec": [
1256
                    {
1257
                        "titel": "PAW_PBE Fe 06Sep2000",
1258
                        "hash": "9530da8244e4dac17580869b4adab115",
1259
                    },
1260
                    {
1261
                        "titel": "PAW_PBE S 08Apr2002",
1262
                        "hash": "d368db6899d8839859bbee4811a42a88",
1263
                    },
1264
                ],
1265
            },
1266
        )
1267

1268
    def test_process_entry(self):
1✔
1269
        # Correct parameters
1270
        assert self.compat.process_entry(self.entry_O) is not None
1✔
1271
        assert self.compat.process_entry(self.entry_F) is not None
1✔
1272

1273
    def test_correction_value(self):
1✔
1274
        # Check actual correction
1275
        assert self.compat.process_entry(self.entry_O).correction == pytest.approx(-1.723 * 2 - 0.66975 * 3)
1✔
1276
        assert self.compat.process_entry(self.entry_F).correction == pytest.approx(-1.723)
1✔
1277
        assert self.compat.process_entry(self.entry_S).correction == pytest.approx(-1.113)
1✔
1278

1279
    def test_U_value(self):
1✔
1280
        # MIT should have a U value for Fe containing sulfides
1281
        assert self.compat.process_entry(self.entry_S) is not None
1✔
1282

1283
        # MIT should not have a U value for Ni containing sulfides
1284
        entry = ComputedEntry(
1✔
1285
            "NiS2",
1286
            -2,
1287
            correction=0.0,
1288
            parameters={
1289
                "is_hubbard": True,
1290
                "hubbards": {"Ni": 1.9, "S": 0},
1291
                "run_type": "GGA+U",
1292
                "potcar_spec": [
1293
                    {
1294
                        "titel": "PAW_PBE Ni 06Sep2000",
1295
                        "hash": "653f5772e68b2c7fd87ffd1086c0d710",
1296
                    },
1297
                    {
1298
                        "titel": "PAW_PBE S 08Apr2002",
1299
                        "hash": "d368db6899d8839859bbee4811a42a88",
1300
                    },
1301
                ],
1302
            },
1303
        )
1304

1305
        assert self.compat.process_entry(entry) is None
1✔
1306

1307
        entry = ComputedEntry(
1✔
1308
            "NiS2",
1309
            -2,
1310
            correction=0.0,
1311
            parameters={
1312
                "is_hubbard": True,
1313
                "hubbards": None,
1314
                "run_type": "GGA",
1315
                "potcar_spec": [
1316
                    {
1317
                        "titel": "PAW_PBE Ni 06Sep2000",
1318
                        "hash": "653f5772e68b2c7fd87ffd1086c0d710",
1319
                    },
1320
                    {
1321
                        "titel": "PAW_PBE S 08Apr2002",
1322
                        "hash": "d368db6899d8839859bbee4811a42a88",
1323
                    },
1324
                ],
1325
            },
1326
        )
1327

1328
        assert self.ggacompat.process_entry(entry) is not None
1✔
1329

1330
    def test_wrong_U_value(self):
1✔
1331
        # Wrong U value
1332
        entry = ComputedEntry(
1✔
1333
            "Fe2O3",
1334
            -1,
1335
            correction=0.0,
1336
            parameters={
1337
                "is_hubbard": True,
1338
                "hubbards": {"Fe": 5.2, "O": 0},
1339
                "run_type": "GGA+U",
1340
                "potcar_spec": [
1341
                    {
1342
                        "titel": "PAW_PBE Fe 06Sep2000",
1343
                        "hash": "9530da8244e4dac17580869b4adab115",
1344
                    },
1345
                    {
1346
                        "titel": "PAW_PBE O 08Apr2002",
1347
                        "hash": "7a25bc5b9a5393f46600a4939d357982",
1348
                    },
1349
                ],
1350
            },
1351
        )
1352

1353
        assert self.compat.process_entry(entry) is None
1✔
1354

1355
        # GGA run
1356
        entry = ComputedEntry(
1✔
1357
            "Fe2O3",
1358
            -1,
1359
            correction=0.0,
1360
            parameters={
1361
                "is_hubbard": False,
1362
                "hubbards": None,
1363
                "run_type": "GGA",
1364
                "potcar_spec": [
1365
                    {
1366
                        "titel": "PAW_PBE Fe 06Sep2000",
1367
                        "hash": "9530da8244e4dac17580869b4adab115",
1368
                    },
1369
                    {
1370
                        "titel": "PAW_PBE O 08Apr2002",
1371
                        "hash": "7a25bc5b9a5393f46600a4939d357982",
1372
                    },
1373
                ],
1374
            },
1375
        )
1376
        assert self.compat.process_entry(entry) is None
1✔
1377
        assert self.ggacompat.process_entry(entry) is not None
1✔
1378

1379
    def test_wrong_psp(self):
1✔
1380
        # Wrong psp
1381
        entry = ComputedEntry(
1✔
1382
            "Fe2O3",
1383
            -1,
1384
            correction=0.0,
1385
            parameters={
1386
                "is_hubbard": True,
1387
                "hubbards": {"Fe": 4.0, "O": 0},
1388
                "run_type": "GGA+U",
1389
                "potcar_spec": [
1390
                    {
1391
                        "titel": "PAW_PBE Fe_pv 06Sep2000",
1392
                        "hash": "994537de5c4122b7f1b77fb604476db4",
1393
                    },
1394
                    {
1395
                        "titel": "PAW_PBE O 08Apr2002",
1396
                        "hash": "7a25bc5b9a5393f46600a4939d357982",
1397
                    },
1398
                ],
1399
            },
1400
        )
1401
        assert self.compat.process_entry(entry) is None
1✔
1402

1403
    def test_element_processing(self):
1✔
1404
        # Testing processing of elements.
1405
        entry = ComputedEntry(
1✔
1406
            "O",
1407
            -1,
1408
            correction=0.0,
1409
            parameters={
1410
                "is_hubbard": False,
1411
                "hubbards": {},
1412
                "potcar_spec": [
1413
                    {
1414
                        "titel": "PAW_PBE O 08Apr2002",
1415
                        "hash": "7a25bc5b9a5393f46600a4939d357982",
1416
                    }
1417
                ],
1418
                "run_type": "GGA",
1419
            },
1420
        )
1421
        entry = self.compat.process_entry(entry)
1✔
1422
        assert entry.energy == pytest.approx(-1)
1✔
1423

1424
    def test_same_potcar_symbol(self):
1✔
1425
        # Same symbol different hash thus a different potcar
1426
        # Correct Hash Correct Symbol
1427
        entry = ComputedEntry(
1✔
1428
            "Fe2O3",
1429
            -1,
1430
            correction=0.0,
1431
            parameters={
1432
                "is_hubbard": True,
1433
                "hubbards": {"Fe": 4.0, "O": 0},
1434
                "run_type": "GGA+U",
1435
                "potcar_spec": [
1436
                    {
1437
                        "titel": "PAW_PBE Fe 06Sep2000",
1438
                        "hash": "9530da8244e4dac17580869b4adab115",
1439
                    },
1440
                    {
1441
                        "titel": "PAW_PBE O 08Apr2002",
1442
                        "hash": "7a25bc5b9a5393f46600a4939d357982",
1443
                    },
1444
                ],
1445
            },
1446
        )
1447
        # Incorrect Hash Correct Symbol
1448
        entry2 = ComputedEntry(
1✔
1449
            "Fe2O3",
1450
            -1,
1451
            correction=0.0,
1452
            parameters={
1453
                "is_hubbard": True,
1454
                "hubbards": {"Fe": 4.0, "O": 0},
1455
                "run_type": "GGA+U",
1456
                "potcar_spec": [
1457
                    {"titel": "PAW_PBE Fe 06Sep2000", "hash": "DifferentHash"},
1458
                    {
1459
                        "titel": "PAW_PBE O 08Apr2002",
1460
                        "hash": "7a25bc5b9a5393f46600a4939d357982",
1461
                    },
1462
                ],
1463
            },
1464
        )
1465

1466
        compat = MITCompatibility()
1✔
1467
        assert len(compat.process_entries([entry, entry2])) == 2
1✔
1468
        assert len(self.compat.process_entries([entry, entry2])) == 1
1✔
1469

1470
    def test_revert_to_symbols(self):
1✔
1471
        # Test that you can revert to potcar_symbols if potcar_spec is not present
1472
        compat = MITCompatibility()
1✔
1473
        entry = ComputedEntry(
1✔
1474
            "Fe2O3",
1475
            -1,
1476
            correction=0.0,
1477
            parameters={
1478
                "is_hubbard": True,
1479
                "hubbards": {"Fe": 4.0, "O": 0},
1480
                "run_type": "GGA+U",
1481
                "potcar_symbols": ["PAW_PBE Fe 06Sep2000", "PAW_PBE O 08Apr2002"],
1482
            },
1483
        )
1484

1485
        assert compat.process_entry(entry) is not None
1✔
1486
        # raise if check_potcar_hash is set
1487
        with pytest.raises(ValueError):
1✔
1488
            self.compat.process_entry(entry)
1✔
1489

1490
    def test_potcar_doenst_match_structure(self):
1✔
1491
        compat = MITCompatibility()
1✔
1492
        entry = ComputedEntry(
1✔
1493
            "Li2O3",
1494
            -1,
1495
            correction=0.0,
1496
            parameters={
1497
                "is_hubbard": True,
1498
                "hubbards": {"Fe": 4.0, "O": 0},
1499
                "run_type": "GGA+U",
1500
                "potcar_symbols": ["PAW_PBE Fe_pv 06Sep2000", "PAW_PBE O 08Apr2002"],
1501
            },
1502
        )
1503

1504
        assert compat.process_entry(entry) is None
1✔
1505

1506
    def test_potcar_spec_is_none(self):
1✔
1507
        compat = MITCompatibility(check_potcar_hash=True)
1✔
1508
        entry = ComputedEntry(
1✔
1509
            "Li2O3",
1510
            -1,
1511
            correction=0.0,
1512
            parameters={
1513
                "is_hubbard": True,
1514
                "hubbards": {"Fe": 4.0, "O": 0},
1515
                "run_type": "GGA+U",
1516
                "potcar_spec": [None, None],
1517
            },
1518
        )
1519

1520
        assert compat.process_entry(entry) is None
1✔
1521

1522
    def test_get_explanation_dict(self):
1✔
1523
        compat = MITCompatibility(check_potcar_hash=False)
1✔
1524
        entry = ComputedEntry(
1✔
1525
            "Fe2O3",
1526
            -1,
1527
            correction=0.0,
1528
            parameters={
1529
                "is_hubbard": True,
1530
                "hubbards": {"Fe": 4.0, "O": 0},
1531
                "run_type": "GGA+U",
1532
                "potcar_spec": [
1533
                    {
1534
                        "titel": "PAW_PBE Fe 06Sep2000",
1535
                        "hash": "994537de5c4122b7f1b77fb604476db4",
1536
                    },
1537
                    {
1538
                        "titel": "PAW_PBE O 08Apr2002",
1539
                        "hash": "7a25bc5b9a5393f46600a4939d357982",
1540
                    },
1541
                ],
1542
            },
1543
        )
1544
        d = compat.get_explanation_dict(entry)
1✔
1545
        assert "MITRelaxSet Potcar Correction" == d["corrections"][0]["name"]
1✔
1546

1547
    def test_msonable(self):
1✔
1548
        compat_dict = self.compat.as_dict()
1✔
1549
        decoder = MontyDecoder()
1✔
1550
        temp_compat = decoder.process_decoded(compat_dict)
1✔
1551
        assert isinstance(temp_compat, MITCompatibility)
1✔
1552

1553

1554
class OxideTypeCorrectionTest(unittest.TestCase):
1✔
1555
    def setUp(self):
1✔
1556
        self.compat = MITCompatibility(check_potcar_hash=True)
1✔
1557

1558
    def test_no_struct_compat(self):
1✔
1559
        lio2_entry_nostruct = ComputedEntry(
1✔
1560
            Composition("Li2O4"),
1561
            -3,
1562
            data={"oxide_type": "superoxide"},
1563
            parameters={
1564
                "is_hubbard": False,
1565
                "hubbards": None,
1566
                "run_type": "GGA",
1567
                "potcar_spec": [
1568
                    {
1569
                        "titel": "PAW_PBE Li 17Jan2003",
1570
                        "hash": "65e83282d1707ec078c1012afbd05be8",
1571
                    },
1572
                    {
1573
                        "titel": "PAW_PBE O 08Apr2002",
1574
                        "hash": "7a25bc5b9a5393f46600a4939d357982",
1575
                    },
1576
                ],
1577
            },
1578
        )
1579

1580
        lio2_entry_corrected = self.compat.process_entry(lio2_entry_nostruct)
1✔
1581
        assert lio2_entry_corrected.energy == pytest.approx(-3 - 0.13893 * 4)
1✔
1582

1583
    def test_process_entry_superoxide(self):
1✔
1584
        el_li = Element("Li")
1✔
1585
        el_o = Element("O")
1✔
1586
        latt = Lattice([[3.985034, 0.0, 0.0], [0.0, 4.881506, 0.0], [0.0, 0.0, 2.959824]])
1✔
1587
        elts = [el_li, el_li, el_o, el_o, el_o, el_o]
1✔
1588
        coords = []
1✔
1589
        coords.append([0.500000, 0.500000, 0.500000])
1✔
1590
        coords.append([0.0, 0.0, 0.0])
1✔
1591
        coords.append([0.632568, 0.085090, 0.500000])
1✔
1592
        coords.append([0.367432, 0.914910, 0.500000])
1✔
1593
        coords.append([0.132568, 0.414910, 0.000000])
1✔
1594
        coords.append([0.867432, 0.585090, 0.000000])
1✔
1595
        struct = Structure(latt, elts, coords)
1✔
1596
        lio2_entry = ComputedStructureEntry(
1✔
1597
            struct,
1598
            -3,
1599
            parameters={
1600
                "is_hubbard": False,
1601
                "hubbards": None,
1602
                "run_type": "GGA",
1603
                "potcar_spec": [
1604
                    {
1605
                        "titel": "PAW_PBE Li 17Jan2003",
1606
                        "hash": "65e83282d1707ec078c1012afbd05be8",
1607
                    },
1608
                    {
1609
                        "titel": "PAW_PBE O 08Apr2002",
1610
                        "hash": "7a25bc5b9a5393f46600a4939d357982",
1611
                    },
1612
                ],
1613
            },
1614
        )
1615

1616
        lio2_entry_corrected = self.compat.process_entry(lio2_entry)
1✔
1617
        assert lio2_entry_corrected.energy == pytest.approx(-3 - 0.13893 * 4)
1✔
1618

1619
    def test_process_entry_peroxide(self):
1✔
1620
        latt = Lattice.from_parameters(3.159597, 3.159572, 7.685205, 89.999884, 89.999674, 60.000510)
1✔
1621
        el_li = Element("Li")
1✔
1622
        el_o = Element("O")
1✔
1623
        elts = [el_li, el_li, el_li, el_li, el_o, el_o, el_o, el_o]
1✔
1624
        coords = [
1✔
1625
            [0.666656, 0.666705, 0.750001],
1626
            [0.333342, 0.333378, 0.250001],
1627
            [0.000001, 0.000041, 0.500001],
1628
            [0.000001, 0.000021, 0.000001],
1629
            [0.333347, 0.333332, 0.649191],
1630
            [0.333322, 0.333353, 0.850803],
1631
            [0.666666, 0.666686, 0.350813],
1632
            [0.666665, 0.666684, 0.149189],
1633
        ]
1634
        struct = Structure(latt, elts, coords)
1✔
1635
        li2o2_entry = ComputedStructureEntry(
1✔
1636
            struct,
1637
            -3,
1638
            parameters={
1639
                "is_hubbard": False,
1640
                "hubbards": None,
1641
                "run_type": "GGA",
1642
                "potcar_spec": [
1643
                    {
1644
                        "titel": "PAW_PBE Li 17Jan2003",
1645
                        "hash": "65e83282d1707ec078c1012afbd05be8",
1646
                    },
1647
                    {
1648
                        "titel": "PAW_PBE O 08Apr2002",
1649
                        "hash": "7a25bc5b9a5393f46600a4939d357982",
1650
                    },
1651
                ],
1652
            },
1653
        )
1654

1655
        li2o2_entry_corrected = self.compat.process_entry(li2o2_entry)
1✔
1656
        assert li2o2_entry_corrected.energy == pytest.approx(-3 - 0.44317 * 4)
1✔
1657

1658
    def test_process_entry_ozonide(self):
1✔
1659
        el_li = Element("Li")
1✔
1660
        el_o = Element("O")
1✔
1661
        elts = [el_li, el_o, el_o, el_o]
1✔
1662
        latt = Lattice.from_parameters(3.999911, 3.999911, 3.999911, 133.847504, 102.228244, 95.477342)
1✔
1663
        coords = [
1✔
1664
            [0.513004, 0.513004, 1.000000],
1665
            [0.017616, 0.017616, 0.000000],
1666
            [0.649993, 0.874790, 0.775203],
1667
            [0.099587, 0.874790, 0.224797],
1668
        ]
1669
        struct = Structure(latt, elts, coords)
1✔
1670
        lio3_entry = ComputedStructureEntry(
1✔
1671
            struct,
1672
            -3,
1673
            parameters={
1674
                "is_hubbard": False,
1675
                "hubbards": None,
1676
                "run_type": "GGA",
1677
                "potcar_spec": [
1678
                    {
1679
                        "titel": "PAW_PBE Li 17Jan2003",
1680
                        "hash": "65e83282d1707ec078c1012afbd05be8",
1681
                    },
1682
                    {
1683
                        "titel": "PAW_PBE O 08Apr2002",
1684
                        "hash": "7a25bc5b9a5393f46600a4939d357982",
1685
                    },
1686
                ],
1687
            },
1688
        )
1689

1690
        lio3_entry_corrected = self.compat.process_entry(lio3_entry)
1✔
1691
        assert lio3_entry_corrected.energy == pytest.approx(-3.0)
1✔
1692

1693
    def test_process_entry_oxide(self):
1✔
1694
        el_li = Element("Li")
1✔
1695
        el_o = Element("O")
1✔
1696
        elts = [el_li, el_li, el_o]
1✔
1697
        latt = Lattice.from_parameters(3.278, 3.278, 3.278, 60, 60, 60)
1✔
1698
        coords = [[0.25, 0.25, 0.25], [0.75, 0.75, 0.75], [0.0, 0.0, 0.0]]
1✔
1699
        struct = Structure(latt, elts, coords)
1✔
1700
        li2o_entry = ComputedStructureEntry(
1✔
1701
            struct,
1702
            -3,
1703
            parameters={
1704
                "is_hubbard": False,
1705
                "hubbards": None,
1706
                "run_type": "GGA",
1707
                "potcar_spec": [
1708
                    {
1709
                        "titel": "PAW_PBE Li 17Jan2003",
1710
                        "hash": "65e83282d1707ec078c1012afbd05be8",
1711
                    },
1712
                    {
1713
                        "titel": "PAW_PBE O 08Apr2002",
1714
                        "hash": "7a25bc5b9a5393f46600a4939d357982",
1715
                    },
1716
                ],
1717
            },
1718
        )
1719

1720
        li2o_entry_corrected = self.compat.process_entry(li2o_entry)
1✔
1721
        assert li2o_entry_corrected.energy == pytest.approx(-3.0 - 0.66975)
1✔
1722

1723

1724
class SulfideTypeCorrection2020Test(unittest.TestCase):
1✔
1725
    def setUp(self):
1✔
1726
        self.compat = MaterialsProject2020Compatibility(check_potcar_hash=False)
1✔
1727

1728
    def test_struct_no_struct(self):
1✔
1729
        # Processing an Entry should produce the same correction whether or not
1730
        # that entry has a Structure attached to it.
1731

1732
        # Na2S2, entry mp-2400, with and without structure
1733
        from collections import defaultdict
1✔
1734

1735
        entry_struct_as_dict = {
1✔
1736
            "@module": "pymatgen.entries.computed_entries",
1737
            "@class": "ComputedStructureEntry",
1738
            "energy": -28.42580746,
1739
            "composition": defaultdict(float, {"Na": 4.0, "S": 4.0}),
1740
            "correction": 0,
1741
            "parameters": {
1742
                "run_type": "GGA",
1743
                "is_hubbard": False,
1744
                "pseudo_potential": {
1745
                    "functional": "PBE",
1746
                    "labels": ["Na_pv", "S"],
1747
                    "pot_type": "paw",
1748
                },
1749
                "hubbards": {},
1750
                "potcar_symbols": ["PBE Na_pv", "PBE S"],
1751
                "oxide_type": "None",
1752
            },
1753
            "data": {"oxide_type": "None"},
1754
            "entry_id": "mp-2400",
1755
            "structure": {
1756
                "@module": "pymatgen.core.structure",
1757
                "@class": "Structure",
1758
                "charge": None,
1759
                "lattice": {
1760
                    "matrix": [
1761
                        [4.5143094, 0.0, 0.0],
1762
                        [-2.2571547, 3.90950662, 0.0],
1763
                        [0.0, 0.0, 10.28414905],
1764
                    ],
1765
                    "a": 4.5143094,
1766
                    "b": 4.514309399183436,
1767
                    "c": 10.28414905,
1768
                    "alpha": 90.0,
1769
                    "beta": 90.0,
1770
                    "gamma": 120.00000000598358,
1771
                    "volume": 181.50209256783256,
1772
                },
1773
                "sites": [
1774
                    {
1775
                        "species": [{"element": "Na", "occu": 1}],
1776
                        "abc": [0.0, 0.0, 0.0],
1777
                        "xyz": [0.0, 0.0, 0.0],
1778
                        "label": "Na",
1779
                        "properties": {"magmom": 0.0},
1780
                    },
1781
                    {
1782
                        "species": [{"element": "Na", "occu": 1}],
1783
                        "abc": [0.0, 0.0, 0.5],
1784
                        "xyz": [0.0, 0.0, 5.142074525],
1785
                        "label": "Na",
1786
                        "properties": {"magmom": 0.0},
1787
                    },
1788
                    {
1789
                        "species": [{"element": "Na", "occu": 1}],
1790
                        "abc": [0.33333333, 0.66666667, 0.25],
1791
                        "xyz": [
1792
                            -2.2571547075855847e-08,
1793
                            2.6063377596983557,
1794
                            2.5710372625,
1795
                        ],
1796
                        "label": "Na",
1797
                        "properties": {"magmom": 0.0},
1798
                    },
1799
                    {
1800
                        "species": [{"element": "Na", "occu": 1}],
1801
                        "abc": [0.66666667, 0.33333333, 0.75],
1802
                        "xyz": [2.2571547225715474, 1.3031688603016447, 7.7131117875],
1803
                        "label": "Na",
1804
                        "properties": {"magmom": 0.0},
1805
                    },
1806
                    {
1807
                        "species": [{"element": "S", "occu": 1}],
1808
                        "abc": [0.33333333, 0.66666667, 0.644551],
1809
                        "xyz": [
1810
                            -2.2571547075855847e-08,
1811
                            2.6063377596983557,
1812
                            6.62865855432655,
1813
                        ],
1814
                        "label": "S",
1815
                        "properties": {"magmom": 0.0},
1816
                    },
1817
                    {
1818
                        "species": [{"element": "S", "occu": 1}],
1819
                        "abc": [0.66666667, 0.33333333, 0.144551],
1820
                        "xyz": [
1821
                            2.2571547225715474,
1822
                            1.3031688603016447,
1823
                            1.4865840293265502,
1824
                        ],
1825
                        "label": "S",
1826
                        "properties": {"magmom": 0.0},
1827
                    },
1828
                    {
1829
                        "species": [{"element": "S", "occu": 1}],
1830
                        "abc": [0.66666667, 0.33333333, 0.355449],
1831
                        "xyz": [
1832
                            2.2571547225715474,
1833
                            1.3031688603016447,
1834
                            3.65549049567345,
1835
                        ],
1836
                        "label": "S",
1837
                        "properties": {"magmom": 0.0},
1838
                    },
1839
                    {
1840
                        "species": [{"element": "S", "occu": 1}],
1841
                        "abc": [0.33333333, 0.66666667, 0.855449],
1842
                        "xyz": [
1843
                            -2.2571547075855847e-08,
1844
                            2.6063377596983557,
1845
                            8.79756502067345,
1846
                        ],
1847
                        "label": "S",
1848
                        "properties": {"magmom": 0.0},
1849
                    },
1850
                ],
1851
            },
1852
        }
1853

1854
        entry_no_struct_as_dict = {
1✔
1855
            "@module": "pymatgen.entries.computed_entries",
1856
            "@class": "ComputedEntry",
1857
            "energy": -28.42580746,
1858
            "composition": defaultdict(float, {"Na": 4.0, "S": 4.0}),
1859
            "correction": 0,
1860
            "parameters": {
1861
                "run_type": "GGA",
1862
                "is_hubbard": False,
1863
                "pseudo_potential": {
1864
                    "functional": "PBE",
1865
                    "labels": ["Na_pv", "S"],
1866
                    "pot_type": "paw",
1867
                },
1868
                "hubbards": {},
1869
                "potcar_symbols": ["PBE Na_pv", "PBE S"],
1870
                "oxide_type": "None",
1871
            },
1872
            "data": {"oxide_type": "None"},
1873
            "entry_id": "mp-2400",
1874
        }
1875

1876
        na2s2_entry_struct = ComputedStructureEntry.from_dict(entry_struct_as_dict)
1✔
1877
        na2s2_entry_nostruct = ComputedEntry.from_dict(entry_no_struct_as_dict)
1✔
1878

1879
        struct_corrected = self.compat.process_entry(na2s2_entry_struct)
1✔
1880
        nostruct_corrected = self.compat.process_entry(na2s2_entry_nostruct)
1✔
1881

1882
        assert struct_corrected.correction == pytest.approx(nostruct_corrected.correction)
1✔
1883

1884

1885
class OxideTypeCorrectionNoPeroxideCorrTest(unittest.TestCase):
1✔
1886
    def setUp(self):
1✔
1887
        self.compat = MITCompatibility(correct_peroxide=False)
1✔
1888

1889
    def test_oxide_energy_corr(self):
1✔
1890
        el_li = Element("Li")
1✔
1891
        el_o = Element("O")
1✔
1892
        elts = [el_li, el_li, el_o]
1✔
1893
        latt = Lattice.from_parameters(3.278, 3.278, 3.278, 60, 60, 60)
1✔
1894
        coords = [[0.25, 0.25, 0.25], [0.75, 0.75, 0.75], [0.0, 0.0, 0.0]]
1✔
1895
        struct = Structure(latt, elts, coords)
1✔
1896
        li2o_entry = ComputedStructureEntry(
1✔
1897
            struct,
1898
            -3,
1899
            parameters={
1900
                "is_hubbard": False,
1901
                "hubbards": None,
1902
                "run_type": "GGA",
1903
                "potcar_spec": [
1904
                    {
1905
                        "titel": "PAW_PBE Li 17Jan2003",
1906
                        "hash": "65e83282d1707ec078c1012afbd05be8",
1907
                    },
1908
                    {
1909
                        "titel": "PAW_PBE O 08Apr2002",
1910
                        "hash": "7a25bc5b9a5393f46600a4939d357982",
1911
                    },
1912
                ],
1913
            },
1914
        )
1915

1916
        li2o_entry_corrected = self.compat.process_entry(li2o_entry)
1✔
1917
        assert li2o_entry_corrected.energy == pytest.approx(-3.0 - 0.66975)
1✔
1918

1919
    def test_peroxide_energy_corr(self):
1✔
1920
        latt = Lattice.from_parameters(3.159597, 3.159572, 7.685205, 89.999884, 89.999674, 60.000510)
1✔
1921
        el_li = Element("Li")
1✔
1922
        el_o = Element("O")
1✔
1923
        elts = [el_li, el_li, el_li, el_li, el_o, el_o, el_o, el_o]
1✔
1924
        coords = [
1✔
1925
            [0.666656, 0.666705, 0.750001],
1926
            [0.333342, 0.333378, 0.250001],
1927
            [0.000001, 0.000041, 0.500001],
1928
            [0.000001, 0.000021, 0.000001],
1929
            [0.333347, 0.333332, 0.649191],
1930
            [0.333322, 0.333353, 0.850803],
1931
            [0.666666, 0.666686, 0.350813],
1932
            [0.666665, 0.666684, 0.149189],
1933
        ]
1934
        struct = Structure(latt, elts, coords)
1✔
1935
        li2o2_entry = ComputedStructureEntry(
1✔
1936
            struct,
1937
            -3,
1938
            parameters={
1939
                "is_hubbard": False,
1940
                "hubbards": None,
1941
                "run_type": "GGA",
1942
                "potcar_spec": [
1943
                    {
1944
                        "titel": "PAW_PBE Li 17Jan2003",
1945
                        "hash": "65e83282d1707ec078c1012afbd05be8",
1946
                    },
1947
                    {
1948
                        "titel": "PAW_PBE O 08Apr2002",
1949
                        "hash": "7a25bc5b9a5393f46600a4939d357982",
1950
                    },
1951
                ],
1952
            },
1953
        )
1954

1955
        li2o2_entry_corrected = self.compat.process_entry(li2o2_entry)
1✔
1956
        with pytest.raises(AssertionError):
1✔
1957
            self.assertAlmostEqual(*(li2o2_entry_corrected.energy, -3 - 0.44317 * 4, 4))
1✔
1958
        assert li2o2_entry_corrected.energy == pytest.approx(-3 - 0.66975 * 4)
1✔
1959

1960
    def test_ozonide(self):
1✔
1961
        el_li = Element("Li")
1✔
1962
        el_o = Element("O")
1✔
1963
        elts = [el_li, el_o, el_o, el_o]
1✔
1964
        latt = Lattice.from_parameters(3.999911, 3.999911, 3.999911, 133.847504, 102.228244, 95.477342)
1✔
1965
        coords = [
1✔
1966
            [0.513004, 0.513004, 1.000000],
1967
            [0.017616, 0.017616, 0.000000],
1968
            [0.649993, 0.874790, 0.775203],
1969
            [0.099587, 0.874790, 0.224797],
1970
        ]
1971
        struct = Structure(latt, elts, coords)
1✔
1972
        lio3_entry = ComputedStructureEntry(
1✔
1973
            struct,
1974
            -3,
1975
            parameters={
1976
                "is_hubbard": False,
1977
                "hubbards": None,
1978
                "run_type": "GGA",
1979
                "potcar_spec": [
1980
                    {
1981
                        "titel": "PAW_PBE Li 17Jan2003",
1982
                        "hash": "65e83282d1707ec078c1012afbd05be8",
1983
                    },
1984
                    {
1985
                        "titel": "PAW_PBE O 08Apr2002",
1986
                        "hash": "7a25bc5b9a5393f46600a4939d357982",
1987
                    },
1988
                ],
1989
            },
1990
        )
1991

1992
        lio3_entry_corrected = self.compat.process_entry(lio3_entry)
1✔
1993
        assert lio3_entry_corrected.energy == pytest.approx(-3.0 - 3 * 0.66975)
1✔
1994

1995

1996
class TestMaterialsProjectAqueousCompatibility:
1✔
1997
    """
1998
    Test MaterialsProjectAqueousCompatibility
1999

2000
    -x- formation energy of H2O should always be -2.458 eV/H2O
2001
    -x- H2 energy should always be the same value
2002
    -x- H2O energy should always be the same value
2003
    -x- Should get warnings if you init without all energy args
2004
    -x- Should get CompatibilityError if you get_entry without all energy args
2005
    -x- energy args should auto-populate from entries passed to process_entries
2006
    -x- check compound entropies appropriately added
2007
    -x- check hydrate adjustment appropriately applied
2008

2009
    Notes:
2010
        Argument values from MaterialsProjectCompatibility as of April 2020:
2011
            corrected DFT energy of H2O = -15.5875 eV/H2O (mp-697111) or -5.195 eV/atom
2012
            corrected DFT energy of O2 = -4.9276 eV/atom (mp-12957)
2013
            total energy corrections applied to H2O (eV/H2O) -0.70229 eV/H2O or -0.234 eV/atom
2014
    """
2015

2016
    def test_h_h2o_energy_with_args_single(self):
1✔
2017
        compat = MaterialsProjectAqueousCompatibility(
1✔
2018
            o2_energy=-4.9276,
2019
            h2o_energy=-5,
2020
            h2o_adjustments=-0.234,
2021
            solid_compat=None,
2022
        )
2023

2024
        h2o_entry_1 = ComputedEntry(Composition("H2O"), -15)  # -5 eV/atom
1✔
2025
        h2o_entry_2 = ComputedEntry(Composition("H4O2"), -6)  # -1 eV/atom
1✔
2026
        h2_entry_1 = ComputedEntry(Composition("H8"), -100)  # -12.5 eV/atom
1✔
2027
        h2_entry_2 = ComputedEntry(Composition("H2"), -16)  # -8 eV/atom
1✔
2028

2029
        for entry in [h2o_entry_1, h2o_entry_2]:
1✔
2030
            compat.process_entries(entry)
1✔
2031

2032
        for entry in [h2_entry_1, h2_entry_2]:
1✔
2033
            with pytest.warns(UserWarning, match="Processing single H2 entries"):
1✔
2034
                compat.process_entries(entry)
1✔
2035

2036
        # the corrections should set the energy of any H2 polymorph the same, because
2037
        # we have only processed one entry at time. Energy differences of H2O
2038
        # polymorphs should be preserved.
2039
        assert h2o_entry_2.energy_per_atom == pytest.approx(h2o_entry_1.energy_per_atom + 4)
1✔
2040
        assert h2_entry_2.energy_per_atom == pytest.approx(h2_entry_1.energy_per_atom)
1✔
2041

2042
        o2_entry_1 = ComputedEntry(Composition("O2"), -4.9276 * 2)
1✔
2043
        o2_entry_1 = compat.process_entries(o2_entry_1)[0]
1✔
2044

2045
        h2o_form_e = 3 * h2o_entry_1.energy_per_atom - 2 * h2_entry_2.energy_per_atom - o2_entry_1.energy_per_atom
1✔
2046
        assert h2o_form_e == pytest.approx(MU_H2O)
1✔
2047

2048
    def test_h_h2o_energy_with_args_multi(self):
1✔
2049
        compat = MaterialsProjectAqueousCompatibility(
1✔
2050
            o2_energy=-4.9276,
2051
            h2o_energy=-5,
2052
            h2o_adjustments=-0.234,
2053
            solid_compat=None,
2054
        )
2055

2056
        h2o_entry_1 = ComputedEntry(Composition("H2O"), -15)  # -5 eV/atom
1✔
2057
        h2o_entry_2 = ComputedEntry(Composition("H4O2"), -6)  # -1 eV/atom
1✔
2058
        h2_entry_1 = ComputedEntry(Composition("H8"), -100)  # -12.5 eV/atom
1✔
2059
        h2_entry_2 = ComputedEntry(Composition("H2"), -16)  # -8 eV/atom
1✔
2060

2061
        compat.process_entries([h2o_entry_1, h2o_entry_2, h2_entry_1, h2_entry_2])
1✔
2062

2063
        # Energy differences of H2O and H2 polymorphs should be preserved.
2064
        assert h2o_entry_2.energy_per_atom == pytest.approx(h2o_entry_1.energy_per_atom + 4)
1✔
2065
        assert h2_entry_2.energy_per_atom == pytest.approx(h2_entry_1.energy_per_atom + 4.5)
1✔
2066

2067
        o2_entry_1 = ComputedEntry(Composition("O2"), -4.9276 * 2)
1✔
2068
        o2_entry_1 = compat.process_entries(o2_entry_1)[0]
1✔
2069

2070
        h2o_form_e = 3 * h2o_entry_1.energy_per_atom - 2 * h2_entry_1.energy_per_atom - o2_entry_1.energy_per_atom
1✔
2071
        assert h2o_form_e == pytest.approx(MU_H2O)
1✔
2072

2073
    def test_h_h2o_energy_no_args(self):
1✔
2074
        with pytest.warns(UserWarning, match="You did not provide the required O2 and H2O energies."):
1✔
2075
            compat = MaterialsProjectAqueousCompatibility(solid_compat=None)
1✔
2076

2077
        h2o_entry_1 = ComputedEntry(Composition("H2O"), (-5.195 + 0.234) * 3, correction=-0.234 * 3)  # -5.195 eV/atom
1✔
2078
        h2o_entry_2 = ComputedEntry(Composition("H4O2"), -6)  # -1 eV/atom
1✔
2079
        h2_entry_1 = ComputedEntry(Composition("H8"), -100)  # -12.5 eV/atom``
1✔
2080
        h2_entry_2 = ComputedEntry(Composition("H2"), -16)  # -8 eV/atom
1✔
2081
        o2_entry_1 = ComputedEntry(Composition("O2"), -4.9276 * 2)
1✔
2082

2083
        with pytest.raises(CompatibilityError, match="Either specify the energies as arguments to "):
1✔
2084
            compat.get_adjustments(h2_entry_1)
1✔
2085

2086
        compat.process_entries([h2o_entry_1, h2o_entry_2, h2_entry_1, h2_entry_2, o2_entry_1])
1✔
2087

2088
        assert compat.o2_energy == -4.9276
1✔
2089
        assert compat.h2o_energy == -5.195
1✔
2090
        assert compat.h2o_adjustments == -0.234
1✔
2091

2092
        # the corrections should preserve the difference in energy among H2O and H2 polymorphs
2093
        assert h2o_entry_2.energy_per_atom == pytest.approx(h2o_entry_1.energy_per_atom + 4.195)
1✔
2094
        assert h2_entry_2.energy_per_atom == pytest.approx(h2_entry_1.energy_per_atom + 4.5)
1✔
2095

2096
        # the water formation energy, calculated from the lowest energy polymorphs,
2097
        # should equal the experimental value
2098
        h2o_form_e = 3 * h2o_entry_1.energy_per_atom - 2 * h2_entry_1.energy_per_atom - o2_entry_1.energy_per_atom
1✔
2099
        assert h2o_form_e == pytest.approx(MU_H2O)
1✔
2100

2101
    def test_compound_entropy(self):
1✔
2102
        compat = MaterialsProjectAqueousCompatibility(
1✔
2103
            o2_energy=-10, h2o_energy=-20, h2o_adjustments=-0.5, solid_compat=None
2104
        )
2105

2106
        o2_entry_1 = ComputedEntry(Composition("O2"), -4.9276 * 2)
1✔
2107

2108
        initial_energy = o2_entry_1.energy_per_atom
1✔
2109
        o2_entry_1 = compat.process_entries(o2_entry_1)[0]
1✔
2110
        processed_energy = o2_entry_1.energy_per_atom
1✔
2111

2112
        assert initial_energy - processed_energy == pytest.approx(compat.cpd_entropies["O2"])
1✔
2113

2114
    def test_hydrate_adjustment(self):
1✔
2115
        compat = MaterialsProjectAqueousCompatibility(
1✔
2116
            o2_energy=-10, h2o_energy=-20, h2o_adjustments=-0.5, solid_compat=None
2117
        )
2118

2119
        hydrate_entry = ComputedEntry(Composition("FeH4O2"), -10)
1✔
2120

2121
        initial_energy = hydrate_entry.energy
1✔
2122
        hydrate_entry = compat.process_entries(hydrate_entry)[0]
1✔
2123
        processed_energy = hydrate_entry.energy
1✔
2124

2125
        assert initial_energy - processed_energy == pytest.approx(2 * (compat.h2o_adjustments * 3 + MU_H2O))
1✔
2126

2127

2128
class AqueousCorrectionTest(unittest.TestCase):
1✔
2129
    def setUp(self):
1✔
2130
        module_dir = os.path.dirname(os.path.abspath(__file__))
1✔
2131
        fp = os.path.join(module_dir, os.path.pardir, "MITCompatibility.yaml")
1✔
2132
        self.corr = AqueousCorrection(fp)
1✔
2133

2134
    def test_compound_energy(self):
1✔
2135
        O2_entry = self.corr.correct_entry(
1✔
2136
            ComputedEntry(Composition("O2"), -4.9355 * 2, parameters={"run_type": "GGA"})
2137
        )
2138
        H2_entry = self.corr.correct_entry(ComputedEntry(Composition("H2"), 3, parameters={"run_type": "GGA"}))
1✔
2139
        H2O_entry = self.corr.correct_entry(ComputedEntry(Composition("H2O"), 3, parameters={"run_type": "GGA"}))
1✔
2140
        H2O_formation_energy = H2O_entry.energy - (H2_entry.energy + O2_entry.energy / 2.0)
1✔
2141
        assert H2O_formation_energy == pytest.approx(-2.46)
1✔
2142

2143
        entry = ComputedEntry(Composition("H2O"), -16, parameters={"run_type": "GGA"})
1✔
2144
        entry = self.corr.correct_entry(entry)
1✔
2145
        assert entry.energy == pytest.approx(-14.916)
1✔
2146

2147
        entry = ComputedEntry(Composition("H2O"), -24, parameters={"run_type": "GGA"})
1✔
2148
        entry = self.corr.correct_entry(entry)
1✔
2149
        assert entry.energy == pytest.approx(-14.916)
1✔
2150

2151
        entry = ComputedEntry(Composition("Cl"), -24, parameters={"run_type": "GGA"})
1✔
2152
        entry = self.corr.correct_entry(entry)
1✔
2153
        assert entry.energy == pytest.approx(-24.344373)
1✔
2154

2155

2156
class MITAqueousCompatibilityTest(unittest.TestCase):
1✔
2157
    def setUp(self):
1✔
2158
        self.compat = MITCompatibility(check_potcar_hash=True)
1✔
2159
        self.aqcompat = MITAqueousCompatibility(check_potcar_hash=True)
1✔
2160
        module_dir = os.path.dirname(os.path.abspath(__file__))
1✔
2161
        fp = os.path.join(module_dir, os.path.pardir, "MITCompatibility.yaml")
1✔
2162
        self.aqcorr = AqueousCorrection(fp)
1✔
2163

2164
    def test_aqueous_compat(self):
1✔
2165
        el_li = Element("Li")
1✔
2166
        el_o = Element("O")
1✔
2167
        el_h = Element("H")
1✔
2168
        latt = Lattice.from_parameters(3.565276, 3.565276, 4.384277, 90.000000, 90.000000, 90.000000)
1✔
2169
        elts = [el_h, el_h, el_li, el_li, el_o, el_o]
1✔
2170
        coords = [
1✔
2171
            [0.000000, 0.500000, 0.413969],
2172
            [0.500000, 0.000000, 0.586031],
2173
            [0.000000, 0.000000, 0.000000],
2174
            [0.500000, 0.500000, 0.000000],
2175
            [0.000000, 0.500000, 0.192672],
2176
            [0.500000, 0.000000, 0.807328],
2177
        ]
2178
        struct = Structure(latt, elts, coords)
1✔
2179
        lioh_entry = ComputedStructureEntry(
1✔
2180
            struct,
2181
            -3,
2182
            parameters={
2183
                "is_hubbard": False,
2184
                "hubbards": None,
2185
                "run_type": "GGA",
2186
                "potcar_spec": [
2187
                    {
2188
                        "titel": "PAW_PBE Li 17Jan2003",
2189
                        "hash": "65e83282d1707ec078c1012afbd05be8",
2190
                    },
2191
                    {
2192
                        "titel": "PAW_PBE O 08Apr2002",
2193
                        "hash": "7a25bc5b9a5393f46600a4939d357982",
2194
                    },
2195
                    {
2196
                        "titel": "PAW_PBE H 15Jun2001",
2197
                        "hash": "bb43c666e3d36577264afe07669e9582",
2198
                    },
2199
                ],
2200
            },
2201
        )
2202
        lioh_entry_compat = self.compat.process_entry(lioh_entry)
1✔
2203
        lioh_entry_compat_aqcorr = self.aqcorr.correct_entry(lioh_entry_compat)
1✔
2204
        lioh_entry_aqcompat = self.aqcompat.process_entry(lioh_entry)
1✔
2205
        assert lioh_entry_compat_aqcorr.energy == pytest.approx(lioh_entry_aqcompat.energy)
1✔
2206

2207
    def test_potcar_doenst_match_structure(self):
1✔
2208
        compat = MITCompatibility()
1✔
2209
        el_li = Element("Li")
1✔
2210
        el_o = Element("O")
1✔
2211
        el_h = Element("H")
1✔
2212
        latt = Lattice.from_parameters(3.565276, 3.565276, 4.384277, 90.000000, 90.000000, 90.000000)
1✔
2213
        elts = [el_h, el_h, el_li, el_li, el_o, el_o]
1✔
2214
        coords = [
1✔
2215
            [0.000000, 0.500000, 0.413969],
2216
            [0.500000, 0.000000, 0.586031],
2217
            [0.000000, 0.000000, 0.000000],
2218
            [0.500000, 0.500000, 0.000000],
2219
            [0.000000, 0.500000, 0.192672],
2220
            [0.500000, 0.000000, 0.807328],
2221
        ]
2222
        struct = Structure(latt, elts, coords)
1✔
2223

2224
        lioh_entry = ComputedStructureEntry(
1✔
2225
            struct,
2226
            -3,
2227
            parameters={
2228
                "is_hubbard": False,
2229
                "hubbards": None,
2230
                "run_type": "GGA",
2231
                "potcar_symbols": ["PAW_PBE Fe 17Jan2003", "PAW_PBE O 08Apr2002", "PAW_PBE H 15Jun2001"],
2232
            },
2233
        )
2234

2235
        assert compat.process_entry(lioh_entry) is None
1✔
2236

2237
    def test_msonable(self):
1✔
2238
        compat_dict = self.aqcompat.as_dict()
1✔
2239
        decoder = MontyDecoder()
1✔
2240
        temp_compat = decoder.process_decoded(compat_dict)
1✔
2241
        assert isinstance(temp_compat, MITAqueousCompatibility)
1✔
2242

2243
    def test_dont_error_on_weird_elements(self):
1✔
2244
        entry = ComputedEntry(
1✔
2245
            "AmSi",
2246
            -1,
2247
            correction=0.0,
2248
            parameters={
2249
                "potcar_spec": [
2250
                    {
2251
                        "titel": "PAW_PBE Am 08May2007",
2252
                        "hash": "ed5eebd8a143e35a0c19e9f8a2c42a93",
2253
                    },
2254
                    {
2255
                        "titel": "PAW_PBE Si 05Jan2001",
2256
                        "hash": "b2b0ea6feb62e7cde209616683b8f7f5",
2257
                    },
2258
                ]
2259
            },
2260
        )
2261
        assert self.compat.process_entry(entry) is None
1✔
2262

2263

2264
class CorrectionErrors2020CompatibilityTest(unittest.TestCase):
1✔
2265
    def setUp(self):
1✔
2266
        warnings.simplefilter("ignore")
1✔
2267
        self.compat = MaterialsProject2020Compatibility()
1✔
2268

2269
        self.entry1 = ComputedEntry(
1✔
2270
            "Fe2O3",
2271
            -1,
2272
            correction=0.0,
2273
            parameters={
2274
                "is_hubbard": True,
2275
                "hubbards": {"Fe": 5.3, "O": 0},
2276
                "run_type": "GGA+U",
2277
                "potcar_spec": [
2278
                    {
2279
                        "titel": "PAW_PBE Fe_pv 06Sep2000",
2280
                        "hash": "994537de5c4122b7f1b77fb604476db4",
2281
                    },
2282
                    {
2283
                        "titel": "PAW_PBE O 08Apr2002",
2284
                        "hash": "7a25bc5b9a5393f46600a4939d357982",
2285
                    },
2286
                ],
2287
            },
2288
        )
2289

2290
        self.entry_sulfide = ComputedEntry(
1✔
2291
            "FeS",
2292
            -1,
2293
            0.0,
2294
            parameters={
2295
                "is_hubbard": False,
2296
                "run_type": "GGA",
2297
                "potcar_spec": [
2298
                    {
2299
                        "titel": "PAW_PBE Fe_pv 06Sep2000",
2300
                        "hash": "994537de5c4122b7f1b77fb604476db4",
2301
                    },
2302
                    {
2303
                        "titel": "PAW_PBE S 08Apr2002",
2304
                        "hash": "7a25bc5b9a5393f46600a4939d357982",
2305
                    },
2306
                ],
2307
            },
2308
        )
2309

2310
        self.entry2 = ComputedEntry(
1✔
2311
            "Fe3O4",
2312
            -2,
2313
            correction=0.0,
2314
            parameters={
2315
                "is_hubbard": True,
2316
                "hubbards": {"Fe": 5.3, "O": 0},
2317
                "run_type": "GGA+U",
2318
                "potcar_spec": [
2319
                    {
2320
                        "titel": "PAW_PBE Fe_pv 06Sep2000",
2321
                        "hash": "994537de5c4122b7f1b77fb604476db4",
2322
                    },
2323
                    {
2324
                        "titel": "PAW_PBE O 08Apr2002",
2325
                        "hash": "7a25bc5b9a5393f46600a4939d357982",
2326
                    },
2327
                ],
2328
            },
2329
        )
2330

2331
        self.entry_fluoride = ComputedEntry(
1✔
2332
            "FeF3",
2333
            -2,
2334
            correction=0.0,
2335
            parameters={
2336
                "is_hubbard": True,
2337
                "hubbards": {"Fe": 5.3, "F": 0},
2338
                "run_type": "GGA+U",
2339
                "potcar_spec": [
2340
                    {
2341
                        "titel": "PAW_PBE Fe_pv 06Sep2000",
2342
                        "hash": "994537de5c4122b7f1b77fb604476db4",
2343
                    },
2344
                    {
2345
                        "titel": "PAW_PBE F 08Apr2002",
2346
                        "hash": "180141c33d032bfbfff30b3bea9d23dd",
2347
                    },
2348
                ],
2349
            },
2350
        )
2351

2352
        self.entry_hydride = ComputedEntry(
1✔
2353
            "LiH",
2354
            -2,
2355
            correction=0.0,
2356
            parameters={
2357
                "is_hubbard": False,
2358
                "run_type": "GGA",
2359
                "potcar_spec": [
2360
                    {
2361
                        "titel": "PAW_PBE Li_sv 10Sep2004",
2362
                        "hash": "8245d7383d7556214082aa40a887cd96",
2363
                    },
2364
                    {
2365
                        "titel": "PAW_PBE H 15Jun2001",
2366
                        "hash": "bb43c666e3d36577264afe07669e9582",
2367
                    },
2368
                ],
2369
            },
2370
        )
2371

2372
    def tearDown(self):
1✔
2373
        warnings.simplefilter("default")
1✔
2374

2375
    def test_errors(self):
1✔
2376
        entry1_corrected = self.compat.process_entry(self.entry1)
1✔
2377
        assert entry1_corrected.correction_uncertainty == pytest.approx(sqrt((2 * 0.0101) ** 2 + (3 * 0.002) ** 2))
1✔
2378

2379
        entry2_corrected = self.compat.process_entry(self.entry2)
1✔
2380
        assert entry2_corrected.correction_uncertainty == pytest.approx(sqrt((3 * 0.0101) ** 2 + (4 * 0.002) ** 2))
1✔
2381

2382
        entry_sulfide_corrected = self.compat.process_entry(self.entry_sulfide)
1✔
2383
        assert entry_sulfide_corrected.correction_uncertainty == pytest.approx(0.0093)
1✔
2384

2385
        entry_fluoride_corrected = self.compat.process_entry(self.entry_fluoride)
1✔
2386
        assert entry_fluoride_corrected.correction_uncertainty == pytest.approx(sqrt((3 * 0.0026) ** 2 + 0.0101**2))
1✔
2387

2388
        entry_hydride_corrected = self.compat.process_entry(self.entry_hydride)
1✔
2389
        assert entry_hydride_corrected.correction_uncertainty == pytest.approx(0.0013)
1✔
2390

2391

2392
if __name__ == "__main__":
1✔
2393
    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