Пример #1
1
def test_emt1():
    from ase import Atoms
    from ase.calculators.emt import EMT
    from ase.constraints import FixBondLength
    from ase.io import Trajectory
    from ase.optimize import BFGS

    a = 3.6
    b = a / 2
    cu = Atoms('Cu2Ag',
               positions=[(0, 0, 0), (b, b, 0), (a, a, b)],
               calculator=EMT())
    e0 = cu.get_potential_energy()
    print(e0)

    d0 = cu.get_distance(0, 1)
    cu.set_constraint(FixBondLength(0, 1))
    t = Trajectory('cu2ag.traj', 'w', cu)
    qn = BFGS(cu)
    qn.attach(t.write)

    def f():
        print(cu.get_distance(0, 1))

    qn.attach(f)
    qn.run(fmax=0.001)
    assert abs(cu.get_distance(0, 1) - d0) < 1e-14
Пример #2
1
def get_fingerprint(Optimizer, indiv, binsize, cutoffdist):
    """Function to calculate the fingerprint of a structure"""

    rs = numpy.linspace(0.0, cutoffdist, cutoffdist/binsize)
    indi = indiv[0]
    Vuc = indi.get_volume()
    if Optimizer.structure == 'Defect':
        solid = Atoms()
        solid.extend(indi)
        solid.extend(indiv.bulki)
    elif Optimizer.structure == 'Crystal':
        solid = indi.repeat([3, 3, 3])
    else:
        solid = indi.copy()

    syms = sorted(list(set([atm.symbol for atm in solid])))
    fingerprints = []
    for i in range(len(syms)):
        for j in range(i, len(syms)):
            indl = [atm for atm in indi if atm.symbol == syms[i]]
            ind = Atoms()
            for one in indl:
                ind.append(one)
            soll = [atm for atm in solid if atm.symbol == syms[j]]
            sol = Atoms()
            for one in soll:
                sol.append(one)
            soli = [atm for atm in solid if atm.symbol == syms[i]]
            value = []
            for R in rs:
                value2 = []
                for k in range(len(ind)):
                    value1 = []
                    for m in range(len(sol)):
                        if k != m:
                            rij = sol.get_distance(k, m, mic = True)
                            if rij == 0:
                                pass
                                #pdb.set_trace()
                            value1.append(dirac(R, a=rij, sig=0.02) * 1. / (4*math.pi * rij** 2*binsize * len(soli) * len(sol) / Vuc))
                    value2.append(sum(value1))
                value.append(sum(value2))
            fingerprints.append(value)

    fpt = []
    for one in fingerprints:
        fpt.extend(one)

    return fpt
Пример #3
1
def voids(atoms_in):
    """Find location and size of voids in a given structure.

    Returns the voids as 'X' atoms. The atoms' charge is misused
    to contain the voids' radius.
    """
    
    trials = 6  # XXX do not hardwire

    atoms = atoms_in.copy()
    # append moving atom
    atoms.append(Atom('X'))
    atoms.set_calculator(RepulsivePotential())

    voids_a = Atoms()
    voids_a.set_cell(atoms.get_cell())
    voids_a.set_pbc(atoms.get_pbc())

    positions = atoms.get_positions()
    for pos in positions[:-1]:
        for c in range(trials):
            positions[-1] = pos + 0.1 * np.random.uniform(-1, 1, size=3)
            atoms.set_positions(positions)
            
            # XXX do not hardwire
            relax = FIRE(atoms,
                         logfile=None
                         )
            # XXX do not hardwire
            relax.run(fmax=0.001, steps=100)
                
            # get minimal distance
            Rmin = 100000
            for b in range(len(atoms) - 1):
                R = atoms.get_distance(b, -1, mic=True)
                if R < Rmin:
                    Rmin = R

            # check if new or better
            voids_a.append(Atom('X',
                                atoms.get_positions()[-1],
                                charge=Rmin))
            voids_a.set_positions(voids_a.get_positions(wrap=True))

            remove = []
            last = len(voids_a) - 1
            for ia, a in enumerate(voids_a[:-1]):
                d = voids_a.get_distance(ia, -1, mic=True)
                if d < a.charge or d < Rmin:
                    if a.charge > Rmin:
                        remove.append(last)
                    else:
                        remove.append(ia)
            remove.sort()
            if last not in remove:
                p = voids_a.get_positions()[-1]
                print('found new void at [%g,%g,%g], R=%g' %
                      (p[0], p[1], p[2], Rmin))
            for a in remove[::-1]:
                if a != last:
                    p = voids_a.get_positions()[a]
                    print('removing void at [%g,%g,%g], R=%g' %
                          (p[0], p[1], p[2], voids_a[a].charge))
                voids_a.pop(a)

    return voids_a
Пример #4
1
def check_min_dist(Optimizer, totalsol, type='Defect', nat=None, min_len=0.7, STR=''):
        if type=='Defect' or type=='Crystal' or type=='Surface':
            if nat==None:
                nat=len(totalsol)
            cutoffs=[2.0 for one in totalsol]
            nl=NeighborList(cutoffs,bothways=True,self_interaction=False)
            nl.update(totalsol)
            for one in totalsol[0:nat]:
                nbatoms=Atoms()
                nbatoms.append(one)
                indices, offsets=nl.get_neighbors(one.index)
                for index, d in zip(indices,offsets):
                    index = int(index)
                    sym=totalsol[index].symbol
                    pos=totalsol[index].position + numpy.dot(d,totalsol.get_cell())
                    at=Atom(symbol=sym,position=pos)
                    nbatoms.append(at)
                while True:
                    dflag=False
                    for i in range(1,len(nbatoms)):
                        d=nbatoms.get_distance(0,i)
                        if d < min_len:
                            nbatoms.set_distance(0,i,min_len+.01,fix=0.5)
                            STR+='--- WARNING: Atoms too close (<0.7A) - Implement Move ---\n'
                            dflag=True
                    if dflag==False:
                        break
                for i in range(len(indices)):
                    totalsol[indices[i]].position=nbatoms[i+1].position
                totalsol[one.index].position=nbatoms[0].position
                nl.update(totalsol)
        elif type=='Cluster':
            if not 'LAMMPS' in Optimizer.modules:
                for i in range(len(totalsol)):
                    for j in range(len(totalsol)):
                        if i != j:
                            d=totalsol.get_distance(i,j)
                            if d < min_len:
                                totalsol.set_distance(i,j,min_len,fix=0.5)
                                STR+='--- WARNING: Atoms too close (<0.7A) - Implement Move ---\n'
            else:
                rank = MPI.COMM_WORLD.Get_rank()
                #logger = logging.getLogger(Optimizer.loggername)
                R = totalsol.arrays['positions']
                tol = 0.01
                epsilon = 0.05
                fix = 0.5
                
                closelist = numpy.arange(len(totalsol))
                iter = 0
                while len(closelist) > 0 and iter<2:
                    iter+=1
                    closelist = []
                    dist=spatial.distance.cdist(R,R)
                    numpy.fill_diagonal(dist,1.0)
                    smalldist = numpy.where(dist < min_len-tol)
   
                    for ind in range(len(smalldist[0])):
                        i = smalldist[0][ind]
                        j = smalldist[1][ind]
                        if i < j and dist[i][j] < min_len-tol:
                            closelist.append(i)
                            closelist.append(j)
                            if dist[i][j] > epsilon:
                                x = 1.0 - min_len / dist[i][j]
                                D = R[j]-R[i]
                                R[i] += (x * fix) * D
                                R[j] -= (x * (1.0 - fix)) * D
                            else:
                                R[i] += [0.2, 0.0, 0.0]
                                R[j] -= [0.2, 0.0, 0.0]
                            R2P = [R[i],R[j]]
                            dist2P=spatial.distance.cdist(R2P,R)
                            dist[i] = dist2P[0]
                            dist[j] = dist2P[1]
                            for k in range(len(R)):
                                dist[k][i] = dist[i][k]
                                dist[k][j] = dist[j][k]
                    closelist=list(set(closelist))
                    closelist.sort()
                    #if len(closelist) != 0:
                    #    logger.info('M:iter {0}, closelist size {1}'.format(iter,len(closelist)))
        else:
            print 'WARNING: In Check_Min_Dist in EvalEnergy: Structure Type not recognized'
        return totalsol, STR
Пример #5
1
    # plt.plot(D, E)

    F1 = np.polyval(np.polyder(np.polyfit(D, E, 7)), D)
    F2 = F[:, :3, 0].sum(1)
    error = abs(F1 - F2).max()

    dimer.constraints = FixInternals(
        bonds=[(r, (0, 2)), (r, (1, 2)),
               (r, (3, 5)), (r, (4, 5))],
        angles=[(a, (0, 2, 1)), (a, (3, 5, 4))])
    opt = GPMin(dimer,
               trajectory=calc.name + '.traj', logfile=calc.name + 'd.log')
    opt.run(0.01)

    e0 = dimer.get_potential_energy()
    d0 = dimer.get_distance(2, 5)
    R = dimer.positions
    v1 = R[1] - R[5]
    v2 = R[5] - (R[3] + R[4]) / 2
    a0 = np.arccos(np.dot(v1, v2) /
                   (np.dot(v1, v1) * np.dot(v2, v2))**0.5) / np.pi * 180
    fmt = '{0:>20}: {1:.3f} {2:.3f} {3:.3f} {4:.1f}'
    print(fmt.format(calc.name, -min(E), -e0, d0, a0))
    assert abs(e0 + eexp) < 0.002
    assert abs(d0 - dexp) < 0.01
    assert abs(a0 - aexp) < 4

print(fmt.format('reference', 9.999, eexp, dexp, aexp))

# plt.show()
def test_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)
    d2 = co2.get_distance(-2, -1)

    calc = EMT()
    slab.set_calculator(calc)
    if wrap:
        # Remap into the cell so bond is actually wrapped:
        slab.set_scaled_positions(slab.get_scaled_positions() % 1.0)
    constraint = FixLinearTriatomic(triples=[(-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
    assert abs(slab.get_distance(-2, -1, mic=1) - d2) < 1e-9
Пример #7
0
def test_external_force():
    """Tests for class ExternalForce in ase/constraints.py"""
    f_ext = 0.2

    atom1 = 0
    atom2 = 1
    atom3 = 2

    atoms = Atoms('H3', positions=[(0, 0, 0), (0.751, 0, 0), (0, 1., 0)])
    atoms.calc = EMT()

    # Without external force
    optimize(atoms)
    dist1 = atoms.get_distance(atom1, atom2)

    # With external force
    con1 = ExternalForce(atom1, atom2, f_ext)
    atoms.set_constraint(con1)
    optimize(atoms)
    dist2 = atoms.get_distance(atom1, atom2)
    # Distance should increase due to the external force
    assert dist2 > dist1

    # Combine ExternalForce with FixBondLength

    # Fix the bond on which the force acts
    con2 = FixBondLength(atom1, atom2)
    # ExternalForce constraint at the beginning of the list!!!
    atoms.set_constraint([con1, con2])
    optimize(atoms)
    f_con = con2.constraint_forces

    # It was already optimized with this external force, therefore
    # the constraint force should be almost zero
    assert norm(f_con[0]) <= fmax

    # To get the complete constraint force (with external force),
    # use only the FixBondLength constraint, after the optimization with
    # ExternalForce
    atoms.set_constraint(con2)
    optimize(atoms)
    f_con = con2.constraint_forces[0]
    assert round(norm(f_con), 2) == round(abs(f_ext), 2)

    # Fix another bond and incrase the external force
    f_ext *= 2
    con1 = ExternalForce(atom1, atom2, f_ext)
    d1 = atoms.get_distance(atom1, atom3)
    con2 = FixBondLength(atom1, atom3)
    # ExternalForce constraint at the beginning of the list!!!
    atoms.set_constraint([con1, con2])
    optimize(atoms)
    d2 = atoms.get_distance(atom1, atom3)
    # Fixed distance should not change
    assert round(d1, 5) == round(d2, 5)
Пример #8
0
def test_CO2linear_Au111_langevin(testdir):
    """Test Langevin with constraints for rigid linear
    triatomic molecules"""

    rng = np.random.RandomState(0)
    eref = 3.133526

    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)
    d2 = co2.get_distance(-2, -1)

    calc = EMT()
    slab.calc = calc
    constraint = FixLinearTriatomic(triples=[(-2, -3, -1)])
    slab.set_constraint(constraint)

    fr = 0.1
    dyn = Langevin(slab,
                   2.0 * units.fs,
                   temperature_K=300,
                   friction=fr,
                   trajectory='langevin_%.1f.traj' % fr,
                   logfile='langevin_%.1f.log' % fr,
                   loginterval=20,
                   rng=rng)
    dyn.run(100)

    # Check that the temperature is within a reasonable range
    T = slab.get_temperature()
    assert T > 100
    assert T < 500

    # Check that the constraints work
    assert abs(slab.get_distance(-3, -2, mic=1) - d0) < 1e-9
    assert abs(slab.get_distance(-3, -1, mic=1) - d1) < 1e-9
    assert abs(slab.get_distance(-2, -1, mic=1) - d2) < 1e-9

    # If the energy differs from the reference energy
    # it is most probable that the redistribution of
    # random forces in Langevin is not working properly
    assert abs(slab.get_potential_energy() - eref) < 1e-4
Пример #9
0
def test_atom():
    m = Atoms('H2')
    a = m[0]
    b = Atom('H')
    for c in [a, b]:
        assert c.x == 0
        c.z = 24.0
        assert c.position[2] == 24.0
        assert c.symbol == 'H'
        c.number = 92
        assert c.symbol == 'U'
        c.symbol = 'Fe'
        assert c.number == 26
        c.tag = 42
        assert c.tag == 42
        c.momentum = (1, 2, 3)
    assert m[0].tag == 42
    momenta = m.get_momenta()
    assert abs(momenta).sum() > 0
    m = Atoms('LiH')
    for a in m:
        print(a.symbol)
    for a in m:
        if a.symbol == 'H':
            a.z = 0.75
    assert m.get_distance(0, 1) == 0.75
    a = m.pop()
    m += a
    del m[:1]
    print(m)
Пример #10
0
def test_qmmm_acn():
    import numpy as np

    import ase.units as units
    from ase import Atoms
    from ase.calculators.acn import (ACN, m_me, r_cn, r_mec,
                                     sigma_me, sigma_c, sigma_n,
                                     epsilon_me, epsilon_c, epsilon_n)
    from ase.calculators.qmmm import SimpleQMMM, LJInteractionsGeneral, EIQMMM
    from ase.constraints import FixLinearTriatomic
    from ase.optimize import BFGS

    # From https://www.sciencedirect.com/science/article/pii/S0166128099002079
    eref = 4.9 * units.kcal / units.mol
    dref = 3.368
    aref = 79.1

    sigma = np.array([sigma_me, sigma_c, sigma_n])
    epsilon = np.array([epsilon_me, epsilon_c, epsilon_n])
    inter = LJInteractionsGeneral(sigma, epsilon, sigma, epsilon, 3)

    for calc in [ACN(),
                 SimpleQMMM([0, 1, 2], ACN(), ACN(), ACN()),
                 SimpleQMMM([0, 1, 2], ACN(), ACN(), ACN(), vacuum=3.0),
                 EIQMMM([0, 1, 2], ACN(), ACN(), inter),
                 EIQMMM([0, 1, 2], ACN(), ACN(), inter, vacuum=3.0),
                 EIQMMM([3, 4, 5], ACN(), ACN(), inter, vacuum=3.0)]:
        dimer = Atoms('CCNCCN',
                      [(-r_mec, 0, 0),
                       (0, 0, 0),
                       (r_cn, 0, 0),
                       (r_mec, 3.7, 0),
                       (0, 3.7, 0),
                       (-r_cn, 3.7, 0)])

        masses = dimer.get_masses()
        masses[::3] = m_me
        dimer.set_masses(masses)

        dimer.calc = calc

        fixd = FixLinearTriatomic(triples=[(0, 1, 2), (3, 4, 5)])

        dimer.set_constraint(fixd)

        opt = BFGS(dimer, maxstep=0.04,
                   trajectory=calc.name + '.traj', logfile=calc.name + 'd.log')
        opt.run(0.001, steps=1000)

        e0 = dimer.get_potential_energy()
        d0 = dimer.get_distance(1, 4)
        a0 = dimer.get_angle(2, 1, 4)
        fmt = '{0:>25}: {1:.3f} {2:.3f} {3:.1f}'
        print(fmt.format(calc.name, -e0, d0, a0))
        assert abs(e0 + eref) < 0.013
        assert abs(d0 - dref) < 0.224
        assert abs(a0 - aref) < 2.9

    print(fmt.format('reference', eref, dref, aref))
Пример #11
0
def test_n2():
    from ase import Atoms
    from ase.calculators.emt import EMT
    from ase.optimize import QuasiNewton

    n2 = Atoms('N2', positions=[(0, 0, 0), (0, 0, 1.1)], calculator=EMT())
    QuasiNewton(n2).run(0.01)
    print(n2.get_distance(0, 1), n2.get_potential_energy())
Пример #12
0
        def iterate(atoms : Atoms):
            delta = 0.01
            global bond1
            global bond2
            force = atoms.get_forces()[i['DIFFATOM']]
            bond1_dist   = atoms.get_distance(i['DIFFATOM'], i['CONSATOM1'], vector=False)
            bond1_vector = atoms.get_distance(i['DIFFATOM'], i['CONSATOM1'], vector=True )
            bond1_unit = bond1_vector / bond1_dist
            bond2_dist   = atoms.get_distance(i['DIFFATOM'], i['CONSATOM2'], vector=False)
            bond2_vector = atoms.get_distance(i['DIFFATOM'], i['CONSATOM2'], vector=True )
            bond2_unit = bond2_vector / bond2_dist

            bond1_projection = np.dot(force, bond1_unit)
            bond2_projection = np.dot(force, bond2_unit)
            if abs(bond1_projection) > bond2_projection:
                if bond1_projection > 0:
                    print('Growing Bond 1')
                    bond1 += delta
                    bond2 -= delta / 4
                else:
                    print('Shrinking Bond 1')
                    bond1 -= delta
                    bond2 += delta / 4
            else:
                if bond2_projection > 0:
                    print('Growing Bond 2')
                    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)
Пример #13
0
def get_fingerprint(Optimizer, indiv, binsize, cutoffdist):
    """Function to calculate the fingerprint of a structure
    """
    rs = numpy.linspace(0.0, cutoffdist, cutoffdist / binsize)
    indi = indiv[0]
    Vuc = indi.get_volume()
    if Optimizer.structure == 'Defect':
        solid = Atoms()
        solid.extend(indi)
        solid.extend(indiv.bulki)
    elif Optimizer.structure == 'Crystal':
        solid = indi.repeat([3, 3, 3])
    else:
        solid = indi.copy()
    syms = sorted(list(set([atm.symbol for atm in solid])))
    fingerprints = []
    for i in range(len(syms)):
        for j in range(i, len(syms)):
            indl = [atm for atm in indi if atm.symbol == syms[i]]
            ind = Atoms()
            for one in indl:
                ind.append(one)
            soll = [atm for atm in solid if atm.symbol == syms[j]]
            sol = Atoms()
            for one in soll:
                sol.append(one)
            soli = [atm for atm in solid if atm.symbol == syms[i]]
            value = []
            for R in rs:
                value2 = []
                for k in range(len(ind)):
                    value1 = []
                    for m in range(len(sol)):
                        if k != m:
                            rij = sol.get_distance(k, m, mic=True)
                            if rij == 0:
                                pass
                                #pdb.set_trace()
                            value1.append(
                                dirac(R, a=rij, sig=0.02) * 1 /
                                (4 * math.pi * rij**2 * binsize * len(soli) *
                                 len(sol) / Vuc))
                    value2.append(sum(value1))
                value.append(sum(value2))
            fingerprints.append(value)
    fpt = []
    for one in fingerprints:
        fpt.extend(one)
    return fpt
Пример #14
0
def check_min_dist(totalsol, type='Defect', nat=None, min_len=0.7, STR=''):
    if type == 'Defect' or type == 'Crystal' or type == 'Surface':
        if nat == None:
            nat = len(totalsol)
        cutoffs = [2.0 for one in totalsol]
        nl = NeighborList(cutoffs, bothways=True, self_interaction=False)
        nl.update(totalsol)
        for one in totalsol[0:nat]:
            nbatoms = Atoms()
            nbatoms.append(one)
            indices, offsets = nl.get_neighbors(one.index)
            for index, d in zip(indices, offsets):
                index = int(index)
                sym = totalsol[index].symbol
                pos = totalsol[index].position + numpy.dot(
                    d, totalsol.get_cell())
                at = Atom(symbol=sym, position=pos)
                nbatoms.append(at)
            while True:
                dflag = False
                for i in range(1, len(nbatoms)):
                    d = nbatoms.get_distance(0, i)
                    if d < min_len:
                        nbatoms.set_distance(0, i, min_len + .01, fix=0.5)
                        STR += '--- WARNING: Atoms too close (<0.7A) - Implement Move ---\n'
                        dflag = True
                if dflag == False:
                    break
            for i in range(len(indices)):
                totalsol[indices[i]].position = nbatoms[i + 1].position
            totalsol[one.index].position = nbatoms[0].position
            nl.update(totalsol)
    elif type == 'Cluster':
        for i in range(len(totalsol)):
            for j in range(len(totalsol)):
                if i != j:
                    d = totalsol.get_distance(i, j)
                    if d < min_len:
                        totalsol.set_distance(i, j, min_len, fix=0.5)
                        STR += '--- WARNING: Atoms too close (<0.7A) - Implement Move ---\n'
    else:
        print 'WARNING: In Check_Min_Dist in EvalEnergy: Structure Type not recognized'
    return totalsol, STR
Пример #15
0
def get_distances(indices, positions, rvecs=None):
    """Compute distances between particles"""
    atoms = Atoms(positions=positions, )
    if rvecs is not None:
        cell = ase.geometry.Cell(rvecs)
        atoms.set_cell(cell)
        atoms.set_pbc(True)
        mic = True
    else:
        cell = None
        mic = False

    ndist = indices.shape[0]
    distances = np.zeros(ndist)
    for i in range(ndist):
        distances[i] = atoms.get_distance(indices[i, 0],
                                          indices[i, 1],
                                          mic=mic)
    return distances
Пример #16
0
def main():
    arg = sys.argv
    inputfile = arg[1]
    outputfile = arg[2]
    atom1 = int(arg[3])
    atom2 = int(arg[4])
    f = open(inputfile)
    output = open(outputfile, 'w')
    atoms = None
    atom_output = Trajectory('trajectory.traj', 'w', atoms)
    iteration = 0
    trajectories = []
    a = 10.0
    b = 10.0
    c = 10.0
    cell_atoms = np.array([[a, 0, 0], [0, b, 0], [0, 0, c]])
    while True:
        coordinates = []
        type_atoms = []
        line = f.readline()
        if not line:
            break
        atom_numb = int(line.split()[0])
        line = f.readline()
        for i in range(0, atom_numb):
            line = f.readline()
            fields = line.split()
            type_atoms.append(fields[0])
            coordinates.append(
                [float(fields[1]),
                 float(fields[2]),
                 float(fields[3])])
        traj = Atoms(np.array(type_atoms),
                     positions=np.array(coordinates),
                     cell=cell_atoms,
                     pbc=True)
        traj.wrap()
        atom_output.write(traj)
        output.write("%6d %8.4f\n" %
                     (iteration, traj.get_distance(atom1, atom2, mic=True)))
        iteration += 1
Пример #17
0
class AutoTST_Molecule():
    """
    A class that allows for one to create RMG, RDKit and ASE
    molecules from a single string with identical atom indicies

    Inputs:
    * smiles (str): a SMILES string that describes the molecule of interest
    * rmg_molecule (RMG Molecule object): an rmg molecule that we can extract information from
    """
    def __init__(self, smiles=None, rmg_molecule=None):

        assert (
            smiles or rmg_molecule
        ), "Please provide a SMILES string and / or an RMG Molecule object."

        if smiles and rmg_molecule:
            assert rmg_molecule.isIsomorphic(
                Molecule(SMILES=smiles
                         )), "SMILES string did not match RMG Molecule object"
            self.smiles = smiles
            self.rmg_molecule = rmg_molecule

        elif rmg_molecule:
            self.rmg_molecule = rmg_molecule
            self.smiles = rmg_molecule.toSMILES()

        else:
            self.smiles = smiles
            self.rmg_molecule = Molecule(SMILES=smiles)

        self.get_rdkit_molecule()
        self.set_rmg_coords("RDKit")
        self.get_ase_molecule()
        self.get_torsions()
        self.get_angles()
        self.get_bonds()

    def __repr__(self):
        return '<AutoTST Molecule "{0}">'.format(self.smiles)

    def get_rdkit_molecule(self):
        """
        A method to create an RDKit Molecule from the rmg_molecule.
        Indicies will be the same as in the RMG Molecule
        """

        RDMol = self.rmg_molecule.toRDKitMol(removeHs=False)

        rdkit.Chem.AllChem.EmbedMolecule(RDMol)

        self.rdkit_molecule = RDMol

    def get_ase_molecule(self):
        """
        A method to create an ASE Molecule from the rdkit_molecule.
        Indicies will be the same as in the RMG and RDKit Molecule.
        """
        mol_list = AllChem.MolToMolBlock(self.rdkit_molecule).split('\n')
        ase_atoms = []
        for i, line in enumerate(mol_list):

            if i > 3:
                try:
                    atom0, atom1, bond, rest = line
                    atom0 = int(atom0)
                    atom0 = int(atom1)
                    bond = float(bond)

                except ValueError:
                    try:
                        x, y, z, symbol = line.split()[0:4]
                        x = float(x)
                        y = float(y)
                        z = float(z)

                        ase_atoms.append(
                            Atom(symbol=symbol, position=(x, y, z)))
                    except:
                        continue

        self.ase_molecule = Atoms(ase_atoms)
        return self.ase_molecule

    def view_mol(self):
        """
        A method designed to create a 3D figure of the AutoTST_Molecule with py3Dmol from the rdkit_molecule
        """
        mb = Chem.MolToMolBlock(self.rdkit_molecule)
        p = py3Dmol.view(width=400, height=400)
        p.addModel(mb, "sdf")
        p.setStyle({'stick': {}})
        p.setBackgroundColor('0xeeeeee')
        p.zoomTo()
        return p.show()

#############################################################################

    def get_bonds(self):

        rdmol_copy = self.rdkit_molecule
        bond_list = []
        for bond in rdmol_copy.GetBonds():
            bond_list.append((bond.GetBeginAtomIdx(), bond.GetEndAtomIdx()))

        bonds = []
        for indices in bond_list:
            i, j = indices

            length = self.ase_molecule.get_distance(i, j)

            reaction_center = "No"

            bond = Bond(indices=indices,
                        length=length,
                        reaction_center=reaction_center)

            bonds.append(bond)
        self.bonds = bonds
        return self.bonds

    def get_angles(self):

        rdmol_copy = self.rdkit_molecule

        angle_list = []
        for atom1 in rdmol_copy.GetAtoms():
            for atom2 in atom1.GetNeighbors():
                for atom3 in atom2.GetNeighbors():
                    if atom1.GetIdx() == atom3.GetIdx():
                        continue

                    to_add = (atom1.GetIdx(), atom2.GetIdx(), atom3.GetIdx())
                    if (to_add in angle_list) or (tuple(reversed(to_add))
                                                  in angle_list):
                        continue
                    angle_list.append(to_add)

        angles = []
        for indices in angle_list:
            i, j, k = indices

            degree = self.ase_molecule.get_angle(i, j, k)
            ang = Angle(indices=indices,
                        degree=degree,
                        left_mask=[],
                        right_mask=[])
            left_mask = self.get_left_mask(ang)
            right_mask = self.get_right_mask(ang)

            reaction_center = "No"

            angles.append(
                Angle(indices, degree, left_mask, right_mask, reaction_center))
        self.angles = angles
        return self.angles

    def get_torsions(self):
        rdmol_copy = self.rdkit_molecule

        torsion_list = []
        cistrans_list = []
        for bond1 in rdmol_copy.GetBonds():
            atom1 = bond1.GetBeginAtom()
            atom2 = bond1.GetEndAtom()
            if atom1.IsInRing() or atom2.IsInRing():
                # Making sure that bond1 we're looking at are not in a ring
                continue

            bond_list1 = list(atom1.GetBonds())
            bond_list2 = list(atom2.GetBonds())

            if not len(bond_list1) > 1 and not len(bond_list2) > 1:
                # Making sure that there are more than one bond attached to
                # the atoms we're looking at
                continue

            # Getting the 0th and 3rd atom and insuring that atoms
            # attached to the 1st and 2nd atom are not terminal hydrogens
            # We also make sure that all of the atoms are properly bound together

            # If the above are satisfied, we append a tuple of the torsion our torsion_list
            got_atom0 = False
            got_atom3 = False

            for bond0 in bond_list1:
                atomX = bond0.GetOtherAtom(atom1)
                # if atomX.GetAtomicNum() == 1 and len(atomX.GetBonds()) == 1:
                # This means that we have a terminal hydrogen, skip this
                # NOTE: for H_abstraction TSs, a non teminal H should exist
                #    continue
                if atomX.GetIdx() != atom2.GetIdx():
                    got_atom0 = True
                    atom0 = atomX

            for bond2 in bond_list2:
                atomY = bond2.GetOtherAtom(atom2)
                # if atomY.GetAtomicNum() == 1 and len(atomY.GetBonds()) == 1:
                # This means that we have a terminal hydrogen, skip this
                #    continue
                if atomY.GetIdx() != atom1.GetIdx():
                    got_atom3 = True
                    atom3 = atomY

            if not (got_atom0 and got_atom3):
                # Making sure atom0 and atom3 were not found
                continue

            # Looking to make sure that all of the atoms are properly bonded to eached
            if ("SINGLE" in str(
                    rdmol_copy.GetBondBetweenAtoms(
                        atom1.GetIdx(), atom2.GetIdx()).GetBondType())
                    and rdmol_copy.GetBondBetweenAtoms(atom0.GetIdx(),
                                                       atom1.GetIdx())
                    and rdmol_copy.GetBondBetweenAtoms(atom1.GetIdx(),
                                                       atom2.GetIdx())
                    and rdmol_copy.GetBondBetweenAtoms(atom2.GetIdx(),
                                                       atom3.GetIdx())):

                torsion_tup = (atom0.GetIdx(), atom1.GetIdx(), atom2.GetIdx(),
                               atom3.GetIdx())

                already_in_list = False
                for torsion_entry in torsion_list:
                    a, b, c, d = torsion_entry
                    e, f, g, h = torsion_tup

                    if (b, c) == (f, g) or (b, c) == (g, f):
                        already_in_list = True

                if not already_in_list:
                    torsion_list.append(torsion_tup)

            if ("DOUBLE" in str(
                    rdmol_copy.GetBondBetweenAtoms(
                        atom1.GetIdx(), atom2.GetIdx()).GetBondType())
                    and rdmol_copy.GetBondBetweenAtoms(atom0.GetIdx(),
                                                       atom1.GetIdx())
                    and rdmol_copy.GetBondBetweenAtoms(atom1.GetIdx(),
                                                       atom2.GetIdx())
                    and rdmol_copy.GetBondBetweenAtoms(atom2.GetIdx(),
                                                       atom3.GetIdx())):

                torsion_tup = (atom0.GetIdx(), atom1.GetIdx(), atom2.GetIdx(),
                               atom3.GetIdx())

                already_in_list = False
                for torsion_entry in torsion_list:
                    a, b, c, d = torsion_entry
                    e, f, g, h = torsion_tup

                    if (b, c) == (f, g) or (b, c) == (g, f):
                        already_in_list = True

                if not already_in_list:
                    cistrans_list.append(torsion_tup)

        torsions = []
        cistrans = []
        for indices in torsion_list:
            i, j, k, l = indices

            dihedral = self.ase_molecule.get_dihedral(i, j, k, l)
            tor = Torsion(indices=indices,
                          dihedral=dihedral,
                          left_mask=[],
                          right_mask=[])
            left_mask = self.get_left_mask(tor)
            right_mask = self.get_right_mask(tor)
            reaction_center = "No"

            torsions.append(
                Torsion(indices, dihedral, left_mask, right_mask,
                        reaction_center))

        for indices in cistrans_list:
            i, j, k, l = indices

            dihedral = self.ase_molecule.get_dihedral(i, j, k, l)
            tor = CisTrans(indices=indices,
                           dihedral=dihedral,
                           left_mask=[],
                           right_mask=[])
            left_mask = self.get_left_mask(tor)
            right_mask = self.get_right_mask(tor)
            reaction_center = "No"

            cistrans.append(
                CisTrans(indices, dihedral, left_mask, right_mask,
                         reaction_center))
        self.torsions = torsions
        self.cistrans = cistrans
        return self.torsions

    def get_right_mask(self, torsion_or_angle):

        rdmol_copy = self.rdkit_molecule

        rdkit_atoms = rdmol_copy.GetAtoms()

        if (isinstance(torsion_or_angle, autotst.geometry.Torsion)
                or isinstance(torsion_or_angle, autotst.geometry.CisTrans)):

            L1, L0, R0, R1 = torsion_or_angle.indices

            # trying to get the left hand side of this torsion
            LHS_atoms_index = [L0, L1]
            RHS_atoms_index = [R0, R1]

        elif isinstance(torsion_or_angle, autotst.geometry.Angle):
            a1, a2, a3 = torsion_or_angle.indices
            LHS_atoms_index = [a2, a1]
            RHS_atoms_index = [a2, a3]

        complete_RHS = False
        i = 0
        atom_index = RHS_atoms_index[0]
        while complete_RHS is False:
            try:
                RHS_atom = rdkit_atoms[atom_index]
                for neighbor in RHS_atom.GetNeighbors():
                    if (neighbor.GetIdx()
                            in RHS_atoms_index) or (neighbor.GetIdx()
                                                    in LHS_atoms_index):
                        continue
                    else:
                        RHS_atoms_index.append(neighbor.GetIdx())
                i += 1
                atom_index = RHS_atoms_index[i]

            except IndexError:
                complete_RHS = True

        right_mask = [
            index in RHS_atoms_index for index in range(len(self.ase_molecule))
        ]

        return right_mask

    def get_left_mask(self, torsion_or_angle):

        rdmol_copy = self.rdkit_molecule

        rdkit_atoms = rdmol_copy.GetAtoms()

        if (isinstance(torsion_or_angle, autotst.geometry.Torsion)
                or isinstance(torsion_or_angle, autotst.geometry.CisTrans)):

            L1, L0, R0, R1 = torsion_or_angle.indices

            # trying to get the left hand side of this torsion
            LHS_atoms_index = [L0, L1]
            RHS_atoms_index = [R0, R1]

        elif isinstance(torsion_or_angle, autotst.geometry.Angle):
            a1, a2, a3 = torsion_or_angle.indices
            LHS_atoms_index = [a2, a1]
            RHS_atoms_index = [a2, a3]

        complete_LHS = False
        i = 0
        atom_index = LHS_atoms_index[0]
        while complete_LHS is False:
            try:
                LHS_atom = rdkit_atoms[atom_index]
                for neighbor in LHS_atom.GetNeighbors():
                    if (neighbor.GetIdx()
                            in LHS_atoms_index) or (neighbor.GetIdx()
                                                    in RHS_atoms_index):
                        continue
                    else:
                        LHS_atoms_index.append(neighbor.GetIdx())
                i += 1
                atom_index = LHS_atoms_index[i]

            except IndexError:
                complete_LHS = True

        left_mask = [
            index in LHS_atoms_index for index in range(len(self.ase_molecule))
        ]

        return left_mask

    def set_rmg_coords(self, molecule_base):

        if molecule_base == "RDKit":
            mol_list = AllChem.MolToMolBlock(self.rdkit_molecule).split('\n')
            for i, atom in enumerate(self.rmg_molecule.atoms):
                j = i + 4
                coords = mol_list[j].split()[:3]
                for k, coord in enumerate(coords):
                    coords[k] = float(coord)
                atom.coords = np.array(coords)

        elif molecule_base == "ASE":
            for i, position in enumerate(self.ase_molecule.get_positions()):
                self.rmg_molecule.atoms[i].coords = position

    def update_from_rdkit_mol(self):

        # In order to update the ase molecule you simply need to rerun the get_ase_molecule method
        self.get_ase_molecule()
        self.set_rmg_coords("RDKit")
        # Getting the new torsion angles
        self.get_torsions()

    def update_from_ase_mol(self):

        self.set_rmg_coords("ASE")
        # setting the geometries of the rdkit molecule
        positions = self.ase_molecule.get_positions()
        conf = self.rdkit_molecule.GetConformers()[0]
        for i, atom in enumerate(self.rdkit_molecule.GetAtoms()):
            conf.SetAtomPosition(i, positions[i])

        # Getting the new torsion angles
        self.get_torsions()

    def update_from_rmg_mol(self):

        conf = self.rdkit_molecule.GetConformers()[0]
        ase_atoms = []
        for i, atom in enumerate(self.rmg_molecule.atoms):
            x, y, z = atom.coords
            symbol = atom.symbol

            conf.SetAtomPosition(i, [x, y, z])

            ase_atoms.append(Atom(symbol=symbol, position=(x, y, z)))

        self.ase_molecule = Atoms(ase_atoms)

        # Getting the new torsion angles
        self.get_torsions()
Пример #18
0
class Conformer():
    """
    A class for generating and editing 3D conformers of molecules
    """

    def __init__(self, smiles=None, rmg_molecule=None, index=0):

        self.energy = None
        self.index = index

        if (smiles or rmg_molecule):
            if smiles and rmg_molecule:
                assert rmg_molecule.isIsomorphic(RMGMolecule(
                    SMILES=smiles)), "SMILES string did not match RMG Molecule object"
                self.smiles = smiles
                self.rmg_molecule = rmg_molecule

            elif rmg_molecule:
                self.rmg_molecule = rmg_molecule
                self.smiles = rmg_molecule.toSMILES()

            else:
                self.smiles = smiles
                self.rmg_molecule = RMGMolecule(SMILES=smiles)

            self.rmg_molecule.updateMultiplicity()
            self.get_molecules()
            self.get_geometries()
            self._symmetry_number = None

        else:
            self.smiles = None
            self.rmg_molecule = None
            self.rdkit_molecule = None
            self.ase_molecule = None
            self.bonds = []
            self.angles = []
            self.torsions = []
            self.cistrans = []
            self.chiral_centers = []
            self._symmetry_number = None

    def __repr__(self):
        return '<Conformer "{}">'.format(self.smiles)

    def copy(self):
        copy_conf = Conformer()
        copy_conf.smiles = self.smiles
        copy_conf.rmg_molecule = self.rmg_molecule.copy()
        copy_conf.rdkit_molecule = self.rdkit_molecule.__copy__()
        copy_conf.ase_molecule = self.ase_molecule.copy()
        copy_conf.get_geometries()
        copy_conf.energy = self.energy
        return copy_conf

    @property
    def symmetry_number(self):
        if not self._symmetry_number:
            self._symmetry_number = self.calculate_symmetry_number()
        return self._symmetry_number

    def get_rdkit_mol(self):
        """
        A method for creating an rdkit geometry from an rmg mol
        """

        assert self.rmg_molecule, "Cannot create an RDKit geometry without an RMG molecule object"

        RDMol = self.rmg_molecule.toRDKitMol(removeHs=False)
        rdkit.Chem.AllChem.EmbedMolecule(RDMol)
        self.rdkit_molecule = RDMol

        mol_list = AllChem.MolToMolBlock(self.rdkit_molecule).split('\n')
        for i, atom in enumerate(self.rmg_molecule.atoms):
            j = i + 4
            coords = mol_list[j].split()[:3]
            for k, coord in enumerate(coords):
                coords[k] = float(coord)
            atom.coords = np.array(coords)

        return self.rdkit_molecule

    def get_ase_mol(self):
        """
        A method for creating an ase atoms object from an rdkit mol
        """

        if not self.rdkit_molecule:
            self.get_rdkit_mol()

        mol_list = AllChem.MolToMolBlock(self.rdkit_molecule).split('\n')
        ase_atoms = []
        for i, line in enumerate(mol_list):
            if i > 3:
                try:
                    atom0, atom1, bond, rest = line
                    atom0 = int(atom0)
                    atom0 = int(atom1)
                    bond = float(bond)
                except ValueError:
                    try:
                        x, y, z, symbol = line.split()[0:4]
                        x = float(x)
                        y = float(y)
                        z = float(z)
                        ase_atoms.append(
                            Atom(symbol=symbol, position=(x, y, z)))
                    except BaseException:
                        continue

        self.ase_molecule = Atoms(ase_atoms)

        return self.ase_molecule

    def get_molecules(self):
        if not self.rmg_molecule:
            self.rmg_molecule = RMGMolecule(SMILES=self.smiles)
        self.rdkit_molecule = self.get_rdkit_mol()
        self.ase_molecule = self.get_ase_mol()
        self.get_geometries()

        return self.rdkit_molecule, self.ase_molecule

    def view(self):
        """
        A method designed to create a 3D figure of the AutoTST_Molecule with py3Dmol from the rdkit_molecule
        """
        mb = Chem.MolToMolBlock(self.rdkit_molecule)
        p = py3Dmol.view(width=600, height=600)
        p.addModel(mb, "sdf")
        p.setStyle({'stick': {}})
        p.setBackgroundColor('0xeeeeee')
        p.zoomTo()
        return p.show()

    def get_bonds(self):
        """
        A method for identifying all of the bonds in a conformer
        """
        bond_list = []
        for bond in self.rdkit_molecule.GetBonds():
            bond_list.append((bond.GetBeginAtomIdx(), bond.GetEndAtomIdx()))

        bonds = []
        for index, indices in enumerate(bond_list):
            i, j = indices

            length = self.ase_molecule.get_distance(i, j)
            center = False
            if ((self.rmg_molecule.atoms[i].label) and (
                    self.rmg_molecule.atoms[j].label)):
                center = True

            bond = Bond(index=index,
                        atom_indices=indices,
                        length=length,
                        reaction_center=center)
            mask = self.get_mask(bond)
            bond.mask = mask

            bonds.append(bond)

        self.bonds = bonds

        return self.bonds

    def get_angles(self):
        """
        A method for identifying all of the angles in a conformer
        """

        angle_list = []
        for atom1 in self.rdkit_molecule.GetAtoms():
            for atom2 in atom1.GetNeighbors():
                for atom3 in atom2.GetNeighbors():
                    if atom1.GetIdx() == atom3.GetIdx():
                        continue

                    to_add = (atom1.GetIdx(), atom2.GetIdx(), atom3.GetIdx())
                    if (to_add in angle_list) or (
                            tuple(reversed(to_add)) in angle_list):
                        continue
                    angle_list.append(to_add)

        angles = []
        for index, indices in enumerate(angle_list):
            i, j, k = indices

            degree = self.ase_molecule.get_angle(i, j, k)
            ang = Angle(index=index,
                        atom_indices=indices,
                        degree=degree,
                        mask=[])
            mask = self.get_mask(ang)
            reaction_center = False

            angles.append(Angle(index=index,
                                atom_indices=indices,
                                degree=degree,
                                mask=mask,
                                reaction_center=reaction_center))
        self.angles = angles
        return self.angles

    def get_torsions(self):
        """
        A method for identifying all of the torsions in a conformer
        """
        torsion_list = []
        for bond1 in self.rdkit_molecule.GetBonds():
            atom1 = bond1.GetBeginAtom()
            atom2 = bond1.GetEndAtom()
            if atom1.IsInRing() or atom2.IsInRing():
                # Making sure that bond1 we're looking at are not in a ring
                continue

            bond_list1 = list(atom1.GetBonds())
            bond_list2 = list(atom2.GetBonds())

            if not len(bond_list1) > 1 and not len(bond_list2) > 1:
                # Making sure that there are more than one bond attached to
                # the atoms we're looking at
                continue

            # Getting the 0th and 3rd atom and insuring that atoms
            # attached to the 1st and 2nd atom are not terminal hydrogens
            # We also make sure that all of the atoms are properly bound
            # together

            # If the above are satisfied, we append a tuple of the torsion our
            # torsion_list
            got_atom0 = False
            got_atom3 = False

            for bond0 in bond_list1:
                atomX = bond0.GetOtherAtom(atom1)
                # if atomX.GetAtomicNum() == 1 and len(atomX.GetBonds()) == 1:
                # This means that we have a terminal hydrogen, skip this
                # NOTE: for H_abstraction TSs, a non teminal H should exist
                #    continue
                if atomX.GetIdx() != atom2.GetIdx():
                    got_atom0 = True
                    atom0 = atomX

            for bond2 in bond_list2:
                atomY = bond2.GetOtherAtom(atom2)
                # if atomY.GetAtomicNum() == 1 and len(atomY.GetBonds()) == 1:
                # This means that we have a terminal hydrogen, skip this
                #    continue
                if atomY.GetIdx() != atom1.GetIdx():
                    got_atom3 = True
                    atom3 = atomY

            if not (got_atom0 and got_atom3):
                # Making sure atom0 and atom3 were not found
                continue

            # Looking to make sure that all of the atoms are properly bonded to
            # eached
            if (
                "SINGLE" in str(
                    self.rdkit_molecule.GetBondBetweenAtoms(
                        atom1.GetIdx(),
                        atom2.GetIdx()).GetBondType()) and self.rdkit_molecule.GetBondBetweenAtoms(
                    atom0.GetIdx(),
                    atom1.GetIdx()) and self.rdkit_molecule.GetBondBetweenAtoms(
                    atom1.GetIdx(),
                    atom2.GetIdx()) and self.rdkit_molecule.GetBondBetweenAtoms(
                        atom2.GetIdx(),
                    atom3.GetIdx())):

                torsion_tup = (atom0.GetIdx(), atom1.GetIdx(),
                               atom2.GetIdx(), atom3.GetIdx())

                already_in_list = False
                for torsion_entry in torsion_list:
                    a, b, c, d = torsion_entry
                    e, f, g, h = torsion_tup

                    if (b, c) == (f, g) or (b, c) == (g, f):
                        already_in_list = True

                if not already_in_list:
                    torsion_list.append(torsion_tup)

        torsions = []
        for index, indices in enumerate(torsion_list):
            i, j, k, l = indices

            dihedral = self.ase_molecule.get_dihedral(i, j, k, l)
            tor = Torsion(index=index,
                          atom_indices=indices,
                          dihedral=dihedral,
                          mask=[])
            mask = self.get_mask(tor)
            reaction_center = False

            torsions.append(Torsion(index=index,
                                    atom_indices=indices,
                                    dihedral=dihedral,
                                    mask=mask,
                                    reaction_center=reaction_center))

        self.torsions = torsions
        return self.torsions

    def get_cistrans(self):
        """
        A method for identifying all possible cistrans bonds in a molecule
        """
        torsion_list = []
        cistrans_list = []
        for bond1 in self.rdkit_molecule.GetBonds():
            atom1 = bond1.GetBeginAtom()
            atom2 = bond1.GetEndAtom()
            if atom1.IsInRing() or atom2.IsInRing():
                # Making sure that bond1 we're looking at are not in a ring
                continue

            bond_list1 = list(atom1.GetBonds())
            bond_list2 = list(atom2.GetBonds())

            if not len(bond_list1) > 1 and not len(bond_list2) > 1:
                # Making sure that there are more than one bond attached to
                # the atoms we're looking at
                continue

            # Getting the 0th and 3rd atom and insuring that atoms
            # attached to the 1st and 2nd atom are not terminal hydrogens
            # We also make sure that all of the atoms are properly bound
            # together

            # If the above are satisfied, we append a tuple of the torsion our
            # torsion_list
            got_atom0 = False
            got_atom3 = False

            for bond0 in bond_list1:
                atomX = bond0.GetOtherAtom(atom1)
                # if atomX.GetAtomicNum() == 1 and len(atomX.GetBonds()) == 1:
                # This means that we have a terminal hydrogen, skip this
                # NOTE: for H_abstraction TSs, a non teminal H should exist
                #    continue
                if atomX.GetIdx() != atom2.GetIdx():
                    got_atom0 = True
                    atom0 = atomX

            for bond2 in bond_list2:
                atomY = bond2.GetOtherAtom(atom2)
                # if atomY.GetAtomicNum() == 1 and len(atomY.GetBonds()) == 1:
                # This means that we have a terminal hydrogen, skip this
                #    continue
                if atomY.GetIdx() != atom1.GetIdx():
                    got_atom3 = True
                    atom3 = atomY

            if not (got_atom0 and got_atom3):
                # Making sure atom0 and atom3 were not found
                continue

            # Looking to make sure that all of the atoms are properly bonded to
            # eached
            if (
                "DOUBLE" in str(
                    self.rdkit_molecule.GetBondBetweenAtoms(
                        atom1.GetIdx(),
                        atom2.GetIdx()).GetBondType()) and self.rdkit_molecule.GetBondBetweenAtoms(
                    atom0.GetIdx(),
                    atom1.GetIdx()) and self.rdkit_molecule.GetBondBetweenAtoms(
                    atom1.GetIdx(),
                    atom2.GetIdx()) and self.rdkit_molecule.GetBondBetweenAtoms(
                        atom2.GetIdx(),
                    atom3.GetIdx())):

                torsion_tup = (atom0.GetIdx(), atom1.GetIdx(),
                               atom2.GetIdx(), atom3.GetIdx())

                already_in_list = False
                for torsion_entry in torsion_list:
                    a, b, c, d = torsion_entry
                    e, f, g, h = torsion_tup

                    if (b, c) == (f, g) or (b, c) == (g, f):
                        already_in_list = True

                if not already_in_list:
                    cistrans_list.append(torsion_tup)

        cistrans = []

        for ct_index, indices in enumerate(cistrans_list):
            i, j, k, l = indices

            b0 = self.rdkit_molecule.GetBondBetweenAtoms(i, j)
            b1 = self.rdkit_molecule.GetBondBetweenAtoms(j, k)
            b2 = self.rdkit_molecule.GetBondBetweenAtoms(k, l)

            b0.SetBondDir(Chem.BondDir.ENDUPRIGHT)
            b2.SetBondDir(Chem.BondDir.ENDDOWNRIGHT)

            Chem.AssignStereochemistry(self.rdkit_molecule, force=True)

            if "STEREOZ" in str(b1.GetStereo()):
                if round(self.ase_molecule.get_dihedral(i, j, k, l), -1) == 0:
                    atom = self.rdkit_molecule.GetAtomWithIdx(k)
                    bonds = atom.GetBonds()
                    for bond in bonds:
                        indexes = [
                            bond.GetBeginAtomIdx(),
                            bond.GetEndAtomIdx()]
                        if not ((sorted([j, k]) == sorted(indexes)) or (
                                sorted([k, l]) == sorted(indexes))):
                            break

                    for index in indexes:
                        if not (index in indices):
                            l = index
                            break

                indices = [i, j, k, l]
                stero = "Z"

            else:
                if round(
                    self.ase_molecule.get_dihedral(
                        i, j, k, l), -1) == 180:
                    atom = self.rdkit_molecule.GetAtomWithIdx(k)
                    bonds = atom.GetBonds()
                    for bond in bonds:
                        indexes = [
                            bond.GetBeginAtomIdx(),
                            bond.GetEndAtomIdx()]
                        if not ((sorted([j, k]) == sorted(indexes)) or (
                                sorted([k, l]) == sorted(indexes))):
                            break

                    for index in indexes:
                        if not (index in indices):
                            l = index
                            break

                indices = [i, j, k, l]
                stero = "E"

            dihedral = self.ase_molecule.get_dihedral(i, j, k, l)
            tor = CisTrans(index=ct_index,
                           atom_indices=indices,
                           dihedral=dihedral,
                           mask=[],
                           stero=stero)
            mask = self.get_mask(tor)
            reaction_center = False

            cistrans.append(CisTrans(index=ct_index,
                                     atom_indices=indices,
                                     dihedral=dihedral,
                                     mask=mask,
                                     stero=stero
                                     )
                            )

        self.cistrans = cistrans
        return self.cistrans

    def get_mask(self, geometry):
        """
        Getting the right hand mask for a geometry object:

        - self: an AutoTST Conformer object
        - geometry: a Bond, Angle, Dihedral, or Torsion object 


        """

        rdkit_atoms = self.rdkit_molecule.GetAtoms()
        if (isinstance(geometry, autotst.geometry.Torsion) or
                isinstance(geometry, autotst.geometry.CisTrans)):

            L1, L0, R0, R1 = geometry.atom_indices

            # trying to get the left hand side of this torsion
            LHS_atoms_index = [L0, L1]
            RHS_atoms_index = [R0, R1]

        elif isinstance(geometry, autotst.geometry.Angle):
            a1, a2, a3 = geometry.atom_indices
            LHS_atoms_index = [a2, a1]
            RHS_atoms_index = [a2, a3]

        elif isinstance(geometry, autotst.geometry.Bond):
            a1, a2 = geometry.atom_indices
            LHS_atoms_index = [a1]
            RHS_atoms_index = [a2]

        complete_RHS = False
        i = 0
        atom_index = RHS_atoms_index[0]
        while complete_RHS is False:
            try:
                RHS_atom = rdkit_atoms[atom_index]
                for neighbor in RHS_atom.GetNeighbors():
                    if (neighbor.GetIdx() in RHS_atoms_index) or (
                            neighbor.GetIdx() in LHS_atoms_index):
                        continue
                    else:
                        RHS_atoms_index.append(neighbor.GetIdx())
                i += 1
                atom_index = RHS_atoms_index[i]

            except IndexError:
                complete_RHS = True

        mask = [index in RHS_atoms_index for index in range(
            len(self.ase_molecule))]

        return mask

    def get_chiral_centers(self):
        """
        A method to identify
        """

        centers = rdkit.Chem.FindMolChiralCenters(
            self.rdkit_molecule, includeUnassigned=True)
        chiral_centers = []

        for index, center in enumerate(centers):
            atom_index, chirality = center

            chiral_centers.append(
                ChiralCenter(
                    index=index,
                    atom_index=atom_index,
                    chirality=chirality))

        self.chiral_centers = chiral_centers
        return self.chiral_centers

    def get_geometries(self):
        """
        A helper method to obtain all geometry things
        """

        self.bonds = self.get_bonds()
        self.angles = self.get_angles()
        self.torsions = self.get_torsions()
        self.cistrans = self.get_cistrans()
        self.chiral_centers = self.get_chiral_centers()

        return (
            self.bonds,
            self.angles,
            self.torsions,
            self.cistrans,
            self.chiral_centers)

    def update_coords(self):
        """
        A function that creates distance matricies for the RMG, ASE, and RDKit molecules and finds which
        (if any) are different. If one is different, this will update the coordinates of the other two
        with the different one. If all three are different, nothing will happen. If all are the same,
        nothing will happen.
        """
        rdkit_dm = rdkit.Chem.rdmolops.Get3DDistanceMatrix(self.rdkit_molecule)
        ase_dm = self.ase_molecule.get_all_distances()
        l = len(self.rmg_molecule.atoms)
        rmg_dm = np.zeros((l, l))

        for i, atom_i in enumerate(self.rmg_molecule.atoms):
            for j, atom_j in enumerate(self.rmg_molecule.atoms):
                rmg_dm[i][j] = np.linalg.norm(atom_i.coords - atom_j.coords)

        d1 = round(abs(rdkit_dm - ase_dm).max(), 3)
        d2 = round(abs(rdkit_dm - rmg_dm).max(), 3)
        d3 = round(abs(ase_dm - rmg_dm).max(), 3)

        if np.all(np.array([d1, d2, d3]) > 0):
            return False, None

        if np.any(np.array([d1, d2, d3]) > 0):
            if d1 == 0:
                diff = "rmg"
                self.update_coords_from("rmg")
            elif d2 == 0:
                diff = "ase"
                self.update_coords_from("ase")
            else:
                diff = "rdkit"
                self.update_coords_from("rdkit")

            return True, diff
        else:
            return True, None

    def update_coords_from(self, mol_type="ase"):
        """
        A method to update the coordinates of the RMG, RDKit, and ASE objects with a chosen object.
        """

        possible_mol_types = ["ase", "rmg", "rdkit"]

        assert (mol_type.lower() in possible_mol_types), "Please specifiy a valid mol type. Valid types are {}".format(
            possible_mol_types)

        if mol_type.lower() == "rmg":
            conf = self.rdkit_molecule.GetConformers()[0]
            ase_atoms = []
            for i, atom in enumerate(self.rmg_molecule.atoms):
                x, y, z = atom.coords
                symbol = atom.symbol

                conf.SetAtomPosition(i, [x, y, z])

                ase_atoms.append(Atom(symbol=symbol, position=(x, y, z)))

            self.ase_molecule = Atoms(ase_atoms)
            # self.calculate_symmetry_number()

        elif mol_type.lower() == "ase":
            conf = self.rdkit_molecule.GetConformers()[0]
            for i, position in enumerate(self.ase_molecule.get_positions()):
                self.rmg_molecule.atoms[i].coords = position
                conf.SetAtomPosition(i, position)

            # self.calculate_symmetry_number()

        elif mol_type.lower() == "rdkit":

            mol_list = AllChem.MolToMolBlock(self.rdkit_molecule).split('\n')
            for i, atom in enumerate(self.rmg_molecule.atoms):
                j = i + 4
                coords = mol_list[j].split()[:3]
                for k, coord in enumerate(coords):
                    coords[k] = float(coord)
                atom.coords = np.array(coords)

            self.get_ase_mol()
            # self.calculate_symmetry_number()

    def set_bond_length(self, bond_index, length):
        """
        This is a method to set bond lengths
        Variabels:
        - bond_index (int): the index of the bond you want to edit
        - length (float, int): the distance you want to set the bond (in angstroms)
        """

        assert isinstance(length, (float, int))

        matched = False
        for bond in self.bonds:
            if bond.index == bond_index:
                matched = True
                break

        if not matched:
            logging.info("Angle index provided is out of range. Nothing was changed.")
            return self

        i, j = bond.atom_indices
        self.ase_molecule.set_distance(
            a0=i,
            a1=j,
            distance=length,
            mask=bond.mask,
            fix=0
        )

        bond.length = length

        self.update_coords_from(mol_type="ase")
        return self

    def set_angle(self, angle_index, angle):
        """
        A method that will set the angle of an Angle object accordingly
        """

        assert isinstance(
            angle, (int, float)), "Plese provide a float or an int for the angle"

        matched = False
        for a in self.angles:
            if a.index == angle_index:
                matched = True
                break

        if not matched:
            logging.info("Angle index provided is out of range. Nothing was changed.")
            return self

        i, j, k = a.atom_indices
        self.ase_molecule.set_angle(
            a1=i,
            a2=j,
            a3=k,
            angle=angle,
            mask=a.mask
        )

        a.degree = angle

        self.update_coords_from(mol_type="ase")

        return self

    def set_torsion(self, torsion_index, dihedral):
        """
        A method that will set the diehdral angle of a Torsion object accordingly.
        """

        assert isinstance(
            dihedral, (int, float)), "Plese provide a float or an int for the diehdral angle"

        matched = False
        for torsion in self.torsions:
            if torsion.index == torsion_index:
                matched = True
                break

        if not matched:
            logging.info("Torsion index provided is out of range. Nothing was changed.")
            return self

        i, j, k, l = torsion.atom_indices
        self.ase_molecule.set_dihedral(
            a1=i,
            a2=j,
            a3=k,
            a4=l,
            angle=dihedral,
            mask=torsion.mask
        )
        torsion.dihedral = dihedral

        self.update_coords_from(mol_type="ase")

        return self

    def set_cistrans(self, cistrans_index, stero="E"):
        """
        A module that will set a corresponding cistrans bond to the proper E/Z config
        """

        assert stero.upper() in [
            "E", "Z"], "Please specify a valid stero direction."

        matched = False
        for cistrans in self.cistrans:
            if cistrans.index == cistrans_index:
                matched = True
                break

        if not matched:
            logging.info("CisTrans index provided is out of range. Nothing was changed.")
            return self

        if cistrans.stero == stero.upper():
            self.update_coords_from("ase")
            return self

        else:
            cistrans.stero = stero.upper()
            i, j, k, l = cistrans.atom_indices
            self.ase_molecule.rotate_dihedral(
                a1=i,
                a2=j,
                a3=k,
                a4=l,
                angle=float(180),
                mask=cistrans.mask
            )
            cistrans.stero = stero.upper()

            self.update_coords_from(mol_type="ase")
            return self

    def set_chirality(self, chiral_center_index, stero="R"):
        """
        A module that can set the orientation of a chiral center.
        """
        assert stero.upper() in ["R", "S"], "Specify a valid stero orientation"

        centers_dict = {
            'R': Chem.rdchem.ChiralType.CHI_TETRAHEDRAL_CW,
            'S': Chem.rdchem.ChiralType.CHI_TETRAHEDRAL_CCW
        }

        assert isinstance(chiral_center_index,
                          int), "Please provide an integer for the index"

        rdmol = self.rdkit_molecule.__copy__()

        match = False
        for chiral_center in self.chiral_centers:
            if chiral_center.index == chiral_center_index:
                match = True
                break

        if not match:
            logging.info("ChiralCenter index provided is out of range. Nothing was changed")
            return self

        rdmol.GetAtomWithIdx(chiral_center.atom_index).SetChiralTag(
            centers_dict[stero.upper()])

        rdkit.Chem.rdDistGeom.EmbedMolecule(rdmol)

        old_torsions = self.torsions[:] + self.cistrans[:]

        self.rdkit_molecule = rdmol
        self.update_coords_from(mol_type="rdkit")

        # Now resetting dihedral angles in case if they changed.

        for torsion in old_torsions:
            i, j, k, l = torsion.atom_indices

            self.ase_molecule.set_dihedral(
                a1=i,
                a2=j,
                a3=k,
                a4=l,
                mask=torsion.mask,
                angle=torsion.dihedral,
            )

        self.update_coords_from(mol_type="ase")

        return self

    def calculate_symmetry_number(self):
        from rmgpy.qm.symmetry import PointGroupCalculator
        from rmgpy.qm.qmdata import QMData

        atom_numbers = self.ase_molecule.get_atomic_numbers()
        coordinates = self.ase_molecule.get_positions()

        qmdata = QMData(
            groundStateDegeneracy=1,  # Only needed to check if valid QMData
            numberOfAtoms=len(atom_numbers),
            atomicNumbers=atom_numbers,
            atomCoords=(coordinates, str('angstrom')),
            energy=(0.0, str('kcal/mol'))  # Only needed to avoid error
        )
        settings = type(str(''), (), dict(symmetryPath=str(
            'symmetry'), scratchDirectory="."))()  # Creates anonymous class
        pgc = PointGroupCalculator(settings, self.smiles, qmdata)
        pg = pgc.calculate()
        #os.remove("{}.symm".format(self.smiles))

        if pg is not None:
            symmetry_number = pg.symmetryNumber
        else:
            symmetry_number = 1

        return symmetry_number
Пример #19
0
def lattice_alteration_nn(indiv, Optimizer):
    """Move function to perform random move along random axis for nearest neighbor distance to random atoms
    Inputs:
        indiv = Individual class object to be altered
        Optimizer = Optimizer class object with needed parameters
    Outputs:
        indiv = Altered Individual class object
    """
    if 'MU' in Optimizer.debug:
        debug = True
    else:
        debug = False
    if Optimizer.structure=='Defect':
        if Optimizer.isolate_mutation:
            indc,indb,vacant,swaps,stro = find_defects(indiv[0],Optimizer.solidbulk,0)
            ind = indc.copy()
            ind.extend(indb)
        else:
            ind=indiv[0].copy()
            indc=indiv[0].copy()
    else:
        ind=indiv[0].copy()
        indc=indiv[0].copy()
    if len(indc) != 0:
        ctoff1 = [1.0 for one in ind]
        nl = NeighborList(ctoff1, bothways=True, self_interaction=False)
        nl.update(ind)
        try:
            natomsmove=random.randint(1,len(indc)/2)
        except ValueError:
            natomsmove=1
        passn=0
        for count in range(natomsmove):
            try:
                indexmv = random.choice([i for i in range(len(indc))])
                indices, offsets = nl.get_neighbors(indexmv)
                nns = Atoms()
                nns.append(ind[indexmv])
                for index, d in zip(indices,offsets):
                    index = int(index)
                    pos = ind[index].position + numpy.dot(d,ind.get_cell())
                    nns.append(Atom(symbol=ind[index].symbol, position=pos))
                dist = [nns.get_distance(0,i) for i in range(1, len(nns))]
                r = sum(dist)/len(dist)
                dir = random.choice([[1,0,0],[-1,0,0],[0,1,0],[0,-1,0],[0,0,1],[0,0,-1]])
                ind[indexmv].position += [i*r for i in dir]
            except:
                passn+=1
        indiv[0]=ind.copy()
    else:
        natomsmove=0
        passn=0
    Optimizer.output.write('Lattice Alteration NN Mutation performed on individual\n')
    Optimizer.output.write('Index = '+repr(indiv.index)+'\n')
    natomsmove-=passn
    Optimizer.output.write('Number of atoms moved = '+repr(natomsmove)+'\n')
    Optimizer.output.write(repr(indiv[0])+'\n')
    muttype='LANN'+repr(natomsmove)
    if indiv.energy==0:
        indiv.history_index=indiv.history_index+'m'+muttype
    else:
        indiv.history_index=repr(indiv.index)+'m'+muttype
    return indiv
Пример #20
0
import numpy as np
from ase import Atoms
from ase.optimize import BFGS
from gpaw import GPAW
from gpaw.wavefunctions.pw import PW
from gpaw.test import equal
from gpaw.mpi import world

a = 2.65
slab = Atoms('Li2',
             [(0, 0, 0), (0, 0, a)],
             cell=(a, a, 3 * a),
             pbc=True)
k = 4
calc = GPAW(mode=PW(200),
            eigensolver='rmm-diis',
            parallel={'band': min(world.size, 4)},
            idiotproof=0,
            kpts=(k, k, 1))
slab.set_calculator(calc)
BFGS(slab).run(fmax=0.01)
assert abs(slab.get_distance(0, 1) - 2.4594) < 0.001, slab.get_distance(0, 1)
Пример #21
0
f_ext = 0.2

atom1 = 0
atom2 = 1

atom3 = 2

fmax = 0.001

atoms = Atoms('H3', positions=[(0, 0, 0), (0.751, 0, 0), (0, 1., 0)])
atoms.set_calculator(EMT())

# Without external force
opt = FIRE(atoms)
opt.run(fmax=fmax)
dist1 = atoms.get_distance(atom1, atom2)

# With external force
con1 = ExternalForce(atom1, atom2, f_ext)
atoms.set_constraint(con1)
opt = FIRE(atoms)
opt.run(fmax=fmax)
dist2 = atoms.get_distance(atom1, atom2)
# Distance should increase due to the external force
assert dist2 > dist1

# Combine ExternalForce with FixBondLength

# Fix the bond on which the force acts
con2 = FixBondLength(atom1, atom2)
# ExternalForce constraint at the beginning of the list!!!
Пример #22
0
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
Пример #23
0
from ase import Atoms
from ase.calculators.emt import EMT
from ase.optimize import QuasiNewton

n2 = Atoms('N2', positions=[(0, 0, 0), (0, 0, 1.1)],
           calculator=EMT())
QuasiNewton(n2).run(0.01)
print(n2.get_distance(0, 1), n2.get_potential_energy())
Пример #24
0
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
Пример #25
0
def test_turbomole_qmmm():
    """Test the Turbomole calculator in simple QMMM and
    explicit interaction QMMM simulations."""

    r = rOH
    a = angleHOH * pi / 180
    D = np.linspace(2.5, 3.5, 30)

    interaction = LJInteractions({('O', 'O'): (epsilon0, sigma0)})
    qm_par = {'esp fit': 'kollman', 'multiplicity': 1}

    for calc in [
            TIP3P(),
            SimpleQMMM([0, 1, 2], Turbomole(**qm_par), TIP3P(), TIP3P()),
            SimpleQMMM([0, 1, 2],
                       Turbomole(**qm_par),
                       TIP3P(),
                       TIP3P(),
                       vacuum=3.0),
            EIQMMM([0, 1, 2], Turbomole(**qm_par), TIP3P(), interaction),
            EIQMMM([3, 4, 5],
                   Turbomole(**qm_par),
                   TIP3P(),
                   interaction,
                   vacuum=3.0),
            EIQMMM([0, 1, 2],
                   Turbomole(**qm_par),
                   TIP3P(),
                   interaction,
                   vacuum=3.0)
    ]:
        dimer = Atoms('H2OH2O',
                      [(r * cos(a), 0, r * sin(a)), (r, 0, 0), (0, 0, 0),
                       (r * cos(a / 2), r * sin(a / 2), 0),
                       (r * cos(a / 2), -r * sin(a / 2), 0), (0, 0, 0)])
        dimer.calc = calc

        E = []
        F = []
        for d in D:
            dimer.positions[3:, 0] += d - dimer.positions[5, 0]
            E.append(dimer.get_potential_energy())
            F.append(dimer.get_forces())

        F = np.array(F)

        F1 = np.polyval(np.polyder(np.polyfit(D, E, 7)), D)
        F2 = F[:, :3, 0].sum(1)
        error = abs(F1 - F2).max()
        assert error < 0.9

        dimer.set_constraint(
            FixInternals(bonds=[(r, (0, 2)), (r, (1, 2)), (r, (3, 5)),
                                (r, (4, 5))],
                         angles_deg=[(angleHOH, (0, 2, 1)),
                                     (angleHOH, (3, 5, 4))]))
        opt = BFGS(dimer,
                   trajectory=calc.name + '.traj',
                   logfile=calc.name + 'd.log')
        opt.run(0.01)

        e0 = dimer.get_potential_energy()
        d0 = dimer.get_distance(2, 5)
        R = dimer.positions
        v1 = R[1] - R[5]
        v2 = R[5] - (R[3] + R[4]) / 2
        a0 = np.arccos(
            np.dot(v1, v2) /
            (np.dot(v1, v1) * np.dot(v2, v2))**0.5) / np.pi * 180
        fmt = '{0:>20}: {1:.3f} {2:.3f} {3:.3f} {4:.1f}'
        print(fmt.format(calc.name, -min(E), -e0, d0, a0))
 name = dire + 'Pt-bulk-fcc-%.0f-%.0f-%.4f' % (ecut, k, a)
 filename = name + '.txt'
 b = a / 2
 c = 'a-Pt-%.0f-%.0f-%.4f' % (ecut, k, a)
 bulk = Atoms('Pt',
              cell=[[0, b, b], [b, 0, b], [b, b, 0]],
              pbc=True)
 #bulk = L1_0(symbol=('Co','Pt'),latticeconstant=(a,c), pbc=True)
 if not os.path.exists(os.path.dirname(filename)):
     try:
         os.makedirs(os.path.dirname(filename))
     except OSError as exc:  # Guard against race condition
         if exc.errno != errno.EEXIST:
             raise
 bulk *= [2, 2, 2]
 distancebefore = bulk.get_distance(1, 2)
 bulk.pop(4)
 bulk.append(Atom('Co', [0.0, 1.96, 1.96]))
 bulk.pop(6)
 bulk.append(
     Atom('Co', [
         3.9199999999999999, 3.9199999999999999, 3.9199999999999999
     ]))
 #bulk.set_initial_magnetic_moments([1,1,1,1])
 calc = GPAW(
     mode=PW(ecut),  # cutoff
     kpts=(k, k, k),  # k-points
     xc='PBE',
     txt=filename)  # output file
 bulk.set_calculator(calc)
 relax = QuasiNewton(bulk, logfile=c + '.log')
Пример #27
0
    F1 = np.polyval(np.polyder(np.polyfit(D, E, 7)), D)
    F2 = F[:, :3, 0].sum(1)
    error = abs(F1 - F2).max()

    dimer.constraints = FixBondLengths([(3 * i + j, 3 * i + (j + 1) % 3)
                                       for i in range(2)
                                        for j in [0, 1, 2]])
    opt = BFGS(dimer,
               trajectory=calc.name + '.traj', logfile=calc.name + 'd.log')
    opt.run(0.001)

    if calc.name == 'tip4p':  # save optimized geom for EIQMMM test
        tip4pdimer = dimer.copy()

    e0 = dimer.get_potential_energy()
    d0 = dimer.get_distance(0, 3)
    R = dimer.positions
    v1 = R[2] - R[3]
    v2 = R[3] - (R[4] + R[5]) / 2
    a0 = np.arccos(np.dot(v1, v2) /
                   (np.dot(v1, v1) * np.dot(v2, v2))**0.5) / np.pi * 180
    fmt = '{0:>25}: {1:.3f} {2:.3f} {3:.3f} {4:.1f}'
    print(fmt.format(calc.name, -min(E), -e0, d0, a0))
    assert abs(e0 + eexp) < 0.002
    assert abs(d0 - dexp) < 0.006
    assert abs(a0 - aexp) < 2.5

# plt.show()

print(fmt.format('reference', 9.999, eexp, dexp, aexp))
Пример #28
0
from ase import Atoms
from ase.calculators.emt import EMT
from ase.constraints import FixBondLength
from ase.io import Trajectory
from ase.optimize import BFGS

a = 3.6
b = a / 2
cu = Atoms('Cu2Ag',
           positions=[(0, 0, 0),
                      (b, b, 0),
                      (a, a, b)],
           calculator=EMT())
e0 = cu.get_potential_energy()
print(e0)

d0 = cu.get_distance(0, 1)
cu.set_constraint(FixBondLength(0, 1))
t = Trajectory('cu2ag.traj', 'w', cu)
qn = BFGS(cu)
qn.attach(t.write)
def f(): print(cu.get_distance(0,1))
qn.attach(f)
qn.run(fmax=0.01)
assert abs(cu.get_distance(0, 1) - d0) < 1e-14
Пример #29
0
def check_min_dist(Optimizer, totalsol, type='Defect', nat=None, min_len=0.7, STR=''):
    if type=='Defect' or type=='Crystal' or type=='Surface':
        if nat==None:
            nat=len(totalsol)
        cutoffs=[2.0 for one in totalsol]
        nl=NeighborList(cutoffs,bothways=True,self_interaction=False)
        nl.update(totalsol)
        for one in totalsol[0:nat]:
            nbatoms=Atoms()
            nbatoms.append(one)
            indices, offsets=nl.get_neighbors(one.index)
            for index, d in zip(indices,offsets):
                index = int(index)
                sym=totalsol[index].symbol
                pos=totalsol[index].position + numpy.dot(d,totalsol.get_cell())
                at=Atom(symbol=sym,position=pos)
                nbatoms.append(at)
            while True:
                dflag=False
                for i in range(1,len(nbatoms)):
                    d=nbatoms.get_distance(0,i)
                    if d < min_len:
                        nbatoms.set_distance(0,i,min_len+.01,fix=0.5)
                        STR+='--- WARNING: Atoms too close (<0.7A) - Implement Move ---\n'
                        dflag=True
                if dflag==False:
                    break
            for i in range(len(indices)):
                totalsol[indices[i]].position=nbatoms[i+1].position
            totalsol[one.index].position=nbatoms[0].position
            nl.update(totalsol)
    elif type=='Cluster':
        rank = MPI.COMM_WORLD.Get_rank()
        logger = logging.getLogger(Optimizer.loggername)
        R = totalsol.arrays['positions']
        tol = 0.01
        epsilon = 0.05
        fix = 0.5
        if Optimizer.forcing == 'EllipoidShape' or Optimizer.forcing == 'FreeNatom': 
          com = totalsol.get_center_of_mass()       
          cmax = numpy.maximum.reduce(R)
          cmin = numpy.minimum.reduce(R)
          rmax= (cmax-cmin)/2.0 
          if Optimizer.forcing == 'FreeNatom':
             rcutoff = 44.0
             cutoff = [44.0,44.0,20.0]        
          else:
             rcutoff = 11.0
             cutoff = [12.0,12.0,12.0]        
          rcutoff = 44.0
          cutoff = [44.0,44.0,20.0]        
          #check if atoms are isolated outside of cluster
          cutoffs=[3.0 for one in totalsol]
          nl=NeighborList(cutoffs,bothways=True,self_interaction=False)
          nl.update(totalsol)
          for i in range(len(totalsol)):
             indices, offsets=nl.get_neighbors(i)
             D = R[i]-com
             radius = (numpy.dot(D,D))**0.5 #numpy.linalg.norm(D)
             if len(indices) < 12 or radius > rcutoff :
                # logger.info('M:move atoms back when indice {0} or radius {1}'.format(len(indices),radius))
                # R[i] = [com[j] + D[j]/radius*rcutoff for j in range(3)]
                theta=math.radians(random.uniform(0,360))
                phi=math.radians(random.uniform(0,180))
                R[i][0] = com[0] + (rmax[0]+2.5)*math.sin(theta)*math.cos(phi) #allow atoms expend by 2.5 ang
                R[i][1] = com[1] + (rmax[1]+2.5)*math.sin(theta)*math.sin(phi)
                R[i][2] = com[2] + rmax[2]*math.cos(theta)
                # logger.info('M:move atoms back new pos {0} {1} {2}'.format(rmax[0]*math.sin(theta)*math.cos(phi),rmax[1]*math.sin(theta)*math.sin(phi),rmax[2]*math.cos(theta)))
               
          # check if atoms are within cluster region 
          for i in range(0,len(totalsol)):
            # D = R[i]-com
            for j in range(3):                 
               if D[j] > cutoff[j] or D[j] < -cutoff[j]:
         #         logger.info('M:before move R {0} & com {1}'.format(R[i][j],com[j]))
                  #if rank==0:
                  #   print "before:",j,R[i][j],com[j] 
                  R[i][j] = com[j]+numpy.sign(D[j])*cutoff[j]*random.random()
         #         logger.info('M:after move R {0} '.format(R[i][j]))
                  #if rank==0:
                  #   print "after:",R[i][j]
              #    STR+='--- WARNING: Atoms too far along x-y (>44A) - Implement Move ---\n'          
                  D = R[i]-com
        #    radius = (numpy.dot(D,D))**0.5 #numpy.linalg.norm(D)
             #  STR+='--- WARNING: Atoms too far (>56A) - Implement Move ---\n'          
              

        closelist = numpy.arange(len(totalsol))
        iter = 0
        while len(closelist) > 0 and iter<2:
          iter+=1 
         # checklist = numpy.copy(closelist)
          closelist = []  
          dist=scipy.spatial.distance.cdist(R,R)       
          numpy.fill_diagonal(dist,1.0)
          smalldist = numpy.where(dist < min_len-tol)
         # for i in checklist:
            # for j in range(i+1,len(totalsol)):
         #    if len(checklist) == len(totalsol):
         #       jstart = i+1
         #    else:
         #       jstart = 0
         #    for j in range(jstart,len(totalsol)):
         #       if i != j and dist[i][j] < min_len:
             #       d=totalsol.get_distance(i,j)
             #       if d < min_len:
             #           totalsol.set_distance(i,j,min_len,fix=0.5)
                    # d = (D[0]*D[0]+D[1]*D[1]+D[2]*D[2])**0.5
          for ind in range(len(smalldist[0])):
                   i = smalldist[0][ind]
                   j = smalldist[1][ind]
                   if i < j and dist[i][j] < min_len-tol:   
                        closelist.append(i)
                        closelist.append(j)
                        if dist[i][j] > epsilon:
                      	  x = 1.0 - min_len / dist[i][j]
                          D = R[j]-R[i]
                         # print "node:",rank,"x",x,R[i],R[j],D, dist[i][j]
                       	  R[i] += (x * fix) * D
                          R[j] -= (x * (1.0 - fix)) * D
                        else:
                          R[i] += [0.2, 0.0, 0.0]
                          R[j] -= [0.2, 0.0, 0.0] 
                        R2P = [R[i],R[j]]
                        dist2P=scipy.spatial.distance.cdist(R2P,R)       
                        dist[i] = dist2P[0]
                        dist[j] = dist2P[1]
                        for k in range(len(R)):
                            dist[k][i] = dist[i][k]
                            dist[k][j] = dist[j][k]
                      #  STR+='--- WARNING: Atoms too close (<0.7A) - Implement Move ---\n'
          closelist=list(set(closelist))
          closelist.sort()
          if len(closelist) != 0: 
             logger.info('M:iter {0}, closelist size {1}'.format(iter,len(closelist)))
         #    print "rank", rank, closelist
    else:
        print 'WARNING: In Check_Min_Dist in EvalEnergy: Structure Type not recognized'
    return totalsol, STR
Пример #30
0
from ase.calculators.emt import EMT
from ase.constraints import FixBondLengths
from ase.optimize import BFGS
from ase.build import fcc111, add_adsorbate

for wrap 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 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
a = 10
d = 1.17103

CO2 = Atoms('CO2',
            positions=[[a / 2, a / 2, a / 2], [a / 2 - d, a / 2, a / 2],
                       [a / 2 + d, a / 2, a / 2]],
            cell=(a, a, a))

# Next, we need to create a calculator object

# The optimization calculation
# First we create the GPAW object

calc_PBE = GPAW(xc='PBE')
CO2.set_calculator(calc_PBE)

# By the way: by default, convergence of SCF is such that difference in energy is < 0.0005

# We can change this by adding the parameter: convergence={'energy': 0.0001}

# Next, we use a relaxation procedure
# Here, the atoms will be moved small steps in search for the optimal structure until the force on each atom is less that 0.05 eV/Ang

relax = QuasiNewton(CO2)
relax.run(fmax=0.05)
CO2.get_distance(0, 1)

# We started from the correct structure, that's why the optimization finished in only 1 step.
# Change d to 1 and see what happens. The optimization will finish in a number of iterations.
Пример #32
0
from ase import Atoms
from ase.calculators.emt import EMT
from ase.constraints import FixBondLength
from ase.io import PickleTrajectory
from ase.optimize import BFGS

a = 3.6
b = a / 2
cu = Atoms('Cu2Ag',
           positions=[(0, 0, 0),
                      (b, b, 0),
                      (a, a, b)],
           calculator=EMT())
e0 = cu.get_potential_energy()
print e0

d0 = cu.get_distance(0, 1)
cu.set_constraint(FixBondLength(0, 1))
t = PickleTrajectory('cu2ag.traj', 'w', cu)
qn = BFGS(cu)
qn.attach(t.write)
def f(): print cu.get_distance(0,1)
qn.attach(f)
qn.run(fmax=0.01)
assert abs(cu.get_distance(0, 1) - d0) < 1e-14
Пример #33
0
def lattice_alteration_nn(indiv, Optimizer):
    """Move function to perform random move along random axis for nearest neighbor distance to random atoms
    Inputs:
        indiv = Individual class object to be altered
        Optimizer = Optimizer class object with needed parameters
    Outputs:
        indiv = Altered Individual class object
    """
    if 'MU' in Optimizer.debug:
        debug = True
    else:
        debug = False
    if Optimizer.structure == 'Defect':
        if Optimizer.isolate_mutation:
            indc, indb, vacant, swaps, stro = find_defects(
                indiv[0], Optimizer.solidbulk, 0)
            ind = indc.copy()
            ind.extend(indb)
        else:
            ind = indiv[0].copy()
            indc = indiv[0].copy()
    else:
        ind = indiv[0].copy()
        indc = indiv[0].copy()
    if len(indc) != 0:
        ctoff1 = [1.0 for one in ind]
        nl = NeighborList(ctoff1, bothways=True, self_interaction=False)
        nl.update(ind)
        try:
            natomsmove = random.randint(1, len(indc) / 2)
        except ValueError:
            natomsmove = 1
        passn = 0
        for count in range(natomsmove):
            try:
                indexmv = random.choice([i for i in range(len(indc))])
                indices, offsets = nl.get_neighbors(indexmv)
                nns = Atoms()
                nns.append(ind[indexmv])
                for index, d in zip(indices, offsets):
                    index = int(index)
                    pos = ind[index].position + numpy.dot(d, ind.get_cell())
                    nns.append(Atom(symbol=ind[index].symbol, position=pos))
                dist = [nns.get_distance(0, i) for i in range(1, len(nns))]
                r = sum(dist) / len(dist)
                dir = random.choice([[1, 0, 0], [-1, 0, 0], [0, 1, 0],
                                     [0, -1, 0], [0, 0, 1], [0, 0, -1]])
                ind[indexmv].position += [i * r for i in dir]
            except:
                passn += 1
        indiv[0] = ind.copy()
    else:
        natomsmove = 0
        passn = 0
    Optimizer.output.write(
        'Lattice Alteration NN Mutation performed on individual\n')
    Optimizer.output.write('Index = ' + repr(indiv.index) + '\n')
    natomsmove -= passn
    Optimizer.output.write('Number of atoms moved = ' + repr(natomsmove) +
                           '\n')
    Optimizer.output.write(repr(indiv[0]) + '\n')
    muttype = 'LANN' + repr(natomsmove)
    if indiv.energy == 0:
        indiv.history_index = indiv.history_index + 'm' + muttype
    else:
        indiv.history_index = repr(indiv.index) + 'm' + muttype
    return indiv
Пример #34
0
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
Пример #35
0
# corresponding total energy, bond length and angle


for e_s in e_shifts:
    starttime = time.time()
    calc = Siesta('h2o',meshcutoff=200.0 * units.Ry, mix=0.5, pulay=4)
    calc.set_fdf('PAO.EnergyShift', e_s * units.eV)    
    calc.set_fdf('PAO.SplitNorm', 0.15)
    calc.set_fdf('PAO.BasisSize', 'SZ')
    h2o.set_calculator(calc)
    # Make a -traj file named h2o_current_shift.traj:      
    dyn = QuasiNewton(h2o, trajectory='h2o_%s.traj' % e_s)
    dyn.run(fmax=0.02)      # Perform the relaxation      
    E = h2o.get_potential_energy()
    print                                # Make the output more readable      
    print "E_shift: %.2f" %e_s       
    print "----------------"
    print "Total Energy: %.4f" % E       # Print total energy      
    d = h2o.get_distance(0,2)
    print "Bond length: %.4f" % d        # Print bond length      
    p = h2o.positions
    d1 = p[0] - p[2]
    d2 = p[1] - p[2]
    r = np.dot(d1, d2) / (np.linalg.norm(d1) * np.linalg.norm(d2))
    angle = np.arccos(r) / pi * 180
    print "Bond angle: %.4f" % angle      # Print bond angle
    endtime = time.time()
    walltime = endtime - starttime
    print 'Wall time: %.5f' % walltime
    print                                # Make the output more readable      
Пример #36
0
co.pbc = True
t.write(co)
del t

# append to a nonexisting file
fname = '2.nc'
if os.path.isfile(fname):
    os.remove(fname)
t = NetCDFTrajectory(fname, 'a', co)
del t

fname = '3.nc'
t = NetCDFTrajectory(fname, 'w', co)
# File is not created before first write
co.set_pbc([True, False, False])
d = co.get_distance(0, 1)
with warnings.catch_warnings():
    warnings.simplefilter('ignore', UserWarning)
    t.write(co)
del t
# Check pbc
for c in [1, 1000]:
    t = NetCDFTrajectory(fname, chunk_size=c)
    a = t[-1]
    assert a.pbc[0] and not a.pbc[1] and not a.pbc[2]
    assert abs(a.get_distance(0, 1) - d) < 1e-6
    del t
# Append something in Voigt notation
t = NetCDFTrajectory(fname, 'a')
for frame, a in enumerate(t):
    test = np.random.random([len(a), 6])
Пример #37
0
def test_qmmm(testdir):
    r = rOH
    a = angleHOH * pi / 180

    # From https://doi.org/10.1063/1.445869
    eexp = 6.50 * units.kcal / units.mol
    dexp = 2.74
    aexp = 27

    D = np.linspace(2.5, 3.5, 30)

    i = LJInteractions({('O', 'O'): (epsilon0, sigma0)})

    # General LJ interaction object
    sigma_mm = np.array([0, 0, sigma0])
    epsilon_mm = np.array([0, 0, epsilon0])
    sigma_qm = np.array([0, 0, sigma0])
    epsilon_qm = np.array([0, 0, epsilon0])
    ig = LJInteractionsGeneral(sigma_qm, epsilon_qm, sigma_mm, epsilon_mm, 3)

    for calc in [
            TIP3P(),
            SimpleQMMM([0, 1, 2], TIP3P(), TIP3P(), TIP3P()),
            SimpleQMMM([0, 1, 2], TIP3P(), TIP3P(), TIP3P(), vacuum=3.0),
            EIQMMM([0, 1, 2], TIP3P(), TIP3P(), i),
            EIQMMM([3, 4, 5], TIP3P(), TIP3P(), i, vacuum=3.0),
            EIQMMM([0, 1, 2], TIP3P(), TIP3P(), i, vacuum=3.0),
            EIQMMM([0, 1, 2], TIP3P(), TIP3P(), ig),
            EIQMMM([3, 4, 5], TIP3P(), TIP3P(), ig, vacuum=3.0),
            EIQMMM([0, 1, 2], TIP3P(), TIP3P(), ig, vacuum=3.0)
    ]:
        dimer = Atoms('H2OH2O',
                      [(r * cos(a), 0, r * sin(a)), (r, 0, 0), (0, 0, 0),
                       (r * cos(a / 2), r * sin(a / 2), 0),
                       (r * cos(a / 2), -r * sin(a / 2), 0), (0, 0, 0)])
        dimer.calc = calc

        E = []
        F = []
        for d in D:
            dimer.positions[3:, 0] += d - dimer.positions[5, 0]
            E.append(dimer.get_potential_energy())
            F.append(dimer.get_forces())

        F = np.array(F)

        F1 = np.polyval(np.polyder(np.polyfit(D, E, 7)), D)
        F2 = F[:, :3, 0].sum(1)
        error = abs(F1 - F2).max()
        assert error < 0.01

        dimer.constraints = FixInternals(bonds=[(r, (0, 2)), (r, (1, 2)),
                                                (r, (3, 5)), (r, (4, 5))],
                                         angles_deg=[
                                             (np.degrees(a), (0, 2, 1)),
                                             (np.degrees(a), (3, 5, 4))
                                         ])
        opt = GPMin(dimer,
                    trajectory=calc.name + '.traj',
                    logfile=calc.name + 'd.log')
        opt.run(0.01)

        e0 = dimer.get_potential_energy()
        d0 = dimer.get_distance(2, 5)
        R = dimer.positions
        v1 = R[1] - R[5]
        v2 = R[5] - (R[3] + R[4]) / 2
        a0 = np.arccos(
            np.dot(v1, v2) /
            (np.dot(v1, v1) * np.dot(v2, v2))**0.5) / np.pi * 180
        fmt = '{0:>20}: {1:.3f} {2:.3f} {3:.3f} {4:.1f}'
        print(fmt.format(calc.name, -min(E), -e0, d0, a0))
        assert abs(e0 + eexp) < 0.002
        assert abs(d0 - dexp) < 0.01
        assert abs(a0 - aexp) < 4

    print(fmt.format('reference', 9.999, eexp, dexp, aexp))
Пример #38
0
from ase import Atoms

# Setup a chain of H,O,C
# H-O Dist = 2
# O-C Dist = 3
# C-H Dist = 5 with mic=False
# C-H Dist = 4 with mic=True
a = Atoms('HOC', positions=[(1, 1, 1), (3, 1, 1), (6, 1, 1)])
a.set_cell((9, 2, 2))
a.set_pbc((True, False, False))


# Calculate indiviually with mic=True
assert a.get_distance(0, 1, mic=True) == 2
assert a.get_distance(1, 2, mic=True) == 3
assert a.get_distance(0, 2, mic=True) == 4

# Calculate indiviually with mic=False
assert a.get_distance(0, 1, mic=False) == 2
assert a.get_distance(1, 2, mic=False) == 3
assert a.get_distance(0, 2, mic=False) == 5

# Calculate in groups with mic=True
assert (a.get_distances(0, [1, 2], mic=True) == [2, 4]).all()

# Calculate in groups with mic=False
assert (a.get_distances(0, [1, 2], mic=False) == [2, 5]).all()

# Calculate all with mic=True
assert (a.get_all_distances(mic=True) == [[0, 2, 4],
                                          [2, 0, 3],
Пример #39
0
from ase import Atom, Atoms

m = Atoms('H2')
a = m[0]
b = Atom('H')
for c in [a, b]:
    assert c.x == 0
    c.z = 24.0
    assert c.position[2] == 24.0
    assert c.symbol == 'H'
    c.number = 92
    assert c.symbol == 'U'
    c.symbol = 'Fe'
    assert c.number == 26
    c.tag = 42
    assert c.tag == 42
    c.momentum = (1,2,3)
assert m[0].tag == 42
momenta = m.get_momenta()
m = Atoms('LiH')
for a in m:
    print(a.symbol)
for a in m:  
    if a.symbol == 'H':
        a.z = 0.75
assert m.get_distance(0, 1) == 0.75
a = m.pop()
m += a
del m[:1]
print(m)
Пример #40
0
    t.write(co)
del t

# append to a nonexisting file
if netcdftrajectory.have_nc == netcdftrajectory.NC_IS_NETCDF4:
    fname = '2.nc'
    if os.path.isfile(fname):
        os.remove(fname)
    t = NetCDFTrajectory(fname, 'a', co)
    del t

fname = '3.nc'
t = NetCDFTrajectory(fname, 'w', co)
# File is not created before first write
co.set_pbc([True, False, False])
d = co.get_distance(0, 1)
t.write(co)
del t
# Check pbc
t = NetCDFTrajectory(fname)
a = t[-1]
assert a.pbc[0] and not a.pbc[1] and not a.pbc[2]
assert abs(a.get_distance(0, 1) - d) < 1e-6
del t
# Append something in Voigt notation
t = NetCDFTrajectory(fname, 'a')
for frame, a in enumerate(t):
    test = np.random.random([len(a), 6])
    a.set_array('test', test)
    t.write_arrays(a, frame, ['test'])
del t
Пример #41
0
def test_qmmm_tip4p():
    from math import cos, sin, pi

    import numpy as np
    #import matplotlib.pyplot as plt

    import ase.units as units
    from ase import Atoms
    from ase.calculators.tip4p import TIP4P, epsilon0, sigma0, rOH, angleHOH
    from ase.calculators.qmmm import (SimpleQMMM, EIQMMM, LJInteractions,
                                      LJInteractionsGeneral)
    from ase.constraints import FixInternals
    from ase.optimize import BFGS

    r = rOH
    a = angleHOH * pi / 180

    # From https://doi.org/10.1063/1.445869
    eexp = 6.24 * units.kcal / units.mol
    dexp = 2.75
    aexp = 46

    D = np.linspace(2.5, 3.5, 30)

    i = LJInteractions({('O', 'O'): (epsilon0, sigma0)})

    # General LJ interaction object
    sigma_mm = np.array([sigma0, 0, 0])
    epsilon_mm = np.array([epsilon0, 0, 0])
    sigma_qm = np.array([sigma0, 0, 0])
    epsilon_qm = np.array([epsilon0, 0, 0])
    ig = LJInteractionsGeneral(sigma_qm, epsilon_qm, sigma_mm, epsilon_mm, 3)

    for calc in [
            TIP4P(),
            SimpleQMMM([0, 1, 2], TIP4P(), TIP4P(), TIP4P()),
            SimpleQMMM([0, 1, 2], TIP4P(), TIP4P(), TIP4P(), vacuum=3.0),
            EIQMMM([0, 1, 2], TIP4P(), TIP4P(), i),
            EIQMMM([3, 4, 5], TIP4P(), TIP4P(), i, vacuum=3.0),
            EIQMMM([0, 1, 2], TIP4P(), TIP4P(), i, vacuum=3.0),
            EIQMMM([0, 1, 2], TIP4P(), TIP4P(), ig),
            EIQMMM([3, 4, 5], TIP4P(), TIP4P(), ig, vacuum=3.0),
            EIQMMM([0, 1, 2], TIP4P(), TIP4P(), ig, vacuum=3.0)
    ]:
        dimer = Atoms('OH2OH2', [(0, 0, 0), (r * cos(a), 0, r * sin(a)),
                                 (r, 0, 0), (0, 0, 0),
                                 (r * cos(a / 2), r * sin(a / 2), 0),
                                 (r * cos(a / 2), -r * sin(a / 2), 0)])
        dimer.calc = calc

        E = []
        F = []
        for d in D:
            dimer.positions[3:, 0] += d - dimer.positions[3, 0]
            E.append(dimer.get_potential_energy())
            F.append(dimer.get_forces())

        F = np.array(F)

        #plt.plot(D, E)

        F1 = np.polyval(np.polyder(np.polyfit(D, E, 7)), D)
        F2 = F[:, :3, 0].sum(1)
        error = abs(F1 - F2).max()
        assert error < 0.01

        dimer.constraints = FixInternals(bonds=[(r, (0, 1)), (r, (0, 2)),
                                                (r, (3, 4)), (r, (3, 5))],
                                         angles=[(a, (2, 0, 1)),
                                                 (a, (5, 3, 4))])
        opt = BFGS(dimer,
                   maxstep=0.04,
                   trajectory=calc.name + '.traj',
                   logfile=calc.name + 'd.log')
        opt.run(0.01)

        e0 = dimer.get_potential_energy()
        d0 = dimer.get_distance(0, 3)
        R = dimer.positions
        v1 = R[2] - R[3]
        v2 = R[3] - (R[5] + R[4]) / 2
        a0 = np.arccos(
            np.dot(v1, v2) /
            (np.dot(v1, v1) * np.dot(v2, v2))**0.5) / np.pi * 180
        fmt = '{0:>23}: {1:.3f} {2:.3f} {3:.3f} {4:.1f}'
        print(fmt.format(calc.name, -min(E), -e0, d0, a0))
        assert abs(e0 + eexp) < 0.002
        assert abs(d0 - dexp) < 0.006
        assert abs(a0 - aexp) < 2.5

    print(fmt.format('reference', 9.999, eexp, dexp, aexp))
Пример #42
0
    # plt.plot(D, E)

    F1 = np.polyval(np.polyder(np.polyfit(D, E, 7)), D)
    F2 = F[:, :3, 0].sum(1)
    error = abs(F1 - F2).max()

    dimer.constraints = FixInternals(
        bonds=[(r, (0, 2)), (r, (1, 2)),
               (r, (3, 5)), (r, (4, 5))],
        angles=[(a, (0, 2, 1)), (a, (3, 5, 4))])
    opt = BFGS(dimer,
               trajectory=calc.name + '.traj', logfile=calc.name + 'd.log')
    opt.run(0.01)

    e0 = dimer.get_potential_energy()
    d0 = dimer.get_distance(2, 5)
    R = dimer.positions
    v1 = R[1] - R[5]
    v2 = R[5] - (R[3] + R[4]) / 2
    a0 = np.arccos(np.dot(v1, v2) /
                   (np.dot(v1, v1) * np.dot(v2, v2))**0.5) / np.pi * 180
    fmt = '{0:>20}: {1:.3f} {2:.3f} {3:.3f} {4:.1f}'
    print(fmt.format(calc.name, -min(E), -e0, d0, a0))
    assert abs(e0 + eexp) < 0.002
    assert abs(d0 - dexp) < 0.006
    assert abs(a0 - aexp) < 2

print(fmt.format('reference', 9.999, eexp, dexp, aexp))

# plt.show()
Пример #43
0
            mode=PW(700),
            kpts=kpts,
            xc='PBE',
            txt=myGpaw.symstr+'.out',
            occupations=FermiDirac(width=0.05),
          #   nbands=-2,
            convergence={'energy': 0.0005,  # eV / electron
               'density': 1.0e-4,
               'eigenstates': 4.0e-8,  # eV^2 / electron
               'bands': 'CBM+2.0',
               'forces': float('inf')}, # eV / Ang Max
            )

atoms.calc = calc
e2 = atoms.get_potential_energy()
d0 = atoms.get_distance(0, 1)
calc.write(myGpaw.symstr+'.gpw')

fd = open('optimization.txt', 'w')
print('experimental bond length:', file=fd)
print('experimental energy: %5.2f eV' % e2, file=fd)
print('bondlength              : %5.2f Ang' % d0, file=fd)

# # Find the theoretical bond length:
relax = QuasiNewton(atoms, logfile='qn.log', trajectory=myGpaw.symstr+'.emt.traj')
relax.run(fmax=0.05)

e2 = atoms.get_potential_energy()
d0 = atoms.get_distance(0, 1)
# calc.write(myGpaw.symstr+'relax.gpw')
Пример #44
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)
    opt = PreconLBFGS(monomer, precon=Exp(A=3), trajectory=name + 'M.traj')
    opt.run(0.02)
    e0 = monomer.get_potential_energy()
    be = dimer.get_potential_energy() - e0
    d = dimer.get_distance(0, 3)
    print(name, be, d)
    if name == '012':
        assert abs(be - -0.288) < 0.002
        assert abs(d - 2.76) < 0.02
    else:
        assert abs(be - -0.316) < 0.002
        assert abs(d - 2.67) < 0.02
Пример #45
-1
def test_emt1(testdir):
    a = 3.6
    b = a / 2
    cu = Atoms('Cu2Ag',
               positions=[(0, 0, 0),
                          (b, b, 0),
                          (a, a, b)],
               calculator=EMT())
    e0 = cu.get_potential_energy()
    print(e0)

    d0 = cu.get_distance(0, 1)
    cu.set_constraint(FixBondLength(0, 1))

    def f():
        print(cu.get_distance(0, 1))

    qn = BFGS(cu)
    with Trajectory('cu2ag.traj', 'w', cu) as t:
        qn.attach(t.write)

        qn.attach(f)
        qn.run(fmax=0.001)

    assert abs(cu.get_distance(0, 1) - d0) < 1e-14
def test_CO2_Au111(wrap, testdir):
    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)
    with BFGS(slab, trajectory='relax_%d.traj' % wrap) as dyn:
        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
Пример #47
-1
class Polycrystal(OrthoBox):
    def __init__(self, boxsize, numcrystallites, crystallitenames,
                 crystallitecenters):
        super().__init__(boxsize)
        self.numcrystallites = numcrystallites
        self.crystaltype = crystallitenames
        self.crystallitecenters = crystallitecenters
        self.crystallites = [Atoms() for n in range(numcrystallites)]
        self.crystalliteids = [[i] for i in range(numcrystallites)]

    def setgraintypes(self, typemap):
        self.graintypes = typemap

    def embedatoms(self, maskcrystal, grainid, keepatoms, compress=True):
        crystal = maskcrystal.copy()
        slicecrystal = crystal[keepatoms]
        natoms = slicecrystal.get_global_number_of_atoms()
        self.crystalliteids[grainid] = [grainid for i in range(natoms)]
        self.crystallites[grainid] = slicecrystal

    def compress(self):
        polycrystalbox = self.sidelens + self.angles
        self.polycrystal = Atoms(cell=polycrystalbox, pbc=True)
        for i, c in enumerate(self.crystallites):
            cids = self.crystalliteids[i]
            c.set_tags(cids)
            self.polycrystal += c
        self.natoms = self.polycrystal.get_global_number_of_atoms()
        chemsym = set(self.polycrystal.get_chemical_symbols())
        self.chemmap = {c: i + 1 for i, c in enumerate(chemsym)}
        self.nspecies = len(chemsym)

    def pruneoverlap(self, criteria=0.5, verbose=False):
        ''' TODO: remove atoms overlapping assume PBC conditions'''
        print(
            "NOTICE: The pruning routine does not accoutn for stoichiometry restrictions."
        )

        cutoff = neighborlist.natural_cutoffs(self.polycrystal)
        neighbors = neighborlist.NeighborList(cutoff,
                                              self_interaction=False,
                                              bothways=False)
        neighbors.update(self.polycrystal)

        isremoved = []
        for a in self.polycrystal:
            ineigh = neighbors.get_neighbors(a.index)
            for j in ineigh[0]:
                r = self.polycrystal.get_distance(a.index, j, mic=True)
                if r < criteria and j not in isremoved:
                    isremoved.append(j)
                    if verbose:
                        print("Atom ID %i removed due to overlap!" % (j))

        del self.polycrystal[isremoved]
        self.natoms = self.polycrystal.get_global_number_of_atoms()
Пример #48
-1
def test_atoms_distance():
    # Setup a chain of H,O,C
    # H-O Dist = 2
    # O-C Dist = 3
    # C-H Dist = 5 with mic=False
    # C-H Dist = 4 with mic=True
    a = Atoms('HOC', positions=[(1, 1, 1), (3, 1, 1), (6, 1, 1)])
    a.set_cell((9, 2, 2))
    a.set_pbc((True, False, False))


    # Calculate indiviually with mic=True
    assert a.get_distance(0, 1, mic=True) == 2
    assert a.get_distance(1, 2, mic=True) == 3
    assert a.get_distance(0, 2, mic=True) == 4

    # Calculate indiviually with mic=False
    assert a.get_distance(0, 1, mic=False) == 2
    assert a.get_distance(1, 2, mic=False) == 3
    assert a.get_distance(0, 2, mic=False) == 5

    # Calculate in groups with mic=True
    assert (a.get_distances(0, [1, 2], mic=True) == [2, 4]).all()

    # Calculate in groups with mic=False
    assert (a.get_distances(0, [1, 2], mic=False) == [2, 5]).all()

    # Calculate all with mic=True
    assert (a.get_all_distances(mic=True) == [[0, 2, 4],
                                              [2, 0, 3],
                                              [4, 3, 0]]).all()

    # Calculate all with mic=False
    assert (a.get_all_distances(mic=False) == [[0, 2, 5],
                                               [2, 0, 3],
                                               [5, 3, 0]]).all()

    # Scale Distance
    old = a.get_distance(0, 1)
    a.set_distance(0, 1, 0.9, add=True, factor=True)
    new = a.get_distance(0, 1)
    diff = new - 0.9 * old
    assert abs(diff) < 10e-6

    # Change Distance
    old = a.get_distance(0, 1)
    a.set_distance(0, 1, 0.9, add=True)
    new = a.get_distance(0, 1)
    diff = new - old - 0.9
    assert abs(diff) < 10e-6
Пример #49
-1
def check_min_dist(totalsol, type='Defect', nat=None, min_len=0.7, STR=''):
    if type=='Defect' or type=='Crystal' or type=='Surface':
        if nat==None:
            nat=len(totalsol)
        cutoffs=[2.0 for one in totalsol]
        nl=NeighborList(cutoffs,bothways=True,self_interaction=False)
        nl.update(totalsol)
        for one in totalsol[0:nat]:
            nbatoms=Atoms()
            nbatoms.append(one)
            indices, offsets=nl.get_neighbors(one.index)
            for index, d in zip(indices,offsets):
                index = int(index)
                sym=totalsol[index].symbol
                pos=totalsol[index].position + numpy.dot(d,totalsol.get_cell())
                at=Atom(symbol=sym,position=pos)
                nbatoms.append(at)
            while True:
                dflag=False
                for i in range(1,len(nbatoms)):
                    d=nbatoms.get_distance(0,i)
                    if d < min_len:
                        nbatoms.set_distance(0,i,min_len+.01,fix=0.5)
                        STR+='--- WARNING: Atoms too close (<0.7A) - Implement Move ---\n'
                        dflag=True
                if dflag==False:
                    break
            for i in range(len(indices)):
                totalsol[indices[i]].position=nbatoms[i+1].position
            totalsol[one.index].position=nbatoms[0].position
            nl.update(totalsol)
    elif type=='Cluster':
        for i in range(len(totalsol)):
            for j in range(len(totalsol)):
                if i != j:
                    d=totalsol.get_distance(i,j)
                    if d < min_len:
                        totalsol.set_distance(i,j,min_len,fix=0.5)
                        STR+='--- WARNING: Atoms too close (<0.7A) - Implement Move ---\n'
    else:
        print 'WARNING: In Check_Min_Dist in EvalEnergy: Structure Type not recognized'
    return totalsol, STR
Пример #50
-1
def eval_energy(input):
    """Function to evaluate energy of an individual
    Inputs:
        input = [Optimizer class object with parameters, Individual class structure to be evaluated]
    Outputs:
        energy, bul, individ, signal
        energy = energy of Individual evaluated
        bul = bulk structure of Individual if simulation structure is Defect
        individ = Individual class structure evaluated
        signal = string of information about evaluation
    """
    if input[0]==None:
        energy=0
        bul=0
        individ=0
        rank = MPI.COMM_WORLD.Get_rank()
        signal='Evaluated none individual on '+repr(rank)+'\n'
    else:
        [Optimizer, individ]=input
    if Optimizer.calc_method=='MAST':
        energy = individ.energy
        bul = individ.energy
        signal = 'Recieved MAST structure\n'
    else:
        if Optimizer.parallel: rank = MPI.COMM_WORLD.Get_rank()
        if not Optimizer.genealogy:
            STR='----Individual ' + str(individ.index)+ ' Optimization----\n'
        else:
            STR='----Individual ' + str(individ.history_index)+ ' Optimization----\n'
        indiv=individ[0]
        if 'EE' in Optimizer.debug:
            debug = True
        else:
            debug = False
        if debug: 
            write_xyz(Optimizer.debugfile,indiv,'Recieved by eval_energy')
            Optimizer.debugfile.flush()
        if Optimizer.structure=='Defect':
            indi=indiv.copy()
            if Optimizer.alloy==True:
                bulk=individ.bulki
            else:
                bulk=individ.bulko
            nat=indi.get_number_of_atoms()
            csize=bulk.get_cell()                                                                                                         
            totalsol=Atoms(cell=csize, pbc=True)
            totalsol.extend(indi)
            totalsol.extend(bulk)
            for sym,c,m,u in Optimizer.atomlist:
                nc=len([atm for atm in totalsol if atm.symbol==sym])
                STR+='Defect configuration contains '+repr(nc)+' '+repr(sym)+' atoms\n'
    
        elif Optimizer.structure=='Surface':
            totalsol=Atoms()
            totalsol.extend(indiv)
            nat=indiv.get_number_of_atoms()
            totalsol.extend(individ.bulki)
            for sym,c,m,u in Optimizer.atomlist:
                nc=len([atm for atm in totalsol if atm.symbol==sym])
                STR+='Surface-Bulk configuration contains '+repr(nc)+' '+repr(sym)+' atoms\n'
            cell=numpy.maximum.reduce(indiv.get_cell())
            totalsol.set_cell([cell[0],cell[1],500])
            totalsol.set_pbc([True,True,False])
    
        if Optimizer.constrain_position:
            ts = totalsol.copy()
            indc,indb,vacant,swap,stro = find_defects(ts,Optimizer.solidbulk,0)
            sbulk = Optimizer.solidbulk.copy()
            bcom = sbulk.get_center_of_mass()
            #totalsol.translate(-bulkcom)
            #indc.translate(-bulkcom)
            #totalsol.append(Atom(position=[0,0,0]))
    # 			for one in indc:
    # 				index = [atm.index for atm in totalsol if atm.position[0]==one.position[0] and atm.position[1]==one.position[1] and atm.position[2]==one.position[2]][0]
    # 				if totalsol.get_distance(-1,index) > Optimizer.sf:
    # 					r = random.random()
    # 					totalsol.set_distance(-1,index,Optimizer.sf*r,fix=0)
    # 			totalsol.pop()
    # 			totalsol.translate(bulkcom)
            com = indc.get_center_of_mass()
            dist = (sum((bcom[i] - com[i])**2 for i in range(3)))**0.5
            if dist > Optimizer.sf:
                STR+='Shifting structure to within region\n'
                r = random.random()*Optimizer.sf
                comv = numpy.linalg.norm(com)
                ncom = [one*r/comv for one in com]
                trans = [ncom[i]-com[i] for i in range(3)]
                indices = []
                for one in indc:
                    id = [atm.index for atm in totalsol if atm.position[0]==one.position[0] and atm.position[1]==one.position[1] and atm.position[2]==one.position[2]][0]
                    totalsol[id].position += trans
    
        # Check for atoms that are too close
        min_len=0.7
        #pdb.set_trace()
        if not Optimizer.fixed_region:
            if Optimizer.structure=='Defect' or Optimizer.structure=='Surface':
                cutoffs=[2.0 for one in totalsol]
                nl=NeighborList(cutoffs,bothways=True,self_interaction=False)
                nl.update(totalsol)
                for one in totalsol[0:nat]:
                    nbatoms=Atoms()
                    nbatoms.append(one)
                    indices, offsets=nl.get_neighbors(one.index)
                    for index, d in zip(indices,offsets):
                        index = int(index)
                        sym=totalsol[index].symbol
                        pos=totalsol[index].position + numpy.dot(d,totalsol.get_cell())
                        at=Atom(symbol=sym,position=pos)
                        nbatoms.append(at)
                    while True:
                        dflag=False
                        for i in range(1,len(nbatoms)):
                            d=nbatoms.get_distance(0,i)
                            if d < min_len:
                                nbatoms.set_distance(0,i,min_len+.01,fix=0.5)
                                STR+='--- WARNING: Atoms too close (<0.7A) - Implement Move ---\n'
                                dflag=True
                        if dflag==False:
                            break
                    for i in range(len(indices)):
                        totalsol[indices[i]].position=nbatoms[i+1].position
                    totalsol[one.index].position=nbatoms[0].position
                    nl.update(totalsol)
                if debug:
                    write_xyz(Optimizer.debugfile,totalsol,'After minlength check')
                    Optimizer.debugfile.flush()
            else:
                for i in range(len(indiv)):
                    for j in range(len(indiv)):
                        if i != j:
                            d=indiv.get_distance(i,j)
                            if d < min_len:
                                indiv.set_distance(i,j,min_len,fix=0.5)
                                STR+='--- WARNING: Atoms too close (<0.7A) - Implement Move ---\n'
                if debug:
                    write_xyz(Optimizer.debugfile,indiv,'After minlength check')
                    Optimizer.debugfile.flush()
    
        # Set calculator to use to get forces/energies
        if Optimizer.parallel:
            calc = setup_calculator(Optimizer)
            if Optimizer.fixed_region:
                pms=copy.deepcopy(calc.parameters)
                try:
                    pms['mass'][len(pms['mass'])-1] += '\ngroup RO id >= '+repr(nat)+'\nfix freeze RO setforce 0.0 0.0 0.0\n'
                except KeyError:
                    pms['pair_coeff'][0] += '\ngroup RO id >= '+repr(nat)+'\nfix freeze RO setforce 0.0 0.0 0.0\n'
                calc = LAMMPS(parameters=pms, files=calc.files, keep_tmp_files=calc.keep_tmp_files, tmp_dir=calc.tmp_dir)
                lmin = copy.copy(Optimizer.lammps_min)
                Optimizer.lammps_min = None
                Optimizer.static_calc = setup_calculator(Optimizer)
                Optimizer.lammps_min = lmin
        else:
            calc=Optimizer.calc
        if Optimizer.structure=='Defect' or Optimizer.structure=='Surface':
            totalsol.set_calculator(calc)
            totalsol.set_pbc(True)
        else:
            indiv.set_calculator(calc)
            indiv.set_pbc(True)	#Current bug in ASE optimizer-Lammps prevents pbc=false 
            if Optimizer.structure=='Cluster':
                indiv.set_cell([500,500,500])
                indiv.translate([250,250,250])
    
        cwd=os.getcwd()
        # Perform Energy Minimization
        if not Optimizer.parallel:
            Optimizer.output.flush()
        if Optimizer.ase_min == True:
            try:
                if Optimizer.structure=='Defect' or Optimizer.structure=='Surface':
                    dyn=BFGS(totalsol)
                else:
                    dyn=BFGS(indiv)
                dyn.run(fmax=Optimizer.ase_min_fmax, steps=Optimizer.ase_min_maxsteps)
            except OverflowError:
                STR+='--- Error: Infinite Energy Calculated - Implement Random ---\n'
                box=Atoms()
                indiv=gen_pop_box(Optimizer.natoms, Optimizer.atomlist, Optimizer.size)
                indiv.set_calculator(calc)
                dyn=BFGS(indiv)
                dyn.run(fmax=fmax, steps=steps)
            except numpy.linalg.linalg.LinAlgError:
                STR+='--- Error: Singular Matrix - Implement Random ---\n'
                indiv=gen_pop_box(Optimizer.natoms, Optimizer.atomlist, Optimizer.size)
                indiv.set_calculator(calc)
                dyn=BFGS(indiv)
                dyn.run(fmax=fmax, steps=steps)
            # Get Energy of Minimized Structure
            if Optimizer.structure=='Defect' or Optimizer.structure=='Surface':
                en=totalsol.get_potential_energy()
                #force=numpy.maximum.reduce(abs(totalsol.get_forces()))
                if Optimizer.fitness_scheme == 'enthalpyfit':
                    pressure=totalsol.get_isotropic_pressure(totalsol.get_stress())
                    cell_max=numpy.maximum.reduce(totalsol.get_positions())
                    cell_min=numpy.minimum.reduce(totalsol.get_positions())
                    cell=cell_max-cell_min
                    volume=cell[0]*cell[1]*cell[2]
                else:
                    pressure=0
                    volume=0
                na=totalsol.get_number_of_atoms()
                ena=en/na
                energy=en
                individ[0]=totalsol[0:nat]
                bul=totalsol[(nat):len(totalsol)]
                STR+='Number of positions = '+repr(len(bul)+len(individ[0]))+'\n'
                individ[0].set_cell(csize)
                indiv=individ[0]
            else:
                en=indiv.get_potential_energy()
                if Optimizer.fitness_scheme == 'enthalpyfit':
                    pressure=indiv.get_isotropic_pressure(indiv.get_stress())
                    cell_max=numpy.maximum.reduce(indiv.get_positions())
                    cell_min=numpy.minimum.reduce(indiv.get_positions())
                    cell=cell_max-cell_min
                    volume=cell[0]*cell[1]*cell[2]
                else: 
                    pressure=0
                    volume=0
                na=indiv.get_number_of_atoms()
                ena=en/na
                energy=ena
                individ[0]=indiv
                bul=0
        else:
            if Optimizer.structure=='Defect' or Optimizer.structure=='Surface':
                if Optimizer.calc_method=='VASP':
                    en=totalsol.get_potential_energy()
                    calcb=Vasp(restart=True)
                    totalsol=calcb.get_atoms()
                    stress=calcb.read_stress()
                else:
                    try:
                        totcop=totalsol.copy()
                        if debug: write_xyz(Optimizer.debugfile,totcop,'Individual sent to lammps')
                        OUT=totalsol.calc.calculate(totalsol)
                        totalsol=OUT['atoms']
                        totalsol.set_pbc(True)
                        if Optimizer.fixed_region:
                            if debug:
                                print 'Energy of fixed region calc = ', OUT['thermo'][-1]['pe']
                            totalsol.set_calculator(Optimizer.static_calc)
                            OUT=totalsol.calc.calculate(totalsol)
                            totalsol=OUT['atoms']
                            totalsol.set_pbc(True)
                            if debug:
                                print 'Energy of static calc = ', OUT['thermo'][-1]['pe']
                        en=OUT['thermo'][-1]['pe']
                        stress=numpy.array([OUT['thermo'][-1][i] for i in ('pxx','pyy','pzz','pyz','pxz','pxy')])*(-1e-4*GPa)
                        #force=numpy.maximum.reduce(abs(totalsol.get_forces()))
                        if debug:
                            write_xyz(Optimizer.debugfile,totalsol,'After Lammps Minimization')
                            Optimizer.debugfile.flush()
                    except Exception, e:
                        os.chdir(cwd)
                        STR+='WARNING: Exception during energy eval:\n'+repr(e)+'\n'
                        f=open('problem-structures.xyz','a')
                        write_xyz(f,totcop,data='Starting structure hindex='+individ.history_index)
                        write_xyz(f,totalsol,data='Lammps Min structure')
                        en=10
                        stress=0
                        f.close()
                if Optimizer.fitness_scheme == 'enthalpyfit':
                    pressure=totalsol.get_isotropic_pressure(stress)
                    cell_max=numpy.maximum.reduce(totalsol.get_positions())
                    cell_min=numpy.minimum.reduce(totalsol.get_positions())
                    cell=cell_max-cell_min
                    volume=cell[0]*cell[1]*cell[2]
                else:
                    pressure=totalsol.get_isotropic_pressure(stress)
                    volume=0
                na=totalsol.get_number_of_atoms()
                ena=en/na
                energy=en
                if Optimizer.structure=='Defect':
                    if Optimizer.fixed_region==True or Optimizer.finddefects==False:
                        individ[0]=totalsol[0:nat]
                        bul=totalsol[(nat):len(totalsol)]
                        individ[0].set_cell(csize)
                    else:
                        if 'FI' in Optimizer.debug:
                            outt=find_defects(totalsol,Optimizer.solidbulk,Optimizer.sf,atomlistcheck=Optimizer.atomlist,trackvacs=Optimizer.trackvacs,trackswaps=Optimizer.trackswaps,debug=Optimizer.debugfile)
                        else:
                            outt=find_defects(totalsol,Optimizer.solidbulk,Optimizer.sf,atomlistcheck=Optimizer.atomlist,trackvacs=Optimizer.trackvacs,trackswaps=Optimizer.trackswaps,debug=False)
                        individ[0]=outt[0]
                        bul=outt[1]
                        individ.vacancies = outt[2]
                        individ.swaps = outt[3]
                        STR += outt[4]
                    indiv=individ[0]
                else:
                    top,bul=find_top_layer(totalsol,Optimizer.surftopthick)
                    indiv=top.copy()
                    individ[0]=top.copy()
            else: