예제 #1
0
    if rank in ranks:
        calc = GPAW(mode=PW(500),
                    xc='PBE',
                    basis='dzp',
                    maxiter=99,
                    kpts=(2, 2, 1),
                    txt='neb{}.txt'.format(j),
                    communicator=ranks)
        image.set_calculator(calc)
    images.append(image)

images.append(final)

# Initialize neb object
neb = NEB(images, k=0.5, parallel=True, method='eb', climb=False)
#neb.interpolate()

# Converge path roughly before invoking the CI method
qn = BFGS(neb, trajectory='neb_rough.traj')
qn.run(fmax=0.15)

# Turn on CI
neb.climb = True

# Fully converge the path including an image climbing to the saddle point
qn = BFGS(neb, trajectory='neb_CI.traj')
qn.run(fmax=0.09)

write('neb_done.traj', images)
예제 #2
0
파일: neb.py 프로젝트: rosswhitfield/ase
for i in range(nimages):
    images.append(images[0].copy())
images[-1].positions[6, 1] = 2 - images[0].positions[6, 1]
neb = NEB(images)
neb.interpolate()
if 0:  # verify that initial images make sense
    from ase.visualize import view
    view(neb.images)

for image in images:
    image.set_calculator(MorsePotential())

dyn = BFGS(neb, trajectory='mep.traj')  # , logfile='mep.log')

dyn.run(fmax=fmax)

for a in neb.images:
    print(a.positions[-1], a.get_potential_energy())

neb.climb = True
dyn.run(fmax=fmax)

# Check NEB tools.
nt_images = read('mep.traj@-4:')
nebtools = NEBtools(nt_images)
nt_fmax = nebtools.get_fmax(climb=True)
Ef, dE = nebtools.get_barrier()
print(Ef, dE, fmax, nt_fmax)
assert nt_fmax < fmax
assert abs(Ef - 1.389) < 0.001
예제 #3
0
파일: mlneb.py 프로젝트: hauser-group/mlpot
def aie_ml_neb(neb,
               ml_calc,
               steps=150,
               ml_steps=150,
               t_mep=0.3,
               t_ci=0.01,
               t_ci_on=1.0,
               r_max=None,
               t_mep_ml=None,
               callback_after_ml_neb=None):
    """


    Koistinen et al. J. Chem. Phys. 147, 152720 (2017)
    """
    images = neb.images
    # save initial path as the machine learning NEB run is always restarted
    # from the initial path.
    initial_path = [image.get_positions().copy() for image in images]

    if r_max is None:
        # Koistinen et al. suggest half of the length of the initial path for
        # r_max:
        r_max = 0.5 * sum([
            distance(images[i - 1], images[i]) for i in range(1, len(images))
        ])
        print('r_max = %.2f' % r_max)

    # Default value of the threshold for the MEP on the machine learning
    # surface following Koistinen et al.
    t_mep_ml = t_mep_ml or 0.1 * t_ci

    # Add first and last image to the training data
    for image in (images[0], images[-1]):
        training_image = image.copy()
        training_image.set_calculator(
            SinglePointCalculator(
                training_image,
                forces=image.get_forces(apply_constraint=False),
                energy=image.get_potential_energy()))
        ml_calc.add_data(training_image)

    ml_images = [image.copy() for image in images]
    [ml_image.set_calculator(copy(ml_calc)) for ml_image in ml_images]
    ml_neb = NEB(
        ml_images,
        k=neb.k,
        climb=neb.climb,
        method=neb.method,
        remove_rotation_and_translation=neb.remove_rotation_and_translation)

    for i_step in range(steps):
        # Step A:
        # evaluate intermediate images and add them to the training_image data
        for image, ml_image in zip(images[1:-1], ml_images[1:-1]):
            # Update image positions
            image.set_positions(ml_image.get_positions())
            training_image = image.copy()
            training_image.set_calculator(
                SinglePointCalculator(
                    training_image,
                    forces=image.get_forces(apply_constraint=False),
                    energy=image.get_potential_energy()))
            ml_calc.add_data(training_image)

        # Step B:
        # Reshape forces into N_intermediate_images x N_atoms x 3
        forces = neb.get_forces().reshape((len(ml_neb.images) - 2, -1, 3))
        print('Maximum force per image after %d evaluations of the band:' %
              (i_step + 1))
        print(np.sqrt((forces**2).sum(axis=2).max(axis=1)))

        # Step C:
        # This differs from Koistinen et al. by checking the maximum force
        # on any atom and not the norm of the force vector
        max_force = np.sqrt((forces**2).sum(axis=2).max())
        # Use imax-1 since forces only contains intermediate images
        ci_force = np.sqrt((forces[neb.imax - 1, :, :]**2).sum(axis=1).max())
        print('Maximum force: ', max_force)
        print('Force on climbing image: ', ci_force)
        if max_force < t_mep and ci_force < t_ci:
            # Converged
            return True
        # Step D:
        ml_calc.fit()
        params = ml_calc.get_params()

        # Step E:
        for ml_image, init_pos in zip(ml_images, initial_path):
            # Update calculator
            ml_image.calc.set_params(**params)
            # Reset positions to inital path
            ml_image.set_positions(init_pos.copy())
        ml_neb.climb = False
        _relaxation_phase(ml_neb, ml_calc, ml_steps, t_mep_ml, t_ci_on, r_max)

        if callback_after_ml_neb is not None:
            callback_after_ml_neb(images, ml_images, ml_calc)
    # No convergence reached:
    return False
예제 #4
0
파일: mlneb.py 프로젝트: hauser-group/mlpot
def run_mla_neb(neb,
                ml_calc,
                optimizer=FIRE,
                steps=100,
                f_max=0.05,
                f_max_ml=None,
                f_max_ml_ci=None,
                steps_ml=150,
                steps_ml_ci=150,
                r_max=None,
                callback_after_ml_neb=None):
    """
    """
    images = neb.images
    N_atoms = len(images[0])
    # save initial path as the machine learning NEB run is always restarted
    # from the initial path.
    initial_path = [image.get_positions().copy() for image in images]

    # set default values for the machine learning NEB calculations
    f_max_ml = f_max_ml or 10 * f_max
    f_max_ml_ci = f_max_ml_ci or 0.5 * f_max
    if r_max is None:
        # Koistinen et al. J. Chem. Phys. 147, 152720 (2017) suggest half of
        # the length of the initial path for r_max:
        r_max = 0.5 * sum([
            distance(images[i - 1], images[i]) for i in range(1, len(images))
        ])
        print('r_max = %.2f' % r_max)

    # make a copy of all images and attach a copy of the machine learning
    # calculator. Add a copy the whole band to the training images
    ml_images = [image.copy() for image in images]
    training_images = [image.copy() for image in images]
    for image, ml_image, training_image in zip(images, ml_images,
                                               training_images):
        ml_image.set_calculator(copy(ml_calc))
        training_image.set_calculator(
            SinglePointCalculator(
                forces=image.get_forces(apply_constraint=False),
                energy=image.get_potential_energy(),
                atoms=training_image))
        ml_calc.add_data(training_image)

    ml_neb = NEB(
        ml_images,
        k=neb.k,
        climb=neb.climb,
        method=neb.method,
        remove_rotation_and_translation=neb.remove_rotation_and_translation)

    for step_i in range(steps):
        # get the forces on the inner images including the spring forces and
        # reshape them
        true_forces = neb.get_forces().reshape(
            (len(neb.images) - 2, N_atoms, 3))
        print('Maximum force per image after %d evaluations of the band:' %
              (step_i + 1))
        print(np.sqrt((true_forces**2).sum(axis=2).max(axis=1)))
        # Check for convergence, following the default ase convergence
        # criterion
        if (true_forces**2).sum(axis=2).max() < f_max**2:
            print('Converged after %d evaluations of the band.' % (step_i + 1))
            break

        # fit the machine learning model to the training images
        ml_calc.fit()
        # save the fitted parameters of the machine learning model
        params = ml_calc.get_params()

        # reset machine learning path to initial path and set the parameters of
        # the individual ml_image calculators to the newly fitted values.
        for ml_image, init_positions in zip(ml_images, initial_path):
            ml_image.set_positions(init_positions.copy())
            ml_image.calc.set_params(**params)

        # optimize nudged elastic band on the machine learning PES. Start
        # without climbing. Should the first run converge. Switch climb = True
        # and optimize.
        ml_neb.climb = False
        if run_neb_on_ml_pes(ml_neb,
                             training_images,
                             optimizer=optimizer,
                             fmax=f_max_ml,
                             steps=steps_ml,
                             r_max=r_max)[0]:
            print('Switching to climbing image NEB')
            ml_neb.climb = True
            run_neb_on_ml_pes(ml_neb,
                              training_images,
                              optimizer=optimizer,
                              fmax=f_max_ml_ci,
                              steps=steps_ml_ci,
                              r_max=r_max)

        if callback_after_ml_neb is not None:
            callback_after_ml_neb(images, ml_images, ml_calc)

        # calculate the inner images at machine learning minimum energy path
        # and append the results to the training images
        for image, ml_image in zip(images[1:-1], ml_images[1:-1]):
            image.set_positions(ml_image.get_positions())
            training_image = image.copy()
            # calculation of the ab initio forces happens at this point because
            # get_potential_energy() and get_forces() are called for the new
            # positions of 'image'.
            training_image.set_calculator(
                SinglePointCalculator(
                    forces=image.get_forces(apply_constraint=False),
                    energy=image.get_potential_energy(),
                    atoms=training_image))
            training_images.append(training_image)
            ml_calc.add_data(training_image)
예제 #5
0
def test_neb(plt):
    from ase import Atoms
    from ase.constraints import FixAtoms
    import ase.io
    from ase.neb import NEB, NEBTools
    from ase.calculators.morse import MorsePotential
    from ase.optimize import BFGS, QuasiNewton

    def calc():
        # Common calculator for all images.
        return MorsePotential()

    # Create and relax initial and final states.
    initial = Atoms('H7',
                    positions=[(0, 0, 0), (1, 0, 0), (0, 1, 0), (1, 1, 0),
                               (0, 2, 0), (1, 2, 0), (0.5, 0.5, 1)],
                    constraint=[FixAtoms(range(6))],
                    calculator=calc())
    dyn = QuasiNewton(initial)
    dyn.run(fmax=0.01)

    final = initial.copy()
    final.calc = calc()
    final.positions[6, 1] = 2 - initial.positions[6, 1]
    dyn = QuasiNewton(final)
    dyn.run(fmax=0.01)

    # Run NEB without climbing image.
    fmax = 0.05
    nimages = 4

    images = [initial]
    for index in range(nimages - 2):
        images += [initial.copy()]
        images[-1].calc = calc()
    images += [final]

    neb = NEB(images)
    neb.interpolate()

    with BFGS(neb, trajectory='mep.traj') as dyn:
        dyn.run(fmax=fmax)

        # Check climbing image.
        neb.climb = True
        dyn.run(fmax=fmax)

    # Check NEB tools.
    nt_images = ase.io.read('mep.traj', index='-{:d}:'.format(nimages))
    nebtools = NEBTools(nt_images)
    nt_fmax = nebtools.get_fmax(climb=True)
    Ef, dE = nebtools.get_barrier()
    print(Ef, dE, fmax, nt_fmax)
    assert nt_fmax < fmax
    assert abs(Ef - 1.389) < 0.001
    # Plot one band.
    nebtools.plot_band()
    # Plot many (ok, 2) bands.
    nt_images = ase.io.read('mep.traj', index='-{:d}:'.format(2 * nimages))
    nebtools = NEBTools(nt_images)
    nebtools.plot_bands()