-
Notifications
You must be signed in to change notification settings - Fork 55
/
vibespresso.py
84 lines (73 loc) · 2.83 KB
/
vibespresso.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
#****************************************************************************
# Copyright (C) 2013 SUNCAT
# This file is distributed under the terms of the
# GNU General Public License. See the file `COPYING'
# in the root directory of the present distribution,
# or http://www.gnu.org/copyleft/gpl.txt .
#****************************************************************************
from ase.calculators.general import Calculator
from espresso import espresso
import numpy as np
class vibespresso(Calculator):
"""
Special espresso calculator, which expects the first calculation to
be performed for a structure without displacements. All subsequent
calculations are then initialized with the Kohn-Sham potential of
the first calculation to speed up vibrational calculations.
"""
def __init__(self,
outdirprefix = 'out',
**kwargs
):
"""
In addition to the parameters of a standard espresso calculator,
outdirprefix (default: 'out') can be specified, which will be the
prefix of the output of the calculations for different displacements
"""
self.arg = kwargs.copy()
self.outdirprefix = outdirprefix
self.counter = 0
self.equilibriumdensity = outdirprefix+'_equi.tgz'
self.firststep = True
self.ready = False
def update(self, atoms):
if self.atoms is not None:
x = atoms.positions-self.atoms.positions
if np.max(x)>1E-13 or np.min(x)<-1E-13:
self.ready = False
else:
self.atoms = atoms.copy()
self.runcalc(atoms)
if atoms is not None:
self.atoms = atoms.copy()
def runcalc(self, atoms):
if not self.ready:
self.arg['outdir'] = self.outdirprefix+'_%04d' % self.counter
self.counter += 1
if self.firststep:
self.esp = espresso(**self.arg)
self.esp.set_atoms(atoms)
self.esp.get_potential_energy(atoms)
self.esp.save_chg(self.equilibriumdensity)
self.firststep = False
else:
self.arg['startingpot'] = 'file'
self.esp = espresso(**self.arg)
self.esp.set_atoms(atoms)
self.esp.load_chg(self.equilibriumdensity)
self.esp.get_potential_energy(atoms)
self.esp.stop()
self.ready = True
def get_potential_energy(self, atoms, force_consistent=False):
self.update(atoms)
if force_consistent:
return self.esp.energy_free
else:
return self.esp.energy_zero
def get_forces(self, atoms):
self.update(atoms)
return self.esp.forces
def get_name(self):
return 'VibEspresso'
def get_version(self):
return '0.1'