root / ase / md / nptberendsen.py
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
|