root / ase / utils / eos.py @ 7
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
|