def test_neb_methods(method, optimizer, precon, optmethod, ref_vacancy, setup_images): # unpack the reference result Ef_ref, dE_ref, saddle_ref = ref_vacancy # now relax the MEP for comparison images, _, _ = setup_images fmax_history = [] def save_fmax_history(mep): fmax_history.append(mep.get_residual()) k = 0.1 if precon == 'Exp': k = 0.01 mep = NEB(images, k=k, method=method, precon=precon) if optmethod is not None: opt = optimizer(mep, method=optmethod) else: opt = optimizer(mep) opt.attach(save_fmax_history, 1, mep) opt.run(fmax=1e-2) nebtools = NEBTools(images) Ef, dE = nebtools.get_barrier(fit=False) print(f'{method},{optimizer.__name__},{precon} ' f'=> Ef = {Ef:.3f}, dE = {dE:.3f}') forcefit = fit_images(images) output_dir = os.path.dirname(__file__) with open( f'{output_dir}/MEP_{method}_{optimizer.__name__}_{optmethod}' f'_{precon}.json', 'w') as f: json.dump( { 'fmax_history': fmax_history, 'method': method, 'optmethod': optmethod, 'precon': precon, 'optimizer': optimizer.__name__, 'path': forcefit.path, 'energies': forcefit.energies.tolist(), 'fit_path': forcefit.fit_path.tolist(), 'fit_energies': forcefit.fit_energies.tolist(), 'lines': np.array(forcefit.lines).tolist(), 'Ef': Ef, 'dE': dE }, f) centre = 2 # we have 5 images total, so central image has index 2 vdiff, _ = find_mic(images[centre].positions - saddle_ref.positions, images[centre].cell) print(f'Ef error {Ef - Ef_ref} dE error {dE - dE_ref} ' f'position error at saddle {abs(vdiff).max()}') assert abs(Ef - Ef_ref) < 1e-2 assert abs(dE - dE_ref) < 1e-2 assert abs(vdiff).max() < 1e-2
def neb(self): from ase.utils.forcecurve import fit_images try: forcefit = fit_images(self.images) except Exception as err: self.bad_plot(err, _('Images must have energies and forces, ' 'and atoms must not be stationary.')) else: self.pipe('neb', forcefit)
def test_integrate_forces(setup_images): images, _, _ = setup_images forcefit = fit_images(images) neb = NEB(images) spline_points = 1000 # it is the default value s, E, F = neb.integrate_forces(spline_points=spline_points) # check the difference between initial and final images np.testing.assert_allclose(E[0] - E[-1], forcefit.energies[0] - forcefit.energies[-1], atol=1.0e-10) # assert the maximum Energy value is in the middle assert np.argmax(E) == spline_points // 2 - 1 # check the maximum values (barrier value) # tolerance value is rather high since the images are not relaxed np.testing.assert_allclose(E.max(), forcefit.energies.max(), rtol=2.5e-2)
def get_barrier(self, fit=True, raw=False): """Returns the barrier estimate from the NEB, along with the Delta E of the elementary reaction. If fit=True, the barrier is estimated based on the interpolated fit to the images; if fit=False, the barrier is taken as the maximum-energy image without interpolation. Set raw=True to get the raw energy of the transition state instead of the forward barrier.""" forcefit = fit_images(self.images) energies = forcefit.energies fit_energies = forcefit.fit_energies dE = energies[-1] - energies[0] if fit: barrier = max(fit_energies) else: barrier = max(energies) if raw: barrier += self.images[0].get_potential_energy() return barrier, dE
def plot_band(self, ax=None): """Plots the NEB band on matplotlib axes object 'ax'. If ax=None returns a new figure object.""" forcefit = fit_images(self.images) ax = forcefit.plot(ax=ax) return ax.figure
def get_fit(self): return fit_images(self.images)