Spaces:
Sleeping
Sleeping
File size: 5,621 Bytes
51a84f1 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 |
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)
|