Exemple #1
0
    def _get_graphs(cutoff, ordered_structures):
        """
        Generate graph representations of magnetic structures with nearest
        neighbor bonds. Right now this only works for MinimumDistanceNN.

        Args:
            cutoff (float): Cutoff in Angstrom for nearest neighbor search.
            ordered_structures (list): Structure objects.

        Returns:
            sgraphs (list): StructureGraph objects.

        """

        # Strategy for finding neighbors
        if cutoff:
            strategy = MinimumDistanceNN(cutoff=cutoff, get_all_sites=True)
        else:
            strategy = MinimumDistanceNN()  # only NN

        # Generate structure graphs
        sgraphs = [
            StructureGraph.with_local_env_strategy(s, strategy=strategy)
            for s in ordered_structures
        ]

        return sgraphs
Exemple #2
0
    def test_get_local_order_params(self):
        nn = MinimumDistanceNN()
        ops = nn.get_local_order_parameters(self.diamond, 0)
        self.assertAlmostEqual(ops['tetrahedral'], 0.9999934389036574)

        ops = nn.get_local_order_parameters(self.nacl, 0)
        self.assertAlmostEqual(ops['octahedral'], 0.9999995266669)
Exemple #3
0
    def test_substitute(self):
        structure = Structure.from_file(os.path.join(os.path.dirname(__file__),
                                                     "..", "..", "..",
                                                     "test_files", "Li2O.cif"))
        molecule = FunctionalGroups["methyl"]

        structure_copy = copy.deepcopy(structure)
        structure_copy_graph = copy.deepcopy(structure)

        sg = StructureGraph.with_local_env_strategy(structure, MinimumDistanceNN())
        sg_copy = copy.deepcopy(sg)

        # Ensure that strings and molecules lead to equivalent substitutions
        sg.substitute_group(1, molecule, MinimumDistanceNN)
        sg_copy.substitute_group(1, "methyl", MinimumDistanceNN)
        self.assertEqual(sg, sg_copy)

        # Ensure that the underlying structure has been modified as expected
        structure_copy.substitute(1, "methyl")
        self.assertEqual(structure_copy, sg.structure)

        # Test inclusion of graph dictionary
        graph_dict = {(0, 1): {"weight": 0.5},
                      (0, 2): {"weight": 0.5},
                      (0, 3): {"weight": 0.5},
                      }

        sg_with_graph = StructureGraph.with_local_env_strategy(structure_copy_graph,
                                                               MinimumDistanceNN())
        sg_with_graph.substitute_group(1, "methyl", MinimumDistanceNN,
                                       graph_dict=graph_dict)
        edge = sg_with_graph.graph.get_edge_data(11, 13)[0]
        self.assertEqual(edge["weight"], 0.5)
Exemple #4
0
def shifted_sites_after_prismatic_disto(struct, metal_index, angle):
    mini = MinimumDistanceNN(tol=0.3)
    print("rotating around index : ", metal_index)
    neighbor_O = mini.get_nn_info(struct, metal_index)

    [X, Y, Z] = struct[metal_index].coords
    print("metal coords : ", [X, Y, Z])

    trueSites = []  # list of dict with index and shifted coordinates
    O_above = [O['site_index'] for O in neighbor_O if O['site'].z - Z > 0]
    O_below = [O['site_index'] for O in neighbor_O if O['site'].z - Z < 0]

    symOperation = find_symmop(struct,
                               angle,
                               translation=(0, 0, 0),
                               center=[X, Y, Z])
    trueSites += find_translated_sites(struct, O_above, symOperation)

    symOperation = find_symmop(struct,
                               -angle,
                               translation=(0, 0, 0),
                               center=[X, Y, Z])
    trueSites += find_translated_sites(struct, O_below, symOperation)

    return (trueSites)
Exemple #5
0
    def test_mul(self):

        square_sg_mul = self.square_sg * (2, 1, 1)

        square_sg_mul_ref_str = """Structure Graph
Structure: 
Full Formula (H2)
Reduced Formula: H2
abc   :  10.000000   5.000000  50.000000
angles:  90.000000  90.000000  90.000000
Sites (2)
  #  SP      a    b    c
---  ----  ---  ---  ---
  0  H     0      0    0
  1  H     0.5    0   -0
Graph: bonds
from    to  to_image    
----  ----  ------------
   0     0  (0, 1, 0)   
   0     0  (0, -1, 0)  
   0     1  (0, 0, 0)   
   0     1  (-1, 0, 0)  
   1     1  (0, 1, 0)   
   1     1  (0, -1, 0)  
"""
        square_sg_mul_actual_str = str(square_sg_mul)

        # only testing bonds portion,
        # the c frac_coord of the second H can vary from
        # 0 to -0 depending on machine precision
        square_sg_mul_ref_str = "\n".join(
            square_sg_mul_ref_str.splitlines()[11:])
        square_sg_mul_actual_str = "\n".join(
            square_sg_mul_actual_str.splitlines()[11:])

        self.assertEqual(square_sg_mul_actual_str, square_sg_mul_ref_str)

        # test sequential multiplication
        sq_sg_1 = self.square_sg * (2, 2, 1)
        sq_sg_1 = sq_sg_1 * (2, 2, 1)
        sq_sg_2 = self.square_sg * (4, 4, 1)
        self.assertEqual(sq_sg_1.graph.number_of_edges(),
                         sq_sg_2.graph.number_of_edges())

        mos2_sg_mul = self.mos2_sg * (3, 3, 1)
        for idx in mos2_sg_mul.structure.indices_from_symbol("Mo"):
            self.assertEqual(mos2_sg_mul.get_coordination_of_site(idx), 6)

        mos2_sg_premul = StructureGraph.with_local_env_strategy(
            self.structure * (3, 3, 1), MinimumDistanceNN())
        self.assertTrue(mos2_sg_mul == mos2_sg_premul)

        # test 3D Structure

        nio_sg = StructureGraph.with_local_env_strategy(
            self.NiO, MinimumDistanceNN())
        nio_sg = nio_sg * 3

        for n in range(len(nio_sg)):
            self.assertEqual(nio_sg.get_coordination_of_site(n), 6)
Exemple #6
0
    def test_get_local_order_params(self):

        nn = MinimumDistanceNN()
        ops = nn.get_local_order_parameters(self.diamond, 0)
        self.assertAlmostEqual(ops['tetrahedral'], 0.9999934389036574)

        ops = nn.get_local_order_parameters(self.nacl, 0)
        self.assertAlmostEqual(ops['octahedral'], 0.9999995266669)
Exemple #7
0
def get_MO_pairs(struct, metal_str="Mn"):
    print("getting {} - O pairs".format(metal_str))
    atom_pair_list = []
    mini = MinimumDistanceNN(tol=0.3)
    for center_index in struct.indices_from_symbol(metal_str):
        neighbor_O = mini.get_nn_info(struct, center_index)
        atom_pair_list += [[center_index, O['site_index']] for O in neighbor_O
                           if O['site'].species_string in ["O", "S"]]
    return (atom_pair_list)
Exemple #8
0
    def test_all_nn_classes(self):
        self.assertAlmostEqual(MinimumDistanceNN().get_cn(self.diamond, 0), 4)
        self.assertAlmostEqual(MinimumDistanceNN().get_cn(self.nacl, 0), 6)
        self.assertAlmostEqual(
            MinimumDistanceNN(tol=0.01).get_cn(self.cscl, 0), 8)
        self.assertAlmostEqual(
            MinimumDistanceNN(tol=0.1).get_cn(self.mos2, 0), 6)
        for image in MinimumDistanceNN(tol=0.1).get_nn_images(self.mos2, 0):
            self.assertTrue(image in [(0, 0, 0), (0, 1,
                                                  0), (-1, 0,
                                                       0), (0, 0,
                                                            0), (0, 1,
                                                                 0), (-1, 0,
                                                                      0)])

        self.assertAlmostEqual(
            MinimumOKeeffeNN(tol=0.01).get_cn(self.diamond, 0), 4)
        self.assertAlmostEqual(
            MinimumOKeeffeNN(tol=0.01).get_cn(self.nacl, 0), 6)
        self.assertAlmostEqual(
            MinimumOKeeffeNN(tol=0.01).get_cn(self.cscl, 0), 8)

        self.assertAlmostEqual(
            MinimumVIRENN(tol=0.01).get_cn(self.diamond, 0), 4)
        self.assertAlmostEqual(MinimumVIRENN(tol=0.01).get_cn(self.nacl, 0), 6)
        self.assertAlmostEqual(MinimumVIRENN(tol=0.01).get_cn(self.cscl, 0), 8)

        self.assertAlmostEqual(
            BrunnerNN_reciprocal(tol=0.01).get_cn(self.diamond, 0), 4)
        self.assertAlmostEqual(
            BrunnerNN_reciprocal(tol=0.01).get_cn(self.nacl, 0), 6)
        self.assertAlmostEqual(
            BrunnerNN_reciprocal(tol=0.01).get_cn(self.cscl, 0), 14)

        self.assertAlmostEqual(
            BrunnerNN_relative(tol=0.01).get_cn(self.diamond, 0), 16)
        self.assertAlmostEqual(
            BrunnerNN_relative(tol=0.01).get_cn(self.nacl, 0), 18)
        self.assertAlmostEqual(
            BrunnerNN_relative(tol=0.01).get_cn(self.cscl, 0), 8)

        self.assertAlmostEqual(
            BrunnerNN_real(tol=0.01).get_cn(self.diamond, 0), 16)
        self.assertAlmostEqual(
            BrunnerNN_real(tol=0.01).get_cn(self.nacl, 0), 18)
        self.assertAlmostEqual(
            BrunnerNN_real(tol=0.01).get_cn(self.cscl, 0), 8)

        self.assertAlmostEqual(EconNN(tol=0.01).get_cn(self.diamond, 0), 4)
        self.assertAlmostEqual(EconNN(tol=0.01).get_cn(self.nacl, 0), 6)
        self.assertAlmostEqual(EconNN(tol=0.01).get_cn(self.cscl, 0), 14)

        self.assertAlmostEqual(VoronoiNN(tol=0.5).get_cn(self.diamond, 0), 4)
        self.assertAlmostEqual(VoronoiNN(tol=0.5).get_cn(self.nacl, 0), 6)
        self.assertAlmostEqual(VoronoiNN(tol=0.5).get_cn(self.cscl, 0), 8)
Exemple #9
0
def metal_envt(struc):

    # Counts the Me environment in a structure
    # argument : pymatgen.core.structure
    # return : 2elt list of (7 element list) : the i th element is the
    # propotion of A with i A neighbors

    A = "Mg"
    B = "Mn"
    C = "Na"

    # neighborA = [0 for i in range(0, 7, 1)]
    # neighborB = [0 for i in range(0, 7, 1)]
    # A_indices = struc.indices_from_symbol(A)
    nbC = len(struc.indices_from_symbol(C))
    neighborC = np.zeros(6)
    #print("{0} {1}".format(nbC,C))

    sCopy = RemoveSpeciesTransformation(["O"]).apply_transformation(struc)
    # print(sCopy)
    mini = MinimumDistanceNN(tol=0.3)

    for i, site in enumerate(sCopy):
        # print(str(i))
        # print(site)
        siteName = site.species_string
        if siteName == C:
            neigList = mini.get_nn_info(sCopy, i)
            #print("{0} closest neighboors \n".format(len(neigList)))
            coordA = 0
            coordB = 0
            for neighbor in neigList:
                # index = neighbor['site_index']
                neighborName = neighbor['site'].species_string
                #print(" ( {0} at {1} ) ".format(neighborName,index))
                if neighborName == A:
                    coordA += 1
                if neighborName == B:
                    coordB += 1

            neighborC[coordA] += 1

    #print("neighborC list :" , neighborC)
    if nbC == 0:
        normalizedNeighborC = [0 for i in neighborC]
    else:
        normalizedNeighborC = [i / nbC for i in neighborC]
        print("coordination {0} : {1} \nnormalized by {2} : {3} \n".format(
            C, neighborC, nbC, normalizedNeighborC))

    return normalizedNeighborC
Exemple #10
0
def get_layer_indices(struct, separator_specie, refIndex=-1):

    # fonction to gather the indexes of all the atoms in layers separated by Na atoms
    # input : the layered structure, the index of one non-Na reference atom
    # returns : an ordered list of indexes of all the atoms in the layer of
    # the reference atom

    A = "Mn"
    B = "Mg"
    C = "O"

    # if no reference is given, takes the first atom of A as a reference
    if refIndex == -1:
        layerIndices = [struct.indices_from_symbol(C)[0]]
    else:
        layerIndices = [refIndex]

    mini = MinimumDistanceNN(tol=0.5)

    # algorithm : 2 buffer list (prev and new atomList) and a definitive list
    # adds all neighbor of the old buffer  atoms to a  new buffer list
    # if they are non-Na and non-already counted in the definitive List
    # Stops when the new buffer is empty (all non-Na atoms next to the layer
    # have been counted)

    prevAtomList = layerIndices
    finish = False
    while not finish:
        newAtomList = []
        for prevAtomIndex in prevAtomList:
            neigList = mini.get_nn_info(struct, prevAtomIndex)
            for neighbor in neigList:
                index = neighbor['site_index']
                name = neighbor['site'].species_string
                # print(name)
                if not (name in separator_specie +
                        [struct[prevAtomIndex].species_string]) and not (
                            index in layerIndices):
                    layerIndices.append(index)
        if len(newAtomList) > 0:
            previousAtomList = newAtomList
            layerIndices = layerIndices + newAtomList
        else:
            finish = True

    layerIndices.sort()

    return layerIndices
Exemple #11
0
    def test_all_nn_classes(self):
        self.assertAlmostEqual(MinimumDistanceNN().get_cn(self.diamond, 0), 4)
        self.assertAlmostEqual(MinimumDistanceNN().get_cn(self.nacl, 0), 6)
        self.assertAlmostEqual(
            MinimumDistanceNN(tol=0.01).get_cn(self.cscl, 0), 8)
        self.assertAlmostEqual(
            MinimumDistanceNN(tol=0.1).get_cn(self.mos2, 0), 6)
        for image in MinimumDistanceNN(tol=0.1).get_nn_images(self.mos2, 0):
            self.assertTrue(image in [[0, 0, 0], [0, 1, 0], [-1, 0, 0], \
                    [0, 0, 0], [0, 1, 0], [-1, 0, 0]])

        self.assertAlmostEqual(
            MinimumOKeeffeNN(tol=0.01).get_cn(self.diamond, 0), 4)
        self.assertAlmostEqual(
            MinimumOKeeffeNN(tol=0.01).get_cn(self.nacl, 0), 6)
        self.assertAlmostEqual(
            MinimumOKeeffeNN(tol=0.01).get_cn(self.cscl, 0), 8)

        self.assertAlmostEqual(
            MinimumVIRENN(tol=0.01).get_cn(self.diamond, 0), 4)
        self.assertAlmostEqual(MinimumVIRENN(tol=0.01).get_cn(self.nacl, 0), 6)
        self.assertAlmostEqual(MinimumVIRENN(tol=0.01).get_cn(self.cscl, 0), 8)

        self.assertAlmostEqual(BrunnerNN(tol=0.01).get_cn(self.diamond, 0), 4)
        self.assertAlmostEqual(BrunnerNN(tol=0.01).get_cn(self.nacl, 0), 6)
        self.assertAlmostEqual(BrunnerNN(tol=0.01).get_cn(self.cscl, 0), 14)

        self.assertAlmostEqual(
            BrunnerNN(mode="real", tol=0.01).get_cn(self.diamond, 0), 16)
        self.assertAlmostEqual(
            BrunnerNN(mode="real", tol=0.01).get_cn(self.nacl, 0), 18)
        self.assertAlmostEqual(
            BrunnerNN(mode="real", tol=0.01).get_cn(self.cscl, 0), 8)

        self.assertAlmostEqual(
            BrunnerNN(mode="relative", tol=0.01).get_cn(self.diamond, 0), 16)
        self.assertAlmostEqual(
            BrunnerNN(mode="relative", tol=0.01).get_cn(self.nacl, 0), 18)
        self.assertAlmostEqual(
            BrunnerNN(mode="relative", tol=0.01).get_cn(self.cscl, 0), 8)

        self.assertAlmostEqual(EconNN(tol=0.01).get_cn(self.diamond, 0), 4)
        self.assertAlmostEqual(EconNN(tol=0.01).get_cn(self.nacl, 0), 6)
        self.assertAlmostEqual(EconNN(tol=0.01).get_cn(self.cscl, 0), 14)

        self.assertAlmostEqual(VoronoiNN_modified().get_cn(self.diamond, 0), 4)
        self.assertAlmostEqual(VoronoiNN_modified().get_cn(self.nacl, 0), 6)
        self.assertAlmostEqual(VoronoiNN_modified().get_cn(self.cscl, 0), 8)
Exemple #12
0
def get_local_env_method(method):  # pylint:disable=too-many-return-statements
    """get a local environment method based on its name"""
    method = method.lower()

    if method.lower() == "crystalnn":
        # see eq. 15 and 16 in
        # https://pubs.acs.org/doi/full/10.1021/acs.inorgchem.0c02996
        # for the x_diff_weight parameter.
        # in the paper it is called δen and it is set to 3
        # we found better results by lowering this weight
        return CrystalNN(porous_adjustment=True,
                         x_diff_weight=1.5,
                         search_cutoff=4.5)
    if method.lower() == "econnn":
        return EconNN()
    if method.lower() == "brunnernn":
        return BrunnerNN_relative()
    if method.lower() == "minimumdistance":
        return MinimumDistanceNN()
    if method.lower() == "vesta":
        return VESTA_NN
    if method.lower() == "voronoinn":
        return VoronoiNN()
    if method.lower() == "atr":
        return ATR_NN
    if method.lower() == "li":
        return LI_NN

    return JmolNN()
def scene_dicts():
    structure = Structure.from_file(str(Path(__file__).parent / "mgo_defects" / "Va_O1_0" / "CONTCAR-finish"))
    graph = MinimumDistanceNN().get_bonded_structure(structure=structure)
    return SceneDicts(
        {"125_up": {"vertices": np.array([[0] * 3, [0.1] * 3, [0.2] * 3]),
                    "faces": np.array([[0, 1, 2]])}},
        structure_graph=graph)
Exemple #14
0
    def test_no_duplicate_hops(self):

        test_structure_dict = {
            "@module":
            "pymatgen.core.structure",
            "@class":
            "Structure",
            "charge":
            None,
            "lattice": {
                "matrix": [[2.990355, -5.149042, 0.0],
                           [2.990355, 5.149042, 0.0], [0.0, 0.0, 24.51998]]
            },
            "sites": [
                {
                    "species": [{
                        "element": "Ba",
                        "occu": 1
                    }],
                    "abc": [0.005572, 0.994428, 0.151095],
                    "properties": {}
                },
            ],
        }

        test_structure = Structure.from_dict(test_structure_dict)

        nn = MinimumDistanceNN(cutoff=6, get_all_sites=True)

        sg = StructureGraph.with_local_env_strategy(test_structure, nn)

        self.assertEqual(sg.graph.number_of_edges(), 3)
    def __init__(self,
                 structure,
                 migrating_specie,
                 max_path_length=10,
                 symprec=0.1,
                 vac_mode=False):
        """
        Args:
            structure: Input structure that contains all sites.
            migrating_specie (Specie-like): The specie that migrates. E.g.,
                "Li".
            max_path_length (float): Maximum length of NEB path in the unit
                of Angstrom. Defaults to None, which means you are setting the
                value to the min cutoff until finding 1D or >1D percolating paths.
            symprec (float): Symmetry precision to determine equivalence.
        """
        self.structure = structure
        self.migrating_specie = get_el_sp(migrating_specie)
        self.symprec = symprec
        self.a = SpacegroupAnalyzer(self.structure, symprec=self.symprec)
        self.symm_structure = self.a.get_symmetrized_structure()
        self.only_sites = self.get_only_sites()
        self.unique_hops = None

        # Generate the graph edges between these all the sites
        self.s_graph = StructureGraph.with_local_env_strategy(
            self.only_sites,
            MinimumDistanceNN(
                cutoff=max_path_length,
                get_all_sites=True))  # weights in this graph are the distances
        self.s_graph.set_node_attributes()
Exemple #16
0
    def test_all_nn_classes(self):
        self.assertEqual(MinimumDistanceNN(cutoff=5, get_all_sites=True).get_cn(
            self.cscl, 0), 14)
        self.assertEqual(MinimumDistanceNN().get_cn(self.diamond, 0), 4)
        self.assertEqual(MinimumDistanceNN().get_cn(self.nacl, 0), 6)
        self.assertEqual(MinimumDistanceNN().get_cn(self.lifepo4, 0), 6)
        self.assertEqual(MinimumDistanceNN(tol=0.01).get_cn(self.cscl, 0), 8)
        self.assertEqual(MinimumDistanceNN(tol=0.1).get_cn(self.mos2, 0), 6)

        for image in MinimumDistanceNN(tol=0.1).get_nn_images(self.mos2, 0):
            self.assertTrue(image in [(0, 0, 0), (0, 1, 0), (-1, 0, 0),
                                      (0, 0, 0), (0, 1, 0), (-1, 0, 0)])

        okeeffe = MinimumOKeeffeNN(tol=0.01)
        self.assertEqual(okeeffe.get_cn(self.diamond, 0), 4)
        self.assertEqual(okeeffe.get_cn(self.nacl, 0), 6)
        self.assertEqual(okeeffe.get_cn(self.cscl, 0), 8)
        self.assertEqual(okeeffe.get_cn(self.lifepo4, 0), 2)

        virenn = MinimumVIRENN(tol=0.01)
        self.assertEqual(virenn.get_cn(self.diamond, 0), 4)
        self.assertEqual(virenn.get_cn(self.nacl, 0), 6)
        self.assertEqual(virenn.get_cn(self.cscl, 0), 8)
        self.assertEqual(virenn.get_cn(self.lifepo4, 0), 2)

        brunner_recip = BrunnerNN_reciprocal(tol=0.01)
        self.assertEqual(brunner_recip.get_cn(self.diamond, 0), 4)
        self.assertEqual(brunner_recip.get_cn(self.nacl, 0), 6)
        self.assertEqual(brunner_recip.get_cn(self.cscl, 0), 14)
        self.assertEqual(brunner_recip.get_cn(self.lifepo4, 0), 6)

        brunner_rel = BrunnerNN_relative(tol=0.01)
        self.assertEqual(brunner_rel.get_cn(self.diamond, 0), 4)
        self.assertEqual(brunner_rel.get_cn(self.nacl, 0), 6)
        self.assertEqual(brunner_rel.get_cn(self.cscl, 0), 14)
        self.assertEqual(brunner_rel.get_cn(self.lifepo4, 0), 6)

        brunner_real = BrunnerNN_real(tol=0.01)
        self.assertEqual(brunner_real.get_cn(self.diamond, 0), 4)
        self.assertEqual(brunner_real.get_cn(self.nacl, 0), 6)
        self.assertEqual(brunner_real.get_cn(self.cscl, 0), 14)
        self.assertEqual(brunner_real.get_cn(self.lifepo4, 0), 30)

        econn = EconNN()
        self.assertEqual(econn.get_cn(self.diamond, 0), 4)
        self.assertEqual(econn.get_cn(self.nacl, 0), 6)
        self.assertEqual(econn.get_cn(self.cscl, 0), 14)
        self.assertEqual(econn.get_cn(self.lifepo4, 0), 6)

        voroinn = VoronoiNN(tol=0.5)
        self.assertEqual(voroinn.get_cn(self.diamond, 0), 4)
        self.assertEqual(voroinn.get_cn(self.nacl, 0), 6)
        self.assertEqual(voroinn.get_cn(self.cscl, 0), 8)
        self.assertEqual(voroinn.get_cn(self.lifepo4, 0), 6)

        crystalnn = CrystalNN()
        self.assertEqual(crystalnn.get_cn(self.diamond, 0), 4)
        self.assertEqual(crystalnn.get_cn(self.nacl, 0), 6)
        self.assertEqual(crystalnn.get_cn(self.cscl, 0), 8)
        self.assertEqual(crystalnn.get_cn(self.lifepo4, 0), 6)
Exemple #17
0
def get_metal_next_neighbor(struct, center_index):
    next_metal_neighbors = []

    # gather the indices of all metal next neighbors
    # metals around neighbor of neighbor Os
    mini = MinimumDistanceNN(tol=0.3)
    neighbor_O = mini.get_nn_info(struct, center_index)
    for O_index in [O['site_index'] for O in neighbor_O]:
        next_metal_neighbors += [
            M['site_index'] for M in mini.get_nn_info(struct, O_index)
            if (M['site'].specie.symbol not in ["Na", "Li", "O"])
        ]

    # remove the doubles and the metal center
    next_metal_neighbors = set(next_metal_neighbors)
    next_metal_neighbors.discard(center_index)

    return (next_metal_neighbors)
Exemple #18
0
    def test_draw(self):

        # draw MoS2 graph
        self.mos2_sg.draw_graph_to_file('MoS2_single.pdf',
                                        image_labels=True,
                                        hide_image_edges=False)
        mos2_sg = self.mos2_sg * (9, 9, 1)
        mos2_sg.draw_graph_to_file('MoS2.pdf', algo='neato')

        # draw MoS2 graph that's been successively multiplied
        mos2_sg_2 = self.mos2_sg * (3, 3, 1)
        mos2_sg_2 = mos2_sg_2 * (3, 3, 1)
        mos2_sg_2.draw_graph_to_file('MoS2_twice_mul.pdf',
                                     algo='neato',
                                     hide_image_edges=True)

        # draw MoS2 graph that's generated from a pre-multiplied Structure
        mos2_sg_premul = StructureGraph.with_local_env_strategy(
            self.structure * (3, 3, 1), MinimumDistanceNN())
        mos2_sg_premul.draw_graph_to_file('MoS2_premul.pdf',
                                          algo='neato',
                                          hide_image_edges=True)

        # draw graph for a square lattice
        self.square_sg.draw_graph_to_file('square_single.pdf',
                                          hide_image_edges=False)
        square_sg = self.square_sg * (5, 5, 1)
        square_sg.draw_graph_to_file('square.pdf',
                                     algo='neato',
                                     image_labels=True,
                                     node_labels=False)

        # draw graph for a body-centered square lattice
        self.bc_square_sg.draw_graph_to_file('bc_square_single.pdf',
                                             hide_image_edges=False)
        bc_square_sg = self.bc_square_sg * (9, 9, 1)
        bc_square_sg.draw_graph_to_file('bc_square.pdf',
                                        algo='neato',
                                        image_labels=False)

        # draw graph for a body-centered square lattice defined in an alternative way
        self.bc_square_sg_r.draw_graph_to_file('bc_square_r_single.pdf',
                                               hide_image_edges=False)
        bc_square_sg_r = self.bc_square_sg_r * (9, 9, 1)
        bc_square_sg_r.draw_graph_to_file('bc_square_r.pdf',
                                          algo='neato',
                                          image_labels=False)

        # delete generated test files
        test_files = ('bc_square_r_single.pdf', 'bc_square_r.pdf',
                      'bc_square_single.pdf', 'bc_square.pdf',
                      'MoS2_premul.pdf', 'MOS2_single.pdf',
                      'MoS2_twice_mul.pdf', 'MoS2.pdf', 'square_single.pdf',
                      'square.pdf')
        for test_file in test_files:
            os.remove(test_file)
    def test_all_nn_classes(self):
        self.assertAlmostEqual(MinimumDistanceNN().get_cn(self.diamond, 0), 4)
        self.assertAlmostEqual(MinimumDistanceNN().get_cn(self.nacl, 0), 6)
        self.assertAlmostEqual(
            MinimumDistanceNN(tol=0.01).get_cn(self.cscl, 0), 8)
        self.assertAlmostEqual(
            MinimumDistanceNN(tol=0.1).get_cn(self.mos2, 0), 6)
        for image in MinimumDistanceNN(tol=0.1).get_nn_images(self.mos2, 0):
            self.assertTrue(image in [[0, 0, 0], [0, 1, 0], [-1, 0, 0], \
                    [0, 0, 0], [0, 1, 0], [-1, 0, 0]])

        self.assertAlmostEqual(
            MinimumOKeeffeNN(tol=0.01).get_cn(self.diamond, 0), 4)
        self.assertAlmostEqual(
            MinimumOKeeffeNN(tol=0.01).get_cn(self.nacl, 0), 6)
        self.assertAlmostEqual(
            MinimumOKeeffeNN(tol=0.01).get_cn(self.cscl, 0), 8)

        self.assertAlmostEqual(
            MinimumVIRENN(tol=0.01).get_cn(self.diamond, 0), 4)
        self.assertAlmostEqual(MinimumVIRENN(tol=0.01).get_cn(self.nacl, 0), 6)
        self.assertAlmostEqual(MinimumVIRENN(tol=0.01).get_cn(self.cscl, 0), 8)
Exemple #20
0
    def test_no_duplicate_hops(self):

        test_structure = Structure(
            lattice=[[2.990355, -5.149042, 0.0], [2.990355, 5.149042, 0.0], [0.0, 0.0, 24.51998]],
            species=["Ba"],
            coords=[[0.005572, 0.994428, 0.151095]],
        )

        nn = MinimumDistanceNN(cutoff=6, get_all_sites=True)

        sg = StructureGraph.with_local_env_strategy(test_structure, nn)

        self.assertEqual(sg.graph.number_of_edges(), 3)
Exemple #21
0
    def test_from_local_env_and_equality_and_diff(self):
        nn = MinimumDistanceNN()
        sg = StructureGraph.with_local_env_strategy(self.structure, nn)
        
        self.assertEqual(sg.graph.number_of_edges(), 6)

        nn2 = MinimumOKeeffeNN()
        sg2 = StructureGraph.with_local_env_strategy(self.structure, nn2)

        self.assertTrue(sg == sg2)
        self.assertTrue(sg == self.mos2_sg)

        # TODO: find better test case where graphs are different
        diff = sg.diff(sg2)
        self.assertEqual(diff['dist'], 0)
Exemple #22
0
    def test_extract_molecules(self):

        structure_file = os.path.join(os.path.dirname(__file__), "..", "..", "..",
                                      'test_files/H6PbCI3N_mp-977013_symmetrized.cif')

        s = Structure.from_file(structure_file)

        nn = MinimumDistanceNN()
        sg = StructureGraph.with_local_env_strategy(s, nn)

        molecules = sg.get_subgraphs_as_molecules()
        self.assertEqual(molecules[0].composition.formula, "H3 C1")
        self.assertEqual(len(molecules), 1)

        molecules = self.mos2_sg.get_subgraphs_as_molecules()
        self.assertEqual(len(molecules), 0)
 def with_distance(cls, structure: Structure, migrating_specie: str,
                   max_distance: float, **kwargs) -> "MigrationGraph":
     """
     Using a specific nn strategy to get the connectivity graph between all the migrating ion sites.
     Args:
         max_distance: Maximum length of NEB path in the unit
             of Angstrom. Defaults to None, which means you are setting the
             value to the min cutoff until finding 1D or >1D percolating paths.
     Returns:
         A constructed MigrationGraph object
     """
     only_sites = get_only_sites_from_structure(structure, migrating_specie)
     migration_graph = StructureGraph.with_local_env_strategy(
         only_sites,
         MinimumDistanceNN(cutoff=max_distance, get_all_sites=True),
     )
     return cls(structure=structure, m_graph=migration_graph, **kwargs)
Exemple #24
0
    def __init__(
        self,
        structure,
        migrating_specie,
        max_path_length=10,
        symprec=0.1,
        vac_mode=False,
        name: str = None,
    ):
        """
        Construct the FullPathMapper object using a structure will all mobile sites occupied.
        A structure graph is generated by connecting all sites withing max_path_length distance of each other
        The sites are decorated with Migration graph objects and then grouped together based on their equivalence.

        Args:
            structure: Input structure that contains all sites.
            migrating_specie (Specie-like): The specie that migrates. E.g.,
                "Li".
            max_path_length (float): Maximum length of NEB path in the unit
                of Angstrom. Defaults to None, which means you are setting the
                value to the min cutoff until finding 1D or >1D percolating paths.
            symprec (float): Symmetry precision to determine equivalence.
        """
        self.structure = structure
        self.migrating_specie = get_el_sp(migrating_specie)
        self.max_path_length = max_path_length
        self.symprec = symprec
        self.name = name
        self.a = SpacegroupAnalyzer(self.structure, symprec=self.symprec)
        self.symm_structure = self.a.get_symmetrized_structure()
        self.only_sites = self.get_only_sites()
        if vac_mode:
            raise NotImplementedError
        self.vac_mode = vac_mode
        self.unique_hops = None

        # Generate the graph edges between these all the sites
        self.s_graph = StructureGraph.with_local_env_strategy(
            self.only_sites,
            MinimumDistanceNN(cutoff=max_path_length, get_all_sites=True),
        )  # weights in this graph are the distances
        self.s_graph.set_node_attributes()
        self.populate_edges_with_migration_paths()
        self.group_and_label_hops()
        self._populate_unique_hops_dict()
Exemple #25
0
    def test_extract_molecules(self):

        structure_file = os.path.join(
            PymatgenTest.TEST_FILES_DIR,
            "H6PbCI3N_mp-977013_symmetrized.cif",
        )

        s = Structure.from_file(structure_file)

        nn = MinimumDistanceNN()
        sg = StructureGraph.with_local_env_strategy(s, nn)

        molecules = sg.get_subgraphs_as_molecules()
        self.assertEqual(molecules[0].composition.formula, "H3 C1")
        self.assertEqual(len(molecules), 1)

        molecules = self.mos2_sg.get_subgraphs_as_molecules()
        self.assertEqual(len(molecules), 0)
    def apply_transformation(self, structure):
        """
        Apply the transformation.

        Args:
            structure: Structure or Molecule to apply the transformation to

        Returns:
            the transformed structure
        """
        structure = structure.copy()
        site = structure[self.site_index]

        def f(x, r, r0):
            return x * r0 / r

        r0 = max([
            site.distance(_["site"]) for _ in MinimumDistanceNN().get_nn_info(
                structure, self.site_index)
        ])
        if hasattr(structure, "lattice"):
            m = structure.lattice.matrix
            m = (abs(m) > 1e-5) * m
            a, b, c = m[0], m[1], m[2]
            x = abs(np.dot(a, np.cross(b, c)) / np.linalg.norm(np.cross(b, c)))
            y = abs(np.dot(b, np.cross(a, c)) / np.linalg.norm(np.cross(a, c)))
            z = abs(np.dot(c, np.cross(a, b)) / np.linalg.norm(np.cross(a, b)))
            rmax = np.floor(min([x, y, z]) / 2)
        else:
            rmax = np.max(structure.distance_matrix)

        for vals in structure.get_neighbors(site,
                                            r=r0 if self.nn_only else rmax):
            site2, distance, index = vals[:3]
            v = site2.coords - site.coords
            kwargs = {
                "indices": [index],
                "vector":
                v * f(self.displacement, distance, r0) / np.linalg.norm(v)
            }
            if hasattr(structure, "lattice"):
                kwargs["frac_coords"] = False
            structure.translate_sites(**kwargs)
        return structure
Exemple #27
0
def get_neighbors_of_site_with_index_future(struct, n, approach="min_dist", \
                                            delta=0.1, cutoff=10.0):
    """
    Returns the neighbors of a given site using a specific neighbor-finding
    method.

    Args:
        struct (Structure): input structure.
        n (int): index of site in Structure object for which motif type
                is to be determined.
        approach (str): type of neighbor-finding approach, where
              "min_dist" will use the MinimumDistanceNN class,
              "voronoi" the VoronoiNN class, "min_OKeeffe" the
              MinimumOKeeffe class, and "min_VIRE" the MinimumVIRENN class.
        delta (float): tolerance involved in neighbor finding.
        cutoff (float): (large) radius to find tentative neighbors.

    Returns: neighbor sites.
    """

    warnings.warn('This function will go into Pymatgen very soon.')

    if approach == "min_dist":
        return MinimumDistanceNN(tol=delta, cutoff=cutoff).get_nn(
            struct, n)
    elif approach == "voronoi":
        return VoronoiNN(tol=delta, cutoff=cutoff).get_nn(
            struct, n)
    elif approach == "min_OKeeffe":
        return MinimumOKeeffeNN(tol=delta, cutoff=cutoff).get_nn(
            struct, n)
    elif approach == "min_VIRE":
        return MinimumVIRENN(tol=delta, cutoff=cutoff).get_nn(
            struct, n)
    else:
        raise RuntimeError("unsupported neighbor-finding method ({}).".format(
            approach))
Exemple #28
0
    def __init__(
        self,
        structure,
        structure_graph=None,
        larsen_dim=None,
        cheon_dim=None,
        gorai_dim=None,
    ):
        """
        This class uses 3 algorithms implemented in pymatgen to automate recognition of low-dimensional materials.

        Args:
            structure (object): pmg Structure object.

            structure_graph (object): pmg StructureGraph object.

            larsen_dim (int): As defined in P. M. Larsen et al., Phys. Rev. Materials 3, 034003 (2019).

            cheon_dim (int): As defined in Cheon, G. et al., Nano Lett. 2017.

            gorai_dim (int): As defined in Gorai, P. et al., J. Mater. Chem. A 2, 4136 (2016).

        """

        self.structure = structure
        self.structure_graph = structure_graph
        self.larsen_dim = larsen_dim
        self.cheon_dim = cheon_dim
        self.gorai_dim = gorai_dim

        # Default to MinimumDistanceNN for generating structure graph.
        sgraph = MinimumDistanceNN().get_bonded_structure(structure)

        self.structure_graph = sgraph

        # Get Larsen dimensionality
        self.larsen_dim = get_dimensionality_larsen(self.structure_graph)
Exemple #29
0
def get_MMOO_quadruplets(struct):

    AB_list = get_Mn_Mn_pairs(struct)
    print("nb of pairs to test : {}".format(len(AB_list)))

    quadruplets = []

    for A, B in AB_list:
        mini = MinimumDistanceNN(tol=0.35)

        O_A_indices = [O['site_index'] for O in mini.get_nn_info(struct, A)]
        O_pair = [
            O['site_index'] for O in mini.get_nn_info(struct, B)
            if O["site_index"] in O_A_indices
        ]

        # O_pair = O_A_indices & O_B_indices

        nb_O = len(O_pair)

        if nb_O == 2:
            quadruplets.append({"metal_pair": [A, B], "oxygen_pair": O_pair})

        elif nb_O > 2:

            O_pair_dict = [
                O for O in mini.get_nn_info(struct, B)
                if O['site_index'] in O_pair
            ]

            print("common O between atoms {} are not a pair : {}".format(
                [A, B], O_pair))

            for O in O_pair_dict:

                dA, imgA = O["site"].distance_and_image(struct[B], jimage=None)

                dB, imgB = O["site"].distance_and_image(struct[A], jimage=None)
                # print(imgA,imgB)

                O["hash"] = hash((tuple(imgA), tuple(imgB)))
                #print("O site : {}, dist : {}".format(O["site_index"],dA+dB))

            O_pair = [
                O["site_index"] for O in sorted(O_pair, key=itemgetter('hash'))
            ]
            print("sorted O list : {}".format(
                [dictA["site_index"] for dictA in O_pair]))
            while len(O_pair) > 0:
                O1 = O_pair.pop()
                O2 = O_pair.pop()
                quadruplets.append({
                    "metal_pair": [A, B],
                    "oxygen_pair": [O1, O2]
                })

        else:
            print("Not enough O in the pair !!")

    print("Valid MMOO quadruplets : {}".format(len(quadruplets)))
    return (quadruplets)
Exemple #30
0
def get_NNs_pm(atoms, site_idx, NN_method):
    """
	Get coordinating atoms to the adsorption site

	Args:
		atoms (Atoms object): atoms object of MOF

		site_idx (int): ASE index of adsorption site
		
		NN_method (string): string representing the desired Pymatgen
		nearest neighbor algorithm:
		refer to http://pymatgen.org/_modules/pymatgen/analysis/local_env.html
	
	Returns:
		neighbors_idx (list of ints): ASE indices of coordinating atoms
	"""
    #Convert ASE Atoms object to Pymatgen Structure object
    bridge = pm_ase.AseAtomsAdaptor()
    struct = bridge.get_structure(atoms)

    #Select Pymatgen NN algorithm
    NN_method = NN_method.lower()
    if NN_method == 'vire':
        nn_object = MinimumVIRENN()
    elif NN_method == 'voronoi':
        nn_object = VoronoiNN()
    elif NN_method == 'jmol':
        nn_object = JmolNN()
    elif NN_method == 'min_dist':
        nn_object = MinimumDistanceNN()
    elif NN_method == 'okeeffe':
        nn_object = MinimumOKeeffeNN()
    elif NN_method == 'brunner_real':
        nn_object = BrunnerNN_real()
    elif NN_method == 'brunner_recpirocal':
        nn_object = BrunnerNN_reciprocal()
    elif NN_method == 'brunner_relative':
        nn_object = BrunnerNN_relative()
    elif NN_method == 'econ':
        nn_object = EconNN()
    elif NN_method == 'dict':
        #requires a cutoff dictionary located in the pwd
        nn_object = CutOffDictNN(cut_off_dict='cut_off_dict.txt')
    elif NN_method == 'critic2':
        nn_object = Critic2NN()
    elif NN_method == 'openbabel':
        nn_object = OpenBabelNN()
    elif NN_method == 'covalent':
        nn_object = CovalentBondNN()
    elif NN_method == 'crystal':
        nn_object = CrystalNN(porous_adjustment=True)
    elif NN_method == 'crystal_nonporous':
        nn_object = CrystalNN(porous_adjustment=False)
    else:
        raise ValueError('Invalid NN algorithm specified')

    #Find coordinating atoms
    with warnings.catch_warnings():
        warnings.simplefilter('ignore')
        neighbors = nn_object.get_nn_info(struct, site_idx)
    neighbors_idx = []
    for neighbor in neighbors:
        neighbors_idx.append(neighbor['site_index'])

    return neighbors_idx
Exemple #31
0
def metalBondCount(struc):

    # Counts the metal metal bounds in a structure
    # argument pymatgen.core.structure
    # return [ normalizedBonds, normalizedAA, normalizedBB]

    # normalizedBond = 3 elt list =[ nb AA bonds, nb BB bonds, nb  AB bonds ] / nb of metal
    # normalizedAA = 7 element list : the ith elt is the number of A with i A-neighbor
    # (ie if there are 1/4 of the Mg surrounded by 3 Mg, normalizedAA[3] = 0.25)
    # normalizedBB = idem for B

    # Logically, if nbA = nbB, normalizedAA = normalizedBB

    A = "Mg"
    B = "Mn"
    countAA = 0
    countAB = 0
    countBB = 0

    neighborAA = [0 for i in range(7)]
    neighborBB = [0 for i in range(7)]

    A_indices = struc.indices_from_symbol(A)
    B_indices = struc.indices_from_symbol(B)
    nbA = len(A_indices)
    nbB = len(B_indices)
    nbTot = nbA + nbB
    print("{0} {1}, {2} {3} : {4}".format(nbA, A, nbB, B, nbTot))

    sCopy = RemoveSpeciesTransformation(["Na",
                                         "O"]).apply_transformation(struc)

    #    struc.remove_species('O')
    mini = MinimumDistanceNN(tol=0.3)

    for i, site in enumerate(sCopy):
        # print(str(i))
        neigList = mini.get_nn_info(sCopy, i)
        #print("{0} closest neighboors \n".format(len(neigList)))
        coord = 0

        for neighbor in neigList:
            index = neighbor['site_index']
            name = neighbor['site'].species_string
            #           print(" ( {0} at {1} ) ".format(name,index))

            if site.species_string == A:
                if name == A:
                    countAA += 1
                    coord += 1
                if name == B:
                    countAB += 1
            if site.species_string == B:
                if name == A:
                    countAB += 1
                if name == B:
                    countBB += 1
                    coord += 1

        if site.species_string == A:
            neighborAA[coord] += 1
        elif site.species_string == B:
            neighborBB[coord] += 1

    bonds = [countAA // 2, countBB // 2, countAB // 2]
    normalizedBonds = [i / nbTot for i in bonds]
    print("[{3}{3}, {4}{4}, {3}{4}] = {0} normalized by {1} : {2} \n".format(
        bonds, nbTot, normalizedBonds, A, B))
    if nbA > 0:
        normalizedAA = [i / nbA for i in neighborAA]
        print(
            "[Nombre de {0} avec [1-6] {0} autour] = {1} normalized by {2} : {3} \n"
            .format(A, neighborAA, nbA, normalizedAA))
    else:
        normalizedAA = neighborAA
    if nbB > 0:
        normalizedBB = [i / nbB for i in neighborBB]
        print(
            "[Nombre de {0} avec [1-6] {0} autour] = {1} normalized by {2} : {3} \n"
            .format(B, neighborBB, nbB, normalizedBB))
    else:
        normalizedBB = neighborBB
    return [normalizedBonds, normalizedAA, normalizedBB]