def replicate_graph(graph, positions, rep): repgraph = dg.IceGraph() nmol = positions.shape[0] for i, j in graph.edges(data=False): # positions in the unreplicated cell vec = positions[j] - positions[i] delta = np.floor(vec + 0.5).astype(int) for x in range(rep[0]): for y in range(rep[1]): for z in range(rep[2]): xi = (x + delta[0] + rep[0]) % rep[0] yi = (y + delta[1] + rep[1]) % rep[1] zi = (z + delta[2] + rep[2]) % rep[2] newi = i + nmol * (xi + rep[0] * (yi + rep[1] * zi)) newj = j + nmol * (x + rep[0] * (y + rep[1] * z)) if graph[i][j]['fixed']: # fixed pair repgraph.add_edge(newi, newj, fixed=True) else: # shuffle the bond directions if 0 == random.randint(0, 1): repgraph.add_edge(newi, newj, fixed=False) else: repgraph.add_edge(newj, newi, fixed=False) # replicate "ignores" == dopants list in the graph repgraph.ignores = replicate_labels(graph.ignores, nmol, rep) return repgraph
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 replicate_graph(graph, positions, rep): repgraph = dg.IceGraph() nmol = positions.shape[0] for i, j, k in graph.edges_iter(data=True): vec = positions[j] - positions[i] #positions in the unreplicated cell delta = np.floor(vec + 0.5).astype(int) for x in range(rep[0]): for y in range(rep[1]): for z in range(rep[2]): xi = (x + delta[0] + rep[0]) % rep[0] yi = (y + delta[1] + rep[1]) % rep[1] zi = (z + delta[2] + rep[2]) % rep[2] newi = i + nmol * (xi + rep[0] * (yi + rep[1] * zi)) newj = j + nmol * (x + rep[0] * (y + rep[1] * z)) if 0 == random.randint(0, 1): #shuffle the bond directions repgraph.add_edge(newi, newj) else: repgraph.add_edge(newj, newi) return repgraph
def prepare_random_graph(self, fixed): if self.pairs is None: self.logger.info(" Pairs are not given explicitly.") self.logger.info( " Estimating the bonds according to the pair distances.") self.logger.debug("Bondlen: {0}".format(self.bondlen)) # 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 = pl.pairs_fine(self.waters, self.bondlen, self.cell.mat, grid, distance=False) # self.pairs = [v for v in zip(j0,j1)] # Check using a simpler algorithm. # Do not use it for normal debug because it is too slow if False: # self.logger.level <= logging.DEBUG: pairs1 = self.pairs pairs2 = [ v for v in pl.pairs_crude(self.waters, self.bondlen, self.cell.mat, distance=False) ] self.logger.debug("pairs1: {0}".format(len(pairs1))) self.logger.debug("pairs2: {0}".format(len(pairs2))) for pair in pairs1: i, j = pair assert (i, j) in pairs2 or (j, i) in pairs2 for pair in pairs2: i, j = pair assert (i, j) in pairs1 or (j, i) in pairs1 graph = dg.IceGraph() if fixed is not None: 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) self.logger.info(" Number of water nodes: {0}".format( graph.number_of_nodes())) return graph
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