Spaces:
Running
Running
| 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(""" | |
| <style> | |
| .main { background-color: #0E1117; } | |
| .block-container { padding-top: 1.2rem; } | |
| .metric-card { | |
| background: linear-gradient(135deg,#1a1d27,#252836); | |
| border:1px solid #2d3048; border-radius:12px; | |
| padding:0.9rem 1rem; text-align:center; | |
| } | |
| .metric-card .label { font-size:0.7rem; color:#8891a4; text-transform:uppercase; letter-spacing:.08em; } | |
| .metric-card .value { font-size:1.5rem; font-weight:700; color:#fff; margin:3px 0; } | |
| .metric-card .delta { font-size:0.72rem; color:#4ade80; } | |
| .section-hdr { | |
| font-size:0.95rem; font-weight:600; color:#94a3b8; | |
| text-transform:uppercase; letter-spacing:.06em; | |
| border-bottom:1px solid #1e2433; padding-bottom:5px; margin-bottom:10px; | |
| } | |
| div[data-testid="stTabs"] button { font-size:0.85rem; } | |
| </style> | |
| """, unsafe_allow_html=True) | |
| # ── Cache ────────────────────────────────────────────────────────────────────── | |
| 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""" | |
| <div class="metric-card"> | |
| <div class="label">{label}</div> | |
| <div class="value">{val}</div> | |
| <div class="delta">{sub}</div> | |
| </div>""", unsafe_allow_html=True) | |
| st.markdown("<br>", 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('<div class="section-hdr">Core Workflow Pipeline</div>', 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"<b>{lbl}</b>", | |
| 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('<div class="section-hdr">Module 1: DFT Data Upload</div>', 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('<div class="section-hdr">Module 2: AI Dataset Builder — 9 Configuration Types</div>', | |
| 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('<div class="section-hdr">Module 3: ML Force Field Trainer</div>', | |
| 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('<div class="section-hdr">CMA-ES Optimisation Convergence (1.3 × 10⁴ iterations)</div>', | |
| 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('<div class="section-hdr">ML Model Benchmark — Energy MAE, Force MAE, Speed</div>', | |
| 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('<div class="section-hdr">Module 4: AI Simulation Manager</div>', | |
| 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('<div class="section-hdr">Module 5: AI Property Predictor — 8 Battery Properties</div>', | |
| 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('<div class="section-hdr">SEI Component Analysis & LiF Formation</div>', | |
| 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('<div class="section-hdr">Module 6: AI Ranking Engine — Multi-Objective Material Scoring</div>', | |
| 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('<div class="section-hdr">Final Tool Output — 8 Deliverables</div>', | |
| 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('<div class="section-hdr">Experimental Validation Roadmap</div>', | |
| unsafe_allow_html=True) | |
| st.dataframe(VALIDATION_RECS, use_container_width=True, hide_index=True) | |
| st.divider() | |
| st.markdown('<div class="section-hdr">MVP → Full Production Roadmap</div>', | |
| 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('<div class="section-hdr">ReaxFF Parameter Summary</div>', 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('<div class="section-hdr">Na-Ion Battery (SIB) — DFT Cathode Data</div>', | |
| 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""" | |
| <div class="metric-card"> | |
| <div class="label">{lbl}</div> | |
| <div class="value">{val}</div> | |
| <div class="delta">{sub}</div> | |
| </div>""", unsafe_allow_html=True) | |
| st.markdown("<br>", 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 | |
| """) | |