Statistiques
| Révision :

root / ase / md / nvtberendsen.py @ 1

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

1
"""Berendsen NVT dynamics class."""
2

    
3
import sys
4
import numpy as np
5
from ase.md.md import MolecularDynamics
6

    
7

    
8
# For parallel GPAW simulations, the random forces should be distributed.
9
if '_gpaw' in sys.modules:
10
    # http://wiki.fysik.dtu.dk/gpaw
11
    from gpaw.mpi import world as gpaw_world
12
else:
13
    gpaw_world = None
14

    
15

    
16
class NVTBerendsen(MolecularDynamics):
17
    """Berendsen (constant N, V, T) molecular dynamics.
18

19
    Usage: NVTBerendsen(atoms, timestep, temperature, taut, fixcm)
20

21
    atoms
22
        The list of atoms.
23
        
24
    timestep
25
        The time step.
26

27
    temperature
28
        The desired temperature, in Kelvin.
29

30
    taut
31
        Time constant for Berendsen temperature coupling.
32

33
    fixcm
34
        If True, the position and momentum of the center of mass is
35
        kept unperturbed.  Default: True.
36

37
    """
38

    
39
    def __init__(self, atoms, timestep, temperature, taut, fixcm=True,
40
                 trajectory=None, logfile=None, loginterval=1,
41
                 communicator=gpaw_world):
42

    
43
        MolecularDynamics.__init__(self, atoms, timestep, trajectory, 
44
                                   logfile, loginterval)
45
        self.taut = taut
46
        self.temperature = temperature
47
        self.fixcm = fixcm  # will the center of mass be held fixed?
48
        self.communicator = communicator
49

    
50
    def set_taut(self, taut):
51
        self.taut = taut
52

    
53
    def get_taut(self):
54
        return self.taut
55

    
56
    def set_temperature(self, temperature):
57
        self.temperature = temperature
58

    
59
    def get_temperature(self):
60
        return self.temperature
61

    
62
    def set_timestep(self, timestep):
63
        self.dt = timestep
64

    
65
    def get_timestep(self):
66
        return self.dt
67

    
68
    def scale_velocities(self):
69
        """ Do the NVT Berendsen velocity scaling """
70
        tautscl = self.dt / self.taut
71
        old_temperature = self.atoms.get_temperature()
72

    
73
        scl_temperature = np.sqrt(1.0+ (self.temperature/ old_temperature- 1.0)
74
                                  *tautscl)
75
        #limit the velocity scaling to reasonable values
76
        if scl_temperature > 1.1:
77
            scl_temperature = 1.1
78
        if scl_temperature < 0.9:
79
            scl_temperature = 0.9
80
        
81
        atoms = self.atoms
82
        p = self.atoms.get_momenta()
83
        p = scl_temperature * p 
84
        self.atoms.set_momenta(p)
85
        return 
86

    
87

    
88
    def step(self, f):
89
        """ move one timestep forward using Berenden NVT molecular dynamics."""
90
        self.scale_velocities()
91

    
92
        #one step velocity verlet
93
        atoms = self.atoms
94
        p = self.atoms.get_momenta()
95
        p += 0.5 * self.dt * f
96

    
97
        if self.fixcm:
98
            # calculate the center of mass
99
            # momentum and subtract it
100
            psum = p.sum(axis=0) / float(len(p))
101
            p = p - psum
102

    
103
        self.atoms.set_positions(self.atoms.get_positions() +
104
             self.dt * p / self.atoms.get_masses()[:,np.newaxis])
105

    
106
        # We need to store the momenta on the atoms before calculating
107
        # the forces, as in a parallel Asap calculation atoms may
108
        # migrate during force calculations, and the momenta need to
109
        # migrate along with the atoms.  For the same reason, we
110
        # cannot use self.masses in the line above.
111

    
112
        self.atoms.set_momenta(p)
113
        f = self.atoms.get_forces()
114
        atoms.set_momenta(self.atoms.get_momenta() + 0.5 * self.dt * f)
115

    
116
        return f
117