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)
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
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
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
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
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