Statistiques
| Révision :

root / ase / md / nvtberendsen.py @ 1

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

1 1 tkerber
"""Berendsen NVT dynamics class."""
2 1 tkerber
3 1 tkerber
import sys
4 1 tkerber
import numpy as np
5 1 tkerber
from ase.md.md import MolecularDynamics
6 1 tkerber
7 1 tkerber
8 1 tkerber
# For parallel GPAW simulations, the random forces should be distributed.
9 1 tkerber
if '_gpaw' in sys.modules:
10 1 tkerber
    # http://wiki.fysik.dtu.dk/gpaw
11 1 tkerber
    from gpaw.mpi import world as gpaw_world
12 1 tkerber
else:
13 1 tkerber
    gpaw_world = None
14 1 tkerber
15 1 tkerber
16 1 tkerber
class NVTBerendsen(MolecularDynamics):
17 1 tkerber
    """Berendsen (constant N, V, T) molecular dynamics.
18 1 tkerber

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

21 1 tkerber
    atoms
22 1 tkerber
        The list of atoms.
23 1 tkerber

24 1 tkerber
    timestep
25 1 tkerber
        The time step.
26 1 tkerber

27 1 tkerber
    temperature
28 1 tkerber
        The desired temperature, in Kelvin.
29 1 tkerber

30 1 tkerber
    taut
31 1 tkerber
        Time constant for Berendsen temperature coupling.
32 1 tkerber

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

37 1 tkerber
    """
38 1 tkerber
39 1 tkerber
    def __init__(self, atoms, timestep, temperature, taut, fixcm=True,
40 1 tkerber
                 trajectory=None, logfile=None, loginterval=1,
41 1 tkerber
                 communicator=gpaw_world):
42 1 tkerber
43 1 tkerber
        MolecularDynamics.__init__(self, atoms, timestep, trajectory,
44 1 tkerber
                                   logfile, loginterval)
45 1 tkerber
        self.taut = taut
46 1 tkerber
        self.temperature = temperature
47 1 tkerber
        self.fixcm = fixcm  # will the center of mass be held fixed?
48 1 tkerber
        self.communicator = communicator
49 1 tkerber
50 1 tkerber
    def set_taut(self, taut):
51 1 tkerber
        self.taut = taut
52 1 tkerber
53 1 tkerber
    def get_taut(self):
54 1 tkerber
        return self.taut
55 1 tkerber
56 1 tkerber
    def set_temperature(self, temperature):
57 1 tkerber
        self.temperature = temperature
58 1 tkerber
59 1 tkerber
    def get_temperature(self):
60 1 tkerber
        return self.temperature
61 1 tkerber
62 1 tkerber
    def set_timestep(self, timestep):
63 1 tkerber
        self.dt = timestep
64 1 tkerber
65 1 tkerber
    def get_timestep(self):
66 1 tkerber
        return self.dt
67 1 tkerber
68 1 tkerber
    def scale_velocities(self):
69 1 tkerber
        """ Do the NVT Berendsen velocity scaling """
70 1 tkerber
        tautscl = self.dt / self.taut
71 1 tkerber
        old_temperature = self.atoms.get_temperature()
72 1 tkerber
73 1 tkerber
        scl_temperature = np.sqrt(1.0+ (self.temperature/ old_temperature- 1.0)
74 1 tkerber
                                  *tautscl)
75 1 tkerber
        #limit the velocity scaling to reasonable values
76 1 tkerber
        if scl_temperature > 1.1:
77 1 tkerber
            scl_temperature = 1.1
78 1 tkerber
        if scl_temperature < 0.9:
79 1 tkerber
            scl_temperature = 0.9
80 1 tkerber
81 1 tkerber
        atoms = self.atoms
82 1 tkerber
        p = self.atoms.get_momenta()
83 1 tkerber
        p = scl_temperature * p
84 1 tkerber
        self.atoms.set_momenta(p)
85 1 tkerber
        return
86 1 tkerber
87 1 tkerber
88 1 tkerber
    def step(self, f):
89 1 tkerber
        """ move one timestep forward using Berenden NVT molecular dynamics."""
90 1 tkerber
        self.scale_velocities()
91 1 tkerber
92 1 tkerber
        #one step velocity verlet
93 1 tkerber
        atoms = self.atoms
94 1 tkerber
        p = self.atoms.get_momenta()
95 1 tkerber
        p += 0.5 * self.dt * f
96 1 tkerber
97 1 tkerber
        if self.fixcm:
98 1 tkerber
            # calculate the center of mass
99 1 tkerber
            # momentum and subtract it
100 1 tkerber
            psum = p.sum(axis=0) / float(len(p))
101 1 tkerber
            p = p - psum
102 1 tkerber
103 1 tkerber
        self.atoms.set_positions(self.atoms.get_positions() +
104 1 tkerber
             self.dt * p / self.atoms.get_masses()[:,np.newaxis])
105 1 tkerber
106 1 tkerber
        # We need to store the momenta on the atoms before calculating
107 1 tkerber
        # the forces, as in a parallel Asap calculation atoms may
108 1 tkerber
        # migrate during force calculations, and the momenta need to
109 1 tkerber
        # migrate along with the atoms.  For the same reason, we
110 1 tkerber
        # cannot use self.masses in the line above.
111 1 tkerber
112 1 tkerber
        self.atoms.set_momenta(p)
113 1 tkerber
        f = self.atoms.get_forces()
114 1 tkerber
        atoms.set_momenta(self.atoms.get_momenta() + 0.5 * self.dt * f)
115 1 tkerber
116 1 tkerber
        return f