Spaces:
Sleeping
Sleeping
import pymatgen as mg | |
import pandas as pd | |
import numpy as np | |
from pymatgen.core.structure import Composition | |
def calculate_density(comp): | |
"""Calculates densisty based on Rule of Mixtures (ROM).""" | |
# comp = Composition(formula) | |
weights = [comp.get_atomic_fraction(e) for e in comp.elements] | |
vols = np.array([e.molar_volume for e in comp.elements]) | |
atomic_masses = np.array([e.atomic_mass for e in comp.elements]) | |
val = np.sum(weights * atomic_masses) / np.sum(weights * vols) | |
return round(val, 1) | |
def calculate_young_modulus(comp): | |
"""Calculates Young Modulus based on Rule of Mixtures (ROM).""" | |
# comp = Composition(formula) | |
weights = np.array([comp.get_atomic_fraction(e) for e in comp.elements]) | |
vols = np.array([e.molar_volume for e in comp.elements]) | |
ym_vals = [] | |
for e in comp.elements: | |
if str(e) == "C": # use diamond form for carbon | |
ym_vals.append(1050) | |
elif str(e) == "B": # use minimum value for Boron Carbide | |
ym_vals.append(362) | |
elif str(e) == "Mo": | |
ym_vals.append(329) | |
elif str(e) == "Co": | |
ym_vals.append(209) | |
else: | |
ym_vals.append(e.youngs_modulus) | |
# ym_vals = np.array([e.youngs_modulus for e in comp.elements]) | |
ym_vals = np.array(ym_vals) | |
if None in ym_vals: | |
print(comp, ym_vals) | |
return "" | |
val = np.sum(weights * vols * ym_vals) / np.sum(weights * vols) | |
if val is np.nan: | |
val = 0 | |
return int(round(val, 0)) | |
def calculate_electronegativity(comp): | |
return comp.average_electroneg | |
def create_composition(comp_df): | |
ls_comp = comp_df.to_dict("records") | |
res = [] | |
for comp_dict in ls_comp: | |
elem_fill = np.sum([comp_dict[e] for e in comp_dict]) | |
comp_dict["Fe"] = 100 - elem_fill | |
# print(comp_dict) | |
compo = Composition.from_weight_dict(comp_dict) | |
res.append(compo) | |
comp_df["composition"] = res | |
return comp_df | |
def calculate_electronegativity(comp): | |
return comp.average_electroneg | |
def calculate_valence_electron_concentration(comp): | |
""" | |
Using the formuma from https://www.sciencedirect.com/science/article/pii/S0927025622000015#s0100 | |
VEC = Sum(j=1 to N)C(j)VEC(j) | |
where N is the number of alloying elements, C(j) and VEC(j) are the atomic percentage and the valence electron number of element j | |
""" | |
weights = np.array([comp.get_atomic_fraction(e) for e in comp.elements]) | |
val_ls = [] | |
for e in comp.elements: | |
if str(e) == "Cr": | |
val_ls.append(6) | |
elif str(e) == "Mo": | |
# For Mo valence electron can vary from 2 to 6 | |
val_ls.append(4) | |
else: | |
val_ls.append(e.valence[1]) | |
val_ls = np.array(val_ls) | |
vec = np.sum(weights * val_ls) | |
return vec | |
def calculate_configuration_entropy(comp): | |
""" | |
Using the formuma from https://www.sciencedirect.com/science/article/pii/S0927025622000015#s0100 | |
VEC = -R*Sum(j=1 to N)C(j)ln(C(j)) | |
where N is the number of alloying elements, C(j) is the atomic percentage element j and R is the gas constant | |
The gas constant is omitted for now | |
""" | |
weights = np.array([comp.get_atomic_fraction(e) for e in comp.elements]) | |
ent = np.sum(weights * np.log(weights)) | |
return ent | |
def add_physics_features(df): | |
""" | |
Adds the density and young modulus as additional columns | |
elem_df: pd.DataFrame containing the proportion of each elements | |
""" | |
mapping = {"%C": "C", "%Co": "Co", "%Cr": "Cr", "%V": "V", "%Mo": "Mo", "%W": "W"} | |
if type(df) != pd.DataFrame: | |
# Fix for the case where the input df is not a dataframe but an array | |
print(df.shape) | |
if df.shape[1] < 10: | |
cols = ["%C", "%Co", "%Cr", "%V", "%Mo", "%W", "Temperature_C"] | |
else: | |
cols = [ | |
"%C", | |
"%Co", | |
"%Cr", | |
"%V", | |
"%Mo", | |
"%W", | |
"M6C", | |
"M23C6", | |
"FCCA1#2", | |
"M2C", | |
"MC - SHP", | |
"MC ETA", | |
"%C matrice", | |
"%Co matrice", | |
"%Cr matrice", | |
"%V matrice", | |
"%Mo matrice", | |
"%W matrice", | |
"Temperature_C", | |
] | |
df = pd.DataFrame(df, columns=cols) | |
print(df.shape) | |
elem_df = df[mapping.keys()] | |
elem_df.rename(columns=mapping, inplace=True) | |
elem_df["Fe"] = 100 - elem_df.sum(axis=1) | |
df_w_compo = create_composition(elem_df) | |
df["density"] = np.vectorize(calculate_density)(df_w_compo["composition"]) | |
df["young_modulus"] = np.vectorize(calculate_young_modulus)(df_w_compo["composition"]) | |
df["electronegativity"] = np.vectorize(calculate_electronegativity)(df_w_compo["composition"]) | |
df["valence_electron_concentration"] = np.vectorize(calculate_valence_electron_concentration)( | |
df_w_compo["composition"] | |
) | |
df["configuration_entropy"] = np.vectorize(calculate_configuration_entropy)(df_w_compo["composition"]) | |
return df | |
if __name__ == "__main__": | |
df = pd.DataFrame([[0.3, 5, 3.9, 2.1, 5, 1.2]], columns=["%C", "%Co", "%Cr", "%V", "%Mo", "%W"]) | |
df = pd.DataFrame([[0.3, 5, 3.9, 2.1, 5, 1.2]], columns=["C", "Co", "Cr", "V", "Mo", "W"]) | |
df = pd.DataFrame([[7, 38]], columns=["Al", "Ni"]) # Debug density issue on gradio demo | |
# add_physics_features(df) | |
df = create_composition(df) | |
val = calculate_density(df["composition"].iloc[0]) | |
print(val) | |