root / ase / calculators / morse.py @ 5
Historique | Voir | Annoter | Télécharger (1,42 ko)
1 |
from math import exp, sqrt |
---|---|
2 |
import numpy as np |
3 |
|
4 |
class MorsePotential: |
5 |
"""Morse potential.
|
6 |
|
7 |
Default values chosen to be similar as Lennard-Jones.
|
8 |
"""
|
9 |
def __init__(self, rho0=6.0, epsilon=1.0, r0=1.0): |
10 |
self.epsilon = epsilon
|
11 |
self.rho0 = rho0
|
12 |
self.r0 = r0
|
13 |
self.positions = None |
14 |
|
15 |
def update(self, atoms): |
16 |
assert not atoms.get_pbc().any() |
17 |
if (self.positions is None or |
18 |
(self.positions != atoms.get_positions()).any()):
|
19 |
self.calculate(atoms)
|
20 |
|
21 |
def get_potential_energy(self, atoms): |
22 |
self.update(atoms)
|
23 |
return self.energy |
24 |
|
25 |
def get_forces(self, atoms): |
26 |
self.update(atoms)
|
27 |
return self._forces |
28 |
|
29 |
def get_stress(self, atoms): |
30 |
return np.zeros((3, 3)) |
31 |
|
32 |
def calculate(self, atoms): |
33 |
positions = atoms.get_positions() |
34 |
self.energy = 0.0 |
35 |
self._forces = np.zeros((len(atoms), 3)) |
36 |
preF = 2 * self.epsilon * self.rho0 / self.r0 |
37 |
for i1, p1 in enumerate(positions): |
38 |
for i2, p2 in enumerate(positions[:i1]): |
39 |
diff = p2 - p1 |
40 |
r = sqrt(np.dot(diff, diff)) |
41 |
expf = exp(self.rho0 * (1.0 - r / self.r0)) |
42 |
self.energy += self.epsilon * expf * (expf - 2) |
43 |
F = preF * expf * (expf - 1) * diff / r
|
44 |
self._forces[i1] -= F
|
45 |
self._forces[i2] += F
|
46 |
self.positions = positions.copy()
|