Beispiel #1
0
    def run_task(self, fw_spec):
        user_incar_settings = self["user_incar_settings"]
        interpolation_type = self.get("interpolation_type", "IDPP")
        idpp_species = fw_spec.get("idpp_species")
        user_kpoints_settings = self.get("user_kpoints_settings")
        try:
            ep0 = Structure.from_dict(fw_spec["ep0"])
            ep1 = Structure.from_dict(fw_spec["ep1"])
        except:
            ep0 = fw_spec["ep0"]
            ep1 = fw_spec["ep1"]

        # Get number of images.
        nimages = user_incar_settings.get("IMAGES", self._get_nimages(ep0, ep1))
        if interpolation_type == "IDPP":
            from pymatgen_diffusion.neb.pathfinder import IDPPSolver

            obj = IDPPSolver.from_endpoints([ep0, ep1], nimages=nimages)
            images = obj.run(species=idpp_species)
            images_dic_list = [image.as_dict() for image in images]
        elif interpolation_type == "linear":
            images = self._get_images_by_linear_interp(nimages, ep0, ep1)
            images_dic_list = [i.as_dict() for i in images]
        else:
            raise ValueError("The interpolation method must either be 'linear' or 'IDPP'!")

        write = WriteNEBFromImages(neb_label='1', user_incar_settings=user_incar_settings,
                                   user_kpoints_settings=user_kpoints_settings)
        fw_spec["neb"] = [images_dic_list]
        write.run_task(fw_spec=fw_spec)
Beispiel #2
0
    def run_task(self, fw_spec):
        user_incar_settings = self["user_incar_settings"]
        interpolation_type = self.get("interpolation_type", "IDPP")
        idpp_species = fw_spec.get("idpp_species")
        user_kpoints_settings = self.get("user_kpoints_settings")
        try:
            ep0 = Structure.from_dict(fw_spec["ep0"])
            ep1 = Structure.from_dict(fw_spec["ep1"])
        except Exception:
            ep0 = fw_spec["ep0"]
            ep1 = fw_spec["ep1"]

        # Get number of images.
        nimages = user_incar_settings.get("IMAGES",
                                          self._get_nimages(ep0, ep1))
        if interpolation_type == "IDPP":
            from pymatgen.analysis.diffusion.neb.pathfinder import IDPPSolver

            obj = IDPPSolver.from_endpoints([ep0, ep1], nimages=nimages)
            images = obj.run(species=idpp_species)
            images_dic_list = [image.as_dict() for image in images]
        elif interpolation_type == "linear":
            images = self._get_images_by_linear_interp(nimages, ep0, ep1)
            images_dic_list = [i.as_dict() for i in images]
        else:
            raise ValueError(
                "The interpolation method must either be 'linear' or 'IDPP'!")

        write = WriteNEBFromImages(
            neb_label="1",
            user_incar_settings=user_incar_settings,
            user_kpoints_settings=user_kpoints_settings,
        )
        fw_spec["neb"] = [images_dic_list]
        write.run_task(fw_spec=fw_spec)
Beispiel #3
0
    def match(self, snls, mat):
        """
        Finds a material doc that matches with the given snl
        Args:
            snl ([dict]): the snls list
            mat (dict): a materials doc
        Returns:
            generator of materials doc keys
        """

        m_strucs = [Structure.from_dict(mat["structure"])] + [
            Structure.from_dict(init_struc)
            for init_struc in mat["initial_structures"]
        ]
        snl_strucs = [StructureNL.from_dict(snl) for snl in snls]

        groups = group_structures(
            m_strucs + snl_strucs,
            ltol=self.settings.LTOL,
            stol=self.settings.STOL,
            angle_tol=self.settings.ANGLE_TOL,
        )
        matched_groups = [
            group for group in groups if any(
                isinstance(struc, Structure) for struc in group)
        ]
        snls = [
            struc for struc in group for group in matched_groups
            if isinstance(struc, StructureNL)
        ]

        self.logger.debug(f"Found {len(snls)} SNLs for {mat['material_id']}")
        return snls
    def get_training_data(self, split=False):
        """returns the data used to train the model

        Parameters
        ----------
        split : bool
            If True return the train/test split dataset used to train model. If False return list of input structure and target properties
        Returns
        -------
        data_list: List
             If split==False, list of dictionary's with keys as 'structure' 'TARGET'
            'structure' will return the structure as a dict that can be reconstructed as a pymatgen.structure
        train_in, test_in : List
            If split==True, list of pymatgen.Structure used to train/test model
        train_out, test_out : List
            If split==True, list of target values used to train/test model
        Examples
        --------
        >>> with MLRester() as mlr:
        >>>     model = mlr.get_model(['Al','Ni'],doi='1.2.5555')
        >>> data = model.get_training_data()
        >>> input = []
        >>> target = []
        >>> for data_point in data[0:3]:
        >>>     input.append(Structure.from_dict(data_point['structure']))
        >>>     target.append(data_point['Formation_Energy'])
        >>> print(f'len(test_in)  = {len(test_in)} element_type = {str(type(test_in[0]))[8:-2]}')
        >>> print(f'len(test_out) = {len(test_out)} element_type = {str(type(test_out[0]))[8:-2]}')
        len(test_in)  = 3 element_type = pymatgen.core.structure.Structure
        len(test_out) = 3 element_type = float
        """
        with urllib.request.urlopen(self.training_data_path) as url:
            data = json.loads(url.read().decode())
        train = data["training"]
        test = data["testing"]
        if split:
            test_in = []
            test_out = []
            train_in = []
            train_out = []
            for ind in range(len(train)):
                if ind < len(test):
                    data_point = test[str(ind)]
                    test_in.append(Structure.from_dict(
                        data_point['structure']))
                    test_out.append(data_point['Formation_Energy'])
                data_point = train[str(ind)]
                train_in.append(Structure.from_dict(data_point['structure']))
                train_out.append(data_point['Formation_Energy'])
            return train_in, train_out, test_in, test_out
        else:
            data_list = [
                data[k][key] for k in data.keys() for key in data[k].keys()
            ]
            return data_list
Beispiel #5
0
    def process_item(self, item):
        """
        Calculates substrate matches for all given substrates

        Args:
            item (dict): a dict with a material_id and a structure

        Returns:
            dict: a diffraction dict
        """
        material = item["material"]
        elastic_tensor = item.get("elastic_tensor", None)
        substrates = item["substrates"]

        self.logger.debug("Calculating substrates for {}".format(
            get(self.materials.key, material)))

        film = Structure.from_dict(material["structure"])

        all_matches = []

        sa = SubstrateAnalyzer()

        for s in substrates:

            substrate = Structure.from_dict(s["structure"])

            # Calculate all matches and group by substrate orientation
            matches_by_orient = groupby_itemkey(
                sa.calculate(film, substrate, elastic_tensor, lowest=True),
                "sub_miller")

            # Find the lowest area match for each substrate orientation
            lowest_matches = [
                min(g, key=itemgetter("match_area"))
                for k, g in matches_by_orient
            ]

            for match in lowest_matches:
                db_entry = {
                    "film_id": material[self.materials.key],
                    "sub_id": s[self.materials.key],
                    "orient": " ".join(map(str, match["sub_miller"])),
                    "sub_form": substrate.composition.reduced_formula,
                    "film_orient": " ".join(map(str, match["film_miller"])),
                    "area": match["match_area"],
                }
                if "elastic_energy" in match:
                    db_entry["energy"] = match["elastic_energy"]
                    db_entry["strain"] = match["strain"]

                all_matches.append(db_entry)

        return all_matches
Beispiel #6
0
    def _match_material(self, taskdoc, ltol=0.2, stol=0.3, angle_tol=5):
        """
        Returns the material_id that has the same structure as this task as
         determined by the structure matcher. Returns None if no match.

        Args:
            taskdoc (dict): a JSON-like task document
            ltol (float): StructureMatcher tuning parameter
            stol (float): StructureMatcher tuning parameter
            angle_tol (float): StructureMatcher tuning parameter

        Returns:
            (int) matching material_id or None
        """
        formula = taskdoc["formula_reduced_abc"]

        # handle the "parent structure" option, which is used to intentionally force slightly
        # different structures to contribute to the same "material", e.g. from an ordering scheme
        if "parent_structure" in taskdoc:
            t_struct = Structure.from_dict(
                taskdoc["parent_structure"]["structure"])
            q = {
                "formula_reduced_abc":
                formula,
                "parent_structure.spacegroup.number":
                taskdoc["parent_structure"]["spacegroup"]["number"]
            }
        else:
            sgnum = taskdoc["output"]["spacegroup"]["number"]
            t_struct = Structure.from_dict(taskdoc["output"]["structure"])
            q = {"formula_reduced_abc": formula, "sg_number": sgnum}

        for m in self._materials.find(q, {
                "parent_structure": 1,
                "structure": 1,
                "material_id": 1
        }):
            s_dict = m["parent_structure"][
                "structure"] if "parent_structure" in m else m["structure"]
            m_struct = Structure.from_dict(s_dict)
            sm = StructureMatcher(ltol=ltol,
                                  stol=stol,
                                  angle_tol=angle_tol,
                                  primitive_cell=True,
                                  scale=True,
                                  attempt_supercell=False,
                                  allow_subset=False,
                                  comparator=ElementComparator())

            if sm.fit(m_struct, t_struct):
                return m["material_id"]

        return None
Beispiel #7
0
def test_local_extrema_append_sites_to_supercell_info2(local_extrema,
                                                       simple_cubic):
    sites = {
        "H1":
        Site(element="H",
             wyckoff_letter="a",
             site_symmetry="mmm",
             equivalent_atoms=[0, 1, 2, 3, 4, 5, 6, 7])
    }
    actual_cubic = Structure.from_dict(simple_cubic.as_dict())
    supercell_info = SupercellInfo(actual_cubic * [2, 2, 2], "Pm-3m",
                                   [[2, 0, 0], [0, 2, 0], [0, 0, 2]], sites,
                                   [])

    actual_2 = local_extrema.append_sites_to_supercell_info(supercell_info,
                                                            indices=[2])

    interstitials = [
        Interstitial(frac_coords=[0.05, 0.0, 0.0],
                     site_symmetry="4mm",
                     info="test #2")
    ]
    expected_2 = SupercellInfo(actual_cubic * [2, 2, 2], "Pm-3m",
                               [[2, 0, 0], [0, 2, 0], [0, 0, 2]], sites,
                               interstitials)
    assert actual_2 == expected_2
Beispiel #8
0
    def write_cfgs(self, filename, cfg_pool):
        """
        Write the formatted configuration file.

        Args:
            filename (str): The filename to be written.
            cfg_pool (list): The configuration pool contains
                structure and energy/forces properties.
        """
        lines = []
        elements = []
        for dataset in cfg_pool:
            if isinstance(dataset['structure'], dict):
                structure = Structure.from_dict(dataset['structure'])
            else:
                structure = dataset['structure']
            energy = dataset['outputs']['energy']
            forces = dataset['outputs']['forces']
            virial_stress = dataset['outputs']['virial_stress']

            lines.append(
                self._line_up(structure, energy, forces, virial_stress))

            elements.extend(structure.species)

        if self.elements is None:
            self.elements = [element.name for element in sorted(set(elements))]

        with open(filename, 'w') as f:
            f.write('\n'.join(lines))

        return filename
Beispiel #9
0
    def write_cfg(self, filename, cfg_pool):
        """
        Write configurations to file
        Args:
            filename (str): filename
            cfg_pool (list): list of configurations

        Returns:

        """
        if not self.elements:
            raise ValueError("No species given.")

        lines = []
        for dataset in cfg_pool:
            if isinstance(dataset['structure'], dict):
                structure = Structure.from_dict(dataset['structure'])
            else:
                structure = dataset['structure']
            energy = dataset['outputs']['energy']
            forces = dataset['outputs']['forces']
            virial_stress = dataset['outputs']['virial_stress']
            virial_stress = [
                virial_stress[self.vasp_stress_order.index(n)]
                for n in self.mtp_stress_order
            ]
            lines.append(
                self._line_up(structure, energy, forces, virial_stress))

        with open(filename, 'w') as f:
            f.write('\n'.join(lines))

        return filename
Beispiel #10
0
 def from_dict(cls, d):
     structure = Structure.from_dict(d["structure"])
     return cls(structure, np.array(d["displacements"]), specie=d["specie"],
                temperature=d["temperature"], time_step=d["time_step"],
                step_skip=d["step_skip"], min_obs=d["min_obs"],
                smoothed=d.get("smoothed", "max"),
                avg_nsteps=d.get("avg_nsteps", 1000))
Beispiel #11
0
def feff_task_to_spectrum(doc):
    energy = doc["spectrum"][0]  # (eV)
    intensity = doc["spectrum"][3]  # (mu)
    structure: Structure = Structure.from_dict(doc["structure"])
    # Clean site properties
    for site_prop in structure.site_properties.keys():
        structure.remove_site_property(site_prop)

    absorbing_index = doc["absorbing_atom"]
    absorbing_element = structure[absorbing_index].specie
    edge = doc["edge"]
    spectrum_type = doc["spectrum_type"]

    spectrum = XAS(
        x=energy,
        y=intensity,
        structure=structure,
        absorbing_element=absorbing_element,
        absorbing_index=absorbing_index,
        edge=edge,
        spectrum_type=spectrum_type,
    )
    # Adding a attr is not a robust process
    # Figure out better solution later
    spectrum.last_updated = doc["last_updated"]
    spectrum.task_ids = [doc["xas_id"]]
    return spectrum
Beispiel #12
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)
Beispiel #13
0
def calcs_reversed_to_trajectory(calcs_reversed: List[dict]):
    """
    Converts data from calc_reversed to pymatgen Trajectory objects
    that contain structure, energy, force and stress data for each
    ionic step.

    Args:
        calcs_reversed: List of dictionaries in calcs_reversed entry
            of a task document.
    """
    trajectories = []

    for calculation in calcs_reversed:
        for step in calculation["output"]["ionic_steps"]:

            structures = []
            frame_props = defaultdict(list)  # type: dict

            structures.append(Structure.from_dict(step["structure"]))

            frame_props["e_fr_energy"].append(step["e_fr_energy"])
            frame_props["e_wo_entrp"].append(step["e_wo_entrp"])
            frame_props["e_0_energy"].append(step["e_wo_entrp"])
            frame_props["forces"].append(step["forces"])
            frame_props["stresses"].append(step["stress"])

        traj = Trajectory.from_structures(structures,
                                          frame_properties=frame_props,
                                          time_step=None).as_dict()
        trajectories.append(traj)

    return trajectories
Beispiel #14
0
    def setUp(self):
        with open(os.path.join(test_dir, 'si_structure.json'), 'r') as sth:
            si_str = Structure.from_dict(json.load(sth))

        with open(os.path.join(test_dir, 'si_bandstructure_line.json'),
                  'r') as bsh:
            si_bs_line = BandStructureSymmLine.from_dict(json.load(bsh))
        si_bs_line.structure = si_str

        with open(os.path.join(test_dir, 'si_bandstructure_uniform.json'),
                  'r') as bsh:
            si_bs_uniform = BandStructure.from_dict(json.load(bsh))
        si_bs_uniform.structure = si_str
        self.si_kpts = list(HighSymmKpath(si_str).kpath['kpoints'].values())
        self.df = pd.DataFrame({
            'bs_line': [si_bs_line],
            'bs_uniform': [si_bs_uniform]
        })

        with open(os.path.join(test_dir, 'VBr2_971787_bandstructure.json'),
                  'r') as bsh:
            vbr2_uniform = BandStructure.from_dict(json.load(bsh))

        self.vbr2kpts = [
            k.frac_coords for k in vbr2_uniform.labels_dict.values()
        ]
        self.vbr2kpts = [
            [0.0, 0.0, 0.0],  # \\Gamma
            [0.2, 0.0, 0.0],  # between \\Gamma and M
            [0.5, 0.0, 0.0],  # M
            [0.5, 0.0, 0.5]
        ]  # L

        self.df2 = pd.DataFrame({'bs_line': [vbr2_uniform]})
Beispiel #15
0
def get_eq_structure_by_metadata(metadata, db_file=None):
    '''
    Get the equilibrium structure by metadata

    Parameters
    ----------
        metadata: dict
            The metadata use for searching the database
        db_file: filepath-like
            The file path of db.json(the settings for mongodb file)
            if it is None or >>db_file<<, then using the db_file of fireworks configurations
    Returns
    -------
        eq_structure: pymatgen.Strucutre object
            the equilibrium structure
    '''
    if (db_file is None) or (db_file == '>>db_file<<'):
        db_file = loadfn(config_to_dict()["FWORKER_LOC"])["env"]["db_file"]
    vasp_db = VaspCalcDb.from_db_file(db_file, admin=True)
    static_items = list(vasp_db.db['tasks'].find({
        'metadata.tag':
        metadata['tag']
    }).sort('_id', 1))
    structure_list = [itemi['output']['structure'] for itemi in static_items]
    if structure_list:
        #not empty
        eq_structure = Structure.from_dict(structure_list[0])
        return eq_structure
Beispiel #16
0
def append_interstitial(supercell_info: SupercellInfo,
                        unitcell_structure: Union[Structure, IStructure],
                        frac_coords: List[Union[List[float], Coords]],
                        infos: List[str]) -> SupercellInfo:
    """
    inv_trans_mat must be multiplied with coords from the right as the
    trans_mat is multiplied to the unitcell lattice vector from the left.
    see __mul__ of IStructure in pymatgen.
    x_u, x_s means the frac coordinates in unitcell and supercell,
    while a, b, c are the unitcell lattice vector.
    (a_u, b_u, c_u) . (a, b, c) = (a_s, b_s, c_s) . trans_mat . (a, b, c)
    (a_u, b_u, c_u) = (a_s, b_s, c_s) . trans_mat
    so, (a_s, b_s, c_s) = (a_u, b_u, c_u) . inv_trans_ma
    """
    if supercell_info.unitcell_structure and \
            supercell_info.unitcell_structure != unitcell_structure:
        raise NotPrimitiveError

    if isinstance(frac_coords[0], float):
        frac_coords = [frac_coords]

    for fcoord, info in zip(frac_coords, infos):
        us = Structure.from_dict(unitcell_structure.as_dict())
        us.append(species=Element.H, coords=fcoord)
        symmetrizer = StructureSymmetrizer(us)
        site_symm = symmetrizer.spglib_sym_data["site_symmetry_symbols"][-1]

        inv_matrix = inv(np.array(supercell_info.transformation_matrix))
        new_coords = np.dot(fcoord, inv_matrix).tolist()

        supercell_info.interstitials.append(
            Interstitial(frac_coords=new_coords,
                         site_symmetry=site_symm,
                         info=info))
    return supercell_info
Beispiel #17
0
    def run(self):
        logger.info("MaterialsDescriptorBuilder starting...")
        self._build_indexes()

        q = {}
        if not self.update_all:
            q["descriptors.density"] = {"$exists": False}

        mats = [
            m for m in self._materials.find(q, {
                "structure": 1,
                "material_id": 1
            })
        ]

        pbar = tqdm(mats)
        for m in pbar:
            pbar.set_description("Processing materials_id: {}".format(
                m['material_id']))
            struct = Structure.from_dict(m["structure"])
            d = {"descriptors": {}}
            d["descriptors"]["dimensionality"] = get_dimensionality(struct)
            d["descriptors"]["density"] = struct.density
            d["descriptors"]["nsites"] = len(struct)
            d["descriptors"]["volume"] = struct.volume

            self._materials.update_one({"material_id": m["material_id"]},
                                       {"$set": d})
Beispiel #18
0
    def get_images_list(self, structure_docs, scheme, fixed_index,
                        fixed_specie):
        """
        Returns a list of structure objects with selective
        dynamics applied according ot the specified scheme.

        Args:
            structure_docs (list): list of structure
                dictionaries
            scheme (str): "fix_two_atom"
        Returns:
             list of structure objects
        """
        if isinstance(structure_docs, (list)) == False:
            raise TypeError("list input required for structure_docs")

        if scheme == "fix_two_atom":
            images = []
            for doc in structure_docs:
                structure = Structure.from_dict(doc)
                image = self.add_fix_two_atom_selective_dynamics(
                    structure, fixed_index, fixed_specie)
                images.append(image)
        # ToDo: add radius based selective dynamics scheme
        else:
            raise ValueError(
                "selective_dynamics_scheme does match any supported schemes, check input value"
            )
        return images
    def from_dict(cls, d):
        """

        Args:
            d (dict): Dict representation

        Returns:
            GruneisenPhononBandStructure: Phonon band structure with Grueneisen parameters.

        """

        lattice_rec = Lattice(d["lattice_rec"]["matrix"])
        eigendisplacements = np.array(
            d["eigendisplacements"]["real"]) + np.array(
                d["eigendisplacements"]["imag"]) * 1j
        structure = Structure.from_dict(
            d["structure"]) if "structure" in d else None
        return cls(
            qpoints=d["qpoints"],
            frequencies=np.array(d["bands"]),
            gruneisenparameters=np.array(d["gruneisen"]),
            lattice=lattice_rec,
            eigendisplacements=eigendisplacements,
            labels_dict=d["labels_dict"],
            structure=structure,
        )
Beispiel #20
0
    def iterate(self, nested_dict=None):
        """http://stackoverflow.com/questions/10756427/loop-through-all-nested-dictionary-values"""
        d = self if nested_dict is None else nested_dict
        if nested_dict is None:
            self.level = 0
        for key in list(d.keys()):
            value = d[key]
            if isinstance(value, _Mapping):
                if value.get("@class") == "Structure":
                    from pymatgen.core import Structure

                    yield key, Structure.from_dict(value)
                    continue
                yield (self.level, key), None
                if value.get("@class") == "Table":
                    from mpcontribs.io.core.components.tdata import Table

                    yield key, Table.from_dict(value)
                    continue
                # if Quantity is not None and value.get('@class') == 'Quantity':
                #     quantity = Quantity.from_dict(value)
                #     yield key, quantity
                #     continue
                if "display" in value and "value" in value:  # 'unit' is optional
                    yield (self.level, key), value["display"]
                    continue
                self.level += 1
                for inner_key, inner_value in self.iterate(nested_dict=value):
                    yield inner_key, inner_value
                self.level -= 1
            else:
                yield (self.level, key), value
Beispiel #21
0
    def from_dict(cls, d):
        eigenvalues = {}
        # Programmatic access to enumeration members in Enum class.
        for s, v in d["eigenvalues"].items():
            eigenvalues[Spin(int(s))] = np.array(v)

        final_structure = d["final_structure"]
        if isinstance(final_structure, dict):
            final_structure = Structure.from_dict(final_structure)

        band_edge_energies = str_key_to_spin(d["band_edge_energies"])
        participation_ratio = str_key_to_spin(d["participation_ratio"])
        orbital_character = str_key_to_spin(d["orbital_character"])

        return cls(
            final_structure=final_structure,
            site_symmetry=d["site_symmetry"],
            total_energy=d["total_energy"],
            total_magnetization=d["total_magnetization"],
            eigenvalues=eigenvalues,
            kpoint_coords=d["kpoint_coords"],
            kpoint_weights=d["kpoint_weights"],
            electrostatic_potential=d["electrostatic_potential"],
            vbm=d["vbm"],
            cbm=d["cbm"],
            volume=d["volume"],
            fermi_level=d["fermi_level"],
            is_converged=d["is_converged"],
            defect_center=d["defect_center"],
            defect_coords=d["defect_coords"],
            displacements=d["displacements"],
            neighboring_sites_after_relax=d["neighboring_sites_after_relax"],
            band_edge_energies=band_edge_energies,
            participation_ratio=participation_ratio,
            orbital_character=orbital_character)
Beispiel #22
0
    def test_analysis(self):

        # load example tasks (since workflow re-uses existing FW building
        # blocks for the actual calculations, the most important test is
        # the new analysis task)
        tasks = self.get_task_collection()
        with open(os.path.join(ref_dir, "ordering/sample_tasks.json"),
                  "r") as f:
            sample_tasks = load(f)
        wf_uuid = sample_tasks[0]["wf_meta"]["wf_uuid"]
        parent_structure = Structure.from_dict(
            sample_tasks[0]["input"]["structure"]).get_primitive_structure()
        tasks.insert_many(sample_tasks)

        toDb = MagneticOrderingsToDb(db_file=os.path.join(DB_DIR, "db.json"),
                                     wf_uuid=wf_uuid,
                                     parent_structure=parent_structure,
                                     perform_bader=False,
                                     scan=False)
        toDb.run_task({})

        mag_ordering_collection = self.get_task_database().magnetic_orderings
        from pprint import pprint
        stable_ordering = mag_ordering_collection.find_one({"stable": True})
        self.assertEqual(stable_ordering['input']['index'], 2)
        self.assertAlmostEqual(stable_ordering['magmoms']['vasp'][0], -2.738)
Beispiel #23
0
def _create_inputs(basename, structures_dir, atom_featurizer, bond_featurizer,
                   max_num_neighbors, cutoff):
    # load structure
    structure_json_basename = basename + ".json"
    structure_json_path = os.path.join(structures_dir, structure_json_basename)
    with open(structure_json_path, "r") as f:
        structure = Structure.from_dict(json.load(f))

    initial_atom_features = atom_featurizer(structure)

    # Padding neighbors might cause artificial effect, see https://github.com/txie-93/cgcnn/pull/16
    neighbors = structure.get_all_neighbors(r=cutoff)
    neighbors = [sorted(nn, key=lambda n: n.nn_distance)
                 for nn in neighbors]  # sort by distances
    bond_features, neighbor_indices = bond_featurizer(neighbors,
                                                      max_num_neighbors)

    inputs = {
        "neighbor_indices": neighbor_indices,  # (num_atoms, max_num_neighbors)
        "atom_features":
        initial_atom_features,  # (num_atoms, num_atom_features)
        "bond_features":
        bond_features,  # (num_atoms, max_num_neighbors, num_bond_features)
    }

    return inputs
Beispiel #24
0
    def write_cfgs(self, filename, cfg_pool):
        """
        Write the formatted configuration file.

        Args:
            filename (str): The filename to be written.
            cfg_pool (list): The configuration pool contains
                structure and energy/forces properties.
        """
        if not filename.endswith('.xyz'):
            raise RuntimeError('The extended xyz file should end with ".xyz"')

        lines = []
        for dataset in cfg_pool:
            if isinstance(dataset['structure'], dict):
                structure = Structure.from_dict(dataset['structure'])
            else:
                structure = dataset['structure']
            energy = dataset['outputs']['energy']
            forces = dataset['outputs']['forces']
            virial_stress = dataset['outputs']['virial_stress']

            lines.append(
                self._line_up(structure, energy, forces, virial_stress))

        with open(filename, 'w') as f:
            f.write('\n'.join(lines))

        return filename
Beispiel #25
0
def get_thermal_props(qha_result, phonon=True):
    """
    Return a dictionary of thermal properties in J/mol-atom from a QHA analysis.

    Parameters
    ----------
    qha_result : Dictionary of a QHA summary dict
    phonon : bool
        Whether to get the phonon data (True) or Debye data (False). Defaults to True.
        If the has_phonon key is False, it will fall back to Debye automatically.

    Returns
    -------
    dict
        Dictionary of thermal properties. Dictionary keys are GM, HM, SM, CPM, and T.
    """
    struct = Structure.from_dict(qha_result['structure'])
    if phonon and qha_result['has_phonon']:
        G = np.array(
            mget(qha_result, 'phonon.gibbs_free_energy'
                 )) * eV_per_atom_to_J_per_mol / struct.composition.num_atoms
        T = np.array(mget(qha_result, 'phonon.temperatures'))
    else:
        G = np.array(
            mget(qha_result, 'debye.gibbs_free_energy'
                 )) * eV_per_atom_to_J_per_mol / struct.composition.num_atoms
        T = np.array(mget(qha_result, 'debye.temperatures'))
    dT = T[1] - T[0]
    Cp = -T * np.gradient(np.gradient(G, dT), dT)
    S = -np.gradient(G, dT)
    H = G + T * S

    thermal_properties = {'GM': G, 'HM': H, 'SM': S, 'CPM': Cp, 'T': T}
    return thermal_properties
Beispiel #26
0
 def from_dict(cls, d):
     structure = Structure.from_dict(d["structure"])
     return cls(structure, np.array(d["displacements"]), specie=d["specie"],
                temperature=d["temperature"], time_step=d["time_step"],
                step_skip=d["step_skip"], min_obs=d["min_obs"],
                smoothed=d.get("smoothed", "max"),
                avg_nsteps=d.get("avg_nsteps", 1000))
    def _check_run(self, d, mode):
        if mode not in [
                "structure optimization",
                "bulk_modulus deformation 0",
                "bulk_modulus deformation 4",
                "fit equation of state",
        ]:
            raise ValueError("Invalid mode!")

        if mode not in ["fit equation of state"]:
            self.assertEqual(d["formula_pretty"], "Si")
            self.assertEqual(d["formula_anonymous"], "A")
            self.assertEqual(d["nelements"], 1)
            self.assertEqual(d["state"], "successful")

        if mode in ["structure optimization"]:
            self.assertAlmostEqual(
                d["calcs_reversed"][0]["output"]["structure"]["lattice"]["a"],
                3.866, 3)
            self.assertAlmostEqual(d["output"]["energy_per_atom"], -5.432, 3)
            self.relaxed_struct_si = d["calcs_reversed"][0]["output"][
                "structure"]

        elif mode in ["bulk_modulus deformation 0"]:
            for i, l in enumerate(["a", "b", "c"]):
                self.assertAlmostEqual(
                    d["input"]["structure"]["lattice"][l],
                    self.relaxed_struct_si["lattice"][l] *
                    (self.deformations[0][i][i]),
                    2,
                )
            stress = d["calcs_reversed"][0]["output"]["ionic_steps"][-1][
                "stress"]
            np.testing.assert_allclose(stress,
                                       np.diag([189.19, 189.19, 189.19]),
                                       atol=1e-2)

        elif mode in ["bulk_modulus deformation 4"]:
            for i, l in enumerate(["a", "b", "c"]):
                self.assertAlmostEqual(
                    d["input"]["structure"]["lattice"][l],
                    self.relaxed_struct_si["lattice"][l] *
                    (self.deformations[4][i][i]),
                    2,
                )
            stress = d["calcs_reversed"][0]["output"]["ionic_steps"][-1][
                "stress"]
            np.testing.assert_allclose(stress,
                                       np.diag([-65.56, -65.56, -65.56]),
                                       atol=1e-2)

        elif mode in ["fit equation of state"]:
            self.assertAlmostEqual(d["bulk_modulus"], 88.90, places=2)
            self.assertEqual(len(d["all_task_ids"]), 7)
            self.assertEqual(len(d["energies"]), self.ndeformations)
            self.assertEqual(len(d["volumes"]), self.ndeformations)
            s = SpacegroupAnalyzer(Structure.from_dict(
                d["structure"])).get_conventional_standard_structure()
            self.assertAlmostEqual(s.lattice.c, 5.468, places=3)
Beispiel #28
0
    def _match_material(self, doc, ltol=0.2, stol=0.3, angle_tol=5):
        """
        Returns the material_id that has the same structure as this doc as
         determined by the structure matcher. Returns None if no match.

        Args:
            doc (dict): a JSON-like document
            ltol (float): StructureMatcher tuning parameter
            stol (float): StructureMatcher tuning parameter
            angle_tol (float): StructureMatcher tuning parameter

        Returns:
            (int) matching material_id or None
        """
        formula = doc["formula_reduced_abc"]
        sgnum = doc["spacegroup"]["number"]

        for m in self._materials.find(
            {
                "formula_reduced_abc": formula,
                "sg_number": sgnum
            },
            {
                "structure": 1,
                "material_id": 1
            },
        ):

            m_struct = Structure.from_dict(m["structure"])
            t_struct = Structure.from_dict(doc["structure"])

            sm = StructureMatcher(
                ltol=ltol,
                stol=stol,
                angle_tol=angle_tol,
                primitive_cell=True,
                scale=True,
                attempt_supercell=False,
                allow_subset=False,
                comparator=ElementComparator(),
            )

            if sm.fit(m_struct, t_struct):
                return m["material_id"]

        return None
Beispiel #29
0
 def from_dict(cls, d):
     """
     As in :Class: `pymatgen.core.Structure` except
     restoring graphs using `from_dict_of_dicts`
     from NetworkX to restore graph information.
     """
     s = Structure.from_dict(d['structure'])
     return cls(s, d['graphs'])
Beispiel #30
0
 def from_dict(cls, d):
     """
     As in :Class: `pymatgen.core.Structure` except
     restoring graphs using `from_dict_of_dicts`
     from NetworkX to restore graph information.
     """
     s = Structure.from_dict(d['structure'])
     return cls(s, d['graphs'])
Beispiel #31
0
def get_static_structure_by_metadata(metadata, db_file=None):
    '''
    Get the static structure by metadata

    Parameters
    ----------
        metadata: dict
            The metadata use for searching the database
        db_file: filepath-like
            The file path of db.json(the settings for mongodb file)
            if it is None or >>db_file<<, then using the db_file of fireworks configurations
    Returns
    -------
        structure_list: list
            The list of different structures.
            The structures are sorted by volume
    '''
    if (db_file is None) or (db_file == '>>db_file<<'):
        db_file = loadfn(config_to_dict()["FWORKER_LOC"])["env"]["db_file"]
    vasp_db = VaspCalcDb.from_db_file(db_file, admin=True)
    static_items = list(
        vasp_db.collection.find(
            {'$and': [{
                'metadata.tag': metadata['tag']
            }, {
                'adopted': True
            }]}))
    #static_items = list(vasp_db.db['tasks'].find({'metadata.tag': metadata}))
    structure_list = [
        Structure.from_dict(itemi['output']['structure'])
        for itemi in static_items
    ]
    volumes = [
        itemi['output']['structure']['lattice']['volume']
        for itemi in static_items
    ]
    energies = [itemi['output']['energy_per_atom'] for itemi in static_items]
    band_gap = []

    static_settings = {}
    for itemi in static_items:
        if itemi['output']['is_gap_direct']:
            band_gap.append(itemi['output']['bandgap'])
        else:
            band_gap.append(itemi['output']['direct_gap'])
        if not static_settings:
            pot = itemi['input']['pseudo_potential']['functional'].upper()
            if pot == "":
                pot = itemi['orig_inputs']['potcar']['functional'].upper()
                if pot == 'Perdew-Zunger81'.upper(): pot = "LDA"
            static_settings['user_potcar_functional'] = pot
            static_settings['user_incar_settings'] = itemi['input']['incar']

    structure_list = sort_x_by_y(structure_list, volumes)
    band_gap = sort_x_by_y(band_gap, volumes)
    energies = sort_x_by_y(energies, volumes)
    volumes = sorted(volumes)
    return (structure_list, energies, band_gap, static_settings, volumes)
def convert_cd_to_de( cd, b_cse):
    """
    As of pymatgen v2.0, ComputedDefect objects were deprecated in favor
    of DefectEntry objects in pymatgen.analysis.defects.core
    This function takes a ComputedDefect (either as a dict or object) and
    converts it into a DefectEntry object in order to handle legacy
    PyCDT creation within the current paradigm of PyCDT.

    :param cd (dict or ComputedDefect object): ComputedDefect as an object or as a dictionary
    :params b_cse (dict or ComputedStructureEntry object): ComputedStructureEntry of bulk entry
        associated with the ComputedDefect.
    :return: de (DefectEntry): Resulting DefectEntry object
    """
    if type(cd) != dict:
        cd = cd.as_dict()
    if type(b_cse) != dict:
        b_cse = b_cse.as_dict()

    bulk_sc_structure = Structure.from_dict( b_cse["structure"])

    #modify defect_site as required for Defect object, confirming site exists in bulk structure
    site_cls = cd["site"]
    defect_site = PeriodicSite.from_dict( site_cls)
    def_nom = cd["name"].lower()
    if "sub_" in def_nom or "as_" in def_nom:
        #modify site object for substitution site of Defect object
        site_cls["species"][0]["element"] = cd["name"].split("_")[2]
        defect_site = PeriodicSite.from_dict( site_cls)

    poss_deflist = sorted(
        bulk_sc_structure.get_sites_in_sphere(defect_site.coords, 0.1, include_index=True), key=lambda x: x[1])
    if len(poss_deflist) != 1:
        raise ValueError("ComputedDefect to DefectEntry conversion failed. "
                         "Could not determine periodic site position in bulk supercell.")

    # create defect object
    if "vac_" in def_nom:
        defect_obj = Vacancy(bulk_sc_structure, defect_site, charge=cd["charge"])
    elif "as_" in def_nom or "sub_" in def_nom:
        defect_obj = Substitution(bulk_sc_structure, defect_site, charge=cd["charge"])
    elif "int_" in def_nom:
        defect_obj = Interstitial(bulk_sc_structure, defect_site, charge=cd["charge"])
    else:
        raise ValueError("Could not recognize defect type for {}".format( cd["name"]))


    # assign proper energy and parameter metadata
    uncorrected_energy = cd["entry"]["energy"] - b_cse["energy"]
    def_path = os.path.split( cd["entry"]["data"]["locpot_path"])[0]
    bulk_path = os.path.split( b_cse["data"]["locpot_path"])[0]
    p = {"defect_path": def_path,
         "bulk_path": bulk_path,
         "encut": cd["entry"]["data"]["encut"]}

    de = DefectEntry( defect_obj, uncorrected_energy, parameters = p)

    return de
Beispiel #33
0
 def from_dict(cls, d):
     structure = Structure.from_dict(d["structure"])
     return cls(structure,
                np.array(d["displacements"]),
                specie=d["specie"],
                temperature=d["temperature"],
                time_step=d["time_step"],
                step_skip=d["step_skip"],
                min_obs=d["min_obs"],
                weighted=d["weighted"])
Beispiel #34
0
 def run_task(self, fw_spec):
     user_incar_settings = self.get("user_incar_settings", {})
     user_kpoints_settings = self.get("user_kpoints_settings", {})
     neb_label = self.get("neb_label")
     assert neb_label.isdigit() and int(neb_label) >= 1
     images = fw_spec["neb"][int(neb_label) - 1]
     try:
         images = [Structure.from_dict(i) for i in images]
     except:
         images = images
     vis = MVLCINEBSet(images, user_incar_settings=user_incar_settings,
                       user_kpoints_settings=user_kpoints_settings)
     vis.write_input(".")
    def setUp(self):
        with open(os.path.join(test_dir, 'si_structure.json'),'r') as sth:
            si_str = Structure.from_dict(json.load(sth))

        with open(os.path.join(test_dir, 'si_bandstructure_line.json'),'r') as bsh:
            si_bs_line = BandStructureSymmLine.from_dict(json.load(bsh))
        si_bs_line.structure = si_str

        with open(os.path.join(test_dir, 'si_bandstructure_uniform.json'),'r') as bsh:
            si_bs_uniform = BandStructure.from_dict(json.load(bsh))
        si_bs_uniform.structure = si_str
        self.si_kpts = list(HighSymmKpath(si_str).kpath['kpoints'].values())
        self.df = pd.DataFrame({'bs_line': [si_bs_line], 'bs_uniform': [si_bs_uniform]})

        with open(os.path.join(test_dir, 'VBr2_971787_bandstructure.json'), 'r') as bsh:
            vbr2_uniform = BandStructure.from_dict(json.load(bsh))

        self.vbr2kpts = [k.frac_coords for k in vbr2_uniform.labels_dict.values()]
        self.vbr2kpts = [[0.0, 0.0, 0.0], # \\Gamma
                         [0.2, 0.0, 0.0], # between \\Gamma and M
                         [0.5, 0.0, 0.0], # M
                         [0.5, 0.0, 0.5]] # L

        self.df2 = pd.DataFrame({'bs_line': [vbr2_uniform]})
    def process_entry(self, defect_entry, perform_corrections = True):
        """
        Process a given DefectEntry with qualifiers given from initialization of class.
        Order of processing is:
            1) perform all possible defect corrections with information given
            2) consider delocalization analyses based on qualifier metrics
            given initialization of class. If delocalized, flag entry as delocalized
            3) update corrections to defect entry and flag as delocalized

        Corrections are applied based on:
            i) if free charges are more than free_chg_cutoff then will not apply charge correction,
                because it no longer is applicable
            ii) use charge correction set by preferred_cc
            iii) only use BandFilling correction if use_bandfilling is set to True
            iv) only use BandEdgeShift correction if use_bandedgeshift is set to True
        """
        for struct_key in ["bulk_sc_structure", "initial_defect_structure", "final_defect_structure"]:
            if struct_key in defect_entry.parameters.keys() and isinstance(defect_entry.parameters[struct_key], dict):
                defect_entry.parameters[struct_key] = Structure.from_dict(defect_entry.parameters[struct_key])

        if perform_corrections:
            self.perform_all_corrections(defect_entry)

        self.delocalization_analysis(defect_entry)

        # apply corrections based on delocalization analysis
        corrections = {}
        skip_charge_corrections = False
        if "num_hole_vbm" in defect_entry.parameters.keys():
            if (self.free_chg_cutoff < defect_entry.parameters["num_hole_vbm"]) or (
                self.free_chg_cutoff < defect_entry.parameters["num_elec_cbm"]):
                logger.info('Will not use charge correction because too many free charges')
                skip_charge_corrections = True

        if skip_charge_corrections:
            corrections.update({'charge_correction': 0.})
        else:
            if ('freysoldt' in self.preferred_cc.lower()) and ('freysoldt_meta' in defect_entry.parameters.keys()):
                frey_meta = defect_entry.parameters['freysoldt_meta']
                frey_corr = frey_meta["freysoldt_electrostatic"] + frey_meta["freysoldt_potential_alignment_correction"]
                corrections.update({'charge_correction': frey_corr})
            elif ('kumagai_meta' in defect_entry.parameters.keys()):
                kumagai_meta = defect_entry.parameters['kumagai_meta']
                kumagai_corr = kumagai_meta["kumagai_electrostatic"] + \
                    kumagai_meta["kumagai_potential_alignment_correction"]
                corrections.update({'charge_correction': kumagai_corr})
            else:
                logger.info('Could not use any charge correction because insufficient metadata was supplied.')

        if self.use_bandfilling:
            if "bandfilling_meta" in defect_entry.parameters.keys():
                bfc_corr = defect_entry.parameters["bandfilling_meta"]["bandfilling_correction"]
                corrections.update({'bandfilling_correction': bfc_corr})
            else:
                logger.info('Could not use band filling correction because insufficient metadata was supplied.')
        else:
            corrections.update({'bandfilling_correction': 0.})


        if self.use_bandedgeshift and ("bandshift_meta" in defect_entry.parameters.keys()):
            corrections.update({'bandedgeshifting_correction':
                                    defect_entry.parameters["bandshift_meta"]["bandedgeshifting_correction"] })

            # also want to update relevant data for phase diagram
            defect_entry.parameters.update({
                'phasediagram_meta': {
                    'vbm': defect_entry.parameters['hybrid_vbm'],
                    'gap': defect_entry.parameters['hybrid_cbm'] - defect_entry.parameters['hybrid_vbm']
                }
            })
        else:
            corrections.update({'bandedgeshifting_correction': 0.})
            if (type(defect_entry.parameters['vbm']) == float) and (type(defect_entry.parameters['cbm']) == float):
                # still want to have vbm and gap ready for phase diagram
                defect_entry.parameters.update({
                'phasediagram_meta': {
                    'vbm': defect_entry.parameters['vbm'],
                    'gap': defect_entry.parameters['cbm'] - defect_entry.parameters['vbm']
                    }
                })

        defect_entry.corrections.update(corrections)

        return defect_entry
Beispiel #37
0
    def run_task(self, fw_spec):

        label = self["label"]
        assert label in ["parent", "ep0", "ep1"] or "neb" in label, "Unknown label!"

        d_img = float(self.get("d_img", 0.7))  # Angstrom
        wf_name = fw_spec["wf_name"]
        src_dir = os.path.abspath(".")
        dest_dir = os.path.join(fw_spec["_fw_env"]["run_dest_root"], wf_name, label)
        shutil.copytree(src_dir, dest_dir)

        # Update fw_spec based on the type of calculations.
        if "neb" in label:
            # Update all relaxed images.
            subs = glob.glob("[0-2][0-9]")
            nimages = len(subs)
            concar_list = ["{:02}/CONTCAR".format(i) for i in range(nimages)[1:-1]]
            images = [Structure.from_file(contcar) for contcar in concar_list]

            # Update the two ending "images".
            images.insert(0, Structure.from_file("00/POSCAR"))
            images.append(Structure.from_file("{:02}/POSCAR".format(nimages - 1)))
            images = [s.as_dict() for s in images]
            neb = fw_spec.get("neb")
            neb.append(images)
            update_spec = {"neb": neb, "_queueadapter": {"nnodes": str(len(images) - 2),
                                                         "nodes": str(len(images) - 2)}}
            # Use neb walltime if it is in fw_spec
            if fw_spec["neb_walltime"] is not None:
                update_spec["_queueadapter"].update({"walltime": fw_spec.get("neb_walltime")})

        elif label in ["ep0", "ep1"]:
            # Update relaxed endpoint structures.
            file = glob.glob("CONTCAR*")[0]
            ep = Structure.from_file(file, False)  # One endpoint

            if fw_spec.get("incar_images"):  # "incar_images": pre-defined image number.
                update_spec = {label: ep.as_dict(),
                               "_queueadapter": {"nnodes": fw_spec["incar_images"],
                                                 "nodes": fw_spec["incar_images"]}}
            else:
                # Calculate number of images if "IMAGES" tag is not provided.
                index = int(label[-1])
                ep_1_dict = fw_spec.get("ep{}".format(1 - index))  # Another endpoint
                try:
                    ep_1 = Structure.from_dict(ep_1_dict)
                except:
                    ep_1 = ep_1_dict

                max_dist = max(get_endpoint_dist(ep, ep_1))
                nimages = round(max_dist / d_img) or 1
                update_spec = {label: ep, "_queueadapter": {"nnodes": int(nimages),
                                                            "nodes": int(nimages)}}
            # Use neb walltime if it is in fw_spec
            if fw_spec["neb_walltime"] is not None:
                update_spec["_queueadapter"].update({"walltime": fw_spec.get("neb_walltime")})

        else:  # label == "parent"
            f = glob.glob("CONTCAR*")[0]
            s = Structure.from_file(f, False)
            ep0, ep1 = get_endpoints_from_index(s, fw_spec["site_indices"])

            update_spec = {"parent": s.as_dict(), "ep0": ep0.as_dict(), "ep1": ep1.as_dict()}

        # Clear current directory.
        for d in os.listdir(src_dir):
            try:
                os.remove(os.path.join(src_dir, d))
            except:
                shutil.rmtree(os.path.join(src_dir, d))

        return FWAction(update_spec=update_spec)
Beispiel #38
0
 def from_dict(cls, d):
     structure = Structure.from_dict(d["structure"])
     return cls(structure, np.array(d["displacements"]), specie=d["specie"],
                temperature=d["temperature"], time_step=d["time_step"],
                step_skip=d["step_skip"], min_obs=d["min_obs"],
                weighted=d["weighted"])