def calculate(self, atoms=None, properties=['energy'], system_changes=all_changes): LennardJones.calculate(self, atoms, properties, system_changes) if 'forces' in self.results: self.results['forces'] += 1e-4 * self.rng.normal( size=self.results['forces'].shape, ) if 'stress' in self.results: self.results['stress'] += 1e-4 * self.rng.normal( size=self.results['stress'].shape, )
def calculate(self, atoms=None, properties=['energy'], system_changes=all_changes): LennardJones.calculate(self, atoms, properties, system_changes) natoms = len(self.atoms) epsilon = self.parameters.epsilon sigma = self.parameters.sigma k = self.parameters.k r0 = self.parameters.r0 rc = self.parameters.rc if rc is None: rc = 3 * r0 energy = 0.0 forces = np.zeros((natoms, 3)) stress = np.zeros((3, 3)) tags = self.atoms.get_tags() for tag in np.unique(tags): # Adding (intramolecular) harmonic potential part indices = np.where(tags == tag)[0] assert len(indices) == 2 a1, a2 = indices d = self.atoms.get_distance(a1, a2, mic=True, vector=True) r = np.linalg.norm(d) energy += 0.5 * k * (r - r0) ** 2 f = -k * (r - r0) * d forces[a1] -= f forces[a2] += f stress += np.dot(np.array([f]).T, np.array([d])) # Substracting intramolecular LJ part r2 = r ** 2 c6 = (sigma**2 / r2)**3 c12 = c6 ** 2 energy += -4 * epsilon * (c12 - c6).sum() f = (24 * epsilon * (2 * c12 - c6) / r2) * d forces[a1] -= -f forces[a2] += -f stress += -np.dot(np.array([f]).T, np.array([d])) if 'stress' in properties: stress += stress.T.copy() stress *= -0.5 / self.atoms.get_volume() self.results['stress'] += stress.flat[[0, 4, 8, 5, 2, 1]] self.results['energy'] += energy self.results['free_energy'] += energy self.results['forces'] += forces
def example(): from ase.calculators.lj import LennardJones from theforce.util.flake import Hex from ase.io.trajectory import Trajectory from ase.optimize import BFGSLineSearch from ase.io import Trajectory # initial state + dft calculator ini_atoms = TorchAtoms(positions=Hex().array(), cutoff=3.0) dftcalc = LennardJones() ini_atoms.set_calculator(dftcalc) BFGSLineSearch(ini_atoms).run(fmax=0.01) vel = np.random.uniform(-1., 1., size=ini_atoms.positions.shape) * 1. vel -= vel.mean(axis=0) ini_atoms.set_velocities(vel) # use a pretrained model by writing it to the checkpoint # (alternatively set, for example, itrain=10*[5] in mlmd) pre = """GaussianProcessPotential([PairKernel(RBF(signal=3.2251566545458794, lengthscale=tensor([0.1040])), 0, 0, factor=PolyCut(3.0, n=2))], White(signal=0.1064043798026091, requires_grad=True))""".replace( '\n', '') with open('gp.chp', 'w') as chp: chp.write(pre) # run(md) mlmd(ini_atoms, 3.0, 0.5, 0.03, tolerance=0.18, max_steps=100, soap=False, itrain=10 * [3], retrain_every=5, retrain=5) # recalculate all with the actual calculator and compare traj = Trajectory('md.traj') energies = [] forces = [] dum = 0 for atoms in traj: dum += 1 e = atoms.get_potential_energy() f = atoms.get_forces() dftcalc.calculate(atoms) ee = dftcalc.results['energy'] ff = dftcalc.results['forces'] energies += [(e, ee)] forces += [(f.reshape(-1), ff.reshape(-1))] import pylab as plt get_ipython().run_line_magic('matplotlib', 'inline') fig, axes = plt.subplots(1, 2, figsize=(8, 3)) axes[0].scatter(*zip(*energies)) axes[0].set_xlabel('ml') axes[0].set_ylabel('dft') a, b = (np.concatenate(v) for v in zip(*forces)) axes[1].scatter(a, b) axes[1].set_xlabel('ml') axes[1].set_ylabel('dft') fig.tight_layout() fig.text(0.2, 0.8, 'energy') fig.text(0.7, 0.8, 'forces')