def test_combine_mm2(): # More biased initial positions for faster test. Set # to false for a slower, harder test. fast_test = True atoms = make_4mer() atoms.constraints = FixBondLengths([(3 * i + j, 3 * i + (j + 1) % 3) for i in range(int(len(atoms) // 3)) for j in [0, 1, 2]]) atoms.calc = TIP3P(np.Inf) tag = '4mer_tip3_opt.' opt = FIRE(atoms, logfile=tag + 'log', trajectory=tag + 'traj') opt.run(fmax=0.05) tip3_pos = atoms.get_positions() sig = np.array([sigma0, 0, 0]) eps = np.array([epsilon0, 0, 0]) rc = np.Inf idxes = [[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 10, 11], list(range(6)), list(range(9)), list(range(6, 12))] for ii, idx in enumerate(idxes): atoms = make_4mer() if fast_test: atoms.set_positions(tip3_pos) atoms.constraints = FixBondLengths([(3 * i + j, 3 * i + (j + 1) % 3) for i in range(len(atoms) // 3) for j in [0, 1, 2]]) atoms.calc = CombineMM(idx, 3, 3, TIP3P(rc), TIP3P(rc), sig, eps, sig, eps, rc=rc) tag = '4mer_combtip3_opt_{0:02d}.'.format(ii) opt = FIRE(atoms, logfile=tag + 'log', trajectory=tag + 'traj') opt.run(fmax=0.05) assert ((abs(atoms.positions - tip3_pos) < 1e-8).all()) print('{0}: {1!s:>28s}: Same Geometry as TIP3P'.format( atoms.calc.name, idx))
def _constrain_molecule(atoms, rattle=0.00001): """Helper function for place_and_preoptimize_adsorbates Args: atoms (ase.Atoms) : adsorbate molecule rattle (float) : standard deviation of the structure rattling Returns: list : list of different constraints from ase.constraints bonds, angles and dihedrals other than those of sp3-centers are constrained """ # Rattling is important, otherwise the optimization fails! atoms.rattle(stdev=rattle) nb_lst, nl = _get_neighbours(atoms, buffer_factor=1.5) fb = FixBondLengths(nb_lst) fa = _fix_nearest_atom_to_x(atoms, nl) angles = _get_all_angles(atoms, nb_lst) dihedrals = _get_all_dihedrals(atoms, angles) # keep dihedrals with sp2 or sp center # use neighbor list and a custom dictionary for number of nearest neighbors dihedrals = _filter_dihedrals(atoms, nl, dihedrals) print("kept dhls", dihedrals) fi = FixInternals(angles= angles, dihedrals = dihedrals) hookean_lst = _hookean_bonds(atoms, nb_lst) # IMPORTANT! fix binding atom at the end, otherwise it moves! atoms.set_constraint(hookean_lst.extend([fi, fb, fa])) return atoms
def get_energies(autotst_object): if isinstance(autotst_object, autotst.molecule.AutoTST_Molecule): ase_object = autotst_object.ase_molecule labels = [] if isinstance(autotst_object, autotst.reaction.AutoTST_Reaction): ase_object = autotst_object.ts.ase_ts labels = [] for atom in autotst_object.ts.rmg_ts.getLabeledAtoms().values(): labels.append(atom.sortingLabel) if isinstance(autotst_object, autotst.reaction.AutoTST_TS): ase_object = autotst_object.ase_ts labels = [] for atom in autotst_object.ts.rmg_ts.getLabeledAtoms().values(): labels.append(atom.sortingLabel) constrained_energy = ase_object.get_potential_energy() ase_copy = ase_object.copy() ase_copy.set_calculator(ase_object.get_calculator()) ase_copy.set_constraint( FixBondLengths(list(itertools.combinations(labels, 2)))) opt = BFGS(ase_copy) opt.run(fmax=0.01) relaxed_energy = ase_copy.get_potential_energy() return constrained_energy, relaxed_energy, ase_copy
def FixBlock(indices_list): bonds = [] for indices in indices_list: for i in range(len(indices) - 1): for j in range(i + 1, len(indices)): bonds.append([indices[i], indices[j]]) return FixBondLengths(bonds)
def test_rattle(): i = LJInteractions({('O', 'O'): (epsilon0, sigma0)}) for calc in [ TIP3P(), SimpleQMMM([0, 1, 2], TIP3P(), TIP3P(), TIP3P()), EIQMMM([0, 1, 2], TIP3P(), TIP3P(), i) ]: dimer = s22('Water_dimer') for m in [0, 3]: dimer.set_angle(m + 1, m, m + 2, angleHOH) dimer.set_distance(m, m + 1, rOH, fix=0) dimer.set_distance(m, m + 2, rOH, fix=0) fixOH1 = [(3 * i, 3 * i + 1) for i in range(2)] fixOH2 = [(3 * i, 3 * i + 2) for i in range(2)] fixHH = [(3 * i + 1, 3 * i + 2) for i in range(2)] dimer.set_constraint(FixBondLengths(fixOH1 + fixOH2 + fixHH)) dimer.calc = calc e = dimer.get_potential_energy() md = VelocityVerlet(dimer, 8.0 * units.fs, trajectory=calc.name + '.traj', logfile=calc.name + '.log', loginterval=5) md.run(25) de = dimer.get_potential_energy() - e assert abs(de - -0.028) < 0.001
def test_CO2_Au111(wrap): zpos = cos(134.3 / 2.0 * pi / 180.0) * 1.197 xpos = sin(134.3 / 2.0 * pi / 180.0) * 1.19 co2 = Atoms('COO', positions=[(-xpos + 1.2, 0, -zpos), (-xpos + 1.2, -1.1, -zpos), (-xpos + 1.2, 1.1, -zpos)]) slab = fcc111('Au', size=(2, 2, 4), vacuum=2 * 5, orthogonal=True) slab.center() add_adsorbate(slab, co2, 1.5, 'bridge') slab.set_pbc((True, True, False)) d0 = co2.get_distance(-3, -2) d1 = co2.get_distance(-3, -1) calc = EMT() slab.calc = calc if wrap: # Remap into the cell so bond is actually wrapped: slab.set_scaled_positions(slab.get_scaled_positions() % 1.0) constraint = FixBondLengths([[-3, -2], [-3, -1]]) slab.set_constraint(constraint) dyn = BFGS(slab, trajectory='relax_%d.traj' % wrap) dyn.run(fmax=0.05) assert abs(slab.get_distance(-3, -2, mic=1) - d0) < 1e-9 assert abs(slab.get_distance(-3, -1, mic=1) - d1) < 1e-9
def partial_optimize_mol(autotst_object): """ # CURRENTLY BROKEN """ if isinstance(autotst_object, autotst.species.Species): ase_object = autotst_object.ase_molecule labels = [] if isinstance(autotst_object, autotst.reaction.Reaction): ase_object = autotst_object.ts.ase_ts labels = [] for atom in autotst_object.ts.rmg_ts.getLabeledAtoms().values(): labels.append(atom.sortingLabel) if isinstance(autotst_object, autotst.reaction.TS): ase_object = autotst_object.ase_ts labels = [] for atom in autotst_object.ts.rmg_ts.getLabeledAtoms().values(): labels.append(atom.sortingLabel) ase_copy = ase_object.copy() ase_copy.set_calculator(ase_object.get_calculator()) ase_copy.set_constraint( FixBondLengths(list(itertools.combinations(labels, 2)))) opt = BFGS(ase_copy) complete = opt.run(fmax=0.01, steps=5) relaxed_energy = ase_copy.get_potential_energy() return relaxed_energy, ase_copy
def make_dimer(constraint=True): """Prepare atoms object for testing""" dimer = s22.create_s22_system("Water_dimer") calc = TIP3P(rc=9.0) dimer.calc = calc if constraint: dimer.constraints = FixBondLengths([(3 * i + j, 3 * i + (j + 1) % 3) for i in range(2) for j in [0, 1, 2]]) return dimer
def opt_conf(conformer, calculator, i): """ A helper function to optimize the geometry of a conformer. Only for use within this parent function """ labels = [] for bond in conformer.bonds: labels.append(bond.atom_indices) if isinstance(conformer, TS): label = conformer.reaction_label ind1 = conformer.rmg_molecule.getLabeledAtom("*1").sortingLabel ind2 = conformer.rmg_molecule.getLabeledAtom("*3").sortingLabel labels.append([ind1, ind2]) type = 'ts' else: label = conformer.smiles type = 'species' if isinstance(calc, FileIOCalculator): if calculator.directory: directory = calculator.directory else: directory = 'conformer_logs' calculator.label = "{}_{}".format(conformer.smiles, i) calculator.directory = os.path.join( directory, label, '{}_{}'.format(conformer.smiles, i)) if not os.path.exists(calculator.directory): try: os.makedirs(calculator.directory) except OSError: logging.info("An error occured when creating {}".format( calculator.directory)) calculator.atoms = conformer.ase_molecule from ase.constraints import FixBondLengths c = FixBondLengths(labels) conformer.ase_molecule.set_constraint(c) conformer.ase_molecule.set_calculator(calculator) opt = BFGS(conformer.ase_molecule, logfile=None) opt.run() conformer.update_coords_from("ase") energy = get_energy(conformer) return_dict[i] = (energy, conformer.ase_molecule.arrays, conformer.ase_molecule.get_all_distances())
def test_fixbonds(): """Test Atoms.__delitem__ with FixAtoms constraint.""" from ase import Atoms from ase.constraints import FixBondLengths a = Atoms('H3') a.constraints = FixBondLengths([(1, 2)]) assert (a[:].constraints[0].pairs == [(1, 2)]).all() assert (a[1:].constraints[0].pairs == [(0, 1)]).all() assert len(a[2:].constraints) == 0 assert len(a[1:2].constraints) == 0 assert len(a[:2].constraints) == 0 assert len(a[:1].constraints) == 0 # Execise Atoms.__init__: Atoms(a)
def test_getindices(): from ase.build import fcc111 from ase.constraints import (FixAtoms, FixBondLengths, FixLinearTriatomic, FixInternals, Hookean, constrained_indices) slab = fcc111('Pt', (4, 4, 4)) C1 = FixAtoms([0, 2, 4]) C2 = FixBondLengths([[0, 1], [0, 2]]) C3 = FixInternals(bonds=[[1, [7, 8]], [1, [8, 9]]]) C4 = Hookean(a1=30, a2=40, rt=1.79, k=5.) C5 = FixLinearTriatomic(triples=[(0, 1, 2), (3, 4, 5)]) slab.set_constraint([C1, C2, C3, C4, C5]) assert all( constrained_indices(slab, (FixAtoms, FixBondLengths)) == [0, 1, 2, 4]) assert all( constrained_indices(slab, (FixBondLengths, FixLinearTriatomic)) == [0, 1, 2, 3, 4, 5]) assert all( constrained_indices(slab) == [0, 1, 2, 3, 4, 5, 7, 8, 9, 30, 40])
def constrain_ads_bonds(host): """Constrains the distance between atoms in adsorbate to adjacent adsorbate atoms :param host: host zeolite with adsorbate :return: host zeolite with constrained adsorbate Args: host: """ atom_types = host.get_atom_types() ads_inds = [atom_types[i] for i in atom_types.keys() if 'adsorbate' in i] # gets the indicies of adsorbate atoms nl = NeighborList(natural_cutoffs(host), self_interaction=False, bothways=True) nl.update(host) bonds_to_fix = [] for ind in ads_inds: neigb_list = [j for j in nl.get_neighbors(ind)[0] if j in ads_inds] # indicies of adsorbate atom neighbors for neighb_ind in neigb_list: # makes pairs of adjacent atom indicies, small index first if neighb_ind > ind: bond_pair = [ind, neighb_ind] else: bond_pair = [neighb_ind, ind] # adds bond pair to list iff not already there if bond_pair not in bonds_to_fix: bonds_to_fix.append(bond_pair) else: pass c = FixBondLengths(bonds_to_fix) host.set_constraint(c) # should apply change to a copy?? return host
from ase.build import fcc111 from ase.constraints import (FixAtoms, FixBondLengths, FixInternals, Hookean, constrained_indices) slab = fcc111('Pt', (4, 4, 4)) C1 = FixAtoms([0, 2, 4]) C2 = FixBondLengths([[0, 1], [0, 2]]) C3 = FixInternals(bonds=[[1, [7, 8]], [1, [8, 9]]]) C4 = Hookean(a1=30, a2=40, rt=1.79, k=5.) slab.set_constraint([C1, C2, C3, C4]) assert all( constrained_indices(slab, (FixAtoms, FixBondLengths)) == [0, 1, 2, 4]) assert all(constrained_indices(slab) == [0, 1, 2, 4, 7, 8, 9, 30, 40])
def relax_precon(atoms, calc, fmax=5e-2, smax=1e-4, variable_cell=False, trajfile=None, logfile=None, maxsteps=10000, verbose=True, dEmin=1e-3, a_min=1e-8, optimizer='LBFGS', cellbounds=None, fix_bond_lengths_pairs=None, debug=False): """ Locally optimizes the geometry using the preconditioned optimizers. atoms: the Atoms object calc: a calculator instance to attach to the Atoms object fmax: the force convergence criterion (in eV/Angstrom) smax: the stress convergence criterion (in eV/Angstrom^3) variable_cell: whether to also optimize the cell vectors trajfile: filename of the trajectory to attach to the optimizers logfile: filename of the logfile for the optimizers maxsteps: maximum allowed total number of ionic steps verbose: whether to print output or remain silent dEmin: minimum (absolute) energy difference for the main loop iterations; if the energy difference is smaller, the minimization is aborted a_min: minimal value for the linesearch parameter in the PreconLBFGS optimizer optimizer: 'LBFGS' or 'FIRE', the preferred type of (preconditioned) optimizer cellbounds: ase.ga.bulk_utilities.CellBounds instance for setting bounds on the cell shape and size during variable-cell relaxation fix_bond_lengths_pairs: list of (i,j) tuples of atom pairs for which the (minimum image) bond distance will be kept fixed debug: if True, extra output may be printed to stdout """ assert optimizer in ['LBFGS', 'FIRE'] class UnitCellFilterFixBondLengthsWrapper(UnitCellFilterFixBondLengths): """ Wrapper to nitCellFilterFixBondLengths, required because of ase.optimize.precon.estimate_mu. """ def __init__(self, atoms): UnitCellFilterFixBondLengths.__init__(self, atoms, maxiter=1000, pairs=fix_bond_lengths_pairs) if variable_cell: atoms.set_pbc(True) else: smax = None cellbounds = None atoms.wrap() atoms.set_calculator(calc) nsteps = 0 if trajfile is not None: if os.path.exists(trajfile): os.remove(trajfile) traj = Trajectory(trajfile, 'a', atoms) else: traj = None if fix_bond_lengths_pairs is not None: original_constraints = [c for c in atoms.constraints] bond_lengths = np.zeros(len(fix_bond_lengths_pairs)) for i, ab in enumerate(fix_bond_lengths_pairs): bond_lengths[i] = atoms.get_distance(ab[0], ab[1], mic=True) fbl_constraint = FixBondLengths(fix_bond_lengths_pairs) atoms.set_constraint(original_constraints + [fbl_constraint]) if variable_cell: # Start with partial relaxation using fixed cell vectors if fix_bond_lengths_pairs or optimizer == 'FIRE': # PreconFIRE is more suitable in this case dyn = PreconFIRE_My(atoms, precon=Exp(A=3), use_armijo=True, variable_cell=False, logfile=logfile) else: dyn = PreconLBFGS_My(atoms, precon=Exp(A=3), use_armijo=True, variable_cell=False, logfile=logfile, maxstep=0.2, a_min=a_min) attach1 = VarianceError(atoms, dyn, N=5) dyn.attach(attach1) attach2 = DivergenceError(atoms, dyn, N=2, max_slope=0.05) dyn.attach(attach2) if traj is not None: dyn.attach(traj) try: dyn.run(fmax=1., steps=25) except RuntimeError as err: if debug: print(err.message, flush=True) nsteps += dyn.get_number_of_steps() if variable_cell and fix_bond_lengths_pairs is not None: # Fixing bond lengths will be taken care of # by the modified UnitCellFilter atoms.set_constraint(original_constraints) atoms = UnitCellFilterFixBondLengthsWrapper(atoms) elif variable_cell: atoms = UnitCellFilter(atoms) steps = 30 niter = 0 maxiter = 50 nerr = 0 maxerr = 10 e_prev = 1e64 while nsteps < maxsteps and niter < maxiter and nerr < maxerr: e = atoms.get_potential_energy() if abs(e - e_prev) < dEmin: break e_prev = e try: if optimizer == 'LBFGS': dyn = PreconLBFGS_My(atoms, precon=Exp(A=3), use_armijo=True, logfile=logfile, a_min=a_min, variable_cell=False, maxstep=0.2, cellbounds=cellbounds) elif optimizer == 'FIRE': dyn = PreconFIRE_My(atoms, precon=Exp(A=3), use_armijo=True, variable_cell=False, logfile=logfile, maxmove=0.5, cellbounds=cellbounds) dyn.e1 = None try: dyn._just_reset_hessian except AttributeError: dyn._just_reset_hessian = True if traj is not None: dyn.attach(traj) attach1 = VarianceError(atoms, dyn, N=5) dyn.attach(attach1) attach2 = DivergenceError(atoms, dyn, N=2, max_slope=0.05) dyn.attach(attach2) dyn.run(fmax=fmax, smax=smax, steps=steps) nsteps += dyn.get_number_of_steps() except RuntimeError as err: if debug: print(err.message, flush=True) nerr += 1 nsteps += dyn.get_number_of_steps() dyn = PreconFIRE_My(atoms, precon=Exp(A=3), use_armijo=False, variable_cell=False, logfile=logfile, maxmove=0.5, cellbounds=cellbounds) if traj is not None: dyn.attach(traj) attach1 = VarianceError(atoms, dyn, N=5) dyn.attach(attach1) attach2 = DivergenceError(atoms, dyn, N=2, max_slope=0.05) dyn.attach(attach2) try: dyn.run(fmax=fmax, smax=smax, steps=steps) except RuntimeError as err: if debug: print(err.message, flush=True) nerr += 1 nsteps += dyn.get_number_of_steps() niter += 1 try: if dyn.converged(): break except RuntimeError: break if isinstance(atoms, UnitCellFilterFixBondLengthsWrapper): atoms = atoms.atoms atoms.wrap() pos = atoms.get_positions() cell = atoms.get_cell() pbc = atoms.get_pbc() for (i1, i2), bl in zip(fix_bond_lengths_pairs, bond_lengths): vec = pos[i2] - pos[i1] vec = find_mic([vec], cell, pbc)[0][0] pos[i2] = pos[i1] + vec * bl / np.linalg.norm(vec) atoms.set_positions(pos) atoms = UnitCellFilterFixBondLengthsWrapper(atoms) calculate_regular = False if fix_bond_lengths_pairs is not None: # Guarantee that the fixed bonds have the specified length pos = atoms.get_positions() if isinstance(atoms, Filter): cell = atoms.atoms.get_cell() pbc = atoms.atoms.get_pbc() else: cell = atoms.get_cell() pbc = atoms.get_pbc() for (i1, i2), bl in zip(fix_bond_lengths_pairs, bond_lengths): vec = pos[i2] - pos[i1] vec = find_mic([vec], cell, pbc)[0][0] pos[i2] = pos[i1] + vec * bl / np.linalg.norm(vec) if isinstance(atoms, Filter): atoms = atoms.atoms atoms.set_positions(pos[:len(atoms)]) atoms = UnitCellFilterFixBondLengthsWrapper(atoms) try: E = atoms.get_potential_energy() F = atoms.get_forces()[:len(atoms.atoms)] S = atoms.stress except RuntimeError: calculate_regular = True else: atoms.set_constraint(original_constraints) atoms.set_positions(pos) atoms.set_constraint(original_constraints + [fbl_constraint]) calculate_regular = True if isinstance(atoms, Filter): atoms = atoms.atoms if fix_bond_lengths_pairs is None or calculate_regular: E = atoms.get_potential_energy() F = atoms.get_forces() S = atoms.get_stress() if variable_cell else None atoms.wrap() if verbose: print('Done E=%8.3f, maxF=%5.3f, maxS=%5.3e, nsteps=%d' % \ (E, (F**2).sum(axis=1).max()**0.5, 0. if S is None else np.max(np.abs(S)), nsteps), flush=True) finalize(atoms, energy=E, forces=F, stress=S) return atoms
def atoms(): dimer = s22.create_s22_system("Water_dimer") dimer.constraints = FixBondLengths( [(3 * i + j, 3 * i + (j + 1) % 3) for i in range(2) for j in [0, 1, 2]] ) return dimer
atoms = make_atoms() atoms2 = make_atoms() atoms2.translate([0., 3, 0]) atoms2.rotate(180, 'y') atoms2.translate([3, 0, 0]) atoms += atoms2 return atoms # More biased initial positions for faster test. Set # to false for a slower, harder test. fast_test = True atoms = make_4mer() atoms.constraints = FixBondLengths([(3 * i + j, 3 * i + (j + 1) % 3) for i in range(int(len(atoms) // 3)) for j in [0, 1, 2]]) atoms.calc = TIP3P(np.Inf) tag = '4mer_tip3_opt.' opt = FIRE(atoms, logfile=tag + 'log', trajectory=tag + 'traj') opt.run(fmax=0.05) tip3_pos = atoms.get_positions() sig = np.array([sigma0, 0, 0]) eps = np.array([epsilon0, 0, 0]) rc = np.Inf idxes = [[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 10, 11], list(range(6)), list(range(9)), list(range(6, 12))]
i = LJInteractions({('O', 'O'): (epsilon0, sigma0)}) for calc in [ TIP3P(), SimpleQMMM([0, 1, 2], TIP3P(), TIP3P(), TIP3P()), EIQMMM([0, 1, 2], TIP3P(), TIP3P(), i) ]: dimer = s22('Water_dimer') for m in [0, 3]: dimer.set_angle(m + 1, m, m + 2, angleHOH) dimer.set_distance(m, m + 1, rOH, fix=0) dimer.set_distance(m, m + 2, rOH, fix=0) fixOH1 = [(3 * i, 3 * i + 1) for i in range(2)] fixOH2 = [(3 * i, 3 * i + 2) for i in range(2)] fixHH = [(3 * i + 1, 3 * i + 2) for i in range(2)] dimer.set_constraint(FixBondLengths(fixOH1 + fixOH2 + fixHH)) dimer.calc = calc e = dimer.get_potential_energy() md = VelocityVerlet(dimer, 2.0 * units.fs, trajectory=calc.name + '.traj', logfile=calc.name + '.log', loginterval=20) md.run(100) de = dimer.get_potential_energy() - e assert abs(de - -0.028) < 0.001
"""Test Atoms.__delitem__ with FixAtoms constraint.""" from ase import Atoms from ase.constraints import FixBondLengths a = Atoms('H3') a.constraints = FixBondLengths([(1, 2)]) assert (a[:].constraints[0].pairs == [(1, 2)]).all() assert (a[1:].constraints[0].pairs == [(0, 1)]).all() assert len(a[2:].constraints) == 0 assert len(a[1:2].constraints) == 0 assert len(a[:2].constraints) == 0 assert len(a[:1].constraints) == 0 # Execise Atoms.__init__: Atoms(a)
def relax_one(t, kptdensity=3.5): cellbounds = CellBounds(bounds={'phi': [0.1 * 180., 0.9 * 180.], 'chi': [0.1 * 180., 0.9 * 180.], 'psi': [0.1 * 180., 0.9 * 180.], 'a': [1.5, 20], 'b': [1.5, 20], 'c':[1.5, 20]}) if not cellbounds.is_within_bounds(t.get_cell()): print('Candidate outside cellbounds -- skipping') finalize(t, energy=1e9, forces=None, stress=None) return t tags = t.get_tags() pos = t.get_positions() pairs = [] for tag in list(set(tags)): indices = list(np.where(tags == tag)[0]) if len(indices) == 2: pairs.append(indices) c = FixBondLengths(pairs) t.set_constraint(c) blmin = {(1, 1): 1.8, (1, 8): 0.9, (1, 46): 1.8, (8, 8): 2.0, (8, 46): 1.5, (46, 46): 1.5} t = push_apart(t, blmin, variable_cell=True) del t.constraints oh_bondlength = 0.97907 for (o_atom, h_atom) in pairs: vec = t.get_distance(o_atom, h_atom, mic=True, vector=True) pos[h_atom] = pos[o_atom] + vec * oh_bondlength / np.linalg.norm(vec) t.set_positions(pos) print('Starting relaxation', flush=True) clock = time() t.wrap() calc = DftbPlusCalculator(t, kpts=0.66*kptdensity, use_spline=True, read_chg=True, maximum_angular_momenta={'Pd': 2, 'H': 0, 'O': 1}) try: t = relax_precon(t, calc, fmax=2e-1, smax=1e-2, variable_cell=True, optimizer='LBFGS', a_min=1e-4, cellbounds=cellbounds, fix_bond_lengths_pairs=pairs, logfile='opt_first.log', trajfile='opt_first.traj') except (IOError, TypeError, RuntimeError, UnboundLocalError) as err: # SCC or geometry optimization convergence problem print(err) if isinstance(t, Filter): t = t.atoms del t.constraints t.wrap() calc = DftbPlusCalculator(t, kpts=kptdensity, use_spline=True, read_chg=True, maximum_angular_momenta={'Pd': 2, 'H': 0, 'O': 1}) try: t = relax_precon(t, calc, fmax=1e-1, smax=5e-3, variable_cell=True, optimizer='LBFGS', a_min=1e-4, cellbounds=cellbounds, fix_bond_lengths_pairs=pairs, logfile='opt.log', trajfile='opt.traj') except (IOError, TypeError, RuntimeError, UnboundLocalError) as err: # SCC or geometry optimization convergence problem print(err) try: t = read('opt.traj@-1') energy = t.get_potential_energy() forces = t.get_forces() stress = t.get_stress() except (FileNotFoundError, UnknownFileTypeError) as err: print(err) energy, forces, stress = (1e9, None, None) if isinstance(t, Filter): t = t.atoms finalize(t, energy=energy, forces=forces, stress=stress) print('Relaxing took %.3f seconds.' % (time() - clock), flush=True) os.system('mv opt_first.traj prev_first.traj') os.system('mv opt_first.log prev_first.log') os.system('mv opt.log prev.log') os.system('mv opt.traj prev.traj') penalize(t) return t
from math import sqrt, pi from ase import Atoms from ase.calculators.emt import EMT from ase.constraints import FixBondLengths from ase.optimize import BFGS, QuasiNewton from ase.neb import SingleCalculatorNEB from ase.lattice.surface import fcc111, add_adsorbate from math import sqrt, cos, sin zpos = cos(134.3 / 2.0 * pi / 180.0) * 1.197 xpos = sin(134.3 / 2.0 * pi / 180.0) * 1.19 co2 = Atoms('COO', positions=[(-xpos + 1.2, 0, -zpos), (-xpos + 1.2, -1.1, -zpos), (-xpos + 1.2, 1.1, -zpos)]) slab = fcc111('Au', size=(2, 2, 4), vacuum=2 * 5, orthogonal=True) slab.center() add_adsorbate(slab, co2, 1.5, 'bridge') slab.set_pbc((True, True, False)) d0 = co2.get_distance(-3, -2) d1 = co2.get_distance(-3, -1) calc = EMT() slab.set_calculator(calc) constraint = FixBondLengths([[-3, -2], [-3, -1]]) slab.set_constraint(constraint) dyn = BFGS(slab, trajectory='relax.traj') dyn.run(fmax=0.05) assert abs(co2.get_distance(-3, -2) - d0) < 1e-14 assert abs(co2.get_distance(-3, -1) - d1) < 1e-14
from ase.optimize.precon import PreconLBFGS, Exp from gpaw import GPAW r = rOH a = angleHOH / 180 * pi interaction = LJInteractions({('O', 'O'): (epsilon0, sigma0)}) for selection in [[0, 1, 2], [3, 4, 5]]: name = ''.join(str(i) for i in selection) dimer = Atoms('OH2OH2', [(0, 0, 0), (-r * cos(a / 2), r * sin(a / 2), 0), (-r * cos(a / 2), -r * sin(a / 2), 0), (0, 0, 0), (-r * cos(a), 0, r * sin(a)), (-r, 0, 0)]) dimer.positions[3:, 0] += 2.8 dimer.constraints = FixBondLengths([ ((selection[i] + 3) % 6, (selection[i - 1] + 3) % 6) for i in range(3) ]) dimer.calc = EIQMMM(selection, GPAW(txt=name + '.txt', h=0.16), TIP4P(), interaction, vacuum=4, embedding=Embedding(rc=0.2, rc2=20, width=1), output=name + '.out') opt = LBFGS(dimer, trajectory=name + '.traj') opt.run(0.02) monomer = dimer[selection] monomer.center(vacuum=4) monomer.calc = GPAW(txt=name + 'M.txt', h=0.16)
bond2 += delta bond1 -= delta / 4 else: print('Shrinking Bond 2') bond2 -= delta bond1 += delta / 4 bonds = [ [ bond1, [ i['DIFFATOM'], i['CONSATOM1'] ] ], [ bond2, [ i['DIFFATOM'], i['CONSATOM2'] ] ] ] return FixInternals(bonds=bonds) else: from ase.constraints import FixBondLengths print('Constraining Bonds') c = FixBondLengths([[i['DIFFATOM'], i['CONSATOM1']], [i['DIFFATOM'], i['CONSATOM2']]]) elif 'CONSATOM3' in i: from Classes_ASE import InPlane as KeepInPlane print('3 Atom Constraint') c = KeepInPlane(i['DIFFATOM'], (i['CONSATOM1'], i['CONSATOM2'], i['CONSATOM3'])) elif 'SURFACE_REFERENCE' in i: from Classes_ASE import InMPPlane_SurfaceReference as KeepInPlane print('Perpendicular Constraint using Reference POSCAR') c=KeepInPlane(i['DIFFATOM'], (i['CONSATOM1'], i['CONSATOM2']), i['SURFACE_REFERENCE']) else: from Classes_ASE import InMPPlaneXY as KeepInPlane print('Perpendicular Constraint') c = KeepInPlane(i['DIFFATOM'], (i['CONSATOM1'], i['CONSATOM2'])) atoms.wrap(atoms.get_scaled_positions()[i['DIFFATOM']])
from ase.io import Trajectory import ase.units as u md_cls_and_kwargs = [ (VelocityVerlet, {}), (Langevin, { "temperature": 300 * u.kB, "friction": 0.02 }), ] # prepare atoms object for testing dimer = s22.create_s22_system("Water_dimer") calc = TIP3P(rc=9.0) dimer.constraints = FixBondLengths([(3 * i + j, 3 * i + (j + 1) % 3) for i in range(2) for j in [0, 1, 2]]) def fmax(forces): return np.sqrt((forces**2).sum(axis=1).max()) def test_opt(cls, atoms, calc, logfile="opt.log", trajectory="opt.traj"): """run optimization and verify that log and trajectory coincide""" # clean files to make sure the correct ones are tested for file in (*Path().glob("*.log"), *Path().glob("*.traj")): file.unlink() opt_atoms = atoms.copy() opt_atoms.constraints = atoms.constraints
from ase.lattice.surface import fcc111, add_adsorbate from math import sqrt, cos, sin for mic in [False, True]: zpos = cos(134.3 / 2.0 * pi / 180.0) * 1.197 xpos = sin(134.3 / 2.0 * pi / 180.0) * 1.19 co2 = Atoms('COO', positions=[(-xpos + 1.2, 0, -zpos), (-xpos + 1.2, -1.1, -zpos), (-xpos + 1.2, 1.1, -zpos)]) slab = fcc111('Au', size=(2, 2, 4), vacuum=2 * 5, orthogonal=True) slab.center() add_adsorbate(slab, co2, 1.5, 'bridge') slab.set_pbc((True, True, False)) d0 = co2.get_distance(-3, -2) d1 = co2.get_distance(-3, -1) calc = EMT() slab.set_calculator(calc) if mic: # Remap into the cell so bond is actually wrapped. slab.set_scaled_positions(slab.get_scaled_positions() % 1.0) constraint = FixBondLengths([[-3, -2], [-3, -1]], mic=True, atoms=slab) else: constraint = FixBondLengths([[-3, -2], [-3, -1]]) slab.set_constraint(constraint) dyn = BFGS(slab, trajectory='relax_%s.traj' % ('mic' if mic else 'no_mic')) dyn.run(fmax=0.05) assert abs(slab.get_distance(-3, -2, mic=mic) - d0) < 1e-9 assert abs(slab.get_distance(-3, -1, mic=mic) - d1) < 1e-9
def opt_conf(i, rmsd_cutoff): """ A helper function to optimize the geometry of a conformer. Only for use within this parent function """ conformer = conformers[i] calculator = conformer.ase_molecule.get_calculator() labels = [] for bond in conformer.get_bonds(): labels.append(bond.atom_indices) if isinstance(conformer, TS): label = conformer.reaction_label ind1 = conformer.rmg_molecule.get_labeled_atoms("*1")[0].sorting_label ind2 = conformer.rmg_molecule.get_labeled_atoms("*3")[0].sorting_label labels.append([ind1, ind2]) type = 'ts' else: label = conformer.smiles type = 'species' if isinstance(calc, FileIOCalculator): if calculator.directory: directory = calculator.directory else: directory = 'conformer_logs' calculator.label = "{}_{}".format(conformer.smiles, i) calculator.directory = os.path.join(directory, label,'{}_{}'.format(conformer.smiles, i)) if not os.path.exists(calculator.directory): try: os.makedirs(calculator.directory) except OSError: logging.info("An error occured when creating {}".format(calculator.directory)) calculator.atoms = conformer.ase_molecule conformer.ase_molecule.set_calculator(calculator) opt = BFGS(conformer.ase_molecule, logfile=None) if type == 'species': if isinstance(i,int): c = FixBondLengths(labels) conformer.ase_molecule.set_constraint(c) try: opt.run(steps=1e6) except RuntimeError: logging.info("Optimization failed...we will use the unconverged geometry") pass if str(i) == 'ref': conformer.update_coords_from("ase") try: rmg_mol = Molecule() rmg_mol.from_xyz( conformer.ase_molecule.arrays["numbers"], conformer.ase_molecule.arrays["positions"] ) if not rmg_mol.is_isomorphic(reference_mol): logging.info("{}_{} is not isomorphic with reference mol".format(conformer,str(i))) return False except AtomTypeError: logging.info("Could not create a RMG Molecule from optimized conformer coordinates...assuming not isomorphic") return False if type == 'ts': c = FixBondLengths(labels) conformer.ase_molecule.set_constraint(c) try: opt.run(fmax=0.20, steps=1e6) except RuntimeError: logging.info("Optimization failed...we will use the unconverged geometry") pass conformer.update_coords_from("ase") energy = get_energy(conformer) conformer.energy = energy if len(return_dict)>0: conformer_copy = conformer.copy() for index,post in return_dict.items(): conf_copy = conformer.copy() conf_copy.ase_molecule.positions = post conf_copy.update_coords_from("ase") rmsd = rdMolAlign.GetBestRMS(conformer_copy.rdkit_molecule,conf_copy.rdkit_molecule) if rmsd <= rmsd_cutoff: return True if str(i) != 'ref': return_dict[i] = conformer.ase_molecule.get_positions() return True
def delete_single_atom_with_constraint(atoms=None, indice_to_delete=None): if indice_to_delete is None: return # nothing to delete elif indice_to_delete > len(atoms)-1: raise RuntimeError("try too remove too many atoms?") # I have to teach each fix objects individually, how can I make it smarter? hookean_pairs = [] fix_atoms_indices = [] fix_bondlengths_indices = None never_delete_indices = [] fix_lines_indices = [] for c in atoms.constraints: if isinstance(c, FixAtoms): fix_atoms_indices.append(c.get_indices()) elif isinstance(c, Hookean): hookean_pairs.append([c.get_indices(), c.threshold, c.spring]) elif isinstance(c, FixBondLengths): if fix_bondlengths_indices is not None: raise RuntimeError("Do you have more than one FixBondLengths?") fix_bondlengths_indices = c.pairs.copy() elif isinstance(c, NeverDelete): for ind in c.get_indices(): never_delete_indices.append(ind) elif isinstance(c, FixedLine): fix_lines_indices.append([c.a, c.dir]) else: try: cn = c.__class__.__name__ except AttributeError: cn = "Unknown" raise RuntimeError("constraint type %s is not supported" % cn) new_constraints = [] for old_inds in fix_atoms_indices: new_inds = [] for ind in old_inds: if ind < indice_to_delete: new_inds.append(ind) elif ind > indice_to_delete: new_inds.append(ind - 1) else: continue if len(new_inds) > 0: new_constraints.append(FixAtoms(indices=new_inds)) for old_inds, rt, k in hookean_pairs: if indice_to_delete in old_inds: continue new_inds = [] for ind in old_inds: if ind < indice_to_delete: new_inds.append(ind) else: new_inds.append(ind-1) new_constraints.append(Hookean(a1=new_inds[0], a2=new_inds[1], rt=rt, k=k)) for ind, direction in fix_lines_indices: if ind == indice_to_delete: continue elif ind < indice_to_delete: new_constraints.append(FixedLine(ind, direction=direction)) else: new_constraints.append(FixedLine(ind-1,direction=direction)) if fix_bondlengths_indices is not None: number_of_cons, ncols = fix_bondlengths_indices.shape assert ncols == 2 new_inds = [] for ic in range(number_of_cons): ind1, ind2 = fix_bondlengths_indices[ic][0], fix_bondlengths_indices[ic][1] if ind1 == indice_to_delete or ind2 == indice_to_delete: continue else: pairs = [] if ind1 < indice_to_delete: pairs.append(ind1) else: pairs.append(ind1-1) if ind2 < indice_to_delete: pairs.append(ind2) else: pairs.append(ind2-1) new_inds.append(pairs) if len(new_inds) > 0: new_constraints.append(FixBondLengths(pairs=new_inds)) if len(never_delete_indices) > 0: new_inds = [] for ind in never_delete_indices: if ind < indice_to_delete: new_inds.append(ind) elif ind > indice_to_delete: new_inds.append(ind - 1) if len(new_inds) > 0: new_constraints.append(NeverDelete(indices=new_inds)) # remove all the constraints atoms.set_constraint() del atoms[indice_to_delete] # add back the constraints atoms.set_constraint(new_constraints) return