Beispiel #1
0
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
Beispiel #2
0
    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
Beispiel #3
0
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
Beispiel #4
0
    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
Beispiel #5
0
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