Exemplo n.º 1
0
    def afm_structures(self, structure_key, ferro_structure):
        # sets magnetism on a structures key and assigns to self.magnetized_structures_dict
        if set(ferro_structure.site_properties["magmom"]) == set([0]):
            print("%s is not magnetic; ferromagnetic structure to be run" %
                  str(ferro_structure.formula))
            self.magnetized_structures_dict[structure_key][
                'FM'] = ferro_structure
            self.unique_magnetizations[structure_key][
                'FM'] = ferro_structure.site_properties["magmom"]
        else:
            random_enumerations = self.random_antiferromagnetic(
                ferro_structure.site_properties["magmom"], [],
                self.magnetization_dict['Max_antiferro'], self.num_tries)
            afm_enum_number = 1
            written = 0
            for enumeration in random_enumerations:
                antiferro_structure = ferro_structure.copy()
                for magmom_idx in range(
                        len(antiferro_structure.site_properties["magmom"])):
                    antiferro_structure.replace(
                        magmom_idx,
                        antiferro_structure.species[magmom_idx],
                        properties={'magmom': enumeration[magmom_idx] + 0})
                # Check to make sure the structure isn't equal to any existing structures
                exists = False
                csm = CollinearMagneticStructureAnalyzer(antiferro_structure)
                for existing_key in list(
                        self.magnetized_structures_dict[structure_key]):
                    matches = csm.matches_ordering(
                        self.magnetized_structures_dict[structure_key]
                        [existing_key])
                    if matches == True:
                        exists = True
                        break
                    else:
                        pass
                # Write to the magnetism dictionary if the structure does not exist
                if exists == False:
                    afm_key = 'AFM' + str(afm_enum_number)
                    self.magnetized_structures_dict[structure_key][
                        afm_key] = antiferro_structure
                    self.unique_magnetizations[structure_key][
                        afm_key] = antiferro_structure.site_properties[
                            "magmom"]
                    afm_enum_number += 1
                    written += 1
                else:
                    pass

                # Break condition if Max_antiferro is reached
                if written == self.magnetization_dict['Max_antiferro']:
                    break
Exemplo n.º 2
0
def get_commensurate_orderings(magnetic_structures, energies):
    """Generate supercells for static calculations.

    From the ground state magnetic ordering and first excited state,
    generate supercells with magnetic orderings.

    If the gs is FM, match supercells to the 1st es.
    If the gs is AFM, FM is included by default, 1st es may not be.
    If the gs is FiM, 1st es may not be captured.

    Args:
        magnetic_structures (list): Structures.
        energies (list): Energies per atom.

    Returns:
        matched_structures (list): Commensurate supercells for static
            calculations.

    TODO:
        * Only consider orderings with |S_i| = ground state
        * Constrain noncollinear magmoms

    """

    # Sort by energies
    ordered_structures = [
        s for _, s in sorted(zip(energies, magnetic_structures), reverse=False)
    ]
    ordered_energies = sorted(energies, reverse=False)

    # Ground state and 1st excited state
    gs_struct = ordered_structures[0]
    es_struct = ordered_structures[1]

    cmsa = CollinearMagneticStructureAnalyzer(es_struct,
                                              threshold=0.0,
                                              threshold_nonmag=1.0,
                                              make_primitive=False)
    cmsa.ordering.value
    es_struct = cmsa.structure

    cmsa = CollinearMagneticStructureAnalyzer(gs_struct,
                                              threshold=0.0,
                                              threshold_nonmag=1.0,
                                              make_primitive=False)
    gs_ordering = cmsa.ordering.value
    gs_struct = cmsa.structure

    # FM gs will always be commensurate so we match to the 1st es
    if gs_ordering == "FM":
        enum_struct = es_struct
        fm_moments = np.array(gs_struct.site_properties["magmom"])
        fm_moment = np.mean(fm_moments[np.nonzero(fm_moments)])
        gs_magmoms = [fm_moment for m in es_struct.site_properties["magmom"]]
    elif gs_ordering in ["FiM", "AFM"]:
        enum_struct = gs_struct
        gs_magmoms = [abs(m) for m in gs_struct.site_properties["magmom"]]

    mse = MagneticStructureEnumerator(
        enum_struct,
        strategies=("ferromagnetic", "antiferromagnetic"),
        automatic=False,
        transformation_kwargs={
            "min_cell_size": 1,
            "max_cell_size": 2,
            "check_ordered_symmetry": False,
        },
    )

    # Enumerator bookkeeping
    input_index = mse.input_index
    ordered_structure_origins = mse.ordered_structure_origins

    matched_structures = []

    sm = StructureMatcher(primitive_cell=False,
                          attempt_supercell=True,
                          comparator=ElementComparator())

    # Get commensurate supercells
    for s in mse.ordered_structures:
        try:
            s2 = sm.get_s2_like_s1(enum_struct, s)
        except:
            s2 = None
        if s2 is not None:
            # Standardize magnetic structure
            cmsa = CollinearMagneticStructureAnalyzer(s2,
                                                      threshold=0.0,
                                                      make_primitive=False)
            s2 = cmsa.structure
            matched_structures.append(s2)

    # Find the gs ordering in the enumerated supercells
    cmsa = CollinearMagneticStructureAnalyzer(gs_struct,
                                              threshold=0.0,
                                              make_primitive=False)

    [cmsa.matches_ordering(s) for s in matched_structures].index(True)

    # Enforce all magmom magnitudes to match the gs
    for s in matched_structures:
        ms = s.site_properties["magmom"]
        magmoms = [np.sign(m1) * m2 for m1, m2 in zip(ms, gs_magmoms)]
        s.add_site_property("magmom", magmoms)

    return matched_structures, input_index, ordered_structure_origins