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
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
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))
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))
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