Ejemplo n.º 1
0
def is_hbonded2(mybgf, atom1, atom2, d_crit=2.2):
    """
    returns True if two atoms are h-bonded by a geometric definition.
    This definition is introduced in Grishina, N., & Buch, V. (2004). J. Chem. Phys., 120(11), 5217.
    20160608: Works only for O atoms.
    """

    if not "O" in atom1.ffType or not "O" in atom2.ffType:
        return False

    d = np.array([atom1.x, atom1.y, atom1.z])
    a = np.array([atom2.x, atom2.y, atom2.z])

    if mybgf.CRYSTX:
        pbc = mybgf.CRYSTX[:3]
    else:
        pbc = 0

    # A1-H ... A2
    for ano in atom1.CONECT:
        atom = mybgf.getAtom(ano)  # this should be an H atom
        x = np.array([atom.x, atom.y, atom.z])
        if pbc:
            dist = nu.pbc_dist(x, a, pbc)
        else:
            dist = nu.dist(x, a)
        if 1e-5 < dist < d_crit:
            return x

    # A1 ... H-A2
    for ano in atom2.CONECT:
        atom = mybgf.getAtom(ano)  # this should be an H atom
        x = np.array([atom.x, atom.y, atom.z])
        if pbc:
            dist = nu.pbc_dist(x, a, pbc)
        else:
            dist = nu.dist(x, a)
        if 1e-5 < dist < d_crit:
            return x

    return []
Ejemplo n.º 2
0
        def calc_hbonds():
            # variables
            A = []
            D = []
            hbonds = []
            d_crit = 3.5
            a_crit = 30.0

            for atom in mybgf.a:
                if selection:
                    if "O" in atom.ffType and eval(selection):
                        A.append(atom)
                    if "O" in atom.ffType and eval(selection):
                        D.append(atom)
                else:
                    if "O" in atom.ffType:
                        A.append(atom)
                    if "O" in atom.ffType:
                        D.append(atom)
            if not len(A) or not len(D):
                nu.die(
                    "There are no atoms which can make H_bond (O atoms so far)!"
                )

            # find nearest neighbor from D atom

            # calculate hbonds
            for d_atom in D:
                d = np.array([d_atom.x, d_atom.y, d_atom.z])
                for a_atom in A:
                    a = np.array([a_atom.x, a_atom.y, a_atom.z])
                    if 1e-5 < nu.pbc_dist(a, d, mytrj.pbc[t]) < d_crit:
                        for ano in d_atom.CONECT:
                            h_atom = mybgf.getAtom(ano)
                            h = np.array([h_atom.x, h_atom.y, h_atom.z])
                            u = h - d
                            v = a - d
                            theta = np.dot(u, v) / norm(u) / norm(v)
                            theta = np.degrees(arccos(theta))
                            if theta < a_crit:
                                hbonds.append([
                                    d_atom.aNo, a_atom.aNo, d_atom.z, a_atom.z
                                ])
                                #donors.append(d_atom.aNo)
                                #acceptors.append(a_atom.aNo)
                                #hydrogens.append(h_atom.aNo)
                                #distances.append(dist)

            return hbonds
Ejemplo n.º 3
0
        def calc_hbonds():
            # variables
            A = []
            D = []
            hbonds = []
            d_crit = 3.5
            a_crit = 30.0

            for atom in mybgf.a:
                if selection:
                    if "O" in atom.ffType and eval(selection):
                        A.append(atom)
                    if "O" in atom.ffType and eval(selection):
                        D.append(atom)
                else:
                    if "O" in atom.ffType:
                        A.append(atom)
                    if "O" in atom.ffType:
                        D.append(atom)
            if not len(A) or not len(D):
                nu.die(
                    "There are no atoms which can make H_bond (O atoms so far)!"
                )

            # calculate hbonds
            for d_atom in D:
                d = np.array([d_atom.x, d_atom.y, d_atom.z])
                neigh_anos = bt.get_neighbors_aNo(A,
                                                  d,
                                                  r=d_crit,
                                                  pbc=mytrj.pbc[t])
                for ano in neigh_anos:
                    a_atom = mybgf.getAtom(ano)
                    h = bt.is_hbonded2(mybgf, d_atom,
                                       a_atom)  # returns hbonded H coord
                    if len(h) != 0:
                        a = np.array([a_atom.x, a_atom.y, a_atom.z])
                        dist = nu.pbc_dist(a, d, mytrj.pbc[t])
                        u = h - d
                        v = a - d
                        theta = np.dot(u, v) / norm(u) / norm(v)
                        theta = np.degrees(arccos(theta))
                        hbonds.append(
                            [d_atom.aNo, a_atom.aNo, d, a, dist, theta])

            return hbonds
Ejemplo n.º 4
0
def is_hbonded(mybgf, atom1, atom2, d_crit=3.5, a_crit=30.0):
    """
    returns True if two atoms are h-bonded with a popular geometric definition d(O..O) = 3.5 and A(H-O-O) < 30'
    20160529: Works only for O atoms.
    """
    from numpy import arccos
    from numpy.linalg import norm

    if not "O" in atom1.ffType or not "O" in atom2.ffType:
        return False

    d = np.array([atom1.x, atom1.y, atom1.z])
    a = np.array([atom2.x, atom2.y, atom2.z])
    if 1e-5 < nu.pbc_dist(a, d, mybgf.CRYSTX[:3]) < d_crit:
        for ano in atom1.CONECT:
            # atom1: donor, atom2: acceptor
            h_atom = mybgf.getAtom(ano)
            h = np.array([h_atom.x, h_atom.y, h_atom.z])
            u = h - d
            v = a - d
            theta = np.dot(u, v) / norm(u) / norm(v)
            theta = np.degrees(arccos(theta))
            if theta < a_crit:
                return True

        for ano in atom2.CONECT:
            # atom2: donor, atom1: acceptor
            h_atom = mybgf.getAtom(ano)
            h = np.array([h_atom.x, h_atom.y, h_atom.z])
            u = h - d
            v = a - d
            theta = np.dot(u, v) / norm(u) / norm(v)
            theta = np.degrees(arccos(theta))
            if theta < a_crit:
                return True

    return False
Ejemplo n.º 5
0
        def calc_hbonds():
            hbonds = []
            d_crit = 3.6

            if selection:
                for atom in mybgf.a:
                    if "O" in atom.ffType and eval(selection):
                        A.append(atom)
                    if "O" in atom.ffType and eval(selection):
                        D.append(atom)

            # calculate hbonds
            for d_atom in D:
                d = np.array([d_atom.x, d_atom.y, d_atom.z])  # donor coord
                neigh_anos = bt.get_neighbors_aNo(A,
                                                  d,
                                                  r=d_crit,
                                                  pbc=mytrj.pbc[t],
                                                  k=6)

                for ano in neigh_anos:
                    a_atom = mybgf.getAtom(ano)
                    a = np.array([a_atom.x, a_atom.y,
                                  a_atom.z])  # acceptor coord
                    dist = nu.pbc_dist(a, d, mytrj.pbc[t])
                    if dist > 2.0:
                        for ano in d_atom.CONECT:
                            h_atom = mybgf.getAtom(ano)
                            h = np.array([h_atom.x, h_atom.y, h_atom.z])
                            u = h - d
                            v = a - d
                            theta = np.dot(u, v) / norm(u) / norm(v)
                            #theta = np.degrees(arccos(theta))
                            if -0.17364817766693034885171662676931 < theta < 1.0:
                                hbonds.append([dist, np.degrees(theta)])

            return hbonds
Ejemplo n.º 6
0
def calc_hbonds(mybgf, selection=""):
    # variables
    A = []
    D = []
    hbonds = []
    d_crit = 3.5
    a_crit = 30.0

    for atom in mybgf.a:
        if selection:
            if "O" in atom.ffType and eval(selection):
                A.append(atom)
            if "O" in atom.ffType and eval(selection):
                D.append(atom)
        else:
            if "O" in atom.ffType:
                A.append(atom)
            if "O" in atom.ffType:
                D.append(atom)
    if not len(A) or not len(D):
        nu.die("There are no atoms which can make H_bond (O atoms so far)!")

    # calculate hbonds
    for d_atom in D:
        d = np.array([d_atom.x, d_atom.y, d_atom.z])  # donor coord
        neigh_anos = bt.get_neighbors_aNo(A,
                                          d,
                                          r=d_crit,
                                          pbc=mytrj.pbc[t],
                                          k=6)
        donors = [d_atom.aNo] + d_atom.CONECT

        for ano in neigh_anos:
            a_atom = mybgf.getAtom(ano)
            a = np.array([a_atom.x, a_atom.y, a_atom.z])  # acceptor coord
            acceptors = [a_atom.aNo] + a_atom.CONECT

            for ano in d_atom.CONECT:
                h_atom = mybgf.getAtom(ano)
                h = np.array([h_atom.x, h_atom.y, h_atom.z])
                u = h - d
                v = a - d
                theta = np.dot(u, v) / norm(u) / norm(v)
                theta = np.degrees(arccos(theta))
                if theta < a_crit:  # HBond exists
                    dist = nu.pbc_dist(a, d, mytrj.pbc[t])
                    dist_ah = nu.pbc_dist(d, h, mytrj.pbc[t])

                    # E_vdw
                    sigma_r = O_sigma / dist
                    sigma_r_6 = sigma_r**6
                    sigma_r_12 = sigma_r**12
                    E_vdw = 4.0 * O_epsilon * (sigma_r_12 - sigma_r_6)
                    # E_vdw in kcal/mol

                    # E_coul
                    E_coul = 0.0
                    for i, j in itertools.product(donors, acceptors):
                        atom1 = mybgf.getAtom(i)
                        atom2 = mybgf.getAtom(j)
                        a1 = [atom1.x, atom1.y, atom1.z]
                        a2 = [atom2.x, atom2.y, atom2.z]
                        dist_ij = nu.pbc_dist(a1, a2, mytrj.pbc[t])
                        E_coul += 332.06371 * atom1.charge * atom2.charge / dist_ij  # E_coul in kcal/mol

                    # E_hbond
                    E_hbond = E_coul + E_vdw  # E_hbond = E_vdw + E_coul

                    # update for v4
                    # angle between H-O-H plane and O..O vector
                    H1 = mybgf.getAtom(d_atom.CONECT[0])
                    h1 = [H1.x, H1.y, H1.z]  # H1
                    H2 = mybgf.getAtom(d_atom.CONECT[1])
                    h2 = [H2.x, H2.y, H2.z]  # H2
                    p = d - h1
                    q = d - h2
                    n = np.cross(p, q)  # normal vector of the H1-O-H2 plane
                    m = a - d
                    # O..O vector
                    alpha = np.dot(n, m) / norm(n) / norm(m)
                    alpha = np.degrees(arcsin(
                        alpha))  # angle between H-O-H plane and O..O vector

                    hbonds.append([
                        d_atom.aNo, a_atom.aNo, d, a, dist, theta,
                        [E_coul, E_vdw, E_hbond], dist_ah, alpha
                    ])  # v4

    return hbonds
Ejemplo n.º 7
0
    def make_infinite(self, *args):
        '''
        args: filename to save
        '''
        print("CNT.py: make_infinite()")
        if len(args) > 1:
            nu.warn("make_infinite(): Too many arguments.")

        if not self.isPBCadjusted:
            nu.warn(
                "make_infinite(): You are trying to make infinite NT without adjusting PBC."
            )
            #return 0;

        print("\t* Found " + str(len(self.NTatoms)) +
              " atoms for the nanotube.")
        print("\t* Found " + str(len(self.WATatoms)) + " atoms for water.")

        if self.type == "BNT":
            self.detach_hydrogen()

        aNo_pair = []
        for atom in self.NTatoms:
            if len(atom.CONECT) == 3:
                continue

            x = np.array([atom.x, atom.y, atom.z])
            min_atom_aNo = 100000
            # placeholder
            min_atom_d = 10000.0

            for atom2 in self.NTatoms:
                if (not atom2.aNo in atom.CONECT) and len(atom2.CONECT) == 2:
                    if (atom.rName == atom2.rName) and (
                            self.type == "CNT" or atom.ffType != atom2.ffType):
                        y = np.array([atom2.x, atom2.y, atom2.z])
                        if -1.0 < ((x - y) * self.axismask).sum() < 1.0:
                            continue
                            # prevent adjacent atoms
                        d = nu.pbc_dist(x, y, self.pbc)
                        if d < min_atom_d:
                            min_atom_aNo = atom2.aNo
                            min_atom_d = d

            aNo_pair.append([atom.aNo, min_atom_aNo])

        for i in aNo_pair:
            self.bgfmodel.connectAtoms(i[0], i[1])

        self.check_connectivity()
        self.bgfmodel.renumber()

        if len(args) == 0:
            value = raw_input(
                "Do you want to save the infinite Nanotube structure to BGF file [N]? "
            )
            if "y" in value.lower():
                filename = self.model_filename[:-4] + ".infinite.bgf"
                value = raw_input("Filename to save [" + filename +
                                  "]? ") or filename
                self.bgfmodel.saveBGF(value)
        elif len(args) == 1:
            self.bgfmodel.saveBGF(args[0])
Ejemplo n.º 8
0
def countWaterCNT(bgf_file,
                  trj_file,
                  d_crit=3.5,
                  selection='',
                  nsample=0,
                  silent=False):

    ### init
    # constants
    deg_109p47 = math.radians(109.47)

    # variables
    timestep = 0
    l_timestep = []
    line = []
    n_header = 0
    avg_angles = []
    avg_diheds = []
    bin = np.arange(0.0, 181.0, 1.0)
    t1 = 0
    t2 = 0
    # clock

    myBGF = bgf.BgfFile(bgf_file)
    myTRJ = open(trj_file)
    myTRJ.seek(0)
    myDAT = open(bgf_file[:-4] + ".AOP.dat", "w")
    myDAT.write("#timestep\tAOP\tF4\n")

    # how many steps to go?
    #mytrj = lt.lammpstrj(trj_file)
    mytrj = Trj(trj_file)
    l_timestep = mytrj.load()
    n_timestep = len(l_timestep)
    l_timestep.sort()
    requested_timesteps = l_timestep[-nsample:]

    print(
        "Using neighboring water distance criteria %4.1f A (should be consistent with the coordination number)"
        % d_crit)
    print("The trajectory contains " + str(n_timestep) + " timesteps.")

    # Find header of the trajectory file
    while 1:
        templine = myTRJ.readline()
        line.append(templine.strip('\n').strip('ITEM: '))
        n_header += 1
        if "ITEM: ATOMS" in templine:
            break

    # INITIAL trajectory information
    timestep = int(line[1])
    natoms = int(line[3])
    boxsize = [
        line[5].split(' ')[0], line[5].split(' ')[1], line[6].split(' ')[0],
        line[6].split(' ')[1], line[7].split(' ')[0], line[7].split(' ')[1]
    ]
    boxsize = [float(i) for i in boxsize]
    keywords = line[8].strip('ATOMS ')

    # for every shot in the trajectory file update BGF and manipulate
    dumpatom = get_line(trj_file)
    processed_step = 0

    t1 = t2 = 0
    elapsed_time = 0

    while 1:
        ### Show progress
        t1 = time.time()
        remaining_time = elapsed_time * (len(requested_timesteps) -
                                         processed_step)
        sys.stdout.write('\r' + "Reading timestep.. " + str(timestep) +
                         " (Remaining time: " +
                         "{0:4.1f}".format(remaining_time) + " seconds, " +
                         "{0:4.1f} minutes".format(remaining_time / 60) + ")")
        sys.stdout.flush()

        ### Read
        try:
            chunk = [next(dumpatom) for i in range(natoms + n_header)]
        except StopIteration:
            break

        timestep = int(chunk[1])
        natoms = int(chunk[3])
        boxsize = [
            chunk[5].split(' ')[0], chunk[5].split(' ')[1],
            chunk[6].split(' ')[0], chunk[6].split(' ')[1],
            chunk[7].split(' ')[0], chunk[7].split(' ')[1]
        ]
        boxsize = [float(i) for i in boxsize]
        boxsize = [(boxsize[1] - boxsize[0]), (boxsize[3] - boxsize[2]),
                   (boxsize[5] - boxsize[4])]
        keywords = chunk[8].split('ATOMS ')[1].strip('\n').split(' ')

        if not timestep in requested_timesteps:
            continue

        ### update myBGF with trajectory information ###
        natom_bgf = len(myBGF.a)  # number of atoms in BGF file

        if not natom_bgf == natoms:
            nu.die(
                "Number of atoms in trajectory file does not match with BGF file."
            )

        mode = ""
        if 'xs' in keywords or 'ys' in keywords or 'zs' in keywords:
            mode = 'scaled'
        elif 'x' in keywords or 'y' in keywords or 'z' in keywords:
            mode = 'normal'
        elif 'xu' in keywords or 'yu' in keywords or 'zu' in keywords:
            mode = 'unwrapped'

        # actual coordinate
        coordinfo = chunk[9:]

        # assume that coordinfo is similar to ['id', 'type', 'xs', 'ys', 'zs', 'ix', 'iy', 'iz']
        for atomline in coordinfo:
            atomcoord = atomline.split(' ')

            atom = myBGF.getAtom(int(atomcoord[0]))

            if mode == 'scaled':
                atom.x = float(atomcoord[2]) * boxsize[0]
                atom.y = float(atomcoord[3]) * boxsize[1]
                atom.z = float(atomcoord[4]) * boxsize[2]

            elif mode == 'unwrapped':
                atom.x = float(atomcoord[2])
                atom.y = float(atomcoord[3])
                atom.z = float(atomcoord[4])

            elif mode == 'normal':
                try:
                    ix_index = keywords.index('ix')
                    iy_index = keywords.index('iy')
                    iz_index = keywords.index('iz')
                except ValueError:
                    nu.warn(
                        "No image information no the trajectory file. Will be treated as unwrapped."
                    )
                    atom.x = float(atomcoord[2])
                    atom.y = float(atomcoord[3])
                    atom.z = float(atomcoord[4])
                else:
                    atom.x = (int(atomcoord[ix_index]) * boxsize[0]) + float(
                        atomcoord[2])
                    atom.y = (int(atomcoord[iy_index]) * boxsize[1]) + float(
                        atomcoord[3])
                    atom.z = (int(atomcoord[iz_index]) * boxsize[2]) + float(
                        atomcoord[4])

            try:
                for i in range(0, 3):
                    myBGF.CRYSTX[i] = boxsize[i]
            except:
                pass

        # apply periodic condition
        myBGF = bgftools.periodicMoleculeSort(myBGF, myBGF.CRYSTX, silent=True)

        ### myBGF update complete! ###

        # get water OW
        O = []
        anos_O = []
        for atom in myBGF.a:
            if selection:
                if "O" in atom.ffType and eval(selection):
                    O.append(atom)
                    anos_O.append(atom.aNo)
            else:
                if "O" in atom.ffType:
                    O.append(atom)
                    anos_O.append(atom.aNo)

        if not len(O):
            nu.die("There are no O atoms which satisfies %s!" % selection)

        ### calculate AOP and F4
        sys.stdout.write('AOP..... ')
        sys.stdout.flush()

        coords = []
        anos = []
        for atom in O:
            coords.append([atom.x, atom.y, atom.z])
            anos.append(atom.aNo)

        pbc = np.array(myBGF.CRYSTX[:3])
        coords = np.array(coords)
        tree = pkdtree.PeriodicKDTree(
            pbc, coords)  # KDtree for distance calculation

        # analyze local water structures for a timestep
        n_neighbors = []
        angles = []
        diheds = []
        for atom in O:
            # local variables

            # find neighbors
            neighbors = []
            # list of O atoms near centerO
            centerO = np.array([atom.x, atom.y, atom.z])
            d, ndx = tree.query(centerO, k=6)
            index = np.where((d >= 1e-4) & (d <= d_crit))  # discard self
            for i in ndx[index]:
                neighbors.append(myBGF.getAtom(anos[i]))

            # calculate O1-O-O2 angle
            for i, j in itertools.combinations(neighbors, 2):
                if not "O" in i.ffType or not "O" in j.ffType:
                    nu.die("Wrong atom found.")
                x = [i.x, i.y, i.z]
                y = [j.x, j.y, j.z]
                pbc_dist = nu.pbc_dist(x, y, pbc)
                dist = nu.dist(x, y)
                if abs(pbc_dist - dist) > 0.1:
                    continue
                    # discard atoms over pbc boundaries

                # angle
                angle = nu.angle(x, centerO, y, radians=False)
                angles.append(angle)

            n_neighbors.append(
                len(neighbors))  # number of neighboring water molecules

            # calculate dihedral
            for i in neighbors:
                # find aNos of H located farthest among all combinations
                hO_anos = atom.CONECT
                hi_anos = i.CONECT
                max_dist_pair = []
                max_dist = 0.0
                for k, l in itertools.product(hO_anos, hi_anos):
                    h1 = myBGF.getAtom(k)  # H atom connected with atom
                    h2 = myBGF.getAtom(l)  # H atom connected with i
                    dist = bgf.distance(h1, h2)
                    if dist > max_dist:
                        max_dist = dist
                        max_dist_pair = [
                            h1, h2
                        ]  # now we have two H atoms in maximum distance connected with atom and i

                # dihedral angle
                phi = bgf.dihedral(max_dist_pair[0],
                                   atom,
                                   i,
                                   max_dist_pair[1],
                                   radians=False)
                diheds.append(phi)

        hist_angle, _ = np.histogram(angles, bins=bin, normed=True)
        hist_dihed, _ = np.histogram(diheds, bins=bin, normed=True)
        avg_angles.append(hist_angle)
        avg_diheds.append(hist_dihed)

        sys.stdout.write(
            'Done                                                        ')
        sys.stdout.flush()

        # write output
        processed_step += 1
        t2 = time.time()  # time mark
        elapsed_time = t2 - t1

    avg_angles = np.mean(np.array(avg_angles), axis=0)
    avg_diheds = np.mean(np.array(avg_diheds), axis=0)

    #print(avg_diheds)

    myDAT.write("#angles population\n")
    for index, i in enumerate(avg_angles):
        myDAT.write("%8.2f %8.5f\n" % (_[index], avg_angles[index]))
    myDAT.write("\n\n")
    myDAT.write("#diheds population\n")
    for index, i in enumerate(avg_diheds):
        myDAT.write("%8.2f %8.5f\n" % (_[index], avg_diheds[index]))

    myDAT.close()
    print('')

    return 1
Ejemplo n.º 9
0
if len(sys.argv) < 2:
    print(usage)
    sys.exit(0)

bgffile = bgf.BgfFile(sys.argv[1])
if sys.argv[2]:
    delta = float(sys.argv[2])
else:
    delta = 0.001

c = [atom for atom in bgffile.a if "C_2G" in atom.ffType]

dist = []
for atom in tqdm.tqdm(c, ncols=120, desc="Calculating"):
    x = [atom.x, atom.y, atom.z]
    for ano in atom.CONECT:
        atom2 = bgffile.getAtom(ano)
        y = [atom2.x, atom2.y, atom2.z]
        dist.append(nu.pbc_dist(x, y, bgffile.CRYSTX[:3]))

dist = np.array(dist)
if delta < (dist.max() - dist.min()):
    print(dist.min(), dist.max(), dist.max()-dist.min())
    bin = np.arange(dist.min(), dist.max(), delta)
    distr, _ = np.histogram(dist, bins=bin)
    norm_distr = distr / float(distr.sum())
    pprint(norm_distr)
else:
    print("average: %s, stdev: %s" % (dist.mean(), dist.std()))
Ejemplo n.º 10
0
        def calc_hbonds():
            # variables
            A = []
            D = []
            hbonds = []
            d_crit = 3.5
            a_crit = 30.0

            for atom in mybgf.a:
                if selection:
                    if "O" in atom.ffType and eval(selection):
                        A.append(atom)
                    if "O" in atom.ffType and eval(selection):
                        D.append(atom)
                else:
                    if "O" in atom.ffType:
                        A.append(atom)
                    if "O" in atom.ffType:
                        D.append(atom)
            if not len(A) or not len(D):
                nu.die(
                    "There are no atoms which can make H_bond (O atoms so far)!"
                )

            # calculate hbonds
            for d_atom in D:
                d = np.array([d_atom.x, d_atom.y, d_atom.z])  # donor coord
                neigh_anos = bt.get_neighbors_aNo(A,
                                                  d,
                                                  r=d_crit,
                                                  pbc=mytrj.pbc[t],
                                                  k=6)
                donors = [d_atom.aNo] + d_atom.CONECT

                for ano in neigh_anos:
                    a_atom = mybgf.getAtom(ano)
                    a = np.array([a_atom.x, a_atom.y,
                                  a_atom.z])  # acceptor coord
                    acceptors = [a_atom.aNo] + a_atom.CONECT

                    for ano in d_atom.CONECT:
                        h_atom = mybgf.getAtom(ano)
                        h = np.array([h_atom.x, h_atom.y, h_atom.z])
                        u = h - d
                        v = a - d
                        theta = np.dot(u, v) / norm(u) / norm(v)
                        theta = np.degrees(arccos(theta))
                        if theta < a_crit:
                            dist = nu.pbc_dist(a, d, mytrj.pbc[t])
                            dist_dh = nu.pbc_dist(d, h, mytrj.pbc[t])
                            # E_vdw
                            sigma_r = O_sigma / dist
                            sigma_r_6 = sigma_r**6
                            sigma_r_12 = sigma_r**12
                            E_vdw = 4.0 * O_epsilon * (sigma_r_12 - sigma_r_6)
                            # Evdw in kcal/mol

                            # E_coul
                            E_coul = 0.0
                            for i, j in itertools.product(donors, acceptors):
                                atom1 = mybgf.getAtom(i)
                                atom2 = mybgf.getAtom(j)
                                a1 = [atom1.x, atom1.y, atom1.z]
                                a2 = [atom2.x, atom2.y, atom2.z]
                                dist_ij = nu.pbc_dist(a1, a2, mytrj.pbc[t])
                                E_coul += 332.06371 * atom1.charge * atom2.charge / dist_ij
                            #E_coul /= 2.0
                            E_hbond = E_coul + E_vdw  # E_hbond = E_vdw + E_coul
                            #print("e_coul: %f, e_coul2: %f, E_coul: %f, E_vdw: %f, E_hbond: %f, O-O dist: %f, O-H dist: %f" % (e_coul, e_coul2, E_coul, E_vdw, E_hbond, dist, dist_a_dh))
                            #print("E_coul: %f, E_vdw: %f, E_hbond: %f, O-O dist: %f" % (E_coul, E_vdw, E_hbond, dist))

                            #hbonds.append([d_atom.aNo, a_atom.aNo, d, a, dist, theta, [E_coul, E_vdw, E_hbond]])
                            hbonds.append([
                                d_atom.aNo, a_atom.aNo, d, a, dist, theta,
                                [E_coul, E_vdw, E_hbond], dist_dh
                            ])

            return hbonds
Ejemplo n.º 11
0
    if "S" in atom.ffType:
        if atom.z > avg_mo_z:
            atom.ffType = "S_3a"
        else:
            atom.ffType = "S_3b"

# remove infinite boundary
n_del = 0
for atom in tqdm.tqdm(moslayer.a, ncols=120, desc='Removing pbc bonds'):
    a = [atom.x, atom.y, atom.z]
    connected_ano = atom.CONECT
    for ano in connected_ano:
        atom2 = moslayer.getAtom(ano)
        a2 = [atom2.x, atom2.y, atom2.z]
        dist = nu.dist(a, a2)
        pbc_dist = nu.pbc_dist(a, a2, moslayer.CRYSTX[:3])
        if dist != pbc_dist:
            moslayer.disconnect(moslayer.a2i[atom.aNo],
                                moslayer.a2i[atom2.aNo])
            n_del += 1
print("%d bonds are disconnected." % n_del)

# remove infinite boundary
n_del = 0
for atom in tqdm.tqdm(moslayer.a, ncols=120, desc='Removing pbc bonds 2'):
    a = [atom.x, atom.y, atom.z]
    connected_ano = atom.CONECT
    for ano in connected_ano:
        atom2 = moslayer.getAtom(ano)
        a2 = [atom2.x, atom2.y, atom2.z]
        dist = nu.dist(a, a2)
Ejemplo n.º 12
0
def make_infinite(mybgf):
    def calc_bond_dist(pbc=False):
        dist = []
        for atom in mybgf.a:
            if not "C_2G" in atom.ffType:
                continue
            for ano in atom.CONECT:
                atom2 = mybgf.getAtom(ano)
                if not "C_2G" in atom2.ffType:
                    continue

                if pbc:
                    dist.append(bgf.pbc_distance(atom, atom2,
                                                 mybgf.CRYSTX[:3]))
                else:
                    dist.append(bgf.distance(atom, atom2))

        return np.average(dist), np.std(dist)

    distance, _ = calc_bond_dist()

    # TODO: need to distinguish armchair and zigzag boundaries
    minmax_x = bgftools.atoms_minmax(mybgf,
                                     "x",
                                     selection="'C_2G' in atom.ffType")
    minmax_y = bgftools.atoms_minmax(mybgf,
                                     "y",
                                     selection="'C_2G' in atom.ffType")

    pbc_x = (minmax_x[1] - minmax_x[0]) + distance * np.cos(
        np.radians(30))  # in 5nm x 5nm graphene, x boundaries are armchair
    pbc_y = (minmax_y[1] - minmax_y[0]
             ) + distance  # in 5nm x 5nm graphene, y boundaries are zigzag

    mybgf.PERIOD = "111"
    mybgf.AXES = "ZYX"
    mybgf.SGNAME = "P 1                  1    1"
    mybgf.CELLS = [-1, 1, -1, 1, -1, 1]
    mybgf.CRYSTX = [pbc_x, pbc_y, 10.0, 90.0, 90.0, 90.0]
    print("Assigning new pbc: %s" % mybgf.CRYSTX)

    # init
    aNo_pair = []
    pbc = mybgf.CRYSTX[:3]

    edge_atoms = []

    # loop
    for atom in tqdm(mybgf.a, ncols=80, miniters=100, desc="Analyzing atoms"):
        if not "C" in atom.ffType:
            continue
        if len(atom.CONECT) == 3:
            continue

        x = np.array([atom.x, atom.y, atom.z])
        min_atom_aNo = 100000
        # placeholder
        min_atom_d = 10000.0

        for atom2 in mybgf.a:
            if len(atom2.CONECT) == 3:
                continue

            if atom.aNo != atom2.aNo:
                if (not atom2.aNo in atom.CONECT) and len(
                        atom2.CONECT) != 3 and (atom.rName == atom2.rName):
                    y = np.array([atom2.x, atom2.y, atom2.z])
                    d = nu.pbc_dist(x, y, pbc)
                    if d < min_atom_d:
                        min_atom_aNo = atom2.aNo
                        min_atom_d = d

        #aNo_pair.append([atom.aNo, min_atom_aNo])
        if min_atom_aNo == 100000:
            nu.die("Failed to find the closest atom for atom number " +
                   str(atom.aNo))

        mybgf.connectAtoms(atom.aNo, min_atom_aNo)

    #for i in aNo_pair:
    #    mybgf.connectAtoms(i[0], i[1])

    check_connectivity()

    # check bond distance stdev
    _, stdev = calc_bond_dist(pbc=True)
    if stdev <= 1e5:
        print("The structure seems to have regular distance over pbc.")
    else:
        nu.die("PBC assignment does not give a regular distances over pbc.")

    if out_file == "":
        filename = bgf_file.split(".bgf")[0] + ".infinite.bgf"
    else:
        filename = out_file
    value = raw_input("Filename to save [" + filename + "]? ") or filename
    mybgf.saveBGF(value)
Ejemplo n.º 13
0
def hbonds(mybgf, selection = ""):
    '''
    This function calculates Hydrogen bonds(hbonds) between O(donor) and O(acceptor), especially for water molecules.
    Input: 
        - bgf.BgfFile mybgf
        - string selection: a region to search donor and acceptor atoms in mybgf
    Output:
        - int n_sel_atoms: number of hbond-able atoms in the selection region
        - list hbonds: self-descriptive
    '''

    # variables
    pbc = mybgf.CRYSTX[:3]
    d_crit = 3.5; a_crit = 30.0 # Chandler's criteria

    if selection:
        A = [atom for atom in mybgf.a if "O" in atom.ffType and eval(selection)]
        D = [atom for atom in mybgf.a if "O" in atom.ffType and eval(selection)]
    else:
        A = [atom for atom in mybgf.a if "O" in atom.ffType]
        D = [atom for atom in mybgf.a if "O" in atom.ffType]

    if not len(A) or not len(D):
        nu.warn("There are no atoms which can make hbonds (O atoms so far)!")
        return

    # calculate hbonds
    hbonds = []; 

    for d_atom in D:
        d = np.array([d_atom.x, d_atom.y, d_atom.z])    # donor coord
        neigh_anos = bt.get_neighbors_aNo(A, d, r=d_crit, pbc=pbc, k=5)
        donors = [d_atom.aNo] + d_atom.CONECT

        for ano in neigh_anos:
            a_atom = mybgf.getAtom(ano)
            a = np.array([a_atom.x, a_atom.y, a_atom.z])    # acceptor coord
            acceptors = [a_atom.aNo] + a_atom.CONECT

            for ano in d_atom.CONECT:
                h_atom = mybgf.getAtom(ano)
                h = np.array([h_atom.x, h_atom.y, h_atom.z])
                u = h - d; v = a - d; 
                theta = np.dot(u, v) / norm(u) / norm(v); theta = np.degrees(arccos(theta))
                if theta < a_crit:  # HBond exists
                    # calculate pair energy as Hbond energy
                    dist = nu.pbc_dist(a, d, pbc)
                    dist_ah = nu.pbc_dist(d, h, pbc)

                    # E_vdw
                    sigma_r = O_sigma / dist; sigma_r_6 = sigma_r**6; sigma_r_12 = sigma_r**12
                    E_vdw = 4.0 * O_epsilon * (sigma_r_12 - sigma_r_6); # E_vdw in kcal/mol

                    # E_coul
                    E_coul = 0.0
                    for i, j in itertools.product(donors, acceptors):
                        atom1 = mybgf.getAtom(i)
                        atom2 = mybgf.getAtom(j)
                        a1 = [atom1.x, atom1.y, atom1.z]
                        a2 = [atom2.x, atom2.y, atom2.z]
                        dist_ij = nu.pbc_dist(a1, a2, pbc)
                        E_coul += 332.06371 * atom1.charge * atom2.charge / dist_ij # E_coul in kcal/mol

                    # E_hbond
                    E_hbond = E_coul + E_vdw  # E_hbond = E_vdw + E_coul

                    '''
                    # calculate dreiding style hbond energy:  http://lammps.sandia.gov/doc/pair_hbond_dreiding.html
                    # REMARK: tested on bulk water, ice, and confined water between MoS2 but achieved suspicious values:
                    # 6.0 $\AA$ maximum: -7.925 kcal/mol
                    # 8.0 $\AA$ maximum: -7.875 kcal/mol
                    # 11.0 $\AA$ maximum: -8.025 kcal/mol
                    # ice maximum: -8.325 kcal/mol
                    # water maximum: -7.775 kcal/mol
                    sigma = 2.75 # in A
                    epsilon = 9.0 # in kcal/mol
                    u = d - h; v = a - h; cos_theta = np.dot(u, v) / norm(u) / norm(v); #cos_theta = np.cos(theta)
                    sigma_r = sigma / dist; sigma_r_2 = sigma_r**2; sigma_r_12 = sigma_r_2**6; sigma_r_10 = sigma_r_2**5
                    E_hbond = epsilon * ( 5 * sigma_r_12 - 6 * sigma_r_10 ) * cos_theta**4
                    '''

                    hbonds.append([d_atom.aNo, a_atom.aNo, dist, theta, E_hbond])   # v5

    return hbonds