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