• 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

98.75
/pymatgen/analysis/tests/test_eos.py
1
# Copyright (c) Pymatgen Development Team.
2
# Distributed under the terms of the MIT License.
3

4

5
from __future__ import annotations
1✔
6

7
import unittest
1✔
8

9
import numpy as np
1✔
10
from pytest import approx
1✔
11

12
from pymatgen.analysis.eos import EOS, NumericalEOS
1✔
13
from pymatgen.util.testing import PymatgenTest
1✔
14

15

16
class EOSTest(PymatgenTest):
1✔
17
    def setUp(self):
1✔
18
        # Si data from Cormac
19
        self.volumes = [
1✔
20
            25.987454833,
21
            26.9045702104,
22
            27.8430241908,
23
            28.8029649591,
24
            29.7848370694,
25
            30.7887887064,
26
            31.814968055,
27
            32.8638196693,
28
            33.9353435494,
29
            35.0299842495,
30
            36.1477417695,
31
            37.2892088485,
32
            38.4543854865,
33
            39.6437162376,
34
            40.857201102,
35
            42.095136449,
36
            43.3579668329,
37
            44.6456922537,
38
            45.9587572656,
39
            47.2973100535,
40
            48.6614988019,
41
            50.0517680652,
42
            51.4682660281,
43
            52.9112890601,
44
            54.3808371612,
45
            55.8775030703,
46
            57.4014349722,
47
            58.9526328669,
48
        ]
49
        self.energies = [
1✔
50
            -7.63622156576,
51
            -8.16831294894,
52
            -8.63871612686,
53
            -9.05181213218,
54
            -9.41170988374,
55
            -9.72238224345,
56
            -9.98744832526,
57
            -10.210309552,
58
            -10.3943401353,
59
            -10.5427238068,
60
            -10.6584266073,
61
            -10.7442240979,
62
            -10.8027285713,
63
            -10.8363890521,
64
            -10.8474912964,
65
            -10.838157792,
66
            -10.8103477586,
67
            -10.7659387815,
68
            -10.7066179666,
69
            -10.6339907853,
70
            -10.5495538639,
71
            -10.4546677714,
72
            -10.3506386542,
73
            -10.2386366017,
74
            -10.1197772808,
75
            -9.99504030111,
76
            -9.86535084973,
77
            -9.73155247952,
78
        ]
79
        num_eos = EOS(eos_name="numerical_eos")
1✔
80
        self.num_eos_fit = num_eos.fit(self.volumes, self.energies)
1✔
81

82
    def test_run_all_models(self):
1✔
83
        # these have been checked for plausibility,
84
        # but are not benchmarked against independently known values
85
        test_output = {
1✔
86
            "birch": {
87
                "b0": 0.5369258244952931,
88
                "b1": 4.178644231838501,
89
                "e0": -10.8428039082307,
90
                "v0": 40.98926572870838,
91
            },
92
            "birch_murnaghan": {
93
                "b0": 0.5369258245417454,
94
                "b1": 4.178644235500821,
95
                "e0": -10.842803908240892,
96
                "v0": 40.98926572528106,
97
            },
98
            "deltafactor": {
99
                "b0": 0.5369258245611414,
100
                "b1": 4.178644231924639,
101
                "e0": -10.842803908299294,
102
                "v0": 40.989265727927936,
103
            },
104
            "murnaghan": {
105
                "b0": 0.5144967693786603,
106
                "b1": 3.9123862262572264,
107
                "e0": -10.836794514626673,
108
                "v0": 41.13757930387086,
109
            },
110
            "numerical_eos": {
111
                "b0": 0.5557257614101998,
112
                "b1": 4.344039148405489,
113
                "e0": -10.847490826530702,
114
                "v0": 40.857200064982536,
115
            },
116
            "pourier_tarantola": {
117
                "b0": 0.5667729960804602,
118
                "b1": 4.331688936974368,
119
                "e0": -10.851486685041658,
120
                "v0": 40.86770643373908,
121
            },
122
            "vinet": {
123
                "b0": 0.5493839425156859,
124
                "b1": 4.3051929654936885,
125
                "e0": -10.846160810560756,
126
                "v0": 40.916875663779784,
127
            },
128
        }
129

130
        for eos_name in EOS.MODELS:
1✔
131
            eos = EOS(eos_name=eos_name)
1✔
132
            _ = eos.fit(self.volumes, self.energies)
1✔
133
            for param in ("b0", "b1", "e0", "b0"):
1✔
134
                # TODO: solutions only stable to 2 decimal places
135
                # between different machines, this seems far too low?
136
                self.assertArrayAlmostEqual(_.results[param], test_output[eos_name][param], decimal=1)
1✔
137

138
    def test_fitting(self):
1✔
139
        # courtesy of @katherinelatimer2013
140
        # known correct values for Vinet
141

142
        # Mg
143

144
        mp153_volumes = [
1✔
145
            16.69182365,
146
            17.25441763,
147
            17.82951915,
148
            30.47573817,
149
            18.41725977,
150
            29.65211363,
151
            28.84346369,
152
            19.01777055,
153
            28.04965916,
154
            19.63120886,
155
            27.27053682,
156
            26.5059864,
157
            20.25769112,
158
            25.75586879,
159
            20.89736201,
160
            25.02003097,
161
            21.55035204,
162
            24.29834347,
163
            22.21681221,
164
            23.59066888,
165
            22.89687316,
166
        ]
167

168
        mp153_energies = [
1✔
169
            -1.269884575,
170
            -1.339411225,
171
            -1.39879471,
172
            -1.424480995,
173
            -1.44884184,
174
            -1.45297499,
175
            -1.4796246,
176
            -1.49033594,
177
            -1.504198485,
178
            -1.52397006,
179
            -1.5264432,
180
            -1.54609291,
181
            -1.550269435,
182
            -1.56284009,
183
            -1.569937375,
184
            -1.576420935,
185
            -1.583470925,
186
            -1.58647189,
187
            -1.591436505,
188
            -1.592563495,
189
            -1.594347355,
190
        ]
191

192
        mp153_known_energies_vinet = [
1✔
193
            -1.270038831,
194
            -1.339366487,
195
            -1.398683238,
196
            -1.424556061,
197
            -1.448746649,
198
            -1.453000456,
199
            -1.479614511,
200
            -1.490266797,
201
            -1.504163502,
202
            -1.523910268,
203
            -1.526395734,
204
            -1.546038792,
205
            -1.550298657,
206
            -1.562800797,
207
            -1.570015274,
208
            -1.576368392,
209
            -1.583605186,
210
            -1.586404575,
211
            -1.591578378,
212
            -1.592547954,
213
            -1.594410995,
214
        ]
215

216
        # C: 4.590843262
217
        # B: 2.031381599
218
        mp153_known_e0_vinet = -1.594429229
1✔
219
        mp153_known_v0_vinet = 22.95764159
1✔
220

221
        eos = EOS(eos_name="vinet")
1✔
222

223
        fit = eos.fit(mp153_volumes, mp153_energies)
1✔
224

225
        np.testing.assert_array_almost_equal(fit.func(mp153_volumes), mp153_known_energies_vinet, decimal=5)
1✔
226

227
        assert mp153_known_e0_vinet == approx(fit.e0, abs=1e-4)
1✔
228
        assert mp153_known_v0_vinet == approx(fit.v0, abs=1e-4)
1✔
229

230
        # expt. value 35.5, known fit 36.16
231
        assert fit.b0_GPa == approx(36.16258687442761, abs=1e-4)
1✔
232

233
        # Si
234

235
        mp149_volumes = [
1✔
236
            15.40611854,
237
            14.90378698,
238
            16.44439516,
239
            21.0636307,
240
            17.52829835,
241
            16.98058208,
242
            18.08767363,
243
            18.65882487,
244
            19.83693435,
245
            15.91961152,
246
            22.33987173,
247
            21.69548924,
248
            22.99688883,
249
            23.66666322,
250
            20.44414922,
251
            25.75374305,
252
            19.24187473,
253
            24.34931029,
254
            25.04496106,
255
            27.21116571,
256
            26.4757653,
257
        ]
258

259
        mp149_energies = [
1✔
260
            -4.866909695,
261
            -4.7120965,
262
            -5.10921253,
263
            -5.42036228,
264
            -5.27448405,
265
            -5.200810795,
266
            -5.331915665,
267
            -5.3744186,
268
            -5.420058145,
269
            -4.99862686,
270
            -5.3836163,
271
            -5.40610838,
272
            -5.353700425,
273
            -5.31714654,
274
            -5.425263555,
275
            -5.174988295,
276
            -5.403353105,
277
            -5.27481447,
278
            -5.227210275,
279
            -5.058992615,
280
            -5.118805775,
281
        ]
282

283
        mp149_known_energies_vinet = [
1✔
284
            -4.866834585,
285
            -4.711786499,
286
            -5.109642598,
287
            -5.420093739,
288
            -5.274605844,
289
            -5.201025714,
290
            -5.331899365,
291
            -5.374315789,
292
            -5.419671568,
293
            -4.998827503,
294
            -5.383703409,
295
            -5.406038887,
296
            -5.353926272,
297
            -5.317484252,
298
            -5.424963418,
299
            -5.175090887,
300
            -5.403166824,
301
            -5.275096644,
302
            -5.227427635,
303
            -5.058639193,
304
            -5.118654229,
305
        ]
306

307
        # C: 4.986513158
308
        # B: 4.964976215
309
        mp149_known_e0_vinet = -5.424963506
1✔
310
        mp149_known_v0_vinet = 20.44670279
1✔
311

312
        eos = EOS(eos_name="vinet")
1✔
313

314
        fit = eos.fit(mp149_volumes, mp149_energies)
1✔
315

316
        np.testing.assert_array_almost_equal(fit.func(mp149_volumes), mp149_known_energies_vinet, decimal=5)
1✔
317

318
        assert mp149_known_e0_vinet == approx(fit.e0, abs=1e-4)
1✔
319
        assert mp149_known_v0_vinet == approx(fit.v0, abs=1e-4)
1✔
320

321
        # expt. value 97.9, known fit 88.39
322
        assert fit.b0_GPa == approx(88.38629337404822, abs=1e-4)
1✔
323

324
        # Ti
325

326
        mp72_volumes = [
1✔
327
            12.49233296,
328
            12.91339188,
329
            13.34380224,
330
            22.80836212,
331
            22.19195533,
332
            13.78367177,
333
            21.58675559,
334
            14.23310328,
335
            20.99266009,
336
            20.4095592,
337
            14.69220297,
338
            19.83736385,
339
            15.16106697,
340
            19.2759643,
341
            15.63980711,
342
            18.72525771,
343
            16.12851491,
344
            18.18514127,
345
            16.62729878,
346
            17.65550599,
347
            17.13626153,
348
        ]
349

350
        mp72_energies = [
1✔
351
            -7.189983803,
352
            -7.33985647,
353
            -7.468745423,
354
            -7.47892835,
355
            -7.54945107,
356
            -7.578012237,
357
            -7.61513166,
358
            -7.66891898,
359
            -7.67549721,
360
            -7.73000681,
361
            -7.74290386,
362
            -7.77803379,
363
            -7.801246383,
364
            -7.818964483,
365
            -7.84488189,
366
            -7.85211192,
367
            -7.87486651,
368
            -7.876767777,
369
            -7.892161533,
370
            -7.892199957,
371
            -7.897605303,
372
        ]
373

374
        mp72_known_energies_vinet = [
1✔
375
            -7.189911138,
376
            -7.339810181,
377
            -7.468716095,
378
            -7.478678021,
379
            -7.549402394,
380
            -7.578034391,
381
            -7.615240977,
382
            -7.669091347,
383
            -7.675683891,
384
            -7.730188653,
385
            -7.74314028,
386
            -7.778175824,
387
            -7.801363213,
388
            -7.819030923,
389
            -7.844878053,
390
            -7.852099741,
391
            -7.874737806,
392
            -7.876686864,
393
            -7.891937429,
394
            -7.892053535,
395
            -7.897414664,
396
        ]
397

398
        # C: 3.958192998
399
        # B: 6.326790098
400
        mp72_known_e0_vinet = -7.897414997
1✔
401
        mp72_known_v0_vinet = 17.13223229
1✔
402

403
        eos = EOS(eos_name="vinet")
1✔
404

405
        fit = eos.fit(mp72_volumes, mp72_energies)
1✔
406

407
        np.testing.assert_array_almost_equal(fit.func(mp72_volumes), mp72_known_energies_vinet, decimal=5)
1✔
408

409
        assert mp72_known_e0_vinet == approx(fit.e0, abs=1e-4)
1✔
410
        assert mp72_known_v0_vinet == approx(fit.v0, abs=1e-4)
1✔
411

412
        # expt. value 107.3, known fit 112.63
413
        assert fit.b0_GPa == approx(112.62927187296167, abs=1e-4)
1✔
414

415
    def test_numerical_eoswrapper(self):
1✔
416
        # using numerical eos directly vs via EOS wrapper
417
        numerical_eos = NumericalEOS(self.volumes, self.energies)
1✔
418
        numerical_eos.fit()
1✔
419
        assert len(numerical_eos.eos_params) > 3
1✔
420
        assert float(numerical_eos.e0) == approx(self.num_eos_fit.e0, abs=1e-3)
1✔
421
        assert float(numerical_eos.v0) == approx(self.num_eos_fit.v0, abs=1e-3)
1✔
422
        assert float(numerical_eos.b0) == approx(self.num_eos_fit.b0, abs=1e-3)
1✔
423
        assert float(numerical_eos.b1) == approx(self.num_eos_fit.b1, abs=1e-3)
1✔
424
        self.assertArrayAlmostEqual(numerical_eos.eos_params, self.num_eos_fit.eos_params)
1✔
425

426
    def test_numerical_eos_values(self):
1✔
427
        np.testing.assert_almost_equal(self.num_eos_fit.e0, -10.84749, decimal=3)
1✔
428
        np.testing.assert_almost_equal(self.num_eos_fit.v0, 40.857201, decimal=1)
1✔
429
        np.testing.assert_almost_equal(self.num_eos_fit.b0, 0.55, decimal=2)
1✔
430
        # TODO: why were these tests commented out?
431
        # np.testing.assert_almost_equal(self.num_eos_fit.b0_GPa, 89.0370727, decimal=1)
432
        # np.testing.assert_almost_equal(self.num_eos_fit.b1, 4.344039, decimal=2)
433

434
    def test_eos_func(self):
1✔
435
        # list vs np.array arguments
436
        np.testing.assert_almost_equal(
1✔
437
            self.num_eos_fit.func([0, 1, 2]),
438
            self.num_eos_fit.func(np.array([0, 1, 2])),
439
            decimal=10,
440
        )
441
        # func vs _func
442
        np.testing.assert_almost_equal(
1✔
443
            self.num_eos_fit.func(0.0),
444
            self.num_eos_fit._func(0.0, self.num_eos_fit.eos_params),
445
            decimal=10,
446
        )
447
        # test the eos function: energy = f(volume)
448
        # numerical eos evaluated at volume=0 == a0 of the fit polynomial
449
        np.testing.assert_almost_equal(self.num_eos_fit.func(0.0), self.num_eos_fit.eos_params[-1], decimal=6)
1✔
450
        birch_eos = EOS(eos_name="birch")
1✔
451
        birch_eos_fit = birch_eos.fit(self.volumes, self.energies)
1✔
452
        # birch eos evaluated at v0 == e0
453
        np.testing.assert_almost_equal(birch_eos_fit.func(birch_eos_fit.v0), birch_eos_fit.e0, decimal=6)
1✔
454

455
        # TODO: Reactivate
456
        # fig = birch_eos_fit.plot_ax(ax=None, show=False, fontsize=8, title="birch eos")
457
        # self.assertTrue(hasattr(fig, "savefig"))
458

459
    def test_eos_func_call(self):
1✔
460
        # eos_fit_obj.func(volume) == eos_fit_obj(volume)
461
        np.testing.assert_almost_equal(self.num_eos_fit.func(0.0), self.num_eos_fit(0.0), decimal=10)
1✔
462

463
    def test_summary_dict(self):
1✔
464
        d = {
1✔
465
            "e0": self.num_eos_fit.e0,
466
            "b0": self.num_eos_fit.b0,
467
            "b1": self.num_eos_fit.b1,
468
            "v0": self.num_eos_fit.v0,
469
        }
470
        assert self.num_eos_fit.results == d
1✔
471

472

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