def toWater(coord, cell): logger = logging.getLogger() dmin = shortest_distance(coord, cell) pairs = [ v for v in pl.pairlist_crude(coord, dmin * 1.4, cell, distance=False) ] for vtet, dtet in tetrahedra(pairs, dmin * 1.4, coord, cell): p = dtet[0] + (dtet[1] + dtet[2] + dtet[3]) / 4 p -= np.floor(p) yield p
def prepare_random_graph(self, fixed): if self.pairs is None: self.logger.info(" Pairs are not given explicitly.") self.logger.info( " Start estimating the bonds according to the pair distances." ) # make bonded pairs according to the pair distance. # make before replicating them. grid = pl.determine_grid(self.cell.mat, self.bondlen) assert np.product( grid ) > 0, "Too thin unit cell. Consider use of --rep option if the cell was made by cif2ice." self.pairs = [ v for v in pl.pairlist_fine(self.waters, self.bondlen, self.cell.mat, grid, distance=False) ] # Check using a simpler algorithm. if self.logger.level <= logging.DEBUG: pairs2 = [ v for v in pl.pairlist_crude(self.waters, self.bondlen, self.cell.mat, distance=False) ] self.logger.debug("pairs: {0}".format(len(self.pairs))) self.logger.debug("pairs2: {0}".format(len(pairs2))) for pair in self.pairs: i, j = pair assert (i, j) in pairs2 or (j, i) in pairs2 for pair in pairs2: i, j = pair assert (i, j) in self.pairs or (j, i) in self.pairs graph = dg.IceGraph() for i, j in fixed: graph.add_edge(i, j, fixed=True) # Fixed pairs are default. for pair in self.pairs: i, j = pair if graph.has_edge(i, j) or graph.has_edge(j, i): pass else: if random.randint(0, 1) == 0: graph.add_edge(i, j, fixed=False) else: graph.add_edge(j, i, fixed=False) return graph
def main(): mode = "python" #output python module for GenIce if sys.argv[1] == "-y": mode = "yaplot" sys.argv.pop(1) Ncyl = int(sys.argv[1]) #read O positions cell, atoms = LoadAR3R(sys.stdin) #build the network dmin = shortest_distance(atoms, cell) pairs = [ v for v in pl.pairlist_crude(atoms, dmin * 1.1, cell, distance=False) ] #decorate dec = decorate(atoms, cell, pairs, Ncyl, mode) print(dec)
def generate_ice(lattice_type, density=-1, seed=1000, rep=(1, 1, 1), stage=3): logger = logging.getLogger() logger.info("Ice type: {0}".format(lattice_type)) lat = safe_import("lattice", lattice_type) #Show the document of the module try: for line in lat.__doc__.splitlines(): logger.info("!!! {0}".format(line)) except: pass lat.waters = load_numbers(lat.waters) logger.debug("Waters: {0}".format(len(lat.waters))) lat.waters = lat.waters.reshape((lat.waters.size // 3, 3)) #prepare cell transformation matrix if lat.celltype == "rect": if type(lat.cell) is str: lat.cell = np.fromstring(lat.cell, sep=" ") elif type(lat.cell) is list: lat.cell = np.array(lat.cell) lat.cell = np.diag(lat.cell) elif lat.celltype == "monoclinic": if type(lat.cell) is str: lat.cell = np.fromstring(lat.cell, sep=" ") elif type(lat.cell) is list: lat.cell = np.array(lat.cell) beta = lat.cell[3] * math.pi / 180. lat.cell = np.array( ((lat.cell[0] * 1.0, lat.cell[1] * 0.0, lat.cell[2] * math.cos(beta)), (lat.cell[0] * 0.0, lat.cell[1] * 1.0, lat.cell[2] * 0.0), (lat.cell[0] * 0.0, lat.cell[1] * 0.0, lat.cell[2] * math.sin(beta)))) lat.cell = lat.cell.transpose( ) #all the vector calculations are done in transposed manner. elif lat.celltype == "triclinic": """ Put the vectors like following: cell = "ax 0 0 bx by 0 cx cy cz" when you define a unit cell in Lattice/ """ if type(lat.cell) is str: lat.cell = np.fromstring(lat.cell, sep=" ") logger.debug(lat.cell) elif type(lat.cell) is list: lat.cell = np.array(lat.cell) lat.cell = np.reshape(lat.cell, (3, 3)) #assert lat.cell[0,1] == 0 and lat.cell[0,2] == 0 and lat.cell[1,2] == 0 else: logger.error("unknown cell type: {0}".format(lat.celltype)) sys.exit(1) #express molecular positions in the coordinate relative to the cell if lat.coord == "absolute": lat.waters = np.dot( lat.waters, np.linalg.inv(lat.cell), ) lat.waters = np.array(lat.waters) random.seed(seed) np.random.seed(seed) #Prearranged network topology information (if available) pairs = None bondlen = None try: if type(lat.pairs) is str: lines = lat.pairs.split("\n") pairs = set() for line in lines: columns = line.split() if len(columns) == 2: i, j = [int(x) for x in columns] pairs.add(frozenset([i, j])) elif type(lat.pairs) is list: pairs = set() for pair in pairs: pairs.add(frozenset(pair)) except AttributeError: logger.info("Graph is not defined.") #Bond length threshold try: bondlen = lat.bondlen except AttributeError: logger.info("Bond length is not defined.") #set density if density < 0: density = lat.density #scale the cell according to the (specified) density mass = 18 #water NB = 6.022e23 nmol = lat.waters.shape[0] #nmol in a unit cell volume = np.linalg.det(lat.cell) #volume of a unit cell in nm**3 d = mass * nmol / (NB * volume * 1e-21) ratio = (d / density)**(1.0 / 3.0) lat.cell *= ratio if bondlen is not None: bondlen *= ratio if True: logger.info("Start placing the bonds.") if pairs is None: logger.info(" Pairs are not given explicitly.") logger.info( " Start estimating the bonds according to the pair distances." ) #make bonded pairs according to the pair distance. #make before replicating them. grid = pl.determine_grid(lat.cell, bondlen) pairs = pl.pairlist_fine(lat.waters, bondlen, lat.cell, grid, distance=False) if logger.level <= logging.DEBUG: pairs2 = pl.pairlist_crude(lat.waters, bondlen, lat.cell, distance=False) logger.debug("pairs: {0}".format(len(pairs))) logger.debug("pairs2: {0}".format(len(pairs2))) for pair in pairs: i, j = pair assert (i, j) in pairs2 or (j, i) in pairs2 for pair in pairs2: i, j = pair assert (i, j) in pairs or (j, i) in pairs logger.info(" End estimating the bonds.") shuffled_pairs = [] for pair in pairs: i, j = pair if random.randint(0, 1) == 0: i, j = j, i shuffled_pairs.append((i, j)) graph = dg.IceGraph() graph.register_pairs(shuffled_pairs) logger.info("End placing the bonds.") #replicate water molecules to make a repeated cell reppositions = replicate(lat.waters, rep) #scale the cell for d in range(3): lat.cell[:, d] *= rep[d] result = { "positions": reppositions, "cell": lat.cell, "celltype": lat.celltype, "bondlen": bondlen } if stage == 0: return result #return reppositions, None, None, lat.cell, lat.celltype, bondlen #replicate the graph #This also shuffles the bond directions graph = replicate_graph(graph, lat.waters, rep) result["graph"] = graph if stage == 1: return result #Test undir = graph.to_undirected() for node in range(undir.number_of_nodes()): if node not in undir: logger.debug("z=0 at {0}".format(node)) else: z = len(undir.neighbors(node)) if z != 4: logger.debug("z={0} at {1}".format(z, node)) if graph.number_of_edges() != len(reppositions) * 2: logger.info( "Inconsistent number of HBs {0} for number of molecules {1}.". format(graph.number_of_edges(), len(reppositions))) return result #make them obey the ice rule logger.info("Start making the bonds obey the ice rules.") graph.purge_ice_defects() logger.info("End making the bonds obey the ice rules.") if stage == 2: result["graph"] = graph return result #Rearrange HBs to purge the total dipole moment. logger.info("Start depolarization.") double_net_test = True try: if lat.double_network: double_net_test = (rep[0] % 2 == 0) and (rep[1] % 2 == 0) and (rep[2] % 2 == 0) except: pass #just ignore. if not double_net_test: logger.error( "In making the ice structure having the double network (e.g. ices 6 and 7), all the repetition numbers (--rep) must be even." ) sys.exit(1) spacegraph = dg.SpaceIceGraph(graph, coord=reppositions) draw = dg.YaplotDraw(reppositions, lat.cell, data=spacegraph) yapresult = dg.depolarize(spacegraph, lat.cell, draw=draw) logger.info("End depolarization.") #determine the orientations of the water molecules based on edge directions. rotmatrices = orientations(reppositions, spacegraph, lat.cell) result["rotmatrices"] = rotmatrices result["graph"] = spacegraph result["yaplot"] = yapresult if stage == 3: return result