def find_apsis(coord, cell, distance, vertex, axis): logger = logging.getLogger() grid = pl.determine_grid(cell, distance) logger.debug("Grid: {0}".format(grid)) #for Z case apsis = coord[vertex] + axis*0.5 #find the atoms near the apsis min_d = 1e99 min_a = -1 for i,j,d in pl.pairs_fine_hetero([apsis,], coord, distance, cell, grid, distance=True): if d < min_d: min_a = j min_d = d return min_a
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 find_apsis(coord, cell, distance, vertex, axis): logger = logging.getLogger() grid = pl.determine_grid(cell, distance) logger.debug("Grid: {0}".format(grid)) #for Z case apsis = coord[vertex] + axis * 0.5 #find the atoms near the apsis min_d = 1e99 min_a = -1 for i, j, d in pl.pairs_fine_hetero([ apsis, ], coord, distance, cell, grid, distance=True): if d < min_d: min_a = j min_d = d return min_a
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.pairs_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.pairs_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 argparser(arg): global waters, cell, celltype, coord, density, pairs # additional for analice global rotmat logger = logging.getLogger() args = arg.split(":") assert 0 < len(args) <= 3, __doc__ if len(args) == 1: O = "Ow" H = "Hw" elif len(args) == 2: O = args[1] H = None else: O = args[1] H = args[2] filename = args[0] file = open(filename) file.readline() natom = int(file.readline()) hatoms = [] waters = [] for i in range(natom): line = file.readline() # resid = int(line[0:5]) # resna = line[5:10] atomname = line[10:15].replace(' ', '') # atomid = int(line[15:20]) pos = np.array([float(x) for x in line[20:].split()[:3]]) #drop velocity if atomname == O: waters.append(pos) elif H is not None and re.fullmatch(H, atomname): hatoms.append(pos) else: logger.info("Skip {0}".format(atomname)) c = [float(x) for x in file.readline().split()] if len(c) == 3: cell = np.array([[c[0],0.,0.], [0.,c[1],0.], [0.,0.,c[2]]]) else: cell = np.array([[c[0],c[3],c[4]], [c[5],c[1],c[6]], [c[7],c[8],c[2]]]) celltype = 'triclinic' coord = 'absolute' density = len(waters) / (np.linalg.det(cell)*1e-21) * 18 / 6.022e23 if len(hatoms) > 0: celli = np.linalg.inv(cell) # relative coord rh = [np.dot(x, celli) for x in hatoms] ro = [np.dot(x, celli) for x in waters] # rotmatrices for analice rotmat = [] for i in range(len(waters)): o = waters[i] h0, h1 = hatoms[i*2:i*2+2] h0 -= o h1 -= o y = h1 - h0 y /= np.linalg.norm(y) z = h0+h1 z /= np.linalg.norm(z) x = np.cross(y,z) rotmat.append(np.vstack([x,y,z])) grid = pl.determine_grid(cell, 0.245) # remove intramolecular OHs pairs = [] for o,h in pl.pairs_fine_hetero(ro, rh, 0.245, cell, grid, distance=False): if h == o*2 or h == o*2+1: # adjust oxygen positions dh = rh[h] - ro[o] dh -= np.floor(dh + 0.5) waters[o] += np.dot(dh, cell)*1./16. else: # register a new intermolecular pair pairs.append((h//2, o)) logger.debug(" # of pairs: {0} {1}".format(len(pairs),len(waters)))
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
def argparser(arg): global waters, cell, celltype, coord, density, pairs # additional for analice global rotmat logger = logging.getLogger() args = arg.split(":") assert 0 < len(args) <= 3, __doc__ if len(args) == 1: O = "Ow" H = "Hw" elif len(args) == 2: O = args[1] H = None else: O = args[1] H = args[2] filename = args[0] file = open(filename) file.readline() natom = int(file.readline()) hatoms = [] waters = [] for i in range(natom): line = file.readline() # resid = int(line[0:5]) # resna = line[5:10] atomname = line[10:15].replace(' ', '') # atomid = int(line[15:20]) pos = np.array([float(x) for x in line[20:].split()[:3]]) #drop velocity if atomname == O: waters.append(pos) elif H is not None and re.fullmatch(H, atomname): hatoms.append(pos) else: logger.info("Skip {0}".format(atomname)) c = [float(x) for x in file.readline().split()] if len(c) == 3: cell = np.array([[c[0], 0., 0.], [0., c[1], 0.], [0., 0., c[2]]]) else: cell = np.array([[c[0], c[3], c[4]], [c[5], c[1], c[6]], [c[7], c[8], c[2]]]) celltype = 'triclinic' coord = 'absolute' density = len(waters) / (np.linalg.det(cell) * 1e-21) * 18 / 6.022e23 if len(hatoms) > 0: celli = np.linalg.inv(cell) # relative coord rh = [np.dot(x, celli) for x in hatoms] ro = [np.dot(x, celli) for x in waters] # rotmatrices for analice rotmat = [] for i in range(len(waters)): o = waters[i] h0, h1 = hatoms[i * 2:i * 2 + 2] h0 -= o h1 -= o y = h1 - h0 y /= np.linalg.norm(y) z = h0 + h1 z /= np.linalg.norm(z) x = np.cross(y, z) rotmat.append(np.vstack([x, y, z])) grid = pl.determine_grid(cell, 0.245) # remove intramolecular OHs pairs = [] for o, h in pl.pairs_fine_hetero(ro, rh, 0.245, cell, grid, distance=False): if h == o * 2 or h == o * 2 + 1: # adjust oxygen positions dh = rh[h] - ro[o] dh -= np.floor(dh + 0.5) waters[o] += np.dot(dh, cell) * 1. / 16. else: # register a new intermolecular pair pairs.append((h // 2, o)) logger.debug(" # of pairs: {0} {1}".format(len(pairs), len(waters)))