Statistiques
| Révision :

root / ase / md / nptberendsen.py @ 3

Historique | Voir | Annoter | Télécharger (3,79 ko)

1
"""Berendsen NPT dynamics class."""
2

    
3
import numpy as np
4

    
5
#from ase.md import MolecularDynamics
6
from ase.md.nvtberendsen import NVTBerendsen
7
import ase.units as units
8
#import math
9

    
10

    
11
class NPTBerendsen(NVTBerendsen):
12
    """Berendsen (constant N, P, T) molecular dynamics.
13

14
    Usage: NPTBerendsen(atoms, timestep, temperature, taut, pressure, taup)
15

16
    atoms
17
        The list of atoms.
18
        
19
    timestep
20
        The time step.
21

22
    temperature
23
        The desired temperature, in Kelvin.
24

25
    taut
26
        Time constant for Berendsen temperature coupling.
27

28
    fixcm
29
        If True, the position and momentum of the center of mass is
30
        kept unperturbed.  Default: True.
31

32
    pressure
33
        The desired pressure, in bar (1 bar = 1e5 Pa).
34

35
    taup
36
        Time constant for Berendsen pressure coupling.
37

38
    compressibility
39
        The compressibility of the material, water 4.57E-5 bar-1, in bar-1
40

41
    """
42

    
43
    def __init__(self, atoms, timestep, temperature, taut=0.5e3*units.fs,
44
                 pressure = 1.01325, taup=1e3*units.fs,
45
                 compressibility=4.57e-5, fixcm=True,
46
                 trajectory=None, logfile=None, loginterval=1):
47

    
48
        NVTBerendsen.__init__(self, atoms, timestep, temperature, taut, fixcm,
49
                              trajectory, 
50
                              logfile, loginterval)
51
        self.taup = taup
52
        self.pressure = pressure
53
        self.compressibility = compressibility
54

    
55
    def set_taup(self, taut):
56
        self.taut = taut
57

    
58
    def get_taup(self):
59
        return self.taut
60

    
61
    def set_pressure(self, pressure):
62
        self.pressure = pressure
63

    
64
    def get_pressure(self):
65
        return self.pressure
66

    
67
    def set_compressibility(self, compressibility):
68
        self.compressibility = compressibility
69

    
70
    def get_compressibility(self):
71
        return self.compressibility
72

    
73
    def set_timestep(self, timestep):
74
        self.dt = timestep
75

    
76
    def get_timestep(self):
77
        return self.dt
78

    
79

    
80

    
81
    def scale_positions_and_cell(self):
82
        """ Do the Berendsen pressure coupling,
83
        scale the atom positon and the simulation cell."""
84

    
85
        taupscl = self.dt / self.taup
86
        stress = self.atoms.get_stress()
87
        old_pressure = self.atoms.get_isotropic_pressure(stress)
88
        scl_pressure = 1.0 - taupscl * self.compressibility / 3.0 * \
89
                       (self.pressure - old_pressure)
90

    
91
        #print "old_pressure", old_pressure
92
        #print "volume scaling by:", scl_pressure
93

    
94
        cell = self.atoms.get_cell()
95
        positions = self.atoms.get_positions()
96

    
97
        cell = scl_pressure * cell
98
        positions = scl_pressure * positions 
99

    
100
        self.atoms.set_cell(cell, scale_atoms=False)
101
        self.atoms.set_positions(positions)
102

    
103
        return 
104

    
105

    
106
    def step(self, f):
107
        """ move one timestep forward using Berenden NPT molecular dynamics."""
108

    
109
        NVTBerendsen.scale_velocities(self)
110
        self.scale_positions_and_cell()
111

    
112
        #one step velocity verlet
113
        atoms = self.atoms
114
        p = self.atoms.get_momenta()
115
        p += 0.5 * self.dt * f
116

    
117
        if self.fixcm:
118
            # calculate the center of mass
119
            # momentum and subtract it
120
            psum = p.sum(axis=0) / float(len(p))
121
            p = p - psum
122

    
123
        self.atoms.set_positions(self.atoms.get_positions() +
124
             self.dt * p / self.atoms.get_masses()[:,np.newaxis])
125

    
126
        # We need to store the momenta on the atoms before calculating
127
        # the forces, as in a parallel Asap calculation atoms may
128
        # migrate during force calculations, and the momenta need to
129
        # migrate along with the atoms.  For the same reason, we
130
        # cannot use self.masses in the line above.
131

    
132
        self.atoms.set_momenta(p)
133
        f = self.atoms.get_forces()
134
        atoms.set_momenta(self.atoms.get_momenta() + 0.5 * self.dt * f)
135

    
136

    
137
        return f