示例#1
0
def prepare_entry(structure_type, tot_e, species):
    """
    Prepare entries from total energy and species.

    Args:
        structure_type(str): "garnet" or "perovskite"
        tot_e (float): total energy in eV/f.u.
        species (dict): species in dictionary.

    Returns:
        ce (ComputedEntry)
    """

    formula = spe2form(structure_type, species)
    composition = Composition(formula)
    elements = [el.name for el in composition]

    potcars = ["pbe %s" % CONFIG['POTCAR'][el] for el in elements]

    parameters = {"potcar_symbols": list(potcars), "oxide_type": 'oxide'}

    for el in elements:
        if el in LDAUU:
            parameters.update({"hubbards": {el: LDAUU[el]}})

    ce = ComputedEntry(composition=composition,
                       energy=0,
                       parameters=parameters)
    ce.uncorrected_energy = tot_e
    compat = MaterialsProjectCompatibility()
    ce = compat.process_entry(ce)  # Correction added

    return ce
示例#2
0
def filter_entries(structure_type, all_entries, species, return_removed=False):
    """
    Filter out the entry with exact same structure as queried entry among the
    entries in queried chemical space obtained from Materials Project.

    Used Pymatgen.analysis.structure_matcher.fit_anonymous to match the prototype
    of give structures.

    Args:
        structure_type(str): "garnet" or "perovskite"
         all_entries (list): entries in queried chemical space obtained from Materials Project
         composition (Composition): composition of queried entry
         return_removed (bool): If True, return the filtered entries

    Returns:
        filtered_entries (list)
    """
    global MATCHER, PROTO
    if not MATCHER:
        MATCHER = StructureMatcher(ltol=0.2,
                                   stol=0.3,
                                   angle_tol=5,
                                   primitive_cell=True,
                                   comparator=ElementComparator())

    if not PROTO:
        garnet_proto_path = os.path.join(DATA_DIR, "garnet/proto_mp-3050.cif")
        perov_proto_path = os.path.join(DATA_DIR,
                                        "perovskite/proto_mp-4019.cif")
        PROTO = {
            "garnet":
            Structure.from_file(garnet_proto_path).get_primitive_structure(),
            "perovskite":
            Structure.from_file(perov_proto_path).get_primitive_structure()
        }
        a_sites = [60, 61, 62, 63, 64, 65, 66, 67]
        for site_ind in a_sites:
            PROTO['garnet'].replace(site_ind, {"Ga": 1})

    P = PROTO[structure_type].copy()
    if structure_type == 'garnet:':
        P.replace_species({
            "Y": species['c'],
            "Ga": species['a'],
            "Al": species['d']
        })
    elif structure_type == 'perovskite':
        P.replace_species({"Ca": species['a'], "Ti": species['b']})
    composition = Composition(spe2form(structure_type, species))
    if not return_removed:
        return [e for e in all_entries \
                if e.name != composition.reduced_formula \
                and not MATCHER.fit(e.structure, P)]
    else:
        removed = [e for e in all_entries \
                   if e.name == composition.reduced_formula \
                   and MATCHER.fit(e.structure, P)]
        return removed, [e for e in all_entries if e not in removed]
示例#3
0
def get_ehull(structure_type,
              tot_e,
              species,
              unmix_entries=None,
              all_entries=None,
              debug=False,
              from_mp=False):
    """
    Get Ehull predicted under given total energy and species. The composition
    can be either given by the species dict(for garnet only) or a formula.

    Args:
        structure_type(str): "garnet" or "perovskite"
        tot_e (float): total energy, the unit is in accordance with given
            composition.
        species (dict): species in dictionary.
        unmix_entries (list): additional list of unmix entries.
        all_entries(list): Manually supply the entries whithin the chemical space
        debug(bool): Whether or not to run it in debug mode. (For test only)
        from_mp(bool): Whether or not to query entries from MP (would take long)

    Returns:
        ehull (float): energy above hull.
    """

    formula = spe2form(structure_type, species)
    composition = Composition(formula)
    elements = [i.name for i in composition.elements]
    unmix_entries = [] if unmix_entries is None else unmix_entries
    if not all_entries:
        if from_mp:
            all_entries = m.get_entries_in_chemsys(
                [el.name for el in composition], inc_structure=True)
        else:
            entries_dict = EHULL_ENTRIES[structure_type]
            all_entries = get_entries_in_chemsy(entries_dict, elements)

    all_entries = filter_entries(structure_type, all_entries, species)

    # For unmix: no need to find calc entries, for mix,
    # calc entries were provided through unmix_entries
    # calc_entries_dict = CALC_ENTRIES[structure_type]
    # all_calc_entries = get_entries_in_chemsy(calc_entries_dict, elements)
    # compat = MaterialsProjectCompatibility()
    # all_calc_entries = compat.process_entries(all_calc_entries)
    # if all_calc_entries:
    #     all_entries = all_entries + all_calc_entries

    if not all_entries:
        raise ValueError("Incomplete")
    entry = prepare_entry(structure_type, tot_e, species)
    if debug:
        return entry, all_entries

    phase_diagram = PhaseDiagram(all_entries + [entry] + unmix_entries)

    return phase_diagram.get_decomp_and_e_above_hull(entry)
示例#4
0
def get_decomposed_entries(structure_type, species, oxides_table_path):
    """
    Get decomposed entries for mix types
    Args:one
        species (dict): species in dictionary.
        structure_type(str): garnet or perovskite

    Returns:
        decompose entries(list):
            list of entries prepared from unmix
            garnets/perovskite decomposed from input mix
            garnet/perovskite
    """
    def decomposed(specie_complex):
        """Decompose those have sub-dict to individual dict objects."""
        for site, specie in specie_complex.items():
            spe_copy = specie_complex.copy()
            if len(specie) > 1:
                for spe, amt in specie.items():
                    spe_copy[site] = {spe: 1}
                    yield spe_copy

    decompose_entries = []
    model, scaler, graph = load_model_and_scaler(structure_type, "unmix")
    std_formula = STD_FORMULA[structure_type]
    for unmix_species in decomposed(species):
        charge = sum([
            spe.oxi_state * amt * SITE_INFO[structure_type][site]["num_atoms"]
            for site in SITE_INFO[structure_type].keys()
            for spe, amt in unmix_species[site].items()
        ])
        if not abs(charge - 2 * std_formula['O']) < 0.1:
            continue

        formula = spe2form(structure_type, unmix_species)
        calc_entries = [entry for entry in CALC_ENTRIES[structure_type] if \
                        entry.name == Composition(formula).reduced_formula]
        if calc_entries:
            for entry in calc_entries:
                decompose_entries.append(entry)

        else:
            descriptors = get_descriptor(structure_type, unmix_species)
            with graph.as_default():
                form_e = get_form_e(descriptors, model, scaler)
            # tot_e = get_tote(form_e * std_formula.num_atoms, unmix_species)
            tot_e = get_tote(structure_type, form_e * std_formula.num_atoms,
                             unmix_species, oxides_table_path)
            entry = prepare_entry(structure_type, tot_e, unmix_species)
            compat = MaterialsProjectCompatibility()
            entry = compat.process_entry(entry)
            decompose_entries.append(entry)

    return decompose_entries
示例#5
0
def get_ehull(structure_type,
              tot_e,
              species,
              unmix_entries=None,
              all_entries=None,
              debug=False):
    """
    Get Ehull predicted under given total energy and species. The composition
    can be either given by the species dict(for garnet only) or a formula.

    Args:
        tot_e (float): total energy, the unit is in accordance with given
            composition.
        species (dict): species in dictionary.
        unmix_entries (list): additional list of unmix entries.

    Returns:
        ehull (float): energy above hull.
    """
    formula = spe2form(structure_type, species)
    composition = Composition(formula)
    unmix_entries = [] if unmix_entries is None else unmix_entries

    if not all_entries:
        all_entries = m.get_entries_in_chemsys([el.name for el in composition],
                                               inc_structure=True)
    all_entries = filter_entries(structure_type, all_entries, species)

    all_calc_entries = [e for e in CALC_ENTRIES[structure_type]
                        if set(e.composition).issubset(set(composition)) \
                        and e.name != composition.reduced_formula]

    if all_calc_entries:
        all_entries = all_entries + all_calc_entries

    compat = MaterialsProjectCompatibility()
    all_entries = compat.process_entries(all_entries)

    if not all_entries:
        raise ValueError("Incomplete")
    entry = prepare_entry(structure_type, tot_e, species)

    if debug:
        return entry, all_entries

    phase_diagram = PhaseDiagram(all_entries + [entry] + unmix_entries)

    return phase_diagram.get_decomp_and_e_above_hull(entry)
示例#6
0
def get_decomposed_entries(structure_type, species):
    """
    Get decomposed entries for mix types
    Args:
        structure_type(str): "garnet" or "perovskite"
        species (dict): species in dictionary.
        structure_type(str): garnet or perovskite

    Returns:
        decompose entries(list):
            list of entries prepared from unmix
            garnets/perovskite decomposed from input mix
            garnet/perovskite
    """
    def decomposed(specie_complex):
        """Decompose those have sub-dict to individual dict objects."""
        for site, specie in specie_complex.items():
            spe_copy = specie_complex.copy()
            if len(specie) > 1:
                for spe, amt in specie.items():
                    spe_copy[site] = {spe: 1}
                    yield spe_copy

    decompose_entries = []
    model, scaler = load_model_and_scaler(structure_type, "unmix")
    std_formula = STD_FORMULA[structure_type]
    for unmix_species in decomposed(species):
        charge = sum([
            spe.oxi_state * amt * SITE_INFO[structure_type][site]["num_atoms"]
            for site in SITE_INFO[structure_type].keys()
            for spe, amt in unmix_species[site].items()
        ])
        if not abs(charge - 2 * std_formula['O']) < 0.1:
            continue

        formula = spe2form(structure_type, unmix_species)
        composition = Composition(formula)
        elements = [el.name for el in composition]
        chemsy = '-'.join(sorted(elements))
        calc_entries = []
        if CALC_ENTRIES[structure_type].get(chemsy):
            calc_entries = [entry for entry in CALC_ENTRIES[structure_type][chemsy] if \
                            entry.name == Composition(formula).reduced_formula]
        else:
            pass
        if calc_entries:
            decompose_entries.extend(calc_entries)

        else:
            cn_specific = True if structure_type == 'garnet' else False
            descriptors = get_descriptor(structure_type,
                                         unmix_species,
                                         cn_specific=cn_specific)
            form_e = get_form_e(descriptors, model, scaler)
            # tot_e = get_tote(form_e * std_formula.num_atoms, unmix_species)
            tot_e = get_tote(structure_type, form_e * std_formula.num_atoms,
                             unmix_species)
            entry = prepare_entry(structure_type, tot_e, unmix_species)
            compat = MaterialsProjectCompatibility()
            entry = compat.process_entry(entry)
            decompose_entries.append(entry)

    return decompose_entries
示例#7
0
文件: app.py 项目: lq131/garnetdnn
def query():
    try:
        structure_type = 'garnet'
        c_string = request.args.get("c_string")
        a_string = request.args.get("a_string")
        d_string = request.args.get("d_string")
        formula = ""

        c_composition = parse_composition(structure_type, c_string, "C")
        a_composition = parse_composition(structure_type, a_string, "A")
        d_composition = parse_composition(structure_type, d_string, "D")

        charge = -2.0 * 12

        for k in c_composition.keys():
            charge += 3 * k.oxi_state * c_composition.get_atomic_fraction(k)
        for k in a_composition.keys():
            charge += 2 * k.oxi_state * a_composition.get_atomic_fraction(k)
        for k in d_composition.keys():
            charge += 3 * k.oxi_state * d_composition.get_atomic_fraction(k)

        if len(c_composition) > 1:
            mix_site = "c"
        elif len(a_composition) > 1:
            mix_site = "a"
        elif len(d_composition) > 1:
            mix_site = "d"
        else:
            mix_site = None

        species = {"a": a_composition, "d": d_composition, "c": c_composition}

        if abs(charge) < 0.1:
            formula = spe2form(structure_type, species)
            if ResponseCache.get(formula):
                response = ResponseCache[formula]
                form_e = response['form_e']
                decomp = response['decomp']
                ehull = response['ehull']
            else:  # Cache miss
                with tf.Session() as sess:
                    model, scaler, graph = load_model_and_scaler(structure_type, mix_site) if mix_site \
                        else load_model_and_scaler(structure_type, "unmix")
                    inputs = get_descriptor(structure_type, species)
                    with graph.as_default():
                        form_e = get_form_e(inputs, model, scaler) * 20
                    tot_e = get_tote(structure_type, form_e, species)
                    if mix_site:
                        decompose_entries = get_decomposed_entries(
                            structure_type, species)
                        decomp, ehull = get_ehull(
                            structure_type,
                            tot_e,
                            species,
                            unmix_entries=decompose_entries)
                    else:
                        decomp, ehull = get_ehull(structure_type, tot_e,
                                                  species)
                response = {"form_e": form_e, "decomp": decomp, "ehull": ehull}
                if len(ResponseCache) > MAX_CACHE:
                    ResponseCache.popitem(last=False)
                ResponseCache.update({formula: response})

            message = [
                "<i>E<sub>f</sub></i> = %.3f eV/fu" % form_e,
                "<i>E<sub>hull</sub></i> = %.0f meV/atom" % (ehull * 1000)
            ]

            if ehull > 0:
                reaction = []
                for k, v in decomp.items():
                    comp = k.composition
                    comp, f = comp.get_reduced_composition_and_factor()
                    reaction.append(
                        '%.3f <a href="https://www.materialsproject.org/materials/%s">%s</a>'
                        % (v * f / comp.num_atoms * 20, k.entry_id,
                           html_formula(comp.reduced_formula)))
                message.append("Decomposition: " + " + ".join(reaction))

            message = "<br>".join(message)

        else:
            message = "Not charge neutral! Total charge = %.0f" % charge
    except Exception as ex:
        message = str(ex)
    return make_response(
        render_template('index.html',
                        c_string=c_string,
                        a_string=a_string,
                        d_string=d_string,
                        formula=html_formula(formula),
                        message=message))
示例#8
0
文件: app.py 项目: lq131/garnetdnn
def perovskite_query():
    try:
        structure_type = 'perovskite'
        a_string = request.args.get("a_string")
        b_string = request.args.get("b_string")
        formula = ""
        a_composition = parse_composition(structure_type, a_string, "A")
        b_composition = parse_composition(structure_type, b_string, "B")
        charge = -2.0 * 6

        for k in a_composition.keys():
            charge += 2 * k.oxi_state * a_composition.get_atomic_fraction(k)
        for k in b_composition.keys():
            charge += 2 * k.oxi_state * b_composition.get_atomic_fraction(k)

        if len(a_composition) > 1:
            mix_site = "a"
        elif len(b_composition) > 1:
            mix_site = "b"
        else:
            mix_site = None

        species = {"a": a_composition, "b": b_composition}

        if abs(charge) < 0.1:
            formula = spe2form(structure_type, species)
            if ResponseCache.get(formula):
                response = ResponseCache[formula]
                form_e = response['form_e']
                decomp = response['decomp']
                ehull = response['ehull']

            else:  # Cache miss
                with tf.Session() as sess:
                    model, scaler, graph = load_model_and_scaler(structure_type, mix_site) if mix_site \
                        else load_model_and_scaler(structure_type, "unmix")
                    inputs = get_descriptor(structure_type,
                                            species,
                                            cn_specific=False)
                    with graph.as_default():
                        form_e = get_form_e(inputs, model, scaler) * 10
                    # form_e predicted from model is always in /atom
                    # the get_tote func always returns the tote with in /standard fu
                    # which is A2B2O6, 10 atoms
                    tot_e = get_tote(structure_type, form_e, species)
                    if mix_site:
                        decompose_entries = get_decomposed_entries(
                            structure_type, species)
                        decomp, ehull = get_ehull(
                            structure_type,
                            tot_e,
                            species,
                            unmix_entries=decompose_entries)
                    else:
                        decomp, ehull = get_ehull(structure_type, tot_e,
                                                  species)

                    response = {
                        "form_e": form_e,
                        "decomp": decomp,
                        "ehull": ehull
                    }
                    if len(ResponseCache) > MAX_CACHE:
                        ResponseCache.popitem(last=False)
                    ResponseCache.update({formula: response})

            message = [
                "<i>E<sub>f</sub></i> = %.3f eV/fu" % (form_e),
                "<i>E<sub>hull</sub></i> = %.0f meV/atom" % (ehull * 1000)
            ]
            if ehull > 0:
                reaction = []
                for k, v in decomp.items():
                    comp = k.composition
                    rcomp, f = comp.get_reduced_composition_and_factor()
                    reaction.append(
                        '%.3f <a href="https://www.materialsproject.org/materials/%s">%s</a>'
                        % (v * f / comp.num_atoms * 10, k.entry_id,
                           html_formula(comp.reduced_formula)))
                message.append("Decomposition: " + " + ".join(reaction))

            message = "<br>".join(message)
        else:
            message = "Not charge neutral! Total charge = %.0f" % charge
    except Exception as ex:
        message = str(ex)

    return make_response(
        render_template('index_perov.html',
                        a_string=a_string,
                        b_string=b_string,
                        formula=html_formula(formula),
                        message=message))
示例#9
0
def query(nclicks, c_string, a_string, d_string):
    if nclicks > 0:
        try:
            structure_type = 'garnet'
            formula = ""

            c_composition = parse_composition(structure_type, c_string, "C")
            a_composition = parse_composition(structure_type, a_string, "A")
            d_composition = parse_composition(structure_type, d_string, "D")

            charge = -2.0 * 12

            for k in c_composition.keys():
                charge += 3 * k.oxi_state * c_composition.get_atomic_fraction(k)
            for k in a_composition.keys():
                charge += 2 * k.oxi_state * a_composition.get_atomic_fraction(k)
            for k in d_composition.keys():
                charge += 3 * k.oxi_state * d_composition.get_atomic_fraction(k)

            if len(c_composition) > 1:
                mix_site = "c"
            elif len(a_composition) > 1:
                mix_site = "a"
            elif len(d_composition) > 1:
                mix_site = "d"
            else:
                mix_site = None

            species = {"a": a_composition, "d": d_composition, "c": c_composition}

            if abs(charge) < 0.1:
                with tf.Session() as sess:

                    oxide_table_path = os.path.join(os.path.dirname(os.path.abspath(__file__)),
                                                    "data/garnet_oxi_table.json")
                    model, scaler, graph = load_model_and_scaler(structure_type, mix_site) if mix_site \
                        else load_model_and_scaler(structure_type, "unmix")
                    inputs = get_descriptor(structure_type, species)

                    with graph.as_default():
                        form_e = get_form_e(inputs, model, scaler) * 20
                    tot_e = get_tote(structure_type, form_e, species,
                                     oxides_table_path=oxide_table_path)
                    if mix_site:
                        decompose_entries = get_decomposed_entries(structure_type,
                                                                   species,
                                                                   oxide_table_path)
                        decomp, ehull = get_ehull(structure_type, tot_e, species,
                                                  unmix_entries=decompose_entries)
                    else:
                        decomp, ehull = get_ehull(structure_type, tot_e, species)
                    formula = spe2form(structure_type, species)
                    message = [html.P("Ef = %.3f eV/fu" % form_e),
                               html.P("Ehull = %.0f meV/atom" % (ehull * 1000))]
                    if ehull > 0:
                        message.append(html.Span("Decomposition: "))
                        i = 0
                        for k, v in decomp.items():
                            comp = k.composition
                            comp, f = comp.get_reduced_composition_and_factor()
                            if i != 0:
                                message.append(html.Span(" + "))
                            message.append(html.Span("%.3f" % (v * f / comp.num_atoms * 20)))
                            message.append(dcc.Link(comp.reduced_formula,
                                         href='https://www.materialsproject.org/materials/%s' % k.entry_id)
                            )
                            i += 1
            else:
                message = [html.P("Not charge neutral! Total charge = %.0f" % charge)]
        except Exception as ex:
            message = html.P(str(ex))
        print(message)
        return message