import streamlit as st import pandas as pd import numpy as np import plotly.express as px import plotly.graph_objects as go from utils.data import ( FF_PERFORMANCE, ARRHENIUS_PARAMS, DFT_MECHANISMS, SEI_MATERIALS, ML_MODELS, SIM_CAMPAIGN, DFT_CONFIG_TYPES, DFT_FILE_FORMATS, ELECTROLYTE_DECOMP, MECHANICAL_PROPS, THERMAL_SAFETY, ANODE_MATERIALS, ADDITIVES, DECOMP_PRODUCTS, REACTION_PATHWAYS, VALIDATION_RECS, get_loss_curve, build_diffusion_table, build_arrhenius_lines, build_strain_curves, build_eos_curves, build_rdf_data, build_cycle_life_curves, build_rate_capability, build_msd_curves, build_ion_mobility_map, build_dendrite_risk, diffusion_coefficient, R_GAS, # SIB cathode data SIB_STRUCTURES, SIB_FORMATION_ENERGIES, SIB_AVG_CHARGES, SIB_CATHODE_RANKING, SIB_DIFFUSION, SIB_VOLTAGE, SIB_PIPELINE_STAGES, SIB_SCREENED, build_bader_df, ) from utils.plots import ( ff_performance_chart, loss_curve_chart, arrhenius_plot, diffusion_bar_chart, strain_energy_plot, eos_plot, rdf_plot, sei_ranking_chart, sei_radar, ml_model_scatter, activation_energy_comparison, msd_plot, cycle_life_plot, rate_capability_plot, thermal_safety_plot, electrolyte_ranking_chart, anode_ranking_chart, additive_ranking_chart, multi_objective_pareto, ion_mobility_plot, dendrite_risk_plot, reaction_pathway_plot, mechanical_spider, # SIB plots sib_structure_overview, sib_lattice_radar, sib_bader_box, sib_bader_heatmap, sib_charge_transfer_bar, sib_formation_energy_chart, sib_cathode_ranking_chart, sib_cathode_radar, sib_diffusion_bar, sib_screened_bubble, sib_pipeline_status, ) st.set_page_config( page_title="Battery-AI Simulation Engine ยท LiB + SIB", page_icon="๐Ÿ”‹", layout="wide", initial_sidebar_state="expanded", ) st.markdown(""" """, unsafe_allow_html=True) # โ”€โ”€ Cache โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ @st.cache_data def load_static(): return ( get_loss_curve(), build_diffusion_table(), build_arrhenius_lines(), build_strain_curves(), build_eos_curves(), build_msd_curves(), build_ion_mobility_map(), build_dendrite_risk(), build_cycle_life_curves(), build_rate_capability(), ) (loss_df, diff_df, arr_df, strain_df, eos_df, msd_df, mob_df, dendrite_df, cycle_df, rate_df) = load_static() # โ”€โ”€ Sidebar โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ with st.sidebar: st.markdown("## ๐Ÿ”‹ Battery-AI Engine") st.caption("Force Field & Simulation Platform") st.divider() st.markdown("#### Global Filters") sel_ff = st.multiselect( "Force Fields", ["Yun et al.", "Wang et al.", "This Work"], default=["Yun et al.", "Wang et al.", "This Work"], ) sel_system = st.selectbox( "Li System", ["LiF", "Liโ‚€.โ‚‰F (10% vacancies)", "Liโ‚.โ‚F (10% interstitials)"], ) sel_temp = st.select_slider("Temperature (K)", [300, 400, 500], value=300) sel_rdf_ff = st.radio("RDF Force Field", ["This Work", "Yun et al."], horizontal=True) st.divider() st.markdown("#### Live Diffusivity Calculator") c_T = st.slider("Temperature (K)", 250, 700, 300, step=10) c_ff = st.selectbox("Force Field", ["This Work", "Yun et al.", "Wang et al."]) c_sys = st.selectbox("System", ["LiF", "Liโ‚€.โ‚‰F (10% vacancies)", "Liโ‚.โ‚F (10% interstitials)"], key="sb_sys") _p = ARRHENIUS_PARAMS[c_sys][c_ff] _D = diffusion_coefficient(_p["D0"], _p["Ea"], c_T) st.metric(f"D at {c_T} K", f"{_D:.3e} cmยฒ/s", delta=f"Eโ‚ = {_p['Ea']} kJ/mol") st.divider() st.markdown("#### ๐Ÿ”ท Na-Ion Battery") sel_sib_mat = st.multiselect( "SIB Cathode Materials", ["NaFePOโ‚„", "Naโ‚‚MnNiOโ‚„"], default=["NaFePOโ‚„", "Naโ‚‚MnNiOโ‚„"], key="sb_sib_mat", ) st.divider() st.caption("Battery-ION ยท LiB + SIB") # โ”€โ”€ Header & KPIs โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ st.title("๐Ÿ”‹ Battery-AI Force Field & Simulation Engine") st.markdown( "End-to-end AI platform: **DFT data โ†’ ML force-field training โ†’ MD simulation โ†’ " "battery property prediction โ†’ ranked material recommendations.** " "Covers both **Li-ion (LiB)** and **Na-ion (SIB)** cathode systems." ) kpis = [ ("DFT Simulations", "300+", "training database (LiB)"), ("SIB Structures", "4", "NaFePOโ‚„ + Naโ‚‚MnNiOโ‚„ (UC + SC)"), ("Energy Rยฒ (New FF)", "0.293", "vs โˆ’0.093 prior"), ("D @300K (LiF FF)", "3.44ร—10โปโธ", "cmยฒ/s"), ("NaFePOโ‚„ Eform", "โˆ’2.38 eV/atom", "DFT computed"), ("Naโ‚‚MnNiOโ‚„ Eform", "โˆ’1.542 eV/atom", "DFT computed"), ("NaFePOโ‚„ AI Score", "89/100", "AI cathode ranking"), ("Na D (b-axis)", "8.5ร—10โปยนโฐ cmยฒ/s", "predicted ML-NEB"), ] cols = st.columns(len(kpis)) for col, (label, val, sub) in zip(cols, kpis): with col: st.markdown(f"""
{label}
{val}
{sub}
""", unsafe_allow_html=True) st.markdown("
", unsafe_allow_html=True) # โ”€โ”€ Tabs: 9 tabs โ€” 8 LiB + 1 new SIB (Na-Ion Battery) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ tabs = st.tabs([ "๐Ÿ  Workflow Overview", "๐Ÿ“ DFT Data Input", "โšก ML Force Field Trainer", "๐Ÿ”ฌ MD Simulation Engine", "๐Ÿค– AI Property Predictor", "๐Ÿงช SEI Analysis", "๐Ÿ† AI Ranking Engine", "๐Ÿ“‹ Deliverables & Validation", "๐Ÿ”ท Na-Ion Battery (SIB)", ]) # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• # TAB 1 โ€” Workflow Overview # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• with tabs[0]: st.markdown('
Core Workflow Pipeline
', unsafe_allow_html=True) st.caption( "The tool takes DFT data as input, then uses ML/AI to automate " "force-field training, MD simulation, battery property prediction, and material ranking." ) # Visual pipeline pipeline_steps = [ ("๐Ÿ“ฅ", "Input DFT Data", "Energy, forces, charges, relaxed structures, defect structures, surfaces, strain data, diffusion pathways"), ("๐Ÿงน", "AI Data Processor", "Cleans DFT data, checks quality, removes duplicates, labels configurations, builds training datasets"), ("๐Ÿง ", "ML Force Field Training", "Trains M3GNet / NequIP / CHGNet / DeepMD / SchNet / ALIGNN-FF. Also supports AI-assisted ReaxFF optimisation"), ("โš™๏ธ", "AI Simulation Manager", "Auto-runs: Li-ion diffusion ยท SEI formation ยท LiF stability ยท electrolyte decomposition ยท dendrite growth ยท anodeโ€“cathode interface"), ("๐Ÿ“Š", "Battery Property Predictor", "Predicts: ionic diffusivity ยท activation energy ยท SEI stability ยท decomp. risk ยท mechanical stability ยท thermal safety ยท cycle-life ยท capacity retention"), ("๐Ÿ†", "AI Ranking Engine", "Multi-objective scoring of materials, electrolytes, additives. Final output: top candidates + predicted properties + ranked recommendations."), ] for icon, title, body in pipeline_steps: with st.expander(f"{icon} **{title}**", expanded=False): st.markdown(body) st.divider() # Pipeline flow figure fig_pipe = go.Figure() labels = [s[1] for s in pipeline_steps] x_pos = list(range(len(labels))) fig_pipe.add_trace(go.Scatter( x=x_pos, y=[1] * len(x_pos), mode="markers+text", marker=dict(size=52, color=["#3A86FF","#8B5CF6","#FF4757","#F59E0B","#06B6D4","#4ade80"], line=dict(width=2, color="#fff")), text=[s[0] for s in pipeline_steps], textfont=dict(size=20), hovertext=labels, hoverinfo="text", )) for i, lbl in enumerate(labels): fig_pipe.add_annotation(x=i, y=0.82, text=f"{lbl}", showarrow=False, font=dict(size=10, color="#EEE"), align="center") for i in range(len(labels) - 1): fig_pipe.add_annotation(x=i + 0.52, y=1, text="โ†’", showarrow=False, font=dict(size=22, color="#aaa")) fig_pipe.update_layout( height=200, showlegend=False, xaxis=dict(showgrid=False, zeroline=False, showticklabels=False, range=[-0.5, 5.5]), yaxis=dict(showgrid=False, zeroline=False, showticklabels=False, range=[0.6, 1.2]), plot_bgcolor="rgba(0,0,0,0)", paper_bgcolor="rgba(0,0,0,0)", margin=dict(t=10, b=10, l=10, r=10), ) st.plotly_chart(fig_pipe, use_container_width=True, key="pipeline_viz") st.divider() c1, c2 = st.columns(2) with c1: st.markdown("#### Tool Modules Summary") modules = pd.DataFrame({ "Module": ["1. DFT Data Input", "2. AI Dataset Builder", "3. ML Force Field Trainer", "4. MD Simulation Engine", "5. AI Property Predictor", "6. Ranking & Report Generator"], "Focus": ["Upload & validate DFT files", "Organise into 9 configuration types", "Train M3GNet/CHGNet/NequIP/DeepMD", "NVT/NPT runs via LAMMPS", "8 predicted battery properties", "Multi-objective material ranking"], "Tech": ["ASE, pymatgen", "pymatgen, ASE", "PyTorch, ParAMS", "LAMMPS, PACKMOL", "Einsteinโ€“Smoluchowski, CI-NEB", "Streamlit, Plotly"], }) st.dataframe(modules, use_container_width=True, hide_index=True) with c2: st.markdown("#### Final Tool Output (8 Deliverables)") deliverables = pd.DataFrame({ "#": list(range(1, 9)), "Deliverable": [ "Ranked battery material candidates", "AI-trained force field model", "MD simulation results", "Diffusion coefficient & activation energy", "SEI stability prediction", "Electrolyte decomposition risk", "LIB performance summary", "Experimental validation roadmap", ], "Tab": ["AI Ranking Engine", "ML FF Trainer", "MD Simulation Engine", "AI Property Predictor", "SEI Analysis", "AI Property Predictor", "Deliverables", "Deliverables"], }) st.dataframe(deliverables, use_container_width=True, hide_index=True) # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• # TAB 2 โ€” DFT Data Input (Module 1 + 2) # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• with tabs[1]: st.markdown('
Module 1: DFT Data Upload
', unsafe_allow_html=True) st.caption("Users upload DFT results in any of the supported formats. The AI Data Processor then validates, labels, and organises them into training groups.") c1, c2 = st.columns([1, 1.2]) with c1: st.markdown("#### Accepted File Formats") st.dataframe(DFT_FILE_FORMATS, use_container_width=True, hide_index=True) st.markdown("#### Simulated Upload Interface") st.info("In the live tool, users drag-and-drop DFT files here. The processor auto-detects format and extracts energies, forces, and charges.") uploaded = st.file_uploader( "Upload DFT file (demo โ€” any file accepted for preview)", type=["xyz","cif","txt","csv","json"], accept_multiple_files=False, ) if uploaded: st.success(f"Received: **{uploaded.name}** ({uploaded.size:,} bytes) โ€” format auto-detected, queued for processing.") else: st.caption("No file uploaded โ€” showing database statistics below.") with c2: st.markdown("#### Training Database Quality Metrics") quality = pd.DataFrame({ "Metric": ["Total DFT simulations", "Database entries (energy+force+charge)", "Energy accuracy target", "Force accuracy target", "Duplicate check", "Autocorrelation reduction", "Data accessibility"], "Value": ["300+", "3,000+", "< 0.01 eV/atom", "< 5.1ร—10โปยณ eV/ร…", "Stochastic sampling", "Minimised by design", "Open-access"], }) st.dataframe(quality, use_container_width=True, hide_index=True) # Dataset composition pie df_pie = DFT_CONFIG_TYPES.copy() fig_pie = px.pie(df_pie, names="Configuration Type", values="Entries in DB", title="DFT Database Composition by Configuration Type", color_discrete_sequence=px.colors.qualitative.Plotly, hole=0.4) fig_pie.update_layout(height=360, plot_bgcolor="rgba(0,0,0,0)", paper_bgcolor="rgba(0,0,0,0)", font=dict(color="#EEE"), legend=dict(bgcolor="rgba(0,0,0,0)", font=dict(size=10)), margin=dict(t=50, b=10)) st.plotly_chart(fig_pie, use_container_width=True, key="db_pie") st.divider() st.markdown('
Module 2: AI Dataset Builder โ€” 9 Configuration Types
', unsafe_allow_html=True) st.caption( "Automatically creates training groups covering all battery-relevant phenomena. " "ReaxFF/ML force fields fail if the training set does not cover the target phenomenon." ) st.dataframe(DFT_CONFIG_TYPES, use_container_width=True, hide_index=True) st.divider() c1, c2 = st.columns(2) with c1: st.markdown("#### Database Configuration Counts") fig_bar = px.bar(DFT_CONFIG_TYPES, x="Entries in DB", y="Configuration Type", orientation="h", color="Configuration Type", color_discrete_sequence=px.colors.qualitative.Plotly, title="Entries per Configuration Type") fig_bar.update_layout(height=360, showlegend=False, plot_bgcolor="rgba(0,0,0,0)", paper_bgcolor="rgba(0,0,0,0)", font=dict(color="#EEE"), margin=dict(t=45, b=10, l=220)) fig_bar.update_xaxes(gridcolor="rgba(255,255,255,0.1)") st.plotly_chart(fig_bar, use_container_width=True, key="config_bar") with c2: st.markdown("#### Simulation Campaign Log") st.dataframe(SIM_CAMPAIGN, use_container_width=True, hide_index=True) st.markdown(""" **Key simulation parameters:** - DFT code: VASP/BAND (PBE functional, DZ NAO basis) - k-point accuracy: < 0.01 eV/atom - ab initio MD: DFTB (Grimme xTB) - LAMMPS ReaxFF-MD: 500 ps NVT, ฮดt = 0.25 fs """) # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• # TAB 3 โ€” ML Force Field Trainer (Module 3) # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• with tabs[2]: st.markdown('
Module 3: ML Force Field Trainer
', unsafe_allow_html=True) st.caption( "Trains AI force fields to replace expensive DFT. First version: " "DFT data โ†’ M3GNet / CHGNet / NequIP โ†’ MD simulation. " "Advanced: AI-assisted ReaxFF parameter optimisation via CMA-ES." ) c1, c2 = st.columns([1.4, 1]) with c1: st.markdown("#### Force Field Prediction Accuracy") st.plotly_chart(ff_performance_chart(FF_PERFORMANCE), use_container_width=True, key="ff_perf") with c2: st.markdown("#### Metrics") perf_df = pd.DataFrame(FF_PERFORMANCE).rename(columns={ "Force Field": "FF", "Energy Rยฒ": "E Rยฒ", "Energy RMSE (eV)": "E RMSE", "Force Rยฒ": "F Rยฒ", "Force RMSE (eV/ร…)": "F RMSE"}) st.dataframe(perf_df.style.background_gradient(subset=["E Rยฒ","F Rยฒ"], cmap="RdYlGn"), use_container_width=True, hide_index=True) st.markdown(""" **Key finding:** Both Yun et al. and Wang et al. produce negative energy Rยฒ (โˆ’0.093) โ€” systematic failure to describe solid LiF. The new FF reaches Rยฒ=0.293 for energy and 0.377 for forces, recovering physical solid-state behaviour. """) st.divider() st.markdown('
CMA-ES Optimisation Convergence (1.3 ร— 10โด iterations)
', unsafe_allow_html=True) st.plotly_chart(loss_curve_chart(loss_df), use_container_width=True, key="loss_curve") st.caption("Bond interactions optimised first (0โ€“5,000 iter), then van der Waals (5,000โ€“13,000 iter). Angular/torsional terms could not converge โ€” degenerate loss gradients.") st.divider() st.markdown('
ML Model Benchmark โ€” Energy MAE, Force MAE, Speed
', unsafe_allow_html=True) st.caption("Bubble size = inference speed (larger = faster). Recommended: CHGNet or NequIP for this dataset size (~3,000 entries).") st.plotly_chart(ml_model_scatter(ML_MODELS), use_container_width=True, key="ml_scatter") st.divider() c1, c2 = st.columns(2) with c1: st.markdown("#### Model Specifications") st.dataframe(ML_MODELS[["Model","Architecture","Energy MAE (meV/atom)","Force MAE (meV/ร…)","Rยฒ Energy"]], use_container_width=True, hide_index=True) with c2: st.markdown("#### Recommended Training Pipeline") st.markdown(""" **MVP (first version):** 1. DFT data โ†’ **M3GNet / CHGNet / NequIP** 2. ~3,000 labelled configurations 3. Train energy + force head 4. Export as LAMMPS-compatible model 5. Run NVT MD at 300/400/500 K **Advanced (ReaxFF path):** 1. DFT data โ†’ **ParAMS + CMA-ES** 2. Step-wise: bonds โ†’ vdW โ†’ angles 3. Up to 13,000 optimisation iterations 4. Validate against CI-NEB barriers **ReaxFF parameter categories:** General (41) ยท Atoms (32/type) ยท Bonds (16/bond) ยท Off-diagonal (6) ยท Angles (7) ยท Dihedral (7) ยท H-bonds (4) """) st.divider() st.markdown("#### CI-NEB Energy Barrier Comparison") neb_data = pd.DataFrame({ "Mechanism": ["Vacancy", "Direct-hopping", "Knock-off (est.)"], "DFT Zheng et al. (kJ/mol)": [63.7, 52.1, 24.1], "DFT this work (kJ/mol)": [64.3, 87.5, "โ€”"], "New ReaxFF MD Eโ‚ (kJ/mol)": [11.0, 11.0, 11.0], "Status": ["Underestimated 5.8ร—", "Underestimated 8ร—", "Underestimated 2.2ร—"], }) st.dataframe(neb_data, use_container_width=True, hide_index=True) st.warning("Activation energies from MD are still 2โ€“8ร— below DFT CI-NEB barriers. Future training sets must explicitly include Li-transport pathway configurations.") # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• # TAB 4 โ€” MD Simulation Engine (Module 4) # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• with tabs[3]: st.markdown('
Module 4: AI Simulation Manager
', unsafe_allow_html=True) st.caption( "Auto-runs: NVT/NPT ยท Li-ion diffusion ยท SEI interface ยท " "electrolyte decomposition ยท LiF stability ยท anodeโ€“electrolyte interface ยท dendrite growth" ) subtab_md = st.tabs(["๐Ÿ“ˆ Diffusion & Arrhenius", "๐Ÿ”ฌ Crystal Stability", "๐ŸŒก๏ธ RDF Evolution", "๐Ÿ“‰ MSD Analysis", "โš ๏ธ Dendrite Growth Risk"]) # โ”€โ”€ MD Sub-tab 1: Diffusion with subtab_md[0]: c_a, c_b = st.columns(2) with c_a: filtered_arr = arr_df[ arr_df["Force Field"].isin(sel_ff) | (arr_df["Force Field"] == "DFT reference") ] st.plotly_chart(arrhenius_plot(filtered_arr, sel_system), use_container_width=True, key="arrhenius") with c_b: filtered_diff = diff_df[diff_df["Force Field"].isin(sel_ff)] st.plotly_chart(diffusion_bar_chart(filtered_diff, sel_temp), use_container_width=True, key="diff_bar") st.plotly_chart(activation_energy_comparison(), use_container_width=True, key="ea_comp") st.markdown("#### Diffusion Data Table") disp = diff_df[diff_df["Force Field"].isin(sel_ff)].copy() disp["D (cmยฒ/s)"] = disp["D (cmยฒ/s)"].apply(lambda x: f"{x:.3e}") st.dataframe(disp[["System","Force Field","Temperature (K)","D (cmยฒ/s)","logโ‚โ‚€(D)"]] .sort_values(["System","Force Field","Temperature (K)"]), use_container_width=True, hide_index=True) st.markdown(""" **New FF at 300 K (LiF):** D = 3.44 ร— 10โปโธ cmยฒ/s โ€” ~1000ร— lower than Yun/Wang (3.56 ร— 10โปโต cmยฒ/s). Electrolyte Liโบ diffusivity: 0.5โ€“1.4 ร— 10โปโต cmยฒ/s. New FF correctly places LiF in the solid-state regime. """) # โ”€โ”€ MD Sub-tab 2: Crystal Stability with subtab_md[1]: c1, c2 = st.columns(2) with c1: st.plotly_chart(strain_energy_plot(strain_df), use_container_width=True, key="strain") st.caption("Shear strain ฮตโ‚โ‚‚ โ€” old FFs show inverted concavity (negative cโ‚โ‚‚ elastic constant). New FF recovers parabolic minimum near equilibrium.") with c2: st.plotly_chart(eos_plot(eos_df), use_container_width=True, key="eos") st.caption("Murnaghan EOS โ€” old FFs: no energy minimum. New FF agrees with DFT even at ยฑ30% volume change.") st.markdown("#### LiF Crystal Phases (Materials Project data)") crystal_data = pd.DataFrame({ "Phase": ["Stable FCC (Fm3ฬ„m)", "Metastable HEX (P6โ‚ƒmc)", "Metastable BCC (Pm3ฬ„m)"], "Space Group": ["Fm3ฬ„m", "P6โ‚ƒmc", "Pm3ฬ„m"], "Lattice": ["Face-Centered Cubic", "Hexagonal", "Body-Centered Cubic"], "Formation Energy (DFT, eV)": [-4.31, -4.18, -3.95], "First Liโ€“F Distance (ร…)": [2.01, 1.96, 2.08], "New FF Accuracy": ["Excellent", "Good", "Moderate"], }) st.dataframe(crystal_data, use_container_width=True, hide_index=True) # โ”€โ”€ MD Sub-tab 3: RDF with subtab_md[2]: st.caption("Liโ€“F g(r) during 500 ps NVT at 300 K. Crystalline LiF: sharp peaks at 2.01 ร…, 4.02 ร…, 5.69 ร…. LiF melt point = 1121 K โ€” any amorphization at 300 K is unphysical.") rdf_sel = build_rdf_data(sel_rdf_ff) st.plotly_chart(rdf_plot(rdf_sel, sel_rdf_ff), use_container_width=True, key="rdf_sel") c1, c2 = st.columns(2) with c1: st.markdown("#### Old FFs โ€” Amorphization within 2 ps") rdf_old = build_rdf_data("Yun et al.") st.plotly_chart(rdf_plot(rdf_old, "Yun et al."), use_container_width=True, key="rdf_old") with c2: st.markdown("#### New FF โ€” Crystalline Order Preserved") rdf_new = build_rdf_data("This Work") st.plotly_chart(rdf_plot(rdf_new, "This Work"), use_container_width=True, key="rdf_new") # โ”€โ”€ MD Sub-tab 4: MSD with subtab_md[3]: st.caption("MSD slope = 6D (Einsteinโ€“Smoluchowski). New FF gives 100โ€“1000ร— lower slope โ†’ correct solid-state Li transport.") st.plotly_chart(msd_plot(msd_df), use_container_width=True, key="msd_plot") st.markdown(""" **Diffusion from MSD:** D = ฮฑโ‚/6, where ฮฑโ‚ is the MSD linear slope (least-squares fit). Simulations run for 500 ps; MSD sampled every 50 steps (12.5 fs interval). """) # โ”€โ”€ MD Sub-tab 5: Dendrite with subtab_md[4]: st.caption("Higher overpotential for Li plating โ†’ greater dendrite nucleation risk. LiF-rich SEI suppresses dendrites by providing uniform Liโบ flux (low local overpotential).") st.plotly_chart(dendrite_risk_plot(dendrite_df), use_container_width=True, key="dendrite") st.markdown(""" **Dendrite mechanism:** Non-uniform SEI creates hotspots of high local current density, lowering the nucleation barrier. LiF-rich SEI (uniform, mechanically stiff) distributes Liโบ flux evenly, raising the overpotential threshold for dendrite nucleation. **SEI role:** Mechanical stiffness of LiF (Young's modulus 109 GPa) suppresses dendrite penetration, while high ionic conductivity reduces local current hotspots. """) # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• # TAB 5 โ€” AI Property Predictor (Module 5) โ€” all 8 properties # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• with tabs[4]: st.markdown('
Module 5: AI Property Predictor โ€” 8 Battery Properties
', unsafe_allow_html=True) prop_tabs = st.tabs([ "โšก Ionic Diffusivity", "๐Ÿ”ฅ Activation Energy", "๐Ÿ›ก๏ธ SEI Stability", "๐Ÿ’ฅ Electrolyte Decomp. Risk", "๐Ÿ’ช Mechanical Stability", "๐ŸŒก๏ธ Thermal Safety", "โ™ป๏ธ Cycle-Life Risk", "๐Ÿ“‰ Capacity Retention", ]) # โ”€โ”€ P1: Ionic Diffusivity with prop_tabs[0]: st.markdown("**Predicted by:** Arrhenius D = Dโ‚€ ยท exp(โˆ’Eโ‚/RT) from MSD slopes") c1, c2 = st.columns(2) with c1: arr_filt = arr_df[arr_df["Force Field"].isin(sel_ff) | (arr_df["Force Field"] == "DFT reference")] st.plotly_chart(arrhenius_plot(arr_filt, sel_system), use_container_width=True, key="prop_arrh") with c2: st.metric("D (LiF, 300K, New FF)", "3.44 ร— 10โปโธ cmยฒ/s", delta="~1000ร— lower than prior FFs") st.metric("D (LiF, 300K, Yun/Wang)", "3.56 ร— 10โปโต cmยฒ/s", delta="โ‰ˆ electrolyte-like โ€” unphysical") st.metric("D (electrolyte Liโบ)", "0.5โ€“1.4 ร— 10โปโต cmยฒ/s", delta="Ref. Lee et al. 2002") st.markdown("New FF correctly places LiF in the **solid-state regime**, 2 orders of magnitude below the electrolyte.") # โ”€โ”€ P2: Activation Energy with prop_tabs[1]: st.markdown("**Predicted by:** Arrhenius slope = โˆ’Eโ‚/R from log(D) vs 1/T linear regression") st.plotly_chart(activation_energy_comparison(), use_container_width=True, key="prop_ea") st.dataframe(pd.DataFrame({ "System": ["LiF","LiF","LiF","Liโ‚€.โ‚‰F","Liโ‚€.โ‚‰F","Liโ‚€.โ‚‰F","Liโ‚.โ‚F","Liโ‚.โ‚F","Liโ‚.โ‚F"], "Force Field": ["Yun et al.","Wang et al.","This Work"]*3, "Eโ‚ (kJ/mol)": [7.50,7.0,11.0,7.1,6.810,5.1,7.6,6.22,6.0], "Eโ‚ err (kJ/mol)": [0.02,0.2,1.6,1.4,0.013,0.5,0.5,0.04,0.8], }), use_container_width=True, hide_index=True) st.warning("All FF Eโ‚ values (5โ€“11 kJ/mol) are well below the DFT CI-NEB barriers (24โ€“87 kJ/mol). Activation energies are underestimated โ€” future training must include transport-pathway configurations.") # โ”€โ”€ P3: SEI Stability with prop_tabs[2]: st.markdown("**Predicted by:** Multi-criteria scoring (ionic conductivity, electronic insulation, mechanical, thermal)") c1, c2 = st.columns([1.3, 1]) with c1: st.plotly_chart(sei_ranking_chart(SEI_MATERIALS), use_container_width=True, key="prop_sei_rank") with c2: radar_sel = st.multiselect("Compare components (radar)", SEI_MATERIALS["Component"].tolist(), default=["LiF (FEC-derived)","Liโ‚‚COโ‚ƒ","Liโ‚‚O"], key="prop_radar_sel") if radar_sel: st.plotly_chart(sei_radar(SEI_MATERIALS, radar_sel), use_container_width=True, key="prop_radar") # โ”€โ”€ P4: Electrolyte Decomp. Risk with prop_tabs[3]: st.markdown("**Predicted by:** Decomposition onset voltage, ionic conductivity, electrochemical window, temperature stability") st.plotly_chart(electrolyte_ranking_chart(ELECTROLYTE_DECOMP), use_container_width=True, key="prop_elec_rank") st.dataframe(ELECTROLYTE_DECOMP[["Electrolyte","Decomp. Onset (V vs Li/Liโบ)", "Decomp. Risk Score (1=low)","LiF SEI Formation?", "Ionic Conductivity (mS/cm)","Decomp. Products"]], use_container_width=True, hide_index=True) st.markdown(""" **FEC advantage:** 1M LiPFโ‚† + 10% FEC has the lowest decomp. risk score (3.1) and highest LiF SEI yield among liquid electrolytes. FEC decomposes selectively to produce LiF-dominant SEI, confirmed by DFT and ReaxFF simulations. """) st.markdown("#### Decomposition Products by Precursor") st.dataframe(DECOMP_PRODUCTS, use_container_width=True, hide_index=True) st.markdown("#### Reaction Pathway: FEC โ†’ LiF") st.plotly_chart(reaction_pathway_plot(REACTION_PATHWAYS), use_container_width=True, key="prop_rxn_path") # โ”€โ”€ P5: Mechanical Stability with prop_tabs[4]: st.markdown("**Predicted by:** Elastic constants from energy-strain DFT calculations (Cโ‚โ‚, Cโ‚โ‚‚, Cโ‚„โ‚„ for FCC LiF)") mech_sel = st.multiselect("Select materials for radar", MECHANICAL_PROPS["Material"].tolist(), default=["LiF","Liโ‚‚COโ‚ƒ","Graphite anode","Silicon anode"], key="mech_sel") if mech_sel: st.plotly_chart(mechanical_spider(MECHANICAL_PROPS, mech_sel), use_container_width=True, key="prop_mech_radar") st.dataframe(MECHANICAL_PROPS, use_container_width=True, hide_index=True) st.info("**LiF Young's modulus: 109 GPa** โ€” stiffest SEI component. Suppresses dendrite penetration and accommodates volume changes better than organic components.") # โ”€โ”€ P6: Thermal Safety with prop_tabs[5]: st.markdown("**Predicted by:** Thermal decomposition onset temperatures from literature + ReaxFF thermal MD") st.plotly_chart(thermal_safety_plot(THERMAL_SAFETY), use_container_width=True, key="prop_thermal") st.dataframe(THERMAL_SAFETY, use_container_width=True, hide_index=True) st.success("**LiF melting point: 1121.35 K (848 ยฐC)** โ€” far above all operating temperatures. The highest thermal stability of any SEI component.") st.error("**Thermal runaway onset: ~130 ยฐC** โ€” triggered by SEI breakdown releasing exothermic energy. LiF-rich SEI delays this onset by ~20โ€“40 ยฐC vs. organic-dominated SEI.") # โ”€โ”€ P7: Cycle-Life Risk with prop_tabs[6]: st.markdown("**Predicted by:** SEI growth model โ€” capacity fade rate โˆ SEI decomposition frequency") st.plotly_chart(cycle_life_plot(cycle_df), use_container_width=True, key="prop_cycle") st.markdown(""" **Key predictions:** - LiF-rich SEI: >88% capacity retention after 200 cycles, >80% after 500 cycles - Artificially engineered LiF SEI: >90% after 500 cycles - No SEI engineering: drops below 80% (EOL) around cycle 200 - End-of-Life threshold (80%) used per IEC 62660-2 standard """) # โ”€โ”€ P8: Capacity Retention (Rate Capability) with prop_tabs[7]: st.markdown("**Predicted by:** Rate capability from MD-derived diffusion coefficients at different C-rates") st.plotly_chart(rate_capability_plot(rate_df), use_container_width=True, key="prop_rate") st.markdown(""" **Interpretation:** - LiF SEI maintains higher capacity at high C-rates due to lower Liโบ transport resistance - Si anode shows dramatic capacity drop above 2C โ€” volume expansion disrupts SEI continuity - Li metal + LiF SEI: best absolute capacity and rate performance (no anode volume change) """) st.markdown("#### Ion Mobility Map โ€” Liโบ Through SEI Depth") st.plotly_chart(ion_mobility_plot(mob_df), use_container_width=True, key="prop_mob") st.caption("Inorganic LiF inner layer (0โ€“5 nm): D โ‰ˆ 3.44ร—10โปโธ cmยฒ/s. Mixed zone (5โ€“12 nm): gradient. Organic outer layer (12โ€“20 nm): D โ‰ˆ 22ร—10โปโธ cmยฒ/s.") # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• # TAB 6 โ€” SEI Analysis # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• with tabs[5]: st.markdown('
SEI Component Analysis & LiF Formation
', unsafe_allow_html=True) c1, c2 = st.columns([1.3, 1]) with c1: st.plotly_chart(sei_ranking_chart(SEI_MATERIALS), use_container_width=True, key="sei_rank") with c2: st.markdown("#### Scoring Weights") st.markdown(""" | Property | Weight | |---|---| | Electronic Insulation | 30% | | Ionic Conductivity | 25% | | Mechanical Stability | 20% | | Thermal Stability | 15% | | Decomp. Risk (โˆ’) | 10% | """) st.info("**LiF** scores highest: exceptional electronic insulation (9.8/10), " "high ionic transport, lowest decomp. risk. Ko & Yoon, Ceram. Int. 2019.") st.divider() c1, c2 = st.columns(2) with c1: radar_sei = st.multiselect("Radar โ€” select components", SEI_MATERIALS["Component"].tolist(), default=["LiF (FEC-derived)","Liโ‚‚COโ‚ƒ","Liโ‚‚O"], key="sei_tab_radar") if radar_sei: st.plotly_chart(sei_radar(SEI_MATERIALS, radar_sei), use_container_width=True, key="sei_radar_tab") with c2: st.markdown("#### Full SEI Dataset") st.dataframe( SEI_MATERIALS.style.background_gradient(subset=["Overall Score"], cmap="RdYlGn"), use_container_width=True, hide_index=True) st.divider() st.markdown("#### FEC Decomposition โ†’ LiF Formation Pathway") st.plotly_chart(reaction_pathway_plot(REACTION_PATHWAYS), use_container_width=True, key="sei_rxn_path") st.dataframe(REACTION_PATHWAYS, use_container_width=True, hide_index=True) st.divider() st.markdown("#### Ion Mobility Through SEI Layers") st.plotly_chart(ion_mobility_plot(mob_df), use_container_width=True, key="sei_mob") # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• # TAB 7 โ€” AI Ranking Engine (Module 6) # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• with tabs[6]: st.markdown('
Module 6: AI Ranking Engine โ€” Multi-Objective Material Scoring
', unsafe_allow_html=True) st.caption( "Ranks materials, additives, and electrolytes using multi-objective scoring. " "Final output: top battery candidates + predicted properties + simulation evidence + ranked recommendations." ) rank_tabs = st.tabs(["๐Ÿงช SEI Components", "๐Ÿ”Œ Electrolytes", "โšก Anode Materials", "โž• Additives", "๐Ÿ“Š Pareto Analysis"]) # โ”€โ”€ R1: SEI with rank_tabs[0]: st.plotly_chart(sei_ranking_chart(SEI_MATERIALS), use_container_width=True, key="rank_sei") st.dataframe(SEI_MATERIALS.sort_values("Overall Score", ascending=False), use_container_width=True, hide_index=True) # โ”€โ”€ R2: Electrolytes with rank_tabs[1]: st.plotly_chart(electrolyte_ranking_chart(ELECTROLYTE_DECOMP), use_container_width=True, key="rank_elec") st.dataframe( ELECTROLYTE_DECOMP[["Electrolyte","Overall Score","Decomp. Risk Score (1=low)", "Ionic Conductivity (mS/cm)","Electrochemical Window (V)", "Temperature Stability (ยฐC)","LiF SEI Formation?","Decomp. Products"]] .sort_values("Overall Score", ascending=False), use_container_width=True, hide_index=True, ) st.success("**Top recommendation:** 1M LiPFโ‚† + 10% FEC in EC/DMC โ€” highest LiF SEI formation, lowest decomp. risk among liquid electrolytes. Confirmed by FEC โ†’ LiF reaction pathway simulations.") # โ”€โ”€ R3: Anode Materials with rank_tabs[2]: st.plotly_chart(anode_ranking_chart(ANODE_MATERIALS), use_container_width=True, key="rank_anode") st.dataframe(ANODE_MATERIALS.sort_values("Overall Score", ascending=False), use_container_width=True, hide_index=True) st.markdown(""" **Volume expansion** is the critical challenge for Si and Sn anodes โ€” disrupts SEI continuity every cycle. The LiF SEI is more resilient to volume changes than organic SEI due to its high Young's modulus (109 GPa). """) # โ”€โ”€ R4: Additives with rank_tabs[3]: st.plotly_chart(additive_ranking_chart(ADDITIVES), use_container_width=True, key="rank_add") st.dataframe(ADDITIVES.sort_values("Overall Score", ascending=False), use_container_width=True, hide_index=True) st.success("**FEC (fluoroethylene carbonate)** is the top-ranked additive: highest LiF SEI enhancement (9.5/10), 35% cycle-life improvement, HF scavenging capability confirmed by simulation.") # โ”€โ”€ R5: Pareto with rank_tabs[4]: st.markdown("#### Multi-Objective Pareto โ€” Capacity vs. Volume Expansion (bubble = cycle stability)") st.plotly_chart(multi_objective_pareto(ANODE_MATERIALS), use_container_width=True, key="pareto") st.caption("Ideal anode: upper-left corner (high capacity, low expansion). Bubble size = cycle stability score. Graphite + LiF SEI is the most practical current choice.") st.divider() st.markdown("#### Electrolyte Score Decomposition") elec_fig = px.bar( ELECTROLYTE_DECOMP.melt(id_vars=["Electrolyte"], value_vars=["Ionic Conductivity (mS/cm)", "Electrochemical Window (V)", "Temperature Stability (ยฐC)"]), x="Electrolyte", y="value", color="variable", barmode="group", title="Electrolyte Property Comparison", color_discrete_sequence=px.colors.qualitative.Plotly, ) elec_fig.update_layout(height=380, plot_bgcolor="rgba(0,0,0,0)", paper_bgcolor="rgba(0,0,0,0)", font=dict(color="#EEE"), legend=dict(bgcolor="rgba(0,0,0,0)"), xaxis=dict(tickangle=-20), margin=dict(t=55, b=60)) elec_fig.update_xaxes(gridcolor="rgba(255,255,255,0.1)") elec_fig.update_yaxes(gridcolor="rgba(255,255,255,0.1)") st.plotly_chart(elec_fig, use_container_width=True, key="elec_decomp_bar") # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• # TAB 8 โ€” Final Report & Experimental Validation # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• with tabs[7]: st.markdown('
Final Tool Output โ€” 8 Deliverables
', unsafe_allow_html=True) deliverable_details = [ ("1", "Ranked Battery Material Candidates", "SEI: LiF > Liโ‚‚COโ‚ƒ > Liโ‚‚O. Electrolyte: FEC-based > standard EC/DMC. Anode: Graphite (near-term), Li metal (future). Additive: FEC (35% cycle-life improvement).", "๐Ÿ†"), ("2", "AI-Trained Force Field Model", "New ReaxFF: E Rยฒ=0.293, F Rยฒ=0.377. D(300K)=3.44ร—10โปโธ cmยฒ/s โ€” 1000ร— improvement. Available: CHGNet/NequIP models trained on 3,000+ DFT configurations.", "๐Ÿง "), ("3", "MD Simulation Results", "500 ps NVT at 300/400/500 K. Systems: LiF, Liโ‚€.โ‚‰F, Liโ‚.โ‚F. RDF confirms crystalline order preservation. MSD confirms correct solid-state diffusion.", "โš™๏ธ"), ("4", "Diffusion Coefficient & Activation Energy", "D(LiF,300K) = 3.44ร—10โปโธ cmยฒ/s. Eโ‚(LiF) = 11.0 ยฑ 1.6 kJ/mol. CI-NEB barriers: vacancy 64.3 kJ/mol, direct-hop 87.5 kJ/mol (still underestimated by FF).", "๐Ÿ“ˆ"), ("5", "SEI Stability Prediction", "LiF: Overall Score 8.65/10. Electronic insulation 9.8/10. Thermal onset 842ยฐC. Mechanical stiffness 109 GPa (Young's modulus). Best SEI component for LIBs.", "๐Ÿ›ก๏ธ"), ("6", "Electrolyte Decomposition Risk", "EC/DMC+FEC: Decomp. risk 3.1/10 (lowest liquid). Onset 1.1 V vs Li/Liโบ. Primary products: LiF (dominant), Liโ‚‚COโ‚ƒ. Solid electrolytes (LGPS): risk 1.5/10.", "๐Ÿ’ฅ"), ("7", "LIB Performance Summary", "Capacity retention: LiF SEI >88% @200cy, >80% @500cy. Rate capability: LiF SEI maintains 300 mAh/g @10C (graphite). Thermal runaway delayed by ~30ยฐC with LiF SEI.", "๐Ÿ“‹"), ("8", "Experimental Validation Recommendations", "8 prioritised experiments: XPS depth profiling, cryo-TEM, EIS, EELS, in-situ NMR, GITT, ARC calorimetry, long-term cycling. See table below.", "๐Ÿ”ฌ"), ] for num, title, details, icon in deliverable_details: with st.expander(f"{icon} **{num}. {title}**", expanded=(num == "1")): st.markdown(details) st.divider() st.markdown('
Experimental Validation Roadmap
', unsafe_allow_html=True) st.dataframe(VALIDATION_RECS, use_container_width=True, hide_index=True) st.divider() st.markdown('
MVP โ†’ Full Production Roadmap
', unsafe_allow_html=True) roadmap = pd.DataFrame({ "Phase": ["MVP (now)", "Phase 2", "Phase 3", "Phase 4"], "Focus": [ "LiF-rich SEI in Li-ion battery (graphite anode)", "Expand SEI: Liโ‚‚COโ‚ƒ, Liโ‚‚O, organic components", "Si & Li-metal anodes โ€” large volume expansion", "Full battery pack: multi-scale โ†’ system level", ], "New Training Data": [ "300+ DFT for LiF (done)", "+500 DFT: Liโ‚‚COโ‚ƒ, Liโ‚‚O, organic ROCOโ‚‚Li", "+1000 DFT: Si-Li, Li-Li, large supercells", "Continuum + atomistic coupling", ], "ML Model": [ "ReaxFF (CMA-ES) / CHGNet / NequIP", "NequIP / DeepMD on multi-component SEI", "Graph NN with large-cell support", "Multi-scale ML + FEM coupling", ], "Target": [ "D within 2ร— of CI-NEB; >88% cap. retention", "Mixed SEI composition prediction", "Volume expansion + dendrite model", "Thermal + electrochemical cell model", ], }) st.dataframe(roadmap, use_container_width=True, hide_index=True) st.divider() st.markdown('
ReaxFF Parameter Summary
', unsafe_allow_html=True) c1, c2 = st.columns(2) with c1: param_data = pd.DataFrame({ "Type": ["General", "Atoms (per NA)", "Bonds (per bond)", "Off-diagonal", "Angles", "Dihedral", "H-bonds"], "Parameters per entry": [41, 32, 16, 6, 7, 7, 4], }) fig_params = px.bar(param_data, x="Type", y="Parameters per entry", color="Type", title="ReaxFF Coefficient Distribution", color_discrete_sequence=px.colors.qualitative.Plotly) fig_params.update_layout(height=300, showlegend=False, plot_bgcolor="rgba(0,0,0,0)", paper_bgcolor="rgba(0,0,0,0)", font=dict(color="#EEE"), margin=dict(t=45, b=40)) fig_params.update_xaxes(gridcolor="rgba(255,255,255,0.1)") fig_params.update_yaxes(gridcolor="rgba(255,255,255,0.1)") st.plotly_chart(fig_params, use_container_width=True, key="reaxff_params") with c2: st.markdown("#### ReaxFF Coefficient Breakdown") coeff_df = pd.DataFrame({ "Type": ["General", "Atoms", "Bonds", "Off-diagonal", "Angles", "Dihedral", "H-bonds"], "Count": [41, 32, 16, 6, 7, 7, 4], "Description": [ "Global FF parameters", "Per atomic species", "Per bond pair", "Cross terms", "3-body interactions", "4-body torsional", "Hydrogen-bond terms", ], }) st.dataframe(coeff_df, use_container_width=True, hide_index=True) # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• # TAB 9 โ€” Na-Ion Battery (SIB) # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• with tabs[8]: st.markdown('
Na-Ion Battery (SIB) โ€” DFT Cathode Data
', unsafe_allow_html=True) st.markdown( "DFT-computed data for two sodium-ion cathode materials: **NaFePOโ‚„** and **Naโ‚‚MnNiOโ‚„**. " "The 8-stage AI pipeline maps each DFT result to a specific AI workflow stage โ€” " "from structure encoding to intelligent cathode ranking." ) # Sub-tabs within the SIB tab sib_tabs = st.tabs([ "๐Ÿ“Š DFT Database", "โšก Formation Energy", "๐Ÿ”ฌ Bader Charge Analysis", "๐Ÿš€ Na Diffusion", "๐Ÿ† Cathode Ranking", "๐Ÿค– AI Pipeline", "๐Ÿ”ฎ AI Screening", "๐Ÿ“ˆ Voltage & Capacity", ]) # โ”€โ”€ SIB Sub-tab 1: DFT Database โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ with sib_tabs[0]: st.markdown("### Crystal Structure Database") st.markdown( "Four fully-relaxed DFT structures computed with VASP (GGA+U), " "forming the **seed dataset** for the Battery Foundation Model." ) # KPI row for SIB structures sib_kpis = [ ("NaFePOโ‚„ Unit Cell", "28 atoms", "a=5.10, b=6.94, c=9.11 ร…"), ("NaFePOโ‚„ Supercell", "128 atoms", "2ร—2ร—1 ยท โˆ’746.93 eV"), ("Naโ‚‚MnNiOโ‚„ Unit Cell", "24 atoms", "a=b=3.052, c=32.148 ร… ยท hexagonal"), ("Naโ‚‚MnNiOโ‚„ Supercell", "96 atoms", "2ร—2ร—1 ยท โˆ’517.270 eV"), ] sib_kcols = st.columns(4) for col, (lbl, val, sub) in zip(sib_kcols, sib_kpis): with col: st.markdown(f"""
{lbl}
{val}
{sub}
""", unsafe_allow_html=True) st.markdown("
", unsafe_allow_html=True) st.markdown("#### Structure Summary Table") st.dataframe( SIB_STRUCTURES.style.background_gradient( subset=["Total Energy (eV)", "Formation Energy (eV/atom)"], cmap="Blues" ), use_container_width=True, ) st.markdown("#### Total Energy & Formation Energy Comparison") st.plotly_chart(sib_structure_overview(SIB_STRUCTURES), use_container_width=True, key="sib_structure_overview") st.markdown("#### Lattice Parameter Radar") all_mats = SIB_STRUCTURES["Material"].tolist() sel_mats_radar = st.multiselect( "Select structures", all_mats, default=all_mats[:2], key="sib_lat_radar_sel" ) if sel_mats_radar: st.plotly_chart(sib_lattice_radar(SIB_STRUCTURES, sel_mats_radar), use_container_width=True, key="sib_lattice_radar") st.markdown("#### Key Structural Properties") st.info(""" **NaFePOโ‚„ (Olivine structure):** - Orthorhombic symmetry (Pnma) ยท all angles 90ยฐ - Strong 1D diffusion channels along b-axis (shortest path Na โ†” vacancy) - Supercell 2ร—2ร—1: 128 atoms ideal for Na diffusion MD simulations **Naโ‚‚MnNiOโ‚„ (Layered oxide):** - Hexagonal symmetry ยท ฮณ=120ยฐ ยท large c-axis (32 ร…) - 2D diffusion in ab-plane; c-axis interlayer hopping limited - Mnยณโบ/Niยฒโบ redox centres โ†’ higher voltage potential (3.45 V) """) # โ”€โ”€ SIB Sub-tab 2: Formation Energy โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ with sib_tabs[1]: st.markdown("### Formation Energy Analysis โ€” Stage 3: Formation Energy Predictor") st.markdown( "Formation energies from DFT calculations are used to train an AI model that " "can screen **millions of hypothetical cathodes** without running DFT." ) col1, col2, col3, col4 = st.columns(4) with col1: st.metric("NaFePOโ‚„ Eform", "โˆ’2.38 eV/atom", "DFT") with col2: st.metric("Naโ‚‚MnNiOโ‚„ Eform", "โˆ’1.542 eV/atom", "DFT") with col3: st.metric("Naโ‚ƒVโ‚‚(POโ‚„)โ‚ƒ Eform", "โˆ’2.85 eV/atom", "Literature reference") with col4: st.metric("Stability rank: NaFePOโ‚„", "#2 of 8", "Most stable DFT-computed") st.plotly_chart(sib_formation_energy_chart(SIB_FORMATION_ENERGIES), use_container_width=True, key="sib_form_e") st.markdown("#### Formation Energy Table") st.dataframe( SIB_FORMATION_ENERGIES.style.background_gradient( subset=["Formation Energy (eV/atom)"], cmap="Greens_r" ), use_container_width=True, ) st.info( "**Interpretation:** More negative Eform = thermodynamically more stable. " "NaFePOโ‚„ (โˆ’2.38 eV/atom) is significantly more stable than Naโ‚‚MnNiOโ‚„ (โˆ’1.542 eV/atom). " "The AI formation energy predictor learns from these two ground-truth points to " "extrapolate across the composition space." ) # โ”€โ”€ SIB Sub-tab 3: Bader Charge Analysis โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ with sib_tabs[2]: st.markdown("### Bader Charge Analysis โ€” Stage 4: Charge Distribution Model") st.markdown( "Bader charges computed from DFT calculations are targets for the AI charge " "distribution model. These predict **oxidation state, charge transfer, and redox activity** " "โ€” critical inputs to the voltage predictor." ) bader_df = build_bader_df() st.markdown("#### Average Charges Heatmap (all 4 structures)") st.plotly_chart(sib_bader_heatmap(bader_df), use_container_width=True, key="sib_bader_heatmap") st.markdown("#### Average Cation Charges Comparison") st.plotly_chart(sib_charge_transfer_bar(bader_df), use_container_width=True, key="sib_charge_transfer") st.markdown("#### Per-atom Bader Charge Distribution") sib_mat_sel = st.selectbox( "Select material", ["NaFePOโ‚„", "Naโ‚‚MnNiOโ‚„"], key="sib_bader_mat_sel" ) sib_struct_sel = st.radio( "Select structure", ["Unit Cell", "Supercell 2ร—2ร—1"], horizontal=True, key="sib_bader_struct_sel" ) struct_label = ( f"Unit Cell ({28 if sib_mat_sel == 'NaFePOโ‚„' else 24} atoms)" if sib_struct_sel == "Unit Cell" else f"Supercell 2ร—2ร—1 ({128 if sib_mat_sel == 'NaFePOโ‚„' else 96} atoms)" ) sub_bader = bader_df[ (bader_df["Material"] == sib_mat_sel) & (bader_df["Structure"] == struct_label) ] if not sub_bader.empty: st.plotly_chart(sib_bader_box(sub_bader.assign(Material=sib_mat_sel), sib_mat_sel), use_container_width=True, key="sib_bader_box") st.markdown("#### Summary Table โ€” Average Charges") st.dataframe(SIB_AVG_CHARGES, use_container_width=True) st.info(""" **Key charge insights:** - **Naโบ in NaFePOโ‚„:** +0.890 e โ€” consistent with Naโบ ionic character - **Fe in NaFePOโ‚„:** +1.486 e โ€” confirms Feยฒโบ oxidation state (partially covalent Feโˆ’O bonds) - **P in NaFePOโ‚„:** +5.0 e โ€” fully ionic Pโตโบ (phosphate POโ‚„ยณโป group) - **Mn in Naโ‚‚MnNiOโ‚„:** +1.729 e โ€” Mnยณโบ state; active redox centre - **Ni in Naโ‚‚MnNiOโ‚„:** +1.283 e โ€” Niยฒโบ state; will oxidize to Niยณโบ on desodiation - **O charge range:** โˆ’1.13 to โˆ’1.87 e โ€” wider range in NaFePOโ‚„ (multiple O environments) """) # โ”€โ”€ SIB Sub-tab 4: Na Diffusion โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ with sib_tabs[3]: st.markdown("### Naโบ Diffusion Prediction โ€” Stage 5: Sodium Diffusion Prediction") st.markdown( "Using the 128-atom NaFePOโ‚„ and 96-atom Naโ‚‚MnNiOโ‚„ supercells, Na vacancy and " "interstitial migration pathways are generated. ML-NEB predicts migration barriers " "and diffusion coefficients." ) c1, c2, c3, c4 = st.columns(4) with c1: st.metric("Best D (NaFePOโ‚„)", "8.5ร—10โปยนโฐ cmยฒ/s", "b-axis vacancy hop") with c2: st.metric("Min Barrier (NaFePOโ‚„)", "0.18 eV", "b-axis olivine tunnel") with c3: st.metric("Best D (Naโ‚‚MnNiOโ‚„)", "6.8ร—10โปยนยน cmยฒ/s", "ab-plane vacancy") with c4: st.metric("Min Barrier (Naโ‚‚MnNiOโ‚„)", "0.25 eV", "2D ab-plane hop") st.plotly_chart(sib_diffusion_bar(SIB_DIFFUSION), use_container_width=True, key="sib_diffusion_bar") st.markdown("#### Diffusion Mechanism Details") st.dataframe( SIB_DIFFUSION.style.background_gradient( subset=["Migration Barrier Ea (eV)"], cmap="Reds" ), use_container_width=True, ) st.info(""" **Diffusion insights:** - **NaFePOโ‚„ (olivine):** Strongly anisotropic โ€” b-axis is the primary Naโบ channel (Eโ‚=0.18 eV) while c-axis is nearly blocked (Eโ‚=0.55 eV) - **Naโ‚‚MnNiOโ‚„ (layered):** 2D diffusion in ab-plane (Eโ‚=0.25 eV); large interlayer spacing (32 ร…) severely limits c-direction hopping (Eโ‚=0.68 eV) - Both materials show **higher barriers than Li in LiF** (~64 kJ/mol โ‰ˆ 0.66 eV), but Na diffusion benefits from a larger ionic radius increasing tunnel size """) # โ”€โ”€ SIB Sub-tab 5: Cathode Ranking โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ with sib_tabs[4]: st.markdown("### AI Cathode Ranking โ€” Stage 8: Intelligent Cathode Ranking") st.markdown( "The AI ranks cathode candidates using a weighted 5-property score. " "DFT-computed data (NaFePOโ‚„: **89/100**, Naโ‚‚MnNiOโ‚„: **82/100**) anchors the ranking." ) r1, r2, r3 = st.columns(3) with r1: st.metric("๐Ÿฅ‡ NaFePOโ‚„ AI Score", "89.0 / 100", "DFT-validated") with r2: st.metric("๐Ÿฅˆ Naโ‚‚MnNiOโ‚„ AI Score", "82.0 / 100", "DFT-validated") with r3: st.metric("Screening pool", "8 materials", "2 DFT + 3 AI + 3 literature") st.plotly_chart(sib_cathode_ranking_chart(SIB_CATHODE_RANKING), use_container_width=True, key="sib_cathode_ranking") st.markdown("#### Cathode Property Radar") avail_mats = SIB_CATHODE_RANKING["Material"].tolist() sel_radar_mats = st.multiselect( "Select cathodes to compare", avail_mats, default=avail_mats[:3], key="sib_radar_mats", ) if sel_radar_mats: st.plotly_chart(sib_cathode_radar(SIB_CATHODE_RANKING, sel_radar_mats), use_container_width=True, key="sib_cathode_radar") st.markdown("#### Full Ranking Table") st.dataframe( SIB_CATHODE_RANKING.style.background_gradient( subset=["AI Score (0โ€“100)"], cmap="YlGn" ).format({"AI Score (0โ€“100)": "{:.1f}", "AI Score": "{:.2f}"}), use_container_width=True, ) st.markdown("#### Ranking Weights") wt_cols = st.columns(5) for col, (prop, wt) in zip(wt_cols, [ ("Stability", "25%"), ("Voltage", "25%"), ("Diffusion", "20%"), ("Capacity", "20%"), ("Safety", "10%"), ]): col.metric(prop, wt) # โ”€โ”€ SIB Sub-tab 6: AI Pipeline โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ with sib_tabs[5]: st.markdown("### 8-Stage AI Pipeline") st.markdown( "Each piece of DFT data maps to a specific AI pipeline stage. " "This view shows which stages are complete, ready, or in progress." ) st.plotly_chart(sib_pipeline_status(SIB_PIPELINE_STAGES), use_container_width=True, key="sib_pipeline_status") st.markdown("#### Detailed Pipeline Mapping") for _, row in SIB_PIPELINE_STAGES.iterrows(): status_emoji = { "Done": "โœ…", "Ready": "๐Ÿ”ต", "Trained": "๐ŸŸก", "Predicted": "๐ŸŸฃ", "Training": "๐Ÿ”ด", }.get(row["Status"], "โšช") with st.expander(f"{status_emoji} Stage {row['Stage']}: {row['Name']} โ€” {row['Status']}"): cols = st.columns(2) with cols[0]: st.markdown("**DFT Input:**") st.info(row["DFT Input"]) with cols[1]: st.markdown("**AI Output:**") st.success(row["AI Output"]) st.markdown("#### Legend") leg_cols = st.columns(5) for col, (color, label) in zip(leg_cols, [ ("๐ŸŸข", "Done โ€” data already computed"), ("๐Ÿ”ต", "Ready โ€” can run immediately"), ("๐ŸŸก", "Trained โ€” model ready"), ("๐ŸŸฃ", "Predicted โ€” AI output available"), ("๐Ÿ”ด", "Training โ€” in progress"), ]): col.markdown(f"{color} {label}") # โ”€โ”€ SIB Sub-tab 7: AI Screening โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ with sib_tabs[6]: st.markdown("### AI-Screened Hypothetical Cathodes โ€” Stage 3 Output") st.markdown( "Once trained on the DFT-validated entries, the formation energy predictor " "screens hypothetical compositions. Below are the first 10 candidates including " "the two DFT-validated anchor points." ) st.plotly_chart(sib_screened_bubble(SIB_SCREENED), use_container_width=True, key="sib_screened_bubble") st.markdown("#### Screened Cathode Table") st.dataframe( SIB_SCREENED.style.background_gradient( subset=["Predicted Voltage (V)", "Predicted Capacity (mAh/g)"], cmap="Blues" ).background_gradient( subset=["Predicted Eform (eV/atom)"], cmap="Greens_r" ), use_container_width=True, ) st.info(""" **Reading the bubble chart:** - **X-axis:** Predicted voltage vs Na/Naโบ (higher โ†’ more energy dense) - **Y-axis:** Predicted capacity in mAh/g (higher โ†’ more charge storage) - **Bubble size:** Absolute value of formation energy (larger โ†’ more stable) - **Colour:** Red = DFT-verified, Green = AI-predicted **Top AI candidate:** Naโ‚‚Mn0.5Co0.5Oโ‚„ โ€” highest capacity (200 mAh/g) and voltage (3.55 V) but lower stability (Eform = โˆ’1.72 eV/atom). Needs DFT validation. """) st.markdown("#### Next DFT Calculations Recommended") next_dft = pd.DataFrame({ "Structure": [ "Naโ‚€.โ‚ˆโ‚‡โ‚…FePOโ‚„ (vacancy)", "Naโ‚€.โ‚‡โ‚…FePOโ‚„ (vacancy)", "FePOโ‚„ (fully desodiated)", "NaFePOโ‚„ + NEB path", "Naโ‚‚MnNiOโ‚„ + NEB path", "NaFePOโ‚„ elastic tensor", "NaFePOโ‚„ PDOS/bandgap", ], "Purpose": [ "Partial desodiation state", "Half desodiation state", "Fully charged state", "Na migration barrier (DFT NEB)", "Na migration barrier (DFT NEB)", "Mechanical stability", "Electronic properties โ†’ conductivity", ], "AI Stage": [ "Stage 2 (Dataset)", "Stage 2 (Dataset)", "Stage 3 (Eform)", "Stage 5 (Diffusion)", "Stage 5 (Diffusion)", "Stage 7 (Performance)", "Stage 7 (Performance)", ], "Priority": ["High", "High", "High", "Critical", "Critical", "Medium", "Medium"], }) st.dataframe( next_dft.style.applymap( lambda v: "color: #f87171" if v == "Critical" else "color: #F59E0B" if v == "High" else "color: #4ade80", subset=["Priority"], ), use_container_width=True, ) # โ”€โ”€ SIB Sub-tab 8: Voltage & Capacity โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ with sib_tabs[7]: st.markdown("### Voltage & Capacity Prediction โ€” Stage 7: Battery Performance") st.markdown( "Predicted from charge distribution (Stage 4) combined with formation energy (Stage 3). " "The Feยฒโบโ†’Feยณโบ and Mnยณโบโ†’Mnโดโบ redox couples determine operating voltage." ) v1, v2, v3, v4 = st.columns(4) with v1: st.metric("NaFePOโ‚„ Voltage", "2.87 V vs Na/Naโบ", "Feยฒโบ/Feยณโบ couple") with v2: st.metric("Naโ‚‚MnNiOโ‚„ Voltage", "3.45 V vs Na/Naโบ", "Mnยณโบ/Niยฒโบ couple") with v3: st.metric("NaFePOโ‚„ Capacity", "154 mAh/g", "1 Na per formula unit") with v4: st.metric("Naโ‚‚MnNiOโ‚„ Capacity", "195 mAh/g", "2 Na per formula unit") st.markdown("#### Voltage State Table (DFT computed)") st.dataframe(SIB_VOLTAGE, use_container_width=True) # Simple voltage vs capacity scatter fig_vc = px.scatter( SIB_SCREENED, x="Predicted Voltage (V)", y="Predicted Capacity (mAh/g)", color="Source", symbol="Stability", size=[20] * len(SIB_SCREENED), text="Material", title="Voltage vs Capacity โ€” All Cathode Candidates", color_discrete_map={"DFT": "#FF4757", "AI": "#4ade80"}, labels={"Predicted Voltage (V)": "Voltage (V vs Na/Naโบ)"}, ) fig_vc.update_traces(textposition="top center", textfont_size=8) fig_vc.add_hline(y=150, line_dash="dot", line_color="#aaa", annotation_text="Min target: 150 mAh/g") fig_vc.add_vline(x=2.5, line_dash="dot", line_color="#aaa", annotation_text="Min target: 2.5 V") fig_vc.update_layout( plot_bgcolor="#0E1117", paper_bgcolor="#0E1117", font_color="#e5e7eb", height=450, ) st.plotly_chart(fig_vc, use_container_width=True, key="sib_vc_scatter") st.info(""" **Energy density comparison:** - **NaFePOโ‚„:** 2.87 V ร— 154 mAh/g โ‰ˆ **442 Wh/kg** (theoretical) - **Naโ‚‚MnNiOโ‚„:** 3.45 V ร— 195 mAh/g โ‰ˆ **674 Wh/kg** (theoretical) - **LiB LiFePOโ‚„ (reference):** 3.45 V ร— 170 mAh/g โ‰ˆ 586 Wh/kg Naโ‚‚MnNiOโ‚„ shows competitive energy density with LiFePOโ‚„ while using earth-abundant Mn/Ni instead of scarce Li. """) st.markdown("#### Industrial Vision โ€” Battery Foundation Model") st.markdown(""" The DFT-computed dataset is the **seed** for the Battery Foundation Model: | Input | AI Engine Module | Output | |-------|-----------------|--------| | DFT structures | Structure Encoder (GNN) | Latent material representation | | Formation energies | Formation Energy Predictor | Screen 10โถ candidates | | Bader charges | Charge Distribution Model | Voltage prediction | | Supercell structures | Diffusion Predictor | Na-ion conductivity | | MD trajectories | Cycle-Life Predictor | Degradation forecast | | Experimental data | Calibration layer | Validated recommendations | **Recommended next steps:** 1. Add vacancy structures (Naโ‚€.โ‚ˆโ‚‡โ‚…FePOโ‚„, Naโ‚€.โ‚‡โ‚…FePOโ‚„) 2. Run NEB calculations for both materials 3. Compute elastic tensors and electronic bandgaps 4. Integrate finite-temperature (300/500/700 K) MD trajectories 5. Expand to full cathode library (10+ materials) for the production platform """)