Statistiques
| Révision :

root / ase / utils / eos.py @ 18

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