Exemplo n.º 1
0
def make_lattice_info(oatoms, hatoms, cellmat):
    logger = getLogger()

    assert oatoms.shape[0] > 0
    assert hatoms is None or oatoms.shape[0] * 2 == hatoms.shape[0]
    coord = 'relative'
    density = oatoms.shape[0] / (np.linalg.det(cellmat) *
                                 1e-21) * 18 / 6.022e23

    if hatoms is None:
        return SimpleNamespace(waters=oatoms,
                               coord=coord,
                               density=density,
                               bondlen=0.3,
                               cell=cellmat)

    rotmat = np.zeros((oatoms.shape[0], 3, 3))
    for i in range(oatoms.shape[0]):
        ro = oatoms[i]
        rdh0 = rel_wrap(hatoms[i * 2] - ro)
        rdh1 = rel_wrap(hatoms[i * 2 + 1] - ro)
        dh0 = np.dot(rdh0, cellmat)
        dh1 = np.dot(rdh1, cellmat)
        y = dh0 - dh1
        y /= np.linalg.norm(y)
        z = dh0 + dh1
        z /= np.linalg.norm(z)
        x = np.cross(y, z)
        rotmat[i] = np.vstack([x, y, z])
        # 重心位置を補正。
        oatoms[i] += (rdh0 + rdh1) * 1. / 18.
    grid = pl.determine_grid(cellmat, 0.245)
    # remove intramolecular OHs
    # 水素結合は原子の平均位置で定義している。
    pairs = []
    logger.debug("  Make pair list.")
    for o, h in pl.pairs_fine_hetero(oatoms,
                                     hatoms,
                                     0.245,
                                     cellmat,
                                     grid,
                                     distance=False):
        if not (h == o * 2 or h == o * 2 + 1):
            # hとoは別の分子の上にあって近い。
            # register a new intermolecular pair
            pairs.append((h // 2, o))
    logger.debug("  # of pairs: {0} {1}".format(len(pairs), oatoms.shape[0]))

    return SimpleNamespace(waters=oatoms,
                           coord=coord,
                           density=density,
                           pairs=pairs,
                           rotmat=rotmat,
                           cell=cellmat,
                           __doc__=None)
Exemplo n.º 2
0
def orientations(coord, graph, cell):
    """
    Does not work when two OHs are colinear
    """

    logger = getLogger()
    rotmatrices = []
    assert len(
        coord) == graph.number_of_nodes()  # just for a test of pure water

    for node in range(graph.number_of_nodes()):
        if node in graph.ignores:
            # for dopants; do not rotate
            rotmat = np.identity(3)
        else:
            vsucc = [
                cell.rel2abs(rel_wrap(coord[x] - coord[node]))
                for x in graph.successors(node)
            ]

            if len(vsucc) < 2:  # TSL
                vpred = [
                    cell.rel2abs(rel_wrap(coord[x] - coord[node]))
                    for x in graph.predecessors(node)
                ]
                vsucc = [x / np.linalg.norm(x) for x in vsucc]
                vpred = [x / np.linalg.norm(x) for x in vpred]

                if len(vpred) > 2:
                    vpred = vpred[:
                                  2]  # number of incoming bonds should be <= 2
                vcomp = assume_tetrahedral_vectors(vpred + vsucc)
                logger.debug("Node {0} vcomp {1} vsucc {2} vpred {3}".format(
                    node, vcomp, vsucc, vpred))
                vsucc = (vsucc + vcomp)[:2]

            logger.debug("Node {0} vsucc {1}".format(node, vsucc))
            assert 2 <= len(vsucc), "Probably a wrong ice network."
            # normalize vsucc
            vsucc[0] /= np.linalg.norm(vsucc[0])
            vsucc[1] /= np.linalg.norm(vsucc[1])
            y = vsucc[1] - vsucc[0]
            y /= np.linalg.norm(y)
            z = (vsucc[0] + vsucc[1]) / 2
            z /= np.linalg.norm(z)
            x = np.cross(y, z)
            # orthogonality check
            # logger.debug((x@x,y@y,z@z,x@y,y@z,z@x))
            rotmat = np.vstack([x, y, z])

        rotmatrices.append(rotmat)

    return rotmatrices
Exemplo n.º 3
0
def shortest_distance(coord, cell, pairs=None):
    dmin = 1e99

    if pairs is None:
        iter = it.combinations(coord, 2)
    else:
        iter = [(coord[i], coord[j]) for i, j in pairs]

    for c1, c2 in iter:
        r = cell.rel2abs(rel_wrap(c1 - c2))
        rr = np.dot(r, r)

        if rr < dmin:
            dmin = rr

    return dmin**0.5
Exemplo n.º 4
0
def Alkyl(cpos, root, cell, molname, backbone):
    """
    put a normal-alkyl group rooted at root toward cpos.
    """
    logger = getLogger()
    # logger.info("  Put butyl at {0}".format(molname))
    v1abs = cell.rel2abs(rel_wrap(cpos - root))
    v1 = v1abs / np.linalg.norm(v1abs)

    origin = cell.rel2abs(root)
    CC = 0.154
    rawatoms = alkyl.alkyl(v1, v1abs * 1.5 / CC, backbone)

    atoms = []
    for i, atom in enumerate(rawatoms):
        atomname, pos = atom
        atompos = cell.abs_wrapf(pos * CC + origin)
        atoms.append([i, molname, atomname, atompos, 0])

    return atoms
Exemplo n.º 5
0
def neighbor_cages_of_dopants(dopants, waters, cagepos, cell):
    """
    Just shows the environments of the dopants
    """
    #logger = getLogger()
    dnei = defaultdict(set)

    for site, name in dopants.items():
        org = waters[site]

        for i, pos in enumerate(cagepos):
            #Displacement (relative)
            a = cell.rel2abs(rel_wrap(pos - org))
            sqdistance = np.dot(a, a)

            if sqdistance < 0.57**2:
                dnei[site].add(i)
                # logger.info((i,cagepos[i]))

    return dnei
Exemplo n.º 6
0
def replicate_groups(groups, waters, cagepos, rep):
    """
    This is not that easy.
    """
    logger = getLogger()
    # Storage for replicated groups
    newgroups = defaultdict(dict)

    for root, cages in groups.items():
        # Position of root (water) (fractional)
        root_pos = waters[root]

        for cage, group_name in cages.items():
            # Position of the cage (fractional)
            cage_pos = cagepos[cage]
            # Relative position of the cage
            delta = rel_wrap(cage_pos - root_pos)
            # (Image) cell that the cage resides
            gcell = np.floor(root_pos + delta)

            for x in range(rep[0]):
                for y in range(rep[1]):
                    for z in range(rep[2]):
                        r = np.array((x, y, z))
                        # label of the root (water) in the replica
                        newroot = root + len(waters) * \
                            (x + rep[0] * (y + rep[1] * z))
                        # replicated cell in which the cage resides.
                        # modulo by positive number is always positive.
                        cr = (r + gcell) % rep
                        newcage = cage + \
                            len(cagepos) * (cr[0] + rep[0]
                                            * (cr[1] + rep[1] * cr[2]))
                        newcage = int(newcage)
                        newgroups[newroot][newcage] = group_name
                        # logger.info(("root",newroot,"newcage", newcage))
    return newgroups