root / ase / utils / eos.py @ 1
Historique | Voir | Annoter | Télécharger (2,48 ko)
1 |
# -*- coding: utf-8 -*-
|
---|---|
2 |
from math import sqrt |
3 |
|
4 |
import numpy as np |
5 |
|
6 |
from ase.units import kJ |
7 |
|
8 |
class EquationOfState: |
9 |
"""Fit equation of state for bulk systems.
|
10 |
|
11 |
The following equation is used::
|
12 |
|
13 |
2 3 -1/3
|
14 |
E(V) = c + c t + c t + c t , t = V
|
15 |
0 1 2 3
|
16 |
|
17 |
Use::
|
18 |
|
19 |
eos = EquationOfState(volumes, energies)
|
20 |
v0, e0, B = eos.fit()
|
21 |
eos.plot()
|
22 |
|
23 |
"""
|
24 |
def __init__(self, volumes, energies): |
25 |
self.v = np.array(volumes)
|
26 |
self.e = np.array(energies)
|
27 |
self.v0 = None |
28 |
|
29 |
def fit(self): |
30 |
"""Calculate volume, energy, and bulk modulus.
|
31 |
|
32 |
Returns the optimal volume, the minumum energy, and the bulk
|
33 |
modulus. Notice that the ASE units for the bulk modulus is
|
34 |
eV/Angstrom^3 - to get the value in GPa, do this::
|
35 |
|
36 |
v0, e0, B = eos.fit()
|
37 |
print B / kJ * 1.0e24, 'GPa'
|
38 |
|
39 |
"""
|
40 |
|
41 |
fit0 = np.poly1d(np.polyfit(self.v**-(1.0 / 3), self.e, 3)) |
42 |
fit1 = np.polyder(fit0, 1)
|
43 |
fit2 = np.polyder(fit1, 1)
|
44 |
|
45 |
self.v0 = None |
46 |
for t in np.roots(fit1): |
47 |
if t > 0 and fit2(t) > 0: |
48 |
self.v0 = t**-3 |
49 |
break
|
50 |
|
51 |
if self.v0 is None: |
52 |
raise ValueError('No minimum!') |
53 |
|
54 |
self.e0 = fit0(t)
|
55 |
self.B = t**5 * fit2(t) / 9 |
56 |
self.fit0 = fit0
|
57 |
|
58 |
return self.v0, self.e0, self.B |
59 |
|
60 |
def plot(self, filename=None, show=None): |
61 |
"""Plot fitted energy curve.
|
62 |
|
63 |
Uses Matplotlib to plot the energy curve. Use *show=True* to
|
64 |
show the figure and *filename='abc.png'* or
|
65 |
*filename='abc.eps'* to save the figure to a file."""
|
66 |
|
67 |
#import matplotlib.pyplot as plt
|
68 |
import pylab as plt |
69 |
|
70 |
if self.v0 is None: |
71 |
self.fit()
|
72 |
|
73 |
if filename is None and show is None: |
74 |
show = True
|
75 |
|
76 |
x = 3.95
|
77 |
f = plt.figure(figsize=(x * 2.5**0.5, x)) |
78 |
f.subplots_adjust(left=0.12, right=0.9, top=0.9, bottom=0.15) |
79 |
plt.plot(self.v, self.e, 'o') |
80 |
x = np.linspace(min(self.v), max(self.v), 100) |
81 |
plt.plot(x, self.fit0(x**-(1.0 / 3)), '-r') |
82 |
plt.xlabel(u'volume [Å^3]')
|
83 |
plt.ylabel(u'energy [eV]')
|
84 |
plt.title(u'E: %.3f eV, V: %.3f Å^3, B: %.3f GPa' %
|
85 |
(self.e0, self.v0, self.B / kJ * 1.0e24)) |
86 |
|
87 |
if show:
|
88 |
plt.show() |
89 |
if filename is not None: |
90 |
f.savefig(filename) |
91 |
|
92 |
return f
|